|
|
| version 1.58, 2001/11/05 11:46:21 | version 1.63, 2001/12/07 15:24:46 |
|---|---|
| Line 53 static void _if(Request& r, const String | Line 53 static void _if(Request& r, const String |
| static void _untaint(Request& r, const String& method_name, MethodParams *params) { | static void _untaint(Request& r, const String& method_name, MethodParams *params) { |
| Pool& pool=r.pool(); | Pool& pool=r.pool(); |
| const String& lang_name=params->as_string(0, "lang must be string"); | uchar lang; |
| String::Untaint_lang lang=static_cast<String::Untaint_lang>( | if(params->size()==1) |
| untaint_lang_name2enum->get_int(lang_name)); | lang=String::UL_AS_IS; // mark as simply 'tainted'. useful in html from sql |
| if(!lang) | else { |
| throw Exception(0, 0, | const String& lang_name=params->as_string(0, "lang must be string"); |
| &lang_name, | lang=untaint_lang_name2enum->get_int(lang_name); |
| "invalid untaint language"); | if(!lang) |
| throw Exception(0, 0, | |
| &lang_name, | |
| "invalid taint language"); | |
| } | |
| { | { |
| Value& vbody=params->as_junction(1, "body must be code"); | Value& vbody=params->as_junction(params->size()-1, "body must be code"); |
| Temp_lang temp_lang(r, lang); // set temporarily specified ^untaint[language; | Temp_lang temp_lang(r, lang); // set temporarily specified ^untaint[language; |
| r.write_pass_lang(r.process(vbody)); // process marking tainted with that lang | r.write_pass_lang(r.process(vbody)); // process marking tainted with that lang |
| Line 72 static void _untaint(Request& r, const S | Line 76 static void _untaint(Request& r, const S |
| static void _taint(Request& r, const String&, MethodParams *params) { | static void _taint(Request& r, const String&, MethodParams *params) { |
| Pool& pool=r.pool(); | Pool& pool=r.pool(); |
| String::Untaint_lang lang; | uchar lang; |
| if(params->size()==1) | if(params->size()==1) |
| lang=String::UL_TAINTED; // mark as simply 'tainted'. useful in table:set | lang=String::UL_TAINTED; // mark as simply 'tainted'. useful in table:set |
| else { | else { |
| const String& lang_name=params->as_string(0, "lang must be string"); | const String& lang_name=params->as_string(0, "lang must be string"); |
| lang=static_cast<String::Untaint_lang>( | lang=untaint_lang_name2enum->get_int(lang_name); |
| untaint_lang_name2enum->get_int(lang_name)); | |
| if(!lang) | if(!lang) |
| throw Exception(0, 0, | throw Exception(0, 0, |
| &lang_name, | &lang_name, |
| Line 118 static void _process(Request& r, const S | Line 121 static void _process(Request& r, const S |
| // evaluate source to process | // evaluate source to process |
| const String& source= | const String& source= |
| r.process(params->as_no_junction(0, "body must be string")).as_string(); | r.process(params->as_junction(0, "body must be code")).as_string(); |
| // process source code, append processed methods to 'self' class | // process source code, append processed methods to 'self' class |
| // maybe-define new @main | // maybe-define new @main |
| r.use_buf(source.cstr(), place, &self_class); | r.use_buf(source.cstr(String::UL_UNSPECIFIED, r.connection), place, &self_class); |
| // maybe-execute @main[] | // maybe-execute @main[] |
| if(const Method *method=self_class.get_method(*main_method_name)) { | if(const Method *method=self_class.get_method(*main_method_name)) { |
| Line 229 static void _error(Request& r, const Str | Line 232 static void _error(Request& r, const Str |
| /// @todo rewrite ugly code with try/try to autoobject TempConnection | /// @todo rewrite ugly code with try/try to autoobject TempConnection |
| static void _connect(Request& r, const String& method_name, MethodParams *params) { | static void _connect(Request& r, const String& method_name, MethodParams *params) { |
| Pool& pool=r.pool(); | Pool& pool=r.pool(); |
| #ifdef RESOURCES_DEBUG | |
| struct timeval mt[2]; | |
| #endif | |
| Value& url=params->as_no_junction(0, "url must not be code"); | Value& url=params->as_no_junction(0, "url must not be code"); |
| Value& body_code=params->as_junction(1, "body must be code"); | Value& body_code=params->as_junction(1, "body must be code"); |
| Table *protocol2driver_and_client= | Table *protocol2driver_and_client= |
| static_cast<Table *>(r.classes_conf.get(r.OP.name())); | static_cast<Table *>(r.classes_conf.get(r.OP.name())); |
| #ifdef RESOURCES_DEBUG | |
| //measure:before | |
| gettimeofday(&mt[0],NULL); | |
| #endif | |
| // connect | // connect |
| SQL_Connection& connection=SQL_driver_manager->get_connection( | SQL_Connection& connection=SQL_driver_manager->get_connection( |
| url.as_string(), method_name, protocol2driver_and_client); | url.as_string(), method_name, protocol2driver_and_client); |
| #ifdef RESOURCES_DEBUG | |
| //measure:after connect | |
| gettimeofday(&mt[1],NULL); | |
| double t[2]; | |
| for(int i=0;i<2;i++) | |
| t[i]=mt[i].tv_sec+mt[i].tv_usec/1000000.0; | |
| r.sql_connect_time+=t[1]-t[0]; | |
| #endif | |
| // remember/set current connection | // remember/set current connection |
| SQL_Connection *saved_connection=r.connection; | SQL_Connection *saved_connection=r.connection; |
| r.connection=&connection; | r.connection=&connection; |
| Line 323 static void _case(Request& r, const Stri | Line 342 static void _case(Request& r, const Stri |
| } | } |
| } | } |
| // cache-- | |
| // consts | |
| const int DATA_STRING_SERIALIZED_VERSION=0x0001; | |
| // helper types | |
| #ifndef DOXYGEN | |
| struct Data_string_serialized_prolog { | |
| int version; | |
| }; | |
| #endif | |
| void cache_delete(Pool& pool, const String& file_spec) { | |
| file_delete(pool, file_spec, false/*fail_on_read_problem*/); | |
| } | |
| void cache_put(Pool& pool, const String& file_spec, const String& data_string) { | |
| void *data; size_t data_size; | |
| data_string.serialize( | |
| sizeof(Data_string_serialized_prolog), | |
| data, data_size); | |
| Data_string_serialized_prolog& prolog= | |
| *static_cast<Data_string_serialized_prolog *>(data); | |
| prolog.version=DATA_STRING_SERIALIZED_VERSION; | |
| file_write(pool, | |
| file_spec, | |
| data, data_size, | |
| false/*as_text*/); | |
| } | |
| String *cache_get(Pool& pool, const String& file_spec) { | |
| void* data; size_t data_size; | |
| if(!file_read(pool, file_spec, | |
| data, data_size, | |
| false/*as_text*/, | |
| false/*fail_on_read_problem*/)) | |
| return 0; | |
| Data_string_serialized_prolog& prolog= | |
| *static_cast<Data_string_serialized_prolog *>(data); | |
| if(data_size<sizeof(Data_string_serialized_prolog)) | |
| throw Exception(0, 0, | |
| &file_spec, | |
| "bad cached file, too short"); | |
| if(prolog.version!=DATA_STRING_SERIALIZED_VERSION) | |
| throw Exception(0, 0, | |
| &file_spec, | |
| "data string version 0x%04X not equal to 0x%04X, recreate file", | |
| prolog.version, DATA_STRING_SERIALIZED_VERSION); | |
| String& result=*new(pool) String(pool); | |
| if(data_size) { | |
| result.deserialize( | |
| sizeof(Data_string_serialized_prolog), | |
| data, data_size, file_spec.cstr()); | |
| } | |
| return &result; | |
| } | |
| static void _cache(Request& r, const String& method_name, MethodParams *params) { | |
| // ^cache[file_spec](lifespan){code} time=0 no cache | |
| Pool& pool=r.pool(); | |
| // file_spec, expires, body code | |
| const String &file_spec=params->as_string(0, "key must be string"); | |
| time_t lifespan=(time_t)params->as_double(1, "lifespan must be number", r); | |
| Value& body_code=params->as_junction(2, "body must be code"); | |
| if(lifespan) { // 'lifespan' specified? try cached copy... | |
| size_t size; | |
| time_t atime, mtime, ctime; | |
| // {file_spec} modification time | |
| if(!file_stat(file_spec, size, atime, mtime, ctime, false/*no exception on error*/) | |
| || (time(0)-mtime) > lifespan) // cached file expired | |
| cache_delete(pool, file_spec); | |
| else | |
| if(String *cached_body=cache_get(pool, file_spec)) { // have cached copy? | |
| // write it out | |
| r.write_assign_lang(*cached_body); | |
| // happy with it | |
| return; | |
| } | |
| } else // 'lifespan'=0, forget cached copy | |
| cache_delete(pool, file_spec); | |
| // process | |
| Value& processed_body=r.process(body_code); | |
| // put it to cache if 'lifespan' specified | |
| if(lifespan) | |
| cache_put(pool, file_spec, processed_body.as_string()); | |
| // write it out | |
| r.write_assign_lang(processed_body); | |
| } | |
| // constructor | // constructor |
| MOP::MOP(Pool& apool) : Methoded(apool), | MOP::MOP(Pool& apool) : Methoded(apool), |
| Line 336 MOP::MOP(Pool& apool) : Methoded(apool), | Line 455 MOP::MOP(Pool& apool) : Methoded(apool), |
| add_native_method("if", Method::CT_ANY, _if, 2, 3); | add_native_method("if", Method::CT_ANY, _if, 2, 3); |
| // ^untaint[as-is|uri|sql|js|html|html-typo]{code} | // ^untaint[as-is|uri|sql|js|html|html-typo]{code} |
| add_native_method("untaint", Method::CT_ANY, _untaint, 2, 2); | add_native_method("untaint", Method::CT_ANY, _untaint, 1, 2); |
| // ^taint[as-is|uri|sql|js|html|html-typo]{code} | // ^taint[as-is|uri|sql|js|html|html-typo]{code} |
| add_native_method("taint", Method::CT_ANY, _taint, 1, 2); | add_native_method("taint", Method::CT_ANY, _taint, 1, 2); |
| Line 367 MOP::MOP(Pool& apool) : Methoded(apool), | Line 486 MOP::MOP(Pool& apool) : Methoded(apool), |
| // ^connect[protocol://user:pass@host[:port]/database]{code with ^sql-s} | // ^connect[protocol://user:pass@host[:port]/database]{code with ^sql-s} |
| add_native_method("connect", Method::CT_ANY, _connect, 2, 2); | add_native_method("connect", Method::CT_ANY, _connect, 2, 2); |
| // ^cache[file_spec](time){code} time=0 no cache | |
| add_native_method("cache", Method::CT_ANY, _cache, 3, 3); | |
| // switch | // switch |
| // ^switch[value]{cases} | // ^switch[value]{cases} |