From a2e8e103e007cfa7f463be95b7404c5946e04efd Mon Sep 17 00:00:00 2001 From: Kevin Easton Date: Wed, 28 Oct 2015 21:46:38 +1100 Subject: [PATCH] Modularise handling of DCC offers There's several different types of DCC offers, all of which need slightly different handling. Previously they were all handled by the monster function register_dcc_type() - this breaks them out into seperate functions for handling SEND, RESEND, CHAT and BOT offers, moves common code into static helper functions and renames the entry point from ctcp.c to handle_dcc_offer(). This will allow adding a way for modules to register DCC offer types that they're interested in. This also moves rename_file() from misc.c into dcc.c, where its only user is. --- include/dcc.h | 2 +- include/misc.h | 1 - source/ctcp.c | 2 +- source/dcc.c | 684 +++++++++++++++++++++++++++++++------------------ source/misc.c | 33 --- 5 files changed, 434 insertions(+), 288 deletions(-) diff --git a/include/dcc.h b/include/dcc.h index 7f097aa..20b4d74 100644 --- a/include/dcc.h +++ b/include/dcc.h @@ -128,7 +128,7 @@ void dcc_bot_transmit(char *, char *, char *); void dcc_raw_transmit(char *, char *, char *); - void register_dcc_type(char *, char *, char *, char *, char *, char *, char *, char *, void (*func)(int)); + void handle_dcc_offer(char *, char *, char *, char *, char *, char *, char *, char *); void dcc_reject(char *, char *, char *); char *dcc_raw_connect(char *, unsigned short); diff --git a/include/misc.h b/include/misc.h index dfdf625..55c5df9 100644 --- a/include/misc.h +++ b/include/misc.h @@ -81,7 +81,6 @@ extern LastMsg last_sent_ctcp[2]; char *BX_random_str (int, int); void check_auto_away (time_t); ChannelList * BX_prepare_command (int *, char *, int); - int rename_file (char *, char **); void putlog (int, ...); void add_mode_buffer ( char *, int); diff --git a/source/ctcp.c b/source/ctcp.c index eaec32d..e389a7e 100644 --- a/source/ctcp.c +++ b/source/ctcp.c @@ -749,7 +749,7 @@ CTCP_HANDLER(do_dcc) if (!size || !port || !inetaddr || !description) return NULL; #endif - register_dcc_type(from, type, description, inetaddr, port, size, extra_flags, FromUserHost, NULL); + handle_dcc_offer(from, type, description, inetaddr, port, size, extra_flags, FromUserHost); return NULL; } diff --git a/source/dcc.c b/source/dcc.c index 02ed9b5..6a0030e 100644 --- a/source/dcc.c +++ b/source/dcc.c @@ -179,7 +179,7 @@ int (*dcc_close_func) (int, sockaddr_foobar, int) = NULL; #define DCC_OUTPUT 3 #define DCC_CLOSE 4 -int check_dcc_init(char *type, char *nick, char *uhost, char *description, char *size, char *extra, unsigned long TempLong, unsigned int TempInt); +static int check_dcc_init(char *nick, char *type, char *description, char *address, char *port, char *size, char *extra, char *uhost); /* bind type, sock num, type, address, port, buffer, buflen , newline */ #ifndef O_BINARY @@ -531,7 +531,6 @@ DCC_List *new_i; s = &new_i->sock; new = (DCC_int *)s->info; - new->remport = ntohs(new->remport); if ((new_s = connect_by_number(inet_ntoa(new->remote), &new->remport, SERVICE_CLIENT, PROTOCOL_TCP, 0)) < 0 #ifdef HAVE_SSL || (flags & DCC_SSL ? SSL_dcc_create(s, new_s, 1) : 0) < 0 @@ -549,7 +548,6 @@ DCC_List *new_i; reset_display_target(); return NULL; } - new->remport = ntohs(new->remport); flags |= DCC_ACTIVE; add_socketread(new_s, new->remport, flags|type, nick, new_i->sock.func_read, NULL); set_socketinfo(new_s, new); @@ -1121,174 +1119,241 @@ int i; void process_dcc_send1(int s); void start_dcc_get(int s); -void register_dcc_type(char *nick, char *type, char *description, char *address, char *port, char *size, char *extra, char *uhost, void (*func1)(int)) +/* dcc_fullname() + * Return an allocated string with the full pathname to a DCC downloaded file. + */ +static char *dcc_fullname(const char *filename) { - int Ctype; - unsigned long filesize = 0; - SocketList *s; - DCC_int *n; - DCC_List *new_d = NULL; - unsigned long TempLong; - unsigned int TempInt; - void (*func)(int) = NULL; - int autoget = 0; - int autoresume = 0; - struct stat resume_sb; - unsigned long tdcc = 0; - char *fullname = NULL; - UserList *ul = NULL; + char *fullname; - set_display_target(NULL, LOG_DCC); - if (description) + if (get_string_var(DCC_DLDIR_VAR)) { - char *c; -#if defined(__EMX__) || defined(WINNT) - if ((c = strrchr(description, '/')) || (c = strrchr(description, '\\'))) -#else - if ((c = strrchr(description, '/'))) -#endif - description = c + 1; - if (description && *description == '.') - *description = '_'; + char *tmp = m_sprintf("%s/%s", get_string_var(DCC_DLDIR_VAR), filename); + fullname = expand_twiddle(tmp); + new_free(&tmp); } + else + { + fullname = m_strdup(filename); + } + return fullname; +} + +static int parse_offer_params(const char *address, const char *port, const char *size, + unsigned long *p_addr, unsigned int *p_port, unsigned long *p_filesize) +{ if (size && *size) - filesize = atol(size); + *p_filesize = atol(size); + else + *p_filesize = 0; - TempLong = strtoul(address, NULL, 10); - TempInt = (unsigned)strtoul(port, NULL, 10); - if (TempInt < 1024) + *p_addr = strtoul(address, NULL, 10); + *p_port = (unsigned)strtoul(port, NULL, 10); + if (*p_port < 1024) { - put_it("%s", convert_output_format("$G %RDCC%n Privileged port attempt [$0]", "%d", TempInt)); - reset_display_target(); - return; + put_it("%s", convert_output_format("$G %RDCC%n Privileged port attempt [$0]", "%d", *p_port)); + return 0; } - else if (TempLong == 0 || TempInt == 0) + if (*p_addr == 0) { struct in_addr in; - in.s_addr = htonl(TempLong); - put_it("%s", convert_output_format("$G %RDCC%n Handshake ignored because of 0 port or address [$0:$1]", "%d %s", TempInt, inet_ntoa(in))); - reset_display_target(); - return; + in.s_addr = htonl(*p_addr); + put_it("%s", convert_output_format("$G %RDCC%n Handshake ignored because of 0 port or address [$0:$1]", "%d %s", *p_port, inet_ntoa(in))); + return 0; } - if (check_dcc_init(type, nick, uhost, description, size, extra, TempLong, TempInt)) - return; - if (*type == 'T' && *(type+1)) - { - tdcc = DCC_TDCC; - type++; - } + return 1; +} +static int check_collision(char *nick, const char *description, int type) +{ + SocketList *s = find_dcc(nick, description, NULL, type, 0, -1, -1); - if (!my_stricmp(type, "CHAT")) - Ctype = DCC_CHAT; - else if (!my_stricmp(type, "BOT")) - Ctype = DCC_BOTMODE; - else if (!my_stricmp(type, "SEND")) - Ctype = DCC_FILEREAD; - else if (!my_stricmp(type, "RESEND")) - Ctype = DCC_REFILEREAD; -#ifdef MIRC_BROKEN_DCC_RESUME - else if (!my_stricmp(type, "RESUME")) - - { - /* - * Dont be deceieved by the arguments we're passing it. - * The arguments are "out of order" because MIRC doesnt - * send them in the traditional order. Ugh. Comments - * borrowed from epic. - */ - dcc_getfile_resume_demanded(nick, description, address, port); - return; - } - else if (!my_stricmp(type, "ACCEPT")) - { - /* - * See the comment above. - */ - dcc_getfile_resume_start (nick, description, address, port); - return; - } -#endif - else - { - put_it("%s", convert_output_format("$G %RDCC%n Unknown DCC $0 ($1) received from $2", "%s %s %s", type, description, nick)); - reset_display_target(); - return; - } - - if (tdcc) type--; - - if ((s = find_dcc(nick, description, NULL, Ctype, 0, -1, -1))) + if (s) { if ((s->flags & DCC_ACTIVE)) { /* collision. */ put_it("%s", convert_output_format("$G %RDCC%n Received DCC $0 request from $1 while previous session active", "%s %s", type, nick)); - reset_display_target(); - return; + return 0; } if ((s->flags & DCC_WAIT)) { - if (Ctype == DCC_CHAT) + if (type == DCC_CHAT) { - autoget = 1; - if (do_hook(DCC_CONNECT_LIST,"%s CHAT %s",nick, "already requested connecting")) + if (do_hook(DCC_CONNECT_LIST,"%s CHAT %s",nick, "already requested connecting")) put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_CONNECT_FSET), "%s %s %s %s %s %d", update_clock(GET_TIME), "CHAT", nick, space, "already requested connecting...", 0)); dcc_chat(NULL, nick); - return; + return 0; } send_ctcp(CTCP_NOTICE, nick, CTCP_DCC, "DCC %s collision occured while connecting to %s (%s)", type, nickname, description); erase_dcc_info(s->is_read, 1, "%s", convert_output_format("$G %RDCC%n $0 collision for $1:$2", "%s %s %s", type, nick, description)); close_socketread(s->is_read); - reset_display_target(); - return; + return 0; } } - if (do_hook(DCC_REQUEST_LIST,"%s %s %s %lu",nick, dcc_types[Ctype]->name, description, filesize)) + + return 1; +} + +static DCC_int *create_dcc_int(const char *nick, const char *description, + const char *userhost, unsigned long address, unsigned short port, + unsigned long filesize, int server) +{ + UserList *ul = NULL; + DCC_int *n = new_malloc(sizeof *n); + +#ifdef WANT_USERLIST + ul = lookup_userlevelc(nick, userhost, "*", NULL); +#endif + + if (userhost) + n->userhost = m_strdup(userhost); + n->ul = ul; + n->remport = port; + n->remote.s_addr = htonl(address); + n->filesize = filesize; + n->filename = m_strdup(description); + n->user = m_strdup(nick); + n->blocksize = get_int_var(DCC_BLOCK_SIZE_VAR); + n->server = server; + n->file = -1; /* just in case */ + n->struct_type = DCC_STRUCT_TYPE; + + return n; +} + +static DCC_List *add_dcc_pending(DCC_int *dcc, int flags, void (*func_read)(int)) +{ + DCC_List *new_d = new_malloc(sizeof *new_d); + + new_d->sock.info = dcc; + new_d->sock.server = new_d->nick = m_strdup(dcc->user); + new_d->sock.port = dcc->remport; + new_d->sock.flags = flags; + new_d->sock.time = now + dcc_timeout; + new_d->sock.func_read = func_read; /* point this to the startup function */ + new_d->next = pending_dcc; + pending_dcc = new_d; + + return new_d; +} + +/* show_dcc_offer() + * Wrapper to show the user using the default format a non-file (eg. CHAT) DCC offer. + */ +static void show_dcc_offer(const char *nick, const char *dcc_name, + const char *description, const char *userhost, unsigned long offer_addr, + unsigned int offer_port) +{ + if (!dcc_quiet) { -#ifdef WANT_USERLIST - ul = lookup_userlevelc(nick, FromUserHost, "*", NULL); -#endif - if (!dcc_quiet) + struct in_addr in; + in.s_addr = htonl(offer_addr); + put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_REQUEST_FSET), + "%s %s %s %s %s %s %d", + update_clock(GET_TIME), dcc_name, description, nick, userhost, + inet_ntoa(in), offer_port)); + } + + if (beep_on_level & LOG_DCC) + beep_em(1); +} + +/* show_dcc_fileoffer() + * Wrapper to show the user using the default format a file (eg. SEND) DCC offer. + */ +static void show_dcc_fileoffer(const char *nick, const char *dcc_name, + const char *description, const char *userhost, unsigned long offer_addr, + unsigned int offer_port, unsigned long filesize) +{ + if (!dcc_quiet) + { + struct in_addr in; + char buf[40]; + in.s_addr = htonl(offer_addr); + sprintf(buf, "%2.4g",_GMKv(filesize)); + put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_REQUEST_FSET), + "%s %s \"%s\" %s %s %s %d %s %s", + update_clock(GET_TIME), dcc_name, description, nick, userhost, + inet_ntoa(in), offer_port, _GMKs(filesize), buf)); + } + + if (!filesize) + put_it("%s", convert_output_format("$G %RDCC%n Warning: Offered file has zero size", NULL, NULL)); + + if (beep_on_level & LOG_DCC) + beep_em(1); +} + +static void dcc_chat_offer(char *nick, char *type, char *description, + char *address, char *port, char *size, char *extra, char *userhost, + int server) +{ + int Ctype = DCC_CHAT; + unsigned long filesize; + unsigned long TempLong; + unsigned int TempInt; + DCC_int *n; + int autoget = 0; + + if (!parse_offer_params(address, port, size, &TempLong, &TempInt, &filesize)) + return; + + if (!check_collision(nick, description, Ctype)) + return; + + n = create_dcc_int(nick, description, userhost, TempLong, TempInt, filesize, server); + + if (do_hook(DCC_REQUEST_LIST, "%s %s %s 0", nick, dcc_types[Ctype]->name, description)) + { + show_dcc_offer(nick, dcc_types[Ctype]->name, description, userhost, TempLong, TempInt); + + if (get_int_var(BOT_MODE_VAR) && n->ul) { - struct in_addr in; - char buf[40]; - in.s_addr = htonl(TempLong); - sprintf(buf, "%2.4g",_GMKv(filesize)); - if (filesize) - put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_REQUEST_FSET), - "%s %s \"%s\" %s %s %s %d %s %s", - update_clock(GET_TIME),dcc_types[Ctype]->name, description, - nick, FromUserHost, - inet_ntoa(in), TempInt, - _GMKs(filesize), buf)); - else - put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_REQUEST_FSET), - "%s %s %s %s %s %s %d", - update_clock(GET_TIME),dcc_types[Ctype]->name, - description, nick, FromUserHost, - inet_ntoa(in), TempInt)); + autoget = 1; } - if (Ctype == DCC_CHAT) + else { -#ifdef WANT_USERLIST - if (get_int_var(BOT_MODE_VAR) && ul) - autoget = 1; - else -#endif - { - extern char *last_chat_req; - bitchsay("Type /chat to answer or /nochat to close"); - malloc_strcpy(&last_chat_req, nick); - } - if (beep_on_level & LOG_DCC) - beep_em(1); + extern char *last_chat_req; + bitchsay("Type /chat to answer or /nochat to close"); + malloc_strcpy(&last_chat_req, nick); } + } + + n->dccnum = ++dcc_count; + add_dcc_pending(n, Ctype|DCC_OFFER, process_dcc_chat); + + if (autoget) + dcc_create(nick, n->filename, NULL, n->filesize, 0, Ctype, DCC_OFFER, process_dcc_chat); +} + +#ifndef BITCHX_LITE +static void dcc_bot_offer(char *nick, char *type, char *description, + char *address, char *port, char *size, char *extra, char *userhost, + int server) +{ + int Ctype = DCC_BOTMODE; + unsigned long filesize; + unsigned long TempLong; + unsigned int TempInt; + DCC_int *n; + + if (!parse_offer_params(address, port, size, &TempLong, &TempInt, &filesize)) + return; + + if (!check_collision(nick, description, Ctype)) + return; + + n = create_dcc_int(nick, description, userhost, TempLong, TempInt, filesize, server); + + if (do_hook(DCC_REQUEST_LIST, "%s %s %s 0", nick, dcc_types[Ctype]->name, description)) + { + show_dcc_offer(nick, dcc_types[Ctype]->name, description, userhost, TempLong, TempInt); #if 0 - if ((Ctype == DCC_BOTMODE) && (p = get_string_var(BOT_PASSWORD_VAR))) + if (p = get_string_var(BOT_PASSWORD_VAR)) { if (encrypt && !strcmp(p, encrypt)) ;/* do it */ @@ -1297,147 +1362,255 @@ void register_dcc_type(char *nick, char *type, char *description, char *address, } #endif } - n = new_malloc(sizeof(DCC_int)); - if (uhost) - n->userhost = m_strdup(uhost); - n->ul = ul; - n->remport = htons(TempInt); - n->remote.s_addr = htonl(TempLong); - n->filesize = filesize; - n->filename = m_strdup(description); - n->user = m_strdup(nick); - n->blocksize = get_int_var(DCC_BLOCK_SIZE_VAR); - n->server = from_server; - n->file = -1; /* just in case */ - n->struct_type = DCC_STRUCT_TYPE; - - if ((Ctype == DCC_FILEREAD) || (Ctype == DCC_REFILEREAD)) + + n->dccnum = ++dcc_count; + add_dcc_pending(n, Ctype|DCC_OFFER, process_dcc_bot); +} +#endif + +static int rename_file(char **new_file) +{ + FILE *fp = NULL; + char c[10]; + char *tmp = NULL; + char buffer[BIG_BUFFER_SIZE]; + + strlcpy(buffer, *new_file, sizeof buffer); + + do { + if (fp != NULL) + fclose(fp); + sprintf(c, "%03i.", getrandom(0, 999)); + tmp = dcc_fullname(c); + malloc_strcat(&tmp, buffer); + fp = fopen(tmp, "r"); + new_free(&tmp); + } while (fp != NULL); + + malloc_sprintf(new_file, "%s%s", c, buffer); + return 0; +} + +/* Logic to determine whether or not to autoget a file offer */ +static int do_autoget(const char *nick, unsigned long filesize) +{ + if (!get_int_var(DCC_AUTOGET_VAR) && + !find_name_in_genericlist(nick, dcc_no_flood, DCC_HASHSIZE, 0)) + return 0; + if (filesize/1024 > get_int_var(DCC_MAX_AUTOGET_SIZE_VAR)) + return 0; + if (!filesize) + return 0; + return 1; +} + +static void dcc_send_offer(char *nick, char *type, char *description, + char *address, char *port, char *size, char *extra, char *userhost, + int server) +{ + int Ctype = DCC_FILEREAD; + unsigned long filesize; + unsigned long TempLong; + unsigned int TempInt; + unsigned long tdcc = 0; + DCC_int *n; + DCC_List *new_d; + int autoget = 0; + int autoresume = 0; + struct stat resume_sb; + char *fullname = NULL; + + if (!parse_offer_params(address, port, size, &TempLong, &TempInt, &filesize)) + return; + + if (*type == 'T') + tdcc = DCC_TDCC; + + if (!check_collision(nick, description, Ctype)) + return; + + n = create_dcc_int(nick, description, userhost, TempLong, TempInt, filesize, server); + + if (do_hook(DCC_REQUEST_LIST,"%s %s %s %lu", nick, dcc_types[Ctype]->name, description, filesize)) { - char *tmp = NULL, *p; - malloc_sprintf(&tmp, "%s/%s", get_string_var(DCC_DLDIR_VAR), n->filename); - p = expand_twiddle(tmp); + show_dcc_fileoffer(nick, dcc_types[Ctype]->name, description, userhost, TempLong, TempInt, filesize); + } + + fullname = dcc_fullname(n->filename); + autoget = do_autoget(nick, n->filesize); - if (!n->filesize) - put_it("%s", convert_output_format("$G %RDCC%n Warning: Offered file has zero size", NULL, NULL)); - - if ((get_int_var(DCC_AUTOGET_VAR) || find_name_in_genericlist(nick, dcc_no_flood, DCC_HASHSIZE, 0)) && - (n->filesize/1024 < get_int_var(DCC_MAX_AUTOGET_SIZE_VAR)) && n->filesize) - autoget = 1; - if (Ctype == DCC_FILEREAD) + if (!dcc_overwrite_var && stat(fullname, &resume_sb) == 0) + { + /* File already exists */ + if (autoget) { - if (!dcc_overwrite_var && stat(p, &resume_sb) == 0) + /* autoget of an existing file: either rename it, resume it, or punt */ + if (get_int_var(DCC_AUTORENAME_VAR)) { - /* File already exists */ - if (autoget) - { - /* autoget of an existing file: either rename it, resume it, or punt */ - if (get_int_var(DCC_AUTORENAME_VAR)) - { - rename_file(p, &n->filename); - } + rename_file(&n->filename); + new_free(&fullname); + fullname = dcc_fullname(n->filename); + } #ifdef MIRC_BROKEN_DCC_RESUME - else if (resume_sb.st_size < n->filesize && get_int_var(DCC_AUTORESUME_VAR)) - { - put_it("%s", convert_output_format("$G %RDCC%n Warning: File $0 exists: trying to autoresume", "%s", p)); - autoresume = 1; - } + else if (resume_sb.st_size < n->filesize && get_int_var(DCC_AUTORESUME_VAR)) + { + put_it("%s", convert_output_format("$G %RDCC%n Warning: File $0 exists: trying to autoresume", "%s", fullname)); + autoresume = 1; + } #endif - else - { - autoget = 0; - } - } - - if (!autoget) - { -#ifdef MIRC_BROKEN_DCC_RESUME - if (resume_sb.st_size < n->filesize) - put_it("%s", convert_output_format("$G %RDCC%n Warning: File $0 exists: use /DCC RENAME or /DCC RESUME if you don't want to overwrite", "%s", p)); - else -#endif - put_it("%s", convert_output_format("$G %RDCC%n Warning: File $0 exists: use /DCC RENAME if you don't want to overwrite", "%s", p)); - } + else + { + autoget = 0; } } - malloc_sprintf(&tmp, "%s/%s", get_string_var(DCC_DLDIR_VAR), n->filename); - fullname = expand_twiddle(tmp); - new_free(&tmp); new_free(&p); - } - if (!func) - { - switch (Ctype) + if (!autoget) { -#ifndef BITCHX_LITE - case DCC_BOTMODE: - func = process_dcc_bot; - break; +#ifdef MIRC_BROKEN_DCC_RESUME + if (resume_sb.st_size < n->filesize) + put_it("%s", convert_output_format("$G %RDCC%n Warning: File $0 exists: use /DCC RENAME or /DCC RESUME if you don't want to overwrite", "%s", fullname)); + else #endif - case DCC_CHAT: - func = process_dcc_chat; - break; - case DCC_REFILEREAD: - case DCC_FILEREAD: - func = start_dcc_get; - break; - case DCC_FILEOFFER: - case DCC_REFILEOFFER: - func = process_dcc_send1; - break; - default: - yell("Unsupported dcc type [%s]", type); - return; + put_it("%s", convert_output_format("$G %RDCC%n Warning: File $0 exists: use /DCC RENAME if you don't want to overwrite", "%s", fullname)); } } - else - func = func1; + n->dccnum = ++dcc_count; - new_d = new_malloc(sizeof(DCC_List)); - new_d->sock.info = n; - new_d->sock.server = new_d->nick = m_strdup(nick); - new_d->sock.port = TempInt; - new_d->sock.flags = Ctype|DCC_OFFER|tdcc; - new_d->sock.time = now + dcc_timeout; - new_d->sock.func_read = func; /* point this to the startup function */ - new_d->next = pending_dcc; - pending_dcc = new_d; + new_d = add_dcc_pending(n, Ctype|DCC_OFFER|tdcc, start_dcc_get); + + if (autoresume) + { + n->transfer_orders.byteoffset = resume_sb.st_size; + n->bytes_read = 0L; + new_d->sock.flags |= DCC_RESUME_REQ; + send_ctcp(CTCP_PRIVMSG, nick, CTCP_DCC, "RESUME %s %d %ld", + n->filename, n->remport, resume_sb.st_size); + } if (autoget && fullname) { - if (autoresume) + DCC_int *new = NULL; + if (!dcc_quiet) { - n->transfer_orders.byteoffset = resume_sb.st_size; - n->bytes_read = 0L; - new_d->sock.flags |= DCC_RESUME_REQ; - send_ctcp(CTCP_PRIVMSG, nick, CTCP_DCC, "RESUME %s %d %ld", - n->filename, ntohs(n->remport), resume_sb.st_size); + put_it("%s", + convert_output_format("$G %RDCC%n Auto-accepting $0 of file %C$2-%n from %K[%C$1%K]", + "%s%s %s %s", tdcc ? "T" : "", dcc_types[Ctype]->name, nick, n->filename)); + } + if ((n->file = open(fullname, O_WRONLY | O_CREAT | O_BINARY, 0644)) > 0) + { + if ((new = dcc_create(nick, n->filename, NULL, n->filesize, 0, Ctype, DCC_OFFER|tdcc, start_dcc_get))) + new->blocksize = get_int_var(DCC_BLOCK_SIZE_VAR); } else + put_it("%s", convert_output_format("$G %RDCC%n Unable to open $0-", "%s", fullname)); + } +} + +static void dcc_resend_offer(char *nick, char *type, char *description, + char *address, char *port, char *size, char *extra, char *userhost, + int server) +{ + int Ctype = DCC_REFILEREAD; + unsigned long filesize; + unsigned long TempLong; + unsigned int TempInt; + unsigned long tdcc = 0; + DCC_int *n; + int autoget = 0; + char *fullname = NULL; + + if (!parse_offer_params(address, port, size, &TempLong, &TempInt, &filesize)) + return; + + if (*type == 'T') + tdcc = DCC_TDCC; + + if (!check_collision(nick, description, Ctype)) + return; + + n = create_dcc_int(nick, description, userhost, TempLong, TempInt, filesize, server); + + if (do_hook(DCC_REQUEST_LIST,"%s %s %s %lu", nick, dcc_types[Ctype]->name, description, filesize)) + { + show_dcc_fileoffer(nick, dcc_types[Ctype]->name, description, userhost, TempLong, TempInt, filesize); + } + + fullname = dcc_fullname(n->filename); + autoget = do_autoget(nick, n->filesize); + + n->dccnum = ++dcc_count; + add_dcc_pending(n, Ctype|DCC_OFFER|tdcc, start_dcc_get); + + if (autoget && fullname) + { + DCC_int *new = NULL; + if (!dcc_quiet) { - DCC_int *new = NULL; - int mode = O_WRONLY | O_CREAT | O_BINARY; - if (!dcc_quiet) - { - put_it("%s", - convert_output_format("$G %RDCC%n Auto-accepting $0 of file %C$2-%n from %K[%C$1%K]", - "%s%s %s %s", tdcc ? "T" : "", dcc_types[Ctype]->name, nick, n->filename)); - } - if (Ctype == DCC_REFILEREAD) - mode |= O_APPEND; - if ((n->file = open(fullname, mode, 0644)) > 0) - { - if ((new = dcc_create(nick, n->filename, NULL, n->filesize, 0, Ctype, DCC_OFFER|tdcc, func))) - new->blocksize = get_int_var(DCC_BLOCK_SIZE_VAR); - } - else - put_it("%s", convert_output_format("$G %RDCC%n Unable to open $0-", "%s", fullname)); + put_it("%s", + convert_output_format("$G %RDCC%n Auto-accepting $0 of file %C$2-%n from %K[%C$1%K]", + "%s%s %s %s", tdcc ? "T" : "", dcc_types[Ctype]->name, nick, n->filename)); } + if ((n->file = open(fullname, O_WRONLY | O_CREAT | O_BINARY | O_APPEND, 0644)) > 0) + { + if ((new = dcc_create(nick, n->filename, NULL, n->filesize, 0, Ctype, DCC_OFFER|tdcc, start_dcc_get))) + new->blocksize = get_int_var(DCC_BLOCK_SIZE_VAR); + } + else + put_it("%s", convert_output_format("$G %RDCC%n Unable to open $0-", "%s", fullname)); } - if (Ctype == DCC_CHAT && autoget) - dcc_create(nick, n->filename, NULL, n->filesize, 0, Ctype, DCC_OFFER, func); +} + +void handle_dcc_offer(char *nick, char *type, char *description, + char *address, char *port, char *size, char *extra, char *userhost) +{ + set_display_target(NULL, LOG_DCC); + + if (description) + { + char *c; +#if defined(__EMX__) || defined(WINNT) + if ((c = strrchr(description, '\\')) + description = c + 1; +#endif + if ((c = strrchr(description, '/'))) + description = c + 1; + if (description && *description == '.') + *description = '_'; + } + + if (check_dcc_init(nick, type, description, address, port, size, extra, userhost)) + { + reset_display_target(); + return; + } + + if (!my_stricmp(type, "CHAT")) + dcc_chat_offer(nick, type, description, address, port, size, extra, userhost, from_server); +#ifndef BITCHX_LITE + else if (!my_stricmp(type, "BOT")) + dcc_bot_offer(nick, type, description, address, port, size, extra, userhost, from_server); +#endif + else if (!my_stricmp(type, "SEND") || !my_stricmp(type, "TSEND")) + dcc_send_offer(nick, type, description, address, port, size, extra, userhost, from_server); + else if (!my_stricmp(type, "RESEND") || !my_stricmp(type, "TRESEND")) + dcc_resend_offer(nick, type, description, address, port, size, extra, userhost, from_server); +#ifdef MIRC_BROKEN_DCC_RESUME + else if (!my_stricmp(type, "RESUME")) + + /* + * Dont be deceieved by the arguments we're passing it. + * The arguments are "out of order" because MIRC doesnt + * send them in the traditional order. Ugh. Comments + * borrowed from epic. + */ + dcc_getfile_resume_demanded(nick, description, address, port); + else if (!my_stricmp(type, "ACCEPT")) + dcc_getfile_resume_start (nick, description, address, port); +#endif + else + put_it("%s", convert_output_format("$G %RDCC%n Unknown DCC $0 ($1) received from $2", "%s %s %s", type, description, nick)); reset_display_target(); - new_free(&fullname); } void process_dcc(char *args) @@ -3556,7 +3729,7 @@ int blocksize = 0; old_dp = doing_privmsg; old_dn = doing_notice; old_dc = in_ctcp_flag; /* Just in case we have to fool the protocol enforcement. */ doing_privmsg = doing_notice = in_ctcp_flag = 0; - send_ctcp(CTCP_PRIVMSG, nick, CTCP_DCC, "RESUME %s %d %ld", n->filename, ntohs(n->remport), sb.st_size); + send_ctcp(CTCP_PRIVMSG, nick, CTCP_DCC, "RESUME %s %d %ld", n->filename, n->remport, sb.st_size); doing_privmsg = old_dp; doing_notice = old_dn; in_ctcp_flag = old_dc; } @@ -4102,7 +4275,7 @@ SocketList *s; add_socketread(snum, port, DCC_WAIT|DCC_FTPOPEN, host, start_ftp, NULL); new = new_malloc(sizeof(DCC_int)); new->struct_type = DCC_STRUCT_TYPE; - new->remport = htons(port); + new->remport = port; new->blocksize = blocksize; get_time(&new->starttime); get_time(&new->lasttime); @@ -4147,9 +4320,16 @@ char *nick, } } -int check_dcc_init(char *type, char *nick, char *uhost, char *description, char *size, char *extra, unsigned long TempLong, unsigned int TempInt) +static int check_dcc_init(char *nick, char *type, char *description, char *address, char *port, char *size, char *extra, char *uhost) { -int i; + int i; + unsigned long filesize; + unsigned long TempLong; + unsigned int TempInt; + + if (!parse_offer_params(address, port, size, &TempLong, &TempInt, &filesize)) + return 0; + for (i = 0; dcc_types[i]->name; i++) { if (!my_stricmp(type, dcc_types[i]->name)) diff --git a/source/misc.c b/source/misc.c index fc3864f..68519c5 100644 --- a/source/misc.c +++ b/source/misc.c @@ -1243,39 +1243,6 @@ FILE *f; #endif } -int rename_file(char *old_file, char **new_file) -{ - FILE *fp; - char *c, *tmp = NULL; - char buffer[BIG_BUFFER_SIZE]; - - c = alloca(10); - sprintf(c, "%03i.", getrandom(0, 999)); - if (get_string_var(DCC_DLDIR_VAR)) - malloc_sprintf(&tmp, "%s/%s", get_string_var(DCC_DLDIR_VAR), c); - else - malloc_sprintf(&tmp, "%s", c); - - malloc_strcat(&tmp, *new_file); - strlcpy(buffer, *new_file, sizeof buffer); - while ((fp = fopen(tmp, "r")) != NULL) - { - fclose(fp); - sprintf(c, "%03i.", getrandom(0, 999)); - if (get_string_var(DCC_DLDIR_VAR)) - malloc_sprintf(&tmp, "%s/%s", get_string_var(DCC_DLDIR_VAR), c); - else - malloc_sprintf(&tmp, "%s", c); - malloc_strcat(&tmp, buffer); - } - if (fp != NULL) - fclose(fp); - malloc_sprintf(new_file, "%s", c); - malloc_strcat(new_file, buffer); - new_free(&tmp); - return 0; -} - int isme(char *nick) { return ((my_stricmp(nick, get_server_nickname(from_server)) == 0) ? 1 : 0);