|
|
| version 1.216.4.1, 2006/02/03 15:26:51 | version 1.232, 2008/06/06 17:24:23 |
|---|---|
| Line 34 static const char * const IDENT_COMMON_C | Line 34 static const char * const IDENT_COMMON_C |
| #include "pa_globals.h" | #include "pa_globals.h" |
| #include "pa_charsets.h" | #include "pa_charsets.h" |
| #include "pa_http.h" | #include "pa_http.h" |
| #include "pa_request_charsets.h" | |
| // some maybe-undefined constants | // some maybe-undefined constants |
| Line 91 void fix_line_breaks(char *str, size_t& | Line 92 void fix_line_breaks(char *str, size_t& |
| } | } |
| char* file_read_text(Request_charsets& charsets, | char* file_read_text(Request_charsets& charsets, |
| const String& file_spec, | const String& file_spec, |
| bool fail_on_read_problem, | bool fail_on_read_problem, |
| HashStringValue* params/*, HashStringValue* * out_fields*/) { | HashStringValue* params/*, HashStringValue* * out_fields*/) { |
| File_read_result file= | File_read_result file= |
| file_read(charsets, file_spec, true, params, fail_on_read_problem); | file_read(charsets, file_spec, true, params, fail_on_read_problem); |
| return file.success?file.str:0; | return file.success?file.str:0; |
| Line 111 int pa_get_valid_file_options_count(Hash | Line 112 int pa_get_valid_file_options_count(Hash |
| result++; | result++; |
| if(options.get(PA_COLUMN_ENCLOSER_NAME)) | if(options.get(PA_COLUMN_ENCLOSER_NAME)) |
| result++; | result++; |
| if(options.get(PA_CHARSET_NAME)) | |
| result++; | |
| return result; | return result; |
| } | } |
| Line 121 struct File_read_action_info { | Line 124 struct File_read_action_info { |
| }; | }; |
| #endif | #endif |
| static void file_read_action( | static void file_read_action( |
| struct stat& finfo, | struct stat& finfo, |
| int f, | int f, |
| const String& file_spec, const char* /*fname*/, bool as_text, | const String& file_spec, const char* /*fname*/, bool as_text, |
| void *context) { | void *context) { |
| 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) |
| Line 152 static void file_read_action( | Line 155 static void file_read_action( |
| } | } |
| } | } |
| File_read_result file_read(Request_charsets& charsets, const String& file_spec, | File_read_result file_read(Request_charsets& charsets, const String& file_spec, |
| bool as_text, HashStringValue *params, | bool as_text, HashStringValue *params, |
| bool fail_on_read_problem, | bool fail_on_read_problem, |
| char* buf, size_t offset, size_t count) { | char* buf, size_t offset, size_t count) { |
| File_read_result result={false, 0, 0, 0}; | File_read_result result={false, 0, 0, 0}; |
| if(file_spec.starts_with("http://")) { | if(file_spec.starts_with("http://")) { |
| if(offset || count) | if(offset || count) |
| throw Exception("parser.runtime", | throw Exception(PARSER_RUNTIME, |
| 0, | 0, |
| "offset and load options are not supported for HTTP:// file load"); | "offset and load options are not supported for HTTP:// file load"); |
| Line 172 File_read_result file_read(Request_chars | Line 175 File_read_result file_read(Request_chars |
| if(params) { | if(params) { |
| int valid_options=pa_get_valid_file_options_count(*params); | int valid_options=pa_get_valid_file_options_count(*params); |
| if(valid_options!=params->count()) | if(valid_options!=params->count()) |
| throw Exception("parser.runtime", | throw Exception(PARSER_RUNTIME, |
| 0, | 0, |
| "invalid option passed"); | "invalid option passed"); |
| } | } |
| Line 182 File_read_result file_read(Request_chars | Line 185 File_read_result file_read(Request_chars |
| result.success=file_read_action_under_lock(file_spec, | result.success=file_read_action_under_lock(file_spec, |
| "read", file_read_action, &info, | "read", file_read_action, &info, |
| as_text, fail_on_read_problem); | 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<char *>(body.str); // hacking a little | |
| result.length=body.length; | |
| } | |
| } | |
| } | } |
| if(result.success && as_text) { | if(result.success && as_text) { |
| Line 203 File_read_result file_read(Request_chars | Line 219 File_read_result file_read(Request_chars |
| void check_safe_mode(struct stat finfo, const String& file_spec, const char* fname) { | void check_safe_mode(struct stat finfo, const String& file_spec, const char* fname) { |
| if(finfo.st_uid/*foreign?*/!=geteuid() | if(finfo.st_uid/*foreign?*/!=geteuid() |
| && finfo.st_gid/*foreign?*/!=getegid()) | && finfo.st_gid/*foreign?*/!=getegid()) |
| throw Exception("parser.runtime", | throw Exception(PARSER_RUNTIME, |
| &file_spec, | &file_spec, |
| "parser is in safe mode: " | "parser is in safe mode: " |
| "reading files of foreign group and user disabled " | "reading files of foreign group and user disabled " |
| Line 232 bool file_read_action_under_lock(const S | Line 248 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=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", | throw Exception("file.lock", |
| Line 261 bool file_read_action_under_lock(const S | Line 277 bool file_read_action_under_lock(const S |
| pa_unlock(f);close(f); | pa_unlock(f);close(f); |
| return true; | return true; |
| } else { | } else { |
| if(fail_on_read_problem) | if(fail_on_read_problem) |
| throw Exception(errno==EACCES?"file.access":errno==ENOENT?"file.missing":0, | throw Exception(errno==EACCES?"file.access":errno==ENOENT?"file.missing":0, |
| &file_spec, | &file_spec, |
| Line 282 void create_dir_for_file(const String& f | Line 298 void create_dir_for_file(const String& f |
| bool file_write_action_under_lock( | bool file_write_action_under_lock( |
| const String& file_spec, | 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 as_text, |
| bool do_append, | bool do_append, |
| bool do_block, | bool do_block, |
| Line 353 void file_write( | Line 371 void file_write( |
| bool as_text, | bool as_text, |
| bool do_append) { | bool do_append) { |
| File_write_action_info info={data, size}; | File_write_action_info info={data, size}; |
| file_write_action_under_lock( | file_write_action_under_lock( |
| file_spec, | file_spec, |
| "write", file_write_action, &info, | "write", |
| file_write_action, | |
| &info, | |
| as_text, | as_text, |
| do_append); | do_append); |
| } | } |
| Line 447 bool file_executable(const String& file_ | Line 468 bool file_executable(const String& file_ |
| } | } |
| bool file_stat(const String& file_spec, | bool file_stat(const String& file_spec, |
| size_t& rsize, | size_t& rsize, |
| time_t& ratime, | time_t& ratime, |
| time_t& rmtime, | time_t& rmtime, |
| time_t& rctime, | time_t& rctime, |
| bool fail_on_read_problem) { | bool fail_on_read_problem) { |
| const char* fname=file_spec.cstr(String::L_FILE_SPEC); | const char* fname=file_spec.cstr(String::L_FILE_SPEC); |
| struct stat finfo; | struct stat finfo; |
| if(stat(fname, &finfo)!=0) | if(stat(fname, &finfo)!=0) |
| Line 470 bool file_stat(const String& file_spec, | Line 491 bool file_stat(const String& file_spec, |
| } | } |
| char* getrow(char* *row_ref, char delim) { | char* getrow(char* *row_ref, char delim) { |
| char* result=*row_ref; | char* result=*row_ref; |
| if(result) { | if(result) { |
| *row_ref=strchr(result, delim); | *row_ref=strchr(result, delim); |
| if(*row_ref) | if(*row_ref) |
| *((*row_ref)++)=0; | *((*row_ref)++)=0; |
| else if(!*result) | else if(!*result) |
| return 0; | return 0; |
| } | } |
| return result; | return result; |
| } | } |
| char* lsplit(char* string, char delim) { | char* lsplit(char* string, char delim) { |
| if(string) { | if(string) { |
| char* v=strchr(string, delim); | char* v=strchr(string, delim); |
| if(v) { | if(v) { |
| *v=0; | *v=0; |
| return v+1; | return v+1; |
| } | } |
| } | } |
| return 0; | return 0; |
| } | } |
| char* lsplit(char* *string_ref, char delim) { | char* lsplit(char* *string_ref, char delim) { |
| char* result=*string_ref; | char* result=*string_ref; |
| char* next=lsplit(*string_ref, delim); | char* next=lsplit(*string_ref, delim); |
| *string_ref=next; | *string_ref=next; |
| return result; | return result; |
| } | } |
| char* rsplit(char* string, char delim) { | char* rsplit(char* string, char delim) { |
| if(string) { | if(string) { |
| char* v=strrchr(string, delim); | char* v=strrchr(string, delim); |
| if(v) { | if(v) { |
| *v=0; | *v=0; |
| return v+1; | return v+1; |
| } | } |
| } | } |
| return NULL; | return NULL; |
| } | |
| // format: %[flags][width][.precision]type http://msdn.microsoft.com/ru-ru/library/56e442dc(en-us,VS.80).aspx | |
| // flags: '-', '+', ' ', '#', '0' http://msdn.microsoft.com/ru-ru/library/8aky45ct(en-us,VS.80).aspx | |
| // width, precision: non negative decimal number | |
| enum FormatType { | |
| FormatInvalid, | |
| FormatInt, | |
| FormatUInt, | |
| FormatDouble | |
| }; | |
| FormatType format_type(char* fmt){ | |
| enum FormatState { | |
| Percent, | |
| Flags, | |
| Width, | |
| Precision, | |
| Done | |
| } state=Percent; | |
| FormatType result=FormatInvalid; | |
| char* pos=fmt; | |
| while(char c=*(pos++)){ | |
| switch(state){ | |
| case Percent: | |
| if(c=='%'){ | |
| state=Flags; | |
| } else { | |
| return FormatInvalid; // 1st char must be '%' only | |
| } | |
| break; | |
| case Flags: | |
| if(strchr("-+ #0", c)!=0){ | |
| break; | |
| } | |
| // go to the next step | |
| case Width: | |
| if(c=='.'){ | |
| state=Precision; | |
| break; | |
| } | |
| // go to the next step | |
| case Precision: | |
| if(c>='0' && c<='9'){ | |
| if(state == Flags) state=Width; // no more flags | |
| break; | |
| } else if(c=='d' || c=='i'){ | |
| result=FormatInt; | |
| } else if(strchr("feEgG", c)!=0){ | |
| result=FormatDouble; | |
| } else if(strchr("uoxX", c)!=0){ | |
| result=FormatUInt; | |
| } else { | |
| return FormatInvalid; // invalid char | |
| } | |
| state=Done; | |
| break; | |
| case Done: | |
| return FormatInvalid; // no chars allowed after 'type' | |
| } | |
| } | |
| return result; | |
| } | } |
| /// @todo less stupid type detection | |
| const char* format(double value, char* fmt) { | const char* format(double value, char* fmt) { |
| char local_buf[MAX_NUMBER]; | char local_buf[MAX_NUMBER]; |
| size_t size; | size_t size; |
| if(fmt) | if(fmt && strlen(fmt)){ |
| if(strpbrk(fmt, "diouxX")) | switch(format_type(fmt)){ |
| if(strpbrk(fmt, "ouxX")) | case FormatDouble: |
| size=snprintf(local_buf, sizeof(local_buf), fmt, (uint)value); | size=snprintf(local_buf, sizeof(local_buf), fmt, value); |
| else | break; |
| case FormatInt: | |
| size=snprintf(local_buf, sizeof(local_buf), fmt, (int)value); | size=snprintf(local_buf, sizeof(local_buf), fmt, (int)value); |
| else | break; |
| size=snprintf(local_buf, sizeof(local_buf), fmt, value); | case FormatUInt: |
| else | size=snprintf(local_buf, sizeof(local_buf), fmt, (uint)value); |
| size=snprintf(local_buf, sizeof(local_buf), "%d", (int)value); | break; |
| case FormatInvalid: | |
| throw Exception(PARSER_RUNTIME, | |
| 0, | |
| "Incorrect format string '%s' was specified.", fmt); | |
| } | |
| } else | |
| size=snprintf(local_buf, sizeof(local_buf), "%d", (int)value); | |
| if(size < 0 || size >= MAX_NUMBER-1){ // on win32 we manually reduce max size while printing | |
| throw Exception(PARSER_RUNTIME, | |
| 0, | |
| "Error occure white executing snprintf with format string '%s'.", fmt); | |
| } | |
| return pa_strdup(local_buf, size); | return pa_strdup(local_buf, size); |
| } | } |
| Line 546 size_t stdout_write(const void *buf, siz | Line 645 size_t stdout_write(const void *buf, siz |
| #endif | #endif |
| } | } |
| enum EscapeState { | |
| EscapeRest, | |
| EscapeFirst, | |
| EscapeSecond, | |
| EscapeUnicode | |
| }; | |
| /* | |
| char* unescape_chars(const char* cp, int len) { | char* unescape_chars(const char* cp, int len) { |
| char* s=new(PointerFreeGC) char[len + 1]; | char* s=new(PointerFreeGC) char[len + 1]; |
| enum EscapeState { | EscapeState escapeState=EscapeRest; |
| EscapeRest, | |
| EscapeFirst, | |
| EscapeSecond | |
| } escapeState=EscapeRest; | |
| uint escapedValue=0; | uint escapedValue=0; |
| int srcPos=0; | int srcPos=0; |
| int dstPos=0; | int dstPos=0; |
| Line 560 char* unescape_chars(const char* cp, int | Line 662 char* unescape_chars(const char* cp, int |
| uchar ch=(uchar)cp[srcPos]; | uchar ch=(uchar)cp[srcPos]; |
| switch(escapeState) { | switch(escapeState) { |
| case EscapeRest: | case EscapeRest: |
| if(ch=='%') { | if(ch=='%') { |
| escapeState=EscapeFirst; | escapeState=EscapeFirst; |
| } else if(ch=='+') { | } else if(ch=='+'){ |
| s[dstPos++]=' '; | s[dstPos++]=' '; |
| } else { | } else { |
| s[dstPos++]=ch; | s[dstPos++]=ch; |
| } | } |
| break; | break; |
| case EscapeFirst: | case EscapeFirst: |
| escapedValue=hex_value[ch] << 4; | escapedValue=hex_value[ch] << 4; |
| escapeState=EscapeSecond; | escapeState=EscapeSecond; |
| break; | break; |
| case EscapeSecond: | case EscapeSecond: |
| escapedValue +=hex_value[ch]; | escapedValue +=hex_value[ch]; |
| s[dstPos++]=(char)escapedValue; | s[dstPos++]=(char)escapedValue; |
| escapeState=EscapeRest; | escapeState=EscapeRest; |
| break; | break; |
| } | } |
| srcPos++; | srcPos++; |
| } | } |
| s[dstPos]=0; | s[dstPos]=0; |
| return s; | return s; |
| } | } |
| */ | |
| char* unescape_chars(const char* cp, int len, Charset* charset){ | |
| char* s=new(PointerFreeGC) char[len + 1]; // enough (%uXXXX==6 bytes, max utf-8 char length==6 bytes) | |
| char* dst=s; | |
| EscapeState escapeState=EscapeRest; | |
| uint escapedValue=0; | |
| int srcPos=0; | |
| short int jsCnt=0; | |
| while(srcPos < len) { | |
| uchar c=(uchar)cp[srcPos]; | |
| if(c=='%'){ | |
| escapeState=EscapeFirst; | |
| } else { | |
| switch(escapeState) { | |
| case EscapeRest: | |
| if(c=='+'){ | |
| *dst++=' '; | |
| } else { | |
| *dst++=c; | |
| } | |
| break; | |
| case EscapeFirst: | |
| if(charset && c=='u'){ | |
| // escaped unicode value: %u0430 | |
| jsCnt=0; | |
| escapedValue=0; | |
| escapeState=EscapeUnicode; | |
| } else { | |
| if(isxdigit(c)){ | |
| escapedValue=hex_value[c] << 4; | |
| escapeState=EscapeSecond; | |
| } else { | |
| *dst++=c; | |
| escapeState=EscapeRest; | |
| } | |
| } | |
| break; | |
| case EscapeSecond: | |
| if(isxdigit(c)){ | |
| escapedValue+=hex_value[c]; | |
| *dst++=(char)escapedValue; | |
| } | |
| escapeState=EscapeRest; | |
| break; | |
| case EscapeUnicode: | |
| if(isxdigit(c)){ | |
| escapedValue=(escapedValue << 4) + hex_value[c]; | |
| if(++jsCnt==4){ | |
| // transcode utf8 char to client charset (we can lost some chars here) | |
| charset->store_Char((XMLByte*&)dst, (XMLCh)escapedValue, '?'); | |
| escapeState=EscapeRest; | |
| } | |
| } else { | |
| // not full unicode value | |
| escapeState=EscapeRest; | |
| } | |
| break; | |
| } | |
| } | |
| srcPos++; | |
| } | |
| *dst=0; // zero-termination | |
| return s; | |
| } | |
| #ifdef WIN32 | #ifdef WIN32 |
| void back_slashes_to_slashes(char* s) { | void back_slashes_to_slashes(char* s) { |
| Line 601 void slashes_to_back_slashes(char* s) { | Line 770 void slashes_to_back_slashes(char* s) { |
| */ | */ |
| #endif | #endif |
| bool StrEqNc(const char* s1, const char* s2, bool strict) { | bool StrStartFromNC(const char* str, const char* substr, bool equal){ |
| while(true) { | while(true) { |
| if(!(*s1)) { | if(!(*substr)){ |
| if(!(*s2)) | if(!(*str)) |
| return true; | return true; |
| else | else |
| return !strict; | return !equal; |
| } else if(!(*s2)) | } |
| return !strict; | if(!(*str)) |
| if(isalpha((unsigned char)*s1)) { | return false; |
| if(tolower((unsigned char)*s1) !=tolower((unsigned char)*s2)) | if(isalpha((unsigned char)*str)) { |
| if(tolower((unsigned char)*str)!=tolower((unsigned char)*substr)) | |
| return false; | return false; |
| } else if((*s1) !=(*s2)) | } else if((*str) != (*substr)) |
| return false; | return false; |
| s1++; | str++; |
| s2++; | substr++; |
| } | |
| } | |
| char* pa_tolower(char *str){ | |
| for(char *p=str; *p; p++) | |
| *p=(char)tolower((unsigned char)*p); | |
| return str; | |
| } | |
| char* pa_toupper(char *str){ | |
| for(char *p=str; *p; p++) | |
| *p=(char)toupper((unsigned char)*p); | |
| return str; | |
| } | |
| size_t strpos(const char *str, const char *substr) { | |
| const char *p = strstr(str, substr); | |
| return (p==0)?STRING_NOT_FOUND:p-str; | |
| } | |
| char* strpart(const char* str, size_t len) { | |
| char *result=new(PointerFreeGC) char[len+1]; | |
| memcpy(result, str, len); | |
| result[len]=0; | |
| return result; | |
| } | |
| // content-type: xxx; charset=WE-NEED-THIS | |
| // content-type: xxx; charset="WE-NEED-THIS" | |
| // content-type: xxx; charset="WE-NEED-THIS"; | |
| Charset* detect_charset(char* content_type_value){ | |
| if(const char* start=strstr(content_type_value, "CHARSET=")){ | |
| start+=8;/*skip CHARSET=*/ | |
| char* end=0; | |
| if(*start && (*start=='"' || *start =='\'')){ | |
| char quote=*start; | |
| start++; | |
| end=(char*)strchr(start, quote); | |
| } | |
| if(!end) | |
| end=(char*)strchr(start, ';'); | |
| size_t len; | |
| if(end){ | |
| *end=0; | |
| len=end-start; | |
| } else { | |
| len=strlen(start); | |
| } | |
| String::Body NAME=String::Body(start, len); | |
| return &charsets.get(NAME); | |
| } | } |
| return 0; | |
| } | } |
| Charset* detect_charset(const char* content_type_value){ | |
| size_t len=strlen(content_type_value); | |
| char* value=new(PointerFreeGC) char[len+1]; | |
| memcpy(value, content_type_value, len); | |
| return detect_charset(pa_toupper(value)); | |
| } | |
| Charset* detect_charset(Request_charsets& charsets, const String& content_type_value){ | |
| return detect_charset(content_type_value.change_case(charsets.source(), String::CC_UPPER).cstrm(String::L_UNSPECIFIED, 0, &charsets)); | |
| } | |
| static bool isLeap(int year) { | static bool isLeap(int year) { |
| return !( | return !( |
| (year % 4) || ((year % 400) && !(year % 100)) | (year % 4) || ((year % 400) && !(year % 100)) |
| ); | ); |
| } | } |
| int getMonthDays(int year, int month) { | int getMonthDays(int year, int month) { |
| int monthDays[]={ | static int monthDays[]={ |
| 31, | 31, |
| isLeap(year) ? 29 : 28, | 28, |
| 31, | 31, |
| 30, | 30, |
| 31, | 31, |
| 30, | 30, |
| 31, | 31, |
| 31, | 31, |
| 30, | 30, |
| 31, | 31, |
| 30, | 30, |
| 31 | 31 |
| }; | }; |
| return monthDays[month]; | return (month == 1 /* january -- 0 */ && isLeap(year)) ? 29 : monthDays[month]; |
| } | } |
| void remove_crlf(char* start, char* end) { | int remove_crlf(char* start, char* end) { |
| for(char* p=start; p<end; p++) | char* from=start; |
| switch(*p) { | char* to=start; |
| case '\n': *p='|'; break; | bool skip=false; |
| case '\r': *p=' '; break; | while(from < end){ |
| switch(*from){ | |
| case '\n': | |
| case '\r': | |
| case '\t': | |
| case ' ': | |
| if(!skip){ | |
| *to=' '; | |
| to++; | |
| skip=true; | |
| } | |
| break; | |
| default: | |
| if(from != to) | |
| *to=*from; | |
| to++; | |
| skip=false; | |
| } | } |
| from++; | |
| } | |
| return to-start; | |
| } | } |
| Line 966 char* pa_base64_encode(const char *in, s | Line 1221 char* pa_base64_encode(const char *in, s |
| return result; | 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<File_base64_action_info *>(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) | 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) */ | /* wont go to more than had (overly conservative) */ |
| Line 978 void pa_base64_decode(const char *in, si | Line 1271 void pa_base64_decode(const char *in, si |
| assert(result_size <= in_size); | assert(result_size <= in_size); |
| result[result_size]=0; // for text files | 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<unsigned long *>(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); | |
| } | |
| } | |