4
0

userrec.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  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. u = findsuser_by_name(m->nick);
  210. host = nmalloc(strlen(m->uhost) + strlen(m->nick) + 2);
  211. sprintf(host, "%s!%s", m->nick, m->uhost);
  212. mhost = nmalloc(strlen(host) + 10); /* better a few bytes too much than too little */
  213. // I use maskstricthost() here, because stats.mod shouldn't strip
  214. // a host anywhere at all. (strict-hosts 0 sucks...)
  215. maskstricthost(host, mhost);
  216. // mhost = nrealloc(mhost, strlen(mhost) + strlen(nick) + 1);sprintf(mhost, "%s%s", m->nick, mhost + 1);
  217. if (u) {
  218. if (suser_addhosts(u)) {
  219. saddhost(u, mhost, now, now);
  220. m->user = u;
  221. putlog(LOG_MISC, "*", "Stats.Mod: Added stats-hostmask %s to %s.", mhost, u->user);
  222. }
  223. } else {
  224. #ifndef NO_EGG
  225. uu = get_user_by_host(host);
  226. if (!uu && (autoadd == 0)) {
  227. nfree(mhost);
  228. nfree(host);
  229. return;
  230. }
  231. if (uu)
  232. u = addsuser(uu->handle, now, now);
  233. else
  234. #endif
  235. u = addsuser(m->nick, now, now);
  236. saddhost(u, mhost, now, now);
  237. #ifndef NO_EGG
  238. if (uu)
  239. putlog(LOG_MISC, "*", "Stats.Mod: %s matched %s(in the \"common\" userfile), added %s to userbase.", host, uu->handle, u->user);
  240. else
  241. #endif
  242. putlog(LOG_MISC, "*", "Stats.Mod: Added %s(%s) to userbase.", u->user, mhost);
  243. m->user = u;
  244. // send a welcome message to our new user
  245. welcome_suser(m->nick, u, chan->chan);
  246. }
  247. if (m->user) {
  248. m->stats = findlocstats(chan->chan, m->user->user);
  249. if (!m->stats)
  250. m->stats = initstats(chan->chan, m->user->user);
  251. } else
  252. m->stats = NULL;
  253. nfree(mhost);
  254. nfree(host);
  255. }
  256. static void welcome_suser(char *nick, struct stats_userlist *u, char *chan)
  257. {
  258. char *text;
  259. reset_global_vars();
  260. glob_user = u;
  261. glob_nick = nick;
  262. glob_slang = slang_find(coreslangs, slang_chanlang_get(chanlangs, chan));
  263. if ((text = getslang_first(500))) {
  264. dprintf(DP_HELP, "NOTICE %s :%s\n", nick, text);
  265. while ((text = getslang_next()))
  266. dprintf(DP_HELP, "NOTICE %s :%s\n", nick, text);
  267. }
  268. }
  269. static int listsuser(locstats *ls, char *chan)
  270. {
  271. if (!ls->u)
  272. ls->u = findsuser_by_name(ls->user);
  273. if (ls->u && !suser_list(ls->u))
  274. return 0;
  275. return 1;
  276. }
  277. static int countsusers()
  278. {
  279. static struct stats_userlist *u;
  280. int users = 0;
  281. Context;
  282. for (u = suserlist; u; u = u->next)
  283. users++;
  284. return users;
  285. }
  286. static int counthosts()
  287. {
  288. static struct stats_userlist *u;
  289. static struct stats_hostlist *h;
  290. int hosts = 0;
  291. Context;
  292. for (u = suserlist; u; u = u->next)
  293. for (h = u->hosts; h; h = h->next)
  294. hosts++;
  295. return hosts;
  296. }
  297. static void weed_userlink_from_chanset(struct stats_userlist *u)
  298. {
  299. struct stats_chan *chan;
  300. struct stats_member *m;
  301. Context;
  302. for (chan = schan_getfirst(); chan; chan = schan_getnext()) {
  303. for (m = schan_members_getfirst(&chan->members); m; m = schan_members_getnext(&chan->members)) {
  304. if (m->user == u) {
  305. m->user = NULL;
  306. m->stats = NULL;
  307. }
  308. }
  309. }
  310. }
  311. static void weed_statlink_from_chanset(locstats *ls)
  312. {
  313. struct stats_chan *chan;
  314. struct stats_member *m;
  315. Context;
  316. for (chan = schan_getfirst(); chan; chan = schan_getnext()) {
  317. for (m = schan_members_getfirst(&chan->members); m; m = schan_members_getnext(&chan->members)) {
  318. if (m->stats == ls) {
  319. m->stats = NULL;
  320. }
  321. }
  322. }
  323. }
  324. /* weed_userlink_from_locstats():
  325. * removes all references to a userstruct from the stat-structs
  326. * (mostly used if the user got deleted)
  327. */
  328. static void weed_userlink_from_locstats(struct stats_userlist *u)
  329. {
  330. globstats *gs;
  331. locstats *ls;
  332. Context;
  333. for (gs = sdata; gs; gs = gs->next)
  334. for (ls = gs->local; ls; ls = ls->next)
  335. if (ls->u == u)
  336. ls->u = NULL;
  337. Context;
  338. }
  339. static void setemail(struct stats_userlist *u, char *email)
  340. {
  341. if (!u) {
  342. putlog(LOG_MISC, "*", "ERROR! Tried to set email for NULL!");
  343. return;
  344. }
  345. if (u->email) {
  346. debug0("email exists... deleting");
  347. nfree(u->email);
  348. u->email = NULL;
  349. }
  350. while (email[0] == ' ')
  351. email++;
  352. if (email[0]) {
  353. u->email = nmalloc(strlen(email) + 1);
  354. strcpy(u->email, email);
  355. debug1("newemail: '%s'", u->email);
  356. }
  357. }
  358. static void sethomepage(struct stats_userlist *u, char *homepage)
  359. {
  360. int len;
  361. if (!u) {
  362. putlog(LOG_MISC, "*", "ERROR! Tried to set homepage for NULL!");
  363. return;
  364. }
  365. if (u->homepage) {
  366. nfree(u->homepage);
  367. u->homepage = NULL;
  368. }
  369. while (homepage[0] == ' ')
  370. homepage++;
  371. if (homepage[0]) {
  372. if (!strncasecmp(homepage, "http://", 7)) {
  373. u->homepage = nmalloc(strlen(homepage) + 1);
  374. strcpy(u->homepage, homepage);
  375. } else {
  376. len = strlen(homepage) + 7 + 1;
  377. u->homepage = nmalloc(len);
  378. snprintf(u->homepage, len, "http://%s", homepage);
  379. }
  380. }
  381. }
  382. static void setpassword(struct stats_userlist *u, char *password)
  383. {
  384. if (!u) {
  385. putlog(LOG_MISC, "*", "ERROR! Tried to set password for NULL!");
  386. return;
  387. }
  388. if (u->password) {
  389. nfree(u->password);
  390. u->password = NULL;
  391. }
  392. while (password[0] == ' ')
  393. password++;
  394. if (password[0]) {
  395. u->password = nmalloc(strlen(password) + 1);
  396. strcpy(u->password, password);
  397. }
  398. }
  399. static time_t get_creation_time_from_locstats(char *user)
  400. {
  401. struct stats_chan *chan;
  402. locstats *ls;
  403. time_t creation = now;
  404. for (chan = schan_getfirst(); chan; chan = schan_getnext()) {
  405. ls = findlocstats(chan->chan, user);
  406. if (ls) {
  407. if (ls->started < creation)
  408. creation = ls->started;
  409. } else
  410. debug2("no ls: %s@%s", user, chan->chan);
  411. }
  412. debug2("creation of %s: %lu", user, creation);
  413. if (creation == now)
  414. debug0("creation == now!");
  415. return creation;
  416. }
  417. static time_t get_laston_time_from_hosts(char *user)
  418. {
  419. struct stats_userlist *u;
  420. struct stats_hostlist *h;
  421. time_t laston = now;
  422. u = findsuser_by_name(user);
  423. if (u) {
  424. for (h = u->hosts; h; h = h->next)
  425. if (h->lastused > laston)
  426. laston = h->lastused;
  427. }
  428. debug2("laston of %s: %lu", user, laston);
  429. return laston;
  430. }
  431. static int user_changeflag(struct stats_userlist *u, char *mode)
  432. {
  433. Assert(u);
  434. if (!strcasecmp(mode, "+list"))
  435. suser_setflag(u, S_LIST);
  436. else if (!strcasecmp(mode, "-list"))
  437. suser_delflag(u, S_LIST);
  438. if (!strcasecmp(mode, "+addhosts"))
  439. suser_setflag(u, S_ADDHOSTS);
  440. else if (!strcasecmp(mode, "-addhosts"))
  441. suser_delflag(u, S_ADDHOSTS);
  442. else if (!strcasecmp(mode, "+nostats")) {
  443. suser_setflag(u, S_NOSTATS);
  444. suser_delflag(u, S_LIST);
  445. } else if (!strcasecmp(mode, "-nostats"))
  446. suser_delflag(u, S_NOSTATS);
  447. else
  448. return 0;
  449. return 1;
  450. }
  451. static void free_suserlist(struct stats_userlist *e)
  452. {
  453. struct stats_userlist *ee;
  454. Context;
  455. while (e) {
  456. ee = e->next;
  457. stats_userlist_free_entry(e);
  458. e = ee;
  459. }
  460. }
  461. static void free_hostlist(struct stats_hostlist *e)
  462. {
  463. struct stats_hostlist *ee;
  464. Context;
  465. while (e) {
  466. ee = e->next;
  467. nfree(e->mask);
  468. nfree(e);
  469. e = ee;
  470. }
  471. }
  472. static int user_email_password(struct stats_userlist *user)
  473. {
  474. char *p, *text = NULL;
  475. int len = 0, newlen = 0, ret;
  476. if (!user->password)
  477. return U_NOPASSWORD;
  478. if (!user->email)
  479. return U_NOEMAIL;
  480. text = nmalloc(1);
  481. *text = 0;
  482. for (p = getslang_first(1510); p; p = getslang_next()) {
  483. newlen = strlen(p);
  484. text = nrealloc(text, len + newlen + 1 + 1);
  485. len += newlen + 1;
  486. strcat(text, p);
  487. strcat(text, "\n");
  488. }
  489. ret = email_send(user->email, getslang(1500), text);
  490. nfree(text);
  491. return ret;
  492. }
  493. static int user_merge(char *sTo, char *sFrom)
  494. {
  495. struct stats_userlist *uTo, *uFrom;
  496. struct stats_hostlist *h;
  497. uTo = findsuser_by_name(sTo);
  498. uFrom = findsuser_by_name(sFrom);
  499. if (!uTo || !uFrom)
  500. return 0;
  501. if (!userdata_merge(sTo, sFrom))
  502. return 0;
  503. for (h = uFrom->hosts; h; h = h->next)
  504. saddhost(uTo, h->mask, h->lastused, h->created);
  505. delsuser(sFrom);
  506. return 1;
  507. }