userrec.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556
  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. for (text = getslang_first(500); text; text = getslang_next())
  264. dprintf(DP_HELP, "NOTICE %s :%s\n", nick, text);
  265. }
  266. static int listsuser(locstats *ls, char *chan)
  267. {
  268. if (!ls->u)
  269. ls->u = findsuser_by_name(ls->user);
  270. if (ls->u && !suser_list(ls->u))
  271. return 0;
  272. return 1;
  273. }
  274. static int countsusers()
  275. {
  276. static struct stats_userlist *u;
  277. int users = 0;
  278. Context;
  279. for (u = suserlist; u; u = u->next)
  280. users++;
  281. return users;
  282. }
  283. static int counthosts()
  284. {
  285. static struct stats_userlist *u;
  286. static struct stats_hostlist *h;
  287. int hosts = 0;
  288. Context;
  289. for (u = suserlist; u; u = u->next)
  290. for (h = u->hosts; h; h = h->next)
  291. hosts++;
  292. return hosts;
  293. }
  294. static void weed_userlink_from_chanset(struct stats_userlist *u)
  295. {
  296. struct stats_chan *chan;
  297. struct stats_member *m;
  298. Context;
  299. for (chan = schan_getfirst(); chan; chan = schan_getnext()) {
  300. for (m = schan_members_getfirst(&chan->members); m; m = schan_members_getnext(&chan->members)) {
  301. if (m->user == u) {
  302. m->user = NULL;
  303. m->stats = NULL;
  304. }
  305. }
  306. }
  307. }
  308. static void weed_statlink_from_chanset(locstats *ls)
  309. {
  310. struct stats_chan *chan;
  311. struct stats_member *m;
  312. Context;
  313. for (chan = schan_getfirst(); chan; chan = schan_getnext()) {
  314. for (m = schan_members_getfirst(&chan->members); m; m = schan_members_getnext(&chan->members)) {
  315. if (m->stats == ls) {
  316. m->stats = NULL;
  317. }
  318. }
  319. }
  320. }
  321. /* weed_userlink_from_locstats():
  322. * removes all references to a userstruct from the stat-structs
  323. * (mostly used if the user got deleted)
  324. */
  325. static void weed_userlink_from_locstats(struct stats_userlist *u)
  326. {
  327. globstats *gs;
  328. locstats *ls;
  329. Context;
  330. for (gs = sdata; gs; gs = gs->next)
  331. for (ls = gs->local; ls; ls = ls->next)
  332. if (ls->u == u)
  333. ls->u = NULL;
  334. Context;
  335. }
  336. static void setemail(struct stats_userlist *u, char *email)
  337. {
  338. if (!u) {
  339. putlog(LOG_MISC, "*", "ERROR! Tried to set email for NULL!");
  340. return;
  341. }
  342. if (u->email) {
  343. debug0("email exists... deleting");
  344. nfree(u->email);
  345. u->email = NULL;
  346. }
  347. while (email[0] == ' ')
  348. email++;
  349. if (email[0]) {
  350. u->email = nmalloc(strlen(email) + 1);
  351. strcpy(u->email, email);
  352. debug1("newemail: '%s'", u->email);
  353. }
  354. }
  355. static void sethomepage(struct stats_userlist *u, char *homepage)
  356. {
  357. int len;
  358. if (!u) {
  359. putlog(LOG_MISC, "*", "ERROR! Tried to set homepage for NULL!");
  360. return;
  361. }
  362. if (u->homepage) {
  363. nfree(u->homepage);
  364. u->homepage = NULL;
  365. }
  366. while (homepage[0] == ' ')
  367. homepage++;
  368. if (homepage[0]) {
  369. if (!strncasecmp(homepage, "http://", 7)) {
  370. u->homepage = nmalloc(strlen(homepage) + 1);
  371. strcpy(u->homepage, homepage);
  372. } else {
  373. len = strlen(homepage) + 7 + 1;
  374. u->homepage = nmalloc(len);
  375. snprintf(u->homepage, len, "http://%s", homepage);
  376. }
  377. }
  378. }
  379. static void setpassword(struct stats_userlist *u, char *password)
  380. {
  381. if (!u) {
  382. putlog(LOG_MISC, "*", "ERROR! Tried to set password for NULL!");
  383. return;
  384. }
  385. if (u->password) {
  386. nfree(u->password);
  387. u->password = NULL;
  388. }
  389. while (password[0] == ' ')
  390. password++;
  391. if (password[0]) {
  392. u->password = nmalloc(strlen(password) + 1);
  393. strcpy(u->password, password);
  394. }
  395. }
  396. static time_t get_creation_time_from_locstats(char *user)
  397. {
  398. struct stats_chan *chan;
  399. locstats *ls;
  400. time_t creation = now;
  401. for (chan = schan_getfirst(); chan; chan = schan_getnext()) {
  402. ls = findlocstats(chan->chan, user);
  403. if (ls) {
  404. if (ls->started < creation)
  405. creation = ls->started;
  406. } else
  407. debug2("no ls: %s@%s", user, chan->chan);
  408. }
  409. debug2("creation of %s: %lu", user, creation);
  410. if (creation == now)
  411. debug0("creation == now!");
  412. return creation;
  413. }
  414. static time_t get_laston_time_from_hosts(char *user)
  415. {
  416. struct stats_userlist *u;
  417. struct stats_hostlist *h;
  418. time_t laston = now;
  419. u = findsuser_by_name(user);
  420. if (u) {
  421. for (h = u->hosts; h; h = h->next)
  422. if (h->lastused > laston)
  423. laston = h->lastused;
  424. }
  425. debug2("laston of %s: %lu", user, laston);
  426. return laston;
  427. }
  428. static int user_changeflag(struct stats_userlist *u, char *mode)
  429. {
  430. Assert(u);
  431. if (!strcasecmp(mode, "+list"))
  432. suser_setflag(u, S_LIST);
  433. else if (!strcasecmp(mode, "-list"))
  434. suser_delflag(u, S_LIST);
  435. if (!strcasecmp(mode, "+addhosts"))
  436. suser_setflag(u, S_ADDHOSTS);
  437. else if (!strcasecmp(mode, "-addhosts"))
  438. suser_delflag(u, S_ADDHOSTS);
  439. else if (!strcasecmp(mode, "+nostats")) {
  440. suser_setflag(u, S_NOSTATS);
  441. suser_delflag(u, S_LIST);
  442. } else if (!strcasecmp(mode, "-nostats"))
  443. suser_delflag(u, S_NOSTATS);
  444. else
  445. return 0;
  446. return 1;
  447. }
  448. static void free_suserlist(struct stats_userlist *e)
  449. {
  450. struct stats_userlist *ee;
  451. Context;
  452. while (e) {
  453. ee = e->next;
  454. stats_userlist_free_entry(e);
  455. e = ee;
  456. }
  457. }
  458. static void free_hostlist(struct stats_hostlist *e)
  459. {
  460. struct stats_hostlist *ee;
  461. Context;
  462. while (e) {
  463. ee = e->next;
  464. nfree(e->mask);
  465. nfree(e);
  466. e = ee;
  467. }
  468. }
  469. static int user_email_password(struct stats_userlist *user)
  470. {
  471. char *p, *text = NULL;
  472. int len = 0, newlen = 0, ret;
  473. if (!user->password)
  474. return U_NOPASSWORD;
  475. if (!user->email)
  476. return U_NOEMAIL;
  477. text = nmalloc(1);
  478. *text = 0;
  479. for (p = getslang_first(1510); p; p = getslang_next()) {
  480. newlen = strlen(p);
  481. text = nrealloc(text, len + newlen + 1 + 1);
  482. len += newlen + 1;
  483. strcat(text, p);
  484. strcat(text, "\n");
  485. }
  486. ret = email_send(user->email, getslang(1500), text);
  487. nfree(text);
  488. return ret;
  489. }
  490. static int user_merge(char *sTo, char *sFrom)
  491. {
  492. struct stats_userlist *uTo, *uFrom;
  493. struct stats_hostlist *h;
  494. uTo = findsuser_by_name(sTo);
  495. uFrom = findsuser_by_name(sFrom);
  496. if (!uTo || !uFrom)
  497. return 0;
  498. if (!userdata_merge(sTo, sFrom))
  499. return 0;
  500. for (h = uFrom->hosts; h; h = h->next)
  501. saddhost(uTo, h->mask, h->lastused, h->created);
  502. delsuser(sFrom);
  503. return 1;
  504. }