00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef lint
00026 static const char rcsid[] = "$Id: filesys.c,v 1.24 2003-12-11 00:49:10 wcc Exp $";
00027 #endif
00028
00029 #include <fcntl.h>
00030 #include <sys/stat.h>
00031 #define MODULE_NAME "filesys"
00032 #define MAKING_FILESYS
00033 #ifdef HAVE_CONFIG_H
00034 # include "config.h"
00035 #endif
00036 #include <sys/file.h>
00037 #if HAVE_DIRENT_H
00038 # include <dirent.h>
00039 # define NAMLEN(dirent) strlen((dirent)->d_name)
00040 #else
00041 # define dirent direct
00042 # define NAMLEN(dirent) (dirent)->d_namlen
00043 # if HAVE_SYS_NDIR_H
00044 # include <sys/ndir.h>
00045 # endif
00046 # if HAVE_SYS_DIR_H
00047 # include <sys/dir.h>
00048 # endif
00049 # if HAVE_NDIR_H
00050 # include <ndir.h>
00051 # endif
00052 #endif
00053 #include "lib/eggdrop/module.h"
00054 #include "filedb3.h"
00055 #include "filesys.h"
00056 #include "src/tandem.h"
00057 #include "files.h"
00058 #include "dbcompat.h"
00059 #include "filelist.h"
00060
00061 #define start filesys_LTX_start
00062
00063 static bind_table_t *BT_file;
00064 static Function *transfer_funcs = NULL;
00065
00066 static eggdrop_t *egg = NULL;
00067
00068
00069 static char dccdir[121] = "";
00070
00071
00072 static char dccin[121] = "";
00073
00074
00075 static int upload_to_cd = 0;
00076
00077
00078
00079
00080 static int dcc_maxsize = 1024;
00081
00082
00083 static int dcc_users = 0;
00084
00085
00086
00087
00088 static char filedb_path[121] = "";
00089
00090 static struct dcc_table DCC_FILES =
00091 {
00092 "FILES",
00093 DCT_MASTER | DCT_VALIDIDX | DCT_SHOWWHO | DCT_SIMUL | DCT_CANBOOT | DCT_FILES,
00094 eof_dcc_files,
00095 dcc_files,
00096 NULL,
00097 NULL,
00098 disp_dcc_files,
00099 kill_dcc_files,
00100 out_dcc_files
00101 };
00102
00103 static struct dcc_table DCC_GET =
00104 {
00105 "GET",
00106 DCT_FILETRAN | DCT_VALIDIDX,
00107 eof_dcc_get,
00108 dcc_get,
00109 &wait_dcc_xfer,
00110 transfer_get_timeout,
00111 display_dcc_get,
00112 kill_dcc_xfer,
00113 out_dcc_xfer,
00114 outdone_dcc_xfer
00115 };
00116
00117 static struct dcc_table DCC_FORK_SEND =
00118 {
00119 "FORK_SEND",
00120 DCT_FILETRAN | DCT_FORKTYPE | DCT_FILESEND | DCT_VALIDIDX,
00121 eof_dcc_fork_send,
00122 dcc_fork_send,
00123 &wait_dcc_xfer,
00124 eof_dcc_fork_send,
00125 display_dcc_fork_send,
00126 kill_dcc_xfer,
00127 out_dcc_xfer
00128 };
00129
00130 static struct dcc_table DCC_GET_PENDING =
00131 {
00132 "GET_PENDING",
00133 DCT_FILETRAN | DCT_VALIDIDX,
00134 eof_dcc_get,
00135 dcc_get_pending,
00136 &wait_dcc_xfer,
00137 transfer_get_timeout,
00138 display_dcc_get_p,
00139 kill_dcc_xfer,
00140 out_dcc_xfer
00141 };
00142
00143 static struct dcc_table DCC_SEND =
00144 {
00145 "SEND",
00146 DCT_FILETRAN | DCT_FILESEND | DCT_VALIDIDX,
00147 eof_dcc_send,
00148 dcc_send,
00149 &wait_dcc_xfer,
00150 tout_dcc_send,
00151 display_dcc_send,
00152 kill_dcc_xfer,
00153 out_dcc_xfer
00154 };
00155
00156 static struct user_entry_type USERENTRY_DCCDIR =
00157 {
00158 NULL,
00159 NULL,
00160 NULL,
00161 NULL,
00162 NULL,
00163 NULL,
00164 NULL,
00165 NULL,
00166 NULL,
00167 NULL,
00168 NULL,
00169 NULL,
00170 "DCCDIR"
00171 };
00172
00173 static struct user_entry_type USERENTRY_FSTAT =
00174 {
00175 NULL,
00176 fstat_gotshare,
00177 fstat_dupuser,
00178 fstat_unpack,
00179 fstat_pack,
00180 fstat_write_userfile,
00181 fstat_kill,
00182 NULL,
00183 fstat_set,
00184 fstat_tcl_get,
00185 fstat_tcl_set,
00186 fstat_display,
00187 "FSTAT"
00188 };
00189
00190 #include "files.c"
00191 #include "filedb3.c"
00192 #include "tclfiles.c"
00193 #include "dbcompat.c"
00194 #include "filelist.c"
00195
00196
00197
00198
00199 static int check_tcl_fil(char *cmd, int idx, char *text)
00200 {
00201 struct flag_record fr = {FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0};
00202 int x;
00203
00204 get_user_flagrec(dcc[idx].user, &fr, dcc[idx].u.file->chat->con_chan);
00205 x = check_bind(BT_file, cmd, &fr, dcc[idx].nick, dcc[idx].sock, text);
00206 if (x & BIND_RET_LOG) {
00207 putlog(LOG_FILES, "*", "#%s# files: %s %s", dcc[idx].nick, cmd, text);
00208 }
00209 return 0;
00210 }
00211
00212 static int at_limit(char *nick)
00213 {
00214 int i, x = 0;
00215
00216 for (i = 0; i < dcc_total; i++)
00217 if (dcc[i].type == &DCC_GET || dcc[i].type == &DCC_GET_PENDING)
00218 if (!strcasecmp(dcc[i].nick, nick))
00219 x++;
00220 return (x >= dcc_limit);
00221 }
00222
00223 static void wipe_tmp_filename(char *fn, int idx)
00224 {
00225 int i, ok = 1;
00226
00227 if (!copy_to_tmp)
00228 return;
00229
00230 for (i = 0; i < dcc_total; i++) {
00231 if ((i != idx) &&
00232 (dcc[i].type == &DCC_GET || dcc[i].type == &DCC_GET_PENDING) &&
00233 (!strcmp(dcc[i].u.xfer->filename, fn))) {
00234 ok = 0;
00235 break;
00236 }
00237 }
00238 if (ok)
00239 unlink(fn);
00240 }
00241
00242 static void queue_file(char *dir, char *file, char *from, char *to)
00243 {
00244 fileq_t *q = fileq;
00245
00246 fileq = (fileq_t *) malloc(sizeof(fileq_t));
00247 fileq->next = q;
00248 fileq->dir = strdup(dir);
00249 fileq->file = strdup(file);
00250 strcpy(fileq->nick, from);
00251 strcpy(fileq->to, to);
00252 }
00253
00254
00255
00256
00257
00258
00259
00260 static int raw_dcc_resend_send(char *filename, char *nick, char *from,
00261 char *dir, int resend, char *addr)
00262 {
00263 int zz, port, i;
00264 char *nfn, *buf = NULL;
00265 long dccfilesize;
00266 FILE *f, *dccfile;
00267
00268 putlog(LOG_DEBUG, "*", "|FILESYS| raw_dcc_resend_send(... addr=\"%s\")",
00269 addr);
00270 zz = -1;
00271 dccfile = fopen(filename,"r");
00272 fseek(dccfile, 0, SEEK_END);
00273 dccfilesize = ftell(dccfile);
00274 fclose(dccfile);
00275
00276 if (dccfilesize == 0)
00277 return DCCSEND_FEMPTY;
00278 if (reserved_port_min > 0 && reserved_port_min < reserved_port_max) {
00279 for (port = reserved_port_min; port <= reserved_port_max; port++) {
00280 if (addr && addr[0])
00281 zz = open_address_listen(addr, &port);
00282 else {
00283 zz = open_listen(&port, AF_INET);
00284 addr = getlocaladdr(-1);
00285 }
00286 if (zz != -1)
00287 break;
00288 }
00289 } else {
00290 port = reserved_port_min;
00291 if (addr && addr[0])
00292 zz = open_address_listen(addr, &port);
00293 else {
00294 zz = open_listen(&port, AF_INET);
00295 addr = getlocaladdr(-1);
00296 }
00297 }
00298
00299 if (zz == -1)
00300 return DCCSEND_NOSOCK;
00301
00302 nfn = strrchr(dir, '/');
00303 if (nfn == NULL)
00304 nfn = dir;
00305 else
00306 nfn++;
00307 f = fopen(filename, "r");
00308
00309 if (!f)
00310 return DCCSEND_BADFN;
00311
00312 if ((i = new_dcc(&DCC_GET_PENDING, sizeof(struct xfer_info))) == -1)
00313 return DCCSEND_FULL;
00314
00315 dcc[i].sock = zz;
00316 strcpy(dcc[i].addr, "222.173.240.13");
00317 dcc[i].port = port;
00318 strcpy(dcc[i].nick, nick);
00319 strcpy(dcc[i].host, "irc");
00320 dcc[i].u.xfer->filename = calloc(1, strlen(filename) + 1);
00321 strcpy(dcc[i].u.xfer->filename, filename);
00322 if (strchr(nfn, ' '))
00323 nfn = buf = replace_spaces(nfn);
00324 dcc[i].u.xfer->origname = calloc(1, strlen(nfn) + 1);
00325 strcpy(dcc[i].u.xfer->origname, nfn);
00326 strlcpy(dcc[i].u.xfer->from, from, sizeof dcc[i].u.xfer->from);
00327 strlcpy(dcc[i].u.xfer->dir, dir, sizeof dcc[i].u.xfer->dir);
00328 dcc[i].u.xfer->length = dccfilesize;
00329 dcc[i].timeval = now;
00330 dcc[i].u.xfer->f = f;
00331 dcc[i].u.xfer->type = resend ? XFER_RESEND_PEND : XFER_SEND;
00332 if (nick[0] != '*') {
00333 dprintf(DP_HELP, "PRIVMSG %s :\001DCC %sSEND %s %s %d %lu\001\n", nick,
00334 resend ? "RE" : "", nfn, addr,
00335 port, dccfilesize);
00336 putlog(LOG_FILES, "*", "Begin DCC %ssend %s to %s", resend ? "re" : "",
00337 nfn, nick);
00338 }
00339 if (buf)
00340 free(buf);
00341 return DCCSEND_OK;
00342 }
00343
00344 static int raw_dcc_resend(char *filename, char *nick, char *from,
00345 char *dir, char *addr)
00346 {
00347 return raw_dcc_resend_send(filename, nick, from, dir, 1, addr);
00348 }
00349
00350 static int raw_dcc_send(char *filename, char *nick, char *from,
00351 char *dir, char *addr)
00352 {
00353 return raw_dcc_resend_send(filename, nick, from, dir, 0, addr);
00354 }
00355
00356 static int fstat_unpack(struct userrec *u, struct user_entry *e)
00357 {
00358 char *par, *arg;
00359 struct filesys_stats *fs;
00360
00361 fs = calloc(1, sizeof(struct filesys_stats));
00362 par = e->u.list->extra;
00363 arg = newsplit(&par);
00364 if (arg[0])
00365 fs->uploads = atoi(arg);
00366 arg = newsplit(&par);
00367 if (arg[0])
00368 fs->upload_ks = atoi(arg);
00369 arg = newsplit(&par);
00370 if (arg[0])
00371 fs->dnloads = atoi(arg);
00372 arg = newsplit(&par);
00373 if (arg[0])
00374 fs->dnload_ks = atoi(arg);
00375
00376 list_type_kill(e->u.list);
00377 e->u.extra = fs;
00378 return 1;
00379 }
00380
00381 static int fstat_pack(struct userrec *u, struct user_entry *e)
00382 {
00383 struct filesys_stats *fs;
00384 struct list_type *l = malloc(sizeof(struct list_type));
00385
00386 fs = e->u.extra;
00387 l->extra = malloc(41);
00388 snprintf(l->extra, 41, "%09u %09u %09u %09u",
00389 fs->uploads, fs->upload_ks, fs->dnloads, fs->dnload_ks);
00390 l->next = NULL;
00391 e->u.list = l;
00392 free(fs);
00393 return 1;
00394 }
00395
00396 static int fstat_write_userfile(FILE *f, struct userrec *u,
00397 struct user_entry *e)
00398 {
00399 struct filesys_stats *fs;
00400
00401 fs = e->u.extra;
00402 if (fprintf(f, "--FSTAT %09u %09u %09u %09u\n",
00403 fs->uploads, fs->upload_ks,
00404 fs->dnloads, fs->dnload_ks) == EOF)
00405 return 0;
00406 return 1;
00407 }
00408
00409 static int fstat_set(struct userrec *u, struct user_entry *e, void *buf)
00410 {
00411 struct filesys_stats *fs = buf;
00412
00413 if (e->u.extra != fs) {
00414 if (e->u.extra)
00415 free(e->u.extra);
00416 e->u.extra = fs;
00417 } else if (!fs)
00418 return 1;
00419 return 1;
00420 }
00421
00422 static int fstat_tcl_get(Tcl_Interp *irp, struct userrec *u,
00423 struct user_entry *e, int argc, char **argv)
00424 {
00425 struct filesys_stats *fs;
00426 char d[50];
00427
00428 BADARGS(3, 4, " handle FSTAT ?u/d?");
00429 fs = e->u.extra;
00430 if (argc == 3)
00431 snprintf(d, sizeof d, "%u %u %u %u", fs->uploads, fs->upload_ks,
00432 fs->dnloads, fs->dnload_ks);
00433 else
00434 switch (argv[3][0]) {
00435 case 'u':
00436 snprintf(d, sizeof d, "%u %u", fs->uploads, fs->upload_ks);
00437 break;
00438 case 'd':
00439 snprintf(d, sizeof d, "%u %u", fs->dnloads, fs->dnload_ks);
00440 break;
00441 }
00442
00443 Tcl_AppendResult(irp, d, NULL);
00444 return TCL_OK;
00445 }
00446
00447 static int fstat_kill(struct user_entry *e)
00448 {
00449 if (e->u.extra)
00450 free(e->u.extra);
00451 free(e);
00452 return 1;
00453 }
00454
00455 static void fstat_display(int idx, struct user_entry *e)
00456 {
00457 struct filesys_stats *fs;
00458
00459 fs = e->u.extra;
00460 dprintf(idx, " FILES: %u download%s (%luk), %u upload%s (%luk)\n",
00461 fs->dnloads, (fs->dnloads == 1) ? "" : "s", fs->dnload_ks,
00462 fs->uploads, (fs->uploads == 1) ? "" : "s", fs->upload_ks);
00463 }
00464
00465 static int fstat_gotshare(struct userrec *u, struct user_entry *e,
00466 char *par, int idx)
00467 {
00468 return 0;
00469 }
00470
00471 static int fstat_dupuser(struct userrec *u, struct userrec *o,
00472 struct user_entry *e)
00473 {
00474 struct filesys_stats *fs;
00475
00476 if (e->u.extra) {
00477 fs = malloc(sizeof(struct filesys_stats));
00478 memcpy(fs, e->u.extra, sizeof(struct filesys_stats));
00479 return set_user(&USERENTRY_FSTAT, u, fs);
00480 }
00481 return 0;
00482 }
00483
00484 static void stats_add_dnload(struct userrec *u, unsigned long bytes)
00485 {
00486 struct user_entry *ue;
00487 struct filesys_stats *fs;
00488
00489 if (u) {
00490 if (!(ue = find_user_entry(&USERENTRY_FSTAT, u)) ||
00491 !(fs = ue->u.extra))
00492 fs = calloc(1, sizeof(struct filesys_stats));
00493 fs->dnloads++;
00494 fs->dnload_ks += ((bytes + 512) / 1024);
00495 set_user(&USERENTRY_FSTAT, u, fs);
00496 }
00497 }
00498
00499 static void stats_add_upload(struct userrec *u, unsigned long bytes)
00500 {
00501 struct user_entry *ue;
00502 struct filesys_stats *fs;
00503
00504 if (u) {
00505 if (!(ue = find_user_entry(&USERENTRY_FSTAT, u)) ||
00506 !(fs = ue->u.extra))
00507 fs = calloc(1, sizeof(struct filesys_stats));
00508 fs->uploads++;
00509 fs->upload_ks += ((bytes + 512) / 1024);
00510 set_user(&USERENTRY_FSTAT, u, fs);
00511 }
00512 }
00513
00514 static int fstat_tcl_set(Tcl_Interp *irp, struct userrec *u,
00515 struct user_entry *e, int argc, char **argv)
00516 {
00517 struct filesys_stats *fs;
00518 int f = 0, k = 0;
00519
00520 BADARGS(4, 6, " handle FSTAT u/d ?files ?ks??");
00521 if (argc > 4)
00522 f = atoi(argv[4]);
00523 if (argc > 5)
00524 k = atoi(argv[5]);
00525 switch (argv[3][0]) {
00526 case 'u':
00527 case 'd':
00528 if (!(fs = e->u.extra))
00529 fs = calloc(1, sizeof(struct filesys_stats));
00530 switch (argv[3][0]) {
00531 case 'u':
00532 fs->uploads = f;
00533 fs->upload_ks = k;
00534 break;
00535 case 'd':
00536 fs->dnloads = f;
00537 fs->dnload_ks = k;
00538 break;
00539 }
00540 set_user(&USERENTRY_FSTAT, u, fs);
00541 break;
00542 case 'r':
00543 set_user(&USERENTRY_FSTAT, u, NULL);
00544 break;
00545 }
00546 return TCL_OK;
00547 }
00548
00549 static void dcc_files_pass(int idx, char *buf, int x)
00550 {
00551 struct userrec *u = get_user_by_handle(userlist, dcc[idx].nick);
00552
00553 if (!x)
00554 return;
00555 if (u_pass_match(u, buf)) {
00556 if (too_many_filers()) {
00557 dprintf(idx, _("Too many people are in the file system right now.\n"));
00558 dprintf(idx, _("Please try again later.\n"));
00559 putlog(LOG_MISC, "*", "File area full: DCC chat [%s]%s", dcc[idx].nick,
00560 dcc[idx].host);
00561 killsock(dcc[idx].sock);
00562 lostdcc(idx);
00563 return;
00564 }
00565 dcc[idx].type = &DCC_FILES;
00566 if (dcc[idx].status & STAT_TELNET)
00567 dprintf(idx, "\377\374\001\n");
00568 putlog(LOG_FILES, "*", "File system: [%s]%s/%d", dcc[idx].nick,
00569 dcc[idx].host, dcc[idx].port);
00570 if (!welcome_to_files(idx)) {
00571 putlog(LOG_FILES, "*", _("File system broken."));
00572 killsock(dcc[idx].sock);
00573 lostdcc(idx);
00574 } else {
00575 struct userrec *u = get_user_by_handle(userlist, dcc[idx].nick);
00576
00577 touch_laston(u, "filearea", now);
00578 }
00579 return;
00580 }
00581 dprintf(idx, _("Negative on that, Houston.\n"));
00582 putlog(LOG_MISC, "*", "Bad password: DCC chat [%s]%s", dcc[idx].nick,
00583 dcc[idx].host);
00584 killsock(dcc[idx].sock);
00585 lostdcc(idx);
00586 }
00587
00588
00589
00590 static int got_files_cmd(int idx, char *msg)
00591 {
00592 char *code;
00593
00594 strcpy(msg, check_bind_filt(idx, msg));
00595 if (!msg[0])
00596 return 1;
00597 if (msg[0] == '.')
00598 msg++;
00599 code = newsplit(&msg);
00600 return check_tcl_fil(code, idx, msg);
00601 }
00602
00603 static void dcc_files(int idx, char *buf, int i)
00604 {
00605 if (buf[0] &&
00606 detect_dcc_flood(&dcc[idx].timeval, dcc[idx].u.file->chat, idx))
00607 return;
00608 dcc[idx].timeval = now;
00609 strcpy(buf, check_bind_filt(idx, buf));
00610 if (!buf[0])
00611 return;
00612 touch_laston(dcc[idx].user, "filearea", now);
00613 if (buf[0] == ',') {
00614 for (i = 0; i < dcc_total; i++) {
00615 if ((dcc[i].type->flags & DCT_MASTER) && dcc[idx].user &&
00616 (dcc[idx].user->flags & USER_MASTER) &&
00617 ((dcc[i].type == &DCC_FILES) ||
00618 (dcc[i].u.chat->channel >= 0)) &&
00619 ((i != idx) || (dcc[idx].status & STAT_ECHO)))
00620 dprintf(i, "-%s- %s\n", dcc[idx].nick, &buf[1]);
00621 }
00622 } else if (got_files_cmd(idx, buf)) {
00623 dprintf(idx, "*** Ja mata!\n");
00624 flush_lines(idx, dcc[idx].u.file->chat);
00625 putlog(LOG_FILES, "*", "DCC user [%s]%s left file system", dcc[idx].nick,
00626 dcc[idx].host);
00627 set_user(&USERENTRY_DCCDIR, dcc[idx].user, dcc[idx].u.file->dir);
00628 if (dcc[idx].status & STAT_CHAT) {
00629 struct chat_info *ci;
00630
00631 dprintf(idx, _("Returning you to command mode...\n"));
00632 ci = dcc[idx].u.file->chat;
00633 free_null(dcc[idx].u.file);
00634 dcc[idx].u.chat = ci;
00635 dcc[idx].status &= (~STAT_CHAT);
00636 dcc[idx].type = &DCC_CHAT;
00637 if (dcc[idx].u.chat->channel >= 0) {
00638 chanout_but(-1, dcc[idx].u.chat->channel,
00639 "*** %s has returned.\n", dcc[idx].nick);
00640 if (dcc[idx].u.chat->channel < 100000)
00641 botnet_send_join_idx(idx, -1);
00642 }
00643 } else {
00644 dprintf(idx, _("Dropping connection now.\n"));
00645 putlog(LOG_FILES, "*", "Left files: [%s]%s/%d", dcc[idx].nick,
00646 dcc[idx].host, dcc[idx].port);
00647 killsock(dcc[idx].sock);
00648 lostdcc(idx);
00649 }
00650 }
00651 if (dcc[idx].status & STAT_PAGE)
00652 flush_lines(idx, dcc[idx].u.file->chat);
00653 }
00654
00655 static void my_tell_file_stats(int idx, char *hand)
00656 {
00657 struct userrec *u;
00658 struct filesys_stats *fs;
00659 float fr = (-1.0), kr = (-1.0);
00660
00661 u = get_user_by_handle(userlist, hand);
00662 if (u == NULL)
00663 return;
00664 if (!(fs = get_user(&USERENTRY_FSTAT, u))) {
00665 dprintf(idx, _("No file statistics for %s.\n"), hand);
00666 } else {
00667 dprintf(idx, " uploads: %4u / %6luk\n", fs->uploads, fs->upload_ks);
00668 dprintf(idx, "downloads: %4u / %6luk\n", fs->dnloads, fs->dnload_ks);
00669 if (fs->uploads)
00670 fr = ((float) fs->dnloads / (float) fs->uploads);
00671 if (fs->upload_ks)
00672 kr = ((float) fs->dnload_ks / (float) fs->upload_ks);
00673 if (fr < 0.0)
00674 dprintf(idx, _("(infinite file leech)\n"));
00675 else
00676 dprintf(idx, "leech ratio (files): %6.2f\n", fr);
00677 if (kr < 0.0)
00678 dprintf(idx, _("(infinite size leech)\n"));
00679 else
00680 dprintf(idx, "leech ratio (size) : %6.2f\n", kr);
00681 }
00682 }
00683
00684 static int cmd_files(struct userrec *u, int idx, char *par)
00685 {
00686 int atr = u ? u->flags : 0;
00687 static struct chat_info *ci;
00688
00689 if (dccdir[0] == 0)
00690 dprintf(idx, _("There is no file transfer area.\n"));
00691 else if (too_many_filers()) {
00692 dprintf(idx,
00693 P_("The maximum of %d person is in the file area right now.\n",
00694 "The maximum of %d people are in the file area right now.\n",
00695 dcc_users), dcc_users);
00696 dprintf(idx, _("Please try again later.\n"));
00697 } else {
00698 if (!(atr & (USER_MASTER | USER_XFER)))
00699 dprintf(idx, _("You don't have access to the file area.\n"));
00700 else {
00701 putlog(LOG_CMDS, "*", "#%s# files", dcc[idx].nick);
00702 dprintf(idx, _("Entering file system...\n"));
00703 if (dcc[idx].u.chat->channel >= 0) {
00704
00705 chanout_but(-1, dcc[idx].u.chat->channel,
00706 "*** %s has left: file system\n",
00707 dcc[idx].nick);
00708 if (dcc[idx].u.chat->channel < 100000)
00709 botnet_send_part_idx(idx, "file system");
00710 }
00711 ci = dcc[idx].u.chat;
00712 dcc[idx].u.file = calloc(1, sizeof(struct file_info));
00713 dcc[idx].u.file->chat = ci;
00714 dcc[idx].type = &DCC_FILES;
00715 dcc[idx].status |= STAT_CHAT;
00716 if (!welcome_to_files(idx)) {
00717 struct chat_info *ci = dcc[idx].u.file->chat;
00718
00719 free_null(dcc[idx].u.file);
00720 dcc[idx].u.chat = ci;
00721 dcc[idx].type = &DCC_CHAT;
00722 putlog(LOG_FILES, "*", _("File system broken."));
00723 if (dcc[idx].u.chat->channel >= 0) {
00724 chanout_but(-1, dcc[idx].u.chat->channel,
00725 "*** %s has returned.\n",
00726 dcc[idx].nick);
00727 if (dcc[idx].u.chat->channel < 100000)
00728 botnet_send_join_idx(idx, -1);
00729 }
00730 } else
00731 touch_laston(u, "filearea", now);
00732 }
00733 }
00734 return 0;
00735 }
00736
00737 static int _dcc_send(int idx, char *filename, char *nick, char *dir,
00738 int resend)
00739 {
00740 int x;
00741 char *nfn, *buf = NULL;
00742
00743 if (strlen(nick) > NICKMAX)
00744 nick[NICKMAX] = 0;
00745 if (resend)
00746 x = raw_dcc_resend(filename, nick, dcc[idx].nick, dir, 0);
00747 else
00748 x = raw_dcc_send(filename, nick, dcc[idx].nick, dir, 0);
00749 if (x == DCCSEND_FULL) {
00750 dprintf(idx, _("Sorry, too many DCC connections. (try again later)\n"));
00751 putlog(LOG_FILES, "*", "DCC connections full: %sGET %s [%s]", filename,
00752 resend ? "RE" : "", dcc[idx].nick);
00753 return 0;
00754 }
00755 if (x == DCCSEND_NOSOCK) {
00756 if (reserved_port_min) {
00757 dprintf(idx, _("All my DCC SEND ports are in use. Try later.\n"));
00758 putlog(LOG_FILES, "*", "DCC port in use (can't open): %sGET %s [%s]",
00759 resend ? "RE" : "", filename, dcc[idx].nick);
00760 } else {
00761 dprintf(idx, _("Unable to listen at a socket.\n"));
00762 putlog(LOG_FILES, "*", "DCC socket error: %sGET %s [%s]", filename,
00763 resend ? "RE" : "", dcc[idx].nick);
00764 }
00765 return 0;
00766 }
00767 if (x == DCCSEND_BADFN) {
00768 dprintf(idx, _("File not found ?\n"));
00769 putlog(LOG_FILES, "*", "DCC file not found: %sGET %s [%s]", filename,
00770 resend ? "RE" : "", dcc[idx].nick);
00771 return 0;
00772 }
00773 if (x == DCCSEND_FEMPTY) {
00774 dprintf(idx, _("The file is empty. Aborted transfer.\n"));
00775 putlog(LOG_FILES, "*", "DCC file is empty: %s [%s]", filename,
00776 dcc[idx].nick);
00777 return 0;
00778 }
00779 nfn = strrchr(dir, '/');
00780 if (nfn == NULL)
00781 nfn = dir;
00782 else
00783 nfn++;
00784
00785
00786 if (strchr(nfn, ' ')) {
00787 char *p;
00788
00789 realloc_strcpy(buf, nfn);
00790 p = nfn = buf;
00791 while ((p = strchr(p, ' ')) != NULL)
00792 *p = '_';
00793 }
00794
00795 if (strcasecmp(nick, dcc[idx].nick))
00796 dprintf(DP_HELP, "NOTICE %s :Here is %s file from %s %s...\n", nick,
00797 resend ? "the" : "a", dcc[idx].nick, resend ? "again " : "");
00798 dprintf(idx, "%sending: %s to %s\n", resend ? "Res" : "S", nfn, nick);
00799 free_null(buf);
00800 return 1;
00801 }
00802
00803 static int do_dcc_send(int idx, char *dir, char *fn, char *nick, int resend)
00804 {
00805 char *s = NULL, *s1 = NULL;
00806 int x;
00807
00808 if (nick && strlen(nick) > NICKMAX)
00809 nick[NICKMAX] = 0;
00810 if (dccdir[0] == 0) {
00811 dprintf(idx, _("DCC file transfers not supported.\n"));
00812 putlog(LOG_FILES, "*", "Refused dcc %sget %s from [%s]", resend ? "re" : "",
00813 fn, dcc[idx].nick);
00814 return 0;
00815 }
00816 if (strchr(fn, '/') != NULL) {
00817 dprintf(idx, _("Filename cannot have '/' in it...\n"));
00818 putlog(LOG_FILES, "*", "Refused dcc %sget %s from [%s]", resend ? "re" : "",
00819 fn, dcc[idx].nick);
00820 return 0;
00821 }
00822 if (dir[0]) {
00823 s = malloc(strlen(dccdir) + strlen(dir) + strlen(fn) + 2);
00824 sprintf(s, "%s%s/%s", dccdir, dir, fn);
00825 } else {
00826 s = malloc(strlen(dccdir) + strlen(fn) + 1);
00827 sprintf(s, "%s%s", dccdir, fn);
00828 }
00829 if (!file_readable(s)) {
00830 dprintf(idx, "No such file.\n");
00831 putlog(LOG_FILES, "*", "Refused dcc %sget %s from [%s]", resend ? "re" : "",
00832 fn, dcc[idx].nick);
00833 free_null(s);
00834 return 0;
00835 }
00836 if (!nick || !nick[0])
00837 nick = dcc[idx].nick;
00838
00839 if (at_limit(nick)) {
00840 char xxx[1024];
00841
00842 sprintf(xxx, "%d*%s%s", strlen(dccdir), dccdir, dir);
00843 queue_file(xxx, fn, dcc[idx].nick, nick);
00844 dprintf(idx, "Queued: %s to %s\n", fn, nick);
00845 free_null(s);
00846 return 1;
00847 }
00848 if (copy_to_tmp) {
00849 char *tempfn = mktempfile(fn);
00850
00851
00852 s = realloc(s, strlen(dccdir) + strlen(dir) + strlen(fn) + 2);
00853 sprintf(s, "%s%s%s%s", dccdir, dir, dir[0] ? "/" : "", fn);
00854 s1 = realloc(s1, strlen(tempdir) + strlen(tempfn) + 1);
00855 sprintf(s1, "%s%s", tempdir, tempfn);
00856 free_null(tempfn);
00857 if (copyfile(s, s1) != 0) {
00858 dprintf(idx, _("Can't make temporary copy of file!\n"));
00859 putlog(LOG_FILES | LOG_MISC, "*",
00860 "Refused dcc %sget %s: copy to %s FAILED!",
00861 resend ? "re" : "", fn, tempdir);
00862 free_null(s);
00863 free_null(s1);
00864 return 0;
00865 }
00866 } else {
00867 s1 = realloc(s1, strlen(dccdir) + strlen(dir) + strlen(fn) + 2);
00868 sprintf(s1, "%s%s%s%s", dccdir, dir, dir[0] ? "/" : "", fn);
00869 }
00870 s = realloc(s, strlen(dir) + strlen(fn) + 2);
00871 sprintf(s, "%s%s%s", dir, dir[0] ? "/" : "", fn);
00872 x = _dcc_send(idx, s1, nick, s, resend);
00873 if (x != DCCSEND_OK)
00874 wipe_tmp_filename(s1, -1);
00875 free_null(s);
00876 free_null(s1);
00877 return x;
00878 }
00879
00880 static void tout_dcc_files_pass(int i)
00881 {
00882 dprintf(i, _("Timeout.\n"));
00883 putlog(LOG_MISC, "*", "Password timeout on dcc chat: [%s]%s", dcc[i].nick,
00884 dcc[i].host);
00885 killsock(dcc[i].sock);
00886 lostdcc(i);
00887 }
00888
00889 static void disp_dcc_files(int idx, char *buf)
00890 {
00891 sprintf(buf, "file flags: %c%c%c%c%c",
00892 dcc[idx].status & STAT_CHAT ? 'C' : 'c',
00893 dcc[idx].status & STAT_PARTY ? 'P' : 'p',
00894 dcc[idx].status & STAT_TELNET ? 'T' : 't',
00895 dcc[idx].status & STAT_ECHO ? 'E' : 'e',
00896 dcc[idx].status & STAT_PAGE ? 'P' : 'p');
00897 }
00898
00899 static void disp_dcc_files_pass(int idx, char *buf)
00900 {
00901 sprintf(buf, "fpas waited %lus", now - dcc[idx].timeval);
00902 }
00903
00904 static void kill_dcc_files(int idx, void *x)
00905 {
00906 register struct file_info *f = (struct file_info *) x;
00907
00908 if (f->chat)
00909 DCC_CHAT.kill(idx, f->chat);
00910 free_null(x);
00911 }
00912
00913 static void eof_dcc_files(int idx)
00914 {
00915 dcc[idx].u.file->chat->con_flags = 0;
00916 putlog(LOG_MISC, "*", "Lost dcc connection to %s (%s/%d)", dcc[idx].nick,
00917 dcc[idx].host, dcc[idx].port);
00918 killsock(dcc[idx].sock);
00919 lostdcc(idx);
00920 }
00921
00922 static void out_dcc_files(int idx, char *buf, void *x)
00923 {
00924 register struct file_info *p = (struct file_info *) x;
00925
00926 if (p->chat)
00927 DCC_CHAT.output(idx, buf, p->chat);
00928 else
00929 tputs(dcc[idx].sock, buf, strlen(buf));
00930 }
00931
00932 static cmd_t mydcc[] =
00933 {
00934 {"files", "-", cmd_files, NULL},
00935 {NULL, NULL, NULL, NULL}
00936 };
00937
00938 static tcl_strings mystrings[] =
00939 {
00940 {"files_path", dccdir, 120, STR_DIR | STR_PROTECT},
00941 {"incoming_path", dccin, 120, STR_DIR | STR_PROTECT},
00942 {"filedb_path", filedb_path, 120, STR_DIR | STR_PROTECT},
00943 {NULL, NULL, 0, 0}
00944 };
00945
00946 static tcl_ints myints[] =
00947 {
00948 {"max_filesize", &dcc_maxsize},
00949 {"max_file_users", &dcc_users},
00950 {"upload_to_pwd", &upload_to_cd},
00951 {NULL, NULL}
00952 };
00953
00954 static struct dcc_table DCC_FILES_PASS =
00955 {
00956 "FILES_PASS",
00957 0,
00958 eof_dcc_files,
00959 dcc_files_pass,
00960 NULL,
00961 tout_dcc_files_pass,
00962 disp_dcc_files_pass,
00963 kill_dcc_files,
00964 out_dcc_files
00965 };
00966
00967
00968 static void filesys_dcc_send_hostresolved(int);
00969
00970
00971
00972 static void filesys_dcc_send(char *nick, char *from, struct userrec *u,
00973 char *text)
00974 {
00975 char *param, *ip, *prt, *buf = NULL, *msg;
00976 int atr = u ? u->flags : 0, i;
00977 unsigned long ipnum;
00978 char ipbuf[32];
00979
00980 buf = malloc(strlen(text) + 1);
00981 msg = buf;
00982 strcpy(buf, text);
00983 param = newsplit(&msg);
00984 if (!(atr & USER_XFER)) {
00985 putlog(LOG_FILES, "*",
00986 "Refused DCC SEND %s (no access): %s!%s", param,
00987 nick, from);
00988 if (!quiet_reject)
00989 dprintf(DP_HELP, "NOTICE %s :No access\n", nick);
00990 } else if (!dccin[0] && !upload_to_cd) {
00991 dprintf(DP_HELP,
00992 "NOTICE %s :DCC file transfers not supported.\n", nick);
00993 putlog(LOG_FILES, "*",
00994 "Refused dcc send %s from %s!%s", param, nick, from);
00995 } else if (strchr(param, '/')) {
00996 dprintf(DP_HELP,
00997 "NOTICE %s :Filename cannot have '/' in it...\n", nick);
00998 putlog(LOG_FILES, "*",
00999 "Refused dcc send %s from %s!%s", param, nick, from);
01000 } else {
01001 ip = newsplit(&msg);
01002 prt = newsplit(&msg);
01003 if (atoi(prt) < 1024 || atoi(prt) > 65535) {
01004
01005 dprintf(DP_HELP, "NOTICE %s :%s (invalid port)\n", nick,
01006 _("Failed to connect"));
01007 putlog(LOG_FILES, "*", "Refused dcc send %s (%s): invalid port", param,
01008 nick);
01009 } else if (atoi(msg) == 0) {
01010 dprintf(DP_HELP,
01011 "NOTICE %s :Sorry, file size info must be included.\n",
01012 nick);
01013 putlog(LOG_FILES, "*", "Refused dcc send %s (%s): no file size",
01014 param, nick);
01015 } else if (dcc_maxsize && (atoi(msg) > (dcc_maxsize * 1024))) {
01016 dprintf(DP_HELP, "NOTICE %s :Sorry, file too large.\n", nick);
01017 putlog(LOG_FILES, "*", "Refused dcc send %s (%s): file too large", param,
01018 nick);
01019 } else {
01020 i = new_dcc(&DCC_DNSWAIT, sizeof(struct dns_info));
01021 if (i < 0) {
01022 dprintf(DP_HELP, "NOTICE %s :Sorry, too many DCC connections.\n",
01023 nick);
01024 putlog(LOG_MISC, "*", "DCC connections full: SEND %s (%s!%s)",
01025 param, nick, from);
01026 return;
01027 }
01028 putlog(LOG_DEBUG, "*", "|FILESYS| dcc send ip: (%s)", ip);
01029 ipnum = strtoul(ip, NULL, 10);
01030 ipnum = htonl(ipnum);
01031 inet_ntop(AF_INET, &ipnum, ipbuf, sizeof(ipbuf));
01032 ip = ipbuf;
01033 strlcpy(dcc[i].addr, ip, sizeof dcc[i].addr);
01034 putlog(LOG_DEBUG, "*", "|FILESYS| addr: (%s)", dcc[i].addr);
01035 dcc[i].port = atoi(prt);
01036 dcc[i].sock = (-1);
01037 dcc[i].user = u;
01038 strcpy(dcc[i].nick, nick);
01039 strcpy(dcc[i].host, from);
01040 dcc[i].u.dns->cbuf = calloc(1, strlen(param) + 1);
01041 strcpy(dcc[i].u.dns->cbuf, param);
01042 dcc[i].u.dns->ibuf = atoi(msg);
01043
01044 dcc[i].u.dns->host = calloc(1, strlen(dcc[i].addr) + 1);
01045 strcpy(dcc[i].u.dns->host, dcc[i].addr);
01046
01047 dcc[i].u.dns->dns_type = RES_HOSTBYIP;
01048 dcc[i].u.dns->dns_success = filesys_dcc_send_hostresolved;
01049 dcc[i].u.dns->dns_failure = filesys_dcc_send_hostresolved;
01050 dcc[i].u.dns->type = &DCC_FORK_SEND;
01051 dcc_dnshostbyip(dcc[i].addr);
01052 }
01053 }
01054 free_null(buf);
01055 }
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065 #define MKTEMPFILE_TOT (7 + 2 + 8)
01066 static char *mktempfile(char *filename)
01067 {
01068 char rands[8], *tempname, *fn = filename;
01069 int l;
01070
01071 make_rand_str(rands, 7);
01072 l = strlen(filename);
01073 if ((l + MKTEMPFILE_TOT) > NAME_MAX) {
01074 fn[NAME_MAX - MKTEMPFILE_TOT] = 0;
01075 l = NAME_MAX - MKTEMPFILE_TOT;
01076 fn = malloc(l + 1);
01077 strlcpy(fn, filename, sizeof fn);
01078 }
01079 tempname = malloc(l + MKTEMPFILE_TOT + 1);
01080 sprintf(tempname, "%u-%s-%s", getpid(), rands, fn);
01081 if (fn != filename)
01082 free_null(fn);
01083 return tempname;
01084 }
01085
01086 static void filesys_dcc_send_hostresolved(int i)
01087 {
01088 char *s1, *param = NULL, prt[100], *tempf;
01089 int len = dcc[i].u.dns->ibuf, j;
01090
01091 sprintf(prt, "%d", dcc[i].port);
01092 realloc_strcpy(param, dcc[i].u.dns->cbuf);
01093
01094 changeover_dcc(i, &DCC_FORK_SEND, sizeof(struct xfer_info));
01095 if (param[0] == '.')
01096 param[0] = '_';
01097
01098 dcc[i].u.xfer->origname = calloc(1, strlen(param) + 1);
01099 strcpy(dcc[i].u.xfer->origname, param);
01100 tempf = mktempfile(param);
01101 dcc[i].u.xfer->filename = calloc(1, strlen(tempf) + 1);
01102 strcpy(dcc[i].u.xfer->filename, tempf);
01103
01104 free_null(tempf);
01105 free_null(param);
01106
01107 if (upload_to_cd) {
01108 char *p = get_user(&USERENTRY_DCCDIR, dcc[i].user);
01109
01110 if (p)
01111 sprintf(dcc[i].u.xfer->dir, "%s%s/", dccdir, p);
01112 else
01113 sprintf(dcc[i].u.xfer->dir, "%s", dccdir);
01114 } else
01115 strcpy(dcc[i].u.xfer->dir, dccin);
01116 dcc[i].u.xfer->length = len;
01117 s1 = malloc(strlen(dcc[i].u.xfer->dir) +
01118 strlen(dcc[i].u.xfer->origname) + 1);
01119 sprintf(s1, "%s%s", dcc[i].u.xfer->dir, dcc[i].u.xfer->origname);
01120 if (file_readable(s1)) {
01121 dprintf(DP_HELP, "NOTICE %s :File `%s' already exists.\n",
01122 dcc[i].nick, dcc[i].u.xfer->origname);
01123 lostdcc(i);
01124 free_null(s1);
01125 } else {
01126 free_null(s1);
01127
01128 for (j = 0; j < dcc_total; j++)
01129 if (j != i) {
01130 if ((dcc[j].type->flags & (DCT_FILETRAN | DCT_FILESEND))
01131 == (DCT_FILETRAN | DCT_FILESEND)) {
01132 if (!strcmp(dcc[i].u.xfer->origname, dcc[j].u.xfer->origname)) {
01133 dprintf(DP_HELP, "NOTICE %s :File `%s' is already being sent.\n",
01134 dcc[i].nick, dcc[i].u.xfer->origname);
01135 lostdcc(i);
01136 return;
01137 }
01138 }
01139 }
01140
01141 s1 = malloc(strlen(tempdir) + strlen(dcc[i].u.xfer->filename) + 1);
01142 sprintf(s1, "%s%s", tempdir, dcc[i].u.xfer->filename);
01143 dcc[i].u.xfer->f = fopen(s1, "w");
01144 free_null(s1);
01145 if (dcc[i].u.xfer->f == NULL) {
01146 dprintf(DP_HELP,
01147 "NOTICE %s :Can't create file `%s' (temp dir error)\n",
01148 dcc[i].nick, dcc[i].u.xfer->origname);
01149 lostdcc(i);
01150 } else {
01151 dcc[i].timeval = now;
01152 dcc[i].sock = getsock(SOCK_BINARY);
01153 if (dcc[i].sock < 0 || open_telnet_dcc(dcc[i].sock, dcc[i].addr, prt) < 0)
01154 dcc[i].type->eof(i);
01155 }
01156 }
01157 }
01158
01159
01160
01161 static int filesys_DCC_CHAT(char *nick, char *from, char *handle,
01162 char *object, char *keyword, char *text)
01163 {
01164 char *param, *ip, *prt, buf[512], *msg = buf;
01165 int i, sock;
01166 struct userrec *u = get_user_by_handle(userlist, handle);
01167 struct flag_record fr = {FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0};
01168
01169 if (strcasecmp(object, botname))
01170 return 0;
01171 if (!strncasecmp(text, "SEND ", 5)) {
01172 filesys_dcc_send(nick, from, u, text + 5);
01173 return 1;
01174 }
01175 if (strncasecmp(text, "CHAT ", 5) || !u)
01176 return 0;
01177 strcpy(buf, text + 5);
01178 get_user_flagrec(u, &fr, 0);
01179 param = newsplit(&msg);
01180 if (dcc_total == max_dcc) {
01181 putlog(LOG_MISC, "*", _("DCC connections full: %s %s (%s!%s)"), "CHAT(file)", param, nick, from);
01182 } else if (glob_party(fr))
01183 return 0;
01184 else if (!glob_xfer(fr)) {
01185 if (!quiet_reject)
01186 dprintf(DP_HELP, "NOTICE %s :%s\n", nick, _("No access"));
01187 putlog(LOG_MISC, "*", "%s: %s!%s", _("Refused DCC chat (no access)"), nick, from);
01188 } else if (u_pass_match(u, "-")) {
01189 if (!quiet_reject)
01190 dprintf(DP_HELP, "NOTICE %s :%s\n", nick, _("You must have a password set."));
01191 putlog(LOG_MISC, "*", "%s: %s!%s", _("Refused DCC chat (no password)"), nick, from);
01192 } else if (!dccdir[0]) {
01193 putlog(LOG_MISC, "*", "%s: %s!%s", _("Refused DCC chat (+x but no file area)"), nick, from);
01194 } else {
01195 ip = newsplit(&msg);
01196 prt = newsplit(&msg);
01197 sock = getsock(0);
01198 if (sock < 0 || open_telnet_dcc(sock, ip, prt) < 0) {
01199 neterror(buf);
01200 if (!quiet_reject)
01201 dprintf(DP_HELP, "NOTICE %s :%s (%s)\n", nick,
01202 _("Failed to connect"), buf);
01203 putlog(LOG_MISC, "*", "%s: CHAT(file) (%s!%s)", _("DCC connection failed"),
01204 nick, from);
01205 putlog(LOG_MISC, "*", " (%s)", buf);
01206 killsock(sock);
01207 } else if (atoi(prt) < 1024 || atoi(prt) > 65535) {
01208
01209 if (!quiet_reject)
01210 dprintf(DP_HELP, "NOTICE %s :%s", nick,
01211 _("Failed to connect (invalid port)\n"));
01212 putlog(LOG_FILES, "*", "%s: %s!%s", _("Refused DCC chat (invalid port)"), nick, from);
01213
01214 } else {
01215 unsigned int ip_int;
01216
01217 i = new_dcc(&DCC_FILES_PASS, sizeof(struct file_info));
01218 sscanf(ip, "%u", &ip_int);
01219 strcpy(dcc[i].addr, iptostr(htonl(ip_int)));
01220 dcc[i].port = atoi(prt);
01221 dcc[i].sock = sock;
01222 strcpy(dcc[i].nick, u->handle);
01223 strcpy(dcc[i].host, from);
01224 dcc[i].status = STAT_ECHO;
01225 dcc[i].timeval = now;
01226 dcc[i].u.file->chat = calloc(1, sizeof(struct chat_info));
01227 strcpy(dcc[i].u.file->chat->con_chan, "*");
01228 dcc[i].user = u;
01229 putlog(LOG_MISC, "*", "DCC connection: CHAT(file) (%s!%s)", nick, from);
01230 dprintf(i, "%s\n", _("Enter your password."));
01231 }
01232 }
01233 return 1;
01234 }
01235
01236 static cmd_t myctcp[] =
01237 {
01238 {"DCC", "", filesys_DCC_CHAT, "files:DCC"},
01239 {NULL, NULL, NULL, NULL}
01240 };
01241
01242 static void init_server_ctcps(char *module)
01243 {
01244 add_builtins("ctcp", myctcp);
01245 }
01246
01247 static cmd_t myload[] =
01248 {
01249 {"server", "", (Function) init_server_ctcps, "filesys:server"},
01250 {NULL, NULL, NULL, NULL}
01251 };
01252
01253 static void filesys_report(int idx, int details)
01254 {
01255 if (details) {
01256 if (dccdir[0]) {
01257 dprintf(idx, _(" DCC file path: %s"), dccdir);
01258 if (upload_to_cd)
01259 dprintf(idx, _("\n incoming: (go to the current dir)\n"));
01260 else if (dccin[0])
01261 dprintf(idx, _("\n incoming: %s\n"), dccin);
01262 else
01263 dprintf(idx, _(" (no uploads)\n"));
01264 if (dcc_users)
01265 dprintf(idx, _(" max users is %d\n"), dcc_users);
01266 if ((upload_to_cd) || (dccin[0]))
01267 dprintf(idx, _(" DCC max file size: %dk\n"), dcc_maxsize);
01268 } else
01269 dprintf(idx, _(" (Filesystem module loaded, but no active dcc path.)\n"));
01270 }
01271 }
01272
01273 static char *filesys_close()
01274 {
01275 int i;
01276
01277 putlog(LOG_MISC, "*", _("Unloading filesystem, killing all filesystem connections."));
01278 for (i = 0; i < dcc_total; i++)
01279 if (dcc[i].type == &DCC_FILES) {
01280 dprintf(i, _("-=- poof -=-\n"));
01281 dprintf(i,
01282 _("You have been booted from the filesystem, module unloaded.\n"));
01283 killsock(dcc[i].sock);
01284 lostdcc(i);
01285 } else if (dcc[i].type == &DCC_FILES_PASS) {
01286 killsock(dcc[i].sock);
01287 lostdcc(i);
01288 }
01289 rem_tcl_commands(mytcls);
01290 rem_tcl_strings(mystrings);
01291 rem_tcl_ints(myints);
01292 rem_builtins("dcc", mydcc);
01293 rem_builtins("load", myload);
01294 rem_help_reference("filesys.help");
01295 rem_builtins("ctcp", myctcp);
01296 bind_table_del(BT_file);
01297 del_entry_type(&USERENTRY_DCCDIR);
01298 module_undepend(MODULE_NAME);
01299 return NULL;
01300 }
01301
01302 EXPORT_SCOPE char *start();
01303
01304 static Function filesys_table[] =
01305 {
01306
01307 (Function) start,
01308 (Function) filesys_close,
01309 (Function) 0,
01310 (Function) filesys_report,
01311
01312 (Function) 0,
01313 (Function) add_file,
01314 (Function) incr_file_gots,
01315 (Function) is_valid,
01316 };
01317
01318 char *start(eggdrop_t *eggdrop)
01319 {
01320 egg = eggdrop;
01321
01322 module_register(MODULE_NAME, filesys_table, 2, 0);
01323 if (!module_depend(MODULE_NAME, "eggdrop", 107, 0)) {
01324 module_undepend(MODULE_NAME);
01325 return _("This module requires eggdrop1.7.0 or later");
01326 }
01327 add_tcl_commands(mytcls);
01328 add_tcl_strings(mystrings);
01329 add_tcl_ints(myints);
01330 BT_file = bind_table_add("file", 3, "sis", MATCH_MASK, BIND_STACKABLE);
01331 add_builtins("dcc", mydcc);
01332 add_builtins("load", myload);
01333 add_builtins("file", myfiles);
01334 add_help_reference("filesys.help");
01335 init_server_ctcps(0);
01336 memcpy(&USERENTRY_DCCDIR, &USERENTRY_INFO, sizeof(struct user_entry_type) -
01337 sizeof(char *));
01338 add_entry_type(&USERENTRY_DCCDIR);
01339 DCC_FILES_PASS.timeout_val = &password_timeout;
01340 return NULL;
01341 }
01342
01343 static int is_valid()
01344 {
01345 return dccdir[0];
01346 }