void UPnpCDS::HandleBrowse( HTTPRequest *pRequest ) { UPnpCDSExtensionResults *pResult = NULL; UPnpCDSRequest request; request.m_sObjectId = pRequest->m_mapParams[ "ObjectID" ]; request.m_sContainerID = pRequest->m_mapParams[ "ContainerID" ]; request.m_sParentId = "0"; request.m_eBrowseFlag = GetBrowseFlag( pRequest->m_mapParams[ "BrowseFlag" ] ); request.m_sFilter = pRequest->m_mapParams[ "Filter" ]; request.m_nStartingIndex = pRequest->m_mapParams[ "StartingIndex" ].toLong(); request.m_nRequestedCount = pRequest->m_mapParams[ "RequestedCount"].toLong(); request.m_sSortCriteria = pRequest->m_mapParams[ "SortCriteria" ]; /* VERBOSE(VB_UPNP,QString("UPnpCDS::ProcessRequest \n" ": url = %1 \n" ": Method = %2 \n" ": ObjectId = %3 \n" ": BrowseFlag = %4 \n" ": Filter = %5 \n" ": StartingIndex = %6 \n" ": RequestedCount = %7 \n" ": SortCriteria = %8 " ) .arg( pRequest->m_sBaseUrl ) .arg( pRequest->m_sMethod ) .arg( request.m_sObjectId ) .arg( request.m_eBrowseFlag ) .arg( request.m_sFilter ) .arg( request.m_nStartingIndex ) .arg( request.m_nRequestedCount) .arg( request.m_sSortCriteria )); */ UPnPResultCode eErrorCode = UPnPResult_CDS_NoSuchObject; QString sErrorDesc = ""; short nNumberReturned = 0; short nTotalMatches = 0; short nUpdateID = 0; QString sResultXML; VERBOSE(VB_UPNP, QString("UPnpCDS::HandleBrowse ObjectID=%1, ContainerId=%2") .arg(request.m_sObjectId) .arg(request.m_sContainerID)); if (request.m_sObjectId == "0") { // ------------------------------------------------------------------ // This is for the root object... lets handle it. // ------------------------------------------------------------------ switch( request.m_eBrowseFlag ) { case CDS_BrowseMetadata: { // ---------------------------------------------------------------------- // Return Root Object Only // ---------------------------------------------------------------------- eErrorCode = UPnPResult_Success; nNumberReturned = 1; nTotalMatches = 1; nUpdateID = m_root.m_nUpdateId; m_root.SetChildCount( m_extensions.count() ); sResultXML = m_root.toXml(); break; } case CDS_BrowseDirectChildren: { // Loop Through each extension and Build the Root Folders // -=>TODO: Need to handle StartingIndex & RequestedCount eErrorCode = UPnPResult_Success; nTotalMatches = m_extensions.count(); nUpdateID = m_root.m_nUpdateId; if (request.m_nRequestedCount == 0) request.m_nRequestedCount = nTotalMatches; short nStart = Max( request.m_nStartingIndex, short( 0 )); short nCount = Min( nTotalMatches, request.m_nRequestedCount ); UPnpCDSExtension *pExtension = m_extensions.at( nStart ); UPnpCDSRequest childRequest; childRequest.m_sParentId = "0"; childRequest.m_eBrowseFlag = CDS_BrowseMetadata; childRequest.m_sFilter = ""; childRequest.m_nStartingIndex = 0; childRequest.m_nRequestedCount = 1; childRequest.m_sSortCriteria = ""; while (( pExtension != NULL ) && (nNumberReturned < nCount )) { childRequest.m_sObjectId = pExtension->m_sExtensionId; pResult = pExtension->Browse( &childRequest ); if (pResult != NULL) { if (pResult->m_eErrorCode == UPnPResult_Success) { sResultXML += pResult->GetResultXML(); nNumberReturned ++; } delete pResult; } pExtension = m_extensions.next(); } break; } default: break; } } else { // ------------------------------------------------------------------ // Look for a CDS Extension that knows how to handle this ObjectID // ------------------------------------------------------------------ UPnpCDSExtension *pExtension = m_extensions.first(); while (( pExtension != NULL ) && (pResult == NULL)) { VERBOSE(VB_UPNP, QString("UPNP Browse : Searching for : %1 / ObjectID : %2").arg(pExtension->m_sExtensionId).arg(request.m_sObjectId)); pResult = pExtension->Browse( &request ); pExtension = m_extensions.next(); } if (pResult != NULL) { eErrorCode = pResult->m_eErrorCode; sErrorDesc = pResult->m_sErrorDesc; if (eErrorCode == UPnPResult_Success) { nNumberReturned = pResult->m_List.count(); nTotalMatches = pResult->m_nTotalMatches; nUpdateID = pResult->m_nUpdateID; sResultXML = pResult->GetResultXML(); } delete pResult; } } // ---------------------------------------------------------------------- // Output Results of Browse Method // ---------------------------------------------------------------------- if (eErrorCode == UPnPResult_Success) { NameValueList list; QString sResults = DIDL_LITE_BEGIN; sResults += sResultXML; sResults += DIDL_LITE_END; list.append( new NameValue( "Result" , sResults )); list.append( new NameValue( "NumberReturned", QString::number( nNumberReturned ))); list.append( new NameValue( "TotalMatches" , QString::number( nTotalMatches ))); list.append( new NameValue( "UpdateID" , QString::number( nUpdateID ))); pRequest->FormatActionResponse( &list ); } else UPnp::FormatErrorResponse ( pRequest, eErrorCode, sErrorDesc ); }
/*---------------------------------------------------------------------- | CMediaCrawler::OnBrowseRoot +---------------------------------------------------------------------*/ NPT_Result CMediaCrawler::OnBrowseRoot(PLT_ActionReference& action) { NPT_String browseFlagValue; if (NPT_FAILED(action->GetArgumentValue("BrowseFlag", browseFlagValue))) { NPT_LOG_WARNING("PLT_FileMediaServer::OnBrowse - invalid arguments."); return NPT_FAILURE; } /* extract browseFlag */ BrowseFlags browseFlag; if (NPT_FAILED(GetBrowseFlag(browseFlagValue, browseFlag))) { /* error */ NPT_LOG_WARNING("PLT_FileMediaServer::OnBrowseRoot - BrowseFlag value not allowed."); action->SetError(402,"Invalid BrowseFlag arg."); return NPT_FAILURE; } if (browseFlag == BROWSEMETADATA) { PLT_MediaContainer item; item.m_Title = "Root"; item.m_ParentID = "-1"; item.m_ObjectID = "0"; item.m_ChildrenCount = GetMediaServers().GetItemCount(); item.m_ObjectClass.type = "object.container"; /* convert item to didl */ NPT_String filter; action->GetArgumentValue("Filter", filter); NPT_String tmp; NPT_CHECK_SEVERE(PLT_Didl::ToDidl(item, filter, tmp)); /* add didl header and footer */ NPT_String didl = didl_header + tmp + didl_footer; action->SetArgumentValue("Result", didl); action->SetArgumentValue("NumberReturned", "1"); action->SetArgumentValue("TotalMatches", "1"); // update ID may be wrong here, it should be the one of the container? action->SetArgumentValue("UpdateId", "1"); // TODO: We need to keep track of the overall updateID of the CDS } else { NPT_String startingInd; NPT_String reqCount; NPT_String filter; NPT_CHECK_SEVERE(action->GetArgumentValue("StartingIndex", startingInd)); NPT_CHECK_SEVERE(action->GetArgumentValue("RequestedCount", reqCount)); NPT_CHECK_SEVERE(action->GetArgumentValue("Filter", filter)); unsigned long start_index, req_count; if (NPT_FAILED(startingInd.ToInteger(start_index)) || NPT_FAILED(reqCount.ToInteger(req_count))) { return NPT_FAILURE; } unsigned long cur_index = 0; unsigned long num_returned = 0; unsigned long total_matches = 0; //unsigned long update_id = 0; PLT_MediaContainer item; NPT_String tmp; NPT_String didl = didl_header; // populate a list of containers (one container per known servers) const NPT_Lock<PLT_DeviceDataReferenceList>& devices = GetMediaServers(); NPT_Lock<PLT_DeviceDataReferenceList>::Iterator entry = devices.GetFirstItem(); while (entry) { PLT_DeviceDataReference device = (*entry); item.m_Title = device->GetFriendlyName(); item.m_ObjectID = FormatObjectId(device->GetUUID(), "0"); item.m_ParentID = "0"; item.m_ObjectClass.type = "object.container"; if ((cur_index >= start_index) && ((num_returned < req_count) || (req_count == 0))) { NPT_CHECK_SEVERE(PLT_Didl::ToDidl(item, filter, tmp)); didl += tmp; num_returned++; } cur_index++; total_matches++; ++entry; } didl += didl_footer; action->SetArgumentValue("Result", didl); action->SetArgumentValue("NumberReturned", NPT_String::FromInteger(num_returned)); action->SetArgumentValue("TotalMatches", NPT_String::FromInteger(total_matches)); action->SetArgumentValue("UpdateId", "1"); } return NPT_SUCCESS; }