messagingfw/wappushfw/ROContentHandler/src/MessageComposer.cpp
changeset 0 8e480a14352b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/messagingfw/wappushfw/ROContentHandler/src/MessageComposer.cpp	Mon Jan 18 20:36:02 2010 +0200
@@ -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 `&#0;').
+		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;
+	}