* Introduce a new strcatf() function to help simplify some areas of the code.
This commit is contained in:
373
upnpsoap.c
373
upnpsoap.c
@ -61,13 +61,12 @@
|
||||
|
||||
#include "config.h"
|
||||
#include "upnpglobalvars.h"
|
||||
#include "utils.h"
|
||||
#include "upnphttp.h"
|
||||
#include "upnpsoap.h"
|
||||
#include "upnpreplyparse.h"
|
||||
#include "getifaddr.h"
|
||||
|
||||
#include "scanner.h"
|
||||
#include "utils.h"
|
||||
#include "sql.h"
|
||||
#include "log.h"
|
||||
|
||||
@ -555,17 +554,13 @@ inline static void
|
||||
add_resized_res(int srcw, int srch, int reqw, int reqh, char *dlna_pn,
|
||||
char *detailID, struct Response *passed_args)
|
||||
{
|
||||
int ret;
|
||||
int dstw = reqw;
|
||||
int dsth = reqh;
|
||||
char str_buf[256];
|
||||
|
||||
if( passed_args->flags & FLAG_NO_RESIZE )
|
||||
return;
|
||||
|
||||
ret = sprintf(str_buf, "<res ");
|
||||
memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1);
|
||||
passed_args->size += ret;
|
||||
strcatf(passed_args->str, "<res ");
|
||||
if( passed_args->filter & FILTER_RES_RESOLUTION )
|
||||
{
|
||||
dstw = reqw;
|
||||
@ -574,17 +569,12 @@ add_resized_res(int srcw, int srch, int reqw, int reqh, char *dlna_pn,
|
||||
dsth = reqh;
|
||||
dstw = (((reqh<<10)/srch) * srcw>>10);
|
||||
}
|
||||
ret = sprintf(str_buf, "resolution=\"%dx%d\" ", dstw, dsth);
|
||||
memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1);
|
||||
passed_args->size += ret;
|
||||
strcatf(passed_args->str, "resolution=\"%dx%d\" ", dstw, dsth);
|
||||
}
|
||||
ret = sprintf(str_buf, "protocolInfo=\"http-get:*:image/jpeg:DLNA.ORG_PN=%s;DLNA.ORG_CI=1\">"
|
||||
"http://%s:%d/Resized/%s.jpg?width=%d,height=%d"
|
||||
"</res>",
|
||||
dlna_pn, lan_addr[0].str, runtime_vars.port,
|
||||
detailID, dstw, dsth);
|
||||
memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1);
|
||||
passed_args->size += ret;
|
||||
strcatf(passed_args->str, "protocolInfo=\"http-get:*:image/jpeg:DLNA.ORG_PN=%s;DLNA.ORG_CI=1\">"
|
||||
"http://%s:%d/Resized/%s.jpg?width=%d,height=%d"
|
||||
"</res>",
|
||||
dlna_pn, lan_addr[0].str, runtime_vars.port, detailID, dstw, dsth);
|
||||
}
|
||||
|
||||
inline static void
|
||||
@ -592,48 +582,30 @@ add_res(char *size, char *duration, char *bitrate, char *sampleFrequency,
|
||||
char *nrAudioChannels, char *resolution, char *dlna_pn, char *mime,
|
||||
char *detailID, char *ext, struct Response *passed_args)
|
||||
{
|
||||
int ret;
|
||||
char str_buf[256];
|
||||
|
||||
ret = sprintf(str_buf, "<res ");
|
||||
memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1);
|
||||
passed_args->size += ret;
|
||||
strcatf(passed_args->str, "<res ");
|
||||
if( size && (passed_args->filter & FILTER_RES_SIZE) ) {
|
||||
ret = sprintf(str_buf, "size=\"%s\" ", size);
|
||||
memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1);
|
||||
passed_args->size += ret;
|
||||
strcatf(passed_args->str, "size=\"%s\" ", size);
|
||||
}
|
||||
if( duration && (passed_args->filter & FILTER_RES_DURATION) ) {
|
||||
ret = sprintf(str_buf, "duration=\"%s\" ", duration);
|
||||
memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1);
|
||||
passed_args->size += ret;
|
||||
strcatf(passed_args->str, "duration=\"%s\" ", duration);
|
||||
}
|
||||
if( bitrate && (passed_args->filter & FILTER_RES_BITRATE) ) {
|
||||
ret = sprintf(str_buf, "bitrate=\"%s\" ", bitrate);
|
||||
memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1);
|
||||
passed_args->size += ret;
|
||||
strcatf(passed_args->str, "bitrate=\"%s\" ", bitrate);
|
||||
}
|
||||
if( sampleFrequency && (passed_args->filter & FILTER_RES_SAMPLEFREQUENCY) ) {
|
||||
ret = sprintf(str_buf, "sampleFrequency=\"%s\" ", sampleFrequency);
|
||||
memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1);
|
||||
passed_args->size += ret;
|
||||
strcatf(passed_args->str, "sampleFrequency=\"%s\" ", sampleFrequency);
|
||||
}
|
||||
if( nrAudioChannels && (passed_args->filter & FILTER_RES_NRAUDIOCHANNELS) ) {
|
||||
ret = sprintf(str_buf, "nrAudioChannels=\"%s\" ", nrAudioChannels);
|
||||
memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1);
|
||||
passed_args->size += ret;
|
||||
strcatf(passed_args->str, "nrAudioChannels=\"%s\" ", nrAudioChannels);
|
||||
}
|
||||
if( resolution && (passed_args->filter & FILTER_RES_RESOLUTION) ) {
|
||||
ret = sprintf(str_buf, "resolution=\"%s\" ", resolution);
|
||||
memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1);
|
||||
passed_args->size += ret;
|
||||
strcatf(passed_args->str, "resolution=\"%s\" ", resolution);
|
||||
}
|
||||
ret = snprintf(str_buf, sizeof(str_buf), "protocolInfo=\"http-get:*:%s:%s\">"
|
||||
"http://%s:%d/MediaItems/%s.%s"
|
||||
"</res>",
|
||||
mime, dlna_pn, lan_addr[0].str, runtime_vars.port, detailID, ext);
|
||||
memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1);
|
||||
passed_args->size += ret;
|
||||
strcatf(passed_args->str, "protocolInfo=\"http-get:*:%s:%s\">"
|
||||
"http://%s:%d/MediaItems/%s.%s"
|
||||
"</res>",
|
||||
mime, dlna_pn, lan_addr[0].str,
|
||||
runtime_vars.port, detailID, ext);
|
||||
}
|
||||
|
||||
#define SELECT_COLUMNS "SELECT o.OBJECT_ID, o.PARENT_ID, o.REF_ID, o.DETAIL_ID, o.CLASS," \
|
||||
@ -651,21 +623,22 @@ callback(void *args, int argc, char **argv, char **azColName)
|
||||
*tn = argv[18], *creator = argv[19], *dlna_pn = argv[20], *mime = argv[21], *album_art = argv[22];
|
||||
char dlna_buf[96];
|
||||
char ext[5];
|
||||
char str_buf[512];
|
||||
struct string_s *str = passed_args->str;
|
||||
int ret = 0;
|
||||
|
||||
/* Make sure we have at least 4KB left of allocated memory to finish the response. */
|
||||
if( passed_args->size > (passed_args->alloced - 4096) )
|
||||
/* Make sure we have at least 8KB left of allocated memory to finish the response. */
|
||||
if( str->off > (str->size - 8192) )
|
||||
{
|
||||
#if MAX_RESPONSE_SIZE > 0
|
||||
if( (passed_args->alloced+1048576) <= MAX_RESPONSE_SIZE )
|
||||
if( (str->size+DEFAULT_RESP_SIZE) <= MAX_RESPONSE_SIZE )
|
||||
{
|
||||
#endif
|
||||
passed_args->resp = realloc(passed_args->resp, (passed_args->alloced+1048576));
|
||||
if( passed_args->resp )
|
||||
str->data = realloc(str->data, (str->off+DEFAULT_RESP_SIZE));
|
||||
if( str->data )
|
||||
{
|
||||
passed_args->alloced += 1048576;
|
||||
DPRINTF(E_DEBUG, L_HTTP, "HUGE RESPONSE ALERT: UPnP SOAP response had to be enlarged to %d. [%d results so far]\n", passed_args->alloced, passed_args->returned);
|
||||
str->size += DEFAULT_RESP_SIZE;
|
||||
DPRINTF(E_DEBUG, L_HTTP, "UPnP SOAP response enlarged to %d. [%d results so far]\n",
|
||||
str->size, passed_args->returned);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -739,120 +712,85 @@ callback(void *args, int argc, char **argv, char **azColName)
|
||||
}
|
||||
}
|
||||
|
||||
ret = snprintf(str_buf, 512, "<item id=\"%s\" parentID=\"%s\" restricted=\"1\"", id, parent);
|
||||
memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1);
|
||||
passed_args->size += ret;
|
||||
ret = strcatf(str, "<item id=\"%s\" parentID=\"%s\" restricted=\"1\"", id, parent);
|
||||
if( refID && (passed_args->filter & FILTER_REFID) ) {
|
||||
ret = sprintf(str_buf, " refID=\"%s\"", refID);
|
||||
memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1);
|
||||
passed_args->size += ret;
|
||||
ret = strcatf(str, " refID=\"%s\"", refID);
|
||||
}
|
||||
ret = snprintf(str_buf, 512, ">"
|
||||
"<dc:title>%s</dc:title>"
|
||||
"<upnp:class>object.%s</upnp:class>",
|
||||
title, class);
|
||||
memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1);
|
||||
passed_args->size += ret;
|
||||
ret = strcatf(str, ">"
|
||||
"<dc:title>%s</dc:title>"
|
||||
"<upnp:class>object.%s</upnp:class>",
|
||||
title, class);
|
||||
if( comment && (passed_args->filter & FILTER_DC_DESCRIPTION) ) {
|
||||
ret = snprintf(str_buf, 512, "<dc:description>%.384s</dc:description>", comment);
|
||||
memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1);
|
||||
passed_args->size += ret;
|
||||
ret = strcatf(str, "<dc:description>%.384s</dc:description>", comment);
|
||||
}
|
||||
if( creator && (passed_args->filter & FILTER_DC_CREATOR) ) {
|
||||
ret = snprintf(str_buf, 512, "<dc:creator>%s</dc:creator>", creator);
|
||||
memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1);
|
||||
passed_args->size += ret;
|
||||
ret = strcatf(str, "<dc:creator>%s</dc:creator>", creator);
|
||||
}
|
||||
if( date && (passed_args->filter & FILTER_DC_DATE) ) {
|
||||
ret = snprintf(str_buf, 512, "<dc:date>%s</dc:date>", date);
|
||||
memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1);
|
||||
passed_args->size += ret;
|
||||
ret = strcatf(str, "<dc:date>%s</dc:date>", date);
|
||||
}
|
||||
if( artist ) {
|
||||
if( (*mime == 'v') && (passed_args->filter & FILTER_UPNP_ACTOR) ) {
|
||||
ret = snprintf(str_buf, 512, "<upnp:actor>%s</upnp:actor>", artist);
|
||||
memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1);
|
||||
passed_args->size += ret;
|
||||
ret = strcatf(str, "<upnp:actor>%s</upnp:actor>", artist);
|
||||
}
|
||||
if( passed_args->filter & FILTER_UPNP_ARTIST ) {
|
||||
ret = snprintf(str_buf, 512, "<upnp:artist>%s</upnp:artist>", artist);
|
||||
memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1);
|
||||
passed_args->size += ret;
|
||||
ret = strcatf(str, "<upnp:artist>%s</upnp:artist>", artist);
|
||||
}
|
||||
}
|
||||
if( album && (passed_args->filter & FILTER_UPNP_ALBUM) ) {
|
||||
ret = snprintf(str_buf, 512, "<upnp:album>%s</upnp:album>", album);
|
||||
memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1);
|
||||
passed_args->size += ret;
|
||||
ret = strcatf(str, "<upnp:album>%s</upnp:album>", album);
|
||||
}
|
||||
if( genre && (passed_args->filter & FILTER_UPNP_GENRE) ) {
|
||||
ret = snprintf(str_buf, 512, "<upnp:genre>%s</upnp:genre>", genre);
|
||||
memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1);
|
||||
passed_args->size += ret;
|
||||
ret = strcatf(str, "<upnp:genre>%s</upnp:genre>", genre);
|
||||
}
|
||||
if( strncmp(id, MUSIC_PLIST_ID, strlen(MUSIC_PLIST_ID)) == 0 ) {
|
||||
track = strrchr(id, '$')+1;
|
||||
}
|
||||
if( track && atoi(track) && (passed_args->filter & FILTER_UPNP_ORIGINALTRACKNUMBER) ) {
|
||||
ret = sprintf(str_buf, "<upnp:originalTrackNumber>%s</upnp:originalTrackNumber>", track);
|
||||
memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1);
|
||||
passed_args->size += ret;
|
||||
ret = strcatf(str, "<upnp:originalTrackNumber>%s</upnp:originalTrackNumber>", track);
|
||||
}
|
||||
if( album_art && atoi(album_art) )
|
||||
{
|
||||
/* Video and audio album art is handled differently */
|
||||
if( *mime == 'v' && (passed_args->filter & FILTER_RES) && !(passed_args->flags & FLAG_MS_PFS) ) {
|
||||
ret = sprintf(str_buf, "<res protocolInfo=\"http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN\">"
|
||||
"http://%s:%d/AlbumArt/%s-%s.jpg"
|
||||
"</res>",
|
||||
lan_addr[0].str, runtime_vars.port, album_art, detailID);
|
||||
memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1);
|
||||
passed_args->size += ret;
|
||||
ret = strcatf(str, "<res protocolInfo=\"http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN\">"
|
||||
"http://%s:%d/AlbumArt/%s-%s.jpg"
|
||||
"</res>",
|
||||
lan_addr[0].str, runtime_vars.port, album_art, detailID);
|
||||
} else if( passed_args->filter & FILTER_UPNP_ALBUMARTURI ) {
|
||||
ret = sprintf(str_buf, "<upnp:albumArtURI");
|
||||
memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1);
|
||||
passed_args->size += ret;
|
||||
ret = strcatf(str, "<upnp:albumArtURI");
|
||||
if( passed_args->filter & FILTER_UPNP_ALBUMARTURI_DLNA_PROFILEID ) {
|
||||
ret = sprintf(str_buf, " dlna:profileID=\"%s\" xmlns:dlna=\"urn:schemas-dlna-org:metadata-1-0/\"", "JPEG_TN");
|
||||
memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1);
|
||||
passed_args->size += ret;
|
||||
ret = strcatf(str, " dlna:profileID=\"JPEG_TN\" xmlns:dlna=\"urn:schemas-dlna-org:metadata-1-0/\"");
|
||||
}
|
||||
ret = sprintf(str_buf, ">http://%s:%d/AlbumArt/%s-%s.jpg</upnp:albumArtURI>",
|
||||
lan_addr[0].str, runtime_vars.port, album_art, detailID);
|
||||
memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1);
|
||||
passed_args->size += ret;
|
||||
ret = strcatf(str, ">http://%s:%d/AlbumArt/%s-%s.jpg</upnp:albumArtURI>",
|
||||
lan_addr[0].str, runtime_vars.port, album_art, detailID);
|
||||
}
|
||||
}
|
||||
#ifdef PFS_HACK
|
||||
if( (passed_args->flags & FLAG_MS_PFS) && *mime == 'i' ) {
|
||||
ret = snprintf(str_buf, 512, "<upnp:album>%s</upnp:album>", "[No Keywords]");
|
||||
memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1);
|
||||
passed_args->size += ret;
|
||||
ret = strcatf(str, "<upnp:album>%s</upnp:album>", "[No Keywords]");
|
||||
|
||||
if( tn && atoi(tn) ) {
|
||||
ret = snprintf(str_buf, 512, "<upnp:albumArtURI>"
|
||||
"http://%s:%d/Thumbnails/%s.jpg"
|
||||
"</upnp:albumArtURI>",
|
||||
lan_addr[0].str, runtime_vars.port, detailID);
|
||||
ret = strcatf(str, "<upnp:albumArtURI>"
|
||||
"http://%s:%d/Thumbnails/%s.jpg"
|
||||
"</upnp:albumArtURI>",
|
||||
lan_addr[0].str, runtime_vars.port, detailID);
|
||||
} else {
|
||||
ret = snprintf(str_buf, 512, "<upnp:albumArtURI>"
|
||||
"http://%s:%d/Resized/%s.jpg?width=160,height=160"
|
||||
"</upnp:albumArtURI>",
|
||||
lan_addr[0].str, runtime_vars.port, detailID);
|
||||
ret = strcatf(str, "<upnp:albumArtURI>"
|
||||
"http://%s:%d/Resized/%s.jpg?width=160,height=160"
|
||||
"</upnp:albumArtURI>",
|
||||
lan_addr[0].str, runtime_vars.port, detailID);
|
||||
}
|
||||
memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1);
|
||||
passed_args->size += ret;
|
||||
}
|
||||
#endif
|
||||
if( passed_args->filter & FILTER_RES ) {
|
||||
mime_to_ext(mime, ext);
|
||||
if( (passed_args->client == EFreeBox) && tn && atoi(tn) ) {
|
||||
ret = sprintf(str_buf, "<res protocolInfo=\"http-get:*:%s:%s\">"
|
||||
"http://%s:%d/Thumbnails/%s.jpg"
|
||||
"</res>",
|
||||
mime, "DLNA.ORG_PN=JPEG_TN", lan_addr[0].str, runtime_vars.port, detailID);
|
||||
memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1);
|
||||
passed_args->size += ret;
|
||||
ret = strcatf(str, "<res protocolInfo=\"http-get:*:%s:%s\">"
|
||||
"http://%s:%d/Thumbnails/%s.jpg"
|
||||
"</res>",
|
||||
mime, "DLNA.ORG_PN=JPEG_TN", lan_addr[0].str,
|
||||
runtime_vars.port, detailID);
|
||||
}
|
||||
add_res(size, duration, bitrate, sampleFrequency, nrAudioChannels,
|
||||
resolution, dlna_buf, mime, detailID, ext, passed_args);
|
||||
@ -868,12 +806,11 @@ callback(void *args, int argc, char **argv, char **azColName)
|
||||
}
|
||||
#endif
|
||||
if( tn && atoi(tn) ) {
|
||||
ret = sprintf(str_buf, "<res protocolInfo=\"http-get:*:%s:%s\">"
|
||||
"http://%s:%d/Thumbnails/%s.jpg"
|
||||
"</res>",
|
||||
mime, "DLNA.ORG_PN=JPEG_TN", lan_addr[0].str, runtime_vars.port, detailID);
|
||||
memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1);
|
||||
passed_args->size += ret;
|
||||
ret = strcatf(str, "<res protocolInfo=\"http-get:*:%s:%s\">"
|
||||
"http://%s:%d/Thumbnails/%s.jpg"
|
||||
"</res>",
|
||||
mime, "DLNA.ORG_PN=JPEG_TN", lan_addr[0].str,
|
||||
runtime_vars.port, detailID);
|
||||
}
|
||||
}
|
||||
else if( *mime == 'v' ) {
|
||||
@ -947,74 +884,52 @@ callback(void *args, int argc, char **argv, char **azColName)
|
||||
}
|
||||
}
|
||||
}
|
||||
ret = sprintf(str_buf, "</item>");
|
||||
ret = strcatf(str, "</item>");
|
||||
}
|
||||
else if( strncmp(class, "container", 9) == 0 )
|
||||
{
|
||||
ret = sprintf(str_buf, "<container id=\"%s\" parentID=\"%s\" restricted=\"1\" ", id, parent);
|
||||
memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1);
|
||||
passed_args->size += ret;
|
||||
ret = strcatf(str, "<container id=\"%s\" parentID=\"%s\" restricted=\"1\" ", id, parent);
|
||||
if( passed_args->filter & FILTER_CHILDCOUNT )
|
||||
{
|
||||
int children;
|
||||
ret = sql_get_int_field(db, "SELECT count(*) from OBJECTS where PARENT_ID = '%s';", id);
|
||||
children = (ret > 0) ? ret : 0;
|
||||
ret = sprintf(str_buf, "childCount=\"%d\"", children);
|
||||
memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1);
|
||||
passed_args->size += ret;
|
||||
ret = strcatf(str, "childCount=\"%d\"", children);
|
||||
}
|
||||
/* If the client calls for BrowseMetadata on root, we have to include our "upnp:searchClass"'s, unless they're filtered out */
|
||||
if( (passed_args->requested == 1) && (strcmp(id, "0") == 0) )
|
||||
{
|
||||
if( passed_args->filter & FILTER_UPNP_SEARCHCLASS )
|
||||
{
|
||||
ret = sprintf(str_buf, ">"
|
||||
"<upnp:searchClass includeDerived=\"1\">object.item.audioItem</upnp:searchClass>"
|
||||
"<upnp:searchClass includeDerived=\"1\">object.item.imageItem</upnp:searchClass>"
|
||||
"<upnp:searchClass includeDerived=\"1\">object.item.videoItem</upnp:searchClass");
|
||||
memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1);
|
||||
passed_args->size += ret;
|
||||
ret = strcatf(str, ">"
|
||||
"<upnp:searchClass includeDerived=\"1\">object.item.audioItem</upnp:searchClass>"
|
||||
"<upnp:searchClass includeDerived=\"1\">object.item.imageItem</upnp:searchClass>"
|
||||
"<upnp:searchClass includeDerived=\"1\">object.item.videoItem</upnp:searchClass");
|
||||
}
|
||||
}
|
||||
ret = snprintf(str_buf, 512, ">"
|
||||
"<dc:title>%s</dc:title>"
|
||||
"<upnp:class>object.%s</upnp:class>",
|
||||
title, class);
|
||||
memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1);
|
||||
passed_args->size += ret;
|
||||
ret = strcatf(str, ">"
|
||||
"<dc:title>%s</dc:title>"
|
||||
"<upnp:class>object.%s</upnp:class>",
|
||||
title, class);
|
||||
if( creator && (passed_args->filter & FILTER_DC_CREATOR) ) {
|
||||
ret = snprintf(str_buf, 512, "<dc:creator>%s</dc:creator>", creator);
|
||||
memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1);
|
||||
passed_args->size += ret;
|
||||
ret = strcatf(str, "<dc:creator>%s</dc:creator>", creator);
|
||||
}
|
||||
if( genre && (passed_args->filter & FILTER_UPNP_GENRE) ) {
|
||||
ret = snprintf(str_buf, 512, "<upnp:genre>%s</upnp:genre>", genre);
|
||||
memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1);
|
||||
passed_args->size += ret;
|
||||
ret = strcatf(str, "<upnp:genre>%s</upnp:genre>", genre);
|
||||
}
|
||||
if( artist && (passed_args->filter & FILTER_UPNP_ARTIST) ) {
|
||||
ret = snprintf(str_buf, 512, "<upnp:artist>%s</upnp:artist>", artist);
|
||||
memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1);
|
||||
passed_args->size += ret;
|
||||
ret = strcatf(str, "<upnp:artist>%s</upnp:artist>", artist);
|
||||
}
|
||||
if( album_art && atoi(album_art) && (passed_args->filter & FILTER_UPNP_ALBUMARTURI) ) {
|
||||
ret = sprintf(str_buf, "<upnp:albumArtURI ");
|
||||
memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1);
|
||||
passed_args->size += ret;
|
||||
ret = strcatf(str, "<upnp:albumArtURI ");
|
||||
if( passed_args->filter & FILTER_UPNP_ALBUMARTURI_DLNA_PROFILEID ) {
|
||||
ret = sprintf(str_buf, "dlna:profileID=\"%s\" xmlns:dlna=\"urn:schemas-dlna-org:metadata-1-0/\"", "JPEG_TN");
|
||||
memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1);
|
||||
passed_args->size += ret;
|
||||
ret = strcatf(str, "dlna:profileID=\"JPEG_TN\" xmlns:dlna=\"urn:schemas-dlna-org:metadata-1-0/\"");
|
||||
}
|
||||
ret = sprintf(str_buf, ">http://%s:%d/AlbumArt/%s-%s.jpg</upnp:albumArtURI>",
|
||||
lan_addr[0].str, runtime_vars.port, album_art, detailID);
|
||||
memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1);
|
||||
passed_args->size += ret;
|
||||
ret = strcatf(str, ">http://%s:%d/AlbumArt/%s-%s.jpg</upnp:albumArtURI>",
|
||||
lan_addr[0].str, runtime_vars.port, album_art, detailID);
|
||||
}
|
||||
ret = sprintf(str_buf, "</container>");
|
||||
ret = strcatf(str, "</container>");
|
||||
}
|
||||
memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1);
|
||||
passed_args->size += ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1028,16 +943,13 @@ BrowseContentDirectory(struct upnphttp * h, const char * action)
|
||||
"<Result>"
|
||||
"<DIDL-Lite"
|
||||
CONTENT_DIRECTORY_SCHEMAS;
|
||||
|
||||
char *resp = malloc(1048576);
|
||||
char str_buf[512];
|
||||
char *zErrMsg = 0;
|
||||
char *sql, *ptr;
|
||||
int ret;
|
||||
struct Response args;
|
||||
struct string_s str;
|
||||
int totalMatches;
|
||||
struct NameValueParserData data;
|
||||
*resp = '\0';
|
||||
|
||||
ParseNameValue(h->req_buf + h->req_contentoff, h->req_contentlen, &data);
|
||||
char * ObjectId = GetValueFromNameValueList(&data, "ObjectID");
|
||||
@ -1068,21 +980,19 @@ BrowseContentDirectory(struct upnphttp * h, const char * action)
|
||||
goto browse_error;
|
||||
}
|
||||
memset(&args, 0, sizeof(args));
|
||||
memset(&str, 0, sizeof(str));
|
||||
|
||||
args.alloced = 1048576;
|
||||
args.resp = resp;
|
||||
args.size = sprintf(resp, "%s", resp0);
|
||||
str.data = malloc(DEFAULT_RESP_SIZE);
|
||||
str.size = DEFAULT_RESP_SIZE;
|
||||
str.off = sprintf(str.data, "%s", resp0);
|
||||
args.str = &str;
|
||||
/* See if we need to include DLNA namespace reference */
|
||||
args.filter = set_filter_flags(Filter, h->req_client);
|
||||
if( args.filter & FILTER_DLNA_NAMESPACE )
|
||||
{
|
||||
ret = sprintf(str_buf, DLNA_NAMESPACE);
|
||||
memcpy(resp+args.size, &str_buf, ret+1);
|
||||
args.size += ret;
|
||||
ret = strcatf(&str, DLNA_NAMESPACE);
|
||||
}
|
||||
ret = sprintf(str_buf, ">\n");
|
||||
memcpy(resp+args.size, &str_buf, ret+1);
|
||||
args.size += ret;
|
||||
strcatf(&str, ">\n");
|
||||
|
||||
args.returned = 0;
|
||||
args.requested = RequestedCount;
|
||||
@ -1188,22 +1098,19 @@ BrowseContentDirectory(struct upnphttp * h, const char * action)
|
||||
goto browse_error;
|
||||
}
|
||||
}
|
||||
ret = snprintf(str_buf, sizeof(str_buf), "</DIDL-Lite></Result>\n"
|
||||
"<NumberReturned>%u</NumberReturned>\n"
|
||||
"<TotalMatches>%u</TotalMatches>\n"
|
||||
"<UpdateID>%u</UpdateID>"
|
||||
"</u:BrowseResponse>",
|
||||
args.returned, totalMatches, updateID);
|
||||
memcpy(resp+args.size, &str_buf, ret+1);
|
||||
args.size += ret;
|
||||
BuildSendAndCloseSoapResp(h, resp, args.size);
|
||||
ret = strcatf(&str, "</DIDL-Lite></Result>\n"
|
||||
"<NumberReturned>%u</NumberReturned>\n"
|
||||
"<TotalMatches>%u</TotalMatches>\n"
|
||||
"<UpdateID>%u</UpdateID>"
|
||||
"</u:BrowseResponse>",
|
||||
args.returned, totalMatches, updateID);
|
||||
BuildSendAndCloseSoapResp(h, str.data, str.off);
|
||||
browse_error:
|
||||
ClearNameValueList(&data);
|
||||
if( orderBy )
|
||||
free(orderBy);
|
||||
if( args.flags & FLAG_FREE_OBJECT_ID )
|
||||
sqlite3_free(ObjectId);
|
||||
free(resp);
|
||||
free(orderBy);
|
||||
free(str.data);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1215,16 +1122,13 @@ SearchContentDirectory(struct upnphttp * h, const char * action)
|
||||
"<Result>"
|
||||
"<DIDL-Lite"
|
||||
CONTENT_DIRECTORY_SCHEMAS;
|
||||
|
||||
char *resp = malloc(1048576);
|
||||
char *zErrMsg = 0;
|
||||
char *sql, *ptr;
|
||||
char **result;
|
||||
char str_buf[4096];
|
||||
int ret;
|
||||
struct Response args;
|
||||
struct string_s str;
|
||||
int totalMatches = 0;
|
||||
*resp = '\0';
|
||||
int ret;
|
||||
|
||||
struct NameValueParserData data;
|
||||
ParseNameValue(h->req_buf + h->req_contentoff, h->req_contentlen, &data);
|
||||
@ -1254,26 +1158,24 @@ SearchContentDirectory(struct upnphttp * h, const char * action)
|
||||
}
|
||||
}
|
||||
memset(&args, 0, sizeof(args));
|
||||
memset(&str, 0, sizeof(str));
|
||||
|
||||
args.alloced = 1048576;
|
||||
args.resp = resp;
|
||||
args.size = sprintf(resp, "%s", resp0);
|
||||
str.data = malloc(DEFAULT_RESP_SIZE);
|
||||
str.size = DEFAULT_RESP_SIZE;
|
||||
str.off = sprintf(str.data, "%s", resp0);
|
||||
/* See if we need to include DLNA namespace reference */
|
||||
args.filter = set_filter_flags(Filter, h->req_client);
|
||||
if( args.filter & FILTER_DLNA_NAMESPACE )
|
||||
{
|
||||
ret = sprintf(str_buf, DLNA_NAMESPACE);
|
||||
memcpy(resp+args.size, &str_buf, ret+1);
|
||||
args.size += ret;
|
||||
ret = strcatf(&str, DLNA_NAMESPACE);
|
||||
}
|
||||
ret = sprintf(str_buf, ">\n");
|
||||
memcpy(resp+args.size, &str_buf, ret+1);
|
||||
args.size += ret;
|
||||
ret = strcatf(&str, ">\n");
|
||||
|
||||
args.returned = 0;
|
||||
args.requested = RequestedCount;
|
||||
args.client = h->req_client;
|
||||
args.flags = h->reqflags;
|
||||
args.str = &str;
|
||||
if( h->reqflags & FLAG_MS_PFS )
|
||||
{
|
||||
if( strchr(ContainerID, '$') || (strcmp(ContainerID, "0") == 0) )
|
||||
@ -1346,13 +1248,13 @@ SearchContentDirectory(struct upnphttp * h, const char * action)
|
||||
if( strstr(SearchCriteria, "@id") )
|
||||
{
|
||||
newSearchCriteria = strdup(SearchCriteria);
|
||||
newSearchCriteria = SearchCriteria = modifyString(newSearchCriteria, "@id", "OBJECT_ID", 0);
|
||||
SearchCriteria = newSearchCriteria = modifyString(newSearchCriteria, "@id", "OBJECT_ID", 0);
|
||||
}
|
||||
if( strstr(SearchCriteria, "res is ") )
|
||||
{
|
||||
if( !newSearchCriteria )
|
||||
newSearchCriteria = strdup(SearchCriteria);
|
||||
newSearchCriteria = SearchCriteria = modifyString(newSearchCriteria, "res is ", "MIME is ", 0);
|
||||
SearchCriteria = newSearchCriteria = modifyString(newSearchCriteria, "res is ", "MIME is ", 0);
|
||||
}
|
||||
#if 0 // Does 360 need this?
|
||||
if( strstr(SearchCriteria, "&") )
|
||||
@ -1367,14 +1269,16 @@ SearchContentDirectory(struct upnphttp * h, const char * action)
|
||||
}
|
||||
DPRINTF(E_DEBUG, L_HTTP, "Translated SearchCriteria: %s\n", SearchCriteria);
|
||||
|
||||
sprintf(str_buf, "SELECT (select count(distinct DETAIL_ID) from OBJECTS o left join DETAILS d on (o.DETAIL_ID = d.ID)"
|
||||
" where (OBJECT_ID glob '%s$*') and (%s))"
|
||||
" + "
|
||||
"(select count(*) from OBJECTS o left join DETAILS d on (o.DETAIL_ID = d.ID)"
|
||||
" where (OBJECT_ID = '%s') and (%s))",
|
||||
ContainerID, SearchCriteria, ContainerID, SearchCriteria);
|
||||
sql = sqlite3_mprintf("SELECT (select count(distinct DETAIL_ID)"
|
||||
" from OBJECTS o left join DETAILS d on (o.DETAIL_ID = d.ID)"
|
||||
" where (OBJECT_ID glob '%s$*') and (%s))"
|
||||
" + "
|
||||
"(select count(*) from OBJECTS o left join DETAILS d on (o.DETAIL_ID = d.ID)"
|
||||
" where (OBJECT_ID = '%s') and (%s))",
|
||||
ContainerID, SearchCriteria, ContainerID, SearchCriteria);
|
||||
//DEBUG DPRINTF(E_DEBUG, L_HTTP, "Count SQL: %s\n", sql);
|
||||
ret = sql_get_table(db, str_buf, &result, NULL, NULL);
|
||||
ret = sql_get_table(db, sql, &result, NULL, NULL);
|
||||
sqlite3_free(sql);
|
||||
if( ret == SQLITE_OK )
|
||||
{
|
||||
totalMatches = atoi(result[1]);
|
||||
@ -1428,27 +1332,20 @@ SearchContentDirectory(struct upnphttp * h, const char * action)
|
||||
sqlite3_free(zErrMsg);
|
||||
}
|
||||
sqlite3_free(sql);
|
||||
strcat(resp, str_buf);
|
||||
ret = snprintf(str_buf, sizeof(str_buf), "</DIDL-Lite></Result>\n"
|
||||
"<NumberReturned>%u</NumberReturned>\n"
|
||||
"<TotalMatches>%u</TotalMatches>\n"
|
||||
"<UpdateID>%u</UpdateID>"
|
||||
"</u:SearchResponse>",
|
||||
args.returned, totalMatches, updateID);
|
||||
memcpy(resp+args.size, &str_buf, ret+1);
|
||||
args.size += ret;
|
||||
BuildSendAndCloseSoapResp(h, resp, args.size);
|
||||
ret = strcatf(&str, "</DIDL-Lite></Result>\n"
|
||||
"<NumberReturned>%u</NumberReturned>\n"
|
||||
"<TotalMatches>%u</TotalMatches>\n"
|
||||
"<UpdateID>%u</UpdateID>"
|
||||
"</u:SearchResponse>",
|
||||
args.returned, totalMatches, updateID);
|
||||
BuildSendAndCloseSoapResp(h, str.data, str.off);
|
||||
search_error:
|
||||
ClearNameValueList(&data);
|
||||
if( orderBy )
|
||||
free(orderBy);
|
||||
if( newSearchCriteria )
|
||||
free(newSearchCriteria);
|
||||
free(resp);
|
||||
if( h->reqflags & FLAG_MS_PFS )
|
||||
{
|
||||
sqlite3_free(ContainerID);
|
||||
}
|
||||
free(orderBy);
|
||||
free(newSearchCriteria);
|
||||
free(str.data);
|
||||
}
|
||||
|
||||
/*
|
||||
|
Reference in New Issue
Block a user