misc.c 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366
  1. /*
  2. * Copyright (C) 1997 Robey Pointer
  3. * Copyright (C) 1999 - 2002 Eggheads Development Team
  4. * Copyright (C) 2002 - 2008 Bryan Drewery
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version 2
  9. * of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  19. */
  20. /*
  21. * misc.c -- handles:
  22. * split() maskhost() dumplots() daysago() days() daysdur()
  23. * queueing output for the bot (msg and help)
  24. * resync buffers for sharebots
  25. * motd display and %var substitution
  26. *
  27. */
  28. #include "common.h"
  29. #include "misc.h"
  30. #include "settings.h"
  31. #include "binary.h"
  32. #include "rfc1459.h"
  33. #include "botnet.h"
  34. #include "misc_file.h"
  35. #include "egg_timer.h"
  36. #include "dcc.h"
  37. #include "users.h"
  38. #include "shell.h"
  39. #include "main.h"
  40. #include "debug.h"
  41. #include "dccutil.h"
  42. #include "chanprog.h"
  43. #include "color.h"
  44. #include "botmsg.h"
  45. #include "bg.h"
  46. #include "chan.h"
  47. #include "tandem.h"
  48. #include "src/mod/server.mod/server.h"
  49. #include "src/mod/irc.mod/irc.h"
  50. #include "userrec.h"
  51. #include "stat.h"
  52. #include "net.h"
  53. #include <sys/wait.h>
  54. #include <stdarg.h>
  55. #include <sys/types.h>
  56. #include <signal.h>
  57. int server_lag = 0; /* GUESS! */
  58. bool use_invites = 0;
  59. bool use_exempts = 0;
  60. /*
  61. * Misc functions
  62. */
  63. /* low-level stuff for other modules
  64. */
  65. size_t my_strcpy(register char *a, register const char *b)
  66. {
  67. register const char *c = b;
  68. while (*b)
  69. *a++ = *b++;
  70. *a = *b;
  71. return b - c;
  72. }
  73. /* Split first word off of rest and put it in first
  74. */
  75. void splitc(char *first, char *rest, char divider)
  76. {
  77. char *p = strchr(rest, divider);
  78. if (p == NULL) {
  79. if (first != rest && first)
  80. first[0] = 0;
  81. return;
  82. }
  83. *p = 0;
  84. if (first != NULL)
  85. strcpy(first, rest);
  86. if (first != rest)
  87. /* In most circumstances, strcpy with src and dst being the same buffer
  88. * can produce undefined results. We're safe here, as the src is
  89. * guaranteed to be at least 2 bytes higher in memory than dest. <Cybah>
  90. */
  91. strcpy(rest, p + 1);
  92. }
  93. /* As above, but lets you specify the 'max' number of bytes (EXCLUDING the
  94. * terminating null).
  95. *
  96. * Example of use:
  97. *
  98. * char buf[HANDLEN + 1];
  99. *
  100. * splitcn(buf, input, "@", HANDLEN);
  101. *
  102. * <Cybah>
  103. */
  104. void splitcn(char *first, char *rest, char divider, size_t max)
  105. {
  106. char *p = strchr(rest, divider);
  107. if (p == NULL) {
  108. if (first != rest && first)
  109. first[0] = 0;
  110. return;
  111. }
  112. *p = 0;
  113. if (first != NULL)
  114. strlcpy(first, rest, max);
  115. if (first != rest)
  116. /* In most circumstances, strcpy with src and dst being the same buffer
  117. * can produce undefined results. We're safe here, as the src is
  118. * guaranteed to be at least 2 bytes higher in memory than dest. <Cybah>
  119. */
  120. strcpy(rest, p + 1);
  121. }
  122. char *splitnick(char **blah)
  123. {
  124. char *p = NULL, *q = *blah;
  125. p = strchr(*blah, '!');
  126. if (p) {
  127. *p = 0;
  128. *blah = p + 1;
  129. return q;
  130. }
  131. return "";
  132. }
  133. int remove_crlf(char *line)
  134. {
  135. char *p = NULL;
  136. int removed = 0;
  137. if ((p = strchr(line, '\n'))) {
  138. *p = 0;
  139. removed++;
  140. }
  141. if ((p = strchr(line, '\r'))) {
  142. *p = 0;
  143. removed++;
  144. }
  145. return removed;
  146. }
  147. int remove_crlf_r(char *line)
  148. {
  149. char *p = NULL;
  150. int removed = 0;
  151. if ((p = strrchr(line, '\n'))) {
  152. *p = 0;
  153. removed++;
  154. }
  155. if ((p = strrchr(line, '\r'))) {
  156. *p = 0;
  157. removed++;
  158. }
  159. return removed;
  160. }
  161. char *newsplit(char **rest)
  162. {
  163. if (!rest)
  164. return *rest = "";
  165. register char *o = *rest, *r = NULL;
  166. while (*o == ' ')
  167. o++;
  168. r = o;
  169. while (*o && (*o != ' '))
  170. o++;
  171. if (*o)
  172. *o++ = 0;
  173. *rest = o;
  174. return r;
  175. }
  176. /* Convert "abc!user@a.b.host" into "*!user@*.b.host"
  177. * or "abc!user@1.2.3.4" into "*!user@1.2.3.*"
  178. * or "abc!user@0:0:0:0:0:ffff:1.2.3.4" into "*!user@0:0:0:0:0:ffff:1.2.3.*"
  179. * or "abc!user@3ffe:604:2:b02e:6174:7265:6964:6573" into
  180. * "*!user@3ffe:604:2:b02e:6174:7265:6964:*"
  181. */
  182. void maskhost(const char *s, char *nw)
  183. {
  184. register const char *p, *q, *e, *f;
  185. int i;
  186. *nw++ = '*';
  187. *nw++ = '!';
  188. p = (q = strchr(s, '!')) ? q + 1 : s;
  189. /* Strip of any nick, if a username is found, use last 8 chars */
  190. if ((q = strchr(p, '@'))) {
  191. int fl = 0;
  192. if ((q - p) > 9) {
  193. nw[0] = '*';
  194. p = q - 7;
  195. i = 1;
  196. } else
  197. i = 0;
  198. while (*p != '@') {
  199. if (!fl && strchr("~+-^=", *p))
  200. nw[i] = '?';
  201. else
  202. nw[i] = *p;
  203. fl++;
  204. p++;
  205. i++;
  206. }
  207. nw[i++] = '@';
  208. q++;
  209. } else {
  210. nw[0] = '*';
  211. nw[1] = '@';
  212. i = 2;
  213. q = s;
  214. }
  215. nw += i;
  216. e = NULL;
  217. /* Now q points to the hostname, i point to where to put the mask */
  218. if ((!(p = strchr(q, '.')) || !(e = strchr(p + 1, '.'))) && !strchr(q, ':'))
  219. /* TLD or 2 part host */
  220. strcpy(nw, q);
  221. else {
  222. if (e == NULL) { /* IPv6 address? */
  223. const char *mask_str;
  224. f = strrchr(q, ':');
  225. if (strchr(f, '.')) { /* IPv4 wrapped in an IPv6? */
  226. f = strrchr(f, '.');
  227. mask_str = ".*";
  228. } else /* ... no, true IPv6. */
  229. mask_str = ":*";
  230. strncpy(nw, q, f - q);
  231. /* No need to nw[f-q] = 0 here, as the strcpy below will
  232. * terminate the string for us.
  233. */
  234. nw += (f - q);
  235. strcpy(nw, mask_str);
  236. } else {
  237. for (f = e; *f; f++);
  238. f--;
  239. if (*f >= '0' && *f <= '9') { /* Numeric IP address */
  240. while (*f != '.')
  241. f--;
  242. strncpy(nw, q, f - q);
  243. /* No need to nw[f-q] = 0 here, as the strcpy below will
  244. * terminate the string for us.
  245. */
  246. nw += (f - q);
  247. strcpy(nw, ".*");
  248. } else { /* Normal host >= 3 parts */
  249. /* a.b.c -> *.b.c
  250. * a.b.c.d -> *.b.c.d if tld is a country (2 chars)
  251. * OR *.c.d if tld is com/edu/etc (3 chars)
  252. * a.b.c.d.e -> *.c.d.e etc
  253. */
  254. const char *x = strchr(e + 1, '.');
  255. if (!x)
  256. x = p;
  257. else if (strchr(x + 1, '.'))
  258. x = e;
  259. else if (strlen(x) == 3)
  260. x = p;
  261. else
  262. x = e;
  263. simple_sprintf(nw, "*%s", x);
  264. }
  265. }
  266. }
  267. }
  268. /* Convert an interval (in seconds) to one of:
  269. * "19 days ago", "1 day ago", "18:12"
  270. */
  271. void daysago(time_t mynow, time_t then, char *out)
  272. {
  273. if (mynow - then > 86400) {
  274. int mydays = (mynow - then) / 86400;
  275. simple_sprintf(out, "%d day%s ago", mydays, (mydays == 1) ? "" : "s");
  276. return;
  277. }
  278. egg_strftime(out, 6, "%H:%M", gmtime(&then));
  279. }
  280. /* Convert an interval (in seconds) to one of:
  281. * "in 19 days", "in 1 day", "at 18:12"
  282. */
  283. void days(time_t mynow, time_t then, char *out)
  284. {
  285. if (mynow - then > 86400) {
  286. int mydays = (mynow - then) / 86400;
  287. simple_sprintf(out, "in %d day%s", mydays, (mydays == 1) ? "" : "s");
  288. return;
  289. }
  290. egg_strftime(out, 9, "at %H:%M", gmtime(&now));
  291. }
  292. /* Convert an interval (in seconds) to one of:
  293. * "for 19 days", "for 1 day", "for 09:10"
  294. */
  295. void daysdur(time_t mynow, time_t then, char *out)
  296. {
  297. if (mynow - then > 86400) {
  298. int mydays = (mynow - then) / 86400;
  299. simple_sprintf(out, "for %d day%s", mydays, (mydays == 1) ? "" : "s");
  300. return;
  301. }
  302. char s[81] = "";
  303. int hrs, mins;
  304. strcpy(out, "for ");
  305. mynow -= then;
  306. hrs = (int) (mynow / 3600);
  307. mins = (int) ((mynow - (hrs * 3600)) / 60);
  308. sprintf(s, "%02d:%02d", hrs, mins);
  309. strcat(out, s);
  310. }
  311. /* show l33t banner */
  312. static const char *wbanner(void) {
  313. /*
  314. .__ __ .__
  315. __ _ ______________ |__|/ |_| |__
  316. \ \/ \/ /\_ __ \__ \ | \ __\ | \
  317. \ / | | \// __ \| || | | Y \
  318. \/\_/ |__| (____ /__||__| |___| /
  319. \/ \/
  320. */
  321. return STR(" .__ __ .__\n__ _ ______________ |__|/ |_| |__\n\\ \\/ \\/ /\\_ __ \\__ \\ | \\ __\\ | \\\n \\ / | | \\// __ \\| || | | Y \\\n \\/\\_/ |__| (____ /__||__| |___| /\n \\/ \\/\n");
  322. #ifdef no
  323. switch (randint(9)) {
  324. case 0: return STR(" .__ __ .__\n__ _ ______________ |__|/ |_| |__\n\\ \\/ \\/ /\\_ __ \\__ \\ | \\ __\\ | \\\n \\ / | | \\// __ \\| || | | Y \\\n \\/\\_/ |__| (____ /__||__| |___| /\n \\/ \\/\n");
  325. case 1: return STR(" _ _ _ \n__ ___ __ __ _(_) |_| |__ \n\\ \\ /\\ / / '__/ _` | | __| '_ \\ \n \\ V V /| | | (_| | | |_| | | |\n \\_/\\_/ |_| \\__,_|_|\\__|_| |_|\n");
  326. //case 2: return STR("@@@ @@@ @@@ @@@@@@@ @@@@@@ @@@ @@@@@@@ @@@ @@@\n@@@ @@@ @@@ @@@@@@@@ @@@@@@@@ @@@ @@@@@@@ @@@ @@@\n@@! @@! @@! @@! @@@ @@! @@@ @@! @@! @@! @@@\n!@! !@! !@! !@! @!@ !@! @!@ !@! !@! !@! @!@\n@!! !!@ @!@ @!@!!@! @!@!@!@! !!@ @!! @!@!@!@!\n!@! !!! !@! !!@!@! !!!@!!!! !!! !!! !!!@!!!!\n!!: !!: !!: !!: :!! !!: !!! !!: !!: !!: !!!\n:!: :!: :!: :!: !:! :!: !:! :!: :!: :!: !:!\n :::: :: ::: :: ::: :: ::: :: :: :: :::\n :: : : : : : : : : : : : : : :\n");
  327. case 3: return STR(" o8o . oooo\n `'' .o8 `888\noooo oooo ooo oooo d8b .oooo. oooo .o888oo 888 .oo.\n `88. `88. .8' `888''8P `P )88b `888 888 888P'Y88b\n `88..]88..8' 888 .oP'888 888 888 888 888\n `888'`888' 888 d8( 888 888 888 . 888 888\n `8' `8' d888b `Y888''8o o888o '888' o888o o888o\n");
  328. case 4: return STR(" *\n * * **\n** *** ** **\n** * ** **\n ** *** **** *** **** ******** **\n ** *** *** * **** **** * **** *** ******** ** ***\n ** *** **** ** **** * *** * *** ** ** * ***\n ** ** ** ** * **** ** ** *** ***\n ** ** ** ** ** ** ** ** ** **\n ** ** ** ** ** ** ** ** ** **\n ** ** ** ** ** ** ** ** ** **\n ** ** * ** ** ** ** ** ** **\n ******* ******* *** ** ** ** ** ** **\n ***** ***** *** ***** ** *** * ** ** **\n *** ** *** ** **\n *\n *\n *\n *\n");
  329. case 5: return STR(" ::: === === :::==== :::==== ::: :::==== ::: ===\n ::: === === ::: === ::: === ::: :::==== ::: ===\n === === === ======= ======== === === ========\n =========== === === === === === === === ===\n ==== ==== === === === === === === === ===\n");
  330. case 6: return STR(" _ _ _ ______ _______ _____ _______ _ _\n | | | |_____/ |_____| | | |_____|\n |__|__| | \\_ | | __|__ | | |\n");
  331. case 7: return STR(" dBPdBPdBP dBBBBBb dBBBBBb dBP dBBBBBBP dBP dBP\n dBP BB\n dBPdBPdBP dBBBBK dBP BB dBP dBP dBBBBBP\n dBPdBPdBP dBP BB dBP BB dBP dBP dBP dBP\n dBBBBBBBP dBP dB' dBBBBBBB dBP dBP dBP dBP\n");
  332. case 8: return STR(" /\n # #/\n ### # ##\n## # ## ##\n## ## ##\n ## ### #### ### /### /### ### ########## /##\n ## ### ###/ ###/ #### / ###/ ########### ## / ###\n ## ### ### ## ###/ ### ## ## ##/ ###\n ## ## ## ## ## ## ## ## ## ##\n ## ## ## ## ## ## ## ## ## ##\n ## ## ## ## ## ## ## ## ## ##\n ## ## ## ## ## ## ## ## ## ##\n ## /# / ## ## /# ## ## ## ##\n ######/ ######/ ### ####/ ## ### /## ## ##\n ##### ##### ### ### ##/##/ ## ## ##\n /\n /\n /\n /");
  333. }
  334. return "";
  335. #endif
  336. }
  337. void show_banner(int idx)
  338. {
  339. /* we use sock so that colors aren't applied to banner */
  340. if (dcc[idx].status & STAT_BANNER)
  341. dumplots(-dcc[idx].sock, "", wbanner());
  342. dprintf(idx, " \n");
  343. dprintf(-dcc[idx].sock, STR(" -------------------------------------------------------- \n"));
  344. dprintf(-dcc[idx].sock, STR("| - http://wraith.botpack.net/ - |\n"));
  345. dprintf(-dcc[idx].sock, STR("| Get Shell/Irc/Web hosting @ http://www.xzibition.com |\n"));
  346. dprintf(-dcc[idx].sock, STR("| Use coupon code 'wraith' for 30%% off lifetime |\n"));
  347. dprintf(-dcc[idx].sock, STR(" -------------------------------------------------------- \n"));
  348. dprintf(idx, " \n");
  349. }
  350. /* show motd to dcc chatter */
  351. void show_motd(int idx)
  352. {
  353. if (motd[0]) {
  354. char *who = NULL, *buf = NULL, *buf_ptr = NULL, date[50] = "";
  355. time_t when;
  356. buf = buf_ptr = strdup(motd);
  357. who = newsplit(&buf);
  358. when = atoi(newsplit(&buf));
  359. egg_strftime(date, sizeof date, "%c %Z", gmtime(&when));
  360. dprintf(idx, "Motd set by %s%s%s (%s)\n", BOLD(idx), who, BOLD_END(idx), date);
  361. dumplots(idx, "* ", replace(buf, "\\n", "\n"));
  362. dprintf(idx, " \n");
  363. free(buf_ptr);
  364. } else
  365. dprintf(idx, "Motd: none\n");
  366. }
  367. void show_channels(int idx, char *handle)
  368. {
  369. struct chanset_t *chan = NULL;
  370. struct flag_record fr = { FR_CHAN | FR_GLOBAL, 0, 0, 0 };
  371. struct userrec *u = NULL;
  372. int first = 0, total = 0;
  373. size_t l = 0;
  374. char format[120] = "";
  375. if (handle)
  376. u = get_user_by_handle(userlist, handle);
  377. else
  378. u = dcc[idx].user;
  379. for (chan = chanset;chan ;chan = chan->next) {
  380. get_user_flagrec(u, &fr, chan->dname);
  381. if (l < strlen(chan->dname)) {
  382. l = strlen(chan->dname);
  383. }
  384. if (real_chk_op(fr, chan, 0))
  385. total++;
  386. }
  387. egg_snprintf(format, sizeof format, " %%c%%-%us %%-s%%-s%%-s%%-s%%-s%%-s\n", (l+2));
  388. for (chan = chanset;chan;chan = chan->next) {
  389. get_user_flagrec(u, &fr, chan->dname);
  390. if (real_chk_op(fr, chan, 0)) {
  391. if (!first) {
  392. dprintf(idx, "%s %s access to %d channel%s:\n", handle ? u->handle : "You", handle ? "has" : "have", total, (total > 1) ? "s" : "");
  393. first = 1;
  394. }
  395. dprintf(idx, format, !conf.bot->hub && me_op(chan) ? '@' : ' ', chan->dname, !shouldjoin(chan) ? "(inactive) " : "",
  396. channel_privchan(chan) ? "(private) " : "", chan->manop ? "(no manop) " : "",
  397. channel_bitch(chan) && !channel_botbitch(chan) ? "(bitch) " : channel_botbitch(chan) ? "(botbitch) " : "",
  398. channel_closed(chan) ? "(closed) " : "", channel_backup(chan) ? "(backup)" : "");
  399. }
  400. }
  401. if (!first)
  402. dprintf(idx, "%s %s not have access to any channels.\n", handle ? u->handle : "You", handle ? "does" : "do");
  403. }
  404. /* Create a string with random letters and digits
  405. */
  406. void make_rand_str(char *s, size_t len)
  407. {
  408. int r = 0;
  409. size_t j = 0;
  410. for (j = 0; j < len; j++) {
  411. r = randint(4);
  412. if (r == 0)
  413. s[j] = '0' + randint(10);
  414. else if (r == 1)
  415. s[j] = 'a' + randint(26);
  416. else if (r == 2)
  417. s[j] = 'A' + randint(26);
  418. else if (r == 3)
  419. s[j] = RANDSPECIAL[randint(RANDSPECIALLEN)];
  420. if (j && strchr(BADREPEATEDRAND, s[j]) && s[j] == s[j - 1]) {
  421. while (s[j] == s[j - 1])
  422. s[j] = 'A' + randint(26);
  423. }
  424. }
  425. if (strchr(BADPASSCHARS, s[0]))
  426. s[0] = 'a' + randint(26);
  427. s[len] = '\0';
  428. }
  429. /* Return an allocated buffer which contains a copy of the string
  430. * 'str', with all 'div' characters escaped by 'mask'. 'mask'
  431. * characters are escaped too.
  432. *
  433. * Remember to free the returned memory block.
  434. */
  435. char *str_escape(const char *str, const char divc, const char mask)
  436. {
  437. const size_t len = strlen(str);
  438. size_t buflen = (2 * len), blen = 0;
  439. char *buf = NULL, *b = NULL;
  440. const char *s = NULL;
  441. b = buf = (char *) my_calloc(1, buflen + 1);
  442. for (s = str; *s; s++) {
  443. /* Resize buffer. */
  444. if ((buflen - blen) <= 3) {
  445. buflen <<= 1; /* * 2 */
  446. buf = (char *) my_realloc(buf, buflen + 1);
  447. if (!buf)
  448. return NULL;
  449. b = buf + blen;
  450. }
  451. if (*s == divc || *s == mask) {
  452. sprintf(b, "%c%02x", mask, *s);
  453. b += 3;
  454. blen += 3;
  455. } else {
  456. *(b++) = *s;
  457. blen++;
  458. }
  459. }
  460. *b = 0;
  461. return buf;
  462. }
  463. /* Search for a certain character 'div' in the string 'str', while
  464. * ignoring escaped characters prefixed with 'mask'.
  465. *
  466. * The string
  467. *
  468. * "\\3a\\5c i am funny \\3a):further text\\5c):oink"
  469. *
  470. * as str, '\\' as mask and ':' as div would change the str buffer
  471. * to
  472. *
  473. * ":\\ i am funny :)"
  474. *
  475. * and return a pointer to "further text\\5c):oink".
  476. *
  477. * NOTE: If you look carefully, you'll notice that strchr_unescape()
  478. * behaves differently than strchr().
  479. */
  480. char *strchr_unescape(char *str, const char divc, register const char esc_char)
  481. {
  482. char buf[3] = "";
  483. register char *s = NULL, *p = NULL;
  484. for (s = p = str; *s; s++, p++) {
  485. if (*s == esc_char) { /* Found escape character. */
  486. /* Convert code to character. */
  487. buf[0] = s[1], buf[1] = s[2];
  488. *p = (unsigned char) strtol(buf, NULL, 16);
  489. s += 2;
  490. } else if (*s == divc) {
  491. *p = *s = 0;
  492. return (s + 1); /* Found searched for character. */
  493. } else
  494. *p = *s;
  495. }
  496. *p = 0;
  497. return NULL;
  498. }
  499. /* As strchr_unescape(), but converts the complete string, without
  500. * searching for a specific delimiter character.
  501. */
  502. void str_unescape(char *str, register const char esc_char)
  503. {
  504. strchr_unescape(str, 0, esc_char);
  505. return;
  506. }
  507. /* Is every character in a string a digit? */
  508. int str_isdigit(const char *str)
  509. {
  510. if (!str || (str && !*str))
  511. return 0;
  512. if (*str == '-')
  513. str++;
  514. for(; *str; ++str) {
  515. if (!egg_isdigit(*str))
  516. return 0;
  517. }
  518. return 1;
  519. }
  520. /* Kills the bot. s1 is the reason shown to other bots,
  521. * s2 the reason shown on the partyline. (Sup 25Jul2001)
  522. */
  523. void kill_bot(char *s1, char *s2)
  524. {
  525. if (conf.bot->hub)
  526. write_userfile(-1);
  527. else
  528. server_die();
  529. chatout("*** %s\n", s1);
  530. botnet_send_chat(-1, conf.bot->nick, s1);
  531. botnet_send_bye(s2);
  532. fatal(s2, 0);
  533. }
  534. void
  535. readsocks(const char *fname)
  536. {
  537. /* Don't bother setting this if a hub
  538. ... it is only intended to prevent parting channels (in bot_shouldjoin())
  539. */
  540. if (!conf.bot->hub)
  541. restarting = 1;
  542. FILE *f = NULL;
  543. if (!(f = fopen(fname, "r"))) {
  544. fatal(STR("CANT READ SOCKSFILE"), 0);
  545. }
  546. char buf[1024] = "", *nick = NULL, *jnick = NULL, *bufp = NULL, *type = NULL, *buf_ptr = NULL, *ip4 = NULL, *ip6 = NULL;
  547. time_t old_buildts = 0;
  548. bool enc = 0, first = 1;
  549. while (fgets(buf, sizeof(buf), f) != NULL) {
  550. remove_crlf(buf);
  551. if (first) {
  552. if (!strncmp(buf, STR("+enc"), 4))
  553. enc = 1;
  554. first = 0;
  555. }
  556. if (enc)
  557. bufp = buf_ptr = decrypt_string(settings.salt1, buf);
  558. else
  559. bufp = buf;
  560. // dprintf(DP_STDOUT, "read line: %s\n", buf);
  561. type = newsplit(&bufp);
  562. if (!strcmp(type, STR("-dcc")))
  563. dprintf(DP_STDOUT, STR("Added dcc: %d\n"), dcc_read(f, enc));
  564. else if (!strcmp(type, STR("-sock")))
  565. dprintf(DP_STDOUT, STR("Added fd: %d\n"), sock_read(f, enc));
  566. else if (!strcmp(type, STR("+online_since")))
  567. online_since = strtol(bufp, NULL, 10);
  568. else if (!strcmp(type, STR("+server_floodless")))
  569. floodless = 1;
  570. else if (!strcmp(type, STR("+buildts")))
  571. old_buildts = strtol(bufp, NULL, 10);
  572. else if (!strcmp(type, STR("+jupenick")))
  573. jnick = strdup(bufp);
  574. else if (!strcmp(type, STR("+botname")))
  575. nick = strdup(bufp);
  576. else if (!strcmp(type, STR("+ip4")))
  577. ip4 = strdup(bufp);
  578. else if (!strcmp(type, STR("+ip6")))
  579. ip6 = strdup(bufp);
  580. if (enc)
  581. free(buf_ptr);
  582. }
  583. restart_time = now;
  584. if (old_buildts && buildts > old_buildts)
  585. restart_was_update = 1;
  586. tell_dcc(DP_STDOUT);
  587. tell_netdebug(DP_STDOUT);
  588. unlink(fname);
  589. fclose(f);
  590. if (jnick) {
  591. var_set_by_name(conf.bot->nick, "jupenick", jnick);
  592. var_set_userentry(conf.bot->nick, "jupenick", jnick);
  593. }
  594. if (nick) {
  595. var_set_by_name(conf.bot->nick, "nick", nick);
  596. var_set_userentry(conf.bot->nick, "nick", nick);
  597. }
  598. if (servidx >= 0) {
  599. char nserv[50] = "";
  600. if ((ip4 && ip6) && (strcmp(ip4, myipstr(AF_INET)) || strcmp(ip6, myipstr(AF_INET6)))) {
  601. if (tands > 0) { /* We're not linked yet.. but for future */
  602. botnet_send_chat(-1, conf.bot->nick, STR("IP changed."));
  603. botnet_send_bye(STR("IP changed."));
  604. }
  605. fatal("brb", 1);
  606. } else {
  607. simple_snprintf(nserv, sizeof(nserv), "%s:%d", dcc[servidx].host, dcc[servidx].port);
  608. add_server(nserv);
  609. curserv = 0;
  610. rehash_server(dcc[servidx].host, nick);
  611. dprintf(DP_DUMP, "VERSION\n");
  612. reset_chans = 1;
  613. }
  614. }
  615. if (nick)
  616. free(nick);
  617. if (jnick)
  618. free(jnick);
  619. if (socksfile)
  620. free(socksfile);
  621. if (ip4)
  622. free(ip4);
  623. if (ip6)
  624. free(ip6);
  625. }
  626. /* Update system code
  627. */
  628. void
  629. restart(int idx)
  630. {
  631. const char *reason = updating ? STR("Updating...") : STR("Restarting...");
  632. Tempfile *socks = new Tempfile("socks");
  633. int fd = 0;
  634. sdprintf("%s", reason);
  635. if (tands > 0) {
  636. botnet_send_chat(-1, conf.bot->nick, (char *) reason);
  637. botnet_send_bye(reason);
  638. }
  639. /* kill all connections except STDOUT/server */
  640. for (fd = 0; fd < dcc_total; fd++) {
  641. if (dcc[fd].type && dcc[fd].type != &SERVER_SOCKET && dcc[fd].sock != STDOUT) {
  642. if (dcc[fd].sock >= 0)
  643. killsock(dcc[fd].sock);
  644. lostdcc(fd);
  645. }
  646. }
  647. fprintf(socks->f, STR("+enc\n"));
  648. /* write out all leftover dcc[] entries */
  649. for (fd = 0; fd < dcc_total; fd++)
  650. if (dcc[fd].type && dcc[fd].sock != STDOUT)
  651. dcc_write(socks->f, fd);
  652. /* write out all leftover socklist[] entries */
  653. for (fd = 0; fd < MAXSOCKS; fd++)
  654. if (socklist[fd].sock != STDOUT)
  655. sock_write(socks->f, fd);
  656. if (server_online) {
  657. if (botname[0])
  658. lfprintf(socks->f, STR("+botname %s\n"), botname);
  659. if (jupenick[0])
  660. lfprintf(socks->f, STR("+jupenick %s\n"), jupenick);
  661. }
  662. lfprintf(socks->f, STR("+online_since %li\n"), online_since);
  663. if (floodless)
  664. lfprintf(socks->f, STR("+server_floodless %d\n"), floodless);
  665. lfprintf(socks->f, STR("+buildts %li\n"), buildts);
  666. lfprintf(socks->f, STR("+ip4 %s\n"), myipstr(AF_INET));
  667. lfprintf(socks->f, STR("+ip6 %s\n"), myipstr(AF_INET6));
  668. fflush(socks->f);
  669. socks->my_close();
  670. if (conf.bot->hub)
  671. write_userfile(idx);
  672. if (server_online) {
  673. do_chanset(NULL, NULL, STR("+inactive"), DO_LOCAL);
  674. dprintf(DP_DUMP, STR("JOIN 0\n"));
  675. }
  676. fixmod(binname);
  677. /* replace image now */
  678. char *argv[4] = { NULL, NULL, NULL, NULL };
  679. argv[0] = strdup(shell_escape(binname));
  680. if (!backgrd || term_z || sdebug) {
  681. char shit[7] = "";
  682. simple_sprintf(shit, STR("-%s%s%s"), !backgrd ? "n" : "", term_z ? "t" : "", sdebug ? "D" : "");
  683. argv[1] = strdup(shit);
  684. argv[2] = strdup(shell_escape(conf.bot->nick));
  685. } else {
  686. argv[1] = strdup(shell_escape(conf.bot->nick));
  687. }
  688. unlink(conf.bot->pid_file);
  689. FILE *fp = NULL;
  690. if (!(fp = fopen(conf.bot->pid_file, "w")))
  691. return;
  692. fprintf(fp, "%d %s\n", getpid(), socks->file);
  693. fclose(fp);
  694. execvp(argv[0], &argv[0]);
  695. /* hopefully this is never reached */
  696. putlog(LOG_MISC, "*", STR("Could not restart: %s"), strerror(errno));
  697. return;
  698. }
  699. #ifdef NO
  700. void
  701. hard_restart(int idx)
  702. {
  703. char buf[1024] = "";
  704. write_userfile(idx);
  705. if (!conf.bot->hub) {
  706. nuke_server((char *) reason); /* let's drop the server connection ASAP */
  707. cycle_time = 0;
  708. }
  709. fatal(idx <= 0x7FF0 ? reason : NULL, 1);
  710. usleep(2000 * 500);
  711. simple_snprintf(buf, sizeof(buf), "%s -B %s\n", shell_escape(binname), shell_escape(conf.bot->nick));
  712. unlink(conf.bot->pid_file); /* if this fails it is ok, cron will restart the bot, *hopefully* */
  713. system(buf); /* start new bot. */
  714. exit(0);
  715. }
  716. #endif
  717. int updatebin(int idx, char *par, int secs)
  718. {
  719. if (!par || !par[0]) {
  720. logidx(idx, "Not enough parameters.");
  721. return 1;
  722. }
  723. char *path = (char *) my_calloc(1, strlen(binname) + strlen(par) + 2);
  724. char *newbin = NULL, buf[DIRMAX] = "";
  725. #ifndef CYGWIN_HACKS
  726. int i;
  727. #endif /* !CYGWIN_HACKS */
  728. strcpy(path, binname);
  729. newbin = strrchr(path, '/');
  730. if (!newbin) {
  731. free(path);
  732. logidx(idx, STR("Don't know current binary name"));
  733. return 1;
  734. }
  735. newbin++;
  736. if (strchr(par, '/')) {
  737. *newbin = 0;
  738. logidx(idx, STR("New binary must be in %s and name must be specified without path information"), path);
  739. free(path);
  740. return 1;
  741. }
  742. strcpy(newbin, par);
  743. #ifdef CYGWIN_HACKS
  744. /* tack on the .exe */
  745. if (!strstr(path, ".exe")) {
  746. path = (char *) my_realloc(path, strlen(path) + 4 + 1);
  747. strcat(path, ".exe");
  748. path[strlen(path)] = 0;
  749. }
  750. #endif /* CYGWIN_HACKS */
  751. if (!strcmp(path, binname)) {
  752. free(path);
  753. logidx(idx, STR("Can't update with the current binary"));
  754. return 1;
  755. }
  756. if (!can_stat(path)) {
  757. logidx(idx, STR("%s can't be accessed"), path);
  758. free(path);
  759. return 1;
  760. }
  761. if (fixmod(path)) {
  762. logidx(idx, STR("Can't set mode 0600 on %s"), path);
  763. free(path);
  764. return 1;
  765. }
  766. /* make a backup just in case. */
  767. simple_snprintf(buf, sizeof(buf), STR("%s/.bin.old"), conf.datadir);
  768. copyfile(binname, buf);
  769. write_settings(path, -1, 0); /* re-write the binary with our packdata */
  770. Tempfile *conffile = new Tempfile("conf");
  771. if (writeconf(NULL, conffile->f, CONF_ENC)) {
  772. putlog(LOG_MISC, "*", STR("Failed to write temporary config file for update."));
  773. delete conffile;
  774. return 1;
  775. }
  776. /* The binary should return '2' when ran with -2, if not it's probably corrupt. */
  777. #ifndef CYGWIN_HACKS
  778. simple_snprintf(buf, sizeof(buf), STR("%s -2"), shell_escape(path));
  779. putlog(LOG_DEBUG, "*", STR("Running for update binary test: %s"), buf);
  780. i = system(buf);
  781. if (i == -1 || WEXITSTATUS(i) != 2) {
  782. dprintf(idx, STR("Couldn't restart new binary (error %d)\n"), i);
  783. putlog(LOG_MISC, "*", STR("Couldn't restart new binary (error %d)"), i);
  784. delete conffile;
  785. return i;
  786. }
  787. #endif /* !CYGWIN_HACKS */
  788. /* now to send our config to the new binary */
  789. #ifndef CYGWIN_HACKS
  790. simple_snprintf(buf, sizeof(buf), STR("%s -4 %s"), shell_escape(path), conffile->file);
  791. putlog(LOG_DEBUG, "*", STR("Running for update conf: %s"), buf);
  792. i = system(buf);
  793. delete conffile;
  794. if (i == -1 || WEXITSTATUS(i) != 6) { /* 6 for successfull config read/write */
  795. dprintf(idx, STR("Couldn't pass config to new binary (error %d)\n"), i);
  796. putlog(LOG_MISC, "*", STR("Couldn't pass config to new binary (error %d)"), i);
  797. return i;
  798. }
  799. #endif /* !CYGWIN_HACKS */
  800. #ifdef CYGWIN_HACKS
  801. {
  802. size_t binsize = conffile->len + 7 + 1;
  803. char *tmpbuf = (char *) my_calloc(1, binsize);
  804. simple_snprintf(tmpbuf, binsize, "%sbin.old.exe", conffile->file);
  805. tmpbuf[binsize - 1] = 0;
  806. movefile(binname, tmpbuf);
  807. free(tmpbuf);
  808. }
  809. #endif /* CYGWIN_HACKS */
  810. if (movefile(path, binname)) {
  811. logidx(idx, STR("Can't rename %s to %s"), path, binname);
  812. free(path);
  813. return 1;
  814. }
  815. if (updating == UPDATE_EXIT) { /* dont restart/kill/spawn bots, just die ! */
  816. printf(STR("* Moved binary to: %s\n"), binname);
  817. fatal(STR("Binary updated."), 0);
  818. }
  819. if (updating == UPDATE_AUTO) {
  820. /* Make all other bots do a soft restart */
  821. conf_checkpids(conf.bots);
  822. conf_killbot(conf.bots, NULL, NULL, SIGHUP);
  823. if (conf.bot->pid)
  824. kill(conf.bot->pid, SIGHUP);
  825. exit(0);
  826. }
  827. if (!conf.bot->hub && secs > 0) {
  828. /* Make all other bots do a soft restart */
  829. conf_checkpids(conf.bots);
  830. conf_killbot(conf.bots, NULL, NULL, SIGHUP);
  831. /* invoked with -u */
  832. if (updating == UPDATE_AUTO) {
  833. if (conf.bot->pid)
  834. kill(conf.bot->pid, SIGHUP);
  835. exit(0);
  836. }
  837. /* this odd statement makes it so specifying 1 sec will restart other bots running
  838. * and then just restart with no delay */
  839. updating = UPDATE_AUTO;
  840. if (secs > 1) {
  841. egg_timeval_t howlong;
  842. howlong.sec = secs;
  843. howlong.usec = 0;
  844. timer_create_complex(&howlong, STR("restarting for update"), (Function) restart, (void *) idx, 0);
  845. } else
  846. restart(idx);
  847. return 0;
  848. } else
  849. restart(idx); /* no timer */
  850. /* this should never be reached */
  851. return 2;
  852. }
  853. int bot_aggressive_to(struct userrec *u)
  854. {
  855. char mypval[20] = "", botpval[20] = "";
  856. link_pref_val(u, botpval);
  857. link_pref_val(conf.bot->u, mypval);
  858. // sdprintf("botpval: %s", botpval);
  859. // sdprintf("mypval: %s", mypval);
  860. if (strcmp(mypval, botpval) < 0)
  861. return 1;
  862. else
  863. return 0;
  864. }
  865. int goodpass(char *pass, int idx, char *nick)
  866. {
  867. if (!pass[0])
  868. return 0;
  869. char tell[201] = "", last = 0;
  870. int nalpha = 0, lcase = 0, ucase = 0, ocase = 0, tc, repeats = 0, score = 0;
  871. size_t length = strlen(pass);
  872. if (strchr(BADPASSCHARS, pass[0])) {
  873. simple_snprintf(tell, sizeof(tell), "Passes may not begin with '-'");
  874. goto fail;
  875. }
  876. for (int i = 0; i < (signed) length; i++) {
  877. if (pass[i] == last)
  878. repeats++;
  879. tc = (int) pass[i];
  880. if (tc < 58 && tc > 47)
  881. ocase++; /* number */
  882. else if (tc < 91 && tc > 64)
  883. ucase++; /* upper case */
  884. else if (tc < 123 && tc > 96)
  885. lcase++; /* lower case */
  886. else
  887. nalpha++; /* non-alphabet/number */
  888. last = pass[i];
  889. }
  890. score += ocase * 3;
  891. score += nalpha * 2;
  892. score += ucase * 2;
  893. score += lcase * 1;
  894. score += length * 1;
  895. score -= repeats * 1;
  896. simple_snprintf(tell, sizeof(tell), "Password NOT set due to being too weak. Try more characters, numbers, capitals");
  897. if (score < 16) {
  898. fail:
  899. if (idx)
  900. dprintf(idx, "%s\n", tell);
  901. else if (nick[0])
  902. dprintf(DP_HELP, "NOTICE %s :%s\n", nick, tell);
  903. return 0;
  904. }
  905. return 1;
  906. }
  907. #define REPLACES 10
  908. char *replace(const char *string, const char *oldie, const char *newbie)
  909. {
  910. if (string == NULL || !string[0])
  911. return (char *) string;
  912. if (oldie == NULL || !oldie[0])
  913. return (char *) string;
  914. char *c = NULL;
  915. if ((c = (char *) strstr(string, oldie)) == NULL)
  916. return (char *) string;
  917. static int n = 0;
  918. static char newstring_buf[REPLACES][1024];
  919. char *newstring = newstring_buf[n++];
  920. egg_memset(newstring, 0, 1024);
  921. if (n == REPLACES)
  922. n = 0;
  923. const size_t new_len = strlen(newbie), old_len = strlen(oldie), end = (strlen(string) - old_len);
  924. size_t str_index = 0, newstr_index = 0, oldie_index = c - string, cpy_len;
  925. while(str_index <= end && c != NULL) {
  926. cpy_len = oldie_index-str_index;
  927. strncpy(newstring + newstr_index, string + str_index, cpy_len);
  928. newstr_index += cpy_len;
  929. str_index += cpy_len;
  930. strcpy(newstring + newstr_index, newbie);
  931. newstr_index += new_len;
  932. str_index += old_len;
  933. if((c = (char *) strstr(string + str_index, oldie)) != NULL)
  934. oldie_index = c - string;
  935. }
  936. strcpy(newstring + newstr_index, string + str_index);
  937. return (newstring);
  938. }
  939. char* replace_vars(char *buf) {
  940. return replace(buf, "$n", botname);
  941. }
  942. void showhelp(int idx, struct flag_record *flags, const char *string)
  943. {
  944. struct flag_record fr = {FR_GLOBAL | FR_CHAN, 0, 0, 0 };
  945. char *helpstr = (char *) my_calloc(1, strlen(string) + 1000 + 1);
  946. char tmp[2] = "", flagstr[10] = "";
  947. bool ok = 1;
  948. while (string && string[0]) {
  949. if (*string == '%') {
  950. if (!strncmp(string + 1, "{+", 2)) {
  951. while (*string && *string != '+') {
  952. string++;
  953. }
  954. flagstr[0] = 0;
  955. while (*string && *string != '}') {
  956. simple_snprintf(tmp, sizeof(tmp), "%c", *string);
  957. strcat(flagstr, tmp);
  958. string++;
  959. }
  960. string++;
  961. break_down_flags(flagstr, &fr, NULL);
  962. if (flagrec_ok(&fr, flags)) {
  963. ok = 1;
  964. while (*string && *string != '%') {
  965. simple_snprintf(tmp, sizeof(tmp), "%c", *string);
  966. strcat(helpstr, tmp);
  967. string++;
  968. }
  969. if (!strncmp(string + 1, "{-", 2)) {
  970. ok = 1;
  971. while (*string && *string != '}') {
  972. string++;
  973. }
  974. string++;
  975. }
  976. } else {
  977. ok = 0;
  978. }
  979. } else if (!strncmp(string + 1, "{-", 2)) {
  980. ok = 1;
  981. while (*string && *string != '}') {
  982. string++;
  983. }
  984. string++;
  985. } else if (*string == '{') {
  986. while (*string && *string != '}') {
  987. string++;
  988. }
  989. } else if (*(string + 1) == 'd') {
  990. string += 2;
  991. if (dcc[idx].u.chat->channel >= 0)
  992. strcat(helpstr, settings.dcc_prefix);
  993. } else if (*(string + 1) == '%') {
  994. string += 2;
  995. strcat(helpstr, "%");
  996. } else {
  997. if (ok) {
  998. simple_snprintf(tmp, sizeof(tmp), "%c", *string);
  999. strcat(helpstr, tmp);
  1000. }
  1001. string++;
  1002. }
  1003. } else {
  1004. if (ok) {
  1005. simple_snprintf(tmp, sizeof(tmp), "%c", *string);
  1006. strcat(helpstr, tmp);
  1007. }
  1008. string++;
  1009. }
  1010. }
  1011. helpstr[strlen(helpstr)] = 0;
  1012. if (helpstr[0]) dumplots(idx, "", helpstr);
  1013. free(helpstr);
  1014. }
  1015. /* Arrange the N elements of ARRAY in random order. */
  1016. void shuffleArray(char* array[], size_t n)
  1017. {
  1018. for (size_t i = 0; i < n; i++) {
  1019. const size_t j = randint(n);
  1020. char* temp = array[j];
  1021. array[j] = array[i];
  1022. array[i] = temp;
  1023. }
  1024. }
  1025. void shuffle(char *string, char *delim)
  1026. {
  1027. char *array[501], *str = NULL, *work = NULL;
  1028. size_t len = 0;
  1029. egg_bzero(&array, sizeof array);
  1030. work = strdup(string);
  1031. str = strtok(work, delim);
  1032. while(str && *str)
  1033. {
  1034. array[len] = str;
  1035. len++;
  1036. str = strtok((char*) NULL, delim);
  1037. }
  1038. shuffleArray(array, len);
  1039. string[0] = 0;
  1040. for (size_t i = 0; i < len; i++) {
  1041. strcat(string, array[i]);
  1042. if (i != len - 1)
  1043. strcat(string, delim);
  1044. }
  1045. free(work);
  1046. string[strlen(string)] = 0;
  1047. }
  1048. /* returns
  1049. 1: use ANSI
  1050. 2: use mIRC
  1051. 0: neither
  1052. */
  1053. int
  1054. coloridx(int idx)
  1055. {
  1056. if (idx == -1) { /* who cares, just show color! */
  1057. return 1; /* ANSI */
  1058. } else if (idx == -2) {
  1059. return 2; /* mIRC */
  1060. /* valid idx and NOT relaying */
  1061. } else if (idx >= 0) {
  1062. if (dcc[idx].irc || dcc[idx].bot) {
  1063. return 0;
  1064. } else if ((dcc[idx].status & STAT_COLOR) && (dcc[idx].type && dcc[idx].type != &DCC_RELAYING)) {
  1065. /* telnet probably wants ANSI, even though it might be a relay from an mIRC client; fuck`em */
  1066. if (dcc[idx].status & STAT_TELNET)
  1067. return 1;
  1068. /* non-telnet is probably a /dcc-chat, most irc clients support mIRC codes... */
  1069. else
  1070. return 2;
  1071. }
  1072. }
  1073. return 0;
  1074. }
  1075. const char *
  1076. color(int idx, int type, int which)
  1077. {
  1078. int ansi = 0;
  1079. /* if user is connected over TELNET or !backgrd, show ANSI
  1080. * if they are relaying, they are most likely on an IRC client and should have mIRC codes
  1081. */
  1082. if ((ansi = coloridx(idx)) == 0)
  1083. return "";
  1084. if (ansi == 2)
  1085. ansi = 0;
  1086. if (type == BOLD_OPEN) {
  1087. return ansi ? "\033[1m" : "\002";
  1088. } else if (type == BOLD_CLOSE) {
  1089. // return ansi ? "\033[22m" : "\002";
  1090. return ansi ? "\033[0m" : "\002";
  1091. } else if (type == UNDERLINE_OPEN) {
  1092. return ansi ? "\033[4m" : "\037";
  1093. } else if (type == UNDERLINE_CLOSE) {
  1094. return ansi ? "\033[24m" : "\037";
  1095. } else if (type == FLASH_OPEN) {
  1096. return ansi ? "\033[5m" : "\002\037";
  1097. } else if (type == FLASH_CLOSE) {
  1098. return ansi ? "\033[0m" : "\037\002";
  1099. } else if (type == COLOR_OPEN) {
  1100. switch (which) {
  1101. case C_BLACK: return ansi ? "\033[30m" : "\00301";
  1102. case C_RED: return ansi ? "\033[31m" : "\00305";
  1103. case C_GREEN: return ansi ? "\033[32m" : "\00303";
  1104. case C_BROWN: return ansi ? "\033[33m" : "\00307";
  1105. case C_BLUE: return ansi ? "\033[34m" : "\00302";
  1106. case C_PURPLE: return ansi ? "\033[35m" : "\00306";
  1107. case C_CYAN: return ansi ? "\033[36m" : "\00310";
  1108. case C_WHITE: return ansi ? "\033[1;37m" : "\00300";
  1109. case C_DARKGREY: return ansi ? "\033[1;30m" : "\00314";
  1110. case C_LIGHTRED: return ansi ? "\033[1;31m" : "\00304";
  1111. case C_LIGHTGREEN: return ansi ? "\033[1;32m" : "\00309";
  1112. case C_LIGHTBLUE: return ansi ? "\033[1;34m" : "\00312";
  1113. case C_LIGHTPURPLE: return ansi ? "\033[1;35m" : "\00313";
  1114. case C_LIGHTCYAN: return ansi ? "\033[1;36m" : "\00311";
  1115. case C_LIGHTGREY: return ansi ? "\033[37m" : "\00315";
  1116. case C_YELLOW: return ansi ? "\033[1;33m" : "\00308";
  1117. default: break;
  1118. }
  1119. } else if (type == COLOR_CLOSE) {
  1120. return ansi ? "\033[0m" : "\00300";
  1121. }
  1122. /* This should never be reached.. */
  1123. return "";
  1124. }
  1125. char *
  1126. strtolower(char *s)
  1127. {
  1128. char *p = s;
  1129. while (*p) {
  1130. *p = tolower(*p);
  1131. p++;
  1132. }
  1133. return s;
  1134. }
  1135. char *
  1136. strtoupper(char *s)
  1137. {
  1138. char *p = s;
  1139. while (*p) {
  1140. *p = toupper(*p);
  1141. p++;
  1142. }
  1143. return s;
  1144. }
  1145. char *step_thru_file(FILE *fd)
  1146. {
  1147. if (fd == NULL) {
  1148. return NULL;
  1149. }
  1150. char tempBuf[1024] = "", *retStr = NULL;
  1151. while (!feof(fd)) {
  1152. fgets(tempBuf, sizeof(tempBuf), fd);
  1153. if (!feof(fd)) {
  1154. if (retStr == NULL) {
  1155. retStr = (char *) my_calloc(1, strlen(tempBuf) + 2);
  1156. strcpy(retStr, tempBuf);
  1157. } else {
  1158. retStr = (char *) my_realloc(retStr, strlen(retStr) + strlen(tempBuf));
  1159. strcat(retStr, tempBuf);
  1160. }
  1161. if (retStr[strlen(retStr)-1] == '\n') {
  1162. retStr[strlen(retStr)-1] = 0;
  1163. break;
  1164. }
  1165. }
  1166. }
  1167. return retStr;
  1168. }
  1169. char *trim(char *string)
  1170. {
  1171. if (string) {
  1172. char *ibuf = NULL, *obuf = NULL;
  1173. for (ibuf = obuf = string; *ibuf; ) {
  1174. while (*ibuf && (isspace (*ibuf)))
  1175. ibuf++;
  1176. if (*ibuf && (obuf != string))
  1177. *(obuf++) = ' ';
  1178. while (*ibuf && (!isspace (*ibuf)))
  1179. *(obuf++) = *(ibuf++);
  1180. }
  1181. *obuf = '\0';
  1182. }
  1183. return (string);
  1184. }
  1185. int skipline (char *line, int *skip) {
  1186. static int multi = 0;
  1187. if (strstr(line, "*/"))
  1188. multi = 0;
  1189. if ( (!strncmp(line, "#", 1)) || (!strncmp(line, ";", 1)) || (!strncmp(line, "//", 2)) ) {
  1190. (*skip)++;
  1191. } else if ( (strstr(line, "/*")) && (strstr(line, "*/")) ) {
  1192. multi = 0;
  1193. (*skip)++;
  1194. } else if ( (strstr(line, "/*")) ) {
  1195. (*skip)++;
  1196. multi = 1;
  1197. } else if ( (strstr(line, "*/")) ) {
  1198. multi = 0;
  1199. } else {
  1200. if (!multi) (*skip) = 0;
  1201. }
  1202. return (*skip);
  1203. }