|
|
|
|
@ -959,6 +959,18 @@ 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'; |
|
|
|
|
const char* group_name = ""; |
|
|
|
|
int invite = ct && !strcmp(ct, "invite"); |
|
|
|
|
if (invite) { |
|
|
|
|
char* separator = memchr(text, '\0', plen); |
|
|
|
|
if (!separator || (size_t)(separator - text) + 8 > plen || |
|
|
|
|
strncmp(separator + 1, "utun://", 7) || memchr(separator + 1, '\0', plen - (separator + 1 - text))) { |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_DM, "invite PM: malformed payload conv=%s seq=%llu bytes=%zu", conv_id, |
|
|
|
|
(unsigned long long)seq, plen); |
|
|
|
|
goto fail; |
|
|
|
|
} |
|
|
|
|
group_name = text; |
|
|
|
|
} |
|
|
|
|
struct attachment_info attachment = {0}; |
|
|
|
|
int file = ct && !strcmp(ct, "file"); |
|
|
|
|
if (file) { |
|
|
|
|
@ -970,15 +982,19 @@ int dm_list_messages_json(struct UTUN_INSTANCE* inst, const char* conv_id, int c
|
|
|
|
|
const char* path = ready == 1 ? (const char*)sqlite3_column_text(st, 10) : ""; |
|
|
|
|
const char* status = delivered && dir ? "delivered" : ready == 1 ? "ready" : downloading ? "downloading" : |
|
|
|
|
ready < 0 ? "expired" : "pending"; |
|
|
|
|
char esc_ct[512], esc_data[DM_DATA_MAX * 2 + 8], esc_path[2048]; |
|
|
|
|
json_escape(ct ? ct : "", esc_ct, sizeof(esc_ct)); json_escape(text, esc_data, sizeof(esc_data)); |
|
|
|
|
char esc_ct[512], esc_data[DM_DATA_MAX * 6 + 1], esc_group[DM_DATA_MAX * 6 + 1], esc_path[2048]; |
|
|
|
|
json_escape(group_name, esc_group, sizeof(esc_group)); |
|
|
|
|
const char* display_data = invite ? text + strlen(group_name) + 1 : text; |
|
|
|
|
json_escape(ct ? ct : "", esc_ct, sizeof(esc_ct)); json_escape(display_data, 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," |
|
|
|
|
"\"tags\":{\"group_name\":\"%s\"}," |
|
|
|
|
"\"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), file ? attachment_content_type(attachment.kind) : "text/plain", |
|
|
|
|
(unsigned long long)sqlite3_column_int64(st, 11), esc_group, |
|
|
|
|
file ? attachment_content_type(attachment.kind) : "text/plain", |
|
|
|
|
attachment.duration_ms, attachment.width, attachment.height, attachment.waveform) < 0) goto fail; |
|
|
|
|
first = 0; |
|
|
|
|
} |
|
|
|
|
@ -1065,10 +1081,25 @@ static void dm_invite_ready(void* arg, int result, const char* link) {
|
|
|
|
|
char conv[64]; |
|
|
|
|
snprintf(conv, sizeof(conv), "%llu", (unsigned long long)dm_derive_conv_id(req->inst->node_id, req->peer_node_id)); |
|
|
|
|
size_t bytes = strlen(link); |
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_DM, "invite PM: registered request=%llu peer=%llu ch=%llu bytes=%zu ttl=%ds", |
|
|
|
|
sqlite3_stmt* st = NULL; |
|
|
|
|
char channel[64], payload[DM_DATA_MAX]; |
|
|
|
|
snprintf(channel, sizeof(channel), "%llu", (unsigned long long)req->channel_id); |
|
|
|
|
struct dm_state* dm = dm_of(req->inst); |
|
|
|
|
int rc = sqlite3_prepare_v2(dm->db, "SELECT name FROM channels WHERE channel_id=?", -1, &st, NULL); |
|
|
|
|
if (rc == SQLITE_OK) { sqlite3_bind_text(st, 1, channel, -1, SQLITE_STATIC); rc = sqlite3_step(st); } |
|
|
|
|
size_t name_bytes = rc == SQLITE_ROW ? (size_t)sqlite3_column_bytes(st, 0) : 0; |
|
|
|
|
if (rc != SQLITE_ROW || name_bytes + 1 + bytes > sizeof(payload)) { |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_DM, "invite PM: group metadata failed ch=%s rc=%d name_bytes=%zu link_bytes=%zu sql=%s", |
|
|
|
|
channel, rc, name_bytes, bytes, sqlite3_errmsg(dm->db)); |
|
|
|
|
sqlite3_finalize(st); dm_invite_done(req, DM_INVITE_SEND_ERROR); return; |
|
|
|
|
} |
|
|
|
|
memcpy(payload, sqlite3_column_text(st, 0), name_bytes); payload[name_bytes] = '\0'; |
|
|
|
|
memcpy(payload + name_bytes + 1, link, bytes); |
|
|
|
|
sqlite3_finalize(st); |
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_DM, "invite PM: registered request=%llu peer=%llu ch=%llu name_bytes=%zu link_bytes=%zu ttl=%ds", |
|
|
|
|
(unsigned long long)req->request_id, (unsigned long long)req->peer_node_id, |
|
|
|
|
(unsigned long long)req->channel_id, bytes, JOIN_KEY_TTL_SECONDS); |
|
|
|
|
int rc = dm_send(req->inst, conv, "text", (const uint8_t*)link, (uint32_t)bytes); |
|
|
|
|
(unsigned long long)req->channel_id, name_bytes, bytes, JOIN_KEY_TTL_SECONDS); |
|
|
|
|
rc = dm_send(req->inst, conv, "invite", (const uint8_t*)payload, (uint32_t)(name_bytes + 1 + bytes)); |
|
|
|
|
if (rc) DEBUG_ERROR(DEBUG_CATEGORY_DM, "invite PM: send failed request=%llu conv=%s rc=%d", |
|
|
|
|
(unsigned long long)req->request_id, conv, rc); |
|
|
|
|
dm_invite_done(req, rc ? DM_INVITE_SEND_ERROR : DM_INVITE_OK); |
|
|
|
|
|