Commit parse of many structures (message, chat, photo, etc)
This commit is contained in:
parent
5f2080e956
commit
baa56b709c
19
gen_constants_h.awk
Normal file
19
gen_constants_h.awk
Normal file
@ -0,0 +1,19 @@
|
||||
BEGIN {
|
||||
print "#ifndef CONSTANTS_H";
|
||||
print "#define CONSTANTS_H";
|
||||
}
|
||||
// {
|
||||
if (split ($1, a, "#") == 2) {
|
||||
gsub (/[A-Z]/, "_&", a[1]);
|
||||
gsub (/[.]/, "_", a[1]);
|
||||
if (a[2] in h) {
|
||||
print "ERROR: Duplicate magic " a[2] " for define " a[1] " and " h[a[2]] >"/dev/stderr/"
|
||||
exit 1;
|
||||
}
|
||||
h[a[2]] = a[1];
|
||||
print "#define", "CODE_" tolower(a[1]), "0x" a[2];
|
||||
}
|
||||
}
|
||||
END {
|
||||
print "#endif";
|
||||
}
|
24
interface.c
24
interface.c
@ -104,14 +104,28 @@ int get_complete_mode (void) {
|
||||
}
|
||||
|
||||
extern int user_num;
|
||||
extern struct user *Users[];
|
||||
extern int chat_num;
|
||||
extern union user_chat *Peers[];
|
||||
int complete_user_list (int index, const char *text, int len, char **R) {
|
||||
index ++;
|
||||
while (index < user_num && (!Users[index]->print_name || strncmp (Users[index]->print_name, text, len))) {
|
||||
while (index < user_num + chat_num && (!Peers[index]->print_name || strncmp (Peers[index]->print_name, text, len) || Peers[index]->id < 0)) {
|
||||
index ++;
|
||||
}
|
||||
if (index < user_num) {
|
||||
*R = strdup (Users[index]->print_name);
|
||||
if (index < user_num + chat_num) {
|
||||
*R = strdup (Peers[index]->print_name);
|
||||
return index;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int complete_user_chat_list (int index, const char *text, int len, char **R) {
|
||||
index ++;
|
||||
while (index < user_num + chat_num && (!Peers[index]->print_name || strncmp (Peers[index]->print_name, text, len))) {
|
||||
index ++;
|
||||
}
|
||||
if (index < user_num + chat_num) {
|
||||
*R = strdup (Peers[index]->print_name);
|
||||
return index;
|
||||
} else {
|
||||
return -1;
|
||||
@ -161,7 +175,7 @@ char *command_generator (const char *text, int state) {
|
||||
index = complete_user_list (index, text, len, &R);
|
||||
return R;
|
||||
case 2:
|
||||
index = complete_string_list (chat_list, index, text, len, &R);
|
||||
index = complete_user_chat_list (index, text, len, &R);
|
||||
return R;
|
||||
case 3:
|
||||
return rl_filename_completion_function(text,state);
|
||||
|
@ -270,7 +270,10 @@ static inline char *fetch_str (int len) {
|
||||
|
||||
static inline char *fetch_str_dup (void) {
|
||||
int l = prefetch_strlen ();
|
||||
return strndup (fetch_str (l), l);
|
||||
char *s = malloc (l + 1);
|
||||
memcpy (s, fetch_str (l), l);
|
||||
s[l] = 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
static __inline__ unsigned long long rdtsc(void) {
|
||||
@ -299,6 +302,17 @@ static inline long long fetch_long (void) {
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline double fetch_double (void) {
|
||||
double r = *(double *)in_ptr;
|
||||
in_ptr += 2;
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline void fetch_ints (void *data, int count) {
|
||||
memcpy (data, in_ptr, 4 * count);
|
||||
in_ptr += count;
|
||||
}
|
||||
|
||||
int get_random_bytes (void *buf, int n);
|
||||
|
||||
int pad_rsa_encrypt (char *from, int from_len, char *to, int size, BIGNUM *N, BIGNUM *E);
|
||||
|
334
structures.c
334
structures.c
@ -105,7 +105,7 @@ void fetch_chat (struct chat *C) {
|
||||
memset (C, 0, sizeof (*C));
|
||||
unsigned x = fetch_int ();
|
||||
assert (x == CODE_chat_empty || x == CODE_chat || x == CODE_chat_forbidden);
|
||||
C->id = fetch_int ();
|
||||
C->id = -fetch_int ();
|
||||
if (x == CODE_chat_empty) {
|
||||
C->flags = 1;
|
||||
return;
|
||||
@ -130,34 +130,200 @@ void fetch_chat (struct chat *C) {
|
||||
fetch_file_location (&C->photo_small);
|
||||
fetch_file_location (&C->photo_big);
|
||||
}
|
||||
C->user_num = fetch_int ();
|
||||
C->date = fetch_int ();
|
||||
if (fetch_int () == (int)CODE_bool_true) {
|
||||
C->flags |= 16;
|
||||
}
|
||||
C->version = fetch_int ();
|
||||
} else {
|
||||
C->photo_small.dc = -2;
|
||||
C->photo_big.dc = -2;
|
||||
C->user_num = -1;
|
||||
C->date = fetch_int ();
|
||||
C->version = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void fetch_photo_size (struct photo_size *S) {
|
||||
unsigned x = fetch_int ();
|
||||
assert (x == CODE_photo_size || x == CODE_photo_cached_size);
|
||||
S->type = fetch_str_dup ();
|
||||
fetch_file_location (&S->loc);
|
||||
S->w = fetch_int ();
|
||||
S->h = fetch_int ();
|
||||
if (x == CODE_photo_size) {
|
||||
S->size = fetch_int ();
|
||||
} else {
|
||||
S->data = fetch_str_dup ();
|
||||
}
|
||||
}
|
||||
|
||||
void fetch_geo (struct geo *G) {
|
||||
assert (fetch_int () == CODE_geo_point);
|
||||
G->longitude = fetch_double ();
|
||||
G->latitude = fetch_double ();
|
||||
}
|
||||
|
||||
void fetch_photo (struct photo *P) {
|
||||
memset (P, 0, sizeof (*P));
|
||||
unsigned x = fetch_int ();
|
||||
P->id = fetch_long ();
|
||||
if (x == CODE_photo_empty) { return; }
|
||||
P->access_hash = fetch_long ();
|
||||
P->user_id = fetch_int ();
|
||||
P->date = fetch_int ();
|
||||
P->caption = fetch_str_dup ();
|
||||
fetch_geo (&P->geo);
|
||||
assert (fetch_int () == CODE_vector);
|
||||
P->sizes_num = fetch_int ();
|
||||
P->sizes = malloc (sizeof (struct photo_size) * P->sizes_num);
|
||||
int i;
|
||||
for (i = 0; i < P->sizes_num; i++) {
|
||||
fetch_photo_size (&P->sizes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void fetch_video (struct video *V) {
|
||||
memset (V, 0, sizeof (*V));
|
||||
unsigned x = fetch_int ();
|
||||
V->id = fetch_long ();
|
||||
if (x == CODE_video_empty) { return; }
|
||||
V->access_hash = fetch_long ();
|
||||
V->user_id = fetch_int ();
|
||||
V->date = fetch_int ();
|
||||
V->caption = fetch_str_dup ();
|
||||
V->duration = fetch_int ();
|
||||
V->size = fetch_int ();
|
||||
fetch_photo_size (&V->thumb);
|
||||
V->dc_id = fetch_int ();
|
||||
V->w = fetch_int ();
|
||||
V->h = fetch_int ();
|
||||
}
|
||||
|
||||
void fetch_message_action (struct message_action *M) {
|
||||
memset (M, 0, sizeof (*M));
|
||||
unsigned x = fetch_int ();
|
||||
M->type = x;
|
||||
switch (x) {
|
||||
case CODE_message_action_empty:
|
||||
break;
|
||||
case CODE_message_action_chat_create:
|
||||
M->title = fetch_str_dup ();
|
||||
assert (fetch_int () == (int)CODE_vector);
|
||||
M->user_num = fetch_int ();
|
||||
M->users = malloc (M->user_num * 4);
|
||||
fetch_ints (M->users, M->user_num);
|
||||
break;
|
||||
case CODE_message_action_chat_edit_title:
|
||||
M->new_title = fetch_str_dup ();
|
||||
break;
|
||||
case CODE_message_action_chat_edit_photo:
|
||||
fetch_photo (&M->photo);
|
||||
break;
|
||||
case CODE_message_action_chat_delete_photo:
|
||||
break;
|
||||
case CODE_message_action_chat_add_user:
|
||||
M->user = fetch_int ();
|
||||
break;
|
||||
case CODE_message_action_chat_delete_user:
|
||||
M->user = fetch_int ();
|
||||
break;
|
||||
default:
|
||||
assert (0);
|
||||
}
|
||||
}
|
||||
|
||||
void fetch_message_media (struct message_media *M) {
|
||||
memset (M, 0, sizeof (*M));
|
||||
M->type = fetch_int ();
|
||||
switch (M->type) {
|
||||
case CODE_message_media_empty:
|
||||
break;
|
||||
case CODE_message_media_photo:
|
||||
fetch_photo (&M->photo);
|
||||
break;
|
||||
case CODE_message_media_video:
|
||||
fetch_video (&M->video);
|
||||
break;
|
||||
case CODE_message_media_geo:
|
||||
fetch_geo (&M->geo);
|
||||
break;
|
||||
case CODE_message_media_contact:
|
||||
M->phone = fetch_str_dup ();
|
||||
M->first_name = fetch_str_dup ();
|
||||
M->last_name = fetch_str_dup ();
|
||||
M->user_id = fetch_int ();
|
||||
break;
|
||||
case CODE_message_media_unsupported:
|
||||
M->data = fetch_str_dup ();
|
||||
break;
|
||||
default:
|
||||
assert (0);
|
||||
}
|
||||
}
|
||||
|
||||
void fetch_message (struct message *M) {
|
||||
memset (M, 0, sizeof (*M));
|
||||
unsigned x = fetch_int ();
|
||||
assert (x == CODE_message_empty || x == CODE_message || x == CODE_message_forwarded || x == CODE_message_service);
|
||||
M->id = fetch_int ();
|
||||
if (x == CODE_message_empty) {
|
||||
M->flags |= 1;
|
||||
return;
|
||||
}
|
||||
if (x == CODE_message_forwarded) {
|
||||
M->fwd_from_id = fetch_int ();
|
||||
M->fwd_date = fetch_int ();
|
||||
}
|
||||
M->from_id = fetch_int ();
|
||||
M->to_id = fetch_int ();
|
||||
M->out = (fetch_int () == (int)CODE_bool_true);
|
||||
M->unread = (fetch_int () == (int)CODE_bool_true);
|
||||
M->date = fetch_int ();
|
||||
if (x == CODE_message_service) {
|
||||
M->service = 1;
|
||||
fetch_message_action (&M->action);
|
||||
} else {
|
||||
M->message = fetch_str_dup ();
|
||||
fetch_message_media (&M->media);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#define user_cmp(a,b) ((a)->id - (b)->id)
|
||||
|
||||
DEFINE_TREE(user,struct user *,user_cmp,0)
|
||||
struct tree_user *user_tree;
|
||||
DEFINE_TREE(peer,union user_chat *,user_cmp,0)
|
||||
DEFINE_TREE(message,struct message *,user_cmp,0)
|
||||
struct tree_peer *peer_tree;
|
||||
struct tree_message *message_tree;
|
||||
|
||||
int chat_num;
|
||||
int user_num;
|
||||
struct user *Users[MAX_USER_NUM];
|
||||
int users_allocated;
|
||||
int chats_allocated;
|
||||
int messages_allocated;
|
||||
union user_chat *Peers[MAX_USER_NUM];
|
||||
|
||||
struct message message_list = {
|
||||
.next_use = &message_list,
|
||||
.prev_use = &message_list
|
||||
};
|
||||
|
||||
struct user *fetch_alloc_user (void) {
|
||||
struct user *U = malloc (sizeof (*U));
|
||||
fetch_user (U);
|
||||
union user_chat *U = malloc (sizeof (*U));
|
||||
fetch_user (&U->user);
|
||||
users_allocated ++;
|
||||
struct user *U1 = tree_lookup_user (user_tree, U);
|
||||
union user_chat *U1 = tree_lookup_peer (peer_tree, U);
|
||||
if (U1) {
|
||||
free_user (U1);
|
||||
free_user (&U1->user);
|
||||
memcpy (U1, U, sizeof (*U));
|
||||
free (U);
|
||||
users_allocated --;
|
||||
return U1;
|
||||
return &U1->user;
|
||||
} else {
|
||||
user_tree = tree_insert_user (user_tree, U, lrand48 ());
|
||||
Users[user_num ++] = U;
|
||||
return U;
|
||||
peer_tree = tree_insert_peer (peer_tree, U, lrand48 ());
|
||||
Peers[chat_num + (user_num ++)] = U;
|
||||
return &U->user;
|
||||
}
|
||||
}
|
||||
|
||||
@ -168,10 +334,144 @@ void free_user (struct user *U) {
|
||||
if (U->phone) { free (U->phone); }
|
||||
}
|
||||
|
||||
void free_photo_size (struct photo_size *S) {
|
||||
free (S->type);
|
||||
free (S->data);
|
||||
}
|
||||
|
||||
void free_photo (struct photo *P) {
|
||||
free (P->caption);
|
||||
int i;
|
||||
for (i = 0; i < P->sizes_num; i++) {
|
||||
free_photo_size (&P->sizes[i]);
|
||||
}
|
||||
free (P->sizes);
|
||||
}
|
||||
|
||||
void free_video (struct video *V) {
|
||||
free (V->caption);
|
||||
free (&V->thumb);
|
||||
}
|
||||
|
||||
void free_message_media (struct message_media *M) {
|
||||
switch (M->type) {
|
||||
case CODE_message_media_empty:
|
||||
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:
|
||||
free (M->phone);
|
||||
free (M->first_name);
|
||||
free (M->last_name);
|
||||
return;
|
||||
case CODE_message_media_unsupported:
|
||||
free (M->data);
|
||||
return;
|
||||
default:
|
||||
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:
|
||||
free (M->title);
|
||||
free (M->users);
|
||||
break;
|
||||
case CODE_message_action_chat_edit_title:
|
||||
free (M->new_title);
|
||||
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;
|
||||
default:
|
||||
assert (0);
|
||||
}
|
||||
}
|
||||
|
||||
void free_message (struct message *M) {
|
||||
if (!M->service) {
|
||||
if (M->message) { free (M->message); }
|
||||
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;
|
||||
}
|
||||
|
||||
struct message *fetch_alloc_message (void) {
|
||||
struct message *M = malloc (sizeof (*M));
|
||||
fetch_message (M);
|
||||
struct message *M1 = tree_lookup_message (message_tree, M);
|
||||
messages_allocated ++;
|
||||
if (M1) {
|
||||
message_del_use (M1);
|
||||
free_message (M1);
|
||||
memcpy (M1, M, sizeof (*M));
|
||||
free (M);
|
||||
message_add_use (M1);
|
||||
messages_allocated --;
|
||||
return M1;
|
||||
} else {
|
||||
message_add_use (M);
|
||||
message_tree = tree_insert_message (message_tree, M, lrand48 ());
|
||||
return M;
|
||||
}
|
||||
}
|
||||
|
||||
struct chat *fetch_alloc_chat (void) {
|
||||
union user_chat *U = malloc (sizeof (*U));
|
||||
fetch_chat (&U->chat);
|
||||
chats_allocated ++;
|
||||
union user_chat *U1 = tree_lookup_peer (peer_tree, U);
|
||||
if (U1) {
|
||||
free_chat (&U1->chat);
|
||||
*U1 = *U;
|
||||
free (U);
|
||||
chats_allocated --;
|
||||
return &U1->chat;
|
||||
} else {
|
||||
peer_tree = tree_insert_peer (peer_tree, U, lrand48 ());
|
||||
Peers[(chat_num ++) + user_num] = U;
|
||||
return &U->chat;
|
||||
}
|
||||
}
|
||||
|
||||
void free_chat (struct chat *U) {
|
||||
if (U->title) { free (U->title); }
|
||||
if (U->print_title) { free (U->print_title); }
|
||||
}
|
||||
|
||||
int print_stat (char *s, int len) {
|
||||
return snprintf (s, len,
|
||||
"user_num\t%d\n"
|
||||
"users_allocated\t%d\n",
|
||||
user_num,
|
||||
users_allocated);
|
||||
"users_allocated\t%d\n"
|
||||
"chats_allocated\t%d\n"
|
||||
"messages_allocated\t%d\n",
|
||||
users_allocated,
|
||||
chats_allocated,
|
||||
messages_allocated
|
||||
);
|
||||
}
|
||||
|
116
structures.h
116
structures.h
@ -17,33 +17,137 @@ struct user_status {
|
||||
struct user {
|
||||
int id;
|
||||
int flags;
|
||||
char *print_name;
|
||||
struct file_location photo_big;
|
||||
struct file_location photo_small;
|
||||
char *first_name;
|
||||
char *last_name;
|
||||
char *phone;
|
||||
char *print_name;
|
||||
long long access_hash;
|
||||
struct file_location photo_big;
|
||||
struct file_location photo_small;
|
||||
struct user_status status;
|
||||
};
|
||||
|
||||
struct chat {
|
||||
int id;
|
||||
int flags;
|
||||
char *title;
|
||||
char *print_title;
|
||||
struct file_location photo_big;
|
||||
struct file_location photo_small;
|
||||
char *title;
|
||||
int user_num;
|
||||
int date;
|
||||
int version;
|
||||
struct file_location photo_big;
|
||||
struct file_location photo_small;
|
||||
};
|
||||
|
||||
union user_chat {
|
||||
struct {
|
||||
int id;
|
||||
int flags;
|
||||
char *print_name;
|
||||
struct file_location photo_big;
|
||||
struct file_location photo_small;
|
||||
};
|
||||
struct user user;
|
||||
struct chat chat;
|
||||
};
|
||||
|
||||
struct photo_size {
|
||||
char *type;
|
||||
struct file_location loc;
|
||||
int w;
|
||||
int h;
|
||||
int size;
|
||||
char *data;
|
||||
};
|
||||
|
||||
struct geo {
|
||||
double longitude;
|
||||
double latitude;
|
||||
};
|
||||
|
||||
struct photo {
|
||||
long long id;
|
||||
long long access_hash;
|
||||
int user_id;
|
||||
int date;
|
||||
char *caption;
|
||||
struct geo geo;
|
||||
int sizes_num;
|
||||
struct photo_size *sizes;
|
||||
};
|
||||
|
||||
struct video {
|
||||
long long id;
|
||||
long long access_hash;
|
||||
int user_id;
|
||||
int date;
|
||||
char *caption;
|
||||
int duration;
|
||||
int size;
|
||||
struct photo_size thumb;
|
||||
int dc_id;
|
||||
int w;
|
||||
int h;
|
||||
};
|
||||
|
||||
struct message_action {
|
||||
int type;
|
||||
union {
|
||||
struct {
|
||||
char *title;
|
||||
int user_num;
|
||||
int *users;
|
||||
};
|
||||
char *new_title;
|
||||
struct photo photo;
|
||||
int user;
|
||||
};
|
||||
};
|
||||
|
||||
struct message_media {
|
||||
int type;
|
||||
union {
|
||||
struct photo photo;
|
||||
struct video video;
|
||||
struct geo geo;
|
||||
struct {
|
||||
char *phone;
|
||||
char *first_name;
|
||||
char *last_name;
|
||||
int user_id;
|
||||
};
|
||||
void *data;
|
||||
};
|
||||
};
|
||||
|
||||
struct message {
|
||||
struct message *next_use, *prev_use;
|
||||
int id;
|
||||
int flags;
|
||||
int fwd_from_id;
|
||||
int fwd_date;
|
||||
int from_id;
|
||||
int to_id;
|
||||
int out;
|
||||
int unread;
|
||||
int date;
|
||||
int service;
|
||||
union {
|
||||
struct message_action action;
|
||||
struct {
|
||||
char *message;
|
||||
struct message_media media;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
void fetch_file_location (struct file_location *loc);
|
||||
void fetch_user (struct user *U);
|
||||
struct user *fetch_alloc_user (void);
|
||||
struct chat *fetch_alloc_chat (void);
|
||||
|
||||
void free_user (struct user *U);
|
||||
void free_chat (struct chat *U);
|
||||
|
||||
int print_stat (char *s, int len);
|
||||
#endif
|
||||
|
@ -1,2 +1,3 @@
|
||||
#define MAX_DC_NUM 9
|
||||
#define MAX_USER_NUM 1000
|
||||
#define MAX_CHAT_NUM 1000
|
||||
|
9
tg.pub
Normal file
9
tg.pub
Normal file
@ -0,0 +1,9 @@
|
||||
-----BEGIN RSA PUBLIC KEY-----
|
||||
MIIBCgKCAQEAwVACPi9w23mF3tBkdZz+zwrzKOaaQdr01vAbU4E1pvkfj4sqDsm6
|
||||
lyDONS789sVoD/xCS9Y0hkkC3gtL1tSfTlgCMOOul9lcixlEKzwKENj1Yz/s7daS
|
||||
an9tqw3bfUV/nqgbhGX81v/+7RFAEd+RwFnK7a+XYl9sluzHRyVVaTTveB2GazTw
|
||||
Efzk2DWgkBluml8OREmvfraX3bkHZJTKX4EQSjBbbdJ2ZXIsRrYOXfaA+xayEGB+
|
||||
8hdlLmAjbCVfaigxX0CDqWeR1yFL9kwd9P0NsZRPsmoqVwMbMu7mStFai6aIhc3n
|
||||
Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB
|
||||
-----END RSA PUBLIC KEY-----
|
||||
|
Loading…
x
Reference in New Issue
Block a user