Diff for /parser3/src/main/pa_request.C between versions 1.112 and 1.133

version 1.112, 2001/04/11 15:45:51 version 1.133, 2001/05/21 07:33:53
Line 10 Line 10
   
 #include "pa_config_includes.h"  #include "pa_config_includes.h"
   
 #include <locale.h>  #include "pcre.h"
   #include "internal.h"
   extern "C" unsigned char pcre_default_tables[]; // pcre/chartables.c
   
 #include "pa_sapi.h"  #include "pa_sapi.h"
 #include "pa_common.h"  #include "pa_common.h"
 #include "pa_request.h"  #include "pa_request.h"
 #include "pa_wwrapper.h"  #include "pa_wwrapper.h"
 #include "pa_vclass.h"  #include "pa_vclass.h"
 #include "_op.h"  
 #include "_table.h"  
 #include "_file.h"  
 #include "pa_globals.h"  #include "pa_globals.h"
 #include "pa_vint.h"  #include "pa_vint.h"
 #include "pa_vmethod_frame.h"  #include "pa_vmethod_frame.h"
 #include "pa_types.h"  #include "pa_types.h"
 #include "pa_vtable.h"  #include "pa_vtable.h"
 #include "_random.h"  
 #include "pa_vfile.h"  #include "pa_vfile.h"
 #include "_mail.h"  
 #include "_exec.h"  
 #include "_image.h"  
   
 /// $LIMITS.post_max_size default 10M  
 const size_t MAX_POST_SIZE_DEFAULT=10*0x400*400;  
   
 /// content type of exception response, when no @MAIN:exception handler defined  /// content type of exception response, when no @MAIN:exception handler defined
 const char *UNHANDLED_EXCEPTION_CONTENT_TYPE="text/plain";  const char *UNHANDLED_EXCEPTION_CONTENT_TYPE="text/plain";
Line 40  const char *UNHANDLED_EXCEPTION_CONTENT_ Line 32  const char *UNHANDLED_EXCEPTION_CONTENT_
 /// content type of response when no $MAIN:defaults.content-type defined  /// content type of response when no $MAIN:defaults.content-type defined
 const char *DEFAULT_CONTENT_TYPE="text/html";  const char *DEFAULT_CONTENT_TYPE="text/html";
   
   Methoded *MOP_create(Pool&);
   
 //  //
 Request::Request(Pool& apool,  Request::Request(Pool& apool,
                                  Info& ainfo,                                   Info& ainfo,
                                  String::Untaint_lang adefault_lang) : Pooled(apool),                                   String::Untaint_lang adefault_lang) : Pooled(apool),
         stack(apool),          stack(apool),
         OP(apool),          OP(*MOP_create(apool)),
         env(apool),          env(apool),
         form(apool),          form(apool),
         request(apool, *this),          request(apool, *this),
Line 58  Request::Request(Pool& apool, Line 52  Request::Request(Pool& apool,
         used_files(apool),          used_files(apool),
         default_content_type(0),          default_content_type(0),
         mime_types(0),          mime_types(0),
         connection(0), protocol2library(0),          main_class(0),
         mail(0)          connection(0),
           pcre_tables(0),
           classes_conf(apool),
           anti_endless_execute_recoursion(0)
 {  {
         // root superclass,           /// directly used
         //   parent of all classes,           // operators
         //   operators holder          OP.register_directly_used(*this);
         initialize_op_class(pool(), OP);          // classes:
         classes().put(*op_class_name, &OP);          // table, file, random, mail, image, ...
         // table class          methoded_array->register_directly_used(*this);
         classes().put(*table_class_name, table_class);    
         // file class          /// methodless
         classes().put(*file_class_name, file_class);      
         // random class  
         classes().put(*random_class_name, random_class);          
         // env class          // env class
         classes().put(*env_class_name, &env);          classes().put(*NEW String(pool(), ENV_CLASS_NAME), &env);
         // form class  
         classes().put(*form_class_name, &form);   
         // request class          // request class
         classes().put(*request_class_name, &request);             classes().put(*NEW String(pool(), REQUEST_CLASS_NAME), &request);       
         // response class  
         classes().put(*response_class_name, &response);   
         // cookie class          // cookie class
         classes().put(*cookie_class_name, &cookie);          classes().put(*NEW String(pool(), COOKIE_CLASS_NAME), &cookie);
         // mail class  
         classes().put(*mail_class_name, mail_class);          /// methoded
         // image class          // response class
         classes().put(*image_class_name, image_class);          classes().put(response.get_class()->name(), &response); 
   
           /// bases used
           // form class
           classes().put(form.get_class()->base()->name(), &form); 
 }  }
   
   static void element2ctypes(unsigned char *tables, 
           Value& ctype, const String& name, 
           unsigned char bit,
           int group_offset=-1,
           bool skip_ws=true) {
           Value *value=ctype.get_element(name);
           if(!value)
                   return;
   
           unsigned char *ctypes_table=tables+ctypes_offset;
           const unsigned char *cstr=
                   (const unsigned char *)value->as_string().cstr(String::UL_AS_IS);
           for(; *cstr; cstr++) {
                   unsigned char c=*cstr;
                   if(skip_ws && (c=='\n' || c=='\t' || c==' '))
                           continue;
                   ctypes_table[c]|=bit;
   
                   if(group_offset>=0)
                           tables[cbits_offset+group_offset+c/8] |= 1 << (c%8);
           }                               
   }
   static void cstr2ctypes(unsigned char *tables, const unsigned char *cstr, 
                                                   unsigned char bit) {
           unsigned char *ctypes_table=tables+ctypes_offset;
           ctypes_table[0]=bit;
           for(; *cstr; cstr++) {
                   unsigned char c=*cstr;
                   ctypes_table[c]|=bit;
           }
   }
   static void prepare_case_tables(unsigned char *tables) {
           unsigned char *lcc_table=tables+lcc_offset;
           unsigned char *fcc_table=tables+fcc_offset;
           for(int i=0; i<0x100; i++)
                   lcc_table[i]=fcc_table[i]=i;
   }
   static void element2case(unsigned char *tables, Value& ctype, const String& name) {
           Value *value=ctype.get_element(name);
           if(!value)
                   return;
   
           unsigned char *lcc_table=tables+lcc_offset;
           unsigned char *fcc_table=tables+fcc_offset;
           const unsigned char *cstr=
                   (const unsigned char *)value->as_string().cstr(String::UL_AS_IS);
           unsigned char from=0;
           for(; *cstr; cstr++) {
                   unsigned char c=*cstr;
                   if(c=='\n' || c=='\t' || c==' ')
                           continue;
                   if(from) {
                           lcc_table[from]=c;
                           fcc_table[from]=c; fcc_table[c]=from;
                           from=0;
                   } else
                           from=c;
           }
   }
 /**  /**
         load MAIN class, execute @main.          load MAIN class, execute @main.
         MAIN class consists of all the auto.p files we'd manage to find          MAIN class consists of all the auto.p files we'd manage to find
Line 95  Request::Request(Pool& apool, Line 148  Request::Request(Pool& apool,
         the file user requested us to process          the file user requested us to process
         all located classes become children of one another,          all located classes become children of one another,
         composing class we name 'MAIN'          composing class we name 'MAIN'
   
         @test get read of setlocale  
 */  */
 void Request::core(const char *root_auto_path, bool root_auto_fail,  void Request::core(const char *root_auto_path, bool root_auto_fail,
                                    const char *site_auto_path, bool site_auto_fail,                                     const char *site_auto_path, bool site_auto_fail,
                                    bool header_only) {                                     bool header_only) {
         VStateless_class *main_class=0;          //_asm { int 3 }
         bool need_rethrow=false;  Exception rethrow_me;          bool need_rethrow=false;  Exception rethrow_me;
         TRY {          TRY {
                 char *auto_filespec=(char *)malloc(MAX_STRING);                  char *auto_filespec=(char *)malloc(MAX_STRING);
Line 116  void Request::core(const char *root_auto Line 167  void Request::core(const char *root_auto
                                 main_class_name, main_class);                                  main_class_name, main_class);
                 }                  }
   
                 // $MAIN:LIMITS hash used here,                  // configure root options
                 //      until someone with less privileges have overriden them                  //      until someone with less privileges have overriden them
                 {                  OP.configure_admin(*this);
                         Value *limits=main_class?main_class->get_element(*limits_name):0;                  methoded_array->configure_admin(*this);
                         if(info.method && StrEqNc(info.method, "post", true)) {  
                                 // $limits.post_max_size default 10M  
                                 Value *element=limits?limits->get_element(*post_max_size_name):0;  
                                 size_t value=element?(size_t)element->as_double():0;  
                                 size_t post_max_size=value?value:MAX_POST_SIZE_DEFAULT;  
                                   
                                 if(size_t limit=max(0, min(info.content_length, post_max_size))) {  
                                         // read POST data  
                                         post_data=(char *)malloc(limit);  
                                         post_size=SAPI::read_post(pool(), post_data, limit);  
                                         if(post_size!=limit)  
                                                 THROW(0, 0,   
                                                         0,   
                                                         "post_size(%d)!=limit(%d)",   
                                                                 post_size, limit);  
                                 }  
                         }  
   
                         form.fill_fields(*this);  
                 }  
   
                 // filling cookies  
                 cookie.fill_fields(*this);  
   
                 // loading site auto.p                  // loading site auto.p
                 if(site_auto_path) {                  if(site_auto_path) {
Line 158  void Request::core(const char *root_auto Line 186  void Request::core(const char *root_auto
                 // to the one beside requested file.                  // to the one beside requested file.
                 // all assigned bases from upper dir                  // all assigned bases from upper dir
                 {                  {
                         /* /document/root */                          Array ladder(pool());
                         char *file_spec=                          const char *after=info.path_translated;
                                 (char *)malloc(strlen(info.path_translated)+strlen(AUTO_FILE_NAME)+1);                          size_t drlen=strlen(info.document_root);
                         size_t document_root_size=strlen(info.document_root);                          if(memcmp(after, info.document_root, drlen)==0) {
                         if(info.document_root[document_root_size-1]=='/')                                  after+=drlen;
                                 document_root_size--;                                  if(after[-1]=='/') 
                         memcpy(file_spec, info.document_root, document_root_size);                                          --after;
                           }
                         /* /requested/file.html */                          
                         char *branches=(char *)malloc(strlen(info.path_translated)+1);                          while(const char *before=strchr(after, '/')) {
                         strcpy(branches, info.path_translated+document_root_size);                                  String& step=*NEW String(pool());
                         char *next=branches;                                  if(after!=info.path_translated) {
                         char *append_here=file_spec+document_root_size;                                          step.APPEND_CLEAN(
                                                   info.path_translated, before+1/* / */-info.path_translated,
                         size_t slash_auto_p_size=strlen("/" AUTO_FILE_NAME);                                                  "path-translated-scanned", ladder.size());
                         while(true) {                                          step << AUTO_FILE_NAME;
                                 char *step=lsplit(&next, '/');                                          ladder+=&step;
                                 if(next) { // not 'file.html' part                                  }
                                         size_t step_size=strlen(step);                                  after=before+1;
                                         memcpy(append_here, step, step_size);                          }
                                         append_here+=step_size;                          for(int i=ladder.size(); --i>=0; ) {
                                         memcpy(append_here, "/" AUTO_FILE_NAME, slash_auto_p_size+1);                                  const String& sfile_spec=*ladder.get_string(i);
                                         append_here++/* / */;                                  main_class=use_file(sfile_spec, false/*ignore read problem*/,
                                           main_class_name, main_class);
                                         String& sfile_spec=*NEW String(pool());  
                                         sfile_spec.APPEND_CLEAN(file_spec, 0, "scanned", 0);  
                                         main_class=use_file(sfile_spec, false/*ignore read problem*/,  
                                                 main_class_name, main_class);  
                                 } else  
                                         break;  
                         }                          }
                 }                  }
   
                 // compiling requested file                  // compile requested file
                 String& spath_translated=*NEW String(pool());                  String& spath_translated=*NEW String(pool());
                 spath_translated.APPEND_CLEAN(info.path_translated, 0, "user-request", 0);                  spath_translated.APPEND_CLEAN(info.path_translated, 0, "user-request", 0);
                 main_class=use_file(spath_translated, true/*don't ignore read problem*/,                  main_class=use_file(spath_translated, true/*don't ignore read problem*/,
                         main_class_name, main_class);                          main_class_name, main_class);
   
                   // configure not-root=user options
                   OP.configure_user(*this);
                   methoded_array->configure_user(*this);
   
                 // $MAIN:DEFAULTS                  // $MAIN:DEFAULTS
                 Value *defaults=main_class->get_element(*defaults_name);                  Value *defaults=main_class->get_element(*defaults_name);
                 // value must be allocated on request's pool for that pool used on                  // value must be allocated on request's pool for that pool used on
                 // meaning constructing @see attributed_meaning_to_string                  // meaning constructing @see attributed_meaning_to_string
                 default_content_type=defaults?defaults->get_element(*content_type_name):0;                  default_content_type=defaults?defaults->get_element(*content_type_name):0;
                 if(Value *element=main_class->get_element(*html_typo_name))                  if(Value *element=main_class->get_element(*user_html_name))
                         if(Table *table=element->get_table())                          if(Table *table=element->get_table())
                                 pool().set_tag(table);                                  pool().set_tag(table);
   
                 // $MAIN:SQL.drivers  
                 if(Value *sql=main_class->get_element(*main_sql_name))  
                         if(Value *element=sql->get_element(*main_sql_drivers_name))  
                                 protocol2library=element->get_table();            
   
                 // $MAIN:MIME-TYPES                  // $MAIN:MIME-TYPES
                 if(Value *element=main_class->get_element(*mime_types_name))                  if(Value *element=main_class->get_element(*mime_types_name))
                         if(Table *table=element->get_table())                          if(Table *table=element->get_table())
                                 mime_types=table;                                                         mime_types=table;                       
   
                 // $MAIN:LOCALE.ctype[Russian_Russia.1251]                  /*
 /*                          $MAIN:CTYPE[
 #define LC_ALL      0                                  $white-space[
 #define LC_COLLATE  1                                          ^#09^#0A^#0B^#0C^#0D^#20]
 #define LC_CTYPE    2                                  $digit[
 #define LC_MONETARY 3                                          0123456789]
 #define LC_NUMERIC  4                                  $hex-digit[
 #define LC_TIME     5                                          0123456789ABCDEFabcdef]
 */                                  $letter[
                 if(Value *locale=main_class->get_element(*locale_name))                                          ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]
                         if(Value *element=locale->get_element(*locale_ctype_name)) {                                  $word[
                                 const String& name=element->as_string();                                          0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz]
                                 if(!setlocale(LC_CTYPE, name.cstr()))  
                                         THROW(0, 0,                                  $lowercase[
                                                 &name,                                          AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz]
                                                 "locale is invalid");                          ]
                         }                  */
                   if(Value *ctype=main_class->get_element(*ctype_name)) {
                           // lowcase, flipcase, bits digit+word+whitespace, masks
                           pcre_tables=(unsigned char *)calloc(tables_length);
                           prepare_case_tables(pcre_tables);
   
                           element2ctypes(pcre_tables, *ctype, *ctype_white_space_name, ctype_space, cbit_space, false);
                           element2ctypes(pcre_tables, *ctype, *ctype_digit_name, ctype_digit, cbit_digit);
                           element2ctypes(pcre_tables, *ctype, *ctype_hex_digit_name, ctype_xdigit);
                           element2ctypes(pcre_tables, *ctype, *ctype_letter_name, ctype_letter);
                           element2ctypes(pcre_tables, *ctype, *ctype_word_name, ctype_word, cbit_word);
                           cstr2ctypes(pcre_tables, (const unsigned char *)"*+?{^.$|()[", ctype_meta);
   
                           element2case(pcre_tables, *ctype, *ctype_lowercase_name);
                   } else
                           pcre_tables=pcre_default_tables;
   
                 // $MAIN:MAIL[$SMTP[mail.design.ru]]                  // filling form fields
                 if(Value *mail_element=main_class->get_element(*mail_name))                  form.fill_fields(*this);
                         if(!(mail=mail_element->get_hash()))  
                                 THROW(0, 0,  
                                         0,  
                                         "$MAIN:MAIL is not hash");  
   
                   // filling cookies
                   cookie.fill_fields(*this);
   
                 // execute @main[]                  // execute @main[]
                 const String *body_string=execute_method(*main_class, *main_method_name);                  const String *body_string=execute_method(*main_class, *main_method_name);
Line 252  void Request::core(const char *root_auto Line 286  void Request::core(const char *root_auto
                 VString body_vstring_before_post_process(*body_string);                  VString body_vstring_before_post_process(*body_string);
                 VString *body_vstring_after_post_process=&body_vstring_before_post_process;                  VString *body_vstring_after_post_process=&body_vstring_before_post_process;
                                   
                 // post-process                  // @postprocess
                 if(Value *value=main_class->get_element(*post_process_method_name))                  if(Value *value=main_class->get_element(*post_process_method_name))
                         if(Junction *junction=value->get_junction())                          if(Junction *junction=value->get_junction())
                                 if(const Method *method=junction->method) {                                  if(const Method *method=junction->method) {
                                         // preparing to pass parameters to                                           // preparing to pass parameters to 
                                         //      @post-process[data]                                          //      @postprocess[data]
                                         VMethodFrame frame(pool(), *junction, false);                                          VMethodFrame frame(pool(), value->name(), *junction, false);
                                         frame.set_self(*main_class);                                          frame.set_self(*main_class);
   
                                         frame.store_param(method->name,                                           frame.store_param(method->name, 
Line 272  void Request::core(const char *root_auto Line 306  void Request::core(const char *root_auto
                 // extract response body                  // extract response body
                 Value *body_value=static_cast<Value *>(                  Value *body_value=static_cast<Value *>(
                         response.fields().get(*body_name));                          response.fields().get(*body_name));
                 if(body_value) // there is some $request.body                  if(body_value) // there is some $response.body
                         body_file=body_value->as_vfile();                          body_file=body_value->as_vfile();
   
                 // OK. write out the result                  // OK. write out the result
Line 283  void Request::core(const char *root_auto Line 317  void Request::core(const char *root_auto
                 TRY {                  TRY {
                         // log the beast                          // log the beast
                         const String *problem_source=e.problem_source();                          const String *problem_source=e.problem_source();
                         if(problem_source)                          if(problem_source && problem_source->size())
                                 SAPI::log(pool(),                                  SAPI::log(pool(),
 #ifndef NO_STRING_ORIGIN  #ifndef NO_STRING_ORIGIN
                                         "%s(%d): "                                          "%s(%d): "
Line 323  void Request::core(const char *root_auto Line 357  void Request::core(const char *root_auto
                                                 if(const Method *method=junction->method) {                                                  if(const Method *method=junction->method) {
                                                         // preparing to pass parameters to                                                           // preparing to pass parameters to 
                                                         //      @exception[origin;source;comment;type;code]                                                          //      @exception[origin;source;comment;type;code]
                                                         VMethodFrame frame(pool(), *junction, false);                                                          VMethodFrame frame(pool(), value->name(), *junction, false);
                                                         frame.set_self(*main_class);                                                          frame.set_self(*main_class);
   
                                                         const String *problem_source=e.problem_source();                                                          const String *problem_source=e.problem_source();
                                                         // origin                                                          // origin
                                                         Value *origin_value=0;                                                          Value *origin_value=0;
 #ifndef NO_STRING_ORIGIN  #ifndef NO_STRING_ORIGIN
                                                         if(problem_source) {                                                          if(problem_source && problem_source->size()) {
                                                                 const Origin& origin=problem_source->origin();                                                                  const Origin& origin=problem_source->origin();
                                                                 if(origin.file) {                                                                  if(origin.file) {
                                                                         char *buf=(char *)malloc(MAX_STRING);                                                                          char *buf=(char *)malloc(MAX_STRING);
Line 347  void Request::core(const char *root_auto Line 381  void Request::core(const char *root_auto
   
                                                         // source                                                          // source
                                                         Value *source_value=0;                                                          Value *source_value=0;
                                                         if(problem_source) {                                                          if(problem_source && problem_source->size()) {
                                                                 String& problem_source_copy=*NEW String(pool());                                                                  String& problem_source_copy=*NEW String(pool());
                                                                 problem_source_copy.append(*problem_source,                                                                   problem_source_copy.append(*problem_source, 
                                                                         flang, true);                                                                          flang, true);
Line 473  VStateless_class *Request::use_buf(const Line 507  VStateless_class *Request::use_buf(const
         return &cclass;          return &cclass;
 }  }
   
 /**  
         - fail_if_junction(true, junction = fail  
         - fail_if_junction(false, not junction = fail  
 */  
 void Request::fail_if_junction_(bool is, Value& value,   
                                                                 const String& method_name, const char *msg) {  
   
         if((value.get_junction()!=0) ^ !is)  
                 THROW(0, 0,  
                         &method_name,  
                         msg);  
 }  
   
 const String& Request::relative(const char *apath, const String& relative_name) {  const String& Request::relative(const char *apath, const String& relative_name) {
         int lpath_buf_size=strlen(apath)+1;          int lpath_buf_size=strlen(apath)+1;
     char *lpath=(char *)malloc(lpath_buf_size);      char *lpath=(char *)malloc(lpath_buf_size);
         memcpy(lpath, apath, lpath_buf_size);          memcpy(lpath, apath, lpath_buf_size);
     rsplit(lpath, '/');      if(!rsplit(lpath, '/'))
                   strcpy(lpath, ".");
         String& result=*NEW String(pool(), lpath);          String& result=*NEW String(pool(), lpath);
     result << "/" << relative_name;      result << "/" << relative_name;
     return result;      return result;
Line 515  static void add_header_attribute(const H Line 537  static void add_header_attribute(const H
         Value& lmeaning=*static_cast<Value *>(ameaning);          Value& lmeaning=*static_cast<Value *>(ameaning);
         Pool& pool=lmeaning.pool();          Pool& pool=lmeaning.pool();
   
         String attribute(pool);  
         SAPI::add_header_attribute(pool,          SAPI::add_header_attribute(pool,
                 attribute.append(aattribute, String::UL_HTTP_HEADER, true).cstr(),                   aattribute.cstr(String::UL_AS_IS), 
                 attributed_meaning_to_string(lmeaning, String::UL_HTTP_HEADER).cstr());                  attributed_meaning_to_string(lmeaning, String::UL_HTTP_HEADER).cstr());
 }  }
 void Request::output_result(const VFile& body_file, bool header_only) {  void Request::output_result(const VFile& body_file, bool header_only) {
Line 579  const String& Request::mime_type_of(cons Line 600  const String& Request::mime_type_of(cons
                                                 "MIME-TYPE table column elements must not be empty");                                                  "MIME-TYPE table column elements must not be empty");
                 }                  }
         return *NEW String(pool(), "application/octet-stream");          return *NEW String(pool(), "application/octet-stream");
 }  
   
   }

Removed from v.1.112  
changed lines
  Added in v.1.133


E-mail: