--- parser3/src/include/pa_request.h 2001/09/30 09:56:43 1.99 +++ parser3/src/include/pa_request.h 2002/04/15 10:35:22 1.129 @@ -1,16 +1,15 @@ /** @file Parser: request class decl. - Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com) - Author: Alexander Petrosyan (http://design.ru/paf) + Copyright (c) 2001, 2002 ArtLebedev Group (http://www.artlebedev.com) + Author: Alexandr Petrosian (http://paf.design.ru) - $Id: pa_request.h,v 1.99 2001/09/30 09:56:43 parser Exp $ + $Id: pa_request.h,v 1.129 2002/04/15 10:35:22 paf Exp $ */ #ifndef PA_REQUEST_H #define PA_REQUEST_H -#include "pa_config_includes.h" #include "pa_pool.h" #include "pa_hash.h" #include "pa_wcontext.h" @@ -19,6 +18,7 @@ #include "pa_vclass.h" #include "pa_vobject.h" #include "pa_venv.h" +#include "pa_vstatus.h" #include "pa_vform.h" #include "pa_vmath.h" #include "pa_vrequest.h" @@ -26,13 +26,16 @@ #include "pa_vcookie.h" #include "pa_sql_driver_manager.h" -#ifdef XML -# include -# include -# include -# include +#ifdef RESOURCES_DEBUG +#include #endif +// consts + +const uint ANTI_ENDLESS_EXECUTE_RECOURSION=500; + +// defines + #ifndef NO_STRING_ORIGIN # define COMPILE_PARAMS \ const char *source, \ @@ -52,12 +55,20 @@ class Temp_lang; class Methoded; +class VMethodFrame; /// Main workhorse. class Request : public Pooled { - friend Temp_lang; + friend class Temp_lang; + friend class Temp_connection; public: +#ifdef RESOURCES_DEBUG + /// measures + double sql_connect_time; + double sql_request_time; +#endif + /// some information from web server class Info { public: @@ -74,9 +85,10 @@ public: Request(Pool& apool, Info& ainfo, - String::Untaint_lang adefault_lang ///< all tainted data default untainting lang + uchar adefault_lang, ///< all tainted data default untainting lang + bool status_allowed ///< status class allowed ); - ~Request() {} + ~Request(); /// global classes Hash& classes() { return fclasses; } @@ -95,6 +107,18 @@ public: /// executes ops void execute(const Array& ops); // execute.C + /// execute ops with anti-recoursion check + void recoursion_checked_execute(const String *name, const Array& ops) { + // anti_endless_execute_recoursion + if(++anti_endless_execute_recoursion==ANTI_ENDLESS_EXECUTE_RECOURSION) { + anti_endless_execute_recoursion=0; // give @exception a chance + throw Exception("parser.runtime", + name, + "call canceled - endless recursion detected"); + } + execute(ops); // execute it + anti_endless_execute_recoursion--; + } /// compiles the file, maybe forcing it's class @a name and @a base_class. VStateless_class *use_file( @@ -107,15 +131,24 @@ public: const char *source, const char *file, VStateless_class *aclass=0, const String *name=0, VStateless_class *base_class=0); // core.C - /// processes any code-junction there may be inside of @a value - Value& process( - Value& value, - const String *name=0, - bool intercept_string=true); // execute.C + /// processes any code-junction there may be inside of @a value + StringOrValue process(Value& input_value, + bool intercept_string, + void (*postexecute)(void *info)=0, void *postexecute_info=0); // 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(); + } + //@} + /// appending, sure of clean string inside void write_no_lang(const String& astring) { - wcontext->write(astring, String::UL_CLEAN); + wcontext->write(astring, + String::UL_CLEAN | flang&String::UL_OPTIMIZE_BIT); } /// appending string, passing language built into string being written void write_pass_lang(const String& astring) { @@ -125,13 +158,21 @@ public: void write_assign_lang(Value& avalue) { wcontext->write(avalue, flang); } + /// appending string, assigning untaint language + void write_assign_lang(const String& astring) { + wcontext->write(astring, flang); + } /// appending possible string, passing language built into string being written void write_pass_lang(Value& avalue) { wcontext->write(avalue, String::UL_PASS_APPENDED); } /// appending sure value, that would be converted to clean string void write_no_lang(Value& avalue) { - wcontext->write(avalue, String::UL_CLEAN); + if(wcontext->get_in_expression()) + wcontext->write(avalue); + else + wcontext->write(avalue, + String::UL_CLEAN | flang&String::UL_OPTIMIZE_BIT); } /// appending sure value, not VString void write_expr_result(Value& avalue) { @@ -147,8 +188,15 @@ public: /// returns the mime type of 'user_file_name_cstr' const String& mime_type_of(const char *user_file_name_cstr); - /// PCRE character tables - unsigned char *pcre_tables(); + /// returns current SQL connection if any + SQL_Connection *connection(const String *source) { + if(!fconnection && source) + throw Exception("parser.runtime", + source, + "outside of 'connect' operator"); + + return fconnection; + } public: @@ -161,6 +209,8 @@ public: Methoded& OP; /// $env:fields VEnv env; + /// $status:fields + VStatus status; /// $form:elements VForm form; /// $math:constants @@ -172,17 +222,20 @@ public: /// $cookie:elements VCookie cookie; + //@{ request processing status + /// execution stack + Stack stack; /// contexts Value *self, *root, *rcontext; /// contexts WContext *wcontext; + /// exception stack trace + Stack exception_trace; + //@} /// 'MAIN' class conglomerat VStateless_class *main_class; - /// connection - SQL_Connection *connection; - /// classes configured data Hash classes_conf; @@ -194,39 +247,30 @@ private: // core data /// already used files to avoid cyclic uses Hash used_files; - /// execution stack - Stack stack; - /** endless execute(execute(... preventing counter @see ANTI_ENDLESS_EXECUTE_RECOURSION */ uint anti_endless_execute_recoursion; - /// charset->pcre_tables+XML256TableTranscoder [Request_CTYPE_value] - Hash CTYPE; - private: // compile.C VStateless_class& real_compile(COMPILE_PARAMS); private: // execute.C - const String *execute_method(Value& aself, - const Method& method, bool return_cstr=true); - const String *execute_virtual_method(Value& aself, - const String& method_name, bool return_cstr=true); + const String *execute_method(Value& aself, const Method& method, + bool return_cstr); + const String& execute_method(VMethodFrame& amethodFrame, const Method& method); + const String *execute_virtual_method(Value& aself, const String& method_name); const String *execute_nonvirtual_method(VStateless_class& aclass, - const String& method_name, bool return_cstr=true); + const String& method_name, + bool return_cstr); - Value *get_element(); - -private: // lang&raw - - String::Untaint_lang flang; + Value *get_element(bool can_call_operator); private: // defaults - const String::Untaint_lang fdefault_lang; + const uchar fdefault_lang; Value *default_content_type; private: // mime types @@ -236,42 +280,45 @@ private: // mime types private: // lang manipulation - String::Untaint_lang set_lang(String::Untaint_lang alang) { - String::Untaint_lang result=flang; + uchar set_lang(uchar alang) { + uchar result=flang; flang=alang; return result; } - void restore_lang(String::Untaint_lang alang) { + void restore_lang(uchar alang) { flang=alang; } -private: +private: // lang&raw + + uchar flang; - void output_result(const VFile& body_file, bool header_only); -}; -/// Request::CTYPE hash value -class Request_CTYPE_value : public Pooled { -public: - /// PCRE character tables - unsigned char *pcre_tables; -#ifdef XML - /// Xalan transformer for this charset - XML256TableTranscoder *transcoder; -#endif +private: // connection manipulation - Request_CTYPE_value(Pool& apool, - unsigned char * apcre_tables, XML256TableTranscoder *atranscoder) : Pooled(apool), - pcre_tables(apcre_tables), transcoder(atranscoder) { + SQL_Connection *set_connection(SQL_Connection *aconnection) { + SQL_Connection *result=fconnection; + fconnection=aconnection; + return result; + } + void restore_connection(SQL_Connection *aconnection) { + fconnection=aconnection; } + +private: + + /// connection + SQL_Connection *fconnection; + + void output_result(const VFile& body_file, bool header_only); }; /// Auto-object used for temporary changing Request::flang. class Temp_lang { Request& frequest; - String::Untaint_lang saved_lang; + uchar saved_lang; public: - Temp_lang(Request& arequest, String::Untaint_lang alang) : + Temp_lang(Request& arequest, uchar alang) : frequest(arequest), saved_lang(arequest.set_lang(alang)) { } @@ -280,6 +327,20 @@ public: } }; +/// Auto-object used for temporary changing Request::fconnection. +class Temp_connection { + Request& frequest; + SQL_Connection *saved_connection; +public: + Temp_connection(Request& arequest, SQL_Connection *aconnection) : + frequest(arequest), + saved_connection(arequest.set_connection(aconnection)) { + } + ~Temp_connection() { + frequest.restore_connection(saved_connection); + } +}; + /** @b method parameters passed in this array. contains handy typecast ad junction/not junction ensurers @@ -304,12 +365,16 @@ public: return get_as(index, false, msg); } /// handy expression auto-processing to double - double as_double(int index, Request& r) { - return get_processed(index, r).as_double(); + double as_double(int index, const char *msg, Request& r) { + return get_processed(index, msg, r).as_double(); } /// handy expression auto-processing to int - int as_int(int index, Request& r) { - return get_processed(index, r).as_int(); + int as_int(int index, const char *msg, Request& r) { + return get_processed(index, msg, r).as_int(); + } + /// handy expression auto-processing to bool + bool as_bool(int index, const char *msg, Request& r) { + return get_processed(index, msg, r).as_bool(); } /// handy string ensurer const String& as_string(int index, const char *msg) { @@ -322,16 +387,15 @@ private: Value& get_as(int index, bool as_junction, const char *msg) { Value& result=get(index); if((result.get_junction()!=0) ^ as_junction) - THROW(0, 0, + throw Exception("parser.runtime", &fmethod_name, "%s (parameter #%d)", msg, 1+index); + return result; } - Value& get_processed(int index, Request& r) { - return r.process(get(index), - 0/*no name*/, - false/*don't intercept string*/); + Value& get_processed(int index, const char *msg, Request& r) { + return r.process_to_value(as_junction(index, msg), 0/*no name*/); } private: