Diff for /parser3/src/main/pa_http.C between versions 1.121 and 1.129

version 1.121, 2023/09/26 20:49:10 version 1.129, 2024/11/04 03:53:25
Line 1 Line 1
 /** @file  /** @file
         Parser: http support functions.          Parser: http support functions.
   
         Copyright (c) 2001-2023 Art. Lebedev Studio (http://www.artlebedev.com)          Copyright (c) 2001-2024 Art. Lebedev Studio (http://www.artlebedev.com)
         Authors: Konstantin Morshnev <moko@design.ru>, Alexandr Petrosian <paf@design.ru>          Authors: Konstantin Morshnev <moko@design.ru>, Alexandr Petrosian <paf@design.ru>
  */   */
   
Line 173  public: Line 173  public:
                 ArrayString aheaders;                  ArrayString aheaders;
                 header_block.split(aheaders, 0, "\n");                  header_block.split(aheaders, 0, "\n");
   
                 Array_iterator<const String*> i(aheaders);                  ArrayString::Iterator i(aheaders);
                 i.next(); // skipping status                  i.next(); // skipping status
                 for(;i.has_next();){                  for(;i;){
                         const char *line=i.next()->cstr();                          const char *line=i.next()->cstr();
                         if(!headers.add_header(line))                          if(!headers.add_header(line))
                                 throw Exception("http.response", 0, "bad response from host - bad header \"%s\"", line);                                  throw Exception("http.response", 0, "bad response from host - bad header \"%s\"", line);
Line 288  static int http_request(HTTP_response& r Line 288  static int http_request(HTTP_response& r
                         struct sockaddr_in dest;                          struct sockaddr_in dest;
                                   
                         if(!set_addr(&dest, host, port))                          if(!set_addr(&dest, host, port))
                                 throw Exception("http.host", 0, "can not resolve hostname \"%s\"", host);                                   throw Exception("http.host", 0, "cannot resolve hostname \"%s\"", host); 
                                                   
                         if((sock=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP/*0*/)) == INVALID_SOCKET) {                          if((sock=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP/*0*/)) == INVALID_SOCKET) {
                                 int no=pa_socks_errno();                                  int no=pa_socks_errno();
                                 throw Exception("http.connect", 0, "can not make socket: %s (%d)", pa_socks_strerr(no), no);                                   throw Exception("http.connect", 0, "cannot make socket: %s (%d)", pa_socks_strerr(no), no); 
                         }                          }
   
                         // To enable SO_DONTLINGER (that is, disable SO_LINGER)                           // To enable SO_DONTLINGER (that is, disable SO_LINGER) 
Line 311  static int http_request(HTTP_response& r Line 311  static int http_request(HTTP_response& r
   
                         if(connect(sock, (struct sockaddr *)&dest, sizeof(dest))) {                          if(connect(sock, (struct sockaddr *)&dest, sizeof(dest))) {
                                 int no=pa_socks_errno();                                  int no=pa_socks_errno();
                                 throw Exception("http.connect", 0, "can not connect to host \"%s\": %s (%d)", host, pa_socks_strerr(no), no);                                  throw Exception("http.connect", 0, "cannot connect to host \"%s\": %s (%d)", host, pa_socks_strerr(no), no);
                         }                          }
   
                         if(send(sock, request, request_size, 0)!=(ssize_t)request_size) {                          if(send(sock, request, request_size, 0)!=(ssize_t)request_size) {
Line 511  static void form_value2part(HashStringVa Line 511  static void form_value2part(HashStringVa
                 Form_table_value2string_info info(key, *part.string);                  Form_table_value2string_info info(key, *part.string);
                 part.info = &info;                  part.info = &info;
                 tvalue->for_each(form_table_value2part, &part);                  tvalue->for_each(form_table_value2part, &part);
         } else if(VFile* vfile=static_cast<VFile *>(value->as("file"))){          } else if(VFile* vfile=dynamic_cast<VFile *>(value)){
                 form_file_value2part(key, *vfile, part);                  form_file_value2part(key, *vfile, part);
         } else          } else
                 throw Exception(PARSER_RUNTIME, new String(key, String::L_TAINTED), "is %s, " HTTP_FORM_NAME " option value can be string, table or file only", value->type());                  throw Exception(PARSER_RUNTIME, new String(key, String::L_TAINTED), "is %s, " HTTP_FORM_NAME " option value can be string, table or file only", value->type());
Line 551  static ArrayString* parse_cookie(Request Line 551  static ArrayString* parse_cookie(Request
                                 if(first_pair) {                                  if(first_pair) {
                                         // name + value                                          // name + value
                                         name=sname;                                          name=sname;
                                         value=smeaning;                                          if(smeaning)
                                                   value=smeaning;
                                         first_pair=false;                                          first_pair=false;
                                 } else {                                  } else {
                                         const String& slower=sname->change_case(r.charsets.source(), String::CC_LOWER);                                          const String& slower=sname->change_case(r.charsets.source(), String::CC_LOWER);
Line 594  static ArrayString* parse_cookie(Request Line 595  static ArrayString* parse_cookie(Request
 Table* parse_cookies(Request& r, Table *cookies){  Table* parse_cookies(Request& r, Table *cookies){
         Table& result=*new Table(new Cookies_table_template_columns);          Table& result=*new Table(new Cookies_table_template_columns);
   
         for(Array_iterator<Table::element_type> i(*cookies); i.has_next(); )          for(Array_iterator<Table::element_type> i(*cookies); i; )
                 if(ArrayString* row=parse_cookie(r, *i.next()->get(0)))                  if(ArrayString* row=parse_cookie(r, *i.next()->get(0)))
                         result+=row;                          result+=row;
   
Line 703  File_read_http_result pa_internal_file_r Line 704  File_read_http_result pa_internal_file_r
   
         if(encode){          if(encode){
                 if(method_is_get)                  if(method_is_get)
                         throw Exception(PARSER_RUNTIME, 0, "you can not use $." HTTP_FORM_ENCTYPE_NAME " option with method GET");                          throw Exception(PARSER_RUNTIME, 0, "you cannot 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;
   
Line 713  File_read_http_result pa_internal_file_r Line 714  File_read_http_result pa_internal_file_r
   
         if(vbody){          if(vbody){
                 if(method_is_get)                  if(method_is_get)
                         throw Exception(PARSER_RUNTIME, 0, "you can not use $." HTTP_BODY_NAME " option with method GET");                          throw Exception(PARSER_RUNTIME, 0, "you cannot use $." HTTP_BODY_NAME " option with method GET");
   
                 if(form)                  if(form)
                         throw Exception(PARSER_RUNTIME, 0, "you can not use options $." HTTP_BODY_NAME " and $." HTTP_FORM_NAME " together");                          throw Exception(PARSER_RUNTIME, 0, "you cannot use options $." HTTP_BODY_NAME " and $." HTTP_FORM_NAME " together");
         }          }
   
         //preparing request          //preparing request
Line 831  File_read_http_result pa_internal_file_r Line 832  File_read_http_result pa_internal_file_r
                 }                  }
   
                 if(request_body)                  if(request_body)
                         head << "Content-Length: " << format(post_size, "%u") << CRLF;                          head << "Content-Length: " << pa_uitoa(post_size) << CRLF;
                                   
                 head << CRLF;                  head << CRLF;
                                   
Line 874  File_read_http_result pa_internal_file_r Line 875  File_read_http_result pa_internal_file_r
         if (!real_remote_charset)          if (!real_remote_charset)
                 real_remote_charset=asked_remote_charset; // never null                  real_remote_charset=asked_remote_charset; // never null
   
         for(Array_iterator<HTTP_Headers::Header> i(response.headers.headers); i.has_next(); ){          for(Array_iterator<HTTP_Headers::Header> i(response.headers.headers); i; ){
                 HTTP_Headers::Header header=i.next();                  HTTP_Headers::Header header=i.next();
   
                 header.transcode(*real_remote_charset, r.charsets.source());                  header.transcode(*real_remote_charset, r.charsets.source());
Line 1217  bool HTTPD_Connection::accept(SOCKET ser Line 1218  bool HTTPD_Connection::accept(SOCKET ser
                 throw Exception("httpd.accept", 0, "error accepting connection: %s (%d)", pa_socks_strerr(no), no);                  throw Exception("httpd.accept", 0, "error accepting connection: %s (%d)", pa_socks_strerr(no), no);
         }          }
   
   //      Has no positive performance effect, requires include <netinet/tcp.h>
   //      static int sock_on=1;
   //      setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&sock_on, sizeof(sock_on));
   
         remote_addr = pa_strdup(inet_ntoa(addr.sin_addr));          remote_addr = pa_strdup(inet_ntoa(addr.sin_addr));
         LOG(pa_log("httpd [%d] accepted from %s", sock, remote_addr));          LOG(pa_log("httpd [%d] accepted from %s", sock, remote_addr));
         return true;          return true;
Line 1253  SOCKET HTTPD_Server::bind(const char *ho Line 1258  SOCKET HTTPD_Server::bind(const char *ho
   
         if(!set_addr(&me, host, (short)pa_atoui(port))){          if(!set_addr(&me, host, (short)pa_atoui(port))){
                 if (host)                  if (host)
                         throw Exception("httpd.bind", 0, "can not resolve hostname \"%s\"", host);                          throw Exception("httpd.bind", 0, "cannot resolve hostname \"%s\"", host);
                 me.sin_addr.s_addr=INADDR_ANY;                  me.sin_addr.s_addr=INADDR_ANY;
         }          }
   
Line 1261  SOCKET HTTPD_Server::bind(const char *ho Line 1266  SOCKET HTTPD_Server::bind(const char *ho
   
         if(sock == INVALID_SOCKET){          if(sock == INVALID_SOCKET){
                 int no=pa_socks_errno();                  int no=pa_socks_errno();
                 throw Exception("httpd.bind", 0, "can not make socket: %s (%d)", pa_socks_strerr(no), no);                  throw Exception("httpd.bind", 0, "cannot make socket: %s (%d)", pa_socks_strerr(no), no);
         }          }
   
         static int sock_on = 1;          static int sock_on = 1;
Line 1272  SOCKET HTTPD_Server::bind(const char *ho Line 1277  SOCKET HTTPD_Server::bind(const char *ho
             listen(sock, 16)) {              listen(sock, 16)) {
                 closesocket(sock);                  closesocket(sock);
                 int no = pa_socks_errno();                  int no = pa_socks_errno();
                 throw Exception("httpd.bind", 0, "can not bind socket: %s (%d)", pa_socks_strerr(no), no);                  throw Exception("httpd.bind", 0, "cannot bind socket: %s (%d)", pa_socks_strerr(no), no);
         }          }
         return sock;          return sock;
 }  }

Removed from v.1.121  
changed lines
  Added in v.1.129


E-mail: