keep in sync with OGN upstream (SVN-320)
[ircu2.10.12-pk.git] / ircd / m_svspart.c
diff --git a/ircd/m_svspart.c b/ircd/m_svspart.c
new file mode 100644 (file)
index 0000000..cb50456
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * IRC - Internet Relay Chat, ircd/m_svspart.c
+ * Written by Pierre Schweitzer.
+ */
+
+#include "config.h"
+
+#include "channel.h"
+#include "client.h"
+#include "handlers.h"
+#include "hash.h"
+#include "ircd.h"
+#include "ircd_chattr.h"
+#include "ircd_features.h"
+#include "ircd_reply.h"
+#include "ircd_string.h"
+#include "msg.h"
+#include "numeric.h"
+#include "numnicks.h"
+#include "s_debug.h"
+#include "s_user.h"
+#include "send.h"
+
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+/** SVSPART
+ * SVSPART is forwarded to the server where the user is connected to.
+ * This allows to send SVSPARTs from all servers in the network but additionally causes
+ * some overhead. Though, SVSPART is not often called and this overhead can be ignored.
+ */
+/* ms_svspart - server message handler
+ *
+ * parv[0] = sender prefix
+ * parv[1] = numeric of client
+ * parv[2] = channel, NO CHANLIST!
+ * parv[3] = comment (optional)
+ */
+signed int ms_svspart(struct Client* cptr, struct Client* sptr, signed int parc, char* parv[]) {
+    struct Client *acptr;
+    struct Channel *chptr;
+    struct JoinBuf part;
+    struct Membership *member;
+    unsigned int flags = 0;
+    int use_comment;
+
+    if(parc < 3) {
+        return protocol_violation(cptr, "Too few arguments for SVSPART");
+    }
+
+    /* Ignore if the user has already quitted. */
+    if(!(acptr = findNUser(parv[1]))) {
+        return 0;
+    }
+
+    /* Check channelname. */
+    if(!IsChannelName(parv[2]) || !strIsIrcCh(parv[2])) {
+        return 0;
+    }
+
+    /* Get the channel */
+    chptr = get_channel(acptr, parv[2], CGT_NO_CREATE);
+
+    /* Ensure the user is in channel */
+    if (!(member = find_member_link(chptr, acptr))) return 0;
+
+    /* Forward the message to the server where the user is connected to. */
+    if(!MyConnect(acptr)) {
+        if (parc > 3)
+            sendcmdto_one(sptr, CMD_SVSPART, acptr, "%s %s :%s", parv[1], chptr->chname, parv[3]);
+        else
+            sendcmdto_one(sptr, CMD_SVSPART, acptr, "%s %s", parv[1], chptr->chname);
+        return 0;
+    }
+
+    /* Check if we can put part message */
+    use_comment = (parc > 3 && !EmptyString(parv[3]) &&
+                   member_can_send_to_channel(member, 0));
+
+    /* Use join buf to make him leave - use comment if provided */
+    joinbuf_init(&part, acptr, acptr, JOINBUF_TYPE_PART,
+                     use_comment ? parv[3] : 0, 0);
+
+    if (!member_can_send_to_channel(member, 0))
+      flags |= CHFL_BANNED;
+
+    if (IsDelayedJoin(member))
+      flags |= CHFL_DELAYED;
+
+    /* Make the user leave */
+    joinbuf_join(&part, chptr, flags);
+
+    joinbuf_flush(&part);
+
+    return 0;
+}
+  
\ No newline at end of file