Diff for /parser3/src/main/pa_common.C between versions 1.216.4.1 and 1.232

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);
           }
   }
   

Removed from v.1.216.4.1  
changed lines
  Added in v.1.232


E-mail: