From 294bf39458035cbeec7706dab8f7d0450e8eb4ec Mon Sep 17 00:00:00 2001 From: divverent Date: Sat, 14 Jul 2007 07:26:30 +0000 Subject: [PATCH] add Cmd_QuoteString, and make the config writing code use that to quote strings written to the config file (so binds containing backslashes and quotes are saved correctly) git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@7487 d7cf8633-e32d-0410-b094-e92efae38249 --- cmd.c | 95 ++++++++++++++++++++++++++++++++++------------------------ cmd.h | 7 +++++ keys.c | 10 +++++-- 3 files changed, 70 insertions(+), 42 deletions(-) diff --git a/cmd.c b/cmd.c index d9485765..aa697001 100644 --- a/cmd.c +++ b/cmd.c @@ -550,11 +550,63 @@ static const char *Cmd_GetDirectCvarValue(const char *varname, cmdalias_t *alias return NULL; } +qboolean Cmd_QuoteString(char *out, size_t outlen, const char *in, const char *quoteset) +{ + qboolean quote_quot = !!strchr(quoteset, '"'); + qboolean quote_backslash = !!strchr(quoteset, '\\'); + qboolean quote_dollar = !!strchr(quoteset, '$'); + + while(*in) + { + if(*in == '"' && quote_quot) + { + if(outlen <= 2) + { + *out++ = 0; + return false; + } + *out++ = '\\'; --outlen; + *out++ = '"'; --outlen; + } + else if(*in == '\\' && quote_backslash) + { + if(outlen <= 2) + { + *out++ = 0; + return false; + } + *out++ = '\\'; --outlen; + *out++ = '\\'; --outlen; + } + else if(*in == '\\' && quote_dollar) + { + if(outlen <= 2) + { + *out++ = 0; + return false; + } + *out++ = '$'; --outlen; + *out++ = '$'; --outlen; + } + else + { + if(outlen <= 1) + { + *out++ = 0; + return false; + } + *out++ = *in; --outlen; + } + ++in; + } + *out++ = 0; + return true; +} + static const char *Cmd_GetCvarValue(const char *var, size_t varlen, cmdalias_t *alias) { static char varname[MAX_INPUTLINE]; static char varval[MAX_INPUTLINE]; - char *p; const char *varstr; char *varfunc; @@ -599,34 +651,8 @@ static const char *Cmd_GetCvarValue(const char *var, size_t varlen, cmdalias_t * if(!varfunc || !strcmp(varfunc, "q")) // note: quoted form is default, use "asis" to override! { // quote it so it can be used inside double quotes - // we just need to replace " by \" - p = varval; - while(*varstr) - { - if(*varstr == '"') - { - if(p - varval >= (ssize_t)(sizeof(varval) - 2)) - break; - *p++ = '\\'; - *p++ = '"'; - } - else if(*varstr == '\\') - { - if(p - varval >= (ssize_t)(sizeof(varval) - 2)) - break; - *p++ = '\\'; - *p++ = '\\'; - } - else - { - if(p - varval >= (ssize_t)(sizeof(varval) - 1)) - break; - *p++ = *varstr; - } - ++varstr; - } - *p++ = 0; - //Con_Printf("quoted form: %s\n", varval); + // we just need to replace " by \", and of course, double backslashes + Cmd_QuoteString(varval, sizeof(varval), varstr, "\"\\"); return varval; } else if(!strcmp(varfunc, "asis")) @@ -766,8 +792,6 @@ static void Cmd_ExecuteAlias (cmdalias_t *alias) { static char buffer[ MAX_INPUTLINE + 2 ]; static char buffer2[ MAX_INPUTLINE * 2 + 2 ]; - char *q; - const char *p; Cmd_PreprocessString( alias->value, buffer, sizeof(buffer) - 2, alias ); // insert at start of command buffer, so that aliases execute in order // (fixes bug introduced by Black on 20050705) @@ -775,14 +799,7 @@ static void Cmd_ExecuteAlias (cmdalias_t *alias) // Note: Cbuf_PreprocessString will be called on this string AGAIN! So we // have to make sure that no second variable expansion takes place, otherwise // alias parameters containing dollar signs can have bad effects. - for(p = buffer, q = buffer2; *p; ) - { - if(*p == '$') - *q++ = '$'; - *q++ = *p++; - } - *q++ = 0; - + Cmd_QuoteString(buffer2, sizeof(buffer2), buffer, "$"); Cbuf_InsertText( buffer2 ); } diff --git a/cmd.h b/cmd.h index 130e3cde..d2ae07d7 100644 --- a/cmd.h +++ b/cmd.h @@ -149,5 +149,12 @@ void Cmd_Print(const char *text); // used by command functions to send output to either the graphics console or // passed as a print message to the client +qboolean Cmd_QuoteString(char *out, size_t outlen, const char *in, const char *quoteset); +// quotes a string so that it can be used as a command argument again; +// quoteset is a string that contains one or more of ", \, $ and specifies +// the characters to be quoted (you usually want to either pass "\"\\" or +// "\"\\$"). Returns true on success, and false on overrun (in which case out +// will contain a part of the quoted string). + #endif diff --git a/keys.c b/keys.c index eb393826..6e61c438 100644 --- a/keys.c +++ b/keys.c @@ -801,17 +801,21 @@ void Key_WriteBindings (qfile_t *f) { int i, j; + char bindbuf[MAX_INPUTLINE]; + const char *p; for (j = 0; j < MAX_BINDMAPS; j++) { for (i = 0; i < (int)(sizeof(keybindings[0])/sizeof(keybindings[0][0])); i++) { - if (keybindings[j][i]) + p = keybindings[j][i]; + if (p) { + Cmd_QuoteString(bindbuf, sizeof(bindbuf), p, "\"\\"); if (j == 0) - FS_Printf(f, "bind %s \"%s\"\n", Key_KeynumToString (i), keybindings[j][i]); + FS_Printf(f, "bind %s \"%s\"\n", Key_KeynumToString (i), bindbuf); else - FS_Printf(f, "in_bind %d %s \"%s\"\n", j, Key_KeynumToString (i), keybindings[j][i]); + FS_Printf(f, "in_bind %d %s \"%s\"\n", j, Key_KeynumToString (i), bindbuf); } } } -- 2.39.2