--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/messagingfw/msgcommonutils/src/msgtextutils.cpp Mon Jan 18 20:36:02 2010 +0200
@@ -0,0 +1,950 @@
+/*
+* 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:
+* Miscellaneous text related utility methods.
+*
+*/
+
+
+
+// ========== INCLUDE FILES ================================
+
+#include <e32std.h>
+#include <e32base.h>
+#include <f32file.h>
+#include <s32file.h>
+
+#include <charconv.h>
+#include <txtrich.h>
+
+#include <cmsvattachment.h>
+#include <cmsvmimeheaders.h>
+#include <mmsvattachmentmanager.h>
+
+#include "msgtextutils.h"
+
+// ========== LOCAL CONSTANTS AND MACROS ===================
+
+/* Reddy - Moved ot header
+// Default charsets
+const TUint KDefaultCharConvCharset = KCharacterSetIdentifierAscii;
+const TUint KDefaultMIBCharset = KCharacterSetMIBEnumUsAscii;
+*/
+
+const TInt KMaxSampleLengthForAutoDetection = 512;
+const TInt KCharsetPluginArrayGranularity = 10;
+
+const TUint KCharParagraphSeparator = 0x2029;
+const TUint KCharLineFeed = 0x0a;
+const TUint KCharCarriageReturn = 0x0d;
+const TUint KCharAsciiDot = 0x2e;
+const TUint KCharAsciiMax = 0x7f;
+
+const TInt KMaxFileNameLength = 8; // must be at least 4!
+const TInt KMaxFileExtensionLenght = 5; // includes dot
+const TInt KMaxFileTotalLength = 12;
+
+_LIT8( KReplaceChar8, "_" );
+_LIT16( KReplaceChar16, "_" );
+
+// ========== MEMBER FUNCTIONS =============================
+
+
+// ---------------------------------------------------------
+// CMsgTextUtils::NewL
+// ---------------------------------------------------------
+//
+EXPORT_C CMsgTextUtils* CMsgTextUtils::NewL( RFs& aFs )
+ {
+ CMsgTextUtils* data = new ( ELeave ) CMsgTextUtils( aFs );
+ CleanupStack::PushL( data );
+ data->ConstructL();
+ CleanupStack::Pop();
+ return data;
+ }
+
+
+// ---------------------------------------------------------
+// CMsgTextUtils::CMsgTextUtils
+//
+// Constructor
+// ---------------------------------------------------------
+//
+CMsgTextUtils::CMsgTextUtils( RFs& aFs )
+ : iFs( aFs )
+ {
+ }
+
+
+// ---------------------------------------------------------
+// CMsgTextUtils::ConstructL
+// ---------------------------------------------------------
+//
+void CMsgTextUtils::ConstructL()
+ {
+ // Nothing to do. Reserved for future use.
+ }
+
+// ---------------------------------------------------------
+// CMsgTextUtils::~CMsgTextUtils
+//
+// Destructor.
+// ---------------------------------------------------------
+//
+CMsgTextUtils::~CMsgTextUtils()
+ {
+ delete iCharConv;
+ }
+
+// ---------------------------------------------------------
+// CMsgTextUtils::ConvertToBuffer8LC
+//
+// ---------------------------------------------------------
+//
+EXPORT_C HBufC8* CMsgTextUtils::ConvertToBuffer8LC(
+ const TDesC& aText,
+ TUint aCharacterSetIdentifier )
+ {
+ TInt origLength = aText.Length();
+ TInt maxLength = origLength;
+ HBufC8* resultBuffer = HBufC8::NewLC( maxLength );
+ if ( !iCharConv )
+ {
+ iCharConv = CCnvCharacterSetConverter::NewL();
+ }
+
+ if ( iCharConv->PrepareToConvertToOrFromL( aCharacterSetIdentifier, iFs ) !=
+ CCnvCharacterSetConverter::EAvailable )
+ {
+ User::Leave( KErrNotSupported );
+ }
+
+ iCharConv->SetReplacementForUnconvertibleUnicodeCharactersL( KReplaceChar8 );
+
+ TBuf8<40> outputBuffer;
+ TPtrC16 remainderOfUnicode( aText );
+
+ FOREVER
+ {
+ const TInt doneAll = iCharConv->ConvertFromUnicode( outputBuffer, remainderOfUnicode );
+
+ if ( doneAll == CCnvCharacterSetConverter::EErrorIllFormedInput )
+ {
+ User::Leave( KErrCorrupt );
+ }
+ else if ( doneAll < 0 )
+ {
+ // For future expansion of errors
+ User::Leave( KErrGeneral );
+ }
+ else
+ { // lint
+ }
+
+ // Make sure outputBuffer fits into resultBuffer
+ while ( resultBuffer->Length() + outputBuffer.Length() > maxLength )
+ {
+ // Increase resultBuffer length by origLength
+ maxLength += origLength;
+ resultBuffer = resultBuffer->ReAllocL( maxLength );
+ CleanupStack::Pop(); // resultBuffer
+ CleanupStack::PushL(resultBuffer);
+ }
+ // Append to result
+ resultBuffer->Des().Append( outputBuffer );
+
+ if ( doneAll == 0 )
+ {
+ return resultBuffer; // All converted
+ }
+
+ remainderOfUnicode.Set( remainderOfUnicode.Right( doneAll ));
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgTextUtils::ConvertToBuffer16LC
+//
+// ---------------------------------------------------------
+//
+EXPORT_C HBufC* CMsgTextUtils::ConvertToBuffer16LC(
+ const TDesC& aText,
+ TUint aCharacterSetIdentifier )
+ {
+ HBufC8* resultBuffer = ConvertToBuffer8LC( aText, aCharacterSetIdentifier );
+
+ HBufC* finalresult = HBufC::NewL( resultBuffer->Length() );
+ finalresult->Des().Copy( *resultBuffer );
+ CleanupStack::PopAndDestroy(); // resultbuffer
+ CleanupStack::PushL( finalresult );
+
+ return finalresult;
+ }
+
+// ---------------------------------------------------------
+// CMsgTextUtils::ConvertToFileL
+//
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgTextUtils::ConvertToFileL(
+ const TDesC& aText,
+ RFile& aFile,
+ TUint aCharacterSetIdentifier )
+ {
+ // Takes ownership of "aFile".
+ RFileWriteStream writer( aFile );
+ writer.PushL();
+
+ if ( !iCharConv )
+ {
+ iCharConv = CCnvCharacterSetConverter::NewL();
+ }
+
+ if ( iCharConv->PrepareToConvertToOrFromL( aCharacterSetIdentifier, iFs )
+ != CCnvCharacterSetConverter::EAvailable )
+ {
+ User::Leave( KErrNotSupported );
+ }
+
+ iCharConv->SetReplacementForUnconvertibleUnicodeCharactersL( KReplaceChar8 );
+
+ TBuf8<128> outputBuffer;
+ TPtrC16 remainderOfUnicodeText( aText );
+ FOREVER
+ {
+ TInt doneAll = iCharConv->ConvertFromUnicode(
+ outputBuffer, remainderOfUnicodeText );
+ if ( doneAll == CCnvCharacterSetConverter::EErrorIllFormedInput )
+ {
+ User::Leave( KErrCorrupt );
+ }
+ else if ( doneAll < 0 ) // future-proof against "TError" expanding
+ {
+ User::Leave( KErrGeneral );
+ }
+ else
+ { // lint
+ }
+
+ writer.WriteL( outputBuffer );
+
+ if ( doneAll == 0 )
+ {
+ // All of aText has been converted and handled
+ writer.CommitL();
+ writer.Pop();
+ writer.Close();
+ return;
+ }
+ remainderOfUnicodeText.Set( remainderOfUnicodeText.Right( doneAll ) );
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgTextUtils::CharconvIdToMibIdL
+//
+// ---------------------------------------------------------
+//
+EXPORT_C TUint CMsgTextUtils::CharconvIdToMibIdL( TUint aCharconvCharsetId )
+ {
+ // Switch-case is here for performance optimization
+ TUint charset = 0;
+ switch ( aCharconvCharsetId )
+ {
+ case 0:
+ // Symbian OS native charset
+ charset = KCharacterSetMIBEnumIso10646Ucs2;
+ break;
+ case KCharacterSetIdentifierAscii:
+ charset = KCharacterSetMIBEnumUsAscii;
+ break;
+ case KCharacterSetIdentifierUtf8:
+ charset = KCharacterSetMIBEnumUtf8;
+ break;
+ case KCharacterSetIdentifierIso88591:
+ charset = KCharacterSetMIBEnumISO_8859_1;
+ break;
+ case KCharacterSetIdentifierIso88592:
+ charset = KCharacterSetMIBEnumISO_8859_2;
+ break;
+ case KCharacterSetIdentifierIso88593:
+ charset = KCharacterSetMIBEnumISO_8859_3;
+ break;
+ case KCharacterSetIdentifierIso88594:
+ charset = KCharacterSetMIBEnumISO_8859_4;
+ break;
+ case KCharacterSetIdentifierIso88595:
+ charset = KCharacterSetMIBEnumISO_8859_5;
+ break;
+ case KCharacterSetIdentifierIso88596:
+ charset = KCharacterSetMIBEnumISO_8859_6;
+ break;
+ case KCharacterSetIdentifierIso88597:
+ charset = KCharacterSetMIBEnumISO_8859_7;
+ break;
+ case KCharacterSetIdentifierIso88598:
+ charset = KCharacterSetMIBEnumISO_8859_8;
+ break;
+ case KCharacterSetIdentifierIso88599:
+ charset = KCharacterSetMIBEnumISO_8859_9;
+ break;
+ case KCharacterSetIdentifierIso885910:
+ charset = KCharacterSetMIBEnumISO_8859_10;
+ break;
+ case KCharacterSetIdentifierIso885913:
+ charset = KCharacterSetMIBEnumISO_8859_13;
+ break;
+ case KCharacterSetIdentifierIso885914:
+ charset = KCharacterSetMIBEnumISO_8859_14;
+ break;
+ case KCharacterSetIdentifierIso885915:
+ charset = KCharacterSetMIBEnumISO_8859_15;
+ break;
+ case KCharacterSetIdentifierUtf7:
+ charset = KCharacterSetMIBEnumUtf7;
+ break;
+ case KCharacterSetIdentifierCodePage1252:
+ charset = KCharacterSetMIBEnumCodePage1252;
+ break;
+ // Chinese charsets
+ case KCharacterSetIdentifierGb2312:
+ charset = KCharacterSetMIBEnumGb2312;
+ break;
+ case KCharacterSetIdentifierHz:
+ charset = KCharacterSetMIBEnumHz;
+ break;
+ case KCharacterSetIdentifierGbk:
+ charset = KCharacterSetMIBEnumGbk;
+ break;
+ case KCharacterSetIdentifierBig5:
+ charset = KCharacterSetMIBEnumBig5;
+ break;
+ // Japanese charsets
+ case KCharacterSetIdentifierShiftJis:
+ charset = KCharacterSetMIBEnumShiftJis;
+ break;
+ case KCharacterSetIdentifierIso2022Jp:
+ charset = KCharacterSetMIBEnumIso2022Jp;
+ break;
+ case KCharacterSetIdentifierJis:
+ charset = KCharacterSetMIBEnumJis;
+ break;
+ case KCharacterSetIdentifierEucJpPacked:
+ charset = KCharacterSetMIBEnumEucJpPacked;
+ break;
+ default:
+ {
+ if ( !iCharConv )
+ {
+ iCharConv = CCnvCharacterSetConverter::NewL();
+ }
+ charset = iCharConv->ConvertCharacterSetIdentifierToMibEnumL(
+ aCharconvCharsetId, iFs );
+ if ( charset == 0 )
+ {
+ charset = KDefaultMIBCharset;
+ }
+ break;
+ }
+ }
+ return charset;
+ }
+
+// ---------------------------------------------------------
+// CMsgTextUtils::MibIdToCharconvIdL
+//
+// ---------------------------------------------------------
+//
+EXPORT_C TUint CMsgTextUtils::MibIdToCharconvIdL( TUint aMibId )
+ {
+ // Switch-case is here for performance optimization
+ TUint charset = 0;
+ switch ( aMibId )
+ {
+ case KCharacterSetMIBEnumIso10646Ucs2:
+ case KCharacterSetMIBEnumUTF16:
+ //no conversion for Unicode
+ charset = 0;
+ break;
+ case KCharacterSetMIBEnumUTF16BE:
+ charset = KCharacterSetIdentifierUnicodeBig;
+ break;
+ case KCharacterSetMIBEnumUTF16LE:
+ charset = KCharacterSetIdentifierUnicodeLittle;
+ break;
+ case KCharacterSetMIBEnumUsAscii:
+ charset = KCharacterSetIdentifierAscii;
+ break;
+ case KCharacterSetMIBEnumUtf8:
+ charset = KCharacterSetIdentifierUtf8;
+ break;
+ case KCharacterSetMIBEnumISO_8859_1:
+ charset = KCharacterSetIdentifierIso88591;
+ break;
+ case KCharacterSetMIBEnumISO_8859_2:
+ charset = KCharacterSetIdentifierIso88592;
+ break;
+ case KCharacterSetMIBEnumISO_8859_3:
+ charset = KCharacterSetIdentifierIso88593;
+ break;
+ case KCharacterSetMIBEnumISO_8859_4:
+ charset = KCharacterSetIdentifierIso88594;
+ break;
+ case KCharacterSetMIBEnumISO_8859_5:
+ charset = KCharacterSetIdentifierIso88595;
+ break;
+ case KCharacterSetMIBEnumISO_8859_6:
+ charset = KCharacterSetIdentifierIso88596;
+ break;
+ case KCharacterSetMIBEnumISO_8859_7:
+ charset = KCharacterSetIdentifierIso88597;
+ break;
+ case KCharacterSetMIBEnumISO_8859_8:
+ charset = KCharacterSetIdentifierIso88598;
+ break;
+ case KCharacterSetMIBEnumISO_8859_9:
+ charset = KCharacterSetIdentifierIso88599;
+ break;
+ case KCharacterSetMIBEnumISO_8859_10:
+ charset = KCharacterSetIdentifierIso885910;
+ break;
+ case KCharacterSetMIBEnumISO_8859_13:
+ charset = KCharacterSetIdentifierIso885913;
+ break;
+ case KCharacterSetMIBEnumISO_8859_14:
+ charset = KCharacterSetIdentifierIso885914;
+ break;
+ case KCharacterSetMIBEnumISO_8859_15:
+ charset = KCharacterSetIdentifierIso885915;
+ break;
+ case KCharacterSetMIBEnumUtf7:
+ charset = KCharacterSetIdentifierUtf7;
+ break;
+ case KCharacterSetMIBEnumCodePage1252:
+ charset = KCharacterSetIdentifierCodePage1252;
+ break;
+ // Chinese charsets
+ case KCharacterSetMIBEnumGb2312:
+ charset = KCharacterSetIdentifierGb2312;
+ break;
+ case KCharacterSetMIBEnumHz:
+ charset = KCharacterSetIdentifierHz;
+ break;
+ case KCharacterSetMIBEnumGbk:
+ charset = KCharacterSetIdentifierGbk;
+ break;
+ case KCharacterSetMIBEnumBig5:
+ charset = KCharacterSetIdentifierBig5;
+ break;
+ // Japanese charsets
+ case KCharacterSetMIBEnumShiftJis:
+ charset = KCharacterSetIdentifierShiftJis;
+ break;
+ case KCharacterSetMIBEnumIso2022Jp:
+ charset = KCharacterSetIdentifierIso2022Jp;
+ break;
+ case KCharacterSetMIBEnumJis:
+ charset = KCharacterSetIdentifierJis;
+ break;
+ case KCharacterSetMIBEnumEucJpPacked:
+ charset = KCharacterSetIdentifierEucJpPacked;
+ break;
+ default:
+ {
+ if ( !iCharConv )
+ {
+ iCharConv = CCnvCharacterSetConverter::NewL();
+ }
+ charset = iCharConv->ConvertMibEnumOfCharacterSetToIdentifierL( aMibId, iFs );
+ if ( charset == 0 )
+ {
+ charset = KDefaultCharConvCharset;
+ }
+ break;
+ }
+ }
+ return charset;
+ }
+
+// ---------------------------------------------------------
+// ConvertParagraphSeparatorsLC
+// ---------------------------------------------------------
+//
+EXPORT_C HBufC* CMsgTextUtils::ConvertParagraphSeparatorsLC( const TDesC& aText )
+ {
+ TInt position;
+ TPtrC ptr;
+
+ TInt numberOfSeparators = 0;
+
+ position = 0;
+ ptr.Set( aText.Mid( 0 ) );
+ while ( position != KErrNotFound && position < aText.Length() )
+ {
+ ptr.Set( ptr.Mid( position ) );
+ position = ptr.Locate( TChar( KCharParagraphSeparator ) );
+ if ( position != KErrNotFound )
+ {
+ numberOfSeparators++;
+ position++; // point past separator just found
+ }
+ }
+
+ HBufC* convertedText = HBufC::NewLC( aText.Length() + numberOfSeparators );
+ ptr.Set( aText.Mid( 0 ) );
+ TInt start = 0;
+ position = aText.Locate( TChar( KCharParagraphSeparator ) );
+ while ( position != KErrNotFound && start < aText.Length() )
+ {
+ ptr.Set( aText.Mid( start ) );
+ position = ptr.Locate( TChar( KCharParagraphSeparator ) );
+ if ( position != KErrNotFound )
+ {
+ convertedText->Des().Append( ptr.Left( position ) );
+ convertedText->Des().Append( TChar( KCharCarriageReturn ) );
+ convertedText->Des().Append( TChar( KCharLineFeed ) );
+ start = start + position + 1; // point past separator
+ }
+ }
+ // append what is left after last separator has been found
+ if ( start < aText.Length() )
+ {
+ convertedText->Des().Append( aText.Mid( start ) );
+ }
+
+ return convertedText;
+ }
+
+// ---------------------------------------------------------
+// CMsgTextUtils::TrimAndRemoveNonAlphaDigit
+//
+// NOTE: This is intended for small strings. With long
+// strings if could be more efficient to to seek replacable
+// chars than to loop thru every char.
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgTextUtils::TrimAndRemoveNonAlphaDigit( TDes& aString )
+ {
+ aString.Trim();
+ for (TInt i = aString.Length(); --i >= 0 ;)
+ {
+ TChar c = (TChar) aString[i];
+ // Allow dots i.e. "." because they are allowed in URI and
+ // because filename are created from content-location
+ // so this will result to "filename.txt" instead of "filename_txt"
+ if ( aString[i] > KCharAsciiMax ||
+ ( aString[i] != KCharAsciiDot && !c.IsAlphaDigit() ) )
+ {
+ aString.Replace( i, 1, KReplaceChar16 );
+ }
+ }
+ }
+
+// ---------------------------------------------------------
+// UTF8Size
+// ---------------------------------------------------------
+//
+EXPORT_C TInt CMsgTextUtils::UTF8Size( TPtrC aText )
+ {
+ TInt count = 0;
+ TInt sizeInBytes = 0;
+ TUint16 charValue;
+ while ( count < aText.Length() )
+ {
+ charValue = aText[count];
+ if ( charValue < 0x80 )
+ {
+ sizeInBytes += 1;
+ }
+ else if ( charValue < 0x800 )
+ {
+ sizeInBytes += 2;
+ }
+ else //if ( charValue < 0x10000 )
+ {
+ sizeInBytes += 3;
+ }
+ count++;
+ }
+ return sizeInBytes;
+ }
+
+// ---------------------------------------------------------
+// ConvertLineBreaksL
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgTextUtils::ConvertLineBreaksL( CRichText& aText, TInt aMode )
+ {
+ if ( aMode & ECRLFtoLF )
+ {
+ DoConvertCRLFL( aText );
+ }
+ }
+
+// ---------------------------------------------------------
+// DoConvertCRLFL
+// ---------------------------------------------------------
+//
+void CMsgTextUtils::DoConvertCRLFL( CRichText& aText )
+ {
+ TInt i( 0 );
+ TInt documentLength( aText.DocumentLength() );
+
+ while ( i < documentLength )
+ {
+ if ( aText.Read( i, 1 ).Locate( KCharCarriageReturn ) != KErrNotFound )
+ {
+ if ( i < documentLength - 1 &&
+ aText.Read( i + 1, 1 ).Locate( KCharLineFeed ) != KErrNotFound )
+ {
+ // "CR+LF" -> "LF"
+ aText.DeleteL( i, 1 );
+ documentLength--;
+ }
+ }
+ i++;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// RecognizeCharSetL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TUint CMsgTextUtils::RecognizeCharSetL( RFs& aFs, RFile& aFile )
+ {
+ TUint charSet( 0 );
+
+ HBufC8* sample = HBufC8::NewLC( KMaxSampleLengthForAutoDetection );
+ TPtr8 sampleDes = sample->Des();
+
+ TInt fileSize( 0 );
+ User::LeaveIfError( aFile.Size( fileSize ) );
+ User::LeaveIfError( aFile.Read( 0, sampleDes, fileSize > sampleDes.MaxLength()
+ ? sampleDes.MaxLength()
+ : fileSize ) );
+
+
+ // Check for Byte Order Mark (BOM)
+ // U+FEFF ZERO WIDTH NON-BREAKING SPACE
+ //
+ // (from www.unicode.org FAQ)
+ // - FE FF -> UTF-16, big-endian
+ // - FF FE -> UTF-16, little-endian
+ //
+ if ( !sampleDes.Length() ||
+ ( sampleDes.Size() >= 2 &&
+ ( ( sampleDes[0] == 0xfe && sampleDes[1] == 0xff ) ||
+ ( sampleDes[0] == 0xff && sampleDes[1] == 0xfe ) ) ) )
+ {
+ // Zero means no conversion
+ charSet = 0;
+ }
+ else
+ {
+ const CArrayFix<CCnvCharacterSetConverter::SCharacterSet>* availableSets =
+ CCnvCharacterSetConverter::CreateArrayOfCharacterSetsAvailableLC( aFs );
+
+ CArrayFix<CCnvCharacterSetConverter::SCharacterSet>* toDetectSets =
+ new ( ELeave ) CArrayFixFlat<CCnvCharacterSetConverter::SCharacterSet>( KCharsetPluginArrayGranularity );
+ CleanupStack::PushL( toDetectSets );
+
+ const TInt count( availableSets->Count() );
+ for ( TInt i( 0 ); i < count; i++ )
+ {
+ switch ( availableSets->At( i ).Identifier() )
+ {
+ case KCharacterSetIdentifierSms7Bit:
+ // remove Sms7Bit from charset list
+ break;
+ default:
+ toDetectSets->AppendL( availableSets->At( i ) );
+ break;
+ }
+ }
+
+ TUint resultCharset( 0 );
+ TInt confidence( 0 );
+ CCnvCharacterSetConverter::AutoDetectCharacterSetL(
+ confidence, resultCharset, *toDetectSets, sampleDes );
+ charSet = resultCharset;
+
+ CleanupStack::PopAndDestroy( 2 ); // availableSets, toDetectSets
+ }
+ CleanupStack::PopAndDestroy( sample );
+ TInt seekPos(0);
+ aFile.Seek( ESeekStart, seekPos );
+ return charSet;
+ }
+
+// ---------------------------------------------------------
+// GetSafeAttachmentNameLC
+// ---------------------------------------------------------
+//
+EXPORT_C HBufC* CMsgTextUtils::GetSafeAttachmentNameLC(
+ MMsvAttachmentManager& aManager,
+ const TDesC& aFileName,
+ TMsvAttachmentId aAttachmentId,
+ TBool aContentLocation )
+ {
+ TBuf<KMaxFileNameLength> name;
+ TBuf<KMaxFileExtensionLenght> ext;
+ TBuf<KMaxFileTotalLength> candidate;
+ TParsePtrC parse( aFileName );
+
+ ext.Copy( parse.Ext().Left( KMaxFileExtensionLenght ) );
+ CMsgTextUtils::TrimAndRemoveNonAlphaDigit( ext );
+
+ TInt nameLen = Min( KMaxFileNameLength,
+ ( KMaxFileTotalLength - ext.Length() ) );
+ name.Copy( parse.Name().Left( nameLen ) );
+ CMsgTextUtils::TrimAndRemoveNonAlphaDigit( name );
+
+ candidate.Copy( name );
+ candidate.Append( ext );
+
+ TBool safeFound = EFalse;
+ TInt count = aManager.AttachmentCount();
+ TInt i = 0;
+ while ( !safeFound && i < count )
+ {
+ safeFound = ETrue;
+ for ( TInt ii = 0; ii < count && safeFound; ii++ )
+ {
+ CMsvAttachment* attachment = aManager.GetAttachmentInfoL( ii );
+ CleanupStack::PushL( attachment );
+ if ( aContentLocation )
+ {
+ CMsvMimeHeaders* msvMime = CMsvMimeHeaders::NewLC();
+ msvMime->RestoreL( *attachment );
+ if ( attachment->Id() != aAttachmentId &&
+ !candidate.CompareF( msvMime->ContentLocation() ) )
+ {
+ safeFound = EFalse;
+ }
+ CleanupStack::PopAndDestroy( msvMime );
+ }
+ else
+ {
+ if ( attachment->Id() != aAttachmentId &&
+ !candidate.CompareF( attachment->AttachmentName() ) )
+ {
+ safeFound = EFalse;
+ }
+ }
+ CleanupStack::PopAndDestroy( attachment );
+ }
+ i++;
+ if ( !safeFound )
+ {
+ name.Zero();
+ name.Copy( parse.Name().Left( nameLen - 3 ) );
+ CMsgTextUtils::TrimAndRemoveNonAlphaDigit( name );
+ TBuf<3> num;
+ num.NumFixedWidth( i, EDecimal, 3 );
+ name.Append( num );
+ candidate.Zero();
+ candidate.Copy( name );
+ candidate.Append( ext );
+ }
+ }
+
+ // It is guaranteed that we always find a safe candidate:
+ // - either safeFound == ETrue, or
+ // - we've got "count + 1st" candidate while there are
+ // "count" existing attachments.
+ HBufC* safeFileName = candidate.AllocLC();
+ return safeFileName;
+ }
+
+// ---------------------------------------------------------
+// from: TBool CImRecvConvert::IsIllegalChar(const TUint aChar)
+// ---------------------------------------------------------
+//
+LOCAL_C TBool IsIllegalChar(const TUint aChar)
+ {
+ return (
+ aChar == '*' ||
+ aChar == '\\' ||
+ aChar == '<' ||
+ aChar == '>' ||
+ aChar == ':' ||
+ aChar == '.' ||
+ aChar == '"' ||
+ aChar == '/' ||
+ aChar == '|' ||
+ aChar == '?' ||
+ aChar == CEditableText::EParagraphDelimiter ||
+ aChar == CEditableText::ELineBreak ||
+ aChar < ' ' );
+ }
+
+// ---------------------------------------------------------
+// GetFileNameFromBuffer
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgTextUtils::GetFileNameFromBuffer(
+ TFileName& aFileName,
+ const TDesC& aBuffer,
+ TInt aMaxLength,
+ const TDesC* aExt /*= NULL*/ )
+ {
+ if ( aExt != NULL )
+ {
+ aMaxLength -= aExt->Length();
+ }
+
+ TInt len = aBuffer.Length();
+ TInt max = Min( len, aMaxLength );
+
+ //__ASSERT_DEBUG( max > 0, Panic( EMsgZeroLength ) );
+
+ aFileName.Zero();
+
+ TInt cc = 0;
+ TUint ch;
+ TUint ch1 = 0;
+ TBool spaces = EFalse;
+ for ( TInt i = 0; i < len && cc < max; i++ )
+ {
+ ch = aBuffer[i];
+
+ // ignore spaces from beginning of the buffer until first
+ // non-space is encountered.
+ if ( !spaces && ch != ' ' )
+ {
+ spaces = ETrue;
+ }
+
+ if ( i > 0 )
+ {
+ ch1 = aBuffer[i - 1];
+ }
+
+ // strip illegal chars away.
+ // checks also if previous and current chars are '.'
+ if ( spaces && ! IsIllegalChar( ch ) )
+ {
+ if ( !( i > 0 && ch == '.' && ch1 == '.' ) )
+ {
+ aFileName.Append( ch );
+ cc++;
+ }
+ }
+ }
+
+ aFileName.Trim();
+
+ // If filename is empty at this point, do not append extension either.
+ // Instead, empty filename is returned so that caller can use whatever
+ // default s/he has for it.
+ if ( aFileName.Length() > 0 && aExt != NULL )
+ {
+ aFileName.Append( *aExt );
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgTextUtils::ConvertToUnicodeL
+// Converts input 8-bit data buffer (in given foreign charset type) to unicode buffer.
+// ---------------------------------------------------------
+EXPORT_C HBufC16* CMsgTextUtils::ConvertToUnicodeL( const TDesC8& aText, TUint aCharacterSetIdentifier )
+ {
+ TInt origLength = aText.Length();
+ TInt maxLength = origLength;
+
+ if ( !iCharConv )
+ {
+ iCharConv = CCnvCharacterSetConverter::NewL();
+ }
+
+ //buffer to hold target data and return to caller
+ HBufC* resultBuffer = HBufC::NewL( maxLength );
+ _LIT8( KReplaceChar8, "_" );
+
+ if ( iCharConv->PrepareToConvertToOrFromL( aCharacterSetIdentifier, iFs ) !=
+ CCnvCharacterSetConverter::EAvailable )
+ {
+ User::Leave( KErrNotSupported );
+ }
+
+ //TODO:: need to set endianess if required.
+ //TODO:: below line is not necessary i guess???
+ //The missing character is simply replaced by the Unicode character which represents unknown characters (0xFFFD)
+ //iCharConv->SetReplacementForUnconvertibleUnicodeCharactersL( KReplaceChar8 );
+
+ TBuf16<40> outputBuffer;
+ TPtrC8 remainderOfinputBuf ( aText );
+ //TODO: KStateDefault header include
+ TInt aState = 0; // KStateDefault;
+
+ FOREVER
+ {
+ const TInt doneAll = iCharConv->ConvertToUnicode( outputBuffer, remainderOfinputBuf, aState );
+
+ if ( doneAll == CCnvCharacterSetConverter::EErrorIllFormedInput )
+ {
+ User::Leave( KErrCorrupt );
+ }
+ else if ( doneAll < 0 )
+ {
+ // For future expansion of errors
+ User::Leave( KErrGeneral );
+ }
+ else
+ { // lint
+ }
+
+ // Make sure outputBuffer fits into resultBuffer
+ while ( resultBuffer->Length() + outputBuffer.Length() > maxLength )
+ {
+ // Increase resultBuffer length by origLength
+ maxLength += origLength;
+ resultBuffer = resultBuffer->ReAllocL( maxLength );
+ }
+ // Append to result
+ resultBuffer->Des().Append( outputBuffer );
+
+ if ( doneAll == 0 )
+ {
+ /* Testing */
+ /* start ---
+ resultBuffer = resultBuffer->ReAllocL( maxLength + 20);
+ resultBuffer->Des().Append(_L("Korean Enc:415-5434"));
+ ---- End */
+ return resultBuffer; // All converted
+ }
+ //TODO:: set the buffer correctly w.r.t length, Remember this is HBUFC16
+ remainderOfinputBuf.Set( remainderOfinputBuf.Right( doneAll ));
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgTextUtils::ConvertPtrToDesC16
+// Converts input 8-bit data buffer to 16-bit data buffer.
+// ---------------------------------------------------------
+EXPORT_C void CMsgTextUtils::ConvertPtrToDesC16( const TDes8& aFromBuff8, TDes16& aToBuff16 )
+ {
+ TInt i = 0;
+ TInt j = 0;
+
+ aToBuff16.FillZ( aToBuff16.MaxSize()/2 ); //MaxSize returns in bytes, hence devide by 2
+ while( j < (aFromBuff8.Length() - 1) )
+ {
+ aToBuff16[i] = aFromBuff8[j++] & 0xff; // low byte
+ aToBuff16[i++] |= (aFromBuff8[j++] << 8); // high byte
+ }
+ aToBuff16.SetLength(i);
+ }
+
+// End of File