Diff for /parser3/src/main/pa_http.C between versions 1.60 and 1.69

version 1.60, 2014/04/15 21:52:57 version 1.69, 2015/10/26 01:21:58
Line 1 Line 1
 /** @file  /** @file
         Parser: http support functions.          Parser: http support functions.
   
         Copyright (c) 2001-2012 Art. Lebedev Studio (http://www.artlebedev.com)          Copyright (c) 2001-2015 Art. Lebedev Studio (http://www.artlebedev.com)
         Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)          Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
  */   */
   
Line 68  static bool set_addr(struct sockaddr_in Line 68  static bool set_addr(struct sockaddr_in
         addr->sin_family=AF_INET;          addr->sin_family=AF_INET;
         addr->sin_port=htons(port);           addr->sin_port=htons(port); 
         if(host) {          if(host) {
                 ulong packed_ip=inet_addr(host);                  struct hostent *hostIP=gethostbyname(host);
                 if(packed_ip!=INADDR_NONE)                  if(hostIP && hostIP->h_addrtype == AF_INET){
                         memcpy(&addr->sin_addr, &packed_ip, sizeof(packed_ip));                           memcpy(&addr->sin_addr, hostIP->h_addr, hostIP->h_length);
                 else {                          return true;
                         struct hostent *hostIP=gethostbyname(host);                  }
                         if(hostIP)           }
                                 memcpy(&addr->sin_addr, hostIP->h_addr, hostIP->h_length);           return false;
                         else  
                                 return false;  
                 }   
         } else   
                 addr->sin_addr.s_addr=INADDR_ANY;  
         return true;  
 }  }
   
 size_t guess_content_length(char* buf) {  size_t guess_content_length(char* buf) {
Line 347  static void http_pass_header(HashStringV Line 341  static void http_pass_header(HashStringV
                 *info->user_agent_specified=true;                  *info->user_agent_specified=true;
         if(strcasecmp(name_cstr, HTTP_CONTENT_TYPE)==0){          if(strcasecmp(name_cstr, HTTP_CONTENT_TYPE)==0){
                 *info->content_type_specified=true;                  *info->content_type_specified=true;
                 *info->content_type_url_encoded=StrStartFromNC(value.cstr(), HTTP_CONTENT_TYPE_FORM_URLENCODED);                  *info->content_type_url_encoded=pa_strncasecmp(value.cstr(), HTTP_CONTENT_TYPE_FORM_URLENCODED)==0;
         }          }
 }  }
   
Line 410  static void form_value2string( Line 404  static void form_value2string(
         } else          } else
                 throw Exception(PARSER_RUNTIME,                  throw Exception(PARSER_RUNTIME,
                         new String(key, String::L_TAINTED),                          new String(key, String::L_TAINTED),
                         "is %s, "HTTP_FORM_NAME" option value can be string or table only (file is allowed for $."HTTP_METHOD_NAME"[POST] + $."HTTP_FORM_ENCTYPE_NAME"["HTTP_CONTENT_TYPE_MULTIPART_FORMDATA"])", value->type());                          "is %s, " HTTP_FORM_NAME " option value can be string or table only (file is allowed for $." HTTP_METHOD_NAME "[POST] + $." HTTP_FORM_ENCTYPE_NAME "[" HTTP_CONTENT_TYPE_MULTIPART_FORMDATA "])", value->type());
 }  }
   
 const char* pa_form2string(HashStringValue& form, Request_charsets& charsets) {  const char* pa_form2string(HashStringValue& form, Request_charsets& charsets) {
Line 516  static void form_value2part( Line 510  static void form_value2part(
         } else          } else
                 throw Exception(PARSER_RUNTIME,                  throw Exception(PARSER_RUNTIME,
                         new String(key, String::L_TAINTED),                          new String(key, String::L_TAINTED),
                         "is %s, "HTTP_FORM_NAME" option value can be string, table or file only", value->type());                          "is %s, " HTTP_FORM_NAME " option value can be string, table or file only", value->type());
 }  }
   
 const char* pa_form2string_multipart(HashStringValue& form, Request& r, const char* boundary, size_t& post_size){  const char* pa_form2string_multipart(HashStringValue& form, Request& r, const char* boundary, size_t& post_size){
Line 548  static void find_headers_end(char* p, Line 542  static void find_headers_end(char* p,
   
 // Set-Cookie: name=value; Domain=docs.foo.com; Path=/accounts; Expires=Wed, 13-Jan-2021 22:23:01 GMT; Secure; HttpOnly  // Set-Cookie: name=value; Domain=docs.foo.com; Path=/accounts; Expires=Wed, 13-Jan-2021 22:23:01 GMT; Secure; HttpOnly
 static ArrayString* parse_cookie(Request& r, const String& cookie) {  static ArrayString* parse_cookie(Request& r, const String& cookie) {
         char *current=strdup(cookie.cstr());          char *current=pa_strdup(cookie.cstr());
                   
         const String* name=0;          const String* name=0;
         const String* value=&String::Empty;          const String* value=&String::Empty;
Line 630  File_read_http_result pa_internal_file_r Line 624  File_read_http_result pa_internal_file_r
                                                 bool transcode_text_result) {                                                  bool transcode_text_result) {
         File_read_http_result result;          File_read_http_result result;
         char host[MAX_STRING];          char host[MAX_STRING];
           const char *idna_host;
         const char* uri;           const char* uri; 
         short port=80;          short port=80;
         const char* method="GET";          const char* method="GET";
Line 686  File_read_http_result pa_internal_file_r Line 681  File_read_http_result pa_internal_file_r
                         omit_post_charset=vomit_post_charset->as_bool();                          omit_post_charset=vomit_post_charset->as_bool();
                 }                  }
                 if(Value* vcharset_name=options->get(PA_CHARSET_NAME)) {                  if(Value* vcharset_name=options->get(PA_CHARSET_NAME)) {
                         valid_options++;  
                         asked_remote_charset=&charsets.get(vcharset_name->as_string().change_case(r.charsets.source(), String::CC_UPPER));                          asked_remote_charset=&charsets.get(vcharset_name->as_string().change_case(r.charsets.source(), String::CC_UPPER));
                 }                   } 
                 if(Value* vresponse_charset_name=options->get(PA_RESPONSE_CHARSET_NAME)) {                  if(Value* vresponse_charset_name=options->get(PA_RESPONSE_CHARSET_NAME)) {
                           valid_options++;
                         real_remote_charset=&charsets.get(vresponse_charset_name->as_string().change_case(r.charsets.source(), String::CC_UPPER));                          real_remote_charset=&charsets.get(vresponse_charset_name->as_string().change_case(r.charsets.source(), String::CC_UPPER));
                 }                   } 
                 if(Value* vuser=options->get(HTTP_USER)) {                  if(Value* vuser=options->get(HTTP_USER)) {
Line 711  File_read_http_result pa_internal_file_r Line 706  File_read_http_result pa_internal_file_r
                 if(method_is_get)                  if(method_is_get)
                         throw Exception(PARSER_RUNTIME,                          throw Exception(PARSER_RUNTIME,
                                 0,                                  0,
                                 "you can not use $."HTTP_FORM_ENCTYPE_NAME" option with method GET");                                  "you can not use $." HTTP_FORM_ENCTYPE_NAME " option with method GET");
   
                 multipart=strcasecmp(encode, HTTP_CONTENT_TYPE_MULTIPART_FORMDATA)==0;                  multipart=strcasecmp(encode, HTTP_CONTENT_TYPE_MULTIPART_FORMDATA)==0;
   
                 if(!multipart && strcasecmp(encode, HTTP_CONTENT_TYPE_FORM_URLENCODED)!=0)                  if(!multipart && strcasecmp(encode, HTTP_CONTENT_TYPE_FORM_URLENCODED)!=0)
                         throw Exception(PARSER_RUNTIME,                          throw Exception(PARSER_RUNTIME,
                                 0,                                  0,
                                 "$."HTTP_FORM_ENCTYPE_NAME" option value can be "HTTP_CONTENT_TYPE_FORM_URLENCODED" or "HTTP_CONTENT_TYPE_MULTIPART_FORMDATA" only");                                  "$." HTTP_FORM_ENCTYPE_NAME " option value can be " HTTP_CONTENT_TYPE_FORM_URLENCODED " or " HTTP_CONTENT_TYPE_MULTIPART_FORMDATA " only");
         }          }
   
         if(vbody){          if(vbody){
                 if(method_is_get)                  if(method_is_get)
                         throw Exception(PARSER_RUNTIME,                          throw Exception(PARSER_RUNTIME,
                                 0,                                  0,
                                 "you can not use $."HTTP_BODY_NAME" option with method GET");                                  "you can not use $." HTTP_BODY_NAME " option with method GET");
   
                 if(form)                  if(form)
                         throw Exception(PARSER_RUNTIME,                          throw Exception(PARSER_RUNTIME,
                                 0,                                  0,
                                 "you can not use options $."HTTP_BODY_NAME" and $."HTTP_FORM_NAME" together");                                  "you can not use options $." HTTP_BODY_NAME " and $." HTTP_FORM_NAME " together");
         }          }
   
         //preparing request          //preparing request
Line 763  File_read_http_result pa_internal_file_r Line 758  File_read_http_result pa_internal_file_r
                                 throw Exception(PARSER_RUNTIME, &connect_string, "invalid port number '%s'", port_cstr);                                  throw Exception(PARSER_RUNTIME, &connect_string, "invalid port number '%s'", port_cstr);
                 }                  }
   
                   idna_host=pa_idna_encode(host, r.charsets.source());
   
                 // making request head                  // making request head
                 String head;                  String head;
                 head << method << " " << uri;                  head << method << " " << uri;
                 if(method_is_get && form)                  if(method_is_get && form)
                         head << (strchr(uri, '?')!=0?"&":"?") << pa_form2string(*form, r.charsets);                          head << (strchr(uri, '?')!=0?"&":"?") << pa_form2string(*form, r.charsets);
   
                 head <<" HTTP/1.0" CRLF "Host: "<< host;                  head <<" HTTP/1.0" CRLF "Host: "<< idna_host;
                 if (port != 80)                  if (port != 80)
                         head << ":" << port_cstr;                          head << ":" << port_cstr;
                 head << CRLF;                  head << CRLF;
Line 834  File_read_http_result pa_internal_file_r Line 831  File_read_http_result pa_internal_file_r
                                         String::C(vbody->as_string().cstr(), vbody->as_string().length()),                                          String::C(vbody->as_string().cstr(), vbody->as_string().length()),
                                         r.charsets.source(),                                          r.charsets.source(),
                                         *asked_remote_charset                                          *asked_remote_charset
                                 );                                  ).str;
                         }                          }
                         post_size=strlen(request_body);                          post_size=strlen(request_body);
                 }                  }
Line 890  File_read_http_result pa_internal_file_r Line 887  File_read_http_result pa_internal_file_r
   
         // sending request          // sending request
         int status_code=http_request(response, response_size,          int status_code=http_request(response, response_size,
                 host, port, request, request_size,                  idna_host, port, request, request_size,
                 timeout_secs, fail_on_status_ne_200);                   timeout_secs, fail_on_status_ne_200); 
                   
         // processing results             // processing results   
Line 960  File_read_http_result pa_internal_file_r Line 957  File_read_http_result pa_internal_file_r
                         result.headers->put(HTTP_COOKIES_NAME, new VTable(parse_cookies(r, vcookies->get_table())));                          result.headers->put(HTTP_COOKIES_NAME, new VTable(parse_cookies(r, vcookies->get_table())));
         }          }
   
         if(as_text && raw_body_size>=3 && strncmp(raw_body, "\xEF\xBB\xBF", 3)==0){          if(as_text){
                 // skip UTF-8 signature (BOM code)                  real_remote_charset=charsets.checkBOM(raw_body, raw_body_size, real_remote_charset);
                 raw_body+=3;  
                 raw_body_size-=3;  
                 if(!real_remote_charset)  
                         real_remote_charset=&UTF8_charset;  
         }          }
   
         // output response          // output response

Removed from v.1.60  
changed lines
  Added in v.1.69


E-mail: