diff -r 000000000000 -r 33413c0669b9 vpnui/vpnpolins/src/cmdfileparser.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vpnui/vpnpolins/src/cmdfileparser.cpp Thu Dec 17 09:14:51 2009 +0200 @@ -0,0 +1,464 @@ +/* +* Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "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: Parses the XML command file (VPN command file) +* +*/ + + + +#include + +// XML parser includes +#include "XwImpl.h" +#include "XppImpl.h" + +#include "cmdfilexmltags.h" +#include "cmdfileparser.h" +#include "policyinstaller_constants.h" +#include "log_r6.h" + + +CCmdFileParser::CCmdFileParser() + { + } + +CCmdFileParser::~CCmdFileParser() + { + LOG_("-> CCmdFileParser::~CCmdFileParser()"); + ReleaseResources(); + LOG_("<- CCmdFileParser::~CCmdFileParser()"); + } + +void CCmdFileParser::ParseL(const TDesC8& aInputData) + { + LOG_("-> CCmdFileParser::ParseL()"); + // Release any allocated resources, for a clean parse + ReleaseResources(); + + iParserStack = new (ELeave) CArrayFixFlat(3); + iParsedValuesArray = new (ELeave) CArrayFixFlat(3); + + // Parse XML and extract the parameters + ParseXmlL(aInputData); + + iParseReady = ETrue; + + LOG_("<- CCmdFileParser::ParseL()"); + } + +void CCmdFileParser::ReleaseResources() + { + LOG_("-> CCmdFileParser::ReleaseResources()"); + + iParseReady = EFalse; + + delete iFileContents; + iFileContents = NULL; + + delete iPKCS12Pwd; + iPKCS12Pwd = NULL; + + delete iFileName; + iFileName = NULL; + + // Delete parser stack entries before deleting + // the stack pointer + if (iParserStack) + { + LOG_(" Deleting items from parser stack"); + + for (TInt i = iParserStack->Count() - 1; i >= 0; i--) + { + LOG_1(" Deleting at %d", i); + delete iParserStack->At(i); + iParserStack->At(i) = NULL; + } + + LOG_(" Reset parser"); + iParserStack->Reset(); + } + + delete iParserStack; + iParserStack = NULL; + + // Delete parsed values entries before deleting + // the array pointer + if (iParsedValuesArray) + { + LOG_(" Deleting items from parsed values"); + for (TInt i = iParsedValuesArray->Count() - 1; i >= 0; i--) + { + LOG_1(" Deleting at %d", i); + delete iParsedValuesArray->At(i); + iParsedValuesArray->At(i) = NULL; + } + + LOG_(" Reset parsed values"); + iParsedValuesArray->Reset(); + } + + delete iParsedValuesArray; + iParsedValuesArray = NULL; + + LOG_("<- CCmdFileParser::ReleaseResources()"); + } + +void CCmdFileParser::PushNodeL(const TDesC8& aName) + { + LOG_("-> CCmdFileParser::PushNodeL()"); + + HBufC8* node = aName.AllocLC(); + + LOG8_1(" PUSH Node: '%S'", node); + + iParserStack->AppendL(node); + CleanupStack::Pop(node); + + LOG_("<- CCmdFileParser::PushNodeL()"); + } + +void CCmdFileParser::PopNode() + { + LOG_("-> CCmdFileParser::PopNode()"); + + // Just pop, unless we ought to stop + TInt lastIdx = iParserStack->Count()-1; + if (lastIdx >= 0) + { + LOG8_1(" POP Node: '%S'", iParserStack->At(lastIdx)); + LOG_1(" Removing from parserstack index %d", lastIdx); + + delete iParserStack->At(lastIdx); + iParserStack->Delete(lastIdx); + } + + LOG_("<- CCmdFileParser::PopNode()"); + } + +TBool CCmdFileParser::IsTopmostNode(const TDesC8& aName) const + { + LOG_("-> CCmdFileParser::IsTopmostNode()"); + LOG8_1(" CHECKING: '%S'", &aName); + + TBool ret(EFalse); + if (iParserStack) + { + TInt lastIdx = iParserStack->Count()-1; + TPtrC8 top = *(iParserStack->At(lastIdx)); + + LOG8_1(" FOUND: '%S'", &top); + + if (aName.Compare(top) == 0) + { + ret = ETrue; + } + } + + LOG_1("<- CCmdFileParser::IsTopmostNode() val: %d", ret); + + return ret; + } + +HBufC8* CCmdFileParser::ParseTreeUriL(const TDesC8& aText) const + { + LOG_("-> CCmdFileParser::ParseTreeUriL()"); + LOG8_1(" Input: '%S'", &aText); + + HBufC8* ret(NULL); + TInt uriLen(aText.Length()); + TInt itemCount(0); + if (iParserStack) + { + // First, with precise scientifical approach establish + // the amount of wide bytes required for storing the URI + itemCount = iParserStack->Count(); + + LOG_1(" Items in stack: %d", itemCount); + + for (TInt i = 0; i < itemCount; i++) + { + uriLen += iParserStack->At(i)->Length(); + } + + // The number of "slash" ("/") characters required, + // with utmost precision + uriLen += itemCount; + ret = HBufC8::NewL(uriLen); + + // And then store the URI to a new string. + for (TInt i = 0; i < itemCount; i++) + { + ret->Des().Append(*(iParserStack->At(i))); + ret->Des().Append(KCmdUriSeparator); + } + ret->Des().Append(aText); + } + + LOG_("<- CCmdFileParser::ParseTreeUriL()"); + return ret; + } + +TBool CCmdFileParser::IsValidText(const TDesC8& aText) const + { + LOG_("-> CCmdFileParser::IsValidText()"); + TBool ret(ETrue); + + // We don't support "CR/LF" characters in the + // beginning of valid value names + TInt idx = aText.Find(KCmdCr); + if (idx >= 0 && idx < 2) + { + ret = EFalse; + } + else + { + idx = aText.Find(KCmdLf); + if (idx >= 0 && idx < 2) + { + ret = EFalse; + } + } + + LOG_1("<- CCmdFileParser::IsValidText() ret: %d", ret); + return ret; + } + +void CCmdFileParser::ParseXmlL(const TDesC8& aInputData) + { + LOG_("-> CCmdFileParser::ParseXmlL()"); + + LOG_(" Instantiate parser array"); + + CDesC8ArrayFlat* parserValueArray = new (ELeave) CDesC8ArrayFlat(10); + CleanupStack::PushL(parserValueArray); + + LOG_(" Instantiate XML parser"); + CXmlPullParser* parser = CXmlPullParser::NewLC(*parserValueArray); + + TPtrC8 name; + TPtrC8 attribute; + + LOG_(" Set input"); + parser->SetInput(aInputData); + + LOG_(" Get length"); + TInt len = parser->Length(); + LOG_1(" XML length: %d bytes", len); + + // Check the first element + LOG_(" Get the next (first) element"); + parser->NextL(); + + if (parser->State() != CXmlPullParser::EStateStartTag) + { + LOG_(" LEAVE: XML data is not in VPN's required format!"); + User::Leave(KErrCorrupt); + } + + LOG_(" Starting the main parser loop"); + TPtrC8 text; + + // Main loop: + // - While XML nodes still exist do: + // - If "opening" node (), push to the stack + // - If "closing" node (), pop from the stack + // - If a text node, make sure it's valid and then store + // the URI so the value can be fetched later on. + while (parser->State() != CXmlPullParser::EStateEndDocument) + { + parser->Name(name); + + if (parser->State() == CXmlPullParser::EStateStartTag) + { + LOG8_1(" START: '%S'", &name); + PushNodeL(name); + } + else if (parser->State() == CXmlPullParser::EStateEndTag) + { + LOG8_1(" END: '%S'", &name); + if (IsTopmostNode(name)) + { + PopNode(); + } + else + { + // Item on top of the stack wasn't what was + // expected. Indicates corrupted XML. + LOG_(" ERROR: Node end tag mismatch with expected"); + User::Leave(KErrCorrupt); + } + } + else if (parser->State() == CXmlPullParser::EStateText) + { + parser->TextL(text); + if (IsValidText(text)) + { + LOG8_1(" Text: '%S'", &text); + + HBufC8* uri = ParseTreeUriL(text); + + LOG8_1(" URI: '%S'", uri); + + CleanupStack::PushL(uri); + + iParsedValuesArray->AppendL(uri); + + CleanupStack::Pop(uri); + } + } + + parser->NextL(); + } + + LOG_(" Popping"); + + CleanupStack::PopAndDestroy(2, parserValueArray); + + LOG_("<- CCmdFileParser::ParseXmlL()"); + } + + +HBufC* CCmdFileParser::GetParsedValueStrL(const TDesC8& aUri) + { + LOG_("-> CCmdFileParser::GetParsedValueStrL()"); + + HBufC* ret(NULL); + + // Get the "leaf" value (i.e. attribute's value) + // and alloc a new string for it + TPtrC8 ptr = FindUri(aUri); + if (ptr.Length() > 0) + { + LOG_(" Ptr length > 0"); + LOG8_1(" Ptr: '%S'", &ptr); + ret = HBufC::NewL(ptr.Length()); + ret->Des().Copy(ptr); + } + else + { + LOG_(" Ptr length < 1"); + } + + LOG_("<- CCmdFileParser::GetParsedValueStrL()"); + + return ret; + } + +void CCmdFileParser::GetParsedValueIntL(const TDesC8& aUri, TInt& aVal) + { + LOG_("-> CCmdFileParser::GetParsedValueIntL()"); + + // Get the attribute's value as string... + HBufC* str = GetParsedValueStrL(aUri); + + if (str) + { + LOG_(" Valid string"); + CleanupStack::PushL(str); + + // ... and convert it to an integer + LOG_(" Converting string to int"); + TLex lexer(*str); + TInt status = lexer.Val(aVal); + + if (status != KErrNone) + { + LOG_1("<- CCmdFileParser::GetParsedValueIntL() LEAVE: %d", status); + User::Leave(status); + } + + CleanupStack::PopAndDestroy(str); + } + else + { + aVal = KErrNotFound; + } + LOG_("<- CCmdFileParser::GetParsedValueIntL()"); + } + +void CCmdFileParser::GetParsedValueBoolL(const TDesC8& aUri, TBool& aVal) + { + LOG_("-> CCmdFileParser::GetParsedValueBoolL()"); + + // Get the attribute's value as string... + HBufC* str = GetParsedValueStrL(aUri); + + if (str) + { + CleanupStack::PushL(str); + + // ... and see whether it matches "true" + // Note that this comparison is extremely case-sensitive + if (str->Compare(KTrue) == 0) + { + aVal = ETrue; + } + else + { + aVal = EFalse; + } + + CleanupStack::PopAndDestroy(str); + } + else + { + aVal = EFalse; + } + + LOG_("<- CCmdFileParser::GetParsedValueBoolL()"); + } + +/** + * Extracts the "leaf value" ie. attribute's value instance + * from an uri. + * E.g. returns "BEEFFACED" if the full URI was + * root/node1/node2/attribute1/BEEFFACED + * (Or in XML representation, + * + * + * BEEFFACED + * + * ) + * + */ +TPtrC8 CCmdFileParser::FindUri(const TDesC8& aUri) const + { + LOG_("-> CCmdFileParser::FindUri()"); + LOG8_1(" Searching URI '%S'", &aUri); + + TPtrC8 ret(KNullDesC8); + + if (iParsedValuesArray) + { + TInt count = iParsedValuesArray->Count(); + for (TInt i = 0; i < count; i++) + { + TPtrC8 fulluri = *(iParsedValuesArray->At(i)); + + // Check if we find the requested URI from the + // very beginning of the parsed value's URI + if (fulluri.Find(aUri) == 0) + { + // Extract the "remaining" string -- the value (assuming correct syntax) + ret.Set(fulluri.Right(fulluri.Length() - aUri.Length())); + } + } + } + + LOG_("<- CCmdFileParser::FindUri()"); + + return ret; + } + +