Annotation of parser3/src/targets/cgi/pa_sapi_info.h, revision 1.1
1.1 ! moko 1: #ifndef PA_SAPI_INFO_H
! 2: #define PA_SAPI_INFO_H
! 3:
! 4: #define IDENT_PA_SAPI_INFO_H "$Id: pa_sapi_info.h,v 1.34 2020/08/13 11:44:20 moko Exp $"
! 5:
! 6: #include "pa_sapi.h"
! 7: #include "pa_http.h"
! 8:
! 9: /// IIS refuses to read bigger chunks
! 10: const size_t READ_POST_CHUNK_SIZE=0x400*0x400; // 1M
! 11:
! 12: class SAPI_Info : public PA_Allocated {
! 13: public:
! 14: int http_response_code;
! 15:
! 16: SAPI_Info() : http_response_code(0) {}
! 17:
! 18: virtual char* get_env(const char* name) {
! 19: if(char *local=getenv(name))
! 20: return pa_strdup(local);
! 21: else
! 22: return 0;
! 23: }
! 24:
! 25: virtual const char* const *get_env() {
! 26: #ifdef _MSC_VER
! 27: extern char **_environ;
! 28: return _environ;
! 29: #else
! 30: extern char **environ;
! 31: return environ;
! 32: #endif
! 33: }
! 34:
! 35: virtual size_t read_post(char *, size_t) {
! 36: return 0;
! 37: }
! 38:
! 39: virtual void add_header_attribute(const char* dont_store_key, const char* dont_store_value) {
! 40: if(strcasecmp(dont_store_key, HTTP_STATUS)==0)
! 41: http_response_code=atoi(dont_store_value);
! 42: }
! 43:
! 44: virtual void send_header() {}
! 45:
! 46: virtual size_t send_body(const void *buf, size_t size) {
! 47: return stdout_write(buf, size);
! 48: }
! 49:
! 50: virtual void die(const char *content, int content_length) {
! 51: stdout_write(content, content_length);
! 52: }
! 53:
! 54: } *sapiInfo = NULL;
! 55:
! 56: class SAPI_Info_CGI : public SAPI_Info {
! 57: public:
! 58:
! 59: virtual size_t read_post(char *buf, size_t max_bytes) {
! 60: size_t read_size=0;
! 61: do {
! 62: ssize_t chunk_size=read(fileno(stdin), buf+read_size, min(READ_POST_CHUNK_SIZE, max_bytes-read_size));
! 63: if(chunk_size<=0)
! 64: break;
! 65: read_size+=chunk_size;
! 66: } while(read_size<max_bytes);
! 67: return read_size;
! 68: }
! 69:
! 70: virtual void add_header_attribute(const char* dont_store_key, const char* dont_store_value) {
! 71: SAPI_Info::add_header_attribute(dont_store_key, dont_store_value);
! 72: // if(!request || !request->console.was_used())
! 73: printf("%s: %s\n", capitalize(dont_store_key), dont_store_value);
! 74: }
! 75:
! 76: virtual void send_header() {
! 77: puts("");
! 78: }
! 79:
! 80: virtual void die(const char *content, int content_length) {
! 81: // prepare header
! 82: // let's be honest, that's bad we couldn't produce valid output
! 83: // capitalized headers passed for preventing malloc during capitalization
! 84: add_header_attribute(HTTP_STATUS_CAPITALIZED, "500");
! 85: add_header_attribute(HTTP_CONTENT_TYPE_CAPITALIZED, "text/plain");
! 86: // don't use 'format' function because it calls malloc
! 87: char content_length_cstr[MAX_NUMBER];
! 88: snprintf(content_length_cstr, sizeof(content_length_cstr), "%u", content_length);
! 89: add_header_attribute(HTTP_CONTENT_LENGTH_CAPITALIZED, content_length_cstr);
! 90:
! 91: // send header
! 92: send_header();
! 93: // body
! 94: send_body(content, content_length);
! 95: }
! 96:
! 97: };
! 98:
! 99: class SAPI_Info_HTTPD : public SAPI_Info {
! 100: public:
! 101:
! 102: HTTPD_Connection &connection;
! 103: String output;
! 104:
! 105: SAPI_Info_HTTPD(HTTPD_Connection &aconnection) : connection(aconnection) {}
! 106:
! 107: virtual char* get_env(const char* name) {
! 108: for(Array_iterator<ResponseHeaders::Header> i(connection.headers()); i.has_next(); ){
! 109: ResponseHeaders::Header header=i.next();
! 110: if(!strcmp(name, header.name.cstr()))
! 111: return header.value.cstrm();
! 112: }
! 113: return NULL;
! 114: }
! 115:
! 116: static const char* mk_env_pair(const char* key, const char* value) {
! 117: char *result=new(PointerFreeGC) char[5 /*HTTP_*/ + strlen(key) + 1 /*=*/ + strlen(value) + 1 /*0*/];
! 118: strcpy(result, "HTTP_"); strcat(result, key); strcat(result, "="); strcat(result, value);
! 119: return result;
! 120: }
! 121:
! 122: virtual const char* const *get_env() {
! 123: const char** result=new(PointerGC) const char*[connection.headers().count()+1/*0*/];
! 124: const char** cur=result;
! 125: for(Array_iterator<ResponseHeaders::Header> i(connection.headers()); i.has_next(); ){
! 126: ResponseHeaders::Header header=i.next();
! 127: *cur++=mk_env_pair(header.name.cstr(), header.value.cstr());
! 128: }
! 129: *cur=NULL;
! 130: return result;
! 131: }
! 132:
! 133: virtual size_t read_post(char *, size_t) {
! 134: return 0;
! 135: }
! 136:
! 137: virtual void add_header_attribute(const char* dont_store_key, const char* dont_store_value) {
! 138: if(strcasecmp(dont_store_key, "location")==0)
! 139: http_response_code=302;
! 140: if(strcasecmp(dont_store_key, HTTP_STATUS)==0)
! 141: http_response_code=atoi(dont_store_value);
! 142: else
! 143: output << capitalize(dont_store_key) << ": " << pa_strdup(dont_store_value) << "\r\n";
! 144: }
! 145:
! 146: static const char *message(int code) {
! 147: struct Lookup {
! 148: int code;
! 149: const char *message;
! 150: } static lookup[] = {
! 151: {200, "OK"},
! 152: {206, "Partial Content"},
! 153: {301, "Moved Permanently"},
! 154: {302, "Found"},
! 155: {400, "Bad Request"},
! 156: {401, "Unauthorized"},
! 157: {403, "Forbidden"},
! 158: {404, "Not Found"},
! 159: {500, "Internal Server Error"},
! 160: {501, "Not Implemented"},
! 161: {502, "Bad Gateway"},
! 162: {504, "Gateway Timeout"},
! 163: { 0, "Undescribed"}
! 164: };
! 165: Lookup *cur = lookup;
! 166: for(; cur->code; cur++)
! 167: if(code == cur->code)
! 168: return cur->message;
! 169: return cur->message;
! 170: }
! 171:
! 172: virtual void send_header() {
! 173: String result("HTTP/1.0 ");
! 174: result << String::Body::Format(http_response_code) << " " << message(http_response_code) << "\r\n" << output << "\r\n";
! 175: send_body(result.cstr(), result.length());
! 176: }
! 177:
! 178: virtual size_t send_body(const void *buf, size_t size) {
! 179: if(send(connection.sock, buf, size, 0)!=(ssize_t)size) {
! 180: int no=pa_socks_errno();
! 181: throw Exception("httpd.timeout", 0, "error sending response: %s (%d)", pa_socks_strerr(no), no);
! 182: }
! 183: return size;
! 184: }
! 185:
! 186: };
! 187:
! 188: #endif
E-mail: