--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/vpnengine/utlxml/src/XmlPullParser.cpp Thu Dec 17 09:14:51 2009 +0200
@@ -0,0 +1,1487 @@
+/*
+* Copyright (c) 2003 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: Implementation of CXmlPullParser.
+*
+*/
+
+
+
+#include <eikenv.h>
+#include <e32std.h>
+#include <e32des8.h>
+#include "XppImpl.h"
+
+const TInt KExtraPunctuation = 5;
+const TInt KBufSizeIncrement = 1024;
+const TInt KBufInitSize = 2048;
+
+//
+// Common literal text
+//
+_LIT8(KOpenBracket, "<");
+_LIT8(KCloseBracket, ">");
+//_LIT8(KStartEndTag, "</");
+//_LIT8(KCloseTag, "/>");
+_LIT8(KSpace, " ");
+_LIT8(KEquals, "=");
+_LIT8(KSlash, "/");
+_LIT8(KSingleQuote, "\'");
+_LIT8(KDoubleQuote, "\"");
+//_LIT8(KQuestionMark, "?");
+//_LIT8(KExclamationMark, "!");
+//_LIT8(KOpenCurlyBracket, "{");
+//_LIT8(KCloseCurlyBracket, "}");
+//_LIT8(KHyphen, "-");
+_LIT8(KOpenAngleBracket , "[");
+_LIT8(KCloseAngleBracket, "]");
+
+_LIT8(KAmpersand, "&");
+_LIT8(KAmpersandHash, "&#");
+_LIT8(KSemicolon, ";");
+
+// XML special marks
+//_LIT8(KStartXmlProlog, "<?xml");
+//_LIT8(KStartComment, "<!--");
+_LIT8(KEndComment, "-->");
+//_LIT8(KStartProcessingInstructions, "<?");
+_LIT8(KEndPIAndProlog, "?>");
+_LIT8(KStartCData, "<![CDATA[");
+_LIT8(KEndCData, "]]>");
+//_LIT8(KStartDocType, "<!DOCTYPE");
+//_LIT8(KStartElement, "<!ELEMENT");
+//_LIT8(KStartAttList, "<!ATTLIST");
+//_LIT8(KStartEntity, "<!ENTITY");
+//_LIT8(KStartNotation, "<!NOTATION");
+//_LIT8(KEndCdata, "]]>");
+
+_LIT8(KEntityLowerThan, "<"); // <
+_LIT8(KEntityGreaterThan, ">"); // >
+_LIT8(KEntityAmpersand, "&"); // &
+_LIT8(KEntityApostrophe, "'"); // '
+_LIT8(KEntityQuotation, """); // "
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////////////////////////////////
+CXmlPullParser::CXmlPullParser()
+: iState(EStateStartDocument), iCurrentElementPos(0), iPathBufPtr(NULL, 0), iDepth(0),
+iIsEmptyElement(EFalse), iCdataStartFound(EFalse), iCdataSectionText(EFalse),
+iStringValuePtr(NULL, 0), iStringValueArray(NULL)
+ {
+ }
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////////////////////////////////
+// NewLC with two stage construction
+EXPORT_C CXmlPullParser* CXmlPullParser::NewLC(CDesC8ArrayFlat& aStringValueArray)
+ {
+ // get new, leave if can't
+ CXmlPullParser* self = new (ELeave) CXmlPullParser();
+ // push onto cleanup stack in case self->ConstructL leaves
+ CleanupStack::PushL(self);
+ // complete construction with second phase constructor
+ self->ConstructL(aStringValueArray);
+ return self;
+ }
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////////////////////////////////
+EXPORT_C CXmlPullParser* CXmlPullParser::NewL(CDesC8ArrayFlat& aStringValueArray)
+ {
+ CXmlPullParser* self=NewLC(aStringValueArray);
+ CleanupStack::Pop();
+ return self;
+ }
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////////////////////////////////
+void CXmlPullParser::ConstructL(CDesC8ArrayFlat& aStringValueArray)
+ {
+ iPathBuf = HBufC8::NewMaxL(KBufInitSize);
+ iPathBufPtr.Set(iPathBuf->Des());
+ iPathBufPtr.SetLength(0); // Otherwise the Length is set to KBufInitSize
+ iCAttrDataArray = new (ELeave) CArrayFixFlat<TAttrData>(1);
+ iStringValue = HBufC8::NewMaxL(KBufInitSize);
+ iStringValuePtr.Set(iStringValue->Des());
+ iStringValuePtr.SetLength(0); // Otherwise the Length is set to KBufInitSize
+ //iStringValueArray = new (ELeave) CDesC8ArrayFlat(1);
+ iStringValueArray = &aStringValueArray;
+ }
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////////////////////////////////
+CXmlPullParser::~CXmlPullParser()
+ {
+ delete (iPathBuf);
+ delete iCAttrDataArray;
+ delete (iStringValue);
+ //delete iStringValueArray;
+ }
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////////////////////////////////
+void CXmlPullParser::CheckSpaceL(const TDesC8& aText)
+ {
+ TInt spaceLeft = iPathBufPtr.MaxLength() - iPathBufPtr.Length() - KExtraPunctuation;
+ if (aText.Length() > spaceLeft)
+ {
+ TInt newMaxLength = iPathBufPtr.MaxLength() + aText.Length() + KBufSizeIncrement;
+ iPathBuf = iPathBuf->ReAllocL(newMaxLength);
+ iPathBufPtr.Set(iPathBuf->Des());
+ }
+ }
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////////////////////////////////
+EXPORT_C void CXmlPullParser::SetInput(const TDesC8& aInput)
+ {
+ iState = EStateStartDocument;
+ iText.Set(KNullDesC8);
+ iCAttrDataArray->Delete(0, iCAttrDataArray->Count());
+ iDocument.Set(aInput);
+ iDocPart.Set(KNullDesC8);
+ iLexer.Assign(aInput); // Assigns a string to this object from a descriptor
+ iCurrentElementPos = 0;
+ iPathBufPtr.Zero();
+ iElement.Set(KNullDesC8);
+ iDepth = 0;
+ iIsEmptyElement = EFalse;
+ iCdataStartFound = EFalse;
+ iCdataSectionText = EFalse;
+ }
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////////////////////////////////
+EXPORT_C TInt CXmlPullParser::NextL()
+ {
+ TInt rv;
+
+ switch (iState)
+ {
+ case EStateStartDocument:
+ // skip
+ if ((rv = SkipLeadingNonRelevantElements()) == ERcDocumentError)
+ {
+ return rv;
+ }
+ else
+ {
+ iCurrentElementPos = iLexer.Offset();
+ rv = GetElementStartTagL();
+ return rv;
+ }
+ //break;
+
+ case EStateStartTag:
+ // skip
+ if ((rv = SkipNonRelevantElements()) == ERcDocumentError)
+ {
+ return rv;
+ }
+ else
+ {
+ iCurrentElementPos = iLexer.Offset();
+ if (iIsEmptyElement)
+ {
+ // delete /end tag from the iPathBuf
+ // this is done by subtracting the length of the buffer
+ iPathBufPtr.SetLength(iPathBufPtr.LocateReverse('/'));
+
+ // decrement iDepth
+ iDepth--;
+
+ // if we have an XML-document that is only one empty-element
+ // then we must check if we are already in the end of the document
+ if (CheckIfEndOfFile())
+ {
+ return KErrNone;
+ }
+ }
+ if (CheckIfNextEndTag()) // Check iState!!
+ {
+ if (iState == EStateError)
+ {
+ return ERcDocumentError;
+ }
+ else
+ {
+ rv = GetElementEndTag();
+ return rv;
+ }
+ }
+ else if (CheckIfNextStartTag()) // Check iState!!
+ {
+ if (iState == EStateError)
+ {
+ return ERcDocumentError;
+ }
+ else
+ {
+ rv = GetElementStartTagL();
+ return rv;
+ }
+ }
+ else // etext
+ {
+ rv = GetElementText();
+ return rv;
+ }
+ }
+ //break;
+
+ case EStateText:
+ // skip
+ if ((rv = SkipNonRelevantElements()) == ERcDocumentError)
+ {
+ return rv;
+ }
+ else
+ {
+ iCurrentElementPos = iLexer.Offset();
+ if (iState == EStateEndDocument)
+ {
+ // in EStateText we can not be in the end of the xml-document
+ iState = EStateError;
+ return ERcDocumentError;
+ }
+
+ if (iCdataStartFound)
+ {
+ rv = GetElementText();
+ return rv;
+ }
+ else
+ {
+ if (CheckIfNextEndTag()) // Check iState!!
+ {
+ if (iState == EStateError)
+ {
+ return ERcDocumentError;
+ }
+ else
+ {
+ // get end tag
+ rv = GetElementEndTag();
+ return rv;
+ }
+ }
+ else if (CheckIfNextStartTag()) // Check iState!!
+ {
+ if (iState == EStateError)
+ {
+ return ERcDocumentError;
+ }
+ else
+ {
+ // get start tag
+ rv = GetElementStartTagL();
+ return rv;
+ }
+ }
+ else // etext
+ {
+ // get text
+ rv = GetElementText();
+ return rv;
+ }
+ }
+ }
+ //break;
+
+ case EStateEndTag:
+ // after end tag can be end of file, new start tag, new end tag or etext
+ // skip
+ if ((rv = SkipNonRelevantElements()) == ERcDocumentError)
+ {
+ return rv;
+ }
+ else
+ {
+ iCurrentElementPos = iLexer.Offset();
+ if (CheckIfEndOfFile())
+ {
+ return KErrNone;
+ }
+ else
+ {
+ if (CheckIfNextStartTag()) // Check iState
+ {
+ if (iState == EStateError)
+ {
+ return ERcDocumentError;
+ }
+ else
+ {
+ rv = GetElementStartTagL();
+ return rv;
+ }
+ }
+ else if (CheckIfNextEndTag()) // Check iState!!
+ {
+ if (iState == EStateError)
+ {
+ return ERcDocumentError;
+ }
+ else
+ {
+ rv = GetElementEndTag();
+ return rv;
+ }
+ }
+ else // etext
+ {
+ // get text
+ rv = GetElementText();
+ return rv;
+ }
+ }
+ }
+
+ //break;
+ case EStateEndDocument:
+ return ERcWrongParserState;
+ //break;
+ case EStateError:
+ return ERcWrongParserState;
+ //break;
+ default:
+ return ERcUnknown; // all the States are handled above
+ //break;
+ }
+ }
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////////////////////////////////
+EXPORT_C CXmlPullParser::TParserState CXmlPullParser::State()
+ {
+ return iState;
+ }
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////////////////////////////////
+EXPORT_C TInt CXmlPullParser::Name(TPtrC8& aName)
+ {
+ if ((iState == EStateStartTag) ||
+ (iState == EStateText) ||
+ (iState == EStateEndTag) ||
+ (iState == EStateEndDocument))
+ {
+ aName.Set(iElement);
+ return KErrNone;
+ }
+ else
+ {
+ return ERcWrongParserState;
+ }
+ }
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////////////////////////////////
+EXPORT_C TInt CXmlPullParser::PathL(TPtrC8& aPath)
+ {
+ if ((iState == EStateStartTag) ||
+ (iState == EStateText) ||
+ (iState == EStateEndTag))
+ {
+ aPath.Set(iPathBufPtr);
+ return KErrNone;
+ }
+ else
+ {
+ return ERcWrongParserState;
+ }
+ }
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////////////////////////////////
+EXPORT_C TInt CXmlPullParser::Depth(TInt& aDepth)
+ {
+ if ((iState == EStateStartTag) ||
+ (iState == EStateText) ||
+ (iState == EStateEndTag))
+ {
+ aDepth = iDepth;
+ return KErrNone;
+ }
+ else
+ {
+ return ERcWrongParserState;
+ }
+ }
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////////////////////////////////
+EXPORT_C TInt CXmlPullParser::AttributeCount(TInt& aCount)
+ {
+ if (iState == EStateStartTag)
+ {
+ aCount = iCAttrDataArray->Count();
+ return KErrNone;
+ }
+ else
+ {
+ return ERcWrongParserState;
+ }
+ }
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////////////////////////////////
+EXPORT_C TInt CXmlPullParser::AttributeName(TInt aIndex, TPtrC8& aName)
+ {
+ if (iState == EStateStartTag)
+ {
+ if ((aIndex < iCAttrDataArray->Count()) && (aIndex >= 0))
+ {
+ aName.Set(iCAttrDataArray->At(aIndex).iName);
+ return KErrNone;
+ }
+ else
+ {
+ return KErrNotFound;
+ }
+ }
+ else
+ {
+ return ERcWrongParserState;
+ }
+ }
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////////////////////////////////
+EXPORT_C TInt CXmlPullParser::AttributeValuePredefEntitiesNotEscaped(TInt aIndex, TPtrC8& aValue)
+ {
+ if (iState == EStateStartTag)
+ {
+ if ((aIndex < iCAttrDataArray->Count()) && (aIndex >= 0))
+ {
+ aValue.Set(iCAttrDataArray->At(aIndex).iValue);
+ return KErrNone;
+ }
+ else
+ {
+ return KErrNotFound;
+ }
+ }
+ else
+ {
+ return ERcWrongParserState;
+ }
+ }
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////////////////////////////////
+EXPORT_C TInt CXmlPullParser::AttributeValuePredefEntitiesNotEscaped(const TDesC8& aName, TPtrC8& aValue)
+ {
+ TInt count;
+ TInt index = 0;
+ if (iState == EStateStartTag)
+ {
+ count = iCAttrDataArray->Count();
+ while (index < count)
+ {
+ if (iCAttrDataArray->At(index).iName == aName)
+ {
+ aValue.Set(iCAttrDataArray->At(index).iValue);
+ return KErrNone;
+ }
+ else
+ {
+ index ++;
+ }
+ }
+ return KErrNotFound;
+ }
+ else
+ {
+ return ERcWrongParserState;
+ }
+ }
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////////////////////////////////
+EXPORT_C TInt CXmlPullParser::AttributeValueL(TInt aIndex, TPtrC8& aValue)
+ {
+ TInt ret;
+ ret = AttributeValuePredefEntitiesNotEscaped(aIndex, aValue);
+
+ if (ret == KErrNone)
+ {
+ CheckStringValueBufferSpaceL(aValue);
+
+ iStringValuePtr = aValue;
+
+ if ( (ret = EscapeCharRefAndPreDefEntities()) != KErrNone )
+ {
+ return ret;
+ }
+ else
+ {
+ iStringValueArray->AppendL(iStringValuePtr);
+ aValue.Set(iStringValueArray->MdcaPoint(iStringValueArray->MdcaCount()-1));
+ return KErrNone;
+ }
+ }
+ else
+ {
+ return ret;
+ }
+ }
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////////////////////////////////
+EXPORT_C TInt CXmlPullParser::AttributeValueL(const TDesC8& aName, TPtrC8& aValue)
+ {
+ TInt ret;
+ ret = AttributeValuePredefEntitiesNotEscaped(aName, aValue);
+
+ if (ret == KErrNone)
+ {
+ CheckStringValueBufferSpaceL(aValue);
+
+ iStringValuePtr = aValue;
+
+ if ( (ret = EscapeCharRefAndPreDefEntities()) != KErrNone )
+ {
+ return ret;
+ }
+ else
+ {
+ iStringValueArray->AppendL(iStringValuePtr);
+ aValue.Set(iStringValueArray->MdcaPoint(iStringValueArray->MdcaCount()-1));
+ return KErrNone;
+ }
+ }
+ else
+ {
+ return ret;
+ }
+ }
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////////////////////////////////
+void CXmlPullParser::CheckStringValueBufferSpaceL(const TDesC8& aValue)
+ {
+ TInt newLength = aValue.Length();
+ if ( newLength > (iStringValuePtr.MaxLength()) )
+ {
+ iStringValue = iStringValue->ReAllocL(newLength);
+ iStringValuePtr.Set(iStringValue->Des());
+ }
+ }
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////////////////////////////////
+EXPORT_C TInt CXmlPullParser::IsEmptyElement(TBool& aIsEmptyElement)
+ {
+ if (iState == EStateStartTag)
+ {
+ aIsEmptyElement = iIsEmptyElement;
+ return KErrNone;
+ }
+ else
+ {
+ return ERcWrongParserState;
+ }
+ }
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////////////////////////////////
+EXPORT_C TInt CXmlPullParser::TextPredefEntitiesNotEscaped(TPtrC8& aText)
+ {
+ if (iState == EStateText)
+ {
+ aText.Set(iText);
+ return KErrNone;
+ }
+ else
+ {
+ return ERcWrongParserState;
+ }
+ }
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////////////////////////////////
+EXPORT_C TInt CXmlPullParser::TextL(TPtrC8& aText)
+ {
+ TInt ret;
+ ret = TextPredefEntitiesNotEscaped(aText);
+
+ if (ret == KErrNone)
+ {
+ CheckStringValueBufferSpaceL(aText);
+
+ iStringValuePtr = aText;
+
+ if ( !(iCdataSectionText) )
+ {
+ if ( (ret = EscapeCharRefAndPreDefEntities()) != KErrNone )
+ {
+ return ret;
+ }
+ else
+ {
+ iStringValueArray->AppendL(iStringValuePtr);
+ aText.Set(iStringValueArray->MdcaPoint(iStringValueArray->MdcaCount()-1));
+ }
+ }
+ return KErrNone;
+ }
+ else
+ {
+ return ret;
+ }
+ }
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////////////////////////////////
+EXPORT_C TInt CXmlPullParser::Pos()
+ {
+ return iLexer.Offset();
+ }
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////////////////////////////////
+EXPORT_C TInt CXmlPullParser::CurrentElementPos()
+ {
+ return iCurrentElementPos;
+ }
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////////////////////////////////
+EXPORT_C TInt CXmlPullParser::Length()
+ {
+ return iDocument.Length();
+ }
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////////////////////////////////
+EXPORT_C TPtrC8 CXmlPullParser::DocPart(TInt aStartPos, TInt aEndPos)
+ {
+ iDocPart.Set(iDocument.Mid(aStartPos, (aEndPos - aStartPos + 1)));
+ return iDocPart;
+ }
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////////////////////////////////
+TInt CXmlPullParser::SkipLeadingNonRelevantElements()
+ {
+ TPtrC8 token;
+ TInt endStringOffset;
+ TBool prologFound = ETrue;
+ TBool commentFound = ETrue;
+ TBool piFound = ETrue;
+ TBool dtdFound = ETrue;
+
+ iLexer.SkipSpaceAndMark(iMarkPosition); // Remember where we are
+
+ if (iLexer.Eos())
+ {
+ iState = EStateEndDocument;
+ return KErrNone;
+ }
+ else
+ {
+ token.Set(iLexer.Remainder()); // pointer to the rest of the xml document
+
+ while (prologFound || commentFound || piFound || dtdFound)
+ {
+ // check for prolog: if prolog found skip it
+ if (iLexer.Get() == '<' && iLexer.Get() == '?' &&
+ iLexer.Get() == 'x' && iLexer.Get() == 'm' && iLexer.Get() == 'l')
+ {
+ token.Set(iLexer.Remainder()); // pointer to the rest of the xml document
+ if (token.Find(KEndPIAndProlog) != KErrNotFound)
+ {
+ endStringOffset = token.Find(KEndPIAndProlog) + KEndPIAndProlog().Length();
+ iLexer.Inc(endStringOffset);
+ iLexer.SkipSpaceAndMark(iMarkPosition); // Remember where we are
+ prologFound = ETrue;
+ }
+ else
+ {
+ iState = EStateError;
+ return ERcDocumentError; // no end string found
+ }
+ }
+ else
+ {
+ iLexer.UnGetToMark(iMarkPosition);
+ prologFound = EFalse;
+ }
+
+ // check for comment: if found skip it
+ if (iLexer.Get() == '<' && iLexer.Get() == '!' &&
+ iLexer.Get() == '-' && iLexer.Get() == '-')
+ {
+ token.Set(iLexer.Remainder()); // pointer to the rest of the xml document
+ if (token.Find(KEndComment) != KErrNotFound)
+ {
+ endStringOffset = token.Find(KEndComment) + KEndComment().Length();
+ iLexer.Inc(endStringOffset);
+ iLexer.SkipSpaceAndMark(iMarkPosition); // Remember where we are
+ commentFound = ETrue;
+ }
+ else
+ {
+ iState = EStateError;
+ return ERcDocumentError; // no end string found
+ }
+ }
+ else
+ {
+ iLexer.UnGetToMark(iMarkPosition);
+ commentFound = EFalse;
+ }
+
+ // check for processing instructions: if found skip it
+ if (iLexer.Get() == '<' && iLexer.Get() == '?')
+ {
+ token.Set(iLexer.Remainder()); // pointer to the rest of the xml document
+ if (token.Find(KEndPIAndProlog) != KErrNotFound)
+ {
+ endStringOffset = token.Find(KEndPIAndProlog) + KEndPIAndProlog().Length();
+ iLexer.Inc(endStringOffset);
+ iLexer.SkipSpaceAndMark(iMarkPosition); // Remember where we are
+ piFound = ETrue;
+ }
+ else
+ {
+ iState = EStateError;
+ return ERcDocumentError; // no end string found
+ }
+ }
+ else
+ {
+ iLexer.UnGetToMark(iMarkPosition);
+ piFound = EFalse;
+ }
+
+ // check for document type declaration: if found skip it
+ if (iLexer.Get() == '<' && iLexer.Get() == '!' &&
+ iLexer.Get() == 'D' && iLexer.Get() == 'O' &&
+ iLexer.Get() == 'C' && iLexer.Get() == 'T' &&
+ iLexer.Get() == 'Y' && iLexer.Get() == 'P' &&
+ iLexer.Get() == 'E')
+ {
+ token.Set(iLexer.Remainder()); // pointer to the rest of the xml document
+ // if '[' found skip to ']' and then search for '>' (= end of doctype)
+ if (token.Find(KOpenAngleBracket) != KErrNotFound)
+ {
+ iLexer.Inc(token.Find(KOpenAngleBracket)
+ + KOpenAngleBracket().Length());
+ token.Set(iLexer.Remainder());
+ // Search for ']'
+ if (token.Find(KCloseAngleBracket) != KErrNotFound)
+ {
+ iLexer.Inc(token.Find(KCloseAngleBracket) + KCloseAngleBracket().Length());
+ token.Set(iLexer.Remainder());
+ }
+ else
+ {
+ iState = EStateError;
+ return ERcDocumentError; // no end string found
+ }
+ }
+ if (token.Find(KCloseBracket) != KErrNotFound)
+ {
+ endStringOffset = token.Find(KCloseBracket) + KCloseBracket().Length();
+ iLexer.Inc(endStringOffset);
+ iLexer.SkipSpaceAndMark(iMarkPosition); // Remember where we are
+ dtdFound = ETrue;
+ }
+ else
+ {
+ iState = EStateError;
+ return ERcDocumentError; // no end string found
+ }
+ }
+ else
+ {
+ iLexer.UnGetToMark(iMarkPosition);
+ dtdFound = EFalse;
+ }
+ }
+ }
+ return KErrNone;
+ }
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////////////////////////////////
+TInt CXmlPullParser::SkipNonRelevantElements()
+ {
+ TPtrC8 token;
+ TInt endStringOffset;
+ TBool prologFound = ETrue;
+ TBool commentFound = ETrue;
+ TBool piFound = ETrue;
+ TBool dtdFound = ETrue;
+
+ iLexer.Mark(iMarkPosition); // Remember where we are
+
+ if (iLexer.Eos())
+ {
+ iState = EStateEndDocument;
+ return KErrNone;
+ }
+ else
+ {
+ token.Set(iLexer.Remainder()); // pointer to the rest of the xml document
+
+ while (prologFound || commentFound || piFound || dtdFound)
+ {
+ // check for prolog: if prolog found -> error
+ // Spec says: "The document type declaration must appear before
+ // the first element in the document."
+ if (iLexer.Get() == '<' && iLexer.Get() == '?' &&
+ iLexer.Get() == 'x' && iLexer.Get() == 'm' && iLexer.Get() == 'l')
+ {
+ prologFound = ETrue;
+ iState = EStateError;
+ return ERcDocumentError;
+ }
+ else
+ {
+ iLexer.UnGetToMark(iMarkPosition);
+ prologFound = EFalse;
+ }
+
+ // check for comment: if found skip it
+ if (iLexer.Get() == '<' && iLexer.Get() == '!' &&
+ iLexer.Get() == '-' && iLexer.Get() == '-')
+ {
+ token.Set(iLexer.Remainder()); // pointer to the rest of the xml document
+ if (token.Find(KEndComment) != KErrNotFound)
+ {
+ endStringOffset = token.Find(KEndComment) + KEndComment().Length();
+ iLexer.Inc(endStringOffset);
+ iLexer.Mark(iMarkPosition); // Remember where we are
+ commentFound = ETrue;
+ }
+ else
+ {
+ iState = EStateError;
+ return ERcDocumentError; // no end string found
+ }
+ }
+ else
+ {
+ iLexer.UnGetToMark(iMarkPosition);
+ commentFound = EFalse;
+ }
+
+ // check for processing instructions: if found skip it
+ if (iLexer.Get() == '<' && iLexer.Get() == '?')
+ {
+ token.Set(iLexer.Remainder()); // pointer to the rest of the xml document
+ if (token.Find(KEndPIAndProlog) != KErrNotFound)
+ {
+ endStringOffset = token.Find(KEndPIAndProlog) + KEndPIAndProlog().Length();
+ iLexer.Inc(endStringOffset);
+ iLexer.Mark(iMarkPosition); // Remember where we are
+ piFound = ETrue;
+ }
+ else
+ {
+ iState = EStateError;
+ return ERcDocumentError; // no end string found
+ }
+ }
+ else
+ {
+ iLexer.UnGetToMark(iMarkPosition);
+ piFound = EFalse;
+ }
+
+ // check for document type declaration: if found skip it
+ if (iLexer.Get() == '<' && iLexer.Get() == '!' &&
+ iLexer.Get() == 'D' && iLexer.Get() == 'O' &&
+ iLexer.Get() == 'C' && iLexer.Get() == 'T' &&
+ iLexer.Get() == 'Y' && iLexer.Get() == 'P' &&
+ iLexer.Get() == 'E')
+ {
+ token.Set(iLexer.Remainder()); // pointer to the rest of the xml document
+ // if '[' found skip to ']' and then search for '>' (= end of doctype)
+ if (token.Find(KOpenAngleBracket) != KErrNotFound)
+ {
+ iLexer.Inc(token.Find(KOpenAngleBracket)
+ + KOpenAngleBracket().Length());
+ token.Set(iLexer.Remainder());
+ // Search for ']'
+ if (token.Find(KCloseAngleBracket) != KErrNotFound)
+ {
+ iLexer.Inc(token.Find(KCloseAngleBracket) + KCloseAngleBracket().Length());
+ token.Set(iLexer.Remainder());
+ }
+ else
+ {
+ iState = EStateError;
+ return ERcDocumentError; // no end string found
+ }
+ }
+ if (token.Find(KCloseBracket) != KErrNotFound)
+ {
+ endStringOffset = token.Find(KCloseBracket) + KCloseBracket().Length();
+ iLexer.Inc(endStringOffset);
+ iLexer.SkipSpaceAndMark(iMarkPosition); // Remember where we are
+ dtdFound = ETrue;
+ }
+ else
+ {
+ iState = EStateError;
+ return ERcDocumentError; // no end string found
+ }
+
+ }
+ else
+ {
+ iLexer.UnGetToMark(iMarkPosition);
+ dtdFound = EFalse;
+ }
+ }
+ }
+ return KErrNone;
+ }
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////////////////////////////////
+TInt CXmlPullParser::GetElementStartTagL()
+ {
+ TPtrC8 token;
+ TPtrC8 startTag;
+ TInt offset;
+ TInt eqpos;
+ TInt spacepos;
+ TInt attrValueLen;
+ TLex8 tokenLexer;
+ TChar ch;
+
+
+ iLexer.Mark(iMarkPosition); // Remember where we are
+
+ if (iLexer.Eos())
+ {
+ iState = EStateError; // we can not be in the end of the doc when
+ // we should have Start Tag
+ return ERcDocumentError;
+ }
+ else
+ {
+
+ // Delete attributes from iCAttrDataArray
+ iCAttrDataArray->Delete(0, iCAttrDataArray->Count());
+
+
+ if (iLexer.Get() == '<' && iLexer.Peek().IsAlpha())
+ {
+ iLexer.Mark(iMarkPosition); // start of the element
+ token.Set(iLexer.Remainder());
+ offset = token.Find(KCloseBracket);
+
+ // start tag and possible attribute(s)
+ startTag.Set(token.Left(offset));
+ tokenLexer.Assign(startTag);
+
+ // Start tag format: '<' Name (S Attribute)* S?'>'
+ // tag name -> iElement
+ if (startTag.Find(KSpace) == KErrNotFound)
+ {
+ // case: no attributes/space in the start tag
+ iElement.Set(startTag.Left(offset));
+ if (iElement[iElement.Length() - 1] == '/')
+ {
+ iElement.Set(iElement.Left(iElement.Length() - 1));
+ }
+ }
+ else
+ {
+ // case: space after tag name or
+ // case: at least one attribute in the start tag
+ iElement.Set(startTag.Left(startTag.Find(KSpace)));
+ }
+
+ // set state
+ iState = EStateStartTag;
+
+ // Add /tag name to iPathBuf
+ CheckSpaceL(iElement); // Check that there is enough space in iPathBuf
+
+ iPathBufPtr.Append(KSlash); // '/'
+ iPathBufPtr.Append(iElement); // tag name
+
+ // increment iDepth
+ iDepth++;
+
+ while ((eqpos = startTag.Find(KEquals)) != KErrNotFound)
+ {
+ TAttrData startTagAttr;
+ // get attribute(s)
+ spacepos = startTag.Find(KSpace);
+ tokenLexer.Inc(spacepos);
+ startTagAttr.iName.Set(startTag.Mid(spacepos + KSpace().Length(),
+ eqpos - spacepos - KEquals().Length()));
+ // rest of the start tag and attributes
+ startTag.Set(startTag.Right(startTag.Length() - eqpos - KEquals().Length()));
+ tokenLexer.Inc(eqpos - spacepos + KEquals().Length());
+ ch = tokenLexer.Get();
+ if (ch == '\'' || ch == '\"') // this should be ' or "
+ {
+ startTag.Set(startTag.Right(startTag.Length() - 1));
+ // if attribute ending ' or " not found return error
+ if ((attrValueLen = startTag.Locate(ch)) != KErrNotFound)
+ {
+ startTagAttr.iValue.Set(startTag.Left(attrValueLen));
+ iCAttrDataArray->AppendL(startTagAttr);
+ startTag.Set(startTag.Right(startTag.Length() - attrValueLen));
+ tokenLexer.Inc(attrValueLen);
+ }
+ else
+ {
+ iState = EStateError;
+ return ERcDocumentError;
+ }
+ }
+ else
+ {
+ iState = EStateError;
+ return ERcDocumentError;
+ }
+ }
+
+ // check if tag is empty element
+ iLexer.Inc(offset - KCloseBracket().Length()); // iLexer into the end of the tag - 1 position
+ iLexer.Mark(iMarkPosition);
+
+ if (iLexer.Get() == '/') // next char is '>' for sure
+ {
+ iLexer.Inc(KCloseBracket().Length());
+ iIsEmptyElement = ETrue;
+ iLexer.Mark(iMarkPosition);
+ }
+ else if (iLexer.Get() == '>')
+ {
+ iIsEmptyElement = EFalse;
+ iLexer.Mark(iMarkPosition);
+ }
+ else
+ {
+ iState = EStateError;
+ return ERcDocumentError;
+ }
+ }
+ else
+ {
+ iState = EStateError;
+ return ERcDocumentError;
+ }
+ }
+ return KErrNone;
+ }
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////////////////////////////////
+TInt CXmlPullParser::GetElementText()
+ {
+ TPtrC8 elementText;
+ TInt offset;
+ TInt cdataStartOffset;
+ TInt cdataEndOffset;
+
+ iLexer.Mark(iMarkPosition); // Remember where we are
+
+ if (iLexer.Eos())
+ {
+ iState = EStateError; // we can not be in the end of the doc when
+ // we should have Start Tag
+ return ERcDocumentError;
+ }
+ else
+ {
+ elementText.Set(iLexer.Remainder());
+
+ if (iCdataStartFound)
+ {
+ if ((cdataEndOffset = elementText.Find(KEndCData)) != KErrNotFound)
+ {
+ iCdataStartFound = EFalse;
+ iCdataSectionText = ETrue; // text inside CDATA section
+ iText.Set(elementText.Left(cdataEndOffset));
+ if (iText.Find(KStartCData) != KErrNotFound)
+ {
+ // Nested CDATA sections are not allowed
+ iState = EStateError;
+ return ERcDocumentError;
+ }
+ iLexer.Inc(cdataEndOffset + KEndCData().Length());
+ }
+ else
+ {
+ // CDATA end not found -> error
+ iState = EStateError;
+ return ERcDocumentError;
+ }
+ }
+ else
+ {
+ // Start of CDATA section '<![CDATA['
+ if ((cdataStartOffset = elementText.Find(KStartCData)) == 0)
+ {
+ if ((cdataEndOffset = elementText.Find(KEndCData)) != KErrNotFound)
+ {
+ iCdataStartFound = EFalse;
+ iCdataSectionText = ETrue; // text inside CDATA section
+ iText.Set(elementText.Mid(KStartCData().Length(), cdataEndOffset - KStartCData().Length()));
+ if (iText.Find(KStartCData) != KErrNotFound)
+ {
+ // Nested CDATA sections are not allowed
+ iState = EStateError;
+ return ERcDocumentError;
+ }
+ iLexer.Inc(cdataEndOffset + KEndCData().Length());
+ }
+ else
+ {
+ // CDATA end not found -> error
+ iState = EStateError;
+ return ERcDocumentError;
+ }
+ }
+ else
+ {
+ offset = elementText.Find(KOpenBracket); // any '<'
+
+ if ((cdataStartOffset != KErrNotFound) && !(offset < cdataStartOffset))
+ {
+ iCdataStartFound = ETrue;
+ iCdataSectionText = EFalse; // text before CDATA section
+ iText.Set(elementText.Left(cdataStartOffset));
+ iLexer.Inc(cdataStartOffset + KStartCData().Length());
+ }
+ else
+ {
+ // No CDATA section found
+ // iCdataStartFound = EFalse; // this is EFalse any way
+ iCdataSectionText = EFalse;
+ if (offset != KErrNotFound)
+ {
+ iText.Set(elementText.Left(offset));
+ iLexer.Inc(offset);
+ }
+ else
+ {
+ iState = EStateError;
+ return ERcDocumentError;
+ }
+ }
+ }
+ }
+ iState = EStateText;
+ return KErrNone;
+ }
+ }
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////////////////////////////////
+TBool CXmlPullParser::CheckIfNextEndTag()
+ {
+ iLexer.Mark(iMarkPosition);
+
+ if (iLexer.Eos())
+ {
+ iState = EStateError; // we can not be in the end of the doc when
+ // we should have Start/End Tag
+ return ETrue; // the caller must check the iState!!
+ }
+ else
+ {
+ if (iLexer.Get() == '<' && iLexer.Get() == '/')
+ {
+ iLexer.UnGetToMark(iMarkPosition);
+ return ETrue;
+ }
+ else
+ {
+ iLexer.UnGetToMark(iMarkPosition);
+ return EFalse;
+ }
+ }
+ }
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////////////////////////////////
+TBool CXmlPullParser::CheckIfNextStartTag()
+ {
+ iLexer.Mark(iMarkPosition);
+
+ if (iLexer.Eos())
+ {
+ iState = EStateError; // we can not be in the end of the doc when
+ // we should have Start/End Tag
+ return ETrue; // the caller must check the iState!!
+ }
+ else
+ {
+ if (iLexer.Get() == '<' && iLexer.Get().IsAlpha())
+ {
+ iLexer.UnGetToMark(iMarkPosition);
+ return ETrue;
+ }
+ else
+ {
+ iLexer.UnGetToMark(iMarkPosition);
+ return EFalse;
+ }
+ }
+ }
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////////////////////////////////
+TInt CXmlPullParser::GetElementEndTag()
+ {
+ TPtrC8 elementText;
+ TInt offset;
+
+ iLexer.Mark(iMarkPosition); // Remember where we are
+
+ if (iLexer.Eos())
+ {
+ iState = EStateError; // we can not be in the end of the doc when
+ // we should have End Tag
+ return ERcDocumentError;
+ }
+ else
+ {
+ if (iLexer.Get() == '<' && iLexer.Get() == '/')
+ {
+ elementText.Set(iLexer.Remainder());
+ if ((offset = elementText.Find(KCloseBracket)) != KErrNotFound)
+ {
+ // End tag format: '</' Name S? '>'
+ iElement.Set(elementText.Left(offset));
+ if (iElement[iElement.Length() - 1] == ' ')
+ {
+ iElement.Set(iElement.Left(iElement.Length() - 1));
+ }
+
+ // delete /end tag from the iPathBuf
+ // this is done by subtracting the length of the buffer
+ iPathBufPtr.SetLength(iPathBufPtr.LocateReverse('/'));
+
+ // decrement iDepth
+ iDepth--;
+
+ iLexer.Inc(offset + KCloseBracket().Length());
+ iState = EStateEndTag;
+ return KErrNone;
+ }
+ else
+ {
+ iState = EStateError;
+ return ERcDocumentError;
+ }
+ }
+ else
+ {
+ iState = EStateError;
+ return ERcDocumentError;
+ }
+ }
+ }
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////////////////////////////////
+TBool CXmlPullParser::CheckIfEndOfFile()
+ {
+ iLexer.Mark(iMarkPosition);
+
+ if ( (iDepth == 0) && (iPathBufPtr.Length() == 0) )
+ {
+ iState = EStateEndDocument;
+ return ETrue;
+ }
+ else
+ {
+ return EFalse;
+ }
+ }
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////////////////////////////////
+TInt CXmlPullParser::EscapeCharRefAndPreDefEntities()
+ {
+ TInt retVal;
+
+ if (iStringValuePtr.Find(KAmpersandHash) != KErrNotFound)
+ {
+ retVal = CharacterReferencesEscaped(); // handle ª and &#aa;
+ if ( retVal != KErrNone )
+ {
+ return retVal;
+ }
+ }
+
+ if (iStringValuePtr.Find(KAmpersand) != KErrNotFound)
+ {
+ retVal = PredefinedEntitiesEscaped(); // handle < > & ' and "
+ if ( retVal != KErrNone )
+ {
+ return retVal;
+ }
+ }
+
+ return KErrNone;
+ }
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////////////////////////////////
+TInt CXmlPullParser::CharacterReferencesEscaped()
+ {
+ TInt startPos, length;
+ TInt retVal;
+ TInt i = 0;
+ TRadix radix = EDecimal;
+
+ TLex8 tempLexer;
+ TLexMark8 mark;
+ TUint number;
+
+ TPtrC8 tempPtr;
+
+ while ( (startPos = iStringValuePtr.Find(KAmpersandHash)) != KErrNotFound)
+ {
+ tempPtr.Set(iStringValuePtr.Right(iStringValuePtr.Length() - startPos));
+ length = tempPtr.Find(KSemicolon) - KAmpersandHash().Length();
+ tempPtr.Set(iStringValuePtr.Mid(startPos + KAmpersandHash().Length(), length));
+ tempLexer.Assign(tempPtr);
+ if ( tempLexer.Peek() == 'x' )
+ {
+ tempLexer.Inc(); //increment to next character position
+ tempLexer.Mark(mark);
+ for ( i = 0; i < (length - 1); i++ ) // check that whole input is hexadecimal
+ {
+ if ( !(tempLexer.Get()).IsHexDigit() )
+ {
+ return ERcDocumentError; // after &#x there must be hexadecimal digits (0-9, a-f, A-F).
+ }
+ }
+ tempLexer.UnGetToMark(mark);
+ radix = EHex;
+ }
+ else
+ {
+ tempLexer.Mark(mark);
+ for ( i = 0; i < length; i++ )
+ {
+ if ( !(tempLexer.Get()).IsDigit() )
+ {
+ return ERcDocumentError; // after &# there must be standard decimal digits (0-9).
+ }
+ }
+ tempLexer.UnGetToMark(mark);
+ radix = EDecimal;
+ }
+
+ if ( (retVal = tempLexer.Val(number, radix)) == KErrNone)
+ {
+ TChar ch(number);
+ TBuf8<12> buf;
+ buf.Append(ch);
+ iStringValuePtr.Replace(startPos, length + KAmpersandHash().Length() +
+ KSemicolon().Length(), buf);
+ }
+ else
+ {
+ return retVal;
+ }
+ }
+ return KErrNone;
+ }
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////////////////////////////////
+TInt CXmlPullParser::PredefinedEntitiesEscaped()
+ {
+ TInt pos;
+
+ while (iStringValuePtr.Find(KAmpersand) != KErrNotFound)
+ {
+ if ((pos = iStringValuePtr.Find(KEntityLowerThan)) != KErrNotFound)
+ {
+ iStringValuePtr.Replace(pos, KEntityLowerThan().Length(), KOpenBracket);
+ }
+ else if ((pos = iStringValuePtr.Find(KEntityGreaterThan)) != KErrNotFound)
+ {
+ iStringValuePtr.Replace(pos, KEntityGreaterThan().Length(), KCloseBracket);
+ }
+ else if ((pos = iStringValuePtr.Find(KEntityAmpersand)) != KErrNotFound)
+ {
+ iStringValuePtr.Replace(pos, KEntityAmpersand().Length(), KAmpersand);
+ }
+ else if ((pos = iStringValuePtr.Find(KEntityApostrophe)) != KErrNotFound)
+ {
+ iStringValuePtr.Replace(pos, KEntityApostrophe().Length(), KSingleQuote);
+ }
+ else if ((pos = iStringValuePtr.Find(KEntityQuotation)) != KErrNotFound)
+ {
+ iStringValuePtr.Replace(pos, KEntityQuotation().Length(), KDoubleQuote);
+ }
+ else
+ {
+ return KErrNone;
+ }
+ }
+ return KErrNone;
+ }