|
|
| version 1.296, 2016/12/21 21:14:42 | version 1.301, 2017/02/06 16:17:12 |
|---|---|
| Line 79 volatile const char * IDENT_PA_COMMON_C= | Line 79 volatile const char * IDENT_PA_COMMON_C= |
| const String file_status_name(FILE_STATUS_NAME); | const String file_status_name(FILE_STATUS_NAME); |
| // forwards | |
| const UTF16* pa_utf16_encode(const char* in, Charset& source_charset); | |
| // functions | // functions |
| #ifdef _MSC_VER | |
| int pa_stat(const char *pathname, struct stat *buffer){ | |
| const UTF16* utf16name=pa_utf16_encode(pathname, pa_thread_request().charsets.source()); | |
| return _wstat64((const wchar_t *)utf16name, buffer); | |
| } | |
| int pa_open(const char *pathname, int flags, int mode){ | |
| const UTF16* utf16name=pa_utf16_encode(pathname, pa_thread_request().charsets.source()); | |
| return _wopen((const wchar_t *)utf16name, flags, mode); | |
| } | |
| FILE *pa_fopen(const char *pathname, const char *mode){ | |
| const UTF16* utf16name=pa_utf16_encode(pathname, pa_thread_request().charsets.source()); | |
| const UTF16* utf16mode=pa_utf16_encode(mode, pa_thread_request().charsets.source()); | |
| return _wfopen((const wchar_t *)utf16name, (const wchar_t *)utf16mode); | |
| } | |
| #endif | |
| char* file_read_text(Request_charsets& charsets, const String& file_spec, bool fail_on_read_problem, HashStringValue* params, bool transcode_result) { | char* file_read_text(Request_charsets& charsets, const String& file_spec, bool fail_on_read_problem, HashStringValue* params, bool transcode_result) { |
| File_read_result file=file_read(charsets, file_spec, true, params, fail_on_read_problem, 0, 0, 0, transcode_result); | File_read_result file=file_read(charsets, file_spec, true, params, fail_on_read_problem, 0, 0, 0, transcode_result); |
| return file.success?file.str:0; | return file.success?file.str:0; |
| Line 118 static void file_read_action(struct stat | Line 142 static void file_read_action(struct stat |
| File_read_action_info& info=*static_cast<File_read_action_info *>(context); | File_read_action_info& info=*static_cast<File_read_action_info *>(context); |
| size_t to_read_size=info.count; | size_t to_read_size=info.count; |
| if(!to_read_size) | if(!to_read_size) |
| to_read_size=(size_t)finfo.st_size; | to_read_size=check_file_size(finfo.st_size, file_spec); |
| if(to_read_size) { | if(to_read_size) { |
| if(info.offset) | if(info.offset) |
| lseek(f, info.offset, SEEK_SET); | lseek(f, info.offset, SEEK_SET); |
| Line 234 bool file_read_action_under_lock(const S | Line 258 bool file_read_action_under_lock(const S |
| // they delay update till open, so we would receive "!^test[" string | // they delay update till open, so we would receive "!^test[" string |
| // if would do stat, next open. | // if would do stat, next open. |
| // later: it seems, even this does not help sometimes | // later: it seems, even this does not help sometimes |
| if((f=open(fname, O_RDONLY|(as_text?_O_TEXT:_O_BINARY)))>=0) { | if((f=pa_open(fname, O_RDONLY|(as_text?_O_TEXT:_O_BINARY)))>=0) { |
| try { | try { |
| if(pa_lock_shared_blocking(f)!=0) | if(pa_lock_shared_blocking(f)!=0) |
| throw Exception("file.lock", &file_spec, "shared lock failed: %s (%d), actual filename '%s'", strerror(errno), errno, fname); | throw Exception("file.lock", &file_spec, "shared lock failed: %s (%d), actual filename '%s'", strerror(errno), errno, fname); |
| struct stat finfo; | struct stat finfo; |
| if(fstat(f, &finfo)!=0) | if(pa_fstat(f, &finfo)!=0) |
| throw Exception("file.missing", // hardly possible: we just opened it OK | throw Exception("file.missing", // hardly possible: we just opened it OK |
| &file_spec, "stat failed: %s (%d), actual filename '%s'", strerror(errno), errno, fname); | &file_spec, "stat failed: %s (%d), actual filename '%s'", strerror(errno), errno, fname); |
| Line 287 bool file_write_action_under_lock( | Line 311 bool file_write_action_under_lock( |
| if(access(fname, W_OK)!=0) // no | if(access(fname, W_OK)!=0) // no |
| create_dir_for_file(file_spec); | create_dir_for_file(file_spec); |
| if((f=open(fname, | if((f=pa_open(fname, |
| O_CREAT|O_RDWR | O_CREAT|O_RDWR |
| |(as_text?_O_TEXT:_O_BINARY) | |(as_text?_O_TEXT:_O_BINARY) |
| |(do_append?O_APPEND:PA_O_TRUNC), 0664))>=0) { | |(do_append?O_APPEND:PA_O_TRUNC), 0664))>=0) { |
| Line 302 bool file_write_action_under_lock( | Line 326 bool file_write_action_under_lock( |
| try { | try { |
| #if (defined(HAVE_FCHMOD) && defined(PA_SAFE_MODE)) | #if (defined(HAVE_FCHMOD) && defined(PA_SAFE_MODE)) |
| struct stat finfo; | struct stat finfo; |
| if(fstat(f, &finfo)==0 && finfo.st_mode & 0111) | if(pa_fstat(f, &finfo)==0 && finfo.st_mode & 0111) |
| fchmod(f, finfo.st_mode & 0666/*clear executable bits*/); // backward: ignore errors if any | fchmod(f, finfo.st_mode & 0666/*clear executable bits*/); // backward: ignore errors if any |
| #endif | #endif |
| action(f, context); | action(f, context); |
| Line 462 void file_move(const String& old_spec, c | Line 486 void file_move(const String& old_spec, c |
| bool entry_exists(const char* fname, struct stat *afinfo) { | bool entry_exists(const char* fname, struct stat *afinfo) { |
| struct stat lfinfo; | struct stat lfinfo; |
| bool result=stat(fname, &lfinfo)==0; | bool result=pa_stat(fname, &lfinfo)==0; |
| if(afinfo) | if(afinfo) |
| *afinfo=lfinfo; | *afinfo=lfinfo; |
| return result; | return result; |
| Line 496 bool file_executable(const String& file_ | Line 520 bool file_executable(const String& file_ |
| bool file_stat(const String& file_spec, uint64_t& rsize, time_t& ratime, time_t& rmtime, time_t& rctime, bool fail_on_read_problem) { | bool file_stat(const String& file_spec, uint64_t& rsize, time_t& ratime, time_t& rmtime, time_t& rctime, bool fail_on_read_problem) { |
| const char* fname=file_spec.taint_cstr(String::L_FILE_SPEC); | const char* fname=file_spec.taint_cstr(String::L_FILE_SPEC); |
| struct stat finfo; | struct stat finfo; |
| if(stat(fname, &finfo)!=0) { | if(pa_stat(fname, &finfo)!=0) { |
| if(fail_on_read_problem) | if(fail_on_read_problem) |
| throw Exception("file.missing", &file_spec, "getting file size failed: %s (%d), real filename '%s'", strerror(errno), errno, fname); | throw Exception("file.missing", &file_spec, "getting file size failed: %s (%d), real filename '%s'", strerror(errno), errno, fname); |
| else | else |
| return false; | return false; |
| } | } |
| rsize=finfo.st_size; | rsize=finfo.st_size; |
| ratime=finfo.st_atime; | ratime=(time_t)finfo.st_atime; |
| rmtime=finfo.st_mtime; | rmtime=(time_t)finfo.st_mtime; |
| rctime=finfo.st_ctime; | rctime=(time_t)finfo.st_ctime; |
| return true; | return true; |
| } | } |
| size_t check_file_size(uint64_t size, const String& file_spec){ | |
| if(size > pa_file_size_limit) | |
| throw Exception(PARSER_RUNTIME, &file_spec, "content size of %.15g bytes exceeds the limit (%.15g bytes)", (double)size, (double)pa_file_size_limit); | |
| return (size_t)size; | |
| } | |
| /** | /** |
| String related functions | String related functions |
| */ | */ |
| Line 1163 struct File_base64_action_info { | Line 1193 struct File_base64_action_info { |
| unsigned char** base64; | unsigned char** base64; |
| }; | }; |
| static void file_base64_file_action(struct stat& finfo, int f, const String&, void *context) { | static void file_base64_file_action(struct stat& finfo, int f, const String& file_spec, void *context) { |
| if(finfo.st_size) { | if(finfo.st_size) { |
| File_base64_action_info& info=*static_cast<File_base64_action_info *>(context); | File_base64_action_info& info=*static_cast<File_base64_action_info *>(context); |
| *info.base64=new(PointerFreeGC) unsigned char[finfo.st_size * 2 + 6]; | *info.base64=new(PointerFreeGC) unsigned char[check_file_size(finfo.st_size, file_spec) * 2 + 6]; |
| unsigned char* base64 = *info.base64; | unsigned char* base64 = *info.base64; |
| int state=0; | int state=0; |
| int save=0; | int save=0; |
| Line 1246 inline void CalcCrc32(const unsigned cha | Line 1276 inline void CalcCrc32(const unsigned cha |
| } | } |
| const unsigned long pa_crc32(const char *in, size_t in_size){ | unsigned long pa_crc32(const char *in, size_t in_size){ |
| unsigned long crc32=0xFFFFFFFF; | unsigned long crc32=0xFFFFFFFF; |
| InitCrc32Table(); | InitCrc32Table(); |
| Line 1269 static void file_crc32_file_action(struc | Line 1299 static void file_crc32_file_action(struc |
| } | } |
| } | } |
| const unsigned long pa_crc32(const String& file_spec){ | unsigned long pa_crc32(const String& file_spec){ |
| unsigned long crc32=0xFFFFFFFF; | unsigned long crc32=0xFFFFFFFF; |
| file_read_action_under_lock(file_spec, "crc32", file_crc32_file_action, &crc32); | file_read_action_under_lock(file_spec, "crc32", file_crc32_file_action, &crc32); |
| return ~crc32; | return ~crc32; |
| Line 1302 Charset* detect_charset(const char* cont | Line 1332 Charset* detect_charset(const char* cont |
| return 0; | return 0; |
| } | } |
| const UTF16* pa_utf16_encode(const char* in, Charset& source_charset){ | |
| if(!in) | |
| return 0; | |
| String::C sIn(in,strlen(in)); | |
| UTF16* utf16=(UTF16*)pa_malloc_atomic(sIn.length*2+2); | |
| UTF16* utf16_end=utf16; | |
| if(!source_charset.isUTF8()) | |
| sIn=Charset::transcode(sIn, source_charset, pa_UTF8_charset); | |
| int status=pa_convertUTF8toUTF16((const UTF8**)&sIn.str, (const UTF8*)(sIn.str+sIn.length), &utf16_end, utf16+sIn.length+1, strictConversion); | |
| if(status != conversionOK) | |
| throw Exception("utf-16 encode", new String(in), "utf-16 conversion failed (%d)", status); | |
| *utf16_end=0; | |
| return utf16; | |
| } | |
| const char* pa_utf16_decode(const UTF16* in, Charset& asked_charset){ | |
| if(!in) | |
| return 0; | |
| const UTF16* utf16_start=in; | |
| const UTF16* utf16_end; | |
| for(utf16_end=in; *utf16_end; utf16_end++); | |
| char *result = (char *)pa_malloc_atomic((utf16_end-in)*6+1); | |
| char *result_end = result; | |
| int status=pa_convertUTF16toUTF8(&utf16_start, utf16_end, (UTF8**)&result_end, (UTF8*)(result+(utf16_end-in)*6), strictConversion); | |
| if(status != conversionOK) | |
| throw Exception("utf-16 decode", 0, "utf conversion failed (%d)", status); | |
| *result_end='\0'; | |
| if(!asked_charset.isUTF8()) | |
| result = (char *)Charset::transcode(result, pa_UTF8_charset, asked_charset).cstr(); | |
| return result; | |
| } | |
| static bool is_latin(const char *in){ | static bool is_latin(const char *in){ |
| for(; *in; in++){ | for(; *in; in++){ |
| Line 1313 static bool is_latin(const char *in){ | Line 1388 static bool is_latin(const char *in){ |
| #define MAX_IDNA_LENGTH 256 | #define MAX_IDNA_LENGTH 256 |
| const char *pa_idna_encode(const char *in, Charset &source_charset){ | const char *pa_idna_encode(const char *in, Charset& source_charset){ |
| if(!in || is_latin(in)) | if(!in || is_latin(in)) |
| return in; | return in; |