upnpmediaserver/contentdirectoryservice/src/upnpelementfactory.cpp
branchnew development branch with rendering state machine and other goodies
changeset 38 5360b7ddc251
parent 32 3785f754ee62
equal deleted inserted replaced
32:3785f754ee62 38:5360b7ddc251
    17  
    17  
    18 
    18 
    19 // INCLUDE FILES
    19 // INCLUDE FILES
    20 #include <sysutil.h>
    20 #include <sysutil.h>
    21 #include <uri8.h>
    21 #include <uri8.h>
    22 #include <xml/dom/xmlengdomparser.h>
    22 #include <xmlengdomparser.h>
    23 
    23 
    24 #include "upnpelementfactory.h"
    24 #include "upnpelementfactory.h"
    25 #include "upnpcontentdirectoryglobals.h"
    25 #include "upnpcontentdirectoryglobals.h"
    26 #include "upnpstring.h"
    26 #include "upnpstring.h"
    27 #include "upnpprotocolinfo.h"
    27 #include "upnpprotocolinfo.h"
   105         CleanupClosePushL(fs);
   105         CleanupClosePushL(fs);
   106 
   106 
   107         TFileName path;
   107         TFileName path;
   108         User::LeaveIfError(fs.PrivatePath(path));
   108         User::LeaveIfError(fs.PrivatePath(path));
   109 
   109 
       
   110         // Load dll file
       
   111         TFileName objectsXmlFileName( KObjectsXmlFileName() );
       
   112         TFileName dllName;
       
   113         Dll::FileName( dllName );
       
   114         TBuf<2> drive = dllName.Left( 2 ); // Drive letter followed by ':' 
       
   115         objectsXmlFileName.Insert( 0, drive );
       
   116         
   110         TParse fp;
   117         TParse fp;
   111         fp.Set(KObjectsXmlFileName(),&path, 0);
   118         fp.Set(objectsXmlFileName,&path, 0);
   112         path = fp.FullName();
   119         path = fp.FullName();
   113 
   120 
   114         iDocument = parser.ParseFileL( path );        
   121         iDocument = parser.ParseFileL( path );        
   115         CleanupStack::PopAndDestroy(&fs);
   122         CleanupStack::PopAndDestroy(&fs);
   116         }
   123         }
   130 //
   137 //
   131 CUpnpElementFactory::CUpnpElementFactory()
   138 CUpnpElementFactory::CUpnpElementFactory()
   132 {
   139 {
   133 
   140 
   134 }
   141 }
       
   142 
       
   143 // -----------------------------------------------------------------------------
       
   144 // CUpnpElementFactory::CheckRestrictedValue()
       
   145 // -----------------------------------------------------------------------------
       
   146 //
       
   147 TBool CUpnpElementFactory::CheckRestrictedValue (TPtrC8& restrVal)
       
   148     {
       
   149     TBool retVal = EFalse;
       
   150 
       
   151     if ( 
       
   152     (UpnpCD::Kfalse().Compare( restrVal ) != 0) &&
       
   153     (UpnpCD::KZero().Compare( restrVal ) != 0) &&
       
   154     (UpnpCD::Ktrue().Compare( restrVal ) != 0) &&
       
   155     (UpnpCD::KOne().Compare( restrVal ) != 0)
       
   156     )
       
   157         {
       
   158         retVal = ETrue;
       
   159         }
       
   160     return retVal;
       
   161     }
       
   162 
   135 
   163 
   136 // -----------------------------------------------------------------------------
   164 // -----------------------------------------------------------------------------
   137 // CUpnpElementFactory::ValidateNewObjectL()
   165 // CUpnpElementFactory::ValidateNewObjectL()
   138 // Function to validate a new object given by Control Point, especially 
   166 // Function to validate a new object given by Control Point, especially 
   139 // upnp:class element field eg. object.item.musictrack
   167 // upnp:class element field eg. object.item.musictrack
   142 // -----------------------------------------------------------------------------
   170 // -----------------------------------------------------------------------------
   143 //
   171 //
   144 
   172 
   145 TUpnpErrorCode CUpnpElementFactory::ValidateNewObjectL( const TXmlEngElement& aNewElement, TBool aNew, TBool aLocalSharing)
   173 TUpnpErrorCode CUpnpElementFactory::ValidateNewObjectL( const TXmlEngElement& aNewElement, TBool aNew, TBool aLocalSharing)
   146 {
   174 {
   147     /*
       
   148     TInt i;    
   175     TInt i;    
   149     TPtrC8 objectType = KItem();
   176     TPtrC8 objectType = KItem();
   150 
   177 
   151     RXmlEngNodeList<TXmlEngElement> elements;
   178     RXmlEngNodeList<TXmlEngElement> elements;
   152     CleanupClosePushL(elements);
   179     CleanupClosePushL(elements);
   174         objectType.Set( KContainer() );
   201         objectType.Set( KContainer() );
   175     }
   202     }
   176                            
   203                            
   177     // restriced value
   204     // restriced value
   178     TPtrC8 restrVal = UpnpDomInterface::GetAttrValueL( object,  KRestricted );
   205     TPtrC8 restrVal = UpnpDomInterface::GetAttrValueL( object,  KRestricted );
   179     if ( 
   206     
   180     (UpnpCD::Kfalse().Compare( restrVal ) != 0) &&
   207     if (CheckRestrictedValue(restrVal))
   181     (UpnpCD::KZero().Compare( restrVal ) != 0) &&
   208         {
   182     (UpnpCD::Ktrue().Compare( restrVal ) != 0) &&
   209         User::Leave ( EBadMetadata);
   183     (UpnpCD::KOne().Compare( restrVal ) != 0)
   210         }
   184     )
       
   185     {
       
   186         User::Leave( EBadMetadata );
       
   187     }
       
   188     
   211     
   189     // for convenience later, take now a reference to the children of the object
   212     // for convenience later, take now a reference to the children of the object
   190     RXmlEngNodeList<TXmlEngElement> children;
   213     RXmlEngNodeList<TXmlEngElement> children;
   191     CleanupClosePushL(children);
   214     CleanupClosePushL(children);
   192     object.GetChildElements( children );
   215     object.GetChildElements( children );
   268                 CleanupClosePushL(properties);
   291                 CleanupClosePushL(properties);
   269                 ps.GetChildElements( properties );
   292                 ps.GetChildElements( properties );
   270         
   293         
   271                 const TDesC8& propertyType = UpnpDomInterface::GetAttrValueL( ps, KType() );
   294                 const TDesC8& propertyType = UpnpDomInterface::GetAttrValueL( ps, KType() );
   272 
   295 
   273                 TBool elementFound;
   296                 TBool elementFound(EFalse);
   274                 
       
   275 
   297 
   276                 // check each property
   298                 // check each property
   277                 while ( properties.HasNext() )
   299                 while ( properties.HasNext() )
   278                 {
   300                 {
   279                     
   301                     
   280                     TXmlEngElement el = properties.Next();
   302                     TXmlEngElement el = properties.Next();
   281 
   303 
   282                     // Validate element
   304                     elementFound = ValidateElementL (object, propertyType, el, elementFound, aNew, aLocalSharing);
   283                     if ( propertyType == KElement() )
       
   284                     {
       
   285                         elementFound = EFalse;
       
   286                         
       
   287                         // Check if this element is requiered
       
   288                         const TDesC8& required = UpnpDomInterface::GetAttrValueL( el, KRequiredObject() );
       
   289 
       
   290                         TPtrC8 elementName = UpnpDomInterface::GetAttrValueL( el, KName() );
       
   291 
       
   292                         // If it's required then check it's existence
       
   293 
       
   294                         if ( required == UpnpCD::KOne() || elementName == KRes()  ||  elementName == KAlbumArtURI() )
       
   295                         {
       
   296                         if( !KRes().Compare(elementName) ||  !KAlbumArtURI().Compare(elementName))
       
   297                         {
       
   298                             elementFound = ETrue;
       
   299                         }
       
   300                             // get children once more, because this kind of list does not have any reset function
       
   301                             object.GetChildElements( children );
       
   302                             while ( children.HasNext() )
       
   303                             {
       
   304                                 
       
   305                                 TXmlEngElement child = children.Next();
       
   306                                 
       
   307                                 HBufC8* nameWithNs = NameWithNsLC( child );
       
   308 
       
   309                                 if ( *nameWithNs == elementName )
       
   310                                 {
       
   311                                     // local sharing
       
   312                                     if(aNew && *nameWithNs == KRes)
       
   313                                     {
       
   314                                         TUriParser8 up;
       
   315                                         TPtrC8 rv(child.Text());
       
   316                                         if(rv.Length())
       
   317                                         {
       
   318                                             User::LeaveIfError( up.Parse(child.Text()) );
       
   319                                             TPtrC8 path( up.Extract(EUriPath) );
       
   320                                             TPtrC8 scheme( up.Extract(EUriScheme) );
       
   321 
       
   322                                             if(aLocalSharing)
       
   323                                             { // local action
       
   324                                                 if( scheme == UpnpHTTP::KSchemeFile8())
       
   325                                                 {
       
   326                                                     // The path can be: /c:/....
       
   327                                                     // or /c/... - without colon.
       
   328                                                     // Both situation are correct but 
       
   329                                                     // in further operations we assume 
       
   330                                                     // there is not any colon next to the drive letter.
       
   331                                                     // Therefore, remove it if second element of path table equals ':'
       
   332                                                     if(path[2] == KColon8()[0])
       
   333                                                     { // There IS a colon next to the drive letter.
       
   334                                                         // Here is an example uri:
       
   335                                                         // file:///c:/...
       
   336                                                         // As you can see the second colon must be removed
       
   337                                                         HBufC8* uri = child.Text().AllocLC();
       
   338                                                         TPtr8 uriPtr(uri->Des());
       
   339                                                         TPtrC8 tmp(uri->Des());
       
   340                                                         TInt second = 2;
       
   341                                                         TInt colonPos = 0;
       
   342                                                         for(TInt i = 0; i < second; i++)
       
   343                                                         {
       
   344                                                             colonPos += tmp.Find(KColon8) + 1;
       
   345                                                             tmp.Set( uriPtr.Mid(colonPos) );                                                    
       
   346                                                         }
       
   347                                                         // remove the colon
       
   348                                                         uriPtr.Replace(colonPos - 1, KColon8().Length(), KNullString8);
       
   349                                                         // set TXmlEngElement value
       
   350                                                         child.SetTextL(uriPtr);
       
   351                                                         
       
   352                                                         // clean up             
       
   353                                                         CleanupStack::PopAndDestroy(uri);                                               
       
   354                                                     }
       
   355                         
       
   356                                                     // check other  restrictions
       
   357                                                     TUriParser8 up;
       
   358                                                     User::LeaveIfError( up.Parse(child.Text()) );
       
   359                                                     TPtrC8 path( up.Extract(EUriPath) );
       
   360 
       
   361                                                     // sharing from Z: drive is forbidden
       
   362                                                     // second character is a drive letter
       
   363                                                     if(path[1] == KForbiddenDrivez()[0] || path[1] == KForbiddenDriveZ()[0])
       
   364                                                     {
       
   365                                                         User::Leave(EArgumentValue);
       
   366                                                     }
       
   367                                                     
       
   368                                                     // cannot share from private directory
       
   369                                                     if(!path.Match(KForbiddenPrivatePattern))
       
   370                                                     {
       
   371                                                         User::Leave(EArgumentValue);
       
   372                                                     }
       
   373                                                     
       
   374                                                 }
       
   375                                             }
       
   376                                             else
       
   377                                             { // not local action
       
   378                                                 // "file" schema is forbidden here
       
   379                                                 if(scheme == UpnpHTTP::KSchemeFile8())
       
   380                                                 {
       
   381                                                     User::Leave(EArgumentValue);
       
   382                                                 }
       
   383                                             }
       
   384                                         }
       
   385                                     }
       
   386 
       
   387 
       
   388                                     if ( elementFound ) 
       
   389                                     {
       
   390                                         // multiple values for one element!
       
   391                                         const TDesC8& multiple = UpnpDomInterface::GetAttrValueL( el, KMultiple() );
       
   392                                         
       
   393                                         // if it's not allowed for this element, leave!
       
   394                                         if ( !multiple.Length() )
       
   395                                         {
       
   396                                             User::Leave( EInvalidArgs );
       
   397                                         }
       
   398                                     }
       
   399                                     elementFound = ETrue;
       
   400                                     // mark the element required - if not res
       
   401                                     if( KRes().Compare(elementName) && KAlbumArtURI().Compare(elementName))
       
   402                                     {
       
   403                                         child.AddNewAttributeL(KRequiredAtrName,KTrueValue8);
       
   404                                     }
       
   405                                     
       
   406                                     // nested validation 
       
   407                                     RXmlEngNodeList<TXmlEngElement> nestEls;
       
   408                                     CleanupClosePushL(nestEls);
       
   409                                     el.GetChildElements(nestEls);
       
   410                                     while(nestEls.HasNext())
       
   411                                     {
       
   412                                         TXmlEngElement nestPs = nestEls.Next();
       
   413 
       
   414                                         // take the properties
       
   415                                         RXmlEngNodeList<TXmlEngElement> nestProperties;
       
   416                                         nestPs.GetChildElements( nestProperties );
       
   417                                         const TDesC8& nestPropertyType = UpnpDomInterface::GetAttrValueL( nestPs, KType() );
       
   418                                         // Validate attribute   
       
   419                                         if ( nestPropertyType == KAttribute() )
       
   420                                         {
       
   421                                             while(nestProperties.HasNext())
       
   422                                             {   
       
   423                                                 TXmlEngElement nestEl = nestProperties.Next();
       
   424                                                 //TBool nestElementFound;
       
   425 
       
   426                                                 //nestElementFound = EFalse;
       
   427                                                 
       
   428                                                 const TDesC8& nestRequired = UpnpDomInterface::GetAttrValueL( nestEl, KRequiredObject() );
       
   429                                                 TPtrC8 nestElementName = UpnpDomInterface::GetAttrValueL( nestEl, KName() );
       
   430                                                 if ( nestRequired == UpnpCD::KOne() || nestElementName == KDlnaProfileID)
       
   431                                                 {
       
   432                                                     TPtrC8 nestCurrentValue = UpnpDomInterface::GetAttrValueL( child, nestElementName );
       
   433                                                     
       
   434                                                     TPtrC8 nameOfAttr;
       
   435                                                     TPtrC8 valOfAttr;
       
   436                                                     nameOfAttr.Set( nestElementName );
       
   437                                                     
       
   438                                                     // Start of 'dlna:profileID' attribute case                                                 
       
   439                                                     if( nameWithNs->Des() == KAlbumArtURI && nestElementName == KDlnaProfileID) // ---------------- 1 ------------
       
   440                                                     {   
       
   441                                                         TXmlEngAttr profId = child.AttributeNodeL(KProfileID, KXmlnsDlna);
       
   442                                                         if(profId.NotNull())
       
   443                                                         {
       
   444                                                             if (profId.Value().Compare(KDefaultProfileID))
       
   445                                                             {
       
   446                                                                 User::Leave( EBadMetadata );
       
   447                                                             }
       
   448                                                             // setting real name of attribute -> localName
       
   449                                                             nestElementName.Set(KProfileID); // descriptor  
       
   450                                                             nameOfAttr.Set( nestElementName ); // related TString
       
   451                                                                                                                                                                                                                                                                                             
       
   452                                                             // generating a new value of 'dlna:profileID'
       
   453                                                             HBufC8* albumArtURIelemValue = UpnpDomInterface::GetElementValueL(child).AllocLC();
       
   454                                                             TPtr8 albumArtURIelemValuePtr( albumArtURIelemValue->Des() );                                                       
       
   455                                                             
       
   456                                                             albumArtURIelemValuePtr.Trim(); // deletes leading and trailing whitespace characters                                                   
       
   457                                                             child.SetValueL(albumArtURIelemValuePtr); // sets new trimmed value to albumArtURI
       
   458                                                                                                                                                         
       
   459                                                             CUpnpDlnaProtocolInfo* tempProtocolInfo = NULL;
       
   460                                                             TInt error = iContentDirectory->GetProtocolInfoL( albumArtURIelemValuePtr, tempProtocolInfo );
       
   461                                                             TPtrC8 tempPnParam;
       
   462                                                             if( error >=0 )
       
   463                                                             {
       
   464                                                                 tempPnParam.Set( tempProtocolInfo->PnParameter() );
       
   465                                                                     
       
   466                                                                 nestCurrentValue.Set(tempPnParam); // descriptor
       
   467                                                                 valOfAttr.Set(tempPnParam); // related TString                                                         
       
   468                                                             }
       
   469                                                             else 
       
   470                                                             {
       
   471                                                                 User::Leave( EBadMetadata );
       
   472                                                             }                                                       
       
   473                                                             CleanupStack::PopAndDestroy(albumArtURIelemValue);
       
   474                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
       
   475                                                             // if albumArtURI doesn't contain profileID -> it creates one and also related namespace
       
   476                                                             // if albumArtURI contains profileID -> it modifies profileID's value
       
   477                                                             child.SetAttributeL( nameOfAttr, valOfAttr, KXmlnsDlna(), KDlnaPrefix() );
       
   478                                                                                                                     
       
   479                                                             delete tempProtocolInfo;
       
   480                                                             tempProtocolInfo = NULL;    
       
   481                                                         }
       
   482                                                         
       
   483                                                     } // End of 'dlna:profileID' attribute case
       
   484                                                     else                    
       
   485                                                     {
       
   486                                                         if ( !nestCurrentValue.Length() )  
       
   487                                                         {
       
   488                                                             
       
   489                                                             if(nestElementName == KprotocolInfo)
       
   490                                                             {
       
   491                                                                 if( ! aLocalSharing )
       
   492                                                                 {
       
   493                                                                     valOfAttr.Set( KEmptyProtocolInfoVal8() );
       
   494                                                                 }
       
   495                                                                 else 
       
   496                                                                 {
       
   497                                                                     User::Leave( EBadMetadata );
       
   498                                                                 }
       
   499                                                             }                                                                                                   //------- 2 -----                                                                                    //------- 2 -----                  
       
   500                                                             else
       
   501                                                             {
       
   502                                                                 valOfAttr.Set( KNullDesC8() );
       
   503                                                             }
       
   504                                 
       
   505                                                             child.AddNewAttributeL( nameOfAttr, valOfAttr );                                                            
       
   506                                                         }
       
   507                                                         else 
       
   508                                                         {
       
   509                                                             if(nestElementName == KprotocolInfo) 
       
   510                                                             {
       
   511                                                                 HBufC8* protInfoValue = NULL;
       
   512                                                                 TRAPD(err, protInfoValue = ValidateProtocolInfoInResL( nestCurrentValue, aLocalSharing ));
       
   513                                                                 if(err)
       
   514                                                                 {
       
   515                                                                     User::Leave(EBadMetadata);
       
   516                                                                 }
       
   517                                                                 CleanupStack::PushL( protInfoValue );
       
   518                                                                 valOfAttr.Set( *protInfoValue );
       
   519                                                                 child.SetAttributeL( nameOfAttr, valOfAttr );
       
   520                                                                 CleanupStack::PopAndDestroy( protInfoValue );                                                           
       
   521                                                             }                                                                                                 //------- 3 -----                                                                                         //------- 3 -----
       
   522                                                         }
       
   523                                                     }                                                                                                                                                                                                                                                                                                                                                                                       
       
   524                                                                                                         
       
   525 
       
   526                                                     // if not main tag mark the attr is required
       
   527                                                     if( !IsMainObjectTagL(child) && nestElementName != KDlnaProfileID)
       
   528                                                     {
       
   529                                                        
       
   530                                                         HBufC8* attrReq = HBufC8::NewLC(
       
   531                                                             nestElementName.Length()
       
   532                                                             +KRequiredAtrSuf().Length() );
       
   533                                                         TPtr8 attrReqPtr(attrReq->Des());
       
   534                                                         attrReqPtr = nestElementName;
       
   535                                                         attrReqPtr.Append(KRequiredAtrSuf);
       
   536                                                         child.AddNewAttributeL( attrReqPtr, KTrueValue8 );
       
   537                                                         CleanupStack::PopAndDestroy(attrReq);
       
   538                                                     }
       
   539                                                 }
       
   540                                             }
       
   541                                         }
       
   542                                     
       
   543                                     }
       
   544                                     CleanupStack::PopAndDestroy(&nestEls);
       
   545                                 }
       
   546                                 CleanupStack::PopAndDestroy( nameWithNs );
       
   547                                 
       
   548                             }
       
   549                                 
       
   550                             // If not found, add it
       
   551                             if ( !elementFound )
       
   552                             {
       
   553                                 User::Leave(EBadMetadata);
       
   554                             }
       
   555                         } 
       
   556                     }
       
   557                         
   305                         
   558                     // Validate attribute   
   306                     // Validate attribute   
   559                     if ( propertyType == KAttribute() )
   307                     if ( propertyType == KAttribute() )
   560                     {
   308                     {
   561                         elementFound = EFalse;
   309                         elementFound = EFalse;
   562                         
   310                         ValidateAttributeL(el, object);
   563                         const TDesC8& required = UpnpDomInterface::GetAttrValueL( el, KRequiredObject() );
       
   564                         if ( required == UpnpCD::KOne() )
       
   565                         {
       
   566 
       
   567                             const TDesC8& elementName = UpnpDomInterface::GetAttrValueL( el, KName() );
       
   568 
       
   569                             const TDesC8& currentValue = UpnpDomInterface::GetAttrValueL( object, elementName );
       
   570                             
       
   571                             if ( !currentValue.Length() )  
       
   572                             {
       
   573                                 TXmlEngAttr attr = object.AttributeNodeL( elementName );
       
   574 
       
   575                                 if(attr.NotNull())
       
   576                                 {
       
   577                                     attr.SetValueL(KNullDesC8);
       
   578                                 }
       
   579                                 else
       
   580                                 {
       
   581                                     object.AddNewAttributeL( elementName, KNullDesC8 );
       
   582                                 }                               
       
   583                             }
       
   584                             // if not main tag mark the attr is required
       
   585                             if(!IsMainObjectTagL(object))
       
   586                             {
       
   587                                 HBufC8* attrReq = HBufC8::NewLC(
       
   588                                     elementName.Length()+KRequiredAtrSuf().Length() );
       
   589                                 TPtr8 attrReqPtr(attrReq->Des());
       
   590                                 attrReqPtr = elementName;
       
   591                                 attrReqPtr.Append(KRequiredAtrSuf);
       
   592                                 object.AddNewAttributeL( attrReqPtr, KTrueValue8 );
       
   593                                 CleanupStack::PopAndDestroy(attrReq);
       
   594                             }
       
   595                         }
       
   596                     }
   311                     }
   597                 }
   312                 }
   598                 CleanupStack::PopAndDestroy(&properties);
   313                 CleanupStack::PopAndDestroy(&properties);
   599             }
   314             }
   600         }
   315         }
   605     
   320     
   606     // now the object 
   321     // now the object 
   607     // * has the all required fields (if some were missing, they are added)
   322     // * has the all required fields (if some were missing, they are added)
   608     // * had a proper xml structure (_not_ using UpnpDomInterface:: functions that do not care)
   323     // * had a proper xml structure (_not_ using UpnpDomInterface:: functions that do not care)
   609     // * has for sure a mostly proper object structure 
   324     // * has for sure a mostly proper object structure 
   610 */
   325 
   611     return EUndefined;
   326     return EUndefined;
   612 }
   327 }
       
   328 
       
   329 TBool CUpnpElementFactory::ValidateElementL (TXmlEngElement aObject, 
       
   330         const TDesC8& aPropertyType, TXmlEngElement aEl, TBool aElementFound, TBool aNew,
       
   331         TBool aLocalSharing)
       
   332     {
       
   333         TBool elementFound = aElementFound;
       
   334         RXmlEngNodeList<TXmlEngElement> children;
       
   335         // Validate element
       
   336         if ( aPropertyType == KElement() )
       
   337         {
       
   338             elementFound = EFalse;
       
   339             
       
   340             // Check if this element is requiered
       
   341             const TDesC8& required = UpnpDomInterface::GetAttrValueL( aEl, KRequiredObject() );
       
   342     
       
   343             TPtrC8 elementName = UpnpDomInterface::GetAttrValueL( aEl, KName() );
       
   344     
       
   345             // If it's required then check it's existence
       
   346     
       
   347             if ( required == UpnpCD::KOne() || elementName == KRes()  ||  elementName == KAlbumArtURI() )
       
   348             {
       
   349                 if( !KRes().Compare(elementName) ||  !KAlbumArtURI().Compare(elementName))
       
   350                 {
       
   351                     elementFound = ETrue;
       
   352                 }
       
   353                 // get children once more, because this kind of list does not have any reset function
       
   354                 aObject.GetChildElements( children );
       
   355     
       
   356                 elementFound = HandleChildrenL (children, aNew, aLocalSharing, elementFound, aEl);
       
   357                     
       
   358                 // If not found, add it
       
   359                 if ( !elementFound )
       
   360                 {
       
   361                     User::Leave(EBadMetadata);
       
   362                 }
       
   363             } 
       
   364         }
       
   365         return elementFound;
       
   366     }
       
   367 
       
   368 TBool CUpnpElementFactory::HandleChildrenL (RXmlEngNodeList<TXmlEngElement> aChildren, TBool aNew, TBool aLocalSharing,
       
   369         TBool aElementFound, TXmlEngElement aEl)
       
   370     {
       
   371     TBool elementFound = aElementFound;
       
   372     TPtrC8 elementName = UpnpDomInterface::GetAttrValueL( aEl, KName() );
       
   373     
       
   374     while ( aChildren.HasNext() )
       
   375     {
       
   376         TXmlEngElement child = aChildren.Next();
       
   377         
       
   378         HBufC8* nameWithNs = NameWithNsLC( child );
       
   379 
       
   380         if ( *nameWithNs == elementName )
       
   381         {
       
   382             // local sharing
       
   383             if(aNew && *nameWithNs == KRes)
       
   384             {
       
   385                 TUriParser8 up;
       
   386                 TPtrC8 rv(child.Text());
       
   387                 if(rv.Length())
       
   388                 {
       
   389                     User::LeaveIfError( up.Parse(child.Text()) );
       
   390                     TPtrC8 path( up.Extract(EUriPath) );
       
   391                     TPtrC8 scheme( up.Extract(EUriScheme) );
       
   392 
       
   393                     if(aLocalSharing)
       
   394                     { // local action
       
   395                         if( scheme == UpnpHTTP::KSchemeFile8())
       
   396                         {
       
   397                             // The path can be: /c:/....
       
   398                             // or /c/... - without colon.
       
   399                             // Both situation are correct but 
       
   400                             // in further operations we assume 
       
   401                             // there is not any colon next to the drive letter.
       
   402                             // Therefore, remove it if second element of path table equals ':'
       
   403                             if(path[2] == KColon8()[0])
       
   404                             { // There IS a colon next to the drive letter.
       
   405                                 // Here is an example uri:
       
   406                                 // file:///c:/...
       
   407                                 // As you can see the second colon must be removed
       
   408                                 HBufC8* uri = child.Text().AllocLC();
       
   409                                 TPtr8 uriPtr(uri->Des());
       
   410                                 TPtrC8 tmp(uri->Des());
       
   411                                 TInt second = 2;
       
   412                                 TInt colonPos = 0;
       
   413                                 for(TInt i = 0; i < second; i++)
       
   414                                 {
       
   415                                     colonPos += tmp.Find(KColon8) + 1;
       
   416                                     tmp.Set( uriPtr.Mid(colonPos) );                                                    
       
   417                                 }
       
   418                                 // remove the colon
       
   419                                 uriPtr.Replace(colonPos - 1, KColon8().Length(), KNullString8);
       
   420                                 // set TXmlEngElement value
       
   421                                 child.SetTextL(uriPtr);
       
   422                                 
       
   423                                 // clean up             
       
   424                                 CleanupStack::PopAndDestroy(uri);                                               
       
   425                             }
       
   426 
       
   427                             // check other  restrictions
       
   428                             TUriParser8 up;
       
   429                             User::LeaveIfError( up.Parse(child.Text()) );
       
   430                             TPtrC8 path( up.Extract(EUriPath) );
       
   431 
       
   432                             // sharing from Z: drive is forbidden
       
   433                             // second character is a drive letter
       
   434                             if(path[1] == KForbiddenDrivez()[0] || path[1] == KForbiddenDriveZ()[0])
       
   435                             {
       
   436                                 User::Leave(EArgumentValue);
       
   437                             }
       
   438                             
       
   439                             // cannot share from private directory
       
   440                             if(!path.Match(KForbiddenPrivatePattern))
       
   441                             {
       
   442                                 User::Leave(EArgumentValue);
       
   443                             }
       
   444                             
       
   445                         }
       
   446                     }
       
   447                     else
       
   448                     { // not local action
       
   449                         // "file" schema is forbidden here
       
   450                         if(scheme == UpnpHTTP::KSchemeFile8())
       
   451                         {
       
   452                             User::Leave(EArgumentValue);
       
   453                         }
       
   454                     }
       
   455                 }
       
   456             }
       
   457 
       
   458 
       
   459             if ( elementFound ) 
       
   460             {
       
   461                 // multiple values for one element!
       
   462                 const TDesC8& multiple = UpnpDomInterface::GetAttrValueL( aEl, KMultiple() );
       
   463                 
       
   464                 // if it's not allowed for this element, leave!
       
   465                 if ( !multiple.Length() )
       
   466                 {
       
   467                     User::Leave( EInvalidArgs );
       
   468                 }
       
   469             }
       
   470             elementFound = ETrue;
       
   471             // mark the element required - if not res
       
   472             if( KRes().Compare(elementName) && KAlbumArtURI().Compare(elementName))
       
   473             {
       
   474                 child.AddNewAttributeL(KRequiredAtrName,KTrueValue8);
       
   475             }
       
   476             
       
   477             // nested validation 
       
   478             RXmlEngNodeList<TXmlEngElement> nestEls;
       
   479             CleanupClosePushL(nestEls);
       
   480             aEl.GetChildElements(nestEls);
       
   481             CheckNestedElementsL(nestEls, child, aLocalSharing);
       
   482             CleanupStack::PopAndDestroy(&nestEls);
       
   483         }
       
   484         CleanupStack::PopAndDestroy( nameWithNs );
       
   485         
       
   486     }
       
   487 
       
   488     return elementFound;
       
   489 }
       
   490 
       
   491 
       
   492 void CUpnpElementFactory::CheckNestedElementsL(RXmlEngNodeList<TXmlEngElement> aNestEls, TXmlEngElement aChild,
       
   493         TBool aLocalSharing)
       
   494 {
       
   495     HBufC8* nameWithNs = NameWithNsLC( aChild );
       
   496     while(aNestEls.HasNext())
       
   497     {
       
   498         TXmlEngElement nestPs = aNestEls.Next();
       
   499     
       
   500         // take the properties
       
   501         RXmlEngNodeList<TXmlEngElement> nestProperties;
       
   502         nestPs.GetChildElements( nestProperties );
       
   503         const TDesC8& nestPropertyType = UpnpDomInterface::GetAttrValueL( nestPs, KType() );
       
   504         // Validate attribute   
       
   505         if ( nestPropertyType == KAttribute() )
       
   506         {
       
   507             while(nestProperties.HasNext())
       
   508             {   
       
   509                 TXmlEngElement nestEl = nestProperties.Next();
       
   510                 //TBool nestElementFound;
       
   511     
       
   512                 //nestElementFound = EFalse;
       
   513                 
       
   514                 const TDesC8& nestRequired = UpnpDomInterface::GetAttrValueL( nestEl, KRequiredObject() );
       
   515                 TPtrC8 nestElementName = UpnpDomInterface::GetAttrValueL( nestEl, KName() );
       
   516                 if ( nestRequired == UpnpCD::KOne() || nestElementName == KDlnaProfileID)
       
   517                 {
       
   518                     TPtrC8 nestCurrentValue = UpnpDomInterface::GetAttrValueL( aChild, nestElementName );
       
   519                     
       
   520                     TPtrC8 nameOfAttr;
       
   521                     TPtrC8 valOfAttr;
       
   522                     nameOfAttr.Set( nestElementName );
       
   523                     
       
   524                     // Start of 'dlna:profileID' attribute case                                                 
       
   525                     if( nameWithNs->Des() == KAlbumArtURI && nestElementName == KDlnaProfileID) // ---------------- 1 ------------
       
   526                     {   
       
   527                         TXmlEngAttr profId = aChild.AttributeNodeL(KProfileID, KXmlnsDlna);
       
   528                         if(profId.NotNull())
       
   529                         {
       
   530                             if (profId.Value().Compare(KDefaultProfileID))
       
   531                             {
       
   532                                 User::Leave( EBadMetadata );
       
   533                             }
       
   534                             // setting real name of attribute -> localName
       
   535                             nestElementName.Set(KProfileID); // descriptor  
       
   536                             nameOfAttr.Set( nestElementName ); // related TString
       
   537                                                                                                                                                                                                                                                             
       
   538                             // generating a new value of 'dlna:profileID'
       
   539                             HBufC8* albumArtURIelemValue = UpnpDomInterface::GetElementValueL(aChild).AllocLC();
       
   540                             TPtr8 albumArtURIelemValuePtr( albumArtURIelemValue->Des() );                                                       
       
   541                             
       
   542                             albumArtURIelemValuePtr.Trim(); // deletes leading and trailing whitespace characters                                                   
       
   543                             aChild.SetValueL(albumArtURIelemValuePtr); // sets new trimmed value to albumArtURI
       
   544                                                                                                                         
       
   545                             CUpnpDlnaProtocolInfo* tempProtocolInfo = NULL;
       
   546                             TInt error = iContentDirectory->GetProtocolInfoL( albumArtURIelemValuePtr, tempProtocolInfo );
       
   547                             TPtrC8 tempPnParam;
       
   548                             if( error >=0 )
       
   549                             {
       
   550                                 tempPnParam.Set( tempProtocolInfo->PnParameter() );
       
   551                                     
       
   552                                 nestCurrentValue.Set(tempPnParam); // descriptor
       
   553                                 valOfAttr.Set(tempPnParam); // related TString                                                         
       
   554                             }
       
   555                             else 
       
   556                             {
       
   557                                 User::Leave( EBadMetadata );
       
   558                             }                                                       
       
   559                             CleanupStack::PopAndDestroy(albumArtURIelemValue);
       
   560                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
       
   561                             // if albumArtURI doesn't contain profileID -> it creates one and also related namespace
       
   562                             // if albumArtURI contains profileID -> it modifies profileID's value
       
   563                             aChild.SetAttributeL( nameOfAttr, valOfAttr, KXmlnsDlna(), KDlnaPrefix() );
       
   564                                                                                     
       
   565                             delete tempProtocolInfo;
       
   566                             tempProtocolInfo = NULL;    
       
   567                         }
       
   568                         
       
   569                     } // End of 'dlna:profileID' attribute case
       
   570                     else                    
       
   571                     {
       
   572                         if ( !nestCurrentValue.Length() )  
       
   573                         {
       
   574                             
       
   575                             if(nestElementName == KprotocolInfo)
       
   576                             {
       
   577                                 if( ! aLocalSharing )
       
   578                                 {
       
   579                                     valOfAttr.Set( KEmptyProtocolInfoVal8() );
       
   580                                 }
       
   581                                 else 
       
   582                                 {
       
   583                                     User::Leave( EBadMetadata );
       
   584                                 }
       
   585                             }                                                                                                   //------- 2 -----                                                                                    //------- 2 -----                  
       
   586                             else
       
   587                             {
       
   588                                 valOfAttr.Set( KNullDesC8() );
       
   589                             }
       
   590     
       
   591                             aChild.AddNewAttributeL( nameOfAttr, valOfAttr );                                                            
       
   592                         }
       
   593                         else 
       
   594                         {
       
   595                             if(nestElementName == KprotocolInfo) 
       
   596                             {
       
   597                                 HBufC8* protInfoValue = NULL;
       
   598                                 TRAPD(err, protInfoValue = ValidateProtocolInfoInResL( nestCurrentValue, aLocalSharing ));
       
   599                                 if(err)
       
   600                                 {
       
   601                                     User::Leave(EBadMetadata);
       
   602                                 }
       
   603                                 CleanupStack::PushL( protInfoValue );
       
   604                                 valOfAttr.Set( *protInfoValue );
       
   605                                 aChild.SetAttributeL( nameOfAttr, valOfAttr );
       
   606                                 CleanupStack::PopAndDestroy( protInfoValue );                                                           
       
   607                             }                                                                                                 //------- 3 -----                                                                                         //------- 3 -----
       
   608                         }
       
   609                     }                                                                                                                                                                                                                                                                                                                                                                                       
       
   610                                                                         
       
   611     
       
   612                     // if not main tag mark the attr is required
       
   613                     if( !IsMainObjectTagL(aChild) && nestElementName != KDlnaProfileID)
       
   614                     {
       
   615                        
       
   616                         HBufC8* attrReq = HBufC8::NewLC(
       
   617                             nestElementName.Length()
       
   618                             +KRequiredAtrSuf().Length() );
       
   619                         TPtr8 attrReqPtr(attrReq->Des());
       
   620                         attrReqPtr = nestElementName;
       
   621                         attrReqPtr.Append(KRequiredAtrSuf);
       
   622                         aChild.AddNewAttributeL( attrReqPtr, KTrueValue8 );
       
   623                         CleanupStack::PopAndDestroy(attrReq);
       
   624                     }
       
   625                 }
       
   626             }
       
   627         }
       
   628     
       
   629     }
       
   630 }
       
   631 
       
   632 void CUpnpElementFactory::ValidateAttributeL(TXmlEngElement aElement, TXmlEngElement aObject)
       
   633     {
       
   634         
       
   635         const TDesC8& required = UpnpDomInterface::GetAttrValueL( aElement, KRequiredObject() );
       
   636         if ( required == UpnpCD::KOne() )
       
   637         {
       
   638 
       
   639             const TDesC8& elementName = UpnpDomInterface::GetAttrValueL( aElement, KName() );
       
   640 
       
   641             const TDesC8& currentValue = UpnpDomInterface::GetAttrValueL( aObject, elementName );
       
   642             
       
   643             if ( !currentValue.Length() )  
       
   644             {
       
   645                 TXmlEngAttr attr = aObject.AttributeNodeL( elementName );
       
   646 
       
   647                 if(attr.NotNull())
       
   648                 {
       
   649                     attr.SetValueL(KNullDesC8);
       
   650                 }
       
   651                 else
       
   652                 {
       
   653                     aObject.AddNewAttributeL( elementName, KNullDesC8 );
       
   654                 }                               
       
   655             }
       
   656             // if not main tag mark the attr is required
       
   657             if(!IsMainObjectTagL(aObject))
       
   658             {
       
   659                 HBufC8* attrReq = HBufC8::NewLC(
       
   660                     elementName.Length()+KRequiredAtrSuf().Length() );
       
   661                 TPtr8 attrReqPtr(attrReq->Des());
       
   662                 attrReqPtr = elementName;
       
   663                 attrReqPtr.Append(KRequiredAtrSuf);
       
   664                 aObject.AddNewAttributeL( attrReqPtr, KTrueValue8 );
       
   665                 CleanupStack::PopAndDestroy(attrReq);
       
   666             }
       
   667         }
       
   668     }
       
   669 
   613 // -----------------------------------------------------------------------------
   670 // -----------------------------------------------------------------------------
   614 // CUpnpElementFactory::ValidatePropertiesL()
   671 // CUpnpElementFactory::ValidatePropertiesL()
   615 // Function leaves on error.
   672 // Function leaves on error.
   616 // -----------------------------------------------------------------------------
   673 // -----------------------------------------------------------------------------
   617 //
   674 //
   922     {
   979     {
   923         TXmlEngElement root = aDocument.DocumentElement();
   980         TXmlEngElement root = aDocument.DocumentElement();
   924         RXmlEngNodeList<TXmlEngElement> children;
   981         RXmlEngNodeList<TXmlEngElement> children;
   925         CleanupClosePushL(children);
   982         CleanupClosePushL(children);
   926         root.GetChildElements( children );
   983         root.GetChildElements( children );
   927     //    children.HasNext();
   984         children.HasNext();
   928         CleanupStack::PopAndDestroy(&children);
   985         CleanupStack::PopAndDestroy(&children);
   929         return children.Next();
   986         return children.Next();
   930     }
   987     }
   931 }
   988 }
   932 
   989 
   942     TXmlEngElement active;
   999     TXmlEngElement active;
   943     RXmlEngDocument ret;
  1000     RXmlEngDocument ret;
   944     ret.OpenL(iDOMImpl);
  1001     ret.OpenL(iDOMImpl);
   945     CleanupClosePushL(ret);
  1002     CleanupClosePushL(ret);
   946 
  1003 
   947  /*    if( aDocument.IsNull() || aDocument.DocumentElement().IsNull() )
  1004     if( aDocument.IsNull() || aDocument.DocumentElement().IsNull() )
   948     {
  1005     {
   949         User::Leave( KErrNotFound );            
  1006         User::Leave( KErrNotFound );            
   950     }
  1007     }
   951         
  1008         
   952     if ( aDocument.DocumentElement().Name().CompareF( KDidlLite() ) != 0 )
  1009     if ( aDocument.DocumentElement().Name().CompareF( KDidlLite() ) != 0 )
   962         children.HasNext();
  1019         children.HasNext();
   963         active = children.Next().Unlink().AsElement();
  1020         active = children.Next().Unlink().AsElement();
   964         CleanupStack::PopAndDestroy(&children);
  1021         CleanupStack::PopAndDestroy(&children);
   965     }
  1022     }
   966     ret.SetDocumentElement(active);
  1023     ret.SetDocumentElement(active);
   967    */    
  1024     
   968     CleanupStack::Pop(&ret);
  1025     CleanupStack::Pop(&ret);
   969     
  1026     
   970     return ret;
  1027     return ret;
   971 }
  1028 }
   972 
  1029 
  1148     {
  1205     {
  1149         return localName.AllocLC();
  1206         return localName.AllocLC();
  1150     }
  1207     }
  1151 }
  1208 }
  1152 
  1209 
       
  1210 void CUpnpElementFactory::CheckElementValidity (TXmlEngElement& aElement)
       
  1211 {
       
  1212     if ( aElement.IsNull() ) 
       
  1213     {
       
  1214         // no <class> element! leave
       
  1215         User::Leave( EBadMetadata );
       
  1216     }
       
  1217     
       
  1218     // check that does the new element have all the required fields for its type
       
  1219     // and also check that it does not have whatever fields (only optional allowed)
       
  1220     
       
  1221     TPtrC8 content = aElement.Text();
       
  1222     if( !content.Length() )
       
  1223     {
       
  1224         User::Leave( EBadMetadata );
       
  1225     }
       
  1226 }
       
  1227 
       
  1228 
  1153 // -----------------------------------------------------------------------------
  1229 // -----------------------------------------------------------------------------
  1154 // CUpnpElementFactory::ClassesL()
  1230 // CUpnpElementFactory::ClassesL()
  1155 // Gets classes descriptions for given object.
  1231 // Gets classes descriptions for given object.
  1156 // -----------------------------------------------------------------------------
  1232 // -----------------------------------------------------------------------------
  1157 //
  1233 //
  1162     // if survived here, we have the new element of type item or container
  1238     // if survived here, we have the new element of type item or container
  1163     // let's analyze its type
  1239     // let's analyze its type
  1164     TXmlEngElement type;
  1240     TXmlEngElement type;
  1165     UpnpDomInterface::GetElementL ( aObject, type, KClass() );
  1241     UpnpDomInterface::GetElementL ( aObject, type, KClass() );
  1166 
  1242 
  1167     if ( type.IsNull() ) 
  1243     CheckElementValidity (type);
  1168     {
       
  1169         // no <class> element! leave
       
  1170         User::Leave( EBadMetadata );
       
  1171     }
       
  1172 
       
  1173     // check that does the new element have all the required fields for its type
       
  1174     // and also check that it does not have whatever fields (only optional allowed)
       
  1175     RPointerArray<TPtrC8> objectFields;
  1244     RPointerArray<TPtrC8> objectFields;
  1176     
  1245     
  1177     TPtrC8 content = type.Text();
       
  1178     if( !content.Length() )
       
  1179     {
       
  1180         User::Leave( EBadMetadata );
       
  1181     }
       
  1182     //--- removing white spaces ------------------      
  1246     //--- removing white spaces ------------------      
  1183     HBufC8* tempBuffer = type.Text().AllocLC(); 
  1247     HBufC8* tempBuffer = type.Text().AllocLC(); 
  1184     TPtr8 tmpPtr(tempBuffer->Des());
  1248     TPtr8 tmpPtr(tempBuffer->Des());
  1185     UpnpCdUtils::RemoveWhiteSpacesL(tmpPtr);        
  1249     UpnpCdUtils::RemoveWhiteSpacesL(tmpPtr);        
  1186     CleanupStack::Check(tempBuffer);
  1250     CleanupStack::Check(tempBuffer);
  1208                 *objectFields[i] );
  1272                 *objectFields[i] );
  1209         CleanupStack::Check(tempBuffer);
  1273         CleanupStack::Check(tempBuffer);
  1210         // if such type found
  1274         // if such type found
  1211         if ( objectDescription.NotNull() ) 
  1275         if ( objectDescription.NotNull() ) 
  1212         {
  1276         {
  1213             aArray.AppendL( objectDescription );
  1277             aArray.Append( objectDescription );
  1214         }
  1278         }
  1215         /* This case is valid for any numeric value of containerID used in CreateObject() action
  1279         /* This case is valid for any numeric value of containerID used in CreateObject() action
  1216         *  We do some checking starting from 3rd string of <upnp:class> element, if the string isn't
  1280         *  We do some checking starting from 3rd string of <upnp:class> element, if the string isn't
  1217         *  recognizable, instead of leaving, we trims the value of <upnp:class> element, e.g:
  1281         *  recognizable, instead of leaving, we trims the value of <upnp:class> element, e.g:
  1218         *  'object.item.imageItem.abcd' -> is trimmed into -> 'object.item.imageItem'
  1282         *  'object.item.imageItem.abcd' -> is trimmed into -> 'object.item.imageItem'