misc.c 38 KB

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