--- parser3/src/classes/file.C 2016/11/01 23:10:40 1.255 +++ parser3/src/classes/file.C 2017/02/06 16:17:12 1.261 @@ -25,7 +25,7 @@ #include "pa_vregex.h" #include "pa_version.h" -volatile const char * IDENT_FILE_C="$Id: file.C,v 1.255 2016/11/01 23:10:40 moko Exp $"; +volatile const char * IDENT_FILE_C="$Id: file.C,v 1.261 2017/02/06 16:17:12 moko Exp $"; // defines @@ -118,6 +118,7 @@ static const char* suexec_safe_env_lst[] // statics +static const String::Body size_name("size"); static const String::Body adate_name("adate"); static const String::Body mdate_name("mdate"); static const String::Body cdate_name("cdate"); @@ -191,7 +192,7 @@ static void _move(Request& r, MethodPara 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(context); int nCount=0; @@ -285,7 +286,7 @@ static void _load(Request& r, MethodPara if(file.headers){ file.headers->for_each(_load_pass_param, &self.fields()); } else { - size_t size; + uint64_t size; time_t atime, mtime, ctime; file_stat(lfile_name, size, atime, mtime, ctime); @@ -385,14 +386,15 @@ static void _create(Request& r, MethodPa static void _stat(Request& r, MethodParams& params) { const String& lfile_name=params.as_string(0, FILE_NAME_MUST_NOT_BE_CODE); - size_t size; + uint64_t size; time_t atime, mtime, ctime; file_stat(r.absolute(lfile_name), size, atime, mtime, ctime); 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*/, 0 /*fake size*/, &lfile_name, 0, &r); HashStringValue& ff=self.fields(); + ff.put(size_name, new VDouble((double)size) /*real size*/); ff.put(adate_name, new VDate((pa_time_t)atime)); ff.put(mdate_name, new VDate((pa_time_t)mtime)); ff.put(cdate_name, new VDate((pa_time_t)ctime)); @@ -503,7 +505,8 @@ static void _exec_cgi(Request& r, Method env.put("SCRIPT_NAME", script_name); // environment & stdin from param - String *in=new String(); + bool in_is_text_mode=true; + String::C in; Charset *charset=0; // default script works raw_in 'source' charset = no transcoding needed if(param_index < params.count()) { if(HashStringValue* user_env=params.as_hash(param_index++, "env")) { @@ -523,14 +526,13 @@ static void _exec_cgi(Request& r, Method if(info.vstdin) { if(const String* sstdin=info.vstdin->get_string()) { // untaint stdin - in = new String(sstdin->cstr_to_string_body_untaint(String::L_AS_IS, r.connection(false), &r.charsets), String::L_AS_IS); + in = String::C(sstdin->cstr_to_string_body_untaint(String::L_AS_IS, r.connection(false), &r.charsets)); } else - if(VFile* vfile=static_cast(info.vstdin->as("file"))) - in->append_know_length((const char* )vfile->value_ptr(), vfile->value_size(), String::L_TAINTED); - else - throw Exception(PARSER_RUNTIME, - 0, - STDIN_EXEC_PARAM_NAME " parameter must be string or file"); + if(VFile* vfile=static_cast(info.vstdin->as("file"))){ + in = String::C((const char* )vfile->value_ptr(), vfile->value_size()); + in_is_text_mode = vfile->is_text_mode(); + } else + throw Exception(PARSER_RUNTIME, 0, STDIN_EXEC_PARAM_NAME " parameter must be string or file"); } } } @@ -563,14 +565,15 @@ static void _exec_cgi(Request& r, Method if(charset) { Charset::transcode(env, r.charsets.source(), *charset); Charset::transcode(argv, r.charsets.source(), *charset); - in=&Charset::transcode(*in, r.charsets.source(), *charset); + if(in_is_text_mode) + in=Charset::transcode(in, r.charsets.source(), *charset); } // @todo // ifdef WIN32 do OEM->ANSI transcode on some(.cmd?) programs to // match silent conversion in OS // exec! - PA_exec_result execution=pa_exec(false/*forced_allow*/, script_name, &env, argv, *in); + PA_exec_result execution=pa_exec(false/*forced_allow*/, script_name, &env, argv, in); File_read_result *file_out=&execution.out; String *real_err=&execution.err; @@ -659,7 +662,7 @@ static void _exec_cgi(Request& r, Method } } else { // ^file::exec // $body - self.set(false/*not tainted*/, is_text, file_out->str, file_out->length); + self.set(false/*not tainted*/, is_text, file_out->str ? file_out->str : pa_strdup("") /*to distinguish from stat-ed file*/, file_out->length); } // $status @@ -727,10 +730,10 @@ static void _list(Request& r, MethodPara int ovector[ovector_size]; 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); - 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); *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);