struct tgp_msg_loading *tgp_msg_loading_init (struct tgl_message *M) { struct tgp_msg_loading *C = talloc0 (sizeof (struct tgp_msg_loading)); C->pending = 0; C->msg = M; C->data = NULL; return C; }
void read_secret_chat_file (void) { if (binlog_enabled) { return; } int fd = open (get_secret_chat_filename (), O_CREAT | O_RDWR, 0600); if (fd < 0) { return; } int x[2]; if (read (fd, x, 8) < 8) { close (fd); return; } if (x[0] != (int)SECRET_CHAT_FILE_MAGIC) { close (fd); return; } int version = x[1]; assert (version >= 0); int cc; assert (read (fd, &cc, 4) == 4); int i; for (i = 0; i < cc; i++) { peer_t *P = talloc0 (sizeof (*P)); struct secret_chat *E = &P->encr_chat; int t; assert (read (fd, &t, 4) == 4); P->id = MK_ENCR_CHAT (t); assert (read (fd, &P->flags, 4) == 4); assert (read (fd, &t, 4) == 4); assert (t > 0); P->print_name = talloc (t + 1); assert (read (fd, P->print_name, t) == t); P->print_name[t] = 0; peer_insert_name (P); assert (read (fd, &E->state, 4) == 4); assert (read (fd, &E->user_id, 4) == 4); assert (read (fd, &E->admin_id, 4) == 4); assert (read (fd, &E->ttl, 4) == 4); assert (read (fd, &E->access_hash, 8) == 8); if (E->state != sc_waiting) { E->g_key = talloc (256); assert (read (fd, E->g_key, 256) == 256); E->nonce = talloc (256); assert (read (fd, E->nonce, 256) == 256); } assert (read (fd, E->key, 256) == 256); assert (read (fd, &E->key_fingerprint, 8) == 8); insert_encrypted_chat (P); } if (version >= 1) { assert (read (fd, &encr_root, 4) == 4); if (encr_root) { assert (read (fd, &encr_param_version, 4) == 4); encr_prime = talloc (256); assert (read (fd, encr_prime, 256) == 256); } } close (fd); }
void bl_do_channel (struct tgl_state *TLS, int id, long long *access_hash, int *date, const char *title, int title_len, const char *username, int username_len, struct tl_ds_chat_photo *chat_photo, struct tl_ds_photo *photo, int *version, char *about, int about_len, int *participants_count, int *admins_count, int *kicked_count, int *last_read_in, int flags) /* {{{ */ { tgl_peer_t *_U = tgl_peer_get (TLS, TGL_MK_CHANNEL (id)); unsigned updates = 0; if ((flags & TGLPF_CREATE) && (flags != TGL_FLAGS_UNCHANGED)) { if (!_U) { _U = talloc0 (sizeof (*_U)); _U->id = TGL_MK_CHANNEL (id); tglp_insert_channel (TLS, _U); } else { assert (!(_U->flags & TGLPF_CREATED)); } updates |= TGL_UPDATE_CREATED; } else { assert (_U->flags & TGLPF_CREATED); } struct tgl_channel *C = &_U->channel; if (flags == TGL_FLAGS_UNCHANGED) { flags = C->flags; } flags &= TGLCHF_TYPE_MASK; if ((flags & TGLCHF_TYPE_MASK) != (C->flags & TGLCHF_TYPE_MASK)) { updates |= TGL_UPDATE_FLAGS; } C->flags = (C->flags & ~TGLCHF_TYPE_MASK) | flags; if (access_hash && *access_hash != C->access_hash) { C->access_hash = *access_hash; C->id.access_hash = *access_hash; updates |= TGL_UPDATE_ACCESS_HASH; } if (date) { C->date = *date; } if (title && (!C->title || mystreq1 (C->title, title, title_len))) { if (C->title) { tfree_str (C->title); } C->title = tstrndup (title, title_len); if (C->print_title) { tglp_peer_delete_name (TLS, (void *)C); tfree_str (C->print_title); } C->print_title = TLS->callback.create_print_name (TLS, C->id, C->title, 0, 0, 0); tglp_peer_insert_name (TLS, (void *)C); updates |= TGL_UPDATE_TITLE; } if (chat_photo) { if (chat_photo->photo_big && DS_LVAL (chat_photo->photo_big->secret) != C->photo_big.secret) { tglf_fetch_file_location (TLS, &C->photo_big, chat_photo->photo_big); tglf_fetch_file_location (TLS, &C->photo_small, chat_photo->photo_small); updates |= TGL_UPDATE_PHOTO; } } if (photo) { if (!C->photo || C->photo->id != DS_LVAL (photo->id)) { if (C->photo) { tgls_free_photo (TLS, C->photo); } C->photo = tglf_fetch_alloc_photo (TLS, photo); C->flags |= TGLPF_HAS_PHOTO; } } if (username) { if (!C->username || mystreq1 (C->username, username, username_len)) { if (C->username) { tfree_str (C->username); } C->username = tstrndup (username, username_len); updates |= TGL_UPDATE_USERNAME; } } if (about) { if (!C->about || mystreq1 (C->about, about, about_len)) { tfree_str (C->about); } C->about = tstrndup (about, about_len); } if (admins_count) { C->admins_count = *admins_count; } if (participants_count) { C->participants_count = *participants_count; } if (kicked_count) { C->kicked_count = *kicked_count; } if (last_read_in) { C->last_read_in = *last_read_in; tgls_messages_mark_read (TLS, C->last, 0, C->last_read_in); } if (TLS->callback.channel_update && updates) { TLS->callback.channel_update (TLS, C, updates); } }
void bl_do_encr_chat (struct tgl_state *TLS, int id, long long *access_hash, int *date, int *admin, int *user_id, void *key, void *g_key, void *first_key_id, int *state, int *ttl, int *layer, int *in_seq_no, int *last_in_seq_no, int *out_seq_no, long long *key_fingerprint, int flags, const char *print_name, int print_name_len) /* {{{ */ { tgl_peer_t *_U = tgl_peer_get (TLS, TGL_MK_ENCR_CHAT (id)); unsigned updates = 0; if ((flags & TGLPF_CREATE) && (flags != TGL_FLAGS_UNCHANGED)) { if (!_U) { _U = talloc0 (sizeof (*_U)); _U->id = TGL_MK_ENCR_CHAT (id); tglp_insert_encrypted_chat (TLS, _U); } else { assert (!(_U->flags & TGLPF_CREATED)); } updates |= TGL_UPDATE_CREATED; } else { assert (_U->flags & TGLPF_CREATED); } struct tgl_secret_chat *U = (void *)_U; if (flags == TGL_FLAGS_UNCHANGED) { flags = U->flags; } flags &= TGLECF_TYPE_MASK; if ((flags & TGLECF_TYPE_MASK) != (U->flags & TGLECF_TYPE_MASK)) { updates |= TGL_UPDATE_FLAGS; } U->flags = (U->flags & ~TGLECF_TYPE_MASK) | flags; if (access_hash && *access_hash != U->access_hash) { U->access_hash = *access_hash; U->id.access_hash = *access_hash; updates |= TGL_UPDATE_ACCESS_HASH; } if (date) { U->date = *date; } if (admin) { U->admin_id = *admin; } if (user_id) { U->user_id = *user_id; } if (key_fingerprint) { U->key_fingerprint = *key_fingerprint; } if (in_seq_no) { U->in_seq_no = *in_seq_no; } if (out_seq_no) { U->out_seq_no = *out_seq_no; } if (last_in_seq_no) { U->last_in_seq_no = *last_in_seq_no; } tgl_peer_t *Us = tgl_peer_get (TLS, TGL_MK_USER (U->user_id)); if (!U->print_name) { if (print_name) { U->print_name = tstrndup (print_name, print_name_len); } else { if (Us) { U->print_name = TLS->callback.create_print_name (TLS, TGL_MK_ENCR_CHAT (id), "!", Us->user.first_name, Us->user.last_name, 0); } else { static char buf[100]; tsnprintf (buf, 99, "user#%d", U->user_id); U->print_name = TLS->callback.create_print_name (TLS, TGL_MK_ENCR_CHAT (id), "!", buf, 0, 0); } tglp_peer_insert_name (TLS, (void *)U); } } if (g_key) { if (!U->g_key) { U->g_key = talloc (256); } memcpy (U->g_key, g_key, 256); } if (key) { memcpy (U->key, key, 256); } if (first_key_id) { memcpy (U->first_key_sha, first_key_id, 20); } if (state) { if (U->state == sc_waiting && *state == sc_ok) { tgl_do_create_keys_end (TLS, U); } if ((int)U->state != *state) { switch (*state) { case sc_request: updates |= TGL_UPDATE_REQUESTED; break; case sc_ok: updates |= TGL_UPDATE_WORKING; vlogprintf (E_WARNING, "Secret chat in ok state\n"); break; default: break; } } U->state = *state; } if (TLS->callback.secret_chat_update && updates) { TLS->callback.secret_chat_update (TLS, U, updates); } }
void bl_do_chat (struct tgl_state *TLS, int id, const char *title, int title_len, int *user_num, int *date, int *version, struct tl_ds_vector *participants, struct tl_ds_chat_photo *chat_photo, struct tl_ds_photo *photo, int *admin, int *last_read_in, int *last_read_out, int flags) /* {{{ */ { tgl_peer_t *_U = tgl_peer_get (TLS, TGL_MK_CHAT (id)); unsigned updates = 0; if ((flags & TGLPF_CREATE) && (flags != TGL_FLAGS_UNCHANGED)) { if (!_U) { _U = talloc0 (sizeof (*_U)); _U->id = TGL_MK_CHAT (id); tglp_insert_chat (TLS, _U); } else { assert (!(_U->flags & TGLPF_CREATED)); } updates |= TGL_UPDATE_CREATED; } else { assert (_U->flags & TGLPF_CREATED); } struct tgl_chat *C = &_U->chat; if (flags == TGL_FLAGS_UNCHANGED) { flags = C->flags; } flags &= TGLCF_TYPE_MASK; if ((flags & TGLCF_TYPE_MASK) != (C->flags & TGLCF_TYPE_MASK)) { updates |= TGL_UPDATE_FLAGS; } C->flags = (C->flags & ~TGLCF_TYPE_MASK) | flags; if (title && (!C->title || mystreq1 (C->title, title, title_len))) { if (C->title) { tfree_str (C->title); } C->title = tstrndup (title, title_len); if (C->print_title) { tglp_peer_delete_name (TLS, (void *)C); tfree_str (C->print_title); } C->print_title = TLS->callback.create_print_name (TLS, C->id, C->title, 0, 0, 0); tglp_peer_insert_name (TLS, (void *)C); updates |= TGL_UPDATE_TITLE; } if (user_num) { C->users_num = *user_num; } if (date) { C->date = *date; } if (chat_photo && chat_photo->photo_big) { if (DS_LVAL (chat_photo->photo_big->secret) != C->photo_big.secret) { tglf_fetch_file_location (TLS, &C->photo_big, chat_photo->photo_big); tglf_fetch_file_location (TLS, &C->photo_small, chat_photo->photo_small); updates |= TGL_UPDATE_PHOTO; } } if (photo) { if (!C->photo || C->photo->id != DS_LVAL (photo->id)) { if (C->photo) { tgls_free_photo (TLS, C->photo); } C->photo = tglf_fetch_alloc_photo (TLS, photo); C->flags |= TGLPF_HAS_PHOTO; //updates |= TGL_UPDATE_PHOTO; } } if (admin && *admin != C->admin_id) { C->admin_id = *admin; updates |= TGL_UPDATE_ADMIN; } if (version) { assert (participants); if (*version > C->version) { C->version = *version; if (C->user_list) { tfree (C->user_list, 12 * C->user_list_size); } C->user_list_size = DS_LVAL (participants->f1); C->user_list = talloc (12 * C->user_list_size); int i; for (i = 0; i < C->user_list_size; i++) { struct tl_ds_chat_participant *DS_P = participants->f2[i]; C->user_list[i].user_id = DS_LVAL (DS_P->user_id); C->user_list[i].inviter_id = DS_LVAL (DS_P->inviter_id); C->user_list[i].date = DS_LVAL (DS_P->date); } updates |= TGL_UPDATE_MEMBERS; } } if (last_read_in) { C->last_read_in = *last_read_in; tgls_messages_mark_read (TLS, C->last, 0, C->last_read_in); } if (last_read_out) { C->last_read_out = *last_read_out; tgls_messages_mark_read (TLS, C->last, TGLMF_OUT, C->last_read_out); } if (TLS->callback.chat_update && updates) { TLS->callback.chat_update (TLS, C, updates); } }
void bl_do_user (struct tgl_state *TLS, int id, long long *access_hash, const char *first_name, int first_name_len, const char *last_name, int last_name_len, const char *phone, int phone_len, const char *username, int username_len, struct tl_ds_photo *photo, struct tl_ds_user_profile_photo *profile_photo, int *last_read_in, int *last_read_out, struct tl_ds_bot_info *bot_info, int flags) /* {{{ */ { tgl_peer_t *_U = tgl_peer_get (TLS, TGL_MK_USER (id)); unsigned updates = 0; if ((flags & TGLPF_CREATE) && (flags != TGL_FLAGS_UNCHANGED)) { if (!_U) { _U = talloc0 (sizeof (*_U)); _U->id = TGL_MK_USER (id); tglp_insert_user (TLS, _U); } else { assert (!(_U->flags & TGLPF_CREATED)); } updates |= TGL_UPDATE_CREATED; } else { assert (_U->flags & TGLPF_CREATED); } struct tgl_user *U = (void *)_U; if (flags == TGL_FLAGS_UNCHANGED) { flags = U->flags; } flags &= TGLUF_TYPE_MASK; if ((flags & TGLUF_TYPE_MASK) != (U->flags & TGLUF_TYPE_MASK)) { updates |= TGL_UPDATE_FLAGS; } U->flags = (U->flags & ~TGLUF_TYPE_MASK) | flags; if (access_hash && *access_hash != U->access_hash) { U->access_hash = *access_hash; U->id.access_hash = *access_hash; updates |= TGL_UPDATE_ACCESS_HASH; } if (first_name || last_name) { if (!U->first_name || !U->last_name || mystreq1 (U->first_name, first_name, first_name_len) || mystreq1 (U->last_name, last_name, last_name_len)) { if (U->first_name) { tfree_str (U->first_name); } U->first_name = tstrndup (first_name, first_name_len); if (U->last_name) { tfree_str (U->last_name); } U->last_name = tstrndup (last_name, last_name_len); updates |= TGL_UPDATE_NAME; if (U->print_name) { tglp_peer_delete_name (TLS, (void *)U); tfree_str (U->print_name); } U->print_name = TLS->callback.create_print_name (TLS, U->id, U->first_name, U->last_name, 0, 0); tglp_peer_insert_name (TLS, (void *)U); } } if (phone && (!U->phone || mystreq1 (U->phone, phone, phone_len))) { if (U->phone) { tfree_str (U->phone); } U->phone = tstrndup (phone, phone_len); updates |= TGL_UPDATE_PHONE; } if (username && (!U->username || mystreq1 (U->username, username, username_len))) { if (U->username) { tfree_str (U->username); } U->username = tstrndup (username, username_len); updates |= TGL_UPDATE_USERNAME; } if (photo) { if (!U->photo || U->photo->id != DS_LVAL (photo->id)) { if (U->photo) { tgls_free_photo (TLS, U->photo); } U->photo = tglf_fetch_alloc_photo (TLS, photo); U->flags |= TGLUF_HAS_PHOTO; } } if (profile_photo) { if (U->photo_id != DS_LVAL (profile_photo->photo_id)) { U->photo_id = DS_LVAL (profile_photo->photo_id); tglf_fetch_file_location (TLS, &U->photo_big, profile_photo->photo_big); tglf_fetch_file_location (TLS, &U->photo_small, profile_photo->photo_small); updates |= TGL_UPDATE_PHOTO; } } if (last_read_in) { U->last_read_in = *last_read_in; tgls_messages_mark_read (TLS, U->last, 0, U->last_read_in); } if (last_read_out) { U->last_read_out = *last_read_out; tgls_messages_mark_read (TLS, U->last, TGLMF_OUT, U->last_read_out); } if (bot_info) { if (!U->bot_info || U->bot_info->version != DS_LVAL (bot_info->version)) { if (U->bot_info) { tgls_free_bot_info (TLS, U->bot_info); } U->bot_info = tglf_fetch_alloc_bot_info (TLS, bot_info); } } if (TLS->callback.user_update && updates) { TLS->callback.user_update (TLS, U, updates); } }