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