javacommons/security/legacysupport/midp2securitypolicyv2/plugins/securitypolicyV2/src/XPFParser.cpp
branchRCL_3
changeset 19 04becd199f91
child 50 023eef975703
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javacommons/security/legacysupport/midp2securitypolicyv2/plugins/securitypolicyV2/src/XPFParser.cpp	Tue Apr 27 16:30:29 2010 +0300
@@ -0,0 +1,1583 @@
+/*
+* Copyright (c) 2003 - 2004 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:
+*
+*/
+
+
+
+
+/**
+ *
+ * @file    XPFParser.cpp
+ *
+ * @internal
+ *
+ */
+
+#include "j2me/midp2/security/MPermission.h"
+#include "ConnectionFilterType.h"
+#include "FunctionGroup.h"
+#include "FunctionGroupBinding.h"
+#include "FileSystemAccessPolicy.h"
+#include "DriveAccessPolicy.h"
+#include "PathAccessPolicy.h"
+#include "ProtectionDomain.h"
+#include "SecurityPolicy.h"
+#include "XPFParser.h"
+#include "BlanketPermissionPolicy.h"
+#include "BlanketPermissionPolicyElement.h"
+#include <j2me/jdebug.h>
+
+#define MAX_LENGTH_DG_POLICY 40
+
+namespace MIDP
+{
+
+CXPFParser* CXPFParser::NewLC(RFile& aFile, CSecurityPolicy& aPolicy)
+{
+    CXPFParser* xpfp = new(ELeave) CXPFParser(aFile, aPolicy);
+
+    CleanupStack::PushL(xpfp);
+    xpfp->ConstructL();
+    return xpfp;
+}
+
+CXPFParser::CXPFParser(RFile& aFile, CSecurityPolicy& aPolicy):
+        iFile(aFile),
+        iPolicy(aPolicy)
+{
+}
+
+CXPFParser::~CXPFParser()
+{
+    iFile.Close();
+    iFunctionGroups.Close();
+    delete iFileBuffer;
+    delete iBuffer;
+    delete iFunctionGroupName;
+}
+
+const TUint32 KFileBufferSize = 8192;
+
+const TUint32 KLineBufferSize = 256;
+
+void CXPFParser::ConstructL(void)
+{
+    iFileBuffer = HBufC8::NewL(KFileBufferSize);
+    iBuffer = HBufC::NewL(KLineBufferSize);
+}
+
+_LIT(KFormatVersion, "FormatVersion: 1.0");
+_LIT(KBlanket,  "Blanket");
+_LIT(KOneshot,  "Oneshot");
+_LIT(KSession,  "Session");
+_LIT(KNo,       "No");
+
+// Policy := Misc* FormatVersion Domains FunctionGroups Bindings Misc*
+
+void CXPFParser::ParseL(void)
+{
+    MiscL();
+    EnsureL(*iBuffer, KFormatVersion);
+    DomainsL();
+    FunctionGroupsL();
+    BindingsL();
+    while (ReadLineL() != -1)
+    {
+        if ((iLineLength > 0) && ((*iBuffer)[0] != '#'))
+        {
+            UnexpectedL(ECommentOrNewline, *iBuffer);
+        }
+    }
+}
+
+//
+// Domains := Misc* ^'Domains' NewLine (Misc* Domain NewLine+)+  ^'EndDomain' NewLine
+//
+
+_LIT(KDomains,    "Domains");
+_LIT(KEndDomains, "EndDomains");
+
+void CXPFParser::DomainsL(void)
+{
+    MiscL();
+    EnsureL(*iBuffer, KDomains);
+    for (;;)
+    {
+        MiscL();
+        DomainL();
+        if (*iBuffer == KEndDomains)
+        {
+            break;
+        }
+        iNextLine = ETrue;
+    }
+}
+
+//
+// Domain := WS* 'Domain:' WS+ DomainName (NewLine ConnectionFilters 'EndDomain')? NewLine
+//
+// ConnectionFilters := WS* 'ConnectionFilters' NewLine
+//                                (Misc* ConnectionFilter NewLine+)+
+//                      WS* 'EndConnectionFilters' NewLine
+//
+
+_LIT(KDomain,               "Domain:");
+_LIT(KEndDomain,            "EndDomain");
+_LIT(KUntrusted,            "[UNTRUSTED]");
+_LIT(KConnectionFilters,    "ConnectionFilters");
+_LIT(KEndConnectionFilters, "EndConnectionFilters");
+_LIT(KFileAccess,           "FileAccess");
+_LIT(KEndFileAccess,        "EndFileAccess");
+_LIT(KBlanketPermission,    "BlanketPermission");
+_LIT(KEndBlanketPermission, "EndBlanketPermission");
+
+void CXPFParser::DomainL(void)
+{
+    EnsureTokenL(KDomain);
+    switch (TokenL())
+    {
+    case EString:
+
+        if (iPolicy.FindProtectionDomain(iToken) != NULL)
+        {
+            DuplicateDeclarationL(EDomain, iToken);
+        }
+        iCurrentDomain = iPolicy.AddProtectionDomainL(iToken);
+        break;
+
+    case ESymbol:
+
+        if (iToken == KUntrusted)
+        {
+            if (iUntrustedDomain != NULL)
+            {
+                DuplicateDeclarationL(EUntrustedDomain, iToken);
+            }
+            iUntrustedDomain = iPolicy.AddUntrustedProtectionDomainL();
+            iCurrentDomain   = iUntrustedDomain;
+            break;
+        }
+
+        // Fall-through
+
+    default:
+
+        UnexpectedL(EDomainName, iToken);
+    }
+    NewLinePlusL();
+    TokenL();
+
+    TBool endDomainExpected = EFalse;
+
+    if (iToken == KConnectionFilters)
+    {
+        ConnectionFiltersL();
+        endDomainExpected = ETrue;
+        TokenL();
+    }
+
+    if (iToken == KFileAccess)
+    {
+        FileAccessL();
+        endDomainExpected = ETrue;
+        TokenL();
+    }
+
+    if (iToken == KBlanketPermission)
+    {
+        BlanketPermissionL();
+        endDomainExpected = ETrue;
+        TokenL();
+    }
+
+    if (endDomainExpected)
+    {
+        EnsureL(iToken, KEndDomain);
+        NewLinePlusL();
+    }
+    else
+    {
+        iLineOffset = 0;
+    }
+}
+
+void CXPFParser::ConnectionFiltersL(void)
+{
+    NewLineL();
+    for (;;)
+    {
+        MiscL();
+        ConnectionFilterL();
+        NewLinePlusL();
+        TokenL();
+        if (iToken == KEndConnectionFilters)
+        {
+            break;
+        }
+        iNextLine = ETrue;
+        iLineOffset = 0;
+    }
+    NewLinePlusL();
+}
+
+_LIT(KNegativePortFilter,       "NegativePortFilter:");
+_LIT(KEndNegativePortFilter,    "EndNegativePortFilter");
+_LIT(KPort,                     "Port:");
+
+//
+// ConnectionFilter   := NegativePortFilter
+//
+// NegativePortFilter := 'NegativePortFilter' Ports 'EndNegativePortFilter' NewLine
+//
+// Ports              := (Misc* 'Port:' port NewLine+)+
+//
+
+_LIT(KNegativePortFilterTypeName, "NegativePortFilter");
+
+void CXPFParser::ConnectionFilterL(void)
+{
+    EnsureTokenL(KNegativePortFilter);
+
+    HBufC* scheme = StringLC();
+
+    NewLineL();
+    for (;;)
+    {
+        MiscL();
+        EnsureTokenL(KPort);
+
+        HBufC* port = StringLC();
+
+        User::LeaveIfError(iArgs.Append(port));
+        CleanupStack::Pop(port);
+        NewLinePlusL();
+        TokenL();
+        if (iToken == KEndNegativePortFilter)
+        {
+            break;
+        }
+        iNextLine   = ETrue;
+        iLineOffset = 0;
+    }
+    NewLineL();
+    iCurrentDomain->AddConnectionFilterL(
+        KNegativePortFilterTypeName,
+        ENegativePortFilter,
+        *scheme,
+        iArgs);
+    iArgs.ResetAndDestroy();
+    CleanupStack::PopAndDestroy(scheme);
+}
+
+_LIT(KDriveList,        "DriveList:");
+_LIT(KEndDriveList,     "EndDriveList");
+
+void CXPFParser::FileAccessL(void)
+{
+    CFileSystemAccessPolicy* fsap = CFileSystemAccessPolicy::NewL();
+    iCurrentDomain->SetFileSystemAccessPolicy(fsap);
+
+    for (;;)
+    {
+        NewLinePlusL();
+        TokenL();
+        if (iToken == KDriveList)
+        {
+            DriveListL(*fsap);
+        }
+        else if (iToken == KEndFileAccess)
+        {
+            break;
+        }
+    }
+    NewLinePlusL();
+}
+
+
+_LIT(KMutualExclusionSet,       "MutualExclusionSet");
+_LIT(KEndMutualExclusionSet,    "EndMutualExclusionSet");
+_LIT(KRiskConfirmationSet,      "RiskConfirmationSet");
+_LIT(KEndRiskConfirmationSet,   "EndRiskConfirmationSet");
+
+void CXPFParser::BlanketPermissionL(void)
+{
+    DEBUG("CXPFParser::BlanketPermissionL() - Enter");
+    CBlanketPermissionPolicy* bpp = CBlanketPermissionPolicy::NewL();
+    CleanupStack::PushL(bpp);
+
+    for (;;)
+    {
+        NewLinePlusL();
+        TokenL();
+        if (iToken == KMutualExclusionSet || iToken == KRiskConfirmationSet)
+        {
+            ExclusionSetL(bpp);
+        }
+        else if (iToken == KEndBlanketPermission)
+        {
+            break;
+        }
+    }
+    NewLinePlusL();
+    CleanupStack::Pop(bpp);
+    iCurrentDomain->SetBlanketPermissionPolicy(bpp);
+    DEBUG("CXPFParser::BlanketPermissionL() - Exit");
+}
+
+
+void CXPFParser::ExclusionSetL(CBlanketPermissionPolicy* aBlanketPermissionPolicy)
+{
+    //Parse mutually excusive blanket permission sets and the
+    //downgrade policy for each such pair of sets
+    DEBUG("CXPFParser::ExclusionSetL() - Enter");
+    TBool endOfSetA= EFalse;
+
+    CBlanketPermissionPolicyElement* pe = CBlanketPermissionPolicyElement::NewL();
+    CleanupStack::PushL(pe);
+
+    //Sets clash type in policy element to either KMutualExclusionSet or KRiskConfirmationSet
+    pe->AppendDowngradeFunctionGroupListL(iToken.AllocL());
+
+    NewLinePlusL();
+    // Parse mutually excusive blanket permission sets
+    for (;;)
+    {
+        TToken type = TokenL();
+        if (type==EString)
+        {
+            if (!endOfSetA)
+            {//Add token to set A
+                pe->AppendFunctionGroupAL(iToken.AllocL());
+            }
+            else
+            {//Add token to set B
+                pe->AppendFunctionGroupBL(iToken.AllocL());
+            }
+
+        }
+        else if ((type==ESymbol) && (iToken.Length() == 1))   // ':'
+        {
+            //create setB now
+            endOfSetA=ETrue;
+        }
+        else if (iToken==KEndMutualExclusionSet || iToken==KEndRiskConfirmationSet)
+            break;
+
+        if (iToken.Length() == 0)
+        {
+            NewLinePlusL();
+        }
+
+    }
+
+    //Add the sets and permission downgrade policy to the
+    //CBlanketPermissionPolicy object for this domain
+    CleanupStack::Pop(pe);
+    aBlanketPermissionPolicy->Add(pe);
+    DEBUG("CXPFParser::ExclusionSetL() - Exit");
+}
+
+
+_LIT(KPathAccess,       "PathAccess:");
+_LIT(KEndPathAccess,    "EndPathAccess");
+_LIT(KPathMapping,      "PathMapping:");
+_LIT(KEndPathMapping,   "EndPathMapping");
+
+//
+// DriveList := 'DriveList:' ( PathAccess | PathMapping )+ 'EndDriveList'
+//
+
+void CXPFParser::DriveListL(CFileSystemAccessPolicy& aFileSystemAccessPolicy)
+{
+    CPathAccessPolicy* pap = CPathAccessPolicy::NewL();
+    CleanupReleasePushL(*pap);
+
+    // Parse drive letters
+    for (;;)
+    {
+        TokenL();
+
+        if (iToken.Length() == 1)
+        {
+            TDriveNumber drive = TDriveNumber(DriveTokenL());
+            CDriveAccessPolicy& dap =
+                aFileSystemAccessPolicy.GetDriveAccessPolicyL(drive);
+            dap.SetPathAccessPolicy(pap);
+        }
+        else
+        {
+            // Anything other that a single character moves on to the paths.
+            break;
+        }
+    }
+
+    if (iToken.Length() == 0)
+    {
+        NewLinePlusL();
+        TokenL();
+    }
+
+    for (;;)
+    {
+        if (iToken == KPathAccess)
+        {
+            PathAccessL(*pap);
+        }
+        else if (iToken == KPathMapping)
+        {
+            PathMappingL(*pap);
+        }
+        else if (iToken == KEndDriveList)
+        {
+            break;
+        }
+        NewLinePlusL();
+        TokenL();
+    }
+
+    CleanupStack::PopAndDestroy(pap);    // Only actually deleted if not used.
+}
+
+//
+// Drive := <Single character between A and Z inclusive>
+//
+
+_LIT(KDriveLetter, "drive letter");
+
+TInt CXPFParser::DriveTokenL()
+{
+    TUint letter = iToken[0];
+
+    if (letter >= 'A' && letter <= 'Z')
+    {
+        return (letter - 'A' + EDriveA);
+    }
+
+    if (letter >= 'a' && letter <= 'z')
+    {
+        return (letter - 'a' + EDriveA);
+    }
+
+    UnexpectedL(KDriveLetter, iToken);
+    return -1;  // Keep compiler happy.
+}
+
+
+_LIT(KRead,             "Read");
+_LIT(KWrite,            "Write");
+
+//
+// PathAccess := ‘PathAccess:’ ( ‘Read’ | ‘Write’ )* Path+ ‘EndPathAccess’
+//
+// Path := <String containing one or more path elements>
+//
+
+void CXPFParser::PathAccessL(CPathAccessPolicy& aPathAccessPolicy)
+{
+    TInt modeBits = 0;
+
+    for (;;)
+    {
+        TokenL();
+        if (iToken == KRead)
+        {
+            modeBits |= 1;
+        }
+        else if (iToken == KWrite)
+        {
+            modeBits |= 2;
+        }
+        else if (iToken.Length() == 0)
+        {
+            break;
+        }
+        else
+        {
+            UnexpectedL(EPathAccessMode, iToken);
+        }
+    }
+
+    MDriveAccessPolicy::TAccessMode mode;
+    switch (modeBits)
+    {
+    case 1:
+        mode = MDriveAccessPolicy::ERead;
+        break;
+    case 2:
+        mode = MDriveAccessPolicy::EWrite;
+        break;
+    case 3:
+        mode = MDriveAccessPolicy::EReadWrite;
+        break;
+    default:
+        mode = MDriveAccessPolicy::ENone;
+    }
+
+    // Now the paths, ending with 'EndPathAccess'
+    for (;;)
+    {
+        NewLinePlusL();
+        TokenL();
+
+        if (iToken == KEndPathAccess)
+        {
+            break;
+        }
+
+        aPathAccessPolicy.AddPathAccessL(iToken, mode);
+    }
+}
+
+
+//
+// PathMapping := 'PathMapping' ( From To )+ 'EndPathMapping'
+//
+// From := Dir
+//
+// Dir := <String containing a single directory name>
+//
+// To := Path | ( ‘MIDLET_HOME’ Path )
+//
+
+_LIT(KMidletHome,       "MIDLET_HOME");
+
+void CXPFParser::PathMappingL(CPathAccessPolicy& aPathAccessPolicy)
+{
+    for (;;)
+    {
+        NewLinePlusL();
+        TokenL();
+
+        if (iToken == KEndPathMapping)
+        {
+            break;
+        }
+
+        TBuf<KMaxFileName> from = iToken;
+        TBool inMidletHome = EFalse;
+
+        if (TokenL() == ESymbol && iToken == KMidletHome)
+        {
+            inMidletHome = ETrue;
+            TokenL();
+        }
+
+        aPathAccessPolicy.AddPathMappingL(from, iToken, inMidletHome);
+    }
+}
+
+
+
+//
+// FunctionGroups := Misc*
+//                    'FunctionGroups' NewLine
+//                         (Misc* FunctionGroup NewLine+)+
+//                    'EndFunctionGroups' NewLine
+//
+
+_LIT(KFunctionGroups,       "FunctionGroups");
+_LIT(KEndFunctionGroups,    "EndFunctionGroups");
+
+void CXPFParser::FunctionGroupsL(void)
+{
+    MiscL();
+    EnsureL(*iBuffer, KFunctionGroups);
+    for (;;)
+    {
+        MiscL();
+        FunctionGroupL();
+        NewLinePlusL();
+        if (*iBuffer == KEndFunctionGroups)
+        {
+            break;
+        }
+        iNextLine = ETrue;
+    }
+}
+
+//
+// FunctionGroup := 'FunctionGroup:' WS+ String NewLine
+//                       Permissions
+//                  'EndFunctionGroup' NewLine
+//
+// Permissions   := Misc*
+//                   WS* 'Permissions' NewLine
+//                        (PermissionName NewLine+)+
+//                   WS* 'EndPermisions' NewLine
+//
+
+_LIT(KFunctionGroup,    "FunctionGroup:");
+_LIT(KPermissions,      "Permissions");
+_LIT(KEndPermissions,   "EndPermissions");
+_LIT(KEndFunctionGroup, "EndFunctionGroup");
+
+
+void CXPFParser::FunctionGroupL(void)
+{
+    EnsureTokenL(KFunctionGroup);
+
+    HBufC* functionGroupName = StringLC();
+
+    if (FindFunctionGroup(*functionGroupName) != NULL)
+    {
+        DuplicateDeclarationL(EFunctionGroup, *functionGroupName);
+    }
+
+    CFunctionGroup* functionGroup = iPolicy.AddFunctionGroupL(*functionGroupName);
+
+    CleanupStack::PopAndDestroy(functionGroupName);
+    User::LeaveIfError(iFunctionGroups.Append(functionGroup));
+    MiscL();
+    EnsureTokenL(KPermissions);
+    NewLineL();
+    for (;;)
+    {
+        MiscL();
+        if (TokenL() != ESymbol)
+        {
+            UnexpectedL(EPermissionName, iToken);
+        }
+        iPolicy.AddPermissionL(*functionGroup, iToken);
+        NewLinePlusL();
+        TokenL();
+        if (iToken == KEndPermissions)
+        {
+            break;
+        }
+        iNextLine = ETrue;
+        iLineOffset = 0;
+    }
+    NewLinePlusL();
+    EnsureTokenL(KEndFunctionGroup);
+    NewLineL();
+
+}
+
+_LIT(KBindings,     "Bindings");
+_LIT(KEndBindings,  "EndBindings");
+
+//
+// Bindings := Misc* 'Bindings' NewLine (Misc* DomainBindings NewLine+)+ 'EndBindings' NewLine
+//
+
+void CXPFParser::BindingsL(void)
+{
+    MiscL();
+    EnsureL(*iBuffer, KBindings);
+    for (;;)
+    {
+        MiscL();
+        DomainBindingsL();
+        NewLinePlusL();
+        if (*iBuffer == KEndBindings)
+        {
+            break;
+        }
+        iNextLine = ETrue;
+    }
+}
+
+_LIT(KDomainBindings,           "DomainBindings:");
+_LIT(KEndDomainBindings,        "EndDomainBindings");
+
+//
+// DomainBindings := 'DomainBindings:' WS+ DomainName NewLine
+//                         FunctionGroupBindings
+//                   'EndDomainBindings' NewLine
+//
+
+void CXPFParser::DomainBindingsL(void)
+{
+    EnsureTokenL(KDomainBindings);
+    switch (TokenL())
+    {
+    case EString:
+
+        iCurrentDomain = iPolicy.FindProtectionDomain(iToken);
+        if (iCurrentDomain == NULL)
+        {
+            UndeclaredL(EDomain, iToken);
+        }
+        break;
+
+    case ESymbol:
+
+        if (iToken == KUntrusted)
+        {
+            iCurrentDomain = iUntrustedDomain;
+            if (iCurrentDomain == NULL)
+            {
+                UndeclaredL(EUntrustedDomain, iToken);
+            }
+            break;
+        }
+        // Fall-through
+
+    default:
+
+        UnexpectedL(EDomainName, iToken);
+    }
+    for (;;)
+    {
+        MiscL();
+
+        TBool wildcardBinding = FunctionGroupBindingL();
+
+        NewLinePlusL();
+        TokenL();
+        if (iToken == KEndDomainBindings)
+        {
+            break;
+        }
+        if (wildcardBinding)
+        {
+            UnexpectedL(KEndDomainBindings, iToken);
+        }
+        iNextLine   = ETrue;
+        iLineOffset = 0;
+    }
+    NewLineL();
+    iFunctionGroupBindings.Reset();
+}
+
+_LIT(KFunctionGroupBinding,     "FunctionGroupBinding:");
+_LIT(KWildcard,                 "[*]");
+_LIT(KPermission,               "Permission:");
+_LIT(KAllowed,                  "Allowed");
+_LIT(KUser,                     "User");
+_LIT(KDefaultMode,              "DefaultMode:");
+_LIT(KMaximumMode,              "MaximumMode:");
+_LIT(KRules,                    "Rules");
+_LIT(KEndRules,                 "EndRules");
+_LIT(KEndFunctionGroupBinding,  "EndFunctionGroupBinding");
+
+_LIT(KFunctionGroupNameOrWildcard, "FunctionGroupName or Wildcard");
+
+#if !defined (NO_SYNTAX_EXTENSIONS)
+_LIT(KInteractionModes,     "InteractionModes");
+_LIT(KEndInteractionModes,  "EndInteractionModes");
+#endif
+
+TBool CXPFParser::FunctionGroupBindingL(void)
+{
+    TBool wildcardBinding = EFalse;
+
+    EnsureTokenL(KFunctionGroupBinding);
+    switch (TokenL())
+    {
+    case EString:
+        delete iFunctionGroupName;
+        iFunctionGroupName = NULL;
+        iFunctionGroupName = iToken.AllocL();
+        if (FindFunctionGroup(*iFunctionGroupName) == NULL)
+        {
+            UndeclaredL(EFunctionGroup, *iFunctionGroupName);
+        }
+        if (FindFunctionGroupBinding(*iFunctionGroupName) != NULL)
+        {
+            DuplicateDeclarationL(EFunctionGroupBinding, *iFunctionGroupName);
+        }
+        break;
+
+    case ESymbol:
+
+        if (iToken == KWildcard)
+        {
+            wildcardBinding = ETrue;
+            break;
+        }
+
+        // Fall-through;
+
+    default:
+
+        UnexpectedL(KFunctionGroupNameOrWildcard, iToken);
+    }
+    NewLinePlusL();
+    EnsureTokenL(KPermission);
+    TokenL();
+
+    MPermission::TMode defaultMode = MPermission::EAllow;
+    MPermission::TMode maximumMode = MPermission::EAllow;
+
+    CFunctionGroupBinding* binding;
+
+    if (iToken == KAllowed)
+    {
+        NewLinePlusL();
+        if (!wildcardBinding)
+        {
+            binding = iCurrentDomain->AddFunctionGroupBindingL(
+                          *iFunctionGroupName,
+                          MPermission::EAllowed,
+                          defaultMode,
+                          maximumMode);
+            User::LeaveIfError(iFunctionGroupBindings.Append(binding));
+        }
+        else
+        {
+            AddDefaultBindingsL(MPermission::EAllowed, defaultMode, maximumMode);
+        }
+    }
+    else if (iToken == KUser)
+    {
+#if defined (NO_SYNTAX_EXTENSIONS)
+        NewLinePlusL();
+        EnsureTokenL(KDefaultMode);
+        defaultMode = InteractionModeL();
+        NewLinePlusL();
+        EnsureTokenL(KMaximumMode);
+        maximumMode = InteractionModeL();
+        NewLinePlusL();
+        if (!wildcardBinding)
+        {
+            binding = iCurrentDomain->AddFunctionGroupBindingL(
+                          *iFunctionGroupName,
+                          MPermission::EUser,
+                          defaultMode,
+                          maximumMode);
+            User::LeaveIfError(iFunctionGroupBindings.Append(binding));
+            TokenL();
+            if (iToken == KRules)
+            {
+                for (;;)
+                {
+                    MiscL();
+                    RuleL(*binding);
+                    NewLinePlusL();
+                    TokenL();
+                    if (iToken == KEndRules)
+                    {
+                        break;
+                    }
+                    iNextLine   = ETrue;
+                    iLineOffset = 0;
+                }
+                NewLinePlusL();
+            }
+            else
+            {
+                iLineOffset = 0;
+            }
+        }
+        else
+        {
+            AddDefaultBindingsL(MPermission::EUser, defaultMode, maximumMode);
+        }
+#else
+        NewLinePlusL();
+        EnsureTokenL(KDefaultMode);
+        defaultMode = InteractionModeL();
+        NewLinePlusL();
+        TokenL();
+        if (iToken == KMaximumMode)
+        {
+            maximumMode = InteractionModeL();
+            NewLinePlusL();
+            if (!wildcardBinding)
+            {
+                binding = iCurrentDomain->AddFunctionGroupBindingL(
+                              *iFunctionGroupName,
+                              MPermission::EUser,
+                              defaultMode,
+                              maximumMode);
+                User::LeaveIfError(iFunctionGroupBindings.Append(binding));
+                TokenL();
+                if (iToken == KRules)
+                {
+                    for (;;)
+                    {
+                        MiscL();
+                        RuleL(*binding);
+                        NewLinePlusL();
+                        TokenL();
+                        if (iToken == KEndRules)
+                        {
+                            break;
+                        }
+                        iNextLine   = ETrue;
+                        iLineOffset = 0;
+                    }
+                    NewLinePlusL();
+                }
+                else
+                {
+                    iLineOffset = 0;
+                }
+            }
+            else
+            {
+                AddDefaultBindingsL(MPermission::EUser, defaultMode, maximumMode);
+            }
+        }
+        else if (iToken == KInteractionModes)
+        {
+            TUint32 interactionModes = 0;
+            TUint32 interactionMode  = 0;
+
+            for (;;)
+            {
+                NewLinePlusL();
+                TokenL();
+                if (iToken == KEndInteractionModes)
+                {
+                    break;
+                }
+                else if (iToken == KNo)
+                {
+                    interactionMode = 1 << MPermission::EDenied;
+                }
+                else if (iToken == KOneshot)
+                {
+                    interactionMode = 1 << MPermission::EOneshot;
+                }
+                else if (iToken == KSession)
+                {
+                    interactionMode = 1 << MPermission::ESession;
+                }
+                else if (iToken == KBlanket)
+                {
+                    interactionMode = 1 << MPermission::EBlanket;
+                }
+                else
+                {
+                    UnexpectedL(EInteractionMode, iToken);
+                }
+                if (interactionModes & interactionMode)
+                {
+                    User::Leave(-1);
+                }
+                interactionModes |= interactionMode;
+            }
+            NewLinePlusL();
+            if (!wildcardBinding)
+            {
+                iCurrentDomain->AddFunctionGroupBindingL(
+                    *iFunctionGroupName,
+                    MPermission::EUser,
+                    defaultMode,
+                    interactionModes);
+            }
+            else
+            {
+                AddDefaultBindingsL(MPermission::EAllowed, defaultMode, interactionModes);
+            }
+        }
+        else
+        {
+            UnexpectedL(EPermissionType, iToken);
+        }
+#endif
+    }
+    else
+    {
+        UnexpectedL(EPermissionType, iToken);
+    }
+    EnsureTokenL(KEndFunctionGroupBinding);
+    NewLineL();
+    return wildcardBinding;
+}
+
+_LIT(KSimpleMapping,        "SimpleMapping:");
+_LIT(KFunctionGroupMode,    "FunctionGroupMode:");
+_LIT(KPermissionMode,       "PermissionMode:");
+_LIT(KEndSimpleMapping,     "EndSimpleMapping");
+
+void CXPFParser::RuleL(CFunctionGroupBinding& aBinding)
+{
+    EnsureTokenL(KSimpleMapping);
+    TokenL();
+
+    HBufC* permission = iToken.AllocLC();
+
+    NewLinePlusL();
+    for (;;)
+    {
+        EnsureTokenL(KFunctionGroupMode);
+        User::LeaveIfError(iMappings.Append(InteractionModeL()));
+        NewLinePlusL();
+        EnsureTokenL(KPermissionMode);
+        User::LeaveIfError(iMappings.Append(InteractionModeL()));
+        NewLinePlusL();
+        TokenL();
+        if (iToken == KEndSimpleMapping)
+        {
+            break;
+        }
+        //iNextLine = ETrue; "JCF commented out to allow grouped simplemappings to work"
+        iLineOffset = 0;
+    }
+    NewLineL();
+    aBinding.AddSimpleMappingL(*permission, iMappings);
+    CleanupStack::PopAndDestroy(permission);
+    iMappings.Reset();
+}
+
+_LIT(KDenied,   "Denied");
+
+MPermission::TMode CXPFParser::InteractionModeL(void)
+{
+    MPermission::TMode mode = MPermission::EInvalid;
+
+    if (TokenL() != ESymbol)
+    {
+        UnexpectedL(ESymbol, iToken);
+    }
+    if (iToken == KBlanket)
+    {
+        mode = MPermission::EBlanket;
+    }
+    else if (iToken == KOneshot)
+    {
+        mode = MPermission::EOneshot;
+    }
+    else if (iToken == KSession)
+    {
+        mode = MPermission::ESession;
+    }
+    else if (iToken == KDenied)
+    {
+        mode = MPermission::EDenied;
+    }
+    else
+    {
+        UnexpectedL(EInteractionMode, iToken);
+    }
+    return mode;
+}
+
+
+void CXPFParser::MiscL(void)
+{
+    for (;;)
+    {
+        if (ReadLineL() == -1)
+        {
+            //UnexpectedL(EEof, ????);
+        }
+        if ((iBuffer->Length() > 0) && ((*iBuffer)[0] != '#'))
+        {
+            break;
+        }
+    }
+}
+
+void CXPFParser::NewLineL(void)
+{
+    SkipWhitespace();
+    if (iLineOffset != iLineLength)
+    {
+        UnexpectedL(EEndOfLine, EAny);
+    }
+}
+
+void CXPFParser::NewLinePlusL(void)
+{
+    NewLineL();
+    for (;;)
+    {
+        if (ReadLineL() != 0)
+        {
+            break;
+        }
+    }
+}
+
+void CXPFParser::SkipWhitespace(void)
+{
+    while (iLineOffset < iLineLength)
+    {
+        TUint16 c = (*iBuffer)[iLineOffset];
+
+        if ((c != 0x09) && (c != 0x20))
+        {
+            break;
+        }
+        ++iLineOffset;
+    }
+}
+
+void CXPFParser::EnsureL(const TDesC& aActual, const TDesC& aExpected)
+{
+    if (aActual != aExpected)
+    {
+        UnexpectedL(aExpected, aActual);
+    }
+}
+
+void CXPFParser::EnsureTokenL(const TDesC& aExpectedToken)
+{
+    TokenL();
+    EnsureL(iToken, aExpectedToken);
+}
+
+CXPFParser::TToken CXPFParser::TokenL(TToken aExpected)
+{
+    TPtrC   buffer = *iBuffer;
+    TToken  token  = ENoToken;
+
+    while (iLineOffset < iLineLength)
+    {
+        TUint16 c = buffer[iLineOffset];
+
+        if (c == '#')
+        {
+            iLineOffset = iLineLength;
+            break;
+        }
+        else if ((c != 0x09) && (c != 0x20))
+        {
+            break;
+        }
+        ++iLineOffset;
+    }
+
+    TUint32 length = 0;
+    TUint32 start  = iLineOffset;
+
+    if (iLineOffset < iLineLength)
+    {
+        TBool stringp = buffer[iLineOffset] == '"';
+
+        if (stringp)
+        {
+            ++start;
+            ++iLineOffset;
+        }
+        while (iLineOffset < iLineLength)
+        {
+            TUint16 c = buffer[iLineOffset];
+
+            if (stringp)
+            {
+                if (buffer[iLineOffset] == '"')
+                {
+                    ++iLineOffset;
+                    break;
+                }
+            }
+            else if ((c == 0x09) || (c == 0x20))
+            {
+                break;
+            }
+            ++iLineOffset;
+            ++length;
+        }
+        if (stringp)
+        {
+            token = EString;
+            if (iLineOffset == iLineLength)
+            {
+                //UnexpectedL(EString, EEndOfLine);
+            }
+        }
+        else
+        {
+            token = ESymbol;
+        }
+    }
+    iToken.Set(iBuffer->Ptr() + start, length);
+    if ((aExpected != EAny) && (aExpected != token))
+    {
+        UnexpectedL(aExpected, iToken);
+    }
+    return token;
+}
+
+HBufC* CXPFParser::StringLC(void)
+{
+    TokenL(EString);
+    return iToken.AllocLC();
+}
+
+TInt CXPFParser::ReadLineL(void)
+{
+    if (iNextLine)
+    {
+        iNextLine = EFalse;
+    }
+    else if (ReadLineL(iBuffer) != -1)
+    {
+        iLineLength = iBuffer->Length();
+        ++iLineNumber;
+        iLineOffset = 0;
+    }
+    else
+    {
+        iLineLength = -1;
+    }
+    return iLineLength;
+}
+
+const TUint16 CR = 13;
+const TUint16 LF = 10;
+
+TInt CXPFParser::ReadLineL(HBufC*& aBuffer)
+{
+    TBool   eof    = EFalse;
+    TPtr    buffer = aBuffer->Des();
+    TInt    length = buffer.MaxLength();
+    TInt    offset = 0;
+
+    buffer.SetLength(0);
+    for (;;)
+    {
+        TUint16 c;
+        TInt    n;
+
+        n = ReadChar(c);
+        if (n < 0)
+        {
+            User::Leave(n);
+        }
+        else if (n == 0)
+        {
+            eof = ETrue;
+            break;
+        }
+        if (c == CR)
+        {
+            if (ReadChar(c) != KErrNone)
+            {
+            }
+            if (c != LF)
+            {
+            }
+            break;
+        }
+        else if (c == LF)
+        {
+            break;
+        }
+        if (offset == length)
+        {
+            length += length;
+            iBuffer = iBuffer->ReAllocL(length);
+        }
+        buffer.Append(c);
+        ++offset;
+    }
+    return buffer.Length() > 0 ? buffer.Length() : (eof ? -1 : 0);
+}
+
+TInt CXPFParser::ReadChar(TUint16& aChar)
+{
+    TInt   status;
+    TUint8 a;
+
+    status = Read(a);
+    if (status == KErrEof)
+    {
+        return 0;
+    }
+    else if (status != KErrNone)
+    {
+        return status;
+    }
+    if (a <= 0x7F)
+    {
+        aChar = a;
+    }
+    else
+    {
+        TUint8 b;
+
+        status = Read(b);
+        if (status != KErrNone)
+        {
+            return status;
+        }
+        if ((b & 0xC0) != 0x80)
+        {
+            return KErrCorrupt;
+        }
+        switch (a & 0xF0)
+        {
+        case 0xC0:
+        case 0xD0:
+
+            aChar = (TUint16)((((TUint16)a & 0x1F) << 6) + (((TUint16)b) & 0x3F));
+            break;
+
+        case 0xE0:
+        {
+            TUint8  c;
+
+            status = Read(c);
+            if (status != KErrNone)
+            {
+                return status;
+            }
+            if ((c & 0xC0) != 0x80)
+            {
+                return KErrCorrupt;
+            }
+            aChar = (char)(((a & 0x1F) << 6) + ((b & 0x3F) << 6) + (b & 0x3F));
+        }
+        break;
+
+        default:
+            // No support for 4-byte encoding
+            return KErrCorrupt;
+        }
+    }
+    return 1;
+}
+
+TInt CXPFParser::Read(TUint8& aByte)
+{
+    if (iFileBufferOffset == iFileBufferLength)
+    {
+        TPtr8 ptr    = iFileBuffer->Des();
+        TInt  status = iFile.Read(ptr);
+
+        if (status != KErrNone)
+        {
+            return status;
+        }
+        iFileBufferOffset = 0;
+        iFileBufferLength = iFileBuffer->Length();
+        if (iFileBufferLength == 0)
+        {
+            return KErrEof;
+        }
+    }
+    aByte = (*iFileBuffer)[iFileBufferOffset++];
+    return KErrNone;
+}
+
+CFunctionGroup* CXPFParser::FindFunctionGroup(const TDesC& aName)
+{
+    TInt functionGroupCount = iFunctionGroups.Count();
+
+    for (TInt i = 0; i < functionGroupCount; i++)
+    {
+        if (iFunctionGroups[i]->Name() == aName)
+        {
+            return iFunctionGroups[i];
+        }
+    }
+    return NULL;
+}
+
+CFunctionGroupBinding* CXPFParser::FindFunctionGroupBinding(const TDesC& aName)
+{
+    TInt bindingCount = iFunctionGroupBindings.Count();
+
+    for (TInt i = 0; i < bindingCount; i++)
+    {
+        if (iFunctionGroupBindings[i]->FunctionGroup().Name() == aName)
+        {
+            return iFunctionGroupBindings[i];
+        }
+    }
+    return NULL;
+}
+
+void CXPFParser::AddDefaultBindingsL(
+    MPermission::TType aType,
+    MPermission::TMode aDefaultMode,
+    MPermission::TMode aMaximumMode)
+{
+    TInt fgCount = iFunctionGroups.Count();
+
+    for (TInt i = 0; i < fgCount; i++)
+    {
+        CFunctionGroup* fg = iFunctionGroups[i];
+
+        if (FindFunctionGroupBinding(fg->Name()) == NULL)
+        {
+            iCurrentDomain->AddFunctionGroupBindingL(
+                fg->Name(),
+                aType,
+                aDefaultMode,
+                aMaximumMode);
+        }
+    }
+}
+
+void CXPFParser::AddDefaultBindingsL(
+    MPermission::TType aType,
+    MPermission::TMode aDefaultMode,
+    TUint32            aInteractionModeMap)
+{
+    TInt fgCount = iFunctionGroups.Count();
+
+    for (TInt i = 0; i < fgCount; i++)
+    {
+        CFunctionGroup* fg = iFunctionGroups[i];
+
+        if (FindFunctionGroupBinding(fg->Name()) == NULL)
+        {
+            iCurrentDomain->AddFunctionGroupBindingL(
+                fg->Name(),
+                aType,
+                aDefaultMode,
+                aInteractionModeMap);
+        }
+    }
+}
+
+#if !defined(_DEBUG)
+
+void CXPFParser::DuplicateDeclarationL(TDeclarationType, const TDesC&)
+{
+    User::Leave(KErrCorrupt);
+}
+
+void CXPFParser::UndeclaredL(TDeclarationType, const TDesC&)
+{
+    User::Leave(KErrCorrupt);
+}
+
+void CXPFParser::UnexpectedL(const TDesC&, const TDesC&)
+{
+    User::Leave(KErrCorrupt);
+}
+
+void CXPFParser::UnexpectedL(TToken /*aExpected*/, const TDesC& /*aActual*/)
+{
+    User::Leave(KErrCorrupt);
+}
+
+void CXPFParser::UnexpectedL(TToken /*aExpected*/, TToken /*aActual*/)
+{
+    User::Leave(KErrCorrupt);
+}
+
+#else
+
+}   // End namespace MIDP around include
+#include "j2me/jdebug.h"
+namespace MIDP      // Reopen it again
+{
+
+_LIT(KDuplicateDeclarationTemplate, "Error at line %d: The %S %S has already been declared");
+
+void CXPFParser::DuplicateDeclarationL(TDeclarationType aType, const TDesC& aName)
+{
+    ErrorL(KDuplicateDeclarationTemplate, ToString(aType), aName);
+}
+
+_LIT(KUndeclaredTemplate, "Error at line %d: The %S %S has not been declared");
+
+void CXPFParser::UndeclaredL(TDeclarationType aType, const TDesC& aName)
+{
+    ErrorL(KUndeclaredTemplate, ToString(aType), aName);
+}
+
+_LIT(KUnexpectedTemplate, "Error at line %d: Expected %S but got %S");
+
+void CXPFParser::UnexpectedL(const TDesC& aExpected, const TDesC& aActual)
+{
+    ErrorL(KUnexpectedTemplate, aExpected, aActual);
+}
+
+void CXPFParser::UnexpectedL(TToken aExpectedToken, const TDesC& aActual)
+{
+    UnexpectedL(ToString(aExpectedToken), aActual);
+}
+
+void CXPFParser::UnexpectedL(TToken aExpectedToken, TToken aActualToken)
+{
+    UnexpectedL(ToString(aExpectedToken), ToString(aActualToken));
+}
+
+void CXPFParser::ErrorL(const TDesC& aTemplate, const TDesC& aArg1, const TDesC& aArg2)
+{
+    HBufC* buffer    = HBufC::NewLC(aTemplate.Length() + aArg1.Length() + aArg2.Length());
+    TPtr   bufferPtr = buffer->Des();
+
+    bufferPtr.Format(aTemplate, iLineNumber, &aArg1, &aArg2);
+    DEBUG_STR("%S", *buffer);
+    delete buffer;
+    User::Leave(KErrCorrupt);
+}
+
+_LIT(KSayWhat, "????");
+
+_LIT(KStringToken,              "a string");
+_LIT(KSymbolToken,              "a symbol");
+_LIT(KCommentToken,             "a comment");
+_LIT(KCommentOrNewlineToken,    "a comment or newline");
+
+const TDesC& CXPFParser::ToString(TToken aToken)
+{
+    switch (aToken)
+    {
+    case EString:
+
+        return KStringToken;
+
+    case ESymbol:
+
+        return KSymbolToken;
+
+    case EComment:
+
+        return KCommentToken;
+
+    case ECommentOrNewline:
+
+        return KCommentOrNewlineToken;
+
+    default:
+
+        return KSayWhat;
+    }
+}
+
+_LIT(KDomainDecl,               "domain");
+_LIT(KUntrustedDomainDecl,      "untrusted domain");
+_LIT(KFunctionGroupDecl,        "function group");
+_LIT(KPermissionDecl,           "permission");
+_LIT(KFunctionGroupBindingDecl, "function group binding");
+
+
+const TDesC& CXPFParser::ToString(TDeclarationType aDeclarationType)
+{
+    switch (aDeclarationType)
+    {
+    case EDomain:
+
+        return KDomainDecl;
+
+    case EUntrustedDomain:
+
+        return KUntrustedDomainDecl;
+
+    case EFunctionGroup:
+
+        return KFunctionGroupDecl;
+
+    case EPermission:
+
+        return KPermissionDecl;
+
+    case EFunctionGroupBinding:
+
+        return KFunctionGroupBinding;
+
+    default:
+
+        return KSayWhat;
+    }
+}
+
+
+#endif /* !defined(_DEBUG) */
+
+} // end of namespace MIDP