sl@0: // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // INCLUDE FILES sl@0: // sl@0: // sl@0: sl@0: #include sl@0: #include sl@0: sl@0: /** sl@0: Decode the string sl@0: @param aSrcString source string sl@0: @param rDestString Destination string sl@0: @return KErrNone if decode is complete sl@0: @return KErrCorrupt if string is not QuotedPrintable compliant sl@0: */ sl@0: EXPORT_C TInt QuotedPrintableCodec::Decode( const TDesC8& aSrcString, TDes8& rDestString ) sl@0: { sl@0: sl@0: #ifdef _DEBUG sl@0: TInt KPanicInvalidSMTPLine = 6; sl@0: _LIT(KDllName,"MultipartParser"); sl@0: #endif sl@0: sl@0: const TUint8 KImcvSP = ' '; sl@0: const TUint8 KImcvCR = '\r'; sl@0: const TUint8 KImcvLF = '\n'; sl@0: const TUint8 KImcvTab = '\t'; sl@0: const TUint8 KImcvEquals = '='; sl@0: TUint8 qpCharacter = KImcvEquals; sl@0: sl@0: TInt error = KErrNone; sl@0: sl@0: __ASSERT_DEBUG(aSrcString.Length(), User::Panic( KDllName ,KPanicInvalidSMTPLine)); sl@0: sl@0: rDestString = KNullDesC8; sl@0: sl@0: TPtrC8 source( aSrcString.Ptr(), aSrcString.Length() ); sl@0: const TUint8* pSource = source.Ptr(); sl@0: const TUint8* pEnd = pSource+aSrcString.Length(); sl@0: sl@0: // find out if this is a blank line, if so then we'll add a paragraph delimiter instead sl@0: // assume it's blank and then look for non-blank characters sl@0: // avoid the CRLF at the end of the line (we know it's there thanks to the assertion above) sl@0: sl@0: TBool blankLine = ETrue; sl@0: while (pSource < pEnd-2) sl@0: { sl@0: if (*pSource!=KImcvSP && *pSource!=KImcvTab) sl@0: { sl@0: blankLine = EFalse; sl@0: break; sl@0: } sl@0: pSource++; sl@0: } sl@0: sl@0: if ( blankLine ) sl@0: { sl@0: rDestString.Copy( aSrcString ); sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt outputLength=0; sl@0: TUint8 loBits; sl@0: TUint8 hiBits; sl@0: TUint8 asciiValue; sl@0: pSource = source.Ptr(); // reset to start of source data sl@0: const TUint8 zero = '0'; sl@0: const TUint8 alphaAdjust = 55; // 'A' is ascii 65 so we need to subtract 55 from sl@0: // alphabetical hex digits to get their numeric value sl@0: while( pSource < pEnd ) sl@0: { sl@0: if (*pSource != qpCharacter ) sl@0: { sl@0: // Quoted character or Attachment bound, just bung it on & move to the next one sl@0: // *ptr++ = *pSource; sl@0: outputLength++; sl@0: rDestString.Append( *pSource ); sl@0: } sl@0: else // check for encoded character sl@0: { sl@0: // start looking at the next two characters, if they are there. sl@0: sl@0: if ( pSource+2 < pEnd ) sl@0: { sl@0: pSource++; sl@0: sl@0: // check for '=' at EOL => this is a soft break, so remove it sl@0: if (*pSource != KImcvCR) sl@0: { sl@0: if(*pSource != KImcvLF) sl@0: { sl@0: // now decode hex value into ASCII code : hi-order bits come first sl@0: hiBits = (TUint8)(0x0F & (IsDigit( *pSource ) ? (TUint8)(*pSource-zero) : (TUint8)(*pSource-alphaAdjust))); sl@0: pSource++; sl@0: loBits = (TUint8)(0x0F & (IsDigit( *pSource ) ? (TUint8)(*pSource-zero) : (TUint8)(*pSource-alphaAdjust))); sl@0: asciiValue = (TUint8)( (hiBits<<4) + loBits); sl@0: // bung the character thus formed onto the decoded string sl@0: rDestString.Append( asciiValue ); sl@0: // *ptr++ = asciiValue; sl@0: outputLength++; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: pSource++; sl@0: if(*pSource != KImcvLF) sl@0: { sl@0: error=KErrCorrupt; sl@0: pSource-=2; sl@0: rDestString.Append( *pSource ); sl@0: pSource++; sl@0: rDestString.Append( *pSource ); sl@0: pSource++; sl@0: outputLength+=2; sl@0: } sl@0: } sl@0: } sl@0: else sl@0: { sl@0: // copy the rest of the data & use up the input string in the process. sl@0: sl@0: while (pSource < pEnd) sl@0: { sl@0: error=KErrCorrupt; // not QP compliant sl@0: //*ptr++ = *pSource++; sl@0: outputLength++; sl@0: rDestString.Append( *pSource ); sl@0: pSource++; sl@0: } sl@0: } sl@0: } // check for '=' char sl@0: sl@0: pSource++; // next source charactery sl@0: } // while sl@0: sl@0: rDestString.SetLength(outputLength); sl@0: sl@0: return error; sl@0: } sl@0: sl@0: /** sl@0: Check for digit sl@0: @param aChar charcter to be check sl@0: @return ETrue if passed charcter is digit sl@0: @return EFalse if passed charcter is not digit sl@0: */ sl@0: TBool QuotedPrintableCodec::IsDigit( TChar aChar ) sl@0: { sl@0: return ( (aChar >= '0') && (aChar <= '9') ); sl@0: }