lists.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  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 = malloc(strlen(Reason) + 1);
  132. if (newelem->reason)
  133. strlcpy(newelem->reason, Reason, strlen(Reason) + 1);
  134. else
  135. Log(LOG_EMERG,
  136. "Can't allocate memory for new list reason text!");
  137. }
  138. else
  139. newelem->reason = NULL;
  140. newelem->valid_until = ValidUntil;
  141. newelem->next = e;
  142. h->first = newelem;
  143. return true;
  144. }
  145. /**
  146. * Delete a list element from a list.
  147. *
  148. * @param h List head.
  149. * @param p Pointer to previous list element or NULL, if there is none.
  150. * @param victim List element to delete.
  151. */
  152. static void
  153. Lists_Unlink(struct list_head *h, struct list_elem *p, struct list_elem *victim)
  154. {
  155. assert(victim != NULL);
  156. assert(h != NULL);
  157. if (p)
  158. p->next = victim->next;
  159. else
  160. h->first = victim->next;
  161. if (victim->reason)
  162. free(victim->reason);
  163. free(victim);
  164. }
  165. /**
  166. * Delete a given IRC mask from a list.
  167. *
  168. * @param h List head.
  169. * @param Mask IRC mask to delete from the list.
  170. */
  171. GLOBAL void
  172. Lists_Del(struct list_head *h, const char *Mask)
  173. {
  174. struct list_elem *e, *last, *victim;
  175. assert(h != NULL);
  176. assert(Mask != NULL);
  177. last = NULL;
  178. e = Lists_GetFirst(h);
  179. while (e) {
  180. if (strcasecmp(e->mask, Mask) == 0) {
  181. LogDebug("Deleted \"%s\" from list", e->mask);
  182. victim = e;
  183. e = victim->next;
  184. Lists_Unlink(h, last, victim);
  185. continue;
  186. }
  187. last = e;
  188. e = e->next;
  189. }
  190. }
  191. /**
  192. * Free a complete list.
  193. *
  194. * @param head List head.
  195. */
  196. GLOBAL void
  197. Lists_Free(struct list_head *head)
  198. {
  199. struct list_elem *e, *victim;
  200. assert(head != NULL);
  201. e = head->first;
  202. head->first = NULL;
  203. while (e) {
  204. LogDebug("Deleted \"%s\" from list" , e->mask);
  205. victim = e;
  206. e = e->next;
  207. if (victim->reason)
  208. free(victim->reason);
  209. free(victim);
  210. }
  211. }
  212. /**
  213. * Check if an IRC mask is already contained in a list.
  214. *
  215. * @param h List head.
  216. * @param Mask IRC mask to test.
  217. * @return true if mask is already stored in the list, false otherwise.
  218. */
  219. GLOBAL struct list_elem *
  220. Lists_CheckDupeMask(const struct list_head *h, const char *Mask )
  221. {
  222. struct list_elem *e;
  223. e = h->first;
  224. while (e) {
  225. if (strcasecmp(e->mask, Mask) == 0)
  226. return e;
  227. e = e->next;
  228. }
  229. return NULL;
  230. }
  231. /**
  232. * Generate a valid IRC mask from "any" string given.
  233. *
  234. * Attention: This mask is only valid until the next call to Lists_MakeMask(),
  235. * because a single global buffer ist used! You have to copy the generated
  236. * mask to some sane location yourself!
  237. *
  238. * @param Pattern Source string to generate an IRC mask for.
  239. * @return Pointer to global result buffer.
  240. */
  241. GLOBAL const char *
  242. Lists_MakeMask(const char *Pattern)
  243. {
  244. static char TheMask[MASK_LEN];
  245. char *excl, *at;
  246. assert(Pattern != NULL);
  247. excl = strchr(Pattern, '!');
  248. at = strchr(Pattern, '@');
  249. if (at && at < excl)
  250. excl = NULL;
  251. if (!at && !excl) {
  252. /* Neither "!" nor "@" found: use string as nick name */
  253. strlcpy(TheMask, Pattern, sizeof(TheMask) - 5);
  254. strlcat(TheMask, "!*@*", sizeof(TheMask));
  255. return TheMask;
  256. }
  257. if (!at && excl) {
  258. /* Domain part is missing */
  259. strlcpy(TheMask, Pattern, sizeof(TheMask) - 3);
  260. strlcat(TheMask, "@*", sizeof(TheMask));
  261. return TheMask;
  262. }
  263. if (at && !excl) {
  264. /* User name is missing */
  265. *at = '\0'; at++;
  266. strlcpy(TheMask, Pattern, sizeof(TheMask) - 5);
  267. strlcat(TheMask, "!*@", sizeof(TheMask));
  268. strlcat(TheMask, at, sizeof(TheMask));
  269. return TheMask;
  270. }
  271. /* All parts (nick, user and domain name) are given */
  272. strlcpy(TheMask, Pattern, sizeof(TheMask));
  273. return TheMask;
  274. } /* Lists_MakeMask */
  275. /**
  276. * Check if a client is listed in a list.
  277. *
  278. * @param h List head.
  279. * @param Client Client to check.
  280. * @return true if client is listed, false if not.
  281. */
  282. bool
  283. Lists_Check(struct list_head *h, CLIENT *Client)
  284. {
  285. return Lists_CheckReason(h, Client) != NULL;
  286. }
  287. /**
  288. * Check if a client is listed in a list and return the "reason".
  289. *
  290. * @param h List head.
  291. * @param Client Client to check.
  292. * @return true if client is listed, false if not.
  293. */
  294. char *
  295. Lists_CheckReason(struct list_head *h, CLIENT *Client)
  296. {
  297. struct list_elem *e, *last, *next;
  298. assert(h != NULL);
  299. e = h->first;
  300. last = NULL;
  301. while (e) {
  302. next = e->next;
  303. if (Match(e->mask, Client_Mask(Client))) {
  304. if (e->valid_until == 1) {
  305. /* Entry is valid only once, delete it */
  306. LogDebug("Deleted \"%s\" from list (used).",
  307. e->mask);
  308. Lists_Unlink(h, last, e);
  309. }
  310. return e->reason ? e->reason : "";
  311. }
  312. last = e;
  313. e = next;
  314. }
  315. return NULL;
  316. }
  317. /**
  318. * Check list and purge expired entries.
  319. *
  320. * @param h List head.
  321. */
  322. GLOBAL void
  323. Lists_Expire(struct list_head *h, const char *ListName)
  324. {
  325. struct list_elem *e, *last, *next;
  326. time_t now;
  327. assert(h != NULL);
  328. e = h->first;
  329. last = NULL;
  330. now = time(NULL);
  331. while (e) {
  332. next = e->next;
  333. if (e->valid_until > 1 && e->valid_until < now) {
  334. /* Entry is expired, delete it */
  335. if (e->reason)
  336. Log(LOG_INFO,
  337. "Deleted \"%s\" (\"%s\") from %s list (expired).",
  338. e->mask, e->reason, ListName);
  339. else
  340. Log(LOG_INFO,
  341. "Deleted \"%s\" from %s list (expired).",
  342. e->mask, ListName);
  343. Lists_Unlink(h, last, e);
  344. e = next;
  345. continue;
  346. }
  347. last = e;
  348. e = next;
  349. }
  350. }
  351. /**
  352. * Return the number of entries of a list.
  353. *
  354. * @param h List head.
  355. * @return Number of items.
  356. */
  357. GLOBAL unsigned long
  358. Lists_Count(struct list_head *h)
  359. {
  360. struct list_elem *e;
  361. unsigned long count = 0;
  362. assert(h != NULL);
  363. e = h->first;
  364. while (e) {
  365. count++;
  366. e = e->next;
  367. }
  368. return count;
  369. }
  370. /* -eof- */