|
1 // Copyright (c) 2006-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 // |
|
15 |
|
16 #ifndef __CIMAPCOMMAND_H__ |
|
17 #define __CIMAPCOMMAND_H__ |
|
18 |
|
19 #include <e32std.h> |
|
20 #include <mentact.h> |
|
21 #include <msvstd.h> |
|
22 |
|
23 // Typedefs |
|
24 typedef RArray<TPtrC8> RDesParts; |
|
25 |
|
26 // Forward Declaration |
|
27 class MOutputStream; |
|
28 class CImapFolderInfo; |
|
29 |
|
30 /** |
|
31 Abstract base class for sending IMAP commands and receiving and parsing IMAP responses. |
|
32 Each implementation of this class represents a single IMAP command together with its expected responses. |
|
33 Each implementation can use this base class to handle unsolicited responses. |
|
34 |
|
35 @internalTechnology |
|
36 @prototype |
|
37 */ |
|
38 class CImapCommand : public CBase |
|
39 { |
|
40 public: |
|
41 /** |
|
42 Identifies the tagged response code that was received for this message. |
|
43 */ |
|
44 enum TResponseCode |
|
45 { |
|
46 /** |
|
47 No tagged response has been received yet. |
|
48 The command is not yet complete. |
|
49 */ |
|
50 EImapResponseNone, |
|
51 /** |
|
52 A tagged OK response has been received. |
|
53 The command has completed successfully. |
|
54 Note that receipt of an UNTAGGED OK response should not cause iResponse code to be updated to this value. |
|
55 */ |
|
56 EImapResponseOk, |
|
57 /** |
|
58 A tagged NO response has been received. |
|
59 The server has completed the command by refusing to run it. |
|
60 */ |
|
61 EImapResponseNo, |
|
62 /** |
|
63 A tagged BAD response has been received. |
|
64 The server has completed the command because it did not understand the command and was not able to run it. |
|
65 */ |
|
66 EImapResponseBad |
|
67 }; |
|
68 |
|
69 /** |
|
70 The result of parsing a block of data. |
|
71 This indicates how the block was parsed, and whether further data is expected. |
|
72 */ |
|
73 enum TParseBlockResult |
|
74 { |
|
75 /** |
|
76 The block was not recognised, so we need to do generic handling. |
|
77 */ |
|
78 ENotRecognised, |
|
79 /** |
|
80 The block was parsed, but more data (e.g. a literal block) is needed for this response. |
|
81 */ |
|
82 EResponseIncomplete, |
|
83 /** |
|
84 The block was parsed and the whole of an untagged response has now been received. |
|
85 No more data is expected for this response. |
|
86 but the command is still expecting to receive a tagged response. |
|
87 */ |
|
88 ECompleteUntagged, |
|
89 /** |
|
90 The block was parsed and the whole of a tagged response has now been received. |
|
91 No more data is expected for this command. |
|
92 The result code can be accessed using CImapCommand::Result(); |
|
93 */ |
|
94 ECompleteTagged, |
|
95 }; |
|
96 |
|
97 /** |
|
98 Indicates what kind of data is expected next (if any) and how to handle it. |
|
99 */ |
|
100 enum TParseState |
|
101 { |
|
102 /** |
|
103 CImapCommand is waiting for the beginning of a new tagged or untagged response. |
|
104 A line of data is expected, starting with a tag, * or + character. |
|
105 */ |
|
106 EWaitStartResponse, |
|
107 /** |
|
108 The subclass is in the middle of parsing a response. |
|
109 It is expecting a block of literal data. |
|
110 */ |
|
111 EWaitLiteralParse, |
|
112 /** |
|
113 The subclass is in the middle of parsing a response. |
|
114 It is expecting a line of data. |
|
115 */ |
|
116 EWaitLineParse, |
|
117 /** |
|
118 CImapCommand is in the middle of discarding a response, |
|
119 so that it can get to the start of the next response. |
|
120 It is expecting a block of literal data. |
|
121 */ |
|
122 EWaitLiteralIngore, |
|
123 /** |
|
124 CImapCommand is in the middle of discarding a response, |
|
125 so that it can get to the start of the next response. |
|
126 It is expecting a line of data. |
|
127 */ |
|
128 EWaitLineIgnore, |
|
129 /** |
|
130 The final tagged response for this command has been received. |
|
131 No more data is expected. |
|
132 */ |
|
133 ECommandComplete |
|
134 }; |
|
135 |
|
136 enum { KMinPartsForIsLineTagged = 2 }; |
|
137 |
|
138 enum TTagType |
|
139 { |
|
140 ETagged, |
|
141 EUntagged, |
|
142 EContinuation |
|
143 }; |
|
144 |
|
145 ~CImapCommand(); |
|
146 |
|
147 /** |
|
148 Sends the command represented by this object as a message to the IMAP server. |
|
149 @param aTagId Used to generate the IMAP tag that identifies the message. |
|
150 @param aStream The output stream on which the message will be sent. |
|
151 The provided output stream should already be set up and ready to use. |
|
152 */ |
|
153 virtual void SendMessageL(TInt aTagId, MOutputStream& aStream)=0; |
|
154 |
|
155 virtual void SendDataCnfL(); |
|
156 |
|
157 TParseState ParseBlockL(const TDesC8& aData); |
|
158 |
|
159 virtual void WaitingForMoreDataL(); |
|
160 |
|
161 virtual void Cancel(); |
|
162 TBool Flushing() const; |
|
163 virtual TBool CanCompleteFlushNow() const; |
|
164 |
|
165 TResponseCode ResponseCode() const; |
|
166 TInt LiteralBytesExpected() const; |
|
167 |
|
168 static void CorruptDataL(TInt aLogId); |
|
169 void CorruptDataL(); |
|
170 |
|
171 static HBufC8* EncodeMailboxNameForSendL(const TDesC16& aMailboxName); |
|
172 static TBool CheckForPrintableAtomSpecial(const TDesC8& aString, TInt& aCountQuotedSpecials); |
|
173 |
|
174 // Utility methods for parsing |
|
175 static TInt TagLength(TInt aTagId); |
|
176 static void GetDelimitedPartsL(TChar aDelimiter, const TDesC8& aData, RDesParts& aOutDelimitedPartsList, TInt aMaxParts = 0); |
|
177 |
|
178 TInt GetTagId() ; |
|
179 |
|
180 protected: |
|
181 CImapCommand(CImapFolderInfo* aSelectedFolderData, TInt aLogId); |
|
182 |
|
183 /** |
|
184 This is called after whole line or literal block has been received. |
|
185 An implementation of this method should parse the supplied data and store the results |
|
186 in the subclass's data members. |
|
187 @param aData The data to be parsed. This will either be a single line or single block of literal data. |
|
188 The first call to ParseMessageL() will always receive a line. |
|
189 Subsequent calls will receive whatever was requested in the return value of the previous call to this method. |
|
190 @return This indicates how the block was parsed, and whether further data is expected. |
|
191 */ |
|
192 virtual TParseBlockResult DoParseBlockL(const TDesC8& aData) = 0; |
|
193 |
|
194 virtual TInt NumberOfTaggedResponsesExpected() const; |
|
195 void ParseStartResponseFlushL(const TDesC8& aData); |
|
196 |
|
197 TTagType GetTagTypeL(TInt& aTagId); |
|
198 TPtrC8 GetNextPart(); |
|
199 TPtrC8 PeekNextPart(); |
|
200 TPtrC8 Remainder(); |
|
201 TPtrC8 GetResponseTextCodeL(); |
|
202 TResponseCode GetResponseStateCode(); |
|
203 |
|
204 void EnterFlushingState(); |
|
205 |
|
206 // Access Methods |
|
207 void SetParseState(TParseState aParseState); |
|
208 TParseState ParseState() const; |
|
209 |
|
210 void SetMessageFlagsChanged(); |
|
211 |
|
212 private: |
|
213 void ParseLineL(const TDesC8& aLine); |
|
214 void ParseLiteralL(const TDesC8& aLiteralBlock); |
|
215 |
|
216 TParseBlockResult ParseUnhandledBlockL(const TDesC8& aLine); |
|
217 TInt PeekLiteralRequest(const TDesC8& aLine); |
|
218 |
|
219 protected: |
|
220 /** |
|
221 Stores the tag id supplied by SendMessage() |
|
222 Use iTagId to validate that tagged responses have the correct tag id. |
|
223 */ |
|
224 TInt iTagId; |
|
225 /** |
|
226 Holds the data to be sent on the output stream to the remote server. |
|
227 */ |
|
228 HBufC8* iOutputBuffer; |
|
229 |
|
230 TPtrC8 iUnparsedData; |
|
231 /** |
|
232 Pointer to the folder data object for the currently selected mailbox. |
|
233 The pointer can be NULL if no mailbox is currently selected. |
|
234 The pointer is NOT owned by this object. |
|
235 */ |
|
236 CImapFolderInfo* iSelectedFolderData; |
|
237 |
|
238 /** |
|
239 Stores the tag completion code of the response message |
|
240 */ |
|
241 TResponseCode iResponseCode; |
|
242 |
|
243 /** |
|
244 Most commands are complete only when the tagged response is received. |
|
245 However there are some scenarios where receipt of any response is sufficient |
|
246 to complete the command - in which case this flag should be set to ETrue. |
|
247 */ |
|
248 TBool iCompleteOnAnyResponse; |
|
249 |
|
250 /** |
|
251 If a literal block is expected in the next call to ParseBlockL(), then |
|
252 the number of bytes expected is recorded here. |
|
253 0 indicates that a literal block is not expected. |
|
254 */ |
|
255 TInt iLiteralBytesExpected; |
|
256 #if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT) |
|
257 /** |
|
258 If message body is downloaded using FETCH BINARY. |
|
259 The number of bytes received for previous fetch is recorded here. |
|
260 This valued is used to make sure that there are no extra body fetch command are issued |
|
261 */ |
|
262 TInt iPreviousLiteralBytesReceived; |
|
263 #endif |
|
264 |
|
265 /** |
|
266 The log id of the session that owns this command object. |
|
267 */ |
|
268 TInt iLogId; |
|
269 |
|
270 private: |
|
271 /** |
|
272 Indicates what kind of data is expected next (if any) and how to handle it. |
|
273 */ |
|
274 TParseState iParseState; |
|
275 |
|
276 /** |
|
277 When true, all incoming data is ignored until the last tagged response. |
|
278 */ |
|
279 TBool iFlushing; |
|
280 |
|
281 /** |
|
282 Counts the number of tagged responses that need to be flushed. |
|
283 Usually, this is just the one, but for pipelined commands many requests |
|
284 are made at a time, so many tagged responses need to be flushed after a cancel. |
|
285 */ |
|
286 TInt iTaggedResponsesToFlush; |
|
287 }; |
|
288 |
|
289 /** |
|
290 Provides a migration path that replaces DoParseBlockL() with separate |
|
291 subclass methods for different kinds of incoming data. |
|
292 */ |
|
293 class CImapCommandEx : public CImapCommand |
|
294 { |
|
295 protected: |
|
296 CImapCommandEx(CImapFolderInfo* aSelectedFolderData, TInt aLogId); |
|
297 |
|
298 void BaseParseTaggedResponseL(TInt aTagId); |
|
299 |
|
300 /** |
|
301 Called when a tagged response is received. |
|
302 iUnparsed data contains the incoming line, excluding the tag. |
|
303 @param aTagId The value of the incoming tag. |
|
304 @return Whether this tags response completes the command. |
|
305 Unless multiple commands are being sent (e.g. in fetch body), this should return ETrue. |
|
306 */ |
|
307 virtual TBool ParseTaggedResponseL(TInt aTagId); |
|
308 virtual void ParseContinuationResponseL(); |
|
309 |
|
310 virtual TParseBlockResult ParseUntaggedResponseL(); |
|
311 virtual void ParseLiteralBlockL(); |
|
312 virtual TBool ParseLineFollowingLiteralL(); |
|
313 |
|
314 private: |
|
315 TParseBlockResult ParseStartResponseL(); |
|
316 |
|
317 // Implements CImapCommand |
|
318 TParseBlockResult DoParseBlockL(const TDesC8& aData); |
|
319 }; |
|
320 |
|
321 #endif // __CIMAPCOMMAND_H__ |