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);