userent.c 25 KB

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