added gnutls backend and moved backend code into new files
[ircu2.10.12-pk.git] / ircd / m_invite.c
index 47beba3cd217fc68ab91cb551a6959209bc6aeee..2479753dd5f152f304cf6777d168b063c979ae68 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_features.h"
+#include "ircd_log.h"
 #include "ircd_reply.h"
 #include "ircd_string.h"
 #include "list.h"
 #include "send.h"
 #include "struct.h"
 
-#include <assert.h>
+/* #include <assert.h> -- Now using assert in ircd_log.h */
 
 /*
  * m_invite - generic message handler
@@ -129,12 +125,12 @@ int m_invite(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
      * list the channels you have an invite to.
      */
     struct SLink *lp;
-    for (lp = sptr->user->invited; lp; lp = lp->next)
+    for (lp = cli_user(sptr)->invited; lp; lp = lp->next)
       send_reply(cptr, RPL_INVITELIST, lp->value.chptr->chname);
     send_reply(cptr, RPL_ENDOFINVITELIST);
     return 0;
   }
-
+  
   if (parc < 3 || EmptyString(parv[2]))
     return need_more_params(sptr, "INVITE");
 
@@ -146,30 +142,10 @@ int m_invite(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
   if (is_silenced(sptr, acptr))
     return 0;
 
-  clean_channelname(parv[2]);
-
-  if (!IsChannelPrefix(*parv[2]))
-    return 0;
-
-  if (!(chptr = FindChannel(parv[2]))) {
-    if (IsModelessChannel(parv[2]) || IsLocalChannel(parv[2])) {
-      send_reply(sptr, ERR_NOTONCHANNEL, parv[2]);
-      return 0;
-    }
-
-    /* Do not disallow to invite to non-existant #channels, otherwise they
-       would simply first be created, causing only MORE bandwidth usage. */
-
-    if (check_target_limit(sptr, acptr, acptr->name, 0))
-      return 0;
-
-    send_reply(sptr, RPL_INVITING, acptr->name, parv[2]);
-
-    if (acptr->user->away)
-      send_reply(sptr, RPL_AWAY, acptr->name, acptr->user->away);
-
-    sendcmdto_one(sptr, CMD_INVITE, acptr, "%s :%s", acptr->name, parv[2]);
-
+  if (!IsChannelName(parv[2])
+      || !strIsIrcCh(parv[2])
+      || !(chptr = FindChannel(parv[2]))) {
+    send_reply(sptr, ERR_NOSUCHCHANNEL, parv[2]);
     return 0;
   }
 
@@ -179,7 +155,7 @@ int m_invite(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
   }
 
   if (find_channel_member(acptr, chptr)) {
-    send_reply(sptr, ERR_USERONCHANNEL, acptr->name, chptr->chname);
+    send_reply(sptr, ERR_USERONCHANNEL, cli_name(acptr), chptr->chname);
     return 0;
   }
 
@@ -190,18 +166,35 @@ int m_invite(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
 
   /* If we get here, it was a VALID and meaningful INVITE */
 
-  if (check_target_limit(sptr, acptr, acptr->name, 0))
+  if (check_target_limit(sptr, acptr, cli_name(acptr), 0))
     return 0;
 
-  send_reply(sptr, RPL_INVITING, acptr->name, chptr->chname);
+  send_reply(sptr, RPL_INVITING, cli_name(acptr), chptr->chname);
 
-  if (acptr->user->away)
-    send_reply(sptr, RPL_AWAY, acptr->name, acptr->user->away);
+  if (cli_user(acptr)->away)
+    send_reply(sptr, RPL_AWAY, cli_name(acptr), cli_user(acptr)->away);
 
-  if (MyConnect(acptr))
+  if (MyConnect(acptr)) {
     add_invite(acptr, chptr);
+    sendcmdto_one(sptr, CMD_INVITE, acptr, "%s %H", cli_name(acptr), chptr);
+  } else if (!IsLocalChannel(chptr->chname)) {
+    sendcmdto_one(sptr, CMD_INVITE, acptr, "%s %H %Tu", cli_name(acptr), chptr,
+                  chptr->creationtime);
+  }
 
-  sendcmdto_one(sptr, CMD_INVITE, acptr, "%s :%H", acptr->name, chptr);
+  if (!IsLocalChannel(chptr->chname) || MyConnect(acptr)) {
+    if (feature_bool(FEAT_ANNOUNCE_INVITES)) {
+      /* Announce to channel operators. */
+      sendcmdto_channel_butserv_butone(&his, get_error_numeric(RPL_ISSUEDINVITE)->str,
+                                       NULL, chptr, sptr, SKIP_NONOPS,
+                                       "%H %C %C :%C has been invited by %C",
+                                       chptr, acptr, sptr, acptr, sptr);
+      /* Announce to servers with channel operators. */
+      sendcmdto_channel_servers_butone(sptr, NULL, TOK_INVITE, chptr, acptr, SKIP_NONOPS,
+                                       "%s %H %Tu", cli_name(acptr),
+                                       chptr, chptr->creationtime);
+    }
+  }
 
   return 0;
 }
@@ -212,6 +205,7 @@ int m_invite(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
  *   parv[0] - sender prefix
  *   parv[1] - user to invite
  *   parv[2] - channel name
+ *   parv[3] - (optional) channel timestamp
  *
  * - INVITE now is accepted only if who does it is chanop (this of course
  *   implies that channel must exist and he must be on it).
@@ -221,201 +215,89 @@ int m_invite(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
  *
  * - Invite with no parameters now lists the channels you are invited to.
  *                                                         - Isomer 23 Oct 99
+ *
+ * - Invite with too-late timestamp, or with no timestamp from a bursting
+ *   server, is silently discarded.                   - Entrope 19 Jan 05
  */
 int ms_invite(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
 {
   struct Client *acptr;
   struct Channel *chptr;
+  time_t invite_ts;
   
   if (IsServer(sptr)) {
     /*
      * this will blow up if we get an invite from a server
      * we look for channel membership in sptr below. 
      */
-    /* PROTOCOL WARNING */
-    return 0;
+    return protocol_violation(sptr,"Server attempting to invite");
   }
   if (parc < 3 || EmptyString(parv[2])) {
     /*
      * should have been handled upstream, ignore it.
      */
-    /* PROTOCOL WARNING */
-    return 0;
+    protocol_violation(sptr,"Too few arguments to invite");
+    return need_more_params(sptr,"INVITE");
   }
-  if ('#' != *parv[2]) {
+  if (!IsGlobalChannel(parv[2])) {
     /*
      * should not be sent
      */
-    /* PROTOCOL WARNING */
-    return 0;
+    return protocol_violation(sptr, "Invite to a non-standard channel %s",parv[2]);
   }
   if (!(acptr = FindUser(parv[1]))) {
     send_reply(sptr, ERR_NOSUCHNICK, parv[1]);
     return 0;
   }
-  if (!MyUser(acptr)) {
-    /*
-     * just relay the message
-     */
-    sendcmdto_one(sptr, CMD_INVITE, acptr, "%s :%s", acptr->name, parv[2]);
-    return 0;
-  }
-
-  if (is_silenced(sptr, acptr))
-    return 0;
 
   if (!(chptr = FindChannel(parv[2]))) {
     /*
-     * allow invites to non existant channels, bleah
+     * allow invites to non existent channels, bleah
      * avoid JOIN, INVITE, PART abuse
      */
     sendcmdto_one(sptr, CMD_INVITE, acptr, "%C :%s", acptr, parv[2]);
     return 0;
   }
 
-  if (!find_channel_member(sptr, chptr)) {
-    send_reply(sptr, ERR_NOTONCHANNEL, chptr->chname);
-    return 0;
-  }
-  if (find_channel_member(acptr, chptr)) {
-    send_reply(sptr, ERR_USERONCHANNEL, acptr->name, chptr->chname);
+  if (parc > 3) {
+    invite_ts = atoi(parv[3]);
+    if (invite_ts > chptr->creationtime)
+      return 0;
+  } else if (IsBurstOrBurstAck(cptr))
     return 0;
-  }
-  add_invite(acptr, chptr);
-  sendcmdto_one(sptr, CMD_INVITE, acptr, "%s :%H", acptr->name, chptr);
-  return 0;
-}
-
 
-#if 0
-/*
- * m_invite
- *
- *   parv[0] - sender prefix
- *   parv[1] - user to invite
- *   parv[2] - channel name
- *
- * - INVITE now is accepted only if who does it is chanop (this of course
- *   implies that channel must exist and he must be on it).
- *
- * - On the other side it IS processed even if channel is NOT invite only
- *   leaving room for other enhancements like inviting banned ppl.  -- Nemesi
- *
- * - Invite with no parameters now lists the channels you are invited to.
- *                                                         - Isomer 23 Oct 99
- */
-int m_invite(struct Client* cptr, struct Client *sptr, int parc, char *parv[])
-{
-  struct Client *acptr;
-  struct Channel *chptr;
-  
-  if (parc < 2 ) { 
-    /*
-     * list the channels you have an invite to.
-     */
-    struct SLink *lp;
-    for (lp = sptr->user->invited; lp; lp = lp->next)
-      sendto_one(cptr, rpl_str(RPL_INVITELIST), me.name, cptr->name, /* XXX DEAD */
-                lp->value.chptr->chname);
-    sendto_one(cptr, rpl_str(RPL_ENDOFINVITELIST), me.name, cptr->name); /* XXX DEAD */
+  if (!IsChannelService(sptr) && !find_channel_member(sptr, chptr)) {
+    send_reply(sptr, ERR_NOTONCHANNEL, chptr->chname);
     return 0;
   }
 
-  if (parc < 3 || *parv[2] == '\0')
-    return need_more_params(sptr, "INVITE");
-
-  if (!(acptr = FindUser(parv[1])))
-  {
-    sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], parv[1]); /* XXX DEAD */
+  if (find_channel_member(acptr, chptr)) {
+    send_reply(sptr, ERR_USERONCHANNEL, cli_name(acptr), chptr->chname);
     return 0;
   }
 
   if (is_silenced(sptr, acptr))
     return 0;
 
-  if (MyUser(sptr))
-    clean_channelname(parv[2]);
-  else if (IsLocalChannel(parv[2]))
-    return 0;
-
-  if (*parv[2] == '0' || !IsChannelName(parv[2]))
-    return 0;
-
-  if (!(chptr = FindChannel(parv[2])))
-  {
-    if (IsModelessChannel(parv[2]) || IsLocalChannel(parv[2]))
-    {
-      sendto_one(sptr, err_str(ERR_NOTONCHANNEL), me.name, parv[0], parv[2]); /* XXX DEAD */
-      return 0;
-    }
-
-    /* Do not disallow to invite to non-existant #channels, otherwise they
-       would simply first be created, causing only MORE bandwidth usage. */
-    if (MyConnect(sptr))
-    {
-      if (check_target_limit(sptr, acptr, acptr->name, 0))
-        return 0;
-
-      sendto_one(sptr, rpl_str(RPL_INVITING), me.name, parv[0], /* XXX DEAD */
-          acptr->name, parv[2]);
-
-      if (acptr->user->away)
-        sendto_one(sptr, rpl_str(RPL_AWAY), me.name, parv[0], /* XXX DEAD */
-            acptr->name, acptr->user->away);
-    }
-
-    sendto_prefix_one(acptr, sptr, ":%s INVITE %s :%s", parv[0], /* XXX DEAD */
-        acptr->name, parv[2]);
-
-    return 0;
-  }
-
-  if (!find_channel_member(sptr, chptr))
-  {
-    sendto_one(sptr, err_str(ERR_NOTONCHANNEL), me.name, parv[0], /* XXX DEAD */
-        chptr->chname);
-    return 0;
-  }
-
-  if (find_channel_member(acptr, chptr))
-  {
-    sendto_one(sptr, err_str(ERR_USERONCHANNEL), /* XXX DEAD */
-        me.name, parv[0], acptr->name, chptr->chname);
-    return 0;
-  }
-
-  if (MyConnect(sptr))
-  {
-    if (!is_chan_op(sptr, chptr))
-    {
-      sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED), /* XXX DEAD */
-          me.name, parv[0], chptr->chname);
-      return 0;
-    }
-
-    /* If we get here, it was a VALID and meaningful INVITE */
-
-    if (check_target_limit(sptr, acptr, acptr->name, 0))
-      return 0;
-
-    sendto_one(sptr, rpl_str(RPL_INVITING), me.name, parv[0], /* XXX DEAD */
-        acptr->name, chptr->chname);
-
-    if (acptr->user->away)
-      sendto_one(sptr, rpl_str(RPL_AWAY), me.name, parv[0], /* XXX DEAD */
-          acptr->name, acptr->user->away);
-  }
-
   if (MyConnect(acptr)) {
     add_invite(acptr, chptr);
-  sendto_prefix_one(acptr, sptr, ":%s INVITE %s :%s", parv[0], /* XXX DEAD */
-      acptr->name, chptr->chname);
+    sendcmdto_one(sptr, CMD_INVITE, acptr, "%s %H", cli_name(acptr), chptr);
+  } else {
+    sendcmdto_one(sptr, CMD_INVITE, acptr, "%s %H %Tu", cli_name(acptr), chptr,
+                  chptr->creationtime);
+  }
+
+  if (feature_bool(FEAT_ANNOUNCE_INVITES)) {
+    /* Announce to channel operators. */
+    sendcmdto_channel_butserv_butone(&his, get_error_numeric(RPL_ISSUEDINVITE)->str,
+                                     NULL, chptr, sptr, SKIP_NONOPS,
+                                     "%H %C %C :%C has been invited by %C",
+                                     chptr, acptr, sptr, acptr, sptr);
+    /* Announce to servers with channel operators. */
+    sendcmdto_channel_servers_butone(sptr, NULL, TOK_INVITE, chptr, acptr, SKIP_NONOPS,
+                                     "%s %H %Tu", cli_name(acptr), chptr,
+                                     chptr->creationtime);
   }
-  else
-    sendto_highprot_butone(acptr, 10, "%s%s " TOK_INVITE " %s :%s", /* XXX DEAD */
-       NumNick(sptr), acptr->name, chptr->chname);
 
   return 0;
 }
-#endif /* 0 */
-