Skip to content

Commit d6d5e18

Browse files
committed
modernized local media file handling with std::filesystem and std::ifstream
1 parent aef7dd3 commit d6d5e18

File tree

4 files changed

+39
-38
lines changed

4 files changed

+39
-38
lines changed

common/arg.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3304,9 +3304,9 @@ common_params_context common_params_parser_init(common_params & params, llama_ex
33043304
).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_ALLOWED_LOCAL_MEDIA_PATH"));
33053305
add_opt(common_arg(
33063306
{"--local-media-max-size-mb"}, "N",
3307-
string_format("max size in mb for local media files (default: %d)", params.local_media_max_size_mb),
3307+
string_format("max size in mb for local media files (default: %lu)", params.local_media_max_size_mb),
33083308
[](common_params & params, int value) {
3309-
params.local_media_max_size_mb = value;
3309+
params.local_media_max_size_mb = static_cast<size_t>(value);
33103310
}
33113311
).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_LOCAL_MEDIA_MAX_SIZE_MB"));
33123312
add_opt(common_arg(

common/common.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,7 @@ struct common_params {
429429
int32_t n_cache_reuse = 0; // min chunk size to reuse from the cache via KV shifting
430430
int32_t n_ctx_checkpoints = 8; // max number of context checkpoints per slot
431431
int32_t cache_ram_mib = 8192; // -1 = no limit, 0 - disable, 1 = 1 MiB, etc.
432-
int32_t local_media_max_size_mb = 15; // max size of loaded local media files
432+
size_t local_media_max_size_mb = 15; // 0 = no limit, 15 = 1 MiB. Max size of loaded local media files
433433

434434
std::string hostname = "127.0.0.1";
435435
std::string public_path = ""; // NOLINT

tools/server/server.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2586,15 +2586,15 @@ struct server_context {
25862586
SRV_INF("thinking = %d\n", enable_thinking);
25872587

25882588
oai_parser_opt = {
2589-
/* use_jinja */ params_base.use_jinja,
2590-
/* prefill_assistant */ params_base.prefill_assistant,
2591-
/* reasoning_format */ params_base.reasoning_format,
2592-
/* chat_template_kwargs */ params_base.default_template_kwargs,
2593-
/* common_chat_templates */ chat_templates.get(),
2594-
/* allow_image */ mctx ? mtmd_support_vision(mctx) : false,
2595-
/* allow_audio */ mctx ? mtmd_support_audio (mctx) : false,
2596-
/* enable_thinking */ enable_thinking,
2597-
/* local_media_max_size_mb */ params_base.local_media_max_size_mb,
2589+
/* use_jinja */ params_base.use_jinja,
2590+
/* prefill_assistant */ params_base.prefill_assistant,
2591+
/* reasoning_format */ params_base.reasoning_format,
2592+
/* chat_template_kwargs */ params_base.default_template_kwargs,
2593+
/* common_chat_templates */ chat_templates.get(),
2594+
/* allow_image */ mctx ? mtmd_support_vision(mctx) : false,
2595+
/* allow_audio */ mctx ? mtmd_support_audio (mctx) : false,
2596+
/* enable_thinking */ enable_thinking,
2597+
/* local_media_max_size_mb */ params_base.local_media_max_size_mb,
25982598
/* allowed_local_media_path */ params_base.allowed_local_media_path,
25992599
};
26002600
}

tools/server/utils.hpp

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
#include <vector>
2929
#include <memory>
3030
#include <cinttypes>
31+
#include <filesystem>
32+
#include <fstream>
3133

3234
#define DEFAULT_OAICOMPAT_MODEL "gpt-3.5-turbo"
3335

@@ -530,7 +532,7 @@ struct oaicompat_parser_options {
530532
bool allow_image;
531533
bool allow_audio;
532534
bool enable_thinking = true;
533-
int32_t local_media_max_size_mb;
535+
size_t local_media_max_size_mb;
534536
std::string allowed_local_media_path;
535537
};
536538

@@ -642,36 +644,35 @@ static json oaicompat_chat_params_parse(
642644

643645
} else if (string_starts_with(url, "file://")) {
644646
// 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");
651650
}
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);
655655
}
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);
662662
}
663-
fseek(f, 0, SEEK_END);
664-
long file_size = ftell(f);
663+
const auto file_size = std::filesystem::file_size(input_path);
665664
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);
668672
}
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());
675676
throw std::runtime_error("Failed to read entire image file");
676677
}
677678
out_files.push_back(buf);

0 commit comments

Comments
 (0)