#include "bothdefs.h" #ifdef WEBSERVER #include "iweb.h" #ifdef CLIENTONLY IWEBFILE *IWebGenerateFile(char *name) { return NULL; } #else char lastrecordedmvd[MAX_QPATH]; IWeb_FileGen_t *IWeb_GenerationBuffer; int IWeb_GenerationBufferTotal; void IWeb_MoreGeneratedResize(int newsize) { IWeb_FileGen_t *ob; if (IWeb_GenerationBuffer && IWeb_GenerationBufferTotal >= newsize) return; //already big enough ob = IWeb_GenerationBuffer; IWeb_GenerationBuffer = BZ_Malloc(sizeof(IWeb_GenerationBuffer) + newsize); IWeb_GenerationBuffer->data = (char *)(IWeb_GenerationBuffer+1); if (ob) { memcpy(IWeb_GenerationBuffer->data, ob->data, ob->len); BZ_Free(ob); } IWeb_GenerationBufferTotal = newsize; } void IWeb_Generate(const char *buf) { long count = strlen(buf); if (!IWeb_GenerationBuffer || IWeb_GenerationBuffer->len + count >= IWeb_GenerationBufferTotal) IWeb_MoreGeneratedResize(IWeb_GenerationBufferTotal + count+(16*1024)); memcpy(&IWeb_GenerationBuffer->data[IWeb_GenerationBuffer->len], buf, count); IWeb_GenerationBuffer->len+=count; } int Rank_Enumerate (unsigned int first, unsigned int last, void (*callback) (const rankinfo_t *ri)); //leader first. void IWeb_ParseForm(char *info, int infolen, char *text) { char *eq, *and; char *token, *out; *info = '\0'; if (!text) return; while(*text) { eq = strchr(text, '='); if (!eq) break; *eq = '\0'; and = strchr(eq+1, '&'); if (and) *and = '\0'; for (out = token = eq+1; *token;) { if (*token == '+') { *out++ = ' '; token++; } else if (*token == '%' && token[1] && token[2]) { int c = 0; if (token[1] >= '0' && token[1] <= '9') { c += token[1] - '0'; } else if (token[1] >= 'a' && token[1] <= 'f') { c += token[1] - 'a'+10; } else if (token[1] >= 'A' && token[1] <= 'F') { c += token[1] - 'A'+10; } c*=16; if (token[2] >= '0' && token[2] <= '9') { c += token[2] - '0'; } else if (token[2] >= 'a' && token[2] <= 'f') { c += token[2] - 'a'+10; } else if (token[2] >= 'A' && token[2] <= 'F') { c += token[2] - 'A'+10; } *out++ = c; token+=3; } else *out++ = *token++; } *out = '\0'; Info_SetValueForKey(info, text, eq+1, infolen); if (!and) return; text = and+1; } } void IWeb_GenerateAdminFile(char *parms, char *content, int contentlength) { extern char outputbuf[]; //redirected buffer - always null termed. char info[16384]; char *pwd; char *cmd; char *mark, *start; extern cvar_t rcon_password; IWeb_Generate("FTEQWSV - admin"); if (*rcon_password.string) { IWeb_ParseForm(info, sizeof(info), content); pwd = Info_ValueForKey(info, "pwd"); cmd = Info_ValueForKey(info, "cmd"); IWeb_Generate("
"); IWeb_Generate("
"); IWeb_Generate(""); IWeb_Generate("
"); IWeb_Generate(""); IWeb_Generate("
"); IWeb_Generate(""); IWeb_Generate("
"); IWeb_Generate("
"); if (!strcmp(rcon_password.string, pwd)) { Con_Printf("Web based rcon: %s\n", cmd); SV_BeginRedirect(-1); Cmd_ExecuteString(cmd, RESTRICT_RCON); for (mark = start = outputbuf; *mark; mark++) { if (*mark == '\n') { *mark = '\0'; IWeb_Generate(start); IWeb_Generate("
"); start = mark+1; } } IWeb_Generate(start); SV_EndRedirect(); } else if (*pwd) IWeb_Generate("Password is incorrect."); } else IWeb_Generate("

Remote administration is not enabled.

"); IWeb_Generate(""); } void IWeb_GenerateRankingsFileCallback(const rankinfo_t *ri) { IWeb_Generate(""); IWeb_Generate(ri->h.name); IWeb_Generate(""); IWeb_Generate(va("%i", ri->s.kills)); IWeb_Generate(""); IWeb_Generate(va("%i", ri->s.deaths)); IWeb_Generate(""); IWeb_Generate(""); } void IWeb_GenerateRankingsFile (char *parms, char *content, int contentlength) { IWeb_Generate(""); if (Rank_OpenRankings()) { IWeb_Generate(""); IWeb_Generate(""); if (Rank_Enumerate(atoi(parms), atoi(parms)+20, IWeb_GenerateRankingsFileCallback) == 20) { IWeb_Generate("
Players
"); if (atoi(parms) >= 20) IWeb_Generate(va("Less", atoi(parms)-20)); else if (atoi(parms) > 0) IWeb_Generate(va("Less", 0)); IWeb_Generate(va("More", atoi(parms)+20)); } else { IWeb_Generate(""); if (atoi(parms) >= 20) IWeb_Generate(va("Less", atoi(parms)-20)); else if (atoi(parms) > 0) IWeb_Generate(va("Less", 0)); } } else IWeb_Generate("

Rankings are disabled. Sorry.

"); IWeb_Generate(""); } void IWeb_GenerateIndexFile (char *parms, char *content, int contentlength) { extern cvar_t rcon_password; char *s, *o; char key[128], value[128]; int l; qboolean added; client_t *cl; IWeb_Generate("FTEQWSV"); IWeb_Generate("

"); IWeb_Generate(hostname.string); IWeb_Generate("

"); IWeb_Generate("Server website

"); if (Rank_OpenRankings()) IWeb_Generate("Click here to see ranked players.

"); if (*rcon_password.string) IWeb_Generate("Admin.

"); s = svs.info; IWeb_Generate(""); IWeb_Generate(""); 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; IWeb_Generate(""); } IWeb_Generate("
Server Info
"); IWeb_Generate(key); if (!*s) { IWeb_Generate("MISSING VALUE\n"); return; } o = value; s++; while (*s && *s != '\\') *o++ = *s++; *o = 0; if (*s) s++; IWeb_Generate(""); IWeb_Generate(value); IWeb_Generate("
"); IWeb_Generate("

"); IWeb_Generate(""); added = false; for (l = 0, cl = svs.clients; l < sv.allocated_client_slots; l++, cl++) { if (cl->state <= cs_zombie) continue; IWeb_Generate(""); added = true; } if (!added) { IWeb_Generate("
Players
"); IWeb_Generate(cl->name); IWeb_Generate(""); IWeb_Generate(va("%i", cl->old_frags)); IWeb_Generate("
"); IWeb_Generate("No players on server"); IWeb_Generate(""); } IWeb_Generate("
"); IWeb_Generate(""); } typedef struct { char *name; void (*GenerationFunction) (char *parms, char *content, int contentlength); float lastgenerationtime; float oldbysecs; IWeb_FileGen_t *buffer; int genid; } IWebFile_t; IWebFile_t IWebFiles[] = { {"allplayers.html", IWeb_GenerateRankingsFile}, {"index.html", IWeb_GenerateIndexFile}, {"admin.html", IWeb_GenerateAdminFile} }; IWEBFILE *IWebGenerateFile(char *name, char *content, int contentlength) { int fnum; char *parms; int len; if (!sv.state) return NULL; if (*lastrecordedmvd && !strcmp(name, "lastdemo.mvd")) if (strcmp(name, "lastdemo.mvd")) //no infinate loops please... return IWebFOpenRead(lastrecordedmvd); parms = strchr(name, '?'); if (!parms) parms = name + strlen(name); len = parms-name; if (*parms) parms++; if (!*name) return NULL; for (fnum = 0; fnum < sizeof(IWebFiles) / sizeof(IWebFile_t); fnum++) { if (!Q_strncasecmp(name, IWebFiles[fnum].name, len+1)) { IWEBFILE *ret; if (IWebFiles[fnum].buffer) { if (IWebFiles[fnum].lastgenerationtime+10 < Sys_DoubleTime() || contentlength||*parms) //10 sec lifetime { IWebFiles[fnum].buffer->references--; //remove our reference and check free if (IWebFiles[fnum].buffer->references<=0) { BZ_Free(IWebFiles[fnum].buffer); IWebFiles[fnum].buffer = NULL; } } } if (!IWebFiles[fnum].buffer) { if (IWeb_GenerationBuffer!=NULL) Sys_Error("Recursive file generation\n"); IWebFiles[fnum].GenerationFunction(parms, content, contentlength); IWebFiles[fnum].buffer = IWeb_GenerationBuffer; if (!contentlength) { IWeb_GenerationBuffer->references++; //so it can't be sent once and freed instantly. IWebFiles[fnum].lastgenerationtime = Sys_DoubleTime(); } else IWebFiles[fnum].lastgenerationtime = -10; } ret = IWebMalloc(sizeof(IWEBFILE)); if (!ret) { BZ_Free(IWeb_GenerationBuffer); return NULL; } ret->f = NULL; ret->bufferdata = IWebFiles[fnum].buffer; ret->length = ret->bufferdata->len; ret->bufferdata->references++; ret->pos = 0; ret->start = 0; ret->end = ret->start+ret->length; IWeb_GenerationBuffer = NULL; return ret; } } return NULL; } #endif #endif