userent.c 26 KB

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