Commit 2867d373 authored by Oleg Davydov's avatar Oleg Davydov

Merge branch 'master' of https://github.com/vysheng/tg

parents 465657d6 7a9764f2
......@@ -23,10 +23,11 @@ LIB_LIST=${LIB}/libtgl.a
TG_OBJECTS=${OBJ}/main.o ${OBJ}/loop.o ${OBJ}/interface.o ${OBJ}/lua-tg.o
TGL_OBJECTS=${OBJ}/net.o ${OBJ}/mtproto-common.o ${OBJ}/mtproto-client.o ${OBJ}/queries.o ${OBJ}/structures.o ${OBJ}/binlog.o ${OBJ}/auto/auto.o ${OBJ}/tgl.o ${OBJ}/updates.o
TLC_OBJECTS=${OBJ}/tlc.o ${OBJ}/tl-parser.o ${OBJ}/crc32.o
TLD_OBJECTS=${OBJ}/dump-tl-file.o
GENERATE_OBJECTS=${OBJ}/generate.o
COMMON_OBJECTS=${OBJ}/tools.o
OBJ_LIST=${TG_OBJECTS} ${TLC_OBJECTS} ${GENERATE_OBJECTS} ${COMMON_OBJECTS} ${TGL_OBJECTS}
OBJ_C=${TLC_OBJECTS} ${GENERATE_OBJECTS} ${COMMON_OBJECTS} ${TGL_OBJECTS}
OBJ_LIST=${TG_OBJECTS} ${TLC_OBJECTS} ${GENERATE_OBJECTS} ${COMMON_OBJECTS} ${TGL_OBJECTS} ${TLD_OBJECTS}
OBJ_C=${TLC_OBJECTS} ${GENERATE_OBJECTS} ${COMMON_OBJECTS} ${TGL_OBJECTS} ${TLD_OBJECTS}
DEPENDENCE=$(subst ${OBJ}/,${DEP}/,$(patsubst %.o,%.d,${OBJ_LIST}))
DEPENDENCE_LIST=${DEPENDENCE}
......@@ -41,6 +42,7 @@ CC=@CC@
all: ${EXE_LIST} ${DIR_LIST} ${LIB_LIST}
create_dirs_and_headers: ${DIR_LIST} ${AUTO}/auto.c ${AUTO}/auto-header.h ${AUTO}/constants.h
create_dirs: ${DIR_LIST}
dump-tl: ${EXE}/dump-tl-file
${DIR_LIST}:
@test -d $@ || mkdir -p $@
......@@ -85,6 +87,9 @@ ${AUTO}/auto-header.h: ${AUTO}/scheme.tlo ${EXE}/generate
${AUTO}/constants.h: ${AUTO}/scheme2.tl ${srcdir}/gen_constants_h.awk
awk -f ${srcdir}/gen_constants_h.awk < $< > $@
${EXE}/dump-tl-file: ${OBJ}/auto/auto.o ${TLD_OBJECTS}
${CC} ${OBJ}/auto/auto.o ${TLD_OBJECTS} ${LINK_FLAGS} -o $@
clean:
rm -rf ${DIR_LIST} config.log config.status > /dev/null || echo "all clean"
......@@ -74,5 +74,7 @@ Function_list (arguments are listed aside from cb_function and cb_extra, :
status_online ()
status_offline ()
send_location (peer, latitude, longitude)
Also, you have function
postpone (cb_function, cb_extra, timeout). It will call your cb_function in specified number of seconds (number of seconds may be double).
This diff is collapsed.
......@@ -432,6 +432,6 @@ static void print_offset (void) {
char *tglf_extf_fetch (struct paramed_type *T) {
out_buf_pos = 0;
fetch_type_any (T);
if (fetch_type_any (T) < 0) { return 0; }
return out_buf;
}
......@@ -782,6 +782,12 @@ static int fetch_comb_binlog_send_message_text (void *extra) {
}
M->to_id = tgl_set_peer_id (t, fetch_int ());
if (t == TGL_PEER_ENCR_CHAT) {
tgl_peer_t *P = tgl_peer_get (M->to_id);
if (P) {
P->encr_chat.out_seq_no ++;
}
}
M->date = fetch_int ();
int l = prefetch_strlen ();
......@@ -824,6 +830,11 @@ static int fetch_comb_binlog_send_message_action_encr (void *extra) {
M->media.type = tgl_message_media_none;
tglf_fetch_message_action_encrypted (&M->action);
tgl_peer_t *P = tgl_peer_get (M->to_id);
if (P) {
P->encr_chat.out_seq_no ++;
}
M->unread = 1;
M->out = tgl_get_peer_id (M->from_id) == tgl_state.our_id;
......@@ -952,6 +963,11 @@ static int fetch_comb_binlog_create_message_media_encr_pending (void *extra) {
int t = fetch_int ();
M->to_id = tgl_set_peer_id (t, fetch_int ());
M->date = fetch_int ();
tgl_peer_t *P = tgl_peer_get (M->to_id);
if (P) {
P->encr_chat.out_seq_no ++;
}
int l = prefetch_strlen ();
M->message = talloc (l + 1);
......@@ -1316,13 +1332,53 @@ static void create_new_binlog (void) {
static int s[1000];
packet_ptr = s;
out_int (CODE_binlog_start);
out_int (CODE_binlog_dc_option);
out_int (tgl_state.test_mode ? TG_SERVER_TEST_DC : TG_SERVER_DC);
out_string ("");
out_string (tgl_state.test_mode ? TG_SERVER_TEST : TG_SERVER);
out_int (443);
out_int (CODE_binlog_default_dc);
out_int (tgl_state.test_mode ? TG_SERVER_TEST_DC : TG_SERVER_DC);
if (tgl_state.test_mode) {
out_int (CODE_binlog_dc_option);
out_int (1);
out_string ("");
out_string (TG_SERVER_TEST_1);
out_int (443);
out_int (CODE_binlog_dc_option);
out_int (2);
out_string ("");
out_string (TG_SERVER_TEST_2);
out_int (443);
out_int (CODE_binlog_dc_option);
out_int (3);
out_string ("");
out_string (TG_SERVER_TEST_3);
out_int (443);
out_int (CODE_binlog_default_dc);
out_int (2);
} else {
out_int (CODE_binlog_dc_option);
out_int (1);
out_string ("");
out_string (TG_SERVER_1);
out_int (443);
out_int (CODE_binlog_dc_option);
out_int (2);
out_string ("");
out_string (TG_SERVER_2);
out_int (443);
out_int (CODE_binlog_dc_option);
out_int (3);
out_string ("");
out_string (TG_SERVER_3);
out_int (443);
out_int (CODE_binlog_dc_option);
out_int (4);
out_string ("");
out_string (TG_SERVER_4);
out_int (443);
out_int (CODE_binlog_dc_option);
out_int (5);
out_string ("");
out_string (TG_SERVER_5);
out_int (443);
out_int (CODE_binlog_default_dc);
out_int (2);
}
int fd = open (get_binlog_file_name (), O_WRONLY | O_EXCL | O_CREAT, 0600);
if (fd < 0) {
......@@ -1542,7 +1598,7 @@ void bl_do_user_set_friend (struct tgl_user *U, int friend) {
void bl_do_dc_option (int id, int l1, const char *name, int l2, const char *ip, int port) {
struct tgl_dc *DC = tgl_state.DC_list[id];
if (DC) { return; }
if (DC && !strncmp (ip, DC->ip, l2)) { return; }
clear_packet ();
out_int (CODE_binlog_dc_option);
......@@ -1717,7 +1773,7 @@ void bl_do_encr_chat_init (int id, int user_id, unsigned char random[], unsigned
void bl_do_set_pts (int pts) {
if (tgl_state.locks & TGL_LOCK_DIFF) { return; }
if (pts == tgl_state.pts) { return; }
if (pts <= tgl_state.pts) { return; }
int *ev = alloc_log_event (8);
ev[0] = CODE_binlog_set_pts;
ev[1] = pts;
......@@ -1726,7 +1782,7 @@ void bl_do_set_pts (int pts) {
void bl_do_set_qts (int qts) {
if (tgl_state.locks & TGL_LOCK_DIFF) { return; }
if (qts == tgl_state.qts) { return; }
if (qts <= tgl_state.qts) { return; }
int *ev = alloc_log_event (8);
ev[0] = CODE_binlog_set_qts;
ev[1] = qts;
......@@ -1735,7 +1791,7 @@ void bl_do_set_qts (int qts) {
void bl_do_set_date (int date) {
if (tgl_state.locks & TGL_LOCK_DIFF) { return; }
if (date == tgl_state.date) { return; }
if (date <= tgl_state.date) { return; }
int *ev = alloc_log_event (8);
ev[0] = CODE_binlog_set_date;
ev[1] = date;
......
telegram-cli (0.1-1) unstable; urgency=low
telegram-cli (1.0.5.1-1) unstable; urgency=low
* Initial release (Closes #737563)
* Initial release
-- Cleto Martín <cleto@debian.org> Mon, 03 Feb 2014 20:00:03 +0000
-- Steve Illichevsky <still.ru@gmail.com> Wed, 01 Oct 2014 21:06:28 +0400
Source: telegram-cli
Section: net
Priority: optional
Maintainer: Cleto Martín <cleto@debian.org>
Build-Depends: debhelper (>= 8.0.0),
autotools-dev,
autoconf-archive,
libreadline-dev,
libconfig-dev,
libssl-dev,
lua5.2,
liblua5.2-dev
Standards-Version: 3.9.4
Priority: extra
Maintainer: Steve Illichevsky <still.ru@gmail.com>
Build-Depends: debhelper (>= 8.0.0),
autotools-dev,
autoconf-archive,
libreadline-dev,
libconfig-dev,
libssl-dev,
lua5.1,
liblua5.1-dev
Standards-Version: 3.9.2
Homepage: https://github.com/vysheng/tg
Vcs-Git: git://github.com/vysheng/tg.git
Vcs-Browser: https://github.com/vysheng/tg
......@@ -33,4 +33,4 @@ Description: Command-line interface for Telegram messenger
* Group chat: create and manage groups.
* Secret chat: secured and encrypted conversations.
* Contact management: add/edit/remove contacts.
* Multimedia support: send/load photos and videos.
* Multimedia support: send/load photos and videos.
\ No newline at end of file
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Format: http://dep.debian.net/deps/dep5
Upstream-Name: telegram-cli
Source: https://github.com/vysheng/tg
Files: *
Copyright: 2013 Vitaly Valtman
License: GPL-2.0+
Copyright: 2013-2014 Vitaly Valtman <https://github.com/vysheng>
License: GPL-3.0+
Files: debian/*
Copyright: 2014 Cleto Martín <cleto@debian.org>
License: GPL-2.0+
Copyright: 2014 Steve Illichevsky <still.ru@gmail.com>
License: GPL-3.0+
License: GPL-2.0+
This package is free software; you can redistribute it and/or modify
License: GPL-3.0+
This program 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
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
.
This package is distributed in the hope that it will be useful,
......@@ -22,7 +22,10 @@ License: GPL-2.0+
GNU General Public License for more details.
.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
along with this program. If not, see <http://www.gnu.org/licenses/>.
.
On Debian systems, the complete text of the GNU General
Public License version 2 can be found in "/usr/share/common-licenses/GPL-2".
Public License version 3 can be found in "/usr/share/common-licenses/GPL-3".
# Please also look if there are files or directories which have a
# different copyright/license attached and list them here.
README.es
README-LUA
README.md
#telegram-cli.8
telegram-cli_1.0.5.1-1_i386.deb net extra
telegram usr/bin
bin/telegram-cli usr/bin
bin/tlc usr/bin
server.pub etc/telegram-cli
#!/usr/bin/make -f
# -*- makefile -*-
# Sample debian/rules that uses debhelper.
# This file was originally written by Joey Hess and Craig Small.
# As a special exception, when this file is copied by dh-make into a
# dh-make output file, you may use that output file without restriction.
# This special exception was added by Craig Small in version 0.37 of dh-make.
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
VERSION=$(shell dpkg-parsechangelog | sed -n 's/^Version: //p' | cut -f1 -d'-')
PACKAGE_NAME=$(shell dpkg-parsechangelog | sed -n 's/^Source: //p')
%:
dh $@ --with autotools-dev
dh $@ --with autotools-dev
build-orig:
mkdir -p $(PACKAGE_NAME)-$(VERSION)
tar --exclude=ax_lua.m4 --exclude=debian --exclude=\.pc \
--exclude=$(PACKAGE_NAME)-$(VERSION) -cf - . \
| ( cd $(PACKAGE_NAME)-$(VERSION) && tar xf - )
tar -cf ../$(PACKAGE_NAME)_$(VERSION).orig.tar $(PACKAGE_NAME)-$(VERSION)
$(RM) -r $(PACKAGE_NAME)-$(VERSION)
xz ../$(PACKAGE_NAME)_$(VERSION).orig.tar
mkdir -p $(PACKAGE_NAME)-$(VERSION)
tar --exclude=ax_lua.m4 --exclude=debian --exclude=\.pc \
--exclude=$(PACKAGE_NAME)-$(VERSION) -cf - . \
| ( cd $(PACKAGE_NAME)-$(VERSION) && tar xf - )
tar -cf ../$(PACKAGE_NAME)_$(VERSION).orig.tar $(PACKAGE_NAME)-$(VERSION)
$(RM) -r $(PACKAGE_NAME)-$(VERSION)
xz ../$(PACKAGE_NAME)_$(VERSION).orig.tar
\ No newline at end of file
.TH man 8 "02 October 2014" "1.0.5.1" "telegram-cli man page"
.SH NAME
telegram-cli \- Command-line interface for Telegram messenger
.SH SYNOPSIS
telegram-cli -k [keyfile]
.SH DESCRIPTION
Telegram messenger is a cloud-based instant messaging designed for
smart phones and similar to Whatsapp but more flexible, and
powerful. You can send messages, photos, videos and documents to
people who are in your phone contacts (and have Telegram). Telegram
also supports secret chats whose provide a private (encrypted) way of
communication.
.
This package contains a command-line based client for Telegram with
the following features:
* Colored terminal messages.
* Message management: history, stats, etc.
* Group chat: create and manage groups.
* Secret chat: secured and encrypted conversations.
* Contact management: add/edit/remove contacts.
* Multimedia support: send/load photos and videos.
.SH OPTIONS
Telegram-cli Usage
-u specify username (would not be asked during authorization)
-k specify location of public key (possible multiple entries)
-v increase verbosity (0-ERROR 1-WARNIN 2-NOTICE 3+-DEBUG-levels)
-N message num mode
-c config file name
-p use specified profile
-l log level
-f during authorization fetch all messages since registration
-E diable auto accept of encrypted chats
-s lua script file
-W send dialog_list query and wait for answer before reading input
-C disable color output
-R disable readline
-d daemon mode
-L <log-name> log file name
-U <user-name> change uid after start
-G <group-name> change gid after start
-D disable output
-P <port> port to listen for input commands
-S <socket-name> unix socket to create
.SH SEE ALSO
.SH BUGS
No known bugs.
.SH AUTHOR
Vitaliy Vatman (-@-)
\ No newline at end of file
debian/telegram-cli.8
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <stdarg.h>
#include <fcntl.h>
#include <assert.h>
#include <string.h>
#include "auto.h"
int *tgl_in_ptr, *tgl_in_end;
int tgl_packet_buffer[0];
int *tgl_packet_ptr;
char *tgl_strdup (char *s) {
return strdup (s);
}
void tgl_out_cstring (const char *str, long len) {}
char *tglf_extf_fetch (struct paramed_type *T);
#define LEN (1 << 28)
static int x[LEN / 4];
int main (int argc, char **argv) {
int i;
int dump_binlog = 0;
while ((i = getopt (argc, argv, "b")) != -1) {
switch (i) {
case 'b':
dump_binlog = 1;
break;
default:
printf ("unknown option '%c'\n", (char)i);
exit (1);
}
}
if (!dump_binlog) {
exit (1);
}
if (optind + 1 != argc) {
exit (1);
}
int fd = open (argv[optind], O_RDONLY);
if (fd < 0) {
perror ("open");
exit (1);
}
int r = read (fd, x, LEN);
if (r <= 0) {
perror ("read");
exit (1);
}
if (r == LEN) {
printf ("Too long file\n");
exit (1);
}
assert (!(r & 3));
tgl_in_ptr = x;
tgl_in_end = x + (r / 4);
while (tgl_in_ptr < tgl_in_end) {
if (dump_binlog) {
char *R = tglf_extf_fetch (TYPE_TO_PARAM(binlog_update));
if (!R) {
printf ("Can not fetch\n");
exit (1);
}
printf ("%s\n", R);
}
}
return 0;
}
encrypted_scheme16.tl
\ No newline at end of file
encrypted_scheme17.tl
\ No newline at end of file
---types---
decryptedMessageLayer#99a438cf layer:int message:DecryptedMessage = DecryptedMessageLayer;
decryptedMessage_l16#1f814f1f random_id:long random_bytes:bytes message:string media:DecryptedMessageMedia = DecryptedMessage;
decryptedMessageService_l16#aa48327d random_id:long random_bytes:bytes action:DecryptedMessageAction = DecryptedMessage;
decryptedMessage#20a6d4e2 in_seq_no:int out_seq_no:int ttl:int random_id:long random_bytes:bytes message:string media:DecryptedMessageMedia = DecryptedMessage;
decryptedMessageService#9bb84a4e in_seq_no:int out_seq_no:int random_id:long random_bytes:bytes action:DecryptedMessageAction = DecryptedMessage;
decryptedMessageMediaEmpty#89f5c4a = DecryptedMessageMedia;
decryptedMessageMediaPhoto#32798a8c thumb:bytes thumb_w:int thumb_h:int w:int h:int size:int key:bytes iv:bytes = DecryptedMessageMedia;
//decryptedMessageMediaVideo#4cee6ef3 thumb:bytes thumb_w:int thumb_h:int duration:int w:int h:int size:int key:bytes iv:bytes = DecryptedMessageMedia;
decryptedMessageMediaGeoPoint#35480a59 lat:double long:double = DecryptedMessageMedia;
decryptedMessageMediaContact#588a0a97 phone_number:string first_name:string last_name:string user_id:int = DecryptedMessageMedia;
decryptedMessageActionSetMessageTTL#a1733aec ttl_seconds:int = DecryptedMessageAction;
decryptedMessageMediaDocument#b095434b thumb:bytes thumb_w:int thumb_h:int file_name:string mime_type:string size:int key:bytes iv:bytes = DecryptedMessageMedia;
//decryptedMessageMediaAudio#6080758f duration:int size:int key:bytes iv:bytes = DecryptedMessageMedia;
decryptedMessageMediaVideo#524a415d thumb:bytes thumb_w:int thumb_h:int duration:int mime_type:string w:int h:int size:int key:bytes iv:bytes = DecryptedMessageMedia;
decryptedMessageMediaAudio#57e0a9cb duration:int mime_type:string size:int key:bytes iv:bytes = DecryptedMessageMedia;
decryptedMessageActionReadMessages#c4f40be random_ids:Vector<long> = DecryptedMessageAction;
decryptedMessageActionDeleteMessages#65614304 random_ids:Vector<long> = DecryptedMessageAction;
decryptedMessageActionScreenshotMessages#8ac1f475 random_ids:Vector<long> = DecryptedMessageAction;
decryptedMessageActionFlushHistory#6719e45c = DecryptedMessageAction;
decryptedMessageActionNotifyLayer#f3048883 layer:int = DecryptedMessageAction;
decryptedMessageActionTyping#ccb27641 action:SendMessageAction = DecryptedMessageAction;
---functions---
This diff is collapsed.
......@@ -91,6 +91,8 @@ static int delete_stdin_event;
extern volatile int sigterm_cnt;
extern char *start_command;
static void stdin_read_callback_all (int arg, short what, struct event *self) {
if (!readline_disabled) {
if (((long)arg) & 1) {
......@@ -500,9 +502,19 @@ void read_dc (int auth_file_fd, int id, unsigned ver) {
}
void empty_auth_file (void) {
char *ip = tgl_state.test_mode ? TG_SERVER_TEST : TG_SERVER;
bl_do_dc_option (tgl_state.test_mode ? TG_SERVER_TEST_DC : TG_SERVER_DC, 0, "", strlen (ip), ip, 443);
bl_do_set_working_dc (tgl_state.test_mode ? TG_SERVER_TEST_DC : TG_SERVER_DC);
if (tgl_state.test_mode) {
bl_do_dc_option (1, 0, "", strlen (TG_SERVER_TEST_1), TG_SERVER_TEST_1, 443);
bl_do_dc_option (2, 0, "", strlen (TG_SERVER_TEST_2), TG_SERVER_TEST_2, 443);
bl_do_dc_option (3, 0, "", strlen (TG_SERVER_TEST_3), TG_SERVER_TEST_3, 443);
bl_do_set_working_dc (2);
} else {
bl_do_dc_option (1, 0, "", strlen (TG_SERVER_1), TG_SERVER_1, 443);
bl_do_dc_option (2, 0, "", strlen (TG_SERVER_2), TG_SERVER_2, 443);
bl_do_dc_option (3, 0, "", strlen (TG_SERVER_3), TG_SERVER_3, 443);
bl_do_dc_option (4, 0, "", strlen (TG_SERVER_4), TG_SERVER_4, 443);
bl_do_dc_option (5, 0, "", strlen (TG_SERVER_5), TG_SERVER_5, 443);
bl_do_set_working_dc (2);
}
}
int need_dc_list_update;
......@@ -842,6 +854,20 @@ int loop (void) {
lua_diff_end ();
#endif
if (start_command) {
safe_quit = 1;
while (*start_command) {
char *start = start_command;
while (*start_command && *start_command != '\n') {
start_command ++;
}
if (*start_command) {
*start_command = 0;
start_command ++;
}
interpreter_ex (start, 0);
}
}
/*tgl_do_get_dialog_list (get_dialogs_callback, 0);
if (wait_dialog_list) {
......
......@@ -495,6 +495,7 @@ enum lua_query_type {
lq_send_contact,
lq_status_online,
lq_status_offline,
lq_send_location,
lq_extf
};
......@@ -1086,6 +1087,14 @@ void lua_do_all (void) {
free (s);
p += 2;
break;
case lq_send_location:
if (sizeof (void *) == 4) {
tgl_do_send_location (((tgl_peer_t *)lua_ptr[p + 1])->id , *(float *)(lua_ptr + p + 2), *(float *)(lua_ptr + p + 3), lua_msg_cb, lua_ptr[p]);
} else {
tgl_do_send_location (((tgl_peer_t *)lua_ptr[p + 1])->id , *(double *)(lua_ptr + p + 2), *(double *)(lua_ptr + p + 3), lua_msg_cb, lua_ptr[p]);
}
p += 4;
break;
/*
lq_delete_msg,
lq_restore_msg,
......@@ -1120,7 +1129,8 @@ enum lua_function_param {
lfp_number,
lfp_positive_number,
lfp_nonnegative_number,
lfp_msg
lfp_msg,
lfp_double
};
struct lua_function {
......@@ -1168,6 +1178,7 @@ struct lua_function functions[] = {
{"send_contact", lq_send_contact, { lfp_peer, lfp_string, lfp_string, lfp_string, lfp_none }},
{"status_online", lq_status_online, { lfp_none }},
{"status_offline", lq_status_offline, { lfp_none }},
{"send_location", lq_send_location, { lfp_peer, lfp_double, lfp_double, lfp_none }},
{"ext_function", lq_extf, { lfp_string, lfp_none }},
{ 0, 0, { lfp_none}}
};
......@@ -1203,6 +1214,7 @@ static int parse_lua_function (lua_State *L, struct lua_function *F) {
const char *s;
tgl_peer_t *P;
long long num;
double dval;
struct tgl_message *M;
switch (F->params[p]) {
case lfp_none:
......@@ -1256,6 +1268,17 @@ static int parse_lua_function (lua_State *L, struct lua_function *F) {
lua_ptr[pos + p] = (void *)(long)num;
break;
case lfp_double:
dval = lua_tonumber (L, -cc);
if (sizeof (void *) == 4) {
*(float *)(lua_ptr + pos + p) = dval;
} else {
assert (sizeof (void *) >= 8);
*(double *)(lua_ptr + pos + p) = dval;
}
break;
case lfp_positive_number:
num = lua_tonumber (L, -cc);
if (num <= 0) {
......
......@@ -59,6 +59,7 @@
#include <grp.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include "telegram.h"
#include "loop.h"
......@@ -110,6 +111,7 @@ int readline_disabled;
int disable_output;
int reset_authorization;
int port;
char *start_command;
void set_default_username (const char *s) {
if (default_username) {
......@@ -283,7 +285,7 @@ void parse_config_val (config_t *conf, char **s, char *param_name, const char *d
strcpy (buf + l, param_name);
config_lookup_string (conf, buf, &r);
if (r) {
if (path) {
if (path && *r != '/') {
tasprintf (s, "%s/%s", path, r);
} else {
*s = tstrdup (r);
......@@ -399,6 +401,11 @@ void parse_config (void) {
tasprintf (&secret_chat_file_name, "%s/%s/%s", get_home_directory (), CONFIG_DIRECTORY, SECRET_CHAT_FILE);
}
tgl_set_download_directory (downloads_directory);
if (!mkdir (downloads_directory, CONFIG_DIRECTORY_MODE)) {
if (!disable_output) {
printf ("[%s] created\n", downloads_directory);
}
}
}
#endif
......@@ -421,7 +428,7 @@ void usage (void) {
#endif
printf (" -l log level\n");
printf (" -f during authorization fetch all messages since registration\n");
printf (" -E diable auto accept of encrypted chats\n");
printf (" -E disable auto accept of encrypted chats\n");
#ifdef USE_LUA
printf (" -s lua script file\n");
#endif
......@@ -435,6 +442,7 @@ void usage (void) {
printf (" -D disable output\n");
printf (" -P <port> port to listen for input commands\n");
printf (" -S <socket-name> unix socket to create\n");
printf (" -e <commands> make commands end exit\n");
exit (1);
}
......@@ -537,7 +545,7 @@ char *unix_socket;
void args_parse (int argc, char **argv) {
int opt = 0;
while ((opt = getopt (argc, argv, "u:hk:vNl:fEwWCRdL:DU:G:qP:S:"
while ((opt = getopt (argc, argv, "u:hk:vNl:fEwWCRdL:DU:G:qP:S:e:"
#ifdef HAVE_LIBCONFIG
"c:p:"
#else
......@@ -626,6 +634,9 @@ void args_parse (int argc, char **argv) {
case 'S':
unix_socket = optarg;
break;
case 'e':
start_command = optarg;
break;
case 'h':
default:
usage ();
......
......@@ -80,7 +80,7 @@
#define MAX_NET_RES (1L << 16)
//extern int log_level;
#ifndef HAVE___BUILTIN_BSWAP32
#if !defined(HAVE___BUILTIN_BSWAP32) && !defined(__FreeBSD__) && !defined(__OpenBSD__)
static inline unsigned __builtin_bswap32(unsigned x) {
return ((x << 24) & 0xff000000 ) |
((x << 8) & 0x00ff0000 ) |
......@@ -284,6 +284,13 @@ static int process_respq_answer (struct connection *c, char *packet, int len, in
unsigned long long what;
unsigned p1, p2;
int i;
long long packet_auth_key_id = *(long long *)packet;
if (packet_auth_key_id) {
assert (temp_key);
vlogprintf (E_WARNING, "received packet during creation of temp auth key. Probably answer on old query. Drop\n");
return 0;
}
vlogprintf (E_DEBUG, "process_respq_answer(), len=%d, op=0x%08x\n", len, *(int *)(packet + 20));
assert (len >= 76);
assert (!*(long long *) packet);
......@@ -552,6 +559,12 @@ static int process_dh_answer (struct connection *c, char *packet, int len, int t
//if (len < 116) {
// vlogprintf (E_ERROR, "%u * %u = %llu", p1, p2, what);
//}
long long packet_auth_key_id = *(long long *)packet;
if (packet_auth_key_id) {
assert (temp_key);
vlogprintf (E_WARNING, "received packet during creation of temp auth key. Probably answer on old query. Drop\n");
return 0;
}
assert (len >= 116);
assert (!*(long long *) packet);
assert (*(int *) (packet + 16) == len - 20);
......@@ -660,6 +673,13 @@ static void mpc_on_get_config (void *extra, int success);
static int process_auth_complete (struct connection *c UU, char *packet, int len, int temp_key) {
struct tgl_dc *D = tgl_state.net_methods->get_dc (c);
vlogprintf (E_DEBUG - 1, "process_dh_answer(), len=%d\n", len);
long long packet_auth_key_id = *(long long *)packet;
if (packet_auth_key_id) {
assert (temp_key);
vlogprintf (E_WARNING, "received packet during creation of temp auth key. Probably answer on old query. Drop\n");
return 0;
}
assert (len == 72);
assert (!*(long long *) packet);
assert (*(int *) (packet + 16) == len - 20);
......@@ -1058,8 +1078,9 @@ static int process_rpc_message (struct connection *c UU, struct encrypted_messag
assert (len >= MINSZ && (len & 15) == (UNENCSZ & 15));
struct tgl_dc *DC = tgl_state.net_methods->get_dc (c);
if (enc->auth_key_id != DC->temp_auth_key_id && enc->auth_key_id != DC->auth_key_id) {
vlogprintf (E_ERROR, "received msg from dc %d with auth_key_id %lld (perm_auth_key_id %lld temp_auth_key_id %lld)\n",
vlogprintf (E_WARNING, "received msg from dc %d with auth_key_id %lld (perm_auth_key_id %lld temp_auth_key_id %lld). Dropping\n",
DC->id, enc->auth_key_id, DC->auth_key_id, DC->temp_auth_key_id);
return 0;
}
if (enc->auth_key_id == DC->temp_auth_key_id) {
assert (enc->auth_key_id == DC->temp_auth_key_id);
......@@ -1280,7 +1301,7 @@ void tglmp_on_start (void) {
}
if (!ok) {
vlogprintf (E_ERROR, "No pubic keys found\n");
vlogprintf (E_ERROR, "No public keys found\n");
exit (1);
}
......@@ -1341,19 +1362,26 @@ static void regen_temp_key_gw (evutil_socket_t fd, short what, void *arg) {
}
struct tgl_dc *tglmp_alloc_dc (int id, char *ip, int port UU) {
assert (!tgl_state.DC_list[id]);
struct tgl_dc *DC = talloc0 (sizeof (*DC));
DC->id = id;
DC->ip = ip;
DC->port = port;
tgl_state.DC_list[id] = DC;
if (id > tgl_state.max_dc_num) {
tgl_state.max_dc_num = id;
//assert (!tgl_state.DC_list[id]);
if (!tgl_state.DC_list[id]) {
struct tgl_dc *DC = talloc0 (sizeof (*DC));
DC->id = id;
DC->ip = ip;
DC->port = port;
tgl_state.DC_list[id] = DC;
if (id > tgl_state.max_dc_num) {
tgl_state.max_dc_num = id;
}
DC->ev = evtimer_new (tgl_state.ev_base, regen_temp_key_gw, DC);
static struct timeval p;
event_add (DC->ev, &p);
return DC;
} else {
struct tgl_dc *DC = tgl_state.DC_list[id];
tfree_str (DC->ip);
DC->ip = tstrdup (ip);
return DC;
}
DC->ev = evtimer_new (tgl_state.ev_base, regen_temp_key_gw, DC);
static struct timeval p;
event_add (DC->ev, &p);
return DC;
}
static struct mtproto_methods mtproto_methods = {
......
......@@ -201,7 +201,6 @@ static inline int prefetch_strlen (void) {
static inline char *fetch_str (int len) {
assert (len >= 0);
vlogprintf (E_DEBUG + 3, "fetch_string: len = %d\n", len);
if (len < 254) {
char *str = (char *) in_ptr + 1;
in_ptr += 1 + (len >> 2);
......@@ -294,12 +293,10 @@ int tgl_fetch_bignum (BIGNUM *x);
static inline int fetch_int (void) {
assert (in_ptr + 1 <= in_end);
vlogprintf (E_DEBUG + 3, "fetch_int: 0x%08x (%d)\n", *in_ptr, *in_ptr);
return *(in_ptr ++);
}
static inline int fetch_bool (void) {
vlogprintf (E_DEBUG + 3, "fetch_bool: 0x%08x (%d)\n", *in_ptr, *in_ptr);
assert (in_ptr + 1 <= in_end);
assert (*(in_ptr) == (int)CODE_bool_true || *(in_ptr) == (int)CODE_bool_false);
return *(in_ptr ++) == (int)CODE_bool_true;
......
......@@ -26,11 +26,11 @@
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <sys/types.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <stdio.h>
......@@ -345,6 +345,10 @@ static void restart_connection (struct connection *c) {
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons (c->port);
if (strcmp (c->ip, c->dc->ip)) {
tfree_str (c->ip);
c->ip = tstrdup (c->dc->ip);
}
addr.sin_addr.s_addr = inet_addr (c->ip);
......
......@@ -94,7 +94,7 @@ struct query *tglq_query_get (long long id) {
static int alarm_query (struct query *q) {
assert (q);
vlogprintf (E_DEBUG, "Alarm query %lld\n", q->msg_id);
vlogprintf (E_DEBUG - 1, "Alarm query %lld\n", q->msg_id);
//q->ev.timeout = get_double_time () + QUERY_TIMEOUT;
//insert_event_timer (&q->ev);
......@@ -118,7 +118,9 @@ static int alarm_query (struct query *q) {
tglmp_encrypt_send_message (q->session->c, packet_buffer, packet_ptr - packet_buffer, q->flags & QUERY_FORCE_SEND);
} else {
q->flags &= ~QUERY_ACK_RECEIVED;
queries_tree = tree_delete_query (queries_tree, q);
if (tree_lookup_query (queries_tree, q)) {
queries_tree = tree_delete_query (queries_tree, q);
}
q->msg_id = tglmp_encrypt_send_message (q->session->c, q->data, q->data_len, (q->flags & QUERY_FORCE_SEND) | 1);
queries_tree = tree_insert_query (queries_tree, q, lrand48 ());
q->session_id = q->session->session_id;
......@@ -219,14 +221,35 @@ void tglq_query_error (long long id) {
event_del (q->ev);
}
queries_tree = tree_delete_query (queries_tree, q);
if (q->methods && q->methods->on_error) {
q->methods->on_error (q, error_code, error_len, error);
int res = 0;
if (q->methods && q->methods->on_error && error_code != 500) {
res = q->methods->on_error (q, error_code, error_len, error);
} else {
vlogprintf ( E_WARNING, "error for query #%lld: #%d :%.*s\n", id, error_code, error_len, error);
if (error_code == 420 || error_code == 500) {
int wait;
if (error_code == 420) {
if (strncmp (error, "FLOOD_WAIT_", 11)) {
vlogprintf (E_ERROR, "error = '%s'\n", error);
wait = 10;
} else {
wait = atoll (error + 11);
}
} else {
wait = 10;
}
q->flags &= ~QUERY_ACK_RECEIVED;
static struct timeval ptimeout;
ptimeout.tv_sec = wait;
event_add (q->ev, &ptimeout);
q->session_id = 0;
res = 1;
}
}
if (res <= 0) {
tfree (q->data, q->data_len * 4);
event_free (q->ev);
tfree (q, sizeof (*q));
}
tfree (q->data, q->data_len * 4);
event_free (q->ev);
tfree (q, sizeof (*q));
}
tgl_state.active_queries --;
}
......@@ -314,7 +337,7 @@ static void out_random (int n) {
int allow_send_linux_version;
void tgl_do_insert_header (void) {
out_int (CODE_invoke_with_layer16);
out_int (CODE_invoke_with_layer17);
out_int (CODE_init_connection);
out_int (TG_APP_ID);
if (allow_send_linux_version) {
......@@ -914,7 +937,17 @@ static int msg_send_on_answer (struct query *q UU) {
}
static int msg_send_on_error (struct query *q, int error_code, int error_len, char *error) {
vlogprintf (E_WARNING, "error for query #%lld: #%d :%.*s\n", q->msg_id, error_code, error_len, error);
//vlogprintf (E_WARNING, "error for query #%lld: #%d :%.*s\n", q->msg_id, error_code, error_len, error);
if (error_code == 420) {
assert (!strncmp (error, "FLOOD_WAIT_", 11));
int wait = atoll (error + 11);
q->flags &= ~QUERY_ACK_RECEIVED;
static struct timeval ptimeout;
ptimeout.tv_sec = wait;
event_add (q->ev, &ptimeout);
q->session_id = 0;
return 1;
}
long long x = *(long long *)q->extra;
tfree (q->extra, 8);
struct tgl_message *M = tgl_message_get (x);
......@@ -957,7 +990,13 @@ void tgl_do_send_encr_msg_action (struct tgl_message *M, void (*callback)(void *
out_long (P->encr_chat.access_hash);
out_long (M->id);
encr_start ();
out_int (CODE_decrypted_message_service);
if (P->encr_chat.layer <= 16) {
out_int (CODE_decrypted_message_service_l16);
} else {
out_int (CODE_decrypted_message_service);
out_int (2 * P->encr_chat.in_seq_no + (P->encr_chat.admin_id != tgl_state.our_id));
out_int (2 * P->encr_chat.out_seq_no + (P->encr_chat.admin_id == tgl_state.our_id));
}
out_long (M->id);
static int buf[4];
tglt_secure_random (buf, 16);
......@@ -1001,7 +1040,14 @@ void tgl_do_send_encr_msg (struct tgl_message *M, void (*callback)(void *callbac
out_long (P->encr_chat.access_hash);
out_long (M->id);
encr_start ();
out_int (CODE_decrypted_message);
if (P->encr_chat.layer <= 16) {
out_int (CODE_decrypted_message_l16);
} else {
out_int (CODE_decrypted_message);
out_int (2 * P->encr_chat.in_seq_no + (P->encr_chat.admin_id != tgl_state.our_id));
out_int (2 * P->encr_chat.out_seq_no + (P->encr_chat.admin_id == tgl_state.our_id));
out_int (0);
}
out_long (M->id);
static int buf[4];
tglt_secure_random (buf, 16);
......@@ -1141,6 +1187,7 @@ void tgl_do_messages_mark_read (tgl_peer_id_t id, int max_id, int offset, void (
out_peer_id (id);
out_int (max_id);
out_int (offset);
out_int (CODE_bool_true);
int *t = talloc (12);
t[0] = tgl_get_peer_type (id);
t[1] = tgl_get_peer_id (id);
......@@ -1738,7 +1785,14 @@ static void send_part (struct send_file *f, void *callback, void *callback_extra
tglt_secure_random (&r, 8);
out_long (r);
encr_start ();
out_int (CODE_decrypted_message);
if (P->encr_chat.layer <= 16) {
out_int (CODE_decrypted_message_l16);
} else {
out_int (CODE_decrypted_message);
out_int (2 * P->encr_chat.in_seq_no + (P->encr_chat.admin_id != tgl_state.our_id));
out_int (2 * P->encr_chat.out_seq_no + (P->encr_chat.admin_id == tgl_state.our_id) + 2);
out_int (0);
}
out_long (r);
out_random (15 + 4 * (lrand48 () % 3));
out_string ("");
......@@ -1783,9 +1837,7 @@ static void send_part (struct send_file *f, void *callback, void *callback_extra
out_cstring ((void *)f->key, 32);
out_cstring ((void *)f->init_iv, 32);
long long msg_id;
tglt_secure_random (&msg_id, 8);
bl_do_create_message_media_encr_pending (msg_id, tgl_state.our_id, tgl_get_peer_type (f->to_id), tgl_get_peer_id (f->to_id), time (0), 0, 0, save_ptr, packet_ptr - save_ptr);
bl_do_create_message_media_encr_pending (r, tgl_state.our_id, tgl_get_peer_type (f->to_id), tgl_get_peer_id (f->to_id), time (0), 0, 0, save_ptr, packet_ptr - save_ptr);
encr_finish (&P->encr_chat);
if (f->size < (16 << 20)) {
......@@ -1807,7 +1859,7 @@ static void send_part (struct send_file *f, void *callback, void *callback_extra
out_int ((*(int *)md5) ^ (*(int *)(md5 + 4)));
tfree_secure (f->iv, 32);
struct tgl_message *M = tgl_message_get (msg_id);
struct tgl_message *M = tgl_message_get (r);
assert (M);
//M->media.encr_photo.key = f->key;
......@@ -1943,6 +1995,7 @@ void tgl_do_set_profile_photo (char *file_name, void (*callback)(void *callback_
}
/* }}} */
/* {{{ Forward */
static int fwd_msg_on_answer (struct query *q UU) {
assert (fetch_int () == (int)CODE_messages_stated_message);
......@@ -2093,6 +2146,65 @@ void tgl_do_forward_media (tgl_peer_id_t id, int n, void (*callback)(void *callb
}
/* }}} */
/* {{{ Send location */
void tgl_do_send_location(tgl_peer_id_t id, double latitude, double longitude, void (*callback)(void *callback_extra, int success, struct tgl_message *M), void *callback_extra) {
if (tgl_get_peer_type (id) == TGL_PEER_ENCR_CHAT) {
clear_packet ();
out_int (CODE_messages_send_encrypted);
out_int (CODE_input_encrypted_chat);
out_int (tgl_get_peer_id (id));
tgl_peer_t *P = tgl_peer_get (id);
assert (P);
out_long (P->encr_chat.access_hash);
long long r;
tglt_secure_random (&r, 8);
out_long (r);
encr_start ();
if (P->encr_chat.layer <= 16) {
out_int (CODE_decrypted_message_l16);
} else {
out_int (CODE_decrypted_message);
out_int (2 * P->encr_chat.in_seq_no + (P->encr_chat.admin_id != tgl_state.our_id));
out_int (2 * P->encr_chat.out_seq_no + (P->encr_chat.admin_id == tgl_state.our_id) + 2);
out_int (0);
}
out_long (r);
out_random (15 + 4 * (lrand48 () % 3));
out_string ("");
int *save_ptr = packet_ptr;
out_int (CODE_decrypted_message_media_geo_point);
out_double (latitude);
out_double (longitude);
bl_do_create_message_media_encr_pending (r, tgl_state.our_id, tgl_get_peer_type (id), tgl_get_peer_id (id), time (0), 0, 0, save_ptr, packet_ptr - save_ptr);
encr_finish (&P->encr_chat);
struct tgl_message *M = tgl_message_get (r);
assert (M);
tglq_send_query (tgl_state.DC_working, packet_ptr - packet_buffer, packet_buffer, &msg_send_encr_methods, M, callback, callback_extra);
} else {
long long t;
tglt_secure_random (&t, 8);
vlogprintf (E_DEBUG, "t = %lld\n", t);
clear_packet ();
out_int (CODE_messages_send_media);
out_peer_id (id);
out_int (CODE_input_media_geo_point);
out_int (CODE_input_geo_point);
out_double (latitude);
out_double (longitude);
out_long (t);
tglq_send_query (tgl_state.DC_working, packet_ptr - packet_buffer, packet_buffer, &fwd_msg_methods, 0, callback, callback_extra);
}
}
/* }}} */
/* {{{ Rename chat */
static int rename_chat_on_answer (struct query *q UU) {
assert (fetch_int () == (int)CODE_messages_stated_message);
......@@ -2361,6 +2473,10 @@ static int download_on_answer (struct query *q) {
struct download *D = q->extra;
if (D->fd == -1) {
D->fd = open (D->name, O_CREAT | O_WRONLY, 0640);
if (D->fd < 0) {
vlogprintf (E_ERROR, "Can not open for writing: %m\n");
assert (D->fd >= 0);
}
}
fetch_int (); // mtime
int len = prefetch_strlen ();
......@@ -2906,6 +3022,9 @@ static int send_encr_accept_on_answer (struct query *q UU) {
print_end ();
}*/
if (E->state == sc_ok) {
tgl_do_send_encr_chat_layer (E);
}
if (q->callback) {
((void (*)(void *, int, struct tgl_secret_chat *))q->callback) (q->callback_extra, E->state == sc_ok, E);
}
......
scheme16.tl
\ No newline at end of file
scheme17.tl
\ No newline at end of file
This diff is collapsed.
-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEAwVACPi9w23mF3tBkdZz+zwrzKOaaQdr01vAbU4E1pvkfj4sqDsm6
lyDONS789sVoD/xCS9Y0hkkC3gtL1tSfTlgCMOOul9lcixlEKzwKENj1Yz/s7daS
an9tqw3bfUV/nqgbhGX81v/+7RFAEd+RwFnK7a+XYl9sluzHRyVVaTTveB2GazTw
Efzk2DWgkBluml8OREmvfraX3bkHZJTKX4EQSjBbbdJ2ZXIsRrYOXfaA+xayEGB+
8hdlLmAjbCVfaigxX0CDqWeR1yFL9kwd9P0NsZRPsmoqVwMbMu7mStFai6aIhc3n
Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB
-----END RSA PUBLIC KEY-----
......@@ -108,6 +108,34 @@ char *tgls_default_create_print_name (tgl_peer_id_t id, const char *a1, const ch
return tstrdup (s);
}
enum tgl_typing_status tglf_fetch_typing (void) {
switch (fetch_int ()) {
case CODE_send_message_typing_action:
return tgl_typing_typing;
case CODE_send_message_cancel_action:
return tgl_typing_cancel;
case CODE_send_message_record_video_action:
return tgl_typing_record_video;
case CODE_send_message_upload_video_action:
return tgl_typing_upload_video;
case CODE_send_message_record_audio_action:
return tgl_typing_record_audio;
case CODE_send_message_upload_audio_action:
return tgl_typing_upload_audio;
case CODE_send_message_upload_photo_action:
return tgl_typing_upload_photo;
case CODE_send_message_upload_document_action:
return tgl_typing_upload_document;
case CODE_send_message_geo_location_action:
return tgl_typing_geo;
case CODE_send_message_choose_contact_action:
return tgl_typing_choose_contact;
default:
assert (0);
return tgl_typing_none;
}
}
/* {{{ Fetch */
int tglf_fetch_file_location (struct tgl_file_location *loc) {
......@@ -512,8 +540,8 @@ void tglf_fetch_photo_size (struct tgl_photo_size *S) {
void tglf_fetch_geo (struct tgl_geo *G) {
unsigned x = fetch_int ();
if (x == CODE_geo_point) {
G->longitude = fetch_double ();
G->latitude = fetch_double ();
G->longitude = fetch_double ();
} else {
assert (x == CODE_geo_point_empty);
G->longitude = 0;
......@@ -923,8 +951,8 @@ void tglf_fetch_message_media_encrypted (struct tgl_message_media *M) {
*/
case CODE_decrypted_message_media_geo_point:
M->type = tgl_message_media_geo;
M->geo.longitude = fetch_double ();
M->geo.latitude = fetch_double ();
M->geo.longitude = fetch_double ();
break;
case CODE_decrypted_message_media_contact:
M->type = tgl_message_media_contact;
......@@ -990,6 +1018,10 @@ void tglf_fetch_message_action_encrypted (struct tgl_message_action *M) {
case CODE_decrypted_message_action_flush_history:
M->type = tgl_message_action_flush_history;
break;
case CODE_decrypted_message_action_typing:
M->type = tgl_message_action_typing;
M->typing = tglf_fetch_typing ();
break;
default:
vlogprintf (E_ERROR, "x = 0x%08x\n", x);
assert (0);
......@@ -1009,6 +1041,10 @@ tgl_peer_id_t tglf_fetch_peer_id (void) {
void tglf_fetch_message (struct tgl_message *M) {
unsigned x = fetch_int ();
assert (x == CODE_message_empty || x == CODE_message || x == CODE_message_forwarded || x == CODE_message_service);
int flags = 0;
if (x != CODE_message_empty) {
flags = fetch_int ();
}
int id = fetch_int ();
assert (M->id == id);
if (x == CODE_message_empty) {
......@@ -1024,11 +1060,12 @@ void tglf_fetch_message (struct tgl_message *M) {
int from_id = fetch_int ();
tgl_peer_id_t to_id = tglf_fetch_peer_id ();
fetch_bool (); // out.
//fetch_bool (); // out.
int unread = fetch_bool ();
//int unread = fetch_bool ();
int date = fetch_int ();
int unread = (flags & 1) != 0;
int new = !(M->flags & FLAG_CREATED);
if (x == CODE_message_service) {
......@@ -1190,12 +1227,30 @@ void tglf_fetch_encrypted_message (struct tgl_message *M) {
assert (layer >= 0);
x = fetch_int ();
}
assert (x == CODE_decrypted_message || x == CODE_decrypted_message_service);
assert (x == CODE_decrypted_message || x == CODE_decrypted_message_service || x == CODE_decrypted_message_l16 || x == CODE_decrypted_message_service_l16);
//assert (id == fetch_long ());
if (x == CODE_decrypted_message || x == CODE_decrypted_message_service) {
int out_seq_no = fetch_int ();
int in_seq_no = fetch_int ();
if (in_seq_no / 2 <= P->encr_chat.in_seq_no) {
vlogprintf (E_WARNING, "Hole in seq in secret chat. in_seq_no = %d, expect_seq_no = %d\n", in_seq_no / 2, P->encr_chat.in_seq_no + 1);
}
if (in_seq_no / 2 > P->encr_chat.in_seq_no + 1) {
vlogprintf (E_WARNING, "Hole in seq in secret chat. in_seq_no = %d, expect_seq_no = %d\n", in_seq_no / 2, P->encr_chat.in_seq_no + 1);
}
//vlogprintf (E_WARNING, "in = %d, out = %d\n", in_seq_no, out_seq_no);
assert (out_seq_no / 2 <= P->encr_chat.out_seq_no);
P->encr_chat.in_seq_no = in_seq_no / 2;
if (x == CODE_decrypted_message) {
fetch_int (); // ttl
}
} else {
P->encr_chat.in_seq_no ++;
}
fetch_long ();
ll = prefetch_strlen ();
fetch_str (ll); // random_bytes
if (x == CODE_decrypted_message) {
if (x == CODE_decrypted_message || x == CODE_decrypted_message_l16) {
l = prefetch_strlen ();
s = fetch_str (l);
start = in_ptr;
......@@ -1216,9 +1271,9 @@ void tglf_fetch_encrypted_message (struct tgl_message *M) {
if (ok) {
int *start_file = in_ptr;
assert (skip_type_any (TYPE_TO_PARAM (encrypted_file)) >= 0);
if (x == CODE_decrypted_message) {
if (x == CODE_decrypted_message || x == CODE_decrypted_message_l16) {
bl_do_create_message_media_encr (id, P->encr_chat.user_id, TGL_PEER_ENCR_CHAT, to_id, date, l, s, start, end - start, start_file, in_ptr - start_file);
} else if (x == CODE_decrypted_message_service) {
} else if (x == CODE_decrypted_message_service || x == CODE_decrypted_message_service_l16) {
bl_do_create_message_service_encr (id, P->encr_chat.user_id, TGL_PEER_ENCR_CHAT, to_id, date, start, end - start);
}
} else {
......@@ -1226,7 +1281,7 @@ void tglf_fetch_encrypted_message (struct tgl_message *M) {
M->media.type = CODE_message_media_empty;
}
} else {
if (ok && x == CODE_decrypted_message_service) {
if (ok && (x == CODE_decrypted_message_service || x == CODE_decrypted_message_service_l16)) {
bl_do_create_message_service_encr (id, P->encr_chat.user_id, TGL_PEER_ENCR_CHAT, to_id, date, start, end - start);
}
}
......@@ -1310,12 +1365,12 @@ struct tgl_user *tglf_fetch_alloc_user_full (void) {
}
struct tgl_message *tglf_fetch_alloc_message (void) {
int data[2];
prefetch_data (data, 8);
struct tgl_message *M = tgl_message_get (data[1]);
int data[3];
prefetch_data (data, 12);
struct tgl_message *M = tgl_message_get (data[0] != (int)CODE_message_empty ? data[2] : data[1]);
if (!M) {
M = tglm_message_alloc (data[1]);
M = tglm_message_alloc (data[0] != (int)CODE_message_empty ? data[2] : data[1]);
}
tglf_fetch_message (M);
return M;
......
......@@ -51,5 +51,6 @@ void tglp_peer_delete_name (tgl_peer_t *P);
void tglp_insert_encrypted_chat (tgl_peer_t *P);
void tglp_insert_user (tgl_peer_t *P);
void tglp_insert_chat (tgl_peer_t *P);
enum tgl_typing_status tglf_fetch_typing (void);
#endif
......@@ -120,7 +120,22 @@ enum tgl_message_action_type {
tgl_message_action_delete_messages,
tgl_message_action_screenshot_messages,
tgl_message_action_flush_history,
tgl_message_action_notify_layer
tgl_message_action_notify_layer,
tgl_message_action_typing
};
enum tgl_typing_status {
tgl_typing_none,
tgl_typing_typing,
tgl_typing_cancel,
tgl_typing_record_video,
tgl_typing_upload_video,
tgl_typing_record_audio,
tgl_typing_upload_audio,
tgl_typing_upload_photo,
tgl_typing_upload_document,
tgl_typing_geo,
tgl_typing_choose_contact
};
struct tgl_file_location {
......@@ -288,6 +303,8 @@ struct tgl_secret_chat {
int date;
int ttl;
int layer;
int in_seq_no;
int out_seq_no;
long long access_hash;
unsigned char *g_key;
unsigned char *nonce;
......@@ -367,6 +384,7 @@ struct tgl_message_action {
int read_cnt;
int delete_cnt;
int screenshot_cnt;
enum tgl_typing_status typing;
};
};
......
......@@ -24,16 +24,22 @@
#include <string.h>
#define TGL_MAX_DC_NUM 100
#define TG_SERVER "149.154.167.50"
#define TG_SERVER_TEST "149.154.167.40"
#define TG_SERVER_DC 2
#define TG_SERVER_TEST_DC 2
#define TG_SERVER_1 "173.240.5.1"
#define TG_SERVER_2 "149.154.167.51"
#define TG_SERVER_3 "174.140.142.6"
#define TG_SERVER_4 "149.154.167.91"
#define TG_SERVER_5 "149.154.171.5"
#define TG_SERVER_TEST_1 "173.240.5.253"
#define TG_SERVER_TEST_2 "149.154.167.40"
#define TG_SERVER_TEST_3 "174.140.142.5"
// JUST RANDOM STRING
#define TGL_BUILD "2014"
#define TGL_VERSION "1.0.5"
#define TGL_BUILD "2234"
#define TGL_VERSION "1.0.6"
#define TGL_ENCRYPTED_LAYER 16
#define TGL_ENCRYPTED_LAYER 17
struct connection;
struct mtproto_methods;
......@@ -70,8 +76,8 @@ struct tgl_update_callback {
void (*new_msg)(struct tgl_message *M);
void (*marked_read)(int num, struct tgl_message *list[]);
void (*logprintf)(const char *format, ...) __attribute__ ((format (printf, 1, 2)));
void (*type_notification)(struct tgl_user *U);
void (*type_in_chat_notification)(struct tgl_user *U, struct tgl_chat *C);
void (*type_notification)(struct tgl_user *U, enum tgl_typing_status status);
void (*type_in_chat_notification)(struct tgl_user *U, struct tgl_chat *C, enum tgl_typing_status status);
void (*type_in_secret_chat_notification)(struct tgl_secret_chat *E);
void (*status_notification)(struct tgl_user *U);
void (*user_registered)(struct tgl_user *U);
......@@ -289,6 +295,7 @@ void tgl_do_send_contact (tgl_peer_id_t id, const char *phone, int phone_len, co
void tgl_do_forward_media (tgl_peer_id_t id, int n, void (*callback)(void *callback_extra, int success, struct tgl_message *M), void *callback_extra);
void tgl_do_del_contact (tgl_peer_id_t id, void (*callback)(void *callback_extra, int success), void *callback_extra);
void tgl_do_set_encr_chat_ttl (struct tgl_secret_chat *E, int ttl, void (*callback)(void *callback_extra, int success, struct tgl_message *M), void *callback_extra);
void tgl_do_send_location(tgl_peer_id_t id, double latitude, double longitude, void (*callback)(void *callback_extra, int success, struct tgl_message *M), void *callback_extra);
void tgl_do_visualize_key (tgl_peer_id_t id, unsigned char buf[16]);
......
......@@ -99,24 +99,28 @@ void tglu_work_update (struct connection *c, long long msg_id) {
break;
case CODE_update_user_typing:
{
//vlogprintf (E_ERROR, "user typing\n");
tgl_peer_id_t id = TGL_MK_USER (fetch_int ());
tgl_peer_t *U = tgl_peer_get (id);
enum tgl_typing_status status = tglf_fetch_typing ();
if (tgl_state.callback.type_notification && U) {
tgl_state.callback.type_notification ((void *)U);
tgl_state.callback.type_notification ((void *)U, status);
}
}
break;
case CODE_update_chat_user_typing:
{
//vlogprintf (E_ERROR, "chat typing\n");
tgl_peer_id_t chat_id = TGL_MK_CHAT (fetch_int ());
tgl_peer_id_t id = TGL_MK_USER (fetch_int ());
tgl_peer_t *C = tgl_peer_get (chat_id);
tgl_peer_t *U = tgl_peer_get (id);
enum tgl_typing_status status = tglf_fetch_typing ();
if (U && C) {
if (tgl_state.callback.type_in_chat_notification) {
tgl_state.callback.type_in_chat_notification ((void *)U, (void *)C);
tgl_state.callback.type_in_chat_notification ((void *)U, (void *)C, status);
}
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment