/*---------------------------------------------------------------------- | PLT_FileMediaConnectDelegate::OnSearchContainer +---------------------------------------------------------------------*/ NPT_Result PLT_FileMediaConnectDelegate::OnSearchContainer(PLT_ActionReference& action, const char* object_id, const char* search_criteria, const char* filter, NPT_UInt32 starting_index, NPT_UInt32 requested_count, const char* sort_criteria, const PLT_HttpRequestContext& context) { /* parse search criteria */ /* TODO: HACK TO PASS DLNA */ if (search_criteria && NPT_StringsEqual(search_criteria, "Unknownfieldname")) { /* error */ NPT_LOG_WARNING_1("Unsupported or invalid search criteria %s", search_criteria); action->SetError(708, "Unsupported or invalid search criteria"); return NPT_FAILURE; } /* locate the file from the object ID */ NPT_String dir; if (NPT_FAILED(GetFilePath(object_id, dir))) { /* error */ NPT_LOG_WARNING("ObjectID not found."); action->SetError(710, "No Such Container."); return NPT_FAILURE; } /* retrieve the item type */ NPT_FileInfo info; NPT_Result res = NPT_File::GetInfo(dir, &info); if (NPT_FAILED(res) || (info.m_Type != NPT_FileInfo::FILE_TYPE_DIRECTORY)) { /* error */ NPT_LOG_WARNING("No such container"); action->SetError(710, "No such container"); return NPT_FAILURE; } /* hack for now to return something back to XBox 360 */ return OnBrowseDirectChildren(action, object_id, filter, starting_index, requested_count, sort_criteria, context); }
/*---------------------------------------------------------------------- | PLT_MediaServer::OnBrowse +---------------------------------------------------------------------*/ NPT_Result CMediaCrawler::OnBrowse(PLT_ActionReference& action, const NPT_HttpRequestContext& context) { NPT_Result res; NPT_String object_id; if (NPT_FAILED(action->GetArgumentValue("ObjectId", object_id))) { NPT_LOG_WARNING("PLT_FileMediaServer::OnBrowse - invalid arguments."); return NPT_FAILURE; } NPT_LOG_FINE_1("PLT_FileMediaServer::OnOnBrowse - id = %s\r\n", (const char*)object_id); // extract server uuid and server object id from our object id NPT_String server_uuid; NPT_String server_object_id; if (NPT_FAILED(SplitObjectId(object_id, server_uuid, server_object_id))) { /* error */ NPT_LOG_WARNING("CMediaCrawler::OnBrowse - ObjectID not found."); action->SetError(701, "No Such Object."); return NPT_FAILURE; } // root ? if (server_uuid.GetLength() == 0) { res = OnBrowseRoot(action); } else { // we have a device to browse // is it device root? if (server_object_id.GetLength() == 0) { server_object_id = "0"; } res = OnBrowseDevice(action, server_uuid, server_object_id, context); } if (NPT_FAILED(res) && (action->GetErrorCode() == 0)) { action->SetError(800, "Internal error"); } return res; }
/*---------------------------------------------------------------------- | main +---------------------------------------------------------------------*/ int main(int, char**) { NPT_LogManager::GetDefault().Configure("plist:.level=ALL;"); NPT_LOG_L(MyLogger, NPT_LOG_LEVEL_WARNING, "blabla"); NPT_LOG_L2(MyLogger, NPT_LOG_LEVEL_WARNING, "blabla %d %d", 8, 9); NPT_LOG(NPT_LOG_LEVEL_WARNING, "blibli"); NPT_LOG_2(NPT_LOG_LEVEL_INFO, "fofo %d %d", 5, 7); NPT_LOG_SEVERE("this is severe!"); NPT_LOG_SEVERE_1("this is severe (%d)", 9); NPT_LOG_SEVERE_L(MyLogger, "this is severe!"); NPT_LOG_SEVERE_L1(MyLogger, "this is severe (%d)", 9); NPT_LOG_SEVERE_L(FooLogger, "this is severe!"); NPT_LOG_SEVERE_L1(FooLogger, "this is severe (%d)", 9); NPT_LOG_SEVERE("severe"); NPT_LOG_WARNING("warning"); NPT_LOG_INFO("info"); NPT_LOG_FINE("fine"); NPT_LOG_FINER("finer"); NPT_LOG_FINEST("finest"); NPT_LOG_SEVERE_L(FooLogger, "severe"); NPT_LOG_WARNING_L(FooLogger, "warning"); NPT_LOG_INFO_L(FooLogger, "info"); NPT_LOG_FINE_L(FooLogger, "fine"); NPT_LOG_FINER_L(FooLogger, "finer"); NPT_LOG_FINEST_L(FooLogger, "finest"); TestLargeBuffer(); TestCheck(); TestCheckSevere(); TestCheckWarning(); TestCheckInfo(); TestCheckFine(); TestCheckFiner(); TestCheckFinest(); TestCheckL(); TestCheckSevereL(); TestCheckWarningL(); TestCheckInfoL(); TestCheckFineL(); TestCheckFinerL(); TestCheckFinestL(); return 0; }
/*---------------------------------------------------------------------- | PLT_MediaServer::OnUpdate +---------------------------------------------------------------------*/ NPT_Result PLT_MediaServer::OnUpdate(PLT_ActionReference& action, const PLT_HttpRequestContext& context) { if (!m_Delegate) return NPT_ERROR_NOT_IMPLEMENTED; int err; const char* msg = NULL; NPT_String object_id, current_xml, new_xml; NPT_Map<NPT_String,NPT_String> curr_values; NPT_Map<NPT_String,NPT_String> new_values; NPT_CHECK_LABEL(action->GetArgumentValue("ObjectID", object_id), args); NPT_CHECK_LABEL(object_id.IsEmpty(),args); NPT_CHECK_LABEL(action->GetArgumentValue("CurrentTagValue", current_xml), args); NPT_CHECK_LABEL(action->GetArgumentValue("NewTagValue", new_xml), args); if (NPT_FAILED(ParseTagList(current_xml, curr_values))) { err = 702; msg = "Invalid currentTagvalue"; goto failure; } if (NPT_FAILED(ParseTagList(new_xml, new_values))) { err = 703; msg = "Invalid newTagValue"; goto failure; } if (curr_values.GetEntryCount() != new_values.GetEntryCount()) { err = 706; msg = "Paramater mismatch"; goto failure; } return m_Delegate->OnUpdateObject(action, object_id, curr_values, new_values, context); args: err = 402; msg = "Invalid args"; failure: NPT_LOG_WARNING(msg); action->SetError(err, msg); return NPT_FAILURE; }
/*---------------------------------------------------------------------- | NPT_Win32Thread::Start +---------------------------------------------------------------------*/ NPT_Result NPT_Win32Thread::Start() { if (m_ThreadHandle > 0) { // failed NPT_LOG_WARNING("thread already started !"); return NPT_ERROR_INVALID_STATE; } NPT_LOG_FINER("creating thread"); // create the native thread #if defined(_WIN32_WCE) DWORD thread_id; #else unsigned int thread_id; #endif // create a stack local variable 'detached', as this object // may already be deleted when _beginthreadex returns and // before we get to call detach on the given thread bool detached = m_Detached; HANDLE thread_handle = (HANDLE) _beginthreadex(NULL, NPT_CONFIG_THREAD_STACK_SIZE, EntryPoint, reinterpret_cast<void*>(this), 0, &thread_id); if (thread_handle == 0) { // failed return NPT_FAILURE; } if (detached) { CloseHandle(thread_handle); } else { m_ThreadHandle = thread_handle; } m_ThreadId = (DWORD)thread_id; return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_FileMediaServer::OnBrowseMetadata +---------------------------------------------------------------------*/ NPT_Result PLT_FileMediaServer::OnBrowseMetadata(PLT_ActionReference& action, const char* object_id, const NPT_HttpRequestContext& context) { NPT_String didl; PLT_MediaObjectReference item; /* locate the file from the object ID */ NPT_String filepath; if (NPT_FAILED(GetFilePath(object_id, filepath))) { /* error */ NPT_LOG_WARNING("PLT_FileMediaServer::OnBrowse - ObjectID not found."); action->SetError(701, "No Such Object."); return NPT_FAILURE; } item = BuildFromFilePath( filepath, true, &context.GetLocalAddress()); if (item.IsNull()) return NPT_FAILURE; NPT_String filter; NPT_CHECK_SEVERE(action->GetArgumentValue("Filter", filter)); NPT_String tmp; NPT_CHECK_SEVERE(PLT_Didl::ToDidl(*item.AsPointer(), filter, tmp)); /* add didl header and footer */ didl = didl_header + tmp + didl_footer; NPT_CHECK_SEVERE(action->SetArgumentValue("Result", didl)); NPT_CHECK_SEVERE(action->SetArgumentValue("NumberReturned", "1")); NPT_CHECK_SEVERE(action->SetArgumentValue("TotalMatches", "1")); // update ID may be wrong here, it should be the one of the container? // TODO: We need to keep track of the overall updateID of the CDS NPT_CHECK_SEVERE(action->SetArgumentValue("UpdateId", "1")); return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_Didl::FromDidl +---------------------------------------------------------------------*/ NPT_Result PLT_Didl::FromDidl(const char* xml, PLT_MediaObjectListReference& objects) { NPT_String str; PLT_MediaObject* object = NULL; NPT_XmlNode* node = NULL; NPT_XmlElementNode* didl = NULL; NPT_XmlParser parser; NPT_LOG_FINE("Parsing Didl..."); NPT_CHECK_LABEL_SEVERE(parser.Parse(xml, node), cleanup); if (!node || !node->AsElementNode()) { NPT_LOG_SEVERE("Invalid node type"); goto cleanup; } didl = node->AsElementNode(); if (didl->GetTag().Compare("DIDL-Lite", true)) { NPT_LOG_SEVERE("Invalid node tag"); goto cleanup; } // create entry list objects = new PLT_MediaObjectList(); // for each child, find out if it's a container or not // and then invoke the FromDidl on it for (NPT_List<NPT_XmlNode*>::Iterator children = didl->GetChildren().GetFirstItem(); children; children++) { NPT_XmlElementNode* child = (*children)->AsElementNode(); if (!child) continue; if (child->GetTag().Compare("Container", true) == 0) { object = new PLT_MediaContainer(); } else if (child->GetTag().Compare("item", true) == 0) { object = new PLT_MediaItem(); } else { NPT_LOG_WARNING("Invalid node tag"); continue; } if (NPT_FAILED(object->FromDidl(child))) { NPT_LOG_WARNING_1("Invalid didl for object: %s", (const char*) PLT_XmlHelper::Serialize(*child, false)); continue; } objects->Add(object); object = NULL; // reset to make sure it doesn't get deleted twice in case of error } delete node; return NPT_SUCCESS; cleanup: objects = NULL; delete node; delete object; return NPT_FAILURE; }
/*---------------------------------------------------------------------- | PLT_FileMediaServer::OnBrowseDirectChildren +---------------------------------------------------------------------*/ NPT_Result PLT_FileMediaServer::OnBrowseDirectChildren(PLT_ActionReference& action, const char* object_id, const NPT_HttpRequestContext& context) { /* locate the file from the object ID */ NPT_String dir; if (NPT_FAILED(GetFilePath(object_id, dir))) { /* error */ NPT_LOG_WARNING("PLT_FileMediaServer::OnBrowse - ObjectID not found."); action->SetError(701, "No Such Object."); return NPT_FAILURE; } /* retrieve the item type */ NPT_FileInfo info; NPT_Result res = NPT_File::GetInfo(dir, &info); if (NPT_FAILED(res)) { /* Object does not exist */ NPT_LOG_WARNING_1("PLT_FileMediaServer::OnBrowse - BROWSEDIRECTCHILDREN failed for item %s", dir.GetChars()); action->SetError(800, "Can't retrieve info " + dir); return NPT_FAILURE; } if (info.m_Type != NPT_FileInfo::FILE_TYPE_DIRECTORY) { /* error */ NPT_LOG_WARNING("PLT_FileMediaServer::OnBrowse - BROWSEDIRECTCHILDREN not allowed on an item."); action->SetError(710, "item is not a container."); return NPT_FAILURE; } NPT_String filter; NPT_String startingInd; NPT_String reqCount; NPT_CHECK_SEVERE(action->GetArgumentValue("Filter", filter)); NPT_CHECK_SEVERE(action->GetArgumentValue("StartingIndex", startingInd)); NPT_CHECK_SEVERE(action->GetArgumentValue("RequestedCount", reqCount)); NPT_UInt32 start_index, req_count; if (NPT_FAILED(startingInd.ToInteger(start_index)) || NPT_FAILED(reqCount.ToInteger(req_count))) { action->SetError(412, "Precondition failed"); return NPT_FAILURE; } NPT_List<NPT_String> entries; res = NPT_File::ListDirectory(dir, entries, 0, 0); if (NPT_FAILED(res)) { NPT_LOG_WARNING_1("PLT_FileMediaServer::OnBrowseDirectChildren - failed to open dir %s", (const char*) dir); return res; } unsigned long cur_index = 0; unsigned long num_returned = 0; unsigned long total_matches = 0; NPT_String didl = didl_header; PLT_MediaObjectReference item; for (NPT_List<NPT_String>::Iterator it = entries.GetFirstItem(); it; ++it) { NPT_String& filename = *it; item = BuildFromFilePath( NPT_FilePath::Create(dir, filename), true, &context.GetLocalAddress()); if (!item.IsNull()) { if ((cur_index >= start_index) && ((num_returned < req_count) || (req_count == 0))) { NPT_String tmp; NPT_CHECK_SEVERE(PLT_Didl::ToDidl(*item.AsPointer(), filter, tmp)); didl += tmp; num_returned++; } cur_index++; total_matches++; } }; didl += didl_footer; NPT_CHECK_SEVERE(action->SetArgumentValue("Result", didl)); NPT_CHECK_SEVERE(action->SetArgumentValue("NumberReturned", NPT_String::FromInteger(num_returned))); NPT_CHECK_SEVERE(action->SetArgumentValue("TotalMatches", NPT_String::FromInteger(total_matches))); // 0 means we don't know how many we have but most browsers don't like that!! NPT_CHECK_SEVERE(action->SetArgumentValue("UpdateId", "1")); return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_MediaServer::OnSearch +---------------------------------------------------------------------*/ NPT_Result PLT_MediaServer::OnSearch(PLT_ActionReference& action, const PLT_HttpRequestContext& context) { NPT_COMPILER_UNUSED(context); NPT_Result res; NPT_String container_id; NPT_String search; NPT_String filter; NPT_String start; NPT_String count; NPT_String sort; NPT_List<NPT_String> sort_list; if (NPT_FAILED(action->GetArgumentValue("ContainerId", container_id)) || NPT_FAILED(action->GetArgumentValue("SearchCriteria", search)) || NPT_FAILED(action->GetArgumentValue("Filter", filter)) || NPT_FAILED(action->GetArgumentValue("StartingIndex", start)) || NPT_FAILED(action->GetArgumentValue("RequestedCount", count)) || NPT_FAILED(action->GetArgumentValue("SortCriteria", sort))) { NPT_LOG_WARNING("Missing arguments"); action->SetError(402, "Invalid args"); return NPT_SUCCESS; } /* convert index and counts to int */ NPT_UInt32 starting_index, requested_count; if (NPT_FAILED(start.ToInteger(starting_index)) || NPT_FAILED(count.ToInteger(requested_count))) { NPT_LOG_WARNING_2("Invalid arguments (%s, %s)", start.GetChars(), count.GetChars()); action->SetError(402, "Invalid args"); return NPT_FAILURE; } /* parse sort criteria */ if (NPT_FAILED(ParseSort(sort, sort_list))) { NPT_LOG_WARNING_1("Unsupported or invalid sort criteria error (%s)", sort.GetChars()); action->SetError(709, "Unsupported or invalid sort criteria error"); return NPT_FAILURE; } NPT_LOG_INFO_5("Processing Search from %s with id=\"%s\", search=\"%s\", start=%d, count=%d", (const char*)context.GetRemoteAddress().GetIpAddress().ToString(), (const char*)container_id, (const char*)search, starting_index, requested_count); if (search.IsEmpty() || search == "*") { res = OnBrowseDirectChildren( action, container_id, filter, starting_index, requested_count, sort, context); } else { res = OnSearchContainer( action, container_id, search, filter, starting_index, requested_count, sort, context); } if (NPT_FAILED(res) && (action->GetErrorCode() == 0)) { action->SetError(800, "Internal error"); } return res; }
/*---------------------------------------------------------------------- | PLT_MediaServer::OnBrowse +---------------------------------------------------------------------*/ NPT_Result PLT_MediaServer::OnBrowse(PLT_ActionReference& action, const PLT_HttpRequestContext& context) { NPT_Result res; NPT_String object_id; NPT_String browse_flag_val; NPT_String filter; NPT_String start; NPT_String count; NPT_String sort; NPT_List<NPT_String> sort_list; if (NPT_FAILED(action->GetArgumentValue("ObjectId", object_id)) || NPT_FAILED(action->GetArgumentValue("BrowseFlag", browse_flag_val)) || NPT_FAILED(action->GetArgumentValue("Filter", filter)) || NPT_FAILED(action->GetArgumentValue("StartingIndex", start)) || NPT_FAILED(action->GetArgumentValue("RequestedCount", count)) || NPT_FAILED(action->GetArgumentValue("SortCriteria", sort))) { NPT_LOG_WARNING("Missing arguments"); action->SetError(402, "Invalid args"); return NPT_SUCCESS; } /* extract flag */ BrowseFlags flag; if (NPT_FAILED(ParseBrowseFlag(browse_flag_val, flag))) { /* error */ NPT_LOG_WARNING_1("BrowseFlag value not allowed (%s)", (const char*)browse_flag_val); action->SetError(402, "Invalid args"); return NPT_SUCCESS; } /* convert index and counts to int */ NPT_UInt32 starting_index, requested_count; if (NPT_FAILED(start.ToInteger(starting_index)) || NPT_FAILED(count.ToInteger(requested_count)) || PLT_Didl::ConvertFilterToMask(filter) == 0) { NPT_LOG_WARNING_3("Invalid arguments (%s, %s, %s)", start.GetChars(), count.GetChars(), filter.GetChars()); action->SetError(402, "Invalid args"); return NPT_FAILURE; } /* parse sort criteria for validation */ if (NPT_FAILED(ParseSort(sort, sort_list))) { NPT_LOG_WARNING_1("Unsupported or invalid sort criteria error (%s)", sort.GetChars()); action->SetError(709, "Unsupported or invalid sort criteria error"); return NPT_FAILURE; } NPT_LOG_FINE_6("Processing %s from %s with id=\"%s\", filter=\"%s\", start=%d, count=%d", (const char*)browse_flag_val, (const char*)context.GetRemoteAddress().GetIpAddress().ToString(), (const char*)object_id, (const char*)filter, starting_index, requested_count); /* Invoke the browse function */ if (flag == BROWSEMETADATA) { res = OnBrowseMetadata( action, object_id, filter, starting_index, requested_count, sort, context); } else { res = OnBrowseDirectChildren( action, object_id, filter, starting_index, requested_count, sort, context); } if (NPT_FAILED(res) && (action->GetErrorCode() == 0)) { action->SetError(800, "Internal error"); } return res; }
/*---------------------------------------------------------------------- | CMediaCrawler::OnBrowseDevice +---------------------------------------------------------------------*/ NPT_Result CMediaCrawler::OnBrowseDevice(PLT_ActionReference& action, const char* server_uuid, const char* server_object_id, NPT_SocketInfo* info /* = NULL */) { NPT_Result res; PLT_DeviceDataReference device; { // look for device first const NPT_Lock<PLT_DeviceDataReferenceList>& devices = GetMediaServers(); //NPT_AutoLock lock(devices); if (NPT_FAILED(NPT_ContainerFind(devices, PLT_DeviceDataFinder(server_uuid), device))) { /* error */ NPT_LOG_WARNING("CMediaCrawler::OnBrowseDevice - device not found."); action->SetError(701, "No Such Object."); return NPT_FAILURE; } } // look for args and convert them NPT_String browseFlagValue; NPT_String startingInd; NPT_String reqCount; NPT_String filter; NPT_String sort; NPT_CHECK_SEVERE(action->GetArgumentValue("BrowseFlag", browseFlagValue)); NPT_CHECK_SEVERE(action->GetArgumentValue("StartingIndex", startingInd)); NPT_CHECK_SEVERE(action->GetArgumentValue("RequestedCount", reqCount)); NPT_CHECK_SEVERE(action->GetArgumentValue("Filter", filter)); NPT_CHECK_SEVERE(action->GetArgumentValue("SortCriteria", sort)); unsigned long start_index, req_count; if (NPT_FAILED(startingInd.ToInteger(start_index)) || NPT_FAILED(reqCount.ToInteger(req_count))) { return NPT_FAILURE; } // create a container for our result // this will be filled in by OnBrowseResponse CMediaCrawlerBrowseInfoReference browse_info(new CMediaCrawlerBrowseInfo()); browse_info->shared_var.SetValue(0); // send off the browse packet. Note that this will // not block. The shared variable is used to block // until the response has been received. res = Browse(device, server_object_id, start_index, req_count, (browseFlagValue == "BrowseMetadata")?1:0, filter, sort, new CMediaCrawlerBrowseInfoReference(browse_info)); NPT_CHECK_SEVERE(res); // wait 30 secs for response res = browse_info->shared_var.WaitUntilEquals(1, 30000); NPT_CHECK_SEVERE(res); // did the browse fail? if (NPT_FAILED(browse_info->res)) { action->SetError(browse_info->code, ""); return NPT_FAILURE; } action->SetArgumentValue("Result", UpdateDidl(server_uuid, browse_info->didl, info)); action->SetArgumentValue("NumberReturned", browse_info->nr); action->SetArgumentValue("TotalMatches", browse_info->tm); action->SetArgumentValue("UpdateId", browse_info->uid); action->SetArgumentValue("ObjectID", FormatObjectId(server_uuid, browse_info->object_id)); return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | 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; }
/*---------------------------------------------------------------------- | PLT_MediaBrowser::Browse +---------------------------------------------------------------------*/ NPT_Result PLT_MediaBrowser::Browse(PLT_DeviceDataReference& device, const char* obj_id, NPT_UInt32 start_index, NPT_UInt32 count, bool browse_metadata, const char* filter, const char* sort_criteria, void* userdata) { // look for the service PLT_Service* service; NPT_String type; type = "urn:schemas-upnp-org:service:ContentDirectory:1"; if (NPT_FAILED(device->FindServiceByType(type, service))) { NPT_LOG_WARNING_1("Service %s not found", (const char*)type); return NPT_FAILURE; } PLT_ActionDesc* action_desc = service->FindActionDesc("Browse"); if (action_desc == NULL) { NPT_LOG_WARNING("Action Browse not found in service"); return NPT_FAILURE; } PLT_ActionReference action(new PLT_Action(action_desc)); // Set the object id PLT_Arguments args; if (NPT_FAILED(action->SetArgumentValue("ObjectID", obj_id))) { return NPT_ERROR_INVALID_PARAMETERS; } // set the browse_flag if (NPT_FAILED(action->SetArgumentValue("BrowseFlag", browse_metadata?"BrowseMetadata":"BrowseDirectChildren"))) { return NPT_ERROR_INVALID_PARAMETERS; } // set the Filter if (NPT_FAILED(action->SetArgumentValue("Filter", filter))) { return NPT_ERROR_INVALID_PARAMETERS; } // set the Starting Index if (NPT_FAILED(action->SetArgumentValue("StartingIndex", NPT_String::FromInteger(start_index)))) { return NPT_ERROR_INVALID_PARAMETERS; } // set the Requested Count if (NPT_FAILED(action->SetArgumentValue("RequestedCount", NPT_String::FromInteger(count)))) { return NPT_ERROR_INVALID_PARAMETERS; } // set the Requested Count if (NPT_FAILED(action->SetArgumentValue("SortCriteria", sort_criteria))) { return NPT_ERROR_INVALID_PARAMETERS; } // set the arguments on the action, this will check the argument values if (NPT_FAILED(m_CtrlPoint->InvokeAction(action, userdata))) { return NPT_ERROR_INVALID_PARAMETERS; } return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | NPT_ZipFile::Parse +---------------------------------------------------------------------*/ NPT_Result NPT_ZipFile::Parse(NPT_InputStream& stream, NPT_ZipFile*& file) { // defautl return value file = NULL; // check that we know the size of the stream NPT_LargeSize stream_size = 0; NPT_Result result = stream.GetSize(stream_size); if (NPT_FAILED(result)) { NPT_LOG_WARNING_1("cannot get stream size (%d)", result); return result; } if (stream_size < 22) { NPT_LOG_WARNING("input stream too short"); return NPT_ERROR_INVALID_FORMAT; } // seek to the most likely start of the end of central directory record unsigned int max_eocdr_size = 22+65536; if (max_eocdr_size > stream_size) { max_eocdr_size = (unsigned int)stream_size; } unsigned char eocdr[22]; bool record_found = false; NPT_Position position = 0; for (unsigned int i=0; i<max_eocdr_size; i++) { position = stream_size-22-i; result = stream.Seek(position); if (NPT_FAILED(result)) { NPT_LOG_WARNING_1("seek failed (%d)", result); return result; } result = stream.ReadFully(eocdr, 22); if (NPT_FAILED(result)) { NPT_LOG_WARNING_1("read failed (%d)", result); return result; } NPT_UInt32 signature = NPT_BytesToInt32Le(eocdr); if (signature == NPT_ZIP_END_OF_CENTRAL_DIRECTORY_SIGNATURE) { record_found = true; break; } } if (!record_found) { NPT_LOG_WARNING("eocd record not found at end of stream"); return NPT_ERROR_INVALID_FORMAT; } // parse the eocdr NPT_UInt32 this_disk = NPT_BytesToInt16Le(&eocdr[ 4]); NPT_UInt32 start_disk = NPT_BytesToInt16Le(&eocdr[ 6]); NPT_UInt64 this_disk_entry_count = NPT_BytesToInt16Le(&eocdr[ 8]); NPT_UInt64 total_entry_count = NPT_BytesToInt16Le(&eocdr[10]); NPT_UInt64 central_directory_size = NPT_BytesToInt32Le(&eocdr[12]); NPT_Position central_directory_offset = NPT_BytesToInt32Le(&eocdr[16]); // format check if (this_disk != 0 || start_disk != 0) { return NPT_ERROR_NOT_SUPPORTED; } if (this_disk_entry_count != total_entry_count) { return NPT_ERROR_NOT_SUPPORTED; } // check if this is a zip64 file if (central_directory_offset == 0xFFFFFFFF) { unsigned char zip64_locator[20]; result = stream.Seek(position-20); if (NPT_FAILED(result)) { NPT_LOG_WARNING_1("seek failed (%d)", result); return result; } result = stream.ReadFully(zip64_locator, 20); if (NPT_FAILED(result)) { NPT_LOG_WARNING_1("read failed (%d)", result); return result; } NPT_UInt32 signature = NPT_BytesToInt32Le(&zip64_locator[0]); if (signature != NPT_ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR_SIGNATURE) { NPT_LOG_WARNING("zip64 directory locator signature not found"); return NPT_ERROR_INVALID_FORMAT; } NPT_UInt32 zip64_disk_start = NPT_BytesToInt32Le(&zip64_locator[ 4]); NPT_UInt64 zip64_directory_offset = NPT_BytesToInt64Le(&zip64_locator[ 8]); NPT_UInt32 zip64_disk_count = NPT_BytesToInt32Le(&zip64_locator[16]); // format check if (zip64_disk_start != 0 || zip64_disk_count != 1) { return NPT_ERROR_NOT_SUPPORTED; } // size check if (zip64_directory_offset > stream_size) { NPT_LOG_WARNING("zip64 directory offset too large"); return NPT_ERROR_INVALID_FORMAT; } // load and parse the eocdr64 unsigned char eocdr64[56]; result = stream.Seek(zip64_directory_offset); if (NPT_FAILED(result)) { NPT_LOG_WARNING_1("seek failed (%d)", result); return result; } result = stream.ReadFully(eocdr64, 56); if (NPT_FAILED(result)) { NPT_LOG_WARNING_1("read failed (%d)", result); return result; } signature = NPT_BytesToInt32Le(&eocdr64[0]); if (signature != NPT_ZIP64_END_OF_CENTRAL_DIRECTORY_SIGNATURE) { NPT_LOG_WARNING("zip64 directory signature not found"); return NPT_ERROR_INVALID_FORMAT; } this_disk = NPT_BytesToInt32Le(&eocdr64[16]); start_disk = NPT_BytesToInt32Le(&eocdr64[20]); this_disk_entry_count = NPT_BytesToInt64Le(&eocdr64[24]); total_entry_count = NPT_BytesToInt64Le(&eocdr64[32]); central_directory_size = NPT_BytesToInt64Le(&eocdr64[40]); central_directory_offset = NPT_BytesToInt64Le(&eocdr64[48]); } // format check if (this_disk != 0 || start_disk != 0) { return NPT_ERROR_NOT_SUPPORTED; } if (this_disk_entry_count != total_entry_count) { return NPT_ERROR_NOT_SUPPORTED; } // check that the size looks reasonable if (central_directory_size > NPT_ZIP_MAX_DIRECTORY_SIZE) { NPT_LOG_WARNING("central directory larger than max supported"); return NPT_ERROR_OUT_OF_RANGE; } if (total_entry_count > NPT_ZIP_MAX_ENTRY_COUNT) { NPT_LOG_WARNING("central directory larger than max supported"); return NPT_ERROR_OUT_OF_RANGE; } // read the central directory NPT_DataBuffer central_directory_buffer; result = central_directory_buffer.SetDataSize((NPT_Size)central_directory_size); if (NPT_FAILED(result)) { NPT_LOG_WARNING_1("central directory too large (%lld)", central_directory_size); return result; } result = stream.Seek(central_directory_offset); if (NPT_FAILED(result)) { NPT_LOG_WARNING_1("seek failed (%d)", result); return result; } result = stream.ReadFully(central_directory_buffer.UseData(), (NPT_Size)central_directory_size); if (NPT_FAILED(result)) { NPT_LOG_WARNING_1("failed to read central directory (%d)", result); return result; } // create a new file object file = new NPT_ZipFile(); file->m_Entries.Reserve((NPT_Cardinal)total_entry_count); // parse all entries const unsigned char* buffer = (const unsigned char*)central_directory_buffer.GetData(); for (unsigned int i=0; i<total_entry_count; i++) { NPT_UInt32 signature = NPT_BytesToInt32Le(buffer); if (signature != NPT_ZIP_CENTRAL_FILE_HEADER_SIGNATURE) { NPT_LOG_WARNING("unexpected signature in central directory"); break; } NPT_ZipFile::Entry entry(buffer); if (entry.m_DirectoryEntrySize > central_directory_size) { NPT_LOG_WARNING_1("entry size too large (%d)", entry.m_DirectoryEntrySize); break; } file->GetEntries().Add(entry); central_directory_size -= entry.m_DirectoryEntrySize; buffer += entry.m_DirectoryEntrySize; } return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_FileMediaServer::OnBrowseDirectChildren +---------------------------------------------------------------------*/ NPT_Result PLT_FileMediaServer::OnBrowseDirectChildren(PLT_ActionReference& action, const char* object_id, NPT_SocketInfo* info /* = NULL */) { /* locate the file from the object ID */ NPT_String dir; if (NPT_FAILED(GetFilePath(object_id, dir))) { /* error */ NPT_LOG_WARNING("PLT_FileMediaServer::OnBrowse - ObjectID not found."); action->SetError(701, "No Such Object."); return NPT_FAILURE; } /* retrieve the item type */ NPT_DirectoryEntryInfo entry_info; NPT_Result res = NPT_DirectoryEntry::GetInfo(dir, entry_info); if (NPT_FAILED(res)) { /* Object does not exist */ action->SetError(800, "Can't retrieve info " + dir); return NPT_FAILURE; } if (entry_info.type != NPT_DIRECTORY_TYPE) { /* error */ NPT_LOG_WARNING("PLT_FileMediaServer::OnBrowse - BROWSEDIRECTCHILDREN not allowed on an item."); action->SetError(710, "item is not a container."); return NPT_FAILURE; } NPT_String filter; NPT_String startingInd; NPT_String reqCount; NPT_CHECK_SEVERE(action->GetArgumentValue("Filter", filter)); NPT_CHECK_SEVERE(action->GetArgumentValue("StartingIndex", startingInd)); NPT_CHECK_SEVERE(action->GetArgumentValue("RequestedCount", reqCount)); unsigned long start_index, req_count; if (NPT_FAILED(startingInd.ToInteger(start_index)) || NPT_FAILED(reqCount.ToInteger(req_count))) { return NPT_FAILURE; } NPT_String path = dir; if (!path.EndsWith(m_DirDelimiter)) { path += m_DirDelimiter; } /* start iterating through the directory */ NPT_Directory directory(path); NPT_String entryName; res = directory.GetNextEntry(entryName); if (NPT_FAILED(res)) { NPT_LOG_WARNING_1("PLT_FileMediaServer::OnBrowseDirectChildren - failed to open dir %s", (const char*) path); return res; } unsigned long cur_index = 0; unsigned long num_returned = 0; unsigned long total_matches = 0; //unsigned long update_id = 0; NPT_String didl = didl_header; PLT_MediaObjectReference item; do { item = BuildFromFilePath(path + entryName, true, info); if (!item.IsNull()) { if ((cur_index >= start_index) && ((num_returned < req_count) || (req_count == 0))) { NPT_String tmp; NPT_CHECK_SEVERE(PLT_Didl::ToDidl(*item.AsPointer(), filter, tmp)); didl += tmp; num_returned++; } cur_index++; total_matches++; } res = directory.GetNextEntry(entryName); } while (NPT_SUCCEEDED(res)); didl += didl_footer; NPT_CHECK_SEVERE(action->SetArgumentValue("Result", didl)); NPT_CHECK_SEVERE(action->SetArgumentValue("NumberReturned", NPT_String::FromInteger(num_returned))); NPT_CHECK_SEVERE(action->SetArgumentValue("TotalMatches", NPT_String::FromInteger(total_matches))); NPT_CHECK_SEVERE(action->SetArgumentValue("UpdateId", "1")); return NPT_SUCCESS; }