|         |      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 // SAX libxml2 parser plugin | 
|         |     15 // | 
|         |     16  | 
|         |     17 #include "xmlengsaxplugin.h" | 
|         |     18 #include "xmlengsaxpluginerror.h" | 
|         |     19 #include "libxml2_globals_private.h" | 
|         |     20  | 
|         |     21 MParser* CXMLEngineSAXPlugin::NewL(TAny* aInitParams) | 
|         |     22 	{ | 
|         |     23  | 
|         |     24 	CXMLEngineSAXPlugin* self = new(ELeave)  | 
|         |     25 		CXMLEngineSAXPlugin(reinterpret_cast<TParserInitParams*>(aInitParams)); | 
|         |     26 	CleanupStack::PushL(self); | 
|         |     27 	self->ConstructL(); | 
|         |     28 	CleanupStack::Pop(self); | 
|         |     29  | 
|         |     30 	return (static_cast<MParser*>(self)); | 
|         |     31 	} | 
|         |     32 	 | 
|         |     33 	 | 
|         |     34 CXMLEngineSAXPlugin::CXMLEngineSAXPlugin(TParserInitParams* aInitParams) | 
|         |     35 :	iContentHandler (reinterpret_cast<MContentHandler*>(aInitParams->iContentHandler)), | 
|         |     36 	iStringDictionaryCollection (reinterpret_cast<RStringDictionaryCollection*> | 
|         |     37 											(aInitParams->iStringDictionaryCollection)), | 
|         |     38 	iCharSetConverter (reinterpret_cast<CCharSetConverter*>(aInitParams->iCharSetConverter)), | 
|         |     39 	iElementStack (reinterpret_cast<RElementStack*>(aInitParams->iElementStack)) | 
|         |     40 	{ | 
|         |     41 	}	 | 
|         |     42  | 
|         |     43  | 
|         |     44 void CXMLEngineSAXPlugin::ConstructL()  | 
|         |     45 	{ | 
|         |     46  | 
|         |     47 	//settings flag as EFalse | 
|         |     48 	Flag_Error_Status = EFalse; | 
|         |     49 		 | 
|         |     50 	//setting the callbacks for LibXML2 sax parser | 
|         |     51 	iParserEvents.externalSubset = ExternalSubset; | 
|         |     52 	iParserEvents.entityDecl = EntityDeclaration;		 | 
|         |     53 	iParserEvents.getEntity = GetEntityCal; | 
|         |     54 	iParserEvents.resolveEntity = ResolveEntity;	 | 
|         |     55 	iParserEvents.startDocument = StartDocument; | 
|         |     56 	iParserEvents.endDocument = EndDocument;		 | 
|         |     57 	iParserEvents.characters = Characters; | 
|         |     58 	iParserEvents.startPrefixMapping = StartPrefixMapping;		 | 
|         |     59 	iParserEvents.endPrefixMapping = EndPrefixMapping; | 
|         |     60 	iParserEvents.initialized = XML_SAX2_MAGIC; | 
|         |     61 	iParserEvents.startElementNs = StartElementNs; | 
|         |     62 	iParserEvents.endElementNs = EndElementNs; | 
|         |     63 	iParserEvents.ignorableWhitespace = IgnorableWhitespace;		 | 
|         |     64 	iParserEvents.processingInstruction = ProcessingInstruction; | 
|         |     65 	iParserEvents.serror = StructuredError; | 
|         |     66 	iParserEvents.getParameterEntity = GetParameterEntity; | 
|         |     67 		 | 
|         |     68 	//checking if content handler or dictionary are null | 
|         |     69 	User::LeaveIfNull(iContentHandler);  		 | 
|         |     70 	User::LeaveIfNull(iStringDictionaryCollection); | 
|         |     71 	 | 
|         |     72 	iStringPool = iStringDictionaryCollection->StringPool(); | 
|         |     73 	XmlEngineAttachL();	 | 
|         |     74 	} | 
|         |     75  | 
|         |     76 CXMLEngineSAXPlugin::~CXMLEngineSAXPlugin() | 
|         |     77     { | 
|         |     78     XmlEngineCleanup(iParserContext);    	 | 
|         |     79     iParserContext = NULL; | 
|         |     80          | 
|         |     81     //releasing rest of objects | 
|         |     82     iStringDictionaryCollection = NULL; | 
|         |     83 	iContentHandler = NULL; | 
|         |     84 	iCharSetConverter = NULL; | 
|         |     85 	iElementStack = NULL; | 
|         |     86 	 | 
|         |     87 	//releasing entity object | 
|         |     88 	iEntity.name = NULL; | 
|         |     89 	iEntity.orig = NULL; | 
|         |     90 	iEntity.content = NULL; | 
|         |     91 	} | 
|         |     92  | 
|         |     93  | 
|         |     94 //From MParser | 
|         |     95 		 | 
|         |     96 /**  | 
|         |     97  * Enable a feature.  | 
|         |     98  */ | 
|         |     99 TInt CXMLEngineSAXPlugin::EnableFeature(TInt aParserFeature) | 
|         |    100 	{ | 
|         |    101 	if(aParserFeature & ~(KFeatures)) | 
|         |    102 		return KErrNotSupported; | 
|         |    103  | 
|         |    104 	iParserMode |= aParserFeature; | 
|         |    105  | 
|         |    106 	return KErrNone; | 
|         |    107 	} | 
|         |    108 		  | 
|         |    109 /**  | 
|         |    110  * Disable a feature.  | 
|         |    111  */ | 
|         |    112 TInt CXMLEngineSAXPlugin::DisableFeature(TInt aParserFeature) | 
|         |    113 	{ | 
|         |    114 	if(aParserFeature & ~(KFeatures)) | 
|         |    115 		return KErrNotSupported; | 
|         |    116  | 
|         |    117 	iParserMode &= ~aParserFeature; | 
|         |    118  | 
|         |    119 	return KErrNone; | 
|         |    120 	}	 | 
|         |    121  | 
|         |    122 /**  | 
|         |    123  * See if a feature is enabled.  | 
|         |    124  */	 | 
|         |    125 TBool CXMLEngineSAXPlugin::IsFeatureEnabled(TInt aParserFeature) const | 
|         |    126 	{ | 
|         |    127 	return iParserMode & aParserFeature; | 
|         |    128 	} | 
|         |    129  | 
|         |    130 void CXMLEngineSAXPlugin::StopParsing(TInt aError) | 
|         |    131     { | 
|         |    132     if(iParserContext) | 
|         |    133         { | 
|         |    134         xmlStopParser(iParserContext); | 
|         |    135         iParserContext->errNo = aError;     | 
|         |    136         if ( aError == KErrNoMemory )  | 
|         |    137             { | 
|         |    138             xmlSetOOM(); | 
|         |    139             } | 
|         |    140         }     | 
|         |    141     } | 
|         |    142  | 
|         |    143 /**  | 
|         |    144  * Parses a descriptor that contains part of a document.  | 
|         |    145  */ | 
|         |    146 void CXMLEngineSAXPlugin::ParseChunkL(const TDesC8& aDescriptor) | 
|         |    147 	{	 | 
|         |    148 	 | 
|         |    149 	TInt result = KErrNone; | 
|         |    150 	 | 
|         |    151 	if (!iParserContext) | 
|         |    152 		{		 | 
|         |    153 		//creating sax parser object | 
|         |    154 	    iParserContext = xmlCreatePushParserCtxt(  | 
|         |    155    						(xmlSAXHandler*) &iParserEvents,  | 
|         |    156    						this,  | 
|         |    157   						(const char *) aDescriptor.Ptr(),  | 
|         |    158 						aDescriptor.Length(), | 
|         |    159    						NULL | 
|         |    160    						); | 
|         |    161 		if(!iParserContext) | 
|         |    162 			{ | 
|         |    163 			CleanupAndLeaveL(KErrNoMemory);			 | 
|         |    164 			} | 
|         |    165 		 | 
|         |    166 		//creating empty document object | 
|         |    167 		iParserContext->myDoc = xmlNewDoc(BAD_CAST "SAX compatibility mode document"); | 
|         |    168 		if(!iParserContext->myDoc) | 
|         |    169 			{ | 
|         |    170 			CleanupAndLeaveL(KErrNoMemory);			 | 
|         |    171 			} | 
|         |    172 		iParserContext->myDoc->intSubset = xmlNewDtd(iParserContext->myDoc, BAD_CAST "fake", NULL, NULL); | 
|         |    173 		if(!iParserContext->myDoc->intSubset) | 
|         |    174 			{ | 
|         |    175 			CleanupAndLeaveL(KErrNoMemory);			 | 
|         |    176 			} | 
|         |    177 		 | 
|         |    178 		//parsing process | 
|         |    179 	    result = xmlParseChunk(iParserContext, NULL, 0, 0);					 | 
|         |    180 		} | 
|         |    181 	else | 
|         |    182 		{ | 
|         |    183 		//parsing process | 
|         |    184 		result = xmlParseChunk( | 
|         |    185 				iParserContext,  | 
|         |    186 				(const char *) aDescriptor.Ptr(),  | 
|         |    187 				aDescriptor.Length(), | 
|         |    188 				0);		 | 
|         |    189 		} | 
|         |    190 					 | 
|         |    191 	//handling error situation | 
|         |    192 	//if fatal error, function throws exception  | 
|         |    193 	//in any other case next chunk is taken (recoverable) | 
|         |    194 	if ((result == XML_ERR_NO_MEMORY) || (iParserContext->lastError.level == XML_ERR_FATAL) | 
|         |    195 	        || (result < 0)) | 
|         |    196 		{ | 
|         |    197 		CleanupAndLeaveL(GetErrorNum(result));	 | 
|         |    198 		} | 
|         |    199 	} | 
|         |    200 	 | 
|         |    201 /**  | 
|         |    202  * Parses a descriptor that contains the last  part of a document.  | 
|         |    203  */ | 
|         |    204 void CXMLEngineSAXPlugin::ParseLastChunkL(const TDesC8& /*aDescriptor*/) | 
|         |    205 	{ | 
|         |    206 	if (!iParserContext) | 
|         |    207 		{ | 
|         |    208 		User::Leave(EXmlParserError); | 
|         |    209 		} | 
|         |    210  | 
|         |    211 	//parsing process | 
|         |    212 	TInt result(KErrNone); | 
|         |    213 	result = xmlParseChunk(iParserContext, NULL, 0, 1); | 
|         |    214 	if ((result == XML_ERR_NO_MEMORY) || (iParserContext->lastError.level == XML_ERR_FATAL) | 
|         |    215 	        || (result < 0)) | 
|         |    216 		{ | 
|         |    217 		CleanupAndLeaveL(GetErrorNum(result));			 | 
|         |    218 		}			 | 
|         |    219 		 | 
|         |    220 	//releasing context to the parser | 
|         |    221     xmlParserCtxtPtr ctxt = reinterpret_cast<xmlParserCtxtPtr>(iParserContext); | 
|         |    222     if(ctxt->myDoc)                      | 
|         |    223        { | 
|         |    224        xmlFreeDoc(ctxt->myDoc);  | 
|         |    225        } | 
|         |    226     xmlFreeParserCtxt(ctxt); | 
|         |    227 	iParserContext = NULL;	 | 
|         |    228 	 | 
|         |    229 	} | 
|         |    230  | 
|         |    231 /**  | 
|         |    232  * Interfaces don't have a destructor, so we have an explicit method instead.  | 
|         |    233  */ | 
|         |    234 void CXMLEngineSAXPlugin::Release() | 
|         |    235 	{ | 
|         |    236 	delete this; | 
|         |    237 	} | 
|         |    238  | 
|         |    239 void CXMLEngineSAXPlugin::CleanupAndLeaveL(TInt aError) | 
|         |    240 	{ | 
|         |    241 	// reseting OOM flag | 
|         |    242 	if((aError == KErrNoMemory) && xmlOOMFlag()) | 
|         |    243 	    { | 
|         |    244 	    xmlResetOOM(); | 
|         |    245 	    } | 
|         |    246  | 
|         |    247 	//releasing context to the parser | 
|         |    248 	if(iParserContext) | 
|         |    249 	    {	     | 
|         |    250         xmlParserCtxtPtr ctxt = reinterpret_cast<xmlParserCtxtPtr>(iParserContext); | 
|         |    251         if(ctxt->myDoc)                      | 
|         |    252             { | 
|         |    253             xmlFreeDoc(ctxt->myDoc);  | 
|         |    254             } | 
|         |    255         xmlFreeParserCtxt(ctxt);		 | 
|         |    256 	    } | 
|         |    257     iParserContext = NULL; | 
|         |    258 	 | 
|         |    259 	if (aError) | 
|         |    260 		{ | 
|         |    261 		User::Leave(aError);			 | 
|         |    262 		} | 
|         |    263 	else | 
|         |    264 		{ | 
|         |    265 		User::Leave(EXmlParserError); | 
|         |    266 		} | 
|         |    267 	} | 
|         |    268  | 
|         |    269 // From MContentSouce | 
|         |    270 	 | 
|         |    271 /**  | 
|         |    272  * This method tells us what's the next content handler in the chain.  | 
|         |    273  */			 | 
|         |    274 void CXMLEngineSAXPlugin::SetContentSink (MContentHandler& aContentHandler) | 
|         |    275 	{ | 
|         |    276 	iContentHandler = &aContentHandler; | 
|         |    277 	} | 
|         |    278  | 
|         |    279  | 
|         |    280 //Public getter and setter method | 
|         |    281 		 | 
|         |    282 /** | 
|         |    283  * This method returns a parser context object.  | 
|         |    284  */	 | 
|         |    285 xmlParserCtxtPtr CXMLEngineSAXPlugin::getParserContext() const | 
|         |    286 	{ | 
|         |    287 	return iParserContext; | 
|         |    288 	} | 
|         |    289 	 | 
|         |    290 xmlEntity& CXMLEngineSAXPlugin::GetEntity() | 
|         |    291 	{ | 
|         |    292 	return iEntity; | 
|         |    293 	} | 
|         |    294  | 
|         |    295  | 
|         |    296 // __________________________________________________________________________ | 
|         |    297 // Exported proxy for instantiation method resolution | 
|         |    298 // Define the interface UIDs | 
|         |    299 const TImplementationProxy ImplementationTable[] = { | 
|         |    300 	IMPLEMENTATION_PROXY_ENTRY(0x101f9783, CXMLEngineSAXPlugin::NewL) | 
|         |    301 	}; | 
|         |    302  | 
|         |    303  | 
|         |    304 EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount) | 
|         |    305 	{ | 
|         |    306 	aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy); | 
|         |    307  | 
|         |    308 	return ImplementationTable; | 
|         |    309 	} | 
|         |    310 	 |