char *test_Dir_resolve_file() { Dir *test = Dir_create("tests/", "sample.html", "test/plain"); mu_assert(test != NULL, "Failed to make test dir."); FileRecord *rec = Dir_resolve_file(test, bfromcstr("/"), bfromcstr("/sample.json")); mu_assert(rec != NULL, "Failed to resolve file that should be there."); rec = Dir_resolve_file(test, bfromcstr("/"), bfromcstr("/")); mu_assert(rec != NULL, "Failed to find default file."); rec = Dir_resolve_file(test, bfromcstr("/"), bfromcstr("/../../../../../etc/passwd")); mu_assert(rec == NULL, "HACK! should not find this."); Dir_destroy(test); test = Dir_create("foobar/", "sample.html", "test/plan"); mu_assert(test != NULL, "Failed to make the failed dir."); rec = Dir_resolve_file(test, bfromcstr("/"), bfromcstr("/sample.json")); mu_assert(rec == NULL, "Should not get something from a bad base directory."); Dir_destroy(test); return NULL; }
int Dir_serve_file(Dir *dir, Request *req, Connection *conn) { FileRecord *file = NULL; bstring resp = NULL; bstring path = Request_path(req); bstring pattern = req->pattern; int rc = 0; int is_get = biseq(req->request_method, &HTTP_GET); int is_head = is_get ? 0 : biseq(req->request_method, &HTTP_HEAD); check(path, "Request had not path. That's weird."); req->response_size = 0; if(!(is_get || is_head)) { req->status_code = 405; rc = Response_send_status(conn, &HTTP_405); check_debug(rc == blength(&HTTP_405), "Failed to send 405 to client."); return -1; } else { file = Dir_resolve_file(dir, pattern, path); resp = Dir_calculate_response(req, file); if(resp) { rc = Response_send_status(conn, resp); check_debug(rc == blength(resp), "Failed to send error response on file serving."); } else if(is_get) { rc = Dir_stream_file(file, conn); req->response_size = rc; check_debug(rc == file->sb.st_size, "Didn't send all of the file, sent %d of %s.", rc, bdata(path)); } else if(is_head) { rc = Dir_send_header(file, conn); check_debug(rc, "Failed to write header to socket."); } else { sentinel("How the hell did you get to here. Tell Zed."); } FileRecord_release(file); return 0; } sentinel("Invalid code branch, Tell Zed you have magic."); error: FileRecord_release(file); return -1; }
char *test_Dir_resolve_file() { Dir *test = Dir_create( bfromcstr("tests/"), bfromcstr("sample.html"), bfromcstr("test/plain"), 0); mu_assert(test != NULL, "Failed to make test dir."); FileRecord *rec = Dir_resolve_file(test, bfromcstr("/"), bfromcstr("/sample.json")); mu_assert(rec != NULL, "Failed to resolve file that should be there."); rec = Dir_resolve_file(test, bfromcstr("/"), bfromcstr("/")); mu_assert(rec != NULL, "Failed to find default file."); rec = Dir_resolve_file(test, bfromcstr("/"), bfromcstr("/../../../../../etc/passwd")); mu_assert(rec == NULL, "HACK! should not find this."); rec = Dir_resolve_file(test, bfromcstr("/tests/"), bfromcstr("/test")); mu_assert(rec == NULL, "Should NOT find short paths."); rec = Dir_resolve_file(test, bfromcstr("/"), bfromcstr("/%E2%82%ACtonn%C3%A4nt%2520.tx%C3%BE")); mu_assert(rec != NULL, "Should find file with a percent-encoded name."); rec = Dir_resolve_file(test, bfromcstr("/"), bfromcstr("/%E2%82%ACtonn%C3%A4nt%2520/present.txt")); mu_assert(rec != NULL, "Should find file inside percent-encoded path."); Dir_destroy(test); test = Dir_create( bfromcstr("foobar/"), bfromcstr("sample.html"), bfromcstr("test/plan"), 0); mu_assert(test != NULL, "Failed to make the failed dir."); rec = Dir_resolve_file(test, bfromcstr("/"), bfromcstr("/sample.json")); mu_assert(rec == NULL, "Should not get something from a bad base directory."); Dir_destroy(test); return NULL; }