24
|
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 |
{
|
|
563 |
LOGSMSPROT1("CSmsReassemblyStore::SetPassedToClientL()");
|
|
564 |
|
|
565 |
TSmsReassemblyEntry entry(reinterpret_cast<const TSmsReassemblyEntry&>(Entries()[aIndex]));
|
|
566 |
|
|
567 |
const TBool alreadyPassed = entry.PassedToClient();
|
|
568 |
|
|
569 |
if ((!aPassed && alreadyPassed) || (aPassed && !alreadyPassed))
|
|
570 |
{
|
|
571 |
entry.SetPassedToClient(aPassed);
|
|
572 |
ChangeEntryL(aIndex, entry);
|
|
573 |
}
|
|
574 |
} // CSmsReassemblyStore::SetPassedToClientL
|
|
575 |
|
|
576 |
|
|
577 |
/**
|
|
578 |
* Open the sms reassembly store.
|
|
579 |
*/
|
|
580 |
void CSmsReassemblyStore::OpenStoreL()
|
|
581 |
{
|
|
582 |
LOGSMSPROT1("CSmsReassemblyStore::OpenStoreL()");
|
|
583 |
|
|
584 |
this->OpenL(iFullPathBuf,KReassemblyStoreUid);
|
|
585 |
} // CSmsReassemblyStore::OpenStoreL
|
|
586 |
|
|
587 |
|
|
588 |
/**
|
|
589 |
* Constructor
|
|
590 |
*
|
|
591 |
* @param aFs Used to set CSARStore object
|
|
592 |
*/
|
|
593 |
CSmsReassemblyStore::CSmsReassemblyStore(RFs& aFs)
|
|
594 |
:CSARStore(aFs)
|
|
595 |
{
|
|
596 |
// NOP
|
|
597 |
} // CSmsReassemblyStore::CSmsReassemblyStore
|
|
598 |
|
|
599 |
|
|
600 |
CSmsSegmentationStore* CSmsSegmentationStore::NewL(RFs& aFs)
|
|
601 |
{
|
|
602 |
LOGSMSPROT1("CSmsSegmentationStore::NewL()");
|
|
603 |
|
|
604 |
CSmsSegmentationStore* segmentationStore = new(ELeave) CSmsSegmentationStore(aFs);
|
|
605 |
CleanupStack::PushL( segmentationStore );
|
|
606 |
segmentationStore->ConstructL();
|
|
607 |
CleanupStack::Pop( segmentationStore );
|
|
608 |
return segmentationStore;
|
|
609 |
} // CSmsSegmentationStore::NewL
|
|
610 |
|
|
611 |
|
|
612 |
void CSmsSegmentationStore::ConstructL()
|
|
613 |
{
|
|
614 |
LOGSMSPROT1("CSmsSegmentationStore::ConstructL()");
|
|
615 |
|
|
616 |
//generate fullpath of segmentation store.
|
|
617 |
PrivatePath(iFullPathBuf);
|
|
618 |
//append store name
|
|
619 |
iFullPathBuf.Append(KSegmentationStoreName);
|
|
620 |
|
|
621 |
// Set the default value for the maxmum number messages in the segmentation store.
|
|
622 |
iMaxmumNumberOfMessagesInSegmentationStore = KDefaultMaxmumNumberOfMessagesInSegmentationStore;
|
|
623 |
|
|
624 |
CESockIniData* ini = NULL;
|
|
625 |
_LIT(KSmseskfile, "smswap.sms.esk");
|
|
626 |
TRAPD(ret, ini=CESockIniData::NewL(KSmseskfile));
|
|
627 |
if(ret == KErrNone)
|
|
628 |
{
|
|
629 |
// Get the maximum number of messages allowed in the segmentation store from .ESK file
|
|
630 |
CleanupStack::PushL(ini);
|
|
631 |
|
|
632 |
TPtrC value;
|
|
633 |
if((ini->FindVar(_L("SegmentationStoreOptions"),_L("MaxNumOfMessInSegStore"),value)))
|
|
634 |
{
|
|
635 |
TLex16 valueconv(value);
|
|
636 |
valueconv.Val(iMaxmumNumberOfMessagesInSegmentationStore);
|
|
637 |
}
|
|
638 |
CleanupStack::PopAndDestroy(ini);
|
|
639 |
}
|
|
640 |
else if (ret != KErrNotFound && ret != KErrPathNotFound)
|
|
641 |
{
|
|
642 |
User::Leave(ret);
|
|
643 |
}
|
|
644 |
} // CSmsSegmentationStore::ConstructL
|
|
645 |
|
|
646 |
|
|
647 |
CSmsSegmentationStore::~CSmsSegmentationStore()
|
|
648 |
{
|
|
649 |
// NOP
|
|
650 |
} // CSmsSegmentationStore::~CSmsSegmentationStore
|
|
651 |
|
|
652 |
|
|
653 |
TInt CSmsSegmentationStore::Next8BitReferenceL()
|
|
654 |
{
|
|
655 |
LOGSMSPROT1("CSmsSegmentationStore::Next8BitReferenceL");
|
|
656 |
|
|
657 |
TInt reference8bit=0;
|
|
658 |
TInt reference16bit=0;
|
|
659 |
TStreamId streamid=ExtraStreamId();
|
|
660 |
|
|
661 |
//
|
|
662 |
// access file store
|
|
663 |
//
|
|
664 |
BeginTransactionLC();
|
|
665 |
if (streamid!=KNullStreamId)
|
|
666 |
{
|
|
667 |
TRAPD(ret,InternalizeConcatenationReferencesL(streamid,reference8bit,reference16bit));
|
|
668 |
if(ret != KErrNone)
|
|
669 |
{
|
|
670 |
// We have to leave on any error; otherwise a duplicate reference number will be generated
|
|
671 |
// The transaction will revert
|
|
672 |
LOGSMSPROT2("WARNING! CSmsSegmentationStore::InternalizeConcatenationReferencesL left with %d", ret);
|
|
673 |
User::Leave(ret); // stream not corrupted
|
|
674 |
}
|
|
675 |
reference8bit=(reference8bit+1)%0x100;
|
|
676 |
}
|
|
677 |
TRAPD(ret, ExternalizeConcatenationReferencesL(streamid,reference8bit,reference16bit));
|
|
678 |
if(ret != KErrNone)
|
|
679 |
{
|
|
680 |
// We have to leave on any error; otherwise a duplicate reference number will be generated
|
|
681 |
// The transaction will revert
|
|
682 |
LOGSMSPROT2("WARNING! CSmsSegmentationStore::ExternalizeConcatenationReferencesL left with %d", ret);
|
|
683 |
User::Leave(ret); // stream not corrupted
|
|
684 |
}
|
|
685 |
SetExtraStreamIdL(streamid);
|
|
686 |
CommitTransactionL();
|
|
687 |
return reference8bit;
|
|
688 |
} // CSmsSegmentationStore::Next8BitReferenceL
|
|
689 |
|
|
690 |
|
|
691 |
TInt CSmsSegmentationStore::Next16BitReferenceL()
|
|
692 |
{
|
|
693 |
LOGSMSPROT1("CSmsSegmentationStore::Next16BitReferenceL");
|
|
694 |
TInt reference8bit=0;
|
|
695 |
TInt reference16bit=0x100;
|
|
696 |
TStreamId streamid=ExtraStreamId();
|
|
697 |
//
|
|
698 |
// access file store
|
|
699 |
//
|
|
700 |
BeginTransactionLC();
|
|
701 |
if (streamid!=KNullStreamId)
|
|
702 |
{
|
|
703 |
TRAPD(ret,InternalizeConcatenationReferencesL(streamid,reference8bit,reference16bit));
|
|
704 |
if(ret != KErrNone)
|
|
705 |
{
|
|
706 |
// We have to leave on any error; otherwise a duplicate reference number will be generated
|
|
707 |
// The transaction will revert
|
|
708 |
LOGSMSPROT2("WARNING! CSmsSegmentationStore::InternalizeConcatenationReferencesL left with %d", ret);
|
|
709 |
User::Leave(ret); // stream not corrupted
|
|
710 |
}
|
|
711 |
reference16bit=((reference16bit+1)%0xFF00)+0x100;
|
|
712 |
}
|
|
713 |
TRAPD(ret, ExternalizeConcatenationReferencesL(streamid,reference8bit,reference16bit));
|
|
714 |
if(ret != KErrNone)
|
|
715 |
{
|
|
716 |
// We have to leave on any error; otherwise a duplicate reference number will be generated
|
|
717 |
// The transaction will revert
|
|
718 |
LOGSMSPROT2("WARNING! CSmsSegmentationStore::ExternalizeConcatenationReferencesL left with %d", ret);
|
|
719 |
User::Leave(ret); // stream not corrupted
|
|
720 |
}
|
|
721 |
SetExtraStreamIdL(streamid);
|
|
722 |
CommitTransactionL();
|
|
723 |
return reference16bit;
|
|
724 |
} // CSmsSegmentationStore::Next16BitReferenceL
|
|
725 |
|
|
726 |
|
|
727 |
/**
|
|
728 |
* Adds a CSmsMessage to the segmentation store
|
|
729 |
*
|
|
730 |
* @note aSumbit.Buffer() may be shortened to TSAREntry::ESmsSAREntryDescriptionLength
|
|
731 |
*
|
|
732 |
* @param aSubmit Message to add to the segmentation store
|
|
733 |
* @pre aSubmit.Type() is ESmsSubmit
|
|
734 |
* @pre aSubmit.EncodeMessagePdusL() has been called. This is so PopulateEntry sets the correct total on the TSAREntry
|
|
735 |
*/
|
|
736 |
void CSmsSegmentationStore::AddSubmitL(const TSmsAddr& aSmsAddr,CSmsMessage& aSubmit)
|
|
737 |
{
|
|
738 |
LOGSMSPROT1("CSmsSegmentationStore::AddSubmitL");
|
|
739 |
|
|
740 |
__ASSERT_ALWAYS(aSubmit.Type()==CSmsPDU::ESmsSubmit,SmspPanic(KSmspPanicNotSubmit));
|
|
741 |
|
|
742 |
BeginTransactionLC();
|
|
743 |
|
|
744 |
|
|
745 |
RSmsSegmentationStoreRefStatusArray refStatus;
|
|
746 |
CleanupClosePushL(refStatus);
|
|
747 |
|
|
748 |
TStreamId streamid=KNullStreamId;
|
|
749 |
CSmsBufferBase& buffer=aSubmit.Buffer();
|
|
750 |
TInt length=buffer.Length();
|
|
751 |
if (length>TSAREntry::ESmsSAREntryDescriptionLength)
|
|
752 |
buffer.DeleteL(TSAREntry::ESmsSAREntryDescriptionLength,length-TSAREntry::ESmsSAREntryDescriptionLength);
|
|
753 |
|
|
754 |
ExternalizeEntryL(streamid,aSmsAddr,aSubmit, refStatus);
|
|
755 |
|
|
756 |
TSmsSegmentationEntry entry;
|
|
757 |
entry.SetDataStreamId(streamid);
|
|
758 |
PopulateEntry(entry, aSubmit, refStatus);
|
|
759 |
|
|
760 |
CleanupStack::PopAndDestroy(&refStatus);
|
|
761 |
|
|
762 |
AddEntryL(entry);
|
|
763 |
CommitTransactionL();
|
|
764 |
} // CSmsSegmentationStore::AddSubmitL
|
|
765 |
|
|
766 |
|
|
767 |
TBool CSmsSegmentationStore::AddCommandL(const TSmsAddr& aSmsAddr,const CSmsMessage& aCommand, CSmsSegmentationStore::RSmsSegmentationStoreRefStatusArray& aRefStatus)
|
|
768 |
{
|
|
769 |
LOGSMSPROT1("CSmsSegmentationStore::AddCommandL");
|
|
770 |
__ASSERT_ALWAYS(aCommand.Type()==CSmsPDU::ESmsCommand,SmspPanic(KSmspPanicNotCommand));
|
|
771 |
const TInt count=Entries().Count();
|
|
772 |
const TLogId logid=(TLogId) aCommand.LogServerId();
|
|
773 |
|
|
774 |
BeginTransactionLC();
|
|
775 |
|
|
776 |
for (TInt i=count-1; i>=0; --i)
|
|
777 |
{
|
|
778 |
if ((logid!=KLogNullId) && (logid==Entries()[i].LogServerId()))
|
|
779 |
{
|
|
780 |
DeleteEntryL(i);
|
|
781 |
break;
|
|
782 |
}
|
|
783 |
}
|
|
784 |
TBool found=EFalse;
|
|
785 |
|
|
786 |
CSmsBuffer* buffer=CSmsBuffer::NewL();
|
|
787 |
CSmsMessage* smsmessage=CSmsMessage::NewL(iFs, CSmsPDU::ESmsSubmit,buffer);
|
|
788 |
CleanupStack::PushL(smsmessage);
|
|
789 |
TGsmSmsTelNumber parsedaddress;
|
|
790 |
aCommand.ParsedToFromAddress(parsedaddress);
|
|
791 |
TInt telLen;
|
|
792 |
|
|
793 |
for (TInt j=0; j<count; j++)
|
|
794 |
{
|
|
795 |
TSmsSegmentationEntry entry = (TSmsSegmentationEntry&)Entries()[j];
|
|
796 |
const CSmsPDU::TSmsPDUType type = entry.PduType();
|
|
797 |
telLen=Min(entry.Description2().Length(),parsedaddress.iTelNumber.Length());
|
|
798 |
if ((type==CSmsPDU::ESmsSubmit) &&
|
|
799 |
entry.IsComplete() &&
|
|
800 |
(entry.Description2().Right(telLen)==parsedaddress.iTelNumber.Right(telLen)) &&
|
|
801 |
(entry.Time()==aCommand.Time()))
|
|
802 |
{
|
|
803 |
found=ETrue;
|
|
804 |
TSmsAddr smsaddr;
|
|
805 |
|
|
806 |
InternalizeEntryL(entry.DataStreamId(),smsaddr,*smsmessage, aRefStatus);
|
|
807 |
TStreamId streamid;
|
|
808 |
CSmsSubmit& submit=(CSmsSubmit&) smsmessage->SmsPDU();
|
|
809 |
if ((((CSmsCommand&) aCommand.SmsPDU()).CommandType()==TSmsCommandType::ESmsCommandTypeEnableStatusReportRequest) &&
|
|
810 |
(!submit.StatusReportRequest()))
|
|
811 |
{
|
|
812 |
submit.SetStatusReportRequest(ETrue);
|
|
813 |
streamid=entry.DataStreamId();
|
|
814 |
ExternalizeEntryL(streamid,smsaddr,*smsmessage, aRefStatus);
|
|
815 |
PopulateEntry(entry,*smsmessage, aRefStatus);
|
|
816 |
ChangeEntryL(j,entry);
|
|
817 |
}
|
|
818 |
|
|
819 |
RSmsSegmentationStoreRefStatusArray refStatusTemp;
|
|
820 |
CleanupClosePushL(refStatusTemp);
|
|
821 |
|
|
822 |
streamid=KNullStreamId;
|
|
823 |
|
|
824 |
ExternalizeEntryL(streamid,aSmsAddr,aCommand, refStatusTemp);
|
|
825 |
entry.SetDataStreamId(streamid);
|
|
826 |
PopulateEntry(entry,aCommand, refStatusTemp);
|
|
827 |
|
|
828 |
CleanupStack::PopAndDestroy(&refStatusTemp);
|
|
829 |
|
|
830 |
AddEntryL(entry);
|
|
831 |
|
|
832 |
break;
|
|
833 |
}
|
|
834 |
}
|
|
835 |
CleanupStack::PopAndDestroy(smsmessage); // smsmessage
|
|
836 |
CommitTransactionL();
|
|
837 |
|
|
838 |
return found;
|
|
839 |
} // CSmsSegmentationStore::AddCommandL
|
|
840 |
|
|
841 |
|
|
842 |
TBool CSmsSegmentationStore::AddReferenceL(const CSmsMessage& aSmsMessage,TInt aReference)
|
|
843 |
{
|
|
844 |
const TInt count=Entries().Count();
|
|
845 |
LOGSMSPROT3("CSmsSegmentationStore::AddReferenceL [count=%d, ref=%d]", count, aReference);
|
|
846 |
TInt i=0;
|
|
847 |
TInt logserverid=aSmsMessage.LogServerId();
|
|
848 |
if (logserverid!=KLogNullId)
|
|
849 |
{
|
|
850 |
for (i=0; i<count; i++)
|
|
851 |
{
|
|
852 |
if (logserverid==((TSmsSegmentationEntry&)Entries()[i]).LogServerId())
|
|
853 |
break;
|
|
854 |
}
|
|
855 |
}
|
|
856 |
else
|
|
857 |
{
|
|
858 |
TGsmSmsTelNumber parsedaddress;
|
|
859 |
aSmsMessage.ParsedToFromAddress(parsedaddress);
|
|
860 |
TInt telLen;
|
|
861 |
for (i=0; i<count; i++)
|
|
862 |
{
|
|
863 |
TSAREntry tsareenty = Entries()[i];
|
|
864 |
TSmsSegmentationEntry& entry = static_cast<TSmsSegmentationEntry&>(tsareenty);
|
|
865 |
telLen=Min(entry.Description2().Length(),parsedaddress.iTelNumber.Length());
|
|
866 |
const CSmsPDU::TSmsPDUType type=entry.PduType();
|
|
867 |
if ((type==aSmsMessage.Type()) && (!entry.IsComplete()) && (aSmsMessage.Time()==entry.Time()) && (entry.Description2().Right(telLen)==parsedaddress.iTelNumber.Right(telLen)))
|
|
868 |
break;
|
|
869 |
}
|
|
870 |
}
|
|
871 |
if(i>=count)
|
|
872 |
{
|
|
873 |
LOGSMSPROT3("WARNING! KSmspPanicEntryWithLogServerIdNotFound [i=%d, count=%d]", i, count);
|
|
874 |
return EFalse;
|
|
875 |
}
|
|
876 |
|
|
877 |
RSmsSegmentationStoreRefStatusArray refStatusArray;
|
|
878 |
CleanupClosePushL(refStatusArray);
|
|
879 |
|
|
880 |
TSAREntry tsareenty = Entries()[i];
|
|
881 |
TSmsSegmentationEntry& entry = static_cast<TSmsSegmentationEntry&>(tsareenty);
|
|
882 |
TStreamId streamid=entry.DataStreamId();
|
|
883 |
TSmsAddr smsaddr;
|
|
884 |
CSmsBuffer* buffer=CSmsBuffer::NewL();
|
|
885 |
CSmsMessage* smsmessage=CSmsMessage::NewL(iFs, CSmsPDU::ESmsDeliver,buffer);
|
|
886 |
CleanupStack::PushL(smsmessage);
|
|
887 |
|
|
888 |
//
|
|
889 |
// access the file store
|
|
890 |
//
|
|
891 |
InternalizeEntryL(streamid,smsaddr,*smsmessage, refStatusArray);
|
|
892 |
refStatusArray.InsertL(aReference);
|
|
893 |
|
|
894 |
BeginTransactionLC();
|
|
895 |
ExternalizeEntryL(streamid,smsaddr,*smsmessage, refStatusArray);
|
|
896 |
|
|
897 |
PopulateEntry(entry,/*smsaddr,*/*smsmessage, refStatusArray);
|
|
898 |
ChangeEntryL(i,entry);
|
|
899 |
CommitTransactionL();
|
|
900 |
|
|
901 |
//
|
|
902 |
// AEH: moved here because if is done before calling ChangeEntryL
|
|
903 |
// it will pop and destroy the filestore which is also on
|
|
904 |
// the cleanup stack
|
|
905 |
//
|
|
906 |
CleanupStack::PopAndDestroy(2); // smsmessage, refStatus
|
|
907 |
|
|
908 |
return entry.Total()==entry.Count();
|
|
909 |
}
|
|
910 |
|
|
911 |
|
|
912 |
/**
|
|
913 |
* Does exactly the same thing as AddReferenceL() i.e. adds the the segment refernce to a list. But
|
|
914 |
* to support the new status report schemes a slight change has been made. Instead of inserting
|
|
915 |
* just a reference now its status is inserted as well. This is provided one of the two new schemes
|
|
916 |
* is being used. If the status is required then we do exactly the same as AddReferenceL(), but if
|
|
917 |
* it's not then we just call the InsertL() method with an extra parameter: EStatusComplete.
|
|
918 |
*
|
|
919 |
* @param aSmsMessage Reference to CSmsMessage.
|
|
920 |
* @param aReference The PDU reference.
|
|
921 |
*/
|
|
922 |
TBool CSmsSegmentationStore::AddReferenceStatusPairL(const CSmsMessage& aSmsMessage,TInt aReference, TUint aSegmentSequenceNumber)
|
|
923 |
{
|
|
924 |
const TInt count=Entries().Count();
|
|
925 |
LOGSMSPROT3("CSmsSegmentationStore::AddReferenceStatusPairL [count=%d, ref=%d]", count, aReference);
|
|
926 |
TInt i=0;
|
|
927 |
TInt logserverid=aSmsMessage.LogServerId();
|
|
928 |
if (logserverid!=KLogNullId)
|
|
929 |
{
|
|
930 |
for (i=0; i<count; i++)
|
|
931 |
{
|
|
932 |
if (logserverid==((TSmsSegmentationEntry&)Entries()[i]).LogServerId())
|
|
933 |
break;
|
|
934 |
}
|
|
935 |
}
|
|
936 |
else
|
|
937 |
{
|
|
938 |
TGsmSmsTelNumber parsedaddress;
|
|
939 |
aSmsMessage.ParsedToFromAddress(parsedaddress);
|
|
940 |
TInt telLen;
|
|
941 |
for (i=0; i<count; i++)
|
|
942 |
{
|
|
943 |
TSAREntry tsareenty = Entries()[i];
|
|
944 |
TSmsSegmentationEntry& entry = static_cast<TSmsSegmentationEntry&>(tsareenty);
|
|
945 |
telLen=Min(entry.Description2().Length(),parsedaddress.iTelNumber.Length());
|
|
946 |
const CSmsPDU::TSmsPDUType type=entry.PduType();
|
|
947 |
if ((type==aSmsMessage.Type()) && (!entry.IsComplete()) && (aSmsMessage.Time()==entry.Time()) && (entry.Description2().Right(telLen)==parsedaddress.iTelNumber.Right(telLen)))
|
|
948 |
break;
|
|
949 |
}
|
|
950 |
}
|
|
951 |
if(i>=count)
|
|
952 |
{
|
|
953 |
LOGSMSPROT3("WARNING! KSmspPanicEntryWithLogServerIdNotFound [i=%d, count=%d]", i, count);
|
|
954 |
return EFalse;
|
|
955 |
}
|
|
956 |
|
|
957 |
RSmsSegmentationStoreRefStatusArray refStatusArray;
|
|
958 |
CleanupClosePushL(refStatusArray);
|
|
959 |
TSAREntry tsareenty = Entries()[i];
|
|
960 |
TSmsSegmentationEntry& entry = static_cast<TSmsSegmentationEntry&>(tsareenty);
|
|
961 |
|
|
962 |
TStreamId streamid=entry.DataStreamId();
|
|
963 |
TSmsAddr smsaddr;
|
|
964 |
CSmsBuffer* buffer=CSmsBuffer::NewL();
|
|
965 |
CSmsMessage* smsmessage=CSmsMessage::NewL(iFs, CSmsPDU::ESmsDeliver,buffer);
|
|
966 |
CleanupStack::PushL(smsmessage);
|
|
967 |
|
|
968 |
//
|
|
969 |
// access the file store
|
|
970 |
//
|
|
971 |
InternalizeEntryL(streamid,smsaddr,*smsmessage, refStatusArray);
|
|
972 |
|
|
973 |
if (aSmsMessage.Scheme() == EControlParametersScheme)
|
|
974 |
{
|
|
975 |
TUint8 octet(0);
|
|
976 |
TInt ret;
|
|
977 |
|
|
978 |
ret = ((CSmsSMSCCtrlParameterOperations&)aSmsMessage.GetOperationsForIEL(CSmsInformationElement::ESmsIEISMSCControlParameters)).GetStatusReport(aSegmentSequenceNumber, octet);
|
|
979 |
if (ret == KErrNone)
|
|
980 |
{
|
|
981 |
if (octet & ESmsSMSCControlParametersMask)
|
|
982 |
{
|
|
983 |
refStatusArray.InsertL(aReference);
|
|
984 |
}
|
|
985 |
else
|
|
986 |
{
|
|
987 |
refStatusArray.InsertL(TSmsSegmentationStoreRefStatus(aReference, EStatusComplete));
|
|
988 |
}
|
|
989 |
}
|
|
990 |
}
|
|
991 |
else if(aSmsMessage.Scheme() == ETPSRRScheme)
|
|
992 |
{
|
|
993 |
TInt tpsrr;
|
|
994 |
tpsrr = ((CSmsTPSRROperations&)aSmsMessage.GetOperationsForNonIEL(ESmsTPSRRParameter)).GetStatusReport(aSegmentSequenceNumber);
|
|
995 |
|
|
996 |
if(tpsrr == TSmsFirstOctet::ESmsStatusReportNotRequested)
|
|
997 |
{
|
|
998 |
refStatusArray.InsertL(TSmsSegmentationStoreRefStatus(aReference, EStatusComplete));
|
|
999 |
}
|
|
1000 |
else if(tpsrr == TSmsFirstOctet::ESmsStatusReportRequested)
|
|
1001 |
{
|
|
1002 |
refStatusArray.InsertL(aReference);
|
|
1003 |
}
|
|
1004 |
}
|
|
1005 |
else
|
|
1006 |
{
|
|
1007 |
User::Leave(KErrArgument);
|
|
1008 |
}
|
|
1009 |
|
|
1010 |
|
|
1011 |
BeginTransactionLC();
|
|
1012 |
ExternalizeEntryL(streamid,smsaddr,*smsmessage, refStatusArray);
|
|
1013 |
|
|
1014 |
PopulateEntry(entry,/*smsaddr,*/*smsmessage, refStatusArray);
|
|
1015 |
ChangeEntryL(i,entry);
|
|
1016 |
CommitTransactionL();
|
|
1017 |
|
|
1018 |
//
|
|
1019 |
// AEH: moved here because if is done before calling ChangeEntryL
|
|
1020 |
// it will pop and destroy the filestore which is also on
|
|
1021 |
// the cleanup stack
|
|
1022 |
//
|
|
1023 |
CleanupStack::PopAndDestroy(2); // smsmessage, refStatus
|
|
1024 |
|
|
1025 |
return entry.Total()==entry.Count();
|
|
1026 |
} // CSmsSegmentationStore::AddReferenceStatusPairL
|
|
1027 |
|
|
1028 |
|
|
1029 |
TBool CSmsSegmentationStore::AddStatusReportL(TInt& aIndex,TBool& aComplete,const CSmsMessage& aStatusReport)
|
|
1030 |
{
|
|
1031 |
LOGSMSPROT1("CSmsSegmentationStore::AddStatusReportL");
|
|
1032 |
|
|
1033 |
__ASSERT_DEBUG(aStatusReport.Type()==CSmsPDU::ESmsStatusReport,SmspPanic(KSmspPanicNotStatusReport));
|
|
1034 |
|
|
1035 |
const CSmsStatusReport& statusreport=(CSmsStatusReport&) aStatusReport.SmsPDU();
|
|
1036 |
const TInt reference=statusreport.MessageReference();
|
|
1037 |
const TInt status=statusreport.Status();
|
|
1038 |
const TInt isPerm = IsPermanentStatus(status);
|
|
1039 |
const TSmsFirstOctet::TSmsStatusReportQualifier qualifier=statusreport.StatusReportQualifier();
|
|
1040 |
TBool found=EFalse;
|
|
1041 |
aComplete=EFalse;
|
|
1042 |
|
|
1043 |
LOGSMSPROT4("CSmsSegmentationStore::AddStatusReportL [ref=%d status=%d IsPerm=%d]", reference, status, isPerm);
|
|
1044 |
|
|
1045 |
if(!isPerm)
|
|
1046 |
{
|
|
1047 |
return EFalse;
|
|
1048 |
}
|
|
1049 |
|
|
1050 |
RSmsSegmentationStoreRefStatusArray refStatusArray;
|
|
1051 |
CleanupClosePushL(refStatusArray);
|
|
1052 |
|
|
1053 |
const TInt count1=Entries().Count();
|
|
1054 |
|
|
1055 |
TSmsAddr smsaddr;
|
|
1056 |
CSmsBuffer* buffer=CSmsBuffer::NewL();
|
|
1057 |
CSmsMessage* smsmessage=CSmsMessage::NewL(iFs, CSmsPDU::ESmsDeliver,buffer);
|
|
1058 |
CleanupStack::PushL(smsmessage);
|
|
1059 |
TGsmSmsTelNumber parsedaddress;
|
|
1060 |
aStatusReport.ParsedToFromAddress(parsedaddress);
|
|
1061 |
|
|
1062 |
BeginTransactionLC();
|
|
1063 |
|
|
1064 |
aIndex = count1;
|
|
1065 |
|
|
1066 |
TInt telLen;
|
|
1067 |
while (!found && aIndex--)
|
|
1068 |
{
|
|
1069 |
TSAREntry tsareenty = Entries()[aIndex];
|
|
1070 |
TSmsSegmentationEntry& entry = static_cast<TSmsSegmentationEntry&>(tsareenty);
|
|
1071 |
|
|
1072 |
// Remove leading zeros of national numbers
|
|
1073 |
TPtrC trimmedTelNumber(TrimLeadingZeros(entry.Description2()));
|
|
1074 |
TPtrC trimmedParsedTelNumber(TrimLeadingZeros(parsedaddress.iTelNumber));
|
|
1075 |
|
|
1076 |
telLen=Min(trimmedTelNumber.Length(),trimmedParsedTelNumber.Length());
|
|
1077 |
|
|
1078 |
const CSmsPDU::TSmsPDUType type = entry.PduType();
|
|
1079 |
const TInt startref = entry.Reference1();
|
|
1080 |
const TInt stopref = entry.Reference2();
|
|
1081 |
|
|
1082 |
TBool sameTelNumbers = entry.Description2().Right(telLen) == parsedaddress.iTelNumber.Right(telLen);
|
|
1083 |
|
|
1084 |
if (sameTelNumbers)
|
|
1085 |
{
|
|
1086 |
LOGSMSPROT1("CSmsSegmentationStore::AddStatusReportL telNumber from submit report matches that from SMS message");
|
|
1087 |
}
|
|
1088 |
else
|
|
1089 |
{
|
|
1090 |
LOGSMSPROT1("CSmsSegmentationStore::AddStatusReportL telNumber from submit report does NOT match that from SMS message");
|
|
1091 |
}
|
|
1092 |
|
|
1093 |
if (sameTelNumbers &&
|
|
1094 |
(((qualifier==TSmsFirstOctet::ESmsStatusReportResultOfCommand) && (type==CSmsPDU::ESmsCommand)) ||
|
|
1095 |
((qualifier==TSmsFirstOctet::ESmsStatusReportResultOfSubmit) && (type==CSmsPDU::ESmsSubmit))) &&
|
|
1096 |
(((stopref>=startref) &&(reference>=startref) && (reference<=stopref))||((stopref<startref) &&((reference>=startref) || (reference<=stopref))))
|
|
1097 |
)
|
|
1098 |
{
|
|
1099 |
InternalizeEntryL(entry.DataStreamId(),smsaddr,*smsmessage, refStatusArray);
|
|
1100 |
TInt refStatusPos = refStatusArray.Find(reference); //assumes Find returns the first matching reference in the array
|
|
1101 |
TInt numMessagePDUs=entry.Total();
|
|
1102 |
|
|
1103 |
if (refStatusPos != KErrNotFound)
|
|
1104 |
{
|
|
1105 |
const TInt refStatusArrayCount = refStatusArray.Count();
|
|
1106 |
|
|
1107 |
//Find an element in refStatusArray where Reference() == reference and Status() is not permanent
|
|
1108 |
while (!found && refStatusPos < refStatusArrayCount && refStatusArray[refStatusPos].Reference() == reference)
|
|
1109 |
{
|
|
1110 |
//@note This loop assumes refStatusArray is sorted iReference
|
|
1111 |
if (!IsPermanentStatus(refStatusArray[refStatusPos].Status())&&(refStatusArrayCount <= numMessagePDUs))
|
|
1112 |
{
|
|
1113 |
found = ETrue;
|
|
1114 |
}
|
|
1115 |
else
|
|
1116 |
{
|
|
1117 |
LOGSMSPROT4("CSmsSegmentationStore::AddStatusReportL WARNING: Status already perm [status=%d refStatusPos=%d count=%d]", refStatusArray[refStatusPos].Status(), refStatusPos, refStatusArrayCount);
|
|
1118 |
refStatusPos++;
|
|
1119 |
}
|
|
1120 |
}
|
|
1121 |
|
|
1122 |
if (found)
|
|
1123 |
{
|
|
1124 |
LOGSMSPROT2("CSmsSegmentationStore::AddStatusReportL Found [refStatusPos=%d]", refStatusPos);
|
|
1125 |
refStatusArray[refStatusPos].SetStatus(status);
|
|
1126 |
TStreamId streamid=entry.DataStreamId();
|
|
1127 |
ExternalizeEntryL(streamid,smsaddr,*smsmessage, refStatusArray);
|
|
1128 |
PopulateEntry(entry,*smsmessage, refStatusArray);
|
|
1129 |
ChangeEntryL(aIndex,entry);
|
|
1130 |
aComplete=StatusArrayComplete(refStatusArray, entry);
|
|
1131 |
LOGSMSPROT2("CSmsSegmentationStore::AddStatusReportL StatusArrayComplete %d", aComplete);
|
|
1132 |
}
|
|
1133 |
}
|
|
1134 |
}
|
|
1135 |
}
|
|
1136 |
|
|
1137 |
if (found && (smsmessage->Type()==CSmsPDU::ESmsCommand)) // look for original submit
|
|
1138 |
{
|
|
1139 |
TTime time=smsmessage->Time();
|
|
1140 |
found=EFalse;
|
|
1141 |
|
|
1142 |
RSmsSegmentationStoreRefStatusArray refStatusArray2;
|
|
1143 |
CleanupClosePushL(refStatusArray2);
|
|
1144 |
refStatusArray2.CopyL(refStatusArray);
|
|
1145 |
refStatusArray2.ResetAllStatus();
|
|
1146 |
|
|
1147 |
aComplete=EFalse;
|
|
1148 |
TInt telLen;
|
|
1149 |
for (aIndex=0; aIndex<count1; aIndex++)
|
|
1150 |
{
|
|
1151 |
TSAREntry tsareenty = Entries()[aIndex];
|
|
1152 |
TSmsSegmentationEntry& entry = static_cast<TSmsSegmentationEntry&>(tsareenty);
|
|
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 |
TSmsSegmentationStoreRefStatus& refStatus2 = refStatusArray2[i];
|
|
1180 |
if (!IsPermanentStatus(refStatus2.Status()))
|
|
1181 |
{
|
|
1182 |
refStatus2.SetStatus(refStatusArray[i].Status());
|
|
1183 |
}
|
|
1184 |
}
|
|
1185 |
|
|
1186 |
TStreamId streamid=entry.DataStreamId();
|
|
1187 |
ExternalizeEntryL(streamid,smsaddr,*smsmessage, refStatusArray2);
|
|
1188 |
PopulateEntry(entry,/*smsaddr,*/*smsmessage, refStatusArray2);
|
|
1189 |
ChangeEntryL(aIndex,entry);
|
|
1190 |
aComplete=StatusArrayComplete(refStatusArray2, entry);
|
|
1191 |
LOGSMSPROT3("CSmsSegmentationStore::StatusArrayComplete [aStatus=%d, ret=%d]", status, aComplete);
|
|
1192 |
break;
|
|
1193 |
}
|
|
1194 |
}
|
|
1195 |
|
|
1196 |
CleanupStack::PopAndDestroy(&refStatusArray2);
|
|
1197 |
}
|
|
1198 |
|
|
1199 |
CommitTransactionL();
|
|
1200 |
CleanupStack::PopAndDestroy(2); // smsmessage, refStatusArray
|
|
1201 |
|
|
1202 |
LOGSMSPROT2("CSmsSegmentationStore::AddStatusReportL Exit [found=%d]", found);
|
|
1203 |
return found;
|
|
1204 |
} // CSmsSegmentationStore::AddStatusReportL
|
|
1205 |
|
|
1206 |
|
|
1207 |
void CSmsSegmentationStore::GetMessageL(TInt aIndex,TSmsAddr& aSmsAddr,CSmsMessage& aSmsMessage, RSmsSegmentationStoreRefStatusArray& aRefStatusArray)
|
|
1208 |
{
|
|
1209 |
LOGSMSPROT2("CSmsSegmentationStore::GetMessageL [aIndex=%d]", aIndex);
|
|
1210 |
|
|
1211 |
InternalizeEntryL(Entries()[aIndex].DataStreamId(),aSmsAddr,aSmsMessage, aRefStatusArray);
|
|
1212 |
} // CSmsSegmentationStore::GetMessageL
|
|
1213 |
|
|
1214 |
|
|
1215 |
/**
|
|
1216 |
* internalize the concat refs from the permanent file store to internal memory
|
|
1217 |
*
|
|
1218 |
* @note You have to call CSARStore::OpenFileLC() before calling this function
|
|
1219 |
* and CSARStore::CloseFile() after.
|
|
1220 |
*/
|
|
1221 |
void CSmsSegmentationStore::InternalizeConcatenationReferencesL(const TStreamId& aStreamId,TInt& aReference8bit,TInt& aReference16bit)
|
|
1222 |
{
|
|
1223 |
LOGSMSPROT1("CSmsSegmentationStore::InternalizeConcatenationReferencesL Start");
|
|
1224 |
RStoreReadStream readstream;
|
|
1225 |
readstream.OpenLC(FileStore(),aStreamId);
|
|
1226 |
aReference8bit=readstream.ReadInt32L();
|
|
1227 |
aReference16bit=readstream.ReadInt32L();
|
|
1228 |
CleanupStack::PopAndDestroy();
|
|
1229 |
LOGSMSPROT1("CSmsSegmentationStore::InternalizeConcatenationReferencesL End");
|
|
1230 |
} // CSmsSegmentationStore::InternalizeConcatenationReferencesL
|
|
1231 |
|
|
1232 |
|
|
1233 |
/**
|
|
1234 |
* externalize the concat refs from the permanent file store to internal memory
|
|
1235 |
*
|
|
1236 |
* @note You have to call CSARStore::OpenFileLC() before calling this function
|
|
1237 |
* and CSARStore::CloseFile() after.
|
|
1238 |
*/
|
|
1239 |
void CSmsSegmentationStore::ExternalizeConcatenationReferencesL(TStreamId& aStreamId,TInt aReference8bit,TInt aReference16bit)
|
|
1240 |
{
|
|
1241 |
LOGSMSPROT1("CSmsSegmentationStore::ExternalizeConcatenationReferencesL Start");
|
|
1242 |
RStoreWriteStream writestream;
|
|
1243 |
if (aStreamId==KNullStreamId)
|
|
1244 |
aStreamId=writestream.CreateLC(FileStore());
|
|
1245 |
else
|
|
1246 |
writestream.ReplaceLC(FileStore(),aStreamId);
|
|
1247 |
writestream.WriteInt32L(aReference8bit);
|
|
1248 |
writestream.WriteInt32L(aReference16bit);
|
|
1249 |
writestream.CommitL();
|
|
1250 |
CleanupStack::PopAndDestroy();
|
|
1251 |
LOGSMSPROT1("CSmsSegmentationStore::ExternalizeConcatenationReferencesL End");
|
|
1252 |
} // CSmsSegmentationStore::ExternalizeConcatenationReferencesL
|
|
1253 |
|
|
1254 |
|
|
1255 |
/**
|
|
1256 |
* internalize all the entries from the permanent file store to internal memory
|
|
1257 |
*
|
|
1258 |
* @note You have to call CSARStore::OpenFileLC() before calling this function
|
|
1259 |
* and CSARStore::CloseFile() after.
|
|
1260 |
*/
|
|
1261 |
void CSmsSegmentationStore::InternalizeEntryL(const TStreamId& aStreamId,TSmsAddr& aSmsAddr,CSmsMessage& aSmsMessage, RSmsSegmentationStoreRefStatusArray& aRefStatusArray)
|
|
1262 |
{
|
|
1263 |
LOGSMSPROT1("CSmsSegmentationStore::InternalizeEntryL Start");
|
|
1264 |
|
|
1265 |
aRefStatusArray.Reset();
|
|
1266 |
|
|
1267 |
RStoreReadStream readstream;
|
|
1268 |
readstream.OpenLC(FileStore(),aStreamId);
|
|
1269 |
readstream >> aSmsAddr;
|
|
1270 |
readstream >> aSmsMessage;
|
|
1271 |
readstream >> aRefStatusArray;
|
|
1272 |
CleanupStack::PopAndDestroy(&readstream);
|
|
1273 |
|
|
1274 |
LOGSMSPROT2("CSmsSegmentationStore::InternalizeEntryL End [count=%d]", aRefStatusArray.Count());
|
|
1275 |
} // CSmsSegmentationStore::InternalizeEntryL
|
|
1276 |
|
|
1277 |
|
|
1278 |
/**
|
|
1279 |
* externalizes all the entries from the internal memory to the permanent file store
|
|
1280 |
*/
|
|
1281 |
void CSmsSegmentationStore::ExternalizeEntryL(TStreamId& aStreamId,const TSmsAddr& aSmsAddr,const CSmsMessage& aSmsMessage, const RSmsSegmentationStoreRefStatusArray& aRefStatusArray)
|
|
1282 |
{
|
|
1283 |
LOGSMSPROT1("CSmsSegmentationStore::ExternalizeEntryL Start");
|
|
1284 |
|
|
1285 |
RStoreWriteStream writestream;
|
|
1286 |
|
|
1287 |
if (aStreamId==KNullStreamId)
|
|
1288 |
aStreamId=writestream.CreateLC(FileStore());
|
|
1289 |
else
|
|
1290 |
writestream.ReplaceLC(FileStore(),aStreamId);
|
|
1291 |
|
|
1292 |
writestream << aSmsAddr;
|
|
1293 |
writestream << aSmsMessage;
|
|
1294 |
writestream << aRefStatusArray;
|
|
1295 |
writestream.CommitL();
|
|
1296 |
CleanupStack::PopAndDestroy(&writestream);
|
|
1297 |
|
|
1298 |
LOGSMSPROT2("CSmsSegmentationStore::ExternalizeEntryL End [count=%d]", aRefStatusArray.Count());
|
|
1299 |
} // CSmsSegmentationStore::ExternalizeEntryL
|
|
1300 |
|
|
1301 |
|
|
1302 |
/**
|
|
1303 |
* Populates an SMS message into SAR store entry
|
|
1304 |
*
|
|
1305 |
* @pre aSmsMessage.EncodeMessagePdusL() has been called
|
|
1306 |
*
|
|
1307 |
* @param aEntry Entry to be populated to
|
|
1308 |
* @param aSmsMessage SMS message to be populated from
|
|
1309 |
* @param aReferenceArray Array containing references
|
|
1310 |
* @param aStatusArray Array containing status
|
|
1311 |
*/
|
|
1312 |
void CSmsSegmentationStore::PopulateEntry(TSmsSegmentationEntry& aEntry,
|
|
1313 |
const CSmsMessage& aSmsMessage,
|
|
1314 |
const RSmsSegmentationStoreRefStatusArray& aRefStatusArray)
|
|
1315 |
{
|
|
1316 |
LOGSMSPROT1("CSmsSegmentationStore::PopulateEntry");
|
|
1317 |
TBool statusreportrequest=EFalse;
|
|
1318 |
if (aSmsMessage.Type()==CSmsPDU::ESmsSubmit)
|
|
1319 |
{
|
|
1320 |
aEntry.SetReference(0);
|
|
1321 |
aEntry.SetTotal(1);
|
|
1322 |
CSmsSubmit& submit=(CSmsSubmit&) aSmsMessage.SmsPDU();
|
|
1323 |
aEntry.SetValidityPeriod(submit.ValidityPeriod().Int());
|
|
1324 |
|
|
1325 |
if (aSmsMessage.Scheme() == EDefaultScheme)
|
|
1326 |
{
|
|
1327 |
statusreportrequest=((CSmsSubmit&) aSmsMessage.SmsPDU()).StatusReportRequest();
|
|
1328 |
}
|
|
1329 |
else
|
|
1330 |
{
|
|
1331 |
statusreportrequest = ETrue;
|
|
1332 |
}
|
|
1333 |
}
|
|
1334 |
else
|
|
1335 |
{
|
|
1336 |
statusreportrequest=((CSmsCommand&) aSmsMessage.SmsPDU()).StatusReportRequest();
|
|
1337 |
}
|
|
1338 |
|
|
1339 |
if (aSmsMessage.TextPresent())
|
|
1340 |
{
|
|
1341 |
if (aSmsMessage.SmsPDU().TextConcatenated())
|
|
1342 |
{
|
|
1343 |
aEntry.SetReference(aSmsMessage.SmsPDU().ConcatenatedMessageReference());
|
|
1344 |
|
|
1345 |
//
|
|
1346 |
// aSmsMessage.EncodeMessagePdusL() must have been called before this point,
|
|
1347 |
// otherwise aSmsMessage.SmsPDU().NumConcatenatedMessagePDUs() will return 1.
|
|
1348 |
//
|
|
1349 |
aEntry.SetTotal(aSmsMessage.SmsPDU().NumConcatenatedMessagePDUs());
|
|
1350 |
}
|
|
1351 |
}
|
|
1352 |
|
|
1353 |
aEntry.SetLogServerId(aSmsMessage.LogServerId());
|
|
1354 |
// Strip out spaces etc from address
|
|
1355 |
TGsmSmsTelNumber parsedaddress;
|
|
1356 |
aSmsMessage.ParsedToFromAddress(parsedaddress);
|
|
1357 |
aEntry.SetDescription2(parsedaddress.iTelNumber);
|
|
1358 |
aEntry.SetTime(aSmsMessage.Time());
|
|
1359 |
|
|
1360 |
const TInt count= aRefStatusArray.Count();
|
|
1361 |
__ASSERT_DEBUG((count>=0) && (count<=aEntry.Total()),SmspPanic(KSmspPanicBadReferenceArray));
|
|
1362 |
aEntry.SetCount(count);
|
|
1363 |
TInt reference1=0xFF;
|
|
1364 |
TInt reference2=0x00;
|
|
1365 |
TInt startref=reference1;
|
|
1366 |
TInt stopref=reference2;
|
|
1367 |
|
|
1368 |
if(count>0 && statusreportrequest)
|
|
1369 |
{
|
|
1370 |
startref=aRefStatusArray[0].Reference();
|
|
1371 |
stopref=aRefStatusArray[count-1].Reference();
|
|
1372 |
}
|
|
1373 |
|
|
1374 |
TInt delivered=0;
|
|
1375 |
TInt failed=0;
|
|
1376 |
for (TInt i=0; i<count; i++)
|
|
1377 |
{
|
|
1378 |
const TSmsSegmentationStoreRefStatus& refStatus = aRefStatusArray[i];
|
|
1379 |
|
|
1380 |
if (refStatus.Status() == TSmsStatus::ESmsShortMessageReceivedBySME)
|
|
1381 |
delivered++;
|
|
1382 |
else if (IsPermanentStatus(refStatus.Status()))
|
|
1383 |
failed++;
|
|
1384 |
}
|
|
1385 |
|
|
1386 |
//
|
|
1387 |
// AEH: Defect fix for EDNPAHN-4WADW3 'Unreliable logging'
|
|
1388 |
//
|
|
1389 |
// a little hack here to store information about whether
|
|
1390 |
// we need Status Report or not, in the TSAREntry. This
|
|
1391 |
// is because we want to retrieve it later in PurgeL.
|
|
1392 |
// An extra bit is added iData4, LSB of byte 3. See gsmustor.h
|
|
1393 |
// for more documentation.
|
|
1394 |
//
|
|
1395 |
aEntry.SetDeliveredAndFailed(delivered, failed);
|
|
1396 |
TBool have_sr = EFalse;
|
|
1397 |
|
|
1398 |
if (aSmsMessage.Scheme() == EDefaultScheme)
|
|
1399 |
{
|
|
1400 |
have_sr=((CSmsSubmit&) aSmsMessage.SmsPDU()).StatusReportRequest();
|
|
1401 |
}
|
|
1402 |
else
|
|
1403 |
{
|
|
1404 |
have_sr = ETrue;
|
|
1405 |
}
|
|
1406 |
|
|
1407 |
aEntry.SetPduTypeAndRefs(have_sr, aSmsMessage.Type(), startref, stopref);
|
|
1408 |
} // CSmsSegmentationStore::PopulateEntry
|
|
1409 |
|
|
1410 |
|
|
1411 |
/**
|
|
1412 |
* Returns ETrue if the status array is complete
|
|
1413 |
*
|
|
1414 |
* @param aStatusArray Array containing status
|
|
1415 |
* @param aEntry SAR Entry
|
|
1416 |
*/
|
|
1417 |
TBool CSmsSegmentationStore::StatusArrayComplete(const RSmsSegmentationStoreRefStatusArray& aRefStatusArray, TSAREntry& aEntry)
|
|
1418 |
{
|
|
1419 |
TInt permanent=0;
|
|
1420 |
const TInt count= aRefStatusArray.Count();
|
|
1421 |
for (TInt i=0; i<count; i++)
|
|
1422 |
{
|
|
1423 |
const TBool ret = IsPermanentStatus(aRefStatusArray[i].Status());
|
|
1424 |
LOGSMSPROT4("CSmsSegmentationStore::IsPermanentStatus [Status: %d, RetVal: %d, count=%d]", aRefStatusArray[i].Status(), ret, count);
|
|
1425 |
if (ret)
|
|
1426 |
permanent++;
|
|
1427 |
}
|
|
1428 |
return (permanent==count) && (permanent==aEntry.Total() );
|
|
1429 |
} // CSmsSegmentationStore::StatusArrayComplete
|
|
1430 |
|
|
1431 |
|
|
1432 |
/**
|
|
1433 |
* C'tor
|
|
1434 |
*/
|
|
1435 |
CSmsSegmentationStore::CSmsSegmentationStore(RFs& aFs)
|
|
1436 |
:CSARStore(aFs)
|
|
1437 |
{
|
|
1438 |
LOGSMSPROT1("CSmsSegmentationStore::CSmsSegmentationStore()");
|
|
1439 |
|
|
1440 |
} // CSmsSegmentationStore::CSmsSegmentationStore
|
|
1441 |
|
|
1442 |
|
|
1443 |
TInt CSmsSegmentationStore::TSmsSegmentationStoreRefStatus::Compare(const TSmsSegmentationStoreRefStatus& aLeft, const TSmsSegmentationStoreRefStatus& aRight)
|
|
1444 |
{
|
|
1445 |
LOGSMSPROT1("CSmsSegmentationStore::TSmsSegmentationStoreRefStatus::Compare()");
|
|
1446 |
|
|
1447 |
return aLeft.iReference - aRight.iReference;
|
|
1448 |
} // CSmsSegmentationStore::TSmsSegmentationStoreRefStatus::Compare
|
|
1449 |
|
|
1450 |
|
|
1451 |
void CSmsSegmentationStore::TSmsSegmentationStoreRefStatus::InternalizeL(RReadStream& aStream)
|
|
1452 |
{
|
|
1453 |
LOGSMSPROT1("CSmsSegmentationStore::TSmsSegmentationStoreRefStatus::InternalizeL()");
|
|
1454 |
|
|
1455 |
iReference = aStream.ReadInt32L();
|
|
1456 |
iStatus = aStream.ReadInt32L();
|
|
1457 |
} // CSmsSegmentationStore::TSmsSegmentationStoreRefStatus::InternalizeL
|
|
1458 |
|
|
1459 |
|
|
1460 |
void CSmsSegmentationStore::TSmsSegmentationStoreRefStatus::ExternalizeL(RWriteStream& aStream) const
|
|
1461 |
{
|
|
1462 |
LOGSMSPROT1("CSmsSegmentationStore::TSmsSegmentationStoreRefStatus::ExternalizeL()");
|
|
1463 |
|
|
1464 |
aStream.WriteInt32L(iReference);
|
|
1465 |
aStream.WriteInt32L(iStatus);
|
|
1466 |
} // CSmsSegmentationStore::TSmsSegmentationStoreRefStatus::ExternalizeL
|
|
1467 |
|
|
1468 |
|
|
1469 |
void CSmsSegmentationStore::RSmsSegmentationStoreRefStatusArray::InsertL(const TSmsSegmentationStoreRefStatus& aRefStatus)
|
|
1470 |
{
|
|
1471 |
LOGSMSPROT1("CSmsSegmentationStore::RSmsSegmentationStoreRefStatusArray::InsertL()");
|
|
1472 |
|
|
1473 |
TLinearOrder<TSmsSegmentationStoreRefStatus> order(TSmsSegmentationStoreRefStatus::Compare);
|
|
1474 |
User::LeaveIfError(InsertInOrderAllowRepeats(aRefStatus, order));
|
|
1475 |
} // CSmsSegmentationStore::RSmsSegmentationStoreRefStatusArray::InsertL
|
|
1476 |
|
|
1477 |
|
|
1478 |
TInt CSmsSegmentationStore::RSmsSegmentationStoreRefStatusArray::Find(const TSmsSegmentationStoreRefStatus& aRefStatus) const
|
|
1479 |
{
|
|
1480 |
LOGSMSPROT1("CSmsSegmentationStore::RSmsSegmentationStoreRefStatusArray::Find()");
|
|
1481 |
|
|
1482 |
TLinearOrder<TSmsSegmentationStoreRefStatus> order(TSmsSegmentationStoreRefStatus::Compare);
|
|
1483 |
TInt index = FindInOrder(aRefStatus, order);
|
|
1484 |
if (index != KErrNotFound)
|
|
1485 |
{
|
|
1486 |
//The function is to return the first occurence. However FindInOrder()
|
|
1487 |
//uses a binary search algorithm and does not guarantee to return the 1st item if there are duplicate items.
|
|
1488 |
//Therefore we manually check for duplicates to the left of the found item.
|
|
1489 |
while (index > 0 && (operator[](index-1).Reference() == aRefStatus.Reference()))
|
|
1490 |
{
|
|
1491 |
--index;
|
|
1492 |
}
|
|
1493 |
}
|
|
1494 |
return index;
|
|
1495 |
} // CSmsSegmentationStore::RSmsSegmentationStoreRefStatusArray::Find
|
|
1496 |
|
|
1497 |
|
|
1498 |
void CSmsSegmentationStore::RSmsSegmentationStoreRefStatusArray::CopyL(const RSmsSegmentationStoreRefStatusArray& aOther)
|
|
1499 |
{
|
|
1500 |
LOGSMSPROT1("CSmsSegmentationStore::RSmsSegmentationStoreRefStatusArray::CopyL()");
|
|
1501 |
|
|
1502 |
Reset();
|
|
1503 |
|
|
1504 |
TInt count = aOther.Count();
|
|
1505 |
while (count--)
|
|
1506 |
{
|
|
1507 |
InsertL(aOther[count]);
|
|
1508 |
}
|
|
1509 |
} // CSmsSegmentationStore::RSmsSegmentationStoreRefStatusArray::CopyL
|
|
1510 |
|
|
1511 |
|
|
1512 |
void CSmsSegmentationStore::RSmsSegmentationStoreRefStatusArray::ResetAllStatus(TInt aStatus)
|
|
1513 |
{
|
|
1514 |
LOGSMSPROT1("CSmsSegmentationStore::RSmsSegmentationStoreRefStatusArray::ResetAllStatus()");
|
|
1515 |
|
|
1516 |
TInt count = Count();
|
|
1517 |
while (count--)
|
|
1518 |
{
|
|
1519 |
(*this)[count].SetStatus(aStatus);
|
|
1520 |
}
|
|
1521 |
} // CSmsSegmentationStore::RSmsSegmentationStoreRefStatusArray::ResetAllStatus
|
|
1522 |
|
|
1523 |
|
|
1524 |
void CSmsSegmentationStore::RSmsSegmentationStoreRefStatusArray::InternalizeL(RReadStream& aStream)
|
|
1525 |
{
|
|
1526 |
LOGSMSPROT1("CSmsSegmentationStore::RSmsSegmentationStoreRefStatusArray::InternalizeL()");
|
|
1527 |
|
|
1528 |
TInt count = aStream.ReadInt32L();
|
|
1529 |
while (count--)
|
|
1530 |
{
|
|
1531 |
TSmsSegmentationStoreRefStatus refStatus;
|
|
1532 |
aStream >> refStatus;
|
|
1533 |
InsertL(refStatus); //maintain order
|
|
1534 |
}
|
|
1535 |
} // CSmsSegmentationStore::RSmsSegmentationStoreRefStatusArray::InternalizeL
|
|
1536 |
|
|
1537 |
|
|
1538 |
void CSmsSegmentationStore::RSmsSegmentationStoreRefStatusArray::ExternalizeL(RWriteStream& aStream) const
|
|
1539 |
{
|
|
1540 |
LOGSMSPROT1("CSmsSegmentationStore::RSmsSegmentationStoreRefStatusArray::ExternalizeL()");
|
|
1541 |
|
|
1542 |
const TInt count = Count();
|
|
1543 |
aStream.WriteInt32L(count);
|
|
1544 |
|
|
1545 |
for (TInt i = 0; i < count; i++)
|
|
1546 |
{
|
|
1547 |
aStream << (*this)[i];
|
|
1548 |
}
|
|
1549 |
} // CSmsSegmentationStore::RSmsSegmentationStoreRefStatusArray::ExternalizeL
|
|
1550 |
|
|
1551 |
|
|
1552 |
TBool CSmsSegmentationStore::HasEntryWithLogIdL(TLogId aLogID,TInt& aRefNo,TInt& aSent)
|
|
1553 |
{
|
|
1554 |
LOGSMSPROT1("CSmsSegmentationStore::HasEntryWithLogIdL()");
|
|
1555 |
|
|
1556 |
TInt count=Entries().Count();
|
|
1557 |
TBool found=EFalse;
|
|
1558 |
if(aLogID != KLogNullId)
|
|
1559 |
{
|
|
1560 |
TInt total;
|
|
1561 |
TInt sent;
|
|
1562 |
BeginTransactionLC();
|
|
1563 |
for (TInt i=count-1; i>=0; --i)
|
|
1564 |
{
|
|
1565 |
if (aLogID==Entries()[i].LogServerId())
|
|
1566 |
{
|
|
1567 |
const TSAREntry& entry=Entries()[i];
|
|
1568 |
total=entry.Total();
|
|
1569 |
sent=entry.Count();
|
|
1570 |
if( sent < total)
|
|
1571 |
{
|
|
1572 |
aSent=sent;
|
|
1573 |
aRefNo=entry.Reference();
|
|
1574 |
found=ETrue;
|
|
1575 |
}
|
|
1576 |
else
|
|
1577 |
{
|
|
1578 |
DeleteEntryL(i);
|
|
1579 |
LOGSMSPROT3("CSmsSegmentationStore::HasEntryWithLogIdL [Entry: %d LogId %d - deleted]", i, aLogID );
|
|
1580 |
}
|
|
1581 |
break;
|
|
1582 |
}
|
|
1583 |
}
|
|
1584 |
CommitTransactionL();
|
|
1585 |
}
|
|
1586 |
return found;
|
|
1587 |
} // CSmsSegmentationStore::HasEntryWithLogIdL
|
|
1588 |
|
|
1589 |
|
|
1590 |
/**
|
|
1591 |
* Open the sms segmentation store.
|
|
1592 |
*/
|
|
1593 |
void CSmsSegmentationStore::OpenStoreL()
|
|
1594 |
{
|
|
1595 |
LOGSMSPROT1("CSmsSegmentationStore::OpenStoreL()");
|
|
1596 |
|
|
1597 |
this->OpenL(iFullPathBuf,KSegmentationStoreUid);
|
|
1598 |
} // CSmsSegmentationStore::OpenStoreL
|