Example #1
0
/*----------------------------------------------------------------------
|   PLT_FileMediaServer::ServeFile
+---------------------------------------------------------------------*/
NPT_Result 
PLT_FileMediaServer::ServeFile(NPT_HttpRequest&              request, 
                               const NPT_HttpRequestContext& context,
                               NPT_HttpResponse&             response,
                               const NPT_String&             uri_path,
                               const NPT_String&             file_path)
{
    NPT_COMPILER_UNUSED(context);

    // prevent hackers from accessing files outside of our root
    if ((file_path.Find("/..") >= 0) || (file_path.Find("\\..") >= 0)) {
        return NPT_FAILURE;
    }

    // File requested
    NPT_String path = m_FileBaseUri.GetPath();
    if (path.Compare(uri_path.Left(path.GetLength()), true) == 0) {
        NPT_Position start, end;
        PLT_HttpHelper::GetRange(request, start, end);
        
        return PLT_FileServer::ServeFile(response,
                                         NPT_FilePath::Create(m_Path, file_path), 
                                         start, 
                                         end, 
                                         !request.GetMethod().Compare("HEAD"));
    } 

    // Album Art requested
    path = m_AlbumArtBaseUri.GetPath();
    if (path.Compare(uri_path.Left(path.GetLength()), true) == 0) {
        return OnAlbumArtRequest(response, m_Path + file_path);
    } 
    
    return NPT_FAILURE;
}
Example #2
0
/*----------------------------------------------------------------------
|   NPT_DirectoryCreate
+---------------------------------------------------------------------*/
NPT_Result 
NPT_DirectoryCreate(const char* path, bool create_parents)
{
    NPT_Result res = NPT_SUCCESS;
    NPT_String fullpath = path;

    // replace delimiters with the proper one for the platform
    fullpath.Replace((NPT_DIR_DELIMITER_CHR == '/')?'\\':'/', NPT_DIR_DELIMITER_CHR);
    // remove excessive delimiters
    fullpath.TrimRight(NPT_DIR_DELIMITER_CHR);

    if (create_parents) {
        NPT_String parent_path;

        // look for a delimiter from the beginning
        int delimiter = fullpath.Find(NPT_DIR_DELIMITER_CHR, 1);
        while (delimiter > 0 && NPT_SUCCEEDED(res)) {
            // copy the path up to the delimiter
            parent_path = fullpath.SubString(0, delimiter);

            // create the directory non recursively
            res = NPT_DirectoryCreate(parent_path, false);   

            // look for the next delimiter
            delimiter = fullpath.Find(NPT_DIR_DELIMITER_CHR, delimiter + 1);
        }

        if (NPT_FAILED(res)) return res;
    }

    // create directory
    return NPT_Directory::Create(fullpath);
}
Example #3
0
/*----------------------------------------------------------------------
|   PLT_HttpServer::ServeFile
+---------------------------------------------------------------------*/
NPT_Result 
PLT_HttpServer::ServeFile(const NPT_HttpRequest&        request, 
                          const NPT_HttpRequestContext& context,
                          NPT_HttpResponse&             response,
                          NPT_String                    file_path) 
{
    NPT_InputStreamReference stream;
    NPT_File                 file(file_path);
    NPT_FileInfo             file_info;
    
    // prevent hackers from accessing files outside of our root
    if ((file_path.Find("/..") >= 0) || (file_path.Find("\\..") >= 0) ||
        NPT_FAILED(NPT_File::GetInfo(file_path, &file_info))) {
        return NPT_ERROR_NO_SUCH_ITEM;
    }
    
    // check for range requests
    const NPT_String* range_spec = request.GetHeaders().GetHeaderValue(NPT_HTTP_HEADER_RANGE);
    
    // handle potential 304 only if range header not set
    NPT_DateTime  date;
    NPT_TimeStamp timestamp;
    if (NPT_SUCCEEDED(PLT_UPnPMessageHelper::GetIfModifiedSince((NPT_HttpMessage&)request, date)) &&
        !range_spec) {
        date.ToTimeStamp(timestamp);
        
        NPT_LOG_INFO_5("File %s timestamps: request=%d (%s) vs file=%d (%s)", 
                       (const char*)request.GetUrl().GetPath(),
                       (NPT_UInt32)timestamp.ToSeconds(),
                       (const char*)date.ToString(),
                       (NPT_UInt32)file_info.m_ModificationTime,
                       (const char*)NPT_DateTime(file_info.m_ModificationTime).ToString());
        
        if (timestamp >= file_info.m_ModificationTime) {
            // it's a match
            NPT_LOG_FINE_1("Returning 304 for %s", request.GetUrl().GetPath().GetChars());
            response.SetStatus(304, "Not Modified", NPT_HTTP_PROTOCOL_1_1);
            return NPT_SUCCESS;
        }
    }
    
    // open file
    if (NPT_FAILED(file.Open(NPT_FILE_OPEN_MODE_READ)) || 
        NPT_FAILED(file.GetInputStream(stream))        ||
        stream.IsNull()) {
        return NPT_ERROR_NO_SUCH_ITEM;
    }
    
    // set Last-Modified and Cache-Control headers
    if (file_info.m_ModificationTime) {
        NPT_DateTime last_modified = NPT_DateTime(file_info.m_ModificationTime);
        response.GetHeaders().SetHeader("Last-Modified", last_modified.ToString(NPT_DateTime::FORMAT_RFC_1123), true);
        response.GetHeaders().SetHeader("Cache-Control", "max-age=0,must-revalidate", true);
        //response.GetHeaders().SetHeader("Cache-Control", "max-age=1800", true);
    }
    
    PLT_HttpRequestContext tmp_context(request, context);
    return ServeStream(request, context, response, stream, PLT_MimeType::GetMimeType(file_path, &tmp_context));
}
/*----------------------------------------------------------------------
|   CUPnPRenderer::ProcessHttpRequest
+---------------------------------------------------------------------*/
NPT_Result
CUPnPRenderer::ProcessHttpGetRequest(NPT_HttpRequest&              request,
                                  const NPT_HttpRequestContext& context,
                                  NPT_HttpResponse&             response)
{
    // get the address of who sent us some data back
    NPT_String  ip_address = context.GetRemoteAddress().GetIpAddress().ToString();
    NPT_String  method     = request.GetMethod();
    NPT_String  protocol   = request.GetProtocol();
    NPT_HttpUrl url        = request.GetUrl();

    if (url.GetPath() == "/thumb") {
        NPT_HttpUrlQuery query(url.GetQuery());
        NPT_String filepath = query.GetField("path");
        if (!filepath.IsEmpty()) {
            NPT_HttpEntity* entity = response.GetEntity();
            if (entity == NULL) return NPT_ERROR_INVALID_STATE;

            // check the method
            if (request.GetMethod() != NPT_HTTP_METHOD_GET &&
                request.GetMethod() != NPT_HTTP_METHOD_HEAD) {
                response.SetStatus(405, "Method Not Allowed");
                return NPT_SUCCESS;
            }

            // prevent hackers from accessing files outside of our root
            if ((filepath.Find("/..") >= 0) || (filepath.Find("\\..") >=0)) {
                return NPT_FAILURE;
            }
#if 1
            std::string path;
            //url
#else
            // open the file
            CStdString path = CURL::Decode((const char*) filepath);
#endif
            NPT_File file(path.c_str());
            NPT_Result result = file.Open(NPT_FILE_OPEN_MODE_READ);
            if (NPT_FAILED(result)) {
                response.SetStatus(404, "Not Found");
                return NPT_SUCCESS;
            }
            NPT_InputStreamReference stream;
            file.GetInputStream(stream);
            entity->SetContentType(GetMimeType(filepath));
            entity->SetInputStream(stream, true);

            return NPT_SUCCESS;
        }
    }

    return PLT_MediaRenderer::ProcessHttpGetRequest(request, context, response);
}
Example #5
0
/*----------------------------------------------------------------------
|   PLT_FileMediaServer::OnAlbumArtRequest
+---------------------------------------------------------------------*/
NPT_Result 
PLT_FileMediaServer::OnAlbumArtRequest(NPT_HttpResponse& response,
                                       NPT_String        file_path)
{
    NPT_LargeSize            total_len;
    NPT_File                 file(file_path);
    NPT_InputStreamReference stream;

    // prevent hackers from accessing files outside of our root
    if ((file_path.Find("/..") >= 0) || (file_path.Find("\\..") >= 0)) {
        return NPT_FAILURE;
    }

    if (NPT_FAILED(file.Open(NPT_FILE_OPEN_MODE_READ)) || 
        NPT_FAILED(file.GetInputStream(stream))        || 
        NPT_FAILED(stream->GetSize(total_len)) || (total_len == 0)) {
        goto filenotfound;
    } else {
        NPT_String extension = NPT_FilePath::FileExtension(file_path);
        if (extension.GetLength() == 0) {
            goto filenotfound;
        }

        PLT_MetadataHandler* metadataHandler = NULL;
        char* caData;
        int   caDataLen;
        NPT_Result ret = NPT_ContainerFind(m_MetadataHandlers, 
                                           PLT_MetadataHandlerFinder(extension), 
                                           metadataHandler);
        if (NPT_FAILED(ret) || metadataHandler == NULL) {
            goto filenotfound;
        }
        // load the metadatahandler and read the cover art
        if (NPT_FAILED(metadataHandler->Load(*stream)) || 
            NPT_FAILED(metadataHandler->GetCoverArtData(caData, caDataLen))) {
            goto filenotfound;
        }
        
        PLT_HttpHelper::SetContentType(response, "application/octet-stream");
        PLT_HttpHelper::SetBody(response, caData, caDataLen);
        delete caData;
        return NPT_SUCCESS;
    }

filenotfound:
    response.SetStatus(404, "File Not Found");
    return NPT_SUCCESS;
}
/*----------------------------------------------------------------------
|   CUPnPDirectory::GetFriendlyName
+---------------------------------------------------------------------*/
const char*
CUPnPDirectory::GetFriendlyName(const char* url)
{
    NPT_String path = url;
    if (!path.EndsWith("/")) path += "/";

    if (path.Left(7).Compare("upnp://", true) != 0) {
        return NULL;
    } else if (path.Compare("upnp://", true) == 0) {
        return "UPnP Media Servers (Auto-Discover)";
    }

    // look for nextslash
    int next_slash = path.Find('/', 7);
    if (next_slash == -1)
        return NULL;

    NPT_String uuid = path.SubString(7, next_slash-7);
    NPT_String object_id = path.SubString(next_slash+1, path.GetLength()-next_slash-2);

    // look for device
    PLT_DeviceDataReference* device;
    const NPT_Lock<PLT_DeviceMap>& devices = CUPnP::GetInstance()->m_MediaBrowser->GetMediaServers();
    if (NPT_FAILED(devices.Get(uuid, device)) || device == NULL)
        return NULL;

    return (const char*)(*device)->GetFriendlyName();
}
Example #7
0
/*----------------------------------------------------------------------
|   CMediaCrawler::SplitObjectId
+---------------------------------------------------------------------*/
NPT_Result
CMediaCrawler::SplitObjectId(const NPT_String& object_id, NPT_String& server_uuid, NPT_String& server_object_id)
{
    // reset output params
    server_uuid = "";
    server_object_id = "";

    if (object_id.GetLength() == 0 || object_id[0] != '0')
        return NPT_ERROR_INVALID_FORMAT;

    if (object_id.GetLength() > 1) {
        if (object_id[1] != '/') return NPT_ERROR_INVALID_FORMAT;
    
        server_uuid = object_id.SubString(2);

        // look for next delimiter
        int index = server_uuid.Find('/');
        if (index >= 0) {
            server_object_id = server_uuid.SubString(index+1);
            server_uuid.SetLength(index);
        }
    }

    return NPT_SUCCESS;
}
Example #8
0
/*----------------------------------------------------------------------
|   CUPnPDirectory::GetFriendlyName
+---------------------------------------------------------------------*/
const char*
CUPnPDirectory::GetFriendlyName(const char* url)
{
    NPT_String path = url;
    if (!path.EndsWith("/")) path += "/";

    if (path.Left(7).Compare("upnp://", true) != 0) {
        return NULL;
    } else if (path.Compare("upnp://", true) == 0) {
        return "UPnP Media Servers (Auto-Discover)";
    }

    // look for nextslash
    int next_slash = path.Find('/', 7);
    if (next_slash == -1)
        return NULL;

    NPT_String uuid = path.SubString(7, next_slash-7);
    NPT_String object_id = path.SubString(next_slash+1, path.GetLength()-next_slash-2);

    // look for device
    PLT_DeviceDataReference device;
    if(!FindDeviceWait(CUPnP::GetInstance(), uuid, device))
        return NULL;

    return (const char*)device->GetFriendlyName();
}
Example #9
0
void 
GPAC_MediaController::OnMSStateVariablesChanged(PLT_Service* service, NPT_List<PLT_StateVariable*>* vars)
{
	GPAC_MediaServerItem *ms = NULL;
	gf_mx_p(m_ControlPointLock);

	u32 i, count;
	count = gf_list_count(m_MediaServers);
	for (i=0; i<count; i++) {
		GPAC_MediaServerItem *ms = (GPAC_MediaServerItem *) gf_list_get(m_MediaServers, i);
		if (ms->m_UUID==service->GetDevice()->GetUUID()) {
			break;
		}
		ms = NULL;
	}
	
	if (!ms) {
		gf_mx_v(m_ControlPointLock);
		return;
	}

    PLT_StateVariable* var = PLT_StateVariable::Find(*vars, "ContainerUpdateIDs");
    if (var) {
        // variable found, parse value
        NPT_String value = var->GetValue();
        NPT_String item_id, update_id;
        int index;

        while (value.GetLength()) {
            // look for container id
            index = value.Find(',');
            if (index < 0) break;
            item_id = value.Left(index);
            value = value.SubString(index+1);

            // look for update id
            if (value.GetLength()) {
                index = value.Find(',');
                update_id = (index<0)?value:value.Left(index);
                value = (index<0)?"":value.SubString(index+1);

				m_pUPnP->ContainerChanged(ms->m_device, item_id, update_id);
            }       
        }
    }        
	gf_mx_v(m_ControlPointLock);
}
Example #10
0
/*----------------------------------------------------------------------
|   PLT_SyncMediaBrowser::OnMSStateVariablesChanged
+---------------------------------------------------------------------*/
void 
PLT_SyncMediaBrowser::OnMSStateVariablesChanged(PLT_Service*                  service, 
                                                NPT_List<PLT_StateVariable*>* vars)
{
    NPT_AutoLock lock(m_MediaServers);
    
    PLT_DeviceDataReference device;
    const NPT_List<PLT_DeviceMapEntry*>::Iterator it = 
        m_MediaServers.GetEntries().Find(PLT_DeviceMapFinderByUUID(service->GetDevice()->GetUUID()));
    if (!it) return; // device with this service has gone away

    device = (*it)->GetValue();
    PLT_StateVariable* var = PLT_StateVariable::Find(*vars, "ContainerUpdateIDs");
    if (var) {
        // variable found, parse value
        NPT_String value = var->GetValue();
        NPT_String item_id, update_id;
        int index;

        while (value.GetLength()) {
            // look for container id
            index = value.Find(',');
            if (index < 0) break;
            item_id = value.Left(index);
            value = value.SubString(index+1);

            // look for update id
            if (value.GetLength()) {
                index = value.Find(',');
                update_id = (index<0)?value:value.Left(index);
                value = (index<0)?"":value.SubString(index+1);

                // clear cache for that device
                if (m_UseCache) m_Cache.Clear(device->GetUUID(), item_id);

                // notify listener
                if (m_ContainerListener) m_ContainerListener->OnContainerChanged(device, item_id, update_id);
            }       
        }
    }        
}
Example #11
0
/*----------------------------------------------------------------------
|   PLT_FileMediaServer::ProcessFileRequest
+---------------------------------------------------------------------*/
NPT_Result 
PLT_FileMediaServer::ProcessFileRequest(NPT_HttpRequest&  request, 
                                        NPT_HttpResponse& response, 
                                        NPT_SocketInfo&   client_info)
{
    NPT_COMPILER_UNUSED(client_info);

    NPT_LOG_FINE("PLT_FileMediaServer::ProcessFileRequest Received Request:");
    PLT_LOG_HTTP_MESSAGE(NPT_LOG_LEVEL_FINE, &request);

    response.GetHeaders().SetHeader("Accept-Ranges", "bytes");

    if (request.GetMethod().Compare("GET") && request.GetMethod().Compare("HEAD")) {
        response.SetStatus(500, "Internal Server Error");
        return NPT_SUCCESS;
    }

    // File requested
    NPT_String path = m_FileBaseUri.GetPath();
    NPT_String strUri = NPT_Uri::PercentDecode(request.GetUrl().GetPath());

    NPT_HttpUrlQuery query(request.GetUrl().GetQuery());
    NPT_String file_path = query.GetField("path");

    // hack for XBMC support for 360, we urlencoded the ? to that the 360 doesn't strip out the query
    // but then the query ends being parsed as part of the path
    int index = strUri.Find("path=");
    if (index>0) file_path = strUri.Right(strUri.GetLength()-index-5);
    if (file_path.GetLength() == 0) goto failure;

    // HACK for wmp: somehow they inverse our slashes !
    // do it only if we're on windows
    if (m_DirDelimiter == "\\") {
        file_path.Replace('/', '\\');
    }

    if (path.Compare(strUri.Left(path.GetLength()), true) == 0) {
        NPT_Integer start, end;
        PLT_HttpHelper::GetRange(&request, start, end);

        return PLT_FileServer::ServeFile(m_Path + file_path, &response, start, end, !request.GetMethod().Compare("HEAD"));
    } 

    // Album Art requested
    path = m_AlbumArtBaseUri.GetPath();
    if (path.Compare(strUri.Left(path.GetLength()), true) == 0) {
        return OnAlbumArtRequest(m_Path + file_path, response);
    } 

failure:
    response.SetStatus(404, "File Not Found");
    return NPT_SUCCESS;
}
/*----------------------------------------------------------------------
|   PLT_MicroMediaController::HandleCmd_seek
+---------------------------------------------------------------------*/
void
PLT_MicroMediaController::HandleCmd_seek(const char* command)
{
    PLT_DeviceDataReference device;
    GetCurMediaRenderer(device);
    if (!device.IsNull()) {
        // remove first part of command ("seek")
        NPT_String target = command;
        NPT_List<NPT_String> args = target.Split(" ");
        if (args.GetItemCount() < 2) return;

        args.Erase(args.GetFirstItem());
        target = NPT_String::Join(args, " ");

        Seek(device, 0, (target.Find(":")!=-1)?"REL_TIME":"X_DLNA_REL_BYTE", target, NULL);
    }
}
Example #13
0
/*----------------------------------------------------------------------
|   CUPnPVirtualPathDirectory::SplitPath
+---------------------------------------------------------------------*/
bool
CUPnPVirtualPathDirectory::SplitPath(const char* object_id, NPT_String& share_name, NPT_String& path)
{
    int index = 0;
    NPT_String id = object_id;
    id.TrimRight("/");

    // reset output params first
    share_name = "";
    path = "";

    if (id.StartsWith("virtualpath://upnproot")) {
        index = 22;
    } else if (id.StartsWith("virtualpath://upnpmusic")) {
        index = 23;
    } else if (id.StartsWith("virtualpath://upnpvideo")) {
        index = 23;
    } else if (id.StartsWith("virtualpath://upnppictures")) {
        index = 26;
    } else {
        return false;
    }

    // nothing to split
    if (id.GetLength() <= (NPT_Cardinal)index) {
        return true;
    }

    // invalid id!
    if (id[index] != '/') {
        return false;
    }

    // look for share
    index = id.Find('/', index+1);
    share_name = id.SubString(0, (index==-1)?id.GetLength():index);

    if (index >= 0) {
        path = id.SubString(index+1);
    }

    return true;
}
Example #14
0
/*----------------------------------------------------------------------
|   CUPnPDirectory::GetDirectory
+---------------------------------------------------------------------*/
bool
CUPnPDirectory::GetDirectory(const CStdString& strPath, CFileItemList &items)
{
    CUPnP* upnp = CUPnP::GetInstance();

    /* upnp should never be cached, it has internal cache */
    items.SetCacheToDisc(CFileItemList::CACHE_NEVER);

    // We accept upnp://devuuid/[item_id/]
    NPT_String path = strPath.c_str();
    if (!path.StartsWith("upnp://", true)) {
        return false;
    }

    if (path.Compare("upnp://", true) == 0) {
        upnp->StartClient();

        // root -> get list of devices
        const NPT_Lock<PLT_DeviceDataReferenceList>& devices = upnp->m_MediaBrowser->GetMediaServers();
        NPT_List<PLT_DeviceDataReference>::Iterator device = devices.GetFirstItem();
        while (device) {
            NPT_String name = (*device)->GetFriendlyName();
            NPT_String uuid = (*device)->GetUUID();

            CFileItemPtr pItem(new CFileItem((const char*)name));
            pItem->SetPath(CStdString((const char*) "upnp://" + uuid + "/"));
            pItem->m_bIsFolder = true;
            pItem->SetThumbnailImage((const char*)(*device)->GetIconUrl("image/jpeg"));

            items.Add(pItem);

            ++device;
        }
    } else {
        if (!path.EndsWith("/")) path += "/";

        // look for nextslash
        int next_slash = path.Find('/', 7);

        NPT_String uuid = (next_slash==-1)?path.SubString(7):path.SubString(7, next_slash-7);
        NPT_String object_id = (next_slash==-1)?"":path.SubString(next_slash+1);
        object_id.TrimRight("/");
        if (object_id.GetLength()) {
            CStdString tmp = (char*) object_id;
            CURL::Decode(tmp);
            object_id = tmp;
        }

        // try to find the device with wait on startup
        PLT_DeviceDataReference device;
        if (!FindDeviceWait(upnp, uuid, device))
            goto failure;

        // issue a browse request with object_id
        // if object_id is empty use "0" for root
        object_id = object_id.IsEmpty()?"0":object_id;

        // remember a count of object classes
        std::map<NPT_String, int> classes;

        // just a guess as to what types of files we want
        bool video = true;
        bool audio = true;
        bool image = true;
        m_strFileMask.TrimLeft("/");
        if (!m_strFileMask.IsEmpty()) {
            video = m_strFileMask.Find(".wmv") >= 0;
            audio = m_strFileMask.Find(".wma") >= 0;
            image = m_strFileMask.Find(".jpg") >= 0;
        }

        // special case for Windows Media Connect and WMP11 when looking for root
        // We can target which root subfolder we want based on directory mask
        if (object_id == "0" && ((device->GetFriendlyName().Find("Windows Media Connect", 0, true) >= 0) ||
                                 (device->m_ModelName == "Windows Media Player Sharing"))) {

            // look for a specific type to differentiate which folder we want
            if (audio && !video && !image) {
                // music
                object_id = "1";
            } else if (!audio && video && !image) {
                // video
                object_id = "2";
            } else if (!audio && !video && image) {
                // pictures
                object_id = "3";
            }
        }

#ifdef DISABLE_SPECIALCASE
        // same thing but special case for XBMC
        if (object_id == "0" && ((device->m_ModelName.Find("XBMC", 0, true) >= 0) ||
                                 (device->m_ModelName.Find("Xbox Media Center", 0, true) >= 0))) {
            // look for a specific type to differentiate which folder we want
            if (audio && !video && !image) {
                // music
                object_id = "virtualpath://upnpmusic";
            } else if (!audio && video && !image) {
                // video
                object_id = "virtualpath://upnpvideo";
            } else if (!audio && !video && image) {
                // pictures
                object_id = "virtualpath://upnppictures";
            }
        }
#endif

        // if error, return now, the device could have gone away
        // this will make us go back to the sources list
        PLT_MediaObjectListReference list;
        NPT_Result res = upnp->m_MediaBrowser->BrowseSync(device, object_id, list);
        if (NPT_FAILED(res)) goto failure;

        // empty list is ok
        if (list.IsNull()) goto cleanup;

        PLT_MediaObjectList::Iterator entry = list->GetFirstItem();
        while (entry) {
            // disregard items with wrong class/type
            if( (!video && (*entry)->m_ObjectClass.type.CompareN("object.item.videoitem", 21,true) == 0)
                    || (!audio && (*entry)->m_ObjectClass.type.CompareN("object.item.audioitem", 21,true) == 0)
                    || (!image && (*entry)->m_ObjectClass.type.CompareN("object.item.imageitem", 21,true) == 0) )
            {
                ++entry;
                continue;
            }

            // never show empty containers in media views
            if((*entry)->IsContainer()) {
                if( (audio || video || image)
                        && ((PLT_MediaContainer*)(*entry))->m_ChildrenCount == 0) {
                    ++entry;
                    continue;
                }
            }

            NPT_String ObjectClass = (*entry)->m_ObjectClass.type.ToLowercase();

            // keep count of classes
            classes[(*entry)->m_ObjectClass.type]++;

            CFileItemPtr pItem(new CFileItem((const char*)(*entry)->m_Title));
            pItem->SetLabelPreformated(true);
            pItem->m_strTitle = (const char*)(*entry)->m_Title;
            pItem->m_bIsFolder = (*entry)->IsContainer();

            CStdString id = (char*) (*entry)->m_ObjectID;
            CURL::Encode(id);
            pItem->SetPath(CStdString((const char*) "upnp://" + uuid + "/" + id.c_str()));

            // if it's a container, format a string as upnp://uuid/object_id
            if (pItem->m_bIsFolder) {
                pItem->SetPath(pItem->GetPath() + "/");

                // look for metadata
                if( ObjectClass.StartsWith("object.container.album.videoalbum") ) {
                    pItem->SetLabelPreformated(false);
                    CUPnP::PopulateTagFromObject(*pItem->GetVideoInfoTag(), *(*entry), NULL);

                } else if( ObjectClass.StartsWith("object.container.album.photoalbum")) {
                    //CPictureInfoTag* tag = pItem->GetPictureInfoTag();

                } else if( ObjectClass.StartsWith("object.container.album") ) {
                    pItem->SetLabelPreformated(false);
                    CUPnP::PopulateTagFromObject(*pItem->GetMusicInfoTag(), *(*entry), NULL);
                }

            } else {

                // set a general content type
                if (ObjectClass.StartsWith("object.item.videoitem"))
                    pItem->SetMimeType("video/octet-stream");
                else if(ObjectClass.StartsWith("object.item.audioitem"))
                    pItem->SetMimeType("audio/octet-stream");
                else if(ObjectClass.StartsWith("object.item.imageitem"))
                    pItem->SetMimeType("image/octet-stream");

                if ((*entry)->m_Resources.GetItemCount()) {
                    PLT_MediaItemResource& resource = (*entry)->m_Resources[0];

                    // set metadata
                    if (resource.m_Size != (NPT_LargeSize)-1) {
                        pItem->m_dwSize  = resource.m_Size;
                    }

                    // look for metadata
                    if( ObjectClass.StartsWith("object.item.videoitem") ) {
                        pItem->SetLabelPreformated(false);
                        CUPnP::PopulateTagFromObject(*pItem->GetVideoInfoTag(), *(*entry), &resource);

                    } else if( ObjectClass.StartsWith("object.item.audioitem") ) {
                        pItem->SetLabelPreformated(false);
                        CUPnP::PopulateTagFromObject(*pItem->GetMusicInfoTag(), *(*entry), &resource);

                    } else if( ObjectClass.StartsWith("object.item.imageitem") ) {
                        //CPictureInfoTag* tag = pItem->GetPictureInfoTag();

                    }
                }
            }

            // look for date?
            if((*entry)->m_Description.date.GetLength()) {
                SYSTEMTIME time = {};
                sscanf((*entry)->m_Description.date, "%hu-%hu-%huT%hu:%hu:%hu",
                       &time.wYear, &time.wMonth, &time.wDay, &time.wHour, &time.wMinute, &time.wSecond);
                pItem->m_dateTime = time;
            }

            // if there is a thumbnail available set it here
            if((*entry)->m_ExtraInfo.album_art_uri.GetLength())
                pItem->SetThumbnailImage((const char*) (*entry)->m_ExtraInfo.album_art_uri);
            else if((*entry)->m_Description.icon_uri.GetLength())
                pItem->SetThumbnailImage((const char*) (*entry)->m_Description.icon_uri);

            PLT_ProtocolInfo fanart_mask("xbmc.org", "*", "fanart", "*");
            for(unsigned i = 0; i < (*entry)->m_Resources.GetItemCount(); ++i) {
                PLT_MediaItemResource& res = (*entry)->m_Resources[i];
                if(res.m_ProtocolInfo.Match(fanart_mask)) {
                    pItem->SetProperty("fanart_image", (const char*)res.m_Uri);
                    break;
                }
            }
            items.Add(pItem);

            ++entry;
        }

        NPT_String max_string = "";
        int        max_count  = 0;
        for(std::map<NPT_String, int>::iterator it = classes.begin(); it != classes.end(); it++)
        {
            if(it->second > max_count)
            {
                max_string = it->first;
                max_count  = it->second;
            }
        }
        items.SetContent(GetContentMapping(max_string));
    }

cleanup:
    return true;

failure:
    return false;
}
Example #15
0
/*----------------------------------------------------------------------
|   CUPnPDirectory::GetDirectory
+---------------------------------------------------------------------*/
bool
CUPnPDirectory::GetDirectory(const CStdString& strPath, CFileItemList &items)
{
    CUPnP* upnp = CUPnP::GetInstance();

    /* upnp should never be cached, it has internal cache */
    items.SetCacheToDisc(CFileItemList::CACHE_NEVER);

    // We accept upnp://devuuid/[item_id/]
    NPT_String path = strPath.c_str();
    if (!path.StartsWith("upnp://", true)) {
        return false;
    }

    if (path.Compare("upnp://", true) == 0) {
        upnp->StartClient();

        // root -> get list of devices
        const NPT_Lock<PLT_DeviceDataReferenceList>& devices = upnp->m_MediaBrowser->GetMediaServers();
        NPT_List<PLT_DeviceDataReference>::Iterator device = devices.GetFirstItem();
        while (device) {
            NPT_String name = (*device)->GetFriendlyName();
            NPT_String uuid = (*device)->GetUUID();

            CFileItemPtr pItem(new CFileItem((const char*)name));
            pItem->SetPath(CStdString((const char*) "upnp://" + uuid + "/"));
            pItem->m_bIsFolder = true;
            pItem->SetArt("thumb", (const char*)(*device)->GetIconUrl("image/png"));

            items.Add(pItem);

            ++device;
        }
    } else {
        if (!path.EndsWith("/")) path += "/";

        // look for nextslash
        int next_slash = path.Find('/', 7);

        NPT_String uuid = (next_slash==-1)?path.SubString(7):path.SubString(7, next_slash-7);
        NPT_String object_id = (next_slash==-1)?"":path.SubString(next_slash+1);
        object_id.TrimRight("/");
        if (object_id.GetLength()) {
            CStdString tmp = (char*) object_id;
            CURL::Decode(tmp);
            object_id = tmp;
        }

        // try to find the device with wait on startup
        PLT_DeviceDataReference device;
        if (!FindDeviceWait(upnp, uuid, device))
            goto failure;

        // issue a browse request with object_id
        // if object_id is empty use "0" for root
        object_id = object_id.IsEmpty()?"0":object_id;

        // remember a count of object classes
        std::map<NPT_String, int> classes;

        // just a guess as to what types of files we want
        bool video = true;
        bool audio = true;
        bool image = true;
        m_strFileMask.TrimLeft("/");
        if (!m_strFileMask.IsEmpty()) {
            video = m_strFileMask.Find(".wmv") >= 0;
            audio = m_strFileMask.Find(".wma") >= 0;
            image = m_strFileMask.Find(".jpg") >= 0;
        }

        // special case for Windows Media Connect and WMP11 when looking for root
        // We can target which root subfolder we want based on directory mask
        if (object_id == "0" && ((device->GetFriendlyName().Find("Windows Media Connect", 0, true) >= 0) ||
                                 (device->m_ModelName == "Windows Media Player Sharing"))) {

            // look for a specific type to differentiate which folder we want
            if (audio && !video && !image) {
                // music
                object_id = "1";
            } else if (!audio && video && !image) {
                // video
                object_id = "2";
            } else if (!audio && !video && image) {
                // pictures
                object_id = "3";
            }
        }

#ifdef DISABLE_SPECIALCASE
        // same thing but special case for XBMC
        if (object_id == "0" && ((device->m_ModelName.Find("XBMC", 0, true) >= 0) ||
                                 (device->m_ModelName.Find("Xbox Media Center", 0, true) >= 0))) {
            // look for a specific type to differentiate which folder we want
            if (audio && !video && !image) {
                // music
                object_id = "virtualpath://upnpmusic";
            } else if (!audio && video && !image) {
                // video
                object_id = "virtualpath://upnpvideo";
            } else if (!audio && !video && image) {
                // pictures
                object_id = "virtualpath://upnppictures";
            }
        }
#endif

        // if error, return now, the device could have gone away
        // this will make us go back to the sources list
        PLT_MediaObjectListReference list;
        NPT_Result res = upnp->m_MediaBrowser->BrowseSync(device, object_id, list);
        if (NPT_FAILED(res)) goto failure;

        // empty list is ok
        if (list.IsNull()) goto cleanup;

        PLT_MediaObjectList::Iterator entry = list->GetFirstItem();
        while (entry) {
            // disregard items with wrong class/type
            if( (!video && (*entry)->m_ObjectClass.type.CompareN("object.item.videoitem", 21,true) == 0)
             || (!audio && (*entry)->m_ObjectClass.type.CompareN("object.item.audioitem", 21,true) == 0)
             || (!image && (*entry)->m_ObjectClass.type.CompareN("object.item.imageitem", 21,true) == 0) )
            {
                ++entry;
                continue;
            }

            // never show empty containers in media views
            if((*entry)->IsContainer()) {
                if( (audio || video || image)
                 && ((PLT_MediaContainer*)(*entry))->m_ChildrenCount == 0) {
                    ++entry;
                    continue;
                }
            }


            // keep count of classes
            classes[(*entry)->m_ObjectClass.type]++;
            CFileItemPtr pItem = BuildObject(*entry);
            if(!pItem) {
                ++entry;
                continue;
            }

            CStdString id = (char*) (*entry)->m_ObjectID;
            CURL::Encode(id);
            URIUtils::AddSlashAtEnd(id);
            pItem->SetPath(CStdString((const char*) "upnp://" + uuid + "/" + id.c_str()));

            items.Add(pItem);

            ++entry;
        }

        NPT_String max_string = "";
        int        max_count  = 0;
        for(std::map<NPT_String, int>::iterator it = classes.begin(); it != classes.end(); it++)
        {
          if(it->second > max_count)
          {
            max_string = it->first;
            max_count  = it->second;
          }
        }
        std::string content = GetContentMapping(max_string);
        items.SetContent(content);
        if (content == "unknown")
        {
          items.AddSortMethod(SORT_METHOD_UNSORTED, 571, LABEL_MASKS("%L", "%I", "%L", ""));
          items.AddSortMethod(SORT_METHOD_LABEL_IGNORE_FOLDERS, 551, LABEL_MASKS("%L", "%I", "%L", ""));
          items.AddSortMethod(SORT_METHOD_SIZE, 553, LABEL_MASKS("%L", "%I", "%L", "%I"));
          items.AddSortMethod(SORT_METHOD_DATE, 552, LABEL_MASKS("%L", "%J", "%L", "%J"));
        }
    }

cleanup:
    return true;

failure:
    return false;
}
Example #16
0
bool parseRangeHeader(const NPT_String& text, NPT_UInt64 totalLength, NPT_UInt64& offset, NPT_UInt64& length)
{
	if (!text.StartsWith("bytes=")) {
		return false;
	}

	if (text.Find(',') >= 0) {
		// multiple ranges, currently unsupported
		return false;
	}

	int sep = text.Find('-', 6);
	if (sep < 0) {
		return false;
	}

	NPT_String p1 = text.SubString(6, sep - 6);
	NPT_String p2 = text.SubString(sep + 1);
	NPT_UInt64 v1, v2;

	if (p1.IsEmpty()) {
		if (p2.IsEmpty()) {
			return false;
		} else {
			if (NPT_FAILED(NPT_ParseInteger64(p2, v2))) {
				return false;
			}
			if (v2 <= totalLength) {
				offset = totalLength - v2;
				length = v2;
			} else {
				offset = 0;
				length = totalLength;
			}
		}
	} else {
		if (NPT_FAILED(NPT_ParseInteger64(p1, v1))) {
			return false;
		}
		if (v1 >= totalLength) {
			return false;
		}
		if (p2.IsEmpty()) {
			offset = v1;
			length = totalLength - offset;
		} else {
			if (NPT_FAILED(NPT_ParseInteger64(p2, v2))) {
				return false;
			}
			if (v2 >= totalLength) {
				return false;
			}
			if (v2 < v1) {
				return false;
			}
			offset = v1;
			length = v2 - v1 + 1;
		}
	}

	return true;
}
/*----------------------------------------------------------------------
|   CUPnPDirectory::GetDirectory
+---------------------------------------------------------------------*/
bool
CUPnPDirectory::GetDirectory(const CStdString& strPath, CFileItemList &items)
{
    CGUIDialogProgress* dlgProgress = NULL;

    CUPnP* upnp = CUPnP::GetInstance();

    /* upnp should never be cached, it has internal cache */
    items.SetCacheToDisc(CFileItemList::CACHE_NEVER);

    // start client if it hasn't been done yet
    bool client_started = upnp->IsClientStarted();
    upnp->StartClient();

    // We accept upnp://devuuid/[item_id/]
    NPT_String path = strPath.c_str();
    if (!path.StartsWith("upnp://", true)) {
        return false;
    }

    if (path.Compare("upnp://", true) == 0) {
        // root -> get list of devices
        const NPT_Lock<PLT_DeviceMap>& devices = upnp->m_MediaBrowser->GetMediaServers();
        const NPT_List<PLT_DeviceMapEntry*>& entries = devices.GetEntries();
        NPT_List<PLT_DeviceMapEntry*>::Iterator entry = entries.GetFirstItem();
        while (entry) {
            PLT_DeviceDataReference device = (*entry)->GetValue();
            NPT_String name = device->GetFriendlyName();
            NPT_String uuid = (*entry)->GetKey();

            CFileItemPtr pItem(new CFileItem((const char*)name));
            pItem->m_strPath = (const char*) "upnp://" + uuid + "/";
            pItem->m_bIsFolder = true;
            pItem->SetThumbnailImage((const char*)device->GetIconUrl("image/jpeg"));

            items.Add(pItem);

            ++entry;
        }
    } else {
        if (!path.EndsWith("/")) path += "/";

        // look for nextslash
        int next_slash = path.Find('/', 7);

        NPT_String uuid = (next_slash==-1)?path.SubString(7):path.SubString(7, next_slash-7);
        NPT_String object_id = (next_slash==-1)?"":path.SubString(next_slash+1);
        object_id.TrimRight("/");
        if (object_id.GetLength()) {
            CStdString tmp = (char*) object_id;
            CUtil::UrlDecode(tmp);
            object_id = tmp;
        }

        // look for device in our list
        // (and wait for it to respond for 5 secs if we're just starting upnp client)
        NPT_TimeStamp watchdog;
        NPT_System::GetCurrentTimeStamp(watchdog);
        watchdog += 5.f;

        PLT_DeviceDataReference* device;
        for (;;) {
            const NPT_Lock<PLT_DeviceMap>& devices = upnp->m_MediaBrowser->GetMediaServers();
            if (NPT_SUCCEEDED(devices.Get(uuid, device)) && device)
                break;

            // fail right away if device not found and upnp client was already running
            if (client_started)
                goto failure;

            // otherwise check if we've waited long enough without success
            NPT_TimeStamp now;
            NPT_System::GetCurrentTimeStamp(now);
            if (now > watchdog)
                goto failure;

            // sleep a bit and try again
            NPT_System::Sleep(NPT_TimeInterval(1, 0));
        }

        // issue a browse request with object_id
        // if object_id is empty use "0" for root
        object_id = object_id.IsEmpty()?"0":object_id;

        // just a guess as to what types of files we want
        bool video = true;
        bool audio = true;
        bool image = true;
        m_strFileMask.TrimLeft("/");
        if (!m_strFileMask.IsEmpty()) {
            video = m_strFileMask.Find(".wmv") >= 0;
            audio = m_strFileMask.Find(".wma") >= 0;
            image = m_strFileMask.Find(".jpg") >= 0;
        }

        // special case for Windows Media Connect and WMP11 when looking for root
        // We can target which root subfolder we want based on directory mask
        if (object_id == "0" && (((*device)->GetFriendlyName().Find("Windows Media Connect", 0, true) >= 0) ||
                                 ((*device)->m_ModelName == "Windows Media Player Sharing"))) {

            // look for a specific type to differentiate which folder we want
            if (audio && !video && !image) {
                // music
                object_id = "1";
            } else if (!audio && video && !image) {
                // video
                object_id = "2";
            } else if (!audio && !video && image) {
                // pictures
                object_id = "3";
            }
        }

#ifdef DISABLE_SPECIALCASE
        // same thing but special case for XBMC
        if (object_id == "0" && (((*device)->m_ModelName.Find("XBMC", 0, true) >= 0) ||
                                 ((*device)->m_ModelName.Find("Xbox Media Center", 0, true) >= 0))) {
            // look for a specific type to differentiate which folder we want
            if (audio && !video && !image) {
                // music
                object_id = "virtualpath://upnpmusic";
            } else if (!audio && video && !image) {
                // video
                object_id = "virtualpath://upnpvideo";
            } else if (!audio && !video && image) {
                // pictures
                object_id = "virtualpath://upnppictures";
            }
        }
#endif
        // bring up dialog if object is not cached
        if (!upnp->m_MediaBrowser->IsCached(uuid, object_id)) {
            dlgProgress = (CGUIDialogProgress*)m_gWindowManager.GetWindow(WINDOW_DIALOG_PROGRESS);
            if (dlgProgress) {
                dlgProgress->ShowProgressBar(false);
                dlgProgress->SetCanCancel(false);
                dlgProgress->SetHeading(20334);
                dlgProgress->SetLine(0, 194);
                dlgProgress->SetLine(1, "");
                dlgProgress->SetLine(2, "");
                dlgProgress->StartModal();
            }
        }

        // if error, return now, the device could have gone away
        // this will make us go back to the sources list
        PLT_MediaObjectListReference list;
        NPT_Result res = upnp->m_MediaBrowser->Browse(*device, object_id, list);
        if (NPT_FAILED(res)) goto failure;

        // empty list is ok
        if (list.IsNull()) goto cleanup;

        PLT_MediaObjectList::Iterator entry = list->GetFirstItem();
        while (entry) {
            // disregard items with wrong class/type
            if( (!video && (*entry)->m_ObjectClass.type.CompareN("object.item.videoitem", 21,true) == 0)
             || (!audio && (*entry)->m_ObjectClass.type.CompareN("object.item.audioitem", 21,true) == 0)
             || (!image && (*entry)->m_ObjectClass.type.CompareN("object.item.imageitem", 21,true) == 0) )
            {
                ++entry;
                continue;
            }

            // never show empty containers in media views
            if((*entry)->IsContainer()) {
                if( (audio || video || image)
                 && ((PLT_MediaContainer*)(*entry))->m_ChildrenCount == 0) {
                    ++entry;
                    continue;
                }
            }

            CFileItemPtr pItem(new CFileItem((const char*)(*entry)->m_Title));
            pItem->SetLabelPreformated(true);
            pItem->m_bIsFolder = (*entry)->IsContainer();

            // if it's a container, format a string as upnp://uuid/object_id
            if (pItem->m_bIsFolder) {
                CStdString id = (char*) (*entry)->m_ObjectID;
                CUtil::URLEncode(id);
                pItem->m_strPath = (const char*) "upnp://" + uuid + "/" + id.c_str() + "/";
            } else {
                if ((*entry)->m_Resources.GetItemCount()) {
                    PLT_MediaItemResource& resource = (*entry)->m_Resources[0];

                    // look for a resource with "xbmc-get" protocol
                    // if we can't find one, keep the first resource
                    NPT_ContainerFind((*entry)->m_Resources,
                                      CProtocolFinder("xbmc-get"),
                                      resource);

                    CLog::Log(LOGDEBUG, "CUPnPDirectory::GetDirectory - resource protocol info '%s'", (const char*)(resource.m_ProtocolInfo));

                    // if it's an item, path is the first url to the item
                    // we hope the server made the first one reachable for us
                    // (it could be a format we dont know how to play however)
                    pItem->m_strPath = (const char*) resource.m_Uri;

                    // set metadata
                    if (resource.m_Size > 0) {
                        pItem->m_dwSize  = resource.m_Size;
                    }

                    // set a general content type
                    CStdString type = (const char*)(*entry)->m_ObjectClass.type.Left(21);
                    if     (type.Equals("object.item.videoitem"))
                        pItem->SetContentType("video/octet-stream");
                    else if(type.Equals("object.item.audioitem"))
                        pItem->SetContentType("audio/octet-stream");
                    else if(type.Equals("object.item.imageitem"))
                        pItem->SetContentType("image/octet-stream");

                    // look for content type in protocol info
                    if (resource.m_ProtocolInfo.GetLength()) {
                        char proto[1024];
                        char dummy1[1024];
                        char ct[1204];
                        char dummy2[1024];
                        int fields = sscanf(resource.m_ProtocolInfo, "%[^:]:%[^:]:%[^:]:%[^:]", proto, dummy1, ct, dummy2);
                        if (fields == 4) {
                            if (strcmp(ct, "application/octet-stream") != 0) {
                                pItem->SetContentType(ct);
                            }
                        } else {
                            CLog::Log(LOGERROR, "CUPnPDirectory::GetDirectory - invalid protocol info '%s'", (const char*)(resource.m_ProtocolInfo));
                        }
                    }

                    // look for date?
                    if((*entry)->m_Description.date.GetLength()) {
                        SYSTEMTIME time = {};
                        sscanf((*entry)->m_Description.date, "%hu-%hu-%huT%hu:%hu:%hu",
                               &time.wYear, &time.wMonth, &time.wDay, &time.wHour, &time.wMinute, &time.wSecond);
                        pItem->m_dateTime = time;
                    }

                    // look for metadata
                    if( (*entry)->m_ObjectClass.type.CompareN("object.item.videoitem", 21,true) == 0 ) {
                        pItem->SetLabelPreformated(false);
                        CUPnP::PopulateTagFromObject(*pItem->GetVideoInfoTag(), *(*entry), &resource);
                    } else if( (*entry)->m_ObjectClass.type.CompareN("object.item.audioitem", 21,true) == 0 ) {
                        pItem->SetLabelPreformated(false);
                        CUPnP::PopulateTagFromObject(*pItem->GetMusicInfoTag(), *(*entry), &resource);
                    } else if( (*entry)->m_ObjectClass.type.CompareN("object.item.imageitem", 21,true) == 0 ) {
                      //CPictureInfoTag* tag = pItem->GetPictureInfoTag();
                    }
                }
            }

            // if there is a thumbnail available set it here
            if((*entry)->m_ExtraInfo.album_art_uri.GetLength())
                pItem->SetThumbnailImage((const char*) (*entry)->m_ExtraInfo.album_art_uri);
            else if((*entry)->m_Description.icon_uri.GetLength())
                pItem->SetThumbnailImage((const char*) (*entry)->m_Description.icon_uri);

            items.Add(pItem);

            ++entry;
        }
    }

cleanup:
    if (dlgProgress) dlgProgress->Close();
    return true;

failure:
    if (dlgProgress) dlgProgress->Close();
    return false;
}
Example #18
0
/*----------------------------------------------------------------------
|   PLT_Didl::ConvertFilterToMask
+---------------------------------------------------------------------*/
NPT_UInt64
PLT_Didl::ConvertFilterToMask(const NPT_String& filter)
{
    // easy out
    if (filter.GetLength() == 0) return PLT_FILTER_MASK_ALL;
    
    // a filter string is a comma delimited set of fields identifying
    // a given DIDL property (or set of properties).  
    // These fields are or start with: upnp:, @, [email protected], res, dc:, [email protected]

    NPT_UInt64  mask = 0;
    const char* s = filter;
    int         i = 0;

    while (s[i] != '\0') {
        int next_comma = filter.Find(',', i);
        int len = ((next_comma < 0)?(int)filter.GetLength():next_comma)-i;

        if (NPT_String::CompareN(s+i, "*", 1) == 0) {
            // return now, there's no point in parsing the rest
            return PLT_FILTER_MASK_ALL;
        }
        
        // title is required, so we return a non empty mask
        mask |= PLT_FILTER_MASK_TITLE;

        if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_TITLE, len, true) == 0) {
            mask |= PLT_FILTER_MASK_TITLE;
        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_REFID, len, true) == 0) {
            mask |= PLT_FILTER_MASK_REFID;
        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_CREATOR, len, true) == 0) {
            mask |= PLT_FILTER_MASK_CREATOR;
        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_ARTIST, len, true) == 0) {
            mask |= PLT_FILTER_MASK_ARTIST;
        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_ACTOR, len, true) == 0) {
            mask |= PLT_FILTER_MASK_ACTOR;
        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_DIRECTOR, len, true) == 0) {
            mask |= PLT_FILTER_MASK_DIRECTOR;
        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_AUTHOR, len, true) == 0) {
            mask |= PLT_FILTER_MASK_AUTHOR;       
        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_DATE, len, true) == 0) {
            mask |= PLT_FILTER_MASK_DATE;
        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_ALBUM, len, true) == 0) {
            mask |= PLT_FILTER_MASK_ALBUM;
        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_GENRE, len, true) == 0) {
            mask |= PLT_FILTER_MASK_GENRE;
        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_ALBUMARTURI, len, true) == 0 ||
                   NPT_String::CompareN(s+i, PLT_FILTER_FIELD_ALBUMARTURI_DLNAPROFILEID, len, true) == 0) {
            mask |= PLT_FILTER_MASK_ALBUMARTURI;
        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_DESCRIPTION, len, true) == 0) {
            mask |= PLT_FILTER_MASK_DESCRIPTION;
        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_LONGDESCRIPTION, len, true) == 0) {
            mask |= PLT_FILTER_MASK_LONGDESCRIPTION;
        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_ORIGINALTRACK, len, true) == 0) {
            mask |= PLT_FILTER_MASK_ORIGINALTRACK;
        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_LASTPOSITION, len, true) == 0) {
            mask |= PLT_FILTER_MASK_LASTPOSITION;
        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_LASTPLAYBACK, len, true) == 0) {
            mask |= PLT_FILTER_MASK_LASTPLAYBACK;
        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_PLAYCOUNT, len, true) == 0) {
            mask |= PLT_FILTER_MASK_PLAYCOUNT;
        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_SEARCHABLE, len, true) == 0) {
            mask |= PLT_FILTER_MASK_SEARCHABLE;
        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_SEARCHCLASS, len, true) == 0) {
            mask |= PLT_FILTER_MASK_SEARCHCLASS;
        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_CONTAINER_SEARCHABLE, len, true) == 0) {
            mask |= PLT_FILTER_MASK_SEARCHABLE;       
        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_CHILDCOUNT, len, true) == 0) {
            mask |= PLT_FILTER_MASK_CHILDCOUNT;
        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_CONTAINER_CHILDCOUNT, len, true) == 0) {
            mask |= PLT_FILTER_MASK_CHILDCOUNT;
        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_PROGRAMTITLE, len, true) == 0) {
            mask |= PLT_FILTER_MASK_PROGRAMTITLE;
        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_SERIESTITLE, len, true) == 0) {
            mask |= PLT_FILTER_MASK_SERIESTITLE;
        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_EPISODE, len, true) == 0) {
            mask |= PLT_FILTER_MASK_EPISODE;
        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_RATING, len, true) == 0) {
            mask |= PLT_FILTER_MASK_RATING;
        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_PUBLISHER, len, true) == 0) {
            mask |= PLT_FILTER_MASK_PUBLISHER;
        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_RES, len, true) == 0) {
            mask |= PLT_FILTER_MASK_RES;
        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_RES_DURATION, len, true) == 0 ||
				   NPT_String::CompareN(s+i, PLT_FILTER_FIELD_RES_DURATION_SHORT, len, true) == 0) {
            mask |= PLT_FILTER_MASK_RES | PLT_FILTER_MASK_RES_DURATION;
        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_RES_SIZE, len, true) == 0) {
            mask |= PLT_FILTER_MASK_RES | PLT_FILTER_MASK_RES_SIZE;
        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_RES_PROTECTION, len, true) == 0) {
            mask |= PLT_FILTER_MASK_RES | PLT_FILTER_MASK_RES_PROTECTION;
        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_RES_RESOLUTION, len, true) == 0) {
            mask |= PLT_FILTER_MASK_RES | PLT_FILTER_MASK_RES_RESOLUTION;
        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_RES_BITRATE, len, true) == 0) {
            mask |= PLT_FILTER_MASK_RES | PLT_FILTER_MASK_RES_BITRATE;
        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_RES_BITSPERSAMPLE, len, true) == 0) {
            mask |= PLT_FILTER_MASK_RES | PLT_FILTER_MASK_RES_BITSPERSAMPLE;
		} else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_RES_NRAUDIOCHANNELS, len, true) == 0) {
            mask |= PLT_FILTER_MASK_RES | PLT_FILTER_MASK_RES_NRAUDIOCHANNELS;
		} else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_RES_SAMPLEFREQUENCY, len, true) == 0) {
            mask |= PLT_FILTER_MASK_RES | PLT_FILTER_MASK_RES_SAMPLEFREQUENCY;
		} else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_EPISODE_COUNT, len, true) == 0) {
            mask |= PLT_FILTER_MASK_EPISODE_COUNT;
        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_EPISODE_SEASON, len, true) == 0) {
            mask |= PLT_FILTER_MASK_EPISODE_SEASON;
        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_XBMC_DATEADDED, len, true) == 0) {
            mask |= PLT_FILTER_MASK_XBMC_DATEADDED;
        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_XBMC_RATING, len, true) == 0) {
            mask |= PLT_FILTER_MASK_XBMC_RATING;
        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_XBMC_VOTES, len, true) == 0) {
            mask |= PLT_FILTER_MASK_XBMC_VOTES;
        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_XBMC_ARTWORK, len, true) == 0) {
            mask |= PLT_FILTER_MASK_XBMC_ARTWORK;
        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_XBMC_UNIQUE_IDENTIFIER, len, true) == 0) {
            mask |= PLT_FILTER_MASK_XBMC_UNIQUE_IDENTIFIER;
        }

        if (next_comma < 0) {
            return mask;
        }

        i = next_comma + 1;
    }

    return mask;
}