summaryrefslogtreecommitdiff
path: root/protocols/Telegram/tgl/structures.c
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/Telegram/tgl/structures.c')
-rw-r--r--protocols/Telegram/tgl/structures.c2311
1 files changed, 0 insertions, 2311 deletions
diff --git a/protocols/Telegram/tgl/structures.c b/protocols/Telegram/tgl/structures.c
deleted file mode 100644
index a680e4c415..0000000000
--- a/protocols/Telegram/tgl/structures.c
+++ /dev/null
@@ -1,2311 +0,0 @@
-/*
- This file is part of tgl-library
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
- Copyright Vitaly Valtman 2013-2015
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <assert.h>
-#include <string.h>
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-#include "tgl-structures.h"
-#include "mtproto-common.h"
-//#include "telegram.h"
-#include "tree.h"
-#include <openssl/aes.h>
-#include <openssl/bn.h>
-#include <openssl/sha.h>
-#include "queries.h"
-#include "tgl-binlog.h"
-#include "tgl-methods-in.h"
-#include "updates.h"
-#include "mtproto-client.h"
-
-#include "tgl.h"
-#include "auto.h"
-#include "auto/auto-types.h"
-#include "auto/auto-skip.h"
-#include "auto/auto-fetch-ds.h"
-#include "auto/auto-free-ds.h"
-
-#define sha1 SHA1
-#if defined(WIN32) || defined(_WIN32)
-#define bzero(b,len) (memset((b), '\0', (len)) )
-#endif
-
-struct random2local {
- long long random_id;
- int local_id;
-};
-
-static int id_cmp (struct tgl_message *M1, struct tgl_message *M2);
-#define peer_cmp(a,b) (tgl_cmp_peer_id (a->id, b->id))
-#define peer_cmp_name(a,b) (strcmp (a->print_name, b->print_name))
-
-static int random_id_cmp (struct random2local *L, struct random2local *R) {
- if (L->random_id < R->random_id) { return -1; }
- if (L->random_id > R->random_id) { return 1; }
- return 0;
-}
-
-static int photo_id_cmp (struct tgl_photo *L, struct tgl_photo *R) {
- if (L->id < R->id) { return -1; }
- if (L->id > R->id) { return 1; }
- return 0;
-}
-
-static int document_id_cmp (struct tgl_document *L, struct tgl_document *R) {
- if (L->id < R->id) { return -1; }
- if (L->id > R->id) { return 1; }
- return 0;
-}
-
-static int webpage_id_cmp (struct tgl_webpage *L, struct tgl_webpage *R) {
- if (L->id < R->id) { return -1; }
- if (L->id > R->id) { return 1; }
- return 0;
-}
-
-DEFINE_TREE(peer,tgl_peer_t *,peer_cmp,0)
-DEFINE_TREE(peer_by_name,tgl_peer_t *,peer_cmp_name,0)
-DEFINE_TREE(message,struct tgl_message *,id_cmp,0)
-DEFINE_TREE(random_id,struct random2local *, random_id_cmp,0)
-DEFINE_TREE(photo,struct tgl_photo *,photo_id_cmp,0)
-DEFINE_TREE(document,struct tgl_document *,document_id_cmp,0)
-DEFINE_TREE(webpage,struct tgl_webpage *,webpage_id_cmp,0)
-
-
-char *tgls_default_create_print_name (struct tgl_state *TLS, tgl_peer_id_t id, const char *a1, const char *a2, const char *a3, const char *a4) {
- const char *d[4];
- d[0] = a1; d[1] = a2; d[2] = a3; d[3] = a4;
- static char buf[10000];
- buf[0] = 0;
- int i;
- int p = 0;
- for (i = 0; i < 4; i++) {
- if (d[i] && strlen (d[i])) {
- p += tsnprintf (buf + p, 9999 - p, "%s%s", p ? "_" : "", d[i]);
- assert (p < 9990);
- }
- }
- char *s = buf;
- while (*s) {
- if (((unsigned char)*s) <= ' ') { *s = '_'; }
- if (*s == '#') { *s = '@'; }
- s++;
- }
- s = buf;
- int fl = strlen (s);
- int cc = 0;
- while (1) {
- tgl_peer_t *P = tgl_peer_get_by_name (TLS, s);
- if (!P || !tgl_cmp_peer_id (P->id, id)) {
- break;
- }
- cc ++;
- assert (cc <= 9999);
- tsnprintf (s + fl, 9999 - fl, "#%d", cc);
- }
- return tstrdup (s);
-}
-
-enum tgl_typing_status tglf_fetch_typing_new (struct tl_ds_send_message_action *DS_SMA) {
- if (!DS_SMA) { return 0; }
- switch (DS_SMA->magic) {
- case CODE_send_message_typing_action:
- return tgl_typing_typing;
- case CODE_send_message_cancel_action:
- return tgl_typing_cancel;
- case CODE_send_message_record_video_action:
- return tgl_typing_record_video;
- case CODE_send_message_upload_video_action:
- return tgl_typing_upload_video;
- case CODE_send_message_record_audio_action:
- return tgl_typing_record_audio;
- case CODE_send_message_upload_audio_action:
- return tgl_typing_upload_audio;
- case CODE_send_message_upload_photo_action:
- return tgl_typing_upload_photo;
- case CODE_send_message_upload_document_action:
- return tgl_typing_upload_document;
- case CODE_send_message_geo_location_action:
- return tgl_typing_geo;
- case CODE_send_message_choose_contact_action:
- return tgl_typing_choose_contact;
- default:
- assert (0);
- return tgl_typing_none;
- }
-}
-
-enum tgl_typing_status tglf_fetch_typing (void) {
- struct tl_ds_send_message_action *DS_SMA = fetch_ds_type_send_message_action (TYPE_TO_PARAM (send_message_action));
- enum tgl_typing_status res = tglf_fetch_typing_new (DS_SMA);
- free_ds_type_send_message_action (DS_SMA, TYPE_TO_PARAM (send_message_action));
- return res;
-}
-
-/* {{{ Fetch */
-
-int tglf_fetch_file_location_new (struct tgl_state *TLS, struct tgl_file_location *loc, struct tl_ds_file_location *DS_FL) {
- if (!DS_FL) { return 0; }
- loc->dc = DS_LVAL (DS_FL->dc_id);
- loc->volume = DS_LVAL (DS_FL->volume_id);
- loc->local_id = DS_LVAL (DS_FL->local_id);
- loc->secret = DS_LVAL (DS_FL->secret);
- return 0;
-}
-
-int tglf_fetch_user_status_new (struct tgl_state *TLS, struct tgl_user_status *S, struct tgl_user *U, struct tl_ds_user_status *DS_US) {
- if (!DS_US) { return 0; }
- switch (DS_US->magic) {
- case CODE_user_status_empty:
- if (S->online) {
- tgl_insert_status_update (TLS, U);
- if (S->online == 1) {
- tgl_remove_status_expire (TLS, U);
- }
- }
- S->online = 0;
- S->when = 0;
- break;
- case CODE_user_status_online:
- {
- if (S->online != 1) {
- S->when = DS_LVAL (DS_US->expires);
- if (S->online) {
- tgl_insert_status_update (TLS, U);
- }
- tgl_insert_status_expire (TLS, U);
- S->online = 1;
- } else {
- if (DS_LVAL (DS_US->expires) != S->when) {
- S->when = DS_LVAL (DS_US->expires);
- tgl_remove_status_expire (TLS, U);
- tgl_insert_status_expire (TLS, U);
- }
- }
- }
- break;
- case CODE_user_status_offline:
- if (S->online != -1) {
- if (S->online) {
- tgl_insert_status_update (TLS, U);
- }
- if (S->online == 1) {
- tgl_remove_status_expire (TLS, U);
- }
- }
- S->online = -1;
- S->when = DS_LVAL (DS_US->was_online);
- break;
- case CODE_user_status_recently:
- if (S->online != -2) {
- if (S->online) {
- tgl_insert_status_update (TLS, U);
- }
- if (S->online == 1) {
- tgl_remove_status_expire (TLS, U);
- }
- }
- S->online = -2;
- break;
- case CODE_user_status_last_week:
- if (S->online != -3) {
- if (S->online) {
- tgl_insert_status_update (TLS, U);
- }
- if (S->online == 1) {
- tgl_remove_status_expire (TLS, U);
- }
- }
- S->online = -3;
- break;
- case CODE_user_status_last_month:
- if (S->online != -4) {
- if (S->online) {
- tgl_insert_status_update (TLS, U);
- }
- if (S->online == 1) {
- tgl_remove_status_expire (TLS, U);
- }
- }
- S->online = -4;
- break;
- default:
- assert (0);
- }
- return 0;
-}
-
-int tglf_fetch_user_new (struct tgl_state *TLS, struct tgl_user *U, struct tl_ds_user *DS_U) {
- if (!DS_U) { return 0; }
- U->id = TGL_MK_USER (DS_LVAL (DS_U->id));
- if (DS_U->magic == CODE_user_empty) {
- return 0;
- }
-
- int flags = U->flags & 0xffff;
-
- if (DS_LVAL (DS_U->flags) & (1 << 10)) {
- bl_do_set_our_id (TLS, tgl_get_peer_id (U->id));
- flags |= TGLUF_SELF;
- }
-
- if (DS_LVAL (DS_U->flags) & (1 << 11)) {
- flags |= TGLUF_CONTACT;
- }
-
- if (DS_LVAL (DS_U->flags) & (1 << 12)) {
- flags |= TGLUF_MUTUAL_CONTACT;
- }
-
-
- if (DS_LVAL (DS_U->flags) & (1 << 14)) {
- flags |= TGLUF_BOT;
- }
- /*
- if (DS_LVAL (DS_U->flags) & (1 << 15)) {
- flags |= TGLUF_BOT_FULL_ACCESS;
- }
-
- if (DS_LVAL (DS_U->flags) & (1 << 16)) {
- flags |= TGLUF_BOT_NO_GROUPS;
- }*/
-
- if (!(flags & TGLUF_CREATED)) {
- flags |= TGLUF_CREATE | TGLUF_CREATED;
- }
-
- bl_do_user_new (TLS, tgl_get_peer_id (U->id),
- DS_U->access_hash,
- DS_STR (DS_U->first_name),
- DS_STR (DS_U->last_name),
- DS_STR (DS_U->phone),
- DS_STR (DS_U->username),
- NULL,
- NULL, 0, NULL, 0,
- DS_U->photo,
- NULL, NULL,
- NULL,
- flags
- );
-
- if (DS_U->status) {
- assert (tglf_fetch_user_status_new (TLS, &U->status, U, DS_U->status) >= 0);
- }
-
- if (DS_LVAL (DS_U->flags) & (1 << 13)) {
- if (!(U->flags & TGLUF_DELETED)) {
- bl_do_user_delete (TLS, U);
- }
- }
-
- return 0;
-}
-
-void tglf_fetch_user_full_new (struct tgl_state *TLS, struct tgl_user *U, struct tl_ds_user_full *DS_UF) {
- if (!DS_UF) { return; }
-
- tglf_fetch_user_new (TLS, U, DS_UF->user);
-
- int flags = U->flags & 0xffff;
-
- if (DS_BVAL (DS_UF->blocked)) {
- flags |= TGLUF_BLOCKED;
- } else {
- flags &= ~TGLUF_BLOCKED;
- }
-
- bl_do_user_new (TLS, tgl_get_peer_id (U->id),
- NULL,
- NULL, 0,
- NULL, 0,
- NULL, 0,
- NULL, 0,
- DS_UF->profile_photo,
- //DS_STR (DS_UF->real_first_name), DS_STR (DS_UF->real_last_name),
- NULL, 0, NULL, 0,
- NULL,
- NULL, NULL,
- DS_UF->bot_info,
- flags
- );
-}
-
-void str_to_256 (unsigned char *dst, char *src, int src_len) {
- if (src_len >= 256) {
- memcpy (dst, src + src_len - 256, 256);
- } else {
- bzero (dst, 256 - src_len);
- memcpy (dst + 256 - src_len, src, src_len);
- }
-}
-
-void str_to_32 (unsigned char *dst, char *src, int src_len) {
- if (src_len >= 32) {
- memcpy (dst, src + src_len - 32, 32);
- } else {
- bzero (dst, 32 - src_len);
- memcpy (dst + 32 - src_len, src, src_len);
- }
-}
-
-void tglf_fetch_encrypted_chat_new (struct tgl_state *TLS, struct tgl_secret_chat *U, struct tl_ds_encrypted_chat *DS_EC) {
- if (!DS_EC) { return; }
- U->id = TGL_MK_ENCR_CHAT (DS_LVAL (DS_EC->id));
- if (DS_EC->magic == CODE_encrypted_chat_empty) {
- return;
- }
- int new = !(U->flags & TGLPF_CREATED);
-
- if (DS_EC->magic == CODE_encrypted_chat_discarded) {
- if (new) {
- vlogprintf (E_WARNING, "Unknown chat in deleted state. May be we forgot something...\n");
- return;
- }
- bl_do_encr_chat_delete (TLS, U);
- //write_secret_chat_file ();
- return;
- }
-
- static unsigned char g_key[256];
- if (new) {
- if (DS_EC->magic != CODE_encrypted_chat_requested) {
- vlogprintf (E_WARNING, "Unknown chat. May be we forgot something...\n");
- return;
- }
-
- str_to_256 (g_key, DS_STR (DS_EC->g_a));
-
- int user_id = DS_LVAL (DS_EC->participant_id) + DS_LVAL (DS_EC->admin_id) - TLS->our_id;
- int r = sc_request;
- bl_do_encr_chat_new (TLS, tgl_get_peer_id (U->id),
- DS_EC->access_hash,
- DS_EC->date,
- DS_EC->admin_id,
- &user_id,
- NULL,
- (void *)g_key,
- NULL,
- &r,
- NULL, NULL, NULL, NULL, NULL,
- NULL,
- TGLECF_CREATE | TGLECF_CREATED
- );
- } else {
- if (DS_EC->magic == CODE_encrypted_chat_waiting) {
- int r = sc_waiting;
- bl_do_encr_chat_new (TLS, tgl_get_peer_id (U->id),
- DS_EC->access_hash,
- DS_EC->date,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- &r,
- NULL, NULL, NULL, NULL, NULL,
- NULL,
- TGL_FLAGS_UNCHANGED
- );
- return; // We needed only access hash from here
- }
-
- str_to_256 (g_key, DS_STR (DS_EC->g_a_or_b));
-
- //write_secret_chat_file ();
- int r = sc_ok;
- bl_do_encr_chat_new (TLS, tgl_get_peer_id (U->id),
- DS_EC->access_hash,
- DS_EC->date,
- NULL,
- NULL,
- NULL,
- g_key,
- NULL,
- &r,
- NULL, NULL, NULL, NULL, NULL,
- DS_EC->key_fingerprint,
- TGL_FLAGS_UNCHANGED
- );
- }
-}
-
-void tglf_fetch_chat_new (struct tgl_state *TLS, struct tgl_chat *C, struct tl_ds_chat *DS_C) {
- if (!DS_C) { return; }
-
- C->id = TGL_MK_CHAT (DS_LVAL (DS_C->id));
- if (DS_C->magic == CODE_chat_empty) {
- return;
- }
-
- int flags = C->flags & 0xffff;
- if (!(flags & TGLCF_CREATED)) {
- flags |= TGLCF_CREATE | TGLCF_CREATED;
- }
-
- bl_do_chat_new (TLS, tgl_get_peer_id (C->id),
- DS_STR (DS_C->title),
- DS_C->participants_count,
- DS_C->date,
- NULL,
- NULL,
- DS_C->photo,
- NULL,
- NULL,
- NULL, NULL,
- flags
- );
-}
-
-void tglf_fetch_chat_full_new (struct tgl_state *TLS, struct tgl_chat *C, struct tl_ds_messages_chat_full *DS_MCF) {
- if (!DS_MCF) { return; }
- struct tl_ds_chat_full *DS_CF = DS_MCF->full_chat;
-
- C->id = TGL_MK_CHAT (DS_LVAL (DS_CF->id));
-
- bl_do_chat_new (TLS, tgl_get_peer_id (C->id),
- NULL, 0,
- NULL,
- NULL,
- DS_CF->participants->version,
- (struct tl_ds_vector *)DS_CF->participants->participants,
- NULL,
- DS_CF->chat_photo,
- DS_CF->participants->admin_id,
- NULL, NULL,
- C->flags & 0xffff
- );
-
- if (DS_MCF->users) {
- int i;
- for (i = 0; i < DS_LVAL (DS_MCF->users->cnt); i++) {
- tglf_fetch_alloc_user_new (TLS, DS_MCF->users->data[i]);
- }
- }
-
- if (DS_MCF->chats) {
- int i;
- for (i = 0; i < DS_LVAL (DS_MCF->chats->cnt); i++) {
- tglf_fetch_alloc_chat_new (TLS, DS_MCF->chats->data[i]);
- }
- }
-
- if (DS_CF->bot_info) {
- int n = DS_LVAL (DS_CF->bot_info->cnt);
- int i;
- for (i = 0; i < n; i++) {
- struct tl_ds_bot_info *DS_BI = DS_CF->bot_info->data[i];
-
- tgl_peer_t *P = tgl_peer_get (TLS, TGL_MK_USER (DS_LVAL (DS_BI->user_id)));
- if (P && (P->flags & TGLCF_CREATED)) {
- bl_do_user_new (TLS, tgl_get_peer_id (P->id),
- NULL,
- NULL, 0,
- NULL, 0,
- NULL, 0,
- NULL, 0,
- NULL,
- NULL, 0, NULL, 0,
- NULL,
- NULL, NULL,
- DS_BI,
- TGL_FLAGS_UNCHANGED
- );
- }
- }
- }
-}
-
-void tglf_fetch_photo_size_new (struct tgl_state *TLS, struct tgl_photo_size *S, struct tl_ds_photo_size *DS_PS) {
- memset (S, 0, sizeof (*S));
-
- S->type = DS_STR_DUP (DS_PS->type);
- S->w = DS_LVAL (DS_PS->w);
- S->h = DS_LVAL (DS_PS->h);
- S->size = DS_LVAL (DS_PS->size);
- if (DS_PS->bytes) {
- S->size = DS_PS->bytes->len;
- }
-
- tglf_fetch_file_location_new (TLS, &S->loc, DS_PS->location);
-}
-
-void tglf_fetch_geo_new (struct tgl_state *TLS, struct tgl_geo *G, struct tl_ds_geo_point *DS_GP) {
- G->longitude = DS_LVAL (DS_GP->longitude);
- G->latitude = DS_LVAL (DS_GP->latitude);
-}
-
-struct tgl_photo *tglf_fetch_alloc_photo_new (struct tgl_state *TLS, struct tl_ds_photo *DS_P) {
- if (!DS_P) { return NULL; }
- if (DS_P->magic == CODE_photo_empty) { return NULL; }
-
- struct tgl_photo *P = tgl_photo_get (TLS, DS_LVAL (DS_P->id));
- if (P) {
- P->refcnt ++;
- return P;
- }
-
-
- P = talloc0 (sizeof (*P));
- P->id = DS_LVAL (DS_P->id);
- P->refcnt = 1;
-
- tgl_photo_insert (TLS, P);
-
- P->access_hash = DS_LVAL (DS_P->access_hash);
- P->user_id = DS_LVAL (DS_P->user_id);
- P->date = DS_LVAL (DS_P->date);
- P->caption = NULL;//DS_STR_DUP (DS_P->caption);
- tglf_fetch_geo_new (TLS, &P->geo, DS_P->geo);
-
- P->sizes_num = DS_LVAL (DS_P->sizes->cnt);
- P->sizes = talloc (sizeof (struct tgl_photo_size) * P->sizes_num);
- int i;
- for (i = 0; i < P->sizes_num; i++) {
- tglf_fetch_photo_size_new (TLS, &P->sizes[i], DS_P->sizes->data[i]);
- }
-
- return P;
-}
-
-struct tgl_document *tglf_fetch_alloc_video_new (struct tgl_state *TLS, struct tl_ds_video *DS_V) {
- if (!DS_V) { return NULL; }
-
- if (DS_V->magic == CODE_video_empty) { return NULL; }
-
- struct tgl_document *D = tgl_document_get (TLS, DS_LVAL (DS_V->id));
- if (D) {
- D->refcnt ++;
- return D;
- }
-
-
- D = talloc0 (sizeof (*D));
- D->id = DS_LVAL (DS_V->id);
- D->refcnt = 1;
-
- tgl_document_insert (TLS, D);
-
- D->flags = TGLDF_VIDEO;
-
- D->access_hash = DS_LVAL (DS_V->access_hash);
- D->user_id = DS_LVAL (DS_V->user_id);
- D->date = DS_LVAL (DS_V->date);
- D->caption = NULL;//DS_STR_DUP (DS_V->caption);
- D->duration = DS_LVAL (DS_V->duration);
- D->mime_type = tstrdup ("video/");//DS_STR_DUP (DS_V->mime_type);
- D->size = DS_LVAL (DS_V->size);
- tglf_fetch_photo_size_new (TLS, &D->thumb, DS_V->thumb);
-
- D->dc_id = DS_LVAL (DS_V->dc_id);
- D->w = DS_LVAL (DS_V->w);
- D->h = DS_LVAL (DS_V->h);
- return D;
-}
-
-struct tgl_document *tglf_fetch_alloc_audio_new (struct tgl_state *TLS, struct tl_ds_audio *DS_A) {
- if (!DS_A) { return NULL; }
-
- if (DS_A->magic == CODE_audio_empty) { return NULL; }
-
- struct tgl_document *D = tgl_document_get (TLS, DS_LVAL (DS_A->id));
- if (D) {
- D->refcnt ++;
- return D;
- }
-
-
- D = talloc0 (sizeof (*D));
- D->id = DS_LVAL (DS_A->id);
- D->refcnt = 1;
-
- tgl_document_insert (TLS, D);
-
- D->flags = TGLDF_AUDIO;
-
- D->access_hash = DS_LVAL (DS_A->access_hash);
- D->user_id = DS_LVAL (DS_A->user_id);
- D->date = DS_LVAL (DS_A->date);
- D->duration = DS_LVAL (DS_A->duration);
- D->mime_type = DS_STR_DUP (DS_A->mime_type);
- D->size = DS_LVAL (DS_A->size);
- D->dc_id = DS_LVAL (DS_A->dc_id);
-
- return D;
-}
-
-void tglf_fetch_document_attribute_new (struct tgl_state *TLS, struct tgl_document *D, struct tl_ds_document_attribute *DS_DA) {
- switch (DS_DA->magic) {
- case CODE_document_attribute_image_size:
- D->flags |= TGLDF_IMAGE;
- D->w = DS_LVAL (DS_DA->w);
- D->h = DS_LVAL (DS_DA->h);
- return;
- case CODE_document_attribute_animated:
- D->flags |= TGLDF_ANIMATED;
- return;
- case CODE_document_attribute_sticker:
- case CODE_document_attribute_sticker_l28:
- D->flags |= TGLDF_STICKER;
- return;
- case CODE_document_attribute_video:
- D->flags |= TGLDF_VIDEO;
- D->duration = DS_LVAL (DS_DA->duration);
- D->w = DS_LVAL (DS_DA->w);
- D->h = DS_LVAL (DS_DA->h);
- return;
- case CODE_document_attribute_audio:
- D->flags |= TGLDF_AUDIO;
- D->duration = DS_LVAL (DS_DA->duration);
- return;
- case CODE_document_attribute_filename:
- D->caption = DS_STR_DUP (DS_DA->file_name);
- return;
- default:
- assert (0);
- }
-}
-
-struct tgl_document *tglf_fetch_alloc_document_new (struct tgl_state *TLS, struct tl_ds_document *DS_D) {
- if (!DS_D) { return NULL; }
-
- if (DS_D->magic == CODE_document_empty) { return NULL; }
-
- struct tgl_document *D = tgl_document_get (TLS, DS_LVAL (DS_D->id));
- if (D) {
- D->refcnt ++;
- return D;
- }
-
-
- D = talloc0 (sizeof (*D));
- D->id = DS_LVAL (DS_D->id);
- D->refcnt = 1;
-
- tgl_document_insert (TLS, D);
-
- D->access_hash = DS_LVAL (DS_D->access_hash);
- D->user_id = DS_LVAL (DS_D->user_id);
- D->date = DS_LVAL (DS_D->date);
- D->caption = DS_STR_DUP (DS_D->file_name);
- D->mime_type = DS_STR_DUP (DS_D->mime_type);
- D->size = DS_LVAL (DS_D->size);
- D->dc_id = DS_LVAL (DS_D->dc_id);
-
- tglf_fetch_photo_size_new (TLS, &D->thumb, DS_D->thumb);
-
- if (DS_D->attributes) {
- int i;
- for (i = 0; i < DS_LVAL (DS_D->attributes->cnt); i++) {
- tglf_fetch_document_attribute_new (TLS, D, DS_D->attributes->data[i]);
- }
- }
- return D;
-}
-
-struct tgl_webpage *tglf_fetch_alloc_webpage_new (struct tgl_state *TLS, struct tl_ds_web_page *DS_W) {
- if (!DS_W) { return NULL; }
-
- struct tgl_webpage *W = tgl_webpage_get (TLS, DS_LVAL (DS_W->id));
- if (W) {
- W->refcnt ++;
- } else {
- W = talloc0 (sizeof (*W));
- W->id = DS_LVAL (DS_W->id);
- W->refcnt = 1;
-
- tgl_webpage_insert (TLS, W);
- }
-
- if (!W->url) {
- W->url = DS_STR_DUP (DS_W->url);
- }
-
- if (!W->display_url) {
- W->display_url = DS_STR_DUP (DS_W->display_url);
- }
-
- if (!W->type) {
- W->type = DS_STR_DUP (DS_W->type);
- }
-
- if (!W->site_name) {
- W->site_name = DS_STR_DUP (DS_W->site_name);
- }
-
- if (!W->title) {
- W->title = DS_STR_DUP (DS_W->title);
- }
-
- if (!W->photo) {
- W->photo = tglf_fetch_alloc_photo_new (TLS, DS_W->photo);
- }
-
- if (!W->description) {
- W->description = DS_STR_DUP (DS_W->description);
- }
-
- if (!W->embed_url) {
- W->embed_url = DS_STR_DUP (DS_W->embed_url);
- }
-
- if (!W->embed_type) {
- W->embed_type = DS_STR_DUP (DS_W->embed_type);
- }
-
- W->embed_width = DS_LVAL (DS_W->embed_width);
-
- W->embed_height = DS_LVAL (DS_W->embed_height);
-
- W->duration = DS_LVAL (DS_W->duration);
-
- if (!W->author) {
- W->author = DS_STR_DUP (DS_W->author);
- }
- return W;
-}
-
-void tglf_fetch_message_action_new (struct tgl_state *TLS, struct tgl_message_action *M, struct tl_ds_message_action *DS_MA) {
- if (!DS_MA) { return; }
- memset (M, 0, sizeof (*M));
-
- switch (DS_MA->magic) {
- case CODE_message_action_empty:
- M->type = tgl_message_action_none;
- break;
- case CODE_message_action_geo_chat_create:
- {
- M->type = tgl_message_action_geo_chat_create;
- assert (0);
- }
- break;
- case CODE_message_action_geo_chat_checkin:
- M->type = tgl_message_action_geo_chat_checkin;
- break;
- case CODE_message_action_chat_create:
- {
- M->type = tgl_message_action_chat_create;
- M->title = DS_STR_DUP (DS_MA->title);
-
- M->user_num = DS_LVAL (DS_MA->users->cnt);
- M->users = talloc (M->user_num * 4);
- int i;
- for (i = 0; i < M->user_num; i++) {
- M->users[i] = DS_LVAL (DS_MA->users->data[i]);
- }
- }
- break;
- case CODE_message_action_chat_edit_title:
- M->type = tgl_message_action_chat_edit_title;
- M->new_title = DS_STR_DUP (DS_MA->title);
- break;
- case CODE_message_action_chat_edit_photo:
- M->type = tgl_message_action_chat_edit_photo;
- M->photo = tglf_fetch_alloc_photo_new (TLS, DS_MA->photo);
- break;
- case CODE_message_action_chat_delete_photo:
- M->type = tgl_message_action_chat_delete_photo;
- break;
- case CODE_message_action_chat_add_user:
- M->type = tgl_message_action_chat_add_user;
- M->user = DS_LVAL (DS_MA->user_id);
- break;
- case CODE_message_action_chat_delete_user:
- M->type = tgl_message_action_chat_delete_user;
- M->user = DS_LVAL (DS_MA->user_id);
- break;
- case CODE_message_action_chat_joined_by_link:
- M->type = tgl_message_action_chat_add_user_by_link;
- M->user = DS_LVAL (DS_MA->inviter_id);
- break;
- default:
- assert (0);
- }
-}
-
-void tglf_fetch_message_short_new (struct tgl_state *TLS, struct tgl_message *M, struct tl_ds_updates *DS_U) {
- tgl_peer_t *P = tgl_peer_get (TLS, TGL_MK_USER (DS_LVAL (DS_U->user_id)));
- if (!P || !(P->flags & TGLPF_CREATED)) {
- tgl_do_get_difference (TLS, 0, 0, 0);
- return;
- }
-
- int flags = M->flags & 0xffff;
-
- if (M->flags & TGLMF_PENDING) {
- M->flags ^= TGLMF_PENDING;
- }
-
- if (!(flags & TGLMF_CREATED)) {
- flags |= TGLMF_CREATE | TGLMF_CREATED;
- }
-
- int f = DS_LVAL (DS_U->flags);
-
- if (f & 1) {
- flags |= TGLMF_UNREAD;
- }
- if (f & 2) {
- flags |= TGLMF_OUT;
- }
- if (f & 16) {
- flags |= TGLMF_MENTION;
- }
-
- struct tl_ds_message_media A;
- A.magic = CODE_message_media_empty;
- int type = TGL_PEER_USER;
-
- bl_do_create_message_new (TLS, DS_LVAL (DS_U->id),
- (f & 2) ? &TLS->our_id : DS_U->user_id,
- &type, (f & 2) ? DS_U->user_id : &TLS->our_id,
- DS_U->fwd_from_id,
- DS_U->fwd_date,
- DS_U->date,
- DS_STR (DS_U->message),
- &A,
- NULL,
- DS_U->reply_to_msg_id,
- NULL,
- flags
- );
-}
-
-void tglf_fetch_message_short_chat_new (struct tgl_state *TLS, struct tgl_message *M, struct tl_ds_updates *DS_U) {
- tgl_peer_t *P = tgl_peer_get (TLS, TGL_MK_USER (DS_LVAL (DS_U->from_id)));
- if (!P || !(P->flags & TGLPF_CREATED)) {
- tgl_do_get_difference (TLS, 0, 0, 0);
- return;
- }
- P = tgl_peer_get (TLS, TGL_MK_CHAT (DS_LVAL (DS_U->chat_id)));
- if (!P || !(P->flags & TGLPF_CREATED)) {
- tgl_do_get_difference (TLS, 0, 0, 0);
- return;
- }
-
- int flags = M->flags & 0xffff;
-
- if (M->flags & TGLMF_PENDING) {
- M->flags ^= TGLMF_PENDING;
- }
-
- if (!(flags & TGLMF_CREATED)) {
- flags |= TGLMF_CREATE | TGLMF_CREATED;
- }
-
- int f = DS_LVAL (DS_U->flags);
-
- if (f & 1) {
- flags |= TGLMF_UNREAD;
- }
- if (f & 2) {
- flags |= TGLMF_OUT;
- }
- if (f & 16) {
- flags |= TGLMF_MENTION;
- }
-
- struct tl_ds_message_media A;
- A.magic = CODE_message_media_empty;
-
- int type = TGL_PEER_CHAT;
- bl_do_create_message_new (TLS, DS_LVAL (DS_U->id),
- DS_U->from_id,
- &type, DS_U->chat_id,
- DS_U->fwd_from_id,
- DS_U->fwd_date,
- DS_U->date,
- DS_STR (DS_U->message),
- &A,
- NULL,
- DS_U->reply_to_msg_id,
- NULL,
- flags
- );
-}
-
-
-void tglf_fetch_message_media_new (struct tgl_state *TLS, struct tgl_message_media *M, struct tl_ds_message_media *DS_MM) {
- if (!DS_MM) { return; }
- memset (M, 0, sizeof (*M));
- switch (DS_MM->magic) {
- case CODE_message_media_empty:
- M->type = tgl_message_media_none;
- break;
- case CODE_message_media_photo:
- case CODE_message_media_photo_l27:
- M->type = tgl_message_media_photo;
- M->photo = tglf_fetch_alloc_photo_new (TLS, DS_MM->photo);
- M->caption = DS_STR_DUP (DS_MM->caption);
- break;
- case CODE_message_media_video:
- case CODE_message_media_video_l27:
- M->type = tgl_message_media_video;
- M->document = tglf_fetch_alloc_video_new (TLS, DS_MM->video);
- M->caption = DS_STR_DUP (DS_MM->caption);
- break;
- case CODE_message_media_audio:
- M->type = tgl_message_media_audio;
- M->document = tglf_fetch_alloc_audio_new (TLS, DS_MM->audio);
- break;
- case CODE_message_media_document:
- M->type = tgl_message_media_document;
- M->document = tglf_fetch_alloc_document_new (TLS, DS_MM->document);
- break;
- case CODE_message_media_geo:
- M->type = tgl_message_media_geo;
- tglf_fetch_geo_new (TLS, &M->geo, DS_MM->geo);
- break;
- case CODE_message_media_contact:
- M->type = tgl_message_media_contact;
- M->phone = DS_STR_DUP (DS_MM->phone_number);
- M->first_name = DS_STR_DUP (DS_MM->first_name);
- M->last_name = DS_STR_DUP (DS_MM->last_name);
- M->user_id = DS_LVAL (DS_MM->user_id);
- break;
- //case CODE_message_media_unsupported:
- //case CODE_message_media_unsupported_l22:
- // M->type = tgl_message_media_unsupported;
- // break;
- case CODE_message_media_web_page:
- M->type = tgl_message_media_webpage;
- M->webpage = tglf_fetch_alloc_webpage_new (TLS, DS_MM->webpage);
- break;
- case CODE_message_media_venue:
- M->type = tgl_message_media_venue;
- tglf_fetch_geo_new (TLS, &M->venue.geo, DS_MM->geo);
- M->venue.title = DS_STR_DUP (DS_MM->title);
- M->venue.address = DS_STR_DUP (DS_MM->address);
- M->venue.provider = DS_STR_DUP (DS_MM->provider);
- M->venue.venue_id = DS_STR_DUP (DS_MM->venue_id);
- break;
- default:
- assert (0);
- }
-}
-
-void tglf_fetch_message_media_encrypted_new (struct tgl_state *TLS, struct tgl_message_media *M, struct tl_ds_decrypted_message_media *DS_DMM) {
- if (!DS_DMM) { return; }
-
- memset (M, 0, sizeof (*M));
- switch (DS_DMM->magic) {
- case CODE_decrypted_message_media_empty:
- M->type = tgl_message_media_none;
- //M->type = CODE_message_media_empty;
- break;
- case CODE_decrypted_message_media_photo:
- case CODE_decrypted_message_media_video:
- case CODE_decrypted_message_media_video_l12:
- case CODE_decrypted_message_media_document:
- case CODE_decrypted_message_media_audio:
- //M->type = CODE_decrypted_message_media_video;
- M->type = tgl_message_media_document_encr;
-
- M->encr_document = talloc0 (sizeof (*M->encr_document));
-
- switch (DS_DMM->magic) {
- case CODE_decrypted_message_media_photo:
- M->encr_document->flags = TGLDF_IMAGE;
- break;
- case CODE_decrypted_message_media_video:
- case CODE_decrypted_message_media_video_l12:
- M->encr_document->flags = TGLDF_VIDEO;
- break;
- case CODE_decrypted_message_media_document:
- //M->encr_document->flags = TGLDF_DOCUMENT;
- break;
- case CODE_decrypted_message_media_audio:
- M->encr_document->flags = TGLDF_AUDIO;
- break;
- }
-
- M->encr_document->w = DS_LVAL (DS_DMM->w);
- M->encr_document->h = DS_LVAL (DS_DMM->h);
- M->encr_document->size = DS_LVAL (DS_DMM->size);
- M->encr_document->duration = DS_LVAL (DS_DMM->duration);
- M->encr_document->mime_type = DS_STR_DUP (DS_DMM->mime_type);
-
- M->encr_document->key = talloc (32);
- str_to_32 (M->encr_document->key, DS_STR (DS_DMM->key));
- M->encr_document->iv = talloc (32);
- str_to_32 (M->encr_document->iv, DS_STR (DS_DMM->iv));
- break;
- case CODE_decrypted_message_media_geo_point:
- M->type = tgl_message_media_geo;
- M->geo.latitude = DS_LVAL (DS_DMM->latitude);
- M->geo.longitude = DS_LVAL (DS_DMM->longitude);
- break;
- case CODE_decrypted_message_media_contact:
- M->type = tgl_message_media_contact;
- M->phone = DS_STR_DUP (DS_DMM->phone_number);
- M->first_name = DS_STR_DUP (DS_DMM->first_name);
- M->last_name = DS_STR_DUP (DS_DMM->last_name);
- M->user_id = DS_LVAL (DS_DMM->user_id);
- break;
- default:
- assert (0);
- }
-}
-
-void tglf_fetch_message_action_encrypted_new (struct tgl_state *TLS, struct tgl_message_action *M, struct tl_ds_decrypted_message_action *DS_DMA) {
- if (!DS_DMA) { return; }
-
- switch (DS_DMA->magic) {
- case CODE_decrypted_message_action_set_message_t_t_l:
- M->type = tgl_message_action_set_message_ttl;
- M->ttl = DS_LVAL (DS_DMA->ttl_seconds);
- break;
- case CODE_decrypted_message_action_read_messages:
- M->type = tgl_message_action_read_messages;
- {
- M->read_cnt = DS_LVAL (DS_DMA->random_ids->cnt);
-
- int i;
- for (i = 0; i < M->read_cnt; i++) {
- struct tgl_message *N = tgl_message_get (TLS, DS_LVAL (DS_DMA->random_ids->data[i]));
- if (N) {
- N->flags &= ~TGLMF_UNREAD;
- }
- }
- }
- break;
- case CODE_decrypted_message_action_delete_messages:
- M->type = tgl_message_action_delete_messages;
- break;
- case CODE_decrypted_message_action_screenshot_messages:
- M->type = tgl_message_action_screenshot_messages;
- {
- M->screenshot_cnt = DS_LVAL (DS_DMA->random_ids->cnt);
- }
- break;
- case CODE_decrypted_message_action_notify_layer:
- M->type = tgl_message_action_notify_layer;
- M->layer = DS_LVAL (DS_DMA->layer);
- break;
- case CODE_decrypted_message_action_flush_history:
- M->type = tgl_message_action_flush_history;
- break;
- case CODE_decrypted_message_action_typing:
- M->type = tgl_message_action_typing;
- M->typing = tglf_fetch_typing_new (DS_DMA->action);
- break;
- case CODE_decrypted_message_action_resend:
- M->type = tgl_message_action_resend;
- M->start_seq_no = DS_LVAL (DS_DMA->start_seq_no);
- M->end_seq_no = DS_LVAL (DS_DMA->end_seq_no);
- break;
- case CODE_decrypted_message_action_noop:
- M->type = tgl_message_action_noop;
- break;
- case CODE_decrypted_message_action_request_key:
- M->type = tgl_message_action_request_key;
-
- M->exchange_id = DS_LVAL (DS_DMA->exchange_id);
- M->g_a = talloc (256);
- str_to_256 (M->g_a, DS_STR (DS_DMA->g_a));
- break;
- case CODE_decrypted_message_action_accept_key:
- M->type = tgl_message_action_accept_key;
-
- M->exchange_id = DS_LVAL (DS_DMA->exchange_id);
- M->g_a = talloc (256);
- str_to_256 (M->g_a, DS_STR (DS_DMA->g_b));
- M->key_fingerprint = DS_LVAL (DS_DMA->key_fingerprint);
- break;
- case CODE_decrypted_message_action_commit_key:
- M->type = tgl_message_action_commit_key;
-
- M->exchange_id = DS_LVAL (DS_DMA->exchange_id);
- M->key_fingerprint = DS_LVAL (DS_DMA->key_fingerprint);
- break;
- case CODE_decrypted_message_action_abort_key:
- M->type = tgl_message_action_abort_key;
-
- M->exchange_id = DS_LVAL (DS_DMA->exchange_id);
- break;
- default:
- assert (0);
- }
-}
-
-tgl_peer_id_t tglf_fetch_peer_id_new (struct tgl_state *TLS, struct tl_ds_peer *DS_P) {
- if (DS_P->magic == CODE_peer_user) {
- return TGL_MK_USER (DS_LVAL (DS_P->user_id));
- } else {
- return TGL_MK_CHAT (DS_LVAL (DS_P->chat_id));
- }
-}
-
-void tglf_fetch_message_new (struct tgl_state *TLS, struct tgl_message *M, struct tl_ds_message *DS_M) {
- if (!DS_M || DS_M->magic == CODE_message_empty) { return; }
-
- assert (M->id == DS_LVAL (DS_M->id));
-
- tgl_peer_id_t to_id = tglf_fetch_peer_id_new (TLS, DS_M->to_id);
- {
- tgl_peer_t *P = tgl_peer_get (TLS, to_id);
- if (!P || !(P->flags & TGLPF_CREATED)) {
- tgl_do_get_difference (TLS, 0, 0, 0);
- return;
- }
- P = tgl_peer_get (TLS, TGL_MK_USER (DS_LVAL (DS_M->from_id)));
- if (!P || !(P->flags & TGLPF_CREATED)) {
- tgl_do_get_difference (TLS, 0, 0, 0);
- return;
- }
- }
-
- int new = !(M->flags & TGLMF_CREATED);
-
- if (new) {
- int peer_id = tgl_get_peer_id (to_id);
- int peer_type = tgl_get_peer_type (to_id);
-
- int flags = 0;
- if (DS_LVAL (DS_M->flags) & 1) {
- flags |= TGLMF_UNREAD;
- }
- if (DS_LVAL (DS_M->flags) & 2) {
- flags |= TGLMF_OUT;
- }
- if (DS_LVAL (DS_M->flags) & 16) {
- flags |= TGLMF_MENTION;
- }
-
- bl_do_create_message_new (TLS, DS_LVAL (DS_M->id),
- DS_M->from_id,
- &peer_type, &peer_id,
- DS_M->fwd_from_id, DS_M->fwd_date,
- DS_M->date,
- DS_STR (DS_M->message),
- DS_M->media,
- DS_M->action,
- DS_M->reply_to_msg_id,
- DS_M->reply_markup,
- flags | TGLMF_CREATE | TGLMF_CREATED
- );
- }
-}
-
-static int *decr_ptr;
-static int *decr_end;
-
-static int decrypt_encrypted_message (struct tgl_secret_chat *E) {
- int *msg_key = decr_ptr;
- decr_ptr += 4;
- assert (decr_ptr < decr_end);
- static unsigned char sha1a_buffer[20];
- static unsigned char sha1b_buffer[20];
- static unsigned char sha1c_buffer[20];
- static unsigned char sha1d_buffer[20];
-
- static unsigned char buf[64];
-
- int *e_key = E->exchange_state != tgl_sce_committed ? E->key : E->exchange_key;
-
- memcpy (buf, msg_key, 16);
- memcpy (buf + 16, e_key, 32);
- sha1 (buf, 48, sha1a_buffer);
-
- memcpy (buf, e_key + 8, 16);
- memcpy (buf + 16, msg_key, 16);
- memcpy (buf + 32, e_key + 12, 16);
- sha1 (buf, 48, sha1b_buffer);
-
- memcpy (buf, e_key + 16, 32);
- memcpy (buf + 32, msg_key, 16);
- sha1 (buf, 48, sha1c_buffer);
-
- memcpy (buf, msg_key, 16);
- memcpy (buf + 16, e_key + 24, 32);
- sha1 (buf, 48, sha1d_buffer);
-
- static unsigned char key[32];
- memcpy (key, sha1a_buffer + 0, 8);
- memcpy (key + 8, sha1b_buffer + 8, 12);
- memcpy (key + 20, sha1c_buffer + 4, 12);
-
- static unsigned char iv[32];
- memcpy (iv, sha1a_buffer + 8, 12);
- memcpy (iv + 12, sha1b_buffer + 0, 8);
- memcpy (iv + 20, sha1c_buffer + 16, 4);
- memcpy (iv + 24, sha1d_buffer + 0, 8);
-
- AES_KEY aes_key;
- AES_set_decrypt_key (key, 256, &aes_key);
- AES_ige_encrypt ((void *)decr_ptr, (void *)decr_ptr, 4 * (decr_end - decr_ptr), &aes_key, iv, 0);
- memset (&aes_key, 0, sizeof (aes_key));
-
- int x = *(decr_ptr);
- if (x < 0 || (x & 3)) {
- return -1;
- }
- assert (x >= 0 && !(x & 3));
- sha1 ((void *)decr_ptr, 4 + x, sha1a_buffer);
-
- if (memcmp (sha1a_buffer + 4, msg_key, 16)) {
- return -1;
- }
- return 0;
-}
-
-void tglf_fetch_encrypted_message_new (struct tgl_state *TLS, struct tgl_message *M, struct tl_ds_encrypted_message *DS_EM) {
- if (!DS_EM) { return; }
-
- int new = !(M->flags & TGLMF_CREATED);
- if (!new) {
- return;
- }
-
- tgl_peer_t *P = tgl_peer_get (TLS, TGL_MK_ENCR_CHAT (DS_LVAL (DS_EM->chat_id)));
- if (!P || P->encr_chat.state != sc_ok) {
- vlogprintf (E_WARNING, "Encrypted message to unknown chat. Dropping\n");
- return;
- }
-
- decr_ptr = (void *)DS_EM->bytes->data;
- decr_end = decr_ptr + (DS_EM->bytes->len / 4);
-
- if (P->encr_chat.exchange_state == tgl_sce_committed && P->encr_chat.key_fingerprint == *(long long *)decr_ptr) {
- tgl_do_confirm_exchange (TLS, (void *)P, 0);
- assert (P->encr_chat.exchange_state == tgl_sce_none);
- }
-
- long long key_fingerprint = P->encr_chat.exchange_state != tgl_sce_committed ? P->encr_chat.key_fingerprint : P->encr_chat.exchange_key_fingerprint;
- if (*(long long *)decr_ptr != key_fingerprint) {
- vlogprintf (E_WARNING, "Encrypted message with bad fingerprint to chat %s\n", P->print_name);
- return;
- }
-
- decr_ptr += 2;
-
- if (decrypt_encrypted_message (&P->encr_chat) < 0) {
- vlogprintf (E_WARNING, "can not decrypt message\n");
- return;
- }
-
- int *save_in_ptr = in_ptr;
- int *save_in_end = in_end;
-
- in_ptr = decr_ptr;
- int ll = *in_ptr;
- in_end = in_ptr + ll / 4 + 1;
- assert (fetch_int () == ll);
-
- if (skip_type_decrypted_message_layer (TYPE_TO_PARAM (decrypted_message_layer)) < 0 || in_ptr != in_end) {
- vlogprintf (E_WARNING, "can not fetch message\n");
- in_ptr = save_in_ptr;
- in_end = save_in_end;
- return;
- }
-
- in_ptr = decr_ptr;
- assert (fetch_int () == ll);
-
- struct tl_ds_decrypted_message_layer *DS_DML = fetch_ds_type_decrypted_message_layer (TYPE_TO_PARAM (decrypted_message_layer));
- assert (DS_DML);
-
- in_ptr = save_in_ptr;
- in_end = save_in_end;
-
- //bl_do_encr_chat_set_layer (TLS, (void *)P, DS_LVAL (DS_DML->layer));
- bl_do_encr_chat_new (TLS, tgl_get_peer_id (P->id),
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, DS_DML->layer, NULL, NULL, NULL, NULL,
- TGL_FLAGS_UNCHANGED
- );
-
- int in_seq_no = DS_LVAL (DS_DML->out_seq_no);
- int out_seq_no = DS_LVAL (DS_DML->in_seq_no);
-
- if (in_seq_no / 2 != P->encr_chat.in_seq_no) {
- vlogprintf (E_WARNING, "Hole in seq in secret chat. in_seq_no = %d, expect_seq_no = %d\n", in_seq_no / 2, P->encr_chat.in_seq_no);
- free_ds_type_decrypted_message_layer (DS_DML, TYPE_TO_PARAM(decrypted_message_layer));
- return;
- }
-
- if ((in_seq_no & 1) != 1 - (P->encr_chat.admin_id == TLS->our_id) ||
- (out_seq_no & 1) != (P->encr_chat.admin_id == TLS->our_id)) {
- vlogprintf (E_WARNING, "Bad msg admin\n");
- free_ds_type_decrypted_message_layer (DS_DML, TYPE_TO_PARAM(decrypted_message_layer));
- return;
- }
- if (out_seq_no / 2 > P->encr_chat.out_seq_no) {
- vlogprintf (E_WARNING, "In seq no is bigger than our's out seq no (out_seq_no = %d, our_out_seq_no = %d). Drop\n", out_seq_no / 2, P->encr_chat.out_seq_no);
- free_ds_type_decrypted_message_layer (DS_DML, TYPE_TO_PARAM(decrypted_message_layer));
- return;
- }
- if (out_seq_no / 2 < P->encr_chat.last_in_seq_no) {
- vlogprintf (E_WARNING, "Clients in_seq_no decreased (out_seq_no = %d, last_out_seq_no = %d). Drop\n", out_seq_no / 2, P->encr_chat.last_in_seq_no);
- free_ds_type_decrypted_message_layer (DS_DML, TYPE_TO_PARAM(decrypted_message_layer));
- return;
- }
-
- struct tl_ds_decrypted_message *DS_DM = DS_DML->message;
- if (M->id != DS_LVAL (DS_DM->random_id)) {
- vlogprintf (E_ERROR, "Incorrect message: id = %"_PRINTF_INT64_"d, new_id = %"_PRINTF_INT64_"d\n", M->id, DS_LVAL (DS_DM->random_id));
- free_ds_type_decrypted_message_layer (DS_DML, TYPE_TO_PARAM(decrypted_message_layer));
- return;
- }
-
- int peer_type = TGL_PEER_ENCR_CHAT;
- int peer_id = tgl_get_peer_id (P->id);
-
- bl_do_create_message_encr_new (TLS, M->id, &P->encr_chat.user_id, &peer_type, &peer_id, DS_EM->date, DS_STR (DS_DM->message), DS_DM->media, DS_DM->action, DS_EM->file, TGLMF_CREATE | TGLMF_CREATED | TGLMF_ENCRYPTED);
-
- if (in_seq_no >= 0 && out_seq_no >= 0) {
- //bl_do_encr_chat_update_seq (TLS, (void *)P, in_seq_no / 2 + 1, out_seq_no / 2);
- in_seq_no = in_seq_no / 2 + 1;
- out_seq_no = out_seq_no / 2;
- bl_do_encr_chat_new (TLS, tgl_get_peer_id (P->id),
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, &in_seq_no, &out_seq_no, NULL, NULL,
- TGL_FLAGS_UNCHANGED
- );
- assert (P->encr_chat.in_seq_no == in_seq_no);
- }
-
- free_ds_type_decrypted_message_layer (DS_DML, TYPE_TO_PARAM(decrypted_message_layer));
-}
-
-void tglf_fetch_encrypted_message_file_new (struct tgl_state *TLS, struct tgl_message_media *M, struct tl_ds_encrypted_file *DS_EF) {
- if (DS_EF->magic == CODE_encrypted_file_empty) {
- assert (M->type != tgl_message_media_document_encr);
- } else {
- assert (M->type == tgl_message_media_document_encr);
- assert (M->encr_document);
-
- M->encr_document->id = DS_LVAL (DS_EF->id);
- M->encr_document->access_hash = DS_LVAL (DS_EF->access_hash);
- if (!M->encr_document->size) {
- M->encr_document->size = DS_LVAL (DS_EF->size);
- }
- M->encr_document->dc_id = DS_LVAL (DS_EF->dc_id);
- M->encr_document->key_fingerprint = DS_LVAL (DS_EF->key_fingerprint);
- }
-}
-
-static int id_cmp (struct tgl_message *M1, struct tgl_message *M2) {
- if (M1->id < M2->id) { return -1; }
- else if (M1->id > M2->id) { return 1; }
- else { return 0; }
-}
-
-static void increase_peer_size (struct tgl_state *TLS) {
- if (TLS->peer_num == TLS->peer_size) {
- int new_size = TLS->peer_size ? 2 * TLS->peer_size : 10;
- int old_size = TLS->peer_size;
- if (old_size) {
- TLS->Peers = trealloc (TLS->Peers, old_size * sizeof (void *), new_size * sizeof (void *));
- } else {
- TLS->Peers = talloc (new_size * sizeof (void *));
- }
- TLS->peer_size = new_size;
- }
-}
-
-struct tgl_user *tglf_fetch_alloc_user_new (struct tgl_state *TLS, struct tl_ds_user *DS_U) {
- tgl_peer_t *U = tgl_peer_get (TLS, TGL_MK_USER (DS_LVAL (DS_U->id)));
- if (!U) {
- TLS->users_allocated ++;
- U = talloc0 (sizeof (*U));
- U->id = TGL_MK_USER (DS_LVAL (DS_U->id));
- TLS->peer_tree = tree_insert_peer (TLS->peer_tree, U, lrand48 ());
- increase_peer_size (TLS);
- TLS->Peers[TLS->peer_num ++] = U;
- }
- tglf_fetch_user_new (TLS, &U->user, DS_U);
- return &U->user;
-}
-
-struct tgl_secret_chat *tglf_fetch_alloc_encrypted_chat_new (struct tgl_state *TLS, struct tl_ds_encrypted_chat *DS_EC) {
- tgl_peer_t *U = tgl_peer_get (TLS, TGL_MK_ENCR_CHAT (DS_LVAL (DS_EC->id)));
- if (!U) {
- U = talloc0 (sizeof (*U));
- U->id = TGL_MK_ENCR_CHAT (DS_LVAL (DS_EC->id));
- TLS->encr_chats_allocated ++;
- TLS->peer_tree = tree_insert_peer (TLS->peer_tree, U, lrand48 ());
- increase_peer_size (TLS);
- TLS->Peers[TLS->peer_num ++] = U;
- }
- tglf_fetch_encrypted_chat_new (TLS, &U->encr_chat, DS_EC);
- return &U->encr_chat;
-}
-
-struct tgl_user *tglf_fetch_alloc_user_full_new (struct tgl_state *TLS, struct tl_ds_user_full *DS_U) {
- tgl_peer_t *U = tgl_peer_get (TLS, TGL_MK_USER (DS_LVAL (DS_U->user->id)));
- if (U) {
- tglf_fetch_user_full_new (TLS, &U->user, DS_U);
- return &U->user;
- } else {
- TLS->users_allocated ++;
- U = talloc0 (sizeof (*U));
- U->id = TGL_MK_USER (DS_LVAL (DS_U->user->id));
- TLS->peer_tree = tree_insert_peer (TLS->peer_tree, U, lrand48 ());
- tglf_fetch_user_full_new (TLS, &U->user, DS_U);
- increase_peer_size (TLS);
- TLS->Peers[TLS->peer_num ++] = U;
- return &U->user;
- }
-}
-
-struct tgl_message *tglf_fetch_alloc_message_new (struct tgl_state *TLS, struct tl_ds_message *DS_M) {
- struct tgl_message *M = tgl_message_get (TLS, DS_LVAL (DS_M->id));
-
- if (!M) {
- M = tglm_message_alloc (TLS, DS_LVAL (DS_M->id));
- }
- tglf_fetch_message_new (TLS, M, DS_M);
- return M;
-}
-
-struct tgl_message *tglf_fetch_alloc_encrypted_message_new (struct tgl_state *TLS, struct tl_ds_encrypted_message *DS_EM) {
- struct tgl_message *M = tgl_message_get (TLS, DS_LVAL (DS_EM->random_id));
-
- if (!M) {
- M = talloc0 (sizeof (*M));
- M->id = DS_LVAL (DS_EM->random_id);
- tglm_message_insert_tree (TLS, M);
- TLS->messages_allocated ++;
- assert (tgl_message_get (TLS, M->id) == M);
- }
- tglf_fetch_encrypted_message_new (TLS, M, DS_EM);
-
- if (M->flags & TGLMF_CREATED) {
- tgl_peer_t *_E = tgl_peer_get (TLS, M->to_id);
- assert (_E);
- struct tgl_secret_chat *E = &_E->encr_chat;
- if (M->action.type == tgl_message_action_request_key) {
- if (E->exchange_state == tgl_sce_none || (E->exchange_state == tgl_sce_requested && E->exchange_id > M->action.exchange_id )) {
- tgl_do_accept_exchange (TLS, E, M->action.exchange_id, M->action.g_a);
- } else {
- vlogprintf (E_WARNING, "Exchange: Incorrect state (received request, state = %d)\n", E->exchange_state);
- }
- }
- if (M->action.type == tgl_message_action_accept_key) {
- if (E->exchange_state == tgl_sce_requested && E->exchange_id == M->action.exchange_id) {
- tgl_do_commit_exchange (TLS, E, M->action.g_a);
- } else {
- vlogprintf (E_WARNING, "Exchange: Incorrect state (received accept, state = %d)\n", E->exchange_state);
- }
- }
- if (M->action.type == tgl_message_action_commit_key) {
- if (E->exchange_state == tgl_sce_accepted && E->exchange_id == M->action.exchange_id) {
- tgl_do_confirm_exchange (TLS, E, 1);
- } else {
- vlogprintf (E_WARNING, "Exchange: Incorrect state (received commit, state = %d)\n", E->exchange_state);
- }
- }
- if (M->action.type == tgl_message_action_abort_key) {
- if (E->exchange_state != tgl_sce_none && E->exchange_id == M->action.exchange_id) {
- tgl_do_abort_exchange (TLS, E);
- } else {
- vlogprintf (E_WARNING, "Exchange: Incorrect state (received abort, state = %d)\n", E->exchange_state);
- }
- }
- if (M->action.type == tgl_message_action_notify_layer) {
- bl_do_encr_chat_new (TLS, tgl_get_peer_id (E->id),
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, &M->action.layer, NULL, NULL, NULL, NULL,
- TGL_FLAGS_UNCHANGED
- );
- }
- if (M->action.type == tgl_message_action_set_message_ttl) {
- //bl_do_encr_chat_set_ttl (TLS, E, M->action.ttl);
- bl_do_encr_chat_new (TLS, tgl_get_peer_id (E->id),
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- &M->action.ttl, NULL, NULL, NULL, NULL, NULL,
- TGL_FLAGS_UNCHANGED
- );
- }
- }
- return M;
-}
-
-struct tgl_message *tglf_fetch_alloc_message_short_new (struct tgl_state *TLS, struct tl_ds_updates *DS_U) {
- int id = DS_LVAL (DS_U->id);
- struct tgl_message *M = tgl_message_get (TLS, id);
-
- if (!M) {
- M = talloc0 (sizeof (*M));
- M->id = id;
- tglm_message_insert_tree (TLS, M);
- TLS->messages_allocated ++;
- }
- tglf_fetch_message_short_new (TLS, M, DS_U);
- return M;
-}
-
-struct tgl_message *tglf_fetch_alloc_message_short_chat_new (struct tgl_state *TLS, struct tl_ds_updates *DS_U) {
- int id = DS_LVAL (DS_U->id);
- struct tgl_message *M = tgl_message_get (TLS, id);
-
- if (!M) {
- M = talloc0 (sizeof (*M));
- M->id = id;
- tglm_message_insert_tree (TLS, M);
- TLS->messages_allocated ++;
- }
- tglf_fetch_message_short_chat_new (TLS, M, DS_U);
- return M;
-}
-
-struct tgl_chat *tglf_fetch_alloc_chat_new (struct tgl_state *TLS, struct tl_ds_chat *DS_C) {
- tgl_peer_t *U = tgl_peer_get (TLS, TGL_MK_CHAT (DS_LVAL (DS_C->id)));
- if (!U) {
- TLS->chats_allocated ++;
- U = talloc0 (sizeof (*U));
- U->id = TGL_MK_CHAT (DS_LVAL (DS_C->id));
- TLS->peer_tree = tree_insert_peer (TLS->peer_tree, U, lrand48 ());
- increase_peer_size (TLS);
- TLS->Peers[TLS->peer_num ++] = U;
- }
- tglf_fetch_chat_new (TLS, &U->chat, DS_C);
- return &U->chat;
-}
-
-struct tgl_chat *tglf_fetch_alloc_chat_full_new (struct tgl_state *TLS, struct tl_ds_messages_chat_full *DS_MCF) {
- tgl_peer_t *U = tgl_peer_get (TLS, TGL_MK_CHAT (DS_LVAL (DS_MCF->full_chat->id)));
- if (U) {
- tglf_fetch_chat_full_new (TLS, &U->chat, DS_MCF);
- return &U->chat;
- } else {
- TLS->chats_allocated ++;
- U = talloc0 (sizeof (*U));
- U->id = TGL_MK_CHAT (DS_LVAL (DS_MCF->full_chat->id));
- TLS->peer_tree = tree_insert_peer (TLS->peer_tree, U, lrand48 ());
- tglf_fetch_chat_full_new (TLS, &U->chat, DS_MCF);
- increase_peer_size (TLS);
- TLS->Peers[TLS->peer_num ++] = U;
- return &U->chat;
- }
-}
-
-struct tgl_bot_info *tglf_fetch_alloc_bot_info (struct tgl_state *TLS, struct tl_ds_bot_info *DS_BI) {
- if (!DS_BI || DS_BI->magic == CODE_bot_info_empty) { return NULL; }
- struct tgl_bot_info *B = talloc (sizeof (*B));
- B->version = DS_LVAL (DS_BI->version);
- B->share_text = DS_STR_DUP (DS_BI->share_text);
- B->description = DS_STR_DUP (DS_BI->description);
-
- B->commands_num = DS_LVAL (DS_BI->commands->cnt);
- B->commands = talloc (sizeof (struct tgl_bot_command) * B->commands_num);
- int i;
- for (i = 0; i < B->commands_num; i++) {
- struct tl_ds_bot_command *BC = DS_BI->commands->data[i];
- B->commands[i].command = DS_STR_DUP (BC->command);
- B->commands[i].description = DS_STR_DUP (BC->description);
- }
- return B;
-}
-
-struct tgl_message_reply_markup *tglf_fetch_alloc_reply_markup (struct tgl_state *TLS, struct tgl_message *M, struct tl_ds_reply_markup *DS_RM) {
- if (!DS_RM) { return NULL; }
-
- struct tgl_message_reply_markup *R = talloc0 (sizeof (*R));
- R->flags = DS_LVAL (DS_RM->flags);
- R->refcnt = 1;
-
- R->rows = DS_RM->rows ? DS_LVAL (DS_RM->rows->cnt) : 0;
-
- int total = 0;
- R->row_start = talloc ((R->rows + 1) * 4);
- R->row_start[0] = 0;
- int i;
- for (i = 0; i < R->rows; i++) {
- struct tl_ds_keyboard_button_row *DS_K = DS_RM->rows->data[i];
- total += DS_LVAL (DS_K->buttons->cnt);
- R->row_start[i + 1] = total;
- }
- R->buttons = talloc (sizeof (void *) * total);
- int r = 0;
- for (i = 0; i < R->rows; i++) {
- struct tl_ds_keyboard_button_row *DS_K = DS_RM->rows->data[i];
- int j;
- for (j = 0; j < DS_LVAL (DS_K->buttons->cnt); j++) {
- struct tl_ds_keyboard_button *DS_KB = DS_K->buttons->data[j];
- R->buttons[r ++] = DS_STR_DUP (DS_KB->text);
- }
- }
- assert (r == total);
- return R;
-}
-/* }}} */
-
-void tglp_insert_encrypted_chat (struct tgl_state *TLS, tgl_peer_t *P) {
- TLS->encr_chats_allocated ++;
- TLS->peer_tree = tree_insert_peer (TLS->peer_tree, P, lrand48 ());
- increase_peer_size (TLS);
- TLS->Peers[TLS->peer_num ++] = P;
-}
-
-void tglp_insert_user (struct tgl_state *TLS, tgl_peer_t *P) {
- TLS->users_allocated ++;
- TLS->peer_tree = tree_insert_peer (TLS->peer_tree, P, lrand48 ());
- increase_peer_size (TLS);
- TLS->Peers[TLS->peer_num ++] = P;
-}
-
-void tglp_insert_chat (struct tgl_state *TLS, tgl_peer_t *P) {
- TLS->chats_allocated ++;
- TLS->peer_tree = tree_insert_peer (TLS->peer_tree, P, lrand48 ());
- increase_peer_size (TLS);
- TLS->Peers[TLS->peer_num ++] = P;
-}
-
-void tgl_insert_empty_user (struct tgl_state *TLS, int uid) {
- tgl_peer_id_t id = TGL_MK_USER (uid);
- if (tgl_peer_get (TLS, id)) { return; }
- tgl_peer_t *P = talloc0 (sizeof (*P));
- P->id = id;
- tglp_insert_user (TLS, P);
-}
-
-void tgl_insert_empty_chat (struct tgl_state *TLS, int cid) {
- tgl_peer_id_t id = TGL_MK_CHAT (cid);
- if (tgl_peer_get (TLS, id)) { return; }
- tgl_peer_t *P = talloc0 (sizeof (*P));
- P->id = id;
- tglp_insert_chat (TLS, P);
-}
-
-/* {{{ Free */
-
-void tgls_free_photo_size (struct tgl_state *TLS, struct tgl_photo_size *S) {
- tfree_str (S->type);
- if (S->data) {
- tfree (S->data, S->size);
- }
-}
-
-void tgls_free_photo (struct tgl_state *TLS, struct tgl_photo *P) {
- if (--P->refcnt) {
- assert (P->refcnt > 0);
- return;
- }
- if (P->caption) { tfree_str (P->caption); }
- if (P->sizes) {
- int i;
- for (i = 0; i < P->sizes_num; i++) {
- tgls_free_photo_size (TLS, &P->sizes[i]);
- }
- tfree (P->sizes, sizeof (struct tgl_photo_size) * P->sizes_num);
- }
- TLS->photo_tree = tree_delete_photo (TLS->photo_tree, P);
- tfree (P, sizeof (*P));
-}
-
-void tgls_free_document (struct tgl_state *TLS, struct tgl_document *D) {
- if (--D->refcnt) {
- assert (D->refcnt);
- return;
- }
- if (D->mime_type) { tfree_str (D->mime_type);}
- if (D->caption) {tfree_str (D->caption);}
- tgls_free_photo_size (TLS, &D->thumb);
-
- TLS->document_tree = tree_delete_document (TLS->document_tree, D);
- tfree (D, sizeof (*D));
-}
-
-void tgls_free_webpage (struct tgl_state *TLS, struct tgl_webpage *W) {
- if (--W->refcnt) {
- assert (W->refcnt);
- return;
- }
- if (W->url) { tfree_str (W->url); }
- if (W->display_url) { tfree_str (W->display_url); }
- if (W->title) { tfree_str (W->title); }
- if (W->site_name) { tfree_str (W->site_name); }
- if (W->type) { tfree_str (W->type); }
- if (W->description) { tfree_str (W->description); }
- if (W->photo) { tgls_free_photo (TLS, W->photo); }
- if (W->embed_url) { tfree_str (W->embed_url); }
- if (W->embed_type) { tfree_str (W->embed_type); }
- if (W->author) { tfree_str (W->author); }
-
- TLS->webpage_tree = tree_delete_webpage (TLS->webpage_tree, W);
- tfree (W, sizeof (*W));
-}
-
-void tgls_free_message_media (struct tgl_state *TLS, struct tgl_message_media *M) {
- switch (M->type) {
- case tgl_message_media_none:
- case tgl_message_media_geo:
- return;
- case tgl_message_media_photo:
- tgls_free_photo (TLS, M->photo);
- M->photo = NULL;
- return;
- case tgl_message_media_contact:
- tfree_str (M->phone);
- tfree_str (M->first_name);
- tfree_str (M->last_name);
- return;
- case tgl_message_media_document:
- case tgl_message_media_video:
- case tgl_message_media_audio:
- tgls_free_document (TLS, M->document);
- return;
- case tgl_message_media_unsupported:
- tfree (M->data, M->data_size);
- return;
- case tgl_message_media_document_encr:
- tfree_secure (M->encr_document->key, 32);
- tfree_secure (M->encr_document->iv, 32);
- tfree (M->encr_document, sizeof (*M->encr_document));
- return;
- case tgl_message_media_webpage:
- tgls_free_webpage (TLS, M->webpage);
- return;
- case tgl_message_media_venue:
- if (M->venue.title) { tfree_str (M->venue.title); }
- if (M->venue.address) { tfree_str (M->venue.address); }
- if (M->venue.provider) { tfree_str (M->venue.provider); }
- if (M->venue.venue_id) { tfree_str (M->venue.venue_id); }
- return;
- default:
- vlogprintf (E_ERROR, "type = 0x%08x\n", M->type);
- assert (0);
- }
-}
-
-void tgls_free_message_action (struct tgl_state *TLS, struct tgl_message_action *M) {
- switch (M->type) {
- case tgl_message_action_none:
- return;
- case tgl_message_action_chat_create:
- tfree_str (M->title);
- tfree (M->users, M->user_num * 4);
- return;
- case tgl_message_action_chat_edit_title:
- tfree_str (M->new_title);
- return;
- case tgl_message_action_chat_edit_photo:
- tgls_free_photo (TLS, M->photo);
- M->photo = NULL;
- return;
- case tgl_message_action_chat_delete_photo:
- case tgl_message_action_chat_add_user:
- case tgl_message_action_chat_add_user_by_link:
- case tgl_message_action_chat_delete_user:
- case tgl_message_action_geo_chat_create:
- case tgl_message_action_geo_chat_checkin:
- case tgl_message_action_set_message_ttl:
- case tgl_message_action_read_messages:
- case tgl_message_action_delete_messages:
- case tgl_message_action_screenshot_messages:
- case tgl_message_action_flush_history:
- case tgl_message_action_typing:
- case tgl_message_action_resend:
- case tgl_message_action_notify_layer:
- case tgl_message_action_commit_key:
- case tgl_message_action_abort_key:
- case tgl_message_action_noop:
- return;
- case tgl_message_action_request_key:
- case tgl_message_action_accept_key:
- tfree (M->g_a, 256);
- return;
-/* default:
- vlogprintf (E_ERROR, "type = 0x%08x\n", M->type);
- assert (0);*/
- }
- vlogprintf (E_ERROR, "type = 0x%08x\n", M->type);
- assert (0);
-}
-
-void tgls_clear_message (struct tgl_state *TLS, struct tgl_message *M) {
- if (!(M->flags & TGLMF_SERVICE)) {
- if (M->message) { tfree (M->message, M->message_len + 1); }
- tgls_free_message_media (TLS, &M->media);
- } else {
- tgls_free_message_action (TLS, &M->action);
- }
-}
-
-void tgls_free_reply_markup (struct tgl_state *TLS, struct tgl_message_reply_markup *R) {
- if (!--R->refcnt) {
- tfree (R->buttons, R->row_start[R->rows] * sizeof (void *));
- tfree (R->row_start, 4 * (R->rows + 1));
- tfree (R, sizeof (*R));
- } else {
- assert (R->refcnt > 0);
- }
-}
-
-void tgls_free_message (struct tgl_state *TLS, struct tgl_message *M) {
- tgls_clear_message (TLS, M);
- if (M->reply_markup) {
- tgls_free_reply_markup (TLS, M->reply_markup);
- }
- tfree (M, sizeof (*M));
-}
-
-void tgls_free_chat (struct tgl_state *TLS, struct tgl_chat *U) {
- if (U->title) { tfree_str (U->title); }
- if (U->print_title) { tfree_str (U->print_title); }
- if (U->user_list) {
- tfree (U->user_list, U->user_list_size * 12);
- }
- if (U->photo) { tgls_free_photo (TLS, U->photo); }
- tfree (U, sizeof (*U));
-}
-
-void tgls_free_user (struct tgl_state *TLS, struct tgl_user *U) {
- if (U->first_name) { tfree_str (U->first_name); }
- if (U->last_name) { tfree_str (U->last_name); }
- if (U->print_name) { tfree_str (U->print_name); }
- if (U->phone) { tfree_str (U->phone); }
- if (U->real_first_name) { tfree_str (U->real_first_name); }
- if (U->real_last_name) { tfree_str (U->real_last_name); }
- if (U->status.ev) { tgl_remove_status_expire (TLS, U); }
- if (U->photo) { tgls_free_photo (TLS, U->photo); }
- tfree (U, sizeof (*U));
-}
-
-void tgls_free_encr_chat (struct tgl_state *TLS, struct tgl_secret_chat *U) {
- if (U->print_name) { tfree_str (U->print_name); }
- if (U->g_key) { tfree (U->g_key, 256); }
- tfree (U, sizeof (*U));
-}
-
-void tgls_free_peer (struct tgl_state *TLS, tgl_peer_t *P) {
- if (tgl_get_peer_type (P->id) == TGL_PEER_USER) {
- tgls_free_user (TLS, (void *)P);
- } else if (tgl_get_peer_type (P->id) == TGL_PEER_CHAT) {
- tgls_free_chat (TLS, (void *)P);
- } else if (tgl_get_peer_type (P->id) == TGL_PEER_ENCR_CHAT) {
- tgls_free_encr_chat (TLS, (void *)P);
- } else {
- assert (0);
- }
-}
-
-void tgls_free_bot_info (struct tgl_state *TLS, struct tgl_bot_info *B) {
- if (!B) { return; }
- int i;
- for (i = 0; i < B->commands_num; i++) {
- tfree_str (B->commands[i].command);
- tfree_str (B->commands[i].description);
- }
- tfree (B->commands, sizeof (struct tgl_bot_command) * B->commands_num);
- tfree_str (B->share_text);
- tfree_str (B->description);
- tfree (B, sizeof (*B));
-}
-/* }}} */
-
-/* Messages {{{ */
-
-void tglm_message_del_use (struct tgl_state *TLS, struct tgl_message *M) {
- M->next_use->prev_use = M->prev_use;
- M->prev_use->next_use = M->next_use;
-}
-
-void tglm_message_add_use (struct tgl_state *TLS, struct tgl_message *M) {
- M->next_use = TLS->message_list.next_use;
- M->prev_use = &TLS->message_list;
- M->next_use->prev_use = M;
- M->prev_use->next_use = M;
-}
-
-void tglm_message_add_peer (struct tgl_state *TLS, struct tgl_message *M) {
- tgl_peer_id_t id;
- if (!tgl_cmp_peer_id (M->to_id, TGL_MK_USER (TLS->our_id))) {
- id = M->from_id;
- } else {
- id = M->to_id;
- }
- tgl_peer_t *P = tgl_peer_get (TLS, id);
- if (!P) {
- P = talloc0 (sizeof (*P));
- P->id = id;
- switch (tgl_get_peer_type (id)) {
- case TGL_PEER_USER:
- TLS->users_allocated ++;
- break;
- case TGL_PEER_CHAT:
- TLS->chats_allocated ++;
- break;
- case TGL_PEER_GEO_CHAT:
- TLS->geo_chats_allocated ++;
- break;
- case TGL_PEER_ENCR_CHAT:
- TLS->encr_chats_allocated ++;
- break;
- }
- TLS->peer_tree = tree_insert_peer (TLS->peer_tree, P, lrand48 ());
- increase_peer_size (TLS);
- TLS->Peers[TLS->peer_num ++] = P;
- }
- if (!P->last) {
- P->last = M;
- M->prev = M->next = 0;
- } else {
- if (tgl_get_peer_type (P->id) != TGL_PEER_ENCR_CHAT) {
- struct tgl_message *N = P->last;
- struct tgl_message *NP = 0;
- while (N && N->id > M->id) {
- NP = N;
- N = N->next;
- }
- if (N) {
- assert (N->id < M->id);
- }
- M->next = N;
- M->prev = NP;
- if (N) { N->prev = M; }
- if (NP) { NP->next = M; }
- else { P->last = M; }
- } else {
- struct tgl_message *N = P->last;
- struct tgl_message *NP = 0;
- M->next = N;
- M->prev = NP;
- if (N) { N->prev = M; }
- if (NP) { NP->next = M; }
- else { P->last = M; }
- }
- }
-}
-
-void tglm_message_del_peer (struct tgl_state *TLS, struct tgl_message *M) {
- tgl_peer_id_t id;
- if (!tgl_cmp_peer_id (M->to_id, TGL_MK_USER (TLS->our_id))) {
- id = M->from_id;
- } else {
- id = M->to_id;
- }
- tgl_peer_t *P = tgl_peer_get (TLS, id);
- if (M->prev) {
- M->prev->next = M->next;
- }
- if (M->next) {
- M->next->prev = M->prev;
- }
- if (P && P->last == M) {
- P->last = M->next;
- }
-}
-
-struct tgl_message *tglm_message_alloc (struct tgl_state *TLS, long long id) {
- struct tgl_message *M = talloc0 (sizeof (*M));
- M->id = id;
- tglm_message_insert_tree (TLS, M);
- TLS->messages_allocated ++;
- return M;
-}
-
-void tglm_message_insert_tree (struct tgl_state *TLS, struct tgl_message *M) {
- assert (M->id);
- TLS->message_tree = tree_insert_message (TLS->message_tree, M, lrand48 ());
-}
-
-void tglm_message_remove_tree (struct tgl_state *TLS, struct tgl_message *M) {
- assert (M->id);
- TLS->message_tree = tree_delete_message (TLS->message_tree, M);
-}
-
-void tglm_message_insert (struct tgl_state *TLS, struct tgl_message *M) {
- tglm_message_add_use (TLS, M);
- tglm_message_add_peer (TLS, M);
-}
-
-void tglm_message_insert_unsent (struct tgl_state *TLS, struct tgl_message *M) {
- TLS->message_unsent_tree = tree_insert_message (TLS->message_unsent_tree, M, lrand48 ());
-}
-
-void tglm_message_remove_unsent (struct tgl_state *TLS, struct tgl_message *M) {
- TLS->message_unsent_tree = tree_delete_message (TLS->message_unsent_tree, M);
-}
-
-static void __send_msg (struct tgl_message *M, void *_TLS) {
- struct tgl_state *TLS = _TLS;
- vlogprintf (E_NOTICE, "Resending message...\n");
- //print_message (M);
-
- if (M->media.type != tgl_message_media_none) {
- assert (M->flags & TGLMF_ENCRYPTED);
- bl_do_message_delete (TLS, M);
- } else {
- tgl_do_send_msg (TLS, M, 0, 0);
- }
-}
-
-void tglm_send_all_unsent (struct tgl_state *TLS) {
- tree_act_ex_message (TLS->message_unsent_tree, __send_msg, TLS);
-}
-/* }}} */
-
-struct tgl_photo *tgl_photo_get (struct tgl_state *TLS, long long id) {
- struct tgl_photo P;
- P.id = id;
- return tree_lookup_photo (TLS->photo_tree, &P);
-}
-
-void tgl_photo_insert (struct tgl_state *TLS, struct tgl_photo *P) {
- TLS->photo_tree = tree_insert_photo (TLS->photo_tree, P, lrand48 ());
-}
-
-struct tgl_document *tgl_document_get (struct tgl_state *TLS, long long id) {
- struct tgl_document P;
- P.id = id;
- return tree_lookup_document (TLS->document_tree, &P);
-}
-
-void tgl_document_insert (struct tgl_state *TLS, struct tgl_document *P) {
- TLS->document_tree = tree_insert_document (TLS->document_tree, P, lrand48 ());
-}
-
-struct tgl_webpage *tgl_webpage_get (struct tgl_state *TLS, long long id) {
- struct tgl_webpage P;
- P.id = id;
- return tree_lookup_webpage (TLS->webpage_tree, &P);
-}
-
-void tgl_webpage_insert (struct tgl_state *TLS, struct tgl_webpage *P) {
- TLS->webpage_tree = tree_insert_webpage (TLS->webpage_tree, P, lrand48 ());
-}
-
-void tglp_peer_insert_name (struct tgl_state *TLS, tgl_peer_t *P) {
- TLS->peer_by_name_tree = tree_insert_peer_by_name (TLS->peer_by_name_tree, P, lrand48 ());
-}
-
-void tglp_peer_delete_name (struct tgl_state *TLS, tgl_peer_t *P) {
- TLS->peer_by_name_tree = tree_delete_peer_by_name (TLS->peer_by_name_tree, P);
-}
-
-tgl_peer_t *tgl_peer_get (struct tgl_state *TLS, tgl_peer_id_t id) {
- static tgl_peer_t U;
- U.id = id;
- return tree_lookup_peer (TLS->peer_tree, &U);
-}
-
-struct tgl_message *tgl_message_get (struct tgl_state *TLS, long long id) {
- struct tgl_message M;
- M.id = id;
- return tree_lookup_message (TLS->message_tree, &M);
-}
-
-tgl_peer_t *tgl_peer_get_by_name (struct tgl_state *TLS, const char *s) {
- static tgl_peer_t P;
- P.print_name = (void *)s;
- tgl_peer_t *R = tree_lookup_peer_by_name (TLS->peer_by_name_tree, &P);
- return R;
-}
-
-void tgl_peer_iterator_ex (struct tgl_state *TLS, void (*it)(tgl_peer_t *P, void *extra), void *extra) {
- tree_act_ex_peer (TLS->peer_tree, it, extra);
-}
-
-int tgl_complete_user_list (struct tgl_state *TLS, int index, const char *text, int len, char **R) {
- index ++;
- while (index < TLS->peer_num && (!TLS->Peers[index]->print_name || strncmp (TLS->Peers[index]->print_name, text, len) || tgl_get_peer_type (TLS->Peers[index]->id) != TGL_PEER_USER)) {
- index ++;
- }
- if (index < TLS->peer_num) {
- *R = strdup (TLS->Peers[index]->print_name);
- assert (*R);
- return index;
- } else {
- return -1;
- }
-}
-
-int tgl_complete_chat_list (struct tgl_state *TLS, int index, const char *text, int len, char **R) {
- index ++;
- while (index < TLS->peer_num && (!TLS->Peers[index]->print_name || strncmp (TLS->Peers[index]->print_name, text, len) || tgl_get_peer_type (TLS->Peers[index]->id) != TGL_PEER_CHAT)) {
- index ++;
- }
- if (index < TLS->peer_num) {
- *R = strdup (TLS->Peers[index]->print_name);
- assert (*R);
- return index;
- } else {
- return -1;
- }
-}
-
-int tgl_complete_encr_chat_list (struct tgl_state *TLS, int index, const char *text, int len, char **R) {
- index ++;
- while (index < TLS->peer_num && (!TLS->Peers[index]->print_name || strncmp (TLS->Peers[index]->print_name, text, len) || tgl_get_peer_type (TLS->Peers[index]->id) != TGL_PEER_ENCR_CHAT)) {
- index ++;
- }
- if (index < TLS->peer_num) {
- *R = strdup (TLS->Peers[index]->print_name);
- assert (*R);
- return index;
- } else {
- return -1;
- }
-}
-
-int tgl_complete_peer_list (struct tgl_state *TLS, int index, const char *text, int len, char **R) {
- index ++;
- while (index < TLS->peer_num && (!TLS->Peers[index]->print_name || strncmp (TLS->Peers[index]->print_name, text, len))) {
- index ++;
- }
- if (index < TLS->peer_num) {
- *R = strdup (TLS->Peers[index]->print_name);
- assert (*R);
- return index;
- } else {
- return -1;
- }
-}
-
-int tgl_secret_chat_for_user (struct tgl_state *TLS, tgl_peer_id_t user_id) {
- int index = 0;
- while (index < TLS->peer_num && (tgl_get_peer_type (TLS->Peers[index]->id) != TGL_PEER_ENCR_CHAT || TLS->Peers[index]->encr_chat.user_id != tgl_get_peer_id (user_id) || TLS->Peers[index]->encr_chat.state != sc_ok)) {
- index ++;
- }
- if (index < TLS->peer_num) {
- return tgl_get_peer_id (TLS->Peers[index]->encr_chat.id);
- } else {
- return -1;
- }
-}
-
-void tgls_free_peer_gw (tgl_peer_t *P, void *TLS) {
- tgls_free_peer (TLS, P);
-}
-
-void tgls_free_message_gw (struct tgl_message *M, void *TLS) {
- tgls_free_message (TLS, M);
-}
-
-void tgl_free_all (struct tgl_state *TLS) {
- tree_act_ex_peer (TLS->peer_tree, tgls_free_peer_gw, TLS);
- TLS->peer_tree = tree_clear_peer (TLS->peer_tree);
- TLS->peer_by_name_tree = tree_clear_peer_by_name (TLS->peer_by_name_tree);
- tree_act_ex_message (TLS->message_tree, tgls_free_message_gw, TLS);
- TLS->message_tree = tree_clear_message (TLS->message_tree);
- tree_act_ex_message (TLS->message_unsent_tree, tgls_free_message_gw, TLS);
- TLS->message_unsent_tree = tree_clear_message (TLS->message_unsent_tree);
- tglq_query_free_all (TLS);
-
- if (TLS->encr_prime) { tfree (TLS->encr_prime, 256); }
-
-
- if (TLS->binlog_name) { tfree_str (TLS->binlog_name); }
- if (TLS->auth_file) { tfree_str (TLS->auth_file); }
- if (TLS->downloads_directory) { tfree_str (TLS->downloads_directory); }
-
- int i;
- for (i = 0; i < TLS->rsa_key_num; i++) {
- tfree_str (TLS->rsa_key_list[i]);
- }
-
- for (i = 0; i <= TLS->max_dc_num; i++) if (TLS->DC_list[i]) {
- tgls_free_dc (TLS, TLS->DC_list[i]);
- }
- BN_CTX_free (TLS->BN_ctx);
- tgls_free_pubkey (TLS);
-
- if (TLS->ev_login) { TLS->timer_methods->free (TLS->ev_login); }
- if (TLS->online_updates_timer) { TLS->timer_methods->free (TLS->online_updates_timer); }
-}
-
-int tgl_print_stat (struct tgl_state *TLS, char *s, int len) {
- return tsnprintf (s, len,
- "users_allocated\t%d\n"
- "chats_allocated\t%d\n"
- "encr_chats_allocated\t%d\n"
- "peer_num\t%d\n"
- "messages_allocated\t%d\n",
- TLS->users_allocated,
- TLS->chats_allocated,
- TLS->encr_chats_allocated,
- TLS->peer_num,
- TLS->messages_allocated
- );
-}
-
-void tglf_fetch_int_array (int *dst, struct tl_ds_vector *src, int len) {
- int i;
- assert (len <= *src->f1);
- for (i = 0; i < len; i++) {
- dst[i] = *(int *)src->f2[i];
- }
-}
-
-void tglf_fetch_int_tuple (int *dst, int **src, int len) {
- int i;
- for (i = 0; i < len; i++) {
- dst[i] = *src[i];
- }
-}
-
-
-void tgls_messages_mark_read (struct tgl_state *TLS, struct tgl_message *M, int out, int seq) {
- while (M && M->id > seq) {
- if ((M->flags & TGLMF_OUT) == out) {
- if (!(M->flags & TGLMF_UNREAD)) {
- return;
- }
- }
- M = M->next;
- }
- while (M) {
- if ((M->flags & TGLMF_OUT) == out) {
- if (M->flags & TGLMF_UNREAD) {
- M->flags &= ~TGLMF_UNREAD;
- TLS->callback.marked_read (TLS, 1, &M);
- } else {
- return;
- }
- }
- M = M->next;
- }
-}
-
-void tgls_insert_random2local (struct tgl_state *TLS, long long random_id, int local_id) {
- struct random2local *X = talloc (sizeof (*X));
- X->random_id = random_id;
- X->local_id = local_id;
-
- struct random2local *R = tree_lookup_random_id (TLS->random_id_tree, X);
- assert (!R);
-
- TLS->random_id_tree = tree_insert_random_id (TLS->random_id_tree, X, lrand48 ());
-}
-
-int tgls_get_local_by_random (struct tgl_state *TLS, long long random_id) {
- struct random2local X;
- X.random_id = random_id;
- struct random2local *Y = tree_lookup_random_id (TLS->random_id_tree, &X);
- if (Y) {
- TLS->random_id_tree = tree_delete_random_id (TLS->random_id_tree, Y);
- int y = Y->local_id;
- tfree (Y, sizeof (*Y));
- return y;
- } else {
- return 0;
- }
-}