lowlevellibsandfws/apputils/multipartparser/src/qpcodec.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 02 Feb 2010 02:01:42 +0200
changeset 0 e4d67989cc36
permissions -rw-r--r--
Revision: 201002 Kit: 201005

// Copyright (c) 2008-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 FILES
// 
//

#include <e32std.h>
#include <bafl/qpcodec.h>

/**
Decode the string
@param aSrcString source string
@param rDestString Destination string
@return  KErrNone  if decode is complete
@return  KErrCorrupt if string is not QuotedPrintable compliant
*/
EXPORT_C TInt QuotedPrintableCodec::Decode( const TDesC8& aSrcString, TDes8& rDestString )
	{
	
#ifdef _DEBUG
	TInt KPanicInvalidSMTPLine = 6;
	_LIT(KDllName,"MultipartParser");
#endif
	
	const TUint8 KImcvSP			= ' ';
	const TUint8 KImcvCR			= '\r';
	const TUint8 KImcvLF			= '\n';	
	const TUint8 KImcvTab			= '\t';
	const TUint8 KImcvEquals		= '=';
	TUint8 qpCharacter = KImcvEquals;
	
	TInt error = KErrNone;
	
	__ASSERT_DEBUG(aSrcString.Length(), User::Panic( KDllName ,KPanicInvalidSMTPLine));

	rDestString = KNullDesC8;

	TPtrC8 source( aSrcString.Ptr(), aSrcString.Length() );
	const TUint8* pSource = source.Ptr();
	const TUint8* pEnd = pSource+aSrcString.Length();
	
	// find out if this is a blank line, if so then we'll add a paragraph delimiter instead
	// assume it's blank and then look for non-blank characters
	// avoid the CRLF at the end of the line (we know it's there thanks to the assertion above)

	TBool blankLine = ETrue; 
	while (pSource < pEnd-2) 
		{
		if (*pSource!=KImcvSP && *pSource!=KImcvTab)
			{
			blankLine = EFalse;
			break;
			}
		pSource++;
		}

	if ( blankLine )
		{
		rDestString.Copy( aSrcString );
		return KErrNone;
		}

	TInt outputLength=0;
	TUint8 loBits;
	TUint8 hiBits;
	TUint8 asciiValue;
	pSource = source.Ptr();	// reset to start of source data
	const TUint8 zero = '0';
	const TUint8 alphaAdjust = 55;  // 'A' is ascii 65 so we need to subtract 55 from 
									// alphabetical hex digits to get their numeric value
	while( pSource < pEnd )
		{
		if (*pSource != qpCharacter )
			{
			//  Quoted character or Attachment bound, just bung it on & move to the next one
			// *ptr++ = *pSource;
			outputLength++;
			rDestString.Append( *pSource );
			}
		else	// check for encoded character
			{
			// start looking at the next two characters, if they are there.

			if ( pSource+2 < pEnd )
				{
				pSource++;

				// check for '=' at EOL => this is a soft break, so remove it
				if (*pSource != KImcvCR) 
					{
					if(*pSource != KImcvLF) 
						{
					 	 // now decode hex value into ASCII code : hi-order bits come first
						 hiBits = (TUint8)(0x0F & (IsDigit( *pSource ) ? (TUint8)(*pSource-zero) : (TUint8)(*pSource-alphaAdjust)));
						 pSource++;
						 loBits = (TUint8)(0x0F & (IsDigit( *pSource ) ? (TUint8)(*pSource-zero) : (TUint8)(*pSource-alphaAdjust)));
						 asciiValue = (TUint8)( (hiBits<<4) + loBits);
						 // bung the character thus formed onto the decoded string
						 rDestString.Append( asciiValue );
						 // *ptr++ = asciiValue;
						 outputLength++;
						}
					}
				else
					{
					pSource++;
					if(*pSource != KImcvLF)
						{
						error=KErrCorrupt;
						pSource-=2;
						rDestString.Append( *pSource );
						pSource++;
						rDestString.Append( *pSource );
						pSource++;
						outputLength+=2;
						}
					}
				}
			else
				{
				// copy the rest of the data & use up the input string in the process.

				while (pSource < pEnd)
					{
					error=KErrCorrupt; // not QP compliant
					//*ptr++ = *pSource++;
					outputLength++;
					rDestString.Append( *pSource );
					pSource++;
					}
				}
			} // check for '=' char
		
		pSource++;  // next source charactery
	} // while

	rDestString.SetLength(outputLength);

	return error;
	}

/**
Check for digit
@param aChar charcter to be check
@return  ETrue if passed charcter is digit
@return  EFalse if passed charcter is not digit
*/	
TBool QuotedPrintableCodec::IsDigit( TChar aChar )
{
	return ( (aChar >= '0') && (aChar <= '9') );
}