mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-17 22:50:51 +00:00
remove a whole swath of potential buffer overflows by removing the buffer.
Also audit a few of the "FIXME: overflow" tags
This commit is contained in:
parent
59c26b5ce0
commit
ada828bdc9
12 changed files with 246 additions and 310 deletions
|
@ -51,12 +51,13 @@ qboolean Info_FilterForKey (const char *key, const char **filter_list);
|
|||
|
||||
void Info_Print (info_t *info);
|
||||
void Info_RemoveKey (info_t *info, const char *key);
|
||||
void Info_SetValueForKey (info_t *info, const char *key, const char *value, int flags);
|
||||
void Info_SetValueForStarKey (info_t *info, const char *key, const char *value, int flags);
|
||||
int Info_SetValueForKey (info_t *info, const char *key, const char *value, int flags);
|
||||
int Info_SetValueForStarKey (info_t *info, const char *key, const char *value, int flags);
|
||||
const char *Info_ValueForKey (info_t *info, const char *key);
|
||||
|
||||
info_t *Info_ParseString (const char *s, int maxsize, int flags);
|
||||
void Info_Destroy (info_t *info);
|
||||
char *Info_MakeString (info_t *info, int (*filter)(const char *));
|
||||
void Info_AddKeys (info_t *info, info_t *keys);
|
||||
|
||||
#endif // _INFO_H
|
||||
|
|
|
@ -94,8 +94,9 @@ Info_RemoveKey (info_t *info, const char *key)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
Info_SetValueForStarKey (info_t *info, const char *key, const char *value, int flags)
|
||||
int
|
||||
Info_SetValueForStarKey (info_t *info, const char *key, const char *value,
|
||||
int flags)
|
||||
{
|
||||
info_key_t *k;
|
||||
int cursize;
|
||||
|
@ -104,17 +105,17 @@ Info_SetValueForStarKey (info_t *info, const char *key, const char *value, int f
|
|||
|
||||
if (strstr (key, "\\") || strstr (value, "\\")) {
|
||||
Sys_Printf ("Can't use keys or values with a \\\n");
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strstr (key, "\"") || strstr (value, "\"")) {
|
||||
Sys_Printf ("Can't use keys or values with a \"\n");
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strlen (key) > 63 || strlen (value) > 63) {
|
||||
Sys_Printf ("Keys and values must be < 64 characters.\n");
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
k = Hash_Find (info->tab, key);
|
||||
cursize = info->cursize;
|
||||
|
@ -125,11 +126,11 @@ Info_SetValueForStarKey (info_t *info, const char *key, const char *value, int f
|
|||
if (info->maxsize &&
|
||||
cursize + strlen (key) + 1 + strlen (value) + 1 > info->maxsize) {
|
||||
Sys_Printf ("Info string length exceeded\n");
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
if (k) {
|
||||
if (strequal (k->value, value))
|
||||
return;
|
||||
return 0;
|
||||
info->cursize -= strlen (k->value) + 1;
|
||||
free ((char*)k->value);
|
||||
} else {
|
||||
|
@ -156,18 +157,19 @@ Info_SetValueForStarKey (info_t *info, const char *key, const char *value, int f
|
|||
*d = 0;
|
||||
info->cursize += strlen (str) + 1;
|
||||
k->value = str;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
Info_SetValueForKey (info_t *info, const char *key, const char *value,
|
||||
int flags)
|
||||
{
|
||||
if (key[0] == '*') {
|
||||
Sys_Printf ("Can't set * keys\n");
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Info_SetValueForStarKey (info, key, value, flags);
|
||||
return Info_SetValueForStarKey (info, key, value, flags);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -269,3 +271,16 @@ Info_MakeString (info_t *info, int (*filter)(const char *))
|
|||
free (key_list);
|
||||
return string;
|
||||
}
|
||||
|
||||
void
|
||||
Info_AddKeys (info_t *info, info_t *keys)
|
||||
{
|
||||
info_key_t **key_list;
|
||||
info_key_t **key;
|
||||
|
||||
key_list = (info_key_t **)Hash_GetList (keys->tab);
|
||||
for (key = key_list; *key; key++) {
|
||||
Info_SetValueForKey (info, (*key)->key, (*key)->value, 0);
|
||||
}
|
||||
free (key_list);
|
||||
}
|
||||
|
|
|
@ -1290,7 +1290,7 @@ QFS_Open (const char *path, const char *mode)
|
|||
QFile *
|
||||
QFS_WOpen (const char *path, int zip)
|
||||
{
|
||||
char mode[5] = "wb\000\000";
|
||||
char mode[5] = "wb\000\000\000";
|
||||
|
||||
if (zip) {
|
||||
mode[2] = 'z';
|
||||
|
|
|
@ -91,7 +91,7 @@ typedef struct {
|
|||
float fixangletime[MAX_CLIENTS];
|
||||
vec3_t angles[MAX_CLIENTS];
|
||||
struct dstring_s *name;
|
||||
struct dstring_s *path;
|
||||
struct dstring_s *text;
|
||||
int parsecount;
|
||||
int lastwritten;
|
||||
demo_frame_t frames[DEMO_FRAMES];
|
||||
|
|
|
@ -663,45 +663,16 @@ CL_AddQFInfoKeys (void)
|
|||
static void
|
||||
CL_FullInfo_f (void)
|
||||
{
|
||||
char key[512], value[512]; //FIXME: overflow
|
||||
char *o;
|
||||
const char *s;
|
||||
info_t *info;
|
||||
|
||||
if (Cmd_Argc () != 2) {
|
||||
Con_Printf ("fullinfo <complete info string>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
s = Cmd_Argv (1);
|
||||
if (*s == '\\')
|
||||
s++;
|
||||
while (*s) {
|
||||
o = key;
|
||||
while (*s && *s != '\\')
|
||||
*o++ = *s++;
|
||||
*o = 0;
|
||||
|
||||
if (!*s) {
|
||||
Con_Printf ("MISSING VALUE\n");
|
||||
return;
|
||||
}
|
||||
|
||||
o = value;
|
||||
s++;
|
||||
while (*s && *s != '\\')
|
||||
*o++ = *s++;
|
||||
*o = 0;
|
||||
|
||||
if (*s)
|
||||
s++;
|
||||
|
||||
if (strcaseequal (key, pmodel_name) || strcaseequal (key, emodel_name))
|
||||
continue;
|
||||
|
||||
Info_SetValueForKey (cls.userinfo, key, value,
|
||||
(!strequal (key, "name")) |
|
||||
(strequal (key, "team") << 1));
|
||||
}
|
||||
info = Info_ParseString (Cmd_Argv (1), MAX_INFO_STRING, 0);
|
||||
Info_AddKeys (cls.userinfo, info);
|
||||
Info_Destroy (info);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -411,7 +411,7 @@ read_hosts (const char *fname)
|
|||
{
|
||||
FILE *host_file;
|
||||
int host_port;
|
||||
char host_name[256]; //FIXME: overflow
|
||||
char host_name[256];
|
||||
static const char *fake_heartbeat = " ";
|
||||
char *buf;
|
||||
struct sockaddr_in host_addr;
|
||||
|
@ -501,7 +501,7 @@ ma_log (const char *fmt, ...)
|
|||
va_list args;
|
||||
time_t mytime = 0;
|
||||
struct tm *local = NULL;
|
||||
char stamp[1024]; //FIXME: overflow
|
||||
char stamp[123];
|
||||
|
||||
mytime = time (NULL);
|
||||
local = localtime (&mytime);
|
||||
|
|
|
@ -416,7 +416,7 @@ Sbar_SortFrags (qboolean includespec)
|
|||
static void
|
||||
Sbar_SortTeams (void)
|
||||
{
|
||||
char t[16 + 1]; //FIXME: overflow
|
||||
char t[16 + 1];
|
||||
int i, j, k;
|
||||
player_info_t *s;
|
||||
|
||||
|
@ -535,7 +535,7 @@ dmo_ping (view_t *view, int x, int y, player_info_t *s)
|
|||
static inline void
|
||||
dmo_uid (view_t *view, int x, int y, player_info_t *s)
|
||||
{
|
||||
char num[12]; //FIXME: overflow
|
||||
char num[12];
|
||||
int p;
|
||||
|
||||
p = s->userid;
|
||||
|
@ -683,7 +683,7 @@ draw_weapons_hud (view_t *view)
|
|||
static void
|
||||
draw_ammo_sbar (view_t *view)
|
||||
{
|
||||
char num[12]; //FIXME: overflow
|
||||
char num[12];
|
||||
int i;
|
||||
|
||||
// ammo counts
|
||||
|
@ -704,7 +704,7 @@ draw_ammo_sbar (view_t *view)
|
|||
static void
|
||||
draw_ammo_hud (view_t *view)
|
||||
{
|
||||
char num[12]; //FIXME: overflow
|
||||
char num[12];
|
||||
int i;
|
||||
|
||||
// ammo counts
|
||||
|
@ -989,7 +989,7 @@ Sbar_Draw (void)
|
|||
void
|
||||
Sbar_TeamOverlay (view_t *view)
|
||||
{
|
||||
char num[12]; //FIXME: overflow
|
||||
char num[20];
|
||||
int pavg, plow, phigh, i, k, l, x, y;
|
||||
team_t *tm;
|
||||
info_key_t *player_team = cl.players[cl.playernum].team;
|
||||
|
@ -1481,7 +1481,7 @@ static void
|
|||
draw_minifrags (view_t *view)
|
||||
{
|
||||
int numlines, top, bottom, f, i, k, x, y;
|
||||
char num[12]; //FIXME: overflow
|
||||
char num[20];
|
||||
player_info_t *s;
|
||||
|
||||
scr_copyeverything = 1;
|
||||
|
@ -1555,7 +1555,7 @@ static void
|
|||
draw_miniteam (view_t *view)
|
||||
{
|
||||
int i, k, x, y;
|
||||
char num[12]; //FIXME: overflow
|
||||
char num[12];
|
||||
info_key_t *player_team = cl.players[cl.playernum].team;
|
||||
team_t *tm;
|
||||
|
||||
|
@ -1590,7 +1590,7 @@ draw_time (view_t *view)
|
|||
struct tm *local = NULL;
|
||||
time_t utc = 0;
|
||||
const char *timefmt = NULL;
|
||||
char st[80]; //FIXME: overflow
|
||||
char st[80];
|
||||
|
||||
// Get local time
|
||||
utc = time (NULL);
|
||||
|
@ -1609,7 +1609,7 @@ draw_time (view_t *view)
|
|||
static void
|
||||
draw_fps (view_t *view)
|
||||
{
|
||||
static char st[80]; //FIXME: overflow
|
||||
static char st[80];
|
||||
double t;
|
||||
static double lastframetime;
|
||||
static double lastfps;
|
||||
|
|
|
@ -341,12 +341,12 @@ SV_Give_f (void)
|
|||
}
|
||||
|
||||
// Use this to keep track of current level --KB
|
||||
static char curlevel[MAX_QPATH] = ""; //FIXME: overflow
|
||||
static dstring_t *curlevel;
|
||||
|
||||
const char *
|
||||
SV_Current_Map (void)
|
||||
{
|
||||
return curlevel;
|
||||
return curlevel ? curlevel->str : "";
|
||||
}
|
||||
|
||||
static const char *
|
||||
|
@ -393,29 +393,33 @@ nice_time (float time)
|
|||
static void
|
||||
SV_Map_f (void)
|
||||
{
|
||||
char level[MAX_QPATH]; //FIXME: overflow
|
||||
char expanded[MAX_QPATH]; //FIXME: overflow
|
||||
const char *level;
|
||||
char *expanded;
|
||||
QFile *f;
|
||||
|
||||
if (!curlevel)
|
||||
curlevel = dstring_newstr ();
|
||||
|
||||
if (Cmd_Argc () > 2) {
|
||||
SV_Printf ("map <levelname> : continue game on a new level\n");
|
||||
return;
|
||||
}
|
||||
if (Cmd_Argc () == 1) {
|
||||
SV_Printf ("map is %s (%s)\n", curlevel, nice_time (sv.time));
|
||||
SV_Printf ("map is %s (%s)\n", curlevel->str, nice_time (sv.time));
|
||||
return;
|
||||
}
|
||||
strncpy (level, Cmd_Argv (1), sizeof (level) - 1);
|
||||
level[sizeof (level) - 1] = 0;
|
||||
level = Cmd_Argv (1);
|
||||
|
||||
// check to make sure the level exists
|
||||
snprintf (expanded, sizeof (expanded), "maps/%s.bsp", level);
|
||||
expanded = nva ("maps/%s.bsp", level);
|
||||
QFS_FOpenFile (expanded, &f);
|
||||
if (!f) {
|
||||
SV_Printf ("Can't find %s\n", expanded);
|
||||
free (expanded);
|
||||
return;
|
||||
}
|
||||
Qclose (f);
|
||||
free (expanded);
|
||||
|
||||
if (sv.demorecording)
|
||||
SV_Stop_f ();
|
||||
|
@ -423,8 +427,7 @@ SV_Map_f (void)
|
|||
SV_BroadcastCommand ("changing\n");
|
||||
SV_SendMessagesToAll ();
|
||||
|
||||
strncpy (curlevel, level, sizeof (curlevel) - 1);
|
||||
curlevel[sizeof (curlevel) - 1] = 0;
|
||||
dstring_copystr (curlevel, level);
|
||||
SV_SpawnServer (level);
|
||||
|
||||
SV_BroadcastCommand ("reconnect\n");
|
||||
|
@ -562,17 +565,36 @@ SV_Status_f (void)
|
|||
#define MAXPENALTY 10.0
|
||||
|
||||
static void
|
||||
SV_Cuff_f (void)
|
||||
SV_Punish (int mode)
|
||||
{
|
||||
int i;
|
||||
double mins = 0.5;
|
||||
qboolean all = false, done = false;
|
||||
client_t *cl = 0;
|
||||
char text[1024]; //FIXME: overflow
|
||||
dstring_t *text = dstring_new();
|
||||
const char *cmd = 0;
|
||||
const char *cmd_do = 0;
|
||||
const char *cmd_undo = 0;
|
||||
int field_offs = 0;
|
||||
|
||||
switch (mode) {
|
||||
case 0:
|
||||
cmd = "cuff";
|
||||
cmd_do = "cuffed";
|
||||
cmd_undo = "un-cuffed";
|
||||
field_offs = field_offset (client_t, cuff_time);
|
||||
break;
|
||||
case 1:
|
||||
cmd = "mute";
|
||||
cmd_do = "muted";
|
||||
cmd_undo = "can speak";
|
||||
field_offs = field_offset (client_t, lockedtill);
|
||||
break;
|
||||
}
|
||||
|
||||
if (Cmd_Argc () != 2 && Cmd_Argc () != 3) {
|
||||
SV_Printf ("usage: cuff <name/userid/ALL> [minutes]\n"
|
||||
" (default = 0.5, 0 = cancel cuff).\n");
|
||||
SV_Printf ("usage: %s <name/userid/ALL> [minutes]\n"
|
||||
" (default = 0.5, 0 = cancel cuff).\n", cmd);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -589,133 +611,52 @@ SV_Cuff_f (void)
|
|||
mins = MAXPENALTY;
|
||||
}
|
||||
if (cl) {
|
||||
cl->cuff_time = realtime + mins * 60.0;
|
||||
*(double *)((char *)cl + field_offs) = realtime + mins * 60.0;
|
||||
if (mins) {
|
||||
sprintf (text, "You are cuffed for %.1f minutes\n\n"
|
||||
"reconnecting won't help...\n", mins);
|
||||
ClientReliableWrite_Begin (cl, svc_centerprint, 2 + strlen (text));
|
||||
ClientReliableWrite_String (cl, text);
|
||||
dsprintf (text, "You are %s for %.1f minutes\n\n"
|
||||
"reconnecting won't help...\n", cmd_do, mins);
|
||||
ClientReliableWrite_Begin (cl, svc_centerprint,
|
||||
2 + strlen (text->str));
|
||||
ClientReliableWrite_String (cl, text->str);
|
||||
}
|
||||
}
|
||||
if (all) {
|
||||
for (i = 0, cl = svs.clients; i < MAX_CLIENTS; i++, cl++) {
|
||||
if (cl->state < cs_zombie)
|
||||
continue;
|
||||
cl->cuff_time = realtime + mins * 60.0;
|
||||
*(double *)((char *)cl + field_offs) = realtime + mins * 60.0;
|
||||
done = true;
|
||||
if (mins) {
|
||||
sprintf (text, "You are cuffed for %.1f minutes\n\n"
|
||||
"reconnecting won't help...\n", mins);
|
||||
dsprintf (text, "You are %s for %.1f minutes\n\n"
|
||||
"reconnecting won't help...\n", cmd_do, mins);
|
||||
ClientReliableWrite_Begin (cl, svc_centerprint,
|
||||
2 + strlen (text));
|
||||
ClientReliableWrite_String (cl, text);
|
||||
2 + strlen (text->str));
|
||||
ClientReliableWrite_String (cl, text->str);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (done) {
|
||||
if (mins)
|
||||
SV_BroadcastPrintf (PRINT_HIGH, "%s cuffed for %.1f minutes.\n",
|
||||
all? "All Users" : cl->name, mins);
|
||||
SV_BroadcastPrintf (PRINT_HIGH, "%s %s for %.1f minutes.\n",
|
||||
all? "All Users" : cl->name, cmd_do, mins);
|
||||
else
|
||||
SV_BroadcastPrintf (PRINT_HIGH, "%s un-cuffed.\n",
|
||||
all? "All Users" : cl->name);
|
||||
SV_BroadcastPrintf (PRINT_HIGH, "%s %s.\n",
|
||||
all? "All Users" : cl->name, cmd_do);
|
||||
}
|
||||
dstring_delete (text);
|
||||
}
|
||||
|
||||
static void
|
||||
SV_Cuff_f (void)
|
||||
{
|
||||
SV_Punish (0);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
SV_Mute_f (void)
|
||||
{
|
||||
int i;
|
||||
double mins = 0.5;
|
||||
qboolean all = false, done = false;
|
||||
client_t *cl = 0;
|
||||
char text[1024]; //FIXME: overflow
|
||||
|
||||
if (Cmd_Argc () != 2 && Cmd_Argc () != 3) {
|
||||
SV_Printf ("usage: mute <name/userid/ALL> [minutes]\n"
|
||||
" (default = 0.5, 0 = cancel mute).\n");
|
||||
return;
|
||||
}
|
||||
if (strequal (Cmd_Argv (1),"ALL")) {
|
||||
all = true;
|
||||
} else {
|
||||
cl = SV_Match_User (Cmd_Argv (1));
|
||||
}
|
||||
if (!all && !cl)
|
||||
return;
|
||||
if (Cmd_Argc () == 3) {
|
||||
mins = atof (Cmd_Argv (2));
|
||||
if (mins < 0.0 || mins > MAXPENALTY)
|
||||
mins = MAXPENALTY;
|
||||
}
|
||||
if (cl) {
|
||||
cl->lockedtill = realtime + mins * 60.0;
|
||||
done = true;
|
||||
if (mins) {
|
||||
sprintf (text, "You are muted for %.1f minutes\n\n"
|
||||
"reconnecting won't help...\n", mins);
|
||||
ClientReliableWrite_Begin (cl, svc_centerprint, 2 + strlen (text));
|
||||
ClientReliableWrite_String (cl, text);
|
||||
}
|
||||
}
|
||||
if (all) {
|
||||
for (i = 0, cl = svs.clients; i < MAX_CLIENTS; i++, cl++) {
|
||||
if (cl->state < cs_zombie)
|
||||
continue;
|
||||
cl->lockedtill = realtime + mins * 60.0;
|
||||
done = true;
|
||||
if (mins) {
|
||||
sprintf (text, "You are muted for %.1f minutes\n\n"
|
||||
"reconnecting won't help...\n", mins);
|
||||
ClientReliableWrite_Begin (cl, svc_centerprint,
|
||||
2 + strlen (text));
|
||||
ClientReliableWrite_String (cl, text);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (done) {
|
||||
if (mins)
|
||||
SV_BroadcastPrintf (PRINT_HIGH, "%s muted for %.1f minutes.\n",
|
||||
all? "All Users" : cl->name, mins);
|
||||
else
|
||||
SV_BroadcastPrintf (PRINT_HIGH, "%s allowed to speak.\n",
|
||||
all? "All Users" : cl->name);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
SV_Tell (const char *prefix)
|
||||
{
|
||||
char *p;
|
||||
char text[512]; //FIXME: overflow
|
||||
client_t *cl;
|
||||
int i;
|
||||
|
||||
if (Cmd_Argc () < 3) {
|
||||
SV_Printf ("usage: tell <name/userid> <text...>\n");
|
||||
return;
|
||||
}
|
||||
if (!(cl = SV_Match_User (Cmd_Argv (1))))
|
||||
return;
|
||||
|
||||
p = Hunk_TempAlloc (strlen (Cmd_Args (2)) + 1);
|
||||
strcpy (p, Cmd_Args (2));
|
||||
if (*p == '"') {
|
||||
p++;
|
||||
p[strlen (p) - 1] = 0;
|
||||
}
|
||||
// construct "[PRIVATE] Console> "
|
||||
sprintf (text, "[\xd0\xd2\xc9\xd6\xc1\xd4\xc5] %s\x8d ", prefix);
|
||||
i = strlen (text);
|
||||
strncat (text, p, sizeof (text) - 1 - i);
|
||||
text[sizeof (text) - 1] = 0;
|
||||
SV_Printf ("%s\n", text);
|
||||
for (; text[i];)
|
||||
text[i++] |= 0x80; // non-bold text
|
||||
SV_ClientPrintf (1, cl, PRINT_CHAT, "\n"); // bell
|
||||
SV_ClientPrintf (1, cl, PRINT_HIGH, "%s\n", text);
|
||||
SV_ClientPrintf (1, cl, PRINT_CHAT, "%s", ""); // bell
|
||||
SV_Punish (1);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -759,11 +700,10 @@ SV_Match_f (void)
|
|||
|
||||
|
||||
static void
|
||||
SV_ConSay (const char *prefix)
|
||||
SV_ConSay (const char *prefix, client_t *client)
|
||||
{
|
||||
char *p;
|
||||
char text[1024]; //FIXME: overflow
|
||||
client_t *client;
|
||||
dstring_t *text;
|
||||
int j;
|
||||
|
||||
if (Cmd_Argc () < 2)
|
||||
|
@ -775,51 +715,67 @@ SV_ConSay (const char *prefix)
|
|||
p++;
|
||||
p[strlen (p) - 1] = 0;
|
||||
}
|
||||
strcpy (text, prefix); // bold header
|
||||
strcat (text, "\x8d "); // and arrow
|
||||
j = strlen (text);
|
||||
strncat (text, p, sizeof (text) - j);
|
||||
SV_Printf ("%s\n", text);
|
||||
while (text[j])
|
||||
text[j++] |= 0x80; // non-bold text
|
||||
text = dstring_new ();
|
||||
dstring_copystr (text, prefix);
|
||||
dstring_appendstr (text, "\x8d "); // arrow
|
||||
j = strlen (text->str);
|
||||
dstring_appendstr (text, p);
|
||||
SV_Printf ("%s\n", text->str);
|
||||
while (text->str[j])
|
||||
text->str[j++] |= 0x80; // non-bold text
|
||||
|
||||
if (client) {
|
||||
SV_ClientPrintf (1, client, PRINT_CHAT, "\n"); // bell
|
||||
SV_ClientPrintf (1, client, PRINT_HIGH, "%s\n", text->str);
|
||||
SV_ClientPrintf (1, client, PRINT_CHAT, "%s", ""); // bell
|
||||
} else {
|
||||
for (j = 0, client = svs.clients; j < MAX_CLIENTS; j++, client++) {
|
||||
if (client->state < cs_zombie)
|
||||
continue;
|
||||
SV_ClientPrintf (1, client, PRINT_HIGH, "%s\n", text);
|
||||
SV_ClientPrintf (1, client, PRINT_HIGH, "%s\n", text->str);
|
||||
if (*prefix != 'I') // beep, except for Info says
|
||||
SV_ClientPrintf (0, client, PRINT_CHAT, "%s", "");
|
||||
}
|
||||
if (sv.demorecording) {
|
||||
DemoWrite_Begin (dem_all, 0, strlen (text) + 3);
|
||||
DemoWrite_Begin (dem_all, 0, strlen (text->str) + 3);
|
||||
MSG_WriteByte (&demo.dbuf->sz, svc_print);
|
||||
MSG_WriteByte (&demo.dbuf->sz, PRINT_CHAT);
|
||||
MSG_WriteString (&demo.dbuf->sz, text);
|
||||
MSG_WriteString (&demo.dbuf->sz, text->str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
SV_Tell_f (void)
|
||||
{
|
||||
client_t *cl;
|
||||
|
||||
if (Cmd_Argc () < 3) {
|
||||
SV_Printf ("usage: tell <name/userid> <text...>\n");
|
||||
return;
|
||||
}
|
||||
if (!(cl = SV_Match_User (Cmd_Argv (1))))
|
||||
return;
|
||||
|
||||
if (rcon_from_user)
|
||||
SV_Tell("Admin");
|
||||
SV_ConSay ("[\xd0\xd2\xc9\xd6\xc1\xd4\xc5] Admin", cl);
|
||||
else
|
||||
SV_Tell("Console");
|
||||
SV_ConSay ("[\xd0\xd2\xc9\xd6\xc1\xd4\xc5] Console", cl);
|
||||
}
|
||||
|
||||
static void
|
||||
SV_ConSay_f (void)
|
||||
{
|
||||
if (rcon_from_user)
|
||||
SV_ConSay ("Admin");
|
||||
SV_ConSay ("Admin", 0);
|
||||
else
|
||||
SV_ConSay ("Console");
|
||||
SV_ConSay ("Console", 0);
|
||||
}
|
||||
|
||||
static void
|
||||
SV_ConSay_Info_f (void)
|
||||
{
|
||||
SV_ConSay ("Info");
|
||||
SV_ConSay ("Info", 0);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -541,14 +541,12 @@ SV_DemoWritePackets (int num)
|
|||
}
|
||||
|
||||
static int
|
||||
memwrite (QFile * _mem, const void *buffer, int size)
|
||||
memwrite (QFile *_mem, const void *buffer, int size)
|
||||
{
|
||||
int i;
|
||||
byte **mem = (byte **) _mem;
|
||||
const byte *buf;
|
||||
|
||||
for (i = size, buf = buffer; i; i--)
|
||||
*(*mem)++ = *buf++;
|
||||
memcpy (*mem, buffer, size);
|
||||
*mem += size;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
@ -585,18 +583,12 @@ SV_Stop (int reason)
|
|||
}
|
||||
|
||||
if (reason == 2) {
|
||||
char path[MAX_OSPATH];
|
||||
|
||||
// stop and remove
|
||||
if (demo.disk)
|
||||
Qclose (demo.file);
|
||||
|
||||
sprintf (path, "%s/%s/%s", qfs_gamedir->dir.def, demo.path->str,
|
||||
demo.name->str);
|
||||
QFS_Remove (path);
|
||||
|
||||
strcpy (path + strlen (path) - 3, "txt");
|
||||
QFS_Remove (path);
|
||||
QFS_Remove (demo.name->str);
|
||||
QFS_Remove (demo.text->str);
|
||||
|
||||
demo.file = NULL;
|
||||
sv.demorecording = false;
|
||||
|
@ -632,8 +624,8 @@ SV_Stop (int reason)
|
|||
if (!reason)
|
||||
SV_BroadcastPrintf (PRINT_CHAT, "Server recording completed\n");
|
||||
else
|
||||
SV_BroadcastPrintf (PRINT_CHAT,
|
||||
"Server recording stoped\nMax demo size exceeded\n");
|
||||
SV_BroadcastPrintf (PRINT_CHAT, "Server recording stoped\n"
|
||||
"Max demo size exceeded\n");
|
||||
/*
|
||||
if (sv_onrecordfinish->string[0]) {
|
||||
extern redirect_t sv_redirected;
|
||||
|
@ -740,12 +732,15 @@ SV_WriteSetDemoMessage (void)
|
|||
static const char *
|
||||
SV_PrintTeams (void)
|
||||
{
|
||||
char teams[MAX_CLIENTS][128];
|
||||
const char *teams[MAX_CLIENTS];
|
||||
char *p;
|
||||
int i, j, numcl = 0, numt = 0;
|
||||
client_t *clients[MAX_CLIENTS];
|
||||
char buf[2048] = { 0 };
|
||||
const char *team;
|
||||
static dstring_t *buffer;
|
||||
|
||||
if (!buffer)
|
||||
buffer = dstring_new ();
|
||||
|
||||
// count teams and players
|
||||
for (i = 0; i < MAX_CLIENTS; i++) {
|
||||
|
@ -756,42 +751,43 @@ SV_PrintTeams (void)
|
|||
|
||||
team = Info_ValueForKey (svs.clients[i].userinfo, "team");
|
||||
clients[numcl++] = &svs.clients[i];
|
||||
|
||||
for (j = 0; j < numt; j++)
|
||||
if (!strcmp (team, teams[j]))
|
||||
break;
|
||||
if (j != numt)
|
||||
continue;
|
||||
|
||||
strcpy (teams[numt++], team);
|
||||
teams[numt++] = team;
|
||||
}
|
||||
|
||||
// create output
|
||||
|
||||
if (numcl == 2) // duel
|
||||
{
|
||||
sprintf (buf, "team1 %s\nteam2 %s\n", clients[0]->name,
|
||||
dsprintf (buffer, "team1 %s\nteam2 %s\n", clients[0]->name,
|
||||
clients[1]->name);
|
||||
} else if (!teamplay->int_val) // ffa
|
||||
{
|
||||
sprintf (buf, "players:\n");
|
||||
dsprintf (buffer, "players:\n");
|
||||
for (i = 0; i < numcl; i++)
|
||||
sprintf (buf + strlen (buf), " %s\n", clients[i]->name);
|
||||
dasprintf (buffer, " %s\n", clients[i]->name);
|
||||
} else { // teamplay
|
||||
for (j = 0; j < numt; j++) {
|
||||
sprintf (buf + strlen (buf), "team %s:\n", teams[j]);
|
||||
dasprintf (buffer, "team %s:\n", teams[j]);
|
||||
for (i = 0; i < numcl; i++) {
|
||||
team = Info_ValueForKey (svs.clients[i].userinfo, "team");
|
||||
if (!strcmp (team, teams[j]))
|
||||
sprintf (buf + strlen (buf), " %s\n", clients[i]->name);
|
||||
dasprintf (buffer, " %s\n", clients[i]->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!numcl)
|
||||
return "\n";
|
||||
for (p = buf; *p; p++)
|
||||
for (p = buffer->str; *p; p++)
|
||||
*p = sys_char_map[(byte) * p];
|
||||
return va ("%s", buf);
|
||||
return buffer->str;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -806,19 +802,21 @@ SV_Record (char *name)
|
|||
sizebuf_t buf;
|
||||
char buf_data[MAX_MSGLEN];
|
||||
int n, i;
|
||||
char path[MAX_OSPATH];
|
||||
const char *info;
|
||||
dstring_t *tn = demo.name, *tp = demo.path;
|
||||
|
||||
client_t *player;
|
||||
const char *gamedir, *s;
|
||||
int seq = 1;
|
||||
|
||||
{
|
||||
// save over memset
|
||||
dstring_t *tn = demo.name, *tt = demo.text;
|
||||
memset (&demo, 0, sizeof (demo));
|
||||
dstring_clearstr (demo.name = tn);
|
||||
dstring_clearstr (demo.text = tt);
|
||||
}
|
||||
for (i = 0; i < UPDATE_BACKUP; i++)
|
||||
demo.recorder.frames[i].entities.entities = demo_entities[i];
|
||||
dstring_clearstr (demo.name = tn);
|
||||
dstring_clearstr (demo.path = tp);
|
||||
|
||||
DemoBuffer_Init (&demo.dbuffer, demo.buffer, sizeof (demo.buffer));
|
||||
DemoSetMsgBuf (NULL, &demo.frames[0].buf);
|
||||
|
@ -835,45 +833,36 @@ SV_Record (char *name)
|
|||
SV_InitRecord ();
|
||||
|
||||
s = name + strlen (name);
|
||||
while (*s != '/')
|
||||
while (s > name && *s != '/')
|
||||
s--;
|
||||
dstring_clearstr (demo.name);
|
||||
dstring_clearstr (demo.path);
|
||||
dstring_appendstr (demo.name, s + 1);
|
||||
dstring_appendstr (demo.path, sv_demoDir->string);
|
||||
dstring_copystr (demo.name, s + (*s == '/'));
|
||||
|
||||
if (demo.path->size < 2)
|
||||
dstring_appendstr (demo.path, ".");
|
||||
|
||||
SV_BroadcastPrintf (PRINT_CHAT, "Server starts recording (%s):\n%s\n",
|
||||
SV_BroadcastPrintf (PRINT_CHAT, "Server started recording (%s):\n%s\n",
|
||||
demo.disk ? "disk" : "memory", demo.name->str);
|
||||
Cvar_Set (serverdemo, demo.name->str);
|
||||
|
||||
strcpy (path, name);
|
||||
strcpy (path + strlen (path) - 3, "txt");
|
||||
dstring_copystr (demo.text, name);
|
||||
strcpy (demo.text->str + strlen (demo.text->str) - 3, "txt");
|
||||
|
||||
if (sv_demotxt->int_val) {
|
||||
QFile *f;
|
||||
|
||||
f = QFS_Open (path, "w+t");
|
||||
f = QFS_Open (demo.text->str, "w+t");
|
||||
if (f != NULL) {
|
||||
char buf[2000];
|
||||
char date[20];
|
||||
time_t tim;
|
||||
|
||||
time (&tim);
|
||||
strftime (date, 19, "%Y-%m-%d-%H-%M", localtime (&tim));
|
||||
|
||||
sprintf (buf, "date %s\nmap %s\nteamplay %d\ndeathmatch %d\n"
|
||||
strftime (date, sizeof (date), "%Y-%m-%d-%H-%M", localtime (&tim));
|
||||
Qprintf (f, "date %s\nmap %s\nteamplay %d\ndeathmatch %d\n"
|
||||
"timelimit %d\n%s",
|
||||
date, sv.name, teamplay->int_val,
|
||||
deathmatch->int_val, timelimit->int_val, SV_PrintTeams ());
|
||||
Qwrite (f, buf, strlen (buf));
|
||||
Qflush (f);
|
||||
deathmatch->int_val, timelimit->int_val,
|
||||
SV_PrintTeams ());
|
||||
Qclose (f);
|
||||
}
|
||||
} else
|
||||
unlink (path);
|
||||
QFS_Remove (demo.text->str);
|
||||
|
||||
sv.demorecording = true;
|
||||
demo.pingtime = demo.time = sv.time;
|
||||
|
@ -1061,23 +1050,25 @@ SV_Record (char *name)
|
|||
static char *
|
||||
SV_CleanName (const unsigned char *name)
|
||||
{
|
||||
static char text[1024];
|
||||
char *out = text;
|
||||
static char *text;
|
||||
static size_t text_len;
|
||||
char *out, c;
|
||||
|
||||
*out = sys_char_map[*name++];
|
||||
if (text_len < strlen (name)) {
|
||||
text_len = (strlen (name) + 1023) & ~1023;
|
||||
text = realloc (text, text_len);
|
||||
}
|
||||
|
||||
while (*name)
|
||||
if (*out == '_' && sys_char_map[*name] == '_')
|
||||
name++;
|
||||
else
|
||||
*++out = sys_char_map[*name++];
|
||||
out = text;
|
||||
do {
|
||||
c = sys_char_map[*name++];
|
||||
if (c != '_')
|
||||
*out++ = c;
|
||||
} while (c);
|
||||
|
||||
*++out = 0;
|
||||
return text;
|
||||
}
|
||||
|
||||
#define MAX_DEMO_NAME 64 // FIXME
|
||||
|
||||
/*
|
||||
SV_Record_f
|
||||
|
||||
|
@ -1253,7 +1244,7 @@ Demo_Init (void)
|
|||
}
|
||||
|
||||
demo.name = dstring_newstr ();
|
||||
demo.path = dstring_newstr ();
|
||||
demo.text = dstring_newstr ();
|
||||
|
||||
svs.demomem = Hunk_AllocName (size, "demo");
|
||||
svs.demomemsize = size;
|
||||
|
|
|
@ -1361,8 +1361,8 @@ PF_logfrag (progs_t *pr)
|
|||
|
||||
// do gib event callback
|
||||
if (sv_frag_e->func) {
|
||||
char buf[16]; //FIXME: overflow
|
||||
char type1[2], type2[2]; //FIXME: overflow
|
||||
char buf[16];
|
||||
char type1[2], type2[2];
|
||||
int u1, u2;
|
||||
|
||||
type1[1] = type2[1] = 0;
|
||||
|
|
|
@ -558,15 +558,15 @@ SV_Begin_f (void *unused)
|
|||
static void
|
||||
SV_NextDownload_f (void *unused)
|
||||
{
|
||||
byte buffer[1024];
|
||||
byte buffer[768]; // FIXME protocol limit? could be bigger?
|
||||
int percent, size, r;
|
||||
|
||||
if (!host_client->download)
|
||||
return;
|
||||
|
||||
r = host_client->downloadsize - host_client->downloadcount;
|
||||
if (r > 768)
|
||||
r = 768;
|
||||
if (r > sizeof (buffer))
|
||||
r = sizeof (buffer);
|
||||
r = Qread (host_client->download, buffer, r);
|
||||
ClientReliableWrite_Begin (host_client, svc_download, 6 + r);
|
||||
ClientReliableWrite_Short (host_client, r);
|
||||
|
@ -741,29 +741,16 @@ static void
|
|||
SV_Say (qboolean team)
|
||||
{
|
||||
char *i, *p;
|
||||
char text[2048], t1[32];
|
||||
const char *t2, *type;
|
||||
dstring_t *text;
|
||||
const char *t1 = 0, *t2, *type, *fmt;
|
||||
client_t *client;
|
||||
int tmp, j, cls = 0;
|
||||
|
||||
if (Cmd_Argc () < 2)
|
||||
return;
|
||||
|
||||
if (team) {
|
||||
strncpy (t1, Info_ValueForKey (host_client->userinfo, "team"), 31);
|
||||
t1[31] = 0;
|
||||
}
|
||||
|
||||
if (host_client->spectator && (!sv_spectalk->int_val || team)) {
|
||||
snprintf (text, sizeof (text), "[SPEC] %s: ", host_client->name);
|
||||
type = "2";
|
||||
} else if (team) {
|
||||
snprintf (text, sizeof (text), "(%s): ", host_client->name);
|
||||
type = "1";
|
||||
} else {
|
||||
snprintf (text, sizeof (text), "%s: ", host_client->name);
|
||||
type = "0";
|
||||
}
|
||||
if (team)
|
||||
t1 = Info_ValueForKey (host_client->userinfo, "team");
|
||||
|
||||
if (fp_messages) {
|
||||
if (!sv.paused && realtime < host_client->lockedtill) {
|
||||
|
@ -793,6 +780,20 @@ SV_Say (qboolean team)
|
|||
host_client->whensaid[host_client->whensaidhead] = realtime;
|
||||
}
|
||||
|
||||
text = dstring_new ();
|
||||
|
||||
if (host_client->spectator && (!sv_spectalk->int_val || team)) {
|
||||
fmt = "[SPEC] %s: ";
|
||||
type = "2";
|
||||
} else if (team) {
|
||||
fmt = "(%s): ";
|
||||
type = "1";
|
||||
} else {
|
||||
fmt = "%s: ";
|
||||
type = "0";
|
||||
}
|
||||
dsprintf (text, fmt, host_client->name);
|
||||
|
||||
p = Hunk_TempAlloc (strlen (Cmd_Args (1)) + 1);
|
||||
strcpy (p, Cmd_Args (1));
|
||||
|
||||
|
@ -810,6 +811,7 @@ SV_Say (qboolean team)
|
|||
SV_ClientPrintf (1, host_client, PRINT_HIGH, "You were kicked "
|
||||
"for attempting to fake messages\n");
|
||||
SV_DropClient (host_client);
|
||||
dstring_delete (text);
|
||||
return;
|
||||
} else
|
||||
*i = '#';
|
||||
|
@ -819,10 +821,8 @@ SV_Say (qboolean team)
|
|||
GIB_Event_Callback (sv_chat_e, 2, va ("%i", host_client->userid), p,
|
||||
type);
|
||||
|
||||
strncat (text, p, sizeof (text) - strlen (text));
|
||||
strncat (text, "\n", sizeof (text) - strlen (text));
|
||||
|
||||
SV_Printf ("%s", text);
|
||||
dstring_appendstr (text, p);
|
||||
dstring_appendstr (text, "\n");
|
||||
|
||||
for (j = 0, client = svs.clients; j < MAX_CLIENTS; j++, client++) {
|
||||
if (client->state < cs_connected) // Clients connecting can hear.
|
||||
|
@ -843,22 +843,25 @@ SV_Say (qboolean team)
|
|||
}
|
||||
}
|
||||
cls |= 1 << j;
|
||||
SV_ClientPrintf (0, client, PRINT_CHAT, "%s", text);
|
||||
SV_ClientPrintf (0, client, PRINT_CHAT, "%s", text->str);
|
||||
}
|
||||
|
||||
if (!sv.demorecording || !cls)
|
||||
if (!sv.demorecording || !cls) {
|
||||
dstring_delete (text);
|
||||
return;
|
||||
}
|
||||
// non-team messages should be seen allways, even if not tracking any
|
||||
// player
|
||||
if (!team && ((host_client->spectator && sv_spectalk->value)
|
||||
|| !host_client->spectator)) {
|
||||
DemoWrite_Begin (dem_all, 0, strlen (text) + 3);
|
||||
DemoWrite_Begin (dem_all, 0, strlen (text->str) + 3);
|
||||
} else {
|
||||
DemoWrite_Begin (dem_multiple, cls, strlen (text) + 3);
|
||||
DemoWrite_Begin (dem_multiple, cls, strlen (text->str) + 3);
|
||||
}
|
||||
MSG_WriteByte (&demo.dbuf->sz, svc_print);
|
||||
MSG_WriteByte (&demo.dbuf->sz, PRINT_CHAT);
|
||||
MSG_WriteString (&demo.dbuf->sz, text);
|
||||
MSG_WriteString (&demo.dbuf->sz, text->str);
|
||||
dstring_delete (text);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1084,7 +1087,7 @@ SV_Msg_f (void *unused)
|
|||
static void
|
||||
SV_SetInfo_f (void *unused)
|
||||
{
|
||||
char oldval[MAX_INFO_STRING];
|
||||
char *oldval;
|
||||
|
||||
if (Cmd_Argc () == 1) {
|
||||
SV_Printf ("User info settings:\n");
|
||||
|
@ -1100,22 +1103,20 @@ SV_SetInfo_f (void *unused)
|
|||
if (Cmd_Argv (1)[0] == '*')
|
||||
return; // don't set priveledged values
|
||||
|
||||
// preserve the old value
|
||||
strcpy (oldval, Info_ValueForKey (host_client->userinfo,
|
||||
Cmd_Argv (1)));
|
||||
|
||||
if (UserInfoCallback) {
|
||||
*sv_globals.self = EDICT_TO_PROG (&sv_pr_state, sv_player);
|
||||
P_STRING (&sv_pr_state, 0) = PR_SetString (&sv_pr_state, Cmd_Argv (1));
|
||||
P_STRING (&sv_pr_state, 1) = PR_SetString (&sv_pr_state, Cmd_Argv (2));
|
||||
PR_ExecuteProgram (&sv_pr_state, UserInfoCallback);
|
||||
return;
|
||||
} else {
|
||||
Info_SetValueForKey (host_client->userinfo, Cmd_Argv (1), Cmd_Argv (2),
|
||||
!sv_highchars->int_val);
|
||||
if (strequal
|
||||
(Info_ValueForKey (host_client->userinfo, Cmd_Argv (1)), oldval))
|
||||
return; // key hasn't changed
|
||||
}
|
||||
|
||||
oldval = strdup (Info_ValueForKey (host_client->userinfo, Cmd_Argv (1)));
|
||||
if (!Info_SetValueForKey (host_client->userinfo, Cmd_Argv (1),
|
||||
Cmd_Argv (2), !sv_highchars->int_val)) {
|
||||
// key hasn't changed
|
||||
free (oldval);
|
||||
return;
|
||||
}
|
||||
|
||||
// process any changed values
|
||||
|
@ -1127,6 +1128,7 @@ SV_SetInfo_f (void *unused)
|
|||
Cmd_Argv (1), oldval,
|
||||
Info_ValueForKey (host_client->userinfo,
|
||||
Cmd_Argv (1)));
|
||||
free (oldval);
|
||||
|
||||
if (Info_FilterForKey (Cmd_Argv (1), client_info_filters)) {
|
||||
MSG_WriteByte (&sv.reliable_datagram, svc_setinfo);
|
||||
|
|
Loading…
Reference in a new issue