irc-mode.c 21 KB

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