--- parser3/src/targets/cgi/pa_sapi_info.h 2020/10/11 22:59:19 1.3 +++ parser3/src/targets/cgi/pa_sapi_info.h 2020/12/15 17:23:56 1.12 @@ -1,7 +1,7 @@ #ifndef PA_SAPI_INFO_H #define PA_SAPI_INFO_H -#define IDENT_PA_SAPI_INFO_H "$Id: pa_sapi_info.h,v 1.3 2020/10/11 22:59:19 moko Exp $" +#define IDENT_PA_SAPI_INFO_H "$Id: pa_sapi_info.h,v 1.12 2020/12/15 17:23:56 moko Exp $" #include "pa_sapi.h" #include "pa_http.h" @@ -9,11 +9,15 @@ /// IIS refuses to read bigger chunks const size_t READ_POST_CHUNK_SIZE=0x400*0x400; // 1M +// for signal handlers and cgi console detection +static Request *request=0; + + class SAPI_Info : public PA_Allocated { public: int http_response_code; - SAPI_Info() : http_response_code(0) {} + SAPI_Info() : http_response_code(200) {} virtual char* get_env(const char* name) { if(char *local=getenv(name)) @@ -22,6 +26,10 @@ public: return 0; } + virtual bool set_env(const char*, const char*) { + return false; + } + virtual const char* const *get_env() { #ifdef _MSC_VER extern char **_environ; @@ -47,10 +55,6 @@ public: return stdout_write(buf, size); } - virtual void die(const char *content, int content_length) { - stdout_write(content, content_length); - } - } *sapiInfo = NULL; class SAPI_Info_CGI : public SAPI_Info { @@ -69,7 +73,7 @@ public: virtual void add_header_attribute(const char* dont_store_key, const char* dont_store_value) { SAPI_Info::add_header_attribute(dont_store_key, dont_store_value); -// if(!request || !request->console.was_used()) + if(!request || !request->console.was_used()) printf("%s: %s\n", capitalize(dont_store_key), dont_store_value); } @@ -77,22 +81,6 @@ public: puts(""); } - virtual void die(const char *content, int content_length) { - // prepare header - // let's be honest, that's bad we couldn't produce valid output - // capitalized headers passed for preventing malloc during capitalization - add_header_attribute(HTTP_STATUS_CAPITALIZED, "500"); - add_header_attribute(HTTP_CONTENT_TYPE_CAPITALIZED, "text/plain"); - // don't use 'format' function because it calls malloc - char content_length_cstr[MAX_NUMBER]; - snprintf(content_length_cstr, sizeof(content_length_cstr), "%u", content_length); - add_header_attribute(HTTP_CONTENT_LENGTH_CAPITALIZED, content_length_cstr); - - // send header - send_header(); - // body - send_body(content, content_length); - } }; @@ -143,6 +131,11 @@ public: return !value ? NULL : value.cstrm(); } + virtual bool set_env(const char* name, const char* value) { + env.put(name, *new String(value)); + return true; + } + virtual const char* const *get_env() { const char** result=new(PointerGC) const char*[env.count()+1/*0*/]; const char** cur=result; @@ -155,8 +148,8 @@ public: return result; } - virtual size_t read_post(char *, size_t) { - return 0; + virtual size_t read_post(char *buf, size_t max_bytes) { + return connection.read_post(buf, max_bytes); } virtual void add_header_attribute(const char* dont_store_key, const char* dont_store_value) { @@ -168,19 +161,42 @@ public: output << capitalize(dont_store_key) << ": " << pa_strdup(dont_store_value) << "\r\n"; } - static const char *message(int code) { + static const char *exception_http_status(const char *type) { + struct Lookup { + const char *code; + const char *type; + } static lookup[] = { + {"400", "httpd.request"}, + {"400", "http.response"}, + {"404", "file.missing"}, + {"408", "httpd.timeout"}, + {"501", "httpd.method"}, + { NULL, ""} + }; + Lookup *cur = lookup; + for(; cur->code; cur++) + if(!strcmp(type, cur->type)) + return cur->code; + return "500"; + } + + static const char *status_message(int code) { struct Lookup { int code; const char *message; } static lookup[] = { {200, "OK"}, + {204, "No Content"}, {206, "Partial Content"}, {301, "Moved Permanently"}, {302, "Found"}, + {304, "Not Modified"}, {400, "Bad Request"}, {401, "Unauthorized"}, {403, "Forbidden"}, {404, "Not Found"}, + {408, "Request Timeout"}, + {416, "Range Not Satisfiable"}, {500, "Internal Server Error"}, {501, "Not Implemented"}, {502, "Bad Gateway"}, @@ -196,16 +212,12 @@ public: virtual void send_header() { String result("HTTP/1.0 "); - result << String::Body::Format(http_response_code) << " " << message(http_response_code) << "\r\n" << output << "\r\n"; + result << String::Body::Format(http_response_code) << " " << status_message(http_response_code) << "\r\n" << output << "\r\n"; send_body(result.cstr(), result.length()); } virtual size_t send_body(const void *buf, size_t size) { - if(send(connection.sock, buf, size, 0)!=(ssize_t)size) { - int no=pa_socks_errno(); - throw Exception("httpd.timeout", 0, "error sending response: %s (%d)", pa_socks_strerr(no), no); - } - return size; + return connection.send_body(buf, size); } };