irc-mode.c 19 KB

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