transfer.c 55 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087
  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. #define MODULE_NAME "transfer"
  10. #define MAKING_TRANSFER
  11. /* sigh sunos */
  12. #include <sys/types.h>
  13. #include <sys/stat.h>
  14. #include "src/mod/module.h"
  15. #include "src/mod/update.mod/update.h"
  16. #include "src/tandem.h"
  17. #include "src/users.h"
  18. #include "transfer.h"
  19. #include <netinet/in.h>
  20. #include <arpa/inet.h>
  21. static Function *global = NULL, *update_funcs = NULL;
  22. static int copy_to_tmp = 1; /* Copy files to /tmp before transmitting? */
  23. static int wait_dcc_xfer = 40; /* Timeout time on DCC xfers */
  24. static p_tcl_bind_list H_rcvd, H_sent, H_lost, H_tout;
  25. static int dcc_limit = 4; /* Maximum number of simultaneous file
  26. downloads allowed */
  27. static int dcc_block = 0; /* Size of one dcc block */
  28. static int quiet_reject = 1; /* Quietly reject dcc chat or sends from
  29. users without access? */
  30. /*
  31. * Prototypes
  32. */
  33. static void stats_add_dnload(struct userrec *, unsigned long);
  34. static void stats_add_upload(struct userrec *, unsigned long);
  35. static void wipe_tmp_filename(char *, int);
  36. static int at_limit(char *);
  37. static void dcc_get_pending(int, char *, int);
  38. static struct dcc_table DCC_SEND;
  39. static struct dcc_table DCC_GET;
  40. static struct dcc_table DCC_GET_PENDING;
  41. static fileq_t *fileq = NULL;
  42. /*
  43. * Misc functions
  44. */
  45. #undef MATCH
  46. #define MATCH (match+sofar)
  47. /* This function SHAMELESSLY :) pinched from match.c in the original
  48. * source, see that file for info about the author etc.
  49. */
  50. #define QUOTE '\\'
  51. #define WILDS '*'
  52. #define WILDQ '?'
  53. #define NOMATCH 0
  54. /*
  55. * wild_match_file(char *ma, char *na)
  56. *
  57. * Features: Forward, case-sensitive, ?, *
  58. * Best use: File mask matching, as it is case-sensitive
  59. */
  60. static int wild_match_file(register char *m, register char *n)
  61. {
  62. char *ma = m, *lsm = 0, *lsn = 0;
  63. int match = 1;
  64. register unsigned int sofar = 0;
  65. /* Take care of null strings (should never match) */
  66. if ((m == 0) || (n == 0) || (!*n))
  67. return NOMATCH;
  68. /* (!*m) test used to be here, too, but I got rid of it. After all, If
  69. * (!*n) was false, there must be a character in the name (the second
  70. * string), so if the mask is empty it is a non-match. Since the
  71. * algorithm handles this correctly without testing for it here and this
  72. * shouldn't be called with null masks anyway, it should be a bit faster
  73. * this way.
  74. */
  75. while (*n) {
  76. /* Used to test for (!*m) here, but this scheme seems to work better */
  77. switch (*m) {
  78. case 0:
  79. do
  80. m--; /* Search backwards */
  81. while ((m > ma) && (*m == '?')); /* For first non-? char */
  82. if ((m > ma) ? ((*m == '*') && (m[-1] != QUOTE)) : (*m == '*'))
  83. return MATCH; /* nonquoted * = match */
  84. break;
  85. case WILDS:
  86. do
  87. m++;
  88. while (*m == WILDS); /* Zap redundant wilds */
  89. lsm = m;
  90. lsn = n; /* Save * fallback spot */
  91. match += sofar;
  92. sofar = 0;
  93. continue; /* Save tally count */
  94. case WILDQ:
  95. m++;
  96. n++;
  97. continue; /* Match one char */
  98. case QUOTE:
  99. m++; /* Handle quoting */
  100. }
  101. if (*m == *n) { /* If matching */
  102. m++;
  103. n++;
  104. sofar++;
  105. continue; /* Tally the match */
  106. }
  107. if (lsm) { /* Try to fallback on * */
  108. n = ++lsn;
  109. m = lsm; /* Restore position */
  110. /* Used to test for (!*n) here but it wasn't necessary so it's gone */
  111. sofar = 0;
  112. continue; /* Next char, please */
  113. }
  114. return NOMATCH; /* No fallbacks=No match */
  115. }
  116. while (*m == WILDS)
  117. m++; /* Zap leftover *s */
  118. return (*m) ? NOMATCH : MATCH; /* End of both = match */
  119. }
  120. static void wipe_tmp_filename(char *fn, int idx)
  121. {
  122. int i, ok = 1;
  123. if (!copy_to_tmp)
  124. return;
  125. for (i = 0; i < dcc_total; i++)
  126. if (i != idx)
  127. if (dcc[i].type == &DCC_GET || dcc[i].type == &DCC_GET_PENDING)
  128. if (!strcmp(dcc[i].u.xfer->filename, fn)) {
  129. ok = 0;
  130. break;
  131. }
  132. if (ok)
  133. unlink(fn);
  134. }
  135. /* Return true if this user has >= the maximum number of file xfers allowed.
  136. */
  137. static int at_limit(char *nick)
  138. {
  139. int i, x = 0;
  140. for (i = 0; i < dcc_total; i++)
  141. if (dcc[i].type == &DCC_GET || dcc[i].type == &DCC_GET_PENDING)
  142. if (!egg_strcasecmp(dcc[i].nick, nick))
  143. x++;
  144. return (x >= dcc_limit);
  145. }
  146. /* Replaces all spaces with underscores (' ' -> '_'). The returned buffer
  147. * needs to be freed after use.
  148. */
  149. static char *replace_spaces(char *fn)
  150. {
  151. register char *ret, *p;
  152. p = ret = nmalloc(strlen(fn) + 1);
  153. strcpy(ret, fn);
  154. while ((p = strchr(p, ' ')) != NULL)
  155. *p = '_';
  156. return ret;
  157. }
  158. /*
  159. * Tcl sent, rcvd, tout and lost functions
  160. */
  161. static int builtin_sentrcvd STDVAR
  162. {
  163. Function F = (Function) cd;
  164. BADARGS(4, 4, " hand nick path");
  165. CHECKVALIDITY(builtin_sentrcvd);
  166. F(argv[1], argv[2], argv[3]);
  167. return TCL_OK;
  168. }
  169. static int builtin_toutlost STDVAR
  170. {
  171. Function F = (Function) cd;
  172. BADARGS(6, 6, " hand nick path acked length");
  173. CHECKVALIDITY(builtin_toutlost);
  174. F(argv[1], argv[2], argv[3], argv[4], argv[5]);
  175. return TCL_OK;
  176. }
  177. static void check_tcl_sentrcvd(struct userrec *u, char *nick, char *path,
  178. p_tcl_bind_list h)
  179. {
  180. struct flag_record fr = {FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0};
  181. char *hand = u ? u->handle : "*"; /* u might be NULL. */
  182. get_user_flagrec(u, &fr, NULL);
  183. Tcl_SetVar(interp, "_sr1", hand, 0);
  184. Tcl_SetVar(interp, "_sr2", nick, 0);
  185. Tcl_SetVar(interp, "_sr3", path, 0);
  186. check_tcl_bind(h, hand, &fr, " $_sr1 $_sr2 $_sr3",
  187. MATCH_MASK | BIND_USE_ATTR | BIND_STACKABLE);
  188. }
  189. static void check_tcl_toutlost(struct userrec *u, char *nick, char *path,
  190. unsigned long acked, unsigned long length,
  191. p_tcl_bind_list h)
  192. {
  193. struct flag_record fr = {FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0};
  194. char *hand = u ? u->handle : "*"; /* u might be NULL. */
  195. char s[15];
  196. get_user_flagrec(u, &fr, NULL);
  197. Tcl_SetVar(interp, "_sr1", hand, 0);
  198. Tcl_SetVar(interp, "_sr2", nick, 0);
  199. Tcl_SetVar(interp, "_sr3", path, 0);
  200. egg_snprintf(s, sizeof s, "%lu", acked);
  201. Tcl_SetVar(interp, "_sr4", s, 0);
  202. egg_snprintf(s, sizeof s, "%lu", length);
  203. Tcl_SetVar(interp, "_sr5", s, 0);
  204. check_tcl_bind(h, hand, &fr, " $_sr1 $_sr2 $_sr3 $_sr4 $_sr5",
  205. MATCH_MASK | BIND_USE_ATTR | BIND_STACKABLE);
  206. }
  207. /*
  208. * File queue functions
  209. */
  210. static int expmem_fileq()
  211. {
  212. fileq_t *q;
  213. int tot = 0;
  214. for (q = fileq; q; q = q->next)
  215. tot += strlen(q->dir) + strlen(q->file) + 2 + sizeof(fileq_t);
  216. return tot;
  217. }
  218. static void queue_file(char *dir, char *file, char *from, char *to)
  219. {
  220. fileq_t *q = fileq;
  221. fileq = (fileq_t *) nmalloc(sizeof(fileq_t));
  222. fileq->next = q;
  223. fileq->dir = (char *) nmalloc(strlen(dir) + 1);
  224. fileq->file = (char *) nmalloc(strlen(file) + 1);
  225. strcpy(fileq->dir, dir);
  226. strcpy(fileq->file, file);
  227. strcpy(fileq->nick, from);
  228. strcpy(fileq->to, to);
  229. }
  230. static void deq_this(fileq_t *this)
  231. {
  232. fileq_t *q = fileq, *last = NULL;
  233. while (q && q != this) {
  234. last = q;
  235. q = q->next;
  236. }
  237. if (!q)
  238. return; /* Bogus ptr */
  239. if (last)
  240. last->next = q->next;
  241. else
  242. fileq = q->next;
  243. nfree(q->dir);
  244. nfree(q->file);
  245. nfree(q);
  246. }
  247. /* Remove all files queued to a certain user.
  248. */
  249. static void flush_fileq(char *to)
  250. {
  251. fileq_t *q = fileq;
  252. int fnd = 1;
  253. while (fnd) {
  254. q = fileq;
  255. fnd = 0;
  256. while (q != NULL) {
  257. if (!egg_strcasecmp(q->to, to)) {
  258. deq_this(q);
  259. q = NULL;
  260. fnd = 1;
  261. }
  262. if (q != NULL)
  263. q = q->next;
  264. }
  265. }
  266. }
  267. static void send_next_file(char *to)
  268. {
  269. fileq_t *q, *this = NULL;
  270. char *s, *s1;
  271. int x;
  272. for (q = fileq; q; q = q->next)
  273. if (!egg_strcasecmp(q->to, to))
  274. this = q;
  275. if (this == NULL)
  276. return; /* None */
  277. /* Copy this file to /tmp */
  278. if (this->dir[0] == '*') { /* Absolute path */
  279. s = nmalloc(strlen(&this->dir[1]) + strlen(this->file) + 2);
  280. sprintf(s, "%s/%s", &this->dir[1], this->file);
  281. } else {
  282. char *p = strchr(this->dir, '*');
  283. if (p == NULL) { /* if it's messed up */
  284. send_next_file(to);
  285. return;
  286. }
  287. p++;
  288. s = nmalloc(strlen(p) + strlen(this->file) + 2);
  289. sprintf(s, "%s%s%s", p, p[0] ? "/" : "", this->file);
  290. strcpy(this->dir, &(p[atoi(this->dir)]));
  291. }
  292. if (copy_to_tmp) {
  293. s1 = nmalloc(strlen(tempdir) + strlen(this->file) + 1);
  294. sprintf(s1, "%s%s", tempdir, this->file);
  295. if (copyfile(s, s1) != 0) {
  296. putlog(LOG_FILES | LOG_MISC, "*",
  297. TRANSFER_COPY_FAILED,
  298. this->file, tempdir);
  299. dprintf(DP_HELP,
  300. TRANSFER_FILESYS_BROKEN,
  301. this->to);
  302. strcpy(s, this->to);
  303. flush_fileq(s);
  304. nfree(s1);
  305. nfree(s);
  306. return;
  307. }
  308. } else {
  309. s1 = nmalloc(strlen(s) + 1);
  310. strcpy(s1, s);
  311. }
  312. if (this->dir[0] == '*') {
  313. s = nrealloc(s, strlen(&this->dir[1]) + strlen(this->file) + 2);
  314. sprintf(s, "%s/%s", &this->dir[1], this->file);
  315. } else {
  316. s = nrealloc(s, strlen(this->dir) + strlen(this->file) + 2);
  317. sprintf(s, "%s%s%s", this->dir, this->dir[0] ? "/" : "", this->file);
  318. }
  319. x = raw_dcc_send(s1, this->to, this->nick, s);
  320. if (x == DCCSEND_OK) {
  321. if (egg_strcasecmp(this->to, this->nick))
  322. dprintf(DP_HELP, TRANSFER_FILE_ARRIVE, this->to,
  323. this->nick);
  324. deq_this(this);
  325. nfree(s);
  326. nfree(s1);
  327. return;
  328. }
  329. wipe_tmp_filename(s1, -1);
  330. if (x == DCCSEND_FULL) {
  331. putlog(LOG_FILES, "*",TRANSFER_LOG_CONFULL, s1, this->nick);
  332. dprintf(DP_HELP,
  333. TRANSFER_NOTICE_CONFULL,
  334. this->to);
  335. strcpy(s, this->to);
  336. flush_fileq(s);
  337. } else if (x == DCCSEND_NOSOCK) {
  338. putlog(LOG_FILES, "*", TRANSFER_LOG_SOCKERR, s1, this->nick);
  339. dprintf(DP_HELP, TRANSFER_NOTICE_SOCKERR,
  340. this->to);
  341. strcpy(s, this->to);
  342. flush_fileq(s);
  343. } else {
  344. if (x == DCCSEND_FEMPTY) {
  345. putlog(LOG_FILES, "*", TRANSFER_LOG_FILEEMPTY, this->file);
  346. dprintf(DP_HELP, TRANSFER_NOTICE_FILEEMPTY,
  347. this->to, this->file);
  348. }
  349. deq_this(this);
  350. }
  351. nfree(s);
  352. nfree(s1);
  353. return;
  354. }
  355. static void show_queued_files(int idx)
  356. {
  357. int i, cnt = 0, len;
  358. char spaces[] = " ";
  359. fileq_t *q;
  360. for (q = fileq; q; q = q->next) {
  361. if (!egg_strcasecmp(q->nick, dcc[idx].nick)) {
  362. if (!cnt) {
  363. spaces[HANDLEN - 9] = 0;
  364. dprintf(idx, TRANSFER_SEND_TO , spaces);
  365. dprintf(idx, TRANSFER_LINES , spaces);
  366. spaces[HANDLEN - 9] = ' ';
  367. }
  368. cnt++;
  369. spaces[len = HANDLEN - strlen(q->to)] = 0;
  370. if (q->dir[0] == '*')
  371. dprintf(idx, " %s%s %s/%s\n", q->to, spaces, &q->dir[1],
  372. q->file);
  373. else
  374. dprintf(idx, " %s%s /%s%s%s\n", q->to, spaces, q->dir,
  375. q->dir[0] ? "/" : "", q->file);
  376. spaces[len] = ' ';
  377. }
  378. }
  379. for (i = 0; i < dcc_total; i++) {
  380. if ((dcc[i].type == &DCC_GET_PENDING || dcc[i].type == &DCC_GET) &&
  381. (!egg_strcasecmp(dcc[i].nick, dcc[idx].nick) ||
  382. !egg_strcasecmp(dcc[i].u.xfer->from, dcc[idx].nick))) {
  383. char *nfn;
  384. if (!cnt) {
  385. spaces[HANDLEN - 9] = 0;
  386. dprintf(idx, TRANSFER_SEND_TO , spaces);
  387. dprintf(idx, TRANSFER_LINES , spaces);
  388. spaces[HANDLEN - 9] = ' ';
  389. }
  390. nfn = strrchr(dcc[i].u.xfer->origname, '/');
  391. if (nfn == NULL)
  392. nfn = dcc[i].u.xfer->origname;
  393. else
  394. nfn++;
  395. cnt++;
  396. spaces[len = HANDLEN - strlen(dcc[i].nick)] = 0;
  397. if (dcc[i].type == &DCC_GET_PENDING)
  398. dprintf(idx,TRANSFER_WAITING, dcc[i].nick, spaces,
  399. nfn);
  400. else
  401. dprintf(idx,TRANSFER_DONE, dcc[i].nick, spaces,
  402. nfn, (100.0 * ((float) dcc[i].status /
  403. (float) dcc[i].u.xfer->length)));
  404. spaces[len] = ' ';
  405. }
  406. }
  407. if (!cnt)
  408. dprintf(idx,TRANSFER_QUEUED_UP);
  409. else
  410. dprintf(idx,TRANSFER_TOTAL, cnt);
  411. }
  412. static void fileq_cancel(int idx, char *par)
  413. {
  414. int fnd = 1, matches = 0, atot = 0, i;
  415. fileq_t *q;
  416. char *s = NULL;
  417. while (fnd) {
  418. q = fileq;
  419. fnd = 0;
  420. while (q != NULL) {
  421. if (!egg_strcasecmp(dcc[idx].nick, q->nick)) {
  422. s = nrealloc(s, strlen(q->dir) + strlen(q->file) + 3);
  423. if (q->dir[0] == '*')
  424. sprintf(s, "%s/%s", &q->dir[1], q->file);
  425. else
  426. sprintf(s, "/%s%s%s", q->dir, q->dir[0] ? "/" : "", q->file);
  427. if (wild_match_file(par, s)) {
  428. dprintf(idx,TRANSFER_CANCELLED, s, q->to);
  429. fnd = 1;
  430. deq_this(q);
  431. q = NULL;
  432. matches++;
  433. }
  434. if (!fnd && wild_match_file(par, q->file)) {
  435. dprintf(idx,TRANSFER_CANCELLED, s, q->to);
  436. fnd = 1;
  437. deq_this(q);
  438. q = NULL;
  439. matches++;
  440. }
  441. }
  442. if (q != NULL)
  443. q = q->next;
  444. }
  445. }
  446. if (s)
  447. nfree(s);
  448. for (i = 0; i < dcc_total; i++) {
  449. if ((dcc[i].type == &DCC_GET_PENDING || dcc[i].type == &DCC_GET) &&
  450. (!egg_strcasecmp(dcc[i].nick, dcc[idx].nick) ||
  451. !egg_strcasecmp(dcc[i].u.xfer->from, dcc[idx].nick))) {
  452. char *nfn = strrchr(dcc[i].u.xfer->origname, '/');
  453. if (nfn == NULL)
  454. nfn = dcc[i].u.xfer->origname;
  455. else
  456. nfn++;
  457. if (wild_match_file(par, nfn)) {
  458. dprintf(idx,TRANSFER_ABORT_DCCSEND, nfn);
  459. if (egg_strcasecmp(dcc[i].nick, dcc[idx].nick))
  460. dprintf(DP_HELP, TRANSFER_NOTICE_ABORT,
  461. dcc[i].nick, nfn, dcc[idx].nick);
  462. if (dcc[i].type == &DCC_GET)
  463. putlog(LOG_FILES, "*",TRANSFER_DCC_CANCEL, nfn,
  464. dcc[i].nick, dcc[i].status, dcc[i].u.xfer->length);
  465. wipe_tmp_filename(dcc[i].u.xfer->filename, i);
  466. atot++;
  467. matches++;
  468. killsock(dcc[i].sock);
  469. lostdcc(i);
  470. }
  471. }
  472. }
  473. if (!matches)
  474. dprintf(idx,TRANSFER_NO_MATCHES);
  475. else
  476. dprintf(idx, TRANSFER_CANCELLED_FILE, matches, (matches != 1) ? "s" : "");
  477. for (i = 0; i < atot; i++)
  478. if (!at_limit(dcc[idx].nick))
  479. send_next_file(dcc[idx].nick);
  480. }
  481. static int tcl_getfileq STDVAR
  482. {
  483. char *s = NULL;
  484. fileq_t *q;
  485. BADARGS(2, 2, " handle");
  486. for (q = fileq; q; q = q->next) {
  487. if (!egg_strcasecmp(q->nick, argv[1])) {
  488. s = nrealloc(s, strlen(q->to) + strlen(q->dir) + strlen(q->file) + 4);
  489. if (q->dir[0] == '*')
  490. sprintf(s, "%s %s/%s", q->to, &q->dir[1], q->file);
  491. else
  492. sprintf(s, "%s /%s%s%s", q->to, q->dir, q->dir[0] ? "/" : "", q->file);
  493. Tcl_AppendElement(irp, s);
  494. }
  495. }
  496. if (s)
  497. nfree(s);
  498. return TCL_OK;
  499. }
  500. /*
  501. * Misc Tcl functions
  502. */
  503. static int tcl_dccsend STDVAR
  504. {
  505. char s[10], *sys, *nfn;
  506. int i;
  507. FILE *f;
  508. BADARGS(3, 3, " filename ircnick");
  509. f = fopen(argv[1], "r");
  510. if (f == NULL) {
  511. /* File not found */
  512. Tcl_AppendResult(irp, "3", NULL);
  513. return TCL_OK;
  514. }
  515. fclose(f);
  516. nfn = strrchr(argv[1], '/');
  517. if (nfn == NULL)
  518. nfn = argv[1];
  519. else
  520. nfn++;
  521. if (at_limit(argv[2])) {
  522. /* Queue that mother */
  523. if (nfn == argv[1])
  524. queue_file("*", nfn, "(script)", argv[2]);
  525. else {
  526. nfn--;
  527. *nfn = 0;
  528. nfn++;
  529. sys = nmalloc(strlen(argv[1]) + 2);
  530. sprintf(sys, "*%s", argv[1]);
  531. queue_file(sys, nfn, "(script)", argv[2]);
  532. nfree(sys);
  533. }
  534. Tcl_AppendResult(irp, "4", NULL);
  535. return TCL_OK;
  536. }
  537. if (copy_to_tmp) {
  538. sys = nmalloc(strlen(tempdir) + strlen(nfn) + 1);
  539. sprintf(sys, "%s%s", tempdir, nfn);
  540. f = fopen(sys, "r");
  541. if (f) {
  542. fclose(f);
  543. Tcl_AppendResult(irp, "5", NULL);
  544. return TCL_OK;
  545. } else
  546. copyfile(argv[1], sys);
  547. } else {
  548. sys = nmalloc(strlen(argv[1]) + 1);
  549. strcpy(sys, argv[1]);
  550. }
  551. i = raw_dcc_send(sys, argv[2], "*", argv[1]);
  552. if (i > 0)
  553. wipe_tmp_filename(sys, -1);
  554. egg_snprintf(s, sizeof s, "%d", i);
  555. Tcl_AppendResult(irp, s, NULL);
  556. nfree(sys);
  557. return TCL_OK;
  558. }
  559. static int tcl_getfilesendtime STDVAR
  560. {
  561. int sock, i;
  562. char s[15];
  563. BADARGS(2, 2, " idx");
  564. /* Btw, what the tcl interface refers to as `idx' is the socket number
  565. for the C part. */
  566. sock = atoi(argv[1]);
  567. for (i = 0; i < dcc_total; i++)
  568. if (dcc[i].sock == sock) {
  569. if (dcc[i].type == &DCC_SEND || dcc[i].type == &DCC_GET) {
  570. egg_snprintf(s, sizeof s, "%lu", dcc[i].u.xfer->start_time);
  571. Tcl_AppendResult(irp, s, NULL);
  572. } else
  573. Tcl_AppendResult(irp, "-2", NULL); /* Not a valid file transfer,
  574. honey. */
  575. return TCL_OK;
  576. }
  577. Tcl_AppendResult(irp, "-1", NULL); /* No matching entry found. */
  578. return TCL_OK;
  579. }
  580. static tcl_cmds mytcls[] =
  581. {
  582. {"dccsend", tcl_dccsend},
  583. {"getfileq", tcl_getfileq},
  584. {"getfilesendtime", tcl_getfilesendtime},
  585. {NULL, NULL}
  586. };
  587. /*
  588. * DCC routines
  589. */
  590. /* Instead of reading all data intended to go into the DCC block
  591. * in one go, we read it in PMAX_SIZE chunks, feed it to tputs and
  592. * continue until we get to know that the network buffer only
  593. * buffers the data instead of sending it.
  594. *
  595. * In that case, we delay further sending until we receive the
  596. * dcc outdone event.
  597. *
  598. * Note: To optimize buffer sizes, we default to PMAX_SIZE, but
  599. * allocate a smaller buffer for smaller pending_data sizes.
  600. */
  601. #define PMAX_SIZE 4096
  602. static unsigned long pump_file_to_sock(FILE *file, long sock,
  603. register unsigned long pending_data)
  604. {
  605. const unsigned long buf_len = pending_data >= PMAX_SIZE ?
  606. PMAX_SIZE : pending_data;
  607. char *bf = nmalloc(buf_len);
  608. register unsigned long actual_size;
  609. if (bf) {
  610. do {
  611. actual_size = pending_data >= buf_len ? buf_len : pending_data;
  612. fread(bf, actual_size, 1, file);
  613. tputs(sock, bf, actual_size);
  614. pending_data -= actual_size;
  615. } while (!sock_has_data(SOCK_DATA_OUTGOING, sock) && pending_data != 0);
  616. nfree(bf);
  617. }
  618. return pending_data;
  619. }
  620. static void eof_dcc_fork_send(int idx)
  621. {
  622. char s1[121];
  623. char *s2;
  624. fclose(dcc[idx].u.xfer->f);
  625. if (!strcmp(dcc[idx].nick, "*users")) {
  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. break;
  632. }
  633. if (y != 0) {
  634. dcc[y].status &= ~STAT_GETTING;
  635. dcc[y].status &= ~STAT_SHARE;
  636. }
  637. putlog(LOG_BOTS, "*", USERF_FAILEDXFER);
  638. unlink(dcc[idx].u.xfer->filename);
  639. } else if (!strcmp(dcc[idx].nick, "*binary")) {
  640. int x, y = 0;
  641. for (x = 0; x < dcc_total; x++)
  642. if ((!egg_strcasecmp(dcc[x].nick, dcc[idx].host)) &&
  643. (dcc[x].type->flags & DCT_BOT)) {
  644. y = x;
  645. break;
  646. }
  647. if (y != 0) {
  648. dcc[y].status &= ~STAT_GETTINGU;
  649. }
  650. putlog(LOG_BOTS, "*", "Failed binary transfer.");
  651. } else {
  652. neterror(s1);
  653. if (!quiet_reject)
  654. dprintf(DP_HELP, "NOTICE %s :%s (%s)\n", dcc[idx].nick,
  655. DCC_CONNECTFAILED1, s1);
  656. putlog(LOG_MISC, "*", "%s: SEND %s (%s!%s)", DCC_CONNECTFAILED2,
  657. dcc[idx].u.xfer->origname, dcc[idx].nick, dcc[idx].host);
  658. putlog(LOG_MISC, "*", " (%s)", s1);
  659. s2 = nmalloc(strlen(tempdir) + strlen(dcc[idx].u.xfer->filename) + 1);
  660. sprintf(s2, "%s%s", tempdir, dcc[idx].u.xfer->filename);
  661. unlink(s2);
  662. nfree(s2);
  663. }
  664. killsock(dcc[idx].sock);
  665. lostdcc(idx);
  666. }
  667. static void eof_dcc_send(int idx)
  668. {
  669. int ok, j;
  670. char *ofn, *nfn, s[1024], *hand;
  671. struct userrec *u;
  672. fclose(dcc[idx].u.xfer->f);
  673. if (dcc[idx].u.xfer->length == dcc[idx].status) {
  674. int l;
  675. /* Success */
  676. ok = 0;
  677. if (!strcmp(dcc[idx].nick, "*users")) {
  678. module_entry *me = module_find("share", 0, 0);
  679. if (me && me->funcs) {
  680. Function f = me->funcs[SHARE_FINISH];
  681. (f) (idx);
  682. }
  683. killsock(dcc[idx].sock);
  684. lostdcc(idx);
  685. return;
  686. } else if (!strcmp(dcc[idx].nick, "*binary")) {
  687. module_entry *me = module_find("update", 0, 0);
  688. if (me && me->funcs) {
  689. Function f = me->funcs[UPDATE_FINISH];
  690. (f) (idx);
  691. }
  692. killsock(dcc[idx].sock);
  693. lostdcc(idx);
  694. return;
  695. }
  696. putlog(LOG_FILES, "*", TRANSFER_COMPLETED_DCC,
  697. dcc[idx].u.xfer->origname, dcc[idx].nick, dcc[idx].host);
  698. egg_snprintf(s, sizeof s, "%s!%s", dcc[idx].nick, dcc[idx].host);
  699. u = get_user_by_host(s);
  700. hand = u ? u->handle : "*";
  701. l = strlen(dcc[idx].u.xfer->filename);
  702. if (l > NAME_MAX) {
  703. /* The filename is to long... blow it off */
  704. putlog(LOG_FILES, "*",TRANSFER_FILENAME_TOOLONG , l);
  705. dprintf(DP_HELP, TRANSFER_NOTICE_FNTOOLONG,
  706. dcc[idx].nick, l);
  707. putlog(LOG_FILES, "*", TRANSFER_TOO_BAD );
  708. dprintf(DP_HELP, TRANSFER_NOTICE_TOOBAD,
  709. dcc[idx].nick);
  710. killsock(dcc[idx].sock);
  711. lostdcc(idx);
  712. return;
  713. }
  714. /* Move the file from /tmp */
  715. ofn = nmalloc(strlen(tempdir) + strlen(dcc[idx].u.xfer->filename) + 1);
  716. nfn = nmalloc(strlen(dcc[idx].u.xfer->dir)
  717. + strlen(dcc[idx].u.xfer->origname) + 1);
  718. sprintf(ofn, "%s%s", tempdir, dcc[idx].u.xfer->filename);
  719. sprintf(nfn, "%s%s", dcc[idx].u.xfer->dir, dcc[idx].u.xfer->origname);
  720. if (movefile(ofn, nfn))
  721. putlog(LOG_MISC | LOG_FILES, "*",
  722. TRANSFER_FAILED_MOVE, nfn, ofn);
  723. else {
  724. /* Add to file database */
  725. module_entry *fs = module_find("filesys", 0, 0);
  726. if (fs != NULL) {
  727. Function f = fs->funcs[FILESYS_ADDFILE];
  728. f(dcc[idx].u.xfer->dir, dcc[idx].u.xfer->origname, hand);
  729. }
  730. stats_add_upload(u, dcc[idx].u.xfer->length);
  731. check_tcl_sentrcvd(u, dcc[idx].nick, nfn, H_rcvd);
  732. }
  733. nfree(ofn);
  734. nfree(nfn);
  735. for (j = 0; j < dcc_total; j++)
  736. if (!ok && (dcc[j].type->flags & (DCT_GETNOTES)) &&
  737. !egg_strcasecmp(dcc[j].nick, hand)) {
  738. ok = 1;
  739. dprintf(j,TRANSFER_THANKS);
  740. }
  741. if (!ok)
  742. dprintf(DP_HELP,TRANSFER_NOTICE_THANKS,
  743. dcc[idx].nick);
  744. killsock(dcc[idx].sock);
  745. lostdcc(idx);
  746. return;
  747. }
  748. /* Failure :( */
  749. if (!strcmp(dcc[idx].nick, "*users")) {
  750. int x, y = 0;
  751. for (x = 0; x < dcc_total; x++)
  752. if ((!egg_strcasecmp(dcc[x].nick, dcc[idx].host)) &&
  753. (dcc[x].type->flags & DCT_BOT))
  754. y = x;
  755. if (y) {
  756. putlog(LOG_BOTS, "*",TRANSFER_USERFILE_LOST,
  757. dcc[y].nick);
  758. unlink(dcc[idx].u.xfer->filename);
  759. /* Drop that bot */
  760. dprintf(y, "bye\n");
  761. egg_snprintf(s, sizeof s,TRANSFER_USERFILE_DISCON,
  762. dcc[y].nick);
  763. botnet_send_unlinked(y, dcc[y].nick, s);
  764. chatout("*** %s\n", dcc[y].nick, s);
  765. if (y < idx) {
  766. int t = y;
  767. y = idx;
  768. idx = t;
  769. }
  770. if (y != idx) {
  771. killsock(dcc[y].sock);
  772. lostdcc(y);
  773. }
  774. killsock(dcc[idx].sock);
  775. lostdcc(idx);
  776. }
  777. } else if (!strcmp(dcc[idx].nick, "*binary")) {
  778. int x, y = 0;
  779. for (x = 0; x < dcc_total; x++)
  780. if ((!egg_strcasecmp(dcc[x].nick, dcc[idx].host)) &&
  781. (dcc[x].type->flags & DCT_BOT))
  782. y = x;
  783. if (y) {
  784. putlog(LOG_BOTS, "*", "Lost binary transfer from %s; aborting.", dcc[y].nick);
  785. unlink(dcc[idx].u.xfer->filename);
  786. /* Drop that bot */
  787. // dprintf(y, "bye\n");
  788. // egg_snprintf(s, sizeof s,"Disconnected %s (aborted binary transfer)", dcc[y].nick);
  789. // botnet_send_unlinked(y, dcc[y].nick, s);
  790. // chatout("*** %s\n", dcc[y].nick, s);
  791. // if (y != idx) {
  792. // killsock(dcc[y].sock);
  793. // lostdcc(y);
  794. // }
  795. killsock(dcc[idx].sock);
  796. lostdcc(idx);
  797. }
  798. } else {
  799. putlog(LOG_FILES, "*",TRANSFER_LOST_DCCSEND,
  800. dcc[idx].u.xfer->origname, dcc[idx].nick, dcc[idx].host,
  801. dcc[idx].status, dcc[idx].u.xfer->length);
  802. ofn = nmalloc(strlen(tempdir) + strlen(dcc[idx].u.xfer->filename) + 1);
  803. sprintf(ofn, "%s%s", tempdir, dcc[idx].u.xfer->filename);
  804. unlink(ofn);
  805. nfree(ofn);
  806. killsock(dcc[idx].sock);
  807. lostdcc(idx);
  808. }
  809. }
  810. /* Determine byte order. Used for resend DCC startup packets.
  811. */
  812. static inline u_8bit_t byte_order_test(void)
  813. {
  814. u_16bit_t test = TRANSFER_REGET_PACKETID;
  815. if (*((u_8bit_t *)&test) == ((TRANSFER_REGET_PACKETID & 0xff00) >> 8))
  816. return 0;
  817. if (*((u_8bit_t *)&test) == (TRANSFER_REGET_PACKETID & 0x00ff))
  818. return 1;
  819. return 0;
  820. }
  821. /* Parse and handle resend DCC startup packets.
  822. */
  823. inline static void handle_resend_packet(int idx, transfer_reget *reget_data)
  824. {
  825. if (byte_order_test() != reget_data->byte_order) {
  826. /* The sender's byte order does not match our's so we need to switch the
  827. * bytes first, before we can make use of them.
  828. */
  829. reget_data->packet_id = ((reget_data->packet_id & 0x00ff) << 8) |
  830. ((reget_data->packet_id & 0xff00) >> 8);
  831. reget_data->byte_offset = ((reget_data->byte_offset & 0xff000000) >> 24) |
  832. ((reget_data->byte_offset & 0x00ff0000) >> 8) |
  833. ((reget_data->byte_offset & 0x0000ff00) << 8) |
  834. ((reget_data->byte_offset & 0x000000ff) << 24);
  835. }
  836. if (reget_data->packet_id != TRANSFER_REGET_PACKETID)
  837. putlog(LOG_FILES, "*", TRANSFER_REGET_PACKET,
  838. dcc[idx].nick, dcc[idx].u.xfer->origname);
  839. else
  840. dcc[idx].u.xfer->offset = reget_data->byte_offset;
  841. dcc[idx].u.xfer->type = XFER_RESEND;
  842. }
  843. /* Handles DCC packets the client sends us. As soon as the last sent dcc
  844. * block is fully acknowledged we send the next block.
  845. *
  846. * Note: The first received packet during reget is a special 8 bit packet
  847. * containing special information.
  848. */
  849. static void dcc_get(int idx, char *buf, int len)
  850. {
  851. char xnick[NICKLEN];
  852. unsigned char bbuf[4];
  853. unsigned long cmp, l;
  854. int w = len + dcc[idx].u.xfer->sofar, p = 0;
  855. dcc[idx].timeval = now; /* Mark as active */
  856. /* Add bytes to our buffer if we don't have a complete response yet.
  857. * This is either a 4 bit ack or the 8 bit reget packet.
  858. */
  859. if (w < 4 ||
  860. (w < 8 && dcc[idx].u.xfer->type == XFER_RESEND_PEND)) {
  861. my_memcpy(&(dcc[idx].u.xfer->buf[dcc[idx].u.xfer->sofar]), buf, len);
  862. dcc[idx].u.xfer->sofar += len;
  863. return;
  864. /* Waiting for the 8 bit reget packet? */
  865. } else if (dcc[idx].u.xfer->type == XFER_RESEND_PEND) {
  866. /* The 8 bit packet is complete now. Parse it. */
  867. if (w == 8) {
  868. transfer_reget reget_data;
  869. my_memcpy(&reget_data, dcc[idx].u.xfer->buf, dcc[idx].u.xfer->sofar);
  870. my_memcpy(&reget_data + dcc[idx].u.xfer->sofar, buf, len);
  871. handle_resend_packet(idx, &reget_data);
  872. cmp = dcc[idx].u.xfer->offset;
  873. } else
  874. return;
  875. /* Fall through! */
  876. /* No, only want 4 bit ack responses. */
  877. } else {
  878. /* Complete packet? */
  879. if (w == 4) {
  880. my_memcpy(bbuf, dcc[idx].u.xfer->buf, dcc[idx].u.xfer->sofar);
  881. my_memcpy(&(bbuf[dcc[idx].u.xfer->sofar]), buf, len);
  882. } else {
  883. p = ((w - 1) & ~3) - dcc[idx].u.xfer->sofar;
  884. w = w - ((w - 1) & ~3);
  885. if (w < 4) {
  886. my_memcpy(dcc[idx].u.xfer->buf, &(buf[p]), w);
  887. return;
  888. }
  889. my_memcpy(bbuf, &(buf[p]), w);
  890. }
  891. /* This is more compatible than ntohl for machines where an int
  892. * is more than 4 bytes:
  893. */
  894. cmp = ((unsigned int) (bbuf[0]) << 24) +
  895. ((unsigned int) (bbuf[1]) << 16) +
  896. ((unsigned int) (bbuf[2]) << 8) + bbuf[3];
  897. dcc[idx].u.xfer->acked = cmp;
  898. }
  899. dcc[idx].u.xfer->sofar = 0;
  900. if (cmp > dcc[idx].u.xfer->length && cmp > dcc[idx].status) {
  901. /* Attempt to resume, but file is not as long as requested... */
  902. putlog(LOG_FILES, "*",
  903. TRANSFER_BEHIND_FILEEND,
  904. dcc[idx].u.xfer->origname, dcc[idx].nick);
  905. } else if (cmp > dcc[idx].status) {
  906. /* Attempt to resume */
  907. if (!strcmp(dcc[idx].nick, "*users")) {
  908. putlog(LOG_BOTS, "*",TRANSFER_TRY_SKIP_AHEAD);
  909. } else if (!strcmp(dcc[idx].nick, "*binary")) {
  910. putlog(LOG_BOTS, "*","!!! Trying to skip ahead on binary transfer");
  911. } else {
  912. fseek(dcc[idx].u.xfer->f, cmp, SEEK_SET);
  913. dcc[idx].status = cmp;
  914. putlog(LOG_FILES, "*",TRANSFER_RESUME_FILE,
  915. (int) (cmp / 1024), dcc[idx].u.xfer->origname,
  916. dcc[idx].nick);
  917. }
  918. } else {
  919. if (dcc[idx].u.xfer->ack_type == XFER_ACK_UNKNOWN) {
  920. if (cmp < dcc[idx].u.xfer->offset)
  921. /* If we don't start at the top of the file, some clients only tell
  922. * us the really received bytes (e.g. bitchx). This seems to be the
  923. * case here.
  924. */
  925. dcc[idx].u.xfer->ack_type = XFER_ACK_WITHOUT_OFFSET;
  926. else
  927. dcc[idx].u.xfer->ack_type = XFER_ACK_WITH_OFFSET;
  928. }
  929. if (dcc[idx].u.xfer->ack_type == XFER_ACK_WITHOUT_OFFSET)
  930. cmp += dcc[idx].u.xfer->offset;
  931. }
  932. if (cmp != dcc[idx].status)
  933. return;
  934. if (dcc[idx].status == dcc[idx].u.xfer->length) {
  935. /* Successful send, we are done */
  936. killsock(dcc[idx].sock);
  937. fclose(dcc[idx].u.xfer->f);
  938. if (!strcmp(dcc[idx].nick, "*users")) {
  939. module_entry *me = module_find("share", 0, 0);
  940. int x, y = 0;
  941. for (x = 0; x < dcc_total; x++)
  942. if (!egg_strcasecmp(dcc[x].nick, dcc[idx].host) &&
  943. (dcc[x].type->flags & DCT_BOT))
  944. y = x;
  945. if (y != 0)
  946. dcc[y].status &= ~STAT_SENDING;
  947. putlog(LOG_BOTS, "*",TRANSFER_COMPLETED_USERFILE,
  948. dcc[y].nick);
  949. unlink(dcc[idx].u.xfer->filename);
  950. /* Any sharebot things that were queued: */
  951. if (me && me->funcs[SHARE_DUMP_RESYNC])
  952. ((me->funcs)[SHARE_DUMP_RESYNC]) (y);
  953. xnick[0] = 0;
  954. } else if (!strcmp(dcc[idx].nick, "*binary")) {
  955. int x, y = 0;
  956. for (x = 0; x < dcc_total; x++)
  957. if (!egg_strcasecmp(dcc[x].nick, dcc[idx].host) &&
  958. (dcc[x].type->flags & DCT_BOT))
  959. y = x;
  960. if (y != 0) {
  961. dcc[y].status &= ~STAT_SENDINGU;
  962. dcc[y].status |= STAT_UPDATED;
  963. }
  964. putlog(LOG_BOTS, "*", "Completed binary file send to %s",
  965. dcc[y].nick);
  966. xnick[0] = 0;
  967. #ifdef HUB
  968. bupdating = 0;
  969. #endif
  970. } else {
  971. module_entry *fs = module_find("filesys", 0, 0);
  972. struct userrec *u = get_user_by_handle(userlist,
  973. dcc[idx].u.xfer->from);
  974. check_tcl_sentrcvd(u, dcc[idx].nick,
  975. dcc[idx].u.xfer->dir, H_sent);
  976. if (fs != NULL) {
  977. Function f = fs->funcs[FILESYS_INCRGOTS];
  978. f(dcc[idx].u.xfer->dir);
  979. }
  980. /* Download is credited to the user who requested it
  981. * (not the user who actually received it)
  982. */
  983. stats_add_dnload(u, dcc[idx].u.xfer->length);
  984. putlog(LOG_FILES, "*",TRANSFER_FINISHED_DCCSEND,
  985. dcc[idx].u.xfer->origname, dcc[idx].nick);
  986. wipe_tmp_filename(dcc[idx].u.xfer->filename, idx);
  987. strcpy((char *) xnick, dcc[idx].nick);
  988. }
  989. lostdcc(idx);
  990. /* Any to dequeue? */
  991. if (!at_limit(xnick))
  992. send_next_file(xnick);
  993. return;
  994. }
  995. /* Note: No fseek() needed here, because the file position is kept from
  996. * the last run.
  997. */
  998. l = dcc_block;
  999. if (l == 0 || dcc[idx].status + l > dcc[idx].u.xfer->length)
  1000. l = dcc[idx].u.xfer->length - dcc[idx].status;
  1001. dcc[idx].u.xfer->block_pending = pump_file_to_sock(dcc[idx].u.xfer->f,
  1002. dcc[idx].sock, l);
  1003. dcc[idx].status += l;
  1004. }
  1005. static void eof_dcc_get(int idx)
  1006. {
  1007. char xnick[NICKLEN], s[1024];
  1008. fclose(dcc[idx].u.xfer->f);
  1009. if (!strcmp(dcc[idx].nick, "*users")) {
  1010. int x, y = 0;
  1011. for (x = 0; x < dcc_total; x++)
  1012. if (!egg_strcasecmp(dcc[x].nick, dcc[idx].host) &&
  1013. (dcc[x].type->flags & DCT_BOT))
  1014. y = x;
  1015. putlog(LOG_BOTS, "*", TRANSFER_ABORT_USERFILE);
  1016. /* Note: no need to unlink the xfer file, as it's already unlinked. */
  1017. xnick[0] = 0;
  1018. /* Drop that bot */
  1019. dprintf(-dcc[y].sock, "bye\n");
  1020. egg_snprintf(s, sizeof s, TRANSFER_USERFILE_DISCON,
  1021. dcc[y].nick);
  1022. botnet_send_unlinked(y, dcc[y].nick, s);
  1023. chatout("*** %s\n", s);
  1024. if (y != idx) {
  1025. killsock(dcc[y].sock);
  1026. lostdcc(y);
  1027. }
  1028. killsock(dcc[idx].sock);
  1029. lostdcc(idx);
  1030. return;
  1031. } else if (!strcmp(dcc[idx].nick, "*binary")) {
  1032. int x, y = 0;
  1033. for (x = 0; x < dcc_total; x++)
  1034. if (!egg_strcasecmp(dcc[x].nick, dcc[idx].host) &&
  1035. (dcc[x].type->flags & DCT_BOT))
  1036. y = x;
  1037. putlog(LOG_BOTS, "*", "Lost binary transfer; aborting.");
  1038. /* Note: no need to unlink the xfer file, as it's already unlinked. */
  1039. xnick[0] = 0;
  1040. /* Drop that bot */
  1041. dcc[y].status &= ~STAT_SENDINGU;
  1042. #ifdef HUB
  1043. bupdating = 0;
  1044. #endif
  1045. // dprintf(-dcc[y].sock, "bye\n");
  1046. // egg_snprintf(s, sizeof s, "Disconnected %s (aborted binary transfer)",
  1047. // dcc[y].nick);
  1048. // botnet_send_unlinked(y, dcc[y].nick, s);
  1049. // chatout("*** %s\n", s);
  1050. // if (y != idx) {
  1051. // killsock(dcc[y].sock);
  1052. // lostdcc(y);
  1053. // }
  1054. killsock(dcc[idx].sock);
  1055. lostdcc(idx);
  1056. return;
  1057. } else {
  1058. struct userrec *u;
  1059. /* Call `lost' DCC trigger now.
  1060. */
  1061. egg_snprintf(s, sizeof s, "%s!%s", dcc[idx].nick, dcc[idx].host);
  1062. u = get_user_by_host(s);
  1063. check_tcl_toutlost(u, dcc[idx].nick, dcc[idx].u.xfer->dir,
  1064. dcc[idx].u.xfer->acked, dcc[idx].u.xfer->length,
  1065. H_lost);
  1066. putlog(LOG_FILES, "*",TRANSFER_LOST_DCCGET,
  1067. dcc[idx].u.xfer->origname, dcc[idx].nick, dcc[idx].host);
  1068. wipe_tmp_filename(dcc[idx].u.xfer->filename, idx);
  1069. strcpy(xnick, dcc[idx].nick);
  1070. }
  1071. killsock(dcc[idx].sock);
  1072. lostdcc(idx);
  1073. /* Send next queued file if there is one */
  1074. if (!at_limit(xnick))
  1075. send_next_file(xnick);
  1076. }
  1077. static void dcc_send(int idx, char *buf, int len)
  1078. {
  1079. char s[512], *b;
  1080. unsigned long sent;
  1081. fwrite(buf, len, 1, dcc[idx].u.xfer->f);
  1082. dcc[idx].status += len;
  1083. /* Put in network byte order */
  1084. sent = dcc[idx].status;
  1085. s[0] = (sent / (1 << 24));
  1086. s[1] = (sent % (1 << 24)) / (1 << 16);
  1087. s[2] = (sent % (1 << 16)) / (1 << 8);
  1088. s[3] = (sent % (1 << 8));
  1089. tputs(dcc[idx].sock, s, 4);
  1090. dcc[idx].timeval = now;
  1091. if (dcc[idx].status > dcc[idx].u.xfer->length &&
  1092. dcc[idx].u.xfer->length > 0) {
  1093. dprintf(DP_HELP,TRANSFER_BOGUS_FILE_LENGTH, dcc[idx].nick);
  1094. putlog(LOG_FILES, "*",
  1095. TRANSFER_FILE_TOO_LONG,
  1096. dcc[idx].u.xfer->origname, dcc[idx].nick, dcc[idx].host);
  1097. fclose(dcc[idx].u.xfer->f);
  1098. b = nmalloc(strlen(tempdir) + strlen(dcc[idx].u.xfer->filename) + 1);
  1099. sprintf(b, "%s%s", tempdir, dcc[idx].u.xfer->filename);
  1100. unlink(b);
  1101. nfree(b);
  1102. killsock(dcc[idx].sock);
  1103. lostdcc(idx);
  1104. }
  1105. }
  1106. static void transfer_get_timeout(int i)
  1107. {
  1108. char xx[1024];
  1109. fclose(dcc[i].u.xfer->f);
  1110. if (strcmp(dcc[i].nick, "*users") == 0) {
  1111. int x, y = 0;
  1112. for (x = 0; x < dcc_total; x++)
  1113. if ((!egg_strcasecmp(dcc[x].nick, dcc[i].host)) &&
  1114. (dcc[x].type->flags & DCT_BOT))
  1115. y = x;
  1116. if (y != 0) {
  1117. dcc[y].status &= ~STAT_SENDING;
  1118. dcc[y].status &= ~STAT_SHARE;
  1119. }
  1120. unlink(dcc[i].u.xfer->filename);
  1121. putlog(LOG_BOTS, "*",TRANSFER_USERFILE_TIMEOUT);
  1122. dprintf(y, "bye\n");
  1123. egg_snprintf(xx, sizeof xx,TRANSFER_DICONNECT_TIMEOUT,
  1124. dcc[y].nick);
  1125. botnet_send_unlinked(y, dcc[y].nick, xx);
  1126. chatout("*** %s\n", xx);
  1127. if (y < i) {
  1128. int t = y;
  1129. y = i;
  1130. i = t;
  1131. }
  1132. killsock(dcc[y].sock);
  1133. lostdcc(y);
  1134. xx[0] = 0;
  1135. } else if (strcmp(dcc[i].nick, "*binary") == 0) {
  1136. int x, y = 0;
  1137. for (x = 0; x < dcc_total; x++)
  1138. if ((!egg_strcasecmp(dcc[x].nick, dcc[i].host)) &&
  1139. (dcc[x].type->flags & DCT_BOT))
  1140. y = x;
  1141. if (y != 0) {
  1142. dcc[y].status &= ~STAT_SENDINGU;
  1143. }
  1144. putlog(LOG_BOTS, "*","Timeout on binary transfer.");
  1145. dprintf(y, "bye\n");
  1146. egg_snprintf(xx, sizeof xx,"Disconnected %s (timed-out binary transfer)",
  1147. dcc[y].nick);
  1148. botnet_send_unlinked(y, dcc[y].nick, xx);
  1149. chatout("*** %s\n", xx);
  1150. if (y < i) {
  1151. int t = y;
  1152. y = i;
  1153. i = t;
  1154. }
  1155. killsock(dcc[y].sock);
  1156. lostdcc(y);
  1157. xx[0] = 0;
  1158. } else {
  1159. char *p;
  1160. struct userrec *u;
  1161. p = strrchr(dcc[i].u.xfer->origname, '/');
  1162. dprintf(DP_HELP, TRANSFER_NOTICE_TIMEOUT,
  1163. dcc[i].nick, p ? p + 1 : dcc[i].u.xfer->origname);
  1164. /* Call DCC `timeout' trigger now.
  1165. */
  1166. egg_snprintf(xx, sizeof xx, "%s!%s", dcc[i].nick, dcc[i].host);
  1167. u = get_user_by_host(xx);
  1168. check_tcl_toutlost(u, dcc[i].nick, dcc[i].u.xfer->dir,
  1169. dcc[i].u.xfer->acked, dcc[i].u.xfer->length, H_tout);
  1170. putlog(LOG_FILES, "*",TRANSFER_DCC_GET_TIMEOUT,
  1171. p ? p + 1 : dcc[i].u.xfer->origname, dcc[i].nick, dcc[i].status,
  1172. dcc[i].u.xfer->length);
  1173. wipe_tmp_filename(dcc[i].u.xfer->filename, i);
  1174. strcpy(xx, dcc[i].nick);
  1175. }
  1176. killsock(dcc[i].sock);
  1177. lostdcc(i);
  1178. if (!at_limit(xx))
  1179. send_next_file(xx);
  1180. }
  1181. static void tout_dcc_send(int idx)
  1182. {
  1183. if (!strcmp(dcc[idx].nick, "*users")) {
  1184. int x, y = 0;
  1185. for (x = 0; x < dcc_total; x++)
  1186. if (!egg_strcasecmp(dcc[x].nick, dcc[idx].host) &&
  1187. (dcc[x].type->flags & DCT_BOT))
  1188. y = x;
  1189. if (y != 0) {
  1190. dcc[y].status &= ~STAT_GETTING;
  1191. dcc[y].status &= ~STAT_SHARE;
  1192. }
  1193. unlink(dcc[idx].u.xfer->filename);
  1194. putlog(LOG_BOTS, "*", TRANSFER_USERFILE_TIMEOUT);
  1195. } else if (!strcmp(dcc[idx].nick, "*binary")) {
  1196. int x, y = 0;
  1197. for (x = 0; x < dcc_total; x++)
  1198. if (!egg_strcasecmp(dcc[x].nick, dcc[idx].host) &&
  1199. (dcc[x].type->flags & DCT_BOT))
  1200. y = x;
  1201. if (y != 0) {
  1202. dcc[y].status &= ~STAT_GETTINGU;
  1203. }
  1204. putlog(LOG_BOTS, "*", "Timeout on binary transfer.");
  1205. } else {
  1206. char *buf;
  1207. dprintf(DP_HELP,TRANSFER_NOTICE_TIMEOUT,
  1208. dcc[idx].nick, dcc[idx].u.xfer->origname);
  1209. putlog(LOG_FILES, "*",TRANSFER_DCC_SEND_TIMEOUT,
  1210. dcc[idx].u.xfer->origname, dcc[idx].nick, dcc[idx].status,
  1211. dcc[idx].u.xfer->length);
  1212. buf = nmalloc(strlen(tempdir) + strlen(dcc[idx].u.xfer->filename) + 1);
  1213. sprintf(buf, "%s%s", tempdir, dcc[idx].u.xfer->filename);
  1214. unlink(buf);
  1215. nfree(buf);
  1216. }
  1217. killsock(dcc[idx].sock);
  1218. lostdcc(idx);
  1219. }
  1220. static void display_dcc_get(int idx, char *buf)
  1221. {
  1222. if (dcc[idx].status == dcc[idx].u.xfer->length)
  1223. sprintf(buf,TRANSFER_SEND, dcc[idx].u.xfer->acked,
  1224. dcc[idx].u.xfer->length, dcc[idx].u.xfer->origname);
  1225. else
  1226. sprintf(buf,TRANSFER_SEND, dcc[idx].status,
  1227. dcc[idx].u.xfer->length, dcc[idx].u.xfer->origname);
  1228. }
  1229. static void display_dcc_get_p(int idx, char *buf)
  1230. {
  1231. sprintf(buf,TRANSFER_SEND_WAITED, now - dcc[idx].timeval,
  1232. dcc[idx].u.xfer->origname);
  1233. }
  1234. static void display_dcc_send(int idx, char *buf)
  1235. {
  1236. Context;
  1237. sprintf(buf,TRANSFER_SEND, dcc[idx].status,
  1238. dcc[idx].u.xfer->length, dcc[idx].u.xfer->origname);
  1239. }
  1240. static void display_dcc_fork_send(int idx, char *buf)
  1241. {
  1242. sprintf(buf,TRANSFER_CONN_SEND);
  1243. }
  1244. static int expmem_dcc_xfer(void *x)
  1245. {
  1246. register struct xfer_info *p = (struct xfer_info *) x;
  1247. int tot;
  1248. tot = sizeof(struct xfer_info);
  1249. if (p->filename)
  1250. tot += strlen(p->filename) + 1;
  1251. /* We need to check if origname points to filename before
  1252. * accounting for the memory.
  1253. */
  1254. if (p->origname && p->filename != p->origname)
  1255. tot += strlen(p->origname) + 1;
  1256. return tot;
  1257. }
  1258. static void kill_dcc_xfer(int idx, void *x)
  1259. {
  1260. register struct xfer_info *p = (struct xfer_info *) x;
  1261. if (p->filename)
  1262. nfree(p->filename);
  1263. /* We need to check if origname points to filename before
  1264. * attempting to free the memory.
  1265. */
  1266. if (p->origname && p->origname != p->filename)
  1267. nfree(p->origname);
  1268. nfree(x);
  1269. }
  1270. static void out_dcc_xfer(int idx, char *buf, void *x)
  1271. {
  1272. }
  1273. static void outdone_dcc_xfer(int idx)
  1274. {
  1275. if (dcc[idx].u.xfer->block_pending)
  1276. dcc[idx].u.xfer->block_pending =
  1277. pump_file_to_sock(dcc[idx].u.xfer->f, dcc[idx].sock,
  1278. dcc[idx].u.xfer->block_pending);
  1279. }
  1280. static struct dcc_table DCC_SEND =
  1281. {
  1282. "SEND",
  1283. DCT_FILETRAN | DCT_FILESEND | DCT_VALIDIDX,
  1284. eof_dcc_send,
  1285. dcc_send,
  1286. &wait_dcc_xfer,
  1287. tout_dcc_send,
  1288. display_dcc_send,
  1289. expmem_dcc_xfer,
  1290. kill_dcc_xfer,
  1291. out_dcc_xfer
  1292. };
  1293. static void dcc_fork_send(int idx, char *x, int y);
  1294. static struct dcc_table DCC_FORK_SEND =
  1295. {
  1296. "FORK_SEND",
  1297. DCT_FILETRAN | DCT_FORKTYPE | DCT_FILESEND | DCT_VALIDIDX,
  1298. eof_dcc_fork_send,
  1299. dcc_fork_send,
  1300. &wait_dcc_xfer,
  1301. eof_dcc_fork_send,
  1302. display_dcc_fork_send,
  1303. expmem_dcc_xfer,
  1304. kill_dcc_xfer,
  1305. out_dcc_xfer
  1306. };
  1307. static void dcc_fork_send(int idx, char *x, int y)
  1308. {
  1309. char s1[121];
  1310. if (dcc[idx].type != &DCC_FORK_SEND)
  1311. return;
  1312. dcc[idx].type = &DCC_SEND;
  1313. dcc[idx].u.xfer->start_time = now;
  1314. egg_snprintf(s1, sizeof s1, "%s!%s", dcc[idx].nick, dcc[idx].host);
  1315. if (strcmp(dcc[idx].nick, "*users") && strcmp(dcc[idx].nick, "*binary"))
  1316. putlog(LOG_MISC, "*", TRANSFER_DCC_CONN, dcc[idx].u.xfer->origname, s1);
  1317. }
  1318. static struct dcc_table DCC_GET =
  1319. {
  1320. "GET",
  1321. DCT_FILETRAN | DCT_VALIDIDX,
  1322. eof_dcc_get,
  1323. dcc_get,
  1324. &wait_dcc_xfer,
  1325. transfer_get_timeout,
  1326. display_dcc_get,
  1327. expmem_dcc_xfer,
  1328. kill_dcc_xfer,
  1329. out_dcc_xfer,
  1330. outdone_dcc_xfer
  1331. };
  1332. static struct dcc_table DCC_GET_PENDING =
  1333. {
  1334. "GET_PENDING",
  1335. DCT_FILETRAN | DCT_VALIDIDX,
  1336. eof_dcc_get,
  1337. dcc_get_pending,
  1338. &wait_dcc_xfer,
  1339. transfer_get_timeout,
  1340. display_dcc_get_p,
  1341. expmem_dcc_xfer,
  1342. kill_dcc_xfer,
  1343. out_dcc_xfer
  1344. };
  1345. static void dcc_get_pending(int idx, char *buf, int len)
  1346. {
  1347. unsigned long ip;
  1348. unsigned short port;
  1349. int i;
  1350. char s[UHOSTLEN];
  1351. i = answer(dcc[idx].sock, s, &ip, &port, 1);
  1352. killsock(dcc[idx].sock);
  1353. dcc[idx].sock = i;
  1354. dcc[idx].addr = ip;
  1355. dcc[idx].port = (int) port;
  1356. if (dcc[idx].sock == -1) {
  1357. neterror(s);
  1358. dprintf(DP_HELP, TRANSFER_NOTICE_BAD_CONN, dcc[idx].nick, s);
  1359. putlog(LOG_FILES, "*", TRANSFER_LOG_BAD_CONN,
  1360. dcc[idx].u.xfer->origname, dcc[idx].nick, dcc[idx].host);
  1361. fclose(dcc[idx].u.xfer->f);
  1362. lostdcc(idx);
  1363. return;
  1364. }
  1365. dcc[idx].type = &DCC_GET;
  1366. dcc[idx].u.xfer->ack_type = XFER_ACK_UNKNOWN;
  1367. /*
  1368. * Note: The file was already opened and dcc[idx].u.xfer->f may be
  1369. * used immediately. Leave it opened until the file transfer
  1370. * is complete.
  1371. */
  1372. /* Are we resuming? */
  1373. if (dcc[idx].u.xfer->type == XFER_RESUME_PEND) {
  1374. int l;
  1375. if (dcc_block == 0 || dcc[idx].u.xfer->length < dcc_block) {
  1376. l = dcc[idx].u.xfer->length - dcc[idx].u.xfer->offset;
  1377. dcc[idx].status = dcc[idx].u.xfer->length;
  1378. } else {
  1379. l = dcc_block;
  1380. dcc[idx].status = dcc[idx].u.xfer->offset + dcc_block;
  1381. }
  1382. /* Seek forward ... */
  1383. fseek(dcc[idx].u.xfer->f, dcc[idx].u.xfer->offset, SEEK_SET);
  1384. dcc[idx].u.xfer->block_pending = pump_file_to_sock(dcc[idx].u.xfer->f,
  1385. dcc[idx].sock, l);
  1386. dcc[idx].u.xfer->type = XFER_RESUME;
  1387. } else {
  1388. dcc[idx].u.xfer->offset = 0;
  1389. /* If we're resending the data, wait for the client's response first,
  1390. * before sending anything ourself.
  1391. */
  1392. if (dcc[idx].u.xfer->type != XFER_RESEND_PEND) {
  1393. if (dcc_block == 0 || dcc[idx].u.xfer->length < dcc_block)
  1394. dcc[idx].status = dcc[idx].u.xfer->length;
  1395. else
  1396. dcc[idx].status = dcc_block;
  1397. dcc[idx].u.xfer->block_pending = pump_file_to_sock(dcc[idx].u.xfer->f,
  1398. dcc[idx].sock,
  1399. dcc[idx].status);
  1400. } else
  1401. dcc[idx].status = 0;
  1402. }
  1403. dcc[idx].timeval = dcc[idx].u.xfer->start_time = now;
  1404. }
  1405. /* Starts a new DCC SEND or DCC RESEND connection to `nick', transferring
  1406. * `filename' from `dir'.
  1407. *
  1408. * Use raw_dcc_resend() and raw_dcc_send() instead of this function.
  1409. */
  1410. static int raw_dcc_resend_send(char *filename, char *nick, char *from,
  1411. char *dir, int resend)
  1412. {
  1413. int zz, port, i;
  1414. char *nfn, *buf = NULL;
  1415. long dccfilesize;
  1416. FILE *f, *dccfile;
  1417. sdprintf("raw_dcc_resend_send()");
  1418. zz = (-1);
  1419. dccfile = fopen(filename,"r");
  1420. fseek(dccfile, 0, SEEK_END);
  1421. dccfilesize = ftell(dccfile);
  1422. fclose(dccfile);
  1423. /* File empty?! */
  1424. if (dccfilesize == 0)
  1425. return DCCSEND_FEMPTY;
  1426. if (reserved_port_min > 0 && reserved_port_min < reserved_port_max) {
  1427. for (port = reserved_port_min; port <= reserved_port_max; port++)
  1428. #ifdef USE_IPV6
  1429. if ((zz = open_listen_by_af(&port, AF_INET)) != -1) /* no idea how we want to handle this -poptix 02/03/03 */
  1430. #else
  1431. if ((zz = open_listen(&port)) != -1)
  1432. #endif /* USE_IPV6 */
  1433. break;
  1434. } else {
  1435. port = reserved_port_min;
  1436. #ifdef USE_IPV6
  1437. zz = open_listen_by_af(&port, AF_INET);
  1438. #else
  1439. zz = open_listen(&port);
  1440. #endif /* USE_IPV6 */
  1441. }
  1442. if (zz == (-1))
  1443. return DCCSEND_NOSOCK;
  1444. nfn = strrchr(dir, '/');
  1445. if (nfn == NULL)
  1446. nfn = dir;
  1447. else
  1448. nfn++;
  1449. f = fopen(filename, "r");
  1450. if (!f)
  1451. return DCCSEND_BADFN;
  1452. if ((i = new_dcc(&DCC_GET_PENDING, sizeof(struct xfer_info))) == -1)
  1453. return DCCSEND_FULL;
  1454. dcc[i].sock = zz;
  1455. dcc[i].addr = (IP) (-559026163);
  1456. dcc[i].port = port;
  1457. strcpy(dcc[i].nick, nick);
  1458. strcpy(dcc[i].host, "irc");
  1459. dcc[i].u.xfer->filename = get_data_ptr(strlen(filename) + 1);
  1460. strcpy(dcc[i].u.xfer->filename, filename);
  1461. if (strchr(nfn, ' '))
  1462. nfn = buf = replace_spaces(nfn);
  1463. dcc[i].u.xfer->origname = get_data_ptr(strlen(nfn) + 1);
  1464. strcpy(dcc[i].u.xfer->origname, nfn);
  1465. strncpyz(dcc[i].u.xfer->from, from, NICKLEN);
  1466. strncpyz(dcc[i].u.xfer->dir, dir, DIRLEN);
  1467. dcc[i].u.xfer->length = dccfilesize;
  1468. dcc[i].timeval = now;
  1469. dcc[i].u.xfer->f = f;
  1470. dcc[i].u.xfer->type = resend ? XFER_RESEND_PEND : XFER_SEND;
  1471. if (nick[0] != '*') {
  1472. dprintf(DP_HELP, "PRIVMSG %s :\001DCC %sSEND %s %lu %d %lu\001\n", nick,
  1473. resend ? "RE" : "", nfn,
  1474. iptolong(natip[0] ? (IP) inet_addr(natip) : getmyip()), port,
  1475. dccfilesize);
  1476. putlog(LOG_FILES, "*",TRANSFER_BEGIN_DCC, resend ? TRANSFER_RE : "",
  1477. nfn, nick);
  1478. }
  1479. if (buf)
  1480. nfree(buf);
  1481. return DCCSEND_OK;
  1482. }
  1483. /* Starts a DCC RESEND connection.
  1484. */
  1485. static int raw_dcc_resend(char *filename, char *nick, char *from, char *dir)
  1486. {
  1487. return raw_dcc_resend_send(filename, nick, from, dir, 1);
  1488. }
  1489. /* Starts a DCC_SEND connection.
  1490. */
  1491. static int raw_dcc_send(char *filename, char *nick, char *from, char *dir)
  1492. {
  1493. return raw_dcc_resend_send(filename, nick, from, dir, 0);
  1494. }
  1495. static tcl_ints myints[] =
  1496. {
  1497. {"max-dloads", &dcc_limit},
  1498. {"dcc-block", &dcc_block},
  1499. {"copy-to-tmp", &copy_to_tmp},
  1500. {"xfer-timeout", &wait_dcc_xfer},
  1501. {NULL, NULL}
  1502. };
  1503. /*
  1504. * fstat functions
  1505. */
  1506. static int fstat_unpack(struct userrec *u, struct user_entry *e)
  1507. {
  1508. char *par, *arg;
  1509. struct filesys_stats *fs;
  1510. fs = user_malloc(sizeof(struct filesys_stats));
  1511. egg_bzero(fs, sizeof(struct filesys_stats));
  1512. par = e->u.list->extra;
  1513. arg = newsplit(&par);
  1514. if (arg[0])
  1515. fs->uploads = atoi(arg);
  1516. arg = newsplit(&par);
  1517. if (arg[0])
  1518. fs->upload_ks = atoi(arg);
  1519. arg = newsplit(&par);
  1520. if (arg[0])
  1521. fs->dnloads = atoi(arg);
  1522. arg = newsplit(&par);
  1523. if (arg[0])
  1524. fs->dnload_ks = atoi(arg);
  1525. list_type_kill(e->u.list);
  1526. e->u.extra = fs;
  1527. return 1;
  1528. }
  1529. static int fstat_pack(struct userrec *u, struct user_entry *e)
  1530. {
  1531. register struct filesys_stats *fs;
  1532. struct list_type *l = user_malloc(sizeof(struct list_type));
  1533. fs = e->u.extra;
  1534. l->extra = user_malloc(41);
  1535. egg_snprintf(l->extra, 41, "%09u %09u %09u %09u",
  1536. fs->uploads, fs->upload_ks, fs->dnloads, fs->dnload_ks);
  1537. l->next = NULL;
  1538. e->u.list = l;
  1539. nfree(fs);
  1540. return 1;
  1541. }
  1542. static int fstat_write_userfile(FILE *f, struct userrec *u,
  1543. struct user_entry *e)
  1544. {
  1545. register struct filesys_stats *fs;
  1546. fs = e->u.extra;
  1547. if (lfprintf(f, "--FSTAT %09u %09u %09u %09u\n",
  1548. fs->uploads, fs->upload_ks,
  1549. fs->dnloads, fs->dnload_ks) == EOF)
  1550. return 0;
  1551. return 1;
  1552. }
  1553. static int fstat_set(struct userrec *u, struct user_entry *e, void *buf)
  1554. {
  1555. register struct filesys_stats *fs = buf;
  1556. if (e->u.extra != fs) {
  1557. if (e->u.extra)
  1558. nfree(e->u.extra);
  1559. e->u.extra = fs;
  1560. } else if (!fs) /* e->u.extra == NULL && fs == NULL */
  1561. return 1;
  1562. if (!noshare && !(u->flags & (USER_BOT | USER_UNSHARED))) {
  1563. if (fs)
  1564. /* Don't check here for something like
  1565. * ofs->uploads != fs->uploads || ofs->upload_ks != fs->upload_ks ||
  1566. * ofs->dnloads != fs->dnloads || ofs->dnload_ks != fs->dnload_ks
  1567. * someone could do:
  1568. * e->u.extra->uploads = 12345;
  1569. * fs = user_malloc(sizeof(struct filesys_stats));
  1570. * memcpy (...e->u.extra...fs...);
  1571. * set_user(&USERENTRY_FSTAT, u, fs);
  1572. * then we wouldn't detect here that something's changed...
  1573. * --rtc
  1574. */
  1575. shareout (NULL, "ch fstat %09u %09u %09u %09u\n",
  1576. fs->uploads, fs->upload_ks, fs->dnloads, fs->dnload_ks);
  1577. else
  1578. shareout (NULL, "ch fstat r\n");
  1579. }
  1580. return 1;
  1581. }
  1582. static int fstat_tcl_get(Tcl_Interp *irp, struct userrec *u,
  1583. struct user_entry *e, int argc, char **argv)
  1584. {
  1585. register struct filesys_stats *fs;
  1586. char d[50];
  1587. BADARGS(3, 4, " handle FSTAT ?u/d?");
  1588. fs = e->u.extra;
  1589. if (argc == 3)
  1590. egg_snprintf(d, sizeof d, "%u %u %u %u", fs->uploads, fs->upload_ks,
  1591. fs->dnloads, fs->dnload_ks);
  1592. else
  1593. switch (argv[3][0]) {
  1594. case 'u':
  1595. egg_snprintf(d, sizeof d, "%u %u", fs->uploads, fs->upload_ks);
  1596. break;
  1597. case 'd':
  1598. egg_snprintf(d, sizeof d, "%u %u", fs->dnloads, fs->dnload_ks);
  1599. break;
  1600. }
  1601. Tcl_AppendResult(irp, d, NULL);
  1602. return TCL_OK;
  1603. }
  1604. static int fstat_kill(struct user_entry *e)
  1605. {
  1606. if (e->u.extra)
  1607. nfree(e->u.extra);
  1608. nfree(e);
  1609. return 1;
  1610. }
  1611. static int fstat_expmem(struct user_entry *e)
  1612. {
  1613. return sizeof(struct filesys_stats);
  1614. }
  1615. static void fstat_display(int idx, struct user_entry *e, struct userrec *u)
  1616. {
  1617. struct filesys_stats *fs;
  1618. fs = e->u.extra;
  1619. dprintf(idx, " FILES: %u download%s (%luk), %u upload%s (%luk)\n",
  1620. fs->dnloads, (fs->dnloads == 1) ? "" : "s", fs->dnload_ks,
  1621. fs->uploads, (fs->uploads == 1) ? "" : "s", fs->upload_ks);
  1622. }
  1623. static int fstat_gotshare(struct userrec *u, struct user_entry *e,
  1624. char *par, int idx);
  1625. static int fstat_dupuser(struct userrec *u, struct userrec *o,
  1626. struct user_entry *e);
  1627. static void stats_add_dnload(struct userrec *u, unsigned long bytes);
  1628. static void stats_add_upload(struct userrec *u, unsigned long bytes);
  1629. static int fstat_tcl_set(Tcl_Interp *irp, struct userrec *u,
  1630. struct user_entry *e, int argc, char **argv);
  1631. static struct user_entry_type USERENTRY_FSTAT =
  1632. {
  1633. NULL,
  1634. fstat_gotshare,
  1635. fstat_dupuser,
  1636. fstat_unpack,
  1637. fstat_pack,
  1638. fstat_write_userfile,
  1639. fstat_kill,
  1640. NULL,
  1641. fstat_set,
  1642. fstat_tcl_get,
  1643. fstat_tcl_set,
  1644. fstat_expmem,
  1645. fstat_display,
  1646. "FSTAT"
  1647. };
  1648. static int fstat_gotshare(struct userrec *u, struct user_entry *e,
  1649. char *par, int idx)
  1650. {
  1651. char *p;
  1652. struct filesys_stats *fs;
  1653. noshare = 1;
  1654. switch (par[0]) {
  1655. case 'u':
  1656. case 'd':
  1657. /* No stats_add_up/dnload here, it's already been sent... --rtc */
  1658. break;
  1659. case 'r':
  1660. set_user (&USERENTRY_FSTAT, u, NULL);
  1661. break;
  1662. default:
  1663. if (!(fs = e->u.extra)) {
  1664. fs = user_malloc(sizeof(struct filesys_stats));
  1665. egg_bzero(fs, sizeof(struct filesys_stats));
  1666. }
  1667. p = newsplit (&par);
  1668. if (p[0])
  1669. fs->uploads = atoi (p);
  1670. p = newsplit (&par);
  1671. if (p[0])
  1672. fs->upload_ks = atoi (p);
  1673. p = newsplit (&par);
  1674. if (p[0])
  1675. fs->dnloads = atoi (p);
  1676. p = newsplit (&par);
  1677. if (p[0])
  1678. fs->dnload_ks = atoi (p);
  1679. set_user(&USERENTRY_FSTAT, u, fs);
  1680. break;
  1681. }
  1682. noshare = 0;
  1683. return 1;
  1684. }
  1685. static int fstat_dupuser(struct userrec *u, struct userrec *o,
  1686. struct user_entry *e)
  1687. {
  1688. struct filesys_stats *fs;
  1689. if (e->u.extra) {
  1690. fs = user_malloc(sizeof(struct filesys_stats));
  1691. my_memcpy(fs, e->u.extra, sizeof(struct filesys_stats));
  1692. return set_user(&USERENTRY_FSTAT, u, fs);
  1693. }
  1694. return 0;
  1695. }
  1696. static void stats_add_dnload(struct userrec *u, unsigned long bytes)
  1697. {
  1698. struct user_entry *ue;
  1699. register struct filesys_stats *fs;
  1700. if (u) {
  1701. if (!(ue = find_user_entry (&USERENTRY_FSTAT, u)) ||
  1702. !(fs = ue->u.extra)) {
  1703. fs = user_malloc(sizeof(struct filesys_stats));
  1704. egg_bzero(fs, sizeof(struct filesys_stats));
  1705. }
  1706. fs->dnloads++;
  1707. fs->dnload_ks += ((bytes + 512) / 1024);
  1708. set_user(&USERENTRY_FSTAT, u, fs);
  1709. /* No shareout here, set_user already sends info... --rtc */
  1710. }
  1711. }
  1712. static void stats_add_upload(struct userrec *u, unsigned long bytes)
  1713. {
  1714. struct user_entry *ue;
  1715. register struct filesys_stats *fs;
  1716. if (u) {
  1717. if (!(ue = find_user_entry (&USERENTRY_FSTAT, u)) ||
  1718. !(fs = ue->u.extra)) {
  1719. fs = user_malloc(sizeof(struct filesys_stats));
  1720. egg_bzero(fs, sizeof(struct filesys_stats));
  1721. }
  1722. fs->uploads++;
  1723. fs->upload_ks += ((bytes + 512) / 1024);
  1724. set_user(&USERENTRY_FSTAT, u, fs);
  1725. /* No shareout here, set_user already sends info... --rtc */
  1726. }
  1727. }
  1728. static int fstat_tcl_set(Tcl_Interp *irp, struct userrec *u,
  1729. struct user_entry *e, int argc, char **argv)
  1730. {
  1731. register struct filesys_stats *fs;
  1732. int f = 0, k = 0;
  1733. BADARGS(4, 6, " handle FSTAT u/d ?files ?ks??");
  1734. if (argc > 4)
  1735. f = atoi(argv[4]);
  1736. if (argc > 5)
  1737. k = atoi(argv[5]);
  1738. switch (argv[3][0]) {
  1739. case 'u':
  1740. case 'd':
  1741. if (!(fs = e->u.extra)) {
  1742. fs = user_malloc(sizeof(struct filesys_stats));
  1743. egg_bzero(fs, sizeof(struct filesys_stats));
  1744. }
  1745. switch (argv[3][0]) {
  1746. case 'u':
  1747. fs->uploads = f;
  1748. fs->upload_ks = k;
  1749. break;
  1750. case 'd':
  1751. fs->dnloads = f;
  1752. fs->dnload_ks = k;
  1753. break;
  1754. }
  1755. set_user (&USERENTRY_FSTAT, u, fs);
  1756. break;
  1757. case 'r':
  1758. set_user (&USERENTRY_FSTAT, u, NULL);
  1759. break;
  1760. }
  1761. return TCL_OK;
  1762. }
  1763. /*
  1764. * CTCP functions
  1765. */
  1766. /* This handles DCC RESUME requests.
  1767. */
  1768. static int ctcp_DCC_RESUME(char *nick, char *from, char *handle,
  1769. char *object, char *keyword, char *text)
  1770. {
  1771. char *action, *fn, buf[512], *msg = buf;
  1772. int i, port;
  1773. unsigned long offset;
  1774. strcpy(msg, text);
  1775. action = newsplit(&msg);
  1776. if (egg_strcasecmp(action, "RESUME"))
  1777. return 0;
  1778. fn = newsplit(&msg);
  1779. port = atoi(newsplit(&msg));
  1780. offset = my_atoul(newsplit(&msg));
  1781. /* Search for existing SEND */
  1782. for (i = 0; i < dcc_total; i++)
  1783. if ((dcc[i].type == &DCC_GET_PENDING) &&
  1784. (!rfc_casecmp(dcc[i].nick, nick)) && (dcc[i].port == port))
  1785. break;
  1786. /* No matching transfer found? */
  1787. if (i == dcc_total)
  1788. return 0;
  1789. if (dcc[i].u.xfer->length <= offset) {
  1790. char *p = strrchr(dcc[i].u.xfer->origname, '/');
  1791. dprintf(DP_HELP,TRANSFER_DCC_IGNORED,
  1792. nick, p ? p + 1 : dcc[i].u.xfer->origname);
  1793. return 0;
  1794. }
  1795. dcc[i].u.xfer->type = XFER_RESUME_PEND;
  1796. dcc[i].u.xfer->offset = offset;
  1797. dprintf(DP_HELP, "PRIVMSG %s :\001DCC ACCEPT %s %d %u\001\n", nick,
  1798. fn, port, offset);
  1799. /* Now we wait for the client to connect. */
  1800. return 1;
  1801. }
  1802. static cmd_t transfer_ctcps[] =
  1803. {
  1804. {"DCC", "", ctcp_DCC_RESUME, "transfer:DCC"},
  1805. {NULL, NULL, NULL, NULL}
  1806. };
  1807. /* Add our CTCP bindings if the server module is loaded. */
  1808. static int server_transfer_setup(char *mod)
  1809. {
  1810. p_tcl_bind_list H_ctcp;
  1811. if ((H_ctcp = find_bind_table("ctcp")))
  1812. add_builtins(H_ctcp, transfer_ctcps);
  1813. return 1;
  1814. }
  1815. static cmd_t transfer_load[] =
  1816. {
  1817. {"server", "", server_transfer_setup, NULL},
  1818. {NULL, "", NULL, NULL}
  1819. };
  1820. /*
  1821. * Module functions
  1822. */
  1823. static int transfer_expmem()
  1824. {
  1825. return expmem_fileq();
  1826. }
  1827. static void transfer_report(int idx, int details)
  1828. {
  1829. if (details) {
  1830. dprintf(idx,TRANSFER_STAT_BLOCK,
  1831. dcc_block, (dcc_block == 0) ? " (turbo dcc)" : "", dcc_limit);
  1832. dprintf(idx,TRANSFER_STAT_MEMORY, transfer_expmem());
  1833. }
  1834. }
  1835. EXPORT_SCOPE char *transfer_start();
  1836. static Function transfer_table[] =
  1837. {
  1838. (Function) transfer_start,
  1839. (Function) NULL,
  1840. (Function) transfer_expmem,
  1841. (Function) transfer_report,
  1842. /* 4- 7 */
  1843. (Function) & DCC_FORK_SEND, /* struct dcc_table */
  1844. (Function) at_limit,
  1845. (Function) & copy_to_tmp, /* int */
  1846. (Function) fileq_cancel,
  1847. /* 8 - 11 */
  1848. (Function) queue_file,
  1849. (Function) raw_dcc_send,
  1850. (Function) show_queued_files,
  1851. (Function) wild_match_file,
  1852. /* 12 - 15 */
  1853. (Function) wipe_tmp_filename,
  1854. (Function) & DCC_GET, /* struct dcc_table */
  1855. (Function) & H_rcvd, /* p_tcl_bind_list */
  1856. (Function) & H_sent, /* p_tcl_bind_list */
  1857. /* 16 - 19 */
  1858. (Function) & USERENTRY_FSTAT, /* struct user_entry_type */
  1859. (Function) & quiet_reject, /* int */
  1860. (Function) raw_dcc_resend,
  1861. (Function) & H_lost, /* p_tcl_bind_list */
  1862. /* 20 - 23 */
  1863. (Function) & H_tout, /* p_tcl_bind_list */
  1864. };
  1865. char *transfer_start(Function *global_funcs)
  1866. {
  1867. global = global_funcs;
  1868. fileq = NULL;
  1869. module_register(MODULE_NAME, transfer_table, 2, 2);
  1870. if (!(update_funcs = module_depend(MODULE_NAME, "update", 0, 0))) {
  1871. module_undepend(MODULE_NAME);
  1872. return "This module requires update module 0.0 or later.";
  1873. }
  1874. add_tcl_commands(mytcls);
  1875. add_tcl_ints(myints);
  1876. add_builtins(H_load, transfer_load);
  1877. server_transfer_setup(NULL);
  1878. H_rcvd = add_bind_table("rcvd", HT_STACKABLE, builtin_sentrcvd);
  1879. H_sent = add_bind_table("sent", HT_STACKABLE, builtin_sentrcvd);
  1880. H_lost = add_bind_table("lost", HT_STACKABLE, builtin_toutlost);
  1881. H_tout = add_bind_table("tout", HT_STACKABLE, builtin_toutlost);
  1882. USERENTRY_FSTAT.get = def_get;
  1883. add_entry_type(&USERENTRY_FSTAT);
  1884. return NULL;
  1885. }