userent.c 24 KB

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