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;
}
Exemple #2
0
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;
}
Exemple #4
0
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);
}
Exemple #8
0
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);
  }
}
Exemple #9
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);
    }
Exemple #12
0
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);
}
Exemple #13
0
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);
}
Exemple #14
0
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));
}
Exemple #17
0
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);
}
Exemple #18
0
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;
}
Exemple #19
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;
}
Exemple #20
0
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);
  }
}
Exemple #21
0
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;
}
Exemple #23
0
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);
  }
}