|
|
| version 1.346, 2015/09/22 23:38:59 | version 1.352, 2016/04/01 16:27:32 |
|---|---|
| Line 1 | Line 1 |
| /** @file | /** @file |
| Parser: request class main part. @see compile.C and execute.C. | Parser: request class main part. @see compile.C and execute.C. |
| 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 43 const char* UNHANDLED_EXCEPTION_CONTENT_ | Line 43 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"; |
| const char* ORIGINS_CONTENT_TYPE="text/plain"; | |
| // defines for globals | // defines for globals |
| Line 70 const String exception_handled_part_name | Line 69 const String exception_handled_part_name |
| #define CHARSETS_NAME "CHARSETS" | #define CHARSETS_NAME "CHARSETS" |
| #define MIME_TYPES_NAME "MIME-TYPES" | #define MIME_TYPES_NAME "MIME-TYPES" |
| #define STRICT_VARS_NAME "STRICT-VARS" | #define STRICT_VARS_NAME "STRICT-VARS" |
| #define ORIGINS_MODE_NAME "ORIGINS" | |
| #define CONF_METHOD_NAME "conf" | #define CONF_METHOD_NAME "conf" |
| #define POST_PROCESS_METHOD_NAME "postprocess" | #define POST_PROCESS_METHOD_NAME "postprocess" |
| #define CLASS_PATH_NAME "CLASS_PATH" | #define CLASS_PATH_NAME "CLASS_PATH" |
| Line 85 static const String charsets_name(CHARSE | Line 83 static const String charsets_name(CHARSE |
| static const String main_class_name(MAIN_CLASS_NAME); | static const String main_class_name(MAIN_CLASS_NAME); |
| static const String mime_types_name(MIME_TYPES_NAME); | static const String mime_types_name(MIME_TYPES_NAME); |
| static const String strict_vars_name(STRICT_VARS_NAME); | static const String strict_vars_name(STRICT_VARS_NAME); |
| static const String origins_mode_name(ORIGINS_MODE_NAME); | |
| static const String conf_method_name(CONF_METHOD_NAME); | static const String conf_method_name(CONF_METHOD_NAME); |
| static const String post_process_method_name(POST_PROCESS_METHOD_NAME); | static const String post_process_method_name(POST_PROCESS_METHOD_NAME); |
| static const String class_path_name(CLASS_PATH_NAME); | static const String class_path_name(CLASS_PATH_NAME); |
| Line 149 Request::Request(SAPI_Info& asapi_info, | Line 146 Request::Request(SAPI_Info& asapi_info, |
| pa_register_thread_request(*this); | pa_register_thread_request(*this); |
| // file_no=0 => unknown | // file_no=0 => unknown |
| file_list+=String::Body("UNKNOWN"); | file_list+="UNKNOWN"; |
| file_list+=String::Body("-body of process-"); // pseudo_file_no__process | file_list+="-body of process-"; // pseudo_file_no__process |
| // maybe expire old caches | // maybe expire old caches |
| cache_managers->maybe_expire(); | cache_managers->maybe_expire(); |
| /// directly used | /// directly used |
| // MAIN class, operators | // MAIN class, operators |
| classes().put(main_class.name(), &main_class); | classes().put(main_class.type(), &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); |
| /// methodless | /// methodless |
| // env class | // env class |
| classes().put(String::Body(ENV_CLASS_NAME), new VEnv(asapi_info)); | classes().put(ENV_CLASS_NAME, new VEnv(asapi_info)); |
| // status class | // status class |
| classes().put(String::Body(STATUS_CLASS_NAME), new VStatus()); | classes().put(STATUS_CLASS_NAME, new VStatus()); |
| // request class | // request class |
| classes().put(String::Body(REQUEST_CLASS_NAME), new VRequest(arequest_info, charsets, form, asapi_info)); | classes().put(REQUEST_CLASS_NAME, new VRequest(arequest_info, charsets, form, asapi_info)); |
| // cookie class | // cookie class |
| classes().put(String::Body(COOKIE_CLASS_NAME), &cookie); | classes().put(COOKIE_CLASS_NAME, &cookie); |
| // console class | // console class |
| classes().put(String::Body(CONSOLE_CLASS_NAME), &console); | classes().put(CONSOLE_CLASS_NAME, &console); |
| /// methoded | /// methoded |
| // response class | // response class |
| classes().put(response.get_class()->name(), &response); | classes().put(response.get_class()->type(), &response); |
| /// bases used | /// bases used |
| // form class | // form class |
| classes().put(form.get_class()->base_class()->name(), &form); | classes().put(form.get_class()->base_class()->type(), &form); |
| // mail class | // mail class |
| classes().put(mail.get_class()->base_class()->name(), &mail); | classes().put(mail.get_class()->base_class()->type(), &mail); |
| // math class | // math class |
| { | { |
| Value& math=*new VMath; | Value& math=*new VMath; |
| classes().put(math.get_class()->base_class()->name(), &math); | classes().put(math.get_class()->base_class()->type(), &math); |
| } | } |
| // memory class | // memory class |
| { | { |
| Value& memory=*new VMemory; | Value& memory=*new VMemory; |
| classes().put(memory.get_class()->base_class()->name(), &memory); | classes().put(memory.get_class()->base_class()->type(), &memory); |
| } | } |
| } | } |
| Line 274 void Request::configure_admin(VStateless | Line 271 void Request::configure_admin(VStateless |
| methoded_array().configure_admin(*this); | methoded_array().configure_admin(*this); |
| } | } |
| const char* Request::get_exception_cstr( | const char* Request::get_exception_cstr(const Exception& e, Request::Exception_details& details) { |
| const Exception& e, | |
| Request::Exception_details& details) { | |
| #define PA_URI_FORMAT "%s: " | #define PA_URI_FORMAT "%s: " |
| #define PA_COMMENT_TYPE_FORMAT "%s [%s]" | |
| #define PA_ORIGIN_FILE_POS_FORMAT "%s(%d:%d): " | #define PA_ORIGIN_FILE_POS_FORMAT "%s(%d:%d): " |
| #define PA_SOURCE_FORMAT "'%s' " | #define PA_SOURCE_FORMAT "'%s' " |
| #define PA_COMMENT_TYPE_FORMAT "%s [%s]" | |
| #define PA_ORIGIN_FILE_POS_VALUE file_list[details.origin.file_no].cstr(), 1+details.origin.line, 1+details.origin.col, | |
| #define PA_SOURCE_VALUE details.problem_source->cstr(), | |
| #define EXCEPTION_CSTR(f1,v1,f2,v2) \ | |
| snprintf(result, MAX_STRING, \ | |
| PA_URI_FORMAT \ | |
| f1 f2 \ | |
| PA_COMMENT_TYPE_FORMAT, \ | |
| request_info.uri, \ | |
| v1 v2 \ | |
| e.comment(), e.type() \ | |
| ); | |
| char* result=new(PointerFreeGC) char[MAX_STRING]; | char* result=new(PointerFreeGC) char[MAX_STRING]; |
| if(details.problem_source) { // do we know the guy? | if(details.problem_source) { // do we know the guy? |
| if(details.trace) { // do whe know where he came from? | if(details.origin.file_no) // do whe know where he came from? |
| Operation::Origin origin=details.trace.origin(); | EXCEPTION_CSTR(PA_ORIGIN_FILE_POS_FORMAT, PA_ORIGIN_FILE_POS_VALUE, PA_SOURCE_FORMAT, PA_SOURCE_VALUE) |
| snprintf(result, MAX_STRING, | else |
| PA_URI_FORMAT | EXCEPTION_CSTR(PA_SOURCE_FORMAT, PA_SOURCE_VALUE,,) |
| PA_ORIGIN_FILE_POS_FORMAT | } else { |
| PA_SOURCE_FORMAT PA_COMMENT_TYPE_FORMAT, | if(details.origin.file_no) // do whe know where he came from? |
| request_info.uri, | EXCEPTION_CSTR(PA_ORIGIN_FILE_POS_FORMAT, PA_ORIGIN_FILE_POS_VALUE,,) |
| file_list[origin.file_no].cstr(), 1+origin.line, 1+origin.col, | else |
| details.problem_source->cstr(), | EXCEPTION_CSTR(,,,) |
| e.comment(), e.type() | } |
| ); | |
| } else | |
| snprintf(result, MAX_STRING, | |
| PA_URI_FORMAT | |
| PA_SOURCE_FORMAT PA_COMMENT_TYPE_FORMAT, | |
| request_info.uri, | |
| details.problem_source->cstr(), | |
| e.comment(), e.type() | |
| ); | |
| } else | |
| snprintf(result, MAX_STRING, | |
| PA_URI_FORMAT | |
| PA_COMMENT_TYPE_FORMAT, | |
| request_info.uri, | |
| e.comment(), e.type() | |
| ); | |
| return result; | return result; |
| } | } |
| Line 547 void Request::use_file_directly(VStatele | Line 542 void Request::use_file_directly(VStatele |
| } | } |
| void Request::use_file(VStateless_class& aclass, | void Request::use_file(VStateless_class& aclass, const String& file_name, const String* use_filespec/*absolute*/) { |
| const String& file_name, | |
| const String* use_filespec/*absolute*/) { | |
| if(file_name.is_empty()) | if(file_name.is_empty()) |
| throw Exception(PARSER_RUNTIME, | throw Exception(PARSER_RUNTIME, |
| Line 597 void Request::use_file(VStateless_class& | Line 590 void Request::use_file(VStateless_class& |
| use_file_directly(aclass, *filespec); | use_file_directly(aclass, *filespec); |
| } | } |
| void Request::use_file(VStateless_class& aclass, const String& file_name, const String* use_filespec/*absolute*/, Operation::Origin origin) { | |
| static String use("USE"); | |
| try { | |
| use_file(aclass, file_name, use_filespec); | |
| } catch (...) { | |
| exception_trace.push(Trace(&use, origin)); | |
| rethrow; | |
| } | |
| } | |
| void Request::use_buf(VStateless_class& aclass, | void Request::use_buf(VStateless_class& aclass, |
| const char* source, const String* main_alias, | const char* source, const String* main_alias, |
| Line 938 const String& Request::transcode(const x | Line 940 const String& Request::transcode(const x |
| } | } |
| #endif | #endif |
| const Request::Trace Request::Exception_trace::extract_origin(const String*& problem_source) { | |
| Trace result; | |
| if(!is_empty()) { | |
| result=bottom_value(); | |
| if(!problem_source) { // we don't know who trigged the bug? | |
| problem_source=result.name(); // consider the stack-top-guy (we usually know source of next-from-throw-point exception) did that | |
| fbottom++; | |
| } else if(result.name()==problem_source) // it is that same guy? | |
| fbottom++; // throw away that trace | |
| else { | |
| // stack top contains not us, | |
| // leaving result intact | |
| // it would help ^throw | |
| } | |
| } | |
| return result; | |
| } | |
| Request::Exception_details Request::get_details(const Exception& e) { | Request::Exception_details Request::get_details(const Exception& e) { |
| const String* problem_source=e.problem_source(); | const String* problem_source=e.problem_source(); |
| Trace trace=exception_trace.extract_origin(problem_source); | |
| VHash& vhash=*new VHash; HashStringValue& hash=vhash.hash(); | VHash& vhash=*new VHash; HashStringValue& hash=vhash.hash(); |
| Operation::Origin origin={0, 0, 0}; | |
| if(!exception_trace.is_empty()) { | |
| Trace bottom=exception_trace.bottom_value(); | |
| origin=bottom.origin(); | |
| if(!problem_source) { // we don't know who trigged the bug | |
| problem_source=bottom.name(); // we usually know source of next-from-throw-point exception did that | |
| exception_trace.set_bottom_index(exception_trace.bottom_index()+1); | |
| } else if (bottom.name()==problem_source) { // it is that same guy? | |
| exception_trace.set_bottom_index(exception_trace.bottom_index()+1); // throw away that trace | |
| } else { | |
| // stack top contains not us, leaving intact to help ^throw | |
| } | |
| } | |
| // $.type | // $.type |
| if(const char* type=e.type(true)) | if(const char* type=e.type(true)) |
| hash.put(exception_type_part_name, new VString(*new String(type))); | hash.put(exception_type_part_name, new VString(*new String(type))); |
| // $.source | // $.source |
| if(problem_source) { | if(problem_source) |
| String& source=*new String(*problem_source, String::L_TAINTED); | hash.put(exception_source_part_name, new VString(*new String(*problem_source, String::L_TAINTED))); |
| hash.put(exception_source_part_name, new VString(source)); | |
| } | |
| // $.file lineno colno | // $.file $.lineno $.colno |
| if(trace) { | if(origin.file_no){ |
| const Operation::Origin origin=trace.origin(); | hash.put("file", new VString(*new String(file_list[origin.file_no], String::L_TAINTED))); |
| hash.put(String::Body("file"), | hash.put("lineno", new VInt(1+origin.line)); |
| new VString(*new String(file_list[origin.file_no], String::L_TAINTED))); | hash.put("colno", new VInt(1+origin.col)); |
| hash.put(String::Body("lineno"), new VInt(1+origin.line)); | |
| hash.put(String::Body("colno"), new VInt(1+origin.col)); | |
| } | } |
| // $.comment | // $.comment |
| if(const char* comment=e.comment(true)) | if(const char* comment=e.comment(true)) |
| hash.put(exception_comment_part_name, | hash.put(exception_comment_part_name, new VString(*new String(comment, String::L_TAINTED))); |
| new VString(*new String(comment, String::L_TAINTED))); | |
| // $.handled(0) | // $.handled(0) |
| hash.put(exception_handled_part_name, &VBool::get(false)); | hash.put(exception_handled_part_name, &VBool::get(false)); |
| return Request::Exception_details(trace, problem_source, vhash); | return Request::Exception_details(origin, problem_source, vhash); |
| } | } |
| Temp_value_element::Temp_value_element(Request& arequest, Value& awhere, const String& aname, Value* awhat) : | Temp_value_element::Temp_value_element(Request& arequest, Value& awhere, const String& aname, Value* awhat) : |