diff -r 8e6fa1719340 -r 4455192101e4 pushmtm/Plugins/PushContentHandler/CSIContentHandler.cpp --- a/pushmtm/Plugins/PushContentHandler/CSIContentHandler.cpp Wed Sep 01 12:31:04 2010 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1835 +0,0 @@ -/* -* Copyright (c) 2002 Nokia Corporation and/or its subsidiary(-ies). -* All rights reserved. -* This component and the accompanying materials are made available -* under the terms of the License "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: Implementation of CSIContentHandler. -* -*/ - - - -// INCLUDE FILES - -#include "CSIContentHandler.h" -#include "PushMtmUtil.h" -#include "PushMtmSettings.h" -#include "PushMtmLog.h" -#include "PushMtmUiDef.h" -#include "StringResourceReader.h" -#include "PushContentHandlerPanic.h" -#include "si_dict.h" -#include "PushContentHandlerUtils.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// CONSTANTS - -// si attributes / elements -_LIT8( KSi, "si" ); -_LIT8( KIndication, "indication" ); -_LIT8( KHrefAttrib, "href" ); -_LIT8( KSiIdAttrib, "si-id" ); -_LIT8( KCreatedAttrib, "created" ); -_LIT8( KExpiresAttrib, "si-expires" ); -_LIT8( KActionAttrib, "action" ); - -// action attribute literals -_LIT8( KDeleteAction, "delete" ); -_LIT8( KSignalNone, "signal-none" ); -_LIT8( KSignalLow, "signal-low" ); -_LIT8( KSignalMedium, "signal-medium" ); -_LIT8( KSignalHigh, "signal-high" ); - -_LIT( KSiTextContentType, "text/vnd.wap.si" ); - -const TInt KValidMaxEncodedDateTimeSize = 7; -const TInt KValidUTCLength = 20; // YYYY-MM-DDTHH:MM:SSZ -const TInt KValidUTCNumericals = 14; -const TInt KValidUTCYearBlockLength = 4; -const TInt KValidUTCOtherBlockLength = 2; -const TUint8 KAsciiZeroCharCode = 0x30; - -const TInt KValidTTimeMonthStart = 4; -const TInt KValidTTimeDayStart = 6; -const TInt KValidTTimeHourStart = 8; -const TInt KValidTTimeMinuteStart = 10; -const TInt KValidTTimeSecondStart = 12; -const TInt KValidTTimeBlockLength = 2; - -const TInt KValidTTimeLength = 14; // YYYYMMDDHHMMSS - -const TInt KNoOfDictArrays = 1; - -_LIT( KCharMinus, "-" ); -_LIT( KCharT, "T" ); -_LIT( KCharColon, ":" ); -_LIT( KCharZ, "Z" ); - -/// Conversion buffer size. -LOCAL_D const TInt KPushConversionBufferSize = 256; -/// Zero width non-breaking space character. -LOCAL_D const TUint16 KPushZeroWidthNbsp = 0xfeff; - -// ================= MEMBER FUNCTIONS ======================= - -// --------------------------------------------------------- -// CSIContentHandler::NewL -// --------------------------------------------------------- -// -CSIContentHandler* CSIContentHandler::NewL() - { - PUSHLOG_ENTERFN("CSIContentHandler::NewL") - - CSIContentHandler* self = new (ELeave) CSIContentHandler; - CleanupStack::PushL( self ); - self->ConstructL(); - CleanupStack::Pop( self ); - - PUSHLOG_LEAVEFN("CSIContentHandler::NewL") - return self; - } - -// --------------------------------------------------------- -// CSIContentHandler::~CSIContentHandler -// --------------------------------------------------------- -// -CSIContentHandler::~CSIContentHandler() - { - PUSHLOG_ENTERFN("CSIContentHandler::~CSIContentHandler") - - Cancel(); - delete iHrefBuf; - delete iSiIdBuf; - delete iData; - delete iCharacterSetConverter; - iCharacterSetConverter = NULL; - delete iCharacterSetsAvailable; - iCharacterSetsAvailable = NULL; - - PUSHLOG_LEAVEFN("CSIContentHandler::~CSIContentHandler") - } - -// --------------------------------------------------------- -// CSIContentHandler::CSIContentHandler -// --------------------------------------------------------- -// -CSIContentHandler::CSIContentHandler() -: CPushContentHandlerBase(), - iSavedMsgId( KMsvNullIndexEntryId ), - iPushMsgAction( KErrNotFound ), - iExpiresTime( Time::NullTTime() ), - iCreatedTime( Time::NullTTime() ) - { - } - -// --------------------------------------------------------- -// CSIContentHandler::ConstructL -// --------------------------------------------------------- -// -void CSIContentHandler::ConstructL() - { - PUSHLOG_ENTERFN("CSIContentHandler::ConstructL") - - CPushContentHandlerBase::ConstructL(); - // Added to Active Scheduler. - - PUSHLOG_LEAVEFN("CSIContentHandler::ConstructL") - } - -// --------------------------------------------------------- -// CSIContentHandler::CollectGarbageL -// --------------------------------------------------------- -// -void CSIContentHandler::CollectGarbageL() - { - PUSHLOG_ENTERFN("CSIContentHandler::CollectGarbageL") - - DoCollectGarbageL(); - - //Ready. - iState = EFilteringAndParsing; - IdleComplete(); - - PUSHLOG_LEAVEFN("CSIContentHandler::CollectGarbageL") - } - -// --------------------------------------------------------- -// CSIContentHandler::ParsePushMsgL -// Note that cXML parser dosn't do any validation! -// --------------------------------------------------------- -// -void CSIContentHandler::ParsePushMsgL() - { - PUSHLOG_ENTERFN("CSIContentHandler::ParsePushMsgL") - - TPtrC8 bodyPtr; - iMessage->GetMessageBody( bodyPtr ); - // If there is no body in the message leave with an error - if ( bodyPtr.Size() == 0 ) - { - PUSHLOG_WRITE("CSIContentHandler::ParsePushMsgL: Empty body") - User::Leave( KErrCorrupt ); - } - - // Get content type. It will tell us wheather the msg body is encoded or - // textual. - TPtrC contentType; - iMessage->GetContentType( contentType ); - PUSHLOG_WRITE_FORMAT("CSIContentHandler::ParsePushMsgL: HTTP header - Content type <%S>",&contentType); - - /* - TPtrC8 encodingPtr; - TBool encodingFound = iMessage->GetHeaderField - ( EHttpContentEncoding, encodingPtr ); - #ifdef __TEST_LOG__ - TBuf<64> encodingBuf; - encodingBuf.Copy( encodingPtr ); - PUSHLOG_WRITE_FORMAT(" HTTP header - Content encoding <%S>",&encodingBuf); - #endif // __TEST_LOG__ - */ - - // Add SI dictionary. - NW_WBXML_Dictionary_t* dictArray[ KNoOfDictArrays ] = - { (NW_WBXML_Dictionary_t*)&NW_SI_WBXMLDictionary }; - - NW_Status_t stat = NW_STAT_SUCCESS; - - RWbxmlDictionary wbxmlDict; - wbxmlDict.InitializeL( KNoOfDictArrays, dictArray ); - CleanupClosePushL( wbxmlDict ); - - NW_TinyDom_Handle_t domHandle; - NW_Byte* buffer = (NW_Byte*)bodyPtr.Ptr(); - NW_Int32 length = (NW_Int32)bodyPtr.Size(); - // Let's use the content type now. - NW_Bool encoded = ( contentType.CompareF( KSiTextContentType ) == 0 ) ? - NW_FALSE : NW_TRUE; - // SI public identifier. - NW_Uint32 publicID = NW_SI_PublicId; - NW_Bool extTNotStringTable = NW_FALSE; - NW_DOM_NodeType_t type = 0; - /********************************** - * Root of DOM - ***********************************/ - CDocumentTreeOwner* docTreeOwner = new (ELeave) CDocumentTreeOwner; - CleanupStack::PushL( docTreeOwner ); - NW_DOM_DocumentNode_t* domNode = NW_DOM_DocumentNode_BuildTree - ( - &domHandle, - buffer, - length, - encoded, - publicID, - extTNotStringTable - ); - if (!domNode) - { - PUSHLOG_WRITE("CSIContentHandler::ParsePushMsgL: domNode is Null") - } - User::LeaveIfNull( domNode ); - PUSHLOG_WRITE("CSIContentHandler::ParsePushMsgL: domNode is not Null") // to be deleted - // Let domNode be on the Cleanup Stack. - docTreeOwner->SetDocTree( domNode ); - - // It must be a document node. - type = NW_DOM_Node_getNodeType( domNode ); - if ( type != NW_DOM_DOCUMENT_NODE ) - { - PUSHLOG_WRITE_FORMAT("CSIContentHandler::ParsePushMsgL: Not Document node <%d>",type) - User::Leave( KErrArgument ); - } - - // Get character encoding (NW_Uint32) - iCharEncoding = NW_DOM_DocumentNode_getCharacterEncoding( domNode ); - PUSHLOG_WRITE_FORMAT("CSIContentHandler::ParsePushMsgL: Doc char encoding <%x>",iCharEncoding) - - /********************************** - * ELEMENT si - ***********************************/ - // Get the first element of the document that must be an si. - // first make sure if there any children in the dom tree, otherwise we will PANIC(in NW_DOM_DocumentNode_getDocumentElement) and crash WatcherMainThread. - TBool domNodeHasChildNodes = EFalse; - domNodeHasChildNodes = NW_DOM_Node_hasChildNodes( domNode ); - PUSHLOG_WRITE_FORMAT("CSIContentHandler::ParsePushMsgL: check if Dom tree has node <%d>", domNodeHasChildNodes) - if (!domNodeHasChildNodes) - { - PUSHLOG_WRITE("CSIContentHandler::ParsePushMsgL: No SI element present in the dom tree. Message corrupted.") - User::Leave( KErrCorrupt ); - } - - PUSHLOG_WRITE("CSIContentHandler::ParsePushMsgL: before calling getDocumentElement") - NW_DOM_ElementNode_t* siElement = - NW_DOM_DocumentNode_getDocumentElement( domNode ); - PUSHLOG_WRITE("CSIContentHandler::ParsePushMsgL: after calling getDocumentElement") - if (!siElement) - { - PUSHLOG_WRITE("CSIContentHandler::ParsePushMsgL: siElement is Null") - } - PUSHLOG_WRITE("CSIContentHandler::ParsePushMsgL: siElement is not Null, before leaving") - User::LeaveIfNull( siElement ); - PUSHLOG_WRITE("CSIContentHandler::ParsePushMsgL: siElement is not Null, after leaving if siElement is null") - - type = NW_DOM_Node_getNodeType( siElement ); - - CStringOwner* stringOwner = new (ELeave) CStringOwner; - CleanupStack::PushL( stringOwner ); - - NW_String_t* name = NW_String_new(); - User::LeaveIfNull( name ); - // Let name be on the Cleanup Stack. - stringOwner->SetString( name ); - stat = NW_DOM_Node_getNodeName( siElement, name ); - User::LeaveIfError( NwxStatusToErrCode( stat ) ); - NW_Byte* nameBuf = NW_String_getStorage( name ); - NW_Uint16 nameLen = NW_String_getCharCount( name, iCharEncoding ); - TPtrC8 namePtr( nameBuf, nameLen ); - - // Now comes the validity check. - if ( type != NW_DOM_ELEMENT_NODE || namePtr.CompareF( KSi ) != 0 ) - { - PUSHLOG_WRITE_FORMAT("CSIContentHandler::ParsePushMsgL: Not si element node <%d>",type) - User::Leave( KErrArgument ); - } - - CleanupStack::PopAndDestroy( stringOwner ); // stringOwner - - /********************************** - * ELEMENT indication - ***********************************/ - if ( NW_DOM_Node_hasChildNodes( siElement ) ) - { - NW_DOM_Node_t* node = NW_DOM_Node_getFirstChild( siElement ); - if (!node) - { - PUSHLOG_WRITE("CSIContentHandler::ParsePushMsgL: no si child nodes!") - } - User::LeaveIfNull( node ); - - // Find the indication element. - TBool indicationFound = EFalse; - do { - type = NW_DOM_Node_getNodeType( node ); - - CStringOwner* stringOwner = new (ELeave) CStringOwner; - CleanupStack::PushL( stringOwner ); - - NW_String_t* name = NW_String_new(); - User::LeaveIfNull( name ); - stringOwner->SetString( name ); - stat = NW_DOM_Node_getNodeName( node, name ); - PUSHLOG_WRITE_FORMAT("CSIContentHandler::ParsePushMsgL: getNodeName ErrCode: %d", NwxStatusToErrCode( stat )) - User::LeaveIfError( NwxStatusToErrCode( stat ) ); - NW_Byte* nameBuf = NW_String_getStorage( name ); - NW_Uint16 nameLen = NW_String_getCharCount( name, - iCharEncoding ); - TPtrC8 namePtr( nameBuf, nameLen ); - - if ( type == NW_DOM_ELEMENT_NODE && - namePtr.CompareF( KIndication ) == 0 ) - { - // We found the indication element. Parse it. - PUSHLOG_WRITE("CSIContentHandler::ParsePushMsgL: indication under si found.") - indicationFound = ETrue; - NW_DOM_ElementNode_t* indicationElement = - REINTERPRET_CAST( NW_DOM_ElementNode_t*, node ); - ParseIndicationL( *indicationElement ); - } - - CleanupStack::PopAndDestroy( stringOwner ); // stringOwner - - if ( !indicationFound ) - { - // Iterate next. - node = NW_DOM_Node_getNextSibling( node ); - if ( !node ) - { - PUSHLOG_WRITE("CSIContentHandler::ParsePushMsgL: No more sibling.") - break; - } - } - - } while ( !indicationFound ); - } - - // Cleanup. - CleanupStack::PopAndDestroy( 2, &wbxmlDict ); // docTreeOwner, wbxmlDict - - if ( !ActionFlag() ) - { - // default if no action explicitly stated - iPushMsgAction = CSIPushMsgEntry::ESIPushMsgSignalMedium; - SetActionFlag( ETrue ); - PUSHLOG_WRITE_FORMAT("CSIContentHandler::ParsePushMsgL: Defaulting to ActionFlag: %d",iPushMsgAction) - } - - iState = EProcessing; - IdleComplete(); - - PUSHLOG_LEAVEFN("CSIContentHandler::ParsePushMsgL") - } - -// --------------------------------------------------------- -// CSIContentHandler::ParseIndicationL -// --------------------------------------------------------- -// -void CSIContentHandler::ParseIndicationL( NW_DOM_ElementNode_t& aIndication ) - { - PUSHLOG_ENTERFN("CSIContentHandler::ParseIndicationL") - - NW_Status_t stat = NW_STAT_SUCCESS; - NW_DOM_NodeType_t type = 0; - - if ( NW_DOM_ElementNode_hasAttributes( &aIndication ) ) - { - NW_DOM_AttributeListIterator_t attrIter; - stat = NW_DOM_ElementNode_getAttributeListIterator - ( &aIndication, &attrIter ); - PUSHLOG_WRITE_FORMAT("CSIContentHandler::ParseIndicationL: getAttribListIter ErrCode: %d", NwxStatusToErrCode( stat )) - User::LeaveIfError( NwxStatusToErrCode( stat ) ); - - NW_DOM_AttributeHandle_t attrHandle; - while ( NW_DOM_AttributeListIterator_getNextAttribute - ( &attrIter, &attrHandle ) == NW_STAT_WBXML_ITERATE_MORE ) - { - ParseIndAttributeL( attrHandle ); - } - } - - /********************************** - * PCDATA of ELEMENT indication - ***********************************/ - if ( NW_DOM_Node_hasChildNodes( &aIndication ) ) - { - NW_DOM_TextNode_t* textNode = - NW_DOM_Node_getFirstChild( &aIndication ); - User::LeaveIfNull( textNode ); - - type = NW_DOM_Node_getNodeType( textNode ); - if ( type != NW_DOM_TEXT_NODE ) - { - PUSHLOG_WRITE_FORMAT("CSIContentHandler::ParseIndicationL: Not text node <%d>",type) - User::Leave( KErrArgument ); - } - - ParseTextL( *textNode ); - } - - PUSHLOG_LEAVEFN("CSIContentHandler::ParseIndicationL") - } - -// --------------------------------------------------------- -// CSIContentHandler::ParseIndAttributeL -// --------------------------------------------------------- -// -void CSIContentHandler::ParseIndAttributeL( NW_DOM_AttributeHandle_t& - aAttrHandle ) - { - PUSHLOG_ENTERFN("CSIContentHandler::ParseIndAttributeL") - - NW_Status_t stat = NW_STAT_SUCCESS; - - CStringOwner* stringOwner = new (ELeave) CStringOwner; - CleanupStack::PushL( stringOwner ); - - NW_String_t* attrName = NW_String_new(); - User::LeaveIfNull( attrName ); - stringOwner->SetString( attrName ); - - // Get the name of the attribute. - stat = NW_DOM_AttributeHandle_getName( &aAttrHandle, attrName ); - User::LeaveIfError( NwxStatusToErrCode( stat ) ); - NW_Byte* attrNameBuf = NW_String_getStorage( attrName ); - NW_Uint16 attrNameLen = NW_String_getCharCount( attrName, iCharEncoding ); - TPtrC8 attrNamePtr( attrNameBuf, attrNameLen ); - - if ( attrNamePtr.CompareF( KCreatedAttrib ) == 0 ) - { - if ( CreatedFlag() ) - { - PUSHLOG_WRITE(" created redefinition") - User::Leave( KErrCorrupt ); - } - else - { - TBool gotDate = AttributeToTTimeL( aAttrHandle, iCreatedTime ); - SetCreatedFlag( gotDate ); - PUSHLOG_WRITE_FORMAT(" iCreatedTime set %d",gotDate?1:0) - } - } - else if ( attrNamePtr.CompareF( KHrefAttrib ) == 0 ) - { - if ( HrefFlag() ) - { - PUSHLOG_WRITE(" href redefinition") - User::Leave( KErrCorrupt ); - } - else - { - CStringOwner* stringOwner = new (ELeave) CStringOwner; - CleanupStack::PushL( stringOwner ); - - NW_String_t* val = NW_String_new(); - User::LeaveIfNull( val ); - stringOwner->SetString( val ); - stat = NW_DOM_AttributeHandle_getValue( &aAttrHandle, val ); - if ( stat != NW_STAT_DOM_NO_STRING_RETURNED ) - { - User::LeaveIfError( NwxStatusToErrCode( stat ) ); - NW_Byte* storage = NW_String_getStorage( val ); - NW_Uint16 length = NW_String_getCharCount( val, - iCharEncoding ); - if ( length == 0 ) - { - // Zero length href attribute is considered as missing. - PUSHLOG_WRITE(" Zero length HrefFlag"); - } - else - { - TPtrC8 hrefPtr( storage, length ); - HBufC* tempHrefBuf = HBufC::NewMaxL( length ); - // No leavable after it!!! until... - tempHrefBuf->Des().Copy( hrefPtr ); - iHrefBuf = tempHrefBuf; // ...until here. - SetHrefFlag( ETrue ); - PUSHLOG_WRITE_FORMAT(" HrefFlag set <%S>",iHrefBuf); - } - } - - CleanupStack::PopAndDestroy( stringOwner ); // stringOwner - } - } - else if ( attrNamePtr.CompareF( KExpiresAttrib ) == 0 ) - { - if ( ExpiresFlag() ) - { - PUSHLOG_WRITE(" expires redefinition") - User::Leave( KErrCorrupt ); - } - else - { - TBool gotDate = AttributeToTTimeL( aAttrHandle, iExpiresTime ); - SetExpiresFlag( gotDate ); - PUSHLOG_WRITE_FORMAT(" iExpiresTime set %d",gotDate?1:0) - } - } - else if ( attrNamePtr.CompareF( KSiIdAttrib ) == 0 ) - { - if ( SiIdFlag() ) - { - PUSHLOG_WRITE(" si-id redefinition") - User::Leave( KErrCorrupt ); - } - else - { - // It is expected to be String. - CStringOwner* stringOwner = new (ELeave) CStringOwner; - CleanupStack::PushL( stringOwner ); - - NW_String_t* val = NW_String_new(); - User::LeaveIfNull( val ); - stringOwner->SetString( val ); - stat = NW_DOM_AttributeHandle_getValue( &aAttrHandle, val ); - User::LeaveIfError( NwxStatusToErrCode( stat ) ); - NW_Byte* storage = NW_String_getStorage( val ); - NW_Uint16 length = NW_String_getCharCount( val, iCharEncoding ); - TPtrC8 siidPtr( storage, length ); - - iSiIdBuf = HBufC::NewMaxL( siidPtr.Length() ); - iSiIdBuf->Des().Copy( siidPtr ); - SetSiIdFlag( ETrue ); - PUSHLOG_WRITE_FORMAT(" SiIdFlag set <%S>",iSiIdBuf) - - CleanupStack::PopAndDestroy( stringOwner ); // stringOwner - } - } - else if ( attrNamePtr.CompareF( KActionAttrib ) == 0 ) - { - if ( ActionFlag() ) - { - PUSHLOG_WRITE(" action redefinition") - User::Leave( KErrCorrupt ); - } - else - { - // It is expected to be String. - CStringOwner* stringOwner = new (ELeave) CStringOwner; - CleanupStack::PushL( stringOwner ); - - NW_String_t* val = NW_String_new(); - User::LeaveIfNull( val ); - stringOwner->SetString( val ); - stat = NW_DOM_AttributeHandle_getValue( &aAttrHandle, val ); - User::LeaveIfError( NwxStatusToErrCode( stat ) ); - NW_Byte* storage = NW_String_getStorage( val ); - NW_Uint16 length = NW_String_getCharCount( val, iCharEncoding ); - TPtrC8 actionPtr( storage, length ); - - iPushMsgAction = ConvertActionString( actionPtr ); - SetActionFlag( ETrue ); - PUSHLOG_WRITE_FORMAT(" ActionFlag: %d",iPushMsgAction) - - CleanupStack::PopAndDestroy( stringOwner ); // stringOwner - } - } - else - { - __ASSERT_DEBUG( EFalse, - ContHandPanic( EPushContHandPanUnexpSiToken ) ); - } - - CleanupStack::PopAndDestroy( stringOwner ); // stringOwner - - PUSHLOG_LEAVEFN("CSIContentHandler::ParseIndAttributeL") - } - -// --------------------------------------------------------- -// CSIContentHandler::ParseTextL -// --------------------------------------------------------- -// -void CSIContentHandler::ParseTextL( NW_DOM_TextNode_t& aTextNode ) - { - PUSHLOG_ENTERFN("CSIContentHandler::ParseTextL") - - if ( DataFlag() ) - { - PUSHLOG_WRITE(" Data flag already set.") - } - else - { - CStringOwner* stringOwner = new (ELeave) CStringOwner; - CleanupStack::PushL( stringOwner ); - - NW_String_t* data = NW_String_new(); - User::LeaveIfNull( data ); - stringOwner->SetString( data ); - NW_Status_t stat = NW_STAT_SUCCESS; - stat = NW_DOM_TextNode_getData( &aTextNode, data ); - User::LeaveIfError( NwxStatusToErrCode( stat ) ); - - HBufC16* ucs2buffer = ConvertToUnicodeL( *data, iCharEncoding ); - // Be careful: ucs2buffer is not on the CleanupStack! - __ASSERT_DEBUG( ucs2buffer != 0, ContHandPanic( EPushContHandPanNullUcs2Buf ) ); - - TPtrC16 ucs2ptrC( *ucs2buffer ); - if ( ucs2ptrC.Length() == 0 ) - { - // Zero length data is considered as nothing. - PUSHLOG_WRITE(" Zero length Data"); - } - else - { - PUSHLOG_WRITE_FORMAT(" Data: <%S>",&ucs2ptrC); - - #ifdef __TEST_LOG__ - // Write out each unicode character identifier - TInt length = ucs2ptrC.Length(); - for (TInt logI=0;logI currChar; - currChar.Copy( ucs2ptrC.Mid( logI, /*aLength*/1 ) ); - PUSHLOG_WRITE_FORMAT2(" 0x%x %S",currChar[0],&currChar); - } - #endif // __TEST_LOG__ - - iData = ucs2buffer; // Ownership transferred. - ucs2buffer = NULL; - SetDataFlag( ETrue ); - } - - CleanupStack::PopAndDestroy( stringOwner ); - } - - PUSHLOG_LEAVEFN("CSIContentHandler::ParseTextL") - } - -// --------------------------------------------------------- -// CSIContentHandler::ConvertToUnicodeL -// --------------------------------------------------------- -// -HBufC16* CSIContentHandler::ConvertToUnicodeL( const TDesC8& aSrc, TUint aCharSetId ) - { - PUSHLOG_ENTERFN("CSIContentHandler::ConvertToUnicodeL"); - - __ASSERT_DEBUG( aCharSetId != 0, ContHandPanic( EPushContHandPanNullCharSetId ) ); - - InitialiseCharacterSetConverterL(); - - HBufC16* ucs2buffer = NULL; // The return value. - TBool resultOnStack = EFalse; - - #ifdef __TEST_LOG__ - // Write out the original 8-bit buffer - TInt origiLength = aSrc.Length(); - for (TInt origiLogI=0;origiLogI currChar; // Only 16-bit buffer can be written out. - currChar.Copy( aSrc.Mid( origiLogI, /*aLength*/1 ) ); - PUSHLOG_WRITE_FORMAT2(" 0x%x %S",currChar[0],&currChar); - } - #endif // __TEST_LOG__ - - // Result - HBufC16* buffer = HBufC16::NewLC( KPushConversionBufferSize ); - PUSHLOG_WRITE(" buffer allocated"); - TPtr16 ptr( buffer->Des() ); - - // Prepare conversion for the given charset ID. - RFs& fs = iMsvSession->FileSession(); - iCharacterSetConverter->PrepareToConvertToOrFromL - ( aCharSetId, *iCharacterSetsAvailable, fs ); - PUSHLOG_WRITE(" PrepareToConvertToOrFromL OK"); - - TInt state = 0; - TInt remaining = iCharacterSetConverter->ConvertToUnicode( ptr, aSrc, state ); - PUSHLOG_WRITE_FORMAT(" remaining: %d",remaining); - while ( remaining >= 0 ) - { - if ( ucs2buffer == NULL ) - { - ucs2buffer = HBufC::NewLC( ptr.Length() ); - resultOnStack = ETrue; - } - else - { - __ASSERT_DEBUG( resultOnStack, - ContHandPanic( EPushContHandPanSiResNotOnStack ) ); - // This may change the address of ucs2buffer so we need to put - // it on the cleanup stack again!! - ucs2buffer = ucs2buffer->ReAllocL - ( ucs2buffer->Length() + ptr.Length() ); - CleanupStack::Pop(); // old ucs2buffer - CleanupStack::PushL( ucs2buffer ); // possibly new copy - PUSHLOG_WRITE(" ucs2buffer reallocated"); - } - TPtr16 ucs2ptr( ucs2buffer->Des() ); - ucs2ptr.Append( ptr ); - if ( remaining > 0 ) - { - // Try to convert all remaining characters. - ptr.Zero(); - remaining = iCharacterSetConverter->ConvertToUnicode - ( ptr, aSrc.Right( remaining ), state ); - PUSHLOG_WRITE_FORMAT(" remaining: %d",remaining); - } - else - { - PUSHLOG_WRITE(" break"); - break; - } - } - - if ( resultOnStack ) - { - CleanupStack::Pop(); // ucs2buffer - resultOnStack = EFalse; - } - - // ucs2buffer is not on the CleanupStack! - - CleanupStack::PopAndDestroy( buffer ); // buffer - - if ( ucs2buffer == NULL ) - { - PUSHLOG_WRITE(" NULL ucs2buffer - allocating an empty buf"); - ucs2buffer = KNullDesC().AllocL(); - } - else - { - // Check if first character is a Zero-width nbsp. - TPtrC16 ucs2ptrC( *ucs2buffer ); - if ( ucs2ptrC.Length() >= 1 && ucs2ptrC[0] == KPushZeroWidthNbsp ) - { - // First character is a Zero-width NBSP. This character is used as - // BOM in some encodings and should not be present at this point. - // But we are tolerant and remove it. - // (Not expecting big-endianness here.) - HBufC16* temp = ucs2buffer; - CleanupStack::PushL( temp ); - ucs2buffer = ucs2ptrC.Mid( 1 ).AllocL(); - CleanupStack::PopAndDestroy( temp ); // temp - PUSHLOG_WRITE(" BOM removed"); - } - else - { - PUSHLOG_WRITE(" No BOM"); - } - } - - - PUSHLOG_LEAVEFN("CSIContentHandler::ConvertToUnicodeL"); - return ucs2buffer; - } - -// --------------------------------------------------------- -// CSIContentHandler::ConvertToUnicodeL -// --------------------------------------------------------- -// -HBufC16* CSIContentHandler::ConvertToUnicodeL - ( NW_String_t& aString, NW_Uint32 aCharEncoding ) - { - PUSHLOG_ENTERFN("CSIContentHandler::ConvertToUnicodeL"); - - /* As cXmlLibrary does, we support only the following charsets: - #define HTTP_iso_10646_ucs_2 0x03E8 - #define HTTP_iso_8859_1 0x04 - #define HTTP_us_ascii 0x03 - #define HTTP_utf_8 0x6A - #define HTTP_utf_16 1015 - */ - TUint id = 0; - if ( aCharEncoding == HTTP_iso_10646_ucs_2 ) - { - id = KCharacterSetIdentifierUcs2; - PUSHLOG_WRITE(" KCharacterSetIdentifierUcs2") - } - else if ( aCharEncoding == HTTP_iso_8859_1 ) - { - id = KCharacterSetIdentifierIso88591; - PUSHLOG_WRITE(" KCharacterSetIdentifierIso88591") - } - else if ( aCharEncoding == HTTP_us_ascii ) - { - id = KCharacterSetIdentifierAscii; - PUSHLOG_WRITE(" KCharacterSetIdentifierAscii") - } - else if ( aCharEncoding == HTTP_utf_8 ) - { - id = KCharacterSetIdentifierUtf8; - PUSHLOG_WRITE(" KCharacterSetIdentifierUtf8") - } - else if ( aCharEncoding == HTTP_utf_16 ) // No such in CharConv.h - { - id = KCharacterSetIdentifierUcs2; - PUSHLOG_WRITE(" KCharacterSetIdentifierUcs2") - } - else - { - id = KCharacterSetIdentifierUtf8; // Defaulting to UTF-8 - PUSHLOG_WRITE(" DEFAULTING to KCharacterSetIdentifierUtf8"); - } - - PUSHLOG_WRITE_FORMAT(" id: 0x%x",id); - __ASSERT_DEBUG( id != 0, ContHandPanic( EPushContHandPanNullCharSetId ) ); - - // Source - PUSHLOG_WRITE_FORMAT(" Storage: 0x%x",NW_String_getStorage(&aString)); - PUSHLOG_WRITE_FORMAT(" Byte count: %d",NW_String_getByteCount(&aString)-1); - - // We will use NW_String_getByteCount(&aString)-1 as size, because - // NW_String_getByteCount(&aString) includes NULL terminator. - const TPtrC8 src( NW_String_getStorage(&aString), - NW_String_getByteCount(&aString)-1 ); - HBufC16* ucs2buffer = ConvertToUnicodeL( src, id ); - - PUSHLOG_LEAVEFN("CSIContentHandler::ConvertToUnicodeL"); - return ucs2buffer; - } - -// --------------------------------------------------------- -// CSIContentHandler::InitialiseCharacterSetConverterL -// --------------------------------------------------------- -// -void CSIContentHandler::InitialiseCharacterSetConverterL() - { - PUSHLOG_ENTERFN("CSIContentHandler::InitialiseCharacterSetConverterL") - - iCharacterSetConverter = CCnvCharacterSetConverter::NewL(); - - RFs& fs = iMsvSession->FileSession(); - iCharacterSetsAvailable = - CCnvCharacterSetConverter::CreateArrayOfCharacterSetsAvailableL( fs ); - - PUSHLOG_LEAVEFN("CSIContentHandler::InitialiseCharacterSetConverterL") - } - -// --------------------------------------------------------- -// CSIContentHandler::ConvertActionString -// --------------------------------------------------------- -// -TUint CSIContentHandler::ConvertActionString - ( const TDesC8& aActionString ) const - { - const TInt KMatchFound = 0; - - // set to default signal value (to rid ourselves of build warning) - TUint actionValue = CSIPushMsgEntry::ESIPushMsgSignalMedium; - - if ( aActionString.Compare( KDeleteAction ) == KMatchFound ) - { - actionValue = CSIPushMsgEntry::ESIPushMsgDelete; - } - else if ( aActionString.Compare( KSignalNone ) == KMatchFound ) - { - actionValue = CSIPushMsgEntry::ESIPushMsgSignalNone; - } - else if ( aActionString.Compare( KSignalLow ) == KMatchFound ) - { - actionValue = CSIPushMsgEntry::ESIPushMsgSignalLow; - } - else if ( aActionString.Compare( KSignalMedium ) == KMatchFound ) - { - actionValue = CSIPushMsgEntry::ESIPushMsgSignalMedium; - } - else if ( aActionString.Compare( KSignalHigh ) == KMatchFound ) - { - actionValue = CSIPushMsgEntry::ESIPushMsgSignalHigh; - } - - return actionValue; - } - -// --------------------------------------------------------- -// CSIContentHandler::SetSIPushMsgEntryFieldsL -// --------------------------------------------------------- -// -void CSIContentHandler::SetSIPushMsgEntryFieldsL( CSIPushMsgEntry& - aSIPushMsgEntry ) - { - PUSHLOG_ENTERFN("CSIContentHandler::SetSIPushMsgEntryFieldsL") - - if ( SiIdFlag() || HrefFlag() ) - { - if ( SiIdFlag() && ( HrefFlag() == EFalse ) ) - { - // Message has only si-id but no href. - aSIPushMsgEntry.SetIdL( *iSiIdBuf ); - } - else if ( HrefFlag() && ( SiIdFlag() == EFalse ) ) - { - // If message has no si-id but does have a href, use href as si-id. - aSIPushMsgEntry.SetIdL( *iHrefBuf ); - aSIPushMsgEntry.SetUrlL( *iHrefBuf ); - } - else - { - // Use si-id and href as is. - aSIPushMsgEntry.SetIdL( *iSiIdBuf ); - aSIPushMsgEntry.SetUrlL( *iHrefBuf ); - } - } - - __ASSERT_DEBUG( ActionFlag(), - ContHandPanic( EPushContHandPanUnspecSiAction ) ); - if ( ActionFlag() ) - { - aSIPushMsgEntry.SetAction( iPushMsgAction ); - } - else // default if no action explicitly stated - { - aSIPushMsgEntry.SetAction( CSIPushMsgEntry::ESIPushMsgSignalMedium ); - } - - // uses default null time value if no explicit date set in message - aSIPushMsgEntry.SetCreated( iCreatedTime ); - aSIPushMsgEntry.SetExpires( iExpiresTime ); - - // PCDATA (text) from message - if ( DataFlag() ) - { - aSIPushMsgEntry.SetTextL( *iData ); - } - - TPtrC8 msgHeaderPtr; - iMessage->GetHeader( msgHeaderPtr ); - aSIPushMsgEntry.SetHeaderL( msgHeaderPtr ); - - // Get server address. - TPtrC8 srvAddress; - if ( iMessage->GetServerAddress( srvAddress ) ) - { - aSIPushMsgEntry.SetFromL( srvAddress ); - } - - // First line in Inbox: TMsvEntry::iDetails. - if ( srvAddress.Length() == 0 ) - { - // Read from resource. - HBufC* details = - iStrRscReader->AllocReadResourceLC( R_PUSHMISC_UNK_SENDER ); - aSIPushMsgEntry.SetMsgDetailsL( *details ); - CleanupStack::PopAndDestroy( details ); - } - else - { - // Convert the "From" information to the format required by the UI - // spec and then decode it. - HBufC* details = iWapPushUtils->ConvertDetailsL( srvAddress ); - CleanupStack::PushL( details ); - HBufC* convertedFrom = - CPushMtmUtil::ConvertUriToDisplayFormL( *details ); - CleanupStack::PushL( convertedFrom ); - // - aSIPushMsgEntry.SetMsgDetailsL( *convertedFrom ); - // - CleanupStack::PopAndDestroy( 2, details ); // convertedFrom, details - } - - // Second line in Inbox: TMsvEntry::iDescription. - if ( DataFlag() ) - { - // Display SI message. - aSIPushMsgEntry.SetMsgDescriptionL( *iData ); - } - else - { - // Display URL. - __ASSERT_DEBUG( HrefFlag(), - ContHandPanic( EPushContHandPanUnspecSiHref ) ); - const TPtrC url = aSIPushMsgEntry.Url(); - HBufC* convertedUrl = CPushMtmUtil::ConvertUriToDisplayFormL( url ); - CleanupStack::PushL( convertedUrl ); - // - aSIPushMsgEntry.SetMsgDescriptionL( *convertedUrl ); - // - CleanupStack::PopAndDestroy( convertedUrl ); // convertedUrl - } - - // ******** Push MTM specific processing ********* - - /* - * Unfortunately in CPushMsgEntryBase there is no such functionality - * with which we can reach TMsvEntry as non-const, but we have to - * modify the entry's iMtmData2 member somehow. We can do it - * with either casting or with modifying and saving the entry - * manually after it has been saved by CSIPushMsgEntry. The latter - * solution is more expensive so we choose the first. - */ - TMsvEntry& tEntry = CONST_CAST( TMsvEntry&, aSIPushMsgEntry.Entry() ); - if ( HrefFlag() ) - { - CPushMtmUtil::SetAttrs( tEntry, EPushMtmAttrHasHref ); - } - else - { - CPushMtmUtil::ResetAttrs( tEntry, EPushMtmAttrHasHref ); - } - - // *** Set the entry to unread and new state. *** - - tEntry.SetNew( ETrue ); - tEntry.SetUnread( ETrue ); - - PUSHLOG_LEAVEFN("CSIContentHandler::SetSIPushMsgEntryFieldsL") - } - -// --------------------------------------------------------- -// CSIContentHandler::ProcessingPushMsgEntryL -// --------------------------------------------------------- -// -void CSIContentHandler::ProcessingPushMsgEntryL() - { - PUSHLOG_ENTERFN("CSIContentHandler::ProcessingPushMsgEntryL") - - TBool deletePushMsg( EFalse ); - - __ASSERT_DEBUG( ActionFlag(), - ContHandPanic( EPushContHandPanUnspecSiAction ) ); - - // S60 requirement: if both the href and the message is empty then - // delete the msg. - if ( HrefFlag() == EFalse && DataFlag() == EFalse ) - { - deletePushMsg = ETrue; - } - - // Expiration. - if ( !deletePushMsg && ExpiresFlag() ) - { - TTime today; - today.UniversalTime(); -#ifdef __TEST_LOG__ - _LIT( KDateFormat, "%E%D%X%N%Y %1 %2 %3" ); - _LIT( KTimeFormat, "%-B%:0%J%:1%T%:2%S%:3%+B" ); - TBuf<32> dateHolder; - TBuf<32> timeHolder; - today.FormatL( dateHolder, KDateFormat ); - today.FormatL( timeHolder, KTimeFormat ); - PUSHLOG_WRITE_FORMAT(" now date: <%S>",&dateHolder) - PUSHLOG_WRITE_FORMAT(" now time: <%S>",&timeHolder) - iExpiresTime.FormatL( dateHolder, KDateFormat ); - iExpiresTime.FormatL( timeHolder, KTimeFormat ); - PUSHLOG_WRITE_FORMAT(" exp date: <%S>",&dateHolder) - PUSHLOG_WRITE_FORMAT(" exp time: <%S>",&timeHolder) -#endif // __TEST_LOG__ - // check if message has expiry date before today's date - if ( iExpiresTime < today ) - { - PUSHLOG_WRITE("CSIContentHandler already expired") - deletePushMsg = ETrue; - } - } - - // An SI with the action attribute set to “delete” MUST have an - // explicitly assigned value for si-id. - if ( !deletePushMsg && ActionFlag() ) - { - if ( iPushMsgAction == CSIPushMsgEntry::ESIPushMsgDelete ) - { - if ( !SiIdFlag() || ( SiIdFlag() && iSiIdBuf->Length() == 0 ) ) - { - deletePushMsg = ETrue; - } - } - } - - // Handling out of order delivery & Replacement. - TMsvId matchingEntryId = KMsvNullIndexEntryId; - - if ( !deletePushMsg && ( SiIdFlag() || HrefFlag() ) && CreatedFlag() ) - { - deletePushMsg = HandleMsgOrderReceptionL( matchingEntryId ); - } - - if ( !deletePushMsg && ActionFlag() ) - { - // SI with action=signal-none must not be presented to the end-user. - // Note. In S60 signal-none behaves the same as delete: the - // message is discarded after processing it! - if ( iPushMsgAction == CSIPushMsgEntry::ESIPushMsgSignalNone ) - { - deletePushMsg = ETrue; - } - // SI with action=delete must also be discarded. - else if ( iPushMsgAction == CSIPushMsgEntry::ESIPushMsgDelete ) - { - deletePushMsg = ETrue; - } - } - - // Store message if not marked for deletion. - if ( !deletePushMsg ) - { - StoreSIMessageL( matchingEntryId ); - } - else - { - // The new entry must be discarded. - // Delete the corresponding matching entry, too. - if ( matchingEntryId != KMsvNullIndexEntryId ) - { - iWapPushUtils->DeleteEntryL( matchingEntryId ); - } - } - - iState = EDone; - IdleComplete(); - - PUSHLOG_LEAVEFN("CSIContentHandler::ProcessingPushMsgEntryL") - } - -// --------------------------------------------------------- -// CSIContentHandler::StoreSIMessageL -// --------------------------------------------------------- -// -void CSIContentHandler::StoreSIMessageL( TMsvId aMatchingEntryId ) - { - PUSHLOG_ENTERFN("CSIContentHandler::StoreSIMessageL") - - CSIPushMsgEntry* siEntry = CSIPushMsgEntry::NewL(); - CleanupStack::PushL( siEntry ); - - if ( aMatchingEntryId != KMsvNullIndexEntryId ) - { - PUSHLOG_WRITE("Matching SI found"); - //Delete this old entry - iWapPushUtils->DeleteEntryL( aMatchingEntryId ); - } - - SetSIPushMsgEntryFieldsL( *siEntry ); - iSavedMsgId = siEntry->SaveL( *iMsvSession, KMsvGlobalInBoxIndexEntryId ); - -#ifdef __TEST_LOG__ - _LIT( KDateFormat, "%E%D%X%N%Y %1 %2 %3" ); - _LIT( KTimeFormat, "%-B%:0%J%:1%T%:2%S%:3%+B" ); - TBuf<32> dateHolder; - TBuf<32> timeHolder; - TTime recDateTime = siEntry->ReceivedDate(); - recDateTime.FormatL( dateHolder, KDateFormat ); - recDateTime.FormatL( timeHolder, KTimeFormat ); - PUSHLOG_WRITE_FORMAT(" rec date: <%S>",&dateHolder) - PUSHLOG_WRITE_FORMAT(" rec time: <%S>",&timeHolder) -#endif // __TEST_LOG__ - - CleanupStack::PopAndDestroy( siEntry ); // siEntry - - PUSHLOG_LEAVEFN("CSIContentHandler::StoreSIMessageL") - } - -// --------------------------------------------------------- -// CSIContentHandler::HandleMsgOrderReceptionL -// --------------------------------------------------------- -// -TBool CSIContentHandler::HandleMsgOrderReceptionL( TMsvId& aMatchingEntryId ) - { - PUSHLOG_ENTERFN("CSIContentHandler::HandleMsgOrderReceptionL") - - __ASSERT_DEBUG( ( SiIdFlag() || HrefFlag() ), - ContHandPanic( EPushContHandPanNoSiIdOrHrefAttr ) ); - __ASSERT_DEBUG( CreatedFlag(), - ContHandPanic( EPushContHandPanNoCreatedAttr ) ); - - CMsvEntrySelection* matchingIdList = NULL; - TBool discardPushMsg( EFalse ); - - // Get list of matching stored SI messages. - if ( SiIdFlag() && iSiIdBuf->Length() != 0 ) - { - matchingIdList = iWapPushUtils->FindSiIdLC( *iSiIdBuf ); - } - else // HrefFlag() - { - // Use href as si-id. - matchingIdList = iWapPushUtils->FindSiIdLC( *iHrefBuf ); - } - const TInt matchingListCount( matchingIdList->Count() ); - // Note that the count can be greater than 1. - - PUSHLOG_WRITE_FORMAT("CSIContentHandler Count: %d",matchingListCount) - - if ( 0 < matchingListCount && CreatedFlag() ) - { - CSIPushMsgEntry* siEntry = CSIPushMsgEntry::NewL(); - CleanupStack::PushL( siEntry ); - - // Delete older stored messages and/or mark current message for - // deletion if same date or older than stored messages - TBool foundOneToBeReplaced = EFalse; - for ( TInt count = 0; count < matchingListCount; ++count ) - { - TMsvId matchingSiMsgEntryId( matchingIdList->At(count) ); - - siEntry->RetrieveL( *iMsvSession, matchingSiMsgEntryId ); - - // Skip date comparisons if creation date not valid - - // SI without created attribute never gets replaced. - TTime existingSiCreatedTime( siEntry->Created() ); - - if ( existingSiCreatedTime == Time::NullTTime() ) - { - // continue; - } - else - { - __ASSERT_DEBUG( !foundOneToBeReplaced, - ContHandPanic( EPushContHandPanTooManySi ) ); - if ( foundOneToBeReplaced ) - { - PUSHLOG_WRITE(" Already found one") - // Only one SI has to be found. - // If the program runs into it, then make a - // garbage collection to ensure consistency and - // remove other messages found. - iWapPushUtils->DeleteEntryL( matchingSiMsgEntryId ); - // After the 'for' only one SI is allowed that has created - // attribute. - } - else - { - foundOneToBeReplaced = ETrue; // A match was found. - // Check if received SI is newer than existing stored Si - // (out of order). - if ( iCreatedTime > existingSiCreatedTime ) - { - PUSHLOG_WRITE(" Replacing...") - // The new SI replaces the existing. - aMatchingEntryId = matchingSiMsgEntryId; - discardPushMsg = EFalse; - } - else if ( iCreatedTime <= existingSiCreatedTime ) - { - PUSHLOG_WRITE(" Discarding...") - // Received SI is older than existing stored Si. - discardPushMsg = ETrue; - } - } - } - } - - CleanupStack::PopAndDestroy( siEntry ); // siEntry - } - - CleanupStack::PopAndDestroy( matchingIdList ); // matchingIdList - - PUSHLOG_LEAVEFN("CSIContentHandler::HandleMsgOrderReceptionL") - return discardPushMsg; - } - -// --------------------------------------------------------- -// CSIContentHandler::ConvertDateTimeL -// --------------------------------------------------------- -// -TBool CSIContentHandler::ConvertDateTimeL( const TDesC& aDateTime, - TTime& aConvertedDate ) const - { - PUSHLOG_ENTERFN("CSIContentHandler::ConvertDateTimeL") - - TTime convertedTime = Time::NullTTime(); - TBool convertedOK = EFalse; - - // check supplied descriptor is the correct length - if ( aDateTime.Length() != KValidUTCLength ) - { - PUSHLOG_WRITE_FORMAT(" invalid UTC length <%d>",aDateTime.Length()) - User::Leave( KErrCorrupt ); - } - else - { - TBuf str = aDateTime; - PUSHLOG_WRITE_FORMAT(" datetime str: <%S>",&str) - if ( !IsValidUTCTime( str ) ) - { - // The UTC time is invalid. - PUSHLOG_WRITE(" invalid UTC time") - User::Leave( KErrCorrupt ); - } - else - { - // Now 'str' is in format YYYYMMDD:HHMMSS - // Adjust UTC time to zero offset TTime. Only month and day - // is effected. - const TInt KFirstMonthChar = KValidTTimeMonthStart; - const TInt KSecondMonthChar = KFirstMonthChar + 1; - const TInt KFirstDayChar = KValidTTimeDayStart; - const TInt KSecondDayChar = KFirstDayChar + 1; - // Month. - // check for special case of month = 10 which becomes 09 - if ( str[KFirstMonthChar] == '1' && str[KSecondMonthChar] == '0' ) - { - str[KFirstMonthChar] = '0'; - str[KSecondMonthChar] = '9'; - } - else - { - // month value is either 11, 12 or less than 10, ie 1 - 9. - // reduce day by one, eg 11 becomes 10, 12 becomes 11, 09 becomes 08 - str[KSecondMonthChar]--; - } - - // Day. - // check for special cases 10, 20, 30 - if ( str[KSecondDayChar] == '0' ) - { - // reduce day by 1, ie 10 becomes 09, 20 becomes 19 ... - str[KSecondDayChar] = '9'; - str[KFirstDayChar]--; - } - else - { - // day value is between 1 and 9 so reduce day by one - // eg 29 becomes 28, 11 bcomes 10, 31 becomes 30 - str[KSecondDayChar]--; - } - - // string is now syntaxically correct, but Set() will return an - // error if it's semantically incorrect. - User::LeaveIfError( convertedTime.Set( str ) ); - convertedOK = ETrue; - } - } - - PUSHLOG_LEAVEFN("CSIContentHandler::ConvertDateTimeL") - aConvertedDate = convertedTime; - return convertedOK; - } - -// --------------------------------------------------------- -// CSIContentHandler::ConvertOpaqueToUtcL -// --------------------------------------------------------- -// -HBufC* CSIContentHandler::ConvertOpaqueToUtcL( const TDesC8& aOpaque ) const - { - PUSHLOG_ENTERFN("CSIContentHandler::ConvertOpaqueToUtcL") - - const TInt opaqueSize = aOpaque.Size(); - if ( KValidMaxEncodedDateTimeSize < opaqueSize ) - { - PUSHLOG_WRITE_FORMAT(" Bad OPAQUE size: <%d>",opaqueSize) - User::Leave( KErrCorrupt ); - } - - HBufC* converted = HBufC::NewMaxLC( KValidUTCLength ); - TPtr convertedPtr = converted->Des(); - convertedPtr.SetLength( 0 ); // Reset. - - // Split up each opaque byte to two bytes. - TUint8 byte( 0x00 ); - TUint8 high( 0x00 ); - TUint8 low( 0x00 ); - TInt i = 0; - for ( i = 0; i < opaqueSize; ++i ) - { - byte = aOpaque[i]; - high = (TUint8)( (byte & 0xF0) >> 4 ); - low = (TUint8)( byte & 0x0F ); - // Check high and low if they are in the range [0-9]. - if ( 9 < high || 9 < low ) - { - PUSHLOG_WRITE_FORMAT2(" Overflow: <%d, %d>",high,low) - User::Leave( KErrOverflow ); - } - convertedPtr.Append( TChar(KAsciiZeroCharCode + high) ); - convertedPtr.Append( TChar(KAsciiZeroCharCode + low) ); - } - - // A valid UTC %Datetime contains 14 numerical characters and 6 - // non-numerical: “1999-04-30T06:40:00Z”. - // So fill the remaining bytes with zeros. - for ( i = convertedPtr.Length(); i < KValidUTCNumericals; ++i ) - { - convertedPtr.Append( TChar('0') ); - } - - // Insert the necessary non-numerical boundary characters. - i = 0; - // Skip year and insert '-'. (Don't forget to increase i with 1 each time!) - i += KValidUTCYearBlockLength; - convertedPtr.Insert( i++, KCharMinus ); - // Skip month and insert '-'. - i += KValidUTCOtherBlockLength; - convertedPtr.Insert( i++, KCharMinus ); - // Skip day and insert 'T'. - i += KValidUTCOtherBlockLength; - convertedPtr.Insert( i++, KCharT ); - // Skip hour and insert ':'. - i += KValidUTCOtherBlockLength; - convertedPtr.Insert( i++, KCharColon ); - // Skip minute and insert ':'. - i += KValidUTCOtherBlockLength; - convertedPtr.Insert( i++, KCharColon ); - // Skip second and insert 'Z'. - i += KValidUTCOtherBlockLength; - convertedPtr.Insert( i++, KCharZ ); - - CleanupStack::Pop( converted ); // converted - PUSHLOG_LEAVEFN("CSIContentHandler::ConvertOpaqueToUtcL") - return converted; - } - -// --------------------------------------------------------- -// CSIContentHandler::IsValidUTCTime -// --------------------------------------------------------- -// -TBool CSIContentHandler::IsValidUTCTime( TDes& aDateTime ) const - { - PUSHLOG_ENTERFN("CSIContentHandler::IsValidUTCTime") - - TBool isValid( ETrue ); // Return value. - - // Now aDateTime has to be in format YYYY-MM-DDTHH:MM:SSZ - - // check supplied descriptor is the correct length - if ( aDateTime.Length() != KValidUTCLength ) - { - PUSHLOG_WRITE_FORMAT(" invalid UTC length <%d>",aDateTime.Length()) - isValid = EFalse; - } - else - { - // strip out formatting characters - TInt formatCharPos = 4; - aDateTime.Delete( formatCharPos, 1 ); - // now move through two characters at a time and remove other chars - // to just leave digits - const TInt KRemainingFormatChars = 5; - TInt i( 0 ); - for ( i = 0; i < KRemainingFormatChars; ++i ) - { - formatCharPos += 2; - aDateTime.Delete( formatCharPos, 1 ); - } - - // Now aDateTime has to be in format YYYYMMDDHHMMSS - - __ASSERT_DEBUG( aDateTime.Length() == KValidTTimeLength, - ContHandPanic( EPushContHandPanBadTTimeLength ) ); - - // now have UTC string stripped of format characters - check remaining - // characters are all digits - YYYYMMDDHHMMSS - TChar ch; - for ( i = 0; i < KValidTTimeLength; ++i ) - { - ch = aDateTime[i]; - if ( ch.IsDigit() == EFalse ) - { - PUSHLOG_WRITE_FORMAT(" not digit <%d>",i) - isValid = EFalse; - } - } - - if ( isValid ) - { - /* - In YYYYMMDDHHMMSS - YYYY = 4 digit year ("0000" ... "9999") - MM = 2 digit month ("01"=January, "02"=February ... "12"=December) - DD = 2 digit day ("01", "02" ... "31") - HH = 2 digit hour, 24-hour timekeeping system ("00" ... "23") - MM = 2 digit minute ("00" ... "59") - SS = 2 digit second ("00" ... "59") - */ - TInt err; - TUint val; - // Do not check year. There are no restrictions. - // Check month. - TLex parser( aDateTime.Mid( KValidTTimeMonthStart, - KValidTTimeBlockLength ) ); - err = parser.Val( val, EDecimal ); - if ( err ) - { - isValid = EFalse; - PUSHLOG_WRITE_FORMAT(" parser err: <%d>",err) - } - else - { - PUSHLOG_WRITE_FORMAT(" month: <%d>",val) - if ( val < 1 || 12 < val ) - { - isValid = EFalse; - } - } - // Check day. - if ( isValid ) - { - parser = aDateTime.Mid( KValidTTimeDayStart, - KValidTTimeBlockLength ); - err = parser.Val( val, EDecimal ); - if ( err ) - { - isValid = EFalse; - PUSHLOG_WRITE_FORMAT(" parser err: <%d>",err) - } - else - { - PUSHLOG_WRITE_FORMAT(" day: <%d>",val) - if ( val < 1 || 31 < val ) - { - isValid = EFalse; - } - } - } - // Check hour. - if ( isValid ) - { - parser = aDateTime.Mid( KValidTTimeHourStart, - KValidTTimeBlockLength ); - err = parser.Val( val, EDecimal ); - if ( err ) - { - isValid = EFalse; - PUSHLOG_WRITE_FORMAT(" parser err: <%d>",err) - } - else - { - PUSHLOG_WRITE_FORMAT(" hour: <%d>",val) - if ( 23 < val ) - { - isValid = EFalse; - } - } - } - // Check minute. - if ( isValid ) - { - parser = aDateTime.Mid( KValidTTimeMinuteStart, - KValidTTimeBlockLength ); - err = parser.Val( val, EDecimal ); - if ( err ) - { - isValid = EFalse; - PUSHLOG_WRITE_FORMAT(" parser err: <%d>",err) - } - else - { - PUSHLOG_WRITE_FORMAT(" min: <%d>",val) - if ( 59 < val ) - { - isValid = EFalse; - } - } - } - // Check second. - if ( isValid ) - { - parser = aDateTime.Mid( KValidTTimeSecondStart, - KValidTTimeBlockLength ); - err = parser.Val( val, EDecimal ); - if ( err ) - { - isValid = EFalse; - PUSHLOG_WRITE_FORMAT(" parser err: <%d>",err) - } - else - { - PUSHLOG_WRITE_FORMAT(" sec: <%d>",val) - if ( 59 < val ) - { - isValid = EFalse; - } - } - } - - // insert colon seperating date from time - const TInt KColonPosition = 8; - aDateTime.Insert( KColonPosition, KCharColon ); - - // Now aDateTime has to be in format YYYYMMDD:HHMMSS - } - } - - PUSHLOG_LEAVEFN("CSIContentHandler::IsValidUTCTime") - return isValid; // aDateTime contains a modified buffer. - } - -// --------------------------------------------------------- -// CSIContentHandler::AttributeToTTimeL -// --------------------------------------------------------- -// -TBool CSIContentHandler::AttributeToTTimeL - ( NW_DOM_AttributeHandle_t& aAttrHandle, - TTime& aConvertedDate ) const - { - PUSHLOG_ENTERFN("CSIContentHandler::AttributeToTTimeL") - - TBool gotDate = EFalse; - NW_Status_t stat = NW_STAT_SUCCESS; - NW_DOM_AttrVal_t attrVal; - - // It is expected to be String or Opaque. - // It may be Opaque, to which we will need a NW_DOM_AttrVal_t structure. - stat = NW_DOM_AttributeHandle_getNextVal( &aAttrHandle, &attrVal ); - - if ( stat != NW_STAT_WBXML_ITERATE_MORE ) - { - User::LeaveIfError( NwxStatusToErrCode( stat ) ); - } - else - { - NW_Uint16 valType = NW_DOM_AttrVal_getType( &attrVal ); - - if ( valType == NW_DOM_ATTR_VAL_STRING ) - { - CStringOwner* stringOwner = new (ELeave) CStringOwner; - CleanupStack::PushL( stringOwner ); - - NW_String_t* val = NW_String_new(); - User::LeaveIfNull( val ); - stringOwner->SetString( val ); - // - stat = NW_DOM_AttrVal_toString( &attrVal, val, iCharEncoding ); - User::LeaveIfError( NwxStatusToErrCode( stat ) ); - NW_Byte* storage = NW_String_getStorage( val ); - NW_Uint16 length = NW_String_getCharCount( val, iCharEncoding ); - TPtrC8 dataPtr( storage, length ); - HBufC* dataBuf = HBufC::NewMaxLC( dataPtr.Length() ); - dataBuf->Des().Copy( dataPtr ); - gotDate = ConvertDateTimeL( *dataBuf, aConvertedDate ); - - CleanupStack::PopAndDestroy( 2, stringOwner ); // dataBuf, - // stringOwner - } - else if ( valType == NW_DOM_ATTR_VAL_OPAQUE ) - { - NW_Uint32 len = 0; - NW_Byte* data = NW_DOM_AttrVal_getOpaque( &attrVal, &len ); - User::LeaveIfNull( data ); - TPtrC8 dataPtr( data, len ); - - HBufC* dateTime = ConvertOpaqueToUtcL( dataPtr ); - CleanupStack::PushL( dateTime ); - gotDate = ConvertDateTimeL( *dateTime, aConvertedDate ); - CleanupStack::PopAndDestroy( dateTime ); // dateTime - } - else - { - User::Leave( KErrNotSupported ); - } - } - - PUSHLOG_LEAVEFN("CSIContentHandler::AttributeToTTimeL") - return gotDate; // aConvertedDate contains the result. - } - -// --------------------------------------------------------- -// CSIContentHandler::HandleMessageL -// --------------------------------------------------------- -// -void CSIContentHandler::HandleMessageL( CPushMessage* aPushMsg, - TRequestStatus& aStatus ) - { - PUSHLOG_ENTERFN("CSIContentHandler::HandleMessageL") - - __ASSERT_DEBUG( aPushMsg != NULL, - ContHandPanic( EPushContHandPanMsgNull ) ); - -#ifdef __TEST_LOG__ - TPtrC8 bodyPtr; - aPushMsg->GetMessageBody( bodyPtr ); - PUSHLOG_HEXDUMP( bodyPtr ) -#endif // __TEST_LOG__ - - iMessage = aPushMsg; - iAcknowledge = ETrue; - SetConfirmationStatus( aStatus ); - - iState = EGarbageCollecting; - IdleComplete(); - - PUSHLOG_LEAVEFN("CSIContentHandler::HandleMessageL") - } - -// --------------------------------------------------------- -// CSIContentHandler::HandleMessageL -// --------------------------------------------------------- -// -void CSIContentHandler::HandleMessageL( CPushMessage* aPushMsg ) - { - PUSHLOG_ENTERFN("CSIContentHandler::HandleMessageL") - - __ASSERT_DEBUG( aPushMsg != NULL, - ContHandPanic( EPushContHandPanMsgNull ) ); - -#ifdef __TEST_LOG__ - TPtrC8 bodyPtr; - aPushMsg->GetMessageBody( bodyPtr ); - PUSHLOG_HEXDUMP( bodyPtr ) -#endif // __TEST_LOG__ - - iAcknowledge = EFalse; - iMessage = aPushMsg; - - iState = EGarbageCollecting; - IdleComplete(); - - PUSHLOG_LEAVEFN("CSIContentHandler::HandleMessageL") - } - -// --------------------------------------------------------- -// CSIContentHandler::CancelHandleMessage -// --------------------------------------------------------- -// -void CSIContentHandler::CancelHandleMessage() - { - PUSHLOG_ENTERFN("CSIContentHandler::CancelHandleMessage") - Cancel(); - PUSHLOG_LEAVEFN("CSIContentHandler::CancelHandleMessage") - } - -// --------------------------------------------------------- -// CSIContentHandler::CPushHandlerBase_Reserved1 -// --------------------------------------------------------- -// -void CSIContentHandler::CPushHandlerBase_Reserved1() - { - } - -// --------------------------------------------------------- -// CSIContentHandler::CPushHandlerBase_Reserved2 -// --------------------------------------------------------- -// -void CSIContentHandler::CPushHandlerBase_Reserved2() - { - } - -// --------------------------------------------------------- -// CSIContentHandler::DoCancel -// --------------------------------------------------------- -// -void CSIContentHandler::DoCancel() - { - PUSHLOG_ENTERFN("CSIContentHandler::DoCancel") - Complete( KErrCancel ); - PUSHLOG_LEAVEFN("CSIContentHandler::DoCancel") - } - -// --------------------------------------------------------- -// CSIContentHandler::RunL -// --------------------------------------------------------- -// -void CSIContentHandler::RunL() - { - // Handle errors in RunError(). - PUSHLOG_WRITE_FORMAT("iStatus.Int(): %d",iStatus.Int()) - User::LeaveIfError( iStatus.Int() ); - - // use active state machine routine to manage activites: - switch ( iState ) - { - case EGarbageCollecting: - { - CollectGarbageL(); - break; - } - case EFilteringAndParsing: - { - if ( !FilterPushMsgL() ) - { - // It did not pass the filter. Done. - iState = EDone; - IdleComplete(); - } - else - { - // Continue. - TInt ret = KErrNone; - PUSHLOG_WRITE("CSIContentHandler::RunL : before trapping parsing.") - TRAP(ret, ParsePushMsgL()); - PUSHLOG_WRITE_FORMAT("CSIContentHandler::RunL : after trapping parsing. ret = %d", ret) - if ( ret != KErrNone) - { - PUSHLOG_WRITE("CSIContentHandler::RunL : Parsing failed. discarding message.") - iState = EDone; - IdleComplete(); - } - } - break; - } - case EProcessing: - { - ProcessingPushMsgEntryL(); - break; - } - case EDone: - { - PUSHLOG_WRITE("CSIContentHandler EDone") - Complete( KErrNone ); - break; - } - default: - { - // JIC. - PUSHLOG_WRITE("CSIContentHandler default Done") - Complete( KErrNone ); - break; - } - } - } - -// --------------------------------------------------------- -// CSIContentHandler::RunError -// --------------------------------------------------------- -// -TInt CSIContentHandler::RunError( TInt aError ) - { - PUSHLOG_WRITE_FORMAT("CSIContentHandler::RunError: %d",aError) - - iState = EDone; - Complete( aError ); - return KErrNone; - } -