securityanddataprivacytools/securitytools/certapp/encdec/encdec.cpp
changeset 0 2c201484c85f
child 8 35751d3474b7
equal deleted inserted replaced
-1:000000000000 0:2c201484c85f
       
     1 /*
       
     2 * Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include "encdec.h"
       
    20 #include <sstream>
       
    21 #include <errno.h>
       
    22 #include <s32ucmp.h>
       
    23 #include "stringconv.h"
       
    24 #include <stdio.h>
       
    25 #include "x509utils.h"
       
    26 
       
    27 RDecodeReadStream::RDecodeReadStream(CFileStore *aStore, RReadStream &aReadStream)
       
    28 	: iStore(aStore), iCertBaseName(), iReadStream(aReadStream), iHumanReadable(false), iToken(), 
       
    29 	  iPrefetchedTokenIsValid(false), iPrefetchedToken()
       
    30 {
       
    31 }
       
    32 
       
    33 RDecodeReadStream::RDecodeReadStream(const std::string &aCertBaseName, RReadStream &aReadStream)
       
    34 	: iStore(0), iCertBaseName(aCertBaseName), iReadStream(aReadStream), iHumanReadable(true), iToken(), 
       
    35 	  iPrefetchedTokenIsValid(false), iPrefetchedToken()
       
    36 {
       
    37 }
       
    38 
       
    39 void RDecodeReadStream::RawRead(void *aPtr, TUint32 aLength)
       
    40 {
       
    41 	iReadStream.ReadL((TUint8 *)aPtr, aLength);
       
    42 }
       
    43 
       
    44 void RDecodeReadStream::CheckName(const std::string &aExpected)
       
    45 {
       
    46 	ReadNextToken();
       
    47 
       
    48 	if(iToken != aExpected)
       
    49 		{
       
    50 		dbg << Log::Indent() << "Expected token '" << aExpected <<"' but got token '" << iToken << "'" << Log::Endl();
       
    51 		FatalError();
       
    52 		}
       
    53 	   
       
    54 }
       
    55 
       
    56 TUint32 ReadUnsignedNumber(std::string &aStr, size_t aSize)
       
    57 {
       
    58 	TUint32 val;
       
    59 	std::istringstream ss(aStr);
       
    60 
       
    61 	if((aStr.length() > 2) && 
       
    62 	   (aStr[0] == '0') && 
       
    63 	   ((aStr[1] == 'x') || (aStr[1] == 'X')))
       
    64 		{
       
    65 		// Hex number starting with 0x
       
    66 		char ch;
       
    67 		ss >> ch >> ch; // Discard the 0x
       
    68 		ss >> std::hex >> val;
       
    69 		}
       
    70 	else
       
    71 		{
       
    72 		// Decimal number
       
    73 		ss >> val;
       
    74 		}
       
    75 
       
    76 	// Now work out if we consumed the entire token without error
       
    77 	if(ss.fail())
       
    78 		{
       
    79 		// Number decode failed
       
    80 		dbg << Log::Indent() << "Failed to decode '" << aStr << "' as a number" << Log::Endl();
       
    81 		FatalError();
       
    82 		}
       
    83 
       
    84 	// Make sure we consumed all data
       
    85 	if(! ss.eof())
       
    86 		{
       
    87 		// Trailing chars on numeric token
       
    88 		FatalError();
       
    89 		}
       
    90 
       
    91 	if(aSize != 4)
       
    92 		{
       
    93 		// Check range
       
    94 		// nb the following check would fail if aSize==4 because x>>32 == x if sizeof(x)==4
       
    95 		if((val >> (8*aSize)) != 0)
       
    96 			{
       
    97 			// Higher order bits are set above the size of the variable we
       
    98 			// are returning into
       
    99 			FatalError();
       
   100 			}
       
   101 		}
       
   102 return val;
       
   103 }
       
   104 
       
   105 
       
   106 TUint32 RDecodeReadStream::ReadUnsignedNumber(size_t aSize)
       
   107 {
       
   108 BULLSEYE_OFF
       
   109 	if((TUint32(aSize)>4))
       
   110 		{
       
   111 		FatalError();
       
   112 		}
       
   113 BULLSEYE_RESTORE
       
   114 
       
   115 	ReadNextToken();
       
   116 
       
   117 	return ::ReadUnsignedNumber(iToken, aSize);
       
   118 }
       
   119 
       
   120 const std::string &RDecodeReadStream::Token() const
       
   121 {
       
   122 	return iToken;
       
   123 }
       
   124 
       
   125 void RDecodeReadStream::ReadNextToken()
       
   126 {
       
   127 	if(iPrefetchedTokenIsValid)
       
   128 		{
       
   129 		// Copy prefetched token to current token
       
   130 		iToken = iPrefetchedToken;
       
   131 		iPrefetchedToken.clear();
       
   132 		iPrefetchedTokenIsValid = false;
       
   133 		return;
       
   134 		}
       
   135 		
       
   136 	GetToken(iToken);
       
   137 }
       
   138 
       
   139 const std::string &RDecodeReadStream::PeakToken()
       
   140 {
       
   141 	if(!iPrefetchedTokenIsValid)
       
   142 		{
       
   143 		GetToken(iPrefetchedToken);
       
   144 		iPrefetchedTokenIsValid = true;
       
   145 		}
       
   146 
       
   147 	return iPrefetchedToken;
       
   148 }
       
   149 
       
   150 
       
   151 
       
   152 
       
   153 
       
   154 bool RDecodeReadStream::HumanReadable() const
       
   155 {
       
   156 	return iHumanReadable;
       
   157 }
       
   158 
       
   159 
       
   160 void RDecodeReadStream::Close()
       
   161 {
       
   162 	iReadStream.Close();
       
   163 }
       
   164 
       
   165 void RDecodeReadStream::GetToken(std::string &aToken)
       
   166 {
       
   167 	aToken.clear();
       
   168 
       
   169 	TUint8 ch;
       
   170 	do 
       
   171 		{
       
   172 		iReadStream >> ch;
       
   173 		if(ch == '#')
       
   174 			{
       
   175 			// Skip comment
       
   176 			++ch;
       
   177 			while((ch != '\r') && (ch != '\n'))
       
   178 				{
       
   179 				iReadStream >> ch;
       
   180 				} 
       
   181 
       
   182 			}
       
   183 		} while((ch == ' ') || (ch == '\t') || (ch == '\r') || (ch == '\n'));
       
   184 	
       
   185 	if(ch == '"')
       
   186 		{
       
   187 		// Read a string
       
   188 		iReadStream >> ch; // read first char
       
   189 		while(ch != '"')
       
   190 			{
       
   191 			if(ch=='\\')
       
   192 				{
       
   193 				// \X causes X to always be saved (even if X is ")
       
   194 				iReadStream >> ch;
       
   195 				}
       
   196 			
       
   197 			aToken.push_back(ch);
       
   198 			iReadStream >> ch;
       
   199 			}
       
   200 		// At this point ch contains WS so it can be discarded.
       
   201 		return;
       
   202 		}
       
   203 
       
   204 	// Read a non-string token
       
   205 	while((ch != ' ') && (ch != '\t') && (ch != '\r') && (ch != '\n'))
       
   206 		{
       
   207 		aToken.push_back(ch);
       
   208 		iReadStream >> ch;
       
   209 		}
       
   210 	// At this point ch contains WS so it can be discarded.
       
   211 	return;
       
   212 }
       
   213 
       
   214 
       
   215 
       
   216 
       
   217 
       
   218 REncodeWriteStream::REncodeWriteStream(CFileStore *aStore, RWriteStream &aWriteStream)
       
   219 	: iStore(aStore),
       
   220 	  iCertBaseName(), // not used for STORE based streams
       
   221 	  iWriteStream(&aWriteStream),
       
   222 	  iLogStream(0), 
       
   223 	  iHumanReadable(false), iPemOut(false), iVerbose(false), iIndentLevel(0)
       
   224 {
       
   225 }
       
   226 
       
   227 REncodeWriteStream::REncodeWriteStream(const std::string &aCertBaseName, RWriteStream &aWriteStream)
       
   228 	: iStore(0), iCertBaseName(aCertBaseName), iWriteStream(&aWriteStream),
       
   229 	  iLogStream(0), 
       
   230 	  iHumanReadable(true), iPemOut(false), iVerbose(false), iIndentLevel(0)
       
   231 {
       
   232 }
       
   233 
       
   234 REncodeWriteStream::REncodeWriteStream(Log &aLog)
       
   235 	: iStore(0), iWriteStream(0), iLogStream(&aLog.Stream()), 
       
   236 	  iHumanReadable(true), iPemOut(false), iVerbose(false), iIndentLevel(aLog.IndentLevel())
       
   237 {
       
   238 }
       
   239 
       
   240 void REncodeWriteStream::WriteBin(const void *aPtr, TUint32 aLength)
       
   241 {
       
   242 	if(iWriteStream)
       
   243 		{
       
   244 		iWriteStream->WriteL((TUint8 *)aPtr, aLength);
       
   245 		}
       
   246 	if(iLogStream)
       
   247 		{
       
   248 		iLogStream->write((const char *)aPtr, aLength);
       
   249 		iLogStream->flush();
       
   250 		}
       
   251 }
       
   252 
       
   253 void REncodeWriteStream::WriteQuotedUtf8(const void *aStr, TUint32 aLength)
       
   254 {
       
   255 	std::string tmp((const char *)aStr, aLength);
       
   256 	
       
   257 	// Insert a backslash before any backslash chars
       
   258 	size_t pos = 0;
       
   259 	while((pos = tmp.find('\\', pos)) != std::string::npos)
       
   260 		{
       
   261 		tmp.insert(pos, "\\", 1);
       
   262 		pos += 2;
       
   263 		}
       
   264 
       
   265 	// Insert a backslash before any double quote chars
       
   266 	pos = 0;
       
   267 	while((pos = tmp.find('"', pos)) != std::string::npos)
       
   268 		{
       
   269 		tmp.insert(pos, "\\", 1);
       
   270 		pos += 2;
       
   271 		}
       
   272 
       
   273 	if(iWriteStream)
       
   274 		{
       
   275 		iWriteStream->WriteL((TUint8 *)tmp.data(), tmp.size());
       
   276 		}
       
   277 	if(iLogStream)
       
   278 		{
       
   279 		iLogStream->write(tmp.data(), tmp.size());
       
   280 		iLogStream->flush();
       
   281 		}
       
   282 }
       
   283 
       
   284 void REncodeWriteStream::WriteByte(TUint8 aByte)
       
   285 {
       
   286 	WriteBin(&aByte, 1);
       
   287 }
       
   288 
       
   289 void REncodeWriteStream::WriteCStr(const void *aCstr)
       
   290 {
       
   291 	WriteBin(aCstr, strlen((const char *)aCstr));
       
   292 }
       
   293 
       
   294 void REncodeWriteStream::WriteHexNumber(TUint32 aNumber)
       
   295 {
       
   296 	char buf[20];
       
   297 	int len = sprintf(buf, "0x%x", aNumber);
       
   298 	WriteBin(buf, len);
       
   299 }
       
   300 
       
   301 
       
   302 void REncodeWriteStream::WriteSpace()
       
   303 {
       
   304 BULLSEYE_OFF
       
   305 	if(!iHumanReadable) return;
       
   306 BULLSEYE_RESTORE
       
   307 	WriteByte(' ');
       
   308 }
       
   309 
       
   310 void REncodeWriteStream::WriteLineEnd()
       
   311 {
       
   312 BULLSEYE_OFF
       
   313 	if(!iHumanReadable) return;
       
   314 BULLSEYE_RESTORE
       
   315 #ifdef linux
       
   316 	WriteByte('\n');
       
   317 #else
       
   318 	WriteBin("\r\n", 2);
       
   319 #endif
       
   320 }
       
   321 
       
   322 
       
   323 void REncodeWriteStream::WriteIndent()
       
   324 {
       
   325 BULLSEYE_OFF
       
   326 	if(!iHumanReadable) return;
       
   327 BULLSEYE_RESTORE
       
   328 	for(int i=0; i<iIndentLevel; ++i)
       
   329 		{
       
   330 		WriteByte('\t');
       
   331 		}
       
   332 }
       
   333 
       
   334 void REncodeWriteStream::IncIndent()
       
   335 {
       
   336 	prog.IncIndent();
       
   337 	++iIndentLevel;
       
   338 BULLSEYE_OFF
       
   339 	if(iIndentLevel < 0) FatalError();
       
   340 BULLSEYE_RESTORE
       
   341 }
       
   342 
       
   343 void REncodeWriteStream::DecIndent()
       
   344 {
       
   345 	prog.DecIndent();
       
   346 	--iIndentLevel;
       
   347 BULLSEYE_OFF
       
   348 	if(iIndentLevel < 0) FatalError();
       
   349 BULLSEYE_RESTORE
       
   350 }
       
   351 
       
   352 bool REncodeWriteStream::HumanReadable() const
       
   353 {
       
   354 	return iHumanReadable;
       
   355 }
       
   356 
       
   357 bool &REncodeWriteStream::PemOut()
       
   358 {
       
   359 	return iPemOut;
       
   360 }
       
   361 
       
   362 bool &REncodeWriteStream::Verbose()
       
   363 {
       
   364 	return iVerbose;
       
   365 }
       
   366 
       
   367 
       
   368 
       
   369 std::string REncodeWriteStream::CertFileName(TUint32 aFormat, TUint32 aCertNumber)
       
   370 {
       
   371 	std::stringstream ss;
       
   372 	ss << iCertBaseName;
       
   373 	ss << "cert";
       
   374 	ss << aCertNumber;
       
   375 	if(aFormat == EX509Certificate)
       
   376 		{
       
   377 		if(iPemOut)
       
   378 			{
       
   379 			ss << ".pem";
       
   380 			}
       
   381 		else
       
   382 			{
       
   383 			ss << ".der";
       
   384 			}
       
   385 		}
       
   386 	else
       
   387 		{
       
   388 		ss << ".dat";
       
   389 		}
       
   390 	
       
   391 	return ss.str();
       
   392 }
       
   393 
       
   394 
       
   395 
       
   396 void REncodeWriteStream::Close()
       
   397 {
       
   398 BULLSEYE_OFF
       
   399 	if(iWriteStream)
       
   400 BULLSEYE_RESTORE
       
   401 		{
       
   402 		iWriteStream->Close();
       
   403 		}
       
   404 }
       
   405 
       
   406 CFileStore *REncodeWriteStream::StoreObject()
       
   407 {
       
   408 BULLSEYE_OFF
       
   409 	if(iStore == 0) FatalError();
       
   410 BULLSEYE_RESTORE
       
   411 	return iStore;
       
   412 }
       
   413 
       
   414 RWriteStream &REncodeWriteStream::StoreWriteStream()
       
   415 {
       
   416 BULLSEYE_OFF
       
   417 	if(iWriteStream == 0) FatalError();
       
   418 BULLSEYE_RESTORE
       
   419 	return *iWriteStream;
       
   420 }
       
   421 
       
   422 bool REncodeWriteStream::Quiet() const
       
   423 {
       
   424 	return iLogStream != 0;
       
   425 }
       
   426 
       
   427 TUint8 fromHex(TUint8 ch)
       
   428 	/**
       
   429 	   Convert a single hex char from ascii
       
   430 	 */
       
   431 {
       
   432 	// convert to lowercase
       
   433 	if((ch >= 'A') && (ch <= 'F'))
       
   434 		{
       
   435 		ch -= ('A' -'a');
       
   436 		}
       
   437 	// Handle a-f
       
   438 	if((ch >= 'a') && (ch <= 'f'))
       
   439 		{
       
   440 		return ch - 'a' + 10;
       
   441 		}
       
   442 
       
   443 	// Handle 0-9
       
   444 	if((ch >= '0') && (ch <= '9'))
       
   445 		{
       
   446 		return ch - '0';
       
   447 		}
       
   448 
       
   449 	// Illegal
       
   450 	FatalError();
       
   451 	return 0xff;
       
   452 }
       
   453 
       
   454 EncDecContainerItem::~EncDecContainerItem()
       
   455 {
       
   456 }
       
   457 
       
   458 
       
   459 #ifdef _BullseyeCoverage
       
   460 #pragma BullseyeCoverage off
       
   461 #endif
       
   462 std::string EncDecContainerItem::ItemName() const
       
   463 {
       
   464 	// Should never be called
       
   465 	exit(-1);
       
   466 	std::string tmp;
       
   467 	return tmp;
       
   468 }
       
   469 
       
   470 void EncDecContainerItem::SetItemName(const std::string &)
       
   471 {
       
   472 	// Should never be called
       
   473 	exit(-1);
       
   474 }
       
   475 #ifdef _BullseyeCoverage
       
   476 #pragma BullseyeCoverage restore
       
   477 #endif
       
   478 
       
   479 
       
   480 
       
   481 EncDecContainer::EncDecContainer(const char *aContainerName, EncDecContainerItemFactoryFunc *aFactory)
       
   482 	: iName(aContainerName), iFactory(aFactory), iArray()
       
   483 {
       
   484 }
       
   485 
       
   486 EncDecContainer::~EncDecContainer()
       
   487 {
       
   488 	reset();
       
   489 }
       
   490 
       
   491 void EncDecContainer::push_back(EncDecContainerItem *aItem)
       
   492 {
       
   493 	iArray.push_back(aItem);
       
   494 }
       
   495 
       
   496 const EncDecContainerItem &EncDecContainer::operator[](TUint32 aIndex) const
       
   497 {
       
   498 	return *iArray[aIndex];
       
   499 }
       
   500 
       
   501 EncDecContainerItem &EncDecContainer::operator[](TUint32 aIndex)
       
   502 {
       
   503 	return *iArray[aIndex];
       
   504 }
       
   505 
       
   506 TUint32 EncDecContainer::size() const
       
   507 {
       
   508 	return iArray.size();
       
   509 }
       
   510 
       
   511 void EncDecContainer::reset()
       
   512 {
       
   513 	while(!iArray.empty())
       
   514 		{
       
   515 		EncDecContainerItem *p = iArray.back();
       
   516 		iArray.pop_back();
       
   517 		delete p;
       
   518 		}
       
   519 }
       
   520 
       
   521 
       
   522 
       
   523 void EncDecContainer::Encode(REncodeWriteStream &aWriteStream) const
       
   524 {
       
   525 	// Calculate Start/End container names
       
   526 	std::string startName("Start");
       
   527 	startName.append(iName);
       
   528 	std::string endName("End");
       
   529 	endName.append(iName);
       
   530 
       
   531 	prog << Log::Indent() << "Writing " << startName << Log::Endl();
       
   532 
       
   533 	TUint32 arrayLength = iArray.size();
       
   534 
       
   535 	if(aWriteStream.HumanReadable())
       
   536 		{
       
   537 		// Human
       
   538 		aWriteStream.WriteIndent();
       
   539 		aWriteStream.WriteBin(startName.data(), startName.size());
       
   540 		aWriteStream.WriteLineEnd();
       
   541 		}
       
   542 	else
       
   543 		{
       
   544 		// Binary
       
   545 		// Write length of array
       
   546 		aWriteStream.WriteBin(&arrayLength, sizeof(arrayLength));
       
   547 		}
       
   548 	
       
   549 	aWriteStream.IncIndent();
       
   550 
       
   551 	// Write array entries
       
   552 	for(TUint32 i=0; i < arrayLength; ++i)
       
   553 		{
       
   554 		std::ostringstream entryComment;
       
   555 		entryComment << "# Entry " << i+1;
       
   556 		prog << Log::Indent() << entryComment.str() << Log::Endl();
       
   557 		
       
   558 		bool bracketItem = (iArray[i]->ItemType() != 0);
       
   559 		if(aWriteStream.HumanReadable())
       
   560 			{
       
   561 			if(bracketItem)
       
   562 				{
       
   563 				std::ostringstream itemStart;
       
   564 				itemStart << "Start" << iArray[i]->ItemType() << " " << iArray[i]->ItemName();
       
   565 				prog << Log::Indent() << itemStart.str() << Log::Endl();
       
   566 				
       
   567 				aWriteStream.WriteIndent();
       
   568 				aWriteStream.WriteCStr("Start");
       
   569 				aWriteStream.WriteCStr(iArray[i]->ItemType());
       
   570 				aWriteStream.WriteCStr(" \"");
       
   571 				aWriteStream.WriteQuotedUtf8(iArray[i]->ItemName().data(), iArray[i]->ItemName().size());
       
   572 				aWriteStream.WriteCStr("\"");
       
   573 				aWriteStream.WriteLineEnd();
       
   574 				}
       
   575 			else
       
   576 				{
       
   577 				aWriteStream.WriteIndent();
       
   578 				aWriteStream.WriteBin(entryComment.str().data(), entryComment.str().size());
       
   579 				aWriteStream.WriteLineEnd();
       
   580 				}
       
   581 			}
       
   582 		aWriteStream.IncIndent();
       
   583 		iArray[i]->Encode(aWriteStream);
       
   584 		aWriteStream.DecIndent();
       
   585 		if(bracketItem && aWriteStream.HumanReadable())
       
   586 			{
       
   587 			std::ostringstream tmp;
       
   588 			tmp << "End" << iArray[i]->ItemType();
       
   589 
       
   590 			prog << Log::Indent() << tmp.str() << Log::Endl();
       
   591 
       
   592 			aWriteStream.WriteIndent();
       
   593 			aWriteStream.WriteBin(tmp.str().data(), tmp.str().size());
       
   594 			aWriteStream.WriteLineEnd();
       
   595 			}
       
   596 		}
       
   597 
       
   598 	aWriteStream.DecIndent();
       
   599 
       
   600 	if(aWriteStream.HumanReadable())
       
   601 		{
       
   602 		// Human
       
   603 		aWriteStream.WriteIndent();
       
   604 		aWriteStream.WriteCStr("End");
       
   605 		aWriteStream.WriteBin(iName.data(), iName.size());
       
   606 		aWriteStream.WriteLineEnd();
       
   607 		}
       
   608 
       
   609 	prog << Log::Indent() << endName << Log::Endl();
       
   610 
       
   611 	return;
       
   612 }
       
   613 
       
   614 void EncDecContainer::Decode(RDecodeReadStream &aReadStream)
       
   615 {
       
   616 	// Calculate Start/End container names
       
   617 	std::string startName("Start");
       
   618 	startName.append(iName);
       
   619 	std::string endName("End");
       
   620 	endName.append(iName);
       
   621 
       
   622 	prog << Log::Indent() << "Reading " << startName << Log::Endl();
       
   623 
       
   624 	if(aReadStream.HumanReadable())
       
   625 		{
       
   626 		// Human
       
   627 
       
   628 		// Check/consume container StartX
       
   629 		aReadStream.CheckName(startName);
       
   630 
       
   631 		prog.IncIndent();
       
   632 		
       
   633 		// Create items until we find the container EndX
       
   634 		TUint32 entryNum=1;
       
   635 		while(aReadStream.PeakToken() != endName)
       
   636 			{
       
   637 			// Progress message
       
   638 			prog << Log::Indent() << "# Entry " << std::dec << entryNum++ << std::hex << Log::Endl();
       
   639 
       
   640 			EncDecContainerItem *item = iFactory();
       
   641 			bool bracketedItem = (item->ItemType() != 0);
       
   642 			std::string itemName;
       
   643 			if(bracketedItem && aReadStream.HumanReadable())
       
   644 				{
       
   645 				// Bracketed item, so read ItemType tag and ItemName
       
   646 				std::string itemStart("Start");
       
   647 				itemStart.append(item->ItemType());
       
   648 				aReadStream.CheckName(itemStart);
       
   649 				prog << Log::Indent() << itemStart;
       
   650 
       
   651 				// Read item name
       
   652 				aReadStream.ReadNextToken();
       
   653 				itemName = aReadStream.Token();
       
   654 				}
       
   655 		
       
   656 			prog.IncIndent();
       
   657 			item->Decode(aReadStream);
       
   658 			iArray.push_back(item);
       
   659 			prog.DecIndent();
       
   660 			if(bracketedItem && aReadStream.HumanReadable())
       
   661 				{
       
   662 				// Bracketed item, so read End ItemType tag
       
   663 				std::string itemEnd("End");
       
   664 				itemEnd.append(item->ItemType());
       
   665 				aReadStream.CheckName(itemEnd);
       
   666 				// and set item name
       
   667 				item->SetItemName(itemName);
       
   668 				}
       
   669 			}
       
   670 
       
   671 		// Check/consume container EndX
       
   672 		aReadStream.CheckName(endName);
       
   673 
       
   674 		prog.DecIndent();
       
   675 		}
       
   676 	else
       
   677 		{
       
   678 		// Binary
       
   679 		// Read number of entries
       
   680 		TUint32 arrayLength;
       
   681 		aReadStream.RawRead(&arrayLength, sizeof(arrayLength));
       
   682 
       
   683 		prog.IncIndent();
       
   684 		for(TUint32 i=0; i < arrayLength; ++i)
       
   685 			{
       
   686 			EncDecContainerItem *item = iFactory();
       
   687 			prog << Log::Indent() << "# Entry " << std::dec << i+1 << std::hex << Log::Endl();
       
   688 			prog.IncIndent();
       
   689 			item->Decode(aReadStream);
       
   690 			prog.DecIndent();
       
   691 			iArray.push_back(item);
       
   692 			}
       
   693 		prog.DecIndent();
       
   694 		}
       
   695 
       
   696 	prog << Log::Indent() << endName << Log::Endl();
       
   697 
       
   698 }
       
   699 
       
   700 
       
   701 
       
   702 
       
   703 REncodeWriteStream& operator<<(REncodeWriteStream& aStream, const EncDecContainer &aContainer)
       
   704 {
       
   705 	aContainer.Encode(aStream);
       
   706 	return aStream;
       
   707 }
       
   708 
       
   709 RDecodeReadStream& operator>>(RDecodeReadStream& aStream,EncDecContainer &aContainer)
       
   710 {
       
   711 	aContainer.Decode(aStream);
       
   712 	return aStream;
       
   713 }
       
   714 
       
   715 //
       
   716 // TUid
       
   717 //
       
   718 void EncodeHuman(REncodeWriteStream& aStream,const TUid &aUid)
       
   719 {
       
   720 	aStream.WriteHexNumber(aUid.iUid);
       
   721 }
       
   722 void DecodeHuman(RDecodeReadStream& aStream,TUid &aUid)
       
   723 {
       
   724 	aUid.iUid = aStream.ReadUnsignedNumber(sizeof(aUid.iUid));
       
   725 }
       
   726 
       
   727 //
       
   728 // TName
       
   729 //
       
   730 void EncodeHuman(REncodeWriteStream& aStream,const TName &aName)
       
   731 {
       
   732 	// Compress the internal UTF-16 to human readable UTF-8
       
   733 	;
       
   734 	TInt outputBytes = 0;
       
   735 	TUint8 *outBuf = cstrFromUtf16(aName.Ptr(), aName.Length(), outputBytes);
       
   736 	
       
   737 	aStream.WriteByte('"');
       
   738 	aStream.WriteQuotedUtf8(outBuf, outputBytes);
       
   739 	aStream.WriteByte('"');
       
   740 
       
   741 	delete [] outBuf;
       
   742 }
       
   743 void DecodeHuman(RDecodeReadStream& aStream,TName &aName)
       
   744 {
       
   745 	aStream.ReadNextToken();
       
   746 
       
   747 	// Expand UTF-8 into internal UTF-16LE representation
       
   748 	TInt outputWords = 0;
       
   749 	TText *outputBuf = utf16FromUtf8((const TUint8 *)aStream.Token().data(), aStream.Token().size(), outputWords);
       
   750 	memcpy((void *)aName.Ptr(), outputBuf, outputWords*2);
       
   751 	aName.SetLength(outputWords);
       
   752 	delete [] outputBuf;
       
   753 }
       
   754 
       
   755 void readContainer(const std::string &aFileName, bool aHuman, EncDecContainer &container)
       
   756 {
       
   757 	if(aHuman)
       
   758 		{
       
   759 		FileReadStream fileReadStream(aFileName, true);
       
   760 		std::string certBaseName(aFileName);
       
   761 		size_t dotLoc = certBaseName.rfind('.');
       
   762 		if(dotLoc != std::string::npos)
       
   763 			{
       
   764 			certBaseName.erase(dotLoc);
       
   765 			}
       
   766 		certBaseName += '_';
       
   767 		RDecodeReadStream inStream(certBaseName, fileReadStream); // human readable
       
   768 		inStream >> container;
       
   769 		inStream.Close();
       
   770 		}
       
   771 	else
       
   772 		{
       
   773 		RFs fs;
       
   774 		User::LeaveIfError(fs.Connect());
       
   775 		CleanupClosePushL(fs);
       
   776 		
       
   777 		CPermanentFileStore* store = CPermanentFileStore::OpenLC(fs, _L16(aFileName.c_str()),EFileShareAny | EFileRead);
       
   778 		store->SetTypeL(KPermanentFileStoreLayoutUid);
       
   779 
       
   780 		RStoreReadStream rootStream;
       
   781 		rootStream.OpenLC(*store, store->Root());
       
   782 		TUint32 dataStreamId;
       
   783 		rootStream >> dataStreamId;
       
   784 		CleanupStack::PopAndDestroy(&rootStream); 
       
   785 
       
   786 		RStoreReadStream dataStream;
       
   787 		dataStream.OpenLC(*store, dataStreamId);
       
   788 
       
   789 		RDecodeReadStream readStream(store, dataStream); // binary store
       
   790 
       
   791 		readStream >> container;
       
   792 
       
   793 		CleanupStack::PopAndDestroy(&dataStream); 
       
   794 		CleanupStack::PopAndDestroy(store); 
       
   795 		CleanupStack::PopAndDestroy(&fs); 
       
   796 		}
       
   797 }
       
   798 
       
   799 
       
   800 void writeContainer(const char *aFileName, bool aHuman, bool aPemOut, bool aVerbose, const EncDecContainer &container)
       
   801 {
       
   802 	prog << Log::Indent() << "Writing output file '" << aFileName << "'" << Log::Endl();
       
   803 	prog.IncIndent();
       
   804 	if(aHuman)
       
   805 		{
       
   806 		FileWriteStream fileWriteStream(aFileName);
       
   807 		// Calculate based name by striping last .xx extension and appending an underscore.
       
   808 		std::string certBaseName(aFileName);
       
   809 		size_t dotLoc = certBaseName.rfind('.');
       
   810 		if(dotLoc != std::string::npos)
       
   811 			{
       
   812 			certBaseName.erase(dotLoc);
       
   813 			}
       
   814 		certBaseName += '_';
       
   815 		
       
   816 		REncodeWriteStream outStream(certBaseName, fileWriteStream); // human readable
       
   817 		outStream.PemOut() = aPemOut;
       
   818 		outStream.Verbose() = aVerbose;
       
   819 		outStream << container;
       
   820 		outStream.Close();
       
   821 		}
       
   822 	else
       
   823 		{
       
   824 		RFs fs;
       
   825 		User::LeaveIfError(fs.Connect());
       
   826 		CleanupClosePushL(fs);
       
   827 
       
   828 		CFileStore* store = CPermanentFileStore::ReplaceLC(fs,_L16(aFileName),EFileShareAny | EFileRead | EFileWrite);
       
   829 		store->SetTypeL(KPermanentFileStoreLayoutUid);
       
   830 		
       
   831 		RStoreWriteStream dataStream;
       
   832 		TStreamId dataStreamId = dataStream.CreateLC(*store);
       
   833 
       
   834 		REncodeWriteStream outStream(store, dataStream); // binary
       
   835 		outStream << container;
       
   836 		outStream.Close();
       
   837 
       
   838 		dataStream.CommitL();
       
   839 		dataStream.Close();
       
   840 
       
   841 		RStoreWriteStream rootStream;
       
   842 		TStreamId rootId = rootStream.CreateLC(*store);
       
   843 		rootStream << dataStreamId;
       
   844 		rootStream.CommitL();
       
   845 		rootStream.Close();
       
   846 		
       
   847 
       
   848 		store->SetRootL(rootId);
       
   849 		store->CommitL();
       
   850 		CleanupStack::PopAndDestroy(&dataStream); 
       
   851 		CleanupStack::PopAndDestroy(store); 
       
   852 		CleanupStack::PopAndDestroy(&fs); 
       
   853 		}
       
   854 	prog.DecIndent();
       
   855 }
       
   856 
       
   857 
       
   858 // End of file