Diff for /parser3/src/main/pa_request.C between versions 1.63 and 1.84

version 1.63, 2001/03/22 11:19:11 version 1.84, 2001/03/27 16:35:55
Line 8 Line 8
         $Id$          $Id$
 */  */
   
 #include <string.h>  #include "pa_config_includes.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 "_root.h"  #include "_root.h"
 #include "_table.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_vmframe.h"  #include "pa_vmframe.h"
 #include "pa_types.h"  #include "pa_types.h"
   #include "pa_vtable.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
   const char *UNHANDLED_EXCEPTION_CONTENT_TYPE="text/plain";
   
   /// content type of response when no $MAIN:defaults.content-type defined
   const char *DEFAULT_CONTENT_TYPE="text/html";
   
   //
 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),
Line 34  Request::Request(Pool& apool, Line 47  Request::Request(Pool& apool,
         fclasses(apool),          fclasses(apool),
         fdefault_lang(adefault_lang), flang(adefault_lang),          fdefault_lang(adefault_lang), flang(adefault_lang),
         info(ainfo),          info(ainfo),
         fdefault_content_type(0)          default_content_type(0),
           used_files(apool)
 {  {
         // root superclass,           // root superclass, 
         //   parent of all classes,           //   parent of all classes, 
Line 43  Request::Request(Pool& apool, Line 57  Request::Request(Pool& apool,
         classes().put(*root_class_name, &ROOT);          classes().put(*root_class_name, &ROOT);
         // table class          // table class
         classes().put(*table_class_name, table_class);            classes().put(*table_class_name, table_class);  
           // file class
           classes().put(*file_class_name, file_class);    
         // env class          // env class
         classes().put(*env_class_name, &env);          classes().put(*env_class_name, &env);
         // form class          // form class
Line 66  static void add_header_attribute(const H Line 81  static void add_header_attribute(const H
         Pool& pool=lmeaning.pool();          Pool& pool=lmeaning.pool();
   
         String attribute(pool);          String attribute(pool);
         (*service_funcs.add_header_attribute)(pool,          SAPI::add_header_attribute(pool,
                 attribute.append(aattribute, String::UL_HEADER, true).cstr(),                   attribute.append(aattribute, String::UL_HEADER, true).cstr(), 
                 attributed_meaning_to_string(lmeaning).cstr());                  attributed_meaning_to_string(lmeaning).cstr());
 }  }
   
   /**
           load MAIN class, execute @main.
           MAIN class consists of all the auto.p files we'd manage to find
           plus
           the file user requested us to process
           all located classes become children of one another,
           composing class we name 'MAIN'
   */
 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) {
Line 79  void Request::core(const char *root_auto Line 102  void Request::core(const char *root_auto
         TRY {          TRY {
                 char *auto_filespec=(char *)malloc(MAX_STRING);                  char *auto_filespec=(char *)malloc(MAX_STRING);
                                   
                 // load MAIN class,  
                 //      it consists of all the auto.p files we'd manage to find  
                 //      plus  
                 //      the file user requested us to process  
                 //      all located classes become children of one another,  
                 //      composing class we name 'MAIN'  
   
                 // loading root auto.p                   // loading root auto.p 
                 if(root_auto_path) {                  if(root_auto_path) {
                         strncpy(auto_filespec, root_auto_path, MAX_STRING-strlen(AUTO_FILE_NAME));                          String& filespec=*NEW String(pool());
                         strcat(auto_filespec, AUTO_FILE_NAME);                          filespec.APPEND(root_auto_path, 0, "root_auto", 0);
                         main_class=use_file(                          filespec.APPEND_CONST("/" AUTO_FILE_NAME);
                                 auto_filespec, root_auto_fail,  
                                 main_class_name, main_class);  
                 }  
   
                 // loading system auto.p 2  
                 if(site_auto_path) {  
                         strncpy(auto_filespec, site_auto_path, MAX_STRING-strlen(AUTO_FILE_NAME));  
                         strcat(auto_filespec, AUTO_FILE_NAME);  
                         main_class=use_file(                          main_class=use_file(
                                 auto_filespec, site_auto_fail,                                  filespec, root_auto_fail,
                                 main_class_name, main_class);                                  main_class_name, main_class);
                 }                  }
   
                 Value *element;  
                 // $MAIN:limits hash used here,                  // $MAIN:limits hash used here,
                 //      until someone with less privileges have overriden them                  //      until someone with less privileges have overriden them
                 Value *limits=main_class?main_class->get_element(*limits_name):0;                  {
                 // $limits.post_max_size default 10M                          Value *limits=main_class?main_class->get_element(*limits_name):0;
                 element=limits?limits->get_element(*post_max_size_name):0;                          // $limits.post_max_size default 10M
                 int value=element?(size_t)element->get_double():0;                          Value *element=limits?limits->get_element(*post_max_size_name):0;
                 int post_max_size=value?value:10*0x400*400;                          size_t value=element?(size_t)element->as_double():0;
                           size_t post_max_size=value?value:MAX_POST_SIZE_DEFAULT;
                           
                           form.fill_fields(*this, post_max_size);
                   }
   
                 form.fill_fields(*this, post_max_size);                  // filling cookies
                 cookie.fill_fields(*this);                  cookie.fill_fields(*this);
   
                 // TODO: load site auto.p files, all assigned bases from upper dir                  // loading site auto.p
                 /*char *site_auto_file="Y:\\parser3\\src\\auto.p";                  if(site_auto_path) {
                 main_class=use_file(                          String& filespec=*NEW String(pool());
                         site_auto_file, false/*ignore possible read problem* /,                          filespec.APPEND(site_auto_path, 0, "site_auto", 0);
                         main_class_name, main_class);*/                          filespec.APPEND_CONST("/" AUTO_FILE_NAME);
                           main_class=use_file(
                 // $MAIN:defaults                                  filespec, site_auto_fail,
                 Value *defaults=main_class?main_class->get_element(*defaults_name):0;                                  main_class_name, main_class);
                 fdefault_content_type=defaults?defaults->get_element(*content_type_name):0;                  }
   
                 // there must be some auto.p                  // loading auto.p files from document_root/.. 
                 if(/*\*/0&&!main_class)                  // to the one beside requested file.
                         THROW(0,0,                  // all assigned bases from upper dir
                                 0,                  {
                                 "no 'auto.p' found (nither system nor any site's)");                          /* /document/root */
                           char *file_spec=
                                   (char *)malloc(strlen(info.path_translated)+strlen(AUTO_FILE_NAME)+1);
                           size_t document_root_size=strlen(info.document_root);
                           if(info.document_root[document_root_size-1]=='/')
                                   document_root_size--;
                           memcpy(file_spec, info.document_root, document_root_size);
   
                           /* /requested/file.html */
                           char *branches=(char *)malloc(strlen(info.path_translated)+1);
                           strcpy(branches, info.path_translated+document_root_size);
                           char *next=branches;
                           char *append_here=file_spec+document_root_size;
   
                           size_t slash_auto_p_size=strlen("/" AUTO_FILE_NAME);
                           while(true) {
                                   char *step=lsplit(&next, '/');
                                   if(next) { // not 'file.html' part
                                           size_t step_size=strlen(step);
                                           memcpy(append_here, step, step_size);
                                           append_here+=step_size;
                                           memcpy(append_here, "/" AUTO_FILE_NAME, slash_auto_p_size+1);
                                           append_here++/* / */;
   
                                           String& sfile_spec=*NEW String(pool());
                                           sfile_spec.APPEND(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                  // compiling requested file
                 main_class=use_file(info.path_translated, true/*don't ignore read problem*/,                  String& spath_translated=*NEW String(pool());
                   spath_translated.APPEND(info.path_translated, 0, "user-request", 0);
                   main_class=use_file(spath_translated, true/*don't ignore read problem*/,
                         main_class_name, main_class);                          main_class_name, main_class);
   
                   // $MAIN:defaults
                   Value *defaults=main_class->get_element(*defaults_name);
                   // value must be allocated on request's pool for that pool used on
                   // meaning constructing @see attributed_meaning_to_string
                   default_content_type=defaults?defaults->get_element(*content_type_name):0;
                   if(Value *element=main_class->get_element(*html_typo_name))
                           if(Table *table=element->get_table())
                                   pool().set_tag(table);
   
                 // 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);
                 if(!body_string)                  if(!body_string)
Line 143  void Request::core(const char *root_auto Line 196  void Request::core(const char *root_auto
                         0,                           0, 
                         "'"MAIN_METHOD_NAME"' method not found");                          "'"MAIN_METHOD_NAME"' method not found");
   
                   // post-process
                   // todo
   
                 // 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));
Line 152  void Request::core(const char *root_auto Line 208  void Request::core(const char *root_auto
                 // OK. write out the result                  // OK. write out the result
                 output_result(*body_string, header_only);                  output_result(*body_string, header_only);
         }           } 
         CATCH(e) {          CATCH(e) { // request handling problem
                   // we're returning not result, but error explanation
                 TRY {                  TRY {
                         // we're returning not result, but error explanation                          // log the beast
                           const String *problem_source=e.problem_source();
                           if(problem_source)
                                   SAPI::log(pool(),
   #ifndef NO_STRING_ORIGIN
                                           "%s(%d): "
   #endif
                                           "'%s' %s [%s %s]",
   #ifndef NO_STRING_ORIGIN
                                           problem_source->origin().file?problem_source->origin().file:"global",
                                           problem_source->origin().line,
   #endif
                                           problem_source->cstr(),
                                           e.comment(),
                                           e.type()?e.type()->cstr():"-",
                                           e.code()?e.code()->cstr():"-"
                                   );
                           else
                                   SAPI::log(pool(),
                                           "%s [%s %s]",
                                           e.comment(),
                                           e.type()?e.type()->cstr():"-",
                                           e.code()?e.code()->cstr():"-"
                                           );
   
                         // reset language to default                          // reset language to default
                         flang=fdefault_lang;                          flang=fdefault_lang;
Line 274  void Request::core(const char *root_auto Line 354  void Request::core(const char *root_auto
   
                                 // future $response:content-type                                  // future $response:content-type
                                 response.fields().put(*content_type_name,                                   response.fields().put(*content_type_name, 
                                         NEW VString(*NEW String(pool(), "text/plain")));                                          NEW VString(*NEW String(pool(), UNHANDLED_EXCEPTION_CONTENT_TYPE)));
                                 // future $response:body                                  // future $response:body
                                 body_string=NEW String(pool(), buf);                                  body_string=NEW String(pool(), buf);
                         }                          }
Line 299  void Request::core(const char *root_auto Line 379  void Request::core(const char *root_auto
   
 }  }
   
 /// @todo find|solve cyclic dependences  VStateless_class *Request::use_file(const String& file_spec, bool fail_on_read_problem,
 VStateless_class *Request::use_file(  
                                                                         const char *file, bool fail_on_read_problem,  
                                                                         const String *name,                                                                           const String *name, 
                                                                         VStateless_class *base_class) {                                                                          VStateless_class *base_class) {
         char *source=file_read_text(pool(), file, fail_on_read_problem);          // cyclic dependence check
           if(used_files.get(file_spec))
                   return base_class;
           used_files.put(file_spec, (Hash::Val *)true);
   
   
           char *source=file_read_text(pool(), file_spec, fail_on_read_problem);
         if(!source)          if(!source)
                 return base_class;                  return base_class;
   
         return use_buf(source, file, 0/*new class*/, name, base_class);          return use_buf(source, file_spec.cstr(), 0/*new class*/, name, base_class);
 }  }
   
 VStateless_class *Request::use_buf(  VStateless_class *Request::use_buf(const char *source, const char *file,
                                                                    const char *source, const char *file,  
                                                                    VStateless_class *aclass, const String *name,                                                                      VStateless_class *aclass, const String *name, 
                                                                    VStateless_class *base_class) {                                                                     VStateless_class *base_class) {
         // compile loaded class          // compile loaded class
Line 336  void Request::fail_if_junction_(bool is, Line 419  void Request::fail_if_junction_(bool is,
                         msg);                          msg);
 }  }
   
 char *Request::relative(const char *path, const char *file) {  const String& Request::relative(const char *apath, const String& relative_name) {
     char *result=(char *)malloc(strlen(path)+strlen(file)+1);          int lpath_buf_size=strlen(apath)+1;
         strcpy(result, path);      char *lpath=(char *)malloc(lpath_buf_size);
     rsplit(result, '/');          memcpy(lpath, apath, lpath_buf_size);
     strcat(result, "/");      rsplit(lpath, '/');
     strcat(result, file);          String& result=*NEW String(pool(), lpath);
       result.APPEND_CONST("/");
           result.append(relative_name, String::UL_PASS_APPENDED);
     return result;      return result;
 }  }
   
 char *Request::absolute(const char *name) {  const String& Request::absolute(const String& relative_name) {
         if(name[0]=='/') {          char *relative_name_cstr=relative_name.cstr();
                 char *result=(char *)malloc(strlen(info.document_root)+strlen(name)+1);          if(relative_name_cstr[0]=='/') {
                 strcpy(result, info.document_root);                  String& result=*NEW String(pool(), info.document_root);
                 strcat(result, name);                  result.append(relative_name, String::UL_PASS_APPENDED);
                 return result;                  return result;
         } else           } else 
                 return relative(info.path_translated, name);                  return relative(info.path_translated, relative_name);
 }  }
   
 void Request::output_result(const String& body_string, bool header_only) {  void Request::output_result(const String& body_string, bool header_only) {
Line 360  void Request::output_result(const String Line 445  void Request::output_result(const String
         cookie.output_result();          cookie.output_result();
                   
         // set default content-type          // set default content-type
         if(fdefault_content_type)          response.fields().put_dont_replace(*content_type_name, 
                 response.fields().put_dont_replace(*content_type_name, fdefault_content_type);                  default_content_type?default_content_type
                   :NEW VString(*NEW String(pool(), DEFAULT_CONTENT_TYPE)));
   
         // prepare header: $response:fields without :body          // prepare header: $response:fields without :body
         response.fields().foreach(add_header_attribute, /*excluding*/ body_name);          response.fields().for_each(add_header_attribute, /*excluding*/ body_name);
   
         // prepare...          // prepare...
         const char *body=body_string.cstr();          const char *body=body_string.cstr();
         size_t content_length=strlen(body);          size_t content_length=strlen(body);
   
         // prepare header: content-length          // prepare header: content-length
         char content_length_cstr[MAX_NUMBER];          if(content_length) { // useful for redirecting [header "location: http://..."]
         snprintf(content_length_cstr, MAX_NUMBER, "%d", content_length);                  char content_length_cstr[MAX_NUMBER];
         (*service_funcs.add_header_attribute)(pool(), "content-length", content_length_cstr);                  snprintf(content_length_cstr, MAX_NUMBER, "%lu", content_length);
                   SAPI::add_header_attribute(pool(), "content-length", content_length_cstr);
           }
   
         // send header          // send header
         (*service_funcs.send_header)(pool());          SAPI::send_header(pool());
           
         // send body          // send body
         if(!header_only)          if(!header_only)
                 (*service_funcs.send_body)(pool(), body, content_length);                  SAPI::send_body(pool(), body, content_length);
 }  }

Removed from v.1.63  
changed lines
  Added in v.1.84


E-mail: