Merge docml changeset, iby creation mods and sqlite_secure (bug 2548).
/*
* 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:
* This file implements a package file parser for the Reference Installer.
*
*/
#include "sifrefpkgparser.h"
#include <f32file.h>
#include "usiflog.h"
#include <usif/usiferror.h>
using namespace Usif;
/**
A set of helper functions for the parser.
*/
namespace
{
_LIT8(KTxtCRLF, "\r\n");
_LIT8(KTxtLanguages, "Languages");
_LIT8(KTxtComponentName, "ComponentName");
_LIT8(KTxtComponentVendor, "ComponentVendor");
_LIT8(KTxtComponentVersion, "ComponentVersion");
_LIT8(KTxtFile, "File");
/** Maximum length of a value string in a package file */
const TInt KMaxValueLength = 0xFF;
void SplitLineL(const TPtrC8& aLine, TPtrC8& aName, TPtrC8& aValue)
{
const TInt colon = aLine.Locate(':');
if (colon == KErrNotFound)
{
DEBUG_PRINTF2(_L8("Missing colon in line: %S"), &aLine);
User::Leave(KErrCorrupt);
}
aName.Set(aLine.Left(colon));
aValue.Set(aLine.Mid(colon+1));
}
void SplitValuesL(const TPtrC8& aValues, RCHBufCArray& aValueArray)
{
TPtrC8 values(aValues);
while (values.Size() > 0)
{
TInt quot = values.Locate('"');
if (quot == KErrNotFound)
{
return;
}
values.Set(values.Mid(quot+1));
quot = values.Locate('"');
if (quot == KErrNotFound)
{
DEBUG_PRINTF2(_L8("Missing closing quotation mark in line: %S"), &aValues);
User::Leave(KErrCorrupt);
}
TPtrC8 token(values.Left(quot));
HBufC* value = HBufC::NewLC(KMaxValueLength);
TPtr valPtr(value->Des());
valPtr.Copy(token);
aValueArray.AppendL(value);
CleanupStack::Pop(value);
values.Set(values.Mid(quot+1));
}
}
void ParseComponentVersionL(const TPtrC8& aStringVersion, TVersion& aVersion)
{
// Check if already defined
if (aVersion.iMajor || aVersion.iMinor || aVersion.iBuild)
{
DEBUG_PRINTF(_L8("Multiple definition of Component Version"));
User::Leave(KErrCorrupt);
}
// Convert the major version number of Component Version
TLex8 lex(aStringVersion);
lex.SkipSpace();
TInt err = lex.Val(aVersion.iMajor);
if (err != KErrNone)
{
DEBUG_PRINTF(_L8("Failed parsing the major version number of Component Version"));
User::LeaveIfError(err);
}
lex.Inc();
// Convert the minor version number of Component Version
err = lex.Val(aVersion.iMinor);
if (err != KErrNone)
{
DEBUG_PRINTF(_L8("Failed parsing the minor version number of Component Version"));
User::LeaveIfError(err);
}
lex.Inc();
// Convert the build version number of Component Version
err = lex.Val(aVersion.iBuild);
if (err != KErrNone)
{
DEBUG_PRINTF(_L8("Failed parsing the build version number of Component Version"));
User::LeaveIfError(err);
}
}
TLanguage LanguageMapL(TDesC& aLanguage)
{
if (aLanguage == _L("EN"))
{
return ELangEnglish;
}
else if (aLanguage == _L("HU"))
{
return ELangHungarian;
}
else if (aLanguage == _L("PL"))
{
return ELangPolish;
}
DEBUG_PRINTF2(_L8("Language %S is not supported by this Reference Installer"), &aLanguage);
User::Leave(KErrSifUnsupportedLanguage);
return ELangNone;// Suppress warning
}
}
CSifRefPkgParser* CSifRefPkgParser::NewL(const TDesC& aFileName)
{
CSifRefPkgParser* self = new (ELeave) CSifRefPkgParser;
CleanupStack::PushL(self);
self->ParseL(aFileName);
CleanupStack::Pop(self);
return self;
}
CSifRefPkgParser::CSifRefPkgParser(): iVersion(0, 0, 0)
{
}
CSifRefPkgParser::~CSifRefPkgParser()
{
iLanguages.Close();
iComponentNames.Close();
iVendorNames.Close();
iFiles.Close();
}
const RLanguageArray& CSifRefPkgParser::Languages() const
{
return iLanguages;
}
const RCHBufCArray& CSifRefPkgParser::ComponentNames() const
{
return iComponentNames;
}
const RCHBufCArray& CSifRefPkgParser::VendorNames() const
{
return iVendorNames;
}
const TVersion& CSifRefPkgParser::Version() const
{
return iVersion;
}
const RCHBufCArray& CSifRefPkgParser::Files() const
{
return iFiles;
}
void CSifRefPkgParser::ParseL(const TDesC& aFileName)
{
RFs fs;
RFile file;
User::LeaveIfError(fs.Connect());
CleanupClosePushL(fs);
TInt err = file.Open(fs, aFileName, EFileShareReadersOnly);
if (err != KErrNone)
{
DEBUG_PRINTF3(_L8("Failed to open file: %S with error: %d"), &aFileName, err);
User::Leave(err);
}
CleanupClosePushL(file);
ParseL(file);
CleanupStack::PopAndDestroy(2, &fs);
}
void CSifRefPkgParser::ParseL(RFile& aFileHandle)
{
// Read the file into the buffer
TInt fileSize = 0;
User::LeaveIfError(aFileHandle.Size(fileSize));
HBufC8* buffer = HBufC8::NewLC(fileSize);
TPtr8 bufPtr = buffer->Des();
TInt err = aFileHandle.Read(bufPtr);
if (err != KErrNone)
{
DEBUG_PRINTF2(_L8("Failed to read reference package file with err %d"), err);
User::LeaveIfError(err);
}
// Iterate over the lines
TPtrC8 lines(*buffer);
const TInt crlfLen = TPtrC8(KTxtCRLF).Size();
while (lines.Size() > 0)
{
// Find next line
TPtrC8 line;
const TInt crlfPos = lines.Find(KTxtCRLF);
if (crlfPos != KErrNotFound)
{
line.Set(lines.Left(crlfPos));
lines.Set(lines.Mid(crlfPos+crlfLen));
}
else
{
if (lines.Size() > 0)
{
line.Set(lines);
lines.Set(TPtrC8());
}
}
// Split the line into a pair of the name of a tag and its value
TPtrC8 name, value;
SplitLineL(line, name, value);
// Hand over the pair to recognition
LineHandlerL(name, value);
}
CleanupStack::PopAndDestroy(buffer);
// Check whether the file we have just parsed wasn't corrupted
CheckInvariantL();
}
void CSifRefPkgParser::LineHandlerL(const TPtrC8& aName, const TPtrC8& aValue)
{
if (aName == KTxtLanguages)
{
if (iLanguages.Count() > 0)
{
DEBUG_PRINTF(_L8("Multiple definition of languages"));
User::Leave(KErrCorrupt);
}
RCHBufCArray languages;
CleanupClosePushL(languages);
SplitValuesL(aValue, languages);
const TInt count = languages.Count();
for (TInt i=0; i<count; ++i)
{
iLanguages.AppendL(LanguageMapL(*languages[i]));
}
CleanupStack::PopAndDestroy(&languages);
}
else if (aName == KTxtComponentName)
{
if (iComponentNames.Count() > 0)
{
DEBUG_PRINTF(_L8("Multiple definition of Component Name"));
User::Leave(KErrCorrupt);
}
SplitValuesL(aValue, iComponentNames);
}
else if (aName == KTxtComponentVendor)
{
if (iVendorNames.Count() > 0)
{
DEBUG_PRINTF(_L8("Multiple definition of Component Vendor"));
User::Leave(KErrCorrupt);
}
SplitValuesL(aValue, iVendorNames);
}
else if (aName == KTxtComponentVersion)
{
ParseComponentVersionL(aValue, iVersion);
}
else if (aName == KTxtFile)
{
HBufC* file = HBufC::NewLC(aValue.Size());
TPtr fileBuf = file->Des();
fileBuf.Copy(aValue);
fileBuf.Trim();
iFiles.AppendL(file);
CleanupStack::Pop(file);
}
else
{
DEBUG_PRINTF2(_L8("Failed due to unrecognized token: %S"), &aName);
User::Leave(KErrCorrupt);
}
}
TInt CSifRefPkgParser::GetLanguageIndex(TLanguage aLanguage) const
{
const TInt count = iLanguages.Count();
for (TInt i=0; i<count; ++i)
{
if (iLanguages[i] == aLanguage)
{
return i;
}
}
return KErrNotFound;
}
void CSifRefPkgParser::CheckInvariantL() const
{
if (iVersion.iMajor == 0 && iVersion.iMinor == 0 && iVersion.iBuild == 0)
{
DEBUG_PRINTF(_L8("Version not specified!"));
User::Leave(KErrCorrupt);
}
if (iLanguages.Count() == 0)
{
DEBUG_PRINTF(_L8("Language not specified!"));
User::Leave(KErrCorrupt);
}
if (iLanguages.Count() != iComponentNames.Count())
{
DEBUG_PRINTF(_L8("The number of languages and component names don't match!"));
User::Leave(KErrCorrupt);
}
if (iLanguages.Count() != iVendorNames.Count())
{
DEBUG_PRINTF(_L8("The number of languages and vendor names don't match!"));
User::Leave(KErrCorrupt);
}
}