ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/branches/8.2.x/modules/core/m_mode.c
Revision: 8483
Committed: Wed Apr 4 15:07:19 2018 UTC (5 years, 11 months ago) by michael
Content type: text/x-csrc
File size: 7048 byte(s)
Log Message:
- Move svstag related code into its own files

File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 *
4 * Copyright (c) 1997-2018 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 int what = MODE_ADD, badmode = 0;
60
61 if ((target_p = find_person(source_p, parv[1])) == NULL)
62 {
63 if (MyConnect(source_p))
64 sendto_one_numeric(source_p, &me, ERR_NOSUCHCHANNEL, parv[1]);
65 return;
66 }
67
68 if (source_p != target_p)
69 {
70 sendto_one_numeric(source_p, &me, ERR_USERSDONTMATCH);
71 return;
72 }
73
74 if (parc < 3)
75 {
76 char buf[UMODE_MAX_STR] = "";
77 char *m = buf;
78
79 *m++ = '+';
80 for (tab = umode_tab; tab->c; ++tab)
81 if (HasUMode(source_p, tab->flag))
82 *m++ = tab->c;
83 *m = '\0';
84
85 sendto_one_numeric(source_p, &me, RPL_UMODEIS, buf);
86 return;
87 }
88
89 /* Parse user mode change string */
90 for (const char *m = parv[2]; *m; ++m)
91 {
92 switch (*m)
93 {
94 case '+':
95 what = MODE_ADD;
96 break;
97 case '-':
98 what = MODE_DEL;
99 break;
100 case 'o':
101 if (what == MODE_ADD)
102 {
103 if (!MyConnect(source_p) && !HasUMode(source_p, UMODE_OPER))
104 {
105 ++Count.oper;
106 SetOper(source_p);
107 }
108 }
109 else
110 {
111 if (!HasUMode(source_p, UMODE_OPER))
112 break;
113
114 ClearOper(source_p);
115 --Count.oper;
116
117 if (MyConnect(source_p))
118 {
119 dlink_node *node;
120
121 svstag_detach(&source_p->svstags, RPL_WHOISOPERATOR);
122 conf_detach(source_p, CONF_OPER);
123
124 ClrOFlag(source_p);
125 DelUMode(source_p, ConfigGeneral.oper_only_umodes);
126
127 if ((node = dlinkFindDelete(&oper_list, source_p)))
128 free_dlink_node(node);
129 }
130 }
131
132 break;
133
134 case 'S': /* Only servers may set +S in a burst */
135 case 'W': /* Only servers may set +W in a burst */
136 case 'r': /* Only services may set +r */
137 break;
138
139 default:
140 if ((tab = umode_map[(unsigned char)*m]))
141 {
142 if (MyConnect(source_p) && !HasUMode(source_p, UMODE_OPER) &&
143 (ConfigGeneral.oper_only_umodes & tab->flag))
144 badmode = 1;
145 else
146 {
147 if (what == MODE_ADD)
148 AddUMode(source_p, tab->flag);
149 else
150 DelUMode(source_p, tab->flag);
151 }
152 }
153 else if (MyConnect(source_p))
154 badmode = 1;
155
156 break;
157 }
158 }
159
160 if (badmode)
161 sendto_one_numeric(source_p, &me, ERR_UMODEUNKNOWNFLAG);
162
163 if (MyConnect(source_p) && HasUMode(source_p, UMODE_ADMIN) &&
164 !HasOFlag(source_p, OPER_FLAG_ADMIN))
165 {
166 sendto_one_notice(source_p, &me, ":*** You have no admin flag;");
167 DelUMode(source_p, UMODE_ADMIN);
168 }
169
170 if (!(setmodes & UMODE_INVISIBLE) && HasUMode(source_p, UMODE_INVISIBLE))
171 ++Count.invisi;
172 else if ((setmodes & UMODE_INVISIBLE) && !HasUMode(source_p, UMODE_INVISIBLE))
173 --Count.invisi;
174
175 /*
176 * Compare new modes with old modes and send string which will cause
177 * servers to update correctly.
178 */
179 send_umode_out(source_p, setmodes);
180 }
181
182 /*! \brief MODE command handler
183 *
184 * \param source_p Pointer to allocated Client struct from which the message
185 * originally comes from. This can be a local or remote client.
186 * \param parc Integer holding the number of supplied arguments.
187 * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL
188 * pointers.
189 * \note Valid arguments for this command are:
190 * - parv[0] = command
191 * - parv[1] = channel or nick name
192 * - parv[2] = modes to be added or removed
193 */
194 static int
195 m_mode(struct Client *source_p, int parc, char *parv[])
196 {
197 struct Membership *member = NULL;
198
199 if (EmptyString(parv[1]))
200 {
201 sendto_one_numeric(source_p, &me, ERR_NEEDMOREPARAMS, "MODE");
202 return 0;
203 }
204
205 /* Now, try to find the channel in question */
206 if (!IsChanPrefix(*parv[1]))
207 {
208 /* If here, it has to be a non-channel name */
209 set_user_mode(source_p, parc, parv);
210 return 0;
211 }
212
213 struct Channel *chptr;
214 if ((chptr = hash_find_channel(parv[1])) == NULL)
215 {
216 sendto_one_numeric(source_p, &me, ERR_NOSUCHCHANNEL, parv[1]);
217 return 0;
218 }
219
220 /* Now known the channel exists */
221 if (parc < 3)
222 {
223 char modebuf[MODEBUFLEN] = "";
224 char parabuf[MODEBUFLEN] = "";
225
226 channel_modes(chptr, source_p, modebuf, parabuf);
227 sendto_one_numeric(source_p, &me, RPL_CHANNELMODEIS, chptr->name, modebuf, parabuf);
228 sendto_one_numeric(source_p, &me, RPL_CREATIONTIME, chptr->name, chptr->creationtime);
229 return 0;
230 }
231
232 if (MyClient(source_p))
233 {
234 member = find_channel_link(source_p, chptr);
235
236 if (!IsFloodDone(source_p))
237 if (!((parc == 3) && (parv[2][0] == 'b') && (parv[2][1] == '\0')))
238 flood_endgrace(source_p);
239 }
240
241 channel_mode_set(source_p, chptr, member, parc - 2, parv + 2);
242 return 0;
243 }
244
245 static struct Message mode_msgtab =
246 {
247 .cmd = "MODE",
248 .args_min = 2,
249 .args_max = MAXPARA,
250 .handlers[UNREGISTERED_HANDLER] = m_unregistered,
251 .handlers[CLIENT_HANDLER] = m_mode,
252 .handlers[SERVER_HANDLER] = m_mode,
253 .handlers[ENCAP_HANDLER] = m_ignore,
254 .handlers[OPER_HANDLER] = m_mode
255 };
256
257 static void
258 module_init(void)
259 {
260 mod_add_cmd(&mode_msgtab);
261 }
262
263 static void
264 module_exit(void)
265 {
266 mod_del_cmd(&mode_msgtab);
267 }
268
269 struct module module_entry =
270 {
271 .version = "$Revision$",
272 .modinit = module_init,
273 .modexit = module_exit,
274 .flags = MODULE_FLAG_CORE
275 };

Properties

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