--- /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 <e32std.h>
+
+// 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<HBufC8*>(3);
+ iParsedValuesArray = new (ELeave) CArrayFixFlat<HBufC8*>(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 (<start>), push to the stack
+ // - If "closing" node (</start>), 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,
+ * <node1>
+ * <node2>
+ * <attribute1>BEEFFACED</attribute1>
+ * </node2>
+ * </node1>)
+ *
+ */
+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;
+ }
+
+