--- parser3/src/main/pa_common.C 2005/11/24 13:50:29 1.204.6.9 +++ parser3/src/main/pa_common.C 2007/04/23 10:30:31 1.224 @@ -24,9 +24,9 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. * -*/ + */ -static const char * const IDENT_COMMON_C="$Date: 2005/11/24 13:50:29 $"; +static const char * const IDENT_COMMON_C="$Date: 2007/04/23 10:30:31 $"; #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 " @@ -430,17 +446,17 @@ static bool entry_readable(const String& } return false; } -bool file_readable(const String& file_spec) { +bool file_exist(const String& file_spec) { return entry_readable(file_spec, false); } -bool dir_readable(const String& file_spec) { +bool dir_exists(const String& file_spec) { return entry_readable(file_spec, true); } -const String* file_readable(const String& path, const String& name) { +const String* file_exist(const String& path, const String& name) { String& result=*new String(path); result << "/"; result << name; - return file_readable(result)?&result:0; + 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; @@ -553,7 +569,7 @@ char* unescape_chars(const char* cp, int EscapeFirst, EscapeSecond } escapeState=EscapeRest; - uchar escapedValue=0; + uint escapedValue=0; int srcPos=0; int dstPos=0; while(srcPos < len) { @@ -569,12 +585,12 @@ char* unescape_chars(const char* cp, int } break; case EscapeFirst: - escapedValue=(uchar)(hex_value[ch] << 4); + escapedValue=hex_value[ch] << 4; escapeState=EscapeSecond; break; case EscapeSecond: escapedValue +=hex_value[ch]; - s[dstPos++]=escapedValue; + s[dstPos++]=(char)escapedValue; escapeState=EscapeRest; break; } @@ -627,9 +643,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,7 +657,7 @@ int getMonthDays(int year, int month) { 30, 31 }; - return monthDays[month]; + return (month == 2 && isLeap(year)) ? 29 : monthDays[month]; } void remove_crlf(char* start, char* end) { @@ -809,7 +825,7 @@ g_mime_utils_base64_encode_step (const u case 2: *saveout++ = *inptr++; case 1: *saveout++ = *inptr++; } - ((char *)save)[0] += inlen; + *(char *)save = *(char *)save+(char)inlen; } /*d(printf ("mode = %d\nc1 = %c\nc2 = %c\n", @@ -922,9 +938,9 @@ g_mime_utils_base64_decode_step (const u saved = (saved << 6) | c; i++; if (i == 4) { - *outptr++ = saved >> 16; - *outptr++ = saved >> 8; - *outptr++ = saved; + *outptr++ = (unsigned char)(saved >> 16); + *outptr++ = (unsigned char)(saved >> 8); + *outptr++ = (unsigned char)(saved); i = 0; } } @@ -966,6 +982,44 @@ char* pa_base64_encode(const char *in, s return result; } + +char* pa_base64_encode(const String& file_spec) +{ + unsigned char* base64=0; + File_base64_action_info info={&base64}; + + file_read_action_under_lock(file_spec, + "pa_base64_encode", file_base64_file_action, &info); + + return (char*)base64; +} + + +static void file_base64_file_action( + struct stat& finfo, + int f, + const String&, const char* /*fname*/, bool, + void *context) { + + if(finfo.st_size) { + File_base64_action_info& info=*static_cast(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 +1032,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); + } +} +