* 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;
|
||||
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);
|
||||
if ( event->mask & IN_ISDIR && (event->mask & (IN_CREATE|IN_MOVED_TO)) )
|
||||
{
|
||||
|
@ -82,9 +82,6 @@ typedef enum {
|
||||
int
|
||||
ends_with(const char *haystack, const char *needle);
|
||||
|
||||
char *
|
||||
modifyString(char *string, const char *before, const char *after, short like);
|
||||
|
||||
void
|
||||
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);
|
||||
if( strchr(fname, '\\') )
|
||||
{
|
||||
fname = modifyString(fname, "\\", "/", 0);
|
||||
fname = modifyString(fname, "\\", "/");
|
||||
goto retry;
|
||||
}
|
||||
else if( (fname = strchr(fname, '/')) )
|
||||
|
@ -96,11 +96,11 @@ SendRootContainer(struct upnphttp *h)
|
||||
static char *
|
||||
unescape_tag(char *tag)
|
||||
{
|
||||
modifyString(tag, "&", "&", 0);
|
||||
modifyString(tag, "&amp;lt;", "<", 0);
|
||||
modifyString(tag, "&lt;", "<", 0);
|
||||
modifyString(tag, "&amp;gt;", ">", 0);
|
||||
modifyString(tag, "&gt;", ">", 0);
|
||||
modifyString(tag, "&amp;", "&");
|
||||
modifyString(tag, "&amp;lt;", "<");
|
||||
modifyString(tag, "&lt;", "<");
|
||||
modifyString(tag, "&amp;gt;", ">");
|
||||
modifyString(tag, "&gt;", ">");
|
||||
return tag;
|
||||
}
|
||||
|
||||
|
297
upnpsoap.c
297
upnpsoap.c
@ -1333,6 +1333,254 @@ browse_error:
|
||||
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
|
||||
SearchContentDirectory(struct upnphttp * h, const char * action)
|
||||
{
|
||||
@ -1349,7 +1597,7 @@ SearchContentDirectory(struct upnphttp * h, const char * action)
|
||||
int totalMatches;
|
||||
int ret;
|
||||
char *ContainerID, *Filter, *SearchCriteria, *SortCriteria;
|
||||
char *newSearchCriteria = NULL, *orderBy = NULL;
|
||||
char *orderBy = NULL;
|
||||
char groupBy[] = "group by DETAIL_ID";
|
||||
struct NameValueParserData data;
|
||||
int RequestedCount = 0;
|
||||
@ -1426,49 +1674,8 @@ SearchContentDirectory(struct upnphttp * h, const char * action)
|
||||
*ContainerID = '*';
|
||||
else if( strcmp(ContainerID, MUSIC_ALL_ID) == 0 )
|
||||
groupBy[0] = '\0';
|
||||
if( !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);
|
||||
}
|
||||
}
|
||||
|
||||
SearchCriteria = parse_search_criteria(SearchCriteria);
|
||||
DPRINTF(E_DEBUG, L_HTTP, "Translated SearchCriteria: %s\n", SearchCriteria);
|
||||
|
||||
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 )
|
||||
sqlite3_free(ContainerID);
|
||||
free(orderBy);
|
||||
free(newSearchCriteria);
|
||||
free(SearchCriteria);
|
||||
free(str.data);
|
||||
}
|
||||
|
||||
|
34
utils.c
34
utils.c
@ -164,14 +164,14 @@ strcasestrc(const char *s, const char *p, const char t)
|
||||
}
|
||||
|
||||
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;
|
||||
char *s, *p, *t;
|
||||
char *s, *p;
|
||||
|
||||
oldlen = strlen(before);
|
||||
newlen = strlen(after);
|
||||
if( newlen+like > oldlen )
|
||||
if( newlen > oldlen )
|
||||
{
|
||||
s = string;
|
||||
while( (p = strstr(s, before)) )
|
||||
@ -179,7 +179,7 @@ modifyString(char * string, const char * before, const char * after, short like)
|
||||
chgcnt++;
|
||||
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( s )
|
||||
string = s;
|
||||
@ -195,24 +195,6 @@ modifyString(char * string, const char * before, const char * after, short like)
|
||||
return string;
|
||||
memmove(p + newlen, p + oldlen, strlen(p + oldlen) + 1);
|
||||
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;
|
||||
}
|
||||
|
||||
@ -227,10 +209,10 @@ escape_tag(const char *tag, int force_alloc)
|
||||
if( strchr(tag, '&') || strchr(tag, '<') || strchr(tag, '>') || strchr(tag, '"') )
|
||||
{
|
||||
esc_tag = strdup(tag);
|
||||
esc_tag = modifyString(esc_tag, "&", "&amp;", 0);
|
||||
esc_tag = modifyString(esc_tag, "<", "&lt;", 0);
|
||||
esc_tag = modifyString(esc_tag, ">", "&gt;", 0);
|
||||
esc_tag = modifyString(esc_tag, "\"", "&quot;", 0);
|
||||
esc_tag = modifyString(esc_tag, "&", "&amp;");
|
||||
esc_tag = modifyString(esc_tag, "<", "&lt;");
|
||||
esc_tag = modifyString(esc_tag, ">", "&gt;");
|
||||
esc_tag = modifyString(esc_tag, "\"", "&quot;");
|
||||
}
|
||||
else if( force_alloc )
|
||||
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);
|
||||
|
||||
char *
|
||||
modifyString(char * string, const char * before, const char * after, short like);
|
||||
modifyString(char * string, const char * before, const char * after);
|
||||
|
||||
char *
|
||||
escape_tag(const char *tag, int force_alloc);
|
||||
|
Loading…
x
Reference in New Issue
Block a user