From 07a6c2c8430a2c2386dc9063fbaa353a73abb78c Mon Sep 17 00:00:00 2001 From: Viktor Semykin Date: Tue, 8 Jun 2010 20:30:55 +0300 Subject: shell commands are really working now --- plugins/shellexec/shellexec.c | 109 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 106 insertions(+), 3 deletions(-) (limited to 'plugins/shellexec') diff --git a/plugins/shellexec/shellexec.c b/plugins/shellexec/shellexec.c index 178add2e..f576ca9b 100644 --- a/plugins/shellexec/shellexec.c +++ b/plugins/shellexec/shellexec.c @@ -46,12 +46,115 @@ trim (char* s) return h; } +static int +shell_quote (const char *source, char *dest) +{ + char *sp, *dp; + + for (sp = source, dp = dest; *sp; sp++, dp++) + { + if (*sp == '\'') + { + strcpy (dp, "'\\''"); + dp += 3; + } + else + *dp = *sp; + } + *dp = 0; +} + + +/* + format_shell_command function + Similarly to db_format_title formats track's string + and quotes all fields to make them safe for shell + + %a, %t, %b, %B, %C, %n, %N, %y, %g, %c, %r are handled. Use double-% to + skip field. + + + Example: + + Format string: + echo %a - %t %%a - %%t + + Output: + echo 'Blind Faith' - 'Can'\''t Find My Way Home' %a - %t +*/ +static const char* +format_shell_command (DB_playItem_t *it, const char *format) +{ + char *p; + const char *trailing = format; + const char *field; + char *res, *res_p; + + res = res_p = malloc (65536); //FIXME: possible heap corruption + + for (;;) + { + p = strchr (trailing, '%'); + if (!p) break; + + switch (*(p+1)) + { + case 'a': field = "artist"; break; + case 't': field = "title"; break; + case 'b': field = "album"; break; + case 'B': field = "band"; break; + case 'C': field = "composer"; break; + case 'n': field = "track"; break; + case 'N': field = "numtracks"; break; + case 'y': field = "year"; break; + case 'g': field = "genre"; break; + case 'c': field = "comment"; break; + case 'r': field = "copyright"; break; + case 'f': break; + default: field = NULL; + } + + if (field == NULL) + { + int l = ((*(p+1) == '%') ? 1 : 0); + trace ("field is null; p: %s; p+1: %s; l: %d; trailing: %s; res_p: %s\n", p, p+1, l, trailing, res_p); + strncpy (res_p, trailing, p-trailing+l); + res_p += (p-trailing+l); + trailing = p+l+1; + trace ("res: %s; trailing: %s\n", res, res_p, trailing); + continue; + } + else + { + const char *meta; + if (*(p+1) == 'f') + meta = it->fname; + else + meta = deadbeef->pl_find_meta (it, field); + + char quoted [strlen (meta) * 4 + 1]; //Worst case is when all chars are single quote + shell_quote (meta, quoted); + + strncpy (res_p, trailing, p-trailing); + res_p += (p-trailing); + *res_p++ = '\''; + strcpy (res_p, quoted); + res_p += strlen (quoted); + *res_p++ = '\''; + trailing = p+2; + } + } + strcpy (res_p, trailing); + return res; +} + static int shx_callback (DB_playItem_t *it, void *data) { - char fmt[1024]; //FIXME: possible stack corruption - deadbeef->pl_format_title (it, -1, fmt, sizeof (fmt), -1, data); - printf ("%s\n", fmt); + const char *cmd = format_shell_command (it, data); + printf ("%s\n", cmd); + system (cmd); + free (cmd); return 0; } -- cgit v1.2.3