From 1b3fd931505f38ba6f04be924a2dd9aac26d1817 Mon Sep 17 00:00:00 2001 From: koplenov Date: Sat, 9 May 2026 19:19:35 +0300 Subject: [PATCH] update image to xep-0385 --- xmpp.view.ts | 60 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 56 insertions(+), 4 deletions(-) diff --git a/xmpp.view.ts b/xmpp.view.ts index 740e022..b80965f 100644 --- a/xmpp.view.ts +++ b/xmpp.view.ts @@ -129,6 +129,44 @@ return msg_id } + static async hash_file(file: File, algorithm = 'SHA-256'): Promise { + const buffer = await file.arrayBuffer() + const digest = await crypto.subtle.digest(algorithm, buffer) + const bytes = new Uint8Array(digest) + let binary = '' + const chunk = 0x8000 + for (let i = 0; i < bytes.length; i += chunk) { + binary += String.fromCharCode(...bytes.subarray(i, i + chunk)) + } + return btoa(binary) + } + + send_media_sharing(to: string, body: string, file_name: string, size: number, mime: string, hash_algo: string, hash_value: string, get_url: string, type: 'chat' | 'groupchat' = 'chat', id?: string): string { + const msg_id = id ?? this._id() + const begin = body.indexOf(file_name) + const end = begin >= 0 ? begin + file_name.length : body.length + this._send( + `` + + `${ this._esc(body) }` + + `` + + `` + + `` + + `${ this._esc(mime) }` + + `${ this._esc(file_name) }` + + `${ size }` + + `${ this._esc(hash_value) }` + + `` + + `` + + `` + + `` + + `` + + `` + + `` + + `` + ) + return msg_id + } + // XEP-0333: send a chat marker (received/displayed/acknowledged) for a previously-received message id. send_marker(to: string, kind: 'received' | 'displayed' | 'acknowledged', id: string, type: 'chat' | 'groupchat' = 'chat') { console.log('[xmpp] → send_marker', { to, kind, id, type }) @@ -513,7 +551,18 @@ private _handle_message(el: Element) { } const type = el.getAttribute('type') || 'chat'; - const body = this._getBody(el); + let body = this._getBody(el); + if (!body) { + const reference = this._find(el, 'urn:xmpp:reference:0', 'reference') + if (reference?.getAttribute('type') === 'data') { + const media = reference.querySelector('media-sharing') + const file = media?.querySelector('file') + const name = file?.querySelector('name')?.textContent + const source = media?.querySelector('sources reference')?.getAttribute('uri') + if (name) body = `Shared file: ${ name }` + else if (source) body = source + } + } if (!body) return; // XEP-0333: peer requested chat markers for this message @@ -1946,9 +1995,12 @@ private _handle_message(el: Element) { if (!this._conn) throw new Error('Not connected') const { put, get } = await this._conn.request_slot(file.name, file.size, file.type) await Xmpp_conn.upload(put, file) - const id = `l${ Date.now() }_${ Math.random().toString(36).slice(2) }` - this._conn.send_message(jid, get, id) - this._add_message({ id, from: this.my_jid().split('/')[0], to: jid, body: get, time: Date.now() }) + const hash = await Xmpp_conn.hash_file(file) + const body = `Shared file: ${ file.name }` + const id = `l${ Date.now() }_${ Math.random().toString(36).slice(2) }` + const type = this._rooms.has(jid) ? 'groupchat' : 'chat' + this._conn.send_media_sharing(jid, body, file.name, file.size, file.type || 'application/octet-stream', 'sha-256', hash, get, type, id) + this._add_message({ id, from: this.my_jid().split('/')[0], to: jid, body, time: Date.now() }) this._scroll_to_bottom(jid) } }