/* info_str.c Hexen2World info strings handling $Id: info_str.c,v 1.8 2007/10/01 11:00:32 sezero Exp $ */ #include "quakedef.h" #include /* =============== Info_ValueForKey Searches the string for the given key and returns the associated value, or an empty string. =============== */ char *Info_ValueForKey (const char *s, const char *key) { char pkey[512]; static char value[4][512]; // use two buffers so compares // work without stomping on each other static int valueindex; char *o; valueindex = (valueindex + 1) % 4; if (*s == '\\') s++; while (1) { o = pkey; while (*s != '\\') { if (!*s) return ""; *o++ = *s++; } *o = 0; s++; o = value[valueindex]; while (*s != '\\' && *s) { if (!*s) return ""; *o++ = *s++; } *o = 0; if (!strcmp (key, pkey) ) return value[valueindex]; if (!*s) return ""; s++; } } void Info_RemoveKey (char *s, const char *key) { char *start; char pkey[512]; char value[512]; char *o; if (strstr (key, "\\")) { Con_Printf ("Can't use a key with a \\\n"); return; } while (1) { start = s; if (*s == '\\') s++; o = pkey; while (*s != '\\') { if (!*s) return; *o++ = *s++; } *o = 0; s++; o = value; while (*s != '\\' && *s) { if (!*s) return; *o++ = *s++; } *o = 0; if (!strcmp (key, pkey) ) { strcpy (start, s); // remove this part return; } if (!*s) return; } } void Info_RemovePrefixedKeys (char *start, char prefix) { char *s; char pkey[512]; char value[512]; char *o; s = start; while (1) { if (*s == '\\') s++; o = pkey; while (*s != '\\') { if (!*s) return; *o++ = *s++; } *o = 0; s++; o = value; while (*s != '\\' && *s) { if (!*s) return; *o++ = *s++; } *o = 0; if (pkey[0] == prefix) { Info_RemoveKey (start, pkey); s = start; } if (!*s) return; } } void Info_SetValueForStarKey (char *s, const char *key, const char *value, size_t maxsize) { char newvalue[1024], *v; int c; if (strstr (key, "\\") || strstr (value, "\\") ) { Con_Printf ("Can't use keys or values with a \\\n"); return; } if (strstr (key, "\"") || strstr (value, "\"") ) { Con_Printf ("Can't use keys or values with a \"\n"); return; } if (strlen(key) > 63 || strlen(value) > 63) { Con_Printf ("Keys and values must be < 64 characters.\n"); return; } Info_RemoveKey (s, key); if (!*value) return; if (strlen(key) + 1 + strlen(value) + 1 + strlen(s) >= maxsize) { // >= maxsize, not > maxsize, for the null termination. // +1 for each of key and value for the added \ characters Con_Printf ("Info string length exceeded\n"); return; } sprintf (newvalue, "\\%s\\%s", key, value); // only copy ascii values s += strlen(s); v = newvalue; while (*v) { c = (unsigned char)*v++; #ifndef SERVERONLY // client only allows highbits on name if (q_strcasecmp(key, "name") != 0) { c &= 127; if (c < 32 || c > 127) continue; // auto lowercase team if (q_strcasecmp(key, "team") == 0) c = tolower(c); } #else if (!sv_highchars.integer) { c &= 127; if (c < 32 || c > 127) continue; } #endif // c &= 127; // strip high bits if (c > 13) // && c < 127) *s++ = c; } *s = 0; } void Info_SetValueForKey (char *s, const char *key, const char *value, size_t maxsize) { if (key[0] == '*') { Con_Printf ("Can't set * keys\n"); return; } Info_SetValueForStarKey (s, key, value, maxsize); } void Info_Print (const char *s) { char key[512]; char value[512]; char *o; int l; if (*s == '\\') s++; while (*s) { o = key; while (*s && *s != '\\') *o++ = *s++; l = o - key; if (l < 20) { memset (o, ' ', 20-l); key[20] = 0; } else *o = 0; Con_Printf ("%s", key); if (!*s) { Con_Printf ("MISSING VALUE\n"); return; } o = value; s++; while (*s && *s != '\\') *o++ = *s++; *o = 0; if (*s) s++; Con_Printf ("%s\n", value); } }