messagingfw/biomsgfw/wappsrc/wapp.cpp
changeset 0 8e480a14352b
child 41 0abbef78e78b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/messagingfw/biomsgfw/wappsrc/wapp.cpp	Mon Jan 18 20:36:02 2010 +0200
@@ -0,0 +1,3830 @@
+// Copyright (c) 2000-2009 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:
+//
+
+#include <e32std.h>
+#include <msventry.h>
+#include <bsp.h>
+#include <wapp.h>
+#include <wappdef.h>
+#include "wapperr.h"
+#include <wappstr.rsg>
+
+#include "CWappBookmark.h"
+#include "IspTableData.h"
+#include "IpBearerData.h"
+#include "SmsBearerData.h"
+#include "GprsBearerData.h"
+
+#include <mmssettingsproxybase.h>
+
+#include <msvstd.h>
+#include <msventry.h>
+#include <msvids.h>
+#include <msvuids.h>
+#include <mtclreg.h>
+
+#include <ipaddr.h>
+#include <barsc.h>
+#include <barsread.h>
+#include <bautils.h>
+
+#include <cbioasyncwaiter.h>
+#include <cmsvattachment.h>
+#include <mmsvattachmentmanager.h>
+#include <mmsvattachmentmanagersync.h>
+
+#ifdef SYMBIAN_BOOKMARK_DATABASE
+#include <bookmarkdatabase.h>
+#include <bookmark.h>
+#endif // SYMBIAN_BOOKMARK_DATABASE
+
+#ifdef _DEBUG
+const TUid KUidSmartMessageMtm = {0x10001262};
+const TInt32 KUidBIOWAPAccessPointMsg = 0x10005532;
+#endif
+
+const TInt KMaxNameBufferLength = 35;
+
+_LIT8(KCRLinefeed,			"\r\n");
+_LIT8(KEBookmarkItemBegin,	"BEGIN:eBOOKMARK\r\n");		//  Precedes a Bookmark in the Bookmark file
+_LIT8(KEBookmarkItemName,	"NAME:");	// Precedes a Bookmark Name
+_LIT8(KEBookmarkItemURL,	"URL:");		// Precedes a Bookmark URL
+_LIT8(KEBookmarkType,		"TYPE:Wap\r\n");
+_LIT8(KEBookmarkItemEnd,	"END:eBOOKMARK\r\n");
+
+_LIT(KEBookmarkExtension,	".eBM");
+
+_LIT(KWappResourceFile, "\\resource\\messaging\\wappstr.rsc");
+
+const TUint32 KCharsetUCS2 = 1000;
+const TUint32 KCharsetUTF8 = 106;
+const TUint32 KCharsetASCII = 3;
+
+
+// The number of characters that are constant for an eBookmark
+// file. It is the sum of the above literals.
+// 
+const TInt KEBookmarkConstantChars = 55;
+
+CMsvBIOWapAccessParser::CMsvBIOWapAccessParser(CRegisteredParserDll& aRegisteredParserDll, CMsvEntry& aEntry, RFs& aFs)
+: CBaseScriptParser2(aRegisteredParserDll, aEntry, aFs)
+   {
+   }
+
+EXPORT_C CMsvBIOWapAccessParser* CMsvBIOWapAccessParser::NewL(CRegisteredParserDll& aRegisteredParserDll, CMsvEntry& aEntry, RFs& aFs)
+    {
+    CMsvBIOWapAccessParser* self = new (ELeave) CMsvBIOWapAccessParser(aRegisteredParserDll, aEntry, aFs);
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop();
+    return self;
+    }
+
+CMsvBIOWapAccessParser::~CMsvBIOWapAccessParser()
+    {
+	Cancel();
+	// Char Conversion
+	delete iCharsetConverter;
+    delete iSettings;
+	delete iSmsBuf;
+	delete iStringTable;
+	if (iBookmarkList!=NULL)
+		{
+		iBookmarkList->ResetAndDestroy();
+		delete iBookmarkList;
+		}
+	delete iModemInitString;
+    if (iParsedFieldArray != NULL)
+        {
+        iParsedFieldArray->ResetAndDestroy();
+        delete iParsedFieldArray;
+        }
+	delete iWapIpISPTable;
+	delete iWapSmsTable;
+	delete iWapGprsTable;
+	delete iGsmCsdWapIpTable;
+	delete iGprsWapIpTable;
+
+	delete iDBSession;
+	REComSession::FinalClose();
+    }
+
+//
+//	ConstructL			- ConstructL fn - creates the Parsed Field array, 
+//						  and connects the file system if unconnected
+//	
+void CMsvBIOWapAccessParser::ConstructL()
+    {
+	iParsedFieldArray = new(ELeave) CArrayPtrSeg<CParsedField>(16);	
+	iDBSession = CMDBSession::NewL(CMDBSession::LatestVersion());
+	iBookmarkList = new(ELeave) CArrayPtrSeg<CWappBookmark> (4);// 4 should be enough
+	iGsmCsdData = EFalse;
+	iGsmSmsData = EFalse;
+	iGprsData	= EFalse;
+	iURLData	= EFalse;
+	iNameData	= EFalse;
+	iIdData		= EFalse;
+	iMMSURLData = EFalse;
+    CActiveScheduler::Add(this);
+    }
+
+//
+//	ParseL		- public method forming part of the API.  Calls ChangeState to set 
+//				  state for parsing. Helper functions do the parsing
+//
+void CMsvBIOWapAccessParser::ParseL(TRequestStatus& aStatus, const TDesC& aSms)
+    {
+    TMsvEntry entry = iEntry.Entry();   //  Get the generic stuff
+    iEntryId = entry.Id();              //  store the TMsvId
+
+	// Message must be unparsed, or parsed or committed - anything else is a big error
+    __ASSERT_DEBUG((   entry.MtmData3() == BIO_MSG_ENTRY_UNPARSED
+					|| entry.MtmData3() == BIO_MSG_ENTRY_PARSED
+					|| entry.MtmData3() == BIO_MSG_ENTRY_PROCESSED),
+                            Panic(EWappErrMessageProcessed));
+	
+	// Message must not be empty 
+	__ASSERT_DEBUG (aSms.Length() > 0 ,Panic( EWappEmptyBuffer));
+
+   //  Already parsed....just return
+    if(entry.MtmData3() == BIO_MSG_ENTRY_PARSED || entry.MtmData3() == BIO_MSG_ENTRY_PROCESSED)
+        {
+        iReport = &aStatus;
+        User::RequestComplete(iReport, KErrNone);
+        }
+    //  not parsed so start the Parsing operation
+    else if(entry.MtmData3() == BIO_MSG_ENTRY_UNPARSED)
+        {
+        delete iSmsBuf;
+        iSettings = NULL;
+        iSmsBuf = aSms.AllocL();
+        ChangeStateL(EStart);		// Do do initial processing, and go Active
+        aStatus = KRequestPending;
+        iReport = &aStatus;
+        }
+    else
+        {
+        User::Leave(KErrNotSupported);
+        }
+    }
+
+//
+//  ProcessL() --   If  parsed data is not already in memory, ProcessL loads it from the store
+//					created during parsing. Creates a new entry in the WAP settings CommDb tables, from the data
+//
+void CMsvBIOWapAccessParser::ProcessL(TRequestStatus& aStatus)
+    {
+	// Calls ChangeState to get State Engine going. ( DoProcess does the hard work)
+
+	iEntryId= iEntry.Entry().Id(); //store id of Bio Msg entry 
+
+	// Must be a smart/Bio message, of type WAP access point and not have the failure flag set
+	__ASSERT_DEBUG(iEntry.Entry().iMtm==KUidSmartMessageMtm, Panic(EWappInvalidEntry));
+	__ASSERT_DEBUG(iEntry.Entry().iBioType ==KUidBIOWAPAccessPointMsg, Panic(EWappInvalidEntry));
+	__ASSERT_DEBUG(iEntry.Entry().Failed()== 0 , Panic(EWappInvalidEntry));
+
+	ResetProcessVariablesL();       // Reset variables to initial state
+	ChangeStateL(EProcessInitialise);   //Set the initial state
+
+	aStatus = KRequestPending;
+	iReport = &aStatus; 	
+   	}
+
+//	 DoCancel	-  Cancels the Active Object operation and returns control to the caller
+//
+void CMsvBIOWapAccessParser::DoCancel()
+    {
+	User::RequestComplete(iReport,KErrCancel);
+    }
+
+//
+//	RunL()		-		Called by the Active Scheduler when it finishes its Wait Loop. 
+//						Doesn't do much as ParseL and Process keep going until they are complete.
+//						Returns the current status. 
+//
+void CMsvBIOWapAccessParser::RunL()
+    {
+    iCompleted = iStatus.Int();
+
+	if (iCompleted != KErrNone)
+		{
+		User::RequestComplete(iReport,iCompleted);
+		return;
+		}
+	TInt currentState = iState;
+	TRAPD(error, CallChangeStateL(currentState));
+	switch (currentState)
+		{
+		case EStart:
+		case EProcessInitialise:
+		case EProcessMessage:
+			if (error!=KErrNone)
+				User::RequestComplete(iReport, error);  // Return error code
+			break;
+		case EParseMessage:
+		case ECompleteMessage:
+			User::RequestComplete(iReport, iCompleted); // Nothing more - allow calling RunL to complete and return status
+			break;
+		default:
+			break;
+		}
+    }
+
+void CMsvBIOWapAccessParser::CallChangeStateL(TInt aState)
+	{
+	switch (aState)
+		{
+		case EStart:
+			ChangeStateL(EParseMessage);
+			break;
+		case EProcessInitialise:
+			ChangeStateL(EProcessMessage);
+			break;
+		case EProcessMessage:
+			ChangeStateL(ECompleteMessage);  // last stage change iMtmData3 
+			break;
+		default:
+			break;
+		}
+	}
+
+//
+//	ChangeStateL		-	Used to advance the state to the next level.
+//							Makes most of the important calls.
+//
+void CMsvBIOWapAccessParser::ChangeStateL(TParseSession aState)
+    {
+	iState = aState;
+    switch (iState)
+        {                    
+		case EStart:	// Check the data we've got - if OK get the Active Stuff going
+			if (!iSmsBuf)			
+				User::Leave(KWappErrNullValue);
+			else if (iSmsBuf->Length() == 0)
+				User::Leave(KWappErrContent);
+			break;
+        case EParseMessage:
+			iSms = iSmsBuf->Des();      // initialise TLex object
+			ParseMessageL();
+            break;
+		case EProcessInitialise:
+			if (!iSmsParsed)
+				RestoreParsedDataL();
+			PreProcessL();  //Scan iParsedFieldArray extracting data - leaves if data is invalid
+			ValidateCharacteristicsL(); // Ensures that the mix of characteristic is valid
+			break;
+		case EProcessMessage:
+			DoProcessL(); // Do the proper processing of and committing to CommDb
+			break;
+		case ECompleteMessage:
+			CompleteMessageL();
+			break;
+        default:
+            break;
+        }
+
+	// Finished this step -add ourselves to Scheduler,& return error code to calling thread.
+	RequestComplete(iStatus, KErrNone); 
+	SetActive();
+    }
+
+//
+//	ParseMessageL()		- Performs various checks, if data has been saved it restores it  
+//						  else it calls DoParseL which does the hard stuff).
+//
+void CMsvBIOWapAccessParser::ParseMessageL()
+	{
+	// MUST have Bio message, of type WAP access point and no failure flag set
+	__ASSERT_DEBUG(iEntry.Entry().iMtm==KUidSmartMessageMtm, Panic(EWappInvalidEntry));
+	__ASSERT_DEBUG(iEntry.Entry().iBioType ==KUidBIOWAPAccessPointMsg, Panic(EWappInvalidEntry));
+	__ASSERT_DEBUG(iEntry.Entry().Failed()== 0 , Panic(EWappInvalidEntry));
+
+	// Message already parsed(includes processed).  Just restore data and return
+	if (iEntry.Entry().MtmData3() == BIO_MSG_ENTRY_PARSED || 
+		iEntry.Entry().MtmData3() == BIO_MSG_ENTRY_PROCESSED)
+		iSmsParsed = ETrue;   // Have a store produced during parsing. 
+	else 
+		iSmsParsed = EFalse;
+
+	if(iSmsParsed)  // parsed before - restore data
+		{
+		RestoreParsedDataL();
+		return;
+		}
+
+	DoParseL();			// Does the actual parsing of the message contents
+	SettingsNamePresentL(); // Check for Name Characteristic- if not found appends a default one
+	StoreParsedDataL(); // Saves the parsed fields to store & sets TMSvEntry values
+	iSmsParsed=ETrue;
+	}
+
+//
+//  CompleteMessageL()	-	Completes the ProcessL operation, by setting the iMtmData3 
+//							flag to BIO_MSG_ENTRY_PROCESSEDMessage body, and TMsvEntry's
+//							iDescription and iDetails are left unchanged
+//
+void CMsvBIOWapAccessParser::CompleteMessageL()
+    {
+	TMsvEntry entry= iEntry.Entry();
+	entry.SetMtmData3(BIO_MSG_ENTRY_PROCESSED);
+
+	iEntry.ChangeL(entry);
+    }
+
+//
+//	RequestComplete()	-	Completes an AO operation, and passes control back to the caller
+//
+void CMsvBIOWapAccessParser::RequestComplete(TRequestStatus& aStatus, TInt aError)
+    {
+    TRequestStatus* p = &aStatus;
+    User::RequestComplete(p, aError);
+    }
+
+//
+//  DoParseL()		- Parses through encoded message body extracting the fields from the characteristics
+//					Uses helper functions to handle reading and storing of characteristics and parms. 
+//					Parsing performed in one continuous operation.
+//
+void CMsvBIOWapAccessParser::DoParseL()
+    {
+	const TInt KDecimalSizeOfMaxInt = 10; // length of 0xFFFFFFFF in a string in decimal
+	TBuf<KDecimalSizeOfMaxInt> localBuf;
+	TChar thisCharacter;
+ 
+	thisCharacter = GetNextMessageByteL();	// Read the first char to get XML version number
+	/*
+	The version byte contains the the major version minus one in the upper four bits 
+	of the 8 bit integer, and the minor version in the lower four bits.
+	*/
+	TUint wbxmlversionbyte = thisCharacter; 
+	TUint majorversion = ((wbxmlversionbyte & 0xF0) + 0x10) - 0x0F; // gives the major version, eg if wbxml spec version 1.2, it gives 1.
+	TUint minorversion = wbxmlversionbyte & 0x0F; //gives the minor version, eg if wbxml spec version 1.2, it gives 2.
+	
+	iWBXMLversionX10 = (majorversion *10) + minorversion; //i.e. If actual version is 1.1 this is *10 to remove the decimal place.
+
+	//Append this to the array
+	localBuf.NumUC(iWBXMLversionX10,EDecimal);  //Format to a decimal string
+	AppendDataPairL(KWappXMLversion, localBuf); // Append to array of parsed fields
+
+	// Now need to get the 32bit int encoded over a number of bytes
+	iPublicID = Read_mb_u_int32L();		// Read in a multi byte 32bit int value
+	localBuf.NumUC(iPublicID, EHex);	// Format to a string as hex 
+	AppendDataPairL(KWappPublicID, localBuf); 
+	
+	// WAP Binary XML version 1.1 also has additional info for the character set.
+	if (iWBXMLversionX10 !=10)				// If WAP Binary XML version > 1.0
+		iCharacterSet = Read_mb_u_int32L(); // Get the character set
+	else
+		//This is the character set MIBenum for UTF-8. 
+		//According to WBXML spec version 1.1 and 1.2, this is the default which should 
+		//be assumed if the charset value is not available. Value 0 must not be used. 
+		iCharacterSet = 106; 
+
+	delete iCharsetConverter;
+	iCharsetConverter = NULL;
+	iCharsetConverter = CWapCharsetConverter::NewL(iFs, iCharacterSet);
+
+	localBuf.NumUC(iCharacterSet, EHex);	// Convert to string as hex 
+	AppendDataPairL(KWappCharacterSet,localBuf);
+
+	// Coded string table length - don't need this once we have string table
+	// as we store copies of the strings within parsed data fields 
+	TUint32 stringTableLength = Read_mb_u_int32L();
+
+	//Read in string table if it exists, i.e. length >0 otherwise skip this step
+	if (stringTableLength>0) 
+		{
+		iStringTable = HBufC::NewL(stringTableLength);
+		iSms.Mark();					// Mark the current position
+
+		TUint32 remaining = iSms.RemainderFromMark().Length(); //Eliminates warning about comparison in next line
+		
+		if ( remaining > stringTableLength) // Sting Table doesn't exceed end of message
+			iSms.Inc(stringTableLength);	// so increment to the character following the string table
+		else
+			User::Leave(KWappErrEOS); // Table exceeds message length - unrecoverable error
+		iStringTable->Des().Copy(iSms.MarkedToken());
+		}
+
+	thisCharacter = GetNextMessageByteL();
+	//This should be a Characteristic List with content, but no attributes
+	if (thisCharacter == (KWAPP_CHAR_LIST+KWAPP_TAG_CONTENT))
+		{
+		// Main loop - keep moving through the message, until we reach the end or error
+		TBool finished = EFalse;
+		while (!finished)
+			{		
+			// Read in characteristics, any order is accepted
+			if (!iSms.Eos() && (iSms.Peek() & 0x3F) == KWAPP_CHARACTERISTIC)
+				{
+				// Read in characteristic, inc. its terminator tag - no terminator =error!
+				ReadCharacteristicL();
+				}
+			else
+				{
+				if (iSms.Eos()) // Error end of message
+					User::Leave(KWappErrEOS);
+				else if ((TUint)iSms.Peek()==KWAPP_END_TAG) // END Tag - OK we've finished!
+					finished = ETrue;
+				else if ( (iSms.Peek()& 0x3F != KWAPP_CHARACTERISTIC) || (iSms.Peek() != KWAPP_END_TAG) )
+					User::Leave(KWappErrUnexpectedValue); //Not a Characteristic or END token
+				}
+			}
+		} // End of if (thisCharacter == (KWAPP_CHAR_LIST..... )
+	else
+		User::Leave(KWappErrMandatoryTagMissing);
+    }
+// end CMsvBIOWapAccessParser::DoParseL()
+
+//	
+//	ReadCharacteristicL()		-  Reads in a characteristic from the message.
+//
+void  CMsvBIOWapAccessParser::ReadCharacteristicL()
+	{
+	TBool hasContent;
+	TInt  characteristicIndex=0; // start position in array for this characteristic
+	CParsedField* parsedField = new(ELeave)CParsedField();
+	CleanupStack::PushL(parsedField);		
+
+	TChar currentCharacter = GetNextMessageByteL();
+	iCurrentCharacteristic =EWappUnknown; // Reset flag for current characteristic's type
+
+	// Use bit comparison of token with mask 0x3F to check explicitly that correct 
+	// bits are set i.e. that bits 0-5 = 0x06   (NB Actual value = 0x86 or =0xC6)
+	if ( ( currentCharacter & 0x3F) != KWAPP_CHARACTERISTIC ) // i.e. not or 0x06
+		User::Leave(KWappErrUnexpectedValue);		
+	else
+		{
+		if ( !(currentCharacter & KWAPP_TAG_ATTRIBUTES)) // Bit 7 must be set!
+			User::Leave(KWappErrNoAttributes); 
+		if (currentCharacter & KWAPP_TAG_CONTENT)  //Bit 6 is set - characteristic has content
+			hasContent =ETrue;
+		else
+			hasContent =EFalse;
+
+
+	// ***************			IMPORTANT NOTE		   ************************
+	// An XML element name without a defined token is sent as an inline string or
+	// string table ref. prefixed by the TYPE token 0x05 (ie "TYPE="). (True for
+	// WirelessFuture web site!!) THE ONLY UNDEFINED Type tag is BOOKMARK in version
+	// 1.0. Therefore if it's 0x05  - check the version. For 1.0 read next char.
+	// Token must be an inline string or string table ref.Otherwise we have an error.
+	// ****************************************************************************
+
+		// Read the next byte - info on the type of our characteristic  
+		currentCharacter = (TUint) GetNextMessageByteL();
+		
+		// Check if the tokens 0x05 "TYPE=" - should be for WBXML version = 1.0 
+		// Read next character
+		if (currentCharacter == KWAPP_TYPE)
+			{
+			// "TYPE=" should be followed by an inline string, or string table reference
+			// So read another char & increment a place - should now 0x03 or 0x83
+			currentCharacter = (TUint) GetNextMessageByteL();
+			if  (	!(currentCharacter & KWAPP_STR_I) &&	// Is current character != 0x03 ?
+					!(currentCharacter & KWAPP_STR_T))		// or != 0x83 
+				 User::Leave(KWappErrUnexpectedValue);		// Doc is badly formed doc - leave
+			}
+
+	// NB for address characteristics, need to store position of the start, so that
+	// we can search for certain fields. If they're not present we must add defaults.  
+	// Could just scan from the end of the array, but if we miss our target then may
+	// just increment past this characteristic, through previous ones.
+ 
+		switch (currentCharacter)
+			{
+			case KWAPP_ADDR_TYPE:  // Token = 0x06
+				{
+				AppendNameFieldL(KWappCharAddress);		
+				characteristicIndex = iParsedFieldArray->Count()-1; // Store index for this element
+				iCurrentCharacteristic = EWappAddressCharacteristic; //General code for an address
+				break;
+				}
+			case KWAPP_URL_TYPE:   //Token = 0x07
+				{
+				AppendNameFieldL(KWappCharURL);
+				iCurrentCharacteristic  = EWappURLCharacteristic; // it's a URL characteristic
+				break;
+				}
+			case KWAPP_NAME_TYPE:  // Token = 0x08
+				{
+				AppendNameFieldL(KWappCharName); 
+				iCurrentCharacteristic = EWappNameCharacteristic;//it's a NAME characteristic
+				break;
+				}
+			case KWAPP_STR_I:		// Token = 0x03  , Global WAP XML value
+				{
+				// Null terminated inline string follows the token, call fn to read it
+				parsedField->SetFieldNameL(*ReadInlineStringLC());
+				CleanupStack::PopAndDestroy(); //inline string
+				break;
+				}
+			case KWAPP_STR_T:		// Token = 0x83,  Global WAP XML value
+				{
+				// multi byte 32 bit integer follows, an reference to an offset in the string table
+				TUint32 offset =0;
+				offset = Read_mb_u_int32L(); // read in the integer
+				parsedField->SetFieldNameL(*ReadStringTableReferenceLC(offset));//Get string table value,& set the descriptor
+				CleanupStack::PopAndDestroy(); // string table reference
+				break;
+				}
+			case KWAPP_ID:			// Token = 0x7D.  Used in version 5.0
+				{
+				AppendNameFieldL(KWappCharID);  
+				iCurrentCharacteristic = EWappIDCharacteristic; 
+				break;
+				}
+			case KWAPP_BOOKMARK:	// Token = 07F, currently bookmarks stored in file
+				{
+				AppendNameFieldL(KWappCharBookmark);  
+				iCurrentCharacteristic = EWappBookmarkCharacteristic; 
+				break;
+				}
+			case KWAPP_MMS_URL:
+				{
+				AppendNameFieldL(KWappCharMMSURL);
+				iCurrentCharacteristic = EWappMMSURLCharacteristic;
+				break;
+				}
+			default:
+				User::Leave(KWappErrUnrecognised);   // Unrecognised token or somethings badly wrong
+			}
+		
+
+		// If iCurrentCharacteristic isn't set we've just read in a string table ref
+		// or inline string. Now check the token and set the flag.
+		if (iCurrentCharacteristic == EWappUnknown)
+			{
+			// Get index of last element
+			if (parsedField->FieldName().CompareF(KWappAddr)==0)
+				{
+				iCurrentCharacteristic = EWappAddressCharacteristic; 
+				AppendNameFieldL(KWappCharAddress);	
+				characteristicIndex = iParsedFieldArray->Count()-1;//May be an address so store index
+				}
+			else if (parsedField->FieldName().CompareF(KWappURL)==0)
+				{
+				iCurrentCharacteristic = EWappURLCharacteristic;
+				AppendNameFieldL(KWappCharURL);
+				}
+			else if (parsedField->FieldName().CompareF(KWappMMSURL)==0)
+				{
+				iCurrentCharacteristic = EWappMMSURLCharacteristic;
+				AppendNameFieldL(KWappCharMMSURL);
+				}
+			else if (parsedField->FieldName().CompareF(KWappName)==0)
+				{
+				iCurrentCharacteristic = EWappNameCharacteristic;
+				AppendNameFieldL(KWappCharName); 
+				}
+			else if (parsedField->FieldName().CompareF(KWappBookmark)==0)
+				{
+				iCurrentCharacteristic = EWappBookmarkCharacteristic;
+				AppendNameFieldL(KWappCharBookmark);
+				}
+			else if (parsedField->FieldName().CompareF(KWappID)==0)
+				{
+				iCurrentCharacteristic = EWappIDCharacteristic;
+				AppendNameFieldL(KWappCharID); 
+				}
+			else 
+				{
+				User::Leave(KWappErrUnrecognised);// Unrecognised characteristic type 
+				}
+			}		
+		CleanupStack::PopAndDestroy(parsedField);
+	
+		//Check for a VALUE attribute before checking for Parms
+		currentCharacter =(TUint) GetNextMessageByteL();
+		if (currentCharacter ==KWAPP_VALUE_ATTRIB)
+			{
+			// Have a value following the TYPE - read in value and store it.
+			TInt  lastElement = iParsedFieldArray->Count()-1;
+			currentCharacter = (TUint) GetNextMessageByteL();
+
+			if (currentCharacter == KWAPP_STR_I)		//Inline string
+				{
+				iParsedFieldArray->At(lastElement)->SetFieldValueL(*ReadInlineStringLC()); //Set value of last element in array
+				CleanupStack::PopAndDestroy();
+				}
+
+			else if (currentCharacter ==KWAPP_STR_T)	//String table reference
+				{
+				TUint32 tableOffset = Read_mb_u_int32L();
+				iParsedFieldArray->At(lastElement)->SetFieldValueL(*ReadStringTableReferenceLC(tableOffset));  //Set Value of last element in array
+				CleanupStack::PopAndDestroy();
+				}
+
+			else 
+				{
+				User::Leave(KWappErrUnexpectedValue);
+				}
+
+			// Read the next character for the END TAG check in the following line 
+			currentCharacter = (TUint)GetNextMessageByteL();
+			}
+
+		//Check the character- should be 0x01 the end of the characteristic header
+		if (!currentCharacter ==KWAPP_END_TAG) // Not END - error condition
+			{
+			User::Leave(KWappErrNoTermination); 
+			}
+
+		// We shouldn't be at the end of the message. The next byte should be one of the following 
+		//	    - PARM if this characteristic has content, 
+		//		- start of another characteristic
+		//		- END token (0x01).
+		// So take a peek at the next byte
+		TUint peekAhead;
+
+		if (iSms.Eos())
+			User::Leave(KWappErrEOS);	// Somethings wrong - message end
+		
+		peekAhead = (TUint) iSms.Peek();
+
+		// Type is Set - address,URL,Name, Bookmark or ID. Check hasContent flag set correctly. 
+		if ( ((iCurrentCharacteristic == EWappAddressCharacteristic) && !hasContent) || //Address must have Content
+		     ((iCurrentCharacteristic == EWappNameCharacteristic) && !hasContent)	 ||  //Name must have Content
+			 ((iCurrentCharacteristic == EWappBookmarkCharacteristic) && !hasContent)|| //Bookmark must have Content
+			 ((iCurrentCharacteristic == EWappIDCharacteristic) && !hasContent)		 || //ID must have Content
+			 ((iCurrentCharacteristic == EWappURLCharacteristic) && hasContent)		 ||  // Url must NOT have Content
+			 ((iCurrentCharacteristic == EWappMMSURLCharacteristic) && hasContent)     )  // MmsUrl does not have content
+			 User::Leave(KWappErrContent); // Test for validity of content flag failed.
+			
+
+		if (hasContent)  // passed previous test, - exclude URL as hasContent=EFalse
+			{
+			if ( (peekAhead & 0x3F) ==KWAPP_PARM) // bit comparison with 0x07
+				{
+				// Check sucessful, now check for attributes and content (0x80, & 0x40)
+				if ( (peekAhead & KWAPP_TAG_ATTRIBUTES) && ( !(peekAhead & KWAPP_TAG_CONTENT) ) )
+					{
+					//Have attributes, and no content - ALL OK!
+					currentCharacter = (TUint32) GetNextMessageByteL();
+					while (currentCharacter != KWAPP_END_TAG)
+						{
+						ReadParmL(); // Sets iCurrentCharacteristic for addresses
+						
+						currentCharacter = (TUint32) GetNextMessageByteL();  // Get the next character from message
+						
+						if ( (currentCharacter != (KWAPP_PARM+KWAPP_TAG_ATTRIBUTES))
+							&& (currentCharacter !=KWAPP_END_TAG) ) // Not 0x87, nor 0x01 = error
+							User::Leave(KWappErrUnexpectedValue); 
+						}
+					}
+				else  // Token MUST be 0x87, parms MUST have content but NO attributes!
+					User::Leave(KWappErrNoAttributes);  
+				}
+			else  //Bits 0-5 are Not 0x07  Should be a PARM token
+				User::Leave(KWappErrUnexpectedValue); 
+			} //END of (hasContent)
+		}
+		// END of  if ( !( (TUint32)currentCharacter & KWAPP_CHARACTERISTIC) )
+
+
+
+// ************************** MANDATORY PARMS & DEFAULT VALUES **************************
+// Finished reading in the parms for the characteristic.  Each Address Characteristic 
+// has it's own set of defaults. If this is an address - ensure defaults are present.
+		
+
+// CHARACTERISTIC TYPE = ADDRESS, BEARER TYPE  = GSM/CSD or IS-136/CSD
+//	 Bearer, Proxy, and Csd_Dialstring are mandatory..
+//   Auth. Names and Passwords don't have defaults so are not set here!
+		
+		if ( iCurrentCharacteristic == EWappGsmCsdCharacteristic||
+			iCurrentCharacteristic == EWappIS136CsdCharacteristic )
+			{
+			//Required PARMS				OTA v4.0	   v5.0
+			//CSD-		PROXY					Y			Y
+			//			PORT				add default of 9200	
+			//			CSD_DIALSTRING			Y			Y
+			//			CSD_AUTHNAME			Y			N
+			//			CSD_AUTHSECRET			Y			N
+			//			CSD_CALLTYPE			Y		Add default of PAP
+			//			CSD_CALLSPEED		    Y       Add default of AUTO
+
+			// Check mandatory PARMS present else bad message - unrecoverable error!
+			TInt index;
+		
+			// OTA v4.0 & 5.0:  required Parms present?
+			index = LocateParsedFieldName(KWappProxy,characteristicIndex);
+			if (index == KErrNotFound) // TODO can this be null? || (iParsedFieldArray->At(index)->FieldValue() == TPtrC()))
+				User::Leave(KWappErrMandatoryTagMissing);
+			
+			index = LocateParsedFieldName(KWappCsdDial,characteristicIndex);
+			if (index == KErrNotFound) // Can this be Null?? || (iParsedFieldArray->At(index)->FieldValue() == TPtrC()) )
+				User::Leave(KWappErrMandatoryTagMissing); 
+
+			// OTA v4.0 only, mandatory Parms  present?
+			if (iWBXMLversionX10 == 10)
+				{
+				index = LocateParsedFieldName(KWappPPPAuthName,characteristicIndex);
+				if (index == KErrNotFound)// Can this be NULL || (iParsedFieldArray->At(index)->FieldValue() == TPtrC()))
+					User::Leave(KWappErrMandatoryTagMissing);
+			
+				index = LocateParsedFieldName(KWappPPPAuthSecret,characteristicIndex);
+				if (index == KErrNotFound) // Can this be a Null value? || (iParsedFieldArray->At(index)->FieldValue() == TPtrC()) )
+					User::Leave(KWappErrMandatoryTagMissing); 
+				}
+
+			// Search for PORT from beginning of this characteristic to array end or next 
+			// Characteristic - whichever's first. NB this is currently the last characteristic in array!
+
+			index = LocateParsedFieldName(KWappPort, characteristicIndex);
+			if (index ==KErrNotFound)	// Not Found - add the default value
+				{
+				index = LocateParsedFieldName(KWappProxy,characteristicIndex); // Mandatory - check already made
+				InsertDataPairL(KWappPort, KWappPort9200, index+1);
+				}
+			
+			// Check for the PPP_AUTHTYPE element
+			index = LocateParsedFieldName(KWappPPPAuthType, characteristicIndex);
+			if (index ==KErrNotFound)	// Not Found - add the default value
+				{
+				index = LocateParsedFieldName(KWappCsdDial, characteristicIndex); // always present
+				// Create new element,NAME="PPP_CALLTYPE", VALUE="PAP"
+				InsertDataPairL(KWappPPPAuthType, KWappPAP, index+1);
+				}
+
+			// Check for the CSD_CALLTYPE element
+			index = LocateParsedFieldName(KWappCsdCallType, characteristicIndex);
+			if (index ==KErrNotFound)	// Not Found - add the default value
+				{
+				index = LocateParsedFieldName(KWappPPPAuthType, characteristicIndex); 
+				if (index ==KErrNotFound)
+					User::Leave(KWappErrMandatoryTagMissing); // Error - should be here from step above!!!
+				else
+					// Create new element,NAME="CSD_CALLTYPE", VALUE="ANALOGUE"
+					InsertDataPairL(KWappCsdCallType, KWappAnalogue, index+1);
+				}
+
+			// Check for the CSD_CALLSPEED element
+			index = LocateParsedFieldName(KWappCsdCallSpeed, characteristicIndex);
+			if (index ==KErrNotFound)	// Not Found - add the default value
+				{
+				index = LocateParsedFieldName(KWappCsdCallType,characteristicIndex);
+				if (index ==KErrNotFound)
+					User::Leave(KWappErrMandatoryTagMissing); // Error - should be here from step above!!!
+				else				
+					//Create new PARM,
+					// If CSD_CALLTYPE="ANALOGUE"   ->  NAME="CSD_CALLSPEED", VALUE="AUTO" 
+					// else if CSD_CALLTYPE="ISDN"  ->  NAME="CSD_CALLSPEED", VALUE="9600" 
+					if (iParsedFieldArray->At(index)->FieldValue().CompareF(KWappISDN)==0)
+						InsertDataPairL(KWappCsdCallSpeed, KWappSpeed9600, index+1);
+					else
+						InsertDataPairL(KWappCsdCallSpeed, KWappSpeedAuto, index+1);
+				}
+			}// END of if(iCurrentCharacteristic == EWappCSDCharacteristic)|| .......
+
+
+// CHARACTERISTIC TYPE = ADDRESS, BEARER TYPE  = GSM/SMS 
+// Only the PORT PARM value is optional - all the rest are mandatory
+		
+		if (iCurrentCharacteristic == EWappGsmSmsCharacteristic)
+			{
+			//Required PARMS				OTA v4.0	   v5.0
+			//SMS-		PROXY					Y			Y
+			//			SMS_SMSC_ADDRESS		Y
+	
+			// Check that required fields are present - badly formed message otherwise
+			TInt fieldIndex = LocateParsedFieldName(KWappProxy, characteristicIndex);
+			if (fieldIndex == KErrNotFound ) // TODO Check if this can be null || (iParsedFieldArray->At(fieldIndex)->FieldValue().Length()==0) )
+				User::Leave(KWappErrMandatoryTagMissing); 
+
+			fieldIndex = LocateParsedFieldName(KWappSMSCAddress, characteristicIndex);
+			if ((fieldIndex ==KErrNotFound)) // TODO Check if this can be null   || (iParsedFieldArray->At(fieldIndex)->FieldValue().Length()==0) )
+				User::Leave(KWappErrMandatoryTagMissing);
+
+
+			if (LocateParsedFieldName(KWappPort, characteristicIndex) ==KErrNotFound) //Tag not found
+				{
+				fieldIndex = LocateParsedFieldName(KWappProxy, characteristicIndex); //Mandatory field
+				// Create a new  element, NAME="PORT", VALUE="9200"
+				InsertDataPairL(KWappPort,KWappPort9200, fieldIndex+1);
+				}
+			}//END of  if(iCurrentCharacteristic == EWappSMSCharacteristic)
+
+
+// CHARACTERISTIC TYPE = ADDRESS, BEARER TYPE  = GSM/USSD 
+		if (iCurrentCharacteristic == EWappGsmUssdCharacteristic)
+			{
+			
+			//Only USSD Service Code is mandatory - MUST not be NULL
+			TInt index = LocateParsedFieldName(KWappUSSDCode, characteristicIndex);
+			if (index == KErrNotFound || iParsedFieldArray->At(index)->FieldValue().Length()==0)
+				User::Leave(KWappErrMandatoryTagMissing);
+			
+			// PROXY is optional for USSD but has no default value
+			// Do have defaults for PROXY_TYPE and PORT
+			if (LocateParsedFieldName(KWappProxyType, characteristicIndex)  ==KErrNotFound) //Tag not found
+				{
+				index = LocateParsedFieldName(KWappUSSDCode, characteristicIndex); //Mandatory field
+			
+				// Create a new  element, NAME="PROXY_TYPE", VALUE="MSISDNNO"
+				InsertDataPairL(KWappProxyType,KWappMsisdnNo, index+1);
+				}
+
+			if ( LocateParsedFieldName(KWappPort, characteristicIndex) == KErrNotFound) // Not Found - add the default value
+				{
+				index = LocateParsedFieldName(KWappProxyType,characteristicIndex);
+				if (index ==KErrNotFound)
+					User::Leave(KWappErrMandatoryTagMissing); // Error - should be here from step above!!!
+				else	// Create new element,NAME="PORT", VALUE="9200"
+					InsertDataPairL(KWappPort, KWappPort9200, index+1);
+				}
+			} // END of -  if (iCurrentCharacteristic == EWappGsmUssdCharacteristic)... 
+
+
+// CHARACTERISTIC TYPE = ADDRESS, BEARER TYPE  = GPRS 
+		if (iCurrentCharacteristic == EWappGprsCharacteristic)
+			{
+			// AHF - Removed check for tag GPRSACCESSPOINTNAME - no longer mandatory in OTA v7.0
+
+			// Check that mandatory PROXY field is present - else it's a badly formed msg
+			TInt index = LocateParsedFieldName(KWappProxy, characteristicIndex);
+			if (index == KErrNotFound ) 
+				User::Leave(KWappErrMandatoryTagMissing); 
+
+			//Search for optional Port field - if not found, search for mandatory Proxy field and insert "9200"
+			index = LocateParsedFieldName(KWappPort, characteristicIndex);
+			if (index ==KErrNotFound)
+				{
+				index = LocateParsedFieldName(KWappProxy,characteristicIndex); // Mandatory - check already made
+				InsertDataPairL(KWappPort, KWappPort9200, index+1); // NAME="PORT", VALUE = "9200"
+				}
+
+			// Check for the PPP_AUTHTYPE element - add default value if not found
+			index = LocateParsedFieldName(KWappPPPAuthType, characteristicIndex);
+			if (index ==KErrNotFound)	
+				{
+				index = LocateParsedFieldName(KWappCsdDial, characteristicIndex); // always present
+				InsertDataPairL(KWappPPPAuthType, KWappPAP, index+1); // NAME="PPP_CALLTYPE", VALUE="PAP"
+				}
+			}
+
+
+
+	}
+// END of CMsvBIOWapAccessParser::ReadCharacteristicL()
+
+//
+//	ReadParmL()		-	Reads in contents of a PARM & inserts into iParsedFieldArray
+//						as a CParsedField object. ASSUME that the PARM tag has
+//						been read & verified  before this is called. Consequently
+//					    now positioned at the start of the attributes 
+
+void CMsvBIOWapAccessParser::ReadParmL()
+	{
+
+	CParsedField* parsedField = new(ELeave) CParsedField;
+	CleanupStack::PushL(parsedField);
+	TChar currentCharacter = GetNextMessageByteL();
+
+	switch ((TUint) currentCharacter)
+		{
+		case KWAPP_NAME_ATTRIB:  //0x10 "NAME=..." ,string(inline or table ref.) should follow
+			{
+			//Start of NAME attribute, check for inline string/string table reference
+			currentCharacter=GetNextMessageByteL();
+			if ((TUint32) currentCharacter == KWAPP_STR_I)
+				{
+				parsedField->SetFieldNameL(*ReadInlineStringLC());
+				CleanupStack::PopAndDestroy(); 
+				}
+			else if ((TUint32) currentCharacter== KWAPP_STR_T)
+				{
+				TUint32 offset = Read_mb_u_int32L();
+				parsedField->SetFieldNameL(*ReadStringTableReferenceLC(offset));
+				CleanupStack::PopAndDestroy(); 
+				}
+				else // it isn't an inline string or string table ref - ERROR!
+					User::Leave(KWappErrNoTermination); 
+			break;
+			}
+		case KWAPP_BEARER: //0x12 NAME="BEARER"
+			{
+			parsedField->SetFieldNameL(KWappBearer); 
+			break;
+			}
+		case KWAPP_PROXY: //0x13   NAME="PROXY"  (Mandatory for GSM/CSD, GSM/SMS, IS136/CSD)
+			{
+			parsedField->SetFieldNameL(KWappProxy);	
+			break;
+			}
+		case KWAPP_PORT	://0x14 NAME="PORT"
+			{
+			parsedField->SetFieldNameL(KWappPort);	
+			break;
+			}
+		case KWAPP_NAME ://0x15 NAME = "NAME"
+			{
+			parsedField->SetFieldNameL(KWappName);	
+			break;
+			}
+		case KWAPP_PROXYTYPE  ://0x16 NAME="PROXY_TYPE"
+			{
+			parsedField->SetFieldNameL(KWappProxyType);
+			break;
+			}
+		case KWAPP_URL	:	// 0x17 NAME="URL"
+			{
+			parsedField->SetFieldNameL(KWappURL);	
+			break;
+			}
+		case KWAPP_PROXY_AUTHNAME :			// 0x18  NAME="PROXY_AUTHNAME"
+			{
+			parsedField->SetFieldNameL(KWappProxyAuthName);
+			break;
+			}
+		case KWAPP_PROXY_AUTHSECRET :		//0x19 NAME="PROXY_AUTHSECRET"
+			{
+			parsedField->SetFieldNameL(KWappProxyAuthSecret);
+			break;
+			}
+		case KWAPP_PROXY_LOGIN_TYPE :
+			{
+			parsedField->SetFieldNameL(KWappProxyLoginType);
+			break;
+			}
+		case KWAPP_SMS_SMSC_ADDR  :    //0x1A   NAME="SMS_SMSC_ADDR"  (Mandatory field for GSM/SMS)
+			{
+			parsedField->SetFieldNameL(KWappSMSCAddress); 
+			break;
+			}
+		case KWAPP_USSD_SERV_CODE :	//0x1B NAME="USSD_SER_CODE" (Mandatory for GSM/USSD)
+			{
+			parsedField->SetFieldNameL(KWappUSSDCode);	
+			break;
+			}
+		case KWAPP_ACCESS_POINT_NAME :	//0x1C	 NAME="ACCESSPOINTNAME" (Mandatory for GPRS)
+			{
+			parsedField->SetFieldNameL(KWappAccessPointName);
+			break;
+			}
+		case KWAPP_CSD_DIALSTRING :		//0x21   NAME="CSD_DIALSTRING" (Mandatory for GSM/CSD,IS136/CSD)
+			{
+			parsedField->SetFieldNameL(KWappCsdDial);
+			break;
+			}
+		case KWAPP_PPP_AUTHTYPE	  :		//0x22   NAME="CSD_AUTHTYPE"
+			{
+			parsedField->SetFieldNameL(KWappPPPAuthType);
+			break;
+			}
+		case KWAPP_PPP_AUTHNAME	  :	  //0x23   NAME="CSD_AUTHNAME"
+			{
+			parsedField->SetFieldNameL(KWappPPPAuthName);
+			break;
+			}
+		case KWAPP_PPP_AUTHSECRET :	  //0x24    NAME="CSD_AUTHSECRET"
+			{
+			parsedField->SetFieldNameL(KWappPPPAuthSecret);
+			break;
+			}
+		case KWAPP_PPP_LOGIN_TYPE :
+			{
+			parsedField->SetFieldNameL(KWappPPPLoginType);
+			break;
+			}
+		case KWAPP_CSD_CALLTYPE	  :	// 0x25    NAME="CSD_CALLTYPE"
+			{
+			parsedField->SetFieldNameL(KWappCsdCallType);
+			break;
+			}
+		case KWAPP_CSD_CALLSPEED  :	//0x28    NAME="CSD_CALLSPEED"
+			{
+			parsedField->SetFieldNameL(KWappCsdCallSpeed);
+			break;
+			}
+		case KWAPP_NAME_ISP	  :		//0x7E    NAME="ISP_NAME"
+			{
+			parsedField->SetFieldNameL(KWappISP);
+			break;
+			}
+
+		default:
+			User::Leave(KWappErrUnexpectedValue); // don't recognise the tag
+		}
+
+	// The early version of the WAP server, supporting version 4.0 of the Nokia OTA specs
+	// codes up PROXY_AUTHNAME & PROXY_AUTHSECRET as the PROXY token followed by
+	// a string/str ref. So we MUST check if inline string/str table ref follows
+	if (currentCharacter==KWAPP_PROXY) 
+		{
+		if (iSms.Eos())
+			User::Leave(KWappErrEOS); // ERROR - Unexpected end of message!! Nothing to peek at!
+		else if ( ((TUint)iSms.Peek() == KWAPP_STR_I) || ((TUint)iSms.Peek() == KWAPP_STR_T)) 
+			{
+			// String follows immediately after Name token not a Value Tag
+			TUint32 anOffset;
+			currentCharacter = GetNextMessageByteL();
+			HBufC* name = NULL;
+			if ((TUint) currentCharacter == KWAPP_STR_I)
+				{
+				name = ReadInlineStringLC();
+				}
+			else 
+				{
+				if ((TUint) currentCharacter != KWAPP_STR_T)
+					User::Leave(KWappErrUnexpectedValue); // Should not get here unless something is very wrong! 
+				anOffset = Read_mb_u_int32L();
+				name = ReadStringTableReferenceLC(anOffset);
+				}
+
+			//Defect fix for Def021848-Incorrect use of ReAllocL in wapp	
+			HBufC* newName = name->ReAllocL(name->Length() + parsedField->FieldName().Length());
+			CleanupStack::Pop(name);//Remove name from the Cleanup Stack as it would have been deleted by ReAllocL()
+			CleanupStack::PushL(newName);
+			newName->Des().Append(parsedField->FieldName()); //insert PROXY at front of string 
+			parsedField->SetFieldNameL(*newName);			  //replace current string  with new one
+			CleanupStack::PopAndDestroy(newName); 
+			}
+		}
+
+	TBool addParsedField = ETrue;
+
+	currentCharacter=GetNextMessageByteL(); //Get next byte - should be the Value tag
+	switch( (TUint32) currentCharacter)
+		{
+		case KWAPP_VALUE_ATTRIB : // 0x11  "VALUE=", string(inline or table ref) follows
+			{
+			if (iSms.Eos())
+				{
+				User::Leave(KWappErrEOS); // ERROR - Unexpected end of message!! Nothing to peek at!
+				}		
+			//Check for 0x01 (KWAPP_END_TAG) - assign fieldvalue with empty value and ignore the other 
+			if ( ((TUint)iSms.Peek() == KWAPP_END_TAG)) //Something wrong - Wrong PARAM Value 
+				{
+				addParsedField = EFalse;
+  				break;
+				}
+			// Start of VALUE attribute, string should follow
+			currentCharacter= GetNextMessageByteL();
+			if ((TUint32) currentCharacter == KWAPP_STR_I)		//Inline string
+				{
+				HBufC* value = ReadInlineStringLC();
+				parsedField->SetFieldValueL(*value);
+				CleanupStack::PopAndDestroy();
+				}
+			else if ((TUint32) currentCharacter== KWAPP_STR_T)	//String Table ref
+				{
+				TUint32 offset = Read_mb_u_int32L();			// Read 32bit int
+				HBufC* value = ReadStringTableReferenceLC(offset);	// Read in characters
+				parsedField->SetFieldValueL(*value);
+				CleanupStack::PopAndDestroy();
+				}
+				else //Not an inline string or string table ref - somethings wrong!
+					User::Leave(KWappErrUnexpectedValue); 
+			break;
+			}
+		case KWAPP_GSM_SMS_OLD	:	// 0x41 VALUE="GSM/SMS"
+			{
+			// Old value of GSM/SMS tag - ONLY valid for Version 4.0 of the specs, ie WBXML = 1.0!			
+			parsedField->SetFieldValueL(KWappGsmSms);		
+			break;
+			}
+		case KWAPP_GSM_CSD		:	// 0x45 VALUE="GSM/CSD"
+			{
+			parsedField->SetFieldValueL(KWappGsmCsd);			
+			break;
+			}		
+		case KWAPP_GSM_SMS_NEW	:	//  0x46 VALUE="GSM/SMS" ONLY valid for Version 5.0 of the specs, i.e.WBXML = 1.1!
+			{
+			parsedField->SetFieldValueL(KWappGsmSms);		
+			break;
+			}
+		case KWAPP_GSM_USSD		:	//0x47	VALUE="GSM/USSD" only defined for version 5.0 only 
+			{
+			parsedField->SetFieldValueL(KWappGsmUssd);
+			break;
+			}
+		case KWAPP_IS136		:	//  0x48   VALUE="IS136/CSD" for version 5.0 only
+			{
+			parsedField->SetFieldValueL(KWappIS136Csd);	
+			break;
+			}
+		case KWAPP_GPRS			:	// 0x49    VALUE="GSM/GPRS"
+			{
+			parsedField->SetFieldValueL(KWappGprs);
+			break;
+			}
+		case KWAPP_PORT_9200	:	// 0x60 VALUE="9200"
+			{
+			parsedField->SetFieldValueL(KWappPort9200);	
+			break;
+			}
+		case KWAPP_PORT_9201	:	// 0x61 VALUE="9201"
+			{
+			parsedField->SetFieldValueL(KWappPort9201);		
+			break;
+			}
+		case KWAPP_PORT_9202	:	// 0x62  VALUE="9202"
+			{
+			parsedField->SetFieldValueL(KWappPort9202);		
+			break;
+			}
+		case KWAPP_PORT_9203	:	// 0x63  VALUE="9203"
+			{
+			parsedField->SetFieldValueL(KWappPort9203);		
+			break;
+			}
+		case KWAPP_AUTOMATIC	:	//	0x64 
+			{
+			parsedField->SetFieldValueL(KWappAuthAutomatic);
+			break;
+			}
+		case KWAPP_MANUAL		:	// 0x65
+			{
+			parsedField->SetFieldValueL(KWappAuthManual);
+			break;
+			}
+		case KWAPP_SPEED_AUTO	:	// 0x6A VALUE="AUTO"
+			{
+			parsedField->SetFieldValueL(KWappSpeedAuto);		
+			break;
+			}
+		case KWAPP_SPEED_9600	:	// 0x6B VALUE="9600"
+			{
+			parsedField->SetFieldValueL(KWappSpeed9600);		
+			break;
+			}
+		case KWAPP_SPEED_14400	:	// 0x6C VALUE="14400"
+			{
+			parsedField->SetFieldValueL(KWappSpeed14400);		
+			break;
+			}
+		case KWAPP_SPEED_19200	:   //0x6D  VALUE="19200"
+			{
+			parsedField->SetFieldValueL(KWappSpeed19200);	
+			break;
+			}
+		case KWAPP_SPEED_28800  :   //0x6E  VALUE="28800"
+			{
+			parsedField->SetFieldValueL(KWappSpeed28800);	
+			break;
+			}
+		case KWAPP_SPEED_38400  :   //0X6F	VALUE="38400"
+			{
+			parsedField->SetFieldValueL(KWappSpeed38400);	
+			break;
+			}
+		case KWAPP_PAP			:	// 0x70	VALUE="PAP"
+			{
+			parsedField->SetFieldValueL(KWappPAP);		
+			break;
+			}
+		case KWAPP_CHAP			:	//0X71	VALUE="CHAP"
+			{
+			parsedField->SetFieldValueL(KWappCHAP);			
+			break;
+			}
+		case KWAPP_ANALOGUE		:	//0X72	VALUE="ANALOGUE"
+			{
+			parsedField->SetFieldValueL(KWappAnalogue);		
+			break;
+			}
+		case KWAPP_ISDN			:	//0X73	VALUE="ISDN"
+			{
+			parsedField->SetFieldValueL(KWappISDN);	
+			break;
+			}
+		case KWAPP_SPEED_43200  :   //0X74	VALUE="43200"
+			{
+			parsedField->SetFieldValueL(KWappSpeed43200);	
+			break;
+			}
+		case KWAPP_SPEED_56700  :	//0X75	VALUE="56700"
+			{
+			parsedField->SetFieldValueL(KWappSpeed56700);	
+			break;
+			}
+		case KWAPP_MSISDN_NO    :  //0X76	VALUE="MSISDN_NO"
+			{
+			parsedField->SetFieldValueL(KWappMsisdnNo);	
+			break;
+			}
+		case KWAPP_IPV4         :	//OX77	VALUE="IPV4"
+			{
+			parsedField->SetFieldValueL(KWappIpv4);	
+			
+			break;
+			}
+		case KWAPP_MSCHAP		:	//0x78  VALUE="MSCHAP"
+			{
+			parsedField->SetFieldValueL(KWappMSCHAP);
+			break;
+			}
+			
+		default:
+			User::Leave(KWappErrUnexpectedValue); // Unknown tag - can't process it
+		}
+
+	// If iCurrentCharacteristic is a general address type and NAME="BEARER". Then
+	//  set the current type flag to the correct type, so we know exactly  what we're dealing with
+	if (iCurrentCharacteristic==EWappAddressCharacteristic 
+					&& parsedField->FieldName().CompareF(KWappBearer)==0)
+		{
+		if (parsedField->FieldValue().CompareF(KWappGsmCsd)==0)
+			iCurrentCharacteristic =EWappGsmCsdCharacteristic;
+		else if (parsedField->FieldValue().CompareF(KWappGsmSms)==0)
+			iCurrentCharacteristic = EWappGsmSmsCharacteristic;
+		else if (parsedField->FieldValue().CompareF(KWappGsmUssd)==0)
+			iCurrentCharacteristic = EWappGsmUssdCharacteristic;
+		else if (parsedField->FieldValue().CompareF(KWappIS136Csd)==0)
+			iCurrentCharacteristic = EWappIS136CsdCharacteristic;
+		else if (parsedField->FieldValue().CompareF(KWappGprs)==0)
+			iCurrentCharacteristic = EWappGprsCharacteristic;
+		else 
+			User::Leave(KWappErrUnrecognised);
+		}
+	
+	// Got our Name and Value fields- check next byte - should be 0x01 =END
+	currentCharacter = GetNextMessageByteL();
+
+	if (currentCharacter != KWAPP_END_TAG) // Our PARM is not correctly terminated!
+		User::Leave(KWappErrNoTermination);
+	
+	// Check flag to see if parsed field should be added or not
+	if (addParsedField)
+		{
+		// Extracted the NAME and VALUE so create a container and append to our array
+		iParsedFieldArray->AppendL(parsedField);		
+		CleanupStack::Pop(parsedField);
+		}
+	else
+		{
+		CleanupStack::PopAndDestroy(parsedField);	
+		}
+	}
+//End of CMsvBIOWapAccessParser::ReadParmL()
+
+
+//	SettingsNamePresentL()  - Check if the NAME characteristic is defined.  if it isn't add 
+//							 a default one that is unique.  Use a base stem of "WAP Settings" and
+//							 append a suffix to it. The suffix is calculated by incrementing, until
+//							 a unique digit is found. 
+//
+void CMsvBIOWapAccessParser::SettingsNamePresentL()
+	{
+	TBool nameDefined = EFalse;		// Is a Name characteristic present?
+	TBool bearerPresent = EFalse;	// Is address characteristic present?
+
+	// Search  for the start of a NAME characteristic - i.e. Field Name="NAME"
+	TInt nFields = iParsedFieldArray->Count();
+
+	TInt loopCount=0;
+	while (loopCount < nFields && !nameDefined)
+		{
+		if (iParsedFieldArray->At(loopCount)->FieldName().CompareF(KWappCharName)==0)
+			{
+			// At start of a Name characteristic
+			// Make sure that we won't try checking past the end of the array
+			if (loopCount+1 < nFields) // NB loopCount started at zero
+				{
+				// Verify that this is followed by NAME parm - NAME token & a non NULL value
+				if (iParsedFieldArray->At(loopCount+1)->FieldName().CompareF(KWappName)==0)
+					{
+					if (iParsedFieldArray->At(loopCount+1)->FieldValue().Length()!=0)
+						nameDefined = ETrue;
+					}
+				}
+			}
+		loopCount++;
+		}
+
+	loopCount = 0;
+	while (loopCount < nFields)
+		{
+		// Beginning of an Address Characteristic? 
+		if (iParsedFieldArray->At(loopCount)->FieldName().CompareF(KWappCharAddress) ==0)
+			bearerPresent = ETrue; // Assume  all Parms are present- will leave later if not!
+		loopCount++;
+		}
+
+	if (nameDefined ==EFalse && bearerPresent)   // NAME characteristic not defined - add a default
+		{
+		TBuf<KCommsDbSvrMaxColumnNameLength> recordName;
+		HBufC*	nameBuffer = HBufC::NewLC(30);
+		TInt	currentRecord = 1;
+		TBool	nameExists = EFalse; 
+
+		TFileName fileName;
+		Dll::FileName(fileName);
+		TParse parse;
+		parse.Set(KWappResourceFile, &fileName, NULL);
+		fileName = parse.FullName();
+		BaflUtils::NearestLanguageFile(iFs, fileName);
+
+		RResourceFile resourceFile;
+	    resourceFile.OpenL(iFs, fileName);
+	    CleanupClosePushL(resourceFile);
+	    HBufC8* buffer = resourceFile.AllocReadLC(DEFAULT_WAP_SETTINGS_NAME);
+	    TResourceReader resourceReader;
+	    resourceReader.SetBuffer(buffer);
+	    TPtrC defaultSettingsName = resourceReader.ReadTPtrC();
+		CCDWAPAccessPointRecord *wapRecord = static_cast<CCDWAPAccessPointRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdWAPAccessPointRecord));
+		CleanupStack::PushL(wapRecord);
+		nameBuffer->Des().Format(defaultSettingsName, currentRecord);  // create our name string
+		while(!nameExists)
+			{
+			wapRecord->iRecordName.SetMaxLengthL(nameBuffer->Length());
+			wapRecord->iRecordName = *nameBuffer;				
+				
+			if(wapRecord->FindL(*iDBSession)) 		
+				{
+				++currentRecord;					
+				nameBuffer->Des().Format(defaultSettingsName, currentRecord); 
+				}
+			else 
+				nameExists = ETrue;				
+			}
+		CleanupStack::PopAndDestroy(wapRecord);
+
+		// Add characteristic header, then name and value to the parsed fields
+		AppendNameFieldL(KWappCharName);
+		AppendDataPairL(KWappName, nameBuffer->Des());
+		CleanupStack::PopAndDestroy(3, nameBuffer); // nameBuffer, resourceFile, buffer
+		}
+
+	}//END of SettingsNamePresentL()
+
+//	RestoreParsedDataL()			-  Restores CParsedField data into the array
+//
+//
+void CMsvBIOWapAccessParser::RestoreParsedDataL()
+	{
+	//	Assume that our server message context is correctly set to the Bio Msg entry	
+	iEntry.SetEntryL(iEntryId);
+	
+	// Has the entry been parsed,(iMtmData3 =1) or parsed & processed (iMtmData3 =2)
+	// If not leave with error code
+	if (   iEntry.Entry().MtmData3() != BIO_MSG_ENTRY_PARSED
+		&& iEntry.Entry().MtmData3() != BIO_MSG_ENTRY_PROCESSED)
+		{
+		iSmsParsed=EFalse;			// Entry has not been parsed yet no data to restore
+		User::Leave(KWappErrMsgUnparsed);
+		}
+
+	if(!iEntry.HasStoreL())
+		{
+		iSmsParsed=EFalse;			// Entry has no store -  not parsed yet?
+		User::Leave(KWappErrStoreNotFound);  
+		}
+	//Message has been parsed and data stored = restore it!
+	CMsvStore* store=iEntry.EditStoreL();
+	CleanupStack::PushL(store);
+	RestoreL(*store);
+	CleanupStack::PopAndDestroy();//store
+
+	//Now set a few key variables using the data in the iParsedFieldArray
+	TLex myLex;
+	if (iParsedFieldArray->At(0)->FieldName().CompareF(KWappXMLversion)==0)
+		{
+		myLex =iParsedFieldArray->At(0)->FieldName(); 
+		myLex.Mark();
+		myLex.Val(iWBXMLversionX10, EDecimal);
+		}
+	else
+		User::Leave(KWappErrMandatoryTagMissing);  // error- XML version is missing
+	
+	// Field at index=1 is PublicID - don't currently need this 
+	// Field at index=2 is Character Set - will present if XML version =1.1, but not for 1.0
+
+	if (iWBXMLversionX10==11)
+		{ // Have the Character Set
+		if (iParsedFieldArray->At(2)->FieldName().CompareF(KWappCharacterSet)==0 )
+			{
+			myLex =iParsedFieldArray->At(1)->FieldName();
+			myLex.Mark(); //Mark the start.  
+			myLex.Val(iCharacterSet, EHex);
+			}
+		}
+	else 
+		iCharacterSet=0;
+	}
+// End of function  CMsvBIOWapAccessParser::RestoreParsedDataL()
+
+// StoreParsedDataL()  - stores array of parsed data in a store - calls base class StoreL()
+// 
+void CMsvBIOWapAccessParser::StoreParsedDataL()
+	{
+	// Set to the current Entry id, create a store & save data
+	iEntry.SetEntryL(iEntryId);
+	CMsvStore* store=iEntry.EditStoreL();
+	CleanupStack::PushL(store);
+	StoreL(*store);
+	CleanupStack::PopAndDestroy();//store
+
+	// Set the parsed flag on the TMsvEntry
+	iEntry.SetEntryL(iEntryId);
+	TMsvEntry entry= iEntry.Entry();
+	entry.SetMtmData3(BIO_MSG_ENTRY_PARSED);
+
+	iEntry.ChangeL(entry);
+	}
+
+//
+//		ResetProcessVariablesL()-Resets array of bookmarks and recreates the objects mapping to CommDb Table s
+//
+//
+void CMsvBIOWapAccessParser::ResetProcessVariablesL()
+	{
+	// Re-set boolean flags
+	iGsmCsdData		= EFalse;
+	iGsmSmsData		= EFalse;
+	iGprsData		= EFalse;
+	iURLData		= EFalse;
+	iMMSURLData		= EFalse;
+	iNameData		= EFalse;
+	iIdData			= EFalse;
+	// Zero IDs
+	iRecordId = 0; 
+	iWapAccessPtID = 0;	
+	iWapLocation = 0; 
+	iWapChargeCard = 0;
+
+	iBookmarkList->ResetAndDestroy();
+
+	iWAPSettingsName.Set(TPtrC());  // Null the value in this descriptor
+
+	delete iGsmCsdWapIpTable;
+	iGsmCsdWapIpTable = NULL;
+	delete iGprsWapIpTable;
+	iGprsWapIpTable =NULL;
+	delete iWapIpISPTable;
+	iWapIpISPTable = NULL;
+	delete iWapSmsTable;
+	iWapSmsTable = NULL;
+	delete iWapGprsTable;
+	iWapGprsTable = NULL;
+	delete iModemInitString;
+	iModemInitString = NULL;
+	}
+
+// 
+// Read_mb_u_int32() -- Helper function that uses the TLex iSms to extract a 32-bit 
+//						integer encoded in a number of bytes. If Bit7 of the first
+//						byte is set, the number continues over into the next byte,
+//						and so on. If Bit7 is not set then it's the last byte.
+//
+TUint32  CMsvBIOWapAccessParser::Read_mb_u_int32L()
+	{
+	TUint32 decodedValue = 0;
+	TBool	completed =EFalse;
+
+	while(!completed)
+		{
+		TUint32 thisByte = (TUint) GetNextMessageByteL();  // cast the character returned by Get to a TUint32
+		if (decodedValue & 0x2000000)   // is Bit25 set? If so, bitshifting 7 places 
+			User::Leave(KWappErrOutsideBoundaries);	// left will cause overflow 		
+		
+		(decodedValue = decodedValue<<7); // assignment to keep compiler happy 
+								//shift current value 7 places to the left, i.e. *256
+
+		if ( (thisByte & KWAPP_MB_INT32_CONTINUATION) ) 
+			{ 
+			// bit 7 set, integer continues into next byte so keep processing
+			thisByte = thisByte & 0x7F; //	mask Bit7 by AND'ing with all other bits 
+									    // set to 1, i.e. 01111111 =0x7F
+			decodedValue += thisByte;
+			// leave completed set to EFalse
+			}
+		else    // bit 7 isn't set, processing's completed so set flag  
+			{
+			decodedValue += thisByte;
+			completed = ETrue;
+			}
+		}
+	return decodedValue;
+	}  
+
+//
+//		GetStringTableItemL()	- Returns the string contained within the string table starting
+//								  at the offset passed in as a parameter.
+//				
+HBufC* CMsvBIOWapAccessParser::ReadStringTableReferenceLC(TUint32 anOffset)
+	{
+	if (iStringTable ==NULL)
+		User::Leave(KWappErrStringTable);		// Making a call to an nonexistant object! 
+	TUint32 stringTableLength = iStringTable->Length();
+	if (stringTableLength<=0)					//Nothing to process, or worse, an error!
+		User::Leave(KWappErrOutsideBoundaries);	//Past end of table
+	if (anOffset >= stringTableLength)			// anOffset must be < last element of buffer								
+		User::Leave(KWappErrOutsideBoundaries);	// Last element must be NULL terminator!
+
+	TUint32 stringTableItem = anOffset; // Current element in iStringTable
+	TUint32 stringLength=0; // Length of string
+	while ( iStringTable->Des()[stringTableItem] !=KWAPP_STR_TERM)
+		{	
+		// increment through the String Table to first NULL terminator 
+		stringTableItem++;
+		if (stringTableItem > (TUint)iStringTable->Length())  // Cast to remove warning, Length >=0
+			User::Leave(KWappErrOutsideBoundaries);   // Problem -gone past the end of the descriptor 
+		stringLength++;
+		}	
+	// return a descriptor starting at the offset and up to the char before the NULL terminator
+
+	// Char Conversion
+	TPtrC data = iStringTable->Des().Mid(stringTableItem, stringTableLength-1);
+	HBufC* text = HBufC::NewLC(data.Length());
+	TPtr des(text->Des());
+	iCharsetConverter->ConvertL(data, des);
+	return text;
+	}
+
+
+/*
+Finds the end of the UCS2 string. Each character is represented by exactly 2bytes of data 
+According to WBXML version 1.0 
+"if a character encoding includes a NULL then that NULL character must be used as the termination character"
+Hence we are assuming that the end of the string is marked by two NULL bytes.
+*/
+void CMsvBIOWapAccessParser::ReadUCS2StringL()
+{
+	TBool endofinlinestring = EFalse;
+	TBool endoflexstring = EFalse; 
+	TBool foundNull;
+
+	while (!endoflexstring && !endofinlinestring)
+	{
+		foundNull = EFalse;
+		endoflexstring = iSms.Eos();
+
+		if (!endoflexstring)
+			{
+			if (iSms.Peek() == KWAPP_STR_TERM)
+				{
+				foundNull = ETrue;
+				}
+			
+			iSms.Inc();
+			if (iSms.Eos()) //check we haven't reached the end of the sms
+				User::Leave(KWappErrEOS);
+
+			else if (foundNull && iSms.Peek()== KWAPP_STR_TERM)
+				endofinlinestring = ETrue;
+			}
+		else
+			User::Leave(KWappErrEOS);
+	}
+	
+}
+
+
+
+/*
+According to WBXML version 1.0 
+"if a character encoding includes a NULL then that NULL character must
+ be used as the termination character"
+
+Finding the end of the ASCII string:
+ This is simply done as each character is represented by a maximum 
+ of 7 bits of data, hence each character is one byte only. 
+ Thus, it is assumed that the end of the string is marked by a NULL which in ASCII is 0x00
+
+  so the string "hi" would be represented as 
+  0x68 0x69 0x00
+
+Finding the end of the UTF-8 string. 
+ From RFC 2279:
+ "In UTF-8, characters are encoded using sequences of 1 to 6 octets.
+   The only octet of a "sequence" of one has the higher-order bit set to
+   0, the remaining 7 bits being used to encode the character value. In
+   a sequence of n octets, n>1, the initial octet has the n higher-order
+   bits set to 1, followed by a bit set to 0.  The remaining bit(s) of
+   that octet contain bits from the value of the character to be
+   encoded.  The following octet(s) all have the higher-order bit set to
+   1 and the following bit set to 0, leaving 6 bits in each to contain
+   bits from the character to be encoded.
+
+   The table below summarizes the format of these different octet types.
+   The letter x indicates bits available for encoding bits of the UCS-4
+   character value.
+
+   UCS-4 range (hex.)           UTF-8 octet sequence (binary)
+   0000 0000-0000 007F   0xxxxxxx
+   0000 0080-0000 07FF   110xxxxx 10xxxxxx
+   0000 0800-0000 FFFF   1110xxxx 10xxxxxx 10xxxxxx
+
+   0001 0000-001F FFFF   11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+   0020 0000-03FF FFFF   111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
+   0400 0000-7FFF FFFF   1111110x 10xxxxxx ... 10xxxxxx
+ "
+ ASCII values 0-127 are represented in UTF8 by one byte with the msb set to 0.
+
+ This means that no byte in a stream of bytes representing a (non NULL) character will ever be 0x00.
+ So there will only be one 0x00 in the string and this will represent the end of the string.
+
+ For example
+  the string of roman numerals "VIIIIII" where VIII is the first character and III is the second character
+  would be represented in UTF-8 as:
+
+  0xE2 0x85 0xA2 0xE2 0x85 0xA7 0x00
+
+ The single byte 0x00 is the NULL terminator representing the end of the string.
+*/
+void CMsvBIOWapAccessParser::ReadASCIIorUTF8StringL()
+{
+	while (!iSms.Eos() && iSms.Peek() !=KWAPP_STR_TERM /*0x00*/)
+		{
+		iSms.Inc();
+		}
+
+	if (iSms.Eos()) // End of the string! Other chars should follow
+			User::Leave(KWappErrEOS); 
+
+}
+
+/*
+because iSms is a TLex it is padded out and so 
+when parsing unicode strings you end up with unnecessary characters
+*/
+
+//HBufC* CMsvBIOWapAccessParser::RemovePadding()
+//{
+//}
+
+
+//
+//		ReadInlineStringL()	- Returns the string begining at the current position in the 
+//							  message. Increments TLex position until string termination found.
+//
+HBufC* CMsvBIOWapAccessParser::ReadInlineStringLC()
+	{
+	if (!iSms.Eos())//Mark the starting point of the string
+		iSms.Mark(); 
+	else			// End of the string! Can't proceed!
+		User::Leave(KWappErrEOS);
+
+		//find the end of the string by taking into accout how it is encoded
+	switch (iCharacterSet)
+		{
+		case KCharsetASCII:
+		case KCharsetUTF8:
+			ReadASCIIorUTF8StringL();
+			break;
+		case KCharsetUCS2:
+			ReadUCS2StringL();
+			break;
+		default:
+			User::Leave(KErrNotSupported);
+			break;
+		};
+	
+	//the end of the string has been found so mark it. 
+	TPtrC data =iSms.MarkedToken();
+	iSms.Inc(); //Increment up to the KWAPP_STR_TERM so next time we read the char after the end of the string
+	/*
+	Marked token is now converted to unicode 
+	for the purpose of applying to commdb for example. 
+	*/
+	
+	// Char Conversion
+	//for unicode parsing to remove unnecessary padding	
+	if (iCharacterSet == KCharsetUCS2)
+		{
+		HBufC* text = HBufC::NewMaxLC(data.Length() / 2);
+		TPtr destext(text->Des()); 
+
+		TInt	j = 0;
+		TInt	i = 1;
+
+		while (j < data.Length() / 2)
+			{
+			destext[j] = data[i];
+			i += 2;
+			j++;
+			}
+
+		return text;
+		}
+	else
+		{
+		HBufC* text = HBufC::NewMaxLC(data.Length());
+		TPtr destext(text->Des()); 
+
+		iCharsetConverter->ConvertL(data, destext);
+
+		return text;
+		}
+	}
+
+
+//
+//		AppendDataPairL()	- Appends a CParsedField containing data from the message, to the 
+//							  array of parsed fields (iParsedFieldsArray).
+//
+void CMsvBIOWapAccessParser::AppendDataPairL(const TDesC& aFieldName, const TDesC& aFieldValue)
+	{
+	// Appends a CParsedField object to iParsedFieldArray.
+	// Both fields have valid data
+	CParsedField* localData = new (ELeave) CParsedField;
+	CleanupStack::PushL(localData);
+	localData->SetFieldNameL(aFieldName);
+	localData->SetFieldValueL(aFieldValue);
+	CleanupStack::Pop();
+	iParsedFieldArray->AppendL(localData);
+	}
+
+//
+//		AppendNameFieldL()	- Appends a CParsedField containing just a Name from the message, 
+//							  to the array of parsed fields (iParsedFieldsArray).
+//
+void CMsvBIOWapAccessParser::AppendNameFieldL(const TDesC& aFieldName)
+	{
+	// Appends a CParsedField object to iParsedFieldArray.
+	// Only the Name field has valid data, the Value field is left NULL
+	CParsedField* localData = new (ELeave) CParsedField;
+	CleanupStack::PushL(localData);
+	localData->SetFieldNameL(aFieldName);
+	localData->SetFieldValueL(KNullDesC);  // Set to an empty descriptor
+	CleanupStack::Pop();
+	iParsedFieldArray->AppendL(localData);
+	}
+
+void CMsvBIOWapAccessParser::InsertDataPairL(const TDesC& aFieldName, const TDesC& aFieldValue, TInt anIndex)
+	{	
+	// check that the position is valid!  Leave if out of bounds
+	// Limits 0 - insert at front of array, iParsedData->Count() append to end
+	if (!(anIndex<= iParsedFieldArray->Count() && anIndex >= 0) )
+		User::Leave(KErrArgument);
+	CParsedField* localField = new (ELeave)CParsedField;
+	CleanupStack::PushL(localField);
+	localField->SetFieldNameL(aFieldName);
+	localField->SetFieldValueL(aFieldValue);
+	CleanupStack::Pop();
+	iParsedFieldArray->InsertL(anIndex, localField);
+	}
+
+TChar CMsvBIOWapAccessParser::GetNextMessageByteL()
+	{	
+	if (iSms.Eos())  // Error - unexpectedly reached the end of the TLex buffer!!!!!
+		User::Leave(KWappErrEOS);
+	return iSms.Get();
+	}
+
+TInt CMsvBIOWapAccessParser::LocateParsedFieldName(const TDesC& aFieldName, const TInt aStartIndex)
+	{
+	//Searches from a start pos'n, default=0, until either finds a match, or end of array
+	TInt  count=aStartIndex;
+	TBool nextCharacteristic =EFalse;
+	
+	//loop until end of the array, found the first match or found another Characteristic!
+	TInt nFields = iParsedFieldArray->Count();
+	while	(count < nFields &&			//	End of array?
+			(iParsedFieldArray->At(count)->FieldName().CompareF(aFieldName)  !=0) && //Match found?
+			!nextCharacteristic  )
+		{
+
+		if ( (count !=aStartIndex)  && (IsCharacteristicName(count)) )
+			// Not 1st first element of characteristic and found field for another
+			// characteristic- Must have reached next characteristic - stop looping
+			{
+			nextCharacteristic =ETrue;
+			}
+
+		++count;
+		}
+
+	if (count < nFields && !nextCharacteristic)    // found a match in the array, even if it is last element
+		return count;
+	else 
+		return KErrNotFound;  // Didn't find a match or reached next characteristic - flag the errror
+	}
+
+//
+//	DoProcessL()  - Workhorse for ProcessL function.  Extracts information from parsed field 
+//					array into separate objects. Writes settings to the COMMS DB, if 
+//					there is data for at least one bearer type. Saves any Bookmarks to file.
+//
+void CMsvBIOWapAccessParser::DoProcessL()
+	{
+	if (iGsmCsdData || iGsmSmsData || iGprsData) 
+		{
+		WriteDataToDBL();
+		}
+	WriteBookmarksToFileL();
+
+	if( iMMSURLData )
+		{
+		WriteMMSURLL();
+		}		
+
+	if (!iGprsData && !iGsmCsdData && !iGsmSmsData && !iMMSURLData && (iBookmarkList->Count()==0)) 
+		{
+		// No bearers, no bookmarks - must be a settings message - wouldn't be here otherwise 
+		if (iNameData && iURLData)   // iIDData optional
+			{
+			UpdateStartPageUrlL();   // update the URL of the start page in WAP table		
+			}
+		}
+		
+	}
+
+//
+//	PreProcessL -	goes through the fields in the array of parsed data, extracting information
+//					only extracts information for first of each of the 4 bearer types - i.e. max  
+//					of 4 entries in the ISP/WAP tables. Additional address characteristics are 
+//					ignored. 
+//
+void CMsvBIOWapAccessParser::PreProcessL()
+	{
+	TInt arrayPtr=0;   // current position in the array of ParsedFields
+
+	while (arrayPtr < iParsedFieldArray->Count())
+		{
+		// Check current field if characteristic - peek at next field -> bearer type
+					// GSM/CSD		- extract data from GSM/CSD Address characteristic
+					// GSM/SMS		- extract data from GSM/SMS Address characteristic
+					// GPRS			- extract data from GPRS Address characteristic
+					// GSM/USSD		- TO DO,  GSM/USSD Address characteristic unsupported
+					// IS136/CSD	- TO DO,  IS136/CSD Address characteristic unsupported 
+					// ID			- extract data from ID characteristic
+					// NAME			- extract data from NAME characteristic
+					// URL			- extract data from URL characteristic
+					// BOOKMARK		- extract Bookmark characteristic & append to Bookmark array
+		// Otherwise report an error
+
+		// Increment past WBXML Version, public ID or character set to the data we want
+		if ((iParsedFieldArray->At(arrayPtr)->FieldName().CompareF(KWappXMLversion) ==0) ||
+			(iParsedFieldArray->At(arrayPtr)->FieldName().CompareF(KWappPublicID) ==0)||
+			(iParsedFieldArray->At(arrayPtr)->FieldName().CompareF(KWappCharacterSet) ==0))
+		
+			arrayPtr++;	
+		else if	(iParsedFieldArray->At(arrayPtr)->FieldName().CompareF(KWappCharAddress) ==0)
+			{
+			// Stepped past first 3 fields & its an Address Characteristic
+			// So read the next line to determine type of bearer 
+
+			TPtrC addressValue;
+			arrayPtr++;			//increment to the next element 
+			
+			if (iParsedFieldArray->At(arrayPtr)->FieldName().CompareF(KWappBearer)==0) 
+				addressValue.Set(iParsedFieldArray->At(arrayPtr)->FieldValue());   // Note the bearer type
+			else
+				User::Leave(KWappErrMandatoryTagMissing); // Not a BEARER - error!
+
+			// Next - either extract the bearer data into the table objects, if this is the 
+			// first of this type, or skip past the data to the next characteristic. 
+			if ((addressValue.CompareF(KWappGsmCsd)==0)) 
+				{
+				// GSM/CSD Characteristic so add data to ISP and WAP table objects, or go to next characteristic
+				ExtractBearerDataL(arrayPtr); 
+				}
+			
+			else if ((addressValue.CompareF(KWappGsmSms)==0)) 
+				{
+				// GSM/CSD Characteristic so either add data to ISP and WAP table objects, or skip past to next characteristic
+				ExtractBearerDataL(arrayPtr);
+				}
+
+			else if (addressValue.CompareF(KWappGsmUssd)==0)
+				{
+				User::Leave(KWappErrNotSupported);  // Don't support these at the moment!
+
+		//		ExtractBearerDataL(arrayPtr); //Add data to ISP and WAP table objects
+				}
+
+			else if (addressValue.CompareF(KWappIS136Csd)==0)
+				{
+				User::Leave(KWappErrNotSupported);  // Don't do these at the moment!
+		//		ExtractBearerDataL(arrayPtr); //Add data to ISP and WAP table objects 
+				}
+			else if (addressValue.CompareF(KWappGprs)==0)
+				{
+				ExtractBearerDataL(arrayPtr);
+				}
+			else 
+				User::Leave(KWappErrUnrecognised); // Value doesn't match any of the known ones
+			}
+
+		// Check if it's a  URL characteristic
+		else if (iParsedFieldArray->At(arrayPtr)->FieldName().CompareF(KWappCharURL) ==0)
+			{ 
+			// The URL Characteristic has NO PARM elements only a value
+
+			if (iURLData == EFalse)  // Not been set previously
+				{
+				// Use the first instance of a URL - set it to the characteristic value even if it's null 
+				iUrl.Set(iParsedFieldArray->At(arrayPtr)->FieldValue()); 
+				iURLData = ETrue;
+				}
+			arrayPtr++;
+			}
+
+		// Check if it's a Name Characteristic
+		else if (iParsedFieldArray->At(arrayPtr)->FieldName().CompareF(KWappCharName) ==0)
+			{ 
+			// The NAME Characteristic should have EXACTLY 1 PARM element
+			arrayPtr++; // increment to the Parm in this characteristic
+			if (arrayPtr == iParsedFieldArray->Count() || 
+				iParsedFieldArray->At(arrayPtr)->FieldName().CompareF(KWappName)!=0) 
+				User::Leave(KWappErrBadMessage);
+			
+			// Initialise the Settings Name variable if it hasn't been set
+			if (iWAPSettingsName.Length()==0)    
+				{
+				// Use the first instance of NAME - set it to the value even if it's null 
+				iWAPSettingsName.Set(iParsedFieldArray->At(arrayPtr)->FieldValue());
+				iNameData = ETrue;
+				}
+			
+			while ( arrayPtr< iParsedFieldArray->Count() && !(IsCharacteristicName(arrayPtr)) )
+					arrayPtr++;   // increment to beginning of next characteristic
+			
+			}
+
+		//Is it a BOOKMARK ?  Bookmarks must contain EXACTLY 2 PARM elements - NAME then URL 
+		else if (iParsedFieldArray->At(arrayPtr)->FieldName().CompareF(KWappCharBookmark)==0)
+			{  
+			arrayPtr++;							
+			ExtractBookmarkDataL(arrayPtr);
+			}
+
+		// Is it an ID characteristic ?
+		else  if (iParsedFieldArray->At(arrayPtr)->FieldName().CompareF(KWappCharID) ==0)
+			{  
+			arrayPtr++;		//Increment to the NAME Parm
+
+			// End of array or PARM Type != NAME
+			if (arrayPtr == iParsedFieldArray->Count() || 
+				iParsedFieldArray->At(arrayPtr)->FieldName().CompareF(KWappName)!=0)
+				User::Leave(KWappErrBadMessage);
+
+			if (iIdData == EFalse)
+				{
+				// Use the 1st instance of an ID - set to value even if it's null!
+				iID.Set(iParsedFieldArray->At(arrayPtr)->FieldValue());
+				iIdData = ETrue;
+				}
+
+			while ( arrayPtr< iParsedFieldArray->Count() && !(IsCharacteristicName(arrayPtr)) )
+					arrayPtr++;   // increment to beginning of next characteristic
+ 			}
+		else if(iParsedFieldArray->At(arrayPtr)->FieldName().CompareF(KWappCharMMSURL) ==0)
+			{
+			// The MMSURL Characteristic has NO PARM elements only a value
+
+			if (iMMSURLData == EFalse)  // Not been set previously
+				{
+				// Use the first instance of a URL - set it to the characteristic value even if it's null 
+				iMMSUrl.Set(iParsedFieldArray->At(arrayPtr)->FieldValue()); 
+				iMMSURLData = ETrue;
+				}
+
+			arrayPtr++; // Increment to the next element in the array
+			}
+
+		else // Unrecognised characteristic token
+			User::Leave(KWappErrUnrecognised);
+		}
+	}
+// END of function  CMsvBIOWapAccessParser::PreProcessL()
+
+//
+//	ExtractBearerDataL()	-  
+//
+//			Called by PreProcessL when it finds an address bearer type.  Uses the reference to 
+//			the current position in iParsedFieldArray to extract info to insert into CWapTableData 
+//			and CIspTableData objects. Increment the index position as the function scans
+//			through the iParsedFieldArray - ensures the value in calling function is correct. 
+//
+void CMsvBIOWapAccessParser::ExtractBearerDataL(TInt& aCurrentPos)
+	{
+	
+	TWappBearerType currentBearer = EWappUnknownBearer;
+
+	// local flags - 
+	// For all address characteristics, only process 1st instance of each parm type - ignore the rest
+	TBool bearer			= EFalse;
+	TBool proxy				= EFalse;
+	TBool port				= EFalse;
+	TBool csdDialstring		= EFalse;
+	TBool pppAuthType		= EFalse;
+	TBool pppAuthName		= EFalse;
+	TBool pppAuthSecret		= EFalse;
+	TBool pppLoginType		= EFalse;
+	TBool csdCallType		= EFalse;
+	TBool csdCallSpeed		= EFalse;
+	TBool pxAuthName		= EFalse;
+	TBool pxAuthSecret		= EFalse;
+	TBool pxLoginType		= EFalse;
+	TBool ispName			= EFalse;
+	TBool smsSMSCAddr		= EFalse;
+//	TBool ussdServiceCode	= EFalse;  //Currently not used - will be needed if GSM/USSD supported
+
+	TInt arrayEnd  = iParsedFieldArray->Count();
+	TCsdCallType  callType =EAnalogue;
+	TCsdCallSpeed callSpeed =EAutobauding;
+
+	// First check - current parm  MUST  BE A BEARER
+	// Following Parms can be in any order, but the first must be a BEARER.
+
+	if (iParsedFieldArray->At(aCurrentPos)->FieldName().CompareF(KWappBearer) !=0)
+		User::Leave(KWappErrMandatoryTagMissing);   // First Parm is not a BEARER - big problem!!
+
+
+	while ( aCurrentPos< arrayEnd &&  // Stop checking if past the array end, or next value
+			!(IsCharacteristicName(aCurrentPos))  )     // is another Characteristic, ie.  address, URL, Bookmark, ID or Name
+		{ 
+		TPtrC fieldName = iParsedFieldArray->At(aCurrentPos)->FieldName();
+		if (IsValidTokenNameL(aCurrentPos) !=KErrNone) //Validate this Parm Name
+			User::Leave(KWappErrUnrecognised);		   
+		
+		// Check the next parsed field data -  BEARER type
+
+		if (fieldName.CompareF(KWappBearer) ==0)
+			{
+			//Set the current local bearer type, & then bearer variable
+			TPtrC currentValue = iParsedFieldArray->At(aCurrentPos)->FieldValue();
+			if (currentValue.CompareF(KWappGsmCsd) ==0)
+				{
+				if (!bearer)   // first time here!
+					{
+					if (!iGsmCsdData) // No previous GSM bearers
+						{
+						iGsmCsdWapIpTable		= CWapIpBearerData::NewL();   // Create the required table mapping objects
+						iWapIpISPTable	= CIspTableData::NewL();
+						currentBearer = EWappGsmCsdBearer;// set local bearer type variable
+						bearer = ETrue;  // ignore further BEARER's only for this characteristic
+						}
+					else // Already got data increment to next characteristic and return
+						{
+						while ( aCurrentPos< arrayEnd && !(IsCharacteristicName(aCurrentPos)) )
+							aCurrentPos++;   // increment to beginning of next characteristic
+						return;				 // return to PrePocessL
+						}
+					}
+				}
+
+			else if (currentValue.CompareF(KWappGsmSms) ==0)
+				{
+				if (!bearer)  // haven't set the bearer type yet,  ignore all after first
+					{
+					if (!iGsmSmsData)  // No previous SMS bearers
+						{
+						iWapSmsTable =  CWapSmsBearerData::NewL();
+						currentBearer =EWappGsmSmsBearer;
+						bearer = ETrue;			// ignore any further BEARERs in this Characteristic 
+						}
+					else   // Already got bearer data  goto next characteristic & return
+						{
+						while ( aCurrentPos< arrayEnd && !(IsCharacteristicName(aCurrentPos)) )
+							aCurrentPos++;  // increment to beginning of next characteristic
+						return;				// return to PrePocessL
+						}
+					}
+				}
+			
+			else if (currentValue.CompareF(KWappGsmUssd) ==0)
+				{
+				currentBearer =EWappGsmUssdBearer;
+				//NB   Add support for USSD bearer here when required
+				// NOTE - must consider proxy & proxy type with USSD!
+				User::Leave(KWappErrNotSupported);
+				}
+			
+			else if (currentValue.CompareF(KWappIS136Csd) ==0)
+				{
+				currentBearer =EWappIS136CsdBearer;
+				//NB  Add support for IS 136 when required
+				// NOTE - will it be the same as for GSM/CSD ?
+				User::Leave(KWappErrNotSupported);
+				}
+			else if (currentValue.CompareF(KWappGprs) ==0)
+				{
+				if (!bearer)   // first time here!
+					{
+					if (!iGprsData) // No previous bearers
+						{
+						iGprsWapIpTable		= CWapIpBearerData::NewL();   // Create the required table mapping objects
+						iWapGprsTable =  CWapGprsBearerData::NewL();
+						iWapIpISPTable = CIspTableData::NewL();
+						currentBearer = EWappGprsBearer;// set local bearer type variable
+						bearer = ETrue;  // ignore further BEARER's only for this characteristic
+						}
+					else // Already got bearer data, increment to next characteristic and return
+						{
+						while ( aCurrentPos< arrayEnd && !(IsCharacteristicName(aCurrentPos)) )
+							aCurrentPos++;   // increment to beginning of next characteristic
+						return;				 // return to PrePocessL
+						}
+					}
+				}
+			else 
+				User::Leave(KWappErrUnrecognised);   // Unknown bearer type - Help!!!!
+			}
+
+		//Check for the PROXY characteristics - String used to set Table Data
+	
+		// CSD proxy value into		iIspTable::iGateway	    -  goes in   ISP_IP_GATEWAY 
+		//							iWapTable::iGatewayAddr	-  goes into WAP_GATEWAY_ADDRESS
+		// SMS proxy value into		iWapTable::iGatewayAddr	-  goes into WAP_GATEWAY_ADDRESS
+			
+		// NB If support for USSD, or IS136 required, add additional code here.
+		else if (fieldName.CompareF(KWappProxy) ==0)
+			{
+			if(!proxy) // First PROXY for this characteristic
+				{
+				switch(currentBearer)
+					{
+					case EWappGsmSmsBearer:
+						iWapSmsTable->iGatewayAddr.Set(iParsedFieldArray->At(aCurrentPos)->FieldValue());
+						break;
+					case EWappGsmCsdBearer:
+						iGsmCsdWapIpTable->iGatewayAddr->SetAddrL(iParsedFieldArray->At(aCurrentPos)->FieldValue());
+						iWapIpISPTable->iGateway->SetAddrL(iParsedFieldArray->At(aCurrentPos)->FieldValue());
+						break;
+					case EWappGprsBearer:
+						iGprsWapIpTable->iGatewayAddr->SetAddrL(iParsedFieldArray->At(aCurrentPos)->FieldValue());
+						iWapGprsTable->iGatewayAddr->SetAddrL(iParsedFieldArray->At(aCurrentPos)->FieldValue());
+						break;
+					default: 	
+						User::Leave(KWappErrUnrecognised); // Unrecognised currentBearer
+					}
+				proxy = ETrue;
+				}
+			}
+
+
+		//Check for the PORT characteristics - first encounter set it, ignore it afterwards
+		else if ((fieldName.CompareF(KWappPort)==0) &&  !port)   
+			{   
+			// Record that we've checked a port value - should be one of 4 values!
+			
+			if (  (iParsedFieldArray->At(aCurrentPos)->FieldValue().CompareF(KWappPort9200) ==0)
+				||(iParsedFieldArray->At(aCurrentPos)->FieldValue().CompareF(KWappPort9201) ==0) 
+				||(iParsedFieldArray->At(aCurrentPos)->FieldValue().CompareF(KWappPort9202) ==0)
+				||(iParsedFieldArray->At(aCurrentPos)->FieldValue().CompareF(KWappPort9203) ==0))
+			
+				{
+				if (currentBearer == EWappGsmSmsBearer)
+					iWapSmsTable->iPort.Set(iParsedFieldArray->At(aCurrentPos)->FieldValue());
+				else if (currentBearer == EWappGsmCsdBearer)
+					iGsmCsdWapIpTable->iPort.Set(iParsedFieldArray->At(aCurrentPos)->FieldValue());
+				else if (currentBearer == EWappGprsBearer)
+					iGprsWapIpTable->iPort.Set(iParsedFieldArray->At(aCurrentPos)->FieldValue());
+				}
+			else
+				{
+				if (currentBearer == EWappGsmSmsBearer)
+					iWapSmsTable->iPort.Set(KWappPort9200);
+				else if (currentBearer == EWappGsmCsdBearer)
+					iGsmCsdWapIpTable->iPort.Set(KWappPort9200);
+				else if (currentBearer == EWappGprsBearer)
+					iGprsWapIpTable->iPort.Set(KWappPort9200);
+				}
+			port = ETrue;
+			}
+
+
+// ******* Following group are for GSM/CSD & IS136/CSD - GSM/SMS and GSM/USSD follow after ********
+
+		//	Is it a CSD_DIALSTRING? 
+		else if (fieldName.CompareF(KWappCsdDial)==0)
+			{
+			// Must be either GSM/CSD or IS136/CSD
+			if ( (currentBearer != EWappGsmCsdBearer) &&
+				  (currentBearer != EWappIS136CsdBearer) )
+				  User::Leave(KWappErrUnexpectedValue);
+			else if (!csdDialstring)
+				{
+				iWapIpISPTable->iDefaultPhoneNum.Set(iParsedFieldArray->At(aCurrentPos)->FieldValue());
+				csdDialstring=ETrue;
+				}
+			}
+
+		//	Check for PPP_AUTHTYPE 
+		//  Now don't set the iIFName - always "ppp" & this protocol takes care of rest
+		else if (fieldName.CompareF(KWappPPPAuthType)==0 && !pppAuthType)
+			{
+			if(currentBearer==EWappGprsBearer)
+				{
+				if(iParsedFieldArray->At(aCurrentPos)->FieldValue().CompareF(KWappPAP)==0)
+					iWapGprsTable->iPlainTextAuthDisabled = EFalse;
+				else 
+					iWapGprsTable->iPlainTextAuthDisabled = ETrue;
+				}
+			// set the flag so we don't check again
+			pppAuthType =ETrue;
+			}
+
+		//	Check if its a PPP_AUTHNAME
+		else if (fieldName.CompareF(KWappPPPAuthName)==0)
+			{
+			if (!pppAuthName)
+				{
+				switch(currentBearer)
+					{
+					case EWappGsmCsdBearer:
+					case EWappIS136CsdBearer:
+						iWapIpISPTable->iLoginName.Set(iParsedFieldArray->At(aCurrentPos)->FieldValue());
+						break;
+					case EWappGprsBearer:
+						iWapGprsTable->iLoginName.Set(iParsedFieldArray->At(aCurrentPos)->FieldValue());
+						break;
+					default:
+						// SMS, USSD and GPRS don't have CSD authentication names
+						User::Leave(KWappErrUnexpectedValue); 
+					}
+				pppAuthName = ETrue;
+				}
+			}
+
+		//	Is it PPP_AUTHSECRET?
+		else if (fieldName.CompareF(KWappPPPAuthSecret)==0 )
+			{
+
+			if (!pppAuthSecret)
+				{
+				switch(currentBearer)
+					{
+					case EWappGsmCsdBearer:
+					case EWappIS136CsdBearer:
+						iWapIpISPTable->iLoginPass.Set(iParsedFieldArray->At(aCurrentPos)->FieldValue());
+						break;
+					case EWappGprsBearer:
+						iWapGprsTable->iLoginPass.Set(iParsedFieldArray->At(aCurrentPos)->FieldValue());
+						break;
+					default:
+						// SMS, GPRS & USSD don't have authentication type
+						User::Leave(KWappErrUnexpectedValue);
+					}
+				pppAuthSecret = ETrue;
+				}
+			}
+		//	Is it a PPP_LOGIN_TYPE? 
+		else if (fieldName.CompareF(KWappPPPLoginType)==0)
+			{
+			if(!pppLoginType)
+				{
+				const TDesC& val = iParsedFieldArray->At(aCurrentPos)->FieldValue();
+				switch(currentBearer)
+					{
+					case EWappGsmCsdBearer:
+					case EWappIS136CsdBearer:
+						{
+						if(val.CompareF(KWappAuthAutomatic)==0)
+							{
+							iWapIpISPTable->iIFPromptForAuthentication = EFalse;
+							iWapIpISPTable->iPromptForLoginDetails = EFalse;
+							}
+						else
+							{
+							iWapIpISPTable->iIFPromptForAuthentication = ETrue;
+							iWapIpISPTable->iPromptForLoginDetails = ETrue;
+							}
+						}
+						break;
+					case EWappGprsBearer:
+						{
+						if(val.CompareF(KWappAuthAutomatic)==0)
+							iWapGprsTable->iIFPromptForAuth = EFalse;
+						else
+							iWapGprsTable->iIFPromptForAuth = ETrue;
+						}
+						break;
+					default:
+						User::Leave(KWappErrUnexpectedValue);
+					}
+				}
+			pppLoginType = ETrue;
+			}
+
+		//	Is it a CSD_CALLTYPE? 
+		else if (fieldName.CompareF(KWappCsdCallType)==0)
+			{
+			// ONLY  GSM/CSD bearer has call types
+			if ( (currentBearer !=  EWappGsmCsdBearer) )
+				  User::Leave(KWappErrUnexpectedValue);
+
+			else if (!csdCallType)
+				{
+				// Can have values ANALOGUE (don't set  nothing) & ISDN (set modem init string)
+				if (iParsedFieldArray->At(aCurrentPos)->FieldValue().CompareF(KWappISDN)==0)
+					{
+					// TODO implement this function when Symbian know device specs
+					SetModemInitStringL(); 
+					callType = EIsdn;
+					}
+				else if ((iParsedFieldArray->At(aCurrentPos)->FieldValue().CompareF(KWappAnalogue)==0))
+					{
+					callType = EAnalogue;
+					}
+				else
+					callType = EAnalogue;  // Not recognised so set to default of ANALOGUE
+				csdCallType =ETrue;
+				}
+			}
+
+		//Check if its a CSD_CALLSPEED
+		else if (fieldName.CompareF(KWappCsdCallSpeed)==0)
+			{
+			// ONLY CSD bearer has call speed - anything else is an error
+			if  (currentBearer !=  EWappGsmCsdBearer)
+				  User::Leave(KWappErrUnexpectedValue);
+			else if (!csdCallSpeed)
+				{
+				TPtrC value = iParsedFieldArray->At(aCurrentPos)->FieldValue();
+				// Set the local variable for callspeed - will set the iIspTable value at end of fn
+				if (value.CompareF(KWappSpeedAuto)==0)
+					callSpeed = EAutobauding ; // Auto speed select - device chooses
+				else if (value.CompareF(KWappSpeed9600)==0)
+					callSpeed = E9600baud;
+				else if (value.CompareF(KWappSpeed14400)==0)
+					callSpeed = E14400baud;
+				else if (value.CompareF(KWappSpeed19200)==0)
+					callSpeed = E19200baud;
+				else if (value.CompareF(KWappSpeed28800)==0)
+					callSpeed = E28800baud;
+				else if (value.CompareF(KWappSpeed38400)==0)
+					callSpeed = E38400baud;
+				else if (value.CompareF(KWappSpeed43200)==0)
+					callSpeed = E43200baud;
+				else if (value.CompareF(KWappSpeed56700)==0)
+					callSpeed = E57600baud;
+				else 
+					callSpeed = EAutobauding;// Set to the default of AUTO 
+
+				csdCallSpeed =ETrue;
+				}
+			}
+
+		//	Check if its a PROXY_AUTHNAME - must be CSD or GPRS
+		else if (fieldName.CompareF(KWappProxyAuthName)==0 )
+			{
+			switch(currentBearer)
+				{
+				case EWappGsmCsdBearer:
+				case EWappIS136CsdBearer:
+					if (!pxAuthName)
+						{
+						iGsmCsdWapIpTable->iProxyAuthName.Set(iParsedFieldArray->At(aCurrentPos)->FieldValue());
+						pxAuthName =ETrue;
+						}
+					break;
+				case EWappGprsBearer:
+					if (!pxAuthName)
+						{
+						iGprsWapIpTable->iProxyAuthName.Set(iParsedFieldArray->At(aCurrentPos)->FieldValue());
+						pxAuthName =ETrue;
+						}
+					break;
+				default:
+					User::Leave(KWappErrUnexpectedValue);
+				}
+			}
+
+		//	Is it a PROXY_AUTHSECRET?  
+		else if (fieldName.CompareF(KWappProxyAuthSecret)==0)
+			{
+			switch(currentBearer)
+				{
+				case EWappGsmCsdBearer:
+				case EWappIS136CsdBearer:
+					if (!pxAuthSecret)
+						{
+						iGsmCsdWapIpTable->iProxyAuthSecret.Set(iParsedFieldArray->At(aCurrentPos)->FieldValue());
+						pxAuthSecret =ETrue;
+						}
+					break;
+				case EWappGprsBearer:
+					if (!pxAuthSecret)
+						{
+						iGprsWapIpTable->iProxyAuthSecret.Set(iParsedFieldArray->At(aCurrentPos)->FieldValue());
+						pxAuthSecret =ETrue;
+						}
+					break;
+				default:
+					User::Leave(KWappErrUnexpectedValue);
+				}
+			}
+
+		// Is it a PROXY_LOGIN_TYPE?
+		
+		else if (fieldName.CompareF(KWappProxyLoginType)==0)
+			{
+			//We just set the variable in the mapping object for the WAP IP Bearer Table. Don't do anything with it yet.
+			switch(currentBearer)
+				{
+				case EWappGsmCsdBearer:
+				case EWappIS136CsdBearer:
+					if (!pxAuthSecret)
+						{
+						if (iParsedFieldArray->At(aCurrentPos)->FieldValue().CompareF(KWappAuthAutomatic))
+							iGsmCsdWapIpTable->iProxyUseAutoLogin = ETrue;
+						else
+							iGsmCsdWapIpTable->iProxyUseAutoLogin = EFalse;
+						}
+					break;
+				case EWappGprsBearer:
+					if (!pxAuthSecret)
+						{
+						if (iParsedFieldArray->At(aCurrentPos)->FieldValue().CompareF(KWappAuthAutomatic))
+							iGprsWapIpTable->iProxyUseAutoLogin = ETrue;
+						else
+							iGprsWapIpTable->iProxyUseAutoLogin = EFalse;
+						}
+					break;
+				default:
+					User::Leave(KWappErrUnexpectedValue);
+				}
+
+
+			pxLoginType = ETrue;
+			}
+
+
+		//  Is it a ISP _NAME element?
+		else if (fieldName.CompareF(KWappISP)==0)
+			{
+			// Must be a CSD or Grps bearer
+			if ( (currentBearer !=  EWappGsmCsdBearer) &&
+				  (currentBearer  != EWappIS136CsdBearer) &&
+				  (currentBearer  != EWappGprsBearer)   )
+				  User::Leave(KWappErrUnexpectedValue);
+			else if (!ispName)
+				{
+				iWapIpISPTable->iISPDescription.Set(iParsedFieldArray->At(aCurrentPos)->FieldValue());
+				ispName =ETrue;
+				}			
+			} 
+
+
+// ******************  Following are for GSM/SMS settings  *********************
+		else if (fieldName.CompareF(KWappSMSCAddress)==0)
+			{
+			if (currentBearer  !=  EWappGsmSmsBearer) 
+				User::Leave(KWappErrUnexpectedValue);// Only SMS has a SMSC address - error condition
+			else if (!smsSMSCAddr)
+				{
+				iWapSmsTable->iWapServiceAddr.Set(iParsedFieldArray->At(aCurrentPos)->FieldValue());
+				smsSMSCAddr = ETrue;
+				}
+			}
+
+		//Check for PROXY_TYPE characteristic
+
+		// TO DO When/If USSD support is required! Add it here
+		// Need to know how to set Addressing Scheme for USSD & CSD/SMS/etc!!!!!
+		// Currently only alter value of dummy variable to keep the compiler happy
+		else if (fieldName.CompareF(KWappProxyType) ==0)
+			{
+			// Must be a USSD or GPRS bearer type - otherwise error!
+			if (currentBearer == EWappGsmUssdBearer) 
+				{
+				// NB If USSD support req'd,set the Addressing type here. NB Not yet defined in CommDb!
+				}
+			else if(currentBearer == EWappGprsBearer)
+				{
+				if(iParsedFieldArray->At(aCurrentPos)->FieldValue().CompareF(KWappIpv4)!=0)
+					User::Leave(KWappErrUnrecognised);
+				}
+			else
+				User::Leave(KWappErrUnrecognised);
+			}
+
+		//  Check for USSD service code
+		else if (fieldName.CompareF(KWappUSSDCode)==0)
+			{
+			if (currentBearer  == EWappGsmUssdBearer)
+				{  
+				// NB - If USSD support req'd, set the Service Centre Address here!
+				}
+			else 
+				User::Leave(KWappErrUnrecognised); // Not a USSD address, so shouldn't be here - error
+			}
+
+		// Access point is GPRS only
+		else if (fieldName.CompareF(KWappAccessPointName)==0)
+			{
+			if (currentBearer  == EWappGprsBearer)
+				{
+				iWapGprsTable->iAccessPointName.Set(iParsedFieldArray->At(aCurrentPos)->FieldValue());
+				}
+			else
+				User::Leave(KWappErrUnrecognised); // Shouldn't have a GPRS address if we aren't GPRS!
+			}
+
+		aCurrentPos++;
+		}// END of the While loop
+
+	if (currentBearer == EWappGsmCsdBearer)
+		{
+		if (!iGsmCsdData)
+			{
+			if (!pppLoginType) 
+				{
+				// Login type not set so determine value for whether login and authorisation set
+				if (iWapIpISPTable->iLoginName.Length()!=0 && iWapIpISPTable->iLoginPass.Length()!=0)
+					{
+					iWapIpISPTable->iPromptForLoginDetails =EFalse;
+					iWapIpISPTable->iIFPromptForAuthentication =EFalse;
+					}
+				}
+			if (! pxLoginType)
+				if (iGsmCsdWapIpTable->iProxyAuthName.Length()!=0 && iGsmCsdWapIpTable->iProxyAuthSecret.Length()!=0)
+					{
+					iGsmCsdWapIpTable->iProxyUseAutoLogin = ETrue;
+					}
+	
+			// Set the iIspTable->iCsdCallSpeed member -  need the calltype and the callspeed values
+			if (callType == EAnalogue)
+				{
+				switch (callSpeed)
+					{
+					case EAutobauding:
+						iWapIpISPTable->iCallSpeed = RMobileCall::ESpeedAutobauding;
+						iWapIpISPTable->iCallDataProtocol = RMobileCall::EProtocolV34;
+						break;
+					case E9600baud:
+						iWapIpISPTable->iCallSpeed = RMobileCall::ESpeed9600;
+						iWapIpISPTable->iCallDataProtocol = RMobileCall::EProtocolV32;
+						break;
+					case E14400baud:
+						iWapIpISPTable->iCallSpeed = RMobileCall::ESpeed14400;
+						iWapIpISPTable->iCallDataProtocol = RMobileCall::EProtocolV34;
+						break;
+					case E19200baud:
+						iWapIpISPTable->iCallSpeed =RMobileCall::ESpeed19200;
+						iWapIpISPTable->iCallDataProtocol = RMobileCall::EProtocolV34;
+						break;
+					case E28800baud:
+						iWapIpISPTable->iCallSpeed =RMobileCall::ESpeed28800;
+						iWapIpISPTable->iCallDataProtocol = RMobileCall::EProtocolV34;
+						break;
+					case E38400baud:
+					case E43200baud:
+					case E57600baud:
+						iWapIpISPTable->iCallSpeed = RMobileCall::ESpeedAutobauding;
+						iWapIpISPTable->iCallDataProtocol = RMobileCall::EProtocolV34;
+						break;
+					default:  //SHOULD be one of the above!
+						iWapIpISPTable->iCallSpeed = RMobileCall::ESpeedAutobauding;
+						iWapIpISPTable->iCallDataProtocol = RMobileCall::EProtocolV34;
+						break;
+					}
+				}
+			else if (!iGsmCsdData && callType == EIsdn)
+				{
+				iWapIpISPTable->iCallDataProtocol = RMobileCall::EProtocolV110;
+				switch (callSpeed)
+					{
+					case EAutobauding:				
+						iWapIpISPTable->iCallSpeed = RMobileCall::ESpeedAutobauding;
+					break;
+					case E9600baud:
+						iWapIpISPTable->iCallSpeed = RMobileCall::ESpeed9600;
+						break;
+					case E14400baud:
+						iWapIpISPTable->iCallSpeed =RMobileCall::ESpeed14400;
+						break;
+					case E19200baud:
+						iWapIpISPTable->iCallSpeed =RMobileCall::ESpeed19200;
+						break;
+					case E28800baud:
+						iWapIpISPTable->iCallSpeed =RMobileCall::ESpeed28800;
+						break;
+					case E38400baud:
+						iWapIpISPTable->iCallSpeed =RMobileCall::ESpeed38400;
+						break;
+					case E43200baud:
+						iWapIpISPTable->iCallSpeed =RMobileCall::ESpeed48000;
+						break;
+					case E57600baud:
+						iWapIpISPTable->iCallSpeed = RMobileCall::ESpeed56000;
+						break;
+					default:  //SHOULD be one of the above!
+						iWapIpISPTable->iCallSpeed = RMobileCall::ESpeedAutobauding;
+						break;
+					}
+				}
+			else
+				User::Leave(KWappErrUnrecognised); //Unrecognised value for calltype - error
+			}
+		iGsmCsdData = ETrue;
+		}
+
+	else if (currentBearer == EWappGsmSmsBearer)
+		iGsmSmsData = ETrue;
+	else if(currentBearer == EWappGprsBearer)
+		{
+		if (!pppLoginType)
+			{
+			if (iWapGprsTable->iLoginName.Length() > 0 && iWapGprsTable->iLoginPass.Length() > 0)
+				iWapGprsTable->iIFPromptForAuth =EFalse;
+			}
+		iGprsData = ETrue;
+		}
+
+	}
+//  End of function  CMsvBIOWapAccessParser::ExtractBearerDataL()
+
+//
+//	ExtractBookmarkDataL() - 
+//			Extracts bookmark from parsed data.  Adds default if name field is not
+//			set.  Discards the Bookmark if URL field is blank (ie nothing added to Bookmark 
+//			List) NB exactly 2 PARMs in a bookmark, NAME & URL, any order.
+//	
+void CMsvBIOWapAccessParser::ExtractBookmarkDataL(TInt& aIndex)
+	{
+	TPtrC tempPtr;
+	TBool foundName = EFalse;
+	TBool foundURL = EFalse;
+	TInt  parmsChecked = 0;
+
+	HBufC* bookmarkName = NULL;
+	HBufC* bookmarkURL = NULL;
+
+	// Should be set to the next parm in the Bookmark  NOTE: Can't properly check that 
+	// an Empty Name or URL Parsed field is not the start of another characteristic
+	while (aIndex < iParsedFieldArray->Count() && !IsCharacteristicName(aIndex))  
+		{
+		// check token is correct - copy NAME 
+		if (parmsChecked <2 && iParsedFieldArray->At(aIndex)->FieldName().CompareF(KWappName) ==0) 
+			{
+			if (foundName ==EFalse)
+				{
+				tempPtr.Set(iParsedFieldArray->At(aIndex)->FieldValue());
+				if (tempPtr.Length()==0)
+					tempPtr.Set(KWappDefaultBMName);
+				bookmarkName = tempPtr.AllocL();
+				CleanupStack::PushL(bookmarkName);
+				foundName =ETrue;
+				}
+			parmsChecked++;
+			}
+		else if (parmsChecked <2 && iParsedFieldArray->At(aIndex)->FieldName().CompareF(KWappURL)==0)
+			{
+			if (foundURL == EFalse)
+				{
+				tempPtr.Set(iParsedFieldArray->At(aIndex)->FieldValue());
+				if (tempPtr.Length() > 0)
+					{
+					bookmarkURL = tempPtr.AllocL();
+					CleanupStack::PushL(bookmarkURL);
+					foundURL =ETrue;
+					}
+				}
+			parmsChecked++;
+			}
+		// Advance to next field if not at the end of the array
+		if (aIndex <iParsedFieldArray->Count())
+			aIndex++;		 
+		}
+		// If we've only looked at 2 Parms and have both a Name AND URL 
+		// it's a well-formed bookmark so add to it to our List
+		if (foundName && foundURL && parmsChecked ==2) 
+			{
+			CWappBookmark* newBookmark =  CWappBookmark::NewLC();
+			newBookmark->SetNameL(*bookmarkName);
+			newBookmark->SetUrlL(*bookmarkURL);
+			iBookmarkList->AppendL(newBookmark); 				
+			CleanupStack::Pop(); // release newBookmark	
+			}
+		if(bookmarkName) CleanupStack::PopAndDestroy();
+		if(bookmarkURL) CleanupStack::PopAndDestroy();
+	}
+
+//
+//	ValidateCharacteristicsL() - Validates the data extracted by PreProcessL. 
+//
+//	Following are legitimate messages
+//		 -  entirely bookmarks
+//		 -  1+ bearers with any no of other characteristics
+//		 -  Non-Null URL and Non Null name of existing settings records
+//
+//	Any other combinations are invalid i.e.
+//				
+//				Bookmarks with ID/URL/NAME & NO Bearer
+//									
+void CMsvBIOWapAccessParser::ValidateCharacteristicsL()
+	{
+	
+	// Bookmarks message - bookmarks & no bearers, should be no URL, ID or Settings Name
+	if ((iBookmarkList->Count() >0) && 
+		!(iGsmCsdData || iGsmSmsData || iGprsData) && 
+		(iURLData || iNameData || iIdData))
+			User::Leave(KWappErrBadMessage);  
+	
+	// start page update message - URL+NAME but no Bearers, no bookmarks
+	if (iURLData && iNameData && 
+		!(iGsmCsdData || iGsmSmsData || iGprsData) && 
+		(iBookmarkList->Count()==0) && 
+		((iUrl.Length()==0) || (iWAPSettingsName.Length()==0)))
+			User::Leave(KWappErrBadMessage);
+
+	if ((iGsmCsdData || iGsmSmsData || iGprsData) && 
+		(iWAPSettingsName.Length()==0))     // Need a name for CommDb - default
+			User::Leave(KWappErrBadMessage); //  should have been given if nothing in message 
+	}
+
+//
+//	IsCharacteristicName	-	Returns ETrue if the Name at the index is a genuine 
+//								Characteristic Type and the Value is NULL
+//
+TBool CMsvBIOWapAccessParser::IsCharacteristicName(TInt anIndex)
+	{
+	TPtrC name = iParsedFieldArray->At(anIndex)->FieldName();
+	if (  
+		(name.CompareF(KWappCharAddress) ==0) ||  // Address
+		(name.CompareF(KWappCharURL) ==0) ||	  // URL 
+		(name.CompareF(KWappCharMMSURL) ==0) ||	  // MMS URL 
+		(name.CompareF(KWappCharName) ==0) ||  // NAME
+		(name.CompareF(KWappCharBookmark) ==0) || // Bookmark
+		(name.CompareF(KWappCharID) ==0)  ) // ID
+			return ETrue;	// Is a characteristic name
+	else
+		return EFalse;		// Not a characteristic name
+	}
+
+//		
+//	SetModemInitStringL() -  Sets the modem initialisation string
+//
+void CMsvBIOWapAccessParser::SetModemInitStringL() // Sets the modem initialisation string
+	{
+	delete iModemInitString;
+	iModemInitString =NULL;
+	iModemInitString=KDummyModemInitStr().AllocL();
+	}
+
+
+void CMsvBIOWapAccessParser::DeleteCommDatTableEntryL(TMDBElementId aElementName, const TDesC& aCsdNameStr)
+	{	
+	switch	(aElementName)
+		{
+		case KCDTIdWAPIPBearerRecord:
+			{
+			CCDWAPIPBearerRecord *wapIPRecord = static_cast<CCDWAPIPBearerRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdWAPIPBearerRecord));
+			CleanupStack::PushL(wapIPRecord);
+			wapIPRecord->iWAPAccessPointId = iWapAccessPtID;
+			
+			if(wapIPRecord->FindL(*iDBSession))
+				{
+				TUint32 accessId = wapIPRecord->iWAPIAP;
+				if ( !((iGsmCsdData && iGsmCsdWapIpTable->iIapId == accessId) ||
+			           			(iGprsData && iGprsWapIpTable->iIapId == accessId)))					
+					{
+					wapIPRecord->DeleteL(*iDBSession);			
+					}
+				}
+			CleanupStack::PopAndDestroy(wapIPRecord);					
+			}			
+			break;
+		case KCDTIdWAPSMSBearerRecord:
+			{
+			CCDWAPSMSBearerRecord *smsRecord = static_cast<CCDWAPSMSBearerRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdWAPSMSBearerRecord));
+			CleanupStack::PushL(smsRecord);
+			smsRecord->iWAPAccessPointId = iWapAccessPtID;
+			if(smsRecord->FindL(*iDBSession))
+				{
+				smsRecord->DeleteL(*iDBSession);			
+				}
+			CleanupStack::PopAndDestroy(smsRecord);	
+			}			
+			break;
+		case KCDTIdIAPRecord:
+			{
+			CCDIAPRecord *iapRecord = static_cast<CCDIAPRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdIAPRecord));
+			CleanupStack::PushL(iapRecord);
+			iapRecord->iRecordName.SetMaxLengthL(aCsdNameStr.Length());
+			iapRecord->iRecordName = aCsdNameStr;				
+			if(iapRecord->FindL(*iDBSession))
+				{
+				iapRecord->DeleteL(*iDBSession);				
+				}
+			CleanupStack::PopAndDestroy(iapRecord);
+			}			
+			break;
+		case KCDTIdDialOutISPRecord:
+			{
+			CCDDialOutISPRecord *dialOutISPRecord = static_cast<CCDDialOutISPRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdDialOutISPRecord));
+			CleanupStack::PushL(dialOutISPRecord);
+			dialOutISPRecord->iRecordName.SetMaxLengthL(aCsdNameStr.Length());
+			dialOutISPRecord->iRecordName = aCsdNameStr;
+			if(dialOutISPRecord->FindL(*iDBSession))
+				{
+				dialOutISPRecord->DeleteL(*iDBSession);				
+				}
+			CleanupStack::PopAndDestroy(dialOutISPRecord);						
+			}
+			break;		
+		case KCDTIdOutgoingGprsRecord:
+			{
+			CCDOutgoingGprsRecord *gprsRecord = static_cast<CCDOutgoingGprsRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdOutgoingGprsRecord));
+			CleanupStack::PushL(gprsRecord);
+			gprsRecord->iRecordName.SetMaxLengthL(aCsdNameStr.Length());
+			gprsRecord->iRecordName = aCsdNameStr;
+			if(gprsRecord->FindL(*iDBSession))
+				{
+				gprsRecord->DeleteL(*iDBSession);				
+				}
+			CleanupStack::PopAndDestroy(gprsRecord);		
+			}
+			break;			
+		}
+	}	
+
+void CMsvBIOWapAccessParser::WriteDataToDBL()
+	{
+	// Should have a table for at least one bearer!!
+	__ASSERT_DEBUG (iWapSmsTable != NULL || iWapGprsTable != NULL || (iGsmCsdWapIpTable != NULL && iWapIpISPTable !=NULL), 
+									  Panic(EWappNullPointer));
+
+	if (iWAPSettingsName.Length()==0)
+		{
+		iWAPSettingsName.Set(KWapDefaultSettingsName);
+		}	
+
+	TBuf<KMaxNameBufferLength> csdNameStr;
+	csdNameStr.Copy(iWAPSettingsName);
+	csdNameStr.Append(KGsmCsdSuffix);
+	if (iGsmCsdData)
+		{
+		iCurrentBearerType = EWappGsmCsdBearer;  // Set the bearer type indicator for use in next functions
+
+		WriteToCommDatDialOutISPTableL(csdNameStr);
+		SetWapIspEntryIdL(csdNameStr);	// Sets iWapIspID		
+		
+		WriteToCommsDatIAPTableL(csdNameStr);			
+		SetWapIapEntryIdL(csdNameStr, *iGsmCsdWapIpTable);			// Sets iWapIapID
+		}
+	else
+		{
+		DeleteCommDatTableEntryL(KCDTIdDialOutISPRecord,csdNameStr);
+		DeleteCommDatTableEntryL(KCDTIdIAPRecord,csdNameStr);
+		}
+
+	TBuf<KMaxNameBufferLength> gprsNameStr;
+	gprsNameStr.Copy(iWAPSettingsName);
+	gprsNameStr.Append(KGprsSuffix);
+	if(iGprsData)
+		{
+		iCurrentBearerType = EWappGprsBearer;		
+		WriteToCommDatGprsTableL(gprsNameStr);		
+		SetWapIspEntryIdL(gprsNameStr);	// Sets iWapIspID
+		WriteToCommsDatIAPTableL(gprsNameStr);				
+				
+		SetWapIapEntryIdL(gprsNameStr, *iGprsWapIpTable);			// Sets iWapIapID
+		}
+	else
+		{
+		DeleteCommDatTableEntryL(KCDTIdOutgoingGprsRecord,gprsNameStr);
+		DeleteCommDatTableEntryL(KCDTIdIAPRecord,gprsNameStr);
+		}
+		
+	WriteToCommDatWapAccessPointTableL(iWAPSettingsName);		
+
+	SetWapAPEntryIdL();
+
+
+	if (iGsmCsdData)
+		{
+		// Set the flag so that correct mapping object is used to set the data in the WAP IP Bearer table
+		iCurrentBearerType = EWappGsmCsdBearer;
+		WriteToCommDatWapIpBearerTableL();		
+		}
+	else 		
+		{
+		DeleteCommDatTableEntryL(KCDTIdWAPIPBearerRecord,csdNameStr);
+		}
+		
+
+	if ((iGprsData))
+		{
+		// Set the flag so that correct mapping object is used to set the data in the WAP IP Bearer table
+		iCurrentBearerType = EWappGprsBearer;
+		WriteToCommDatWapIpBearerTableL();
+		}
+	else
+		{
+		DeleteCommDatTableEntryL(KCDTIdWAPIPBearerRecord,gprsNameStr);
+		}
+		
+		
+	if (iGsmSmsData)
+		{
+		WriteToCommDatWapSmsBearerTableL();	
+		}		
+	else		
+		{
+		DeleteCommDatTableEntryL(KCDTIdWAPSMSBearerRecord,iWAPSettingsName);
+		}
+		
+		
+
+
+//	if ((iGsmCsdData) && iModemInitString)    // Only if CSD and has string set (ie ISDN)
+//		CreateTableL(TPtrC(MODEM), iWAPSettingsName);  //TODO Not yet implemented 
+	}
+
+// End of function  CMsvBIOWapAccessParser::WriteDataToDBL()
+
+
+void CMsvBIOWapAccessParser::WriteToCommsDatIAPTableL(const TDesC& aRecName)
+	{	
+	CCDIAPRecord *iapRecord = static_cast<CCDIAPRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdIAPRecord));
+	CleanupStack::PushL(iapRecord);
+	iapRecord->iRecordName.SetMaxLengthL(aRecName.Length());
+	iapRecord->iRecordName = aRecName;
+	
+	TBool newRecord = EFalse;
+	if(!iapRecord->FindL(*iDBSession))
+		{
+		iapRecord->SetRecordId(KCDNewRecordRequest);
+		newRecord = ETrue;
+		}		
+			
+	switch (iCurrentBearerType)
+		{
+		case EWappGsmCsdBearer:
+			{
+			iapRecord->iService = iWapIpISPTable->iISPCommDbRecordId;
+			iapRecord->iServiceType.SetMaxLengthL(((TPtrC)KCDTypeNameDialOutISP).Length());
+			iapRecord->iServiceType = (TPtrC)KCDTypeNameDialOutISP;			
+
+			//there are 7 fields in IAP table which cannot have null values, and so when creating an IAP record we were only filling in one of the fields which meant we were submitting a record with lots of null values which can't be handled.
+			iapRecord->iBearer = (TUint32)2;
+			
+			iapRecord->iBearerType.SetMaxLengthL(((TPtrC)KCDTypeNameModemBearer).Length());
+			iapRecord->iBearerType = (TPtrC)KCDTypeNameModemBearer;
+			iapRecord->iNetwork = (TUint32)1;
+			iapRecord->iNetworkWeighting = (TUint32)0;
+			iapRecord->iLocation = (TUint32)4;							
+			}
+			break;
+		case EWappGprsBearer:
+			{
+			iapRecord->iService = iWapGprsTable->iGprsCommDbRecordId;
+			iapRecord->iServiceType.SetMaxLengthL(((TPtrC)KCDTypeNameDialOutISP).Length());
+			iapRecord->iServiceType = (TPtrC)KCDTypeNameOutgoingWCDMA;
+
+			//there are 7 fields in IAP table which cannot have null values, and so when creating an IAP record we were only filling in one of the fields which meant we were submitting a record with lots of null values which can't be handled.
+			iapRecord->iBearer = (TUint32)2;
+			iapRecord->iBearerType.SetMaxLengthL(((TPtrC)KCDTypeNameModemBearer).Length());
+			iapRecord->iBearerType = (TPtrC)KCDTypeNameModemBearer;
+			iapRecord->iNetwork = (TUint32)1;
+			iapRecord->iNetworkWeighting = (TUint32)0;	
+			iapRecord->iLocation = (TUint32)4;	
+			}									
+			break;
+		default:
+			break;
+		}	
+	
+	if(newRecord)
+		{					
+		iapRecord->StoreL(*iDBSession);
+		}		
+	else
+		{
+		iapRecord->ModifyL(*iDBSession);	
+		}	
+	
+	CleanupStack::PopAndDestroy(iapRecord);
+	}
+	
+void CMsvBIOWapAccessParser::WriteToCommDatWapSmsBearerTableL()
+	{	
+	CCDWAPSMSBearerRecord *wapSMSBearerRecord = static_cast<CCDWAPSMSBearerRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdWAPSMSBearerRecord));
+	CleanupStack::PushL(wapSMSBearerRecord);
+	//Search based on WAPAccessPointId
+	wapSMSBearerRecord->iWAPAccessPointId = iWapAccessPtID;	
+	
+	TBool newRecord = EFalse;	
+	if(!wapSMSBearerRecord->FindL(*iDBSession))	
+		{
+		wapSMSBearerRecord->SetRecordId(KCDNewRecordRequest);			
+		newRecord = ETrue;
+		}			
+	
+	wapSMSBearerRecord->iWAPGatewayAddress.SetMaxLengthL(iWapSmsTable->iGatewayAddr.Length());
+	wapSMSBearerRecord->iWAPGatewayAddress = iWapSmsTable->iGatewayAddr;
+	
+	wapSMSBearerRecord->iWAPServiceCentreAddress.SetMaxLengthL(iWapSmsTable->iWapServiceAddr.Length());
+	wapSMSBearerRecord->iWAPServiceCentreAddress = iWapSmsTable->iWapServiceAddr;
+	
+	wapSMSBearerRecord->iWAPWSPOption = GetWSPType(iWapSmsTable->iPort);			
+	wapSMSBearerRecord->iWAPSecurity = UseSecurity(iWapSmsTable->iPort);	
+		
+	if(newRecord)
+		{					
+		wapSMSBearerRecord->StoreL(*iDBSession);
+		}		
+	else
+		{
+		wapSMSBearerRecord->ModifyL(*iDBSession);	
+		}		
+	
+	CleanupStack::PopAndDestroy(wapSMSBearerRecord);
+	}
+
+void CMsvBIOWapAccessParser::WriteToCommDatWapIpBearerTableL()
+	{	
+	CCDWAPIPBearerRecord *wapIPBearerRecord = static_cast<CCDWAPIPBearerRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdWAPIPBearerRecord));
+	CleanupStack::PushL(wapIPBearerRecord);
+	//Search based on WAPAccessPointId
+	wapIPBearerRecord->iWAPAccessPointId = iWapAccessPtID;	
+	
+	TBool newRecord = EFalse;	
+	if(!wapIPBearerRecord->FindL(*iDBSession))
+		{
+		wapIPBearerRecord->SetRecordId(KCDNewRecordRequest);					
+		newRecord = ETrue;
+		}		
+	
+	CWapIpBearerData* wapIpTableData = NULL;
+	switch (iCurrentBearerType)
+		{
+		case EWappGsmCsdBearer:
+			{
+			wapIpTableData = iGsmCsdWapIpTable;	
+			}			
+			break;
+		case EWappGprsBearer:
+			{
+			wapIpTableData = iGprsWapIpTable;	
+			}			
+			break;
+		default:
+			User::Leave(KWappErrUnexpectedValue);
+		}
+	__ASSERT_DEBUG(wapIpTableData, Panic(KWappErrNullValue));
+
+	wapIPBearerRecord->iWAPAccessPointId = iWapAccessPtID;
+ 	wapIPBearerRecord->iWAPIAP = wapIpTableData->iIapId;			// Get from SetWapEntryIdsL
+
+	wapIPBearerRecord->iWAPGatewayAddress.SetMaxLengthL((wapIpTableData->iGatewayAddr->Addr()).Length());
+	wapIPBearerRecord->iWAPGatewayAddress = wapIpTableData->iGatewayAddr->Addr();
+	
+	wapIPBearerRecord->iWAPWSPOption =  GetWSPType(wapIpTableData->iPort);
+	wapIPBearerRecord->iWAPSecurity =  UseSecurity(wapIpTableData->iPort);
+	
+	TLex lex = wapIpTableData->iPort;
+	TInt port = 0;	
+	User::LeaveIfError(lex.Val(port));
+	wapIPBearerRecord->iWAPProxyPort =  port;
+	
+	wapIPBearerRecord->iWAPProxyLoginName.SetMaxLengthL(wapIpTableData->iProxyAuthName.Length());
+	wapIPBearerRecord->iWAPProxyLoginName = wapIpTableData->iProxyAuthName;
+	
+	wapIPBearerRecord->iWAPProxyLoginPass.SetMaxLengthL(wapIpTableData->iProxyAuthSecret.Length());
+	wapIPBearerRecord->iWAPProxyLoginPass = wapIpTableData->iProxyAuthSecret;
+	
+	if(newRecord)
+		{					
+		wapIPBearerRecord->StoreL(*iDBSession);
+		}		
+	else
+		{
+		wapIPBearerRecord->ModifyL(*iDBSession);	
+		}	
+	
+	CleanupStack::PopAndDestroy(wapIPBearerRecord);	
+	}
+
+void CMsvBIOWapAccessParser::WriteToCommDatWapAccessPointTableL(const TDesC& aRecName)
+	{	
+	CCDWAPAccessPointRecord *wapAPRecord = static_cast<CCDWAPAccessPointRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdWAPAccessPointRecord));
+	CleanupStack::PushL(wapAPRecord);
+	wapAPRecord->iRecordName.SetMaxLengthL(aRecName.Length());	
+	wapAPRecord->iRecordName = aRecName;
+	TBool newRecord = EFalse;
+	if(!wapAPRecord->FindL(*iDBSession))
+		{
+		wapAPRecord->SetRecordId(KCDNewRecordRequest);
+		newRecord = ETrue;	
+		}
+				
+	if (iUrl.Length() != 0)
+		{
+		wapAPRecord->iWAPStartPage.SetMaxLengthL(iUrl.Length());
+		wapAPRecord->iWAPStartPage = iUrl;	
+		}		
+
+	if ((iGsmCsdData) || (iGprsData))
+		wapAPRecord->iWAPCurrentBearer = TPtrC(WAP_IP_BEARER);
+	else if (iGsmSmsData)
+		wapAPRecord->iWAPCurrentBearer = TPtrC(WAP_SMS_BEARER);
+	else
+		User::Leave(KWappErrUnexpectedValue);	
+	
+	if(newRecord)
+		{					
+		wapAPRecord->StoreL(*iDBSession);
+		}		
+	else
+		{
+		wapAPRecord->ModifyL(*iDBSession);	
+		}
+	
+	CleanupStack::PopAndDestroy(wapAPRecord);
+	}
+
+void CMsvBIOWapAccessParser::WriteToCommDatGprsTableL(const TDesC& aRecName)
+	{	
+	CCDOutgoingGprsRecord *gprsRecord = static_cast<CCDOutgoingGprsRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdOutgoingGprsRecord));
+	CleanupStack::PushL(gprsRecord);
+	gprsRecord->iRecordName.SetMaxLengthL(aRecName.Length());
+	gprsRecord->iRecordName = aRecName;
+	
+	TBool newRecord = EFalse;
+	if(!gprsRecord->FindL(*iDBSession))	
+		{
+		gprsRecord->SetRecordId(KCDNewRecordRequest);
+		newRecord = ETrue;	
+		}
+				
+	gprsRecord->iGPRSAPN.SetMaxLengthL(iWapGprsTable->iAccessPointName.Length());
+	gprsRecord->iGPRSAPN = iWapGprsTable->iAccessPointName;
+	
+	gprsRecord->iGPRSPDPType = iWapGprsTable->iPDPType;
+	
+	gprsRecord->iGPRSPDPAddress.SetMaxLengthL(iWapGprsTable->iPDPAddress->Des().Length());
+	gprsRecord->iGPRSPDPAddress = iWapGprsTable->iPDPAddress->Des();
+
+	gprsRecord->iGPRSIfPromptForAuth = iWapGprsTable->iIFPromptForAuth;
+	
+	gprsRecord->iGPRSIfAuthName.SetMaxLengthL(iWapGprsTable->iLoginName.Length());
+	gprsRecord->iGPRSIfAuthName = iWapGprsTable->iLoginName;
+	
+	gprsRecord->iGPRSIfAuthPass.SetMaxLengthL(iWapGprsTable->iLoginPass.Length());
+	gprsRecord->iGPRSIfAuthPass = iWapGprsTable->iLoginPass;
+	
+	gprsRecord->iGPRSIPGateway.SetMaxLengthL(iWapGprsTable->iGatewayAddr->Addr().Length());
+	gprsRecord->iGPRSIPGateway = iWapGprsTable->iGatewayAddr->Addr();
+	
+	gprsRecord->iGPRSIPAddrFromServer = iWapGprsTable->iIpAddrFromServer;
+	
+	gprsRecord->iGPRSIPDNSAddrFromServer = iWapGprsTable->iIPDnsAddrFromServer;
+	gprsRecord->iGPRSDisablePlainTextAuth = iWapGprsTable->iPlainTextAuthDisabled;	
+	
+	if(newRecord)
+		{					
+		gprsRecord->StoreL(*iDBSession);
+		}		
+	else
+		{
+		gprsRecord->ModifyL(*iDBSession);	
+		}
+	
+	CleanupStack::PopAndDestroy(gprsRecord);	
+	}
+
+void CMsvBIOWapAccessParser::WriteToCommDatDialOutISPTableL(const TDesC& aRecName)
+	{	
+	CCDDialOutISPRecord *dialoutRecord = static_cast<CCDDialOutISPRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdDialOutISPRecord));
+	CleanupStack::PushL(dialoutRecord);
+	dialoutRecord->iRecordName.SetMaxLengthL(aRecName.Length());	
+	dialoutRecord->iRecordName = aRecName;
+	
+	TBool newRecord = EFalse;
+	if(!dialoutRecord->FindL(*iDBSession))
+		{										
+		dialoutRecord->SetRecordId(KCDNewRecordRequest);
+		newRecord = ETrue;
+		
+		iWapIpISPTable->iISPCommDbRecordId = dialoutRecord->iRecordTag.RecordId();
+		}
+		
+	//It's time to write values	
+	(dialoutRecord->iDescription).SetMaxLengthL(iWapIpISPTable->iISPDescription.Length());
+	dialoutRecord->iDescription = iWapIpISPTable->iISPDescription;
+	
+	dialoutRecord->iType = iWapIpISPTable->iISPType; 
+	
+	dialoutRecord->iDefaultTelNum.SetMaxLengthL(iWapIpISPTable->iDefaultPhoneNum.Length());
+	dialoutRecord->iDefaultTelNum = iWapIpISPTable->iDefaultPhoneNum;
+	
+	dialoutRecord->iDialResolution = iWapIpISPTable->iDialResolution; //Mandatory, ETrue  default
+
+	dialoutRecord->iUseLoginScript = iWapIpISPTable->iUseScript;	//Mandatory, EFalse by default
+	
+	if (iWapIpISPTable->iLoginScript.Length() != 0)
+		{
+		(dialoutRecord->iLoginScript).SetMaxLengthL(iWapIpISPTable->iLoginScript.Length()); 	
+		dialoutRecord->iLoginScript = iWapIpISPTable->iLoginScript; 
+		}	
+	dialoutRecord->iPromptForLogin = iWapIpISPTable->iPromptForLoginDetails; // Mandatory, ETrue by default
+	dialoutRecord->iLoginName.SetMaxLengthL((iWapIpISPTable->iLoginName).Length());
+	dialoutRecord->iLoginName = iWapIpISPTable->iLoginName;
+	
+	(dialoutRecord->iLoginPass).SetMaxLengthL((iWapIpISPTable->iLoginPass).Length());
+	dialoutRecord->iLoginPass = iWapIpISPTable->iLoginPass;
+	
+	dialoutRecord->iDisplayPct = iWapIpISPTable->iDisplayPCT;
+
+	(dialoutRecord->iIfParams).SetMaxLengthL((iWapIpISPTable->iIFParams).Length());
+	dialoutRecord->iIfParams = iWapIpISPTable->iIFParams;
+	
+	(dialoutRecord->iIfNetworks).SetMaxLengthL((iWapIpISPTable->iIFNetworks->Des()).Length());
+	dialoutRecord->iIfNetworks = iWapIpISPTable->iIFNetworks->Des(); // Set to "IP"
+	
+	dialoutRecord->iIfPromptForAuth = iWapIpISPTable->iPromptForLoginDetails; //Mandatory, default is ETrue
+	
+	(dialoutRecord->iIfAuthName).SetMaxLengthL((iWapIpISPTable->iLoginName).Length());
+	dialoutRecord->iIfAuthName = iWapIpISPTable->iLoginName;
+	
+	(dialoutRecord->iIfAuthPass).SetMaxLengthL((iWapIpISPTable->iLoginPass).Length());
+	dialoutRecord->iIfAuthPass = iWapIpISPTable->iLoginPass;
+	
+	dialoutRecord->iIfAuthRetries = iWapIpISPTable->iNumAuthAttempts;
+
+	dialoutRecord->iIfCallbackEnabled = iWapIpISPTable->iCallBackEnabled;
+	if (iWapIpISPTable->iCallBackEnabled)
+		{
+		dialoutRecord->iIfCallbackType = iWapIpISPTable->iCallBackType;		
+		TPtr8 tempPtr(0,0); 		
+		tempPtr.Copy(iWapIpISPTable->iCallBackInfo);
+		
+		dialoutRecord->iIfCallbackInfo.SetMaxLengthL(tempPtr.Length());
+		dialoutRecord->iIfCallbackInfo = tempPtr;
+		dialoutRecord->iCallbackTimeout = 10000; 
+		}
+
+	dialoutRecord->iIpAddrFromServer = iWapIpISPTable->iAddrFromServer; //Mandatory set to True
+	
+	(dialoutRecord->iIpAddr).SetMaxLengthL((iWapIpISPTable->iInOutAddress->Addr()).Length());
+	dialoutRecord->iIpNetMask = iWapIpISPTable->iNetmask->Addr();
+	
+	(dialoutRecord->iIpGateway).SetMaxLengthL((iWapIpISPTable->iGateway->Addr()).Length());
+	dialoutRecord->iIpGateway = iWapIpISPTable->iGateway->Addr();
+	
+	dialoutRecord->iIpDnsAddrFromServer = iWapIpISPTable->iDNSFromServer;
+	// Following will write NULL strings to database, clearing any previous settings.
+	
+	(dialoutRecord->iIpNameServer1).SetMaxLengthL((iWapIpISPTable->iDNS1->Addr()).Length());
+	dialoutRecord->iIpNameServer1 = iWapIpISPTable->iDNS1->Addr();
+	
+	(dialoutRecord->iIpNameServer2).SetMaxLengthL((iWapIpISPTable->iDNS2->Addr()).Length());
+	dialoutRecord->iIpNameServer2 = iWapIpISPTable->iDNS2->Addr();
+	
+	dialoutRecord->iEnableIpHeaderComp = iWapIpISPTable->iHeaderCompressionEnabled;
+	// Don't bother with LCP extensions -  leave as null field
+	dialoutRecord->iDisablePlainTextAuth = iWapIpISPTable->iPlainTextAuthDisabled;
+	dialoutRecord->iEnableSwComp = iWapIpISPTable->iSwCompressionEnabled;	
+	dialoutRecord->iBearerSpeed = iWapIpISPTable->iCallSpeed;
+	dialoutRecord->iBearerProtocol = iWapIpISPTable->iCallDataProtocol;
+
+	if(newRecord)
+		{					
+		dialoutRecord->StoreL(*iDBSession);
+		}		
+	else
+		{
+		dialoutRecord->ModifyL(*iDBSession);	
+		}
+	
+	CleanupStack::PopAndDestroy(dialoutRecord);
+	}
+
+
+//
+//		SetWapIspEntryIdL	- The iCurrentBearerType variable MUST be correctly set before this 
+//							  function is called. Searches the appropriate Service table - DIAL_OUT_ISP
+//							 or  OUTGOING_WCDMA  - for records named as aEntryName (which should be unique!)
+//						   When it finds the record, it uses the record ID to set the class member iWapIspID.
+//
+void CMsvBIOWapAccessParser::SetWapIspEntryIdL(const TDesC& aEntryName)
+	{
+	TUint32 recId = 0;	
+	switch (iCurrentBearerType)
+		{
+		case EWappGsmCsdBearer:
+			{
+			CCDDialOutISPRecord *dialOutRecord = static_cast<CCDDialOutISPRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdDialOutISPRecord));
+			CleanupStack::PushL(dialOutRecord);
+			dialOutRecord->iRecordName.SetMaxLengthL(aEntryName.Length());
+			dialOutRecord->iRecordName = aEntryName;			
+						
+			if (dialOutRecord->FindL(*iDBSession))			
+				{				
+				recId = dialOutRecord->iRecordTag.RecordId();									
+				}
+			else
+				{				
+				User::Leave(KErrNotFound);
+				}
+			CleanupStack::PopAndDestroy(dialOutRecord);			
+			}			
+			break;
+		case EWappGprsBearer:
+			{
+			CCDOutgoingGprsRecord *gprsRecord = static_cast<CCDOutgoingGprsRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdOutgoingGprsRecord));
+			CleanupStack::PushL(gprsRecord);
+			gprsRecord->iRecordName.SetMaxLengthL(aEntryName.Length());
+			gprsRecord->iRecordName = aEntryName;
+						
+			if (gprsRecord->FindL(*iDBSession))
+				{
+				recId = gprsRecord->iRecordTag.RecordId();					
+				}
+			else
+				{				
+				User::Leave(KErrNotFound);
+				}
+			CleanupStack::PopAndDestroy(gprsRecord);	
+			}						
+			break;
+		default:
+			User::Leave(KWappErrUnexpectedValue);
+		}
+		
+	switch (iCurrentBearerType)
+		{
+		case EWappGsmCsdBearer:
+			iWapIpISPTable->iISPCommDbRecordId = recId;
+			break;
+		case EWappGprsBearer:
+			iWapGprsTable->iGprsCommDbRecordId = recId;
+			break;
+		default:
+			User::Leave(KWappErrUnexpectedValue);
+			break;
+		}	
+	}
+
+
+//
+//		SetWapIapEntryIdL	- Searches the IAP database for records of the same name 
+//						  as aEntryName (which should be unique!). When it finds the 
+//						  record, it uses the record ID to set the class member iWapIapID.
+//
+void CMsvBIOWapAccessParser::SetWapIapEntryIdL(const TDesC& aEntryName, CWapIpBearerData& aWapIpTable)
+	{
+	CCDIAPRecord *iAPRecord = static_cast<CCDIAPRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdIAPRecord));
+	CleanupStack::PushL(iAPRecord);
+	iAPRecord->iRecordName.SetMaxLengthL(aEntryName.Length());
+	iAPRecord->iRecordName = aEntryName;
+				
+	if (iAPRecord->FindL(*iDBSession))
+		{
+		aWapIpTable.iIapId = iAPRecord->iRecordTag.RecordId();					
+		}
+	else
+		{
+		User::Leave(KErrNotFound);		
+		}
+	CleanupStack::PopAndDestroy(iAPRecord);	
+	}
+
+//
+//		SetWapIspEntryIdL	- Searches the WAP_ACCESS_POINT table for records of the same name 
+//						  as iWapSettingsName (which should be unique!). When it finds the 
+//						  record, it uses the record ID to set the class member iWapIspID.
+//
+void CMsvBIOWapAccessParser::SetWapAPEntryIdL()
+	{
+	CCDWAPAccessPointRecord *wapAccessRecord = static_cast<CCDWAPAccessPointRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdWAPAccessPointRecord));
+	CleanupStack::PushL(wapAccessRecord);
+	wapAccessRecord->iRecordName.SetMaxLengthL(iWAPSettingsName.Length());
+	wapAccessRecord->iRecordName = iWAPSettingsName;	
+	
+	if (wapAccessRecord->FindL(*iDBSession))
+		{    
+		iWapAccessPtID = wapAccessRecord->iRecordTag.RecordId();	//  set the WAP AP table ID					
+		}
+	else
+		{
+		User::Leave(KErrNotFound);		
+		}
+	CleanupStack::PopAndDestroy(wapAccessRecord);	
+	}
+	
+
+void CMsvBIOWapAccessParser::WriteMMSURLL()
+	{
+
+	// check that the version of the MMS settings proxy dll is suitable
+	RImplInfoPtrArray list;
+   	REComSession::ListImplementationsL(KMMSSettingsProxyInterfaceUid, list);
+   	TInt count = list.Count();
+   	TBool found = EFalse;
+   	// may be more than one implementation, look for the 'right' one
+   	while (!found && count-- > 0)
+    	{
+      	if (list[count]->ImplementationUid() == KMMSSettingsProxyBaseUid &&
+        	list[count]->Version() == KMMSSettingsProxyVersionSupported)
+         	{
+         	// Found supported version - stop looking.
+         	found = ETrue;
+         	}
+      	}
+   	list.ResetAndDestroy();
+   	// if there are no implementations or the version is unsupported, then leave
+	if (!found)
+		User::Leave(KErrNotFound);
+
+	CMMSSettingsProxyBase* settings = CMMSSettingsProxyBase::NewL(KMMSSettingsProxyBaseUid);
+	CleanupStack::PushL(settings);
+
+	TSglQue<TMMSSettingsPair> settingList(_FOFF(TMMSSettingsPair, iLink));
+
+	// Different MMS implementations require different things.  Pass all the things they might
+	// want and allow the implementation to use those it chooses.
+
+	// The MMS Url
+	TMMSSettingsPair urlPair;
+	urlPair.iName.Set(KMMSUrl);
+	urlPair.iValue = &iMMSUrl;
+	settingList.AddFirst(urlPair);
+
+
+	TBuf<KMaxNameBufferLength> nameStr;
+	nameStr.Copy(iWAPSettingsName);
+	if (iGsmCsdData)
+		{
+		nameStr.Append(KGsmCsdSuffix);
+		}
+
+	if(iGprsData)
+		{
+		nameStr.Append(KGprsSuffix);
+		}	
+
+
+	TUint32 id=0;
+
+	switch (iCurrentBearerType)
+		{
+		case EWappGsmCsdBearer:
+			{
+			CCDDialOutISPRecord *dialOutISPRecord = static_cast<CCDDialOutISPRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdDialOutISPRecord));
+			CleanupStack::PushL(dialOutISPRecord);
+			dialOutISPRecord->iRecordName.SetMaxLengthL(nameStr.Length());
+			dialOutISPRecord->iRecordName = nameStr;		
+			if(!dialOutISPRecord->FindL(*iDBSession))
+				{
+				User::Leave(KErrNotFound);	
+				}				
+			id = dialOutISPRecord->iRecordTag.RecordId();
+			CleanupStack::PopAndDestroy(dialOutISPRecord);
+			}
+			break;
+		case EWappGprsBearer:
+			{
+			CCDOutgoingGprsRecord *gprsRecord = static_cast<CCDOutgoingGprsRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdOutgoingGprsRecord));
+			CleanupStack::PushL(gprsRecord);
+			gprsRecord->iRecordName.SetMaxLengthL(nameStr.Length());
+			gprsRecord->iRecordName = nameStr;	
+				
+			if(!gprsRecord->FindL(*iDBSession))
+				{
+				User::Leave(KErrNotFound);	
+				}			
+			id = gprsRecord->iRecordTag.RecordId();
+			CleanupStack::PopAndDestroy(gprsRecord);
+			}
+			break;
+		default:
+			User::Leave(KWappErrUnexpectedValue);
+		}	
+
+	TMMSSettingsPair commDbRecordId;
+	commDbRecordId.iName.Set(KCommDbRecordId);
+	commDbRecordId.iValue = &id;
+	settingList.AddFirst(commDbRecordId);
+
+	TMMSSettingsPair msvServerEntryPair;
+	// 24/08/04
+	// In messaging API v2, iEntry is no longer a CMsvServerEntry, but rather a CMsvEntry.
+	// For this reason, the following code has been changed.
+	// This breaks data compatability.
+	// CMsvEntry
+	msvServerEntryPair.iName.Set(KMsvEntry);
+	msvServerEntryPair.iValue = &iEntry;
+	settingList.AddFirst(msvServerEntryPair);
+
+	settings->SetMMSValuesL(settingList);
+	CleanupStack::PopAndDestroy(settings);
+	}
+
+
+//	GetWSPTypeL - Helper function used by IP and SMS functions above. Returns appropriate enum
+//
+TCommsDbWapWspOption CMsvBIOWapAccessParser::GetWSPType(TDesC& aPortValue)
+	{
+	TCommsDbWapWspOption wspType;
+
+	// Is it Connection Orientated link ?
+	if ( (aPortValue.CompareF(KWappPort9201)==0)||
+			(aPortValue.CompareF(KWappPort9203)==0) )
+		
+			wspType=EWapWspOptionConnectionOriented;
+	
+	else
+		if ( (aPortValue.CompareF(KWappPort9200)==0)||
+		  (aPortValue.CompareF(KWappPort9202)==0) )
+
+			wspType=EWapWspOptionConnectionless;
+		else  //unknown type -  so apply the default 
+			wspType=EWapWspOptionConnectionless;
+
+	return  wspType;
+	}
+
+TBool CMsvBIOWapAccessParser::UseSecurity(TDesC& aPortValue)
+	{
+	TBool useWapSecurity;
+	// Is it unsecured link?
+	if ( (aPortValue.CompareF(KWappPort9200)==0)||
+		  (aPortValue.CompareF(KWappPort9201)==0) )
+		useWapSecurity=EFalse;
+	else
+		if ( (aPortValue.CompareF(KWappPort9202)==0)||
+			 (aPortValue.CompareF(KWappPort9203)==0) )
+			useWapSecurity=ETrue;
+		else  // unknown Port value - shouldn't happen but use default anyway
+			useWapSecurity = EFalse;
+	
+	return useWapSecurity;
+	}
+
+//	UpdateStartPageUrlL() - Searchs the WAP table for a match to the name and updates
+//							the WAP_START_PAGE field with the value in the URL char of the message
+//
+
+void CMsvBIOWapAccessParser::UpdateStartPageUrlL()
+	{
+	__ASSERT_DEBUG(iWAPSettingsName.Length() != 0, Panic(EWappEmptyBuffer));
+	__ASSERT_DEBUG(iUrl.Length() != 0, Panic(EWappEmptyBuffer));
+
+	CCDWAPAccessPointRecord *wapAPRecord = static_cast<CCDWAPAccessPointRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdWAPAccessPointRecord));
+	CleanupStack::PushL(wapAPRecord);
+	wapAPRecord->iRecordName.SetMaxLengthL(iWAPSettingsName.Length());
+	wapAPRecord->iRecordName = iWAPSettingsName;	
+	
+	if(!wapAPRecord->FindL(*iDBSession))
+		{
+		User::Leave(KErrNotFound);
+		}	
+	wapAPRecord->iWAPStartPage.SetMaxLengthL(iUrl.Length());
+	wapAPRecord->iWAPStartPage = iUrl;
+	wapAPRecord->ModifyL(*iDBSession);	
+	CleanupStack::PopAndDestroy(wapAPRecord);
+	}
+
+
+//
+// IsValidTokenNameL()	- Checks that the name field at the position specified is 
+//						  a valid Characteristic or Parm name
+//
+
+TInt CMsvBIOWapAccessParser::IsValidTokenNameL(const TInt aArrayIndex)
+	{
+	TPtrC name;
+
+	name.Set(iParsedFieldArray->At(aArrayIndex)->FieldName());
+
+	if ( (name.CompareF(KWappXMLversion) ==0)||
+		 (name.CompareF(KWappPublicID) ==0)||
+		 (name.CompareF(KWappCharacterSet) ==0)||   		
+		 (name.CompareF(KWappCharAddress) ==0)||		// ADDRESS Characteristic
+		 (name.CompareF(KWappCharURL) ==0)||			// URL Characteristic 
+		 (name.CompareF(KWappCharMMSURL) ==0)||			// URL Characteristic 
+		 (name.CompareF(KWappCharName) ==0)||				// NAME Characteristic OR ATTRIBUTE 
+		 (name.CompareF(KWappCharBookmark) ==0)||		// BOOKMARK Characteristic 
+		 (name.CompareF(KWappCharID) ==0)||				// ID Characteristic 
+		 (name.CompareF(KWappURL) ==0)||				// URL Parm 
+		 (name.CompareF(KWappName) ==0)||				// NAME Parm OR ATTRIBUTE 
+		 (name.CompareF(KWappBearer) ==0)||				// BEARER Attribute 
+		 (name.CompareF(KWappProxy) ==0)||				// PROXY
+		 (name.CompareF(KWappPort) ==0)||				// PORT
+		 (name.CompareF(KWappProxyType) ==0)||			// PROXY_TYPE  - for USSD only
+		 (name.CompareF(KWappProxyAuthName) ==0)||		// PROXY_AUTHNAME
+		 (name.CompareF(KWappProxyAuthSecret) ==0)||	// PROXY_AUTHSECRET
+		 (name.CompareF(KWappProxyLoginType) ==0)||		// PROXY_LOGIN_TYPE
+		 (name.CompareF(KWappSMSCAddress) ==0)||		// SMS_SMSC_ADDRESS
+		 (name.CompareF(KWappUSSDCode) ==0)||			// USSD SERVICE CODE
+		 (name.CompareF(KWappAccessPointName) ==0)||	// ACCESSPOINTNAME
+		 (name.CompareF(KWappCsdDial) ==0)||			// CSD_DIALSTRING
+		 (name.CompareF(KWappPPPAuthType) ==0)||		// PPP_AUTHTYPE
+		 (name.CompareF(KWappPPPAuthName) ==0)||		// PPP_AUTHNAME
+		 (name.CompareF(KWappPPPAuthSecret) ==0)||		// PPP_AUTHSECRET
+		 (name.CompareF(KWappPPPLoginType) ==0)||		// PPP_LOGIN_TYPE
+		 (name.CompareF(KWappCsdCallType) ==0)||		// CSD_CALLTYPE
+		 (name.CompareF(KWappCsdCallSpeed) ==0)||		// CSD_CALLSPEED
+		 (name.CompareF(KWappISP) ==0) )				// ISP_NAME
+ 
+
+		return KErrNone;
+	else 
+		return KWappErrUnrecognised;
+	}
+
+//
+//  WriteBookmarksToFileL() - Store Bookmarks as an attachment file 
+//	in the .eBM format. If the system runs out of memory while
+//  the bookmarks are being written to the file, the file will be
+//	deleted. For example, if 2 bookmarks have already been written
+//	to the file, and the writing of the third bookmark fails, the
+//	file will be deleted. Otherwise, a failure of file writing would
+//	need to be handled differently from memory allocation failure.
+//
+void CMsvBIOWapAccessParser::WriteBookmarksToFileL()
+{
+	
+	TInt numberOfItems = iBookmarkList->Count();
+
+	if (numberOfItems > 0)	// Only create a file if there is something 
+							//to save
+	{	
+
+		TFileName filePath;
+
+
+		// build the filename
+		TMsvId entryId = iEntry.Entry().Id();
+		filePath.Num(entryId,EHex);
+		filePath.Append(KEBookmarkExtension);
+		
+		// Get the attachment manager and create an empty attachment file
+		CMsvStore* store = iEntry.EditStoreL();
+		CleanupStack::PushL(store);
+		
+		MMsvAttachmentManager& manager = store->AttachmentManagerL();
+		MMsvAttachmentManagerSync& managerSync = store->AttachmentManagerExtensionsL();		
+		RemoveAttachmentIfExistL(filePath, manager, managerSync);
+		CMsvAttachment* attachment = CMsvAttachment::NewL(CMsvAttachment::EMsvFile);
+		CleanupStack::PushL(attachment);
+		attachment->SetAttachmentNameL(filePath);
+		
+		RFile file;
+		managerSync.CreateAttachmentL(filePath, file, attachment);
+		CleanupStack::Pop(attachment); // ownership passed
+		
+		CleanupClosePushL(file);
+		
+
+#ifdef SYMBIAN_BOOKMARK_DATABASE
+		// Open the bookmark database ready to add the bookmarks
+		RBkDatabase bookmarkDb;
+		bookmarkDb.OpenL();
+		CleanupClosePushL(bookmarkDb);
+#endif // SYMBIAN_BOOKMARK_DATABASE
+
+		// Stream each bookmark into the file.
+		// The eBookmark file must contain only 8bit ascii.
+		// Add a linefeed to the end of each line.
+		
+		TInt count = 0;
+			
+		while(count < numberOfItems)
+			{
+			CWappBookmark& item = *iBookmarkList->At(count);
+			
+			// Allocate enough space to hold the full bookmark entry.
+
+			TInt length =	item.Name().Length() + 
+							item.Url().Length()  + 
+							KEBookmarkConstantChars;
+			
+			HBufC8* writeBuf = HBufC8::NewLC(length);
+			
+			TPtr8 des = writeBuf->Des();
+
+			des.Append(KEBookmarkItemBegin);
+			des.Append(KEBookmarkItemURL);
+			des.Append(item.Url());
+			des.Append(KCRLinefeed);
+			des.Append(KEBookmarkItemName);
+			des.Append(item.Name());
+			des.Append(KCRLinefeed);
+			des.Append(KEBookmarkType);
+			des.Append(KEBookmarkItemEnd);
+
+			User::LeaveIfError(file.Write(des));
+			
+			CleanupStack::PopAndDestroy();
+
+#ifdef SYMBIAN_BOOKMARK_DATABASE
+			// Add the bookmark to the bookmark database
+			RBkBookmark bookmark = bookmarkDb.CreateBookmarkL();
+			CleanupClosePushL(bookmark);
+			bookmark.SetTitleL(item.Name());
+			// Convert Uri to 8-bit
+			HBufC8* bookmarkUri = HBufC8::NewLC(item.Url().Length());
+			bookmarkUri->Des().Copy(item.Url());
+			bookmark.SetUriL(*bookmarkUri);
+			CleanupStack::PopAndDestroy(2, &bookmark); // bookmarkUri, bookmark
+#endif // SYMBIAN_BOOKMARK_DATABASE
+
+			count++;
+			}
+
+#ifdef SYMBIAN_BOOKMARK_DATABASE			
+		// Commit all the added bookmarks and close bookmark db
+		bookmarkDb.CommitL();
+		CleanupStack::PopAndDestroy(&bookmarkDb);
+#endif // SYMBIAN_BOOKMARK_DATABASE
+
+		// File writing has completed, set the size in the attachment
+		TInt fileSize;
+		User::LeaveIfError(file.Size(fileSize));
+		attachment->SetSize(fileSize);
+		
+		// commit the changes
+		store->CommitL();
+		CleanupStack::PopAndDestroy(2, store); // file, store
+
+	}
+}	
+//  End of function WriteBookmarksToFileL()
+
+void CMsvBIOWapAccessParser::RemoveAttachmentIfExistL(const TDesC& aFileName, MMsvAttachmentManager& aManager, MMsvAttachmentManagerSync& aManagerSync)
+	{
+	// If an attachment already exists with the same filename then delete
+	// the existing one so multiple files of the same name dont exist
+	for( TInt ii=0; ii<aManager.AttachmentCount(); ++ii )
+		{
+		CMsvAttachment* attachmentInfo = aManager.GetAttachmentInfoL(ii);
+		CleanupStack::PushL(attachmentInfo);
+		if( attachmentInfo->AttachmentName().CompareF(aFileName) == 0 )
+			{
+			
+			// We have a match, delete the attachment as we will have
+			// to add it as new one
+			aManagerSync.RemoveAttachmentL(ii);
+			CleanupStack::PopAndDestroy(attachmentInfo); // attachmentInfo
+			break;
+			}
+		CleanupStack::PopAndDestroy(attachmentInfo);
+		}
+	}
+
+void CMsvBIOWapAccessParser::Panic(TInt aPanic)
+	{
+	User::Panic(KWappDll, aPanic);
+	}
+
+
+CWapCharsetConverter* CWapCharsetConverter::NewL(RFs& aFs, TUint aMibEnum)
+	{
+	CWapCharsetConverter* self = new (ELeave) CWapCharsetConverter(aFs);
+	CleanupStack::PushL(self);
+	self->ConstructL(aMibEnum);
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+void CWapCharsetConverter::ConstructL(TInt aMibEnum)
+	{
+	iConverter = CCnvCharacterSetConverter::NewL();
+	iAvailableCharsets = iConverter->CreateArrayOfCharacterSetsAvailableL(iFs);
+
+	if(aMibEnum == 0)
+		{
+		iParseable = EFalse;
+		return;
+		}
+	
+	TInt charset = iConverter->ConvertMibEnumOfCharacterSetToIdentifierL(aMibEnum, iFs);
+
+	if(charset==0)
+		{
+		iParseable = EFalse;
+		return;
+		}
+
+	CCnvCharacterSetConverter::TAvailability t = iConverter->PrepareToConvertToOrFromL(charset, iFs);
+	iParseable = (t == CCnvCharacterSetConverter::EAvailable);
+	}
+
+void CWapCharsetConverter::ConvertL(const TDesC& aSource, TDes& aSink)
+	{
+	if(iParseable)
+		{
+		//defect fix for Inc021752
+		HBufC8* des = HBufC8::NewLC(aSource.Length());
+		des->Des().Copy(aSource);
+
+		TInt state = CCnvCharacterSetConverter::KStateDefault;
+
+		//defect fix for Inc021752
+		User::LeaveIfError(iConverter->ConvertToUnicode(aSink, *des, state));
+		CleanupStack::PopAndDestroy(des);
+		}
+	else
+		{
+		aSink.Copy(aSource);
+		}
+	}
+
+CWapCharsetConverter::~CWapCharsetConverter()
+	{
+	delete iConverter;
+	delete iAvailableCharsets;
+	}