Added libconfig to parse config. Something fixed in net
This commit is contained in:
parent
a064540223
commit
c04a0f5d6a
2
Makefile
2
Makefile
@ -1,6 +1,6 @@
|
|||||||
CC=cc
|
CC=cc
|
||||||
CFLAGS=-c -Wall -Wextra -Werror -fPIC -ggdb -O2 -fno-omit-frame-pointer -fno-strict-aliasing -rdynamic
|
CFLAGS=-c -Wall -Wextra -Werror -fPIC -ggdb -O2 -fno-omit-frame-pointer -fno-strict-aliasing -rdynamic
|
||||||
LDFLAGS=-lreadline -lssl -lcrypto -lrt -lz -ggdb -rdynamic
|
LDFLAGS=-lreadline -lssl -lcrypto -lrt -lz -lconfig -ggdb -rdynamic
|
||||||
LD=cc
|
LD=cc
|
||||||
|
|
||||||
SRC=main.c loop.c interface.c net.c mtproto-common.c mtproto-client.c queries.c structures.c
|
SRC=main.c loop.c interface.c net.c mtproto-common.c mtproto-client.c queries.c structures.c
|
||||||
|
3
loop.c
3
loop.c
@ -43,6 +43,7 @@
|
|||||||
|
|
||||||
extern char *default_username;
|
extern char *default_username;
|
||||||
extern char *auth_token;
|
extern char *auth_token;
|
||||||
|
extern int test_dc;
|
||||||
void set_default_username (const char *s);
|
void set_default_username (const char *s);
|
||||||
int default_dc_num;
|
int default_dc_num;
|
||||||
|
|
||||||
@ -188,7 +189,7 @@ void read_dc (int auth_file_fd, int id, unsigned ver) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void empty_auth_file (void) {
|
void empty_auth_file (void) {
|
||||||
struct dc *DC = alloc_dc (1, strdup (TG_SERVER), 443);
|
struct dc *DC = alloc_dc (1, strdup (test_dc ? TG_SERVER_TEST : TG_SERVER), 443);
|
||||||
assert (DC);
|
assert (DC);
|
||||||
dc_working_num = 1;
|
dc_working_num = 1;
|
||||||
auth_state = 0;
|
auth_state = 0;
|
||||||
|
187
main.c
187
main.c
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
Copyright Vitaly Valtman 2013
|
Copyright Vitaly Valtman 2013
|
||||||
*/
|
*/
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@ -31,6 +32,7 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <execinfo.h>
|
#include <execinfo.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <libconfig.h>
|
||||||
|
|
||||||
#include "loop.h"
|
#include "loop.h"
|
||||||
#include "mtproto-client.h"
|
#include "mtproto-client.h"
|
||||||
@ -38,12 +40,12 @@
|
|||||||
#define PROGNAME "telegram-client"
|
#define PROGNAME "telegram-client"
|
||||||
#define VERSION "0.01"
|
#define VERSION "0.01"
|
||||||
|
|
||||||
#define CONFIG_DIRECTORY ".telegram/"
|
#define CONFIG_DIRECTORY ".telegram"
|
||||||
#define CONFIG_FILE CONFIG_DIRECTORY "config"
|
#define CONFIG_FILE "config"
|
||||||
#define AUTH_KEY_FILE CONFIG_DIRECTORY "auth"
|
#define AUTH_KEY_FILE "auth"
|
||||||
#define STATE_FILE CONFIG_DIRECTORY "state"
|
#define STATE_FILE "state"
|
||||||
#define SECRET_CHAT_FILE CONFIG_DIRECTORY "secret"
|
#define SECRET_CHAT_FILE "secret"
|
||||||
#define DOWNLOADS_DIRECTORY "downloads/"
|
#define DOWNLOADS_DIRECTORY "downloads"
|
||||||
|
|
||||||
#define CONFIG_DIRECTORY_MODE 0700
|
#define CONFIG_DIRECTORY_MODE 0700
|
||||||
|
|
||||||
@ -52,9 +54,16 @@
|
|||||||
"# Feel free to put something here\n"
|
"# Feel free to put something here\n"
|
||||||
|
|
||||||
char *default_username;
|
char *default_username;
|
||||||
int setup_mode;
|
|
||||||
char *auth_token;
|
char *auth_token;
|
||||||
int msg_num_mode;
|
int msg_num_mode;
|
||||||
|
char *config_filename;
|
||||||
|
char *prefix;
|
||||||
|
int test_dc;
|
||||||
|
char *auth_file_name;
|
||||||
|
char *state_file_name;
|
||||||
|
char *secret_chat_file_name;
|
||||||
|
char *downloads_directory;
|
||||||
|
char *config_directory;
|
||||||
|
|
||||||
void set_default_username (const char *s) {
|
void set_default_username (const char *s) {
|
||||||
if (default_username) {
|
if (default_username) {
|
||||||
@ -63,11 +72,6 @@ void set_default_username (const char *s) {
|
|||||||
default_username = strdup (s);
|
default_username = strdup (s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_setup_mode (void) {
|
|
||||||
setup_mode = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* {{{ TERMINAL */
|
/* {{{ TERMINAL */
|
||||||
tcflag_t old_lflag;
|
tcflag_t old_lflag;
|
||||||
cc_t old_vtime;
|
cc_t old_vtime;
|
||||||
@ -100,7 +104,7 @@ char *get_home_directory (void) {
|
|||||||
return current_passwd->pw_dir;
|
return current_passwd->pw_dir;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
char *get_config_directory (void) {
|
char *get_config_directory (void) {
|
||||||
@ -115,63 +119,47 @@ char *get_config_directory (void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
char *get_config_filename (void) {
|
char *get_config_filename (void) {
|
||||||
char *config_filename;
|
|
||||||
int length = strlen (get_home_directory ()) + strlen (CONFIG_FILE) + 2;
|
|
||||||
|
|
||||||
config_filename = (char *) calloc (length, sizeof (char));
|
|
||||||
sprintf (config_filename, "%s/" CONFIG_FILE, get_home_directory ());
|
|
||||||
return config_filename;
|
return config_filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *get_auth_key_filename (void) {
|
char *get_auth_key_filename (void) {
|
||||||
char *auth_key_filename;
|
return auth_file_name;
|
||||||
int length = strlen (get_home_directory ()) + strlen (AUTH_KEY_FILE) + 2;
|
|
||||||
|
|
||||||
auth_key_filename = (char *) calloc (length, sizeof (char));
|
|
||||||
sprintf (auth_key_filename, "%s/" AUTH_KEY_FILE, get_home_directory ());
|
|
||||||
return auth_key_filename;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char *get_state_filename (void) {
|
char *get_state_filename (void) {
|
||||||
char *state_filename;
|
return state_file_name;
|
||||||
int length = strlen (get_home_directory ()) + strlen (STATE_FILE) + 2;
|
|
||||||
|
|
||||||
state_filename = (char *) calloc (length, sizeof (char));
|
|
||||||
sprintf (state_filename, "%s/" STATE_FILE, get_home_directory ());
|
|
||||||
return state_filename;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char *get_secret_chat_filename (void) {
|
char *get_secret_chat_filename (void) {
|
||||||
char *secret_chat_filename;
|
return secret_chat_file_name;
|
||||||
int length = strlen (get_home_directory ()) + strlen (SECRET_CHAT_FILE) + 2;
|
|
||||||
|
|
||||||
secret_chat_filename = (char *) calloc (length, sizeof (char));
|
|
||||||
sprintf (secret_chat_filename, "%s/" SECRET_CHAT_FILE, get_home_directory ());
|
|
||||||
return secret_chat_filename;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char *get_downloads_directory (void)
|
char *get_downloads_directory (void) {
|
||||||
{
|
|
||||||
char *downloads_directory;
|
|
||||||
int length = strlen (get_config_directory ()) + strlen (DOWNLOADS_DIRECTORY) + 2;
|
|
||||||
|
|
||||||
downloads_directory = (char *) calloc (length, sizeof (char));
|
|
||||||
sprintf (downloads_directory, "%s/" DOWNLOADS_DIRECTORY, get_config_directory ());
|
|
||||||
|
|
||||||
return downloads_directory;
|
return downloads_directory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *make_full_path (char *s) {
|
||||||
|
if (*s != '/') {
|
||||||
|
char *t = s;
|
||||||
|
assert (asprintf (&s, "%s/%s", get_home_directory (), s) >= 0);
|
||||||
|
free (t);
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
void running_for_first_time (void) {
|
void running_for_first_time (void) {
|
||||||
|
if (config_filename) {
|
||||||
|
return; // Do not create custom config file
|
||||||
|
}
|
||||||
|
assert (asprintf (&config_filename, "%s/%s/%s", get_home_directory (), CONFIG_DIRECTORY, CONFIG_FILE) >= 0);
|
||||||
|
config_filename = make_full_path (config_filename);
|
||||||
|
|
||||||
struct stat *config_file_stat = NULL;
|
struct stat *config_file_stat = NULL;
|
||||||
int config_file_fd;
|
int config_file_fd;
|
||||||
char *config_directory = get_config_directory ();
|
char *config_directory = get_config_directory ();
|
||||||
char *config_filename = get_config_filename ();
|
//char *downloads_directory = get_downloads_directory ();
|
||||||
char *downloads_directory = get_downloads_directory ();
|
|
||||||
|
|
||||||
if (mkdir (config_directory, CONFIG_DIRECTORY_MODE) != 0) {
|
if (!mkdir (config_directory, CONFIG_DIRECTORY_MODE)) {
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
printf ("\nRunning " PROGNAME " for first time!!\n");
|
|
||||||
printf ("[%s] created\n", config_directory);
|
printf ("[%s] created\n", config_directory);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,21 +180,92 @@ void running_for_first_time (void) {
|
|||||||
exit (EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
close (config_file_fd);
|
close (config_file_fd);
|
||||||
int auth_file_fd = open (get_auth_key_filename (), O_CREAT | O_RDWR, 0600);
|
/*int auth_file_fd = open (get_auth_key_filename (), O_CREAT | O_RDWR, 0600);
|
||||||
int x = -1;
|
int x = -1;
|
||||||
assert (write (auth_file_fd, &x, 4) == 4);
|
assert (write (auth_file_fd, &x, 4) == 4);
|
||||||
close (auth_file_fd);
|
close (auth_file_fd);
|
||||||
|
|
||||||
printf ("[%s] created\n", config_filename);
|
printf ("[%s] created\n", config_filename);*/
|
||||||
|
|
||||||
/* create downloads directory */
|
/* create downloads directory */
|
||||||
if (mkdir (downloads_directory, 0755) !=0) {
|
/*if (mkdir (downloads_directory, 0755) !=0) {
|
||||||
perror ("creating download directory");
|
perror ("creating download directory");
|
||||||
exit (EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
|
}*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
set_setup_mode ();
|
void parse_config_val (config_t *conf, char **s, char *param_name, const char *default_name, const char *path) {
|
||||||
|
static char buf[1000];
|
||||||
|
int l = 0;
|
||||||
|
if (prefix) {
|
||||||
|
l = strlen (prefix);
|
||||||
|
memcpy (buf, prefix, l);
|
||||||
|
buf[l ++] = '.';
|
||||||
|
}
|
||||||
|
*s = 0;
|
||||||
|
const char *r = 0;
|
||||||
|
strcpy (buf + l, param_name);
|
||||||
|
config_lookup_string (conf, buf, &r);
|
||||||
|
if (r) {
|
||||||
|
if (path) {
|
||||||
|
assert (asprintf (s, "%s/%s", path, r) >= 0);
|
||||||
|
} else {
|
||||||
|
*s = strdup (r);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (path) {
|
||||||
|
assert (asprintf (s, "%s/%s", path, default_name) >= 0);
|
||||||
|
} else {
|
||||||
|
*s = strdup (default_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void parse_config (void) {
|
||||||
|
config_filename = make_full_path (config_filename);
|
||||||
|
|
||||||
|
config_t conf;
|
||||||
|
config_init (&conf);
|
||||||
|
if (config_read_file (&conf, config_filename) != CONFIG_TRUE) {
|
||||||
|
fprintf (stderr, "Can not read config '%s': error '%s' on the line %d\n", config_filename, config_error_text (&conf), config_error_line (&conf));
|
||||||
|
exit (2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!prefix) {
|
||||||
|
config_lookup_string (&conf, "default_profile", (void *)&prefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char buf[1000];
|
||||||
|
int l = 0;
|
||||||
|
if (prefix) {
|
||||||
|
l = strlen (prefix);
|
||||||
|
memcpy (buf, prefix, l);
|
||||||
|
buf[l ++] = '.';
|
||||||
|
}
|
||||||
|
test_dc = 0;
|
||||||
|
strcpy (buf + l, "test");
|
||||||
|
config_lookup_bool (&conf, buf, &test_dc);
|
||||||
|
|
||||||
|
if (!msg_num_mode) {
|
||||||
|
strcpy (buf + l, "msg_num");
|
||||||
|
config_lookup_bool (&conf, buf, &msg_num_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_config_val (&conf, &config_directory, "config_directory", CONFIG_DIRECTORY, 0);
|
||||||
|
config_directory = make_full_path (config_directory);
|
||||||
|
|
||||||
|
parse_config_val (&conf, &auth_file_name, "auth_file", AUTH_KEY_FILE, config_directory);
|
||||||
|
parse_config_val (&conf, &state_file_name, "state_file", STATE_FILE, config_directory);
|
||||||
|
parse_config_val (&conf, &secret_chat_file_name, "secret", SECRET_CHAT_FILE, config_directory);
|
||||||
|
parse_config_val (&conf, &downloads_directory, "downloads", DOWNLOADS_DIRECTORY, config_directory);
|
||||||
|
|
||||||
|
if (!mkdir (config_directory, CONFIG_DIRECTORY_MODE)) {
|
||||||
|
printf ("[%s] created\n", config_directory);
|
||||||
|
}
|
||||||
|
if (!mkdir (downloads_directory, CONFIG_DIRECTORY_MODE)) {
|
||||||
|
printf ("[%s] created\n", downloads_directory);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void inner_main (void) {
|
void inner_main (void) {
|
||||||
@ -214,7 +273,7 @@ void inner_main (void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void usage (void) {
|
void usage (void) {
|
||||||
printf ("%s [-u username] [-h] [-k public key name]\n", PROGNAME);
|
printf ("%s [-u username] [-h] [-k public key name] [-N] [-v]\n", PROGNAME);
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,7 +283,7 @@ extern int default_dc_num;
|
|||||||
|
|
||||||
void args_parse (int argc, char **argv) {
|
void args_parse (int argc, char **argv) {
|
||||||
int opt = 0;
|
int opt = 0;
|
||||||
while ((opt = getopt (argc, argv, "u:hk:vn:N")) != -1) {
|
while ((opt = getopt (argc, argv, "u:hk:vn:Nc:p:")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'u':
|
case 'u':
|
||||||
set_default_username (optarg);
|
set_default_username (optarg);
|
||||||
@ -235,12 +294,16 @@ void args_parse (int argc, char **argv) {
|
|||||||
case 'v':
|
case 'v':
|
||||||
verbosity ++;
|
verbosity ++;
|
||||||
break;
|
break;
|
||||||
case 'n':
|
|
||||||
default_dc_num = atoi (optarg);
|
|
||||||
break;
|
|
||||||
case 'N':
|
case 'N':
|
||||||
msg_num_mode ++;
|
msg_num_mode ++;
|
||||||
break;
|
break;
|
||||||
|
case 'c':
|
||||||
|
config_filename = strdup (optarg);
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
prefix = strdup (optarg);
|
||||||
|
assert (strlen (prefix) <= 100);
|
||||||
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
default:
|
default:
|
||||||
usage ();
|
usage ();
|
||||||
@ -266,18 +329,20 @@ void sig_handler (int signum) {
|
|||||||
int main (int argc, char **argv) {
|
int main (int argc, char **argv) {
|
||||||
signal (SIGSEGV, sig_handler);
|
signal (SIGSEGV, sig_handler);
|
||||||
signal (SIGABRT, sig_handler);
|
signal (SIGABRT, sig_handler);
|
||||||
running_for_first_time ();
|
|
||||||
|
|
||||||
|
args_parse (argc, argv);
|
||||||
printf (
|
printf (
|
||||||
"Telegram-client version " TG_VERSION ", Copyright (C) 2013 Vitaly Valtman\n"
|
"Telegram-client version " TG_VERSION ", Copyright (C) 2013 Vitaly Valtman\n"
|
||||||
"Telegram-client comes with ABSOLUTELY NO WARRANTY; for details type `show_license'.\n"
|
"Telegram-client comes with ABSOLUTELY NO WARRANTY; for details type `show_license'.\n"
|
||||||
"This is free software, and you are welcome to redistribute it\n"
|
"This is free software, and you are welcome to redistribute it\n"
|
||||||
"under certain conditions; type `show_license' for details.\n"
|
"under certain conditions; type `show_license' for details.\n"
|
||||||
);
|
);
|
||||||
|
running_for_first_time ();
|
||||||
|
parse_config ();
|
||||||
|
|
||||||
|
|
||||||
get_terminal_attributes ();
|
get_terminal_attributes ();
|
||||||
|
|
||||||
args_parse (argc, argv);
|
|
||||||
|
|
||||||
inner_main ();
|
inner_main ();
|
||||||
|
|
||||||
|
@ -1361,8 +1361,9 @@ int process_rpc_message (struct connection *c UU, struct encrypted_message *enc,
|
|||||||
double st = get_server_time (DC);
|
double st = get_server_time (DC);
|
||||||
assert (this_server_time >= st - 300 && this_server_time <= st + 30);
|
assert (this_server_time >= st - 300 && this_server_time <= st + 30);
|
||||||
//assert (enc->msg_id > server_last_msg_id && (enc->msg_id & 3) == 1);
|
//assert (enc->msg_id > server_last_msg_id && (enc->msg_id & 3) == 1);
|
||||||
if (verbosity >= 2) {
|
if (verbosity >= 1) {
|
||||||
logprintf ( "received mesage id %016llx\n", enc->msg_id);
|
logprintf ( "received mesage id %016llx\n", enc->msg_id);
|
||||||
|
hexdump_in ();
|
||||||
}
|
}
|
||||||
server_last_msg_id = enc->msg_id;
|
server_last_msg_id = enc->msg_id;
|
||||||
|
|
||||||
@ -1390,10 +1391,10 @@ int rpc_execute (struct connection *c, int op, int len) {
|
|||||||
if (verbosity) {
|
if (verbosity) {
|
||||||
logprintf ( "outbound rpc connection #%d : received rpc answer %d with %d content bytes\n", c->fd, op, len);
|
logprintf ( "outbound rpc connection #%d : received rpc answer %d with %d content bytes\n", c->fd, op, len);
|
||||||
}
|
}
|
||||||
if (op < 0) {
|
/* if (op < 0) {
|
||||||
assert (read_in (c, Response, Response_len) == Response_len);
|
assert (read_in (c, Response, Response_len) == Response_len);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
if (len >= MAX_RESPONSE_SIZE/* - 12*/ || len < 0/*12*/) {
|
if (len >= MAX_RESPONSE_SIZE/* - 12*/ || len < 0/*12*/) {
|
||||||
logprintf ( "answer too long (%d bytes), skipping\n", len);
|
logprintf ( "answer too long (%d bytes), skipping\n", len);
|
||||||
|
5
net.c
5
net.c
@ -146,7 +146,7 @@ int read_in (struct connection *c, void *data, int len) {
|
|||||||
int x = 0;
|
int x = 0;
|
||||||
while (len) {
|
while (len) {
|
||||||
int y = c->in_head->wptr - c->in_head->rptr;
|
int y = c->in_head->wptr - c->in_head->rptr;
|
||||||
if (y >= len) {
|
if (y > len) {
|
||||||
memcpy (data, c->in_head->rptr, len);
|
memcpy (data, c->in_head->rptr, len);
|
||||||
c->in_head->rptr += len;
|
c->in_head->rptr += len;
|
||||||
c->in_bytes -= len;
|
c->in_bytes -= len;
|
||||||
@ -185,6 +185,7 @@ int read_in_lookup (struct connection *c, void *data, int len) {
|
|||||||
memcpy (data, b->rptr, y);
|
memcpy (data, b->rptr, y);
|
||||||
x += y;
|
x += y;
|
||||||
data += y;
|
data += y;
|
||||||
|
len -= y;
|
||||||
b = b->next;
|
b = b->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -405,7 +406,7 @@ void hexdump_buf (struct connection_buffer *b) {
|
|||||||
|
|
||||||
void try_rpc_read (struct connection *c) {
|
void try_rpc_read (struct connection *c) {
|
||||||
assert (c->in_head);
|
assert (c->in_head);
|
||||||
if (verbosity >= 4) {
|
if (verbosity >= 1) {
|
||||||
hexdump_buf (c->in_head);
|
hexdump_buf (c->in_head);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
net.h
2
net.h
@ -23,7 +23,7 @@
|
|||||||
struct dc;
|
struct dc;
|
||||||
#include "queries.h"
|
#include "queries.h"
|
||||||
#define TG_SERVER "173.240.5.1"
|
#define TG_SERVER "173.240.5.1"
|
||||||
//#define TG_SERVER "95.142.192.66"
|
#define TG_SERVER_TEST "173.240.5.253"
|
||||||
#define TG_APP_HASH "36722c72256a24c1225de00eb6a1ca74"
|
#define TG_APP_HASH "36722c72256a24c1225de00eb6a1ca74"
|
||||||
#define TG_APP_ID 2899
|
#define TG_APP_ID 2899
|
||||||
#define TG_BUILD "203"
|
#define TG_BUILD "203"
|
||||||
|
56
queries.c
56
queries.c
@ -1159,6 +1159,9 @@ int send_file_on_answer (struct query *q UU) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int send_encr_file_on_answer (struct query *q UU) {
|
int send_encr_file_on_answer (struct query *q UU) {
|
||||||
|
if (prefetch_int () != (int)CODE_messages_sent_encrypted_file) {
|
||||||
|
hexdump_in ();
|
||||||
|
}
|
||||||
assert (fetch_int () == (int)CODE_messages_sent_encrypted_file);
|
assert (fetch_int () == (int)CODE_messages_sent_encrypted_file);
|
||||||
struct message *M = q->extra;
|
struct message *M = q->extra;
|
||||||
M->date = fetch_int ();
|
M->date = fetch_int ();
|
||||||
@ -1649,40 +1652,9 @@ void load_next_part (struct download *D);
|
|||||||
int download_on_answer (struct query *q) {
|
int download_on_answer (struct query *q) {
|
||||||
assert (fetch_int () == (int)CODE_upload_file);
|
assert (fetch_int () == (int)CODE_upload_file);
|
||||||
unsigned x = fetch_int ();
|
unsigned x = fetch_int ();
|
||||||
|
assert (x);
|
||||||
struct download *D = q->extra;
|
struct download *D = q->extra;
|
||||||
if (D->fd == -1) {
|
if (D->fd == -1) {
|
||||||
static char buf[100];
|
|
||||||
sprintf (buf, "%s/tmp_%ld_%ld", get_downloads_directory (), lrand48 (), lrand48 ());
|
|
||||||
int l = strlen (buf);
|
|
||||||
switch (x) {
|
|
||||||
case CODE_storage_file_unknown:
|
|
||||||
break;
|
|
||||||
case CODE_storage_file_jpeg:
|
|
||||||
sprintf (buf + l, "%s", ".jpg");
|
|
||||||
break;
|
|
||||||
case CODE_storage_file_gif:
|
|
||||||
sprintf (buf + l, "%s", ".gif");
|
|
||||||
break;
|
|
||||||
case CODE_storage_file_png:
|
|
||||||
sprintf (buf + l, "%s", ".png");
|
|
||||||
break;
|
|
||||||
case CODE_storage_file_mp3:
|
|
||||||
sprintf (buf + l, "%s", ".mp3");
|
|
||||||
break;
|
|
||||||
case CODE_storage_file_mov:
|
|
||||||
sprintf (buf + l, "%s", ".mov");
|
|
||||||
break;
|
|
||||||
case CODE_storage_file_partial:
|
|
||||||
sprintf (buf + l, "%s", ".part");
|
|
||||||
break;
|
|
||||||
case CODE_storage_file_mp4:
|
|
||||||
sprintf (buf + l, "%s", ".mp4");
|
|
||||||
break;
|
|
||||||
case CODE_storage_file_webp:
|
|
||||||
sprintf (buf + l, "%s", ".webp");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
D->name = strdup (buf);
|
|
||||||
D->fd = open (D->name, O_CREAT | O_WRONLY, 0640);
|
D->fd = open (D->name, O_CREAT | O_WRONLY, 0640);
|
||||||
}
|
}
|
||||||
fetch_int (); // mtime
|
fetch_int (); // mtime
|
||||||
@ -1719,7 +1691,27 @@ struct query_methods download_methods = {
|
|||||||
|
|
||||||
void load_next_part (struct download *D) {
|
void load_next_part (struct download *D) {
|
||||||
if (!D->offset) {
|
if (!D->offset) {
|
||||||
|
static char buf[1000];
|
||||||
|
if (!D->id) {
|
||||||
|
sprintf (buf, "%s/download_%lld_%d", get_downloads_directory (), D->volume, D->local_id);
|
||||||
|
} else {
|
||||||
|
sprintf (buf, "%s/download_%lld", get_downloads_directory (), D->id);
|
||||||
|
}
|
||||||
|
D->name = strdup (buf);
|
||||||
|
struct stat st;
|
||||||
|
if (stat (buf, &st) >= 0) {
|
||||||
|
D->offset = st.st_size;
|
||||||
|
if (D->offset >= D->size) {
|
||||||
cur_downloading_bytes += D->size;
|
cur_downloading_bytes += D->size;
|
||||||
|
cur_downloaded_bytes += D->offset;
|
||||||
|
rprintf ("Already downloaded\n");
|
||||||
|
end_load (D);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cur_downloading_bytes += D->size;
|
||||||
|
cur_downloaded_bytes += D->offset;
|
||||||
update_prompt ();
|
update_prompt ();
|
||||||
}
|
}
|
||||||
clear_packet ();
|
clear_packet ();
|
||||||
|
Loading…
Reference in New Issue
Block a user