00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 static struct chanset_t *get_channel(int idx, char *chname)
00027 {
00028 struct chanset_t *chan;
00029
00030 if (chname && chname[0]) {
00031 chan = findchan_by_dname(chname);
00032 if (chan)
00033 return chan;
00034 else
00035 dprintf(idx, "No such channel.\n");
00036 } else {
00037 chname = dcc[idx].u.chat->con_chan;
00038 chan = findchan_by_dname(chname);
00039 if (chan)
00040 return chan;
00041 else
00042 dprintf(idx, "Invalid console channel.\n");
00043 }
00044 return 0;
00045 }
00046
00047
00048
00049 static int has_op(int idx, struct chanset_t *chan)
00050 {
00051 get_user_flagrec(dcc[idx].user, &user, chan->dname);
00052 if (chan_op(user) || (glob_op(user) && !chan_deop(user)))
00053 return 1;
00054 dprintf(idx, "You are not a channel op on %s.\n", chan->dname);
00055 return 0;
00056 }
00057
00058 static int has_oporhalfop(int idx, struct chanset_t *chan)
00059 {
00060 get_user_flagrec(dcc[idx].user, &user, chan->dname);
00061 if (chan_op(user) || chan_halfop(user) || (glob_op(user) &&
00062 !chan_deop(user)) || (glob_halfop(user) && !chan_dehalfop(user)))
00063 return 1;
00064 dprintf(idx, "You are not a channel op or halfop on %s.\n", chan->dname);
00065 return 0;
00066 }
00067
00068
00069
00070
00071 static char *getnick(char *handle, struct chanset_t *chan)
00072 {
00073 char s[UHOSTLEN];
00074 struct userrec *u;
00075 register memberlist *m;
00076
00077 for (m = chan->channel.member; m && m->nick[0]; m = m->next) {
00078 egg_snprintf(s, sizeof s, "%s!%s", m->nick, m->userhost);
00079 if ((u = get_user_by_host(s)) && !egg_strcasecmp(u->handle, handle))
00080 return m->nick;
00081 }
00082 return NULL;
00083 }
00084
00085 static void cmd_act(struct userrec *u, int idx, char *par)
00086 {
00087 char *chname;
00088 struct chanset_t *chan;
00089 memberlist *m;
00090
00091 if (!par[0]) {
00092 dprintf(idx, "Usage: act [channel] <action>\n");
00093 return;
00094 }
00095 if (strchr(CHANMETA, par[0]) != NULL)
00096 chname = newsplit(&par);
00097 else
00098 chname = 0;
00099 chan = get_channel(idx, chname);
00100 if (!chan || !has_op(idx, chan))
00101 return;
00102 m = ismember(chan, botname);
00103 if (!m) {
00104 dprintf(idx, "Cannot say to %s: I'm not on that channel.\n", chan->dname);
00105 return;
00106 }
00107 if ((chan->channel.mode & CHANMODER) && !me_op(chan) && !me_halfop(chan) &&
00108 !me_voice(chan)) {
00109 dprintf(idx, "Cannot say to %s: It is moderated.\n", chan->dname);
00110 return;
00111 }
00112 putlog(LOG_CMDS, "*", "#%s# (%s) act %s", dcc[idx].nick, chan->dname, par);
00113 dprintf(DP_HELP, "PRIVMSG %s :\001ACTION %s\001\n", chan->name, par);
00114 dprintf(idx, "Action to %s: %s\n", chan->dname, par);
00115 }
00116
00117 static void cmd_msg(struct userrec *u, int idx, char *par)
00118 {
00119 char *nick;
00120
00121 nick = newsplit(&par);
00122 if (!par[0])
00123 dprintf(idx, "Usage: msg <nick> <message>\n");
00124 else {
00125 putlog(LOG_CMDS, "*", "#%s# msg %s %s", dcc[idx].nick, nick, par);
00126 dprintf(DP_HELP, "PRIVMSG %s :%s\n", nick, par);
00127 dprintf(idx, "Msg to %s: %s\n", nick, par);
00128 }
00129 }
00130
00131 static void cmd_say(struct userrec *u, int idx, char *par)
00132 {
00133 char *chname;
00134 struct chanset_t *chan;
00135 memberlist *m;
00136
00137 if (!par[0]) {
00138 dprintf(idx, "Usage: say [channel] <message>\n");
00139 return;
00140 }
00141 if (strchr(CHANMETA, par[0]) != NULL)
00142 chname = newsplit(&par);
00143 else
00144 chname = 0;
00145 chan = get_channel(idx, chname);
00146 if (!chan || !has_op(idx, chan))
00147 return;
00148 m = ismember(chan, botname);
00149 if (!m) {
00150 dprintf(idx, "Cannot say to %s: I'm not on that channel.\n", chan->dname);
00151 return;
00152 }
00153 if ((chan->channel.mode & CHANMODER) && !me_op(chan) && !me_halfop(chan) &&
00154 !me_voice(chan)) {
00155 dprintf(idx, "Cannot say to %s: It is moderated.\n", chan->dname);
00156 return;
00157 }
00158 putlog(LOG_CMDS, "*", "#%s# (%s) say %s", dcc[idx].nick, chan->dname, par);
00159 dprintf(DP_HELP, "PRIVMSG %s :%s\n", chan->name, par);
00160 dprintf(idx, "Said to %s: %s\n", chan->dname, par);
00161 }
00162
00163 static void cmd_kickban(struct userrec *u, int idx, char *par)
00164 {
00165 struct chanset_t *chan;
00166 char *chname, *nick, *s1;
00167 memberlist *m;
00168 char s[UHOSTLEN];
00169 char bantype = 0;
00170
00171 if (!par[0]) {
00172 dprintf(idx, "Usage: kickban [channel] [-|@]<nick> [reason]\n");
00173 return;
00174 }
00175
00176 if (strchr(CHANMETA, par[0]) != NULL)
00177 chname = newsplit(&par);
00178 else
00179 chname = 0;
00180 chan = get_channel(idx, chname);
00181 if (!chan || !has_oporhalfop(idx, chan))
00182 return;
00183 if (!channel_active(chan)) {
00184 dprintf(idx, "I'm not on %s right now!\n", chan->dname);
00185 return;
00186 }
00187 if (HALFOP_CANTDOMODE('b')) {
00188 dprintf(idx, "I can't help you now because I'm not a channel op or halfop "
00189 "on %s, or halfops cannot set bans.\n", chan->dname);
00190 return;
00191 }
00192 putlog(LOG_CMDS, "*", "#%s# (%s) kickban %s", dcc[idx].nick,
00193 chan->dname, par);
00194 nick = newsplit(&par);
00195 if ((nick[0] == '@') || (nick[0] == '-')) {
00196 bantype = nick[0];
00197 nick++;
00198 }
00199 if (match_my_nick(nick)) {
00200 dprintf(idx, "I'm not going to kickban myself.\n");
00201 return;
00202 }
00203 m = ismember(chan, nick);
00204 if (!m) {
00205 dprintf(idx, "%s is not on %s\n", nick, chan->dname);
00206 return;
00207 }
00208 if (!me_op(chan) && chan_hasop(m)) {
00209 dprintf(idx, "I can't help you now because halfops cannot kick ops.\n");
00210 return;
00211 }
00212 egg_snprintf(s, sizeof s, "%s!%s", m->nick, m->userhost);
00213 u = get_user_by_host(s);
00214 get_user_flagrec(u, &victim, chan->dname);
00215 if ((chan_op(victim) || (glob_op(victim) && !chan_deop(victim))) &&
00216 !(chan_master(user) || glob_master(user))) {
00217 dprintf(idx, "%s is a legal op.\n", nick);
00218 return;
00219 }
00220 if ((chan_master(victim) || glob_master(victim)) &&
00221 !(glob_owner(user) || chan_owner(user))) {
00222 dprintf(idx, "%s is a %s master.\n", nick, chan->dname);
00223 return;
00224 }
00225 if (glob_bot(victim) && !(glob_owner(user) || chan_owner(user))) {
00226 dprintf(idx, "%s is another channel bot!\n", nick);
00227 return;
00228 }
00229 if (use_exempts && (u_match_mask(global_exempts, s) ||
00230 u_match_mask(chan->exempts, s))) {
00231 dprintf(idx, "%s is permanently exempted!\n", nick);
00232 return;
00233 }
00234 if (m->flags & CHANOP)
00235 add_mode(chan, '-', 'o', m->nick);
00236 check_exemptlist(chan, s);
00237 switch (bantype) {
00238 case '@':
00239 s1 = strchr(s, '@');
00240 s1 -= 3;
00241 s1[0] = '*';
00242 s1[1] = '!';
00243 s1[2] = '*';
00244 break;
00245 case '-':
00246 s1 = strchr(s, '!');
00247 s1[1] = '*';
00248 s1--;
00249 s1[0] = '*';
00250 break;
00251 default:
00252 s1 = quickban(chan, m->userhost);
00253 break;
00254 }
00255 if (bantype == '@' || bantype == '-')
00256 do_mask(chan, chan->channel.ban, s1, 'b');
00257 if (!par[0])
00258 par = "requested";
00259 dprintf(DP_SERVER, "KICK %s %s :%s\n", chan->name, m->nick, par);
00260 m->flags |= SENTKICK;
00261 u_addban(chan, s1, dcc[idx].nick, par, now + (60 * chan->ban_time), 0);
00262 dprintf(idx, "Okay, done.\n");
00263 }
00264
00265 static void cmd_op(struct userrec *u, int idx, char *par)
00266 {
00267 struct chanset_t *chan;
00268 char *nick;
00269 memberlist *m;
00270 char s[UHOSTLEN];
00271
00272 nick = newsplit(&par);
00273 chan = get_channel(idx, par);
00274 if (!chan || !has_op(idx, chan))
00275 return;
00276
00277 if (!nick[0] && !(nick = getnick(u->handle, chan))) {
00278 dprintf(idx, "Usage: op <nick> [channel]\n");
00279 return;
00280 }
00281
00282 if (!channel_active(chan)) {
00283 dprintf(idx, "I'm not on %s right now!\n", chan->dname);
00284 return;
00285 }
00286
00287 if (HALFOP_CANTDOMODE('o')) {
00288 dprintf(idx, "I can't help you now because I'm not a chan op or halfop on "
00289 "%s, or halfops cannot set +o modes.\n", chan->dname);
00290 return;
00291 }
00292
00293 putlog(LOG_CMDS, "*", "#%s# (%s) op %s", dcc[idx].nick, chan->dname, nick);
00294 m = ismember(chan, nick);
00295 if (!m) {
00296 dprintf(idx, "%s is not on %s.\n", nick, chan->dname);
00297 return;
00298 }
00299 egg_snprintf(s, sizeof s, "%s!%s", m->nick, m->userhost);
00300 u = get_user_by_host(s);
00301 get_user_flagrec(u, &victim, chan->dname);
00302 if (chan_deop(victim) || (glob_deop(victim) && !glob_op(victim))) {
00303 dprintf(idx, "%s is currently being auto-deopped.\n", m->nick);
00304 return;
00305 }
00306 if (channel_bitch(chan) && !(chan_op(victim) || (glob_op(victim) &&
00307 !chan_deop(victim)))) {
00308 dprintf(idx, "%s is not a registered op.\n", m->nick);
00309 return;
00310 }
00311 add_mode(chan, '+', 'o', nick);
00312 dprintf(idx, "Gave op to %s on %s.\n", nick, chan->dname);
00313 }
00314
00315 static void cmd_deop(struct userrec *u, int idx, char *par)
00316 {
00317 struct chanset_t *chan;
00318 char *nick;
00319 memberlist *m;
00320 char s[UHOSTLEN];
00321
00322 nick = newsplit(&par);
00323 chan = get_channel(idx, par);
00324 if (!chan || !has_op(idx, chan))
00325 return;
00326
00327 if (!nick[0] && !(nick = getnick(u->handle, chan))) {
00328 dprintf(idx, "Usage: deop <nick> [channel]\n");
00329 return;
00330 }
00331
00332 if (!channel_active(chan)) {
00333 dprintf(idx, "I'm not on %s right now!\n", chan->dname);
00334 return;
00335 }
00336
00337 if (HALFOP_CANTDOMODE('o')) {
00338 dprintf(idx, "I can't help you now because I'm not a chan op or halfop on "
00339 "%s, or halfops cannot set -o modes.\n", chan->dname);
00340 return;
00341 }
00342
00343 putlog(LOG_CMDS, "*", "#%s# (%s) deop %s", dcc[idx].nick, chan->dname, nick);
00344 m = ismember(chan, nick);
00345 if (!m) {
00346 dprintf(idx, "%s is not on %s.\n", nick, chan->dname);
00347 return;
00348 }
00349 if (match_my_nick(nick)) {
00350 dprintf(idx, "I'm not going to deop myself.\n");
00351 return;
00352 }
00353 egg_snprintf(s, sizeof s, "%s!%s", m->nick, m->userhost);
00354 u = get_user_by_host(s);
00355 get_user_flagrec(u, &victim, chan->dname);
00356 if ((chan_master(victim) || glob_master(victim)) &&
00357 !(chan_owner(user) || glob_owner(user))) {
00358 dprintf(idx, "%s is a master for %s.\n", m->nick, chan->dname);
00359 return;
00360 }
00361 if ((chan_op(victim) || (glob_op(victim) && !chan_deop(victim))) &&
00362 !(chan_master(user) || glob_master(user))) {
00363 dprintf(idx, "%s has the op flag for %s.\n", m->nick, chan->dname);
00364 return;
00365 }
00366 add_mode(chan, '-', 'o', nick);
00367 dprintf(idx, "Took op from %s on %s.\n", nick, chan->dname);
00368 }
00369
00370 static void cmd_halfop(struct userrec *u, int idx, char *par)
00371 {
00372 struct chanset_t *chan;
00373 struct userrec *u2;
00374 char *nick;
00375 memberlist *m;
00376 char s[UHOSTLEN];
00377
00378 nick = newsplit(&par);
00379 chan = get_channel(idx, par);
00380 if (!chan)
00381 return;
00382
00383 if (!nick[0] && !(nick = getnick(u->handle, chan))) {
00384 dprintf(idx, "Usage: halfop <nick> [channel]\n");
00385 return;
00386 }
00387
00388 get_user_flagrec(dcc[idx].user, &user, chan->dname);
00389 m = ismember(chan, nick);
00390 if (m && !chan_op(user) && (!glob_op(user) || chan_deop(user))) {
00391 egg_snprintf(s, sizeof s, "%s!%s", m->nick, m->userhost);
00392 u2 = m->user ? m->user : get_user_by_host(s);
00393
00394 if (!u2 || strcmp(u2->handle, dcc[idx].nick) || (!chan_halfop(user) &&
00395 (!glob_halfop(user) || chan_dehalfop(user)))) {
00396 dprintf(idx, "You are not a channel op on %s.\n", chan->dname);
00397 return;
00398 }
00399 }
00400
00401 if (!channel_active(chan)) {
00402 dprintf(idx, "I'm not on %s right now!\n", chan->dname);
00403 return;
00404 }
00405
00406 if (HALFOP_CANTDOMODE('h')) {
00407 dprintf(idx, "I can't help you now because I'm not a chan op or halfop on "
00408 "%s, or halfops cannot set +h modes.\n", chan->dname);
00409 return;
00410 }
00411
00412 putlog(LOG_CMDS, "*", "#%s# (%s) halfop %s", dcc[idx].nick,
00413 chan->dname, nick);
00414 m = ismember(chan, nick);
00415 if (!m) {
00416 dprintf(idx, "%s is not on %s.\n", nick, chan->dname);
00417 return;
00418 }
00419 egg_snprintf(s, sizeof s, "%s!%s", m->nick, m->userhost);
00420 u = get_user_by_host(s);
00421 get_user_flagrec(u, &victim, chan->dname);
00422 if (chan_dehalfop(victim) || (glob_dehalfop(victim) && !glob_halfop(victim))) {
00423 dprintf(idx, "%s is currently being auto-dehalfopped.\n", m->nick);
00424 return;
00425 }
00426 if (channel_bitch(chan) && !(chan_op(victim) || chan_op(victim) ||
00427 (glob_op(victim) && !chan_deop(victim)) || (glob_halfop(victim) &&
00428 !chan_dehalfop(victim)))) {
00429 dprintf(idx, "%s is not a registered halfop.\n", m->nick);
00430 return;
00431 }
00432 add_mode(chan, '+', 'h', nick);
00433 dprintf(idx, "Gave halfop to %s on %s.\n", nick, chan->dname);
00434 }
00435
00436 static void cmd_dehalfop(struct userrec *u, int idx, char *par)
00437 {
00438 struct chanset_t *chan;
00439 struct userrec *u2;
00440 char *nick;
00441 memberlist *m;
00442 char s[UHOSTLEN];
00443
00444 nick = newsplit(&par);
00445 chan = get_channel(idx, par);
00446 if (!chan)
00447 return;
00448
00449 if (!nick[0] && !(nick = getnick(u->handle, chan))) {
00450 dprintf(idx, "Usage: dehalfop <nick> [channel]\n");
00451 return;
00452 }
00453
00454 get_user_flagrec(dcc[idx].user, &user, chan->dname);
00455 m = ismember(chan, nick);
00456 if (m && !chan_op(user) && (!glob_op(user) || chan_deop(user))) {
00457 egg_snprintf(s, sizeof s, "%s!%s", m->nick, m->userhost);
00458 u2 = m->user ? m->user : get_user_by_host(s);
00459
00460 if (!u2 || strcmp(u2->handle, dcc[idx].nick) || (!chan_halfop(user) &&
00461 (!glob_halfop(user) || chan_dehalfop(user)))) {
00462 dprintf(idx, "You are not a channel op on %s.\n", chan->dname);
00463 return;
00464 }
00465 }
00466
00467 if (!channel_active(chan)) {
00468 dprintf(idx, "I'm not on %s right now!\n", chan->dname);
00469 return;
00470 }
00471
00472 if (HALFOP_CANTDOMODE('h')) {
00473 dprintf(idx, "I can't help you now because I'm not a chan op or halfop on "
00474 "%s, or halfops cannot set -h modes.\n", chan->dname);
00475 return;
00476 }
00477
00478 putlog(LOG_CMDS, "*", "#%s# (%s) dehalfop %s", dcc[idx].nick,
00479 chan->dname, nick);
00480 m = ismember(chan, nick);
00481 if (!m) {
00482 dprintf(idx, "%s is not on %s.\n", nick, chan->dname);
00483 return;
00484 }
00485 if (match_my_nick(nick)) {
00486 dprintf(idx, "I'm not going to dehalfop myself.\n");
00487 return;
00488 }
00489 egg_snprintf(s, sizeof s, "%s!%s", m->nick, m->userhost);
00490 u = get_user_by_host(s);
00491 get_user_flagrec(u, &victim, chan->dname);
00492 if ((chan_master(victim) || glob_master(victim)) &&
00493 !(chan_owner(user) || glob_owner(user))) {
00494 dprintf(idx, "%s is a master for %s.\n", m->nick, chan->dname);
00495 return;
00496 }
00497 if ((chan_op(victim) || (glob_op(victim) && !chan_deop(victim))) &&
00498 !(chan_master(user) || glob_master(user))) {
00499 dprintf(idx, "%s has the op flag for %s.\n", m->nick, chan->dname);
00500 return;
00501 }
00502 if ((chan_halfop(victim) || (glob_halfop(victim) &&
00503 !chan_dehalfop(victim))) && !(chan_master(user) || glob_master(user))) {
00504 dprintf(idx, "%s has the halfop flag for %s.\n", m->nick, chan->dname);
00505 return;
00506 }
00507 add_mode(chan, '-', 'h', nick);
00508 dprintf(idx, "Took halfop from %s on %s.\n", nick, chan->dname);
00509 }
00510
00511 static void cmd_voice(struct userrec *u, int idx, char *par)
00512 {
00513 struct chanset_t *chan;
00514 struct userrec *u2;
00515 char *nick;
00516 memberlist *m;
00517 char s[UHOSTLEN];
00518
00519 nick = newsplit(&par);
00520 chan = get_channel(idx, par);
00521 if (!chan)
00522 return;
00523
00524 if (!nick[0] && !(nick = getnick(u->handle, chan))) {
00525 dprintf(idx, "Usage: voice <nick> [channel]\n");
00526 return;
00527 }
00528
00529 get_user_flagrec(dcc[idx].user, &user, chan->dname);
00530 m = ismember(chan, nick);
00531
00532
00533
00534
00535
00536 if (m && !(chan_op(user) || chan_halfop(user) || (glob_op(user) &&
00537 !chan_deop(user)) || (glob_halfop(user) && !chan_dehalfop(user)))) {
00538 egg_snprintf(s, sizeof s, "%s!%s", m->nick, m->userhost);
00539 u2 = m->user ? m->user : get_user_by_host(s);
00540
00541 if (!u2 || strcmp(u2->handle, dcc[idx].nick) || (!chan_voice(user) &&
00542 (!glob_voice(user) || chan_quiet(user)))) {
00543 dprintf(idx, "You are not a channel op or halfop on %s.\n", chan->dname);
00544 return;
00545 }
00546 }
00547
00548 if (!channel_active(chan)) {
00549 dprintf(idx, "I'm not on %s right now!\n", chan->dname);
00550 return;
00551 }
00552
00553 if (HALFOP_CANTDOMODE('v')) {
00554 dprintf(idx, "I can't help you now because I'm not a chan op or halfop on "
00555 "%s, or halfops cannot set +v modes.\n", chan->dname);
00556 return;
00557 }
00558
00559 putlog(LOG_CMDS, "*", "#%s# (%s) voice %s", dcc[idx].nick, chan->dname, nick);
00560 m = ismember(chan, nick);
00561 if (!m) {
00562 dprintf(idx, "%s is not on %s.\n", nick, chan->dname);
00563 return;
00564 }
00565 add_mode(chan, '+', 'v', nick);
00566 dprintf(idx, "Gave voice to %s on %s\n", nick, chan->dname);
00567 }
00568
00569 static void cmd_devoice(struct userrec *u, int idx, char *par)
00570 {
00571 struct chanset_t *chan;
00572 struct userrec *u2;
00573 char *nick;
00574 memberlist *m;
00575 char s[UHOSTLEN];
00576
00577 nick = newsplit(&par);
00578 chan = get_channel(idx, par);
00579 if (!chan)
00580 return;
00581
00582 if (!nick[0] && !(nick = getnick(u->handle, chan))) {
00583 dprintf(idx, "Usage: devoice <nick> [channel]\n");
00584 return;
00585 }
00586
00587 get_user_flagrec(dcc[idx].user, &user, chan->dname);
00588 m = ismember(chan, nick);
00589 if (m && !(chan_op(user) || chan_halfop(user) || (glob_op(user) &&
00590 !chan_deop(user)) || (glob_halfop(user) && !chan_dehalfop(user)))) {
00591 egg_snprintf(s, sizeof s, "%s!%s", m->nick, m->userhost);
00592 u2 = m->user ? m->user : get_user_by_host(s);
00593
00594 if (!u2 || strcmp(u2->handle, dcc[idx].nick) || (!chan_voice(user) &&
00595 (!glob_voice(user) || chan_quiet(user)))) {
00596 dprintf(idx, "You are not a channel op or halfop on %s.\n", chan->dname);
00597 return;
00598 }
00599 }
00600
00601 if (!channel_active(chan)) {
00602 dprintf(idx, "I'm not on %s right now!\n", chan->dname);
00603 return;
00604 }
00605
00606 if (HALFOP_CANTDOMODE('v')) {
00607 dprintf(idx, "I can't help you now because I'm not a chan op or halfop on "
00608 "%s, or halfops cannot set -v modes.\n", chan->dname);
00609 return;
00610 }
00611
00612 putlog(LOG_CMDS, "*", "#%s# (%s) devoice %s", dcc[idx].nick,
00613 chan->dname, nick);
00614 m = ismember(chan, nick);
00615 if (!m) {
00616 dprintf(idx, "%s is not on %s.\n", nick, chan->dname);
00617 return;
00618 }
00619 add_mode(chan, '-', 'v', nick);
00620 dprintf(idx, "Devoiced %s on %s\n", nick, chan->dname);
00621 }
00622
00623 static void cmd_kick(struct userrec *u, int idx, char *par)
00624 {
00625 struct chanset_t *chan;
00626 char *chname, *nick;
00627 memberlist *m;
00628 char s[UHOSTLEN];
00629
00630 if (!par[0]) {
00631 dprintf(idx, "Usage: kick [channel] <nick> [reason]\n");
00632 return;
00633 }
00634 if (strchr(CHANMETA, par[0]) != NULL)
00635 chname = newsplit(&par);
00636 else
00637 chname = 0;
00638 chan = get_channel(idx, chname);
00639 if (!chan || !has_oporhalfop(idx, chan))
00640 return;
00641 if (!channel_active(chan)) {
00642 dprintf(idx, "I'm not on %s right now!\n", chan->dname);
00643 return;
00644 }
00645 if (!me_op(chan) && !me_halfop(chan)) {
00646 dprintf(idx, "I can't help you now because I'm not a channel op or halfop "
00647 "on %s.\n", chan->dname);
00648 return;
00649 }
00650 putlog(LOG_CMDS, "*", "#%s# (%s) kick %s", dcc[idx].nick, chan->dname, par);
00651 nick = newsplit(&par);
00652 if (!par[0])
00653 par = "request";
00654 if (match_my_nick(nick)) {
00655 dprintf(idx, "I'm not going to kick myself.\n");
00656 return;
00657 }
00658 m = ismember(chan, nick);
00659 if (!m) {
00660 dprintf(idx, "%s is not on %s\n", nick, chan->dname);
00661 return;
00662 }
00663 if (!me_op(chan) && chan_hasop(m)) {
00664 dprintf(idx, "I can't help you now because halfops cannot kick ops.\n",
00665 chan->dname);
00666 return;
00667 }
00668 egg_snprintf(s, sizeof s, "%s!%s", m->nick, m->userhost);
00669 u = get_user_by_host(s);
00670 get_user_flagrec(u, &victim, chan->dname);
00671 if ((chan_op(victim) || (glob_op(victim) && !chan_deop(victim))) &&
00672 !(chan_master(user) || glob_master(user))) {
00673 dprintf(idx, "%s is a legal op.\n", nick);
00674 return;
00675 }
00676 if ((chan_master(victim) || glob_master(victim)) &&
00677 !(glob_owner(user) || chan_owner(user))) {
00678 dprintf(idx, "%s is a %s master.\n", nick, chan->dname);
00679 return;
00680 }
00681 if (glob_bot(victim) && !(glob_owner(user) || chan_owner(user))) {
00682 dprintf(idx, "%s is another channel bot!\n", nick);
00683 return;
00684 }
00685 dprintf(DP_SERVER, "KICK %s %s :%s\n", chan->name, m->nick, par);
00686 m->flags |= SENTKICK;
00687 dprintf(idx, "Okay, done.\n");
00688 }
00689
00690 static void cmd_invite(struct userrec *u, int idx, char *par)
00691 {
00692 struct chanset_t *chan;
00693 memberlist *m;
00694 char *nick;
00695
00696 if (!par[0])
00697 par = dcc[idx].nick;
00698 nick = newsplit(&par);
00699 chan = get_channel(idx, par);
00700 if (!chan || !has_oporhalfop(idx, chan))
00701 return;
00702
00703 putlog(LOG_CMDS, "*", "#%s# (%s) invite %s", dcc[idx].nick, chan->dname,
00704 nick);
00705 if (!me_op(chan) && !me_halfop(chan)) {
00706 if (chan->channel.mode & CHANINV) {
00707 dprintf(idx, "I can't help you now because I'm not a channel op or "
00708 "halfop on %s.\n", chan->dname);
00709 return;
00710 }
00711 if (!channel_active(chan)) {
00712 dprintf(idx, "I'm not on %s right now!\n", chan->dname);
00713 return;
00714 }
00715 }
00716 m = ismember(chan, nick);
00717 if (m && !chan_issplit(m)) {
00718 dprintf(idx, "%s is already on %s!\n", nick, chan->dname);
00719 return;
00720 }
00721 dprintf(DP_SERVER, "INVITE %s %s\n", nick, chan->name);
00722 dprintf(idx, "Inviting %s to %s.\n", nick, chan->dname);
00723 }
00724
00725 static void cmd_channel(struct userrec *u, int idx, char *par)
00726 {
00727 char handle[HANDLEN + 1], s[UHOSTLEN], s1[UHOSTLEN], atrflag, chanflag;
00728 struct chanset_t *chan;
00729 memberlist *m;
00730 int maxnicklen, maxhandlen;
00731 char format[81];
00732
00733 chan = get_channel(idx, par);
00734 if (!chan || !has_oporhalfop(idx, chan))
00735 return;
00736 putlog(LOG_CMDS, "*", "#%s# (%s) channel", dcc[idx].nick, chan->dname);
00737 strncpyz(s, getchanmode(chan), sizeof s);
00738 if (channel_pending(chan))
00739 egg_snprintf(s1, sizeof s1, "%s %s", IRC_PROCESSINGCHAN, chan->dname);
00740 else if (channel_active(chan))
00741 egg_snprintf(s1, sizeof s1, "%s %s", IRC_CHANNEL, chan->dname);
00742 else
00743 egg_snprintf(s1, sizeof s1, "%s %s", IRC_DESIRINGCHAN, chan->dname);
00744 dprintf(idx, "%s, %d member%s, mode %s:\n", s1, chan->channel.members,
00745 chan->channel.members == 1 ? "" : "s", s);
00746 if (chan->channel.topic)
00747 dprintf(idx, "%s: %s\n", IRC_CHANNELTOPIC, chan->channel.topic);
00748 if (channel_active(chan)) {
00749
00750 maxnicklen = maxhandlen = 0;
00751 for (m = chan->channel.member; m && m->nick[0]; m = m->next) {
00752 if (strlen(m->nick) > maxnicklen)
00753 maxnicklen = strlen(m->nick);
00754 if ((m->user) && (strlen(m->user->handle) > maxhandlen))
00755 maxhandlen = strlen(m->user->handle);
00756 }
00757 if (maxnicklen < 9)
00758 maxnicklen = 9;
00759 if (maxhandlen < 9)
00760 maxhandlen = 9;
00761
00762 dprintf(idx, "(n = owner, m = master, o = op, d = deop, b = bot)\n");
00763 egg_snprintf(format, sizeof format, " %%-%us %%-%us %%-6s %%-5s %%s\n",
00764 maxnicklen, maxhandlen);
00765 dprintf(idx, format, "NICKNAME", "HANDLE", " JOIN", "IDLE", "USER@HOST");
00766 for (m = chan->channel.member; m && m->nick[0]; m = m->next) {
00767 if (m->joined > 0) {
00768 if ((now - (m->joined)) > 86400)
00769 egg_strftime(s, 6, "%d%b", localtime(&(m->joined)));
00770 else
00771 egg_strftime(s, 6, "%H:%M", localtime(&(m->joined)));
00772 } else
00773 strncpyz(s, " --- ", sizeof s);
00774 if (m->user == NULL) {
00775 egg_snprintf(s1, sizeof s1, "%s!%s", m->nick, m->userhost);
00776 m->user = get_user_by_host(s1);
00777 }
00778 if (m->user == NULL)
00779 strncpyz(handle, "*", sizeof handle);
00780 else
00781 strncpyz(handle, m->user->handle, sizeof handle);
00782 get_user_flagrec(m->user, &user, chan->dname);
00783
00784 if (glob_bot(user) && (glob_op(user) || chan_op(user)))
00785 atrflag = 'B';
00786 else if (glob_bot(user))
00787 atrflag = 'b';
00788 else if (glob_owner(user))
00789 atrflag = 'N';
00790 else if (chan_owner(user))
00791 atrflag = 'n';
00792 else if (glob_master(user))
00793 atrflag = 'M';
00794 else if (chan_master(user))
00795 atrflag = 'm';
00796 else if (glob_deop(user))
00797 atrflag = 'D';
00798 else if (chan_deop(user))
00799 atrflag = 'd';
00800 else if (glob_dehalfop(user))
00801 atrflag = 'R';
00802 else if (chan_dehalfop(user))
00803 atrflag = 'r';
00804 else if (glob_autoop(user))
00805 atrflag = 'A';
00806 else if (chan_autohalfop(user))
00807 atrflag = 'y';
00808 else if (glob_autohalfop(user))
00809 atrflag = 'Y';
00810 else if (chan_autoop(user))
00811 atrflag = 'a';
00812 else if (glob_op(user))
00813 atrflag = 'O';
00814 else if (chan_op(user))
00815 atrflag = 'o';
00816 else if (glob_halfop(user))
00817 atrflag = 'L';
00818 else if (chan_halfop(user))
00819 atrflag = 'l';
00820 else if (glob_quiet(user))
00821 atrflag = 'Q';
00822 else if (chan_quiet(user))
00823 atrflag = 'q';
00824 else if (glob_gvoice(user))
00825 atrflag = 'G';
00826 else if (chan_gvoice(user))
00827 atrflag = 'g';
00828 else if (glob_voice(user))
00829 atrflag = 'V';
00830 else if (chan_voice(user))
00831 atrflag = 'v';
00832 else if (glob_friend(user))
00833 atrflag = 'F';
00834 else if (chan_friend(user))
00835 atrflag = 'f';
00836 else if (glob_kick(user))
00837 atrflag = 'K';
00838 else if (chan_kick(user))
00839 atrflag = 'k';
00840 else if (glob_wasoptest(user))
00841 atrflag = 'W';
00842 else if (chan_wasoptest(user))
00843 atrflag = 'w';
00844 else if (glob_exempt(user))
00845 atrflag = 'E';
00846 else if (chan_exempt(user))
00847 atrflag = 'e';
00848 else
00849 atrflag = ' ';
00850 if (chan_hasop(m))
00851 chanflag = '@';
00852 else if (chan_hashalfop(m))
00853 chanflag = '%';
00854 else if (chan_hasvoice(m))
00855 chanflag = '+';
00856 else
00857 chanflag = ' ';
00858 if (chan_issplit(m)) {
00859 egg_snprintf(format, sizeof format,
00860 "%%c%%-%us %%-%us %%s %%c <- netsplit, %%lus\n",
00861 maxnicklen, maxhandlen);
00862 dprintf(idx, format, chanflag, m->nick, handle, s, atrflag,
00863 now - (m->split));
00864 } else if (!rfc_casecmp(m->nick, botname)) {
00865 egg_snprintf(format, sizeof format,
00866 "%%c%%-%us %%-%us %%s %%c <- it's me!\n",
00867 maxnicklen, maxhandlen);
00868 dprintf(idx, format, chanflag, m->nick, handle, s, atrflag);
00869 } else {
00870
00871 if (now - (m->last) > 86400)
00872 egg_snprintf(s1, sizeof s1, "%2lud", ((now - (m->last)) / 86400));
00873 else if (now - (m->last) > 3600)
00874 egg_snprintf(s1, sizeof s1, "%2luh", ((now - (m->last)) / 3600));
00875 else if (now - (m->last) > 180)
00876 egg_snprintf(s1, sizeof s1, "%2lum", ((now - (m->last)) / 60));
00877 else
00878 strncpyz(s1, " ", sizeof s1);
00879 egg_snprintf(format, sizeof format,
00880 "%%c%%-%us %%-%us %%s %%c %%s %%s\n", maxnicklen,
00881 maxhandlen);
00882 dprintf(idx, format, chanflag, m->nick, handle, s, atrflag, s1,
00883 m->userhost);
00884 }
00885 if (chan_fakeop(m))
00886 dprintf(idx, " (%s)\n", IRC_FAKECHANOP);
00887 if (chan_sentop(m))
00888 dprintf(idx, " (%s)\n", IRC_PENDINGOP);
00889 if (chan_sentdeop(m))
00890 dprintf(idx, " (%s)\n", IRC_PENDINGDEOP);
00891 if (chan_sentkick(m))
00892 dprintf(idx, " (%s)\n", IRC_PENDINGKICK);
00893 }
00894 }
00895 dprintf(idx, "%s\n", IRC_ENDCHANINFO);
00896 }
00897
00898 static void cmd_topic(struct userrec *u, int idx, char *par)
00899 {
00900 struct chanset_t *chan;
00901
00902 if (par[0] && (strchr(CHANMETA, par[0]) != NULL)) {
00903 char *chname = newsplit(&par);
00904
00905 chan = get_channel(idx, chname);
00906 } else
00907 chan = get_channel(idx, "");
00908
00909 if (!chan || !has_oporhalfop(idx, chan))
00910 return;
00911
00912 if (!channel_active(chan)) {
00913 dprintf(idx, "I'm not on %s right now!\n", chan->dname);
00914 return;
00915 }
00916 if (!par[0]) {
00917 if (chan->channel.topic)
00918 dprintf(idx, "The topic for %s is: %s\n", chan->dname,
00919 chan->channel.topic);
00920 else
00921 dprintf(idx, "No topic is set for %s\n", chan->dname);
00922 } else if (channel_optopic(chan) && !me_op(chan) && !me_halfop(chan))
00923 dprintf(idx, "I'm not a channel op or halfop on %s and the channel is "
00924 "+t.\n", chan->dname);
00925 else {
00926 dprintf(DP_SERVER, "TOPIC %s :%s\n", chan->name, par);
00927 dprintf(idx, "Changing topic...\n");
00928 putlog(LOG_CMDS, "*", "#%s# (%s) topic %s", dcc[idx].nick,
00929 chan->dname, par);
00930 }
00931 }
00932
00933 static void cmd_resetbans(struct userrec *u, int idx, char *par)
00934 {
00935 struct chanset_t *chan;
00936 char *chname = newsplit(&par);
00937
00938 chan = get_channel(idx, chname);
00939 if (!chan || !has_oporhalfop(idx, chan))
00940 return;
00941
00942 putlog(LOG_CMDS, "*", "#%s# (%s) resetbans", dcc[idx].nick, chan->dname);
00943 dprintf(idx, "Resetting bans on %s...\n", chan->dname);
00944 resetbans(chan);
00945 }
00946
00947 static void cmd_resetexempts(struct userrec *u, int idx, char *par)
00948 {
00949 struct chanset_t *chan;
00950 char *chname = newsplit(&par);
00951
00952 chan = get_channel(idx, chname);
00953 if (!chan || !has_oporhalfop(idx, chan))
00954 return;
00955
00956 putlog(LOG_CMDS, "*", "#%s# (%s) resetexempts", dcc[idx].nick, chan->dname);
00957 dprintf(idx, "Resetting exempts on %s...\n", chan->dname);
00958 resetexempts(chan);
00959 }
00960
00961 static void cmd_resetinvites(struct userrec *u, int idx, char *par)
00962 {
00963 struct chanset_t *chan;
00964 char *chname = newsplit(&par);
00965
00966 chan = get_channel(idx, chname);
00967 if (!chan || !has_oporhalfop(idx, chan))
00968 return;
00969
00970 putlog(LOG_CMDS, "*", "#%s# (%s) resetinvites", dcc[idx].nick, chan->dname);
00971 dprintf(idx, "Resetting resetinvites on %s...\n", chan->dname);
00972 resetinvites(chan);
00973 }
00974
00975 static void cmd_adduser(struct userrec *u, int idx, char *par)
00976 {
00977 char *nick, *hand;
00978 struct chanset_t *chan;
00979 memberlist *m = NULL;
00980 char s[UHOSTLEN], s1[UHOSTLEN];
00981 int atr = u ? u->flags : 0;
00982 int statichost = 0;
00983 char *p1 = s1;
00984
00985 if ((!par[0]) || ((par[0] == '!') && (!par[1]))) {
00986 dprintf(idx, "Usage: adduser <nick> [handle]\n");
00987 return;
00988 }
00989 nick = newsplit(&par);
00990
00991
00992 if (nick[0] == '!') {
00993 statichost = 1;
00994 nick++;
00995 }
00996
00997 if (!par[0]) {
00998 hand = nick;
00999 } else {
01000 char *p;
01001 int ok = 1;
01002
01003 for (p = par; *p; p++)
01004 if ((unsigned char) *p <= 32)
01005 ok = 0;
01006 if (!ok) {
01007 dprintf(idx, "You can't have strange characters in a nick.\n");
01008 return;
01009 } else if (strchr(BADHANDCHARS, par[0]) != NULL) {
01010 dprintf(idx, "You can't start a nick with '%c'.\n", par[0]);
01011 return;
01012 }
01013 hand = par;
01014 }
01015
01016 for (chan = chanset; chan; chan = chan->next) {
01017 m = ismember(chan, nick);
01018 if (m)
01019 break;
01020 }
01021 if (!m) {
01022 dprintf(idx, "%s is not on any channels I monitor\n", nick);
01023 return;
01024 }
01025 if (strlen(hand) > HANDLEN)
01026 hand[HANDLEN] = 0;
01027 egg_snprintf(s, sizeof s, "%s!%s", m->nick, m->userhost);
01028 u = get_user_by_host(s);
01029 if (u) {
01030 dprintf(idx, "%s is already known as %s.\n", nick, u->handle);
01031 return;
01032 }
01033 u = get_user_by_handle(userlist, hand);
01034 if (u && (u->flags & (USER_OWNER | USER_MASTER)) &&
01035 !(atr & USER_OWNER) && egg_strcasecmp(dcc[idx].nick, hand)) {
01036 dprintf(idx, "You can't add hostmasks to the bot owner/master.\n");
01037 return;
01038 }
01039 if (!statichost)
01040 maskhost(s, s1);
01041 else {
01042 strncpyz(s1, s, sizeof s1);
01043 p1 = strchr(s1, '!');
01044 if (strchr("~^+=-", p1[1])) {
01045 if (strict_host)
01046 p1[1] = '?';
01047 else {
01048 p1[1] = '!';
01049 p1++;
01050 }
01051 }
01052 p1--;
01053 p1[0] = '*';
01054 }
01055 if (!u) {
01056 dprintf(idx, "Added [%s]%s with no password.\n", hand, p1);
01057 userlist = adduser(userlist, hand, p1, "-", USER_DEFAULT);
01058 } else {
01059 dprintf(idx, "Added hostmask %s to %s.\n", p1, u->handle);
01060 addhost_by_handle(hand, p1);
01061 get_user_flagrec(u, &user, chan->dname);
01062 check_this_user(hand, 0, NULL);
01063 }
01064 putlog(LOG_CMDS, "*", "#%s# adduser %s %s", dcc[idx].nick, nick,
01065 hand == nick ? "" : hand);
01066 }
01067
01068 static void cmd_deluser(struct userrec *u, int idx, char *par)
01069 {
01070 char *nick, s[UHOSTLEN];
01071 struct chanset_t *chan;
01072 memberlist *m = NULL;
01073 struct flag_record victim = { FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0 };
01074
01075 if (!par[0]) {
01076 dprintf(idx, "Usage: deluser <nick>\n");
01077 return;
01078 }
01079 nick = newsplit(&par);
01080
01081 for (chan = chanset; chan; chan = chan->next) {
01082 m = ismember(chan, nick);
01083 if (m)
01084 break;
01085 }
01086 if (!m) {
01087 dprintf(idx, "%s is not on any channels I monitor\n", nick);
01088 return;
01089 }
01090 get_user_flagrec(u, &user, chan->dname);
01091 egg_snprintf(s, sizeof s, "%s!%s", m->nick, m->userhost);
01092 u = get_user_by_host(s);
01093 if (!u) {
01094 dprintf(idx, "%s is not a valid user.\n", nick);
01095 return;
01096 }
01097 get_user_flagrec(u, &victim, NULL);
01098
01099
01100
01101
01102
01103
01104
01105 if ((glob_owner(victim) && egg_strcasecmp(dcc[idx].nick, nick)) ||
01106 isowner(u->handle)) {
01107 dprintf(idx, "You can't remove a bot owner!\n");
01108 } else if (glob_botmast(victim) && !glob_owner(user)) {
01109 dprintf(idx, "You can't remove a bot master!\n");
01110 } else if (chan_owner(victim) && !glob_owner(user)) {
01111 dprintf(idx, "You can't remove a channel owner!\n");
01112 } else if (chan_master(victim) && !(glob_owner(user) || chan_owner(user))) {
01113 dprintf(idx, "You can't remove a channel master!\n");
01114 } else if (glob_bot(victim) && !glob_owner(user)) {
01115 dprintf(idx, "You can't remove a bot!\n");
01116 } else {
01117 char buf[HANDLEN + 1];
01118
01119 strncpyz(buf, u->handle, sizeof buf);
01120 buf[HANDLEN] = 0;
01121 if (deluser(u->handle)) {
01122 dprintf(idx, "Deleted %s.\n", buf);
01123 putlog(LOG_CMDS, "*", "#%s# deluser %s [%s]", dcc[idx].nick, nick, buf);
01124 } else
01125 dprintf(idx, "Failed.\n");
01126 }
01127 }
01128
01129 static void cmd_reset(struct userrec *u, int idx, char *par)
01130 {
01131 struct chanset_t *chan;
01132
01133 if (par[0]) {
01134 chan = findchan_by_dname(par);
01135 if (!chan)
01136 dprintf(idx, "%s\n", IRC_NOMONITOR);
01137 else {
01138 get_user_flagrec(u, &user, par);
01139 if (!glob_master(user) && !chan_master(user))
01140 dprintf(idx, "You are not a master on %s.\n", chan->dname);
01141 else if (!channel_active(chan))
01142 dprintf(idx, "I'm not on %s at the moment!\n", chan->dname);
01143 else {
01144 putlog(LOG_CMDS, "*", "#%s# reset %s", dcc[idx].nick, par);
01145 dprintf(idx, "Resetting channel info for %s...\n", chan->dname);
01146 reset_chan_info(chan, CHAN_RESETALL);
01147 }
01148 }
01149 } else if (!(u->flags & USER_MASTER))
01150 dprintf(idx, "You are not a Bot Master.\n");
01151 else {
01152 putlog(LOG_CMDS, "*", "#%s# reset all", dcc[idx].nick);
01153 dprintf(idx, "Resetting channel info for all channels...\n");
01154 for (chan = chanset; chan; chan = chan->next) {
01155 if (channel_active(chan))
01156 reset_chan_info(chan, CHAN_RESETALL);
01157 }
01158 }
01159 }
01160
01161 static cmd_t irc_dcc[] = {
01162 {"adduser", "m|m", (IntFunc) cmd_adduser, NULL},
01163 {"deluser", "m|m", (IntFunc) cmd_deluser, NULL},
01164 {"reset", "m|m", (IntFunc) cmd_reset, NULL},
01165 {"resetbans", "o|o", (IntFunc) cmd_resetbans, NULL},
01166 {"resetexempts", "o|o", (IntFunc) cmd_resetexempts, NULL},
01167 {"resetinvites", "o|o", (IntFunc) cmd_resetinvites, NULL},
01168 {"act", "o|o", (IntFunc) cmd_act, NULL},
01169 {"channel", "o|o", (IntFunc) cmd_channel, NULL},
01170 {"op", "o|o", (IntFunc) cmd_op, NULL},
01171 {"deop", "o|o", (IntFunc) cmd_deop, NULL},
01172 {"halfop", "ol|ol", (IntFunc) cmd_halfop, NULL},
01173 {"dehalfop", "ol|ol", (IntFunc) cmd_dehalfop, NULL},
01174 {"voice", "ov|ov", (IntFunc) cmd_voice, NULL},
01175 {"devoice", "ov|ov", (IntFunc) cmd_devoice, NULL},
01176 {"invite", "o|o", (IntFunc) cmd_invite, NULL},
01177 {"kick", "lo|lo", (IntFunc) cmd_kick, NULL},
01178 {"kickban", "lo|lo", (IntFunc) cmd_kickban, NULL},
01179 {"msg", "o", (IntFunc) cmd_msg, NULL},
01180 {"say", "o|o", (IntFunc) cmd_say, NULL},
01181 {"topic", "lo|lo", (IntFunc) cmd_topic, NULL},
01182 {NULL, NULL, NULL, NULL}
01183 };