"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "upnpsoap.c" between
minidlna-1.1.4.tar.gz and minidlna-1.1.5.tar.gz

About: ReadyMedia (formerly known as MiniDLNA) is a simple media server software, with the aim of being fully compliant with DLNA/UPnP-AV clients.

upnpsoap.c  (minidlna-1.1.4):upnpsoap.c  (minidlna-1.1.5)
skipping to change at line 81 skipping to change at line 81
#include "scanner.h" #include "scanner.h"
#include "sql.h" #include "sql.h"
#include "log.h" #include "log.h"
#ifdef __sparc__ /* Sorting takes too long on slow processors with very large co ntainers */ #ifdef __sparc__ /* Sorting takes too long on slow processors with very large co ntainers */
# define __SORT_LIMIT if( totalMatches < 10000 ) # define __SORT_LIMIT if( totalMatches < 10000 )
#else #else
# define __SORT_LIMIT # define __SORT_LIMIT
#endif #endif
/* Standard Errors:
*
* errorCode errorDescription Description
* -------- ---------------- -----------
* 401 Invalid Action No action by that name at this service.
* 402 Invalid Args Could be any of the following: not enough
in args,
* too many in args, no in a
rg by that name,
* one or more in args are o
f the wrong data type.
* 403 Out of Sync Out of synchronization.
* 501 Action Failed May be returned in current state of servi
ce
* prevents invoking that ac
tion.
* 600-699 TBD Common action errors. Defined by UPnP For
um
* Technical Committee.
* 700-799 TBD Action-specific errors for standard actio
ns.
* Defined by UPnP Forum wor
king committee.
* 800-899 TBD Action-specific errors for non-standard a
ctions.
* Defined by UPnP vendor.
*/
static void
SoapError(struct upnphttp * h, int errCode, const char * errDesc)
{
static const char resp[] =
"<s:Envelope "
"xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" "
"s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
"<s:Body>"
"<s:Fault>"
"<faultcode>s:Client</faultcode>"
"<faultstring>UPnPError</faultstring>"
"<detail>"
"<UPnPError xmlns=\"urn:schemas-upnp-org:control-1-0\">"
"<errorCode>%d</errorCode>"
"<errorDescription>%s</errorDescription>"
"</UPnPError>"
"</detail>"
"</s:Fault>"
"</s:Body>"
"</s:Envelope>";
char body[2048];
int bodylen;
DPRINTF(E_WARN, L_HTTP, "Returning UPnPError %d: %s\n", errCode, errDesc)
;
bodylen = snprintf(body, sizeof(body), resp, errCode, errDesc);
BuildResp2_upnphttp(h, 500, "Internal Server Error", body, bodylen);
SendResp_upnphttp(h);
CloseSocket_upnphttp(h);
}
static void static void
BuildSendAndCloseSoapResp(struct upnphttp * h, BuildSendAndCloseSoapResp(struct upnphttp * h,
const char * body, int bodylen) const char * body, int bodylen)
{ {
static const char beforebody[] = static const char beforebody[] =
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n" "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n"
"<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\ " " "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\ " "
"s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
"<s:Body>"; "<s:Body>";
skipping to change at line 518 skipping to change at line 567
else if( strcmp(item, "av:mediaClass") == 0 ) else if( strcmp(item, "av:mediaClass") == 0 )
{ {
flags |= FILTER_AV_MEDIA_CLASS; flags |= FILTER_AV_MEDIA_CLASS;
} }
item = strtok_r(NULL, ",", &saveptr); item = strtok_r(NULL, ",", &saveptr);
} }
return flags; return flags;
} }
char * static char *
parse_sort_criteria(char *sortCriteria, int *error) parse_sort_criteria(char *sortCriteria, int *error)
{ {
char *order = NULL; char *order = NULL;
char *item, *saveptr; char *item, *saveptr;
int i, ret, reverse, title_sorted = 0; int i, ret, reverse, title_sorted = 0;
struct string_s str; struct string_s str;
*error = 0; *error = 0;
if( force_sort_criteria ) if( force_sort_criteria )
sortCriteria = strdup(force_sort_criteria); sortCriteria = strdup(force_sort_criteria);
skipping to change at line 623 skipping to change at line 672
return order; return order;
} }
inline static void inline static void
add_resized_res(int srcw, int srch, int reqw, int reqh, char *dlna_pn, add_resized_res(int srcw, int srch, int reqw, int reqh, char *dlna_pn,
char *detailID, struct Response *args) char *detailID, struct Response *args)
{ {
int dstw = reqw; int dstw = reqw;
int dsth = reqh; int dsth = reqh;
if( args->flags & FLAG_NO_RESIZE ) if( (args->flags & FLAG_NO_RESIZE) && reqw > 160 && reqh > 160 )
return; return;
strcatf(args->str, "&lt;res "); strcatf(args->str, "&lt;res ");
if( args->filter & FILTER_RES_RESOLUTION ) if( args->filter & FILTER_RES_RESOLUTION )
{ {
dstw = reqw; dstw = reqw;
dsth = ((((reqw<<10)/srcw)*srch)>>10); dsth = ((((reqw<<10)/srcw)*srch)>>10);
if( dsth > reqh ) { if( dsth > reqh ) {
dsth = reqh; dsth = reqh;
dstw = (((reqh<<10)/srch) * srcw>>10); dstw = (((reqh<<10)/srch) * srcw>>10);
skipping to change at line 718 skipping to change at line 767
{ {
int ret; int ret;
ret = sql_get_int_field(db, "SELECT count(*) from OBJECTS where OBJECT_ID = '%q'", ret = sql_get_int_field(db, "SELECT count(*) from OBJECTS where OBJECT_ID = '%q'",
strcmp(object, "*") == 0 ? "0" : object); strcmp(object, "*") == 0 ? "0" : object);
return (ret > 0); return (ret > 0);
} }
#define COLUMNS "o.DETAIL_ID, o.CLASS," \ #define COLUMNS "o.DETAIL_ID, o.CLASS," \
" d.SIZE, d.TITLE, d.DURATION, d.BITRATE, d.SAMPLERATE, d.ARTIST ," \ " d.SIZE, d.TITLE, d.DURATION, d.BITRATE, d.SAMPLERATE, d.ARTIST ," \
" d.ALBUM, d.GENRE, d.COMMENT, d.CHANNELS, d.TRACK, d.DATE, d.RE SOLUTION," \ " d.ALBUM, d.GENRE, d.COMMENT, d.CHANNELS, d.TRACK, d.DATE, d.RE SOLUTION," \
" d.THUMBNAIL, d.CREATOR, d.DLNA_PN, d.MIME, d.ALBUM_ART, d.DISC " " d.THUMBNAIL, d.CREATOR, d.DLNA_PN, d.MIME, d.ALBUM_ART, d.ROTA TION, d.DISC "
#define SELECT_COLUMNS "SELECT o.OBJECT_ID, o.PARENT_ID, o.REF_ID, " COLUMNS #define SELECT_COLUMNS "SELECT o.OBJECT_ID, o.PARENT_ID, o.REF_ID, " COLUMNS
#define NON_ZERO(x) (x && atoi(x))
#define IS_ZERO(x) (!x || !atoi(x))
static int static int
callback(void *args, int argc, char **argv, char **azColName) callback(void *args, int argc, char **argv, char **azColName)
{ {
struct Response *passed_args = (struct Response *)args; struct Response *passed_args = (struct Response *)args;
char *id = argv[0], *parent = argv[1], *refID = argv[2], *detailID = argv [3], *class = argv[4], *size = argv[5], *title = argv[6], char *id = argv[0], *parent = argv[1], *refID = argv[2], *detailID = argv [3], *class = argv[4], *size = argv[5], *title = argv[6],
*duration = argv[7], *bitrate = argv[8], *sampleFrequency = argv[9], *artist = argv[10], *album = argv[11], *duration = argv[7], *bitrate = argv[8], *sampleFrequency = argv[9], *artist = argv[10], *album = argv[11],
*genre = argv[12], *comment = argv[13], *nrAudioChannels = argv[14], *track = argv[15], *date = argv[16], *resolution = argv[17], *genre = argv[12], *comment = argv[13], *nrAudioChannels = argv[14], *track = argv[15], *date = argv[16], *resolution = argv[17],
*tn = argv[18], *creator = argv[19], *dlna_pn = argv[20], *mime = ar gv[21], *album_art = argv[22]; *tn = argv[18], *creator = argv[19], *dlna_pn = argv[20], *mime = ar gv[21], *album_art = argv[22], *rotate = argv[23];
char dlna_buf[128]; char dlna_buf[128];
const char *ext; const char *ext;
struct string_s *str = passed_args->str; struct string_s *str = passed_args->str;
int ret = 0; int ret = 0;
/* Make sure we have at least 8KB left of allocated memory to finish the response. */ /* Make sure we have at least 8KB left of allocated memory to finish the response. */
if( str->off > (str->size - 8192) ) if( str->off > (str->size - 8192) )
{ {
#if MAX_RESPONSE_SIZE > 0 #if MAX_RESPONSE_SIZE > 0
if( (str->size+DEFAULT_RESP_SIZE) <= MAX_RESPONSE_SIZE ) if( (str->size+DEFAULT_RESP_SIZE) <= MAX_RESPONSE_SIZE )
skipping to change at line 763 skipping to change at line 815
#if MAX_RESPONSE_SIZE > 0 #if MAX_RESPONSE_SIZE > 0
} }
else else
{ {
DPRINTF(E_ERROR, L_HTTP, "UPnP SOAP response cut short, t o not exceed the max response size [%lld]!\n", (long long int)MAX_RESPONSE_SIZE) ; DPRINTF(E_ERROR, L_HTTP, "UPnP SOAP response cut short, t o not exceed the max response size [%lld]!\n", (long long int)MAX_RESPONSE_SIZE) ;
return -1; return -1;
} }
#endif #endif
} }
passed_args->returned++; passed_args->returned++;
passed_args->flags &= ~RESPONSE_FLAGS;
if( strncmp(class, "item", 4) == 0 ) if( strncmp(class, "item", 4) == 0 )
{ {
uint32_t dlna_flags = DLNA_FLAG_DLNA_V1_5|DLNA_FLAG_HTTP_STALLING |DLNA_FLAG_TM_B; uint32_t dlna_flags = DLNA_FLAG_DLNA_V1_5|DLNA_FLAG_HTTP_STALLING |DLNA_FLAG_TM_B;
char *alt_title = NULL; char *alt_title = NULL;
/* We may need special handling for certain MIME types */ /* We may need special handling for certain MIME types */
if( *mime == 'v' ) if( *mime == 'v' )
{ {
dlna_flags |= DLNA_FLAG_TM_S; dlna_flags |= DLNA_FLAG_TM_S;
if( passed_args->flags & FLAG_MIME_AVI_DIVX ) if( passed_args->flags & FLAG_MIME_AVI_DIVX )
skipping to change at line 908 skipping to change at line 961
} }
if( album && (passed_args->filter & FILTER_UPNP_ALBUM) ) { if( album && (passed_args->filter & FILTER_UPNP_ALBUM) ) {
ret = strcatf(str, "&lt;upnp:album&gt;%s&lt;/upnp:album&g t;", album); ret = strcatf(str, "&lt;upnp:album&gt;%s&lt;/upnp:album&g t;", album);
} }
if( genre && (passed_args->filter & FILTER_UPNP_GENRE) ) { if( genre && (passed_args->filter & FILTER_UPNP_GENRE) ) {
ret = strcatf(str, "&lt;upnp:genre&gt;%s&lt;/upnp:genre&g t;", genre); ret = strcatf(str, "&lt;upnp:genre&gt;%s&lt;/upnp:genre&g t;", genre);
} }
if( strncmp(id, MUSIC_PLIST_ID, strlen(MUSIC_PLIST_ID)) == 0 ) { if( strncmp(id, MUSIC_PLIST_ID, strlen(MUSIC_PLIST_ID)) == 0 ) {
track = strrchr(id, '$')+1; track = strrchr(id, '$')+1;
} }
if( track && atoi(track) && (passed_args->filter & FILTER_UPNP_OR IGINALTRACKNUMBER) ) { if( NON_ZERO(track) && (passed_args->filter & FILTER_UPNP_ORIGINA LTRACKNUMBER) ) {
ret = strcatf(str, "&lt;upnp:originalTrackNumber&gt;%s&lt ;/upnp:originalTrackNumber&gt;", track); ret = strcatf(str, "&lt;upnp:originalTrackNumber&gt;%s&lt ;/upnp:originalTrackNumber&gt;", track);
} }
if( passed_args->filter & FILTER_RES ) { if( passed_args->filter & FILTER_RES ) {
ext = mime_to_ext(mime); ext = mime_to_ext(mime);
add_res(size, duration, bitrate, sampleFrequency, nrAudio Channels, add_res(size, duration, bitrate, sampleFrequency, nrAudio Channels,
resolution, dlna_buf, mime, detailID, ext, passed _args); resolution, dlna_buf, mime, detailID, ext, passed _args);
if( *mime == 'i' ) { if( *mime == 'i' ) {
int srcw, srch; int srcw, srch;
if( resolution && (sscanf(resolution, "%6dx%6d", &srcw, &srch) == 2) ) if( resolution && (sscanf(resolution, "%6dx%6d", &srcw, &srch) == 2) )
{ {
if( srcw > 4096 || srch > 4096 ) if( srcw > 4096 || srch > 4096 )
add_resized_res(srcw, srch, 4096, 4096, "JPEG_LRG", detailID, passed_args); add_resized_res(srcw, srch, 4096, 4096, "JPEG_LRG", detailID, passed_args);
if( srcw > 1024 || srch > 768 ) if( srcw > 1024 || srch > 768 )
add_resized_res(srcw, srch, 1024, 768, "JPEG_MED", detailID, passed_args); add_resized_res(srcw, srch, 1024, 768, "JPEG_MED", detailID, passed_args);
if( srcw > 640 || srch > 480 ) if( srcw > 640 || srch > 480 )
add_resized_res(srcw, srch, 640, 480, "JPEG_SM", detailID, passed_args); add_resized_res(srcw, srch, 640, 480, "JPEG_SM", detailID, passed_args);
} }
if( !(passed_args->flags & FLAG_RESIZE_THUMBS) && tn && atoi(tn) ) { if( !(passed_args->flags & FLAG_RESIZE_THUMBS) && NON_ZERO(tn) && IS_ZERO(rotate) ) {
ret = strcatf(str, "&lt;res protocolInfo= \"http-get:*:%s:%s\"&gt;" ret = strcatf(str, "&lt;res protocolInfo= \"http-get:*:%s:%s\"&gt;"
"http://%s:%d/Thumbnai ls/%s.jpg" "http://%s:%d/Thumbnai ls/%s.jpg"
"&lt;/res&gt;", "&lt;/res&gt;",
mime, "DLNA.ORG_PN=JPE G_TN;DLNA.ORG_CI=1", lan_addr[passed_args->iface].str, mime, "DLNA.ORG_PN=JPE G_TN;DLNA.ORG_CI=1", lan_addr[passed_args->iface].str,
runtime_vars.port, det ailID); runtime_vars.port, det ailID);
} }
else else
add_resized_res(srcw, srch, 160, 160, "JP EG_TN", detailID, passed_args); add_resized_res(srcw, srch, 160, 160, "JP EG_TN", detailID, passed_args);
} }
else if( *mime == 'v' ) { else if( *mime == 'v' ) {
skipping to change at line 1025 skipping to change at line 1078
ret = strcatf(str, "&lt;s ec:CaptionInfoEx sec:type=\"srt\"&gt;" ret = strcatf(str, "&lt;s ec:CaptionInfoEx sec:type=\"srt\"&gt;"
"htt p://%s:%d/Captions/%s.srt" "htt p://%s:%d/Captions/%s.srt"
"&lt;/ sec:CaptionInfoEx&gt;", "&lt;/ sec:CaptionInfoEx&gt;",
lan_ad dr[passed_args->iface].str, runtime_vars.port, detailID); lan_ad dr[passed_args->iface].str, runtime_vars.port, detailID);
} }
free(alt_title); free(alt_title);
break; break;
} }
} }
} }
if( album_art && atoi(album_art) ) if( NON_ZERO(album_art) )
{ {
/* Video and audio album art is handled differently */ /* Video and audio album art is handled differently */
if( *mime == 'v' && (passed_args->filter & FILTER_RES) && !(passed_args->flags & FLAG_MS_PFS) ) { if( *mime == 'v' && (passed_args->filter & FILTER_RES) && !(passed_args->flags & FLAG_MS_PFS) ) {
ret = strcatf(str, "&lt;res protocolInfo=\"http-g et:*:image/jpeg:DLNA.ORG_PN=JPEG_TN\"&gt;" ret = strcatf(str, "&lt;res protocolInfo=\"http-g et:*:image/jpeg:DLNA.ORG_PN=JPEG_TN\"&gt;"
"http://%s:%d/AlbumArt/%s-%s.j pg" "http://%s:%d/AlbumArt/%s-%s.j pg"
"&lt;/res&gt;", "&lt;/res&gt;",
lan_addr[passed_args->iface].s tr, runtime_vars.port, album_art, detailID); lan_addr[passed_args->iface].s tr, runtime_vars.port, album_art, detailID);
} else if( passed_args->filter & FILTER_UPNP_ALBUMARTURI ) { } else if( passed_args->filter & FILTER_UPNP_ALBUMARTURI ) {
ret = strcatf(str, "&lt;upnp:albumArtURI"); ret = strcatf(str, "&lt;upnp:albumArtURI");
if( passed_args->filter & FILTER_UPNP_ALBUMARTURI _DLNA_PROFILEID ) { if( passed_args->filter & FILTER_UPNP_ALBUMARTURI _DLNA_PROFILEID ) {
skipping to change at line 1047 skipping to change at line 1100
} }
ret = strcatf(str, "&gt;http://%s:%d/AlbumArt/%s- %s.jpg&lt;/upnp:albumArtURI&gt;", ret = strcatf(str, "&gt;http://%s:%d/AlbumArt/%s- %s.jpg&lt;/upnp:albumArtURI&gt;",
lan_addr[passed_args->iface].s tr, runtime_vars.port, album_art, detailID); lan_addr[passed_args->iface].s tr, runtime_vars.port, album_art, detailID);
} }
} }
if( (passed_args->flags & FLAG_MS_PFS) && *mime == 'i' ) { if( (passed_args->flags & FLAG_MS_PFS) && *mime == 'i' ) {
if( passed_args->client == EMediaRoom && !album ) if( passed_args->client == EMediaRoom && !album )
ret = strcatf(str, "&lt;upnp:album&gt;%s&lt;/upnp :album&gt;", "[No Keywords]"); ret = strcatf(str, "&lt;upnp:album&gt;%s&lt;/upnp :album&gt;", "[No Keywords]");
/* EVA2000 doesn't seem to handle embedded thumbnails */ /* EVA2000 doesn't seem to handle embedded thumbnails */
if( !(passed_args->flags & FLAG_RESIZE_THUMBS) && tn && a toi(tn) ) { if( !(passed_args->flags & FLAG_RESIZE_THUMBS) && NON_ZER O(tn) && IS_ZERO(rotate) ) {
ret = strcatf(str, "&lt;upnp:albumArtURI&gt;" ret = strcatf(str, "&lt;upnp:albumArtURI&gt;"
"http://%s:%d/Thumbnails/%s.jp g" "http://%s:%d/Thumbnails/%s.jp g"
"&lt;/upnp:albumArtURI&gt;", "&lt;/upnp:albumArtURI&gt;",
lan_addr[passed_args->iface].s tr, runtime_vars.port, detailID); lan_addr[passed_args->iface].s tr, runtime_vars.port, detailID);
} else { } else {
ret = strcatf(str, "&lt;upnp:albumArtURI&gt;" ret = strcatf(str, "&lt;upnp:albumArtURI&gt;"
"http://%s:%d/Resized/%s.jpg?w idth=160,height=160" "http://%s:%d/Resized/%s.jpg?w idth=160,height=160"
"&lt;/upnp:albumArtURI&gt;", "&lt;/upnp:albumArtURI&gt;",
lan_addr[passed_args->iface].s tr, runtime_vars.port, detailID); lan_addr[passed_args->iface].s tr, runtime_vars.port, detailID);
} }
skipping to change at line 1094 skipping to change at line 1147
} }
if( creator && (passed_args->filter & FILTER_DC_CREATOR) ) { if( creator && (passed_args->filter & FILTER_DC_CREATOR) ) {
ret = strcatf(str, "&lt;dc:creator&gt;%s&lt;/dc:creator&g t;", creator); ret = strcatf(str, "&lt;dc:creator&gt;%s&lt;/dc:creator&g t;", creator);
} }
if( genre && (passed_args->filter & FILTER_UPNP_GENRE) ) { if( genre && (passed_args->filter & FILTER_UPNP_GENRE) ) {
ret = strcatf(str, "&lt;upnp:genre&gt;%s&lt;/upnp:genre&g t;", genre); ret = strcatf(str, "&lt;upnp:genre&gt;%s&lt;/upnp:genre&g t;", genre);
} }
if( artist && (passed_args->filter & FILTER_UPNP_ARTIST) ) { if( artist && (passed_args->filter & FILTER_UPNP_ARTIST) ) {
ret = strcatf(str, "&lt;upnp:artist&gt;%s&lt;/upnp:artist &gt;", artist); ret = strcatf(str, "&lt;upnp:artist&gt;%s&lt;/upnp:artist &gt;", artist);
} }
if( album_art && atoi(album_art) && (passed_args->filter & FILTER _UPNP_ALBUMARTURI) ) { if( NON_ZERO(album_art) && (passed_args->filter & FILTER_UPNP_ALB UMARTURI) ) {
ret = strcatf(str, "&lt;upnp:albumArtURI "); ret = strcatf(str, "&lt;upnp:albumArtURI ");
if( passed_args->filter & FILTER_UPNP_ALBUMARTURI_DLNA_PR OFILEID ) { if( passed_args->filter & FILTER_UPNP_ALBUMARTURI_DLNA_PR OFILEID ) {
ret = strcatf(str, "dlna:profileID=\"JPEG_TN\" xm lns:dlna=\"urn:schemas-dlna-org:metadata-1-0/\""); ret = strcatf(str, "dlna:profileID=\"JPEG_TN\" xm lns:dlna=\"urn:schemas-dlna-org:metadata-1-0/\"");
} }
ret = strcatf(str, "&gt;http://%s:%d/AlbumArt/%s-%s.jpg&l t;/upnp:albumArtURI&gt;", ret = strcatf(str, "&gt;http://%s:%d/AlbumArt/%s-%s.jpg&l t;/upnp:albumArtURI&gt;",
lan_addr[passed_args->iface].str, runt ime_vars.port, album_art, detailID); lan_addr[passed_args->iface].str, runt ime_vars.port, album_art, detailID);
} }
if( passed_args->filter & FILTER_AV_MEDIA_CLASS ) { if( passed_args->filter & FILTER_AV_MEDIA_CLASS ) {
char class; char class;
if( strncmp(id, MUSIC_ID, sizeof(MUSIC_ID)) == 0 ) if( strncmp(id, MUSIC_ID, sizeof(MUSIC_ID)) == 0 )
skipping to change at line 1249 skipping to change at line 1302
if (magic->objectid && *(magic->objectid)) if (magic->objectid && *(magic->objectid))
ObjectID = *(magic->objectid); ObjectID = *(magic->objectid);
if (magic->objectid_sql) if (magic->objectid_sql)
objectid_sql = magic->objectid_sql; objectid_sql = magic->objectid_sql;
if (magic->parentid_sql) if (magic->parentid_sql)
parentid_sql = magic->parentid_sql; parentid_sql = magic->parentid_sql;
if (magic->refid_sql) if (magic->refid_sql)
refid_sql = magic->refid_sql; refid_sql = magic->refid_sql;
if (magic->where) if (magic->where)
strncpyt(where, magic->where, sizeof(where)); strncpyt(where, magic->where, sizeof(where));
if (magic->orderby && !GETFLAG(DLNA_STRICT_MASK))
orderBy = strdup(magic->orderby);
if (magic->max_count > 0) if (magic->max_count > 0)
{ {
int limit = MAX(magic->max_count - StartingIndex, 0);
ret = get_child_count(ObjectID, magic); ret = get_child_count(ObjectID, magic);
totalMatches = ret > magic->max_count ? magic->ma totalMatches = MIN(ret, limit);
x_count : ret; if (RequestedCount > limit || RequestedCount < 0)
if (RequestedCount > magic->max_count || Requeste RequestedCount = limit;
dCount < 0)
RequestedCount = magic->max_count;
} }
} }
if (!where[0]) if (!where[0])
sqlite3_snprintf(sizeof(where), where, "PARENT_ID = '%q'" , ObjectID); sqlite3_snprintf(sizeof(where), where, "PARENT_ID = '%q'" , ObjectID);
if (!totalMatches) if (!totalMatches)
totalMatches = get_child_count(ObjectID, magic); totalMatches = get_child_count(ObjectID, magic);
ret = 0; ret = 0;
if( SortCriteria ) if (SortCriteria && !orderBy)
{ {
__SORT_LIMIT __SORT_LIMIT
orderBy = parse_sort_criteria(SortCriteria, &ret); orderBy = parse_sort_criteria(SortCriteria, &ret);
} }
else if (!orderBy) else if (!orderBy)
{ {
if( strncmp(ObjectID, MUSIC_PLIST_ID, strlen(MUSIC_PLIST_ ID)) == 0 ) if( strncmp(ObjectID, MUSIC_PLIST_ID, strlen(MUSIC_PLIST_ ID)) == 0 )
{ {
if( strcmp(ObjectID, MUSIC_PLIST_ID) == 0 ) if( strcmp(ObjectID, MUSIC_PLIST_ID) == 0 )
ret = xasprintf(&orderBy, "order by d.TIT LE"); ret = xasprintf(&orderBy, "order by d.TIT LE");
else else
ret = xasprintf(&orderBy, "order by lengt h(OBJECT_ID), OBJECT_ID"); ret = xasprintf(&orderBy, "order by lengt h(OBJECT_ID), OBJECT_ID");
} }
else if( args.flags & FLAG_FORCE_SORT ) else if( args.flags & FLAG_FORCE_SORT )
{ {
__SORT_LIMIT __SORT_LIMIT
ret = xasprintf(&orderBy, "order by o.CLASS, d.DI SC, d.TRACK, d.TITLE"); ret = xasprintf(&orderBy, "order by o.CLASS, d.DI SC, d.TRACK, d.TITLE");
} }
/* LG TV ordering bug */
else if( args.client == ELGDevice )
ret = xasprintf(&orderBy, "order by o.CLASS, d.TI
TLE");
else else
orderBy = parse_sort_criteria(SortCriteria, &ret) ; orderBy = parse_sort_criteria(SortCriteria, &ret) ;
if( ret == -1 ) if( ret == -1 )
{ {
free(orderBy); free(orderBy);
orderBy = NULL; orderBy = NULL;
ret = 0; ret = 0;
} }
} }
/* If it's a DLNA client, return an error for bad sort criteria * / /* If it's a DLNA client, return an error for bad sort criteria * /
skipping to change at line 1336 skipping to change at line 1395
"<UpdateID>%u</UpdateID>" "<UpdateID>%u</UpdateID>"
"</u:BrowseResponse>", "</u:BrowseResponse>",
args.returned, totalMatches, updateID); args.returned, totalMatches, updateID);
BuildSendAndCloseSoapResp(h, str.data, str.off); BuildSendAndCloseSoapResp(h, str.data, str.off);
browse_error: browse_error:
ClearNameValueList(&data); ClearNameValueList(&data);
free(orderBy); free(orderBy);
free(str.data); free(str.data);
} }
inline void static inline void
charcat(struct string_s *str, char c) charcat(struct string_s *str, char c)
{ {
if (str->size <= str->off) if (str->size <= str->off)
{ {
str->data[str->size-1] = '\0'; str->data[str->size-1] = '\0';
return; return;
} }
str->data[str->off] = c; str->data[str->off] = c;
str->off += 1; str->off += 1;
} }
skipping to change at line 1817 skipping to change at line 1876
ClearNameValueList(&data); ClearNameValueList(&data);
} }
static void static void
SamsungGetFeatureList(struct upnphttp * h, const char * action) SamsungGetFeatureList(struct upnphttp * h, const char * action)
{ {
static const char resp[] = static const char resp[] =
"<u:X_GetFeatureListResponse xmlns:u=\"urn:schemas-upnp-org:servi ce:ContentDirectory:1\">" "<u:X_GetFeatureListResponse xmlns:u=\"urn:schemas-upnp-org:servi ce:ContentDirectory:1\">"
"<FeatureList>" "<FeatureList>"
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n"
"&lt;Features xmlns=\"urn:schemas-upnp-org:av:avs\"" "&lt;Features xmlns=\"urn:schemas-upnp-org:av:avs\""
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
" xsi:schemaLocation=\"urn:schemas-upnp-org:av:avs http://www.upn p.org/schemas/av/avs.xsd\"&gt;" " xsi:schemaLocation=\"urn:schemas-upnp-org:av:avs http://www.upn p.org/schemas/av/avs.xsd\"&gt;"
"&lt;Feature name=\"samsung.com_BASICVIEW\" version=\"1\"&gt;" "&lt;Feature name=\"samsung.com_BASICVIEW\" version=\"1\"&gt;"
"&lt;container id=\"" MUSIC_ID "\" type=\"object.item.audioItem\ "&lt;container id=\"%s\" type=\"object.item.audioItem\"/&gt;"
"/&gt;" "&lt;container id=\"%s\" type=\"object.item.videoItem\"/&gt;"
"&lt;container id=\"" VIDEO_ID "\" type=\"object.item.videoItem\ "&lt;container id=\"%s\" type=\"object.item.imageItem\"/&gt;"
"/&gt;"
"&lt;container id=\"" IMAGE_ID "\" type=\"object.item.imageItem\
"/&gt;"
"&lt;/Feature&gt;" "&lt;/Feature&gt;"
"&lt;/Features&gt;" "&lt;/Features&gt;"
"</FeatureList></u:X_GetFeatureListResponse>"; "</FeatureList></u:X_GetFeatureListResponse>";
const char *audio = MUSIC_ID;
const char *video = VIDEO_ID;
const char *image = IMAGE_ID;
char body[1024];
int len;
if (runtime_vars.root_container) if (runtime_vars.root_container)
return SoapError(h, 401, "Invalid Action"); {
if (strcmp(runtime_vars.root_container, BROWSEDIR_ID) == 0)
{
audio = MUSIC_DIR_ID;
video = VIDEO_DIR_ID;
image = IMAGE_DIR_ID;
}
else
{
audio = runtime_vars.root_container;
video = runtime_vars.root_container;
image = runtime_vars.root_container;
}
}
BuildSendAndCloseSoapResp(h, resp, sizeof(resp)-1); len = snprintf(body, sizeof(body), resp, audio, video, image);
BuildSendAndCloseSoapResp(h, body, len);
} }
static void static void
SamsungSetBookmark(struct upnphttp * h, const char * action) SamsungSetBookmark(struct upnphttp * h, const char * action)
{ {
static const char resp[] = static const char resp[] =
"<u:X_SetBookmarkResponse" "<u:X_SetBookmarkResponse"
" xmlns:u=\"urn:schemas-upnp-org:service:ContentDirectory:1\">" " xmlns:u=\"urn:schemas-upnp-org:service:ContentDirectory:1\">"
"</u:X_SetBookmarkResponse>"; "</u:X_SetBookmarkResponse>";
skipping to change at line 1924 skipping to change at line 2002
return; return;
} }
i++; i++;
} }
DPRINTF(E_WARN, L_HTTP, "SoapMethod: Unknown: %.*s\n", methodlen, p); DPRINTF(E_WARN, L_HTTP, "SoapMethod: Unknown: %.*s\n", methodlen, p);
} }
SoapError(h, 401, "Invalid Action"); SoapError(h, 401, "Invalid Action");
} }
/* Standard Errors:
*
* errorCode errorDescription Description
* -------- ---------------- -----------
* 401 Invalid Action No action by that name at this service.
* 402 Invalid Args Could be any of the following: not enough
in args,
* too many in args, no in a
rg by that name,
* one or more in args are o
f the wrong data type.
* 403 Out of Sync Out of synchronization.
* 501 Action Failed May be returned in current state of servi
ce
* prevents invoking that ac
tion.
* 600-699 TBD Common action errors. Defined by UPnP For
um
* Technical Committee.
* 700-799 TBD Action-specific errors for standard actio
ns.
* Defined by UPnP Forum wor
king committee.
* 800-899 TBD Action-specific errors for non-standard a
ctions.
* Defined by UPnP vendor.
*/
void
SoapError(struct upnphttp * h, int errCode, const char * errDesc)
{
static const char resp[] =
"<s:Envelope "
"xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" "
"s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
"<s:Body>"
"<s:Fault>"
"<faultcode>s:Client</faultcode>"
"<faultstring>UPnPError</faultstring>"
"<detail>"
"<UPnPError xmlns=\"urn:schemas-upnp-org:control-1-0\">"
"<errorCode>%d</errorCode>"
"<errorDescription>%s</errorDescription>"
"</UPnPError>"
"</detail>"
"</s:Fault>"
"</s:Body>"
"</s:Envelope>";
char body[2048];
int bodylen;
DPRINTF(E_WARN, L_HTTP, "Returning UPnPError %d: %s\n", errCode, errDesc)
;
bodylen = snprintf(body, sizeof(body), resp, errCode, errDesc);
BuildResp2_upnphttp(h, 500, "Internal Server Error", body, bodylen);
SendResp_upnphttp(h);
CloseSocket_upnphttp(h);
}
 End of changes. 24 change blocks. 
25 lines changed or deleted 109 lines changed or added

Home  |  About  |  All  |  Newest  |  Fossies Dox  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTPS