|
|
|
|
@ -306,6 +306,8 @@ static int dm_build_body(struct dm_state* dm, const struct dm_conv* c, uint64_t
|
|
|
|
|
media = data; |
|
|
|
|
data += DM_MEDIA_DESC_SIZE; |
|
|
|
|
data_len -= DM_MEDIA_DESC_SIZE; |
|
|
|
|
struct attachment_info info; |
|
|
|
|
if (attachment_decode(data, data_len, &info)) return -1; |
|
|
|
|
} |
|
|
|
|
uint64_t conv_num = (uint64_t)strtoull(c->conv_id, NULL, 10); |
|
|
|
|
uint8_t nonce[DM_NONCE_SIZE]; |
|
|
|
|
@ -465,6 +467,10 @@ int dm_accept_message(struct UTUN_INSTANCE* inst, const uint8_t* msg, size_t len
|
|
|
|
|
size_t plain_len = 0; |
|
|
|
|
dm_build_nonce(conv, author, seq, nonce); |
|
|
|
|
if (dm_decrypt(c.content_key, nonce, msg + 35 + msg[32], enc_len, plain, &plain_len) != 0) return -1; |
|
|
|
|
if (dm_message_media(msg, len)) { |
|
|
|
|
struct attachment_info info; |
|
|
|
|
if (attachment_decode(plain, plain_len, &info)) return -1; |
|
|
|
|
} |
|
|
|
|
if (dm_exec(dm, "BEGIN IMMEDIATE") != 0) return -1; |
|
|
|
|
int inserted = dm_store_message(dm, conv_id, 0, msg, len); |
|
|
|
|
if (seq > c.last_in_seq) c.last_in_seq = seq; /* Только статистика; не курсор dedup. */ |
|
|
|
|
@ -939,6 +945,12 @@ int dm_list_messages_json(struct UTUN_INSTANCE* inst, const char* conv_id, int c
|
|
|
|
|
if (enc_len < DM_TAG_SIZE || enc_len > DM_DATA_MAX + DM_TAG_SIZE || |
|
|
|
|
dm_decrypt(c.content_key, nonce, enc, (size_t)enc_len, (uint8_t*)text, &plen)) goto fail; |
|
|
|
|
text[plen] = '\0'; |
|
|
|
|
struct attachment_info attachment = {0}; |
|
|
|
|
int file = ct && !strcmp(ct, "file"); |
|
|
|
|
if (file) { |
|
|
|
|
if (attachment_decode((const uint8_t*)text, plen, &attachment)) goto fail; |
|
|
|
|
snprintf(text, sizeof(text), "%s", attachment.name); |
|
|
|
|
} |
|
|
|
|
int ready = sqlite3_column_int(st, 7), downloading = sqlite3_column_int(st, 8); |
|
|
|
|
int delivered = sqlite3_column_bytes(st, 9) == DM_MEDIA_RECEIPT_SIZE; |
|
|
|
|
const char* path = ready == 1 ? (const char*)sqlite3_column_text(st, 10) : ""; |
|
|
|
|
@ -948,10 +960,12 @@ int dm_list_messages_json(struct UTUN_INSTANCE* inst, const char* conv_id, int c
|
|
|
|
|
json_escape(ct ? ct : "", esc_ct, sizeof(esc_ct)); json_escape(text, esc_data, sizeof(esc_data)); |
|
|
|
|
json_escape(path, esc_path, sizeof(esc_path)); |
|
|
|
|
if (strbuf_addf(&sb, "%s{\"dir\":%d,\"seq\":%llu,\"ts\":%llu,\"author\":\"%llu\",\"ct\":\"%s\",\"data\":\"%s\"," |
|
|
|
|
"\"pending\":%s,\"media_status\":\"%s\",\"media_path\":\"%s\",\"media_size\":%llu}", first ? "" : ",", dir, |
|
|
|
|
"\"pending\":%s,\"media_status\":\"%s\",\"media_path\":\"%s\",\"media_size\":%llu," |
|
|
|
|
"\"content_type\":\"%s\",\"duration_ms\":%u,\"width\":%u,\"height\":%u,\"waveform\":\"%s\"}", first ? "" : ",", dir, |
|
|
|
|
(unsigned long long)seq, (unsigned long long)ts, (unsigned long long)author, esc_ct, esc_data, |
|
|
|
|
sqlite3_column_int(st, 6) ? "true" : "false", status, esc_path, |
|
|
|
|
(unsigned long long)sqlite3_column_int64(st, 11)) < 0) goto fail; |
|
|
|
|
(unsigned long long)sqlite3_column_int64(st, 11), file ? attachment_content_type(attachment.kind) : "text/plain", |
|
|
|
|
attachment.duration_ms, attachment.width, attachment.height, attachment.waveform) < 0) goto fail; |
|
|
|
|
first = 0; |
|
|
|
|
} |
|
|
|
|
if (rc != SQLITE_DONE || strbuf_addf(&sb, "]") < 0 || sb.len + 1 > buf_size) goto fail; |
|
|
|
|
|