email/imap4mtm/imapsession/inc/cimapcommand.h
changeset 0 72b543305e3a
equal deleted inserted replaced
-1:000000000000 0:72b543305e3a
       
     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__