Skip to content

Commit

Permalink
ported callvote fix from ioquake3, fixes #7
Browse files Browse the repository at this point in the history
  • Loading branch information
JanSimek committed Mar 17, 2012
1 parent bf3f0bd commit 4a50680
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 21 deletions.
18 changes: 12 additions & 6 deletions src/game/g_cmds.c
Expand Up @@ -2284,6 +2284,7 @@ Cmd_CallVote_f
*/
qboolean Cmd_CallVote_f(gentity_t *ent, unsigned int dwCommand, qboolean fRefCommand)
{
char *c;
int i;
char arg1[MAX_STRING_TOKENS];
char arg2[MAX_STRING_TOKENS];
Expand Down Expand Up @@ -2325,15 +2326,20 @@ qboolean Cmd_CallVote_f(gentity_t *ent, unsigned int dwCommand, qboolean fRefCom
trap_Argv(1, arg1, sizeof(arg1));
trap_Argv(2, arg2, sizeof(arg2));

if (strchr(arg1, ';') || strchr(arg2, ';'))
// check for command separators in arg2
for (c = arg2; *c; ++c)
{
char *strCmdBase = (!fRefCommand) ? "vote" : "ref command";

G_refPrintf(ent, "Invalid %s string.", strCmdBase);
return(qfalse);
switch (*c)
{
case '\n':
case '\r':
case ';':
trap_SendServerCommand(ent - g_entities, "print \"Invalid vote string.\n\"");
return(qfalse);
break;
}
}


if (trap_Argc() > 1 && (i = G_voteCmdCheck(ent, arg1, arg2, fRefCommand)) != G_NOTFOUND) // --OSP
{
if (i != G_OK)
Expand Down
99 changes: 84 additions & 15 deletions src/qcommon/cmd.c
Expand Up @@ -32,7 +32,7 @@
* @brief Quake script command processing module
*/

#include "../qcommon/q_shared.h"
#include "q_shared.h"
#include "qcommon.h"

#define MAX_CMD_BUFFER 131072
Expand Down Expand Up @@ -69,7 +69,7 @@ void Cmd_Wait_f(void)
}
else
{
cmd_wait = 1;
cmd_wait = 1; // ignore the argument
}
}

Expand Down Expand Up @@ -112,7 +112,7 @@ void Cbuf_AddText(const char *text)
Com_Printf("Cbuf_AddText: overflow\n");
return;
}
memcpy(&cmd_text.data[cmd_text.cursize], text, l);
Com_Memcpy(&cmd_text.data[cmd_text.cursize], text, l);
cmd_text.cursize += l;
}

Expand Down Expand Up @@ -144,7 +144,7 @@ void Cbuf_InsertText(const char *text)
}

// copy the new text in
memcpy(cmd_text.data, text, len - 1);
Com_Memcpy(cmd_text.data, text, len - 1);

// add a \n
cmd_text.data[len - 1] = '\n';
Expand All @@ -165,11 +165,13 @@ void Cbuf_ExecuteText(int exec_when, const char *text)
case EXEC_NOW:
if (text && strlen(text) > 0)
{
Com_DPrintf(S_COLOR_YELLOW "EXEC_NOW %s\n", text);
Cmd_ExecuteString(text);
}
else
{
Cbuf_Execute();
Com_DPrintf(S_COLOR_YELLOW "EXEC_NOW %s\n", cmd_text.data);
}
break;
case EXEC_INSERT:
Expand All @@ -195,17 +197,22 @@ void Cbuf_Execute(void)
char line[MAX_CMD_LINE];
int quotes;

// This will keep // style comments all on one line by not breaking on
// a semicolon. It will keep /* ... */ style comments all on one line by not
// breaking it for semicolon or newline.
qboolean in_star_comment = qfalse;
qboolean in_slash_comment = qfalse;
while (cmd_text.cursize)
{
if (cmd_wait)
if (cmd_wait > 0)
{
// skip out while text still remains in buffer, leaving it
// for next frame
cmd_wait--;
break;
}

// find a \n or ; line break
// find a \n or ; line break or comment: // or /* */
text = (char *)cmd_text.data;

quotes = 0;
Expand All @@ -215,12 +222,37 @@ void Cbuf_Execute(void)
{
quotes++;
}
if (!(quotes & 1) && text[i] == ';')

if (!(quotes & 1))
{
break; // don't break if inside a quoted string
if (i < cmd_text.cursize - 1)
{
if (!in_star_comment && text[i] == '/' && text[i + 1] == '/')
{
in_slash_comment = qtrue;
}
else if (!in_slash_comment && text[i] == '/' && text[i + 1] == '*')
{
in_star_comment = qtrue;
}
else if (in_star_comment && text[i] == '*' && text[i + 1] == '/')
{
in_star_comment = qfalse;
// If we are in a star comment, then the part after it is valid
// Note: This will cause it to NUL out the terminating '/'
// but ExecuteString doesn't require it anyway.
i++;
break;
}
}
if (!in_slash_comment && !in_star_comment && text[i] == ';')
{
break;
}
}
if (text[i] == '\n' || text[i] == '\r')
if (!in_star_comment && (text[i] == '\n' || text[i] == '\r'))
{
in_slash_comment = qfalse;
break;
}
}
Expand All @@ -230,7 +262,7 @@ void Cbuf_Execute(void)
i = MAX_CMD_LINE - 1;
}

memcpy(line, text, i);
Com_Memcpy(line, text, i);
line[i] = 0;

// delete the text from the command buffer and move remaining commands down
Expand Down Expand Up @@ -473,14 +505,41 @@ Cmd_Cmd
Retrieve the unmodified command string
For rcon use when you want to transmit without altering quoting
ATVI Wolfenstein Misc #284
============
*/
char *Cmd_Cmd()
char *Cmd_Cmd(void)
{
return cmd_cmd;
}

/*
* @brief Replaces command separators with space to prevent interpretation
*
* This is a hack to protect buggy qvms
* https://bugzilla.icculus.org/show_bug.cgi?id=3593
* https://bugzilla.icculus.org/show_bug.cgi?id=4769
*/
void Cmd_Args_Sanitize(void)
{
int i;

for (i = 1; i < cmd_argc; i++)
{
char *c = cmd_argv[i];

if (strlen(c) > MAX_CVAR_VALUE_STRING - 1)
{
c[MAX_CVAR_VALUE_STRING - 1] = '\0';
}

while ((c = strpbrk(c, "\n\r;")))
{
*c = ' ';
++c;
}
}
}

/*
============
Cmd_TokenizeString
Expand All @@ -491,7 +550,7 @@ are inserted in the apropriate place, The argv array
will point into this temporary buffer.
============
*/
void Cmd_TokenizeString(const char *text_in)
static void Cmd_TokenizeString2(const char *text_in, qboolean ignoreQuotes)
{
const char *text;
char *textOut;
Expand Down Expand Up @@ -558,7 +617,8 @@ void Cmd_TokenizeString(const char *text_in)
}

// handle quoted strings
if (*text == '"')
// NOTE: this doesn't handle \" escaping
if (!ignoreQuotes && *text == '"')
{
cmd_argv[cmd_argc] = textOut;
cmd_argc++;
Expand All @@ -583,7 +643,7 @@ void Cmd_TokenizeString(const char *text_in)
// skip until whitespace, quote, or command
while (*text > ' ')
{
if (text[0] == '"')
if (!ignoreQuotes && text[0] == '"')
{
break;
}
Expand Down Expand Up @@ -616,6 +676,15 @@ void Cmd_TokenizeString(const char *text_in)

}

void Cmd_TokenizeString(const char *text_in)
{
Cmd_TokenizeString2(text_in, qfalse);
}

void Cmd_TokenizeStringIgnoreQuotes(const char *text_in)
{
Cmd_TokenizeString2(text_in, qtrue);
}

/*
============
Expand Down
2 changes: 2 additions & 0 deletions src/qcommon/qcommon.h
Expand Up @@ -485,11 +485,13 @@ char *Cmd_Args(void);
char *Cmd_ArgsFrom(int arg);
void Cmd_ArgsBuffer(char *buffer, int bufferLength);
char *Cmd_Cmd(void);
void Cmd_Args_Sanitize(void);
// The functions that execute commands get their parameters with these
// functions. Cmd_Argv () will return an empty string, not a NULL
// if arg > argc, so string operations are allways safe.

void Cmd_TokenizeString(const char *text);
void Cmd_TokenizeStringIgnoreQuotes(const char *text_in);
// Takes a null terminated string. Does not need to be /n terminated.
// breaks the string up into arg tokens.

Expand Down
1 change: 1 addition & 0 deletions src/server/sv_client.c
Expand Up @@ -1726,6 +1726,7 @@ void SV_ExecuteClientCommand(client_t *cl, const char *s, qboolean clientOK, qbo
// pass unknown strings to the game
if (!u->name && sv.state == SS_GAME)
{
Cmd_Args_Sanitize();
VM_Call(gvm, GAME_CLIENT_COMMAND, cl - svs.clients);
}
}
Expand Down

0 comments on commit 4a50680

Please sign in to comment.