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.
4599 lines
121 KiB
C
4599 lines
121 KiB
C
|
||
/*
|
||
* dcc.c: Things dealing with client to client connections.
|
||
*
|
||
* Copyright(c) 1998 Colten Edwards aka panasync.
|
||
* After alot of unhappiness with the old dcc.c code I took it upon myself
|
||
* to rewrite this code. The only parts not greatly changed by myself was
|
||
* code I had written by me in the first place. ie the ftp code and the
|
||
* dcc botlink code. Some great improvements in dcc speed were realized
|
||
* using non-blocking connects. All the previous dcc modes/commands are still
|
||
* in place and available.
|
||
*/
|
||
|
||
#include "irc.h"
|
||
static char cvsrevision[] = "$Id$";
|
||
CVS_REVISION(dcc_c)
|
||
#include "struct.h"
|
||
|
||
#include <sys/stat.h>
|
||
#include <stdarg.h>
|
||
#include <stdio.h>
|
||
#include <dirent.h>
|
||
#include <sys/ioctl.h>
|
||
|
||
#ifdef HAVE_SYS_FILIO_H
|
||
#include <sys/filio.h>
|
||
#endif
|
||
|
||
#if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX) && !defined(__EMX__)
|
||
# define IO_ARRAYLEN sysconf(_SC_OPEN_MAX)
|
||
#else
|
||
# ifdef FD_SETSIZE
|
||
# define IO_ARRAYLEN FD_SETSIZE
|
||
# else
|
||
# define IO_ARRAYLEN NFDBITS
|
||
# endif
|
||
#endif
|
||
|
||
#include "ctcp.h"
|
||
#include "encrypt.h"
|
||
#include "cdcc.h"
|
||
#include "dcc.h"
|
||
#include "hook.h"
|
||
#include "ircaux.h"
|
||
#include "lastlog.h"
|
||
#include "list.h"
|
||
#include "newio.h"
|
||
#include "output.h"
|
||
#include "parse.h"
|
||
#include "server.h"
|
||
#include "status.h"
|
||
#include "vars.h"
|
||
#include "who.h"
|
||
#include "window.h"
|
||
#include "screen.h"
|
||
#include "ircterm.h"
|
||
#include "hook.h"
|
||
#include "misc.h"
|
||
#include "tcl_bx.h"
|
||
#include "userlist.h"
|
||
#include "hash2.h"
|
||
#include "gui.h"
|
||
#define MAIN_SOURCE
|
||
#include "modval.h"
|
||
|
||
#include <float.h>
|
||
|
||
#ifdef WINNT
|
||
#include <windows.h>
|
||
#endif
|
||
|
||
extern int use_socks;
|
||
|
||
#define DCC_HASHSIZE 11
|
||
HashEntry dcc_no_flood[DCC_HASHSIZE];
|
||
|
||
struct _dcc_types_
|
||
{
|
||
char *name;
|
||
char *module;
|
||
int type;
|
||
int (*init_func)();
|
||
int (*open_func)();
|
||
int (*input)();
|
||
int (*output)();
|
||
int (*close_func)();
|
||
|
||
} _dcc_types[] =
|
||
{
|
||
{"<none>", NULL, 0, NULL, NULL, NULL, NULL, NULL},
|
||
{"CHAT", NULL, DCC_CHAT, NULL, NULL, NULL, NULL, NULL},
|
||
{"SEND", NULL, DCC_FILEOFFER, NULL, NULL, NULL, NULL, NULL},
|
||
{"GET", NULL, DCC_FILEREAD, NULL, NULL, NULL, NULL, NULL},
|
||
{"RAW_LISTEN", NULL, DCC_RAW_LISTEN, NULL, NULL, NULL, NULL, NULL},
|
||
{"RAW", NULL, DCC_RAW, NULL, NULL, NULL, NULL, NULL},
|
||
{"RESEND", NULL, DCC_REFILEOFFER, NULL, NULL, NULL, NULL, NULL},
|
||
{"REGET", NULL, DCC_REFILEREAD, NULL, NULL, NULL, NULL, NULL},
|
||
{"BOT", NULL, DCC_BOTMODE, NULL, NULL, NULL, NULL, NULL},
|
||
{"FTP", NULL, DCC_FTPOPEN, NULL, NULL, NULL, NULL, NULL},
|
||
{"FTPGET", NULL, DCC_FTPGET, NULL, NULL, NULL, NULL, NULL},
|
||
{"FTPSEND", NULL, DCC_FTPSEND, NULL, NULL, NULL, NULL, NULL},
|
||
{NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL}
|
||
};
|
||
|
||
struct _dcc_types_ **dcc_types = NULL;
|
||
|
||
static char DCC_current_transfer_buffer[BIG_BUFFER_SIZE/4];
|
||
unsigned int send_count_stat = 0;
|
||
unsigned int get_count_stat = 0;
|
||
char *last_chat_req = NULL;
|
||
static int dcc_quiet = 0;
|
||
static int dcc_paths = 0;
|
||
static int dcc_overwrite_var = 0;
|
||
double dcc_bytes_in = 0;
|
||
double dcc_bytes_out = 0;
|
||
double dcc_max_rate_in = 0.0;
|
||
static double dcc_min_rate_in = DBL_MAX;
|
||
double dcc_max_rate_out = 0.0;
|
||
static double dcc_min_rate_out = DBL_MAX;
|
||
|
||
time_t dcc_timeout = 600; /* global /set dcc_timeout */
|
||
|
||
static int dcc_count = 0;
|
||
|
||
|
||
|
||
|
||
/* new dcc handler */
|
||
#include "irc.h"
|
||
#include "ircaux.h"
|
||
#include "struct.h"
|
||
#include "misc.h"
|
||
|
||
extern Server *server_list;
|
||
|
||
typedef struct _DCC_List
|
||
{
|
||
struct _DCC_List *next;
|
||
char *nick; /* do NOT free this. it's a shared pointer. */
|
||
SocketList sock;
|
||
} DCC_List;
|
||
|
||
static DCC_List *pending_dcc = NULL;
|
||
|
||
|
||
static void process_dcc_chat(int);
|
||
#ifndef BITCHX_LITE
|
||
static void process_dcc_bot(int);
|
||
#endif
|
||
static void
|
||
start_dcc_chat(int);
|
||
static unsigned char byte_order_test (void);
|
||
static void dcc_update_stats(int);
|
||
|
||
static void update_transfer();
|
||
|
||
static char *strip_path(char *);
|
||
static void dcc_getfile_resume_demanded(char *, char *, char *, char *);
|
||
static void dcc_getfile_resume_start (char *, char *, char *, char *);
|
||
static void output_reject_ctcp (UserhostItem *, char *, char *);
|
||
|
||
extern int use_nat_address;
|
||
extern struct in_addr nat_address;
|
||
|
||
#if 0
|
||
/* sock num, type, address, port */
|
||
int (*dcc_open_func) (int, int, struct sockaddr_foobar, int) = NULL;
|
||
/* type, sock num, buffer, buff_len */
|
||
int (*dcc_output_func) (int, int, char *, int) = NULL;
|
||
/* sock num, type, buffer, new line, len buffer */
|
||
int (*dcc_input_func) (int, int, char *, int, int) = NULL;
|
||
/* socket num, address, port */
|
||
int (*dcc_close_func) (int, sockaddr_foobar, int) = NULL;
|
||
#endif
|
||
|
||
|
||
#define DCC_OPEN 1
|
||
#define DCC_INPUT 2
|
||
#define DCC_OUTPUT 3
|
||
#define DCC_CLOSE 4
|
||
|
||
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
|
||
#define O_BINARY 0
|
||
#endif
|
||
|
||
#define BAR_LENGTH 60
|
||
|
||
typedef struct
|
||
{
|
||
char * name;
|
||
dcc_function function;
|
||
char * help;
|
||
} DCC_commands;
|
||
|
||
DCC_dllcommands *dcc_dllcommands = NULL;
|
||
|
||
|
||
void dcc_chat(char *command, char *args);
|
||
void BX_dcc_filesend(char *command, char *args);
|
||
void BX_dcc_resend(char *command, char *args);
|
||
void dcc_getfile(char *command, char *args);
|
||
void dcc_regetfile(char *command, char *args);
|
||
void dcc_glist(char *command, char *args);
|
||
void dcc_resume(char *command, char *args);
|
||
void dcc_rename(char *command, char *args);
|
||
|
||
void dcc_show_active(char *command, char *args);
|
||
void dcc_set_quiet(char *command, char *args);
|
||
void dcc_set_paths(char *command, char *args);
|
||
void dcc_tog_rename(char *command, char *args);
|
||
void dcc_tog_resume(char *command, char *args);
|
||
void dcc_overwrite_toggle(char *command, char *args);
|
||
void dcc_tog_auto(char *command, char *args);
|
||
void dcc_stats(char *command, char *args);
|
||
void dcc_close(char *command, char *args);
|
||
void dcc_closeall(char *command, char *args);
|
||
void dcc_help1(char *command, char *args);
|
||
void dcc_exempt(char *command, char *args);
|
||
void dcc_ftpopen(char *command, char *args);
|
||
|
||
DCC_commands dcc_commands[] =
|
||
{
|
||
#ifndef BITCHX_LITE
|
||
{ "BOT", dcc_chat, NULL },
|
||
#endif
|
||
{ "CHAT", dcc_chat, "[nick]\n- Starts a dcc chat connection" },
|
||
{ "CLOSE", dcc_close, NULL },
|
||
{ "CLOSEALL", dcc_closeall, NULL },
|
||
{ "SEND", BX_dcc_filesend, "[-b block] [-e passwd] [-p port] [nick|nick1,nick2] filename(s)\n- Send list of files to nick(s)" },
|
||
{ "RESEND", BX_dcc_resend, "[-b block] [-e passwd] [-p port] [nick|nick1,nick2] filename(s)\n- Send list of files to nick(s)" },
|
||
{ "TSEND", BX_dcc_filesend, "[-b block] [-e passwd] [-p port] [nick|nick1,nick2] filename(s)\n- Send list of files to nick(s)" },
|
||
{ "TRESEND", BX_dcc_resend, "[-b block] [-e passwd] [-p port] [nick|nick1,nick2] filename(s)\n- Send list of files to nick(s)" },
|
||
#ifdef MIRC_BROKEN_DCC_RESUME
|
||
{ "RESUME", dcc_resume, NULL },
|
||
#endif
|
||
{ "GET", dcc_getfile, NULL },
|
||
{ "REGET", dcc_regetfile, NULL },
|
||
{ "TGET", dcc_getfile, NULL },
|
||
{ "TREGET", dcc_regetfile, NULL },
|
||
{ "LIST", dcc_glist, NULL },
|
||
{ "FTP", dcc_ftpopen, NULL },
|
||
{ "RENAME", dcc_rename, "nick filename" },
|
||
{ "ACTIVECOUNT",dcc_show_active, NULL },
|
||
{ "QUIETMODE", dcc_set_quiet, NULL },
|
||
{ "SHOWPATHS", dcc_set_paths, NULL },
|
||
{ "AUTORENAME", dcc_tog_rename, NULL },
|
||
{ "AUTORESUME", dcc_tog_resume, NULL },
|
||
{ "AUTOOVERWRITE",dcc_overwrite_toggle, NULL },
|
||
{ "AUTOGET", dcc_tog_auto, NULL },
|
||
{ "STATS", dcc_stats, NULL },
|
||
{ "EXEMPT", dcc_exempt, NULL },
|
||
{ "HELP", dcc_help1, NULL },
|
||
{ NULL, (dcc_function) NULL, NULL }
|
||
};
|
||
|
||
|
||
|
||
static int doing_multi = 0; /*
|
||
* set this if doing multiple requests
|
||
* helps prevent console spam by reducing
|
||
* the amount of output.
|
||
*/
|
||
|
||
#if 0
|
||
int add_dcc_command(char *name, char *help, void (*func)(char *, char *))
|
||
{
|
||
int count = 0;
|
||
if (!dcc_dllcommands) /* ooh first time. need to init. make it double*/
|
||
dcc_dllcommands = new_malloc(sizeof(DCC_commands) * 2);
|
||
else
|
||
{
|
||
for ( ; dcc_dllcommands[count].name; count++) ;
|
||
RESIZE(dcc_dllcommands, DCC_commands, count + 2);
|
||
}
|
||
malloc_strcpy(&dcc_dllcommands[count].name, name);
|
||
malloc_strcpy(&dcc_dllcommands[count].help, help);
|
||
dcc_dllcommands[count].function = func;
|
||
return count + 1;
|
||
}
|
||
|
||
int remove_dcc_hook(char *name)
|
||
{
|
||
int i, count = 0;
|
||
int done = 0;
|
||
for ( ; dcc_dllcommands[count].name; count++) ;
|
||
for (i = 0; i < count; i++)
|
||
{
|
||
if (dcc_dllcommands[i].name && !my_stricmp(dcc_dllcommands[i].name, name))
|
||
{
|
||
new_free(&dcc_dllcommands[i].name);
|
||
new_free(&dcc_dllcommands[i].help);
|
||
dcc_dllcommands[i].function = NULL;
|
||
done++;
|
||
break;
|
||
}
|
||
}
|
||
return done;
|
||
}
|
||
#endif
|
||
|
||
void send_ctcp_booster(char *nick, char *type, char *file, unsigned long address, unsigned short portnum, unsigned long filesize)
|
||
{
|
||
if (filesize)
|
||
send_ctcp(CTCP_PRIVMSG, nick, CTCP_DCC,
|
||
"%s %s %lu %u %lu", type, file,address, portnum, filesize);
|
||
else
|
||
send_ctcp(CTCP_PRIVMSG, nick, CTCP_DCC,
|
||
"%s %s %lu %u", type, file, address, portnum);
|
||
}
|
||
|
||
void send_reject_ctcp(char *nick, char *type, char *name)
|
||
{
|
||
/*
|
||
* And output it to the user
|
||
*/
|
||
userhostbase(nick, output_reject_ctcp, 1, "%s %s %s", nick, type, name ? name : "<any>");
|
||
}
|
||
|
||
void BX_erase_dcc_info(int s, int reject, char *format, ...)
|
||
{
|
||
DCC_int *n = NULL;
|
||
SocketList *s1;
|
||
static time_t last_reject = 0;
|
||
|
||
if (format)
|
||
{
|
||
va_list args;
|
||
char buffer[BIG_BUFFER_SIZE+1];
|
||
va_start(args, format);
|
||
vsnprintf(buffer, BIG_BUFFER_SIZE, format, args);
|
||
va_end(args);
|
||
put_it("%s", buffer);
|
||
}
|
||
dcc_update_stats(s);
|
||
|
||
s1 = get_socket(s);
|
||
if (check_dcc_socket(s) && (n = (DCC_int *)get_socketinfo(s)))
|
||
{
|
||
if (dcc_types[s1->flags & DCC_TYPES]->close_func)
|
||
(*dcc_types[s1->flags & DCC_TYPES]->close_func)(s, n->remote.s_addr, n->remport);
|
||
if (reject && ((now - last_reject) < 2))
|
||
send_reject_ctcp(s1->server,
|
||
(((s1->flags & DCC_TYPES) == DCC_FILEOFFER) ? "GET" :
|
||
((s1->flags & DCC_TYPES) == DCC_FILEREAD) ? "SEND" :
|
||
dcc_types[s1->flags & DCC_TYPES]->name),
|
||
n->filename);
|
||
last_reject = now;
|
||
new_free(&n->user);
|
||
new_free(&n->userhost);
|
||
new_free(&n->encrypt);
|
||
new_free(&n->filename);
|
||
new_free(&n->othername);
|
||
if (n->file > 0) close(n->file);
|
||
new_free(&n);
|
||
}
|
||
set_socketinfo(s, NULL);
|
||
update_transfer();
|
||
dcc_count--;
|
||
/* dcc_renumber_active();*/
|
||
}
|
||
|
||
/* dcc_match()
|
||
*
|
||
* Returns non-zero if the passed DCC socket matches the supplied parameters.
|
||
* NULL for string parameters and -1 for int parameters means Don't-Care.
|
||
*/
|
||
static int dcc_match(const SocketList *s, const char *nick, const char *desc, const char *other, int type, int active, int num)
|
||
{
|
||
const DCC_int *n = s->info;
|
||
|
||
if (type != -1 && type != (s->flags & DCC_TYPES))
|
||
return 0;
|
||
if (num != -1 && num != n->dccnum)
|
||
return 0;
|
||
if (nick && my_stricmp(nick, s->server))
|
||
return 0;
|
||
if (desc && n->filename && my_stricmp(desc, n->filename))
|
||
{
|
||
const char *last = strrchr(n->filename, '/');
|
||
if (!last || my_stricmp(desc, last + 1))
|
||
return 0;
|
||
}
|
||
if (other && n->othername && my_stricmp(other, n->othername))
|
||
return 0;
|
||
if (active == 0 && (s->flags & DCC_ACTIVE))
|
||
return 0;
|
||
if (active == 1 && !(s->flags & DCC_ACTIVE))
|
||
return 0;
|
||
|
||
return 1;
|
||
}
|
||
|
||
/*
|
||
* finds an active dcc connection. one that either is already started
|
||
* or one that has been initiated on our side.
|
||
*/
|
||
|
||
SocketList *BX_find_dcc(const char *nick, const char *desc, const char *other, int type, int create, int active, int num)
|
||
{
|
||
int i;
|
||
SocketList *s;
|
||
|
||
for (i = 0; i < get_max_fd()+1; i++)
|
||
{
|
||
if (!check_dcc_socket(i))
|
||
continue;
|
||
s = get_socket(i);
|
||
|
||
if (dcc_match(s, nick, desc, other, type, active, num))
|
||
return s;
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
/*
|
||
* finds a pending dcc which the other end has initiated.
|
||
*/
|
||
static DCC_List *find_dcc_pending(const char *nick, const char *desc, const char *othername, int type, int remove, int num)
|
||
{
|
||
SocketList *s;
|
||
DCC_List *new_i;
|
||
DCC_List *last_i = NULL;
|
||
|
||
for (new_i = pending_dcc; new_i; last_i = new_i, new_i = new_i->next)
|
||
{
|
||
s = &new_i->sock;
|
||
|
||
if (dcc_match(s, nick, desc, othername, type, -1, num))
|
||
{
|
||
if (remove)
|
||
{
|
||
if (last_i)
|
||
last_i->next = new_i->next;
|
||
else
|
||
pending_dcc = new_i->next;
|
||
}
|
||
|
||
return new_i;
|
||
}
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
void add_userhost_to_chat(UserhostItem *stuff, char *nick, char *args)
|
||
{
|
||
SocketList *Client = NULL;
|
||
DCC_int *n = NULL;
|
||
|
||
if (!stuff || !stuff->nick || !stuff->user || !stuff->host || !strcmp(stuff->user, "<UNKNOWN>"))
|
||
return;
|
||
if ((Client = find_dcc(nick, "chat", NULL, DCC_CHAT, 0, -1, -1)))
|
||
n = (DCC_int *)get_socketinfo(Client->is_read);
|
||
if (n)
|
||
{
|
||
n->userhost = m_sprintf("%s@%s", stuff->user, stuff->host);
|
||
n->server = from_server;
|
||
}
|
||
return;
|
||
}
|
||
|
||
static void refileread_send_start(int s, DCC_int *n)
|
||
{
|
||
struct stat buf;
|
||
lseek(n->file, 0, SEEK_END);
|
||
/* get the size of our file to be resumed */
|
||
fstat(n->file, &buf);
|
||
n->transfer_orders.packet_id = DCC_PACKETID;
|
||
n->transfer_orders.byteoffset = buf.st_size;
|
||
n->transfer_orders.byteorder = byte_order_test();
|
||
put_it("%s", convert_output_format("$G %RDCC %YTelling uplink we want to start at%n: $0", "%s", ulongcomma(n->transfer_orders.byteoffset)));
|
||
send(s, (const char *)&n->transfer_orders, sizeof(struct transfer_struct), 0);
|
||
}
|
||
|
||
#ifdef HAVE_SSL
|
||
int SSL_dcc_create(SocketList *s, int sock, int doconnect)
|
||
{
|
||
set_blocking(sock);
|
||
if(doconnect)
|
||
s->ctx = SSL_CTX_new (SSLv23_client_method());
|
||
else
|
||
s->ctx = SSL_CTX_new (SSLv23_server_method());
|
||
SSL_CTX_set_cipher_list(s->ctx, "ADH:@STRENGTH");
|
||
s->ssl_fd = SSL_new (s->ctx);
|
||
SSL_set_fd (s->ssl_fd, sock);
|
||
if(doconnect)
|
||
return SSL_connect (s->ssl_fd);
|
||
return SSL_accept(s->ssl_fd);
|
||
}
|
||
#endif
|
||
|
||
DCC_int *BX_dcc_create(char *nick, char *filename, char *passwd, unsigned long filesize, int port, int type, unsigned long flags, void (*func)(int))
|
||
{
|
||
|
||
struct sockaddr_foobar myip, blah;
|
||
int ofs = from_server;
|
||
int s;
|
||
DCC_int *new = NULL;
|
||
DCC_List *new_i;
|
||
|
||
|
||
if (from_server == -1)
|
||
from_server = get_window_server(0);
|
||
if (from_server == -1)
|
||
return NULL;
|
||
if (get_int_var(DCC_USE_GATEWAY_ADDR_VAR))
|
||
blah = get_server_uh_addr(from_server);
|
||
else
|
||
blah = get_server_local_addr(from_server);
|
||
memcpy(&myip, &blah, sizeof(struct sockaddr_foobar));
|
||
|
||
if (use_nat_address)
|
||
{
|
||
myip.sf_family = AF_INET;
|
||
myip.sf_addr.s_addr = nat_address.s_addr;
|
||
}
|
||
|
||
set_display_target(NULL, LOG_DCC);
|
||
if ( ((new_i = find_dcc_pending(nick, filename, NULL, type, 1, -1)) && new_i->sock.flags & DCC_OFFER) || (flags & DCC_OFFER))
|
||
{
|
||
SocketList *s = NULL;
|
||
int new_s;
|
||
struct sockaddr_in remaddr;
|
||
socklen_t rl = sizeof(remaddr);
|
||
|
||
|
||
if (!new_i && !(new_i = find_dcc_pending(nick, filename, NULL, type, 1, -1)))
|
||
return NULL;
|
||
s = &new_i->sock;
|
||
new = (DCC_int *)s->info;
|
||
|
||
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
|
||
#endif
|
||
)
|
||
{
|
||
#ifdef HAVE_SSL
|
||
SSL_show_errors();
|
||
#endif
|
||
erase_dcc_info(s->is_read, 1, "%s", convert_output_format("$G %RDCC%n Unable to create connection: $0-", "%s", errno ? strerror(errno) : "Unknown Host"));
|
||
close_socketread(s->is_read);
|
||
from_server = ofs;
|
||
new_free(&new_i->nick);
|
||
new_free(&new_i);
|
||
reset_display_target();
|
||
return NULL;
|
||
}
|
||
flags |= DCC_ACTIVE;
|
||
add_socketread(new_s, new->remport, flags|type, nick, new_i->sock.func_read, NULL);
|
||
set_socketinfo(new_s, new);
|
||
if ((getpeername(new_s, (struct sockaddr *) &remaddr, &rl)) != -1)
|
||
{
|
||
|
||
flags &= ~DCC_OFFER;
|
||
if (type != DCC_RAW)
|
||
{
|
||
int blah;
|
||
|
||
if (type == DCC_FILEOFFER)
|
||
blah = do_hook(DCC_CONNECT_LIST,"%s %s %s %d %ld %s",
|
||
nick, dcc_types[type]->name,
|
||
inet_ntoa(remaddr.sin_addr),
|
||
ntohs(remaddr.sin_port),(unsigned long)new->filesize, new->filename);
|
||
else
|
||
blah = do_hook(DCC_CONNECT_LIST,"%s %s %s %d",
|
||
nick, dcc_types[type]->name,
|
||
inet_ntoa(remaddr.sin_addr),
|
||
ntohs(remaddr.sin_port));
|
||
if (blah && !dcc_quiet)
|
||
put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_CONNECT_FSET),
|
||
"%s %s %s %s %s %d", update_clock(GET_TIME), dcc_types[type]->name, nick, new->userhost?new->userhost:"u@h",
|
||
inet_ntoa(remaddr.sin_addr), (int)ntohs(remaddr.sin_port)));
|
||
}
|
||
}
|
||
if (dcc_types[type]->open_func)
|
||
(*dcc_types[type]->open_func)(new_s, type, new->remote.s_addr, ntohs(remaddr.sin_port));
|
||
if (type == DCC_REFILEREAD)
|
||
refileread_send_start(new_s, new);
|
||
if (get_int_var(DCC_FAST_VAR)
|
||
#ifdef HAVE_SSL
|
||
&& !(flags & DCC_SSL)
|
||
#endif
|
||
)
|
||
{
|
||
set_non_blocking(new_s);
|
||
new->dcc_fast = 1;
|
||
}
|
||
set_socketflags(new_s, flags|type);
|
||
get_time(&new->starttime);
|
||
get_time(&new->lasttime);
|
||
new_free(&new_i->nick);
|
||
new_free(&new_i);
|
||
}
|
||
else
|
||
{
|
||
char *nopath = NULL;
|
||
char *file = NULL;
|
||
char *Type;
|
||
unsigned short portnum = port;
|
||
|
||
/* If a port isn't specified and random local ports is on
|
||
* generate a random port to use.
|
||
*/
|
||
if (!port && get_int_var(RANDOM_LOCAL_PORTS_VAR))
|
||
portnum = random_number(0) % (65536 - 1024) + 1024;
|
||
|
||
if (get_int_var(DCC_FORCE_PORT_VAR))
|
||
portnum = get_int_var(DCC_FORCE_PORT_VAR);
|
||
|
||
flags |= DCC_WAIT;
|
||
if ((s = connect_by_number(NULL, &portnum, SERVICE_SERVER, PROTOCOL_TCP, 1)) < 0)
|
||
{
|
||
/* If a port was specified and we failed, and
|
||
* random local ports is on, try a random port.
|
||
*/
|
||
if(port && get_int_var(RANDOM_LOCAL_PORTS_VAR))
|
||
portnum = random_number(0) % (65536 - 1024) + 1024;
|
||
else
|
||
portnum = 0;
|
||
if ((s = connect_by_number(NULL, &portnum, SERVICE_SERVER, PROTOCOL_TCP, 1)) < 0)
|
||
{
|
||
/* Finally try to get a system port number by using 0 */
|
||
portnum = 0;
|
||
s = connect_by_number(NULL, &portnum, SERVICE_SERVER, PROTOCOL_TCP, 1);
|
||
}
|
||
}
|
||
if (s < 0)
|
||
{
|
||
put_it("%s", convert_output_format("$G %RDCC%n Unable to create connection: $0-", "%s", errno ? strerror(errno) : "Unknown Host"));
|
||
reset_display_target();
|
||
from_server = ofs;
|
||
return NULL;
|
||
}
|
||
Type = dcc_types[type]->name;
|
||
add_socketread(s, portnum, flags|type, nick, func, NULL);
|
||
add_sockettimeout(s, 120, NULL);
|
||
|
||
new = new_malloc(sizeof(DCC_int));
|
||
new->struct_type = DCC_STRUCT_TYPE;
|
||
new->othername = m_strdup(ltoa(portnum));
|
||
new->localport = port;
|
||
new->dccnum = ++dcc_count;
|
||
get_time(&new->lasttime);
|
||
set_socketinfo(s, new);
|
||
|
||
if (!(flags & DCC_TWOCLIENTS))
|
||
{
|
||
reset_display_target();
|
||
from_server = ofs;
|
||
return new;
|
||
}
|
||
if (passwd)
|
||
new->encrypt = m_strdup(passwd);
|
||
if (filename)
|
||
{
|
||
char *p;
|
||
if ((nopath = strrchr(filename, '/')))
|
||
nopath++;
|
||
else
|
||
nopath = filename;
|
||
file = LOCAL_COPY(nopath);
|
||
p = file;
|
||
while ((p = strchr(p, ' ')))
|
||
*p = '_';
|
||
if (strcmp(filename, "bxglobal"))
|
||
new->filename = m_strdup(filename);
|
||
else
|
||
new->filename = m_strdup("_bxglobal");
|
||
}
|
||
new->filesize = filesize;
|
||
#if 0
|
||
if (use_socks && get_string_var(SOCKS_HOST_VAR))
|
||
{
|
||
struct hostent *hp;
|
||
struct sockaddr_in socks;
|
||
unsigned long addr;
|
||
hp = gethostbyname(get_string_var(SOCKS_HOST_VAR));
|
||
memcpy(&socks, hp->h_addr, sizeof(hp->h_length));
|
||
addr = inet_addr(inet_ntoa(socks.sin_addr));
|
||
send_ctcp_booster(nick, Type, file, addr, portnum, filesize);
|
||
}
|
||
else
|
||
#endif
|
||
send_ctcp_booster(nick, Type, file, ntohl(myip.sf_addr.s_addr), portnum, filesize);
|
||
if (!doing_multi && !dcc_quiet)
|
||
{
|
||
if (filesize)
|
||
{
|
||
if (do_hook(DCC_OFFER_LIST, "%s %s %s %lu",
|
||
nick, Type, file, filesize))
|
||
put_it("%s", convert_output_format(fget_string_var(FORMAT_SEND_DCC_CHAT_FSET),
|
||
"%s %s %s", update_clock(GET_TIME), Type, nick));
|
||
}
|
||
else
|
||
{
|
||
if (do_hook(DCC_OFFER_LIST, "%s %s %s", nick, Type, file))
|
||
put_it("%s", convert_output_format(fget_string_var(FORMAT_SEND_DCC_CHAT_FSET),
|
||
"%s %s %s", update_clock(GET_TIME), Type, nick));
|
||
}
|
||
}
|
||
}
|
||
reset_display_target();
|
||
from_server = ofs;
|
||
return new;
|
||
}
|
||
|
||
static void start_dcc_chat(int s)
|
||
{
|
||
struct sockaddr_in remaddr;
|
||
socklen_t sra;
|
||
int type;
|
||
int new_s = -1;
|
||
char *nick = NULL;
|
||
unsigned long flags;
|
||
DCC_int *n = NULL;
|
||
SocketList *sa, *new_sa;
|
||
void (*func)(int) = process_dcc_chat;
|
||
|
||
sa = get_socket(s);
|
||
flags = sa->flags;
|
||
nick = sa->server;
|
||
sra = sizeof(struct sockaddr_in);
|
||
new_s = my_accept(s, (struct sockaddr *) &remaddr, &sra);
|
||
type = flags & DCC_TYPES;
|
||
n = get_socketinfo(s);
|
||
n->user = m_strdup(nick);
|
||
set_display_target(NULL, LOG_DCC);
|
||
#ifndef BITCHX_LITE
|
||
if (type == DCC_BOTMODE) func = process_dcc_bot;
|
||
#endif
|
||
if ((add_socketread(new_s, ntohs(remaddr.sin_port), flags, nick, func, NULL)) < 0)
|
||
{
|
||
erase_dcc_info(s, 0, "%s", convert_output_format("$G %RDCC error: accept() failed. punt!!", NULL, NULL));
|
||
close_socketread(s);
|
||
return;
|
||
}
|
||
flags &= ~DCC_WAIT;
|
||
flags |= DCC_ACTIVE;
|
||
set_socketflags(new_s, flags);
|
||
set_socketinfo(new_s, n);
|
||
|
||
new_sa = get_socket(new_s);
|
||
#ifdef HAVE_SSL
|
||
if((flags & DCC_SSL) && SSL_dcc_create(new_sa, new_s, 0) < 0)
|
||
{
|
||
say("SSL_accept failed.");
|
||
SSL_show_errors();
|
||
return;
|
||
}
|
||
#endif
|
||
|
||
if (do_hook(DCC_CONNECT_LIST, "%s %s %s %d", nick, dcc_types[type]->name,
|
||
inet_ntoa(remaddr.sin_addr), ntohs(remaddr.sin_port)))
|
||
put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_CONNECT_FSET),
|
||
"%s %s %s %s %s %d", update_clock(GET_TIME),
|
||
dcc_types[type]->name,
|
||
nick, n->userhost?n->userhost:"u@h",
|
||
inet_ntoa(remaddr.sin_addr),ntohs(remaddr.sin_port)));
|
||
if ((type == DCC_BOTMODE) && n->encrypt)
|
||
new_free(&n->encrypt);
|
||
get_time(&n->starttime);
|
||
close_socketread(s);
|
||
|
||
if (dcc_types[type]->open_func)
|
||
(*dcc_types[type]->open_func)(new_s, type, n->remote.s_addr, ntohs(remaddr.sin_port));
|
||
reset_display_target();
|
||
}
|
||
|
||
static void process_dcc_chat(int s)
|
||
{
|
||
unsigned long flags;
|
||
char tmp[BIG_BUFFER_SIZE+1];
|
||
char *bufptr;
|
||
long bytesread;
|
||
char *nick;
|
||
int type;
|
||
SocketList *sl;
|
||
|
||
flags = get_socketflags(s);
|
||
nick = get_socketserver(s);
|
||
type = flags & DCC_TYPES;
|
||
sl = get_socket(s);
|
||
bufptr = tmp;
|
||
if (dcc_types[type]->input)
|
||
bytesread = (*dcc_types[type]->input)(s, type, bufptr, 1, BIG_BUFFER_SIZE);
|
||
else
|
||
#ifdef HAVE_SSL
|
||
bytesread = dgets(bufptr, s, 1, BIG_BUFFER_SIZE, sl->ssl_fd);
|
||
#else
|
||
bytesread = dgets(bufptr, s, 1, BIG_BUFFER_SIZE, NULL);
|
||
#endif
|
||
|
||
set_display_target(nick, LOG_DCC);
|
||
switch(bytesread)
|
||
{
|
||
case -1:
|
||
{
|
||
const char *real_tmp = dgets_strerror(dgets_errno);
|
||
if (do_hook(DCC_LOST_LIST, "%s %s %s", nick, dcc_types[type]->name, real_tmp))
|
||
put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_ERROR_FSET),
|
||
"%s %s %s %s", update_clock(GET_TIME),
|
||
dcc_types[type]->name, nick, real_tmp));
|
||
erase_dcc_info(s, 1, NULL);
|
||
close_socketread(s);
|
||
break;
|
||
}
|
||
case 0:
|
||
break;
|
||
default:
|
||
{
|
||
char *equal_nickname = NULL;
|
||
char *uhost, *p;
|
||
DCC_int *n = NULL;
|
||
|
||
n = get_socketinfo(s);
|
||
if ((p = strrchr(tmp, '\r')))
|
||
*p = 0;
|
||
if ((p = strrchr(tmp, '\n')))
|
||
*p = 0;
|
||
my_decrypt(tmp, strlen(tmp), n->encrypt);
|
||
n->bytes_read += bytesread;
|
||
set_display_target(nick, LOG_DCC);
|
||
uhost = alloca(200);
|
||
*uhost = 0;
|
||
if (n->userhost)
|
||
uhost = n->userhost;
|
||
else
|
||
strmopencat(uhost, 99, "Unknown@", "unknown"/*inet_ntoa(remaddr.sin_addr)*/, NULL);
|
||
FromUserHost = uhost;
|
||
|
||
#ifndef BITCHX_LITE
|
||
if (*tmp == DEFAULT_BOTCHAR)
|
||
{
|
||
char *pc;
|
||
pc = tmp+1;
|
||
if ((flags & DCC_BOTCHAT))
|
||
{
|
||
if (my_strnicmp(pc, "chat", 4))
|
||
{
|
||
if (check_tcl_dcc(pc, nick, n->userhost?n->userhost:empty_string, s))
|
||
break;
|
||
}
|
||
} else if (!my_strnicmp(pc, "chat", 4) && check_tcl_dcc(pc, nick, n->userhost?n->userhost:empty_string, s))
|
||
break;
|
||
}
|
||
else if (get_int_var(BOT_MODE_VAR) && !(flags & DCC_BOTCHAT))
|
||
{
|
||
extern int cmd_password(int, char *);
|
||
if (cmd_password(s, tmp))
|
||
{
|
||
dcc_printf(s, "Wrong Password\n");
|
||
erase_dcc_info(sl->is_read, 1, NULL);
|
||
close_socketread(sl->is_read);
|
||
}
|
||
break;
|
||
}
|
||
#endif
|
||
#undef CTCP_REPLY
|
||
#define CTCP_MESSAGE "CTCP_MESSAGE "
|
||
#define CTCP_MESSAGE_LEN strlen(CTCP_MESSAGE)
|
||
#define CTCP_REPLY "CTCP_REPLY "
|
||
#define CTCP_REPLY_LEN strlen(CTCP_REPLY)
|
||
|
||
equal_nickname = alloca(strlen(nick) + 10);
|
||
*equal_nickname = 0;
|
||
strmopencat(equal_nickname, strlen(nick)+4, "=", nick, NULL);
|
||
|
||
|
||
if (!strncmp(tmp, CTCP_MESSAGE, CTCP_MESSAGE_LEN) ||
|
||
(*tmp == CTCP_DELIM_CHAR && !strncmp(tmp+1, "ACTION", 6)))
|
||
{
|
||
char *tmp2;
|
||
tmp2 = LOCAL_COPY(tmp);
|
||
strcpy(tmp, do_ctcp(equal_nickname, get_server_nickname(from_server), stripansicodes((tmp2 + ((*tmp2 == CTCP_DELIM_CHAR) ? 0 : CTCP_MESSAGE_LEN)) ) ));
|
||
if (!*tmp)
|
||
break;
|
||
}
|
||
else if (!strncmp(tmp, CTCP_REPLY, CTCP_REPLY_LEN) || *tmp == CTCP_DELIM_CHAR)
|
||
{
|
||
char *tmp2;
|
||
tmp2 = LOCAL_COPY(tmp);
|
||
strcpy(tmp, do_notice_ctcp(equal_nickname, get_server_nickname(from_server), stripansicodes(tmp2 + (((*tmp2 == CTCP_DELIM_CHAR) ? 0 : CTCP_REPLY_LEN)))));
|
||
if (!*tmp)
|
||
break;
|
||
}
|
||
if (do_hook(DCC_CHAT_LIST, "%s %s", nick, tmp))
|
||
{
|
||
addtabkey(equal_nickname, "msg", 0);
|
||
put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_CHAT_FSET),
|
||
"%s %s %s %s", update_clock(GET_TIME), nick, FromUserHost, tmp));
|
||
add_last_type(&last_dcc[0], MAX_LAST_MSG, nick, NULL, FromUserHost, tmp);
|
||
logmsg(LOG_DCC, nick, 0, "%s", tmp);
|
||
}
|
||
FromUserHost = empty_string;
|
||
break;
|
||
}
|
||
}
|
||
reset_display_target();
|
||
}
|
||
|
||
#ifndef BITCHX_LITE
|
||
static void process_dcc_bot(int s)
|
||
{
|
||
unsigned long flags;
|
||
char tmp[BIG_BUFFER_SIZE+1];
|
||
char *bufptr;
|
||
long bytesread;
|
||
char *nick;
|
||
int type;
|
||
SocketList *sl;
|
||
|
||
flags = get_socketflags(s);
|
||
nick = get_socketserver(s);
|
||
type = flags & DCC_TYPES;
|
||
sl = get_socket(s);
|
||
|
||
bufptr = tmp;
|
||
if (dcc_types[type]->input)
|
||
bytesread = (*dcc_types[type]->input) (type, s, bufptr, 1, BIG_BUFFER_SIZE);
|
||
else
|
||
#ifdef HAVE_SSL
|
||
bytesread = dgets(bufptr, s, 1, BIG_BUFFER_SIZE, sl->ssl_fd);
|
||
#else
|
||
bytesread = dgets(bufptr, s, 1, BIG_BUFFER_SIZE, NULL);
|
||
#endif
|
||
|
||
set_display_target(nick, LOG_DCC);
|
||
switch(bytesread)
|
||
{
|
||
case -1:
|
||
{
|
||
const char *real_tmp = dgets_strerror(dgets_errno);
|
||
if (do_hook(DCC_LOST_LIST, "%s %s %s", nick, dcc_types[type]->name, real_tmp))
|
||
put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_ERROR_FSET),
|
||
"%s %s %s %s", update_clock(GET_TIME),
|
||
dcc_types[type]->name, nick, real_tmp));
|
||
erase_dcc_info(s, 1, NULL);
|
||
close_socketread(s);
|
||
break;
|
||
}
|
||
case 0:
|
||
break;
|
||
default:
|
||
{
|
||
DCC_int *n = NULL;
|
||
char *p;
|
||
n = get_socketinfo(s);
|
||
if ((p = strrchr(tmp, '\r')))
|
||
*p = 0;
|
||
if ((p = strrchr(tmp, '\n')))
|
||
*p = 0;
|
||
|
||
my_decrypt(tmp, strlen(tmp), n->encrypt);
|
||
n->bytes_read += bytesread;
|
||
set_display_target(nick, LOG_DCC);
|
||
handle_dcc_bot(s, tmp);
|
||
}
|
||
}
|
||
reset_display_target();
|
||
}
|
||
#endif
|
||
|
||
/* flag == 1 means show it. flag == 0 used by redirect (and /ctcp) */
|
||
|
||
static void new_dcc_message_transmit (char *user, char *text, char *text_display, int type, int flag, char *cmd, int check_host)
|
||
{
|
||
SocketList *s = NULL;
|
||
DCC_int *n = NULL;
|
||
char tmp[MAX_DCC_BLOCK_SIZE+1];
|
||
int list = 0;
|
||
int len = 0;
|
||
char *host = NULL;
|
||
char thing = 0;
|
||
|
||
*tmp = 0;
|
||
|
||
switch(type)
|
||
{
|
||
case DCC_CHAT:
|
||
thing = '=';
|
||
host = "chat";
|
||
list = SEND_DCC_CHAT_LIST;
|
||
break;
|
||
case DCC_RAW:
|
||
if (check_host)
|
||
{
|
||
if (!(host = next_arg(text, &text)))
|
||
{
|
||
put_it("%s", convert_output_format("$G %RDCC%n No host specified for DCC RAW", NULL, NULL));
|
||
return;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
s = find_dcc(user, host, NULL, type, 0, 1, -1);
|
||
if (!s || !(s->flags & DCC_ACTIVE))
|
||
{
|
||
put_it("%s", convert_output_format("$G %RDCC No active $0:$1 connection for $2", "%s %s %s", dcc_types[type]->name, host?host:"(null)", user));
|
||
return;
|
||
}
|
||
n = (DCC_int *)s->info;
|
||
|
||
/*
|
||
* Check for CTCPs... whee.
|
||
*/
|
||
if (cmd && *text == CTCP_DELIM_CHAR && strncmp(text+1, "ACTION", 6))
|
||
{
|
||
if (!strcmp(cmd, "PRIVMSG"))
|
||
strlcpy(tmp, "CTCP_MESSAGE ", sizeof tmp);
|
||
else
|
||
strlcpy(tmp, "CTCP_REPLY ", sizeof tmp);
|
||
}
|
||
|
||
strmcat(tmp, text, n->blocksize-3);
|
||
strmcat(tmp, "\n", n->blocksize-2);
|
||
|
||
len = strlen(tmp);
|
||
my_encrypt(tmp, len, n->encrypt);
|
||
|
||
if (dcc_types[type]->output)
|
||
(*dcc_types[type]->output) (type, s->is_read, tmp, len);
|
||
else
|
||
#ifdef HAVE_SSL
|
||
if(s->ssl_fd)
|
||
SSL_write(s->ssl_fd, tmp, len);
|
||
else
|
||
#endif
|
||
write(s->is_read, tmp, len);
|
||
n->bytes_sent += len;
|
||
|
||
if (flag && type != DCC_RAW)
|
||
{
|
||
if (do_hook(list, "%s %s", user, text_display ? text_display : text))
|
||
put_it("%s", convert_output_format(fget_string_var(FORMAT_SEND_DCC_CHAT_FSET), "%c %s %s", thing, user, text_display?text_display:text));
|
||
}
|
||
}
|
||
|
||
extern void dcc_chat_transmit (char *user, char *text, char *orig, char *type, int noisy)
|
||
{
|
||
int fd;
|
||
|
||
/*
|
||
* This is just a quick hack. Its not fast, its not elegant,
|
||
* and its not the best way to do this. But i whipped it up in
|
||
* 15 minutes. The "best" soLution is to rewrite dcc_message_transmit
|
||
* to allow us to do this sanely.
|
||
*/
|
||
set_display_target(NULL, LOG_DCC);
|
||
if ((fd = atol(user)))
|
||
{
|
||
SocketList * s;
|
||
char * bogus;
|
||
|
||
if (!check_dcc_socket(fd))
|
||
{
|
||
put_it("%s", convert_output_format("$G %RDCC%n Descriptor [$0] is not an open DCC RAW", "%d", fd));
|
||
return;
|
||
}
|
||
s = get_socket(fd);
|
||
bogus = alloca(strlen(text) + strlen(((DCC_int *)s->info)->filename) + 3);
|
||
|
||
strcpy(bogus, ((DCC_int *)s->info)->filename);
|
||
strcat(bogus, space);
|
||
strcat(bogus, text);
|
||
|
||
new_dcc_message_transmit(user, bogus, orig, DCC_RAW, noisy, type, 0);
|
||
}
|
||
else
|
||
new_dcc_message_transmit(user, text, orig, DCC_CHAT, noisy, type, 0);
|
||
reset_display_target();
|
||
}
|
||
|
||
extern void dcc_bot_transmit (char *user, char *text, char *type)
|
||
{
|
||
set_display_target(user, LOG_DCC);
|
||
new_dcc_message_transmit(user, text, NULL, DCC_BOTMODE, 0, type, 1);
|
||
reset_display_target();
|
||
}
|
||
|
||
extern void dcc_chat_transmit_quiet (char *user, char *text, char *type)
|
||
{
|
||
new_dcc_message_transmit(user, text, NULL, DCC_CHAT, 0, type, 0);
|
||
}
|
||
|
||
int dcc_activechat(char *user)
|
||
{
|
||
return find_dcc(user, NULL, NULL, DCC_CHAT, 0, 1, -1) ? 1 : 0;
|
||
}
|
||
|
||
int dcc_activebot(char *user)
|
||
{
|
||
return find_dcc(user, NULL, NULL, DCC_BOTMODE, 0, 1, -1) ? 1 : 0;
|
||
}
|
||
|
||
int dcc_activeraw(char *user)
|
||
{
|
||
return find_dcc(user, NULL, NULL, DCC_RAW, 0, 1, -1) ? 1 : 0;
|
||
}
|
||
|
||
int get_dcc_type(char *type)
|
||
{
|
||
int tdcc = 0;
|
||
int i;
|
||
if (!type || !*type)
|
||
return -1;
|
||
upper(type);
|
||
if (*type == 'T')
|
||
type++, tdcc = DCC_TDCC;
|
||
|
||
for (i = 0; dcc_types[i]->name; i++)
|
||
if (!strcmp(type, dcc_types[i]->name))
|
||
return i | tdcc;
|
||
return -1;
|
||
}
|
||
|
||
void process_dcc_send1(int s);
|
||
void start_dcc_get(int s);
|
||
|
||
/* dcc_fullname()
|
||
* Return an allocated string with the full pathname to a DCC downloaded file.
|
||
*/
|
||
static char *dcc_fullname(const char *filename)
|
||
{
|
||
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);
|
||
}
|
||
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)
|
||
*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;
|
||
}
|
||
|
||
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));
|
||
return 0;
|
||
}
|
||
if ((s->flags & DCC_WAIT))
|
||
{
|
||
if (type == DCC_CHAT)
|
||
{
|
||
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 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);
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
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)
|
||
{
|
||
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)
|
||
{
|
||
autoget = 1;
|
||
}
|
||
else
|
||
{
|
||
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 (p = get_string_var(BOT_PASSWORD_VAR))
|
||
{
|
||
if (encrypt && !strcmp(p, encrypt))
|
||
;/* do it */
|
||
message_from(NULL, LOG_CRAP);
|
||
return;
|
||
}
|
||
#endif
|
||
}
|
||
|
||
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))
|
||
{
|
||
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)
|
||
{
|
||
/* autoget of an existing file: either rename it, resume it, or punt */
|
||
if (get_int_var(DCC_AUTORENAME_VAR))
|
||
{
|
||
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", 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", 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", fullname));
|
||
}
|
||
}
|
||
|
||
n->dccnum = ++dcc_count;
|
||
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)
|
||
{
|
||
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, 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)
|
||
{
|
||
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();
|
||
}
|
||
|
||
void process_dcc(char *args)
|
||
{
|
||
char *command;
|
||
int i;
|
||
|
||
if (!(command = next_arg(args, &args)))
|
||
return;
|
||
reset_display_target();
|
||
if (dcc_dllcommands)
|
||
{
|
||
DCC_dllcommands *dcc_comm;
|
||
if ((dcc_comm = (DCC_dllcommands *)find_in_list((List **)&dcc_dllcommands, command, 0)))
|
||
{
|
||
dcc_comm->function(dcc_comm->name, args);
|
||
reset_display_target();
|
||
return;
|
||
}
|
||
}
|
||
for (i = 0; dcc_commands[i].name != NULL; i++)
|
||
{
|
||
if (!my_strnicmp(dcc_commands[i].name, command, strlen(command)))
|
||
{
|
||
dcc_commands[i].function(dcc_commands[i].name, args);
|
||
reset_display_target();
|
||
return;
|
||
}
|
||
}
|
||
put_it("%s", convert_output_format("$G Unknown %RDCC%n command: $0", "%s", command));
|
||
reset_display_target();
|
||
}
|
||
|
||
|
||
char *get_dcc_args(char **args, char **passwd, char **port, int *blocksize)
|
||
{
|
||
char *user = NULL;
|
||
while (args && *args && **args)
|
||
{
|
||
char *argument = new_next_arg(*args, args);
|
||
if (argument && *argument)
|
||
{
|
||
|
||
if (*argument == '-')
|
||
{
|
||
argument++;
|
||
if (*argument == 'e')
|
||
*passwd = next_arg(*args, args);
|
||
else if (*argument == 'p')
|
||
*port = next_arg(*args, args);
|
||
else if (*argument == 'b')
|
||
*blocksize = my_atol(next_arg(*args, args));
|
||
}
|
||
else
|
||
user = argument;
|
||
}
|
||
if (user) break;
|
||
}
|
||
return user;
|
||
}
|
||
|
||
void dcc_chat(char *command, char *args)
|
||
{
|
||
char *user;
|
||
char *nick;
|
||
|
||
char *passwd = NULL;
|
||
char *port = NULL;
|
||
char *equal_user = NULL;
|
||
DCC_int *new = NULL;
|
||
SocketList *s = NULL;
|
||
int blocksize = get_int_var(DCC_BLOCK_SIZE_VAR);
|
||
int bot = 0;
|
||
int flags = 0;
|
||
|
||
#ifndef BITCHX_LITE
|
||
if (command && !my_stricmp(command, "BOT"))
|
||
bot++;
|
||
#endif
|
||
|
||
#ifdef HAVE_SSL
|
||
if(my_strnicmp(args, "-SSL", 4) == 0)
|
||
{
|
||
new_next_arg(args, &args);
|
||
flags = DCC_SSL;
|
||
}
|
||
#endif
|
||
|
||
user = get_dcc_args(&args, &passwd, &port, &blocksize);
|
||
if (!user)
|
||
{
|
||
put_it("%s", convert_output_format("$G %RDCC%n You must supply a nickname for DCC chat", NULL, NULL));
|
||
return;
|
||
}
|
||
if (!blocksize || blocksize > MAX_DCC_BLOCK_SIZE)
|
||
blocksize = get_int_var(DCC_BLOCK_SIZE_VAR);
|
||
|
||
while ((nick = next_in_comma_list(user, &user)))
|
||
{
|
||
if (!nick || !*nick)
|
||
break;
|
||
if (isme(nick)) continue;
|
||
if ((s = find_dcc(nick, "chat", NULL, bot?DCC_BOTMODE:DCC_CHAT, 1, -1, -1)))
|
||
{
|
||
if ((s->flags & DCC_ACTIVE) || (s->flags & DCC_WAIT))
|
||
put_it("%s", convert_output_format("$G %RDCC%n A previous DCC chat to $0 exists", "%s", nick));
|
||
new = (DCC_int *)s->info;
|
||
if (s->flags & DCC_WAIT)
|
||
{
|
||
send_ctcp_booster(nick,
|
||
dcc_types[DCC_CHAT]->name, "chat",
|
||
htonl(get_int_var(DCC_USE_GATEWAY_ADDR_VAR) ? get_server_uh_addr(from_server).sf_addr.s_addr : get_server_local_addr(from_server).sf_addr.s_addr),
|
||
htons(s->port), new->filesize);
|
||
add_sockettimeout(s->is_read, 120, NULL);
|
||
}
|
||
continue;
|
||
}
|
||
if ((new = dcc_create(nick, "chat", passwd, 0, port? atol(port) : 0, bot?DCC_BOTMODE:DCC_CHAT, DCC_TWOCLIENTS|flags, start_dcc_chat)))
|
||
{
|
||
new->blocksize = blocksize;
|
||
if (!bot)
|
||
{
|
||
equal_user = alloca(strlen(nick)+4);
|
||
strcpy(equal_user, "=");
|
||
strcat(equal_user, nick);
|
||
addtabkey(equal_user, "msg", 0);
|
||
}
|
||
userhostbase(nick, add_userhost_to_chat, 1, NULL);
|
||
}
|
||
doing_multi++;
|
||
}
|
||
doing_multi = 0;
|
||
}
|
||
|
||
void close_dcc_file(int snum)
|
||
{
|
||
SocketList *s;
|
||
DCC_int *n;
|
||
char lame_ultrix[30]; /* should be plenty */
|
||
char lame_ultrix2[30];
|
||
char lame_ultrix3[30];
|
||
char buffer[50];
|
||
char *tofrom = NULL;
|
||
char *filename, *p;
|
||
#ifdef GUI
|
||
char *who;
|
||
#endif
|
||
|
||
double xtime;
|
||
double xfer;
|
||
double temp;
|
||
unsigned long type;
|
||
char lame_type[30];
|
||
|
||
s = get_socket(snum);
|
||
if (!s || !(n = (DCC_int *)s->info))
|
||
return;
|
||
type = s->flags & DCC_TYPES;
|
||
*lame_type = 0;
|
||
if (s->flags & DCC_TDCC)
|
||
strcpy(lame_type, "T");
|
||
strcat(lame_type, dcc_types[type]->name);
|
||
|
||
xtime = time_since(&n->starttime);
|
||
xfer = (double)(n->bytes_sent ? n->bytes_sent : n->bytes_read);
|
||
|
||
if (xfer == 0.0)
|
||
xfer = 1.0;
|
||
if (xtime == 0.0)
|
||
xtime = 1.0;
|
||
temp = xfer / xtime;
|
||
sprintf(lame_ultrix, "%2.4g %s", _GMKv(temp), _GMKs(temp));
|
||
/* Cant pass %g to put_it (lame ultrix/dgux), fix suggested by sheik. */
|
||
sprintf(lame_ultrix2, "%2.4g%s", _GMKv(xfer), _GMKs(xfer));
|
||
sprintf(lame_ultrix3, "%2.4g", xtime);
|
||
sprintf(buffer, "%%s %s %%s %%s TRANSFER COMPLETE", lame_type);
|
||
|
||
filename = LOCAL_COPY(n->filename);
|
||
p = filename;
|
||
while ((p = strchr(p, ' ')))
|
||
*p = '_';
|
||
|
||
switch(type)
|
||
{
|
||
case DCC_FILEREAD:
|
||
case DCC_REFILEREAD:
|
||
tofrom = "from";
|
||
break;
|
||
case DCC_FILEOFFER:
|
||
case DCC_REFILEOFFER:
|
||
tofrom = "to";
|
||
break;
|
||
default:
|
||
tofrom = "to";
|
||
}
|
||
set_display_target(NULL, LOG_DCC);
|
||
if(do_hook(DCC_LOST_LIST,buffer,s->server, strip_path(n->filename), lame_ultrix))
|
||
put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_LOST_FSET),
|
||
"%s %s %s %s %s %s %s %s",
|
||
update_clock(GET_TIME), lame_type, strip_path(filename),
|
||
lame_ultrix2, tofrom, s->server, lame_ultrix3, lame_ultrix));
|
||
|
||
#ifdef GUI
|
||
who = LOCAL_COPY(s->server);
|
||
#endif
|
||
erase_dcc_info(snum, 0, NULL);
|
||
close_socketread(snum);
|
||
update_transfer();
|
||
update_all_status(current_window, NULL, 0);
|
||
#ifdef GUI
|
||
gui_setfileinfo(filename, who, from_server);
|
||
#endif
|
||
reset_display_target();
|
||
}
|
||
|
||
/*
|
||
* following 3 functions process dcc filesends.
|
||
*/
|
||
|
||
void process_dcc_send1(int snum)
|
||
{
|
||
SocketList *s;
|
||
DCC_int *n;
|
||
u_32int_t bytes = 0;
|
||
int bytesread = 0;
|
||
char *buffer = alloca(MAX_DCC_BLOCK_SIZE+1);
|
||
s = get_socket(snum);
|
||
n = (DCC_int *)s->info;
|
||
if (n->readwaiting || n->eof)
|
||
{
|
||
int numbytes = 0;
|
||
if (!(s->flags & DCC_TDCC) && n->readwaiting)
|
||
{
|
||
if ((ioctl(snum, FIONREAD, &numbytes)) == -1)
|
||
{
|
||
erase_dcc_info(snum, 1, convert_output_format("$G %RDCC%n Remote $0 closed dcc send", "%s", s->server));
|
||
close_socketread(snum);
|
||
return;
|
||
}
|
||
if (numbytes)
|
||
{
|
||
if (read(snum, &bytes, sizeof(u_32int_t)) < sizeof(u_32int_t))
|
||
{
|
||
erase_dcc_info(snum, 1, convert_output_format("$G %RDCC%n Remote closed dcc send", NULL));
|
||
close_socketread(snum);
|
||
}
|
||
bytes = (unsigned long)ntohl(bytes);
|
||
get_time(&n->lasttime);
|
||
if (bytes == (n->filesize - n->transfer_orders.byteoffset))
|
||
{
|
||
close_dcc_file(snum);
|
||
return;
|
||
}
|
||
else if (!n->dcc_fast && (bytes != n->bytes_sent))
|
||
return;
|
||
n->readwaiting = 0;
|
||
}
|
||
}
|
||
else if (n->eof)
|
||
{
|
||
u_32int_t *buf;
|
||
n->readwaiting = 1;
|
||
if ((ioctl(snum, FIONREAD, &numbytes) == -1))
|
||
{
|
||
close_dcc_file(snum);
|
||
return;
|
||
}
|
||
buf = alloca(numbytes+1);
|
||
numbytes = read(snum, buf, numbytes);
|
||
switch(numbytes)
|
||
{
|
||
case -1:
|
||
erase_dcc_info(snum, 1, convert_output_format("$G %RDCC%n Remote $0 closed dcc send", "%s", s->server));
|
||
close_socketread(snum);
|
||
break;
|
||
case 0:
|
||
close_dcc_file(snum);
|
||
break;
|
||
}
|
||
return;
|
||
}
|
||
}
|
||
|
||
if ((bytesread = read(n->file, buffer, n->blocksize)) > 0)
|
||
{
|
||
int num;
|
||
my_encrypt(buffer, bytesread, n->encrypt);
|
||
num = send(snum, buffer, bytesread, 0);
|
||
if (num != bytesread)
|
||
{
|
||
if (num == -1)
|
||
{
|
||
if (errno == EWOULDBLOCK || errno == ENOBUFS)
|
||
lseek(n->file, -bytesread, SEEK_CUR);
|
||
else
|
||
{
|
||
erase_dcc_info(snum, 1, convert_output_format("$G %RDCC%n Remote $0 closed dcc send", "%s", s->server));
|
||
close_socketread(snum);
|
||
return;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
lseek(n->file, -(bytesread - num), SEEK_CUR);
|
||
n->bytes_sent += num;
|
||
}
|
||
n->readwaiting = 1;
|
||
return;
|
||
}
|
||
n->bytes_sent += bytesread;
|
||
n->packets = n->bytes_sent / n->blocksize;
|
||
n->readwaiting = 1;
|
||
get_time(&n->lasttime);
|
||
if (!(n->packets % 10))
|
||
{
|
||
update_transfer();
|
||
if (!(n->packets % 20))
|
||
update_all_status(current_window, NULL, 0);
|
||
}
|
||
}
|
||
else if (!n->eof)
|
||
{
|
||
n->eof = 1;
|
||
n->readwaiting = 1;
|
||
}
|
||
else if (!n->dcc_fast)
|
||
close_dcc_file(snum);
|
||
else
|
||
n->readwaiting = 1;
|
||
}
|
||
|
||
void start_dcc_send(int s)
|
||
{
|
||
struct sockaddr_in remaddr;
|
||
socklen_t sra;
|
||
int type;
|
||
int new_s = -1;
|
||
int tdcc = 0;
|
||
char *nick = NULL;
|
||
unsigned long flags;
|
||
DCC_int *n = NULL;
|
||
struct transfer_struct received = {0};
|
||
char local_type[30];
|
||
|
||
if (!(flags = get_socketflags(s)))
|
||
return; /* wrong place damn it */
|
||
nick = get_socketserver(s);
|
||
sra = sizeof(struct sockaddr_in);
|
||
new_s = my_accept(s, (struct sockaddr *) &remaddr, &sra);
|
||
type = flags & DCC_TYPES;
|
||
n = get_socketinfo(s);
|
||
|
||
set_display_target(NULL, LOG_DCC);
|
||
if ((add_socketread(new_s, ntohs(remaddr.sin_port), flags, nick, process_dcc_send1, NULL)) < 0)
|
||
{
|
||
erase_dcc_info(s, 1, "%s", convert_output_format("$G %RDCC error: accept() failed. punt!!", NULL, NULL));
|
||
close_socketread(s);
|
||
return;
|
||
}
|
||
flags &= ~DCC_WAIT;
|
||
flags |= DCC_ACTIVE;
|
||
set_socketflags(new_s, flags);
|
||
set_socketinfo(new_s, n);
|
||
if ((n->file = open(n->filename, O_RDONLY | O_BINARY)) == -1)
|
||
{
|
||
erase_dcc_info(new_s, 1, "%s", convert_output_format("$G %RDCC%n Unable to open $0: $1-", "%s %s", n->filename, errno ? strerror(errno) : "Unknown Host"));
|
||
close_socketread(new_s);
|
||
close_socketread(s);
|
||
return;
|
||
}
|
||
if (type == DCC_REFILEOFFER)
|
||
{
|
||
alarm(1);
|
||
recv(new_s, (char *)&received, sizeof(struct transfer_struct), 0);
|
||
alarm(0);
|
||
if (byte_order_test() != received.byteorder)
|
||
{
|
||
/* the packet sender orders bytes differently than us,
|
||
* reverse what they sent to get the right value
|
||
*/
|
||
n->transfer_orders.packet_id =
|
||
((received.packet_id & 0x00ff) << 8) |
|
||
((received.packet_id & 0xff00) >> 8);
|
||
|
||
n->transfer_orders.byteoffset =
|
||
((received.byteoffset & 0xff000000) >> 24) |
|
||
((received.byteoffset & 0x00ff0000) >> 8) |
|
||
((received.byteoffset & 0x0000ff00) << 8) |
|
||
((received.byteoffset & 0x000000ff) << 24);
|
||
}
|
||
else
|
||
memcpy(&n->transfer_orders,&received,sizeof(struct transfer_struct));
|
||
if (n->transfer_orders.packet_id != DCC_PACKETID)
|
||
{
|
||
put_it("%s", convert_output_format("$G %RDCC%n reget packet is invalid!!", NULL, NULL));
|
||
memset(&n->transfer_orders, 0, sizeof(struct transfer_struct));
|
||
}
|
||
else
|
||
put_it("%s", convert_output_format("$G %RDCC%n reget starting at $0", "%s", ulongcomma(n->transfer_orders.byteoffset)));
|
||
}
|
||
if (get_int_var(DCC_FAST_VAR) && !(flags & DCC_TDCC))
|
||
{
|
||
set_non_blocking(new_s);
|
||
n->dcc_fast = 1;
|
||
}
|
||
lseek(n->file, n->transfer_orders.byteoffset, SEEK_SET);
|
||
errno = 0;
|
||
*local_type = 0;
|
||
if (tdcc)
|
||
strcpy(local_type, "T");
|
||
strcat(local_type, dcc_types[type]->name);
|
||
if (do_hook(DCC_CONNECT_LIST, "%s %s %s %d %ld %s", nick, local_type,
|
||
inet_ntoa(remaddr.sin_addr), ntohs(remaddr.sin_port), (unsigned long)n->filesize, n->filename) && !dcc_quiet)
|
||
put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_CONNECT_FSET),
|
||
"%s %s %s %s %s %d %d", update_clock(GET_TIME),
|
||
local_type, nick, n->userhost?n->userhost:"u@h",
|
||
inet_ntoa(remaddr.sin_addr),ntohs(remaddr.sin_port),n->transfer_orders.byteoffset ));
|
||
get_time(&n->starttime);
|
||
get_time(&n->lasttime);
|
||
close_socketread(s);
|
||
process_dcc_send1(new_s);
|
||
reset_display_target();
|
||
}
|
||
|
||
void real_file_send(char *nick, char *filename, char *passwd, char *port, int tdcc, unsigned long type, int blocksize)
|
||
{
|
||
DCC_int *new = NULL;
|
||
SocketList *s = NULL;
|
||
unsigned long filesize = 0;
|
||
char FileBuf[BIG_BUFFER_SIZE+1];
|
||
struct stat st;
|
||
|
||
#if defined(__EMX__) || defined(WINNT)
|
||
if (*filename == '/' || *filename == '\\')
|
||
#else
|
||
if (*filename == '/')
|
||
#endif
|
||
strncpy(FileBuf, filename, BIG_BUFFER_SIZE);
|
||
else if (*filename == '~')
|
||
{
|
||
char *fullname;
|
||
if (!(fullname = expand_twiddle(filename)))
|
||
{
|
||
put_it("%s", convert_output_format("$G %RDCC%n Unable to access $0", "%s", filename));
|
||
return;
|
||
}
|
||
strncpy(FileBuf, fullname, BIG_BUFFER_SIZE);
|
||
new_free(&fullname);
|
||
}
|
||
#if defined(__EMX__) || defined(WINNT)
|
||
else if (strlen(filename) > 3 && ( (*(filename+1) == ':') && (*(filename+2) == '/' || *(filename+2) == '\\')) )
|
||
strlcpy(FileBuf, filename, BIG_BUFFER_SIZE);
|
||
#endif
|
||
else
|
||
{
|
||
getcwd(FileBuf, BIG_BUFFER_SIZE);
|
||
strlcat(FileBuf, "/", BIG_BUFFER_SIZE);
|
||
strlcat(FileBuf, filename, BIG_BUFFER_SIZE);
|
||
}
|
||
#if defined(__EMX__) || defined(WINNT)
|
||
convert_unix(FileBuf);
|
||
#endif
|
||
|
||
if (strchr(FileBuf , '*'))
|
||
{
|
||
char *path, *c, *filebuf = NULL;
|
||
DIR *dp;
|
||
struct dirent *dir;
|
||
int count = 0;
|
||
|
||
path = LOCAL_COPY(FileBuf);
|
||
|
||
if ((c = strrchr(path, '/')))
|
||
*c++ = 0;
|
||
|
||
if (!(dp = opendir(path)))
|
||
return;
|
||
while ((dir = readdir(dp)))
|
||
{
|
||
if (!dir->d_ino)
|
||
continue;
|
||
if (!wild_match(c, dir->d_name))
|
||
continue;
|
||
malloc_sprintf(&filebuf, "%s/%s", path, dir->d_name);
|
||
stat(filebuf, &st);
|
||
if (S_ISDIR(st.st_mode))
|
||
{
|
||
new_free(&filebuf);
|
||
continue;
|
||
}
|
||
/* finally. do a send */
|
||
if ((s = find_dcc(nick, filebuf, NULL, type, 1, -1, -1)))
|
||
{
|
||
if ((s->flags & DCC_ACTIVE) || (s->flags & DCC_WAIT))
|
||
put_it("%s", convert_output_format("$G %RDCC%n A previous DCC send to $0 exists", "%s", nick));
|
||
new = (DCC_int *)s->info;
|
||
if (s->flags & DCC_WAIT)
|
||
{
|
||
send_ctcp_booster(nick, dcc_types[type]->name, filebuf, htonl(get_server_local_addr(from_server).sf_addr.s_addr), htons(s->port), new->filesize);
|
||
add_sockettimeout(s->is_read, 120, NULL);
|
||
}
|
||
continue;
|
||
}
|
||
if ((new = dcc_create(nick, filebuf, passwd, st.st_size, port? atol(port) : filesize, type, (tdcc? DCC_TDCC: 0) |DCC_TWOCLIENTS, start_dcc_send)))
|
||
new->blocksize = blocksize;
|
||
|
||
count++;
|
||
new_free(&filebuf);
|
||
}
|
||
closedir(dp);
|
||
if (!dcc_quiet)
|
||
{
|
||
char buff[30];
|
||
strcpy(buff, "file");
|
||
if (count > 1)
|
||
strcat(buff, "s");
|
||
if (count)
|
||
put_it("%s", convert_output_format("$G %RDCC%n Sent DCC SEND request to $0 for $1 $2-", "%s %s %s", nick, buff, filename));
|
||
else
|
||
put_it("%s", convert_output_format("$G %RDCC%n No Files found matching $*", "%s", filename));
|
||
}
|
||
return;
|
||
}
|
||
if (access(FileBuf, R_OK))
|
||
{
|
||
put_it("%s", convert_output_format("$G %RDCC%n No such file $0 exists", "%s", FileBuf));
|
||
return;
|
||
}
|
||
stat(FileBuf, &st);
|
||
if (S_ISDIR(st.st_mode))
|
||
{
|
||
put_it("%s", convert_output_format("$G %RDCC%n $0 is a directory", "%s", FileBuf));
|
||
return;
|
||
}
|
||
if ((s = find_dcc(nick, FileBuf, NULL, type, 1, -1, -1)))
|
||
{
|
||
if ((s->flags & DCC_ACTIVE) || (s->flags & DCC_WAIT))
|
||
put_it("%s", convert_output_format("$G %RDCC%n A previous DCC send to $0 exists", "%s", nick));
|
||
new = (DCC_int *)s->info;
|
||
if (s->flags & DCC_WAIT)
|
||
{
|
||
send_ctcp_booster(nick, dcc_types[type]->name, FileBuf, htonl(get_server_local_addr(from_server).sf_addr.s_addr), htons(s->port), new->filesize);
|
||
add_sockettimeout(s->is_read, 120, NULL);
|
||
}
|
||
return;
|
||
}
|
||
if ((new = dcc_create(nick, FileBuf, passwd, st.st_size, port? atol(port) : filesize, type, (tdcc? DCC_TDCC: 0) |DCC_TWOCLIENTS, start_dcc_send)))
|
||
new->blocksize = blocksize;
|
||
}
|
||
|
||
void BX_dcc_filesend(char *command, char *args)
|
||
{
|
||
char *user;
|
||
char *nick;
|
||
|
||
char *passwd = NULL;
|
||
char *filename = NULL;
|
||
char *port = NULL;
|
||
int tdcc = 0;
|
||
int blocksize = get_int_var(DCC_BLOCK_SIZE_VAR);
|
||
|
||
user = get_dcc_args(&args, &passwd, &port, &blocksize);
|
||
if (!user)
|
||
{
|
||
put_it("%s", convert_output_format("$G %RDCC%n You must supply a nickname for DCC send", NULL, NULL));
|
||
return;
|
||
}
|
||
if (!blocksize || blocksize > MAX_DCC_BLOCK_SIZE)
|
||
blocksize = get_int_var(DCC_BLOCK_SIZE_VAR);
|
||
|
||
if (command && *command == 'T')
|
||
tdcc = DCC_TDCC;
|
||
while ((nick = next_in_comma_list(user, &user)))
|
||
{
|
||
char *new_args;
|
||
if (!nick || !*nick)
|
||
break;
|
||
new_args = LOCAL_COPY(args);
|
||
while ((filename = new_next_arg(new_args, &new_args)))
|
||
{
|
||
if (!filename || !*filename)
|
||
break;
|
||
real_file_send(nick, filename, passwd, port, tdcc, DCC_FILEOFFER, blocksize);
|
||
}
|
||
doing_multi++;
|
||
}
|
||
doing_multi = 0;
|
||
}
|
||
|
||
void BX_dcc_resend(char *command, char *args)
|
||
{
|
||
char *user;
|
||
char *nick;
|
||
|
||
char *passwd = NULL;
|
||
char *filename = NULL;
|
||
char *port = NULL;
|
||
int tdcc = 0;
|
||
int blocksize = get_int_var(DCC_BLOCK_SIZE_VAR);
|
||
|
||
user = get_dcc_args(&args, &passwd, &port, &blocksize);
|
||
if (!user)
|
||
{
|
||
put_it("%s", convert_output_format("$G %RDCC%n You must supply a nickname for DCC resend", NULL, NULL));
|
||
return;
|
||
}
|
||
if (!blocksize || blocksize > MAX_DCC_BLOCK_SIZE)
|
||
blocksize = get_int_var(DCC_BLOCK_SIZE_VAR);
|
||
|
||
if (command && *command == 'T')
|
||
tdcc = DCC_TDCC;
|
||
while ((nick = next_in_comma_list(user, &user)))
|
||
{
|
||
char *new_args;
|
||
if (!nick || !*nick)
|
||
break;
|
||
new_args = LOCAL_COPY(args);
|
||
while ((filename = new_next_arg(new_args, &new_args)))
|
||
{
|
||
if (!filename || !*filename)
|
||
break;
|
||
real_file_send(nick, filename, passwd, port, tdcc, DCC_REFILEOFFER, blocksize);
|
||
}
|
||
doing_multi++;
|
||
}
|
||
doing_multi = 0;
|
||
}
|
||
|
||
|
||
|
||
void start_dcc_get(int snum)
|
||
{
|
||
SocketList *s = get_socket(snum);
|
||
DCC_int *n = s->info;
|
||
int bytes_read;
|
||
char buffer[MAX_DCC_BLOCK_SIZE+1];
|
||
int err;
|
||
|
||
set_display_target(NULL, LOG_DCC);
|
||
bytes_read = read(snum, buffer, MAX_DCC_BLOCK_SIZE);
|
||
switch(bytes_read)
|
||
{
|
||
case -1:
|
||
erase_dcc_info(snum, 1, "%s", convert_output_format("$G %RDCC get to $0 lost: Remote peer closed connection", "%s", s->server));
|
||
close_socketread(snum);
|
||
return;
|
||
case 0:
|
||
close_dcc_file(snum);
|
||
return;
|
||
}
|
||
my_decrypt(buffer, bytes_read, n->encrypt);
|
||
err = write(n->file, buffer, bytes_read);
|
||
if (err == -1)
|
||
{
|
||
erase_dcc_info(snum, 1, "write to local file failed");
|
||
reset_display_target();
|
||
close_socketread(snum);
|
||
return;
|
||
}
|
||
n->bytes_read += bytes_read;
|
||
n->packets = n->bytes_read / n->blocksize;
|
||
{
|
||
u_32int_t bytes;
|
||
bytes = htonl(n->bytes_read);
|
||
send(snum, (char *)&bytes, sizeof(u_32int_t), 0);
|
||
}
|
||
if (n->filesize)
|
||
{
|
||
if (n->bytes_read + n->transfer_orders.byteoffset > n->filesize)
|
||
{
|
||
put_it("%s", convert_output_format("$G %RDCC%n Warning: incoming file is larger than the handshake said", NULL, NULL));
|
||
put_it("%s", convert_output_format("$G %RDCC%n Warning: GET: closing connection", NULL, NULL));
|
||
erase_dcc_info(snum, 1, NULL);
|
||
close_socketread(snum);
|
||
}
|
||
else if ((n->bytes_read + n->transfer_orders.byteoffset) == n->filesize)
|
||
{
|
||
close_dcc_file(snum);
|
||
reset_display_target();
|
||
return;
|
||
}
|
||
if (!(n->packets % 10))
|
||
{
|
||
update_transfer();
|
||
if (!(n->packets % 20))
|
||
update_all_status(current_window, NULL, 0);
|
||
}
|
||
}
|
||
reset_display_target();
|
||
}
|
||
|
||
void real_get_file(char *user, char *filename, char *port, char *passwd, int tdcc, int blocksize)
|
||
{
|
||
DCC_int *new = NULL;
|
||
SocketList *s = NULL;
|
||
DCC_List *s1 = NULL;
|
||
char *nick;
|
||
|
||
while ((nick = next_in_comma_list(user, &user)))
|
||
{
|
||
if (!nick || !*nick)
|
||
break;
|
||
|
||
if ((s1 = find_dcc_pending(nick, filename, NULL, DCC_FILEREAD, 0, -1)))
|
||
{
|
||
new = (DCC_int *)s1->sock.info;
|
||
if ((s = find_dcc(nick, new->filename, NULL, DCC_FILEREAD, 1, -1, -1)))
|
||
{
|
||
put_it("%s", convert_output_format("$G %RDCC%n A previous DCC GET from $0 exists", "%s", nick));
|
||
continue;
|
||
}
|
||
}
|
||
else
|
||
continue;
|
||
if ((new = dcc_create(nick, filename, passwd, 0, port? atol(port) : 0, DCC_FILEREAD, (tdcc?DCC_TDCC:0) | DCC_TWOCLIENTS|DCC_OFFER, start_dcc_get)))
|
||
{
|
||
char *tmp = NULL;
|
||
char *fullname = NULL;
|
||
new->blocksize = blocksize;
|
||
if (get_string_var(DCC_DLDIR_VAR))
|
||
malloc_sprintf(&tmp, "%s/%s", get_string_var(DCC_DLDIR_VAR), new->filename);
|
||
else
|
||
tmp = m_strdup(new->filename);
|
||
if (!(fullname = expand_twiddle(tmp)))
|
||
malloc_strcpy(&fullname, tmp);
|
||
#if defined(WINNT) || defined(__EMX__)
|
||
convert_unix(fullname);
|
||
#endif
|
||
s = find_dcc(nick, filename, NULL, DCC_FILEREAD, 1, -1, -1);
|
||
if ((new->file = open(fullname, O_WRONLY | O_TRUNC | O_CREAT | O_BINARY, 0644)) == -1)
|
||
{
|
||
erase_dcc_info(s->is_read, 1, "%s", convert_output_format("$G %RDCC%n Unable to open $0: $1-", "%s %s", fullname, errno?strerror(errno):"Unknown"));
|
||
close_socketread(s->is_read);
|
||
}
|
||
new_free(&fullname);
|
||
new_free(&tmp);
|
||
|
||
}
|
||
doing_multi++;
|
||
}
|
||
}
|
||
|
||
void dcc_getfile(char *command, char *args)
|
||
{
|
||
char *user;
|
||
|
||
char *passwd = NULL;
|
||
char *filename = NULL;
|
||
char *port = NULL;
|
||
int tdcc = 0;
|
||
int blocksize = get_int_var(DCC_BLOCK_SIZE_VAR);
|
||
|
||
user = get_dcc_args(&args, &passwd, &port, &blocksize);
|
||
if (!user)
|
||
{
|
||
put_it("%s", convert_output_format("$G %RDCC%n You must supply a nickname for DCC get", NULL, NULL));
|
||
return;
|
||
}
|
||
if (!blocksize || blocksize > MAX_DCC_BLOCK_SIZE)
|
||
blocksize = get_int_var(DCC_BLOCK_SIZE_VAR);
|
||
if (command && *command == 'T')
|
||
tdcc = 1;
|
||
|
||
if (!args || !*args)
|
||
real_get_file(user, NULL, port, passwd, tdcc, blocksize);
|
||
else
|
||
{
|
||
char *u = alloca(strlen(user)+1);
|
||
while ((filename = next_in_comma_list(args, &args)))
|
||
{
|
||
if (!filename || !*filename)
|
||
break;
|
||
strcpy(u, user);
|
||
real_get_file(u, filename, port, passwd, tdcc, blocksize);
|
||
}
|
||
}
|
||
doing_multi = 0;
|
||
}
|
||
|
||
void real_reget_file(char *user, char *filename, char *port, char *passwd, int tdcc, int blocksize)
|
||
{
|
||
DCC_int *new = NULL;
|
||
SocketList *s = NULL;
|
||
char *nick;
|
||
|
||
while ((nick = next_in_comma_list(user, &user)))
|
||
{
|
||
char *tmp = NULL;
|
||
char *fullname = NULL;
|
||
DCC_List *s1 = NULL;
|
||
if (!nick || !*nick)
|
||
break;
|
||
|
||
if ((s1 = find_dcc_pending(nick, filename, NULL, DCC_REFILEREAD, 0, -1)))
|
||
{
|
||
new = (DCC_int *)s1->sock.info;
|
||
if ((s = find_dcc(nick, new->filename, NULL, DCC_REFILEREAD, 1, -1, -1)))
|
||
{
|
||
put_it("%s", convert_output_format("$G %RDCC%n A previous DCC REGET from $0 exists", "%s", nick));
|
||
continue;
|
||
}
|
||
}
|
||
else
|
||
continue;
|
||
if (get_string_var(DCC_DLDIR_VAR))
|
||
malloc_sprintf(&tmp, "%s/%s", get_string_var(DCC_DLDIR_VAR), new->filename);
|
||
else
|
||
tmp = m_strdup(new->filename);
|
||
if (!(fullname = expand_twiddle(tmp)))
|
||
malloc_strcpy(&fullname, tmp);
|
||
if ((new->file = open(fullname, O_WRONLY | O_CREAT | O_BINARY, 0644)) != -1)
|
||
{
|
||
if ((new = dcc_create(nick, new->filename, passwd, 0, port? atol(port) : 0, DCC_REFILEREAD, (tdcc?DCC_TDCC:0) | DCC_TWOCLIENTS|DCC_OFFER, start_dcc_get)))
|
||
new->blocksize = blocksize;
|
||
}
|
||
new_free(&fullname);
|
||
new_free(&tmp);
|
||
doing_multi++;
|
||
}
|
||
}
|
||
|
||
void dcc_regetfile(char *command, char *args)
|
||
{
|
||
char *user;
|
||
char *passwd = NULL;
|
||
char *filename = NULL;
|
||
char *port = NULL;
|
||
int tdcc = 0;
|
||
int blocksize = get_int_var(DCC_BLOCK_SIZE_VAR);
|
||
|
||
user = get_dcc_args(&args, &passwd, &port, &blocksize);
|
||
if (!user)
|
||
{
|
||
put_it("%s", convert_output_format("$G %RDCC%n You must supply a nickname for DCC reget", NULL, NULL));
|
||
return;
|
||
}
|
||
if (!blocksize || blocksize > MAX_DCC_BLOCK_SIZE)
|
||
blocksize = get_int_var(DCC_BLOCK_SIZE_VAR);
|
||
if (command && *command == 'T')
|
||
tdcc = 1;
|
||
if (!args || !*args)
|
||
real_reget_file(user, NULL, port, passwd, tdcc, blocksize);
|
||
else
|
||
{
|
||
char *u = alloca(strlen(user)+1);
|
||
while ((filename = next_in_comma_list(args, &args)))
|
||
{
|
||
if (!filename || !*filename)
|
||
break;
|
||
strcpy(u, user);
|
||
real_reget_file(u, filename, port, passwd, tdcc, blocksize);
|
||
}
|
||
}
|
||
doing_multi = 0;
|
||
}
|
||
|
||
static char *get_bar_percent(int percent)
|
||
{
|
||
#ifdef ONLY_STD_CHARS
|
||
static char *_dcc_offer[12] = {"%K-.........%n", /* 0 */
|
||
"%K-.........%n", /* 10 */
|
||
"%K-=........%n", /* 20 */
|
||
"%K-=*.......%n", /* 30 */
|
||
"%K-=*%1%K=%0%K......%n", /* 40 */
|
||
"%K-=*%1%K=-%0%K.....%n", /* 50 */
|
||
"%K-=*%1%K=-.%0%K....%n", /* 60 */
|
||
"%K-=*%1%K=-. %0%K...%n", /* 70 */
|
||
"%K-=*%1%K=-. %R.%0%K..%n", /* 80 */
|
||
"%K-=*%1%K=-. %R.-%0%K.%n", /* 90 */
|
||
"%K-=*%1%K=-. %R.-=%n", /* 100 */
|
||
empty_string};
|
||
#else
|
||
static char *_dcc_offer[12] = {"%K<><4B><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>%n", /* 0 */
|
||
"%K<><4B><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>%n", /* 10 */
|
||
"%K<><4B><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>%n", /* 20 */
|
||
"%K<><4B>۰<EFBFBD><DBB0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>%n", /* 30 */
|
||
"%K<><4B><EFBFBD>%1%K<>%0%K<><4B><EFBFBD><EFBFBD><EFBFBD><EFBFBD>%n", /* 40 */
|
||
"%K<><4B><EFBFBD>%1%K<><4B>%0%K<><4B><EFBFBD><EFBFBD><EFBFBD>%n", /* 50 */
|
||
"%K<><4B><EFBFBD>%1%K<><4B><EFBFBD>%0%K<><4B><EFBFBD><EFBFBD>%n", /* 60 */
|
||
"%K<><4B><EFBFBD>%1%K<><4B><EFBFBD><EFBFBD>%0%K<><4B><EFBFBD>%n", /* 70 */
|
||
"%K<><4B><EFBFBD>%1%K<><4B><EFBFBD><EFBFBD>%R<>%0%K<><4B>%n", /* 80 */
|
||
"%K<><4B><EFBFBD>%1%K<><4B><EFBFBD><EFBFBD>%R<><52>%0%K<>%n", /* 90 */
|
||
"%K<><4B><EFBFBD>%1%K<><4B><EFBFBD><EFBFBD>%R<><52><EFBFBD>%n", /* 100 */
|
||
empty_string};
|
||
#endif
|
||
if (percent <= 100)
|
||
return _dcc_offer[percent];
|
||
return empty_string;
|
||
}
|
||
|
||
|
||
void dcc_glist(char *command, char *args)
|
||
{
|
||
char *dformat =
|
||
"#$[3]0 $[6]1%Y$2%n $[11]3 $[25]4 $[7]5 $6-";
|
||
char *d1format =
|
||
"#$[3]0 $[6]1%Y$2%n $[11]3 $4 $[7]5 $[11]6 $[7]7 $8-";
|
||
char *c1format =
|
||
"#$[3]0 $[6]1%Y$2%n $[11]3 $4 $[-4]5 $[-4]6 $[-3]7 $[-3]8 $[7]9 $10";
|
||
|
||
int i;
|
||
DCC_int *n = NULL;
|
||
SocketList *s;
|
||
int type;
|
||
int tdcc = 0;
|
||
char *status;
|
||
int count = 0;
|
||
DCC_List *c;
|
||
char stats[80];
|
||
char kilobytes[20];
|
||
double barsize = 0.0;
|
||
char spec[BIG_BUFFER_SIZE];
|
||
char *filename, *p;
|
||
|
||
reset_display_target();
|
||
#if !defined(WINNT) && !defined(__EMX__)
|
||
charset_ibmpc();
|
||
#endif
|
||
if (do_hook(DCC_HEADER_LIST, "%s %s %s %s %s %s %s", "Dnum","Type","Nick", "Status", "K/s", "File","Encrypt"))
|
||
{
|
||
#ifdef ONLY_STD_CHARS
|
||
put_it("%s", convert_output_format("%G# %W|%n %GT%gype %W|%n %GN%gick %W|%n %GP%gercent %GC%gomplete %W|%n %GK%g/s %W|%n %GF%gile", NULL, NULL));
|
||
put_it("%s", convert_output_format("%W------------------------------------------------------------------------------", NULL, NULL));
|
||
#else
|
||
put_it("%s", convert_output_format("%G# %W<>%n %GT%gype %W<>%n %GN%gick %W<>%n %GP%gercent %GC%gomplete %W<>%n %GK%g/s %W<>%n %GF%gile", NULL, NULL));
|
||
put_it("%s", convert_output_format("%K<><4B>%n<>%W<>%n<>%K<><4B><EFBFBD><EFBFBD><EFBFBD>%n<>%W<>%n<>%K<><4B><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>%n<>%W<>%n<>%K<><4B><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>%n<>%W<>%n<>%K<><4B><EFBFBD><EFBFBD><EFBFBD>%n<>%W<>%n<>%K<><4B><EFBFBD><EFBFBD><EFBFBD>%n<>%W<>%n<>%K<><4B><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>", NULL, NULL));
|
||
#endif
|
||
}
|
||
for (c = pending_dcc; c; c = c->next, count++)
|
||
{
|
||
char local_type[30];
|
||
char *filename, *p;
|
||
s = &c->sock;
|
||
type = c->sock.flags & DCC_TYPES;
|
||
tdcc = c->sock.flags & DCC_TDCC;
|
||
n = (DCC_int *)c->sock.info;
|
||
*local_type = 0;
|
||
if (tdcc)
|
||
strcpy(local_type, "T");
|
||
strcat(local_type, dcc_types[type]->name);
|
||
filename = LOCAL_COPY(n->filename);
|
||
|
||
p = filename;
|
||
while ((p = strchr(p, ' ')))
|
||
*p = '_';
|
||
|
||
if (do_hook(DCC_STAT_LIST, "%d %s %s %s %s %s %s",
|
||
n->dccnum, local_type,
|
||
c->sock.server,
|
||
s->flags & DCC_OFFER ? "Offer" :
|
||
s->flags & DCC_WAIT ? "Wait" :
|
||
s->flags & DCC_ACTIVE ? "Active" :
|
||
"Unknown",
|
||
"N/A", strip_path(filename), n->encrypt?"E":empty_string))
|
||
{
|
||
put_it("%s", convert_output_format(dformat, "%d %s %s %s %s %s %s",
|
||
n->dccnum,
|
||
local_type,
|
||
n->encrypt ? "E" : "<EFBFBD>",
|
||
c->sock.server,
|
||
|
||
s->flags & DCC_OFFER ? "Offer " :
|
||
s->flags & DCC_WAIT ? "Wait " :
|
||
s->flags & DCC_ACTIVE ? "Active" :
|
||
"Unknown",
|
||
"N/A",
|
||
strip_path(filename)));
|
||
}
|
||
count++;
|
||
}
|
||
for (i = 0; i < get_max_fd() + 1; i++, count++)
|
||
{
|
||
double perc = 0.0;
|
||
double bytes = 0.0;
|
||
char local_type[30];
|
||
time_t xtime;
|
||
int seconds = 0, minutes = 0;
|
||
int iperc = 0;
|
||
int size = 0;
|
||
if (!check_dcc_socket(i))
|
||
continue;
|
||
s = get_socket(i);
|
||
n = (DCC_int *)s->info;
|
||
type = s->flags & DCC_TYPES;
|
||
tdcc = s->flags & DCC_TDCC;
|
||
xtime = now - n->starttime.tv_sec;
|
||
|
||
if (xtime <= 0)
|
||
xtime = 1;
|
||
*local_type = 0;
|
||
if (tdcc)
|
||
strcpy(local_type, "T");
|
||
strcat(local_type, dcc_types[type]->name);
|
||
|
||
filename = LOCAL_COPY(n->filename);
|
||
p = filename;
|
||
while ((p = strchr(p, ' ')))
|
||
*p = '_';
|
||
|
||
if (((type == DCC_CHAT) || (type == DCC_RAW) || (type == DCC_BOTMODE) || (type == DCC_FTPOPEN)))
|
||
{
|
||
if (!(s->flags & DCC_ACTIVE))
|
||
xtime = now - s->time;
|
||
if (do_hook(DCC_STAT_LIST, "%d %s %s %s %s %s %s",
|
||
n->dccnum, local_type, s->server,
|
||
s->flags & DCC_OFFER ? "Offer " :
|
||
s->flags & DCC_WAIT ? "Wait " :
|
||
s->flags & DCC_ACTIVE ?"Active" :
|
||
"Unknown",
|
||
"N/A", strip_path(filename), n->encrypt?"E":empty_string))
|
||
put_it("%s", convert_output_format(c1format, "%d %s %s %s %s %s %s %s",
|
||
n->dccnum,
|
||
local_type,
|
||
n->encrypt ? "E" : "<EFBFBD>",
|
||
s->server,
|
||
s->flags & DCC_OFFER ? "Offer" :
|
||
s->flags & DCC_WAIT ? "Wait" :
|
||
s->flags & DCC_ACTIVE ? "Active" :
|
||
"Unknown",
|
||
convert_time(xtime),
|
||
"N/A",
|
||
strip_path(filename)));
|
||
}
|
||
else
|
||
{
|
||
if (!(s->flags & DCC_ACTIVE))
|
||
{
|
||
if (do_hook(DCC_STAT_LIST, "%d %s %s %s %s %s %s",
|
||
n->dccnum, local_type, s->server,
|
||
s->flags & DCC_OFFER ? "Offer " :
|
||
s->flags & DCC_WAIT ? "Wait " :
|
||
s->flags & DCC_ACTIVE ?"Active" :
|
||
"Unknown",
|
||
"N/A", strip_path(filename), n->encrypt?"E":empty_string))
|
||
put_it("%s", convert_output_format(dformat, "%d %s %s %s %s %s %s",
|
||
n->dccnum,
|
||
local_type,
|
||
n->encrypt ? "E" : "<EFBFBD>",
|
||
s->server,
|
||
s->flags & DCC_OFFER ? "Offer" :
|
||
s->flags & DCC_WAIT ? "Wait" :
|
||
s->flags & DCC_ACTIVE ? "Active" :
|
||
"Unknown",
|
||
"N/A",
|
||
strip_path(filename)));
|
||
continue;
|
||
}
|
||
|
||
|
||
bytes = n->bytes_read + n->bytes_sent;
|
||
|
||
sprintf(kilobytes, "%2.4g", bytes / 1024.0 / xtime);
|
||
|
||
type = s->flags & DCC_TYPES;
|
||
tdcc = s->flags & DCC_TDCC;
|
||
status = s->flags & DCC_OFFER ? "Offer":s->flags & DCC_ACTIVE ? "Active": s->flags&DCC_WAIT?"Wait":"Unknown";
|
||
if ((bytes >= 0) && (s->flags & DCC_ACTIVE))
|
||
{
|
||
if (bytes && (n->filesize - n->transfer_orders.byteoffset) >= bytes)
|
||
{
|
||
perc = (100.0 * ((double)bytes + n->transfer_orders.byteoffset) / (double)(n->filesize));
|
||
if ( perc > 100.0) perc = 100.0;
|
||
else if (perc < 0.0) perc = 0.0;
|
||
seconds = (int) (( (n->filesize - n->transfer_orders.byteoffset - bytes) / (bytes / xtime)) + 0.5);
|
||
minutes = seconds / 60;
|
||
seconds = seconds - (minutes * 60);
|
||
if (minutes > 999) {
|
||
minutes = 999;
|
||
seconds = 59;
|
||
}
|
||
if (seconds < 0) seconds = 0;
|
||
} else
|
||
seconds = minutes = perc = 0;
|
||
|
||
iperc = ((int)perc) / 10;
|
||
barsize = ((double) (n->filesize)) / (double) BAR_LENGTH;
|
||
|
||
size = (int) ((double) bytes / (double)barsize);
|
||
|
||
if (n->filesize == 0)
|
||
size = BAR_LENGTH;
|
||
sprintf(stats, "%4.1f", perc);
|
||
if (!get_int_var(DCC_BAR_TYPE_VAR))
|
||
sprintf(spec, "%s %s%s %02d:%02d", get_bar_percent(iperc), stats, "%%", minutes, seconds);
|
||
else
|
||
sprintf(spec, "%s%s %02d:%02d", stats, "%%", minutes, seconds);
|
||
|
||
strcpy(spec, convert_output_format(spec, NULL, NULL));
|
||
}
|
||
if (do_hook(DCC_STATF_LIST, "%d %s %s %s %s %s %s",
|
||
n->dccnum, local_type, s->server, status,
|
||
kilobytes, strip_path(filename),
|
||
n->encrypt?"E":empty_string))
|
||
{
|
||
char *s1;
|
||
if (!get_int_var(DCC_BAR_TYPE_VAR))
|
||
s1 = d1format;
|
||
else
|
||
s1 = dformat;
|
||
|
||
put_it("%s", convert_output_format(s1, "%d %s %s %s %s %s %s",
|
||
n->dccnum, local_type, n->encrypt ? "E":"<EFBFBD>",
|
||
s->server, spec, kilobytes,
|
||
strip_path(filename)));
|
||
}
|
||
|
||
/* This prints the second DCC stat line, if DCC_BAR_TYPE is non-zero. */
|
||
if (do_hook(DCC_STATF1_LIST, "%s %lu %lu %d %d", stats, (unsigned long)bytes, (unsigned long)n->filesize, minutes, seconds))
|
||
{
|
||
char *stat_ptr, *spec_ptr;
|
||
if (!get_int_var(DCC_BAR_TYPE_VAR))
|
||
continue;
|
||
|
||
snprintf(stats, sizeof stats, "%4.1f%% (%lu of %lu bytes)",
|
||
perc, (unsigned long)bytes, (unsigned long)n->filesize);
|
||
snprintf(spec, sizeof spec, BOLD_TOG_STR "["
|
||
REV_TOG_STR "%*.*s" REV_TOG_STR "%*.*s]" BOLD_TOG_STR
|
||
" ETA " BOLD_TOG_STR "%02d:%02d",
|
||
size, size, space, BAR_LENGTH - size, BAR_LENGTH - size,
|
||
space, minutes, seconds);
|
||
spec_ptr = spec + 3 + (BAR_LENGTH - strlen(stats)) / 2;
|
||
for (stat_ptr = stats; *stat_ptr && *spec_ptr; spec_ptr++)
|
||
{
|
||
if (*spec_ptr != REV_TOG && *spec_ptr != BOLD_TOG)
|
||
*spec_ptr = *stat_ptr++;
|
||
}
|
||
put_it("%s", spec);
|
||
}
|
||
}
|
||
}
|
||
#if !defined(WINNT) && !defined(__EMX__)
|
||
#if defined(LATIN1)
|
||
charset_lat1();
|
||
#elif defined(CHARSET_CUSTOM)
|
||
charset_cst();
|
||
#endif
|
||
#endif
|
||
if (!count)
|
||
bitchsay("No active/pending dcc's");
|
||
else if (do_hook(DCC_POST_LIST, "%s %s %s %s %s %s %s", "DCCnum","Type","Nick", "Status", "K/s", "File","Encrypt"))
|
||
;
|
||
}
|
||
|
||
unsigned char byte_order_test(void)
|
||
{
|
||
unsigned short test = DCC_PACKETID;
|
||
|
||
if (*((unsigned char *)&test) == ((DCC_PACKETID & 0xff00) >> 8))
|
||
return 0;
|
||
|
||
if (*((unsigned char *)&test) == (DCC_PACKETID & 0x00ff))
|
||
return 1;
|
||
return 0;
|
||
}
|
||
|
||
int BX_get_active_count(void)
|
||
{
|
||
int active = 0;
|
||
register int i;
|
||
register SocketList *s;
|
||
register int type;
|
||
for (i = 0; i < get_max_fd() + 1; i++)
|
||
{
|
||
if (check_dcc_socket(i))
|
||
{
|
||
s = get_socket(i);
|
||
type = s->flags & DCC_TYPES;
|
||
if (type == DCC_REFILEREAD || type == DCC_FTPGET ||
|
||
type == DCC_FILEREAD || type == DCC_FILEOFFER ||
|
||
type == DCC_REFILEOFFER)
|
||
active++;
|
||
}
|
||
}
|
||
return active;
|
||
}
|
||
|
||
#if 0
|
||
void dcc_renumber_active(void)
|
||
{
|
||
register int i;
|
||
SocketList *s;
|
||
DCC_int *n;
|
||
int j = 1;
|
||
|
||
for (i = 0; i < get_max_fd() + 1; i++)
|
||
{
|
||
if (check_dcc_socket(i))
|
||
{
|
||
s = get_socket(i);
|
||
n = (DCC_int *)s->info;
|
||
n->dccnum = j++;
|
||
}
|
||
}
|
||
dcc_count = j;
|
||
}
|
||
#endif
|
||
|
||
int check_dcc_list (char *name)
|
||
{
|
||
int do_it = 0;
|
||
register int i = 0;
|
||
for (i = 0; i < get_max_fd() + 1; i++)
|
||
{
|
||
if (check_dcc_socket(i))
|
||
{
|
||
SocketList *s;
|
||
s = get_socket(i);
|
||
if (s->server && !my_stricmp(name, s->server) && !(s->flags & DCC_ACTIVE))
|
||
{
|
||
switch (s->flags & DCC_TYPES)
|
||
{
|
||
case DCC_FILEOFFER:
|
||
case DCC_FILEREAD:
|
||
case DCC_REFILEOFFER:
|
||
case DCC_REFILEREAD:
|
||
do_it++;
|
||
erase_dcc_info(i, 0, NULL);
|
||
close_socketread(i);
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return do_it;
|
||
}
|
||
|
||
|
||
void update_transfer(void)
|
||
{
|
||
register unsigned count= 0;
|
||
double perc = 0.0;
|
||
register int i = 0;
|
||
/* char temp_str[60];*/
|
||
double bytes;
|
||
SocketList *s;
|
||
DCC_int *n;
|
||
unsigned long flags;
|
||
char transfer_buffer[BIG_BUFFER_SIZE];
|
||
char *c;
|
||
|
||
*transfer_buffer = 0;
|
||
for (i = 0; i < get_max_fd() + 1 ; i++)
|
||
{
|
||
if (!check_dcc_socket(i))
|
||
continue;
|
||
s = get_socket(i);
|
||
flags = s->flags & DCC_TYPES;
|
||
if ((s->flags & DCC_OFFER) || (s->flags & DCC_WAIT) || (flags == DCC_RAW) || (flags == DCC_RAW_LISTEN) || (flags == DCC_CHAT) || (flags == DCC_BOTMODE) || (flags == DCC_FTPOPEN))
|
||
continue;
|
||
n = (DCC_int *)s->info;
|
||
bytes = n->bytes_read + n->bytes_sent + n->transfer_orders.byteoffset;
|
||
if (bytes >= 0)
|
||
{
|
||
if (n->filesize >= bytes && (n->filesize > 0))
|
||
{
|
||
perc = (100.0 * ((double)bytes) / (double)(n->filesize));
|
||
if ( perc > 100.0) perc = 100.0;
|
||
else if (perc < 0.0) perc = 0.0;
|
||
|
||
}
|
||
strmopencat(transfer_buffer, BIG_BUFFER_SIZE, ltoa((int)perc), "% ", NULL);
|
||
#if 0
|
||
sprintf(temp_str,"%d%% ",(int) perc);
|
||
strcat(transfer_buffer,temp_str);
|
||
#endif
|
||
}
|
||
if (count++ > 9)
|
||
break;
|
||
}
|
||
if (*(c = transfer_buffer))
|
||
chop(transfer_buffer, 1);
|
||
do_hook(DCC_UPDATE_LIST, "%s", *c ? c : empty_string);
|
||
if (*c)
|
||
{
|
||
while ((c = strchr(c, ' '))) *c = ',';
|
||
}
|
||
if (count)
|
||
{
|
||
/* chop(transfer_buffer, 1);*/
|
||
if (fget_string_var(FORMAT_DCC_FSET))
|
||
{
|
||
sprintf(DCC_current_transfer_buffer, "%s", convert_output_format(fget_string_var(FORMAT_DCC_FSET), "%s", transfer_buffer));
|
||
chop(DCC_current_transfer_buffer, 4);
|
||
}
|
||
else
|
||
sprintf(DCC_current_transfer_buffer, "[%s]", transfer_buffer);
|
||
}
|
||
else
|
||
*DCC_current_transfer_buffer = 0;
|
||
}
|
||
|
||
|
||
/*
|
||
* returns the string without the path (if present) Also
|
||
* converts filename from " " to _
|
||
*/
|
||
static char * strip_path(char *str)
|
||
{
|
||
char *ptr;
|
||
#if 0
|
||
char *q;
|
||
|
||
q = str;
|
||
while ((q = strchr(q, ' ')))
|
||
*q = '_';
|
||
#endif
|
||
if (dcc_paths)
|
||
return str;
|
||
ptr = strrchr(str,'/');
|
||
if (ptr == NULL)
|
||
return str;
|
||
else
|
||
return ptr+1;
|
||
}
|
||
|
||
void dcc_show_active(char *command, char * args)
|
||
{
|
||
put_it("%s", convert_output_format("$G %RDCC%n DCC Active = \002$0\002, Limit = \002$1\002",
|
||
"%d %d", get_active_count(), get_int_var(DCC_SEND_LIMIT_VAR)));
|
||
}
|
||
|
||
void dcc_set_quiet(char *command, char *args )
|
||
{
|
||
dcc_quiet ^=1;
|
||
put_it("%s", convert_output_format("$G %RDCC%n DCC Quiet = \002$0\002", "%s", on_off(dcc_quiet)));
|
||
}
|
||
|
||
void dcc_set_paths(char *command, char *args)
|
||
{
|
||
dcc_paths ^= 1;
|
||
put_it("%s", convert_output_format("$G %RDCC%n DCC paths is now \002$0\002", "%s", on_off(dcc_paths)));
|
||
}
|
||
|
||
void dcc_tog_rename(char *command, char *args)
|
||
{
|
||
int arename = get_int_var(DCC_AUTORENAME_VAR);
|
||
arename ^= 1;
|
||
set_int_var(DCC_AUTORENAME_VAR, arename);
|
||
put_it("%s", convert_output_format("$G %RDCC%n DCC auto rename is now \002$0\002", "%s", on_off(get_int_var(DCC_AUTORENAME_VAR))));
|
||
}
|
||
|
||
void dcc_tog_resume(char *command, char *args)
|
||
{
|
||
int arename = get_int_var(DCC_AUTORESUME_VAR);
|
||
arename ^= 1;
|
||
set_int_var(DCC_AUTORESUME_VAR, arename);
|
||
put_it("%s", convert_output_format("$G %RDCC%n DCC auto resume is now \002$0\002", "%s", on_off(get_int_var(DCC_AUTORESUME_VAR))));
|
||
}
|
||
|
||
void dcc_overwrite_toggle(char *command, char *args)
|
||
{
|
||
dcc_overwrite_var ^= 1;
|
||
put_it("%s", convert_output_format(" DCC overwrite is now \002$0\002", "%s", on_off(dcc_overwrite_var)));
|
||
}
|
||
|
||
void dcc_tog_auto(char *command, char *args)
|
||
{
|
||
int dcc_auto = get_int_var(DCC_AUTOGET_VAR);
|
||
dcc_auto ^= 1;
|
||
set_int_var(DCC_AUTOGET_VAR, dcc_auto);
|
||
put_it("%s", convert_output_format(" DCC autoget is now \002$0\002", "%s", on_off(dcc_auto)));
|
||
}
|
||
|
||
void dcc_stats (char *command, char *unused)
|
||
{
|
||
char max_rate_in[20];
|
||
char min_rate_in[20];
|
||
char max_rate_out[20];
|
||
char min_rate_out[20];
|
||
|
||
sprintf(max_rate_in, "%6.2f", dcc_max_rate_in/1024.0);
|
||
sprintf(min_rate_in, "%6.2f", ((dcc_min_rate_in != DBL_MAX )?dcc_min_rate_in/1024.0: 0.0));
|
||
sprintf(max_rate_out, "%6.2f", dcc_max_rate_out/1024.0);
|
||
sprintf(min_rate_out, "%6.2f", ((dcc_min_rate_out != DBL_MAX) ? dcc_min_rate_out/1024.0: 0.0));
|
||
if (do_hook(DCC_TRANSFER_STAT_LIST, "%lu %s %s %lu %s %s %lu %u %u %s %s %s %s",
|
||
(unsigned long)dcc_bytes_in, max_rate_in, min_rate_in,
|
||
(unsigned long)dcc_bytes_out, max_rate_out, min_rate_out,
|
||
(unsigned long)(send_count_stat+get_count_stat),
|
||
get_active_count(), get_int_var(DCC_SEND_LIMIT_VAR),
|
||
on_off(get_int_var(DCC_AUTOGET_VAR)), on_off(dcc_paths),
|
||
on_off(dcc_quiet), on_off(dcc_overwrite_var)))
|
||
{
|
||
char in[50], out[50];
|
||
sprintf(in, "%3.2f%s", _GMKv(dcc_bytes_in), _GMKs(dcc_bytes_in));
|
||
sprintf(out, "%3.2f%s", _GMKv(dcc_bytes_out), _GMKs(dcc_bytes_out));
|
||
|
||
#ifdef ONLY_CTD_CHARS
|
||
put_it("%s",convert_output_format(" %G========================%K[%Cdcc transfer stats%K]%G=======================", NULL));
|
||
put_it("%s",convert_output_format(" %G| |", NULL));
|
||
put_it("%s",convert_output_format(" %G|%g|-%K[%Cx%cferd %Ci%cn%K]%g-|-%K[%Cx%cferd %Co%cut%K]%g-|-%K[%Ct%cotal %Cf%ciles%K]%g-|-%K[%Ca%cctive%K]%g-|-[%Cl%cimit%K]%g-|%G|", NULL));
|
||
put_it("%s",convert_output_format(" %G|%g| %W$[-10]0 %g| %W$[-10]1 %g| %W$[-10]2 %g| %W$[-8]3 %g| %W$[-7]4 %g|%G|", "%s %s %d %d %d", in, out,send_count_stat+get_count_stat,get_active_count(),get_int_var(DCC_SEND_LIMIT_VAR)));
|
||
put_it("%s",convert_output_format(" %G|%g|------------|-------------|---------------|----------|---------|%G|", NULL));
|
||
put_it("%s",convert_output_format(" %G| |", NULL));
|
||
put_it("%s",convert_output_format(" %g|----%K[%Ci%cn %Cs%ctats%K]%g---|---%K[%Co%cut %Cs%ctats%K]%g---|----------%K[%Ct%coggles%K]%g----------|", NULL));
|
||
put_it("%s",convert_output_format(" %g| %Cm%nax: %W$[-6]0%n%Rkb/s %g| %Cm%nax: %W$[-6]1%n%Rkb/s %g| %Ca%nutoget: %W$[-3]2%n %Cp%naths: %W$[-3]3 %g|", "%s %s %s %s", max_rate_in, max_rate_out, on_off(get_int_var(DCC_AUTOGET_VAR)),on_off(dcc_paths)));
|
||
put_it("%s",convert_output_format(" %g| %Cm%nin: %W$[-6]0%n%Rkb/s %g| %Cm%nin: %W$[-6]1%n%Rkb/s %g| %Co%nverwrite: %W$[-3]2%n %Cq%nuiet: %W$[-3]3 %g|", "%s %s %s %s", min_rate_in, min_rate_out, on_off(dcc_overwrite_var), on_off(dcc_quiet)));
|
||
put_it("%s",convert_output_format(" %g|-----------------|-----------------|-----------------------------|", NULL));
|
||
|
||
#else
|
||
|
||
put_it("%s",convert_output_format(" %G<><47><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>%K[%Cdcc transfer stats%K]%G<><47><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>", NULL));
|
||
put_it("%s",convert_output_format(" %G<> <20>", NULL));
|
||
put_it("%s",convert_output_format(" %G<>%g<><67>%K[%Cx%cferd %Ci%cn%K]%g<><67>-%K[%Cx%cferd %Co%cut%K]%gķ<67>%K[%Ct%cotal %Cf%ciles%K]%g<><67><EFBFBD>%K[%Ca%cctive%K]%gķ<67>[%Cl%cimit%K]%gķ%G<>", NULL));
|
||
put_it("%s",convert_output_format(" %G<>%g<> %W$[-10]0 %g<> %W$[-10]1 %g<> %W$[-10]2 %g<> %W$[-8]3 %g<> %W$[-7]4 %g<>%G<>", "%s %s %d %d %d", in, out,send_count_stat+get_count_stat,get_active_count(),get_int_var(DCC_SEND_LIMIT_VAR)));
|
||
put_it("%s",convert_output_format(" %G<>%g<><67><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ľ<EFBFBD><C4BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ľ<EFBFBD><C4BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ľ%G<>", NULL));
|
||
put_it("%s",convert_output_format(" %G<> <20>", NULL));
|
||
put_it("%s",convert_output_format(" %g<><67><EFBFBD><EFBFBD><EFBFBD>%K[%Ci%cn %Cs%ctats%K]%g<><67><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>%K[%Co%cut %Cs%ctats%K]%g<><67>ķ<EFBFBD><C4B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>%K[%Ct%coggles%K]%g<><67><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ķ", NULL));
|
||
put_it("%s",convert_output_format(" %g<> %Cm%nax: %W$[-6]0%n%Rkb/s %g<> %Cm%nax: %W$[-6]1%n%Rkb/s %g<> %Ca%nutoget: %W$[-3]2%n %Cp%naths: %W$[-3]3 %g<>", "%s %s %s %s", max_rate_in, max_rate_out, on_off(get_int_var(DCC_AUTOGET_VAR)),on_off(dcc_paths)));
|
||
put_it("%s",convert_output_format(" %g<> %Cm%nin: %W$[-6]0%n%Rkb/s %g<> %Cm%nin: %W$[-6]1%n%Rkb/s %g<> %Co%nverwrite: %W$[-3]2%n %Cq%nuiet: %W$[-3]3 %g<>", "%s %s %s %s", min_rate_in, min_rate_out, on_off(dcc_overwrite_var), on_off(dcc_quiet)));
|
||
put_it("%s",convert_output_format(" %g<><67><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ľ<EFBFBD><C4BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ľ", NULL));
|
||
|
||
#endif
|
||
|
||
}
|
||
}
|
||
|
||
/*
|
||
* only call this on dcc finish
|
||
*/
|
||
void dcc_update_stats (int snum)
|
||
{
|
||
time_t xtime;
|
||
SocketList *s;
|
||
DCC_int *n;
|
||
s = get_socket(snum);
|
||
if (!s || !(n = (DCC_int *)s->info))
|
||
return;
|
||
dcc_bytes_in += n->bytes_read;
|
||
dcc_bytes_out += n->bytes_sent;
|
||
xtime = time_since(&n->starttime);
|
||
|
||
if (xtime <= 0)
|
||
xtime = 1;
|
||
if (n->bytes_read)
|
||
{
|
||
get_count_stat++;
|
||
if ((double)n->bytes_read/(double)xtime > dcc_max_rate_in)
|
||
dcc_max_rate_in = (double)n->bytes_read/(double)xtime;
|
||
if ((double)n->bytes_read/ (double)xtime < dcc_min_rate_in)
|
||
dcc_min_rate_in = (double)n->bytes_read/(double)xtime;
|
||
}
|
||
if (n->bytes_sent)
|
||
{
|
||
send_count_stat++;
|
||
if ((double)n->bytes_sent/(double)xtime > dcc_max_rate_out)
|
||
dcc_max_rate_out = (double)n->bytes_sent/(double)xtime;
|
||
if ((double)n->bytes_sent/(double)xtime < dcc_min_rate_out)
|
||
dcc_min_rate_out = (double)n->bytes_sent/ (double)xtime;
|
||
}
|
||
}
|
||
|
||
/* Looks for the dcc transfer that is "current" (last received data)
|
||
* and returns information for it
|
||
*/
|
||
extern char *DCC_get_current_transfer (void)
|
||
{
|
||
return DCC_current_transfer_buffer;
|
||
}
|
||
|
||
|
||
|
||
BUILT_IN_COMMAND(chat)
|
||
{
|
||
int no_chat = 0, flags = 0;
|
||
|
||
if (!my_strnicmp(command, "NOC", 3))
|
||
no_chat = 1;
|
||
|
||
#if HAVE_SSL
|
||
if(my_strnicmp(args, "-SSL", 4) == 0)
|
||
{
|
||
new_next_arg(args, &args);
|
||
flags = DCC_SSL;
|
||
}
|
||
#endif
|
||
|
||
if (args && *args)
|
||
{
|
||
char *tmp = NULL;
|
||
if (no_chat)
|
||
malloc_sprintf(&tmp, "CLOSE CHAT %s", args);
|
||
else
|
||
#ifdef HAVE_SSL
|
||
if(flags & DCC_SSL)
|
||
malloc_sprintf(&tmp, "CHAT -ssl %s", args);
|
||
else
|
||
#endif
|
||
malloc_sprintf(&tmp, "CHAT %s", args);
|
||
process_dcc(tmp);
|
||
new_free(&tmp);
|
||
}
|
||
else if (last_chat_req)
|
||
{
|
||
DCC_int *new;
|
||
if (no_chat)
|
||
{
|
||
char *tmp = NULL;
|
||
malloc_sprintf(&tmp, "CLOSE CHAT %s", last_chat_req);
|
||
process_dcc(tmp);
|
||
new_free(&tmp);
|
||
}
|
||
if ((new = dcc_create(last_chat_req, "chat", NULL, 0, 0, DCC_CHAT, DCC_TWOCLIENTS|DCC_OFFER|flags, start_dcc_chat)))
|
||
{
|
||
char *equal_user;
|
||
new->blocksize = get_int_var(DCC_BLOCK_SIZE_VAR);
|
||
equal_user = alloca(strlen(last_chat_req)+4);
|
||
strcpy(equal_user, "=");
|
||
strcat(equal_user, last_chat_req);
|
||
addtabkey(equal_user, "msg", 0);
|
||
userhostbase(last_chat_req, add_userhost_to_chat, 1, NULL);
|
||
new_free(&last_chat_req);
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
void dcc_exempt(char *command, char *args)
|
||
{
|
||
int remove;
|
||
List *nptr = NULL;
|
||
char *nick;
|
||
if (!args || !*args)
|
||
{
|
||
int count = 0;
|
||
for (nptr = next_namelist(dcc_no_flood, NULL, DCC_HASHSIZE); nptr; nptr = next_namelist(dcc_no_flood, nptr, DCC_HASHSIZE))
|
||
{
|
||
if (count == 0)
|
||
put_it("%s", convert_output_format("$G %RDCC%n autoget list/no flood list", NULL, NULL));
|
||
put_it("%s", nptr->name);
|
||
count++;
|
||
}
|
||
if (count == 0)
|
||
userage("dcc exempt", "+nick to add, nick to remove");
|
||
return;
|
||
}
|
||
nick = next_arg(args, &args);
|
||
while (nick && *nick)
|
||
{
|
||
remove = 1;
|
||
if (*nick == '+')
|
||
{
|
||
remove = 0;
|
||
nick++;
|
||
}
|
||
nptr = find_name_in_genericlist(nick, dcc_no_flood, DCC_HASHSIZE, remove);
|
||
if (remove && nptr)
|
||
{
|
||
bitchsay("removed %s from dcc exempt list", nick);
|
||
new_free(&nptr->name);
|
||
new_free((char **)&nptr);
|
||
}
|
||
else if (!remove && !nptr)
|
||
{
|
||
add_name_to_genericlist(nick, dcc_no_flood, DCC_HASHSIZE);
|
||
bitchsay("added %s to dcc exempt list", nick);
|
||
}
|
||
else if (remove && !nptr)
|
||
put_it("%s", convert_output_format("$G %RDCC%n No such nick on the exempt list %K[%W$0%K]", "%s", nick));
|
||
nick = next_arg(args, &args);
|
||
}
|
||
}
|
||
|
||
int dcc_exempt_save(FILE *fptr)
|
||
{
|
||
int count = 0;
|
||
List *nptr = NULL;
|
||
|
||
fprintf(fptr, "# Exemptions from DCC autoget / flooding controls\n");
|
||
|
||
for (nptr = next_namelist(dcc_no_flood, NULL, DCC_HASHSIZE); nptr; nptr = next_namelist(dcc_no_flood, nptr, DCC_HASHSIZE))
|
||
{
|
||
fprintf(fptr, "DCC EXEMPT +%s\n", nptr->name);
|
||
count++;
|
||
}
|
||
|
||
if (count && do_hook(SAVEFILE_LIST, "DCCexempt %d", count))
|
||
bitchsay("Saved %d DccExempt entries", count);
|
||
|
||
return count;
|
||
}
|
||
|
||
/*
|
||
* This is a callback. When we want to do a CTCP DCC REJECT, we do
|
||
* a WHOIS to make sure theyre still on irc, no sense sending it to
|
||
* nobody in particular. When this gets called back, that means the
|
||
* peer is indeed on irc, so we send them the REJECT.
|
||
*/
|
||
static void output_reject_ctcp (UserhostItem *stuff, char *nick, char *args)
|
||
{
|
||
char *nickname_received;
|
||
char *type;
|
||
char *description;
|
||
|
||
if (!strcmp(stuff->user, "<UNKNOWN>"))
|
||
return;
|
||
/*
|
||
* XXX This is, of course, a monsterous hack.
|
||
*/
|
||
next_arg(args, &args);
|
||
type = next_arg(args, &args);
|
||
description = next_arg(args, &args);
|
||
nickname_received = stuff->nick;
|
||
|
||
if (nickname_received && *nickname_received)
|
||
send_ctcp(CTCP_NOTICE, nickname_received, CTCP_DCC,
|
||
"REJECT %s %s", type, description);
|
||
}
|
||
|
||
extern void dcc_reject (char *from, char *type, char *args)
|
||
{
|
||
SocketList *s;
|
||
DCC_List *s1 = NULL;
|
||
char *description;
|
||
int CType;
|
||
int tdcc = 0;
|
||
|
||
upper(type);
|
||
if (*type == 'T' && *(type+1))
|
||
tdcc = 1;
|
||
for (CType = 0; dcc_types[CType]->name != NULL; CType++)
|
||
if (!strcmp(type+tdcc, dcc_types[CType]->name))
|
||
break;
|
||
|
||
if (!dcc_types[CType]->name)
|
||
return;
|
||
if (tdcc)
|
||
CType |= DCC_TDCC;
|
||
|
||
description = next_arg(args, &args);
|
||
if ((s = find_dcc(from, description, NULL, CType, 0, -1, -1)) || (s1 = find_dcc_pending(from, description, NULL, CType, 1, -1)))
|
||
{
|
||
DCC_int *n;
|
||
if (s1)
|
||
s = & s1->sock;
|
||
n = (DCC_int *)s->info;
|
||
if (do_hook(DCC_LOST_LIST,"%s %s %s REJECTED", from, type, description ? description : "<any>"))
|
||
put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_ERROR_FSET), "%s %s %s %s", update_clock(GET_TIME), type, s->server, n->filename));
|
||
|
||
|
||
if (!s1)
|
||
erase_dcc_info(s->is_read, 0, NULL);
|
||
close_socketread(s->is_read);
|
||
if (s1)
|
||
{
|
||
new_free(&s->server);
|
||
new_free(&n->userhost);
|
||
new_free(&n->user);
|
||
new_free(&n->encrypt);
|
||
new_free(&n->filename);
|
||
new_free(&s1);
|
||
}
|
||
#ifdef WANT_CDCC
|
||
dcc_sendfrom_queue();
|
||
#endif
|
||
update_transfer();
|
||
update_all_status(current_window, NULL, 0);
|
||
}
|
||
}
|
||
|
||
BUILT_IN_COMMAND(dcx)
|
||
{
|
||
int i;
|
||
unsigned long flag;
|
||
SocketList *s;
|
||
int all = 0;
|
||
unsigned long type = 0;
|
||
char *nick = NULL;
|
||
if (!my_stricmp(command, "DCA"))
|
||
all = 1;
|
||
else if (!my_stricmp(command, "DCG"))
|
||
type = DCC_FILEREAD;
|
||
else if (!my_stricmp(command, "DCS"))
|
||
type = DCC_FILEOFFER;
|
||
else if (!my_stricmp(command, "DCX"))
|
||
type = DCC_CHAT;
|
||
else
|
||
return;
|
||
nick = next_arg(args, &args);
|
||
if (!all && !nick)
|
||
return;
|
||
for (i = 0; i < get_max_fd() + 1; i++)
|
||
{
|
||
if (!check_dcc_socket(i))
|
||
continue;
|
||
s = get_socket(i);
|
||
flag = s->flags & DCC_TYPES;
|
||
if (all || (type == flag))
|
||
{
|
||
if ((!all && nick) || (all && nick))
|
||
{
|
||
if (!wild_match(nick, s->server))
|
||
continue;
|
||
}
|
||
erase_dcc_info(i, 1, "%s", convert_output_format("$G %RDCC%n closing dcc $0 to $1", "%s %s", dcc_types[flag]->name, s->server));
|
||
close_socketread(i);
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
void close_all_dcc(void)
|
||
{
|
||
int i;
|
||
SocketList *s;
|
||
unsigned long flag;
|
||
for (i = 0; i < get_max_fd() + 1; i++)
|
||
{
|
||
if (!check_dcc_socket(i))
|
||
continue;
|
||
s = get_socket(i);
|
||
flag = s->flags & DCC_TYPES;
|
||
erase_dcc_info(i, 1, "%s", convert_output_format("$G %RDCC%n closing dcc $0 to $1", "%s %s", dcc_types[flag]->name, s->server));
|
||
close_socketread(i);
|
||
}
|
||
return;
|
||
}
|
||
|
||
|
||
static char *last_notify = NULL;
|
||
|
||
void cancel_dcc_auto(int i, unsigned long flags, SocketList *s)
|
||
{
|
||
if (!last_notify || strcmp(s->server,last_notify))
|
||
{
|
||
send_to_server("NOTICE %s :DCC %s Auto Closed", s->server, dcc_types[flags]->name);
|
||
malloc_strcpy(&last_notify, s->server);
|
||
}
|
||
erase_dcc_info(i, 1, "%s", convert_output_format("$G %RDCC%n Auto-closing idle dcc $0 to $1", "%s %s", dcc_types[flags]->name, s->server));
|
||
close_socketread(i);
|
||
}
|
||
|
||
void dcc_check_idle(void)
|
||
{
|
||
int i;
|
||
time_t dcc_idle_time = get_int_var(_CDCC_CLOSE_IDLE_SENDS_TIME_VAR);
|
||
#ifdef WANT_CDCC
|
||
int minidlecheck = get_int_var(_CDCC_MINSPEED_TIME_VAR);
|
||
#endif
|
||
SocketList *s = NULL;
|
||
DCC_int *n = NULL;
|
||
unsigned long flags;
|
||
|
||
if (pending_dcc)
|
||
{
|
||
DCC_List *s1 = pending_dcc, *last = NULL;
|
||
while (s1)
|
||
{
|
||
s = &s1->sock;
|
||
n = (DCC_int *)s->info;
|
||
if (now >= s->time)
|
||
{
|
||
if (last)
|
||
last->next = s1->next;
|
||
else
|
||
pending_dcc = s1->next;
|
||
new_free(&s->server);
|
||
new_free(&n->user);
|
||
new_free(&n->filename);
|
||
new_free(&n->userhost);
|
||
new_free(&n->encrypt);
|
||
close_socketread(s->is_read);
|
||
new_free(&n);
|
||
new_free(&s1);
|
||
break;
|
||
}
|
||
last = s1;
|
||
s1 = s1->next;
|
||
}
|
||
}
|
||
for (i = 0; i < get_max_fd()+1; i++)
|
||
{
|
||
time_t client_idle,
|
||
this_idle_time;
|
||
|
||
if (!check_dcc_socket(i))
|
||
continue;
|
||
s = get_socket(i);
|
||
n = (DCC_int *)s->info;
|
||
|
||
flags = s->flags & DCC_TYPES;
|
||
client_idle = now - n->lasttime.tv_sec;
|
||
switch (flags)
|
||
{
|
||
case DCC_FILEOFFER:
|
||
case DCC_FILEREAD:
|
||
case DCC_REFILEOFFER:
|
||
case DCC_REFILEREAD:
|
||
this_idle_time = dcc_idle_time * 3;
|
||
break;
|
||
default:
|
||
this_idle_time = dcc_timeout;
|
||
break;
|
||
}
|
||
if (!(s->flags & DCC_ACTIVE))
|
||
{
|
||
if ((client_idle > this_idle_time))
|
||
cancel_dcc_auto(i, flags, s);
|
||
continue;
|
||
}
|
||
#ifdef WANT_CDCC
|
||
switch (flags)
|
||
{
|
||
case DCC_FILEOFFER:
|
||
case DCC_REFILEOFFER:
|
||
if (cdcc_minspeed && minidlecheck && (((now - n->starttime.tv_sec) % minidlecheck) == 0))
|
||
{
|
||
unsigned long sent = n->bytes_sent / 1024;
|
||
double this_speed = 0.0;
|
||
char lame_ultrix1[20];
|
||
char lame_ultrix[20];
|
||
this_speed = (double)((double) sent / (double)(now- n->starttime.tv_sec));
|
||
if (this_speed < (float)cdcc_minspeed)
|
||
{
|
||
sprintf(lame_ultrix, "%2.4g", (double)(sent / (now - n->starttime.tv_sec)));
|
||
sprintf(lame_ultrix1,"%2.4g", (double)cdcc_minspeed);
|
||
if (!last_notify || strcmp(s->server,last_notify))
|
||
{
|
||
send_to_server("NOTICE %s :CDCC Slow dcc %s Auto Closed. Require %sKB/s got %sKB/s", s->server, dcc_types[flags]->name, lame_ultrix1, lame_ultrix);
|
||
malloc_strcpy(&last_notify, s->server);
|
||
}
|
||
erase_dcc_info(i, 1, "%s", convert_output_format("$G %RDCC%n Auto-closing Slow dcc $0 to $1 require $2KB/s got $3KB/s", "%s %s %s %s", dcc_types[flags]->name, s->server, lame_ultrix1, lame_ultrix));
|
||
close_socketread(i);
|
||
}
|
||
break;
|
||
}
|
||
if (client_idle > this_idle_time)
|
||
cancel_dcc_auto(i, flags, s);
|
||
default:
|
||
break;
|
||
}
|
||
#endif
|
||
}
|
||
#ifdef WANT_CDCC
|
||
cdcc_timer_offer();
|
||
#endif
|
||
return;
|
||
}
|
||
|
||
void dcc_close(char *command, char *args)
|
||
{
|
||
char *type;
|
||
char *file;
|
||
char *nick;
|
||
int any_type = 0;
|
||
int any_user = 0;
|
||
int count = 0;
|
||
SocketList *s;
|
||
DCC_List *s1;
|
||
int i;
|
||
int num = -1;
|
||
|
||
type = next_arg(args, &args);
|
||
nick = next_arg(args, &args);
|
||
file = next_arg(args, &args);
|
||
if (type)
|
||
{
|
||
if (!my_stricmp(type, "-all") || !strcmp(type, "*"))
|
||
any_type = 1;
|
||
else if (*type == '#' && (num = my_atol(type+1)))
|
||
any_type = 1;
|
||
}
|
||
if (nick && (!my_stricmp(nick, "-all") || !strcmp(nick, "*")))
|
||
any_user = 1;
|
||
if (!type || (!nick && (!any_type || num == -1)))
|
||
{
|
||
bitchsay("Specify a nick and a type to close or a number");
|
||
return;
|
||
}
|
||
if (!any_type)
|
||
{
|
||
for (i = 0; dcc_types[i]->name; i++)
|
||
if (!my_stricmp(dcc_types[i]->name, type))
|
||
break;
|
||
if (!dcc_types[i]->name)
|
||
{
|
||
bitchsay("Unknown dcc type for close");
|
||
return;
|
||
}
|
||
} else
|
||
i = -1;
|
||
if (any_user)
|
||
nick = NULL;
|
||
while ((s = find_dcc(nick, file, NULL, i, 0, -1, num)))
|
||
{
|
||
DCC_int *n;
|
||
n = (DCC_int *)s->info;
|
||
count++;
|
||
if (do_hook(DCC_LOST_LIST,"%s %s %s USER ABORTED CONNECTION",
|
||
s->server,
|
||
dcc_types[s->flags & DCC_TYPES]->name,
|
||
n->filename ? n->filename : "<any>"))
|
||
say("DCC %s:%s to %s closed",
|
||
dcc_types[s->flags & DCC_TYPES]->name,
|
||
file ? file : "<any>",
|
||
s->server);
|
||
erase_dcc_info(s->is_read, 1, NULL);
|
||
close_socketread(s->is_read);
|
||
}
|
||
while ((s1 = find_dcc_pending(nick, file, NULL, i, 1, num)))
|
||
{
|
||
DCC_int *n;
|
||
s = &s1->sock;
|
||
n = (DCC_int *)s->info;
|
||
count++;
|
||
if (do_hook(DCC_LOST_LIST,"%s %s %s USER ABORTED CONNECTION",
|
||
s->server,
|
||
dcc_types[s->flags & DCC_TYPES]->name,
|
||
n->filename ? n->filename : "<any>"))
|
||
say("DCC %s:%s to %s closed",
|
||
dcc_types[s->flags & DCC_TYPES]->name,
|
||
file ? file : "<any>",
|
||
s->server);
|
||
|
||
send_reject_ctcp(s->server,
|
||
(((s->flags & DCC_TYPES) == DCC_FILEOFFER) ? "GET" :
|
||
((s->flags & DCC_TYPES) == DCC_FILEREAD) ? "SEND" :
|
||
dcc_types[s->flags & DCC_TYPES]->name),
|
||
n->filename);
|
||
|
||
new_free(&s->server);
|
||
new_free(&n->user);
|
||
new_free(&n->filename);
|
||
new_free(&n->userhost);
|
||
new_free(&n->encrypt);
|
||
close_socketread(s->is_read);
|
||
new_free(&n);
|
||
new_free(&s1);
|
||
}
|
||
if (!count)
|
||
put_it("%s", convert_output_format("$G %RDCC%n No DCC $0:$1 to $2 found", "%s %s %s",
|
||
(i == -1 ? "<any>" : type),
|
||
(file ? file : "<any>"),
|
||
(num != -1) ? ltoa(num): nick ? nick : "(null)"));
|
||
update_transfer();
|
||
return;
|
||
}
|
||
|
||
void dcc_closeall(char *command, char *args)
|
||
{
|
||
close_all_dcc();
|
||
}
|
||
|
||
extern int doing_notice;
|
||
|
||
#ifdef MIRC_BROKEN_DCC_RESUME
|
||
|
||
void dcc_getfile_resume_demanded(char *nick, char *filename, char *port, char *offset)
|
||
{
|
||
SocketList *s;
|
||
DCC_int *n;
|
||
int old_dp, old_dn, old_dc;
|
||
|
||
if (filename && !strcmp(filename, "file.ext"))
|
||
filename = NULL;
|
||
if (!(s = find_dcc(nick, filename, port, DCC_FILEOFFER, 1, -1, -1)))
|
||
{
|
||
put_it("%s", convert_output_format("$G %RDCC%n warning in dcc_getfile_resume_demanded", NULL));
|
||
return;
|
||
}
|
||
n = (DCC_int *)s->info;
|
||
if (!offset)
|
||
return;
|
||
old_dp = doing_privmsg;
|
||
old_dn = doing_notice;
|
||
old_dc = in_ctcp_flag;
|
||
|
||
n->bytes_read = n->transfer_orders.byteoffset = my_atol(offset);
|
||
/* n->bytes_read = 0L;*/
|
||
|
||
doing_privmsg = doing_notice = in_ctcp_flag = 0;
|
||
send_ctcp(CTCP_PRIVMSG, nick, CTCP_DCC, "ACCEPT %s %s %s", filename, port, offset);
|
||
doing_privmsg = old_dp;
|
||
doing_notice = old_dn;
|
||
in_ctcp_flag = old_dc;
|
||
}
|
||
|
||
void dcc_getfile_resume_start(char *nick, char *description, char *port, char *offset)
|
||
{
|
||
SocketList *s;
|
||
DCC_int *n;
|
||
const DCC_List *pending;
|
||
char *tmp = NULL;
|
||
char *fullname = NULL;
|
||
struct stat sb;
|
||
|
||
/* resume command has been sent and accepted. */
|
||
if (description && !strcmp(description, "file.ext"))
|
||
description = NULL;
|
||
if ((s = find_dcc(nick, description, NULL, DCC_FILEREAD, 1, 1, -1)))
|
||
{
|
||
put_it("%s", convert_output_format("$G %RDCC%n warning in dcc_getfile_resume_start", NULL));
|
||
return;
|
||
}
|
||
|
||
pending = find_dcc_pending(nick, description, NULL, DCC_FILEREAD, 0, -1);
|
||
if (!pending || !(pending->sock.flags & DCC_RESUME_REQ))
|
||
{
|
||
put_it("%s", convert_output_format("$G %RDCC%n Ignoring unsolicited ACCEPT from $0", "%s", nick));
|
||
return;
|
||
}
|
||
|
||
if (!(n = dcc_create(nick, description, NULL, 0, port?atol(port):0, DCC_FILEREAD, DCC_TWOCLIENTS|DCC_OFFER, start_dcc_get)))
|
||
return;
|
||
|
||
if (get_string_var(DCC_DLDIR_VAR))
|
||
malloc_sprintf(&tmp, "%s/%s", get_string_var(DCC_DLDIR_VAR), n->filename);
|
||
else
|
||
tmp = m_strdup(n->filename);
|
||
if (!(fullname = expand_twiddle(tmp)))
|
||
malloc_strcpy(&fullname, tmp);
|
||
|
||
if (
|
||
!(n->file = open(fullname, O_WRONLY | O_APPEND | O_BINARY, 0644)) ||
|
||
(fstat(n->file, &sb) != 0) ||
|
||
(sb.st_size >= n->filesize)
|
||
)
|
||
{
|
||
int snum;
|
||
if ((s = find_dcc(nick, description, NULL, DCC_FILEREAD, 0, 1, -1)))
|
||
n = (DCC_int *)s->info;
|
||
if (s)
|
||
{
|
||
snum = s->is_read;
|
||
erase_dcc_info(snum, 1, "%s", convert_output_format("$G %RDCC%n Unable to open $0: $1-", "%s %s", n->filename, errno?strerror(errno):"incoming file smaller than existing"));
|
||
close_socketread(snum);
|
||
}
|
||
} else
|
||
put_it("%s", convert_output_format("$G %RDCC%n RESUME of $0 at $1", "%s %l", n->filename, sb.st_size));
|
||
new_free(&fullname);
|
||
new_free(&tmp);
|
||
}
|
||
|
||
void dcc_resume(char *command, char *args)
|
||
{
|
||
char *user, *nick;
|
||
char *filename = NULL;
|
||
char *fullname = NULL;
|
||
char *tmp = NULL;
|
||
char *passwd = NULL;
|
||
char *port = NULL;
|
||
struct stat sb;
|
||
int old_dp, old_dn, old_dc;
|
||
int blocksize = 0;
|
||
|
||
user = get_dcc_args(&args, &passwd, &port, &blocksize);
|
||
if (!user)
|
||
{
|
||
put_it("%s", convert_output_format("$G %RDCC%n You must supply a nickname for DCC RESUME", NULL));
|
||
return;
|
||
}
|
||
|
||
if (!blocksize || blocksize > MAX_DCC_BLOCK_SIZE)
|
||
blocksize = get_int_var(DCC_BLOCK_SIZE_VAR);
|
||
|
||
if (args && *args)
|
||
filename = args;
|
||
|
||
tmp = NULL;
|
||
|
||
while ((nick = next_in_comma_list(user, &user)))
|
||
{
|
||
SocketList *s;
|
||
DCC_int *n;
|
||
DCC_List *s1 = NULL;
|
||
if (!nick || !*nick)
|
||
break;
|
||
if ((s = find_dcc(nick, filename, NULL, DCC_FILEREAD, 1, 1, -1)))
|
||
{
|
||
put_it("%s", convert_output_format("$G %RDCC%n DCC send already active. Unable to RESUME", NULL));
|
||
continue;
|
||
}
|
||
for (s1 = pending_dcc; s1; s1 = s1->next)
|
||
{
|
||
if (my_stricmp(s1->nick, nick))
|
||
continue;
|
||
if ( ((s1->sock.flags & DCC_TYPES) != DCC_FILEREAD) ||
|
||
(s1->sock.flags & DCC_ACTIVE))
|
||
continue;
|
||
break;
|
||
}
|
||
if (!s1)
|
||
continue;
|
||
s = &s1->sock;
|
||
n = (DCC_int *)s->info;
|
||
|
||
if (get_string_var(DCC_DLDIR_VAR))
|
||
malloc_sprintf(&tmp, "%s/%s", get_string_var(DCC_DLDIR_VAR), n->filename);
|
||
else
|
||
tmp = m_strdup(n->filename);
|
||
|
||
if (!(fullname = expand_twiddle(tmp)))
|
||
malloc_strcpy(&fullname, tmp);
|
||
/*
|
||
* This has to be done by hand, we cant use send_ctcp,
|
||
* because this violates the protocol, and send_ctcp checks
|
||
* for that. Ugh.
|
||
*/
|
||
|
||
if (stat(fullname, &sb) == -1)
|
||
{
|
||
/* File doesnt exist. Sheesh. */
|
||
put_it("%s", convert_output_format("$G %RDCC%n Cannot use DCC RESUME if the file doesn't exist [$0|$1-]", "%s %s", fullname, strerror(errno)));
|
||
continue;
|
||
}
|
||
|
||
if (passwd)
|
||
n->encrypt = m_strdup(passwd);
|
||
|
||
n->bytes_sent = 0L;
|
||
n->blocksize = blocksize;
|
||
n->transfer_orders.byteoffset = sb.st_size;
|
||
|
||
s->flags |= DCC_RESUME_REQ;
|
||
|
||
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, n->remport, sb.st_size);
|
||
doing_privmsg = old_dp; doing_notice = old_dn; in_ctcp_flag = old_dc;
|
||
|
||
}
|
||
new_free(&tmp);
|
||
new_free(&fullname);
|
||
/* Then we just sit back and wait for the reply. */
|
||
}
|
||
#endif
|
||
|
||
void dcc_help1(char *command, char *args)
|
||
{
|
||
char *comm;
|
||
int i, c;
|
||
char buffer[BIG_BUFFER_SIZE+1];
|
||
DCC_dllcommands *dcc_comm = NULL;
|
||
if (args && *args)
|
||
{
|
||
comm = next_arg(args, &args);
|
||
upper(comm);
|
||
if ((dcc_comm = (DCC_dllcommands *)find_in_list((List **)&dcc_dllcommands, comm, 0)))
|
||
{
|
||
put_it("%s", convert_output_format("$G Usage: %W/%R$0%n $1 %K-%n $2-", "DCC %s %s", dcc_comm->name, dcc_comm->help?dcc_comm->help:"No help availble yet"));
|
||
return;
|
||
}
|
||
for (i = 0; dcc_commands[i].name != NULL; i++)
|
||
{
|
||
if (!strncmp(comm, dcc_commands[i].name, strlen(comm)))
|
||
{
|
||
put_it("%s", convert_output_format("$G Usage: %W/%R$0%n $1 %K-%n $2-", "DCC %s %s", dcc_commands[i].name, dcc_commands[i].help?dcc_commands[i].help:"No help availble yet"));
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
put_it("%s", convert_output_format("$G %RDCC%n help -", NULL, NULL));
|
||
*buffer = 0;
|
||
c = 0;
|
||
for (dcc_comm = dcc_dllcommands; dcc_comm; dcc_comm = dcc_comm->next)
|
||
{
|
||
strcat(buffer, dcc_comm->name);
|
||
strcat(buffer, space);
|
||
if (++c == 5)
|
||
{
|
||
put_it("%s", convert_output_format("$G $[13]0 $[13]1 $[13]2 $[13]3 $[13]4", "%s", buffer));
|
||
*buffer = 0;
|
||
c = 0;
|
||
}
|
||
}
|
||
if (c)
|
||
put_it("%s", convert_output_format("$G $[13]0 $[13]1 $[13]2 $[13]3 $[13]4", "%s", buffer));
|
||
*buffer = 0;
|
||
c = 0;
|
||
for (i = 0; dcc_commands[i].name; i++)
|
||
{
|
||
strcat(buffer, dcc_commands[i].name);
|
||
strcat(buffer, space);
|
||
if (++c == 5)
|
||
{
|
||
put_it("%s", convert_output_format("$G $[13]0 $[13]1 $[13]2 $[13]3 $[13]4", "%s", buffer));
|
||
*buffer = 0;
|
||
c = 0;
|
||
}
|
||
}
|
||
if (c)
|
||
put_it("%s", convert_output_format("$G $[13]0 $[13]1 $[13]2 $[13]3 $[13]4", "%s", buffer));
|
||
userage("dcc help", "[command] to get help on specific commands");
|
||
}
|
||
|
||
void read_ftp_file(int snum)
|
||
{
|
||
int len = 0;
|
||
char *buf;
|
||
SocketList *s;
|
||
DCC_int *n;
|
||
int err;
|
||
if ((ioctl(snum, FIONREAD, &len) == -1))
|
||
{
|
||
put_it("%s", convert_output_format("$G %gFTP%n file error [$0-]", "%s", strerror(errno)));
|
||
erase_dcc_info(snum, 0, NULL);
|
||
close_socketread(snum);
|
||
return;
|
||
}
|
||
s = get_socket(snum);
|
||
n = (DCC_int *)s->info;
|
||
buf = alloca(len+1);
|
||
err = read(snum, buf, len);
|
||
switch(err)
|
||
{
|
||
case -1:
|
||
erase_dcc_info(snum, 0, NULL);
|
||
close_socketread(snum);
|
||
break;
|
||
case 0:
|
||
close_dcc_file(snum);
|
||
break;
|
||
default:
|
||
write(n->file, buf, len);
|
||
n->bytes_read += len;
|
||
n->packets++;
|
||
get_time(&n->lasttime);
|
||
}
|
||
}
|
||
|
||
int open_listen_port(int s)
|
||
{
|
||
struct sockaddr_in data_addr = { 0 };
|
||
socklen_t len = sizeof(struct sockaddr_in), data = -1;
|
||
int on = 1;
|
||
char *a, *p;
|
||
|
||
if (getsockname(s, (struct sockaddr *)&data_addr, &len) < 0)
|
||
return -1;
|
||
|
||
data_addr.sin_port = 0;
|
||
if ((data = socket(AF_INET, SOCK_STREAM, 0)) < 0)
|
||
return -1;
|
||
if ((setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on))) < 0)
|
||
return -1;
|
||
if ((bind(data, (struct sockaddr *)&data_addr, sizeof(data_addr))) < 0)
|
||
return -1;
|
||
len = sizeof(struct sockaddr_in);
|
||
getsockname(data, (struct sockaddr *)&data_addr, &len);
|
||
|
||
a = (char *)&data_addr.sin_addr;
|
||
p = (char *)&data_addr.sin_port;
|
||
#define UC(b) (((int)b)&0xff)
|
||
dcc_printf(s, "PORT %d,%d,%d,%d,%d,%d\n", UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),UC(p[0]), UC(p[1]));
|
||
#undef UC
|
||
if ((listen(data, 1)) < 0)
|
||
return -1;
|
||
return data;
|
||
}
|
||
|
||
|
||
int handle_ftp(int comm, int snum, SocketList *s, char *buf)
|
||
{
|
||
int err = 0;
|
||
DCC_int *n;
|
||
n = (DCC_int *)s->info;
|
||
get_time(&n->lasttime);
|
||
switch(comm)
|
||
{
|
||
case 220:
|
||
if (n->userhost)
|
||
err = dcc_printf(snum, "user %s\r\n", n->userhost);
|
||
new_free(&n->userhost);
|
||
break;
|
||
case 226:
|
||
s->flags &= ~DCC_WAIT;
|
||
return 0;
|
||
case 331:
|
||
if (n->encrypt)
|
||
{
|
||
err = dcc_printf(snum, "pass %s\r\n", n->encrypt);
|
||
if (err != -1)
|
||
err = dcc_printf(snum, "type I\r\n");
|
||
}
|
||
new_free(&n->encrypt); new_free(&n->othername);
|
||
break;
|
||
case 230:
|
||
{
|
||
char *dir = NULL;
|
||
if (n->othername)
|
||
{
|
||
err = dcc_printf(snum, "cwd %s\r\n", n->othername);
|
||
if (do_hook(FTP_LIST, "%d Changing directory to %s", comm, n->othername))
|
||
put_it("%s", convert_output_format("%gFTP%n Changing directory to $0-", "%s", n->othername));
|
||
}
|
||
new_free(&n->encrypt);
|
||
new_free(&n->userhost);
|
||
new_free(&n->othername);
|
||
new_free(&dir);
|
||
break;
|
||
}
|
||
case 421:
|
||
erase_dcc_info(snum, 0, NULL);
|
||
close_socketread(snum);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
if (do_hook(FTP_LIST, "%d %s", comm, buf))
|
||
put_it("%s", convert_output_format("%gFTP%n $0-", "%s", buf));
|
||
return err;
|
||
}
|
||
|
||
void start_ftp(int snum)
|
||
{
|
||
SocketList *s;
|
||
DCC_int *n;
|
||
char *buf = NULL;
|
||
int i = 0;
|
||
|
||
s = get_socket(snum);
|
||
n = (DCC_int *)s->info;
|
||
if (s->flags & DCC_WAIT)
|
||
{
|
||
struct sockaddr_in remaddr;
|
||
socklen_t rl = sizeof(remaddr);
|
||
|
||
/* maybe we should login here. */
|
||
if (getpeername(snum, (struct sockaddr *) &remaddr, &rl) != -1)
|
||
{
|
||
s->flags = DCC_ACTIVE|DCC_FTPOPEN;
|
||
return;
|
||
}
|
||
erase_dcc_info(snum, 0, "DCC ftp lost");
|
||
close_socketread(snum);
|
||
return;
|
||
}
|
||
buf = alloca(n->blocksize+1);
|
||
*buf = 0;
|
||
switch(dgets(buf, snum, 1, n->blocksize, NULL))
|
||
{
|
||
case -1:
|
||
i = -1;
|
||
break;
|
||
case 0:
|
||
break;
|
||
default:
|
||
{
|
||
int comm = 0;
|
||
char *p;
|
||
if ((p = strrchr(buf, '\r')))
|
||
*p = 0;
|
||
if ((p = strrchr(buf, '\n')))
|
||
*p = 0;
|
||
if ((comm = my_atol(buf)))
|
||
next_arg(buf, &buf);
|
||
i = handle_ftp(comm, snum, s, buf);
|
||
break;
|
||
}
|
||
}
|
||
if (i == -1)
|
||
{
|
||
erase_dcc_info(snum, 0, NULL);
|
||
close_socketread(snum);
|
||
}
|
||
}
|
||
|
||
|
||
void open_ftpget(SocketList *s, char *args)
|
||
{
|
||
DCC_int *new;
|
||
struct sockaddr_in data_addr = { 0 };
|
||
socklen_t len = sizeof(struct sockaddr_in);
|
||
char tmp[BIG_BUFFER_SIZE+1];
|
||
int data = -1, s1 = -1;
|
||
char *p, *bufptr;
|
||
off_t filesize = 0;
|
||
char *filename = NULL;
|
||
|
||
if ((data = open_listen_port(s->is_read)) == -1)
|
||
return;
|
||
|
||
dcc_printf(s->is_read, "retr %s\n", args);
|
||
|
||
memset(tmp, 0, sizeof(tmp));
|
||
bufptr = tmp;
|
||
while (1)
|
||
{
|
||
if (dgets(bufptr, s->is_read, 1, BIG_BUFFER_SIZE, NULL) == -1 && dgets_errno > 0)
|
||
goto error_ftp;
|
||
if (*bufptr == '5')
|
||
goto error_ftp;
|
||
else if (strstr(tmp, "BINARY mode data connection"))
|
||
{
|
||
int i = 0;
|
||
char *q = tmp;
|
||
for (i = 0; i < 9; i++)
|
||
p = next_arg(q, &q);
|
||
if (p)
|
||
{
|
||
p++;
|
||
filesize = my_atol(p);
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
|
||
len = sizeof(struct sockaddr_in);
|
||
if ((s1 = my_accept(data, (struct sockaddr *) &data_addr, &len)) < 0)
|
||
return;
|
||
close(data);
|
||
|
||
#if defined(WINNT) || defined(__EMX__)
|
||
if ((p = strrchr(args, '/')) || (p = strrchr(args, '\\')))
|
||
#else
|
||
if ((p = strrchr(args, '/')))
|
||
#endif
|
||
filename = ++p;
|
||
else
|
||
filename = args;
|
||
|
||
add_socketread(s1, 0, DCC_FTPGET|DCC_ACTIVE, s->server, read_ftp_file, NULL);
|
||
new = new_malloc(sizeof(DCC_int));
|
||
{
|
||
char *t, *expand;
|
||
expand = m_sprintf("%s/%s", get_string_var(DCC_DLDIR_VAR), filename);
|
||
t = expand_twiddle(expand);
|
||
new->file = open(t?t:expand?expand:filename, O_WRONLY|O_CREAT|O_TRUNC | O_BINARY, 0644);
|
||
new_free(&t); new_free(&expand);
|
||
}
|
||
new->struct_type = DCC_STRUCT_TYPE;
|
||
new->filesize = filesize;
|
||
new->filename = m_strdup(filename);
|
||
get_time(&new->starttime);
|
||
get_time(&new->lasttime);
|
||
set_socketinfo(s1, new);
|
||
s->flags |= DCC_WAIT;
|
||
if (do_hook(FTP_LIST, "%s %s", "FTP Attempting to get", filename))
|
||
put_it("%s", convert_output_format("$G %gFTP%n Attempting to get $0", "%s", filename));
|
||
return;
|
||
error_ftp:
|
||
close(data);
|
||
chop(tmp, 2);
|
||
put_it("%s", convert_output_format("$G %gFTP%n $0-", "%s", tmp));
|
||
return;
|
||
|
||
}
|
||
|
||
int dcc_ftpcommand (char *host, char *args)
|
||
{
|
||
SocketList *s;
|
||
s = find_dcc(host, "ftpopen", NULL, DCC_FTPOPEN, 0, 1, -1);
|
||
if (s)
|
||
{
|
||
char *command = next_arg(args, &args);
|
||
char *t_host;
|
||
if (s->flags & DCC_WAIT)
|
||
{
|
||
if (do_hook(FTP_LIST, "%s", "FTP connection is busy"))
|
||
put_it("%s", convert_output_format("$G %gFTP%n connection is busy.", NULL, NULL));
|
||
return 1;
|
||
}
|
||
|
||
if (command && *command)
|
||
{
|
||
if (!my_strnicmp(command, "ls",2) || !my_strnicmp(command, "dir",3))
|
||
{
|
||
int sock, s1;
|
||
DCC_int *new;
|
||
struct sockaddr_in data_addr = { 0 };
|
||
socklen_t len;
|
||
char tmp[BIG_BUFFER_SIZE+1], *bufptr;
|
||
if ((sock = open_listen_port(s->is_read)) == -1)
|
||
return -1;
|
||
dcc_printf(s->is_read, "list -a%s%s\r\n", (args && *args) ?space:empty_string, (args && *args) ? args : empty_string);
|
||
memset(tmp, 0, sizeof(tmp));
|
||
bufptr = tmp;
|
||
while (1)
|
||
{
|
||
if (dgets(bufptr, s->is_read, 1, BIG_BUFFER_SIZE, NULL) == -1 && dgets_errno > 0)
|
||
goto error_port;
|
||
if (*bufptr == '5')
|
||
goto error_port;
|
||
else if (strstr(tmp, "150 Opening BINARY mode data connection"))
|
||
break;
|
||
}
|
||
|
||
len = sizeof(struct sockaddr_in);
|
||
set_blocking(sock);
|
||
alarm(10);
|
||
s1 = accept(sock, (struct sockaddr *) &data_addr, &len);
|
||
alarm(0);
|
||
close(sock);
|
||
if (s1 != -1)
|
||
{
|
||
add_socketread(s1, 0, DCC_FTPCOMMAND|DCC_ACTIVE, s->server, start_ftp, NULL);
|
||
new = new_malloc(sizeof(DCC_int));
|
||
new->struct_type = DCC_STRUCT_TYPE;
|
||
get_time(&new->starttime);
|
||
get_time(&new->lasttime);
|
||
new->blocksize = BIG_BUFFER_SIZE;
|
||
set_socketinfo(s1, new);
|
||
} else
|
||
bitchsay("FTP data connection failed.");
|
||
}
|
||
else if (!my_strnicmp(command, "more", 3))
|
||
dcc_printf(s->is_read, "stat %s\n", args ? args : empty_string);
|
||
else if (!my_strnicmp(command, "cd", 2))
|
||
dcc_printf(s->is_read, "%s%s%s\n", (args && *args) ? "cwd" : "pwd", (args && *args) ? space:empty_string, (args && *args) ?args:empty_string);
|
||
else if (!my_strnicmp(command, "get",3) && args && *args)
|
||
open_ftpget(s, args);
|
||
else
|
||
dcc_printf(s->is_read, "%s%s%s\n", command, (args && *args) ? space:empty_string, (args && *args) ? args:empty_string);
|
||
|
||
t_host = alloca(strlen(host)+4);
|
||
strcpy(t_host, "-");
|
||
strcat(t_host, host);
|
||
addtabkey(t_host, "msg", 0);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (do_hook(FTP_LIST, "%s", "FTP is not connected"))
|
||
put_it("%s", convert_output_format("$G %gFTP%n is not connected.", NULL, NULL));
|
||
return 0;
|
||
}
|
||
return 1;
|
||
error_port:
|
||
return -1;
|
||
}
|
||
|
||
|
||
char *parse_ncftp(char *buffer, char **hostname)
|
||
{
|
||
char *dir = NULL, *p;
|
||
|
||
/*bitchx,bitchx.com,panasync,,,/home/panasync,I,,34ce4360,1,*/
|
||
if (!(p = strchr(buffer, ',')))
|
||
return NULL;
|
||
*p++ = 0; *hostname = p;
|
||
if (!(p = strchr(p, ',')))
|
||
return NULL;
|
||
*p++ = 0;
|
||
if (!(p = strchr(p, ',')))
|
||
return NULL;
|
||
*p++ = 0;
|
||
if (!(p = strchr(p, ',')))
|
||
return NULL;
|
||
*p++ = 0;
|
||
if (!(p = strchr(p, ',')))
|
||
return NULL;
|
||
*p++ = 0;
|
||
|
||
dir = p;
|
||
if (!(p = strchr(p, ',')))
|
||
return NULL;
|
||
*p = 0;
|
||
return (dir && *dir) ? dir : NULL;
|
||
}
|
||
|
||
char *read_ncftp_config(char **hostname)
|
||
{
|
||
char *tmp, *file = NULL;
|
||
char *buffer;
|
||
char *dir = NULL;
|
||
struct stat sb;
|
||
FILE *f;
|
||
tmp = m_sprintf("~/.ncftp/bookmarks");
|
||
file = expand_twiddle(tmp);
|
||
if ((stat(file, &sb) != -1) && (f = fopen(file, "r")))
|
||
{
|
||
char *hst = NULL;
|
||
buffer = alloca(sb.st_size+1);
|
||
freadln(f, buffer, sb.st_size + 1);
|
||
while(!feof(f))
|
||
{
|
||
if ((freadln(f, buffer, sb.st_size + 1)))
|
||
{
|
||
if (*buffer == '#')
|
||
continue;
|
||
dir = parse_ncftp(buffer, &hst);
|
||
if (hst)
|
||
{
|
||
if (!my_stricmp(hst, *hostname))
|
||
break;
|
||
else if (!my_stricmp(*hostname, buffer))
|
||
{
|
||
malloc_strcpy(hostname, hst);
|
||
break;
|
||
}
|
||
}
|
||
dir = NULL;
|
||
}
|
||
}
|
||
fclose(f);
|
||
}
|
||
new_free(&tmp); new_free(&file);
|
||
return dir ? m_strdup(dir) : NULL;
|
||
}
|
||
|
||
void dcc_ftpopen(char *command, char *args)
|
||
{
|
||
char u[] = "anonymous";
|
||
char p[] = "- bxuser@";
|
||
char *host = NULL,
|
||
*user = NULL,
|
||
*pass = NULL,
|
||
*dir = NULL,
|
||
*t_host = NULL;
|
||
unsigned short port = 21;
|
||
int blocksize = 2048;
|
||
int snum;
|
||
SocketList *s;
|
||
|
||
if (!(t_host = next_arg(args, &args)))
|
||
{
|
||
put_it ("%s /dcc ftp hostname user passwd [-p port] [-b blocksize]", convert_output_format("$G %RDCC%n", NULL, NULL));
|
||
return;
|
||
}
|
||
host = m_strdup(t_host);
|
||
while (args && *args)
|
||
{
|
||
char *t;
|
||
if (!my_strnicmp(args, "-p", 2))
|
||
{
|
||
next_arg(args, &args);
|
||
port = my_atol(next_arg(args, &args));
|
||
continue;
|
||
}
|
||
if (!my_strnicmp(args, "-b", 2))
|
||
{
|
||
next_arg(args, &args);
|
||
blocksize = my_atol(next_arg(args, &args));
|
||
continue;
|
||
}
|
||
else if ((t = next_arg(args, &args)))
|
||
{
|
||
if (!user)
|
||
user = t;
|
||
else
|
||
malloc_strcpy(&pass, t);
|
||
}
|
||
}
|
||
if (!user)
|
||
user = u;
|
||
if (!pass)
|
||
pass = m_sprintf("%s%s", p, hostname);
|
||
|
||
dir = read_ncftp_config(&host);
|
||
|
||
if ((s = find_dcc(host, "ftpopen", NULL, DCC_FTPOPEN, 0, -1, -1)))
|
||
{
|
||
put_it("%s", convert_output_format("$G %GFTP%n A previous DCC FTP to $0 exists", "%s", host));
|
||
new_free(&host);
|
||
return;
|
||
}
|
||
|
||
#if defined(WINNT) || defined(__EMX__)
|
||
if ((snum = connect_by_number(host, &port, SERVICE_CLIENT, PROTOCOL_TCP, 0)) < 0)
|
||
#else
|
||
if ((snum = connect_by_number(host, &port, SERVICE_CLIENT, PROTOCOL_TCP, 1)) < 0)
|
||
#endif
|
||
{
|
||
put_it("%s", convert_output_format("$G %gFTP%n command failed connect", NULL, NULL));
|
||
new_free(&host);
|
||
return;
|
||
}
|
||
else
|
||
{
|
||
DCC_int *new;
|
||
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 = port;
|
||
new->blocksize = blocksize;
|
||
get_time(&new->starttime);
|
||
get_time(&new->lasttime);
|
||
malloc_strcpy(&new->userhost, user);
|
||
new->encrypt = pass; /* these are not a mem leak */
|
||
new->user = host; /* free'd in handle_ftp() */
|
||
malloc_strcpy(&new->filename, "ftpopen");
|
||
new->othername = dir;
|
||
|
||
set_socketinfo(snum, new);
|
||
|
||
}
|
||
t_host = alloca(strlen(host)+4);
|
||
strcpy(t_host, "-");
|
||
strcat(t_host, host);
|
||
addtabkey(t_host, "msg", 0);
|
||
return;
|
||
}
|
||
|
||
|
||
void dcc_rename(char *command, char *args)
|
||
{
|
||
DCC_List *tmp;
|
||
DCC_int *n;
|
||
char *nick,
|
||
*filename;
|
||
|
||
nick = next_arg(args, &args);
|
||
filename = new_next_arg(args, &args);
|
||
if (!nick || !filename || !*filename)
|
||
{
|
||
put_it("%s", convert_output_format("$G /DCC rename nick filename", NULL, NULL));
|
||
return;
|
||
}
|
||
for (tmp = pending_dcc; tmp; tmp = tmp->next)
|
||
{
|
||
if (my_stricmp(tmp->nick, nick))
|
||
continue;
|
||
n = (DCC_int *)tmp->sock.info;
|
||
malloc_strcpy(&n->filename, filename);
|
||
break;
|
||
}
|
||
}
|
||
|
||
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))
|
||
break;
|
||
}
|
||
if (!dcc_types[i]->name)
|
||
return 0;
|
||
if (dcc_types[i]->init_func)
|
||
return (*dcc_types[i]->init_func)(type, nick, uhost, description, size, extra, TempLong, TempInt);
|
||
return 0;
|
||
}
|
||
|
||
int BX_add_dcc_bind(char *name, char *module, void *init_func, void *open_func, void *input, void *output, void *close_func)
|
||
{
|
||
int i;
|
||
for (i = 0; dcc_types[i]->name; i++)
|
||
{
|
||
if (!my_stricmp(dcc_types[i]->name, name))
|
||
break;
|
||
}
|
||
if (i >= 0xfe) return 0;
|
||
if (!dcc_types[i])
|
||
{
|
||
RESIZE(dcc_types, struct _dcc_types_ *, i + 2);
|
||
dcc_types[i] = new_malloc(sizeof(struct _dcc_types_));
|
||
}
|
||
if (!dcc_types[i]->name)
|
||
malloc_strcpy(&dcc_types[i]->name, name);
|
||
malloc_strcpy(&dcc_types[i]->module, module);
|
||
dcc_types[i]->init_func = init_func;
|
||
dcc_types[i]->open_func = open_func;
|
||
dcc_types[i]->input = input;
|
||
dcc_types[i]->output = output;
|
||
dcc_types[i]->close_func = close_func;
|
||
dcc_types[i]->type = i;
|
||
return i;
|
||
}
|
||
|
||
int BX_remove_dcc_bind(char *name, int type)
|
||
{
|
||
int i = type & DCC_TYPES;
|
||
if (!dcc_types[i]->module)
|
||
return 0;
|
||
dcc_types[i]->init_func = NULL;
|
||
dcc_types[i]->open_func = NULL;
|
||
dcc_types[i]->input = NULL;
|
||
dcc_types[i]->output = NULL;
|
||
dcc_types[i]->close_func = NULL;
|
||
new_free(&dcc_types[i]->module);
|
||
if (i > DCC_FTPSEND)
|
||
{
|
||
new_free(&dcc_types[i]->name);
|
||
new_free(&dcc_types[i]);
|
||
/* RESIZE(dcc_types, struct _dcc_types *, i - 1);*/
|
||
}
|
||
return 1;
|
||
}
|
||
|
||
int BX_remove_all_dcc_binds(char *name)
|
||
{
|
||
int ret = 0;
|
||
int i, j;
|
||
/* scan to end of list */
|
||
for (i = 0; dcc_types[i]->name; i++);
|
||
i--;
|
||
for (j = i; j > 0; j--)
|
||
ret += remove_dcc_bind(dcc_types[j]->name, dcc_types[j]->type);
|
||
return ret;
|
||
}
|
||
|
||
void init_dcc_table(void)
|
||
{
|
||
int i;
|
||
for (i = 0; _dcc_types[i].name; i++);
|
||
RESIZE(dcc_types, struct _dcc_types_ *, i + 1);
|
||
for (i = 0; _dcc_types[i].name; i++)
|
||
{
|
||
dcc_types[i] = new_malloc(sizeof(struct _dcc_types_));
|
||
dcc_types[i]->name = m_strdup(_dcc_types[i].name);
|
||
dcc_types[i]->type = _dcc_types[i].type;
|
||
}
|
||
dcc_types[i] = new_malloc(sizeof(struct _dcc_types_));
|
||
}
|
||
|
||
char *get_dcc_info(SocketList *s, DCC_int *n, int i)
|
||
{
|
||
char local_type[80];
|
||
*local_type = 0;
|
||
if (s->flags & DCC_TDCC)
|
||
strcpy(local_type, "T");
|
||
strcat(local_type, dcc_types[s->flags & DCC_TYPES]->name);
|
||
return m_sprintf("%s %s %s %ld %lu %lu %lu %s #%d %d",
|
||
local_type, s->server,
|
||
s->flags & DCC_OFFER ? "Offer":
|
||
s->flags & DCC_WAIT ? "Wait":
|
||
s->flags & DCC_ACTIVE? "Active":"Unknown",
|
||
(long)n->starttime.tv_sec,
|
||
(unsigned long)n->transfer_orders.byteoffset,
|
||
(unsigned long)n->bytes_sent, (unsigned long)n->bytes_read,
|
||
n->filename, i, n->server);
|
||
}
|
||
|
||
void dcc_raw_transmit (char *user, char *text, char *type)
|
||
{
|
||
return;
|
||
}
|
||
|
||
#if 0
|
||
/*
|
||
* Usage: $listen(<port>)
|
||
*/
|
||
char *dcc_raw_listen (unsigned short port)
|
||
{
|
||
DCC_list *Client;
|
||
char *PortName;
|
||
|
||
set_display_target(NULL, LOG_DCC);
|
||
|
||
if (port && port < 1025)
|
||
{
|
||
say("May not bind to a privileged port");
|
||
set_display_target(NULL, LOG_CURRENT);
|
||
return NULL;
|
||
}
|
||
PortName = ltoa(port);
|
||
Client = dcc_searchlist("raw_listen", PortName,
|
||
DCC_RAW_LISTEN, 1, NULL, -1);
|
||
|
||
if (Client->flags & DCC_ACTIVE)
|
||
{
|
||
say("A previous DCC RAW_LISTEN on %s exists", PortName);
|
||
set_display_target(NULL, LOG_CURRENT);
|
||
return NULL;
|
||
}
|
||
|
||
if ((Client->read = connect_by_number(NULL, &port, SERVICE_SERVER, PROTOCOL_TCP)) < 0)
|
||
{
|
||
say("Couldnt establish listening socket: [%d] %s", Client->read, strerror(errno));
|
||
Client->flags |= DCC_DELETE;
|
||
set_display_target(NULL, LOG_CURRENT);
|
||
return NULL;
|
||
}
|
||
|
||
new_open(Client->read);
|
||
get_time(&Client->starttime);
|
||
Client->local_port = port;
|
||
Client->flags |= DCC_ACTIVE;
|
||
Client->user = m_strdup(ltoa(Client->local_port));
|
||
set_display_target(NULL, LOG_CURRENT);
|
||
|
||
return m_strdup(Client->user);
|
||
}
|
||
|
||
|
||
/*
|
||
* Usage: $connect(<hostname> <portnum>)
|
||
*/
|
||
char *dcc_raw_connect(char *host, u_short port)
|
||
{
|
||
DCC_list *Client;
|
||
char *PortName;
|
||
struct in_addr address;
|
||
struct hostent *hp;
|
||
|
||
set_display_target(NULL, LOG_DCC);
|
||
if ((address.s_addr = inet_addr(host)) == (unsigned) -1)
|
||
{
|
||
if (!(hp = gethostbyname(host)))
|
||
{
|
||
say("Unknown host: %s", host);
|
||
set_display_target(NULL, LOG_CURRENT);
|
||
return m_strdup(empty_string);
|
||
}
|
||
memmove(&address, hp->h_addr, sizeof(address));
|
||
}
|
||
Client = dcc_searchlist(host, ltoa(port), DCC_RAW, 1, NULL, -1);
|
||
if (Client->flags & DCC_ACTIVE)
|
||
{
|
||
say("A previous DCC RAW to %s on %s exists", host, ltoa(port));
|
||
set_display_target(NULL, LOG_CURRENT);
|
||
return m_strdup(empty_string);
|
||
}
|
||
|
||
/* Sorry. The missing 'htons' call here broke $connect() */
|
||
Client->remport = htons(port);
|
||
memmove((char *)&Client->remote, (char *)&address, sizeof(address));
|
||
Client->flags = DCC_THEIR_OFFER | DCC_RAW;
|
||
if (!dcc_open(Client))
|
||
{
|
||
set_display_target(NULL, LOG_CURRENT);
|
||
return m_strdup(empty_string);
|
||
}
|
||
|
||
PortName = ltoa(Client->read);
|
||
Client->user = m_strdup(PortName);
|
||
if (do_hook(DCC_RAW_LIST, "%s %s E %d", PortName, host, port))
|
||
if (do_hook(DCC_CONNECT_LIST,"%s RAW %s %d",PortName, host, port))
|
||
say("DCC RAW connection to %s on %s via %d established", host, PortName, port);
|
||
|
||
set_display_target(NULL, LOG_CURRENT);
|
||
return m_strdup(PortName);
|
||
}
|
||
#endif
|
||
|
||
char *dcc_raw_connect(char *host, u_short port)
|
||
{
|
||
return m_strdup("-1");
|
||
}
|
||
|
||
char *dcc_raw_listen(int port)
|
||
{
|
||
#if 0
|
||
SocketList *Client;
|
||
char *PortName;
|
||
|
||
set_display_target(NULL, LOG_DCC);
|
||
|
||
if (port && port < 1025)
|
||
{
|
||
say("May not bind to a privileged port");
|
||
set_display_target(NULL, LOG_CURRENT);
|
||
return NULL;
|
||
}
|
||
|
||
PortName = ltoa(port);
|
||
Client = find_dcc(PortName, NULL, "raw_listen", DCC_RAW_LISTEN, 1, 0, -1);
|
||
Client = dcc_searchlist("raw_listen", PortName,
|
||
DCC_RAW_LISTEN, 1, NULL, -1);
|
||
|
||
if (Client->flags & DCC_ACTIVE)
|
||
{
|
||
say("A previous DCC RAW_LISTEN on %s exists", PortName);
|
||
set_display_target(NULL, LOG_CURRENT);
|
||
return NULL;
|
||
}
|
||
|
||
if ((Client->read = connect_by_number(NULL, &port, SERVICE_SERVER, PROTOCOL_TCP)) < 0)
|
||
{
|
||
say("Couldnt establish listening socket: [%d] %s", Client->read, strerror(errno));
|
||
Client->flags |= DCC_DELETE;
|
||
set_display_target(NULL, LOG_CURRENT);
|
||
return NULL;
|
||
}
|
||
|
||
new_open(Client->read);
|
||
get_time(&Client->starttime);
|
||
Client->local_port = port;
|
||
Client->flags |= DCC_ACTIVE;
|
||
Client->user = m_strdup(ltoa(Client->local_port));
|
||
set_display_target(NULL, LOG_CURRENT);
|
||
|
||
return m_strdup(Client->user);
|
||
#endif
|
||
return m_strdup("-1");
|
||
}
|
||
|
||
|
||
|
||
int close_dcc_number(int number)
|
||
{
|
||
if (!check_dcc_socket(number))
|
||
return 0;
|
||
erase_dcc_info(number, 1, NULL);
|
||
close_socketread(number);
|
||
return 1;
|
||
}
|