* Move SearchCriteria parsing to its own function.
This commit is contained in:
parent
2d0ae24009
commit
b15a5d144d
@ -688,7 +688,7 @@ start_inotify()
|
|||||||
i += EVENT_SIZE + event->len;
|
i += EVENT_SIZE + event->len;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
esc_name = modifyString(strdup(event->name), "&", "&", 0);
|
esc_name = modifyString(strdup(event->name), "&", "&");
|
||||||
sprintf(path_buf, "%s/%s", get_path_from_wd(event->wd), event->name);
|
sprintf(path_buf, "%s/%s", get_path_from_wd(event->wd), event->name);
|
||||||
if ( event->mask & IN_ISDIR && (event->mask & (IN_CREATE|IN_MOVED_TO)) )
|
if ( event->mask & IN_ISDIR && (event->mask & (IN_CREATE|IN_MOVED_TO)) )
|
||||||
{
|
{
|
||||||
|
@ -82,9 +82,6 @@ typedef enum {
|
|||||||
int
|
int
|
||||||
ends_with(const char *haystack, const char *needle);
|
ends_with(const char *haystack, const char *needle);
|
||||||
|
|
||||||
char *
|
|
||||||
modifyString(char *string, const char *before, const char *after, short like);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
check_for_captions(const char *path, int64_t detailID);
|
check_for_captions(const char *path, int64_t detailID);
|
||||||
|
|
||||||
|
@ -233,7 +233,7 @@ found:
|
|||||||
DPRINTF(E_DEBUG, L_SCANNER, "- %s not found in db\n", fname);
|
DPRINTF(E_DEBUG, L_SCANNER, "- %s not found in db\n", fname);
|
||||||
if( strchr(fname, '\\') )
|
if( strchr(fname, '\\') )
|
||||||
{
|
{
|
||||||
fname = modifyString(fname, "\\", "/", 0);
|
fname = modifyString(fname, "\\", "/");
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
else if( (fname = strchr(fname, '/')) )
|
else if( (fname = strchr(fname, '/')) )
|
||||||
|
@ -96,11 +96,11 @@ SendRootContainer(struct upnphttp *h)
|
|||||||
static char *
|
static char *
|
||||||
unescape_tag(char *tag)
|
unescape_tag(char *tag)
|
||||||
{
|
{
|
||||||
modifyString(tag, "&", "&", 0);
|
modifyString(tag, "&", "&");
|
||||||
modifyString(tag, "&amp;lt;", "<", 0);
|
modifyString(tag, "&amp;lt;", "<");
|
||||||
modifyString(tag, "&lt;", "<", 0);
|
modifyString(tag, "&lt;", "<");
|
||||||
modifyString(tag, "&amp;gt;", ">", 0);
|
modifyString(tag, "&amp;gt;", ">");
|
||||||
modifyString(tag, "&gt;", ">", 0);
|
modifyString(tag, "&gt;", ">");
|
||||||
return tag;
|
return tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
297
upnpsoap.c
297
upnpsoap.c
@ -1333,6 +1333,254 @@ browse_error:
|
|||||||
free(str.data);
|
free(str.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
charcat(struct string_s *str, char c)
|
||||||
|
{
|
||||||
|
if (str->size <= str->off)
|
||||||
|
{
|
||||||
|
str->data[str->size-1] = '\0';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
str->data[str->off] = c;
|
||||||
|
str->off += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline char *
|
||||||
|
parse_search_criteria(const char *str)
|
||||||
|
{
|
||||||
|
struct string_s criteria;
|
||||||
|
int len;
|
||||||
|
int literal = 0, like = 0;
|
||||||
|
const char *s;
|
||||||
|
|
||||||
|
if (!str)
|
||||||
|
return strdup("1 = 1");
|
||||||
|
|
||||||
|
len = strlen(str) + 32;
|
||||||
|
criteria.data = malloc(len);
|
||||||
|
criteria.size = len;
|
||||||
|
criteria.off = 0;
|
||||||
|
|
||||||
|
s = str;
|
||||||
|
|
||||||
|
while (isspace(*s))
|
||||||
|
s++;
|
||||||
|
|
||||||
|
while (*s)
|
||||||
|
{
|
||||||
|
if (literal)
|
||||||
|
{
|
||||||
|
switch (*s) {
|
||||||
|
case '&':
|
||||||
|
if (strncmp(s, """, 6) == 0)
|
||||||
|
s += 5;
|
||||||
|
else if (strncmp(s, "'", 6) == 0)
|
||||||
|
{
|
||||||
|
strcatf(&criteria, "'");
|
||||||
|
s += 6;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
case '"':
|
||||||
|
literal = 0;
|
||||||
|
if (like)
|
||||||
|
{
|
||||||
|
charcat(&criteria, '%');
|
||||||
|
like--;
|
||||||
|
}
|
||||||
|
charcat(&criteria, '"');
|
||||||
|
break;
|
||||||
|
case '\\':
|
||||||
|
if (strncmp(s, "\\"", 7) == 0)
|
||||||
|
{
|
||||||
|
strcatf(&criteria, "&quot;");
|
||||||
|
s += 7;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'o':
|
||||||
|
if (strncmp(s, "object.", 7) == 0)
|
||||||
|
s += 7;
|
||||||
|
default:
|
||||||
|
charcat(&criteria, *s);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (*s) {
|
||||||
|
case '\\':
|
||||||
|
if (strncmp(s, "\\"", 7) == 0)
|
||||||
|
{
|
||||||
|
strcatf(&criteria, "&quot;");
|
||||||
|
s += 7;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
charcat(&criteria, *s);
|
||||||
|
break;
|
||||||
|
case '"':
|
||||||
|
literal = 1;
|
||||||
|
charcat(&criteria, *s);
|
||||||
|
if (like == 2)
|
||||||
|
{
|
||||||
|
charcat(&criteria, '%');
|
||||||
|
like--;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '&':
|
||||||
|
if (strncmp(s, """, 6) == 0)
|
||||||
|
{
|
||||||
|
literal = 1;
|
||||||
|
strcatf(&criteria, "\"");
|
||||||
|
if (like == 2)
|
||||||
|
{
|
||||||
|
charcat(&criteria, '%');
|
||||||
|
like--;
|
||||||
|
}
|
||||||
|
s += 5;
|
||||||
|
}
|
||||||
|
else if (strncmp(s, "'", 6) == 0)
|
||||||
|
{
|
||||||
|
strcatf(&criteria, "'");
|
||||||
|
s += 5;
|
||||||
|
}
|
||||||
|
else if (strncmp(s, "<", 4) == 0)
|
||||||
|
{
|
||||||
|
strcatf(&criteria, "<");
|
||||||
|
s += 3;
|
||||||
|
}
|
||||||
|
else if (strncmp(s, ">", 4) == 0)
|
||||||
|
{
|
||||||
|
strcatf(&criteria, ">");
|
||||||
|
s += 3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
charcat(&criteria, *s);
|
||||||
|
break;
|
||||||
|
case '@':
|
||||||
|
if (strncmp(s, "@refID", 6) == 0)
|
||||||
|
{
|
||||||
|
strcatf(&criteria, "REF_ID");
|
||||||
|
s += 6;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (strncmp(s, "@id", 3) == 0)
|
||||||
|
{
|
||||||
|
strcatf(&criteria, "OBJECT_ID");
|
||||||
|
s += 3;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
charcat(&criteria, *s);
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
if (strncmp(s, "contains", 8) == 0)
|
||||||
|
{
|
||||||
|
strcatf(&criteria, "like");
|
||||||
|
s += 8;
|
||||||
|
like = 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
charcat(&criteria, *s);
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
if (strncmp(s, "derivedfrom", 11) == 0)
|
||||||
|
{
|
||||||
|
strcatf(&criteria, "like");
|
||||||
|
s += 11;
|
||||||
|
like = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (strncmp(s, "dc:date", 7) == 0)
|
||||||
|
{
|
||||||
|
strcatf(&criteria, "d.DATE");
|
||||||
|
s += 7;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (strncmp(s, "dc:title", 8) == 0)
|
||||||
|
{
|
||||||
|
strcatf(&criteria, "d.TITLE");
|
||||||
|
s += 8;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (strncmp(s, "dc:creator", 10) == 0)
|
||||||
|
{
|
||||||
|
strcatf(&criteria, "d.CREATOR");
|
||||||
|
s += 10;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
charcat(&criteria, *s);
|
||||||
|
break;
|
||||||
|
case 'e':
|
||||||
|
if (strncmp(s, "exists", 6) == 0)
|
||||||
|
{
|
||||||
|
s += 6;
|
||||||
|
while (isspace(*s))
|
||||||
|
s++;
|
||||||
|
if (strncmp(s, "true", 4) == 0)
|
||||||
|
{
|
||||||
|
strcatf(&criteria, "is not NULL");
|
||||||
|
s += 3;
|
||||||
|
}
|
||||||
|
else if (strncmp(s, "false", 5) == 0)
|
||||||
|
{
|
||||||
|
strcatf(&criteria, "is NULL");
|
||||||
|
s += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
charcat(&criteria, *s);
|
||||||
|
break;
|
||||||
|
case 'u':
|
||||||
|
if (strncmp(s, "upnp:class", 10) == 0)
|
||||||
|
{
|
||||||
|
strcatf(&criteria, "o.CLASS");
|
||||||
|
s += 10;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (strncmp(s, "upnp:actor", 10) == 0)
|
||||||
|
{
|
||||||
|
strcatf(&criteria, "d.ARTIST");
|
||||||
|
s += 10;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (strncmp(s, "upnp:artist", 11) == 0)
|
||||||
|
{
|
||||||
|
strcatf(&criteria, "d.ARTIST");
|
||||||
|
s += 11;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (strncmp(s, "upnp:album", 10) == 0)
|
||||||
|
{
|
||||||
|
strcatf(&criteria, "d.ALBUM");
|
||||||
|
s += 10;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (strncmp(s, "upnp:genre", 10) == 0)
|
||||||
|
{
|
||||||
|
strcatf(&criteria, "d.GENRE");
|
||||||
|
s += 10;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
charcat(&criteria, *s);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
charcat(&criteria, *s);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
charcat(&criteria, '\0');
|
||||||
|
|
||||||
|
return criteria.data;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
SearchContentDirectory(struct upnphttp * h, const char * action)
|
SearchContentDirectory(struct upnphttp * h, const char * action)
|
||||||
{
|
{
|
||||||
@ -1349,7 +1597,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 *newSearchCriteria = NULL, *orderBy = NULL;
|
char *orderBy = 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;
|
||||||
@ -1426,49 +1674,8 @@ SearchContentDirectory(struct upnphttp * h, const char * action)
|
|||||||
*ContainerID = '*';
|
*ContainerID = '*';
|
||||||
else if( strcmp(ContainerID, MUSIC_ALL_ID) == 0 )
|
else if( strcmp(ContainerID, MUSIC_ALL_ID) == 0 )
|
||||||
groupBy[0] = '\0';
|
groupBy[0] = '\0';
|
||||||
if( !SearchCriteria )
|
|
||||||
{
|
SearchCriteria = parse_search_criteria(SearchCriteria);
|
||||||
newSearchCriteria = strdup("1 = 1");
|
|
||||||
SearchCriteria = newSearchCriteria;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SearchCriteria = modifyString(SearchCriteria, """, "\"", 0);
|
|
||||||
SearchCriteria = modifyString(SearchCriteria, "'", "'", 0);
|
|
||||||
SearchCriteria = modifyString(SearchCriteria, "<", "<", 0);
|
|
||||||
SearchCriteria = modifyString(SearchCriteria, ">", ">", 0);
|
|
||||||
SearchCriteria = modifyString(SearchCriteria, "object.", "", 0);
|
|
||||||
SearchCriteria = modifyString(SearchCriteria, "derivedfrom", "like", 1);
|
|
||||||
SearchCriteria = modifyString(SearchCriteria, "contains", "like", 2);
|
|
||||||
SearchCriteria = modifyString(SearchCriteria, "dc:date", "d.DATE", 0);
|
|
||||||
SearchCriteria = modifyString(SearchCriteria, "dc:title", "d.TITLE", 0);
|
|
||||||
SearchCriteria = modifyString(SearchCriteria, "dc:creator", "d.CREATOR", 0);
|
|
||||||
SearchCriteria = modifyString(SearchCriteria, "upnp:class", "o.CLASS", 0);
|
|
||||||
SearchCriteria = modifyString(SearchCriteria, "upnp:actor", "d.ARTIST", 0);
|
|
||||||
SearchCriteria = modifyString(SearchCriteria, "upnp:artist", "d.ARTIST", 0);
|
|
||||||
SearchCriteria = modifyString(SearchCriteria, "upnp:album", "d.ALBUM", 0);
|
|
||||||
SearchCriteria = modifyString(SearchCriteria, "upnp:genre", "d.GENRE", 0);
|
|
||||||
SearchCriteria = modifyString(SearchCriteria, "exists true", "is not NULL", 0);
|
|
||||||
SearchCriteria = modifyString(SearchCriteria, "exists false", "is NULL", 0);
|
|
||||||
SearchCriteria = modifyString(SearchCriteria, "@refID", "REF_ID", 0);
|
|
||||||
if( strstr(SearchCriteria, "@id") )
|
|
||||||
{
|
|
||||||
newSearchCriteria = strdup(SearchCriteria);
|
|
||||||
SearchCriteria = newSearchCriteria = modifyString(newSearchCriteria, "@id", "OBJECT_ID", 0);
|
|
||||||
}
|
|
||||||
if( strstr(SearchCriteria, "res is ") )
|
|
||||||
{
|
|
||||||
if( !newSearchCriteria )
|
|
||||||
newSearchCriteria = strdup(SearchCriteria);
|
|
||||||
SearchCriteria = newSearchCriteria = modifyString(newSearchCriteria, "res is ", "MIME is ", 0);
|
|
||||||
}
|
|
||||||
if( strstr(SearchCriteria, "\\\"") )
|
|
||||||
{
|
|
||||||
if( !newSearchCriteria )
|
|
||||||
newSearchCriteria = strdup(SearchCriteria);
|
|
||||||
SearchCriteria = newSearchCriteria = modifyString(newSearchCriteria, "\\\"", "&quot;", 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DPRINTF(E_DEBUG, L_HTTP, "Translated SearchCriteria: %s\n", SearchCriteria);
|
DPRINTF(E_DEBUG, L_HTTP, "Translated SearchCriteria: %s\n", SearchCriteria);
|
||||||
|
|
||||||
totalMatches = sql_get_int_field(db, "SELECT (select count(distinct DETAIL_ID)"
|
totalMatches = sql_get_int_field(db, "SELECT (select count(distinct DETAIL_ID)"
|
||||||
@ -1538,7 +1745,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(newSearchCriteria);
|
free(SearchCriteria);
|
||||||
free(str.data);
|
free(str.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
34
utils.c
34
utils.c
@ -164,14 +164,14 @@ strcasestrc(const char *s, const char *p, const char t)
|
|||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
modifyString(char * string, const char * before, const char * after, short like)
|
modifyString(char * string, const char * before, const char * after)
|
||||||
{
|
{
|
||||||
int oldlen, newlen, chgcnt = 0;
|
int oldlen, newlen, chgcnt = 0;
|
||||||
char *s, *p, *t;
|
char *s, *p;
|
||||||
|
|
||||||
oldlen = strlen(before);
|
oldlen = strlen(before);
|
||||||
newlen = strlen(after);
|
newlen = strlen(after);
|
||||||
if( newlen+like > oldlen )
|
if( newlen > oldlen )
|
||||||
{
|
{
|
||||||
s = string;
|
s = string;
|
||||||
while( (p = strstr(s, before)) )
|
while( (p = strstr(s, before)) )
|
||||||
@ -179,7 +179,7 @@ modifyString(char * string, const char * before, const char * after, short like)
|
|||||||
chgcnt++;
|
chgcnt++;
|
||||||
s = p+oldlen;
|
s = p+oldlen;
|
||||||
}
|
}
|
||||||
s = realloc(string, strlen(string)+((newlen-oldlen)*chgcnt)+1+like);
|
s = realloc(string, strlen(string)+((newlen-oldlen)*chgcnt)+1);
|
||||||
/* If we failed to realloc, return the original alloc'd string */
|
/* If we failed to realloc, return the original alloc'd string */
|
||||||
if( s )
|
if( s )
|
||||||
string = s;
|
string = s;
|
||||||
@ -195,24 +195,6 @@ modifyString(char * string, const char * before, const char * after, short like)
|
|||||||
return string;
|
return string;
|
||||||
memmove(p + newlen, p + oldlen, strlen(p + oldlen) + 1);
|
memmove(p + newlen, p + oldlen, strlen(p + oldlen) + 1);
|
||||||
memcpy(p, after, newlen);
|
memcpy(p, after, newlen);
|
||||||
if( like )
|
|
||||||
{
|
|
||||||
t = p+newlen;
|
|
||||||
while( isspace(*t) )
|
|
||||||
t++;
|
|
||||||
if( *t == '"' )
|
|
||||||
{
|
|
||||||
if( like == 2 )
|
|
||||||
{
|
|
||||||
memmove(t+2, t+1, strlen(t+1)+1);
|
|
||||||
*++t = '%';
|
|
||||||
}
|
|
||||||
while( *++t != '"' )
|
|
||||||
continue;
|
|
||||||
memmove(t+1, t, strlen(t)+1);
|
|
||||||
*t = '%';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s = p + newlen;
|
s = p + newlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -227,10 +209,10 @@ escape_tag(const char *tag, int force_alloc)
|
|||||||
if( strchr(tag, '&') || strchr(tag, '<') || strchr(tag, '>') || strchr(tag, '"') )
|
if( strchr(tag, '&') || strchr(tag, '<') || strchr(tag, '>') || strchr(tag, '"') )
|
||||||
{
|
{
|
||||||
esc_tag = strdup(tag);
|
esc_tag = strdup(tag);
|
||||||
esc_tag = modifyString(esc_tag, "&", "&amp;", 0);
|
esc_tag = modifyString(esc_tag, "&", "&amp;");
|
||||||
esc_tag = modifyString(esc_tag, "<", "&lt;", 0);
|
esc_tag = modifyString(esc_tag, "<", "&lt;");
|
||||||
esc_tag = modifyString(esc_tag, ">", "&gt;", 0);
|
esc_tag = modifyString(esc_tag, ">", "&gt;");
|
||||||
esc_tag = modifyString(esc_tag, "\"", "&quot;", 0);
|
esc_tag = modifyString(esc_tag, "\"", "&quot;");
|
||||||
}
|
}
|
||||||
else if( force_alloc )
|
else if( force_alloc )
|
||||||
esc_tag = strdup(tag);
|
esc_tag = strdup(tag);
|
||||||
|
2
utils.h
2
utils.h
@ -48,7 +48,7 @@ char *
|
|||||||
strcasestrc(const char *s, const char *p, const char t);
|
strcasestrc(const char *s, const char *p, const char t);
|
||||||
|
|
||||||
char *
|
char *
|
||||||
modifyString(char * string, const char * before, const char * after, short like);
|
modifyString(char * string, const char * before, const char * after);
|
||||||
|
|
||||||
char *
|
char *
|
||||||
escape_tag(const char *tag, int force_alloc);
|
escape_tag(const char *tag, int force_alloc);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user