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
00026
00027 #define MODULE_NAME "transfer"
00028 #define MAKING_TRANSFER
00029
00030
00031 #include <sys/types.h>
00032 #include <sys/stat.h>
00033 #include "src/mod/module.h"
00034 #include "src/tandem.h"
00035
00036 #include "src/users.h"
00037 #include "transfer.h"
00038
00039 #include <netinet/in.h>
00040 #include <arpa/inet.h>
00041
00042
00043 static Function *global = NULL;
00044
00045 static p_tcl_bind_list H_rcvd, H_sent, H_lost, H_tout;
00046
00047 static int wait_dcc_xfer = 300;
00048 static int dcc_limit = 3;
00049 static int dcc_block = 0;
00050 static fileq_t *fileq = NULL;
00051
00052 static struct dcc_table DCC_SEND, DCC_GET, DCC_GET_PENDING;
00053
00054 #include "transferfstat.c"
00055 #include "transferqueue.c"
00056 #include "tcltransfer.c"
00057
00058
00059
00060
00061
00062 static int wild_match_file(register char *m, register char *n)
00063 {
00064 char *ma = m, *lsm = 0, *lsn = 0;
00065 int match = 1;
00066 register unsigned int sofar = 0;
00067
00068
00069 if ((m == 0) || (n == 0) || (!*n))
00070 return 0;
00071
00072 while (*n) {
00073 switch (*m) {
00074 case 0:
00075 do
00076 m--;
00077 while ((m > ma) && (*m == '?'));
00078 if ((m > ma) ? ((*m == '*') && (m[-1] != FILEQUOTE)) : (*m == '*'))
00079 return FILEMATCH;
00080 break;
00081 case FILEWILDS:
00082 do
00083 m++;
00084 while (*m == FILEWILDS);
00085 lsm = m;
00086 lsn = n;
00087 match += sofar;
00088 sofar = 0;
00089 continue;
00090 case FILEWILDQ:
00091 m++;
00092 n++;
00093 continue;
00094 case FILEQUOTE:
00095 m++;
00096 }
00097 if (*m == *n) {
00098 m++;
00099 n++;
00100 sofar++;
00101 continue;
00102 }
00103 if (lsm) {
00104 n = ++lsn;
00105 m = lsm;
00106 sofar = 0;
00107 continue;
00108 }
00109 return 0;
00110 }
00111 while (*m == FILEWILDS)
00112 m++;
00113 return (*m) ? 0 : FILEMATCH;
00114 }
00115
00116
00117 static void wipe_tmp_filename(char *fn, int idx)
00118 {
00119 int i, ok = 1;
00120
00121 if (!copy_to_tmp)
00122 return;
00123
00124 for (i = 0; i < dcc_total; i++) {
00125 if ((i != idx) &&
00126 (dcc[i].type == &DCC_GET || dcc[i].type == &DCC_GET_PENDING) &&
00127 (!strcmp(dcc[i].u.xfer->filename, fn))) {
00128 ok = 0;
00129 break;
00130 }
00131 }
00132
00133 if (ok)
00134 unlink(fn);
00135 }
00136
00137
00138
00139 static int at_limit(char *nick)
00140 {
00141 int i, x = 0;
00142
00143 for (i = 0; i < dcc_total; i++)
00144 if ((dcc[i].type == &DCC_GET || dcc[i].type == &DCC_GET_PENDING) &&
00145 !egg_strcasecmp(dcc[i].nick, nick))
00146 x++;
00147
00148 return (x >= dcc_limit);
00149 }
00150
00151
00152
00153
00154 static char *replace_spaces(char *fn)
00155 {
00156 register char *ret, *p;
00157
00158 p = ret = nmalloc(strlen(fn) + 1);
00159 strcpy(ret, fn);
00160 while ((p = strchr(p, ' ')) != NULL)
00161 *p = '_';
00162 return ret;
00163 }
00164
00165
00166 static int builtin_sentrcvd STDVAR
00167 {
00168 Function F = (Function) cd;
00169
00170 BADARGS(4, 4, " hand nick path");
00171
00172 CHECKVALIDITY(builtin_sentrcvd);
00173 F(argv[1], argv[2], argv[3]);
00174 return TCL_OK;
00175 }
00176
00177 static int builtin_toutlost STDVAR
00178 {
00179 Function F = (Function) cd;
00180
00181 BADARGS(6, 6, " hand nick path acked length");
00182
00183 CHECKVALIDITY(builtin_toutlost);
00184 F(argv[1], argv[2], argv[3], argv[4], argv[5]);
00185 return TCL_OK;
00186 }
00187
00188 static void check_tcl_sentrcvd(struct userrec *u, char *nick, char *path,
00189 p_tcl_bind_list h)
00190 {
00191 struct flag_record fr = { FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0 };
00192 char *hand = u ? u->handle : "*";
00193
00194 get_user_flagrec(u, &fr, NULL);
00195 Tcl_SetVar(interp, "_sr1", hand, 0);
00196 Tcl_SetVar(interp, "_sr2", nick, 0);
00197 Tcl_SetVar(interp, "_sr3", path, 0);
00198 check_tcl_bind(h, hand, &fr, " $_sr1 $_sr2 $_sr3",
00199 MATCH_MASK | BIND_USE_ATTR | BIND_STACKABLE);
00200 }
00201
00202 static void check_tcl_toutlost(struct userrec *u, char *nick, char *path,
00203 unsigned long acked, unsigned long length,
00204 p_tcl_bind_list h)
00205 {
00206 struct flag_record fr = { FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0 };
00207 char *hand = u ? u->handle : "*";
00208 char s[15];
00209
00210 get_user_flagrec(u, &fr, NULL);
00211 Tcl_SetVar(interp, "_sr1", hand, 0);
00212 Tcl_SetVar(interp, "_sr2", nick, 0);
00213 Tcl_SetVar(interp, "_sr3", path, 0);
00214 egg_snprintf(s, sizeof s, "%lu", acked);
00215 Tcl_SetVar(interp, "_sr4", s, 0);
00216 egg_snprintf(s, sizeof s, "%lu", length);
00217 Tcl_SetVar(interp, "_sr5", s, 0);
00218 check_tcl_bind(h, hand, &fr, " $_sr1 $_sr2 $_sr3 $_sr4 $_sr5",
00219 MATCH_MASK | BIND_USE_ATTR | BIND_STACKABLE);
00220 }
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237 #define PMAX_SIZE 4096
00238 static unsigned long pump_file_to_sock(FILE *file, long sock,
00239 register unsigned long pending_data)
00240 {
00241 register unsigned long actual_size;
00242 const unsigned long buf_len = pending_data >= PMAX_SIZE ?
00243 PMAX_SIZE : pending_data;
00244 char *bf = nmalloc(buf_len);
00245
00246 if (bf) {
00247 do {
00248 actual_size = pending_data >= buf_len ? buf_len : pending_data;
00249 fread(bf, actual_size, 1, file);
00250 tputs(sock, bf, actual_size);
00251 pending_data -= actual_size;
00252 } while (!sock_has_data(SOCK_DATA_OUTGOING, sock) && pending_data != 0);
00253 nfree(bf);
00254 }
00255 return pending_data;
00256 }
00257
00258 static void eof_dcc_fork_send(int idx)
00259 {
00260 char s1[121];
00261 char *s2;
00262
00263 fclose(dcc[idx].u.xfer->f);
00264 if (!strcmp(dcc[idx].nick, "*users")) {
00265 int x, y = 0;
00266
00267 for (x = 0; x < dcc_total; x++)
00268 if ((!egg_strcasecmp(dcc[x].nick, dcc[idx].host)) &&
00269 (dcc[x].type->flags & DCT_BOT)) {
00270 y = x;
00271 break;
00272 }
00273 if (y != 0) {
00274 dcc[y].status &= ~STAT_GETTING;
00275 dcc[y].status &= ~STAT_SHARE;
00276 }
00277 putlog(LOG_BOTS, "*", USERF_FAILEDXFER);
00278 unlink(dcc[idx].u.xfer->filename);
00279 } else {
00280 neterror(s1);
00281 if (!quiet_reject)
00282 dprintf(DP_HELP, "NOTICE %s :%s (%s)\n", dcc[idx].nick,
00283 DCC_CONNECTFAILED1, s1);
00284 putlog(LOG_MISC, "*", "%s: SEND %s (%s!%s)", DCC_CONNECTFAILED2,
00285 dcc[idx].u.xfer->origname, dcc[idx].nick, dcc[idx].host);
00286 putlog(LOG_MISC, "*", " (%s)", s1);
00287 s2 = nmalloc(strlen(tempdir) + strlen(dcc[idx].u.xfer->filename) + 1);
00288 sprintf(s2, "%s%s", tempdir, dcc[idx].u.xfer->filename);
00289 unlink(s2);
00290 nfree(s2);
00291 }
00292 killsock(dcc[idx].sock);
00293 lostdcc(idx);
00294 }
00295
00296 static void eof_dcc_send(int idx)
00297 {
00298 int ok, j;
00299 char *ofn, *nfn, s[1024], *hand;
00300 struct userrec *u;
00301
00302 fclose(dcc[idx].u.xfer->f);
00303
00304 if (dcc[idx].u.xfer->length == dcc[idx].status) {
00305 int l;
00306
00307
00308 ok = 0;
00309 if (!strcmp(dcc[idx].nick, "*users")) {
00310 module_entry *me = module_find("share", 0, 0);
00311
00312 if (me && me->funcs) {
00313 Function f = me->funcs[SHARE_FINISH];
00314
00315 (f) (idx);
00316 }
00317 killsock(dcc[idx].sock);
00318 lostdcc(idx);
00319 return;
00320 }
00321 putlog(LOG_FILES, "*", TRANSFER_COMPLETED_DCC, dcc[idx].u.xfer->origname,
00322 dcc[idx].nick, dcc[idx].host);
00323 egg_snprintf(s, sizeof s, "%s!%s", dcc[idx].nick, dcc[idx].host);
00324 u = get_user_by_host(s);
00325 hand = u ? u->handle : "*";
00326
00327 l = strlen(dcc[idx].u.xfer->filename);
00328 if (l > NAME_MAX) {
00329 putlog(LOG_FILES, "*", TRANSFER_FILENAME_TOOLONG, l);
00330 dprintf(DP_HELP, TRANSFER_NOTICE_FNTOOLONG, dcc[idx].nick, l);
00331 putlog(LOG_FILES, "*", TRANSFER_TOO_BAD);
00332 dprintf(DP_HELP, TRANSFER_NOTICE_TOOBAD, dcc[idx].nick);
00333 killsock(dcc[idx].sock);
00334 lostdcc(idx);
00335 return;
00336 }
00337
00338 ofn = nmalloc(strlen(tempdir) + strlen(dcc[idx].u.xfer->filename) + 1);
00339 nfn = nmalloc(strlen(dcc[idx].u.xfer->dir)
00340 + strlen(dcc[idx].u.xfer->origname) + 1);
00341 sprintf(ofn, "%s%s", tempdir, dcc[idx].u.xfer->filename);
00342 sprintf(nfn, "%s%s", dcc[idx].u.xfer->dir, dcc[idx].u.xfer->origname);
00343 if (movefile(ofn, nfn))
00344 putlog(LOG_MISC | LOG_FILES, "*", TRANSFER_FAILED_MOVE, nfn, ofn);
00345 else {
00346
00347 module_entry *fs = module_find("filesys", 0, 0);
00348
00349 if (fs != NULL) {
00350 Function f = fs->funcs[FILESYS_ADDFILE];
00351
00352 f(dcc[idx].u.xfer->dir, dcc[idx].u.xfer->origname, hand);
00353 }
00354 stats_add_upload(u, dcc[idx].u.xfer->length);
00355 check_tcl_sentrcvd(u, dcc[idx].nick, nfn, H_rcvd);
00356 }
00357 nfree(ofn);
00358 nfree(nfn);
00359 for (j = 0; j < dcc_total; j++)
00360 if (!ok && (dcc[j].type->flags & (DCT_GETNOTES | DCT_FILES)) &&
00361 !egg_strcasecmp(dcc[j].nick, hand)) {
00362 ok = 1;
00363 dprintf(j, TRANSFER_THANKS);
00364 }
00365 if (!ok)
00366 dprintf(DP_HELP, TRANSFER_NOTICE_THANKS, dcc[idx].nick);
00367 killsock(dcc[idx].sock);
00368 lostdcc(idx);
00369 return;
00370 }
00371
00372 if (!strcmp(dcc[idx].nick, "*users")) {
00373 int x, y = 0;
00374
00375 for (x = 0; x < dcc_total; x++)
00376 if ((!egg_strcasecmp(dcc[x].nick, dcc[idx].host)) &&
00377 (dcc[x].type->flags & DCT_BOT))
00378 y = x;
00379 if (y) {
00380 putlog(LOG_BOTS, "*", TRANSFER_USERFILE_LOST, dcc[y].nick);
00381 unlink(dcc[idx].u.xfer->filename);
00382
00383 dprintf(y, "bye\n");
00384 egg_snprintf(s, sizeof s, TRANSFER_USERFILE_DISCON, dcc[y].nick);
00385 botnet_send_unlinked(y, dcc[y].nick, s);
00386 chatout("*** %s\n", dcc[y].nick, s);
00387 if (y != idx) {
00388 killsock(dcc[y].sock);
00389 lostdcc(y);
00390 }
00391 killsock(dcc[idx].sock);
00392 lostdcc(idx);
00393 }
00394 } else {
00395 putlog(LOG_FILES, "*", TRANSFER_LOST_DCCSEND, dcc[idx].u.xfer->origname,
00396 dcc[idx].nick, dcc[idx].host, dcc[idx].status,
00397 dcc[idx].u.xfer->length);
00398 ofn = nmalloc(strlen(tempdir) + strlen(dcc[idx].u.xfer->filename) + 1);
00399 sprintf(ofn, "%s%s", tempdir, dcc[idx].u.xfer->filename);
00400 unlink(ofn);
00401 nfree(ofn);
00402 killsock(dcc[idx].sock);
00403 lostdcc(idx);
00404 }
00405 }
00406
00407
00408
00409 static inline u_8bit_t byte_order_test(void)
00410 {
00411 u_16bit_t test = TRANSFER_REGET_PACKETID;
00412
00413 if (*((u_8bit_t *) & test) == ((TRANSFER_REGET_PACKETID & 0xff00) >> 8))
00414 return 0;
00415 if (*((u_8bit_t *) & test) == (TRANSFER_REGET_PACKETID & 0x00ff))
00416 return 1;
00417 return 0;
00418 }
00419
00420
00421
00422 inline static void handle_resend_packet(int idx, transfer_reget *reget_data)
00423 {
00424 if (byte_order_test() != reget_data->byte_order) {
00425
00426
00427
00428 reget_data->packet_id = ((reget_data->packet_id & 0x00ff) << 8) |
00429 ((reget_data->packet_id & 0xff00) >> 8);
00430 reget_data->byte_offset = ((reget_data->byte_offset & 0xff000000) >> 24) |
00431 ((reget_data->byte_offset & 0x00ff0000) >> 8) |
00432 ((reget_data->byte_offset & 0x0000ff00) << 8) |
00433 ((reget_data->byte_offset & 0x000000ff) << 24);
00434 }
00435 if (reget_data->packet_id != TRANSFER_REGET_PACKETID)
00436 putlog(LOG_FILES, "*", TRANSFER_REGET_PACKET, dcc[idx].nick,
00437 dcc[idx].u.xfer->origname);
00438 else
00439 dcc[idx].u.xfer->offset = reget_data->byte_offset;
00440 dcc[idx].u.xfer->type = XFER_RESEND;
00441 }
00442
00443
00444
00445
00446
00447
00448
00449 static void dcc_get(int idx, char *buf, int len)
00450 {
00451 char xnick[NICKLEN];
00452 unsigned char bbuf[4];
00453 unsigned long cmp, l;
00454 int w = len + dcc[idx].u.xfer->sofar, p = 0;
00455
00456 dcc[idx].timeval = now;
00457
00458
00459
00460
00461 if (w < 4 || (w < 8 && dcc[idx].u.xfer->type == XFER_RESEND_PEND)) {
00462 my_memcpy(&(dcc[idx].u.xfer->buf[dcc[idx].u.xfer->sofar]), buf, len);
00463 dcc[idx].u.xfer->sofar += len;
00464 return;
00465
00466 } else if (dcc[idx].u.xfer->type == XFER_RESEND_PEND) {
00467
00468 if (w == 8) {
00469 transfer_reget reget_data;
00470
00471 my_memcpy(®et_data, dcc[idx].u.xfer->buf, dcc[idx].u.xfer->sofar);
00472 my_memcpy(®et_data + dcc[idx].u.xfer->sofar, buf, len);
00473 handle_resend_packet(idx, ®et_data);
00474 cmp = dcc[idx].u.xfer->offset;
00475 } else
00476 return;
00477
00478
00479 } else {
00480
00481 if (w == 4) {
00482 my_memcpy(bbuf, dcc[idx].u.xfer->buf, dcc[idx].u.xfer->sofar);
00483 my_memcpy(&(bbuf[dcc[idx].u.xfer->sofar]), buf, len);
00484 } else {
00485 p = ((w - 1) & ~3) - dcc[idx].u.xfer->sofar;
00486 w = w - ((w - 1) & ~3);
00487 if (w < 4) {
00488 my_memcpy(dcc[idx].u.xfer->buf, &(buf[p]), w);
00489 return;
00490 }
00491 my_memcpy(bbuf, &(buf[p]), w);
00492 }
00493
00494
00495
00496 cmp = ((unsigned int) (bbuf[0]) << 24) +
00497 ((unsigned int) (bbuf[1]) << 16) +
00498 ((unsigned int) (bbuf[2]) << 8) + bbuf[3];
00499 dcc[idx].u.xfer->acked = cmp;
00500 }
00501
00502 dcc[idx].u.xfer->sofar = 0;
00503 if (cmp > dcc[idx].u.xfer->length && cmp > dcc[idx].status) {
00504
00505 putlog(LOG_FILES, "*", TRANSFER_BEHIND_FILEEND, dcc[idx].u.xfer->origname,
00506 dcc[idx].nick);
00507 } else if (cmp > dcc[idx].status) {
00508
00509 if (!strcmp(dcc[idx].nick, "*users"))
00510 putlog(LOG_BOTS, "*", TRANSFER_TRY_SKIP_AHEAD);
00511 else {
00512 fseek(dcc[idx].u.xfer->f, cmp, SEEK_SET);
00513 dcc[idx].status = cmp;
00514 putlog(LOG_FILES, "*", TRANSFER_RESUME_FILE, (int) (cmp / 1024),
00515 dcc[idx].u.xfer->origname, dcc[idx].nick);
00516 }
00517 } else {
00518 if (dcc[idx].u.xfer->ack_type == XFER_ACK_UNKNOWN) {
00519 if (cmp < dcc[idx].u.xfer->offset)
00520
00521
00522
00523
00524 dcc[idx].u.xfer->ack_type = XFER_ACK_WITHOUT_OFFSET;
00525 else
00526 dcc[idx].u.xfer->ack_type = XFER_ACK_WITH_OFFSET;
00527 }
00528 if (dcc[idx].u.xfer->ack_type == XFER_ACK_WITHOUT_OFFSET)
00529 cmp += dcc[idx].u.xfer->offset;
00530 }
00531
00532 if (cmp != dcc[idx].status)
00533 return;
00534 if (dcc[idx].status == dcc[idx].u.xfer->length) {
00535
00536 killsock(dcc[idx].sock);
00537 fclose(dcc[idx].u.xfer->f);
00538 if (!strcmp(dcc[idx].nick, "*users")) {
00539 module_entry *me = module_find("share", 0, 0);
00540 int x, y = 0;
00541
00542 for (x = 0; x < dcc_total; x++)
00543 if (!egg_strcasecmp(dcc[x].nick, dcc[idx].host) &&
00544 (dcc[x].type->flags & DCT_BOT))
00545 y = x;
00546 if (y != 0)
00547 dcc[y].status &= ~STAT_SENDING;
00548 putlog(LOG_BOTS, "*", TRANSFER_COMPLETED_USERFILE, dcc[y].nick);
00549 unlink(dcc[idx].u.xfer->filename);
00550
00551 if (me && me->funcs[SHARE_DUMP_RESYNC])
00552 ((me->funcs)[SHARE_DUMP_RESYNC]) (y);
00553 xnick[0] = 0;
00554 } else {
00555 module_entry *fs = module_find("filesys", 0, 0);
00556 struct userrec *u = get_user_by_handle(userlist, dcc[idx].u.xfer->from);
00557
00558 check_tcl_sentrcvd(u, dcc[idx].nick, dcc[idx].u.xfer->dir, H_sent);
00559 if (fs != NULL) {
00560 Function f = fs->funcs[FILESYS_INCRGOTS];
00561
00562 f(dcc[idx].u.xfer->dir);
00563 }
00564
00565
00566
00567 stats_add_dnload(u, dcc[idx].u.xfer->length);
00568 putlog(LOG_FILES, "*", TRANSFER_FINISHED_DCCSEND,
00569 dcc[idx].u.xfer->origname, dcc[idx].nick);
00570 wipe_tmp_filename(dcc[idx].u.xfer->filename, idx);
00571 strcpy((char *) xnick, dcc[idx].nick);
00572 }
00573 lostdcc(idx);
00574
00575 if (!at_limit(xnick))
00576 send_next_file(xnick);
00577 return;
00578 }
00579
00580
00581
00582 l = dcc_block;
00583 if (l == 0 || dcc[idx].status + l > dcc[idx].u.xfer->length)
00584 l = dcc[idx].u.xfer->length - dcc[idx].status;
00585 dcc[idx].u.xfer->block_pending = pump_file_to_sock(dcc[idx].u.xfer->f,
00586 dcc[idx].sock, l);
00587 dcc[idx].status += l;
00588 }
00589
00590 static void eof_dcc_get(int idx)
00591 {
00592 char xnick[NICKLEN], s[1024];
00593
00594 fclose(dcc[idx].u.xfer->f);
00595 if (!strcmp(dcc[idx].nick, "*users")) {
00596 int x, y = 0;
00597
00598 for (x = 0; x < dcc_total; x++)
00599 if (!egg_strcasecmp(dcc[x].nick, dcc[idx].host) &&
00600 (dcc[x].type->flags & DCT_BOT))
00601 y = x;
00602 putlog(LOG_BOTS, "*", TRANSFER_ABORT_USERFILE);
00603
00604 xnick[0] = 0;
00605
00606 dprintf(-dcc[y].sock, "bye\n");
00607 egg_snprintf(s, sizeof s, TRANSFER_USERFILE_DISCON, dcc[y].nick);
00608 botnet_send_unlinked(y, dcc[y].nick, s);
00609 chatout("*** %s\n", s);
00610 if (y != idx) {
00611 killsock(dcc[y].sock);
00612 lostdcc(y);
00613 }
00614 killsock(dcc[idx].sock);
00615 lostdcc(idx);
00616 return;
00617 } else {
00618 struct userrec *u;
00619
00620
00621
00622 egg_snprintf(s, sizeof s, "%s!%s", dcc[idx].nick, dcc[idx].host);
00623 u = get_user_by_host(s);
00624 check_tcl_toutlost(u, dcc[idx].nick, dcc[idx].u.xfer->dir,
00625 dcc[idx].u.xfer->acked, dcc[idx].u.xfer->length, H_lost);
00626
00627 putlog(LOG_FILES, "*", TRANSFER_LOST_DCCGET,
00628 dcc[idx].u.xfer->origname, dcc[idx].nick, dcc[idx].host);
00629 wipe_tmp_filename(dcc[idx].u.xfer->filename, idx);
00630 strcpy(xnick, dcc[idx].nick);
00631 }
00632 killsock(dcc[idx].sock);
00633 lostdcc(idx);
00634
00635 if (!at_limit(xnick))
00636 send_next_file(xnick);
00637 }
00638
00639 static void dcc_send(int idx, char *buf, int len)
00640 {
00641 char s[512], *b;
00642 unsigned long sent;
00643
00644 fwrite(buf, len, 1, dcc[idx].u.xfer->f);
00645 dcc[idx].status += len;
00646
00647 sent = dcc[idx].status;
00648 s[0] = (sent / (1 << 24));
00649 s[1] = (sent % (1 << 24)) / (1 << 16);
00650 s[2] = (sent % (1 << 16)) / (1 << 8);
00651 s[3] = (sent % (1 << 8));
00652 tputs(dcc[idx].sock, s, 4);
00653 dcc[idx].timeval = now;
00654 if (dcc[idx].status > dcc[idx].u.xfer->length && dcc[idx].u.xfer->length > 0) {
00655 dprintf(DP_HELP, TRANSFER_BOGUS_FILE_LENGTH, dcc[idx].nick);
00656 putlog(LOG_FILES, "*", TRANSFER_FILE_TOO_LONG, dcc[idx].u.xfer->origname,
00657 dcc[idx].nick, dcc[idx].host);
00658 fclose(dcc[idx].u.xfer->f);
00659 b = nmalloc(strlen(tempdir) + strlen(dcc[idx].u.xfer->filename) + 1);
00660 sprintf(b, "%s%s", tempdir, dcc[idx].u.xfer->filename);
00661 unlink(b);
00662 nfree(b);
00663 killsock(dcc[idx].sock);
00664 lostdcc(idx);
00665 }
00666 }
00667
00668 static void transfer_get_timeout(int i)
00669 {
00670 char xx[1024];
00671
00672 fclose(dcc[i].u.xfer->f);
00673 if (strcmp(dcc[i].nick, "*users") == 0) {
00674 int x, y = 0;
00675
00676 for (x = 0; x < dcc_total; x++)
00677 if ((!egg_strcasecmp(dcc[x].nick, dcc[i].host)) &&
00678 (dcc[x].type->flags & DCT_BOT))
00679 y = x;
00680 if (y != 0) {
00681 dcc[y].status &= ~STAT_SENDING;
00682 dcc[y].status &= ~STAT_SHARE;
00683 }
00684 unlink(dcc[i].u.xfer->filename);
00685 putlog(LOG_BOTS, "*", TRANSFER_USERFILE_TIMEOUT);
00686 dprintf(y, "bye\n");
00687 egg_snprintf(xx, sizeof xx, TRANSFER_DICONNECT_TIMEOUT, dcc[y].nick);
00688 botnet_send_unlinked(y, dcc[y].nick, xx);
00689 chatout("*** %s\n", xx);
00690 if (y < i) {
00691 int t = y;
00692
00693 y = i;
00694 i = t;
00695 }
00696 killsock(dcc[y].sock);
00697 lostdcc(y);
00698 xx[0] = 0;
00699 } else {
00700 char *p;
00701 struct userrec *u;
00702
00703 p = strrchr(dcc[i].u.xfer->origname, '/');
00704 dprintf(DP_HELP, TRANSFER_NOTICE_TIMEOUT, dcc[i].nick,
00705 p ? p + 1 : dcc[i].u.xfer->origname);
00706
00707
00708
00709 egg_snprintf(xx, sizeof xx, "%s!%s", dcc[i].nick, dcc[i].host);
00710 u = get_user_by_host(xx);
00711 check_tcl_toutlost(u, dcc[i].nick, dcc[i].u.xfer->dir,
00712 dcc[i].u.xfer->acked, dcc[i].u.xfer->length, H_tout);
00713
00714 putlog(LOG_FILES, "*", TRANSFER_DCC_GET_TIMEOUT,
00715 p ? p + 1 : dcc[i].u.xfer->origname, dcc[i].nick, dcc[i].status,
00716 dcc[i].u.xfer->length);
00717 wipe_tmp_filename(dcc[i].u.xfer->filename, i);
00718 strcpy(xx, dcc[i].nick);
00719 }
00720 killsock(dcc[i].sock);
00721 lostdcc(i);
00722 if (!at_limit(xx))
00723 send_next_file(xx);
00724 }
00725
00726 static void tout_dcc_send(int idx)
00727 {
00728
00729 fclose(dcc[idx].u.xfer->f);
00730
00731 if (!strcmp(dcc[idx].nick, "*users")) {
00732 int x, y = 0;
00733
00734 for (x = 0; x < dcc_total; x++)
00735 if (!egg_strcasecmp(dcc[x].nick, dcc[idx].host) &&
00736 (dcc[x].type->flags & DCT_BOT))
00737 y = x;
00738
00739 if (y != 0) {
00740 dcc[y].status &= ~STAT_GETTING;
00741 dcc[y].status &= ~STAT_SHARE;
00742 }
00743
00744 unlink(dcc[idx].u.xfer->filename);
00745
00746 putlog(LOG_BOTS, "*", TRANSFER_USERFILE_TIMEOUT);
00747 } else {
00748 char *buf;
00749
00750 buf = nmalloc(strlen(tempdir) + strlen(dcc[idx].u.xfer->filename) + 1);
00751 sprintf(buf, "%s%s", tempdir, dcc[idx].u.xfer->filename);
00752 unlink(buf);
00753 nfree(buf);
00754
00755 dprintf(DP_HELP, TRANSFER_NOTICE_TIMEOUT, dcc[idx].nick,
00756 dcc[idx].u.xfer->origname);
00757 putlog(LOG_FILES, "*", TRANSFER_DCC_SEND_TIMEOUT, dcc[idx].u.xfer->origname,
00758 dcc[idx].nick, dcc[idx].status, dcc[idx].u.xfer->length);
00759 }
00760
00761 killsock(dcc[idx].sock);
00762 lostdcc(idx);
00763 }
00764
00765 static void display_dcc_get(int idx, char *buf)
00766 {
00767 if (dcc[idx].status == dcc[idx].u.xfer->length)
00768 sprintf(buf, TRANSFER_SEND, dcc[idx].u.xfer->acked,
00769 dcc[idx].u.xfer->length, dcc[idx].u.xfer->origname);
00770 else
00771 sprintf(buf, TRANSFER_SEND, dcc[idx].status,
00772 dcc[idx].u.xfer->length, dcc[idx].u.xfer->origname);
00773 }
00774
00775 static void display_dcc_get_p(int idx, char *buf)
00776 {
00777 sprintf(buf, TRANSFER_SEND_WAITED, now - dcc[idx].timeval,
00778 dcc[idx].u.xfer->origname);
00779 }
00780
00781 static void display_dcc_send(int idx, char *buf)
00782 {
00783 sprintf(buf, TRANSFER_SEND, dcc[idx].status,
00784 dcc[idx].u.xfer->length, dcc[idx].u.xfer->origname);
00785 }
00786
00787 static void display_dcc_fork_send(int idx, char *buf)
00788 {
00789 sprintf(buf, TRANSFER_CONN_SEND);
00790 }
00791
00792 static int expmem_dcc_xfer(void *x)
00793 {
00794 register struct xfer_info *p = (struct xfer_info *) x;
00795 int tot;
00796
00797 tot = sizeof(struct xfer_info);
00798 if (p->filename)
00799 tot += strlen(p->filename) + 1;
00800
00801
00802
00803 if (p->origname && p->filename != p->origname)
00804 tot += strlen(p->origname) + 1;
00805 return tot;
00806 }
00807
00808 static void kill_dcc_xfer(int idx, void *x)
00809 {
00810 register struct xfer_info *p = (struct xfer_info *) x;
00811
00812 if (p->filename)
00813 nfree(p->filename);
00814
00815
00816
00817 if (p->origname && p->origname != p->filename)
00818 nfree(p->origname);
00819 nfree(x);
00820 }
00821
00822 static void out_dcc_xfer(int idx, char *buf, void *x)
00823 {
00824 }
00825
00826 static void outdone_dcc_xfer(int idx)
00827 {
00828 if (dcc[idx].u.xfer->block_pending)
00829 dcc[idx].u.xfer->block_pending =
00830 pump_file_to_sock(dcc[idx].u.xfer->f, dcc[idx].sock,
00831 dcc[idx].u.xfer->block_pending);
00832 }
00833
00834
00835 static struct dcc_table DCC_SEND = {
00836 "SEND",
00837 DCT_FILETRAN | DCT_FILESEND | DCT_VALIDIDX,
00838 eof_dcc_send,
00839 dcc_send,
00840 &wait_dcc_xfer,
00841 tout_dcc_send,
00842 display_dcc_send,
00843 expmem_dcc_xfer,
00844 kill_dcc_xfer,
00845 out_dcc_xfer
00846 };
00847
00848
00849 static struct dcc_table DCC_FORK_SEND = {
00850 "FORK_SEND",
00851 DCT_FILETRAN | DCT_FORKTYPE | DCT_FILESEND | DCT_VALIDIDX,
00852 eof_dcc_fork_send,
00853 dcc_fork_send,
00854 &wait_dcc_xfer,
00855 eof_dcc_fork_send,
00856 display_dcc_fork_send,
00857 expmem_dcc_xfer,
00858 kill_dcc_xfer,
00859 out_dcc_xfer
00860 };
00861
00862
00863 static struct dcc_table DCC_GET = {
00864 "GET",
00865 DCT_FILETRAN | DCT_VALIDIDX,
00866 eof_dcc_get,
00867 dcc_get,
00868 &wait_dcc_xfer,
00869 transfer_get_timeout,
00870 display_dcc_get,
00871 expmem_dcc_xfer,
00872 kill_dcc_xfer,
00873 out_dcc_xfer,
00874 outdone_dcc_xfer
00875 };
00876
00877
00878 static struct dcc_table DCC_GET_PENDING = {
00879 "GET_PENDING",
00880 DCT_FILETRAN | DCT_VALIDIDX,
00881 eof_dcc_get,
00882 dcc_get_pending,
00883 &wait_dcc_xfer,
00884 transfer_get_timeout,
00885 display_dcc_get_p,
00886 expmem_dcc_xfer,
00887 kill_dcc_xfer,
00888 out_dcc_xfer
00889 };
00890
00891 static void dcc_fork_send(int idx, char *x, int y)
00892 {
00893 char s1[121];
00894
00895 if (dcc[idx].type != &DCC_FORK_SEND)
00896 return;
00897
00898 dcc[idx].type = &DCC_SEND;
00899 dcc[idx].u.xfer->start_time = now;
00900
00901 if (strcmp(dcc[idx].nick, "*users")) {
00902 egg_snprintf(s1, sizeof s1, "%s!%s", dcc[idx].nick, dcc[idx].host);
00903 putlog(LOG_MISC, "*", TRANSFER_DCC_CONN, dcc[idx].u.xfer->origname, s1);
00904 }
00905 }
00906
00907 static void dcc_get_pending(int idx, char *buf, int len)
00908 {
00909 unsigned long ip;
00910 unsigned short port;
00911 int i;
00912 char s[UHOSTLEN];
00913
00914 i = answer(dcc[idx].sock, s, &ip, &port, 1);
00915 killsock(dcc[idx].sock);
00916 dcc[idx].sock = i;
00917 dcc[idx].addr = ip;
00918 dcc[idx].port = (int) port;
00919 if (dcc[idx].sock == -1) {
00920 neterror(s);
00921 dprintf(DP_HELP, TRANSFER_NOTICE_BAD_CONN, dcc[idx].nick, s);
00922 putlog(LOG_FILES, "*", TRANSFER_LOG_BAD_CONN, dcc[idx].u.xfer->origname,
00923 dcc[idx].nick, dcc[idx].host);
00924 fclose(dcc[idx].u.xfer->f);
00925 lostdcc(idx);
00926 return;
00927 }
00928
00929 dcc[idx].type = &DCC_GET;
00930 dcc[idx].u.xfer->ack_type = XFER_ACK_UNKNOWN;
00931
00932
00933
00934
00935
00936
00937
00938 if (dcc[idx].u.xfer->type == XFER_RESUME_PEND) {
00939 int l;
00940
00941 if (dcc_block == 0 || dcc[idx].u.xfer->length < dcc_block) {
00942 l = dcc[idx].u.xfer->length - dcc[idx].u.xfer->offset;
00943 dcc[idx].status = dcc[idx].u.xfer->length;
00944 } else {
00945 l = dcc_block;
00946 dcc[idx].status = dcc[idx].u.xfer->offset + dcc_block;
00947 }
00948
00949
00950 fseek(dcc[idx].u.xfer->f, dcc[idx].u.xfer->offset, SEEK_SET);
00951 dcc[idx].u.xfer->block_pending = pump_file_to_sock(dcc[idx].u.xfer->f,
00952 dcc[idx].sock, l);
00953 dcc[idx].u.xfer->type = XFER_RESUME;
00954 } else {
00955 dcc[idx].u.xfer->offset = 0;
00956
00957
00958
00959
00960 if (dcc[idx].u.xfer->type != XFER_RESEND_PEND) {
00961 if (dcc_block == 0 || dcc[idx].u.xfer->length < dcc_block)
00962 dcc[idx].status = dcc[idx].u.xfer->length;
00963 else
00964 dcc[idx].status = dcc_block;
00965 dcc[idx].u.xfer->block_pending = pump_file_to_sock(dcc[idx].u.xfer->f,
00966 dcc[idx].sock,
00967 dcc[idx].status);
00968 } else
00969 dcc[idx].status = 0;
00970 }
00971
00972 dcc[idx].timeval = dcc[idx].u.xfer->start_time = now;
00973 }
00974
00975
00976
00977
00978
00979
00980
00981 static int raw_dcc_resend_send(char *filename, char *nick, char *from,
00982 char *dir, int resend)
00983 {
00984 int zz, port, i;
00985 char *nfn, *buf = NULL;
00986 long dccfilesize;
00987 FILE *f, *dccfile;
00988
00989 zz = -1;
00990 dccfile = fopen(filename, "r");
00991 if (!dccfile)
00992 return DCCSEND_BADFN;
00993 fseek(dccfile, 0, SEEK_END);
00994 dccfilesize = ftell(dccfile);
00995 fclose(dccfile);
00996
00997 if (dccfilesize == 0)
00998 return DCCSEND_FEMPTY;
00999
01000 if (reserved_port_min > 0 && reserved_port_min < reserved_port_max) {
01001 for (port = reserved_port_min; port <= reserved_port_max; port++)
01002 if ((zz = open_listen(&port)) != -1)
01003 break;
01004 } else {
01005 port = reserved_port_min;
01006 zz = open_listen(&port);
01007 }
01008
01009 if (zz == -1)
01010 return DCCSEND_NOSOCK;
01011
01012 nfn = strrchr(dir, '/');
01013 if (nfn == NULL)
01014 nfn = dir;
01015 else
01016 nfn++;
01017
01018 f = fopen(filename, "r");
01019
01020 if (!f)
01021 return DCCSEND_BADFN;
01022
01023 if ((i = new_dcc(&DCC_GET_PENDING, sizeof(struct xfer_info))) == -1)
01024 return DCCSEND_FULL;
01025
01026 dcc[i].sock = zz;
01027 dcc[i].addr = (IP) (-559026163);
01028 dcc[i].port = port;
01029 strcpy(dcc[i].nick, nick);
01030 strcpy(dcc[i].host, "irc");
01031 dcc[i].u.xfer->filename = get_data_ptr(strlen(filename) + 1);
01032 strcpy(dcc[i].u.xfer->filename, filename);
01033 if (strchr(nfn, ' '))
01034 nfn = buf = replace_spaces(nfn);
01035 dcc[i].u.xfer->origname = get_data_ptr(strlen(nfn) + 1);
01036 strcpy(dcc[i].u.xfer->origname, nfn);
01037 strncpyz(dcc[i].u.xfer->from, from, NICKLEN);
01038 strncpyz(dcc[i].u.xfer->dir, dir, DIRLEN);
01039 dcc[i].u.xfer->length = dccfilesize;
01040 dcc[i].timeval = now;
01041 dcc[i].u.xfer->f = f;
01042 dcc[i].u.xfer->type = resend ? XFER_RESEND_PEND : XFER_SEND;
01043
01044 if (nick[0] != '*') {
01045 dprintf(DP_SERVER, "PRIVMSG %s :\001DCC %sSEND %s %lu %d %lu\001\n", nick,
01046 resend ? "RE" : "", nfn, iptolong(natip[0] ?
01047 (IP) inet_addr(natip) : getmyip()), port, dccfilesize);
01048 putlog(LOG_FILES, "*", TRANSFER_BEGIN_DCC, resend ? TRANSFER_RE : "", nfn,
01049 nick);
01050 }
01051
01052 if (buf)
01053 nfree(buf);
01054
01055 return DCCSEND_OK;
01056 }
01057
01058
01059 static int raw_dcc_resend(char *filename, char *nick, char *from, char *dir)
01060 {
01061 return raw_dcc_resend_send(filename, nick, from, dir, 1);
01062 }
01063
01064
01065 static int raw_dcc_send(char *filename, char *nick, char *from, char *dir)
01066 {
01067 return raw_dcc_resend_send(filename, nick, from, dir, 0);
01068 }
01069
01070
01071
01072 static int ctcp_DCC_RESUME(char *nick, char *from, char *handle,
01073 char *object, char *keyword, char *text)
01074 {
01075 char *action, *fn, buf[512], *msg = buf;
01076 int i, port;
01077 unsigned long offset;
01078
01079 strcpy(msg, text);
01080 action = newsplit(&msg);
01081
01082 if (egg_strcasecmp(action, "RESUME"))
01083 return 0;
01084
01085 fn = newsplit(&msg);
01086 port = atoi(newsplit(&msg));
01087 offset = my_atoul(newsplit(&msg));
01088
01089 for (i = 0; i < dcc_total; i++)
01090 if ((dcc[i].type == &DCC_GET_PENDING) &&
01091 (!rfc_casecmp(dcc[i].nick, nick)) && (dcc[i].port == port))
01092 break;
01093 if (i == dcc_total)
01094 return 0;
01095
01096 if (dcc[i].u.xfer->length <= offset) {
01097 char *p = strrchr(dcc[i].u.xfer->origname, '/');
01098
01099 dprintf(DP_HELP, TRANSFER_DCC_IGNORED, nick,
01100 p ? p + 1 : dcc[i].u.xfer->origname);
01101 killsock(dcc[i].sock);
01102 killtransfer(i);
01103 lostdcc(i);
01104 return 0;
01105 }
01106
01107 dcc[i].u.xfer->type = XFER_RESUME_PEND;
01108 dcc[i].u.xfer->offset = offset;
01109 dprintf(DP_SERVER, "PRIVMSG %s :\001DCC ACCEPT %s %d %u\001\n", nick, fn, port,
01110 offset);
01111 return 1;
01112 }
01113
01114 static tcl_ints myints[] = {
01115 {"max-dloads", &dcc_limit},
01116 {"dcc-block", &dcc_block},
01117 {"xfer-timeout", &wait_dcc_xfer},
01118 {NULL, NULL}
01119 };
01120
01121 static cmd_t transfer_ctcps[] = {
01122 {"DCC", "", ctcp_DCC_RESUME, "transfer:DCC"},
01123 {NULL, NULL, NULL, NULL}
01124 };
01125
01126 static cmd_t transfer_load[] = {
01127 {"server", "", server_transfer_setup, NULL},
01128 {NULL, "", NULL, NULL}
01129 };
01130
01131
01132 static int server_transfer_setup(char *mod)
01133 {
01134 p_tcl_bind_list H_ctcp;
01135
01136 if ((H_ctcp = find_bind_table("ctcp")))
01137 add_builtins(H_ctcp, transfer_ctcps);
01138 return 1;
01139 }
01140
01141 static char *transfer_close()
01142 {
01143 int i;
01144 p_tcl_bind_list H_ctcp;
01145
01146 putlog(LOG_MISC, "*", TRANSFER_UNLOADING);
01147 for (i = dcc_total - 1; i >= 0; i--) {
01148 if (dcc[i].type == &DCC_GET || dcc[i].type == &DCC_GET_PENDING)
01149 eof_dcc_get(i);
01150 else if (dcc[i].type == &DCC_SEND)
01151 eof_dcc_send(i);
01152 else if (dcc[i].type == &DCC_FORK_SEND)
01153 eof_dcc_fork_send(i);
01154 }
01155 while (fileq)
01156 deq_this(fileq);
01157 del_entry_type(&USERENTRY_FSTAT);
01158 del_bind_table(H_rcvd);
01159 del_bind_table(H_sent);
01160 del_bind_table(H_lost);
01161 del_bind_table(H_tout);
01162 rem_builtins(H_load, transfer_load);
01163 if ((H_ctcp = find_bind_table("ctcp")))
01164 rem_builtins(H_ctcp, transfer_ctcps);
01165 rem_tcl_commands(mytcls);
01166 rem_tcl_ints(myints);
01167 rem_help_reference("transfer.help");
01168 del_lang_section("transfer");
01169 module_undepend(MODULE_NAME);
01170 return NULL;
01171 }
01172
01173 static int transfer_expmem()
01174 {
01175 return expmem_fileq();
01176 }
01177
01178 static void transfer_report(int idx, int details)
01179 {
01180 if (details) {
01181 int size = transfer_expmem();
01182
01183 dprintf(idx, TRANSFER_STAT_1, dcc_block,
01184 (dcc_block == 0) ? " (turbo dcc)" : "");
01185 dprintf(idx, TRANSFER_STAT_2, dcc_limit);
01186 dprintf(idx, " Using %d byte%s of memory\n", size,
01187 (size != 1) ? "s" : "");
01188 }
01189 }
01190
01191 EXPORT_SCOPE char *transfer_start();
01192
01193 static Function transfer_table[] = {
01194 (Function) transfer_start,
01195 (Function) transfer_close,
01196 (Function) transfer_expmem,
01197 (Function) transfer_report,
01198
01199 (Function) & DCC_FORK_SEND,
01200 (Function) at_limit,
01201 (Function) NULL,
01202 (Function) fileq_cancel,
01203
01204 (Function) queue_file,
01205 (Function) raw_dcc_send,
01206 (Function) show_queued_files,
01207 (Function) wild_match_file,
01208
01209 (Function) wipe_tmp_filename,
01210 (Function) & DCC_GET,
01211 (Function) & H_rcvd,
01212 (Function) & H_sent,
01213
01214 (Function) & USERENTRY_FSTAT,
01215 (Function) NULL,
01216 (Function) raw_dcc_resend,
01217 (Function) & H_lost,
01218
01219 (Function) & H_tout,
01220 (Function) & DCC_SEND,
01221 (Function) & DCC_GET_PENDING,
01222 };
01223
01224 char *transfer_start(Function *global_funcs)
01225 {
01226 global = global_funcs;
01227
01228 fileq = NULL;
01229 module_register(MODULE_NAME, transfer_table, 2, 3);
01230 if (!module_depend(MODULE_NAME, "eggdrop", 106, 0)) {
01231 module_undepend(MODULE_NAME);
01232 return "This module requires Eggdrop 1.6.0 or later.";
01233 }
01234
01235 add_tcl_commands(mytcls);
01236 add_tcl_ints(myints);
01237 add_builtins(H_load, transfer_load);
01238 server_transfer_setup(NULL);
01239 add_help_reference("transfer.help");
01240 H_rcvd = add_bind_table("rcvd", HT_STACKABLE, builtin_sentrcvd);
01241 H_sent = add_bind_table("sent", HT_STACKABLE, builtin_sentrcvd);
01242 H_lost = add_bind_table("lost", HT_STACKABLE, builtin_toutlost);
01243 H_tout = add_bind_table("tout", HT_STACKABLE, builtin_toutlost);
01244
01245 USERENTRY_FSTAT.get = def_get;
01246 add_entry_type(&USERENTRY_FSTAT);
01247 add_lang_section("transfer");
01248 return NULL;
01249 }