vpnui/vpnpolins/src/cmdfileparser.cpp
changeset 0 33413c0669b9
equal deleted inserted replaced
-1:000000000000 0:33413c0669b9
       
     1 /*
       
     2 * Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:   Parses the XML command file (VPN command file)
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 #include <e32std.h>
       
    21 
       
    22 // XML parser includes
       
    23 #include "XwImpl.h"
       
    24 #include "XppImpl.h"
       
    25 
       
    26 #include "cmdfilexmltags.h"
       
    27 #include "cmdfileparser.h"
       
    28 #include "policyinstaller_constants.h"
       
    29 #include "log_r6.h"
       
    30 
       
    31 
       
    32 CCmdFileParser::CCmdFileParser()
       
    33     {
       
    34     }
       
    35 
       
    36 CCmdFileParser::~CCmdFileParser() 
       
    37     {
       
    38     LOG_("-> CCmdFileParser::~CCmdFileParser()");
       
    39     ReleaseResources();
       
    40     LOG_("<- CCmdFileParser::~CCmdFileParser()");
       
    41     }
       
    42 
       
    43 void CCmdFileParser::ParseL(const TDesC8& aInputData)
       
    44     {
       
    45     LOG_("-> CCmdFileParser::ParseL()");
       
    46     // Release any allocated resources, for a clean parse
       
    47     ReleaseResources();
       
    48 
       
    49     iParserStack = new (ELeave) CArrayFixFlat<HBufC8*>(3);
       
    50     iParsedValuesArray = new (ELeave) CArrayFixFlat<HBufC8*>(3);
       
    51 
       
    52     // Parse XML and extract the parameters
       
    53     ParseXmlL(aInputData);
       
    54 
       
    55     iParseReady = ETrue;
       
    56 
       
    57     LOG_("<- CCmdFileParser::ParseL()");
       
    58     }
       
    59 
       
    60 void CCmdFileParser::ReleaseResources() 
       
    61     {
       
    62     LOG_("-> CCmdFileParser::ReleaseResources()");
       
    63 
       
    64     iParseReady = EFalse;
       
    65 
       
    66     delete iFileContents;
       
    67     iFileContents = NULL;
       
    68 
       
    69     delete iPKCS12Pwd;
       
    70     iPKCS12Pwd = NULL;
       
    71 
       
    72     delete iFileName;
       
    73     iFileName = NULL;
       
    74 
       
    75     // Delete parser stack entries before deleting
       
    76     // the stack pointer
       
    77     if (iParserStack) 
       
    78         {
       
    79         LOG_(" Deleting items from parser stack");
       
    80 
       
    81         for (TInt i = iParserStack->Count() - 1; i >= 0; i--) 
       
    82             {
       
    83             LOG_1(" Deleting at %d", i);
       
    84             delete iParserStack->At(i);
       
    85             iParserStack->At(i) = NULL;
       
    86             }
       
    87 
       
    88         LOG_(" Reset parser");
       
    89         iParserStack->Reset();
       
    90         }
       
    91 
       
    92     delete iParserStack;
       
    93     iParserStack = NULL;
       
    94 
       
    95     // Delete parsed values entries before deleting
       
    96     // the array pointer
       
    97     if (iParsedValuesArray) 
       
    98         {
       
    99         LOG_(" Deleting items from parsed values");
       
   100         for (TInt i = iParsedValuesArray->Count() - 1; i >= 0; i--) 
       
   101             {
       
   102             LOG_1(" Deleting at %d", i);
       
   103             delete iParsedValuesArray->At(i);
       
   104             iParsedValuesArray->At(i) = NULL;
       
   105             }
       
   106 
       
   107         LOG_(" Reset parsed values");
       
   108         iParsedValuesArray->Reset();
       
   109         }
       
   110 
       
   111     delete iParsedValuesArray;
       
   112     iParsedValuesArray = NULL;
       
   113 
       
   114     LOG_("<- CCmdFileParser::ReleaseResources()");
       
   115     }
       
   116 
       
   117 void CCmdFileParser::PushNodeL(const TDesC8& aName) 
       
   118     {
       
   119     LOG_("-> CCmdFileParser::PushNodeL()");
       
   120 
       
   121     HBufC8* node = aName.AllocLC();
       
   122 
       
   123     LOG8_1("   PUSH Node: '%S'", node);
       
   124 
       
   125     iParserStack->AppendL(node);
       
   126     CleanupStack::Pop(node);
       
   127 
       
   128     LOG_("<- CCmdFileParser::PushNodeL()");
       
   129     }
       
   130 
       
   131 void CCmdFileParser::PopNode() 
       
   132     {
       
   133     LOG_("-> CCmdFileParser::PopNode()");
       
   134 
       
   135     // Just pop, unless we ought to stop
       
   136     TInt lastIdx = iParserStack->Count()-1;
       
   137     if (lastIdx >= 0) 
       
   138         {
       
   139         LOG8_1("   POP Node: '%S'", iParserStack->At(lastIdx));
       
   140         LOG_1("    Removing from parserstack index %d", lastIdx);
       
   141 
       
   142         delete iParserStack->At(lastIdx);
       
   143         iParserStack->Delete(lastIdx);
       
   144         }
       
   145 
       
   146     LOG_("<- CCmdFileParser::PopNode()");
       
   147     }
       
   148 
       
   149 TBool CCmdFileParser::IsTopmostNode(const TDesC8& aName) const
       
   150     {
       
   151     LOG_("-> CCmdFileParser::IsTopmostNode()");
       
   152     LOG8_1("  CHECKING: '%S'", &aName);
       
   153 
       
   154     TBool ret(EFalse);
       
   155     if (iParserStack) 
       
   156         {
       
   157         TInt lastIdx = iParserStack->Count()-1;
       
   158         TPtrC8 top = *(iParserStack->At(lastIdx));
       
   159 
       
   160         LOG8_1("  FOUND: '%S'", &top);
       
   161 
       
   162         if (aName.Compare(top) == 0)
       
   163             {
       
   164             ret = ETrue;
       
   165             }
       
   166         }
       
   167 
       
   168     LOG_1("<- CCmdFileParser::IsTopmostNode() val: %d", ret);
       
   169 
       
   170     return ret;
       
   171     }
       
   172 
       
   173 HBufC8* CCmdFileParser::ParseTreeUriL(const TDesC8& aText) const
       
   174     {
       
   175     LOG_("-> CCmdFileParser::ParseTreeUriL()");
       
   176     LOG8_1(" Input: '%S'", &aText);
       
   177 
       
   178     HBufC8* ret(NULL);
       
   179     TInt uriLen(aText.Length());
       
   180     TInt itemCount(0);
       
   181     if (iParserStack)
       
   182         {
       
   183         // First, with precise scientifical approach establish 
       
   184         // the amount of wide bytes required for storing the URI
       
   185         itemCount = iParserStack->Count();
       
   186 
       
   187         LOG_1(" Items in stack: %d", itemCount);
       
   188 
       
   189         for (TInt i = 0; i < itemCount; i++) 
       
   190             {
       
   191             uriLen += iParserStack->At(i)->Length();
       
   192             }
       
   193 
       
   194         // The number of "slash" ("/") characters required,
       
   195         // with utmost precision
       
   196         uriLen += itemCount;
       
   197         ret = HBufC8::NewL(uriLen);
       
   198 
       
   199         // And then store the URI to a new string.
       
   200         for (TInt i = 0; i < itemCount; i++) 
       
   201             {
       
   202             ret->Des().Append(*(iParserStack->At(i)));
       
   203             ret->Des().Append(KCmdUriSeparator);
       
   204             }
       
   205         ret->Des().Append(aText);
       
   206         }
       
   207 
       
   208     LOG_("<- CCmdFileParser::ParseTreeUriL()");
       
   209     return ret;
       
   210     }
       
   211 
       
   212 TBool CCmdFileParser::IsValidText(const TDesC8& aText) const
       
   213     {
       
   214     LOG_("-> CCmdFileParser::IsValidText()");
       
   215     TBool ret(ETrue);
       
   216 
       
   217     // We don't support "CR/LF" characters in the
       
   218     // beginning of valid value names
       
   219     TInt idx = aText.Find(KCmdCr);
       
   220     if (idx >= 0 && idx < 2) 
       
   221         {
       
   222         ret = EFalse;
       
   223         }
       
   224     else 
       
   225         {
       
   226         idx = aText.Find(KCmdLf);
       
   227         if (idx >= 0 && idx < 2) 
       
   228             {
       
   229             ret = EFalse;
       
   230             }
       
   231         }
       
   232 
       
   233     LOG_1("<- CCmdFileParser::IsValidText() ret: %d", ret);
       
   234     return ret;
       
   235     }
       
   236     
       
   237 void CCmdFileParser::ParseXmlL(const TDesC8& aInputData)
       
   238     {
       
   239     LOG_("-> CCmdFileParser::ParseXmlL()");
       
   240 
       
   241     LOG_(" Instantiate parser array");
       
   242 
       
   243     CDesC8ArrayFlat* parserValueArray = new (ELeave) CDesC8ArrayFlat(10);
       
   244     CleanupStack::PushL(parserValueArray);
       
   245 
       
   246     LOG_(" Instantiate XML parser");
       
   247     CXmlPullParser* parser = CXmlPullParser::NewLC(*parserValueArray);
       
   248 
       
   249     TPtrC8 name;
       
   250     TPtrC8 attribute;
       
   251 
       
   252     LOG_(" Set input");
       
   253     parser->SetInput(aInputData);
       
   254 
       
   255     LOG_(" Get length");
       
   256     TInt len = parser->Length();
       
   257     LOG_1(" XML length: %d bytes", len);
       
   258 
       
   259     // Check the first element
       
   260     LOG_(" Get the next (first) element");
       
   261     parser->NextL();
       
   262 
       
   263     if (parser->State() != CXmlPullParser::EStateStartTag) 
       
   264         {
       
   265         LOG_(" LEAVE: XML data is not in VPN's required format!");
       
   266         User::Leave(KErrCorrupt);
       
   267         }
       
   268 
       
   269     LOG_(" Starting the main parser loop");
       
   270     TPtrC8 text;
       
   271 
       
   272     // Main loop:
       
   273     // - While XML nodes still exist do:
       
   274     //   - If "opening" node (<start>), push to the stack
       
   275     //   - If "closing" node (</start>), pop from the stack
       
   276     //   - If a text node, make sure it's valid and then store
       
   277     //     the URI so the value can be fetched later on.
       
   278     while (parser->State() != CXmlPullParser::EStateEndDocument)
       
   279         {
       
   280         parser->Name(name);
       
   281 
       
   282         if (parser->State() == CXmlPullParser::EStateStartTag) 
       
   283             {
       
   284             LOG8_1(" START: '%S'", &name);
       
   285             PushNodeL(name);
       
   286             }
       
   287         else if (parser->State() == CXmlPullParser::EStateEndTag) 
       
   288             {
       
   289             LOG8_1(" END: '%S'", &name);
       
   290             if (IsTopmostNode(name)) 
       
   291                 {
       
   292                 PopNode();
       
   293                 }
       
   294             else 
       
   295                 {
       
   296                 // Item on top of the stack wasn't what was
       
   297                 // expected. Indicates corrupted XML.
       
   298                 LOG_(" ERROR: Node end tag mismatch with expected");
       
   299                 User::Leave(KErrCorrupt);
       
   300                 }
       
   301             }
       
   302         else if (parser->State() == CXmlPullParser::EStateText)
       
   303             {
       
   304             parser->TextL(text);
       
   305             if (IsValidText(text)) 
       
   306                 {
       
   307                 LOG8_1(" Text: '%S'", &text);
       
   308                 
       
   309                 HBufC8* uri = ParseTreeUriL(text);
       
   310 
       
   311                 LOG8_1(" URI: '%S'", uri);
       
   312 
       
   313                 CleanupStack::PushL(uri);
       
   314                 
       
   315                 iParsedValuesArray->AppendL(uri);
       
   316                 
       
   317                 CleanupStack::Pop(uri);
       
   318                 }
       
   319             }
       
   320 
       
   321         parser->NextL();
       
   322         }
       
   323 
       
   324     LOG_(" Popping");
       
   325 
       
   326     CleanupStack::PopAndDestroy(2, parserValueArray);
       
   327 
       
   328     LOG_("<- CCmdFileParser::ParseXmlL()");
       
   329     }
       
   330 
       
   331 
       
   332 HBufC* CCmdFileParser::GetParsedValueStrL(const TDesC8& aUri) 
       
   333     {
       
   334     LOG_("-> CCmdFileParser::GetParsedValueStrL()");
       
   335 
       
   336     HBufC* ret(NULL);
       
   337 
       
   338     // Get the "leaf" value (i.e. attribute's value)
       
   339     // and alloc a new string for it
       
   340     TPtrC8 ptr = FindUri(aUri);
       
   341     if (ptr.Length() > 0)
       
   342         {
       
   343         LOG_(" Ptr length > 0");
       
   344         LOG8_1(" Ptr: '%S'", &ptr);
       
   345         ret = HBufC::NewL(ptr.Length());
       
   346         ret->Des().Copy(ptr);
       
   347         }
       
   348     else 
       
   349         {
       
   350         LOG_(" Ptr length < 1");
       
   351         }
       
   352 
       
   353     LOG_("<- CCmdFileParser::GetParsedValueStrL()");
       
   354 
       
   355     return ret;
       
   356     }
       
   357 
       
   358 void CCmdFileParser::GetParsedValueIntL(const TDesC8& aUri, TInt& aVal) 
       
   359     {
       
   360     LOG_("-> CCmdFileParser::GetParsedValueIntL()");
       
   361 
       
   362     // Get the attribute's value as string...
       
   363     HBufC* str = GetParsedValueStrL(aUri);
       
   364 
       
   365     if (str)
       
   366         {
       
   367         LOG_(" Valid string");
       
   368         CleanupStack::PushL(str);
       
   369 
       
   370         // ... and convert it to an integer
       
   371         LOG_(" Converting string to int");
       
   372         TLex lexer(*str);
       
   373         TInt status = lexer.Val(aVal);
       
   374 
       
   375         if (status != KErrNone) 
       
   376             {
       
   377             LOG_1("<- CCmdFileParser::GetParsedValueIntL() LEAVE: %d", status);
       
   378             User::Leave(status);
       
   379             }
       
   380 
       
   381         CleanupStack::PopAndDestroy(str);
       
   382         }
       
   383     else 
       
   384         {
       
   385         aVal = KErrNotFound;
       
   386         }
       
   387     LOG_("<- CCmdFileParser::GetParsedValueIntL()");
       
   388     }
       
   389 
       
   390 void CCmdFileParser::GetParsedValueBoolL(const TDesC8& aUri, TBool& aVal)
       
   391     {
       
   392     LOG_("-> CCmdFileParser::GetParsedValueBoolL()");
       
   393 
       
   394     // Get the attribute's value as string...
       
   395     HBufC* str = GetParsedValueStrL(aUri);
       
   396 
       
   397     if (str) 
       
   398         {
       
   399         CleanupStack::PushL(str);
       
   400 
       
   401         // ... and see whether it matches "true"
       
   402         // Note that this comparison is extremely case-sensitive
       
   403         if (str->Compare(KTrue) == 0) 
       
   404             {
       
   405             aVal = ETrue;
       
   406             }
       
   407         else 
       
   408             {
       
   409             aVal = EFalse;
       
   410             }
       
   411 
       
   412         CleanupStack::PopAndDestroy(str);
       
   413         }
       
   414     else 
       
   415         {
       
   416         aVal = EFalse;
       
   417         }
       
   418 
       
   419     LOG_("<- CCmdFileParser::GetParsedValueBoolL()");
       
   420     }
       
   421 
       
   422 /**
       
   423  * Extracts the "leaf value" ie. attribute's value instance
       
   424  * from an uri.
       
   425  * E.g. returns "BEEFFACED" if the full URI was
       
   426  * root/node1/node2/attribute1/BEEFFACED
       
   427  * (Or in XML representation,
       
   428  * <node1>
       
   429  *   <node2>
       
   430  *     <attribute1>BEEFFACED</attribute1>
       
   431  *   </node2>
       
   432  * </node1>)
       
   433  *
       
   434  */
       
   435 TPtrC8 CCmdFileParser::FindUri(const TDesC8& aUri) const
       
   436     {
       
   437     LOG_("-> CCmdFileParser::FindUri()");
       
   438     LOG8_1(" Searching URI '%S'", &aUri);
       
   439 
       
   440     TPtrC8 ret(KNullDesC8);
       
   441 
       
   442     if (iParsedValuesArray) 
       
   443         {
       
   444         TInt count = iParsedValuesArray->Count();
       
   445         for (TInt i = 0; i < count; i++) 
       
   446             {
       
   447             TPtrC8 fulluri = *(iParsedValuesArray->At(i));
       
   448 
       
   449             // Check if we find the requested URI from the
       
   450             // very beginning of the parsed value's URI
       
   451             if (fulluri.Find(aUri) == 0) 
       
   452                 {
       
   453                 // Extract the "remaining" string -- the value (assuming correct syntax)
       
   454                 ret.Set(fulluri.Right(fulluri.Length() - aUri.Length()));
       
   455                 }
       
   456             }
       
   457         }
       
   458 
       
   459     LOG_("<- CCmdFileParser::FindUri()");
       
   460 
       
   461     return ret;
       
   462     }
       
   463 
       
   464