omads/omadsextensions/adapters/bookmark/src/vbookmarkconverter.cpp
changeset 40 b63e67867dcd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/omads/omadsextensions/adapters/bookmark/src/vbookmarkconverter.cpp	Tue Jul 13 03:39:25 2010 +0530
@@ -0,0 +1,713 @@
+/*
+* Copyright (c) 2005-2007 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:  Bookmark object conversion routines
+*
+*/
+
+
+// INCLUDES
+#include <utf.h>
+#include <favouritesitem.h>
+#include <feedsserverfolderitem.h>
+#include "vbookmarkconverter.h"
+#include "logger.h"
+
+// CONSTANTS
+_LIT8(KVBMKBegin, "BEGIN");
+_LIT8(KVBMKEnd, "END");
+_LIT8(KVBMKVbkm, "VBKM");
+_LIT8(KVBMKEnv, "ENV");
+_LIT8(KVBMKVersion, "VERSION");         
+_LIT8(KVBMKVer, "1.0");             
+_LIT8(KVBMKUrl, "URL");                 
+_LIT8(KVBMKTitle, "TITLE");     
+_LIT8(KVBMKXIrmcUrl, "X-IRMC-URL");
+_LIT8(KVBMKInternetShortcut, "[InternetShortcut]"); 
+_LIT8(KVBMKPrintable, "QUOTED-PRINTABLE");  
+_LIT8(KVBMKLinefeed, "\r\n");
+_LIT8(KVBMKColon, ":");
+_LIT8(KVBMKAssignment, "=");
+_LIT8(KVBMKSemicolon, ";");
+_LIT8(KVBMKNone, "");
+_LIT(KEmptyString, "");
+_LIT8(KVBMKCharset, "CHARSET");
+_LIT8(KVBMKUtf8, "UTF-8");
+
+// -----------------------------------------------------------------------------
+// CVBookmarkConverter::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+CVBookmarkConverter* CVBookmarkConverter::NewL()
+    {
+    CVBookmarkConverter* self = CVBookmarkConverter::NewLC();
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CVBookmarkConverter::NewLC
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+CVBookmarkConverter* CVBookmarkConverter::NewLC()
+    {
+    CVBookmarkConverter* self = new (ELeave) CVBookmarkConverter();
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CVBookmarkConverter::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+void CVBookmarkConverter::ConstructL()
+    {
+    iVersion = HBufC::NewL(1);
+    iTitle = HBufC::NewL(1);
+    iUrl = HBufC::NewL(1);
+    iInternetShortcut = HBufC::NewL(1);
+    }
+
+// -----------------------------------------------------------------------------
+// CVBookmarkConverter::CVBookmarkConverter
+// C++ default constructor can NOT contain any code, that might leave
+// -----------------------------------------------------------------------------
+CVBookmarkConverter::CVBookmarkConverter()
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CVBookmarkConverter::~CVBookmarkConverter
+// Destructor.
+// -----------------------------------------------------------------------------
+CVBookmarkConverter::~CVBookmarkConverter()
+    {
+    delete iVersion;
+    delete iUrl;
+    delete iTitle;
+    delete iInternetShortcut;
+    }
+
+const TDesC& CVBookmarkConverter::GetVersion() const
+    {
+    return *iVersion;
+    }
+
+const TDesC& CVBookmarkConverter::GetUrl() const
+    {
+    return *iUrl;
+    }
+
+const TDesC& CVBookmarkConverter::GetTitle() const
+    {
+    return *iTitle;
+    }
+
+const TDesC& CVBookmarkConverter::GetInternetShortcut() const
+    {
+    return *iInternetShortcut;
+    }
+
+void CVBookmarkConverter::SetVersionL( const TDesC& aVersion )
+    {
+    delete iVersion;
+    iVersion = NULL;
+    iVersion = aVersion.AllocL();
+    }
+    
+void CVBookmarkConverter::SetVersionL( const TDesC8& aVersion )
+    {
+    delete iVersion;
+    iVersion = NULL;
+    iVersion = CnvUtfConverter::ConvertToUnicodeFromUtf8L( aVersion );  
+    }   
+    
+void CVBookmarkConverter::SetUrlL( const TDesC& aUrl )
+    {
+    delete iUrl;
+    iUrl = NULL;
+    iUrl = aUrl.AllocL();
+    }
+    
+void CVBookmarkConverter::SetUrlL( const TDesC8& aUrl )
+    {
+    delete iUrl;
+    iUrl = NULL;
+    iUrl = CnvUtfConverter::ConvertToUnicodeFromUtf8L( aUrl );      
+    }   
+    
+void CVBookmarkConverter::SetTitleL( const TDesC& aTitle )
+    {
+    delete iTitle;
+    iTitle = NULL;
+    iTitle = aTitle.AllocL();
+    }
+        
+void CVBookmarkConverter::SetTitleL( const TDesC8& aTitle, TBookmarkEncoding aEncoding )
+    {
+    delete iTitle;
+    iTitle = NULL;
+    
+    if ( aEncoding == EQuotedPrintable )
+        {
+        HBufC8* decodedData = DecodeQuotedPrintableLC( aTitle );
+        iTitle = CnvUtfConverter::ConvertToUnicodeFromUtf8L( *decodedData );
+        CleanupStack::PopAndDestroy( decodedData );
+        }
+    else
+        {
+        iTitle = CnvUtfConverter::ConvertToUnicodeFromUtf8L( aTitle );
+        }        
+    }
+    
+HBufC8* CVBookmarkConverter::DecodeQuotedPrintableLC( const TDesC8& aEncodedData )
+    {
+    TInt encodedLength = aEncodedData.Length();
+    
+    HBufC8* decodeBuffer = HBufC8::NewLC( encodedLength );
+    TPtr8 ptrDecodeBuffer = decodeBuffer->Des();
+    
+    TInt i(0);
+    while ( i < encodedLength )
+        {
+        TChar nextChar = aEncodedData[i++];
+        
+        if ( nextChar == '=' )
+            {
+            if ( i + 2 > encodedLength )
+                {
+                ptrDecodeBuffer.Append( '=' );
+                if ( i + 1 == encodedLength )
+                    {
+                    ptrDecodeBuffer.Append( aEncodedData[i++] );
+                    }     
+                }
+            else
+                {
+                TPtrC8 data = aEncodedData.Mid( i, 2 );
+                i += 2;    
+                
+                if ( data.Compare(KVBMKLinefeed) == 0 )
+                    {
+                    // Do nothing
+                    // '=' at the end of line is soft line break, not to be decoded
+                    }
+                else
+                    {
+                    TLex8 hexChar( data );
+                    TUint8 value( 0 );
+                    
+                    if ( hexChar.Val( value, EHex ) == KErrNone )
+                        {
+                        ptrDecodeBuffer.Append( TChar( value ) );
+                        }
+                    else
+                        {
+                        // Decoding failed, put the data at itself
+                        ptrDecodeBuffer.Append( '=' );
+                        ptrDecodeBuffer.Append( data );
+                        }    
+                    }
+                }
+            }
+        else
+            {
+            ptrDecodeBuffer.Append( nextChar );
+            }    
+        }
+        
+    return decodeBuffer;    
+    }
+
+void CVBookmarkConverter::SetInternetShortcutL( const TDesC& aInternetShortcut )
+    {
+    delete iInternetShortcut;
+    iInternetShortcut = NULL;
+    iInternetShortcut = aInternetShortcut.AllocL();
+    }
+    
+void CVBookmarkConverter::SetInternetShortcutL( const TDesC8& aInternetShortcut )
+    {
+    delete iInternetShortcut;
+    iInternetShortcut = NULL;
+    iInternetShortcut = CnvUtfConverter::ConvertToUnicodeFromUtf8L( aInternetShortcut );        
+    }   
+
+void CVBookmarkConverter::ExportDbItemL( CFavouritesItem& aItem )
+    {
+    if ( iTitle->Des().Length() > KFavouritesMaxName )
+        {
+        TPtrC title = iTitle->Des().Left( KFavouritesMaxName );
+        aItem.SetNameL( title );
+        }
+    else
+        {
+        aItem.SetNameL( *iTitle );
+        }
+        
+    if ( iUrl->Des().Length() > KFavouritesMaxUrl )
+        {
+        TPtrC url = iUrl->Des().Left( KFavouritesMaxUrl );
+        aItem.SetUrlL( url );
+        }
+    else
+        {
+        aItem.SetUrlL( *iUrl );
+        }   
+    }
+
+void CVBookmarkConverter::ImportDbItemL( const CFavouritesItem& aItem )
+    {
+    ResetL();
+    
+    if( aItem.Type() != CFavouritesItem::EItem )
+        {
+        User::Leave( KErrNotSupported );
+        }
+    
+    SetVersionL( KVBMKVer );
+    SetUrlL( aItem.Url() );
+    SetInternetShortcutL( aItem.Url() );
+    SetTitleL( aItem.Name() );
+    }
+
+void CVBookmarkConverter::ImportDbItemL( const CFolderItem& aItem )
+    {
+    ResetL();
+    
+    if( aItem.IsFolder() )
+        {
+        User::Leave( KErrNotSupported );
+        }
+    
+    SetVersionL( KVBMKVer );
+    SetUrlL( aItem.SourceUrl() );
+    SetInternetShortcutL( aItem.SourceUrl() );
+    SetTitleL( aItem.Name() );
+    }
+
+void CVBookmarkConverter::ExportVBookmarkL( CBufBase& aBuffer )
+    {
+    LOGGER_ENTERFN( "CVBookmarkConverter::ExportVBookmarkL" );
+    
+    iDesc = NULL;
+    iBuffer = &aBuffer;
+    iWriteBufPosition = 0;
+    iWriteBufSize = aBuffer.Size();     
+    
+    ExportL();  
+    iBuffer->ResizeL( iWriteBufPosition );    
+    
+    LOGGER_LEAVEFN( "CVBookmarkConverter::ExportVBookmarkL" );
+    }
+
+void CVBookmarkConverter::ExportVBookmarkL( TDes8& aBuffer )
+    {
+    iDesc = &aBuffer;
+    iBuffer = NULL;
+    
+    ExportL();
+    }
+
+void CVBookmarkConverter::ResetL()
+    {
+    SetVersionL( KEmptyString );
+    SetUrlL( KEmptyString );
+    SetTitleL( KEmptyString );    
+    SetInternetShortcutL( KEmptyString );    
+    }
+    
+void CVBookmarkConverter::ExportL()
+    {
+    LOGGER_ENTERFN( "CVBookmarkConverter::ExportL" );
+    
+    WriteMessageLineL( KVBMKBegin, KVBMKVbkm, KVBMKColon ); // Begin tag
+    
+    HBufC8* version = CnvUtfConverter::ConvertFromUnicodeToUtf8L( *iVersion );
+    CleanupStack::PushL( version );
+    WriteMessageLineL( KVBMKVersion, *version, KVBMKColon ); // Version
+    CleanupStack::PopAndDestroy( version );
+    
+    HBufC8* url = CnvUtfConverter::ConvertFromUnicodeToUtf8L( *iUrl );
+    CleanupStack::PushL( url );
+    // Url
+    WriteL( KVBMKUrl );
+    WriteL( KVBMKSemicolon );
+    WriteL( KVBMKCharset );
+    WriteL( KVBMKAssignment );
+    WriteL( KVBMKUtf8 );
+    WriteL( KVBMKColon );
+    WriteL( *url );
+    WriteL( KVBMKLinefeed );
+    CleanupStack::PopAndDestroy( url );
+    
+    HBufC8* title = CnvUtfConverter::ConvertFromUnicodeToUtf8L( *iTitle );
+    CleanupStack::PushL( title );
+    // Title
+    WriteL( KVBMKTitle );
+    WriteL( KVBMKSemicolon );
+    WriteL( KVBMKCharset );
+    WriteL( KVBMKAssignment );
+    WriteL( KVBMKUtf8 );
+    WriteL( KVBMKColon );
+    WriteL( *title );
+    WriteL( KVBMKLinefeed );
+    CleanupStack::PopAndDestroy( title );          
+
+    if( iInternetShortcut->Length() > 0 )
+        {
+        WriteEnvelopeL();
+        }
+        
+    WriteMessageLineL( KVBMKEnd, KVBMKVbkm, KVBMKColon ); // End tag
+    
+    LOGGER_LEAVEFN( "CVBookmarkConverter::ExportL" );       
+    }
+    
+TInt CVBookmarkConverter::ImportVBookmarkL( const TDesC8& aBuffer )
+    {
+    LOGGER_ENTERFN( "CVBookmarkConverter::ImportVBookmarkL" );
+    
+    ResetL();
+        
+    TInt error = KErrNone;
+    TInt position = 0;
+    TPtrC8 tag;
+    TPtrC8 value;
+    TPtrC8 properties;
+    error = ReadTagAndValue( aBuffer, position, tag, value, properties );
+    if( error != KErrNone )
+        {
+        LOGGER_WRITE_1( "ReadTagAndValue err: %d", error );
+        return error;
+        }
+        
+    if ( ( tag != KVBMKBegin ) || ( value != KVBMKVbkm ) )
+        {
+        LOGGER_WRITE( "Invalid tag" );
+        return KErrNotFound;
+        }
+    
+    while ( ( error = ReadTagAndValue( aBuffer, position, tag, value, properties ) ) == KErrNone )
+        {
+        // Version
+        if ( tag == KVBMKVersion )
+            {
+            SetVersionL( value );
+            }
+        
+        // Url
+        else if ( tag == KVBMKUrl )
+            {
+            SetUrlL( value );
+            }
+        
+        // Title
+        else if ( tag == KVBMKTitle )
+            {
+            TBookmarkEncoding encoding = Encoding( properties );
+            SetTitleL( value, encoding );
+            }
+            
+        // Beginning of envelope    
+        else if ( ( tag == KVBMKBegin ) && ( value == KVBMKEnv ) )
+            {
+            // Read the envelope, quit if error
+            error = ReadEnvelopeL( aBuffer, position );
+            if( error != KErrNone )
+                {
+                return error;
+                }
+            }       
+                
+        // End of Bookmark
+        else if ( ( tag == KVBMKEnd ) && ( value == KVBMKVbkm ) )
+            {
+            return error;
+            }
+        
+        else
+            {
+            // Unknown data, skip
+            }
+        }
+
+    LOGGER_LEAVEFN( "CVBookmarkConverter::ImportVBookmarkL" );      
+    return error;
+    }
+
+void CVBookmarkConverter::WriteMessageLineL( const TDesC8& aMsgLineTag,
+    const TDesC8& aMsgLineData, const TDesC8& aSeparator )
+    {
+    WriteL( aMsgLineTag );
+    WriteL( aSeparator );
+    WriteL( aMsgLineData );
+    WriteL( KVBMKLinefeed );
+    }
+
+TInt CVBookmarkConverter::ReadTagAndValue( const TDesC8& aBuffer, TInt& aPosition, 
+    TPtrC8& aTag, TPtrC8& aValue, TPtrC8& aProperties )
+    {
+    LOGGER_ENTERFN( "CVBookmarkConverter::ReadTagAndValue" );   
+    
+    TPtrC8 start = aBuffer.Mid( aPosition );
+    TInt delimeter = start.Find( KVBMKColon );
+    TInt linefeed = start.Find( KVBMKLinefeed );
+    TInt semicolon = start.Find( KVBMKSemicolon );
+    
+    
+    // Did we find a linefeed?
+    if ( linefeed == KErrNotFound )
+        {
+        // Check whether file ends without newline
+        if( aBuffer.Length() <= ( aPosition + start.Length() ) )
+            {
+            // Set linefeed at the end of the file
+            linefeed = start.Length();
+            }
+        else
+            { 
+            return KErrNotFound;
+            }
+        }
+
+    // Did we find a semicolon?
+    if ( semicolon != KErrNotFound )
+        {
+        // It must be before the delimeter (property identifiers reside in this block)
+        if ( semicolon >= delimeter || semicolon < 0 )
+            {
+            semicolon = KErrNotFound;
+            }
+        }
+    
+    // Did we find the delimeter
+    if( delimeter == KErrNotFound )
+        {
+        return KErrNotFound;
+        }
+
+    // Linefeed must reside behind the delimeter
+    if ( linefeed <= delimeter )
+        {
+        return KErrNotFound;
+        }
+    
+    aTag.Set( start.Left( semicolon != KErrNotFound ? semicolon : delimeter ) );
+    IgnoreSpaces( aTag );
+
+    // Extract value
+    aValue.Set( start.Mid( delimeter + 1, (linefeed - 1) - delimeter ) );
+    IgnoreSpaces( aValue );
+    
+    // Extract properties if found
+    if ( semicolon != KErrNotFound )
+        {
+        aProperties.Set( start.Mid( semicolon, delimeter - semicolon ) );
+        IgnoreSpaces( aProperties );
+        }
+    else
+        {
+        aProperties.Set( KVBMKNone() );
+        }     
+    
+    // update position
+    aPosition += ( linefeed + KVBMKLinefeed().Length() );
+    
+    LOGGER_LEAVEFN( "CVBookmarkConverter::ReadTagAndValue" );       
+    return KErrNone;
+    }
+    
+TInt CVBookmarkConverter::ReadEnvelopeL( const TDesC8& aBuffer, TInt& aPosition )
+    {
+    LOGGER_ENTERFN( "CVBookmarkConverter::ReadEnvelopeL" ); 
+        
+    TInt error = KErrNone;
+    TPtrC8 tag;
+    TPtrC8 value;
+    TPtrC8 properties;
+
+    while ( ( error = ReadTagAndValue( aBuffer, aPosition, tag, value, properties ) ) == KErrNone )
+        {
+        // End of Bookmark
+        if ( tag == KVBMKXIrmcUrl )
+            {
+            error = ReadAssignment( aBuffer, aPosition, tag, value );
+            if ( error != KErrNone )
+                {
+                return error;
+                }
+                
+            if ( tag == KVBMKInternetShortcut )
+                {
+                error = ReadAssignment( aBuffer, aPosition, tag, value );
+                if( error != KErrNone )
+                    {
+                    return error;
+                    }
+                
+                if ( tag == KVBMKUrl )
+                    {
+                    SetInternetShortcutL( value );
+                    }
+                else
+                    {
+                    return KErrNotFound;
+                    }               
+                }
+            else
+                {
+                return KErrNotFound;
+                }
+            }
+        
+        else if ( ( tag == KVBMKEnd ) && ( value == KVBMKEnv ) )
+            {
+            return error;
+            }
+        else
+            {
+            // Unknown data, skip
+            }
+        }
+
+    LOGGER_LEAVEFN( "CVBookmarkConverter::ReadEnvelopeL" );         
+    return error;
+    }
+
+TInt CVBookmarkConverter::ReadAssignment( const TDesC8& aBuffer,
+    TInt& aPosition, TPtrC8& aTag, TPtrC8& aValue )
+    {
+    LOGGER_ENTERFN( "CVBookmarkConverter::ReadAssignment" );    
+        
+    TPtrC8 start = aBuffer.Mid( aPosition );
+    TInt assignment = start.Find( KVBMKAssignment );
+    TInt linefeed = start.Find( KVBMKLinefeed );
+    
+    // Did we find the delimeter and the linefeed
+    if ( ( assignment == KErrNotFound) || ( linefeed == KErrNotFound ) )
+        {
+        return KErrNotFound;
+        }
+    // Linefeed must reside behind the delimeter
+    if ( linefeed <= assignment )
+        {
+        return KErrNotFound;
+        }
+    // Extract tag
+    aTag.Set( start.Left( assignment ) );
+    IgnoreSpaces( aTag );
+
+    // Extract value
+    aValue.Set( start.Mid( assignment + 1, ( linefeed - 1 ) - assignment ) );
+    IgnoreSpaces( aValue );
+    
+    // update position
+    aPosition += ( linefeed + KVBMKLinefeed().Length() );
+
+    LOGGER_LEAVEFN( "CVBookmarkConverter::ReadAssignment" );        
+    return KErrNone;
+    }
+
+void CVBookmarkConverter::WriteEnvelopeL()
+    {
+    WriteMessageLineL( KVBMKBegin, KVBMKEnv, KVBMKColon ); // Begin tag
+
+    // "X-IRMC-URL;QUOTED-PRINTABLE:="
+    WriteL( KVBMKXIrmcUrl );
+    WriteL( KVBMKSemicolon );
+    WriteL( KVBMKPrintable );
+    WriteL( KVBMKColon );
+    WriteL( KVBMKAssignment );
+    WriteL( KVBMKLinefeed );
+    
+    WriteMessageLineL( KVBMKInternetShortcut, KVBMKNone, KVBMKAssignment );
+    
+    HBufC8* internetShortcut = CnvUtfConverter::ConvertFromUnicodeToUtf8L( *iInternetShortcut );
+    CleanupStack::PushL( internetShortcut );
+    WriteMessageLineL( KVBMKUrl, *internetShortcut, KVBMKAssignment );
+    CleanupStack::PopAndDestroy( internetShortcut );
+    
+    WriteMessageLineL( KVBMKEnd, KVBMKEnv, KVBMKColon ); // End tag
+    }
+    
+void CVBookmarkConverter::WriteL( const TDesC8 &aData )
+    {
+    if ( iBuffer )
+        {
+        TInt newPosition = iWriteBufPosition + aData.Length();
+
+        if ( newPosition > iWriteBufSize )
+            {
+            TInt expandStep = newPosition - iWriteBufSize + 100;
+            iBuffer->ExpandL( iWriteBufSize, expandStep );
+            iWriteBufSize += expandStep;
+            }
+
+        iBuffer->Write( iWriteBufPosition, aData );
+        iWriteBufPosition = newPosition;
+        }
+    else if( iDesc )
+        {
+        iDesc->Append( aData );       
+        }
+    }
+    
+void CVBookmarkConverter::IgnoreSpaces( TPtrC8& aData )
+    {
+    TInt last = aData.Length() - 1;
+    
+    TInt begin;
+    for ( begin = 0; begin <= last; begin++ )
+        {
+        if ( !TChar( aData[begin] ).IsSpace() )
+            {
+            break;
+            }
+        }
+        
+    TInt end;   
+    for ( end = last; end >= 0; end-- )
+        {
+        if ( !TChar( aData[end] ).IsSpace() )
+            {
+            break;
+            }
+        }
+        
+    TInt length = end - begin + 1;  
+                
+    if ( ( begin != 0 || end != last ) && length > 0 )
+        {
+        TPtrC8 newData = aData.Mid( begin, length );
+        aData.Set( newData );
+        }
+    }
+    
+TBookmarkEncoding CVBookmarkConverter::Encoding( TPtrC8& aProperties )
+    {
+    TBookmarkEncoding encoding = ENoEncoding;
+    
+    TInt length = aProperties.Length();
+    
+    if ( aProperties.Length() > 0 )
+        {
+        if ( aProperties.Find( KVBMKPrintable ) > 0 )
+            {
+            encoding = EQuotedPrintable;
+            }    
+        }
+    
+    return encoding;
+    }