transfer.c 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259
  1. /*
  2. * transfer.c -- part of transfer.mod
  3. *
  4. */
  5. /*
  6. * Small code snippets related to REGET/RESEND support were taken from
  7. * BitchX, copyright by panasync.
  8. */
  9. #include "src/common.h"
  10. #include "src/cmds.h"
  11. #include "src/misc_file.h"
  12. #include "src/misc.h"
  13. #include "src/main.h"
  14. #include "src/userrec.h"
  15. #include "src/userent.h"
  16. #include "src/tandem.h"
  17. #include "src/net.h"
  18. #include "src/users.h"
  19. #define MAKING_TRANSFER
  20. #include "transfer.h"
  21. #include "src/mod/share.mod/share.h"
  22. #include "src/mod/update.mod/update.h"
  23. #include <sys/types.h>
  24. #include <sys/stat.h>
  25. #include <netinet/in.h>
  26. #include <arpa/inet.h>
  27. #include <errno.h>
  28. extern int bupdating;
  29. #ifdef HUB
  30. static bool copy_to_tmp = 1; /* Copy files to /tmp before transmitting? */
  31. #endif /* HUB */
  32. static time_t wait_dcc_xfer = 40; /* Timeout time on DCC xfers */
  33. static int dcc_limit = 4; /* Maximum number of simultaneous file
  34. downloads allowed */
  35. static unsigned int dcc_block = 0; /* Size of one dcc block */
  36. static bool quiet_reject = 1; /* Quietly reject dcc chat or sends from
  37. users without access? */
  38. /*
  39. * Prototypes
  40. */
  41. #ifdef HUB
  42. static void wipe_tmp_filename(char *, int);
  43. static int at_limit(char *);
  44. static void dcc_get_pending(int, char *, int);
  45. #endif /* HUB */
  46. static fileq_t *fileq = NULL;
  47. /*
  48. * Misc functions
  49. */
  50. #ifdef HUB
  51. static void wipe_tmp_filename(char *fn, int idx)
  52. {
  53. int i, ok = 1;
  54. if (!copy_to_tmp)
  55. return;
  56. for (i = 0; i < dcc_total; i++)
  57. if (i != idx)
  58. if (dcc[i].type == &DCC_GET || dcc[i].type == &DCC_GET_PENDING)
  59. if (!strcmp(dcc[i].u.xfer->filename, fn)) {
  60. ok = 0;
  61. break;
  62. }
  63. if (ok)
  64. unlink(fn);
  65. }
  66. /* Return true if this user has >= the maximum number of file xfers allowed.
  67. */
  68. static int at_limit(char *nick)
  69. {
  70. int i, x = 0;
  71. for (i = 0; i < dcc_total; i++)
  72. if (dcc[i].type == &DCC_GET || dcc[i].type == &DCC_GET_PENDING)
  73. if (!egg_strcasecmp(dcc[i].nick, nick))
  74. x++;
  75. return (x >= dcc_limit);
  76. }
  77. /* Replaces all spaces with underscores (' ' -> '_'). The returned buffer
  78. * needs to be freed after use.
  79. */
  80. static char *replace_spaces(char *fn)
  81. {
  82. register char *ret = NULL, *p = NULL;
  83. p = ret = strdup(fn);
  84. while ((p = strchr(p, ' ')) != NULL)
  85. *p = '_';
  86. return ret;
  87. }
  88. static void deq_this(fileq_t *thisfile)
  89. {
  90. fileq_t *q = fileq, *last = NULL;
  91. while (q && q != thisfile) {
  92. last = q;
  93. q = q->next;
  94. }
  95. if (!q)
  96. return; /* Bogus ptr */
  97. if (last)
  98. last->next = q->next;
  99. else
  100. fileq = q->next;
  101. free(q->dir);
  102. free(q->file);
  103. free(q);
  104. }
  105. /* Remove all files queued to a certain user.
  106. */
  107. static void flush_fileq(char *to)
  108. {
  109. fileq_t *q = fileq;
  110. int fnd = 1;
  111. while (fnd) {
  112. q = fileq;
  113. fnd = 0;
  114. while (q != NULL) {
  115. if (!egg_strcasecmp(q->to, to)) {
  116. deq_this(q);
  117. q = NULL;
  118. fnd = 1;
  119. }
  120. if (q != NULL)
  121. q = q->next;
  122. }
  123. }
  124. }
  125. static void send_next_file(char *to)
  126. {
  127. fileq_t *q = NULL, *thisfile = NULL;
  128. char *s = NULL, *s1 = NULL;
  129. int x;
  130. for (q = fileq; q; q = q->next)
  131. if (!egg_strcasecmp(q->to, to))
  132. thisfile = q;
  133. if (thisfile == NULL)
  134. return; /* None */
  135. /* Copy this file to /tmp */
  136. if (thisfile->dir[0] == '*') { /* Absolute path */
  137. s = (char *) calloc(1, strlen(&thisfile->dir[1]) + strlen(thisfile->file) + 2);
  138. sprintf(s, "%s/%s", &thisfile->dir[1], thisfile->file);
  139. } else {
  140. char *p = strchr(thisfile->dir, '*');
  141. if (p == NULL) { /* if it's messed up */
  142. send_next_file(to);
  143. return;
  144. }
  145. p++;
  146. s = (char *) calloc(1, strlen(p) + strlen(thisfile->file) + 2);
  147. sprintf(s, "%s%s%s", p, p[0] ? "/" : "", thisfile->file);
  148. strcpy(thisfile->dir, &(p[atoi(thisfile->dir)]));
  149. }
  150. if (copy_to_tmp) {
  151. s1 = (char *) calloc(1, strlen(tempdir) + strlen(thisfile->file) + 1);
  152. sprintf(s1, "%s%s", tempdir, thisfile->file);
  153. if (copyfile(s, s1) != 0) {
  154. putlog(LOG_FILES | LOG_MISC, "*",
  155. TRANSFER_COPY_FAILED,
  156. thisfile->file, tempdir);
  157. dprintf(DP_HELP,
  158. TRANSFER_FILESYS_BROKEN,
  159. thisfile->to);
  160. strcpy(s, thisfile->to);
  161. flush_fileq(s);
  162. free(s1);
  163. free(s);
  164. return;
  165. }
  166. } else {
  167. s1 = strdup(s);
  168. }
  169. if (thisfile->dir[0] == '*') {
  170. s = (char *) realloc(s, strlen(&thisfile->dir[1]) + strlen(thisfile->file) + 2);
  171. sprintf(s, "%s/%s", &thisfile->dir[1], thisfile->file);
  172. } else {
  173. s = (char *) realloc(s, strlen(thisfile->dir) + strlen(thisfile->file) + 2);
  174. sprintf(s, "%s%s%s", thisfile->dir, thisfile->dir[0] ? "/" : "", thisfile->file);
  175. }
  176. x = raw_dcc_send(s1, thisfile->to, thisfile->nick, s);
  177. if (x == DCCSEND_OK) {
  178. if (egg_strcasecmp(thisfile->to, thisfile->nick))
  179. dprintf(DP_HELP, TRANSFER_FILE_ARRIVE, thisfile->to,
  180. thisfile->nick);
  181. deq_this(thisfile);
  182. free(s);
  183. free(s1);
  184. return;
  185. }
  186. wipe_tmp_filename(s1, -1);
  187. if (x == DCCSEND_FULL) {
  188. putlog(LOG_FILES, "*",TRANSFER_LOG_CONFULL, s1, thisfile->nick);
  189. dprintf(DP_HELP,
  190. TRANSFER_NOTICE_CONFULL,
  191. thisfile->to);
  192. strcpy(s, thisfile->to);
  193. flush_fileq(s);
  194. } else if (x == DCCSEND_NOSOCK) {
  195. putlog(LOG_FILES, "*", TRANSFER_LOG_SOCKERR, s1, thisfile->nick);
  196. dprintf(DP_HELP, TRANSFER_NOTICE_SOCKERR,
  197. thisfile->to);
  198. strcpy(s, thisfile->to);
  199. flush_fileq(s);
  200. } else {
  201. if (x == DCCSEND_FEMPTY) {
  202. putlog(LOG_FILES, "*", TRANSFER_LOG_FILEEMPTY, thisfile->file);
  203. dprintf(DP_HELP, TRANSFER_NOTICE_FILEEMPTY,
  204. thisfile->to, thisfile->file);
  205. }
  206. deq_this(thisfile);
  207. }
  208. free(s);
  209. free(s1);
  210. return;
  211. }
  212. /*
  213. * DCC routines
  214. */
  215. /* Instead of reading all data intended to go into the DCC block
  216. * in one go, we read it in PMAX_SIZE chunks, feed it to tputs and
  217. * continue until we get to know that the network buffer only
  218. * buffers the data instead of sending it.
  219. *
  220. * In that case, we delay further sending until we receive the
  221. * dcc outdone event.
  222. *
  223. * Note: To optimize buffer sizes, we default to PMAX_SIZE, but
  224. * allocate a smaller buffer for smaller pending_data sizes.
  225. */
  226. #define PMAX_SIZE 4096
  227. static unsigned long pump_file_to_sock(FILE *file, long sock,
  228. register unsigned long pending_data)
  229. {
  230. const unsigned long buf_len = pending_data >= PMAX_SIZE ?
  231. PMAX_SIZE : pending_data;
  232. char *bf = (char *) calloc(1, buf_len);
  233. register unsigned long actual_size;
  234. if (bf) {
  235. do {
  236. actual_size = pending_data >= buf_len ? buf_len : pending_data;
  237. fread(bf, actual_size, 1, file);
  238. tputs(sock, bf, actual_size);
  239. pending_data -= actual_size;
  240. } while (!sock_has_data(SOCK_DATA_OUTGOING, sock) && pending_data != 0);
  241. free(bf);
  242. }
  243. return pending_data;
  244. }
  245. #endif /* HUB */
  246. void eof_dcc_fork_send(int idx)
  247. {
  248. char s1[121] = "", *s2 = NULL;
  249. fclose(dcc[idx].u.xfer->f);
  250. if (!strcmp(dcc[idx].nick, "*users")) {
  251. int x, y = 0;
  252. for (x = 0; x < dcc_total; x++)
  253. if ((!egg_strcasecmp(dcc[x].nick, dcc[idx].host)) &&
  254. (dcc[x].type->flags & DCT_BOT)) {
  255. y = x;
  256. break;
  257. }
  258. if (y != 0) {
  259. dcc[y].status &= ~STAT_GETTING;
  260. dcc[y].status &= ~STAT_SHARE;
  261. }
  262. putlog(LOG_BOTS, "*", USERF_FAILEDXFER);
  263. unlink(dcc[idx].u.xfer->filename);
  264. } else if (!strcmp(dcc[idx].nick, "*binary")) {
  265. int x, y = 0;
  266. for (x = 0; x < dcc_total; x++)
  267. if ((!egg_strcasecmp(dcc[x].nick, dcc[idx].host)) &&
  268. (dcc[x].type->flags & DCT_BOT)) {
  269. y = x;
  270. break;
  271. }
  272. if (y != 0) {
  273. dcc[y].status &= ~STAT_GETTINGU;
  274. }
  275. putlog(LOG_BOTS, "*", "Failed binary transfer.");
  276. unlink(dcc[idx].u.xfer->filename);
  277. } else {
  278. strcpy(s1, strerror(errno));
  279. if (!quiet_reject)
  280. dprintf(DP_HELP, "NOTICE %s :%s (%s)\n", dcc[idx].nick,
  281. DCC_CONNECTFAILED1, s1);
  282. putlog(LOG_MISC, "*", "%s: SEND %s (%s!%s)", DCC_CONNECTFAILED2,
  283. dcc[idx].u.xfer->origname, dcc[idx].nick, dcc[idx].host);
  284. putlog(LOG_MISC, "*", " (%s)", s1);
  285. s2 = (char *) calloc(1, strlen(tempdir) + strlen(dcc[idx].u.xfer->filename) + 1);
  286. sprintf(s2, "%s%s", tempdir, dcc[idx].u.xfer->filename);
  287. unlink(s2);
  288. free(s2);
  289. }
  290. killsock(dcc[idx].sock);
  291. lostdcc(idx);
  292. }
  293. static void eof_dcc_send(int idx)
  294. {
  295. int ok, j;
  296. char *ofn = NULL, *nfn = NULL, s[1024] = "", *hand = NULL;
  297. struct userrec *u = NULL;
  298. fflush(dcc[idx].u.xfer->f);
  299. fsync(fileno(dcc[idx].u.xfer->f));
  300. fclose(dcc[idx].u.xfer->f);
  301. if (dcc[idx].u.xfer->length == dcc[idx].status) {
  302. int l;
  303. /* Success */
  304. ok = 0;
  305. if (!strcmp(dcc[idx].nick, "*users")) {
  306. finish_share(idx);
  307. killsock(dcc[idx].sock);
  308. lostdcc(idx);
  309. return;
  310. } else if (!strcmp(dcc[idx].nick, "*binary")) {
  311. finish_update(idx);
  312. killsock(dcc[idx].sock);
  313. lostdcc(idx);
  314. return;
  315. }
  316. putlog(LOG_FILES, "*", TRANSFER_COMPLETED_DCC,
  317. dcc[idx].u.xfer->origname, dcc[idx].nick, dcc[idx].host);
  318. egg_snprintf(s, sizeof s, "%s!%s", dcc[idx].nick, dcc[idx].host);
  319. u = get_user_by_host(s);
  320. hand = u ? u->handle : (char *) "*";
  321. l = strlen(dcc[idx].u.xfer->filename);
  322. if (l > NAME_MAX) {
  323. /* The filename is to long... blow it off */
  324. putlog(LOG_FILES, "*",TRANSFER_FILENAME_TOOLONG , l);
  325. dprintf(DP_HELP, TRANSFER_NOTICE_FNTOOLONG,
  326. dcc[idx].nick, l);
  327. putlog(LOG_FILES, "*", TRANSFER_TOO_BAD );
  328. dprintf(DP_HELP, TRANSFER_NOTICE_TOOBAD,
  329. dcc[idx].nick);
  330. killsock(dcc[idx].sock);
  331. lostdcc(idx);
  332. return;
  333. }
  334. /* Move the file from /tmp */
  335. ofn = (char *) calloc(1, strlen(tempdir) + strlen(dcc[idx].u.xfer->filename) + 1);
  336. nfn = (char *) calloc(1, strlen(dcc[idx].u.xfer->dir)
  337. + strlen(dcc[idx].u.xfer->origname) + 1);
  338. sprintf(ofn, "%s%s", tempdir, dcc[idx].u.xfer->filename);
  339. sprintf(nfn, "%s%s", dcc[idx].u.xfer->dir, dcc[idx].u.xfer->origname);
  340. if (movefile(ofn, nfn))
  341. putlog(LOG_MISC | LOG_FILES, "*", TRANSFER_FAILED_MOVE, nfn, ofn);
  342. free(ofn);
  343. free(nfn);
  344. for (j = 0; j < dcc_total; j++)
  345. if (!ok && (dcc[j].type->flags & (DCT_GETNOTES)) &&
  346. !egg_strcasecmp(dcc[j].nick, hand)) {
  347. ok = 1;
  348. dprintf(j,TRANSFER_THANKS);
  349. }
  350. if (!ok)
  351. dprintf(DP_HELP,TRANSFER_NOTICE_THANKS,
  352. dcc[idx].nick);
  353. killsock(dcc[idx].sock);
  354. lostdcc(idx);
  355. return;
  356. }
  357. /* Failure :( */
  358. if (!strcmp(dcc[idx].nick, "*users")) {
  359. int x, y = 0;
  360. for (x = 0; x < dcc_total; x++)
  361. if ((!egg_strcasecmp(dcc[x].nick, dcc[idx].host)) &&
  362. (dcc[x].type->flags & DCT_BOT))
  363. y = x;
  364. if (y) {
  365. putlog(LOG_BOTS, "*",TRANSFER_USERFILE_LOST, dcc[y].nick);
  366. unlink(dcc[idx].u.xfer->filename);
  367. /* Drop that bot */
  368. dprintf(y, "bye\n");
  369. egg_snprintf(s, sizeof s,TRANSFER_USERFILE_DISCON, dcc[y].nick);
  370. botnet_send_unlinked(y, dcc[y].nick, s);
  371. chatout("*** %s %s\n", dcc[y].nick, s);
  372. if (y < idx) {
  373. int t = y;
  374. y = idx;
  375. idx = t;
  376. }
  377. if (y != idx) {
  378. killsock(dcc[y].sock);
  379. lostdcc(y);
  380. }
  381. killsock(dcc[idx].sock);
  382. lostdcc(idx);
  383. }
  384. } else if (!strcmp(dcc[idx].nick, "*binary")) {
  385. int x, y = 0;
  386. for (x = 0; x < dcc_total; x++)
  387. if ((!egg_strcasecmp(dcc[x].nick, dcc[idx].host)) &&
  388. (dcc[x].type->flags & DCT_BOT))
  389. y = x;
  390. if (y) {
  391. putlog(LOG_BOTS, "*", "Lost binary transfer from %s; aborting.", dcc[y].nick);
  392. unlink(dcc[idx].u.xfer->filename);
  393. /* Drop that bot
  394. dprintf(y, "bye\n");
  395. egg_snprintf(s, sizeof s,"Disconnected %s (aborted binary transfer)", dcc[y].nick);
  396. botnet_send_unlinked(y, dcc[y].nick, s);
  397. chatout("*** %s\n", dcc[y].nick, s);
  398. if (y != idx) {
  399. killsock(dcc[y].sock);
  400. lostdcc(y);
  401. }
  402. */
  403. killsock(dcc[idx].sock);
  404. lostdcc(idx);
  405. }
  406. } else {
  407. putlog(LOG_FILES, "*",TRANSFER_LOST_DCCSEND,
  408. dcc[idx].u.xfer->origname, dcc[idx].nick, dcc[idx].host,
  409. dcc[idx].status, dcc[idx].u.xfer->length);
  410. ofn = (char *) calloc(1, strlen(tempdir) + strlen(dcc[idx].u.xfer->filename) + 1);
  411. sprintf(ofn, "%s%s", tempdir, dcc[idx].u.xfer->filename);
  412. unlink(ofn);
  413. free(ofn);
  414. killsock(dcc[idx].sock);
  415. lostdcc(idx);
  416. }
  417. }
  418. #ifdef HUB
  419. /* Determine byte order. Used for resend DCC startup packets.
  420. */
  421. static inline u_8bit_t byte_order_test(void)
  422. {
  423. u_16bit_t test = TRANSFER_REGET_PACKETID;
  424. if (*((u_8bit_t *)&test) == ((TRANSFER_REGET_PACKETID & 0xff00) >> 8))
  425. return 0;
  426. if (*((u_8bit_t *)&test) == (TRANSFER_REGET_PACKETID & 0x00ff))
  427. return 1;
  428. return 0;
  429. }
  430. /* Parse and handle resend DCC startup packets.
  431. */
  432. inline static void handle_resend_packet(int idx, transfer_reget *reget_data)
  433. {
  434. if (byte_order_test() != reget_data->byte_order) {
  435. /* The sender's byte order does not match our's so we need to switch the
  436. * bytes first, before we can make use of them.
  437. */
  438. reget_data->packet_id = ((reget_data->packet_id & 0x00ff) << 8) |
  439. ((reget_data->packet_id & 0xff00) >> 8);
  440. reget_data->byte_offset = ((reget_data->byte_offset & 0xff000000) >> 24) |
  441. ((reget_data->byte_offset & 0x00ff0000) >> 8) |
  442. ((reget_data->byte_offset & 0x0000ff00) << 8) |
  443. ((reget_data->byte_offset & 0x000000ff) << 24);
  444. }
  445. if (reget_data->packet_id != TRANSFER_REGET_PACKETID)
  446. putlog(LOG_FILES, "*", TRANSFER_REGET_PACKET,
  447. dcc[idx].nick, dcc[idx].u.xfer->origname);
  448. else
  449. dcc[idx].u.xfer->offset = reget_data->byte_offset;
  450. dcc[idx].u.xfer->type = XFER_RESEND;
  451. }
  452. /* Handles DCC packets the client sends us. As soon as the last sent dcc
  453. * block is fully acknowledged we send the next block.
  454. *
  455. * Note: The first received packet during reget is a special 8 bit packet
  456. * containing special information.
  457. */
  458. void dcc_get(int idx, char *buf, int len)
  459. {
  460. char xnick[NICKLEN] = "";
  461. unsigned char bbuf[4] = "";
  462. unsigned long cmp, l;
  463. int w = len + dcc[idx].u.xfer->sofar, p = 0;
  464. dcc[idx].timeval = now; /* Mark as active */
  465. /* Add bytes to our buffer if we don't have a complete response yet.
  466. * This is either a 4 bit ack or the 8 bit reget packet.
  467. */
  468. if (w < 4 ||
  469. (w < 8 && dcc[idx].u.xfer->type == XFER_RESEND_PEND)) {
  470. egg_memcpy(&(dcc[idx].u.xfer->buf[dcc[idx].u.xfer->sofar]), buf, len);
  471. dcc[idx].u.xfer->sofar += len;
  472. return;
  473. /* Waiting for the 8 bit reget packet? */
  474. } else if (dcc[idx].u.xfer->type == XFER_RESEND_PEND) {
  475. /* The 8 bit packet is complete now. Parse it. */
  476. if (w == 8) {
  477. transfer_reget reget_data;
  478. egg_memcpy(&reget_data, dcc[idx].u.xfer->buf, dcc[idx].u.xfer->sofar);
  479. egg_memcpy(&reget_data + dcc[idx].u.xfer->sofar, buf, len);
  480. handle_resend_packet(idx, &reget_data);
  481. cmp = dcc[idx].u.xfer->offset;
  482. } else
  483. return;
  484. /* Fall through! */
  485. /* No, only want 4 bit ack responses. */
  486. } else {
  487. /* Complete packet? */
  488. if (w == 4) {
  489. egg_memcpy(bbuf, dcc[idx].u.xfer->buf, dcc[idx].u.xfer->sofar);
  490. egg_memcpy(&(bbuf[dcc[idx].u.xfer->sofar]), buf, len);
  491. } else {
  492. p = ((w - 1) & ~3) - dcc[idx].u.xfer->sofar;
  493. w = w - ((w - 1) & ~3);
  494. if (w < 4) {
  495. egg_memcpy(dcc[idx].u.xfer->buf, &(buf[p]), w);
  496. return;
  497. }
  498. egg_memcpy(bbuf, &(buf[p]), w);
  499. }
  500. /* This is more compatible than ntohl for machines where an int
  501. * is more than 4 bytes:
  502. */
  503. cmp = ((unsigned int) (bbuf[0]) << 24) +
  504. ((unsigned int) (bbuf[1]) << 16) +
  505. ((unsigned int) (bbuf[2]) << 8) + bbuf[3];
  506. dcc[idx].u.xfer->acked = cmp;
  507. }
  508. dcc[idx].u.xfer->sofar = 0;
  509. if (cmp > dcc[idx].u.xfer->length && cmp > dcc[idx].status) {
  510. /* Attempt to resume, but file is not as long as requested... */
  511. putlog(LOG_FILES, "*",
  512. TRANSFER_BEHIND_FILEEND,
  513. dcc[idx].u.xfer->origname, dcc[idx].nick);
  514. } else if (cmp > dcc[idx].status) {
  515. /* Attempt to resume */
  516. if (!strcmp(dcc[idx].nick, "*users")) {
  517. putlog(LOG_BOTS, "*", TRANSFER_TRY_SKIP_AHEAD);
  518. } else if (!strcmp(dcc[idx].nick, "*binary")) {
  519. putlog(LOG_BOTS, "*","!!! Trying to skip ahead on binary transfer");
  520. } else {
  521. fseek(dcc[idx].u.xfer->f, cmp, SEEK_SET);
  522. dcc[idx].status = cmp;
  523. putlog(LOG_FILES, "*",TRANSFER_RESUME_FILE,
  524. (int) (cmp / 1024), dcc[idx].u.xfer->origname,
  525. dcc[idx].nick);
  526. }
  527. } else {
  528. if (dcc[idx].u.xfer->ack_type == XFER_ACK_UNKNOWN) {
  529. if (cmp < dcc[idx].u.xfer->offset)
  530. /* If we don't start at the top of the file, some clients only tell
  531. * us the really received bytes (e.g. bitchx). This seems to be the
  532. * case here.
  533. */
  534. dcc[idx].u.xfer->ack_type = XFER_ACK_WITHOUT_OFFSET;
  535. else
  536. dcc[idx].u.xfer->ack_type = XFER_ACK_WITH_OFFSET;
  537. }
  538. if (dcc[idx].u.xfer->ack_type == XFER_ACK_WITHOUT_OFFSET)
  539. cmp += dcc[idx].u.xfer->offset;
  540. }
  541. if (cmp != dcc[idx].status)
  542. return;
  543. if (dcc[idx].status == dcc[idx].u.xfer->length) {
  544. /* Successful send, we are done */
  545. killsock(dcc[idx].sock);
  546. fclose(dcc[idx].u.xfer->f);
  547. if (!strcmp(dcc[idx].nick, "*users")) {
  548. int x, y = 0;
  549. for (x = 0; x < dcc_total; x++)
  550. if (!egg_strcasecmp(dcc[x].nick, dcc[idx].host) &&
  551. (dcc[x].type->flags & DCT_BOT))
  552. y = x;
  553. if (y != 0)
  554. dcc[y].status &= ~STAT_SENDING;
  555. putlog(LOG_BOTS, "*", TRANSFER_COMPLETED_USERFILE, dcc[y].nick);
  556. unlink(dcc[idx].u.xfer->filename);
  557. /* Any sharebot things that were queued: */
  558. dprintf(y, "s !\n");
  559. xnick[0] = 0;
  560. } else if (!strcmp(dcc[idx].nick, "*binary")) {
  561. int x, y = 0;
  562. for (x = 0; x < dcc_total; x++)
  563. if (!egg_strcasecmp(dcc[x].nick, dcc[idx].host) &&
  564. (dcc[x].type->flags & DCT_BOT))
  565. y = x;
  566. if (y != 0) {
  567. dcc[y].status &= ~STAT_SENDINGU;
  568. dcc[y].status |= STAT_UPDATED;
  569. }
  570. putlog(LOG_BOTS, "*", "Completed binary file send to %s", dcc[y].nick);
  571. xnick[0] = 0;
  572. #ifdef HUB
  573. bupdating = 0;
  574. #endif
  575. } else {
  576. /* Download is credited to the user who requested it
  577. * (not the user who actually received it)
  578. */
  579. putlog(LOG_FILES, "*",TRANSFER_FINISHED_DCCSEND, dcc[idx].u.xfer->origname, dcc[idx].nick);
  580. wipe_tmp_filename(dcc[idx].u.xfer->filename, idx);
  581. strcpy((char *) xnick, dcc[idx].nick);
  582. }
  583. lostdcc(idx);
  584. /* Any to dequeue? */
  585. if (!at_limit(xnick))
  586. send_next_file(xnick);
  587. return;
  588. }
  589. /* Note: No fseek() needed here, because the file position is kept from
  590. * the last run.
  591. */
  592. l = dcc_block;
  593. if (l == 0 || dcc[idx].status + l > dcc[idx].u.xfer->length)
  594. l = dcc[idx].u.xfer->length - dcc[idx].status;
  595. dcc[idx].u.xfer->block_pending = pump_file_to_sock(dcc[idx].u.xfer->f, dcc[idx].sock, l);
  596. dcc[idx].status += l;
  597. }
  598. void eof_dcc_get(int idx)
  599. {
  600. char xnick[NICKLEN] = "", s[1024] = "";
  601. fclose(dcc[idx].u.xfer->f);
  602. if (!strcmp(dcc[idx].nick, "*users")) {
  603. int x, y = 0;
  604. for (x = 0; x < dcc_total; x++)
  605. if (!egg_strcasecmp(dcc[x].nick, dcc[idx].host) &&
  606. (dcc[x].type->flags & DCT_BOT))
  607. y = x;
  608. putlog(LOG_BOTS, "*", TRANSFER_ABORT_USERFILE);
  609. /* Note: no need to unlink the xfer file, as it's already unlinked. */
  610. xnick[0] = 0;
  611. /* Drop that bot */
  612. dprintf(-dcc[y].sock, "bye\n");
  613. egg_snprintf(s, sizeof s, TRANSFER_USERFILE_DISCON,
  614. dcc[y].nick);
  615. botnet_send_unlinked(y, dcc[y].nick, s);
  616. chatout("*** %s\n", s);
  617. if (y != idx) {
  618. killsock(dcc[y].sock);
  619. lostdcc(y);
  620. }
  621. if (dcc[idx].sock != -1)
  622. killsock(dcc[idx].sock);
  623. lostdcc(idx);
  624. return;
  625. } else if (!strcmp(dcc[idx].nick, "*binary")) {
  626. int x, y = 0;
  627. for (x = 0; x < dcc_total; x++)
  628. if (!egg_strcasecmp(dcc[x].nick, dcc[idx].host) &&
  629. (dcc[x].type->flags & DCT_BOT))
  630. y = x;
  631. putlog(LOG_BOTS, "*", "Lost binary transfer; aborting.");
  632. /* Note: no need to unlink the xfer file, as it's already unlinked. */
  633. xnick[0] = 0;
  634. /* Drop that bot */
  635. dcc[y].status &= ~STAT_SENDINGU;
  636. #ifdef HUB
  637. bupdating = 0;
  638. #endif
  639. /*
  640. dprintf(-dcc[y].sock, "bye\n");
  641. egg_snprintf(s, sizeof s, "Disconnected %s (aborted binary transfer)",
  642. dcc[y].nick);
  643. botnet_send_unlinked(y, dcc[y].nick, s);
  644. chatout("*** %s\n", s);
  645. if (y != idx) {
  646. killsock(dcc[y].sock);
  647. lostdcc(y);
  648. }
  649. */
  650. killsock(dcc[idx].sock);
  651. lostdcc(idx);
  652. return;
  653. } else {
  654. /* Call `lost' DCC trigger now.
  655. */
  656. putlog(LOG_FILES, "*",TRANSFER_LOST_DCCGET,
  657. dcc[idx].u.xfer->origname, dcc[idx].nick, dcc[idx].host);
  658. wipe_tmp_filename(dcc[idx].u.xfer->filename, idx);
  659. strcpy(xnick, dcc[idx].nick);
  660. }
  661. killsock(dcc[idx].sock);
  662. lostdcc(idx);
  663. /* Send next queued file if there is one */
  664. if (!at_limit(xnick))
  665. send_next_file(xnick);
  666. }
  667. #endif /* HUB */
  668. void dcc_send(int idx, char *buf, int len)
  669. {
  670. char s[SGRAB + 2] = "", *b = NULL;
  671. unsigned long sent;
  672. fwrite(buf, len, 1, dcc[idx].u.xfer->f);
  673. fflush(dcc[idx].u.xfer->f);
  674. fsync(fileno(dcc[idx].u.xfer->f));
  675. dcc[idx].status += len;
  676. /* Put in network byte order */
  677. sent = dcc[idx].status;
  678. s[0] = (sent / (1 << 24));
  679. s[1] = (sent % (1 << 24)) / (1 << 16);
  680. s[2] = (sent % (1 << 16)) / (1 << 8);
  681. s[3] = (sent % (1 << 8));
  682. tputs(dcc[idx].sock, s, 4);
  683. dcc[idx].timeval = now;
  684. if (dcc[idx].status > dcc[idx].u.xfer->length &&
  685. dcc[idx].u.xfer->length > 0) {
  686. dprintf(DP_HELP,TRANSFER_BOGUS_FILE_LENGTH, dcc[idx].nick);
  687. putlog(LOG_FILES, "*",
  688. TRANSFER_FILE_TOO_LONG,
  689. dcc[idx].u.xfer->origname, dcc[idx].nick, dcc[idx].host);
  690. fclose(dcc[idx].u.xfer->f);
  691. b = (char *) calloc(1, strlen(tempdir) + strlen(dcc[idx].u.xfer->filename) + 1);
  692. sprintf(b, "%s%s", tempdir, dcc[idx].u.xfer->filename);
  693. unlink(b);
  694. free(b);
  695. killsock(dcc[idx].sock);
  696. lostdcc(idx);
  697. }
  698. }
  699. #ifdef HUB
  700. static void transfer_get_timeout(int i)
  701. {
  702. char xx[1024] = "";
  703. fclose(dcc[i].u.xfer->f);
  704. if (strcmp(dcc[i].nick, "*users") == 0) {
  705. int x, y = 0;
  706. for (x = 0; x < dcc_total; x++)
  707. if ((!egg_strcasecmp(dcc[x].nick, dcc[i].host)) &&
  708. (dcc[x].type->flags & DCT_BOT))
  709. y = x;
  710. if (y != 0) {
  711. dcc[y].status &= ~STAT_SENDING;
  712. dcc[y].status &= ~STAT_SHARE;
  713. }
  714. unlink(dcc[i].u.xfer->filename);
  715. putlog(LOG_BOTS, "*",TRANSFER_USERFILE_TIMEOUT);
  716. dprintf(y, "bye\n");
  717. egg_snprintf(xx, sizeof xx,TRANSFER_DICONNECT_TIMEOUT,
  718. dcc[y].nick);
  719. botnet_send_unlinked(y, dcc[y].nick, xx);
  720. chatout("*** %s\n", xx);
  721. if (y < i) {
  722. int t = y;
  723. y = i;
  724. i = t;
  725. }
  726. killsock(dcc[y].sock);
  727. lostdcc(y);
  728. xx[0] = 0;
  729. } else if (strcmp(dcc[i].nick, "*binary") == 0) {
  730. int x, y = 0;
  731. for (x = 0; x < dcc_total; x++)
  732. if ((!egg_strcasecmp(dcc[x].nick, dcc[i].host)) &&
  733. (dcc[x].type->flags & DCT_BOT))
  734. y = x;
  735. if (y != 0) {
  736. dcc[y].status &= ~STAT_SENDINGU;
  737. }
  738. putlog(LOG_BOTS, "*","Timeout on binary transfer.");
  739. dprintf(y, "bye\n");
  740. egg_snprintf(xx, sizeof xx,"Disconnected %s (timed-out binary transfer)",
  741. dcc[y].nick);
  742. botnet_send_unlinked(y, dcc[y].nick, xx);
  743. chatout("*** %s\n", xx);
  744. if (y < i) {
  745. int t = y;
  746. y = i;
  747. i = t;
  748. }
  749. killsock(dcc[y].sock);
  750. lostdcc(y);
  751. xx[0] = 0;
  752. } else {
  753. char *p = NULL;
  754. p = strrchr(dcc[i].u.xfer->origname, '/');
  755. dprintf(DP_HELP, TRANSFER_NOTICE_TIMEOUT,
  756. dcc[i].nick, p ? p + 1 : dcc[i].u.xfer->origname);
  757. /* Call DCC `timeout' trigger now.
  758. */
  759. putlog(LOG_FILES, "*",TRANSFER_DCC_GET_TIMEOUT,
  760. p ? p + 1 : dcc[i].u.xfer->origname, dcc[i].nick, dcc[i].status,
  761. dcc[i].u.xfer->length);
  762. wipe_tmp_filename(dcc[i].u.xfer->filename, i);
  763. strcpy(xx, dcc[i].nick);
  764. }
  765. killsock(dcc[i].sock);
  766. lostdcc(i);
  767. if (!at_limit(xx))
  768. send_next_file(xx);
  769. }
  770. #endif /* HUB */
  771. void tout_dcc_send(int idx)
  772. {
  773. if (!strcmp(dcc[idx].nick, "*users")) {
  774. int x, y = 0;
  775. for (x = 0; x < dcc_total; x++)
  776. if (!egg_strcasecmp(dcc[x].nick, dcc[idx].host) &&
  777. (dcc[x].type->flags & DCT_BOT))
  778. y = x;
  779. if (y != 0) {
  780. dcc[y].status &= ~STAT_GETTING;
  781. dcc[y].status &= ~STAT_SHARE;
  782. }
  783. unlink(dcc[idx].u.xfer->filename);
  784. putlog(LOG_BOTS, "*", TRANSFER_USERFILE_TIMEOUT);
  785. } else if (!strcmp(dcc[idx].nick, "*binary")) {
  786. int x, y = 0;
  787. for (x = 0; x < dcc_total; x++)
  788. if (!egg_strcasecmp(dcc[x].nick, dcc[idx].host) &&
  789. (dcc[x].type->flags & DCT_BOT))
  790. y = x;
  791. if (y != 0) {
  792. dcc[y].status &= ~STAT_GETTINGU;
  793. }
  794. putlog(LOG_BOTS, "*", "Timeout on binary transfer.");
  795. } else {
  796. char *buf = NULL;
  797. dprintf(DP_HELP,TRANSFER_NOTICE_TIMEOUT,
  798. dcc[idx].nick, dcc[idx].u.xfer->origname);
  799. putlog(LOG_FILES, "*",TRANSFER_DCC_SEND_TIMEOUT,
  800. dcc[idx].u.xfer->origname, dcc[idx].nick, dcc[idx].status,
  801. dcc[idx].u.xfer->length);
  802. buf = (char *) calloc(1, strlen(tempdir) + strlen(dcc[idx].u.xfer->filename) + 1);
  803. sprintf(buf, "%s%s", tempdir, dcc[idx].u.xfer->filename);
  804. unlink(buf);
  805. free(buf);
  806. }
  807. killsock(dcc[idx].sock);
  808. lostdcc(idx);
  809. }
  810. #ifdef HUB
  811. void display_dcc_get(int idx, char *buf)
  812. {
  813. if (dcc[idx].status == dcc[idx].u.xfer->length)
  814. sprintf(buf, TRANSFER_SEND, dcc[idx].u.xfer->acked,
  815. dcc[idx].u.xfer->length, dcc[idx].u.xfer->origname);
  816. else
  817. sprintf(buf,TRANSFER_SEND, dcc[idx].status,
  818. dcc[idx].u.xfer->length, dcc[idx].u.xfer->origname);
  819. }
  820. void display_dcc_get_p(int idx, char *buf)
  821. {
  822. sprintf(buf,TRANSFER_SEND_WAITED, now - dcc[idx].timeval, dcc[idx].u.xfer->origname);
  823. }
  824. #endif /* HUB */
  825. void display_dcc_send(int idx, char *buf)
  826. {
  827. sprintf(buf,TRANSFER_SEND, dcc[idx].status,
  828. dcc[idx].u.xfer->length, dcc[idx].u.xfer->origname);
  829. }
  830. void display_dcc_fork_send(int idx, char *buf)
  831. {
  832. sprintf(buf, TRANSFER_CONN_SEND);
  833. }
  834. void kill_dcc_xfer(int idx, void *x)
  835. {
  836. register struct xfer_info *p = (struct xfer_info *) x;
  837. if (p->filename)
  838. free(p->filename);
  839. /* We need to check if origname points to filename before
  840. * attempting to free the memory.
  841. */
  842. if (p->origname && p->origname != p->filename)
  843. free(p->origname);
  844. free(x);
  845. }
  846. void out_dcc_xfer(int idx, char *buf, void *x)
  847. {
  848. }
  849. #ifdef HUB
  850. static void outdone_dcc_xfer(int idx)
  851. {
  852. if (dcc[idx].u.xfer->block_pending)
  853. dcc[idx].u.xfer->block_pending =
  854. pump_file_to_sock(dcc[idx].u.xfer->f, dcc[idx].sock,
  855. dcc[idx].u.xfer->block_pending);
  856. }
  857. #endif /* HUB */
  858. struct dcc_table DCC_SEND =
  859. {
  860. "SEND",
  861. DCT_FILETRAN | DCT_FILESEND | DCT_VALIDIDX,
  862. eof_dcc_send,
  863. dcc_send,
  864. &wait_dcc_xfer,
  865. tout_dcc_send,
  866. display_dcc_send,
  867. kill_dcc_xfer,
  868. out_dcc_xfer,
  869. NULL
  870. };
  871. void dcc_fork_send(int idx, char *x, int y);
  872. struct dcc_table DCC_FORK_SEND =
  873. {
  874. "FORK_SEND",
  875. DCT_FILETRAN | DCT_FORKTYPE | DCT_FILESEND | DCT_VALIDIDX,
  876. eof_dcc_fork_send,
  877. dcc_fork_send,
  878. &wait_dcc_xfer,
  879. eof_dcc_fork_send,
  880. display_dcc_fork_send,
  881. kill_dcc_xfer,
  882. out_dcc_xfer,
  883. NULL
  884. };
  885. void dcc_fork_send(int idx, char *x, int y)
  886. {
  887. if (dcc[idx].type != &DCC_FORK_SEND)
  888. return;
  889. char s1[121] = "";
  890. dcc[idx].type = &DCC_SEND;
  891. dcc[idx].status = 0;
  892. dcc[idx].u.xfer->start_time = now;
  893. egg_snprintf(s1, sizeof s1, "%s!%s", dcc[idx].nick, dcc[idx].host);
  894. if (strcmp(dcc[idx].nick, "*users") && strcmp(dcc[idx].nick, "*binary"))
  895. putlog(LOG_MISC, "*", TRANSFER_DCC_CONN, dcc[idx].u.xfer->origname, s1);
  896. }
  897. #ifdef HUB
  898. struct dcc_table DCC_GET =
  899. {
  900. "GET",
  901. DCT_FILETRAN | DCT_VALIDIDX,
  902. eof_dcc_get,
  903. dcc_get,
  904. &wait_dcc_xfer,
  905. transfer_get_timeout,
  906. display_dcc_get,
  907. kill_dcc_xfer,
  908. out_dcc_xfer,
  909. outdone_dcc_xfer,
  910. };
  911. struct dcc_table DCC_GET_PENDING =
  912. {
  913. "GET_PENDING",
  914. DCT_FILETRAN | DCT_VALIDIDX,
  915. eof_dcc_get,
  916. dcc_get_pending,
  917. &wait_dcc_xfer,
  918. transfer_get_timeout,
  919. display_dcc_get_p,
  920. kill_dcc_xfer,
  921. out_dcc_xfer,
  922. NULL
  923. };
  924. static void dcc_get_pending(int idx, char *buf, int len)
  925. {
  926. in_addr_t ip;
  927. port_t port;
  928. int i;
  929. char s[UHOSTLEN] = "";
  930. i = answer(dcc[idx].sock, s, &ip, &port, 1);
  931. killsock(dcc[idx].sock);
  932. dcc[idx].sock = i;
  933. dcc[idx].addr = ip;
  934. dcc[idx].port = (int) port;
  935. if (dcc[idx].sock == -1) {
  936. dprintf(DP_HELP, TRANSFER_NOTICE_BAD_CONN, dcc[idx].nick, strerror(errno));
  937. putlog(LOG_FILES, "*", TRANSFER_LOG_BAD_CONN,
  938. dcc[idx].u.xfer->origname, dcc[idx].nick, dcc[idx].host);
  939. fclose(dcc[idx].u.xfer->f);
  940. lostdcc(idx);
  941. return;
  942. }
  943. dcc[idx].type = &DCC_GET;
  944. dcc[idx].u.xfer->ack_type = XFER_ACK_UNKNOWN;
  945. /*
  946. * Note: The file was already opened and dcc[idx].u.xfer->f may be
  947. * used immediately. Leave it opened until the file transfer
  948. * is complete.
  949. */
  950. /* Are we resuming? */
  951. if (dcc[idx].u.xfer->type == XFER_RESUME_PEND) {
  952. long unsigned int l;
  953. if (dcc_block == 0 || dcc[idx].u.xfer->length < dcc_block) {
  954. l = dcc[idx].u.xfer->length - dcc[idx].u.xfer->offset;
  955. dcc[idx].status = dcc[idx].u.xfer->length;
  956. } else {
  957. l = dcc_block;
  958. dcc[idx].status = dcc[idx].u.xfer->offset + dcc_block;
  959. }
  960. /* Seek forward ... */
  961. fseek(dcc[idx].u.xfer->f, dcc[idx].u.xfer->offset, SEEK_SET);
  962. dcc[idx].u.xfer->block_pending = pump_file_to_sock(dcc[idx].u.xfer->f,
  963. dcc[idx].sock, l);
  964. dcc[idx].u.xfer->type = XFER_RESUME;
  965. } else {
  966. dcc[idx].u.xfer->offset = 0;
  967. /* If we're resending the data, wait for the client's response first,
  968. * before sending anything ourself.
  969. */
  970. if (dcc[idx].u.xfer->type != XFER_RESEND_PEND) {
  971. if (dcc_block == 0 || dcc[idx].u.xfer->length < dcc_block)
  972. dcc[idx].status = dcc[idx].u.xfer->length;
  973. else
  974. dcc[idx].status = dcc_block;
  975. dcc[idx].u.xfer->block_pending = pump_file_to_sock(dcc[idx].u.xfer->f,
  976. dcc[idx].sock,
  977. dcc[idx].status);
  978. } else
  979. dcc[idx].status = 0;
  980. }
  981. dcc[idx].timeval = dcc[idx].u.xfer->start_time = now;
  982. }
  983. /* Starts a new DCC SEND or DCC RESEND connection to `nick', transferring
  984. * `filename' from `dir'.
  985. *
  986. * Use raw_dcc_resend() and raw_dcc_send() instead of this function.
  987. */
  988. static int raw_dcc_resend_send(char *filename, char *nick, char *from, char *dir, int resend)
  989. {
  990. int zz = -1;
  991. int i;
  992. port_t port;
  993. char *nfn = NULL, *buf = NULL;
  994. long dccfilesize;
  995. FILE *f = NULL, *dccfile = NULL;
  996. sdprintf("raw_dcc_resend_send()");
  997. dccfile = fopen(filename, "rb");
  998. if (!dccfile) {
  999. putlog(LOG_MISC, "*", "Failed to open %s: %s", filename, strerror(errno));
  1000. return DCCSEND_FEMPTY;
  1001. }
  1002. fseek(dccfile, 0, SEEK_END);
  1003. dccfilesize = ftell(dccfile);
  1004. fclose(dccfile);
  1005. /* File empty?! */
  1006. if (dccfilesize == 0)
  1007. return DCCSEND_FEMPTY;
  1008. if (conf.portmin > 0 && conf.portmin < conf.portmax) {
  1009. for (port = conf.portmin; port <= conf.portmax; port++)
  1010. #ifdef USE_IPV6
  1011. if ((zz = open_listen_by_af(&port, AF_INET)) != -1) /* no idea how we want to handle this -poptix 02/03/03 */
  1012. #else
  1013. if ((zz = open_listen(&port)) != -1)
  1014. #endif /* USE_IPV6 */
  1015. break;
  1016. } else {
  1017. port = conf.portmin;
  1018. #ifdef USE_IPV6
  1019. zz = open_listen_by_af(&port, AF_INET);
  1020. #else
  1021. zz = open_listen(&port);
  1022. #endif /* USE_IPV6 */
  1023. }
  1024. if (zz == (-1))
  1025. return DCCSEND_NOSOCK;
  1026. nfn = strrchr(dir, '/');
  1027. if (nfn == NULL)
  1028. nfn = dir;
  1029. else
  1030. nfn++;
  1031. f = fopen(filename, "rb");
  1032. if (!f)
  1033. return DCCSEND_BADFN;
  1034. if ((i = new_dcc(&DCC_GET_PENDING, sizeof(struct xfer_info))) == -1)
  1035. return DCCSEND_FULL;
  1036. dcc[i].sock = zz;
  1037. dcc[i].addr = (in_addr_t) (-559026163);
  1038. dcc[i].port = port;
  1039. strcpy(dcc[i].nick, nick);
  1040. strcpy(dcc[i].host, "irc");
  1041. dcc[i].u.xfer->filename = (char *) calloc(1, strlen(filename) + 1);
  1042. strcpy(dcc[i].u.xfer->filename, filename);
  1043. if (strchr(nfn, ' '))
  1044. nfn = buf = replace_spaces(nfn);
  1045. dcc[i].u.xfer->origname = (char *) calloc(1, strlen(nfn) + 1);
  1046. strcpy(dcc[i].u.xfer->origname, nfn);
  1047. strncpyz(dcc[i].u.xfer->from, from, NICKLEN);
  1048. strncpyz(dcc[i].u.xfer->dir, dir, DIRLEN);
  1049. dcc[i].u.xfer->length = dccfilesize;
  1050. dcc[i].timeval = now;
  1051. dcc[i].u.xfer->f = f;
  1052. dcc[i].u.xfer->type = resend ? XFER_RESEND_PEND : XFER_SEND;
  1053. if (nick[0] != '*') {
  1054. dprintf(DP_HELP, "PRIVMSG %s :\001DCC %sSEND %s %lu %d %lu\001\n", nick,
  1055. resend ? "RE" : "", nfn, iptolong(getmyip()), port, dccfilesize);
  1056. putlog(LOG_FILES, "*",TRANSFER_BEGIN_DCC, resend ? TRANSFER_RE : "",
  1057. nfn, nick);
  1058. }
  1059. if (buf)
  1060. free(buf);
  1061. return DCCSEND_OK;
  1062. }
  1063. /* Starts a DCC RESEND connection.
  1064. */
  1065. /*
  1066. static int raw_dcc_resend(char *filename, char *nick, char *from, char *dir)
  1067. {
  1068. return raw_dcc_resend_send(filename, nick, from, dir, 1);
  1069. }
  1070. */
  1071. /* Starts a DCC_SEND connection.
  1072. */
  1073. int raw_dcc_send(char *filename, char *nick, char *from, char *dir)
  1074. {
  1075. return raw_dcc_resend_send(filename, nick, from, dir, 0);
  1076. }
  1077. #endif /* HUB */
  1078. #ifdef LEAF
  1079. /*
  1080. * CTCP functions
  1081. */
  1082. /* This handles DCC RESUME requests.
  1083. */
  1084. /* NOT EVEN USED :D
  1085. static int ctcp_DCC_RESUME(char *nick, char *from, char *handle, char *object, char *keyword, char *text)
  1086. {
  1087. char *action = NULL, *fn = NULL, buf[SGRAB + 2] = "", *msg = buf;
  1088. int i, port;
  1089. unsigned long offset;
  1090. strcpy(msg, text);
  1091. action = newsplit(&msg);
  1092. if (egg_strcasecmp(action, "RESUME"))
  1093. return BIND_RET_LOG;
  1094. fn = newsplit(&msg);
  1095. port = atoi(newsplit(&msg));
  1096. offset = my_atoul(newsplit(&msg));
  1097. // Search for existing SEND
  1098. for (i = 0; i < dcc_total; i++)
  1099. if ((dcc[i].type == &DCC_GET_PENDING) &&
  1100. (!rfc_casecmp(dcc[i].nick, nick)) && (dcc[i].port == port))
  1101. break;
  1102. // No matching transfer found?
  1103. if (i == dcc_total)
  1104. return BIND_RET_LOG;
  1105. if (dcc[i].u.xfer->length <= offset) {
  1106. char *p = strrchr(dcc[i].u.xfer->origname, '/');
  1107. dprintf(DP_HELP,TRANSFER_DCC_IGNORED, nick, p ? p + 1 : dcc[i].u.xfer->origname);
  1108. return BIND_RET_LOG;
  1109. }
  1110. dcc[i].u.xfer->type = XFER_RESUME_PEND;
  1111. dcc[i].u.xfer->offset = offset;
  1112. dprintf(DP_HELP, "PRIVMSG %s :\001DCC ACCEPT %s %d %u\001\n", nick, fn, port, offset);
  1113. // Now we wait for the client to connect.
  1114. return BIND_RET_BREAK;
  1115. }
  1116. static cmd_t transfer_ctcps[] =
  1117. {
  1118. {"DCC", "", ctcp_DCC_RESUME, "transfer:DCC"},
  1119. {NULL, NULL, NULL, NULL}
  1120. };
  1121. */
  1122. /* Add our CTCP bindings if the server module is loaded. */
  1123. static int server_transfer_setup(char *mod)
  1124. {
  1125. /* add_builtins("ctcp", transfer_ctcps); */
  1126. return 1;
  1127. }
  1128. #endif /* LEAF */
  1129. /*
  1130. * Module functions
  1131. */
  1132. void transfer_report(int idx, int details)
  1133. {
  1134. if (details) {
  1135. dprintf(idx,TRANSFER_STAT_BLOCK,
  1136. dcc_block, (dcc_block == 0) ? " (turbo dcc)" : "", dcc_limit);
  1137. }
  1138. }
  1139. void transfer_init()
  1140. {
  1141. fileq = NULL;
  1142. #ifdef LEAF
  1143. server_transfer_setup(NULL);
  1144. #endif /* LEAF */
  1145. }