--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/messagingfw/wappushfw/ROAPTContentHandler/src/MessageComposer.cpp Wed Nov 03 22:41:46 2010 +0530
@@ -0,0 +1,417 @@
+// 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:
+//
+
+#include <f32file.h>
+#include <xml/documentparameters.h>
+#include <xml/taginfo.h>
+#include <xml/attribute.h>
+
+using namespace Xml;
+
+// System Include
+//For base64 encoding
+#include <tconvbase64.h>
+#include <xml/xmlparsererrors.h>
+#include <xml/xmlframeworkerrors.h>
+#include <xml/parserfeature.h>
+
+// User Include
+#include "MessageComposer.h"
+#include "errorcodes.h"
+
+const TInt KXmlBufferlength = 128;
+//text DRM MIME type
+_LIT(KDRMTextContentType, "application/vnd.oma.drm.rights+xml");
+
+//prefix and suffix to be appended.
+_LIT8(KXmlParserDataType, "text/xml");
+_LIT8(KWbxmlParserDataType, "text/wbxml");
+_LIT8(KOpeningBracket, "<");
+_LIT8(KClosingBracket, ">");
+_LIT8(KOpeningEndBracket, "</");
+_LIT8(KOpeningQuote, "=\"");
+_LIT8(KClosingQuote, "\"");
+_LIT8(KSpace," ");
+/**
+ * Constructor
+ * Copy CPushMessage pointer for reference during parse operations
+ */
+CMessageComposer::CMessageComposer ( CPushMessage& aPushMessage )
+ : iPushMessage ( aPushMessage )
+ {
+ iIsKeyValue = EFalse;
+ }
+
+/**
+* Destructor
+* Delete the parser object and close the buffer which store DRM message.
+*/
+CMessageComposer::~CMessageComposer()
+ {
+ delete iParser;
+ iXmlBuf.Close();
+ }
+
+/**
+*/
+CMessageComposer* CMessageComposer::NewL( CPushMessage& aPushMessage)
+ {
+ CMessageComposer* self = new ( ELeave ) CMessageComposer ( aPushMessage );
+ CleanupStack::PushL ( self );
+ self->ConstructL ();
+ CleanupStack::Pop ( self );
+ return ( self );
+ }
+
+/**
+*/
+void CMessageComposer::ConstructL()
+ {
+ iXmlBuf.CreateL(KXmlBufferlength);
+ LoadPluginL ();
+ }
+
+/*
+* Load the plugin based on incoming message (XML or WBXML plugin)
+*/
+void CMessageComposer::LoadPluginL ()
+ {
+ TPtrC contentType;
+ iPushMessage.GetContentType ( contentType );
+ iParser = CParser::NewL ( ( contentType.CompareF ( KDRMTextContentType ) ) ?
+ KWbxmlParserDataType() : KXmlParserDataType(), *this );
+ }
+
+/**
+
+*/
+const TDesC8& CMessageComposer::ParseMessageL ()
+ {
+ // Begin parsing
+ iParser->ParseBeginL ();
+
+ // Get the message body and do parsing.
+ TPtrC8 msgBody;
+ if(iPushMessage.GetMessageBody ( msgBody ))
+ {
+ iParser->EnableFeature ( ERawContent );
+ iParser->ParseL ( msgBody );
+ }
+ else
+ {
+ //Leave with KErrNotFound error code as message body not found
+ User::Leave ( KErrNotFound );
+ }
+
+ // End parsing
+ iParser->ParseEndL ();
+
+ return iXmlBuf;
+ }
+
+RStringPool& CMessageComposer::StringPool ()
+ {
+ return iParser->StringPool ();
+ }
+
+void CMessageComposer::OnStartDocumentL ( const Xml::RDocumentParameters& /*aDocParam*/ , TInt aErrorCode )
+ {
+ User::LeaveIfError ( MapToWapXMLError ( aErrorCode ) );
+ }
+
+void CMessageComposer::OnEndDocumentL ( TInt aErrorCode )
+ {
+ User::LeaveIfError ( MapToWapXMLError ( aErrorCode ) );
+ }
+
+void CMessageComposer::OnStartElementL ( const Xml::RTagInfo& aElement, const Xml::RAttributeArray& aAttributes, TInt aErrorCode )
+ {
+ User::LeaveIfError( MapToWapXMLError ( aErrorCode ) );
+
+ if(aElement.LocalName().DesC().Compare(_L8("ds:KeyValue")) == 0)
+ {
+ iIsKeyValue = ETrue;
+ }
+
+ //Append '<' before the element
+ AppendDataL ( KOpeningBracket );
+ //Append the element
+ AppendDataL ( aElement.LocalName().DesC() );
+
+ //Now append all the attributes and attribute values in loop
+ TInt nAttributes = aAttributes.Count();
+ for ( TInt i = 0; i < nAttributes; ++i )
+ {
+ const RAttribute& attribute = aAttributes[i];
+ const RTagInfo& nameInfo = attribute.Attribute();
+ //Append a blanck space before appending attribute name
+ AppendDataL ( KSpace );
+ //Append the attribute name
+ AppendDataL ( nameInfo.LocalName().DesC() );
+ //Append '="' before appending attribute value
+ AppendDataL ( KOpeningQuote );
+ //Append attribue Value
+ AppendDataL ( attribute.Value().DesC() );
+ //Append '"' after the attribute value
+ AppendDataL ( KClosingQuote );
+ }//End of for loop, appended all attribures of this element
+ //Append '>' after the element
+ AppendDataL ( KClosingBracket );
+ }
+
+void CMessageComposer::OnEndElementL ( const Xml::RTagInfo& aElement , TInt aErrorCode )
+ {
+ User::LeaveIfError ( MapToWapXMLError ( aErrorCode ) );
+
+ AppendDataL ( KOpeningEndBracket );
+ AppendDataL ( aElement.LocalName().DesC() );
+ AppendDataL ( KClosingBracket );
+ }
+
+void CMessageComposer::OnContentL ( const TDesC8& aBytes, TInt aErrorCode )
+ {
+ User::LeaveIfError ( MapToWapXMLError ( aErrorCode ) );
+
+ if(iIsKeyValue)
+ {
+ // Got to base64 encode the 128-bit encryption key.
+ iIsKeyValue = EFalse;
+ TBase64 codec;
+ TInt length = aBytes.Length();
+ // Calculate the length of the base64 encoded key and create a buffer of that length.
+ HBufC8* encodedBytes = HBufC8::NewLC(((length%3)>0)?((length/3)+length+3):((length/3)+length+2));
+ TPtr8 encodedBytesPtr(encodedBytes->Des());
+ codec.Encode(aBytes, encodedBytesPtr);
+ AppendDataL(*encodedBytes);
+ CleanupStack::PopAndDestroy(encodedBytes);
+ }
+ else
+ {
+ //Append the content.
+ AppendDataL ( aBytes );
+ }
+ }
+
+void CMessageComposer::OnStartPrefixMappingL ( const RString& /* aPrefix */, const RString& /* aUri */, TInt aErrorCode )
+ {
+ User::LeaveIfError ( MapToWapXMLError ( aErrorCode ) );
+ }
+
+void CMessageComposer::OnEndPrefixMappingL ( const RString& /* aPrefix */, TInt aErrorCode )
+ {
+ User::LeaveIfError ( MapToWapXMLError ( aErrorCode ) );
+ }
+
+void CMessageComposer::OnIgnorableWhiteSpaceL ( const TDesC8& /* aBytes */, TInt aErrorCode )
+ {
+ User::LeaveIfError ( MapToWapXMLError ( aErrorCode ) );
+ }
+
+void CMessageComposer::OnSkippedEntityL ( const RString& /* aName */, TInt aErrorCode )
+ {
+ User::LeaveIfError ( MapToWapXMLError ( aErrorCode ) );
+ }
+
+void CMessageComposer::OnProcessingInstructionL ( const TDesC8& /* aTarget */, const TDesC8& /* aData */, TInt aErrorCode )
+ {
+ User::LeaveIfError ( MapToWapXMLError ( aErrorCode ) );
+ }
+
+void CMessageComposer::OnError ( TInt aErrorCode )
+ {
+ iLastError = MapToWapXMLError ( aErrorCode );
+ }
+
+TAny* CMessageComposer::GetExtendedInterface ( const TInt32 /* aUid */ )
+ {
+ return NULL;
+ }
+
+TInt CMessageComposer::LastError ()
+ {
+ return iLastError;
+ }
+
+void CMessageComposer::AppendDataL ( const TDesC8& aData )
+ {
+ TInt xmlBufMaxLen = iXmlBuf.MaxLength ();
+ TInt xmlBufLen = iXmlBuf.Length ();
+ TInt dataLen = aData.Length ();
+ if ( xmlBufMaxLen < ( xmlBufLen + dataLen ) )
+ {
+ // Need to allocate more space.
+ TInt lenToAllocate = (dataLen > KXmlBufferlength) ? dataLen : KXmlBufferlength;
+ iXmlBuf.ReAllocL ( xmlBufMaxLen + lenToAllocate );
+ }
+ iXmlBuf.Append ( aData );
+ }
+
+// Map the generic XML parser code to WAP XML errors. Description of the error code
+// has taken from expat.
+TInt CMessageComposer::MapToWapXMLError ( TInt aXmlErrorCode )
+ {
+
+ TInt errorCode = aXmlErrorCode;
+
+ switch ( aXmlErrorCode )
+ {
+ case EXmlParserError:
+ case EXmlSyntax:
+ errorCode = EWapErrGeneral;
+ break;
+ // The document contains no elements
+ // (XML requires all documents to contain exactly one top-level element)..
+ case EXmlNoElements:
+ errorCode = EWapErrXmlLibMissingDocumentRootNode;
+ break;
+
+ // Raised when an input byte could not properly be assigned to a character;
+ // for example, a NUL byte (value 0) in a UTF-8 input stream.
+ case EXmlInvalidToken:
+ errorCode = EWapErrXmlLibIllegalTagName;
+ break;
+
+ // Some token (such as a start tag) was not closed before the end of the stream or
+ // the next token was encountered.
+ case EXmlUnclosedToken:
+ // An end tag did not match the innermost open start tag.
+ case EXmlTagMismatch:
+ errorCode = EWapErrXmlLibEndTagMismatch;
+ break;
+
+ // An incomplete character was found in the input.
+ case EXmlPartialChar:
+ // A character reference referred to a character which is illegal in XML
+ // (for example, character 0, or `�').
+ case EXmlBadCharRef:
+ errorCode = EWapErrXmlLibInvalidCharacterReference;
+ break;
+
+ // An attribute was used more than once in a start tag.
+ case EXmlDuplicateAttribute:
+ errorCode = EWapErrXmlLibInvalidAttributeDeclaration;
+ break;
+
+ // Something other than whitespace occurred after the document element.
+ case EXmlJunkAfterDocElement:
+ // A parameter entity reference was found where it was not allowed.
+ case EXmlPeRef:
+ errorCode = EWapErrDocumentCorrupted;
+ break;
+
+ // A reference was made to a entity which was not defined.
+ case EXmlUndefinedEntity:
+ // An entity reference contained another reference to the same entity; possibly via a
+ // different name, and possibly indirectly.
+ case EXmlRecursiveEntity:
+ case EXmlAsyncEntity:
+ // An entity reference in an attribute value referred to an external entity instead of an internal entity.
+ case EXmlAttributeExternalEntityRef:
+ case EXmlExternalEntityHandling:
+ errorCode = EWapErrXmlLibUnknownEntityReference;
+ break;
+
+ // An entity reference referred to an entity which was declared with a notation,
+ // so cannot be parsed.
+ case EXmlBinaryEntityRef:
+ errorCode = EWapErrDocumentCorrupted;
+ break;
+
+ // An XML declaration was found somewhere other than the start of the input data.
+ case EXmlMisplacedPi:
+ case EXmlIncorrectEncoding:
+ errorCode = EWapErrXmlLibInvalidDocument;
+ break;
+ // The document encoding is not supported by Expat.
+ case EXmlUnknownEncoding:
+ errorCode = EWapErrUnknownDocument;
+ break;
+
+ // A CDATA marked section was not closed.
+ case EXmlUnclosedCdata:
+ errorCode = EWapErrXmlLibMissingCDATASectionEndTag;
+ break;
+
+ // The parser determined that the document was not ``standalone''
+ // though it declared itself to be in the XML declaration, and the NotStandaloneHandler
+ // was set and returned 0.
+ case EXmlNotStandalone:
+ case EXmlUnexpectedState:
+ case EXmlEntityDeclInPe:
+ errorCode = EWapErrUnknownDocument;
+ break;
+
+ case EXmlDtdRequired:
+ errorCode = EWapErrDTDUnavailable;
+ break;
+
+ // A behavioral change was requested after parsing started that can only be changed
+ // before parsing has started. This is (currently) only raised by UseForeignDTD().
+ case EXmlFeatureLockedWhileParsing:
+ errorCode = EWapErrGeneral;
+ break;
+
+ // Xml framework errors
+ case KErrXmlStringDictionaryPluginNotFound:
+ case KErrXmlParserPluginNotFound:
+ case KErrXmlGeneratorPluginNotFound:
+ case KErrXmlPluginNotFound:
+ errorCode = EWapErrPluginNotFound;
+ break;
+
+ case KErrXmlBadCharacterConversion:
+ case KErrXmlUnsupportedCharacterSet:
+ case KErrXmlUnavailableCharacterSet:
+ errorCode = EWapErrXmlLibInvalidCharacterReference;
+ break;
+
+ // MStringDictionary errors ( mainly wbxml errors )
+ case KErrXmlUnsupportedElement:
+ errorCode = EWapErrXmlLibIllegalTagName;
+ break;
+
+ case KErrXmlUnsupportedAttribute:
+ errorCode = EWapErrXmlLibMissingRequiredAttribute;
+ break;
+
+ case KErrXmlUnsupportedAttributeValue:
+ errorCode = EWapErrXmlLibIllegalAttributeValue;
+ break;
+
+ case KErrXmlMissingStringDictionary:
+ errorCode = EWapErrXmlLibMissingDocument;
+ break;
+
+ case KErrXmlUnsupportedDocumentVersion:
+ errorCode = EWapErrXmlLibInvalidDocumentStructure;
+ break;
+
+ case KErrXmlDocumentCorrupt:
+ errorCode = EWapErrDocumentCorrupted;
+ break;
+
+ case KErrXmlStringPoolTableNotFound:
+ case KErrXmlBadIndex:
+ case KErrXmlUnsupportedExtInterface:
+ case KErrXmlLast:
+ errorCode = EWapErrGeneral;
+ break;
+
+ default:
+ // Do nothing. any other kind of error.
+ break;
+ }
+ return errorCode;
+ }