80
|
1 |
// Copyright (c) 2006-2010 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 |
//
|
|
15 |
|
|
16 |
#include "cimapfetchbody.h"
|
|
17 |
#include "moutputstream.h"
|
|
18 |
#include "cimapsession.h"
|
|
19 |
#include "cimapsessionconsts.h"
|
|
20 |
#include "cimapsettings.h"
|
|
21 |
#include "cimapmimeheaderfieldsparser.h"
|
|
22 |
#include "cimapmimeheaderfields.h"
|
|
23 |
#include "cfetchbodyinfo.h"
|
|
24 |
#include "cimapfetchbodyresponse.h"
|
|
25 |
#include "cimaplogger.h"
|
|
26 |
#if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)
|
|
27 |
#include "cimapcapabilityinfo.h"
|
|
28 |
#endif
|
|
29 |
|
|
30 |
const TInt KMaxTagIdSize = 8;
|
|
31 |
const TInt KDefaultMaxFetchSize = 20480;
|
|
32 |
const TInt KOutstandingRequests = 2;
|
|
33 |
const TInt KOutstandingBinaryFetchRequests = 1;
|
|
34 |
|
|
35 |
_LIT8(KCommandFetch, "%S UID FETCH %d (BODY[%S]<%d.%d>)\r\n");
|
|
36 |
_LIT8(KCommandFetchWithMime, "%S UID FETCH %d (BODY[%S]<%d.%d> BODY[%S.MIME])\r\n");
|
|
37 |
_LIT8(KCommandFetchPeek, "%S UID FETCH %d (BODY.PEEK[%S]<%d.%d>)\r\n");
|
|
38 |
_LIT8(KCommandFetchPeekWithMime, "%S UID FETCH %d (BODY.PEEK[%S]<%d.%d> BODY.PEEK[%S.MIME])\r\n");
|
|
39 |
#if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)
|
|
40 |
_LIT8(KCommandFetchBinary, "%S UID FETCH %d (BINARY[%S]<%d.%d>)\r\n");
|
|
41 |
_LIT8(KCommandFetchBinaryPeek, "%S UID FETCH %d (BINARY.PEEK[%S]<%d.%d>)\r\n");
|
|
42 |
#endif
|
|
43 |
_LIT8(KStartSection,"[");
|
|
44 |
_LIT8(KEndSection,"]");
|
|
45 |
_LIT8(KStartLiteral,"{");
|
|
46 |
_LIT8(KEndLiteral,"}");
|
|
47 |
_LIT8(KStartOrigin,"<");
|
|
48 |
_LIT8(KEndOrigin,">");
|
|
49 |
|
|
50 |
CImapFetchBody* CImapFetchBody::NewL(CImapFolderInfo* aSelectedFolderData, TInt aLogId, TUint aMessageUid,TBool aPeek, CFetchBodyInfo& aFetchBodyInfo, CImapFetchBodyResponse& aFetchBodyResponse, CImapSettings& aImapSettings, CImapMailStore& aImapMailStore, CImapSession& aParent)
|
|
51 |
{
|
|
52 |
CImapFetchBody* self = new (ELeave) CImapFetchBody(aSelectedFolderData, aLogId, aMessageUid, aPeek, aFetchBodyInfo, aFetchBodyResponse, aImapSettings, aImapMailStore, aParent);
|
|
53 |
CleanupStack::PushL(self);
|
|
54 |
self->ConstructL();
|
|
55 |
CleanupStack::Pop(self);
|
|
56 |
return self;
|
|
57 |
}
|
|
58 |
|
|
59 |
CImapFetchBody::CImapFetchBody(CImapFolderInfo* aSelectedFolderData, TInt aLogId, TUint aMessageUid, TBool aPeek, CFetchBodyInfo& aFetchBodyInfo, CImapFetchBodyResponse& aFetchBodyResponse, CImapSettings& aImapSettings, CImapMailStore& aImapMailStore, CImapSession& aParent)
|
|
60 |
: CImapCommand(aSelectedFolderData, aLogId),
|
|
61 |
iMessageUid(aMessageUid),
|
|
62 |
iPeek(aPeek),
|
|
63 |
iSizeToFetch(aFetchBodyInfo.SizeToFetch()),
|
|
64 |
iImapSettings(aImapSettings),
|
|
65 |
iFetchBodyInfo(aFetchBodyInfo),
|
|
66 |
iImapMailStore(aImapMailStore),
|
|
67 |
iParent(aParent),
|
|
68 |
iFetchBodyResponse(aFetchBodyResponse),
|
|
69 |
iSendFetch(ETrue)
|
|
70 |
{
|
|
71 |
iPartialFetch=iFetchBodyInfo.PartialDownload();
|
|
72 |
}
|
|
73 |
|
|
74 |
CImapFetchBody::~CImapFetchBody()
|
|
75 |
{
|
|
76 |
// ensure that iImapMailStore will not call StoreOperationComplete()
|
|
77 |
// on this object now that it is being destoyed.
|
|
78 |
|
|
79 |
delete iHeaderFieldsParser;
|
|
80 |
delete iBuf;
|
|
81 |
iTagIds.Reset();
|
|
82 |
}
|
|
83 |
|
|
84 |
/**
|
|
85 |
Overrides CImapCommand::Cancel() by cancelling any outstanding mail store operation.
|
|
86 |
*/
|
|
87 |
void CImapFetchBody::Cancel()
|
|
88 |
{
|
|
89 |
__LOG_TEXT(iLogId, "CImapFetchBody::Cancel()"); // Overrides CImapCommand::Cancel()
|
|
90 |
|
|
91 |
iImapMailStore.CancelRequest(*this);
|
|
92 |
CImapCommand::Cancel();
|
|
93 |
}
|
|
94 |
|
|
95 |
void CImapFetchBody::StoreOperationComplete(TMsvId /*aId*/,TInt aErrorCode)
|
|
96 |
{
|
|
97 |
__LOG_FORMAT((iLogId, "CImapFetchBody::StoreOperationComplete aErrorCode = %d",aErrorCode));
|
|
98 |
iStoreComplete = ETrue;
|
|
99 |
|
|
100 |
// Complete early if there is an error
|
|
101 |
if (aErrorCode != KErrNone)
|
|
102 |
{
|
|
103 |
__LOG_TEXT(iLogId, "CImapFetchBody::StoreOperationComplete - ERROR: Completing Early");
|
|
104 |
iParent.FetchBodyOperationComplete(aErrorCode);
|
|
105 |
}
|
|
106 |
// Otherwise complete only if the last tagged OK has been received.
|
|
107 |
else if(ParseState() == ECommandComplete)
|
|
108 |
{
|
|
109 |
// Call the session to let it know we are done
|
|
110 |
__ASSERT_DEBUG(iRequestCount == iTotalRequests && iOutstandingRequests == 0, TImapServerPanic::ImapPanic(TImapServerPanic::EStoreOperationCompleteWithPendingRequest) );
|
|
111 |
iParent.FetchBodyOperationComplete(aErrorCode);
|
|
112 |
}
|
|
113 |
}
|
|
114 |
|
|
115 |
TBool CImapFetchBody::IsStoreOperationComplete()
|
|
116 |
{
|
|
117 |
return iStoreComplete;
|
|
118 |
}
|
|
119 |
|
|
120 |
void CImapFetchBody::ConstructL()
|
|
121 |
{
|
|
122 |
// obtain
|
|
123 |
iImapSettings.GetTransportBufferSizesL(iMaxFetchSize, iMaxOutstandingRequests);
|
|
124 |
|
|
125 |
#if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)
|
|
126 |
// check for BINARY capability
|
|
127 |
const CImapCapabilityInfo& capabilityInfo = iParent.CapabilityInfo();
|
|
128 |
TBool binaryCapExist = capabilityInfo.QueryFlag(CImapCapabilityInfo::EBinaryCap);
|
|
129 |
#endif
|
|
130 |
|
|
131 |
// if either parameter is undefined, resort to using the defaults.
|
|
132 |
if(iMaxFetchSize==0)
|
|
133 |
{
|
|
134 |
iMaxFetchSize=KDefaultMaxFetchSize;
|
|
135 |
}
|
|
136 |
|
|
137 |
if(iMaxOutstandingRequests==0)
|
|
138 |
{
|
|
139 |
iMaxOutstandingRequests=KOutstandingRequests;
|
|
140 |
}
|
|
141 |
|
|
142 |
//calculate the number of chunks that will be needed
|
|
143 |
iTotalRequests=TotalRequestsRequired(iSizeToFetch);
|
|
144 |
|
|
145 |
__LOG_FORMAT((iLogId, "CImapFetchBody::CImapFetchBody iTotalRequests = %d",iTotalRequests));
|
|
146 |
|
|
147 |
|
|
148 |
if(iFetchBodyInfo.IsText())
|
|
149 |
{
|
|
150 |
// check if chunk storage mechanism is enabled.
|
|
151 |
if(iImapSettings.StorePlainText())
|
|
152 |
{
|
|
153 |
#if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)
|
|
154 |
if(binaryCapExist && iFetchBodyInfo.IsText())
|
|
155 |
{
|
|
156 |
iImapMailStore.InitialiseStorePlainBodyTextL(iTotalRequests,iImapSettings,iFetchBodyInfo,iLogId,*this,*this, ETrue);
|
|
157 |
}
|
|
158 |
else
|
|
159 |
#endif
|
|
160 |
{
|
|
161 |
iImapMailStore.InitialiseStorePlainBodyTextL(iTotalRequests,iImapSettings,iFetchBodyInfo,iLogId,*this,*this);
|
|
162 |
}
|
|
163 |
}
|
|
164 |
else
|
|
165 |
{
|
|
166 |
if(iImapSettings.Store8BitData())
|
|
167 |
{
|
|
168 |
#if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)
|
|
169 |
if(binaryCapExist && iFetchBodyInfo.IsText())
|
|
170 |
{
|
|
171 |
iImapMailStore.InitialiseStoreBody8L(iTotalRequests,iImapSettings,iFetchBodyInfo,iLogId,*this,ETrue);
|
|
172 |
}
|
|
173 |
else
|
|
174 |
#endif
|
|
175 |
{
|
|
176 |
iImapMailStore.InitialiseStoreBody8L(iTotalRequests,iImapSettings,iFetchBodyInfo,iLogId,*this);
|
|
177 |
}
|
|
178 |
}
|
|
179 |
else
|
|
180 |
{
|
|
181 |
#if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)
|
|
182 |
if(binaryCapExist && iFetchBodyInfo.IsText())
|
|
183 |
{
|
|
184 |
iImapMailStore.InitialiseStoreBody16L(iTotalRequests,iImapSettings,iFetchBodyInfo,iLogId,*this,ETrue);
|
|
185 |
}
|
|
186 |
else
|
|
187 |
#endif
|
|
188 |
{
|
|
189 |
iImapMailStore.InitialiseStoreBody16L(iTotalRequests,iImapSettings,iFetchBodyInfo,iLogId,*this);
|
|
190 |
}
|
|
191 |
}
|
|
192 |
}
|
|
193 |
}
|
|
194 |
else
|
|
195 |
{
|
|
196 |
iImapMailStore.InitialiseStoreAttachmentL(iTotalRequests,iImapSettings,iFetchBodyInfo,iLogId,*this);
|
|
197 |
}
|
|
198 |
}
|
|
199 |
|
|
200 |
TInt CImapFetchBody::TotalRequestsRequired(TInt aSize)
|
|
201 |
{
|
|
202 |
|
|
203 |
TInt chunkNumber = aSize / iMaxFetchSize;
|
|
204 |
|
|
205 |
if( (aSize % iMaxFetchSize)>0)
|
|
206 |
{
|
|
207 |
//add a chunk for the last bit of data
|
|
208 |
++chunkNumber;
|
|
209 |
}
|
|
210 |
|
|
211 |
return chunkNumber;
|
|
212 |
}
|
|
213 |
|
|
214 |
|
|
215 |
TInt CImapFetchBody::CalculateChunk(TInt aPos)
|
|
216 |
{
|
|
217 |
return aPos / iMaxFetchSize;
|
|
218 |
}
|
|
219 |
|
|
220 |
/**
|
|
221 |
Formats and sends the IMAP UID FETCH command.
|
|
222 |
@param aTagId Command sequence id which will be send along with the IMAP command.
|
|
223 |
@param aStream A wrapper for the outbound stream of a connected socket, using which
|
|
224 |
the command will be send to the server
|
|
225 |
*/
|
|
226 |
void CImapFetchBody::SendMessageL(TInt aTagId, MOutputStream& aStream)
|
|
227 |
{
|
|
228 |
iOutStream=&aStream;
|
|
229 |
|
|
230 |
#if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)
|
|
231 |
// check for BINARY capability
|
|
232 |
const CImapCapabilityInfo& capabilityInfo = iParent.CapabilityInfo();
|
|
233 |
TBool binaryCapExist = capabilityInfo.QueryFlag(CImapCapabilityInfo::EBinaryCap);
|
|
234 |
if(binaryCapExist && iFetchBodyInfo.IsText())
|
|
235 |
{
|
|
236 |
// if message body part is downloaded using FETCH BINARY, then there should be only one
|
|
237 |
// Outstanding Request
|
|
238 |
iOutstandingRequests = KOutstandingBinaryFetchRequests;
|
|
239 |
}
|
|
240 |
else
|
|
241 |
#endif
|
|
242 |
{
|
|
243 |
//iOutstandingRequests is the smaller of iMaxOutstandingRequests and the total chunk count
|
|
244 |
iOutstandingRequests = iTotalRequests>iMaxOutstandingRequests ? iMaxOutstandingRequests : iTotalRequests;
|
|
245 |
}
|
|
246 |
// SendMessageL will increment the tag ID as the first thing it does, so we
|
|
247 |
// should set it to 1 lower than the fist tag we want to send.
|
|
248 |
iTagId = aTagId - 1;
|
|
249 |
|
|
250 |
SendMessageL();
|
|
251 |
}
|
|
252 |
|
|
253 |
void CImapFetchBody::SendMessageL()
|
|
254 |
{
|
|
255 |
// Set the tag ID to use in the next message
|
|
256 |
++iTagId;
|
|
257 |
|
|
258 |
_LIT8(KTagFormatId, "%d");
|
|
259 |
TBuf8<KMaxTagIdSize>tagIdBuffer;
|
|
260 |
tagIdBuffer.Format(KTagFormatId,iTagId);
|
|
261 |
|
|
262 |
iTagIds.InsertInOrder(iTagId);
|
|
263 |
|
|
264 |
|
|
265 |
//create fetch command based on settings
|
|
266 |
//the offset from which we want to fetch data
|
|
267 |
TInt offset = iRequestCount*iMaxFetchSize;
|
|
268 |
|
|
269 |
// calclulate the size to fetch in this request,
|
|
270 |
// default to max fetch size.
|
|
271 |
TUint sizeToFetch = iMaxFetchSize;
|
|
272 |
|
|
273 |
if(iPartialFetch)
|
|
274 |
{
|
|
275 |
if ((iRequestCount == (iTotalRequests-1)) && (iSizeToFetch<iMaxFetchSize))
|
|
276 |
sizeToFetch = iSizeToFetch;
|
|
277 |
}
|
|
278 |
|
|
279 |
TInt bufLength = 0;
|
|
280 |
bufLength += iFetchBodyInfo.RelativePath()->Length();
|
|
281 |
bufLength += TagLength(offset);
|
|
282 |
bufLength += TagLength(sizeToFetch);
|
|
283 |
bufLength += tagIdBuffer.Length();
|
|
284 |
|
|
285 |
#if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)
|
|
286 |
// check for BINARY capability
|
|
287 |
// Issue binary fetch for plain/text part only
|
|
288 |
const CImapCapabilityInfo& capabilityInfo = iParent.CapabilityInfo();
|
|
289 |
TBool binaryCapExist = capabilityInfo.QueryFlag(CImapCapabilityInfo::EBinaryCap);
|
|
290 |
#endif
|
|
291 |
if (iRequestCount == 0 && !iFetchBodyInfo.iEmbed)
|
|
292 |
{
|
|
293 |
bufLength += iFetchBodyInfo.RelativePath()->Length();
|
|
294 |
|
|
295 |
if (iPeek)
|
|
296 |
{
|
|
297 |
#if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)
|
|
298 |
if(binaryCapExist && iFetchBodyInfo.IsText())
|
|
299 |
{
|
|
300 |
bufLength += KCommandFetchBinaryPeek().Length();
|
|
301 |
}
|
|
302 |
else
|
|
303 |
#endif
|
|
304 |
{
|
|
305 |
bufLength += KCommandFetchPeekWithMime().Length();
|
|
306 |
}
|
|
307 |
}
|
|
308 |
else
|
|
309 |
{
|
|
310 |
#if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)
|
|
311 |
if(binaryCapExist && iFetchBodyInfo.IsText())
|
|
312 |
{
|
|
313 |
bufLength += KCommandFetchBinary().Length();
|
|
314 |
}
|
|
315 |
else
|
|
316 |
#endif
|
|
317 |
{
|
|
318 |
bufLength += KCommandFetchWithMime().Length();
|
|
319 |
}
|
|
320 |
}
|
|
321 |
}
|
|
322 |
else
|
|
323 |
{
|
|
324 |
if(iPeek)
|
|
325 |
{
|
|
326 |
#if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)
|
|
327 |
if(binaryCapExist && iFetchBodyInfo.IsText())
|
|
328 |
{
|
|
329 |
bufLength += KCommandFetchBinaryPeek().Length();
|
|
330 |
}
|
|
331 |
else
|
|
332 |
#endif
|
|
333 |
{
|
|
334 |
bufLength += KCommandFetchPeek().Length();
|
|
335 |
}
|
|
336 |
}
|
|
337 |
else
|
|
338 |
{
|
|
339 |
#if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)
|
|
340 |
if(binaryCapExist && iFetchBodyInfo.IsText())
|
|
341 |
{
|
|
342 |
bufLength += KCommandFetchBinary().Length();
|
|
343 |
}
|
|
344 |
else
|
|
345 |
#endif
|
|
346 |
{
|
|
347 |
bufLength += KCommandFetch().Length();
|
|
348 |
}
|
|
349 |
}
|
|
350 |
}
|
|
351 |
|
|
352 |
//now create the command
|
|
353 |
HBufC8* buffer = HBufC8::NewL(bufLength);
|
|
354 |
delete iOutputBuffer;
|
|
355 |
iOutputBuffer=buffer;
|
|
356 |
|
|
357 |
if (iRequestCount == 0 && !iFetchBodyInfo.iEmbed)
|
|
358 |
{
|
|
359 |
if(iPeek)
|
|
360 |
{
|
|
361 |
#if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)
|
|
362 |
if(binaryCapExist && iFetchBodyInfo.IsText())
|
|
363 |
{
|
|
364 |
iOutputBuffer->Des().Format(KCommandFetchBinaryPeek, &tagIdBuffer, iMessageUid, iFetchBodyInfo.RelativePath(), offset, sizeToFetch, iFetchBodyInfo.RelativePath());
|
|
365 |
}
|
|
366 |
else
|
|
367 |
#endif
|
|
368 |
{
|
|
369 |
iOutputBuffer->Des().Format(KCommandFetchPeekWithMime, &tagIdBuffer, iMessageUid, iFetchBodyInfo.RelativePath(), offset, sizeToFetch, iFetchBodyInfo.RelativePath());
|
|
370 |
}
|
|
371 |
}
|
|
372 |
else
|
|
373 |
{
|
|
374 |
#if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)
|
|
375 |
if(binaryCapExist && iFetchBodyInfo.IsText())
|
|
376 |
{
|
|
377 |
iOutputBuffer->Des().Format(KCommandFetchBinary, &tagIdBuffer, iMessageUid, iFetchBodyInfo.RelativePath(), offset, sizeToFetch, iFetchBodyInfo.RelativePath());
|
|
378 |
}
|
|
379 |
else
|
|
380 |
#endif
|
|
381 |
{
|
|
382 |
iOutputBuffer->Des().Format(KCommandFetchWithMime, &tagIdBuffer, iMessageUid, iFetchBodyInfo.RelativePath(), offset, sizeToFetch, iFetchBodyInfo.RelativePath());
|
|
383 |
}
|
|
384 |
}
|
|
385 |
}
|
|
386 |
else
|
|
387 |
{
|
|
388 |
iFetchBodyInfo.iEmbed = EFalse;
|
|
389 |
if(iPeek)
|
|
390 |
{
|
|
391 |
#if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)
|
|
392 |
if(binaryCapExist && iFetchBodyInfo.IsText())
|
|
393 |
{
|
|
394 |
iOutputBuffer->Des().Format(KCommandFetchBinaryPeek, &tagIdBuffer, iMessageUid, iFetchBodyInfo.RelativePath(), offset, sizeToFetch);
|
|
395 |
}
|
|
396 |
else
|
|
397 |
#endif
|
|
398 |
{
|
|
399 |
iOutputBuffer->Des().Format(KCommandFetchPeek, &tagIdBuffer, iMessageUid, iFetchBodyInfo.RelativePath(), offset, sizeToFetch);
|
|
400 |
}
|
|
401 |
}
|
|
402 |
else
|
|
403 |
{
|
|
404 |
#if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)
|
|
405 |
if(binaryCapExist && iFetchBodyInfo.IsText())
|
|
406 |
{
|
|
407 |
iOutputBuffer->Des().Format(KCommandFetchBinary, &tagIdBuffer, iMessageUid, iFetchBodyInfo.RelativePath(), offset, iMaxFetchSize);
|
|
408 |
}
|
|
409 |
else
|
|
410 |
#endif
|
|
411 |
{
|
|
412 |
iOutputBuffer->Des().Format(KCommandFetch, &tagIdBuffer, iMessageUid, iFetchBodyInfo.RelativePath(), offset, iMaxFetchSize);
|
|
413 |
}
|
|
414 |
}
|
|
415 |
}
|
|
416 |
|
|
417 |
delete iBuf;
|
|
418 |
iBuf = NULL;
|
|
419 |
iReceivedMimeHeaders = EFalse;
|
|
420 |
|
|
421 |
//send the command to the server
|
|
422 |
iOutStream->SendDataReq(*iOutputBuffer);
|
|
423 |
++iRequestCount;
|
|
424 |
}
|
|
425 |
|
|
426 |
/**
|
|
427 |
@param aData Will contain a single line of response from the server for LOGIN command without \r\n.
|
|
428 |
@return will be any one of this
|
|
429 |
1) If the next expected chunk is a literal block, ParseMessageL() will return the size of the block it expects.
|
|
430 |
2) If the next expected chunk is a line, ParseMessageL() will return 0, and Result() will return EImapResponseNone.
|
|
431 |
3) If no further data is expected (e.g. the OK or error tag has been received) then ParseMessageL() will return 0,
|
|
432 |
and Result() will return one of EImapResponseOk, EImapResponseNo or EImapResponseBad.
|
|
433 |
*/
|
|
434 |
CImapCommand::TParseBlockResult CImapFetchBody::DoParseBlockL(const TDesC8& aData)
|
|
435 |
{
|
|
436 |
|
|
437 |
CImapCommand::TParseBlockResult resultCode(ECompleteUntagged);
|
|
438 |
|
|
439 |
switch (iState)
|
|
440 |
{
|
|
441 |
case EStateDataItemLine:
|
|
442 |
{
|
|
443 |
// We are the beginning of a new response, so we can't have found any UID data items yet.
|
|
444 |
// So we need to reset the flag here.
|
|
445 |
iUidDataItemFoundInResponse = EFalse;
|
|
446 |
resultCode = ProcessStartL();
|
|
447 |
|
|
448 |
ASSERT(iState == EStateDataItemLine);
|
|
449 |
|
|
450 |
// If we get EResponseIncomplete then allow the current EStateDataItemLine state to
|
|
451 |
// drop through to ProcessDataItems()
|
|
452 |
// otherwise, EStateComplete will take us straight to the return.
|
|
453 |
if (resultCode != EResponseIncomplete)
|
|
454 |
{
|
|
455 |
iState = EStateComplete;
|
|
456 |
}
|
|
457 |
}
|
|
458 |
break;
|
|
459 |
case EStateBodyLiteral:
|
|
460 |
{
|
|
461 |
// Bump progress: bytesdone is *encoded* length, so we just use the encoded length
|
|
462 |
iFetchBodyInfo.IncrementBytesFetched(aData.Length());
|
|
463 |
|
|
464 |
__ASSERT_DEBUG(aData.Length() == iLiteralSize, TImapServerPanic::ImapPanic(TImapServerPanic::ETParseBlockResultInvalidLiteralSize) );
|
|
465 |
|
|
466 |
ProcessBodyLiteralL(aData);
|
|
467 |
resultCode = EResponseIncomplete; // always expect more data after a literal
|
|
468 |
}
|
|
469 |
break;
|
|
470 |
case EStateMime:
|
|
471 |
{
|
|
472 |
ProcessRestOfMimeL(iUnparsedData);
|
|
473 |
resultCode = EResponseIncomplete;
|
|
474 |
}
|
|
475 |
break;
|
|
476 |
case EStateFetchNextDataItemLine:
|
|
477 |
{
|
|
478 |
// Fetch is over. Get ready to process next data item.
|
|
479 |
iUnparsedData.Set(aData);
|
|
480 |
GetAndStoreNextPart();
|
|
481 |
|
|
482 |
iState = EStateDataItemLine;
|
|
483 |
}
|
|
484 |
break;
|
|
485 |
default:
|
|
486 |
{
|
|
487 |
// unexpected state
|
|
488 |
ASSERT(EFalse);
|
|
489 |
}
|
|
490 |
}
|
|
491 |
|
|
492 |
// The ProcessXxxL() methods above can change the state.
|
|
493 |
// Now we need to check if there are data items to process...
|
|
494 |
if (iState == EStateDataItemLine)
|
|
495 |
{
|
|
496 |
resultCode = ProcessDataItemsL();
|
|
497 |
}
|
|
498 |
else if (iState == EStateComplete)
|
|
499 |
{
|
|
500 |
//if we still have more requests to issue send the next one now
|
|
501 |
|
|
502 |
if(resultCode == ECompleteTagged)
|
|
503 |
{
|
|
504 |
if (iResponseCode == EImapResponseOk)
|
|
505 |
{
|
|
506 |
++iResponseCount;
|
|
507 |
// If we received some MIME headers, we may need to store them
|
|
508 |
// with the CAF framework
|
|
509 |
if ((iReceivedMimeHeaders) && (iFetchBodyInfo.Caf() != NULL) && (iFetchBodyInfo.Caf()->Registered()))
|
|
510 |
{
|
|
511 |
WriteMimeHeadersToCafL();
|
|
512 |
}
|
|
513 |
|
|
514 |
// Store the body data if we received it
|
|
515 |
if (iBuf != NULL)
|
|
516 |
{
|
|
517 |
TInt extraFetchRequestCount = 0;
|
|
518 |
#if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)
|
|
519 |
// check for BINARY capability
|
|
520 |
const CImapCapabilityInfo& capabilityInfo = iParent.CapabilityInfo();
|
|
521 |
TBool binaryCapExist = capabilityInfo.QueryFlag(CImapCapabilityInfo::EBinaryCap);
|
|
522 |
if(binaryCapExist && iFetchBodyInfo.IsText() && iPreviousLiteralBytesReceived < KDefaultMaxFetchSize)
|
|
523 |
{
|
|
524 |
extraFetchRequestCount = iTotalRequests - iRequestCount;
|
|
525 |
// iTotalRequests, iRequestCount and iResponseCount should be same at this stage
|
|
526 |
// iResponseCount will be same as iRequestCount
|
|
527 |
iTotalRequests=iRequestCount;
|
|
528 |
//reset iPreviousLiteralBytesReceived to zero
|
|
529 |
iPreviousLiteralBytesReceived=0;
|
|
530 |
}
|
|
531 |
#endif
|
|
532 |
|
|
533 |
StoreBodyDataL(extraFetchRequestCount);
|
|
534 |
|
|
535 |
if (iRequestCount<iTotalRequests)
|
|
536 |
{
|
|
537 |
// if there are outstanding requests already then just add this request to the count
|
|
538 |
++iOutstandingRequests;
|
|
539 |
|
|
540 |
// If iOutstandingRequests is greater than one, this means a write operation is in progress
|
|
541 |
// and the message will be sent when SendDataCnf() is called.
|
|
542 |
if (iSendFetch && (iOutstandingRequests == 1))
|
|
543 |
{
|
|
544 |
SendMessageL();
|
|
545 |
}
|
|
546 |
|
|
547 |
resultCode=ECompleteUntagged;
|
|
548 |
iResponseCode=EImapResponseNone;
|
|
549 |
}
|
|
550 |
// if there are remaining requests yet to be received then tell the session were not finished.
|
|
551 |
else if(iResponseCount<iTotalRequests)
|
|
552 |
{
|
|
553 |
resultCode = ECompleteUntagged;
|
|
554 |
iResponseCode=EImapResponseNone;
|
|
555 |
}
|
|
556 |
}
|
|
557 |
// if there is no body part to be stored but server sent a OK responsethen set
|
|
558 |
// iStoreComplete to ETrue and Cancel the Request.If more than one FETCH was sent
|
|
559 |
// then Flush the state so that all incoming server data is discarded.
|
|
560 |
else
|
|
561 |
{
|
|
562 |
iStoreComplete = ETrue;
|
|
563 |
iImapMailStore.CancelRequest(*this);
|
|
564 |
|
|
565 |
// Check the tag id
|
|
566 |
if(iTagIds.Count())
|
|
567 |
{
|
|
568 |
EnterFlushingState();
|
|
569 |
resultCode = ECompleteUntagged;
|
|
570 |
iResponseCode = EImapResponseNone;
|
|
571 |
}
|
|
572 |
}
|
|
573 |
}
|
|
574 |
else
|
|
575 |
{
|
|
576 |
iImapMailStore.CancelRequest(*this);
|
|
577 |
}
|
|
578 |
}
|
|
579 |
|
|
580 |
// this response is complete, so the next data (if any) will be a data item line,
|
|
581 |
iState = EStateDataItemLine;
|
|
582 |
}
|
|
583 |
|
|
584 |
// For complete untagged responses, check whether the UID data item was received.
|
|
585 |
// If it was, then this was a genuine response to the UID FETCH command.
|
|
586 |
// If it was not received, then this was an unsolicited server event, and the data should be discarded.
|
|
587 |
if (resultCode == ECompleteUntagged)
|
|
588 |
{
|
|
589 |
if (iUidDataItemFoundInResponse)
|
|
590 |
{
|
|
591 |
// Genuine UID FETCH response - copy UID and FLAG info into the response object
|
|
592 |
iFetchBodyResponse.SetMessageFlagInfo(iMessageFlagInfo);
|
|
593 |
|
|
594 |
// Note: iUidDataItemFoundInResponse is NOT reset here
|
|
595 |
// Instead iUidDataItemFoundInResponse is set to EFalse just prior to calling ProcessStartL() - i.e. at the start of a new response.
|
|
596 |
}
|
|
597 |
else
|
|
598 |
{
|
|
599 |
// Record that an unsolicited FETCH was received - so that a sync will be triggered after this command.
|
|
600 |
__LOG_TEXT(iLogId, "CImapFetchBody::DoParseBlockL() - Found unsolicited FETCH FLAGS");
|
|
601 |
SetMessageFlagsChanged();
|
|
602 |
}
|
|
603 |
}
|
|
604 |
|
|
605 |
return resultCode;
|
|
606 |
}
|
|
607 |
|
|
608 |
/**
|
|
609 |
Returns the number of tagged responses that are currently expected.
|
|
610 |
Because CImapFetchBody uses pipelining - with many simulataneous request running at once
|
|
611 |
it will be expect a tagged response for each request that is still running on the server.
|
|
612 |
@return the number of tagged responses that are currently expected.
|
|
613 |
*/
|
|
614 |
TInt CImapFetchBody::NumberOfTaggedResponsesExpected() const
|
|
615 |
{
|
|
616 |
return iTagIds.Count();
|
|
617 |
}
|
|
618 |
|
|
619 |
CImapCommand::TParseBlockResult CImapFetchBody::ProcessStartL()
|
|
620 |
{
|
|
621 |
TParseBlockResult result = ENotRecognised;
|
|
622 |
|
|
623 |
TInt tagId = 0;
|
|
624 |
TTagType tagged = GetTagTypeL(tagId);
|
|
625 |
switch(tagged)
|
|
626 |
{
|
|
627 |
case ETagged:
|
|
628 |
{
|
|
629 |
// Check the tag id
|
|
630 |
TInt tagPos=iTagIds.FindInOrder(tagId);
|
|
631 |
if(tagPos!=KErrNotFound)
|
|
632 |
{
|
|
633 |
iTagIds.Remove(tagPos);
|
|
634 |
}
|
|
635 |
else
|
|
636 |
{
|
|
637 |
//Unexpected Tagid
|
|
638 |
CorruptDataL();
|
|
639 |
}
|
|
640 |
|
|
641 |
// Fetch and check the response code
|
|
642 |
iResponseCode = GetResponseStateCode();
|
|
643 |
if (iResponseCode == EImapResponseNone)
|
|
644 |
{
|
|
645 |
// Was expecting one of OK/NO/BAD, but didn't get it. This is a parse error.
|
|
646 |
CorruptDataL();
|
|
647 |
}
|
|
648 |
|
|
649 |
result =ECompleteTagged;
|
|
650 |
}
|
|
651 |
break;
|
|
652 |
|
|
653 |
case EUntagged:
|
|
654 |
{
|
|
655 |
// Is this a FETCH response?
|
|
656 |
// Check for Sequence Number followed by "FETCH"
|
|
657 |
|
|
658 |
TPtrC8 part1 = GetNextPart(); // returns KNullDesC8 if there is no part available
|
|
659 |
TPtrC8 part2 = GetNextPart(); // returns KNullDesC8 if there is no part available
|
|
660 |
|
|
661 |
// Is part1 a Sequence Number?
|
|
662 |
TInt sequenceNumber = 0;
|
|
663 |
TLex8 lex(part1);
|
|
664 |
if (lex.Val(sequenceNumber) == KErrNone)
|
|
665 |
{
|
|
666 |
// part1 is a Sequence Number. Now check part2 - is it "FETCH"?
|
|
667 |
|
|
668 |
if(part2.CompareF(KImapTxtFetch) == 0)
|
|
669 |
{
|
|
670 |
|
|
671 |
if (GetAndStoreNextPart())
|
|
672 |
{
|
|
673 |
if (iCurrentPart[0] == '(')
|
|
674 |
{
|
|
675 |
iCurrentPart.Set(iCurrentPart.Mid(1));
|
|
676 |
}
|
|
677 |
else
|
|
678 |
{
|
|
679 |
// was expecting a bracket, got something else
|
|
680 |
CorruptDataL();
|
|
681 |
}
|
|
682 |
}
|
|
683 |
else
|
|
684 |
{
|
|
685 |
// was expecting a bracket, got nothing
|
|
686 |
CorruptDataL();
|
|
687 |
}
|
|
688 |
|
|
689 |
result = EResponseIncomplete;
|
|
690 |
}
|
|
691 |
}
|
|
692 |
}
|
|
693 |
break;
|
|
694 |
case EContinuation:
|
|
695 |
default:
|
|
696 |
{
|
|
697 |
CorruptDataL();
|
|
698 |
}
|
|
699 |
break;
|
|
700 |
}
|
|
701 |
|
|
702 |
// result will be ENotRecognised if tagged not found or untagged FETCH not found.
|
|
703 |
return result;
|
|
704 |
}
|
|
705 |
|
|
706 |
CImapCommand::TParseBlockResult CImapFetchBody::ProcessDataItemsL()
|
|
707 |
{
|
|
708 |
CImapCommand::TParseBlockResult resultCode = EResponseIncomplete;
|
|
709 |
|
|
710 |
TBool foundPart = ETrue;
|
|
711 |
while (iState == EStateDataItemLine && foundPart)
|
|
712 |
{
|
|
713 |
if (iCurrentPart.CompareF(KImapTxtUid) == 0)
|
|
714 |
{
|
|
715 |
ProcessUidL();
|
|
716 |
}
|
|
717 |
else if (iCurrentPart.CompareF(KImapTxtFlags) == 0)
|
|
718 |
{
|
|
719 |
ProcessFlagsL();
|
|
720 |
}
|
|
721 |
|
|
722 |
// check if the part starts 'BODY['
|
|
723 |
else if (iCurrentPart.Find(KImapTxtBody)==0)
|
|
724 |
{
|
|
725 |
//is it the body or the body.mime?
|
|
726 |
if(iCurrentPart.Find(KImapTxtMime) != KErrNotFound )
|
|
727 |
{
|
|
728 |
ProcessStartOfMimeL();
|
|
729 |
}
|
|
730 |
else
|
|
731 |
{
|
|
732 |
ProcessBodyL();
|
|
733 |
}
|
|
734 |
}
|
|
735 |
#if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)
|
|
736 |
// check if the part starts 'BINARY['
|
|
737 |
else if (iCurrentPart.Find(KImapTxtBinary)==0)
|
|
738 |
{
|
|
739 |
// no mime to process for fetch binary
|
|
740 |
ProcessBodyL();
|
|
741 |
}
|
|
742 |
#endif
|
|
743 |
|
|
744 |
// Only fetch the next part if we're still searching for data items.
|
|
745 |
if (iState == EStateDataItemLine)
|
|
746 |
{
|
|
747 |
foundPart = GetAndStoreNextPart();
|
|
748 |
}
|
|
749 |
}
|
|
750 |
|
|
751 |
if (!foundPart && iState == EStateDataItemLine)
|
|
752 |
{
|
|
753 |
if(iBuf && iUnexpectedFormat)
|
|
754 |
{
|
|
755 |
iState = EStateFetchNextDataItemLine;
|
|
756 |
iUnexpectedFormat = EFalse;
|
|
757 |
}
|
|
758 |
resultCode = ECompleteUntagged;
|
|
759 |
}
|
|
760 |
iUnexpectedFormat = EFalse;
|
|
761 |
return resultCode;
|
|
762 |
}
|
|
763 |
|
|
764 |
|
|
765 |
void CImapFetchBody::ProcessStartOfMimeL()
|
|
766 |
{
|
|
767 |
//look for the body section that is being returned
|
|
768 |
TInt secStart=iCurrentPart.Find(KStartSection);
|
|
769 |
TInt secEnd=iCurrentPart.Find(KImapTxtMime);
|
|
770 |
|
|
771 |
if(secStart==KErrNotFound || secEnd==KErrNotFound)
|
|
772 |
{
|
|
773 |
CorruptDataL();
|
|
774 |
}
|
|
775 |
|
|
776 |
TPtrC8 section = iCurrentPart.Mid(secStart + 1, secEnd - secStart - 1);
|
|
777 |
|
|
778 |
//check the section is what we asked for
|
|
779 |
if(section.CompareF(*iFetchBodyInfo.RelativePath()) != 0)
|
|
780 |
{
|
|
781 |
CorruptDataL();
|
|
782 |
}
|
|
783 |
|
|
784 |
// Peek the next part. We don't want to consume it as we may need
|
|
785 |
// to pass it to the header fields parser.
|
|
786 |
iCurrentPart.Set(PeekNextPart());
|
|
787 |
if (iCurrentPart.Length() == 0)
|
|
788 |
{
|
|
789 |
CorruptDataL();
|
|
790 |
}
|
|
791 |
|
|
792 |
iReceivedMimeHeaders = ETrue;
|
|
793 |
|
|
794 |
// If the last character is ')' then we're at the last data item in the list.
|
|
795 |
// Consume the character so that the rest of the data item can be interpreted.
|
|
796 |
if (iCurrentPart.Right(1).CompareF(KImapTxtCloseBracket) == 0)
|
|
797 |
{
|
|
798 |
iCurrentPart.Set(iCurrentPart.Left(iCurrentPart.Length() - 1));
|
|
799 |
}
|
|
800 |
|
|
801 |
// Check if data part is NIL or "" for empty string
|
|
802 |
if (iCurrentPart.CompareF(KImapTxtNil) == 0 || iCurrentPart.CompareF(KImapTxtEmptyStringAsDoubleQuotePair) == 0)
|
|
803 |
{
|
|
804 |
// Consume the NIL part
|
|
805 |
GetAndStoreNextPart();
|
|
806 |
|
|
807 |
// Create empty MIME header fields
|
|
808 |
CImapMimeHeaderFields* fields = CImapMimeHeaderFields::NewL();
|
|
809 |
iFetchBodyResponse.SetHeaderFields(fields);
|
|
810 |
|
|
811 |
// May be more data items coming up
|
|
812 |
iState = EStateDataItemLine;
|
|
813 |
}
|
|
814 |
else
|
|
815 |
{
|
|
816 |
// Pass the rest of the line to the header fields parser
|
|
817 |
iHeaderFieldsParser = CImapMimeHeaderFieldsParser::NewL(iFetchBodyResponse, iLogId);
|
|
818 |
iState = EStateMime;
|
|
819 |
ProcessRestOfMimeL(iUnparsedData);
|
|
820 |
}
|
|
821 |
}
|
|
822 |
|
|
823 |
void CImapFetchBody::ProcessRestOfMimeL(const TDesC8& aData)
|
|
824 |
{
|
|
825 |
TBool wantsMore = iHeaderFieldsParser->ProcessBlockL(aData);
|
|
826 |
|
|
827 |
if (!wantsMore)
|
|
828 |
{
|
|
829 |
delete iHeaderFieldsParser;
|
|
830 |
iHeaderFieldsParser = NULL;
|
|
831 |
iState = EStateFetchNextDataItemLine;
|
|
832 |
}
|
|
833 |
}
|
|
834 |
|
|
835 |
void CImapFetchBody::ProcessBodyL()
|
|
836 |
#if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)
|
|
837 |
{//BODY[1]<0> or BINARY[1]<0>
|
|
838 |
#else
|
|
839 |
{//BODY[1]<0>
|
|
840 |
#endif
|
|
841 |
//look for the body section that is being returned
|
|
842 |
TInt secStart=iCurrentPart.Find(KStartSection);
|
|
843 |
TInt secEnd=iCurrentPart.Find(KEndSection);
|
|
844 |
|
|
845 |
#if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)
|
|
846 |
const CImapCapabilityInfo& capabilityInfo = iParent.CapabilityInfo();
|
|
847 |
if(capabilityInfo.QueryFlag(CImapCapabilityInfo::EBinaryCap) && iFetchBodyInfo.IsText())
|
|
848 |
{
|
|
849 |
if(secStart!=KImapTxtBinary().Length() - 1 || secEnd <= secStart + 1)
|
|
850 |
{
|
|
851 |
CorruptDataL();
|
|
852 |
}
|
|
853 |
}
|
|
854 |
else
|
|
855 |
#endif
|
|
856 |
{
|
|
857 |
if(secStart!=KImapTxtBody().Length() - 1 || secEnd <= secStart + 1)
|
|
858 |
{
|
|
859 |
CorruptDataL();
|
|
860 |
}
|
|
861 |
}
|
|
862 |
|
|
863 |
TPtrC8 section=iCurrentPart.Mid(secStart+1,secEnd-secStart-1);
|
|
864 |
|
|
865 |
//check the section is what we asked for
|
|
866 |
if(section.CompareF(*iFetchBodyInfo.RelativePath()) != 0)
|
|
867 |
{
|
|
868 |
CorruptDataL();
|
|
869 |
}
|
|
870 |
|
|
871 |
//get the origin octet of the form <origin>, this may not exist, if its not
|
|
872 |
//then the origin is at the start of the data
|
|
873 |
TInt originStart=iCurrentPart.Find(KStartOrigin);
|
|
874 |
if(originStart==KErrNotFound)
|
|
875 |
{
|
|
876 |
//the origin octet will be 0, the data will go in the first chunk
|
|
877 |
iCurrentChunk=0;
|
|
878 |
}
|
|
879 |
else
|
|
880 |
{
|
|
881 |
if(originStart != secEnd + 1)
|
|
882 |
{
|
|
883 |
CorruptDataL();
|
|
884 |
}
|
|
885 |
TInt originEnd=iCurrentPart.Find(KEndOrigin);
|
|
886 |
if(originEnd==KErrNotFound || originEnd != iCurrentPart.Length() - 1 )
|
|
887 |
{
|
|
888 |
CorruptDataL();
|
|
889 |
}
|
|
890 |
if(originEnd <= originStart + 1)
|
|
891 |
{
|
|
892 |
CorruptDataL();
|
|
893 |
}
|
|
894 |
|
|
895 |
TPtrC8 originPtr=iCurrentPart.Mid(originStart+1,originEnd-originStart-1);
|
|
896 |
TLex8 originToInt(originPtr);
|
|
897 |
|
|
898 |
TInt origin=0;
|
|
899 |
TInt err = originToInt.Val(origin);
|
|
900 |
if (err != KErrNone)
|
|
901 |
{
|
|
902 |
// Was expecting originPtr to be a number
|
|
903 |
CorruptDataL();
|
|
904 |
}
|
|
905 |
|
|
906 |
//set the chunk number
|
|
907 |
//if the origin was blank ie. <> then this is set to 0, the start of the data
|
|
908 |
iCurrentChunk = CalculateChunk(origin);
|
|
909 |
}
|
|
910 |
|
|
911 |
//now look for the size of the literal
|
|
912 |
TBool foundPart = GetAndStoreNextPart();
|
|
913 |
if(!foundPart)
|
|
914 |
{
|
|
915 |
CorruptDataL();
|
|
916 |
}
|
|
917 |
|
|
918 |
TInt litStart=iCurrentPart.Find(KStartLiteral);
|
|
919 |
TInt litEnd=iCurrentPart.Find(KEndLiteral);
|
|
920 |
|
|
921 |
if(litStart==KErrNotFound && litEnd==KErrNotFound)
|
|
922 |
{
|
|
923 |
// This may be the data item
|
|
924 |
ProcessBodyLiteralL(iCurrentPart);
|
|
925 |
iState = EStateDataItemLine;
|
|
926 |
iUnexpectedFormat = ETrue;
|
|
927 |
}
|
|
928 |
else
|
|
929 |
{
|
|
930 |
if(litStart==KErrNotFound || litEnd==KErrNotFound)
|
|
931 |
{
|
|
932 |
CorruptDataL();
|
|
933 |
}
|
|
934 |
|
|
935 |
if(litEnd <= litStart + 1)
|
|
936 |
{
|
|
937 |
CorruptDataL();
|
|
938 |
}
|
|
939 |
|
|
940 |
TPtrC8 litPtr=iCurrentPart.Mid(litStart+1,litEnd-litStart-1);
|
|
941 |
TLex8 litSizeToInt(litPtr);
|
|
942 |
|
|
943 |
TInt err = litSizeToInt.Val(iLiteralSize);
|
|
944 |
if (err != KErrNone)
|
|
945 |
{
|
|
946 |
// Was expecting litPtr to be a number
|
|
947 |
CorruptDataL();
|
|
948 |
}
|
|
949 |
|
|
950 |
if(GetAndStoreNextPart())
|
|
951 |
{
|
|
952 |
ProcessBodyLiteralL(iCurrentPart);
|
|
953 |
iState = EStateDataItemLine;
|
|
954 |
iUnexpectedFormat = ETrue;
|
|
955 |
}
|
|
956 |
else
|
|
957 |
{
|
|
958 |
//now wait for the litereral
|
|
959 |
iState = EStateBodyLiteral;
|
|
960 |
}
|
|
961 |
}
|
|
962 |
}
|
|
963 |
|
|
964 |
void CImapFetchBody::ProcessBodyLiteralL(const TDesC8& aData)
|
|
965 |
{
|
|
966 |
delete iBuf;
|
|
967 |
iBuf = NULL;
|
|
968 |
iBuf = aData.AllocL();
|
|
969 |
|
|
970 |
//now wait for the line that always follows a literal
|
|
971 |
iState = EStateFetchNextDataItemLine;
|
|
972 |
}
|
|
973 |
|
|
974 |
/**
|
|
975 |
Move to the next part
|
|
976 |
@return whether a part was found
|
|
977 |
*/
|
|
978 |
TBool CImapFetchBody::GetAndStoreNextPart()
|
|
979 |
{
|
|
980 |
iCurrentPart.Set(GetNextPart());
|
|
981 |
return (iCurrentPart.Length() > 0) ? ETrue : EFalse;
|
|
982 |
}
|
|
983 |
|
|
984 |
void CImapFetchBody::ProcessFlagsL()
|
|
985 |
{
|
|
986 |
iUnparsedData.Set(iMessageFlagInfo.ParseFlagsL(iUnparsedData));
|
|
987 |
}
|
|
988 |
|
|
989 |
void CImapFetchBody::ProcessUidL()
|
|
990 |
{
|
|
991 |
if (GetAndStoreNextPart())
|
|
992 |
{
|
|
993 |
TInt err = iMessageFlagInfo.SetMessageUid(iCurrentPart);
|
|
994 |
if (err == KErrNone)
|
|
995 |
{
|
|
996 |
iUidDataItemFoundInResponse = ETrue;
|
|
997 |
}
|
|
998 |
else
|
|
999 |
{
|
|
1000 |
// expected iCurrentPart to be a number representing a UID.
|
|
1001 |
// but we did not get a number.
|
|
1002 |
CorruptDataL();
|
|
1003 |
}
|
|
1004 |
}
|
|
1005 |
}
|
|
1006 |
|
|
1007 |
void CImapFetchBody::WriteMimeHeadersToCafL()
|
|
1008 |
{
|
|
1009 |
CImapMimeHeaderFields* fields = iFetchBodyResponse.HeaderFields();
|
|
1010 |
if (fields != NULL)
|
|
1011 |
{
|
|
1012 |
TPtrC8 name;
|
|
1013 |
TPtrC8 value;
|
|
1014 |
|
|
1015 |
fields->RestartGetNextField();
|
|
1016 |
while (fields->GetNextField(name, value))
|
|
1017 |
{
|
|
1018 |
__LOG_FORMAT((iLogId, "Add CAF metadata: %S %S", &name, &value));
|
|
1019 |
iFetchBodyInfo.Caf()->AddToMetaDataL(name, value);
|
|
1020 |
}
|
|
1021 |
}
|
|
1022 |
}
|
|
1023 |
|
|
1024 |
void CImapFetchBody::StoreBodyDataL(TBool aExtraFetchRequestCount)
|
|
1025 |
{
|
|
1026 |
// We are going to pass the buffer to the mail store, so set our
|
|
1027 |
// buffer to NULL so that we don't try to delete it if the store
|
|
1028 |
// routine leaves.
|
|
1029 |
HBufC8* buf(iBuf);
|
|
1030 |
iBuf = NULL;
|
|
1031 |
|
|
1032 |
if(iFetchBodyInfo.IsText())
|
|
1033 |
{
|
|
1034 |
if(iImapSettings.StorePlainText())
|
|
1035 |
{
|
|
1036 |
iSendFetch = iImapMailStore.StorePlainBodyTextL(buf,iFetchBodyInfo.PartId(),iCurrentChunk,aExtraFetchRequestCount);
|
|
1037 |
}
|
|
1038 |
else
|
|
1039 |
{
|
|
1040 |
if(iImapSettings.Store8BitData())
|
|
1041 |
{
|
|
1042 |
iImapMailStore.StoreBodyChunk8L(buf,iFetchBodyInfo.PartId(),iCurrentChunk,aExtraFetchRequestCount);
|
|
1043 |
}
|
|
1044 |
else
|
|
1045 |
{
|
|
1046 |
iImapMailStore.StoreBodyChunk16L(buf,iFetchBodyInfo.PartId(),iCurrentChunk,aExtraFetchRequestCount);
|
|
1047 |
}
|
|
1048 |
}
|
|
1049 |
}
|
|
1050 |
else //attachments
|
|
1051 |
{
|
|
1052 |
iImapMailStore.StoreAttachmentChunkL(buf,iFetchBodyInfo.PartId(),iCurrentChunk);
|
|
1053 |
}
|
|
1054 |
}
|
|
1055 |
|
|
1056 |
/**
|
|
1057 |
If pipelining is enabled then this method will send the next fetch request to the server after confirmation of the last request having been sent.
|
|
1058 |
@return void
|
|
1059 |
*/
|
|
1060 |
|
|
1061 |
|
|
1062 |
void CImapFetchBody::SendDataCnfL()
|
|
1063 |
{
|
|
1064 |
ASSERT(iOutstandingRequests>0);
|
|
1065 |
--iOutstandingRequests;
|
|
1066 |
//if we want more requests outstanding then send the next one now
|
|
1067 |
if(iOutstandingRequests>0 && iSendFetch)
|
|
1068 |
{
|
|
1069 |
SendMessageL();
|
|
1070 |
}
|
|
1071 |
}
|
|
1072 |
/**
|
|
1073 |
This method will enable the FETCH command to be send to the server if it was
|
|
1074 |
disabled by CImapMailStore due to reciept of out-of-order chunks.
|
|
1075 |
@return void
|
|
1076 |
*/
|
|
1077 |
void CImapFetchBody::EnableSendFetch()
|
|
1078 |
{
|
|
1079 |
iSendFetch = ETrue;
|
|
1080 |
}
|