summaryrefslogtreecommitdiff
path: root/plugins/shellexec
diff options
context:
space:
mode:
authorGravatar Viktor Semykin <thesame.ml@gmail.com>2010-06-08 20:30:55 +0300
committerGravatar Viktor Semykin <thesame.ml@gmail.com>2010-06-08 20:30:55 +0300
commit07a6c2c8430a2c2386dc9063fbaa353a73abb78c (patch)
treebaa4d9a2e2e2bd6d9e59f62c886eba4ada068e2e /plugins/shellexec
parentefb881d97347da50e4f4e8ae6c184a37fcb5faa2 (diff)
shell commands are really working now
Diffstat (limited to 'plugins/shellexec')
-rw-r--r--plugins/shellexec/shellexec.c109
1 files changed, 106 insertions, 3 deletions
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
@@ -47,11 +47,114 @@ trim (char* s)
}
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;
}