Пример #1
0
void fetch_message_media (struct message_media *M) {
  memset (M, 0, sizeof (*M));
  M->type = fetch_int ();
  switch (M->type) {
  case CODE_message_media_empty:
    break;
  case CODE_message_media_photo:
    fetch_photo (&M->photo);
    break;
  case CODE_message_media_video:
    fetch_video (&M->video);
    break;
  case CODE_message_media_geo:
    fetch_geo (&M->geo);
    break;
  case CODE_message_media_contact:
    M->phone = fetch_str_dup ();
    M->first_name = fetch_str_dup ();
    M->last_name = fetch_str_dup ();
    M->user_id = fetch_int ();
    break;
  case CODE_message_media_unsupported:
    M->data = fetch_str_dup ();
    break;
  default:
    logprintf ("type = 0x%08x\n", M->type);
    assert (0);
  }
}
Пример #2
0
void fetch_message_action (struct message_action *M) {
  memset (M, 0, sizeof (*M));
  unsigned x = fetch_int ();
  M->type = x;
  switch (x) {
  case CODE_message_action_empty:
    break;
  case CODE_message_action_chat_create:
    M->title = fetch_str_dup ();
    assert (fetch_int () == (int)CODE_vector);
    M->user_num = fetch_int ();
    M->users = malloc (M->user_num * 4);
    fetch_ints (M->users, M->user_num);
    break;
  case CODE_message_action_chat_edit_title:
    M->new_title = fetch_str_dup ();
    break;
  case CODE_message_action_chat_edit_photo:
    fetch_photo (&M->photo);
    break;
  case CODE_message_action_chat_delete_photo:
    break;
  case CODE_message_action_chat_add_user:
    M->user = fetch_int ();
    break;
  case CODE_message_action_chat_delete_user:
    M->user = fetch_int ();
    break;
  default:
    assert (0);
  }
}
Пример #3
0
int fetch_peer_id (void) {
  unsigned x =fetch_int ();
  if (x == CODE_peer_user) {
    return fetch_int ();
  } else {
    assert (CODE_peer_chat);
    return -fetch_int ();
  }
}
Пример #4
0
/*
 * Get information about port on bridge.
 */
int br_get_port_info(const char *brname, const char *port, 
		     struct port_info *info)
{
	DIR *d;
	char path[SYSFS_PATH_MAX];

	snprintf(path, SYSFS_PATH_MAX, SYSFS_CLASS_NET "%s/brport", port);
	d = opendir(path);
	if (!d)
		goto fallback;

	memset(info, 0, sizeof(*info));

	fetch_id(path, "designated_root", &info->designated_root);
	fetch_id(path, "designated_bridge", &info->designated_bridge);
	info->port_no = fetch_int(path, "port_no");
	info->port_id = fetch_int(path, "port_id");
	info->designated_port = fetch_int(path, "designated_port");
	info->path_cost = fetch_int(path, "path_cost");
	info->designated_cost = fetch_int(path, "designated_cost");
	info->state = fetch_int(path, "state");
	info->top_change_ack = fetch_int(path, "change_ack");
	info->config_pending = fetch_int(path, "config_pending");
	fetch_tv(path, "message_age_timer", &info->message_age_timer_value);
	fetch_tv(path, "forward_delay_timer", &info->forward_delay_timer_value);
	fetch_tv(path, "hold_timer", &info->hold_timer_value);
	info->hairpin_mode = fetch_int(path, "hairpin_mode");

	closedir(d);

	return 0;
fallback:
	return old_get_port_info(brname, port, info);
}
Пример #5
0
void fetch_message_short (struct message *M) {
  memset (M, 0, sizeof (*M));
  M->id = fetch_int ();
  M->from_id = fetch_int ();
  M->message = fetch_str_dup ();
  fetch_int (); // pts
  M->date = fetch_int ();
  fetch_int (); // seq
  M->media.type = CODE_message_media_empty;
  M->unread = 1;
}
Пример #6
0
/*
 * Get bridge parameters using either sysfs or old
 * ioctl.
 */
static int br_get_bridge_info(const char *bridge, struct bridge_info *info)
{
#ifdef HAVE_LIBSYSFS
	struct sysfs_class_device *dev;
	char path[SYSFS_PATH_MAX];

	if (!br_class_net)
		goto fallback;

	dev = sysfs_get_class_device(br_class_net, bridge);
	if (!dev) {
		dprintf("get_class_device '%s' failed\n", bridge);
		goto fallback;
	}

	snprintf(path, SYSFS_PATH_MAX, "%s/bridge", dev->path);
	if (sysfs_path_is_dir(path)) {
		dprintf("path '%s' is not a directory\n", path);
		sysfs_close_class_device(dev);
		goto fallback;
	}

	memset(info, 0, sizeof(*info));
	fetch_id(dev, BRIDGEATTR("root_id"), &info->designated_root);
	fetch_id(dev, BRIDGEATTR("bridge_id"), &info->bridge_id);
	info->root_path_cost = fetch_int(dev, BRIDGEATTR("root_path_cost"));
	fetch_tv(dev, BRIDGEATTR("max_age"), &info->max_age);
	fetch_tv(dev, BRIDGEATTR("hello_time"), &info->hello_time);
	fetch_tv(dev, BRIDGEATTR("forward_delay"), &info->forward_delay);
	fetch_tv(dev, BRIDGEATTR("max_age"), &info->bridge_max_age);
	fetch_tv(dev, BRIDGEATTR("hello_time"), &info->bridge_hello_time);
	fetch_tv(dev, BRIDGEATTR("forward_delay"), &info->bridge_forward_delay);
	fetch_tv(dev, BRIDGEATTR("ageing_time"), &info->ageing_time);
	fetch_tv(dev, BRIDGEATTR("hello_timer"), &info->hello_timer_value);
	fetch_tv(dev, BRIDGEATTR("tcn_timer"), &info->tcn_timer_value);
	fetch_tv(dev, BRIDGEATTR("topology_change_timer"),
		 &info->topology_change_timer_value);;
	fetch_tv(dev, BRIDGEATTR("gc_timer"), &info->gc_timer_value);

	info->root_port = fetch_int(dev, BRIDGEATTR("root_port"));
	info->stp_enabled = fetch_int(dev, BRIDGEATTR("stp_state"));
	info->topology_change = fetch_int(dev, BRIDGEATTR("topology_change"));
	info->topology_change_detected = fetch_int(dev,
						   BRIDGEATTR
						   ("topology_change_detected"));
	sysfs_close_class_device(dev);

	return 0;

fallback:
#endif
	return old_get_bridge_info(bridge, info);
}
Пример #7
0
/*
 * Get information about port on bridge.
 */
int br_get_port_info(const char *brname, const char *port, 
		     struct port_info *info)
{
#ifndef HAVE_LIBSYSFS
	return old_get_port_info(brname, port, info);
#else
	struct sysfs_directory *sdir
		= bridge_sysfs_directory(port, SYSFS_BRIDGE_PORT_ATTR);

	if (!sdir) 
		return old_get_port_info(brname, port, info);

	memset(info, 0, sizeof(*info));
	fetch_id(sdir, "designated_root", &info->designated_root);
	fetch_id(sdir, "designated_bridge", &info->designated_bridge);
	info->port_no = fetch_int(sdir, "port_no");
	info->port_id = fetch_int(sdir, "port_id");
	info->designated_port = fetch_int(sdir, "designated_port");
	info->path_cost = fetch_int(sdir, "path_cost");
	info->designated_cost = fetch_int(sdir, "designated_cost");
	info->state = fetch_int(sdir, "state");
	info->top_change_ack = fetch_int(sdir, "change_ack");
	info->config_pending = fetch_int(sdir, "config_pending");
	fetch_tv(sdir, "message_age_timer", 
		 &info->message_age_timer_value);
	fetch_tv(sdir, "forward_delay_timer",
		 &info->forward_delay_timer_value);
	fetch_tv(sdir, "hold_timer",
		 &info->hold_timer_value);
	sysfs_close_directory(sdir);

	return 0;
#endif
}
Пример #8
0
void fetch_file_location (struct file_location *loc) {
  int x = fetch_int ();
  if (x == CODE_file_location_unavailable) {
    loc->dc = -1;
    loc->volume = fetch_long ();
    loc->local_id = fetch_int ();
    loc->secret = fetch_long ();
  } else {
    assert (x == CODE_file_location);
    loc->dc = fetch_int ();;
    loc->volume = fetch_long ();
    loc->local_id = fetch_int ();
    loc->secret = fetch_long ();
  }
}
Пример #9
0
void fetch_user_status (struct user_status *S) {
  int x = fetch_int ();
  switch (x) {
  case CODE_user_status_empty:
    S->online = 0;
    break;
  case CODE_user_status_online:
    S->online = 1;
    S->when = fetch_int ();
    break;
  case CODE_user_status_offline:
    S->online = -1;
    S->when = fetch_int ();
    break;
  default:
    assert (0);
  }
}
Пример #10
0
void fetch_photo_size (struct photo_size *S) {
  memset (S, 0, sizeof (*S));
  unsigned x = fetch_int ();
  assert (x == CODE_photo_size || x == CODE_photo_cached_size || x == CODE_photo_size_empty);
  S->type = fetch_str_dup ();
  if (x != CODE_photo_size_empty) {
    fetch_file_location (&S->loc);
    S->w = fetch_int ();
    S->h = fetch_int ();
    if (x == CODE_photo_size) {
      S->size = fetch_int ();
    } else {
      S->size = prefetch_strlen ();
      S->data = malloc (S->size);
      memcpy (S->data, fetch_str (S->size), S->size);
    }
  }
}
Пример #11
0
void fetch_notify_settings (void) {
  unsigned x = fetch_int ();
  assert (x == CODE_peer_notify_settings || x == CODE_peer_notify_settings_empty || x == CODE_peer_notify_settings_old);
  if (x == CODE_peer_notify_settings_old) {
    fetch_int (); // mute_until
    int l = prefetch_strlen ();
    fetch_str (l);
    fetch_bool (); // show_previews
    fetch_int (); // peer notify events
  }
  if (x == CODE_peer_notify_settings) {
    fetch_int (); // mute_until
    int l = prefetch_strlen ();
    fetch_str (l);
    fetch_bool (); // show_previews
    fetch_int (); // events_mask
  }
}
Пример #12
0
void fetch_photo (struct photo *P) {
  memset (P, 0, sizeof (*P));
  unsigned x = fetch_int ();
  assert (x == CODE_photo_empty || x == CODE_photo);
  P->id = fetch_long ();
  if (x == CODE_photo_empty) { return; }
  P->access_hash = fetch_long ();
  P->user_id = fetch_int ();
  P->date = fetch_int ();
  P->caption = fetch_str_dup ();
  fetch_geo (&P->geo);
  assert (fetch_int () == CODE_vector);
  P->sizes_num = fetch_int ();
  P->sizes = malloc (sizeof (struct photo_size) * P->sizes_num);
  int i;
  for (i = 0; i < P->sizes_num; i++) {
    fetch_photo_size (&P->sizes[i]);
  }
}
Пример #13
0
void fetch_geo (struct geo *G) {
  unsigned x = fetch_int ();
  if (x == CODE_geo_point) {
    G->longitude = fetch_double ();
    G->latitude = fetch_double ();
  } else {
    assert (x == CODE_geo_point_empty);
    G->longitude = 0;
    G->latitude = 0;
  }
}
Пример #14
0
void fetch_message (struct message *M) {
  memset (M, 0, sizeof (*M));
  unsigned x = fetch_int ();
  assert (x == CODE_message_empty || x == CODE_message || x == CODE_message_forwarded || x == CODE_message_service);
  M->id = fetch_int ();
  if (x == CODE_message_empty) {
    M->flags |= 1;
    return;
  }
  if (x == CODE_message_forwarded) {
    M->fwd_from_id = fetch_int ();
    M->fwd_date = fetch_int ();
  }
  M->from_id = fetch_int ();
  M->to_id = fetch_peer_id ();
  M->out = fetch_bool ();
  M->unread = fetch_bool ();
  M->date = fetch_int ();
  if (x == CODE_message_service) {
    M->service = 1;
    fetch_message_action (&M->action);
  } else {
    M->message = fetch_str_dup ();
    fetch_message_media (&M->media);
  }
}
Пример #15
0
/*
 * Get bridge parameters using either sysfs or old
 * ioctl.
 */
int br_get_bridge_info(const char *bridge, struct bridge_info *info)
{
	DIR *dir;
	char path[SYSFS_PATH_MAX];

	snprintf(path, SYSFS_PATH_MAX, SYSFS_CLASS_NET "%s/bridge", bridge);
	dir = opendir(path);
	if (dir == NULL) {
		dprintf("path '%s' is not a directory\n", path);
		goto fallback;
	}

	memset(info, 0, sizeof(*info));
	fetch_id(path, "root_id", &info->designated_root);
	fetch_id(path, "bridge_id", &info->bridge_id);
	info->root_path_cost = fetch_int(path, "root_path_cost");
	fetch_tv(path, "max_age", &info->max_age);
	fetch_tv(path, "hello_time", &info->hello_time);
	fetch_tv(path, "forward_delay", &info->forward_delay);
	fetch_tv(path, "max_age", &info->bridge_max_age);
	fetch_tv(path, "hello_time", &info->bridge_hello_time);
	fetch_tv(path, "forward_delay", &info->bridge_forward_delay);
	fetch_tv(path, "ageing_time", &info->ageing_time);
	fetch_tv(path, "hello_timer", &info->hello_timer_value);
	fetch_tv(path, "tcn_timer", &info->tcn_timer_value);
	fetch_tv(path, "topology_change_timer", 
		 &info->topology_change_timer_value);;
	fetch_tv(path, "gc_timer", &info->gc_timer_value);

	info->root_port = fetch_int(path, "root_port");
	info->stp_enabled = fetch_int(path, "stp_state");
	info->topology_change = fetch_int(path, "topology_change");
	info->topology_change_detected = fetch_int(path, "topology_change_detected");

	closedir(dir);
	return 0;

fallback:
	return old_get_bridge_info(bridge, info);
}
Пример #16
0
void fetch_video (struct video *V) {
  memset (V, 0, sizeof (*V));
  unsigned x = fetch_int ();
  V->id = fetch_long ();
  if (x == CODE_video_empty) { return; }
  V->access_hash = fetch_long ();
  V->user_id = fetch_int ();
  V->date = fetch_int ();
  V->caption = fetch_str_dup ();
  V->duration = fetch_int ();
  V->size = fetch_int ();
  fetch_photo_size (&V->thumb);
  V->dc_id = fetch_int ();
  V->w = fetch_int ();
  V->h = fetch_int ();
}
Пример #17
0
/*
 * Get bridge parameters using either sysfs or old
 * ioctl.
 */
int br_get_bridge_info(const char *bridge, struct bridge_info *info)
{
#ifndef HAVE_LIBSYSFS
	return old_get_bridge_info(bridge, info);
#else
	struct sysfs_directory *sdir;

	sdir = bridge_sysfs_directory(bridge, SYSFS_BRIDGE_ATTR);
	if (!sdir) 
		return old_get_bridge_info(bridge,info);

	memset(info, 0, sizeof(*info));
	fetch_id(sdir, "root_id", &info->designated_root);
	fetch_id(sdir, "bridge_id", &info->bridge_id);
	info->root_path_cost = fetch_int(sdir, "root_path_cost");
	fetch_tv(sdir, "max_age", &info->max_age);
	fetch_tv(sdir, "hello_time", &info->hello_time);
	fetch_tv(sdir, "forward_delay", &info->forward_delay);
	fetch_tv(sdir, "max_age", &info->bridge_max_age);
	fetch_tv(sdir, "hello_time", &info->bridge_hello_time);
	fetch_tv(sdir, "forward_delay", &info->bridge_forward_delay);
	fetch_tv(sdir, "ageing_time", &info->ageing_time);
	fetch_tv(sdir, "hello_timer", &info->hello_timer_value);
	fetch_tv(sdir, "tcn_timer", &info->tcn_timer_value);
	fetch_tv(sdir, "topology_change_timer", 
		 &info->topology_change_timer_value);;
	fetch_tv(sdir, "gc_timer", &info->gc_timer_value);

	info->root_port = fetch_int(sdir, "root_port");
	info->stp_enabled = fetch_int(sdir, "stp_state");
	info->topology_change = fetch_int(sdir, "topology_change");
	info->topology_change_detected = fetch_int(sdir, "topology_change_detected");
	sysfs_close_directory(sdir);

	return 0;
#endif
}
Пример #18
0
void fetch_user_full (struct user *U) {
  assert (fetch_int () == CODE_user_full);
  fetch_alloc_user ();
  unsigned x;
  assert (fetch_int () == (int)CODE_contacts_link);
  x = fetch_int ();
  assert (x == CODE_contacts_my_link_empty || x == CODE_contacts_my_link_requested || x == CODE_contacts_my_link_contact);
  U->flags &= ~(FLAG_USER_IN_CONTACT | FLAG_USER_OUT_CONTACT);
  if (x == CODE_contacts_my_link_contact) {
    U->flags |= FLAG_USER_IN_CONTACT; 
  }
  if (x == CODE_contacts_my_link_requested) {
    fetch_bool ();
  }
  x = fetch_int ();
  assert (x == CODE_contacts_foreign_link_unknown || x == CODE_contacts_foreign_link_requested || x == CODE_contacts_foreign_link_mutual);
  U->flags &= ~(FLAG_USER_IN_CONTACT | FLAG_USER_OUT_CONTACT);
  if (x == CODE_contacts_foreign_link_mutual) {
    U->flags |= FLAG_USER_IN_CONTACT | FLAG_USER_OUT_CONTACT; 
  }
  if (x == CODE_contacts_foreign_link_requested) {
    U->flags |= FLAG_USER_OUT_CONTACT;
    fetch_bool ();
  }
  fetch_alloc_user ();
  if (U->flags & FLAG_HAS_PHOTO) {
    free_photo (&U->photo);
  }
  fetch_photo (&U->photo);
  fetch_notify_settings ();
  U->blocked = fetch_int ();
  if (U->real_first_name) { free (U->real_first_name); }
  if (U->real_last_name) { free (U->real_last_name); }
  U->real_first_name = fetch_str_dup ();
  U->real_last_name = fetch_str_dup ();
}
Пример #19
0
void fetch_chat (struct chat *C) {
  unsigned x = fetch_int ();
  assert (x == CODE_chat_empty || x == CODE_chat || x == CODE_chat_forbidden);
  C->id = -fetch_int ();
  C->flags &= ~(FLAG_EMPTY | FLAG_DELETED | FLAG_FORBIDDEN | FLAG_CHAT_IN_CHAT);
  if (x == CODE_chat_empty) {
    C->flags |= FLAG_EMPTY;
    return;
  }
  if (x == CODE_chat_forbidden) {
    C->flags |= FLAG_FORBIDDEN;
  }
  if (C->title) { free (C->title); }
  if (C->print_title) { free (C->print_title); }
  C->title = fetch_str_dup ();
  C->print_title = strdup (C->title);
  char *s = C->print_title;
  while (*s) {
    if (*s == ' ') { *s = '_'; }
    s ++;
  }
  if (x == CODE_chat) {
    unsigned y = fetch_int ();
    if (y == CODE_chat_photo_empty) {
      C->photo_small.dc = -2;
      C->photo_big.dc = -2;
    } else {
      assert (y == CODE_chat_photo);
      fetch_file_location (&C->photo_small);
      fetch_file_location (&C->photo_big);
    }
    C->users_num = fetch_int ();
    C->date = fetch_int ();
    if (fetch_int () == (int)CODE_bool_true) {
      C->flags |= FLAG_CHAT_IN_CHAT;
    }
    C->version = fetch_int ();
  } else {
    C->photo_small.dc = -2;
    C->photo_big.dc = -2;
    C->users_num = -1;
    C->date = fetch_int ();
    C->version = -1;
  }
}
Пример #20
0
/* Get a time value out of sysfs */
static void fetch_tv(const char *dev, const char *name, 
		    struct timeval *tv)
{
	__jiffies_to_tv(tv, fetch_int(dev, name));
}
Пример #21
0
void replay_log_event (void) {
  int *start = rptr;
  in_replay_log = 1;
  assert (rptr < wptr);
  int op = *rptr;

  if (verbosity >= 2) {
    logprintf ("log_pos %lld, op 0x%08x\n", binlog_pos, op);
  }

  in_ptr = rptr;
  in_end = wptr;
  switch (op) {
  case LOG_START:
    rptr ++;
    break;
  case CODE_binlog_dc_option:
    in_ptr ++;
    {
      int id = fetch_int ();
      int l1 = prefetch_strlen ();
      char *name = fetch_str (l1);
      int l2 = prefetch_strlen ();
      char *ip = fetch_str (l2);
      int port = fetch_int ();
      if (verbosity) {
        logprintf ( "id = %d, name = %.*s ip = %.*s port = %d\n", id, l1, name, l2, ip, port);
      }
      alloc_dc (id, strndup (ip, l2), port);
    }
    rptr = in_ptr;
    break;
  case LOG_AUTH_KEY:
    rptr ++;
    {
      int num = *(rptr ++);
      assert (num >= 0 && num <= MAX_DC_ID);
      assert (DC_list[num]);
      DC_list[num]->auth_key_id = *(long long *)rptr;
      rptr += 2;
      memcpy (DC_list[num]->auth_key, rptr, 256);
      rptr += 64;
      DC_list[num]->flags |= 1;
    };
    break;
  case LOG_DEFAULT_DC:
    rptr ++;
    { 
      int num = *(rptr ++);
      assert (num >= 0 && num <= MAX_DC_ID);
      DC_working = DC_list[num];
      dc_working_num = num;
    }
    break;
  case LOG_OUR_ID:
    rptr ++;
    {
      our_id = *(rptr ++);
    }
    break;
  case LOG_DC_SIGNED:
    rptr ++;
    {
      int num = *(rptr ++);
      assert (num >= 0 && num <= MAX_DC_ID);
      assert (DC_list[num]);
      DC_list[num]->has_auth = 1;
    }
    break;
  case LOG_DC_SALT:
    rptr ++;
    {
      int num = *(rptr ++);
      assert (num >= 0 && num <= MAX_DC_ID);
      assert (DC_list[num]);
      DC_list[num]->server_salt = *(long long *)rptr;
      rptr += 2;
    };
    break;
/*  case CODE_user_empty:
  case CODE_user_self:
  case CODE_user_contact:
  case CODE_user_request:
  case CODE_user_foreign:
  case CODE_user_deleted:
    fetch_alloc_user ();
    rptr = in_ptr;
    break;*/
  case LOG_DH_CONFIG:
    get_dh_config_on_answer (0);
    rptr = in_ptr;
    break;
  case LOG_ENCR_CHAT_KEY:
    rptr ++;
    {
      peer_id_t id = MK_ENCR_CHAT (*(rptr ++));
      struct secret_chat *U = (void *)user_chat_get (id);
      assert (U);
      U->key_fingerprint = *(long long *)rptr;
      rptr += 2;
      memcpy (U->key, rptr, 256);
      rptr += 64;
    };
    break;
  case LOG_ENCR_CHAT_SEND_ACCEPT:
    rptr ++;
    {
      peer_id_t id = MK_ENCR_CHAT (*(rptr ++));
      struct secret_chat *U = (void *)user_chat_get (id);
      assert (U);
      U->key_fingerprint = *(long long *)rptr;
      rptr += 2;
      memcpy (U->key, rptr, 256);
      rptr += 64;
      if (!U->g_key) {
        U->g_key = malloc (256);
      }
      memcpy (U->g_key, rptr, 256);
      rptr += 64;
    };
    break;
  case LOG_ENCR_CHAT_SEND_CREATE:
    rptr ++;
    {
      peer_id_t id = MK_ENCR_CHAT (*(rptr ++));
      struct secret_chat *U = (void *)user_chat_get (id);
      assert (!U || !(U->flags & FLAG_CREATED));
      if (!U) {
        U = malloc (sizeof (peer_t));
        memset (U, 0, sizeof (peer_t));
        U->id = id;
        insert_encrypted_chat ((void *)U);
      }
      U->flags |= FLAG_CREATED;
      U->user_id = *(rptr ++);
      memcpy (U->key, rptr, 256);
      rptr += 64;
      if (!U->print_name) {  
        peer_t *P = user_chat_get (MK_USER (U->user_id));
        if (P) {
          U->print_name = create_print_name (U->id, "!", P->user.first_name, P->user.last_name, 0);
        } else {
          static char buf[100];
          sprintf (buf, "user#%d", U->user_id);
          U->print_name = create_print_name (U->id, "!", buf, 0, 0);
        }
      }
    };
    break;
  case LOG_ENCR_CHAT_DELETED:
    rptr ++;
    {
      peer_id_t id = MK_ENCR_CHAT (*(rptr ++));
      struct secret_chat *U = (void *)user_chat_get (id);
      if (!U) {
        U = malloc (sizeof (peer_t));
        memset (U, 0, sizeof (peer_t));
        U->id = id;
        insert_encrypted_chat ((void *)U);
      }
      U->flags |= FLAG_CREATED;
      U->state = sc_deleted;
    };
    break;
  case LOG_ENCR_CHAT_WAITING:
    rptr ++;
    {
      peer_id_t id = MK_ENCR_CHAT (*(rptr ++));
      struct secret_chat *U = (void *)user_chat_get (id);
      assert (U);
      U->state = sc_waiting;
      U->date = *(rptr ++);
      U->admin_id = *(rptr ++);
      U->user_id = *(rptr ++);
      U->access_hash = *(long long *)rptr;
      rptr += 2;
    };
    break;
  case LOG_ENCR_CHAT_REQUESTED:
    rptr ++;
    {
      peer_id_t id = MK_ENCR_CHAT (*(rptr ++));
      struct secret_chat *U = (void *)user_chat_get (id);
      if (!U) {
        U = malloc (sizeof (peer_t));
        memset (U, 0, sizeof (peer_t));
        U->id = id;
        insert_encrypted_chat ((void *)U);
      }
      U->flags |= FLAG_CREATED;
      U->state = sc_request;
      U->date = *(rptr ++);
      U->admin_id = *(rptr ++);
      U->user_id = *(rptr ++);
      U->access_hash = *(long long *)rptr;
      if (!U->print_name) {  
        peer_t *P = user_chat_get (MK_USER (U->user_id));
        if (P) {
          U->print_name = create_print_name (U->id, "!", P->user.first_name, P->user.last_name, 0);
        } else {
          static char buf[100];
          sprintf (buf, "user#%d", U->user_id);
          U->print_name = create_print_name (U->id, "!", buf, 0, 0);
        }
      }
      rptr += 2;
    };
    break;
  case LOG_ENCR_CHAT_OK:
    rptr ++;
    {
      peer_id_t id = MK_ENCR_CHAT (*(rptr ++));
      struct secret_chat *U = (void *)user_chat_get (id);
      assert (U);
      U->state = sc_ok;
    }
    break;
  case CODE_binlog_new_user:
    in_ptr ++;
    {
      peer_id_t id = MK_USER (fetch_int ());
      peer_t *_U = user_chat_get (id);
      if (!_U) {
        _U = malloc (sizeof (*_U));
        memset (_U, 0, sizeof (*_U));
        _U->id = id;
        insert_user (_U);
      } else {
        assert (!(_U->flags & FLAG_CREATED));
      }
      struct user *U = (void *)_U;
      U->flags |= FLAG_CREATED;
      if (get_peer_id (id) == our_id) {
        U->flags |= FLAG_USER_SELF;
      }
      U->first_name = fetch_str_dup ();
      U->last_name = fetch_str_dup ();
      U->print_name = create_print_name (U->id, U->first_name, U->last_name, 0, 0);
      U->access_hash = fetch_long ();
      U->phone = fetch_str_dup ();
      if (fetch_int ()) {
        U->flags |= FLAG_USER_CONTACT;
      }
    }
    rptr = in_ptr;
    break;
  case CODE_binlog_user_delete:
    rptr ++;
    {
      peer_id_t id = MK_USER (*(rptr ++));
      peer_t *U = user_chat_get (id);
      assert (U);
      U->flags |= FLAG_DELETED;
    }
    break;
  case CODE_binlog_set_user_access_token:
    rptr ++;
    {
      peer_id_t id = MK_USER (*(rptr ++));
      peer_t *U = user_chat_get (id);
      assert (U);
      U->user.access_hash = *(long long *)rptr;
      rptr += 2;
    }
    break;
  case CODE_binlog_set_user_phone:
    in_ptr ++;
    {
      peer_id_t id = MK_USER (fetch_int ());
      peer_t *U = user_chat_get (id);
      assert (U);
      if (U->user.phone) { free (U->user.phone); }
      U->user.phone = fetch_str_dup ();
    }
    rptr = in_ptr;
    break;
  case CODE_binlog_set_user_friend:
    rptr ++;
    {
      peer_id_t id = MK_USER (*(rptr ++));
      peer_t *U = user_chat_get (id);
      assert (U);
      int friend = *(rptr ++);
      if (friend) { U->flags |= FLAG_USER_CONTACT; }
      else { U->flags &= ~FLAG_USER_CONTACT; }
    }
    break;
  case CODE_binlog_user_full_photo:
    in_ptr ++;
    {
      peer_id_t id = MK_USER (fetch_int ());
      peer_t *U = user_chat_get (id);
      assert (U);
      if (U->flags & FLAG_HAS_PHOTO) {
        free_photo (&U->user.photo);
      }
      fetch_photo (&U->user.photo);
    }
    rptr = in_ptr;
    break;
  case CODE_binlog_user_blocked:
    rptr ++;
    {
      peer_id_t id = MK_USER (*(rptr ++));
      peer_t *U = user_chat_get (id);
      assert (U);
      U->user.blocked = *(rptr ++);
    }
    break;
  case CODE_binlog_set_user_full_name:
    in_ptr ++;
    {
      peer_id_t id = MK_USER (fetch_int ());
      peer_t *U = user_chat_get (id);
      assert (U);
      if (U->user.real_first_name) { free (U->user.real_first_name); }
      if (U->user.real_last_name) { free (U->user.real_last_name); }
      U->user.real_first_name = fetch_str_dup ();
      U->user.real_last_name = fetch_str_dup ();
    }
    rptr = in_ptr;
    break;
  case CODE_binlog_encr_chat_delete:
    rptr ++;
    {
      peer_id_t id = MK_ENCR_CHAT (*(rptr ++));
      peer_t *_U = user_chat_get (id);
      assert (_U);
      struct secret_chat *U = &_U->encr_chat;
      memset (U->key, 0, sizeof (U->key));
      U->flags |= FLAG_DELETED;
      U->state = sc_deleted;
      if (U->nonce) {
        memset (U->nonce, 0, 256);
        free (U->nonce);
        U->nonce = 0;
      }
      if (U->g_key) {
        memset (U->g_key, 0, 256);
        free (U->g_key);
        U->g_key = 0;
      }
    }
    break;
  case CODE_binlog_encr_chat_requested:
    rptr ++;
    {
      peer_id_t id = MK_ENCR_CHAT (*(rptr ++));
      peer_t *_U = user_chat_get (id);
      if (!_U) {
        _U = malloc (sizeof (*_U));
        memset (_U, 0, sizeof (*_U));
        _U->id = id;
        insert_encrypted_chat (_U);
      } else {
        assert (!(_U->flags & FLAG_CREATED));
      }
      struct secret_chat *U = (void *)_U;
      U->access_hash = *(long long *)rptr;
      rptr += 2;
      U->date = *(rptr ++);
      U->admin_id = *(rptr ++);
      U->user_id = *(rptr ++);

      peer_t *Us = user_chat_get (MK_USER (U->user_id));
      if (Us) {
        U->print_name = create_print_name (id, "!", Us->user.first_name, Us->user.last_name, 0);
      } else {
        static char buf[20];
        sprintf (buf, "user#%d", U->user_id);
        U->print_name = create_print_name (id, "!", buf, 0, 0);
      }
      U->g_key = malloc (256);
      U->nonce = malloc (256);
      memcpy (U->g_key, rptr, 256);
      rptr += 64;
      memcpy (U->nonce, rptr, 256);
      rptr += 64;

      U->flags |= FLAG_CREATED;
      U->state = sc_request;
    }
    break;
  case CODE_binlog_set_encr_chat_access_hash:
    rptr ++;
    {
      peer_id_t id = MK_ENCR_CHAT (*(rptr ++));
      peer_t *U = user_chat_get (id);
      assert (U);
      U->encr_chat.access_hash = *(long long *)rptr;
      rptr += 2;
    }
    break;
  case CODE_binlog_set_encr_chat_date:
    rptr ++;
    {
      peer_id_t id = MK_ENCR_CHAT (*(rptr ++));
      peer_t *U = user_chat_get (id);
      assert (U);
      U->encr_chat.date = *(rptr ++);
    }
    break;
  case CODE_binlog_set_encr_chat_state:
    rptr ++;
    {
      peer_id_t id = MK_ENCR_CHAT (*(rptr ++));
      peer_t *U = user_chat_get (id);
      assert (U);
      U->encr_chat.state = *(rptr ++);
    }
    break;
  case CODE_binlog_encr_chat_accepted:
    rptr ++;
    {
      peer_id_t id = MK_ENCR_CHAT (*(rptr ++));
      peer_t *_U = user_chat_get (id);
      assert (_U);
      struct secret_chat *U = &_U->encr_chat;
      if (!U->g_key) {
        U->g_key = malloc (256);
      }
      if (!U->nonce) {
        U->nonce = malloc (256);
      }
      memcpy (U->g_key, rptr, 256);
      rptr += 64;
      memcpy (U->nonce, rptr, 256);
      rptr += 64;
      U->key_fingerprint = *(long long *)rptr;
      rptr += 2;
      if (U->state == sc_waiting) {
        do_create_keys_end (U);
      }
      U->state = sc_ok;
    }
    break;
  case CODE_binlog_set_encr_chat_key:
    rptr ++;
    {
      peer_id_t id = MK_ENCR_CHAT (*(rptr ++));
      peer_t *_U = user_chat_get (id);
      assert (_U);
      struct secret_chat *U = &_U->encr_chat;
      memcpy (U->key, rptr, 256);
      rptr += 64;
      U->key_fingerprint = *(long long *)rptr;
      rptr += 2;
    }
    break;
  case CODE_binlog_set_dh_params:
    rptr ++;
    {
      if (encr_prime) { free (encr_prime); }
      encr_root = *(rptr ++);
      encr_prime = malloc (256);
      memcpy (encr_prime, rptr, 256);
      rptr += 64;
      encr_param_version = *(rptr ++);
    }
    break;
  case CODE_binlog_encr_chat_init:
    rptr ++;
    {
      peer_t *P = malloc (sizeof (*P));
      memset (P, 0, sizeof (*P));
      P->id = MK_ENCR_CHAT (*(rptr ++));
      assert (!user_chat_get (P->id));
      P->encr_chat.user_id = *(rptr ++);
      P->encr_chat.admin_id = our_id;
      insert_encrypted_chat (P);
      peer_t *Us = user_chat_get (MK_USER (P->encr_chat.user_id));
      assert (Us);
      P->print_name = create_print_name (P->id, "!", Us->user.first_name, Us->user.last_name, 0);
      memcpy (P->encr_chat.key, rptr, 256);
      rptr += 64;
      P->encr_chat.g_key = malloc (256);
      memcpy (P->encr_chat.g_key, rptr, 256);
      rptr += 64;
      P->flags |= FLAG_CREATED;
    }
    break;
  case CODE_binlog_set_pts:
    rptr ++;
    pts = *(rptr ++);
    break;
  case CODE_binlog_set_qts:
    rptr ++;
    qts = *(rptr ++);
    break;
  case CODE_binlog_set_date:
    rptr ++;
    last_date = *(rptr ++);
    break;
  case CODE_binlog_set_seq:
    rptr ++;
    seq = *(rptr ++);
    break;
  case CODE_binlog_chat_create:
    in_ptr ++;
    {
      peer_id_t id = MK_CHAT (fetch_int ());
      peer_t *_C = user_chat_get (id);
      if (!_C) {
        _C = malloc (sizeof (*_C));
        memset (_C, 0, sizeof (*_C));
        _C->id = id;
        insert_chat (_C);
      } else {
        assert (!(_C->flags & FLAG_CREATED));
      }
      struct chat *C = &_C->chat;
      C->flags = FLAG_CREATED | fetch_int ();
      C->title = fetch_str_dup ();
      C->print_title = create_print_name (id, C->title, 0, 0, 0);
      C->users_num = fetch_int ();
      C->date = fetch_int ();
      C->version = fetch_int ();
      fetch_data (&C->photo_big, sizeof (struct file_location));
      fetch_data (&C->photo_small, sizeof (struct file_location));
    };
    rptr = in_ptr;
    break;
  case CODE_binlog_chat_change_flags:
    rptr ++;
    {
      peer_t *C = user_chat_get (MK_CHAT (*(rptr ++)));
      assert (C && (C->flags & FLAG_CREATED));
      C->flags |= *(rptr ++);
      C->flags &= ~*(rptr ++);
    };
    break;
  case CODE_binlog_set_chat_title:
    in_ptr ++;
    {
      peer_t *_C = user_chat_get (MK_CHAT (fetch_int ()));
      assert (_C && (_C->flags & FLAG_CREATED));
      struct chat *C = &_C->chat;
      if (C->title) { free (C->title); }
      C->title = fetch_str_dup ();
      C->print_title = create_print_name (C->id, C->title, 0, 0, 0);
    };
    rptr = in_ptr;
    break;
  case CODE_binlog_set_chat_photo:
    in_ptr ++;
    {
      peer_t *C = user_chat_get (MK_CHAT (fetch_int ()));
      assert (C && (C->flags & FLAG_CREATED));
      fetch_data (&C->photo_big, sizeof (struct file_location));
      fetch_data (&C->photo_small, sizeof (struct file_location));
    };
    rptr = in_ptr;
    break;
  case CODE_binlog_set_chat_date:
    rptr ++;
    {
      peer_t *C = user_chat_get (MK_CHAT (*(rptr ++)));
      assert (C && (C->flags & FLAG_CREATED));
      C->chat.date = *(rptr ++);
    };
    break;
  case CODE_binlog_set_chat_version:
    rptr ++;
    {
      peer_t *C = user_chat_get (MK_CHAT (*(rptr ++)));
      assert (C && (C->flags & FLAG_CREATED));
      C->chat.version = *(rptr ++);
      C->chat.users_num = *(rptr ++);
    };
    break;
  case CODE_binlog_set_chat_admin:
    rptr ++;
    {
      peer_t *C = user_chat_get (MK_CHAT (*(rptr ++)));
      assert (C && (C->flags & FLAG_CREATED));
      C->chat.admin_id = *(rptr ++);
    };
    break;
  case CODE_binlog_set_chat_participants:
    rptr ++;
    {
      peer_t *C = user_chat_get (MK_CHAT (*(rptr ++)));
      assert (C && (C->flags & FLAG_CREATED));
      C->chat.user_list_version = *(rptr ++);
      C->chat.user_list_size = *(rptr ++);
      if (C->chat.user_list) { free (C->chat.user_list); }
      C->chat.user_list = malloc (12 * C->chat.user_list_size);
      memcpy (C->chat.user_list, rptr, 12 * C->chat.user_list_size);
      rptr += 3 * C->chat.user_list_size;
    };
    break;
  case CODE_binlog_chat_full_photo:
    in_ptr ++;
    {
      peer_id_t id = MK_CHAT (fetch_int ());
      peer_t *U = user_chat_get (id);
      assert (U && (U->flags & FLAG_CREATED));
      if (U->flags & FLAG_HAS_PHOTO) {
        free_photo (&U->chat.photo);
      }
      fetch_photo (&U->chat.photo);
    }
    rptr = in_ptr;
    break;
  case CODE_binlog_add_chat_participant:
    rptr ++;
    {
      peer_id_t id = MK_CHAT (*(rptr ++));
      peer_t *_C = user_chat_get (id);
      assert (_C && (_C->flags & FLAG_CREATED));
      struct chat *C = &_C->chat;

      int version = *(rptr ++);
      int user = *(rptr ++);
      int inviter = *(rptr ++);
      int date = *(rptr ++);
      assert (C->user_list_version < version);

      int i;
      for (i = 0; i < C->user_list_size; i++) {
        assert (C->user_list[i].user_id != user);
      }
      C->user_list_size ++;
      C->user_list = realloc (C->user_list, 12 * C->user_list_size);
      C->user_list[C->user_list_size - 1].user_id = user;
      C->user_list[C->user_list_size - 1].inviter_id = inviter;
      C->user_list[C->user_list_size - 1].date = date;
      C->user_list_version = version;
    }
    break;
  case CODE_binlog_del_chat_participant:
    rptr ++;
    {
      peer_id_t id = MK_CHAT (*(rptr ++));
      peer_t *_C = user_chat_get (id);
      assert (_C && (_C->flags & FLAG_CREATED));
      struct chat *C = &_C->chat;

      int version = *(rptr ++);
      int user = *(rptr ++);
      assert (C->user_list_version < version);

      int i;
      for (i = 0; i < C->user_list_size; i++) {
        if (C->user_list[i].user_id == user) {
          struct chat_user t;
          t = C->user_list[i];
          C->user_list[i] = C->user_list[C->user_list_size - 1];
          C->user_list[C->user_list_size - 1] = t;
        }
      }
      assert (C->user_list[C->user_list_size - 1].user_id == user);
      C->user_list_size --;
      C->user_list = realloc (C->user_list, 12 * C->user_list_size);
      C->user_list_version = version;
    }
    break;
  case CODE_binlog_create_message_text:
  case CODE_binlog_send_message_text:
    in_ptr ++;
    {
      long long id;
      if (op == CODE_binlog_create_message_text) {
        id = fetch_int ();
      } else {
        id = fetch_long ();
      }
      struct message *M = message_get (id);
      if (!M) {
        M = malloc (sizeof (*M));
        memset (M, 0, sizeof (*M));
        M->id = id;
        message_insert_tree (M);
        messages_allocated ++;
      } else {
        assert (!(M->flags & FLAG_CREATED));
      }
      M->flags |= FLAG_CREATED;
      M->from_id = MK_USER (fetch_int ());
      int t = fetch_int ();
      if (t == PEER_ENCR_CHAT) {
        M->flags |= FLAG_ENCRYPTED;
      }
      M->to_id = set_peer_id (t, fetch_int ());
      M->date = fetch_int ();
      
      int l = prefetch_strlen ();
      M->message = malloc (l + 1);
      memcpy (M->message, fetch_str (l), l);
      M->message[l] = 0;
      M->message_len = l;

      if (t == PEER_ENCR_CHAT) {
        M->media.type = CODE_decrypted_message_media_empty;
      } else {
        M->media.type = CODE_message_media_empty;
      }
      M->unread = 1;
      M->out = get_peer_id (M->from_id) == our_id;

      message_insert (M);
      if (op == CODE_binlog_send_message_text) {
        message_insert_unsent (M);
        M->flags |= FLAG_PENDING;
      }
    }
    rptr = in_ptr;
    break;
  case CODE_binlog_create_message_text_fwd:
    in_ptr ++;
    {
      int id = fetch_int ();
      struct message *M = message_get (id);
      if (!M) {
        M = malloc (sizeof (*M));
        memset (M, 0, sizeof (*M));
        M->id = id;
        message_insert_tree (M);
        messages_allocated ++;
      } else {
        assert (!(M->flags & FLAG_CREATED));
      }
      M->flags |= FLAG_CREATED;
      M->from_id = MK_USER (fetch_int ());
      int t = fetch_int ();
      M->to_id = set_peer_id (t, fetch_int ());
      M->date = fetch_int ();
      M->fwd_from_id = MK_USER (fetch_int ());
      M->fwd_date = fetch_int ();
      
      int l = prefetch_strlen ();
      M->message = malloc (l + 1);
      memcpy (M->message, fetch_str (l), l);
      M->message[l] = 0;
      M->message_len = l;
      
      M->media.type = CODE_message_media_empty;
      M->unread = 1;
      M->out = get_peer_id (M->from_id) == our_id;

      message_insert (M);
    }
    rptr = in_ptr;
    break;
  case CODE_binlog_create_message_media:
    in_ptr ++;
    {
      int id = fetch_int ();
      struct message *M = message_get (id);
      if (!M) {
        M = malloc (sizeof (*M));
        memset (M, 0, sizeof (*M));
        M->id = id;
        message_insert_tree (M);
        messages_allocated ++;
      } else {
        assert (!(M->flags & FLAG_CREATED));
      }
      M->flags |= FLAG_CREATED;
      M->from_id = MK_USER (fetch_int ());
      int t = fetch_int ();
      M->to_id = set_peer_id (t, fetch_int ());
      M->date = fetch_int ();
      
      int l = prefetch_strlen ();
      M->message = malloc (l + 1);
      memcpy (M->message, fetch_str (l), l);
      M->message[l] = 0;
      M->message_len = l;

      fetch_message_media (&M->media);
      M->unread = 1;
      M->out = get_peer_id (M->from_id) == our_id;

      message_insert (M);
    }
    rptr = in_ptr;
    break;
  case CODE_binlog_create_message_media_encr:
    in_ptr ++;
    {
      long long id = fetch_long ();
      struct message *M = message_get (id);
      if (!M) {
        M = malloc (sizeof (*M));
        memset (M, 0, sizeof (*M));
        M->id = id;
        message_insert_tree (M);
        messages_allocated ++;
      } else {
        assert (!(M->flags & FLAG_CREATED));
      }
      M->flags |= FLAG_CREATED | FLAG_ENCRYPTED;
      M->from_id = MK_USER (fetch_int ());
      int t = fetch_int ();
      M->to_id = set_peer_id (t, fetch_int ());
      M->date = fetch_int ();
      
      int l = prefetch_strlen ();
      M->message = malloc (l + 1);
      memcpy (M->message, fetch_str (l), l);
      M->message[l] = 0;
      M->message_len = l;

      fetch_message_media_encrypted (&M->media);
      fetch_encrypted_message_file (&M->media);

      M->unread = 1;
      M->out = get_peer_id (M->from_id) == our_id;

      message_insert (M);
    }
    rptr = in_ptr;
    break;
  case CODE_binlog_create_message_media_fwd:
    in_ptr ++;
    {
      int id = fetch_int ();
      struct message *M = message_get (id);
      if (!M) {
        M = malloc (sizeof (*M));
        memset (M, 0, sizeof (*M));
        M->id = id;
        message_insert_tree (M);
        messages_allocated ++;
      } else {
        assert (!(M->flags & FLAG_CREATED));
      }
      M->flags |= FLAG_CREATED;
      M->from_id = MK_USER (fetch_int ());
      int t = fetch_int ();
      M->to_id = set_peer_id (t, fetch_int ());
      M->date = fetch_int ();
      M->fwd_from_id = MK_USER (fetch_int ());
      M->fwd_date = fetch_int ();
      
      int l = prefetch_strlen ();
      M->message = malloc (l + 1);
      memcpy (M->message, fetch_str (l), l);
      M->message[l] = 0;
      M->message_len = l;

      fetch_message_media (&M->media);
      M->unread = 1;
      M->out = get_peer_id (M->from_id) == our_id;

      message_insert (M);
    }
    rptr = in_ptr;
    break;
  case CODE_binlog_create_message_service:
    in_ptr ++;
    {
      int id = fetch_int ();
      struct message *M = message_get (id);
      if (!M) {
        M = malloc (sizeof (*M));
        memset (M, 0, sizeof (*M));
        M->id = id;
        message_insert_tree (M);
        messages_allocated ++;
      } else {
        assert (!(M->flags & FLAG_CREATED));
      }
      M->flags |= FLAG_CREATED;
      M->from_id = MK_USER (fetch_int ());
      int t = fetch_int ();
      M->to_id = set_peer_id (t, fetch_int ());
      M->date = fetch_int ();

      fetch_message_action (&M->action);
      M->unread = 1;
      M->out = get_peer_id (M->from_id) == our_id;
      M->service = 1;

      message_insert (M);
    }
    rptr = in_ptr;
    break;
  case CODE_binlog_create_message_service_encr:
    in_ptr ++;
    {
      long long id = fetch_long ();
      struct message *M = message_get (id);
      if (!M) {
        M = malloc (sizeof (*M));
        memset (M, 0, sizeof (*M));
        M->id = id;
        message_insert_tree (M);
        messages_allocated ++;
      } else {
        assert (!(M->flags & FLAG_CREATED));
      }
      M->flags |= FLAG_CREATED | FLAG_ENCRYPTED;
      M->from_id = MK_USER (fetch_int ());
      int t = fetch_int ();
      M->to_id = set_peer_id (t, fetch_int ());
      M->date = fetch_int ();

      fetch_message_action_encrypted (&M->action); 
      
      M->unread = 1;
      M->out = get_peer_id (M->from_id) == our_id;
      M->service = 1;

      message_insert (M);
    }
    rptr = in_ptr;
    break;
  case CODE_binlog_create_message_service_fwd:
    in_ptr ++;
    {
      int id = fetch_int ();
      struct message *M = message_get (id);
      if (!M) {
        M = malloc (sizeof (*M));
        memset (M, 0, sizeof (*M));
        M->id = id;
        message_insert_tree (M);
        messages_allocated ++;
      } else {
        assert (!(M->flags & FLAG_CREATED));
      }
      M->flags |= FLAG_CREATED;
      M->from_id = MK_USER (fetch_int ());
      int t = fetch_int ();
      M->to_id = set_peer_id (t, fetch_int ());
      M->date = fetch_int ();
      M->fwd_from_id = MK_USER (fetch_int ());
      M->fwd_date = fetch_int ();
      fetch_message_action (&M->action);
      M->unread = 1;
      M->out = get_peer_id (M->from_id) == our_id;
      M->service = 1;

      message_insert (M);
    }
    rptr = in_ptr;
    break;
  case CODE_binlog_set_unread:
    rptr ++;
    {
      struct message *M = message_get (*(rptr ++));
      assert (M);
      M->unread = 0;
    }
    break;
  case CODE_binlog_set_message_sent:
    rptr ++;
    {
      struct message *M = message_get (*(long long *)rptr);
      rptr += 2;
      assert (M);
      message_remove_unsent (M);
      M->flags &= ~FLAG_PENDING;
    }
    break;
  case CODE_binlog_set_msg_id:
    rptr ++;
    {
      struct message *M = message_get (*(long long *)rptr);
      rptr += 2;
      assert (M);
      if (M->flags & FLAG_PENDING) {
        message_remove_unsent (M);
        M->flags &= ~FLAG_PENDING;
      }
      message_remove_tree (M);
      message_del_peer (M);
      M->id = *(rptr ++);
      if (message_get (M->id)) {
        free_message (M);
        free (M);
      } else {
        message_insert_tree (M);
        message_add_peer (M);
      }
    }
    break;
  case CODE_binlog_delete_msg:
    rptr ++;
    {
      struct message *M = message_get (*(long long *)rptr);
      rptr += 2;
      assert (M);
      if (M->flags & FLAG_PENDING) {
        message_remove_unsent (M);
        M->flags &= ~FLAG_PENDING;
      }
      message_remove_tree (M);
      message_del_peer (M);
      free_message (M);
      free (M);
    }
    break;
  case CODE_update_user_photo:
  case CODE_update_user_name:
    work_update_binlog ();
    rptr = in_ptr;
    break;
  default:
    logprintf ("Unknown logevent [0x%08x] 0x%08x [0x%08x] at %lld\n", *(rptr - 1), op, *(rptr + 1), binlog_pos);

    assert (0);
  }
Пример #22
0
int format_first(ErlNifEnv* env, ErlNifBinary* result, char** fmt_start_ptr, ERL_NIF_TERM* items) {
  char* fmt_start = *fmt_start_ptr;
  char* fmt_iter = fmt_start;
  int consumed = 0;
  int fmt_long = 0;
  int arg_type = ARG_NONE;

  // started at the end of line
  if (*fmt_iter == 0) return 0;

  // find first covnertion spec character or string end
  while (*fmt_iter != 0) {
    if (*fmt_iter == '%') {
      // Ignore "%%" as it does not take any arguments
      if (*(fmt_iter+1) == '%')
        fmt_iter += 2;
      else {
        arg_type = -1;
        break;
      };
    }
    else fmt_iter += 1;
  }

  // find convertion specifier
  while (*fmt_iter != 0){
    if (index("dic", *fmt_iter) != NULL) {
      arg_type = fmt_long?ARG_LONG:ARG_INT;
      consumed++;
      fmt_iter++;
      break;
    };
    if (index("ouxX", *fmt_iter) != NULL) {
      arg_type = fmt_long?ARG_ULONG:ARG_UINT;
      consumed++;
      fmt_iter++;
      break;
    };
    if (index("eEfFgGaA", *fmt_iter) != NULL) {
      arg_type = ARG_DOUBLE;
      consumed++;
      fmt_iter++;
      break;
    };
    if (*fmt_iter == 's') {
      arg_type = ARG_STRING;
      consumed++;
      fmt_iter++;
      break;
    };

    // Extra argument is consumed from input
    if (*fmt_iter == '*') consumed++;

    // We don't support references to argument positions -> return error
    if (*fmt_iter == '$') return -1;

    // Support long
    if (*fmt_iter == 'l') fmt_long = 1;

    // At last, go to next character
    fmt_iter++;
  };

  // convertion spec opened but not closed
  if (arg_type < 0) return -1;
  // Too much stars in spec
  if (consumed > 3) return -1;

  // To not copy part of format, just set zero where scan has ended, then return original value back
  char kept_fmt_byte = *fmt_iter;
  *fmt_iter = 0;

  // We don't really know how much memory will be used, so we call asprintf to let it allocate as much as it needs
  // Do not forget to call free() in the end!
  char* formatted = NULL;
  char* stringbuf;

  int e1, e2;

  switch (arg_type) {
    case ARG_NONE:
      asprintf(&formatted, fmt_start);
      break;
    // Numeric types: see macros above
    case ARG_INT:    fetch_asprintf(fetch_int);
    case ARG_LONG:   fetch_asprintf(fetch_long);
    case ARG_UINT:   fetch_asprintf(fetch_uint);
    case ARG_ULONG:  fetch_asprintf(fetch_ulong);
    case ARG_DOUBLE: fetch_asprintf(fetch_double);

    case ARG_STRING: // This cannot be handled by that simple macros because of allocation inside fetch_string
      switch (consumed) {
        case 1:
          asprintf(&formatted, fmt_start, stringbuf = fetch_string(env, items));
          free(stringbuf);
          break;
        case 2:
          e1 = fetch_int(env, items);
          asprintf(&formatted, fmt_start, e1, stringbuf = fetch_string(env, items));
          free(stringbuf);
          break;
        case 3:
          e1 = fetch_int(env, items);
          e2 = fetch_int(env, items);
          asprintf(&formatted, fmt_start, e1, e2, stringbuf = fetch_string(env, items));
          free(stringbuf);
          break;
      };
      break;
  };

  // Put back saved byte and move format pointer
  *fmt_iter = kept_fmt_byte;
  *fmt_start_ptr = fmt_iter;

  // asprintf did not run or returned error
  if (formatted == NULL || formatted < 0) return -2;

  // remember where we start copying formatted part
  int oldsize = result->size;

  // Here we are sure formatted contains zero-terminated string, so strlen is safe
  int part_length = strlen(formatted);
  enif_realloc_binary(result, oldsize + part_length);

  // Do copy from formatted to result buffer
  char* copy_dest = (char*)result->data + oldsize;
  memcpy(copy_dest, formatted, part_length);

  // free memory allocated by asprintf
  free(formatted);

  // Return number of elements read from items
  return consumed;
};
Пример #23
0
void fetch_user (struct user *U) {
  unsigned x = fetch_int ();
  assert (x == CODE_user_empty || x == CODE_user_self || x == CODE_user_contact ||  x == CODE_user_request || x == CODE_user_foreign || x == CODE_user_deleted);
  U->id = fetch_int ();
  U->flags &= ~(FLAG_EMPTY | FLAG_DELETED | FLAG_USER_SELF | FLAG_USER_FOREIGN | FLAG_USER_CONTACT);
  if (x == CODE_user_empty) {
    U->flags |= FLAG_EMPTY;
    return;
  }
  if (x == CODE_user_self) {
    assert (!our_id || (our_id == U->id));
    if (!our_id) {
      our_id = U->id;
      write_auth_file ();
    }
  }
  if (U->first_name) { free (U->first_name); }
  if (U->last_name) { free (U->last_name); }
  if (U->print_name) { free (U->print_name); }
  U->first_name = fetch_str_dup ();
  U->last_name = fetch_str_dup ();
  if (!strlen (U->first_name)) {
    if (!strlen (U->last_name)) {
      U->print_name = strdup ("none");
    } else {
      U->print_name = strdup (U->last_name);
    }
  } else {
    if (!strlen (U->last_name)) {
      U->print_name = strdup (U->first_name);
    } else {
      U->print_name = malloc (strlen (U->first_name) + strlen (U->last_name) + 2);
      sprintf (U->print_name, "%s_%s", U->first_name, U->last_name);
    }
  }
  char *s = U->print_name;
  while (*s) {
    if (*s == ' ') { *s = '_'; }
    s++;
  }
  int cc = 0;
  while (1) {
    int ok = 1;
    int i;
    for (i = 0; i < user_num + chat_num; i++) {
      if (Peers[i] != (void *)U && Peers[i]->print_name && !strcmp (Peers[i]->print_name, U->print_name)) {
        ok = 0;
        break;
      }
    }
    if (ok) {
      break;
    }
    cc ++;
    assert (cc <= 99);
    if (cc == 1) {
      int l = strlen (U->print_name);
      char *s = malloc (l + 3);
      memcpy (s, U->print_name, l);
      s[l + 2] = 0;
      s[l] = '#';
      s[l + 1] = '1';
      free (U->print_name);
      U->print_name = s;
    } else if (cc == 10) {
      int l = strlen (U->print_name);
      char *s = malloc (l + 2);
      memcpy (s, U->print_name, l);
      s[l + 1] = 0;
      s[l] = '0';
      s[l - 1] = '1';
      free (U->print_name);
      U->print_name = s;
    } else {
      int l = strlen (U->print_name);
      U->print_name[l - 1] ++;
      if (U->print_name[l - 1] > '9') {
        U->print_name[l - 1] = '0';
        U->print_name[l - 2] ++;
      }
    }
  }
  if (x == CODE_user_deleted) {
    U->flags |= FLAG_DELETED;
    return;
  }
  if (x == CODE_user_self) {
    U->flags |= FLAG_USER_SELF;
  } else {
    U->access_hash = fetch_long ();
  }
  if (x == CODE_user_foreign) {
    U->flags |= FLAG_USER_FOREIGN;
    U->phone = 0;
  } else {
    if (U->phone) { free (U->phone); }
    U->phone = fetch_str_dup ();
  }
  //logprintf ("name = %s, surname = %s, phone = %s\n", U->first_name, U->last_name, U->phone);
  unsigned y = fetch_int ();
  //fprintf (stderr, "y = 0x%08x\n", y);
  if (y == CODE_user_profile_photo_empty) {
    U->photo_small.dc = -2;
    U->photo_big.dc = -2;
  } else {
    assert (y == CODE_user_profile_photo || y == 0x990d1493);
    if (y == CODE_user_profile_photo) {
      fetch_long ();
    }
    fetch_file_location (&U->photo_small);
    fetch_file_location (&U->photo_big);
  }
  fetch_user_status (&U->status);
  if (x == CODE_user_self) {
    assert (fetch_int () == (int)CODE_bool_false);
  }
  if (x == CODE_user_contact) {
    U->flags |= FLAG_USER_CONTACT;
  }
}
Пример #24
0
void fetch_chat_full (struct chat *C) {
  unsigned x = fetch_int ();
  assert (x == CODE_messages_chat_full);
  assert (fetch_int () == CODE_chat_full); 
  C->id = -fetch_int ();
  C->flags &= ~(FLAG_EMPTY | FLAG_DELETED | FLAG_FORBIDDEN | FLAG_CHAT_IN_CHAT);
  x = fetch_int ();
  if (x == CODE_chat_participants) {
    assert (fetch_int () == -C->id);
    C->admin_id =  fetch_int ();
    assert (fetch_int () == CODE_vector);
    if (C->users) {
      free (C->users);
    }
    C->users_num = fetch_int ();
    C->users = malloc (sizeof (struct chat_user) * C->users_num);
    int i;
    for (i = 0; i < C->users_num; i++) {
      assert (fetch_int () == (int)CODE_chat_participant);
      C->users[i].user_id = fetch_int ();
      C->users[i].inviter_id = fetch_int ();
      C->users[i].date = fetch_int ();
    }
    C->version = fetch_int ();
  } else {
    C->flags |= FLAG_FORBIDDEN;
    assert (x == CODE_chat_participants_forbidden);
  }
  if (C->flags & FLAG_HAS_PHOTO) {
    free_photo (&C->photo);
  }
  fetch_photo (&C->photo);
  C->flags |= FLAG_HAS_PHOTO;
  fetch_notify_settings ();

  int n, i;
  assert (fetch_int () == CODE_vector);
  n = fetch_int ();
  for (i = 0; i < n; i++) {
    fetch_alloc_chat ();
  }
  assert (fetch_int () == CODE_vector);
  n = fetch_int ();
  for (i = 0; i < n; i++) {
    fetch_alloc_user ();
  }
}