diff -r 000000000000 -r b16258d2340f applayerprotocols/ftpengine/ftpprot/PASVANS.CPP --- /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 +#include +#include + +// +// 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; + }