--- parser3/src/main/pa_common.C 2006/02/03 15:08:04 1.217 +++ parser3/src/main/pa_common.C 2008/02/13 16:03:05 1.227 @@ -26,7 +26,7 @@ * */ -static const char * const IDENT_COMMON_C="$Date: 2006/02/03 15:08:04 $"; +static const char * const IDENT_COMMON_C="$Date: 2008/02/13 16:03:05 $"; #include "pa_common.h" #include "pa_exception.h" @@ -34,6 +34,7 @@ static const char * const IDENT_COMMON_C #include "pa_globals.h" #include "pa_charsets.h" #include "pa_http.h" +#include "pa_request_charsets.h" // some maybe-undefined constants @@ -111,6 +112,8 @@ int pa_get_valid_file_options_count(Hash result++; if(options.get(PA_COLUMN_ENCLOSER_NAME)) result++; + if(options.get(PA_CHARSET_NAME)) + result++; return result; } @@ -158,7 +161,7 @@ File_read_result file_read(Request_chars File_read_result result={false, 0, 0, 0}; if(file_spec.starts_with("http://")) { if(offset || count) - throw Exception("parser.runtime", + throw Exception(PARSER_RUNTIME, 0, "offset and load options are not supported for HTTP:// file load"); @@ -172,7 +175,7 @@ File_read_result file_read(Request_chars if(params) { int valid_options=pa_get_valid_file_options_count(*params); if(valid_options!=params->count()) - throw Exception("parser.runtime", + throw Exception(PARSER_RUNTIME, 0, "invalid option passed"); } @@ -182,6 +185,19 @@ File_read_result file_read(Request_chars result.success=file_read_action_under_lock(file_spec, "read", file_read_action, &info, as_text, fail_on_read_problem); + + if(result.length && as_text && params) { + 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)); + + String::C body=String::C(result.str, result.length); + body=Charset::transcode(body, asked_charset, charsets.source()); + + result.str=const_cast(body.str); // hacking a little + result.length=body.length; + } + } } if(result.success && as_text) { @@ -203,7 +219,7 @@ File_read_result file_read(Request_chars void check_safe_mode(struct stat finfo, const String& file_spec, const char* fname) { if(finfo.st_uid/*foreign?*/!=geteuid() && finfo.st_gid/*foreign?*/!=getegid()) - throw Exception("parser.runtime", + throw Exception(PARSER_RUNTIME, &file_spec, "parser is in safe mode: " "reading files of foreign group and user disabled " @@ -282,7 +298,9 @@ void create_dir_for_file(const String& f bool file_write_action_under_lock( const String& file_spec, - const char* action_name, File_write_action action, void *context, + const char* action_name, + File_write_action action, + void *context, bool as_text, bool do_append, bool do_block, @@ -353,9 +371,12 @@ void file_write( bool as_text, bool do_append) { File_write_action_info info={data, size}; + file_write_action_under_lock( file_spec, - "write", file_write_action, &info, + "write", + file_write_action, + &info, as_text, do_append); } @@ -627,9 +648,9 @@ static bool isLeap(int year) { } int getMonthDays(int year, int month) { - int monthDays[]={ + static int monthDays[]={ 31, - isLeap(year) ? 29 : 28, + 28, 31, 30, 31, @@ -641,15 +662,34 @@ int getMonthDays(int year, int month) { 30, 31 }; - return monthDays[month]; + return (month == 1 && isLeap(year)) ? 29 : monthDays[month]; } -void remove_crlf(char* start, char* end) { - for(char* p=start; p(context); + *info.base64=new(PointerFreeGC) unsigned char[finfo.st_size * 2 + 6]; + unsigned char* base64 = *info.base64; + int state=0; + int save=0; + int nCount; + do { + unsigned char buffer[FILE_BUFFER_SIZE]; + nCount = file_block_read(f, buffer, sizeof(buffer)); + if( nCount ){ + size_t filled=g_mime_utils_base64_encode_step ((const unsigned char*)buffer, nCount, base64, &state, &save); + base64+=filled; + } + } while(nCount > 0); + g_mime_utils_base64_encode_close (0, 0, base64, &state, &save); + } +} + 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) */ @@ -978,3 +1056,49 @@ void pa_base64_decode(const char *in, si assert(result_size <= in_size); result[result_size]=0; // for text files } + + +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, + 0, + "read failed: %s (%d)", strerror(errno), errno); + return nCount; +} + +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); + + return ~crc32; +} + +const unsigned long pa_crc32(const String& file_spec) +{ + unsigned long crc32=0xFFFFFFFF; + file_read_action_under_lock(file_spec, "crc32", file_crc32_file_action, &crc32); + return ~crc32; +} + +static void file_crc32_file_action( + struct stat& finfo, + int f, + const String&, const char* /*fname*/, bool, + void *context) +{ + unsigned long& crc32=*static_cast(context); + if(finfo.st_size) { + InitCrc32Table(); + int nCount=0; + do { + unsigned char buffer[FILE_BUFFER_SIZE]; + nCount = file_block_read(f, buffer, sizeof(buffer)); + for(int i = 0; i < nCount; i++) CalcCrc32(buffer[i], crc32); + } while(nCount > 0); + } +} +