--- parser3/src/main/pa_request.C 2010/08/01 14:49:33 1.322 +++ parser3/src/main/pa_request.C 2015/04/02 22:04:41 1.339 @@ -1,12 +1,10 @@ /** @file Parser: request class main part. @see compile.C and execute.C. - Copyright (c) 2001-2009 ArtLebedev Group (http://www.artlebedev.com) + Copyright (c) 2001-2012 Art. Lebedev Studio (http://www.artlebedev.com) Author: Alexandr Petrosian (http://paf.design.ru) */ -static const char * const IDENT_REQUEST_C="$Date: 2010/08/01 14:49:33 $"; - #include "pa_sapi.h" #include "pa_common.h" #include "pa_request.h" @@ -34,6 +32,8 @@ static const char * const IDENT_REQUEST_ #include "pa_vconsole.h" #include "pa_vdate.h" +volatile const char * IDENT_PA_REQUEST_C="$Id: pa_request.C,v 1.339 2015/04/02 22:04:41 moko Exp $" IDENT_PA_REQUEST_H IDENT_PA_REQUEST_CHARSETS_H IDENT_PA_REQUEST_INFO_H IDENT_PA_VCONSOLE_H; + // consts #define UNHANDLED_EXCEPTION_METHOD_NAME "unhandled_exception" @@ -71,6 +71,7 @@ const String exception_handled_part_name #define CHARSETS_NAME "CHARSETS" #define MIME_TYPES_NAME "MIME-TYPES" +#define STRICT_VARS_NAME "STRICT-VARS" #define ORIGINS_MODE_NAME "ORIGINS" #define CONF_METHOD_NAME "conf" #define POST_PROCESS_METHOD_NAME "postprocess" @@ -83,6 +84,7 @@ const String exception_handled_part_name static const String charsets_name(CHARSETS_NAME); static const String main_class_name(MAIN_CLASS_NAME); static const String mime_types_name(MIME_TYPES_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 post_process_method_name(POST_PROCESS_METHOD_NAME); @@ -97,11 +99,12 @@ VStateless_class& VClassMAIN_create(); // Request::Request(SAPI_Info& asapi_info, Request_info& arequest_info, - String::Language adefault_lang, bool status_allowed): + String::Language adefault_lang): // private anti_endless_execute_recoursion(0), // public + allow_class_replace(false), method_frame(0), rcontext(0), wcontext(0), @@ -112,12 +115,6 @@ Request::Request(SAPI_Info& asapi_info, fin_cycle(0), // public -#ifdef RESOURCES_DEBUG - sql_connect_time(0), - sql_request_time(0), -#endif - - // public request_info(arequest_info), sapi_info(asapi_info), charsets(UTF8_charset, UTF8_charset, UTF8_charset), // default charsets @@ -157,10 +154,9 @@ Request::Request(SAPI_Info& asapi_info, // env class classes().put(String::Body(ENV_CLASS_NAME), new VEnv(asapi_info)); // status class - if(status_allowed) - classes().put(String::Body(STATUS_CLASS_NAME), new VStatus()); + classes().put(String::Body(STATUS_CLASS_NAME), new VStatus()); // request class - classes().put(String::Body(REQUEST_CLASS_NAME), new VRequest(arequest_info, charsets, form)); + classes().put(String::Body(REQUEST_CLASS_NAME), new VRequest(arequest_info, charsets, form, asapi_info)); // cookie class classes().put(String::Body(COOKIE_CLASS_NAME), &cookie); // console class @@ -209,7 +205,7 @@ Value* Request::get_class(const String& frame.store_params(&vname, 1); // we don't need the result - execute_method(frame, *method); + execute_method(frame); result=classes().get(name); } @@ -248,6 +244,18 @@ void Request::configure_admin(VStateless "$" MAIN_CLASS_NAME ":" CHARSETS_NAME " must be hash"); } +#ifdef STRICT_VARS + VVoid::strict_vars=false; + if(Value* strict_vars=conf_class.get_element(strict_vars_name)) { + if(strict_vars->is_bool()) + VVoid::strict_vars=strict_vars->as_bool(); + else + throw Exception(PARSER_RUNTIME, + 0, + "$" MAIN_CLASS_NAME ":" STRICT_VARS_NAME " must be bool"); + } +#endif + // configure method_frame options // until someone with less privileges have overriden them methoded_array().configure_admin(*this); @@ -318,16 +326,7 @@ void Request::configure() { */ void Request::core(const char* config_filespec, bool config_fail_on_read_problem, bool header_only) { -#ifdef RESOURCES_DEBUG -//measures -struct timeval mt[10]; -//measure:before all -gettimeofday(&mt[0],NULL); -#endif try { - // filling mail received - mail.fill_received(*this); - // loading config if(config_filespec) { const String& filespec=*new String(config_filespec); @@ -337,6 +336,9 @@ gettimeofday(&mt[0],NULL); true /*file must exist if 'fail on read problem' not set*/); } + // filling mail received + mail.fill_received(*this); + // loading auto.p files from document_root/.. // to the one beside requested file. // all assigned bases from upper dir @@ -378,10 +380,6 @@ gettimeofday(&mt[0],NULL); rethrow; } -#ifdef RESOURCES_DEBUG -//measure:after compile -gettimeofday(&mt[1],NULL); -#endif // execute @main[] const String* body_string=execute_virtual_method(main_class, main_method_name); if(!body_string) @@ -389,11 +387,6 @@ gettimeofday(&mt[1],NULL); 0, "'"MAIN_METHOD_NAME"' method not found"); -#ifdef RESOURCES_DEBUG - //measure:after main -gettimeofday(&mt[2],NULL); -#endif - // extract response body Value* body_value=response.fields().get(download_name); // $response:download? bool as_attachment=body_value!=0; @@ -411,37 +404,16 @@ gettimeofday(&mt[2],NULL); VMethodFrame frame(*method, 0 /*no parent*/, main_class); frame.store_params(&body_value, 1); - body_value=&execute_method(frame, *method).as_value(); + execute_method(frame); + + body_value=&frame.result().as_value(); } VFile* body_file=body_value->as_vfile(flang, &charsets); -#ifdef RESOURCES_DEBUG -//measure:after postprocess -gettimeofday(&mt[3],NULL); -#endif - // OK. write out the result output_result(body_file, header_only, as_attachment); -#ifdef RESOURCES_DEBUG - //measure:after output_result -gettimeofday(&mt[9],NULL); -t[9]=mt[9].tv_sec+mt[9].tv_usec/1000000.0; - -double t[10]; -for(int i=0;i<10;i++) - t[i]=mt[i].tv_sec+mt[i].tv_usec/1000000.0; -//measure:log2 compile,main,postprocess,output -SAPI::log("rmeasure: %s,%.2f,%.2f,%.2f %.2f,%.2f %.2f", -request_info.uri, -t[1]-t[0], -t[2]-t[1], -t[3]-t[2], -sql_connect_time,sql_request_time, -t[9]-t[3] -); -#endif } catch(const Exception& e) { // request handling problem try { // we're returning not result, but error explanation @@ -465,7 +437,6 @@ t[9]-t[3] if(const Method *method=junction->method) { // preparing to pass parameters to // @unhandled_exception[exception;stack] - VMethodFrame frame(*method, 0 /*no caller*/, main_class); // $stack[^table::create{name file lineno colno}] Table::columns_type stack_trace_columns(new ArrayString); @@ -489,13 +460,17 @@ t[9]-t[3] stack_trace+=row; } - Value *params[]={&details.vhash, new VTable(&stack_trace)}; - frame.store_params(params, 2); - // future $response:body= // execute ^unhandled_exception[exception;stack] exception_trace.clear(); // forget all about previous life, in case there would be error inside of this method, error handled would not be mislead by old stack contents (see extract_origin) - body_string=&execute_method(frame, *method).as_string(); + + VMethodFrame frame(*method, 0 /*no caller*/, main_class); + Value *params[]={&details.vhash, new VTable(&stack_trace)}; + + frame.store_params(params, 2); + execute_method(frame); + + body_string=&frame.result().as_string(); } } } @@ -563,14 +538,19 @@ void Request::use_file(VStateless_class& const String& file_name, const String* use_filespec/*absolute*/) { + if(file_name.is_empty()) + throw Exception(PARSER_RUNTIME, + 0, + "usage failed - no filename was specified"); + const String* filespec=0; if(file_name.first_char()=='/') //absolute path? [no need to scan MAIN:CLASS_PATH] filespec=&absolute(file_name); else if(use_filespec){ // search in current dir first - int afterslash=lastposafter(*use_filespec, 0, "/", 1, true); - if(afterslash>0) - filespec=file_exist(use_filespec->mid(0, afterslash-1), file_name); // found in current dir? + size_t last_slash_pos=use_filespec->strrpbrk("/"); + if(last_slash_pos!=STRING_NOT_FOUND) + filespec=file_exist(use_filespec->mid(0, last_slash_pos), file_name); // found in current dir? } if(!filespec){ @@ -634,6 +614,8 @@ void Request::use_buf(VStateless_class& execute_nonvirtual_method(cclass, auto_method_name, vfilespec, false/*no result needed*/); + + cclass.enable_default_setter(); } } @@ -755,7 +737,7 @@ static void output_pieces(Request& r, const size_t BUFSIZE = 10*0x400; char buf[BUFSIZE]; - const char *range = SAPI::get_env(r.sapi_info, "HTTP_RANGE"); + const char *range = SAPI::Env::get(r.sapi_info, "HTTP_RANGE"); size_t offset=0; size_t part_length=content_length; if(range){ @@ -841,7 +823,7 @@ void Request::output_result(VFile* body_ name_cstr=after_slash; if(char *after_slash=rsplit(name_cstr, '/')) name_cstr=after_slash; - vfile_name=new VString(*new String(name_cstr)); + vfile_name=new VString(*new String(name_cstr)); } } if(vfile_name) { @@ -850,7 +832,7 @@ void Request::output_result(VFile* body_ VHash& hash=*new VHash(); HashStringValue &h=hash.hash(); h.put(value_name, new VString( as_attachment ? content_disposition_attachment : content_disposition_inline )); - h.put(content_disposition_filename_name, vfile_name); + h.put(content_disposition_filename_name, new VString(String(sfile_name, String::L_HTTP_HEADER))); response.fields().put(content_disposition, &hash); @@ -906,6 +888,10 @@ void Request::output_result(VFile* body_ } } +const String& Request::mime_type_of(const String* file_name) { + return mime_type_of(file_name?file_name->taint_cstr(String::L_FILE_SPEC):0); +} + const String& Request::mime_type_of(const char* user_file_name_cstr) { if(mime_types) if(const char* cext=strrchr(user_file_name_cstr, '.')) { @@ -998,3 +984,19 @@ Request::Exception_details Request::get_ return Request::Exception_details(trace, problem_source, vhash); } + +Temp_value_element::Temp_value_element(Request& arequest, Value& awhere, const String& aname, Value* awhat) : + frequest(arequest), + fwhere(awhere), + fname(aname), + saved(awhere.get_element(aname)) +{ + Junction* junction; + if(saved && (junction=saved->get_junction()) && junction->is_getter) + saved=0; + frequest.put_element(fwhere, aname, awhat); +} + +Temp_value_element::~Temp_value_element() { + frequest.put_element(fwhere, fname, saved ? saved : VVoid::get()); +}