irc-mode.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728
  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. * IRC commands for mode changes (MODE, AWAY, ...)
  12. */
  13. #include "portab.h"
  14. static char UNUSED id[] = "$Id: irc-mode.c,v 1.43 2005/06/17 19:14:58 fw Exp $";
  15. #include "imp.h"
  16. #include <assert.h>
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include "defines.h"
  21. #include "conn.h"
  22. #include "client.h"
  23. #include "channel.h"
  24. #include "irc-write.h"
  25. #include "lists.h"
  26. #include "log.h"
  27. #include "parse.h"
  28. #include "messages.h"
  29. #include "resolve.h"
  30. #include "conf.h"
  31. #include "exp.h"
  32. #include "irc-mode.h"
  33. LOCAL bool Client_Mode PARAMS(( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target ));
  34. LOCAL bool Channel_Mode PARAMS(( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel ));
  35. LOCAL bool Add_Invite PARAMS(( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern ));
  36. LOCAL bool Add_Ban PARAMS(( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern ));
  37. LOCAL bool Del_Invite PARAMS(( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern ));
  38. LOCAL bool Del_Ban PARAMS(( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern ));
  39. LOCAL bool Send_ListChange PARAMS(( char *Mode, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Mask ));
  40. GLOBAL bool
  41. IRC_MODE( CLIENT *Client, REQUEST *Req )
  42. {
  43. CLIENT *cl, *origin;
  44. CHANNEL *chan;
  45. assert( Client != NULL );
  46. assert( Req != NULL );
  47. /* No parameters? */
  48. if( Req->argc < 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
  49. /* Origin for answers */
  50. if( Client_Type( Client ) == CLIENT_SERVER )
  51. {
  52. origin = Client_Search( Req->prefix );
  53. if( ! origin ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
  54. }
  55. else origin = Client;
  56. /* Channel or user mode? */
  57. cl = chan = NULL;
  58. if( Client_IsValidNick( Req->argv[0] )) cl = Client_Search( Req->argv[0] );
  59. if( Channel_IsValidName( Req->argv[0] )) chan = Channel_Search( Req->argv[0] );
  60. if( cl ) return Client_Mode( Client, Req, origin, cl );
  61. if( chan ) return Channel_Mode( Client, Req, origin, chan );
  62. /* No target found! */
  63. return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[0] );
  64. } /* IRC_MODE */
  65. LOCAL bool
  66. Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target )
  67. {
  68. /* Handle client mode requests */
  69. char the_modes[COMMAND_LEN], x[2], *mode_ptr;
  70. bool ok, set;
  71. int mode_arg;
  72. size_t len;
  73. /* Is the client allowed to request or change the modes? */
  74. if( Client_Type( Client ) == CLIENT_USER )
  75. {
  76. /* Users are only allowed to manipulate their own modes! */
  77. if( Target != Client ) return IRC_WriteStrClient( Client, ERR_USERSDONTMATCH_MSG, Client_ID( Client ));
  78. }
  79. /* Mode request: let's answer it :-) */
  80. if( Req->argc == 1 ) return IRC_WriteStrClient( Origin, RPL_UMODEIS_MSG, Client_ID( Origin ), Client_Modes( Target ));
  81. mode_arg = 1;
  82. mode_ptr = Req->argv[mode_arg];
  83. /* Initial state: set or unset modes? */
  84. if( *mode_ptr == '+' ) set = true;
  85. else if( *mode_ptr == '-' ) set = false;
  86. else return IRC_WriteStrClient( Origin, ERR_UMODEUNKNOWNFLAG_MSG, Client_ID( Origin ));
  87. /* Prepare reply string */
  88. if( set ) strcpy( the_modes, "+" );
  89. else strcpy( the_modes, "-" );
  90. x[1] = '\0';
  91. ok = CONNECTED;
  92. while( mode_ptr )
  93. {
  94. mode_ptr++;
  95. if( ! *mode_ptr )
  96. {
  97. /* Try next argument if there's any */
  98. mode_arg++;
  99. if( mode_arg < Req->argc ) mode_ptr = Req->argv[mode_arg];
  100. else break;
  101. }
  102. switch( *mode_ptr )
  103. {
  104. case '+':
  105. case '-':
  106. if((( *mode_ptr == '+' ) && ( ! set )) || (( *mode_ptr == '-' ) && ( set )))
  107. {
  108. /* Action modifier ("+"/"-") must be changed ... */
  109. len = strlen( the_modes ) - 1;
  110. if(( the_modes[len] == '+' ) || ( the_modes[len] == '-' ))
  111. {
  112. /* Adjust last action modifier in result */
  113. the_modes[len] = *mode_ptr;
  114. }
  115. else
  116. {
  117. /* Append modifier character to result string */
  118. x[0] = *mode_ptr;
  119. strlcat( the_modes, x, sizeof( the_modes ));
  120. }
  121. if( *mode_ptr == '+' ) set = true;
  122. else set = false;
  123. }
  124. continue;
  125. }
  126. /* Validate modes */
  127. x[0] = '\0';
  128. switch( *mode_ptr )
  129. {
  130. case 'i': /* Invisible */
  131. case 's': /* Server messages */
  132. x[0] = *mode_ptr;
  133. break;
  134. case 'a': /* Away */
  135. if( Client_Type( Client ) == CLIENT_SERVER )
  136. {
  137. x[0] = 'a';
  138. Client_SetAway( Origin, DEFAULT_AWAY_MSG );
  139. }
  140. else ok = IRC_WriteStrClient( Origin, ERR_NOPRIVILEGES_MSG, Client_ID( Origin ));
  141. break;
  142. case 'o': /* IRC operator (only unsettable!) */
  143. if(( ! set ) || ( Client_Type( Client ) == CLIENT_SERVER ))
  144. {
  145. Client_SetOperByMe( Target, false );
  146. x[0] = 'o';
  147. }
  148. else ok = IRC_WriteStrClient( Origin, ERR_NOPRIVILEGES_MSG, Client_ID( Origin ));
  149. break;
  150. case 'r': /* Restricted (only settable) */
  151. if(( set ) || ( Client_Type( Client ) == CLIENT_SERVER )) x[0] = 'r';
  152. else ok = IRC_WriteStrClient( Origin, ERR_RESTRICTED_MSG, Client_ID( Origin ));
  153. break;
  154. default:
  155. Log( LOG_DEBUG, "Unknown mode \"%c%c\" from \"%s\"!?", set ? '+' : '-', *mode_ptr, Client_ID( Origin ));
  156. if( Client_Type( Client ) != CLIENT_SERVER ) ok = IRC_WriteStrClient( Origin, ERR_UMODEUNKNOWNFLAG2_MSG, Client_ID( Origin ), set ? '+' : '-', *mode_ptr );
  157. x[0] = '\0';
  158. goto client_exit;
  159. }
  160. if( ! ok ) break;
  161. /* Is there a valid mode change? */
  162. if( ! x[0] ) continue;
  163. if( set )
  164. {
  165. /* Set mode */
  166. if( Client_ModeAdd( Target, x[0] )) strlcat( the_modes, x, sizeof( the_modes ));
  167. }
  168. else
  169. {
  170. /* Unset mode */
  171. if( Client_ModeDel( Target, x[0] )) strlcat( the_modes, x, sizeof( the_modes ));
  172. }
  173. }
  174. client_exit:
  175. /* Are there changed modes? */
  176. if( the_modes[1] )
  177. {
  178. /* Remoce needless action modifier characters */
  179. len = strlen( the_modes ) - 1;
  180. if(( the_modes[len] == '+' ) || ( the_modes[len] == '-' )) the_modes[len] = '\0';
  181. if( Client_Type( Client ) == CLIENT_SERVER )
  182. {
  183. /* Forward modes to other servers */
  184. IRC_WriteStrServersPrefix( Client, Origin, "MODE %s :%s", Client_ID( Target ), the_modes );
  185. }
  186. else
  187. {
  188. /* Send reply to client and inform other servers */
  189. ok = IRC_WriteStrClientPrefix( Client, Origin, "MODE %s :%s", Client_ID( Target ), the_modes );
  190. IRC_WriteStrServersPrefix( Client, Origin, "MODE %s :%s", Client_ID( Target ), the_modes );
  191. }
  192. Log( LOG_DEBUG, "User \"%s\": Mode change, now \"%s\".", Client_Mask( Target ), Client_Modes( Target ));
  193. }
  194. IRC_SetPenalty( Client, 1 );
  195. return ok;
  196. } /* Client_Mode */
  197. LOCAL bool
  198. Channel_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel )
  199. {
  200. /* Handle channel and channel-user modes */
  201. char the_modes[COMMAND_LEN], the_args[COMMAND_LEN], x[2], argadd[CLIENT_PASS_LEN], *mode_ptr;
  202. bool ok, set, modeok = false, skiponce, use_servermode = false;
  203. int mode_arg, arg_arg;
  204. CLIENT *client;
  205. long l;
  206. size_t len;
  207. /* Mode request: let's answer it :-) */
  208. if( Req->argc == 1 )
  209. {
  210. /* Member or not? -- That's the question! */
  211. if( ! Channel_IsMemberOf( Channel, Origin )) return IRC_WriteStrClient( Origin, RPL_CHANNELMODEIS_MSG, Client_ID( Origin ), Channel_Name( Channel ), Channel_Modes( Channel ));
  212. /* The sender is a member: generate extended reply */
  213. strlcpy( the_modes, Channel_Modes( Channel ), sizeof( the_modes ));
  214. mode_ptr = the_modes;
  215. the_args[0] = '\0';
  216. while( *mode_ptr )
  217. {
  218. switch( *mode_ptr )
  219. {
  220. case 'l':
  221. snprintf( argadd, sizeof( argadd ), " %ld", Channel_MaxUsers( Channel ));
  222. strlcat( the_args, argadd, sizeof( the_args ));
  223. break;
  224. case 'k':
  225. strlcat( the_args, " ", sizeof( the_args ));
  226. strlcat( the_args, Channel_Key( Channel ), sizeof( the_args ));
  227. break;
  228. }
  229. mode_ptr++;
  230. }
  231. if( the_args[0] ) strlcat( the_modes, the_args, sizeof( the_modes ));
  232. return IRC_WriteStrClient( Origin, RPL_CHANNELMODEIS_MSG, Client_ID( Origin ), Channel_Name( Channel ), the_modes );
  233. }
  234. /* Is the user allowed to change modes? */
  235. if( Client_Type( Client ) == CLIENT_USER )
  236. {
  237. /* Is the originating user on that channel? */
  238. if( ! Channel_IsMemberOf( Channel, Origin )) return IRC_WriteStrClient( Origin, ERR_NOTONCHANNEL_MSG, Client_ID( Origin ), Channel_Name( Channel ));
  239. /* Is he channel operator? */
  240. if( strchr( Channel_UserModes( Channel, Origin ), 'o' )) modeok = true;
  241. else if( Conf_OperCanMode )
  242. {
  243. /* IRC-Operators can use MODE as well */
  244. if( Client_OperByMe( Origin )) {
  245. modeok = true;
  246. if ( Conf_OperServerMode ) use_servermode = true; /* Change Origin to Server */
  247. }
  248. }
  249. }
  250. else modeok = true;
  251. mode_arg = 1;
  252. mode_ptr = Req->argv[mode_arg];
  253. if( Req->argc > mode_arg + 1 ) arg_arg = mode_arg + 1;
  254. else arg_arg = -1;
  255. /* Initial state: set or unset modes? */
  256. skiponce = false;
  257. if( *mode_ptr == '-' ) set = false;
  258. else if( *mode_ptr == '+' ) set = true;
  259. else set = skiponce = true;
  260. /* Prepare reply string */
  261. if( set ) strcpy( the_modes, "+" );
  262. else strcpy( the_modes, "-" );
  263. strcpy( the_args, " " );
  264. x[1] = '\0';
  265. ok = CONNECTED;
  266. while( mode_ptr )
  267. {
  268. if( ! skiponce ) mode_ptr++;
  269. if( ! *mode_ptr )
  270. {
  271. /* Try next argument if there's any */
  272. if( arg_arg > mode_arg ) mode_arg = arg_arg;
  273. else mode_arg++;
  274. if( mode_arg < Req->argc ) mode_ptr = Req->argv[mode_arg];
  275. else break;
  276. if( Req->argc > mode_arg + 1 ) arg_arg = mode_arg + 1;
  277. else arg_arg = -1;
  278. }
  279. skiponce = false;
  280. switch( *mode_ptr )
  281. {
  282. case '+':
  283. case '-':
  284. if((( *mode_ptr == '+' ) && ( ! set )) || (( *mode_ptr == '-' ) && ( set )))
  285. {
  286. /* Action modifier ("+"/"-") must be changed ... */
  287. len = strlen( the_modes ) - 1;
  288. if(( the_modes[len] == '+' ) || ( the_modes[len] == '-' ))
  289. {
  290. /* Adjust last action modifier in result */
  291. the_modes[len] = *mode_ptr;
  292. }
  293. else
  294. {
  295. /* Append modifier character to result string */
  296. x[0] = *mode_ptr;
  297. strlcat( the_modes, x, sizeof( the_modes ));
  298. }
  299. if( *mode_ptr == '+' ) set = true;
  300. else set = false;
  301. }
  302. continue;
  303. }
  304. /* Are there arguments left? */
  305. if( arg_arg >= Req->argc ) arg_arg = -1;
  306. /* Validate modes */
  307. x[0] = '\0';
  308. argadd[0] = '\0';
  309. client = NULL;
  310. switch( *mode_ptr )
  311. {
  312. /* --- Channel modes --- */
  313. case 'i': /* Invite only */
  314. case 'm': /* Moderated */
  315. case 'n': /* Only members can write */
  316. case 's': /* Secret channel */
  317. case 't': /* Topic locked */
  318. if( modeok ) x[0] = *mode_ptr;
  319. else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel ));
  320. break;
  321. case 'k': /* Channel key */
  322. if( ! set )
  323. {
  324. if( modeok ) x[0] = *mode_ptr;
  325. else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel ));
  326. break;
  327. }
  328. if( arg_arg > mode_arg )
  329. {
  330. if( modeok )
  331. {
  332. Channel_ModeDel( Channel, 'k' );
  333. Channel_SetKey( Channel, Req->argv[arg_arg] );
  334. strlcpy( argadd, Channel_Key( Channel ), sizeof( argadd ));
  335. x[0] = *mode_ptr;
  336. }
  337. else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel ));
  338. Req->argv[arg_arg][0] = '\0';
  339. arg_arg++;
  340. }
  341. else ok = IRC_WriteStrClient( Origin, ERR_NEEDMOREPARAMS_MSG, Client_ID( Origin ), Req->command );
  342. break;
  343. case 'l': /* Member limit */
  344. if( ! set )
  345. {
  346. if( modeok ) x[0] = *mode_ptr;
  347. else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel ));
  348. break;
  349. }
  350. if( arg_arg > mode_arg )
  351. {
  352. if( modeok )
  353. {
  354. l = atol( Req->argv[arg_arg] );
  355. if( l > 0 && l < 0xFFFF )
  356. {
  357. Channel_ModeDel( Channel, 'l' );
  358. Channel_SetMaxUsers( Channel, l );
  359. snprintf( argadd, sizeof( argadd ), "%ld", l );
  360. x[0] = *mode_ptr;
  361. }
  362. }
  363. else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel ));
  364. Req->argv[arg_arg][0] = '\0';
  365. arg_arg++;
  366. }
  367. else ok = IRC_WriteStrClient( Origin, ERR_NEEDMOREPARAMS_MSG, Client_ID( Origin ), Req->command );
  368. break;
  369. case 'P': /* Persistent channel */
  370. if( modeok )
  371. {
  372. if( set && ( ! Client_OperByMe( Client )))
  373. {
  374. /* Only IRC operators are allowed to set P mode */
  375. ok = IRC_WriteStrClient( Origin, ERR_NOPRIVILEGES_MSG, Client_ID( Origin ));
  376. }
  377. else x[0] = 'P';
  378. }
  379. else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel ));
  380. break;
  381. /* --- Channel user modes --- */
  382. case 'o': /* Channel operator */
  383. case 'v': /* Voice */
  384. if( arg_arg > mode_arg )
  385. {
  386. if( modeok )
  387. {
  388. client = Client_Search( Req->argv[arg_arg] );
  389. if( client ) x[0] = *mode_ptr;
  390. else ok = IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[arg_arg] );
  391. }
  392. else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel ));
  393. Req->argv[arg_arg][0] = '\0';
  394. arg_arg++;
  395. }
  396. else ok = IRC_WriteStrClient( Origin, ERR_NEEDMOREPARAMS_MSG, Client_ID( Origin ), Req->command );
  397. break;
  398. /* --- Channel lists --- */
  399. case 'I': /* Invite lists */
  400. if( arg_arg > mode_arg )
  401. {
  402. /* modify list */
  403. if( modeok )
  404. {
  405. if( set ) Add_Invite( Origin, Client, Channel, Req->argv[arg_arg] );
  406. else Del_Invite( Origin, Client, Channel, Req->argv[arg_arg] );
  407. }
  408. else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel ));
  409. Req->argv[arg_arg][0] = '\0';
  410. arg_arg++;
  411. }
  412. else Lists_ShowInvites( Origin, Channel );
  413. break;
  414. case 'b': /* Ban lists */
  415. if( arg_arg > mode_arg )
  416. {
  417. /* modify list */
  418. if( modeok )
  419. {
  420. if( set ) Add_Ban( Origin, Client, Channel, Req->argv[arg_arg] );
  421. else Del_Ban( Origin, Client, Channel, Req->argv[arg_arg] );
  422. }
  423. else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel ));
  424. Req->argv[arg_arg][0] = '\0';
  425. arg_arg++;
  426. }
  427. else Lists_ShowBans( Origin, Channel );
  428. break;
  429. default:
  430. Log( LOG_DEBUG, "Unknown mode \"%c%c\" from \"%s\" on %s!?", set ? '+' : '-', *mode_ptr, Client_ID( Origin ), Channel_Name( Channel ));
  431. if( Client_Type( Client ) != CLIENT_SERVER ) ok = IRC_WriteStrClient( Origin, ERR_UMODEUNKNOWNFLAG2_MSG, Client_ID( Origin ), set ? '+' : '-', *mode_ptr );
  432. x[0] = '\0';
  433. goto chan_exit;
  434. }
  435. if( ! ok ) break;
  436. /* Is there a valid mode change? */
  437. if( ! x[0] ) continue;
  438. /* Validate target client */
  439. if( client && ( ! Channel_IsMemberOf( Channel, client )))
  440. {
  441. if( ! IRC_WriteStrClient( Origin, ERR_USERNOTINCHANNEL_MSG, Client_ID( Origin ), Client_ID( client ), Channel_Name( Channel ))) break;
  442. continue;
  443. }
  444. if( set )
  445. {
  446. /* Set mode */
  447. if( client )
  448. {
  449. /* Channel-User-Mode */
  450. if( Channel_UserModeAdd( Channel, client, x[0] ))
  451. {
  452. strlcat( the_args, Client_ID( client ), sizeof( the_args ));
  453. strlcat( the_args, " ", sizeof( the_args ));
  454. strlcat( the_modes, x, sizeof( the_modes ));
  455. Log( LOG_DEBUG, "User \"%s\": Mode change on %s, now \"%s\"", Client_Mask( client ), Channel_Name( Channel ), Channel_UserModes( Channel, client ));
  456. }
  457. }
  458. else
  459. {
  460. /* Channel-Mode */
  461. if( Channel_ModeAdd( Channel, x[0] ))
  462. {
  463. strlcat( the_modes, x, sizeof( the_modes ));
  464. Log( LOG_DEBUG, "Channel %s: Mode change, now \"%s\".", Channel_Name( Channel ), Channel_Modes( Channel ));
  465. }
  466. }
  467. }
  468. else
  469. {
  470. /* Unset mode */
  471. if( client )
  472. {
  473. /* Channel-User-Mode */
  474. if( Channel_UserModeDel( Channel, client, x[0] ))
  475. {
  476. strlcat( the_args, Client_ID( client ), sizeof( the_args ));
  477. strlcat( the_args, " ", sizeof( the_args ));
  478. strlcat( the_modes, x, sizeof( the_modes ));
  479. Log( LOG_DEBUG, "User \"%s\": Mode change on %s, now \"%s\"", Client_Mask( client ), Channel_Name( Channel ), Channel_UserModes( Channel, client ));
  480. }
  481. }
  482. else
  483. {
  484. /* Channel-Mode */
  485. if( Channel_ModeDel( Channel, x[0] ))
  486. {
  487. strlcat( the_modes, x, sizeof( the_modes ));
  488. Log( LOG_DEBUG, "Channel %s: Mode change, now \"%s\".", Channel_Name( Channel ), Channel_Modes( Channel ));
  489. }
  490. }
  491. }
  492. /* Are there additional arguments to add? */
  493. if( argadd[0] )
  494. {
  495. len = strlen( the_args ) - 1;
  496. if( the_args[len] != ' ' ) strlcat( the_args, " ", sizeof( the_args ));
  497. strlcat( the_args, argadd, sizeof( the_args ));
  498. }
  499. }
  500. chan_exit:
  501. /* Are there changed modes? */
  502. if( the_modes[1] )
  503. {
  504. /* Clean up mode string */
  505. len = strlen( the_modes ) - 1;
  506. if(( the_modes[len] == '+' ) || ( the_modes[len] == '-' )) the_modes[len] = '\0';
  507. /* Clean up argument string if there are none */
  508. if( ! the_args[1] ) the_args[0] = '\0';
  509. if( Client_Type( Client ) == CLIENT_SERVER )
  510. {
  511. /* Forward mode changes to channel users and other servers */
  512. IRC_WriteStrServersPrefix( Client, Origin, "MODE %s %s%s", Channel_Name( Channel ), the_modes, the_args );
  513. IRC_WriteStrChannelPrefix( Client, Channel, Origin, false, "MODE %s %s%s", Channel_Name( Channel ), the_modes, the_args );
  514. }
  515. else
  516. {
  517. if ( use_servermode ) Origin = Client_ThisServer();
  518. /* Send reply to client and inform other servers and channel users */
  519. ok = IRC_WriteStrClientPrefix( Client, Origin, "MODE %s %s%s", Channel_Name( Channel ), the_modes, the_args );
  520. IRC_WriteStrServersPrefix( Client, Origin, "MODE %s %s%s", Channel_Name( Channel ), the_modes, the_args );
  521. IRC_WriteStrChannelPrefix( Client, Channel, Origin, false, "MODE %s %s%s", Channel_Name( Channel ), the_modes, the_args );
  522. }
  523. }
  524. IRC_SetPenalty( Client, 1 );
  525. return CONNECTED;
  526. } /* Channel_Mode */
  527. GLOBAL bool
  528. IRC_AWAY( CLIENT *Client, REQUEST *Req )
  529. {
  530. assert( Client != NULL );
  531. assert( Req != NULL );
  532. /* Falsche Anzahl Parameter? */
  533. if( Req->argc > 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
  534. if(( Req->argc == 1 ) && (Req->argv[0][0] ))
  535. {
  536. /* AWAY setzen */
  537. Client_SetAway( Client, Req->argv[0] );
  538. Client_ModeAdd( Client, 'a' );
  539. IRC_WriteStrServersPrefix( Client, Client, "MODE %s :+a", Client_ID( Client ));
  540. return IRC_WriteStrClient( Client, RPL_NOWAWAY_MSG, Client_ID( Client ));
  541. }
  542. else
  543. {
  544. /* AWAY loeschen */
  545. Client_ModeDel( Client, 'a' );
  546. IRC_WriteStrServersPrefix( Client, Client, "MODE %s :-a", Client_ID( Client ));
  547. return IRC_WriteStrClient( Client, RPL_UNAWAY_MSG, Client_ID( Client ));
  548. }
  549. } /* IRC_AWAY */
  550. LOCAL bool
  551. Add_Invite( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern )
  552. {
  553. char *mask;
  554. bool already;
  555. assert( Client != NULL );
  556. assert( Channel != NULL );
  557. assert( Pattern != NULL );
  558. mask = Lists_MakeMask( Pattern );
  559. already = Lists_IsInviteEntry( mask, Channel );
  560. if( ! Lists_AddInvited( mask, Channel, false )) return CONNECTED;
  561. if(( Client_Type( Prefix ) == CLIENT_SERVER ) && ( already == true)) return CONNECTED;
  562. return Send_ListChange( "+I", Prefix, Client, Channel, mask );
  563. } /* Add_Invite */
  564. LOCAL bool
  565. Add_Ban( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern )
  566. {
  567. char *mask;
  568. bool already;
  569. assert( Client != NULL );
  570. assert( Channel != NULL );
  571. assert( Pattern != NULL );
  572. mask = Lists_MakeMask( Pattern );
  573. already = Lists_IsBanEntry( mask, Channel );
  574. if( ! Lists_AddBanned( mask, Channel )) return CONNECTED;
  575. if(( Client_Type( Prefix ) == CLIENT_SERVER ) && ( already == true)) return CONNECTED;
  576. return Send_ListChange( "+b", Prefix, Client, Channel, mask );
  577. } /* Add_Ban */
  578. LOCAL bool
  579. Del_Invite( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern )
  580. {
  581. char *mask;
  582. assert( Client != NULL );
  583. assert( Channel != NULL );
  584. assert( Pattern != NULL );
  585. mask = Lists_MakeMask( Pattern );
  586. Lists_DelInvited( mask, Channel );
  587. return Send_ListChange( "-I", Prefix, Client, Channel, mask );
  588. } /* Del_Invite */
  589. LOCAL bool
  590. Del_Ban( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern )
  591. {
  592. char *mask;
  593. assert( Client != NULL );
  594. assert( Channel != NULL );
  595. assert( Pattern != NULL );
  596. mask = Lists_MakeMask( Pattern );
  597. Lists_DelBanned( mask, Channel );
  598. return Send_ListChange( "-b", Prefix, Client, Channel, mask );
  599. } /* Del_Ban */
  600. LOCAL bool
  601. Send_ListChange( char *Mode, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Mask )
  602. {
  603. /* Bestaetigung an Client schicken & andere Server sowie Channel-User informieren */
  604. bool ok;
  605. if( Client_Type( Client ) == CLIENT_USER )
  606. {
  607. /* Bestaetigung an Client */
  608. ok = IRC_WriteStrClientPrefix( Client, Prefix, "MODE %s %s %s", Channel_Name( Channel ), Mode, Mask );
  609. }
  610. else ok = true;
  611. /* an andere Server */
  612. IRC_WriteStrServersPrefix( Client, Prefix, "MODE %s %s %s", Channel_Name( Channel ), Mode, Mask );
  613. /* und lokale User im Channel */
  614. IRC_WriteStrChannelPrefix( Client, Channel, Prefix, false, "MODE %s %s %s", Channel_Name( Channel ), Mode, Mask );
  615. return ok;
  616. } /* Send_ListChange */
  617. /* -eof- */