Beispiel #1
0
Datei: main.c Projekt: analani/tg
char *make_full_path (char *s) {
  if (*s != '/') {
    char *t = s;
    tasprintf (&s, "%s/%s", get_home_directory (), s);
    tfree_str (t);
  }
  return s;
}
Beispiel #2
0
static void one_string_read_end (void) {
  printf ("\n");
  fflush (stdout);

  read_one_string = 0;
  tfree_str (one_string_prompt);
  one_string_prompt = NULL;
  reactivate_readline ();

  one_string_results[one_string_num] = tstrdup (one_string);
  ++one_string_num;

  if (one_string_num < one_string_total_args) {
    do_get_string (TLS);
  } else {
    one_string_cb (TLS, (void *)one_string_results, string_cb_arg);
    int i;
    for (i = 0; i < one_string_total_args; i++) {
      tfree_str (one_string_results[i]);
    }
  }
}
Beispiel #3
0
Datei: main.c Projekt: analani/tg
void running_for_first_time (void) {
  check_type_sizes ();
  if (config_filename) {
    return; // Do not create custom config file
  }
  tasprintf (&config_filename, "%s/%s/%s", get_home_directory (), CONFIG_DIRECTORY, CONFIG_FILE);
  config_filename = make_full_path (config_filename);

  int config_file_fd;
  char *config_directory = get_config_directory ();
  //char *downloads_directory = get_downloads_directory ();

  if (!mkdir (config_directory, CONFIG_DIRECTORY_MODE)) {
    if (!disable_output) {
      printf ("[%s] created\n", config_directory);
    }
  }

  tfree_str (config_directory);
  config_directory = NULL;
  // see if config file is there
  if (access (config_filename, R_OK) != 0) {
    // config file missing, so touch it
    config_file_fd = open (config_filename, O_CREAT | O_RDWR, 0600);
    if (config_file_fd == -1)  {
      perror ("open[config_file]");
      exit (EXIT_FAILURE);
    }
    if (write (config_file_fd, DEFAULT_CONFIG_CONTENTS, strlen (DEFAULT_CONFIG_CONTENTS)) <= 0) {
      perror ("write[config_file]");
      exit (EXIT_FAILURE);
    }
    close (config_file_fd);
    /*int auth_file_fd = open (get_auth_key_filename (), O_CREAT | O_RDWR, 0600);
    int x = -1;
    assert (write (auth_file_fd, &x, 4) == 4);
    close (auth_file_fd);

    printf ("[%s] created\n", config_filename);*/
  
    /* create downloads directory */
    /*if (mkdir (downloads_directory, 0755) !=0) {
      perror ("creating download directory");
      exit (EXIT_FAILURE);
    }*/
  }
}
Beispiel #4
0
void running_for_first_time (void) {
  check_type_sizes ();
  if (!str_empty (config_filename)) {
    return; // Do not create custom config file
  }
  if (str_empty (config_directory)) {
    config_directory = get_config_directory ();
  }
  tasprintf (&config_filename, "%s/%s", config_directory, CONFIG_FILE);
  config_filename = make_full_path (config_filename);
  if (!disable_output) {
    printf ("I: config dir=[%s]\n", config_directory);
  }
  // printf ("I: config file=[%s]\n", config_filename);

  int config_file_fd;
  //char *config_directory = get_config_directory ();
  //char *downloads_directory = get_downloads_directory ();

  if (!mkdir (config_directory, CONFIG_DIRECTORY_MODE)) {
    if (!disable_output) {
      printf ("[%s] created\n", config_directory);
    }
  }

  tfree_str (config_directory);
  config_directory = NULL;
  // see if config file is there
  if (access (config_filename, R_OK) != 0) {
    // config file missing, so touch it
    config_file_fd = open (config_filename, O_CREAT | O_RDWR, 0600);
    if (config_file_fd == -1)  {
      perror ("open[config_file]");
      printf ("I: config_file=[%s]\n", config_filename);
      exit (EXIT_FAILURE);
    }
    if (write (config_file_fd, DEFAULT_CONFIG_CONTENTS, strlen (DEFAULT_CONFIG_CONTENTS)) <= 0) {
      perror ("write[config_file]");
      exit (EXIT_FAILURE);
    }
    close (config_file_fd);
  }
}
Beispiel #5
0
void tgl_set_app_version (struct tgl_state *TLS, const char *app_version) {
  if (TLS->app_version) {
    tfree_str (TLS->app_version);
  }
  TLS->app_version = tstrdup (app_version);
}
Beispiel #6
0
static void send_file_encrypted_end (struct tgl_state *TLS, struct send_file *f, void *callback, void *callback_extra) {
  out_int (CODE_messages_send_encrypted_file);
  out_int (CODE_input_encrypted_chat);
  out_int (tgl_get_peer_id (f->to_id));
  tgl_peer_t *P = tgl_peer_get (TLS, f->to_id);
  assert (P);
  out_long (P->encr_chat.access_hash);
  long long r;
  tglt_secure_random (&r, 8);
  out_long (r);
  encr_start ();
  out_int (CODE_decrypted_message_layer);
  out_random (15 + 4 * (lrand48 () % 3));
  out_int (TGL_ENCRYPTED_LAYER);
  out_int (2 * P->encr_chat.in_seq_no + (P->encr_chat.admin_id != TLS->our_id));
  out_int (2 * P->encr_chat.out_seq_no + (P->encr_chat.admin_id == TLS->our_id));
  out_int (CODE_decrypted_message);
  out_long (r);
  out_int (P->encr_chat.ttl);
  out_string ("");
  int *save_ptr = packet_ptr;
  if (f->flags == -1) {
    out_int (CODE_decrypted_message_media_photo);
  } else if ((f->flags & TGLDF_VIDEO)) {
    out_int (CODE_decrypted_message_media_video);
  } else if ((f->flags & TGLDF_AUDIO)) {
    out_int (CODE_decrypted_message_media_audio);
  } else {
    out_int (CODE_decrypted_message_media_document);
  }
  if (f->flags == -1 || !(f->flags & TGLDF_AUDIO)) {
    out_cstring ("", 0);
    out_int (90);
    out_int (90);
  }
  
  if (f->flags == -1) {
    out_int (f->w);
    out_int (f->h);
  } else if (f->flags & TGLDF_VIDEO) {
    out_int (f->duration);
    out_string (tg_mime_by_filename (f->file_name));
    out_int (f->w);
    out_int (f->h);
  } else if (f->flags & TGLDF_AUDIO) {
    out_int (f->duration);
    out_string (tg_mime_by_filename (f->file_name));
  } else {
    out_string ("");
    out_string (tg_mime_by_filename (f->file_name));
    // document
  }
  
  out_int (f->size);
  out_cstring ((void *)f->key, 32);
  out_cstring ((void *)f->init_iv, 32);
 
  int *save_in_ptr = in_ptr;
  int *save_in_end = in_end;

  in_ptr = save_ptr;
  in_end = packet_ptr;

  assert (skip_type_any (TYPE_TO_PARAM(decrypted_message_media)) >= 0);
  assert (in_ptr == in_end);
  
  in_ptr = save_ptr;
  in_end = packet_ptr;
  
  struct tl_ds_decrypted_message_media *DS_DMM = fetch_ds_type_decrypted_message_media (TYPE_TO_PARAM (decrypted_message_media));
  in_end = save_in_ptr;
  in_ptr = save_in_end;


  int peer_type = tgl_get_peer_type (f->to_id);
  int peer_id = tgl_get_peer_id (f->to_id);
  int date = time (NULL);


  encr_finish (&P->encr_chat);
  if (f->size < (16 << 20)) {
    out_int (CODE_input_encrypted_file_uploaded);
  } else {
    out_int (CODE_input_encrypted_file_big_uploaded);
  }
  out_long (f->id);
  out_int (f->part_num);
  if (f->size < (16 << 20)) {
    out_string ("");
  }

  unsigned char md5[16];
  unsigned char str[64];
  memcpy (str, f->key, 32);
  memcpy (str + 32, f->init_iv, 32);
  MD5 (str, 64, md5);
  out_int ((*(int *)md5) ^ (*(int *)(md5 + 4)));

  tfree_secure (f->iv, 32);
  
  bl_do_create_message_encr_new (TLS, r, &TLS->our_id, &peer_type, &peer_id, &date, NULL, 0, DS_DMM, NULL, NULL, TGLMF_OUT | TGLMF_UNREAD | TGLMF_ENCRYPTED | TGLMF_CREATE | TGLMF_CREATED);

  free_ds_type_decrypted_message_media (DS_DMM, TYPE_TO_PARAM (decrypted_message_media));
  struct tgl_message *M = tgl_message_get (TLS, r);
  assert (M);
      
  tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &send_encr_file_methods, M, callback, callback_extra);
  
  tfree_str (f->file_name);
  tfree (f, sizeof (*f));

}
Beispiel #7
0
Datei: main.c Projekt: analani/tg
void set_default_username (const char *s) {
  if (default_username) { 
    tfree_str (default_username);
  }
  default_username = tstrdup (s);
}
Beispiel #8
0
void parse_config (void) {
  //config_filename = make_full_path (config_filename);
  
  config_t conf;
  config_init (&conf);
  if (config_read_file (&conf, config_filename) != CONFIG_TRUE) {
    fprintf (stderr, "Can not read config '%s': error '%s' on the line %d\n", config_filename, config_error_text (&conf), config_error_line (&conf));
    exit (2);
  }

  if (!prefix) {
    config_lookup_string (&conf, "default_profile", (void *)&prefix);
  }

  static char buf[1000];
  int l = 0;
  if (prefix) {
    l = strlen (prefix);
    memcpy (buf, prefix, l);
    buf[l ++] = '.';
  }
  
  int test_mode = 0;
  strcpy (buf + l, "test");
  config_lookup_bool (&conf, buf, &test_mode);
  if (test_mode) {
    tgl_set_test_mode (TLS);
  }
  
  strcpy (buf + l, "log_level");
  long long t = log_level;
  config_lookup_int (&conf, buf, (void *)&t);
  log_level = t;
  
  if (!msg_num_mode) {
    strcpy (buf + l, "msg_num");
    config_lookup_bool (&conf, buf, &msg_num_mode);
  }

  parse_config_val (&conf, &config_directory, "config_directory", CONFIG_DIRECTORY, 0);
  config_directory = make_full_path (config_directory);

  parse_config_val (&conf, &auth_file_name, "auth_file", AUTH_KEY_FILE, config_directory);
  parse_config_val (&conf, &downloads_directory, "downloads", DOWNLOADS_DIRECTORY, config_directory);
  
  if (!lua_file) {
    parse_config_val (&conf, &lua_file, "lua_script", 0, config_directory);
  }
  
  if (!python_file) {
    parse_config_val (&conf, &python_file, "python_script", 0, config_directory);
  }
 
  #if 0
  strcpy (buf + l, "binlog_enabled");
  config_lookup_bool (&conf, buf, &binlog_enabled);
  #else
  binlog_enabled = 0;
  #endif
  
  int pfs_enabled = 0;
  strcpy (buf + l, "pfs_enabled");
  config_lookup_bool (&conf, buf, &pfs_enabled);
  if (pfs_enabled) {
    tgl_enable_pfs (TLS);
  }

  if (binlog_enabled) {
    parse_config_val (&conf, &binlog_file_name, "binlog", BINLOG_FILE, config_directory);
    tgl_set_binlog_mode (TLS, 1);
    tgl_set_binlog_path (TLS, binlog_file_name);
  } else {
    tgl_set_binlog_mode (TLS, 0);
    parse_config_val (&conf, &state_file_name, "state_file", STATE_FILE, config_directory);
    parse_config_val (&conf, &secret_chat_file_name, "secret", SECRET_CHAT_FILE, config_directory);
    //tgl_set_auth_file_path (auth_file_name);
  }
  tgl_set_download_directory (TLS, downloads_directory);
  
  if (!mkdir (config_directory, CONFIG_DIRECTORY_MODE)) {
    if (!disable_output) {
      printf ("[%s] created\n", config_directory);
    }
  }
  if (!mkdir (downloads_directory, CONFIG_DIRECTORY_MODE)) {
    if (!disable_output) {
      printf ("[%s] created\n", downloads_directory);
    }
  }
  tfree_str (config_directory);
  config_directory = NULL;
  config_destroy (&conf);
}
Beispiel #9
0
Datei: loop.c Projekt: BUSHA/tg
int loop (void) {
  on_start ();
  if (binlog_enabled) {
    double t = get_double_time ();
    logprintf ("replay log start\n");
    replay_log ();
    logprintf ("replay log end in %lf seconds\n", get_double_time () - t);
    write_binlog ();
    #ifdef USE_LUA
      lua_binlog_end ();
    #endif
  } else {
    read_auth_file ();
  }
  update_prompt ();

  assert (DC_list[dc_working_num]);
  if (!DC_working || !DC_working->auth_key_id) {
//  if (auth_state == 0) {
    DC_working = DC_list[dc_working_num];
    assert (!DC_working->auth_key_id);
    dc_authorize (DC_working);
    assert (DC_working->auth_key_id);
    auth_state = 100;
    write_auth_file ();
  }
  
  if (verbosity) {
    logprintf ("Requesting info about DC...\n");
  }
  do_help_get_config ();
  net_loop (0, mcs);
  if (verbosity) {
    logprintf ("DC_info: %d new DC got\n", new_dc_num);
  }
  int i;
  for (i = 0; i <= MAX_DC_NUM; i++) if (DC_list[i] && !DC_list[i]->auth_key_id) {
    dc_authorize (DC_list[i]);
    assert (DC_list[i]->auth_key_id);
    write_auth_file ();
  }

  if (auth_state == 100 || !(DC_working->has_auth)) {
    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()");
          exit (EXIT_FAILURE);
        }
        set_default_username (user);
      }
    }
    int res = do_auth_check_phone (default_username);
    assert (res >= 0);
    logprintf ("%s\n", res > 0 ? "phone registered" : "phone not registered");
    if (res > 0 && !register_mode) {
      do_send_code (default_username);
      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()");
          exit (EXIT_FAILURE);
        }
        if (!strcmp (code, "call")) {
          printf ("You typed \"call\", switching to phone system.\n");
          do_phone_call (default_username);
          printf ("Calling you! Code: ");
          continue;
        }
        if (do_send_code_result (code) >= 0) {
          break;
        }
        printf ("Invalid code. Try again: ");
        tfree_str (code);
      }
      auth_state = 300;
    } 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()");
        exit (EXIT_FAILURE);
      }
      if (!*code || *code == 'y' || *code == 'Y') {
        printf ("Ok, starting registartion.\n");
      } else {
        printf ("Then try again\n");
        exit (EXIT_SUCCESS);
      }
      char *first_name;
      printf ("First name: ");
      if (net_getline (&first_name, &size) == -1) {
        perror ("getline()");
        exit (EXIT_FAILURE);
      }
      char *last_name;
      printf ("Last name: ");
      if (net_getline (&last_name, &size) == -1) {
        perror ("getline()");
        exit (EXIT_FAILURE);
      }

      int dc_num = do_get_nearest_dc ();
      assert (dc_num >= 0 && dc_num <= MAX_DC_NUM && DC_list[dc_num]);
      dc_working_num = dc_num;
      DC_working = DC_list[dc_working_num];
      
      do_send_code (default_username);
      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()");
          exit (EXIT_FAILURE);
        }
        if (!strcmp (code, "call")) {
          printf ("You typed \"call\", switching to phone system.\n");
          do_phone_call (default_username);
          printf ("Calling you! Code: ");
          continue;
        }
        if (do_send_code_result_auth (code, first_name, last_name) >= 0) {
          break;
        }
        printf ("Invalid code. Try again: ");
        tfree_str (code);
      }
      auth_state = 300;
    }
  }

  for (i = 0; i <= MAX_DC_NUM; i++) if (DC_list[i] && !DC_list[i]->has_auth) {
    do_export_auth (i);
    do_import_auth (i);
    bl_do_dc_signed (i);
    write_auth_file ();
  }
  write_auth_file ();

  fflush (stdout);
  fflush (stderr);

  read_state_file ();
  read_secret_chat_file ();

  set_interface_callbacks ();

  do_get_difference ();
  net_loop (0, dgot);
  #ifdef USE_LUA
    lua_diff_end ();
  #endif
  send_all_unsent ();


  do_get_dialog_list ();
  if (wait_dialog_list) {
    dialog_list_got = 0;
    net_loop (0, dlgot);
  }

  return main_loop ();
}
Beispiel #10
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 #11
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 #12
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);
  }
}