Beispiel #1
0
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;
}
Beispiel #2
0
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);
}
Beispiel #3
0
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);
  }
}
Beispiel #4
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);
  }
}
Beispiel #5
0
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);
  }
}
Beispiel #6
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);
  }
}