static int flood_attack_channel(int p_or_n, struct Client *source_p,
struct Channel *chptr, char *chname);
+/* Fifteen seconds should be plenty for a client to reply a ctcp */
+#define LARGE_CTCP_TIME 15
+
#define ENTITY_NONE 0
#define ENTITY_CHANNEL 1
-#define ENTITY_CHANOPS_ON_CHANNEL 2
-#define ENTITY_CLIENT 3
+#define ENTITY_CHANNEL_OPMOD 2
+#define ENTITY_CHANOPS_ON_CHANNEL 3
+#define ENTITY_CLIENT 4
static struct entity targets[512];
static int ntargets = 0;
struct Client *client_p,
struct Client *source_p, struct Channel *chptr, const char *text);
+static void msg_channel_opmod(int p_or_n, const char *command,
+ struct Client *client_p,
+ struct Client *source_p, struct Channel *chptr,
+ const char *text);
+
static void msg_channel_flags(int p_or_n, const char *command,
struct Client *client_p,
struct Client *source_p,
(struct Channel *) targets[i].ptr, parv[2]);
break;
+ case ENTITY_CHANNEL_OPMOD:
+ msg_channel_opmod(p_or_n, command, client_p, source_p,
+ (struct Channel *) targets[i].ptr, parv[2]);
+ break;
+
case ENTITY_CHANOPS_ON_CHANNEL:
msg_channel_flags(p_or_n, command, client_p, source_p,
(struct Channel *) targets[i].ptr,
if(!IsServer(source_p) && !IsService(source_p) && !is_chanop_voiced(msptr))
{
sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
- me.name, source_p->name, with_prefix);
+ get_id(&me, source_p),
+ get_id(source_p, source_p),
+ with_prefix);
return (-1);
}
continue;
}
+ if(IsServer(client_p) && *nick == '=' && nick[1] == '#')
+ {
+ nick++;
+ if((chptr = find_channel(nick)) != NULL)
+ {
+ if(!duplicate_ptr(chptr))
+ {
+ if(ntargets >= ConfigFileEntry.max_targets)
+ {
+ sendto_one(source_p, form_str(ERR_TOOMANYTARGETS),
+ me.name, source_p->name, nick);
+ return (1);
+ }
+ targets[ntargets].ptr = (void *) chptr;
+ targets[ntargets++].type = ENTITY_CHANNEL_OPMOD;
+ }
+ }
+
+ /* non existant channel */
+ else if(p_or_n != NOTICE)
+ sendto_one_numeric(source_p, ERR_NOSUCHNICK,
+ form_str(ERR_NOSUCHNICK), nick);
+
+ continue;
+ }
+
/* no matching anything found - error if not NOTICE */
if(p_or_n != NOTICE)
{
{
sendto_channel_flags(client_p, ALL_MEMBERS, source_p, chptr,
"%s %s :%s", command, chptr->chname, text);
+ if (p_or_n != NOTICE && *text == '\001' &&
+ rb_dlink_list_length(&chptr->locmembers) > (unsigned)(GlobalSetOptions.floodcount / 2))
+ source_p->large_ctcp_sent = rb_current_time();
}
}
else if(chptr->mode.mode & MODE_OPMODERATE &&
- chptr->mode.mode & MODE_MODERATED &&
- IsMember(source_p, chptr))
+ (!(chptr->mode.mode & MODE_NOPRIVMSGS) ||
+ IsMember(source_p, chptr)))
{
- /* only do +z for +m channels for now, as bans/quiets
- * aren't tested for remote clients -- jilles */
if(!flood_attack_channel(p_or_n, source_p, chptr, chptr->chname))
{
- sendto_channel_flags(client_p, ONLY_CHANOPS, source_p, chptr,
- "%s %s :%s", command, chptr->chname, text);
+ sendto_channel_opmod(client_p, source_p, chptr,
+ command, text);
+ }
+ }
+ else
+ {
+ if(p_or_n != NOTICE)
+ sendto_one_numeric(source_p, ERR_CANNOTSENDTOCHAN,
+ form_str(ERR_CANNOTSENDTOCHAN), chptr->chname);
+ }
+}
+/*
+ * msg_channel_opmod
+ *
+ * inputs - flag privmsg or notice
+ * - pointer to command "PRIVMSG" or "NOTICE"
+ * - pointer to client_p
+ * - pointer to source_p
+ * - pointer to channel
+ * output - NONE
+ * side effects - message given channel ops
+ *
+ * XXX - We need to rework this a bit, it's a tad ugly. --nenolod
+ */
+static void
+msg_channel_opmod(int p_or_n, const char *command,
+ struct Client *client_p, struct Client *source_p,
+ struct Channel *chptr, const char *text)
+{
+ char text2[BUFSIZE];
+
+ if(chptr->mode.mode & MODE_NOCOLOR)
+ {
+ rb_strlcpy(text2, text, BUFSIZE);
+ strip_colour(text2);
+ text = text2;
+ if (EmptyString(text))
+ {
+ /* could be empty after colour stripping and
+ * that would cause problems later */
+ if(p_or_n != NOTICE)
+ sendto_one(source_p, form_str(ERR_NOTEXTTOSEND), me.name, source_p->name);
+ return;
+ }
+ }
+
+ if(chptr->mode.mode & MODE_OPMODERATE &&
+ (!(chptr->mode.mode & MODE_NOPRIVMSGS) ||
+ IsMember(source_p, chptr)))
+ {
+ if(!flood_attack_channel(p_or_n, source_p, chptr, chptr->chname))
+ {
+ sendto_channel_opmod(client_p, source_p, chptr,
+ command, text);
}
}
else
return;
}
}
+
+ if (do_floodcount && p_or_n == NOTICE && *text == '\001' &&
+ target_p->large_ctcp_sent + LARGE_CTCP_TIME >= rb_current_time())
+ do_floodcount = 0;
+
+ if (do_floodcount &&
+ flood_attack_client(p_or_n, source_p, target_p))
+ return;
}
else if(source_p->from == target_p->from)
{
sendto_one_numeric(source_p, ERR_NONONREG,
form_str(ERR_NONONREG),
target_p->name);
- /* Only so opers can watch for floods */
- if (do_floodcount)
- (void) flood_attack_client(p_or_n, source_p, target_p);
}
else
{
target_p->localClient->last_caller_id_time = rb_current_time();
}
- /* Only so opers can watch for floods */
- if (do_floodcount)
- (void) flood_attack_client(p_or_n, source_p, target_p);
}
}
else
- {
- /* If the client is remote, we dont perform a special check for
- * flooding.. as we wouldnt block their message anyway.. this means
- * we dont give warnings.. we then check if theyre opered
- * (to avoid flood warnings), lastly if theyre our client
- * and flooding -- fl */
- if(!do_floodcount ||
- !flood_attack_client(p_or_n, source_p, target_p))
- sendto_anywhere(target_p, source_p, command, ":%s", text);
- }
+ sendto_anywhere(target_p, source_p, command, ":%s", text);
}
- else if(!do_floodcount ||
- !flood_attack_client(p_or_n, source_p, target_p))
+ else
sendto_anywhere(target_p, source_p, command, ":%s", text);
return;
nick + 1,
(*nick == '#') ? MATCH_HOST : MATCH_SERVER,
"%s $%s :%s", command, nick, text);
+ if (p_or_n != NOTICE && *text == '\001')
+ source_p->large_ctcp_sent = rb_current_time();
return;
}
}