Browse Source

media_download: fix md_mkdir_parent for Windows (drive letter, backslash), add errno to fopen errors, sanitize base_filename with WARNING

topo_upd
Evgeny 2 months ago
parent
commit
fa5878ef4b
  1. 26
      src/chat/chat_msg.c
  2. 11
      src/media_delivery/media_download.c
  3. 2
      tools/chatgui/src/accountlist.cpp

26
src/chat/chat_msg.c

@ -434,6 +434,22 @@ static void md_download_done_cb(void* arg, int err) {
u_free(ctx);
}
static void sanitize_filename(char* buf, size_t size) {
char orig[256]; snprintf(orig, sizeof(orig), "%s", buf);
size_t w = 0;
for (size_t r = 0; buf[r]; r++) {
char c = buf[r];
if ((unsigned char)c < 0x20) continue;
if (c == '/' || c == '\\' || c == ':' || c == '*' || c == '?'
|| c == '"' || c == '<' || c == '>' || c == '|') continue;
if (w < size - 1) buf[w++] = c;
}
buf[w] = '\0';
if (w == 0) snprintf(buf, size, "file");
if (strcmp(orig, buf) != 0)
DEBUG_WARN(DEBUG_CATEGORY_GENERAL, "%s: filename sanitized [%s] -> [%s]", CC_ID, orig, buf);
}
static int md_start_download(struct UTUN_INSTANCE* inst,
const char* data_str, size_t data_len,
const char* ch_id, const char* base_filename,
@ -503,8 +519,8 @@ static int md_start_download(struct UTUN_INSTANCE* inst,
snprintf(ctx->dest_relpath, sizeof(ctx->dest_relpath), "%s", fp_name);
if (author_sig) memcpy(ctx->author_sig, author_sig, 64);
DEBUG_INFO(DEBUG_CATEGORY_GENERAL, "%s: download start ch=%s media=%02x%02x... blocks=%d size=%lld dest=%s",
CC_ID, ch_id, result.media_id[0], result.media_id[1], nb, (long long)fsize, dest);
DEBUG_INFO(DEBUG_CATEGORY_GENERAL, "%s: download start ch=%s file=%s blocks=%d size=%lld dest=%s",
CC_ID, ch_id, base_filename, nb, (long long)fsize, dest);
media_download_start(inst, 0, &result, dest, media_base, author_node_id, md_download_done_cb, ctx, md_download_progress_cb, ctx);
media_index_result_free(&result);
return 0;
@ -561,9 +577,10 @@ void on_msg_inserted(struct DB_SYNC_INSTANCE* si, uint64_t record_ts, const char
uint8_t dec[256]; int dlen = (int)b64_decode(base_filename + 1, bfi - 1, dec, sizeof(dec));
if (dlen > 0 && dlen < (int)sizeof(base_filename)) { memcpy(base_filename, dec, (size_t)dlen); base_filename[dlen] = '\0'; }
}
if (bfi == 0) snprintf(base_filename, sizeof(base_filename), "file");
if (bfi == 0) snprintf(base_filename, sizeof(base_filename), "file");
sanitize_filename(base_filename, sizeof(base_filename));
const uint8_t* sig_field = (const uint8_t*)strstr(buf, "\"sig\":\"");
const uint8_t* sig_field = (const uint8_t*)strstr(buf, "\"sig\":\"");
uint8_t author_sig[64] = {0};
if (sig_field) {
/* read author_signature from DB — find by ts in on_msg_inserted we don't have sig
@ -647,6 +664,7 @@ void chat_core_attachment_download(const char* channel_id, int64_t msg_id) {
if (dlen > 0 && dlen < (int)sizeof(base_filename)) { memcpy(base_filename, dec, (size_t)dlen); base_filename[dlen] = '\0'; }
}
if (bfi == 0) snprintf(base_filename, sizeof(base_filename), "file");
sanitize_filename(base_filename, sizeof(base_filename));
uint8_t author_sig[64]; memcpy(author_sig, sig_blob, 64);
sqlite3_finalize(st);

11
src/media_delivery/media_download.c

@ -45,8 +45,11 @@ static void md_dl_free(struct media_download* dl) {
static void md_mkdir_parent(const char* filepath) {
char path[1024]; snprintf(path, sizeof(path), "%s", filepath);
char* p = path[0] == '/' ? path + 1 : path;
while ((p = strchr(p, '/'))) {
char* p = path;
if (((p[0] >= 'A' && p[0] <= 'Z') || (p[0] >= 'a' && p[0] <= 'z')) && p[1] == ':')
p += 2;
while (*p == '/' || *p == '\\') p++;
while ((p = strpbrk(p, "/\\"))) {
*p = '\0';
if (utun_mkdir(path, 0755) != 0 && errno != EEXIST) {
DEBUG_ERROR(DEBUG_CATEGORY_GENERAL, "%s: mkdir(%s) failed: %s", MDL_ID, path, strerror(errno));
@ -381,7 +384,7 @@ void media_download_handle_chunk(struct UTUN_INSTANCE* inst,
char tmp[2048];
snprintf(tmp, sizeof(tmp), "%s.chunk_%d", dl->dest_path, bi);
FILE* f = fopen(tmp, "ab");
if (!f) { DEBUG_ERROR(DEBUG_CATEGORY_GENERAL, "%s: fopen(%s) failed for chunk write", MDL_ID, tmp); return; }
if (!f) { DEBUG_ERROR(DEBUG_CATEGORY_GENERAL, "%s: fopen(%s) failed for chunk write: %s", MDL_ID, tmp, strerror(errno)); return; }
size_t wlen = ch->data_len;
if (len >= MEDIA_BLOCK_CHUNK_HDR_SIZE + wlen) {
fwrite(d + MEDIA_BLOCK_CHUNK_HDR_SIZE, 1, wlen, f);
@ -540,7 +543,7 @@ void media_download_handle_done(struct UTUN_INSTANCE* inst,
if (dl->blocks_validated == dl->num_blocks) {
/* assemble file */
FILE* out = fopen(dl->dest_path, "wb");
if (!out) { DEBUG_ERROR(DEBUG_CATEGORY_GENERAL, "%s: fopen(%s) failed for assembly", MDL_ID, dl->dest_path); }
if (!out) { DEBUG_ERROR(DEBUG_CATEGORY_GENERAL, "%s: fopen(%s) failed for assembly: %s", MDL_ID, dl->dest_path, strerror(errno)); }
else {
for (int n = 0; n < dl->num_blocks; n++) {
char tmp2[2048];

2
tools/chatgui/src/accountlist.cpp

@ -84,6 +84,8 @@ AccountList::AccountList(DbManager* db, QWidget *parent)
memberSplitter->setSizes({360, 240});
layout->addWidget(memberSplitter, 1);
connect(m_listView->selectionModel(), &QItemSelectionModel::selectionChanged,
m_listView->viewport(), qOverload<>(&QWidget::update));
connect(m_listView, &QListView::clicked, this, &AccountList::onMemberClicked);
connect(m_listView, &QListView::doubleClicked, this, &AccountList::onMemberDoubleClicked);

Loading…
Cancel
Save