Use validated paths for media submission and backfill
This commit is contained in:
1 parent
16a5e628fd
commit
15fafc42c9
1 file changed
+25
-54
+25
-54
@@ -375,9 +375,14 @@ void chat_core_submit_media_message(struct UTUN_INSTANCE* inst, struct chat_msg_
|
||||
if (req) chat_event_submitted(inst, req->request_id, 0);
|
||||
return;
|
||||
}
|
||||
char media_base[MEDIA_BASE_MAX], location[MEDIA_PATH_MAX], destination[MEDIA_PATH_MAX];
|
||||
if (media_index_get_base(cc->db, media_base) || media_index_location(req->media_dest, media_base, location)
|
||||
|| media_index_path(media_base, location, destination)) {
|
||||
chat_event_submitted(inst, req->request_id, 0); return;
|
||||
}
|
||||
for (struct media_submit_ctx* pending = cc->media_submissions; pending; pending = pending->next) {
|
||||
if ((!strcmp(pending->channel_id, req->channel_id) && pending->delete_pending)
|
||||
|| !strcmp(pending->media_dest, req->media_dest)) {
|
||||
|| !strcmp(pending->media_dest, destination)) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_MEDIA, "media submit rejected: channel deleting/destination busy ch=%s path=%s",
|
||||
req->channel_id, req->media_dest);
|
||||
chat_event_submitted(inst, req->request_id, 0); return;
|
||||
@@ -419,9 +424,7 @@ void chat_core_submit_media_message(struct UTUN_INSTANCE* inst, struct chat_msg_
|
||||
}
|
||||
|
||||
/* build media_base from db_path: dirname(db_path) e.g. /path/to/data */
|
||||
char media_base[MEDIA_BASE_MAX], location[MEDIA_PATH_MAX];
|
||||
if (media_index_get_base(cc->db, media_base) || media_index_location(req->media_dest, media_base, location)
|
||||
|| media_index_track_preparation(cc->db, req->channel_id, req->media_dest, media_base)) {
|
||||
if (media_index_track_preparation(cc->db, req->channel_id, destination, media_base)) {
|
||||
chat_event_submitted(inst, req->request_id, 0); return;
|
||||
}
|
||||
|
||||
@@ -437,7 +440,7 @@ void chat_core_submit_media_message(struct UTUN_INSTANCE* inst, struct chat_msg_
|
||||
memcpy(mctx->reply_hex, reply_hex, strlen(reply_hex) + 1);
|
||||
snprintf(mctx->channel_id, sizeof(mctx->channel_id), "%s", req->channel_id);
|
||||
snprintf(mctx->content_type, sizeof(mctx->content_type), "%s", req->content_type);
|
||||
snprintf(mctx->media_dest, sizeof(mctx->media_dest), "%s", req->media_dest);
|
||||
snprintf(mctx->media_dest, sizeof(mctx->media_dest), "%s", destination);
|
||||
mctx->timestamp = req->timestamp;
|
||||
mctx->duration_ms = req->duration_ms;
|
||||
mctx->width = req->width;
|
||||
@@ -448,7 +451,7 @@ void chat_core_submit_media_message(struct UTUN_INSTANCE* inst, struct chat_msg_
|
||||
}
|
||||
|
||||
if (req->media_video) {
|
||||
if (video_transcode_start(inst->media_async, inst->ua, req->media_src, req->media_dest, on_video_prepared, mctx) < 0)
|
||||
if (video_transcode_start(inst->media_async, inst->ua, req->media_src, destination, on_video_prepared, mctx) < 0)
|
||||
on_video_prepared(mctx, -1, NULL);
|
||||
return;
|
||||
}
|
||||
@@ -457,7 +460,7 @@ void chat_core_submit_media_message(struct UTUN_INSTANCE* inst, struct chat_msg_
|
||||
inst->media_async, inst->ua, cc->db,
|
||||
cc->my_node_id, inst->my_ed25519_privkey,
|
||||
req->channel_id,
|
||||
req->media_src, req->media_dest, req->media_copy ? 1 : 0,
|
||||
req->media_src, destination, req->media_copy ? 1 : 0,
|
||||
media_base,
|
||||
on_media_registered, mctx);
|
||||
}
|
||||
@@ -910,16 +913,10 @@ static int md_start_download(struct UTUN_INSTANCE* inst,
|
||||
char final_name[256];
|
||||
media_final_name(&result, content_type, base_filename, final_name, sizeof(final_name));
|
||||
|
||||
char dest[1024], media_base[512];
|
||||
{
|
||||
const char* last_slash = strrchr(cc->db_path, '/');
|
||||
if (last_slash) {
|
||||
snprintf(media_base, sizeof(media_base), "%.*s", (int)(last_slash - cc->db_path), cc->db_path);
|
||||
} else {
|
||||
snprintf(media_base, sizeof(media_base), "%s", cc->db_path);
|
||||
}
|
||||
}
|
||||
snprintf(dest, sizeof(dest), "%s/media/%s/%s", media_base, ch_id, final_name);
|
||||
char dest[MEDIA_PATH_MAX], media_base[MEDIA_BASE_MAX], relative[MEDIA_PATH_MAX];
|
||||
int length = snprintf(relative, sizeof(relative), "media/%s/%s", ch_id, final_name);
|
||||
if (length < 0 || length >= (int)sizeof(relative) || media_index_get_base(cc->db, media_base)
|
||||
|| media_index_path(media_base, relative, dest)) { media_index_result_free(&result); return -1; }
|
||||
|
||||
struct md_done_ctx* ctx = u_calloc(1, sizeof(*ctx));
|
||||
if (!ctx) { media_index_result_free(&result); return -1; }
|
||||
@@ -936,9 +933,13 @@ static int md_start_download(struct UTUN_INSTANCE* inst,
|
||||
DEBUG_INFO(DEBUG_CATEGORY_GENERAL, "%s: download start ch=%s ct=%s file=%s blocks=%d size=%lld dest=%s",
|
||||
CC_ID, ch_id, content_type ? content_type : "?", final_name, nb, (long long)fsize, dest);
|
||||
uint64_t gid = strtoull(ch_id, NULL, 10);
|
||||
media_download_start(inst, gid, &result, dest, media_base, author_node_id, md_download_done_cb, ctx, md_download_progress_cb, ctx);
|
||||
int started = media_download_start(inst, gid, &result, dest, media_base, author_node_id,
|
||||
md_download_done_cb, ctx, md_download_progress_cb, ctx);
|
||||
media_index_result_free(&result);
|
||||
return 0;
|
||||
if (started < 0) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_MEDIA, "media download rejected ch=%s path=%s", ch_id, dest); u_free(ctx);
|
||||
}
|
||||
return started;
|
||||
}
|
||||
|
||||
static int md_auto_download(struct UTUN_INSTANCE* inst,
|
||||
@@ -1136,10 +1137,8 @@ void chat_media_backfill(struct UTUN_INSTANCE* inst) {
|
||||
struct chat_core_ctx* cc = CC(inst);
|
||||
if (!cc || !cc->initialized || !cc->db) return;
|
||||
|
||||
char media_base[512];
|
||||
const char* last_slash = strrchr(cc->db_path, '/');
|
||||
if (last_slash) snprintf(media_base, sizeof(media_base), "%.*s", (int)(last_slash - cc->db_path), cc->db_path);
|
||||
else snprintf(media_base, sizeof(media_base), "%s", cc->db_path);
|
||||
char media_base[MEDIA_BASE_MAX];
|
||||
if (media_index_get_base(cc->db, media_base)) return;
|
||||
|
||||
int total = 0;
|
||||
sqlite3_stmt* cs = NULL;
|
||||
@@ -1198,37 +1197,9 @@ void chat_media_backfill(struct UTUN_INSTANCE* inst) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int registered = 0;
|
||||
for (int n = 0; n < result.num_blocks; n++) {
|
||||
int exists = 0;
|
||||
sqlite3_stmt* ex = NULL;
|
||||
if (sqlite3_prepare_v2(cc->db, "SELECT 1 FROM media_files WHERE block_id=? LIMIT 1", -1, &ex, NULL) == SQLITE_OK) {
|
||||
sqlite3_bind_blob(ex, 1, result.block_ids + n * 16, 16, SQLITE_STATIC);
|
||||
exists = (sqlite3_step(ex) == SQLITE_ROW);
|
||||
sqlite3_finalize(ex);
|
||||
}
|
||||
if (exists) continue;
|
||||
|
||||
char rel[512];
|
||||
size_t bl = strlen(media_base);
|
||||
if (strncmp(path, media_base, bl) == 0 && path[bl] == '/') snprintf(rel, sizeof(rel), "%s", path + bl + 1);
|
||||
else snprintf(rel, sizeof(rel), "%s", path);
|
||||
|
||||
int64_t chunk_size = (n == result.num_blocks - 1) ? result.file_size - (int64_t)n * result.block_size : result.block_size;
|
||||
int64_t offset = (int64_t)n * result.block_size;
|
||||
|
||||
if (media_index_register_downloaded(cc->db, result.media_id, result.block_ids + n * 16,
|
||||
result.content_hash, ch_id, rel, cc->my_node_id,
|
||||
result.file_size, chunk_size, n, offset) == 0) {
|
||||
registered++;
|
||||
}
|
||||
}
|
||||
|
||||
if (registered > 0) {
|
||||
total += registered;
|
||||
DEBUG_INFO(DEBUG_CATEGORY_GENERAL, "%s: backfill registered %d blocks ch=%s file=%s",
|
||||
CC_ID, registered, ch_id, final_name);
|
||||
}
|
||||
int registered = media_index_register_downloaded_file(cc->db, &result, cc->my_node_id, ch_id, path, media_base);
|
||||
if (!registered) total += result.num_blocks;
|
||||
else DEBUG_ERROR(DEBUG_CATEGORY_MEDIA, "media backfill registration failed ch=%s file=%s", ch_id, path);
|
||||
|
||||
u_free(body);
|
||||
media_index_result_free(&result);
|
||||
|
||||
Reference in new issue
Block a user