1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3 
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 
13 See the GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 
19 */
20 // common.c -- misc functions used in client and server
21 
22 #include "qwsvdef.h"
23 
24 usercmd_t nullcmd; // guarenteed to be zero
25 
26 static char *largv[MAX_NUM_ARGVS + 1];
27 
28 //============================================================================
29 
30 
31 
32 /*
33 ==============================================================================
34 
35 			MESSAGE IO FUNCTIONS
36 
37 Handles byte ordering and avoids alignment errors
38 ==============================================================================
39 */
40 
41 #ifdef FTE_PEXT_FLOATCOORDS
42 
43 int msg_coordsize = 2; // 2 or 4.
44 int msg_anglesize = 1; // 1 or 2.
45 
MSG_FromCoord(coorddata c,int bytes)46 float MSG_FromCoord(coorddata c, int bytes)
47 {
48 	switch(bytes)
49 	{
50 	case 2:	//encode 1/8th precision, giving -4096 to 4096 map sizes
51 		return LittleShort(c.b2)/8.0f;
52 	case 4:
53 		return LittleFloat(c.f);
54 	default:
55 		Sys_Error("MSG_FromCoord: not a sane size");
56 		return 0;
57 	}
58 }
59 
MSG_ToCoord(float f,int bytes)60 coorddata MSG_ToCoord(float f, int bytes)	//return value should be treated as (char*)&ret;
61 {
62 	coorddata r;
63 	switch(bytes)
64 	{
65 	case 2:
66 		r.b4 = 0;
67 		if (f >= 0)
68 			r.b2 = LittleShort((short)(f*8+0.5f));
69 		else
70 			r.b2 = LittleShort((short)(f*8-0.5f));
71 		break;
72 	case 4:
73 		r.f = LittleFloat(f);
74 		break;
75 	default:
76 		Sys_Error("MSG_ToCoord: not a sane size");
77 		r.b4 = 0;
78 	}
79 
80 	return r;
81 }
82 
MSG_ToAngle(float f,int bytes)83 coorddata MSG_ToAngle(float f, int bytes)	//return value is NOT byteswapped.
84 {
85 	coorddata r;
86 	switch(bytes)
87 	{
88 	case 1:
89 		r.b4 = 0;
90 		if (f >= 0)
91 			r.b[0] = (int)(f*(256.0f/360.0f) + 0.5f) & 255;
92 		else
93 			r.b[0] = (int)(f*(256.0f/360.0f) - 0.5f) & 255;
94 		break;
95 	case 2:
96 		r.b4 = 0;
97 		if (f >= 0)
98 			r.b2 = LittleShort((int)(f*(65536.0f/360.0f) + 0.5f) & 65535);
99 		else
100 			r.b2 = LittleShort((int)(f*(65536.0f/360.0f) - 0.5f) & 65535);
101 		break;
102 //	case 4:
103 //		r.f = LittleFloat(f);
104 //		break;
105 	default:
106 		Sys_Error("MSG_ToAngle: not a sane size");
107 		r.b4 = 0;
108 	}
109 
110 	return r;
111 }
112 
113 #endif
114 
115 // writing functions
116 
MSG_WriteChar(sizebuf_t * sb,const int c)117 void MSG_WriteChar (sizebuf_t *sb, const int c)
118 {
119 	byte *buf;
120 
121 #ifdef PARANOID
122 	if (c < -128 || c > 127)
123 		Sys_Error ("MSG_WriteChar: range error");
124 #endif
125 
126 	buf = (byte *) SZ_GetSpace (sb, 1);
127 	buf[0] = c;
128 }
129 
MSG_WriteByte(sizebuf_t * sb,const int c)130 void MSG_WriteByte (sizebuf_t *sb, const int c)
131 {
132 	byte *buf;
133 
134 #ifdef PARANOID
135 	if (c < 0 || c > 255)
136 		Sys_Error ("MSG_WriteByte: range error");
137 #endif
138 
139 	buf = (byte *) SZ_GetSpace (sb, 1);
140 	buf[0] = c;
141 }
142 
MSG_WriteShort(sizebuf_t * sb,const int c)143 void MSG_WriteShort (sizebuf_t *sb, const int c)
144 {
145 	byte *buf;
146 
147 #ifdef PARANOID
148 	if (c < ((short)0x8000) || c > (short)0x7fff)
149 		Sys_Error ("MSG_WriteShort: range error");
150 #endif
151 
152 	buf = (byte *) SZ_GetSpace (sb, 2);
153 	buf[0] = c&0xff;
154 	buf[1] = c>>8;
155 }
156 
MSG_WriteLong(sizebuf_t * sb,const int c)157 void MSG_WriteLong (sizebuf_t *sb, const int c)
158 {
159 	byte *buf;
160 
161 	buf = (byte *) SZ_GetSpace (sb, 4);
162 	buf[0] = c&0xff;
163 	buf[1] = (c>>8)&0xff;
164 	buf[2] = (c>>16)&0xff;
165 	buf[3] = c>>24;
166 }
167 
MSG_WriteFloat(sizebuf_t * sb,const float f)168 void MSG_WriteFloat (sizebuf_t *sb, const float f)
169 {
170 	union
171 	{
172 		float f;
173 		int l;
174 	} dat;
175 
176 
177 	dat.f = f;
178 	dat.l = LittleLong (dat.l);
179 
180 	SZ_Write (sb, &dat.l, 4);
181 }
182 
MSG_WriteString(sizebuf_t * sb,const char * s)183 void MSG_WriteString (sizebuf_t *sb, const char *s)
184 {
185 	if (!s || !*s)
186 		SZ_Write (sb, "", 1);
187 	else
188 		SZ_Write (sb, s, strlen(s)+1);
189 }
190 
MSG_WriteCoord(sizebuf_t * sb,const float f)191 void MSG_WriteCoord (sizebuf_t *sb, const float f)
192 {
193 #ifdef FTE_PEXT_FLOATCOORDS
194 	coorddata i = MSG_ToCoord(f, msg_coordsize);
195 	SZ_Write (sb, (void*)&i, msg_coordsize);
196 #else
197 	MSG_WriteShort (sb, (int)(f * 8));
198 #endif
199 }
200 
MSG_WriteLongCoord(sizebuf_t * sb,float f)201 void MSG_WriteLongCoord(sizebuf_t* sb, float f)
202 {
203 	f = LittleFloat(f);
204 
205 	SZ_Write (sb, (void*)&f, sizeof(f));
206 }
207 
MSG_WriteAngle(sizebuf_t * sb,const float f)208 void MSG_WriteAngle (sizebuf_t *sb, const float f)
209 {
210 #ifdef FTE_PEXT_FLOATCOORDS
211 	if (msg_anglesize == 2)
212 		MSG_WriteAngle16(sb, f);
213 //	else if (msg_anglesize==4)
214 //		MSG_WriteFloat(sb, f);
215 	else
216 #endif
217 		MSG_WriteByte (sb, Q_rint(f * 256.0 / 360.0) & 255);
218 }
219 
MSG_WriteAngle16(sizebuf_t * sb,const float f)220 void MSG_WriteAngle16 (sizebuf_t *sb, const float f)
221 {
222 	MSG_WriteShort (sb, Q_rint(f*65536.0/360.0) & 65535);
223 }
224 
MSG_WriteDeltaUsercmd(sizebuf_t * buf,const usercmd_t * from,const usercmd_t * cmd,unsigned int mvdsv_extensions)225 void MSG_WriteDeltaUsercmd (sizebuf_t *buf, const usercmd_t *from, const usercmd_t *cmd, unsigned int mvdsv_extensions)
226 {
227 	int bits;
228 
229 	// send the movement message
230 	bits = 0;
231 	if (cmd->angles[0] != from->angles[0])
232 		bits |= CM_ANGLE1;
233 	if (cmd->angles[1] != from->angles[1])
234 		bits |= CM_ANGLE2;
235 	if (cmd->angles[2] != from->angles[2])
236 		bits |= CM_ANGLE3;
237 	if (cmd->forwardmove != from->forwardmove)
238 		bits |= CM_FORWARD;
239 	if (cmd->sidemove != from->sidemove)
240 		bits |= CM_SIDE;
241 	if (cmd->upmove != from->upmove)
242 		bits |= CM_UP;
243 	if (cmd->buttons != from->buttons)
244 		bits |= CM_BUTTONS;
245 	if (cmd->impulse != from->impulse)
246 		bits |= CM_IMPULSE;
247 
248 	MSG_WriteByte (buf, bits);
249 
250 	if (bits & CM_ANGLE1)
251 		MSG_WriteAngle16 (buf, cmd->angles[0]);
252 	if (bits & CM_ANGLE2)
253 		MSG_WriteAngle16 (buf, cmd->angles[1]);
254 	if (bits & CM_ANGLE3)
255 		MSG_WriteAngle16 (buf, cmd->angles[2]);
256 
257 	if (bits & CM_FORWARD)
258 		MSG_WriteShort (buf, cmd->forwardmove);
259 	if (bits & CM_SIDE)
260 		MSG_WriteShort (buf, cmd->sidemove);
261 	if (bits & CM_UP)
262 		MSG_WriteShort (buf, cmd->upmove);
263 
264 	if (bits & CM_BUTTONS)
265 		MSG_WriteByte (buf, cmd->buttons);
266 	if (bits & CM_IMPULSE)
267 		MSG_WriteByte (buf, cmd->impulse);
268 
269 	MSG_WriteByte (buf, cmd->msec);
270 }
271 
272 
273 // reading functions
274 
275 int msg_readcount;
276 qbool msg_badread;
277 
MSG_BeginReading(void)278 void MSG_BeginReading (void)
279 {
280 	msg_readcount = 0;
281 	msg_badread = false;
282 }
283 
MSG_GetReadCount(void)284 int MSG_GetReadCount (void)
285 {
286 	return msg_readcount;
287 }
288 
289 // returns -1 and sets msg_badread if no more characters are available
MSG_ReadChar(void)290 int MSG_ReadChar (void)
291 {
292 	int c;
293 
294 	if (msg_readcount + 1 > net_message.cursize)
295 	{
296 		msg_badread = true;
297 		return -1;
298 	}
299 
300 	c = (signed char) net_message.data[msg_readcount];
301 	msg_readcount++;
302 
303 	return c;
304 }
305 
MSG_ReadByte(void)306 int MSG_ReadByte (void)
307 {
308 	int c;
309 
310 	if (msg_readcount + 1 > net_message.cursize)
311 	{
312 		msg_badread = true;
313 		return -1;
314 	}
315 
316 	c = (unsigned char) net_message.data[msg_readcount];
317 	msg_readcount++;
318 
319 	return c;
320 }
321 
MSG_ReadShort(void)322 int MSG_ReadShort (void)
323 {
324 	int c;
325 
326 	if (msg_readcount + 2 > net_message.cursize)
327 	{
328 		msg_badread = true;
329 		return -1;
330 	}
331 
332 	c = (short) (net_message.data[msg_readcount]
333 		+ (net_message.data[msg_readcount+1]<<8));
334 
335 	msg_readcount += 2;
336 
337 	return c;
338 }
339 
MSG_ReadLong(void)340 int MSG_ReadLong (void)
341 {
342 	int c;
343 
344 	if (msg_readcount + 4 > net_message.cursize)
345 	{
346 		msg_badread = true;
347 		return -1;
348 	}
349 
350 	c = net_message.data[msg_readcount]
351 		+ (net_message.data[msg_readcount+1]<<8)
352 		+ (net_message.data[msg_readcount+2]<<16)
353 		+ (net_message.data[msg_readcount+3]<<24);
354 
355 	msg_readcount += 4;
356 
357 	return c;
358 }
359 
MSG_ReadFloat(void)360 float MSG_ReadFloat (void)
361 {
362 	union
363 	{
364 		byte b[4];
365 		float f;
366 		int l;
367 	} dat;
368 
369 	dat.b[0] =	net_message.data[msg_readcount];
370 	dat.b[1] =	net_message.data[msg_readcount+1];
371 	dat.b[2] =	net_message.data[msg_readcount+2];
372 	dat.b[3] =	net_message.data[msg_readcount+3];
373 	msg_readcount += 4;
374 
375 	dat.l = LittleLong (dat.l);
376 
377 	return dat.f;
378 }
379 
MSG_ReadString(void)380 char *MSG_ReadString (void)
381 {
382 	static char string[2048];
383 	int c;
384 	size_t l = 0;
385 
386 	do
387 	{
388 		c = MSG_ReadByte ();
389 
390 		if (c == 255) // skip these to avoid security problems
391 			continue; // with old clients and servers
392 
393 		if (c == -1 || c == 0)
394 			break;
395 
396 		string[l] = c;
397 		l++;
398 	} while (l < sizeof (string) - 1);
399 
400 	string[l] = 0;
401 
402 	return string;
403 }
404 
MSG_ReadStringLine(void)405 char *MSG_ReadStringLine (void)
406 {
407 	static char string[2048];
408 	int c;
409 	size_t l = 0;
410 
411 	do
412 	{
413 		c = MSG_ReadByte ();
414 
415 		if (c == 255)
416 			continue;
417 
418 		if (c == -1 || c == 0 || c == '\n')
419 			break;
420 
421 		string[l] = c;
422 		l++;
423 	} while (l < sizeof (string) - 1);
424 
425 	string[l] = 0;
426 
427 	return string;
428 }
429 
MSG_ReadCoord(void)430 float MSG_ReadCoord (void)
431 {
432 #ifdef FTE_PEXT_FLOATCOORDS
433 
434 	coorddata c = {0};
435 	MSG_ReadData(&c, msg_coordsize);
436 	return MSG_FromCoord(c, msg_coordsize);
437 
438 #else // FTE_PEXT_FLOATCOORDS
439 
440 	return MSG_ReadShort() * (1.0 / 8);
441 
442 #endif // FTE_PEXT_FLOATCOORDS
443 }
444 
MSG_ReadAngle16(void)445 float MSG_ReadAngle16 (void)
446 {
447 	return MSG_ReadShort () * (360.0 / 65536);
448 }
449 
MSG_ReadAngle(void)450 float MSG_ReadAngle (void)
451 {
452 #ifdef FTE_PEXT_FLOATCOORDS
453 
454 	switch(msg_anglesize)
455 	{
456 	case 1:
457 		return MSG_ReadChar() * (360.0/256);
458 	case 2:
459 		return MSG_ReadAngle16();
460 //	case 4:
461 //		return MSG_ReadFloat();
462 	default:
463 		Sys_Error("MSG_ReadAngle: Bad angle size\n");
464 		return 0;
465 	}
466 
467 #else // FTE_PEXT_FLOATCOORDS
468 
469 	return MSG_ReadChar() * (360.0 / 256);
470 
471 #endif // FTE_PEXT_FLOATCOORDS
472 }
473 
MSG_ReadDeltaUsercmd(const usercmd_t * from,usercmd_t * move)474 void MSG_ReadDeltaUsercmd (const usercmd_t *from, usercmd_t *move)
475 {
476 	int bits;
477 
478 	memcpy (move, from, sizeof(*move));
479 
480 	bits = MSG_ReadByte ();
481 
482 	// read current angles
483 	if (bits & CM_ANGLE1)
484 		move->angles[0] = MSG_ReadAngle16 ();
485 	if (bits & CM_ANGLE2)
486 		move->angles[1] = MSG_ReadAngle16 ();
487 	if (bits & CM_ANGLE3)
488 		move->angles[2] = MSG_ReadAngle16 ();
489 
490 	// read movement
491 	if (bits & CM_FORWARD)
492 		move->forwardmove = MSG_ReadShort ();
493 	if (bits & CM_SIDE)
494 		move->sidemove = MSG_ReadShort ();
495 	if (bits & CM_UP)
496 		move->upmove = MSG_ReadShort ();
497 
498 	// read buttons
499 	if (bits & CM_BUTTONS)
500 		move->buttons = MSG_ReadByte ();
501 
502 	if (bits & CM_IMPULSE)
503 		move->impulse = MSG_ReadByte ();
504 
505 	// read time to run command
506 	move->msec = MSG_ReadByte ();
507 }
508 
MSG_ReadData(void * data,int len)509 void MSG_ReadData (void *data, int len)
510 {
511 	int	i;
512 
513 	for (i = 0 ; i < len ; i++)
514 		((byte *)data)[i] = MSG_ReadByte ();
515 }
516 
MSG_ReadSkip(int bytes)517 void MSG_ReadSkip(int bytes)
518 {
519 	for ( ; !msg_badread && bytes > 0; bytes--)
520 	{
521 		MSG_ReadByte ();
522 	}
523 }
524 
525 //===========================================================================
526 
SZ_InitEx(sizebuf_t * buf,byte * data,const int length,qbool allowoverflow)527 void SZ_InitEx (sizebuf_t *buf, byte *data, const int length, qbool allowoverflow)
528 {
529 	memset (buf, 0, sizeof (*buf));
530 	buf->data = data;
531 	buf->maxsize = length;
532 	buf->allowoverflow = allowoverflow;
533 }
534 
SZ_Init(sizebuf_t * buf,byte * data,const int length)535 void SZ_Init (sizebuf_t *buf, byte *data, const int length)
536 {
537 	SZ_InitEx (buf, data, length, false);
538 }
539 
SZ_Clear(sizebuf_t * buf)540 void SZ_Clear (sizebuf_t *buf)
541 {
542 	buf->cursize = 0;
543 	buf->overflowed = false;
544 }
545 
SZ_GetSpace(sizebuf_t * buf,const int length)546 void *SZ_GetSpace (sizebuf_t *buf, const int length)
547 {
548 	void *data;
549 
550 	if (buf->cursize + length > buf->maxsize)
551 	{
552 		if (!buf->allowoverflow)
553 			Sys_Error ("SZ_GetSpace: overflow without allowoverflow set (%d/%d/%d)",
554 			           buf->cursize, length, buf->maxsize);
555 
556 		if (length > buf->maxsize)
557 			Sys_Error ("SZ_GetSpace: %d/%d is > full buffer size",
558 			           length, buf->maxsize);
559 
560 		// because Con_Printf may be redirected
561 		Sys_Printf ("SZ_GetSpace: overflow: cur = %d, len = %d, max = %d\n",
562 		            buf->cursize, length, buf->maxsize);
563 		SZ_Clear (buf);
564 		buf->overflowed = true;
565 	}
566 
567 	data = buf->data + buf->cursize;
568 	buf->cursize += length;
569 
570 	return data;
571 }
572 
SZ_Write(sizebuf_t * buf,const void * data,int length)573 void SZ_Write (sizebuf_t *buf, const void *data, int length)
574 {
575 	byte* dest = SZ_GetSpace(buf, length);
576 
577 	memcpy(dest, data, length);
578 }
579 
SZ_Print(sizebuf_t * buf,const char * data)580 void SZ_Print (sizebuf_t *buf, const char *data)
581 {
582 	int len = strlen(data) + 1;
583 
584 	// Remove trailing '\0'
585 	if (buf->cursize && !buf->data[buf->cursize - 1]) {
586 		--buf->cursize;
587 	}
588 
589 	SZ_Write(buf, data, len);
590 }
591 
592 
593 //============================================================================
594 
595 #define TOKENSIZE sizeof(com_token)
596 char com_token[TOKENSIZE];
597 int com_argc;
598 char **com_argv;
599 
600 com_tokentype_t com_tokentype;
601 
602 /*
603 ==============
604 COM_Parse
605 
606 Parse a token out of a string
607 ==============
608 */
COM_Parse(const char * data)609 const char *COM_Parse (const char *data)
610 {
611 	unsigned char c;
612 	int len;
613 
614 	len = 0;
615 	com_token[0] = 0;
616 
617 	if (!data)
618 		return NULL;
619 
620 	// skip whitespace
621 	while (true)
622 	{
623 		while ((c = *data) == ' ' || c == '\t' || c == '\r' || c == '\n')
624 			data++;
625 
626 		if (c == 0)
627 			return NULL; // end of file;
628 
629 		// skip // comments
630 		if (c=='/' && data[1] == '/')
631 		{
632 			while (*data && *data != '\n')
633 				data++;
634 		}
635 		else
636 			break;
637 	}
638 
639 	// handle quoted strings specially
640 	if (c == '\"')
641 	{
642 		data++;
643 		while (1)
644 		{
645 			c = *data++;
646 			if (c == '\"' || !c)
647 			{
648 				com_token[len] = 0;
649 
650 				if (!c)
651 					data--;
652 
653 				return data;
654 			}
655 
656 			if (len < MAX_COM_TOKEN - 1)
657 			{
658 				com_token[len] = c;
659 				len++;
660 			}
661 		}
662 	}
663 
664 	// parse a regular word
665 	do
666 	{
667 		if (len < MAX_COM_TOKEN-1)
668 		{
669 			com_token[len] = c;
670 			len++;
671 		}
672 		data++;
673 		c = *data;
674 	}
675 	while (c && c != ' ' && c != '\t' && c != '\n' && c != '\r');
676 
677 	com_token[len] = 0;
678 	return data;
679 }
680 
681 #define DEFAULT_PUNCTUATION "(,{})(\':;=!><&|+"
COM_ParseToken(const char * data,const char * punctuation)682 char *COM_ParseToken (const char *data, const char *punctuation)
683 {
684 	int c;
685 	int	len;
686 
687 	if (!punctuation)
688 		punctuation = DEFAULT_PUNCTUATION;
689 
690 	len = 0;
691 	com_token[0] = 0;
692 
693 	if (!data)
694 	{
695 		com_tokentype = TTP_UNKNOWN;
696 		return NULL;
697 	}
698 
699 	// skip whitespace
700 skipwhite:
701 	while ((c = *(unsigned char *) data) <= ' ')
702 	{
703 		if (c == 0)
704 		{
705 			com_tokentype = TTP_UNKNOWN;
706 			return NULL; // end of file;
707 		}
708 
709 		data++;
710 	}
711 
712 	// skip // comments
713 	if (c == '/')
714 	{
715 		if (data[1] == '/')
716 		{
717 			while (*data && *data != '\n')
718 				data++;
719 
720 			goto skipwhite;
721 		}
722 		else if (data[1] == '*')
723 		{
724 			data += 2;
725 
726 			while (*data && (*data != '*' || data[1] != '/'))
727 				data++;
728 
729 			data += 2;
730 			goto skipwhite;
731 		}
732 	}
733 
734 
735 	// handle quoted strings specially
736 	if (c == '\"')
737 	{
738 		com_tokentype = TTP_STRING;
739 		data++;
740 		while (1)
741 		{
742 			if (len >= TOKENSIZE - 1)
743 			{
744 				com_token[len] = '\0';
745 				return (char*) data;
746 			}
747 
748 			c = *data++;
749 
750 			if (c=='\"' || !c)
751 			{
752 				com_token[len] = 0;
753 				return (char*) data;
754 			}
755 
756 			com_token[len] = c;
757 			len++;
758 		}
759 	}
760 
761 	com_tokentype = TTP_UNKNOWN;
762 
763 	// parse single characters
764 	if (strchr (punctuation, c))
765 	{
766 		com_token[len] = c;
767 		len++;
768 		com_token[len] = 0;
769 		return (char*) (data + 1);
770 	}
771 
772 	// parse a regular word
773 	do
774 	{
775 		if (len >= TOKENSIZE - 1)
776 			break;
777 
778 		com_token[len] = c;
779 		data++;
780 		len++;
781 		c = *data;
782 		if (strchr (punctuation, c))
783 			break;
784 
785 	} while (c > 32);
786 
787 	com_token[len] = 0;
788 	return (char*) data;
789 }
790 
791 /*
792 ================
793 COM_InitArgv
794 
795 ================
796 */
COM_InitArgv(int argc,char ** argv)797 void COM_InitArgv (int argc, char **argv)
798 {
799 	for (com_argc = 0; (com_argc < MAX_NUM_ARGVS) && (com_argc < argc); com_argc++)
800 	{
801 			largv[com_argc] = (argv[com_argc]) ? argv[com_argc] : "";
802 	}
803 
804 	largv[com_argc] = "";
805 	com_argv = largv;
806 }
807 
808 /*
809 ================
810 COM_CheckParm
811 
812 Returns the position (1 to argc-1) in the program's argument list
813 where the given parameter appears, or 0 if not present
814 ================
815 */
COM_CheckParm(const char * parm)816 int COM_CheckParm (const char *parm)
817 {
818 	int i;
819 
820 	for (i = 1; i < com_argc; i++)
821 	{
822 		if (!strcmp (parm,com_argv[i]))
823 			return i;
824 	}
825 
826 	return 0;
827 }
828 
COM_Argc(void)829 int COM_Argc (void)
830 {
831 	return com_argc;
832 }
833 
COM_Argv(int arg)834 char *COM_Argv (int arg)
835 {
836 	if (arg < 0 || arg >= com_argc)
837 		return "";
838 	return com_argv[arg];
839 }
840 
841 /*
842 =====================================================================
843 
844   INFO STRINGS
845 
846 =====================================================================
847 */
848 
849 /*
850 ===============
851 Info_ValueForKey
852 
853 Searches the string for the given
854 key and returns the associated value, or an empty string.
855 ===============
856 */
Info_ValueForKey(char * s,const char * key)857 char *Info_ValueForKey (char *s, const char *key)
858 {
859 	char	pkey[512];
860 	static	char value[4][512]; // use two buffers so compares
861 	// work without stomping on each other
862 	static	int valueindex;
863 	char	*o;
864 
865 	valueindex = (valueindex + 1) % 4;
866 	if (*s == '\\')
867 		s++;
868 	while (1)
869 	{
870 		o = pkey;
871 		while (*s != '\\')
872 		{
873 			if (!*s || o >= pkey + sizeof(pkey) - 1)
874 				return "";
875 			*o++ = *s++;
876 		}
877 		*o = 0;
878 		s++;
879 
880 		o = value[valueindex];
881 
882 		while (*s != '\\' && *s)
883 		{
884 			if (!*s || o >= value[valueindex] + sizeof(value[valueindex]) - 1)
885 				return "";
886 			*o++ = *s++;
887 		}
888 		*o = 0;
889 
890 		if (!strncmp (key, pkey, sizeof(pkey)) )
891 			return value[valueindex];
892 
893 		if (!*s)
894 			return "";
895 		s++;
896 	}
897 }
898 
899 /*
900 
901 // WARNING:		non standard behavior for Info_* function, this function may return NULL
902 			 	while other functions always return at least ""
903 
904 char *Info_KeyNameForKeyNum (char *s, int key)
905 {
906 	static char pkey[4][512]; // use two buffers so compares
907 	// work without stomping on each other
908 	static int keyindex;
909 	char *o;
910 
911 	keyindex = (keyindex + 1) % 4;
912 	if (*s == '\\')
913 		s++;
914 
915 	// ?
916 	if (key < 1)
917 		return NULL;
918 
919 	while (1)
920 	{
921 		key--;
922 
923 		// get key name
924 		o = pkey[keyindex];
925 		while (*s != '\\')
926 		{
927 			if (!*s || o >= pkey[keyindex] + sizeof(pkey[keyindex]) - 1)
928 				return NULL;
929 			*o++ = *s++;
930 		}
931 		*o = 0;
932 		s++;
933 
934 		// skip key value
935 		while (*s != '\\' && *s) s++;
936 
937 		if (!key)
938 			return pkey[keyindex];
939 
940 		if (!*s)
941 			return NULL;
942 		s++;
943 	}
944 }
945 
946 */
947 
948 
Info_RemoveKey(char * s,const char * key)949 void Info_RemoveKey (char *s, const char *key)
950 {
951 	char *start;
952 	char pkey[512];
953 	char value[512];
954 	char *o;
955 
956 	if (strstr (key, "\\"))
957 	{
958 		Con_Printf ("Can't use a key with a \\\n");
959 		return;
960 	}
961 
962 	while (1)
963 	{
964 		start = s;
965 		if (*s == '\\')
966 			s++;
967 		o = pkey;
968 		while (*s != '\\')
969 		{
970 			if (!*s || o >= pkey + sizeof(pkey) - 1)
971 				return;
972 			*o++ = *s++;
973 		}
974 		*o = 0;
975 		s++;
976 
977 		o = value;
978 		while (*s != '\\' && *s)
979 		{
980 			if (!*s || o >= value + sizeof(value) - 1)
981 				return;
982 			*o++ = *s++;
983 		}
984 		*o = 0;
985 
986 		if (!strncmp (key, pkey, sizeof(pkey)) )
987 		{
988 			memmove (start, s, strlen(s) + 1);	// remove this part
989 			return;
990 		}
991 
992 		if (!*s)
993 			return;
994 	}
995 
996 }
997 
Info_RemovePrefixedKeys(char * start,char prefix)998 void Info_RemovePrefixedKeys (char *start, char prefix)
999 {
1000 	char *s;
1001 	char pkey[512];
1002 	char value[512];
1003 	char *o;
1004 
1005 	s = start;
1006 
1007 	while (1)
1008 	{
1009 		if (*s == '\\')
1010 			s++;
1011 		o = pkey;
1012 		while (*s != '\\')
1013 		{
1014 			if (!*s || o >= pkey + sizeof(pkey) - 1)
1015 				return;
1016 			*o++ = *s++;
1017 		}
1018 		*o = 0;
1019 		s++;
1020 
1021 		o = value;
1022 		while (*s != '\\' && *s)
1023 		{
1024 			if (!*s || o >= value + sizeof(value) - 1)
1025 				return;
1026 			*o++ = *s++;
1027 		}
1028 		*o = 0;
1029 
1030 		if (pkey[0] == prefix)
1031 		{
1032 			Info_RemoveKey (start, pkey);
1033 			s = start;
1034 		}
1035 
1036 		if (!*s)
1037 			return;
1038 	}
1039 
1040 }
1041 
1042 
Info_SetValueForStarKey(char * s,const char * key,const char * value,unsigned int maxsize)1043 void Info_SetValueForStarKey (char *s, const char *key, const char *value, unsigned int maxsize)
1044 {
1045 	char _new[1024], *v;
1046 	int c;
1047 //	extern cvar_t sv_highchars;
1048 
1049 	if (strstr (key, "\\") || strstr (value, "\\") )
1050 	{
1051 		Con_Printf ("Can't use keys or values with a \\\n");
1052 		return;
1053 	}
1054 
1055 	if (strstr (key, "\"") || strstr (value, "\"") )
1056 	{
1057 		Con_Printf ("Can't use keys or values with a \"\n");
1058 		return;
1059 	}
1060 
1061 	if (strlen(key) >= MAX_KEY_STRING || strlen(value) >= MAX_KEY_STRING)
1062 	{
1063 		Con_Printf ("Keys and values must be < %d characters.\n", MAX_KEY_STRING);
1064 		return;
1065 	}
1066 
1067 	// this next line is kinda trippy
1068 	if (*(v = Info_ValueForKey(s, key)))
1069 	{
1070 		// key exists, make sure we have enough room for new value, if we don't,
1071 		// don't change it!
1072 		if (strlen(value) - strlen(v) + strlen(s) >= maxsize)
1073 		{
1074 			Con_Printf ("Info string length exceeded (change: key = '%s', old value = '%s', new value = '%s', strlen info = '%d', maxsize = '%d')\nFull info string: '%s'\n",
1075 			            key, v, value, strlen(s), maxsize, s);
1076 			return;
1077 		}
1078 	}
1079 	Info_RemoveKey (s, key);
1080 	if (!value || !strlen(value))
1081 		return;
1082 
1083 	snprintf (_new, sizeof(_new), "\\%s\\%s", key, value);
1084 
1085 	if (strlen(_new) + strlen(s) >= maxsize)
1086 	{
1087 		Con_Printf ("Info string length exceeded (add: key = '%s', value = '%s', strlen info = '%d', maxsize = '%d')\nFull info string: '%s'\n",
1088 		            key, value, strlen(s), maxsize, s);
1089 		return;
1090 	}
1091 
1092 	// only copy ascii values
1093 	s += strlen(s);
1094 	v = _new;
1095 	while (*v)
1096 	{
1097 		c = (unsigned char)*v++;
1098 /*
1099 		if (!(int)sv_highchars.value)
1100 		{
1101 			c &= 127;
1102 			if (c < 32 || c > 127)
1103 				continue;
1104 		}
1105 */
1106 		// c &= 127; // strip high bits
1107 		if (c > 13) // && c < 127)
1108 			*s++ = c;
1109 	}
1110 	*s = 0;
1111 }
1112 
Info_SetValueForKey(char * s,const char * key,const char * value,unsigned int maxsize)1113 void Info_SetValueForKey (char *s, const char *key, const char *value, unsigned int maxsize)
1114 {
1115 	if (key[0] == '*')
1116 	{
1117 		Con_Printf ("Can't set * keys\n");
1118 		return;
1119 	}
1120 
1121 	Info_SetValueForStarKey (s, key, value, maxsize);
1122 }
1123 
Info_Print(char * s)1124 void Info_Print (char *s)
1125 {
1126 	char key[512];
1127 	char value[512];
1128 	char *o;
1129 	int l;
1130 
1131 	if (*s == '\\')
1132 		s++;
1133 	while (*s)
1134 	{
1135 		o = key;
1136 		while (*s && *s != '\\')
1137 			*o++ = *s++;
1138 
1139 		l = o - key;
1140 		if (l < 20)
1141 		{
1142 			memset (o, ' ', 20-l);
1143 			key[20] = 0;
1144 		}
1145 		else
1146 			*o = 0;
1147 		Con_Printf ("%s ", key);
1148 
1149 		if (!*s)
1150 		{
1151 			Con_Printf ("MISSING VALUE\n");
1152 			return;
1153 		}
1154 
1155 		o = value;
1156 		s++;
1157 		while (*s && *s != '\\')
1158 			*o++ = *s++;
1159 		*o = 0;
1160 
1161 		if (*s)
1162 			s++;
1163 		Con_Printf ("%s\n", value);
1164 	}
1165 }
1166 
Info_CopyStarKeys(const char * from,char * to,unsigned int maxsize)1167 void Info_CopyStarKeys (const char *from, char *to, unsigned int maxsize)
1168 {
1169 	char key[512];
1170 	char value[512];
1171 	char *o;
1172 
1173 	if (*from == '\\')
1174 		from++;
1175 
1176 	while (*from)
1177 	{
1178 		o = key;
1179 		while (*from && *from != '\\')
1180 			*o++ = *from++;
1181 
1182 		*o = 0;
1183 
1184 		o = value;
1185 		from++;
1186 		while (*from && *from != '\\')
1187 			*o++ = *from++;
1188 		*o = 0;
1189 
1190 		if (*from)
1191 			from++;
1192 		if (key[0] == '*')
1193 			Info_SetValueForStarKey (to, key, value, maxsize);
1194 	}
1195 }
1196 
1197 //============================================================
1198 //
1199 // Alternative variant manipulation with info strings
1200 //
1201 //============================================================
1202 
1203 // this is seems to be "better" than Com_HashKey()
Info_HashKey(const char * str)1204 static unsigned long Info_HashKey (const char *str)
1205 {
1206 	unsigned long hash = 0;
1207 	int c;
1208 
1209 	// the (c&~32) makes it case-insensitive
1210 	// hash function known as sdbm, used in gawk
1211 	while ((c = *str++))
1212         hash = (c &~ 32) + (hash << 6) + (hash << 16) - hash;
1213 
1214     return hash;
1215 }
1216 
1217 // used internally
_Info_Get(ctxinfo_t * ctx,const char * name)1218 static info_t *_Info_Get (ctxinfo_t *ctx, const char *name)
1219 {
1220 	info_t *a;
1221 	int key;
1222 
1223 	if (!ctx || !name || !name[0])
1224 		return NULL;
1225 
1226 	key = Info_HashKey (name) % INFO_HASHPOOL_SIZE;
1227 
1228 	for (a = ctx->info_hash[key]; a; a = a->hash_next)
1229 		if (!strcasecmp(name, a->name))
1230 			return a;
1231 
1232 	return NULL;
1233 }
1234 
Info_Get(ctxinfo_t * ctx,const char * name)1235 char *Info_Get(ctxinfo_t *ctx, const char *name)
1236 {
1237 	static	char value[4][512];
1238 	static	int valueindex = 0;
1239 
1240 	info_t *a = _Info_Get(ctx, name);
1241 
1242 	if ( a )
1243 	{
1244 		valueindex = (valueindex + 1) % 4;
1245 
1246 		strlcpy(value[valueindex], a->value, sizeof(value[0]));
1247 
1248 		return value[valueindex];
1249 	}
1250 	else
1251 	{
1252 		return "";
1253 	}
1254 }
1255 
Info_SetStar(ctxinfo_t * ctx,const char * name,const char * value)1256 qbool Info_SetStar (ctxinfo_t *ctx, const char *name, const char *value)
1257 {
1258 	info_t	*a;
1259 	int key;
1260 
1261 	if (!value)
1262 		value = "";
1263 
1264 	if (!ctx || !name || !name[0])
1265 		return false;
1266 
1267 	// empty value, instead of set just remove it
1268 	if (!value[0])
1269 	{
1270 		return Info_Remove(ctx, name);
1271 	}
1272 
1273 	if (strchr(name, '\\') || strchr(value, '\\'))
1274 		return false;
1275 	if (strchr(name, 128 + '\\') || strchr(value, 128 + '\\'))
1276 		return false;
1277 	if (strchr(name, '"') || strchr(value, '"'))
1278 		return false;
1279 	if (strchr(name, '\r') || strchr(value, '\r')) // bad for print functions
1280 		return false;
1281 	if (strchr(name, '\n') || strchr(value, '\n')) // bad for print functions
1282 		return false;
1283 	if (strchr(name, '$') || strchr(value, '$')) // variable expansion may be exploited, escaping this
1284 		return false;
1285 	if (strchr(name, ';') || strchr(value, ';')) // interpreter may be haxed, escaping this
1286 		return false;
1287 
1288 	if (strlen(name) >= MAX_KEY_STRING || strlen(value) >= MAX_KEY_STRING)
1289 		return false; // too long name/value, its wrong
1290 
1291 	key = Info_HashKey(name) % INFO_HASHPOOL_SIZE;
1292 
1293 	// if already exists, reuse it
1294 	for (a = ctx->info_hash[key]; a; a = a->hash_next)
1295 		if (!strcasecmp(name, a->name))
1296 		{
1297 			Q_free (a->value);
1298 			break;
1299 		}
1300 
1301 	// not found, create new one
1302 	if (!a)
1303 	{
1304 		if (ctx->cur >= ctx->max)
1305 			return false; // too much infos
1306 
1307 		a = (info_t *) Q_malloc (sizeof(info_t));
1308 		a->next = ctx->info_list;
1309 		ctx->info_list = a;
1310 		a->hash_next = ctx->info_hash[key];
1311 		ctx->info_hash[key] = a;
1312 
1313 		ctx->cur++; // increase counter
1314 
1315 		// copy name
1316 		a->name = Q_strdup (name);
1317 	}
1318 
1319 	// copy value
1320 #if 0
1321 	{
1322 		// unfortunatelly evil users use non printable/control chars, so that does not work well
1323 		a->value = Q_strdup (value);
1324 	}
1325 #else
1326 	{
1327 		// skip some control chars, doh
1328 		char v_buf[MAX_KEY_STRING] = {0}, *v = v_buf;
1329 		int i;
1330 
1331 		for (i = 0; value[i]; i++) // len of 'value' should be less than MAX_KEY_STRING according to above checks
1332 		{
1333 			if ((unsigned char)value[i] > 13)
1334 				*v++ = value[i];
1335 		}
1336 		*v = 0;
1337 
1338 		a->value = Q_strdup (v_buf);
1339 	}
1340 #endif
1341 
1342 	// hrm, empty value, remove it then
1343 	if (!a->value[0])
1344 	{
1345 		return Info_Remove(ctx, name);
1346 	}
1347 
1348 	return true;
1349 }
1350 
Info_Set(ctxinfo_t * ctx,const char * name,const char * value)1351 qbool Info_Set (ctxinfo_t *ctx, const char *name, const char *value)
1352 {
1353 	if (!value)
1354 		value = "";
1355 
1356 	if (!ctx || !name || !name[0])
1357 		return false;
1358 
1359 	if (name[0] == '*')
1360 	{
1361 		Con_Printf ("Can't set * keys [%s]\n", name);
1362 		return false;
1363 	}
1364 
1365 	return Info_SetStar (ctx, name, value);
1366 }
1367 
1368 // used internally
_Info_Free(info_t * a)1369 static void _Info_Free(info_t *a)
1370 {
1371 	if (!a)
1372 		return;
1373 
1374 	Q_free (a->name);
1375 	Q_free (a->value);
1376 	Q_free (a);
1377 }
1378 
Info_Remove(ctxinfo_t * ctx,const char * name)1379 qbool Info_Remove (ctxinfo_t *ctx, const char *name)
1380 {
1381 	info_t *a, *prev;
1382 	int key;
1383 
1384 	if (!ctx || !name || !name[0])
1385 		return false;
1386 
1387 	key = Info_HashKey (name) % INFO_HASHPOOL_SIZE;
1388 
1389 	prev = NULL;
1390 	for (a = ctx->info_hash[key]; a; a = a->hash_next)
1391 	{
1392 		if (!strcasecmp(name, a->name))
1393 		{
1394 			// unlink from hash
1395 			if (prev)
1396 				prev->hash_next = a->hash_next;
1397 			else
1398 				ctx->info_hash[key] = a->hash_next;
1399 			break;
1400 		}
1401 		prev = a;
1402 	}
1403 
1404 	if (!a)
1405 		return false;	// not found
1406 
1407 	prev = NULL;
1408 	for (a = ctx->info_list; a; a = a->next)
1409 	{
1410 		if (!strcasecmp(name, a->name))
1411 		{
1412 			// unlink from info list
1413 			if (prev)
1414 				prev->next = a->next;
1415 			else
1416 				ctx->info_list = a->next;
1417 
1418 			// free
1419 			_Info_Free(a);
1420 
1421 			ctx->cur--; // decrease counter
1422 
1423 			return true;
1424 		}
1425 		prev = a;
1426 	}
1427 
1428 	Sys_Error("Info_Remove: info list broken");
1429 	return false; // shut up compiler
1430 }
1431 
1432 // remove all infos
Info_RemoveAll(ctxinfo_t * ctx)1433 void Info_RemoveAll (ctxinfo_t *ctx)
1434 {
1435 	info_t	*a, *next;
1436 
1437 	if (!ctx)
1438 		return;
1439 
1440 	for (a = ctx->info_list; a; a = next) {
1441 		next = a->next;
1442 
1443 		// free
1444 		_Info_Free(a);
1445 	}
1446 	ctx->info_list = NULL;
1447 	ctx->cur = 0; // set counter to 0
1448 
1449 	// clear hash
1450 	memset (ctx->info_hash, 0, sizeof(ctx->info_hash));
1451 }
1452 
Info_Convert(ctxinfo_t * ctx,char * str)1453 qbool Info_Convert(ctxinfo_t *ctx, char *str)
1454 {
1455 	char name[MAX_KEY_STRING], value[MAX_KEY_STRING], *start;
1456 
1457 	if (!ctx)
1458 		return false;
1459 
1460 	for ( ; str && str[0]; )
1461 	{
1462 		if (!(str = strchr(str, '\\')))
1463 			break;
1464 
1465 		start = str; // start of name
1466 
1467 		if (!(str = strchr(start + 1, '\\')))  // end of name
1468 			break;
1469 
1470 		strlcpy(name, start + 1, min(str - start, (int)sizeof(name)));
1471 
1472 		start = str; // start of value
1473 
1474 		str = strchr(start + 1, '\\'); // end of value
1475 
1476 		strlcpy(value, start + 1, str ? min(str - start, (int)sizeof(value)) : (int)sizeof(value));
1477 
1478 		Info_SetStar(ctx, name, value);
1479 	}
1480 
1481 	return true;
1482 }
1483 
Info_ReverseConvert(ctxinfo_t * ctx,char * str,int size)1484 qbool Info_ReverseConvert(ctxinfo_t *ctx, char *str, int size)
1485 {
1486 	info_t *a;
1487 	int next_size;
1488 
1489 	if (!ctx)
1490 		return false;
1491 
1492 	if (!str || size < 1)
1493 		return false;
1494 
1495 	str[0] = 0;
1496 
1497 	for (a = ctx->info_list; a; a = a->next)
1498 	{
1499 		if (!a->value[0])
1500 			continue; // empty
1501 
1502 		next_size = size - 2 - strlen(a->name) - strlen(a->value);
1503 
1504 		if (next_size < 1)
1505 		{
1506 			// sigh, next snprintf will not fit
1507 			return false;
1508 		}
1509 
1510 		snprintf(str, size, "\\%s\\%s", a->name, a->value);
1511 		str += (size - next_size);
1512 		size = next_size;
1513 	}
1514 
1515 	return true;
1516 }
1517 
Info_CopyStar(ctxinfo_t * ctx_from,ctxinfo_t * ctx_to)1518 qbool Info_CopyStar(ctxinfo_t *ctx_from, ctxinfo_t *ctx_to)
1519 {
1520 	info_t *a;
1521 
1522 	if (!ctx_from || !ctx_to)
1523 		return false;
1524 
1525 	if (ctx_from == ctx_to)
1526 		return true; // hrm
1527 
1528 	for (a = ctx_from->info_list; a; a = a->next)
1529 	{
1530 		if (a->name[0] != '*')
1531 			continue; // not a star key
1532 
1533 		// do we need check status of this function?
1534 		Info_SetStar (ctx_to, a->name, a->value);
1535 	}
1536 
1537 	return true;
1538 }
1539 
Info_PrintList(ctxinfo_t * ctx)1540 void Info_PrintList(ctxinfo_t *ctx)
1541 {
1542 	info_t *a;
1543 	int cnt = 0;
1544 
1545 	if (!ctx)
1546 		return;
1547 
1548 	for (a = ctx->info_list; a; a = a->next)
1549 	{
1550 		Con_Printf("%-20s %s\n", a->name, a->value);
1551 		cnt++;
1552 	}
1553 
1554 
1555 	Con_DPrintf("%d infos\n", cnt);
1556 }
1557 
1558 //============================================================================
1559 
1560 static byte chktbl[1024] = {
1561 	0x78,0xd2,0x94,0xe3,0x41,0xec,0xd6,0xd5,0xcb,0xfc,0xdb,0x8a,0x4b,0xcc,0x85,0x01,
1562 	0x23,0xd2,0xe5,0xf2,0x29,0xa7,0x45,0x94,0x4a,0x62,0xe3,0xa5,0x6f,0x3f,0xe1,0x7a,
1563 	0x64,0xed,0x5c,0x99,0x29,0x87,0xa8,0x78,0x59,0x0d,0xaa,0x0f,0x25,0x0a,0x5c,0x58,
1564 	0xfb,0x00,0xa7,0xa8,0x8a,0x1d,0x86,0x80,0xc5,0x1f,0xd2,0x28,0x69,0x71,0x58,0xc3,
1565 	0x51,0x90,0xe1,0xf8,0x6a,0xf3,0x8f,0xb0,0x68,0xdf,0x95,0x40,0x5c,0xe4,0x24,0x6b,
1566 	0x29,0x19,0x71,0x3f,0x42,0x63,0x6c,0x48,0xe7,0xad,0xa8,0x4b,0x91,0x8f,0x42,0x36,
1567 	0x34,0xe7,0x32,0x55,0x59,0x2d,0x36,0x38,0x38,0x59,0x9b,0x08,0x16,0x4d,0x8d,0xf8,
1568 	0x0a,0xa4,0x52,0x01,0xbb,0x52,0xa9,0xfd,0x40,0x18,0x97,0x37,0xff,0xc9,0x82,0x27,
1569 	0xb2,0x64,0x60,0xce,0x00,0xd9,0x04,0xf0,0x9e,0x99,0xbd,0xce,0x8f,0x90,0x4a,0xdd,
1570 	0xe1,0xec,0x19,0x14,0xb1,0xfb,0xca,0x1e,0x98,0x0f,0xd4,0xcb,0x80,0xd6,0x05,0x63,
1571 	0xfd,0xa0,0x74,0xa6,0x86,0xf6,0x19,0x98,0x76,0x27,0x68,0xf7,0xe9,0x09,0x9a,0xf2,
1572 	0x2e,0x42,0xe1,0xbe,0x64,0x48,0x2a,0x74,0x30,0xbb,0x07,0xcc,0x1f,0xd4,0x91,0x9d,
1573 	0xac,0x55,0x53,0x25,0xb9,0x64,0xf7,0x58,0x4c,0x34,0x16,0xbc,0xf6,0x12,0x2b,0x65,
1574 	0x68,0x25,0x2e,0x29,0x1f,0xbb,0xb9,0xee,0x6d,0x0c,0x8e,0xbb,0xd2,0x5f,0x1d,0x8f,
1575 	0xc1,0x39,0xf9,0x8d,0xc0,0x39,0x75,0xcf,0x25,0x17,0xbe,0x96,0xaf,0x98,0x9f,0x5f,
1576 	0x65,0x15,0xc4,0x62,0xf8,0x55,0xfc,0xab,0x54,0xcf,0xdc,0x14,0x06,0xc8,0xfc,0x42,
1577 	0xd3,0xf0,0xad,0x10,0x08,0xcd,0xd4,0x11,0xbb,0xca,0x67,0xc6,0x48,0x5f,0x9d,0x59,
1578 	0xe3,0xe8,0x53,0x67,0x27,0x2d,0x34,0x9e,0x9e,0x24,0x29,0xdb,0x69,0x99,0x86,0xf9,
1579 	0x20,0xb5,0xbb,0x5b,0xb0,0xf9,0xc3,0x67,0xad,0x1c,0x9c,0xf7,0xcc,0xef,0xce,0x69,
1580 	0xe0,0x26,0x8f,0x79,0xbd,0xca,0x10,0x17,0xda,0xa9,0x88,0x57,0x9b,0x15,0x24,0xba,
1581 	0x84,0xd0,0xeb,0x4d,0x14,0xf5,0xfc,0xe6,0x51,0x6c,0x6f,0x64,0x6b,0x73,0xec,0x85,
1582 	0xf1,0x6f,0xe1,0x67,0x25,0x10,0x77,0x32,0x9e,0x85,0x6e,0x69,0xb1,0x83,0x00,0xe4,
1583 	0x13,0xa4,0x45,0x34,0x3b,0x40,0xff,0x41,0x82,0x89,0x79,0x57,0xfd,0xd2,0x8e,0xe8,
1584 	0xfc,0x1d,0x19,0x21,0x12,0x00,0xd7,0x66,0xe5,0xc7,0x10,0x1d,0xcb,0x75,0xe8,0xfa,
1585 	0xb6,0xee,0x7b,0x2f,0x1a,0x25,0x24,0xb9,0x9f,0x1d,0x78,0xfb,0x84,0xd0,0x17,0x05,
1586 	0x71,0xb3,0xc8,0x18,0xff,0x62,0xee,0xed,0x53,0xab,0x78,0xd3,0x65,0x2d,0xbb,0xc7,
1587 	0xc1,0xe7,0x70,0xa2,0x43,0x2c,0x7c,0xc7,0x16,0x04,0xd2,0x45,0xd5,0x6b,0x6c,0x7a,
1588 	0x5e,0xa1,0x50,0x2e,0x31,0x5b,0xcc,0xe8,0x65,0x8b,0x16,0x85,0xbf,0x82,0x83,0xfb,
1589 	0xde,0x9f,0x36,0x48,0x32,0x79,0xd6,0x9b,0xfb,0x52,0x45,0xbf,0x43,0xf7,0x0b,0x0b,
1590 	0x19,0x19,0x31,0xc3,0x85,0xec,0x1d,0x8c,0x20,0xf0,0x3a,0xfa,0x80,0x4d,0x2c,0x7d,
1591 	0xac,0x60,0x09,0xc0,0x40,0xee,0xb9,0xeb,0x13,0x5b,0xe8,0x2b,0xb1,0x20,0xf0,0xce,
1592 	0x4c,0xbd,0xc6,0x04,0x86,0x70,0xc6,0x33,0xc3,0x15,0x0f,0x65,0x19,0xfd,0xc2,0xd3,
1593 	// Only the first 512 bytes of the table are initialized, the rest
1594 	// is just zeros.
1595 	// This is an idiocy in QW but we can't change this, or checksums
1596 	// will not match.
1597 };
1598 
1599 /*
1600 ====================
1601 COM_BlockSequenceCRCByte
1602 
1603 For proxy protecting
1604 ====================
1605 */
COM_BlockSequenceCRCByte(byte * base,int length,int sequence)1606 byte COM_BlockSequenceCRCByte (byte *base, int length, int sequence)
1607 {
1608 	unsigned short crc;
1609 	byte *p;
1610 	byte chkb[60 + 4];
1611 
1612 	p = chktbl + ((unsigned int) sequence % (sizeof (chktbl) - 4));
1613 
1614 	if (length > 60)
1615 		length = 60;
1616 
1617 	memcpy (chkb, base, length);
1618 
1619 	chkb[length] = (sequence & 0xff) ^ p[0];
1620 	chkb[length+1] = p[1];
1621 	chkb[length+2] = ((sequence>>8) & 0xff) ^ p[2];
1622 	chkb[length+3] = p[3];
1623 
1624 	length += 4;
1625 
1626 	crc = CRC_Block (chkb, length);
1627 
1628 	crc &= 0xff;
1629 
1630 	return crc;
1631 }
1632 
1633 //============================================================================
1634 
Q_glob_match_after_star(const char * pattern,const char * text)1635 static qbool Q_glob_match_after_star (const char *pattern, const char *text)
1636 {
1637 	char c, c1;
1638 	const char *p = pattern, *t = text;
1639 
1640 	while ((c = *p++) == '?' || c == '*')
1641 	{
1642 		if (c == '?' && *t++ == '\0')
1643 			return false;
1644 	}
1645 
1646 	if (c == '\0')
1647 		return true;
1648 
1649 	for (c1 = ((c == '\\') ? *p : c); ; )
1650 	{
1651 		if (tolower(*t) == c1 && Q_glob_match (p - 1, t))
1652 			return true;
1653 
1654 		if (*t++ == '\0')
1655 			return false;
1656 	}
1657 }
1658 
1659 /*
1660 Match a pattern against a string.
1661 Based on Vic's Q_WildCmp, which is based on Linux glob_match.
1662 Works like glob_match, except that sets ([]) are not supported.
1663 
1664 A match means the entire string TEXT is used up in matching.
1665 
1666 In the pattern string, `*' matches any sequence of characters,
1667 `?' matches any character. Any other character in the pattern
1668 must be matched exactly.
1669 
1670 To suppress the special syntactic significance of any of `*?\'
1671 and match the character exactly, precede it with a `\'.
1672 */
Q_glob_match(const char * pattern,const char * text)1673 qbool Q_glob_match (const char *pattern, const char *text)
1674 {
1675 	char c;
1676 
1677 	while ((c = *pattern++) != '\0')
1678 	{
1679 		switch (c)
1680 		{
1681 			case '?':
1682 				if (*text++ == '\0')
1683 					return false;
1684 				break;
1685 			case '\\':
1686 				if (tolower (*pattern++) != tolower (*text++))
1687 					return false;
1688 				break;
1689 			case '*':
1690 				return Q_glob_match_after_star (pattern, text);
1691 			default:
1692 				if (tolower (c) != tolower (*text++))
1693 					return false;
1694 		}
1695 	}
1696 
1697 	return (*text == '\0');
1698 }
1699 
1700 //============================================================================
1701 
1702 /*
1703 ==========
1704 Com_HashKey
1705 ==========
1706 */
Com_HashKey(const char * name)1707 int Com_HashKey (const char *name)
1708 {
1709 	int	v;
1710 	unsigned char c;
1711 
1712 	v = 0;
1713 	while ( (c = *name++) != 0 )
1714 		v += c &~ 32; // make it case insensitive
1715 
1716 	return v % 32;
1717 }
1718 
1719 //============================================================================
1720 
1721 static char q_normalize_chartbl[256];
1722 static qbool q_normalize_chartbl_init;
1723 
Q_normalizetext_Init(void)1724 static void Q_normalizetext_Init (void)
1725 {
1726 	int i;
1727 
1728 	for (i = 0; i < 32; i++)
1729 		q_normalize_chartbl[i] = q_normalize_chartbl[i + 128] = '#';
1730 	for (i = 32; i < 128; i++)
1731 		q_normalize_chartbl[i] = q_normalize_chartbl[i + 128] = i;
1732 
1733 	// special cases
1734 	q_normalize_chartbl[10] = 10;
1735 	q_normalize_chartbl[13] = 13;
1736 
1737 	// dot
1738 	q_normalize_chartbl[5      ] = q_normalize_chartbl[14      ] = q_normalize_chartbl[15      ] = q_normalize_chartbl[28      ] = q_normalize_chartbl[46      ] = '.';
1739 	q_normalize_chartbl[5 + 128] = q_normalize_chartbl[14 + 128] = q_normalize_chartbl[15 + 128] = q_normalize_chartbl[28 + 128] = q_normalize_chartbl[46 + 128] = '.';
1740 
1741 	// numbers
1742 	for (i = 18; i < 28; i++)
1743 		q_normalize_chartbl[i] = q_normalize_chartbl[i + 128] = i + 30;
1744 
1745 	// brackets
1746 	q_normalize_chartbl[16] = q_normalize_chartbl[16 + 128]= '[';
1747 	q_normalize_chartbl[17] = q_normalize_chartbl[17 + 128] = ']';
1748 	q_normalize_chartbl[29] = q_normalize_chartbl[29 + 128] = q_normalize_chartbl[128] = '(';
1749 	q_normalize_chartbl[31] = q_normalize_chartbl[31 + 128] = q_normalize_chartbl[130] = ')';
1750 
1751 	// left arrow
1752 	q_normalize_chartbl[127] = '>';
1753 	// right arrow
1754 	q_normalize_chartbl[141] = '<';
1755 
1756 	// '='
1757 	q_normalize_chartbl[30] = q_normalize_chartbl[129] = q_normalize_chartbl[30 + 128] = '=';
1758 
1759 	q_normalize_chartbl_init = true;
1760 }
1761 
1762 /*
1763 ==================
1764 Q_normalizetext
1765 returns readable extended quake names
1766 ==================
1767 */
Q_normalizetext(char * str)1768 char *Q_normalizetext (char *str)
1769 {
1770 	unsigned char	*i;
1771 
1772 	if (!q_normalize_chartbl_init)
1773 		Q_normalizetext_Init();
1774 
1775 	for (i = (unsigned char*)str; *i; i++)
1776 		*i = q_normalize_chartbl[*i];
1777 	return str;
1778 }
1779 
1780 /*
1781 ==================
1782 Q_redtext
1783 returns extended quake names
1784 ==================
1785 */
Q_redtext(unsigned char * str)1786 unsigned char *Q_redtext (unsigned char *str)
1787 {
1788 	unsigned char *i;
1789 	for (i = str; *i; i++)
1790 		if (*i > 32 && *i < 128)
1791 			*i |= 128;
1792 	return str;
1793 }
1794 //<-
1795 
1796 /*
1797 ==================
1798 Q_yelltext
1799 returns extended quake names (yellow numbers)
1800 ==================
1801 */
Q_yelltext(unsigned char * str)1802 unsigned char *Q_yelltext (unsigned char *str)
1803 {
1804 	unsigned char *i;
1805 	for (i = str; *i; i++)
1806 	{
1807 		if (*i >= '0' && *i <= '9')
1808 			*i += 18 - '0';
1809 		else if (*i > 32 && *i < 128)
1810 			*i |= 128;
1811 		else if (*i == 13)
1812 			*i = ' ';
1813 	}
1814 	return str;
1815 }
1816 
1817 //=====================================================================
1818 
1819 // "GPL map" support.  If we encounter a map with a known "GPL" CRC,
1820 // we fake the CRC so that, on the client side, the CRC of the original
1821 // map is transferred to the server, and on the server side, comparison
1822 // of clients' CRC is done against the orignal one
1823 typedef struct {
1824 	const char *mapname;
1825 	int original;
1826 	int gpl;
1827 } csentry_t;
1828 
1829 static csentry_t table[] = {
1830 	// CRCs for AquaShark's "simpletextures" maps
1831 	{ "dm1", 0xc5c7dab3, 0x7d37618e },
1832 	{ "dm2", 0x65f63634, 0x7b337440 },
1833 	{ "dm3", 0x15e20df8, 0x912781ae },
1834 	{ "dm4", 0x9c6fe4bf, 0xc374df89 },
1835 	{ "dm5", 0xb02d48fd, 0x77ca7ce5 },
1836 	{ "dm6", 0x5208da2b, 0x200c8b5d },
1837 	{ "end", 0xbbd4b4a5, 0xf89b12ae }, // this is the version with the extra room
1838 	{ NULL, 0, 0 },
1839 };
1840 
Com_TranslateMapChecksum(const char * mapname,int checksum)1841 int Com_TranslateMapChecksum (const char *mapname, int checksum)
1842 {
1843 	csentry_t *p;
1844 
1845 //	Con_Printf ("Map checksum (%s): 0x%x\n", mapname, checksum);
1846 
1847 	for (p = table; p->mapname; p++)
1848 		if (!strcmp(p->mapname, mapname)) {
1849 			if (checksum == p->gpl)
1850 				return p->original;
1851 			else
1852 				return checksum;
1853 		}
1854 
1855 	return checksum;
1856 }
1857 
COM_FileExists(char * path)1858 qbool COM_FileExists (char *path)
1859 {
1860 	FILE *fexists = NULL;
1861 
1862 	// Try opening the file to see if it exists.
1863 	fexists = fopen(path, "rb");
1864 
1865 	// The file exists.
1866 	if (fexists)
1867 	{
1868 		// Make sure the file is closed.
1869 		fclose (fexists);
1870 		return true;
1871 	}
1872 
1873 	return false;
1874 }
1875 
Q_namecmp(const char * s1,const char * s2)1876 int Q_namecmp(const char* s1, const char* s2)
1877 {
1878 	if (s1 == NULL && s2 == NULL)
1879 		return 0;
1880 
1881 	if (s1 == NULL)
1882 		return -1;
1883 
1884 	if (s2 == NULL)
1885 		return 1;
1886 
1887 	while (*s1 || *s2) {
1888 		if (tolower(*s1 & 0x7f) != tolower(*s2 & 0x7f)) {
1889 			return tolower(*s1 & 0x7f) - tolower(*s2 & 0x7f);
1890 		}
1891 		s1++;
1892 		s2++;
1893 	}
1894 
1895 	return 0;
1896 }
1897