webservices/wsxml/src/senxmlutils.cpp
changeset 0 62f9d29f7211
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/webservices/wsxml/src/senxmlutils.cpp	Thu Jan 07 16:19:19 2010 +0200
@@ -0,0 +1,525 @@
+/*
+* Copyright (c) 2002-2005 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 <utf.h>
+
+#include "SenXmlConstants.h"
+#include "SenXmlUtils.h"
+#include "SenElement.h"
+#include "SenBaseAttribute.h"
+
+#ifdef SYMBIAN_SECURE_ECOM 
+    // for 2.8, 3.0 or newer:
+    #include <xml/attribute.h> // needed for RAttributeArray
+#else // for 2.6 or olde
+    #include "Attribute.h"
+#endif
+
+using namespace Xml;
+
+EXPORT_C HBufC8* SenXmlUtils::ToUtf8LC(const TDesC16& aUnicodeString)
+    {
+    // 6 times multiplier is the worst case...
+    HBufC8* pBuf8 = HBufC8::NewLC(6 * aUnicodeString.Length());
+    TPtr8 des8 = pBuf8->Des();
+    TInt ret = CnvUtfConverter::ConvertFromUnicodeToUtf8(des8, aUnicodeString);
+    User::LeaveIfError(ret);
+
+    // Shrink allocated memory if possible
+    HBufC8* pReallocBuf8 = pBuf8->ReAlloc(pBuf8->Length());
+    if (pReallocBuf8 != NULL)
+        {
+        // It could reallocate
+        CleanupStack::Pop(); // pop pBuf8;
+        CleanupStack::PushL(pReallocBuf8);
+        pBuf8 = pReallocBuf8;
+        }
+    return pBuf8;
+    }
+
+EXPORT_C HBufC16* SenXmlUtils::ToUnicodeLC(const TDesC8& aUtf8String)
+    {
+    HBufC16* pBuf = HBufC16::NewLC(2 * aUtf8String.Length());
+    TPtr16 des = pBuf->Des();
+    TInt ret = CnvUtfConverter::ConvertToUnicodeFromUtf8(des, aUtf8String);
+    User::LeaveIfError(ret);
+    return pBuf;
+    }
+
+
+EXPORT_C TBool SenXmlUtils::StartsWith(const TDesC8& aDes,
+                                       const TDesC8& aPrefix)
+    {
+    if (aDes.Length() < aPrefix.Length())
+        {
+        return EFalse;
+        }
+    else
+        {
+        return (aDes.Left(aPrefix.Length()) == aPrefix);
+        }
+    }
+
+EXPORT_C TBool SenXmlUtils::EndsWith(const TDesC8& aDes,
+                                     const TDesC8& aPostfix)
+    {
+    if (aDes.Length() < aPostfix.Length())
+        {
+        return EFalse;
+        }
+    else
+        {
+        return (aDes.Right(aPostfix.Length()) == aPostfix);
+        }
+    }
+
+EXPORT_C TPtrC8 SenXmlUtils::NsPrefix(const TDesC8& aQName)
+    {
+    TInt colonPos = aQName.Find(KSenColon);
+    if (colonPos < 0)
+        {
+        return KNullDesC8();
+        }
+    else
+        {
+        return aQName.Left(colonPos);
+        }
+    }
+
+EXPORT_C TPtrC8 SenXmlUtils::LocalName(const TDesC8& aQName)
+    {
+    TInt colonPos = aQName.Find(KSenColon);
+    if (colonPos < 0)
+        {
+        return aQName;
+        }
+    else
+        {
+        return aQName.Mid(colonPos + 1);
+        }
+    }
+
+EXPORT_C TPtrC8 SenXmlUtils::AttrValue( const RAttributeArray& aAttributes,
+                                        const TDesC8& aAttrName)
+    {
+    TInt count(aAttributes.Count());
+    for (TInt i=0; i<count;i++)
+        {
+        if (aAttributes[i].Attribute().LocalName().DesC() == aAttrName)
+            {
+            return aAttributes[i].Value().DesC();
+            }
+        }
+    return KNullDesC8();
+    }
+
+//EXPORT_C TPtrC8 SenXmlUtils::AttrType(const RAttributeArray& aAttributes,
+//                                        const TDesC8& aAttrName)
+//  {
+//  TInt count(aAttributes.Count());
+//  for (TInt i=0; i<count;i++)
+//      {
+//      if (aAttributes[i].Attribute().LocalName().DesC() == aAttrName)
+//          {
+//          return aAttributes[i].Type().DesC();
+//          }
+//      }
+//  return KNullDesC8();
+//  }
+
+EXPORT_C void SenXmlUtils::BuildQNameL( const TDesC8& aPrefix,
+                                        const TDesC8& aLocalName,
+                                        HBufC8*& aQName)
+    {
+    aQName = HBufC8::NewLC( aPrefix.Length()+KSenColon().Length()
+                            +aLocalName.Length() );
+    if (aPrefix != KNullDesC8)
+        {
+        aQName->Des().Append(aPrefix);
+        aQName->Des().Append(KSenColon);
+        }
+    aQName->Des().Append(aLocalName);
+    CleanupStack::Pop();
+
+    }
+
+EXPORT_C TBool SenXmlUtils::EncodeHttpCharactersL(const TDesC8& aOriginal,
+                                                     HBufC8*& aEncoded)
+    {
+    TBool retVal = EFalse;
+    delete aEncoded;
+    aEncoded = NULL;
+
+    if (aOriginal == KNullDesC8)
+        {
+        return retVal;
+        }
+    TPtrC8 tokens[] =
+        {
+        KSenEscapedAmp(),
+        KSenEscapedApos(),
+        KSenEscapedDblQuot(),
+        KSenEscapedGt(),
+        KSenEscapedLt()
+        };
+    TText16 tokenChars[] =
+        {
+        '&',
+        '\'',
+        '\"',
+        '>',
+        '<'
+        };
+    
+    // Replace escaped characters, if any
+    for (TInt i = 0; i < aOriginal.Length(); i++)
+        {
+        TBool foundChar = EFalse;
+        for (TUint j = 0; j < (sizeof(tokenChars) / sizeof(TText16)); j++)
+            {
+            if (aOriginal[i] == tokenChars[j])
+                {
+                if (!aEncoded)
+                    {
+                    aEncoded =
+                        HBufC8::NewL(aOriginal.Length() * KSenMaxXmlEscapedLength);
+                    aEncoded->Des().Append(aOriginal.Left(i));
+                    }
+                foundChar = ETrue;
+                aEncoded->Des().Append(tokens[j]);
+                retVal = ETrue; // indicate, that encoding was done
+                break;
+                }
+            }
+        if (!foundChar)
+            {
+            if (aEncoded)
+                {
+                
+                aEncoded->Des().Append(aOriginal[i]);
+                }
+            }
+        }
+
+    return retVal;
+    }
+
+EXPORT_C HBufC8* SenXmlUtils::EncodeHttpCharactersLC( const TDesC8& aOriginal )
+    {
+    HBufC8* pDecoded = NULL;
+    if (!EncodeHttpCharactersL(aOriginal, pDecoded))
+        {
+        // if anything was allocated (never in current implementation)
+        delete pDecoded; 
+        pDecoded = NULL;
+
+        // make a copy of original, so that caller always knows that
+        // there is something from which to take ownership.
+        pDecoded = aOriginal.AllocL();
+        }
+    CleanupStack::PushL(pDecoded);
+    return pDecoded;
+    }
+
+TBool SenXmlUtils::ReplaceAll(TPtr8 aDestination,
+                              const TDesC8& aFrom,
+                              const TDesC8& aTo)
+    {
+    TInt retVal(EFalse);
+    
+    TInt pos = aDestination.Find(aFrom);
+    if (pos != KErrNotFound) retVal = ETrue;
+    
+    while (pos != KErrNotFound)
+        {
+        aDestination.Replace(pos,aFrom.Length(),aTo);
+        pos = aDestination.Find(aFrom);
+        }
+
+    return retVal;
+    }
+/**
+ * DecodeHttpCharactersL() returns ETrue, if any XML escaping
+ * (some Basic Entity) character-sequence was decoded.
+ *
+ * Note that aDecoded points to a copy of the original string
+ * even if there were no basic entities to decode. Otherwise,
+ * it points to a newly allocated descriptor, where some
+ * basic entity or entities has been decoded (replaced) from
+ * aOriginal descriptor.
+ * 
+ */
+EXPORT_C TBool SenXmlUtils::DecodeHttpCharactersL( const TDesC8& aOriginal,
+                                                   HBufC8*& aDecoded )
+    {
+    delete aDecoded;
+    aDecoded = NULL;
+
+    // make a copy of the original
+    aDecoded = aOriginal.AllocL();
+
+    TBool retVal(EFalse);
+
+
+    // replace all five basic entities with XML escaping counterpart,
+    // if found.
+    if (ReplaceAll(aDecoded->Des(), KSenEscapedAmp(), KSenAmpersandDesC8()))
+        {
+        retVal = ETrue;
+        }
+    if (ReplaceAll(aDecoded->Des(), KSenEscapedApos(), KSenAposDesC8()))
+        {
+        retVal = ETrue;
+        }
+    if (ReplaceAll(aDecoded->Des(), KSenEscapedDblQuot(), KSenDblQuotDesC8()))
+        {
+        retVal = ETrue;
+        }
+    if (ReplaceAll(aDecoded->Des(), KSenEscapedGt(), KSenGtDesC8()))
+        {
+        retVal = ETrue;
+        }
+    if (ReplaceAll(aDecoded->Des(), KSenEscapedLt(), KSenLtDesC8()))
+        {
+        retVal = ETrue;
+        }
+
+    return retVal;
+    }
+
+/**
+* In Symbian OS v9.1, see
+* Location: EscapeUtils.h 
+* Link against: inetprotutil.lib 
+*
+*/
+EXPORT_C HBufC8* SenXmlUtils::DecodeHttpCharactersLC(const TDesC8& aOriginal)
+    {
+    HBufC8* pDecoded = NULL;
+
+    // Attempt to decode. Note, that even if no Basic Entities were
+    // decoded into XML escaping characters (&,',",< or >), this
+    // function will return a pointer to a copy of the original
+    // descriptor.
+    DecodeHttpCharactersL(aOriginal, pDecoded);
+
+    // Push to cleanup stack
+    CleanupStack::PushL(pDecoded);
+    return pDecoded;
+    }
+
+EXPORT_C HBufC8* SenXmlUtils::AllocAttrValueL(  const RAttributeArray& apAttrs,
+                                                const TDesC8& aAttrName )
+    {
+    TPtrC8 p = AttrValue(apAttrs, aAttrName);
+    if (p == KNullDesC8)
+        {
+        return NULL;
+        }
+    else
+        {
+        return p.AllocL();
+        }
+    }
+
+// the non-optimized version:
+/* 
+EXPORT_C void SenXmlUtils::LeaveOnXmlEscapesL(const TDesC8& aCandidate)
+    {
+    HBufC8* pValidator = NULL;
+    
+    // check if there are any XML escaping character by calling
+    // basic entity encoding function. 
+    TBool containsEscapes = SenXmlUtils::EncodeHttpCharactersL(aCandidate, pValidator);
+
+    delete pValidator;
+
+    if(containsEscapes)
+        {
+        // some XML-escaping character was found.
+        // Indicate with Leave, that the given 
+        // aChars descriptor is illegal, because
+        // it contained invalid characters
+        User::Leave(KErrSenInvalidCharacters);
+        }
+    }
+*/
+
+// Optimized, but not throughoutly tested version.
+// Based on UPnP project optimizations (2005-10-13).
+
+EXPORT_C void SenXmlUtils::LeaveOnXmlEscapesL(const TDesC8& aCandidate)
+    {
+    // these are the escapes which are searched after
+    TText16 tokenChars[] =
+        {
+        '&',
+        '\'',
+        '\"',
+        '>',
+        '<'
+        };
+    
+    // Search for XML escaping characters
+    for (TInt i=0; i<aCandidate.Length(); i++)
+        {
+        for (TUint j = 0; j < (sizeof(tokenChars) / sizeof(TText16)); j++)
+            {
+            if (aCandidate[i] == tokenChars[j])
+                {
+                // some XML-escaping character was found.
+                // Indicate with Leave, that the given 
+                // aChars descriptor is illegal, because
+                // it contained invalid characters
+                User::Leave(KErrSenInvalidCharacters);
+                }
+            }
+        }
+    }
+
+void SenXmlUtils::LeaveOnInvalidElementNameL(const TDesC8& aCandidate)
+    {
+    if (aCandidate == KNullDesC8)
+        {
+        User::Leave(KErrSenZeroLengthDescriptor);
+        }
+    SenXmlUtils::LeaveOnXmlEscapesL(aCandidate);
+    }
+
+EXPORT_C CSenBaseAttribute* SenXmlUtils::RemoveAttributeL(CSenElement& aElement,
+                                                          const TDesC8& aAttrName)
+    {
+    CSenBaseAttribute* pAttribute = SenXmlUtils::FindAttrL( aElement, aAttrName );
+    if ( pAttribute )
+        {
+        RPointerArray<CSenBaseAttribute>& attributes = aElement.AttributesL();
+        
+        TInt index(attributes.Find(pAttribute));
+        if ( index != KErrNotFound )
+            {
+            attributes.Remove(index); // release ownership
+            }
+        else
+            {
+            // should never occur:
+            pAttribute = NULL; // ownership could not be transferred..
+            }
+        }
+
+    return pAttribute;
+    }
+
+EXPORT_C CSenBaseAttribute* SenXmlUtils::RemoveAttributeL(CSenElement& aElement,
+                                                          CSenBaseAttribute* apAttribute)
+    {
+    return SenXmlUtils::RemoveAttributeL(aElement, apAttribute->Name());
+    }
+    
+CSenBaseAttribute* SenXmlUtils::FindAttrL( CSenElement& aElement,
+                                           const TDesC8& aName )
+    {
+    RPointerArray<CSenBaseAttribute>& attributes = aElement.AttributesL();
+    
+    TInt count(attributes.Count());
+    for (TInt i = 0; i < count; i++)
+        {
+        CSenBaseAttribute* pAttribute = attributes[i];
+        if ( pAttribute->Name() == aName )
+            {
+            return pAttribute;
+            }
+        }
+
+    return NULL;
+    }
+
+EXPORT_C const TDesC8& SenXmlUtils::AddAttributeL(CSenElement& aElement,
+                                                  const TDesC8& aQName,
+                                                  const TDesC8& aLocalName,
+                                                  const TDesC8& aValue)
+    {
+    // first we check for possible namespace declarations...
+    if ( aQName == KSenXmlns || aLocalName == KSenXmlns)
+        {
+        // this is a default name space declaration
+        aElement.SetNamespaceL(aValue);
+        }
+    else if (aLocalName == aElement.NsPrefix())
+        {
+        //we have a new declaration for the namespace of this element
+        aElement.SetNamespaceL(aLocalName, aValue);
+        }
+    else if(aQName.Find(KSenXmlNsAttNamePlusColon) == 0)
+        {
+        // we have an additional namespace declaration
+        aElement.AddNamespaceL(aLocalName, aValue);
+        }
+    else
+        {
+        // we have a real attribute!
+        CSenBaseAttribute* pAttribute = CSenBaseAttribute::NewL(aQName,
+                                                                aLocalName,
+                                                                aValue);
+        AddAttributeL(aElement, pAttribute);
+        }
+    return aValue;
+    }
+
+EXPORT_C const TDesC8& SenXmlUtils::AddAttributeL(CSenElement& aElement,
+                                                  const TDesC8& aAttrName,
+                                                  const TDesC8& aValue)
+    {
+    // note, the aAttrName may be a qualified name or simply localname
+    // strip off the possible prefix from possible qualified name:
+    TPtrC8 localName = SenXmlUtils::LocalName(aAttrName);
+    return AddAttributeL(aElement, aAttrName, localName, aValue);
+    }
+    
+EXPORT_C const TDesC8& SenXmlUtils::AddAttributeL(CSenElement& aElement,
+                                                  CSenBaseAttribute* apAttribute)
+    {
+    CSenBaseAttribute* pOldAtt = FindAttrL( aElement, apAttribute->Name() );
+
+    if(!pOldAtt)
+        {
+        // transfrer the ownership to this class:
+        RPointerArray<CSenBaseAttribute>& attributes = aElement.AttributesL();
+#ifdef EKA2
+        attributes.AppendL(apAttribute);
+#else
+        User::LeaveIfError(attributes.Append(apAttribute));
+#endif // EKA2
+        return apAttribute->Value();
+        }
+    else
+        {
+        pOldAtt->SetValueL(apAttribute->Value());
+        delete apAttribute;
+        apAttribute = NULL;
+        return pOldAtt->Value();
+        }
+    }
+
+// END OF FILE
+