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