Diff for /parser3/src/classes/file.C between versions 1.234 and 1.252

version 1.234, 2015/04/08 18:08:52 version 1.252, 2016/10/04 13:23:45
Line 1 Line 1
 /** @file  /** @file
         Parser: @b file parser class.          Parser: @b file parser class.
   
         Copyright (c) 2001-2012 Art. Lebedev Studio (http://www.artlebedev.com)          Copyright (c) 2001-2015 Art. Lebedev Studio (http://www.artlebedev.com)
         Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)          Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
 */  */
   
Line 68  public: Line 68  public:
   
 // global variable  // global variable
   
 DECLARE_CLASS_VAR(file, new MFile, 0);  DECLARE_CLASS_VAR(file, new MFile);
   
 // consts  // consts
   
Line 133  static void _save(Request& r, MethodPara Line 133  static void _save(Request& r, MethodPara
                 if(HashStringValue* options=params.as_hash(2)){                  if(HashStringValue* options=params.as_hash(2)){
                         int valid_options=0;                          int valid_options=0;
                         if(Value* vcharset_name=options->get(PA_CHARSET_NAME)){                          if(Value* vcharset_name=options->get(PA_CHARSET_NAME)){
                                 asked_charset=&::charsets.get(vcharset_name->as_string().change_case(r.charsets.source(), String::CC_UPPER));                                  asked_charset=&pa_charsets.get(vcharset_name->as_string());
                                 valid_options++;                                  valid_options++;
                         }                          }
                         if(valid_options != options->count())                          if(valid_options != options->count())
Line 153  static void _delete(Request& r, MethodPa Line 153  static void _delete(Request& r, MethodPa
                 if(HashStringValue* options=params.as_hash(1)){                  if(HashStringValue* options=params.as_hash(1)){
                         int valid_options=0;                          int valid_options=0;
                         if(Value* vkeep_empty_dirs=options->get(KEEP_EMPTY_DIRS_NAME)){                          if(Value* vkeep_empty_dirs=options->get(KEEP_EMPTY_DIRS_NAME)){
                                 keep_empty_dirs=r.process_to_value(*vkeep_empty_dirs).as_bool();                                  keep_empty_dirs=r.process(*vkeep_empty_dirs).as_bool();
                                 valid_options++;                                  valid_options++;
                         }                          }
                         if(Value* vsuppress_exception=options->get(SUPPRESS_EXCEPTION_NAME)){                          if(Value* vsuppress_exception=options->get(SUPPRESS_EXCEPTION_NAME)){
                                 fail_on_problem=r.process_to_value(*vsuppress_exception).as_bool();                                  fail_on_problem=r.process(*vsuppress_exception).as_bool();
                                 valid_options++;                                  valid_options++;
                         }                          }
                         if(valid_options != options->count())                          if(valid_options != options->count())
Line 177  static void _move(Request& r, MethodPara Line 177  static void _move(Request& r, MethodPara
                 if(HashStringValue* options=params.as_hash(2)){                  if(HashStringValue* options=params.as_hash(2)){
                         int valid_options=0;                          int valid_options=0;
                         if(Value* vkeep_empty_dirs=options->get(KEEP_EMPTY_DIRS_NAME)){                          if(Value* vkeep_empty_dirs=options->get(KEEP_EMPTY_DIRS_NAME)){
                                 keep_empty_dirs=r.process_to_value(*vkeep_empty_dirs).as_bool();                                  keep_empty_dirs=r.process(*vkeep_empty_dirs).as_bool();
                                 valid_options++;                                  valid_options++;
                         }                          }
                         if(valid_options != options->count())                          if(valid_options != options->count())
Line 191  static void _move(Request& r, MethodPara Line 191  static void _move(Request& r, MethodPara
                 keep_empty_dirs);                  keep_empty_dirs);
 }  }
   
 static void copy_process_source(  static void copy_process_source(struct stat& , int from_file, const String&, void *context) {
                                 struct stat& ,   
                                 int from_file,   
                                 const String& , const char* /*fname*/, bool,   
                                 void *context) {  
         int& to_file=*static_cast<int *>(context);          int& to_file=*static_cast<int *>(context);
   
         int nCount=0;          int nCount=0;
Line 214  static void copy_process_source( Line 210  static void copy_process_source(
 static void copy_open_target(int f, void *from_spec) {  static void copy_open_target(int f, void *from_spec) {
         String& file_spec=*static_cast<String *>(from_spec);          String& file_spec=*static_cast<String *>(from_spec);
         file_read_action_under_lock(file_spec, "copy", copy_process_source, &f);          file_read_action_under_lock(file_spec, "copy", copy_process_source, &f);
 };  }
   
 static void _copy(Request& r, MethodParams& params) {  static void _copy(Request& r, MethodParams& params) {
         Value& vfrom_file_name=params.as_no_junction(0, "from file name must not be code");          Value& vfrom_file_name=params.as_no_junction(0, "from file name must not be code");
Line 266  static void _load(Request& r, MethodPara Line 262  static void _load(Request& r, MethodPara
         if(options){          if(options){
                 options=new HashStringValue(*options);                  options=new HashStringValue(*options);
                 if(Value *voffset=(Value *)options->get(sql_offset_name)){                  if(Value *voffset=(Value *)options->get(sql_offset_name)){
                         offset=r.process_to_value(*voffset).as_int();                          offset=r.process(*voffset).as_int();
                 }                  }
                 if(Value *vlimit=(Value *)options->get(sql_limit_name)){                  if(Value *vlimit=(Value *)options->get(sql_limit_name)){
                         limit=r.process_to_value(*vlimit).as_int();                          limit=r.process(*vlimit).as_int();
                 }                  }
                 // no check on options count here, see file_read                  // no check on options count here, see file_read
         }          }
Line 295  static void _load(Request& r, MethodPara Line 291  static void _load(Request& r, MethodPara
                 file_stat(lfile_name, size, atime, mtime, ctime);                  file_stat(lfile_name, size, atime, mtime, ctime);
                   
                 HashStringValue& ff=self.fields();                  HashStringValue& ff=self.fields();
                 ff.put(adate_name, new VDate(atime));                  ff.put(adate_name, new VDate((pa_time_t)atime));
                 ff.put(mdate_name, new VDate(mtime));                  ff.put(mdate_name, new VDate((pa_time_t)mtime));
                 ff.put(cdate_name, new VDate(ctime));                  ff.put(cdate_name, new VDate((pa_time_t)ctime));
         }          }
 }  }
   
Line 322  static void _create(Request& r, MethodPa Line 318  static void _create(Request& r, MethodPa
         }          }
   
         VString* vcontent_type=0;          VString* vcontent_type=0;
         Charset* asked_charset=0;          Charset* to_charset=0;
           Charset* from_charset=0;
         if(params.count()>options_index)          if(params.count()>options_index)
                 if(HashStringValue* options=params.as_hash(options_index)) {                  if(HashStringValue* options=params.as_hash(options_index)) {
                         int valid_options=0;                          int valid_options=0;
Line 337  static void _create(Request& r, MethodPa Line 334  static void _create(Request& r, MethodPa
                                         valid_options++;                                          valid_options++;
                                 }                                  }
                         }                          }
                           if(Value* vcharset_name=options->get("to-charset")) {
                                   to_charset=&pa_charsets.get(vcharset_name->as_string());
                                   valid_options++;
                           }
                           if(Value* vcharset_name=options->get("from-charset")) {
                                   from_charset=&pa_charsets.get(vcharset_name->as_string());
                                   valid_options++;
                           }
                         if(Value* vcharset_name=options->get(PA_CHARSET_NAME)) {                          if(Value* vcharset_name=options->get(PA_CHARSET_NAME)) {
                                 asked_charset=&::charsets.get(vcharset_name->as_string().change_case(r.charsets.source(), String::CC_UPPER));                                  if(to_charset)
                                           throw Exception(PARSER_RUNTIME, 0, "charset option can not be used with to-charset");
                                   to_charset=&pa_charsets.get(vcharset_name->as_string());
                                 valid_options++;                                  valid_options++;
                         }                          }
                         if(Value* value=options->get(CONTENT_TYPE_NAME)) {                          if(Value* value=options->get(CONTENT_TYPE_NAME)) {
Line 355  static void _create(Request& r, MethodPa Line 362  static void _create(Request& r, MethodPa
   
         if(const String* content_str=vcontent.get_string()){          if(const String* content_str=vcontent.get_string()){
                 String::Body body=content_str->cstr_to_string_body_untaint(String::L_AS_IS, r.connection(false), &r.charsets); // explode content, honor tainting changes                  String::Body body=content_str->cstr_to_string_body_untaint(String::L_AS_IS, r.connection(false), &r.charsets); // explode content, honor tainting changes
                 if(asked_charset && is_text)  
                         body=Charset::transcode(body, r.charsets.source(), *asked_charset);  
                 self.set(true/*tainted*/, is_text, body.cstrm(), body.length(), file_name, vcontent_type, &r);                  self.set(true/*tainted*/, is_text, body.cstrm(), body.length(), file_name, vcontent_type, &r);
         } else {          } else {
                 if(asked_charset)                  VFile& fcontent=*vcontent.as_vfile(String::L_AS_IS); // can't be null
                         throw Exception(PARSER_RUNTIME, 0, "charset option can not be used with file-content");                  if(mode){
                 self.set(*vcontent.as_vfile(String::L_AS_IS), mode != 0, is_text, file_name, vcontent_type, &r);                          self.set(fcontent, &is_text, file_name, vcontent_type, &r);
                           if(is_text && !fcontent.is_text_mode())
                                   from_charset=self.detect_binary_charset(from_charset);
                   } else {
                           self.set(fcontent, 0, file_name, vcontent_type, &r);
                           is_text=fcontent.is_text_mode();
                   }
         }          }
   
           if(to_charset || from_charset)
                   if(is_text)
                           self.transcode(from_charset ? *from_charset : r.charsets.source(), to_charset ? *to_charset : r.charsets.source());
                   else
                           throw Exception(PARSER_RUNTIME, 0, "charset options can not be used with binary content");
 }  }
   
 static void _stat(Request& r, MethodParams& params) {  static void _stat(Request& r, MethodParams& params) {
Line 371  static void _stat(Request& r, MethodPara Line 387  static void _stat(Request& r, MethodPara
   
         size_t size;          size_t size;
         time_t atime, mtime, ctime;          time_t atime, mtime, ctime;
         file_stat(r.absolute(lfile_name),          file_stat(r.absolute(lfile_name), size, atime, mtime, ctime);
                 size,  
                 atime, mtime, ctime);  
                   
         VFile& self=GET_SELF(r, VFile);          VFile& self=GET_SELF(r, VFile);
   
         self.set_binary(true/*tainted*/, 0/*no bytes*/, size, &lfile_name, 0, &r);          self.set_binary(true/*tainted*/, 0/*no bytes*/, size, &lfile_name, 0, &r);
         HashStringValue& ff=self.fields();          HashStringValue& ff=self.fields();
         ff.put(adate_name, new VDate(atime));          ff.put(adate_name, new VDate((pa_time_t)atime));
         ff.put(mdate_name, new VDate(mtime));          ff.put(mdate_name, new VDate((pa_time_t)mtime));
         ff.put(cdate_name, new VDate(ctime));          ff.put(cdate_name, new VDate((pa_time_t)ctime));
 }  }
   
 static bool is_safe_env_key(const char* key) {  static bool is_safe_env_key(const char* key) {
Line 469  static void _exec_cgi(Request& r, Method Line 483  static void _exec_cgi(Request& r, Method
         const String& script_name=r.absolute(params.as_string(param_index++, FILE_NAME_MUST_NOT_BE_CODE));          const String& script_name=r.absolute(params.as_string(param_index++, FILE_NAME_MUST_NOT_BE_CODE));
   
         HashStringString env;          HashStringString env;
         #define ECSTR(name, value_cstr) \          #define ECSTR(name, value_cstr) if(value_cstr) env.put(#name, value_cstr);
                 if(value_cstr) \  
                         env.put( \  
                                 String::Body(#name), \  
                                 String::Body(*value_cstr?value_cstr:0)); \  
         // passing environment          // passing environment
         for(SAPI::Env::Iterator i(r.sapi_info); i; i.next() )          for(SAPI::Env::Iterator i(r.sapi_info); i; i.next() )
                 env.put(                  env.put(i.key(), i.value() );
                         i.key(),  
                         i.value()  
                 );  
   
         // const          // const
         ECSTR(GATEWAY_INTERFACE, "CGI/1.1");          ECSTR(GATEWAY_INTERFACE, "CGI/1.1");
Line 493  static void _exec_cgi(Request& r, Method Line 500  static void _exec_cgi(Request& r, Method
         ECSTR(CONTENT_TYPE, r.request_info.content_type);          ECSTR(CONTENT_TYPE, r.request_info.content_type);
         ECSTR(CONTENT_LENGTH, format(r.request_info.content_length, "%u"));          ECSTR(CONTENT_LENGTH, format(r.request_info.content_length, "%u"));
         // SCRIPT_*          // SCRIPT_*
         env.put(String::Body("SCRIPT_NAME"), script_name);          env.put("SCRIPT_NAME", script_name);
         //env.put(String::Body("SCRIPT_FILENAME"), ??&script_name);  
   
         // environment & stdin from param          // environment & stdin from param
         String *in=new String();          String *in=new String();
Line 503  static void _exec_cgi(Request& r, Method Line 509  static void _exec_cgi(Request& r, Method
                 if(HashStringValue* user_env=params.as_hash(param_index++, "env")) {                  if(HashStringValue* user_env=params.as_hash(param_index++, "env")) {
                         // $.charset  [previewing to handle URI pieces]                          // $.charset  [previewing to handle URI pieces]
                         if(Value* vcharset=user_env->get(CHARSET_EXEC_PARAM_NAME))                          if(Value* vcharset=user_env->get(CHARSET_EXEC_PARAM_NAME))
                                 charset=&charsets.get(vcharset->as_string()                                  charset=&pa_charsets.get(vcharset->as_string());
                                         .change_case(r.charsets.source(), String::CC_UPPER));  
   
                         // $.others                          // $.others
                         Append_env_pair_info info={&r.charsets, &env, 0};                          Append_env_pair_info info={&r.charsets, &env, 0};
Line 544  static void _exec_cgi(Request& r, Method Line 549  static void _exec_cgi(Request& r, Method
                                 } else {                                  } else {
                                         Table* table=param.get_table();                                          Table* table=param.get_table();
                                         if(table){                                          if(table){
                                                 for(size_t i=0; i<table->count(); i++) {                                                  for(size_t j=0; j<table->count(); j++)
                                                         append_to_argv(r, argv, table->get(i)->get(0));                                                          append_to_argv(r, argv, table->get(j)->get(0));
                                                 }  
                                         } else {                                          } else {
                                                 throw Exception(PARSER_RUNTIME,                                                  throw Exception(PARSER_RUNTIME, 0, "param must be string or table");
                                                         0,  
                                                         "param must be string or table");  
                                         }                                          }
                                 }                                  }
                         }                          }
Line 647  static void _exec_cgi(Request& r, Method Line 649  static void _exec_cgi(Request& r, Method
                 // $fields << header                  // $fields << header
                 if(header) {                  if(header) {
                         ArrayString rows;                          ArrayString rows;
                         size_t pos_after=0;                          header->split(rows, 0, eol_marker);
                         header->split(rows, pos_after, eol_marker);  
                         Pass_cgi_header_attribute_info info={0, 0, 0};                          Pass_cgi_header_attribute_info info={0, 0, 0};
                         info.charset=&r.charsets.source();                          info.charset=&r.charsets.source();
                         info.fields=&self.fields();                          info.fields=&self.fields();
Line 666  static void _exec_cgi(Request& r, Method Line 667  static void _exec_cgi(Request& r, Method
                   
         // $stderr          // $stderr
         if(!real_err->is_empty())          if(!real_err->is_empty())
                 self.fields().put(                  self.fields().put("stderr", new VString(*real_err));
                         String::Body("stderr"),  
                         new VString(*real_err));  
 }  }
 static void _exec(Request& r, MethodParams& params) {  static void _exec(Request& r, MethodParams& params) {
         _exec_cgi(r, params, false);          _exec_cgi(r, params, false);
Line 691  static void _list(Request& r, MethodPara Line 690  static void _list(Request& r, MethodPara
                         if(HashStringValue* options=voption.get_hash()) {                          if(HashStringValue* options=voption.get_hash()) {
                                 int valid_options=0;                                  int valid_options=0;
                                 if(Value* vstat=options->get("stat")) {                                  if(Value* vstat=options->get("stat")) {
                                         stat=r.process_to_value(*vstat).as_bool();                                          stat=r.process(*vstat).as_bool();
                                         valid_options++;                                          valid_options++;
                                 }                                  }
                                 if(Value* value=options->get("filter")) {                                  if(Value* value=options->get("filter")) {
Line 734  static void _list(Request& r, MethodPara Line 733  static void _list(Request& r, MethodPara
                 if(!vregex || vregex->exec(ffblk.ff_name, file_name_size, ovector, ovector_size)>=0) {                  if(!vregex || vregex->exec(ffblk.ff_name, file_name_size, ovector, ovector_size)>=0) {
                         Table::element_type row(new ArrayString);                          Table::element_type row(new ArrayString);
                         *row+=new String(pa_strdup(file_name_cstr, file_name_size), String::L_TAINTED);                          *row+=new String(pa_strdup(file_name_cstr, file_name_size), String::L_TAINTED);
                         *row+=new String(String::Body::Format(ffblk.is_dir() ? 1 : 0), String::L_CLEAN);                          *row+=new String(String::Body::Format(ffblk.is_dir(stat) ? 1 : 0), String::L_CLEAN);
                         if(stat) {                          if(stat) {
                                 ffblk.stat_file();  
                                 *row+=VDouble(ffblk.size()).get_string();                                  *row+=VDouble(ffblk.size()).get_string();
                                 *row+=new String(String::Body::Format((int)ffblk.c_timestamp()), String::L_CLEAN);                                  *row+=new String(String::Body::Format((int)ffblk.c_timestamp()), String::L_CLEAN);
                                 *row+=new String(String::Body::Format((int)ffblk.m_timestamp()), String::L_CLEAN);                                  *row+=new String(String::Body::Format((int)ffblk.m_timestamp()), String::L_CLEAN);
Line 756  struct Lock_execute_body_info { Line 754  struct Lock_execute_body_info {
         Value* body_code;          Value* body_code;
 };  };
 #endif  #endif
   
 static void lock_execute_body(int , void *ainfo) {  static void lock_execute_body(int , void *ainfo) {
         Lock_execute_body_info& info=*static_cast<Lock_execute_body_info *>(ainfo);          Lock_execute_body_info& info=*static_cast<Lock_execute_body_info *>(ainfo);
         // execute body          // execute body
         info.r->write_assign_lang(info.r->process(*info.body_code));          info.r->write_assign_lang(info.r->process(*info.body_code));
 };  }
   
 static void _lock(Request& r, MethodParams& params) {  static void _lock(Request& r, MethodParams& params) {
         const String& file_spec=r.absolute(params.as_string(0, FILE_NAME_MUST_BE_STRING));          const String& file_spec=r.absolute(params.as_string(0, FILE_NAME_MUST_BE_STRING));
         Lock_execute_body_info info={          Lock_execute_body_info info={
Line 1012  static void _sql(Request& r, MethodParam Line 1012  static void _sql(Request& r, MethodParam
                         }                          }
                         if(Value* vlimit=options->get(sql_limit_name)) {                          if(Value* vlimit=options->get(sql_limit_name)) {
                                 valid_options++;                                  valid_options++;
                                 limit=(ulong)r.process_to_value(*vlimit).as_double();                                  limit=(ulong)r.process(*vlimit).as_double();
                         }                          }
                         if(Value* voffset=options->get(sql_offset_name)) {                          if(Value* voffset=options->get(sql_offset_name)) {
                                 valid_options++;                                  valid_options++;
                                 offset=(ulong)r.process_to_value(*voffset).as_double();                                  offset=(ulong)r.process(*voffset).as_double();
                         }                          }
                         if(valid_options!=options->count())                          if(valid_options!=options->count())
                                 throw Exception(PARSER_RUNTIME, 0, CALLED_WITH_INVALID_OPTION);                                  throw Exception(PARSER_RUNTIME, 0, CALLED_WITH_INVALID_OPTION);
Line 1030  static void _sql(Request& r, MethodParam Line 1030  static void _sql(Request& r, MethodParam
                 handlers,                  handlers,
                 statement_string);                  statement_string);
   
         if(!handlers.value)          if(!handlers.value.str)
                 throw Exception(PARSER_RUNTIME,                  throw Exception(PARSER_RUNTIME, 0, "produced no result");
                         0,  
                         "produced no result");  
   
         VFile& self=GET_SELF(r, VFile);          VFile& self=GET_SELF(r, VFile);
   
Line 1074  static void _base64(Request& r, MethodPa Line 1072  static void _base64(Request& r, MethodPa
                                                         valid_options++;                                                          valid_options++;
                                                 }                                                  }
                                                 if(Value* vstrict=options->get(BASE64_STRICT_OPTION_NAME)) {                                                  if(Value* vstrict=options->get(BASE64_STRICT_OPTION_NAME)) {
                                                         strict=r.process_to_value(*vstrict).as_bool();                                                          strict=r.process(*vstrict).as_bool();
                                                         valid_options++;                                                          valid_options++;
                                                 }                                                  }
                                                 if(valid_options!=options->count())                                                  if(valid_options!=options->count())
Line 1123  static void _crc32(Request& r, MethodPar Line 1121  static void _crc32(Request& r, MethodPar
 }  }
   
   
 static void file_md5_file_action(  static void file_md5_file_action(struct stat& finfo, int f, const String&, void *context)
                                 struct stat& finfo,   
                                 int f,   
                                 const String& , const char* /*fname*/, bool,   
                                 void *context)  
 {  {
         PA_MD5_CTX& md5context=*static_cast<PA_MD5_CTX *>(context);          PA_MD5_CTX& md5context=*static_cast<PA_MD5_CTX *>(context);
         if(finfo.st_size) {          if(finfo.st_size) {

Removed from v.1.234  
changed lines
  Added in v.1.252


E-mail: