--- parser3/src/main/pa_common.C 2008/08/21 15:57:48 1.237 +++ parser3/src/main/pa_common.C 2009/05/26 10:44:33 1.245 @@ -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/08/21 15:57:48 $"; +static const char * const IDENT_COMMON_C="$Date: 2009/05/26 10:44:33 $"; #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++; @@ -144,7 +154,7 @@ static void file_read_action( *info.data_size=(size_t)read(f, *info.data, to_read_size); if(ssize_t(*info.data_size)<0 || *info.data_size>to_read_size) - throw Exception(0, + throw Exception("file.read", &file_spec, "read failed: actually read %u bytes count not in [0..%u] valid range", *info.data_size, to_read_size); @@ -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; } @@ -361,7 +384,7 @@ static void file_write_action(int f, voi if(info.length) { int written=write(f, info.str, info.length); if(written<0) - throw Exception(0, + throw Exception("file.access", 0, "write failed: %s (%d)", strerror(errno), errno); } @@ -390,6 +413,7 @@ static void rmdir(const String& file_spe rmdir(file_spec.mid(0, pos_after-1/* / */).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); if(unlink(fname)!=0) @@ -404,6 +428,7 @@ 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); @@ -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.cstr(String::L_FILE_SPEC), X_OK)==0; } bool file_stat(const String& file_spec, @@ -765,13 +794,12 @@ size_t strpos(const char *str, const cha // content-type: xxx; charset=WE-NEED-THIS // content-type: xxx; charset="WE-NEED-THIS" // content-type: xxx; charset="WE-NEED-THIS"; -Charset* detect_charset(const char* content_type){ +Charset* detect_charset(const char* content_type, bool already_uppercased){ if(content_type){ - size_t len=strlen(content_type); - char* CONTENT_TYPE=new(PointerFreeGC) char[len+1]; - memcpy(CONTENT_TYPE, content_type, len); - for(char *p=CONTENT_TYPE; *p; p++) - *p=(char)toupper((unsigned char)*p); + char* CONTENT_TYPE=pa_strdup(content_type); + if(!already_uppercased) + for(char *p=CONTENT_TYPE; *p; p++) + *p=(char)toupper((unsigned char)*p); if(const char* begin=strstr(CONTENT_TYPE, "CHARSET=")){ begin+=8; // skip "CHARSET=" @@ -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; @@ -1247,24 +1239,23 @@ void pa_base64_decode(const char *in, si int file_block_read(const int f, unsigned char* buffer, const size_t size){ int nCount = read(f, buffer, size); if (nCount < 0) - throw Exception(0, + throw Exception("file.read", 0, "read failed: %s (%d)", strerror(errno), errno); 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)"; - } -} -