|
|
| version 1.384, 2020/10/28 22:32:02 | version 1.389, 2020/11/10 22:50:58 |
|---|---|
| Line 121 static const String body_name_upper(BODY | Line 121 static const String body_name_upper(BODY |
| static const String content_type_name_upper(HTTP_CONTENT_TYPE_UPPER); | static const String content_type_name_upper(HTTP_CONTENT_TYPE_UPPER); |
| static const String content_disposition_name_upper(CONTENT_DISPOSITION_UPPER); | static const String content_disposition_name_upper(CONTENT_DISPOSITION_UPPER); |
| static const String content_disposition_inline(CONTENT_DISPOSITION_INLINE); | |
| static const String content_disposition_attachment(CONTENT_DISPOSITION_ATTACHMENT); | static const String content_disposition_attachment(CONTENT_DISPOSITION_ATTACHMENT); |
| // defines | // defines |
| Line 402 void Request::core(const char* config_fi | Line 401 void Request::core(const char* config_fi |
| try { | try { |
| // loading config | // loading config |
| if(config_filespec) | if(config_filespec) |
| use_file_directly(main_class, *new String(config_filespec), true, true /*file must exist if 'fail on read problem' not set*/); | use_file_directly(*new String(config_filespec)); |
| // filling mail received | // filling mail received |
| mail.fill_received(*this); | mail.fill_received(*this); |
| // loading auto.p files from document_root/.. | |
| // to the one beside requested file. | |
| // all assigned bases from upper dir | |
| { | |
| const char* after=request_info.path_translated; | |
| size_t drlen=strlen(request_info.document_root); | |
| if(memcmp(after, request_info.document_root, drlen)==0) { | |
| after+=drlen; | |
| if(after[-1]=='/') | |
| --after; | |
| } | |
| while(const char* before=strchr(after, '/')) { | |
| String& sfile_spec=*new String; | |
| if(after!=request_info.path_translated) { | |
| sfile_spec.append_strdup(request_info.path_translated, before-request_info.path_translated, String::L_CLEAN); | |
| sfile_spec << "/" AUTO_FILE_NAME; | |
| use_file_directly(main_class, sfile_spec, true /*fail on read problem*/, false /*but ignore absence, sole user*/); | |
| } | |
| for(after=before+1;*after=='/';after++); | |
| } | |
| } | |
| try { | try { |
| // compile requested file | // compile requested file |
| String& spath_translated=*new String; | if(request_info.path_translated) |
| spath_translated.append_help_length(request_info.path_translated, 0, String::L_TAINTED); | use_file_directly(*new String(request_info.path_translated, String::L_TAINTED), true, true /* load auto.p files */); |
| use_file_directly(main_class, spath_translated); | |
| configure(); | configure(); |
| } catch(...) { | } catch(...) { |
| configure(); // configure anyway, useful in @unhandled_exception [say, if they would want to mail by SMTP something] | configure(); // configure anyway, useful in @unhandled_exception [say, if they would want to mail by SMTP something] |
| Line 558 uint Request::register_file(String::Body | Line 531 uint Request::register_file(String::Body |
| return file_list.count()-1; | return file_list.count()-1; |
| } | } |
| void Request::use_file_directly(VStateless_class& aclass, const String& file_spec, bool fail_on_read_problem, bool fail_on_file_absence) { | void Request::use_file_directly(const String& file_spec, bool fail_on_file_absence, bool with_auto_p) { |
| // cyclic dependence check | // cyclic dependence check |
| if(used_files.get(file_spec)) | if(used_files.get(file_spec)) |
| return; | return; |
| used_files.put(file_spec, true); | used_files.put(file_spec, true); |
| if(fail_on_read_problem && !fail_on_file_absence) // ignore file absence if asked for | if(!fail_on_file_absence && !entry_exists(file_spec)) // ignore file absence if asked for |
| if(!entry_exists(file_spec)) | return; |
| return; | |
| if(const char* source=file_read_text(charsets, file_spec, fail_on_read_problem)) | if(with_auto_p) { |
| use_buf(aclass, source, 0, register_file(file_spec)); | // loading auto.p files from document_root/.. |
| // to the one beside requested file. | |
| // all assigned bases from upper dir | |
| const char* target=file_spec.cstr(); | |
| // all relative paths are calculated from main document | |
| request_info.path_translated=target; | |
| const char* after=target; | |
| size_t drlen=strlen(request_info.document_root); | |
| if(memcmp(after, request_info.document_root, drlen)==0) { | |
| after+=drlen; | |
| if(after[-1]=='/') | |
| --after; | |
| } | |
| while(const char* before=strchr(after, '/')) { | |
| String& sfile_spec=*new String; | |
| if(after!=target) { | |
| sfile_spec.append_strdup(target, before-target, String::L_CLEAN); | |
| sfile_spec << "/" AUTO_FILE_NAME; | |
| use_file_directly(sfile_spec, false /*ignore absence, sole user*/); | |
| } | |
| for(after=before+1;*after=='/';after++); | |
| } | |
| } | |
| if(const char* source=file_read_text(charsets, file_spec, true)) | |
| use_buf(main_class, source, 0, register_file(file_spec)); | |
| } | } |
| void Request::use_file(VStateless_class& aclass, const String& file_name, const String* use_filespec/*absolute*/) { | void Request::use_file(const String& file_name, const String* use_filespec/*absolute*/, bool with_auto_p) { |
| if(file_name.is_empty()) | if(file_name.is_empty()) |
| throw Exception(PARSER_RUNTIME, 0, "usage failed - no filename was specified"); | throw Exception(PARSER_RUNTIME, 0, "usage failed - no filename was specified"); |
| const String* filespec=0; | const String* filespec=0; |
| if(file_name.first_char()=='/') //absolute path? [no need to scan MAIN:CLASS_PATH] | if(file_name.first_char()=='/') //absolute path? [no need to scan MAIN:CLASS_PATH] |
| filespec=&absolute(file_name); | filespec=&full_disk_path(file_name); |
| else if(use_filespec){ // search in current dir first | else if(use_filespec){ // search in current dir first |
| size_t last_slash_pos=use_filespec->strrpbrk("/"); | size_t last_slash_pos=use_filespec->strrpbrk("/"); |
| if(last_slash_pos!=STRING_NOT_FOUND) | if(last_slash_pos!=STRING_NOT_FOUND) |
| Line 594 void Request::use_file(VStateless_class& | Line 595 void Request::use_file(VStateless_class& |
| searched_along_class_path.put(file_name, true); | searched_along_class_path.put(file_name, true); |
| if(Value* element=main_class.get_element(class_path_name)) { | if(Value* element=main_class.get_element(class_path_name)) { |
| if(element->is_string()) { | if(element->is_string()) { |
| filespec=file_exist(absolute(element->as_string()), file_name); // found at class_path? | filespec=file_exist(full_disk_path(element->as_string()), file_name); // found at class_path? |
| } else if(Table *table=element->get_table()) { | } else if(Table *table=element->get_table()) { |
| for(size_t i=table->count(); i--; ) { | for(size_t i=table->count(); i--; ) { |
| const String& path=*(*table->get(i))[0]; | const String& path=*(*table->get(i))[0]; |
| if(filespec=file_exist(absolute(path), file_name)) | if(filespec=file_exist(full_disk_path(path), file_name)) |
| break; // found along class_path | break; // found along class_path |
| } | } |
| } else | } else |
| Line 609 void Request::use_file(VStateless_class& | Line 610 void Request::use_file(VStateless_class& |
| throw Exception(PARSER_RUNTIME, &file_name, "usage failed - no $" MAIN_CLASS_NAME ":" CLASS_PATH_NAME " were specified"); | throw Exception(PARSER_RUNTIME, &file_name, "usage failed - no $" MAIN_CLASS_NAME ":" CLASS_PATH_NAME " were specified"); |
| } | } |
| use_file_directly(aclass, *filespec); | use_file_directly(*filespec, true, with_auto_p); |
| } | } |
| void Request::use_file(const String& file_name, const String* use_filespec/*absolute*/, Operation::Origin origin) { | void Request::use_file(const String& file_name, const String* use_filespec/*absolute*/, Operation::Origin origin) { |
| Line 667 const String& Request::relative(const ch | Line 668 const String& Request::relative(const ch |
| return result; | return result; |
| } | } |
| const String& Request::absolute(const String& relative_name) { | const String& Request::full_disk_path(const String& relative_name) { |
| if(relative_name.first_char()=='/') { | if(relative_name.first_char()=='/') { |
| String& result=*new String(pa_strdup(request_info.document_root)); | String& result=*new String(pa_strdup(request_info.document_root)); |
| result << relative_name; | result << relative_name; |
| return result; | return result; |
| } else | } |
| if(relative_name.pos("://")!=STRING_NOT_FOUND // something like "http://xxx" | if(relative_name.pos("://")!=STRING_NOT_FOUND // something like "http://xxx" |
| #ifdef WIN32 | #ifdef WIN32 |
| || relative_name.pos(":")==1 // DRIVE: | || relative_name.pos(":")==1 // DRIVE: |
| || relative_name.starts_with("\\\\") // UNC1 | || relative_name.starts_with("\\\\") // UNC1 |
| || relative_name.starts_with("//") // UNC2 | || relative_name.starts_with("//") // UNC2 |
| #endif | #endif |
| ) | ) |
| return relative_name; | return relative_name; |
| else | |
| return relative(request_info.path_translated, relative_name); | return relative(request_info.path_translated ? request_info.path_translated : request_info.document_root, relative_name); |
| } | } |
| #ifndef DOXYGEN | #ifndef DOXYGEN |
| Line 804 static void output_pieces(Request& r, bo | Line 805 static void output_pieces(Request& r, bo |
| SAPI::send_header(r.sapi_info); | SAPI::send_header(r.sapi_info); |
| const String& filespec=r.absolute(filename); | const String& filespec=r.full_disk_path(filename); |
| size_t sent = 0; | size_t sent = 0; |
| if(!header_only){ | if(!header_only){ |
| Line 850 void Request::output_result(VFile* body_ | Line 851 void Request::output_result(VFile* body_ |
| if(vfile_name) { | if(vfile_name) { |
| const String& sfile_name=vfile_name->as_string(); | const String& sfile_name=vfile_name->as_string(); |
| if(sfile_name!=NONAME_DAT) { | if(sfile_name!=NONAME_DAT) { |
| VHash& hash=*new VHash(); | if(as_attachment) { |
| HashStringValue &h=hash.hash(); | VHash& hash=*new VHash(); |
| h.put(value_name, new VString( as_attachment ? content_disposition_attachment : content_disposition_inline )); | hash.hash().put(value_name, new VString(content_disposition_attachment)); |
| h.put(content_disposition_filename_name, new VString(*new String(sfile_name, String::L_HTTP_HEADER))); | hash.hash().put(content_disposition_filename_name, new VString(*new String(sfile_name, String::L_HTTP_HEADER))); |
| response.fields().put(content_disposition_name_upper, &hash); | |
| response.fields().put(content_disposition_name_upper, &hash); | } |
| if(!body_file_content_type) | if(!body_file_content_type) |
| body_file_content_type=new VString(mime_type_of(sfile_name.cstr())); | body_file_content_type=new VString(mime_type_of(sfile_name.cstr())); |
| Line 880 void Request::output_result(VFile* body_ | Line 881 void Request::output_result(VFile* body_ |
| const String& sresponse_body_file=vresponse_body_file->as_string(); | const String& sresponse_body_file=vresponse_body_file->as_string(); |
| uint64_t content_length=0; | uint64_t content_length=0; |
| time_t atime=0, mtime=0, ctime=0; | time_t atime=0, mtime=0, ctime=0; |
| file_stat(absolute(sresponse_body_file), content_length, atime, mtime, ctime); | file_stat(full_disk_path(sresponse_body_file), content_length, atime, mtime, ctime); |
| VDate* vdate=0; | VDate* vdate=0; |
| if(Value* v=body_file->fields().get("mdate")) { | if(Value* v=body_file->fields().get("mdate")) { |