|
|
| version 1.143.2.21.2.25, 2003/04/08 16:11:54 | version 1.143.2.21.2.27, 2003/04/11 12:29:00 |
|---|---|
| Line 345 static Charset* detect_charset(Charset& | Line 345 static Charset* detect_charset(Charset& |
| bool quoted=open_quote_pos==charset_begin; | bool quoted=open_quote_pos==charset_begin; |
| if(quoted) | if(quoted) |
| charset_begin++; // skip opening '"' | charset_begin++; // skip opening '"' |
| size_t charset_end=0; | size_t charset_end=CONTENT_TYPE_VALUE.length(); |
| if(quoted) { | if(quoted) { |
| size_t close_quote_pos=CONTENT_TYPE_VALUE.pos('"', charset_begin); | size_t close_quote_pos=CONTENT_TYPE_VALUE.pos('"', charset_begin); |
| if(close_quote_pos!=STRING_NOT_FOUND) | if(close_quote_pos!=STRING_NOT_FOUND) |
| Line 384 static File_read_http_result file_read_h | Line 384 static File_read_http_result file_read_h |
| Value* vheaders=0; | Value* vheaders=0; |
| Charset *asked_remote_charset=0; | Charset *asked_remote_charset=0; |
| String& connect_string=*new String; | |
| // not in ^sql{... L_SQL ...} spirit, but closer to ^file::load one | |
| connect_string.append(file_spec, String::L_URI); // tainted pieces -> URI pieces | |
| const char* connect_string_cstr=connect_string.cstr(String::L_UNSPECIFIED); | |
| const char* current=connect_string_cstr; | |
| if(strncmp(current, "http://", 7)!=0) | |
| throw Exception(0, | |
| &connect_string, | |
| "does not start with http://"); //never | |
| current+=7; | |
| strncpy(host, current, sizeof(host)-1); host[sizeof(host)-1]=0; | |
| char* host_uri=lsplit(host, '/'); | |
| uri=host_uri?current+(host_uri-1-host):"/"; | |
| char* port_cstr=lsplit(host, ':'); | |
| char* error_pos=0; | |
| port=port_cstr?strtol(port_cstr, &error_pos, 0):80; | |
| if(options) { | if(options) { |
| int valid_options=0; | int valid_options=0; |
| if(Value* vmethod=options->get(http_method_name)) { | if(Value* vmethod=options->get(http_method_name)) { |
| Line 434 static File_read_http_result file_read_h | Line 415 static File_read_http_result file_read_h |
| if(!asked_remote_charset) // defaulting to $request:charset | if(!asked_remote_charset) // defaulting to $request:charset |
| asked_remote_charset=&charsets.source(); | asked_remote_charset=&charsets.source(); |
| //making request | //preparing request |
| String request; | String& connect_string=*new String; |
| if(method) | // not in ^sql{... L_SQL ...} spirit, but closer to ^file::load one |
| request<<method; | connect_string.append(file_spec, String::L_URI); // tainted pieces -> URI pieces |
| else | |
| request<<"GET"; | |
| request<< " "<< uri <<" HTTP/1.0\n" | |
| "host: "<< host<<"\n"; | |
| bool user_agent_specified=false; | |
| if(vheaders && !vheaders->is_string()) { // allow empty | |
| if(HashStringValue *headers=vheaders->get_hash()) { | |
| Http_pass_header_info info={&charsets, &request}; | |
| headers->for_each(http_pass_header, &info); | |
| user_agent_specified=info.user_agent_specified; | |
| } else | |
| throw Exception("parser.runtime", | |
| &connect_string, | |
| "headers param must be hash"); | |
| }; | |
| if(!user_agent_specified) // defaulting | |
| request << "user-agent: " DEFAULT_USER_AGENT "\n"; | |
| request<<"\n"; | |
| //sending request | |
| String response; | |
| const char* request_cstr; | const char* request_cstr; |
| { | { |
| // influence URLencoding of tainted pieces to String::L_URI lang | // influence URLencoding of tainted pieces to String::L_URI lang |
| Temp_client_charset temp(charsets, *asked_remote_charset); | Temp_client_charset temp(charsets, *asked_remote_charset); |
| request_cstr=request.cstr(String::L_UNSPECIFIED); | const char* connect_string_cstr=connect_string.cstr(String::L_UNSPECIFIED); |
| const char* current=connect_string_cstr; | |
| if(strncmp(current, "http://", 7)!=0) | |
| throw Exception(0, | |
| &connect_string, | |
| "does not start with http://"); //never | |
| current+=7; | |
| strncpy(host, current, sizeof(host)-1); host[sizeof(host)-1]=0; | |
| char* host_uri=lsplit(host, '/'); | |
| uri=host_uri?current+(host_uri-1-host):"/"; | |
| char* port_cstr=lsplit(host, ':'); | |
| char* error_pos=0; | |
| port=port_cstr?strtol(port_cstr, &error_pos, 0):80; | |
| //making request | |
| String request; | |
| if(method) | |
| request<<method; | |
| else | |
| request<<"GET"; | |
| request<< " "<< uri <<" HTTP/1.0\n" | |
| "host: "<< host <<"\n"; | |
| bool user_agent_specified=false; | |
| if(vheaders && !vheaders->is_string()) { // allow empty | |
| if(HashStringValue *headers=vheaders->get_hash()) { | |
| Http_pass_header_info info={&charsets, &request}; | |
| headers->for_each(http_pass_header, &info); | |
| user_agent_specified=info.user_agent_specified; | |
| } else | |
| throw Exception("parser.runtime", | |
| &connect_string, | |
| "headers param must be hash"); | |
| }; | |
| if(!user_agent_specified) // defaulting | |
| request << "user-agent: " DEFAULT_USER_AGENT "\n"; | |
| request<<"\n"; | |
| // recode pieces not in String::L_URI lang | request_cstr=request.cstr(String::L_UNSPECIFIED); |
| // [those violating HTTP standard, but widly used] | |
| request_cstr=Charset::transcode( | |
| String::C(request_cstr, strlen(request_cstr)), | |
| charsets.source(), | |
| *asked_remote_charset); | |
| } | } |
| // recode those pieces which are not in String::L_URI lang | |
| // [those violating HTTP standard, but widly used] | |
| request_cstr=Charset::transcode( | |
| String::C(request_cstr, strlen(request_cstr)), | |
| charsets.source(), | |
| *asked_remote_charset); | |
| //sending request | |
| String response; | |
| int status_code=http_request(response, | int status_code=http_request(response, |
| host, port, request_cstr, | host, port, request_cstr, |
| timeout, fail_on_status_ne_200); | timeout, fail_on_status_ne_200); |
| Line 505 static File_read_http_result file_read_h | Line 508 static File_read_http_result file_read_h |
| const StringBody HEADER_NAME= | const StringBody HEADER_NAME= |
| line.mid(0, pos).change_case(charsets.source(), String::CC_UPPER); | line.mid(0, pos).change_case(charsets.source(), String::CC_UPPER); |
| const String& header_value=line.mid(pos+2, line.length()); | const String& header_value=line.mid(pos+2, line.length()); |
| if(HEADER_NAME=="CONTENT_TYPE") | if(HEADER_NAME=="CONTENT-TYPE") |
| real_remote_charset=detect_charset(charsets.source(), header_value); | real_remote_charset=detect_charset(charsets.source(), header_value); |
| result.headers->put(HEADER_NAME, new VString(header_value)); | result.headers->put(HEADER_NAME, new VString(header_value)); |
| } | } |
| Line 533 struct File_read_action_info { | Line 536 struct File_read_action_info { |
| }; | }; |
| #endif | #endif |
| static void file_read_action( | static void file_read_action( |
| struct stat& finfo, | struct stat& finfo, |
| int f, | int f, |
| const String& file_spec, const char* fname, bool as_text, | const String& file_spec, const char* fname, bool as_text, |
| void *context) { | void *context) { |
| File_read_action_info& info=*static_cast<File_read_action_info *>(context); | File_read_action_info& info=*static_cast<File_read_action_info *>(context); |
| if(size_t to_read_size=(size_t)finfo.st_size) { | if(size_t to_read_size=(size_t)finfo.st_size) { |
| *info.data=new(PointerFreeGC) char[to_read_size+(as_text?1:0)]; | *info.data=new(PointerFreeGC) char[to_read_size+(as_text?1:0)]; |
| Line 597 File_read_result file_read(Request_chars | Line 600 File_read_result file_read(Request_chars |
| } | } |
| #ifdef PA_SAFE_MODE | #ifdef PA_SAFE_MODE |
| void check_safe_mode(stat finfo, const String& file_spec, const char* fname) { | void check_safe_mode(struct stat finfo, const String& file_spec, const char* fname) { |
| if(finfo.st_uid/*foreign?*/!=geteuid() | if(finfo.st_uid/*foreign?*/!=geteuid() |
| && finfo.st_gid/*foreign?*/!=getegid()) | && finfo.st_gid/*foreign?*/!=getegid()) |
| throw Exception("parser.runtime", | throw Exception("parser.runtime", |