|
1 // Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // Implements CSmsReassemblyStore and CSmsSegmentationStore. |
|
15 // |
|
16 // |
|
17 |
|
18 /** |
|
19 @file |
|
20 */ |
|
21 |
|
22 #include <e32svr.h> |
|
23 #include <es_ini.h> |
|
24 #include "smspstor.h" |
|
25 #include "smspmain.h" |
|
26 #include "smsuaddr.H" |
|
27 #include "Gsmumsg.h" |
|
28 #include "gsmubuf.h" |
|
29 #include <logwrap.h> |
|
30 #include <logwraplimits.h> |
|
31 #include "Gsmuelem.h" |
|
32 #include "gsmuieoperations.h" |
|
33 #include "gsmunonieoperations.h" |
|
34 |
|
35 LOCAL_C TPtrC TrimLeadingZeros(const TDesC& aString) |
|
36 { |
|
37 LOGSMSPROT1("CSARStore::ExternalizeEntryArrayL()"); |
|
38 |
|
39 const TInt len = aString.Length(); |
|
40 |
|
41 if (len == 0) |
|
42 return aString; |
|
43 |
|
44 const TUint16* startChar = &aString[0]; |
|
45 const TUint16* endChar = &aString[len-1]; |
|
46 |
|
47 while (startChar <= endChar && *startChar == '0') |
|
48 { |
|
49 ++startChar; |
|
50 } |
|
51 return TPtrC(startChar, endChar - startChar + 1); |
|
52 } // TrimLeadingZeros |
|
53 |
|
54 |
|
55 /** |
|
56 * Creates new CSmsReassemblyStore instance |
|
57 * |
|
58 * @param aFs File Server handle. |
|
59 */ |
|
60 CSmsReassemblyStore* CSmsReassemblyStore::NewL(RFs& aFs) |
|
61 { |
|
62 LOGSMSPROT1("CSmsReassemblyStore::NewL()"); |
|
63 |
|
64 CSmsReassemblyStore* self = new (ELeave) CSmsReassemblyStore(aFs); |
|
65 CleanupStack::PushL(self); |
|
66 self->ConstructL(); |
|
67 CleanupStack::Pop(self); |
|
68 |
|
69 return self; |
|
70 } // CSmsReassemblyStore::NewL |
|
71 |
|
72 |
|
73 /** |
|
74 * Creates and starts timer |
|
75 */ |
|
76 void CSmsReassemblyStore::ConstructL() |
|
77 { |
|
78 LOGSMSPROT1("CSmsReassemblyStore::ConstructL()"); |
|
79 |
|
80 // |
|
81 // Generate the full path to the reassembly store. |
|
82 // |
|
83 PrivatePath(iFullPathBuf); |
|
84 iFullPathBuf.Append(KReassemblyStoreName); |
|
85 |
|
86 iLastReceivedTime.UniversalTime(); |
|
87 iLastRealTime = iLastReceivedTime; |
|
88 } // CSmsReassemblyStore::ConstructL |
|
89 |
|
90 |
|
91 /** |
|
92 * Destructor |
|
93 */ |
|
94 CSmsReassemblyStore::~CSmsReassemblyStore() |
|
95 { |
|
96 // NOP |
|
97 } // CSmsReassemblyStore::~CSmsReassemblyStore |
|
98 |
|
99 |
|
100 void CSmsReassemblyStore::UpdateLogServerIdL(TInt aIndex, TLogId aLogServerId) |
|
101 { |
|
102 LOGSMSPROT1("CSmsReassemblyStore::UpdateLogServerIdL()"); |
|
103 |
|
104 TSmsReassemblyEntry entry(reinterpret_cast<const TSmsReassemblyEntry&>(Entries()[aIndex])); |
|
105 |
|
106 if (entry.LogServerId() != aLogServerId) |
|
107 { |
|
108 entry.SetLogServerId(aLogServerId); |
|
109 BeginTransactionLC(); |
|
110 ChangeEntryL(aIndex, entry); |
|
111 CommitTransactionL(); |
|
112 } |
|
113 } // CSmsReassemblyStore::UpdateLogServerIdL |
|
114 |
|
115 |
|
116 /** |
|
117 * Searches the reassembly store for a CSmsMessage and returns its index. |
|
118 * |
|
119 * @param aSmsMessage Message to search for. |
|
120 * @param aPassed Determines if we are searching for a message already |
|
121 * passed to the client. |
|
122 * @param aIndex Return index value. |
|
123 * |
|
124 * @return True and an index if aSmsMessage is found in this reassembly store |
|
125 */ |
|
126 TBool CSmsReassemblyStore::FindMessageL(const CSmsMessage& aSmsMessage, |
|
127 TBool aPassed, |
|
128 TInt& aIndex) |
|
129 { |
|
130 LOGSMSPROT1("CSmsReassemblyStore::FindMessageL()"); |
|
131 |
|
132 // |
|
133 // Parse the GSM data from the SMS message... |
|
134 // |
|
135 TGsmSmsTelNumber parsedAddress; |
|
136 |
|
137 aSmsMessage.ParsedToFromAddress(parsedAddress); |
|
138 |
|
139 // |
|
140 // Search the store for a matching message... |
|
141 // |
|
142 for (TInt index = Entries().Count() - 1; index >= 0; index--) |
|
143 { |
|
144 const TSmsReassemblyEntry& entry = reinterpret_cast<const TSmsReassemblyEntry&>(Entries()[index]); |
|
145 |
|
146 // Always search the basic types first and strings last! |
|
147 if (entry.PduType() == aSmsMessage.Type() && |
|
148 entry.PassedToClient() == aPassed && |
|
149 entry.Storage() == aSmsMessage.Storage() && |
|
150 entry.Time() == aSmsMessage.Time() && |
|
151 entry.Description2().Right(8) == parsedAddress.iTelNumber.Right(8)) |
|
152 { |
|
153 // |
|
154 // Found! |
|
155 // |
|
156 LOGSMSPROT2("CSmsReassemblyStore::FindMessage(): Found! index=%d", index); |
|
157 |
|
158 aIndex = index; |
|
159 |
|
160 return ETrue; |
|
161 } |
|
162 } |
|
163 |
|
164 // |
|
165 // Not found... |
|
166 // |
|
167 LOGSMSPROT1("CSmsReassemblyStore::FindMessage(): Not found!"); |
|
168 |
|
169 return EFalse; |
|
170 } // CSmsReassemblyStore::FindMessageL |
|
171 |
|
172 |
|
173 /** |
|
174 * Adds Pdu to reassembly store |
|
175 * |
|
176 * @param aSmsMessage PDU to |
|
177 * @param aGsmSms Used to |
|
178 * @param aIndex Used to |
|
179 * @param aComplete Used to |
|
180 * @param aServiceCenterAddressPresent Used to |
|
181 */ |
|
182 void CSmsReassemblyStore::MatchPDUToExistingMessage(const CSmsMessage& aSmsMessage, |
|
183 TInt& aIndex) |
|
184 { |
|
185 LOGSMSPROT1("CSmsReassemblyStore::MatchPDUToExistingMessage()"); |
|
186 |
|
187 __ASSERT_ALWAYS(!aSmsMessage.IsDecoded(), SmspPanic(KSmspPanicMessageConcatenated)); |
|
188 |
|
189 aIndex = KErrNotFound; |
|
190 |
|
191 TGsmSmsTelNumber parsedAddress; |
|
192 aSmsMessage.ParsedToFromAddress(parsedAddress); |
|
193 |
|
194 // |
|
195 // Search the reassembly store for a matching entry (start from the |
|
196 // end as the most recent PDUs appear at the end)... |
|
197 // |
|
198 TInt reassemblyCount = Entries().Count(); |
|
199 |
|
200 for (TInt index = reassemblyCount - 1; index >= 0; index--) |
|
201 { |
|
202 TSmsReassemblyEntry& entry = (TSmsReassemblyEntry&) Entries()[index]; |
|
203 |
|
204 // Always check the fields in order of the quickest to check... |
|
205 if (entry.IsComplete() == EFalse && |
|
206 entry.PduType() == aSmsMessage.Type() && |
|
207 entry.Storage() == aSmsMessage.Storage()) |
|
208 { |
|
209 TInt telLen = Min(entry.Description2().Length(), |
|
210 parsedAddress.iTelNumber.Length()); |
|
211 |
|
212 if (entry.Description2().Right(telLen) == parsedAddress.iTelNumber.Right(telLen) && |
|
213 entry.Total() == aSmsMessage.SmsPDU().NumConcatenatedMessagePDUs() && |
|
214 entry.Reference() == aSmsMessage.SmsPDU().ConcatenatedMessageReference()) |
|
215 { |
|
216 // |
|
217 // Found it! |
|
218 // |
|
219 aIndex = index; |
|
220 break; |
|
221 } |
|
222 } |
|
223 } |
|
224 |
|
225 LOGSMSPROT3("CSmsReassemblyStore::MatchPDUToExistingMessage(): reassemblyCount=%d, aIndex=%d", reassemblyCount, aIndex); |
|
226 } // CSmsReassemblyStore::MatchPDUToExistingMessage |
|
227 |
|
228 |
|
229 void CSmsReassemblyStore::UpdateExistingMessageL(const CSmsMessage& aSmsMessage, |
|
230 const TGsmSms& aGsmSms, TInt aIndex, |
|
231 TBool& aComplete, |
|
232 TBool& aDuplicateMsgRef, |
|
233 TBool& aDuplicateSlot) |
|
234 { |
|
235 LOGSMSPROT1("CSmsReassemblyStore::UpdateExistingMessageL()"); |
|
236 |
|
237 aComplete = EFalse; |
|
238 aDuplicateMsgRef = EFalse; |
|
239 aDuplicateSlot = EFalse; |
|
240 |
|
241 // |
|
242 // Read the segment from the store into a CSmsMessage buffer... |
|
243 // |
|
244 TSmsReassemblyEntry entry = (TSmsReassemblyEntry&) Entries()[aIndex]; |
|
245 |
|
246 CArrayFix<TInt>* indexArray = new(ELeave) CArrayFixFlat<TInt>(8); |
|
247 CleanupStack::PushL(indexArray); |
|
248 CArrayFixFlat<TGsmSms>* smsArray = new(ELeave) CArrayFixFlat<TGsmSms>(8); |
|
249 CleanupStack::PushL(smsArray); |
|
250 CSmsBuffer* buffer = CSmsBuffer::NewL(); |
|
251 CSmsMessage* smsMessage = CSmsMessage::NewL(iFs, CSmsPDU::ESmsDeliver, buffer); |
|
252 CleanupStack::PushL(smsMessage); |
|
253 |
|
254 InternalizeEntryL(entry.DataStreamId(), *smsMessage, *indexArray, *smsArray); |
|
255 |
|
256 // |
|
257 // Check if this is a duplicated enumerated PDU (e.g. on the SIM or phone memory) |
|
258 // or a duplicated PDU (e.g. in the Reassembly Store)... |
|
259 // |
|
260 TInt concatPDUIndex = aSmsMessage.SmsPDU().ConcatenatedMessagePDUIndex(); |
|
261 |
|
262 if (smsMessage->Storage() == CSmsMessage::ESmsSIMStorage || |
|
263 smsMessage->Storage() == CSmsMessage::ESmsCombinedStorage) |
|
264 { |
|
265 // |
|
266 // In most cases this PDU is being enumerated, but not always. It is |
|
267 // possible for the PDU to be stored on the SIM first before it is |
|
268 // received. |
|
269 // |
|
270 const TGsmSmsSlotEntry& newSlot = aSmsMessage.iSlotArray[0]; |
|
271 TInt slotArrayCount = smsMessage->iSlotArray.Count(); |
|
272 |
|
273 for (TInt slotNum = 0; slotNum < slotArrayCount; slotNum++ ) |
|
274 { |
|
275 const TGsmSmsSlotEntry& slot = smsMessage->iSlotArray[slotNum]; |
|
276 |
|
277 if (slot.iIndex == newSlot.iIndex && slot.iStore == newSlot.iStore) |
|
278 { |
|
279 LOGSMSPROT1("CSmsReassemblyStore::UpdateExistingMessageL(): Duplicate enumerated PDU."); |
|
280 |
|
281 // It is a duplicate that was already stored on the SIM... |
|
282 aDuplicateSlot = ETrue; |
|
283 break; |
|
284 } |
|
285 } |
|
286 } |
|
287 |
|
288 TInt indexArrayCount = indexArray->Count(); |
|
289 |
|
290 for (TInt index = 0; index < indexArrayCount; index++ ) |
|
291 { |
|
292 if (indexArray->At(index) == concatPDUIndex) |
|
293 { |
|
294 LOGSMSPROT1("CSmsReassemblyStore::UpdateExistingMessageL(): Duplicate concatenated PDU."); |
|
295 |
|
296 // The PDU is already stored in the reassembly store. |
|
297 aDuplicateMsgRef = ETrue; |
|
298 break; |
|
299 } |
|
300 } |
|
301 |
|
302 if (aDuplicateMsgRef || aDuplicateSlot) |
|
303 { |
|
304 CleanupStack::PopAndDestroy(3, indexArray); // smsMessage, smsArray, indexArray |
|
305 return; |
|
306 } |
|
307 |
|
308 // |
|
309 // If the PDU is stored then add the slot information... |
|
310 // |
|
311 if (smsMessage->Storage() == CSmsMessage::ESmsSIMStorage || |
|
312 smsMessage->Storage() == CSmsMessage::ESmsCombinedStorage) |
|
313 { |
|
314 smsMessage->AddSlotL(aSmsMessage.iSlotArray[0]); |
|
315 } |
|
316 |
|
317 // |
|
318 // If the PDU is Unsent or Unread, then store that information... |
|
319 // |
|
320 NMobileSmsStore::TMobileSmsStoreStatus status = aSmsMessage.Status(); |
|
321 |
|
322 if (status == NMobileSmsStore::EStoredMessageUnsent || |
|
323 status == NMobileSmsStore::EStoredMessageUnread) |
|
324 { |
|
325 smsMessage->SetStatus(status); |
|
326 } |
|
327 |
|
328 // |
|
329 // Does this PDU mean the message is complete? If so then decode the message, |
|
330 // reset the index and sms arrays (to save space for completed SMSs). |
|
331 // |
|
332 indexArray->AppendL(concatPDUIndex); |
|
333 smsArray->AppendL(aGsmSms); |
|
334 |
|
335 if (smsArray->Count() == smsMessage->SmsPDU().NumConcatenatedMessagePDUs()) |
|
336 { |
|
337 smsMessage->DecodeMessagePDUsL(*smsArray); |
|
338 |
|
339 indexArray->Reset(); |
|
340 smsArray->Reset(); |
|
341 |
|
342 aComplete = ETrue; |
|
343 } |
|
344 |
|
345 // |
|
346 // Write the entry back into the store... |
|
347 // |
|
348 TStreamId streamid = entry.DataStreamId(); |
|
349 smsMessage->SetLogServerId(entry.LogServerId()); |
|
350 |
|
351 BeginTransactionLC(); |
|
352 ExternalizeEntryL(streamid, *smsMessage, *indexArray, *smsArray); |
|
353 PopulateEntry(entry, *smsMessage, smsArray->Count()); |
|
354 ChangeEntryL(aIndex, entry); |
|
355 CommitTransactionL(); |
|
356 |
|
357 CleanupStack::PopAndDestroy(3, indexArray); // smsMessage, smsArray, indexArray |
|
358 } // CSmsReassemblyStore::UpdateExistingMessageL |
|
359 |
|
360 |
|
361 void CSmsReassemblyStore::NewMessagePDUL(TInt& aIndex,CSmsMessage& aSmsMessage,const TGsmSms& aGsmSms) |
|
362 { |
|
363 LOGSMSPROT1("CSmsReassemblyStore::NewMessagePDUL"); |
|
364 |
|
365 CArrayFix<TInt>* indexarray=new(ELeave) CArrayFixFlat<TInt>(8); |
|
366 CleanupStack::PushL(indexarray); |
|
367 CArrayFixFlat<TGsmSms>* smsarray=new(ELeave) CArrayFixFlat<TGsmSms>(8); |
|
368 CleanupStack::PushL(smsarray); |
|
369 TInt index=aSmsMessage.IsDecoded()? 0: aSmsMessage.SmsPDU().ConcatenatedMessagePDUIndex(); |
|
370 indexarray->AppendL(index); |
|
371 smsarray->AppendL(aGsmSms); |
|
372 aIndex=Entries().Count(); |
|
373 CreateEntryL(aSmsMessage,*indexarray,*smsarray); |
|
374 CleanupStack::PopAndDestroy(2); |
|
375 } // CSmsReassemblyStore::NewMessagePDUL |
|
376 |
|
377 |
|
378 void CSmsReassemblyStore::GetMessageL(TInt aIndex,CSmsMessage& aSmsMessage) |
|
379 { |
|
380 LOGSMSPROT2("CSmsReassemblyStore::GetMessageL [aIndex=%d]", aIndex); |
|
381 |
|
382 CArrayFix<TInt>* indexarray=new(ELeave) CArrayFixFlat<TInt>(8); |
|
383 CleanupStack::PushL(indexarray); |
|
384 CArrayFixFlat<TGsmSms>* smsarray=new(ELeave) CArrayFixFlat<TGsmSms>(8); |
|
385 CleanupStack::PushL(smsarray); |
|
386 InternalizeEntryL(Entries()[aIndex].DataStreamId(),aSmsMessage,*indexarray,*smsarray); |
|
387 TInt logid=Entries()[aIndex].LogServerId(); |
|
388 if(aSmsMessage.LogServerId() == KLogNullId && logid != KLogNullId) |
|
389 aSmsMessage.SetLogServerId(logid); |
|
390 CleanupStack::PopAndDestroy(2); // smsarray, indexarray |
|
391 } // CSmsReassemblyStore::GetMessageL |
|
392 |
|
393 |
|
394 /** |
|
395 * internalize all the entries from the permanent file store to internal memory |
|
396 * |
|
397 * NOTE! You have to call CSARStore::OpenFileLC() before calling this function |
|
398 */ |
|
399 void CSmsReassemblyStore::InternalizeEntryL(const TStreamId& aStreamId,CSmsMessage& aSmsMessage,CArrayFix<TInt>& aIndexArray,CArrayFix<TGsmSms>& aSmsArray) |
|
400 { |
|
401 LOGSMSPROT2("CSmsReassemblyStore::InternalizeEntryL Start [sid=%d]", aStreamId.Value()); |
|
402 RStoreReadStream readstream; |
|
403 readstream.OpenLC(FileStore(),aStreamId); |
|
404 readstream >> aSmsMessage; |
|
405 TInt count=readstream.ReadInt32L(); |
|
406 aIndexArray.Reset(); |
|
407 TInt i; |
|
408 for (i=0; i<count; i++) |
|
409 { |
|
410 TInt index=readstream.ReadInt32L(); |
|
411 aIndexArray.AppendL(index); |
|
412 } |
|
413 count=readstream.ReadInt32L(); |
|
414 if(count!=aIndexArray.Count()) |
|
415 User::Leave(KErrCorrupt); |
|
416 aSmsArray.Reset(); |
|
417 for (i=0; i<count; i++) |
|
418 { |
|
419 RMobileSmsMessaging::TMobileSmsGsmTpdu pdu; |
|
420 readstream >> pdu; |
|
421 TGsmSms sms; |
|
422 sms.SetPdu(pdu); |
|
423 aSmsArray.AppendL(sms); |
|
424 } |
|
425 CleanupStack::PopAndDestroy(); |
|
426 LOGSMSPROT2("CSmsReassemblyStore::InternalizeEntryL End [count=%d]", count); |
|
427 } // CSARStore::OpenFileLC |
|
428 |
|
429 |
|
430 /** |
|
431 * externalizes all the entries from the internal memory to the permanent file store |
|
432 * |
|
433 * NOTE! You have to call CSARStore::OpenFileLC() before calling this function |
|
434 */ |
|
435 void CSmsReassemblyStore::ExternalizeEntryL(TStreamId& aStreamId,const CSmsMessage& aSmsMessage,const CArrayFix<TInt>& aIndexArray,const CArrayFix<TGsmSms>& aSmsArray) |
|
436 { |
|
437 LOGSMSPROT2("CSmsReassemblyStore::ExternalizeEntryL Start [sid=%d]", aStreamId.Value()); |
|
438 |
|
439 RStoreWriteStream writestream; |
|
440 if (aStreamId==KNullStreamId) |
|
441 aStreamId=writestream.CreateLC(FileStore()); |
|
442 else |
|
443 writestream.ReplaceLC(FileStore(),aStreamId); |
|
444 writestream << aSmsMessage; |
|
445 TInt count=aIndexArray.Count(); |
|
446 __ASSERT_ALWAYS(count==aIndexArray.Count(),SmspPanic(KSmspPanicBadIndexArray)); |
|
447 writestream.WriteInt32L(count); |
|
448 TInt i=0; |
|
449 for (; i<count; i++) |
|
450 writestream.WriteInt32L(aIndexArray[i]); |
|
451 count=aSmsArray.Count(); |
|
452 writestream.WriteInt32L(count); |
|
453 for (i=0; i<count; i++) |
|
454 { |
|
455 RMobileSmsMessaging::TMobileSmsGsmTpdu pdu; |
|
456 pdu=aSmsArray[i].Pdu(); |
|
457 writestream << pdu; |
|
458 } |
|
459 writestream.CommitL(); |
|
460 CleanupStack::PopAndDestroy(); |
|
461 |
|
462 LOGSMSPROT2("CSmsReassemblyStore::ExternalizeEntryL End [count=%d]", count); |
|
463 } // CSARStore::OpenFileLC |
|
464 |
|
465 |
|
466 void CSmsReassemblyStore::PopulateEntry(TSmsReassemblyEntry& aEntry,const CSmsMessage& aSmsMessage,TInt aNumSmss) |
|
467 { |
|
468 LOGSMSPROT1("CSmsReassemblyStore::PopulateEntry"); |
|
469 aEntry.SetReference(0); |
|
470 aEntry.SetTotal(1); |
|
471 aEntry.SetCount(1); |
|
472 |
|
473 if (aSmsMessage.TextPresent()) |
|
474 { |
|
475 if (aSmsMessage.SmsPDU().TextConcatenated()) |
|
476 { |
|
477 aEntry.SetReference(aSmsMessage.SmsPDU().ConcatenatedMessageReference()); |
|
478 aEntry.SetTotal(aSmsMessage.SmsPDU().NumConcatenatedMessagePDUs()); |
|
479 aEntry.SetCount(aSmsMessage.IsComplete()? aEntry.Total(): aNumSmss); |
|
480 } |
|
481 TInt bits7to4=aSmsMessage.SmsPDU().Bits7To4(); |
|
482 TInt count=aSmsMessage.SmsPDU().UserData().NumInformationElements(); |
|
483 TInt identifier1=0xFF; |
|
484 TInt identifier2=0x00; |
|
485 for (TInt i=0; i<count; i++) |
|
486 { |
|
487 TInt identifier=aSmsMessage.SmsPDU().UserData().InformationElement(i).Identifier(); |
|
488 if ((identifier!=CSmsInformationElement::ESmsIEIConcatenatedShortMessages8BitReference) && (identifier!=CSmsInformationElement::ESmsIEIConcatenatedShortMessages16BitReference)) |
|
489 { |
|
490 if (identifier<identifier1) |
|
491 identifier1=identifier; |
|
492 if (identifier>identifier2) |
|
493 identifier2=identifier; |
|
494 } |
|
495 } |
|
496 |
|
497 if ((bits7to4>=TSmsDataCodingScheme::ESmsDCSMessageWaitingIndicationDiscardMessage) && (bits7to4<=TSmsDataCodingScheme::ESmsDCSMessageWaitingIndicationUCS2)) |
|
498 aEntry.SetBits7to4andIdentifiers(bits7to4, identifier1, identifier2); |
|
499 else |
|
500 aEntry.SetBits7to4andIdentifiers(0, identifier1, identifier2); |
|
501 } |
|
502 |
|
503 //Set the logServerId to aSmsMessage.LogServerId() |
|
504 |
|
505 aEntry.SetLogServerId(aSmsMessage.LogServerId()); |
|
506 |
|
507 const CSmsPDU::TSmsPDUType type(aSmsMessage.Type()); |
|
508 aEntry.SetPduType(type); |
|
509 aEntry.SetPassedToClient(EFalse); |
|
510 |
|
511 aEntry.SetStorage(aSmsMessage.Storage()); |
|
512 if ((type!=CSmsPDU::ESmsSubmitReport) && (type!=CSmsPDU::ESmsDeliverReport)) |
|
513 { |
|
514 // Strip out spaces etc from address |
|
515 TGsmSmsTelNumber parsedaddress; |
|
516 aSmsMessage.ParsedToFromAddress(parsedaddress); |
|
517 aEntry.SetDescription2(parsedaddress.iTelNumber); |
|
518 } |
|
519 |
|
520 aEntry.SetTime(aSmsMessage.Time()); |
|
521 } // CSmsReassemblyStore::PopulateEntry |
|
522 |
|
523 |
|
524 void CSmsReassemblyStore::CreateEntryL(CSmsMessage& aSmsMessage,const CArrayFix<TInt>& aIndexArray,const CArrayFix<TGsmSms>& aSmsArray) |
|
525 { |
|
526 LOGSMSPROT1("CSmsReassemblyStore::CreateEntryL"); |
|
527 TStreamId streamid=KNullStreamId; |
|
528 if (aSmsMessage.Time() >= iLastRealTime) |
|
529 { |
|
530 iLastRealTime=aSmsMessage.Time(); |
|
531 if(iLastReceivedTime >= aSmsMessage.Time()) |
|
532 { |
|
533 aSmsMessage.SetTime(iLastReceivedTime+(TTimeIntervalMicroSeconds32)1); |
|
534 } |
|
535 iLastReceivedTime=aSmsMessage.Time(); //provide uniqueness of time |
|
536 } |
|
537 else // clock turned back |
|
538 { |
|
539 iLastReceivedTime=aSmsMessage.Time(); |
|
540 } |
|
541 BeginTransactionLC(); |
|
542 ExternalizeEntryL(streamid,aSmsMessage,aIndexArray,aSmsArray); |
|
543 TSmsReassemblyEntry entry; |
|
544 entry.SetDataStreamId(streamid); |
|
545 |
|
546 PopulateEntry(entry,aSmsMessage,aSmsArray.Count()); |
|
547 AddEntryL(entry); |
|
548 CommitTransactionL(); |
|
549 } // CSmsReassemblyStore::CreateEntryL |
|
550 |
|
551 |
|
552 TBool CSmsReassemblyStore::PassedToClient( TInt aIndex ) const |
|
553 { |
|
554 LOGSMSPROT1("CSmsReassemblyStore::PassedToClient()"); |
|
555 |
|
556 const TSmsReassemblyEntry& entry = reinterpret_cast<const TSmsReassemblyEntry&>(Entries()[ aIndex ]); |
|
557 return entry.PassedToClient(); |
|
558 } // CSmsReassemblyStore::PassedToClient |
|
559 |
|
560 |
|
561 void CSmsReassemblyStore::SetPassedToClientL(TInt aIndex, TBool aPassed) |
|
562 //TODO CommentThisFunction |
|
563 { |
|
564 LOGSMSPROT1("CSmsReassemblyStore::SetPassedToClientL()"); |
|
565 |
|
566 TSmsReassemblyEntry entry(reinterpret_cast<const TSmsReassemblyEntry&>(Entries()[aIndex])); |
|
567 |
|
568 const TBool alreadyPassed = entry.PassedToClient(); |
|
569 |
|
570 if ((!aPassed && alreadyPassed) || (aPassed && !alreadyPassed)) |
|
571 { |
|
572 entry.SetPassedToClient(aPassed); |
|
573 ChangeEntryL(aIndex, entry); |
|
574 } |
|
575 } // CSmsReassemblyStore::SetPassedToClientL |
|
576 |
|
577 |
|
578 /** |
|
579 * Open the sms reassembly store. |
|
580 */ |
|
581 void CSmsReassemblyStore::OpenStoreL() |
|
582 { |
|
583 LOGSMSPROT1("CSmsReassemblyStore::OpenStoreL()"); |
|
584 |
|
585 this->OpenL(iFullPathBuf,KReassemblyStoreUid); |
|
586 } // CSmsReassemblyStore::OpenStoreL |
|
587 |
|
588 |
|
589 /** |
|
590 * Constructor |
|
591 * |
|
592 * @param aFs Used to set CSARStore object |
|
593 */ |
|
594 CSmsReassemblyStore::CSmsReassemblyStore(RFs& aFs) |
|
595 :CSARStore(aFs) |
|
596 { |
|
597 // NOP |
|
598 } // CSmsReassemblyStore::CSmsReassemblyStore |
|
599 |
|
600 |
|
601 CSmsSegmentationStore* CSmsSegmentationStore::NewL(RFs& aFs) |
|
602 { |
|
603 LOGSMSPROT1("CSmsSegmentationStore::NewL()"); |
|
604 |
|
605 CSmsSegmentationStore* segmentationStore = new(ELeave) CSmsSegmentationStore(aFs); |
|
606 CleanupStack::PushL( segmentationStore ); |
|
607 segmentationStore->ConstructL(); |
|
608 CleanupStack::Pop( segmentationStore ); |
|
609 return segmentationStore; |
|
610 } // CSmsSegmentationStore::NewL |
|
611 |
|
612 |
|
613 void CSmsSegmentationStore::ConstructL() |
|
614 { |
|
615 LOGSMSPROT1("CSmsSegmentationStore::ConstructL()"); |
|
616 |
|
617 //generate fullpath of segmentation store. |
|
618 PrivatePath(iFullPathBuf); |
|
619 //append store name |
|
620 iFullPathBuf.Append(KSegmentationStoreName); |
|
621 |
|
622 // Set the default value for the maxmum number messages in the segmentation store. |
|
623 iMaxmumNumberOfMessagesInSegmentationStore = KDefaultMaxmumNumberOfMessagesInSegmentationStore; |
|
624 |
|
625 CESockIniData* ini = NULL; |
|
626 _LIT(KSmseskfile, "smswap.sms.esk"); |
|
627 TRAPD(ret, ini=CESockIniData::NewL(KSmseskfile)); |
|
628 if(ret == KErrNone) |
|
629 { |
|
630 // Get the maximum number of messages allowed in the segmentation store from .ESK file |
|
631 CleanupStack::PushL(ini); |
|
632 |
|
633 TPtrC value; |
|
634 if((ini->FindVar(_L("SegmentationStoreOptions"),_L("MaxNumOfMessInSegStore"),value))) |
|
635 { |
|
636 TLex16 valueconv(value); |
|
637 valueconv.Val(iMaxmumNumberOfMessagesInSegmentationStore); |
|
638 } |
|
639 CleanupStack::PopAndDestroy(ini); |
|
640 } |
|
641 else if (ret != KErrNotFound && ret != KErrPathNotFound) |
|
642 { |
|
643 User::Leave(ret); |
|
644 } |
|
645 } // CSmsSegmentationStore::ConstructL |
|
646 |
|
647 |
|
648 CSmsSegmentationStore::~CSmsSegmentationStore() |
|
649 { |
|
650 // NOP |
|
651 } // CSmsSegmentationStore::~CSmsSegmentationStore |
|
652 |
|
653 |
|
654 TInt CSmsSegmentationStore::Next8BitReferenceL() |
|
655 { |
|
656 LOGSMSPROT1("CSmsSegmentationStore::Next8BitReferenceL"); |
|
657 |
|
658 TInt reference8bit=0; |
|
659 TInt reference16bit=0; |
|
660 TStreamId streamid=ExtraStreamId(); |
|
661 |
|
662 // |
|
663 // access file store |
|
664 // |
|
665 BeginTransactionLC(); |
|
666 if (streamid!=KNullStreamId) |
|
667 { |
|
668 TRAPD(ret,InternalizeConcatenationReferencesL(streamid,reference8bit,reference16bit)); |
|
669 if(ret != KErrNone) |
|
670 { |
|
671 // We have to leave on any error; otherwise a duplicate reference number will be generated |
|
672 // The transaction will revert |
|
673 LOGSMSPROT2("WARNING! CSmsSegmentationStore::InternalizeConcatenationReferencesL left with %d", ret); |
|
674 User::Leave(ret); // stream not corrupted |
|
675 } |
|
676 reference8bit=(reference8bit+1)%0x100; |
|
677 } |
|
678 TRAPD(ret, ExternalizeConcatenationReferencesL(streamid,reference8bit,reference16bit)); |
|
679 if(ret != KErrNone) |
|
680 { |
|
681 // We have to leave on any error; otherwise a duplicate reference number will be generated |
|
682 // The transaction will revert |
|
683 LOGSMSPROT2("WARNING! CSmsSegmentationStore::ExternalizeConcatenationReferencesL left with %d", ret); |
|
684 User::Leave(ret); // stream not corrupted |
|
685 } |
|
686 SetExtraStreamIdL(streamid); |
|
687 CommitTransactionL(); |
|
688 return reference8bit; |
|
689 } // CSmsSegmentationStore::Next8BitReferenceL |
|
690 |
|
691 |
|
692 TInt CSmsSegmentationStore::Next16BitReferenceL() |
|
693 { |
|
694 LOGSMSPROT1("CSmsSegmentationStore::Next16BitReferenceL"); |
|
695 TInt reference8bit=0; |
|
696 TInt reference16bit=0x100; |
|
697 TStreamId streamid=ExtraStreamId(); |
|
698 // |
|
699 // access file store |
|
700 // |
|
701 BeginTransactionLC(); |
|
702 if (streamid!=KNullStreamId) |
|
703 { |
|
704 TRAPD(ret,InternalizeConcatenationReferencesL(streamid,reference8bit,reference16bit)); |
|
705 if(ret != KErrNone) |
|
706 { |
|
707 // We have to leave on any error; otherwise a duplicate reference number will be generated |
|
708 // The transaction will revert |
|
709 LOGSMSPROT2("WARNING! CSmsSegmentationStore::InternalizeConcatenationReferencesL left with %d", ret); |
|
710 User::Leave(ret); // stream not corrupted |
|
711 } |
|
712 reference16bit=((reference16bit+1)%0xFF00)+0x100; |
|
713 } |
|
714 TRAPD(ret, ExternalizeConcatenationReferencesL(streamid,reference8bit,reference16bit)); |
|
715 if(ret != KErrNone) |
|
716 { |
|
717 // We have to leave on any error; otherwise a duplicate reference number will be generated |
|
718 // The transaction will revert |
|
719 LOGSMSPROT2("WARNING! CSmsSegmentationStore::ExternalizeConcatenationReferencesL left with %d", ret); |
|
720 User::Leave(ret); // stream not corrupted |
|
721 } |
|
722 SetExtraStreamIdL(streamid); |
|
723 CommitTransactionL(); |
|
724 return reference16bit; |
|
725 } // CSmsSegmentationStore::Next16BitReferenceL |
|
726 |
|
727 |
|
728 /** |
|
729 * Adds a CSmsMessage to the segmentation store |
|
730 * |
|
731 * @note aSumbit.Buffer() may be shortened to TSAREntry::ESmsSAREntryDescriptionLength |
|
732 * |
|
733 * @param aSubmit Message to add to the segmentation store |
|
734 * @pre aSubmit.Type() is ESmsSubmit |
|
735 * @pre aSubmit.EncodeMessagePdusL() has been called. This is so PopulateEntry sets the correct total on the TSAREntry |
|
736 */ |
|
737 void CSmsSegmentationStore::AddSubmitL(const TSmsAddr& aSmsAddr,CSmsMessage& aSubmit) |
|
738 { |
|
739 LOGSMSPROT1("CSmsSegmentationStore::AddSubmitL"); |
|
740 |
|
741 __ASSERT_ALWAYS(aSubmit.Type()==CSmsPDU::ESmsSubmit,SmspPanic(KSmspPanicNotSubmit)); |
|
742 |
|
743 BeginTransactionLC(); |
|
744 |
|
745 |
|
746 RSmsSegmentationStoreRefStatusArray refStatus; |
|
747 CleanupClosePushL(refStatus); |
|
748 |
|
749 TStreamId streamid=KNullStreamId; |
|
750 CSmsBufferBase& buffer=aSubmit.Buffer(); |
|
751 TInt length=buffer.Length(); |
|
752 if (length>TSAREntry::ESmsSAREntryDescriptionLength) |
|
753 buffer.DeleteL(TSAREntry::ESmsSAREntryDescriptionLength,length-TSAREntry::ESmsSAREntryDescriptionLength); |
|
754 |
|
755 ExternalizeEntryL(streamid,aSmsAddr,aSubmit, refStatus); |
|
756 |
|
757 TSmsSegmentationEntry entry; |
|
758 entry.SetDataStreamId(streamid); |
|
759 PopulateEntry(entry, aSubmit, refStatus); |
|
760 |
|
761 CleanupStack::PopAndDestroy(&refStatus); |
|
762 |
|
763 AddEntryL(entry); |
|
764 CommitTransactionL(); |
|
765 } // CSmsSegmentationStore::AddSubmitL |
|
766 |
|
767 |
|
768 TBool CSmsSegmentationStore::AddCommandL(const TSmsAddr& aSmsAddr,const CSmsMessage& aCommand, CSmsSegmentationStore::RSmsSegmentationStoreRefStatusArray& aRefStatus) |
|
769 { |
|
770 LOGSMSPROT1("CSmsSegmentationStore::AddCommandL"); |
|
771 __ASSERT_ALWAYS(aCommand.Type()==CSmsPDU::ESmsCommand,SmspPanic(KSmspPanicNotCommand)); |
|
772 const TInt count=Entries().Count(); |
|
773 const TLogId logid=(TLogId) aCommand.LogServerId(); |
|
774 |
|
775 BeginTransactionLC(); |
|
776 |
|
777 //TODO AA: What is it doing here? Please comment |
|
778 for (TInt i=count-1; i>=0; --i) |
|
779 { |
|
780 if ((logid!=KLogNullId) && (logid==Entries()[i].LogServerId())) |
|
781 { |
|
782 DeleteEntryL(i); |
|
783 break; |
|
784 } |
|
785 } |
|
786 TBool found=EFalse; |
|
787 |
|
788 CSmsBuffer* buffer=CSmsBuffer::NewL(); |
|
789 CSmsMessage* smsmessage=CSmsMessage::NewL(iFs, CSmsPDU::ESmsSubmit,buffer); |
|
790 CleanupStack::PushL(smsmessage); |
|
791 TGsmSmsTelNumber parsedaddress; |
|
792 aCommand.ParsedToFromAddress(parsedaddress); |
|
793 TInt telLen; |
|
794 |
|
795 for (TInt j=0; j<count; j++) |
|
796 { |
|
797 TSmsSegmentationEntry entry = (TSmsSegmentationEntry&)Entries()[j]; |
|
798 const CSmsPDU::TSmsPDUType type = entry.PduType(); |
|
799 telLen=Min(entry.Description2().Length(),parsedaddress.iTelNumber.Length()); |
|
800 if ((type==CSmsPDU::ESmsSubmit) && |
|
801 entry.IsComplete() && |
|
802 (entry.Description2().Right(telLen)==parsedaddress.iTelNumber.Right(telLen)) && |
|
803 (entry.Time()==aCommand.Time())) |
|
804 { |
|
805 found=ETrue; |
|
806 TSmsAddr smsaddr; |
|
807 |
|
808 InternalizeEntryL(entry.DataStreamId(),smsaddr,*smsmessage, aRefStatus); |
|
809 TStreamId streamid; |
|
810 CSmsSubmit& submit=(CSmsSubmit&) smsmessage->SmsPDU(); |
|
811 if ((((CSmsCommand&) aCommand.SmsPDU()).CommandType()==TSmsCommandType::ESmsCommandTypeEnableStatusReportRequest) && |
|
812 (!submit.StatusReportRequest())) |
|
813 { |
|
814 submit.SetStatusReportRequest(ETrue); |
|
815 streamid=entry.DataStreamId(); |
|
816 ExternalizeEntryL(streamid,smsaddr,*smsmessage, aRefStatus); |
|
817 PopulateEntry(entry,*smsmessage, aRefStatus); |
|
818 ChangeEntryL(j,entry); |
|
819 } |
|
820 |
|
821 //TODO What is happening here? Seems strange |
|
822 RSmsSegmentationStoreRefStatusArray refStatusTemp; |
|
823 CleanupClosePushL(refStatusTemp); |
|
824 |
|
825 streamid=KNullStreamId; |
|
826 |
|
827 ExternalizeEntryL(streamid,aSmsAddr,aCommand, refStatusTemp); |
|
828 entry.SetDataStreamId(streamid); |
|
829 PopulateEntry(entry,aCommand, refStatusTemp); |
|
830 |
|
831 CleanupStack::PopAndDestroy(&refStatusTemp); |
|
832 |
|
833 AddEntryL(entry); |
|
834 |
|
835 break; |
|
836 } |
|
837 } |
|
838 CleanupStack::PopAndDestroy(smsmessage); // smsmessage |
|
839 CommitTransactionL(); |
|
840 |
|
841 return found; |
|
842 } // CSmsSegmentationStore::AddCommandL |
|
843 |
|
844 |
|
845 TBool CSmsSegmentationStore::AddReferenceL(const CSmsMessage& aSmsMessage,TInt aReference) |
|
846 { |
|
847 TSmsSegmentationEntry entry; // TODO const and inside loop |
|
848 const TInt count=Entries().Count(); |
|
849 LOGSMSPROT3("CSmsSegmentationStore::AddReferenceL [count=%d, ref=%d]", count, aReference); |
|
850 TInt i=0; |
|
851 TInt logserverid=aSmsMessage.LogServerId(); |
|
852 if (logserverid!=KLogNullId) |
|
853 { |
|
854 for (i=0; i<count; i++) |
|
855 { |
|
856 entry = (TSmsSegmentationEntry&)Entries()[i]; |
|
857 if (logserverid==entry.LogServerId()) |
|
858 break; |
|
859 } |
|
860 } |
|
861 else |
|
862 { |
|
863 TGsmSmsTelNumber parsedaddress; |
|
864 aSmsMessage.ParsedToFromAddress(parsedaddress); |
|
865 TInt telLen; |
|
866 for (i=0; i<count; i++) |
|
867 { |
|
868 entry = (TSmsSegmentationEntry&)Entries()[i]; |
|
869 telLen=Min(entry.Description2().Length(),parsedaddress.iTelNumber.Length()); |
|
870 const CSmsPDU::TSmsPDUType type=entry.PduType(); |
|
871 if ((type==aSmsMessage.Type()) && (!entry.IsComplete()) && (aSmsMessage.Time()==entry.Time()) && (entry.Description2().Right(telLen)==parsedaddress.iTelNumber.Right(telLen))) |
|
872 break; |
|
873 } |
|
874 } |
|
875 // __ASSERT_DEBUG(i<count,SmspPanic(KSmspPanicEntryWithLogServerIdNotFound)); TODO |
|
876 if(i>=count) |
|
877 { |
|
878 LOGSMSPROT3("WARNING! KSmspPanicEntryWithLogServerIdNotFound [i=%d, count=%d]", i, count); |
|
879 } |
|
880 |
|
881 RSmsSegmentationStoreRefStatusArray refStatusArray; |
|
882 CleanupClosePushL(refStatusArray); |
|
883 |
|
884 TStreamId streamid=entry.DataStreamId(); |
|
885 TSmsAddr smsaddr; |
|
886 CSmsBuffer* buffer=CSmsBuffer::NewL(); |
|
887 CSmsMessage* smsmessage=CSmsMessage::NewL(iFs, CSmsPDU::ESmsDeliver,buffer); |
|
888 CleanupStack::PushL(smsmessage); |
|
889 |
|
890 // |
|
891 // access the file store |
|
892 // |
|
893 InternalizeEntryL(streamid,smsaddr,*smsmessage, refStatusArray); |
|
894 refStatusArray.InsertL(aReference); |
|
895 |
|
896 BeginTransactionLC(); |
|
897 ExternalizeEntryL(streamid,smsaddr,*smsmessage, refStatusArray); |
|
898 |
|
899 PopulateEntry(entry,/*smsaddr,*/*smsmessage, refStatusArray); |
|
900 ChangeEntryL(i,entry); |
|
901 CommitTransactionL(); |
|
902 |
|
903 // |
|
904 // AEH: moved here because if is done before calling ChangeEntryL |
|
905 // it will pop and destroy the filestore which is also on |
|
906 // the cleanup stack |
|
907 // |
|
908 CleanupStack::PopAndDestroy(2); // smsmessage, refStatus |
|
909 |
|
910 return entry.Total()==entry.Count(); |
|
911 } |
|
912 |
|
913 |
|
914 /** |
|
915 * Does exactly the same thing as AddReferenceL() i.e. adds the the segment refernce to a list. But |
|
916 * to support the new status report schemes a slight change has been made. Instead of inserting |
|
917 * just a reference now its status is inserted as well. This is provided one of the two new schemes |
|
918 * is being used. If the status is required then we do exactly the same as AddReferenceL(), but if |
|
919 * it's not then we just call the InsertL() method with an extra parameter: EStatusComplete. |
|
920 * |
|
921 * @param aSmsMessage Reference to CSmsMessage. |
|
922 * @param aReference The PDU reference. |
|
923 */ |
|
924 TBool CSmsSegmentationStore::AddReferenceStatusPairL(const CSmsMessage& aSmsMessage,TInt aReference, TUint aSegmentSequenceNumber) |
|
925 { |
|
926 TSmsSegmentationEntry entry; // TODO const and inside loop |
|
927 const TInt count=Entries().Count(); |
|
928 LOGSMSPROT3("CSmsSegmentationStore::AddReferenceStatusPairL [count=%d, ref=%d]", count, aReference); |
|
929 TInt i=0; |
|
930 TInt logserverid=aSmsMessage.LogServerId(); |
|
931 if (logserverid!=KLogNullId) |
|
932 { |
|
933 for (i=0; i<count; i++) |
|
934 { |
|
935 entry = (TSmsSegmentationEntry&)Entries()[i]; |
|
936 if (logserverid==entry.LogServerId()) |
|
937 break; |
|
938 } |
|
939 } |
|
940 else |
|
941 { |
|
942 TGsmSmsTelNumber parsedaddress; |
|
943 aSmsMessage.ParsedToFromAddress(parsedaddress); |
|
944 TInt telLen; |
|
945 for (i=0; i<count; i++) |
|
946 { |
|
947 entry = (TSmsSegmentationEntry&)Entries()[i]; |
|
948 telLen=Min(entry.Description2().Length(),parsedaddress.iTelNumber.Length()); |
|
949 const CSmsPDU::TSmsPDUType type=entry.PduType(); |
|
950 if ((type==aSmsMessage.Type()) && (!entry.IsComplete()) && (aSmsMessage.Time()==entry.Time()) && (entry.Description2().Right(telLen)==parsedaddress.iTelNumber.Right(telLen))) |
|
951 break; |
|
952 } |
|
953 } |
|
954 // __ASSERT_DEBUG(i<count,SmspPanic(KSmspPanicEntryWithLogServerIdNotFound)); TODO |
|
955 if(i>=count) |
|
956 { |
|
957 LOGSMSPROT3("WARNING! KSmspPanicEntryWithLogServerIdNotFound [i=%d, count=%d]", i, count); |
|
958 } |
|
959 |
|
960 RSmsSegmentationStoreRefStatusArray refStatusArray; |
|
961 CleanupClosePushL(refStatusArray); |
|
962 |
|
963 TStreamId streamid=entry.DataStreamId(); |
|
964 TSmsAddr smsaddr; |
|
965 CSmsBuffer* buffer=CSmsBuffer::NewL(); |
|
966 CSmsMessage* smsmessage=CSmsMessage::NewL(iFs, CSmsPDU::ESmsDeliver,buffer); |
|
967 CleanupStack::PushL(smsmessage); |
|
968 |
|
969 // |
|
970 // access the file store |
|
971 // |
|
972 InternalizeEntryL(streamid,smsaddr,*smsmessage, refStatusArray); |
|
973 |
|
974 if (aSmsMessage.Scheme() == EControlParametersScheme) |
|
975 { |
|
976 TUint8 octet(0); |
|
977 TInt ret; |
|
978 |
|
979 ret = ((CSmsSMSCCtrlParameterOperations&)aSmsMessage.GetOperationsForIEL(CSmsInformationElement::ESmsIEISMSCControlParameters)).GetStatusReport(aSegmentSequenceNumber, octet); |
|
980 if (ret == KErrNone) |
|
981 { |
|
982 if (octet & ESmsSMSCControlParametersMask) |
|
983 { |
|
984 refStatusArray.InsertL(aReference); |
|
985 } |
|
986 else |
|
987 { |
|
988 refStatusArray.InsertL(TSmsSegmentationStoreRefStatus(aReference, EStatusComplete)); |
|
989 } |
|
990 } |
|
991 } |
|
992 else if(aSmsMessage.Scheme() == ETPSRRScheme) |
|
993 { |
|
994 TInt tpsrr; |
|
995 tpsrr = ((CSmsTPSRROperations&)aSmsMessage.GetOperationsForNonIEL(ESmsTPSRRParameter)).GetStatusReport(aSegmentSequenceNumber); |
|
996 |
|
997 if(tpsrr == TSmsFirstOctet::ESmsStatusReportNotRequested) |
|
998 { |
|
999 refStatusArray.InsertL(TSmsSegmentationStoreRefStatus(aReference, EStatusComplete)); |
|
1000 } |
|
1001 else if(tpsrr == TSmsFirstOctet::ESmsStatusReportRequested) |
|
1002 { |
|
1003 refStatusArray.InsertL(aReference); |
|
1004 } |
|
1005 } |
|
1006 else |
|
1007 { |
|
1008 User::Leave(KErrArgument); |
|
1009 } |
|
1010 |
|
1011 |
|
1012 BeginTransactionLC(); |
|
1013 ExternalizeEntryL(streamid,smsaddr,*smsmessage, refStatusArray); |
|
1014 |
|
1015 PopulateEntry(entry,/*smsaddr,*/*smsmessage, refStatusArray); |
|
1016 ChangeEntryL(i,entry); |
|
1017 CommitTransactionL(); |
|
1018 |
|
1019 // |
|
1020 // AEH: moved here because if is done before calling ChangeEntryL |
|
1021 // it will pop and destroy the filestore which is also on |
|
1022 // the cleanup stack |
|
1023 // |
|
1024 CleanupStack::PopAndDestroy(2); // smsmessage, refStatus |
|
1025 |
|
1026 return entry.Total()==entry.Count(); |
|
1027 } // CSmsSegmentationStore::AddReferenceStatusPairL |
|
1028 |
|
1029 |
|
1030 TBool CSmsSegmentationStore::AddStatusReportL(TInt& aIndex,TBool& aComplete,const CSmsMessage& aStatusReport) |
|
1031 { |
|
1032 LOGSMSPROT1("CSmsSegmentationStore::AddStatusReportL"); |
|
1033 |
|
1034 __ASSERT_DEBUG(aStatusReport.Type()==CSmsPDU::ESmsStatusReport,SmspPanic(KSmspPanicNotStatusReport)); |
|
1035 |
|
1036 const CSmsStatusReport& statusreport=(CSmsStatusReport&) aStatusReport.SmsPDU(); |
|
1037 const TInt reference=statusreport.MessageReference(); |
|
1038 const TInt status=statusreport.Status(); |
|
1039 const TInt isPerm = IsPermanentStatus(status); |
|
1040 const TSmsFirstOctet::TSmsStatusReportQualifier qualifier=statusreport.StatusReportQualifier(); |
|
1041 TBool found=EFalse; |
|
1042 aComplete=EFalse; |
|
1043 |
|
1044 LOGSMSPROT4("CSmsSegmentationStore::AddStatusReportL [ref=%d status=%d IsPerm=%d]", reference, status, isPerm); |
|
1045 |
|
1046 if(!isPerm) |
|
1047 { |
|
1048 return EFalse; |
|
1049 } |
|
1050 |
|
1051 RSmsSegmentationStoreRefStatusArray refStatusArray; |
|
1052 CleanupClosePushL(refStatusArray); |
|
1053 |
|
1054 const TInt count1=Entries().Count(); |
|
1055 |
|
1056 TSmsAddr smsaddr; |
|
1057 CSmsBuffer* buffer=CSmsBuffer::NewL(); |
|
1058 CSmsMessage* smsmessage=CSmsMessage::NewL(iFs, CSmsPDU::ESmsDeliver,buffer); |
|
1059 CleanupStack::PushL(smsmessage); |
|
1060 TGsmSmsTelNumber parsedaddress; |
|
1061 aStatusReport.ParsedToFromAddress(parsedaddress); |
|
1062 TSmsSegmentationEntry entry; // TODO const ref and inside loop |
|
1063 |
|
1064 BeginTransactionLC(); |
|
1065 |
|
1066 aIndex = count1; |
|
1067 |
|
1068 TInt telLen; |
|
1069 while (!found && aIndex--) |
|
1070 { |
|
1071 entry = (TSmsSegmentationEntry&)Entries()[aIndex]; |
|
1072 |
|
1073 // Remove leading zeros of national numbers |
|
1074 TPtrC trimmedTelNumber(TrimLeadingZeros(entry.Description2())); |
|
1075 TPtrC trimmedParsedTelNumber(TrimLeadingZeros(parsedaddress.iTelNumber)); |
|
1076 |
|
1077 telLen=Min(trimmedTelNumber.Length(),trimmedParsedTelNumber.Length()); |
|
1078 |
|
1079 const CSmsPDU::TSmsPDUType type = entry.PduType(); |
|
1080 const TInt startref = entry.Reference1(); |
|
1081 const TInt stopref = entry.Reference2(); |
|
1082 |
|
1083 TBool sameTelNumbers = entry.Description2().Right(telLen) == parsedaddress.iTelNumber.Right(telLen); |
|
1084 |
|
1085 if (sameTelNumbers) |
|
1086 { |
|
1087 LOGSMSPROT1("CSmsSegmentationStore::AddStatusReportL telNumber from submit report matches that from SMS message"); |
|
1088 } |
|
1089 else |
|
1090 { |
|
1091 LOGSMSPROT1("CSmsSegmentationStore::AddStatusReportL telNumber from submit report does NOT match that from SMS message"); |
|
1092 } |
|
1093 |
|
1094 if (sameTelNumbers && |
|
1095 (((qualifier==TSmsFirstOctet::ESmsStatusReportResultOfCommand) && (type==CSmsPDU::ESmsCommand)) || |
|
1096 ((qualifier==TSmsFirstOctet::ESmsStatusReportResultOfSubmit) && (type==CSmsPDU::ESmsSubmit))) && |
|
1097 (((stopref>=startref) &&(reference>=startref) && (reference<=stopref))||((stopref<startref) &&((reference>=startref) || (reference<=stopref)))) |
|
1098 ) |
|
1099 { |
|
1100 InternalizeEntryL(entry.DataStreamId(),smsaddr,*smsmessage, refStatusArray); |
|
1101 TInt refStatusPos = refStatusArray.Find(reference); //assumes Find returns the first matching reference in the array |
|
1102 TInt numMessagePDUs=entry.Total(); |
|
1103 |
|
1104 if (refStatusPos != KErrNotFound) |
|
1105 { |
|
1106 const TInt refStatusArrayCount = refStatusArray.Count(); |
|
1107 |
|
1108 //Find an element in refStatusArray where Reference() == reference and Status() is not permanent |
|
1109 while (!found && refStatusPos < refStatusArrayCount && refStatusArray[refStatusPos].Reference() == reference) |
|
1110 { |
|
1111 //@note This loop assumes refStatusArray is sorted iReference |
|
1112 if (!IsPermanentStatus(refStatusArray[refStatusPos].Status())&&(refStatusArrayCount <= numMessagePDUs)) |
|
1113 { |
|
1114 found = ETrue; |
|
1115 } |
|
1116 else |
|
1117 { |
|
1118 LOGSMSPROT4("CSmsSegmentationStore::AddStatusReportL WARNING: Status already perm [status=%d refStatusPos=%d count=%d]", refStatusArray[refStatusPos].Status(), refStatusPos, refStatusArrayCount); |
|
1119 refStatusPos++; |
|
1120 } |
|
1121 } |
|
1122 |
|
1123 if (found) |
|
1124 { |
|
1125 LOGSMSPROT2("CSmsSegmentationStore::AddStatusReportL Found [refStatusPos=%d]", refStatusPos); |
|
1126 refStatusArray[refStatusPos].SetStatus(status); |
|
1127 TStreamId streamid=entry.DataStreamId(); |
|
1128 ExternalizeEntryL(streamid,smsaddr,*smsmessage, refStatusArray); |
|
1129 PopulateEntry(entry,*smsmessage, refStatusArray); |
|
1130 ChangeEntryL(aIndex,entry); |
|
1131 aComplete=StatusArrayComplete(refStatusArray, entry); |
|
1132 LOGSMSPROT2("CSmsSegmentationStore::AddStatusReportL StatusArrayComplete %d", aComplete); |
|
1133 } |
|
1134 } |
|
1135 } |
|
1136 } |
|
1137 |
|
1138 if (found && (smsmessage->Type()==CSmsPDU::ESmsCommand)) // look for original submit |
|
1139 { |
|
1140 TTime time=smsmessage->Time(); |
|
1141 found=EFalse; |
|
1142 |
|
1143 RSmsSegmentationStoreRefStatusArray refStatusArray2; |
|
1144 CleanupClosePushL(refStatusArray2); |
|
1145 refStatusArray2.CopyL(refStatusArray); |
|
1146 refStatusArray2.ResetAllStatus(); |
|
1147 |
|
1148 aComplete=EFalse; |
|
1149 TInt telLen; |
|
1150 for (aIndex=0; aIndex<count1; aIndex++) |
|
1151 { |
|
1152 entry = (TSmsSegmentationEntry&)Entries()[aIndex]; |
|
1153 telLen=Min(entry.Description2().Length(),parsedaddress.iTelNumber.Length()); |
|
1154 const CSmsPDU::TSmsPDUType type = entry.PduType(); |
|
1155 if ((type==CSmsPDU::ESmsSubmit) && |
|
1156 entry.IsComplete() && |
|
1157 (entry.Time()==time) && |
|
1158 (entry.Description2().Right(telLen)==parsedaddress.iTelNumber.Right(telLen))) |
|
1159 { |
|
1160 |
|
1161 /* |
|
1162 TODO ahe - this should take out of the for loop |
|
1163 only set/delete flags in the for loop and let the methods: |
|
1164 InternalizeXXX |
|
1165 ExternalizeXXX |
|
1166 PopulateEntry |
|
1167 ChangeEntry |
|
1168 ... all ... other big CSarStore methods |
|
1169 have only to run once -> internal loop in this function through |
|
1170 the array of flags |
|
1171 */ |
|
1172 |
|
1173 found=ETrue; |
|
1174 InternalizeEntryL(entry.DataStreamId(),smsaddr,*smsmessage, refStatusArray2); |
|
1175 const TInt count2 = refStatusArray.Count(); |
|
1176 __ASSERT_DEBUG(count2 == refStatusArray2.Count(),SmspPanic(KSmspPanicBadReferenceArray)); |
|
1177 for (TInt i=0; i<count2; i++) |
|
1178 { |
|
1179 //TODO What is this doing? |
|
1180 TSmsSegmentationStoreRefStatus& refStatus2 = refStatusArray2[i]; |
|
1181 if (!IsPermanentStatus(refStatus2.Status())) |
|
1182 { |
|
1183 refStatus2.SetStatus(refStatusArray[i].Status()); |
|
1184 } |
|
1185 } |
|
1186 |
|
1187 TStreamId streamid=entry.DataStreamId(); |
|
1188 ExternalizeEntryL(streamid,smsaddr,*smsmessage, refStatusArray2); |
|
1189 PopulateEntry(entry,/*smsaddr,*/*smsmessage, refStatusArray2); |
|
1190 ChangeEntryL(aIndex,entry); |
|
1191 aComplete=StatusArrayComplete(refStatusArray2, entry); |
|
1192 LOGSMSPROT3("CSmsSegmentationStore::StatusArrayComplete [aStatus=%d, ret=%d]", status, aComplete); |
|
1193 break; |
|
1194 } |
|
1195 } |
|
1196 |
|
1197 CleanupStack::PopAndDestroy(&refStatusArray2); |
|
1198 } |
|
1199 |
|
1200 CommitTransactionL(); |
|
1201 CleanupStack::PopAndDestroy(2); // smsmessage, refStatusArray |
|
1202 |
|
1203 LOGSMSPROT2("CSmsSegmentationStore::AddStatusReportL Exit [found=%d]", found); |
|
1204 return found; |
|
1205 } // CSmsSegmentationStore::AddStatusReportL |
|
1206 |
|
1207 |
|
1208 void CSmsSegmentationStore::GetMessageL(TInt aIndex,TSmsAddr& aSmsAddr,CSmsMessage& aSmsMessage, RSmsSegmentationStoreRefStatusArray& aRefStatusArray) |
|
1209 { |
|
1210 LOGSMSPROT2("CSmsSegmentationStore::GetMessageL [aIndex=%d]", aIndex); |
|
1211 |
|
1212 InternalizeEntryL(Entries()[aIndex].DataStreamId(),aSmsAddr,aSmsMessage, aRefStatusArray); |
|
1213 } // CSmsSegmentationStore::GetMessageL |
|
1214 |
|
1215 |
|
1216 /** |
|
1217 * internalize the concat refs from the permanent file store to internal memory |
|
1218 * |
|
1219 * @note You have to call CSARStore::OpenFileLC() before calling this function |
|
1220 * and CSARStore::CloseFile() after. |
|
1221 */ |
|
1222 void CSmsSegmentationStore::InternalizeConcatenationReferencesL(const TStreamId& aStreamId,TInt& aReference8bit,TInt& aReference16bit) |
|
1223 { |
|
1224 LOGSMSPROT1("CSmsSegmentationStore::InternalizeConcatenationReferencesL Start"); |
|
1225 RStoreReadStream readstream; |
|
1226 readstream.OpenLC(FileStore(),aStreamId); |
|
1227 aReference8bit=readstream.ReadInt32L(); |
|
1228 aReference16bit=readstream.ReadInt32L(); |
|
1229 CleanupStack::PopAndDestroy(); |
|
1230 LOGSMSPROT1("CSmsSegmentationStore::InternalizeConcatenationReferencesL End"); |
|
1231 } // CSmsSegmentationStore::InternalizeConcatenationReferencesL |
|
1232 |
|
1233 |
|
1234 /** |
|
1235 * externalize the concat refs from the permanent file store to internal memory |
|
1236 * |
|
1237 * @note You have to call CSARStore::OpenFileLC() before calling this function |
|
1238 * and CSARStore::CloseFile() after. |
|
1239 */ |
|
1240 void CSmsSegmentationStore::ExternalizeConcatenationReferencesL(TStreamId& aStreamId,TInt aReference8bit,TInt aReference16bit) |
|
1241 { |
|
1242 LOGSMSPROT1("CSmsSegmentationStore::ExternalizeConcatenationReferencesL Start"); |
|
1243 RStoreWriteStream writestream; |
|
1244 if (aStreamId==KNullStreamId) |
|
1245 aStreamId=writestream.CreateLC(FileStore()); |
|
1246 else |
|
1247 writestream.ReplaceLC(FileStore(),aStreamId); |
|
1248 writestream.WriteInt32L(aReference8bit); |
|
1249 writestream.WriteInt32L(aReference16bit); |
|
1250 writestream.CommitL(); |
|
1251 CleanupStack::PopAndDestroy(); |
|
1252 LOGSMSPROT1("CSmsSegmentationStore::ExternalizeConcatenationReferencesL End"); |
|
1253 } // CSmsSegmentationStore::ExternalizeConcatenationReferencesL |
|
1254 |
|
1255 |
|
1256 /** |
|
1257 * internalize all the entries from the permanent file store to internal memory |
|
1258 * |
|
1259 * @note You have to call CSARStore::OpenFileLC() before calling this function |
|
1260 * and CSARStore::CloseFile() after. |
|
1261 */ |
|
1262 void CSmsSegmentationStore::InternalizeEntryL(const TStreamId& aStreamId,TSmsAddr& aSmsAddr,CSmsMessage& aSmsMessage, RSmsSegmentationStoreRefStatusArray& aRefStatusArray) |
|
1263 { |
|
1264 LOGSMSPROT1("CSmsSegmentationStore::InternalizeEntryL Start"); |
|
1265 |
|
1266 aRefStatusArray.Reset(); |
|
1267 |
|
1268 RStoreReadStream readstream; |
|
1269 readstream.OpenLC(FileStore(),aStreamId); |
|
1270 readstream >> aSmsAddr; |
|
1271 readstream >> aSmsMessage; |
|
1272 readstream >> aRefStatusArray; |
|
1273 CleanupStack::PopAndDestroy(&readstream); |
|
1274 |
|
1275 LOGSMSPROT2("CSmsSegmentationStore::InternalizeEntryL End [count=%d]", aRefStatusArray.Count()); |
|
1276 } // CSmsSegmentationStore::InternalizeEntryL |
|
1277 |
|
1278 |
|
1279 /** |
|
1280 * externalizes all the entries from the internal memory to the permanent file store |
|
1281 */ |
|
1282 void CSmsSegmentationStore::ExternalizeEntryL(TStreamId& aStreamId,const TSmsAddr& aSmsAddr,const CSmsMessage& aSmsMessage, const RSmsSegmentationStoreRefStatusArray& aRefStatusArray) |
|
1283 { |
|
1284 LOGSMSPROT1("CSmsSegmentationStore::ExternalizeEntryL Start"); |
|
1285 |
|
1286 RStoreWriteStream writestream; |
|
1287 |
|
1288 if (aStreamId==KNullStreamId) |
|
1289 aStreamId=writestream.CreateLC(FileStore()); |
|
1290 else |
|
1291 writestream.ReplaceLC(FileStore(),aStreamId); |
|
1292 |
|
1293 writestream << aSmsAddr; |
|
1294 writestream << aSmsMessage; |
|
1295 writestream << aRefStatusArray; |
|
1296 writestream.CommitL(); |
|
1297 CleanupStack::PopAndDestroy(&writestream); |
|
1298 |
|
1299 LOGSMSPROT2("CSmsSegmentationStore::ExternalizeEntryL End [count=%d]", aRefStatusArray.Count()); |
|
1300 } // CSmsSegmentationStore::ExternalizeEntryL |
|
1301 |
|
1302 |
|
1303 /** |
|
1304 * Populates an SMS message into SAR store entry |
|
1305 * |
|
1306 * @pre aSmsMessage.EncodeMessagePdusL() has been called |
|
1307 * |
|
1308 * @param aEntry Entry to be populated to |
|
1309 * @param aSmsMessage SMS message to be populated from |
|
1310 * @param aReferenceArray Array containing references |
|
1311 * @param aStatusArray Array containing status |
|
1312 */ |
|
1313 void CSmsSegmentationStore::PopulateEntry(TSmsSegmentationEntry& aEntry, |
|
1314 const CSmsMessage& aSmsMessage, |
|
1315 const RSmsSegmentationStoreRefStatusArray& aRefStatusArray) |
|
1316 { |
|
1317 LOGSMSPROT1("CSmsSegmentationStore::PopulateEntry"); |
|
1318 TBool statusreportrequest=EFalse; |
|
1319 if (aSmsMessage.Type()==CSmsPDU::ESmsSubmit) |
|
1320 { |
|
1321 aEntry.SetReference(0); |
|
1322 aEntry.SetTotal(1); |
|
1323 CSmsSubmit& submit=(CSmsSubmit&) aSmsMessage.SmsPDU(); |
|
1324 aEntry.SetValidityPeriod(submit.ValidityPeriod().Int()); // TODO use val per type |
|
1325 |
|
1326 if (aSmsMessage.Scheme() == EDefaultScheme) |
|
1327 { |
|
1328 statusreportrequest=((CSmsSubmit&) aSmsMessage.SmsPDU()).StatusReportRequest(); |
|
1329 } |
|
1330 else |
|
1331 { |
|
1332 statusreportrequest = ETrue; |
|
1333 } |
|
1334 } |
|
1335 else |
|
1336 { |
|
1337 statusreportrequest=((CSmsCommand&) aSmsMessage.SmsPDU()).StatusReportRequest(); |
|
1338 } |
|
1339 |
|
1340 if (aSmsMessage.TextPresent()) |
|
1341 { |
|
1342 if (aSmsMessage.SmsPDU().TextConcatenated()) |
|
1343 { |
|
1344 aEntry.SetReference(aSmsMessage.SmsPDU().ConcatenatedMessageReference()); |
|
1345 |
|
1346 // |
|
1347 // aSmsMessage.EncodeMessagePdusL() must have been called before this point, |
|
1348 // otherwise aSmsMessage.SmsPDU().NumConcatenatedMessagePDUs() will return 1. |
|
1349 // |
|
1350 aEntry.SetTotal(aSmsMessage.SmsPDU().NumConcatenatedMessagePDUs()); |
|
1351 } |
|
1352 } |
|
1353 |
|
1354 aEntry.SetLogServerId(aSmsMessage.LogServerId()); |
|
1355 // Strip out spaces etc from address |
|
1356 TGsmSmsTelNumber parsedaddress; |
|
1357 aSmsMessage.ParsedToFromAddress(parsedaddress); |
|
1358 aEntry.SetDescription2(parsedaddress.iTelNumber); |
|
1359 aEntry.SetTime(aSmsMessage.Time()); |
|
1360 |
|
1361 const TInt count= aRefStatusArray.Count(); |
|
1362 __ASSERT_DEBUG((count>=0) && (count<=aEntry.Total()),SmspPanic(KSmspPanicBadReferenceArray)); |
|
1363 aEntry.SetCount(count); |
|
1364 TInt reference1=0xFF; |
|
1365 TInt reference2=0x00; |
|
1366 TInt startref=reference1; |
|
1367 TInt stopref=reference2; |
|
1368 |
|
1369 if(count>0 && statusreportrequest) |
|
1370 { |
|
1371 startref=aRefStatusArray[0].Reference(); |
|
1372 stopref=aRefStatusArray[count-1].Reference(); |
|
1373 } |
|
1374 |
|
1375 TInt delivered=0; |
|
1376 TInt failed=0; |
|
1377 for (TInt i=0; i<count; i++) |
|
1378 { |
|
1379 const TSmsSegmentationStoreRefStatus& refStatus = aRefStatusArray[i]; |
|
1380 |
|
1381 if (refStatus.Status() == TSmsStatus::ESmsShortMessageReceivedBySME) |
|
1382 delivered++; |
|
1383 else if (IsPermanentStatus(refStatus.Status())) |
|
1384 failed++; |
|
1385 } |
|
1386 |
|
1387 // |
|
1388 // AEH: Defect fix for EDNPAHN-4WADW3 'Unreliable logging' |
|
1389 // |
|
1390 // a little hack here to store information about whether |
|
1391 // we need Status Report or not, in the TSAREntry. This |
|
1392 // is because we want to retrieve it later in PurgeL. |
|
1393 // An extra bit is added iData4, LSB of byte 3. See gsmustor.h |
|
1394 // for more documentation. |
|
1395 // |
|
1396 aEntry.SetDeliveredAndFailed(delivered, failed); |
|
1397 TBool have_sr = EFalse; |
|
1398 |
|
1399 if (aSmsMessage.Scheme() == EDefaultScheme) |
|
1400 { |
|
1401 have_sr=((CSmsSubmit&) aSmsMessage.SmsPDU()).StatusReportRequest(); |
|
1402 } |
|
1403 else |
|
1404 { |
|
1405 have_sr = ETrue; |
|
1406 } |
|
1407 |
|
1408 aEntry.SetPduTypeAndRefs(have_sr, aSmsMessage.Type(), startref, stopref); |
|
1409 } // CSmsSegmentationStore::PopulateEntry |
|
1410 |
|
1411 |
|
1412 /** |
|
1413 * Returns ETrue if the status array is complete |
|
1414 * |
|
1415 * @param aStatusArray Array containing status |
|
1416 * @param aEntry SAR Entry |
|
1417 */ |
|
1418 TBool CSmsSegmentationStore::StatusArrayComplete(const RSmsSegmentationStoreRefStatusArray& aRefStatusArray, TSAREntry& aEntry) |
|
1419 { |
|
1420 TInt permanent=0; |
|
1421 const TInt count= aRefStatusArray.Count(); |
|
1422 for (TInt i=0; i<count; i++) |
|
1423 { |
|
1424 const TBool ret = IsPermanentStatus(aRefStatusArray[i].Status()); |
|
1425 LOGSMSPROT4("CSmsSegmentationStore::IsPermanentStatus [Status: %d, RetVal: %d, count=%d]", aRefStatusArray[i].Status(), ret, count); |
|
1426 if (ret) |
|
1427 permanent++; |
|
1428 } |
|
1429 /* |
|
1430 * |
|
1431 * TODO ahe - for release |
|
1432 * tested hack: the messagereceived function will be called right |
|
1433 * I did a lot of testing with multipart messages, the sms are |
|
1434 * almost always received and sent now, there might be only problems |
|
1435 * with the SR now - to wait for more logs to see what happens in this |
|
1436 * special cases - and the device crashes and is too slow of course |
|
1437 * |
|
1438 */ |
|
1439 return (permanent==count) && (permanent==aEntry.Total() ); |
|
1440 } // CSmsSegmentationStore::StatusArrayComplete |
|
1441 |
|
1442 |
|
1443 /** |
|
1444 * C'tor |
|
1445 */ |
|
1446 CSmsSegmentationStore::CSmsSegmentationStore(RFs& aFs) |
|
1447 :CSARStore(aFs) |
|
1448 { |
|
1449 LOGSMSPROT1("CSmsSegmentationStore::CSmsSegmentationStore()"); |
|
1450 |
|
1451 } // CSmsSegmentationStore::CSmsSegmentationStore |
|
1452 |
|
1453 |
|
1454 TInt CSmsSegmentationStore::TSmsSegmentationStoreRefStatus::Compare(const TSmsSegmentationStoreRefStatus& aLeft, const TSmsSegmentationStoreRefStatus& aRight) |
|
1455 { |
|
1456 LOGSMSPROT1("CSmsSegmentationStore::TSmsSegmentationStoreRefStatus::Compare()"); |
|
1457 |
|
1458 return aLeft.iReference - aRight.iReference; |
|
1459 } // CSmsSegmentationStore::TSmsSegmentationStoreRefStatus::Compare |
|
1460 |
|
1461 |
|
1462 void CSmsSegmentationStore::TSmsSegmentationStoreRefStatus::InternalizeL(RReadStream& aStream) |
|
1463 { |
|
1464 LOGSMSPROT1("CSmsSegmentationStore::TSmsSegmentationStoreRefStatus::InternalizeL()"); |
|
1465 |
|
1466 iReference = aStream.ReadInt32L(); |
|
1467 iStatus = aStream.ReadInt32L(); |
|
1468 } // CSmsSegmentationStore::TSmsSegmentationStoreRefStatus::InternalizeL |
|
1469 |
|
1470 |
|
1471 void CSmsSegmentationStore::TSmsSegmentationStoreRefStatus::ExternalizeL(RWriteStream& aStream) const |
|
1472 { |
|
1473 LOGSMSPROT1("CSmsSegmentationStore::TSmsSegmentationStoreRefStatus::ExternalizeL()"); |
|
1474 |
|
1475 aStream.WriteInt32L(iReference); |
|
1476 aStream.WriteInt32L(iStatus); |
|
1477 } // CSmsSegmentationStore::TSmsSegmentationStoreRefStatus::ExternalizeL |
|
1478 |
|
1479 |
|
1480 void CSmsSegmentationStore::RSmsSegmentationStoreRefStatusArray::InsertL(const TSmsSegmentationStoreRefStatus& aRefStatus) |
|
1481 { |
|
1482 LOGSMSPROT1("CSmsSegmentationStore::RSmsSegmentationStoreRefStatusArray::InsertL()"); |
|
1483 |
|
1484 TLinearOrder<TSmsSegmentationStoreRefStatus> order(TSmsSegmentationStoreRefStatus::Compare); |
|
1485 User::LeaveIfError(InsertInOrderAllowRepeats(aRefStatus, order)); |
|
1486 } // CSmsSegmentationStore::RSmsSegmentationStoreRefStatusArray::InsertL |
|
1487 |
|
1488 |
|
1489 TInt CSmsSegmentationStore::RSmsSegmentationStoreRefStatusArray::Find(const TSmsSegmentationStoreRefStatus& aRefStatus) const |
|
1490 { |
|
1491 LOGSMSPROT1("CSmsSegmentationStore::RSmsSegmentationStoreRefStatusArray::Find()"); |
|
1492 |
|
1493 TLinearOrder<TSmsSegmentationStoreRefStatus> order(TSmsSegmentationStoreRefStatus::Compare); |
|
1494 TInt index = FindInOrder(aRefStatus, order); |
|
1495 if (index != KErrNotFound) |
|
1496 { |
|
1497 //The function is to return the first occurence. However FindInOrder() |
|
1498 //uses a binary search algorithm and does not guarantee to return the 1st item if there are duplicate items. |
|
1499 //Therefore we manually check for duplicates to the left of the found item. |
|
1500 while (index > 0 && (operator[](index-1).Reference() == aRefStatus.Reference())) |
|
1501 { |
|
1502 --index; |
|
1503 } |
|
1504 } |
|
1505 return index; |
|
1506 } // CSmsSegmentationStore::RSmsSegmentationStoreRefStatusArray::Find |
|
1507 |
|
1508 |
|
1509 void CSmsSegmentationStore::RSmsSegmentationStoreRefStatusArray::CopyL(const RSmsSegmentationStoreRefStatusArray& aOther) |
|
1510 { |
|
1511 LOGSMSPROT1("CSmsSegmentationStore::RSmsSegmentationStoreRefStatusArray::CopyL()"); |
|
1512 |
|
1513 Reset(); |
|
1514 |
|
1515 TInt count = aOther.Count(); |
|
1516 while (count--) |
|
1517 { |
|
1518 InsertL(aOther[count]); |
|
1519 } |
|
1520 } // CSmsSegmentationStore::RSmsSegmentationStoreRefStatusArray::CopyL |
|
1521 |
|
1522 |
|
1523 void CSmsSegmentationStore::RSmsSegmentationStoreRefStatusArray::ResetAllStatus(TInt aStatus) |
|
1524 { |
|
1525 LOGSMSPROT1("CSmsSegmentationStore::RSmsSegmentationStoreRefStatusArray::ResetAllStatus()"); |
|
1526 |
|
1527 TInt count = Count(); |
|
1528 while (count--) |
|
1529 { |
|
1530 (*this)[count].SetStatus(aStatus); |
|
1531 } |
|
1532 } // CSmsSegmentationStore::RSmsSegmentationStoreRefStatusArray::ResetAllStatus |
|
1533 |
|
1534 |
|
1535 void CSmsSegmentationStore::RSmsSegmentationStoreRefStatusArray::InternalizeL(RReadStream& aStream) |
|
1536 { |
|
1537 LOGSMSPROT1("CSmsSegmentationStore::RSmsSegmentationStoreRefStatusArray::InternalizeL()"); |
|
1538 |
|
1539 TInt count = aStream.ReadInt32L(); |
|
1540 while (count--) |
|
1541 { |
|
1542 TSmsSegmentationStoreRefStatus refStatus; |
|
1543 aStream >> refStatus; |
|
1544 InsertL(refStatus); //maintain order |
|
1545 } |
|
1546 } // CSmsSegmentationStore::RSmsSegmentationStoreRefStatusArray::InternalizeL |
|
1547 |
|
1548 |
|
1549 void CSmsSegmentationStore::RSmsSegmentationStoreRefStatusArray::ExternalizeL(RWriteStream& aStream) const |
|
1550 { |
|
1551 LOGSMSPROT1("CSmsSegmentationStore::RSmsSegmentationStoreRefStatusArray::ExternalizeL()"); |
|
1552 |
|
1553 const TInt count = Count(); |
|
1554 aStream.WriteInt32L(count); |
|
1555 |
|
1556 for (TInt i = 0; i < count; i++) |
|
1557 { |
|
1558 aStream << (*this)[i]; |
|
1559 } |
|
1560 } // CSmsSegmentationStore::RSmsSegmentationStoreRefStatusArray::ExternalizeL |
|
1561 |
|
1562 |
|
1563 TBool CSmsSegmentationStore::HasEntryWithLogIdL(TLogId aLogID,TInt& aRefNo,TInt& aSent) |
|
1564 { |
|
1565 LOGSMSPROT1("CSmsSegmentationStore::HasEntryWithLogIdL()"); |
|
1566 |
|
1567 TInt count=Entries().Count(); |
|
1568 TBool found=EFalse; |
|
1569 if(aLogID != KLogNullId) |
|
1570 { |
|
1571 TInt total; |
|
1572 TInt sent; |
|
1573 BeginTransactionLC(); |
|
1574 for (TInt i=count-1; i>=0; --i) |
|
1575 { |
|
1576 if (aLogID==Entries()[i].LogServerId()) |
|
1577 { |
|
1578 const TSAREntry& entry=Entries()[i]; |
|
1579 total=entry.Total(); |
|
1580 sent=entry.Count(); |
|
1581 if( sent < total) |
|
1582 { |
|
1583 aSent=sent; |
|
1584 aRefNo=entry.Reference(); |
|
1585 found=ETrue; |
|
1586 } |
|
1587 else |
|
1588 { |
|
1589 DeleteEntryL(i); |
|
1590 LOGSMSPROT3("CSmsSegmentationStore::HasEntryWithLogIdL [Entry: %d LogId %d - deleted]", i, aLogID ); |
|
1591 } |
|
1592 break; |
|
1593 } |
|
1594 } |
|
1595 CommitTransactionL(); |
|
1596 } |
|
1597 return found; |
|
1598 } // CSmsSegmentationStore::HasEntryWithLogIdL |
|
1599 |
|
1600 |
|
1601 /** |
|
1602 * Open the sms segmentation store. |
|
1603 */ |
|
1604 void CSmsSegmentationStore::OpenStoreL() |
|
1605 { |
|
1606 LOGSMSPROT1("CSmsSegmentationStore::OpenStoreL()"); |
|
1607 |
|
1608 this->OpenL(iFullPathBuf,KSegmentationStoreUid); |
|
1609 } // CSmsSegmentationStore::OpenStoreL |