lists.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  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. struct list_elem {
  31. struct list_elem *next; /** pointer to next list element */
  32. char mask[MASK_LEN]; /** IRC mask */
  33. char *reason; /** Optional "reason" text */
  34. time_t valid_until; /** 0: unlimited; 1: once; t(>1): until t */
  35. };
  36. /**
  37. * Get IRC mask stored in list element.
  38. *
  39. * @param list_elem List element.
  40. * @return Pointer to IRC mask
  41. */
  42. GLOBAL const char *
  43. Lists_GetMask(const struct list_elem *e)
  44. {
  45. assert(e != NULL);
  46. return e->mask;
  47. }
  48. /**
  49. * Get optional "reason" text stored in list element.
  50. *
  51. * @param list_elem List element.
  52. * @return Pointer to "reason" text or empty string ("").
  53. */
  54. GLOBAL const char *
  55. Lists_GetReason(const struct list_elem *e)
  56. {
  57. assert(e != NULL);
  58. return e->reason ? e->reason : "";
  59. }
  60. /**
  61. * Get "validity" value stored in list element.
  62. *
  63. * @param list_elem List element.
  64. * @return Validity: 0=unlimited, 1=once, >1 until this time stamp.
  65. */
  66. GLOBAL time_t
  67. Lists_GetValidity(const struct list_elem *e)
  68. {
  69. assert(e != NULL);
  70. return e->valid_until;
  71. }
  72. /**
  73. * Get first list element of a list.
  74. *
  75. * @param h List head.
  76. * @return Pointer to first list element.
  77. */
  78. GLOBAL struct list_elem*
  79. Lists_GetFirst(const struct list_head *h)
  80. {
  81. assert(h != NULL);
  82. return h->first;
  83. }
  84. /**
  85. * Get next list element of a list.
  86. *
  87. * @param e Current list element.
  88. * @return Pointer to next list element.
  89. */
  90. GLOBAL struct list_elem*
  91. Lists_GetNext(const struct list_elem *e)
  92. {
  93. assert(e != NULL);
  94. return e->next;
  95. }
  96. /**
  97. * Add a new mask to a list.
  98. *
  99. * @param h List head.
  100. * @param Mask The IRC mask to add to the list.
  101. * @param ValidUntil 0: unlimited, 1: only once, t>1: until given time_t.
  102. * @param Reason Reason string or NULL, if no reason should be saved.
  103. * @return true on success, false otherwise.
  104. */
  105. bool
  106. Lists_Add(struct list_head *h, const char *Mask, time_t ValidUntil,
  107. const char *Reason)
  108. {
  109. struct list_elem *e, *newelem;
  110. assert(h != NULL);
  111. assert(Mask != NULL);
  112. e = Lists_CheckDupeMask(h, Mask);
  113. if (e) {
  114. e->valid_until = ValidUntil;
  115. if (Reason) {
  116. if (e->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. * @param Pattern Source string to generate an IRC mask for.
  233. * @param mask Buffer to store the mask.
  234. * @param len Size of the buffer.
  235. */
  236. GLOBAL void
  237. Lists_MakeMask(const char *Pattern, char *mask, size_t len)
  238. {
  239. char *excl, *at;
  240. assert(Pattern != NULL);
  241. excl = strchr(Pattern, '!');
  242. at = strchr(Pattern, '@');
  243. if (at && at < excl)
  244. excl = NULL;
  245. if (!at && !excl) {
  246. /* Neither "!" nor "@" found: use string as nickname */
  247. strlcpy(mask, Pattern, len - 5);
  248. strlcat(mask, "!*@*", len);
  249. } else if (!at && excl) {
  250. /* Domain part is missing */
  251. strlcpy(mask, Pattern, len - 3);
  252. strlcat(mask, "@*", len);
  253. } else if (at && !excl) {
  254. /* User name is missing */
  255. *at = '\0'; at++;
  256. strlcpy(mask, Pattern, len - 5);
  257. strlcat(mask, "!*@", len);
  258. strlcat(mask, at, len);
  259. } else {
  260. /* All parts (nick, user and domain name) are given */
  261. strlcpy(mask, Pattern, len);
  262. }
  263. } /* Lists_MakeMask */
  264. /**
  265. * Check if a client is listed in a list.
  266. *
  267. * @param h List head.
  268. * @param Client Client to check.
  269. * @return true if client is listed, false if not.
  270. */
  271. bool
  272. Lists_Check(struct list_head *h, CLIENT *Client)
  273. {
  274. return Lists_CheckReason(h, Client, NULL, 0);
  275. }
  276. /**
  277. * Check if a client is listed in a list and store the reason.
  278. *
  279. * @param h List head.
  280. * @param Client Client to check.
  281. * @param reason Buffer to store the reason.
  282. * @param len Size of the buffer if reason should be saved.
  283. * @return true if client is listed, false if not.
  284. */
  285. bool
  286. Lists_CheckReason(struct list_head *h, CLIENT *Client, char *reason, size_t len)
  287. {
  288. struct list_elem *e, *last, *next;
  289. assert(h != NULL);
  290. e = h->first;
  291. last = NULL;
  292. while (e) {
  293. next = e->next;
  294. if (Match(e->mask, Client_MaskCloaked(Client))) {
  295. if (len && e->reason)
  296. strlcpy(reason, e->reason, len);
  297. if (e->valid_until == 1) {
  298. /* Entry is valid only once, delete it */
  299. LogDebug("Deleted \"%s\" from list (used).",
  300. e->mask);
  301. Lists_Unlink(h, last, e);
  302. }
  303. return true;
  304. }
  305. last = e;
  306. e = next;
  307. }
  308. return false;
  309. }
  310. /**
  311. * Check list and purge expired entries.
  312. *
  313. * @param h List head.
  314. */
  315. GLOBAL void
  316. Lists_Expire(struct list_head *h, const char *ListName)
  317. {
  318. struct list_elem *e, *last, *next;
  319. time_t now;
  320. assert(h != NULL);
  321. e = h->first;
  322. last = NULL;
  323. now = time(NULL);
  324. while (e) {
  325. next = e->next;
  326. if (e->valid_until > 1 && e->valid_until < now) {
  327. /* Entry is expired, delete it */
  328. if (e->reason)
  329. Log(LOG_INFO,
  330. "Deleted \"%s\" (\"%s\") from %s list (expired).",
  331. e->mask, e->reason, ListName);
  332. else
  333. Log(LOG_INFO,
  334. "Deleted \"%s\" from %s list (expired).",
  335. e->mask, ListName);
  336. Lists_Unlink(h, last, e);
  337. e = next;
  338. continue;
  339. }
  340. last = e;
  341. e = next;
  342. }
  343. }
  344. /**
  345. * Return the number of entries of a list.
  346. *
  347. * @param h List head.
  348. * @return Number of items.
  349. */
  350. GLOBAL unsigned long
  351. Lists_Count(struct list_head *h)
  352. {
  353. struct list_elem *e;
  354. unsigned long count = 0;
  355. assert(h != NULL);
  356. e = h->first;
  357. while (e) {
  358. count++;
  359. e = e->next;
  360. }
  361. return count;
  362. }
  363. /* -eof- */