Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
BitchX
GitHub Repository: BitchX/BitchX1.3
Path: blob/master/source/dcc.c
1069 views
1
2
/*
3
* dcc.c: Things dealing with client to client connections.
4
*
5
* Copyright(c) 1998 Colten Edwards aka panasync.
6
* After alot of unhappiness with the old dcc.c code I took it upon myself
7
* to rewrite this code. The only parts not greatly changed by myself was
8
* code I had written by me in the first place. ie the ftp code and the
9
* dcc botlink code. Some great improvements in dcc speed were realized
10
* using non-blocking connects. All the previous dcc modes/commands are still
11
* in place and available.
12
*/
13
14
#include "irc.h"
15
static char cvsrevision[] = "$Id: dcc.c 104 2010-09-30 13:26:06Z keaston $";
16
CVS_REVISION(dcc_c)
17
#include "struct.h"
18
19
#include <sys/stat.h>
20
#include <stdarg.h>
21
#include <stdio.h>
22
#include <dirent.h>
23
#include <sys/ioctl.h>
24
25
#ifdef HAVE_SYS_FILIO_H
26
#include <sys/filio.h>
27
#endif
28
29
#if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX) && !defined(__EMX__)
30
# define IO_ARRAYLEN sysconf(_SC_OPEN_MAX)
31
#else
32
# ifdef FD_SETSIZE
33
# define IO_ARRAYLEN FD_SETSIZE
34
# else
35
# define IO_ARRAYLEN NFDBITS
36
# endif
37
#endif
38
39
#include "ctcp.h"
40
#include "encrypt.h"
41
#include "cdcc.h"
42
#include "dcc.h"
43
#include "hook.h"
44
#include "ircaux.h"
45
#include "lastlog.h"
46
#include "list.h"
47
#include "newio.h"
48
#include "output.h"
49
#include "parse.h"
50
#include "server.h"
51
#include "status.h"
52
#include "vars.h"
53
#include "who.h"
54
#include "window.h"
55
#include "screen.h"
56
#include "ircterm.h"
57
#include "hook.h"
58
#include "misc.h"
59
#include "tcl_bx.h"
60
#include "userlist.h"
61
#include "hash2.h"
62
#include "gui.h"
63
#define MAIN_SOURCE
64
#include "modval.h"
65
66
#include <float.h>
67
68
#ifdef WINNT
69
#include <windows.h>
70
#endif
71
72
extern int use_socks;
73
74
#define DCC_HASHSIZE 11
75
HashEntry dcc_no_flood[DCC_HASHSIZE];
76
77
struct _dcc_types_
78
{
79
char *name;
80
char *module;
81
int type;
82
int (*init_func)();
83
int (*open_func)();
84
int (*input)();
85
int (*output)();
86
int (*close_func)();
87
88
} _dcc_types[] =
89
{
90
{"<none>", NULL, 0, NULL, NULL, NULL, NULL, NULL},
91
{"CHAT", NULL, DCC_CHAT, NULL, NULL, NULL, NULL, NULL},
92
{"SEND", NULL, DCC_FILEOFFER, NULL, NULL, NULL, NULL, NULL},
93
{"GET", NULL, DCC_FILEREAD, NULL, NULL, NULL, NULL, NULL},
94
{"RAW_LISTEN", NULL, DCC_RAW_LISTEN, NULL, NULL, NULL, NULL, NULL},
95
{"RAW", NULL, DCC_RAW, NULL, NULL, NULL, NULL, NULL},
96
{"RESEND", NULL, DCC_REFILEOFFER, NULL, NULL, NULL, NULL, NULL},
97
{"REGET", NULL, DCC_REFILEREAD, NULL, NULL, NULL, NULL, NULL},
98
{"BOT", NULL, DCC_BOTMODE, NULL, NULL, NULL, NULL, NULL},
99
{"FTP", NULL, DCC_FTPOPEN, NULL, NULL, NULL, NULL, NULL},
100
{"FTPGET", NULL, DCC_FTPGET, NULL, NULL, NULL, NULL, NULL},
101
{"FTPSEND", NULL, DCC_FTPSEND, NULL, NULL, NULL, NULL, NULL},
102
{NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL}
103
};
104
105
struct _dcc_types_ **dcc_types = NULL;
106
107
static char DCC_current_transfer_buffer[BIG_BUFFER_SIZE/4];
108
unsigned int send_count_stat = 0;
109
unsigned int get_count_stat = 0;
110
char *last_chat_req = NULL;
111
static int dcc_quiet = 0;
112
static int dcc_paths = 0;
113
static int dcc_overwrite_var = 0;
114
double dcc_bytes_in = 0;
115
double dcc_bytes_out = 0;
116
double dcc_max_rate_in = 0.0;
117
static double dcc_min_rate_in = DBL_MAX;
118
double dcc_max_rate_out = 0.0;
119
static double dcc_min_rate_out = DBL_MAX;
120
121
time_t dcc_timeout = 600; /* global /set dcc_timeout */
122
123
static int dcc_count = 0;
124
125
126
127
128
/* new dcc handler */
129
#include "irc.h"
130
#include "ircaux.h"
131
#include "struct.h"
132
#include "misc.h"
133
134
extern Server *server_list;
135
136
typedef struct _DCC_List
137
{
138
struct _DCC_List *next;
139
char *nick; /* do NOT free this. it's a shared pointer. */
140
SocketList sock;
141
} DCC_List;
142
143
static DCC_List *pending_dcc = NULL;
144
145
146
static void process_dcc_chat(int);
147
#ifndef BITCHX_LITE
148
static void process_dcc_bot(int);
149
#endif
150
static void
151
start_dcc_chat(int);
152
static unsigned char byte_order_test (void);
153
static void dcc_update_stats(int);
154
155
static void update_transfer();
156
157
static char *strip_path(char *);
158
static void dcc_getfile_resume_demanded(char *, char *, char *, char *);
159
static void dcc_getfile_resume_start (char *, char *, char *, char *);
160
static void output_reject_ctcp (UserhostItem *, char *, char *);
161
162
extern int use_nat_address;
163
extern struct in_addr nat_address;
164
165
#if 0
166
/* sock num, type, address, port */
167
int (*dcc_open_func) (int, int, struct sockaddr_foobar, int) = NULL;
168
/* type, sock num, buffer, buff_len */
169
int (*dcc_output_func) (int, int, char *, int) = NULL;
170
/* sock num, type, buffer, new line, len buffer */
171
int (*dcc_input_func) (int, int, char *, int, int) = NULL;
172
/* socket num, address, port */
173
int (*dcc_close_func) (int, sockaddr_foobar, int) = NULL;
174
#endif
175
176
177
#define DCC_OPEN 1
178
#define DCC_INPUT 2
179
#define DCC_OUTPUT 3
180
#define DCC_CLOSE 4
181
182
int check_dcc_init(char *type, char *nick, char *uhost, char *description, char *size, char *extra, unsigned long TempLong, unsigned int TempInt);
183
/* bind type, sock num, type, address, port, buffer, buflen , newline */
184
185
#ifndef O_BINARY
186
#define O_BINARY 0
187
#endif
188
189
#define BAR_LENGTH 60
190
191
typedef struct
192
{
193
char * name;
194
dcc_function function;
195
char * help;
196
} DCC_commands;
197
198
DCC_dllcommands *dcc_dllcommands = NULL;
199
200
201
void dcc_chat(char *command, char *args);
202
void BX_dcc_filesend(char *command, char *args);
203
void BX_dcc_resend(char *command, char *args);
204
void dcc_getfile(char *command, char *args);
205
void dcc_regetfile(char *command, char *args);
206
void dcc_glist(char *command, char *args);
207
void dcc_resume(char *command, char *args);
208
void dcc_rename(char *command, char *args);
209
210
void dcc_show_active(char *command, char *args);
211
void dcc_set_quiet(char *command, char *args);
212
void dcc_set_paths(char *command, char *args);
213
void dcc_tog_rename(char *command, char *args);
214
void dcc_tog_resume(char *command, char *args);
215
void dcc_overwrite_toggle(char *command, char *args);
216
void dcc_tog_auto(char *command, char *args);
217
void dcc_stats(char *command, char *args);
218
void dcc_close(char *command, char *args);
219
void dcc_closeall(char *command, char *args);
220
void dcc_help1(char *command, char *args);
221
void dcc_exempt(char *command, char *args);
222
void dcc_ftpopen(char *command, char *args);
223
224
DCC_commands dcc_commands[] =
225
{
226
#ifndef BITCHX_LITE
227
{ "BOT", dcc_chat, NULL },
228
#endif
229
{ "CHAT", dcc_chat, "[nick]\n- Starts a dcc chat connection" },
230
{ "CLOSE", dcc_close, NULL },
231
{ "CLOSEALL", dcc_closeall, NULL },
232
{ "SEND", BX_dcc_filesend, "[-b block] [-e passwd] [-p port] [nick|nick1,nick2] filename(s)\n- Send list of files to nick(s)" },
233
{ "RESEND", BX_dcc_resend, "[-b block] [-e passwd] [-p port] [nick|nick1,nick2] filename(s)\n- Send list of files to nick(s)" },
234
{ "TSEND", BX_dcc_filesend, "[-b block] [-e passwd] [-p port] [nick|nick1,nick2] filename(s)\n- Send list of files to nick(s)" },
235
{ "TRESEND", BX_dcc_resend, "[-b block] [-e passwd] [-p port] [nick|nick1,nick2] filename(s)\n- Send list of files to nick(s)" },
236
#ifdef MIRC_BROKEN_DCC_RESUME
237
{ "RESUME", dcc_resume, NULL },
238
#endif
239
{ "GET", dcc_getfile, NULL },
240
{ "REGET", dcc_regetfile, NULL },
241
{ "TGET", dcc_getfile, NULL },
242
{ "TREGET", dcc_regetfile, NULL },
243
{ "LIST", dcc_glist, NULL },
244
{ "FTP", dcc_ftpopen, NULL },
245
{ "RENAME", dcc_rename, "nick filename" },
246
{ "ACTIVECOUNT",dcc_show_active, NULL },
247
{ "QUIETMODE", dcc_set_quiet, NULL },
248
{ "SHOWPATHS", dcc_set_paths, NULL },
249
{ "AUTORENAME", dcc_tog_rename, NULL },
250
{ "AUTORESUME", dcc_tog_resume, NULL },
251
{ "AUTOOVERWRITE",dcc_overwrite_toggle, NULL },
252
{ "AUTOGET", dcc_tog_auto, NULL },
253
{ "STATS", dcc_stats, NULL },
254
{ "EXEMPT", dcc_exempt, NULL },
255
{ "HELP", dcc_help1, NULL },
256
{ NULL, (dcc_function) NULL, NULL }
257
};
258
259
260
261
static int doing_multi = 0; /*
262
* set this if doing multiple requests
263
* helps prevent console spam by reducing
264
* the amount of output.
265
*/
266
267
#if 0
268
int add_dcc_command(char *name, char *help, void (*func)(char *, char *))
269
{
270
int count = 0;
271
if (!dcc_dllcommands) /* ooh first time. need to init. make it double*/
272
dcc_dllcommands = new_malloc(sizeof(DCC_commands) * 2);
273
else
274
{
275
for ( ; dcc_dllcommands[count].name; count++) ;
276
RESIZE(dcc_dllcommands, DCC_commands, count + 2);
277
}
278
malloc_strcpy(&dcc_dllcommands[count].name, name);
279
malloc_strcpy(&dcc_dllcommands[count].help, help);
280
dcc_dllcommands[count].function = func;
281
return count + 1;
282
}
283
284
int remove_dcc_hook(char *name)
285
{
286
int i, count = 0;
287
int done = 0;
288
for ( ; dcc_dllcommands[count].name; count++) ;
289
for (i = 0; i < count; i++)
290
{
291
if (dcc_dllcommands[i].name && !my_stricmp(dcc_dllcommands[i].name, name))
292
{
293
new_free(&dcc_dllcommands[i].name);
294
new_free(&dcc_dllcommands[i].help);
295
dcc_dllcommands[i].function = NULL;
296
done++;
297
break;
298
}
299
}
300
return done;
301
}
302
#endif
303
304
void send_ctcp_booster(char *nick, char *type, char *file, unsigned long address, unsigned short portnum, unsigned long filesize)
305
{
306
if (filesize)
307
send_ctcp(CTCP_PRIVMSG, nick, CTCP_DCC,
308
"%s %s %lu %u %lu", type, file,address, portnum, filesize);
309
else
310
send_ctcp(CTCP_PRIVMSG, nick, CTCP_DCC,
311
"%s %s %lu %u", type, file, address, portnum);
312
}
313
314
void send_reject_ctcp(char *nick, char *type, char *name)
315
{
316
/*
317
* And output it to the user
318
*/
319
userhostbase(nick, output_reject_ctcp, 1, "%s %s %s", nick, type, name ? name : "<any>");
320
}
321
322
void BX_erase_dcc_info(int s, int reject, char *format, ...)
323
{
324
DCC_int *n = NULL;
325
SocketList *s1;
326
static time_t last_reject = 0;
327
328
if (format)
329
{
330
va_list args;
331
char buffer[BIG_BUFFER_SIZE+1];
332
va_start(args, format);
333
vsnprintf(buffer, BIG_BUFFER_SIZE, format, args);
334
va_end(args);
335
put_it("%s", buffer);
336
}
337
dcc_update_stats(s);
338
339
s1 = get_socket(s);
340
if (check_dcc_socket(s) && (n = (DCC_int *)get_socketinfo(s)))
341
{
342
if (dcc_types[s1->flags & DCC_TYPES]->close_func)
343
(*dcc_types[s1->flags & DCC_TYPES]->close_func)(s, n->remote.s_addr, n->remport);
344
if (reject && ((now - last_reject) < 2))
345
send_reject_ctcp(s1->server,
346
(((s1->flags & DCC_TYPES) == DCC_FILEOFFER) ? "GET" :
347
((s1->flags & DCC_TYPES) == DCC_FILEREAD) ? "SEND" :
348
dcc_types[s1->flags & DCC_TYPES]->name),
349
n->filename);
350
last_reject = now;
351
new_free(&n->user);
352
new_free(&n->userhost);
353
new_free(&n->encrypt);
354
new_free(&n->filename);
355
new_free(&n->othername);
356
if (n->file > 0) close(n->file);
357
new_free(&n);
358
}
359
set_socketinfo(s, NULL);
360
update_transfer();
361
dcc_count--;
362
/* dcc_renumber_active();*/
363
}
364
365
/*
366
* finds an active dcc connection. one that either is already started
367
* or one that has been initiated on our side.
368
*/
369
370
SocketList *BX_find_dcc(char *nick, char *desc, char *other, int type, int create, int active, int num)
371
{
372
int i;
373
SocketList *s;
374
DCC_int *n;
375
char *othername = NULL;
376
377
for (i = 0; i < get_max_fd()+1; i++)
378
{
379
if (!check_dcc_socket(i))
380
continue;
381
s = get_socket(i);
382
n = (DCC_int *) s->info;
383
if ( (type != -1) && !((s->flags & DCC_TYPES) == type) )
384
continue;
385
if ((num != -1) && !(n->dccnum == num))
386
continue;
387
if (nick && my_stricmp(nick, s->server))
388
continue;
389
if (desc && n->filename && my_stricmp(desc, n->filename))
390
{
391
char *last;
392
if (!(last = strrchr(n->filename, '/')))
393
continue;
394
last++;
395
if (last && my_stricmp(desc, last))
396
{
397
if (!othername || !n->othername)
398
continue;
399
if (my_stricmp(othername, n->othername))
400
continue;
401
}
402
}
403
if (other && n->othername && my_stricmp(other, n->othername))
404
continue;
405
if (active == 0 && (s->flags & DCC_ACTIVE))
406
continue;
407
if (active == 1 && !(s->flags & DCC_ACTIVE))
408
continue;
409
return s;
410
}
411
return NULL;
412
}
413
414
/*
415
* finds a pending dcc which the other end has initiated.
416
*/
417
DCC_List *find_dcc_pending(char *nick, char *desc, char *othername, int type, int remove, int num)
418
{
419
unsigned long dcc_type;
420
unsigned long flags;
421
SocketList *s;
422
DCC_int *n;
423
DCC_List *new_i;
424
DCC_List *last_i = NULL;
425
for (new_i = pending_dcc; new_i; last_i = new_i, new_i = new_i->next)
426
{
427
flags = new_i->sock.flags;
428
s = &new_i->sock;
429
n = (DCC_int *)s->info;
430
dcc_type = s->flags & DCC_TYPES;
431
if ((type != -1) && !(dcc_type == type))
432
continue;
433
if ((num != -1) && !(n->dccnum == num))
434
continue;
435
if (nick && my_stricmp(nick, new_i->sock.server))
436
continue;
437
if ((desc && my_stricmp(desc, n->filename)))
438
{
439
char *last;
440
if (!(last = strrchr(n->filename, '/')))
441
continue;
442
last++;
443
if (last && my_stricmp(desc, last))
444
continue;
445
}
446
if (othername && n->othername && my_stricmp(othername, n->othername))
447
continue;
448
if (remove)
449
{
450
if (last_i)
451
last_i->next = new_i->next;
452
else
453
pending_dcc = new_i->next;
454
}
455
return new_i;
456
}
457
return NULL;
458
}
459
460
void add_userhost_to_chat(UserhostItem *stuff, char *nick, char *args)
461
{
462
SocketList *Client = NULL;
463
DCC_int *n = NULL;
464
if (!stuff || !nick || !stuff->nick || !stuff->user || !stuff->host || !strcmp(stuff->user, "<UNKNOWN>"))
465
return;
466
if ((Client = find_dcc(nick, "chat", NULL, DCC_CHAT, 0, -1, -1)))
467
n = (DCC_int *)get_socketinfo(Client->is_read);
468
if (n)
469
{
470
n->userhost = m_sprintf("%s@%s", stuff->user, stuff->host);
471
n->server = from_server;
472
}
473
return;
474
}
475
476
static void refileread_send_start(int s, DCC_int *n)
477
{
478
struct stat buf;
479
lseek(n->file, 0, SEEK_END);
480
/* get the size of our file to be resumed */
481
fstat(n->file, &buf);
482
n->transfer_orders.packet_id = DCC_PACKETID;
483
n->transfer_orders.byteoffset = buf.st_size;
484
n->transfer_orders.byteorder = byte_order_test();
485
put_it("%s", convert_output_format("$G %RDCC %YTelling uplink we want to start at%n: $0", "%s", ulongcomma(n->transfer_orders.byteoffset)));
486
send(s, (const char *)&n->transfer_orders, sizeof(struct transfer_struct), 0);
487
}
488
489
#ifdef HAVE_SSL
490
int SSL_dcc_create(SocketList *s, int sock, int doconnect)
491
{
492
set_blocking(sock);
493
if(doconnect)
494
s->ctx = SSL_CTX_new (SSLv23_client_method());
495
else
496
s->ctx = SSL_CTX_new (SSLv23_server_method());
497
SSL_CTX_set_cipher_list(s->ctx, "ADH:@STRENGTH");
498
s->ssl_fd = SSL_new (s->ctx);
499
SSL_set_fd (s->ssl_fd, sock);
500
if(doconnect)
501
return SSL_connect (s->ssl_fd);
502
return SSL_accept(s->ssl_fd);
503
}
504
#endif
505
506
DCC_int *BX_dcc_create(char *nick, char *filename, char *passwd, unsigned long filesize, int port, int type, unsigned long flags, void (*func)(int))
507
{
508
509
struct sockaddr_foobar myip, blah;
510
int ofs = from_server;
511
int s;
512
DCC_int *new = NULL;
513
DCC_List *new_i;
514
515
516
if (from_server == -1)
517
from_server = get_window_server(0);
518
if (from_server == -1)
519
return NULL;
520
if (get_int_var(DCC_USE_GATEWAY_ADDR_VAR))
521
blah = get_server_uh_addr(from_server);
522
else
523
blah = get_server_local_addr(from_server);
524
memcpy(&myip, &blah, sizeof(struct sockaddr_foobar));
525
526
if (use_nat_address)
527
{
528
myip.sf_family = AF_INET;
529
myip.sf_addr.s_addr = nat_address.s_addr;
530
}
531
532
set_display_target(NULL, LOG_DCC);
533
if ( ((new_i = find_dcc_pending(nick, filename, NULL, type, 1, -1)) && new_i->sock.flags & DCC_OFFER) || (flags & DCC_OFFER))
534
{
535
SocketList *s = NULL;
536
int new_s;
537
struct sockaddr_in remaddr;
538
int rl = sizeof(remaddr);
539
540
541
if (!new_i && !(new_i = find_dcc_pending(nick, filename, NULL, type, 1, -1)))
542
return NULL;
543
s = &new_i->sock;
544
new = (DCC_int *)s->info;
545
546
#ifdef DCC_CNCT_PEND
547
flags |= DCC_CNCT_PEND;
548
#endif
549
new->remport = ntohs(new->remport);
550
if ((new_s = connect_by_number(inet_ntoa(new->remote), &new->remport, SERVICE_CLIENT, PROTOCOL_TCP, 0)) < 0
551
#ifdef HAVE_SSL
552
|| (flags & DCC_SSL ? SSL_dcc_create(s, new_s, 1) : 0) < 0
553
#endif
554
)
555
{
556
#ifdef HAVE_SSL
557
SSL_show_errors();
558
#endif
559
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"));
560
close_socketread(s->is_read);
561
from_server = ofs;
562
new_free(&new_i->nick);
563
new_free(&new_i);
564
reset_display_target();
565
return NULL;
566
}
567
new->remport = ntohs(new->remport);
568
flags |= DCC_ACTIVE;
569
add_socketread(new_s, port, flags|type, nick, new_i->sock.func_read, NULL);
570
set_socketinfo(new_s, new);
571
if ((getpeername(new_s, (struct sockaddr *) &remaddr, &rl)) != -1)
572
{
573
574
flags &= ~DCC_OFFER;
575
if (type != DCC_RAW)
576
{
577
int blah;
578
579
if (type == DCC_FILEOFFER)
580
blah = do_hook(DCC_CONNECT_LIST,"%s %s %s %d %ld %s",
581
nick, dcc_types[type]->name,
582
inet_ntoa(remaddr.sin_addr),
583
ntohs(remaddr.sin_port),(unsigned long)new->filesize, new->filename);
584
else
585
blah = do_hook(DCC_CONNECT_LIST,"%s %s %s %d",
586
nick, dcc_types[type]->name,
587
inet_ntoa(remaddr.sin_addr),
588
ntohs(remaddr.sin_port));
589
if (blah && !dcc_quiet)
590
put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_CONNECT_FSET),
591
"%s %s %s %s %s %d", update_clock(GET_TIME), dcc_types[type]->name, nick, new->userhost?new->userhost:"u@h",
592
inet_ntoa(remaddr.sin_addr), (int)ntohs(remaddr.sin_port)));
593
}
594
}
595
if (dcc_types[type]->open_func)
596
(*dcc_types[type]->open_func)(new_s, type, new->remote.s_addr, ntohs(remaddr.sin_port));
597
if (type == DCC_REFILEREAD)
598
refileread_send_start(new_s, new);
599
if (get_int_var(DCC_FAST_VAR)
600
#ifdef HAVE_SSL
601
&& !(flags & DCC_SSL)
602
#endif
603
)
604
{
605
set_non_blocking(new_s);
606
new->dcc_fast = 1;
607
}
608
set_socketflags(new_s, flags|type);
609
get_time(&new->starttime);
610
get_time(&new->lasttime);
611
new_free(&new_i->nick);
612
new_free(&new_i);
613
}
614
else
615
{
616
char *nopath = NULL;
617
char *file = NULL;
618
char *Type;
619
unsigned short portnum = port;
620
621
/* If a port isn't specified and random local ports is on
622
* generate a random port to use.
623
*/
624
if (!port && get_int_var(RANDOM_LOCAL_PORTS_VAR))
625
portnum = random_number(65535 - 1024) + 1024;
626
627
if (get_int_var(DCC_FORCE_PORT_VAR))
628
portnum = get_int_var(DCC_FORCE_PORT_VAR);
629
630
#ifdef DCC_CNCT_PEND
631
flags |= DCC_CNCT_PEND;
632
#endif
633
flags |= DCC_WAIT;
634
if ((s = connect_by_number(NULL, &portnum, SERVICE_SERVER, PROTOCOL_TCP, 1)) < 0)
635
{
636
/* If a port was specified and we failed, and
637
* random local ports is on, try a random port.
638
*/
639
if(port && get_int_var(RANDOM_LOCAL_PORTS_VAR))
640
portnum = random_number(65535 - 1024) + 1024;
641
else
642
portnum = 0;
643
if ((s = connect_by_number(NULL, &portnum, SERVICE_SERVER, PROTOCOL_TCP, 1)) < 0)
644
{
645
/* Finally try to get a system port number by using 0 */
646
portnum = 0;
647
s = connect_by_number(NULL, &portnum, SERVICE_SERVER, PROTOCOL_TCP, 1);
648
}
649
}
650
if (s < 0)
651
{
652
put_it("%s", convert_output_format("$G %RDCC%n Unable to create connection: $0-", "%s", errno ? strerror(errno) : "Unknown Host"));
653
reset_display_target();
654
from_server = ofs;
655
return NULL;
656
}
657
Type = dcc_types[type]->name;
658
add_socketread(s, portnum, flags|type, nick, func, NULL);
659
add_sockettimeout(s, 120, NULL);
660
661
new = new_malloc(sizeof(DCC_int));
662
new->struct_type = DCC_STRUCT_TYPE;
663
new->othername = m_strdup(ltoa(portnum));
664
new->localport = port;
665
new->dccnum = ++dcc_count;
666
get_time(&new->lasttime);
667
set_socketinfo(s, new);
668
669
if (!(flags & DCC_TWOCLIENTS))
670
{
671
reset_display_target();
672
from_server = ofs;
673
return new;
674
}
675
if (passwd)
676
new->encrypt = m_strdup(passwd);
677
if (filename)
678
{
679
char *p;
680
if ((nopath = strrchr(filename, '/')))
681
nopath++;
682
else
683
nopath = filename;
684
file = LOCAL_COPY(nopath);
685
p = file;
686
while ((p = strchr(p, ' ')))
687
*p = '_';
688
if (strcmp(filename, "bxglobal"))
689
new->filename = m_strdup(filename);
690
else
691
new->filename = m_strdup("_bxglobal");
692
}
693
new->filesize = filesize;
694
#if 0
695
if (use_socks && get_string_var(SOCKS_HOST_VAR))
696
{
697
struct hostent *hp;
698
struct sockaddr_in socks;
699
unsigned long addr;
700
hp = gethostbyname(get_string_var(SOCKS_HOST_VAR));
701
memcpy(&socks, hp->h_addr, sizeof(hp->h_length));
702
addr = inet_addr(inet_ntoa(socks.sin_addr));
703
send_ctcp_booster(nick, Type, file, addr, portnum, filesize);
704
}
705
else
706
#endif
707
send_ctcp_booster(nick, Type, file, ntohl(myip.sf_addr.s_addr), portnum, filesize);
708
if (!doing_multi && !dcc_quiet)
709
{
710
if (filesize)
711
{
712
if (do_hook(DCC_OFFER_LIST, "%s %s %s %lu",
713
nick, Type, file, filesize))
714
put_it("%s", convert_output_format(fget_string_var(FORMAT_SEND_DCC_CHAT_FSET),
715
"%s %s %s", update_clock(GET_TIME), Type, nick));
716
}
717
else
718
{
719
if (do_hook(DCC_OFFER_LIST, "%s %s %s", nick, Type, file))
720
put_it("%s", convert_output_format(fget_string_var(FORMAT_SEND_DCC_CHAT_FSET),
721
"%s %s %s", update_clock(GET_TIME), Type, nick));
722
}
723
}
724
}
725
reset_display_target();
726
from_server = ofs;
727
return new;
728
}
729
730
static void start_dcc_chat(int s)
731
{
732
struct sockaddr_in remaddr;
733
int sra;
734
int type;
735
int new_s = -1;
736
char *nick = NULL;
737
unsigned long flags;
738
DCC_int *n = NULL;
739
SocketList *sa, *new_sa;
740
void (*func)(int) = process_dcc_chat;
741
742
sa = get_socket(s);
743
flags = sa->flags;
744
nick = sa->server;
745
sra = sizeof(struct sockaddr_in);
746
new_s = my_accept(s, (struct sockaddr *) &remaddr, &sra);
747
type = flags & DCC_TYPES;
748
n = get_socketinfo(s);
749
n->user = m_strdup(nick);
750
set_display_target(NULL, LOG_DCC);
751
#ifndef BITCHX_LITE
752
if (type == DCC_BOTMODE) func = process_dcc_bot;
753
#endif
754
if ((add_socketread(new_s, ntohs(remaddr.sin_port), flags, nick, func, NULL)) < 0)
755
{
756
erase_dcc_info(s, 0, "%s", convert_output_format("$G %RDCC error: accept() failed. punt!!", NULL, NULL));
757
close_socketread(s);
758
return;
759
}
760
flags &= ~DCC_WAIT;
761
flags |= DCC_ACTIVE;
762
set_socketflags(new_s, flags);
763
set_socketinfo(new_s, n);
764
765
new_sa = get_socket(new_s);
766
#ifdef HAVE_SSL
767
if((flags & DCC_SSL) && SSL_dcc_create(new_sa, new_s, 0) < 0)
768
{
769
say("SSL_accept failed.");
770
SSL_show_errors();
771
return;
772
}
773
#endif
774
775
if (do_hook(DCC_CONNECT_LIST, "%s %s %s %d", nick, dcc_types[type]->name,
776
inet_ntoa(remaddr.sin_addr), ntohs(remaddr.sin_port)))
777
put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_CONNECT_FSET),
778
"%s %s %s %s %s %d", update_clock(GET_TIME),
779
dcc_types[type]->name,
780
nick, n->userhost?n->userhost:"u@h",
781
inet_ntoa(remaddr.sin_addr),ntohs(remaddr.sin_port)));
782
if ((type == DCC_BOTMODE) && n->encrypt)
783
new_free(&n->encrypt);
784
get_time(&n->starttime);
785
close_socketread(s);
786
787
if (dcc_types[type]->open_func)
788
(*dcc_types[type]->open_func)(new_s, type, n->remote.s_addr, ntohs(remaddr.sin_port));
789
reset_display_target();
790
}
791
792
static void process_dcc_chat(int s)
793
{
794
unsigned long flags;
795
char tmp[BIG_BUFFER_SIZE+1];
796
char *bufptr;
797
long bytesread;
798
char *nick;
799
int type;
800
SocketList *sl;
801
802
flags = get_socketflags(s);
803
nick = get_socketserver(s);
804
type = flags & DCC_TYPES;
805
sl = get_socket(s);
806
bufptr = tmp;
807
if (dcc_types[type]->input)
808
bytesread = (*dcc_types[type]->input)(s, type, bufptr, 1, BIG_BUFFER_SIZE);
809
else
810
#ifdef HAVE_SSL
811
bytesread = dgets(bufptr, s, 1, BIG_BUFFER_SIZE, sl->ssl_fd);
812
#else
813
bytesread = dgets(bufptr, s, 1, BIG_BUFFER_SIZE, NULL);
814
#endif
815
816
set_display_target(nick, LOG_DCC);
817
switch(bytesread)
818
{
819
case -1:
820
{
821
const char *real_tmp = dgets_strerror(dgets_errno);
822
if (do_hook(DCC_LOST_LIST, "%s %s %s", nick, dcc_types[type]->name, real_tmp))
823
put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_ERROR_FSET),
824
"%s %s %s %s", update_clock(GET_TIME),
825
dcc_types[type]->name, nick, real_tmp));
826
erase_dcc_info(s, 1, NULL);
827
close_socketread(s);
828
break;
829
}
830
case 0:
831
break;
832
default:
833
{
834
char *equal_nickname = NULL;
835
char *uhost, *p;
836
DCC_int *n = NULL;
837
838
n = get_socketinfo(s);
839
if ((p = strrchr(tmp, '\r')))
840
*p = 0;
841
if ((p = strrchr(tmp, '\n')))
842
*p = 0;
843
my_decrypt(tmp, strlen(tmp), n->encrypt);
844
n->bytes_read += bytesread;
845
set_display_target(nick, LOG_DCC);
846
uhost = alloca(200);
847
*uhost = 0;
848
if (n->userhost)
849
uhost = n->userhost;
850
else
851
strmopencat(uhost, 99, "Unknown@", "unknown"/*inet_ntoa(remaddr.sin_addr)*/, NULL);
852
FromUserHost = uhost;
853
854
#ifndef BITCHX_LITE
855
if (*tmp == DEFAULT_BOTCHAR)
856
{
857
char *pc;
858
pc = tmp+1;
859
if ((flags & DCC_BOTCHAT))
860
{
861
if (my_strnicmp(pc, "chat", 4))
862
{
863
if (check_tcl_dcc(pc, nick, n->userhost?n->userhost:empty_string, s))
864
break;
865
}
866
} else if (!my_strnicmp(pc, "chat", 4) && check_tcl_dcc(pc, nick, n->userhost?n->userhost:empty_string, s))
867
break;
868
}
869
else if (get_int_var(BOT_MODE_VAR) && !(flags & DCC_BOTCHAT))
870
{
871
extern int cmd_password(int, char *);
872
if (cmd_password(s, tmp))
873
{
874
dcc_printf(s, "Wrong Password\n");
875
erase_dcc_info(sl->is_read, 1, NULL);
876
close_socketread(sl->is_read);
877
}
878
break;
879
}
880
#endif
881
#undef CTCP_REPLY
882
#define CTCP_MESSAGE "CTCP_MESSAGE "
883
#define CTCP_MESSAGE_LEN strlen(CTCP_MESSAGE)
884
#define CTCP_REPLY "CTCP_REPLY "
885
#define CTCP_REPLY_LEN strlen(CTCP_REPLY)
886
887
equal_nickname = alloca(strlen(nick) + 10);
888
*equal_nickname = 0;
889
strmopencat(equal_nickname, strlen(nick)+4, "=", nick, NULL);
890
891
892
if (!strncmp(tmp, CTCP_MESSAGE, CTCP_MESSAGE_LEN) ||
893
(*tmp == CTCP_DELIM_CHAR && !strncmp(tmp+1, "ACTION", 6)))
894
{
895
char *tmp2;
896
tmp2 = LOCAL_COPY(tmp);
897
strcpy(tmp, do_ctcp(equal_nickname, get_server_nickname(from_server), stripansicodes((tmp2 + ((*tmp2 == CTCP_DELIM_CHAR) ? 0 : CTCP_MESSAGE_LEN)) ) ));
898
if (!*tmp)
899
break;
900
}
901
else if (!strncmp(tmp, CTCP_REPLY, CTCP_REPLY_LEN) || *tmp == CTCP_DELIM_CHAR)
902
{
903
char *tmp2;
904
tmp2 = LOCAL_COPY(tmp);
905
strcpy(tmp, do_notice_ctcp(equal_nickname, get_server_nickname(from_server), stripansicodes(tmp2 + (((*tmp2 == CTCP_DELIM_CHAR) ? 0 : CTCP_REPLY_LEN)))));
906
if (!*tmp)
907
break;
908
}
909
if (do_hook(DCC_CHAT_LIST, "%s %s", nick, tmp))
910
{
911
addtabkey(equal_nickname, "msg", 0);
912
put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_CHAT_FSET),
913
"%s %s %s %s", update_clock(GET_TIME), nick, FromUserHost, tmp));
914
add_last_type(&last_dcc[0], MAX_LAST_MSG, nick, NULL, FromUserHost, tmp);
915
logmsg(LOG_DCC, nick, 0, "%s", tmp);
916
}
917
FromUserHost = empty_string;
918
break;
919
}
920
}
921
reset_display_target();
922
}
923
924
#ifndef BITCHX_LITE
925
static void process_dcc_bot(int s)
926
{
927
unsigned long flags;
928
char tmp[BIG_BUFFER_SIZE+1];
929
char *bufptr;
930
long bytesread;
931
char *nick;
932
int type;
933
SocketList *sl;
934
935
flags = get_socketflags(s);
936
nick = get_socketserver(s);
937
type = flags & DCC_TYPES;
938
sl = get_socket(s);
939
940
bufptr = tmp;
941
if (dcc_types[type]->input)
942
bytesread = (*dcc_types[type]->input) (type, s, bufptr, 1, BIG_BUFFER_SIZE);
943
else
944
#ifdef HAVE_SSL
945
bytesread = dgets(bufptr, s, 1, BIG_BUFFER_SIZE, sl->ssl_fd);
946
#else
947
bytesread = dgets(bufptr, s, 1, BIG_BUFFER_SIZE, NULL);
948
#endif
949
950
set_display_target(nick, LOG_DCC);
951
switch(bytesread)
952
{
953
case -1:
954
{
955
const char *real_tmp = dgets_strerror(dgets_errno);
956
if (do_hook(DCC_LOST_LIST, "%s %s %s", nick, dcc_types[type]->name, real_tmp))
957
put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_ERROR_FSET),
958
"%s %s %s %s", update_clock(GET_TIME),
959
dcc_types[type]->name, nick, real_tmp));
960
erase_dcc_info(s, 1, NULL);
961
close_socketread(s);
962
break;
963
}
964
case 0:
965
break;
966
default:
967
{
968
DCC_int *n = NULL;
969
char *p;
970
n = get_socketinfo(s);
971
if ((p = strrchr(tmp, '\r')))
972
*p = 0;
973
if ((p = strrchr(tmp, '\n')))
974
*p = 0;
975
976
my_decrypt(tmp, strlen(tmp), n->encrypt);
977
n->bytes_read += bytesread;
978
set_display_target(nick, LOG_DCC);
979
handle_dcc_bot(s, tmp);
980
}
981
}
982
reset_display_target();
983
}
984
#endif
985
986
/* flag == 1 means show it. flag == 0 used by redirect (and /ctcp) */
987
988
static void new_dcc_message_transmit (char *user, char *text, char *text_display, int type, int flag, char *cmd, int check_host)
989
{
990
SocketList *s = NULL;
991
DCC_int *n = NULL;
992
char tmp[MAX_DCC_BLOCK_SIZE+1];
993
int list = 0;
994
int len = 0;
995
char *host = NULL;
996
char thing = 0;
997
998
*tmp = 0;
999
1000
switch(type)
1001
{
1002
case DCC_CHAT:
1003
thing = '=';
1004
host = "chat";
1005
list = SEND_DCC_CHAT_LIST;
1006
break;
1007
case DCC_RAW:
1008
if (check_host)
1009
{
1010
if (!(host = next_arg(text, &text)))
1011
{
1012
put_it("%s", convert_output_format("$G %RDCC%n No host specified for DCC RAW", NULL, NULL));
1013
return;
1014
}
1015
}
1016
break;
1017
}
1018
s = find_dcc(user, host, NULL, type, 0, 1, -1);
1019
if (!s || !(s->flags & DCC_ACTIVE))
1020
{
1021
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));
1022
return;
1023
}
1024
n = (DCC_int *)s->info;
1025
1026
/*
1027
* Check for CTCPs... whee.
1028
*/
1029
if (cmd && *text == CTCP_DELIM_CHAR && strncmp(text+1, "ACTION", 6))
1030
{
1031
if (!strcmp(cmd, "PRIVMSG"))
1032
strmcpy(tmp, "CTCP_MESSAGE ", n->blocksize);
1033
else
1034
strmcpy(tmp, "CTCP_REPLY ", n->blocksize);
1035
}
1036
1037
strmcat(tmp, text, n->blocksize-3);
1038
strmcat(tmp, "\n", n->blocksize-2);
1039
1040
len = strlen(tmp);
1041
my_encrypt(tmp, len, n->encrypt);
1042
1043
if (dcc_types[type]->output)
1044
(*dcc_types[type]->output) (type, s->is_read, tmp, len);
1045
else
1046
#ifdef HAVE_SSL
1047
if(s->ssl_fd)
1048
SSL_write(s->ssl_fd, tmp, len);
1049
else
1050
#endif
1051
write(s->is_read, tmp, len);
1052
n->bytes_sent += len;
1053
1054
if (flag && type != DCC_RAW)
1055
{
1056
if (do_hook(list, "%s %s", user, text_display ? text_display : text))
1057
put_it("%s", convert_output_format(fget_string_var(FORMAT_SEND_DCC_CHAT_FSET), "%c %s %s", thing, user, text_display?text_display:text));
1058
}
1059
}
1060
1061
extern void dcc_chat_transmit (char *user, char *text, char *orig, char *type, int noisy)
1062
{
1063
int fd;
1064
1065
/*
1066
* This is just a quick hack. Its not fast, its not elegant,
1067
* and its not the best way to do this. But i whipped it up in
1068
* 15 minutes. The "best" soLution is to rewrite dcc_message_transmit
1069
* to allow us to do this sanely.
1070
*/
1071
set_display_target(NULL, LOG_DCC);
1072
if ((fd = atol(user)))
1073
{
1074
SocketList * s;
1075
char * bogus;
1076
1077
if (!check_dcc_socket(fd))
1078
{
1079
put_it("%s", convert_output_format("$G %RDCC%n Descriptor [$0] is not an open DCC RAW", "%d", fd));
1080
return;
1081
}
1082
s = get_socket(fd);
1083
bogus = alloca(strlen(text) + strlen(((DCC_int *)s->info)->filename) + 3);
1084
1085
strcpy(bogus, ((DCC_int *)s->info)->filename);
1086
strcat(bogus, space);
1087
strcat(bogus, text);
1088
1089
new_dcc_message_transmit(user, bogus, orig, DCC_RAW, noisy, type, 0);
1090
}
1091
else
1092
new_dcc_message_transmit(user, text, orig, DCC_CHAT, noisy, type, 0);
1093
reset_display_target();
1094
}
1095
1096
extern void dcc_bot_transmit (char *user, char *text, char *type)
1097
{
1098
set_display_target(user, LOG_DCC);
1099
new_dcc_message_transmit(user, text, NULL, DCC_BOTMODE, 0, type, 1);
1100
reset_display_target();
1101
}
1102
1103
extern void dcc_chat_transmit_quiet (char *user, char *text, char *type)
1104
{
1105
new_dcc_message_transmit(user, text, NULL, DCC_CHAT, 0, type, 0);
1106
}
1107
1108
int dcc_activechat(char *user)
1109
{
1110
return find_dcc(user, NULL, NULL, DCC_CHAT, 0, 1, -1) ? 1 : 0;
1111
}
1112
1113
int dcc_activebot(char *user)
1114
{
1115
return find_dcc(user, NULL, NULL, DCC_BOTMODE, 0, 1, -1) ? 1 : 0;
1116
}
1117
1118
int dcc_activeraw(char *user)
1119
{
1120
return find_dcc(user, NULL, NULL, DCC_RAW, 0, 1, -1) ? 1 : 0;
1121
}
1122
1123
int get_dcc_type(char *type)
1124
{
1125
int tdcc = 0;
1126
int i;
1127
if (!type || !*type)
1128
return -1;
1129
upper(type);
1130
if (*type == 'T')
1131
type++, tdcc = DCC_TDCC;
1132
1133
for (i = 0; dcc_types[i]->name; i++)
1134
if (!strcmp(type, dcc_types[i]->name))
1135
return i | tdcc;
1136
return -1;
1137
}
1138
1139
void process_dcc_send1(int s);
1140
void start_dcc_get(int s);
1141
1142
void register_dcc_type(char *nick, char *type, char *description, char *address, char *port, char *size, char *extra, char *uhost, void (*func1)(int))
1143
{
1144
int Ctype;
1145
unsigned long filesize = 0;
1146
SocketList *s;
1147
DCC_int *n;
1148
DCC_List *new_d = NULL;
1149
unsigned long TempLong;
1150
unsigned int TempInt;
1151
void (*func)(int) = NULL;
1152
int autoget = 0;
1153
int autoresume = 0;
1154
unsigned long tdcc = 0;
1155
char *fullname = NULL;
1156
UserList *ul = NULL;
1157
1158
set_display_target(NULL, LOG_DCC);
1159
if (description)
1160
{
1161
char *c;
1162
#if defined(__EMX__) || defined(WINNT)
1163
if ((c = strrchr(description, '/')) || (c = strrchr(description, '\\')))
1164
#else
1165
if ((c = strrchr(description, '/')))
1166
#endif
1167
description = c + 1;
1168
if (description && *description == '.')
1169
*description = '_';
1170
}
1171
if (size && *size)
1172
filesize = atol(size);
1173
1174
TempLong = strtoul(address, NULL, 10);
1175
TempInt = (unsigned)strtoul(port, NULL, 10);
1176
if (TempInt < 1024)
1177
{
1178
put_it("%s", convert_output_format("$G %RDCC%n Privileged port attempt [$0]", "%d", TempInt));
1179
reset_display_target();
1180
return;
1181
}
1182
else if (TempLong == 0 || TempInt == 0)
1183
{
1184
struct in_addr in;
1185
in.s_addr = htonl(TempLong);
1186
put_it("%s", convert_output_format("$G %RDCC%n Handshake ignored because of 0 port or address [$0:$1]", "%d %s", TempInt, inet_ntoa(in)));
1187
reset_display_target();
1188
return;
1189
}
1190
1191
if (check_dcc_init(type, nick, uhost, description, size, extra, TempLong, TempInt))
1192
return;
1193
if (*type == 'T' && *(type+1))
1194
{
1195
tdcc = DCC_TDCC;
1196
type++;
1197
}
1198
1199
1200
if (!my_stricmp(type, "CHAT"))
1201
Ctype = DCC_CHAT;
1202
else if (!my_stricmp(type, "BOT"))
1203
Ctype = DCC_BOTMODE;
1204
else if (!my_stricmp(type, "SEND"))
1205
Ctype = DCC_FILEREAD;
1206
else if (!my_stricmp(type, "RESEND"))
1207
Ctype = DCC_REFILEREAD;
1208
#ifdef MIRC_BROKEN_DCC_RESUME
1209
else if (!my_stricmp(type, "RESUME"))
1210
1211
{
1212
/*
1213
* Dont be deceieved by the arguments we're passing it.
1214
* The arguments are "out of order" because MIRC doesnt
1215
* send them in the traditional order. Ugh. Comments
1216
* borrowed from epic.
1217
*/
1218
dcc_getfile_resume_demanded(nick, description, address, port);
1219
return;
1220
}
1221
else if (!my_stricmp(type, "ACCEPT"))
1222
{
1223
/*
1224
* See the comment above.
1225
*/
1226
dcc_getfile_resume_start (nick, description, address, port);
1227
return;
1228
}
1229
#endif
1230
else
1231
{
1232
put_it("%s", convert_output_format("$G %RDCC%n Unknown DCC $0 ($1) recieved from $2", "%s %s %s", type, description, nick));
1233
reset_display_target();
1234
return;
1235
}
1236
1237
if (tdcc) type--;
1238
1239
if ((s = find_dcc(nick, description, NULL, Ctype, 0, -1, -1)))
1240
{
1241
if ((s->flags & DCC_ACTIVE))
1242
{
1243
/* collision. */
1244
put_it("%s", convert_output_format("$G %RDCC%n Recieved DCC $0 request from $1 while previous session active", "%s %s", type, nick));
1245
reset_display_target();
1246
return;
1247
}
1248
if ((s->flags && DCC_WAIT))
1249
{
1250
if (Ctype == DCC_CHAT)
1251
{
1252
autoget = 1;
1253
if (do_hook(DCC_CONNECT_LIST,"%s CHAT %s",nick, "already requested connecting"))
1254
put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_CONNECT_FSET),
1255
"%s %s %s %s %s %d", update_clock(GET_TIME), "CHAT", nick,
1256
space, "already requested connecting...", 0));
1257
dcc_chat(NULL, nick);
1258
return;
1259
}
1260
send_ctcp(CTCP_NOTICE, nick, CTCP_DCC, "DCC %s collision occured while connecting to %s (%s)", type, nickname, description);
1261
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));
1262
close_socketread(s->is_read);
1263
reset_display_target();
1264
return;
1265
}
1266
}
1267
if (do_hook(DCC_REQUEST_LIST,"%s %s %s %lu",nick, dcc_types[Ctype]->name, description, filesize))
1268
{
1269
#ifdef WANT_USERLIST
1270
ul = lookup_userlevelc(nick, FromUserHost, "*", NULL);
1271
#endif
1272
if (!dcc_quiet)
1273
{
1274
struct in_addr in;
1275
char buf[40];
1276
in.s_addr = htonl(TempLong);
1277
sprintf(buf, "%2.4g",_GMKv(filesize));
1278
if (filesize)
1279
put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_REQUEST_FSET),
1280
"%s %s \"%s\" %s %s %s %d %s %s",
1281
update_clock(GET_TIME),dcc_types[Ctype]->name, description,
1282
nick, FromUserHost,
1283
inet_ntoa(in), TempInt,
1284
_GMKs(filesize), buf));
1285
else
1286
put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_REQUEST_FSET),
1287
"%s %s %s %s %s %s %d",
1288
update_clock(GET_TIME),dcc_types[Ctype]->name,
1289
description, nick, FromUserHost,
1290
inet_ntoa(in), TempInt));
1291
}
1292
if (Ctype == DCC_CHAT)
1293
{
1294
#ifdef WANT_USERLIST
1295
if (get_int_var(BOT_MODE_VAR) && ul)
1296
autoget = 1;
1297
else
1298
#endif
1299
{
1300
extern char *last_chat_req;
1301
bitchsay("Type /chat to answer or /nochat to close");
1302
malloc_strcpy(&last_chat_req, nick);
1303
}
1304
if (beep_on_level & LOG_DCC)
1305
beep_em(1);
1306
}
1307
#if 0
1308
if ((Ctype == DCC_BOTMODE) && (p = get_string_var(BOT_PASSWORD_VAR)))
1309
{
1310
if (encrypt && !strcmp(p, encrypt))
1311
;/* do it */
1312
message_from(NULL, LOG_CRAP);
1313
return;
1314
}
1315
#endif
1316
}
1317
n = new_malloc(sizeof(DCC_int));
1318
if (uhost)
1319
n->userhost = m_strdup(uhost);
1320
n->ul = ul;
1321
n->remport = htons(TempInt);
1322
n->remote.s_addr = htonl(TempLong);
1323
n->filesize = filesize;
1324
n->filename = m_strdup(description);
1325
n->user = m_strdup(nick);
1326
n->blocksize = get_int_var(DCC_BLOCK_SIZE_VAR);
1327
n->server = from_server;
1328
n->file = -1; /* just in case */
1329
n->struct_type = DCC_STRUCT_TYPE;
1330
1331
if ((Ctype == DCC_FILEREAD) || (Ctype == DCC_REFILEREAD))
1332
{
1333
struct stat statit;
1334
char *tmp = NULL, *p;
1335
malloc_sprintf(&tmp, "%s/%s", get_string_var(DCC_DLDIR_VAR), n->filename);
1336
p = expand_twiddle(tmp);
1337
1338
if ((get_int_var(DCC_AUTOGET_VAR) || find_name_in_genericlist(nick, dcc_no_flood, DCC_HASHSIZE, 0)) &&
1339
(n->filesize/1024 < get_int_var(DCC_MAX_AUTOGET_SIZE_VAR)) )
1340
autoget = 1;
1341
if (Ctype == DCC_FILEREAD)
1342
{
1343
int exist = 0;
1344
if ( !dcc_overwrite_var && autoget && ((exist = stat(p, &statit)) == 0))
1345
{
1346
if (!get_int_var(DCC_AUTORENAME_VAR))
1347
{
1348
if (!get_int_var(DCC_AUTORESUME_VAR))
1349
{
1350
/* the file exists. warning is generated */
1351
put_it("%s", convert_output_format("$G %RDCC%n Warning: File $0 exists: use /DCC rename if you dont want to overwrite", "%s", p));
1352
autoget = 0;
1353
}
1354
else
1355
{
1356
put_it("%s", convert_output_format("$G %RDCC%n Warning: File $0 exists: trying to autoresume", "%s", p));
1357
autoresume = 1;
1358
}
1359
}
1360
else
1361
rename_file(p, &n->filename);
1362
}
1363
#ifdef MIRC_BROKEN_DCC_RESUME
1364
if (!autoget && exist)
1365
put_it("%s", convert_output_format("$G %RDCC%n Warning: File $0 exists: use /DCC RESUME nick if you want to resume this file", "%s", p));
1366
#endif
1367
}
1368
malloc_sprintf(&tmp, "%s/%s", get_string_var(DCC_DLDIR_VAR), n->filename);
1369
fullname = expand_twiddle(tmp);
1370
new_free(&tmp); new_free(&p);
1371
}
1372
1373
if (!func)
1374
{
1375
switch (Ctype)
1376
{
1377
#ifndef BITCHX_LITE
1378
case DCC_BOTMODE:
1379
func = process_dcc_bot;
1380
break;
1381
#endif
1382
case DCC_CHAT:
1383
func = process_dcc_chat;
1384
break;
1385
case DCC_REFILEREAD:
1386
case DCC_FILEREAD:
1387
func = start_dcc_get;
1388
break;
1389
case DCC_FILEOFFER:
1390
case DCC_REFILEOFFER:
1391
func = process_dcc_send1;
1392
break;
1393
default:
1394
yell("Unsupported dcc type [%s]", type);
1395
return;
1396
}
1397
}
1398
else
1399
func = func1;
1400
n->dccnum = ++dcc_count;
1401
new_d = new_malloc(sizeof(DCC_List));
1402
new_d->sock.info = n;
1403
new_d->sock.server = new_d->nick = m_strdup(nick);
1404
new_d->sock.port = TempInt;
1405
new_d->sock.flags = Ctype|DCC_OFFER|tdcc;
1406
new_d->sock.time = now + dcc_timeout;
1407
new_d->sock.func_read = func; /* point this to the startup function */
1408
new_d->next = pending_dcc;
1409
pending_dcc = new_d;
1410
if (autoget && fullname)
1411
{
1412
if (!n->filesize)
1413
{
1414
put_it("%s", convert_output_format("$G %RDCC Caution Filesize is 0!! No Autoget", NULL, NULL));
1415
reset_display_target();
1416
return;
1417
}
1418
if (autoget)
1419
{
1420
struct stat sb;
1421
if (autoresume && stat(fullname, &sb) != -1) {
1422
n->transfer_orders.byteoffset = sb.st_size;
1423
n->bytes_read = 0L;
1424
send_ctcp(CTCP_PRIVMSG, nick, CTCP_DCC, "RESUME %s %d %ld", n->filename, ntohs(n->remport), sb.st_size);
1425
} else {
1426
DCC_int *new = NULL;
1427
int mode = O_WRONLY | O_CREAT | O_BINARY;
1428
if (!dcc_quiet)
1429
{
1430
char *prompt;
1431
char local_type[30];
1432
*local_type = 0;
1433
if (tdcc)
1434
*local_type = 'T';
1435
strcat(local_type, dcc_types[Ctype]->name);
1436
lower(local_type);
1437
prompt = m_strdup(convert_output_format(get_string_var(CDCC_PROMPT_VAR), NULL, NULL));
1438
put_it("%s", convert_output_format("$0 Auto-$1ing file %C$3-%n from %K[%C$2%K]", "%s %s %s %s",
1439
prompt, local_type, nick, n->filename));
1440
new_free(&prompt);
1441
}
1442
if (Ctype == DCC_REFILEREAD)
1443
mode |= O_APPEND;
1444
if ((n->file = open(fullname, mode, 0644)) > 0)
1445
{
1446
if ((new = dcc_create(nick, n->filename, NULL, n->filesize, 0, Ctype, DCC_OFFER|tdcc, func)))
1447
new->blocksize = get_int_var(DCC_BLOCK_SIZE_VAR);
1448
}
1449
else
1450
put_it("%s", convert_output_format("$G %RDCC%n Unable to open $0-", "%s", fullname));
1451
}
1452
}
1453
}
1454
if (Ctype == DCC_CHAT && autoget)
1455
dcc_create(nick, n->filename, NULL, n->filesize, 0, Ctype, DCC_OFFER, func);
1456
reset_display_target();
1457
new_free(&fullname);
1458
}
1459
1460
void process_dcc(char *args)
1461
{
1462
char *command;
1463
int i;
1464
1465
if (!(command = next_arg(args, &args)))
1466
return;
1467
reset_display_target();
1468
if (dcc_dllcommands)
1469
{
1470
DCC_dllcommands *dcc_comm;
1471
if ((dcc_comm = (DCC_dllcommands *)find_in_list((List **)&dcc_dllcommands, command, 0)))
1472
{
1473
dcc_comm->function(dcc_comm->name, args);
1474
reset_display_target();
1475
return;
1476
}
1477
}
1478
for (i = 0; dcc_commands[i].name != NULL; i++)
1479
{
1480
if (!my_strnicmp(dcc_commands[i].name, command, strlen(command)))
1481
{
1482
dcc_commands[i].function(dcc_commands[i].name, args);
1483
reset_display_target();
1484
return;
1485
}
1486
}
1487
put_it("%s", convert_output_format("$G Unknown %RDCC%n command: $0", "%s", command));
1488
reset_display_target();
1489
}
1490
1491
1492
char *get_dcc_args(char **args, char **passwd, char **port, int *blocksize)
1493
{
1494
char *user = NULL;
1495
while (args && *args && **args)
1496
{
1497
char *argument = new_next_arg(*args, args);
1498
if (argument && *argument)
1499
{
1500
1501
if (*argument == '-')
1502
{
1503
argument++;
1504
if (*argument == 'e')
1505
*passwd = next_arg(*args, args);
1506
else if (*argument == 'p')
1507
*port = next_arg(*args, args);
1508
else if (*argument == 'b')
1509
*blocksize = my_atol(next_arg(*args, args));
1510
}
1511
else
1512
user = argument;
1513
}
1514
if (user) break;
1515
}
1516
return user;
1517
}
1518
1519
void dcc_chat(char *command, char *args)
1520
{
1521
char *user;
1522
char *nick;
1523
1524
char *passwd = NULL;
1525
char *port = NULL;
1526
char *equal_user = NULL;
1527
DCC_int *new = NULL;
1528
SocketList *s = NULL;
1529
int blocksize = get_int_var(DCC_BLOCK_SIZE_VAR);
1530
int bot = 0;
1531
int flags = 0;
1532
1533
#ifndef BITCHX_LITE
1534
if (command && !my_stricmp(command, "BOT"))
1535
bot++;
1536
#endif
1537
1538
#ifdef HAVE_SSL
1539
if(my_strnicmp(args, "-SSL", 4) == 0)
1540
{
1541
new_next_arg(args, &args);
1542
flags = DCC_SSL;
1543
}
1544
#endif
1545
1546
user = get_dcc_args(&args, &passwd, &port, &blocksize);
1547
if (!user)
1548
{
1549
put_it("%s", convert_output_format("$G %RDCC%n You must supply a nickname for DCC chat", NULL, NULL));
1550
return;
1551
}
1552
if (!blocksize || blocksize > MAX_DCC_BLOCK_SIZE)
1553
blocksize = get_int_var(DCC_BLOCK_SIZE_VAR);
1554
1555
while ((nick = next_in_comma_list(user, &user)))
1556
{
1557
if (!nick || !*nick)
1558
break;
1559
if (isme(nick)) continue;
1560
if ((s = find_dcc(nick, "chat", NULL, bot?DCC_BOTMODE:DCC_CHAT, 1, -1, -1)))
1561
{
1562
if ((s->flags & DCC_ACTIVE) || (s->flags & DCC_WAIT))
1563
put_it("%s", convert_output_format("$G %RDCC%n A previous DCC chat to $0 exists", "%s", nick));
1564
new = (DCC_int *)s->info;
1565
if (s->flags & DCC_WAIT)
1566
{
1567
send_ctcp_booster(nick,
1568
dcc_types[DCC_CHAT]->name, "chat",
1569
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),
1570
htons(s->port), new->filesize);
1571
add_sockettimeout(s->is_read, 120, NULL);
1572
}
1573
continue;
1574
}
1575
if ((new = dcc_create(nick, "chat", passwd, 0, port? atol(port) : 0, bot?DCC_BOTMODE:DCC_CHAT, DCC_TWOCLIENTS|flags, start_dcc_chat)))
1576
{
1577
new->blocksize = blocksize;
1578
if (!bot)
1579
{
1580
equal_user = alloca(strlen(nick)+4);
1581
strcpy(equal_user, "=");
1582
strcat(equal_user, nick);
1583
addtabkey(equal_user, "msg", 0);
1584
}
1585
userhostbase(nick, add_userhost_to_chat, 1, NULL);
1586
}
1587
doing_multi++;
1588
}
1589
doing_multi = 0;
1590
}
1591
1592
void close_dcc_file(int snum)
1593
{
1594
SocketList *s;
1595
DCC_int *n;
1596
char lame_ultrix[30]; /* should be plenty */
1597
char lame_ultrix2[30];
1598
char lame_ultrix3[30];
1599
char buffer[50];
1600
char *tofrom = NULL;
1601
char *filename, *p;
1602
#ifdef GUI
1603
char *who;
1604
#endif
1605
1606
double xtime;
1607
double xfer;
1608
double temp;
1609
unsigned long type;
1610
char lame_type[30];
1611
1612
s = get_socket(snum);
1613
if (!s || !(n = (DCC_int *)s->info))
1614
return;
1615
type = s->flags & DCC_TYPES;
1616
*lame_type = 0;
1617
if (s->flags & DCC_TDCC)
1618
strcpy(lame_type, "T");
1619
strcat(lame_type, dcc_types[type]->name);
1620
1621
xtime = BX_time_diff(n->starttime, get_time(NULL));
1622
xfer = (double)(n->bytes_sent ? n->bytes_sent : n->bytes_read);
1623
1624
if (xfer == 0.0)
1625
xfer = 1.0;
1626
if (xtime == 0.0)
1627
xtime = 1.0;
1628
temp = xfer / xtime;
1629
sprintf(lame_ultrix, "%2.4g %s", _GMKv(temp), _GMKs(temp));
1630
/* Cant pass %g to put_it (lame ultrix/dgux), fix suggested by sheik. */
1631
sprintf(lame_ultrix2, "%2.4g%s", _GMKv(xfer), _GMKs(xfer));
1632
sprintf(lame_ultrix3, "%2.4g", xtime);
1633
sprintf(buffer, "%%s %s %%s %%s TRANSFER COMPLETE", lame_type);
1634
1635
filename = LOCAL_COPY(n->filename);
1636
p = filename;
1637
while ((p = strchr(p, ' ')))
1638
*p = '_';
1639
1640
switch(type)
1641
{
1642
case DCC_FILEREAD:
1643
case DCC_REFILEREAD:
1644
tofrom = "from";
1645
break;
1646
case DCC_FILEOFFER:
1647
case DCC_REFILEOFFER:
1648
tofrom = "to";
1649
break;
1650
default:
1651
tofrom = "to";
1652
}
1653
set_display_target(NULL, LOG_DCC);
1654
if(do_hook(DCC_LOST_LIST,buffer,s->server, strip_path(n->filename), lame_ultrix))
1655
put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_LOST_FSET),
1656
"%s %s %s %s %s %s %s %s",
1657
update_clock(GET_TIME), lame_type, strip_path(filename),
1658
lame_ultrix2, tofrom, s->server, lame_ultrix3, lame_ultrix));
1659
1660
#ifdef GUI
1661
who = LOCAL_COPY(s->server);
1662
#endif
1663
erase_dcc_info(snum, 0, NULL);
1664
close_socketread(snum);
1665
update_transfer();
1666
update_all_status(current_window, NULL, 0);
1667
#ifdef GUI
1668
gui_setfileinfo(filename, who, from_server);
1669
#endif
1670
reset_display_target();
1671
}
1672
1673
/*
1674
* following 3 functions process dcc filesends.
1675
*/
1676
1677
void process_dcc_send1(int snum)
1678
{
1679
SocketList *s;
1680
DCC_int *n;
1681
u_32int_t bytes = 0;
1682
int bytesread = 0;
1683
char *buffer = alloca(MAX_DCC_BLOCK_SIZE+1);
1684
s = get_socket(snum);
1685
n = (DCC_int *)s->info;
1686
if (n->readwaiting || n->eof)
1687
{
1688
int numbytes = 0;
1689
if (!(s->flags & DCC_TDCC) && n->readwaiting)
1690
{
1691
if ((ioctl(snum, FIONREAD, &numbytes)) == -1)
1692
{
1693
erase_dcc_info(snum, 1, convert_output_format("$G %RDCC%n Remote $0 closed dcc send", "%s", s->server));
1694
close_socketread(snum);
1695
return;
1696
}
1697
if (numbytes)
1698
{
1699
if (read(snum, &bytes, sizeof(u_32int_t)) < sizeof(u_32int_t))
1700
{
1701
erase_dcc_info(snum, 1, convert_output_format("$G %RDCC%n Remote closed dcc send", NULL));
1702
close_socketread(snum);
1703
}
1704
bytes = (unsigned long)ntohl(bytes);
1705
get_time(&n->lasttime);
1706
if (bytes == (n->filesize - n->transfer_orders.byteoffset))
1707
{
1708
close_dcc_file(snum);
1709
return;
1710
}
1711
else if (!n->dcc_fast && (bytes != n->bytes_sent))
1712
return;
1713
n->readwaiting = 0;
1714
}
1715
}
1716
else if (n->eof)
1717
{
1718
u_32int_t *buf;
1719
n->readwaiting = 1;
1720
if ((ioctl(snum, FIONREAD, &numbytes) == -1))
1721
{
1722
close_dcc_file(snum);
1723
return;
1724
}
1725
buf = alloca(numbytes+1);
1726
numbytes = read(snum, buf, numbytes);
1727
switch(numbytes)
1728
{
1729
case -1:
1730
erase_dcc_info(snum, 1, convert_output_format("$G %RDCC%n Remote $0 closed dcc send", "%s", s->server));
1731
close_socketread(snum);
1732
break;
1733
case 0:
1734
close_dcc_file(snum);
1735
break;
1736
}
1737
return;
1738
}
1739
}
1740
1741
if ((bytesread = read(n->file, buffer, n->blocksize)) > 0)
1742
{
1743
int num;
1744
my_encrypt(buffer, bytesread, n->encrypt);
1745
num = send(snum, buffer, bytesread, 0);
1746
if (num != bytesread)
1747
{
1748
if (num == -1)
1749
{
1750
if (errno == EWOULDBLOCK || errno == ENOBUFS)
1751
lseek(n->file, -bytesread, SEEK_CUR);
1752
else
1753
{
1754
erase_dcc_info(snum, 1, convert_output_format("$G %RDCC%n Remote $0 closed dcc send", "%s", s->server));
1755
close_socketread(snum);
1756
return;
1757
}
1758
}
1759
else
1760
{
1761
lseek(n->file, -(bytesread - num), SEEK_CUR);
1762
n->bytes_sent += num;
1763
}
1764
n->readwaiting = 1;
1765
return;
1766
}
1767
n->bytes_sent += bytesread;
1768
n->packets = n->bytes_sent / n->blocksize;
1769
n->readwaiting = 1;
1770
get_time(&n->lasttime);
1771
if (!(n->packets % 10))
1772
{
1773
update_transfer();
1774
if (!(n->packets % 20))
1775
update_all_status(current_window, NULL, 0);
1776
}
1777
}
1778
else if (!n->eof)
1779
{
1780
n->eof = 1;
1781
n->readwaiting = 1;
1782
}
1783
else if (!n->dcc_fast)
1784
close_dcc_file(snum);
1785
else
1786
n->readwaiting = 1;
1787
}
1788
1789
void start_dcc_send(int s)
1790
{
1791
struct sockaddr_in remaddr;
1792
int sra;
1793
int type;
1794
int new_s = -1;
1795
int tdcc = 0;
1796
char *nick = NULL;
1797
unsigned long flags;
1798
DCC_int *n = NULL;
1799
struct transfer_struct received = {0};
1800
char local_type[30];
1801
1802
if (!(flags = get_socketflags(s)))
1803
return; /* wrong place damn it */
1804
nick = get_socketserver(s);
1805
sra = sizeof(struct sockaddr_in);
1806
new_s = my_accept(s, (struct sockaddr *) &remaddr, &sra);
1807
type = flags & DCC_TYPES;
1808
n = get_socketinfo(s);
1809
1810
set_display_target(NULL, LOG_DCC);
1811
if ((add_socketread(new_s, ntohs(remaddr.sin_port), flags, nick, process_dcc_send1, NULL)) < 0)
1812
{
1813
erase_dcc_info(s, 1, "%s", convert_output_format("$G %RDCC error: accept() failed. punt!!", NULL, NULL));
1814
close_socketread(s);
1815
return;
1816
}
1817
flags &= ~DCC_WAIT;
1818
flags |= DCC_ACTIVE;
1819
set_socketflags(new_s, flags);
1820
set_socketinfo(new_s, n);
1821
if ((n->file = open(n->filename, O_RDONLY | O_BINARY)) == -1)
1822
{
1823
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"));
1824
close_socketread(new_s);
1825
close_socketread(s);
1826
return;
1827
}
1828
if (type == DCC_REFILEOFFER)
1829
{
1830
alarm(1);
1831
recv(new_s, (char *)&received, sizeof(struct transfer_struct), 0);
1832
alarm(0);
1833
if (byte_order_test() != received.byteorder)
1834
{
1835
/* the packet sender orders bytes differently than us,
1836
* reverse what they sent to get the right value
1837
*/
1838
n->transfer_orders.packet_id =
1839
((received.packet_id & 0x00ff) << 8) |
1840
((received.packet_id & 0xff00) >> 8);
1841
1842
n->transfer_orders.byteoffset =
1843
((received.byteoffset & 0xff000000) >> 24) |
1844
((received.byteoffset & 0x00ff0000) >> 8) |
1845
((received.byteoffset & 0x0000ff00) << 8) |
1846
((received.byteoffset & 0x000000ff) << 24);
1847
}
1848
else
1849
memcpy(&n->transfer_orders,&received,sizeof(struct transfer_struct));
1850
if (n->transfer_orders.packet_id != DCC_PACKETID)
1851
{
1852
put_it("%s", convert_output_format("$G %RDCC%n reget packet is invalid!!", NULL, NULL));
1853
memset(&n->transfer_orders, 0, sizeof(struct transfer_struct));
1854
}
1855
else
1856
put_it("%s", convert_output_format("$G %RDCC%n reget starting at $0", "%s", ulongcomma(n->transfer_orders.byteoffset)));
1857
}
1858
if (get_int_var(DCC_FAST_VAR) && !(flags & DCC_TDCC))
1859
{
1860
set_non_blocking(new_s);
1861
n->dcc_fast = 1;
1862
}
1863
lseek(n->file, n->transfer_orders.byteoffset, SEEK_SET);
1864
errno = 0;
1865
*local_type = 0;
1866
if (tdcc)
1867
strcpy(local_type, "T");
1868
strcat(local_type, dcc_types[type]->name);
1869
if (do_hook(DCC_CONNECT_LIST, "%s %s %s %d %ld %s", nick, local_type,
1870
inet_ntoa(remaddr.sin_addr), ntohs(remaddr.sin_port), (unsigned long)n->filesize, n->filename) && !dcc_quiet)
1871
put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_CONNECT_FSET),
1872
"%s %s %s %s %s %d %d", update_clock(GET_TIME),
1873
local_type, nick, n->userhost?n->userhost:"u@h",
1874
inet_ntoa(remaddr.sin_addr),ntohs(remaddr.sin_port),n->transfer_orders.byteoffset ));
1875
get_time(&n->starttime);
1876
get_time(&n->lasttime);
1877
close_socketread(s);
1878
process_dcc_send1(new_s);
1879
reset_display_target();
1880
}
1881
1882
void real_file_send(char *nick, char *filename, char *passwd, char *port, int tdcc, unsigned long type, int blocksize)
1883
{
1884
DCC_int *new = NULL;
1885
SocketList *s = NULL;
1886
unsigned long filesize = 0;
1887
char FileBuf[BIG_BUFFER_SIZE+1];
1888
struct stat st;
1889
1890
#if defined(__EMX__) || defined(WINNT)
1891
if (*filename == '/' || *filename == '\\')
1892
#else
1893
if (*filename == '/')
1894
#endif
1895
strncpy(FileBuf, filename, BIG_BUFFER_SIZE);
1896
else if (*filename == '~')
1897
{
1898
char *fullname;
1899
if (!(fullname = expand_twiddle(filename)))
1900
{
1901
put_it("%s", convert_output_format("$G %RDCC%n Unable to access $0", "%s", filename));
1902
return;
1903
}
1904
strncpy(FileBuf, fullname, BIG_BUFFER_SIZE);
1905
new_free(&fullname);
1906
}
1907
#if defined(__EMX__) || defined(WINNT)
1908
else if (strlen(filename) > 3 && ( (*(filename+1) == ':') && (*(filename+2) == '/' || *(filename+2) == '\\')) )
1909
strlcpy(FileBuf, filename, BIG_BUFFER_SIZE);
1910
#endif
1911
else
1912
{
1913
getcwd(FileBuf, BIG_BUFFER_SIZE);
1914
strlcat(FileBuf, "/", BIG_BUFFER_SIZE);
1915
strlcat(FileBuf, filename, BIG_BUFFER_SIZE);
1916
}
1917
#if defined(__EMX__) || defined(WINNT)
1918
convert_unix(FileBuf);
1919
#endif
1920
1921
if (strchr(FileBuf , '*'))
1922
{
1923
char *path, *c, *filebuf = NULL;
1924
DIR *dp;
1925
struct dirent *dir;
1926
int count = 0;
1927
1928
path = LOCAL_COPY(FileBuf);
1929
1930
if ((c = strrchr(path, '/')))
1931
*c++ = 0;
1932
1933
if (!(dp = opendir(path)))
1934
return;
1935
while ((dir = readdir(dp)))
1936
{
1937
if (!dir->d_ino)
1938
continue;
1939
if (!wild_match(c, dir->d_name))
1940
continue;
1941
malloc_sprintf(&filebuf, "%s/%s", path, dir->d_name);
1942
stat(filebuf, &st);
1943
if (S_ISDIR(st.st_mode))
1944
{
1945
new_free(&filebuf);
1946
continue;
1947
}
1948
/* finally. do a send */
1949
if ((s = find_dcc(nick, filebuf, NULL, type, 1, -1, -1)))
1950
{
1951
if ((s->flags & DCC_ACTIVE) || (s->flags & DCC_WAIT))
1952
put_it("%s", convert_output_format("$G %RDCC%n A previous DCC send to $0 exists", "%s", nick));
1953
new = (DCC_int *)s->info;
1954
if (s->flags & DCC_WAIT)
1955
{
1956
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);
1957
add_sockettimeout(s->is_read, 120, NULL);
1958
}
1959
continue;
1960
}
1961
if ((new = dcc_create(nick, filebuf, passwd, st.st_size, port? atol(port) : filesize, type, (tdcc? DCC_TDCC: 0) |DCC_TWOCLIENTS, start_dcc_send)))
1962
new->blocksize = blocksize;
1963
1964
count++;
1965
new_free(&filebuf);
1966
}
1967
closedir(dp);
1968
if (!dcc_quiet)
1969
{
1970
char buff[30];
1971
strcpy(buff, "file");
1972
if (count > 1)
1973
strcat(buff, "s");
1974
if (count)
1975
put_it("%s", convert_output_format("$G %RDCC%n Sent DCC SEND request to $0 for $1 $2-", "%s %s %s", nick, buff, filename));
1976
else
1977
put_it("%s", convert_output_format("$G %RDCC%n No Files found matching $*", "%s", filename));
1978
}
1979
return;
1980
}
1981
if (access(FileBuf, R_OK))
1982
{
1983
put_it("%s", convert_output_format("$G %RDCC%n No such file $0 exists", "%s", FileBuf));
1984
return;
1985
}
1986
stat(FileBuf, &st);
1987
if (S_ISDIR(st.st_mode))
1988
{
1989
put_it("%s", convert_output_format("$G %RDCC%n $0 is a directory", "%s", FileBuf));
1990
return;
1991
}
1992
if ((s = find_dcc(nick, FileBuf, NULL, type, 1, -1, -1)))
1993
{
1994
if ((s->flags & DCC_ACTIVE) || (s->flags & DCC_WAIT))
1995
put_it("%s", convert_output_format("$G %RDCC%n A previous DCC send to $0 exists", "%s", nick));
1996
new = (DCC_int *)s->info;
1997
if (s->flags & DCC_WAIT)
1998
{
1999
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);
2000
add_sockettimeout(s->is_read, 120, NULL);
2001
}
2002
return;
2003
}
2004
if ((new = dcc_create(nick, FileBuf, passwd, st.st_size, port? atol(port) : filesize, type, (tdcc? DCC_TDCC: 0) |DCC_TWOCLIENTS, start_dcc_send)))
2005
new->blocksize = blocksize;
2006
}
2007
2008
void BX_dcc_filesend(char *command, char *args)
2009
{
2010
char *user;
2011
char *nick;
2012
2013
char *passwd = NULL;
2014
char *filename = NULL;
2015
char *port = NULL;
2016
int tdcc = 0;
2017
int blocksize = get_int_var(DCC_BLOCK_SIZE_VAR);
2018
2019
user = get_dcc_args(&args, &passwd, &port, &blocksize);
2020
if (!user)
2021
{
2022
put_it("%s", convert_output_format("$G %RDCC%n You must supply a nickname for DCC send", NULL, NULL));
2023
return;
2024
}
2025
if (!blocksize || blocksize > MAX_DCC_BLOCK_SIZE)
2026
blocksize = get_int_var(DCC_BLOCK_SIZE_VAR);
2027
2028
if (command && *command == 'T')
2029
tdcc = DCC_TDCC;
2030
while ((nick = next_in_comma_list(user, &user)))
2031
{
2032
char *new_args;
2033
if (!nick || !*nick)
2034
break;
2035
new_args = LOCAL_COPY(args);
2036
while ((filename = new_next_arg(new_args, &new_args)))
2037
{
2038
if (!filename || !*filename)
2039
break;
2040
real_file_send(nick, filename, passwd, port, tdcc, DCC_FILEOFFER, blocksize);
2041
}
2042
doing_multi++;
2043
}
2044
doing_multi = 0;
2045
}
2046
2047
void BX_dcc_resend(char *command, char *args)
2048
{
2049
char *user;
2050
char *nick;
2051
2052
char *passwd = NULL;
2053
char *filename = NULL;
2054
char *port = NULL;
2055
int tdcc = 0;
2056
int blocksize = get_int_var(DCC_BLOCK_SIZE_VAR);
2057
2058
user = get_dcc_args(&args, &passwd, &port, &blocksize);
2059
if (!user)
2060
{
2061
put_it("%s", convert_output_format("$G %RDCC%n You must supply a nickname for DCC resend", NULL, NULL));
2062
return;
2063
}
2064
if (!blocksize || blocksize > MAX_DCC_BLOCK_SIZE)
2065
blocksize = get_int_var(DCC_BLOCK_SIZE_VAR);
2066
2067
if (command && *command == 'T')
2068
tdcc = DCC_TDCC;
2069
while ((nick = next_in_comma_list(user, &user)))
2070
{
2071
char *new_args;
2072
if (!nick || !*nick)
2073
break;
2074
new_args = LOCAL_COPY(args);
2075
while ((filename = new_next_arg(new_args, &new_args)))
2076
{
2077
if (!filename || !*filename)
2078
break;
2079
real_file_send(nick, filename, passwd, port, tdcc, DCC_REFILEOFFER, blocksize);
2080
}
2081
doing_multi++;
2082
}
2083
doing_multi = 0;
2084
}
2085
2086
2087
2088
void start_dcc_get(int snum)
2089
{
2090
DCC_int *n;
2091
SocketList *s;
2092
int bytes_read;
2093
unsigned long type;
2094
int tdcc = 0;
2095
char buffer[MAX_DCC_BLOCK_SIZE+1];
2096
int err;
2097
s = get_socket(snum);
2098
n = (DCC_int *)s->info;
2099
type = s->flags & DCC_TYPES;
2100
tdcc = s->flags & DCC_TDCC;
2101
2102
2103
2104
set_display_target(NULL, LOG_DCC);
2105
bytes_read = read(snum, buffer, MAX_DCC_BLOCK_SIZE);
2106
switch(bytes_read)
2107
{
2108
case -1:
2109
erase_dcc_info(snum, 1, "%s", convert_output_format("$G %RDCC get to $0 lost: Remote peer closed connection", "%s", s->server));
2110
close_socketread(snum);
2111
return;
2112
case 0:
2113
close_dcc_file(snum);
2114
return;
2115
}
2116
my_decrypt(buffer, bytes_read, n->encrypt);
2117
err = write(n->file, buffer, bytes_read);
2118
if (err == -1)
2119
{
2120
erase_dcc_info(snum, 1, "write to local file failed");
2121
reset_display_target();
2122
close_socketread(snum);
2123
return;
2124
}
2125
n->bytes_read += bytes_read;
2126
n->packets = n->bytes_read / n->blocksize;
2127
{
2128
u_32int_t bytes;
2129
bytes = htonl(n->bytes_read);
2130
send(snum, (char *)&bytes, sizeof(u_32int_t), 0);
2131
}
2132
if (n->filesize)
2133
{
2134
if (n->bytes_read + n->transfer_orders.byteoffset > n->filesize)
2135
{
2136
put_it("%s", convert_output_format("$G %RDCC%n Warning: incoming file is larger than the handshake said", NULL, NULL));
2137
put_it("%s", convert_output_format("$G %RDCC%n Warning: GET: closing connection", NULL, NULL));
2138
erase_dcc_info(snum, 1, NULL);
2139
close_socketread(snum);
2140
}
2141
else if ((n->bytes_read + n->transfer_orders.byteoffset) == n->filesize)
2142
{
2143
close_dcc_file(snum);
2144
reset_display_target();
2145
return;
2146
}
2147
if (!(n->packets % 10))
2148
{
2149
update_transfer();
2150
if (!(n->packets % 20))
2151
update_all_status(current_window, NULL, 0);
2152
}
2153
}
2154
reset_display_target();
2155
}
2156
2157
void real_get_file(char *user, char *filename, char *port, char *passwd, int tdcc, int blocksize)
2158
{
2159
DCC_int *new = NULL;
2160
SocketList *s = NULL;
2161
DCC_List *s1 = NULL;
2162
char *nick;
2163
2164
while ((nick = next_in_comma_list(user, &user)))
2165
{
2166
if (!nick || !*nick)
2167
break;
2168
2169
if ((s1 = find_dcc_pending(nick, filename, NULL, DCC_FILEREAD, 0, -1)))
2170
{
2171
new = (DCC_int *)s1->sock.info;
2172
if ((s = find_dcc(nick, new->filename, NULL, DCC_FILEREAD, 1, -1, -1)))
2173
{
2174
put_it("%s", convert_output_format("$G %RDCC%n A previous DCC GET from $0 exists", "%s", nick));
2175
continue;
2176
}
2177
}
2178
else
2179
continue;
2180
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)))
2181
{
2182
char *tmp = NULL;
2183
char *fullname = NULL;
2184
new->blocksize = blocksize;
2185
if (get_string_var(DCC_DLDIR_VAR))
2186
malloc_sprintf(&tmp, "%s/%s", get_string_var(DCC_DLDIR_VAR), new->filename);
2187
else
2188
tmp = m_strdup(new->filename);
2189
if (!(fullname = expand_twiddle(tmp)))
2190
malloc_strcpy(&fullname, tmp);
2191
#if defined(WINNT) || defined(__EMX__)
2192
convert_unix(fullname);
2193
#endif
2194
s = find_dcc(nick, filename, NULL, DCC_FILEREAD, 1, -1, -1);
2195
if ((new->file = open(fullname, O_WRONLY | O_TRUNC | O_CREAT | O_BINARY, 0644)) == -1)
2196
{
2197
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"));
2198
close_socketread(s->is_read);
2199
}
2200
new_free(&fullname);
2201
new_free(&tmp);
2202
2203
}
2204
doing_multi++;
2205
}
2206
}
2207
2208
void dcc_getfile(char *command, char *args)
2209
{
2210
char *user;
2211
2212
char *passwd = NULL;
2213
char *filename = NULL;
2214
char *port = NULL;
2215
int tdcc = 0;
2216
int blocksize = get_int_var(DCC_BLOCK_SIZE_VAR);
2217
2218
user = get_dcc_args(&args, &passwd, &port, &blocksize);
2219
if (!user)
2220
{
2221
put_it("%s", convert_output_format("$G %RDCC%n You must supply a nickname for DCC get", NULL, NULL));
2222
return;
2223
}
2224
if (!blocksize || blocksize > MAX_DCC_BLOCK_SIZE)
2225
blocksize = get_int_var(DCC_BLOCK_SIZE_VAR);
2226
if (command && *command == 'T')
2227
tdcc = 1;
2228
2229
if (!args || !*args)
2230
real_get_file(user, NULL, port, passwd, tdcc, blocksize);
2231
else
2232
{
2233
char *u = alloca(strlen(user)+1);
2234
while ((filename = next_in_comma_list(args, &args)))
2235
{
2236
if (!filename || !*filename)
2237
break;
2238
strcpy(u, user);
2239
real_get_file(u, filename, port, passwd, tdcc, blocksize);
2240
}
2241
}
2242
doing_multi = 0;
2243
}
2244
2245
void real_reget_file(char *user, char *filename, char *port, char *passwd, int tdcc, int blocksize)
2246
{
2247
DCC_int *new = NULL;
2248
SocketList *s = NULL;
2249
char *nick;
2250
2251
while ((nick = next_in_comma_list(user, &user)))
2252
{
2253
char *tmp = NULL;
2254
char *fullname = NULL;
2255
DCC_List *s1 = NULL;
2256
if (!nick || !*nick)
2257
break;
2258
2259
if ((s1 = find_dcc_pending(nick, filename, NULL, DCC_REFILEREAD, 0, -1)))
2260
{
2261
new = (DCC_int *)s1->sock.info;
2262
if ((s = find_dcc(nick, new->filename, NULL, DCC_REFILEREAD, 1, -1, -1)))
2263
{
2264
put_it("%s", convert_output_format("$G %RDCC%n A previous DCC REGET from $0 exists", "%s", nick));
2265
continue;
2266
}
2267
}
2268
else
2269
continue;
2270
if (get_string_var(DCC_DLDIR_VAR))
2271
malloc_sprintf(&tmp, "%s/%s", get_string_var(DCC_DLDIR_VAR), new->filename);
2272
else
2273
tmp = m_strdup(new->filename);
2274
if (!(fullname = expand_twiddle(tmp)))
2275
malloc_strcpy(&fullname, tmp);
2276
if ((new->file = open(fullname, O_WRONLY | O_CREAT | O_BINARY, 0644)) != -1)
2277
{
2278
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)))
2279
new->blocksize = blocksize;
2280
}
2281
new_free(&fullname);
2282
new_free(&tmp);
2283
doing_multi++;
2284
}
2285
}
2286
2287
void dcc_regetfile(char *command, char *args)
2288
{
2289
char *user;
2290
char *passwd = NULL;
2291
char *filename = NULL;
2292
char *port = NULL;
2293
int tdcc = 0;
2294
int blocksize = get_int_var(DCC_BLOCK_SIZE_VAR);
2295
2296
user = get_dcc_args(&args, &passwd, &port, &blocksize);
2297
if (!user)
2298
{
2299
put_it("%s", convert_output_format("$G %RDCC%n You must supply a nickname for DCC reget", NULL, NULL));
2300
return;
2301
}
2302
if (!blocksize || blocksize > MAX_DCC_BLOCK_SIZE)
2303
blocksize = get_int_var(DCC_BLOCK_SIZE_VAR);
2304
if (command && *command == 'T')
2305
tdcc = 1;
2306
if (!args || !*args)
2307
real_reget_file(user, NULL, port, passwd, tdcc, blocksize);
2308
else
2309
{
2310
char *u = alloca(strlen(user)+1);
2311
while ((filename = next_in_comma_list(args, &args)))
2312
{
2313
if (!filename || !*filename)
2314
break;
2315
strcpy(u, user);
2316
real_reget_file(u, filename, port, passwd, tdcc, blocksize);
2317
}
2318
}
2319
doing_multi = 0;
2320
}
2321
2322
static char *get_bar_percent(int percent)
2323
{
2324
#ifdef ONLY_STD_CHARS
2325
static char *_dcc_offer[12] = {"%K-.........%n", /* 0 */
2326
"%K-.........%n", /* 10 */
2327
"%K-=........%n", /* 20 */
2328
"%K-=*.......%n", /* 30 */
2329
"%K-=*%1%K=%0%K......%n", /* 40 */
2330
"%K-=*%1%K=-%0%K.....%n", /* 50 */
2331
"%K-=*%1%K=-.%0%K....%n", /* 60 */
2332
"%K-=*%1%K=-. %0%K...%n", /* 70 */
2333
"%K-=*%1%K=-. %R.%0%K..%n", /* 80 */
2334
"%K-=*%1%K=-. %R.-%0%K.%n", /* 90 */
2335
"%K-=*%1%K=-. %R.-=%n", /* 100 */
2336
empty_string};
2337
#else
2338
static char *_dcc_offer[12] = {"%K����������%n", /* 0 */
2339
"%K����������%n", /* 10 */
2340
"%K����������%n", /* 20 */
2341
"%K��۰������%n", /* 30 */
2342
"%K���%1%K�%0%K������%n", /* 40 */
2343
"%K���%1%K��%0%K�����%n", /* 50 */
2344
"%K���%1%K���%0%K����%n", /* 60 */
2345
"%K���%1%K����%0%K���%n", /* 70 */
2346
"%K���%1%K����%R�%0%K��%n", /* 80 */
2347
"%K���%1%K����%R��%0%K�%n", /* 90 */
2348
"%K���%1%K����%R���%n", /* 100 */
2349
empty_string};
2350
#endif
2351
if (percent <= 100)
2352
return _dcc_offer[percent];
2353
return empty_string;
2354
}
2355
2356
2357
void dcc_glist(char *command, char *args)
2358
{
2359
char *dformat =
2360
"#$[3]0 $[6]1%Y$2%n $[11]3 $[25]4 $[7]5 $6-";
2361
char *d1format =
2362
"#$[3]0 $[6]1%Y$2%n $[11]3 $4 $[7]5 $[11]6 $[7]7 $8-";
2363
char *c1format =
2364
"#$[3]0 $[6]1%Y$2%n $[11]3 $4 $[-4]5 $[-4]6 $[-3]7 $[-3]8 $[7]9 $10";
2365
2366
int i;
2367
DCC_int *n = NULL;
2368
SocketList *s;
2369
int type;
2370
int tdcc = 0;
2371
char *status;
2372
int count = 0;
2373
DCC_List *c;
2374
char stats[80];
2375
char kilobytes[20];
2376
int barlen = BAR_LENGTH;
2377
double barsize = 0.0;
2378
char spec[BIG_BUFFER_SIZE];
2379
char *filename, *p;
2380
2381
reset_display_target();
2382
#if !defined(WINNT) && !defined(__EMX__)
2383
charset_ibmpc();
2384
#endif
2385
if (do_hook(DCC_HEADER_LIST, "%s %s %s %s %s %s %s", "Dnum","Type","Nick", "Status", "K/s", "File","Encrypt"))
2386
{
2387
#ifdef ONLY_STD_CHARS
2388
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));
2389
put_it("%s", convert_output_format("%W------------------------------------------------------------------------------", NULL, NULL));
2390
#else
2391
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));
2392
put_it("%s", convert_output_format("%K��%n�%W�%n�%K�����%n�%W�%n�%K���������%n�%W�%n�%K���������������%n�%W�%n�%K�����%n�%W�%n�%K�����%n�%W�%n�%K�������������������", NULL, NULL));
2393
#endif
2394
}
2395
for (c = pending_dcc; c; c = c->next, count++)
2396
{
2397
char local_type[30];
2398
char *filename, *p;
2399
s = &c->sock;
2400
type = c->sock.flags & DCC_TYPES;
2401
tdcc = c->sock.flags & DCC_TDCC;
2402
n = (DCC_int *)c->sock.info;
2403
*local_type = 0;
2404
if (tdcc)
2405
strcpy(local_type, "T");
2406
strcat(local_type, dcc_types[type]->name);
2407
filename = LOCAL_COPY(n->filename);
2408
2409
p = filename;
2410
while ((p = strchr(p, ' ')))
2411
*p = '_';
2412
2413
if (do_hook(DCC_STAT_LIST, "%d %s %s %s %s %s %s",
2414
n->dccnum, local_type,
2415
c->sock.server,
2416
s->flags & DCC_OFFER ? "Offer" :
2417
s->flags & DCC_WAIT ? "Wait" :
2418
s->flags & DCC_ACTIVE ? "Active" :
2419
"Unknown",
2420
"N/A", strip_path(filename), n->encrypt?"E":empty_string))
2421
{
2422
put_it("%s", convert_output_format(dformat, "%d %s %s %s %s %s %s",
2423
n->dccnum,
2424
local_type,
2425
n->encrypt ? "E" : "�",
2426
c->sock.server,
2427
2428
s->flags & DCC_OFFER ? "Offer " :
2429
s->flags & DCC_WAIT ? "Wait " :
2430
s->flags & DCC_ACTIVE ? "Active" :
2431
"Unknown",
2432
"N/A",
2433
strip_path(filename)));
2434
}
2435
count++;
2436
}
2437
for (i = 0; i < get_max_fd() + 1; i++, count++)
2438
{
2439
double perc = 0.0;
2440
double bytes = 0.0;
2441
char local_type[30];
2442
time_t xtime;
2443
int seconds = 0, minutes = 0;
2444
int iperc = 0;
2445
int size = 0;
2446
if (!check_dcc_socket(i))
2447
continue;
2448
s = get_socket(i);
2449
n = (DCC_int *)s->info;
2450
type = s->flags & DCC_TYPES;
2451
tdcc = s->flags & DCC_TDCC;
2452
xtime = now - n->starttime.tv_sec;
2453
2454
if (xtime <= 0)
2455
xtime = 1;
2456
*local_type = 0;
2457
if (tdcc)
2458
strcpy(local_type, "T");
2459
strcat(local_type, dcc_types[type]->name);
2460
2461
filename = LOCAL_COPY(n->filename);
2462
p = filename;
2463
while ((p = strchr(p, ' ')))
2464
*p = '_';
2465
2466
if (((type == DCC_CHAT) || (type == DCC_RAW) || (type == DCC_BOTMODE) || (type == DCC_FTPOPEN)))
2467
{
2468
if (!(s->flags & DCC_ACTIVE))
2469
xtime = now - s->time;
2470
if (do_hook(DCC_STAT_LIST, "%d %s %s %s %s %s %s",
2471
n->dccnum, local_type, s->server,
2472
s->flags & DCC_OFFER ? "Offer " :
2473
s->flags & DCC_WAIT ? "Wait " :
2474
s->flags & DCC_ACTIVE ?"Active" :
2475
"Unknown",
2476
"N/A", strip_path(filename), n->encrypt?"E":empty_string))
2477
put_it("%s", convert_output_format(c1format, "%d %s %s %s %s %s %s %s",
2478
n->dccnum,
2479
local_type,
2480
n->encrypt ? "E" : "�",
2481
s->server,
2482
s->flags & DCC_OFFER ? "Offer" :
2483
s->flags & DCC_WAIT ? "Wait" :
2484
s->flags & DCC_ACTIVE ? "Active" :
2485
"Unknown",
2486
convert_time(xtime),
2487
"N/A",
2488
strip_path(filename)));
2489
}
2490
else
2491
{
2492
if (!(s->flags & DCC_ACTIVE))
2493
{
2494
if (do_hook(DCC_STAT_LIST, "%d %s %s %s %s %s %s",
2495
n->dccnum, local_type, s->server,
2496
s->flags & DCC_OFFER ? "Offer " :
2497
s->flags & DCC_WAIT ? "Wait " :
2498
s->flags & DCC_ACTIVE ?"Active" :
2499
"Unknown",
2500
"N/A", strip_path(filename), n->encrypt?"E":empty_string))
2501
put_it("%s", convert_output_format(dformat, "%d %s %s %s %s %s %s",
2502
n->dccnum,
2503
local_type,
2504
n->encrypt ? "E" : "�",
2505
s->server,
2506
s->flags & DCC_OFFER ? "Offer" :
2507
s->flags & DCC_WAIT ? "Wait" :
2508
s->flags & DCC_ACTIVE ? "Active" :
2509
"Unknown",
2510
"N/A",
2511
strip_path(filename)));
2512
continue;
2513
}
2514
2515
2516
bytes = n->bytes_read + n->bytes_sent;
2517
2518
sprintf(kilobytes, "%2.4g", bytes / 1024.0 / xtime);
2519
2520
type = s->flags & DCC_TYPES;
2521
tdcc = s->flags & DCC_TDCC;
2522
status = s->flags & DCC_OFFER ? "Offer":s->flags & DCC_ACTIVE ? "Active": s->flags&DCC_WAIT?"Wait":"Unknown";
2523
if ((bytes >= 0) && (s->flags & DCC_ACTIVE))
2524
{
2525
if (bytes && (n->filesize - n->transfer_orders.byteoffset) >= bytes)
2526
{
2527
perc = (100.0 * ((double)bytes + n->transfer_orders.byteoffset) / (double)(n->filesize));
2528
if ( perc > 100.0) perc = 100.0;
2529
else if (perc < 0.0) perc = 0.0;
2530
seconds = (int) (( (n->filesize - n->transfer_orders.byteoffset - bytes) / (bytes / xtime)) + 0.5);
2531
minutes = seconds / 60;
2532
seconds = seconds - (minutes * 60);
2533
if (minutes > 999) {
2534
minutes = 999;
2535
seconds = 59;
2536
}
2537
if (seconds < 0) seconds = 0;
2538
} else
2539
seconds = minutes = perc = 0;
2540
2541
iperc = ((int)perc) / 10;
2542
barsize = ((double) (n->filesize)) / (double) barlen;
2543
2544
size = (int) ((double) bytes / (double)barsize);
2545
2546
if (n->filesize == 0)
2547
size = barlen;
2548
sprintf(stats, "%4.1f", perc);
2549
if (!get_int_var(DCC_BAR_TYPE_VAR))
2550
sprintf(spec, "%s %s%s %02d:%02d", get_bar_percent(iperc), stats, "%%", minutes, seconds);
2551
else
2552
sprintf(spec, "%s%s %02d:%02d", stats, "%%", minutes, seconds);
2553
2554
strcpy(spec, convert_output_format(spec, NULL, NULL));
2555
}
2556
if (do_hook(DCC_STATF_LIST, "%d %s %s %s %s %s %s",
2557
n->dccnum, local_type, s->server, status,
2558
kilobytes, strip_path(filename),
2559
n->encrypt?"E":empty_string))
2560
{
2561
char *s1;
2562
if (!get_int_var(DCC_BAR_TYPE_VAR))
2563
s1 = d1format;
2564
else
2565
s1 = dformat;
2566
2567
put_it("%s", convert_output_format(s1, "%d %s %s %s %s %s %s",
2568
n->dccnum, local_type, n->encrypt ? "E":"�",
2569
s->server, spec, kilobytes,
2570
strip_path(filename)));
2571
}
2572
2573
if (do_hook(DCC_STATF1_LIST, "%s %lu %lu %d %d", stats, (unsigned long)bytes, (unsigned long)n->filesize, minutes, seconds))
2574
{
2575
char *bar_end, *c;
2576
if (!get_int_var(DCC_BAR_TYPE_VAR))
2577
continue;
2578
memset(spec, 0, 500);
2579
sprintf(stats, "%4.1f%% (%lu of %lu bytes)", perc, (unsigned long)bytes, (unsigned long)n->filesize);
2580
strcpy( spec, "\002[\026");
2581
sprintf(spec+3, "%*s", size+1, space);
2582
bar_end = spec + strlen(spec);
2583
sprintf(bar_end, "%*s", barlen-size+1, space);
2584
if (size <= barlen)
2585
{
2586
memmove(bar_end+1, bar_end, strlen(bar_end));
2587
*bar_end = '\026';
2588
}
2589
strcat(spec, "]\002 ETA \002%02d:%02d\002");
2590
bar_end = (spec+(((BAR_LENGTH+2) / 2) - (strlen(stats) / 2)));
2591
for (c = stats;*c; bar_end++)
2592
{
2593
if (*bar_end == '\026' || *bar_end == '\002')
2594
continue;
2595
*bar_end = *c++;
2596
}
2597
put_it(spec, minutes, seconds);
2598
}
2599
}
2600
}
2601
#if !defined(WINNT) && !defined(__EMX__)
2602
#if defined(LATIN1)
2603
charset_lat1();
2604
#elif defined(CHARSET_CUSTOM)
2605
charset_cst();
2606
#endif
2607
#endif
2608
if (!count)
2609
bitchsay("No active/pending dcc's");
2610
else if (do_hook(DCC_POST_LIST, "%s %s %s %s %s %s %s", "DCCnum","Type","Nick", "Status", "K/s", "File","Encrypt"))
2611
;
2612
}
2613
2614
unsigned char byte_order_test(void)
2615
{
2616
unsigned short test = DCC_PACKETID;
2617
2618
if (*((unsigned char *)&test) == ((DCC_PACKETID & 0xff00) >> 8))
2619
return 0;
2620
2621
if (*((unsigned char *)&test) == (DCC_PACKETID & 0x00ff))
2622
return 1;
2623
return 0;
2624
}
2625
2626
int BX_get_active_count(void)
2627
{
2628
int active = 0;
2629
register int i;
2630
register SocketList *s;
2631
register int type;
2632
for (i = 0; i < get_max_fd() + 1; i++)
2633
{
2634
if (check_dcc_socket(i))
2635
{
2636
s = get_socket(i);
2637
type = s->flags & DCC_TYPES;
2638
if (type == DCC_REFILEREAD || type == DCC_FTPGET ||
2639
type == DCC_FILEREAD || type == DCC_FILEOFFER ||
2640
type == DCC_REFILEOFFER)
2641
active++;
2642
}
2643
}
2644
return active;
2645
}
2646
2647
#if 0
2648
void dcc_renumber_active(void)
2649
{
2650
register int i;
2651
SocketList *s;
2652
DCC_int *n;
2653
int j = 1;
2654
2655
for (i = 0; i < get_max_fd() + 1; i++)
2656
{
2657
if (check_dcc_socket(i))
2658
{
2659
s = get_socket(i);
2660
n = (DCC_int *)s->info;
2661
n->dccnum = j++;
2662
}
2663
}
2664
dcc_count = j;
2665
}
2666
#endif
2667
2668
int check_dcc_list (char *name)
2669
{
2670
int do_it = 0;
2671
register int i = 0;
2672
for (i = 0; i < get_max_fd() + 1; i++)
2673
{
2674
if (check_dcc_socket(i))
2675
{
2676
SocketList *s;
2677
s = get_socket(i);
2678
if (s->server && !my_stricmp(name, s->server) && !(s->flags & DCC_ACTIVE))
2679
{
2680
switch (s->flags & DCC_TYPES)
2681
{
2682
case DCC_FILEOFFER:
2683
case DCC_FILEREAD:
2684
case DCC_REFILEOFFER:
2685
case DCC_REFILEREAD:
2686
do_it++;
2687
erase_dcc_info(i, 0, NULL);
2688
close_socketread(i);
2689
default:
2690
break;
2691
}
2692
}
2693
}
2694
}
2695
return do_it;
2696
}
2697
2698
2699
void update_transfer(void)
2700
{
2701
register unsigned count= 0;
2702
double perc = 0.0;
2703
register int i = 0;
2704
/* char temp_str[60];*/
2705
double bytes;
2706
SocketList *s;
2707
DCC_int *n;
2708
unsigned long flags;
2709
char transfer_buffer[BIG_BUFFER_SIZE];
2710
char *c;
2711
2712
*transfer_buffer = 0;
2713
for (i = 0; i < get_max_fd() + 1 ; i++)
2714
{
2715
if (!check_dcc_socket(i))
2716
continue;
2717
s = get_socket(i);
2718
flags = s->flags & DCC_TYPES;
2719
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))
2720
continue;
2721
n = (DCC_int *)s->info;
2722
bytes = n->bytes_read + n->bytes_sent + n->transfer_orders.byteoffset;
2723
if (bytes >= 0)
2724
{
2725
if (n->filesize >= bytes && (n->filesize > 0))
2726
{
2727
perc = (100.0 * ((double)bytes) / (double)(n->filesize));
2728
if ( perc > 100.0) perc = 100.0;
2729
else if (perc < 0.0) perc = 0.0;
2730
2731
}
2732
strmopencat(transfer_buffer, BIG_BUFFER_SIZE, ltoa((int)perc), "% ", NULL);
2733
#if 0
2734
sprintf(temp_str,"%d%% ",(int) perc);
2735
strcat(transfer_buffer,temp_str);
2736
#endif
2737
}
2738
if (count++ > 9)
2739
break;
2740
}
2741
if (*(c = transfer_buffer))
2742
chop(transfer_buffer, 1);
2743
do_hook(DCC_UPDATE_LIST, "%s", *c ? c : empty_string);
2744
if (*c)
2745
{
2746
while ((c = strchr(c, ' '))) *c = ',';
2747
}
2748
if (count)
2749
{
2750
/* chop(transfer_buffer, 1);*/
2751
if (fget_string_var(FORMAT_DCC_FSET))
2752
{
2753
sprintf(DCC_current_transfer_buffer, convert_output_format(fget_string_var(FORMAT_DCC_FSET), "%s", transfer_buffer));
2754
chop(DCC_current_transfer_buffer, 4);
2755
}
2756
else
2757
sprintf(DCC_current_transfer_buffer, "[%s]", transfer_buffer);
2758
}
2759
else
2760
*DCC_current_transfer_buffer = 0;
2761
}
2762
2763
2764
/*
2765
* returns the string without the path (if present) Also
2766
* converts filename from " " to _
2767
*/
2768
static char * strip_path(char *str)
2769
{
2770
char *ptr;
2771
#if 0
2772
char *q;
2773
2774
q = str;
2775
while ((q = strchr(q, ' ')))
2776
*q = '_';
2777
#endif
2778
if (dcc_paths)
2779
return str;
2780
ptr = strrchr(str,'/');
2781
if (ptr == NULL)
2782
return str;
2783
else
2784
return ptr+1;
2785
}
2786
2787
void dcc_show_active(char *command, char * args)
2788
{
2789
put_it("%s", convert_output_format("$G %RDCC%n DCC Active = \002$0\002, Limit = \002$1\002",
2790
"%d %d", get_active_count(), get_int_var(DCC_SEND_LIMIT_VAR)));
2791
}
2792
2793
void dcc_set_quiet(char *command, char *args )
2794
{
2795
dcc_quiet ^=1;
2796
put_it("%s", convert_output_format("$G %RDCC%n DCC Quiet = \002$0\002", "%s", on_off(dcc_quiet)));
2797
}
2798
2799
void dcc_set_paths(char *command, char *args)
2800
{
2801
dcc_paths ^= 1;
2802
put_it("%s", convert_output_format("$G %RDCC%n DCC paths is now \002$0\002", "%s", on_off(dcc_paths)));
2803
}
2804
2805
void dcc_tog_rename(char *command, char *args)
2806
{
2807
int arename = get_int_var(DCC_AUTORENAME_VAR);
2808
arename ^= 1;
2809
set_int_var(DCC_AUTORENAME_VAR, arename);
2810
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))));
2811
}
2812
2813
void dcc_tog_resume(char *command, char *args)
2814
{
2815
int arename = get_int_var(DCC_AUTORESUME_VAR);
2816
arename ^= 1;
2817
set_int_var(DCC_AUTORESUME_VAR, arename);
2818
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))));
2819
}
2820
2821
void dcc_overwrite_toggle(char *command, char *args)
2822
{
2823
dcc_overwrite_var ^= 1;
2824
put_it("%s", convert_output_format(" DCC overwrite is now \002$0\002", "%s", on_off(dcc_overwrite_var)));
2825
}
2826
2827
void dcc_tog_auto(char *command, char *args)
2828
{
2829
int dcc_auto = get_int_var(DCC_AUTOGET_VAR);
2830
dcc_auto ^= 1;
2831
set_int_var(DCC_AUTOGET_VAR, dcc_auto);
2832
put_it("%s", convert_output_format(" DCC autoget is now \002$0\002", "%s", on_off(dcc_auto)));
2833
}
2834
2835
void dcc_stats (char *command, char *unused)
2836
{
2837
char max_rate_in[20];
2838
char min_rate_in[20];
2839
char max_rate_out[20];
2840
char min_rate_out[20];
2841
2842
sprintf(max_rate_in, "%6.2f", dcc_max_rate_in/1024.0);
2843
sprintf(min_rate_in, "%6.2f", ((dcc_min_rate_in != DBL_MAX )?dcc_min_rate_in/1024.0: 0.0));
2844
sprintf(max_rate_out, "%6.2f", dcc_max_rate_out/1024.0);
2845
sprintf(min_rate_out, "%6.2f", ((dcc_min_rate_out != DBL_MAX) ? dcc_min_rate_out/1024.0: 0.0));
2846
if (do_hook(DCC_TRANSFER_STAT_LIST, "%lu %s %s %lu %s %s %lu %u %u %s %s %s %s",
2847
(unsigned long)dcc_bytes_in, max_rate_in, min_rate_in,
2848
(unsigned long)dcc_bytes_out, max_rate_out, min_rate_out,
2849
(unsigned long)(send_count_stat+get_count_stat),
2850
get_active_count(), get_int_var(DCC_SEND_LIMIT_VAR),
2851
on_off(get_int_var(DCC_AUTOGET_VAR)), on_off(dcc_paths),
2852
on_off(dcc_quiet), on_off(dcc_overwrite_var)))
2853
{
2854
char in[50], out[50];
2855
sprintf(in, "%3.2f%s", _GMKv(dcc_bytes_in), _GMKs(dcc_bytes_in));
2856
sprintf(out, "%3.2f%s", _GMKv(dcc_bytes_out), _GMKs(dcc_bytes_out));
2857
2858
#ifdef ONLY_CTD_CHARS
2859
put_it("%s",convert_output_format(" %G========================%K[%Cdcc transfer stats%K]%G=======================", NULL));
2860
put_it("%s",convert_output_format(" %G| |", NULL));
2861
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));
2862
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)));
2863
put_it("%s",convert_output_format(" %G|%g|------------|-------------|---------------|----------|---------|%G|", NULL));
2864
put_it("%s",convert_output_format(" %G| |", NULL));
2865
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));
2866
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)));
2867
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)));
2868
put_it("%s",convert_output_format(" %g|-----------------|-----------------|-----------------------------|", NULL));
2869
2870
#else
2871
2872
put_it("%s",convert_output_format(" %G������������������������%K[%Cdcc transfer stats%K]%G���������������������͸", NULL));
2873
put_it("%s",convert_output_format(" %G� �", NULL));
2874
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));
2875
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)));
2876
put_it("%s",convert_output_format(" %G�%g������������Ľ����������������������������Ľ�������������������Ľ%G�", NULL));
2877
put_it("%s",convert_output_format(" %G� �", NULL));
2878
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));
2879
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)));
2880
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)));
2881
put_it("%s",convert_output_format(" %g�����������������Ľ����������������������������������������������Ľ", NULL));
2882
2883
#endif
2884
2885
}
2886
}
2887
2888
/*
2889
* only call this on dcc finish
2890
*/
2891
void dcc_update_stats (int snum)
2892
{
2893
time_t xtime;
2894
SocketList *s;
2895
DCC_int *n;
2896
s = get_socket(snum);
2897
if (!s || !(n = (DCC_int *)s->info))
2898
return;
2899
dcc_bytes_in += n->bytes_read;
2900
dcc_bytes_out += n->bytes_sent;
2901
xtime = BX_time_diff(n->starttime, get_time(NULL));
2902
2903
if (xtime <= 0)
2904
xtime = 1;
2905
if (n->bytes_read)
2906
{
2907
get_count_stat++;
2908
if ((double)n->bytes_read/(double)xtime > dcc_max_rate_in)
2909
dcc_max_rate_in = (double)n->bytes_read/(double)xtime;
2910
if ((double)n->bytes_read/ (double)xtime < dcc_min_rate_in)
2911
dcc_min_rate_in = (double)n->bytes_read/(double)xtime;
2912
}
2913
if (n->bytes_sent)
2914
{
2915
send_count_stat++;
2916
if ((double)n->bytes_sent/(double)xtime > dcc_max_rate_out)
2917
dcc_max_rate_out = (double)n->bytes_sent/(double)xtime;
2918
if ((double)n->bytes_sent/(double)xtime < dcc_min_rate_out)
2919
dcc_min_rate_out = (double)n->bytes_sent/ (double)xtime;
2920
}
2921
}
2922
2923
/* Looks for the dcc transfer that is "current" (last recieved data)
2924
* and returns information for it
2925
*/
2926
extern char *DCC_get_current_transfer (void)
2927
{
2928
return DCC_current_transfer_buffer;
2929
}
2930
2931
2932
2933
BUILT_IN_COMMAND(chat)
2934
{
2935
int no_chat = 0, flags = 0;
2936
2937
if (!my_strnicmp(command, "NOC", 3))
2938
no_chat = 1;
2939
2940
#if HAVE_SSL
2941
if(my_strnicmp(args, "-SSL", 4) == 0)
2942
{
2943
new_next_arg(args, &args);
2944
flags = DCC_SSL;
2945
}
2946
#endif
2947
2948
if (args && *args)
2949
{
2950
char *tmp = NULL;
2951
if (no_chat)
2952
malloc_sprintf(&tmp, "CLOSE CHAT %s", args);
2953
else
2954
#ifdef HAVE_SSL
2955
if(flags & DCC_SSL)
2956
malloc_sprintf(&tmp, "CHAT -ssl %s", args);
2957
else
2958
#endif
2959
malloc_sprintf(&tmp, "CHAT %s", args);
2960
process_dcc(tmp);
2961
new_free(&tmp);
2962
}
2963
else if (last_chat_req)
2964
{
2965
DCC_int *new;
2966
if (no_chat)
2967
{
2968
char *tmp = NULL;
2969
malloc_sprintf(&tmp, "CLOSE CHAT %s", last_chat_req);
2970
process_dcc(tmp);
2971
new_free(&tmp);
2972
}
2973
if ((new = dcc_create(last_chat_req, "chat", NULL, 0, 0, DCC_CHAT, DCC_TWOCLIENTS|DCC_OFFER|flags, start_dcc_chat)))
2974
{
2975
char *equal_user;
2976
new->blocksize = get_int_var(DCC_BLOCK_SIZE_VAR);
2977
equal_user = alloca(strlen(last_chat_req)+4);
2978
strcpy(equal_user, "=");
2979
strcat(equal_user, last_chat_req);
2980
addtabkey(equal_user, "msg", 0);
2981
userhostbase(last_chat_req, add_userhost_to_chat, 1, NULL);
2982
new_free(&last_chat_req);
2983
}
2984
}
2985
}
2986
2987
2988
void dcc_exempt(char *command, char *args)
2989
{
2990
int remove;
2991
List *nptr = NULL;
2992
char *nick;
2993
if (!args || !*args)
2994
{
2995
int count = 0;
2996
for (nptr = next_namelist(dcc_no_flood, NULL, DCC_HASHSIZE); nptr; nptr = next_namelist(dcc_no_flood, nptr, DCC_HASHSIZE))
2997
{
2998
if (count == 0)
2999
put_it("%s", convert_output_format("$G %RDCC%n autoget list/no flood list", NULL, NULL));
3000
put_it("%s", nptr->name);
3001
count++;
3002
}
3003
if (count == 0)
3004
userage("/dcc exempt", "+nick to add, nick to remove");
3005
return;
3006
}
3007
nick = next_arg(args, &args);
3008
while (nick && *nick)
3009
{
3010
remove = 1;
3011
if (*nick == '+')
3012
{
3013
remove = 0;
3014
nick++;
3015
}
3016
nptr = find_name_in_genericlist(nick, dcc_no_flood, DCC_HASHSIZE, remove);
3017
if (remove && nptr)
3018
{
3019
bitchsay("removed %s from dcc exempt list", nick);
3020
new_free(&nptr->name);
3021
new_free((char **)&nptr);
3022
}
3023
else if (!remove && !nptr)
3024
{
3025
add_name_to_genericlist(nick, dcc_no_flood, DCC_HASHSIZE);
3026
bitchsay("added %s to dcc exempt list", nick);
3027
}
3028
else if (remove && !nptr)
3029
put_it("%s", convert_output_format("$G: %RDCC%n No such nick on the exempt list %K[%W$0%K]", "%s", nick));
3030
nick = next_arg(args, &args);
3031
}
3032
}
3033
3034
int dcc_exempt_save(FILE *fptr)
3035
{
3036
int count = 0;
3037
List *nptr = NULL;
3038
if (dcc_no_flood)
3039
{
3040
fprintf(fptr, "# Dcc Exempt from autoget OFF list\n");
3041
fprintf(fptr, "DCC EXEMPT ");
3042
}
3043
for (nptr = next_namelist(dcc_no_flood, NULL, DCC_HASHSIZE); nptr; nptr = next_namelist(dcc_no_flood, nptr, DCC_HASHSIZE))
3044
{
3045
fprintf(fptr, "+%s ", nptr->name);
3046
count++;
3047
}
3048
if (dcc_no_flood)
3049
{
3050
fprintf(fptr, "\n");
3051
if (count && do_hook(SAVEFILE_LIST, "DCCexempt %d", count))
3052
bitchsay("Saved %d DccExempt entries", count);
3053
3054
}
3055
return count;
3056
}
3057
3058
/*
3059
* This is a callback. When we want to do a CTCP DCC REJECT, we do
3060
* a WHOIS to make sure theyre still on irc, no sense sending it to
3061
* nobody in particular. When this gets called back, that means the
3062
* peer is indeed on irc, so we send them the REJECT.
3063
*/
3064
static void output_reject_ctcp (UserhostItem *stuff, char *nick, char *args)
3065
{
3066
char *nickname_requested;
3067
char *nickname_recieved;
3068
char *type;
3069
char *description;
3070
if (!stuff || !stuff->user || !strcmp(stuff->user, "<UNKNOWN>"))
3071
{
3072
return;
3073
}
3074
/*
3075
* XXX This is, of course, a monsterous hack.
3076
*/
3077
nickname_requested = next_arg(args, &args);
3078
type = next_arg(args, &args);
3079
description = next_arg(args, &args);
3080
nickname_recieved = stuff->nick;
3081
3082
if (nickname_recieved && *nickname_recieved)
3083
send_ctcp(CTCP_NOTICE, nickname_recieved, CTCP_DCC,
3084
"REJECT %s %s", type, description);
3085
}
3086
3087
extern void dcc_reject (char *from, char *type, char *args)
3088
{
3089
SocketList *s;
3090
DCC_List *s1 = NULL;
3091
char *description;
3092
int CType;
3093
int tdcc = 0;
3094
3095
upper(type);
3096
if (*type == 'T' && *(type+1))
3097
tdcc = 1;
3098
for (CType = 0; dcc_types[CType]->name != NULL; CType++)
3099
if (!strcmp(type+tdcc, dcc_types[CType]->name))
3100
break;
3101
3102
if (!dcc_types[CType]->name)
3103
return;
3104
if (tdcc)
3105
CType |= DCC_TDCC;
3106
3107
description = next_arg(args, &args);
3108
if ((s = find_dcc(from, description, NULL, CType, 0, -1, -1)) || (s1 = find_dcc_pending(from, description, NULL, CType, 1, -1)))
3109
{
3110
DCC_int *n;
3111
if (s1)
3112
s = & s1->sock;
3113
n = (DCC_int *)s->info;
3114
if (do_hook(DCC_LOST_LIST,"%s %s %s REJECTED", from, type, description ? description : "<any>"))
3115
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));
3116
3117
3118
if (!s1)
3119
erase_dcc_info(s->is_read, 0, NULL);
3120
close_socketread(s->is_read);
3121
if (s1)
3122
{
3123
new_free(&s->server);
3124
new_free(&n->userhost);
3125
new_free(&n->user);
3126
new_free(&n->encrypt);
3127
new_free(&n->filename);
3128
new_free(&s1);
3129
}
3130
#ifdef WANT_CDCC
3131
dcc_sendfrom_queue();
3132
#endif
3133
update_transfer();
3134
update_all_status(current_window, NULL, 0);
3135
}
3136
}
3137
3138
BUILT_IN_COMMAND(dcx)
3139
{
3140
int i;
3141
unsigned long flag;
3142
SocketList *s;
3143
int all = 0;
3144
unsigned long type = 0;
3145
char *nick = NULL;
3146
if (!my_stricmp(command, "DCA"))
3147
all = 1;
3148
else if (!my_stricmp(command, "DCG"))
3149
type = DCC_FILEREAD;
3150
else if (!my_stricmp(command, "DCS"))
3151
type = DCC_FILEOFFER;
3152
else if (!my_stricmp(command, "DCX"))
3153
type = DCC_CHAT;
3154
else
3155
return;
3156
nick = next_arg(args, &args);
3157
if (!all && !nick)
3158
return;
3159
for (i = 0; i < get_max_fd() + 1; i++)
3160
{
3161
if (!check_dcc_socket(i))
3162
continue;
3163
s = get_socket(i);
3164
flag = s->flags & DCC_TYPES;
3165
if (all || (type == flag))
3166
{
3167
if ((!all && nick) || (all && nick))
3168
{
3169
if (!wild_match(nick, s->server))
3170
continue;
3171
}
3172
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));
3173
close_socketread(i);
3174
}
3175
}
3176
return;
3177
}
3178
3179
void close_all_dcc(void)
3180
{
3181
int i;
3182
SocketList *s;
3183
unsigned long flag;
3184
for (i = 0; i < get_max_fd() + 1; i++)
3185
{
3186
if (!check_dcc_socket(i))
3187
continue;
3188
s = get_socket(i);
3189
flag = s->flags & DCC_TYPES;
3190
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));
3191
close_socketread(i);
3192
}
3193
return;
3194
}
3195
3196
3197
static char *last_notify = NULL;
3198
3199
void cancel_dcc_auto(int i, unsigned long flags, SocketList *s)
3200
{
3201
if (!last_notify || strcmp(s->server,last_notify))
3202
{
3203
send_to_server("NOTICE %s :DCC %s Auto Closed", s->server, dcc_types[flags]->name);
3204
malloc_strcpy(&last_notify, s->server);
3205
}
3206
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));
3207
close_socketread(i);
3208
}
3209
3210
void dcc_check_idle(void)
3211
{
3212
int i;
3213
time_t dcc_idle_time = get_int_var(_CDCC_CLOSE_IDLE_SENDS_TIME_VAR);
3214
#ifdef WANT_CDCC
3215
int minidlecheck = get_int_var(_CDCC_MINSPEED_TIME_VAR);
3216
#endif
3217
SocketList *s = NULL;
3218
DCC_int *n = NULL;
3219
unsigned long flags;
3220
3221
if (pending_dcc)
3222
{
3223
DCC_List *s1 = pending_dcc, *last = NULL;
3224
while (s1)
3225
{
3226
s = &s1->sock;
3227
n = (DCC_int *)s->info;
3228
if (now >= s->time)
3229
{
3230
if (last)
3231
last->next = s1->next;
3232
else
3233
pending_dcc = s1->next;
3234
new_free(&s->server);
3235
new_free(&n->user);
3236
new_free(&n->filename);
3237
new_free(&n->userhost);
3238
new_free(&n->encrypt);
3239
close_socketread(s->is_read);
3240
new_free(&n);
3241
new_free(&s1);
3242
break;
3243
}
3244
last = s1;
3245
s1 = s1->next;
3246
}
3247
}
3248
for (i = 0; i < get_max_fd()+1; i++)
3249
{
3250
time_t client_idle,
3251
this_idle_time;
3252
3253
if (!check_dcc_socket(i))
3254
continue;
3255
s = get_socket(i);
3256
n = (DCC_int *)s->info;
3257
3258
flags = s->flags & DCC_TYPES;
3259
client_idle = now - n->lasttime.tv_sec;
3260
switch (flags)
3261
{
3262
case DCC_FILEOFFER:
3263
case DCC_FILEREAD:
3264
case DCC_REFILEOFFER:
3265
case DCC_REFILEREAD:
3266
this_idle_time = dcc_idle_time * 3;
3267
break;
3268
default:
3269
this_idle_time = dcc_timeout;
3270
break;
3271
}
3272
if (!(s->flags & DCC_ACTIVE))
3273
{
3274
if ((client_idle > this_idle_time))
3275
cancel_dcc_auto(i, flags, s);
3276
continue;
3277
}
3278
#ifdef WANT_CDCC
3279
switch (flags)
3280
{
3281
case DCC_FILEOFFER:
3282
case DCC_REFILEOFFER:
3283
if (cdcc_minspeed && minidlecheck && (((now - n->starttime.tv_sec) % minidlecheck) == 0))
3284
{
3285
unsigned long sent = n->bytes_sent / 1024;
3286
double this_speed = 0.0;
3287
char lame_ultrix1[20];
3288
char lame_ultrix[20];
3289
this_speed = (double)((double) sent / (double)(now- n->starttime.tv_sec));
3290
if (this_speed < (float)cdcc_minspeed)
3291
{
3292
sprintf(lame_ultrix, "%2.4g", (double)(sent / (now - n->starttime.tv_sec)));
3293
sprintf(lame_ultrix1,"%2.4g", (double)cdcc_minspeed);
3294
if (!last_notify || strcmp(s->server,last_notify))
3295
{
3296
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);
3297
malloc_strcpy(&last_notify, s->server);
3298
}
3299
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));
3300
close_socketread(i);
3301
}
3302
break;
3303
}
3304
if (client_idle > this_idle_time)
3305
cancel_dcc_auto(i, flags, s);
3306
default:
3307
break;
3308
}
3309
#endif
3310
}
3311
#ifdef WANT_CDCC
3312
cdcc_timer_offer();
3313
#endif
3314
return;
3315
}
3316
3317
void dcc_close(char *command, char *args)
3318
{
3319
char *type;
3320
char *file;
3321
char *nick;
3322
int any_type = 0;
3323
int any_user = 0;
3324
int count = 0;
3325
SocketList *s;
3326
DCC_List *s1;
3327
int i;
3328
int num = -1;
3329
3330
type = next_arg(args, &args);
3331
nick = next_arg(args, &args);
3332
file = next_arg(args, &args);
3333
if (type)
3334
{
3335
if (!my_stricmp(type, "-all") || !strcmp(type, "*"))
3336
any_type = 1;
3337
else if (*type == '#' && (num = my_atol(type+1)))
3338
any_type = 1;
3339
}
3340
if (nick && (!my_stricmp(nick, "-all") || !strcmp(nick, "*")))
3341
any_user = 1;
3342
if (!type || (!nick && (!any_type || num == -1)))
3343
{
3344
bitchsay("Specify a nick and a type to close or a number");
3345
return;
3346
}
3347
if (!any_type)
3348
{
3349
for (i = 0; dcc_types[i]->name; i++)
3350
if (!my_stricmp(dcc_types[i]->name, type))
3351
break;
3352
if (!dcc_types[i]->name)
3353
{
3354
bitchsay("Unknown dcc type for close");
3355
return;
3356
}
3357
} else
3358
i = -1;
3359
if (any_user)
3360
nick = NULL;
3361
while ((s = find_dcc(nick, file, NULL, i, 0, -1, num)))
3362
{
3363
DCC_int *n;
3364
n = (DCC_int *)s->info;
3365
count++;
3366
if (do_hook(DCC_LOST_LIST,"%s %s %s USER ABORTED CONNECTION",
3367
s->server,
3368
dcc_types[s->flags & DCC_TYPES]->name,
3369
n->filename ? n->filename : "<any>"))
3370
say("DCC %s:%s to %s closed",
3371
dcc_types[s->flags & DCC_TYPES]->name,
3372
file ? file : "<any>",
3373
s->server);
3374
erase_dcc_info(s->is_read, 1, NULL);
3375
close_socketread(s->is_read);
3376
}
3377
while ((s1 = find_dcc_pending(nick, file, NULL, i, 1, num)))
3378
{
3379
DCC_int *n;
3380
s = &s1->sock;
3381
n = (DCC_int *)s->info;
3382
count++;
3383
if (do_hook(DCC_LOST_LIST,"%s %s %s USER ABORTED CONNECTION",
3384
s->server,
3385
dcc_types[s->flags & DCC_TYPES]->name,
3386
n->filename ? n->filename : "<any>"))
3387
say("DCC %s:%s to %s closed",
3388
dcc_types[s->flags & DCC_TYPES]->name,
3389
file ? file : "<any>",
3390
s->server);
3391
3392
send_reject_ctcp(s->server,
3393
(((s->flags & DCC_TYPES) == DCC_FILEOFFER) ? "GET" :
3394
((s->flags & DCC_TYPES) == DCC_FILEREAD) ? "SEND" :
3395
dcc_types[s->flags & DCC_TYPES]->name),
3396
n->filename);
3397
3398
new_free(&s->server);
3399
new_free(&n->user);
3400
new_free(&n->filename);
3401
new_free(&n->userhost);
3402
new_free(&n->encrypt);
3403
close_socketread(s->is_read);
3404
new_free(&n);
3405
new_free(&s1);
3406
}
3407
if (!count)
3408
put_it("%s", convert_output_format("$G %RDCC%n No DCC $0:$1 to $2 found", "%s %s %s",
3409
(i == -1 ? "<any>" : type),
3410
(file ? file : "<any>"),
3411
(num != -1) ? ltoa(num): nick ? nick : "(null)"));
3412
update_transfer();
3413
return;
3414
}
3415
3416
void dcc_closeall(char *command, char *args)
3417
{
3418
close_all_dcc();
3419
}
3420
3421
extern int doing_notice;
3422
3423
#ifdef MIRC_BROKEN_DCC_RESUME
3424
3425
void dcc_getfile_resume_demanded(char *nick, char *filename, char *port, char *offset)
3426
{
3427
SocketList *s;
3428
DCC_int *n;
3429
int old_dp, old_dn, old_dc;
3430
3431
if (filename && !strcmp(filename, "file.ext"))
3432
filename = NULL;
3433
if (!(s = find_dcc(nick, filename, port, DCC_FILEOFFER, 1, -1, -1)))
3434
{
3435
put_it("%s", convert_output_format("$G %RDCC%n warning in dcc_getfile_resume_demanded", NULL));
3436
return;
3437
}
3438
n = (DCC_int *)s->info;
3439
if (!offset)
3440
return;
3441
old_dp = doing_privmsg;
3442
old_dn = doing_notice;
3443
old_dc = in_ctcp_flag;
3444
3445
n->bytes_read = n->transfer_orders.byteoffset = my_atol(offset);
3446
/* n->bytes_read = 0L;*/
3447
3448
doing_privmsg = doing_notice = in_ctcp_flag = 0;
3449
send_ctcp(CTCP_PRIVMSG, nick, CTCP_DCC, "ACCEPT %s %s %s", filename, port, offset);
3450
doing_privmsg = old_dp;
3451
doing_notice = old_dn;
3452
in_ctcp_flag = old_dc;
3453
}
3454
3455
void dcc_getfile_resume_start (char *nick, char *description, char *address, char *port)
3456
{
3457
SocketList *s;
3458
DCC_int *n;
3459
char *tmp = NULL;
3460
char *fullname = NULL;
3461
struct stat sb;
3462
3463
/* resume command has been sent and accepted. */
3464
if (description && !strcmp(description, "file.ext"))
3465
description = NULL;
3466
if ((s = find_dcc(nick, description, NULL, DCC_FILEREAD, 1, 1, -1)))
3467
{
3468
put_it("%s", convert_output_format("$G %RDCC%n warning in dcc_getfile_resume_start", NULL));
3469
return;
3470
}
3471
if (!(n = dcc_create(nick, description, NULL, 0, port?atol(port):0, DCC_FILEREAD, DCC_TWOCLIENTS|DCC_OFFER, start_dcc_get)))
3472
return;
3473
3474
if (get_string_var(DCC_DLDIR_VAR))
3475
malloc_sprintf(&tmp, "%s/%s", get_string_var(DCC_DLDIR_VAR), n->filename);
3476
else
3477
tmp = m_strdup(n->filename);
3478
if (!(fullname = expand_twiddle(tmp)))
3479
malloc_strcpy(&fullname, tmp);
3480
3481
if (
3482
!(n->file = open(fullname, O_WRONLY | O_APPEND | O_BINARY, 0644)) ||
3483
(fstat(n->file, &sb) != 0) ||
3484
(sb.st_size >= n->filesize)
3485
)
3486
{
3487
int snum;
3488
if ((s = find_dcc(nick, description, NULL, DCC_FILEREAD, 0, 1, -1)))
3489
n = (DCC_int *)s->info;
3490
if (s)
3491
{
3492
snum = s->is_read;
3493
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"));
3494
close_socketread(snum);
3495
}
3496
} else
3497
put_it("DCC RESUME starting at %lu", sb.st_size);
3498
new_free(&fullname);
3499
new_free(&tmp);
3500
}
3501
3502
void dcc_resume(char *command, char *args)
3503
{
3504
char *user, *nick;
3505
char *filename = NULL;
3506
char *fullname = NULL;
3507
char *tmp = NULL;
3508
char *passwd = NULL;
3509
char *port = NULL;
3510
struct stat sb;
3511
int old_dp, old_dn, old_dc;
3512
int blocksize = 0;
3513
3514
user = get_dcc_args(&args, &passwd, &port, &blocksize);
3515
if (!user)
3516
{
3517
put_it("%s", convert_output_format("$G %RDCC%n You must supply a nickname for DCC get", NULL, NULL));
3518
return;
3519
}
3520
if (!blocksize || blocksize > MAX_DCC_BLOCK_SIZE)
3521
blocksize = get_int_var(DCC_BLOCK_SIZE_VAR);
3522
3523
if (!user)
3524
{
3525
put_it("%s", convert_output_format("$G %RDCC%n You must supply a nickname for DCC RESUME", NULL));
3526
return;
3527
}
3528
if (args && *args)
3529
filename = args;
3530
3531
tmp = NULL;
3532
3533
while ((nick = next_in_comma_list(user, &user)))
3534
{
3535
SocketList *s;
3536
DCC_int *n;
3537
DCC_List *s1 = NULL;
3538
if (!nick || !*nick)
3539
break;
3540
if ((s = find_dcc(nick, filename, NULL, DCC_FILEREAD, 1, 1, -1)))
3541
{
3542
put_it("%s", convert_output_format("$G %RDCC%n DCC send already active. Unable to RESUME", NULL));
3543
continue;
3544
}
3545
for (s1 = pending_dcc; s1; s1 = s1->next)
3546
{
3547
if (my_stricmp(s1->nick, nick))
3548
continue;
3549
if ( ((s1->sock.flags & DCC_TYPES) != DCC_FILEREAD) ||
3550
(s1->sock.flags & DCC_ACTIVE))
3551
continue;
3552
break;
3553
}
3554
if (!s1)
3555
continue;
3556
s = &s1->sock;
3557
n = (DCC_int *)s->info;
3558
3559
if (get_string_var(DCC_DLDIR_VAR))
3560
malloc_sprintf(&tmp, "%s/%s", get_string_var(DCC_DLDIR_VAR), n->filename);
3561
else
3562
tmp = m_strdup(n->filename);
3563
3564
if (!(fullname = expand_twiddle(tmp)))
3565
malloc_strcpy(&fullname, tmp);
3566
/*
3567
* This has to be done by hand, we cant use send_ctcp,
3568
* because this violates the protocol, and send_ctcp checks
3569
* for that. Ugh.
3570
*/
3571
3572
if (stat(fullname, &sb) == -1)
3573
{
3574
/* File doesnt exist. Sheesh. */
3575
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)));
3576
continue;
3577
}
3578
3579
if (passwd)
3580
n->encrypt = m_strdup(passwd);
3581
3582
n->bytes_sent = 0L;
3583
n->blocksize = blocksize;
3584
n->transfer_orders.byteoffset = sb.st_size;
3585
3586
old_dp = doing_privmsg; old_dn = doing_notice; old_dc = in_ctcp_flag;
3587
/* Just in case we have to fool the protocol enforcement. */
3588
doing_privmsg = doing_notice = in_ctcp_flag = 0;
3589
send_ctcp(CTCP_PRIVMSG, nick, CTCP_DCC, "RESUME %s %d %ld", n->filename, ntohs(n->remport), sb.st_size);
3590
doing_privmsg = old_dp; doing_notice = old_dn; in_ctcp_flag = old_dc;
3591
3592
}
3593
new_free(&tmp);
3594
new_free(&fullname);
3595
/* Then we just sit back and wait for the reply. */
3596
}
3597
#endif
3598
3599
void dcc_help1(char *command, char *args)
3600
{
3601
char *comm;
3602
int i, c;
3603
char buffer[BIG_BUFFER_SIZE+1];
3604
DCC_dllcommands *dcc_comm = NULL;
3605
if (args && *args)
3606
{
3607
comm = next_arg(args, &args);
3608
upper(comm);
3609
if ((dcc_comm = (DCC_dllcommands *)find_in_list((List **)&dcc_dllcommands, comm, 0)))
3610
{
3611
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"));
3612
return;
3613
}
3614
for (i = 0; dcc_commands[i].name != NULL; i++)
3615
{
3616
if (!strncmp(comm, dcc_commands[i].name, strlen(comm)))
3617
{
3618
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"));
3619
return;
3620
}
3621
}
3622
}
3623
put_it("%s", convert_output_format("$G %RDCC%n help -", NULL, NULL));
3624
*buffer = 0;
3625
c = 0;
3626
for (dcc_comm = dcc_dllcommands; dcc_comm; dcc_comm = dcc_comm->next)
3627
{
3628
strcat(buffer, dcc_comm->name);
3629
strcat(buffer, space);
3630
if (++c == 5)
3631
{
3632
put_it("%s", convert_output_format("$G $[13]0 $[13]1 $[13]2 $[13]3 $[13]4", "%s", buffer));
3633
*buffer = 0;
3634
c = 0;
3635
}
3636
}
3637
if (c)
3638
put_it("%s", convert_output_format("$G $[13]0 $[13]1 $[13]2 $[13]3 $[13]4", "%s", buffer));
3639
*buffer = 0;
3640
c = 0;
3641
for (i = 0; dcc_commands[i].name; i++)
3642
{
3643
strcat(buffer, dcc_commands[i].name);
3644
strcat(buffer, space);
3645
if (++c == 5)
3646
{
3647
put_it("%s", convert_output_format("$G $[13]0 $[13]1 $[13]2 $[13]3 $[13]4", "%s", buffer));
3648
*buffer = 0;
3649
c = 0;
3650
}
3651
}
3652
if (c)
3653
put_it("%s", convert_output_format("$G $[13]0 $[13]1 $[13]2 $[13]3 $[13]4", "%s", buffer));
3654
userage("dcc help", "[command] to get help on specific commands");
3655
}
3656
3657
void read_ftp_file(int snum)
3658
{
3659
int len = 0;
3660
char *buf;
3661
SocketList *s;
3662
DCC_int *n;
3663
int err;
3664
if ((ioctl(snum, FIONREAD, &len) == -1))
3665
{
3666
put_it("%s", convert_output_format("$G %gFTP%n file error [$0-]", "%s", strerror(errno)));
3667
erase_dcc_info(snum, 0, NULL);
3668
close_socketread(snum);
3669
return;
3670
}
3671
s = get_socket(snum);
3672
n = (DCC_int *)s->info;
3673
buf = alloca(len+1);
3674
err = read(snum, buf, len);
3675
switch(err)
3676
{
3677
case -1:
3678
erase_dcc_info(snum, 0, NULL);
3679
close_socketread(snum);
3680
break;
3681
case 0:
3682
close_dcc_file(snum);
3683
break;
3684
default:
3685
write(n->file, buf, len);
3686
n->bytes_read += len;
3687
n->packets++;
3688
get_time(&n->lasttime);
3689
}
3690
}
3691
3692
int open_listen_port(int s)
3693
{
3694
struct sockaddr_in data_addr = { 0 };
3695
int len = sizeof(struct sockaddr_in), data = -1;
3696
int on = 1;
3697
char *a, *p;
3698
3699
if (getsockname(s, (struct sockaddr *)&data_addr, &len) < 0)
3700
return -1;
3701
3702
data_addr.sin_port = 0;
3703
if ((data = socket(AF_INET, SOCK_STREAM, 0)) < 0)
3704
return -1;
3705
if ((setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on))) < 0)
3706
return -1;
3707
if ((bind(data, (struct sockaddr *)&data_addr, sizeof(data_addr))) < 0)
3708
return -1;
3709
len = sizeof(struct sockaddr_in);
3710
getsockname(data, (struct sockaddr *)&data_addr, &len);
3711
3712
a = (char *)&data_addr.sin_addr;
3713
p = (char *)&data_addr.sin_port;
3714
#define UC(b) (((int)b)&0xff)
3715
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]));
3716
#undef UC
3717
if ((listen(data, 1)) < 0)
3718
return -1;
3719
return data;
3720
}
3721
3722
3723
int handle_ftp(int comm, int snum, SocketList *s, char *buf)
3724
{
3725
int err = 0;
3726
DCC_int *n;
3727
n = (DCC_int *)s->info;
3728
get_time(&n->lasttime);
3729
switch(comm)
3730
{
3731
case 220:
3732
if (n->userhost)
3733
err = dcc_printf(snum, "user %s\r\n", n->userhost);
3734
new_free(&n->userhost);
3735
break;
3736
case 226:
3737
s->flags &= ~DCC_WAIT;
3738
return 0;
3739
case 331:
3740
if (n->encrypt)
3741
{
3742
err = dcc_printf(snum, "pass %s\r\n", n->encrypt);
3743
if (err != -1)
3744
err = dcc_printf(snum, "type I\r\n");
3745
}
3746
new_free(&n->encrypt); new_free(&n->othername);
3747
break;
3748
case 230:
3749
{
3750
char *dir = NULL;
3751
if (n->othername)
3752
{
3753
err = dcc_printf(snum, "cwd %s\r\n", n->othername);
3754
if (do_hook(FTP_LIST, "%d Changing directory to %s", comm, n->othername))
3755
put_it("%s", convert_output_format("%gFTP%n Changing directory to $0-", "%s", n->othername));
3756
}
3757
new_free(&n->encrypt);
3758
new_free(&n->userhost);
3759
new_free(&n->othername);
3760
new_free(&dir);
3761
break;
3762
}
3763
case 421:
3764
erase_dcc_info(snum, 0, NULL);
3765
close_socketread(snum);
3766
break;
3767
default:
3768
break;
3769
}
3770
if (do_hook(FTP_LIST, "%d %s", comm, buf))
3771
put_it("%s", convert_output_format("%gFTP%n $0-", "%s", buf));
3772
return err;
3773
}
3774
3775
void start_ftp(int snum)
3776
{
3777
SocketList *s;
3778
DCC_int *n;
3779
char *buf = NULL;
3780
int i = 0;
3781
3782
s = get_socket(snum);
3783
n = (DCC_int *)s->info;
3784
if (s->flags & DCC_WAIT)
3785
{
3786
struct sockaddr_in remaddr;
3787
int rl = sizeof(remaddr);
3788
3789
/* maybe we should login here. */
3790
if (getpeername(snum, (struct sockaddr *) &remaddr, &rl) != -1)
3791
{
3792
s->flags = DCC_ACTIVE|DCC_FTPOPEN;
3793
return;
3794
}
3795
erase_dcc_info(snum, 0, "DCC ftp lost");
3796
close_socketread(snum);
3797
return;
3798
}
3799
buf = alloca(n->blocksize+1);
3800
*buf = 0;
3801
switch(dgets(buf, snum, 1, n->blocksize, NULL))
3802
{
3803
case -1:
3804
i = -1;
3805
break;
3806
case 0:
3807
break;
3808
default:
3809
{
3810
int comm = 0;
3811
char *p;
3812
if ((p = strrchr(buf, '\r')))
3813
*p = 0;
3814
if ((p = strrchr(buf, '\n')))
3815
*p = 0;
3816
if ((comm = my_atol(buf)))
3817
next_arg(buf, &buf);
3818
i = handle_ftp(comm, snum, s, buf);
3819
break;
3820
}
3821
}
3822
if (i == -1)
3823
{
3824
erase_dcc_info(snum, 0, NULL);
3825
close_socketread(snum);
3826
}
3827
}
3828
3829
3830
void open_ftpget(SocketList *s, char *args)
3831
{
3832
SocketList *sock;
3833
DCC_int *new;
3834
struct sockaddr_in data_addr = { 0 };
3835
int len = sizeof(struct sockaddr_in);
3836
char tmp[BIG_BUFFER_SIZE+1];
3837
int data = -1, s1 = -1;
3838
char *p, *bufptr;
3839
off_t filesize = 0;
3840
char *filename = NULL;
3841
3842
if ((data = open_listen_port(s->is_read)) == -1)
3843
return;
3844
3845
dcc_printf(s->is_read, "retr %s\n", args);
3846
3847
memset(tmp, 0, sizeof(tmp));
3848
bufptr = tmp;
3849
while (1)
3850
{
3851
if (dgets(bufptr, s->is_read, 1, BIG_BUFFER_SIZE, NULL) == -1 && dgets_errno > 0)
3852
goto error_ftp;
3853
if (*bufptr == '5')
3854
goto error_ftp;
3855
else if (strstr(tmp, "BINARY mode data connection"))
3856
{
3857
int i = 0;
3858
char *q = tmp;
3859
for (i = 0; i < 9; i++)
3860
p = next_arg(q, &q);
3861
if (p)
3862
{
3863
p++;
3864
filesize = my_atol(p);
3865
}
3866
break;
3867
}
3868
}
3869
3870
len = sizeof(struct sockaddr_in);
3871
if ((s1 = my_accept(data, (struct sockaddr *) &data_addr, &len)) < 0)
3872
return;
3873
close(data);
3874
3875
#if defined(WINNT) || defined(__EMX__)
3876
if ((p = strrchr(args, '/')) || (p = strrchr(args, '\\')))
3877
#else
3878
if ((p = strrchr(args, '/')))
3879
#endif
3880
filename = ++p;
3881
else
3882
filename = args;
3883
3884
add_socketread(s1, 0, DCC_FTPGET|DCC_ACTIVE, s->server, read_ftp_file, NULL);
3885
sock = get_socket(s1);
3886
new = new_malloc(sizeof(DCC_int));
3887
{
3888
char *t, *expand;
3889
expand = m_sprintf("%s/%s", get_string_var(DCC_DLDIR_VAR), filename);
3890
t = expand_twiddle(expand);
3891
new->file = open(t?t:expand?expand:filename, O_WRONLY|O_CREAT|O_TRUNC | O_BINARY, 0644);
3892
new_free(&t); new_free(&expand);
3893
}
3894
new->struct_type = DCC_STRUCT_TYPE;
3895
new->filesize = filesize;
3896
new->filename = m_strdup(filename);
3897
get_time(&new->starttime);
3898
get_time(&new->lasttime);
3899
set_socketinfo(s1, new);
3900
s->flags |= DCC_WAIT;
3901
if (do_hook(FTP_LIST, "%s %s", "FTP Attempting to get", filename))
3902
put_it("%s", convert_output_format("$G %gFTP%n Attempting to get $0", "%s", filename));
3903
return;
3904
error_ftp:
3905
close(data);
3906
chop(tmp, 2);
3907
put_it("%s", convert_output_format("$G %gFTP%n $0-", "%s", tmp));
3908
return;
3909
3910
}
3911
3912
int dcc_ftpcommand (char *host, char *args)
3913
{
3914
SocketList *s;
3915
s = find_dcc(host, "ftpopen", NULL, DCC_FTPOPEN, 0, 1, -1);
3916
if (s)
3917
{
3918
char *command = next_arg(args, &args);
3919
char *t_host;
3920
if (s->flags & DCC_WAIT)
3921
{
3922
if (do_hook(FTP_LIST, "%s", "FTP connection is busy"))
3923
put_it("%s", convert_output_format("$G %gFTP%n connection is busy.", NULL, NULL));
3924
return 1;
3925
}
3926
3927
if (command && *command)
3928
{
3929
if (!my_strnicmp(command, "ls",2) || !my_strnicmp(command, "dir",3))
3930
{
3931
int sock, s1;
3932
DCC_int *new;
3933
struct sockaddr_in data_addr = { 0 };
3934
int len = sizeof(struct sockaddr_in);
3935
char tmp[BIG_BUFFER_SIZE+1], *bufptr;
3936
if ((sock = open_listen_port(s->is_read)) == -1)
3937
return -1;
3938
dcc_printf(s->is_read, "list -a%s%s\r\n", (args && *args) ?space:empty_string, (args && *args) ? args : empty_string);
3939
memset(tmp, 0, sizeof(tmp));
3940
bufptr = tmp;
3941
while (1)
3942
{
3943
if (dgets(bufptr, s->is_read, 1, BIG_BUFFER_SIZE, NULL) == -1 && dgets_errno > 0)
3944
goto error_port;
3945
if (*bufptr == '5')
3946
goto error_port;
3947
else if (strstr(tmp, "150 Opening BINARY mode data connection"))
3948
break;
3949
}
3950
3951
len = sizeof(struct sockaddr_in);
3952
set_blocking(sock);
3953
alarm(10);
3954
s1 = accept(sock, (struct sockaddr *) &data_addr, &len);
3955
alarm(0);
3956
close(sock);
3957
if (s1 != -1)
3958
{
3959
add_socketread(s1, 0, DCC_FTPCOMMAND|DCC_ACTIVE, s->server, start_ftp, NULL);
3960
new = new_malloc(sizeof(DCC_int));
3961
new->struct_type = DCC_STRUCT_TYPE;
3962
get_time(&new->starttime);
3963
get_time(&new->lasttime);
3964
new->blocksize = BIG_BUFFER_SIZE;
3965
set_socketinfo(s1, new);
3966
} else
3967
bitchsay("FTP data connection failed.");
3968
}
3969
else if (!my_strnicmp(command, "more", 3))
3970
dcc_printf(s->is_read, "stat %s\n", (args && *args) ? "cwd" : "pwd", (args && *args) ?args:empty_string);
3971
else if (!my_strnicmp(command, "cd", 2))
3972
dcc_printf(s->is_read, "%s%s%s\n", (args && *args) ? "cwd" : "pwd", (args && *args) ? space:empty_string, (args && *args) ?args:empty_string);
3973
else if (!my_strnicmp(command, "get",3) && args && *args)
3974
open_ftpget(s, args);
3975
else
3976
dcc_printf(s->is_read, "%s%s%s\n", command, (args && *args) ? space:empty_string, (args && *args) ? args:empty_string);
3977
3978
t_host = alloca(strlen(host)+4);
3979
strcpy(t_host, "-");
3980
strcat(t_host, host);
3981
addtabkey(t_host, "msg", 0);
3982
}
3983
}
3984
else
3985
{
3986
if (do_hook(FTP_LIST, "%s", "FTP is not connected"))
3987
put_it("%s", convert_output_format("$G %gFTP%n is not connected.", NULL, NULL));
3988
return 0;
3989
}
3990
return 1;
3991
error_port:
3992
return -1;
3993
}
3994
3995
3996
char *parse_ncftp(char *buffer, char **hostname)
3997
{
3998
char *dir = NULL, *p;
3999
4000
/*bitchx,bitchx.com,panasync,,,/home/panasync,I,,34ce4360,1,*/
4001
if (!(p = strchr(buffer, ',')))
4002
return NULL;
4003
*p++ = 0; *hostname = p;
4004
if (!(p = strchr(p, ',')))
4005
return NULL;
4006
*p++ = 0;
4007
if (!(p = strchr(p, ',')))
4008
return NULL;
4009
*p++ = 0;
4010
if (!(p = strchr(p, ',')))
4011
return NULL;
4012
*p++ = 0;
4013
if (!(p = strchr(p, ',')))
4014
return NULL;
4015
*p++ = 0;
4016
4017
dir = p;
4018
if (!(p = strchr(p, ',')))
4019
return NULL;
4020
*p = 0;
4021
return (dir && *dir) ? dir : NULL;
4022
}
4023
4024
char *read_ncftp_config(char **hostname)
4025
{
4026
char *tmp, *file = NULL;
4027
char *buffer;
4028
char *dir = NULL;
4029
struct stat sb;
4030
FILE *f;
4031
tmp = m_sprintf("~/.ncftp/bookmarks");
4032
file = expand_twiddle(tmp);
4033
if ((stat(file, &sb) != -1) && (f = fopen(file, "r")))
4034
{
4035
char *hst = NULL;
4036
buffer = alloca(sb.st_size+1);
4037
freadln(f, buffer);
4038
while(!feof(f))
4039
{
4040
if ((freadln(f, buffer)))
4041
{
4042
if (*buffer == '#')
4043
continue;
4044
dir = parse_ncftp(buffer, &hst);
4045
if (hst)
4046
{
4047
if (!my_stricmp(hst, *hostname))
4048
break;
4049
else if (!my_stricmp(*hostname, buffer))
4050
{
4051
malloc_strcpy(hostname, hst);
4052
break;
4053
}
4054
}
4055
dir = NULL;
4056
}
4057
}
4058
fclose(f);
4059
}
4060
new_free(&tmp); new_free(&file);
4061
return dir ? m_strdup(dir) : NULL;
4062
}
4063
4064
void dcc_ftpopen(char *command, char *args)
4065
{
4066
char u[] = "anonymous";
4067
char p[] = "- bxuser@";
4068
char *host = NULL,
4069
*user = NULL,
4070
*pass = NULL,
4071
*dir = NULL,
4072
*t_host = NULL;
4073
unsigned short port = 21;
4074
int blocksize = 2048;
4075
int snum;
4076
SocketList *s;
4077
4078
if (!(t_host = next_arg(args, &args)))
4079
{
4080
put_it ("%s /dcc ftp hostname user passwd [-p port] [-b blocksize]", convert_output_format("$G %RDCC%n", NULL, NULL));
4081
return;
4082
}
4083
host = m_strdup(t_host);
4084
while (args && *args)
4085
{
4086
char *t;
4087
if (!my_strnicmp(args, "-p", 2))
4088
{
4089
next_arg(args, &args);
4090
port = my_atol(next_arg(args, &args));
4091
continue;
4092
}
4093
if (!my_strnicmp(args, "-b", 2))
4094
{
4095
next_arg(args, &args);
4096
blocksize = my_atol(next_arg(args, &args));
4097
continue;
4098
}
4099
else if ((t = next_arg(args, &args)))
4100
{
4101
if (!user)
4102
user = t;
4103
else
4104
malloc_strcpy(&pass, t);
4105
}
4106
}
4107
if (!user)
4108
user = u;
4109
if (!pass)
4110
pass = m_sprintf("%s%s", p, hostname);
4111
4112
dir = read_ncftp_config(&host);
4113
4114
if ((s = find_dcc(host, "ftpopen", NULL, DCC_FTPOPEN, 0, -1, -1)))
4115
{
4116
put_it("%s", convert_output_format("$G %GFTP%n A previous DCC FTP to $0 exists", "%s", host));
4117
new_free(&host);
4118
return;
4119
}
4120
4121
#if defined(WINNT) || defined(__EMX__)
4122
if ((snum = connect_by_number(host, &port, SERVICE_CLIENT, PROTOCOL_TCP, 0)) < 0)
4123
#else
4124
if ((snum = connect_by_number(host, &port, SERVICE_CLIENT, PROTOCOL_TCP, 1)) < 0)
4125
#endif
4126
{
4127
put_it("%s", convert_output_format("$G %gFTP%n command failed connect", NULL, NULL));
4128
new_free(&host);
4129
return;
4130
}
4131
else
4132
{
4133
DCC_int *new;
4134
add_socketread(snum, port, DCC_WAIT|DCC_FTPOPEN, host, start_ftp, NULL);
4135
new = new_malloc(sizeof(DCC_int));
4136
new->struct_type = DCC_STRUCT_TYPE;
4137
new->remport = htons(port);
4138
new->blocksize = blocksize;
4139
get_time(&new->starttime);
4140
get_time(&new->lasttime);
4141
malloc_strcpy(&new->userhost, user);
4142
new->encrypt = pass; /* these are not a mem leak */
4143
new->user = host; /* free'd in handle_ftp() */
4144
malloc_strcpy(&new->filename, "ftpopen");
4145
new->othername = dir;
4146
4147
set_socketinfo(snum, new);
4148
4149
}
4150
t_host = alloca(strlen(host)+4);
4151
strcpy(t_host, "-");
4152
strcat(t_host, host);
4153
addtabkey(t_host, "msg", 0);
4154
return;
4155
}
4156
4157
4158
void dcc_rename(char *command, char *args)
4159
{
4160
DCC_List *tmp;
4161
DCC_int *n;
4162
char *nick,
4163
*filename;
4164
4165
nick = next_arg(args, &args);
4166
filename = new_next_arg(args, &args);
4167
if (!nick || !filename || !*filename)
4168
{
4169
put_it("%s", convert_output_format("$G /DCC rename nick filename", NULL, NULL));
4170
return;
4171
}
4172
for (tmp = pending_dcc; tmp; tmp = tmp->next)
4173
{
4174
if (my_stricmp(tmp->nick, nick))
4175
continue;
4176
n = (DCC_int *)tmp->sock.info;
4177
malloc_strcpy(&n->filename, filename);
4178
break;
4179
}
4180
}
4181
4182
int check_dcc_init(char *type, char *nick, char *uhost, char *description, char *size, char *extra, unsigned long TempLong, unsigned int TempInt)
4183
{
4184
int i;
4185
for (i = 0; dcc_types[i]->name; i++)
4186
{
4187
if (!my_stricmp(type, dcc_types[i]->name))
4188
break;
4189
}
4190
if (!dcc_types[i]->name)
4191
return 0;
4192
if (dcc_types[i]->init_func)
4193
return (*dcc_types[i]->init_func)(type, nick, uhost, description, size, extra, TempLong, TempInt);
4194
return 0;
4195
}
4196
4197
int BX_add_dcc_bind(char *name, char *module, void *init_func, void *open_func, void *input, void *output, void *close_func)
4198
{
4199
int i;
4200
for (i = 0; dcc_types[i]->name; i++)
4201
{
4202
if (!my_stricmp(dcc_types[i]->name, name))
4203
break;
4204
}
4205
if (i >= 0xfe) return 0;
4206
if (!dcc_types[i])
4207
{
4208
RESIZE(dcc_types, struct _dcc_types_ *, i + 2);
4209
dcc_types[i] = new_malloc(sizeof(struct _dcc_types_));
4210
}
4211
if (!dcc_types[i]->name)
4212
malloc_strcpy(&dcc_types[i]->name, name);
4213
malloc_strcpy(&dcc_types[i]->module, module);
4214
dcc_types[i]->init_func = init_func;
4215
dcc_types[i]->open_func = open_func;
4216
dcc_types[i]->input = input;
4217
dcc_types[i]->output = output;
4218
dcc_types[i]->close_func = close_func;
4219
dcc_types[i]->type = i;
4220
return i;
4221
}
4222
4223
int BX_remove_dcc_bind(char *name, int type)
4224
{
4225
int i = type & DCC_TYPES;
4226
if (!dcc_types[i]->module)
4227
return 0;
4228
dcc_types[i]->init_func = NULL;
4229
dcc_types[i]->open_func = NULL;
4230
dcc_types[i]->input = NULL;
4231
dcc_types[i]->output = NULL;
4232
dcc_types[i]->close_func = NULL;
4233
new_free(&dcc_types[i]->module);
4234
if (i > DCC_FTPSEND)
4235
{
4236
new_free(&dcc_types[i]->name);
4237
new_free(&dcc_types[i]);
4238
/* RESIZE(dcc_types, struct _dcc_types *, i - 1);*/
4239
}
4240
return 1;
4241
}
4242
4243
int BX_remove_all_dcc_binds(char *name)
4244
{
4245
int ret = 0;
4246
int i, j;
4247
/* scan to end of list */
4248
for (i = 0; dcc_types[i]->name; i++);
4249
i--;
4250
for (j = i; j > 0; j--)
4251
ret += remove_dcc_bind(dcc_types[j]->name, dcc_types[j]->type);
4252
return ret;
4253
}
4254
4255
void init_dcc_table(void)
4256
{
4257
int i;
4258
for (i = 0; _dcc_types[i].name; i++);
4259
RESIZE(dcc_types, struct _dcc_types_ *, i + 1);
4260
for (i = 0; _dcc_types[i].name; i++)
4261
{
4262
dcc_types[i] = new_malloc(sizeof(struct _dcc_types_));
4263
dcc_types[i]->name = m_strdup(_dcc_types[i].name);
4264
dcc_types[i]->type = _dcc_types[i].type;
4265
}
4266
dcc_types[i] = new_malloc(sizeof(struct _dcc_types_));
4267
}
4268
4269
char *get_dcc_info(SocketList *s, DCC_int *n, int i)
4270
{
4271
char local_type[80];
4272
*local_type = 0;
4273
if (s->flags & DCC_TDCC)
4274
strcpy(local_type, "T");
4275
strcat(local_type, dcc_types[s->flags & DCC_TYPES]->name);
4276
return m_sprintf("%s %s %s %lu %lu %lu %lu %s #%d %d",
4277
local_type, s->server,
4278
s->flags & DCC_OFFER ? "Offer":
4279
s->flags & DCC_WAIT ? "Wait":
4280
s->flags & DCC_ACTIVE? "Active":"Unknown",
4281
n->starttime.tv_sec, n->transfer_orders.byteoffset,
4282
n->bytes_sent, n->bytes_read, n->filename, i,
4283
n->server);
4284
}
4285
4286
void dcc_raw_transmit (char *user, char *text, char *type)
4287
{
4288
return;
4289
}
4290
4291
#if 0
4292
/*
4293
* Usage: $listen(<port>)
4294
*/
4295
char *dcc_raw_listen (unsigned short port)
4296
{
4297
DCC_list *Client;
4298
char *PortName;
4299
4300
set_display_target(NULL, LOG_DCC);
4301
4302
if (port && port < 1025)
4303
{
4304
say("May not bind to a privileged port");
4305
set_display_target(NULL, LOG_CURRENT);
4306
return NULL;
4307
}
4308
PortName = ltoa(port);
4309
Client = dcc_searchlist("raw_listen", PortName,
4310
DCC_RAW_LISTEN, 1, NULL, -1);
4311
4312
if (Client->flags & DCC_ACTIVE)
4313
{
4314
say("A previous DCC RAW_LISTEN on %s exists", PortName);
4315
set_display_target(NULL, LOG_CURRENT);
4316
return NULL;
4317
}
4318
4319
if ((Client->read = connect_by_number(NULL, &port, SERVICE_SERVER, PROTOCOL_TCP)) < 0)
4320
{
4321
say("Couldnt establish listening socket: [%d] %s", Client->read, strerror(errno));
4322
Client->flags |= DCC_DELETE;
4323
set_display_target(NULL, LOG_CURRENT);
4324
return NULL;
4325
}
4326
4327
new_open(Client->read);
4328
get_time(&Client->starttime);
4329
Client->local_port = port;
4330
Client->flags |= DCC_ACTIVE;
4331
Client->user = m_strdup(ltoa(Client->local_port));
4332
set_display_target(NULL, LOG_CURRENT);
4333
4334
return m_strdup(Client->user);
4335
}
4336
4337
4338
/*
4339
* Usage: $connect(<hostname> <portnum>)
4340
*/
4341
char *dcc_raw_connect(char *host, u_short port)
4342
{
4343
DCC_list *Client;
4344
char *PortName;
4345
struct in_addr address;
4346
struct hostent *hp;
4347
4348
set_display_target(NULL, LOG_DCC);
4349
if ((address.s_addr = inet_addr(host)) == (unsigned) -1)
4350
{
4351
if (!(hp = gethostbyname(host)))
4352
{
4353
say("Unknown host: %s", host);
4354
set_display_target(NULL, LOG_CURRENT);
4355
return m_strdup(empty_string);
4356
}
4357
memmove(&address, hp->h_addr, sizeof(address));
4358
}
4359
Client = dcc_searchlist(host, ltoa(port), DCC_RAW, 1, NULL, -1);
4360
if (Client->flags & DCC_ACTIVE)
4361
{
4362
say("A previous DCC RAW to %s on %s exists", host, ltoa(port));
4363
set_display_target(NULL, LOG_CURRENT);
4364
return m_strdup(empty_string);
4365
}
4366
4367
/* Sorry. The missing 'htons' call here broke $connect() */
4368
Client->remport = htons(port);
4369
memmove((char *)&Client->remote, (char *)&address, sizeof(address));
4370
Client->flags = DCC_THEIR_OFFER | DCC_RAW;
4371
if (!dcc_open(Client))
4372
{
4373
set_display_target(NULL, LOG_CURRENT);
4374
return m_strdup(empty_string);
4375
}
4376
4377
PortName = ltoa(Client->read);
4378
Client->user = m_strdup(PortName);
4379
if (do_hook(DCC_RAW_LIST, "%s %s E %d", PortName, host, port))
4380
if (do_hook(DCC_CONNECT_LIST,"%s RAW %s %d",PortName, host, port))
4381
say("DCC RAW connection to %s on %s via %d established", host, PortName, port);
4382
4383
set_display_target(NULL, LOG_CURRENT);
4384
return m_strdup(PortName);
4385
}
4386
#endif
4387
4388
char *dcc_raw_connect(char *host, u_short port)
4389
{
4390
return m_strdup("-1");
4391
}
4392
4393
char *dcc_raw_listen(int port)
4394
{
4395
#if 0
4396
SocketList *Client;
4397
char *PortName;
4398
4399
set_display_target(NULL, LOG_DCC);
4400
4401
if (port && port < 1025)
4402
{
4403
say("May not bind to a privileged port");
4404
set_display_target(NULL, LOG_CURRENT);
4405
return NULL;
4406
}
4407
4408
PortName = ltoa(port);
4409
Client = find_dcc(PortName, NULL, "raw_listen", DCC_RAW_LISTEN, 1, 0, -1);
4410
Client = dcc_searchlist("raw_listen", PortName,
4411
DCC_RAW_LISTEN, 1, NULL, -1);
4412
4413
if (Client->flags & DCC_ACTIVE)
4414
{
4415
say("A previous DCC RAW_LISTEN on %s exists", PortName);
4416
set_display_target(NULL, LOG_CURRENT);
4417
return NULL;
4418
}
4419
4420
if ((Client->read = connect_by_number(NULL, &port, SERVICE_SERVER, PROTOCOL_TCP)) < 0)
4421
{
4422
say("Couldnt establish listening socket: [%d] %s", Client->read, strerror(errno));
4423
Client->flags |= DCC_DELETE;
4424
set_display_target(NULL, LOG_CURRENT);
4425
return NULL;
4426
}
4427
4428
new_open(Client->read);
4429
get_time(&Client->starttime);
4430
Client->local_port = port;
4431
Client->flags |= DCC_ACTIVE;
4432
Client->user = m_strdup(ltoa(Client->local_port));
4433
set_display_target(NULL, LOG_CURRENT);
4434
4435
return m_strdup(Client->user);
4436
#endif
4437
return m_strdup("-1");
4438
}
4439
4440
4441
4442
int close_dcc_number(int number)
4443
{
4444
if (!check_dcc_socket(number))
4445
return 0;
4446
erase_dcc_info(number, 1, NULL);
4447
close_socketread(number);
4448
return 1;
4449
}
4450
4451