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:
Bill Currie 2003-08-05 01:45:52 +00:00
parent 59c26b5ce0
commit ada828bdc9
12 changed files with 246 additions and 310 deletions

View file

@ -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

View file

@ -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);
}

View file

@ -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';

View file

@ -183,7 +183,7 @@ static void
SV_SendServerinfo (client_t *client)
{
const char **s;
char message[2048];
char message[2048];
MSG_WriteByte (&client->message, svc_print);
snprintf (message, sizeof (message), "%c\nVersion %s server (%i CRC)", 2,

View file

@ -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];

View file

@ -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);
}
/*

View file

@ -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);

View file

@ -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;

View file

@ -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
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);
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);
MSG_WriteByte (&demo.dbuf->sz, svc_print);
MSG_WriteByte (&demo.dbuf->sz, PRINT_CHAT);
MSG_WriteString (&demo.dbuf->sz, 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->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->str) + 3);
MSG_WriteByte (&demo.dbuf->sz, svc_print);
MSG_WriteByte (&demo.dbuf->sz, PRINT_CHAT);
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

View file

@ -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,
clients[1]->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;
memset (&demo, 0, sizeof (demo));
{
// 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;
@ -1058,26 +1047,28 @@ SV_Record (char *name)
Cleans the demo name, removes restricted chars, makes name lowercase
*/
static char *
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;

View file

@ -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;

View file

@ -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 = '#';
@ -818,11 +820,9 @@ SV_Say (qboolean team)
if (sv_chat_e->func)
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);