static int tgprpl_send_im (PurpleConnection * gc, const char *who, const char *message, PurpleMessageFlags flags) { debug ("tgprpl_send_im()\n"); telegram_conn *conn = purple_connection_get_protocol_data(gc); PurpleAccount *pa = conn->pa; // this is part of a workaround to support clients without // the request API (request.h), see telegram-base.c:request_code() if (conn->in_fallback_chat) { request_code_entered (conn->TLS, message); conn->in_fallback_chat = 0; return 1; } PurpleBuddy *b = purple_find_buddy (pa, who); if (!b) { warning ("Buddy %s not found, cannot send IM\n", who); return -1; } tgl_peer_t *peer = tgl_peer_get(conn->TLS, TGL_MK_USER(atoi (who))); if (!peer) { warning ("Protocol data tgl_peer_t for %s not found, cannot send IM\n", who); return -1; } gchar *raw = purple_unescape_html(message); tgl_do_send_message (conn->TLS, peer->id, raw, (int)strlen (raw), 0, 0); g_free(raw); return 1; }
void net_loop (void) { delete_stdin_event = 0; if (verbosity >= E_DEBUG) { logprintf ("Starting netloop\n"); } term_ev = event_new (TLS->ev_base, 0, EV_READ | EV_PERSIST, stdin_read_callback, 0); event_add (term_ev, 0); int last_get_state = time (0); while (1) { event_base_loop (TLS->ev_base, EVLOOP_ONCE); if (term_ev && delete_stdin_event) { logprintf ("delete stdin\n"); event_free (term_ev); term_ev = 0; } #ifdef USE_LUA lua_do_all (); #endif #ifdef USE_PYTHON py_do_all (); #endif if (safe_quit && !TLS->active_queries) { printf ("All done. Exit\n"); do_halt (0); safe_quit = 0; } if (sigterm_cnt > 0) { do_halt (0); } if (time (0) - last_get_state > 3600) { tgl_do_lookup_state (TLS); last_get_state = time (0); } write_state_file (); update_prompt (); if (unknown_user_list_pos) { int i; for (i = 0; i < unknown_user_list_pos; i++) { tgl_do_get_user_info (TLS, TGL_MK_USER (unknown_user_list[i]), 0, 0, 0); } unknown_user_list_pos = 0; } } if (term_ev) { event_free (term_ev); term_ev = 0; } if (verbosity >= E_DEBUG) { logprintf ("End of netloop\n"); } }
tgl_peer_t *find_peer_by_name (struct tgl_state *TLS, const char *who) { tgl_peer_t *peer = tgl_peer_get (TLS, TGL_MK_USER(atoi (who))); if (peer) { return peer; } peer = tgl_peer_get (TLS, TGL_MK_CHAT(atoi(who))); if (peer) { return peer; } peer = tgl_peer_get (TLS, TGL_MK_ENCR_CHAT(atoi(who))); if (peer) { return peer; } return NULL; }
tgl_peer_id_t tgp_blist_buddy_get_id (PurpleBuddy *buddy) { int id = purple_blist_node_get_int (&buddy->node, TGP_BUDDY_KEY_PEER_ID), type = purple_blist_node_get_int (&buddy->node, TGP_BUDDY_KEY_PEER_TYPE); if (type == TGL_PEER_USER) { return TGL_MK_USER (id); } else if (type == TGL_PEER_ENCR_CHAT) { return TGL_MK_ENCR_CHAT (id); } else { assert (FALSE); } }
static int tgprpl_send_chat (PurpleConnection * gc, int id, const char *message, PurpleMessageFlags flags) { debug ("tgprpl_send_chat()\n"); telegram_conn *conn = purple_connection_get_protocol_data (gc); gchar *raw = purple_unescape_html(message); tgl_do_send_message (conn->TLS, TGL_MK_CHAT(id), raw, (int)strlen (raw), 0, 0); g_free (raw); p2tgl_got_chat_in(conn->TLS, TGL_MK_CHAT(id), TGL_MK_USER(conn->TLS->our_id), message, PURPLE_MESSAGE_RECV, time(NULL)); return 1; }
static unsigned int tgprpl_send_typing (PurpleConnection * gc, const char *who, PurpleTypingState typing) { debug ("tgprpl_send_typing()\n"); int id = atoi (who); telegram_conn *conn = purple_connection_get_protocol_data(gc); tgl_peer_t *U = tgl_peer_get (conn->TLS, TGL_MK_USER (id)); if (U) { if (typing == PURPLE_TYPING) { tgl_do_send_typing (conn->TLS, U->id, tgl_typing_typing, 0, 0); } else { tgl_do_send_typing (conn->TLS, U->id, tgl_typing_cancel, 0, 0); } } return 0; }
static void tgprpl_chat_invite (PurpleConnection * gc, int id, const char *message, const char *name) { debug ("tgprpl_chat_invite()\n"); telegram_conn *conn = purple_connection_get_protocol_data (gc); tgl_peer_t *chat = tgl_peer_get(conn->TLS, TGL_MK_CHAT (id)); tgl_peer_t *user = tgl_peer_get(conn->TLS, TGL_MK_USER (atoi(name))); if (! chat || ! user) { purple_notify_error (_telegram_protocol, "Not found", "Cannot invite buddy to chat.", "Specified user is not existing."); return; } tgl_do_add_user_to_chat (conn->TLS, chat->id, user->id, 0, NULL, NULL); }
void json_pack_chat (json_t *res, tgl_peer_t *P) { assert (P->chat.title); assert (json_object_set (res, "title", json_string (P->chat.title)) >= 0); assert (json_object_set (res, "members_num", json_integer (P->chat.users_num)) >= 0); if (P->chat.user_list) { json_t *m = json_array (); assert (m); int i; for (i = 0; i < P->chat.users_num; i++) { tgl_peer_id_t id = TGL_MK_USER (P->chat.user_list[i].user_id); assert (json_array_append (m, json_pack_peer (id, tgl_peer_get (TLS, id))) >= 0); } assert (json_object_set (res, "members", m) >= 0); } }
static void tgp_chat_add_all_users (struct tgl_state *TLS, PurpleConversation *conv, struct tgl_chat *C) { GList *users = NULL, *flags = NULL; int i = 0; for (; i < C->user_list_size; i++) { struct tgl_chat_user *uid = (C->user_list + i); const char *name = tgp_blist_peer_get_purple_name (TLS, TGL_MK_USER(uid->user_id)); if (! name) { g_warn_if_reached(); continue; } users = g_list_append (users, g_strdup (name)); flags = g_list_append (flags, GINT_TO_POINTER(C->admin_id == uid->user_id ? PURPLE_CBFLAGS_FOUNDER : PURPLE_CBFLAGS_NONE)); } purple_conv_chat_add_users (PURPLE_CONV_CHAT(conv), users, NULL, flags, FALSE); g_list_free_full (users, g_free); g_list_free (flags); }
static void tgp_chat_add_all_users (struct tgl_state *TLS, PurpleConversation *conv, struct tgl_chat *C) { GList *users = NULL, *flags = NULL; int i = 0; for (; i < C->user_list_size; i++) { struct tgl_chat_user *uid = (C->user_list + i); users = g_list_append (users, g_strdup_printf ("%d", uid->user_id)); flags = g_list_append (flags, GINT_TO_POINTER(C->admin_id == uid->user_id ? PURPLE_CBFLAGS_FOUNDER : PURPLE_CBFLAGS_NONE)); } purple_conv_chat_add_users (PURPLE_CONV_CHAT(conv), users, NULL, flags, FALSE); while (users) { p2tgl_conv_add_user_rename (tgl_peer_get (TLS, TGL_MK_USER(atoi (users->data))), conv); users = g_list_next (users); } g_list_free_full (users, g_free); g_list_free (flags); }
static void update_secret_chat_handler (struct tgl_state *TLS, struct tgl_secret_chat *U, unsigned flags) { debug ("secret-chat-state: %d", U->state); if (flags & TGL_UPDATE_WORKING || flags & TGL_UPDATE_DELETED) { write_secret_chat_file (TLS); } PurpleBuddy *buddy = p2tgl_buddy_find (TLS, U->id); if (! (flags & TGL_UPDATE_DELETED)) { if (!buddy) { buddy = p2tgl_buddy_new (TLS, (tgl_peer_t *)U); purple_blist_add_buddy (buddy, NULL, tggroup, NULL); purple_blist_alias_buddy (buddy, U->print_name); } p2tgl_prpl_got_set_status_mobile (TLS, U->id); } if (flags & TGL_UPDATE_REQUESTED && buddy) { connection_data *conn = TLS->ev_base; const char* choice = purple_account_get_string (conn->pa, "accept-secret-chats", "ask"); if (! strcmp (choice, "always")) { tgl_do_accept_encr_chat_request (TLS, U, write_secret_chat_gw, 0); } else if (! strcmp(choice, "ask")) { PurpleBuddy *who = p2tgl_buddy_find (TLS, TGL_MK_USER(U->user_id)); struct accept_secret_chat_data *data = g_new (struct accept_secret_chat_data, 1); data->TLS = TLS; data->U = U; gchar *message = g_strdup_printf ("Accept Secret Chat '%s'?", U->print_name); purple_request_accept_cancel (conn->gc, "Secret Chat", message, "Secret chats can only have one " "end point. If you accept a secret chat on this device, its messages will " "not be available anywhere else. If you decline, you can accept" " the chat on other devices.", 0, conn->pa, who->name, NULL, data, G_CALLBACK(accept_secret_chat_cb), G_CALLBACK(decline_secret_chat_cb)); g_free (message); }
void read_auth_file (void) { if (binlog_enabled) { return; } int auth_file_fd = open (get_auth_key_filename (), O_CREAT | O_RDWR, 0600); if (auth_file_fd < 0) { empty_auth_file (); return; } assert (auth_file_fd >= 0); unsigned x; unsigned m; if (read (auth_file_fd, &m, 4) < 4 || (m != DC_SERIALIZED_MAGIC)) { close (auth_file_fd); empty_auth_file (); return; } assert (read (auth_file_fd, &x, 4) == 4); assert (x > 0); int dc_working_num; assert (read (auth_file_fd, &dc_working_num, 4) == 4); int i; for (i = 0; i <= (int)x; i++) { int y; assert (read (auth_file_fd, &y, 4) == 4); if (y) { read_dc (auth_file_fd, i, m); } } bl_do_set_working_dc (TLS, dc_working_num); int our_id; int l = read (auth_file_fd, &our_id, 4); if (l < 4) { assert (!l); } if (our_id) { bl_do_set_our_id (TLS, TGL_MK_USER (our_id)); } close (auth_file_fd); }
void CTelegramProto::ReadAuth() { DBVARIANT dbv = { 0 }; if (db_get(0, m_szModuleName, "TGL_AUTH", &dbv)) { bl_do_dc_option(TLS, 1, "", 0, TG_SERVER_1, strlen(TG_SERVER_1), 443); bl_do_dc_option(TLS, 2, "", 0, TG_SERVER_2, strlen(TG_SERVER_2), 443); bl_do_dc_option(TLS, 3, "", 0, TG_SERVER_3, strlen(TG_SERVER_3), 443); bl_do_dc_option(TLS, 4, "", 0, TG_SERVER_4, strlen(TG_SERVER_4), 443); bl_do_dc_option(TLS, 5, "", 0, TG_SERVER_5, strlen(TG_SERVER_5), 443); bl_do_set_working_dc(TLS, TG_SERVER_DEFAULT); return; } int *piBlob = (int*)dbv.pbVal; size_t x = (size_t)*piBlob++; int dc_working_num = *piBlob++; for (size_t i = 0; i < x; i++) { int y = *piBlob++; if (y) { read_dc(TLS, piBlob, i); } } bl_do_set_working_dc(TLS, dc_working_num); int our_id = *piBlob++; if (our_id) { bl_do_set_our_id(TLS, TGL_MK_USER(our_id).id); } db_free(&dbv); }
void json_pack_encr_chat (json_t *res, tgl_peer_t *P) { assert (json_object_set (res, "user", json_pack_peer (TGL_MK_USER (P->encr_chat.user_id), tgl_peer_get (TLS, TGL_MK_USER (P->encr_chat.user_id)))) >= 0); }
static void tgprpl_get_info (PurpleConnection * gc, const char *username) { debug ("tgprpl_get_info()\n"); telegram_conn *conn = purple_connection_get_protocol_data(gc); tgl_peer_id_t u = TGL_MK_USER(atoi(username)); tgl_do_get_user_info (conn->TLS, u, 0, on_user_get_info, (void *)1l); }
tgl_peer_t *tgp_encr_chat_get_partner (struct tgl_state *TLS, struct tgl_secret_chat *chat) { return tgl_peer_get (TLS, TGL_MK_USER(chat->admin_id == TLS->our_id ? chat->user_id : chat->admin_id)); }
void tgl_do_send_create_encr_chat (struct tgl_state *TLS, void *x, unsigned char *random, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_secret_chat *E), void *callback_extra) { int user_id = (long)x; int i; unsigned char random_here[256]; tglt_secure_random (random_here, 256); for (i = 0; i < 256; i++) { random[i] ^= random_here[i]; } BIGNUM *a = BN_bin2bn (random, 256, 0); ensure_ptr (a); BIGNUM *p = BN_bin2bn (TLS->encr_prime, 256, 0); ensure_ptr (p); BIGNUM *g = BN_new (); ensure_ptr (g); ensure (BN_set_word (g, TLS->encr_root)); BIGNUM *r = BN_new (); ensure_ptr (r); ensure (BN_mod_exp (r, g, a, p, TLS->BN_ctx)); BN_clear_free (a); static char g_a[256]; memset (g_a, 0, 256); BN_bn2bin (r, (void *)(g_a + (256 - BN_num_bytes (r)))); int t = lrand48 (); while (tgl_peer_get (TLS, TGL_MK_ENCR_CHAT (t))) { t = lrand48 (); } //bl_do_encr_chat_init (TLS, t, user_id, (void *)random, (void *)g_a); int state = sc_waiting; bl_do_encr_chat_new (TLS, t, NULL, NULL, &TLS->our_id, &user_id, random, NULL, NULL, &state, NULL, NULL, NULL, NULL, NULL, NULL, TGLPF_CREATE | TGLPF_CREATED); tgl_peer_t *_E = tgl_peer_get (TLS, TGL_MK_ENCR_CHAT (t)); assert (_E); struct tgl_secret_chat *E = &_E->encr_chat; clear_packet (); out_int (CODE_messages_request_encryption); tgl_peer_t *U = tgl_peer_get (TLS, TGL_MK_USER (E->user_id)); assert (U); if (U && U->user.access_hash) { out_int (CODE_input_user_foreign); out_int (E->user_id); out_long (U->user.access_hash); } else { out_int (CODE_input_user_contact); out_int (E->user_id); } out_int (tgl_get_peer_id (E->id)); out_cstring (g_a, 256); //write_secret_chat_file (); BN_clear_free (g); BN_clear_free (p); BN_clear_free (r); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &send_encr_request_methods, E, callback, callback_extra); }
int loop (void) { tgl_set_callback (TLS, &upd_cb); struct event_base *ev = event_base_new (); tgl_set_ev_base (TLS, ev); tgl_set_net_methods (TLS, &tgl_conn_methods); tgl_set_timer_methods (TLS, &tgl_libevent_timers); assert (TLS->timer_methods); tgl_set_download_directory (TLS, get_downloads_directory ()); tgl_register_app_id (TLS, TELEGRAM_CLI_APP_ID, TELEGRAM_CLI_APP_HASH); tgl_set_app_version (TLS, "Telegram-cli " TELEGRAM_CLI_VERSION); if (ipv6_enabled) { tgl_enable_ipv6 (TLS); } if (bot_mode) { tgl_enable_bot (TLS); } if (disable_link_preview) { tgl_disable_link_preview (TLS); } tgl_init (TLS); if (binlog_enabled) { double t = tglt_get_double_time (); if (verbosity >= E_DEBUG) { logprintf ("replay log start\n"); } tgl_replay_log (TLS); if (verbosity >= E_DEBUG) { logprintf ("replay log end in %lf seconds\n", tglt_get_double_time () - t); } tgl_reopen_binlog_for_writing (TLS); } else { read_auth_file (); read_state_file (); read_secret_chat_file (); } binlog_read = 1; #ifdef USE_LUA lua_binlog_end (); #endif #ifdef USE_PYTHON py_binlog_end (); #endif if (sfd >= 0) { struct event *ev = event_new (TLS->ev_base, sfd, EV_READ | EV_PERSIST, accept_incoming, 0); event_add (ev, 0); } if (usfd >= 0) { struct event *ev = event_new (TLS->ev_base, usfd, EV_READ | EV_PERSIST, accept_incoming, 0); event_add (ev, 0); } update_prompt (); if (reset_authorization) { tgl_peer_t *P = tgl_peer_get (TLS, TGL_MK_USER (TLS->our_id)); if (P && P->user.phone && reset_authorization == 1) { set_default_username (P->user.phone); } bl_do_reset_authorization (TLS); } tgl_enable_pfs(TLS); set_interface_callbacks (); tgl_login (TLS); net_loop (); return 0; }
static char *format_service_msg (struct tgl_state *TLS, struct tgl_message *M) { g_return_val_if_fail(M && M->flags & TGLMF_SERVICE, NULL); connection_data *conn = TLS->ev_base; char *txt = NULL; tgl_peer_t *fromPeer = tgl_peer_get (TLS, M->from_id); g_return_val_if_fail(fromPeer != NULL, NULL); const char *txt_user = fromPeer->print_name; switch (M->action.type) { case tgl_message_action_chat_create: txt = g_strdup_printf (_("%2$s created chat %1$s."), M->action.title, txt_user); break; case tgl_message_action_chat_edit_title: txt = g_strdup_printf (_("%2$s changed title to %1$s."), M->action.new_title, txt_user); break; case tgl_message_action_chat_edit_photo: txt = g_strdup_printf (_("%s changed photo."), txt_user); break; case tgl_message_action_chat_delete_photo: txt = g_strdup_printf (_("%s deleted photo."), txt_user); break; case tgl_message_action_chat_add_user_by_link: { tgl_peer_t *actionPeer = tgl_peer_get (TLS, TGL_MK_USER (M->action.user)); if (actionPeer) { char *alias = actionPeer->print_name; PurpleConversation *conv = purple_find_chat (conn->gc, tgl_get_peer_id (M->to_id)); txt = g_strdup_printf (_("%1$s added user %2$s by link."), alias, txt_user); if (conv) { p2tgl_conv_add_user (TLS, conv, tgl_get_peer_id (fromPeer->id), NULL, 0, FALSE); } return txt; } break; } case tgl_message_action_chat_add_user: { tgl_peer_t *peer = tgl_peer_get (TLS, TGL_MK_USER (M->action.user)); if (peer) { char *alias = peer->print_name; txt = g_strdup_printf (_("%2$s added user %1$s."), alias, txt_user); PurpleConversation *conv = purple_find_chat (conn->gc, tgl_get_peer_id (M->to_id)); if (conv) { p2tgl_conv_add_user (TLS, conv, M->action.user, NULL, 0, FALSE); } } break; } case tgl_message_action_chat_delete_user: { tgl_peer_t *peer = tgl_peer_get (TLS, TGL_MK_USER (M->action.user)); if (peer) { tgl_peer_t *chatPeer = tgl_peer_get (TLS, M->to_id); g_return_val_if_fail(tgl_get_peer_type (chatPeer->id) == TGL_PEER_CHAT, NULL); // make sure that the chat is showing before deleting the user, otherwise the chat will be // initialised after removing the chat and the chat will still contain the deleted user PurpleConversation *conv = tgp_chat_show (TLS, &chatPeer->chat); if (conv) { char *alias = peer->print_name; const char *aliasLeft = tgp_blist_lookup_purple_name (TLS, TGL_MK_USER (M->action.user)); if (tgl_get_peer_id (M->from_id) != tgl_get_peer_id (peer->id)) { txt = g_strdup_printf (_("%2$s deleted user %1$s."), alias, txt_user); } g_return_val_if_fail (aliasLeft, NULL); purple_conv_chat_remove_user (purple_conversation_get_chat_data (conv), aliasLeft, txt); if (M->action.user == tgl_get_peer_id (TLS->our_id)) { purple_conv_chat_left (purple_conversation_get_chat_data (conv)); } // conv_del_user already printed a message, prevent a redundant message // from being printed by returning NULL g_free (txt); return NULL; } char *alias = peer->print_name; if (tgl_get_peer_id (M->from_id) != tgl_get_peer_id (peer->id)) { txt = g_strdup_printf (_("%2$s deleted user %1$s."), alias, txt_user); } } break; } case tgl_message_action_set_message_ttl: txt = g_strdup_printf (P_("%2$s set self destruction timer to %1$d second.", "%2$s set self destruction timer to %1$d seconds.", M->action.ttl), M->action.ttl, txt_user); break; case tgl_message_action_read_messages: txt = g_strdup_printf (P_("%2$s marked %1$d message read.", "%2$s marked %1$d messages read.", M->action.read_cnt), M->action.read_cnt, txt_user); break; case tgl_message_action_delete_messages: txt = g_strdup_printf (P_("%2$s deleted %1$d message.", "%2$s deleted %1$d messages.", M->action.delete_cnt), M->action.delete_cnt, txt_user); break; case tgl_message_action_screenshot_messages: txt = g_strdup_printf (P_("%2$s made a screenshot of %1$d message.", "%2$s made a screenshot of %1$d messages.", M->action.screenshot_cnt), M->action.screenshot_cnt, txt_user); break; default: g_warn_if_reached(); break; } return txt; }
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); } }
int loop (void) { //on_start (); tgl_set_callback (TLS, &upd_cb); //TLS->temp_key_expire_time = 60; struct event_base *ev = event_base_new (); tgl_set_ev_base (TLS, ev); tgl_set_net_methods (TLS, &tgl_conn_methods); tgl_set_timer_methods (TLS, &tgl_libevent_timers); assert (TLS->timer_methods); tgl_set_download_directory (TLS, get_downloads_directory ()); tgl_register_app_id (TLS, TELEGRAM_CLI_APP_ID, TELEGRAM_CLI_APP_HASH); tgl_init (TLS); if (binlog_enabled) { double t = tglt_get_double_time (); if (verbosity >= E_DEBUG) { logprintf ("replay log start\n"); } tgl_replay_log (TLS); if (verbosity >= E_DEBUG) { logprintf ("replay log end in %lf seconds\n", tglt_get_double_time () - t); } tgl_reopen_binlog_for_writing (TLS); } else { read_auth_file (); read_state_file (); read_secret_chat_file (); } binlog_read = 1; #ifdef USE_LUA lua_binlog_end (); #endif if (sfd >= 0) { struct event *ev = event_new (TLS->ev_base, sfd, EV_READ | EV_PERSIST, accept_incoming, 0); event_add (ev, 0); } if (usfd >= 0) { struct event *ev = event_new (TLS->ev_base, usfd, EV_READ | EV_PERSIST, accept_incoming, 0); event_add (ev, 0); } update_prompt (); if (reset_authorization) { tgl_peer_t *P = tgl_peer_get (TLS, TGL_MK_USER (TLS->our_id)); if (P && P->user.phone && reset_authorization == 1) { set_default_username (P->user.phone); } bl_do_reset_authorization (TLS); } net_loop (0, all_authorized); int i; for (i = 0; i <= TLS->max_dc_num; i++) if (TLS->DC_list[i] && !tgl_authorized_dc (TLS, TLS->DC_list[i])) { assert (0); } if (!tgl_signed_dc (TLS, TLS->DC_working)) { if (disable_output) { fprintf (stderr, "Can not login without output\n"); do_halt (1); } if (!default_username) { size_t size = 0; char *user = 0; if (!user) { printf ("Telephone number (with '+' sign): "); if (net_getline (&user, &size) == -1) { perror ("getline()"); do_halt (1); } set_default_username (user); } } tgl_do_send_code (TLS, default_username, sign_in_callback, 0); net_loop (0, sent_code); if (verbosity >= E_DEBUG) { logprintf ("%s\n", should_register ? "phone not registered" : "phone registered"); } if (!should_register) { char *code = 0; size_t size = 0; printf ("Code from sms (if you did not receive an SMS and want to be called, type \"call\"): "); while (1) { if (net_getline (&code, &size) == -1) { perror ("getline()"); do_halt (1); } if (!strcmp (code, "call")) { printf ("You typed \"call\", switching to phone system.\n"); tgl_do_phone_call (TLS, default_username, hash, 0, 0); printf ("Calling you! Code: "); continue; } if (tgl_do_send_code_result (TLS, default_username, hash, code, sign_in_result, 0) >= 0) { break; } printf ("Invalid code. Try again: "); free (code); } } else { printf ("User is not registered. Do you want to register? [Y/n] "); char *code; size_t size; if (net_getline (&code, &size) == -1) { perror ("getline()"); do_halt (1); } if (!*code || *code == 'y' || *code == 'Y') { printf ("Ok, starting registartion.\n"); } else { printf ("Then try again\n"); do_halt (1); } char *first_name; printf ("First name: "); if (net_getline (&first_name, &size) == -1) { perror ("getline()"); do_halt (1); } char *last_name; printf ("Last name: "); if (net_getline (&last_name, &size) == -1) { perror ("getline()"); do_halt (1); } printf ("Code from sms (if you did not receive an SMS and want to be called, type \"call\"): "); while (1) { if (net_getline (&code, &size) == -1) { perror ("getline()"); do_halt (1); } if (!strcmp (code, "call")) { printf ("You typed \"call\", switching to phone system.\n"); tgl_do_phone_call (TLS, default_username, hash, 0, 0); printf ("Calling you! Code: "); continue; } if (tgl_do_send_code_result_auth (TLS, default_username, hash, code, first_name, last_name, sign_in_result, 0) >= 0) { break; } printf ("Invalid code. Try again: "); free (code); } } net_loop (0, signed_in); //bl_do_dc_signed (TLS->DC_working); } for (i = 0; i <= TLS->max_dc_num; i++) if (TLS->DC_list[i] && !tgl_signed_dc (TLS, TLS->DC_list[i])) { tgl_do_export_auth (TLS, i, export_auth_callback, (void*)(long)TLS->DC_list[i]); cur_a_dc = TLS->DC_list[i]; net_loop (0, dc_signed_in); assert (tgl_signed_dc (TLS, TLS->DC_list[i])); } write_auth_file (); fflush (stdout); fflush (stderr); //read_state_file (); //read_secret_chat_file (); set_interface_callbacks (); tglm_send_all_unsent (TLS); tgl_do_get_difference (TLS, sync_from_start, get_difference_callback, 0); net_loop (0, dgot); assert (!(TLS->locks & TGL_LOCK_DIFF)); TLS->started = 1; if (wait_dialog_list) { d_got_ok = 0; tgl_do_get_dialog_list (TLS, dlist_cb, 0); net_loop (0, dgot); } #ifdef USE_LUA lua_diff_end (); #endif if (start_command) { safe_quit = 1; while (*start_command) { char *start = start_command; while (*start_command && *start_command != '\n') { start_command ++; } if (*start_command) { *start_command = 0; start_command ++; } interpreter_ex (start, 0); } } /*tgl_do_get_dialog_list (get_dialogs_callback, 0); if (wait_dialog_list) { dialog_list_got = 0; net_loop (0, dlgot); }*/ return main_loop (); }
static char *format_service_msg (struct tgl_state *TLS, struct tgl_message *M) { assert (M && M->service); char *txt_user = NULL; char *txt_action = NULL; char *txt = NULL; tgl_peer_t *peer = tgl_peer_get (TLS, M->from_id); if (! peer) { return NULL; } txt_user = p2tgl_strdup_alias (peer); switch (M->action.type) { case tgl_message_action_chat_create: txt_action = g_strdup_printf ("created chat %s", M->action.title); break; case tgl_message_action_chat_edit_title: txt_action = g_strdup_printf ("changed title to %s", M->action.new_title); break; case tgl_message_action_chat_edit_photo: txt_action = g_strdup ("changed photo"); break; case tgl_message_action_chat_delete_photo: txt_action = g_strdup ("deleted photo"); break; case tgl_message_action_chat_add_user: { tgl_peer_t *peer = tgl_peer_get (TLS, TGL_MK_USER (M->action.user)); if (peer) { char *alias = p2tgl_strdup_alias (peer); txt_action = g_strdup_printf ("added user %s", alias); g_free (alias); } break; } case tgl_message_action_chat_delete_user: { tgl_peer_t *peer = tgl_peer_get (TLS, TGL_MK_USER (M->action.user)); if (peer) { char *alias = p2tgl_strdup_alias (peer); txt_action = g_strdup_printf ("deleted user %s", alias); g_free (alias); } break; } case tgl_message_action_set_message_ttl: txt_action = g_strdup_printf ("set ttl to %d seconds", M->action.ttl); break; case tgl_message_action_read_messages: txt_action = g_strdup_printf ("%d messages marked read", M->action.read_cnt); break; case tgl_message_action_delete_messages: txt_action = g_strdup_printf ("%d messages deleted", M->action.delete_cnt); break; case tgl_message_action_screenshot_messages: txt_action = g_strdup_printf ("%d messages screenshoted", M->action.screenshot_cnt); break; case tgl_message_action_notify_layer: txt_action = g_strdup_printf ("updated layer to %d", M->action.layer); break; /* case tgl_message_action_request_key: txt_action = g_strdup_printf ("Request rekey #%016llx\n", M->action.exchange_id); break; case tgl_message_action_accept_key: txt_action = g_strdup_printf ("Accept rekey #%016llx\n", M->action.exchange_id); break; case tgl_message_action_commit_key: txt_action = g_strdup_printf ("Commit rekey #%016llx\n", M->action.exchange_id); break; case tgl_message_action_abort_key: txt_action = g_strdup_printf ("Abort rekey #%016llx\n", M->action.exchange_id); break; */ default: txt_action = NULL; break; } if (txt_action) { debug ("SERVICE MESSAGE: %s", txt_action); txt = g_strdup_printf ("%s %s.", txt_user, txt_action); g_free (txt_action); } g_free (txt_user); return txt; }
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); } }