* Bram Moolenaar <Bram@> [060808 22:52]: > ! call system(a:cmd . " '" . nmt . "'") This patch is evil (>:-E~~~). Better add shellescape() function to Vim and properly escape argument.
Patch attached. I'm not sure if I handle WIN/UNIX defines properly, also I don't know how to shell-escape string on DOS/WIN platforms, algorithm was borrowed from php's escapeshellarg() function. This function will do nothing on "nonsupported" platforms. P.S. In UNIX string is surrounded by single quotes and all single quotes in string replaced with quote-backslash-quote-quote. On DOS/WIN it surrounds string with double quotes and replaces doublequotes and percents to space. -- Regards, Sir Raorn.
diff -urN ../vim70-orig/src/eval.c ./src/eval.c --- ../vim70-orig/src/eval.c 2006-08-15 20:24:37 +0400 +++ ./src/eval.c 2006-08-15 20:59:24 +0400 @@ -622,6 +622,7 @@ static void f_setreg __ARGS((typval_T *argvars, typval_T *rettv)); static void f_settabwinvar __ARGS((typval_T *argvars, typval_T *rettv)); static void f_setwinvar __ARGS((typval_T *argvars, typval_T *rettv)); +static void f_shellescape __ARGS((typval_T *argvars, typval_T *rettv)); static void f_simplify __ARGS((typval_T *argvars, typval_T *rettv)); static void f_sort __ARGS((typval_T *argvars, typval_T *rettv)); static void f_soundfold __ARGS((typval_T *argvars, typval_T *rettv)); @@ -7139,6 +7140,7 @@ {"setreg", 2, 3, f_setreg}, {"settabwinvar", 4, 4, f_settabwinvar}, {"setwinvar", 3, 3, f_setwinvar}, + {"shellescape", 1, 1, f_shellescape}, {"simplify", 1, 1, f_simplify}, {"sort", 1, 2, f_sort}, {"soundfold", 1, 1, f_soundfold}, @@ -14609,6 +14611,20 @@ } /* + * "shellescape({string})" function + */ + static void +f_shellescape(argvars, rettv) + typval_T *argvars; + typval_T *rettv; +{ + char_u buf[NUMBUFLEN]; + + rettv->vval.v_string = vim_strsave_shell_escape(get_tv_string(&argvars[0])); + rettv->v_type = VAR_STRING; +} + +/* * "simplify()" function */ static void diff -urN ../vim70-orig/src/misc2.c ./src/misc2.c --- ../vim70-orig/src/misc2.c 2006-05-04 16:12:38 +0400 +++ ./src/misc2.c 2006-08-15 21:11:59 +0400 @@ -1230,6 +1230,109 @@ } /* + * Like vim_strsave_escaped(), but escape string for use as command + * argument in system(). + */ + char_u * +vim_strsave_shell_escape(string) + char_u *string; +{ + char_u *p; + char_u *p2; + char_u *escaped_string; + unsigned length; +#ifdef FEAT_MBYTE + int l; +#endif + + /* + * First count the number of escaped characters required. + * Then allocate the memory and insert them. + */ + length = 3; /* two quotes and the trailing NUL */ + for (p = string; *p; p++) + { +#ifdef FEAT_MBYTE + if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1) + { + length += l; /* count a multibyte char */ + p += l - 1; + continue; + } +#endif + switch (*p) { +#if defined(WIN32) || defined(WIN16) || defined(DOS) + case '"': + case '%': + ++length; + break; +#else +#if defined(UNIX) + case '\'': + length+=4; /* ' => '\'' */ + break; +#endif +#endif + default: + ++length; /* count an ordinary char */ + break; + } + } + escaped_string = alloc(length); + if (escaped_string != NULL) + { + p2 = escaped_string; +#if defined(WIN32) || defined(WIN16) || defined(DOS) + *p2++ = '"'; +#else +#if defined(UNIX) + *p2++ = '\''; +#endif +#endif + for (p = string; *p; p++) + { +#ifdef FEAT_MBYTE + if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1) + { + mch_memmove(p2, p, (size_t)l); + p2 += l; + p += l - 1; /* skip multibyte char */ + continue; + } +#endif + switch (*p) { +#if defined(WIN32) || defined(WIN16) || defined(DOS) + case '"': + case '%': + *p2++=' '; + break; +#else +#if defined(UNIX) + case '\'': + *p2++='\'' + *p2++='\\' + *p2++='\'' + *p2++='\'' + break; +#endif +#endif + default: + *p2++ = *p; + break; + } +#if defined(WIN32) || defined(WIN16) || defined(DOS) + *p2++ = '"'; +#else +#if defined(UNIX) + *p2++ = '\''; +#endif +#endif + *p2 = NUL; + } + return escaped_string; +} + +/* * Like vim_strsave(), but make all characters uppercase. * This uses ASCII lower-to-upper case translation, language independent. */
signature.asc
Description: Digital signature