webservices/wsxml/src/senxmlutils.cpp
changeset 0 62f9d29f7211
equal deleted inserted replaced
-1:000000000000 0:62f9d29f7211
       
     1 /*
       
     2 * Copyright (c) 2002-2005 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:        
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 
       
    21 
       
    22 
       
    23 
       
    24 
       
    25 #include <utf.h>
       
    26 
       
    27 #include "SenXmlConstants.h"
       
    28 #include "SenXmlUtils.h"
       
    29 #include "SenElement.h"
       
    30 #include "SenBaseAttribute.h"
       
    31 
       
    32 #ifdef SYMBIAN_SECURE_ECOM 
       
    33     // for 2.8, 3.0 or newer:
       
    34     #include <xml/attribute.h> // needed for RAttributeArray
       
    35 #else // for 2.6 or olde
       
    36     #include "Attribute.h"
       
    37 #endif
       
    38 
       
    39 using namespace Xml;
       
    40 
       
    41 EXPORT_C HBufC8* SenXmlUtils::ToUtf8LC(const TDesC16& aUnicodeString)
       
    42     {
       
    43     // 6 times multiplier is the worst case...
       
    44     HBufC8* pBuf8 = HBufC8::NewLC(6 * aUnicodeString.Length());
       
    45     TPtr8 des8 = pBuf8->Des();
       
    46     TInt ret = CnvUtfConverter::ConvertFromUnicodeToUtf8(des8, aUnicodeString);
       
    47     User::LeaveIfError(ret);
       
    48 
       
    49     // Shrink allocated memory if possible
       
    50     HBufC8* pReallocBuf8 = pBuf8->ReAlloc(pBuf8->Length());
       
    51     if (pReallocBuf8 != NULL)
       
    52         {
       
    53         // It could reallocate
       
    54         CleanupStack::Pop(); // pop pBuf8;
       
    55         CleanupStack::PushL(pReallocBuf8);
       
    56         pBuf8 = pReallocBuf8;
       
    57         }
       
    58     return pBuf8;
       
    59     }
       
    60 
       
    61 EXPORT_C HBufC16* SenXmlUtils::ToUnicodeLC(const TDesC8& aUtf8String)
       
    62     {
       
    63     HBufC16* pBuf = HBufC16::NewLC(2 * aUtf8String.Length());
       
    64     TPtr16 des = pBuf->Des();
       
    65     TInt ret = CnvUtfConverter::ConvertToUnicodeFromUtf8(des, aUtf8String);
       
    66     User::LeaveIfError(ret);
       
    67     return pBuf;
       
    68     }
       
    69 
       
    70 
       
    71 EXPORT_C TBool SenXmlUtils::StartsWith(const TDesC8& aDes,
       
    72                                        const TDesC8& aPrefix)
       
    73     {
       
    74     if (aDes.Length() < aPrefix.Length())
       
    75         {
       
    76         return EFalse;
       
    77         }
       
    78     else
       
    79         {
       
    80         return (aDes.Left(aPrefix.Length()) == aPrefix);
       
    81         }
       
    82     }
       
    83 
       
    84 EXPORT_C TBool SenXmlUtils::EndsWith(const TDesC8& aDes,
       
    85                                      const TDesC8& aPostfix)
       
    86     {
       
    87     if (aDes.Length() < aPostfix.Length())
       
    88         {
       
    89         return EFalse;
       
    90         }
       
    91     else
       
    92         {
       
    93         return (aDes.Right(aPostfix.Length()) == aPostfix);
       
    94         }
       
    95     }
       
    96 
       
    97 EXPORT_C TPtrC8 SenXmlUtils::NsPrefix(const TDesC8& aQName)
       
    98     {
       
    99     TInt colonPos = aQName.Find(KSenColon);
       
   100     if (colonPos < 0)
       
   101         {
       
   102         return KNullDesC8();
       
   103         }
       
   104     else
       
   105         {
       
   106         return aQName.Left(colonPos);
       
   107         }
       
   108     }
       
   109 
       
   110 EXPORT_C TPtrC8 SenXmlUtils::LocalName(const TDesC8& aQName)
       
   111     {
       
   112     TInt colonPos = aQName.Find(KSenColon);
       
   113     if (colonPos < 0)
       
   114         {
       
   115         return aQName;
       
   116         }
       
   117     else
       
   118         {
       
   119         return aQName.Mid(colonPos + 1);
       
   120         }
       
   121     }
       
   122 
       
   123 EXPORT_C TPtrC8 SenXmlUtils::AttrValue( const RAttributeArray& aAttributes,
       
   124                                         const TDesC8& aAttrName)
       
   125     {
       
   126     TInt count(aAttributes.Count());
       
   127     for (TInt i=0; i<count;i++)
       
   128         {
       
   129         if (aAttributes[i].Attribute().LocalName().DesC() == aAttrName)
       
   130             {
       
   131             return aAttributes[i].Value().DesC();
       
   132             }
       
   133         }
       
   134     return KNullDesC8();
       
   135     }
       
   136 
       
   137 //EXPORT_C TPtrC8 SenXmlUtils::AttrType(const RAttributeArray& aAttributes,
       
   138 //                                        const TDesC8& aAttrName)
       
   139 //  {
       
   140 //  TInt count(aAttributes.Count());
       
   141 //  for (TInt i=0; i<count;i++)
       
   142 //      {
       
   143 //      if (aAttributes[i].Attribute().LocalName().DesC() == aAttrName)
       
   144 //          {
       
   145 //          return aAttributes[i].Type().DesC();
       
   146 //          }
       
   147 //      }
       
   148 //  return KNullDesC8();
       
   149 //  }
       
   150 
       
   151 EXPORT_C void SenXmlUtils::BuildQNameL( const TDesC8& aPrefix,
       
   152                                         const TDesC8& aLocalName,
       
   153                                         HBufC8*& aQName)
       
   154     {
       
   155     aQName = HBufC8::NewLC( aPrefix.Length()+KSenColon().Length()
       
   156                             +aLocalName.Length() );
       
   157     if (aPrefix != KNullDesC8)
       
   158         {
       
   159         aQName->Des().Append(aPrefix);
       
   160         aQName->Des().Append(KSenColon);
       
   161         }
       
   162     aQName->Des().Append(aLocalName);
       
   163     CleanupStack::Pop();
       
   164 
       
   165     }
       
   166 
       
   167 EXPORT_C TBool SenXmlUtils::EncodeHttpCharactersL(const TDesC8& aOriginal,
       
   168                                                      HBufC8*& aEncoded)
       
   169     {
       
   170     TBool retVal = EFalse;
       
   171     delete aEncoded;
       
   172     aEncoded = NULL;
       
   173 
       
   174     if (aOriginal == KNullDesC8)
       
   175         {
       
   176         return retVal;
       
   177         }
       
   178     TPtrC8 tokens[] =
       
   179         {
       
   180         KSenEscapedAmp(),
       
   181         KSenEscapedApos(),
       
   182         KSenEscapedDblQuot(),
       
   183         KSenEscapedGt(),
       
   184         KSenEscapedLt()
       
   185         };
       
   186     TText16 tokenChars[] =
       
   187         {
       
   188         '&',
       
   189         '\'',
       
   190         '\"',
       
   191         '>',
       
   192         '<'
       
   193         };
       
   194     
       
   195     // Replace escaped characters, if any
       
   196     for (TInt i = 0; i < aOriginal.Length(); i++)
       
   197         {
       
   198         TBool foundChar = EFalse;
       
   199         for (TUint j = 0; j < (sizeof(tokenChars) / sizeof(TText16)); j++)
       
   200             {
       
   201             if (aOriginal[i] == tokenChars[j])
       
   202                 {
       
   203                 if (!aEncoded)
       
   204                     {
       
   205                     aEncoded =
       
   206                         HBufC8::NewL(aOriginal.Length() * KSenMaxXmlEscapedLength);
       
   207                     aEncoded->Des().Append(aOriginal.Left(i));
       
   208                     }
       
   209                 foundChar = ETrue;
       
   210                 aEncoded->Des().Append(tokens[j]);
       
   211                 retVal = ETrue; // indicate, that encoding was done
       
   212                 break;
       
   213                 }
       
   214             }
       
   215         if (!foundChar)
       
   216             {
       
   217             if (aEncoded)
       
   218                 {
       
   219                 
       
   220                 aEncoded->Des().Append(aOriginal[i]);
       
   221                 }
       
   222             }
       
   223         }
       
   224 
       
   225     return retVal;
       
   226     }
       
   227 
       
   228 EXPORT_C HBufC8* SenXmlUtils::EncodeHttpCharactersLC( const TDesC8& aOriginal )
       
   229     {
       
   230     HBufC8* pDecoded = NULL;
       
   231     if (!EncodeHttpCharactersL(aOriginal, pDecoded))
       
   232         {
       
   233         // if anything was allocated (never in current implementation)
       
   234         delete pDecoded; 
       
   235         pDecoded = NULL;
       
   236 
       
   237         // make a copy of original, so that caller always knows that
       
   238         // there is something from which to take ownership.
       
   239         pDecoded = aOriginal.AllocL();
       
   240         }
       
   241     CleanupStack::PushL(pDecoded);
       
   242     return pDecoded;
       
   243     }
       
   244 
       
   245 TBool SenXmlUtils::ReplaceAll(TPtr8 aDestination,
       
   246                               const TDesC8& aFrom,
       
   247                               const TDesC8& aTo)
       
   248     {
       
   249     TInt retVal(EFalse);
       
   250     
       
   251     TInt pos = aDestination.Find(aFrom);
       
   252     if (pos != KErrNotFound) retVal = ETrue;
       
   253     
       
   254     while (pos != KErrNotFound)
       
   255         {
       
   256         aDestination.Replace(pos,aFrom.Length(),aTo);
       
   257         pos = aDestination.Find(aFrom);
       
   258         }
       
   259 
       
   260     return retVal;
       
   261     }
       
   262 /**
       
   263  * DecodeHttpCharactersL() returns ETrue, if any XML escaping
       
   264  * (some Basic Entity) character-sequence was decoded.
       
   265  *
       
   266  * Note that aDecoded points to a copy of the original string
       
   267  * even if there were no basic entities to decode. Otherwise,
       
   268  * it points to a newly allocated descriptor, where some
       
   269  * basic entity or entities has been decoded (replaced) from
       
   270  * aOriginal descriptor.
       
   271  * 
       
   272  */
       
   273 EXPORT_C TBool SenXmlUtils::DecodeHttpCharactersL( const TDesC8& aOriginal,
       
   274                                                    HBufC8*& aDecoded )
       
   275     {
       
   276     delete aDecoded;
       
   277     aDecoded = NULL;
       
   278 
       
   279     // make a copy of the original
       
   280     aDecoded = aOriginal.AllocL();
       
   281 
       
   282     TBool retVal(EFalse);
       
   283 
       
   284 
       
   285     // replace all five basic entities with XML escaping counterpart,
       
   286     // if found.
       
   287     if (ReplaceAll(aDecoded->Des(), KSenEscapedAmp(), KSenAmpersandDesC8()))
       
   288         {
       
   289         retVal = ETrue;
       
   290         }
       
   291     if (ReplaceAll(aDecoded->Des(), KSenEscapedApos(), KSenAposDesC8()))
       
   292         {
       
   293         retVal = ETrue;
       
   294         }
       
   295     if (ReplaceAll(aDecoded->Des(), KSenEscapedDblQuot(), KSenDblQuotDesC8()))
       
   296         {
       
   297         retVal = ETrue;
       
   298         }
       
   299     if (ReplaceAll(aDecoded->Des(), KSenEscapedGt(), KSenGtDesC8()))
       
   300         {
       
   301         retVal = ETrue;
       
   302         }
       
   303     if (ReplaceAll(aDecoded->Des(), KSenEscapedLt(), KSenLtDesC8()))
       
   304         {
       
   305         retVal = ETrue;
       
   306         }
       
   307 
       
   308     return retVal;
       
   309     }
       
   310 
       
   311 /**
       
   312 * In Symbian OS v9.1, see
       
   313 * Location: EscapeUtils.h 
       
   314 * Link against: inetprotutil.lib 
       
   315 *
       
   316 */
       
   317 EXPORT_C HBufC8* SenXmlUtils::DecodeHttpCharactersLC(const TDesC8& aOriginal)
       
   318     {
       
   319     HBufC8* pDecoded = NULL;
       
   320 
       
   321     // Attempt to decode. Note, that even if no Basic Entities were
       
   322     // decoded into XML escaping characters (&,',",< or >), this
       
   323     // function will return a pointer to a copy of the original
       
   324     // descriptor.
       
   325     DecodeHttpCharactersL(aOriginal, pDecoded);
       
   326 
       
   327     // Push to cleanup stack
       
   328     CleanupStack::PushL(pDecoded);
       
   329     return pDecoded;
       
   330     }
       
   331 
       
   332 EXPORT_C HBufC8* SenXmlUtils::AllocAttrValueL(  const RAttributeArray& apAttrs,
       
   333                                                 const TDesC8& aAttrName )
       
   334     {
       
   335     TPtrC8 p = AttrValue(apAttrs, aAttrName);
       
   336     if (p == KNullDesC8)
       
   337         {
       
   338         return NULL;
       
   339         }
       
   340     else
       
   341         {
       
   342         return p.AllocL();
       
   343         }
       
   344     }
       
   345 
       
   346 // the non-optimized version:
       
   347 /* 
       
   348 EXPORT_C void SenXmlUtils::LeaveOnXmlEscapesL(const TDesC8& aCandidate)
       
   349     {
       
   350     HBufC8* pValidator = NULL;
       
   351     
       
   352     // check if there are any XML escaping character by calling
       
   353     // basic entity encoding function. 
       
   354     TBool containsEscapes = SenXmlUtils::EncodeHttpCharactersL(aCandidate, pValidator);
       
   355 
       
   356     delete pValidator;
       
   357 
       
   358     if(containsEscapes)
       
   359         {
       
   360         // some XML-escaping character was found.
       
   361         // Indicate with Leave, that the given 
       
   362         // aChars descriptor is illegal, because
       
   363         // it contained invalid characters
       
   364         User::Leave(KErrSenInvalidCharacters);
       
   365         }
       
   366     }
       
   367 */
       
   368 
       
   369 // Optimized, but not throughoutly tested version.
       
   370 // Based on UPnP project optimizations (2005-10-13).
       
   371 
       
   372 EXPORT_C void SenXmlUtils::LeaveOnXmlEscapesL(const TDesC8& aCandidate)
       
   373     {
       
   374     // these are the escapes which are searched after
       
   375     TText16 tokenChars[] =
       
   376         {
       
   377         '&',
       
   378         '\'',
       
   379         '\"',
       
   380         '>',
       
   381         '<'
       
   382         };
       
   383     
       
   384     // Search for XML escaping characters
       
   385     for (TInt i=0; i<aCandidate.Length(); i++)
       
   386         {
       
   387         for (TUint j = 0; j < (sizeof(tokenChars) / sizeof(TText16)); j++)
       
   388             {
       
   389             if (aCandidate[i] == tokenChars[j])
       
   390                 {
       
   391                 // some XML-escaping character was found.
       
   392                 // Indicate with Leave, that the given 
       
   393                 // aChars descriptor is illegal, because
       
   394                 // it contained invalid characters
       
   395                 User::Leave(KErrSenInvalidCharacters);
       
   396                 }
       
   397             }
       
   398         }
       
   399     }
       
   400 
       
   401 void SenXmlUtils::LeaveOnInvalidElementNameL(const TDesC8& aCandidate)
       
   402     {
       
   403     if (aCandidate == KNullDesC8)
       
   404         {
       
   405         User::Leave(KErrSenZeroLengthDescriptor);
       
   406         }
       
   407     SenXmlUtils::LeaveOnXmlEscapesL(aCandidate);
       
   408     }
       
   409 
       
   410 EXPORT_C CSenBaseAttribute* SenXmlUtils::RemoveAttributeL(CSenElement& aElement,
       
   411                                                           const TDesC8& aAttrName)
       
   412     {
       
   413     CSenBaseAttribute* pAttribute = SenXmlUtils::FindAttrL( aElement, aAttrName );
       
   414     if ( pAttribute )
       
   415         {
       
   416         RPointerArray<CSenBaseAttribute>& attributes = aElement.AttributesL();
       
   417         
       
   418         TInt index(attributes.Find(pAttribute));
       
   419         if ( index != KErrNotFound )
       
   420             {
       
   421             attributes.Remove(index); // release ownership
       
   422             }
       
   423         else
       
   424             {
       
   425             // should never occur:
       
   426             pAttribute = NULL; // ownership could not be transferred..
       
   427             }
       
   428         }
       
   429 
       
   430     return pAttribute;
       
   431     }
       
   432 
       
   433 EXPORT_C CSenBaseAttribute* SenXmlUtils::RemoveAttributeL(CSenElement& aElement,
       
   434                                                           CSenBaseAttribute* apAttribute)
       
   435     {
       
   436     return SenXmlUtils::RemoveAttributeL(aElement, apAttribute->Name());
       
   437     }
       
   438     
       
   439 CSenBaseAttribute* SenXmlUtils::FindAttrL( CSenElement& aElement,
       
   440                                            const TDesC8& aName )
       
   441     {
       
   442     RPointerArray<CSenBaseAttribute>& attributes = aElement.AttributesL();
       
   443     
       
   444     TInt count(attributes.Count());
       
   445     for (TInt i = 0; i < count; i++)
       
   446         {
       
   447         CSenBaseAttribute* pAttribute = attributes[i];
       
   448         if ( pAttribute->Name() == aName )
       
   449             {
       
   450             return pAttribute;
       
   451             }
       
   452         }
       
   453 
       
   454     return NULL;
       
   455     }
       
   456 
       
   457 EXPORT_C const TDesC8& SenXmlUtils::AddAttributeL(CSenElement& aElement,
       
   458                                                   const TDesC8& aQName,
       
   459                                                   const TDesC8& aLocalName,
       
   460                                                   const TDesC8& aValue)
       
   461     {
       
   462     // first we check for possible namespace declarations...
       
   463     if ( aQName == KSenXmlns || aLocalName == KSenXmlns)
       
   464         {
       
   465         // this is a default name space declaration
       
   466         aElement.SetNamespaceL(aValue);
       
   467         }
       
   468     else if (aLocalName == aElement.NsPrefix())
       
   469         {
       
   470         //we have a new declaration for the namespace of this element
       
   471         aElement.SetNamespaceL(aLocalName, aValue);
       
   472         }
       
   473     else if(aQName.Find(KSenXmlNsAttNamePlusColon) == 0)
       
   474         {
       
   475         // we have an additional namespace declaration
       
   476         aElement.AddNamespaceL(aLocalName, aValue);
       
   477         }
       
   478     else
       
   479         {
       
   480         // we have a real attribute!
       
   481         CSenBaseAttribute* pAttribute = CSenBaseAttribute::NewL(aQName,
       
   482                                                                 aLocalName,
       
   483                                                                 aValue);
       
   484         AddAttributeL(aElement, pAttribute);
       
   485         }
       
   486     return aValue;
       
   487     }
       
   488 
       
   489 EXPORT_C const TDesC8& SenXmlUtils::AddAttributeL(CSenElement& aElement,
       
   490                                                   const TDesC8& aAttrName,
       
   491                                                   const TDesC8& aValue)
       
   492     {
       
   493     // note, the aAttrName may be a qualified name or simply localname
       
   494     // strip off the possible prefix from possible qualified name:
       
   495     TPtrC8 localName = SenXmlUtils::LocalName(aAttrName);
       
   496     return AddAttributeL(aElement, aAttrName, localName, aValue);
       
   497     }
       
   498     
       
   499 EXPORT_C const TDesC8& SenXmlUtils::AddAttributeL(CSenElement& aElement,
       
   500                                                   CSenBaseAttribute* apAttribute)
       
   501     {
       
   502     CSenBaseAttribute* pOldAtt = FindAttrL( aElement, apAttribute->Name() );
       
   503 
       
   504     if(!pOldAtt)
       
   505         {
       
   506         // transfrer the ownership to this class:
       
   507         RPointerArray<CSenBaseAttribute>& attributes = aElement.AttributesL();
       
   508 #ifdef EKA2
       
   509         attributes.AppendL(apAttribute);
       
   510 #else
       
   511         User::LeaveIfError(attributes.Append(apAttribute));
       
   512 #endif // EKA2
       
   513         return apAttribute->Value();
       
   514         }
       
   515     else
       
   516         {
       
   517         pOldAtt->SetValueL(apAttribute->Value());
       
   518         delete apAttribute;
       
   519         apAttribute = NULL;
       
   520         return pOldAtt->Value();
       
   521         }
       
   522     }
       
   523 
       
   524 // END OF FILE
       
   525