/*
* IRC - Internet Relay Chat, ircd/m_destruct.c
- * Copyright (C) 1997 Carlo Wood.
+ * Copyright (C) 1997, 2005 Carlo Wood.
*
* See file AUTHORS in IRC package for additional names of
* the programmers.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * $Id: m_destruct.c,v 1.9 2005/03/20 16:06:18 entrope Exp $
+ * $Id: m_destruct.c,v 1.9.2.3 2006/01/03 01:25:50 entrope Exp $
*/
#include "config.h"
/* Don't pass on DESTRUCT messages for channels that
are not empty, but instead send a BURST msg upstream. */
if (chptr->users > 0) {
+#if 0 /* Once all servers are 2.10.12, this can be used too.
+ Until then we have to use CREATE and MODE to
+ get the message accross, because older server do
+ not accept a BURST outside the net.burst. */
send_channel_modes(cptr, chptr);
+#else
+ /* This happens when a JOIN and DESTRUCT crossed, ie:
+
+ server1 ----------------- server2
+ DESTRUCT--> <-- JOIN,MODE
+
+ Where the JOIN and MODE are the result of joining
+ the zannel before it expired on server2, or in the
+ case of simulateous expiration, a DESTRUCT crossing
+ with another DESTRUCT (that will be ignored) and
+ a CREATE of a user joining right after that:
+
+ server1 ----------------- server2
+ DESTRUCT--> <-- DESTRUCT <-- CREATE
+
+ in both cases, when the DESTRUCT arrives on
+ server2 we need to send synchronizing messages
+ upstream (to server1). Since sending two CREATEs
+ or JOINs for the same user after another is a
+ protocol violation, we first have to send PARTs
+ (we can't send a DESTRUCT because 2.10.11 ignores
+ DESTRUCT messages (just passes them on) and has
+ a bug that causes two JOIN's for the same user to
+ result in that user being on the channel twice). */
+
+ struct Membership *member;
+ struct ModeBuf mbuf;
+ struct Ban *link;
+
+ /* Next, send all PARTs upstream. */
+ for (member = chptr->members; member; member = member->next_member)
+ sendcmdto_one(member->user, CMD_PART, cptr, "%H", chptr);
+
+ /* Next, send JOINs for all members. */
+ for (member = chptr->members; member; member = member->next_member)
+ sendcmdto_one(member->user, CMD_JOIN, cptr, "%H", chptr);
+
+ /* Build MODE strings. We use MODEBUF_DEST_BOUNCE with MODE_DEL to assure
+ that the resulting MODEs are only sent upstream. */
+ modebuf_init(&mbuf, sptr, cptr, chptr, MODEBUF_DEST_SERVER | MODEBUF_DEST_BOUNCE);
+
+ /* Op/voice the users as appropriate. We use MODE_DEL because we fake a bounce. */
+ for (member = chptr->members; member; member = member->next_member)
+ {
+ if (IsChanOp(member))
+ modebuf_mode_client(&mbuf, MODE_DEL | MODE_CHANOP, member->user, OpLevel(member));
+ if (HasVoice(member))
+ modebuf_mode_client(&mbuf, MODE_DEL | MODE_VOICE, member->user, MAXOPLEVEL + 1);
+ }
+
+ /* Send other MODEs. */
+ modebuf_mode(&mbuf, MODE_DEL | chptr->mode.mode);
+ if (*chptr->mode.key)
+ modebuf_mode_string(&mbuf, MODE_DEL | MODE_KEY, chptr->mode.key, 0);
+ if (chptr->mode.limit)
+ modebuf_mode_uint(&mbuf, MODE_DEL | MODE_LIMIT, chptr->mode.limit);
+ if (*chptr->mode.upass)
+ modebuf_mode_string(&mbuf, MODE_DEL | MODE_UPASS, chptr->mode.upass, 0);
+ if (*chptr->mode.apass)
+ modebuf_mode_string(&mbuf, MODE_DEL | MODE_APASS, chptr->mode.apass, 0);
+ for (link = chptr->banlist; link; link = link->next)
+ modebuf_mode_string(&mbuf, MODE_DEL | MODE_BAN, link->banstr, 0);
+ modebuf_flush(&mbuf);
+#endif
+
return 0;
}
sendcmdto_serv_butone(&me, CMD_DESTRUCT, 0, "%s %Tu", parv[1], chanTS);
/* Remove the empty channel. */
- remove_destruct_event(chptr);
+ if (chptr->destruct_event)
+ remove_destruct_event(chptr);
destruct_channel(chptr);
return 0;