diff -r 000000000000 -r e35f40988205 xml/xmldomandxpath/src/xmlengineserializer/xmlengcontenthandler.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xml/xmldomandxpath/src/xmlengineserializer/xmlengcontenthandler.cpp Thu Dec 17 09:29:21 2009 +0200 @@ -0,0 +1,419 @@ +// 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: +// Content handler implementation +// + +#include "xmlengcontenthandler.h" +#include +#include +#include "xmlengdeserializerxop.h" +#include +#include + +#include +#include + +CXmlEngContentHandler* CXmlEngContentHandler::NewL( CXmlEngDeserializer* aDeserializer, + MContentHandler* aContentHandler ) + { + CXmlEngContentHandler* self = new (ELeave) CXmlEngContentHandler(aDeserializer, aContentHandler); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); //self + return self; + } + +CXmlEngContentHandler::~CXmlEngContentHandler() + { + iCachedPrefixes.ResetAndDestroy(); + iCachedUris.ResetAndDestroy(); + iCachedErrors.Reset(); + iStrPool.Close(); + } + +CXmlEngContentHandler::CXmlEngContentHandler(CXmlEngDeserializer* aDeserializer, + MContentHandler* aContentHandler) +: iDeserializer(aDeserializer), + iContentHandler(aContentHandler) + { + iSkipIncludeElement = 0; + iSkipPrefixMapping = 0; + } + +void CXmlEngContentHandler::ConstructL() + { + iStrPool.OpenL(); + } + +/** +This method is a callback to indicate the start of the document. +@param aDocParam Specifies the various parameters of the document. +@param aDocParam.iCharacterSetName The character encoding of the document. +@param aErrorCode is the error code. + If this is not KErrNone then special action may be required. +*/ +void CXmlEngContentHandler::OnStartDocumentL(const RDocumentParameters& aDocParam, TInt aErrorCode) +{ + iContentHandler->OnStartDocumentL(aDocParam, aErrorCode); +} + + +/** +This method is a callback to indicate the end of the document. +@param aErrorCode is the error code. + If this is not KErrNone then special action may be required. +*/ +void CXmlEngContentHandler::OnEndDocumentL(TInt aErrorCode) +{ + iContentHandler->OnEndDocumentL(aErrorCode); +} + + +/** +This method is a callback to indicate an element has been parsed. +@param aElement is a handle to the element's details. +@param aAttributes contains the attributes for the element. +@param aErrorCode is the error code. + If this is not KErrNone then special action may be required. +*/ +void CXmlEngContentHandler::OnStartElementL(const RTagInfo& aElement, + const RAttributeArray& aAttributes, + TInt aErrorCode) +{ + _LIT8(KInclude, "Include"); + _LIT8(KXopIncludeUri, "http://www.w3.org/2004/08/xop/include"); + _LIT8(KHref, "href"); + _LIT8(KHrefUriEmpty, ""); + + TBool xopInclude = EFalse; + + if(iSkipIncludeElement) + { + if( aElement.LocalName().DesC() == KInclude + && aElement.Uri().DesC() == KXopIncludeUri) + { + xopInclude = ETrue; + ++iSkipIncludeElement; + } + return; + } + + MXmlEngExtendedHandler* ext = (MXmlEngExtendedHandler*)iContentHandler->GetExtendedInterface(MXmlEngExtendedHandler::EExtInterfaceUid); + + // determine if this element is xop:Include + if( xopInclude || + (aElement.LocalName().DesC() == KInclude && + aElement.Uri().DesC() == KXopIncludeUri)) + { + for ( TInt i = 0; i < aAttributes.Count(); i++) + { + if( aAttributes[i].Attribute().LocalName().DesC() == KHref + && aAttributes[i].Attribute().Uri().DesC() == KHrefUriEmpty) + { + TPtrC8 cidValue; + TPtrC8 data; + cidValue.Set(CidValue(aAttributes[i].Value().DesC())); + if( (CXmlEngDeserializer*)iDeserializer->ExternalData() + && iDeserializer->GetDataContainer(cidValue) ) + { + ++iSkipIncludeElement; + iSkipPrefixMapping = ETrue; + if(ext) + ext->OnDataContainerL(*iDeserializer->GetDataContainer(cidValue), KErrNone); + } + else if(((CXmlEngDeserializerXOP*)iDeserializer)->GetData(cidValue, data) == KErrNone) + { + ++iSkipIncludeElement; + iSkipPrefixMapping = ETrue; + if(ext) + { + if(iDeserializer->ParsingOptions().iOptions & TXmlEngParsingOptions::KOptionEncodeToBase64) + { + //TImCodecB64 base64Codec; + // The encoded length of base64 is about twice (use 3x) decoded length + HBufC8* data64 = HBufC8::NewLC(3*data.Size()); + TPtr8 data64Ptr = data64->Des(); + // Encode to the base64 Content-Transfer-Encoding + //base64Codec.Encode(data, data64Ptr); + using namespace BSUL; + Base64Codec::Encode(data, data64Ptr); + if(data64Ptr.Length() == 0) + { + User::Leave(KErrGeneral); + } + ext->OnBinaryContentL(data64Ptr,cidValue,aErrorCode); + CleanupStack::PopAndDestroy(); //data64 + } + else + { + ext->OnBinaryContentL(data,cidValue,aErrorCode); + } + } + + } + else + { + User::Leave(KXmlEngErrBinDataNotFound); + //iContentHandler->OnStartElementL(aElement, aAttributes, aErrorCode); + } + } + } //for + } + + if(!iSkipIncludeElement) + { + if(iCachedUris.Count()) + { + RString prefix; + RString uri; + for(TInt i = 0; i < iCachedPrefixes.Count(); i++) + { + prefix = iStrPool.OpenStringL(iCachedPrefixes[i]->Des()); + CleanupClosePushL(prefix); + uri = iStrPool.OpenStringL(iCachedUris[i]->Des()); + CleanupClosePushL(uri); + iContentHandler->OnStartPrefixMappingL(prefix, uri, iCachedErrors[i]); + CleanupStack::PopAndDestroy(&uri); + CleanupStack::PopAndDestroy(&prefix); + } + } + if(iDeserializer->IsFeatureEnabled(EConvertTagsToLowerCase)) + { + RTagInfo elementTag = ConvertNameToLowerCaseL(aElement); + CleanupClosePushL(elementTag); + iContentHandler->OnStartElementL(elementTag, aAttributes, aErrorCode); + CleanupStack::PopAndDestroy(); //elementTag + } + else + { + iContentHandler->OnStartElementL(aElement, aAttributes, aErrorCode); + } + } + iCachedUris.ResetAndDestroy(); + iCachedPrefixes.ResetAndDestroy(); + iCachedErrors.Reset(); +} + + +/** +This method is a callback to indicate the end of the element has been reached. +@param aElement is a handle to the element's details. +@param aErrorCode is the error code. + If this is not KErrNone then special action may be required. +*/ +void CXmlEngContentHandler::OnEndElementL(const RTagInfo& aElement, TInt aErrorCode) +{ + _LIT8(KInclude, "Include"); + _LIT8(KXopIncludeUri, "http://www.w3.org/2004/08/xop/include"); + + if(iSkipIncludeElement) + { + if( aElement.LocalName().DesC() == KInclude + && aElement.Uri().DesC() == KXopIncludeUri) + { + --iSkipIncludeElement; + } + return; + } + else + { + iSkipPrefixMapping = EFalse; + } + + if(iDeserializer->IsFeatureEnabled(EConvertTagsToLowerCase)) + { + RTagInfo elementTag = ConvertNameToLowerCaseL(aElement); + CleanupClosePushL(elementTag); + iContentHandler->OnEndElementL(elementTag, aErrorCode); + CleanupStack::PopAndDestroy(&elementTag); //elementTag + } + else + { + iContentHandler->OnEndElementL(aElement, aErrorCode); + } +} + +/** +This method is a callback that sends the content of the element. +Not all the content may be returned in one go. The data may be sent in chunks. +When an OnEndElementL is received this means there is no more content to be sent. +@param aBytes is the raw content data for the element. + The client is responsible for converting the data to the + required character set if necessary. + In some instances the content may be binary and must not be converted. +@param aErrorCode is the error code. + If this is not KErrNone then special action may be required. +*/ +void CXmlEngContentHandler::OnContentL(const TDesC8& aBytes, TInt aErrorCode) +{ + if(iSkipIncludeElement) + { + return; + } + iContentHandler->OnContentL(aBytes, aErrorCode); +} + +/** +This method is a notification of the beginning of the scope of a prefix-URI Namespace mapping. +This method is always called before the corresponding OnStartElementL method. +@param aPrefix is the Namespace prefix being declared. +@param aUri is the Namespace URI the prefix is mapped to. +@param aErrorCode is the error code. + If this is not KErrNone then special action may be required. +*/ +void CXmlEngContentHandler::OnStartPrefixMappingL(const RString& aPrefix, const RString& aUri, + TInt aErrorCode) +{ + if(iSkipIncludeElement) + { + return; + } + iSkipPrefixMapping = EFalse; + HBufC8* pref = aPrefix.DesC().AllocL(); + HBufC8* uri = aUri.DesC().AllocL(); + iCachedPrefixes.AppendL(pref); + iCachedUris.AppendL(uri); + iCachedErrors.Append(aErrorCode); +} + +/** +This method is a notification of the end of the scope of a prefix-URI mapping. +This method is called after the corresponding DoEndElementL method. +@param aPrefix is the Namespace prefix that was mapped. +@param aErrorCode is the error code. + If this is not KErrNone then special action may be required. +*/ +void CXmlEngContentHandler::OnEndPrefixMappingL(const RString& aPrefix, TInt aErrorCode) +{ + if(iSkipPrefixMapping) + { + return; + } + iContentHandler->OnEndPrefixMappingL(aPrefix, aErrorCode); +} + +/** +This method is a notification of ignorable whitespace in element content. +@param aBytes are the ignored bytes from the document being parsed. +@param aErrorCode is the error code. + If this is not KErrNone then special action may be required. +*/ +void CXmlEngContentHandler::OnIgnorableWhiteSpaceL(const TDesC8& aBytes, TInt aErrorCode) +{ + if(iSkipIncludeElement) + { + return; + } + iContentHandler->OnIgnorableWhiteSpaceL(aBytes, aErrorCode); +} + +/** +This method is a notification of a skipped entity. If the parser encounters an +external entity it does not need to expand it - it can return the entity as aName +for the client to deal with. +@param aName is the name of the skipped entity. +@param aErrorCode is the error code. + If this is not KErrNone then special action may be required. +*/ +void CXmlEngContentHandler::OnSkippedEntityL(const RString& aName, TInt aErrorCode) +{ + if(iSkipIncludeElement) + { + return; + } + iContentHandler->OnSkippedEntityL(aName, aErrorCode); +} + +/** +This method is a receive notification of a processing instruction. +@param aTarget is the processing instruction target. +@param aData is the processing instruction data. If empty none was supplied. +@param aErrorCode is the error code. + If this is not KErrNone then special action may be required. +*/ +void CXmlEngContentHandler::OnProcessingInstructionL(const TDesC8& aTarget, + const TDesC8& aData, + TInt aErrorCode) +{ + if(iSkipIncludeElement) + { + return; + } + iContentHandler->OnProcessingInstructionL(aTarget, aData, aErrorCode); +} + +/** +This method indicates an error has occurred. +@param aError is the error code +*/ +void CXmlEngContentHandler::OnError(TInt aErrorCode) +{ + iContentHandler->OnError(aErrorCode); +} + +/** +This method obtains the interface matching the specified uid. +@return 0 if no interface matching the uid is found. + Otherwise, the this pointer cast to that interface. +@param aUid the uid identifying the required interface. +*/ +TAny* CXmlEngContentHandler::GetExtendedInterface(const TInt32 /*aUid*/) +{ + return 0; +} + +/** +This method strips CID string from "cid:" prefix to fetch the pure CID value +@return CID value +@param aCid CID string +*/ +TPtrC8 CXmlEngContentHandler::CidValue(const TDesC8& aCid) + { + _LIT8(KCidPrefix, "cid:*"); + TInt position = aCid.Match(KCidPrefix); + if(position < 0) + { + position = 0; + } + return aCid.Mid( position + KCidPrefix().Size() - 1); // minus star character (*) + } + +/** +This method converts element name to lower case and creates new tag info +@return New tag info with lower case element name +@param aTagInfo Original tag info +*/ +RTagInfo CXmlEngContentHandler::ConvertNameToLowerCaseL(const RTagInfo& aElement) + { + // convert name to lower case, create new RTagInfo, invoke callback + HBufC8* uriBuf = aElement.Uri().DesC().AllocLC(); + HBufC8* prefBuf = aElement.Prefix().DesC().AllocLC(); + HBufC8* nameBuf = aElement.LocalName().DesC().AllocLC(); + nameBuf->Des().LowerCase(); + + RString uri = iStrPool.OpenStringL(uriBuf->Des()); + CleanupClosePushL(uri); + RString pref = iStrPool.OpenStringL(prefBuf->Des()); + CleanupClosePushL(pref); + RString name = iStrPool.OpenStringL(nameBuf->Des()); + CleanupStack::Pop(&pref); + CleanupStack::Pop(&uri); + CleanupStack::PopAndDestroy(nameBuf); + CleanupStack::PopAndDestroy(prefBuf); + CleanupStack::PopAndDestroy(uriBuf); + RTagInfo elementTag; + elementTag.Open(uri, pref, name); + TPtrC8 a = elementTag.LocalName().DesC(); + return elementTag; + }