diff options
Diffstat (limited to 'src/irc')
-rw-r--r-- | src/irc/dcc/dcc-files.c | 67 | ||||
-rw-r--r-- | src/irc/dcc/dcc.c | 38 | ||||
-rw-r--r-- | src/irc/dcc/dcc.h | 3 |
3 files changed, 74 insertions, 34 deletions
diff --git a/src/irc/dcc/dcc-files.c b/src/irc/dcc/dcc-files.c index 04e393d7..37bec340 100644 --- a/src/irc/dcc/dcc-files.c +++ b/src/irc/dcc/dcc-files.c @@ -297,10 +297,14 @@ static void dcc_ctcp_msg(IRC_SERVER_REC *server, const char *data, return; } - if (lseek(dcc->fhandle, size, SEEK_SET) != size) { + if (lseek(dcc->fhandle, 0, SEEK_END) == size) { + /* whole file sent */ + dcc->starttime = time(NULL); + dcc_reject(dcc, server); + } + else if (lseek(dcc->fhandle, size, SEEK_SET) != size) { /* error, or trying to seek after end of file */ - signal_emit("dcc closed", 1, dcc); - dcc_destroy(dcc); + dcc_reject(dcc, server); } else { dcc->transfd = dcc->skipped = size; @@ -319,20 +323,26 @@ static void dcc_resume_rec(DCC_REC *dcc) g_return_if_fail(dcc != NULL); - dcc->get_type = DCC_GET_RESUME; dcc->file = dcc_get_download_path(dcc->arg); - dcc->fhandle = open(dcc->file, O_WRONLY, dcc_file_create_mode); if (dcc->fhandle == -1) { signal_emit("dcc error file not found", 2, dcc, dcc->file); - dcc_destroy(dcc); return; } + dcc->get_type = DCC_GET_RESUME; + dcc->transfd = lseek(dcc->fhandle, 0, SEEK_END); if (dcc->transfd < 0) dcc->transfd = 0; dcc->skipped = dcc->transfd; + if (dcc->skipped == dcc->size) { + /* already received whole file */ + dcc->starttime = time(NULL); + dcc_reject(dcc, NULL); + return; + } + str = g_strdup_printf("DCC RESUME %s %d %lu", dcc->arg, dcc->port, dcc->transfd); dcc_ctcp_message(dcc->server, dcc->nick, dcc->chat, FALSE, str); @@ -343,7 +353,7 @@ static void dcc_resume_rec(DCC_REC *dcc) static void cmd_dcc_resume(const char *data) { DCC_REC *dcc; - GSList *tmp; + GSList *tmp, *next; char *nick, *fname; void *free_arg; int found; @@ -355,9 +365,10 @@ static void cmd_dcc_resume(const char *data) if (*nick == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); dcc = NULL; found = FALSE; - for (tmp = dcc_conns; tmp != NULL; tmp = tmp->next) { + for (tmp = dcc_conns; tmp != NULL; tmp = next) { dcc = tmp->data; + next = tmp->next; if (dcc_is_unget(dcc) && g_strcasecmp(dcc->nick, nick) == 0 && (*fname == '\0' || strcmp(dcc->arg, fname) == 0)) { dcc_resume_rec(dcc); @@ -589,6 +600,44 @@ static void cmd_dcc_send(const char *data, IRC_SERVER_REC *server, void *item) cmd_params_free(free_arg); } +static void sig_dcc_request(DCC_REC *dcc, const char *nickaddr) +{ + struct stat statbuf; + const char *masks; + char *str, *file; + int max_size; + + g_return_if_fail(dcc != NULL); + if (dcc->type != DCC_TYPE_GET) return; + + /* check if we want to autoget file offer */ + if (!settings_get_bool("dcc_autoget") && + !settings_get_bool("dcc_autoresume")) + return; + + /* check that autoget masks match */ + masks = settings_get_str("dcc_autoget_masks"); + if (*masks != '\0' && + !masks_match(SERVER(dcc->server), masks, dcc->nick, nickaddr)) + return; + + /* check file size limit, FIXME: it's still possible to send a + bogus file size and then just send what ever sized file.. */ + max_size = settings_get_int("dcc_max_autoget_size"); + if (max_size > 0 && max_size*1024 < dcc->size) + return; + + /* ok. but do we want/need to resume? */ + file = dcc_get_download_path(dcc->arg); + str = g_strdup_printf(settings_get_bool("dcc_autoresume") && + stat(file, &statbuf) == 0 ? + "RESUME %s %s" : "GET %s %s", + dcc->nick, dcc->arg); + signal_emit("command dcc", 2, str, dcc->server); + g_free(file); + g_free(str); +} + static void read_settings(void) { dcc_file_create_mode = octal2dec(settings_get_int("dcc_file_create_mode")); @@ -598,6 +647,7 @@ void dcc_files_init(void) { signal_add("ctcp msg dcc", (SIGNAL_FUNC) dcc_ctcp_msg); signal_add("setup changed", (SIGNAL_FUNC) read_settings); + signal_add_last("dcc request", (SIGNAL_FUNC) sig_dcc_request); signal_add("irssi init finished", (SIGNAL_FUNC) read_settings); command_bind("dcc send", NULL, (SIGNAL_FUNC) cmd_dcc_send); command_bind("dcc get", NULL, (SIGNAL_FUNC) cmd_dcc_get); @@ -608,6 +658,7 @@ void dcc_files_deinit(void) { signal_remove("ctcp msg dcc", (SIGNAL_FUNC) dcc_ctcp_msg); signal_remove("setup changed", (SIGNAL_FUNC) read_settings); + signal_remove("dcc request", (SIGNAL_FUNC) sig_dcc_request); signal_remove("irssi init finished", (SIGNAL_FUNC) read_settings); command_unbind("dcc send", (SIGNAL_FUNC) cmd_dcc_send); command_unbind("dcc get", (SIGNAL_FUNC) cmd_dcc_get); diff --git a/src/irc/dcc/dcc.c b/src/irc/dcc/dcc.c index de8601d5..1d0fc2dc 100644 --- a/src/irc/dcc/dcc.c +++ b/src/irc/dcc/dcc.c @@ -287,7 +287,7 @@ static void dcc_ctcp_msg(IRC_SERVER_REC *server, char *data, { char *type, *arg, *addrstr, *portstr, *sizestr, *str; void *free_arg; - const char *cstr; + const char *masks; DCC_REC *dcc, *olddcc; long size; int dcctype, port; @@ -331,39 +331,23 @@ static void dcc_ctcp_msg(IRC_SERVER_REC *server, char *data, switch (dcc->type) { case DCC_TYPE_GET: - cstr = settings_get_str("dcc_autoget_masks"); - /* check that autoget masks match */ - if (settings_get_bool("dcc_autoget") && (*cstr == '\0' || masks_match(SERVER(server), cstr, sender, sendaddr)) && - /* check file size limit, FIXME: it's possible to send a bogus file size and then just send what ever sized file.. */ - (settings_get_int("dcc_max_autoget_size") <= 0 || (settings_get_int("dcc_max_autoget_size") > 0 && size <= settings_get_int("dcc_max_autoget_size")*1024))) - { - /* automatically get */ - str = g_strdup_printf("GET %s %s", dcc->nick, dcc->arg); - signal_emit("command dcc", 2, str, server); - g_free(str); - } - else - { - /* send request */ - signal_emit("dcc request", 1, dcc); - } + /* send request */ + signal_emit("dcc request", 2, dcc, sendaddr); break; case DCC_TYPE_CHAT: - cstr = settings_get_str("dcc_autochat_masks"); + /* send request */ + signal_emit("dcc request", 2, dcc, sendaddr); + + masks = settings_get_str("dcc_autochat_masks"); if (olddcc != NULL || - (*cstr != '\0' && masks_match(SERVER(server), cstr, sender, sendaddr))) + (*masks != '\0' && masks_match(SERVER(server), masks, sender, sendaddr))) { /* automatically accept chat */ str = g_strdup_printf("CHAT %s", dcc->nick); signal_emit("command dcc", 2, str, server); g_free(str); } - else - { - /* send request */ - signal_emit("dcc request", 1, dcc); - } break; case DCC_TYPE_RESUME: @@ -416,7 +400,8 @@ static void dcc_ctcp_reply(IRC_SERVER_REC *server, char *data, cmd_params_free(free_arg); } -static void dcc_reject(DCC_REC *dcc, IRC_SERVER_REC *server) +/* reject DCC request */ +void dcc_reject(DCC_REC *dcc, IRC_SERVER_REC *server) { char *str; @@ -438,7 +423,7 @@ static void dcc_reject(DCC_REC *dcc, IRC_SERVER_REC *server) } /* SYNTAX: DCC CLOSE <type> <nick> [<file>] */ -static void cmd_dcc_close(IRC_SERVER_REC *server, char *data) +static void cmd_dcc_close(char *data, IRC_SERVER_REC *server) { DCC_REC *dcc; GSList *tmp, *next; @@ -540,6 +525,7 @@ void irc_dcc_init(void) settings_add_bool("dcc", "dcc_autorename", FALSE); settings_add_bool("dcc", "dcc_autoget", FALSE); + settings_add_bool("dcc", "dcc_autoresume", FALSE); settings_add_int("dcc", "dcc_max_autoget_size", 1000); settings_add_str("dcc", "dcc_download_path", "~"); settings_add_int("dcc", "dcc_file_create_mode", 644); diff --git a/src/irc/dcc/dcc.h b/src/irc/dcc/dcc.h index 8aef0c82..686f65a5 100644 --- a/src/irc/dcc/dcc.h +++ b/src/irc/dcc/dcc.h @@ -94,4 +94,7 @@ void dcc_chat_send(DCC_REC *dcc, const char *data); /* If `item' is a query of a =nick, return DCC chat record of nick */ DCC_REC *item_get_dcc(void *item); +/* reject DCC request */ +void dcc_reject(DCC_REC *dcc, IRC_SERVER_REC *server); + #endif |