lists.c 8.4 KB

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