--- parser3/src/main/pa_common.C 2009/08/05 08:57:27 1.248 +++ parser3/src/main/pa_common.C 2010/04/19 19:35:55 1.257 @@ -26,7 +26,7 @@ * */ -static const char * const IDENT_COMMON_C="$Date: 2009/08/05 08:57:27 $"; +static const char * const IDENT_COMMON_C="$Date: 2010/04/19 19:35:55 $"; #include "pa_common.h" #include "pa_exception.h" @@ -67,6 +67,31 @@ const String file_status_name(FILE_STATU // functions +bool capitalized(const char* s){ + bool upper=true; + for(const char* c=s; *c; c++){ + if(*c != (upper ? toupper((unsigned char)*c) : tolower((unsigned char)*c))) + return false; + upper=strchr("-_ ", *c) != 0; + } + return true; +} + +const char* capitalize(const char* s){ + if(!s || capitalized(s)) + return s; + + char* result=pa_strdup(s); + if(result){ + bool upper=true; + for(char* c=result; *c; c++){ + *c=upper ? (char)toupper((unsigned char)*c) : (char)tolower((unsigned char)*c); + upper=strchr("-_ ", *c) != 0; + } + } + return (const char*)result; +} + void fix_line_breaks(char *str, size_t& length) { //_asm int 3; const char* const eob=str+length; @@ -150,7 +175,7 @@ static void file_read_action( lseek(f, info.offset, SEEK_SET); *info.data=info.buf ? info.buf - : new(PointerFreeGC) char[to_read_size+(as_text?1:0)]; + : (char *)pa_malloc_atomic(to_read_size+1); *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) @@ -160,7 +185,7 @@ static void file_read_action( *info.data_size, to_read_size); } else { // empty file // for both, text and binary: for text we need that terminator, for binary we need nonzero pointer to be able to save such files - *info.data=new(PointerFreeGC) char[1]; + *info.data=(char *)pa_malloc_atomic(1); *(char*)(*info.data)=0; *info.data_size=0; return; @@ -177,7 +202,7 @@ File_read_result file_read(Request_chars if(valid_options!=params->count()) throw Exception(PARSER_RUNTIME, 0, - "invalid option passed"); + INVALID_OPTION_PASSED); } File_read_action_info info={&result.str, &result.length, buf, offset, count}; @@ -239,8 +264,9 @@ File_read_result file_load(Request& r, c return result; } -#ifdef PA_SAFE_MODE + void check_safe_mode(struct stat finfo, const String& file_spec, const char* fname) { +#ifdef PA_SAFE_MODE if(finfo.st_uid/*foreign?*/!=geteuid() && finfo.st_gid/*foreign?*/!=getegid()) throw Exception(PARSER_RUNTIME, @@ -253,8 +279,9 @@ void check_safe_mode(struct stat finfo, fname, finfo.st_uid, geteuid(), finfo.st_gid, getegid()); +#endif } -#endif + bool file_read_action_under_lock(const String& file_spec, const char* action_name, File_read_action action, void *context, @@ -281,15 +308,13 @@ bool file_read_action_under_lock(const S strerror(errno), errno, fname); struct stat finfo; - if(stat(fname, &finfo)!=0) + if(fstat(f, &finfo)!=0) throw Exception("file.missing", // hardly possible: we just opened it OK &file_spec, "stat failed: %s (%d), actual filename '%s'", strerror(errno), errno, fname); -#ifdef PA_SAFE_MODE check_safe_mode(finfo, file_spec, fname); -#endif action(finfo, f, file_spec, fname, as_text, context); } catch(...) { @@ -303,7 +328,8 @@ bool file_read_action_under_lock(const S return true; } else { if(fail_on_read_problem) - throw Exception(errno==EACCES?"file.access":errno==ENOENT?"file.missing":0, + throw Exception(errno==EACCES?"file.access" + :(errno==ENOENT || errno==ENOTDIR || errno==ENODEV)?"file.missing":0, &file_spec, "%s failed: %s (%d), actual filename '%s'", action_name, strerror(errno), errno, fname); @@ -350,7 +376,12 @@ bool file_write_action_under_lock( } try { - action(f, context); +#if (defined(HAVE_FCHMOD) && defined(PA_SAFE_MODE)) + struct stat finfo; + if(fstat(f, &finfo)==0 && finfo.st_mode & 0111) + fchmod(f, finfo.st_mode & 0666/*clear executable bits*/); // backward: ignore errors if any +#endif + action(f, context); } catch(...) { #ifdef HAVE_FTRUNCATE if(!do_append) @@ -376,7 +407,8 @@ bool file_write_action_under_lock( #ifndef DOXYGEN struct File_write_action_info { - const char* str; size_t length; + const char* str; + size_t length; }; #endif static void file_write_action(int f, void *context) { @@ -390,10 +422,21 @@ static void file_write_action(int f, voi } } void file_write( - const String& file_spec, - const char* data, size_t size, + Request_charsets& charsets, + const String& file_spec, + const char* data, + size_t size, bool as_text, - bool do_append) { + bool do_append, + Charset* asked_charset) { + + if(as_text && asked_charset){ + String::C body=String::C(data, size); + body=Charset::transcode(body, charsets.source(), *asked_charset); + data=body.str; + size=body.length; + }; + File_write_action_info info={data, size}; file_write_action_under_lock( @@ -969,6 +1012,9 @@ static char *base64_alphabet = * * Returns the number of bytes encoded. **/ + +#define BASE64_GROUPS_IN_LINE 19 + static size_t g_mime_utils_base64_encode_step (const unsigned char *in, size_t inlen, unsigned char *out, int *state, int *save) { @@ -1006,7 +1052,7 @@ g_mime_utils_base64_encode_step (const u *outptr++ = base64_alphabet [((c2 & 0x0f) << 2) | (c3 >> 6)]; *outptr++ = base64_alphabet [c3 & 0x3f]; /* this is a bit ugly ... */ - if ((++already) >= 19) { + if ((++already) >= BASE64_GROUPS_IN_LINE) { *outptr++ = '\n'; already = 0; } @@ -1172,16 +1218,18 @@ g_mime_utils_base64_decode_step (const u 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]; + size_t new_size = ((in_size / 3 + 1) * 4); + new_size += new_size / (BASE64_GROUPS_IN_LINE * 4)/*new lines*/ + 1/*zero terminator*/; + char* result = new(PointerFreeGC) char[new_size]; int state=0; int save=0; #ifndef NDEBUG size_t filled= #endif - g_mime_utils_base64_encode_close ((const unsigned char*)in, in_size, - (unsigned char*)result, &state, &save); - assert(filled <= in_size * 2 + 6); + g_mime_utils_base64_encode_close ((const unsigned char*)in, in_size, (unsigned char*)result, &state, &save); + + //throw Exception(PARSER_RUNTIME, 0, "%d %d %d", in_size, new_size, filled); + assert(filled <= new_size); return result; }