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:
+1
-1
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
+1
-1
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+388
-208
@@ -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);
|
||||
}
|
||||
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_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;
|
||||
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)
|
||||
*p_filesize = atol(size);
|
||||
else
|
||||
*p_filesize = 0;
|
||||
|
||||
*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;
|
||||
}
|
||||
|
||||
if (tdcc) type--;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((s = find_dcc(nick, description, NULL, Ctype, 0, -1, -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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
if (!n->filesize)
|
||||
put_it("%s", convert_output_format("$G %RDCC%n Warning: Offered file has zero size", NULL, NULL));
|
||||
fullname = dcc_fullname(n->filename);
|
||||
autoget = do_autoget(nick, n->filesize);
|
||||
|
||||
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(p, &resume_sb) == 0)
|
||||
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,92 +1468,149 @@ 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
|
||||
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);
|
||||
}
|
||||
|
||||
if (Ctype == DCC_CHAT && autoget)
|
||||
dcc_create(nick, n->filename, NULL, n->filesize, 0, Ctype, DCC_OFFER, func);
|
||||
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;
|
||||
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))
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user