diff --git a/winixd/core/app.cpp b/winixd/core/app.cpp index 1746a3b..c76d5a2 100644 --- a/winixd/core/app.cpp +++ b/winixd/core/app.cpp @@ -1494,25 +1494,28 @@ void App::PrepareHeaderContentType() { if( !cur.request->out_headers.has_key(L"Content-Type") ) { - if( cur.request->return_json ) + if( !cur.request->send_bin_stream ) { - cur.request->out_headers.add(L"Content-Type", L"application/json; charset=UTF-8"); - } - else - { - switch( config.content_type_header ) + if( cur.request->return_json ) { - case 1: - cur.request->out_headers.add(L"Content-Type", L"application/xhtml+xml; charset=UTF-8"); - break; - - case 2: - cur.request->out_headers.add(L"Content-Type", L"application/xml; charset=UTF-8"); - break; + cur.request->out_headers.add(L"Content-Type", L"application/json; charset=UTF-8"); + } + else + { + switch( config.content_type_header ) + { + case 1: + cur.request->out_headers.add(L"Content-Type", L"application/xhtml+xml; charset=UTF-8"); + break; - case 0: - default: - cur.request->out_headers.add(L"Content-Type", L"text/html; charset=UTF-8"); + case 2: + cur.request->out_headers.add(L"Content-Type", L"application/xml; charset=UTF-8"); + break; + + case 0: + default: + cur.request->out_headers.add(L"Content-Type", L"text/html; charset=UTF-8"); + } } } } diff --git a/winixd/core/config.h b/winixd/core/config.h index dcfbcc4..7efd517 100644 --- a/winixd/core/config.h +++ b/winixd/core/config.h @@ -544,22 +544,25 @@ public: std::wstring title_separator; // how to send static files (uploaded by users) to the webserver - // 0 - full path to a file in send_file_header header - // 1 - relative path to a file in send_file_header (need http_send_file_relative_prefix set) + // 0 - winix will read the content of the file and send it back to the webserver + // 1 - winix will use send_file_header header with a full path to the file + // 2 - winix will use send_file_header header with a relative path to the file // default: 0 - // for Apache set: 0 - // for Lighttpd set: 0 - // for Nginx set: 1 + // 0 can be be used with all webservers but it requires to copy the whole file content + // you can omit copying the content with values 1 or 2: + // for Apache set: 1 + // for Lighttpd set: 1 + // for Nginx set: 2 int send_file_mode; - // http header recognized by www server as a file to send back + // http header recognized by www server as a file to send back, used if send_file_mode is 1 or 2 // default: X-SENDFILE - // for Apache set: X-SENDFILE - // for Lighttpd set: X-LIGHTTPD-send-file - // for Nginx set: X-Accel-Redirect + // for Apache set: X-SENDFILE (Apache needs an external module: https://tn123.org/mod_xsendfile/) + // for Lighttpd set: X-LIGHTTPD-send-file (https://redmine.lighttpd.net/projects/1/wiki/X-LIGHTTPD-send-file) + // for Nginx set: X-Accel-Redirect (https://nginx.org/en/docs/http/ngx_http_core_module.html#internal) std::wstring send_file_header; - // relative prefix used for sending static files if send_file_mode is 1 + // relative prefix used for sending static files if send_file_mode is 2 // default: "upload-files-internal" // this prefix is added at the beginning of a relative file path e.g. // /upload-files-internal/simplefs/normal/some_directories/file.jpg diff --git a/winixd/core/misc.cpp b/winixd/core/misc.cpp index 4a92dd0..9980b07 100644 --- a/winixd/core/misc.cpp +++ b/winixd/core/misc.cpp @@ -1162,6 +1162,45 @@ bool GetUTF8File(const std::wstring & file_path, std::wstring & content, bool cl } + +bool GetBinaryFile(const wchar_t * file_path, BinaryPage & content, bool clear_content) +{ +char file[WINIX_OS_PATH_SIZE]; +char buffer[4096]; +size_t buffer_len = sizeof(buffer) / sizeof(char); +std::ifstream get_file_content; + + if( clear_content ) + content.clear(); + + if( !wide_to_utf8(file_path, file, WINIX_OS_PATH_SIZE) ) + return false; + + get_file_content.open(file, std::ios_base::in | std::ios_base::binary); + + if( !get_file_content ) + return false; + + do + { + get_file_content.read(buffer, buffer_len); + content.write(buffer, get_file_content.gcount()); + } + while( !get_file_content.eof() && get_file_content.good() ); + + get_file_content.close(); + +return true; +} + + +bool GetBinaryFile(const std::wstring & file_path, BinaryPage & content, bool clear_content) +{ + return GetBinaryFile(file_path.c_str(), content, clear_content); +} + + + // if there is no an extension it returns a pointer to the last '\0' character const wchar_t * GetFileExt(const wchar_t * name) { diff --git a/winixd/core/misc.h b/winixd/core/misc.h index a287d8f..efaa472 100644 --- a/winixd/core/misc.h +++ b/winixd/core/misc.h @@ -662,6 +662,8 @@ bool RenameFile(const std::wstring & from, const std::wstring & to); bool GetUTF8File(const wchar_t * file_path, std::wstring & content, bool clear_content = true); bool GetUTF8File(const std::wstring & file_path, std::wstring & content, bool clear_content = true); +bool GetBinaryFile(const wchar_t * file_path, BinaryPage & content, bool clear_content = true); +bool GetBinaryFile(const std::wstring & file_path, BinaryPage & content, bool clear_content = true); const wchar_t * GetFileExt(const wchar_t * name); diff --git a/winixd/functions/download.cpp b/winixd/functions/download.cpp index 1c80f33..ecb1c99 100644 --- a/winixd/functions/download.cpp +++ b/winixd/functions/download.cpp @@ -73,18 +73,32 @@ void Download::MakeGet() cur->request->send_as_attachment = cur->request->IsParam(L"attachment"); bool is_thumb = (cur->request->item.item_content.file_has_thumb && cur->request->IsParam(L"thumb")); - if( config->send_file_mode == 0 ) + if( config->send_file_mode == 0 || config->send_file_mode == 1 ) { system->MakeFilePath(cur->request->item, cur->request->x_sendfile, is_thumb); + + if( config->send_file_mode == 0 ) + { + log << log3 << "Download: reading content of file: " << cur->request->x_sendfile << logend; + + if( !GetBinaryFile(cur->request->x_sendfile, cur->request->out_bin_stream) ) + { + log << log1 << "Download: I cannot read the content of the file: " << cur->request->x_sendfile << logend; + } + + // IMPROVEME it would be good to set Content-Type header too + cur->request->x_sendfile.clear(); + cur->request->send_bin_stream = true; + } } else - if( config->send_file_mode == 1 ) + if( config->send_file_mode == 2 ) { system->MakeRelativeFilePath(cur->request->item, config->send_file_relative_prefix, cur->request->x_sendfile, is_thumb); } else { - log << log1 << "Download: send_file_mode in the config should be either 0 or 1" << logend; + log << log1 << "Download: send_file_mode in the config should be either 0, 1 or 2" << logend; } }