4
0

userrec.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565
  1. /*
  2. * Copyright (C) 2000,2001 Florian Sander
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License
  6. * as published by the Free Software Foundation; either version 2
  7. * of the License, or (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17. */
  18. /* Find the stats-user that belongs to a hostmask
  19. */
  20. static struct stats_userlist *findsuser(char *host)
  21. {
  22. struct stats_userlist *user, *u;
  23. struct stats_hostlist *h, *h2;
  24. int len = 0;
  25. Context;
  26. u = NULL;
  27. h2 = NULL;
  28. for (user = suserlist; user; user = user->next) {
  29. for (h = user->hosts; h; h = h->next) {
  30. /* the longest hostmask gives the best match */
  31. if (!len || (strlen(h->mask) > len)) {
  32. if (wild_match(h->mask, host)) {
  33. u = user;
  34. h2 = h;
  35. len = strlen(h->mask);
  36. }
  37. }
  38. }
  39. }
  40. if (u) {
  41. h2->lastused = now;
  42. return u;
  43. }
  44. return NULL;
  45. }
  46. static struct stats_userlist *findsuser_by_name(char *user)
  47. {
  48. struct stats_userlist *u;
  49. Context;
  50. for (u = suserlist; u; u = u->next)
  51. if (!rfc_casecmp(u->user, user))
  52. return u;
  53. return NULL;
  54. }
  55. static struct stats_userlist *addsuser(char *user, time_t created, time_t laston)
  56. {
  57. struct stats_userlist *u, *nu;
  58. Context;
  59. for (u = suserlist; u; u = u->next)
  60. if (!rfc_casecmp(u->user, user))
  61. return u;
  62. u = suserlist;
  63. while (u && u->next)
  64. u = u->next;
  65. nu = stats_userlist_create_entry(user);
  66. nu->user = nmalloc(strlen(user) + 1);
  67. strcpy(nu->user, user);
  68. nu->created = created;
  69. nu->laston = laston;
  70. if (u)
  71. u->next = nu;
  72. else
  73. suserlist = nu;
  74. return nu;
  75. }
  76. static void delsuser(char *user)
  77. {
  78. struct stats_userlist *u, *lu;
  79. Context;
  80. debug1("Deleting %s...", user);
  81. u = suserlist;
  82. lu = NULL;
  83. while (u) {
  84. if (!rfc_casecmp(u->user, user)) {
  85. if (lu)
  86. lu->next = u->next;
  87. else
  88. suserlist = u->next;
  89. stats_userlist_free_entry(u);
  90. if (lu)
  91. u = lu->next;
  92. else
  93. u = suserlist;
  94. } else {
  95. lu = u;
  96. u = u->next;
  97. }
  98. }
  99. }
  100. static struct stats_userlist *stats_userlist_create_entry(char *user)
  101. {
  102. struct stats_userlist *newentry;
  103. newentry = nmalloc(sizeof(struct stats_userlist));
  104. newentry->next = NULL;
  105. newentry->user = NULL;
  106. newentry->password = NULL;
  107. newentry->email = NULL;
  108. newentry->homepage = NULL;
  109. newentry->flags = 0;
  110. newentry->icqnr = 0;
  111. newentry->hosts = NULL;
  112. newentry->created = 0;
  113. newentry->laston = 0;
  114. suser_setflag(newentry, S_LIST);
  115. suser_setflag(newentry, S_ADDHOSTS);
  116. return newentry;
  117. }
  118. /* static int stats_userlist_expmem_entry(struct stats_userlist *what)
  119. {
  120. int size = 0;
  121. Assert(what);
  122. Assert(what->user);
  123. size += sizeof(struct stats_userlist);
  124. size += strlen(what->user) + 1;
  125. if (what->password)
  126. size += strlen(what->password) + 1;
  127. if (what->email)
  128. size += strlen(what->email) + 1;
  129. if (what->homepage)
  130. size += strlen(what->homepage) + 1;
  131. size += hostlist_expmem(what->hosts);
  132. return size;
  133. } */
  134. static void stats_userlist_free_entry(struct stats_userlist *what)
  135. {
  136. Assert(what);
  137. Assert(what->user);
  138. free_hostlist(what->hosts);
  139. nfree(what->user);
  140. if (what->email)
  141. nfree(what->email);
  142. if (what->homepage)
  143. nfree(what->homepage);
  144. if (what->password)
  145. nfree(what->password);
  146. weed_userlink_from_chanset(what);
  147. weed_userlink_from_locstats(what);
  148. nfree(what);
  149. }
  150. static void saddhost(struct stats_userlist *u, char *host, time_t lastused, time_t created)
  151. {
  152. struct stats_hostlist *h, *nh;
  153. Context;
  154. for (h = u->hosts; h; h = h->next)
  155. if (!rfc_casecmp(h->mask, host))
  156. return;
  157. h = u->hosts;
  158. while (h && h->next)
  159. h = h->next;
  160. nh = nmalloc(sizeof(struct stats_hostlist));
  161. nh->mask = nmalloc(strlen(host) + 1);
  162. strcpy(nh->mask, host);
  163. nh->lastused = lastused;
  164. nh->created = created;
  165. nh->next = NULL;
  166. if (h)
  167. h->next = nh;
  168. else
  169. u->hosts = nh;
  170. }
  171. static int sdelhost(struct stats_userlist *u, char *host)
  172. {
  173. struct stats_hostlist *h, *lh;
  174. Context;
  175. h = u->hosts;
  176. lh = NULL;
  177. while (h) {
  178. if (!rfc_casecmp(h->mask, host)) {
  179. nfree(h->mask);
  180. if (lh)
  181. lh->next = h->next;
  182. else
  183. u->hosts = h->next;
  184. nfree(h);
  185. return 1;
  186. }
  187. lh = h;
  188. h = h->next;
  189. }
  190. return 0;
  191. }
  192. static void stats_autosadd(struct stats_member *m, struct stats_chan *chan)
  193. {
  194. struct stats_userlist *u;
  195. struct userrec *uu;
  196. char *mhost, *host;
  197. Context;
  198. if (autoadd < 0)
  199. return;
  200. if (m->spoken_lines < autoadd_min_lines)
  201. return;
  202. if ((now - m->joined) < (autoadd * 60))
  203. return;
  204. if (m->user) {
  205. debug3("Stats.Mod: stats_autosadd called for %s in %s, but m->user already belongs to %s",
  206. m->nick, chan->chan, m->user->user);
  207. return;
  208. }
  209. if (!m->uhost)
  210. return;
  211. if (strchr(m->uhost, '*') || strchr(m->uhost, '?'))
  212. return;
  213. u = findsuser_by_name(m->nick);
  214. host = nmalloc(strlen(m->uhost) + strlen(m->nick) + 2);
  215. sprintf(host, "%s!%s", m->nick, m->uhost);
  216. mhost = nmalloc(strlen(host) + 10); /* better a few bytes too much than too little */
  217. // I use maskstricthost() here, because stats.mod shouldn't strip
  218. // a host anywhere at all. (strict-hosts 0 sucks...)
  219. maskstricthost(host, mhost);
  220. // mhost = nrealloc(mhost, strlen(mhost) + strlen(nick) + 1);sprintf(mhost, "%s%s", m->nick, mhost + 1);
  221. if (u) {
  222. if (suser_addhosts(u)) {
  223. saddhost(u, mhost, now, now);
  224. m->user = u;
  225. putlog(LOG_MISC, "*", "Stats.Mod: Added stats-hostmask %s to %s.", mhost, u->user);
  226. }
  227. } else {
  228. #ifndef NO_EGG
  229. uu = get_user_by_host(host);
  230. if (!uu && (autoadd == 0)) {
  231. nfree(mhost);
  232. nfree(host);
  233. return;
  234. }
  235. if (uu)
  236. u = addsuser(uu->handle, now, now);
  237. else
  238. #endif
  239. u = addsuser(m->nick, now, now);
  240. saddhost(u, mhost, now, now);
  241. #ifndef NO_EGG
  242. if (uu)
  243. putlog(LOG_MISC, "*", "Stats.Mod: %s matched %s(in the \"common\" userfile), added %s to userbase.", host, uu->handle, u->user);
  244. else
  245. #endif
  246. putlog(LOG_MISC, "*", "Stats.Mod: Added %s(%s) to userbase.", u->user, mhost);
  247. m->user = u;
  248. // send a welcome message to our new user
  249. welcome_suser(m->nick, u, chan->chan);
  250. }
  251. if (m->user) {
  252. m->stats = findlocstats(chan->chan, m->user->user);
  253. if (!m->stats)
  254. m->stats = initstats(chan->chan, m->user->user);
  255. } else
  256. m->stats = NULL;
  257. nfree(mhost);
  258. nfree(host);
  259. }
  260. static void welcome_suser(char *nick, struct stats_userlist *u, char *chan)
  261. {
  262. char *text;
  263. reset_global_vars();
  264. if (!greet_new_users)
  265. return;
  266. glob_user = u;
  267. glob_nick = nick;
  268. glob_slang = slang_find(coreslangs, slang_chanlang_get(chanlangs, chan));
  269. if ((text = getslang_first(500))) {
  270. dprintf(DP_HELP, "NOTICE %s :%s\n", nick, text);
  271. while ((text = getslang_next()))
  272. dprintf(DP_HELP, "NOTICE %s :%s\n", nick, text);
  273. }
  274. }
  275. static int listsuser(locstats *ls, char *chan)
  276. {
  277. if (!ls->u)
  278. ls->u = findsuser_by_name(ls->user);
  279. if (ls->u && !suser_list(ls->u))
  280. return 0;
  281. return 1;
  282. }
  283. static int countsusers()
  284. {
  285. static struct stats_userlist *u;
  286. int users = 0;
  287. Context;
  288. for (u = suserlist; u; u = u->next)
  289. users++;
  290. return users;
  291. }
  292. static int counthosts()
  293. {
  294. static struct stats_userlist *u;
  295. static struct stats_hostlist *h;
  296. int hosts = 0;
  297. Context;
  298. for (u = suserlist; u; u = u->next)
  299. for (h = u->hosts; h; h = h->next)
  300. hosts++;
  301. return hosts;
  302. }
  303. static void weed_userlink_from_chanset(struct stats_userlist *u)
  304. {
  305. struct stats_chan *chan;
  306. struct stats_member *m;
  307. Context;
  308. for (chan = schan_getfirst(); chan; chan = schan_getnext()) {
  309. for (m = schan_members_getfirst(&chan->members); m; m = schan_members_getnext(&chan->members)) {
  310. if (m->user == u) {
  311. m->user = NULL;
  312. m->stats = NULL;
  313. }
  314. }
  315. }
  316. }
  317. static void weed_statlink_from_chanset(locstats *ls)
  318. {
  319. struct stats_chan *chan;
  320. struct stats_member *m;
  321. Context;
  322. for (chan = schan_getfirst(); chan; chan = schan_getnext()) {
  323. for (m = schan_members_getfirst(&chan->members); m; m = schan_members_getnext(&chan->members)) {
  324. if (m->stats == ls) {
  325. m->stats = NULL;
  326. }
  327. }
  328. }
  329. }
  330. /* weed_userlink_from_locstats():
  331. * removes all references to a userstruct from the stat-structs
  332. * (mostly used if the user got deleted)
  333. */
  334. static void weed_userlink_from_locstats(struct stats_userlist *u)
  335. {
  336. globstats *gs;
  337. locstats *ls;
  338. Context;
  339. for (gs = sdata; gs; gs = gs->next)
  340. for (ls = gs->local; ls; ls = ls->next)
  341. if (ls->u == u)
  342. ls->u = NULL;
  343. Context;
  344. }
  345. static void setemail(struct stats_userlist *u, char *email)
  346. {
  347. if (!u) {
  348. putlog(LOG_MISC, "*", "ERROR! Tried to set email for NULL!");
  349. return;
  350. }
  351. if (u->email) {
  352. debug0("email exists... deleting");
  353. nfree(u->email);
  354. u->email = NULL;
  355. }
  356. while (email[0] == ' ')
  357. email++;
  358. if (email[0]) {
  359. u->email = nmalloc(strlen(email) + 1);
  360. strcpy(u->email, email);
  361. debug1("newemail: '%s'", u->email);
  362. }
  363. }
  364. static void sethomepage(struct stats_userlist *u, char *homepage)
  365. {
  366. int len;
  367. if (!u) {
  368. putlog(LOG_MISC, "*", "ERROR! Tried to set homepage for NULL!");
  369. return;
  370. }
  371. if (u->homepage) {
  372. nfree(u->homepage);
  373. u->homepage = NULL;
  374. }
  375. while (homepage[0] == ' ')
  376. homepage++;
  377. if (homepage[0]) {
  378. if (!strncasecmp(homepage, "http://", 7)) {
  379. u->homepage = nmalloc(strlen(homepage) + 1);
  380. strcpy(u->homepage, homepage);
  381. } else {
  382. len = strlen(homepage) + 7 + 1;
  383. u->homepage = nmalloc(len);
  384. snprintf(u->homepage, len, "http://%s", homepage);
  385. }
  386. }
  387. }
  388. static void setpassword(struct stats_userlist *u, char *password)
  389. {
  390. if (!u) {
  391. putlog(LOG_MISC, "*", "ERROR! Tried to set password for NULL!");
  392. return;
  393. }
  394. if (u->password) {
  395. nfree(u->password);
  396. u->password = NULL;
  397. }
  398. while (password[0] == ' ')
  399. password++;
  400. if (password[0]) {
  401. u->password = nmalloc(strlen(password) + 1);
  402. strcpy(u->password, password);
  403. }
  404. }
  405. static time_t get_creation_time_from_locstats(char *user)
  406. {
  407. struct stats_chan *chan;
  408. locstats *ls;
  409. time_t creation = now;
  410. for (chan = schan_getfirst(); chan; chan = schan_getnext()) {
  411. ls = findlocstats(chan->chan, user);
  412. if (ls) {
  413. if (ls->started < creation)
  414. creation = ls->started;
  415. } else
  416. debug2("no ls: %s@%s", user, chan->chan);
  417. }
  418. debug2("creation of %s: %lu", user, creation);
  419. if (creation == now)
  420. debug0("creation == now!");
  421. return creation;
  422. }
  423. static time_t get_laston_time_from_hosts(char *user)
  424. {
  425. struct stats_userlist *u;
  426. struct stats_hostlist *h;
  427. time_t laston = now;
  428. u = findsuser_by_name(user);
  429. if (u) {
  430. for (h = u->hosts; h; h = h->next)
  431. if (h->lastused > laston)
  432. laston = h->lastused;
  433. }
  434. debug2("laston of %s: %lu", user, laston);
  435. return laston;
  436. }
  437. static int user_changeflag(struct stats_userlist *u, char *mode)
  438. {
  439. Assert(u);
  440. if (!strcasecmp(mode, "+list"))
  441. suser_setflag(u, S_LIST);
  442. else if (!strcasecmp(mode, "-list"))
  443. suser_delflag(u, S_LIST);
  444. if (!strcasecmp(mode, "+addhosts"))
  445. suser_setflag(u, S_ADDHOSTS);
  446. else if (!strcasecmp(mode, "-addhosts"))
  447. suser_delflag(u, S_ADDHOSTS);
  448. else if (!strcasecmp(mode, "+nostats")) {
  449. suser_setflag(u, S_NOSTATS);
  450. suser_delflag(u, S_LIST);
  451. } else if (!strcasecmp(mode, "-nostats"))
  452. suser_delflag(u, S_NOSTATS);
  453. else
  454. return 0;
  455. return 1;
  456. }
  457. static void free_suserlist(struct stats_userlist *e)
  458. {
  459. struct stats_userlist *ee;
  460. Context;
  461. while (e) {
  462. ee = e->next;
  463. stats_userlist_free_entry(e);
  464. e = ee;
  465. }
  466. }
  467. static void free_hostlist(struct stats_hostlist *e)
  468. {
  469. struct stats_hostlist *ee;
  470. Context;
  471. while (e) {
  472. ee = e->next;
  473. nfree(e->mask);
  474. nfree(e);
  475. e = ee;
  476. }
  477. }
  478. static int user_email_password(struct stats_userlist *user)
  479. {
  480. char *p, *text = NULL;
  481. int len = 0, newlen = 0, ret;
  482. if (!user->password)
  483. return U_NOPASSWORD;
  484. if (!user->email)
  485. return U_NOEMAIL;
  486. text = nmalloc(1);
  487. *text = 0;
  488. for (p = getslang_first(1510); p; p = getslang_next()) {
  489. newlen = strlen(p);
  490. text = nrealloc(text, len + newlen + 1 + 1);
  491. len += newlen + 1;
  492. strcat(text, p);
  493. strcat(text, "\n");
  494. }
  495. ret = email_send(user->email, getslang(1500), text);
  496. nfree(text);
  497. return ret;
  498. }
  499. static int user_merge(char *sTo, char *sFrom)
  500. {
  501. struct stats_userlist *uTo, *uFrom;
  502. struct stats_hostlist *h;
  503. uTo = findsuser_by_name(sTo);
  504. uFrom = findsuser_by_name(sFrom);
  505. if (!uTo || !uFrom)
  506. return 0;
  507. if (!userdata_merge(sTo, sFrom))
  508. return 0;
  509. for (h = uFrom->hosts; h; h = h->next)
  510. saddhost(uTo, h->mask, h->lastused, h->created);
  511. delsuser(sFrom);
  512. return 1;
  513. }