Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

417 lines
6.5 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $Header: $
  6. // $NoKeywords: $
  7. //=============================================================================//
  8. #include "quakedef.h"
  9. #include <stdlib.h>
  10. #include <ctype.h>
  11. #include "filesystem.h"
  12. #include "filesystem_engine.h"
  13. // memdbgon must be the last include file in a .cpp file!!!
  14. #include "tier0/memdbgon.h"
  15. #define MAX_KV_LEN 127
  16. /*
  17. ===============
  18. Info_ValueForKey
  19. Searches the string for the given
  20. key and returns the associated value, or an empty string.
  21. ===============
  22. */
  23. const char *Info_ValueForKey ( const char *s, const char *key )
  24. {
  25. char pkey[512];
  26. static char value[4][512]; // use two buffers so compares
  27. // work without stomping on each other
  28. static int valueindex;
  29. char *o;
  30. valueindex = (valueindex + 1) % 4;
  31. if (*s == '\\')
  32. s++;
  33. while (1)
  34. {
  35. o = pkey;
  36. while (*s != '\\')
  37. {
  38. if (!*s)
  39. return "";
  40. *o++ = *s++;
  41. }
  42. *o = 0;
  43. s++;
  44. o = value[valueindex];
  45. while (*s != '\\' && *s)
  46. {
  47. if (!*s)
  48. return "";
  49. *o++ = *s++;
  50. }
  51. *o = 0;
  52. if (!Q_strcmp (key, pkey) )
  53. return value[valueindex];
  54. if (!*s)
  55. return "";
  56. s++;
  57. }
  58. }
  59. void Info_RemoveKey ( char *s, const char *key )
  60. {
  61. char *start;
  62. char pkey[512];
  63. char value[512];
  64. char *o;
  65. if (Q_strstr (key, "\\"))
  66. {
  67. ConMsg ("Can't use a key with a \\\n");
  68. return;
  69. }
  70. while (1)
  71. {
  72. start = s;
  73. if (*s == '\\')
  74. s++;
  75. o = pkey;
  76. while (*s != '\\')
  77. {
  78. if (!*s)
  79. return;
  80. *o++ = *s++;
  81. }
  82. *o = 0;
  83. s++;
  84. o = value;
  85. while (*s != '\\' && *s)
  86. {
  87. if (!*s)
  88. return;
  89. *o++ = *s++;
  90. }
  91. *o = 0;
  92. if (!Q_strcmp (key, pkey) )
  93. {
  94. // Copies onto self, so okay to not use Q_strncpy???
  95. Q_strcpy (start, s); // remove this part
  96. return;
  97. }
  98. if (!*s)
  99. return;
  100. }
  101. }
  102. void Info_RemovePrefixedKeys (char *start, char prefix)
  103. {
  104. char *s;
  105. char pkey[512];
  106. char value[512];
  107. char *o;
  108. s = start;
  109. while (1)
  110. {
  111. if (*s == '\\')
  112. s++;
  113. o = pkey;
  114. while (*s != '\\')
  115. {
  116. if (!*s)
  117. return;
  118. *o++ = *s++;
  119. }
  120. *o = 0;
  121. s++;
  122. o = value;
  123. while (*s != '\\' && *s)
  124. {
  125. if (!*s)
  126. return;
  127. *o++ = *s++;
  128. }
  129. *o = 0;
  130. if (pkey[0] == prefix)
  131. {
  132. Info_RemoveKey (start, pkey);
  133. s = start;
  134. }
  135. if (!*s)
  136. return;
  137. }
  138. }
  139. bool Info_IsKeyImportant( const char *key )
  140. {
  141. if ( key[0] == '*' )
  142. return true;
  143. if ( !Q_strcmp( key, "name" ) )
  144. return true;
  145. if ( !Q_strcmp( key, "model" ) )
  146. return true;
  147. if ( !Q_strcmp( key, "rate" ) )
  148. return true;
  149. if ( !Q_strcmp( key, "cl_updaterate" ) )
  150. return true;
  151. if ( !Q_strcmp( key, "cl_lw" ) )
  152. return true;
  153. if ( !Q_strcmp( key, "cl_lc" ) )
  154. return true;
  155. if ( !Q_strcmp( key, "tracker" ) )
  156. return true;
  157. return false;
  158. }
  159. char *Info_FindLargestKey( char *s, int maxsize )
  160. {
  161. char key[256];
  162. char value[256];
  163. char *o;
  164. int l;
  165. static char largest_key[256];
  166. int largest_size = 0;
  167. *largest_key = 0;
  168. if (*s == '\\')
  169. s++;
  170. while (*s)
  171. {
  172. int size = 0;
  173. o = key;
  174. while (*s && *s != '\\')
  175. *o++ = *s++;
  176. l = o - key;
  177. *o = 0;
  178. size = Q_strlen( key );
  179. if (!*s)
  180. {
  181. return largest_key;
  182. }
  183. o = value;
  184. s++;
  185. while (*s && *s != '\\')
  186. *o++ = *s++;
  187. *o = 0;
  188. if (*s)
  189. s++;
  190. size += Q_strlen( value );
  191. if ( (size > largest_size) && !Info_IsKeyImportant(key) )
  192. {
  193. largest_size = size;
  194. Q_strncpy( largest_key, key, sizeof( largest_key ) );
  195. }
  196. }
  197. return largest_key;
  198. }
  199. void Info_SetValueForStarKey ( char *s, const char *key, const char *value, int maxsize )
  200. {
  201. char newArray[1024], *v;
  202. int c;
  203. if (Q_strstr (key, "\\") || Q_strstr (value, "\\") )
  204. {
  205. ConMsg ("Can't use keys or values with a \\\n");
  206. return;
  207. }
  208. if (Q_strstr (key, "\"") || Q_strstr (value, "\"") )
  209. {
  210. ConMsg ("Can't use keys or values with a \"\n");
  211. return;
  212. }
  213. if (Q_strlen(key) > MAX_KV_LEN || Q_strlen(value) > MAX_KV_LEN)
  214. {
  215. ConMsg ("Keys and values must be < %i characters.\n", MAX_KV_LEN + 1 );
  216. return;
  217. }
  218. Info_RemoveKey (s, key);
  219. if (!value || !Q_strlen(value))
  220. return;
  221. Q_snprintf (newArray, sizeof( newArray ), "\\%s\\%s", key, value);
  222. if ( (int)(Q_strlen(newArray) + Q_strlen(s)) >= maxsize)
  223. {
  224. // no more room in buffer to add key/value
  225. if ( Info_IsKeyImportant( key ) )
  226. {
  227. // keep removing the largest key/values until we have room
  228. char *largekey;
  229. do {
  230. largekey = Info_FindLargestKey( s, maxsize );
  231. Info_RemoveKey( s, largekey );
  232. } while ( ((int)(Q_strlen(newArray) + Q_strlen(s)) >= maxsize) && *largekey != 0 );
  233. if ( largekey[0] == 0 )
  234. {
  235. // no room to add setting
  236. ConMsg ("Info string length exceeded\n");
  237. return;
  238. }
  239. }
  240. else
  241. {
  242. // no room to add setting
  243. ConMsg ("Info string length exceeded\n");
  244. return;
  245. }
  246. }
  247. // only copy ascii values
  248. s += Q_strlen(s);
  249. v = newArray;
  250. while (*v)
  251. {
  252. c = (unsigned char)*v++;
  253. // client only allows highbits on name
  254. if (stricmp(key, "name") != 0) {
  255. c &= 127;
  256. if (c < 32 || c > 127)
  257. continue;
  258. // auto lowercase team
  259. if (stricmp(key, "team") == 0)
  260. c = tolower(c);
  261. }
  262. if (c > 13)
  263. *s++ = c;
  264. }
  265. *s = 0;
  266. }
  267. void Info_SetValueForKey (char *s, const char *key, const char *value, int maxsize)
  268. {
  269. if (key[0] == '*')
  270. {
  271. ConMsg ("Can't set * keys\n");
  272. return;
  273. }
  274. Info_SetValueForStarKey (s, key, value, maxsize);
  275. }
  276. void Info_Print ( const char *s )
  277. {
  278. char key[512];
  279. char value[512];
  280. char *o;
  281. int l;
  282. if (*s == '\\')
  283. s++;
  284. while (*s)
  285. {
  286. o = key;
  287. while (*s && *s != '\\')
  288. *o++ = *s++;
  289. l = o - key;
  290. if (l < 20)
  291. {
  292. Q_memset (o, ' ', 20-l);
  293. key[20] = 0;
  294. }
  295. else
  296. *o = 0;
  297. ConMsg ("%s", key);
  298. if (!*s)
  299. {
  300. ConMsg ("MISSING VALUE\n");
  301. return;
  302. }
  303. o = value;
  304. s++;
  305. while (*s && *s != '\\')
  306. *o++ = *s++;
  307. *o = 0;
  308. if (*s)
  309. s++;
  310. ConMsg ("%s\n", value);
  311. }
  312. }
  313. /*
  314. ==============
  315. Info_WriteVars
  316. ==============
  317. */
  318. void Info_WriteVars( char *s, FileHandle_t fp )
  319. {
  320. const ConVar *pcvar;
  321. char pkey[512];
  322. static char value[4][512]; // use two buffers so compares
  323. // work without stomping on each other
  324. static int valueindex;
  325. char *o;
  326. valueindex = (valueindex + 1) % 4;
  327. if (*s == '\\')
  328. s++;
  329. while (1)
  330. {
  331. o = pkey;
  332. while (*s != '\\')
  333. {
  334. if (!*s)
  335. return;
  336. *o++ = *s++;
  337. }
  338. *o = 0;
  339. s++;
  340. o = value[valueindex];
  341. while (*s != '\\' && *s)
  342. {
  343. if (!*s)
  344. return;
  345. *o++ = *s++;
  346. }
  347. *o = 0;
  348. pcvar = g_pCVar->FindVar( pkey );
  349. if ( !pcvar && pkey[0] != '*' ) // Don't store out * keys
  350. {
  351. g_pFileSystem->FPrintf( fp, "setinfo \"%s\" \"%s\"\n",
  352. pkey, value[valueindex] );
  353. }
  354. if (!*s)
  355. return;
  356. s++;
  357. }
  358. }