static void handleFile(TSession *const sessionP, const char *const fileName, time_t const fileModTime, MIMEType *const mimeTypeP) { /*---------------------------------------------------------------------------- This is an HTTP request handler for a GET. It does the classic web server thing: send the file named in the URL to the client. -----------------------------------------------------------------------------*/ TFile *fileP; bool success; success = FileOpen(&fileP, fileName, O_BINARY | O_RDONLY); if (!success) ResponseStatusErrno(sessionP); else { if (notRecentlyModified(sessionP, fileModTime)) { ResponseStatus(sessionP, 304); ResponseWriteStart(sessionP); } else sendFileAsResponse(sessionP, fileP, fileName, fileModTime, mimeTypeP); FileClose(fileP); } }
static abyss_bool ServerDefaultHandlerFunc(TSession * const sessionP) { struct _TServer * const srvP = ConnServer(sessionP->conn)->srvP; char *p; char z[4096]; TFileStat fs; unsigned int i; abyss_bool endingslash=FALSE; if (!RequestValidURIPath(sessionP)) { ResponseStatus(sessionP, 400); return TRUE; } /* Must check for * (asterisk uri) in the future */ if (sessionP->request_info.method == m_options) { ResponseAddField(sessionP, "Allow", "GET, HEAD"); ResponseContentLength(sessionP, 0); ResponseStatus(sessionP, 200); return TRUE; } if ((sessionP->request_info.method != m_get) && (sessionP->request_info.method != m_head)) { ResponseAddField(sessionP, "Allow", "GET, HEAD"); ResponseStatus(sessionP, 405); return TRUE; } strcpy(z, srvP->filespath); strcat(z, sessionP->request_info.uri); p = z + strlen(z) - 1; if (*p == '/') { endingslash = TRUE; *p = '\0'; } #ifdef WIN32 p = z; while (*p) { if ((*p) == '/') *p= '\\'; ++p; } #endif /* WIN32 */ if (!FileStat(z, &fs)) { ResponseStatusErrno(sessionP); return TRUE; } if (fs.st_mode & S_IFDIR) { /* Redirect to the same directory but with the ending slash ** to avoid problems with some browsers (IE for examples) when ** they generate relative urls */ if (!endingslash) { strcpy(z, sessionP->request_info.uri); p = z+strlen(z); *p = '/'; *(p+1) = '\0'; ResponseAddField(sessionP, "Location", z); ResponseStatus(sessionP, 302); ResponseWrite(sessionP); return TRUE; } *p = DIRECTORY_SEPARATOR[0]; ++p; i = srvP->defaultfilenames.size; while (i-- > 0) { *p = '\0'; strcat(z, (srvP->defaultfilenames.item[i])); if (FileStat(z, &fs)) { if (!(fs.st_mode & S_IFDIR)) return ServerFileHandler(sessionP, z, fs.st_mtime, srvP->mimeTypeP); } } *(p-1) = '\0'; if (!FileStat(z, &fs)) { ResponseStatusErrno(sessionP); return TRUE; } return ServerDirectoryHandler(sessionP, z, fs.st_mtime, srvP->mimeTypeP); } else return ServerFileHandler(sessionP, z, fs.st_mtime, srvP->mimeTypeP); }
static abyss_bool ServerFileHandler(TSession * const r, char * const z, time_t const fileModTime, MIMEType * const mimeTypeP) { const char * mediatype; TFile file; uint64_t filesize; uint64_t start; uint64_t end; TDate date; char * p; TDate filedate; mediatype = MIMETypeGuessFromFile2(mimeTypeP, z); if (!FileOpen(&file,z,O_BINARY | O_RDONLY)) { ResponseStatusErrno(r); return TRUE; } fileDate(r, fileModTime, &filedate); p = RequestHeaderValue(r, "if-modified-since"); if (p) { if (DateDecode(p,&date)) { if (DateCompare(&filedate, &date) <= 0) { ResponseStatus(r, 304); ResponseWrite(r); return TRUE; } else r->ranges.size = 0; } } filesize = FileSize(&file); switch (r->ranges.size) { case 0: ResponseStatus(r, 200); break; case 1: { abyss_bool decoded; decoded = RangeDecode((char *)(r->ranges.item[0]), filesize, &start, &end); if (!decoded) { ListFree(&(r->ranges)); ResponseStatus(r, 200); break; } sprintf(z, "bytes %llu-%llu/%llu", start, end, filesize); ResponseAddField(r, "Content-range", z); ResponseContentLength(r, end - start + 1); ResponseStatus(r, 206); } break; default: ResponseContentType(r, "multipart/ranges; boundary=" BOUNDARY); ResponseStatus(r, 206); break; } if (r->ranges.size == 0) { ResponseContentLength(r, filesize); ResponseContentType(r, mediatype); } if (DateToString(&filedate, z)) ResponseAddField(r, "Last-Modified", z); ResponseWrite(r); if (r->request_info.method != m_head) sendBody(r, &file, filesize, mediatype, start, end, z); FileClose(&file); return TRUE; }