diff --git a/binlog.c b/binlog.c
index ffe00bc..30cc8a2 100644
--- a/binlog.c
+++ b/binlog.c
@@ -22,6 +22,11 @@ int *rptr;
 int *wptr;
 extern int test_dc;
 
+extern int pts;
+extern int qts;
+extern int last_date;
+extern int seq;
+
 #define MAX_LOG_EVENT_SIZE (1 << 17)
 
 char *get_binlog_file_name (void);
@@ -522,9 +527,25 @@ void replay_log_event (void) {
       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_update_user_photo:
   case CODE_update_user_name:
-    work_update (0, 0);
+    work_update_binlog ();
     rptr = in_ptr;
     break;
   default:
@@ -905,3 +926,31 @@ void bl_do_encr_chat_init (int id, int user_id, unsigned char random[], unsigned
   memcpy (ev + 67, g_a, 256);
   add_log_event (ev, 524);
 }
+
+void bl_do_set_pts (int pts) {
+  int *ev = alloc_log_event (8);
+  ev[0] = CODE_binlog_set_pts;
+  ev[1] = pts;
+  add_log_event (ev, 8);
+}
+
+void bl_do_set_qts (int qts) {
+  int *ev = alloc_log_event (8);
+  ev[0] = CODE_binlog_set_qts;
+  ev[1] = qts;
+  add_log_event (ev, 8);
+}
+
+void bl_do_set_date (int date) {
+  int *ev = alloc_log_event (8);
+  ev[0] = CODE_binlog_set_date;
+  ev[1] = date;
+  add_log_event (ev, 8);
+}
+
+void bl_do_set_seq (int seq) {
+  int *ev = alloc_log_event (8);
+  ev[0] = CODE_binlog_set_seq;
+  ev[1] = seq;
+  add_log_event (ev, 8);
+}
diff --git a/binlog.h b/binlog.h
index 1ce2a37..bf15775 100644
--- a/binlog.h
+++ b/binlog.h
@@ -36,6 +36,10 @@
 #define CODE_binlog_set_encr_chat_key 0x179df2d4
 #define CODE_binlog_set_dh_params 0x20ba46bc
 #define CODE_binlog_encr_chat_init 0x939cd1c7
+#define CODE_binlog_set_pts 0x844e4c1c
+#define CODE_binlog_set_qts 0x3cf22b79
+#define CODE_binlog_set_date 0x33dfe392
+#define CODE_binlog_set_seq 0xb9294837
 
 void *alloc_log_event (int l);
 void replay_log (void);
@@ -69,4 +73,9 @@ void bl_do_encr_chat_init (int id, int user_id, unsigned char random[], unsigned
 void bl_do_dc_signed (int id);
 void bl_do_set_working_dc (int num);
 void bl_do_set_dh_params (int root, unsigned char prime[], int version);
+
+void bl_do_set_pts (int pts);
+void bl_do_set_qts (int qts);
+void bl_do_set_seq (int seq);
+void bl_do_set_date (int date);
 #endif
diff --git a/loop.c b/loop.c
index 8680850..4ac7a54 100644
--- a/loop.c
+++ b/loop.c
@@ -260,6 +260,7 @@ void read_auth_file (void) {
 int pts, qts, seq, last_date;
 
 void read_state_file (void) {
+  if (binlog_enabled) { return; }
   int state_file_fd = open (get_state_filename (), O_CREAT | O_RDWR, 0600);
   if (state_file_fd < 0) {
     return;
@@ -282,6 +283,7 @@ void read_state_file (void) {
 }
 
 void write_state_file (void) {
+  if (binlog_enabled) { return; }
   static int wseq;
   static int wpts;
   static int wqts;
diff --git a/mtproto-client.c b/mtproto-client.c
index da1ca8a..4b4399e 100644
--- a/mtproto-client.c
+++ b/mtproto-client.c
@@ -669,6 +669,7 @@ void fetch_pts (void) {
   } else {
     pts ++;
   }
+  bl_do_set_pts (pts);
 }
 
 void fetch_qts (void) {
@@ -685,12 +686,14 @@ void fetch_qts (void) {
   } else {
     qts ++;
   }
+  bl_do_set_qts (qts);
 }
 
 void fetch_date (void) {
   int p = fetch_int ();
   if (p > last_date) {
     last_date = p;
+    bl_do_set_date (last_date);
   }
 }
 
@@ -699,9 +702,72 @@ void fetch_seq (void) {
   if (x > seq + 1) {
     logprintf ("Hole in seq: seq = %d, x = %d\n", seq, x);
     //do_get_difference ();
+    //seq = x;
+  } else if (x == seq + 1) {
     seq = x;
-  } else if (x >= seq + 1) {
-    seq = x;
+    bl_do_set_seq (seq);
+  }
+}
+
+void work_update_binlog (void) {
+  unsigned op = fetch_int ();
+  switch (op) {
+  case CODE_update_user_name:
+    {
+      peer_id_t user_id = MK_USER (fetch_int ());
+      peer_t *UC = user_chat_get (user_id);
+      if (UC) {
+        struct user *U = &UC->user;
+        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 ();
+        U->print_name = create_print_name (U->id, U->first_name, U->last_name, 0, 0);
+      } else {
+        int l;
+        l = prefetch_strlen ();
+        fetch_str (l);
+        l = prefetch_strlen ();
+        fetch_str (l);
+      }
+    }
+    break;
+  case CODE_update_user_photo:
+    {
+      peer_id_t user_id = MK_USER (fetch_int ());
+      peer_t *UC = user_chat_get (user_id);
+      fetch_date ();
+      if (UC) {
+        struct user *U = &UC->user;
+        
+        unsigned y = fetch_int ();
+        if (y == CODE_user_profile_photo_empty) {
+          U->photo_id = 0;
+          U->photo_big.dc = -2;
+          U->photo_small.dc = -2;
+        } else {
+          assert (y == CODE_user_profile_photo);
+          U->photo_id = fetch_long ();
+          fetch_file_location (&U->photo_small);
+          fetch_file_location (&U->photo_big);
+        }
+      } else {
+        struct file_location t;
+        unsigned y = fetch_int ();
+        if (y == CODE_user_profile_photo_empty) {
+        } else {
+          assert (y == CODE_user_profile_photo);
+          fetch_long (); // photo_id
+          fetch_file_location (&t);
+          fetch_file_location (&t);
+        }
+      }
+      fetch_bool ();
+    }
+    break;
+  default:
+    assert (0);
   }
 }
 
diff --git a/mtproto-client.h b/mtproto-client.h
index 9e44df2..2a7d7e8 100644
--- a/mtproto-client.h
+++ b/mtproto-client.h
@@ -24,4 +24,5 @@ void on_start (void);
 long long encrypt_send_message (struct connection *c, int *msg, int msg_ints, int useful);
 void dc_authorize (struct dc *DC);
 void work_update (struct connection *c, long long msg_id);
+void work_update_binlog (void);
 #endif
diff --git a/queries.c b/queries.c
index 1539791..5c72769 100644
--- a/queries.c
+++ b/queries.c
@@ -2409,17 +2409,19 @@ int difference_got;
 int seq, pts, qts, last_date;
 int get_state_on_answer (struct query *q UU) {
   assert (fetch_int () == (int)CODE_updates_state);
-  pts = fetch_int ();
-  qts = fetch_int ();
-  last_date = fetch_int ();
-  seq = fetch_int ();
+  bl_do_set_pts (fetch_int ());
+  bl_do_set_qts (fetch_int ());
+  bl_do_set_date (fetch_int ());
+  bl_do_set_seq (fetch_int ());
   unread_messages = fetch_int ();
   write_state_file ();
   difference_got = 1;
   return 0;
 }
 
+int get_difference_active;
 int get_difference_on_answer (struct query *q UU) {
+  get_difference_active = 0;
   unsigned x = fetch_int ();
   if (x == CODE_updates_difference_empty) {
     fetch_date ();
@@ -2463,10 +2465,10 @@ int get_difference_on_answer (struct query *q UU) {
       fetch_alloc_user ();
     }
     assert (fetch_int () == (int)CODE_updates_state);
-    pts = fetch_int ();
-    qts = fetch_int ();
-    last_date = fetch_int ();
-    seq = fetch_int ();
+    bl_do_set_pts (fetch_int ());
+    bl_do_set_qts (fetch_int ());
+    bl_do_set_date (fetch_int ());
+    bl_do_set_seq (fetch_int ());
     unread_messages = fetch_int ();
     write_state_file ();
     for (i = 0; i < ml_pos; i++) {
@@ -2492,6 +2494,7 @@ struct query_methods get_difference_methods = {
 };
 
 void do_get_difference (void) {
+  get_difference_active = 1;
   difference_got = 0;
   clear_packet ();
   do_insert_header ();