userent.cc 26 KB

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