userent.c 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132
  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. * userent.c -- handles:
  22. * user-entry handling, new stylem more versatile.
  23. *
  24. */
  25. #include "common.h"
  26. #include "users.h"
  27. #include "src/mod/share.mod/share.h"
  28. #include "misc.h"
  29. #include "chanprog.h"
  30. #include "main.h"
  31. #include "debug.h"
  32. #include "userrec.h"
  33. #include "match.h"
  34. #include "dccutil.h"
  35. #include "crypt.h"
  36. #include "botmsg.h"
  37. #include "botnet.h"
  38. #include <bdlib/src/Stream.h>
  39. #include <bdlib/src/String.h>
  40. static struct user_entry_type *entry_type_list = NULL;
  41. void init_userent()
  42. {
  43. add_entry_type(&USERENTRY_COMMENT);
  44. add_entry_type(&USERENTRY_INFO);
  45. add_entry_type(&USERENTRY_LASTON);
  46. add_entry_type(&USERENTRY_BOTADDR);
  47. add_entry_type(&USERENTRY_OS);
  48. add_entry_type(&USERENTRY_NODENAME);
  49. add_entry_type(&USERENTRY_USERNAME);
  50. add_entry_type(&USERENTRY_ARCH);
  51. add_entry_type(&USERENTRY_OSVER);
  52. add_entry_type(&USERENTRY_PASS);
  53. add_entry_type(&USERENTRY_PASS1);
  54. add_entry_type(&USERENTRY_SECPASS);
  55. add_entry_type(&USERENTRY_HOSTS);
  56. add_entry_type(&USERENTRY_STATS);
  57. add_entry_type(&USERENTRY_ADDED);
  58. add_entry_type(&USERENTRY_MODIFIED);
  59. add_entry_type(&USERENTRY_SET);
  60. }
  61. void list_type_kill(struct list_type *t)
  62. {
  63. struct list_type *u = NULL;
  64. while (t) {
  65. u = t->next;
  66. if (t->extra)
  67. free(t->extra);
  68. free(t);
  69. t = u;
  70. }
  71. }
  72. bool def_unpack(struct userrec *u, struct user_entry *e)
  73. {
  74. char *tmp = e->u.list->extra;
  75. e->u.list->extra = NULL;
  76. list_type_kill(e->u.list);
  77. e->u.string = tmp;
  78. return 1;
  79. }
  80. bool def_kill(struct user_entry *e)
  81. {
  82. free(e->u.string);
  83. free(e);
  84. return 1;
  85. }
  86. void write_userfile_protected(bd::Stream& stream, const struct userrec *u, const struct user_entry *e, int idx)
  87. {
  88. int localhub = nextbot(u->handle);
  89. /* only write if saving local, or if sending to hub, or if sending to same user as entry, or the localhub in the chain */
  90. if (idx == -1 || dcc[idx].hub || dcc[idx].user == u || (localhub != -1 && idx == localhub)) {
  91. bd::String buf;
  92. stream << buf.printf("--%s %s\n", e->type->name, e->u.string);
  93. }
  94. }
  95. void def_write_userfile(bd::Stream& stream, const struct userrec *u, const struct user_entry *e, int idx)
  96. {
  97. bd::String buf;
  98. stream << buf.printf("--%s %s\n", e->type->name, e->u.string);
  99. }
  100. void *def_get(struct userrec *u, struct user_entry *e)
  101. {
  102. return e->u.string;
  103. }
  104. bool def_set_real(struct userrec *u, struct user_entry *e, void *buf, bool protect)
  105. {
  106. char *string = (char *) buf;
  107. if (string && !string[0])
  108. string = NULL;
  109. if (!string && !e->u.string)
  110. return 1;
  111. if (string) {
  112. size_t l = strlen (string);
  113. char *i = NULL;
  114. if (l > 160)
  115. l = 160;
  116. e->u.string = (char *) my_realloc (e->u.string, l + 1);
  117. strlcpy (e->u.string, string, l + 1);
  118. for (i = e->u.string; *i; i++)
  119. /* Allow bold, inverse, underline, color text here...
  120. * But never add cr or lf!! --rtc
  121. */
  122. if ((unsigned int) *i < 32 && !strchr ("\002\003\026\037", *i))
  123. *i = '?';
  124. } else { /* string == NULL && e->u.string != NULL */
  125. free(e->u.string);
  126. e->u.string = NULL;
  127. }
  128. if (!noshare) {
  129. if (protect)
  130. shareout_prot(u, "c %s %s %s\n", e->type->name, u->handle, e->u.string ? e->u.string : "");
  131. else
  132. shareout("c %s %s %s\n", e->type->name, u->handle, e->u.string ? e->u.string : "");
  133. }
  134. return 1;
  135. }
  136. bool def_set(struct userrec *u, struct user_entry *e, void *buf)
  137. {
  138. return (def_set_real(u, e, buf, 0));
  139. }
  140. bool set_protected(struct userrec *u, struct user_entry *e, void *buf)
  141. {
  142. return (def_set_real(u, e, buf, 1));
  143. }
  144. bool def_gotshare(struct userrec *u, struct user_entry *e, char *data, int idx)
  145. {
  146. if (conf.bot->hub)
  147. putlog(LOG_DEBUG, "@", "%s: change %s %s", dcc[idx].nick, e->type->name, u->handle);
  148. return e->type->set(u, e, data);
  149. }
  150. void def_display(int idx, struct user_entry *e, struct userrec *u)
  151. {
  152. dprintf(idx, " %s: %s\n", e->type->name, e->u.string);
  153. }
  154. static void comment_display(int idx, struct user_entry *e, struct userrec *u)
  155. {
  156. if (dcc[idx].user && (dcc[idx].user->flags & USER_MASTER))
  157. dprintf(idx, " COMMENT: %s\n", e->u.string);
  158. }
  159. struct user_entry_type USERENTRY_COMMENT =
  160. {
  161. 0, /* always 0 ;) */
  162. def_gotshare,
  163. def_unpack,
  164. def_write_userfile,
  165. def_kill,
  166. def_get,
  167. def_set,
  168. comment_display,
  169. "COMMENT"
  170. };
  171. struct user_entry_type USERENTRY_INFO =
  172. {
  173. 0, /* always 0 ;) */
  174. def_gotshare,
  175. def_unpack,
  176. def_write_userfile,
  177. def_kill,
  178. def_get,
  179. def_set,
  180. def_display,
  181. "INFO"
  182. };
  183. static void added_display(int idx, struct user_entry *e, struct userrec *u)
  184. {
  185. /* format: unixtime handle */
  186. if (dcc[idx].user && (dcc[idx].user->flags & USER_OWNER)) {
  187. char tmp[30] = "", tmp2[70] = "", *hnd = NULL;
  188. time_t tm;
  189. strlcpy(tmp, e->u.string, sizeof(tmp));
  190. hnd = strchr(tmp, ' ');
  191. if (hnd)
  192. *hnd++ = 0;
  193. tm = atoi(tmp);
  194. strftime(tmp2, sizeof(tmp2), "%a, %d %b %Y %H:%M:%S %Z", gmtime(&tm));
  195. if (hnd)
  196. dprintf(idx, " -- Added %s by %s\n", tmp2, hnd);
  197. else
  198. dprintf(idx, " -- Added %s\n", tmp2);
  199. }
  200. }
  201. struct user_entry_type USERENTRY_ADDED = {
  202. 0, /* always 0 ;) */
  203. def_gotshare,
  204. def_unpack,
  205. def_write_userfile,
  206. def_kill,
  207. def_get,
  208. def_set,
  209. added_display,
  210. "ADDED"
  211. };
  212. static bool set_set(struct userrec *u, struct user_entry *e, void *buf)
  213. {
  214. struct xtra_key *curr = (struct xtra_key *) e->u.extra,
  215. *newxk = (struct xtra_key *) buf, *old = NULL;
  216. /* find the curr key if it exists */
  217. for (; curr; curr = curr->next) {
  218. if (curr->key && !strcasecmp(curr->key, newxk->key)) {
  219. old = curr;
  220. break;
  221. }
  222. }
  223. /* we will possibly free new below, so let's send the information to the botnet now */
  224. if (!noshare && !set_noshare)
  225. /* only share to pertinent bots */
  226. shareout_prot(u, "c %s %s %s %s\n", e->type->name, u->handle, newxk->key, newxk->data ? newxk->data : "");
  227. /* unset and bail out if the new data is empty and the old doesn't exist, why'd we even get this change? */
  228. if (!old && (!newxk->data || !newxk->data[0])) {
  229. /* or simply ... delete non-existant entry */
  230. free(newxk->key);
  231. if (newxk->data)
  232. free(newxk->data);
  233. free(newxk);
  234. return 1;
  235. }
  236. /* if we have a new entry and an old entry.. or our new entry is empty -> clear out the old entry */
  237. if ((old && old != newxk) || !newxk->data || !newxk->data[0]) {
  238. list_delete((struct list_type **) (&e->u.extra), (struct list_type *) old);
  239. free(old->key);
  240. free(old->data);
  241. free(old);
  242. }
  243. /* add the new entry if it's not empty */
  244. if (old != newxk && newxk->data) {
  245. if (newxk->data[0]) {
  246. list_insert((struct xtra_key **) (&e->u.extra), newxk);
  247. } else {
  248. if (newxk->data)
  249. free(newxk->data);
  250. free(newxk->key);
  251. free(newxk);
  252. }
  253. }
  254. return 1;
  255. }
  256. static bool set_unpack(struct userrec *u, struct user_entry *e)
  257. {
  258. struct list_type *curr = NULL, *head = NULL;
  259. head = curr = e->u.list;
  260. e->u.extra = NULL;
  261. if (conf.bot->hub || conf.bot->localhub || !strcasecmp(conf.bot->nick, u->handle)) {
  262. struct xtra_key *t = NULL;
  263. char *key = NULL, *data = NULL;
  264. while (curr) {
  265. t = (struct xtra_key *) my_calloc(1, sizeof(struct xtra_key));
  266. data = curr->extra;
  267. key = newsplit(&data);
  268. if (data[0]) {
  269. t->key = strdup(key);
  270. t->data = strdup(data);
  271. list_insert((struct xtra_key **) (&e->u.extra), t);
  272. } else
  273. free(t);
  274. curr = curr->next;
  275. }
  276. }
  277. list_type_kill(head);
  278. return 1;
  279. }
  280. static void set_display(int idx, struct user_entry *e, struct userrec *u)
  281. {
  282. if (conf.bot->hub) {
  283. struct xtra_key *xk = (struct xtra_key *) e->u.extra;
  284. struct flag_record fr = {FR_GLOBAL, 0, 0, 0 };
  285. get_user_flagrec(dcc[idx].user, &fr, NULL);
  286. /* scan thru xtra field, searching for matches */
  287. for (; xk; xk = xk->next) {
  288. /* ok, it's a valid xtra field entry */
  289. if (glob_owner(fr))
  290. dprintf(idx, " %s: %s\n", xk->key, xk->data ? xk->data : "");
  291. }
  292. }
  293. }
  294. static bool set_gotshare(struct userrec *u, struct user_entry *e, char *buf, int idx)
  295. {
  296. char *name = newsplit(&buf);
  297. if (!name || !name[0])
  298. return 1;
  299. if (!strcasecmp(u->handle, conf.bot->nick)) {
  300. set_noshare = 1;
  301. var_set_by_name(conf.bot->nick, name, buf[0] ? buf : NULL);
  302. set_noshare = 0;
  303. /* var_set_by_name() called set_user(), no need to do it again... */
  304. }
  305. /* not else if as the hub might have gotten a botset for itself */
  306. if (conf.bot->hub || conf.bot->localhub) {
  307. /* only hubs need to bother saving this stuff, leaf bots just store it in vars[] */
  308. struct xtra_key *xk = (struct xtra_key *) my_calloc(1, sizeof(struct xtra_key));
  309. xk->key = strdup(name);
  310. xk->data = (buf && buf[0]) ? strdup(buf) : NULL;
  311. set_set(u, e, xk); /* set the USERENTRY */
  312. }
  313. return 1;
  314. }
  315. static void set_write_userfile(bd::Stream& stream, const struct userrec *u, const struct user_entry *e, int idx)
  316. {
  317. int localhub = nextbot(u->handle);
  318. /* only write if saving local, or if sending to hub, or if sending to same user as entry, or the localhub in the chain */
  319. if (idx == -1 || dcc[idx].hub || dcc[idx].user == u || (localhub != -1 && idx == localhub)) {
  320. struct xtra_key *x = (struct xtra_key *) e->u.extra;
  321. bd::String buf;
  322. for (; x; x = x->next)
  323. stream << buf.printf("--%s %s %s\n", e->type->name, x->key, x->data ? x->data : "");
  324. }
  325. }
  326. static bool set_kill(struct user_entry *e)
  327. {
  328. struct xtra_key *x = (struct xtra_key *) e->u.extra, *y = NULL;
  329. for (; x; x = y) {
  330. y = x->next;
  331. free(x->key);
  332. if (x->data)
  333. free(x->data);
  334. free(x);
  335. }
  336. free(e);
  337. return 1;
  338. }
  339. struct user_entry_type USERENTRY_SET = {
  340. 0,
  341. set_gotshare,
  342. set_unpack,
  343. set_write_userfile,
  344. set_kill,
  345. def_get,
  346. set_set,
  347. set_display,
  348. "SET"
  349. };
  350. static void botmisc_display(int idx, struct user_entry *e, struct userrec *u)
  351. {
  352. if (conf.bot->hub) {
  353. struct flag_record fr = {FR_GLOBAL, 0, 0, 0 };
  354. get_user_flagrec(dcc[idx].user, &fr, NULL);
  355. if (glob_admin(fr))
  356. dprintf(idx, " %s: %s\n", e->type->name, e->u.string ? e->u.string : "");
  357. }
  358. }
  359. struct user_entry_type USERENTRY_USERNAME = {
  360. 0,
  361. def_gotshare,
  362. def_unpack,
  363. write_userfile_protected,
  364. def_kill,
  365. def_get,
  366. set_protected,
  367. botmisc_display,
  368. "USERNAME"
  369. };
  370. struct user_entry_type USERENTRY_NODENAME = {
  371. 0,
  372. def_gotshare,
  373. def_unpack,
  374. write_userfile_protected,
  375. def_kill,
  376. def_get,
  377. set_protected,
  378. botmisc_display,
  379. "NODENAME"
  380. };
  381. struct user_entry_type USERENTRY_OS = {
  382. 0,
  383. def_gotshare,
  384. def_unpack,
  385. write_userfile_protected,
  386. def_kill,
  387. def_get,
  388. set_protected,
  389. botmisc_display,
  390. "OS"
  391. };
  392. struct user_entry_type USERENTRY_OSVER = {
  393. 0,
  394. def_gotshare,
  395. def_unpack,
  396. write_userfile_protected,
  397. def_kill,
  398. def_get,
  399. set_protected,
  400. botmisc_display,
  401. "OSVER"
  402. };
  403. struct user_entry_type USERENTRY_ARCH = {
  404. 0,
  405. def_gotshare,
  406. def_unpack,
  407. write_userfile_protected,
  408. def_kill,
  409. def_get,
  410. set_protected,
  411. botmisc_display,
  412. "ARCH"
  413. };
  414. void stats_add(struct userrec *u, int islogin, int op)
  415. {
  416. if (!u || u->bot)
  417. return;
  418. char *s = (char *) get_user(&USERENTRY_STATS, u), s2[50] = "";
  419. int sl, so;
  420. if (s) {
  421. strlcpy(s2, s, sizeof(s2));
  422. } else
  423. strlcpy(s2, "0 0", sizeof(s2));
  424. s = strchr(s2, ' ');
  425. if (s) {
  426. s++;
  427. so = atoi(s);
  428. } else
  429. so = 0;
  430. sl = atoi(s2);
  431. if (islogin)
  432. sl++;
  433. if (op)
  434. so++;
  435. simple_snprintf(s2, sizeof(s2), "%i %i", sl, so);
  436. set_user(&USERENTRY_STATS, u, s2);
  437. }
  438. char s2_8[3] = "",s1_14[3] = "",s2_1[3] = "";
  439. static void stats_display(int idx, struct user_entry *e, struct userrec *u)
  440. {
  441. /* format: logincount opcount */
  442. if (!u->bot && dcc[idx].user && (dcc[idx].user->flags & USER_OWNER)) {
  443. char *p = strchr(e->u.string, ' ');
  444. if (p)
  445. dprintf(idx, " -- %i logins, %i ops\n", atoi(e->u.string), atoi(p));
  446. }
  447. }
  448. struct user_entry_type USERENTRY_STATS = {
  449. 0, /* always 0 ;) */
  450. def_gotshare,
  451. def_unpack,
  452. def_write_userfile,
  453. def_kill,
  454. def_get,
  455. def_set,
  456. stats_display,
  457. "STATS"
  458. };
  459. void update_mod(char *handle, char *nick, char *cmd, char *par)
  460. {
  461. char tmp[100] = "";
  462. simple_snprintf(tmp, sizeof tmp, "%li, %s (%s %s)", (long) now, nick, cmd, (par && par[0]) ? par : "");
  463. set_user(&USERENTRY_MODIFIED, get_user_by_handle(userlist, handle), tmp);
  464. }
  465. static void modified_display(int idx, struct user_entry *e, struct userrec *u)
  466. {
  467. if (e && dcc[idx].user && (dcc[idx].user->flags & USER_MASTER)) {
  468. char tmp[1024] = "", tmp2[1024] = "", *hnd = NULL;
  469. time_t tm;
  470. strlcpy(tmp, e->u.string, sizeof(tmp));
  471. hnd = strchr(tmp, ' ');
  472. if (hnd)
  473. *hnd++ = 0;
  474. tm = atoi(tmp);
  475. strftime(tmp2, sizeof(tmp2), "%a, %d %b %Y %H:%M:%S %Z", gmtime(&tm));
  476. if (hnd)
  477. dprintf(idx, " -- Modified %s by %s\n", tmp2, hnd);
  478. else
  479. dprintf(idx, " -- Modified %s\n", tmp2);
  480. }
  481. }
  482. struct user_entry_type USERENTRY_MODIFIED =
  483. {
  484. 0,
  485. def_gotshare,
  486. def_unpack,
  487. def_write_userfile,
  488. def_kill,
  489. def_get,
  490. def_set,
  491. modified_display,
  492. "MODIFIED"
  493. };
  494. static bool pass_set(struct userrec *u, struct user_entry *e, void *buf)
  495. {
  496. char *newpass = NULL;
  497. register char *pass = (char *) buf;
  498. if (e->u.extra)
  499. free(e->u.extra);
  500. if (!pass || !pass[0] || (pass[0] == '-'))
  501. e->u.extra = NULL;
  502. else {
  503. unsigned char *p = (unsigned char *) pass;
  504. if (u->bot || (pass[0] == '+'))
  505. newpass = strdup(pass);
  506. else {
  507. if (strlen(pass) > MAXPASSLEN)
  508. pass[MAXPASSLEN] = 0;
  509. while (*p) {
  510. if ((*p <= 32) || (*p == 127))
  511. *p = '?';
  512. p++;
  513. }
  514. newpass = salted_sha1(pass);
  515. }
  516. e->u.extra = strdup(newpass);
  517. }
  518. if (!noshare)
  519. shareout("c %s %s %s\n", e->type->name, u->handle, newpass ? newpass : "");
  520. if (newpass)
  521. free(newpass);
  522. /* clear old records */
  523. noshare = 1;
  524. set_user(&USERENTRY_PASS1, u, NULL);
  525. noshare = 0;
  526. return 1;
  527. }
  528. struct user_entry_type USERENTRY_PASS =
  529. {
  530. 0,
  531. def_gotshare,
  532. def_unpack,
  533. def_write_userfile,
  534. def_kill,
  535. def_get,
  536. pass_set,
  537. NULL,
  538. "PASS2"
  539. };
  540. static bool pass1_set(struct userrec *u, struct user_entry *e, void *buf)
  541. {
  542. register char *pass = (char *) buf;
  543. if (e->u.extra)
  544. free(e->u.extra);
  545. if (!pass || !pass[0] || (pass[0] == '-'))
  546. e->u.extra = NULL;
  547. else {
  548. unsigned char *p = (unsigned char *) pass;
  549. while (*p) {
  550. if ((*p <= 32) || (*p == 127))
  551. *p = '?';
  552. p++;
  553. }
  554. if (u->bot || (pass[0] == '+'))
  555. e->u.extra = strdup(pass);
  556. else
  557. e->u.extra = encrypt_string(u->handle, pass);
  558. }
  559. if (!noshare)
  560. shareout("c %s %s %s\n", e->type->name, u->handle, pass ? pass : "");
  561. return 1;
  562. }
  563. struct user_entry_type USERENTRY_PASS1 =
  564. {
  565. 0,
  566. def_gotshare,
  567. def_unpack,
  568. def_write_userfile,
  569. def_kill,
  570. def_get,
  571. pass1_set,
  572. NULL,
  573. "PASS1"
  574. };
  575. static void secpass_display(int idx, struct user_entry *e, struct userrec *u)
  576. {
  577. struct flag_record fr = {FR_GLOBAL, 0, 0, 0 };
  578. get_user_flagrec(dcc[idx].user, &fr, NULL);
  579. if (!strcmp(u->handle, dcc[idx].nick) || (glob_admin(fr) && isowner(dcc[idx].nick))) {
  580. if (conf.bot->hub)
  581. dprintf(idx, " %s: %s\n", e->type->name, e->u.string);
  582. else {
  583. dprintf(idx, " %s: Hidden on leaf bots.", e->type->name);
  584. if (dcc[idx].u.chat->su_nick)
  585. dprintf(idx, " Nice try, %s.", dcc[idx].u.chat->su_nick);
  586. dprintf(idx, "\n");
  587. }
  588. }
  589. }
  590. struct user_entry_type USERENTRY_SECPASS =
  591. {
  592. 0,
  593. def_gotshare,
  594. def_unpack,
  595. def_write_userfile,
  596. def_kill,
  597. def_get,
  598. def_set,
  599. secpass_display,
  600. "SECPASS"
  601. };
  602. static bool laston_unpack(struct userrec *u, struct user_entry *e)
  603. {
  604. char *par = e->u.list->extra, *arg = newsplit(&par);
  605. struct laston_info *li = (struct laston_info *) my_calloc(1, sizeof(struct laston_info));
  606. if (!par[0])
  607. par = "???";
  608. li->laston = atoi(arg);
  609. li->lastonplace = strdup(par);
  610. list_type_kill(e->u.list);
  611. e->u.extra = li;
  612. return 1;
  613. }
  614. static void laston_write_userfile(bd::Stream& stream, const struct userrec *u, const struct user_entry *e, int idx)
  615. {
  616. struct laston_info *li = (struct laston_info *) e->u.extra;
  617. bd::String buf;
  618. stream << buf.printf("--LASTON %li %s\n", (long) li->laston, li->lastonplace ? li->lastonplace : "");
  619. }
  620. static bool laston_kill(struct user_entry *e)
  621. {
  622. if (((struct laston_info *) (e->u.extra))->lastonplace)
  623. free(((struct laston_info *) (e->u.extra))->lastonplace);
  624. free(e->u.extra);
  625. free(e);
  626. return 1;
  627. }
  628. static bool laston_set(struct userrec *u, struct user_entry *e, void *buf)
  629. {
  630. struct laston_info *li = (struct laston_info *) e->u.extra;
  631. if (li != buf) {
  632. if (li) {
  633. free(li->lastonplace);
  634. free(li);
  635. }
  636. li = (struct laston_info *) buf;
  637. e->u.extra = (struct laston_info *) buf;
  638. }
  639. /* FIXME: laston sharing is disabled until a better solution is found
  640. if (!noshare)
  641. shareout("c LASTON %s %s %li\n", u->handle, li->lastonplace ? li->lastonplace : "-", li->laston);
  642. */
  643. return 1;
  644. }
  645. static bool laston_gotshare(struct userrec *u, struct user_entry *e, char *par, int idx)
  646. {
  647. char *where = NULL;
  648. time_t timeval = 0;
  649. if (par[0])
  650. where = newsplit(&par);
  651. if (!strcmp(where, "-"))
  652. where = NULL;
  653. if (par[0])
  654. timeval = atol(newsplit(&par));
  655. touch_laston(u, where, timeval);
  656. return 1;
  657. }
  658. struct user_entry_type USERENTRY_LASTON =
  659. {
  660. 0, /* always 0 ;) */
  661. laston_gotshare,
  662. laston_unpack,
  663. laston_write_userfile,
  664. laston_kill,
  665. def_get,
  666. laston_set,
  667. 0,
  668. "LASTON"
  669. };
  670. static bool botaddr_unpack(struct userrec *u, struct user_entry *e)
  671. {
  672. char p[1024] = "", *q1 = NULL, *q2 = NULL;
  673. struct bot_addr *bi = (struct bot_addr *) my_calloc(1, sizeof(struct bot_addr));
  674. /* address:port/port:hublevel:uplink */
  675. strlcpy(p, e->u.list->extra, sizeof(p));
  676. q1 = strchr(p, ':');
  677. if (q1)
  678. *q1++ = 0;
  679. bi->address = strdup(p);
  680. if (q1) {
  681. q2 = strchr(q1, ':');
  682. if (q2)
  683. *q2++ = 0;
  684. bi->telnet_port = atoi(q1);
  685. q1 = strchr(q1, '/');
  686. if (q1) {
  687. q1++;
  688. bi->relay_port = atoi(q1);
  689. }
  690. if (q2) {
  691. q1 = strchr(q2, ':');
  692. if (q1) {
  693. *q1++ = 0;
  694. bi->uplink = strdup(q1);
  695. }
  696. bi->hublevel = atoi(q2);
  697. }
  698. }
  699. if (!bi->telnet_port)
  700. bi->telnet_port = 3333;
  701. if (!bi->relay_port)
  702. bi->relay_port = bi->telnet_port;
  703. if (!bi->uplink) {
  704. bi->uplink = (char *) my_calloc(1, 1);
  705. }
  706. list_type_kill(e->u.list);
  707. e->u.extra = bi;
  708. return 1;
  709. }
  710. static bool botaddr_kill(struct user_entry *e)
  711. {
  712. free(((struct bot_addr *) (e->u.extra))->address);
  713. free(((struct bot_addr *) (e->u.extra))->uplink);
  714. free(e->u.extra);
  715. free(e);
  716. return 1;
  717. }
  718. static void botaddr_write_userfile(bd::Stream& stream, const struct userrec *u, const struct user_entry *e, int idx)
  719. {
  720. register struct bot_addr *bi = (struct bot_addr *) e->u.extra;
  721. bd::String buf;
  722. stream << buf.printf("--%s %s:%u/%u:%u:%s\n", e->type->name, bi->address, bi->telnet_port, bi->relay_port, bi->hublevel, bi->uplink);
  723. }
  724. static bool botaddr_set(struct userrec *u, struct user_entry *e, void *buf)
  725. {
  726. register struct bot_addr *bi = (struct bot_addr *) e->u.extra;
  727. if (!bi && !buf)
  728. return 1;
  729. if (bi != buf) {
  730. if (bi) {
  731. free(bi->address);
  732. free(bi->uplink);
  733. free(bi);
  734. }
  735. ContextNote("botaddr_set", "(sharebug) occurred in botaddr_set");
  736. bi = (struct bot_addr *) buf;
  737. e->u.extra = (struct bot_addr *) buf;
  738. }
  739. if (bi && !noshare) {
  740. shareout("c BOTADDR %s %s %d %d %d %s\n",u->handle,
  741. (bi->address && bi->address[0]) ? bi->address : "127.0.0.1",
  742. bi->telnet_port, bi->relay_port, bi->hublevel, bi->uplink);
  743. }
  744. return 1;
  745. }
  746. static void botaddr_display(int idx, struct user_entry *e, struct userrec *u)
  747. {
  748. if (conf.bot->hub) {
  749. struct flag_record fr = {FR_GLOBAL, 0, 0, 0 };
  750. get_user_flagrec(dcc[idx].user, &fr, NULL);
  751. if (glob_admin(fr)) {
  752. register struct bot_addr *bi = (struct bot_addr *) e->u.extra;
  753. if (bi->hublevel && bi->hublevel != 999) {
  754. if (bi->address) {
  755. dprintf(idx, " ADDRESS: %.70s\n", bi->address);
  756. dprintf(idx, " port: %d\n", bi->telnet_port);
  757. }
  758. dprintf(idx, " HUBLEVEL: %d\n", bi->hublevel);
  759. }
  760. if (bi->uplink && bi->uplink[0])
  761. dprintf(idx, " UPLINK: %s\n", bi->uplink);
  762. }
  763. }
  764. }
  765. static bool botaddr_gotshare(struct userrec *u, struct user_entry *e, char *buf, int idx)
  766. {
  767. struct bot_addr *bi = (struct bot_addr *) my_calloc(1, sizeof(struct bot_addr));
  768. char *arg = newsplit(&buf);
  769. bi->address = strdup(arg);
  770. arg = newsplit(&buf);
  771. bi->telnet_port = atoi(arg);
  772. arg = newsplit(&buf);
  773. bi->relay_port = atoi(arg);
  774. arg = newsplit(&buf);
  775. bi->hublevel = atoi(arg);
  776. bi->uplink = strdup(buf);
  777. if (!bi->telnet_port)
  778. bi->telnet_port = 3333;
  779. if (!bi->relay_port)
  780. bi->relay_port = bi->telnet_port;
  781. return botaddr_set(u, e, bi);
  782. }
  783. struct user_entry_type USERENTRY_BOTADDR =
  784. {
  785. 0, /* always 0 ;) */
  786. botaddr_gotshare,
  787. botaddr_unpack,
  788. botaddr_write_userfile,
  789. botaddr_kill,
  790. def_get,
  791. botaddr_set,
  792. botaddr_display,
  793. "BOTADDR"
  794. };
  795. static void hosts_write_userfile(bd::Stream& stream, const struct userrec *u, const struct user_entry *e, int idx)
  796. {
  797. struct list_type *h = NULL;
  798. bd::String buf;
  799. for (h = (struct list_type *) e->u.extra; h; h = h->next)
  800. stream << buf.printf("--HOSTS %s\n", h->extra);
  801. }
  802. static bool hosts_null(struct userrec *u, struct user_entry *e)
  803. {
  804. return 1;
  805. }
  806. static bool hosts_kill(struct user_entry *e)
  807. {
  808. list_type_kill(e->u.list);
  809. free(e);
  810. return 1;
  811. }
  812. static void hosts_display(int idx, struct user_entry *e, struct userrec *u)
  813. {
  814. /* if this is a su, dont show hosts
  815. * otherwise, let users see their own hosts */
  816. if (conf.bot->hub ||
  817. (!conf.bot->hub && (dcc[idx].simul || (!strcmp(u->handle,dcc[idx].nick) && !dcc[idx].u.chat->su_nick)))) {
  818. char s[1024] = "";
  819. struct list_type *q = NULL;
  820. strlcpy(s, " HOSTS: ", sizeof(s));
  821. for (q = e->u.list; q; q = q->next) {
  822. if (s[0] && !s[9])
  823. strlcat(s, q->extra, sizeof(s));
  824. else if (!s[0])
  825. simple_snprintf(s, sizeof(s), " %s", q->extra);
  826. else {
  827. if (strlen(s) + strlen(q->extra) + 2 > 65) {
  828. dprintf(idx, "%s\n", s);
  829. simple_snprintf(s, sizeof(s), " %s", q->extra);
  830. } else {
  831. strlcat(s, ", ", sizeof(s));
  832. strlcat(s, q->extra, sizeof(s));
  833. }
  834. }
  835. }
  836. if (s[0])
  837. dprintf(idx, "%s\n", s);
  838. } else if (!conf.bot->hub) {
  839. dprintf(idx, " HOSTS: Hidden on leaf bots.");
  840. if (dcc[idx].u.chat->su_nick)
  841. dprintf(idx, " Nice try, %s.", dcc[idx].u.chat->su_nick);
  842. dprintf(idx, "\n");
  843. }
  844. }
  845. static bool hosts_set(struct userrec *u, struct user_entry *e, void *buf)
  846. {
  847. if (!buf || !strcasecmp((const char *) buf, "none")) {
  848. /* When the bot crashes, it's in this part, not in the 'else' part */
  849. list_type_kill(e->u.list);
  850. e->u.list = NULL;
  851. } else {
  852. char *host = (char *) buf, *p = strchr(host, ',');
  853. struct list_type **t;
  854. /* Can't have ,'s in hostmasks */
  855. while (p) {
  856. *p = '?';
  857. p = strchr(host, ',');
  858. }
  859. /* fred1: check for redundant hostmasks with
  860. * controversial "superpenis" algorithm ;) */
  861. /* I'm surprised Raistlin hasn't gotten involved in this controversy */
  862. t = &(e->u.list);
  863. while (*t) {
  864. if (wild_match(host, (*t)->extra)) {
  865. struct list_type *listu;
  866. listu = *t;
  867. *t = (*t)->next;
  868. if (listu->extra)
  869. free(listu->extra);
  870. free(listu);
  871. } else
  872. t = &((*t)->next);
  873. }
  874. *t = (struct list_type *) my_calloc(1, sizeof(struct list_type));
  875. (*t)->next = NULL;
  876. (*t)->extra = strdup(host);
  877. }
  878. return 1;
  879. }
  880. static bool hosts_gotshare(struct userrec *u, struct user_entry *e, char *buf, int idx)
  881. {
  882. /* doh, try to be too clever and it bites your butt */
  883. return 0;
  884. }
  885. struct user_entry_type USERENTRY_HOSTS =
  886. {
  887. 0,
  888. hosts_gotshare,
  889. hosts_null,
  890. hosts_write_userfile,
  891. hosts_kill,
  892. def_get,
  893. hosts_set,
  894. hosts_display,
  895. "HOSTS"
  896. };
  897. bool list_append(struct list_type **h, struct list_type *i)
  898. {
  899. for (; *h; h = &((*h)->next))
  900. ;
  901. *h = i;
  902. return 1;
  903. }
  904. bool list_delete(struct list_type **h, struct list_type *i)
  905. {
  906. for (; *h; h = &((*h)->next))
  907. if (*h == i) {
  908. *h = i->next;
  909. return 1;
  910. }
  911. return 0;
  912. }
  913. bool list_contains(struct list_type *h, struct list_type *i)
  914. {
  915. for (; h; h = h->next)
  916. if (h == i) {
  917. return 1;
  918. }
  919. return 0;
  920. }
  921. bool add_entry_type(struct user_entry_type *type)
  922. {
  923. struct userrec *u = NULL;
  924. list_insert((&entry_type_list), type);
  925. for (u = userlist; u; u = u->next) {
  926. struct user_entry *e = find_user_entry(type, u);
  927. if (e && e->name) {
  928. e->type = type;
  929. e->type->unpack(u, e);
  930. free(e->name);
  931. e->name = NULL;
  932. }
  933. }
  934. return 1;
  935. }
  936. struct user_entry_type *find_entry_type(char *name)
  937. {
  938. struct user_entry_type *p = NULL;
  939. for (p = entry_type_list; p; p = p->next) {
  940. if (!strcasecmp(name, p->name))
  941. return p;
  942. }
  943. return NULL;
  944. }
  945. struct user_entry *find_user_entry(struct user_entry_type *et, struct userrec *u)
  946. {
  947. struct user_entry **e = NULL, *t = NULL;
  948. for (e = &(u->entries); *e; e = &((*e)->next)) {
  949. if (((*e)->type == et) || ((*e)->name && !strcasecmp((*e)->name, et->name))) {
  950. t = *e;
  951. *e = t->next;
  952. t->next = u->entries;
  953. u->entries = t;
  954. return t;
  955. }
  956. }
  957. return NULL;
  958. }
  959. void *get_user(struct user_entry_type *et, struct userrec *u)
  960. {
  961. struct user_entry *e = NULL;
  962. if (u && (e = find_user_entry(et, u)))
  963. return et->get(u, e);
  964. return NULL;
  965. }
  966. bool set_user(struct user_entry_type *et, struct userrec *u, void *d)
  967. {
  968. if (!u || !et)
  969. return 0;
  970. struct user_entry *e = NULL;
  971. bool r;
  972. if (!(e = find_user_entry(et, u))) {
  973. e = (struct user_entry *) my_calloc(1, sizeof(struct user_entry));
  974. e->type = et;
  975. e->name = NULL;
  976. e->u.list = NULL;
  977. list_insert((&(u->entries)), e);
  978. }
  979. r = et->set(u, e, d);
  980. if (!e->u.list) {
  981. list_delete((struct list_type **) &(u->entries), (struct list_type *) e);
  982. free(e);
  983. }
  984. return r;
  985. }