--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/upnpavcontrolpoint/avcpengine/src/upnppathresolver.cpp Thu Dec 17 08:52:00 2009 +0200
@@ -0,0 +1,695 @@
+/** @file
+* Copyright (c) 2005-2006 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: CUpnpPathResolver
+*
+*/
+
+
+
+// INCLUDE FILES
+#include "upnppathresolver.h"
+#include "upnppathelement.h"
+#include "upnpresolvehandler.h"
+#include "upnpavcpmanager.h"
+
+#include "upnpavcpenginecommon.h"
+#include "upnpavcpenginehelper.h"
+using namespace UpnpAVCPEngine;
+
+#include "upnpstring.h"
+
+#include <xmlengdom.h>
+#include <xmlengdomparser.h>
+
+#include "upnpdominterface.h"
+
+_LIT8(KIndexFormat, "(%d)");
+
+const static TInt KMaxElementsLimit = 1000;
+
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CUpnpPathResolver::CUpnpPathResolver
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CUpnpPathResolver::CUpnpPathResolver(CUpnpAVCPManager& aManager):
+ iManager(aManager), iUptodate(ETrue)
+ {
+ iSystemId = -1;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpPathResolver::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CUpnpPathResolver::ConstructL(const TDesC8& aUUID)
+ {
+ iUUID = aUUID.AllocL();
+ iDOMImpl.OpenL();
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpPathResolver::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CUpnpPathResolver* CUpnpPathResolver::NewL(CUpnpAVCPManager& aManager, const TDesC8& aUUID)
+ {
+ CUpnpPathResolver* self = new( ELeave ) CUpnpPathResolver(aManager);
+
+ CleanupStack::PushL( self );
+ self->ConstructL(aUUID);
+ CleanupStack::Pop( self );
+
+ return self;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CUpnpPathResolver::~CUpnpPathResolver
+// Destructor
+// -----------------------------------------------------------------------------
+//
+CUpnpPathResolver::~CUpnpPathResolver()
+ {
+ delete iUUID;
+ iAVCPSessions.Reset();
+ iPathElements.ResetAndDestroy();
+ iResolveHandlers.ResetAndDestroy();
+ iDOMImpl.Close();
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpPathResolver::UUID
+// -----------------------------------------------------------------------------
+//
+const TDesC8& CUpnpPathResolver::UUID() const
+ {
+ return *iUUID;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpPathResolver::Match
+// -----------------------------------------------------------------------------
+//
+TBool CUpnpPathResolver::Match(const CUpnpPathResolver& aElement1, const CUpnpPathResolver& aElement2)
+ {
+ return (aElement1.UUID().Compare(aElement2.UUID()) == 0);
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpPathResolver::RegisterSession
+// -----------------------------------------------------------------------------
+//
+void CUpnpPathResolver::RegisterSession(CUpnpAVCPEngineSession* aSession)
+ {
+ TInt index = iAVCPSessions.Find(aSession);
+ if (index == KErrNotFound)
+ {
+ iAVCPSessions.Append(aSession);
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpPathResolver::UnregisterSession
+// -----------------------------------------------------------------------------
+//
+TInt CUpnpPathResolver::UnregisterSession(CUpnpAVCPEngineSession* aSession)
+ {
+ TInt index = iAVCPSessions.Find(aSession);
+ if (index != KErrNotFound)
+ {
+ iAVCPSessions.Remove(index);
+ }
+ return iAVCPSessions.Count();
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpPathResolver::AddElementL
+// -----------------------------------------------------------------------------
+//
+const TDesC8& CUpnpPathResolver::AddElementL(const TDesC8& aParentId, const TDesC8& aId, const TDesC8& aName, const TDesC8& aImportURI)
+ {
+ // if we exceed max capacity for our cache, set to destroy all elements
+ if (iPathElements.Count() > KMaxElementsLimit)
+ iUptodate = EFalse;
+
+
+ CUpnpPathElement* elem = CUpnpPathElement::NewL();
+ CleanupStack::PushL(elem);
+ elem->SetParentIdL(aParentId);
+ elem->SetIdL(aId);
+ elem->SetNameL(aName);
+
+ TIdentityRelation<CUpnpPathElement> matcher( CUpnpPathElement::MatchAll );
+ // check if exist the same element
+ TInt idx = iPathElements.Find( elem, matcher );
+
+ if (idx != KErrNotFound)
+ {
+ if(aImportURI != KNullDesC8())
+ {
+ iPathElements[idx]->SetImportURIL(aImportURI);
+ }
+ CleanupStack::PopAndDestroy(elem);
+ return iPathElements[idx]->Name();
+ }
+ else
+ {
+ // check name duplication
+ TIdentityRelation<CUpnpPathElement> matcherName( CUpnpPathElement::MatchName );
+ TInt index = 0;
+ TInt dupIndex = iPathElements.Find( elem, matcherName );
+
+ while (dupIndex != KErrNotFound)
+ {
+ HBufC8* newName = HBufC8::NewLC(aName.Length() + 10 /*integer*/);
+ *newName = aName;
+ newName->Des().AppendFormat(KIndexFormat, ++index );
+ // change to new name
+ elem->SetNameL(*newName);
+ CleanupStack::PopAndDestroy( newName );
+ dupIndex = iPathElements.Find( elem, matcherName );
+ // check if exists the same element
+ idx = iPathElements.Find( elem, matcher );
+ if (idx != KErrNotFound)
+ {
+ if(aImportURI != KNullDesC8())
+ {
+ iPathElements[idx]->SetImportURIL(aImportURI);
+ }
+ CleanupStack::PopAndDestroy(elem);
+ return iPathElements[idx]->Name();
+ }
+ }
+ if(aImportURI != KNullDesC8())
+ {
+ elem->SetImportURIL(aImportURI);
+ }
+ CleanupStack::Pop(elem);
+ iPathElements.Append(elem);
+ return elem->Name();
+ }
+
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpPathResolver::GetElementId
+// -----------------------------------------------------------------------------
+//
+CUpnpPathElement* CUpnpPathResolver::GetElementL(const TDesC8& aParentId, const TDesC8& aName) const
+ {
+ CUpnpPathElement* elem = CUpnpPathElement::NewL();
+ CleanupStack::PushL(elem);
+ elem->SetNameL(aName);
+ elem->SetParentIdL(aParentId);
+ TIdentityRelation<CUpnpPathElement> matcher( CUpnpPathElement::MatchName );
+ TInt idx = iPathElements.Find( elem, matcher );
+ CleanupStack::PopAndDestroy(elem);
+ if (idx != KErrNotFound)
+ {
+ return iPathElements[idx];
+ }
+ else
+ {
+ return NULL;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpPathResolver::RemoveElement
+// -----------------------------------------------------------------------------
+//
+void CUpnpPathResolver::RemoveElementD(CUpnpPathElement* aElement)
+ {
+ TInt index = iPathElements.Find(aElement);
+ if (index != KErrNotFound)
+ {
+ iPathElements.Remove(index);
+ delete aElement;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpPathResolver::ResolveIdL
+// -----------------------------------------------------------------------------
+//
+void CUpnpPathResolver::ResolveIdL(const TDesC8& aPath, MUpnpResolverObserver& aObserver)
+ {
+ CUpnpResolveHandler* handler = CUpnpResolveHandler::NewL(iManager,*this, aObserver);
+ CleanupStack::PushL(handler);
+ iResolveHandlers.Append(handler);
+ handler->ResolveL(aPath);
+ CleanupStack::Pop(handler);
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpPathResolver::RemoveHandler
+// -----------------------------------------------------------------------------
+//
+void CUpnpPathResolver::RemoveHandler(CUpnpResolveHandler* aHandler)
+ {
+ TInt index = iResolveHandlers.Find(aHandler);
+ if (index != KErrNotFound)
+ {
+ iResolveHandlers.Remove(index);
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpPathResolver::LockReset
+// -----------------------------------------------------------------------------
+//
+void CUpnpPathResolver::LockReset()
+ {
+ DEBUGSTRING8(("-> Obtain lock for resets"));
+ iLocked = ETrue;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CUpnpPathResolver::UnlockReset
+// -----------------------------------------------------------------------------
+//
+void CUpnpPathResolver::UnlockReset()
+ {
+ DEBUGSTRING8(("<- Release lock for resets"));
+ iLocked = EFalse;
+ if (!iUptodate)
+ {
+ DEBUGSTRING8(("Remove all path elements"));
+ iPathElements.ResetAndDestroy();
+ iUptodate = ETrue;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpPathResolver::StateChangedL
+// -----------------------------------------------------------------------------
+//
+void CUpnpPathResolver::StateChangedL(const TDesC8& aSystemId)
+ {
+
+ TLex8 updateidLex( aSystemId );
+ TInt systemUpdate;
+ TInt err = updateidLex.Val( systemUpdate );
+ if (err == KErrNone)
+ {
+ DEBUGSTRING8(("StateChangedL (old: %d)->(new: %d) ", iSystemId,systemUpdate));
+ if (iSystemId != -1 && iSystemId != systemUpdate)
+ {
+ if (!iLocked)
+ {
+ DEBUGSTRING8(("Remove all path elements"));
+ iPathElements.ResetAndDestroy();
+ }
+ else
+ {
+ iUptodate = EFalse;
+ }
+ }
+ iSystemId = systemUpdate;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpPathResolver::SetModifiedTimeL
+// -----------------------------------------------------------------------------
+//
+void CUpnpPathResolver::SetModifiedTimeL(TXmlEngElement& aDateElement, TFileInfo& aEntry)
+ {
+ if (aDateElement.Value().Length())
+ {
+ HBufC8* date = aDateElement.Value().AllocLC();
+
+ TPtrC8 datePtr = date->Des();
+
+ TInt position = datePtr.Locate('-');
+ TInt step = 0;
+ TInt dateParts[3];
+ while (position != KErrNotFound && step <3)
+ {
+ TLex8 lex(datePtr.Left(position));
+ TInt value(0) ;
+ lex.Val(value);
+
+ dateParts[step] = value;
+ step++;
+
+
+ datePtr.Set(datePtr.Mid(position+1));
+ position = datePtr.Locate('-');
+ }
+
+ TLex8 lex(datePtr);
+ TInt value(0) ;
+ lex.Val(value);
+
+ dateParts[step] = value;
+
+ // implement data validation
+ aEntry.iModified = TDateTime(dateParts[0], TMonth(dateParts[1] -1), dateParts[2] -1, 0, 0, 0, 0);
+ CleanupStack::PopAndDestroy(date);
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpPathResolver::ParseBrowseResponse
+// -----------------------------------------------------------------------------
+//
+void CUpnpPathResolver::ParseBrowseResponseL(const TDesC8& aResponse, RArray<TFileInfo>* aDirList, const TDesC8& aObjectId, HBufC8** aResUri)
+ {
+
+ RXmlEngDocument doc = ParseXmlL(aResponse);
+
+ // Does return resorce URI?
+ TBool isReturnUri = aObjectId.Compare(KNullDesC8) != 0;
+ //Start browsing document tree
+ TXmlEngElement root = doc.DocumentElement();
+ CleanupClosePushL( doc );
+
+ if(root.NotNull())
+ {
+
+ RArray<TXmlEngElement> elements;
+ CleanupClosePushL( elements );
+ // get list of containers
+ UpnpDomInterface::GetElementListL(root, elements, KContainer, EFalse);
+ // get list of items
+ UpnpDomInterface::GetElementListL(root, elements, KItem, EFalse);
+
+ for (TInt i = 0; i < elements.Count(); i++)
+ {
+ TXmlEngElement objElem = elements[i];
+ TXmlEngElement titleElem;
+ // check title
+ if ( UpnpDomInterface::GetElementL(objElem, titleElem, KTitle ) &&
+ titleElem.Value().Length())
+ {
+ // check if it's item or container
+ TBool isItem = UpnpDomInterface::CheckTagL(objElem, KItem);
+
+ TPtrC8 id = UpnpDomInterface::GetAttrValueL( objElem, KId);
+ TPtrC8 parentId = UpnpDomInterface::GetAttrValueL( objElem, KParentId);
+ TPtrC8 title = titleElem.Value();
+
+ // try to add new path element, if name is taken, new name will be given
+ const TDesC8& newTitle = AddElementL(parentId, id, title);
+ // check if return dir list
+ if (aDirList)
+ {
+ TFileInfo entry;
+ // set name
+ entry.iName = newTitle;
+
+ // set date
+ TXmlEngElement dateElem;
+ if (UpnpDomInterface::GetElementL(objElem, dateElem, KDate ) )
+ {
+ SetModifiedTimeL(dateElem, entry);
+ }
+
+ if (isItem) // for items
+ {
+ entry.iAtt |= KEntryAttNormal;
+ // get size from res if exist
+ RArray<TXmlEngElement> resElements;
+ CleanupClosePushL( resElements );
+ if (UpnpDomInterface::GetElementListL(objElem, resElements, KRes, EFalse))
+ {
+ // get prefer resource
+ TXmlEngElement res = GetPreferResourceL(resElements);
+ // maybe res URI should be returned
+ if (isReturnUri && UpnpDomInterface::CheckAttributeValueL(objElem, KId, aObjectId))
+ {
+ if (res.NotNull() && res.Value().Length())
+ {
+ *aResUri = res.Value().AllocL();
+ }
+ }
+ // set size base on res@size
+ TPtrC8 size = UpnpDomInterface::GetAttrValueL( res, KSize);
+ TLex8 intLex( size );
+ intLex.Val( entry.iSize );
+
+ //TPtrC8 importUri = UpnpDomInterface::GetAttrValueL( res, KImportUri);
+ TPtrC8 restricted = UpnpDomInterface::GetAttrValueL( objElem, KRestricted);
+ // check if read-only flag should be set
+ if (restricted.Compare(KOne) == 0 || restricted.CompareF(KTrue) == 0)
+ {
+ entry.iAtt |= KEntryAttReadOnly;
+ }
+
+ }
+ CleanupStack::PopAndDestroy(&resElements);
+ }
+ else // for containers
+ {
+ entry.iAtt |= KEntryAttDir;
+ }
+
+ // add to dir result
+ aDirList->Append(entry);
+ }
+ }
+ }
+ CleanupStack::PopAndDestroy(&elements);
+ }
+
+ //Cleanup
+ CleanupStack::PopAndDestroy(&doc);
+ }
+
+
+// -----------------------------------------------------------------------------
+// CUpnpPathResolver::GetResUri
+// -----------------------------------------------------------------------------
+//
+TBool CUpnpPathResolver::GetResUriL(const TDesC8& aResponse, const TDesC8& aId, HBufC8*& aResUri)
+ {
+ TInt found(EFalse);
+ delete aResUri;
+ aResUri = NULL;
+
+ RXmlEngDocument doc = ParseXmlL(aResponse);
+ CleanupClosePushL( doc );
+
+ //Start browsing document tree
+ TXmlEngElement root = doc.DocumentElement();
+
+ if(root.NotNull())
+ {
+ TXmlEngElement item;
+ if ( UpnpDomInterface::GetDirectoryElementL(root, item, KItem, KId, aId) )
+ {
+ RArray<TXmlEngElement> resElements;
+ CleanupClosePushL(resElements);
+ if (UpnpDomInterface::GetElementListL(item, resElements, KRes, EFalse) )
+ {
+ TXmlEngElement res = GetPreferResourceL(resElements);
+
+ if (res.Value().Length())
+ {
+ found = ETrue;
+ aResUri = res.Value().AllocL();
+ }
+ }
+ CleanupStack::PopAndDestroy(&resElements);
+ }
+ }
+
+ CleanupStack::PopAndDestroy(&doc);
+
+ return found;
+ }
+// -----------------------------------------------------------------------------
+// CUpnpPathResolver::BrowseCreateObjectL
+// -----------------------------------------------------------------------------
+//
+TBool CUpnpPathResolver::BrowseCreateObjectL(const TDesC8& aResponse)
+ {
+ TInt found(EFalse);
+ RXmlEngDocument doc = ParseXmlL(aResponse);
+ CleanupClosePushL( doc );
+ //Start browsing document tree
+ TXmlEngElement root = doc.DocumentElement();
+
+ if(root.NotNull())
+ {
+ TXmlEngElement item;
+ if ( UpnpDomInterface::GetElementL(root, item, KItem) )
+ {
+
+ TPtrC8 id = UpnpDomInterface::GetAttrValueL( item, KId);
+ TPtrC8 parentid = UpnpDomInterface::GetAttrValueL( item, KParentId);
+
+ if (id.Length() && parentid.Length())
+ {
+ RArray<TXmlEngElement> resElements;
+ CleanupClosePushL(resElements);
+
+ if(UpnpDomInterface::GetElementListL(item, resElements, KRes, EFalse))
+ {
+ TPtrC8 import;
+ TXmlEngElement resElement = GetResourceWithImportURIL(resElements, import);
+
+
+ if(import.Length())
+ {
+
+ TXmlEngElement titleElem;
+
+ if(UpnpDomInterface::GetElementL(item, titleElem, KTitle))
+ {
+ if ( titleElem.Value().Length())
+ {
+ found = ETrue;
+ TPtrC8 title = titleElem.Value();
+ AddElementL(parentid, id, title, import);
+ }
+ }
+ }
+
+ CleanupStack::PopAndDestroy(&resElements);
+
+ }
+ }
+ }
+ }
+
+
+ //Cleanup
+ CleanupStack::PopAndDestroy(&doc);
+
+ return found;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpPathResolver::GetItemL
+// -----------------------------------------------------------------------------
+//
+TBool CUpnpPathResolver::GetItemL(const TDesC8& aResponse, const TDesC8& aId)
+ {
+ TInt found(EFalse);
+
+ RXmlEngDocument doc = ParseXmlL(aResponse);
+ CleanupClosePushL( doc );
+ //Start browsing document tree
+ TXmlEngElement root = doc.DocumentElement();
+
+ if(root.NotNull())
+ {
+ TXmlEngElement item;
+ if ( UpnpDomInterface::GetDirectoryElementL(root, item, KItem, KId, aId) )
+ {
+ RArray<TXmlEngElement> resElements;
+ CleanupClosePushL(resElements);
+ if (UpnpDomInterface::GetElementListL(item, resElements, KRes, EFalse) )
+ {
+ found = ETrue;
+ }
+ CleanupStack::PopAndDestroy(&resElements);
+ }
+ }
+
+ //Cleanup
+ CleanupStack::PopAndDestroy(&doc);
+
+ return found;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpPathResolver::ParseXmlL
+// -----------------------------------------------------------------------------
+//
+RXmlEngDocument CUpnpPathResolver::ParseXmlL(const TDesC8& aXml)
+ {
+
+ //Create a parser
+ RXmlEngDOMParser parser;
+ User::LeaveIfError( parser.Open(iDOMImpl) );
+ CleanupClosePushL(parser);
+
+ //Handler to the parsed document
+ RXmlEngDocument doc;
+
+ doc = parser.ParseL(aXml);
+ CleanupClosePushL( doc );
+
+ if(doc.IsNull())
+ {
+ User::Leave(KErrUnknown);
+ }
+
+ CleanupStack::Pop(&doc);
+ CleanupStack::PopAndDestroy(&parser);
+ return doc;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CUpnpPathResolver::GetPreferResource
+// -----------------------------------------------------------------------------
+//
+TXmlEngElement CUpnpPathResolver::GetPreferResourceL(const RArray<TXmlEngElement>& aElements)
+ {
+ //DEBUGSTRING8(("GetPreferResource "));
+ if (aElements.Count() > 0)
+ {
+ for (TInt i = 0; i < aElements.Count(); i++)
+ {
+ TXmlEngElement elem = aElements[i];
+ TPtrC8 protocol = UpnpDomInterface::GetAttrValueL(elem, KProtocolInfo);
+ if (protocol.Left(KProtocolInfoBegin().Length()).Compare(KProtocolInfoBegin) == 0)
+ {
+ return elem;
+ }
+ }
+ DEBUGSTRING8(("GetPreferResource: Return empty element (no http-get elements) "));
+ }
+ else
+ {
+ DEBUGSTRING8(("GetPreferResource: Return empty element (size of list = 0) "));
+ }
+ return TXmlEngElement();
+ }
+// -----------------------------------------------------------------------------
+// CUpnpPathResolver::GetResourceWithImportURIL
+// -----------------------------------------------------------------------------
+//
+TXmlEngElement CUpnpPathResolver::GetResourceWithImportURIL(const RArray<TXmlEngElement>& aElements, TPtrC8& aImportURI)
+ {
+ aImportURI.Set(KNullDesC8);
+
+ if (aElements.Count() > 0)
+ {
+ for (TInt i = 0; i < aElements.Count(); i++)
+ {
+ TXmlEngElement elem = aElements[i];
+
+ aImportURI.Set(UpnpDomInterface::GetAttrValueL(elem, KImportUri));
+ if (aImportURI != KNullDesC8)
+ {
+ return elem;
+ }
+ }
+ }
+ return TXmlEngElement();
+ }
+// End of File