Line data Source code
1 : /* SPDX-License-Identifier: GPL-3.0-or-later */
2 : /* Copyright 2026 Peter Csaszar */
3 :
4 : /**
5 : * @file domain/write/edit.c
6 : * @brief messages.editMessage (US-P5-06).
7 : */
8 :
9 : #include "domain/write/edit.h"
10 :
11 : #include "tl_serial.h"
12 : #include "tl_registry.h"
13 : #include "mtproto_rpc.h"
14 : #include "logger.h"
15 :
16 : #include <string.h>
17 :
18 : #define CRC_messages_editMessage 0x48f71778u
19 :
20 4 : static int write_input_peer(TlWriter *w, const HistoryPeer *p) {
21 4 : switch (p->kind) {
22 4 : case HISTORY_PEER_SELF:
23 4 : tl_write_uint32(w, TL_inputPeerSelf);
24 4 : return 0;
25 0 : case HISTORY_PEER_USER:
26 0 : tl_write_uint32(w, TL_inputPeerUser);
27 0 : tl_write_int64 (w, p->peer_id);
28 0 : tl_write_int64 (w, p->access_hash);
29 0 : return 0;
30 0 : case HISTORY_PEER_CHAT:
31 0 : tl_write_uint32(w, TL_inputPeerChat);
32 0 : tl_write_int64 (w, p->peer_id);
33 0 : return 0;
34 0 : case HISTORY_PEER_CHANNEL:
35 0 : tl_write_uint32(w, TL_inputPeerChannel);
36 0 : tl_write_int64 (w, p->peer_id);
37 0 : tl_write_int64 (w, p->access_hash);
38 0 : return 0;
39 0 : default:
40 0 : return -1;
41 : }
42 : }
43 :
44 4 : int domain_edit_message(const ApiConfig *cfg,
45 : MtProtoSession *s, Transport *t,
46 : const HistoryPeer *peer,
47 : int32_t msg_id,
48 : const char *new_text,
49 : RpcError *err) {
50 4 : if (!cfg || !s || !t || !peer || !new_text) return -1;
51 4 : size_t mlen = strlen(new_text);
52 4 : if (mlen == 0 || mlen > 4096) {
53 0 : logger_log(LOG_ERROR, "edit: text length %zu out of bounds", mlen);
54 0 : return -1;
55 : }
56 4 : if (msg_id <= 0) return -1;
57 :
58 4 : TlWriter w; tl_writer_init(&w);
59 4 : tl_write_uint32(&w, CRC_messages_editMessage);
60 4 : tl_write_uint32(&w, 1u << 11); /* flags: only message set */
61 4 : if (write_input_peer(&w, peer) != 0) {
62 0 : tl_writer_free(&w);
63 0 : return -1;
64 : }
65 4 : tl_write_int32 (&w, msg_id);
66 4 : tl_write_string(&w, new_text);
67 :
68 : uint8_t query[8192];
69 4 : if (w.len > sizeof(query)) { tl_writer_free(&w); return -1; }
70 4 : memcpy(query, w.data, w.len);
71 4 : size_t qlen = w.len;
72 4 : tl_writer_free(&w);
73 :
74 4 : uint8_t resp[4096]; size_t resp_len = 0;
75 4 : if (api_call(cfg, s, t, query, qlen, resp, sizeof(resp), &resp_len) != 0) {
76 0 : logger_log(LOG_ERROR, "edit: api_call failed");
77 0 : return -1;
78 : }
79 4 : if (resp_len < 4) return -1;
80 :
81 : uint32_t top;
82 4 : memcpy(&top, resp, 4);
83 4 : if (top == TL_rpc_error) {
84 3 : if (err) rpc_parse_error(resp, resp_len, err);
85 3 : return -1;
86 : }
87 : /* Any Updates envelope = success. */
88 1 : if (top == TL_updates || top == TL_updatesCombined
89 0 : || top == TL_updateShort) {
90 1 : return 0;
91 : }
92 0 : logger_log(LOG_WARN, "edit: unexpected top 0x%08x — assuming success", top);
93 0 : return 0;
94 : }
|