* Move SearchCriteria parsing to its own function.

This commit is contained in:
Justin Maggard 2012-07-28 01:17:30 +00:00
parent 2d0ae24009
commit b15a5d144d
7 changed files with 268 additions and 82 deletions

View File

@ -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)) )
{

View File

@ -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);

View File

@ -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, '/')) )

View File

@ -96,11 +96,11 @@ SendRootContainer(struct upnphttp *h)
static char *
unescape_tag(char *tag)
{
modifyString(tag, "&", "&", 0);
modifyString(tag, "<", "<", 0);
modifyString(tag, "<", "<", 0);
modifyString(tag, ">", ">", 0);
modifyString(tag, ">", ">", 0);
modifyString(tag, "&", "&");
modifyString(tag, "<", "<");
modifyString(tag, "<", "<");
modifyString(tag, ">", ">");
modifyString(tag, ">", ">");
return tag;
}

View File

@ -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, "&quot;", 6) == 0)
s += 5;
else if (strncmp(s, "&apos;", 6) == 0)
{
strcatf(&criteria, "'");
s += 6;
continue;
}
else
break;
case '"':
literal = 0;
if (like)
{
charcat(&criteria, '%');
like--;
}
charcat(&criteria, '"');
break;
case '\\':
if (strncmp(s, "\\&quot;", 7) == 0)
{
strcatf(&criteria, "&amp;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, "\\&quot;", 7) == 0)
{
strcatf(&criteria, "&amp;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, "&quot;", 6) == 0)
{
literal = 1;
strcatf(&criteria, "\"");
if (like == 2)
{
charcat(&criteria, '%');
like--;
}
s += 5;
}
else if (strncmp(s, "&apos;", 6) == 0)
{
strcatf(&criteria, "'");
s += 5;
}
else if (strncmp(s, "&lt;", 4) == 0)
{
strcatf(&criteria, "<");
s += 3;
}
else if (strncmp(s, "&gt;", 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, "&quot;", "\"", 0);
SearchCriteria = modifyString(SearchCriteria, "&apos;", "'", 0);
SearchCriteria = modifyString(SearchCriteria, "&lt;", "<", 0);
SearchCriteria = modifyString(SearchCriteria, "&gt;", ">", 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, "\\\"", "&amp;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
View File

@ -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;amp;", 0);
esc_tag = modifyString(esc_tag, "<", "&amp;lt;", 0);
esc_tag = modifyString(esc_tag, ">", "&amp;gt;", 0);
esc_tag = modifyString(esc_tag, "\"", "&amp;quot;", 0);
esc_tag = modifyString(esc_tag, "&", "&amp;amp;");
esc_tag = modifyString(esc_tag, "<", "&amp;lt;");
esc_tag = modifyString(esc_tag, ">", "&amp;gt;");
esc_tag = modifyString(esc_tag, "\"", "&amp;quot;");
}
else if( force_alloc )
esc_tag = strdup(tag);

View File

@ -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);