xml/xmldomandxpath/src/xmlengineserializer/xmlengcontenthandler.cpp
changeset 0 e35f40988205
child 16 58e164f13314
equal deleted inserted replaced
-1:000000000000 0:e35f40988205
       
     1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Content handler implementation
       
    15 //
       
    16 
       
    17 #include "xmlengcontenthandler.h"
       
    18 #include <xml/dom/xmlengerrors.h>
       
    19 #include <xml/dom/xmlengdeserializer.h>
       
    20 #include "xmlengdeserializerxop.h"
       
    21 #include <xml/dom/xmlengextendedcontenthandler.h>
       
    22 #include <xml/parserfeature.h>
       
    23 
       
    24 #include <xml/dom/xmlengserializeerrors.h>
       
    25 #include <bsul/clientmessage.h>
       
    26 
       
    27 CXmlEngContentHandler* CXmlEngContentHandler::NewL( CXmlEngDeserializer* aDeserializer,
       
    28 											   		MContentHandler* aContentHandler )
       
    29 	{
       
    30 	CXmlEngContentHandler* self = new (ELeave) CXmlEngContentHandler(aDeserializer, aContentHandler);
       
    31 	CleanupStack::PushL(self);
       
    32 	self->ConstructL();
       
    33 	CleanupStack::Pop(self); //self
       
    34 	return self;
       
    35 	}
       
    36 
       
    37 CXmlEngContentHandler::~CXmlEngContentHandler()
       
    38 	{
       
    39 	iCachedPrefixes.ResetAndDestroy();
       
    40 	iCachedUris.ResetAndDestroy();
       
    41 	iCachedErrors.Reset();
       
    42 	iStrPool.Close();
       
    43 	}
       
    44 
       
    45 CXmlEngContentHandler::CXmlEngContentHandler(CXmlEngDeserializer* aDeserializer, 
       
    46 									   		 MContentHandler* aContentHandler)
       
    47 : iDeserializer(aDeserializer),
       
    48   iContentHandler(aContentHandler)
       
    49 	{
       
    50 	iSkipIncludeElement = 0;
       
    51   	iSkipPrefixMapping = 0;
       
    52 	}
       
    53 
       
    54 void CXmlEngContentHandler::ConstructL()
       
    55 	{
       
    56 	iStrPool.OpenL();
       
    57 	}
       
    58 
       
    59 /**
       
    60 This method is a callback to indicate the start of the document.
       
    61 @param				aDocParam Specifies the various parameters of the document.
       
    62 @param				aDocParam.iCharacterSetName The character encoding of the document.
       
    63 @param				aErrorCode is the error code. 
       
    64 					If this is not KErrNone then special action may be required.
       
    65 */
       
    66 void CXmlEngContentHandler::OnStartDocumentL(const RDocumentParameters& aDocParam, TInt aErrorCode)
       
    67 {
       
    68 	iContentHandler->OnStartDocumentL(aDocParam, aErrorCode);
       
    69 }
       
    70 
       
    71 
       
    72 /**
       
    73 This method is a callback to indicate the end of the document.
       
    74 @param				aErrorCode is the error code. 
       
    75 					If this is not KErrNone then special action may be required.
       
    76 */
       
    77 void CXmlEngContentHandler::OnEndDocumentL(TInt aErrorCode)
       
    78 {
       
    79 	iContentHandler->OnEndDocumentL(aErrorCode);
       
    80 }
       
    81 
       
    82 
       
    83 /**
       
    84 This method is a callback to indicate an element has been parsed.
       
    85 @param				aElement is a handle to the element's details.
       
    86 @param				aAttributes contains the attributes for the element.
       
    87 @param				aErrorCode is the error code.
       
    88 					If this is not KErrNone then special action may be required.
       
    89 */
       
    90 void CXmlEngContentHandler::OnStartElementL(const RTagInfo& aElement,
       
    91 								 const RAttributeArray& aAttributes, 
       
    92 								 TInt aErrorCode)
       
    93 {
       
    94 	_LIT8(KInclude, "Include");
       
    95 	_LIT8(KXopIncludeUri, "http://www.w3.org/2004/08/xop/include");
       
    96 	_LIT8(KHref, "href");
       
    97 	_LIT8(KHrefUriEmpty, ""); 
       
    98 	
       
    99 	TBool xopInclude = EFalse;
       
   100 	
       
   101 	if(iSkipIncludeElement)
       
   102 		{
       
   103 		if( aElement.LocalName().DesC() == KInclude
       
   104 	    	&& aElement.Uri().DesC() == KXopIncludeUri)
       
   105 			{
       
   106 			xopInclude = ETrue;
       
   107 			++iSkipIncludeElement;				
       
   108 			}		
       
   109 		return;
       
   110 		}
       
   111 
       
   112 	MXmlEngExtendedHandler* ext = (MXmlEngExtendedHandler*)iContentHandler->GetExtendedInterface(MXmlEngExtendedHandler::EExtInterfaceUid);
       
   113 
       
   114 	// determine if this element is xop:Include
       
   115 	if( xopInclude ||
       
   116 		(aElement.LocalName().DesC() == KInclude &&
       
   117 	    aElement.Uri().DesC() == KXopIncludeUri))
       
   118 		{
       
   119 		for ( TInt i = 0; i < aAttributes.Count(); i++)
       
   120 			{
       
   121 			if( aAttributes[i].Attribute().LocalName().DesC() == KHref
       
   122 				&& aAttributes[i].Attribute().Uri().DesC() == KHrefUriEmpty)
       
   123 				{
       
   124 				TPtrC8 cidValue;
       
   125 				TPtrC8 data;
       
   126 				cidValue.Set(CidValue(aAttributes[i].Value().DesC()));
       
   127 				if( (CXmlEngDeserializer*)iDeserializer->ExternalData() 
       
   128 					 && iDeserializer->GetDataContainer(cidValue) )
       
   129 					{
       
   130 					++iSkipIncludeElement;
       
   131 					iSkipPrefixMapping = ETrue;
       
   132 					if(ext)
       
   133 						ext->OnDataContainerL(*iDeserializer->GetDataContainer(cidValue), KErrNone);	
       
   134 					}
       
   135 				else if(((CXmlEngDeserializerXOP*)iDeserializer)->GetData(cidValue, data) == KErrNone)					
       
   136 					{
       
   137 					++iSkipIncludeElement;
       
   138 					iSkipPrefixMapping = ETrue;
       
   139 					if(ext)
       
   140 						{
       
   141 						if(iDeserializer->ParsingOptions().iOptions & TXmlEngParsingOptions::KOptionEncodeToBase64)
       
   142 							{
       
   143 							//TImCodecB64 base64Codec; 
       
   144 							// The encoded length of base64 is about twice (use 3x) decoded length
       
   145 							HBufC8* data64 = HBufC8::NewLC(3*data.Size());  
       
   146 							TPtr8 data64Ptr = data64->Des();
       
   147 							// Encode to the base64 Content-Transfer-Encoding
       
   148 							//base64Codec.Encode(data, data64Ptr);
       
   149 							using namespace BSUL;
       
   150 							Base64Codec::Encode(data, data64Ptr);
       
   151 							if(data64Ptr.Length() == 0)
       
   152 								{
       
   153 								User::Leave(KErrGeneral);
       
   154 								}
       
   155 							ext->OnBinaryContentL(data64Ptr,cidValue,aErrorCode);
       
   156 							CleanupStack::PopAndDestroy(); //data64							
       
   157 							}
       
   158 						else
       
   159 							{
       
   160 							ext->OnBinaryContentL(data,cidValue,aErrorCode);			
       
   161 							}
       
   162 						}
       
   163 						
       
   164 					}
       
   165 				else
       
   166 					{
       
   167 					User::Leave(KXmlEngErrBinDataNotFound);
       
   168 					//iContentHandler->OnStartElementL(aElement, aAttributes, aErrorCode);
       
   169 					}						
       
   170 				}
       
   171 			} //for
       
   172 		}
       
   173 
       
   174 	if(!iSkipIncludeElement)
       
   175 		{
       
   176 		if(iCachedUris.Count())
       
   177 			{
       
   178 			RString prefix;
       
   179 			RString uri;
       
   180 			for(TInt i = 0; i < iCachedPrefixes.Count(); i++)
       
   181 				{
       
   182 				prefix = iStrPool.OpenStringL(iCachedPrefixes[i]->Des());
       
   183 				CleanupClosePushL(prefix);
       
   184 				uri = iStrPool.OpenStringL(iCachedUris[i]->Des());
       
   185 				CleanupClosePushL(uri);
       
   186 				iContentHandler->OnStartPrefixMappingL(prefix, uri, iCachedErrors[i]);
       
   187 				CleanupStack::PopAndDestroy(&uri);
       
   188 				CleanupStack::PopAndDestroy(&prefix);
       
   189 				}						
       
   190 			}
       
   191 		if(iDeserializer->IsFeatureEnabled(EConvertTagsToLowerCase))
       
   192 			{
       
   193 			RTagInfo elementTag = ConvertNameToLowerCaseL(aElement);
       
   194 			CleanupClosePushL(elementTag);
       
   195 			iContentHandler->OnStartElementL(elementTag, aAttributes, aErrorCode);
       
   196 			CleanupStack::PopAndDestroy(); //elementTag
       
   197 			}
       
   198 		else
       
   199 			{
       
   200 			iContentHandler->OnStartElementL(aElement, aAttributes, aErrorCode);				
       
   201 			}			
       
   202 		}
       
   203 	iCachedUris.ResetAndDestroy();
       
   204 	iCachedPrefixes.ResetAndDestroy();
       
   205 	iCachedErrors.Reset();
       
   206 }
       
   207 
       
   208 	
       
   209 /**
       
   210 This method is a callback to indicate the end of the element has been reached.
       
   211 @param				aElement is a handle to the element's details.
       
   212 @param				aErrorCode is the error code.
       
   213 					If this is not KErrNone then special action may be required.
       
   214 */
       
   215 void CXmlEngContentHandler::OnEndElementL(const RTagInfo& aElement, TInt aErrorCode)
       
   216 {
       
   217 	_LIT8(KInclude, "Include");
       
   218 	_LIT8(KXopIncludeUri, "http://www.w3.org/2004/08/xop/include");
       
   219 	
       
   220 	if(iSkipIncludeElement)
       
   221 		{
       
   222 		if( aElement.LocalName().DesC() == KInclude
       
   223 	    	&& aElement.Uri().DesC() == KXopIncludeUri)
       
   224 			{
       
   225 			--iSkipIncludeElement;				
       
   226 			}
       
   227 		return;
       
   228 		}
       
   229 	else
       
   230 	    {
       
   231 	    iSkipPrefixMapping = EFalse;
       
   232 	    }
       
   233 
       
   234 	if(iDeserializer->IsFeatureEnabled(EConvertTagsToLowerCase))
       
   235 		{
       
   236 		RTagInfo elementTag = ConvertNameToLowerCaseL(aElement);
       
   237 		CleanupClosePushL(elementTag);
       
   238 		iContentHandler->OnEndElementL(elementTag, aErrorCode);
       
   239 		CleanupStack::PopAndDestroy(&elementTag); //elementTag
       
   240 		}
       
   241 	else
       
   242 		{
       
   243 		iContentHandler->OnEndElementL(aElement, aErrorCode);	
       
   244 		}
       
   245 }
       
   246 
       
   247 /**
       
   248 This method is a callback that sends the content of the element.
       
   249 Not all the content may be returned in one go. The data may be sent in chunks.
       
   250 When an OnEndElementL is received this means there is no more content to be sent.
       
   251 @param				aBytes is the raw content data for the element. 
       
   252 					The client is responsible for converting the data to the 
       
   253 					required character set if necessary.
       
   254 					In some instances the content may be binary and must not be converted.
       
   255 @param				aErrorCode is the error code.
       
   256 					If this is not KErrNone then special action may be required.
       
   257 */
       
   258 void CXmlEngContentHandler::OnContentL(const TDesC8& aBytes, TInt aErrorCode)
       
   259 {
       
   260 	if(iSkipIncludeElement)
       
   261 		{
       
   262 		return;
       
   263 		}
       
   264 	iContentHandler->OnContentL(aBytes, aErrorCode);
       
   265 }
       
   266 	
       
   267 /**
       
   268 This method is a notification of the beginning of the scope of a prefix-URI Namespace mapping.
       
   269 This method is always called before the corresponding OnStartElementL method.
       
   270 @param				aPrefix is the Namespace prefix being declared.
       
   271 @param				aUri is the Namespace URI the prefix is mapped to.
       
   272 @param				aErrorCode is the error code.
       
   273 					If this is not KErrNone then special action may be required.
       
   274 */
       
   275 void CXmlEngContentHandler::OnStartPrefixMappingL(const RString& aPrefix, const RString& aUri, 
       
   276 									   TInt aErrorCode)
       
   277 {
       
   278 	if(iSkipIncludeElement)
       
   279 		{
       
   280 		return;
       
   281 		}
       
   282 	iSkipPrefixMapping = EFalse;
       
   283 	HBufC8* pref = aPrefix.DesC().AllocL();
       
   284 	HBufC8* uri = aUri.DesC().AllocL();
       
   285 	iCachedPrefixes.AppendL(pref);
       
   286 	iCachedUris.AppendL(uri);
       
   287 	iCachedErrors.Append(aErrorCode);
       
   288 }
       
   289 
       
   290 /**
       
   291 This method is a notification of the end of the scope of a prefix-URI mapping.
       
   292 This method is called after the corresponding DoEndElementL method.
       
   293 @param				aPrefix is the Namespace prefix that was mapped.
       
   294 @param				aErrorCode is the error code.
       
   295 					If this is not KErrNone then special action may be required.
       
   296 */
       
   297 void CXmlEngContentHandler::OnEndPrefixMappingL(const RString& aPrefix, TInt aErrorCode)
       
   298 {
       
   299 	if(iSkipPrefixMapping)
       
   300 		{
       
   301 		return;
       
   302 		}
       
   303 	iContentHandler->OnEndPrefixMappingL(aPrefix, aErrorCode);
       
   304 }
       
   305 
       
   306 /**
       
   307 This method is a notification of ignorable whitespace in element content.
       
   308 @param				aBytes are the ignored bytes from the document being parsed.
       
   309 @param				aErrorCode is the error code.
       
   310 					If this is not KErrNone then special action may be required.
       
   311 */
       
   312 void CXmlEngContentHandler::OnIgnorableWhiteSpaceL(const TDesC8& aBytes, TInt aErrorCode)
       
   313 {
       
   314 	if(iSkipIncludeElement)
       
   315 		{
       
   316 		return;
       
   317 		}
       
   318 	iContentHandler->OnIgnorableWhiteSpaceL(aBytes, aErrorCode);
       
   319 }
       
   320 
       
   321 /**
       
   322 This method is a notification of a skipped entity. If the parser encounters an 
       
   323 external entity it does not need to expand it - it can return the entity as aName 
       
   324 for the client to deal with.
       
   325 @param				aName is the name of the skipped entity.
       
   326 @param				aErrorCode is the error code.
       
   327 					If this is not KErrNone then special action may be required.
       
   328 */
       
   329 void CXmlEngContentHandler::OnSkippedEntityL(const RString& aName, TInt aErrorCode)
       
   330 {
       
   331 	if(iSkipIncludeElement)
       
   332 		{
       
   333 		return;
       
   334 		}
       
   335 	iContentHandler->OnSkippedEntityL(aName, aErrorCode);
       
   336 }
       
   337 
       
   338 /**
       
   339 This method is a receive notification of a processing instruction.
       
   340 @param				aTarget is the processing instruction target.
       
   341 @param				aData is the processing instruction data. If empty none was supplied.
       
   342 @param				aErrorCode is the error code.
       
   343 					If this is not KErrNone then special action may be required.
       
   344 */
       
   345 void CXmlEngContentHandler::OnProcessingInstructionL(const TDesC8& aTarget,
       
   346 										  const TDesC8& aData, 
       
   347 										  TInt aErrorCode)
       
   348 {
       
   349 	if(iSkipIncludeElement)
       
   350 		{
       
   351 		return;
       
   352 		}
       
   353 	iContentHandler->OnProcessingInstructionL(aTarget, aData, aErrorCode);
       
   354 }
       
   355 
       
   356 /**
       
   357 This method indicates an error has occurred.
       
   358 @param				aError is the error code
       
   359 */
       
   360 void CXmlEngContentHandler::OnError(TInt aErrorCode)
       
   361 {
       
   362 	iContentHandler->OnError(aErrorCode);	
       
   363 }
       
   364 
       
   365 /**
       
   366 This method obtains the interface matching the specified uid.
       
   367 @return				0 if no interface matching the uid is found.
       
   368 					Otherwise, the this pointer cast to that interface.
       
   369 @param				aUid the uid identifying the required interface.
       
   370 */
       
   371 TAny* CXmlEngContentHandler::GetExtendedInterface(const TInt32 /*aUid*/)
       
   372 {
       
   373 	return 0;	
       
   374 }
       
   375 
       
   376 /**
       
   377 This method strips CID string from "cid:" prefix to fetch the pure CID value
       
   378 @return				CID value
       
   379 @param				aCid CID string
       
   380 */
       
   381 TPtrC8 CXmlEngContentHandler::CidValue(const TDesC8& aCid)
       
   382 	{
       
   383 	_LIT8(KCidPrefix, "cid:*");
       
   384 	TInt position = aCid.Match(KCidPrefix);
       
   385 	if(position < 0)
       
   386 		{
       
   387 		position = 0;
       
   388 		}
       
   389 	return aCid.Mid( position + KCidPrefix().Size() - 1); // minus star character (*)
       
   390 	}
       
   391 
       
   392 /**
       
   393 This method converts element name to lower case and creates new tag info
       
   394 @return				New tag info with lower case element name
       
   395 @param				aTagInfo Original tag info
       
   396 */
       
   397 RTagInfo CXmlEngContentHandler::ConvertNameToLowerCaseL(const RTagInfo& aElement)
       
   398 	{
       
   399 	// convert name to lower case, create new RTagInfo, invoke callback
       
   400 	HBufC8* uriBuf = aElement.Uri().DesC().AllocLC();
       
   401 	HBufC8* prefBuf = aElement.Prefix().DesC().AllocLC();
       
   402 	HBufC8* nameBuf = aElement.LocalName().DesC().AllocLC();
       
   403 	nameBuf->Des().LowerCase();
       
   404 	
       
   405 	RString uri = iStrPool.OpenStringL(uriBuf->Des());
       
   406 	CleanupClosePushL(uri);
       
   407 	RString pref = iStrPool.OpenStringL(prefBuf->Des());
       
   408 	CleanupClosePushL(pref);
       
   409 	RString name = iStrPool.OpenStringL(nameBuf->Des());
       
   410 	CleanupStack::Pop(&pref);
       
   411 	CleanupStack::Pop(&uri);
       
   412 	CleanupStack::PopAndDestroy(nameBuf);
       
   413 	CleanupStack::PopAndDestroy(prefBuf);
       
   414 	CleanupStack::PopAndDestroy(uriBuf);
       
   415 	RTagInfo elementTag;
       
   416 	elementTag.Open(uri, pref, name);
       
   417 	TPtrC8 a = elementTag.LocalName().DesC();
       
   418 	return elementTag;	
       
   419 	}