+ /* Forward modes to other servers */
+ IRC_WriteStrServersPrefix( Client, Origin, "MODE %s :%s", Client_ID( Target ), the_modes );
+ }
+ else
+ {
+ /* Send reply to client and inform other servers */
+ ok = IRC_WriteStrClientPrefix( Client, Origin, "MODE %s :%s", Client_ID( Target ), the_modes );
+ IRC_WriteStrServersPrefix( Client, Origin, "MODE %s :%s", Client_ID( Target ), the_modes );
+ }
+ LogDebug("%s \"%s\": Mode change, now \"%s\".",
+ Client_TypeText(Target), Client_Mask(Target),
+ Client_Modes(Target));
+ }
+
+ IRC_SetPenalty( Client, 1 );
+ return ok;
+} /* Client_Mode */
+
+
+static bool
+Channel_Mode_Answer_Request(CLIENT *Origin, CHANNEL *Channel)
+{
+ char the_modes[COMMAND_LEN], the_args[COMMAND_LEN], argadd[CLIENT_PASS_LEN];
+ const char *mode_ptr;
+
+ /* Member or not? -- That's the question! */
+ if (!Channel_IsMemberOf(Channel, Origin))
+ return IRC_WriteStrClient(Origin, RPL_CHANNELMODEIS_MSG,
+ Client_ID(Origin), Channel_Name(Channel), Channel_Modes(Channel));
+
+ /* The sender is a member: generate extended reply */
+ strlcpy(the_modes, Channel_Modes(Channel), sizeof(the_modes));
+ mode_ptr = the_modes;
+ the_args[0] = '\0';
+
+ while(*mode_ptr) {
+ switch(*mode_ptr) {
+ case 'l':
+ snprintf(argadd, sizeof(argadd), " %lu", Channel_MaxUsers(Channel));
+ strlcat(the_args, argadd, sizeof(the_args));
+ break;
+ case 'k':
+ strlcat(the_args, " ", sizeof(the_args));
+ strlcat(the_args, Channel_Key(Channel), sizeof(the_args));
+ break;
+ }
+ mode_ptr++;
+ }
+ if (the_args[0])
+ strlcat(the_modes, the_args, sizeof(the_modes));
+
+ return IRC_WriteStrClient(Origin, RPL_CHANNELMODEIS_MSG,
+ Client_ID(Origin), Channel_Name(Channel), the_modes);
+}
+
+
+/**
+ * Handle channel mode and channel-user mode changes
+ */
+static bool
+Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
+{
+ char the_modes[COMMAND_LEN], the_args[COMMAND_LEN], x[2],
+ argadd[CLIENT_PASS_LEN], *mode_ptr;
+ bool connected, set, skiponce, retval, onchannel;
+ bool modeok = true, use_servermode = false;
+ int mode_arg, arg_arg;
+ CLIENT *client;
+ long l;
+ size_t len;
+
+ if (Channel_IsModeless(Channel))
+ return IRC_WriteStrClient(Client, ERR_NOCHANMODES_MSG,
+ Client_ID(Client), Channel_Name(Channel));
+
+ /* Mode request: let's answer it :-) */
+ if (Req->argc <= 1)
+ return Channel_Mode_Answer_Request(Origin, Channel);
+
+ /* Is the user allowed to change modes? */
+ if (Client_Type(Client) == CLIENT_USER) {
+ /* Is the originating user on that channel? */
+ onchannel = Channel_IsMemberOf(Channel, Origin);
+ modeok = false;
+ /* channel operator? */
+ if (onchannel &&
+ strchr(Channel_UserModes(Channel, Origin), 'o')) {
+ modeok = true;
+ } else if (Conf_OperCanMode) {
+ /* IRC-Operators can use MODE as well */
+ if (Client_OperByMe(Origin)) {
+ modeok = true;
+ if (Conf_OperServerMode)
+ use_servermode = true; /* Change Origin to Server */