source: code/cmd.c@ a6b8c8d

Last change on this file since a6b8c8d was f3c60e6, checked in by Mike Belopuhov <mike@…>, 11 years ago

After some deliberation we have decided that if modtab is enabled
then it should be possible to steal the moderation.

  • Property mode set to 100644
File size: 9.8 KB
RevLine 
[cd7b81d]1/*
[4284008]2 * Copyright (c) 2009, 2010, 2013 Mike Belopuhov
[cd7b81d]3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include <sys/param.h>
18#include <sys/queue.h>
19#include <stdio.h>
20#include <stdlib.h>
21#include <string.h>
22#include <syslog.h>
23#include <unistd.h>
[626f420]24#include <vis.h>
[cd7b81d]25#include <event.h>
26
27#include "icb.h"
28
29extern int creategroups;
30
[9195a6a]31void icb_cmd_help(struct icb_session *, char *);
[bf02a60]32void icb_cmd_beep(struct icb_session *, char *);
[cd7b81d]33void icb_cmd_boot(struct icb_session *, char *);
34void icb_cmd_change(struct icb_session *, char *);
35void icb_cmd_name(struct icb_session *, char *);
[bf02a60]36void icb_cmd_nobeep(struct icb_session *, char *);
[cd7b81d]37void icb_cmd_personal(struct icb_session *, char *);
38void icb_cmd_pass(struct icb_session *, char *);
39void icb_cmd_topic(struct icb_session *, char *);
40void icb_cmd_who(struct icb_session *, char *);
41
42void *
43icb_cmd_lookup(char *cmd)
44{
45 struct {
46 const char *cmd;
47 void (*handler)(struct icb_session *, char *);
48 } cmdtab[] = {
[9195a6a]49 { "?", icb_cmd_help },
[bf02a60]50 { "beep", icb_cmd_beep },
[cd7b81d]51 { "boot", icb_cmd_boot },
52 { "g", icb_cmd_change },
53 { "m", icb_cmd_personal },
54 { "msg", icb_cmd_personal },
55 { "name", icb_cmd_name },
[bf02a60]56 { "nobeep", icb_cmd_nobeep },
[cd7b81d]57 { "pass", icb_cmd_pass },
58 { "topic", icb_cmd_topic },
59 { "w", icb_cmd_who },
60 { NULL, NULL }
61 };
62 int i;
63
64 for (i = 0; cmdtab[i].cmd != NULL; i++)
65 if (strcasecmp(cmdtab[i].cmd, cmd) == 0)
66 return (cmdtab[i].handler);
67 return (NULL);
68}
69
[9195a6a]70void
71icb_cmd_help(struct icb_session *is, char *arg __attribute__((unused)))
72{
73 icb_status(is, STATUS_HELP, "Server supports following commands:");
74 icb_status(is, STATUS_HELP, "beep boot g m name nobeep pass topic");
75}
76
[bf02a60]77void
78icb_cmd_beep(struct icb_session *is, char *arg)
79{
80 struct icb_group *ig = is->group;
81 struct icb_session *s;
[626f420]82 char whom[ICB_MAXNICKLEN];
[bf02a60]83
84 if (strlen(arg) == 0) {
85 icb_error(is, "Invalid user");
86 return;
87 }
88
[b7bc432]89 icb_vis(whom, arg, ICB_MAXNICKLEN, VIS_SP);
[626f420]90
[bf02a60]91 LIST_FOREACH(s, &ig->sess, entry) {
[626f420]92 if (strcmp(s->nick, whom) == 0)
[bf02a60]93 break;
94 }
95 if (s == NULL) {
[626f420]96 icb_status(is, STATUS_NOTIFY, "%s is not signed on", whom);
[bf02a60]97 return;
98 }
99
100 if (ISSETF(s->flags, ICB_SF_NOBEEP | ICB_SF_NOBEEP2)) {
101 icb_error(is, "User has nobeep enabled");
102 if (ISSETF(s->flags, ICB_SF_NOBEEP2))
103 icb_status(s, STATUS_NOBEEP,
104 "%s attempted to beep you", is->nick);
105 return;
106 }
107
108 icb_sendfmt(s, "%c%s", ICB_M_BEEP, is->nick);
109}
110
[cd7b81d]111void
112icb_cmd_boot(struct icb_session *is, char *arg)
113{
114 struct icb_group *ig;
115 struct icb_session *s;
[626f420]116 char whom[ICB_MAXNICKLEN];
[cd7b81d]117
118 /* to boot or not to boot, that is the question */
119 ig = is->group;
[4284008]120 if (!icb_ismod(ig, is)) {
[cd7b81d]121 icb_status(is, STATUS_NOTIFY, "Sorry, booting is a privilege "
122 "you don't possess");
123 return;
124 }
125
[fdbbc45]126 if (strlen(arg) == 0) {
[626f420]127 icb_error(is, "Invalid user");
128 return;
129 }
130
[b7bc432]131 icb_vis(whom, arg, ICB_MAXNICKLEN, VIS_SP);
[626f420]132
[cd7b81d]133 /* who would be a target then? */
134 LIST_FOREACH(s, &ig->sess, entry) {
[626f420]135 if (strcmp(s->nick, whom) == 0)
[cd7b81d]136 break;
137 }
138 if (s == NULL) {
139 icb_status(is, STATUS_NOTIFY, "No such user");
140 return;
141 }
142
143 /* okay, here we go, but first, be polite and notify a user */
144 icb_status(s, STATUS_BOOT, "%s booted you", is->nick);
145 icb_status_group(s->group, s, STATUS_BOOT, "%s was booted", s->nick);
146 icb_drop(s, "booted");
147}
148
149void
150icb_cmd_change(struct icb_session *is, char *arg)
151{
152 struct icb_group *ig;
153 struct icb_session *s;
[626f420]154 char group[ICB_MAXGRPLEN];
[cd7b81d]155 int changing = 0;
156
157 if (strlen(arg) == 0) {
158 icb_error(is, "Invalid group");
159 return;
160 }
161
[b7bc432]162 icb_vis(group, arg, ICB_MAXGRPLEN, VIS_SP);
[626f420]163
[cd7b81d]164 LIST_FOREACH(ig, &groups, entry) {
[626f420]165 if (strcmp(ig->name, group) == 0)
[cd7b81d]166 break;
167 }
168 if (ig == NULL) {
169 if (!creategroups) {
170 icb_error(is, "Invalid group");
171 return;
172 } else {
[626f420]173 if ((ig = icb_addgroup(is, group, NULL)) == NULL) {
[cd7b81d]174 icb_error(is, "Can't create group");
175 return;
176 }
177 icb_log(NULL, LOG_DEBUG, "%s created group %s",
[626f420]178 is->nick, group);
[cd7b81d]179 }
180 }
181
[4d92f03]182 /* see if we're changing to the same group */
[cd7b81d]183 if (is->group && is->group == ig) {
[4d92f03]184 icb_error(is, "You are already in that group");
[cd7b81d]185 return;
186 }
187
188 LIST_FOREACH(s, &ig->sess, entry) {
189 if (strcmp(s->nick, is->nick) == 0) {
190 icb_error(is, "Nick is already in use");
191 return;
192 }
193 }
194
195 if (is->group) {
196 changing = 1;
[4284008]197 if (icb_ismod(is->group, is))
[cd7b81d]198 (void)icb_pass(is->group, is, NULL);
199 LIST_REMOVE(is, entry);
200 icb_status_group(is->group, NULL, STATUS_DEPART,
201 "%s (%s@%s) just left", is->nick, is->client, is->host);
202 }
203
204 is->group = ig;
205 LIST_INSERT_HEAD(&ig->sess, is, entry);
206
207 /* notify group */
208 icb_status_group(ig, is, changing ? STATUS_ARRIVE : STATUS_SIGNON,
209 "%s (%s@%s) entered group", is->nick, is->client, is->host);
210
211 /* acknowledge successful join */
212 icb_status(is, STATUS_STATUS, "You are now in group %s%s", ig->name,
[4284008]213 icb_ismod(ig, is) ? " as moderator" : "");
[cd7b81d]214
215 /* send user a topic name */
216 if (strlen(ig->topic) > 0)
217 icb_status(is, STATUS_TOPIC, "The topic is: %s", ig->topic);
218}
219
220void
221icb_cmd_name(struct icb_session *is, char *arg)
222{
223 struct icb_group *ig = is->group;
224 struct icb_session *s;
[626f420]225 char nick[ICB_MAXNICKLEN];
[cd7b81d]226
227 if (strlen(arg) == 0) {
228 icb_status(is, STATUS_NAME, "Your nickname is %s",
229 is->nick);
230 return;
231 }
232 if (strcasecmp(arg, "admin") == 0) {
233 icb_error(is, "Wuff wuff!");
234 return;
235 }
236 /* sanitize user input */
237 if (strlen(arg) > ICB_MAXNICKLEN)
238 arg[ICB_MAXNICKLEN - 1] = '\0';
[b7bc432]239 icb_vis(nick, arg, ICB_MAXNICKLEN, VIS_SP);
[cd7b81d]240 LIST_FOREACH(s, &ig->sess, entry) {
[626f420]241 if (strcmp(s->nick, nick) == 0) {
[cd7b81d]242 icb_error(is, "Nick is already in use");
243 return;
244 }
245 }
246 icb_status_group(ig, NULL, STATUS_NAME,
[626f420]247 "%s changed nickname to %s", is->nick, nick);
248 strlcpy(is->nick, nick, sizeof is->nick);
[cd7b81d]249}
250
[bf02a60]251void
252icb_cmd_nobeep(struct icb_session *is, char *arg)
253{
254 if (strlen(arg) == 0) {
255 /* fail if we have verbose turned on */
256 if (ISSETF(is->flags, ICB_SF_NOBEEP2)) {
257 icb_error(is, "Can't toggle your nobeep status");
258 return;
259 }
260 /* otherwise toggle the status */
261 if (ISSETF(is->flags, ICB_SF_NOBEEP))
262 CLRF(is->flags, ICB_SF_NOBEEP);
263 else
264 SETF(is->flags, ICB_SF_NOBEEP);
265 icb_status(is, STATUS_NOBEEP, "No-Beep %s",
266 ISSETF(is->flags, ICB_SF_NOBEEP) ? "on" : "off");
267 return;
268 }
269
270 if (strcmp(arg, "on") == 0) {
271 SETF(is->flags, ICB_SF_NOBEEP);
272 CLRF(is->flags, ICB_SF_NOBEEP2); /* can't be on and verbose */
273 icb_status(is, STATUS_NOBEEP, "No-Beep on");
274 } else if (strcmp(arg, "verbose") == 0) {
275 SETF(is->flags, ICB_SF_NOBEEP2);
276 CLRF(is->flags, ICB_SF_NOBEEP); /* can't be on and verbose */
277 icb_status(is, STATUS_NOBEEP, "No-Beep on (verbose)");
278 } else if (strcmp(arg, "off") == 0) {
279 CLRF(is->flags, ICB_SF_NOBEEP | ICB_SF_NOBEEP2);
280 icb_status(is, STATUS_NOBEEP, "No-Beep off");
281 } else
282 icb_error(is, "Invalid nobeep mode");
283}
284
[cd7b81d]285void
286icb_cmd_personal(struct icb_session *is, char *arg)
287{
288 char *p;
289
290 if ((p = strchr(arg, ' ')) == 0) {
291 icb_error(is, "Empty message");
292 return;
293 }
294 *p = '\0';
295 icb_privmsg(is, arg, ++p);
296}
297
298void
[7eb46d4]299icb_cmd_pass(struct icb_session *is, char *arg)
[cd7b81d]300{
[7eb46d4]301 struct icb_group *ig = is->group;
302 struct icb_session *s;
[626f420]303 char whom[ICB_MAXNICKLEN];
[7eb46d4]304
[f3c60e6]305 if (!ig->mod) { /* if there is no mod, try grabbing it */
306 if (icb_modpermit(is, 0) && icb_pass(ig, ig->mod, is) < 0)
[e2fcbc7]307 icb_error(is, "Acquiring group moderation failed.");
308 } else if (icb_ismod(ig, is)) {
[a203cdb]309 if (strlen(arg) == 0) {
310 /* no argument: relinquish moderator */
311 (void)icb_pass(ig, ig->mod, NULL);
312 return;
313 }
[b7bc432]314 icb_vis(whom, arg, ICB_MAXNICKLEN, VIS_SP);
[7eb46d4]315 LIST_FOREACH(s, &ig->sess, entry) {
[626f420]316 if (strcmp(s->nick, whom) == 0)
[7eb46d4]317 break;
318 }
319 if (s == NULL) {
320 icb_status(is, STATUS_NOTIFY, "No such user");
321 return;
322 }
[f3c60e6]323 if (icb_modpermit(s, 0) && icb_pass(ig, ig->mod, s) < 0)
[e2fcbc7]324 icb_error(s, "Acquiring group moderation failed.");
[f3c60e6]325 } else {
326 /*
327 * if group is moderated and we're not the moderator,
328 * but modtab is enabled, then check the permission
329 * and pass moderation if successful.
330 */
331 if (icb_modpermit(is, 1) && icb_pass(ig, ig->mod, is) < 0)
332 icb_error(is, "Acquiring group moderation failed.");
[7eb46d4]333 }
[cd7b81d]334}
335
336void
337icb_cmd_topic(struct icb_session *is, char *arg)
338{
339 struct icb_group *ig = is->group;
[626f420]340 char topic[ICB_MAXTOPICLEN];
[cd7b81d]341
342 if (strlen(arg) == 0) { /* querying the topic */
343 if (strlen(ig->topic) > 0)
344 icb_status(is, STATUS_TOPIC, "The topic is: %s",
345 ig->topic);
346 else
347 icb_status(is, STATUS_TOPIC, "The topic is not set.");
348 } else { /* setting the topic */
[4284008]349 if (!icb_ismod(ig, is)) {
[8886035]350 icb_status(is, STATUS_NOTIFY, "Setting the topic is "
351 "only for moderators.");
352 return;
353 }
[b7bc432]354 icb_vis(topic, arg, ICB_MAXTOPICLEN, 0);
[626f420]355 strlcpy(ig->topic, topic, sizeof ig->topic);
[cd7b81d]356 icb_status_group(ig, NULL, STATUS_TOPIC,
357 "%s changed the topic to \"%s\"", is->nick, ig->topic);
358 }
359}
360
361void
[4284008]362icb_cmd_who(struct icb_session *is, char *arg)
[cd7b81d]363{
[4284008]364 struct icb_group *ig;
[626f420]365 char group[ICB_MAXGRPLEN];
[4284008]366
[b28dd0e]367 while (strlen(arg) && arg[0] == '-') { /* ignore options, for now */
368 /* ircII "set SHOW_CHANNEL_NAMES ON" uses /w -s */
369 while(arg[0] != ' ' && arg[0] != 0)
370 arg++;
371 if(arg[0] == ' ')
372 arg++;
373 }
374
[4284008]375 if (strlen(arg) == 0)
376 return icb_who(is, NULL);
377
[b7bc432]378 icb_vis(group, arg, ICB_MAXGRPLEN, VIS_SP);
[4284008]379 LIST_FOREACH(ig, &groups, entry) {
[626f420]380 if (strcmp(ig->name, group) == 0)
[4284008]381 break;
382 }
383 if (ig == NULL) {
[626f420]384 icb_error(is, "The group %s doesn't exist.", group);
[4284008]385 return;
386 }
387 icb_who(is, ig);
[cd7b81d]388}
Note: See TracBrowser for help on using the repository browser.