--- parser3/src/classes/file.C 2006/12/01 17:40:25 1.148 +++ parser3/src/classes/file.C 2007/04/13 16:58:15 1.154 @@ -5,7 +5,7 @@ Author: Alexandr Petrosian (http://paf.design.ru) */ -static const char * const IDENT_FILE_C="$Date: 2006/12/01 17:40:25 $"; +static const char * const IDENT_FILE_C="$Date: 2007/04/13 16:58:15 $"; #include "pa_config_includes.h" @@ -36,6 +36,9 @@ static const char * const IDENT_FILE_C=" #define NAME_NAME "name" +#define FILE_NAME_MUST_BE_STRING "file name must be string" +#define FILE_NAME_MUST_NOT_BE_CODE "file name must not be code" + // externs extern String sql_limit_name; @@ -126,7 +129,7 @@ static bool is_text_mode(const String& m static void _save(Request& r, MethodParams& params) { Value& vmode_name=params. as_no_junction(0, "mode must not be code"); - Value& vfile_name=params.as_no_junction(1, "file name must not be code"); + Value& vfile_name=params.as_no_junction(1, FILE_NAME_MUST_NOT_BE_CODE); // save GET_SELF(r, VFile).save(r.absolute(vfile_name.as_string()), @@ -134,7 +137,7 @@ static void _save(Request& r, MethodPara } static void _delete(Request& r, MethodParams& params) { - Value& vfile_name=params.as_no_junction(0, "file name must not be code"); + Value& vfile_name=params.as_no_junction(0, FILE_NAME_MUST_NOT_BE_CODE); // unlink file_delete(r.absolute(vfile_name.as_string())); @@ -160,7 +163,7 @@ static void copy_process_source( int nCount=0; do { unsigned char buffer[FILE_BUFFER_SIZE]; - nCount = read(from_file, buffer, sizeof(buffer)); + nCount = file_block_read(from_file, buffer, sizeof(buffer)); int written=write(to_file, buffer, nCount); if( written < 0 ) throw Exception(0, @@ -182,17 +185,13 @@ static void _copy(Request& r, MethodPara String from_spec = r.absolute(vfrom_file_name.as_string()); const String& to_spec = r.absolute(vto_file_name.as_string()); - create_dir_for_file(to_spec); + // create_dir_for_file(to_spec); file_write_action_under_lock( to_spec, "copy", copy_open_target, - &from_spec, - false/*as_text*/, - false/*do_append*/, - true/*block*/, - true/*fail on lock problem*/ ); + &from_spec); } static void _load_pass_param( @@ -203,7 +202,7 @@ static void _load_pass_param( } static void _load(Request& r, MethodParams& params) { Value& vmode_name=params. as_no_junction(0, "mode must not be code"); - const String& lfile_name=r.absolute(params.as_no_junction(1, "file name must not be code").as_string()); + const String& lfile_name=r.absolute(params.as_no_junction(1, FILE_NAME_MUST_NOT_BE_CODE).as_string()); Value* third_param=params.count()>2?¶ms.as_no_junction(2, "filename or options must not be code") :0; HashStringValue* third_param_hash=third_param?third_param->get_hash():0; @@ -230,7 +229,7 @@ static void _load(Request& r, MethodPara ); const char *user_file_name=params.count()>alt_filename_param_index? - params.as_string(alt_filename_param_index, "filename must be string").cstr() + params.as_string(alt_filename_param_index, FILE_NAME_MUST_BE_STRING).cstr() :lfile_name.cstr(String::L_FILE_SPEC); Value* vcontent_type=0; @@ -256,7 +255,7 @@ static void _create(Request& r, MethodPa "only text mode is currently supported"); const char* user_file_name_cstr=r.absolute( - params.as_no_junction(1, "file name must not be code").as_string()).cstr(String::L_FILE_SPEC); + params.as_no_junction(1, FILE_NAME_MUST_NOT_BE_CODE).as_string()).cstr(String::L_FILE_SPEC); const String& content=params.as_string(2, "content must be string"); const char* content_cstr=content.cstr(String::L_UNSPECIFIED); // explode content, honor tainting changes @@ -268,7 +267,7 @@ static void _create(Request& r, MethodPa } static void _stat(Request& r, MethodParams& params) { - Value& vfile_name=params.as_no_junction(0, "file name must not be code"); + Value& vfile_name=params.as_no_junction(0, FILE_NAME_MUST_NOT_BE_CODE); const String& lfile_name=vfile_name.as_string(); @@ -350,7 +349,7 @@ static void pass_cgi_header_attribute( static void _exec_cgi(Request& r, MethodParams& params, bool cgi) { - Value& vfile_name=params.as_no_junction(0, "file name must not be code"); + Value& vfile_name=params.as_no_junction(0, FILE_NAME_MUST_NOT_BE_CODE); const String& script_name=r.absolute(vfile_name.as_string()); @@ -429,10 +428,27 @@ static void _exec_cgi(Request& r, Method // influence tainting // main target -- URLencoding of tainted pieces to String::L_URI lang Temp_client_charset temp(r.charsets, charset? *charset: r.charsets.source()); + for(size_t i=2; i 0) { - argv+=new String(param.cstr_to_string_body(String::L_UNSPECIFIED, 0, &r.charsets), String::L_AS_IS); + Value& param=params.as_no_junction(i, "parameter must not be code"); + if(param.is_defined()){ + if(param.is_string()){ + const String& pstring=*param.get_string(); + if(pstring.length() > 0) { + argv+=new String(pstring.cstr_to_string_body(String::L_UNSPECIFIED, 0, &r.charsets), String::L_AS_IS); + } + } else { + Table* ptable=param.get_table(); + if(ptable){ + for(size_t i=0; icount(); i++) { + argv+=new String(ptable->get(i)->get(0)->cstr_to_string_body(String::L_UNSPECIFIED, 0, &r.charsets), String::L_AS_IS); + } + } else { + throw Exception("parser.runtime", + 0, + "parameter must be string or table"); + } + } } } } @@ -615,7 +631,7 @@ static void lock_execute_body(int , void info.r->write_assign_lang(info.r->process(*info.body_code)); }; static void _lock(Request& r, MethodParams& params) { - const String& file_spec=r.absolute(params.as_string(0, "file name must be string")); + const String& file_spec=r.absolute(params.as_string(0, FILE_NAME_MUST_BE_STRING)); Lock_execute_body_info info={ &r, ¶ms.as_junction(1, "body must be code") @@ -640,7 +656,7 @@ static int lastposafter(const String& s, } static void _find(Request& r, MethodParams& params) { - const String& file_name=params.as_no_junction(0, "file name must not be code").as_string(); + const String& file_name=params.as_no_junction(0, FILE_NAME_MUST_NOT_BE_CODE).as_string(); const String* file_spec; if(file_name.first_char()=='/') file_spec=&file_name; @@ -677,7 +693,7 @@ static void _find(Request& r, MethodPara } static void _dirname(Request& r, MethodParams& params) { - const String& file_spec=params.as_string(0, "file name must be string"); + const String& file_spec=params.as_string(0, FILE_NAME_MUST_BE_STRING); // /a/some.tar.gz > /a // /a/b/ > /a int afterslash=lastposafter(file_spec, 0, "/", 1, true); @@ -688,21 +704,21 @@ static void _dirname(Request& r, MethodP } static void _basename(Request& r, MethodParams& params) { - const String& file_spec=params.as_string(0, "file name must be string"); + const String& file_spec=params.as_string(0, FILE_NAME_MUST_BE_STRING); // /a/some.tar.gz > some.tar.gz int afterslash=lastposafter(file_spec, 0, "/", 1); r.write_assign_lang(file_spec.mid(afterslash, file_spec.length())); } static void _justname(Request& r, MethodParams& params) { - const String& file_spec=params.as_string(0, "file name must be string"); + const String& file_spec=params.as_string(0, FILE_NAME_MUST_BE_STRING); // /a/some.tar.gz > some.tar int afterslash=lastposafter(file_spec, 0, "/", 1); int afterdot=lastposafter(file_spec, afterslash, ".", 1); r.write_assign_lang(file_spec.mid(afterslash, afterdot!=afterslash?afterdot-1:file_spec.length())); } static void _justext(Request& r, MethodParams& params) { - const String& file_spec=params.as_string(0, "file name must be string"); + const String& file_spec=params.as_string(0, FILE_NAME_MUST_BE_STRING); // /a/some.tar.gz > gz int afterdot=lastposafter(file_spec, 0, ".", 1); if(afterdot>0) @@ -710,7 +726,7 @@ static void _justext(Request& r, MethodP } static void _fullpath(Request& r, MethodParams& params) { - const String& file_spec=params.as_string(0, "file name must be string"); + const String& file_spec=params.as_string(0, FILE_NAME_MUST_BE_STRING); const String* result; if(file_spec.first_char()=='/') result=&file_spec; @@ -841,6 +857,8 @@ static void _sql(Request& r, MethodParam } static void _base64(Request& r, MethodParams& params) { + bool dynamic = !(&r.get_self() == file_class); + if ( dynamic ){ VFile& self=GET_SELF(r, VFile); if(params.count()) { // decode @@ -855,6 +873,12 @@ static void _base64(Request& r, MethodPa const char* encoded=pa_base64_encode(self.value_ptr(), self.value_size()); r.write_assign_lang(*new String(encoded, 0, true/*once ?param=base64(something) was needed*/)); } + } else { + // encode + const String& file_spec=params.as_string(0, FILE_NAME_MUST_BE_STRING); + const char* encoded=pa_base64_encode(r.absolute(file_spec)); + r.write_assign_lang(*new String(encoded, 0, true/*once ?param=base64(something) was needed*/)); + } } static void _crc32(Request& r, MethodParams& params) { @@ -862,7 +886,7 @@ static void _crc32(Request& r, MethodPar if(&r.get_self() == file_class) { // ^file:crc32[file-name] if(params.count()) { - const String& file_spec=params.as_string(0, "file name must be string"); + const String& file_spec=params.as_string(0, FILE_NAME_MUST_BE_STRING); crc32=pa_crc32(r.absolute(file_spec)); } else { throw Exception("parser.runtime", @@ -889,7 +913,7 @@ static void file_md5_file_action( int nCount=0; do { unsigned char buffer[FILE_BUFFER_SIZE]; - nCount = read(f, buffer, sizeof(buffer)); + nCount = file_block_read(f, buffer, sizeof(buffer)); if ( nCount ){ pa_MD5Update(&md5context, (const unsigned char*)buffer, nCount); } @@ -924,7 +948,7 @@ static void _md5(Request& r, MethodParam if(&r.get_self() == file_class) { // ^file:md5[file-name] if(params.count()) { - const String& file_spec=params.as_string(0, "file name must be string"); + const String& file_spec=params.as_string(0, FILE_NAME_MUST_BE_STRING); md5=pa_md5(r.absolute(file_spec)); } else { throw Exception("parser.runtime", @@ -1004,7 +1028,8 @@ MFile::MFile(): Methoded("file") { // ^file::base64[string] << decode // ^file.base64[] << encode - add_native_method("base64", Method::CT_DYNAMIC, _base64, 0, 1); + // ^file:base64[file-name] << encode + add_native_method("base64", Method::CT_ANY, _base64, 0, 1); // ^file.crc32[] // ^file:crc32[file-name]