ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/core/m_mode.c
Revision: 8752
Committed: Tue Jan 1 11:07:01 2019 UTC (5 years, 3 months ago) by michael
Content type: text/x-csrc
File size: 6913 byte(s)
Log Message:
- Update copyright years

File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 *
4 * Copyright (c) 1997-2019 ircd-hybrid development team
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19 * USA
20 */
21
22 /*! \file m_mode.c
23 * \brief Includes required functions for processing the MODE command.
24 * \version $Id$
25 */
26
27 #include "stdinc.h"
28 #include "list.h"
29 #include "channel.h"
30 #include "channel_mode.h"
31 #include "client.h"
32 #include "client_svstag.h"
33 #include "hash.h"
34 #include "irc_string.h"
35 #include "ircd.h"
36 #include "numeric.h"
37 #include "user.h"
38 #include "conf.h"
39 #include "server.h"
40 #include "send.h"
41 #include "parse.h"
42 #include "modules.h"
43 #include "packet.h"
44
45
46 /* set_user_mode()
47 *
48 * added 15/10/91 By Darren Reed.
49 * parv[0] - command
50 * parv[1] - username to change mode for
51 * parv[2] - modes to change
52 */
53 static void
54 set_user_mode(struct Client *source_p, const int parc, char *parv[])
55 {
56 const struct user_modes *tab = NULL;
57 const unsigned int setmodes = source_p->umodes;
58 const struct Client *target_p = NULL;
59 bool badmode = false;
60 int what = MODE_ADD;
61
62 if ((target_p = find_person(source_p, parv[1])) == NULL)
63 {
64 if (MyConnect(source_p))
65 sendto_one_numeric(source_p, &me, ERR_NOSUCHCHANNEL, parv[1]);
66 return;
67 }
68
69 if (source_p != target_p)
70 {
71 sendto_one_numeric(source_p, &me, ERR_USERSDONTMATCH);
72 return;
73 }
74
75 if (parc < 3)
76 {
77 char buf[UMODE_MAX_STR] = "";
78 char *m = buf;
79
80 *m++ = '+';
81 for (tab = umode_tab; tab->c; ++tab)
82 if (HasUMode(source_p, tab->flag))
83 *m++ = tab->c;
84 *m = '\0';
85
86 sendto_one_numeric(source_p, &me, RPL_UMODEIS, buf);
87 return;
88 }
89
90 /* Parse user mode change string */
91 for (const char *m = parv[2]; *m; ++m)
92 {
93 switch (*m)
94 {
95 case '+':
96 what = MODE_ADD;
97 break;
98 case '-':
99 what = MODE_DEL;
100 break;
101 case 'o':
102 if (what == MODE_ADD)
103 {
104 if (!MyConnect(source_p) && !HasUMode(source_p, UMODE_OPER))
105 {
106 ++Count.oper;
107 SetOper(source_p);
108 }
109 }
110 else
111 {
112 if (!HasUMode(source_p, UMODE_OPER))
113 break;
114
115 ClearOper(source_p);
116 --Count.oper;
117
118 if (MyConnect(source_p))
119 {
120 dlink_node *node;
121
122 svstag_detach(&source_p->svstags, RPL_WHOISOPERATOR);
123 conf_detach(source_p, CONF_OPER);
124
125 ClrOFlag(source_p);
126 DelUMode(source_p, ConfigGeneral.oper_only_umodes);
127
128 if ((node = dlinkFindDelete(&oper_list, source_p)))
129 free_dlink_node(node);
130 }
131 }
132
133 break;
134
135 case 'S': /* Only servers may set +S in a burst */
136 case 'W': /* Only servers may set +W in a burst */
137 case 'r': /* Only services may set +r */
138 break;
139
140 default:
141 if ((tab = umode_map[(unsigned char)*m]))
142 {
143 if (MyConnect(source_p) && !HasUMode(source_p, UMODE_OPER) &&
144 (ConfigGeneral.oper_only_umodes & tab->flag))
145 badmode = true;
146 else
147 {
148 if (what == MODE_ADD)
149 AddUMode(source_p, tab->flag);
150 else
151 DelUMode(source_p, tab->flag);
152 }
153 }
154 else if (MyConnect(source_p))
155 badmode = true;
156
157 break;
158 }
159 }
160
161 if (badmode == true)
162 sendto_one_numeric(source_p, &me, ERR_UMODEUNKNOWNFLAG);
163
164 if (MyConnect(source_p) && HasUMode(source_p, UMODE_ADMIN) &&
165 !HasOFlag(source_p, OPER_FLAG_ADMIN))
166 {
167 sendto_one_notice(source_p, &me, ":*** You have no admin flag;");
168 DelUMode(source_p, UMODE_ADMIN);
169 }
170
171 if (!(setmodes & UMODE_INVISIBLE) && HasUMode(source_p, UMODE_INVISIBLE))
172 ++Count.invisi;
173 else if ((setmodes & UMODE_INVISIBLE) && !HasUMode(source_p, UMODE_INVISIBLE))
174 --Count.invisi;
175
176 /*
177 * Compare new modes with old modes and send string which will cause
178 * servers to update correctly.
179 */
180 send_umode_out(source_p, setmodes);
181 }
182
183 /*! \brief MODE command handler
184 *
185 * \param source_p Pointer to allocated Client struct from which the message
186 * originally comes from. This can be a local or remote client.
187 * \param parc Integer holding the number of supplied arguments.
188 * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL
189 * pointers.
190 * \note Valid arguments for this command are:
191 * - parv[0] = command
192 * - parv[1] = channel or nick name
193 * - parv[2] = modes to be added or removed
194 */
195 static int
196 m_mode(struct Client *source_p, int parc, char *parv[])
197 {
198 struct Membership *member = NULL;
199
200 if (EmptyString(parv[1]))
201 {
202 sendto_one_numeric(source_p, &me, ERR_NEEDMOREPARAMS, "MODE");
203 return 0;
204 }
205
206 /* Now, try to find the channel in question */
207 if (!IsChanPrefix(*parv[1]))
208 {
209 /* If here, it has to be a non-channel name */
210 set_user_mode(source_p, parc, parv);
211 return 0;
212 }
213
214 struct Channel *chptr;
215 if ((chptr = hash_find_channel(parv[1])) == NULL)
216 {
217 sendto_one_numeric(source_p, &me, ERR_NOSUCHCHANNEL, parv[1]);
218 return 0;
219 }
220
221 /* Now known the channel exists */
222 if (parc < 3)
223 {
224 char modebuf[MODEBUFLEN] = "";
225 char parabuf[MODEBUFLEN] = "";
226
227 channel_modes(chptr, source_p, modebuf, parabuf);
228 sendto_one_numeric(source_p, &me, RPL_CHANNELMODEIS, chptr->name, modebuf, parabuf);
229 sendto_one_numeric(source_p, &me, RPL_CREATIONTIME, chptr->name, chptr->creationtime);
230 return 0;
231 }
232
233 if (MyClient(source_p))
234 member = find_channel_link(source_p, chptr);
235
236 channel_mode_set(source_p, chptr, member, parc - 2, parv + 2);
237 return 0;
238 }
239
240 static struct Message mode_msgtab =
241 {
242 .cmd = "MODE",
243 .args_min = 2,
244 .args_max = MAXPARA,
245 .handlers[UNREGISTERED_HANDLER] = m_unregistered,
246 .handlers[CLIENT_HANDLER] = m_mode,
247 .handlers[SERVER_HANDLER] = m_mode,
248 .handlers[ENCAP_HANDLER] = m_ignore,
249 .handlers[OPER_HANDLER] = m_mode
250 };
251
252 static void
253 module_init(void)
254 {
255 mod_add_cmd(&mode_msgtab);
256 }
257
258 static void
259 module_exit(void)
260 {
261 mod_del_cmd(&mode_msgtab);
262 }
263
264 struct module module_entry =
265 {
266 .version = "$Revision$",
267 .modinit = module_init,
268 .modexit = module_exit,
269 .is_core = true
270 };

Properties

Name Value
svn:eol-style native
svn:keywords Id Revision