Treat G-line-related times as network times, rather than local times.
[ircu2.10.12-pk.git] / ircd / m_part.c
index d4de9b3a1c5758464d54c76cce69101d015d7ce7..bc34ce93572eb3433536ef5fcecb1a61f9a09ae3 100644 (file)
  *            note:   it is guaranteed that parv[0]..parv[parc-1] are all
  *                    non-NULL pointers.
  */
-#if 0
-/*
- * No need to include handlers.h here the signatures must match
- * and we don't need to force a rebuild of all the handlers everytime
- * we add a new one to the list. --Bleep
- */
-#include "handlers.h"
-#endif /* 0 */
+#include "config.h"
+
 #include "channel.h"
 #include "client.h"
 #include "hash.h"
 #include "ircd.h"
+#include "ircd_log.h"
 #include "ircd_reply.h"
 #include "ircd_string.h"
 #include "numeric.h"
 #include "numnicks.h"
 #include "send.h"
 
-#include <assert.h>
+/* #include <assert.h> -- Now using assert in ircd_log.h */
 #include <string.h>
 
 /*
  */
 int m_part(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
 {
-  struct Channel* chptr;
-  struct Membership* member;
-  char*           p = 0;
-  char*           name;
-  char            pbuf[BUFSIZE];
-  char*           comment = (parc > 2 && !EmptyString(parv[parc - 1])) ? parv[parc - 1] : 0;
-
-  *pbuf = '\0';                 /* Initialize the part buffer... -Kev */
+  struct Channel *chptr;
+  struct Membership *member;
+  struct JoinBuf parts;
+  unsigned int flags = 0;
+  char *p = 0;
+  char *name;
 
-  sptr->flags &= ~FLAGS_TS8;
+  ClrFlag(sptr, FLAG_TS8);
 
+  /* check number of arguments */
   if (parc < 2 || parv[1][0] == '\0')
     return need_more_params(sptr, "PART");
 
-  for (; (name = ircd_strtok(&p, parv[1], ",")); parv[1] = 0)
-  {
-    chptr = get_channel(sptr, name, CGT_NO_CREATE);
-    if (!chptr) {
-      sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL), me.name, parv[0], name);
+  /* init join/part buffer */
+  joinbuf_init(&parts, sptr, cptr, JOINBUF_TYPE_PART,
+              (parc > 2 && !EmptyString(parv[parc - 1])) ? parv[parc - 1] : 0,
+              0);
+
+  /* scan through channel list */
+  for (name = ircd_strtok(&p, parv[1], ","); name;
+       name = ircd_strtok(&p, 0, ",")) {
+
+    chptr = get_channel(sptr, name, CGT_NO_CREATE); /* look up channel */
+
+    if (!chptr) { /* complain if there isn't such a channel */
+      send_reply(sptr, ERR_NOSUCHCHANNEL, name);
       continue;
     }
-    if (*name == '&' && !MyUser(sptr))
-      continue;
-    /*
-     * Do not use find_channel_member here: zombies must be able to part too
-     */
-    if (!(member = find_member_link(chptr, sptr)))
-    {
-      /* Normal to get when our client did a kick
-       * for a remote client (who sends back a PART),
-       * so check for remote client or not --Run
-       */
-      if (MyUser(sptr))
-        sendto_one(sptr, err_str(ERR_NOTONCHANNEL), me.name, parv[0],
-            chptr->chname);
+
+    if (!(member = find_member_link(chptr, sptr))) { /* complain if not on */
+      send_reply(sptr, ERR_NOTONCHANNEL, chptr->chname);
       continue;
     }
-    /* Recreate the /part list for sending to servers */
-    if (*name != '&')
-    {
-      if (*pbuf)
-        strcat(pbuf, ",");
-      strcat(pbuf, name);
-    }
-    if (IsZombie(member)
-        || !member_can_send_to_channel(member))  /* Returns 1 if we CAN send */
-      comment = 0;
-    /* Send part to all clients */
-    if (!IsZombie(member))
-    {
-      if (comment)
-        sendto_channel_butserv(chptr, sptr, PartFmt2, parv[0], chptr->chname,
-                               comment);
-      else
-        sendto_channel_butserv(chptr, sptr, PartFmt1, parv[0], chptr->chname);
-    }
-    else if (MyUser(sptr))
+
+    assert(!IsZombie(member)); /* Local users should never zombie */
+
+    if (!member_can_send_to_channel(member, 0))
     {
-      if (comment)
-        sendto_one(sptr, PartFmt2, parv[0], chptr->chname, comment);
-      else
-        sendto_one(sptr, PartFmt1, parv[0], chptr->chname);
+      flags |= CHFL_BANNED;
+      /* Remote clients don't want to see a comment either. */
+      parts.jb_comment = 0;
     }
-    remove_user_from_channel(sptr, chptr);
-  }
-  /* Send out the parts to all servers... -Kev */
-  if (*pbuf)
-  {
-    if (comment)
-      sendto_serv_butone(cptr, PartFmt2serv, NumNick(sptr), pbuf, comment);
-    else
-      sendto_serv_butone(cptr, PartFmt1serv, NumNick(sptr), pbuf);
+
+    if (IsDelayedJoin(member))
+      flags |= CHFL_DELAYED;
+
+    joinbuf_join(&parts, chptr, flags); /* part client from channel */
   }
-  return 0;
+
+  return joinbuf_flush(&parts); /* flush channel parts */
 }
 
 /*
@@ -194,165 +165,45 @@ int m_part(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
  */
 int ms_part(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
 {
-  struct Channelchptr;
-  struct Membershipmember;
-  char*           p = 0;
-  char*           name;
-  char            pbuf[BUFSIZE];
-  char*           comment = (parc > 2 && !EmptyString(parv[parc - 1])) ? parv[parc - 1] : 0;
+  struct Channel *chptr;
+  struct Membership *member;
+  struct JoinBuf parts;
+  unsigned int flags;
+  char *p = 0;
+  char *name;
 
-  *pbuf = '\0';                 /* Initialize the part buffer... -Kev */
-
-  sptr->flags &= ~FLAGS_TS8;
+  ClrFlag(sptr, FLAG_TS8);
 
+  /* check number of arguments */
   if (parc < 2 || parv[1][0] == '\0')
     return need_more_params(sptr, "PART");
 
-  for (; (name = ircd_strtok(&p, parv[1], ",")); parv[1] = 0)
-  {
-    chptr = get_channel(sptr, name, CGT_NO_CREATE);
-    if (!chptr) {
-      sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL), me.name, parv[0], name);
-      continue;
-    }
-    if (*name == '&' && !MyUser(sptr))
-      continue;
-    /*
-     * Do not use find_channel_member here: zombies must be able to part too
-     */
-    if (!(member = find_member_link(chptr, sptr)))
-    {
-      /* Normal to get when our client did a kick
-       * for a remote client (who sends back a PART),
-       * so check for remote client or not --Run
-       */
-      if (MyUser(sptr))
-        sendto_one(sptr, err_str(ERR_NOTONCHANNEL), me.name, parv[0],
-            chptr->chname);
-      continue;
-    }
-    /* Recreate the /part list for sending to servers */
-    if (*name != '&')
-    {
-      if (*pbuf)
-        strcat(pbuf, ",");
-      strcat(pbuf, name);
-    }
-    if (IsZombie(member)
-        || !member_can_send_to_channel(member))  /* Returns 1 if we CAN send */
-      comment = 0;
-    /* Send part to all clients */
-    if (!IsZombie(member))
-    {
-      if (comment)
-        sendto_channel_butserv(chptr, sptr, PartFmt2, parv[0], chptr->chname,
-                               comment);
-      else
-        sendto_channel_butserv(chptr, sptr, PartFmt1, parv[0], chptr->chname);
-    }
-    else if (MyUser(sptr))
-    {
-      if (comment)
-        sendto_one(sptr, PartFmt2, parv[0], chptr->chname, comment);
-      else
-        sendto_one(sptr, PartFmt1, parv[0], chptr->chname);
-    }
-    remove_user_from_channel(sptr, chptr);
-  }
-  /* Send out the parts to all servers... -Kev */
-  if (*pbuf)
-  {
-    if (comment)
-      sendto_serv_butone(cptr, PartFmt2serv, NumNick(sptr), pbuf, comment);
-    else
-      sendto_serv_butone(cptr, PartFmt1serv, NumNick(sptr), pbuf);
-  }
-  return 0;
-}
+  /* init join/part buffer */
+  joinbuf_init(&parts, sptr, cptr, JOINBUF_TYPE_PART,
+              (parc > 2 && !EmptyString(parv[parc - 1])) ? parv[parc - 1] : 0,
+              0);
 
-#if 0
-/*
- * m_part
- *
- * parv[0] = sender prefix
- * parv[1] = channel
- * parv[parc - 1] = comment
- */
-int m_part(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
-{
-  struct Channel* chptr;
-  struct Membership* member;
-  char*           p = 0;
-  char*           name;
-  char            pbuf[BUFSIZE];
-  char*           comment = (parc > 2 && !EmptyString(parv[parc - 1])) ? parv[parc - 1] : 0;
+  /* scan through channel list */
+  for (name = ircd_strtok(&p, parv[1], ","); name;
+       name = ircd_strtok(&p, 0, ",")) {
 
-  *pbuf = '\0';                 /* Initialize the part buffer... -Kev */
+    flags = 0;
 
-  sptr->flags &= ~FLAGS_TS8;
+    chptr = get_channel(sptr, name, CGT_NO_CREATE); /* look up channel */
 
-  if (parc < 2 || parv[1][0] == '\0')
-    return need_more_params(sptr, "PART");
+    if (!chptr || IsLocalChannel(name) ||
+       !(member = find_member_link(chptr, sptr)))
+      continue; /* ignore from remote clients */
 
-  for (; (name = ircd_strtok(&p, parv[1], ",")); parv[1] = 0)
-  {
-    chptr = get_channel(sptr, name, CGT_NO_CREATE);
-    if (!chptr) {
-      sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL), me.name, parv[0], name);
-      continue;
-    }
-    if (*name == '&' && !MyUser(sptr))
-      continue;
-    /*
-     * Do not use find_channel_member here: zombies must be able to part too
-     */
-    if (!(member = find_member_link(chptr, sptr)))
-    {
-      /* Normal to get when our client did a kick
-       * for a remote client (who sends back a PART),
-       * so check for remote client or not --Run
-       */
-      if (MyUser(sptr))
-        sendto_one(sptr, err_str(ERR_NOTONCHANNEL), me.name, parv[0],
-            chptr->chname);
-      continue;
-    }
-    /* Recreate the /part list for sending to servers */
-    if (*name != '&')
-    {
-      if (*pbuf)
-        strcat(pbuf, ",");
-      strcat(pbuf, name);
-    }
-    if (IsZombie(member)
-        || !member_can_send_to_channel(member))  /* Returns 1 if we CAN send */
-      comment = 0;
-    /* Send part to all clients */
-    if (!IsZombie(member))
-    {
-      if (comment)
-        sendto_channel_butserv(chptr, sptr, PartFmt2, parv[0], chptr->chname,
-                               comment);
-      else
-        sendto_channel_butserv(chptr, sptr, PartFmt1, parv[0], chptr->chname);
-    }
-    else if (MyUser(sptr))
-    {
-      if (comment)
-        sendto_one(sptr, PartFmt2, parv[0], chptr->chname, comment);
-      else
-        sendto_one(sptr, PartFmt1, parv[0], chptr->chname);
-    }
-    remove_user_from_channel(sptr, chptr);
-  }
-  /* Send out the parts to all servers... -Kev */
-  if (*pbuf)
-  {
-    if (comment)
-      sendto_serv_butone(cptr, PartFmt2serv, NumNick(sptr), pbuf, comment);
-    else
-      sendto_serv_butone(cptr, PartFmt1serv, NumNick(sptr), pbuf);
+    if (IsZombie(member)) /* figure out special flags... */
+      flags |= CHFL_ZOMBIE;
+
+    if (IsDelayedJoin(member))
+      flags |= CHFL_DELAYED;
+
+    /* part user from channel */
+    joinbuf_join(&parts, chptr, flags);
   }
-  return 0;
+
+  return joinbuf_flush(&parts); /* flush channel parts */
 }
-#endif /* 0 */