--- parser3/src/main/pa_common.C 2008/09/04 09:37:00 1.238 +++ parser3/src/main/pa_common.C 2009/08/05 08:57:27 1.248 @@ -1,7 +1,7 @@ /** @file Parser: commonly functions. - Copyright(c) 2001-2005 ArtLebedev Group (http://www.artlebedev.com) + Copyright(c) 2001-2009 ArtLebedev Group (http://www.artlebedev.com) Author: Alexandr Petrosian (http://paf.design.ru) * BASE64 part @@ -26,7 +26,7 @@ * */ -static const char * const IDENT_COMMON_C="$Date: 2008/09/04 09:37:00 $"; +static const char * const IDENT_COMMON_C="$Date: 2009/08/05 08:57:27 $"; #include "pa_common.h" #include "pa_exception.h" @@ -36,6 +36,7 @@ static const char * const IDENT_COMMON_C #include "pa_http.h" #include "pa_request_charsets.h" #include "pcre.h" +#include "pa_request.h" // some maybe-undefined constants @@ -102,9 +103,18 @@ char* file_read_text(Request_charsets& c return file.success?file.str:0; } +char* file_load_text(Request& r, + const String& file_spec, + bool fail_on_read_problem, + HashStringValue* params, + bool transcode_result) { + File_read_result file= + file_load(r, file_spec, true, params, fail_on_read_problem, 0, 0, 0, transcode_result); + return file.success?file.str:0; +} + /// these options were handled but not checked elsewhere, now check them -int pa_get_valid_file_options_count(HashStringValue& options) -{ +int pa_get_valid_file_options_count(HashStringValue& options) { int result=0; if(options.get(PA_SQL_LIMIT_NAME)) result++; @@ -156,47 +166,36 @@ static void file_read_action( return; } } + File_read_result file_read(Request_charsets& charsets, const String& file_spec, bool as_text, HashStringValue *params, bool fail_on_read_problem, char* buf, size_t offset, size_t count, bool transcode_text_result) { File_read_result result={false, 0, 0, 0}; - if(file_spec.starts_with("http://")) { - if(offset || count) + if(params){ + int valid_options=pa_get_valid_file_options_count(*params); + if(valid_options!=params->count()) throw Exception(PARSER_RUNTIME, 0, - "offset and load options are not supported for HTTP:// file load"); + "invalid option passed"); + } - // fail on read problem - File_read_http_result http=pa_internal_file_read_http(charsets, file_spec, as_text, params, transcode_text_result); - result.success=true; - result.str=http.str; - result.length=http.length; - result.headers=http.headers; - } else { - if(params){ - int valid_options=pa_get_valid_file_options_count(*params); - if(valid_options!=params->count()) - throw Exception(PARSER_RUNTIME, - 0, - "invalid option passed"); - } + File_read_action_info info={&result.str, &result.length, buf, offset, count}; - File_read_action_info info={&result.str, &result.length, - buf, offset, count}; - result.success=file_read_action_under_lock(file_spec, - "read", file_read_action, &info, - as_text, fail_on_read_problem); + result.success=file_read_action_under_lock(file_spec, + "read", file_read_action, &info, + as_text, fail_on_read_problem); - if(as_text && result.success){ + if(as_text){ + if(result.success){ if(result.length>=3 && strncmp(result.str, "\xEF\xBB\xBF", 3)==0){ - // skip UTF-8 signature: EF BB BF (BOM code) + // skip UTF-8 signature (BOM code) result.str+=3; result.length-=3; } if(result.length && transcode_text_result && params){ // must be checked because transcode returns CONST string in case length==0, which contradicts hacking few lines below - if( Value* vcharset_name=params->get(PA_CHARSET_NAME) ){ + if(Value* vcharset_name=params->get(PA_CHARSET_NAME)){ Charset asked_charset=::charsets.get(vcharset_name->as_string(). change_case(charsets.source(), String::CC_UPPER)); @@ -208,10 +207,34 @@ File_read_result file_read(Request_chars } } } + if(result.length) + fix_line_breaks(result.str, result.length); } - - if(as_text && result.length) - fix_line_breaks(result.str, result.length); + + return result; +} + +File_read_result file_load(Request& r, const String& file_spec, + bool as_text, HashStringValue *params, + bool fail_on_read_problem, + char* buf, size_t offset, size_t count, bool transcode_text_result) { + + File_read_result result={false, 0, 0, 0}; + if(file_spec.starts_with("http://")) { + if(offset || count) + throw Exception(PARSER_RUNTIME, + 0, + "offset and load options are not supported for HTTP:// file load"); + + // fail on read problem + File_read_http_result http=pa_internal_file_read_http(r, file_spec, as_text, params, transcode_text_result); + result.success=true; + result.str=http.str; + result.length=http.length; + result.headers=http.headers; + } else + result= + file_read(r.charsets, file_spec, as_text, params, fail_on_read_problem, buf, offset, count, transcode_text_result); return result; } @@ -237,7 +260,7 @@ bool file_read_action_under_lock(const S const char* action_name, File_read_action action, void *context, bool as_text, bool fail_on_read_problem) { - const char* fname=file_spec.cstr(String::L_FILE_SPEC); + const char* fname=file_spec.taint_cstr(String::L_FILE_SPEC); int f; // first open, next stat: @@ -292,7 +315,7 @@ void create_dir_for_file(const String& f size_t pos_after=1; size_t pos_before; while((pos_before=file_spec.pos('/', pos_after))!=STRING_NOT_FOUND) { - mkdir(file_spec.mid(0, pos_before).cstr(String::L_FILE_SPEC), 0775); + mkdir(file_spec.mid(0, pos_before).taint_cstr(String::L_FILE_SPEC), 0775); pos_after=pos_before+1; } } @@ -306,7 +329,7 @@ bool file_write_action_under_lock( bool do_append, bool do_block, bool fail_on_lock_problem) { - const char* fname=file_spec.cstr(String::L_FILE_SPEC); + const char* fname=file_spec.taint_cstr(String::L_FILE_SPEC); int f; if(access(fname, W_OK)!=0) // no create_dir_for_file(file_spec); @@ -388,10 +411,11 @@ static void rmdir(const String& file_spe if((pos_before=file_spec.pos('/', pos_after))!=STRING_NOT_FOUND) rmdir(file_spec, pos_before+1); - rmdir(file_spec.mid(0, pos_after-1/* / */).cstr(String::L_FILE_SPEC)); + rmdir(file_spec.mid(0, pos_after-1/* / */).taint_cstr(String::L_FILE_SPEC)); } + bool file_delete(const String& file_spec, bool fail_on_problem) { - const char* fname=file_spec.cstr(String::L_FILE_SPEC); + const char* fname=file_spec.taint_cstr(String::L_FILE_SPEC); if(unlink(fname)!=0) if(fail_on_problem) throw Exception(errno==EACCES?"file.access":errno==ENOENT?"file.missing":0, @@ -404,9 +428,10 @@ bool file_delete(const String& file_spec rmdir(file_spec, 1); return true; } + void file_move(const String& old_spec, const String& new_spec) { - const char* old_spec_cstr=old_spec.cstr(String::L_FILE_SPEC); - const char* new_spec_cstr=new_spec.cstr(String::L_FILE_SPEC); + const char* old_spec_cstr=old_spec.taint_cstr(String::L_FILE_SPEC); + const char* new_spec_cstr=new_spec.taint_cstr(String::L_FILE_SPEC); create_dir_for_file(new_spec); @@ -429,12 +454,12 @@ bool entry_exists(const char* fname, str } bool entry_exists(const String& file_spec) { - const char* fname=file_spec.cstr(String::L_FILE_SPEC); + const char* fname=file_spec.taint_cstr(String::L_FILE_SPEC); return entry_exists(fname, 0); } static bool entry_readable(const String& file_spec, bool need_dir) { - char* fname=file_spec.cstrm(String::L_FILE_SPEC); + char* fname=file_spec.taint_cstrm(String::L_FILE_SPEC); if(need_dir) { size_t size=strlen(fname); while(size) { @@ -452,20 +477,24 @@ static bool entry_readable(const String& } return false; } + bool file_exist(const String& file_spec) { return entry_readable(file_spec, false); } + bool dir_exists(const String& file_spec) { return entry_readable(file_spec, true); } + const String* file_exist(const String& path, const String& name) { String& result=*new String(path); result << "/"; result << name; return file_exist(result)?&result:0; } + bool file_executable(const String& file_spec) { - return access(file_spec.cstr(String::L_FILE_SPEC), X_OK)==0; + return access(file_spec.taint_cstr(String::L_FILE_SPEC), X_OK)==0; } bool file_stat(const String& file_spec, @@ -474,7 +503,7 @@ bool file_stat(const String& file_spec, time_t& rmtime, time_t& rctime, bool fail_on_read_problem) { - const char* fname=file_spec.cstr(String::L_FILE_SPEC); + const char* fname=file_spec.taint_cstr(String::L_FILE_SPEC); struct stat finfo; if(stat(fname, &finfo)!=0) if(fail_on_read_problem) @@ -767,9 +796,8 @@ size_t strpos(const char *str, const cha // content-type: xxx; charset="WE-NEED-THIS"; Charset* detect_charset(const char* content_type){ if(content_type){ - size_t len=strlen(content_type); - char* CONTENT_TYPE=new(PointerFreeGC) char[len+1]; - memcpy(CONTENT_TYPE, content_type, len); + char* CONTENT_TYPE=pa_strdup(content_type); + for(char *p=CONTENT_TYPE; *p; p++) *p=(char)toupper((unsigned char)*p); @@ -784,48 +812,15 @@ Charset* detect_charset(const char* cont if(!end) end=(char*)strchr(begin, ';'); - size_t len; - if(end){ + if(end) *end=0; // terminator - len=end-begin; - } else { - len=strlen(begin); - } - String::Body NAME=String::Body(begin, len); - return &charsets.get(NAME); + return *begin?&charsets.get(begin):0; } } return 0; } -Charset* detect_charset(Charset& source_charset, const String& content_type){ - const String& CONTENT_TYPE=content_type.change_case(source_charset, String::CC_UPPER); - size_t begin=CONTENT_TYPE.pos("CHARSET="); - if(begin!=STRING_NOT_FOUND) { - begin+=8; // skip "CHARSET=" - size_t end=STRING_NOT_FOUND; - - if(CONTENT_TYPE.pos('"', begin)==begin){ - begin++; - end=CONTENT_TYPE.pos('"', begin); - } else if(CONTENT_TYPE.pos('\'', begin)==begin){ - begin++; - end=CONTENT_TYPE.pos('\'', begin); - } - - if(end==STRING_NOT_FOUND) - end=CONTENT_TYPE.pos(';', begin); - - if(end==STRING_NOT_FOUND) - end=CONTENT_TYPE.length(); - - const String::Body NAME=CONTENT_TYPE.mid(begin, end); - return &charsets.get(NAME); - } - return 0; -} - static bool isLeap(int year) { return !( @@ -928,9 +923,9 @@ int __vsnprintf(char* b, size_t s, const int __snprintf(char* b, size_t s, const char* f, ...) { va_list l; - va_start(l, f); - int r=__vsnprintf(b, s, f, l); - va_end(l); + va_start(l, f); + int r=__vsnprintf(b, s, f, l); + va_end(l); return r; } @@ -1176,8 +1171,7 @@ g_mime_utils_base64_decode_step (const u } -char* pa_base64_encode(const char *in, size_t in_size) -{ +char* pa_base64_encode(const char *in, size_t in_size){ /* wont go to more than 2x size (overly conservative) */ char* result=new(PointerFreeGC) char[in_size * 2 + 6]; int state=0; @@ -1193,8 +1187,7 @@ char* pa_base64_encode(const char *in, s } -char* pa_base64_encode(const String& file_spec) -{ +char* pa_base64_encode(const String& file_spec){ unsigned char* base64=0; File_base64_action_info info={&base64}; @@ -1230,8 +1223,7 @@ static void file_base64_file_action( } } -void pa_base64_decode(const char *in, size_t in_size, char*& result, size_t& result_size) -{ +void pa_base64_decode(const char *in, size_t in_size, char*& result, size_t& result_size) { /* wont go to more than had (overly conservative) */ result=new(PointerFreeGC) char[in_size+1/*terminator*/]; int state=0; @@ -1253,18 +1245,17 @@ int file_block_read(const int f, unsigne return nCount; } -const unsigned long pa_crc32(const char *in, size_t in_size) -{ +const unsigned long pa_crc32(const char *in, size_t in_size){ unsigned long crc32=0xFFFFFFFF; - InitCrc32Table(); - for(size_t i = 0; i < in_size; i++) CalcCrc32(in[i], crc32); + InitCrc32Table(); + for(size_t i = 0; i(context); if(finfo.st_size) { InitCrc32Table(); @@ -1288,13 +1278,3 @@ static void file_crc32_file_action( } } -char* print_pcre_exec_error_text(int exec_result){ - switch(exec_result){ - case PCRE_ERROR_BADUTF8: - return "validation of UTF-8 string failed while pcre_exec (%d)."; - break; - default: - return "regular expression execute error (%d)"; - } -} -