|
|
| version 1.232, 2002/10/14 12:16:06 | version 1.236.4.1, 2002/10/31 12:22:13 |
|---|---|
| Line 32 const char *UNHANDLED_EXCEPTION_CONTENT_ | Line 32 const char *UNHANDLED_EXCEPTION_CONTENT_ |
| const char *DEFAULT_CONTENT_TYPE="text/html"; | const char *DEFAULT_CONTENT_TYPE="text/html"; |
| const char *ORIGINS_CONTENT_TYPE="text/plain"; | const char *ORIGINS_CONTENT_TYPE="text/plain"; |
| Methoded *MOP_create(Pool&); | // op.C |
| VClass& VClassMAIN_create(Pool& pool); | |
| // op.C | // op.C |
| VHash& exception2vhash(Pool& pool, const Exception& e); | VHash& exception2vhash(Pool& pool, const Exception& e); |
| Line 43 Request::Request(Pool& apool, | Line 44 Request::Request(Pool& apool, |
| bool status_allowed) : Pooled(apool), | bool status_allowed) : Pooled(apool), |
| main_method_name(apool, MAIN_METHOD_NAME), | main_method_name(apool, MAIN_METHOD_NAME), |
| stack(apool), | stack(apool), |
| OP(*MOP_create(apool)), | main_class(VClassMAIN_create(apool)), |
| env(apool), | env(apool), |
| status(apool), | status(apool), |
| form(apool), | form(apool), |
| Line 60 Request::Request(Pool& apool, | Line 61 Request::Request(Pool& apool, |
| configure_admin_done(false), | configure_admin_done(false), |
| default_content_type(0), | default_content_type(0), |
| mime_types(0), | mime_types(0), |
| main_class(0), | |
| fconnection(0), | fconnection(0), |
| classes_conf(apool), | classes_conf(apool), |
| anti_endless_execute_recoursion(0), | anti_endless_execute_recoursion(0), |
| Line 68 Request::Request(Pool& apool, | Line 68 Request::Request(Pool& apool, |
| #ifdef RESOURCES_DEBUG | #ifdef RESOURCES_DEBUG |
| , sql_connect_time(0),sql_request_time(0) | , sql_connect_time(0),sql_request_time(0) |
| #endif | #endif |
| , self(0), method_frame(0), rcontext(0), wcontext(0) | , method_frame(0), rcontext(0), wcontext(0) |
| { | { |
| // default charsets | // default charsets |
| pool().set_source_charset(*utf8_charset); | pool().set_source_charset(*utf8_charset); |
| Line 78 Request::Request(Pool& apool, | Line 78 Request::Request(Pool& apool, |
| cache_managers->maybe_expire(); | cache_managers->maybe_expire(); |
| /// directly used | /// directly used |
| // operators | // MAIN class, operators |
| OP.register_directly_used(*this); | classes().put(main_class.name(), &main_class); |
| // classes: | // classes: |
| // table, file, random, mail, image, ... | // table, file, random, mail, image, ... |
| methoded_array->register_directly_used(*this); | methoded_array->register_directly_used(*this); |
| Line 118 Request::~Request() { | Line 118 Request::~Request() { |
| #endif | #endif |
| } | } |
| Value *Request::get_self() { return method_frame?&method_frame->self():0; } | |
| static void load_charset(const Hash::Key& akey, Hash::Val *avalue, void *) { | static void load_charset(const Hash::Key& akey, Hash::Val *avalue, void *) { |
| charsets->load_charset(akey, static_cast<Value *>(avalue)->as_string()); | charsets->load_charset(akey, static_cast<Value *>(avalue)->as_string()); |
| } | } |
| Line 136 void Request::configure_admin(VStateless | Line 138 void Request::configure_admin(VStateless |
| ... | ... |
| ] | ] |
| */ | */ |
| if(Value *vcharsets=conf_class.get_element(*charsets_name, &conf_class, false)) { | if(Value *vcharsets=conf_class.get_element(*charsets_name, conf_class, false)) { |
| if(Hash *charsets=vcharsets->get_hash(0)) | if(Hash *charsets=vcharsets->get_hash(0)) |
| charsets->for_each(load_charset); | charsets->for_each(load_charset); |
| else if(!vcharsets->get_string()) | else if(!vcharsets->get_string()) |
| Line 147 void Request::configure_admin(VStateless | Line 149 void Request::configure_admin(VStateless |
| // configure method_frame options | // configure method_frame options |
| // until someone with less privileges have overriden them | // until someone with less privileges have overriden them |
| OP.configure_admin(*this); | |
| methoded_array->configure_admin(*this); | methoded_array->configure_admin(*this); |
| } | } |
| Line 179 gettimeofday(&mt[0],NULL); | Line 180 gettimeofday(&mt[0],NULL); |
| if(config_filespec) { | if(config_filespec) { |
| String& filespec=*NEW String(pool()); | String& filespec=*NEW String(pool()); |
| filespec.APPEND_CLEAN(config_filespec, 0, "config", 0); | filespec.APPEND_CLEAN(config_filespec, 0, "config", 0); |
| main_class=use_file( | use_file(main_class, |
| filespec, | filespec, true/* ignore class_path */, |
| true/* ignore class_path */, | config_fail_on_read_problem, true/* file must exist if 'fail on read problem' not set */); |
| config_fail_on_read_problem, true/* file must exist if 'fail on read problem' not set */, | |
| main_class_name, main_class); | |
| } | } |
| // loading auto.p files from document_root/.. | // loading auto.p files from document_root/.. |
| Line 207 gettimeofday(&mt[0],NULL); | Line 206 gettimeofday(&mt[0],NULL); |
| "path-translated-scanned", step++); | "path-translated-scanned", step++); |
| sfile_spec << "/" AUTO_FILE_NAME; | sfile_spec << "/" AUTO_FILE_NAME; |
| main_class=use_file(sfile_spec, | use_file(main_class, |
| true/* ignore class_path */, | sfile_spec, true/* ignore class_path */, |
| true/* fail on read problem */, false/* but ignore absence, sole user */, | true/* fail on read problem */, false/* but ignore absence, sole user */); |
| main_class_name, main_class); | |
| } | } |
| after=before+1; | after=before+1; |
| } | } |
| Line 219 gettimeofday(&mt[0],NULL); | Line 217 gettimeofday(&mt[0],NULL); |
| // compile requested file | // compile requested file |
| String& spath_translated=*NEW String(pool()); | String& spath_translated=*NEW String(pool()); |
| spath_translated.APPEND_TAINTED(info.path_translated, 0, "user-request", 0); | spath_translated.APPEND_TAINTED(info.path_translated, 0, "user-request", 0); |
| main_class=use_file(spath_translated, | use_file(main_class, |
| true/* ignore class_path */, | spath_translated, true/* ignore class_path */, |
| true/* fail on read problem*/, true/* fail on abscence */, | true/* fail on read problem*/, true/* fail on abscence */); |
| main_class_name, main_class); | |
| // configure method_frame options if not configured yet | // configure method_frame options if not configured yet |
| if(!configure_admin_done) | if(!configure_admin_done) |
| configure_admin(*main_class, 0); | configure_admin(main_class, 0); |
| // configure not-method_frame=user options | // configure not-method_frame=user options |
| OP.configure_user(*this); | |
| methoded_array->configure_user(*this); | methoded_array->configure_user(*this); |
| // $MAIN:MIME-TYPES | // $MAIN:MIME-TYPES |
| if(Value *element=main_class->get_element(*mime_types_name, main_class, false)) | if(Value *element=main_class.get_element(*mime_types_name, main_class, false)) |
| if(Table *table=element->get_table()) | if(Table *table=element->get_table()) |
| mime_types=table; | mime_types=table; |
| Line 251 gettimeofday(&mt[0],NULL); | Line 247 gettimeofday(&mt[0],NULL); |
| gettimeofday(&mt[1],NULL); | gettimeofday(&mt[1],NULL); |
| #endif | #endif |
| // execute @main[] | // execute @main[] |
| const String *body_string=execute_virtual_method(*main_class, main_method_name); | const String *body_string=execute_virtual_method(main_class, main_method_name); |
| if(!body_string) | if(!body_string) |
| throw Exception("parser.runtime", | throw Exception("parser.runtime", |
| 0, | 0, |
| Line 265 gettimeofday(&mt[2],NULL); | Line 261 gettimeofday(&mt[2],NULL); |
| 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; |
| // @postprocess | // @postprocess |
| if(Value *value=main_class->get_element( | if(Value *value=main_class.get_element( |
| *NEW String(pool(), POST_PROCESS_METHOD_NAME), | *NEW String(pool(), POST_PROCESS_METHOD_NAME), |
| main_class, | main_class, |
| false)) | false)) |
| Line 273 gettimeofday(&mt[2],NULL); | Line 269 gettimeofday(&mt[2],NULL); |
| if(const Method *method=junction->method) { | if(const Method *method=junction->method) { |
| // preparing to pass parameters to | // preparing to pass parameters to |
| // @postprocess[data] | // @postprocess[data] |
| VMethodFrame frame(pool(), method->name, *junction); | VMethodFrame frame(pool(), method->name, *junction, 0/*no parent*/); |
| frame.set_self(*main_class); | frame.set_self(main_class); |
| frame.store_param(&body_vstring_before_post_process); | frame.store_param(&body_vstring_before_post_process); |
| body_vstring_after_post_process= | body_vstring_after_post_process= |
| Line 358 t[9]-t[3] | Line 354 t[9]-t[3] |
| // this is what we'd return in $response:body | // this is what we'd return in $response:body |
| const String *body_string=0; | const String *body_string=0; |
| if(main_class) { // we've managed to end up with some main_class | // maybe we'd be lucky enough as to report an error |
| // maybe we'd be lucky enough as to report an error | // in a gracefull way... |
| // in a gracefull way... | if(Value *value=main_class.get_element( |
| if(Value *value=main_class->get_element( | *NEW String(pool(), UNHANDLED_EXCEPTION_METHOD_NAME), |
| *NEW String(pool(), UNHANDLED_EXCEPTION_METHOD_NAME), | main_class, |
| main_class, | false)) { |
| false)) | 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 | // @unhandled_exception[exception;stack] |
| // @unhandled_exception[exception;stack] | VMethodFrame frame(pool(), method->name, *junction, 0/*no caller*/); |
| VMethodFrame frame(pool(), method->name, *junction); | frame.set_self(main_class); |
| frame.set_self(*main_class); | |
| // $exception | |
| // $exception | frame.store_param(&exception2vhash(pool(), e)); |
| frame.store_param(&exception2vhash(pool(), e)); | // $stack[^table::set{name origin}] |
| // $stack[^table::set{name origin}] | Array& stack_trace_columns=*NEW Array(pool()); |
| Array& stack_trace_columns=*NEW Array(pool()); | stack_trace_columns+=NEW String(pool(), "name"); |
| stack_trace_columns+=NEW String(pool(), "name"); | stack_trace_columns+=NEW String(pool(), "file"); |
| stack_trace_columns+=NEW String(pool(), "file"); | stack_trace_columns+=NEW String(pool(), "lineno"); |
| stack_trace_columns+=NEW String(pool(), "lineno"); | Table& stack_trace=*NEW Table(pool(), 0, &stack_trace_columns); |
| Table& stack_trace=*NEW Table(pool(), 0, &stack_trace_columns); | Array_iter tracei(exception_trace); |
| Array_iter tracei(exception_trace); | while(tracei.has_next()) { |
| while(tracei.has_next()) { | Array& row=*NEW Array(pool()); |
| Array& row=*NEW Array(pool()); | |
| const String *name=(const String *)tracei.next(); | const String *name=(const String *)tracei.next(); |
| row+=name; // name column | row+=name; // name column |
| #ifndef NO_STRING_ORIGIN | #ifndef NO_STRING_ORIGIN |
| const Origin& origin=name->origin(); | const Origin& origin=name->origin(); |
| if(origin.file) { | if(origin.file) { |
| row+=NEW String(pool(), origin.file, 0, true); // file column | row+=NEW String(pool(), origin.file, 0, true); // file column |
| char *buf=(char *)malloc(MAX_NUMBER); | char *buf=(char *)malloc(MAX_NUMBER); |
| size_t buf_size=snprintf(buf, MAX_NUMBER, "%d", 1+origin.line); | size_t buf_size=snprintf(buf, MAX_NUMBER, "%d", 1+origin.line); |
| row+=NEW String(pool(), buf, buf_size, true); // line column | row+=NEW String(pool(), buf, buf_size, true); // line column |
| } | |
| #endif | |
| stack_trace+=&row; | |
| } | } |
| frame.store_param(NEW VTable(pool(), &stack_trace)); | #endif |
| stack_trace+=&row; | |
| // future $response:body= | |
| // execute ^unhandled_exception[exception;stack] | |
| body_string=&execute_method(frame, *method); | |
| } | } |
| frame.store_param(NEW VTable(pool(), &stack_trace)); | |
| // future $response:body= | |
| // execute ^unhandled_exception[exception;stack] | |
| body_string=&execute_method(frame, *method); | |
| } | |
| } | |
| } | } |
| if(!body_string) { // couldn't report an error beautifully? | if(!body_string) { // couldn't report an error beautifully? |
| Line 446 t[9]-t[3] | Line 442 t[9]-t[3] |
| } | } |
| } | } |
| VStateless_class *Request::use_file(const String& file_name, | VStateless_class *Request::use_file(VStateless_class& aclass, |
| bool ignore_class_path, | const String& file_name, bool ignore_class_path, |
| bool fail_on_read_problem, bool fail_on_file_absence, | bool fail_on_read_problem, bool fail_on_file_absence) { |
| const String *name, | |
| VStateless_class *base_class) { | |
| // cyclic dependence check | // cyclic dependence check |
| if(used_files.get(file_name)) | if(used_files.get(file_name)) |
| return base_class; | return 0; |
| used_files.put(file_name, (Hash::Val *)true); | used_files.put(file_name, (Hash::Val *)true); |
| const String *file_spec; | const String *file_spec; |
| Line 463 VStateless_class *Request::use_file(cons | Line 457 VStateless_class *Request::use_file(cons |
| file_spec=&absolute(file_name); | file_spec=&absolute(file_name); |
| else { | else { |
| file_spec=0; | file_spec=0; |
| if(main_class) | if(Value *element=main_class.get_element(*class_path_name, main_class, false)) { |
| if(Value *element=main_class->get_element(*class_path_name, main_class, false)) { | if(element->is_string()) { |
| if(element->is_string()) { | file_spec=file_readable(absolute(element->as_string()), file_name); // found at class_path? |
| file_spec=file_readable(absolute(element->as_string()), file_name); // found at class_path? | } else if(Table *table=element->get_table()) { |
| } else if(Table *table=element->get_table()) { | int size=table->size(); |
| int size=table->size(); | for(int i=size; i--; ) { |
| for(int i=size; i--; ) { | const String& path=*static_cast<Array *>(table->get(i))->get_string(0); |
| const String& path=*static_cast<Array *>(table->get(i))->get_string(0); | if(file_spec=file_readable(absolute(path), file_name)) |
| if(file_spec=file_readable(absolute(path), file_name)) | break; // found along class_path |
| break; // found along class_path | } |
| } | } else |
| } else | throw Exception("parser.runtime", |
| throw Exception("parser.runtime", | 0, |
| 0, | "$" CLASS_PATH_NAME " must be string or table"); |
| "$" CLASS_PATH_NAME " must be string or table"); | if(!file_spec) |
| if(!file_spec) | throw Exception("parser.runtime", |
| throw Exception("parser.runtime", | &file_name, |
| &file_name, | "not found along " MAIN_CLASS_NAME ":" CLASS_PATH_NAME); |
| "not found along " MAIN_CLASS_NAME ":" CLASS_PATH_NAME); | } |
| } | |
| if(!file_spec) | if(!file_spec) |
| throw Exception("parser.runtime", | throw Exception("parser.runtime", |
| &file_name, | &file_name, |
| Line 491 VStateless_class *Request::use_file(cons | Line 484 VStateless_class *Request::use_file(cons |
| if(fail_on_read_problem && !fail_on_file_absence) // ignore file absence if asked for | if(fail_on_read_problem && !fail_on_file_absence) // ignore file absence if asked for |
| if(!entry_exists(*file_spec)) | if(!entry_exists(*file_spec)) |
| return base_class; | return 0; |
| char *source=file_read_text(pool(), *file_spec, fail_on_read_problem); | char *source=file_read_text(pool(), *file_spec, fail_on_read_problem); |
| if(!source) | if(!source) |
| return base_class; | return 0; |
| return use_buf(source, *file_spec, file_spec->cstr(), 0/*new class*/, name, base_class); | return use_buf(aclass, source, *file_spec, file_spec->cstr()); |
| } | } |
| VStateless_class *Request::use_buf(const char *source, | VStateless_class *Request::use_buf(VStateless_class& aclass, |
| const String& filespec, const char *filespec_cstr, | const char *source, |
| VStateless_class *aclass, const String *name, | const String& filespec, const char *filespec_cstr) { |
| VStateless_class *base_class) { | // temporary zero @conf so to maybe-replace it in compiled code |
| // compile loaded class | Temp_method temp_method_conf(aclass, *conf_method_name, 0); |
| VStateless_class& cclass=COMPILE(source, aclass, name, base_class, filespec_cstr); | // temporary zero @auto so to maybe-replace it in compiled code |
| Temp_method temp_method_auto(aclass, *auto_method_name, 0); | |
| VString *vfilespec=NEW VString(filespec); | // compile loaded class |
| VStateless_class& cclass=COMPILE(aclass, source, filespec_cstr); | |
| // locate and execute possible @conf[] static | // locate and execute possible @conf[] static |
| VString *vfilespec=NEW VString(filespec); | |
| const Method *method_called; | const Method *method_called; |
| execute_nonvirtual_method(cclass, | execute_nonvirtual_method(cclass, |
| cclass.get_method(*conf_method_name), vfilespec, | *conf_method_name, vfilespec, |
| 0/*no result needed*/, &method_called); | 0/*no result needed*/, &method_called); |
| if(method_called) { | if(method_called) |
| if(!main_class) | |
| main_class=&cclass; // for method_frame auto.p, when main_class not assigned yet | |
| configure_admin(cclass, &method_called->name); | configure_admin(cclass, &method_called->name); |
| } | |
| // locate and execute possible @auto[] static | // locate and execute possible @auto[] static |
| execute_nonvirtual_method( | execute_nonvirtual_method(cclass, |
| &cclass==&OP?*main_class:cclass, // execute operators@auto in MAIN context | *auto_method_name, vfilespec, |
| cclass.get_method(*auto_method_name), vfilespec, | |
| 0/*no result needed*/); | 0/*no result needed*/); |
| return &cclass; | return &cclass; |
| } | } |
| Line 634 const String& Request::mime_type_of(cons | Line 626 const String& Request::mime_type_of(cons |
| } | } |
| return *NEW String(pool(), "application/octet-stream"); | return *NEW String(pool(), "application/octet-stream"); |
| } | } |
| bool Request::origins_mode() { | |
| return main_class.get_element(*origins_mode_name, main_class, false)!=0; // $ORIGINS mode | |
| } |