channel.c 22 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043
  1. /*
  2. * ngIRCd -- The Next Generation IRC Daemon
  3. * Copyright (c)2001-2005 by 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. * Channel management
  12. */
  13. #define __channel_c__
  14. #include "portab.h"
  15. static char UNUSED id[] = "$Id: channel.c,v 1.65 2008/02/05 16:31:35 fw Exp $";
  16. #include "imp.h"
  17. #include <assert.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <errno.h>
  21. #include <strings.h>
  22. #include "defines.h"
  23. #include "conn-func.h"
  24. #include "client.h"
  25. #include "exp.h"
  26. #include "channel.h"
  27. #include "imp.h"
  28. #include "irc-write.h"
  29. #include "resolve.h"
  30. #include "conf.h"
  31. #include "hash.h"
  32. #include "lists.h"
  33. #include "log.h"
  34. #include "messages.h"
  35. #include "exp.h"
  36. #define REMOVE_PART 0
  37. #define REMOVE_QUIT 1
  38. #define REMOVE_KICK 2
  39. static CHANNEL *My_Channels;
  40. static CL2CHAN *My_Cl2Chan;
  41. static CL2CHAN *Get_Cl2Chan PARAMS(( CHANNEL *Chan, CLIENT *Client ));
  42. static CL2CHAN *Add_Client PARAMS(( CHANNEL *Chan, CLIENT *Client ));
  43. static bool Remove_Client PARAMS(( int Type, CHANNEL *Chan, CLIENT *Client, CLIENT *Origin, const char *Reason, bool InformServer ));
  44. static CL2CHAN *Get_First_Cl2Chan PARAMS(( CLIENT *Client, CHANNEL *Chan ));
  45. static CL2CHAN *Get_Next_Cl2Chan PARAMS(( CL2CHAN *Start, CLIENT *Client, CHANNEL *Chan ));
  46. static bool Delete_Channel PARAMS(( CHANNEL *Chan ));
  47. GLOBAL void
  48. Channel_Init( void )
  49. {
  50. My_Channels = NULL;
  51. My_Cl2Chan = NULL;
  52. } /* Channel_Init */
  53. GLOBAL struct list_head *
  54. Channel_GetListBans(CHANNEL *c)
  55. {
  56. assert(c != NULL);
  57. return &c->list_bans;
  58. }
  59. GLOBAL struct list_head *
  60. Channel_GetListInvites(CHANNEL *c)
  61. {
  62. assert(c != NULL);
  63. return &c->list_invites;
  64. }
  65. GLOBAL void
  66. Channel_InitPredefined( void )
  67. {
  68. /* Vordefinierte persistente Channels erzeugen */
  69. CHANNEL *chan;
  70. char *c;
  71. unsigned int i;
  72. for( i = 0; i < Conf_Channel_Count; i++ )
  73. {
  74. /* Ist ein Name konfiguriert? */
  75. if( ! Conf_Channel[i].name[0] ) continue;
  76. /* Gueltiger Channel-Name? */
  77. if( ! Channel_IsValidName( Conf_Channel[i].name ))
  78. {
  79. Log( LOG_ERR, "Can't create pre-defined channel: invalid name: \"%s\"!", Conf_Channel[i].name );
  80. array_free(&Conf_Channel[i].topic);
  81. continue;
  82. }
  83. /* Gibt es den Channel bereits? */
  84. chan = Channel_Search( Conf_Channel[i].name );
  85. if( chan )
  86. {
  87. Log( LOG_INFO, "Can't create pre-defined channel \"%s\": name already in use.", Conf_Channel[i].name );
  88. array_free(&Conf_Channel[i].topic);
  89. continue;
  90. }
  91. /* Create channel */
  92. chan = Channel_Create(Conf_Channel[i].name);
  93. if (chan) {
  94. Channel_ModeAdd(chan, 'P');
  95. if (array_start(&Conf_Channel[i].topic) != NULL)
  96. Channel_SetTopic(chan, NULL,
  97. array_start(&Conf_Channel[i].topic));
  98. array_free(&Conf_Channel[i].topic);
  99. c = Conf_Channel[i].modes;
  100. while (*c)
  101. Channel_ModeAdd(chan, *c++);
  102. Channel_SetKey(chan, Conf_Channel[i].key);
  103. Channel_SetMaxUsers(chan, Conf_Channel[i].maxusers);
  104. Log(LOG_INFO, "Created pre-defined channel \"%s\".",
  105. Conf_Channel[i].name );
  106. }
  107. else Log(LOG_ERR, "Can't create pre-defined channel \"%s\"!",
  108. Conf_Channel[i].name );
  109. }
  110. } /* Channel_InitPredefined */
  111. GLOBAL void
  112. Channel_Exit( void )
  113. {
  114. CHANNEL *c, *c_next;
  115. CL2CHAN *cl2chan, *cl2chan_next;
  116. /* Channel-Strukturen freigeben */
  117. c = My_Channels;
  118. while( c )
  119. {
  120. c_next = c->next;
  121. array_free(&c->topic);
  122. free( c );
  123. c = c_next;
  124. }
  125. /* Channel-Zuordnungstabelle freigeben */
  126. cl2chan = My_Cl2Chan;
  127. while( c )
  128. {
  129. cl2chan_next = cl2chan->next;
  130. free( cl2chan );
  131. cl2chan = cl2chan_next;
  132. }
  133. } /* Channel_Exit */
  134. GLOBAL bool
  135. Channel_Join( CLIENT *Client, char *Name )
  136. {
  137. CHANNEL *chan;
  138. assert( Client != NULL );
  139. assert( Name != NULL );
  140. if( ! Channel_IsValidName( Name )) {
  141. IRC_WriteStrClient( Client, ERR_NOSUCHCHANNEL_MSG, Client_ID( Client ), Name );
  142. return false;
  143. }
  144. chan = Channel_Search( Name );
  145. if( chan ) {
  146. /* Ist der Client bereits Mitglied? */
  147. if( Get_Cl2Chan( chan, Client )) return false;
  148. }
  149. else
  150. {
  151. /* Gibt es noch nicht? Dann neu anlegen: */
  152. chan = Channel_Create( Name );
  153. if (!chan) return false;
  154. }
  155. /* User dem Channel hinzufuegen */
  156. if( ! Add_Client( chan, Client )) return false;
  157. else return true;
  158. } /* Channel_Join */
  159. /**
  160. * Remove client from channel.
  161. * This function lets a client lead a channel. First, the function checks
  162. * if the channel exists and the client is a member of it and sends out
  163. * appropriate error messages if not. The real work is done by the function
  164. * Remove_Client().
  165. */
  166. GLOBAL bool
  167. Channel_Part(CLIENT * Client, CLIENT * Origin, const char *Name, const char *Reason)
  168. {
  169. CHANNEL *chan;
  170. assert(Client != NULL);
  171. assert(Name != NULL);
  172. assert(Reason != NULL);
  173. chan = Channel_Search(Name);
  174. if (!chan) {
  175. IRC_WriteStrClient(Client, ERR_NOSUCHCHANNEL_MSG,
  176. Client_ID(Client), Name);
  177. return false;
  178. }
  179. if (!Get_Cl2Chan(chan, Client)) {
  180. IRC_WriteStrClient(Client, ERR_NOTONCHANNEL_MSG,
  181. Client_ID(Client), Name);
  182. return false;
  183. }
  184. if (!Remove_Client(REMOVE_PART, chan, Client, Origin, Reason, true))
  185. return false;
  186. else
  187. return true;
  188. } /* Channel_Part */
  189. GLOBAL void
  190. Channel_Kick( CLIENT *Client, CLIENT *Origin, char *Name, char *Reason )
  191. {
  192. CHANNEL *chan;
  193. assert( Client != NULL );
  194. assert( Origin != NULL );
  195. assert( Name != NULL );
  196. assert( Reason != NULL );
  197. chan = Channel_Search( Name );
  198. if( ! chan )
  199. {
  200. IRC_WriteStrClient( Origin, ERR_NOSUCHCHANNEL_MSG, Client_ID( Origin ), Name );
  201. return;
  202. }
  203. if( ! Channel_IsMemberOf( chan, Origin ))
  204. {
  205. IRC_WriteStrClient( Origin, ERR_NOTONCHANNEL_MSG, Client_ID( Origin ), Name );
  206. return;
  207. }
  208. /* Is User Channel-Operator? */
  209. if( ! strchr( Channel_UserModes( chan, Origin ), 'o' ))
  210. {
  211. IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Name);
  212. return;
  213. }
  214. /* Ist the kickED User member of channel? */
  215. if( ! Channel_IsMemberOf( chan, Client ))
  216. {
  217. IRC_WriteStrClient( Origin, ERR_USERNOTINCHANNEL_MSG, Client_ID( Origin ), Client_ID( Client ), Name );
  218. return;
  219. }
  220. Remove_Client( REMOVE_KICK, chan, Client, Origin, Reason, true);
  221. } /* Channel_Kick */
  222. GLOBAL void
  223. Channel_Quit( CLIENT *Client, char *Reason )
  224. {
  225. CHANNEL *c, *next_c;
  226. assert( Client != NULL );
  227. assert( Reason != NULL );
  228. IRC_WriteStrRelatedPrefix( Client, Client, false, "QUIT :%s", Reason );
  229. c = My_Channels;
  230. while( c )
  231. {
  232. next_c = c->next;
  233. Remove_Client( REMOVE_QUIT, c, Client, Client, Reason, false );
  234. c = next_c;
  235. }
  236. } /* Channel_Quit */
  237. GLOBAL unsigned long
  238. Channel_Count( void )
  239. {
  240. CHANNEL *c;
  241. unsigned long count = 0;
  242. c = My_Channels;
  243. while( c )
  244. {
  245. count++;
  246. c = c->next;
  247. }
  248. return count;
  249. } /* Channel_Count */
  250. GLOBAL unsigned long
  251. Channel_MemberCount( CHANNEL *Chan )
  252. {
  253. CL2CHAN *cl2chan;
  254. unsigned long count = 0;
  255. assert( Chan != NULL );
  256. cl2chan = My_Cl2Chan;
  257. while( cl2chan )
  258. {
  259. if( cl2chan->channel == Chan ) count++;
  260. cl2chan = cl2chan->next;
  261. }
  262. return count;
  263. } /* Channel_MemberCount */
  264. GLOBAL int
  265. Channel_CountForUser( CLIENT *Client )
  266. {
  267. /* Count number of channels a user is member of. */
  268. CL2CHAN *cl2chan;
  269. int count = 0;
  270. assert( Client != NULL );
  271. cl2chan = My_Cl2Chan;
  272. while( cl2chan )
  273. {
  274. if( cl2chan->client == Client ) count++;
  275. cl2chan = cl2chan->next;
  276. }
  277. return count;
  278. } /* Channel_CountForUser */
  279. GLOBAL const char *
  280. Channel_Name( const CHANNEL *Chan )
  281. {
  282. assert( Chan != NULL );
  283. return Chan->name;
  284. } /* Channel_Name */
  285. GLOBAL char *
  286. Channel_Modes( CHANNEL *Chan )
  287. {
  288. assert( Chan != NULL );
  289. return Chan->modes;
  290. } /* Channel_Modes */
  291. GLOBAL char *
  292. Channel_Key( CHANNEL *Chan )
  293. {
  294. assert( Chan != NULL );
  295. return Chan->key;
  296. } /* Channel_Key */
  297. GLOBAL unsigned long
  298. Channel_MaxUsers( CHANNEL *Chan )
  299. {
  300. assert( Chan != NULL );
  301. return Chan->maxusers;
  302. } /* Channel_MaxUsers */
  303. GLOBAL CHANNEL *
  304. Channel_First( void )
  305. {
  306. return My_Channels;
  307. } /* Channel_First */
  308. GLOBAL CHANNEL *
  309. Channel_Next( CHANNEL *Chan )
  310. {
  311. assert( Chan != NULL );
  312. return Chan->next;
  313. } /* Channel_Next */
  314. GLOBAL CHANNEL *
  315. Channel_Search( const char *Name )
  316. {
  317. /* Channel-Struktur suchen */
  318. CHANNEL *c;
  319. UINT32 search_hash;
  320. assert( Name != NULL );
  321. search_hash = Hash( Name );
  322. c = My_Channels;
  323. while( c )
  324. {
  325. if( search_hash == c->hash )
  326. {
  327. /* lt. Hash-Wert: Treffer! */
  328. if( strcasecmp( Name, c->name ) == 0 ) return c;
  329. }
  330. c = c->next;
  331. }
  332. return NULL;
  333. } /* Channel_Search */
  334. GLOBAL CL2CHAN *
  335. Channel_FirstMember( CHANNEL *Chan )
  336. {
  337. assert( Chan != NULL );
  338. return Get_First_Cl2Chan( NULL, Chan );
  339. } /* Channel_FirstMember */
  340. GLOBAL CL2CHAN *
  341. Channel_NextMember( CHANNEL *Chan, CL2CHAN *Cl2Chan )
  342. {
  343. assert( Chan != NULL );
  344. assert( Cl2Chan != NULL );
  345. return Get_Next_Cl2Chan( Cl2Chan->next, NULL, Chan );
  346. } /* Channel_NextMember */
  347. GLOBAL CL2CHAN *
  348. Channel_FirstChannelOf( CLIENT *Client )
  349. {
  350. assert( Client != NULL );
  351. return Get_First_Cl2Chan( Client, NULL );
  352. } /* Channel_FirstChannelOf */
  353. GLOBAL CL2CHAN *
  354. Channel_NextChannelOf( CLIENT *Client, CL2CHAN *Cl2Chan )
  355. {
  356. assert( Client != NULL );
  357. assert( Cl2Chan != NULL );
  358. return Get_Next_Cl2Chan( Cl2Chan->next, Client, NULL );
  359. } /* Channel_NextChannelOf */
  360. GLOBAL CLIENT *
  361. Channel_GetClient( CL2CHAN *Cl2Chan )
  362. {
  363. assert( Cl2Chan != NULL );
  364. return Cl2Chan->client;
  365. } /* Channel_GetClient */
  366. GLOBAL CHANNEL *
  367. Channel_GetChannel( CL2CHAN *Cl2Chan )
  368. {
  369. assert( Cl2Chan != NULL );
  370. return Cl2Chan->channel;
  371. } /* Channel_GetChannel */
  372. GLOBAL bool
  373. Channel_IsValidName( const char *Name )
  374. {
  375. assert( Name != NULL );
  376. if(( Name[0] != '#' ) || ( strlen( Name ) >= CHANNEL_NAME_LEN )) return false;
  377. return Name[strcspn(Name, " ,:\007")] == 0;
  378. } /* Channel_IsValidName */
  379. GLOBAL bool
  380. Channel_ModeAdd( CHANNEL *Chan, char Mode )
  381. {
  382. /* set Mode.
  383. * If the channel already had this mode, return false.
  384. * If the channel mode was newly set return true.
  385. */
  386. char x[2];
  387. assert( Chan != NULL );
  388. x[0] = Mode; x[1] = '\0';
  389. if( ! strchr( Chan->modes, x[0] ))
  390. {
  391. /* Channel does not have this mode yet, set it */
  392. strlcat( Chan->modes, x, sizeof( Chan->modes ));
  393. return true;
  394. }
  395. else return false;
  396. } /* Channel_ModeAdd */
  397. GLOBAL bool
  398. Channel_ModeDel( CHANNEL *Chan, char Mode )
  399. {
  400. /* Delete mode.
  401. * if the mode was removed return true.
  402. * if the channel did not have the mode, return false.
  403. */
  404. char *p;
  405. assert( Chan != NULL );
  406. p = strchr( Chan->modes, Mode );
  407. if( ! p ) return false;
  408. /* Channel has mode -> delete */
  409. while( *p )
  410. {
  411. *p = *(p + 1);
  412. p++;
  413. }
  414. return true;
  415. } /* Channel_ModeDel */
  416. GLOBAL bool
  417. Channel_UserModeAdd( CHANNEL *Chan, CLIENT *Client, char Mode )
  418. {
  419. /* Set Channel-User-Mode.
  420. * if mode was newly set, return true.
  421. * if the User already had this channel-mode, return false.
  422. */
  423. CL2CHAN *cl2chan;
  424. char x[2];
  425. assert( Chan != NULL );
  426. assert( Client != NULL );
  427. cl2chan = Get_Cl2Chan( Chan, Client );
  428. assert( cl2chan != NULL );
  429. x[0] = Mode; x[1] = '\0';
  430. if( ! strchr( cl2chan->modes, x[0] ))
  431. {
  432. /* mode not set, -> set it */
  433. strlcat( cl2chan->modes, x, sizeof( cl2chan->modes ));
  434. return true;
  435. }
  436. else return false;
  437. } /* Channel_UserModeAdd */
  438. GLOBAL bool
  439. Channel_UserModeDel( CHANNEL *Chan, CLIENT *Client, char Mode )
  440. {
  441. /* Delete Channel-User-Mode.
  442. * If Mode was removed, return true.
  443. * If User did not have the Channel-Mode, return false.
  444. */
  445. CL2CHAN *cl2chan;
  446. char *p;
  447. assert( Chan != NULL );
  448. assert( Client != NULL );
  449. cl2chan = Get_Cl2Chan( Chan, Client );
  450. assert( cl2chan != NULL );
  451. p = strchr( cl2chan->modes, Mode );
  452. if( ! p ) return false;
  453. /* Client has Mode -> delete */
  454. while( *p )
  455. {
  456. *p = *(p + 1);
  457. p++;
  458. }
  459. return true;
  460. } /* Channel_UserModeDel */
  461. GLOBAL char *
  462. Channel_UserModes( CHANNEL *Chan, CLIENT *Client )
  463. {
  464. /* return Users' Channel-Modes */
  465. CL2CHAN *cl2chan;
  466. assert( Chan != NULL );
  467. assert( Client != NULL );
  468. cl2chan = Get_Cl2Chan( Chan, Client );
  469. assert( cl2chan != NULL );
  470. return cl2chan->modes;
  471. } /* Channel_UserModes */
  472. GLOBAL bool
  473. Channel_IsMemberOf( CHANNEL *Chan, CLIENT *Client )
  474. {
  475. /* Test if Client is on Channel Chan */
  476. assert( Chan != NULL );
  477. assert( Client != NULL );
  478. return Get_Cl2Chan(Chan, Client) != NULL;
  479. } /* Channel_IsMemberOf */
  480. GLOBAL char *
  481. Channel_Topic( CHANNEL *Chan )
  482. {
  483. char *ret;
  484. assert( Chan != NULL );
  485. ret = array_start(&Chan->topic);
  486. return ret ? ret : "";
  487. } /* Channel_Topic */
  488. #ifndef STRICT_RFC
  489. GLOBAL unsigned int
  490. Channel_TopicTime(CHANNEL *Chan)
  491. {
  492. assert(Chan != NULL);
  493. return (unsigned int) Chan->topic_time;
  494. } /* Channel_TopicTime */
  495. GLOBAL char *
  496. Channel_TopicWho(CHANNEL *Chan)
  497. {
  498. assert(Chan != NULL);
  499. return Chan->topic_who;
  500. } /* Channel_TopicWho */
  501. #endif
  502. GLOBAL void
  503. Channel_SetTopic(CHANNEL *Chan, CLIENT *Client, char *Topic)
  504. {
  505. size_t len;
  506. assert( Chan != NULL );
  507. assert( Topic != NULL );
  508. len = strlen(Topic);
  509. if (len < array_bytes(&Chan->topic))
  510. array_free(&Chan->topic);
  511. if (len >= COMMAND_LEN || !array_copyb(&Chan->topic, Topic, len+1))
  512. Log(LOG_WARNING, "could not set new Topic \"%s\" on %s: %s",
  513. Topic, Chan->name, strerror(errno));
  514. #ifndef STRICT_RFC
  515. Chan->topic_time = time(NULL);
  516. if (Client != NULL && Client_Type(Client) != CLIENT_SERVER)
  517. strlcpy(Chan->topic_who, Client_ID(Client),
  518. sizeof Chan->topic_who);
  519. else
  520. strlcpy(Chan->topic_who, DEFAULT_TOPIC_ID,
  521. sizeof Chan->topic_who);
  522. #else
  523. (void) Client;
  524. #endif
  525. } /* Channel_SetTopic */
  526. GLOBAL void
  527. Channel_SetModes( CHANNEL *Chan, char *Modes )
  528. {
  529. assert( Chan != NULL );
  530. assert( Modes != NULL );
  531. strlcpy( Chan->modes, Modes, sizeof( Chan->modes ));
  532. } /* Channel_SetModes */
  533. GLOBAL void
  534. Channel_SetKey( CHANNEL *Chan, char *Key )
  535. {
  536. assert( Chan != NULL );
  537. assert( Key != NULL );
  538. strlcpy( Chan->key, Key, sizeof( Chan->key ));
  539. LogDebug("Channel %s: Key is now \"%s\".", Chan->name, Chan->key );
  540. } /* Channel_SetKey */
  541. GLOBAL void
  542. Channel_SetMaxUsers(CHANNEL *Chan, unsigned long Count)
  543. {
  544. assert( Chan != NULL );
  545. Chan->maxusers = Count;
  546. LogDebug("Channel %s: Member limit is now %lu.", Chan->name, Chan->maxusers );
  547. } /* Channel_SetMaxUsers */
  548. static bool
  549. Can_Send_To_Channel(CHANNEL *Chan, CLIENT *From)
  550. {
  551. bool is_member, has_voice, is_op;
  552. is_member = has_voice = is_op = false;
  553. if (Channel_IsMemberOf(Chan, From)) {
  554. is_member = true;
  555. if (strchr(Channel_UserModes(Chan, From), 'v'))
  556. has_voice = true;
  557. if (strchr(Channel_UserModes(Chan, From), 'o'))
  558. is_op = true;
  559. }
  560. /*
  561. * Is the client allowed to write to channel?
  562. *
  563. * If channel mode n set: non-members cannot send to channel.
  564. * If channel mode m set: need voice.
  565. */
  566. if (strchr(Channel_Modes(Chan), 'n') && !is_member)
  567. return false;
  568. if (is_op || has_voice)
  569. return true;
  570. if (strchr(Channel_Modes(Chan), 'm'))
  571. return false;
  572. return !Lists_Check(&Chan->list_bans, From);
  573. }
  574. GLOBAL bool
  575. Channel_Write(CHANNEL *Chan, CLIENT *From, CLIENT *Client, const char *Text)
  576. {
  577. if (!Can_Send_To_Channel(Chan, From))
  578. return IRC_WriteStrClient(From, ERR_CANNOTSENDTOCHAN_MSG, Client_ID(From), Channel_Name(Chan));
  579. if (Client_Conn(From) > NONE)
  580. Conn_UpdateIdle(Client_Conn(From));
  581. return IRC_WriteStrChannelPrefix(Client, Chan, From, true,
  582. "PRIVMSG %s :%s", Channel_Name(Chan), Text);
  583. }
  584. GLOBAL bool
  585. Channel_Notice(CHANNEL *Chan, CLIENT *From, CLIENT *Client, const char *Text)
  586. {
  587. if (!Can_Send_To_Channel(Chan, From))
  588. return true; /* no error, see RFC 2812 */
  589. if (Client_Conn(From) > NONE)
  590. Conn_UpdateIdle(Client_Conn(From));
  591. return IRC_WriteStrChannelPrefix(Client, Chan, From, true,
  592. "NOTICE %s :%s", Channel_Name(Chan), Text);
  593. }
  594. GLOBAL CHANNEL *
  595. Channel_Create( char *Name )
  596. {
  597. /* Create new CHANNEL structure and add it to linked list */
  598. CHANNEL *c;
  599. assert( Name != NULL );
  600. c = (CHANNEL *)malloc( sizeof( CHANNEL ));
  601. if( ! c )
  602. {
  603. Log( LOG_EMERG, "Can't allocate memory! [New_Chan]" );
  604. return NULL;
  605. }
  606. memset( c, 0, sizeof( CHANNEL ));
  607. strlcpy( c->name, Name, sizeof( c->name ));
  608. c->hash = Hash( c->name );
  609. c->next = My_Channels;
  610. My_Channels = c;
  611. LogDebug("Created new channel structure for \"%s\".", Name);
  612. return c;
  613. } /* Channel_Create */
  614. static CL2CHAN *
  615. Get_Cl2Chan( CHANNEL *Chan, CLIENT *Client )
  616. {
  617. CL2CHAN *cl2chan;
  618. assert( Chan != NULL );
  619. assert( Client != NULL );
  620. cl2chan = My_Cl2Chan;
  621. while( cl2chan )
  622. {
  623. if(( cl2chan->channel == Chan ) && ( cl2chan->client == Client )) return cl2chan;
  624. cl2chan = cl2chan->next;
  625. }
  626. return NULL;
  627. } /* Get_Cl2Chan */
  628. static CL2CHAN *
  629. Add_Client( CHANNEL *Chan, CLIENT *Client )
  630. {
  631. CL2CHAN *cl2chan;
  632. assert( Chan != NULL );
  633. assert( Client != NULL );
  634. /* neue CL2CHAN-Struktur anlegen */
  635. cl2chan = (CL2CHAN *)malloc( sizeof( CL2CHAN ));
  636. if( ! cl2chan )
  637. {
  638. Log( LOG_EMERG, "Can't allocate memory! [Add_Client]" );
  639. return NULL;
  640. }
  641. cl2chan->channel = Chan;
  642. cl2chan->client = Client;
  643. strcpy( cl2chan->modes, "" );
  644. /* Verketten */
  645. cl2chan->next = My_Cl2Chan;
  646. My_Cl2Chan = cl2chan;
  647. Log( LOG_DEBUG, "User \"%s\" joined channel \"%s\".", Client_Mask( Client ), Chan->name );
  648. return cl2chan;
  649. } /* Add_Client */
  650. static bool
  651. Remove_Client( int Type, CHANNEL *Chan, CLIENT *Client, CLIENT *Origin, const char *Reason, bool InformServer )
  652. {
  653. CL2CHAN *cl2chan, *last_cl2chan;
  654. CHANNEL *c;
  655. assert( Chan != NULL );
  656. assert( Client != NULL );
  657. assert( Origin != NULL );
  658. assert( Reason != NULL );
  659. last_cl2chan = NULL;
  660. cl2chan = My_Cl2Chan;
  661. while( cl2chan )
  662. {
  663. if(( cl2chan->channel == Chan ) && ( cl2chan->client == Client )) break;
  664. last_cl2chan = cl2chan;
  665. cl2chan = cl2chan->next;
  666. }
  667. if( ! cl2chan ) return false;
  668. c = cl2chan->channel;
  669. assert( c != NULL );
  670. /* Aus Verkettung loesen und freigeben */
  671. if( last_cl2chan ) last_cl2chan->next = cl2chan->next;
  672. else My_Cl2Chan = cl2chan->next;
  673. free( cl2chan );
  674. switch( Type )
  675. {
  676. case REMOVE_QUIT:
  677. /* QUIT: other servers have already been notified, see Client_Destroy();
  678. * so only inform other clients in same channel. */
  679. assert( InformServer == false );
  680. LogDebug("User \"%s\" left channel \"%s\" (%s).",
  681. Client_Mask( Client ), c->name, Reason );
  682. break;
  683. case REMOVE_KICK:
  684. /* User was KICKed: inform other servers and all users in channel */
  685. if( InformServer )
  686. IRC_WriteStrServersPrefix( Client_NextHop( Origin ),
  687. Origin, "KICK %s %s :%s", c->name, Client_ID( Client ), Reason);
  688. IRC_WriteStrChannelPrefix(Client, c, Origin, false, "KICK %s %s :%s",
  689. c->name, Client_ID( Client ), Reason );
  690. if ((Client_Conn(Client) > NONE) &&
  691. (Client_Type(Client) == CLIENT_USER))
  692. {
  693. IRC_WriteStrClientPrefix(Client, Origin, "KICK %s %s :%s",
  694. c->name, Client_ID( Client ), Reason);
  695. }
  696. LogDebug("User \"%s\" has been kicked of \"%s\" by \"%s\": %s.",
  697. Client_Mask( Client ), c->name, Client_ID(Origin), Reason);
  698. break;
  699. default: /* PART */
  700. if (InformServer)
  701. IRC_WriteStrServersPrefix(Origin, Client, "PART %s :%s", c->name, Reason);
  702. IRC_WriteStrChannelPrefix(Origin, c, Client, false, "PART %s :%s",
  703. c->name, Reason);
  704. if ((Client_Conn(Origin) > NONE) &&
  705. (Client_Type(Origin) == CLIENT_USER))
  706. {
  707. IRC_WriteStrClientPrefix( Origin, Client, "PART %s :%s", c->name, Reason);
  708. LogDebug("User \"%s\" left channel \"%s\" (%s).",
  709. Client_Mask(Client), c->name, Reason);
  710. }
  711. }
  712. /* Wenn Channel nun leer und nicht pre-defined: loeschen */
  713. if( ! strchr( Channel_Modes( Chan ), 'P' ))
  714. {
  715. if( ! Get_First_Cl2Chan( NULL, Chan )) Delete_Channel( Chan );
  716. }
  717. return true;
  718. } /* Remove_Client */
  719. GLOBAL bool
  720. Channel_AddBan(CHANNEL *c, const char *mask )
  721. {
  722. struct list_head *h = Channel_GetListBans(c);
  723. return Lists_Add(h, mask, false);
  724. }
  725. GLOBAL bool
  726. Channel_AddInvite(CHANNEL *c, const char *mask, bool onlyonce)
  727. {
  728. struct list_head *h = Channel_GetListInvites(c);
  729. return Lists_Add(h, mask, onlyonce);
  730. }
  731. static bool
  732. ShowInvitesBans(struct list_head *head, CLIENT *Client, CHANNEL *Channel, bool invite)
  733. {
  734. struct list_elem *e;
  735. char *msg = invite ? RPL_INVITELIST_MSG : RPL_BANLIST_MSG;
  736. char *msg_end;
  737. assert( Client != NULL );
  738. assert( Channel != NULL );
  739. e = Lists_GetFirst(head);
  740. while (e) {
  741. if( ! IRC_WriteStrClient( Client, msg, Client_ID( Client ),
  742. Channel_Name( Channel ), Lists_GetMask(e) )) return DISCONNECTED;
  743. e = Lists_GetNext(e);
  744. }
  745. msg_end = invite ? RPL_ENDOFINVITELIST_MSG : RPL_ENDOFBANLIST_MSG;
  746. return IRC_WriteStrClient( Client, msg_end, Client_ID( Client ), Channel_Name( Channel ));
  747. }
  748. GLOBAL bool
  749. Channel_ShowBans( CLIENT *Client, CHANNEL *Channel )
  750. {
  751. struct list_head *h;
  752. assert( Channel != NULL );
  753. h = Channel_GetListBans(Channel);
  754. return ShowInvitesBans(h, Client, Channel, false);
  755. }
  756. GLOBAL bool
  757. Channel_ShowInvites( CLIENT *Client, CHANNEL *Channel )
  758. {
  759. struct list_head *h;
  760. assert( Channel != NULL );
  761. h = Channel_GetListInvites(Channel);
  762. return ShowInvitesBans(h, Client, Channel, true);
  763. }
  764. static CL2CHAN *
  765. Get_First_Cl2Chan( CLIENT *Client, CHANNEL *Chan )
  766. {
  767. return Get_Next_Cl2Chan( My_Cl2Chan, Client, Chan );
  768. } /* Get_First_Cl2Chan */
  769. static CL2CHAN *
  770. Get_Next_Cl2Chan( CL2CHAN *Start, CLIENT *Client, CHANNEL *Channel )
  771. {
  772. CL2CHAN *cl2chan;
  773. assert( Client != NULL || Channel != NULL );
  774. cl2chan = Start;
  775. while( cl2chan )
  776. {
  777. if(( Client ) && ( cl2chan->client == Client )) return cl2chan;
  778. if(( Channel ) && ( cl2chan->channel == Channel )) return cl2chan;
  779. cl2chan = cl2chan->next;
  780. }
  781. return NULL;
  782. } /* Get_Next_Cl2Chan */
  783. static bool
  784. Delete_Channel( CHANNEL *Chan )
  785. {
  786. /* Channel-Struktur loeschen */
  787. CHANNEL *chan, *last_chan;
  788. last_chan = NULL;
  789. chan = My_Channels;
  790. while( chan )
  791. {
  792. if( chan == Chan ) break;
  793. last_chan = chan;
  794. chan = chan->next;
  795. }
  796. if( ! chan ) return false;
  797. Log( LOG_DEBUG, "Freed channel structure for \"%s\".", Chan->name );
  798. /* Invite- und Ban-Lists aufraeumen */
  799. Lists_Free( &chan->list_bans );
  800. Lists_Free( &chan->list_invites );
  801. /* Neu verketten und freigeben */
  802. if( last_chan ) last_chan->next = chan->next;
  803. else My_Channels = chan->next;
  804. free( chan );
  805. return true;
  806. } /* Delete_Channel */
  807. /* -eof- */