lists.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. /*
  2. * ngIRCd -- The Next Generation IRC Daemon
  3. * Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors.
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. * Please read the file COPYING, README and AUTHORS for more information.
  10. */
  11. #include "portab.h"
  12. /**
  13. * @file
  14. * Management of IRC lists: ban, invite, etc.
  15. */
  16. #include "imp.h"
  17. #include <assert.h>
  18. #include "defines.h"
  19. #include "conn.h"
  20. #include "channel.h"
  21. #include "log.h"
  22. #include "match.h"
  23. #include "messages.h"
  24. #include "irc-write.h"
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include <strings.h>
  28. #include "exp.h"
  29. #include "lists.h"
  30. #define MASK_LEN (2*CLIENT_HOST_LEN)
  31. struct list_elem {
  32. struct list_elem *next; /** pointer to next list element */
  33. char mask[MASK_LEN]; /** IRC mask */
  34. char *reason; /** Optional "reason" text */
  35. time_t valid_until; /** 0: unlimited; 1: once; t(>1): until t */
  36. };
  37. /**
  38. * Get IRC mask stored in list element.
  39. *
  40. * @param list_elem List element.
  41. * @return Pointer to IRC mask
  42. */
  43. GLOBAL const char *
  44. Lists_GetMask(const struct list_elem *e)
  45. {
  46. assert(e != NULL);
  47. return e->mask;
  48. }
  49. /**
  50. * Get optional "reason" text stored in list element.
  51. *
  52. * @param list_elem List element.
  53. * @return Pointer to "reason" text or empty string ("").
  54. */
  55. GLOBAL const char *
  56. Lists_GetReason(const struct list_elem *e)
  57. {
  58. assert(e != NULL);
  59. return e->reason ? e->reason : "";
  60. }
  61. /**
  62. * Get "validity" value stored in list element.
  63. *
  64. * @param list_elem List element.
  65. * @return Validity: 0=unlimited, 1=once, >1 until this time stamp.
  66. */
  67. GLOBAL time_t
  68. Lists_GetValidity(const struct list_elem *e)
  69. {
  70. assert(e != NULL);
  71. return e->valid_until;
  72. }
  73. /**
  74. * Get first list element of a list.
  75. *
  76. * @param h List head.
  77. * @return Pointer to first list element.
  78. */
  79. GLOBAL struct list_elem*
  80. Lists_GetFirst(const struct list_head *h)
  81. {
  82. assert(h != NULL);
  83. return h->first;
  84. }
  85. /**
  86. * Get next list element of a list.
  87. *
  88. * @param e Current list element.
  89. * @return Pointer to next list element.
  90. */
  91. GLOBAL struct list_elem*
  92. Lists_GetNext(const struct list_elem *e)
  93. {
  94. assert(e != NULL);
  95. return e->next;
  96. }
  97. /**
  98. * Add a new mask to a list.
  99. *
  100. * @param h List head.
  101. * @param Mask The IRC mask to add to the list.
  102. * @param ValidUntil 0: unlimited, 1: only once, t>1: until given time_t.
  103. * @param Reason Reason string or NULL, if no reason should be saved.
  104. * @return true on success, false otherwise.
  105. */
  106. bool
  107. Lists_Add(struct list_head *h, const char *Mask, time_t ValidUntil,
  108. const char *Reason)
  109. {
  110. struct list_elem *e, *newelem;
  111. assert(h != NULL);
  112. assert(Mask != NULL);
  113. e = Lists_CheckDupeMask(h, Mask);
  114. if (e) {
  115. e->valid_until = ValidUntil;
  116. if (Reason) {
  117. free(e->reason);
  118. e->reason = strdup(Reason);
  119. }
  120. return true;
  121. }
  122. e = Lists_GetFirst(h);
  123. newelem = malloc(sizeof(struct list_elem));
  124. if (!newelem) {
  125. Log(LOG_EMERG,
  126. "Can't allocate memory for new list entry!");
  127. return false;
  128. }
  129. strlcpy(newelem->mask, Mask, sizeof(newelem->mask));
  130. if (Reason) {
  131. newelem->reason = strdup(Reason);
  132. if (!newelem->reason)
  133. Log(LOG_EMERG,
  134. "Can't allocate memory for new list reason text!");
  135. }
  136. else
  137. newelem->reason = NULL;
  138. newelem->valid_until = ValidUntil;
  139. newelem->next = e;
  140. h->first = newelem;
  141. return true;
  142. }
  143. /**
  144. * Delete a list element from a list.
  145. *
  146. * @param h List head.
  147. * @param p Pointer to previous list element or NULL, if there is none.
  148. * @param victim List element to delete.
  149. */
  150. static void
  151. Lists_Unlink(struct list_head *h, struct list_elem *p, struct list_elem *victim)
  152. {
  153. assert(victim != NULL);
  154. assert(h != NULL);
  155. if (p)
  156. p->next = victim->next;
  157. else
  158. h->first = victim->next;
  159. if (victim->reason)
  160. free(victim->reason);
  161. free(victim);
  162. }
  163. /**
  164. * Delete a given IRC mask from a list.
  165. *
  166. * @param h List head.
  167. * @param Mask IRC mask to delete from the list.
  168. */
  169. GLOBAL void
  170. Lists_Del(struct list_head *h, const char *Mask)
  171. {
  172. struct list_elem *e, *last, *victim;
  173. assert(h != NULL);
  174. assert(Mask != NULL);
  175. last = NULL;
  176. e = Lists_GetFirst(h);
  177. while (e) {
  178. if (strcasecmp(e->mask, Mask) == 0) {
  179. LogDebug("Deleted \"%s\" from list", e->mask);
  180. victim = e;
  181. e = victim->next;
  182. Lists_Unlink(h, last, victim);
  183. continue;
  184. }
  185. last = e;
  186. e = e->next;
  187. }
  188. }
  189. /**
  190. * Free a complete list.
  191. *
  192. * @param head List head.
  193. */
  194. GLOBAL void
  195. Lists_Free(struct list_head *head)
  196. {
  197. struct list_elem *e, *victim;
  198. assert(head != NULL);
  199. e = head->first;
  200. head->first = NULL;
  201. while (e) {
  202. LogDebug("Deleted \"%s\" from list" , e->mask);
  203. victim = e;
  204. e = e->next;
  205. if (victim->reason)
  206. free(victim->reason);
  207. free(victim);
  208. }
  209. }
  210. /**
  211. * Check if an IRC mask is already contained in a list.
  212. *
  213. * @param h List head.
  214. * @param Mask IRC mask to test.
  215. * @return true if mask is already stored in the list, false otherwise.
  216. */
  217. GLOBAL struct list_elem *
  218. Lists_CheckDupeMask(const struct list_head *h, const char *Mask )
  219. {
  220. struct list_elem *e;
  221. e = h->first;
  222. while (e) {
  223. if (strcasecmp(e->mask, Mask) == 0)
  224. return e;
  225. e = e->next;
  226. }
  227. return NULL;
  228. }
  229. /**
  230. * Generate a valid IRC mask from "any" string given.
  231. *
  232. * Attention: This mask is only valid until the next call to Lists_MakeMask(),
  233. * because a single global buffer ist used! You have to copy the generated
  234. * mask to some sane location yourself!
  235. *
  236. * @param Pattern Source string to generate an IRC mask for.
  237. * @return Pointer to global result buffer.
  238. */
  239. GLOBAL const char *
  240. Lists_MakeMask(const char *Pattern)
  241. {
  242. static char TheMask[MASK_LEN];
  243. char *excl, *at;
  244. assert(Pattern != NULL);
  245. excl = strchr(Pattern, '!');
  246. at = strchr(Pattern, '@');
  247. if (at && at < excl)
  248. excl = NULL;
  249. if (!at && !excl) {
  250. /* Neither "!" nor "@" found: use string as nickname */
  251. strlcpy(TheMask, Pattern, sizeof(TheMask) - 5);
  252. strlcat(TheMask, "!*@*", sizeof(TheMask));
  253. return TheMask;
  254. }
  255. if (!at && excl) {
  256. /* Domain part is missing */
  257. strlcpy(TheMask, Pattern, sizeof(TheMask) - 3);
  258. strlcat(TheMask, "@*", sizeof(TheMask));
  259. return TheMask;
  260. }
  261. if (at && !excl) {
  262. /* User name is missing */
  263. *at = '\0'; at++;
  264. strlcpy(TheMask, Pattern, sizeof(TheMask) - 5);
  265. strlcat(TheMask, "!*@", sizeof(TheMask));
  266. strlcat(TheMask, at, sizeof(TheMask));
  267. return TheMask;
  268. }
  269. /* All parts (nick, user and domain name) are given */
  270. strlcpy(TheMask, Pattern, sizeof(TheMask));
  271. return TheMask;
  272. } /* Lists_MakeMask */
  273. /**
  274. * Check if a client is listed in a list.
  275. *
  276. * @param h List head.
  277. * @param Client Client to check.
  278. * @return true if client is listed, false if not.
  279. */
  280. bool
  281. Lists_Check(struct list_head *h, CLIENT *Client)
  282. {
  283. return Lists_CheckReason(h, Client) != NULL;
  284. }
  285. /**
  286. * Check if a client is listed in a list and return the "reason".
  287. *
  288. * @param h List head.
  289. * @param Client Client to check.
  290. * @return true if client is listed, false if not.
  291. */
  292. char *
  293. Lists_CheckReason(struct list_head *h, CLIENT *Client)
  294. {
  295. struct list_elem *e, *last, *next;
  296. assert(h != NULL);
  297. e = h->first;
  298. last = NULL;
  299. while (e) {
  300. next = e->next;
  301. if (Match(e->mask, Client_Mask(Client))) {
  302. if (e->valid_until == 1) {
  303. /* Entry is valid only once, delete it */
  304. LogDebug("Deleted \"%s\" from list (used).",
  305. e->mask);
  306. Lists_Unlink(h, last, e);
  307. }
  308. return e->reason ? e->reason : "";
  309. }
  310. last = e;
  311. e = next;
  312. }
  313. return NULL;
  314. }
  315. /**
  316. * Check list and purge expired entries.
  317. *
  318. * @param h List head.
  319. */
  320. GLOBAL void
  321. Lists_Expire(struct list_head *h, const char *ListName)
  322. {
  323. struct list_elem *e, *last, *next;
  324. time_t now;
  325. assert(h != NULL);
  326. e = h->first;
  327. last = NULL;
  328. now = time(NULL);
  329. while (e) {
  330. next = e->next;
  331. if (e->valid_until > 1 && e->valid_until < now) {
  332. /* Entry is expired, delete it */
  333. if (e->reason)
  334. Log(LOG_INFO,
  335. "Deleted \"%s\" (\"%s\") from %s list (expired).",
  336. e->mask, e->reason, ListName);
  337. else
  338. Log(LOG_INFO,
  339. "Deleted \"%s\" from %s list (expired).",
  340. e->mask, ListName);
  341. Lists_Unlink(h, last, e);
  342. e = next;
  343. continue;
  344. }
  345. last = e;
  346. e = next;
  347. }
  348. }
  349. /**
  350. * Return the number of entries of a list.
  351. *
  352. * @param h List head.
  353. * @return Number of items.
  354. */
  355. GLOBAL unsigned long
  356. Lists_Count(struct list_head *h)
  357. {
  358. struct list_elem *e;
  359. unsigned long count = 0;
  360. assert(h != NULL);
  361. e = h->first;
  362. while (e) {
  363. count++;
  364. e = e->next;
  365. }
  366. return count;
  367. }
  368. /* -eof- */