|
28 | 28 | #include <vector> |
29 | 29 | #include <memory> |
30 | 30 | #include <cinttypes> |
| 31 | +#include <filesystem> |
| 32 | +#include <fstream> |
31 | 33 |
|
32 | 34 | #define DEFAULT_OAICOMPAT_MODEL "gpt-3.5-turbo" |
33 | 35 |
|
@@ -530,7 +532,7 @@ struct oaicompat_parser_options { |
530 | 532 | bool allow_image; |
531 | 533 | bool allow_audio; |
532 | 534 | bool enable_thinking = true; |
533 | | - int32_t local_media_max_size_mb; |
| 535 | + size_t local_media_max_size_mb; |
534 | 536 | std::string allowed_local_media_path; |
535 | 537 | }; |
536 | 538 |
|
@@ -642,36 +644,35 @@ static json oaicompat_chat_params_parse( |
642 | 644 |
|
643 | 645 | } else if (string_starts_with(url, "file://")) { |
644 | 646 | // Strip off the leading "file://" |
645 | | - std::string fname = url.substr(7); |
646 | | - std::vector<std::string> fparts = string_split<std::string>(fname, std::filesystem::path::preferred_separator); |
647 | | - for (const auto &piece : fparts) { |
648 | | - if (piece != "" && !fs_validate_filename(piece)) { |
649 | | - throw std::runtime_error("Invalid filename piece '" + piece + "': " + fname); |
650 | | - } |
| 647 | + const std::string fname = url.substr(7); |
| 648 | + if (opt.allowed_local_media_path == "") { |
| 649 | + throw std::runtime_error("Local media paths are not enabled"); |
651 | 650 | } |
652 | | - // Check allowed local media path |
653 | | - if (opt.allowed_local_media_path == "" || !string_starts_with(fname, opt.allowed_local_media_path)) { |
654 | | - throw std::runtime_error("File path not allowed"); |
| 651 | + const std::filesystem::path allowed_local_media_path = std::filesystem::canonical(std::filesystem::path(opt.allowed_local_media_path)); |
| 652 | + const std::filesystem::path input_path = std::filesystem::canonical(std::filesystem::path(fname)); |
| 653 | + if (!std::filesystem::is_directory(allowed_local_media_path)) { |
| 654 | + throw std::runtime_error("Invalid local media path: " + opt.allowed_local_media_path); |
655 | 655 | } |
656 | | - // load local file path |
657 | | - raw_buffer buf; |
658 | | - FILE * f = fopen(fname.c_str(), "rb"); |
659 | | - if (!f) { |
660 | | - SVR_ERR("Unable to open file %s: %s\n", fname.c_str(), strerror(errno)); |
661 | | - throw std::runtime_error("Unable to open image file"); |
| 656 | + auto [allowed_end, nothing] = std::mismatch(allowed_local_media_path.begin(), allowed_local_media_path.end(), input_path.begin()); |
| 657 | + if (allowed_end != allowed_local_media_path.end()) { |
| 658 | + throw std::runtime_error("Local media file path not allowed: " + fname); |
| 659 | + } |
| 660 | + if (!std::filesystem::is_regular_file(input_path)) { |
| 661 | + throw std::runtime_error("Local media file does not exist: " + fname); |
662 | 662 | } |
663 | | - fseek(f, 0, SEEK_END); |
664 | | - long file_size = ftell(f); |
| 663 | + const auto file_size = std::filesystem::file_size(input_path); |
665 | 664 | if (file_size > opt.local_media_max_size_mb * 1024 * 1024) { |
666 | | - fclose(f); |
667 | | - throw std::runtime_error("Local file exceeds maximum allowed size"); |
| 665 | + throw std::runtime_error("Local media file exceeds maximum allowed size"); |
| 666 | + } |
| 667 | + // load local file path |
| 668 | + std::ifstream f(input_path, std::ios::binary); |
| 669 | + if (!f) { |
| 670 | + SRV_ERR("Unable to open file %s: %s\n", fname.c_str(), strerror(errno)); |
| 671 | + throw std::runtime_error("Unable to open local media file: " + fname); |
668 | 672 | } |
669 | | - fseek(f, 0, SEEK_SET); |
670 | | - buf.resize(file_size); |
671 | | - size_t n_read = fread(buf.data(), 1, file_size, f); |
672 | | - fclose(f); |
673 | | - if (n_read != (size_t)file_size) { |
674 | | - SVR_ERR("Failed to read entire file %s", fname.c_str()); |
| 673 | + raw_buffer buf((std::istreambuf_iterator(f)), std::istreambuf_iterator<char>()); |
| 674 | + if (buf.size() != file_size) { |
| 675 | + SRV_ERR("Failed to read entire file %s", fname.c_str()); |
675 | 676 | throw std::runtime_error("Failed to read entire image file"); |
676 | 677 | } |
677 | 678 | out_files.push_back(buf); |
|
0 commit comments