--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/applayerprotocols/ftpengine/ftpprot/PASVANS.CPP Tue Feb 02 01:09:52 2010 +0200
@@ -0,0 +1,207 @@
+// Copyright (c) 1998-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:
+// PASV command answer parser
+// Author: Philippe Gabriel
+// RFC 959 defines the syntax for answer to the PASV command
+// We must parse an IP+Port number (decimal, big endian)
+// (ip1,ip2,ip3,ip4,ip5,port1,port2)
+// We parse these regular expressions using an FSM
+// Use:
+// TFtpPASVAnswerParser::Reset
+// to Reset the parser before we begin to parse a new answer
+// TFtpPASVAnswerParser::Parse
+// to parse an answer
+// returns:
+// TRUE: we parsed an answer (answer might be correct or inccorect)
+// FALSE: An answer has not been completely parsed yet
+// TFtpPASVAnswerParser::Fetch
+// Fetch an answer
+// returns:
+// TRUE: We got a valid answer
+// FALSE: The answer we got had an invalid syntax
+//
+//
+
+/**
+ @file PASVANS.CPP
+ @internalComponent
+*/
+
+#include "DEBUG.H"
+#include "PASVANS.H"
+#include <e32base.h>
+#include <e32test.h>
+#include <in_sock.h>
+
+//
+// Definitions
+//
+
+TBool TFtpPASVAnswerParser::Fetch(TInetAddr& aFTPServerAddress)
+ {
+ __ASSERT_DEBUG((iState == ESuccess) || (iState == EFailed), User::Panic(_L("TFtpPASVAnswerParser::Fetch incorrect state"), 0));
+ if(iState != ESuccess)
+ return FALSE;
+ aFTPServerAddress = iFTPServerAddress;
+ return TRUE;
+ }
+
+void TFtpPASVAnswerParser::Reset(void)
+ {
+ iState = EIdle;
+ iFTPServerAddress.SetFamily(KAFUnspec);
+ }
+
+TBool TFtpPASVAnswerParser::Parse(const TDesC8& aBuffer, const TInetAddr& aAddr)
+ {
+ if (aAddr.Family() == KAfInet)
+ return ParsePASV(aBuffer);
+ else
+ {
+ __ASSERT_DEBUG(aAddr.Family() == KAfInet6, User::Panic(_L("TFtpPASVAnswerParser"), 0));
+ iFTPServerAddress.SetAddress(aAddr.Ip6Address());
+ return ParseEPSV(aBuffer);
+ }
+ }
+
+TBool TFtpPASVAnswerParser::ParsePASV(const TDesC8& aBuffer)
+ {
+ const TUint8* c;
+ TInt bufLen;
+ TUint aIPAndPort[6];
+
+ if ((iState == ESuccess) || (iState == EFailed))
+ // Already parsed an answer
+ return TRUE;
+ for (c= aBuffer.Ptr(),bufLen = aBuffer.Length();(bufLen>0);bufLen--,c++)
+ {
+ switch (iState)
+ {
+ case EIdle:
+ if (*c=='(')
+ {
+ /* We fetched a (, begin parsing*/
+ iNumberCounter=0;
+ iState++;
+ }
+ break;
+ case EBeginParse:
+ if ((*c>='0') && (*c<='9'))
+ {
+ iDigit.Zero();
+ iDigit.Append(*c);
+ iState++;
+ }
+ break;
+ case EParsing:
+ if ((*c>='0') && (*c<='9'))
+ if(iDigit.Length() == 3)
+ {
+ // We're stuffed, we got more than 3 digits
+ iState = EFailed;
+ return TRUE;
+ }
+ else
+ {
+ iDigit.Append(*c);
+ }
+ else // We should have a , or a ) I accept everything
+ {
+
+ //[1] Translate the last number that we parsed
+ TUint tempValue;
+ TLex input(iDigit);
+ input.Val(tempValue,EDecimal);
+ if(tempValue>255)
+ {
+ // If Value out of bound, we're stuffed
+ // Error bail out
+ iState = EFailed;
+ return TRUE;
+ }
+ aIPAndPort[iNumberCounter++] = tempValue;
+ // [2] Are we waiting for more numbers?
+ if(iNumberCounter == 6)
+ {
+ // OKay We've finished
+ iFTPServerAddress.SetAddress(INET_ADDR(aIPAndPort[0],aIPAndPort[1],aIPAndPort[2],aIPAndPort[3]));
+ iFTPServerAddress.SetPort(aIPAndPort[4]<<8 | aIPAndPort[5]);
+ iState = ESuccess;
+ return TRUE;
+ }
+ else
+ // Fetch next number
+ iState = EBeginParse;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ return FALSE;
+ }
+
+TBool TFtpPASVAnswerParser::ParseEPSV(const TDesC8& aBuffer)
+ {
+ TInt bufLen = aBuffer.Length();
+ TUint port = 0;
+
+ if ((iState == ESuccess) || (iState == EFailed))
+ // Already parsed an answer
+ return ETrue;
+
+ for (const TUint8* c = aBuffer.Ptr();bufLen>0;bufLen--,c++)
+ {
+ switch (iState)
+ {
+ case EIdle:
+ if (*c=='(')
+ {
+ /* We fetched a (, begin parsing*/
+ iState = EBeginParse;
+ }
+ break;
+ case EBeginParse:
+ if (TChar(*c).IsDigit())
+ {
+ port = *c - '0';
+ iState = EParsing;
+ }
+ break;
+ case EParsing:
+ if (TChar(*c).IsDigit())
+ {
+ port = port*10 + (*c - '0');
+ }
+ else // We should have a "|", end the parsing
+ {
+ if(port>(1<<16) || *c != '|')
+ {
+ // If Value out of bound or the last character is not a '|'
+ // then the parsing failed
+ iState = EFailed;
+ return ETrue;
+ }
+
+ iFTPServerAddress.SetPort(port);
+ iState = ESuccess;
+ return ETrue;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ return EFalse;
+ }