--- parser3/src/main/pa_request.C 2010/05/23 01:06:47 1.320 +++ parser3/src/main/pa_request.C 2012/05/24 12:50:20 1.331 @@ -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/05/23 01:06:47 $"; - #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.331 2012/05/24 12:50:20 misha 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,9 +99,10 @@ 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), + anti_endless_json_string_recoursion(0), // public method_frame(0), @@ -157,8 +160,7 @@ 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)); // cookie class @@ -205,12 +207,11 @@ Value* Request::get_class(const String& if(Junction* junction=value->get_junction()) if(const Method *method=junction->method) { Value *vname=new VString(name); - VMethodFrame frame(*junction, 0/*no parent*/); + VMethodFrame frame(*method, 0 /*no parent*/, main_class); - frame.set_self(main_class); frame.store_params(&vname, 1); // we don't need the result - execute_method(frame, *method); + execute_method(frame); result=classes().get(name); } @@ -249,6 +250,17 @@ void Request::configure_admin(VStateless "$" MAIN_CLASS_NAME ":" CHARSETS_NAME " must be hash"); } +#ifdef STRICT_VARS + 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); @@ -409,11 +421,12 @@ gettimeofday(&mt[2],NULL); if(const Method *method=junction->method) { // preparing to pass parameters to // @postprocess[data] - VMethodFrame frame(/*method->name, */ *junction, 0/*no parent*/); - frame.set_self(main_class); + 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); @@ -467,8 +480,6 @@ t[9]-t[3] if(const Method *method=junction->method) { // preparing to pass parameters to // @unhandled_exception[exception;stack] - VMethodFrame frame(/*method->name, */ *junction, 0/*no caller*/); - frame.set_self(main_class); // $stack[^table::create{name file lineno colno}] Table::columns_type stack_trace_columns(new ArrayString); @@ -492,13 +503,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(); } } } @@ -566,14 +581,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){ @@ -844,7 +864,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) { @@ -853,7 +873,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); @@ -909,6 +929,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, '.')) { @@ -926,68 +950,6 @@ const String& Request::mime_type_of(cons return *new String("application/octet-stream"); } -const String* Request::get_method_filename(const Method* method){ - if(ArrayOperation* code=method->parser_code) - if(code){ - Operation::Origin origin={0, 0, 0}; - Array_iterator i(*code); - while( i.has_next() ){ - switch( i.next().code ){ - case OP::OP_CURLY_CODE__STORE_PARAM: - case OP::OP_EXPR_CODE__STORE_PARAM: - case OP::OP_CURLY_CODE__CONSTRUCT: - case OP::OP_NESTED_CODE: - case OP::OP_OBJECT_POOL: - case OP::OP_STRING_POOL: - case OP::OP_CALL: - case OP::OP_CALL__WRITE: - { - i.next(); // skip local ops - i.next(); // skip next opcode - } - case OP::OP_CONSTRUCT_OBJECT: - case OP::OP_CONSTRUCT_OBJECT__WRITE: - case OP::OP_VALUE: - case OP::OP_STRING__WRITE: - case OP::OP_VALUE__GET_CLASS: -#ifdef OPTIMIZE_BYTECODE_GET_OBJECT_ELEMENT - case OP::OP_GET_OBJECT_ELEMENT: - case OP::OP_GET_OBJECT_ELEMENT__WRITE: -#endif -#ifdef OPTIMIZE_BYTECODE_GET_OBJECT_VAR_ELEMENT - case OP::OP_GET_OBJECT_VAR_ELEMENT: - case OP::OP_GET_OBJECT_VAR_ELEMENT__WRITE: -#endif -#ifdef OPTIMIZE_BYTECODE_GET_ELEMENT - case OP::OP_VALUE__GET_ELEMENT: - case OP::OP_VALUE__GET_ELEMENT__WRITE: - case OP::OP_VALUE__GET_ELEMENT_OR_OPERATOR: - case OP::OP_WITH_ROOT__VALUE__GET_ELEMENT: -#endif -#ifdef OPTIMIZE_BYTECODE_GET_SELF_ELEMENT - case OP::OP_WITH_SELF__VALUE__GET_ELEMENT: - case OP::OP_WITH_SELF__VALUE__GET_ELEMENT__WRITE: -#endif -#ifdef OPTIMIZE_BYTECODE_CONSTRUCT - case OP::OP_WITH_ROOT__VALUE__CONSTRUCT_EXPR: - case OP::OP_WITH_ROOT__VALUE__CONSTRUCT_VALUE: - case OP::OP_WITH_WRITE__VALUE__CONSTRUCT_EXPR: - case OP::OP_WITH_WRITE__VALUE__CONSTRUCT_VALUE: - case OP::OP_WITH_SELF__VALUE__CONSTRUCT_EXPR: - case OP::OP_WITH_SELF__VALUE__CONSTRUCT_VALUE: -#endif - { - origin=i.next().origin; - break; - } - } - if(origin.file_no) - return get_used_filename(origin.file_no); - } - } - return 0; -} - const String* Request::get_used_filename(uint file_no){ if(file_no < file_list.count()) return new String(file_list[file_no], String::L_TAINTED);