email/imap4mtm/imapsession/src/cimapstatus.cpp
changeset 0 72b543305e3a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/email/imap4mtm/imapsession/src/cimapstatus.cpp	Thu Dec 17 08:44:11 2009 +0200
@@ -0,0 +1,225 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+
+#include "cimapstatus.h"
+#include "moutputstream.h"
+#include "cimapsessionconsts.h"
+#include "cimapatomwalker.h"
+#include "cimapatom.h"
+#include "cimaputils.h"
+#include "cimapcharconv.h"
+
+// IMAP STATUS command
+_LIT8(KCommandLogin, "%d STATUS %S %S\r\n");
+
+/**
+The factory constructor. Part of two phased construction.
+*/
+CImapStatus* CImapStatus::NewL(CImapFolderInfo* aSelectedFolderData, TInt aLogId, const TDesC& aMailboxName, const TDesC8& aStatusDataItemNames, CImapFolderInfo& aFolderInfo)
+// static method first phase construction
+	{		
+	CImapStatus* self = new (ELeave) CImapStatus(aSelectedFolderData, aLogId, aFolderInfo);
+	CleanupStack::PushL(self);
+	self->ConstructL(aMailboxName, aStatusDataItemNames);
+	CleanupStack::Pop();
+	return self;
+	}
+	
+CImapStatus::CImapStatus(CImapFolderInfo* aSelectedFolderData, TInt aLogId, CImapFolderInfo& aFolderInfo) 
+	: CImapCommandEx(aSelectedFolderData, aLogId)
+	, iFolderInfo(aFolderInfo)
+	{	
+	}
+
+
+/**
+Second phase constructor.
+*/		
+void CImapStatus::ConstructL(const TDesC& aMailboxName, const TDesC8& aStatusDataItemNames)
+	{
+	// Converting the mailbox name from 16 bit to imap-UTF7 charset..
+	iMailboxName = CImapUtils::GetRef().Charconv().ConvertFromUnicodeToImapUtf7L(aMailboxName);
+	
+	iStatusDataItemNames = aStatusDataItemNames.AllocL();
+	iAtomParser = CImapAtomParser::NewL(EFalse, iLogId);
+	}
+/**
+Destructor.
+*/
+CImapStatus::~CImapStatus()
+	{
+	delete iAtomParser;
+	delete iMailboxName;
+	delete iStatusDataItemNames;
+	}
+
+/** 
+Formats and sends the IMAP STATUS command.
+@param aTagId Command sequence id which will be sent along with the IMAP command.
+@param aStream A wrapper for the outbound stream of a connected socket, using which 
+the command will be send to the server
+*/
+void CImapStatus::SendMessageL(TInt aTagId, MOutputStream& aStream)
+	{
+	iTagId = aTagId;
+
+	TInt buffLength = KCommandLogin().Length();	
+	buffLength += iMailboxName->Length();
+	buffLength += iStatusDataItemNames->Length();
+	
+	__ASSERT_DEBUG(iOutputBuffer==NULL, TImapServerPanic::ImapPanic(TImapServerPanic::ECommandOutputBufferNotNull));
+	iOutputBuffer = HBufC8::NewL(buffLength + TagLength(aTagId));	
+	iOutputBuffer->Des().Format(KCommandLogin, aTagId, iMailboxName, iStatusDataItemNames);	
+	
+	//send the command to the server
+	aStream.SendDataReq(*iOutputBuffer);
+	}
+
+/**
+Checks whether this is a STATUS response.
+If it is, then it starts buiding an atom tree.  
+If the tree is completed then the data is parsed straight away.  Otherwise, more data is requested.
+If the atom tree is completed by this line, then tree is parsed to decode the response.
+@return ENotRecognised if this is not a STATUS response
+		EResponseIncomplete if this is a STATUS resposne, but more data is required.
+		ECompleteUntagged if this is a STATUS response that has been fully parsed.
+*/
+CImapCommand::TParseBlockResult CImapStatus::ParseUntaggedResponseL()
+	{
+	TParseBlockResult result = ENotRecognised;
+	
+	TPtrC8 response = GetNextPart();
+	if(response.CompareF(KImapTxtStatus) == 0)
+		{
+		TPtrC8 remainingData = Remainder();
+   		TBool wantMoreData = iAtomParser->ProcessLineL(remainingData);
+   		if (wantMoreData)
+   			{
+   			result = EResponseIncomplete;
+   			}
+   		else
+   			{
+   			ParseStatusResponseL();
+   			result = ECompleteUntagged;
+   			}
+		}
+	
+	return result;
+	}
+
+/**
+Adds the block of literal data to the atom tree.
+And waits for the following line.
+*/
+void CImapStatus::ParseLiteralBlockL()
+	{
+	iAtomParser->ProcessLiteralBlockL(iUnparsedData);
+	}
+
+/**
+Adds the line of data to the atom tree.
+If the atom tree is completed by this line, then tree is parsed to decode the response.
+@return Whether more data (i.e. another literal block) is expected.
+*/
+TBool CImapStatus::ParseLineFollowingLiteralL()
+	{
+	TBool wantMoreData = iAtomParser->ProcessLineL(iUnparsedData);
+	
+	if(!wantMoreData)
+		{
+		ParseStatusResponseL();
+		}
+		
+	return wantMoreData;
+	}
+
+void CImapStatus::ParseStatusResponseL()
+ 	{
+ 	// Traverse the atom tree
+ 	CImapAtomWalker* atomWalker = CImapAtomWalker::NewL(iLogId);
+ 	CleanupStack::PushL(atomWalker);
+ 	
+ 	atomWalker->SetRootL(iAtomParser->RootAtom());
+ 	
+ 	// Move to the first item of the atom tree...
+ 	atomWalker->WalkDownL();
+ 	
+ 	// Skip over the mailbox name
+ 	atomWalker->WalkAcrossL(ETrue);
+ 	
+  	// We should now be at the opening bracket for the status-att-list
+  	atomWalker->WalkDownL();
+  	
+  	// status-att-list = status-att SP number *(SP status-att SP number)
+ 	do
+ 		{
+ 		// Get the status-att
+ 		TPtrC8 statusAtt = atomWalker->CurrentDes(EFalse);
+ 		
+ 		// Get the number value corrosponding to a status data item.
+ 		atomWalker->WalkAcrossL(ETrue);
+ 		TPtrC8 value = atomWalker->CurrentDes(EFalse);
+ 		
+ 		ParseStatusAttributeL(statusAtt, value);
+ 		} 
+  		while (atomWalker->WalkAcrossL(EFalse));
+ 		 	
+ 	CleanupStack::PopAndDestroy(atomWalker);
+ 	}
+
+/**
+Parses the status response.
+@param aAttribute.The status data item.(MESSAGES/UIDNEXT/RECENT/UIDVALIDITY/UNSEEN)
+@param aValue. The value corrosponding a particular status data item.
+*/
+void CImapStatus::ParseStatusAttributeL(const TDesC8& aAttribute, const TDesC8& aValue )
+// Parse response of the form (MESSAGES 899 UIDNEXT 8874)...
+	{
+	TPtrC8 nextPart(aAttribute);
+	TLex8 desToInt(aValue);
+	TInt tempVal = 0;
+	
+	if(desToInt.Val(tempVal) != KErrNone)
+		{
+		CorruptDataL();
+		}
+	
+	// From RFC3501 section 9
+	//	
+	// status-att = "MESSAGES" / "RECENT" / "UIDNEXT" / "UIDVALIDITY" / "UNSEEN"
+		
+	if(nextPart.CompareF(KImapTxtMessages) == 0)
+		{					
+		iFolderInfo.SetMessages(tempVal);
+		}
+	else if(nextPart.CompareF(KImapTxtRecent) == 0)
+		{
+		iFolderInfo.SetRecent(tempVal);					
+		}
+	else if(nextPart.CompareF(KImapTxtUidNext) == 0)
+		{
+		iFolderInfo.SetUidNext(tempVal);					
+		}
+	else if(nextPart.CompareF(KImapTxtUidValidity) == 0)
+		{					
+		iFolderInfo.SetUidValidity(tempVal);
+		}
+	else if(nextPart.CompareF(KImapTxtUnseen) == 0)
+		{					
+		iFolderInfo.SetUnseen(tempVal);
+		}			
+	}
+