Diff for /parser3/src/main/pa_common.C between versions 1.143.2.21.2.8 and 1.143.2.21.2.19

version 1.143.2.21.2.8, 2003/03/21 13:42:31 version 1.143.2.21.2.19, 2003/04/01 16:16:23
Line 12  static const char* IDENT_COMMON_C="$Date Line 12  static const char* IDENT_COMMON_C="$Date
 #include "pa_hash.h"  #include "pa_hash.h"
 #include "pa_globals.h"  #include "pa_globals.h"
   
 //#define PA_HTTP  #define PA_HTTP
   
 #ifdef PA_HTTP  #ifdef PA_HTTP
 #include "pa_vstring.h"  #include "pa_vstring.h"
Line 61  int PASCAL closesocket(SOCKET); Line 61  int PASCAL closesocket(SOCKET);
 #endif  #endif
   
 // locking constants  // locking constants
   //#define PA_DEBUG_NO_LOCKING
   
   #ifdef PA_DEBUG_NO_LOCKING
   
 #ifdef HAVE_FLOCK  #ifdef HAVE_FLOCK
   
Line 105  static int unlock(int fd) { FLOCK(F_TLOC Line 108  static int unlock(int fd) { FLOCK(F_TLOC
 #endif  #endif
 #endif  #endif
   
   #else
   static int lock_shared_blocking(int fd) { return 0; }
   static int lock_exclusive_blocking(int fd) { return 0; }
   static int lock_exclusive_nonblocking(int fd) { return 0; }
   static int unlock(int fd) { return 0; }
   
   #endif
   
 // defines for globals  // defines for globals
   
 #define FILE_STATUS_NAME  "status"  #define FILE_STATUS_NAME  "status"
Line 187  static bool set_addr(struct sockaddr_in Line 198  static bool set_addr(struct sockaddr_in
     return true;      return true;
 }  }
   
 static int http_read_responseString& response, int sock, bool fail_on_status_ne_200){  static int http_read_response(String& response, int sock, bool fail_on_status_ne_200){
         int result=0;          int result=0;
         ssize_t EOLat=0;          size_t EOLat=0;
         while(true) {          while(true) {
                 char *buf=new(PointerFreeGC) char[MAX_STRING];                   char *buf=new(PointerFreeGC) char[MAX_STRING]; 
                 ssize_t size=recv(sock, buf, MAX_STRING, 0);                   ssize_t size=recv(sock, buf, MAX_STRING, 0); 
                 if(size<=0)                  if(size<=0)
                         break;                          break;
                 response.APPEND_TAINTED(buf, size, "remote HTTP server response", 0);                   response.append_strdup(buf, size, String::L_TAINTED); 
                 if(!result && (EOLat=response.pos("\r\n", 2))>=0) { // checking status in first response                  if(!result && (EOLat=response.pos("\r\n", 2))!=STRING_NOT_FOUND) { // checking status in first response
                         const String& status_line=response.mid(0, (size_t)EOLat);                          const String& status_line=response.mid(0, (size_t)EOLat);
                         ArrayString astatus;                           ArrayString astatus; 
                         status_line->split(astatus, 0, " ", 1);                           size_t pos_after=0;
                         const String& status_code=astatus.get(1);                          status_line.split(astatus, pos_after, " "); 
                         result=status_code->as_int();                           const String& status_code=*astatus.get(1);
                           result=status_code.as_int(); 
   
                         if(fail_on_status_ne_200 && result!=200)                          if(fail_on_status_ne_200 && result!=200)
                                 throw Exception("http.status",                                  throw Exception("http.status",
                                         status_code,                                          &status_code,
                                         "invalid HTTP response status");                                          "invalid HTTP response status");
                 }                  }
         }          }
Line 231  static void timeout_handler(int sig){ Line 243  static void timeout_handler(int sig){
 #endif  #endif
   
 static int http_request(  static int http_request(
                                                 String& response,                          String& response,
                                                 const String* origin_string,                           const char* host, int port, 
                                                 const char* host, int port,                           const char* request, 
                                                 const char* request,                           int timeout,
                                                 int timeout,                          bool fail_on_status_ne_200) {
                                                 bool fail_on_status_ne_200) {  
         if(!host)          if(!host)
                 throw Exception("http.host",                   throw Exception("http.host", 
                         origin_string,                           0, 
                         "zero hostname");  //never                          "zero hostname");  //never
   
 #ifdef WE_CAN_USE_ALARM  #ifdef WE_CAN_USE_ALARM
Line 251  static int http_request( Line 262  static int http_request(
 #ifdef WE_CAN_USE_ALARM  #ifdef WE_CAN_USE_ALARM
                 if(sigsetjmp(timeout_env, 1))                  if(sigsetjmp(timeout_env, 1))
                         throw Exception("http.timeout",                           throw Exception("http.timeout", 
                                 origin_string,                                   0, 
                                 "timeout occured while retrieving document");                                   "timeout occured while retrieving document"); 
                 else {                  else {
                         alarm(timeout);                           alarm(timeout); 
Line 260  static int http_request( Line 271  static int http_request(
                                   
                 if(!set_addr(&dest, host, port))                  if(!set_addr(&dest, host, port))
                                 throw Exception("http.host",                                   throw Exception("http.host", 
                                         origin_string,                                           0, 
                                         "can not resolve hostname \"%s\"", host);                                           "can not resolve hostname \"%s\"", host); 
                                                   
                         if((sock=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP/*0*/))<0)                          if((sock=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP/*0*/))<0)
                                 throw Exception("http.connect",                                   throw Exception("http.connect", 
                                         origin_string,                                           0, 
                                         "can not make socket: %s (%d)", strerror(errno), errno);                                           "can not make socket: %s (%d)", strerror(errno), errno); 
                         if(connect(sock, (struct sockaddr *)&dest, sizeof(dest)))                          if(connect(sock, (struct sockaddr *)&dest, sizeof(dest)))
                                 throw Exception("http.connect",                                   throw Exception("http.connect", 
                                         origin_string,                                           0, 
                                         "can not connect to host \"%s\": %s (%d)", host, strerror(errno), errno);                                           "can not connect to host \"%s\": %s (%d)", host, strerror(errno), errno); 
                         size_t request_size=strlen(request);                          size_t request_size=strlen(request);
                         if(send(sock, request, request_size, 0)!=(ssize_t)request_size)                          if(send(sock, request, request_size, 0)!=(ssize_t)request_size)
                                 throw Exception("http.connect",                                   throw Exception("http.connect", 
                                         origin_string,                                           0, 
                                         "error sending request: %s (%d)", strerror(errno), errno);                                           "error sending request: %s (%d)", strerror(errno), errno); 
   
                         result=http_read_response(response, sock, fail_on_status_ne_200);                           result=http_read_response(response, sock, fail_on_status_ne_200); 
Line 296  static int http_request( Line 307  static int http_request(
   
 #ifndef DOXYGEN  #ifndef DOXYGEN
 struct Http_pass_header_info {  struct Http_pass_header_info {
         ;  
         Charset* charset;          Charset* charset;
         String* request;          String* request;
         bool user_agent_specified;          bool user_agent_specified;
 };  };
 #endif  #endif
 static void http_pass_header(HashStringValue::key_type key, HashStringValue::value_type value,   static void http_pass_header(HashStringValue::key_type key, HashStringValue::value_type value, 
                                                          Http_pass_header_info *info) {                               Http_pass_header_info *info) {
     *(info->request)<<*key<<": "      *info->request <<key<<": "
                 << *attributed_meaning_to_string(*info->value, String::L_HTTP_HEADER, false)                  << attributed_meaning_to_string(*value, String::L_HTTP_HEADER, false)
                 <<"\n";                   << "\n"; 
                   
         if(*key->change_case(*info->*info->charset, String::CC_UPPER)=="USER-AGENT")      if(String(key, String::L_TAINTED).change_case(*info->charset, String::CC_UPPER)=="USER-AGENT")
                 info->user_agent_specified=true;                  info->user_agent_specified=true;
 }  }
 #ifndef DOXYGEN  #ifndef DOXYGEN
 struct File_read_http_result {  struct File_read_http_result {
         char *data; size_t size;          char *str; size_t length;
         HashStringValue* headers;          HashStringValue* headers;
 };   }; 
 #endif  #endif
 static File_read_http_result file_read_httpCharset& charset, const String& file_spec,   static File_read_http_result file_read_http(Charset& charset, const String& file_spec, 
                                         HashStringValue *options=0) {                                              HashStringValue *options=0) {
         File_read_http_result result;          File_read_http_result result;
         char host[MAX_STRING];           char host[MAX_STRING]; 
         const char* uri;           const char* uri; 
         int port;          int port;
         const char* method(0);          const char* method=0;
         int timeout=2;          int timeout=2;
         bool fail_on_status_ne_200=true;          bool fail_on_status_ne_200=true;
         Value* vheaders(0);          Value* vheaders=0;
   
         const String& connect_string(new String());          String& connect_string=*new String;
         // not in ^sql{... L_SQL ...} spirit, but closer to ^file::load one          // not in ^sql{... L_SQL ...} spirit, but closer to ^file::load one
         connect_string->append(*file_spec, String::L_URI); // tainted pieces -> URI pieces          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* connect_string_cstr=connect_string.cstr(String::L_UNSPECIFIED); 
         const char* current=connect_string_cstr;          const char* current=connect_string_cstr;
         if(strncmp(current, "http://", 7)!=0)          if(strncmp(current, "http://", 7)!=0)
                 throw Exception(0,                   throw Exception(0, 
                         connect_string,                           &connect_string, 
                         "does not start with http://"); //never                          "does not start with http://"); //never
         current+=7;          current+=7;
   
Line 351  static File_read_http_result file_read_h Line 361  static File_read_http_result file_read_h
                 int valid_options=0;                  int valid_options=0;
                 if(Value* vmethod=options->get(http_method_name)) {                  if(Value* vmethod=options->get(http_method_name)) {
                         valid_options++;                          valid_options++;
                         method=vmethod->as_string()->cstr();                          method=vmethod->as_string().cstr();
                 }                  }
                 if(Value* vtimeout=options->get(http_timeout_name)) {                  if(Value* vtimeout=options->get(http_timeout_name)) {
                         valid_options++;                          valid_options++;
Line 380  static File_read_http_result file_read_h Line 390  static File_read_http_result file_read_h
         request<< " "<< uri <<" HTTP/1.0\nHost: "<< host<<"\n";           request<< " "<< uri <<" HTTP/1.0\nHost: "<< host<<"\n"; 
         bool user_agent_specified=false;          bool user_agent_specified=false;
         if(vheaders && !vheaders->is_string()) { // allow empty          if(vheaders && !vheaders->is_string()) { // allow empty
                 if(HashStringValue *headers=vheaders->get_hash(connect_string)) {                  if(HashStringValue *headers=vheaders->get_hash()) {
                         Http_pass_header_info info={&&charset, &request};                          Http_pass_header_info info={&charset, &request};
                         headers->for_each(http_pass_header, &info);                           headers->for_each(http_pass_header, &info); 
                         user_agent_specified=info.user_agent_specified;                          user_agent_specified=info.user_agent_specified;
                 } else                  } else
                         throw Exception("parser.runtime",                           throw Exception("parser.runtime", 
                                 connect_string,                                  &connect_string,
                                 "headers param must be hash");                                   "headers param must be hash"); 
         };          };
         if(!user_agent_specified) // defaulting          if(!user_agent_specified) // defaulting
Line 397  static File_read_http_result file_read_h Line 407  static File_read_http_result file_read_h
         String response;          String response;
         const char* request_cstr=request.cstr(String::L_UNSPECIFIED);          const char* request_cstr=request.cstr(String::L_UNSPECIFIED);
         int status_code=http_request(response,          int status_code=http_request(response,
                 connect_string, host, port, request_cstr,                   host, port, request_cstr, 
                 timeout, fail_on_status_ne_200);                   timeout, fail_on_status_ne_200); 
                   
         //processing results              //processing results    
         int pos=response.pos("\r\n\r\n", 4);           size_t pos=response.pos("\r\n\r\n", 4); 
         if(pos<1){          if(pos==STRING_NOT_FOUND || pos<1){
                 throw Exception("http.response",                   throw Exception("http.response", 
                         connect_string,                          &connect_string,
                         "bad response from host - no headers found");                           "bad response from host - no headers found"); 
         }          }
         const String& header_block=response.mid(0, pos);           const String& header_block=response.mid(0, pos); 
         const String& body=response.mid(pos+4, response.length());           const String& body=response.mid(pos+4, response.length()); 
                   
         ArrayString aheaders;          ArrayString aheaders;
         result.headers=HashStringValue* (new HashStringValue);           result.headers=new HashStringValue;
         header_block->split(aheaders, 0, "\r\n", 2);           size_t pos_after=0;
           header_block.split(aheaders, pos_after, "\r\n"); 
                   
         //processing headers          //processing headers
         for(int i=1; i<aheaders.count(); i++) {          size_t aheaders_count=aheaders.count();
                 const String& line=aheaders.get(i);          for(size_t i=1; i<aheaders_count; i++) {
                 pos=line->pos(": ", 2);                   const String& line=*aheaders.get(i);
                 if(pos<1)                  pos=line.pos(": ", 2); 
                   if(pos==STRING_NOT_FOUND || pos<1)
                         throw Exception("http.response",                           throw Exception("http.response", 
                                 connect_string,                                  &connect_string,
                                 "bad response from host - bad header \"%s\"", line->cstr().get());                                  "bad response from host - bad header \"%s\"", line.cstr());
                                                   
                 result.headers->put(                  result.headers->put(
                         line->mid(0, pos)->change_case(charset, String::CC_UPPER),                           line.mid(0, pos).change_case(charset, String::CC_UPPER), 
                         Value*(new VString(line->mid(pos+2, line->length()))));                           new VString(line.mid(pos+2, line.length())));
         }          }
   
         // output response          // output response
         result.str=new(PointerFreeGC) char[1/*as text puts terminating zero later*/+(result.length=body->length())];          result.str=body.cstrm();
         body->store_to(result.str, String::L_AS_IS);          result.length=body.length();
         result.headers->put(file_status_name, Value*(new VInt(status_code)));           result.headers->put(file_status_name, new VInt(status_code));
         return result;          return result;
 }  }
   
Line 470  static void file_read_action( Line 482  static void file_read_action(
 File_read_result file_read(Charset& charset, const String& file_spec,   File_read_result file_read(Charset& charset, const String& file_spec, 
                            bool as_text, HashStringValue *params,                             bool as_text, HashStringValue *params,
                            bool fail_on_read_problem) {                             bool fail_on_read_problem) {
         File_read_result result;          File_read_result result={false};
 #ifdef PA_HTTP  #ifdef PA_HTTP
         if(file_spec.starts_with("http://", 7)) {          if(file_spec.starts_with("http://")) {
                 // fail on read problem                  // fail on read problem
                 File_read_http_result http=file_read_http(charset, file_spec, params);                  File_read_http_result http;//=file_read_http(charset, file_spec, params);
                 result.success=true;                  result.success=true;
                 result.str=http.data;                  result.str="HELLO";//http.str;
                 result.length=http.size;                  result.length=5;//http.length;
                 result.headers=http.headers;                   result.headers=new HashStringValue;//http.headers; 
         } else {          } else {
 #endif  #endif
                 File_read_action_info info={&result.str, &result.length};                   File_read_action_info info={&result.str, &result.length}; 
Line 569  bool file_read_action_under_lock(const S Line 581  bool file_read_action_under_lock(const S
   
 static void create_dir_for_file(const String& file_spec) {  static void create_dir_for_file(const String& file_spec) {
         size_t pos_after=1;          size_t pos_after=1;
         int pos_before;          size_t pos_before;
         while((pos_before=file_spec.pos("/", pos_after))>=0) {          while((pos_before=file_spec.pos('/', pos_after))!=STRING_NOT_FOUND) {
                 mkdir(file_spec.mid(0, pos_before).cstr(String::L_FILE_SPEC), 0775);                   mkdir(file_spec.mid(0, pos_before).cstr(String::L_FILE_SPEC), 0775); 
                 pos_after=pos_before+1;                  pos_after=pos_before+1;
         }          }
Line 658  void file_write( Line 670  void file_write(
   
 // throws nothing! [this is required in file_move & file_delete]  // throws nothing! [this is required in file_move & file_delete]
 static void rmdir(const String& file_spec, size_t pos_after) {  static void rmdir(const String& file_spec, size_t pos_after) {
         int pos_before;          size_t pos_before;
         if((pos_before=file_spec.pos("/", pos_after))>=0)          if((pos_before=file_spec.pos('/', pos_after))!=STRING_NOT_FOUND)
                 rmdir(file_spec, pos_before+1);                   rmdir(file_spec, pos_before+1); 
                   
         rmdir(file_spec.mid(0, pos_after-1/* / */).cstr(String::L_FILE_SPEC));           rmdir(file_spec.mid(0, pos_after-1/* / */).cstr(String::L_FILE_SPEC)); 
Line 732  bool file_readable(const String& file_sp Line 744  bool file_readable(const String& file_sp
 bool dir_readable(const String& file_spec) {  bool dir_readable(const String& file_spec) {
         return entry_readable(file_spec, true);           return entry_readable(file_spec, true); 
 }  }
 const String* file_readable(String& path, String& name) {  const String* file_readable(const String& path, const String& name) {
         String& result=*new String(path);          String& result=*new String(path);
         result << "/";           result << "/"; 
         result << name;          result << name;
Line 749  bool file_stat(const String& file_spec, Line 761  bool file_stat(const String& file_spec,
                            time_t& rctime,                              time_t& rctime, 
                            bool fail_on_read_problem) {                             bool fail_on_read_problem) {
         const char* fname=file_spec.cstr(String::L_FILE_SPEC);           const char* fname=file_spec.cstr(String::L_FILE_SPEC); 
     struct stat finfo;          struct stat finfo;
         if(stat(fname, &finfo)!=0)          if(stat(fname, &finfo)!=0)
                 if(fail_on_read_problem)                  if(fail_on_read_problem)
                         throw Exception("file.missing",                           throw Exception("file.missing", 

Removed from v.1.143.2.21.2.8  
changed lines
  Added in v.1.143.2.21.2.19


E-mail: