2013-10-23 18:26:17 +04:00
|
|
|
/*
|
|
|
|
This file is part of telegram-client.
|
|
|
|
|
|
|
|
Telegram-client is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 2 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
Telegram-client is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this telegram-client. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
Copyright Vitaly Valtman 2013
|
|
|
|
*/
|
2013-11-10 02:47:19 +04:00
|
|
|
|
2013-10-12 00:52:20 +04:00
|
|
|
#include <assert.h>
|
2013-11-01 03:18:34 +04:00
|
|
|
#include <string.h>
|
2014-08-06 19:45:46 +02:00
|
|
|
#include "constants.h"
|
2013-10-12 00:52:20 +04:00
|
|
|
#include "structures.h"
|
2013-10-13 14:18:08 +04:00
|
|
|
#include "telegram.h"
|
|
|
|
#include "tree.h"
|
2013-10-18 23:30:24 +04:00
|
|
|
#include "loop.h"
|
2013-11-02 14:14:30 +04:00
|
|
|
#include <openssl/aes.h>
|
|
|
|
#include <openssl/sha.h>
|
2013-11-06 02:24:26 +04:00
|
|
|
#include "queries.h"
|
2013-11-15 04:08:24 +04:00
|
|
|
#include "binlog.h"
|
2014-08-06 19:45:46 +02:00
|
|
|
#include "net.h"
|
2013-11-02 14:14:30 +04:00
|
|
|
|
|
|
|
#define sha1 SHA1
|
|
|
|
|
2013-11-25 20:13:36 +04:00
|
|
|
static int id_cmp (struct message *M1, struct message *M2);
|
|
|
|
#define peer_cmp(a,b) (cmp_peer_id (a->id, b->id))
|
2014-01-31 20:03:40 +04:00
|
|
|
#define peer_cmp_name(a,b) (strcmp (a->print_name, b->print_name))
|
2013-11-25 20:13:36 +04:00
|
|
|
DEFINE_TREE(peer,peer_t *,peer_cmp,0)
|
2014-01-31 20:03:40 +04:00
|
|
|
DEFINE_TREE(peer_by_name,peer_t *,peer_cmp_name,0)
|
2013-11-25 20:13:36 +04:00
|
|
|
DEFINE_TREE(message,struct message *,id_cmp,0)
|
|
|
|
|
|
|
|
struct message message_list = {
|
|
|
|
.next_use = &message_list,
|
|
|
|
.prev_use = &message_list
|
|
|
|
};
|
|
|
|
|
2013-12-02 21:19:08 +04:00
|
|
|
int verbosity;
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
void fetch_skip_photo (struct mtproto_connection *mtp);
|
2013-11-15 04:08:24 +04:00
|
|
|
|
2014-10-03 14:23:15 +02:00
|
|
|
#define code_assert(x) if (!(x)) { fatal ("Can not parse at line %d\n", __LINE__); assert (0); return -1; }
|
2013-12-02 21:19:08 +04:00
|
|
|
#define code_try(x) if ((x) == -1) { return -1; }
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
* Fetch simple structures (immediate fetch into buffer)
|
|
|
|
*
|
|
|
|
*/
|
2013-11-21 23:35:49 +04:00
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
int fetch_file_location (struct mtproto_connection *mtp, struct file_location *loc) {
|
|
|
|
int x = fetch_int (mtp);
|
2013-11-21 23:35:49 +04:00
|
|
|
code_assert (x == CODE_file_location_unavailable || x == CODE_file_location);
|
|
|
|
|
|
|
|
if (x == CODE_file_location_unavailable) {
|
|
|
|
loc->dc = -1;
|
2014-08-06 19:45:46 +02:00
|
|
|
loc->volume = fetch_long (mtp);
|
|
|
|
loc->local_id = fetch_int (mtp);
|
|
|
|
loc->secret = fetch_long (mtp);
|
2013-11-21 23:35:49 +04:00
|
|
|
} else {
|
2014-08-06 19:45:46 +02:00
|
|
|
loc->dc = fetch_int (mtp);
|
|
|
|
loc->volume = fetch_long (mtp);
|
|
|
|
loc->local_id = fetch_int (mtp);
|
|
|
|
loc->secret = fetch_long (mtp);
|
2013-11-15 04:08:24 +04:00
|
|
|
}
|
2013-11-21 23:35:49 +04:00
|
|
|
return 0;
|
2013-11-15 04:08:24 +04:00
|
|
|
}
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
int fetch_user_status (struct mtproto_connection *mtp, struct user_status *S) {
|
|
|
|
unsigned x = fetch_int (mtp);
|
2013-11-21 23:35:49 +04:00
|
|
|
code_assert (x == CODE_user_status_empty || x == CODE_user_status_online || x == CODE_user_status_offline);
|
2013-10-12 00:52:20 +04:00
|
|
|
switch (x) {
|
|
|
|
case CODE_user_status_empty:
|
|
|
|
S->online = 0;
|
2013-11-21 23:35:49 +04:00
|
|
|
S->when = 0;
|
2013-10-12 00:52:20 +04:00
|
|
|
break;
|
|
|
|
case CODE_user_status_online:
|
|
|
|
S->online = 1;
|
2014-08-06 19:45:46 +02:00
|
|
|
S->when = fetch_int (mtp);
|
2013-10-12 00:52:20 +04:00
|
|
|
break;
|
|
|
|
case CODE_user_status_offline:
|
|
|
|
S->online = -1;
|
2014-08-06 19:45:46 +02:00
|
|
|
S->when = fetch_int (mtp);
|
2013-10-12 00:52:20 +04:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
assert (0);
|
|
|
|
}
|
2013-11-21 23:35:49 +04:00
|
|
|
return 0;
|
2013-10-12 00:52:20 +04:00
|
|
|
}
|
|
|
|
|
2013-12-02 21:19:08 +04:00
|
|
|
/*
|
|
|
|
*
|
|
|
|
* Skip simple structures
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
int fetch_skip_file_location (struct mtproto_connection *mtp) {
|
|
|
|
int x = fetch_int (mtp);
|
2013-12-02 21:19:08 +04:00
|
|
|
code_assert (x == CODE_file_location_unavailable || x == CODE_file_location);
|
|
|
|
|
|
|
|
if (x == CODE_file_location_unavailable) {
|
2014-08-06 19:45:46 +02:00
|
|
|
mtp->in_ptr += 5;
|
2013-12-02 21:19:08 +04:00
|
|
|
} else {
|
2014-08-06 19:45:46 +02:00
|
|
|
mtp->in_ptr += 6;
|
2013-12-02 21:19:08 +04:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
int fetch_skip_user_status (struct mtproto_connection *mtp) {
|
|
|
|
unsigned x = fetch_int (mtp);
|
2013-12-02 21:19:08 +04:00
|
|
|
code_assert (x == CODE_user_status_empty || x == CODE_user_status_online || x == CODE_user_status_offline);
|
|
|
|
if (x != CODE_user_status_empty) {
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_int (mtp);
|
2013-12-02 21:19:08 +04:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-09-01 21:25:41 +02:00
|
|
|
char *create_print_name (struct binlog *bl, peer_id_t id, const char *a1, const char *a2, const char *a3, const char *a4) {
|
2013-11-04 21:34:27 +04:00
|
|
|
const char *d[4];
|
|
|
|
d[0] = a1; d[1] = a2; d[2] = a3; d[3] = a4;
|
|
|
|
static char buf[10000];
|
2013-11-30 01:43:56 +04:00
|
|
|
buf[0] = 0;
|
2013-11-04 21:34:27 +04:00
|
|
|
int i;
|
|
|
|
int p = 0;
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
|
if (d[i] && strlen (d[i])) {
|
2014-01-10 18:37:56 +04:00
|
|
|
p += tsnprintf (buf + p, 9999 - p, "%s%s", p ? "_" : "", d[i]);
|
2013-11-04 21:34:27 +04:00
|
|
|
assert (p < 9990);
|
2013-10-13 14:18:08 +04:00
|
|
|
}
|
|
|
|
}
|
2013-11-04 21:34:27 +04:00
|
|
|
char *s = buf;
|
2013-10-13 14:18:08 +04:00
|
|
|
while (*s) {
|
|
|
|
if (*s == ' ') { *s = '_'; }
|
|
|
|
s++;
|
|
|
|
}
|
2013-11-04 21:34:27 +04:00
|
|
|
s = buf;
|
2013-11-25 21:16:34 +04:00
|
|
|
int fl = strlen (s);
|
2013-10-25 02:56:11 +04:00
|
|
|
int cc = 0;
|
|
|
|
while (1) {
|
2014-09-01 21:25:41 +02:00
|
|
|
peer_t *P = peer_lookup_name (bl, s);
|
2014-02-07 19:40:39 +04:00
|
|
|
if (!P || !cmp_peer_id (P->id, id)) {
|
2013-10-25 02:56:11 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
cc ++;
|
2013-11-25 21:16:34 +04:00
|
|
|
assert (cc <= 9999);
|
2014-01-10 18:37:56 +04:00
|
|
|
tsnprintf (s + fl, 9999 - fl, "#%d", cc);
|
2013-10-25 02:56:11 +04:00
|
|
|
}
|
2014-01-10 15:32:57 +04:00
|
|
|
return tstrdup (s);
|
2013-11-04 21:34:27 +04:00
|
|
|
}
|
|
|
|
|
2013-12-02 21:19:08 +04:00
|
|
|
/*
|
|
|
|
*
|
|
|
|
* Fetch with log event
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2014-09-06 21:33:46 +02:00
|
|
|
long long fetch_user_photo (struct mtproto_connection *mtp, struct tgl_user *U) {
|
2014-08-06 19:45:46 +02:00
|
|
|
unsigned x = fetch_int (mtp);
|
2013-11-21 23:35:49 +04:00
|
|
|
code_assert (x == CODE_user_profile_photo || x == CODE_user_profile_photo_old || x == CODE_user_profile_photo_empty);
|
|
|
|
if (x == CODE_user_profile_photo_empty) {
|
2014-08-22 17:05:29 +02:00
|
|
|
bl_do_set_user_profile_photo (mtp->bl, mtp, U, 0, 0, 0);
|
2013-11-21 23:35:49 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
long long photo_id = 1;
|
|
|
|
if (x == CODE_user_profile_photo) {
|
2014-08-06 19:45:46 +02:00
|
|
|
photo_id = fetch_long (mtp);
|
2013-11-21 23:35:49 +04:00
|
|
|
}
|
|
|
|
struct file_location big;
|
|
|
|
struct file_location small;
|
2014-08-06 19:45:46 +02:00
|
|
|
code_try (fetch_file_location (mtp, &small));
|
|
|
|
code_try (fetch_file_location (mtp, &big));
|
2013-11-21 23:35:49 +04:00
|
|
|
|
2014-08-22 17:05:29 +02:00
|
|
|
bl_do_set_user_profile_photo (mtp->bl, mtp, U, photo_id, &big, &small);
|
2013-11-21 23:35:49 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-10-10 17:28:10 +02:00
|
|
|
void sanitize_alias(char *buffer)
|
|
|
|
{
|
|
|
|
size_t len = strlen(buffer);
|
|
|
|
gchar *curr;
|
|
|
|
while ((curr = g_utf8_strchr(buffer, len, '\n'))) {
|
|
|
|
*curr = 0x20;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-27 09:37:35 +02:00
|
|
|
int user_get_alias(peer_t *user, char *buffer, int maxlen)
|
2014-06-22 23:36:52 +02:00
|
|
|
{
|
|
|
|
char* last_name = (user->user.last_name && strlen(user->user.last_name)) ? user->user.last_name : "";
|
|
|
|
char* first_name = (user->user.first_name && strlen(user->user.first_name)) ? user->user.first_name : "";
|
2014-10-10 17:28:10 +02:00
|
|
|
sanitize_alias (last_name);
|
|
|
|
sanitize_alias(first_name);
|
2014-06-22 23:36:52 +02:00
|
|
|
if (strlen(first_name) && strlen(last_name)) {
|
|
|
|
return snprintf(buffer, maxlen, "%s %s", first_name, last_name);
|
|
|
|
} else if (strlen(first_name)) {
|
|
|
|
return snprintf(buffer, maxlen, "%s", first_name);
|
|
|
|
} else if (strlen(last_name)) {
|
|
|
|
return snprintf(buffer, maxlen, "%s", last_name);
|
|
|
|
} else {
|
|
|
|
return snprintf(buffer, maxlen, "%d", get_peer_id(user->id));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-06 21:33:46 +02:00
|
|
|
int fetch_user (struct mtproto_connection *mtp, struct tgl_user *U) {
|
2014-09-01 21:25:41 +02:00
|
|
|
struct telegram *instance = mtp->instance;
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
unsigned x = fetch_int (mtp);
|
2013-11-21 23:35:49 +04:00
|
|
|
code_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);
|
2014-08-06 19:45:46 +02:00
|
|
|
U->id = MK_USER (fetch_int (mtp));
|
2013-11-04 21:34:27 +04:00
|
|
|
if (x == CODE_user_empty) {
|
2013-11-15 04:08:24 +04:00
|
|
|
return 0;
|
2013-11-04 21:34:27 +04:00
|
|
|
}
|
2013-11-21 23:35:49 +04:00
|
|
|
|
2013-11-04 21:34:27 +04:00
|
|
|
if (x == CODE_user_self) {
|
2014-09-01 21:25:41 +02:00
|
|
|
assert (!instance->our_id || (instance->our_id == get_peer_id (U->id)));
|
|
|
|
if (!instance->our_id) {
|
2014-08-22 17:05:29 +02:00
|
|
|
bl_do_set_our_id (mtp->bl, mtp, get_peer_id (U->id));
|
2014-07-26 11:55:45 +02:00
|
|
|
// TODO: What to do here?
|
|
|
|
//write_auth_file ();
|
2013-11-04 21:34:27 +04:00
|
|
|
}
|
|
|
|
}
|
2013-11-21 23:35:49 +04:00
|
|
|
|
|
|
|
int new = 0;
|
|
|
|
if (!(U->flags & FLAG_CREATED)) {
|
|
|
|
new = 1;
|
2013-11-15 04:08:24 +04:00
|
|
|
}
|
2013-11-21 23:35:49 +04:00
|
|
|
if (new) {
|
2014-08-06 19:45:46 +02:00
|
|
|
int l1 = prefetch_strlen (mtp);
|
2013-12-02 21:19:08 +04:00
|
|
|
code_assert (l1 >= 0);
|
2014-08-06 19:45:46 +02:00
|
|
|
char *s1 = fetch_str (mtp, l1);
|
|
|
|
int l2 = prefetch_strlen (mtp);
|
2013-12-02 21:19:08 +04:00
|
|
|
code_assert (l2 >= 0);
|
2014-08-06 19:45:46 +02:00
|
|
|
char *s2 = fetch_str (mtp, l2);
|
2013-11-21 23:35:49 +04:00
|
|
|
|
|
|
|
if (x == CODE_user_deleted && !(U->flags & FLAG_DELETED)) {
|
2014-08-22 17:05:29 +02:00
|
|
|
bl_do_new_user (mtp->bl, mtp, get_peer_id (U->id), s1, l1, s2, l2, 0, 0, 0, 0);
|
|
|
|
bl_do_user_delete (mtp->bl, mtp, U);
|
2013-11-15 04:08:24 +04:00
|
|
|
}
|
2013-11-21 23:35:49 +04:00
|
|
|
if (x != CODE_user_deleted) {
|
|
|
|
long long access_token = 0;
|
|
|
|
if (x != CODE_user_self) {
|
2014-08-06 19:45:46 +02:00
|
|
|
access_token = fetch_long (mtp);
|
2013-11-21 23:35:49 +04:00
|
|
|
}
|
|
|
|
int phone_len = 0;
|
|
|
|
char *phone = 0;
|
|
|
|
if (x != CODE_user_foreign) {
|
2014-08-06 19:45:46 +02:00
|
|
|
phone_len = prefetch_strlen (mtp);
|
2013-12-02 21:19:08 +04:00
|
|
|
code_assert (phone_len >= 0);
|
2014-08-06 19:45:46 +02:00
|
|
|
phone = fetch_str (mtp, phone_len);
|
2013-11-21 23:35:49 +04:00
|
|
|
}
|
2014-08-22 17:05:29 +02:00
|
|
|
bl_do_new_user (mtp->bl, mtp, get_peer_id (U->id), s1, l1, s2, l2, access_token, phone, phone_len, x == CODE_user_contact);
|
2014-08-06 19:45:46 +02:00
|
|
|
if (fetch_user_photo (mtp, U) < 0) { return -1; }
|
2013-11-21 23:35:49 +04:00
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
if (fetch_user_status (mtp, &U->status) < 0) { return -1; }
|
2013-11-21 23:35:49 +04:00
|
|
|
if (x == CODE_user_self) {
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_bool (mtp);
|
2013-11-16 17:04:53 +04:00
|
|
|
}
|
2013-11-15 04:08:24 +04:00
|
|
|
}
|
2013-11-21 23:35:49 +04:00
|
|
|
} else {
|
2014-08-06 19:45:46 +02:00
|
|
|
int l1 = prefetch_strlen (mtp);
|
|
|
|
char *s1 = fetch_str (mtp, l1);
|
|
|
|
int l2 = prefetch_strlen (mtp);
|
|
|
|
char *s2 = fetch_str (mtp, l2);
|
2013-11-21 23:35:49 +04:00
|
|
|
|
2014-08-22 17:05:29 +02:00
|
|
|
bl_do_set_user_name (mtp->bl, mtp, U, s1, l1, s2, l2);
|
2013-11-21 23:35:49 +04:00
|
|
|
|
|
|
|
if (x == CODE_user_deleted && !(U->flags & FLAG_DELETED)) {
|
2014-08-22 17:05:29 +02:00
|
|
|
bl_do_user_delete (mtp->bl, mtp, U);
|
2013-11-15 04:08:24 +04:00
|
|
|
}
|
2013-11-21 23:35:49 +04:00
|
|
|
if (x != CODE_user_deleted) {
|
|
|
|
if (x != CODE_user_self) {
|
2014-08-22 17:05:29 +02:00
|
|
|
bl_do_set_user_access_token (mtp->bl, mtp, U, fetch_long (mtp));
|
2013-11-21 23:35:49 +04:00
|
|
|
}
|
|
|
|
if (x != CODE_user_foreign) {
|
2014-08-06 19:45:46 +02:00
|
|
|
int l = prefetch_strlen (mtp);
|
|
|
|
char *s = fetch_str (mtp, l);
|
2014-08-22 17:05:29 +02:00
|
|
|
bl_do_set_user_phone (mtp->bl, mtp, U, s, l);
|
2013-11-21 23:35:49 +04:00
|
|
|
}
|
2014-08-06 19:45:46 +02:00
|
|
|
if (fetch_user_photo (mtp, U) < 0) { return -1; }
|
2013-11-21 23:35:49 +04:00
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_user_status (mtp, &U->status);
|
2013-11-21 23:35:49 +04:00
|
|
|
if (x == CODE_user_self) {
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_bool (mtp);
|
2013-11-21 23:35:49 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (x == CODE_user_contact) {
|
2014-08-22 17:05:29 +02:00
|
|
|
bl_do_set_user_friend (mtp->bl, mtp, U, 1);
|
2013-11-21 23:35:49 +04:00
|
|
|
} else {
|
2014-08-22 17:05:29 +02:00
|
|
|
bl_do_set_user_friend (mtp->bl, mtp, U, 0);
|
2013-11-21 23:35:49 +04:00
|
|
|
}
|
2013-10-25 23:50:10 +04:00
|
|
|
}
|
2013-10-12 00:52:20 +04:00
|
|
|
}
|
2013-11-21 23:35:49 +04:00
|
|
|
return 0;
|
2013-10-12 00:52:20 +04:00
|
|
|
}
|
2013-10-13 14:18:08 +04:00
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
void fetch_encrypted_chat (struct mtproto_connection *mtp, struct secret_chat *U) {
|
2014-09-01 21:25:41 +02:00
|
|
|
struct telegram *instance = mtp->instance;
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
unsigned x = fetch_int (mtp);
|
2013-11-02 21:01:22 +04:00
|
|
|
assert (x == CODE_encrypted_chat_empty || x == CODE_encrypted_chat_waiting || x == CODE_encrypted_chat_requested || x == CODE_encrypted_chat || x == CODE_encrypted_chat_discarded);
|
2014-08-06 19:45:46 +02:00
|
|
|
U->id = MK_ENCR_CHAT (fetch_int (mtp));
|
2013-11-02 21:01:22 +04:00
|
|
|
if (x == CODE_encrypted_chat_empty) {
|
|
|
|
return;
|
|
|
|
}
|
2013-11-21 23:35:49 +04:00
|
|
|
int new = !(U->flags & FLAG_CREATED);
|
|
|
|
|
2013-11-02 21:01:22 +04:00
|
|
|
if (x == CODE_encrypted_chat_discarded) {
|
2013-11-21 23:35:49 +04:00
|
|
|
if (new) {
|
2014-10-03 14:23:15 +02:00
|
|
|
warning ("Unknown chat in deleted state. May be we forgot something...\n");
|
2013-11-21 23:35:49 +04:00
|
|
|
return;
|
2013-11-04 21:34:27 +04:00
|
|
|
}
|
2014-08-22 17:05:29 +02:00
|
|
|
bl_do_encr_chat_delete (mtp->bl, mtp, U);
|
2014-07-26 11:55:45 +02:00
|
|
|
|
2014-09-06 01:04:57 +02:00
|
|
|
write_secret_chat_file (instance, instance->secret_path);
|
2013-11-02 21:01:22 +04:00
|
|
|
return;
|
|
|
|
}
|
2013-11-04 21:34:27 +04:00
|
|
|
|
2013-11-21 23:35:49 +04:00
|
|
|
static char g_key[256];
|
|
|
|
static char nonce[256];
|
|
|
|
if (new) {
|
2014-08-06 19:45:46 +02:00
|
|
|
long long access_hash = fetch_long (mtp);
|
|
|
|
int date = fetch_int (mtp);
|
|
|
|
int admin_id = fetch_int (mtp);
|
2014-09-01 21:25:41 +02:00
|
|
|
int user_id = fetch_int (mtp) + admin_id - instance->our_id;
|
2013-11-21 23:35:49 +04:00
|
|
|
|
|
|
|
if (x == CODE_encrypted_chat_waiting) {
|
2014-10-03 14:23:15 +02:00
|
|
|
warning ("Unknown chat in waiting state. May be we forgot something...\n");
|
2013-11-21 23:35:49 +04:00
|
|
|
return;
|
2013-11-02 21:01:22 +04:00
|
|
|
}
|
2013-11-21 23:35:49 +04:00
|
|
|
if (x == CODE_encrypted_chat_requested || x == CODE_encrypted_chat) {
|
|
|
|
memset (g_key, 0, sizeof (g_key));
|
|
|
|
memset (nonce, 0, sizeof (nonce));
|
2013-11-02 21:01:22 +04:00
|
|
|
}
|
2013-11-21 23:35:49 +04:00
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
int l = prefetch_strlen (mtp);
|
|
|
|
char *s = fetch_str (mtp, l);
|
2014-10-03 14:23:15 +02:00
|
|
|
if (l != 256) { debug ("l = %d\n", l); }
|
2013-11-04 21:34:27 +04:00
|
|
|
if (l < 256) {
|
2013-11-21 23:35:49 +04:00
|
|
|
memcpy (g_key + 256 - l, s, l);
|
2013-11-04 21:34:27 +04:00
|
|
|
} else {
|
2013-11-21 23:35:49 +04:00
|
|
|
memcpy (g_key, s + (l - 256), 256);
|
2013-11-04 21:34:27 +04:00
|
|
|
}
|
2013-11-21 23:35:49 +04:00
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
/*l = prefetch_strlen (mtp);
|
|
|
|
s = fetch_str (mtp, l);
|
2014-10-03 14:23:15 +02:00
|
|
|
if (l != 256) { debug ("l = %d\n", l); }
|
2013-11-04 21:34:27 +04:00
|
|
|
if (l < 256) {
|
2013-11-21 23:35:49 +04:00
|
|
|
memcpy (nonce + 256 - l, s, l);
|
2013-11-04 21:34:27 +04:00
|
|
|
} else {
|
2013-11-21 23:35:49 +04:00
|
|
|
memcpy (nonce, s + (l - 256), 256);
|
2013-12-24 04:57:01 +04:00
|
|
|
}*/
|
2013-11-21 23:35:49 +04:00
|
|
|
|
|
|
|
if (x == CODE_encrypted_chat) {
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_long (mtp); // fingerprint
|
2013-11-21 23:35:49 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (x == CODE_encrypted_chat) {
|
2014-10-03 14:23:15 +02:00
|
|
|
warning ("Unknown chat in ok state. May be we forgot something...\n");
|
2013-11-21 23:35:49 +04:00
|
|
|
return;
|
2013-11-15 04:08:24 +04:00
|
|
|
}
|
2013-11-21 23:35:49 +04:00
|
|
|
|
2014-08-22 17:05:29 +02:00
|
|
|
bl_do_encr_chat_requested (mtp->bl, mtp, U, access_hash, date, admin_id, user_id, (void *)g_key, (void *)nonce);
|
2014-09-06 01:04:57 +02:00
|
|
|
write_secret_chat_file (instance, instance->secret_path);
|
2013-11-02 21:01:22 +04:00
|
|
|
} else {
|
2014-08-22 17:05:29 +02:00
|
|
|
bl_do_set_encr_chat_access_hash (mtp->bl, mtp, U, fetch_long (mtp));
|
|
|
|
bl_do_set_encr_chat_date (mtp->bl, mtp, U, fetch_int (mtp));
|
2014-08-06 19:45:46 +02:00
|
|
|
if (fetch_int (mtp) != U->admin_id) {
|
2014-10-03 14:23:15 +02:00
|
|
|
failure ("Changed admin in secret chat. WTF?\n");
|
2013-11-21 23:35:49 +04:00
|
|
|
return;
|
|
|
|
}
|
2014-09-01 21:25:41 +02:00
|
|
|
if (U->user_id != U->admin_id + fetch_int (mtp) - instance->our_id) {
|
2014-10-03 14:23:15 +02:00
|
|
|
failure ("Changed partner in secret chat. WTF?\n");
|
2013-11-21 23:35:49 +04:00
|
|
|
return;
|
2013-11-02 21:01:22 +04:00
|
|
|
}
|
2013-11-21 23:35:49 +04:00
|
|
|
if (x == CODE_encrypted_chat_waiting) {
|
2014-08-22 17:05:29 +02:00
|
|
|
bl_do_set_encr_chat_state (mtp->bl, mtp, U, sc_waiting);
|
2014-09-06 01:04:57 +02:00
|
|
|
write_secret_chat_file (instance, instance->secret_path);
|
2013-11-21 23:35:49 +04:00
|
|
|
return; // We needed only access hash from here
|
|
|
|
}
|
|
|
|
|
|
|
|
if (x == CODE_encrypted_chat_requested || x == CODE_encrypted_chat) {
|
|
|
|
memset (g_key, 0, sizeof (g_key));
|
|
|
|
memset (nonce, 0, sizeof (nonce));
|
2013-11-02 21:01:22 +04:00
|
|
|
}
|
2013-11-21 23:35:49 +04:00
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
int l = prefetch_strlen (mtp);
|
|
|
|
char *s = fetch_str (mtp, l);
|
2014-10-03 14:23:15 +02:00
|
|
|
if (l != 256) { debug ("l = %d\n", l); }
|
2013-11-04 21:34:27 +04:00
|
|
|
if (l < 256) {
|
2013-11-21 23:35:49 +04:00
|
|
|
memcpy (g_key + 256 - l, s, l);
|
2013-11-04 21:34:27 +04:00
|
|
|
} else {
|
2013-11-21 23:35:49 +04:00
|
|
|
memcpy (g_key, s + (l - 256), 256);
|
2013-11-04 21:34:27 +04:00
|
|
|
}
|
2013-11-21 23:35:49 +04:00
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
/*l = prefetch_strlen (mtp);
|
|
|
|
s = fetch_str (mtp, l);
|
2014-10-03 14:23:15 +02:00
|
|
|
if (l != 256) { debug ("l = %d\n", l); }
|
2013-11-04 21:34:27 +04:00
|
|
|
if (l < 256) {
|
2013-11-21 23:35:49 +04:00
|
|
|
memcpy (nonce + 256 - l, s, l);
|
2013-11-04 21:34:27 +04:00
|
|
|
} else {
|
2013-11-21 23:35:49 +04:00
|
|
|
memcpy (nonce, s + (l - 256), 256);
|
2013-12-24 04:57:01 +04:00
|
|
|
}*/
|
2013-11-21 23:35:49 +04:00
|
|
|
|
|
|
|
if (x == CODE_encrypted_chat_requested) {
|
|
|
|
return; // Duplicate?
|
2013-11-06 02:24:26 +04:00
|
|
|
}
|
2014-08-22 17:05:29 +02:00
|
|
|
bl_do_encr_chat_accepted (mtp->bl, mtp, U, (void *)g_key, (void *)nonce, fetch_long (mtp));
|
2013-11-02 21:01:22 +04:00
|
|
|
}
|
2014-09-06 01:04:57 +02:00
|
|
|
write_secret_chat_file (instance, instance->secret_path);
|
2013-11-02 21:01:22 +04:00
|
|
|
}
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
void fetch_notify_settings (struct mtproto_connection *mtp);
|
2014-09-06 21:33:46 +02:00
|
|
|
void fetch_user_full (struct mtproto_connection *mtp, struct tgl_user *U) {
|
2014-08-06 19:45:46 +02:00
|
|
|
assert (fetch_int (mtp) == CODE_user_full);
|
|
|
|
fetch_alloc_user (mtp);
|
2013-10-25 21:29:02 +04:00
|
|
|
unsigned x;
|
2014-08-06 19:45:46 +02:00
|
|
|
assert (fetch_int (mtp) == (int)CODE_contacts_link);
|
|
|
|
x = fetch_int (mtp);
|
2013-10-25 21:29:02 +04:00
|
|
|
assert (x == CODE_contacts_my_link_empty || x == CODE_contacts_my_link_requested || x == CODE_contacts_my_link_contact);
|
|
|
|
if (x == CODE_contacts_my_link_requested) {
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_bool (mtp);
|
2013-10-25 21:29:02 +04:00
|
|
|
}
|
2014-08-06 19:45:46 +02:00
|
|
|
x = fetch_int (mtp);
|
2013-10-25 21:29:02 +04:00
|
|
|
assert (x == CODE_contacts_foreign_link_unknown || x == CODE_contacts_foreign_link_requested || x == CODE_contacts_foreign_link_mutual);
|
2013-10-25 21:33:18 +04:00
|
|
|
if (x == CODE_contacts_foreign_link_requested) {
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_bool (mtp);
|
2013-10-25 21:29:02 +04:00
|
|
|
}
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_alloc_user (mtp);
|
2013-11-21 23:35:49 +04:00
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
int *start = mtp->in_ptr;
|
2014-09-20 23:20:14 +02:00
|
|
|
fetch_photo (mtp, &U->photo);
|
2014-08-22 17:05:29 +02:00
|
|
|
bl_do_set_user_full_photo (mtp->bl, mtp, U, start, 4 * (mtp->in_ptr - start));
|
2013-11-21 23:35:49 +04:00
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_notify_settings (mtp);
|
2013-11-21 23:35:49 +04:00
|
|
|
|
2014-08-22 17:05:29 +02:00
|
|
|
bl_do_set_user_blocked (mtp->bl, mtp, U, fetch_bool (mtp));
|
2014-08-06 19:45:46 +02:00
|
|
|
int l1 = prefetch_strlen (mtp);
|
|
|
|
char *s1 = fetch_str (mtp, l1);
|
|
|
|
int l2 = prefetch_strlen (mtp);
|
|
|
|
char *s2 = fetch_str (mtp, l2);
|
2014-08-22 17:05:29 +02:00
|
|
|
bl_do_set_user_real_name (mtp->bl, mtp, U, s1, l1, s2, l2);
|
2013-10-25 21:29:02 +04:00
|
|
|
}
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
void fetch_chat (struct mtproto_connection *mtp, struct chat *C) {
|
|
|
|
unsigned x = fetch_int (mtp);
|
2013-10-13 16:30:53 +04:00
|
|
|
assert (x == CODE_chat_empty || x == CODE_chat || x == CODE_chat_forbidden);
|
2014-08-06 19:45:46 +02:00
|
|
|
C->id = MK_CHAT (fetch_int (mtp));
|
2013-10-13 16:30:53 +04:00
|
|
|
if (x == CODE_chat_empty) {
|
|
|
|
return;
|
|
|
|
}
|
2013-11-23 03:26:35 +04:00
|
|
|
int new = !(C->flags & FLAG_CREATED);
|
|
|
|
if (new) {
|
|
|
|
int y = 0;
|
|
|
|
if (x == CODE_chat_forbidden) {
|
|
|
|
y |= FLAG_FORBIDDEN;
|
2013-10-13 16:30:53 +04:00
|
|
|
}
|
2014-08-06 19:45:46 +02:00
|
|
|
int l = prefetch_strlen (mtp);
|
|
|
|
char *s = fetch_str (mtp, l);
|
2013-11-23 03:26:35 +04:00
|
|
|
|
|
|
|
struct file_location small;
|
|
|
|
struct file_location big;
|
|
|
|
memset (&small, 0, sizeof (small));
|
|
|
|
memset (&big, 0, sizeof (big));
|
|
|
|
int users_num = -1;
|
|
|
|
int date = 0;
|
|
|
|
int version = -1;
|
|
|
|
|
|
|
|
if (x == CODE_chat) {
|
2014-08-06 19:45:46 +02:00
|
|
|
unsigned z = fetch_int (mtp);
|
2014-01-15 16:10:52 +04:00
|
|
|
if (z == CODE_chat_photo_empty) {
|
2013-11-23 03:26:35 +04:00
|
|
|
small.dc = -2;
|
|
|
|
big.dc = -2;
|
|
|
|
} else {
|
2014-01-15 16:10:52 +04:00
|
|
|
assert (z == CODE_chat_photo);
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_file_location (mtp, &small);
|
|
|
|
fetch_file_location (mtp, &big);
|
2013-11-23 03:26:35 +04:00
|
|
|
}
|
2014-08-06 19:45:46 +02:00
|
|
|
users_num = fetch_int (mtp);
|
|
|
|
date = fetch_int (mtp);
|
|
|
|
if (fetch_bool (mtp)) {
|
2013-11-23 03:26:35 +04:00
|
|
|
y |= FLAG_CHAT_IN_CHAT;
|
|
|
|
}
|
2014-08-06 19:45:46 +02:00
|
|
|
version = fetch_int (mtp);
|
2013-11-23 03:26:35 +04:00
|
|
|
} else {
|
|
|
|
small.dc = -2;
|
|
|
|
big.dc = -2;
|
|
|
|
users_num = -1;
|
2014-08-06 19:45:46 +02:00
|
|
|
date = fetch_int (mtp);
|
2013-11-23 03:26:35 +04:00
|
|
|
version = -1;
|
2013-10-14 21:26:25 +04:00
|
|
|
}
|
2013-11-23 03:26:35 +04:00
|
|
|
|
2014-08-22 17:05:29 +02:00
|
|
|
bl_do_create_chat (mtp->bl, mtp, C, y, s, l, users_num, date, version, &big, &small);
|
2013-10-14 21:26:25 +04:00
|
|
|
} else {
|
2013-11-23 03:26:35 +04:00
|
|
|
if (x == CODE_chat_forbidden) {
|
2014-08-22 17:05:29 +02:00
|
|
|
bl_do_chat_forbid (mtp->bl, mtp, C, 1);
|
2013-11-23 03:26:35 +04:00
|
|
|
} else {
|
2014-08-22 17:05:29 +02:00
|
|
|
bl_do_chat_forbid (mtp->bl, mtp, C, 0);
|
2013-11-23 03:26:35 +04:00
|
|
|
}
|
2014-08-06 19:45:46 +02:00
|
|
|
int l = prefetch_strlen (mtp);
|
|
|
|
char *s = fetch_str (mtp, l);
|
2014-08-22 17:05:29 +02:00
|
|
|
bl_do_set_chat_title (mtp->bl, mtp, C, s, l);
|
2013-11-23 03:26:35 +04:00
|
|
|
|
|
|
|
struct file_location small;
|
|
|
|
struct file_location big;
|
|
|
|
memset (&small, 0, sizeof (small));
|
|
|
|
memset (&big, 0, sizeof (big));
|
|
|
|
|
|
|
|
if (x == CODE_chat) {
|
2014-08-06 19:45:46 +02:00
|
|
|
unsigned y = fetch_int (mtp);
|
2013-11-23 03:26:35 +04:00
|
|
|
if (y == CODE_chat_photo_empty) {
|
|
|
|
small.dc = -2;
|
|
|
|
big.dc = -2;
|
|
|
|
} else {
|
|
|
|
assert (y == CODE_chat_photo);
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_file_location (mtp, &small);
|
|
|
|
fetch_file_location (mtp, &big);
|
2013-11-23 03:26:35 +04:00
|
|
|
}
|
2014-08-22 17:05:29 +02:00
|
|
|
bl_do_set_chat_photo (mtp->bl, mtp, C, &big, &small);
|
2014-08-06 19:45:46 +02:00
|
|
|
int users_num = fetch_int (mtp);
|
2014-08-22 17:05:29 +02:00
|
|
|
bl_do_set_chat_date (mtp->bl, mtp, C, fetch_int (mtp));
|
|
|
|
bl_do_set_chat_set_in_chat (mtp->bl, mtp, C, fetch_bool (mtp));
|
|
|
|
bl_do_set_chat_version (mtp->bl, mtp, C, users_num, fetch_int (mtp));
|
2013-11-23 03:26:35 +04:00
|
|
|
} else {
|
2014-08-22 17:05:29 +02:00
|
|
|
bl_do_set_chat_date (mtp->bl, mtp, C, fetch_int (mtp));
|
2013-11-23 03:26:35 +04:00
|
|
|
}
|
2013-10-14 21:26:25 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
void fetch_notify_settings (struct mtproto_connection *mtp) {
|
|
|
|
unsigned x = fetch_int (mtp);
|
2013-10-26 02:03:36 +04:00
|
|
|
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) {
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_int (mtp); // mute_until
|
|
|
|
int l = prefetch_strlen (mtp);
|
|
|
|
fetch_str (mtp, l);
|
|
|
|
fetch_bool (mtp); // show_previews
|
|
|
|
fetch_int (mtp); // peer notify events
|
2013-10-24 21:04:44 +04:00
|
|
|
}
|
2013-10-26 02:03:36 +04:00
|
|
|
if (x == CODE_peer_notify_settings) {
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_int (mtp); // mute_until
|
|
|
|
int l = prefetch_strlen (mtp);
|
|
|
|
fetch_str (mtp, l);
|
|
|
|
fetch_bool (mtp); // show_previews
|
|
|
|
fetch_int (mtp); // events_mask
|
2013-10-26 02:03:36 +04:00
|
|
|
}
|
2013-10-24 21:04:44 +04:00
|
|
|
}
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
void fetch_chat_full (struct mtproto_connection *mtp, struct chat *C) {
|
|
|
|
unsigned x = fetch_int (mtp);
|
2013-10-24 21:04:44 +04:00
|
|
|
assert (x == CODE_messages_chat_full);
|
2014-08-06 19:45:46 +02:00
|
|
|
assert (fetch_int (mtp) == CODE_chat_full);
|
|
|
|
C->id = MK_CHAT (fetch_int (mtp));
|
2013-11-25 20:13:36 +04:00
|
|
|
//C->flags &= ~(FLAG_DELETED | FLAG_FORBIDDEN | FLAG_CHAT_IN_CHAT);
|
|
|
|
//C->flags |= FLAG_CREATED;
|
2014-08-06 19:45:46 +02:00
|
|
|
x = fetch_int (mtp);
|
2013-11-25 20:13:36 +04:00
|
|
|
int version = 0;
|
|
|
|
struct chat_user *users = 0;
|
|
|
|
int users_num = 0;
|
|
|
|
int admin_id = 0;
|
|
|
|
|
2013-10-24 21:04:44 +04:00
|
|
|
if (x == CODE_chat_participants) {
|
2014-08-06 19:45:46 +02:00
|
|
|
assert (fetch_int (mtp) == get_peer_id (C->id));
|
|
|
|
admin_id = fetch_int (mtp);
|
|
|
|
assert (fetch_int (mtp) == CODE_vector);
|
|
|
|
users_num = fetch_int (mtp);
|
2014-01-10 15:32:57 +04:00
|
|
|
users = talloc (sizeof (struct chat_user) * users_num);
|
2013-10-24 21:04:44 +04:00
|
|
|
int i;
|
2013-11-25 21:16:34 +04:00
|
|
|
for (i = 0; i < users_num; i++) {
|
2014-08-06 19:45:46 +02:00
|
|
|
assert (fetch_int (mtp) == (int)CODE_chat_participant);
|
|
|
|
users[i].user_id = fetch_int (mtp);
|
|
|
|
users[i].inviter_id = fetch_int (mtp);
|
|
|
|
users[i].date = fetch_int (mtp);
|
2013-10-24 21:04:44 +04:00
|
|
|
}
|
2014-08-06 19:45:46 +02:00
|
|
|
version = fetch_int (mtp);
|
2013-10-24 21:04:44 +04:00
|
|
|
}
|
2014-08-06 19:45:46 +02:00
|
|
|
int *start = mtp->in_ptr;
|
|
|
|
fetch_skip_photo (mtp);
|
|
|
|
int *end = mtp->in_ptr;
|
|
|
|
fetch_notify_settings (mtp);
|
2013-10-24 21:04:44 +04:00
|
|
|
|
|
|
|
int n, i;
|
2014-08-06 19:45:46 +02:00
|
|
|
assert (fetch_int (mtp) == CODE_vector);
|
|
|
|
n = fetch_int (mtp);
|
2013-10-24 21:04:44 +04:00
|
|
|
for (i = 0; i < n; i++) {
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_alloc_chat (mtp);
|
2013-10-24 21:04:44 +04:00
|
|
|
}
|
2014-08-06 19:45:46 +02:00
|
|
|
assert (fetch_int (mtp) == CODE_vector);
|
|
|
|
n = fetch_int (mtp);
|
2013-10-24 21:04:44 +04:00
|
|
|
for (i = 0; i < n; i++) {
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_alloc_user (mtp);
|
2013-10-24 21:04:44 +04:00
|
|
|
}
|
2013-11-25 20:13:36 +04:00
|
|
|
if (admin_id) {
|
2014-08-22 17:05:29 +02:00
|
|
|
bl_do_set_chat_admin (mtp->bl, mtp, C, admin_id);
|
2013-11-25 20:13:36 +04:00
|
|
|
}
|
|
|
|
if (version > 0) {
|
2014-08-22 17:05:29 +02:00
|
|
|
bl_do_set_chat_participants (mtp->bl, mtp, C, version, users_num, users);
|
2014-01-10 18:37:56 +04:00
|
|
|
tfree (users, sizeof (struct chat_user) * users_num);
|
2013-11-25 20:13:36 +04:00
|
|
|
}
|
2014-08-22 17:05:29 +02:00
|
|
|
bl_do_set_chat_full_photo (mtp->bl, mtp, C, start, 4 * (end - start));
|
2013-10-24 21:04:44 +04:00
|
|
|
}
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
void fetch_photo_size (struct mtproto_connection *mtp, struct photo_size *S) {
|
2013-10-18 20:00:47 +04:00
|
|
|
memset (S, 0, sizeof (*S));
|
2014-08-06 19:45:46 +02:00
|
|
|
unsigned x = fetch_int (mtp);
|
2013-10-21 23:27:29 +04:00
|
|
|
assert (x == CODE_photo_size || x == CODE_photo_cached_size || x == CODE_photo_size_empty);
|
2014-08-06 19:45:46 +02:00
|
|
|
S->type = fetch_str_dup (mtp);
|
2014-10-03 14:23:15 +02:00
|
|
|
debug("s->type %s\n", S->type);
|
2013-10-21 23:27:29 +04:00
|
|
|
if (x != CODE_photo_size_empty) {
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_file_location (mtp, &S->loc);
|
|
|
|
S->w = fetch_int (mtp);
|
|
|
|
S->h = fetch_int (mtp);
|
2013-10-21 23:27:29 +04:00
|
|
|
if (x == CODE_photo_size) {
|
2014-08-06 19:45:46 +02:00
|
|
|
S->size = fetch_int (mtp);
|
2013-10-21 23:27:29 +04:00
|
|
|
} else {
|
2014-08-06 19:45:46 +02:00
|
|
|
S->size = prefetch_strlen (mtp);
|
2014-01-10 15:32:57 +04:00
|
|
|
// S->data = talloc (S->size);
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_str (mtp, S->size);
|
|
|
|
// memcpy (S->data, fetch_str (mtp, S->size), S->size);
|
2013-10-21 23:27:29 +04:00
|
|
|
}
|
2013-10-14 21:26:25 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
void fetch_skip_photo_size (struct mtproto_connection *mtp) {
|
|
|
|
unsigned x = fetch_int (mtp);
|
2013-11-21 23:35:49 +04:00
|
|
|
assert (x == CODE_photo_size || x == CODE_photo_cached_size || x == CODE_photo_size_empty);
|
2014-08-06 19:45:46 +02:00
|
|
|
int l = prefetch_strlen (mtp);
|
|
|
|
fetch_str (mtp, l); // type
|
2013-11-21 23:35:49 +04:00
|
|
|
if (x != CODE_photo_size_empty) {
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_skip_file_location (mtp);
|
|
|
|
mtp->in_ptr += 2; // w, h
|
2013-11-21 23:35:49 +04:00
|
|
|
if (x == CODE_photo_size) {
|
2014-08-06 19:45:46 +02:00
|
|
|
mtp->in_ptr ++;
|
2013-11-21 23:35:49 +04:00
|
|
|
} else {
|
2014-08-06 19:45:46 +02:00
|
|
|
l = prefetch_strlen (mtp);
|
|
|
|
fetch_str (mtp, l);
|
2013-11-21 23:35:49 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
void fetch_geo (struct mtproto_connection *mtp, struct geo *G) {
|
|
|
|
unsigned x = fetch_int (mtp);
|
2013-10-18 20:00:47 +04:00
|
|
|
if (x == CODE_geo_point) {
|
2014-08-06 19:45:46 +02:00
|
|
|
G->longitude = fetch_double (mtp);
|
|
|
|
G->latitude = fetch_double (mtp);
|
2013-10-18 20:00:47 +04:00
|
|
|
} else {
|
|
|
|
assert (x == CODE_geo_point_empty);
|
|
|
|
G->longitude = 0;
|
|
|
|
G->latitude = 0;
|
|
|
|
}
|
2013-10-14 21:26:25 +04:00
|
|
|
}
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
void fetch_skip_geo (struct mtproto_connection *mtp) {
|
|
|
|
unsigned x = fetch_int (mtp);
|
2013-11-21 23:35:49 +04:00
|
|
|
assert (x == CODE_geo_point || x == CODE_geo_point_empty);
|
|
|
|
if (x == CODE_geo_point) {
|
2014-08-06 19:45:46 +02:00
|
|
|
mtp->in_ptr += 4;
|
2013-11-21 23:35:49 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
void fetch_photo (struct mtproto_connection *mtp, struct photo *P) {
|
2013-10-14 21:26:25 +04:00
|
|
|
memset (P, 0, sizeof (*P));
|
2014-08-06 19:45:46 +02:00
|
|
|
unsigned x = fetch_int (mtp);
|
2013-10-24 21:04:44 +04:00
|
|
|
assert (x == CODE_photo_empty || x == CODE_photo);
|
2014-08-06 19:45:46 +02:00
|
|
|
P->id = fetch_long (mtp);
|
2013-10-14 21:26:25 +04:00
|
|
|
if (x == CODE_photo_empty) { return; }
|
2014-08-06 19:45:46 +02:00
|
|
|
P->access_hash = fetch_long (mtp);
|
|
|
|
P->user_id = fetch_int (mtp);
|
|
|
|
P->date = fetch_int (mtp);
|
|
|
|
P->caption = fetch_str_dup (mtp);
|
|
|
|
fetch_geo (mtp, &P->geo);
|
|
|
|
assert (fetch_int (mtp) == CODE_vector);
|
|
|
|
P->sizes_num = fetch_int (mtp);
|
2014-10-03 14:23:15 +02:00
|
|
|
debug("sizes_num %d \n", P->sizes_num);
|
2014-01-10 15:32:57 +04:00
|
|
|
P->sizes = talloc (sizeof (struct photo_size) * P->sizes_num);
|
2013-10-14 21:26:25 +04:00
|
|
|
int i;
|
|
|
|
for (i = 0; i < P->sizes_num; i++) {
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_photo_size (mtp, &P->sizes[i]);
|
2013-10-14 21:26:25 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
void fetch_skip_photo (struct mtproto_connection *mtp) {
|
|
|
|
unsigned x = fetch_int (mtp);
|
2013-11-21 23:35:49 +04:00
|
|
|
assert (x == CODE_photo_empty || x == CODE_photo);
|
2014-08-06 19:45:46 +02:00
|
|
|
mtp->in_ptr += 2; // id
|
2013-11-21 23:35:49 +04:00
|
|
|
if (x == CODE_photo_empty) { return; }
|
2014-08-06 19:45:46 +02:00
|
|
|
mtp->in_ptr += 2 +1 + 1; // access_hash, user_id, date
|
|
|
|
int l = prefetch_strlen (mtp);
|
|
|
|
fetch_str (mtp, l); // caption
|
|
|
|
fetch_skip_geo (mtp);
|
|
|
|
assert (fetch_int (mtp) == CODE_vector);
|
|
|
|
int n = fetch_int (mtp);
|
2013-11-21 23:35:49 +04:00
|
|
|
int i;
|
|
|
|
for (i = 0; i < n; i++) {
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_skip_photo_size (mtp);
|
2013-11-21 23:35:49 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
void fetch_video (struct mtproto_connection *mtp, struct video *V) {
|
2013-10-14 21:26:25 +04:00
|
|
|
memset (V, 0, sizeof (*V));
|
2014-08-06 19:45:46 +02:00
|
|
|
unsigned x = fetch_int (mtp);
|
|
|
|
V->id = fetch_long (mtp);
|
2013-10-14 21:26:25 +04:00
|
|
|
if (x == CODE_video_empty) { return; }
|
2014-08-06 19:45:46 +02:00
|
|
|
V->access_hash = fetch_long (mtp);
|
|
|
|
V->user_id = fetch_int (mtp);
|
|
|
|
V->date = fetch_int (mtp);
|
|
|
|
V->caption = fetch_str_dup (mtp);
|
|
|
|
V->duration = fetch_int (mtp);
|
|
|
|
V->size = fetch_int (mtp);
|
|
|
|
fetch_photo_size (mtp, &V->thumb);
|
|
|
|
V->dc_id = fetch_int (mtp);
|
|
|
|
V->w = fetch_int (mtp);
|
|
|
|
V->h = fetch_int (mtp);
|
|
|
|
}
|
|
|
|
|
|
|
|
void fetch_skip_video (struct mtproto_connection *mtp) {
|
|
|
|
unsigned x = fetch_int (mtp);
|
|
|
|
fetch_long (mtp);
|
2013-11-30 01:43:56 +04:00
|
|
|
if (x == CODE_video_empty) { return; }
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_skip (mtp, 4);
|
|
|
|
int l = prefetch_strlen (mtp);
|
|
|
|
fetch_str (mtp, l);
|
|
|
|
fetch_skip (mtp, 2);
|
|
|
|
fetch_skip_photo_size (mtp);
|
|
|
|
fetch_skip (mtp, 3);
|
2013-11-30 01:43:56 +04:00
|
|
|
}
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
void fetch_audio (struct mtproto_connection *mtp, struct audio *V) {
|
2013-11-15 14:37:14 +04:00
|
|
|
memset (V, 0, sizeof (*V));
|
2014-08-06 19:45:46 +02:00
|
|
|
unsigned x = fetch_int (mtp);
|
|
|
|
V->id = fetch_long (mtp);
|
2013-11-15 14:37:14 +04:00
|
|
|
if (x == CODE_audio_empty) { return; }
|
2014-08-06 19:45:46 +02:00
|
|
|
V->access_hash = fetch_long (mtp);
|
|
|
|
V->user_id = fetch_int (mtp);
|
|
|
|
V->date = fetch_int (mtp);
|
|
|
|
V->duration = fetch_int (mtp);
|
|
|
|
V->size = fetch_int (mtp);
|
|
|
|
V->dc_id = fetch_int (mtp);
|
2013-11-15 14:37:14 +04:00
|
|
|
}
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
void fetch_skip_audio (struct mtproto_connection *mtp) {
|
|
|
|
unsigned x = fetch_int (mtp);
|
|
|
|
fetch_skip (mtp, 2);
|
2013-11-30 01:43:56 +04:00
|
|
|
if (x == CODE_audio_empty) { return; }
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_skip (mtp, 7);
|
2013-11-30 01:43:56 +04:00
|
|
|
}
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
void fetch_document (struct mtproto_connection *mtp, struct document *V) {
|
2013-11-15 14:37:14 +04:00
|
|
|
memset (V, 0, sizeof (*V));
|
2014-08-06 19:45:46 +02:00
|
|
|
unsigned x = fetch_int (mtp);
|
|
|
|
V->id = fetch_long (mtp);
|
2013-11-15 14:37:14 +04:00
|
|
|
if (x == CODE_document_empty) { return; }
|
2014-08-06 19:45:46 +02:00
|
|
|
V->access_hash = fetch_long (mtp);
|
|
|
|
V->user_id = fetch_int (mtp);
|
|
|
|
V->date = fetch_int (mtp);
|
|
|
|
V->caption = fetch_str_dup (mtp);
|
|
|
|
V->mime_type = fetch_str_dup (mtp);
|
|
|
|
V->size = fetch_int (mtp);
|
|
|
|
fetch_photo_size (mtp, &V->thumb);
|
|
|
|
V->dc_id = fetch_int (mtp);
|
|
|
|
}
|
|
|
|
|
|
|
|
void fetch_skip_document (struct mtproto_connection *mtp) {
|
|
|
|
unsigned x = fetch_int (mtp);
|
|
|
|
fetch_skip (mtp, 2);
|
2013-11-30 01:43:56 +04:00
|
|
|
if (x == CODE_document_empty) { return; }
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_skip (mtp, 4);
|
|
|
|
int l = prefetch_strlen (mtp);
|
|
|
|
fetch_str (mtp, l);
|
|
|
|
l = prefetch_strlen (mtp);
|
|
|
|
fetch_str (mtp, l);
|
|
|
|
fetch_skip (mtp, 1);
|
|
|
|
fetch_skip_photo_size (mtp);
|
|
|
|
fetch_skip (mtp, 1);
|
2013-11-30 01:43:56 +04:00
|
|
|
}
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
void fetch_message_action (struct mtproto_connection *mtp, struct message_action *M) {
|
2013-10-14 21:26:25 +04:00
|
|
|
memset (M, 0, sizeof (*M));
|
2014-08-06 19:45:46 +02:00
|
|
|
unsigned x = fetch_int (mtp);
|
2013-10-14 21:26:25 +04:00
|
|
|
M->type = x;
|
|
|
|
switch (x) {
|
|
|
|
case CODE_message_action_empty:
|
|
|
|
break;
|
2013-11-23 03:26:35 +04:00
|
|
|
case CODE_message_action_geo_chat_create:
|
|
|
|
{
|
2014-08-06 19:45:46 +02:00
|
|
|
int l = prefetch_strlen (mtp); // title
|
|
|
|
char *s = fetch_str (mtp, l);
|
|
|
|
int l2 = prefetch_strlen (mtp); // checkin
|
|
|
|
char *s2 = fetch_str (mtp, l2);
|
2014-10-03 14:23:15 +02:00
|
|
|
debug ("Message action: Created geochat %.*s in address %.*s\n", l, s, l2, s2);
|
2013-11-23 03:26:35 +04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case CODE_message_action_geo_chat_checkin:
|
|
|
|
break;
|
2013-10-14 21:26:25 +04:00
|
|
|
case CODE_message_action_chat_create:
|
2014-08-06 19:45:46 +02:00
|
|
|
M->title = fetch_str_dup (mtp);
|
|
|
|
assert (fetch_int (mtp) == (int)CODE_vector);
|
|
|
|
M->user_num = fetch_int (mtp);
|
2014-01-10 15:32:57 +04:00
|
|
|
M->users = talloc (M->user_num * 4);
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_ints (mtp, M->users, M->user_num);
|
2013-10-14 21:26:25 +04:00
|
|
|
break;
|
|
|
|
case CODE_message_action_chat_edit_title:
|
2014-08-06 19:45:46 +02:00
|
|
|
M->new_title = fetch_str_dup (mtp);
|
2013-10-14 21:26:25 +04:00
|
|
|
break;
|
|
|
|
case CODE_message_action_chat_edit_photo:
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_photo (mtp, &M->photo);
|
2013-10-14 21:26:25 +04:00
|
|
|
break;
|
|
|
|
case CODE_message_action_chat_delete_photo:
|
|
|
|
break;
|
|
|
|
case CODE_message_action_chat_add_user:
|
2014-08-06 19:45:46 +02:00
|
|
|
M->user = fetch_int (mtp);
|
2013-10-14 21:26:25 +04:00
|
|
|
break;
|
|
|
|
case CODE_message_action_chat_delete_user:
|
2014-08-06 19:45:46 +02:00
|
|
|
M->user = fetch_int (mtp);
|
2013-10-14 21:26:25 +04:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
assert (0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
void fetch_skip_message_action (struct mtproto_connection *mtp) {
|
|
|
|
unsigned x = fetch_int (mtp);
|
2013-11-30 01:43:56 +04:00
|
|
|
int l;
|
|
|
|
switch (x) {
|
|
|
|
case CODE_message_action_empty:
|
|
|
|
break;
|
|
|
|
case CODE_message_action_geo_chat_create:
|
|
|
|
{
|
2014-08-06 19:45:46 +02:00
|
|
|
l = prefetch_strlen (mtp);
|
|
|
|
fetch_str (mtp, l);
|
|
|
|
l = prefetch_strlen (mtp);
|
|
|
|
fetch_str (mtp, l);
|
2013-11-30 01:43:56 +04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case CODE_message_action_geo_chat_checkin:
|
|
|
|
break;
|
|
|
|
case CODE_message_action_chat_create:
|
2014-08-06 19:45:46 +02:00
|
|
|
l = prefetch_strlen (mtp);
|
|
|
|
fetch_str (mtp, l);
|
|
|
|
assert (fetch_int (mtp) == (int)CODE_vector);
|
|
|
|
l = fetch_int (mtp);
|
|
|
|
fetch_skip (mtp, l);
|
2013-11-30 01:43:56 +04:00
|
|
|
break;
|
|
|
|
case CODE_message_action_chat_edit_title:
|
2014-08-06 19:45:46 +02:00
|
|
|
l = prefetch_strlen (mtp);
|
|
|
|
fetch_str (mtp, l);
|
2013-11-30 01:43:56 +04:00
|
|
|
break;
|
|
|
|
case CODE_message_action_chat_edit_photo:
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_skip_photo (mtp);
|
2013-11-30 01:43:56 +04:00
|
|
|
break;
|
|
|
|
case CODE_message_action_chat_delete_photo:
|
|
|
|
break;
|
|
|
|
case CODE_message_action_chat_add_user:
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_int (mtp);
|
2013-11-30 01:43:56 +04:00
|
|
|
break;
|
|
|
|
case CODE_message_action_chat_delete_user:
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_int (mtp);
|
2013-11-30 01:43:56 +04:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
assert (0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
void fetch_message_short (struct mtproto_connection *mtp, struct message *M) {
|
2014-09-01 21:25:41 +02:00
|
|
|
struct telegram *instance = mtp->instance;
|
|
|
|
|
2013-11-30 01:43:56 +04:00
|
|
|
int new = !(M->flags & FLAG_CREATED);
|
|
|
|
|
|
|
|
if (new) {
|
2014-08-06 19:45:46 +02:00
|
|
|
int id = fetch_int (mtp);
|
|
|
|
int from_id = fetch_int (mtp);
|
2014-09-01 21:25:41 +02:00
|
|
|
int to_id = instance->our_id;
|
2014-08-06 19:45:46 +02:00
|
|
|
int l = prefetch_strlen (mtp);
|
|
|
|
char *s = fetch_str (mtp, l);
|
2013-11-30 01:43:56 +04:00
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_pts (mtp);
|
2013-11-30 01:43:56 +04:00
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
int date = fetch_int (mtp);
|
|
|
|
fetch_seq (mtp);
|
2013-11-30 01:43:56 +04:00
|
|
|
|
2014-08-22 17:05:29 +02:00
|
|
|
bl_do_create_message_text (mtp->bl, mtp, id, from_id, PEER_USER, to_id, date, l, s);
|
2013-11-30 01:43:56 +04:00
|
|
|
} else {
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_int (mtp); // id
|
|
|
|
fetch_int (mtp); // from_id
|
|
|
|
int l = prefetch_strlen (mtp);
|
|
|
|
fetch_str (mtp, l); // text
|
2013-11-30 01:43:56 +04:00
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_pts (mtp);
|
|
|
|
fetch_int (mtp);
|
|
|
|
fetch_seq (mtp);
|
2013-11-30 01:43:56 +04:00
|
|
|
}
|
2013-10-16 23:19:39 +04:00
|
|
|
}
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
void fetch_message_short_chat (struct mtproto_connection *mtp, struct message *M) {
|
2013-11-30 01:43:56 +04:00
|
|
|
int new = !(M->flags & FLAG_CREATED);
|
|
|
|
|
|
|
|
if (new) {
|
2014-08-06 19:45:46 +02:00
|
|
|
int id = fetch_int (mtp);
|
|
|
|
int from_id = fetch_int (mtp);
|
|
|
|
int to_id = fetch_int (mtp);
|
|
|
|
int l = prefetch_strlen (mtp);
|
|
|
|
char *s = fetch_str (mtp, l);
|
2013-11-30 01:43:56 +04:00
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_pts (mtp);
|
2013-11-30 01:43:56 +04:00
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
int date = fetch_int (mtp);
|
|
|
|
fetch_seq (mtp);
|
2013-11-30 01:43:56 +04:00
|
|
|
|
2014-08-22 17:05:29 +02:00
|
|
|
bl_do_create_message_text (mtp->bl, mtp, id, from_id, PEER_CHAT, to_id, date, l, s);
|
2013-11-30 01:43:56 +04:00
|
|
|
} else {
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_int (mtp); // id
|
|
|
|
fetch_int (mtp); // from_id
|
|
|
|
fetch_int (mtp); // to_id
|
|
|
|
int l = prefetch_strlen (mtp);
|
|
|
|
fetch_str (mtp, l); // text
|
2013-11-30 01:43:56 +04:00
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_pts (mtp);
|
|
|
|
fetch_int (mtp);
|
|
|
|
fetch_seq (mtp);
|
2013-11-30 01:43:56 +04:00
|
|
|
}
|
2013-10-16 23:19:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
void fetch_message_media (struct mtproto_connection *mtp, struct message_media *M) {
|
2013-10-14 21:26:25 +04:00
|
|
|
memset (M, 0, sizeof (*M));
|
2014-08-06 19:45:46 +02:00
|
|
|
M->type = fetch_int (mtp);
|
2013-10-14 21:26:25 +04:00
|
|
|
switch (M->type) {
|
|
|
|
case CODE_message_media_empty:
|
|
|
|
break;
|
|
|
|
case CODE_message_media_photo:
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_photo (mtp, &M->photo);
|
2013-10-14 21:26:25 +04:00
|
|
|
break;
|
|
|
|
case CODE_message_media_video:
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_video (mtp, &M->video);
|
2013-10-14 21:26:25 +04:00
|
|
|
break;
|
2013-11-15 14:37:14 +04:00
|
|
|
case CODE_message_media_audio:
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_audio (mtp, &M->audio);
|
2013-11-15 14:37:14 +04:00
|
|
|
break;
|
|
|
|
case CODE_message_media_document:
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_document (mtp, &M->document);
|
2013-11-15 14:37:14 +04:00
|
|
|
break;
|
2013-10-14 21:26:25 +04:00
|
|
|
case CODE_message_media_geo:
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_geo (mtp, &M->geo);
|
2013-10-14 21:26:25 +04:00
|
|
|
break;
|
|
|
|
case CODE_message_media_contact:
|
2014-08-06 19:45:46 +02:00
|
|
|
M->phone = fetch_str_dup (mtp);
|
|
|
|
M->first_name = fetch_str_dup (mtp);
|
|
|
|
M->last_name = fetch_str_dup (mtp);
|
|
|
|
M->user_id = fetch_int (mtp);
|
2013-10-14 21:26:25 +04:00
|
|
|
break;
|
|
|
|
case CODE_message_media_unsupported:
|
2014-08-06 19:45:46 +02:00
|
|
|
M->data_size = prefetch_strlen (mtp);
|
2014-01-10 18:37:56 +04:00
|
|
|
M->data = talloc (M->data_size);
|
2014-08-06 19:45:46 +02:00
|
|
|
memcpy (M->data, fetch_str (mtp, M->data_size), M->data_size);
|
2013-10-14 21:26:25 +04:00
|
|
|
break;
|
|
|
|
default:
|
2014-10-03 14:23:15 +02:00
|
|
|
debug ("type = 0x%08x\n", M->type);
|
2013-10-14 21:26:25 +04:00
|
|
|
assert (0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
void fetch_skip_message_media (struct mtproto_connection *mtp) {
|
|
|
|
unsigned x = fetch_int (mtp);
|
2013-11-30 01:43:56 +04:00
|
|
|
switch (x) {
|
|
|
|
case CODE_message_media_empty:
|
|
|
|
break;
|
|
|
|
case CODE_message_media_photo:
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_skip_photo (mtp);
|
2013-11-30 01:43:56 +04:00
|
|
|
break;
|
|
|
|
case CODE_message_media_video:
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_skip_video (mtp);
|
2013-11-30 01:43:56 +04:00
|
|
|
break;
|
|
|
|
case CODE_message_media_audio:
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_skip_audio (mtp);
|
2013-11-30 01:43:56 +04:00
|
|
|
break;
|
|
|
|
case CODE_message_media_document:
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_skip_document (mtp);
|
2013-11-30 01:43:56 +04:00
|
|
|
break;
|
|
|
|
case CODE_message_media_geo:
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_skip_geo (mtp);
|
2013-11-30 01:43:56 +04:00
|
|
|
break;
|
|
|
|
case CODE_message_media_contact:
|
|
|
|
{
|
|
|
|
int l;
|
2014-08-06 19:45:46 +02:00
|
|
|
l = prefetch_strlen (mtp);
|
|
|
|
fetch_str (mtp, l);
|
|
|
|
l = prefetch_strlen (mtp);
|
|
|
|
fetch_str (mtp, l);
|
|
|
|
l = prefetch_strlen (mtp);
|
|
|
|
fetch_str (mtp, l);
|
|
|
|
fetch_int (mtp);
|
2013-11-30 01:43:56 +04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case CODE_message_media_unsupported:
|
|
|
|
{
|
2014-08-06 19:45:46 +02:00
|
|
|
int l = prefetch_strlen (mtp);
|
|
|
|
fetch_str (mtp, l);
|
2013-11-30 01:43:56 +04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2014-10-03 14:23:15 +02:00
|
|
|
debug ("type = 0x%08x\n", x);
|
2013-11-30 01:43:56 +04:00
|
|
|
assert (0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
void fetch_skip_message_media_encrypted (struct mtproto_connection *mtp) {
|
|
|
|
unsigned x = fetch_int (mtp);
|
2013-11-30 01:43:56 +04:00
|
|
|
int l;
|
|
|
|
switch (x) {
|
|
|
|
case CODE_decrypted_message_media_empty:
|
|
|
|
break;
|
|
|
|
case CODE_decrypted_message_media_photo:
|
2014-08-06 19:45:46 +02:00
|
|
|
l = prefetch_strlen (mtp);
|
|
|
|
fetch_str (mtp, l); // thumb
|
|
|
|
fetch_skip (mtp, 5);
|
2013-11-30 01:43:56 +04:00
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
l = prefetch_strlen (mtp);
|
|
|
|
fetch_str (mtp, l);
|
2013-11-30 01:43:56 +04:00
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
l = prefetch_strlen (mtp);
|
|
|
|
fetch_str (mtp, l);
|
2013-11-30 01:43:56 +04:00
|
|
|
break;
|
|
|
|
case CODE_decrypted_message_media_video:
|
2014-08-06 19:45:46 +02:00
|
|
|
l = prefetch_strlen (mtp);
|
|
|
|
fetch_str (mtp, l); // thumb
|
2013-11-30 01:43:56 +04:00
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_skip (mtp, 6);
|
2013-11-30 01:43:56 +04:00
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
l = prefetch_strlen (mtp);
|
|
|
|
fetch_str (mtp, l);
|
2013-11-30 01:43:56 +04:00
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
l = prefetch_strlen (mtp);
|
|
|
|
fetch_str (mtp, l);
|
2013-11-30 01:43:56 +04:00
|
|
|
break;
|
|
|
|
case CODE_decrypted_message_media_audio:
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_skip (mtp, 2);
|
2013-11-30 01:43:56 +04:00
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
l = prefetch_strlen (mtp);
|
|
|
|
fetch_str (mtp, l);
|
2013-11-30 01:43:56 +04:00
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
l = prefetch_strlen (mtp);
|
|
|
|
fetch_str (mtp, l);
|
2013-11-30 01:43:56 +04:00
|
|
|
break;
|
|
|
|
case CODE_decrypted_message_media_document:
|
2014-08-06 19:45:46 +02:00
|
|
|
l = prefetch_strlen (mtp);
|
|
|
|
fetch_str (mtp, l); // thumb
|
2013-11-30 01:43:56 +04:00
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_skip (mtp, 2);
|
2013-11-30 01:43:56 +04:00
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
l = prefetch_strlen (mtp);
|
|
|
|
fetch_str (mtp, l); // thumb
|
|
|
|
l = prefetch_strlen (mtp);
|
|
|
|
fetch_str (mtp, l); // thumb
|
|
|
|
fetch_skip (mtp, 1);
|
2013-11-30 01:43:56 +04:00
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
l = prefetch_strlen (mtp);
|
|
|
|
fetch_str (mtp, l);
|
2013-11-30 01:43:56 +04:00
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
l = prefetch_strlen (mtp);
|
|
|
|
fetch_str (mtp, l);
|
2013-11-30 01:43:56 +04:00
|
|
|
break;
|
|
|
|
case CODE_decrypted_message_media_geo_point:
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_skip (mtp, 4);
|
2013-11-30 01:43:56 +04:00
|
|
|
break;
|
|
|
|
case CODE_decrypted_message_media_contact:
|
2014-08-06 19:45:46 +02:00
|
|
|
l = prefetch_strlen (mtp);
|
|
|
|
fetch_str (mtp, l); // thumb
|
|
|
|
l = prefetch_strlen (mtp);
|
|
|
|
fetch_str (mtp, l); // thumb
|
|
|
|
l = prefetch_strlen (mtp);
|
|
|
|
fetch_str (mtp, l); // thumb
|
|
|
|
fetch_skip (mtp, 1);
|
2013-11-30 01:43:56 +04:00
|
|
|
break;
|
|
|
|
default:
|
2014-10-03 14:23:15 +02:00
|
|
|
debug ("type = 0x%08x\n", x);
|
2013-11-30 01:43:56 +04:00
|
|
|
assert (0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
void fetch_message_media_encrypted (struct mtproto_connection *mtp, struct message_media *M) {
|
2013-11-02 21:01:22 +04:00
|
|
|
memset (M, 0, sizeof (*M));
|
2014-08-06 19:45:46 +02:00
|
|
|
unsigned x = fetch_int (mtp);
|
2013-11-02 21:01:22 +04:00
|
|
|
int l;
|
2013-11-04 21:34:27 +04:00
|
|
|
switch (x) {
|
2013-11-02 21:01:22 +04:00
|
|
|
case CODE_decrypted_message_media_empty:
|
|
|
|
M->type = CODE_message_media_empty;
|
|
|
|
break;
|
|
|
|
case CODE_decrypted_message_media_photo:
|
|
|
|
M->type = x;
|
2014-08-06 19:45:46 +02:00
|
|
|
l = prefetch_strlen (mtp);
|
|
|
|
fetch_str (mtp, l); // thumb
|
|
|
|
fetch_int (mtp); // thumb_w
|
|
|
|
fetch_int (mtp); // thumb_h
|
|
|
|
M->encr_photo.w = fetch_int (mtp);
|
|
|
|
M->encr_photo.h = fetch_int (mtp);
|
|
|
|
M->encr_photo.size = fetch_int (mtp);
|
2013-11-02 21:01:22 +04:00
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
l = prefetch_strlen (mtp);
|
2013-11-02 21:01:22 +04:00
|
|
|
assert (l > 0);
|
2014-01-10 15:32:57 +04:00
|
|
|
M->encr_photo.key = talloc (32);
|
2013-11-04 21:34:27 +04:00
|
|
|
memset (M->encr_photo.key, 0, 32);
|
|
|
|
if (l <= 32) {
|
2014-08-06 19:45:46 +02:00
|
|
|
memcpy (M->encr_photo.key + (32 - l), fetch_str (mtp, l), l);
|
2013-11-04 21:34:27 +04:00
|
|
|
} else {
|
2014-08-06 19:45:46 +02:00
|
|
|
memcpy (M->encr_photo.key, fetch_str (mtp, l) + (l - 32), 32);
|
2013-11-04 21:34:27 +04:00
|
|
|
}
|
2014-01-10 15:32:57 +04:00
|
|
|
M->encr_photo.iv = talloc (32);
|
2014-08-06 19:45:46 +02:00
|
|
|
l = prefetch_strlen (mtp);
|
2013-11-04 21:34:27 +04:00
|
|
|
assert (l > 0);
|
|
|
|
memset (M->encr_photo.iv, 0, 32);
|
|
|
|
if (l <= 32) {
|
2014-08-06 19:45:46 +02:00
|
|
|
memcpy (M->encr_photo.iv + (32 - l), fetch_str (mtp, l), l);
|
2013-11-04 21:34:27 +04:00
|
|
|
} else {
|
2014-08-06 19:45:46 +02:00
|
|
|
memcpy (M->encr_photo.iv, fetch_str (mtp, l) + (l - 32), 32);
|
2013-11-04 21:34:27 +04:00
|
|
|
}
|
2013-11-02 21:01:22 +04:00
|
|
|
break;
|
|
|
|
case CODE_decrypted_message_media_video:
|
|
|
|
M->type = x;
|
2014-08-06 19:45:46 +02:00
|
|
|
l = prefetch_strlen (mtp);
|
|
|
|
fetch_str (mtp, l); // thumb
|
|
|
|
fetch_int (mtp); // thumb_w
|
|
|
|
fetch_int (mtp); // thumb_h
|
|
|
|
M->encr_video.duration = fetch_int (mtp);
|
|
|
|
M->encr_video.w = fetch_int (mtp);
|
|
|
|
M->encr_video.h = fetch_int (mtp);
|
|
|
|
M->encr_video.size = fetch_int (mtp);
|
2013-11-15 14:37:14 +04:00
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
l = prefetch_strlen (mtp);
|
2013-11-15 14:37:14 +04:00
|
|
|
assert (l > 0);
|
2014-01-10 15:32:57 +04:00
|
|
|
M->encr_video.key = talloc0 (32);
|
2013-11-15 14:37:14 +04:00
|
|
|
if (l <= 32) {
|
2014-08-06 19:45:46 +02:00
|
|
|
memcpy (M->encr_video.key + (32 - l), fetch_str (mtp, l), l);
|
2013-11-15 14:37:14 +04:00
|
|
|
} else {
|
2014-08-06 19:45:46 +02:00
|
|
|
memcpy (M->encr_video.key, fetch_str (mtp, l) + (l - 32), 32);
|
2013-11-15 14:37:14 +04:00
|
|
|
}
|
2014-01-10 15:32:57 +04:00
|
|
|
M->encr_video.iv = talloc (32);
|
2014-08-06 19:45:46 +02:00
|
|
|
l = prefetch_strlen (mtp);
|
2013-11-15 14:37:14 +04:00
|
|
|
assert (l > 0);
|
|
|
|
memset (M->encr_video.iv, 0, 32);
|
|
|
|
if (l <= 32) {
|
2014-08-06 19:45:46 +02:00
|
|
|
memcpy (M->encr_video.iv + (32 - l), fetch_str (mtp, l), l);
|
2013-11-15 14:37:14 +04:00
|
|
|
} else {
|
2014-08-06 19:45:46 +02:00
|
|
|
memcpy (M->encr_video.iv, fetch_str (mtp, l) + (l - 32), 32);
|
2013-11-15 14:37:14 +04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case CODE_decrypted_message_media_audio:
|
|
|
|
M->type = x;
|
2014-08-06 19:45:46 +02:00
|
|
|
M->encr_audio.duration = fetch_int (mtp);
|
|
|
|
M->encr_audio.size = fetch_int (mtp);
|
2013-11-15 14:37:14 +04:00
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
l = prefetch_strlen (mtp);
|
2013-11-15 14:37:14 +04:00
|
|
|
assert (l > 0);
|
2014-01-10 15:32:57 +04:00
|
|
|
M->encr_video.key = talloc0 (32);
|
2013-11-15 14:37:14 +04:00
|
|
|
if (l <= 32) {
|
2014-08-06 19:45:46 +02:00
|
|
|
memcpy (M->encr_video.key + (32 - l), fetch_str (mtp, l), l);
|
2013-11-15 14:37:14 +04:00
|
|
|
} else {
|
2014-08-06 19:45:46 +02:00
|
|
|
memcpy (M->encr_video.key, fetch_str (mtp, l) + (l - 32), 32);
|
2013-11-15 14:37:14 +04:00
|
|
|
}
|
2014-01-10 15:32:57 +04:00
|
|
|
M->encr_video.iv = talloc0 (32);
|
2014-08-06 19:45:46 +02:00
|
|
|
l = prefetch_strlen (mtp);
|
2013-11-15 14:37:14 +04:00
|
|
|
assert (l > 0);
|
|
|
|
if (l <= 32) {
|
2014-08-06 19:45:46 +02:00
|
|
|
memcpy (M->encr_video.iv + (32 - l), fetch_str (mtp, l), l);
|
2013-11-15 14:37:14 +04:00
|
|
|
} else {
|
2014-08-06 19:45:46 +02:00
|
|
|
memcpy (M->encr_video.iv, fetch_str (mtp, l) + (l - 32), 32);
|
2013-11-15 14:37:14 +04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case CODE_decrypted_message_media_document:
|
|
|
|
M->type = x;
|
2014-08-06 19:45:46 +02:00
|
|
|
l = prefetch_strlen (mtp);
|
|
|
|
fetch_str (mtp, l); // thumb
|
|
|
|
fetch_int (mtp); // thumb_w
|
|
|
|
fetch_int (mtp); // thumb_h
|
|
|
|
M->encr_document.file_name = fetch_str_dup (mtp);
|
|
|
|
M->encr_document.mime_type = fetch_str_dup (mtp);
|
|
|
|
M->encr_video.size = fetch_int (mtp);
|
2013-11-02 21:01:22 +04:00
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
l = prefetch_strlen (mtp);
|
2013-11-02 21:01:22 +04:00
|
|
|
assert (l > 0);
|
2014-01-10 15:32:57 +04:00
|
|
|
M->encr_video.key = talloc0 (32);
|
2013-11-04 21:34:27 +04:00
|
|
|
if (l <= 32) {
|
2014-08-06 19:45:46 +02:00
|
|
|
memcpy (M->encr_video.key + (32 - l), fetch_str (mtp, l), l);
|
2013-11-04 21:34:27 +04:00
|
|
|
} else {
|
2014-08-06 19:45:46 +02:00
|
|
|
memcpy (M->encr_video.key, fetch_str (mtp, l) + (l - 32), 32);
|
2013-11-04 21:34:27 +04:00
|
|
|
}
|
2014-01-10 15:32:57 +04:00
|
|
|
M->encr_video.iv = talloc0 (32);
|
2014-08-06 19:45:46 +02:00
|
|
|
l = prefetch_strlen (mtp);
|
2013-11-04 21:34:27 +04:00
|
|
|
assert (l > 0);
|
|
|
|
if (l <= 32) {
|
2014-08-06 19:45:46 +02:00
|
|
|
memcpy (M->encr_video.iv + (32 - l), fetch_str (mtp, l), l);
|
2013-11-04 21:34:27 +04:00
|
|
|
} else {
|
2014-08-06 19:45:46 +02:00
|
|
|
memcpy (M->encr_video.iv, fetch_str (mtp, l) + (l - 32), 32);
|
2013-11-04 21:34:27 +04:00
|
|
|
}
|
2013-11-02 21:01:22 +04:00
|
|
|
break;
|
|
|
|
/* case CODE_decrypted_message_media_file:
|
|
|
|
M->type = x;
|
2014-08-06 19:45:46 +02:00
|
|
|
M->encr_file.filename = fetch_str_dup (mtp);
|
|
|
|
l = prefetch_strlen (mtp);
|
|
|
|
fetch_str (mtp, l); // thumb
|
|
|
|
l = fetch_int (mtp);
|
2013-11-02 21:01:22 +04:00
|
|
|
assert (l > 0);
|
2014-01-10 15:32:57 +04:00
|
|
|
M->encr_file.key = talloc (l);
|
2014-08-06 19:45:46 +02:00
|
|
|
memcpy (M->encr_file.key, fetch_str (mtp, l), l);
|
2013-11-02 21:01:22 +04:00
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
l = fetch_int (mtp);
|
2013-11-02 21:01:22 +04:00
|
|
|
assert (l > 0);
|
2014-01-10 15:32:57 +04:00
|
|
|
M->encr_file.iv = talloc (l);
|
2014-08-06 19:45:46 +02:00
|
|
|
memcpy (M->encr_file.iv, fetch_str (mtp, l), l);
|
2013-11-02 21:01:22 +04:00
|
|
|
break;
|
|
|
|
*/
|
|
|
|
case CODE_decrypted_message_media_geo_point:
|
2014-08-06 19:45:46 +02:00
|
|
|
M->geo.longitude = fetch_double (mtp);
|
|
|
|
M->geo.latitude = fetch_double (mtp);
|
2013-11-02 21:01:22 +04:00
|
|
|
M->type = CODE_message_media_geo;
|
|
|
|
break;
|
|
|
|
case CODE_decrypted_message_media_contact:
|
|
|
|
M->type = CODE_message_media_contact;
|
2014-08-06 19:45:46 +02:00
|
|
|
M->phone = fetch_str_dup (mtp);
|
|
|
|
M->first_name = fetch_str_dup (mtp);
|
|
|
|
M->last_name = fetch_str_dup (mtp);
|
|
|
|
M->user_id = fetch_int (mtp);
|
2013-11-02 21:01:22 +04:00
|
|
|
break;
|
|
|
|
default:
|
2014-10-03 14:23:15 +02:00
|
|
|
debug ("type = 0x%08x\n", x);
|
2013-11-30 01:43:56 +04:00
|
|
|
assert (0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
void fetch_skip_message_action_encrypted (struct mtproto_connection *mtp) {
|
|
|
|
unsigned x = fetch_int (mtp);
|
2013-11-30 01:43:56 +04:00
|
|
|
switch (x) {
|
|
|
|
case CODE_decrypted_message_action_set_message_t_t_l:
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_skip (mtp, 1);
|
2013-11-30 01:43:56 +04:00
|
|
|
break;
|
|
|
|
default:
|
2014-10-03 14:23:15 +02:00
|
|
|
debug ("x = 0x%08x\n", x);
|
2013-11-30 01:43:56 +04:00
|
|
|
assert (0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
void fetch_message_action_encrypted (struct mtproto_connection *mtp, struct message_action *M) {
|
|
|
|
unsigned x = fetch_int (mtp);
|
2013-11-30 01:43:56 +04:00
|
|
|
switch (x) {
|
|
|
|
case CODE_decrypted_message_action_set_message_t_t_l:
|
|
|
|
M->type = x;
|
2014-08-06 19:45:46 +02:00
|
|
|
M->ttl = fetch_int (mtp);
|
2013-11-30 01:43:56 +04:00
|
|
|
break;
|
|
|
|
default:
|
2014-10-03 14:23:15 +02:00
|
|
|
debug ("x = 0x%08x\n", x);
|
2013-11-02 21:01:22 +04:00
|
|
|
assert (0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
peer_id_t fetch_peer_id (struct mtproto_connection *mtp) {
|
|
|
|
unsigned x =fetch_int (mtp);
|
2013-10-18 20:00:47 +04:00
|
|
|
if (x == CODE_peer_user) {
|
2014-08-06 19:45:46 +02:00
|
|
|
return MK_USER (fetch_int (mtp));
|
2013-10-18 20:00:47 +04:00
|
|
|
} else {
|
|
|
|
assert (CODE_peer_chat);
|
2014-08-06 19:45:46 +02:00
|
|
|
return MK_CHAT (fetch_int (mtp));
|
2013-10-18 20:00:47 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
void fetch_message (struct mtproto_connection *mtp, struct message *M) {
|
|
|
|
unsigned x = fetch_int (mtp);
|
2013-10-14 21:26:25 +04:00
|
|
|
assert (x == CODE_message_empty || x == CODE_message || x == CODE_message_forwarded || x == CODE_message_service);
|
2014-08-06 19:45:46 +02:00
|
|
|
int id = fetch_int (mtp);
|
2013-11-30 01:43:56 +04:00
|
|
|
assert (M->id == id);
|
2013-10-14 21:26:25 +04:00
|
|
|
if (x == CODE_message_empty) {
|
|
|
|
return;
|
|
|
|
}
|
2013-11-30 01:43:56 +04:00
|
|
|
int fwd_from_id = 0;
|
|
|
|
int fwd_date = 0;
|
|
|
|
|
2013-10-14 21:26:25 +04:00
|
|
|
if (x == CODE_message_forwarded) {
|
2014-08-06 19:45:46 +02:00
|
|
|
fwd_from_id = fetch_int (mtp);
|
|
|
|
fwd_date = fetch_int (mtp);
|
2013-10-14 21:26:25 +04:00
|
|
|
}
|
2014-08-06 19:45:46 +02:00
|
|
|
int from_id = fetch_int (mtp);
|
|
|
|
peer_id_t to_id = fetch_peer_id (mtp);
|
2013-11-30 01:43:56 +04:00
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_bool (mtp); // out.
|
2013-11-30 01:43:56 +04:00
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
int unread = fetch_bool (mtp);
|
|
|
|
int date = fetch_int (mtp);
|
2013-11-30 01:43:56 +04:00
|
|
|
|
|
|
|
int new = !(M->flags & FLAG_CREATED);
|
|
|
|
|
2013-10-14 21:26:25 +04:00
|
|
|
if (x == CODE_message_service) {
|
2014-08-06 19:45:46 +02:00
|
|
|
int *start = mtp->in_ptr;
|
|
|
|
fetch_skip_message_action (mtp);
|
2013-11-30 01:43:56 +04:00
|
|
|
if (new) {
|
|
|
|
if (fwd_from_id) {
|
2014-08-22 17:05:29 +02:00
|
|
|
bl_do_create_message_service_fwd (mtp->bl, mtp, id, from_id, get_peer_type (to_id), get_peer_id (to_id),
|
2014-08-06 19:45:46 +02:00
|
|
|
date, fwd_from_id, fwd_date, start, (mtp->in_ptr - start));
|
2013-11-30 01:43:56 +04:00
|
|
|
} else {
|
2014-08-22 17:05:29 +02:00
|
|
|
bl_do_create_message_service (mtp->bl, mtp, id, from_id, get_peer_type (to_id),
|
2014-08-06 19:45:46 +02:00
|
|
|
get_peer_id (to_id), date, start, (mtp->in_ptr - start));
|
2013-11-30 01:43:56 +04:00
|
|
|
}
|
|
|
|
}
|
2013-10-14 21:26:25 +04:00
|
|
|
} else {
|
2014-08-06 19:45:46 +02:00
|
|
|
int l = prefetch_strlen (mtp);
|
|
|
|
char *s = fetch_str (mtp, l);
|
|
|
|
int *start = mtp->in_ptr;
|
|
|
|
fetch_skip_message_media (mtp);
|
2013-11-30 01:43:56 +04:00
|
|
|
if (new) {
|
|
|
|
if (fwd_from_id) {
|
2014-08-22 17:05:29 +02:00
|
|
|
bl_do_create_message_media_fwd (mtp->bl, mtp, id, from_id, get_peer_type (to_id),
|
2014-08-06 19:45:46 +02:00
|
|
|
get_peer_id (to_id), date, fwd_from_id, fwd_date, l, s, start, mtp->in_ptr - start);
|
2013-11-30 01:43:56 +04:00
|
|
|
} else {
|
2014-08-22 17:05:29 +02:00
|
|
|
bl_do_create_message_media (mtp->bl, mtp, id, from_id, get_peer_type (to_id),
|
2014-08-06 19:45:46 +02:00
|
|
|
get_peer_id (to_id), date, l, s, start, mtp->in_ptr - start);
|
2013-11-30 01:43:56 +04:00
|
|
|
}
|
|
|
|
}
|
2013-10-13 16:30:53 +04:00
|
|
|
}
|
2014-08-22 17:05:29 +02:00
|
|
|
bl_do_set_unread (mtp->bl, mtp, M, unread);
|
2013-10-13 16:30:53 +04:00
|
|
|
}
|
2013-10-13 14:18:08 +04:00
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
void fetch_geo_message (struct mtproto_connection *mtp, struct message *M) {
|
2013-11-01 23:57:57 +04:00
|
|
|
memset (M, 0, sizeof (*M));
|
2014-08-06 19:45:46 +02:00
|
|
|
unsigned x = fetch_int (mtp);
|
2013-11-01 23:57:57 +04:00
|
|
|
assert (x == CODE_geo_chat_message_empty || x == CODE_geo_chat_message || x == CODE_geo_chat_message_service);
|
2014-08-06 19:45:46 +02:00
|
|
|
M->to_id = MK_GEO_CHAT (fetch_int (mtp));
|
|
|
|
M->id = fetch_int (mtp);
|
2013-11-01 23:57:57 +04:00
|
|
|
if (x == CODE_geo_chat_message_empty) {
|
|
|
|
M->flags |= 1;
|
|
|
|
return;
|
|
|
|
}
|
2014-08-06 19:45:46 +02:00
|
|
|
M->from_id = MK_USER (fetch_int (mtp));
|
|
|
|
M->date = fetch_int (mtp);
|
2013-11-01 23:57:57 +04:00
|
|
|
if (x == CODE_geo_chat_message_service) {
|
|
|
|
M->service = 1;
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_message_action (mtp, &M->action);
|
2013-11-01 23:57:57 +04:00
|
|
|
} else {
|
2014-08-06 19:45:46 +02:00
|
|
|
M->message = fetch_str_dup (mtp);
|
2014-01-21 18:36:46 +04:00
|
|
|
M->message_len = strlen (M->message);
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_message_media (mtp, &M->media);
|
2013-11-01 23:57:57 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-25 20:13:36 +04:00
|
|
|
static int *decr_ptr;
|
|
|
|
static int *decr_end;
|
2013-11-02 14:14:30 +04:00
|
|
|
|
|
|
|
int decrypt_encrypted_message (struct secret_chat *E) {
|
|
|
|
int *msg_key = decr_ptr;
|
|
|
|
decr_ptr += 4;
|
|
|
|
assert (decr_ptr < decr_end);
|
|
|
|
static unsigned char sha1a_buffer[20];
|
|
|
|
static unsigned char sha1b_buffer[20];
|
|
|
|
static unsigned char sha1c_buffer[20];
|
|
|
|
static unsigned char sha1d_buffer[20];
|
|
|
|
|
|
|
|
static unsigned char buf[64];
|
|
|
|
memcpy (buf, msg_key, 16);
|
|
|
|
memcpy (buf + 16, E->key, 32);
|
|
|
|
sha1 (buf, 48, sha1a_buffer);
|
|
|
|
|
|
|
|
memcpy (buf, E->key + 8, 16);
|
|
|
|
memcpy (buf + 16, msg_key, 16);
|
|
|
|
memcpy (buf + 32, E->key + 12, 16);
|
|
|
|
sha1 (buf, 48, sha1b_buffer);
|
|
|
|
|
|
|
|
memcpy (buf, E->key + 16, 32);
|
|
|
|
memcpy (buf + 32, msg_key, 16);
|
|
|
|
sha1 (buf, 48, sha1c_buffer);
|
|
|
|
|
|
|
|
memcpy (buf, msg_key, 16);
|
|
|
|
memcpy (buf + 16, E->key + 24, 32);
|
|
|
|
sha1 (buf, 48, sha1d_buffer);
|
|
|
|
|
|
|
|
static unsigned char key[32];
|
2013-11-04 21:34:27 +04:00
|
|
|
memcpy (key, sha1a_buffer + 0, 8);
|
|
|
|
memcpy (key + 8, sha1b_buffer + 8, 12);
|
|
|
|
memcpy (key + 20, sha1c_buffer + 4, 12);
|
|
|
|
|
|
|
|
static unsigned char iv[32];
|
|
|
|
memcpy (iv, sha1a_buffer + 8, 12);
|
|
|
|
memcpy (iv + 12, sha1b_buffer + 0, 8);
|
|
|
|
memcpy (iv + 20, sha1c_buffer + 16, 4);
|
|
|
|
memcpy (iv + 24, sha1d_buffer + 0, 8);
|
2013-11-02 14:14:30 +04:00
|
|
|
|
|
|
|
AES_KEY aes_key;
|
|
|
|
AES_set_decrypt_key (key, 256, &aes_key);
|
|
|
|
AES_ige_encrypt ((void *)decr_ptr, (void *)decr_ptr, 4 * (decr_end - decr_ptr), &aes_key, iv, 0);
|
2014-01-21 20:02:34 +04:00
|
|
|
memset (&aes_key, 0, sizeof (aes_key));
|
2013-11-02 14:14:30 +04:00
|
|
|
|
2013-11-04 21:34:27 +04:00
|
|
|
int x = *(decr_ptr);
|
2013-11-06 02:24:26 +04:00
|
|
|
if (x < 0 || (x & 3)) {
|
|
|
|
return -1;
|
|
|
|
}
|
2013-11-04 21:34:27 +04:00
|
|
|
assert (x >= 0 && !(x & 3));
|
|
|
|
sha1 ((void *)decr_ptr, 4 + x, sha1a_buffer);
|
2013-11-02 14:14:30 +04:00
|
|
|
|
2013-11-04 21:34:27 +04:00
|
|
|
if (memcmp (sha1a_buffer + 4, msg_key, 16)) {
|
2014-10-03 14:23:15 +02:00
|
|
|
failure ("Sha1 mismatch\n");
|
2013-11-02 14:14:30 +04:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
void fetch_encrypted_message (struct mtproto_connection *mtp, struct message *M) {
|
2014-09-01 21:25:41 +02:00
|
|
|
struct binlog *bl = mtp->bl;
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
unsigned x = fetch_int (mtp);
|
2013-11-02 14:14:30 +04:00
|
|
|
assert (x == CODE_encrypted_message || x == CODE_encrypted_message_service);
|
2013-11-04 21:34:27 +04:00
|
|
|
unsigned sx = x;
|
2013-11-30 01:43:56 +04:00
|
|
|
int new = !(M->flags & FLAG_CREATED);
|
2014-08-06 19:45:46 +02:00
|
|
|
long long id = fetch_long (mtp);
|
|
|
|
int to_id = fetch_int (mtp);
|
2013-11-30 01:43:56 +04:00
|
|
|
peer_id_t chat = MK_ENCR_CHAT (to_id);
|
2014-08-06 19:45:46 +02:00
|
|
|
int date = fetch_int (mtp);
|
2013-11-30 01:43:56 +04:00
|
|
|
|
2014-09-01 21:25:41 +02:00
|
|
|
peer_t *P = user_chat_get (bl, chat);
|
2013-11-02 14:14:30 +04:00
|
|
|
if (!P) {
|
2014-10-03 14:23:15 +02:00
|
|
|
warning ("Encrypted message to unknown chat. Dropping\n");
|
2013-11-21 23:35:49 +04:00
|
|
|
M->flags |= FLAG_MESSAGE_EMPTY;
|
2013-11-02 14:14:30 +04:00
|
|
|
}
|
|
|
|
|
2013-11-04 21:34:27 +04:00
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
int len = prefetch_strlen (mtp);
|
2013-11-04 21:34:27 +04:00
|
|
|
assert ((len & 15) == 8);
|
2014-08-06 19:45:46 +02:00
|
|
|
decr_ptr = (void *)fetch_str (mtp, len);
|
2013-11-04 21:34:27 +04:00
|
|
|
decr_end = decr_ptr + (len / 4);
|
|
|
|
int ok = 0;
|
|
|
|
if (P) {
|
|
|
|
if (*(long long *)decr_ptr != P->encr_chat.key_fingerprint) {
|
2014-10-03 14:23:15 +02:00
|
|
|
warning ("Encrypted message with bad fingerprint to chat %s\n", P->print_name);
|
2013-11-04 21:34:27 +04:00
|
|
|
P = 0;
|
|
|
|
}
|
|
|
|
decr_ptr += 2;
|
|
|
|
}
|
2013-11-30 01:43:56 +04:00
|
|
|
int l = 0;
|
|
|
|
char *s = 0;
|
|
|
|
int *start = 0;
|
|
|
|
int *end = 0;
|
|
|
|
x = 0;
|
|
|
|
if (P && decrypt_encrypted_message (&P->encr_chat) >= 0 && new) {
|
2013-11-04 21:34:27 +04:00
|
|
|
ok = 1;
|
2014-08-06 19:45:46 +02:00
|
|
|
int *save_in_ptr = mtp->in_ptr;
|
|
|
|
int *save_in_end = mtp->in_end;
|
|
|
|
mtp->in_ptr = decr_ptr;
|
|
|
|
int ll = fetch_int (mtp);
|
|
|
|
mtp->in_end = mtp->in_ptr + ll;
|
|
|
|
x = fetch_int (mtp);
|
2013-11-02 14:14:30 +04:00
|
|
|
if (x == CODE_decrypted_message_layer) {
|
2014-08-06 19:45:46 +02:00
|
|
|
int layer = fetch_int (mtp);
|
2013-11-02 14:14:30 +04:00
|
|
|
assert (layer >= 0);
|
2014-08-06 19:45:46 +02:00
|
|
|
x = fetch_int (mtp);
|
2013-11-02 14:14:30 +04:00
|
|
|
}
|
2013-11-04 21:34:27 +04:00
|
|
|
assert (x == CODE_decrypted_message || x == CODE_decrypted_message_service);
|
2014-08-06 19:45:46 +02:00
|
|
|
//assert (id == fetch_long (mtp));
|
|
|
|
fetch_long (mtp);
|
|
|
|
ll = prefetch_strlen (mtp);
|
|
|
|
fetch_str (mtp, ll); // random_bytes
|
2013-11-02 21:01:22 +04:00
|
|
|
if (x == CODE_decrypted_message) {
|
2014-08-06 19:45:46 +02:00
|
|
|
l = prefetch_strlen (mtp);
|
|
|
|
s = fetch_str (mtp, l);
|
|
|
|
start = mtp->in_ptr;
|
|
|
|
fetch_skip_message_media_encrypted (mtp);
|
|
|
|
end = mtp->in_ptr;
|
2013-11-02 21:01:22 +04:00
|
|
|
} else {
|
2014-08-06 19:45:46 +02:00
|
|
|
start = mtp->in_ptr;
|
|
|
|
fetch_skip_message_action_encrypted (mtp);
|
|
|
|
end = mtp->in_ptr;
|
2013-11-02 21:01:22 +04:00
|
|
|
}
|
2014-08-06 19:45:46 +02:00
|
|
|
mtp->in_ptr = save_in_ptr;
|
|
|
|
mtp->in_end = save_in_end;
|
2013-11-04 21:34:27 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (sx == CODE_encrypted_message) {
|
|
|
|
if (ok) {
|
2014-08-06 19:45:46 +02:00
|
|
|
int *start_file = mtp->in_ptr;
|
|
|
|
fetch_skip_encrypted_message_file (mtp);
|
2013-11-30 01:43:56 +04:00
|
|
|
if (x == CODE_decrypted_message) {
|
2014-08-22 17:05:29 +02:00
|
|
|
bl_do_create_message_media_encr (mtp->bl, mtp, id, P->encr_chat.user_id, PEER_ENCR_CHAT, to_id, date, l, s, start, end - start, start_file, mtp->in_ptr - start_file);
|
2013-11-30 01:43:56 +04:00
|
|
|
}
|
2013-11-04 21:34:27 +04:00
|
|
|
} else {
|
2014-08-06 19:45:46 +02:00
|
|
|
x = fetch_int (mtp);
|
2013-11-04 21:34:27 +04:00
|
|
|
if (x == CODE_encrypted_file) {
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_skip (mtp, 7);
|
2013-11-04 21:34:27 +04:00
|
|
|
} else {
|
|
|
|
assert (x == CODE_encrypted_file_empty);
|
|
|
|
}
|
|
|
|
M->media.type = CODE_message_media_empty;
|
|
|
|
}
|
2013-11-30 01:43:56 +04:00
|
|
|
} else {
|
|
|
|
if (ok && x == CODE_decrypted_message_service) {
|
2014-08-22 17:05:29 +02:00
|
|
|
bl_do_create_message_service_encr (mtp->bl, mtp, id, P->encr_chat.user_id, PEER_ENCR_CHAT, to_id, date, start, end - start);
|
2013-11-30 01:43:56 +04:00
|
|
|
}
|
2013-11-02 21:01:22 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
void fetch_encrypted_message_file (struct mtproto_connection *mtp, struct message_media *M) {
|
|
|
|
unsigned x = fetch_int (mtp);
|
2013-11-02 21:01:22 +04:00
|
|
|
assert (x == CODE_encrypted_file || x == CODE_encrypted_file_empty);
|
|
|
|
if (x == CODE_encrypted_file_empty) {
|
|
|
|
assert (M->type != CODE_decrypted_message_media_photo && M->type != CODE_decrypted_message_media_video);
|
|
|
|
} else {
|
2014-03-07 02:43:15 +04:00
|
|
|
assert (M->type == CODE_decrypted_message_media_document || M->type == CODE_decrypted_message_media_photo || M->type == CODE_decrypted_message_media_video || M->type == CODE_decrypted_message_media_audio);
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
M->encr_photo.id = fetch_long(mtp);
|
|
|
|
M->encr_photo.access_hash = fetch_long(mtp);
|
2014-03-07 02:44:41 +04:00
|
|
|
if (!M->encr_photo.size) {
|
2014-08-06 19:45:46 +02:00
|
|
|
M->encr_photo.size = fetch_int (mtp);
|
2014-03-07 02:44:41 +04:00
|
|
|
} else {
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_int (mtp);
|
2014-03-07 02:44:41 +04:00
|
|
|
}
|
2014-08-06 19:45:46 +02:00
|
|
|
M->encr_photo.dc_id = fetch_int(mtp);
|
|
|
|
M->encr_photo.key_fingerprint = fetch_int(mtp);
|
2013-11-02 14:14:30 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
void fetch_skip_encrypted_message_file (struct mtproto_connection *mtp) {
|
|
|
|
unsigned x = fetch_int (mtp);
|
2013-11-30 01:43:56 +04:00
|
|
|
assert (x == CODE_encrypted_file || x == CODE_encrypted_file_empty);
|
|
|
|
if (x == CODE_encrypted_file_empty) {
|
|
|
|
} else {
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_skip (mtp, 7);
|
2013-11-30 01:43:56 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-02 14:14:30 +04:00
|
|
|
static int id_cmp (struct message *M1, struct message *M2) {
|
|
|
|
if (M1->id < M2->id) { return -1; }
|
|
|
|
else if (M1->id > M2->id) { return 1; }
|
|
|
|
else { return 0; }
|
|
|
|
}
|
|
|
|
|
2014-09-06 21:33:46 +02:00
|
|
|
struct tgl_user *fetch_alloc_user (struct mtproto_connection *mtp) {
|
2014-09-01 21:25:41 +02:00
|
|
|
struct binlog *bl = mtp->instance->bl;
|
|
|
|
|
2014-10-03 14:23:15 +02:00
|
|
|
debug("fetch_alloc_user()\n");
|
2013-10-24 21:04:44 +04:00
|
|
|
int data[2];
|
2014-08-06 19:45:46 +02:00
|
|
|
prefetch_data (mtp, data, 8);
|
2014-09-01 21:25:41 +02:00
|
|
|
peer_t *U = user_chat_get (bl, MK_USER (data[1]));
|
2013-11-21 23:35:49 +04:00
|
|
|
if (!U) {
|
2014-09-01 21:25:41 +02:00
|
|
|
bl->users_allocated ++;
|
2014-01-10 15:32:57 +04:00
|
|
|
U = talloc0 (sizeof (*U));
|
2013-11-21 23:35:49 +04:00
|
|
|
U->id = MK_USER (data[1]);
|
2014-09-01 21:25:41 +02:00
|
|
|
bl->peer_tree = tree_insert_peer (bl->peer_tree, U, lrand48 ());
|
|
|
|
assert (bl->peer_num < MAX_PEER_NUM);
|
|
|
|
bl->Peers[bl->peer_num ++] = U;
|
2014-08-17 22:01:04 +02:00
|
|
|
fetch_user (mtp, &U->user);
|
|
|
|
event_update_user_status(mtp->connection->instance, U);
|
2014-08-23 02:50:11 +02:00
|
|
|
event_peer_allocated(mtp->connection->instance, U);
|
2014-08-17 22:01:04 +02:00
|
|
|
} else {
|
|
|
|
fetch_user (mtp, &U->user);
|
|
|
|
event_update_user_status(mtp->connection->instance, U);
|
2014-06-22 23:36:52 +02:00
|
|
|
}
|
2013-11-21 23:35:49 +04:00
|
|
|
return &U->user;
|
2013-10-13 14:18:08 +04:00
|
|
|
}
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
struct secret_chat *fetch_alloc_encrypted_chat (struct mtproto_connection *mtp) {
|
2014-09-01 21:25:41 +02:00
|
|
|
struct binlog *bl = mtp->bl;
|
|
|
|
|
2014-10-03 14:23:15 +02:00
|
|
|
debug("fetch_alloc_encrypted_chat()\n");
|
2013-11-02 21:01:22 +04:00
|
|
|
int data[2];
|
2014-08-06 19:45:46 +02:00
|
|
|
prefetch_data (mtp, data, 8);
|
2014-09-01 21:25:41 +02:00
|
|
|
peer_t *U = user_chat_get (bl, MK_ENCR_CHAT (data[1]));
|
2013-11-21 23:35:49 +04:00
|
|
|
if (!U) {
|
2014-01-10 15:32:57 +04:00
|
|
|
U = talloc0 (sizeof (*U));
|
2013-11-21 23:35:49 +04:00
|
|
|
U->id = MK_ENCR_CHAT (data[1]);
|
2014-09-01 21:25:41 +02:00
|
|
|
bl->encr_chats_allocated ++;
|
|
|
|
bl->peer_tree = tree_insert_peer (bl->peer_tree, U, lrand48 ());
|
|
|
|
assert (bl->peer_num < MAX_PEER_NUM);
|
|
|
|
bl->Peers[bl->peer_num ++] = U;
|
2013-11-02 21:01:22 +04:00
|
|
|
}
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_encrypted_chat (mtp, &U->encr_chat);
|
2014-08-23 02:50:11 +02:00
|
|
|
event_peer_allocated(mtp->connection->instance, U);
|
2013-11-21 23:35:49 +04:00
|
|
|
return &U->encr_chat;
|
2013-11-02 21:01:22 +04:00
|
|
|
}
|
|
|
|
|
2014-09-01 21:25:41 +02:00
|
|
|
void insert_encrypted_chat (struct binlog *bl, peer_t *P) {
|
|
|
|
bl->encr_chats_allocated ++;
|
|
|
|
bl->peer_tree = tree_insert_peer (bl->peer_tree, P, lrand48 ());
|
|
|
|
assert (bl->peer_num < MAX_PEER_NUM);
|
|
|
|
bl->Peers[bl->peer_num ++] = P;
|
2013-11-04 21:34:27 +04:00
|
|
|
}
|
|
|
|
|
2014-09-01 21:25:41 +02:00
|
|
|
void insert_user (struct binlog *bl, peer_t *P) {
|
|
|
|
bl->users_allocated ++;
|
|
|
|
bl->peer_tree = tree_insert_peer (bl->peer_tree, P, lrand48 ());
|
|
|
|
assert (bl->peer_num < MAX_PEER_NUM);
|
|
|
|
bl->Peers[bl->peer_num ++] = P;
|
2013-11-21 23:35:49 +04:00
|
|
|
}
|
|
|
|
|
2014-09-01 21:25:41 +02:00
|
|
|
void insert_chat (struct binlog *bl, peer_t *P) {
|
|
|
|
bl->chats_allocated ++;
|
|
|
|
bl->peer_tree = tree_insert_peer (bl->peer_tree, P, lrand48 ());
|
|
|
|
assert (bl->peer_num < MAX_PEER_NUM);
|
|
|
|
bl->Peers[bl->peer_num ++] = P;
|
2013-11-23 03:26:35 +04:00
|
|
|
}
|
|
|
|
|
2014-09-06 21:33:46 +02:00
|
|
|
struct tgl_user *fetch_alloc_user_full (struct mtproto_connection *mtp) {
|
2014-09-01 21:25:41 +02:00
|
|
|
struct binlog *bl = mtp->bl;
|
2013-10-25 21:29:02 +04:00
|
|
|
int data[3];
|
2014-08-06 19:45:46 +02:00
|
|
|
prefetch_data (mtp, data, 12);
|
2014-09-01 21:25:41 +02:00
|
|
|
peer_t *U = user_chat_get (bl, MK_USER (data[2]));
|
2013-10-25 21:29:02 +04:00
|
|
|
if (U) {
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_user_full (mtp, &U->user);
|
2013-10-25 21:29:02 +04:00
|
|
|
return &U->user;
|
|
|
|
} else {
|
2014-09-01 21:25:41 +02:00
|
|
|
bl->users_allocated ++;
|
2014-01-10 15:32:57 +04:00
|
|
|
U = talloc0 (sizeof (*U));
|
2013-11-01 03:18:34 +04:00
|
|
|
U->id = MK_USER (data[2]);
|
2014-09-01 21:25:41 +02:00
|
|
|
bl->peer_tree = tree_insert_peer (bl->peer_tree, U, lrand48 ());
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_user_full (mtp, &U->user);
|
2014-09-01 21:25:41 +02:00
|
|
|
assert (bl->peer_num < MAX_PEER_NUM);
|
|
|
|
bl->Peers[bl->peer_num ++] = U;
|
2013-10-25 21:29:02 +04:00
|
|
|
return &U->user;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-06 21:33:46 +02:00
|
|
|
void free_user (struct tgl_user *U) {
|
2014-01-10 18:37:56 +04:00
|
|
|
if (U->first_name) { tfree_str (U->first_name); }
|
|
|
|
if (U->last_name) { tfree_str (U->last_name); }
|
|
|
|
if (U->print_name) { tfree_str (U->print_name); }
|
|
|
|
if (U->phone) { tfree_str (U->phone); }
|
2013-10-13 14:18:08 +04:00
|
|
|
}
|
|
|
|
|
2013-10-14 21:26:25 +04:00
|
|
|
void free_photo_size (struct photo_size *S) {
|
2014-01-10 18:37:56 +04:00
|
|
|
tfree_str (S->type);
|
2013-10-18 20:00:47 +04:00
|
|
|
if (S->data) {
|
2014-01-10 18:37:56 +04:00
|
|
|
tfree (S->data, S->size);
|
2013-10-18 20:00:47 +04:00
|
|
|
}
|
2013-10-14 21:26:25 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void free_photo (struct photo *P) {
|
2013-10-18 20:00:47 +04:00
|
|
|
if (!P->access_hash) { return; }
|
2014-01-10 18:37:56 +04:00
|
|
|
if (P->caption) { tfree_str (P->caption); }
|
2013-10-18 20:00:47 +04:00
|
|
|
if (P->sizes) {
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < P->sizes_num; i++) {
|
|
|
|
free_photo_size (&P->sizes[i]);
|
|
|
|
}
|
2014-01-10 18:37:56 +04:00
|
|
|
tfree (P->sizes, sizeof (struct photo_size) * P->sizes_num);
|
2013-10-14 21:26:25 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void free_video (struct video *V) {
|
2013-10-18 20:00:47 +04:00
|
|
|
if (!V->access_hash) { return; }
|
2014-01-10 18:37:56 +04:00
|
|
|
tfree_str (V->caption);
|
2013-10-18 20:00:47 +04:00
|
|
|
free_photo_size (&V->thumb);
|
2013-10-14 21:26:25 +04:00
|
|
|
}
|
|
|
|
|
2013-11-15 14:37:14 +04:00
|
|
|
void free_document (struct document *D) {
|
|
|
|
if (!D->access_hash) { return; }
|
2014-01-10 18:37:56 +04:00
|
|
|
tfree_str (D->caption);
|
|
|
|
tfree_str (D->mime_type);
|
2013-11-15 14:37:14 +04:00
|
|
|
free_photo_size (&D->thumb);
|
|
|
|
}
|
|
|
|
|
2013-10-14 21:26:25 +04:00
|
|
|
void free_message_media (struct message_media *M) {
|
|
|
|
switch (M->type) {
|
|
|
|
case CODE_message_media_empty:
|
2013-10-19 15:46:41 +04:00
|
|
|
case CODE_message_media_geo:
|
2013-11-15 14:37:14 +04:00
|
|
|
case CODE_message_media_audio:
|
2013-10-14 21:26:25 +04:00
|
|
|
return;
|
|
|
|
case CODE_message_media_photo:
|
|
|
|
free_photo (&M->photo);
|
|
|
|
return;
|
|
|
|
case CODE_message_media_video:
|
|
|
|
free_video (&M->video);
|
|
|
|
return;
|
|
|
|
case CODE_message_media_contact:
|
2014-01-10 18:37:56 +04:00
|
|
|
tfree_str (M->phone);
|
|
|
|
tfree_str (M->first_name);
|
|
|
|
tfree_str (M->last_name);
|
2013-10-14 21:26:25 +04:00
|
|
|
return;
|
2013-11-15 14:37:14 +04:00
|
|
|
case CODE_message_media_document:
|
|
|
|
free_document (&M->document);
|
|
|
|
return;
|
2013-10-14 21:26:25 +04:00
|
|
|
case CODE_message_media_unsupported:
|
2014-01-10 18:37:56 +04:00
|
|
|
tfree (M->data, M->data_size);
|
2013-10-14 21:26:25 +04:00
|
|
|
return;
|
2013-11-02 21:01:22 +04:00
|
|
|
case CODE_decrypted_message_media_photo:
|
2013-11-15 14:37:14 +04:00
|
|
|
case CODE_decrypted_message_media_video:
|
|
|
|
case CODE_decrypted_message_media_audio:
|
|
|
|
case CODE_decrypted_message_media_document:
|
2014-01-10 18:37:56 +04:00
|
|
|
tfree_secure (M->encr_photo.key, 32);
|
|
|
|
tfree_secure (M->encr_photo.iv, 32);
|
2013-11-02 21:01:22 +04:00
|
|
|
return;
|
2013-11-04 21:34:27 +04:00
|
|
|
case 0:
|
|
|
|
break;
|
2013-10-14 21:26:25 +04:00
|
|
|
default:
|
2014-10-03 14:23:15 +02:00
|
|
|
debug ("%08x\n", M->type);
|
2013-10-14 21:26:25 +04:00
|
|
|
assert (0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void free_message_action (struct message_action *M) {
|
|
|
|
switch (M->type) {
|
|
|
|
case CODE_message_action_empty:
|
|
|
|
break;
|
|
|
|
case CODE_message_action_chat_create:
|
2014-01-10 18:37:56 +04:00
|
|
|
tfree_str (M->title);
|
|
|
|
tfree (M->users, M->user_num * 4);
|
2013-10-14 21:26:25 +04:00
|
|
|
break;
|
|
|
|
case CODE_message_action_chat_edit_title:
|
2014-01-10 18:37:56 +04:00
|
|
|
tfree_str (M->new_title);
|
2013-10-14 21:26:25 +04:00
|
|
|
break;
|
|
|
|
case CODE_message_action_chat_edit_photo:
|
|
|
|
free_photo (&M->photo);
|
|
|
|
break;
|
|
|
|
case CODE_message_action_chat_delete_photo:
|
|
|
|
break;
|
|
|
|
case CODE_message_action_chat_add_user:
|
|
|
|
break;
|
|
|
|
case CODE_message_action_chat_delete_user:
|
|
|
|
break;
|
2013-11-04 21:34:27 +04:00
|
|
|
case 0:
|
|
|
|
break;
|
2013-10-14 21:26:25 +04:00
|
|
|
default:
|
|
|
|
assert (0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void free_message (struct message *M) {
|
|
|
|
if (!M->service) {
|
2014-01-21 18:36:46 +04:00
|
|
|
if (M->message) { tfree (M->message, M->message_len + 1); }
|
2013-10-14 21:26:25 +04:00
|
|
|
free_message_media (&M->media);
|
|
|
|
} else {
|
|
|
|
free_message_action (&M->action);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void message_del_use (struct message *M) {
|
|
|
|
M->next_use->prev_use = M->prev_use;
|
|
|
|
M->prev_use->next_use = M->next_use;
|
|
|
|
}
|
|
|
|
|
|
|
|
void message_add_use (struct message *M) {
|
|
|
|
M->next_use = message_list.next_use;
|
|
|
|
M->prev_use = &message_list;
|
|
|
|
M->next_use->prev_use = M;
|
|
|
|
M->prev_use->next_use = M;
|
|
|
|
}
|
|
|
|
|
2013-11-04 21:34:27 +04:00
|
|
|
void message_add_peer (struct message *M) {
|
2014-09-01 21:25:41 +02:00
|
|
|
struct binlog *bl = M->instance->bl;
|
2013-11-04 21:34:27 +04:00
|
|
|
peer_id_t id;
|
2014-09-01 21:25:41 +02:00
|
|
|
if (!cmp_peer_id (M->to_id, MK_USER (M->instance->our_id))) {
|
2013-11-04 21:34:27 +04:00
|
|
|
id = M->from_id;
|
|
|
|
} else {
|
|
|
|
id = M->to_id;
|
|
|
|
}
|
2014-09-01 21:25:41 +02:00
|
|
|
peer_t *P = user_chat_get (bl, id);
|
2013-11-04 21:34:27 +04:00
|
|
|
if (!P) {
|
2014-01-10 15:32:57 +04:00
|
|
|
P = talloc0 (sizeof (*P));
|
2013-11-04 21:34:27 +04:00
|
|
|
P->id = id;
|
|
|
|
switch (get_peer_type (id)) {
|
|
|
|
case PEER_USER:
|
2014-09-01 21:25:41 +02:00
|
|
|
bl->users_allocated ++;
|
2013-11-04 21:34:27 +04:00
|
|
|
break;
|
|
|
|
case PEER_CHAT:
|
2014-09-01 21:25:41 +02:00
|
|
|
bl->chats_allocated ++;
|
2013-11-04 21:34:27 +04:00
|
|
|
break;
|
|
|
|
case PEER_GEO_CHAT:
|
2014-09-01 21:25:41 +02:00
|
|
|
bl->geo_chats_allocated ++;
|
2013-11-04 21:34:27 +04:00
|
|
|
break;
|
|
|
|
case PEER_ENCR_CHAT:
|
2014-09-01 21:25:41 +02:00
|
|
|
bl->encr_chats_allocated ++;
|
2013-11-04 21:34:27 +04:00
|
|
|
break;
|
|
|
|
}
|
2014-09-01 21:25:41 +02:00
|
|
|
bl->peer_tree = tree_insert_peer (bl->peer_tree, P, lrand48 ());
|
|
|
|
assert (bl->peer_num < MAX_PEER_NUM);
|
|
|
|
bl->Peers[bl->peer_num ++] = P;
|
2013-11-04 21:34:27 +04:00
|
|
|
}
|
2013-11-30 01:43:56 +04:00
|
|
|
if (!P->last) {
|
|
|
|
P->last = M;
|
|
|
|
M->prev = M->next = 0;
|
|
|
|
} else {
|
|
|
|
if (get_peer_type (P->id) != PEER_ENCR_CHAT) {
|
|
|
|
struct message *N = P->last;
|
|
|
|
struct message *NP = 0;
|
|
|
|
while (N && N->id > M->id) {
|
|
|
|
NP = N;
|
|
|
|
N = N->next;
|
|
|
|
}
|
|
|
|
if (N) { assert (N->id < M->id); }
|
|
|
|
M->next = N;
|
|
|
|
M->prev = NP;
|
|
|
|
if (N) { N->prev = M; }
|
|
|
|
if (NP) { NP->next = M; }
|
|
|
|
else { P->last = M; }
|
|
|
|
} else {
|
|
|
|
struct message *N = P->last;
|
|
|
|
struct message *NP = 0;
|
|
|
|
M->next = N;
|
|
|
|
M->prev = NP;
|
|
|
|
if (N) { N->prev = M; }
|
|
|
|
if (NP) { NP->next = M; }
|
|
|
|
else { P->last = M; }
|
|
|
|
}
|
|
|
|
}
|
2013-11-04 21:34:27 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void message_del_peer (struct message *M) {
|
|
|
|
peer_id_t id;
|
2014-09-01 21:25:41 +02:00
|
|
|
if (!cmp_peer_id (M->to_id, MK_USER (M->instance->our_id))) {
|
2013-11-04 21:34:27 +04:00
|
|
|
id = M->from_id;
|
|
|
|
} else {
|
|
|
|
id = M->to_id;
|
|
|
|
}
|
2014-09-01 21:25:41 +02:00
|
|
|
peer_t *P = user_chat_get (M->instance->bl, id);
|
2013-11-04 21:34:27 +04:00
|
|
|
if (M->prev) {
|
|
|
|
M->prev->next = M->next;
|
|
|
|
}
|
|
|
|
if (M->next) {
|
|
|
|
M->next->prev = M->prev;
|
|
|
|
}
|
|
|
|
if (P && P->last == M) {
|
|
|
|
P->last = M->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
struct message *fetch_alloc_message (struct mtproto_connection *mtp, struct telegram *instance) {
|
2014-09-01 21:25:41 +02:00
|
|
|
struct binlog *bl = mtp->bl;
|
|
|
|
|
2014-10-03 14:23:15 +02:00
|
|
|
debug("fetch_alloc_message()\n");
|
2013-11-30 01:43:56 +04:00
|
|
|
int data[2];
|
2014-08-06 19:45:46 +02:00
|
|
|
prefetch_data (mtp, data, 8);
|
2014-09-01 21:25:41 +02:00
|
|
|
struct message *M = message_get (bl, data[1]);
|
2013-11-30 01:43:56 +04:00
|
|
|
|
|
|
|
if (!M) {
|
2014-01-10 15:32:57 +04:00
|
|
|
M = talloc0 (sizeof (*M));
|
2014-08-23 02:50:11 +02:00
|
|
|
M->instance = instance;
|
2014-09-07 20:56:44 +02:00
|
|
|
M->id = data[1];
|
2013-11-30 01:43:56 +04:00
|
|
|
message_insert_tree (M);
|
2014-09-01 21:25:41 +02:00
|
|
|
mtp->bl->messages_allocated ++;
|
2014-08-23 11:18:42 +02:00
|
|
|
fetch_message (mtp, M);
|
|
|
|
return M;
|
2013-11-01 23:57:57 +04:00
|
|
|
}
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_message (mtp, M);
|
2013-11-30 01:43:56 +04:00
|
|
|
return M;
|
2013-11-01 23:57:57 +04:00
|
|
|
}
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
struct message *fetch_alloc_geo_message (struct mtproto_connection *mtp, struct telegram *instance) {
|
2014-10-03 14:23:15 +02:00
|
|
|
debug("fetch_alloc_geo_message()\n");
|
2014-01-10 15:32:57 +04:00
|
|
|
struct message *M = talloc (sizeof (*M));
|
2014-07-26 11:55:45 +02:00
|
|
|
M->instance = instance;
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_geo_message (mtp, M);
|
2014-09-01 21:25:41 +02:00
|
|
|
struct message *M1 = tree_lookup_message (mtp->bl->message_tree, M);
|
|
|
|
mtp->bl->messages_allocated ++;
|
2013-11-01 23:57:57 +04:00
|
|
|
if (M1) {
|
|
|
|
message_del_use (M1);
|
2013-11-04 21:34:27 +04:00
|
|
|
message_del_peer (M1);
|
2013-11-01 23:57:57 +04:00
|
|
|
free_message (M1);
|
|
|
|
memcpy (M1, M, sizeof (*M));
|
2014-01-10 18:37:56 +04:00
|
|
|
tfree (M, sizeof (*M));
|
2013-11-01 23:57:57 +04:00
|
|
|
message_add_use (M1);
|
2013-11-04 21:34:27 +04:00
|
|
|
message_add_peer (M1);
|
2014-09-01 21:25:41 +02:00
|
|
|
mtp->bl->messages_allocated --;
|
2013-11-01 23:57:57 +04:00
|
|
|
return M1;
|
|
|
|
} else {
|
|
|
|
message_add_use (M);
|
2013-11-04 21:34:27 +04:00
|
|
|
message_add_peer (M);
|
2014-09-01 21:25:41 +02:00
|
|
|
mtp->bl->message_tree = tree_insert_message (mtp->bl->message_tree, M, lrand48 ());
|
2013-10-14 21:26:25 +04:00
|
|
|
return M;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
struct message *fetch_alloc_encrypted_message (struct mtproto_connection *mtp,
|
|
|
|
struct telegram *instance) {
|
2014-09-01 21:25:41 +02:00
|
|
|
struct binlog *bl = mtp->bl;
|
2014-10-03 14:23:15 +02:00
|
|
|
debug("fetch_alloc_encrypted_message()\n");
|
2013-11-30 01:43:56 +04:00
|
|
|
int data[3];
|
2014-08-06 19:45:46 +02:00
|
|
|
prefetch_data (mtp, data, 12);
|
2014-09-01 21:25:41 +02:00
|
|
|
struct message *M = message_get (bl, *(long long *)(data + 1));
|
2013-11-30 01:43:56 +04:00
|
|
|
|
|
|
|
if (!M) {
|
2014-01-10 15:32:57 +04:00
|
|
|
M = talloc0 (sizeof (*M));
|
2014-09-07 20:56:44 +02:00
|
|
|
M->instance = instance;
|
2013-11-30 01:43:56 +04:00
|
|
|
M->id = *(long long *)(data + 1);
|
|
|
|
message_insert_tree (M);
|
2014-09-01 21:25:41 +02:00
|
|
|
mtp->bl->messages_allocated ++;
|
|
|
|
assert (message_get (bl, M->id) == M);
|
2014-10-03 14:23:15 +02:00
|
|
|
debug ("id = %lld\n", M->id);
|
2013-11-02 14:14:30 +04:00
|
|
|
}
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_encrypted_message (mtp, M);
|
2013-11-30 01:43:56 +04:00
|
|
|
return M;
|
2013-11-02 14:14:30 +04:00
|
|
|
}
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
struct message *fetch_alloc_message_short (struct mtproto_connection *mtp,
|
|
|
|
struct telegram *instance) {
|
2014-09-01 21:25:41 +02:00
|
|
|
struct binlog *bl = mtp->bl;
|
2013-11-30 01:43:56 +04:00
|
|
|
int data[1];
|
2014-08-06 19:45:46 +02:00
|
|
|
prefetch_data (mtp, data, 4);
|
2014-09-01 21:25:41 +02:00
|
|
|
struct message *M = message_get (bl, data[0]);
|
2013-11-30 01:43:56 +04:00
|
|
|
|
|
|
|
if (!M) {
|
2014-01-10 15:32:57 +04:00
|
|
|
M = talloc0 (sizeof (*M));
|
2014-09-07 20:56:44 +02:00
|
|
|
M->instance = instance;
|
2013-11-30 01:43:56 +04:00
|
|
|
M->id = data[0];
|
|
|
|
message_insert_tree (M);
|
2014-09-01 21:25:41 +02:00
|
|
|
mtp->bl->messages_allocated ++;
|
2013-10-16 23:19:39 +04:00
|
|
|
}
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_message_short (mtp, M);
|
2013-11-30 01:43:56 +04:00
|
|
|
return M;
|
2013-10-16 23:19:39 +04:00
|
|
|
}
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
struct message *fetch_alloc_message_short_chat (struct mtproto_connection *mtp, struct telegram *instance) {
|
2014-09-01 21:25:41 +02:00
|
|
|
struct binlog *bl = mtp->bl;
|
2013-11-30 01:43:56 +04:00
|
|
|
int data[1];
|
2014-08-06 19:45:46 +02:00
|
|
|
prefetch_data (mtp, data, 4);
|
2014-09-01 21:25:41 +02:00
|
|
|
struct message *M = message_get (bl, data[0]);
|
2013-11-30 01:43:56 +04:00
|
|
|
|
|
|
|
if (!M) {
|
2014-01-10 15:32:57 +04:00
|
|
|
M = talloc0 (sizeof (*M));
|
2014-09-07 20:56:44 +02:00
|
|
|
M->instance = instance;
|
2013-11-30 01:43:56 +04:00
|
|
|
M->id = data[0];
|
|
|
|
message_insert_tree (M);
|
2014-09-01 21:25:41 +02:00
|
|
|
mtp->bl->messages_allocated ++;
|
2013-10-16 23:19:39 +04:00
|
|
|
}
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_message_short_chat (mtp, M);
|
2013-11-30 01:43:56 +04:00
|
|
|
return M;
|
2013-10-16 23:19:39 +04:00
|
|
|
}
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
struct chat *fetch_alloc_chat (struct mtproto_connection *mtp) {
|
2014-09-01 21:25:41 +02:00
|
|
|
struct binlog *bl = mtp->bl;
|
2014-10-03 14:23:15 +02:00
|
|
|
debug("fetch_alloc_chat()\n");
|
2013-10-24 21:04:44 +04:00
|
|
|
int data[2];
|
2014-08-06 19:45:46 +02:00
|
|
|
prefetch_data (mtp, data, 8);
|
2014-09-01 21:25:41 +02:00
|
|
|
peer_t *U = user_chat_get (bl, MK_CHAT (data[1]));
|
2014-10-03 14:23:15 +02:00
|
|
|
debug("id %d\n", U->id.id);
|
|
|
|
debug("type %d\n", U->id.type);
|
2013-11-23 03:26:35 +04:00
|
|
|
if (!U) {
|
2014-09-01 21:25:41 +02:00
|
|
|
bl->chats_allocated ++;
|
2014-01-10 15:32:57 +04:00
|
|
|
U = talloc0 (sizeof (*U));
|
2013-11-23 03:26:35 +04:00
|
|
|
U->id = MK_CHAT (data[1]);
|
2014-09-01 21:25:41 +02:00
|
|
|
bl->peer_tree = tree_insert_peer (bl->peer_tree, U, lrand48 ());
|
|
|
|
assert (bl->peer_num < MAX_PEER_NUM);
|
|
|
|
bl->Peers[bl->peer_num ++] = U;
|
2013-10-24 21:04:44 +04:00
|
|
|
}
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_chat (mtp, &U->chat);
|
2014-08-23 02:50:11 +02:00
|
|
|
event_peer_allocated(mtp->connection->instance, U);
|
2013-11-23 03:26:35 +04:00
|
|
|
return &U->chat;
|
2013-10-24 21:04:44 +04:00
|
|
|
}
|
|
|
|
|
2014-08-06 19:45:46 +02:00
|
|
|
struct chat *fetch_alloc_chat_full (struct mtproto_connection *mtp) {
|
2014-09-01 21:25:41 +02:00
|
|
|
struct binlog *bl = mtp->bl;
|
2013-10-24 21:04:44 +04:00
|
|
|
int data[3];
|
2014-08-06 19:45:46 +02:00
|
|
|
prefetch_data (mtp, data, 12);
|
2014-09-01 21:25:41 +02:00
|
|
|
peer_t *U = user_chat_get (bl, MK_CHAT (data[2]));
|
2013-10-24 21:04:44 +04:00
|
|
|
if (U) {
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_chat_full (mtp, &U->chat);
|
2013-10-24 21:04:44 +04:00
|
|
|
return &U->chat;
|
2013-10-14 21:26:25 +04:00
|
|
|
} else {
|
2014-09-01 21:25:41 +02:00
|
|
|
bl->chats_allocated ++;
|
2014-01-10 15:32:57 +04:00
|
|
|
U = talloc0 (sizeof (*U));
|
2013-11-01 03:18:34 +04:00
|
|
|
U->id = MK_CHAT (data[2]);
|
2014-09-01 21:25:41 +02:00
|
|
|
bl->peer_tree = tree_insert_peer (bl->peer_tree, U, lrand48 ());
|
2014-08-06 19:45:46 +02:00
|
|
|
fetch_chat_full (mtp, &U->chat);
|
2014-09-01 21:25:41 +02:00
|
|
|
assert (bl->peer_num < MAX_PEER_NUM);
|
|
|
|
bl->Peers[bl->peer_num ++] = U;
|
2013-10-14 21:26:25 +04:00
|
|
|
return &U->chat;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void free_chat (struct chat *U) {
|
2014-01-10 18:37:56 +04:00
|
|
|
if (U->title) { tfree_str (U->title); }
|
|
|
|
if (U->print_title) { tfree_str (U->print_title); }
|
2013-10-14 21:26:25 +04:00
|
|
|
}
|
|
|
|
|
2014-09-01 21:25:41 +02:00
|
|
|
int print_stat (struct binlog *bl, char *s, int len) {
|
2014-01-10 18:37:56 +04:00
|
|
|
return tsnprintf (s, len,
|
2014-09-01 21:25:41 +02:00
|
|
|
"bl->users_allocated\t%d\n"
|
|
|
|
"bl->chats_allocated\t%d\n"
|
|
|
|
"secret_bl->chats_allocated\t%d\n"
|
|
|
|
"bl->peer_num\t%d\n"
|
|
|
|
"bl->messages_allocated\t%d\n",
|
|
|
|
bl->users_allocated,
|
|
|
|
bl->chats_allocated,
|
|
|
|
bl->encr_chats_allocated,
|
|
|
|
bl->peer_num,
|
|
|
|
bl->messages_allocated
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
peer_t *user_chat_get (struct binlog *bl, peer_id_t id) {
|
2013-11-15 04:08:24 +04:00
|
|
|
static peer_t U;
|
2013-10-16 23:19:39 +04:00
|
|
|
U.id = id;
|
2014-09-01 21:25:41 +02:00
|
|
|
return tree_lookup_peer (bl->peer_tree, &U);
|
2013-10-16 23:19:39 +04:00
|
|
|
}
|
|
|
|
|
2014-09-01 21:25:41 +02:00
|
|
|
struct message *message_get (struct binlog *bl, long long id) {
|
2013-10-16 23:19:39 +04:00
|
|
|
struct message M;
|
|
|
|
M.id = id;
|
2014-09-01 21:25:41 +02:00
|
|
|
return tree_lookup_message (bl->message_tree, &M);
|
2013-10-16 23:19:39 +04:00
|
|
|
}
|
|
|
|
|
2013-11-02 14:14:30 +04:00
|
|
|
void update_message_id (struct message *M, long long id) {
|
2014-09-01 21:25:41 +02:00
|
|
|
struct binlog *bl = M->instance->bl;
|
|
|
|
bl->message_tree = tree_delete_message (bl->message_tree, M);
|
2013-10-16 23:19:39 +04:00
|
|
|
M->id = id;
|
2014-09-01 21:25:41 +02:00
|
|
|
bl->message_tree = tree_insert_message (bl->message_tree, M, lrand48 ());
|
2013-10-16 23:19:39 +04:00
|
|
|
}
|
2013-10-18 23:30:24 +04:00
|
|
|
|
2013-11-30 01:43:56 +04:00
|
|
|
void message_insert_tree (struct message *M) {
|
2014-09-01 21:25:41 +02:00
|
|
|
struct binlog *bl = M->instance->bl;
|
2013-11-30 01:43:56 +04:00
|
|
|
assert (M->id);
|
2014-09-01 21:25:41 +02:00
|
|
|
bl->message_tree = tree_insert_message (bl->message_tree, M, lrand48 ());
|
2013-11-30 01:43:56 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void message_remove_tree (struct message *M) {
|
2014-09-01 21:25:41 +02:00
|
|
|
struct binlog *bl = M->instance->bl;
|
2013-11-30 01:43:56 +04:00
|
|
|
assert (M->id);
|
2014-09-01 21:25:41 +02:00
|
|
|
bl->message_tree = tree_delete_message (bl->message_tree, M);
|
2013-11-30 01:43:56 +04:00
|
|
|
}
|
|
|
|
|
2013-10-18 23:30:24 +04:00
|
|
|
void message_insert (struct message *M) {
|
|
|
|
message_add_use (M);
|
2013-11-04 21:34:27 +04:00
|
|
|
message_add_peer (M);
|
2013-11-30 01:43:56 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void message_insert_unsent (struct message *M) {
|
2014-09-01 21:25:41 +02:00
|
|
|
struct binlog *bl = M->instance->bl;
|
|
|
|
bl->message_unsent_tree = tree_insert_message (bl->message_unsent_tree, M, lrand48 ());
|
2013-11-30 01:43:56 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void message_remove_unsent (struct message *M) {
|
2014-09-01 21:25:41 +02:00
|
|
|
struct binlog *bl = M->instance->bl;
|
|
|
|
bl->message_unsent_tree = tree_delete_message (bl->message_unsent_tree, M);
|
2013-11-30 01:43:56 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void __send_msg (struct message *M) {
|
2014-10-03 14:23:15 +02:00
|
|
|
debug ("Resending message...\n");
|
2014-07-26 11:55:45 +02:00
|
|
|
//print_message (M);
|
|
|
|
|
|
|
|
assert(M->instance);
|
|
|
|
do_send_msg (M->instance, M);
|
2013-11-30 01:43:56 +04:00
|
|
|
}
|
|
|
|
|
2014-09-01 21:25:41 +02:00
|
|
|
void send_all_unsent (struct binlog *bl) {
|
|
|
|
tree_act_message (bl->message_unsent_tree, __send_msg);
|
2013-10-18 23:30:24 +04:00
|
|
|
}
|
2014-01-31 20:03:40 +04:00
|
|
|
|
2014-09-01 21:25:41 +02:00
|
|
|
void peer_insert_name (struct binlog *bl, peer_t *P) {
|
2014-01-31 20:03:40 +04:00
|
|
|
//if (!P->print_name || !strlen (P->print_name)) { return; }
|
2014-10-03 14:23:15 +02:00
|
|
|
//debug ("+%s\n", P->print_name);
|
2014-09-01 21:25:41 +02:00
|
|
|
bl->peer_by_name_tree = tree_insert_peer_by_name (bl->peer_by_name_tree, P, lrand48 ());
|
2014-01-31 20:03:40 +04:00
|
|
|
}
|
|
|
|
|
2014-09-01 21:25:41 +02:00
|
|
|
void peer_delete_name (struct binlog *bl, peer_t *P) {
|
2014-01-31 20:03:40 +04:00
|
|
|
//if (!P->print_name || !strlen (P->print_name)) { return; }
|
2014-10-03 14:23:15 +02:00
|
|
|
//debug ("-%s\n", P->print_name);
|
2014-09-01 21:25:41 +02:00
|
|
|
bl->peer_by_name_tree = tree_delete_peer_by_name (bl->peer_by_name_tree, P);
|
2014-01-31 20:03:40 +04:00
|
|
|
}
|
|
|
|
|
2014-09-01 21:25:41 +02:00
|
|
|
peer_t *peer_lookup_name (struct binlog *bl, const char *s) {
|
2014-01-31 20:03:40 +04:00
|
|
|
static peer_t P;
|
|
|
|
P.print_name = (void *)s;
|
2014-09-01 21:25:41 +02:00
|
|
|
peer_t *R = tree_lookup_peer_by_name (bl->peer_by_name_tree, &P);
|
2014-01-31 20:03:40 +04:00
|
|
|
return R;
|
|
|
|
}
|
2014-09-01 21:25:41 +02:00
|
|
|
|
|
|
|
void free_messages (struct binlog *bl)
|
|
|
|
{
|
|
|
|
while (bl->message_tree) {
|
|
|
|
struct message *M = tree_get_min_message (bl->message_tree);
|
|
|
|
assert (M);
|
2014-10-03 14:23:15 +02:00
|
|
|
debug ("freeing message: %lld\n", M->id);
|
2014-09-01 21:25:41 +02:00
|
|
|
bl->message_tree = tree_delete_message (bl->message_tree, M);
|
|
|
|
bl->messages_allocated --;
|
|
|
|
free_message (M);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void free_peers (struct binlog *bl)
|
|
|
|
{
|
|
|
|
while (bl->peer_by_name_tree) {
|
|
|
|
bl->peer_by_name_tree = tree_delete_peer_by_name (bl->peer_by_name_tree,
|
|
|
|
tree_get_min_peer_by_name(bl->peer_by_name_tree));
|
|
|
|
}
|
|
|
|
while (bl->peer_tree) {
|
|
|
|
union peer *P = tree_get_min_peer (bl->peer_tree);
|
|
|
|
assert (P);
|
|
|
|
bl->peer_tree = tree_delete_peer (bl->peer_tree, P);
|
|
|
|
bl->peer_num --;
|
|
|
|
free (P->print_name);
|
|
|
|
tfree (P, sizeof (union peer));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|