diff options
Diffstat (limited to 'protocols/Telegram/tgl/structures.c')
-rw-r--r-- | protocols/Telegram/tgl/structures.c | 2311 |
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; - } -} |