--- parser3/src/main/pa_common.C 2003/03/17 14:48:05 1.145.2.1 +++ parser3/src/main/pa_common.C 2003/09/01 12:27:27 1.153.2.1 @@ -5,14 +5,17 @@ Author: Alexandr Petrosian (http://paf.design.ru) */ -static const char* IDENT_COMMON_C="$Date: 2003/03/17 14:48:05 $"; +static const char* IDENT_COMMON_C="$Date: 2003/09/01 12:27:27 $"; #include "pa_common.h" #include "pa_exception.h" #include "pa_globals.h" #include "pa_hash.h" +#include "pa_table.h" #include "pa_vstring.h" #include "pa_vdate.h" +#include "pa_vhash.h" +#include "pa_vtable.h" #ifdef WIN32 # include @@ -143,7 +146,7 @@ static int http_read_response(String& re const String* status_code=0; ssize_t EOLat=0; while(true) { - char *buf=(char *)response.pool().malloc_atomic(MAX_STRING); + char *buf=(char *)response.pool().malloc(MAX_STRING); ssize_t size=recv(sock, buf, MAX_STRING, 0); if(size<=0) break; @@ -182,18 +185,18 @@ static void timeout_handler(int sig){ #endif static int http_request(String& response, - const String *origin_string, - const char* host, int port, - const char* request, - int timeout, - bool fail_on_status_ne_200){ + const String *origin_string, + const char* host, int port, + const char* request, + int timeout, + bool fail_on_status_ne_200) { if(!host) throw Exception("http.host", origin_string, "zero hostname"); //never #ifdef PA_USE_ALARM - signal(SIGALRM, timeout_handler); + signal(SIGALRM, timeout_handler); #endif int sock=-1; #ifdef PA_USE_ALARM @@ -206,14 +209,15 @@ static int http_request(String& response throw Exception("http.timeout", origin_string, "timeout occured while retrieving document"); + return 0; // never } else { alarm(timeout); #endif - try { - int result; + try { + int result; struct sockaddr_in dest; - - if(!set_addr(&dest, host, port)) + + if(!set_addr(&dest, host, port)) throw Exception("http.host", origin_string, "can not resolve hostname \"%s\"", host); @@ -236,19 +240,24 @@ static int http_request(String& response closesocket(sock); #ifdef PA_USE_ALARM alarm(0); - } #endif - return result; - } catch(...) { - if(sock>=0) - closesocket(sock); + return result; + } catch(...) { #ifdef PA_USE_ALARM - alarm(0); + alarm(0); #endif - /*re*/throw; + if(sock>=0) + closesocket(sock); + /*re*/throw; + } +#ifdef PA_USE_ALARM } +#endif } +#undef CRLF +#define CRLF "\r\n" + #ifndef DOXYGEN struct Http_pass_header_info { String* request; @@ -262,11 +271,12 @@ static void http_pass_header(const Hash: *(i.request)<(value), String::UL_HTTP_HEADER, false) - <<"\n"; + << CRLF; if(key.change_case(pool, String::CC_UPPER)=="USER-AGENT") i.user_agent_specified=true; } +/// @todo build .cookies field. use ^file.tables.SET-COOKIES.menu{ for now static void file_read_http(Pool& pool, const String& file_spec, void*& data, size_t& data_size, Hash *options=0, Hash** out_fields=0) { @@ -322,7 +332,7 @@ static void file_read_http(Pool& pool, c //making request String request(pool); - request<< method <<" "<< uri <<" HTTP/1.0\nHost: "<< host<<"\n"; + request<< method <<" "<< uri <<" HTTP/1.0" CRLF "Host: "<< host<< CRLF; bool user_agent_specified=false; if(vheaders && !vheaders->is_string()) { // allow empty if(Hash *headers=vheaders->get_hash(&connect_string)) { @@ -335,8 +345,8 @@ static void file_read_http(Pool& pool, c "headers param must be hash"); }; if(!user_agent_specified) // defaulting - request << "user-agent: " DEFAULT_USER_AGENT "\n"; - request<<"\n"; + request << "user-agent: " DEFAULT_USER_AGENT CRLF; + request<hash(0); + size_t pos_after_ref=0; - header_block.split(aheaders, &pos_after_ref, "\r\n", 2); + header_block.split(aheaders, &pos_after_ref, CRLF, 2); //processing headers for(int i=1;icstr()); - - headers.put( - line->mid(0, pos).change_case(pool, String::CC_UPPER), - new(pool) VString(line->mid(pos+2, line->size()))); + + const String& sname=line->mid(0, pos).change_case(pool, String::CC_UPPER); + const String& string=line->mid(pos+2, line->size()); + + // tables + { + Value *valready=(Value *)tables.get(sname); + bool existed=valready!=0; + Table *table; + if(existed) { + // second+ appearence + table=valready->get_table(); + } else { + // first appearence + Array& columns=*new(pool) Array(pool, 1); + columns+=new(pool) String(pool, "value"); + table=new(pool) Table(pool, 0, &columns); + } + // this string becomes next row + Array& row=*new(pool) Array(pool, 1); + row+=&string; + *table+=&row; + // not existed before? add it + if(!existed) + tables.put(sname, new(pool) VTable(pool, table)); + } + headers.put(sname, new(pool) VString(string)); } else throw Exception("http.response", &connect_string, @@ -397,7 +434,7 @@ static void file_read_action(Pool& pool, void *context) { File_read_action_info& info=*static_cast(context); if(size_t to_read_size=(size_t)finfo.st_size) { - *info.data=pool.malloc_atomic(to_read_size+(as_text?1:0), 3); + *info.data=pool.malloc(to_read_size+(as_text?1:0), 3); *info.data_size=(size_t)read(f, *info.data, to_read_size); if(ssize_t(*info.data_size)<0 || *info.data_size>to_read_size) @@ -407,7 +444,7 @@ static void file_read_action(Pool& pool, *info.data_size, to_read_size); } else { // empty file if(as_text) { - *info.data=pool.malloc_atomic(1); + *info.data=pool.malloc(1); *(char*)(*info.data)=0; } else *info.data=0; @@ -449,6 +486,23 @@ bool file_read(Pool& pool, const String& return result; } +#ifdef PA_SAFE_MODE +void check_safe_mode(struct stat finfo, const String& file_spec, const char* fname) { + if(finfo.st_uid/*foreign?*/!=geteuid() + && finfo.st_gid/*foreign?*/!=getegid()) + throw Exception("parser.runtime", + &file_spec, + "parser is in safe mode: " + "reading files of foreign group and user disabled " + "[recompile parser with --disable-safe-mode configure option], " + "actual filename '%s', " + "fuid(%d)!=euid(%d) or fgid(%d)!=egid(%d)", + fname, + finfo.st_uid, geteuid(), + finfo.st_gid, getegid()); +} +#endif + bool file_read_action_under_lock(Pool& pool, const String& file_spec, const char* action_name, File_read_action action, void *context, bool as_text, @@ -481,12 +535,7 @@ bool file_read_action_under_lock(Pool& p strerror(errno), errno, fname); #ifdef PA_SAFE_MODE - if(finfo.st_uid/*foreign?*/!=geteuid() - && finfo.st_gid/*foreign?*/!=getegid()) - throw Exception("parser.runtime", - &file_spec, - "parser is in safe mode: reading files of foreign group and user disabled [recompile parser with --disable-safe-mode configure option], actual filename '%s'", - fname); + check_safe_mode(finfo, file_spec, fname); #endif action(pool, finfo, f, file_spec, fname, as_text, context); @@ -765,7 +814,7 @@ char* format(Pool& pool, double value, c else size=snprintf(local_buf, sizeof(local_buf), "%d", (int)value); - char* pool_buf=(char *)pool.malloc_atomic(size+1, 4); + char* pool_buf=(char *)pool.malloc(size+1, 4); memcpy(pool_buf, local_buf, size+1); return pool_buf; } @@ -782,12 +831,12 @@ size_t stdout_write(const void *buf, siz return size; #else - return fwrite(buf, 1, size, stdout); + return write(1/*handleof(stdout)*/, buf, size, stdout); #endif } char* unescape_chars(Pool& pool, const char* cp, int len) { - char* s=(char *)pool.malloc_atomic(len + 1, 5); + char* s=(char *)pool.malloc(len + 1, 5); enum EscapeState { EscapeRest, EscapeFirst, @@ -960,6 +1009,7 @@ int pa_sleep(unsigned long secs, unsigne // attributed meaning +/// http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3 static size_t date_attribute(const VDate& vdate, char *buf, size_t buf_size) { const char month_names[12][4]={ "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"}; @@ -972,7 +1022,7 @@ static size_t date_attribute(const VDate throw Exception(0, 0, "bad time in attribute value (seconds from epoch=%ld)", when); - return snprintf(buf, MAX_STRING, "%s, %.2d-%s-%.4d %.2d:%.2d:%.2d GMT", + return snprintf(buf, MAX_STRING, "%s, %.2d %s %.4d %.2d:%.2d:%.2d GMT", days[tms->tm_wday], tms->tm_mday,month_names[tms->tm_mon],tms->tm_year+1900, tms->tm_hour,tms->tm_min,tms->tm_sec); @@ -983,7 +1033,7 @@ static void append_attribute_meaning(Str result.append(string->join_chains(result.pool(), 0), lang, forced); else if(Value *vdate=value.as(VDATE_TYPE, false)) { - char *buf=(char *)result.malloc_atomic(MAX_STRING); + char *buf=(char *)result.malloc(MAX_STRING); size_t size=date_attribute(*static_cast(vdate), buf, MAX_STRING);