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); } }
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); } }
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 (); } }
/* * 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); }
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; }
/* * 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); }
/* * 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 }
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 (); } }
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); } }
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); } } }
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 } }
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]); } }
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; } }
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); } }
/* * 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); }
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 (); }
/* * 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 }
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 (); }
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; } }
/* 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)); }
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); }
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; };
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; } }
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 (); } }