diff --git a/fteqtv/forward.c b/fteqtv/forward.c index b69f8357c..302d75301 100644 --- a/fteqtv/forward.c +++ b/fteqtv/forward.c @@ -27,7 +27,6 @@ Password checks and stuff are implemented here. This is server side stuff. #include "qtv.h" - #undef IN #define IN(x) buffer[(x)&(MAX_PROXY_BUFFER-1)] @@ -531,6 +530,53 @@ void HTMLprintf(char *outb, int outl, char *fmt, ...) *outb++ = 0; } +static void SV_SendHTTPHeader(cluster_t *cluster, oproxy_t *dest, char *error_code, char *content_type, qboolean nocache) +{ + char *s; + char buffer[2048]; + + if (nocache) { + s = "HTTP/1.1 %s OK\n" + "Content-Type: %s\n" + "Cache-Control: no-cache, must-revalidate\n" + "Expires: Mon, 26 Jul 1997 05:00:00 GMT\n" + "Connection: close\n" + "\n"; + } else { + s = "HTTP/1.1 %s OK\n" + "Content-Type: %s\n" + "Connection: close\n" + "\n"; + } + + snprintf(buffer, sizeof(buffer), s, error_code, content_type); + + Net_ProxySend(cluster, dest, buffer, strlen(buffer)); +} + +static void SV_SendHTMLHeader(cluster_t *cluster, oproxy_t *dest, char *title) +{ + char *s; + char buffer[2048]; + + s = "\n" + "\n" + "\n" + " \n" + " %s\n" + " \n" + "\n" + "
"; + + snprintf(buffer, sizeof(buffer), s, title); + + Net_ProxySend(cluster, dest, buffer, strlen(buffer)); +} + +#define HTMLPRINT(str) { sprintf(buffer, str "\n"); Net_ProxySend(cluster, dest, buffer, strlen(buffer)); } + void SV_GenerateNowPlayingHTTP(cluster_t *cluster, oproxy_t *dest) { int player; @@ -539,29 +585,21 @@ void SV_GenerateNowPlayingHTTP(cluster_t *cluster, oproxy_t *dest) char plname[64]; sv_t *streams; - s = "HTTP/1.1 200 OK\n" - "Content-Type: text/html\n" - "Connection: close\n" - "\n"; - Net_ProxySend(cluster, dest, s, strlen(s)); + SV_SendHTTPHeader(cluster, dest, "200", "text/html", true); + SV_SendHTMLHeader(cluster, dest, "QuakeTV: Now Playing"); - sprintf(buffer, "" - "QuakeTV: Now Playing" - "" - ""); - Net_ProxySend(cluster, dest, buffer, strlen(buffer)); - - snprintf(buffer, sizeof(buffer), "

Now Playing on %s

", cluster->hostname); + snprintf(buffer, sizeof(buffer), "

QuakeTV on %s: Now Playing

", cluster->hostname); Net_ProxySend(cluster, dest, buffer, strlen(buffer)); + HTMLPRINT("
"); for (streams = cluster->servers; streams; streams = streams->next) { - sprintf(buffer, "", streams->streamid); + HTMLPRINT("
"); + HTMLprintf(buffer, sizeof(buffer), "%s (%s: %s)", streams->server, streams->gamedir, streams->mapname); + Net_ProxySend(cluster, dest, buffer, strlen(buffer)); + sprintf(buffer, " [ Watch Now ]", streams->streamid); Net_ProxySend(cluster, dest, buffer, strlen(buffer)); - HTMLprintf(buffer, sizeof(buffer), "%s (%s: %s)", streams->server, streams->gamedir, streams->mapname); - Net_ProxySend(cluster, dest, buffer, strlen(buffer)); - s = "
"; - Net_ProxySend(cluster, dest, s, strlen(s)); + HTMLPRINT("
"); } + HTMLPRINT("
"); if (!cluster->servers) { s = "No streams are currently being played
"; Net_ProxySend(cluster, dest, s, strlen(s)); } - s = "
Available Demos
"; - Net_ProxySend(cluster, dest, s, strlen(s)); - s = "Admin
"; - Net_ProxySend(cluster, dest, s, strlen(s)); - sprintf(buffer, "
QTV Version: %i www.fteqw.com
", cluster->buildnumber); Net_ProxySend(cluster, dest, buffer, strlen(buffer)); - sprintf(buffer, ""); - Net_ProxySend(cluster, dest, buffer, strlen(buffer)); + HTMLPRINT(""); +} + +void SV_GenerateCSSFile(cluster_t *cluster, oproxy_t *dest) +{ + char buffer[1024]; + + SV_SendHTTPHeader(cluster, dest, "200", "text/css", false); + + HTMLPRINT("* { font-family: Verdana, Helvetica, sans-serif; }"); + HTMLPRINT("body { color: #000; background-color: #fff; padding: 0 40px; }"); + HTMLPRINT("a { color: #00f; }"); + HTMLPRINT("a.qtvfile { font-weight: bold; }"); + HTMLPRINT("a:visited { color: #00f; }"); + HTMLPRINT("a:hover { background-color: black; color: yellow; }"); + HTMLPRINT("li.spectator { color: #666; font-size: 0.9ex; }"); + HTMLPRINT("dl.nowplaying dd { margin: 0 0 2em 0; }"); + HTMLPRINT("dl.nowplaying dt { margin: 1em 0 0 0; font-size: 1.1em; font-weight: bold; }"); + HTMLPRINT("dl.nowplaying li { list-style: none; margin: 0 0 0 1em; padding: 0; }"); + HTMLPRINT("dl.nowplaying ul { margin: 0 0 0 1em; padding: 0; }"); + HTMLPRINT("#navigation { background-color: #eef; }"); + HTMLPRINT("#navigation li { display: inline; list-style: none; margin: 0 3em; }"); } qboolean SV_GetHTTPHeaderField(char *s, char *field, char *buffer, int buffersize) @@ -658,17 +716,10 @@ void SV_GenerateQTVStub(cluster_t *cluster, oproxy_t *dest, char *streamtype, ch if (!SV_GetHTTPHeaderField(dest->inbuffer, "Host", hostname, sizeof(hostname))) { - s = "HTTP/1.1 400 OK\n" - "Content-Type: text/html\n" - "Connection: close\n" - "\n" + SV_SendHTTPHeader(cluster, dest, "400", "text/html", true); + SV_SendHTMLHeader(cluster, dest, "QuakeTV: Error"); - "" - "" - "QuakeTV: Now Playing" - "" - "" - "Your client did not send a Host field, which is required in HTTP/1.1\n
" + s = "Your client did not send a Host field, which is required in HTTP/1.1\n
" "Please try a different browser.\n" "" ""; @@ -677,11 +728,7 @@ void SV_GenerateQTVStub(cluster_t *cluster, oproxy_t *dest, char *streamtype, ch return; } - s = "HTTP/1.1 200 OK\n" - "Content-Type: text/x-quaketvident\n" - "Connection: close\n" - "\n"; - Net_ProxySend(cluster, dest, s, strlen(s)); + SV_SendHTTPHeader(cluster, dest, "200", "text/x-quaketvident", true); { char *ws; @@ -754,11 +801,10 @@ void SV_GenerateAdminHTTP(cluster_t *cluster, oproxy_t *dest, int streamid, char if (!*cluster->adminpassword) { - s = "HTTP/1.1 403 OK\n" - "Content-Type: text/html\n" - "Connection: close\n" - "\n" - "QuakeTVThe admin password is disabled. You may not log in remotely.\n"; + SV_SendHTTPHeader(cluster, dest, "403", "text/html", true); + SV_SendHTMLHeader(cluster, dest, "QuakeTV: Admin Error"); + + s = "The admin password is disabled. You may not log in remotely.\n"; Net_ProxySend(cluster, dest, s, strlen(s)); return; } @@ -865,9 +911,9 @@ void SV_GenerateAdminHTTP(cluster_t *cluster, oproxy_t *dest, int streamid, char o = s+1; } - s = "
Now Playing
"; + s = "
Now Playing
"; Net_ProxySend(cluster, dest, s, strlen(s)); - s = "Available Demos
"; + s = "Available Demos
"; Net_ProxySend(cluster, dest, s, strlen(s)); sprintf(result, "
QTV Version: %i www.fteqw.com
", cluster->buildnumber); @@ -887,38 +933,31 @@ void SV_GenerateQTVDemoListing(cluster_t *cluster, oproxy_t *dest) int i; char link[256]; char *s; - s = "HTTP/1.1 200 OK\n" - "Content-Type: text/html\n" - "Connection: close\n" - "\n" - "QuakeTV Demos"; - Net_ProxySend(cluster, dest, s, strlen(s)); - s = "

QTV Demo listing

"; - Net_ProxySend(cluster, dest, s, strlen(s)); + SV_SendHTTPHeader(cluster, dest, "200", "text/html", true); + SV_SendHTMLHeader(cluster, dest, "QuakeTV: Demos"); - Cluster_BuildAvailableDemoList(cluster); - for (i = 0; i < cluster->availdemoscount; i++) - { - snprintf(link, sizeof(link), "%s (%ikb)
", cluster->availdemos[i].name, cluster->availdemos[i].name, cluster->availdemos[i].size/1024); - Net_ProxySend(cluster, dest, link, strlen(link)); - } + s = "

QuakeTV: Demo Listing

"; + Net_ProxySend(cluster, dest, s, strlen(s)); - sprintf(link, "

Total: %i demos

", cluster->availdemoscount); + Cluster_BuildAvailableDemoList(cluster); + for (i = 0; i < cluster->availdemoscount; i++) + { + snprintf(link, sizeof(link), "%s (%ikb)
", cluster->availdemos[i].name, cluster->availdemos[i].name, cluster->availdemos[i].size/1024); Net_ProxySend(cluster, dest, link, strlen(link)); + } - s = "
Now Playing
"; - Net_ProxySend(cluster, dest, s, strlen(s)); - s = "Admin
"; - Net_ProxySend(cluster, dest, s, strlen(s)); - - sprintf(link, "
QTV Version: %i www.fteqw.com
", cluster->buildnumber); - Net_ProxySend(cluster, dest, link, strlen(link)); + sprintf(link, "

Total: %i demos

", cluster->availdemoscount); + Net_ProxySend(cluster, dest, link, strlen(link)); - s = "" - ""; - Net_ProxySend(cluster, dest, s, strlen(s)); + sprintf(link, "
QTV Version: %i www.fteqw.com
", cluster->buildnumber); + Net_ProxySend(cluster, dest, link, strlen(link)); + + + s = "" + ""; + Net_ProxySend(cluster, dest, s, strlen(s)); } @@ -994,7 +1033,7 @@ qboolean SV_ReadPendingProxy(cluster_t *cluster, oproxy_t *pend) "Content-Type: text/html\n" "Connection: close\n" "\n" - "QuakeTVNo Content-Length was provided.\n"; + "QuakeTVNo Content-Length was provided.\n"; Net_ProxySend(cluster, pend, s, strlen(s)); pend->flushing = true; return false; @@ -1021,7 +1060,7 @@ qboolean SV_ReadPendingProxy(cluster_t *cluster, oproxy_t *pend) "Content-Type: text/html\n" "Connection: close\n" "\n" - "QuakeTVThat HTTP method is not supported for that URL.\n"; + "QuakeTVThat HTTP method is not supported for that URL.\n"; Net_ProxySend(cluster, pend, s, strlen(s)); } @@ -1043,6 +1082,10 @@ qboolean SV_ReadPendingProxy(cluster_t *cluster, oproxy_t *pend) { SV_GenerateQTVStub(cluster, pend, "file:", pend->inbuffer+20); } + else if (!strncmp(pend->inbuffer+4, "/demo/", 6)) + { + SV_GenerateQTVStub(cluster, pend, "file:", pend->inbuffer+9); + } else if (!strncmp(pend->inbuffer+4, "/about", 6)) { //redirect them to our funky website s = "HTTP/1.0 302 Found\n" @@ -1057,7 +1100,7 @@ qboolean SV_ReadPendingProxy(cluster_t *cluster, oproxy_t *pend) else if (!strncmp(pend->inbuffer+4, "/ ", 2)) { s = "HTTP/1.0 302 Found\n" - "Location: /nowplaying.html\n" + "Location: /nowplaying/\n" "\n"; Net_ProxySend(cluster, pend, s, strlen(s)); } @@ -1082,6 +1125,10 @@ qboolean SV_ReadPendingProxy(cluster_t *cluster, oproxy_t *pend) "Hello World\n"; Net_ProxySend(cluster, pend, s, strlen(s)); }*/ + else if (!strncmp(pend->inbuffer+4, "/style.css", 10)) + { + SV_GenerateCSSFile(cluster, pend); + } else { s = "HTTP/1.1 404 OK\n" @@ -1257,7 +1304,7 @@ qboolean SV_ReadPendingProxy(cluster_t *cluster, oproxy_t *pend) { //starts a demo off the server... source does the same thing though... char buf[256]; - sprintf(buf, sizeof(buf), "demo:%s", colon); + snprintf(buf, sizeof(buf), "demo:%s", colon); qtv = QTV_NewServerConnection(cluster, buf, "", false, true, true, false); if (!qtv) {