--- parser3/src/include/pa_request.h 2013/07/23 14:29:02 1.211 +++ parser3/src/include/pa_request.h 2016/09/29 18:49:43 1.227 @@ -1,14 +1,14 @@ /** @file Parser: request class decl. - 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 (http://paf.design.ru) */ #ifndef PA_REQUEST_H #define PA_REQUEST_H -#define IDENT_PA_REQUEST_H "$Id: pa_request.h,v 1.211 2013/07/23 14:29:02 moko Exp $" +#define IDENT_PA_REQUEST_H "$Id: pa_request.h,v 1.227 2016/09/29 18:49:43 moko Exp $" #include "pa_pool.h" #include "pa_hash.h" @@ -18,12 +18,10 @@ #include "pa_request_info.h" #include "pa_request_charsets.h" #include "pa_sapi.h" -#include "pa_vconsole.h" // consts const uint ANTI_ENDLESS_EXECUTE_RECOURSION=1000; -const uint ANTI_ENDLESS_JSON_STRING_RECOURSION=100; const size_t pseudo_file_no__process=1; // forwards @@ -36,13 +34,15 @@ class VForm; class VResponse; class VCookie; class VStateless_class; +class VConsole; /// Main workhorse. class Request: public PA_Object { friend class Temp_lang; friend class Temp_connection; - friend class Request_context_saver; friend class Temp_request_self; + friend class Temp_value_element; + friend class Request_context_saver; friend class Exception_trace; public: @@ -52,7 +52,6 @@ public: public: Trace(): fname(0) {} void clear() { fname=0; } - operator bool() const { return fname!=0; } Trace(const String* aname, const Operation::Origin aorigin): fname(aname), forigin(aorigin) {} @@ -108,14 +107,12 @@ private: bool is_empty() { return fused==fbottom; } - - const element_type extract_origin(const String*& problem_source); }; ///@{ core data /// classes - HashString fclasses; + HashString fclasses; /// already used files to avoid cyclic uses HashString used_files; @@ -128,8 +125,6 @@ private: */ uint anti_endless_execute_recoursion; - uint anti_endless_json_string_recoursion; - ///@} /// execution stack @@ -139,6 +134,8 @@ private: Exception_trace exception_trace; public: + bool allow_class_replace; + //@{ request processing status /// contexts VMethodFrame* method_frame; @@ -158,14 +155,10 @@ public: uint register_file(String::Body file_spec); struct Exception_details { - const Trace trace; + const Operation::Origin origin; const String* problem_source; VHash& vhash; - - Exception_details( - const Trace atrace, - const String* aproblem_source, - VHash& avhash): trace(atrace), problem_source(aproblem_source), vhash(avhash) {} + Exception_details(const Operation::Origin aorigin, const String* aproblem_source, VHash& avhash): origin(aorigin), problem_source(aproblem_source), vhash(avhash) {} }; Exception_details get_details(const Exception& e); const char* get_exception_cstr(const Exception& e, Exception_details& details); @@ -187,8 +180,9 @@ public: ~Request(); /// global classes - HashString& classes() { return fclasses; } - Value* get_class(const String& name); + HashString& classes() { return fclasses; } + VStateless_class* get_class(const String& name); + void put_class(VStateless_class *aclass){ classes().put(aclass->type(), aclass); } /** core request processing @@ -204,7 +198,7 @@ public: void execute(ArrayOperation& ops); // execute.C void op_call(VMethodFrame &frame); void op_call_write(VMethodFrame &frame); - Value& construct(Value &class_value, const Method &method); + Value& construct(VStateless_class &class_value, const Method &method); /// execute ops with anti-recoursion check void recoursion_checked_execute(/*const String& name, */ArrayOperation& ops) { @@ -219,21 +213,6 @@ public: anti_endless_execute_recoursion--; } - uint json_string_recoursion_go_down(){ - if(++anti_endless_json_string_recoursion==ANTI_ENDLESS_JSON_STRING_RECOURSION){ - anti_endless_json_string_recoursion=0; - throw Exception(PARSER_RUNTIME, - 0, - "call canceled - endless json recursion detected"); - } - return anti_endless_json_string_recoursion; - } - - void json_string_recoursion_go_up(){ - if(anti_endless_json_string_recoursion) - anti_endless_json_string_recoursion--; - } - /// void use_file_directly(VStateless_class& aclass, const String& file_spec, @@ -241,9 +220,8 @@ public: bool fail_on_file_absence=true); /// compiles the file, maybe forcing it's class @a name and @a base_class. - void use_file(VStateless_class& aclass, - const String& file_name, - const String* use_filespec); + void use_file(VStateless_class& aclass, const String& file_name, const String* use_filespec); + void use_file(VStateless_class& aclass, const String& file_name, const String* use_filespec, Operation::Origin origin); /// compiles a @a source buffer void use_buf(VStateless_class& aclass, @@ -253,32 +231,24 @@ public: int line_no_offset=0); /// processes any code-junction there may be inside of @a value - StringOrValue process_getter(Junction& junction); // execute.C - StringOrValue process(Value& input_value, bool intercept_string=true); // execute.C + Value& process_getter(Junction& junction); // execute.C + Value& process(Value& input_value, bool intercept_string=true); // execute.C void process_write(Value& input_value); // execute.C //@{ convinient helpers const String& process_to_string(Value& input_value) { return process(input_value, true/*intercept_string*/).as_string(); } Value& process_to_value(Value& input_value, bool intercept_string=true) { - return process(input_value, intercept_string).as_value(); + return process(input_value, intercept_string); } //@} const String* get_method_filename(const Method* method); // execute.C const String* get_used_filename(uint file_no); -#define DEFINE_DUAL(modification) \ - void write_##modification##_lang(StringOrValue dual) { \ - if(const String* string=dual.get_string()) \ - write_##modification##_lang(*string); \ - else \ - write_##modification##_lang(*dual.get_value()); \ - } - /// appending, sure of clean string inside void write_no_lang(const String& astring) { wcontext->write(astring, - (String::Language)(String::L_CLEAN | flang&String::L_OPTIMIZE_BIT)); + (String::Language)(String::L_CLEAN | (flang & String::L_OPTIMIZE_BIT) )); } /// appending sure value, that would be converted to clean string void write_no_lang(Value& avalue) { @@ -286,7 +256,7 @@ public: wcontext->write(avalue); else wcontext->write(avalue, - (String::Language)(String::L_CLEAN | flang&String::L_OPTIMIZE_BIT)); + (String::Language)(String::L_CLEAN | (flang & String::L_OPTIMIZE_BIT) )); } /// appending string, passing language built into string being written @@ -297,7 +267,6 @@ public: void write_pass_lang(Value& avalue) { wcontext->write(avalue, String::L_PASS_APPENDED); } - DEFINE_DUAL(pass) /// appending possible string, assigning untaint language void write_assign_lang(Value& avalue) { @@ -307,7 +276,11 @@ public: void write_assign_lang(const String& astring) { wcontext->write(astring, flang); } - DEFINE_DUAL(assign) + + /// appending sure value + void write_value(Value& avalue) { + wcontext->write(avalue); + } /// returns relative to @a path path to @a file const String& relative(const char* apath, const String& relative_name); @@ -371,6 +344,7 @@ public: // status read methods VMethodFrame *get_method_frame() { return method_frame; } Value& get_self(); + #define GET_SELF(request, type) (static_cast(request.get_self())) /* for strange reason call to this: r.get_self() @@ -436,6 +410,9 @@ private: // compile.C private: // execute.C Value& get_element(Value& ncontext, const String& name); +#ifdef FEATURE_GET_ELEMENT4CALL + Value& get_element4call(Value& ncontext, const String& name); +#endif private: // defaults @@ -483,7 +460,6 @@ class Request_context_saver { /// execution stack size_t stack; uint anti_endless_execute_recoursion; - uint anti_endless_json_string_recoursion; /// contexts VMethodFrame* method_frame; Value* rcontext; @@ -500,7 +476,6 @@ public: exception_trace_bottom(ar.exception_trace.bottom_index()), stack(ar.stack.top_index()), anti_endless_execute_recoursion(ar.anti_endless_execute_recoursion), - anti_endless_json_string_recoursion(ar.anti_endless_json_string_recoursion), method_frame(ar.method_frame), rcontext(ar.rcontext), wcontext(ar.wcontext), @@ -511,7 +486,6 @@ public: fr.exception_trace.set_bottom_index(exception_trace_bottom); fr.stack.set_top_index(stack); fr.anti_endless_execute_recoursion=anti_endless_execute_recoursion; - fr.anti_endless_json_string_recoursion=anti_endless_json_string_recoursion; fr.method_frame=method_frame, fr.rcontext=rcontext; fr.wcontext=wcontext; fr.flang=flang; fr.fconnection=fconnection; @@ -558,6 +532,29 @@ public: } }; +/// Auto-object used for temporary changing Request::allow_class_replace. +class Temp_class_replace { + Request& frequest; +public: + Temp_class_replace(Request& arequest, bool avalue) : frequest(arequest){ + frequest.allow_class_replace=avalue; + } + ~Temp_class_replace() { + frequest.allow_class_replace=false; + } +}; + +/// Auto-object used for temporarily substituting/removing elements +class Temp_value_element { + Request& frequest; + Value& fwhere; + const String& fname; + Value* saved; +public: + Temp_value_element(Request& arequest, Value& awhere, const String& aname, Value* awhat); + ~Temp_value_element(); +}; + // defines for externs #define EXCEPTION_HANDLED_PART_NAME "handled" @@ -567,7 +564,6 @@ public: extern const String main_method_name; extern const String auto_method_name; -extern const String body_name; extern const String exception_type_part_name; extern const String exception_source_part_name;