lists.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  1. /*
  2. * ngIRCd -- The Next Generation IRC Daemon
  3. * Copyright (c)2001-2005 Alexander Barton (alex@barton.de)
  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. * Management of IRC lists: ban, invite, ...
  12. */
  13. #include "portab.h"
  14. static char UNUSED id[] = "$Id: lists.c,v 1.18 2005/07/31 20:13:08 alex Exp $";
  15. #include "imp.h"
  16. #include <assert.h>
  17. #include "defines.h"
  18. #include "conn.h"
  19. #include "client.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. typedef struct _C2C
  32. {
  33. struct _C2C *next;
  34. char mask[MASK_LEN];
  35. CHANNEL *channel;
  36. bool onlyonce;
  37. } C2C;
  38. static C2C *My_Invites, *My_Bans;
  39. static C2C *New_C2C PARAMS(( char *Mask, CHANNEL *Chan, bool OnlyOnce ));
  40. static bool Check_List PARAMS(( C2C **Cl2Chan, CLIENT *Client, CHANNEL *Chan ));
  41. static bool Already_Registered PARAMS(( C2C *Cl2Chan, char *Mask, CHANNEL *Chan ));
  42. GLOBAL void
  43. Lists_Init( void )
  44. {
  45. /* Modul initialisieren */
  46. My_Invites = My_Bans = NULL;
  47. } /* Lists_Init */
  48. GLOBAL void
  49. Lists_Exit( void )
  50. {
  51. /* Modul abmelden */
  52. C2C *c2c, *next;
  53. /* Invite-Lists freigeben */
  54. c2c = My_Invites;
  55. while( c2c )
  56. {
  57. next = c2c->next;
  58. free( c2c );
  59. c2c = next;
  60. }
  61. /* Ban-Lists freigeben */
  62. c2c = My_Bans;
  63. while( c2c )
  64. {
  65. next = c2c->next;
  66. free( c2c );
  67. c2c = next;
  68. }
  69. } /* Lists_Exit */
  70. GLOBAL bool
  71. Lists_CheckInvited( CLIENT *Client, CHANNEL *Chan )
  72. {
  73. return Check_List( &My_Invites, Client, Chan );
  74. } /* Lists_CheckInvited */
  75. GLOBAL bool
  76. Lists_IsInviteEntry( char *Mask, CHANNEL *Chan )
  77. {
  78. assert( Mask != NULL );
  79. assert( Chan != NULL );
  80. return Already_Registered( My_Invites, Mask, Chan );
  81. } /* Lists_IsInviteEntry */
  82. GLOBAL bool
  83. Lists_AddInvited( char *Mask, CHANNEL *Chan, bool OnlyOnce )
  84. {
  85. C2C *c2c;
  86. assert( Mask != NULL );
  87. assert( Chan != NULL );
  88. if( Already_Registered( My_Invites, Mask, Chan )) return true;
  89. c2c = New_C2C( Mask, Chan, OnlyOnce );
  90. if( ! c2c )
  91. {
  92. Log( LOG_ERR, "Can't add new invite list entry!" );
  93. return false;
  94. }
  95. /* verketten */
  96. c2c->next = My_Invites;
  97. My_Invites = c2c;
  98. Log( LOG_DEBUG, "Added \"%s\" to invite list for \"%s\".", Mask, Channel_Name( Chan ));
  99. return true;
  100. } /* Lists_AddInvited */
  101. GLOBAL void
  102. Lists_DelInvited( char *Mask, CHANNEL *Chan )
  103. {
  104. C2C *c2c, *last, *next;
  105. assert( Mask != NULL );
  106. assert( Chan != NULL );
  107. last = NULL;
  108. c2c = My_Invites;
  109. while( c2c )
  110. {
  111. next = c2c->next;
  112. if(( c2c->channel == Chan ) && ( strcasecmp( c2c->mask, Mask ) == 0 ))
  113. {
  114. /* dieser Eintrag muss geloescht werden */
  115. Log( LOG_DEBUG, "Deleted \"%s\" from invite list for \"%s\"." , c2c->mask, Channel_Name( Chan ));
  116. if( last ) last->next = next;
  117. else My_Invites = next;
  118. free( c2c );
  119. }
  120. else last = c2c;
  121. c2c = next;
  122. }
  123. } /* Lists_DelInvited */
  124. GLOBAL bool
  125. Lists_ShowInvites( CLIENT *Client, CHANNEL *Channel )
  126. {
  127. C2C *c2c;
  128. assert( Client != NULL );
  129. assert( Channel != NULL );
  130. c2c = My_Invites;
  131. while( c2c )
  132. {
  133. if( c2c->channel == Channel )
  134. {
  135. /* Eintrag fuer Channel gefunden; ausgeben: */
  136. if( ! IRC_WriteStrClient( Client, RPL_INVITELIST_MSG, Client_ID( Client ), Channel_Name( Channel ), c2c->mask )) return DISCONNECTED;
  137. }
  138. c2c = c2c->next;
  139. }
  140. return IRC_WriteStrClient( Client, RPL_ENDOFINVITELIST_MSG, Client_ID( Client ), Channel_Name( Channel ));
  141. } /* Lists_ShowInvites */
  142. GLOBAL bool
  143. Lists_SendInvites( CLIENT *Client )
  144. {
  145. C2C *c2c;
  146. assert( Client != NULL );
  147. c2c = My_Invites;
  148. while( c2c )
  149. {
  150. if( ! IRC_WriteStrClient( Client, "MODE %s +I %s", Channel_Name( c2c->channel ), c2c->mask )) return DISCONNECTED;
  151. c2c = c2c->next;
  152. }
  153. return CONNECTED;
  154. } /* Lists_SendInvites */
  155. GLOBAL bool
  156. Lists_SendBans( CLIENT *Client )
  157. {
  158. C2C *c2c;
  159. assert( Client != NULL );
  160. c2c = My_Bans;
  161. while( c2c )
  162. {
  163. if( ! IRC_WriteStrClient( Client, "MODE %s +b %s", Channel_Name( c2c->channel ), c2c->mask )) return DISCONNECTED;
  164. c2c = c2c->next;
  165. }
  166. return CONNECTED;
  167. } /* Lists_SendBans */
  168. GLOBAL bool
  169. Lists_CheckBanned( CLIENT *Client, CHANNEL *Chan )
  170. {
  171. return Check_List( &My_Bans, Client, Chan );
  172. } /* Lists_CheckBanned */
  173. GLOBAL bool
  174. Lists_IsBanEntry( char *Mask, CHANNEL *Chan )
  175. {
  176. assert( Mask != NULL );
  177. assert( Chan != NULL );
  178. return Already_Registered( My_Bans, Mask, Chan );
  179. } /* Lists_IsBanEntry */
  180. GLOBAL bool
  181. Lists_AddBanned( char *Mask, CHANNEL *Chan )
  182. {
  183. C2C *c2c;
  184. assert( Mask != NULL );
  185. assert( Chan != NULL );
  186. if( Already_Registered( My_Bans, Mask, Chan )) return true;
  187. c2c = New_C2C( Mask, Chan, false );
  188. if( ! c2c )
  189. {
  190. Log( LOG_ERR, "Can't add new ban list entry!" );
  191. return false;
  192. }
  193. /* verketten */
  194. c2c->next = My_Bans;
  195. My_Bans = c2c;
  196. Log( LOG_DEBUG, "Added \"%s\" to ban list for \"%s\".", Mask, Channel_Name( Chan ));
  197. return true;
  198. } /* Lists_AddBanned */
  199. GLOBAL void
  200. Lists_DelBanned( char *Mask, CHANNEL *Chan )
  201. {
  202. C2C *c2c, *last, *next;
  203. assert( Mask != NULL );
  204. assert( Chan != NULL );
  205. last = NULL;
  206. c2c = My_Bans;
  207. while( c2c )
  208. {
  209. next = c2c->next;
  210. if(( c2c->channel == Chan ) && ( strcasecmp( c2c->mask, Mask ) == 0 ))
  211. {
  212. /* dieser Eintrag muss geloescht werden */
  213. Log( LOG_DEBUG, "Deleted \"%s\" from ban list for \"%s\"." , c2c->mask, Channel_Name( Chan ));
  214. if( last ) last->next = next;
  215. else My_Bans = next;
  216. free( c2c );
  217. }
  218. else last = c2c;
  219. c2c = next;
  220. }
  221. } /* Lists_DelBanned */
  222. GLOBAL bool
  223. Lists_ShowBans( CLIENT *Client, CHANNEL *Channel )
  224. {
  225. C2C *c2c;
  226. assert( Client != NULL );
  227. assert( Channel != NULL );
  228. c2c = My_Bans;
  229. while( c2c )
  230. {
  231. if( c2c->channel == Channel )
  232. {
  233. /* Eintrag fuer Channel gefunden; ausgeben: */
  234. if( ! IRC_WriteStrClient( Client, RPL_BANLIST_MSG, Client_ID( Client ), Channel_Name( Channel ), c2c->mask )) return DISCONNECTED;
  235. }
  236. c2c = c2c->next;
  237. }
  238. return IRC_WriteStrClient( Client, RPL_ENDOFBANLIST_MSG, Client_ID( Client ), Channel_Name( Channel ));
  239. } /* Lists_ShowBans */
  240. GLOBAL void
  241. Lists_DeleteChannel( CHANNEL *Chan )
  242. {
  243. /* Channel wurde geloescht, Invite- und Ban-Lists aufraeumen */
  244. C2C *c2c, *last, *next;
  245. /* Invite-List */
  246. last = NULL;
  247. c2c = My_Invites;
  248. while( c2c )
  249. {
  250. next = c2c->next;
  251. if( c2c->channel == Chan )
  252. {
  253. /* dieser Eintrag muss geloescht werden */
  254. Log( LOG_DEBUG, "Deleted \"%s\" from invite list for \"%s\"." , c2c->mask, Channel_Name( Chan ));
  255. if( last ) last->next = next;
  256. else My_Invites = next;
  257. free( c2c );
  258. }
  259. else last = c2c;
  260. c2c = next;
  261. }
  262. /* Ban-List */
  263. last = NULL;
  264. c2c = My_Bans;
  265. while( c2c )
  266. {
  267. next = c2c->next;
  268. if( c2c->channel == Chan )
  269. {
  270. /* dieser Eintrag muss geloescht werden */
  271. Log( LOG_DEBUG, "Deleted \"%s\" from ban list for \"%s\"." , c2c->mask, Channel_Name( Chan ));
  272. if( last ) last->next = next;
  273. else My_Bans = next;
  274. free( c2c );
  275. }
  276. else last = c2c;
  277. c2c = next;
  278. }
  279. } /* Lists_DeleteChannel */
  280. GLOBAL char *
  281. Lists_MakeMask( char *Pattern )
  282. {
  283. /* This function generats a valid IRC mask of "any" string. This
  284. * mask is only valid until the next call to Lists_MakeMask(),
  285. * because a single global buffer is used. You have to copy the
  286. * generated mask to some sane location yourself! */
  287. static char TheMask[MASK_LEN];
  288. char *excl, *at;
  289. assert( Pattern != NULL );
  290. excl = strchr( Pattern, '!' );
  291. at = strchr( Pattern, '@' );
  292. if(( at ) && ( at < excl )) excl = NULL;
  293. if(( ! at ) && ( ! excl ))
  294. {
  295. /* Neither "!" nor "@" found: use string as nick name */
  296. strlcpy( TheMask, Pattern, sizeof( TheMask ) - 5 );
  297. strlcat( TheMask, "!*@*", sizeof( TheMask ));
  298. return TheMask;
  299. }
  300. if(( ! at ) && ( excl ))
  301. {
  302. /* Domain part is missing */
  303. strlcpy( TheMask, Pattern, sizeof( TheMask ) - 3 );
  304. strlcat( TheMask, "@*", sizeof( TheMask ));
  305. return TheMask;
  306. }
  307. if(( at ) && ( ! excl ))
  308. {
  309. /* User name is missing */
  310. *at = '\0'; at++;
  311. strlcpy( TheMask, Pattern, sizeof( TheMask ) - 5 );
  312. strlcat( TheMask, "!*@", sizeof( TheMask ));
  313. strlcat( TheMask, at, sizeof( TheMask ));
  314. return TheMask;
  315. }
  316. /* All parts (nick, user and domain name) are given */
  317. strlcpy( TheMask, Pattern, sizeof( TheMask ));
  318. return TheMask;
  319. } /* Lists_MakeMask */
  320. static C2C *
  321. New_C2C( char *Mask, CHANNEL *Chan, bool OnlyOnce )
  322. {
  323. C2C *c2c;
  324. assert( Mask != NULL );
  325. assert( Chan != NULL );
  326. /* Speicher fuer Eintrag anfordern */
  327. c2c = (C2C *)malloc( sizeof( C2C ));
  328. if( ! c2c )
  329. {
  330. Log( LOG_EMERG, "Can't allocate memory! [New_C2C]" );
  331. return NULL;
  332. }
  333. strlcpy( c2c->mask, Mask, sizeof( c2c->mask ));
  334. c2c->channel = Chan;
  335. c2c->onlyonce = OnlyOnce;
  336. return c2c;
  337. } /* New_C2C */
  338. static bool
  339. Check_List( C2C **Cl2Chan, CLIENT *Client, CHANNEL *Chan )
  340. {
  341. C2C *c2c, *last;
  342. assert( Cl2Chan != NULL );
  343. assert( Client != NULL );
  344. assert( Chan != NULL );
  345. c2c = *Cl2Chan;
  346. last = NULL;
  347. while( c2c )
  348. {
  349. if( c2c->channel == Chan )
  350. {
  351. /* Ok, richtiger Channel. Passt die Maske? */
  352. if( Match( c2c->mask, Client_Mask( Client )))
  353. {
  354. /* Treffer! */
  355. if( c2c->onlyonce )
  356. {
  357. /* Eintrag loeschen */
  358. Log( LOG_DEBUG, "Deleted \"%s\" from %s list for \"%s\".", c2c->mask, *Cl2Chan == My_Invites ? "invite" : "ban", Channel_Name( Chan ));
  359. if( last ) last->next = c2c->next;
  360. else *Cl2Chan = c2c->next;
  361. free( c2c );
  362. }
  363. return true;
  364. }
  365. }
  366. last = c2c;
  367. c2c = c2c->next;
  368. }
  369. return false;
  370. } /* Check_List */
  371. static bool
  372. Already_Registered( C2C *List, char *Mask, CHANNEL *Chan )
  373. {
  374. C2C *c2c;
  375. c2c = List;
  376. while( c2c )
  377. {
  378. if(( c2c->channel == Chan ) && ( strcasecmp( c2c->mask, Mask ) == 0 )) return true;
  379. c2c = c2c->next;
  380. }
  381. return false;
  382. } /* Already_Registered */
  383. /* -eof- */