1. uranium
  2. shadowircd

Commits

Jilles Tjoelker  committed 22c77ff

Apply +z to messages blocked by +b and +q as well.
This adds a new server capab EOPMOD which will be used
for an extended topic command also.

  • Participants
  • Parent commits 358f35c
  • Branches trunk

Comments (0)

Files changed (7)

File doc/technical/ts6-protocol.txt

View file
   with that status or higher only.
   capab: CHW
   propagation: all servers with -D users with appropriate status
+- '=' followed by a channel name, to send to chanops only, for cmode +z.
+  capab: CHW and EOPMOD
+  propagation: all servers with -D chanops
 - a user@server message, to send to users on a specific server. The exact
   meaning of the part before the '@' is not prescribed, except that "opers"
   allows IRC operators to send to all IRC operators on the server in an

File help/opers/cmode

View file
      +c     - No color.  All color codes in messages are stripped.
      +g     - Free invite.  Everyone may invite users.  Significantly
               weakens +i control.
-     +z     - Op moderated.  Messages blocked by +m are instead sent to ops.
+     +z     - Op moderated.  Messages blocked by +m, +b and +q are instead
+              sent to ops.
      +L     - Large ban list.  Increase maximum number of +beIq entries.
               Only settable by opers.
      +P     - Permanent.  Channel does not disappear when empty.  Only

File include/s_serv.h

View file
 #define CAP_RSFNC	0x20000 /* rserv FNC */
 #define CAP_SAVE	0x40000 /* supports SAVE (nick collision FNC) */
 #define CAP_EUID	0x80000 /* supports EUID (ext UID + nonencap CHGHOST) */
+#define CAP_EOPMOD	0x100000 /* supports EOPMOD (ext +z + ext topic) */
 
 #define CAP_MASK        (CAP_QS  | CAP_EX   | CAP_CHW  | \
                          CAP_IE  | CAP_KLN  | CAP_SERVICE |\
                          CAP_CLUSTER | CAP_ENCAP | \
                          CAP_ZIP  | CAP_KNOCK  | CAP_UNKLN | \
-			 CAP_RSFNC | CAP_SAVE | CAP_EUID)
+			 CAP_RSFNC | CAP_SAVE | CAP_EUID | CAP_EOPMOD)
 
 #ifdef HAVE_LIBZ
 #define CAP_ZIP_SUPPORTED       CAP_ZIP

File include/send.h

View file
 
 extern void sendto_channel_flags(struct Client *one, int type, struct Client *source_p,
 				 struct Channel *chptr, const char *, ...) AFP(5, 6);
+extern void sendto_channel_opmod(struct Client *one, struct Client *source_p,
+				 struct Channel *chptr, const char *command,
+				 const char *text);
 
 extern void sendto_channel_local(int type, struct Channel *, const char *, ...) AFP(3, 4);
 extern void sendto_channel_local_butone(struct Client *, int type, struct Channel *, const char *, ...) AFP(4, 5);

File modules/core/m_message.c

View file
 
 #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,
 			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)
 		{
 		}
 	}
 	else if(chptr->mode.mode & MODE_OPMODERATE &&
-			chptr->mode.mode & MODE_MODERATED &&
 			(!(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

File src/s_serv.c

View file
 	{ "RSFNC",	CAP_RSFNC },
 	{ "SAVE",	CAP_SAVE },
 	{ "EUID",	CAP_EUID },
+	{ "EOPMOD",	CAP_EOPMOD },
 	{0, 0}
 };
 

File src/send.c

View file
 	rb_linebuf_donebuf(&rb_linebuf_id);
 }
 
+/* sendto_channel_flags()
+ *
+ * inputs	- server not to send to, flags needed, source, channel, va_args
+ * outputs	- message is sent to channel members
+ * side effects -
+ */
+void
+sendto_channel_opmod(struct Client *one, struct Client *source_p,
+		     struct Channel *chptr, const char *command,
+		     const char *text)
+{
+	static char buf[BUFSIZE];
+	va_list args;
+	buf_head_t rb_linebuf_local;
+	buf_head_t rb_linebuf_old;
+	buf_head_t rb_linebuf_new;
+	struct Client *target_p;
+	struct membership *msptr;
+	rb_dlink_node *ptr;
+	rb_dlink_node *next_ptr;
+
+	rb_linebuf_newbuf(&rb_linebuf_local);
+	rb_linebuf_newbuf(&rb_linebuf_old);
+	rb_linebuf_newbuf(&rb_linebuf_new);
+
+	current_serial++;
+
+	if(IsServer(source_p))
+		rb_linebuf_putmsg(&rb_linebuf_local, NULL, NULL,
+			       ":%s %s %s :%s",
+			       source_p->name, command, chptr->chname, text);
+	else
+		rb_linebuf_putmsg(&rb_linebuf_local, NULL, NULL,
+			       ":%s!%s@%s %s %s :%s",
+			       source_p->name, source_p->username, 
+			       source_p->host, command, chptr->chname, text);
+
+	if (chptr->mode.mode & MODE_MODERATED)
+		rb_linebuf_putmsg(&rb_linebuf_old, NULL, NULL,
+			       ":%s %s %s :%s",
+			       use_id(source_p), command, chptr->chname, text);
+	else
+		rb_linebuf_putmsg(&rb_linebuf_old, NULL, NULL,
+			       ":%s NOTICE @%s :<%s:%s> %s",
+			       use_id(source_p->servptr), chptr->chname,
+			       source_p->name, chptr->chname, text);
+	rb_linebuf_putmsg(&rb_linebuf_new, NULL, NULL,
+		       ":%s %s =%s :%s",
+		       use_id(source_p), command, chptr->chname, text);
+
+	RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->members.head)
+	{
+		msptr = ptr->data;
+		target_p = msptr->client_p;
+
+		if(IsIOError(target_p->from) || target_p->from == one)
+			continue;
+
+		if((msptr->flags & CHFL_CHANOP) == 0)
+			continue;
+
+		if(IsDeaf(target_p))
+			continue;
+
+		if(!MyClient(target_p))
+		{
+			/* if we've got a specific type, target must support
+			 * CHW.. --fl
+			 */
+			if(NotCapable(target_p->from, CAP_CHW))
+				continue;
+
+			if(target_p->from->serial != current_serial)
+			{
+				if (IsCapable(target_p->from, CAP_EOPMOD))
+					send_linebuf_remote(target_p, source_p, &rb_linebuf_new);
+				else
+					send_linebuf_remote(target_p, source_p, &rb_linebuf_old);
+				target_p->from->serial = current_serial;
+			}
+		}
+		else
+			_send_linebuf(target_p, &rb_linebuf_local);
+	}
+
+	rb_linebuf_donebuf(&rb_linebuf_local);
+	rb_linebuf_donebuf(&rb_linebuf_old);
+	rb_linebuf_donebuf(&rb_linebuf_new);
+}
 
 /* sendto_channel_local()
  *