X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=mysql_selector.c;h=b2a925e09311a6cc71bf45c488c73eca8a163e99;hp=0eb19bc58da2f7d78681a793efb746cc0b14bc00;hb=5430c77f1fdf97d92796f44623d257b8124bde24;hpb=37dd76b70c9ca6459c483653c1a1d1cc9f32237c diff --git a/mysql_selector.c b/mysql_selector.c index 0eb19bc5..b2a925e0 100644 --- a/mysql_selector.c +++ b/mysql_selector.c @@ -25,9 +25,10 @@ #include "server.cmdline.h" #include "server.h" #include "vss.h" -#include "db.h" +#include "afs.h" #include #include +#include #include "error.h" #include "net.h" #include "string.h" @@ -39,7 +40,19 @@ extern struct misc_meta_data *mmd; static void *mysql_ptr = NULL; -static struct para_macro macro_list[] = { +/** + * contains name/replacement pairs used by s_a_r_list() + * + * \sa s_a_r() + */ +struct para_macro { + /** the name of the macro */ + const char *name; + /** the replacement text */ + const char *replacement; +}; + +static const struct para_macro mysql_macro_list[] = { { .name = "IS_N_SET", .replacement = "(data.%s != '1')" }, { @@ -63,6 +76,94 @@ static struct para_macro macro_list[] = { } }; +/** + * simple search and replace routine + * + * \param src source string + * \param macro_name the name of the macro + * \param replacement the replacement format string + * + * In \p src, replace each occurence of \p macro_name(arg) by the string + * determined by the \p replacement format string. \p replacement may (but + * needs not) contain a single string conversion specifier (%s) which gets + * replaced by \p arg. + * + * \return A string in which all matches in \p src are replaced, or \p NULL if + * an syntax error was encountered. Caller must free the result. + * + * \sa regcomp(3) + */ +__must_check __malloc static char *s_a_r(const char *src, const char* macro_name, + const char *replacement) +{ + regex_t preg; + size_t nmatch = 1; + regmatch_t pmatch[1]; + int eflags = 0; + char *dest = NULL; + const char *bufptr = src; + + if (!macro_name || !replacement || !src) + return para_strdup(src); + regcomp(&preg, macro_name, 0); + while (regexec(&preg, bufptr, nmatch, pmatch, eflags) + != REG_NOMATCH) { + char *tmp, *arg, *o_bracket, *c_bracket; + + o_bracket = strchr(bufptr + pmatch[0].rm_so, '('); + c_bracket = o_bracket? strchr(o_bracket, ')') : NULL; + if (!c_bracket) + goto out; + tmp = para_strdup(bufptr); + tmp[pmatch[0].rm_so] = '\0'; + dest = para_strcat(dest, tmp); + free(tmp); + + arg = para_strdup(o_bracket + 1); + arg[c_bracket - o_bracket - 1] = '\0'; + tmp = make_message(replacement, arg); + free(arg); + dest = para_strcat(dest, tmp); + free(tmp); + bufptr = c_bracket; + bufptr++; + } + dest = para_strcat(dest, bufptr); +// PARA_DEBUG_LOG("%s: returning %s\n", __func__, dest); +out: + regfree(&preg); + return dest; +} + +/** + * replace a string according to a list of macros + * + * \param macro_list the array containing a macro/replacement pairs. + * \param src the source string + * + * This function just calls s_a_r() for each element of \p macro_list. + * + * \return \p NULL if one of the underlying calls to \p s_a_r returned \p NULL. + * Otherwise the completely expanded version of \p src is returned. + */ +__must_check __malloc static char *s_a_r_list(const struct para_macro *macro_list, + char *src) +{ + const struct para_macro *mp = macro_list; + char *ret = NULL, *tmp = para_strdup(src); + + while (mp->name) { + ret = s_a_r(tmp, mp->name, mp->replacement); + free(tmp); + if (!ret) /* syntax error */ + return NULL; + tmp = ret; + mp++; + } + //PARA_DEBUG_LOG("%s: returning %s\n", __func__, dest); + return ret; +} + static int real_query(const char *query) { if (!mysql_ptr) @@ -359,7 +460,8 @@ int com_laa(int fd, int argc, __a_unused char *argv[]) /* * history */ -int com_hist(int fd, int argc, char *argv[]) { +int com_hist(int fd, int argc, char *argv[]) +{ int ret; void *result = NULL; char *q, *atts; @@ -437,7 +539,7 @@ int com_mbox(int fd, int argc, char *argv[]) if (!row[0]) goto out; - tmp = make_message("%s X-Attribute-%s: ', %s, '\n", query, + tmp = make_message("%sX-Attribute-%s: ', %s, '\n", query, row[0], row[0]); free(query); query = tmp; @@ -477,40 +579,38 @@ out: return ret; } -/* get attributes by name. If verbose is not 0, get_a writes a string - * into atts of the form 'att1="0",att2="1"', which is used in com_cam - * for contructing a mysql update query. - * never returns NULL in *NON VERBOSE* mode +/* + * get attributes by name. If verbose is not 0, this function returns a string + * of the form 'att1="0",att2="1"'... which is used in com_cam() for + * constructing a mysql update query. Otherwise the space-separated list of all + * attributes which are set in the audio file given by name is returned. Never + * returns NULL in *NON VERBOSE* mode. */ static char *get_atts(char *name, int verbose) { char *atts = NULL, *buf, *ebn; void *result = NULL, *result2 = NULL; MYSQL_ROW row, row2; - int i, ret; - unsigned int num_fields; + int i; + unsigned num_fields; - ret = -E_NOATTS; result2 = get_all_attributes(); if (!result2) goto out; - ret = -E_ESCAPE; - if (!(ebn = escaped_basename(name))) + ebn = escaped_basename(name); + if (!ebn) goto out; buf = make_message("select * from data where name='%s'", ebn); free(ebn); - ret = -E_NORESULT; result = get_result(buf); free(buf); if (!result) goto out; - ret = -E_EMPTY_RESULT; num_fields = mysql_num_fields(result); if (num_fields < 5) goto out; mysql_data_seek(result2, 4); /* skip Lastplayed, Numplayed... */ row = mysql_fetch_row(result); - ret = -E_NOROW; if (!row) goto out; for (i = 4; i < num_fields; i++) { @@ -525,7 +625,6 @@ static char *get_atts(char *name, int verbose) if (verbose) atts = para_strcat(atts, is_set? "=\"1\"" : "=\"0\""); } - ret = 1; out: if (result2) mysql_free_result(result2); @@ -687,7 +786,7 @@ static char *get_query(char *streamname, char *filename, int with_path) continue; arg = line + n; if (!strcmp(command, "accept:")) { - char *tmp2 = s_a_r_list(macro_list, arg); + char *tmp2 = s_a_r_list(mysql_macro_list, arg); if (accept_opts) accept_opts = para_strcat( accept_opts, " or "); @@ -696,7 +795,7 @@ static char *get_query(char *streamname, char *filename, int with_path) continue; } if (!strcmp(command, "deny:")) { - char *tmp2 = s_a_r_list(macro_list, arg); + char *tmp2 = s_a_r_list(mysql_macro_list, arg); if (deny_opts) deny_opts = para_strcat(deny_opts, " or "); deny_opts = para_strcat(deny_opts, tmp2); @@ -704,10 +803,10 @@ static char *get_query(char *streamname, char *filename, int with_path) continue; } if (!score && !strcmp(command, "score:")) - score = s_a_r_list(macro_list, arg); + score = s_a_r_list(mysql_macro_list, arg); } if (!score) { - score = s_a_r_list(macro_list, conf.mysql_default_score_arg); + score = s_a_r_list(mysql_macro_list, conf.mysql_default_score_arg); if (!score) goto out; } @@ -801,7 +900,6 @@ write: return info; } - /* might return NULL */ static char *get_current_audio_file(void) { @@ -812,11 +910,34 @@ static char *get_current_audio_file(void) return name; } +/* If called as child, mmd_lock must be held */ +static void update_mmd(char *info) +{ + PARA_DEBUG_LOG("%s", "updating shared memory area\n"); + strncpy(mmd->selector_info, info, MMD_INFO_SIZE - 1); + mmd->selector_info[MMD_INFO_SIZE - 1] = '\0'; +} + +static void refresh_selector_info(void) +{ + char *name = get_current_audio_file(); + char *info; + + if (!name) + return; + info = get_selector_info(name); + free(name); + mmd_lock(); + update_mmd(info); + mmd_unlock(); + free(info); +} + /* list attributes / print database info */ static int com_la_info(int fd, int argc, char *argv[]) { char *name = NULL, *meta = NULL, *atts = NULL, *dir = NULL; - int ret, com_la = strcmp(argv[0], "info"); + int ret, la = strcmp(argv[0], "info"); if (argc < 2) { ret = -E_GET_AUDIO_FILE; @@ -833,7 +954,7 @@ static int com_la_info(int fd, int argc, char *argv[]) meta = get_meta(name, 1); atts = get_atts(name, 0); dir = get_dir(name); - if (com_la) + if (la) ret = send_va_buffer(fd, "%s\n", atts); else ret = send_va_buffer(fd, "dir: %s\n" "%s\n" "attributes: %s\n", @@ -1087,7 +1208,10 @@ int com_picass(int fd, int argc, char *argv[]) */ int com_snp(int fd, int argc, char *argv[]) { - return com_set(fd, argc, argv); + int ret = com_set(fd, argc, argv); + if (ret >= 0) + refresh_selector_info(); + return ret; } /* @@ -1364,14 +1488,6 @@ out: return ret; } -/* If called as child, mmd_lock must be held */ -static void update_mmd(char *info) -{ - PARA_DEBUG_LOG("%s", "updating shared memory area\n"); - strncpy(mmd->selector_info, info, MMD_INFO_SIZE - 1); - mmd->selector_info[MMD_INFO_SIZE - 1] = '\0'; -} - static void update_audio_file_server_handler(char *name) { char *info; @@ -1393,24 +1509,11 @@ int com_us(__a_unused int fd, int argc, char *argv[]) return -E_ESCAPE; ret = update_audio_file(argv[1]); free(tmp); + if (ret >= 0) + refresh_selector_info(); return ret; } -static void refresh_selector_info(void) -{ - char *name = get_current_audio_file(); - char *info; - - if (!name) - return; - info = get_selector_info(name); - free(name); - mmd_lock(); - update_mmd(info); - mmd_unlock(); - free(info); -} - /* select previous / next stream */ static int com_ps_ns(__a_unused int fd, int argc, char *argv[]) {