|         |      1 // Copyright (c) 2004-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 // GMXMLCOMPOSE.CPP | 
|         |     15 // @file | 
|         |     16 // This file contains the declaration of the generic CMDXMLComposer class  | 
|         |     17 // which is responsible for creating an XML file | 
|         |     18 // from a given DOM structure. | 
|         |     19 //  | 
|         |     20 // | 
|         |     21  | 
|         |     22 #include <f32file.h> | 
|         |     23 #include <utf.h> | 
|         |     24  | 
|         |     25 #include <gmxmlconstants.h> | 
|         |     26 #include <gmxmlnode.h> | 
|         |     27 #include <gmxmldocument.h> | 
|         |     28 #include <gmxmlelement.h> | 
|         |     29 #include <gmxmlcomposer.h> | 
|         |     30 #include <gmxmlentityconverter.h> | 
|         |     31 #include <gmxmltext.h> | 
|         |     32 #include <gmxmlprocessinginstruction.h> | 
|         |     33 #include <gmxmlcomment.h> | 
|         |     34 #include <gmxmlcdatasection.h> | 
|         |     35 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS  | 
|         |     36 #include "gmxmldummydtd.h" | 
|         |     37 #endif | 
|         |     38  | 
|         |     39 _LIT(KXmlQuotation, """); | 
|         |     40  | 
|         |     41 // | 
|         |     42 // CMDXMLComposer					// | 
|         |     43 // | 
|         |     44  | 
|         |     45 CMDXMLComposer::CMDXMLComposer(MMDXMLComposerObserver* aComposerObserver) : CActive(EPriorityNormal) | 
|         |     46 // | 
|         |     47 // Constructor | 
|         |     48 // | 
|         |     49 	{ | 
|         |     50 	iComposerObserver = aComposerObserver; | 
|         |     51 	iOutputProlog = ETrue; | 
|         |     52 	CActiveScheduler::Add(this); | 
|         |     53 	} | 
|         |     54 	 | 
|         |     55 CMDXMLComposer::CMDXMLComposer(MMDXMLComposerObserver* aComposerObserver, TBool aOutputProlog) : CActive(EPriorityNormal), | 
|         |     56 	iOutputProlog(aOutputProlog) | 
|         |     57 // | 
|         |     58 // Constructor | 
|         |     59 // | 
|         |     60 	{ | 
|         |     61 	iComposerObserver = aComposerObserver; | 
|         |     62 	CActiveScheduler::Add(this); | 
|         |     63 	} | 
|         |     64 //================================================================================== | 
|         |     65  | 
|         |     66 EXPORT_C CMDXMLComposer::~CMDXMLComposer() | 
|         |     67 	{ | 
|         |     68 	Cancel(); | 
|         |     69 	delete iEntityConverter; | 
|         |     70 	delete iCharconv; | 
|         |     71  | 
|         |     72 	iXMLFile.Close(); | 
|         |     73 	} | 
|         |     74  | 
|         |     75 //================================================================================== | 
|         |     76  | 
|         |     77 void CMDXMLComposer::BaseConstructL() | 
|         |     78 	{ | 
|         |     79 	iCharconv = CCnvCharacterSetConverter::NewL(); | 
|         |     80 	iCharconv->SetDowngradeForExoticLineTerminatingCharacters( | 
|         |     81 		CCnvCharacterSetConverter::EDowngradeExoticLineTerminatingCharactersToJustLineFeed); | 
|         |     82 	} | 
|         |     83  | 
|         |     84 //================================================================================== | 
|         |     85  | 
|         |     86 EXPORT_C CMDXMLComposer* CMDXMLComposer::NewL(MMDXMLComposerObserver* aComposerObserver) | 
|         |     87 // | 
|         |     88 // Two phase static factory function constructor | 
|         |     89 // @param aEntityStrings the string table which lists the entity references and conversion | 
|         |     90 // @return Created CMDXMLComposer | 
|         |     91 // @leave can Leave due to OOM | 
|         |     92 // | 
|         |     93 	{ | 
|         |     94 	CMDXMLComposer* self = NewLC(aComposerObserver); | 
|         |     95 	CleanupStack::Pop(self); | 
|         |     96 	return self; | 
|         |     97 	} | 
|         |     98 	 | 
|         |     99 //================================================================================== | 
|         |    100  | 
|         |    101 EXPORT_C CMDXMLComposer* CMDXMLComposer::NewL(MMDXMLComposerObserver* aComposerObserver, TBool aOutputProlog) | 
|         |    102 // | 
|         |    103 // Two phase static factory function constructor | 
|         |    104 // @param aEntityStrings the string table which lists the entity references and conversion | 
|         |    105 // @param aOutputProlog Whether the Doctype and Version tags should be output.  This is | 
|         |    106 // provided for MMS conformance. | 
|         |    107 // @return Created CMDXMLComposer | 
|         |    108 // @leave can Leave due to OOM | 
|         |    109 // | 
|         |    110 	{ | 
|         |    111 	CMDXMLComposer* self = NewLC(aComposerObserver, aOutputProlog); | 
|         |    112 	CleanupStack::Pop(self); | 
|         |    113 	return self; | 
|         |    114 	} | 
|         |    115 	 | 
|         |    116 //================================================================================== | 
|         |    117  | 
|         |    118 EXPORT_C CMDXMLComposer* CMDXMLComposer::NewLC(MMDXMLComposerObserver* aComposerObserver) | 
|         |    119 // | 
|         |    120 // Two phase static factory function constructor | 
|         |    121 // @param aEntityStrings the string table which lists the entity references and conversion | 
|         |    122 // @return Created CMDXMLComposer | 
|         |    123 // @leave can Leave due to OOM | 
|         |    124 // | 
|         |    125 	{ | 
|         |    126 	CMDXMLComposer* self = new (ELeave) CMDXMLComposer(aComposerObserver); | 
|         |    127 	CleanupStack::PushL(self); | 
|         |    128 	self->ConstructL(); | 
|         |    129 	return self; | 
|         |    130 	} | 
|         |    131 	 | 
|         |    132 //================================================================================== | 
|         |    133  | 
|         |    134 EXPORT_C CMDXMLComposer* CMDXMLComposer::NewLC(MMDXMLComposerObserver* aComposerObserver, TBool aOutputProlog) | 
|         |    135 // | 
|         |    136 // Two phase static factory function constructor | 
|         |    137 // @param aEntityStrings the string table which lists the entity references and conversion | 
|         |    138 // @param aOutputProlog Whether the Doctype and Version tags should be output.  This is | 
|         |    139 // provided for MMS conformance. | 
|         |    140 // @return Created CMDXMLComposer | 
|         |    141 // @leave can Leave due to OOM | 
|         |    142 // | 
|         |    143 	{ | 
|         |    144 	CMDXMLComposer* self = new (ELeave) CMDXMLComposer(aComposerObserver, aOutputProlog); | 
|         |    145 	CleanupStack::PushL(self); | 
|         |    146 	self->ConstructL(); | 
|         |    147 	return self; | 
|         |    148 	} | 
|         |    149 	 | 
|         |    150 //================================================================================== | 
|         |    151  | 
|         |    152 void CMDXMLComposer::ConstructL() | 
|         |    153 // | 
|         |    154 // Second stage constructor | 
|         |    155 // @param aEntityStrings the string table which lists the entity references and conversion | 
|         |    156 // | 
|         |    157 	{ | 
|         |    158 	BaseConstructL(); | 
|         |    159 	CMDXMLEntityConverter* entityConverter = new(ELeave) CMDXMLEntityConverter(); | 
|         |    160 	SetEntityConverter(entityConverter); | 
|         |    161 	} | 
|         |    162  | 
|         |    163  | 
|         |    164 //================================================================================== | 
|         |    165  | 
|         |    166 void CMDXMLComposer::InitialiseCompose(CMDXMLDocument* aDocument, TXMLFileType aFileType) | 
|         |    167 	{ | 
|         |    168 	Cancel(); | 
|         |    169 	 | 
|         |    170 	iError = KErrNone; | 
|         |    171 	iSeverity = EXMLNone; | 
|         |    172 	iOutputBuffer.Zero(); | 
|         |    173  | 
|         |    174 	iXMLDoc = aDocument; | 
|         |    175 	iFileType = aFileType; | 
|         |    176  | 
|         |    177 	iOnlyCalculatingSize = EFalse; | 
|         |    178 	iSizeTally = 0; | 
|         |    179 	} | 
|         |    180  | 
|         |    181 EXPORT_C TInt CMDXMLComposer::ComposeFile(RFs aRFs, const TDesC& aFileToCompose, CMDXMLDocument* aDocument, TXMLFileType aFileType) | 
|         |    182 /** Starts file composition. | 
|         |    183  | 
|         |    184 This function can not be called if there is an outstanding size calculation or compose | 
|         |    185 operation in progress. If it is necessary to run two asynchronous operations in parallel | 
|         |    186 then two instances of the CMDXMLComposer are needed. | 
|         |    187  | 
|         |    188 @param aRFS File system to use | 
|         |    189 @param aFileToCompose Name of file to create | 
|         |    190 @param aDocument The document object to compose to the file | 
|         |    191 @return KERRNone if successful | 
|         |    192 **/ | 
|         |    193 	{ | 
|         |    194 	InitialiseCompose(aDocument, aFileType); | 
|         |    195 	iRFs = aRFs; | 
|         |    196 	TInt error = KErrNone; | 
|         |    197  | 
|         |    198 	if(iXMLDoc == NULL) | 
|         |    199 		{ | 
|         |    200 		error = KErrNotSupported; | 
|         |    201 		} | 
|         |    202 	else | 
|         |    203 		{ | 
|         |    204 		switch(iFileType) | 
|         |    205 			{ | 
|         |    206 			case EAscii: | 
|         |    207 				{ | 
|         |    208 				error = iXMLFile.Replace(aRFs, aFileToCompose, EFileWrite | EFileStream); | 
|         |    209 				break; | 
|         |    210 				} | 
|         |    211 			case EUnicode: | 
|         |    212 				error = iXMLFile.Replace(aRFs, aFileToCompose, EFileWrite | EFileStream); | 
|         |    213 				if(error == KErrNone) | 
|         |    214 					{ | 
|         |    215 					// append Unicode File identifier to start of output text | 
|         |    216 					iOutputBuffer.Append(CEditableText::EByteOrderMark); | 
|         |    217 					} | 
|         |    218 				break; | 
|         |    219 			case EUtf8: | 
|         |    220 				{ | 
|         |    221 				error = iXMLFile.Replace(aRFs, aFileToCompose, EFileWrite | EFileStream); | 
|         |    222 				break; | 
|         |    223 				} | 
|         |    224 			default: | 
|         |    225 				error = KErrNotSupported; | 
|         |    226 				break; | 
|         |    227 			} | 
|         |    228 		} | 
|         |    229  | 
|         |    230 	if(error == KErrNone) | 
|         |    231 		{ | 
|         |    232 		SetActive(); | 
|         |    233 		TRequestStatus* s=&iStatus; | 
|         |    234 		User::RequestComplete(s, KErrNone); | 
|         |    235 		} | 
|         |    236 	else | 
|         |    237 		{ | 
|         |    238 		SetError(error, EXMLFatal); | 
|         |    239 		} | 
|         |    240  | 
|         |    241 	return error; | 
|         |    242 	} | 
|         |    243 	 | 
|         |    244 /** Starts file composition to an open file handle. | 
|         |    245  | 
|         |    246 This function must not be called when file sizing is in progress. If it is necessary to calulate | 
|         |    247 the size and generate the XML simultaneously then two instances of the composer should be used, | 
|         |    248 one for sizing and one for composition. | 
|         |    249  | 
|         |    250 @param aFileHandleToCompose An open file handle to write to. Ownership of the file handle is passed even if an error occurs. | 
|         |    251 @param aDocument The document object to compose to the file. | 
|         |    252 @param aFileType Type of the output file. | 
|         |    253 @return KErrNone if successful. | 
|         |    254 */ | 
|         |    255 EXPORT_C TInt CMDXMLComposer::ComposeFile(RFile& aFileHandleToCompose, CMDXMLDocument* aDocument, TXMLFileType aFileType) | 
|         |    256 	{ | 
|         |    257 	InitialiseCompose(aDocument, aFileType); | 
|         |    258 	iXMLFile = aFileHandleToCompose; | 
|         |    259 	TInt error = KErrNone; | 
|         |    260  | 
|         |    261 	if(iXMLDoc == NULL) | 
|         |    262 		{ | 
|         |    263 		error = KErrNotSupported; | 
|         |    264 		} | 
|         |    265 	else | 
|         |    266 		{ | 
|         |    267 		switch(iFileType) | 
|         |    268 			{ | 
|         |    269 			case EUnicode: | 
|         |    270 				{ | 
|         |    271 				// append Unicode File identifier to start of output text | 
|         |    272 				iOutputBuffer.Append(CEditableText::EByteOrderMark); | 
|         |    273 				} | 
|         |    274 			case EAscii: | 
|         |    275 			case EUtf8: | 
|         |    276 				break; | 
|         |    277 			 | 
|         |    278 			default: | 
|         |    279 				error = KErrNotSupported; | 
|         |    280 				break; | 
|         |    281 			} | 
|         |    282 		} | 
|         |    283 	 | 
|         |    284 	if(error == KErrNone) | 
|         |    285 		{ | 
|         |    286 		iStatus = KRequestPending; | 
|         |    287 		SetActive(); | 
|         |    288 		TRequestStatus* s=&iStatus; | 
|         |    289 		User::RequestComplete(s, KErrNone); | 
|         |    290 		} | 
|         |    291 	else | 
|         |    292 		{ | 
|         |    293 		iXMLFile.Close(); | 
|         |    294 		SetError(error, EXMLFatal); | 
|         |    295 		} | 
|         |    296  | 
|         |    297 	return error; | 
|         |    298 	} | 
|         |    299  | 
|         |    300 //================================================================================== | 
|         |    301  | 
|         |    302 /** Starts calculating the size of the XML output without actually writing it to the file. | 
|         |    303  | 
|         |    304 This process is asyncronous, the size value is only updated when ComposeFileComplete | 
|         |    305 is called on the MMDXMLComposerObserver passed in in the NewL. | 
|         |    306  | 
|         |    307 This function can not be called if there is an outstanding size calculation or compose | 
|         |    308 operation in progress. If it is necessary to run two asynchronous operations in parallel | 
|         |    309 then two instances of CMDXMLComposer are needed. | 
|         |    310  | 
|         |    311 @param aSize Will be set to the size of the XML document when composition has completed. | 
|         |    312 @param aDocument The document object to size | 
|         |    313 @param aFileType Type of the output file, required because it will affect the size of the XML | 
|         |    314 @return KErrNone if successful */ | 
|         |    315  | 
|         |    316 EXPORT_C TInt CMDXMLComposer::CalculateFileSize(TInt& aSize, CMDXMLDocument* aDocument, TXMLFileType aFileType) | 
|         |    317 	{ | 
|         |    318 	Cancel(); | 
|         |    319 	 | 
|         |    320 	iError = KErrNone; | 
|         |    321 	iSeverity = EXMLNone; | 
|         |    322 	iOutputBuffer.Zero(); | 
|         |    323  | 
|         |    324 	iXMLDoc = aDocument; | 
|         |    325 	iFileType = aFileType; | 
|         |    326 	TInt error = KErrNone; | 
|         |    327  | 
|         |    328 	if (iFileType == EUnicode) | 
|         |    329 		{ | 
|         |    330 		// The size tally must be incremented by two characters because the unicode byte marker | 
|         |    331 		// gets added in the ComposeFile function that does not get called when we are calculating | 
|         |    332 		// the size. | 
|         |    333 		iSizeTally = 2; | 
|         |    334 		} | 
|         |    335 	else | 
|         |    336 		{ | 
|         |    337 		iSizeTally = 0; | 
|         |    338 		} | 
|         |    339  | 
|         |    340 	iSize = &aSize; | 
|         |    341 	iOnlyCalculatingSize = ETrue; | 
|         |    342  | 
|         |    343 	if(iXMLDoc == NULL) | 
|         |    344 		{ | 
|         |    345 		error = KErrNotSupported; | 
|         |    346 		} | 
|         |    347  | 
|         |    348 	if(error == KErrNone) | 
|         |    349 		{ | 
|         |    350 		SetActive(); | 
|         |    351 		TRequestStatus* s=&iStatus; | 
|         |    352 		User::RequestComplete(s, KErrNone); | 
|         |    353 		} | 
|         |    354 	else | 
|         |    355 		{ | 
|         |    356 		SetError(error, EXMLFatal); | 
|         |    357 		} | 
|         |    358  | 
|         |    359 	return error; | 
|         |    360 	} | 
|         |    361  | 
|         |    362 //================================================================================== | 
|         |    363  | 
|         |    364 EXPORT_C TInt CMDXMLComposer::Error() const | 
|         |    365 	{ | 
|         |    366 	return iError; | 
|         |    367 	} | 
|         |    368  | 
|         |    369 //================================================================================== | 
|         |    370  | 
|         |    371 EXPORT_C TXMLErrorCodeSeverity CMDXMLComposer::ErrorSeverity() const | 
|         |    372 	{ | 
|         |    373 	return iSeverity; | 
|         |    374 	} | 
|         |    375  | 
|         |    376 //================================================================================== | 
|         |    377 	 | 
|         |    378 EXPORT_C CMDXMLEntityConverter* CMDXMLComposer::EntityConverter() const | 
|         |    379 	{ | 
|         |    380 	return iEntityConverter; | 
|         |    381 	} | 
|         |    382  | 
|         |    383 //================================================================================== | 
|         |    384  | 
|         |    385 TInt CMDXMLComposer::OutputCommentL(const TDesC& aComment) | 
|         |    386 // | 
|         |    387 // Output a comment | 
|         |    388 // @param aComment the comment text to output | 
|         |    389 // @return KERRNone if successful, otherwise a file writing error. | 
|         |    390 // | 
|         |    391 	{ | 
|         |    392 	TInt error = KErrNone; | 
|         |    393  | 
|         |    394 	if(iSeverity != EXMLFatal) | 
|         |    395 		{ | 
|         |    396 		error = WriteFileL(KNewLine); | 
|         |    397 		} | 
|         |    398  | 
|         |    399 #ifdef _DEBUG | 
|         |    400 	for(TInt loopIndex = 0; loopIndex < iIndentationLevel; loopIndex++) | 
|         |    401 		{ | 
|         |    402 		if(iSeverity != EXMLFatal) | 
|         |    403 			{ | 
|         |    404 			error = WriteFileL(KTab); | 
|         |    405 			} | 
|         |    406 		} | 
|         |    407 #endif | 
|         |    408  | 
|         |    409 	if(iSeverity != EXMLFatal) | 
|         |    410 		{ | 
|         |    411 		error = WriteFileL(KXMLStartComment); | 
|         |    412 		} | 
|         |    413  | 
|         |    414 	if(iSeverity != EXMLFatal) | 
|         |    415 		{ | 
|         |    416 		error = WriteFileL(aComment); | 
|         |    417 		} | 
|         |    418  | 
|         |    419 	if(iSeverity != EXMLFatal) | 
|         |    420 		{ | 
|         |    421 		error = WriteFileL(KXMLEndComment); | 
|         |    422 		} | 
|         |    423  | 
|         |    424 	return error; | 
|         |    425 	} | 
|         |    426  | 
|         |    427 //================================================================================== | 
|         |    428  | 
|         |    429 TInt CMDXMLComposer::OutputProcessingInstructionL(const TDesC& aInstruction) | 
|         |    430 // | 
|         |    431 // Output a Processing Instruction | 
|         |    432 // @param aInstruction the Processing Instruction text to output | 
|         |    433 // @return KERRNone if successful, otherwise a file writing error. | 
|         |    434 // | 
|         |    435 	{ | 
|         |    436 	TInt error = KErrNone; | 
|         |    437  | 
|         |    438 	if(iSeverity != EXMLFatal) | 
|         |    439 		{ | 
|         |    440 		error = WriteFileL(KNewLine); | 
|         |    441 		} | 
|         |    442  | 
|         |    443 #ifdef _DEBUG | 
|         |    444 	for(TInt loopIndex = 0; loopIndex < iIndentationLevel; loopIndex++) | 
|         |    445 		{ | 
|         |    446 		if(iSeverity != EXMLFatal) | 
|         |    447 			{ | 
|         |    448 			error = WriteFileL(KTab); | 
|         |    449 			} | 
|         |    450 		} | 
|         |    451 #endif | 
|         |    452  | 
|         |    453 	if(iSeverity != EXMLFatal) | 
|         |    454 		{ | 
|         |    455 		error = WriteFileL(KXMLStartProcessingInstruction); | 
|         |    456 		} | 
|         |    457  | 
|         |    458 	if(iSeverity != EXMLFatal) | 
|         |    459 		{ | 
|         |    460 		error = WriteFileL(aInstruction); | 
|         |    461 		} | 
|         |    462  | 
|         |    463 	if(iSeverity != EXMLFatal) | 
|         |    464 		{ | 
|         |    465 		error = WriteFileL(KXMLEndProcessingInstruction); | 
|         |    466 		} | 
|         |    467  | 
|         |    468 	return error; | 
|         |    469 	} | 
|         |    470  | 
|         |    471  | 
|         |    472 //================================================================================== | 
|         |    473  | 
|         |    474 TInt CMDXMLComposer::OutputCDataSectionL(const TDesC& aCDataSection) | 
|         |    475 // | 
|         |    476 // Output a CDataSection | 
|         |    477 // @param aCDataSection the data section text to output | 
|         |    478 // @return KERRNone if successful, otherwise a file writing error. | 
|         |    479 // | 
|         |    480 	{ | 
|         |    481 	TInt error = KErrNone; | 
|         |    482 	 | 
|         |    483 #ifdef _DEBUG | 
|         |    484 	for(TInt loopIndex = 0; loopIndex < iIndentationLevel; loopIndex++) | 
|         |    485 		{ | 
|         |    486 		if(iSeverity != EXMLFatal) | 
|         |    487 			{ | 
|         |    488 			error = WriteFileL(KTab); | 
|         |    489 			} | 
|         |    490 		} | 
|         |    491 #endif | 
|         |    492  | 
|         |    493 	if(iSeverity != EXMLFatal) | 
|         |    494 		{ | 
|         |    495 		error = WriteFileL(KXMLStartCDataSection); | 
|         |    496 		} | 
|         |    497  | 
|         |    498 	if(iSeverity != EXMLFatal) | 
|         |    499 		{ | 
|         |    500 		error = WriteFileL(aCDataSection); | 
|         |    501 		} | 
|         |    502  | 
|         |    503 	if(iSeverity != EXMLFatal) | 
|         |    504 		{ | 
|         |    505 		error = WriteFileL(KXMLEndCDataSection); | 
|         |    506 		} | 
|         |    507  | 
|         |    508 	return error; | 
|         |    509 	} | 
|         |    510  | 
|         |    511 //================================================================================== | 
|         |    512 //Defect fix for INC036136- Enable the use of custom entity converters in GMXML | 
|         |    513  | 
|         |    514 EXPORT_C TInt CMDXMLComposer::OutputDataL(const TDesC& aData) | 
|         |    515 // | 
|         |    516 // Output raw data | 
|         |    517 // it's only intended to be used from within a custom entity converter as | 
|         |    518 // it relies on a Composer sesssion already being in progress | 
|         |    519 // @param the data to be output | 
|         |    520 // @return KERRNone if successful, otherwise a file writing error. | 
|         |    521 // | 
|         |    522 	{ | 
|         |    523 	TInt error = KErrNone; | 
|         |    524  | 
|         |    525 	if(iSeverity != EXMLFatal) | 
|         |    526 		{ | 
|         |    527 		if(aData.Find(KQuotation) != KErrNotFound) | 
|         |    528 			{ | 
|         |    529 			error = ReplaceXmlCharactersL(aData, KQuotation); | 
|         |    530 			} | 
|         |    531 		else | 
|         |    532 			{ | 
|         |    533 			error = WriteFileL(aData);	 | 
|         |    534 			}		 | 
|         |    535 		} | 
|         |    536  | 
|         |    537 	return error; | 
|         |    538 	} | 
|         |    539  | 
|         |    540 //================================================================================== | 
|         |    541 /* Before writing to xml file, search for special character like quotation ("). | 
|         |    542    if it exist then replace it with " and then write it to xml file. | 
|         |    543    Refer section 5 of below URL for more information. | 
|         |    544    http://www.xmlnews.org/docs/xml-basics.html | 
|         |    545    @param aXmlData the data to be output | 
|         |    546    @param aString the special character to search in aXmlData | 
|         |    547    @return KERRNone if successful, otherwise a file writing error.	*/ | 
|         |    548     | 
|         |    549 TInt CMDXMLComposer::ReplaceXmlCharactersL(const TDesC16& aXmlData, const TDesC& aString) | 
|         |    550 	{ | 
|         |    551 	TInt xmlDataIndex; | 
|         |    552 	const TDesC& quot = KXmlQuotation; | 
|         |    553 	HBufC16* xmlData = aXmlData.AllocL(); | 
|         |    554 				 | 
|         |    555 	while((xmlDataIndex = (xmlData->Des()).Find(aString)) != KErrNotFound) | 
|         |    556 		{ | 
|         |    557 		HBufC16* temp = HBufC::NewLC(((xmlData->Des()).Length() - 1) + quot.Length()); | 
|         |    558 		TPtr16 tempPtr = temp->Des(); | 
|         |    559 		tempPtr.Append((xmlData->Des()).Left(xmlDataIndex)); | 
|         |    560 		tempPtr.Append(quot); | 
|         |    561 		tempPtr.Append((xmlData->Des()).Right((xmlData->Des()).Length() - (xmlDataIndex + 1))); | 
|         |    562 		delete xmlData; | 
|         |    563 		xmlData = NULL; | 
|         |    564 		xmlData = tempPtr.AllocL(); | 
|         |    565 		CleanupStack::PopAndDestroy();	// temp | 
|         |    566 		} | 
|         |    567 	TInt error = WriteFileL((xmlData->Des())); | 
|         |    568 	delete xmlData; | 
|         |    569 	xmlData = NULL; | 
|         |    570 	return error; | 
|         |    571 	} | 
|         |    572  | 
|         |    573 //================================================================================== | 
|         |    574  | 
|         |    575 EXPORT_C void CMDXMLComposer::SetEntityConverter(CMDXMLEntityConverter* aEntityConverter) | 
|         |    576 /* | 
|         |    577 	 * Sets the entity converter to be used | 
|         |    578 	 * and  take ownership of the passed entity converter | 
|         |    579 	 * @param aEntityConverter The entity converter to be used | 
|         |    580 	 */ | 
|         |    581 	{ | 
|         |    582 	delete iEntityConverter; | 
|         |    583 	iEntityConverter = aEntityConverter; | 
|         |    584 	} | 
|         |    585  | 
|         |    586 //End Defect fix for INC036136 | 
|         |    587 //================================================================================== | 
|         |    588  | 
|         |    589 EXPORT_C TInt CMDXMLComposer::OutputStartOfElementTagL(const TDesC& aElementName) | 
|         |    590 // | 
|         |    591 // Output a start of element tag | 
|         |    592 // @param aElementName the name of the tag to output | 
|         |    593 // @return KERRNone if successful, otherwise a file writing error. | 
|         |    594 // | 
|         |    595 	{ | 
|         |    596 	TInt error = KErrNone; | 
|         |    597  | 
|         |    598 #ifdef _DEBUG | 
|         |    599 	for(TInt loopIndex = 0; loopIndex < iIndentationLevel; loopIndex++) | 
|         |    600 		{ | 
|         |    601 		if(iSeverity != EXMLFatal) | 
|         |    602 			{ | 
|         |    603 			error = WriteFileL(KTab); | 
|         |    604 			} | 
|         |    605 		} | 
|         |    606 	iIndentationLevel++; | 
|         |    607 #endif | 
|         |    608  | 
|         |    609 	if(iSeverity != EXMLFatal) | 
|         |    610 		{ | 
|         |    611 		error = WriteFileL(KXMLStartTag); | 
|         |    612 		} | 
|         |    613  | 
|         |    614 	if(iSeverity != EXMLFatal) | 
|         |    615 		{ | 
|         |    616 		error = WriteFileL(aElementName); | 
|         |    617 		} | 
|         |    618  | 
|         |    619 	return error; | 
|         |    620 	} | 
|         |    621  | 
|         |    622 //================================================================================== | 
|         |    623  | 
|         |    624 EXPORT_C TInt CMDXMLComposer::OutputEndOfElementTagL(const TBool aHasChildren) | 
|         |    625 // | 
|         |    626 // Output an end of element start tag | 
|         |    627 // @param aHasChildren true if the element has children | 
|         |    628 // @return KERRNone if successful, otherwise a file writing error. | 
|         |    629 // | 
|         |    630 	{ | 
|         |    631 	TInt error = KErrNone; | 
|         |    632  | 
|         |    633 	if(iSeverity != EXMLFatal) | 
|         |    634 		{ | 
|         |    635 		if(aHasChildren) | 
|         |    636 			{ | 
|         |    637 			error = WriteFileL(KXMLEndTag); | 
|         |    638 			} | 
|         |    639 		else | 
|         |    640 			{ | 
|         |    641 			error = WriteFileL(KXMLEndStartTag); | 
|         |    642  | 
|         |    643 	#ifdef _DEBUG | 
|         |    644 			iIndentationLevel--; | 
|         |    645 	#endif | 
|         |    646 			} | 
|         |    647 		} | 
|         |    648  | 
|         |    649 	return error; | 
|         |    650 	} | 
|         |    651  | 
|         |    652 //================================================================================== | 
|         |    653  | 
|         |    654 TInt CMDXMLComposer::OutputEndTagL(const TDesC& aElementName) | 
|         |    655 // | 
|         |    656 // Output an end of element tag | 
|         |    657 // @param aElementName the name of the tag to output | 
|         |    658 // @return KERRNone if successful, otherwise a file writing error. | 
|         |    659 // | 
|         |    660 	{ | 
|         |    661 	TInt error = KErrNone; | 
|         |    662  | 
|         |    663 #ifdef _DEBUG | 
|         |    664 	iIndentationLevel--; | 
|         |    665 	for(TInt loopIndex = 0; loopIndex < iIndentationLevel; loopIndex++) | 
|         |    666 		{ | 
|         |    667 		if(iSeverity != EXMLFatal) | 
|         |    668 			{ | 
|         |    669 			error = WriteFileL(KTab); | 
|         |    670 			} | 
|         |    671 		} | 
|         |    672 #endif | 
|         |    673 	 | 
|         |    674 	if(iSeverity != EXMLFatal) | 
|         |    675 		{ | 
|         |    676 		error = WriteFileL(KXMLStartEndTag); | 
|         |    677 		} | 
|         |    678  | 
|         |    679 	if(iSeverity != EXMLFatal) | 
|         |    680 		{ | 
|         |    681 		error = WriteFileL(aElementName); | 
|         |    682 		} | 
|         |    683  | 
|         |    684 	if(iSeverity != EXMLFatal) | 
|         |    685 		{ | 
|         |    686 		error = WriteFileL(KXMLEndTag); | 
|         |    687 		} | 
|         |    688  | 
|         |    689 	return error; | 
|         |    690 	} | 
|         |    691  | 
|         |    692  | 
|         |    693  | 
|         |    694  | 
|         |    695  | 
|         |    696 //================================================================================== | 
|         |    697  | 
|         |    698 EXPORT_C TInt CMDXMLComposer::OutputAttributeL(const TDesC& aAttributeName, const TDesC& aAttributeValue) | 
|         |    699 // | 
|         |    700 // Output an attribute - name and value. | 
|         |    701 // @param aAttributeName the name of the attribute to output | 
|         |    702 // @param aAttributeValue the text of the attribute value to output | 
|         |    703 // @return KERRNone if successful, otherwise a file writing error. | 
|         |    704 // | 
|         |    705 	{ | 
|         |    706 	TInt error = KErrNone; | 
|         |    707  | 
|         |    708 	if(iSeverity != EXMLFatal) | 
|         |    709 		{ | 
|         |    710 		error = WriteFileL(KSingleSpace); | 
|         |    711 		} | 
|         |    712  | 
|         |    713 	if(iSeverity != EXMLFatal) | 
|         |    714 		{ | 
|         |    715 		error = WriteFileL(aAttributeName); | 
|         |    716 		} | 
|         |    717  | 
|         |    718 	if(iSeverity != EXMLFatal) | 
|         |    719 		{ | 
|         |    720 		error = WriteFileL(KEqualSign); | 
|         |    721 		} | 
|         |    722  | 
|         |    723 	if(iSeverity != EXMLFatal) | 
|         |    724 		{ | 
|         |    725 		error = WriteFileL(KQuotation); | 
|         |    726 		} | 
|         |    727  | 
|         |    728 	if(iSeverity != EXMLFatal) | 
|         |    729 		{ | 
|         |    730 		// Work along the attribute value in sections.  We have two markers in the attribute, | 
|         |    731 		// one at the beginning of the section we're working on and one at the end.  Initially | 
|         |    732 		// beginSection is the start of the string, 0, the end of the section is the first | 
|         |    733 		// CDataSection we find. | 
|         |    734 		// beginSection is an offset within the string, endSection is an offset from that | 
|         |    735 		TInt beginSection = 0; | 
|         |    736 		TInt endSection = aAttributeValue.Find(KXMLStartCDataSection); | 
|         |    737 		 | 
|         |    738 		// We've found at least one CDataSection | 
|         |    739 		while(endSection != KErrNotFound) | 
|         |    740 			{ | 
|         |    741 			// Entity convert this plain text section | 
|         |    742 			TPtrC plainText = aAttributeValue.Mid(beginSection, endSection); | 
|         |    743 			error = iEntityConverter->OutputComposedTextL(this, plainText); | 
|         |    744  | 
|         |    745 			// Move on our markers.  We start the new section at the end of the old one. | 
|         |    746 			beginSection += endSection; | 
|         |    747 			// The end of this section is the end of the CDataSection | 
|         |    748 			endSection = TPtrC(aAttributeValue.Mid(beginSection)).Find(KXMLEndCDataSection); | 
|         |    749 			if(endSection != KErrNotFound) | 
|         |    750 				{ | 
|         |    751 				// The CDataSection ends at the beginning of the end tag, so we need to add | 
|         |    752 				// on the length of the end tag before outputting it without conversion | 
|         |    753 				endSection += TPtrC(KXMLEndCDataSection).Length(); | 
|         |    754 				OutputDataL(aAttributeValue.Mid(beginSection, endSection)); | 
|         |    755  | 
|         |    756 				// Now move on our markers again.  Start at the end of the CDataSection, and | 
|         |    757 				// continue to the beginning of the next one. | 
|         |    758 				beginSection += endSection; | 
|         |    759 				endSection = TPtrC(aAttributeValue.Mid(beginSection)).Find(KXMLStartCDataSection); | 
|         |    760 				} | 
|         |    761 			else | 
|         |    762 				{ | 
|         |    763 				// There's an unterminated CDataSection in our attribute | 
|         |    764 				error = KErrXMLBadAttributeValue; | 
|         |    765 				} | 
|         |    766 			} | 
|         |    767  | 
|         |    768 		// There are no more CDataSections, entity convert the rest of the string | 
|         |    769 		if(!error) | 
|         |    770 			{ | 
|         |    771 			error = iEntityConverter->OutputComposedTextL(this, aAttributeValue.Mid(beginSection)); | 
|         |    772 			} | 
|         |    773 		} | 
|         |    774 	 | 
|         |    775 	if(iSeverity != EXMLFatal) | 
|         |    776 		{ | 
|         |    777 		error = WriteFileL(KQuotation); | 
|         |    778 		} | 
|         |    779  | 
|         |    780 	return error; | 
|         |    781 	} | 
|         |    782  | 
|         |    783 //================================================================================== | 
|         |    784  | 
|         |    785 EXPORT_C TInt CMDXMLComposer::RunError(TInt aError) | 
|         |    786 // | 
|         |    787 // RunError function inherited from CActive base class - intercepts any Leave from | 
|         |    788 // the RunL() function, sets an appropriate errorcode and calls ComposeFileCompleteL | 
|         |    789 // | 
|         |    790 	{ | 
|         |    791 	iSeverity = EXMLFatal; | 
|         |    792 	iError = aError; | 
|         |    793 	iXMLFile.Close(); | 
|         |    794 	TRAPD(err, iComposerObserver->ComposeFileCompleteL()); | 
|         |    795 	return err; | 
|         |    796 	} | 
|         |    797  | 
|         |    798 //================================================================================== | 
|         |    799  | 
|         |    800 EXPORT_C void CMDXMLComposer::DoCancel() | 
|         |    801 // | 
|         |    802 // DoCancel function inherited from CActive base class | 
|         |    803 // | 
|         |    804 	{ | 
|         |    805 	iXMLFile.Close(); | 
|         |    806 	} | 
|         |    807  | 
|         |    808 //================================================================================== | 
|         |    809  | 
|         |    810 void CMDXMLComposer::RunL() | 
|         |    811 // | 
|         |    812 // RunL function inherited from CActive base class - does the actual composition | 
|         |    813 // @leave can Leave due to OOM | 
|         |    814 // | 
|         |    815 	{ | 
|         |    816 	// If this is an ASCII file then check that we can load the character set converter | 
|         |    817 	if(iSeverity != EXMLFatal) | 
|         |    818 		{ | 
|         |    819 		if(iFileType == EAscii) | 
|         |    820 			{ | 
|         |    821 			if (iCharconv->PrepareToConvertToOrFromL(KCharacterSetIdentifierAscii, iRFs)!= | 
|         |    822 				CCnvCharacterSetConverter::EAvailable) | 
|         |    823 				{ | 
|         |    824 				SetError( KErrNotSupported, EXMLFatal); | 
|         |    825 				} | 
|         |    826 			} | 
|         |    827 		} | 
|         |    828  | 
|         |    829 	if(iSeverity != EXMLFatal) | 
|         |    830 		{ | 
|         |    831 	#ifdef _DEBUG | 
|         |    832 		iIndentationLevel = 0; | 
|         |    833 	#endif | 
|         |    834 		 | 
|         |    835 		CMDXMLElement* parentElement = iXMLDoc->DocumentElement(); | 
|         |    836  | 
|         |    837 		TInt error = KErrNone; | 
|         |    838  | 
|         |    839 		if(!parentElement->CheckChildren()) | 
|         |    840 			{ | 
|         |    841 			error = KErrNotSupported; | 
|         |    842 			SetError(KErrXMLInvalidChild, EXMLWorkable); | 
|         |    843 			} | 
|         |    844 		 | 
|         |    845 		if(iOutputProlog) | 
|         |    846 			{ | 
|         |    847 			// Output document level information if required.  MMS conformance requires no Version | 
|         |    848 			// or DocType tag, so we may not want to output them. | 
|         |    849 			if(iSeverity != EXMLFatal) | 
|         |    850 				{ | 
|         |    851 				WriteFileL(iXMLDoc->VersionTag()); | 
|         |    852 				} | 
|         |    853 			if(iSeverity != EXMLFatal) | 
|         |    854 				{ | 
|         |    855 				WriteFileL(KNewLine); | 
|         |    856 				} | 
|         |    857 			if(iSeverity != EXMLFatal) | 
|         |    858 				{ | 
|         |    859 				WriteFileL(iXMLDoc->DocTypeTag()); | 
|         |    860 				} | 
|         |    861 			if(iSeverity != EXMLFatal) | 
|         |    862 				{ | 
|         |    863 				WriteFileL(KNewLine); | 
|         |    864 				} | 
|         |    865 			} | 
|         |    866 			 | 
|         |    867 		// Output the contents of the DOM tree | 
|         |    868 		if(iSeverity != EXMLFatal) | 
|         |    869 			{ | 
|         |    870 			error = ComposeL(); | 
|         |    871 			if(iSeverity != EXMLFatal) | 
|         |    872 				{ | 
|         |    873 				if(error != KErrNone) | 
|         |    874 					{ | 
|         |    875 					SetError(error, EXMLIndeterminate); | 
|         |    876 					} | 
|         |    877  | 
|         |    878 				WriteFileL(KNewLine); | 
|         |    879 				} | 
|         |    880 			} | 
|         |    881  | 
|         |    882 		if(iSeverity != EXMLFatal) | 
|         |    883 			{ | 
|         |    884 			error = FlushOutputBufferL(); | 
|         |    885  | 
|         |    886 			if(error != KErrNone) | 
|         |    887 				{ | 
|         |    888 				SetError(error, EXMLIndeterminate); | 
|         |    889 				} | 
|         |    890 			} | 
|         |    891 		} | 
|         |    892  | 
|         |    893 	iXMLFile.Close(); | 
|         |    894  | 
|         |    895 	if (iOnlyCalculatingSize) | 
|         |    896 		{ | 
|         |    897 		*iSize = iSizeTally; | 
|         |    898 		} | 
|         |    899  | 
|         |    900 	iComposerObserver->ComposeFileCompleteL(); | 
|         |    901 	} | 
|         |    902  | 
|         |    903  | 
|         |    904 TInt CMDXMLComposer::ComposeL() | 
|         |    905 // | 
|         |    906 // Function to output the contents of the node as XML to some output stream. | 
|         |    907 // @param aComposer The composer to use - provides access to output and entity conversion | 
|         |    908 // @return Returns KerrNone if successful or a file write error | 
|         |    909 // @leave Can Leave due to OOM. | 
|         |    910 // | 
|         |    911 	{ | 
|         |    912 	CMDXMLNode* nextPtr; | 
|         |    913 	TInt error = KErrNone; | 
|         |    914 	nextPtr = iXMLDoc->DocumentElement()->FirstChild(); | 
|         |    915  | 
|         |    916  | 
|         |    917 	while(error == KErrNone && nextPtr != NULL) | 
|         |    918 		{ | 
|         |    919 		// compose the start tag of the current element | 
|         |    920 		error = ComposeStartTagL(*nextPtr); | 
|         |    921  | 
|         |    922 		if(error == KErrNone) | 
|         |    923 			{ | 
|         |    924 			// move to the first child is there is one | 
|         |    925 			if(nextPtr->FirstChild() != NULL) | 
|         |    926 				{ | 
|         |    927 				nextPtr = nextPtr->FirstChild(); | 
|         |    928 				} | 
|         |    929 			else | 
|         |    930 				{ | 
|         |    931 				// EndTag is only output if HasChildNodes() == TRUE | 
|         |    932 				error = ComposeEndTagL(*nextPtr); | 
|         |    933  | 
|         |    934 				// move to the next sibling if exists | 
|         |    935 				if(nextPtr->NextSibling() != NULL) | 
|         |    936 					{ | 
|         |    937 					nextPtr = nextPtr->NextSibling(); | 
|         |    938 					} | 
|         |    939  | 
|         |    940 				// no siblings, move back to parent and close parent tag | 
|         |    941 				else | 
|         |    942 					{ | 
|         |    943 					// might need to go up several layers so WHILE rather than IF | 
|         |    944 					while(nextPtr != NULL && nextPtr->NextSibling() == NULL && error == KErrNone) | 
|         |    945 						{ | 
|         |    946 						nextPtr = nextPtr->ParentNode(); | 
|         |    947 						if(nextPtr != NULL) | 
|         |    948 							{ | 
|         |    949 							error = ComposeEndTagL(*nextPtr); | 
|         |    950 							} | 
|         |    951 						} | 
|         |    952  | 
|         |    953 					// if we've stopped at an element with further siblings | 
|         |    954 					if(nextPtr != NULL && nextPtr->NextSibling() != NULL) | 
|         |    955 						{ | 
|         |    956 						nextPtr = nextPtr->NextSibling(); | 
|         |    957 						} | 
|         |    958 					} | 
|         |    959 				} | 
|         |    960 			} | 
|         |    961 		} | 
|         |    962  | 
|         |    963 	return error; | 
|         |    964 	} | 
|         |    965  | 
|         |    966  | 
|         |    967 EXPORT_C TInt CMDXMLComposer::ComposeStartTagL(CMDXMLNode& aNode) | 
|         |    968  // | 
|         |    969  // Outputs a start tag for the node which includes the | 
|         |    970  // tag name and all attribute name value pairs currently | 
|         |    971  // specified.  If the node is an empty node then it | 
|         |    972  // makes the tag an empty node tag, otherwise it creates | 
|         |    973  // a start tag. | 
|         |    974  // @param aNode The Node for which the start tag is being written | 
|         |    975  // @return Returns KerrNone if successful or a file write error | 
|         |    976  //  | 
|         |    977 	{ | 
|         |    978 	TInt error = KErrNone; | 
|         |    979  | 
|         |    980 	switch (aNode.NodeType()) | 
|         |    981 		{ | 
|         |    982 		case CMDXMLNode::ETextNode: | 
|         |    983 			error = iEntityConverter->OutputComposedTextL(this, ((CMDXMLText&)aNode).Data()); | 
|         |    984 			break; | 
|         |    985 		case CMDXMLNode::ECDATASectionNode: | 
|         |    986 			error = OutputCDataSectionL(((CMDXMLCDATASection&)aNode).Data()); | 
|         |    987 			// does nothing | 
|         |    988 			break; | 
|         |    989 		case CMDXMLNode::EProcessingInstructionNode: | 
|         |    990 			error = OutputProcessingInstructionL(((CMDXMLProcessingInstruction&)aNode).Data()); | 
|         |    991 			break; | 
|         |    992 		case CMDXMLNode::ECommentNode: | 
|         |    993 			error = OutputCommentL(((CMDXMLComment&)aNode).Data()); | 
|         |    994 			break; | 
|         |    995 		case CMDXMLNode::EDocumentNode: | 
|         |    996 			// does nothing | 
|         |    997 			break; | 
|         |    998 		case CMDXMLNode::EElementNode: | 
|         |    999 			error = OutputStartOfElementTagL(aNode.NodeName()); | 
|         |   1000 			TInt attIndex; | 
|         |   1001 			// Output all attributes in a loop | 
|         |   1002 			for(attIndex = 0 ; (error == KErrNone && attIndex < ((CMDXMLElement&)aNode).NumAttributes()); attIndex ++ ) | 
|         |   1003 				{ | 
|         |   1004 				TPtrC attributeValue;	 | 
|         |   1005 				TPtrC attributeName; | 
|         |   1006 				error = ((CMDXMLElement&)aNode).AttributeDetails(attIndex, attributeName, attributeValue); | 
|         |   1007 				if(error == KErrNone) | 
|         |   1008 					error = OutputAttributeL(attributeName, attributeValue); | 
|         |   1009 				} | 
|         |   1010  | 
|         |   1011  | 
|         |   1012 			if( error == KErrNone ) | 
|         |   1013 				{ | 
|         |   1014 				error = OutputEndOfElementTagL(aNode.HasChildNodes()); | 
|         |   1015 				} | 
|         |   1016 			break; | 
|         |   1017 		default: | 
|         |   1018 			// does nothing | 
|         |   1019 			break; | 
|         |   1020  | 
|         |   1021  | 
|         |   1022 		} | 
|         |   1023  | 
|         |   1024 	return error; | 
|         |   1025 	} | 
|         |   1026  | 
|         |   1027 EXPORT_C TInt CMDXMLComposer::ComposeEndTagL(CMDXMLNode& aNode) | 
|         |   1028 // | 
|         |   1029 // Outputs an end tag for the node. | 
|         |   1030 // @param aNode the node for which the tag is being written. | 
|         |   1031 // @return Returns KerrNone if successful or a file write error | 
|         |   1032 // | 
|         |   1033 	{ | 
|         |   1034 	TInt error = KErrNone; | 
|         |   1035  | 
|         |   1036 	if (aNode.NodeType() == CMDXMLNode::EElementNode && aNode.NodeName() != KXMLDocumentElementNodeName) | 
|         |   1037 		{ | 
|         |   1038 		if(aNode.HasChildNodes()) | 
|         |   1039 			{ | 
|         |   1040 			error = OutputEndTagL(aNode.NodeName()); | 
|         |   1041 			} | 
|         |   1042 		} | 
|         |   1043 		 | 
|         |   1044  | 
|         |   1045 	return error; | 
|         |   1046 	} | 
|         |   1047  | 
|         |   1048 //================================================================================== | 
|         |   1049  | 
|         |   1050 TInt CMDXMLComposer::WriteFileL(const TDesC& aStringToWrite) | 
|         |   1051 // | 
|         |   1052 // Function to write string to required file format - handles format conversion | 
|         |   1053 // @param aStringToWrite the string to output | 
|         |   1054 // @return returns KERRNone if successful or a file write error. | 
|         |   1055 // | 
|         |   1056 	{ | 
|         |   1057 	TInt error = KErrNone; | 
|         |   1058 	TInt outputBufferLength = iOutputBuffer.Length(); | 
|         |   1059 	TInt additionalLength = aStringToWrite.Length(); | 
|         |   1060  | 
|         |   1061 	if(outputBufferLength + additionalLength <= KWriteBufferLen) | 
|         |   1062 		{ | 
|         |   1063 		iOutputBuffer.Append(aStringToWrite); | 
|         |   1064 		} | 
|         |   1065 	else | 
|         |   1066 		{ | 
|         |   1067 		iOutputBuffer.Append(aStringToWrite.Left(KWriteBufferLen - outputBufferLength)); | 
|         |   1068 		error = FlushOutputBufferL(); | 
|         |   1069 		iOutputBuffer.Zero(); | 
|         |   1070 		WriteFileL(aStringToWrite.Right(additionalLength - (KWriteBufferLen - outputBufferLength))); | 
|         |   1071 		}		 | 
|         |   1072  | 
|         |   1073 	return error; | 
|         |   1074 	} | 
|         |   1075  | 
|         |   1076 //================================================================================== | 
|         |   1077 #define DES_AS_8_BIT(str) (TPtrC8((TText8*)((str).Ptr()), (str).Size())) | 
|         |   1078  | 
|         |   1079 TInt CMDXMLComposer::FlushOutputBufferL() | 
|         |   1080 // | 
|         |   1081 // Function to write string to required file format - handles format conversion | 
|         |   1082 // @param aStringToWrite the string to output | 
|         |   1083 // @return returns KERRNone if successful or a file write or conversion error. | 
|         |   1084 // | 
|         |   1085 	{ | 
|         |   1086 	TInt error = KErrNone; | 
|         |   1087  | 
|         |   1088 	if (!iOnlyCalculatingSize) | 
|         |   1089 		{ | 
|         |   1090 		if(iXMLFile.SubSessionHandle() == KNullHandle) | 
|         |   1091 			{ | 
|         |   1092 			return KErrBadHandle; | 
|         |   1093 			} | 
|         |   1094 		} | 
|         |   1095  | 
|         |   1096 	// All text is processed internally as unicode.  If we've been asked to output | 
|         |   1097 	// another format (Ascii or Utf-8) we need to translate it to that format using | 
|         |   1098 	// charconv before writing the file.   | 
|         |   1099 	switch(iFileType) | 
|         |   1100 		{ | 
|         |   1101 		case EAscii: | 
|         |   1102 		case EUtf8: | 
|         |   1103 			{ | 
|         |   1104 			// We need to convert in a loop as charconv only allows 25 untranslatable | 
|         |   1105 			// characters per block of text.  convResult tells us how many characters | 
|         |   1106 			// were left untranslated at the end of iOutputBuffer so we only look at | 
|         |   1107 			// that many characters on the right hand of iOutputBuffer.  Initially we | 
|         |   1108 			// don't have any characters translated so convResult is the length of | 
|         |   1109 			// iOutputBuffer.  Each time through the loop write out the chunk we've | 
|         |   1110 			// converted.  If there's an error writing the file or doing the character | 
|         |   1111 			// conversion we give up. | 
|         |   1112 			TInt convResult = iOutputBuffer.Length(); | 
|         |   1113 			while((convResult > 0) && (error == KErrNone)) | 
|         |   1114 				{ | 
|         |   1115 				HBufC8* narrow = HBufC8::NewLC(convResult); | 
|         |   1116 				TPtr8 narrowPtr = narrow->Des(); | 
|         |   1117 				if(iFileType == EAscii) | 
|         |   1118 					{ | 
|         |   1119 					convResult = iCharconv->ConvertFromUnicode(narrowPtr, iOutputBuffer.Right(convResult)); | 
|         |   1120 					} | 
|         |   1121 				else // iFileType == EUtf8 | 
|         |   1122 					{ | 
|         |   1123 					convResult = CnvUtfConverter::ConvertFromUnicodeToUtf8(narrowPtr, iOutputBuffer.Right(convResult)); | 
|         |   1124 					} | 
|         |   1125  | 
|         |   1126 				if(convResult >= 0) | 
|         |   1127 					{ | 
|         |   1128 					iSizeTally += narrow->Size(); | 
|         |   1129  | 
|         |   1130 					if (!iOnlyCalculatingSize) | 
|         |   1131 						{ | 
|         |   1132 						error = iXMLFile.Write(narrow->Des()); | 
|         |   1133 						} | 
|         |   1134 					} | 
|         |   1135 				else | 
|         |   1136 					{ | 
|         |   1137 					error = convResult; | 
|         |   1138 					} | 
|         |   1139 				CleanupStack::PopAndDestroy(narrow); | 
|         |   1140 				}  | 
|         |   1141 			break; | 
|         |   1142 			} | 
|         |   1143  | 
|         |   1144 		case EUnicode: | 
|         |   1145 			{ | 
|         |   1146 			TPtrC  output16 = iOutputBuffer; | 
|         |   1147 			TPtrC8 output = DES_AS_8_BIT(output16); | 
|         |   1148 			 | 
|         |   1149 			iSizeTally += output.Size(); | 
|         |   1150  | 
|         |   1151 			if (!iOnlyCalculatingSize) | 
|         |   1152 				{ | 
|         |   1153 				error = iXMLFile.Write(output); | 
|         |   1154 				} | 
|         |   1155  | 
|         |   1156 			break; | 
|         |   1157 			} | 
|         |   1158  | 
|         |   1159 		default: | 
|         |   1160 			error = KErrNotSupported; | 
|         |   1161 			break; | 
|         |   1162 		} | 
|         |   1163  | 
|         |   1164 	if(error != KErrNone) | 
|         |   1165 		{ | 
|         |   1166 		SetError(error, EXMLFatal); | 
|         |   1167 		} | 
|         |   1168  | 
|         |   1169 	return error;	 | 
|         |   1170 	} | 
|         |   1171  | 
|         |   1172 //================================================================================== | 
|         |   1173  | 
|         |   1174 EXPORT_C void CMDXMLComposer::SetError(const TInt aErrorCode, const TXMLErrorCodeSeverity aSeverity) | 
|         |   1175 // | 
|         |   1176 // Sets iError to new errorcode if more serious than any error so far encountered | 
|         |   1177 // | 
|         |   1178 	{ | 
|         |   1179 	if(iSeverity > aSeverity) | 
|         |   1180 		{ | 
|         |   1181 		iSeverity = aSeverity; | 
|         |   1182 		iError = aErrorCode; | 
|         |   1183 		} | 
|         |   1184 	} | 
|         |   1185  | 
|         |   1186 EXPORT_C void CMDXMLComposer::PlaceholderForRemovedExport1(MMDXMLComposerObserver* /*aComposerObserver*/) | 
|         |   1187 	{ | 
|         |   1188 	User::Panic(KLDRIMPORT, KLdrImportedOrdinalDoesNotExist); | 
|         |   1189 	} | 
|         |   1190  | 
|         |   1191 EXPORT_C void CMDXMLComposer::PlaceholderForRemovedExport2() | 
|         |   1192 	{ | 
|         |   1193 	User::Panic(KLDRIMPORT, KLdrImportedOrdinalDoesNotExist); | 
|         |   1194 	} | 
|         |   1195  | 
|         |   1196 EXPORT_C void CMDXMLComposer::PlaceholderForRemovedExport3() | 
|         |   1197 	{ | 
|         |   1198 	User::Panic(KLDRIMPORT, KLdrImportedOrdinalDoesNotExist); | 
|         |   1199 	} | 
|         |   1200  | 
|         |   1201 // End of File |