Annotation of parser3/src/targets/cgi/pa_sapi_info.h, revision 1.2

1.1       moko        1: #ifndef PA_SAPI_INFO_H
                      2: #define PA_SAPI_INFO_H
                      3: 
1.2     ! moko        4: #define IDENT_PA_SAPI_INFO_H "$Id: pa_sapi_info.h,v 1.1 2020/10/10 06:08:37 moko Exp $"
1.1       moko        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) {
1.2     ! moko      108:                for(Array_iterator<HTTP_Headers::Header> i(connection.headers()); i.has_next(); ){
        !           109:                        HTTP_Headers::Header header=i.next();
1.1       moko      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;
1.2     ! moko      125:                for(Array_iterator<HTTP_Headers::Header> i(connection.headers()); i.has_next(); ){
        !           126:                        HTTP_Headers::Header header=i.next();
1.1       moko      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: