Diff for /parser3/src/classes/file.C between versions 1.258 and 1.270

version 1.258, 2016/12/21 21:14:42 version 1.270, 2019/11/22 23:11:24
Line 1 Line 1
 /** @file  /** @file
         Parser: @b file parser class.          Parser: @b file parser class.
   
         Copyright (c) 2001-2015 Art. Lebedev Studio (http://www.artlebedev.com)          Copyright (c) 2001-2017 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 9 Line 9
   
 #include "classes.h"  #include "classes.h"
 #include "pa_vmethod_frame.h"  #include "pa_vmethod_frame.h"
   #include "pa_base64.h"
   
 #include "pa_request.h"  #include "pa_request.h"
 #include "pa_vfile.h"  #include "pa_vfile.h"
Line 192  static void _move(Request& r, MethodPara Line 193  static void _move(Request& r, MethodPara
                 keep_empty_dirs);                  keep_empty_dirs);
 }  }
   
 static void copy_process_source(struct stat& , int from_file, const String&, void *context) {  static void copy_process_source(struct stat&, int from_file, const String&, void *context) {
         int& to_file=*static_cast<int *>(context);          int& to_file=*static_cast<int *>(context);
   
         int nCount=0;          int nCount=0;
Line 217  static void _copy(Request& r, MethodPara Line 218  static void _copy(Request& r, MethodPara
         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");
         Value& vto_file_name=params.as_no_junction(1, "to file name must not be code");          Value& vto_file_name=params.as_no_junction(1, "to file name must not be code");
   
           bool append=false;
           if(params.count()>2)
                   if(HashStringValue* options=params.as_hash(2)){
                           int valid_options=0;
                           if(Value* vappend=options->get("append")){
                                   append=r.process(*vappend).as_bool();
                                   valid_options++;
                           }
                           if(valid_options != options->count())
                                   throw Exception(PARSER_RUNTIME, 0, CALLED_WITH_INVALID_OPTION);
                   }
   
         String from_spec = r.absolute(vfrom_file_name.as_string());          String from_spec = r.absolute(vfrom_file_name.as_string());
         const String& to_spec = r.absolute(vto_file_name.as_string());          const String& to_spec = r.absolute(vto_file_name.as_string());
                   
Line 224  static void _copy(Request& r, MethodPara Line 237  static void _copy(Request& r, MethodPara
                         to_spec,                          to_spec,
                         "copy",                          "copy",
                         copy_open_target,                          copy_open_target,
                         &from_spec);                          &from_spec,
                           false /*as text*/,
                           append);
 }  }
   
 static void _load_pass_param(  static void _load_pass_param(
Line 268  static void _load(Request& r, MethodPara Line 283  static void _load(Request& r, MethodPara
                 if(Value *vlimit=(Value *)options->get(sql_limit_name)){                  if(Value *vlimit=(Value *)options->get(sql_limit_name)){
                         limit=r.process(*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_load
         }          }
         File_read_result file=file_load(r, lfile_name,          File_read_result file=file_load(r, lfile_name, as_text, options, true, offset, limit);
                 as_text, options, true, 0, offset, limit  
         );  
   
         Value* vcontent_type=0;          Value* vcontent_type=0;
         if(file.headers){          if(file.headers){
Line 394  static void _stat(Request& r, MethodPara Line 407  static void _stat(Request& r, MethodPara
   
         self.set_binary(true/*tainted*/, 0 /*no bytes*/, 0 /*fake size*/, &lfile_name, 0, &r);          self.set_binary(true/*tainted*/, 0 /*no bytes*/, 0 /*fake size*/, &lfile_name, 0, &r);
         HashStringValue& ff=self.fields();          HashStringValue& ff=self.fields();
         ff.put(size_name, new VDouble(size) /*real size*/);          ff.put(size_name, new VDouble((double)size) /*real size*/);
         ff.put(adate_name, new VDate((pa_time_t)atime));          ff.put(adate_name, new VDate((pa_time_t)atime));
         ff.put(mdate_name, new VDate((pa_time_t)mtime));          ff.put(mdate_name, new VDate((pa_time_t)mtime));
         ff.put(cdate_name, new VDate((pa_time_t)ctime));          ff.put(cdate_name, new VDate((pa_time_t)ctime));
Line 730  static void _list(Request& r, MethodPara Line 743  static void _list(Request& r, MethodPara
         int ovector[ovector_size];          int ovector[ovector_size];
   
         LOAD_DIR(absolute_path_cstr,           LOAD_DIR(absolute_path_cstr, 
                 const char* file_name_cstr=ffblk.ff_name;                  const char* file_name_cstr=ffblk.name();
                 size_t file_name_size=strlen(file_name_cstr);                  size_t file_name_size=strlen(file_name_cstr);
   
                 if(!vregex || vregex->exec(ffblk.ff_name, file_name_size, ovector, ovector_size)>=0) {                  if(!vregex || vregex->exec(file_name_cstr, 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(stat) ? 1 : 0), String::L_CLEAN);                          *row+=new String(String::Body::Format(ffblk.is_dir(stat) ? 1 : 0), String::L_CLEAN);
Line 939  static void _sql_string(Request& r, Meth Line 952  static void _sql_string(Request& r, Meth
   
 #ifndef DOXYGEN  #ifndef DOXYGEN
 class File_sql_event_handlers: public SQL_Driver_query_event_handlers {  class File_sql_event_handlers: public SQL_Driver_query_event_handlers {
         const String& statement_string; const char* statement_cstr;  
         int got_columns;          int got_columns;
         int got_cells;          int got_cells;
 public:  public:
Line 947  public: Line 959  public:
         const String* user_file_name;          const String* user_file_name;
         const String* user_content_type;          const String* user_content_type;
 public:  public:
         File_sql_event_handlers(          File_sql_event_handlers():
                 const String& astatement_string, const char* astatement_cstr):  
                 statement_string(astatement_string), statement_cstr(astatement_cstr),  
                 got_columns(0),                  got_columns(0),
                 got_cells(0),                  got_cells(0),
                 user_file_name(0),                  user_file_name(0),
Line 957  public: Line 967  public:
   
         bool add_column(SQL_Error& error, const char* /*str*/, size_t /*length*/) {          bool add_column(SQL_Error& error, const char* /*str*/, size_t /*length*/) {
                 if(got_columns++==3) {                  if(got_columns++==3) {
                         error=SQL_Error(PARSER_RUNTIME, "result must contain not more then 3 columns");                          error=SQL_Error("result must contain not more then 3 columns");
                         return true;                          return true;
                 }                  }
                 return false;                  return false;
Line 979  public: Line 989  public:
                                                 user_content_type=new String(str, String::L_TAINTED);                                                  user_content_type=new String(str, String::L_TAINTED);
                                         break;                                          break;
                                 default:                                  default:
                                         error=SQL_Error(PARSER_RUNTIME, "result must not contain more then one row, three columns");                                          error=SQL_Error("result must not contain more then one row, three columns");
                                         return true;                                          return true;
                         }                          }
                         return false;                          return false;
                 } catch(...) {                  } catch(...) {
                         error=SQL_Error("exception occured in File_sql_event_handlers::add_row_cell");                          error=SQL_Error("exception occurred in File_sql_event_handlers::add_row_cell");
                         return true;                          return true;
                 }                  }
         }          }
Line 996  static void _sql(Request& r, MethodParam Line 1006  static void _sql(Request& r, MethodParam
         const String& statement_string=r.process_to_string(statement);          const String& statement_string=r.process_to_string(statement);
         const char* statement_cstr=statement_string.untaint_cstr(String::L_SQL, r.connection());          const char* statement_cstr=statement_string.untaint_cstr(String::L_SQL, r.connection());
   
         File_sql_event_handlers handlers(statement_string, statement_cstr);          File_sql_event_handlers handlers;
   
         ulong limit=SQL_NO_LIMIT;          ulong limit=SQL_NO_LIMIT;
         ulong offset=0;          ulong offset=0;
Line 1025  static void _sql(Request& r, MethodParam Line 1035  static void _sql(Request& r, MethodParam
                 }                  }
   
   
         r.connection()->query(          r.connection()->query(statement_cstr, 0, 0, offset, limit, handlers, statement_string);
                 statement_cstr,   
                 0, 0,  
                 offset, limit,  
                 handlers,  
                 statement_string);  
   
         if(!handlers.value.str)          if(!handlers.value.str)
                 throw Exception(PARSER_RUNTIME, 0, "produced no result");                  throw Exception(PARSER_RUNTIME, 0, "produced no result");
Line 1042  static void _sql(Request& r, MethodParam Line 1047  static void _sql(Request& r, MethodParam
                                 , &r);                                  , &r);
 }  }
   
   extern Base64Options base64_encode_options(Request& r, HashStringValue* options);
   
   Base64Options base64_decode_options(Request& r, HashStringValue* options, VString** vcontent_type) {
           Base64Options result;
           if(options) {
                   int valid_options=0;
                   for(HashStringValue::Iterator i(*options); i; i.next() ) {
                           String::Body key=i.key();
                           Value* value=i.value();
                           if(key == "pad") {
                                   result.pad=r.process(*value).as_bool();
                                   valid_options++;
                           } else if(key == "strict") {
                                   result.strict=r.process(*value).as_bool();
                                   valid_options++;
                           } else if(key == CONTENT_TYPE_NAME) {
                                   *vcontent_type=new VString(value->as_string());
                                   valid_options++;
                           } else if(key == "url-safe") {
                                   if(r.process(*value).as_bool())
                                           result.set_url_safe_abc();
                                   valid_options++;
                           }
                   }
   
                   if(valid_options != options->count())
                           throw Exception(PARSER_RUNTIME, 0, CALLED_WITH_INVALID_OPTION);
           }
           return result;
   }
   
 static void _base64(Request& r, MethodParams& params) {  static void _base64(Request& r, MethodParams& params) {
         bool dynamic=!(&r.get_self() == file_class);          bool dynamic=!(&r.get_self() == file_class);
         if(dynamic) {          if(dynamic) {
                 VFile& self=GET_SELF(r, VFile);                  VFile& self=GET_SELF(r, VFile);
                 if(params.count()) {                  if(params.count()>1 || params.count()==1 && params[0].is_string()) {
                         // decode:                           // decode: 
                         //      ^file::base64[encoded] // backward                          //      ^file::base64[encoded] // backward
                         //      ^file::base64[mode;user-file-name;encoded[;$.content-type[...] $.strict(true|false)]]                          //      ^file::base64[mode;user-file-name;encoded[;$.content-type[...] $.strict(true|false)]]
                         bool is_text=false;                          bool is_text=false;
                         bool strict=false;  
                         VString* vcontent_type=0;  
                         const String* user_file_name=0;                          const String* user_file_name=0;
                           VString* vcontent_type=0;
                           Base64Options options;
   
                         size_t param_index=0;                          size_t param_index=0;
   
                         if(params.count() > 1) {                          if(params.count() > 1) {
                                 if(params.count() < 3)                                  if(params.count() < 3)
                                         throw Exception(PARSER_RUNTIME,                                          throw Exception(PARSER_RUNTIME, 0, "constructor can not have less then 3 parameters (has %d parameters)", params.count()); // actually it accepts 1 parameter (backward)
                                                 0,  
                                                 "constructor can not have less then 3 parameters (has %d parameters)",  
                                                 params.count()); // actually it accepts 1 parameter (backward)  
   
                                 is_text=VFile::is_text_mode(params.as_string(0, MODE_MUST_NOT_BE_CODE));                                  is_text=VFile::is_text_mode(params.as_string(0, MODE_MUST_NOT_BE_CODE));
                                 user_file_name=&params.as_string(1, FILE_NAME_MUST_BE_STRING);                                  user_file_name=&params.as_string(1, FILE_NAME_MUST_BE_STRING);
   
                                 if(params.count() == 4)                                  if(params.count() == 4)
                                         if(HashStringValue* options=params.as_hash(3)) {                                          options=base64_decode_options(r, params.as_hash(3), &vcontent_type);
                                                 int valid_options=0;  
                                                 if(Value* value=options->get(CONTENT_TYPE_NAME)) {  
                                                         vcontent_type=new VString(value->as_string());  
                                                         valid_options++;  
                                                 }  
                                                 if(Value* vstrict=options->get(BASE64_STRICT_OPTION_NAME)) {  
                                                         strict=r.process(*vstrict).as_bool();  
                                                         valid_options++;  
                                                 }  
                                                 if(valid_options!=options->count())  
                                                         throw Exception(PARSER_RUNTIME, 0, CALLED_WITH_INVALID_OPTION);  
                                         }  
   
                                 param_index=2;                                  param_index=2;
                         }                          }
Line 1087  static void _base64(Request& r, MethodPa Line 1109  static void _base64(Request& r, MethodPa
                         const char* encoded=params.as_string(param_index, PARAMETER_MUST_BE_STRING).cstr();                          const char* encoded=params.as_string(param_index, PARAMETER_MUST_BE_STRING).cstr();
   
                         char* decoded=0;                          char* decoded=0;
                         size_t length=0;                          size_t length=pa_base64_decode(encoded, strlen(encoded), decoded, options);
                         pa_base64_decode(encoded, strlen(encoded), decoded, length, strict);  
   
                         self.set(true/*tainted*/, is_text, decoded, length, user_file_name, vcontent_type, &r);                          self.set(true/*tainted*/, is_text, decoded, length, user_file_name, vcontent_type, &r);
                 } else {                  } else {
                         // encode: ^f.base64[]                          // encode: ^f.base64[options]
                         const char* encoded=pa_base64_encode(self.value_ptr(), self.value_size());                          Base64Options options = base64_encode_options(r, params.count() > 0 ? params.as_hash(0) : NULL);
                         r.write(*new String(encoded, String::L_TAINTED/*once ?param=base64(something) was needed**/));                          const char* encoded=pa_base64_encode(self.value_ptr(), self.value_size(), options);
                           r.write(*new String(encoded, String::L_TAINTED /*once ?param=base64(something) was needed**/ ));
                 }                  }
         } else {          } else {
                 // encode: ^file:base64[filespec]                  // encode: ^file:base64[filespec[;options]]
                 const String& file_spec=params.as_string(0, FILE_NAME_MUST_BE_STRING);                  const String& file_spec = params.as_string(0, FILE_NAME_MUST_BE_STRING);
                 const char* encoded=pa_base64_encode(r.absolute(file_spec));                  Base64Options options = base64_encode_options(r, params.count() > 1 ? params.as_hash(1) : NULL);
                 r.write(*new String(encoded, String::L_TAINTED/*once ?param=base64(something) was needed*/));                  const char* encoded = pa_base64_encode(r.absolute(file_spec), options);
                   r.write(*new String(encoded, String::L_TAINTED /*once ?param=base64(something) was needed*/ ));
         }          }
 }  }
   
Line 1266  MFile::MFile(): Methoded("file") { Line 1289  MFile::MFile(): Methoded("file") {
         add_native_method("md5", Method::CT_ANY, _md5, 0, 1);          add_native_method("md5", Method::CT_ANY, _md5, 0, 1);
   
         // ^file:copy[from-file-name;to-file-name]          // ^file:copy[from-file-name;to-file-name]
         add_native_method("copy", Method::CT_STATIC, _copy, 2, 2);          // ^file:copy[from-file-name;to-file-name;$.append(false)]
           add_native_method("copy", Method::CT_STATIC, _copy, 2, 3);
 }  }

Removed from v.1.258  
changed lines
  Added in v.1.270


E-mail: