--- a/securityanddataprivacytools/securitytools/certapp/encdec/encdec.cpp Tue Jul 21 01:04:32 2009 +0100
+++ b/securityanddataprivacytools/securitytools/certapp/encdec/encdec.cpp Thu Sep 10 14:01:51 2009 +0300
@@ -1,858 +1,858 @@
-/*
-* Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
-* All rights reserved.
-* This component and the accompanying materials are made available
-* under the terms of the License "Eclipse Public License v1.0"
-* which accompanies this distribution, and is available
-* at the URL "http://www.eclipse.org/legal/epl-v10.html".
-*
-* Initial Contributors:
-* Nokia Corporation - initial contribution.
-*
-* Contributors:
-*
-* Description:
-*
-*/
-
-
-#include "encdec.h"
-#include <sstream>
-#include <errno.h>
-#include <s32ucmp.h>
-#include "stringconv.h"
-#include <stdio.h>
-#include "x509utils.h"
-
-RDecodeReadStream::RDecodeReadStream(CFileStore *aStore, RReadStream &aReadStream)
- : iStore(aStore), iCertBaseName(), iReadStream(aReadStream), iHumanReadable(false), iToken(),
- iPrefetchedTokenIsValid(false), iPrefetchedToken()
-{
-}
-
-RDecodeReadStream::RDecodeReadStream(const std::string &aCertBaseName, RReadStream &aReadStream)
- : iStore(0), iCertBaseName(aCertBaseName), iReadStream(aReadStream), iHumanReadable(true), iToken(),
- iPrefetchedTokenIsValid(false), iPrefetchedToken()
-{
-}
-
-void RDecodeReadStream::RawRead(void *aPtr, TUint32 aLength)
-{
- iReadStream.ReadL((TUint8 *)aPtr, aLength);
-}
-
-void RDecodeReadStream::CheckName(const std::string &aExpected)
-{
- ReadNextToken();
-
- if(iToken != aExpected)
- {
- dbg << Log::Indent() << "Expected token '" << aExpected <<"' but got token '" << iToken << "'" << Log::Endl();
- FatalError();
- }
-
-}
-
-TUint32 ReadUnsignedNumber(std::string &aStr, size_t aSize)
-{
- TUint32 val;
- std::istringstream ss(aStr);
-
- if((aStr.length() > 2) &&
- (aStr[0] == '0') &&
- ((aStr[1] == 'x') || (aStr[1] == 'X')))
- {
- // Hex number starting with 0x
- char ch;
- ss >> ch >> ch; // Discard the 0x
- ss >> std::hex >> val;
- }
- else
- {
- // Decimal number
- ss >> val;
- }
-
- // Now work out if we consumed the entire token without error
- if(ss.fail())
- {
- // Number decode failed
- dbg << Log::Indent() << "Failed to decode '" << aStr << "' as a number" << Log::Endl();
- FatalError();
- }
-
- // Make sure we consumed all data
- if(! ss.eof())
- {
- // Trailing chars on numeric token
- FatalError();
- }
-
- if(aSize != 4)
- {
- // Check range
- // nb the following check would fail if aSize==4 because x>>32 == x if sizeof(x)==4
- if((val >> (8*aSize)) != 0)
- {
- // Higher order bits are set above the size of the variable we
- // are returning into
- FatalError();
- }
- }
-return val;
-}
-
-
-TUint32 RDecodeReadStream::ReadUnsignedNumber(size_t aSize)
-{
-BULLSEYE_OFF
- if((TUint32(aSize)>4))
- {
- FatalError();
- }
-BULLSEYE_RESTORE
-
- ReadNextToken();
-
- return ::ReadUnsignedNumber(iToken, aSize);
-}
-
-const std::string &RDecodeReadStream::Token() const
-{
- return iToken;
-}
-
-void RDecodeReadStream::ReadNextToken()
-{
- if(iPrefetchedTokenIsValid)
- {
- // Copy prefetched token to current token
- iToken = iPrefetchedToken;
- iPrefetchedToken.clear();
- iPrefetchedTokenIsValid = false;
- return;
- }
-
- GetToken(iToken);
-}
-
-const std::string &RDecodeReadStream::PeakToken()
-{
- if(!iPrefetchedTokenIsValid)
- {
- GetToken(iPrefetchedToken);
- iPrefetchedTokenIsValid = true;
- }
-
- return iPrefetchedToken;
-}
-
-
-
-
-
-bool RDecodeReadStream::HumanReadable() const
-{
- return iHumanReadable;
-}
-
-
-void RDecodeReadStream::Close()
-{
- iReadStream.Close();
-}
-
-void RDecodeReadStream::GetToken(std::string &aToken)
-{
- aToken.clear();
-
- TUint8 ch;
- do
- {
- iReadStream >> ch;
- if(ch == '#')
- {
- // Skip comment
- ++ch;
- while((ch != '\r') && (ch != '\n'))
- {
- iReadStream >> ch;
- }
-
- }
- } while((ch == ' ') || (ch == '\t') || (ch == '\r') || (ch == '\n'));
-
- if(ch == '"')
- {
- // Read a string
- iReadStream >> ch; // read first char
- while(ch != '"')
- {
- if(ch=='\\')
- {
- // \X causes X to always be saved (even if X is ")
- iReadStream >> ch;
- }
-
- aToken.push_back(ch);
- iReadStream >> ch;
- }
- // At this point ch contains WS so it can be discarded.
- return;
- }
-
- // Read a non-string token
- while((ch != ' ') && (ch != '\t') && (ch != '\r') && (ch != '\n'))
- {
- aToken.push_back(ch);
- iReadStream >> ch;
- }
- // At this point ch contains WS so it can be discarded.
- return;
-}
-
-
-
-
-
-REncodeWriteStream::REncodeWriteStream(CFileStore *aStore, RWriteStream &aWriteStream)
- : iStore(aStore),
- iCertBaseName(), // not used for STORE based streams
- iWriteStream(&aWriteStream),
- iLogStream(0),
- iHumanReadable(false), iPemOut(false), iVerbose(false), iIndentLevel(0)
-{
-}
-
-REncodeWriteStream::REncodeWriteStream(const std::string &aCertBaseName, RWriteStream &aWriteStream)
- : iStore(0), iCertBaseName(aCertBaseName), iWriteStream(&aWriteStream),
- iLogStream(0),
- iHumanReadable(true), iPemOut(false), iVerbose(false), iIndentLevel(0)
-{
-}
-
-REncodeWriteStream::REncodeWriteStream(Log &aLog)
- : iStore(0), iWriteStream(0), iLogStream(&aLog.Stream()),
- iHumanReadable(true), iPemOut(false), iVerbose(false), iIndentLevel(aLog.IndentLevel())
-{
-}
-
-void REncodeWriteStream::WriteBin(const void *aPtr, TUint32 aLength)
-{
- if(iWriteStream)
- {
- iWriteStream->WriteL((TUint8 *)aPtr, aLength);
- }
- if(iLogStream)
- {
- iLogStream->write((const char *)aPtr, aLength);
- iLogStream->flush();
- }
-}
-
-void REncodeWriteStream::WriteQuotedUtf8(const void *aStr, TUint32 aLength)
-{
- std::string tmp((const char *)aStr, aLength);
-
- // Insert a backslash before any backslash chars
- size_t pos = 0;
- while((pos = tmp.find('\\', pos)) != std::string::npos)
- {
- tmp.insert(pos, "\\", 1);
- pos += 2;
- }
-
- // Insert a backslash before any double quote chars
- pos = 0;
- while((pos = tmp.find('"', pos)) != std::string::npos)
- {
- tmp.insert(pos, "\\", 1);
- pos += 2;
- }
-
- if(iWriteStream)
- {
- iWriteStream->WriteL((TUint8 *)tmp.data(), tmp.size());
- }
- if(iLogStream)
- {
- iLogStream->write(tmp.data(), tmp.size());
- iLogStream->flush();
- }
-}
-
-void REncodeWriteStream::WriteByte(TUint8 aByte)
-{
- WriteBin(&aByte, 1);
-}
-
-void REncodeWriteStream::WriteCStr(const void *aCstr)
-{
- WriteBin(aCstr, strlen((const char *)aCstr));
-}
-
-void REncodeWriteStream::WriteHexNumber(TUint32 aNumber)
-{
- char buf[20];
- int len = sprintf(buf, "0x%x", aNumber);
- WriteBin(buf, len);
-}
-
-
-void REncodeWriteStream::WriteSpace()
-{
-BULLSEYE_OFF
- if(!iHumanReadable) return;
-BULLSEYE_RESTORE
- WriteByte(' ');
-}
-
-void REncodeWriteStream::WriteLineEnd()
-{
-BULLSEYE_OFF
- if(!iHumanReadable) return;
-BULLSEYE_RESTORE
-#ifdef linux
- WriteByte('\n');
-#else
- WriteBin("\r\n", 2);
-#endif
-}
-
-
-void REncodeWriteStream::WriteIndent()
-{
-BULLSEYE_OFF
- if(!iHumanReadable) return;
-BULLSEYE_RESTORE
- for(int i=0; i<iIndentLevel; ++i)
- {
- WriteByte('\t');
- }
-}
-
-void REncodeWriteStream::IncIndent()
-{
- prog.IncIndent();
- ++iIndentLevel;
-BULLSEYE_OFF
- if(iIndentLevel < 0) FatalError();
-BULLSEYE_RESTORE
-}
-
-void REncodeWriteStream::DecIndent()
-{
- prog.DecIndent();
- --iIndentLevel;
-BULLSEYE_OFF
- if(iIndentLevel < 0) FatalError();
-BULLSEYE_RESTORE
-}
-
-bool REncodeWriteStream::HumanReadable() const
-{
- return iHumanReadable;
-}
-
-bool &REncodeWriteStream::PemOut()
-{
- return iPemOut;
-}
-
-bool &REncodeWriteStream::Verbose()
-{
- return iVerbose;
-}
-
-
-
-std::string REncodeWriteStream::CertFileName(TUint32 aFormat, TUint32 aCertNumber)
-{
- std::stringstream ss;
- ss << iCertBaseName;
- ss << "cert";
- ss << aCertNumber;
- if(aFormat == EX509Certificate)
- {
- if(iPemOut)
- {
- ss << ".pem";
- }
- else
- {
- ss << ".der";
- }
- }
- else
- {
- ss << ".dat";
- }
-
- return ss.str();
-}
-
-
-
-void REncodeWriteStream::Close()
-{
-BULLSEYE_OFF
- if(iWriteStream)
-BULLSEYE_RESTORE
- {
- iWriteStream->Close();
- }
-}
-
-CFileStore *REncodeWriteStream::StoreObject()
-{
-BULLSEYE_OFF
- if(iStore == 0) FatalError();
-BULLSEYE_RESTORE
- return iStore;
-}
-
-RWriteStream &REncodeWriteStream::StoreWriteStream()
-{
-BULLSEYE_OFF
- if(iWriteStream == 0) FatalError();
-BULLSEYE_RESTORE
- return *iWriteStream;
-}
-
-bool REncodeWriteStream::Quiet() const
-{
- return iLogStream != 0;
-}
-
-TUint8 fromHex(TUint8 ch)
- /**
- Convert a single hex char from ascii
- */
-{
- // convert to lowercase
- if((ch >= 'A') && (ch <= 'F'))
- {
- ch -= ('A' -'a');
- }
- // Handle a-f
- if((ch >= 'a') && (ch <= 'f'))
- {
- return ch - 'a' + 10;
- }
-
- // Handle 0-9
- if((ch >= '0') && (ch <= '9'))
- {
- return ch - '0';
- }
-
- // Illegal
- FatalError();
- return 0xff;
-}
-
-EncDecContainerItem::~EncDecContainerItem()
-{
-}
-
-
-#ifdef _BullseyeCoverage
-#pragma BullseyeCoverage off
-#endif
-std::string EncDecContainerItem::ItemName() const
-{
- // Should never be called
- exit(-1);
- std::string tmp;
- return tmp;
-}
-
-void EncDecContainerItem::SetItemName(const std::string &)
-{
- // Should never be called
- exit(-1);
-}
-#ifdef _BullseyeCoverage
-#pragma BullseyeCoverage restore
-#endif
-
-
-
-EncDecContainer::EncDecContainer(const char *aContainerName, EncDecContainerItemFactoryFunc *aFactory)
- : iName(aContainerName), iFactory(aFactory), iArray()
-{
-}
-
-EncDecContainer::~EncDecContainer()
-{
- reset();
-}
-
-void EncDecContainer::push_back(EncDecContainerItem *aItem)
-{
- iArray.push_back(aItem);
-}
-
-const EncDecContainerItem &EncDecContainer::operator[](TUint32 aIndex) const
-{
- return *iArray[aIndex];
-}
-
-EncDecContainerItem &EncDecContainer::operator[](TUint32 aIndex)
-{
- return *iArray[aIndex];
-}
-
-TUint32 EncDecContainer::size() const
-{
- return iArray.size();
-}
-
-void EncDecContainer::reset()
-{
- while(!iArray.empty())
- {
- EncDecContainerItem *p = iArray.back();
- iArray.pop_back();
- delete p;
- }
-}
-
-
-
-void EncDecContainer::Encode(REncodeWriteStream &aWriteStream) const
-{
- // Calculate Start/End container names
- std::string startName("Start");
- startName.append(iName);
- std::string endName("End");
- endName.append(iName);
-
- prog << Log::Indent() << "Writing " << startName << Log::Endl();
-
- TUint32 arrayLength = iArray.size();
-
- if(aWriteStream.HumanReadable())
- {
- // Human
- aWriteStream.WriteIndent();
- aWriteStream.WriteBin(startName.data(), startName.size());
- aWriteStream.WriteLineEnd();
- }
- else
- {
- // Binary
- // Write length of array
- aWriteStream.WriteBin(&arrayLength, sizeof(arrayLength));
- }
-
- aWriteStream.IncIndent();
-
- // Write array entries
- for(TUint32 i=0; i < arrayLength; ++i)
- {
- std::ostringstream entryComment;
- entryComment << "# Entry " << i+1;
- prog << Log::Indent() << entryComment.str() << Log::Endl();
-
- bool bracketItem = (iArray[i]->ItemType() != 0);
- if(aWriteStream.HumanReadable())
- {
- if(bracketItem)
- {
- std::ostringstream itemStart;
- itemStart << "Start" << iArray[i]->ItemType() << " " << iArray[i]->ItemName();
- prog << Log::Indent() << itemStart.str() << Log::Endl();
-
- aWriteStream.WriteIndent();
- aWriteStream.WriteCStr("Start");
- aWriteStream.WriteCStr(iArray[i]->ItemType());
- aWriteStream.WriteCStr(" \"");
- aWriteStream.WriteQuotedUtf8(iArray[i]->ItemName().data(), iArray[i]->ItemName().size());
- aWriteStream.WriteCStr("\"");
- aWriteStream.WriteLineEnd();
- }
- else
- {
- aWriteStream.WriteIndent();
- aWriteStream.WriteBin(entryComment.str().data(), entryComment.str().size());
- aWriteStream.WriteLineEnd();
- }
- }
- aWriteStream.IncIndent();
- iArray[i]->Encode(aWriteStream);
- aWriteStream.DecIndent();
- if(bracketItem && aWriteStream.HumanReadable())
- {
- std::ostringstream tmp;
- tmp << "End" << iArray[i]->ItemType();
-
- prog << Log::Indent() << tmp.str() << Log::Endl();
-
- aWriteStream.WriteIndent();
- aWriteStream.WriteBin(tmp.str().data(), tmp.str().size());
- aWriteStream.WriteLineEnd();
- }
- }
-
- aWriteStream.DecIndent();
-
- if(aWriteStream.HumanReadable())
- {
- // Human
- aWriteStream.WriteIndent();
- aWriteStream.WriteCStr("End");
- aWriteStream.WriteBin(iName.data(), iName.size());
- aWriteStream.WriteLineEnd();
- }
-
- prog << Log::Indent() << endName << Log::Endl();
-
- return;
-}
-
-void EncDecContainer::Decode(RDecodeReadStream &aReadStream)
-{
- // Calculate Start/End container names
- std::string startName("Start");
- startName.append(iName);
- std::string endName("End");
- endName.append(iName);
-
- prog << Log::Indent() << "Reading " << startName << Log::Endl();
-
- if(aReadStream.HumanReadable())
- {
- // Human
-
- // Check/consume container StartX
- aReadStream.CheckName(startName);
-
- prog.IncIndent();
-
- // Create items until we find the container EndX
- TUint32 entryNum=1;
- while(aReadStream.PeakToken() != endName)
- {
- // Progress message
- prog << Log::Indent() << "# Entry " << std::dec << entryNum++ << std::hex << Log::Endl();
-
- EncDecContainerItem *item = iFactory();
- bool bracketedItem = (item->ItemType() != 0);
- std::string itemName;
- if(bracketedItem && aReadStream.HumanReadable())
- {
- // Bracketed item, so read ItemType tag and ItemName
- std::string itemStart("Start");
- itemStart.append(item->ItemType());
- aReadStream.CheckName(itemStart);
- prog << Log::Indent() << itemStart;
-
- // Read item name
- aReadStream.ReadNextToken();
- itemName = aReadStream.Token();
- }
-
- prog.IncIndent();
- item->Decode(aReadStream);
- iArray.push_back(item);
- prog.DecIndent();
- if(bracketedItem && aReadStream.HumanReadable())
- {
- // Bracketed item, so read End ItemType tag
- std::string itemEnd("End");
- itemEnd.append(item->ItemType());
- aReadStream.CheckName(itemEnd);
- // and set item name
- item->SetItemName(itemName);
- }
- }
-
- // Check/consume container EndX
- aReadStream.CheckName(endName);
-
- prog.DecIndent();
- }
- else
- {
- // Binary
- // Read number of entries
- TUint32 arrayLength;
- aReadStream.RawRead(&arrayLength, sizeof(arrayLength));
-
- prog.IncIndent();
- for(TUint32 i=0; i < arrayLength; ++i)
- {
- EncDecContainerItem *item = iFactory();
- prog << Log::Indent() << "# Entry " << std::dec << i+1 << std::hex << Log::Endl();
- prog.IncIndent();
- item->Decode(aReadStream);
- prog.DecIndent();
- iArray.push_back(item);
- }
- prog.DecIndent();
- }
-
- prog << Log::Indent() << endName << Log::Endl();
-
-}
-
-
-
-
-REncodeWriteStream& operator<<(REncodeWriteStream& aStream, const EncDecContainer &aContainer)
-{
- aContainer.Encode(aStream);
- return aStream;
-}
-
-RDecodeReadStream& operator>>(RDecodeReadStream& aStream,EncDecContainer &aContainer)
-{
- aContainer.Decode(aStream);
- return aStream;
-}
-
-//
-// TUid
-//
-void EncodeHuman(REncodeWriteStream& aStream,const TUid &aUid)
-{
- aStream.WriteHexNumber(aUid.iUid);
-}
-void DecodeHuman(RDecodeReadStream& aStream,TUid &aUid)
-{
- aUid.iUid = aStream.ReadUnsignedNumber(sizeof(aUid.iUid));
-}
-
-//
-// TName
-//
-void EncodeHuman(REncodeWriteStream& aStream,const TName &aName)
-{
- // Compress the internal UTF-16 to human readable UTF-8
- ;
- TInt outputBytes = 0;
- TUint8 *outBuf = cstrFromUtf16(aName.Ptr(), aName.Length(), outputBytes);
-
- aStream.WriteByte('"');
- aStream.WriteQuotedUtf8(outBuf, outputBytes);
- aStream.WriteByte('"');
-
- delete [] outBuf;
-}
-void DecodeHuman(RDecodeReadStream& aStream,TName &aName)
-{
- aStream.ReadNextToken();
-
- // Expand UTF-8 into internal UTF-16LE representation
- TInt outputWords = 0;
- TText *outputBuf = utf16FromUtf8((const TUint8 *)aStream.Token().data(), aStream.Token().size(), outputWords);
- memcpy((void *)aName.Ptr(), outputBuf, outputWords*2);
- aName.SetLength(outputWords);
- delete [] outputBuf;
-}
-
-void readContainer(const std::string &aFileName, bool aHuman, EncDecContainer &container)
-{
- if(aHuman)
- {
- FileReadStream fileReadStream(aFileName, true);
- std::string certBaseName(aFileName);
- size_t dotLoc = certBaseName.rfind('.');
- if(dotLoc != std::string::npos)
- {
- certBaseName.erase(dotLoc);
- }
- certBaseName += '_';
- RDecodeReadStream inStream(certBaseName, fileReadStream); // human readable
- inStream >> container;
- inStream.Close();
- }
- else
- {
- RFs fs;
- User::LeaveIfError(fs.Connect());
- CleanupClosePushL(fs);
-
- CPermanentFileStore* store = CPermanentFileStore::OpenLC(fs, _L16(aFileName.c_str()),EFileShareAny | EFileRead);
- store->SetTypeL(KPermanentFileStoreLayoutUid);
-
- RStoreReadStream rootStream;
- rootStream.OpenLC(*store, store->Root());
- TUint32 dataStreamId;
- rootStream >> dataStreamId;
- CleanupStack::PopAndDestroy(&rootStream);
-
- RStoreReadStream dataStream;
- dataStream.OpenLC(*store, dataStreamId);
-
- RDecodeReadStream readStream(store, dataStream); // binary store
-
- readStream >> container;
-
- CleanupStack::PopAndDestroy(&dataStream);
- CleanupStack::PopAndDestroy(store);
- CleanupStack::PopAndDestroy(&fs);
- }
-}
-
-
-void writeContainer(const char *aFileName, bool aHuman, bool aPemOut, bool aVerbose, const EncDecContainer &container)
-{
- prog << Log::Indent() << "Writing output file '" << aFileName << "'" << Log::Endl();
- prog.IncIndent();
- if(aHuman)
- {
- FileWriteStream fileWriteStream(aFileName);
- // Calculate based name by striping last .xx extension and appending an underscore.
- std::string certBaseName(aFileName);
- size_t dotLoc = certBaseName.rfind('.');
- if(dotLoc != std::string::npos)
- {
- certBaseName.erase(dotLoc);
- }
- certBaseName += '_';
-
- REncodeWriteStream outStream(certBaseName, fileWriteStream); // human readable
- outStream.PemOut() = aPemOut;
- outStream.Verbose() = aVerbose;
- outStream << container;
- outStream.Close();
- }
- else
- {
- RFs fs;
- User::LeaveIfError(fs.Connect());
- CleanupClosePushL(fs);
-
- CFileStore* store = CPermanentFileStore::ReplaceLC(fs,_L16(aFileName),EFileShareAny | EFileRead | EFileWrite);
- store->SetTypeL(KPermanentFileStoreLayoutUid);
-
- RStoreWriteStream dataStream;
- TStreamId dataStreamId = dataStream.CreateLC(*store);
-
- REncodeWriteStream outStream(store, dataStream); // binary
- outStream << container;
- outStream.Close();
-
- dataStream.CommitL();
- dataStream.Close();
-
- RStoreWriteStream rootStream;
- TStreamId rootId = rootStream.CreateLC(*store);
- rootStream << dataStreamId;
- rootStream.CommitL();
- rootStream.Close();
-
-
- store->SetRootL(rootId);
- store->CommitL();
- CleanupStack::PopAndDestroy(&dataStream);
- CleanupStack::PopAndDestroy(store);
- CleanupStack::PopAndDestroy(&fs);
- }
- prog.DecIndent();
-}
-
-
-// End of file
+/*
+* Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+
+
+#include "encdec.h"
+#include <sstream>
+#include <errno.h>
+#include <s32ucmp.h>
+#include "stringconv.h"
+#include <stdio.h>
+#include "x509utils.h"
+
+RDecodeReadStream::RDecodeReadStream(CFileStore *aStore, RReadStream &aReadStream)
+ : iStore(aStore), iCertBaseName(), iReadStream(aReadStream), iHumanReadable(false), iToken(),
+ iPrefetchedTokenIsValid(false), iPrefetchedToken()
+{
+}
+
+RDecodeReadStream::RDecodeReadStream(const std::string &aCertBaseName, RReadStream &aReadStream)
+ : iStore(0), iCertBaseName(aCertBaseName), iReadStream(aReadStream), iHumanReadable(true), iToken(),
+ iPrefetchedTokenIsValid(false), iPrefetchedToken()
+{
+}
+
+void RDecodeReadStream::RawRead(void *aPtr, TUint32 aLength)
+{
+ iReadStream.ReadL((TUint8 *)aPtr, aLength);
+}
+
+void RDecodeReadStream::CheckName(const std::string &aExpected)
+{
+ ReadNextToken();
+
+ if(iToken != aExpected)
+ {
+ dbg << Log::Indent() << "Expected token '" << aExpected <<"' but got token '" << iToken << "'" << Log::Endl();
+ FatalError();
+ }
+
+}
+
+TUint32 ReadUnsignedNumber(std::string &aStr, size_t aSize)
+{
+ TUint32 val;
+ std::istringstream ss(aStr);
+
+ if((aStr.length() > 2) &&
+ (aStr[0] == '0') &&
+ ((aStr[1] == 'x') || (aStr[1] == 'X')))
+ {
+ // Hex number starting with 0x
+ char ch;
+ ss >> ch >> ch; // Discard the 0x
+ ss >> std::hex >> val;
+ }
+ else
+ {
+ // Decimal number
+ ss >> val;
+ }
+
+ // Now work out if we consumed the entire token without error
+ if(ss.fail())
+ {
+ // Number decode failed
+ dbg << Log::Indent() << "Failed to decode '" << aStr << "' as a number" << Log::Endl();
+ FatalError();
+ }
+
+ // Make sure we consumed all data
+ if(! ss.eof())
+ {
+ // Trailing chars on numeric token
+ FatalError();
+ }
+
+ if(aSize != 4)
+ {
+ // Check range
+ // nb the following check would fail if aSize==4 because x>>32 == x if sizeof(x)==4
+ if((val >> (8*aSize)) != 0)
+ {
+ // Higher order bits are set above the size of the variable we
+ // are returning into
+ FatalError();
+ }
+ }
+return val;
+}
+
+
+TUint32 RDecodeReadStream::ReadUnsignedNumber(size_t aSize)
+{
+BULLSEYE_OFF
+ if((TUint32(aSize)>4))
+ {
+ FatalError();
+ }
+BULLSEYE_RESTORE
+
+ ReadNextToken();
+
+ return ::ReadUnsignedNumber(iToken, aSize);
+}
+
+const std::string &RDecodeReadStream::Token() const
+{
+ return iToken;
+}
+
+void RDecodeReadStream::ReadNextToken()
+{
+ if(iPrefetchedTokenIsValid)
+ {
+ // Copy prefetched token to current token
+ iToken = iPrefetchedToken;
+ iPrefetchedToken.clear();
+ iPrefetchedTokenIsValid = false;
+ return;
+ }
+
+ GetToken(iToken);
+}
+
+const std::string &RDecodeReadStream::PeakToken()
+{
+ if(!iPrefetchedTokenIsValid)
+ {
+ GetToken(iPrefetchedToken);
+ iPrefetchedTokenIsValid = true;
+ }
+
+ return iPrefetchedToken;
+}
+
+
+
+
+
+bool RDecodeReadStream::HumanReadable() const
+{
+ return iHumanReadable;
+}
+
+
+void RDecodeReadStream::Close()
+{
+ iReadStream.Close();
+}
+
+void RDecodeReadStream::GetToken(std::string &aToken)
+{
+ aToken.clear();
+
+ TUint8 ch;
+ do
+ {
+ iReadStream >> ch;
+ if(ch == '#')
+ {
+ // Skip comment
+ ++ch;
+ while((ch != '\r') && (ch != '\n'))
+ {
+ iReadStream >> ch;
+ }
+
+ }
+ } while((ch == ' ') || (ch == '\t') || (ch == '\r') || (ch == '\n'));
+
+ if(ch == '"')
+ {
+ // Read a string
+ iReadStream >> ch; // read first char
+ while(ch != '"')
+ {
+ if(ch=='\\')
+ {
+ // \X causes X to always be saved (even if X is ")
+ iReadStream >> ch;
+ }
+
+ aToken.push_back(ch);
+ iReadStream >> ch;
+ }
+ // At this point ch contains WS so it can be discarded.
+ return;
+ }
+
+ // Read a non-string token
+ while((ch != ' ') && (ch != '\t') && (ch != '\r') && (ch != '\n'))
+ {
+ aToken.push_back(ch);
+ iReadStream >> ch;
+ }
+ // At this point ch contains WS so it can be discarded.
+ return;
+}
+
+
+
+
+
+REncodeWriteStream::REncodeWriteStream(CFileStore *aStore, RWriteStream &aWriteStream)
+ : iStore(aStore),
+ iCertBaseName(), // not used for STORE based streams
+ iWriteStream(&aWriteStream),
+ iLogStream(0),
+ iHumanReadable(false), iPemOut(false), iVerbose(false), iIndentLevel(0)
+{
+}
+
+REncodeWriteStream::REncodeWriteStream(const std::string &aCertBaseName, RWriteStream &aWriteStream)
+ : iStore(0), iCertBaseName(aCertBaseName), iWriteStream(&aWriteStream),
+ iLogStream(0),
+ iHumanReadable(true), iPemOut(false), iVerbose(false), iIndentLevel(0)
+{
+}
+
+REncodeWriteStream::REncodeWriteStream(Log &aLog)
+ : iStore(0), iWriteStream(0), iLogStream(&aLog.Stream()),
+ iHumanReadable(true), iPemOut(false), iVerbose(false), iIndentLevel(aLog.IndentLevel())
+{
+}
+
+void REncodeWriteStream::WriteBin(const void *aPtr, TUint32 aLength)
+{
+ if(iWriteStream)
+ {
+ iWriteStream->WriteL((TUint8 *)aPtr, aLength);
+ }
+ if(iLogStream)
+ {
+ iLogStream->write((const char *)aPtr, aLength);
+ iLogStream->flush();
+ }
+}
+
+void REncodeWriteStream::WriteQuotedUtf8(const void *aStr, TUint32 aLength)
+{
+ std::string tmp((const char *)aStr, aLength);
+
+ // Insert a backslash before any backslash chars
+ size_t pos = 0;
+ while((pos = tmp.find('\\', pos)) != std::string::npos)
+ {
+ tmp.insert(pos, "\\", 1);
+ pos += 2;
+ }
+
+ // Insert a backslash before any double quote chars
+ pos = 0;
+ while((pos = tmp.find('"', pos)) != std::string::npos)
+ {
+ tmp.insert(pos, "\\", 1);
+ pos += 2;
+ }
+
+ if(iWriteStream)
+ {
+ iWriteStream->WriteL((TUint8 *)tmp.data(), tmp.size());
+ }
+ if(iLogStream)
+ {
+ iLogStream->write(tmp.data(), tmp.size());
+ iLogStream->flush();
+ }
+}
+
+void REncodeWriteStream::WriteByte(TUint8 aByte)
+{
+ WriteBin(&aByte, 1);
+}
+
+void REncodeWriteStream::WriteCStr(const void *aCstr)
+{
+ WriteBin(aCstr, strlen((const char *)aCstr));
+}
+
+void REncodeWriteStream::WriteHexNumber(TUint32 aNumber)
+{
+ char buf[20];
+ int len = sprintf(buf, "0x%x", aNumber);
+ WriteBin(buf, len);
+}
+
+
+void REncodeWriteStream::WriteSpace()
+{
+BULLSEYE_OFF
+ if(!iHumanReadable) return;
+BULLSEYE_RESTORE
+ WriteByte(' ');
+}
+
+void REncodeWriteStream::WriteLineEnd()
+{
+BULLSEYE_OFF
+ if(!iHumanReadable) return;
+BULLSEYE_RESTORE
+#ifdef linux
+ WriteByte('\n');
+#else
+ WriteBin("\r\n", 2);
+#endif
+}
+
+
+void REncodeWriteStream::WriteIndent()
+{
+BULLSEYE_OFF
+ if(!iHumanReadable) return;
+BULLSEYE_RESTORE
+ for(int i=0; i<iIndentLevel; ++i)
+ {
+ WriteByte('\t');
+ }
+}
+
+void REncodeWriteStream::IncIndent()
+{
+ prog.IncIndent();
+ ++iIndentLevel;
+BULLSEYE_OFF
+ if(iIndentLevel < 0) FatalError();
+BULLSEYE_RESTORE
+}
+
+void REncodeWriteStream::DecIndent()
+{
+ prog.DecIndent();
+ --iIndentLevel;
+BULLSEYE_OFF
+ if(iIndentLevel < 0) FatalError();
+BULLSEYE_RESTORE
+}
+
+bool REncodeWriteStream::HumanReadable() const
+{
+ return iHumanReadable;
+}
+
+bool &REncodeWriteStream::PemOut()
+{
+ return iPemOut;
+}
+
+bool &REncodeWriteStream::Verbose()
+{
+ return iVerbose;
+}
+
+
+
+std::string REncodeWriteStream::CertFileName(TUint32 aFormat, TUint32 aCertNumber)
+{
+ std::stringstream ss;
+ ss << iCertBaseName;
+ ss << "cert";
+ ss << aCertNumber;
+ if(aFormat == EX509Certificate)
+ {
+ if(iPemOut)
+ {
+ ss << ".pem";
+ }
+ else
+ {
+ ss << ".der";
+ }
+ }
+ else
+ {
+ ss << ".dat";
+ }
+
+ return ss.str();
+}
+
+
+
+void REncodeWriteStream::Close()
+{
+BULLSEYE_OFF
+ if(iWriteStream)
+BULLSEYE_RESTORE
+ {
+ iWriteStream->Close();
+ }
+}
+
+CFileStore *REncodeWriteStream::StoreObject()
+{
+BULLSEYE_OFF
+ if(iStore == 0) FatalError();
+BULLSEYE_RESTORE
+ return iStore;
+}
+
+RWriteStream &REncodeWriteStream::StoreWriteStream()
+{
+BULLSEYE_OFF
+ if(iWriteStream == 0) FatalError();
+BULLSEYE_RESTORE
+ return *iWriteStream;
+}
+
+bool REncodeWriteStream::Quiet() const
+{
+ return iLogStream != 0;
+}
+
+TUint8 fromHex(TUint8 ch)
+ /**
+ Convert a single hex char from ascii
+ */
+{
+ // convert to lowercase
+ if((ch >= 'A') && (ch <= 'F'))
+ {
+ ch -= ('A' -'a');
+ }
+ // Handle a-f
+ if((ch >= 'a') && (ch <= 'f'))
+ {
+ return ch - 'a' + 10;
+ }
+
+ // Handle 0-9
+ if((ch >= '0') && (ch <= '9'))
+ {
+ return ch - '0';
+ }
+
+ // Illegal
+ FatalError();
+ return 0xff;
+}
+
+EncDecContainerItem::~EncDecContainerItem()
+{
+}
+
+
+#ifdef _BullseyeCoverage
+#pragma BullseyeCoverage off
+#endif
+std::string EncDecContainerItem::ItemName() const
+{
+ // Should never be called
+ exit(-1);
+ std::string tmp;
+ return tmp;
+}
+
+void EncDecContainerItem::SetItemName(const std::string &)
+{
+ // Should never be called
+ exit(-1);
+}
+#ifdef _BullseyeCoverage
+#pragma BullseyeCoverage restore
+#endif
+
+
+
+EncDecContainer::EncDecContainer(const char *aContainerName, EncDecContainerItemFactoryFunc *aFactory)
+ : iName(aContainerName), iFactory(aFactory), iArray()
+{
+}
+
+EncDecContainer::~EncDecContainer()
+{
+ reset();
+}
+
+void EncDecContainer::push_back(EncDecContainerItem *aItem)
+{
+ iArray.push_back(aItem);
+}
+
+const EncDecContainerItem &EncDecContainer::operator[](TUint32 aIndex) const
+{
+ return *iArray[aIndex];
+}
+
+EncDecContainerItem &EncDecContainer::operator[](TUint32 aIndex)
+{
+ return *iArray[aIndex];
+}
+
+TUint32 EncDecContainer::size() const
+{
+ return iArray.size();
+}
+
+void EncDecContainer::reset()
+{
+ while(!iArray.empty())
+ {
+ EncDecContainerItem *p = iArray.back();
+ iArray.pop_back();
+ delete p;
+ }
+}
+
+
+
+void EncDecContainer::Encode(REncodeWriteStream &aWriteStream) const
+{
+ // Calculate Start/End container names
+ std::string startName("Start");
+ startName.append(iName);
+ std::string endName("End");
+ endName.append(iName);
+
+ prog << Log::Indent() << "Writing " << startName << Log::Endl();
+
+ TUint32 arrayLength = iArray.size();
+
+ if(aWriteStream.HumanReadable())
+ {
+ // Human
+ aWriteStream.WriteIndent();
+ aWriteStream.WriteBin(startName.data(), startName.size());
+ aWriteStream.WriteLineEnd();
+ }
+ else
+ {
+ // Binary
+ // Write length of array
+ aWriteStream.WriteBin(&arrayLength, sizeof(arrayLength));
+ }
+
+ aWriteStream.IncIndent();
+
+ // Write array entries
+ for(TUint32 i=0; i < arrayLength; ++i)
+ {
+ std::ostringstream entryComment;
+ entryComment << "# Entry " << i+1;
+ prog << Log::Indent() << entryComment.str() << Log::Endl();
+
+ bool bracketItem = (iArray[i]->ItemType() != 0);
+ if(aWriteStream.HumanReadable())
+ {
+ if(bracketItem)
+ {
+ std::ostringstream itemStart;
+ itemStart << "Start" << iArray[i]->ItemType() << " " << iArray[i]->ItemName();
+ prog << Log::Indent() << itemStart.str() << Log::Endl();
+
+ aWriteStream.WriteIndent();
+ aWriteStream.WriteCStr("Start");
+ aWriteStream.WriteCStr(iArray[i]->ItemType());
+ aWriteStream.WriteCStr(" \"");
+ aWriteStream.WriteQuotedUtf8(iArray[i]->ItemName().data(), iArray[i]->ItemName().size());
+ aWriteStream.WriteCStr("\"");
+ aWriteStream.WriteLineEnd();
+ }
+ else
+ {
+ aWriteStream.WriteIndent();
+ aWriteStream.WriteBin(entryComment.str().data(), entryComment.str().size());
+ aWriteStream.WriteLineEnd();
+ }
+ }
+ aWriteStream.IncIndent();
+ iArray[i]->Encode(aWriteStream);
+ aWriteStream.DecIndent();
+ if(bracketItem && aWriteStream.HumanReadable())
+ {
+ std::ostringstream tmp;
+ tmp << "End" << iArray[i]->ItemType();
+
+ prog << Log::Indent() << tmp.str() << Log::Endl();
+
+ aWriteStream.WriteIndent();
+ aWriteStream.WriteBin(tmp.str().data(), tmp.str().size());
+ aWriteStream.WriteLineEnd();
+ }
+ }
+
+ aWriteStream.DecIndent();
+
+ if(aWriteStream.HumanReadable())
+ {
+ // Human
+ aWriteStream.WriteIndent();
+ aWriteStream.WriteCStr("End");
+ aWriteStream.WriteBin(iName.data(), iName.size());
+ aWriteStream.WriteLineEnd();
+ }
+
+ prog << Log::Indent() << endName << Log::Endl();
+
+ return;
+}
+
+void EncDecContainer::Decode(RDecodeReadStream &aReadStream)
+{
+ // Calculate Start/End container names
+ std::string startName("Start");
+ startName.append(iName);
+ std::string endName("End");
+ endName.append(iName);
+
+ prog << Log::Indent() << "Reading " << startName << Log::Endl();
+
+ if(aReadStream.HumanReadable())
+ {
+ // Human
+
+ // Check/consume container StartX
+ aReadStream.CheckName(startName);
+
+ prog.IncIndent();
+
+ // Create items until we find the container EndX
+ TUint32 entryNum=1;
+ while(aReadStream.PeakToken() != endName)
+ {
+ // Progress message
+ prog << Log::Indent() << "# Entry " << std::dec << entryNum++ << std::hex << Log::Endl();
+
+ EncDecContainerItem *item = iFactory();
+ bool bracketedItem = (item->ItemType() != 0);
+ std::string itemName;
+ if(bracketedItem && aReadStream.HumanReadable())
+ {
+ // Bracketed item, so read ItemType tag and ItemName
+ std::string itemStart("Start");
+ itemStart.append(item->ItemType());
+ aReadStream.CheckName(itemStart);
+ prog << Log::Indent() << itemStart;
+
+ // Read item name
+ aReadStream.ReadNextToken();
+ itemName = aReadStream.Token();
+ }
+
+ prog.IncIndent();
+ item->Decode(aReadStream);
+ iArray.push_back(item);
+ prog.DecIndent();
+ if(bracketedItem && aReadStream.HumanReadable())
+ {
+ // Bracketed item, so read End ItemType tag
+ std::string itemEnd("End");
+ itemEnd.append(item->ItemType());
+ aReadStream.CheckName(itemEnd);
+ // and set item name
+ item->SetItemName(itemName);
+ }
+ }
+
+ // Check/consume container EndX
+ aReadStream.CheckName(endName);
+
+ prog.DecIndent();
+ }
+ else
+ {
+ // Binary
+ // Read number of entries
+ TUint32 arrayLength;
+ aReadStream.RawRead(&arrayLength, sizeof(arrayLength));
+
+ prog.IncIndent();
+ for(TUint32 i=0; i < arrayLength; ++i)
+ {
+ EncDecContainerItem *item = iFactory();
+ prog << Log::Indent() << "# Entry " << std::dec << i+1 << std::hex << Log::Endl();
+ prog.IncIndent();
+ item->Decode(aReadStream);
+ prog.DecIndent();
+ iArray.push_back(item);
+ }
+ prog.DecIndent();
+ }
+
+ prog << Log::Indent() << endName << Log::Endl();
+
+}
+
+
+
+
+REncodeWriteStream& operator<<(REncodeWriteStream& aStream, const EncDecContainer &aContainer)
+{
+ aContainer.Encode(aStream);
+ return aStream;
+}
+
+RDecodeReadStream& operator>>(RDecodeReadStream& aStream,EncDecContainer &aContainer)
+{
+ aContainer.Decode(aStream);
+ return aStream;
+}
+
+//
+// TUid
+//
+void EncodeHuman(REncodeWriteStream& aStream,const TUid &aUid)
+{
+ aStream.WriteHexNumber(aUid.iUid);
+}
+void DecodeHuman(RDecodeReadStream& aStream,TUid &aUid)
+{
+ aUid.iUid = aStream.ReadUnsignedNumber(sizeof(aUid.iUid));
+}
+
+//
+// TName
+//
+void EncodeHuman(REncodeWriteStream& aStream,const TName &aName)
+{
+ // Compress the internal UTF-16 to human readable UTF-8
+ ;
+ TInt outputBytes = 0;
+ TUint8 *outBuf = cstrFromUtf16(aName.Ptr(), aName.Length(), outputBytes);
+
+ aStream.WriteByte('"');
+ aStream.WriteQuotedUtf8(outBuf, outputBytes);
+ aStream.WriteByte('"');
+
+ delete [] outBuf;
+}
+void DecodeHuman(RDecodeReadStream& aStream,TName &aName)
+{
+ aStream.ReadNextToken();
+
+ // Expand UTF-8 into internal UTF-16LE representation
+ TInt outputWords = 0;
+ TText *outputBuf = utf16FromUtf8((const TUint8 *)aStream.Token().data(), aStream.Token().size(), outputWords);
+ memcpy((void *)aName.Ptr(), outputBuf, outputWords*2);
+ aName.SetLength(outputWords);
+ delete [] outputBuf;
+}
+
+void readContainer(const std::string &aFileName, bool aHuman, EncDecContainer &container)
+{
+ if(aHuman)
+ {
+ FileReadStream fileReadStream(aFileName, true);
+ std::string certBaseName(aFileName);
+ size_t dotLoc = certBaseName.rfind('.');
+ if(dotLoc != std::string::npos)
+ {
+ certBaseName.erase(dotLoc);
+ }
+ certBaseName += '_';
+ RDecodeReadStream inStream(certBaseName, fileReadStream); // human readable
+ inStream >> container;
+ inStream.Close();
+ }
+ else
+ {
+ RFs fs;
+ User::LeaveIfError(fs.Connect());
+ CleanupClosePushL(fs);
+
+ CPermanentFileStore* store = CPermanentFileStore::OpenLC(fs, _L16(aFileName.c_str()),EFileShareAny | EFileRead);
+ store->SetTypeL(KPermanentFileStoreLayoutUid);
+
+ RStoreReadStream rootStream;
+ rootStream.OpenLC(*store, store->Root());
+ TUint32 dataStreamId;
+ rootStream >> dataStreamId;
+ CleanupStack::PopAndDestroy(&rootStream);
+
+ RStoreReadStream dataStream;
+ dataStream.OpenLC(*store, dataStreamId);
+
+ RDecodeReadStream readStream(store, dataStream); // binary store
+
+ readStream >> container;
+
+ CleanupStack::PopAndDestroy(&dataStream);
+ CleanupStack::PopAndDestroy(store);
+ CleanupStack::PopAndDestroy(&fs);
+ }
+}
+
+
+void writeContainer(const char *aFileName, bool aHuman, bool aPemOut, bool aVerbose, const EncDecContainer &container)
+{
+ prog << Log::Indent() << "Writing output file '" << aFileName << "'" << Log::Endl();
+ prog.IncIndent();
+ if(aHuman)
+ {
+ FileWriteStream fileWriteStream(aFileName);
+ // Calculate based name by striping last .xx extension and appending an underscore.
+ std::string certBaseName(aFileName);
+ size_t dotLoc = certBaseName.rfind('.');
+ if(dotLoc != std::string::npos)
+ {
+ certBaseName.erase(dotLoc);
+ }
+ certBaseName += '_';
+
+ REncodeWriteStream outStream(certBaseName, fileWriteStream); // human readable
+ outStream.PemOut() = aPemOut;
+ outStream.Verbose() = aVerbose;
+ outStream << container;
+ outStream.Close();
+ }
+ else
+ {
+ RFs fs;
+ User::LeaveIfError(fs.Connect());
+ CleanupClosePushL(fs);
+
+ CFileStore* store = CPermanentFileStore::ReplaceLC(fs,_L16(aFileName),EFileShareAny | EFileRead | EFileWrite);
+ store->SetTypeL(KPermanentFileStoreLayoutUid);
+
+ RStoreWriteStream dataStream;
+ TStreamId dataStreamId = dataStream.CreateLC(*store);
+
+ REncodeWriteStream outStream(store, dataStream); // binary
+ outStream << container;
+ outStream.Close();
+
+ dataStream.CommitL();
+ dataStream.Close();
+
+ RStoreWriteStream rootStream;
+ TStreamId rootId = rootStream.CreateLC(*store);
+ rootStream << dataStreamId;
+ rootStream.CommitL();
+ rootStream.Close();
+
+
+ store->SetRootL(rootId);
+ store->CommitL();
+ CleanupStack::PopAndDestroy(&dataStream);
+ CleanupStack::PopAndDestroy(store);
+ CleanupStack::PopAndDestroy(&fs);
+ }
+ prog.DecIndent();
+}
+
+
+// End of file