Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve history handling #97

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@ distclean:
rm -rf ${DIR_LIST} config.h config.log config.status

mime-types.c: mime.types
@echo "// DO NOT EDIT! SEE MAKE-TARGET 'gen-mime-types'" > mime-types.c
# xxd is usually packaged with vim-common
xxd -i mime.types >> mime-types.c
@echo xxd -i mime.types > mime-types.c
@if command -v xxd >/dev/null 2>&1 ; then \
xxd -i mime.types > mime-types.c ; \
else \
echo "# No xxd installed! Trying to skip ..." ; \
test -r $@ ; \
fi
1 change: 1 addition & 0 deletions auto-static-autocomplete.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ int tglf_extf_autocomplete (struct tgl_state *TLS, const char *text, int text_le
#ifdef DISABLE_EXTF
(void) free_vars_to_be_freed;
assert (0);
return 0;
#else
if (index == -1) {
buffer_pos = data;
Expand Down
1 change: 1 addition & 0 deletions auto-static-fetch.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ static void print_offset (void) {
char *tglf_extf_fetch (struct tgl_state *TLS, struct paramed_type *T) {
#ifdef DISABLE_EXTF
assert (0);
return 0;
#else
out_buf_pos = 0;
if (fetch_type_any (T) < 0) { return 0; }
Expand Down
Empty file removed auto-static-skip.c
Empty file.
1 change: 1 addition & 0 deletions auto-static-store.c
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ void tgl_paramed_type_free (struct paramed_type *P);
struct paramed_type *tglf_extf_store (struct tgl_state *TLS, const char *data, int data_len) {
#ifdef DISABLE_EXTF
assert (0);
return 0;
#else
buffer_pos = (char *)data;
buffer_end = (char *)(data + data_len);
Expand Down
6 changes: 6 additions & 0 deletions crypto/err.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,10 @@

void TGLC_err_print_errors_fp (FILE *fp);

// Don't want to include tgl.h just for this
struct tgl_state;

// Init crypto backend, log to TLS
int TGLC_init (struct tgl_state *TLS);

#endif
41 changes: 41 additions & 0 deletions crypto/err_altern.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,52 @@

#include <gcrypt.h>

#include "../tgl.h"
#include "../tgl-inner.h"
#include "err.h"

void TGLC_err_print_errors_fp (FILE *fp) {
// Can't print anything meaningful, so don't.
(void) fp;
}

int TGLC_init (struct tgl_state *TLS) {
vlogprintf (E_NOTICE, "Init gcrypt\n");
// https://gnupg.org/documentation/manuals/gcrypt/Initializing-the-library.html
// https://lists.gnupg.org/pipermail/gcrypt-devel/2003-August/000458.html

if (gcry_control (GCRYCTL_INITIALIZATION_FINISHED_P)) {
// Someone else already *completed* it.
vlogprintf (E_NOTICE, "Init gcrypt: already initialized -- good\n");
return 0;
}

if (gcry_control (GCRYCTL_ANY_INITIALIZATION_P)) {
// Someone else already *started* it without *completing*.
vlogprintf (E_WARNING, "Init gcrypt: already started *but not completed* by third party -- bad\n");
vlogprintf (E_WARNING, "Init gcrypt: ... not trying to init gcrypt then.\n");
return 0;
}

if (!gcry_check_version (GCRYPT_VERSION)) {
vlogprintf (E_ERROR, "Init gcrypt: version mismatch!\n");
return -1;
}

gcry_error_t err = gcry_control (GCRYCTL_DISABLE_SECMEM, NULL, 0);
if (err != GPG_ERR_NO_ERROR) {
vlogprintf (E_ERROR, "Init gcrypt: secmem failed?!\n");
return -1;
}

/* Tell Libgcrypt that initialization has completed. */
err = gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
if (err != GPG_ERR_NO_ERROR) {
vlogprintf (E_ERROR, "Init gcrypt: init failed?!\n");
return -1;
}

return 0;
}

#endif
8 changes: 8 additions & 0 deletions crypto/err_openssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,18 @@

#include <openssl/err.h>

#include "../tgl.h"
#include "../tgl-inner.h"
#include "err.h"

void TGLC_err_print_errors_fp (FILE *fp) {
ERR_print_errors_fp (fp);
}

int TGLC_init (struct tgl_state *TLS) {
// Doesn't seem to need any initialization.
vlogprintf (6, "Init OpenSSL (no-op)\n");
return 0;
}

#endif
1 change: 0 additions & 1 deletion generate.c
Original file line number Diff line number Diff line change
Expand Up @@ -2307,7 +2307,6 @@ void gen_skip_source (void) {
printf ("#include <assert.h>\n");

printf ("#include \"auto/auto-skip.h\"\n");
printf ("#include \"auto-static-skip.c\"\n");
printf ("#include \"mtproto-common.h\"\n");

int i, j;
Expand Down
9 changes: 5 additions & 4 deletions mtproto-client.c
Original file line number Diff line number Diff line change
Expand Up @@ -678,11 +678,12 @@ static double get_server_time (struct tgl_dc *DC) {

static long long generate_next_msg_id (struct tgl_state *TLS, struct tgl_dc *DC, struct tgl_session *S) {
long long next_id = (long long) (get_server_time (DC) * (1LL << 32)) & -4;
if (next_id <= S->last_msg_id) {
next_id = S->last_msg_id += 4;
if (next_id <= TLS->last_msg_id) {
next_id = TLS->last_msg_id += 4;
} else {
S->last_msg_id = next_id;
TLS->last_msg_id = next_id;
}
S->last_msg_id = next_id; // See tglmp_encrypt_send_message
return next_id;
}

Expand Down Expand Up @@ -754,7 +755,7 @@ long long tglmp_encrypt_send_message (struct tgl_state *TLS, struct connection *
assert (l > 0);
rpc_send_message (TLS, c, &enc_msg, l + UNENCSZ);

return S->last_msg_id;
return S->last_msg_id; // Pray that this was set by generate_next_msg_id somehow
}

int tglmp_encrypt_inner_temp (struct tgl_state *TLS, struct connection *c, int *msg, int msg_ints, int useful, void *data, long long msg_id) {
Expand Down
4 changes: 1 addition & 3 deletions mtproto-utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@ static unsigned long long BN2ull (TGLC_bn *b) {
if (sizeof (unsigned long) == 8) {
return TGLC_bn_get_word (b);
} else if (sizeof (unsigned long long) == 8) {
assert (0); // As long as nobody ever uses this code, assume it is broken.
unsigned long long tmp;
/* Here be dragons, but it should be okay due to be64toh */
TGLC_bn_bn2bin (b, (unsigned char *) &tmp);
Expand All @@ -112,8 +111,7 @@ static void ull2BN (TGLC_bn *b, unsigned long long val) {
if (sizeof (unsigned long) == 8 || val < (1ll << 32)) {
TGLC_bn_set_word (b, val);
} else if (sizeof (unsigned long long) == 8) {
assert (0); // As long as nobody ever uses this code, assume it is broken.
htobe64(val);
val = htobe64(val);
/* Here be dragons, but it should be okay due to htobe64 */
TGLC_bn_bin2bn ((unsigned char *) &val, 8, b);
} else {
Expand Down
83 changes: 62 additions & 21 deletions queries.c
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,20 @@ int utf8_len (const char *s, int len) {
return r;
}

static inline char ascii_char_norm (char c) {
return (c >= 0x41 && c <= 0x5A) ? c + 32 : c;
}

static int ascii_cmp_nocase (const char *what, const char *with, size_t num) {
size_t i;
for (i = 0; i < num; i ++) {
if (ascii_char_norm (what[i]) != ascii_char_norm (with[i])) {
return 1;
}
}
return 0;
}

static char *process_html_text (struct tgl_state *TLS, const char *text, int text_len, int *ent_size, int **ent) {
char *new_text = talloc (2 * text_len + 1);
int stpos[100];
Expand All @@ -619,7 +633,7 @@ static char *process_html_text (struct tgl_state *TLS, const char *text, int tex
return NULL;
}
int old_p = *ent_size;
if (text_len - p >= 3 && !memcmp (text + p, "<b>", 3)) {
if (text_len - p >= 3 && !ascii_cmp_nocase (text + p, "<b>", 3)) {
increase_ent (ent_size, ent, 3);
total ++;
(*ent)[old_p] = CODE_message_entity_bold;
Expand All @@ -630,7 +644,7 @@ static char *process_html_text (struct tgl_state *TLS, const char *text, int tex
p += 2;
continue;
}
if (text_len - p >= 4 && !memcmp (text + p, "</b>", 4)) {
if (text_len - p >= 4 && !ascii_cmp_nocase (text + p, "</b>", 4)) {
if (stp == 0 || sttype[stp - 1] != 0) {
tgl_set_query_error (TLS, EINVAL, "Invalid tag nest");
tfree (new_text, 2 * text_len + 1);
Expand All @@ -641,7 +655,7 @@ static char *process_html_text (struct tgl_state *TLS, const char *text, int tex
p += 3;
continue;
}
if (text_len - p >= 3 && !memcmp (text + p, "<i>", 3)) {
if (text_len - p >= 3 && !ascii_cmp_nocase (text + p, "<i>", 3)) {
increase_ent (ent_size, ent, 3);
total ++;
(*ent)[old_p] = CODE_message_entity_italic;
Expand All @@ -652,7 +666,7 @@ static char *process_html_text (struct tgl_state *TLS, const char *text, int tex
p += 2;
continue;
}
if (text_len - p >= 4 && !memcmp (text + p, "</i>", 4)) {
if (text_len - p >= 4 && !ascii_cmp_nocase (text + p, "</i>", 4)) {
if (stp == 0 || sttype[stp - 1] != 1) {
tgl_set_query_error (TLS, EINVAL, "Invalid tag nest");
tfree (new_text, 2 * text_len + 1);
Expand All @@ -663,7 +677,7 @@ static char *process_html_text (struct tgl_state *TLS, const char *text, int tex
p += 3;
continue;
}
if (text_len - p >= 6 && !memcmp (text + p, "<code>", 6)) {
if (text_len - p >= 6 && !ascii_cmp_nocase (text + p, "<code>", 6)) {
increase_ent (ent_size, ent, 3);
total ++;
(*ent)[old_p] = CODE_message_entity_code;
Expand All @@ -674,7 +688,7 @@ static char *process_html_text (struct tgl_state *TLS, const char *text, int tex
p += 5;
continue;
}
if (text_len - p >= 7 && !memcmp (text + p, "</code>", 7)) {
if (text_len - p >= 7 && !ascii_cmp_nocase (text + p, "</code>", 7)) {
if (stp == 0 || sttype[stp - 1] != 2) {
tgl_set_query_error (TLS, EINVAL, "Invalid tag nest");
tfree (new_text, 2 * text_len + 1);
Expand All @@ -685,12 +699,12 @@ static char *process_html_text (struct tgl_state *TLS, const char *text, int tex
p += 6;
continue;
}
if (text_len - p >= 9 && !memcmp (text + p, "<a href=\"", 9)) {
if (text_len - p >= 9 && !ascii_cmp_nocase (text + p, "<a href=\"", 9)) {
int pp = p + 9;
while (pp < text_len && text[pp] != '"') {
pp ++;
}
if (pp == text_len || pp == text_len - 1 || text[pp + 1] != '>') {
if (pp == text_len || pp == text_len - 1) {
tgl_set_query_error (TLS, EINVAL, "<a> tag did not close");
tfree (new_text, 2 * text_len + 1);
return NULL;
Expand All @@ -716,10 +730,13 @@ static char *process_html_text (struct tgl_state *TLS, const char *text, int tex
memcpy (r + 1, text + p + 9, len);
memset (r + 1 + len, 0, (-len-1) & 3);

p = pp + 1;
while (pp < text_len && text[pp] != '>') {
pp ++;
}
p = pp;
continue;
}
if (text_len - p >= 4 && !memcmp (text + p, "</a>", 4)) {
if (text_len - p >= 4 && !ascii_cmp_nocase (text + p, "</a>", 4)) {
if (stp == 0 || sttype[stp - 1] != 3) {
tgl_set_query_error (TLS, EINVAL, "Invalid tag nest");
tfree (new_text, 2 * text_len + 1);
Expand All @@ -730,24 +747,27 @@ static char *process_html_text (struct tgl_state *TLS, const char *text, int tex
p += 3;
continue;
}
if (text_len - p >= 4 && !memcmp (text + p, "<br>", 4)) {
if (text_len - p >= 4 && !ascii_cmp_nocase (text + p, "<br>", 4)) {
new_text[cur_p ++] = '\n';
p += 3;
continue;
}
tgl_set_query_error (TLS, EINVAL, "Unknown tag");
tfree (new_text, 2 * text_len + 1);
return NULL;
} else if (text_len - p >= 4 && !memcmp (text + p, "&gt;", 4)) {
} else if (text_len - p >= 4 && !ascii_cmp_nocase (text + p, "&gt;", 4)) {
p += 3;
new_text[cur_p ++] = '>';
} else if (text_len - p >= 4 && !memcmp (text + p, "&lt;", 4)) {
} else if (text_len - p >= 4 && !ascii_cmp_nocase (text + p, "&lt;", 4)) {
p += 3;
new_text[cur_p ++] = '<';
} else if (text_len - p >= 5 && !memcmp (text + p, "&amp;", 5)) {
} else if (text_len - p >= 5 && !ascii_cmp_nocase (text + p, "&amp;", 5)) {
p += 4;
new_text[cur_p ++] = '&';
} else if (text_len - p >= 6 && !memcmp (text + p, "&nbsp;", 6)) {
} else if (text_len - p >= 6 && !ascii_cmp_nocase (text + p, "&quot;", 6)) {
p += 5;
new_text[cur_p ++] = '"';
} else if (text_len - p >= 6 && !ascii_cmp_nocase (text + p, "&nbsp;", 6)) {
p += 5;
new_text[cur_p ++] = 0xc2;
new_text[cur_p ++] = 0xa0;
Expand Down Expand Up @@ -1449,7 +1469,9 @@ struct get_history_extra {
tgl_peer_id_t id;
int limit;
int offset;
int max_id;
int offset_id;
int min_id;
int is_range;
};

static void _tgl_do_get_history (struct tgl_state *TLS, struct get_history_extra *E, void (*callback)(struct tgl_state *TLS,void *callback_extra, int success, int size, struct tgl_message *list[]), void *callback_extra);
Expand Down Expand Up @@ -1493,10 +1515,16 @@ static int get_history_on_answer (struct tgl_state *TLS, struct query *q, void *
E->limit = count - E->offset;
if (E->limit < 0) { E->limit = 0; }
}
assert (E->limit >= 0);

if (E->is_range > 0) {
if (n <= 0) {
E->limit = 0; // no messages left in the range
} else if (E->ML[E->list_offset - 1] && E->ML[E->list_offset - 1]->permanent_id.id <= E->min_id + 1) {
E->limit = 0; // offset_id lower than min_id
}
}

if (E->limit <= 0 || DS_MM->magic == CODE_messages_messages || DS_MM->magic == CODE_messages_channel_messages) {
if (E->limit <= 0 || DS_MM->magic == CODE_messages_messages) {
if (q->callback) {
((void (*)(struct tgl_state *TLS, void *, int, int, struct tgl_message **))q->callback) (TLS, q->callback_extra, 1, E->list_offset, E->ML);
}
Expand All @@ -1507,8 +1535,9 @@ static int get_history_on_answer (struct tgl_state *TLS, struct query *q, void *
tfree (E->ML, sizeof (void *) * E->list_size);
tfree (E, sizeof (*E));
} else {
assert (E->list_offset > 0);
E->offset = 0;
E->max_id = E->ML[E->list_offset - 1]->permanent_id.id;
E->offset_id = E->ML[E->list_offset - 1]->permanent_id.id;
_tgl_do_get_history (TLS, E, q->callback, q->callback_extra);
}
return 0;
Expand Down Expand Up @@ -1587,11 +1616,11 @@ static void _tgl_do_get_history (struct tgl_state *TLS, struct get_history_extra
out_int (tgl_get_peer_id (E->id));
out_long (E->id.access_hash);
}
out_int (E->max_id);
out_int (E->offset_id);
out_int (E->offset);
out_int (E->limit);
out_int (0);
out_int (0);
out_int (E->min_id);
tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &get_history_methods, E, callback, callback_extra);
}

Expand All @@ -1607,6 +1636,18 @@ void tgl_do_get_history (struct tgl_state *TLS, tgl_peer_id_t id, int offset, in
E->offset = offset;
_tgl_do_get_history (TLS, E, callback, callback_extra);
}

void tgl_do_get_history_range (struct tgl_state *TLS, tgl_peer_id_t id, int min_id, int max_id, int limit, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, int size, struct tgl_message *list[]), void *callback_extra) {

struct get_history_extra *E = talloc0 (sizeof (*E));
E->id = id;
E->limit = limit;
E->offset_id = max_id;
E->min_id = min_id;
E->is_range = 1;

_tgl_do_get_history (TLS, E, callback, callback_extra);
}
/* }}} */

/* {{{ Get dialogs */
Expand Down
Loading