Fix up a few conformance issues with latest testing tools.
This commit is contained in:
parent
8d6ce5e8b5
commit
0700cf9774
@ -388,6 +388,11 @@ ParseHttpHeaders(struct upnphttp * h)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(strncasecmp(line, "uctt.upnp.org:", 14)==0)
|
||||||
|
{
|
||||||
|
/* Conformance testing */
|
||||||
|
SETFLAG(DLNA_STRICT_MASK);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
next_header:
|
next_header:
|
||||||
while(!(line[0] == '\r' && line[1] == '\n'))
|
while(!(line[0] == '\r' && line[1] == '\n'))
|
||||||
@ -1622,7 +1627,9 @@ SendResp_resizedimg(struct upnphttp * h, char * object)
|
|||||||
dstw = (((height<<10)/srch) * srcw>>10);
|
dstw = (((height<<10)/srch) * srcw>>10);
|
||||||
}
|
}
|
||||||
|
|
||||||
if( dstw <= 640 && dsth <= 480 )
|
if( dstw <= 160 && dsth <= 160 )
|
||||||
|
strcpy(dlna_pn, "DLNA.ORG_PN=JPEG_TN;");
|
||||||
|
else if( dstw <= 640 && dsth <= 480 )
|
||||||
strcpy(dlna_pn, "DLNA.ORG_PN=JPEG_SM;");
|
strcpy(dlna_pn, "DLNA.ORG_PN=JPEG_SM;");
|
||||||
else if( dstw <= 1024 && dsth <= 768 )
|
else if( dstw <= 1024 && dsth <= 768 )
|
||||||
strcpy(dlna_pn, "DLNA.ORG_PN=JPEG_MED;");
|
strcpy(dlna_pn, "DLNA.ORG_PN=JPEG_MED;");
|
||||||
|
79
upnpsoap.c
79
upnpsoap.c
@ -306,15 +306,16 @@ GetCurrentConnectionInfo(struct upnphttp * h, const char * action)
|
|||||||
#define FILTER_RES_RESOLUTION 0x00000400
|
#define FILTER_RES_RESOLUTION 0x00000400
|
||||||
#define FILTER_RES_SAMPLEFREQUENCY 0x00000800
|
#define FILTER_RES_SAMPLEFREQUENCY 0x00000800
|
||||||
#define FILTER_RES_SIZE 0x00001000
|
#define FILTER_RES_SIZE 0x00001000
|
||||||
#define FILTER_UPNP_ACTOR 0x00002000
|
#define FILTER_SEARCHABLE 0x00002000
|
||||||
#define FILTER_UPNP_ALBUM 0x00004000
|
#define FILTER_UPNP_ACTOR 0x00004000
|
||||||
#define FILTER_UPNP_ALBUMARTURI 0x00008000
|
#define FILTER_UPNP_ALBUM 0x00008000
|
||||||
#define FILTER_UPNP_ALBUMARTURI_DLNA_PROFILEID 0x00010000
|
#define FILTER_UPNP_ALBUMARTURI 0x00010000
|
||||||
#define FILTER_UPNP_ARTIST 0x00020000
|
#define FILTER_UPNP_ALBUMARTURI_DLNA_PROFILEID 0x00020000
|
||||||
#define FILTER_UPNP_GENRE 0x00040000
|
#define FILTER_UPNP_ARTIST 0x00040000
|
||||||
#define FILTER_UPNP_ORIGINALTRACKNUMBER 0x00080000
|
#define FILTER_UPNP_GENRE 0x00080000
|
||||||
#define FILTER_UPNP_SEARCHCLASS 0x00100000
|
#define FILTER_UPNP_ORIGINALTRACKNUMBER 0x00100000
|
||||||
#define FILTER_UPNP_STORAGEUSED 0x00200000
|
#define FILTER_UPNP_SEARCHCLASS 0x00200000
|
||||||
|
#define FILTER_UPNP_STORAGEUSED 0x00400000
|
||||||
/* Vendor-specific filter flags */
|
/* Vendor-specific filter flags */
|
||||||
#define FILTER_SEC_CAPTION_INFO_EX 0x01000000
|
#define FILTER_SEC_CAPTION_INFO_EX 0x01000000
|
||||||
#define FILTER_SEC_DCM_INFO 0x02000000
|
#define FILTER_SEC_DCM_INFO 0x02000000
|
||||||
@ -345,6 +346,10 @@ set_filter_flags(char *filter, struct upnphttp *h)
|
|||||||
{
|
{
|
||||||
flags |= FILTER_CHILDCOUNT;
|
flags |= FILTER_CHILDCOUNT;
|
||||||
}
|
}
|
||||||
|
else if( strcmp(item, "@searchable") == 0 )
|
||||||
|
{
|
||||||
|
flags |= FILTER_SEARCHABLE;
|
||||||
|
}
|
||||||
else if( strcmp(item, "dc:creator") == 0 )
|
else if( strcmp(item, "dc:creator") == 0 )
|
||||||
{
|
{
|
||||||
flags |= FILTER_DC_CREATOR;
|
flags |= FILTER_DC_CREATOR;
|
||||||
@ -989,30 +994,27 @@ callback(void *args, int argc, char **argv, char **azColName)
|
|||||||
else if( strncmp(class, "container", 9) == 0 )
|
else if( strncmp(class, "container", 9) == 0 )
|
||||||
{
|
{
|
||||||
ret = strcatf(str, "<container id=\"%s\" parentID=\"%s\" restricted=\"1\" ", id, parent);
|
ret = strcatf(str, "<container id=\"%s\" parentID=\"%s\" restricted=\"1\" ", id, parent);
|
||||||
if( passed_args->filter & FILTER_CHILDCOUNT )
|
if( passed_args->filter & FILTER_SEARCHABLE ) {
|
||||||
{
|
ret = strcatf(str, "searchable=\"1\" ");
|
||||||
|
}
|
||||||
|
if( passed_args->filter & FILTER_CHILDCOUNT ) {
|
||||||
int children;
|
int children;
|
||||||
ret = sql_get_int_field(db, "SELECT count(*) from OBJECTS where PARENT_ID = '%s';", id);
|
ret = sql_get_int_field(db, "SELECT count(*) from OBJECTS where PARENT_ID = '%s';", id);
|
||||||
children = (ret > 0) ? ret : 0;
|
children = (ret > 0) ? ret : 0;
|
||||||
ret = strcatf(str, "childCount=\"%d\"", children);
|
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 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->requested == 1 && strcmp(id, "0") == 0 && (passed_args->filter & FILTER_UPNP_SEARCHCLASS) ) {
|
||||||
{
|
ret = strcatf(str, ">"
|
||||||
ret = strcatf(str, " searchable=\"1\"");
|
"<upnp:searchClass includeDerived=\"1\">object.item.audioItem</upnp:searchClass>"
|
||||||
if( passed_args->filter & FILTER_UPNP_SEARCHCLASS )
|
"<upnp:searchClass includeDerived=\"1\">object.item.imageItem</upnp:searchClass>"
|
||||||
{
|
"<upnp:searchClass includeDerived=\"1\">object.item.videoItem</upnp:searchClass");
|
||||||
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 = strcatf(str, ">"
|
ret = strcatf(str, ">"
|
||||||
"<dc:title>%s</dc:title>"
|
"<dc:title>%s</dc:title>"
|
||||||
"<upnp:class>object.%s</upnp:class>",
|
"<upnp:class>object.%s</upnp:class>",
|
||||||
title, class);
|
title, class);
|
||||||
if( (passed_args->filter & FILTER_UPNP_STORAGEUSED) && strcmp(class+10, "storageFolder") == 0 ) {
|
if( (passed_args->filter & FILTER_UPNP_STORAGEUSED) || strcmp(class+10, "storageFolder") == 0 ) {
|
||||||
/* TODO: Implement real folder size tracking */
|
/* TODO: Implement real folder size tracking */
|
||||||
ret = strcatf(str, "<upnp:storageUsed>%s</upnp:storageUsed>", (size ? size : "-1"));
|
ret = strcatf(str, "<upnp:storageUsed>%s</upnp:storageUsed>", (size ? size : "-1"));
|
||||||
}
|
}
|
||||||
@ -1331,6 +1333,12 @@ parse_search_criteria(const char *str)
|
|||||||
case 'o':
|
case 'o':
|
||||||
if (strncmp(s, "object.", 7) == 0)
|
if (strncmp(s, "object.", 7) == 0)
|
||||||
s += 7;
|
s += 7;
|
||||||
|
else if (strncmp(s, "object\"", 7) == 0 ||
|
||||||
|
strncmp(s, "object"", 12) == 0)
|
||||||
|
{
|
||||||
|
s += 6;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
charcat(&criteria, *s);
|
charcat(&criteria, *s);
|
||||||
break;
|
break;
|
||||||
@ -1498,6 +1506,16 @@ parse_search_criteria(const char *str)
|
|||||||
else
|
else
|
||||||
charcat(&criteria, *s);
|
charcat(&criteria, *s);
|
||||||
break;
|
break;
|
||||||
|
case '(':
|
||||||
|
if (s > str && !isspace(s[-1]))
|
||||||
|
charcat(&criteria, ' ');
|
||||||
|
charcat(&criteria, *s);
|
||||||
|
break;
|
||||||
|
case ')':
|
||||||
|
charcat(&criteria, *s);
|
||||||
|
if (!isspace(s[1]))
|
||||||
|
charcat(&criteria, ' ');
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
charcat(&criteria, *s);
|
charcat(&criteria, *s);
|
||||||
break;
|
break;
|
||||||
@ -1526,7 +1544,7 @@ SearchContentDirectory(struct upnphttp * h, const char * action)
|
|||||||
int totalMatches;
|
int totalMatches;
|
||||||
int ret;
|
int ret;
|
||||||
char *ContainerID, *Filter, *SearchCriteria, *SortCriteria;
|
char *ContainerID, *Filter, *SearchCriteria, *SortCriteria;
|
||||||
char *orderBy = NULL;
|
char *orderBy = NULL, *where = NULL;
|
||||||
char groupBy[] = "group by DETAIL_ID";
|
char groupBy[] = "group by DETAIL_ID";
|
||||||
struct NameValueParserData data;
|
struct NameValueParserData data;
|
||||||
int RequestedCount = 0;
|
int RequestedCount = 0;
|
||||||
@ -1604,8 +1622,11 @@ SearchContentDirectory(struct upnphttp * h, const char * action)
|
|||||||
else if( strcmp(ContainerID, MUSIC_ALL_ID) == 0 )
|
else if( strcmp(ContainerID, MUSIC_ALL_ID) == 0 )
|
||||||
groupBy[0] = '\0';
|
groupBy[0] = '\0';
|
||||||
|
|
||||||
SearchCriteria = parse_search_criteria(SearchCriteria);
|
if( GETFLAG(DLNA_STRICT_MASK) )
|
||||||
DPRINTF(E_DEBUG, L_HTTP, "Translated SearchCriteria: %s\n", SearchCriteria);
|
groupBy[0] = '\0';
|
||||||
|
|
||||||
|
where = parse_search_criteria(SearchCriteria);
|
||||||
|
DPRINTF(E_DEBUG, L_HTTP, "Translated SearchCriteria: %s\n", where);
|
||||||
|
|
||||||
totalMatches = sql_get_int_field(db, "SELECT (select count(distinct DETAIL_ID)"
|
totalMatches = sql_get_int_field(db, "SELECT (select count(distinct DETAIL_ID)"
|
||||||
" from OBJECTS o left join DETAILS d on (o.DETAIL_ID = d.ID)"
|
" from OBJECTS o left join DETAILS d on (o.DETAIL_ID = d.ID)"
|
||||||
@ -1613,7 +1634,7 @@ SearchContentDirectory(struct upnphttp * h, const char * action)
|
|||||||
" + "
|
" + "
|
||||||
"(select count(*) from OBJECTS o left join DETAILS d on (o.DETAIL_ID = d.ID)"
|
"(select count(*) from OBJECTS o left join DETAILS d on (o.DETAIL_ID = d.ID)"
|
||||||
" where (OBJECT_ID = '%q') and (%s))",
|
" where (OBJECT_ID = '%q') and (%s))",
|
||||||
ContainerID, SearchCriteria, ContainerID, SearchCriteria);
|
ContainerID, where, ContainerID, where);
|
||||||
if( totalMatches < 0 )
|
if( totalMatches < 0 )
|
||||||
{
|
{
|
||||||
/* Must be invalid SQL, so most likely bad or unhandled search criteria. */
|
/* Must be invalid SQL, so most likely bad or unhandled search criteria. */
|
||||||
@ -1648,11 +1669,11 @@ SearchContentDirectory(struct upnphttp * h, const char * action)
|
|||||||
" where OBJECT_ID glob '%q$*' and (%s) %s "
|
" where OBJECT_ID glob '%q$*' and (%s) %s "
|
||||||
"%z %s"
|
"%z %s"
|
||||||
" limit %d, %d",
|
" limit %d, %d",
|
||||||
ContainerID, SearchCriteria, groupBy,
|
ContainerID, where, groupBy,
|
||||||
(*ContainerID == '*') ? NULL :
|
(*ContainerID == '*') ? NULL :
|
||||||
sqlite3_mprintf("UNION ALL " SELECT_COLUMNS
|
sqlite3_mprintf("UNION ALL " SELECT_COLUMNS
|
||||||
"from OBJECTS o left join DETAILS d on (d.ID = o.DETAIL_ID)"
|
"from OBJECTS o left join DETAILS d on (d.ID = o.DETAIL_ID)"
|
||||||
" where OBJECT_ID = '%q' and (%s) ", ContainerID, SearchCriteria),
|
" where OBJECT_ID = '%q' and (%s) ", ContainerID, where),
|
||||||
orderBy, StartingIndex, RequestedCount);
|
orderBy, StartingIndex, RequestedCount);
|
||||||
DPRINTF(E_DEBUG, L_HTTP, "Search SQL: %s\n", sql);
|
DPRINTF(E_DEBUG, L_HTTP, "Search SQL: %s\n", sql);
|
||||||
ret = sqlite3_exec(db, sql, callback, (void *) &args, &zErrMsg);
|
ret = sqlite3_exec(db, sql, callback, (void *) &args, &zErrMsg);
|
||||||
@ -1674,7 +1695,7 @@ search_error:
|
|||||||
if( args.flags & FLAG_FREE_OBJECT_ID )
|
if( args.flags & FLAG_FREE_OBJECT_ID )
|
||||||
sqlite3_free(ContainerID);
|
sqlite3_free(ContainerID);
|
||||||
free(orderBy);
|
free(orderBy);
|
||||||
free(SearchCriteria);
|
free(where);
|
||||||
free(str.data);
|
free(str.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user