void HTTPSV_SendHTMLFooter(cluster_t *cluster, oproxy_t *dest) { char *s; char buffer[2048]; snprintf(buffer, sizeof(buffer), "\n <p id='version'><strong><a href='https://github.com/deurk/qtv'>QTV</a> %s, build %i</strong></p>\n", PROXY_VERSION, cluster->buildnumber); Net_ProxySend(cluster, dest, buffer, strlen(buffer)); s = "\n </body>\n\n" "</html>\n"; Net_ProxySend(cluster, dest, s, strlen(s)); }
void HTTPSV_SendHTTPHeader(cluster_t *cluster, oproxy_t *dest, char *error_code, char *content_type, qbool nocache) { char *s; char buffer[2048]; int ierr = atoi(error_code); const char *httpreply = "OK"; switch (ierr) { case 200: httpreply = "OK"; break; case 400: httpreply = "Bad Request"; break; case 403: httpreply = "Forbidden"; break; case 404: httpreply = "Not Found"; break; } if (nocache) { s = "HTTP/1.1 %s %s" CRLF "Content-Type: %s" CRLF "Cache-Control: no-cache, must-revalidate" CRLF "Expires: Mon, 26 Jul 1997 05:00:00 GMT" CRLF "Connection: close" CRLF CRLF; } else { s = "HTTP/1.1 %s %s" CRLF "Content-Type: %s" CRLF "Connection: close" CRLF CRLF; } snprintf(buffer, sizeof(buffer), s, error_code, httpreply, content_type); Net_ProxySend(cluster, dest, buffer, strlen(buffer)); }
// // Gets the hostname from the header provided by the web client. // qbool HTTPSV_GetHostname(cluster_t *cluster, oproxy_t *dest, char *hostname, int buffersize) { char *s = NULL; if (!HTTPSV_GetHeaderField((char *)dest->inbuffer, "Host", hostname, buffersize)) { HTTPSV_SendHTTPHeader(cluster, dest, "400", "text/html", true); HTTPSV_SendHTMLHeader(cluster, dest, "QuakeTV: Error"); s = " <p>Your client did not send a Host field, which is required in HTTP/1.1<br />" "Please try a different browser.</p>\n" "\n </body>\n\n" "</html>\n"; Net_ProxySend(cluster, dest, s, strlen(s)); return false; } return true; }
void HTTPSV_SendHTMLHeader(cluster_t *cluster, oproxy_t *dest, char *title) { char *s; char buffer[2048]; s = "<?xml version=\"1.0\"?>\n" "<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'>\n\n" "<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>\n\n" " <head>\n" " <meta http-equiv=\"content-type\" content=\"text/html; charset=iso-8859-1\" />\n" " <title>%s</title>\n" " <link rel=\"StyleSheet\" href=\"/style.css\" type=\"text/css\" />\n" " <link rel=\"alternate\" title=\"RSS\" href=\"/rss\" type=\"application/rss+xml\" />\n" " <script src=\"/script.js\" type=\"text/javascript\"></script>\n" " </head>\n\n" " <body>\n\n" " <div id=\"navigation\"><span><a href=\"/nowplaying/\">Live</a></span><span><a href=\"/demos/\">Demos</a></span><span><a href=\"/admin/\">Admin</a></span><span><a href=\"https://github.com/deurk/qtv/wiki\" target=\"_blank\">Help</a></span></div>\n\n"; snprintf(buffer, sizeof(buffer), s, title); Net_ProxySend(cluster, dest, buffer, strlen(buffer)); }
void HTTPSV_GetMethod(cluster_t *cluster, oproxy_t *pend) { #define URLCOMPARE(url, str, skip) (!strncmp(url, str, (skip = sizeof(str) - 1))) char *s; char *getpath; char geturl[1024]; int skiplen = 0; HTTPSV_GetURLFromRequest(geturl, (char *)pend->inbuffer, sizeof(geturl)); getpath = geturl; // RFC 2616 requires us to be able to parse an absolute URI also. if (URLCOMPARE(getpath, "http://", skiplen)) { getpath += skiplen; while (*getpath && (*getpath != '\t') && (*getpath != '\r') && (*getpath != '\n') && (*getpath != ' ') && (*getpath != '/')) { getpath++; } } if (URLCOMPARE(getpath, "/nowplaying", skiplen)) { HTTPSV_GenerateNowPlaying(cluster, pend); } else if (URLCOMPARE(getpath, "/watch.qtv?sid=", skiplen)) { HTTPSV_GenerateQTVStub(cluster, pend, "", getpath + skiplen); } else if (URLCOMPARE(getpath, "/watch.qtv?demo=", skiplen)) { HTTPSV_GenerateQTVStub(cluster, pend, "file:", getpath + skiplen); } else if (URLCOMPARE(getpath, "/join.qtv?sid=", skiplen)) { HTTPSV_GenerateQTVJoinStub(cluster, pend, getpath + skiplen); } else if (URLCOMPARE(getpath, "/admin", skiplen)) { HTTPSV_GenerateAdmin(cluster, pend, 0, NULL); } else if (URLCOMPARE(getpath, "/demos", skiplen)) { HTTPSV_GenerateDemoListing(cluster, pend); } else if (!strcmp(getpath, "/style.css")) { HTTPSV_GenerateCSSFile(cluster, pend); } else if (!strcmp(getpath, "/script.js")) { HTTPSV_GenerateJSFile(cluster, pend); } else if (URLCOMPARE(getpath, "/levelshots/", skiplen)) { HTTPSV_GenerateLevelshot(cluster, pend, getpath + skiplen); } else if (URLCOMPARE(getpath, "/dl/demos/", skiplen)) { HTTPSV_GenerateDemoDownload(cluster, pend, getpath + skiplen); } else if (URLCOMPARE(getpath, "/rss", skiplen)) { HTTPSV_GenerateRSS(cluster, pend, ""); } else if (URLCOMPARE(getpath, "/status", skiplen)) { HTTPSV_GenerateQTVStatus(cluster, pend, getpath + skiplen); } else if (!strcmp(FS_FileExtension(getpath), ".png")) { s = strchrrev(getpath, '/') + 1; HTTPSV_GenerateImage(cluster, pend, s); } else if (!strcmp(getpath, "/about")) { // Redirect them to our funky website. s = "HTTP/1.0 302 Found" CRLF "Location: https://github.com/deurk/qtv" CRLF CRLF; Net_ProxySend(cluster, pend, s, strlen(s)); } else if (!strcmp(getpath, "/")) { s = "HTTP/1.0 302 Found" CRLF "Location: /nowplaying/" CRLF CRLF; Net_ProxySend(cluster, pend, s, strlen(s)); } else { HTTPSV_SendHTTPHeader(cluster, pend, "404", "text/html", true); HTTPSV_SendHTMLHeader(cluster, pend, "Address not recognised"); s = " <h1>Address not recognised</h1>\n"; Net_ProxySend(cluster, pend, s, strlen(s)); HTTPSV_SendHTMLFooter(cluster, pend); } }
void HTTPSV_PostMethod(cluster_t *cluster, oproxy_t *pend) { char tempbuf[512]; char *s; char *postpath = (char *)pend->inbuffer + sizeof("POST ") - 1; char *postdata = NULL; int len; // Get the post data. { for (s = (char *)pend->inbuffer; *s; s++) { if (s[0] == '\n' && (s[1] == '\n' || (s[1] == '\r' && s[2] == '\n'))) break; } if (s[0] == '\n' && s[1] == '\n') { s += 2; } else if (s[0] == '\n' && s[1] == '\r' && s[2] == '\n') { s += 3; } postdata = s; } if (!HTTPSV_GetHeaderField((char *)pend->inbuffer, "Content-Length", tempbuf, sizeof(tempbuf))) { s = "HTTP/1.1 411 OK" CRLF "Content-Type: text/html" CRLF "Connection: close" CRLF CRLF "<html>\n\n <head>\n <title>QuakeTV</title>\n </head>\n\n <body>\n <p>No Content-Length was provided.</p>\n </body>\n\n</html>\n"; Net_ProxySend(cluster, pend, s, strlen(s)); pend->flushing = true; return; } len = max(0, atoi(tempbuf)); if (pend->inbuffersize + len >= sizeof(pend->inbuffer) - 20) { // Too much data. pend->flushing = true; return; } len = postdata - (char *)pend->inbuffer + len; if (len > pend->inbuffersize) return; // Still need the body. if (!strncmp(postpath, "/admin", 6)) { HTTPSV_GenerateAdmin(cluster, pend, 0, postdata); } else { s = "HTTP/1.1 404 OK" CRLF "Content-Type: text/html" CRLF "Connection: close" CRLF CRLF "<html>\n\n <head>\n <title>QuakeTV</title>\n </head>\n\n <body>\n <p>That HTTP method is not supported for that URL.</p>\n </body>\n\n</html>\n"; Net_ProxySend(cluster, pend, s, strlen(s)); } pend->flushing = true; return; }
void Net_ProxySendString(cluster_t *cluster, oproxy_t *prox, void *buffer) { Net_ProxySend(cluster, prox, buffer, strlen(buffer)); }