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: