Diff for /parser3/src/classes/file.C between versions 1.201 and 1.214

version 1.201, 2009/09/08 09:12:47 version 1.214, 2011/05/19 06:58:40
Line 25  static const char * const IDENT_FILE_C=" Line 25  static const char * const IDENT_FILE_C="
 #include "pa_sql_connection.h"  #include "pa_sql_connection.h"
 #include "pa_md5.h"  #include "pa_md5.h"
 #include "pa_vregex.h"  #include "pa_vregex.h"
   #include "pa_version.h"
   
 // defines  // defines
   
Line 42  extern String sql_offset_name; Line 43  extern String sql_offset_name;
   
 class MFile: public Methoded {  class MFile: public Methoded {
 public: // VStateless_class  public: // VStateless_class
           
         Value* create_new_value(Pool&) { return new VFile(); }          Value* create_new_value(Pool&) { return new VFile(); }
   
 public: // Methoded  
         bool used_directly() { return true; }  
   
 public:  public:
         MFile();          MFile();
   
 };  };
   
 // global variable  // global variable
Line 115  static bool is_valid_mode (const String& Line 110  static bool is_valid_mode (const String&
         return (mode==text_mode_name || mode==binary_mode_name);          return (mode==text_mode_name || mode==binary_mode_name);
 }  }
   
 static bool is_text_mode(const String& mode) {  bool is_text_mode(const String& mode) {
         if(mode==text_mode_name)          if(mode==text_mode_name)
                 return true;                  return true;
         if(mode==binary_mode_name)          if(mode==binary_mode_name)
Line 131  static void _save(Request& r, MethodPara Line 126  static void _save(Request& r, MethodPara
   
         Charset* asked_charset=0;          Charset* asked_charset=0;
         if(params.count()>2)          if(params.count()>2)
                 if(HashStringValue* options=params.as_no_junction(2, OPTIONS_MUST_NOT_BE_CODE).get_hash()){                  if(HashStringValue* options=params.as_hash(2)){
                         size_t 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=&::charsets.get(vcharset_name->as_string().change_case(r.charsets.source(), String::CC_UPPER));
                                 valid_options++;                                  valid_options++;
                         }                          }
                         if(valid_options != options->count())                          if(valid_options != options->count())
                                 throw Exception(PARSER_RUNTIME,                                  throw Exception(PARSER_RUNTIME, 0, CALLED_WITH_INVALID_OPTION);
                                         0,  
                                         INVALID_OPTION_PASSED);  
                 }                  }
   
         // save          // save
Line 289  static void _create(Request& r, MethodPa Line 282  static void _create(Request& r, MethodPa
                 params.as_no_junction(1, FILE_NAME_MUST_NOT_BE_CODE).as_string()).taint_cstr(String::L_FILE_SPEC);                  params.as_no_junction(1, FILE_NAME_MUST_NOT_BE_CODE).as_string()).taint_cstr(String::L_FILE_SPEC);
   
         const String& content=params.as_string(2, "content must be string");          const String& content=params.as_string(2, "content must be string");
         const String::Body content_body=content.cstr_to_string_body_untaint(String::L_AS_IS); // explode content, honor tainting changes          String::Body content_body=content.cstr_to_string_body_untaint(String::L_AS_IS); // explode content, honor tainting changes
   
           VString* vcontent_type=0;
           if(params.count()>3)
                   if(HashStringValue* options=params.as_hash(3)){
                           Charset* asked_charset=0;
   
                           int valid_options=0;
                           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));
                                   valid_options++;
                           }
                           if(Value* value=options->get(CONTENT_TYPE_NAME)) {
                                   vcontent_type=new VString(value->as_string());
                                   valid_options++;
                           }
                           if(valid_options != options->count())
                                   throw Exception(PARSER_RUNTIME, 0, CALLED_WITH_INVALID_OPTION);
   
                           if(asked_charset)
                                   content_body=Charset::transcode(content_body, r.charsets.source(), *asked_charset);
                   }
   
         VString* vcontent_type=new VString(r.mime_type_of(user_file_name_cstr));          if(!vcontent_type)
                   vcontent_type=new VString(r.mime_type_of(user_file_name_cstr));
                   
         VFile& self=GET_SELF(r, VFile);          VFile& self=GET_SELF(r, VFile);
         self.set(true/*tainted*/, content_body.cstr(), content_body.length(), user_file_name_cstr, vcontent_type);          self.set(true/*tainted*/, content_body.cstr(), content_body.length(), user_file_name_cstr, vcontent_type);
Line 327  static bool is_safe_env_key(const char* Line 342  static bool is_safe_env_key(const char*
                 if(!(c>='A' && c<='Z' || c>='0' && c<='9' || c=='_' || c=='-'))                  if(!(c>='A' && c<='Z' || c>='0' && c<='9' || c=='_' || c=='-'))
                         return false;                          return false;
         }          }
   #ifdef PA_SAFE_MODE
         if(strncasecmp(key, "HTTP_", 5)==0)          if(strncasecmp(key, "HTTP_", 5)==0)
                 return true;                  return true;
         if(strncasecmp(key, "CGI_", 4)==0)          if(strncasecmp(key, "CGI_", 4)==0)
Line 336  static bool is_safe_env_key(const char* Line 352  static bool is_safe_env_key(const char*
                         return true;                          return true;
         }          }
         return false;          return false;
   #else
           return true;
   #endif
 }  }
 #ifndef DOXYGEN  #ifndef DOXYGEN
 struct Append_env_pair_info {  struct Append_env_pair_info {
Line 424  static void _exec_cgi(Request& r, Method Line 443  static void _exec_cgi(Request& r, Method
   
         // const          // const
         ECSTR(GATEWAY_INTERFACE, "CGI/1.1");          ECSTR(GATEWAY_INTERFACE, "CGI/1.1");
           ECSTR(PARSER_VARSION, PARSER_VERSION);
         // from Request.info          // from Request.info
         ECSTR(DOCUMENT_ROOT, r.request_info.document_root);          ECSTR(DOCUMENT_ROOT, r.request_info.document_root);
         ECSTR(PATH_TRANSLATED, r.request_info.path_translated);          ECSTR(PATH_TRANSLATED, r.request_info.path_translated);
Line 436  static void _exec_cgi(Request& r, Method Line 456  static void _exec_cgi(Request& r, Method
         env.put(String::Body("SCRIPT_NAME"), script_name);          env.put(String::Body("SCRIPT_NAME"), script_name);
         //env.put(String::Body("SCRIPT_FILENAME"), ??&script_name);          //env.put(String::Body("SCRIPT_FILENAME"), ??&script_name);
   
         bool stdin_specified=false;  
         // environment & stdin from param          // environment & stdin from param
         String *in=new String();          String *in=new String();
         Charset *charset=0; // default script works raw_in 'source' charset = no transcoding needed          Charset *charset=0; // default script works raw_in 'source' charset = no transcoding needed
Line 458  static void _exec_cgi(Request& r, Method Line 477  static void _exec_cgi(Request& r, Method
                         }                          }
                         // $.stdin                          // $.stdin
                         if(info.vstdin) {                          if(info.vstdin) {
                                 stdin_specified=true;  
                                 if(const String* sstdin=info.vstdin->get_string()) {                                  if(const String* sstdin=info.vstdin->get_string()) {
                                         in->append(*sstdin, String::L_CLEAN, true);                                          // untaint stdin
                                           in = new String(sstdin->cstr_to_string_body_untaint(String::L_AS_IS), String::L_AS_IS);
                                 } else                                  } else
                                         if(VFile* vfile=static_cast<VFile *>(info.vstdin->as("file")))                                          if(VFile* vfile=static_cast<VFile *>(info.vstdin->as("file")))
                                                 in->append_know_length((const char* )vfile->value_ptr(), vfile->value_size(), String::L_TAINTED);                                                  in->append_know_length((const char* )vfile->value_ptr(), vfile->value_size(), String::L_TAINTED);
Line 688  static void _lock(Request& r, MethodPara Line 707  static void _lock(Request& r, MethodPara
                         &info);                          &info);
 }  }
   
 static int lastposafter(const String& s, size_t after, const char* substr, size_t substr_size, bool beforelast=false) {  
         size_t size=0; // just to calm down compiler  
         if(beforelast)  
                 size=s.length();  
         size_t at;  
         while((at=s.pos(String::Body(substr), after))!=STRING_NOT_FOUND) {  
                 size_t newafter=at+substr_size/*skip substr*/;  
                 if(beforelast && newafter==size)  
                         break;  
                 after=newafter;  
         }  
   
         return after;  
 }  
   
 static void _find(Request& r, MethodParams& params) {  static void _find(Request& r, MethodParams& params) {
         const String& file_name=params.as_no_junction(0, FILE_NAME_MUST_NOT_BE_CODE).as_string();          const String& file_name=params.as_no_junction(0, FILE_NAME_MUST_NOT_BE_CODE).as_string();
         const String* file_spec;          const String* file_spec;
Line 842  public: Line 846  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 rows");                                          error=SQL_Error(PARSER_RUNTIME, "result must not contain more then one row, three columns");
                                         return true;                                          return true;
                         }                          }
                         return false;                          return false;
Line 866  static void _sql(Request& r, MethodParam Line 870  static void _sql(Request& r, MethodParam
         ulong offset=0;          ulong offset=0;
   
         if(params.count()>1)          if(params.count()>1)
                 if(HashStringValue* options=params.as_no_junction(1, PARAM_MUST_NOT_BE_CODE).get_hash()){                  if(HashStringValue* options=params.as_hash(1)){
                         int valid_options=0;                          int valid_options=0;
                         if(Value* vfilename=options->get(NAME_NAME)) {                          if(Value* vfilename=options->get(NAME_NAME)) {
                                 valid_options++;                                  valid_options++;
Line 885  static void _sql(Request& r, MethodParam Line 889  static void _sql(Request& r, MethodParam
                                 offset=(ulong)r.process_to_value(*voffset).as_double();                                  offset=(ulong)r.process_to_value(*voffset).as_double();
                         }                          }
                         if(valid_options!=options->count())                          if(valid_options!=options->count())
                                 throw Exception(PARSER_RUNTIME,                                  throw Exception(PARSER_RUNTIME, 0, CALLED_WITH_INVALID_OPTION);
                                         0,  
                                         "called with invalid option");  
                 }                  }
   
   
Line 916  static void _sql(Request& r, MethodParam Line 918  static void _sql(Request& r, MethodParam
 }  }
   
 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()) {
                         // decode: ^file::base64[encoded]                          // decode: 
                         const char* cstr=params.as_string(0, PARAMETER_MUST_BE_STRING).cstr();                          //      ^file::base64[encoded] // backward
                           //      ^file::base64[mode;user-file-name;encoded[;$.content-type[...]]]
                           bool is_text=false;
                           VString* vcontent_type=0;
                           const char* user_file_name_cstr=0;
                           size_t param_index=0;
   
                           if(params.count() > 1) {
                                   if(params.count() < 3)
                                           throw Exception(PARSER_RUNTIME,
                                                   0,
                                                   "constructor can't have less then 3 parameters (has %d parameters)",
                                                   params.count()); // actually it accepts 1 parameter (backward)
   
                                   is_text=is_text_mode(params.as_no_junction(0, MODE_MUST_NOT_BE_CODE).as_string());
                                   user_file_name_cstr=params.as_string(1, FILE_NAME_MUST_BE_STRING).taint_cstr(String::L_FILE_SPEC);
   
                                   if(params.count() == 4)
                                           if(HashStringValue* options=params.as_hash(3)) {
                                                   int valid_options=0;
                                                   if(Value* value=options->get(CONTENT_TYPE_NAME)) {
                                                           vcontent_type=new VString(value->as_string());
                                                           valid_options++;
                                                   }
                                                   if(valid_options!=options->count())
                                                           throw Exception(PARSER_RUNTIME, 0, CALLED_WITH_INVALID_OPTION);
                                           }
   
                                   if(!vcontent_type)
                                           vcontent_type=new VString(r.mime_type_of(user_file_name_cstr));
   
                                   param_index=2;
                           }
   
                           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=0;
                         pa_base64_decode(cstr, strlen(cstr), decoded, length);                          pa_base64_decode(encoded, strlen(encoded), decoded, length);
                         if(decoded && length)  
                                 self.set(true/*tainted*/, decoded, length);                          if(length && is_text)
                                   fix_line_breaks(decoded, length);
                   
                           self.set(true/*tainted*/, decoded, length, user_file_name_cstr, vcontent_type);
   
                           if(params.count() > 1)
                                   self.set_mode(is_text);
                 } else {                  } else {
                         // encode: ^f.base64[]                          // encode: ^f.base64[]
                         const char* encoded=pa_base64_encode(self.value_ptr(), self.value_size());                          const char* encoded=pa_base64_encode(self.value_ptr(), self.value_size());
Line 1027  static void _md5(Request& r, MethodParam Line 1070  static void _md5(Request& r, MethodParam
   
 MFile::MFile(): Methoded("file") {  MFile::MFile(): Methoded("file") {
         // ^file::create[text;user-name;string]          // ^file::create[text;user-name;string]
           // ^file::create[text;user-name;string;options hash]
         // ^file::create[binary;user-name;SOMEDAY SOMETHING]          // ^file::create[binary;user-name;SOMEDAY SOMETHING]
         add_native_method("create", Method::CT_DYNAMIC, _create, 3, 3);          // ^file::create[binary;user-name;SOMEDAY SOMETHING;options hash]
           add_native_method("create", Method::CT_DYNAMIC, _create, 3, 4);
   
         // ^file.save[mode;file-name]          // ^file.save[mode;file-name]
         // ^file.save[mode;file-name;$.charset[...]]          // ^file.save[mode;file-name;$.charset[...]]
Line 1085  MFile::MFile(): Methoded("file") { Line 1130  MFile::MFile(): Methoded("file") {
         // ^file.sql-string[]          // ^file.sql-string[]
         add_native_method("sql-string", Method::CT_DYNAMIC, _sql_string, 0, 0);          add_native_method("sql-string", Method::CT_DYNAMIC, _sql_string, 0, 0);
   
           // ^file::sql{}
         // ^file::sql{}[options hash]          // ^file::sql{}[options hash]
         add_native_method("sql", Method::CT_DYNAMIC, _sql, 1, 2);          add_native_method("sql", Method::CT_DYNAMIC, _sql, 1, 2);
   
         // ^file::base64[string] << decode          // encode:
         // ^file.base64[] << encode          //   ^file.base64[]
         // ^file:base64[file-name] << encode          //   ^file:base64[file-name]
         add_native_method("base64", Method::CT_ANY, _base64, 0, 1);          // decode:
           //   ^file::base64[encoded] // backward
           //   ^file::base64[mode;user-file-name;encoded]
           //   ^file::base64[mode;user-file-name;encoded;$.content-type[...]]
           add_native_method("base64", Method::CT_ANY, _base64, 0, 4);
   
         // ^file.crc32[]          // ^file.crc32[]
         // ^file:crc32[file-name]          // ^file:crc32[file-name]

Removed from v.1.201  
changed lines
  Added in v.1.214


E-mail: