1 /*
2     This file is part of tgl-library
3 
4     This library is free software; you can redistribute it and/or
5     modify it under the terms of the GNU Lesser General Public
6     License as published by the Free Software Foundation; either
7     version 2.1 of the License, or (at your option) any later version.
8 
9     This library is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12     Lesser General Public License for more details.
13 
14     You should have received a copy of the GNU Lesser General Public
15     License along with this library; if not, write to the Free Software
16     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17 
18     Copyright Vitaly Valtman 2013-2015
19 */
20 
21 #ifdef HAVE_CONFIG_H
22 #  include "config.h"
23 #endif
24 
25 #include <unistd.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <sys/file.h>
29 #include <stdlib.h>
30 #include <fcntl.h>
31 #include <errno.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <assert.h>
35 #include "crypto/bn.h"
36 
37 #include "tgl-binlog.h"
38 #include "mtproto-common.h"
39 //#include "net.h"
40 #include "mtproto-client.h"
41 #include "mtproto-utils.h"
42 
43 #include "tgl.h"
44 #include "auto.h"
45 #include "auto/auto-types.h"
46 #include "auto/auto-skip.h"
47 #include "auto/auto-store-ds.h"
48 #include "auto/auto-fetch-ds.h"
49 #include "auto/auto-free-ds.h"
50 
51 #include "tgl-structures.h"
52 #include "tgl-methods-in.h"
53 
54 #include "crypto/sha.h"
55 
mystreq1(const char * a,const char * b,int l)56 static int mystreq1 (const char *a, const char *b, int l) {
57   if ((int)strlen (a) != l) { return 1; }
58   return memcmp (a, b, l);
59 }
60 
bl_do_dc_option(struct tgl_state * TLS,int flags,int id,const char * name,int l1,const char * ip,int l2,int port)61 void bl_do_dc_option (struct tgl_state *TLS, int flags, int id, const char *name, int l1, const char *ip, int l2, int port) /* {{{ */ {
62   struct tgl_dc *DC = TLS->DC_list[id];
63 
64   if (DC) {
65     struct tgl_dc_option *O = DC->options[flags & 3];
66     while (O) {
67       if (!strncmp (O->ip, ip, l2)) {
68         return;
69       }
70       O = O->next;
71     }
72   }
73 
74   vlogprintf (E_NOTICE, "DC%d '%.*s' update: %.*s:%d\n",
75     id,
76     l1, name,
77     l2, ip,
78     port
79   );
80 
81   tglmp_alloc_dc (TLS,
82     flags,
83     id,
84     tstrndup (ip, l2),
85     port
86   );
87 }
88 /* }}} */
89 
bl_do_set_working_dc(struct tgl_state * TLS,int num)90 void bl_do_set_working_dc (struct tgl_state *TLS, int num) /* {{{ */ {
91   assert (num > 0 && num <= MAX_DC_ID);
92   TLS->DC_working = TLS->DC_list[num];
93   TLS->dc_working_num = num;
94 }
95 /* }}} */
96 
bl_do_dc_signed(struct tgl_state * TLS,int num)97 void bl_do_dc_signed (struct tgl_state *TLS, int num) /* {{{ */ {
98   assert (num > 0 && num <= MAX_DC_ID);
99   assert (TLS->DC_list[num]);
100   TLS->DC_list[num]->flags |= TGLDCF_LOGGED_IN;
101 }
102 /* }}} */
103 
bl_do_set_auth_key(struct tgl_state * TLS,int num,unsigned char * buf)104 void bl_do_set_auth_key (struct tgl_state *TLS, int num, unsigned char *buf) /* {{{ */ {
105   assert (num > 0 && num <= MAX_DC_ID);
106   assert (TLS->DC_list[num]);
107 
108   if (TLS->DC_list[num]->auth_key != (char *)buf)
109     memcpy (TLS->DC_list[num]->auth_key, buf, 256);
110 
111   static unsigned char sha1_buffer[20];
112   TGLC_sha1 ((void *)TLS->DC_list[num]->auth_key, 256, sha1_buffer);
113   TLS->DC_list[num]->auth_key_id = *(long long *)(sha1_buffer + 12);
114 
115   TLS->DC_list[num]->flags |= TGLDCF_AUTHORIZED;
116 }
117 /* }}} */
118 
bl_do_set_our_id(struct tgl_state * TLS,tgl_peer_id_t id)119 void bl_do_set_our_id (struct tgl_state *TLS, tgl_peer_id_t id) /* {{{ */ {
120   /*if (TLS->our_id.peer_type) {
121     assert (!tgl_cmp_peer_id (TLS->our_id, id));
122     return;
123   }*/
124 
125   TLS->our_id = id;
126 
127   if (TLS->callback.our_id) {
128     TLS->callback.our_id (TLS, TLS->our_id);
129   }
130 }
131 /* }}} */
132 
bl_do_set_dh_params(struct tgl_state * TLS,int root,unsigned char prime[],int version)133 void bl_do_set_dh_params (struct tgl_state *TLS, int root, unsigned char prime[], int version) /* {{{ */ {
134   if (TLS->encr_prime) { tfree (TLS->encr_prime, 256); TGLC_bn_free (TLS->encr_prime_bn); }
135 
136   TLS->encr_root = root;
137 
138   TLS->encr_prime = talloc (256);
139   memcpy (TLS->encr_prime, prime, 256);
140   TLS->encr_prime_bn = TGLC_bn_new ();
141   TGLC_bn_bin2bn ((void *)TLS->encr_prime, 256, TLS->encr_prime_bn);
142 
143   TLS->encr_param_version = version;
144 
145   assert (tglmp_check_DH_params (TLS, TLS->encr_prime_bn, TLS->encr_root) >= 0);
146 }
147 /* }}} */
148 
bl_do_set_pts(struct tgl_state * TLS,int pts)149 void bl_do_set_pts (struct tgl_state *TLS, int pts) /* {{{ */ {
150   if (TLS->locks & TGL_LOCK_DIFF) { return; }
151   if (pts <= TLS->pts) { return; }
152 
153   TLS->pts = pts;
154 }
155 /* }}} */
156 
bl_do_set_channel_pts(struct tgl_state * TLS,int id,int pts)157 void bl_do_set_channel_pts (struct tgl_state *TLS, int id, int pts) /* {{{ */ {
158   tgl_peer_t *E = tgl_peer_get (TLS, TGL_MK_CHANNEL (id));
159   if (!E || !(E->flags & TGLPF_CREATED)) { return; }
160   if (E->flags & TGLCHF_DIFF) { return ; }
161   if (E->channel.pts <= pts) { return; }
162   E->channel.pts = pts;
163 }
164 /* }}} */
165 
bl_do_set_qts(struct tgl_state * TLS,int qts)166 void bl_do_set_qts (struct tgl_state *TLS, int qts) /* {{{ */ {
167   if (TLS->locks & TGL_LOCK_DIFF) { return; }
168   if (qts <= TLS->qts) { return; }
169 
170   TLS->qts = qts;
171 }
172 /* }}} */
173 
bl_do_set_date(struct tgl_state * TLS,int date)174 void bl_do_set_date (struct tgl_state *TLS, int date) /* {{{ */ {
175   if (TLS->locks & TGL_LOCK_DIFF) { return; }
176   if (date <= TLS->date) { return; }
177 
178   TLS->date = date;
179 }
180 /* }}} */
181 
bl_do_set_seq(struct tgl_state * TLS,int seq)182 void bl_do_set_seq (struct tgl_state *TLS, int seq) /* {{{ */ {
183   if (TLS->locks & TGL_LOCK_DIFF) { return; }
184   if (seq <= TLS->seq) { return; }
185 
186   TLS->seq = seq;
187 }
188 /* }}} */
189 
bl_do_set_msg_id(struct tgl_state * TLS,tgl_message_id_t * old_id,tgl_message_id_t * new_id)190 void bl_do_set_msg_id (struct tgl_state *TLS, tgl_message_id_t *old_id, tgl_message_id_t *new_id) /* {{{ */ {
191   if (!memcmp (old_id, new_id, sizeof (tgl_message_id_t))) {
192     return;
193   }
194 
195   struct tgl_message *M = tgl_message_get (TLS, old_id);
196   assert (M);
197 
198 
199   if (M->flags & TGLMF_PENDING) {
200     tglm_message_remove_unsent (TLS, M);
201     M->flags &= ~TGLMF_PENDING;
202   }
203 
204   tglm_message_remove_tree (TLS, M);
205   tglm_message_del_peer (TLS, M);
206 
207   M->permanent_id = *new_id;
208   if (tgl_message_get (TLS, new_id)) {
209     tglm_message_del_use (TLS, M);
210     tglm_message_del_temp_id (TLS, M);
211     tglm_message_del_random_id (TLS, M);
212     tgls_free_message (TLS, M);
213   } else {
214     tglm_message_insert_tree (TLS, M);
215     tglm_message_add_peer (TLS, M);
216   }
217 
218   M->server_id = new_id->id;
219 }
220 /* }}} */
221 
bl_do_chat_add_user(struct tgl_state * TLS,tgl_peer_id_t id,int version,int user,int inviter,int date)222 void bl_do_chat_add_user (struct tgl_state *TLS, tgl_peer_id_t id, int version, int user, int inviter, int date) /* {{{ */ {
223   tgl_peer_t *P = tgl_peer_get (TLS, id);
224   if (!P || !(P->flags & TGLPF_CREATED)) { return; }
225 
226   struct tgl_chat *C = &P->chat;
227   if (C->user_list_version >= version || !C->user_list_version) { return; }
228 
229   int i;
230   for (i = 0; i < C->user_list_size; i++) {
231     if (C->user_list[i].user_id == user) {
232       return;
233     }
234   }
235 
236   C->user_list_size ++;
237   C->user_list = trealloc (C->user_list, 12 * C->user_list_size - 12, 12 * C->user_list_size);
238   C->user_list[C->user_list_size - 1].user_id = user;
239   C->user_list[C->user_list_size - 1].inviter_id = inviter;
240   C->user_list[C->user_list_size - 1].date = date;
241   C->user_list_version = version;
242 
243   if (TLS->callback.chat_update) {
244     TLS->callback.chat_update (TLS, C, TGL_UPDATE_MEMBERS);
245   }
246 }
247 /* }}} */
248 
bl_do_chat_del_user(struct tgl_state * TLS,tgl_peer_id_t id,int version,int user)249 void bl_do_chat_del_user (struct tgl_state *TLS, tgl_peer_id_t id, int version, int user) /* {{{ */ {
250   tgl_peer_t *P = tgl_peer_get (TLS, id);
251   if (!P || !(P->flags & TGLPF_CREATED)) { return; }
252 
253   struct tgl_chat *C = &P->chat;
254   if (C->user_list_version >= version || !C->user_list_version) { return; }
255 
256   int i;
257   for (i = 0; i < C->user_list_size; i++) {
258     if (C->user_list[i].user_id == user) {
259       struct tgl_chat_user t;
260       t = C->user_list[i];
261       C->user_list[i] = C->user_list[C->user_list_size - 1];
262       C->user_list[C->user_list_size - 1] = t;
263     }
264   }
265   if (C->user_list[C->user_list_size - 1].user_id != user) { return; }
266 
267   assert (C->user_list[C->user_list_size - 1].user_id == user);
268   C->user_list_size --;
269   C->user_list = trealloc (C->user_list, 12 * C->user_list_size + 12, 12 * C->user_list_size);
270   C->user_list_version = version;
271 
272   if (TLS->callback.chat_update) {
273     TLS->callback.chat_update (TLS, C, TGL_UPDATE_MEMBERS);
274   }
275 }
276 /* }}} */
277 
bl_do_edit_message(struct tgl_state * TLS,tgl_message_id_t * id,tgl_peer_id_t * from_id,tgl_peer_id_t * to_id,tgl_peer_id_t * fwd_from_id,int * fwd_date,int * date,const char * message,int message_len,struct tl_ds_message_media * media,struct tl_ds_message_action * action,int * reply_id,struct tl_ds_reply_markup * reply_markup,struct tl_ds_vector * entities,int flags)278 void bl_do_edit_message (struct tgl_state *TLS, tgl_message_id_t *id, tgl_peer_id_t *from_id, tgl_peer_id_t *to_id, tgl_peer_id_t *fwd_from_id, int *fwd_date, int *date, const char *message, int message_len, struct tl_ds_message_media *media, struct tl_ds_message_action *action, int *reply_id, struct tl_ds_reply_markup *reply_markup, struct tl_ds_vector *entities, int flags) /* {{{ */ {
279   assert (!(flags & 0xfffe0000));
280 
281   struct tgl_message *M = tgl_message_get (TLS, id);
282 
283   assert (flags & TGLMF_CREATED);
284   assert (!(flags & TGLMF_ENCRYPTED));
285 
286   if (flags & (1 << 16)) {
287     if (!M) {
288       M = tglm_message_alloc (TLS, id);
289     }
290     M->server_id = id->id;
291     assert (!(M->flags & TGLMF_CREATED));
292   } else {
293     assert (M->flags & TGLMF_CREATED);
294   }
295 
296   assert (M);
297   assert (!(M->flags & TGLMF_ENCRYPTED));
298 
299   if ((M->flags & TGLMF_PENDING) && !(flags & TGLMF_PENDING)){
300     tglm_message_remove_unsent (TLS, M);
301   }
302   if (!(M->flags & TGLMF_PENDING) && (flags & TGLMF_PENDING)){
303     tglm_message_insert_unsent (TLS, M);
304   }
305 
306   if ((M->flags & TGLMF_UNREAD) && !(flags & TGLMF_UNREAD)) {
307     M->flags = (flags & 0xffff) | TGLMF_UNREAD;
308   } else {
309     M->flags = (flags & 0xffff);
310   }
311 
312   if (from_id) {
313     M->from_id = *from_id;
314   } else {
315     if (!M->from_id.peer_type) {
316       assert (to_id);
317       M->from_id = *to_id;
318     }
319   }
320 
321   if (to_id) {
322     assert (flags & 0x10000);
323     M->to_id = *to_id;
324   }
325 
326   if (date) {
327     M->date = *date;
328   }
329 
330   if (fwd_from_id) {
331     assert (fwd_date);
332     M->fwd_from_id = *fwd_from_id;
333     M->fwd_date = *fwd_date;;
334   }
335 
336   if (action) {
337     tglf_fetch_message_action (TLS, &M->action, action);
338     M->flags |= TGLMF_SERVICE;
339   }
340 
341   if (message) {
342     M->message_len = message_len;
343     M->message = tstrndup (message, message_len);
344     assert (!(M->flags & TGLMF_SERVICE));
345   }
346 
347   if (media) {
348     tglf_fetch_message_media (TLS, &M->media, media);
349     assert (!(M->flags & TGLMF_SERVICE));
350   }
351 
352   if (entities) {
353     tglf_fetch_message_entities (TLS, M, entities);
354   }
355 
356   if (reply_id) {
357     M->reply_id = *reply_id;
358   }
359 
360   if (flags & 0x10000) {
361     tglm_message_insert (TLS, M);
362   }
363 
364   if (!(flags & TGLMF_UNREAD) && (M->flags & TGLMF_UNREAD)) {
365     tgls_messages_mark_read (TLS, M, M->flags & TGLMF_OUT, M->permanent_id.id);
366   }
367 
368   if (reply_markup) {
369     M->reply_markup = tglf_fetch_alloc_reply_markup (TLS, M->next, reply_markup);
370   }
371 
372   if (M->flags & TGLMF_PENDING) {
373     tgls_message_change_random_id (TLS, M, M->permanent_id.id);
374   }
375 
376   if (!M->temp_id) {
377     tgls_message_change_temp_id (TLS, M, ++TLS->last_temp_id);
378   }
379 }
380 /* }}} */
381 
bl_do_edit_message_encr(struct tgl_state * TLS,tgl_message_id_t * id,tgl_peer_id_t * from_id,tgl_peer_id_t * to_id,int * date,const char * message,int message_len,struct tl_ds_decrypted_message_media * media,struct tl_ds_decrypted_message_action * action,struct tl_ds_encrypted_file * file,int flags)382 void bl_do_edit_message_encr (struct tgl_state *TLS, tgl_message_id_t *id, tgl_peer_id_t *from_id, tgl_peer_id_t *to_id, int *date, const char *message, int message_len, struct tl_ds_decrypted_message_media *media, struct tl_ds_decrypted_message_action *action, struct tl_ds_encrypted_file *file, int flags) /* {{{ */ {
383   clear_packet ();
384   assert (!(flags & 0xfffe0000));
385 
386   struct tgl_message *M = tgl_message_get (TLS, id);
387 
388   if (flags & (1 << 16)) {
389     if (!M) {
390       M = tglm_message_alloc (TLS, id);
391     } else {
392       assert (!(M->flags & TGLMF_CREATED));
393     }
394     assert (!(M->flags & TGLMF_CREATED));
395   } else {
396     assert (M->flags & TGLMF_CREATED);
397   }
398 
399   assert (flags & TGLMF_CREATED);
400   assert (flags & TGLMF_ENCRYPTED);
401 
402   if ((M->flags & TGLMF_PENDING) && !(flags & TGLMF_PENDING)){
403     tglm_message_remove_unsent (TLS, M);
404   }
405   if (!(M->flags & TGLMF_PENDING) && (flags & TGLMF_PENDING)){
406     tglm_message_insert_unsent (TLS, M);
407   }
408 
409   M->flags = flags & 0xffff;
410 
411   if (from_id) {
412     M->from_id = *from_id;
413   }
414   if (to_id) {
415     assert (flags & 0x10000);
416     M->to_id = *to_id;
417   }
418 
419   if (date) {
420     M->date = *date;
421   }
422 
423   struct tgl_secret_chat *E = (void *)tgl_peer_get (TLS, M->to_id);
424   assert (E);
425 
426   if (action) {
427     tglf_fetch_message_action_encrypted (TLS, &M->action, action);
428     M->flags |= TGLMF_SERVICE;
429   }
430 
431   if (message) {
432     M->message_len = message_len;
433     M->message = tstrndup (message, message_len);
434     assert (!(M->flags & TGLMF_SERVICE));
435   }
436 
437   if (media) {
438     tglf_fetch_message_media_encrypted (TLS, &M->media, media);
439     assert (!(M->flags & TGLMF_SERVICE));
440   }
441 
442   if (file) {
443     tglf_fetch_encrypted_message_file (TLS, &M->media, file);
444     assert (!(M->flags & TGLMF_SERVICE));
445   }
446 
447   if (action && !(M->flags & TGLMF_OUT) && M->action.type == tgl_message_action_notify_layer) {
448     E->layer = M->action.layer;
449   }
450 
451   if ((flags & TGLMF_CREATE) && (flags & TGLMF_OUT)) {
452     E->out_seq_no ++;
453   }
454 
455   if (flags & 0x10000) {
456     tglm_message_insert (TLS, M);
457   }
458 }
459 /* }}} */
460 
bl_do_message_delete(struct tgl_state * TLS,tgl_message_id_t * id)461 void bl_do_message_delete (struct tgl_state *TLS, tgl_message_id_t *id) /* {{{ */ {
462   struct tgl_message *M = tgl_message_get (TLS, id);
463   if (!M) { return; }
464   assert (M);
465   if (M->flags & TGLMF_PENDING) {
466     tglm_message_remove_unsent (TLS, M);
467     M->flags &= ~TGLMF_PENDING;
468   }
469 
470   tglm_message_remove_tree (TLS, M);
471   tglm_message_del_peer (TLS, M);
472   tglm_message_del_use (TLS, M);
473   tglm_message_del_temp_id (TLS, M);
474   tglm_message_del_random_id (TLS, M);
475   tgls_free_message (TLS, M);
476 }
477 /* }}} */
478 
bl_do_msg_update(struct tgl_state * TLS,tgl_message_id_t * id)479 void bl_do_msg_update (struct tgl_state *TLS, tgl_message_id_t *id) /* {{{ */ {
480   struct tgl_message *M = tgl_message_get (TLS, id);
481   if (!M) { return; }
482   assert (M);
483 
484   if (!(M->flags & TGLMF_ENCRYPTED)) {
485     if (TLS->max_msg_id < M->server_id) {
486       TLS->max_msg_id = M->server_id;
487     }
488   }
489 
490   if (TLS->callback.msg_receive) {
491     TLS->callback.msg_receive (TLS, M);
492   }
493 }
494 /* }}} */
495 
bl_do_reset_authorization(struct tgl_state * TLS)496 void bl_do_reset_authorization (struct tgl_state *TLS) /* {{{ */ {
497   int i;
498   for (i = 0; i <= TLS->max_dc_num; i++) if (TLS->DC_list[i]) {
499     struct tgl_dc *D = TLS->DC_list[i];
500     D->flags = 0;
501     D->state = st_init;
502     D->auth_key_id = D->temp_auth_key_id = 0;
503   }
504   TLS->seq = 0;
505   TLS->qts = 0;
506 }
507 /* }}} */
508 
bl_do_encr_chat_exchange(struct tgl_state * TLS,tgl_peer_id_t id,long long * exchange_id,const void * key,int * state)509 void bl_do_encr_chat_exchange (struct tgl_state *TLS, tgl_peer_id_t id, long long *exchange_id, const void *key, int *state) /* {{{ */ {
510   tgl_peer_t *P = tgl_peer_get (TLS, id);
511   if (!P) { return; }
512 
513   if (state) {
514     P->encr_chat.exchange_state = *state;
515   }
516   if (exchange_id) {
517     P->encr_chat.exchange_id = *exchange_id;
518   }
519 
520   static unsigned char sha_buffer[20];
521   switch (P->encr_chat.exchange_state) {
522   case tgl_sce_requested:
523     memcpy (P->encr_chat.exchange_key, key, 256);
524     break;
525   case tgl_sce_accepted:
526     memcpy (P->encr_chat.exchange_key, key, 256);
527 
528     TGLC_sha1 ((unsigned char *)P->encr_chat.exchange_key, 256, sha_buffer);
529     P->encr_chat.exchange_key_fingerprint = *(long long *)(sha_buffer + 12);
530     break;
531   case tgl_sce_committed:
532     memcpy (P->encr_chat.exchange_key, P->encr_chat.key, 256);
533     P->encr_chat.exchange_key_fingerprint = P->encr_chat.key_fingerprint;
534 
535     memcpy (P->encr_chat.key, key, 256);
536 
537     TGLC_sha1 ((unsigned char *)P->encr_chat.key, 256, sha_buffer);
538     P->encr_chat.key_fingerprint = *(long long *)(sha_buffer + 12);
539     break;
540   case tgl_sce_confirmed:
541     P->encr_chat.exchange_state = tgl_sce_none;
542     if (P->encr_chat.exchange_state != tgl_sce_committed) {
543       memcpy (P->encr_chat.key, P->encr_chat.exchange_key, 256);
544       P->encr_chat.key_fingerprint = P->encr_chat.exchange_key_fingerprint;
545     }
546     break;
547   case tgl_sce_aborted:
548     P->encr_chat.exchange_state = tgl_sce_none;
549     if (P->encr_chat.exchange_state == tgl_sce_committed) {
550       memcpy (P->encr_chat.key, P->encr_chat.exchange_key, 256);
551       P->encr_chat.key_fingerprint = P->encr_chat.exchange_key_fingerprint;
552     }
553     break;
554   default:
555     assert (0);
556   }
557 }
558 /* }}} */
559 
bl_do_user(struct tgl_state * TLS,int id,long long * access_hash,const char * first_name,int first_name_len,const char * last_name,int last_name_len,const char * phone,int phone_len,const char * username,int username_len,struct tl_ds_photo * photo,struct tl_ds_user_profile_photo * profile_photo,int * last_read_in,int * last_read_out,struct tl_ds_bot_info * bot_info,int flags)560 void bl_do_user (struct tgl_state *TLS, int id, long long *access_hash, const char *first_name, int first_name_len, const char *last_name, int last_name_len, const char *phone, int phone_len, const char *username, int username_len, struct tl_ds_photo *photo, struct tl_ds_user_profile_photo *profile_photo, int *last_read_in, int *last_read_out, struct tl_ds_bot_info *bot_info, int flags) /* {{{ */ {
561   tgl_peer_t *_U = tgl_peer_get (TLS, TGL_MK_USER (id));
562 
563   unsigned updates = 0;
564 
565   if ((flags & TGLPF_CREATE) && (flags != TGL_FLAGS_UNCHANGED)) {
566     if (!_U) {
567       _U = talloc0 (sizeof (*_U));
568       _U->id = TGL_MK_USER (id);
569       tglp_insert_user (TLS, _U);
570     } else {
571       assert (!(_U->flags & TGLPF_CREATED));
572     }
573     updates |= TGL_UPDATE_CREATED;
574   } else {
575     assert (_U->flags & TGLPF_CREATED);
576   }
577 
578   struct tgl_user *U = (void *)_U;
579   if (flags == TGL_FLAGS_UNCHANGED) { flags = U->flags; }
580   flags &= TGLUF_TYPE_MASK;
581 
582   if ((flags & TGLUF_TYPE_MASK) != (U->flags & TGLUF_TYPE_MASK)) {
583     updates |= TGL_UPDATE_FLAGS;
584   }
585   U->flags = (U->flags & ~TGLUF_TYPE_MASK) | flags;
586 
587   if (access_hash && *access_hash != U->access_hash) {
588     U->access_hash = *access_hash;
589     U->id.access_hash = *access_hash;
590     updates |= TGL_UPDATE_ACCESS_HASH;
591   }
592 
593   if (first_name || last_name) {
594     if (!U->first_name || !U->last_name || mystreq1 (U->first_name, first_name, first_name_len) || mystreq1 (U->last_name, last_name, last_name_len)) {
595       if (U->first_name) {
596         tfree_str (U->first_name);
597       }
598       U->first_name = tstrndup (first_name, first_name_len);
599       if (U->last_name) {
600         tfree_str (U->last_name);
601       }
602       U->last_name = tstrndup (last_name, last_name_len);
603 
604       updates |= TGL_UPDATE_NAME;
605 
606       if (U->print_name) {
607         tglp_peer_delete_name (TLS, (void *)U);
608         tfree_str (U->print_name);
609       }
610       U->print_name = TLS->callback.create_print_name (TLS, U->id, U->first_name, U->last_name, 0, 0);
611       tglp_peer_insert_name (TLS, (void *)U);
612     }
613   }
614 
615   if (phone && (!U->phone || mystreq1 (U->phone, phone, phone_len))) {
616     if (U->phone) {
617       tfree_str (U->phone);
618     }
619     U->phone = tstrndup (phone, phone_len);
620     updates |= TGL_UPDATE_PHONE;
621   }
622 
623   if (username && (!U->username || mystreq1 (U->username, username, username_len))) {
624     if (U->username) {
625       tfree_str (U->username);
626     }
627     U->username = tstrndup (username, username_len);
628     updates |= TGL_UPDATE_USERNAME;
629   }
630 
631   if (photo) {
632     if (!U->photo || U->photo->id != DS_LVAL (photo->id)) {
633       if (U->photo) {
634         tgls_free_photo (TLS, U->photo);
635       }
636       U->photo = tglf_fetch_alloc_photo (TLS, photo);
637       U->flags |= TGLUF_HAS_PHOTO;
638     }
639   }
640 
641   if (profile_photo) {
642     if (U->photo_id != DS_LVAL (profile_photo->photo_id)) {
643       U->photo_id = DS_LVAL (profile_photo->photo_id);
644       tglf_fetch_file_location (TLS, &U->photo_big, profile_photo->photo_big);
645       tglf_fetch_file_location (TLS, &U->photo_small, profile_photo->photo_small);
646       updates |= TGL_UPDATE_PHOTO;
647     }
648   }
649 
650   if (last_read_in) {
651     U->last_read_in = *last_read_in;
652     tgls_messages_mark_read (TLS, U->last, 0, U->last_read_in);
653   }
654   if (last_read_out) {
655     U->last_read_out = *last_read_out;
656     tgls_messages_mark_read (TLS, U->last, TGLMF_OUT, U->last_read_out);
657   }
658 
659   if (bot_info) {
660     if (!U->bot_info || U->bot_info->version != DS_LVAL (bot_info->version)) {
661       if (U->bot_info) {
662         tgls_free_bot_info (TLS, U->bot_info);
663       }
664       U->bot_info = tglf_fetch_alloc_bot_info (TLS, bot_info);
665     }
666   }
667 
668   if (TLS->callback.user_update && updates) {
669     TLS->callback.user_update (TLS, U, updates);
670   }
671 }
672 /* }}} */
673 
bl_do_chat(struct tgl_state * TLS,int id,const char * title,int title_len,int * user_num,int * date,int * version,struct tl_ds_vector * participants,struct tl_ds_chat_photo * chat_photo,struct tl_ds_photo * photo,int * admin,int * last_read_in,int * last_read_out,int flags)674 void bl_do_chat (struct tgl_state *TLS, int id, const char *title, int title_len, int *user_num, int *date, int *version, struct tl_ds_vector *participants, struct tl_ds_chat_photo *chat_photo, struct tl_ds_photo *photo, int *admin, int *last_read_in, int *last_read_out, int flags) /* {{{ */ {
675   tgl_peer_t *_U = tgl_peer_get (TLS, TGL_MK_CHAT (id));
676 
677   unsigned updates = 0;
678 
679   if ((flags & TGLPF_CREATE) && (flags != TGL_FLAGS_UNCHANGED)) {
680     if (!_U) {
681       _U = talloc0 (sizeof (*_U));
682       _U->id = TGL_MK_CHAT (id);
683       tglp_insert_chat (TLS, _U);
684     } else {
685       assert (!(_U->flags & TGLPF_CREATED));
686     }
687     updates |= TGL_UPDATE_CREATED;
688   } else {
689     assert (_U->flags & TGLPF_CREATED);
690   }
691 
692   struct tgl_chat *C = &_U->chat;
693   if (flags == TGL_FLAGS_UNCHANGED) { flags = C->flags; }
694   flags &= TGLCF_TYPE_MASK;
695 
696   if ((flags & TGLCF_TYPE_MASK) != (C->flags & TGLCF_TYPE_MASK)) {
697     updates |= TGL_UPDATE_FLAGS;
698   }
699   C->flags = (C->flags & ~TGLCF_TYPE_MASK) | flags;
700 
701   if (title && (!C->title || mystreq1 (C->title, title, title_len))) {
702     if (C->title) {
703       tfree_str (C->title);
704     }
705     C->title = tstrndup (title, title_len);
706 
707     if (C->print_title) {
708       tglp_peer_delete_name (TLS, (void *)C);
709       tfree_str (C->print_title);
710     }
711     C->print_title = TLS->callback.create_print_name (TLS, C->id, C->title, 0, 0, 0);
712     tglp_peer_insert_name (TLS, (void *)C);
713 
714     updates |= TGL_UPDATE_TITLE;
715   }
716 
717   if (user_num) {
718     C->users_num = *user_num;
719   }
720 
721   if (date) {
722     C->date = *date;
723   }
724 
725   if (chat_photo && chat_photo->photo_big) {
726     if (DS_LVAL (chat_photo->photo_big->secret) != C->photo_big.secret) {
727       tglf_fetch_file_location (TLS, &C->photo_big, chat_photo->photo_big);
728       tglf_fetch_file_location (TLS, &C->photo_small, chat_photo->photo_small);
729       updates |= TGL_UPDATE_PHOTO;
730     }
731   }
732 
733   if (photo) {
734     if (!C->photo || C->photo->id != DS_LVAL (photo->id)) {
735       if (C->photo) {
736         tgls_free_photo (TLS, C->photo);
737       }
738       C->photo = tglf_fetch_alloc_photo (TLS, photo);
739       C->flags |= TGLPF_HAS_PHOTO;
740       //updates |= TGL_UPDATE_PHOTO;
741     }
742   }
743 
744   if (admin && *admin != C->admin_id) {
745     C->admin_id = *admin;
746     updates |= TGL_UPDATE_ADMIN;
747   }
748 
749   if (version) {
750     assert (participants);
751     if (*version > C->version) {
752       C->version = *version;
753 
754       if (C->user_list) { tfree (C->user_list, 12 * C->user_list_size); }
755 
756       C->user_list_size = DS_LVAL (participants->f1);
757       C->user_list = talloc (12 * C->user_list_size);
758 
759       int i;
760       for (i = 0; i < C->user_list_size; i++) {
761         struct tl_ds_chat_participant *DS_P = participants->f2[i];
762         C->user_list[i].user_id = DS_LVAL (DS_P->user_id);
763         C->user_list[i].inviter_id = DS_LVAL (DS_P->inviter_id);
764         C->user_list[i].date = DS_LVAL (DS_P->date);
765       }
766 
767       updates |= TGL_UPDATE_MEMBERS;
768     }
769   }
770 
771   if (last_read_in) {
772     C->last_read_in = *last_read_in;
773     tgls_messages_mark_read (TLS, C->last, 0, C->last_read_in);
774   }
775 
776   if (last_read_out) {
777     C->last_read_out = *last_read_out;
778     tgls_messages_mark_read (TLS, C->last, TGLMF_OUT, C->last_read_out);
779   }
780 
781 
782   if (TLS->callback.chat_update && updates) {
783     TLS->callback.chat_update (TLS, C, updates);
784   }
785 }
786 /* }}} */
787 
bl_do_encr_chat(struct tgl_state * TLS,int id,long long * access_hash,int * date,int * admin,int * user_id,void * key,void * g_key,void * first_key_id,int * state,int * ttl,int * layer,int * in_seq_no,int * last_in_seq_no,int * out_seq_no,long long * key_fingerprint,int flags,const char * print_name,int print_name_len)788 void bl_do_encr_chat (struct tgl_state *TLS, int id, long long *access_hash, int *date, int *admin, int *user_id, void *key, void *g_key, void *first_key_id, int *state, int *ttl, int *layer, int *in_seq_no, int *last_in_seq_no, int *out_seq_no, long long *key_fingerprint, int flags, const char *print_name, int print_name_len) /* {{{ */ {
789   tgl_peer_t *_U = tgl_peer_get (TLS, TGL_MK_ENCR_CHAT (id));
790 
791   unsigned updates = 0;
792 
793   if ((flags & TGLPF_CREATE) && (flags != TGL_FLAGS_UNCHANGED)) {
794     if (!_U) {
795       _U = talloc0 (sizeof (*_U));
796       _U->id = TGL_MK_ENCR_CHAT (id);
797       tglp_insert_encrypted_chat (TLS, _U);
798     } else {
799       assert (!(_U->flags & TGLPF_CREATED));
800     }
801     updates |= TGL_UPDATE_CREATED;
802   } else {
803     assert (_U->flags & TGLPF_CREATED);
804   }
805 
806   struct tgl_secret_chat *U = (void *)_U;
807   if (flags == TGL_FLAGS_UNCHANGED) { flags = U->flags; }
808   flags &= TGLECF_TYPE_MASK;
809 
810   if ((flags & TGLECF_TYPE_MASK) != (U->flags & TGLECF_TYPE_MASK)) {
811     updates |= TGL_UPDATE_FLAGS;
812   }
813   U->flags = (U->flags & ~TGLECF_TYPE_MASK) | flags;
814 
815   if (access_hash && *access_hash != U->access_hash) {
816     U->access_hash = *access_hash;
817     U->id.access_hash = *access_hash;
818     updates |= TGL_UPDATE_ACCESS_HASH;
819   }
820 
821   if (date) {
822     U->date = *date;
823   }
824 
825   if (admin) {
826     U->admin_id = *admin;
827   }
828 
829   if (user_id) {
830     U->user_id = *user_id;
831   }
832 
833   if (key_fingerprint) {
834     U->key_fingerprint = *key_fingerprint;
835   }
836 
837   if (in_seq_no) {
838     U->in_seq_no = *in_seq_no;
839   }
840   if (out_seq_no) {
841     U->out_seq_no = *out_seq_no;
842   }
843   if (last_in_seq_no) {
844     U->last_in_seq_no = *last_in_seq_no;
845   }
846 
847   tgl_peer_t *Us = tgl_peer_get (TLS, TGL_MK_USER (U->user_id));
848 
849   if (!U->print_name) {
850     if (print_name) {
851       U->print_name = tstrndup (print_name, print_name_len);
852     } else {
853       if (Us) {
854         U->print_name = TLS->callback.create_print_name (TLS, TGL_MK_ENCR_CHAT (id), "!", Us->user.first_name, Us->user.last_name, 0);
855       } else {
856         static char buf[100];
857         tsnprintf (buf, 99, "user#%d", U->user_id);
858         U->print_name = TLS->callback.create_print_name (TLS, TGL_MK_ENCR_CHAT (id), "!", buf, 0, 0);
859       }
860       tglp_peer_insert_name (TLS, (void *)U);
861     }
862   }
863 
864   if (g_key) {
865     if (!U->g_key)  {
866       U->g_key = talloc (256);
867     }
868     memcpy (U->g_key, g_key, 256);
869   }
870 
871   if (key) {
872     memcpy (U->key, key, 256);
873   }
874 
875   if (first_key_id) {
876     memcpy (U->first_key_sha, first_key_id, 20);
877   }
878 
879   if (state) {
880     if (U->state == sc_waiting && *state == sc_ok) {
881       tgl_do_create_keys_end (TLS, U);
882     }
883     if ((int)U->state != *state) {
884       switch (*state) {
885       case sc_request:
886         updates |= TGL_UPDATE_REQUESTED;
887         break;
888       case sc_ok:
889         updates |= TGL_UPDATE_WORKING;
890         vlogprintf (E_WARNING, "Secret chat in ok state\n");
891         break;
892       default:
893         break;
894       }
895     }
896     U->state = *state;
897   }
898 
899   if (TLS->callback.secret_chat_update && updates) {
900     TLS->callback.secret_chat_update (TLS, U, updates);
901   }
902 }
903 /* }}} */
904 
bl_do_channel(struct tgl_state * TLS,int id,long long * access_hash,int * date,const char * title,int title_len,const char * username,int username_len,struct tl_ds_chat_photo * chat_photo,struct tl_ds_photo * photo,int * version,char * about,int about_len,int * participants_count,int * admins_count,int * kicked_count,int * last_read_in,int flags)905 void bl_do_channel (struct tgl_state *TLS, int id, long long *access_hash, int *date, const char *title, int title_len, const char *username, int username_len, struct tl_ds_chat_photo *chat_photo, struct tl_ds_photo *photo, int *version, char *about, int about_len, int *participants_count, int *admins_count, int *kicked_count, int *last_read_in, int flags) /* {{{ */ {
906   tgl_peer_t *_U = tgl_peer_get (TLS, TGL_MK_CHANNEL (id));
907 
908   unsigned updates = 0;
909 
910   if ((flags & TGLPF_CREATE) && (flags != TGL_FLAGS_UNCHANGED)) {
911     if (!_U) {
912       _U = talloc0 (sizeof (*_U));
913       _U->id = TGL_MK_CHANNEL (id);
914       tglp_insert_channel (TLS, _U);
915     } else {
916       assert (!(_U->flags & TGLPF_CREATED));
917     }
918     updates |= TGL_UPDATE_CREATED;
919   } else {
920     assert (_U->flags & TGLPF_CREATED);
921   }
922 
923   struct tgl_channel *C = &_U->channel;
924   if (flags == TGL_FLAGS_UNCHANGED) { flags = C->flags; }
925   flags &= TGLCHF_TYPE_MASK;
926 
927   if ((flags & TGLCHF_TYPE_MASK) != (C->flags & TGLCHF_TYPE_MASK)) {
928     updates |= TGL_UPDATE_FLAGS;
929   }
930   C->flags = (C->flags & ~TGLCHF_TYPE_MASK) | flags;
931 
932   if (access_hash && *access_hash != C->access_hash) {
933     C->access_hash = *access_hash;
934     C->id.access_hash = *access_hash;
935     updates |= TGL_UPDATE_ACCESS_HASH;
936   }
937 
938   if (date) {
939     C->date = *date;
940   }
941 
942   if (title && (!C->title || mystreq1 (C->title, title, title_len))) {
943     if (C->title) {
944       tfree_str (C->title);
945     }
946     C->title = tstrndup (title, title_len);
947 
948     if (C->print_title) {
949       tglp_peer_delete_name (TLS, (void *)C);
950       tfree_str (C->print_title);
951     }
952     C->print_title = TLS->callback.create_print_name (TLS, C->id, C->title, 0, 0, 0);
953     tglp_peer_insert_name (TLS, (void *)C);
954 
955     updates |= TGL_UPDATE_TITLE;
956   }
957 
958   if (chat_photo) {
959     if (chat_photo->photo_big && DS_LVAL (chat_photo->photo_big->secret) != C->photo_big.secret) {
960       tglf_fetch_file_location (TLS, &C->photo_big, chat_photo->photo_big);
961       tglf_fetch_file_location (TLS, &C->photo_small, chat_photo->photo_small);
962       updates |= TGL_UPDATE_PHOTO;
963     }
964   }
965 
966   if (photo) {
967     if (!C->photo || C->photo->id != DS_LVAL (photo->id)) {
968       if (C->photo) {
969         tgls_free_photo (TLS, C->photo);
970       }
971       C->photo = tglf_fetch_alloc_photo (TLS, photo);
972       C->flags |= TGLPF_HAS_PHOTO;
973     }
974   }
975 
976   if (username) {
977     if (!C->username || mystreq1 (C->username, username, username_len)) {
978       if (C->username) {
979         tfree_str (C->username);
980       }
981       C->username = tstrndup (username, username_len);
982       updates |= TGL_UPDATE_USERNAME;
983     }
984   }
985 
986   if (about) {
987     if (!C->about || mystreq1 (C->about, about, about_len)) {
988       tfree_str (C->about);
989     }
990     C->about = tstrndup (about, about_len);
991   }
992 
993   if (admins_count) {
994     C->admins_count = *admins_count;
995   }
996 
997   if (participants_count) {
998     C->participants_count = *participants_count;
999   }
1000 
1001   if (kicked_count) {
1002     C->kicked_count = *kicked_count;
1003   }
1004 
1005   if (last_read_in) {
1006     C->last_read_in = *last_read_in;
1007     tgls_messages_mark_read (TLS, C->last, 0, C->last_read_in);
1008   }
1009 
1010   if (TLS->callback.channel_update && updates) {
1011     TLS->callback.channel_update (TLS, C, updates);
1012   }
1013 }
1014 /* }}} */
1015 
bl_do_peer_delete(struct tgl_state * TLS,tgl_peer_id_t id)1016 void bl_do_peer_delete (struct tgl_state *TLS, tgl_peer_id_t id) /* {{{ */ {
1017   tgl_peer_t *P = tgl_peer_get (TLS, id);
1018   if (!P || !(P->flags & TGLPF_CREATED)) { return; }
1019 
1020   if (P->flags & TGLPF_DELETED) { return; }
1021   P->flags |= TGLPF_DELETED;
1022 
1023   switch (id.peer_type) {
1024   case TGL_PEER_USER:
1025     if (TLS->callback.user_update) {
1026       TLS->callback.user_update (TLS, (void *)P, TGL_UPDATE_DELETED);
1027     }
1028     break;
1029   case TGL_PEER_CHAT:
1030     if (TLS->callback.chat_update) {
1031       TLS->callback.chat_update (TLS, (void *)P, TGL_UPDATE_DELETED);
1032     }
1033     break;
1034   case TGL_PEER_ENCR_CHAT:
1035     if (TLS->callback.secret_chat_update) {
1036       TLS->callback.secret_chat_update (TLS, (void *)P, TGL_UPDATE_DELETED);
1037     }
1038     break;
1039   case TGL_PEER_CHANNEL:
1040     if (TLS->callback.channel_update) {
1041       TLS->callback.channel_update (TLS, (void *)P, TGL_UPDATE_DELETED);
1042     }
1043     break;
1044   default:
1045     assert (0);
1046   }
1047 }
1048 /* }}} */
1049