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.
This commit is contained in:
Kevin Easton
2015-10-28 21:46:38 +11:00
parent af3b0c920a
commit a2e8e103e0
5 changed files with 434 additions and 288 deletions

View File

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

View File

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

View File

@@ -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;
}

View File

@@ -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))
{
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;
set_display_target(NULL, LOG_DCC);
if (description)
{
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 = '_';
}
if (size && *size)
filesize = atol(size);
TempLong = strtoul(address, NULL, 10);
TempInt = (unsigned)strtoul(port, NULL, 10);
if (TempInt < 1024)
{
put_it("%s", convert_output_format("$G %RDCC%n Privileged port attempt [$0]", "%d", TempInt));
reset_display_target();
return;
}
else if (TempLong == 0 || TempInt == 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;
}
if (check_dcc_init(type, nick, uhost, description, size, extra, TempLong, TempInt))
return;
if (*type == 'T' && *(type+1))
{
tdcc = DCC_TDCC;
type++;
}
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_fullname()
* Return an allocated string with the full pathname to a DCC downloaded file.
*/
dcc_getfile_resume_demanded(nick, description, address, port);
return;
}
else if (!my_stricmp(type, "ACCEPT"))
static char *dcc_fullname(const char *filename)
{
/*
* See the comment above.
*/
dcc_getfile_resume_start (nick, description, address, port);
return;
char *fullname;
if (get_string_var(DCC_DLDIR_VAR))
{
char *tmp = m_sprintf("%s/%s", get_string_var(DCC_DLDIR_VAR), filename);
fullname = expand_twiddle(tmp);
new_free(&tmp);
}
#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;
fullname = m_strdup(filename);
}
return fullname;
}
if (tdcc) type--;
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)
*p_filesize = atol(size);
else
*p_filesize = 0;
if ((s = find_dcc(nick, description, NULL, Ctype, 0, -1, -1)))
*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", *p_port));
return 0;
}
if (*p_addr == 0)
{
struct in_addr in;
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;
}
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 (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"))
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, FromUserHost, "*", NULL);
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)
{
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(TempLong);
in.s_addr = htonl(offer_addr);
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));
update_clock(GET_TIME), dcc_name, description, nick, userhost,
inet_ntoa(in), offer_port, _GMKs(filesize), buf));
}
if (Ctype == DCC_CHAT)
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)
{
#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);
}
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,35 +1362,84 @@ 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)
{
char *tmp = NULL, *p;
malloc_sprintf(&tmp, "%s/%s", get_string_var(DCC_DLDIR_VAR), n->filename);
p = expand_twiddle(tmp);
FILE *fp = NULL;
char c[10];
char *tmp = NULL;
char buffer[BIG_BUFFER_SIZE];
if (!n->filesize)
put_it("%s", convert_output_format("$G %RDCC%n Warning: Offered file has zero size", NULL, NULL));
strlcpy(buffer, *new_file, sizeof buffer);
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)
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 (!dcc_overwrite_var && stat(p, &resume_sb) == 0)
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))
{
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 (!dcc_overwrite_var && stat(fullname, &resume_sb) == 0)
{
/* File already exists */
if (autoget)
@@ -1333,12 +1447,14 @@ void register_dcc_type(char *nick, char *type, char *description, char *address,
/* 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));
put_it("%s", convert_output_format("$G %RDCC%n Warning: File $0 exists: trying to autoresume", "%s", fullname));
autoresume = 1;
}
#endif
@@ -1352,80 +1468,36 @@ void register_dcc_type(char *nick, char *type, char *description, char *address,
{
#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));
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
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));
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));
}
}
}
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)
{
#ifndef BITCHX_LITE
case DCC_BOTMODE:
func = process_dcc_bot;
break;
#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;
}
}
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;
if (autoget && fullname)
{
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, ntohs(n->remport), resume_sb.st_size);
n->filename, n->remport, resume_sb.st_size);
}
else
if (autoget && fullname)
{
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 ((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, func)))
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
@@ -1433,11 +1505,112 @@ void register_dcc_type(char *nick, char *type, char *description, char *address,
}
}
if (Ctype == DCC_CHAT && autoget)
dcc_create(nick, n->filename, NULL, n->filesize, 0, Ctype, DCC_OFFER, func);
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)
{
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));
}
}
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;
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))

View File

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