userent.c 24 KB

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