* 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

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