|
9 | 9 |
|
10 | 10 | #include "tl_serial.h" |
11 | 11 | #include "tl_registry.h" |
| 12 | +#include "tl_skip.h" |
12 | 13 | #include "mtproto_rpc.h" |
13 | 14 | #include "logger.h" |
14 | 15 | #include "raii.h" |
|
19 | 20 | #define CRC_contacts_getContacts 0x5dd69e12u |
20 | 21 | #define CRC_contact 0x145ade0bu |
21 | 22 |
|
22 | | -/* Copy at most dst_cap-1 bytes from src (NUL-terminates). */ |
23 | | -static void copy_str(char *dst, size_t dst_cap, const char *src) { |
24 | | - if (!dst || dst_cap == 0) return; |
25 | | - dst[0] = '\0'; |
26 | | - if (!src) return; |
27 | | - size_t n = strlen(src); |
28 | | - if (n >= dst_cap) n = dst_cap - 1; |
29 | | - memcpy(dst, src, n); |
30 | | - dst[n] = '\0'; |
31 | | -} |
32 | | - |
33 | | -/* Parse one User/UserEmpty from @r; fill id + name fields on @e. |
34 | | - * Unknown constructors are skipped via tl_skip_object. */ |
35 | | -static void parse_user_into(TlReader *r, ContactEntry *entries, int count) { |
36 | | - if (!tl_reader_ok(r)) return; |
37 | | - uint32_t crc = tl_read_uint32(r); |
38 | | - |
39 | | - if (crc == TL_userEmpty) { |
40 | | - /* userEmpty#d3bc4b7a id:long */ |
41 | | - int64_t id = tl_read_int64(r); |
42 | | - (void)id; |
43 | | - return; |
44 | | - } |
45 | | - if (crc != TL_user && crc != TL_user2) { |
46 | | - logger_log(LOG_WARN, "contacts: unknown User 0x%08x — skipping", crc); |
47 | | - return; |
48 | | - } |
49 | | - |
50 | | - uint32_t flags = tl_read_uint32(r); |
51 | | - (void)tl_read_uint32(r); /* flags2 */ |
52 | | - int64_t id = tl_read_int64(r); |
53 | | - |
54 | | - int64_t access_hash = 0; |
55 | | - if (flags & (1u << 0)) access_hash = tl_read_int64(r); |
56 | | - |
57 | | - char first_name[64] = {0}; |
58 | | - char last_name[64] = {0}; |
59 | | - char username[64] = {0}; |
60 | | - |
61 | | - if (flags & (1u << 1)) { RAII_STRING char *s = tl_read_string(r); copy_str(first_name, sizeof(first_name), s); } |
62 | | - if (flags & (1u << 2)) { RAII_STRING char *s = tl_read_string(r); copy_str(last_name, sizeof(last_name), s); } |
63 | | - if (flags & (1u << 3)) { RAII_STRING char *s = tl_read_string(r); copy_str(username, sizeof(username), s); } |
64 | | - |
65 | | - /* Match by user_id and fill name fields. */ |
66 | | - for (int i = 0; i < count; i++) { |
67 | | - if (entries[i].user_id == id) { |
68 | | - entries[i].access_hash = access_hash; |
69 | | - copy_str(entries[i].first_name, sizeof(entries[i].first_name), first_name); |
70 | | - copy_str(entries[i].last_name, sizeof(entries[i].last_name), last_name); |
71 | | - copy_str(entries[i].username, sizeof(entries[i].username), username); |
72 | | - break; |
73 | | - } |
74 | | - } |
75 | | -} |
76 | | - |
77 | 23 | int domain_get_contacts(const ApiConfig *cfg, |
78 | 24 | MtProtoSession *s, Transport *t, |
79 | 25 | ContactEntry *out, int max_entries, int *out_count) { |
@@ -140,13 +86,32 @@ int domain_get_contacts(const ApiConfig *cfg, |
140 | 86 | /* saved_count:int */ |
141 | 87 | tl_read_int32(&r); |
142 | 88 |
|
143 | | - /* users:Vector<User> — enriches the entries already written */ |
| 89 | + /* users:Vector<User> — tl_extract_user advances past the FULL object |
| 90 | + * so the cursor is correctly positioned for the next user each iteration. */ |
144 | 91 | uint32_t uvec = tl_read_uint32(&r); |
145 | 92 | if (uvec == TL_vector) { |
146 | 93 | uint32_t ucount = tl_read_uint32(&r); |
147 | 94 | for (uint32_t i = 0; i < ucount; i++) { |
148 | 95 | if (!tl_reader_ok(&r)) break; |
149 | | - parse_user_into(&r, out, written); |
| 96 | + UserSummary us = {0}; |
| 97 | + if (tl_extract_user(&r, &us) != 0) { |
| 98 | + logger_log(LOG_WARN, "contacts: user parse failed at index %u", i); |
| 99 | + break; |
| 100 | + } |
| 101 | + for (int j = 0; j < written; j++) { |
| 102 | + if (out[j].user_id == us.id) { |
| 103 | + out[j].access_hash = us.access_hash; |
| 104 | + size_t n = strlen(us.name); |
| 105 | + if (n >= sizeof(out[j].name)) n = sizeof(out[j].name) - 1; |
| 106 | + memcpy(out[j].name, us.name, n); |
| 107 | + out[j].name[n] = '\0'; |
| 108 | + n = strlen(us.username); |
| 109 | + if (n >= sizeof(out[j].username)) n = sizeof(out[j].username) - 1; |
| 110 | + memcpy(out[j].username, us.username, n); |
| 111 | + out[j].username[n] = '\0'; |
| 112 | + break; |
| 113 | + } |
| 114 | + } |
150 | 115 | } |
151 | 116 | } |
152 | 117 |
|
|
0 commit comments