os/security/securityanddataprivacytools/securitytools/certapp/encdec/encdec.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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