X-Git-Url: http://git.pk910.de/?a=blobdiff_plain;f=ircd%2Fm_destruct.c;h=f5b7dd60cfc118cbda14667fcfbf4ea1909403e2;hb=refs%2Fheads%2Fupstream-ssl;hp=632e27ab0c00f9fb44d3f3e8839fb08f1e121a34;hpb=b95f40f9ed63623ca230165e95cdc77ae6d1e2a6;p=ircu2.10.12-pk.git diff --git a/ircd/m_destruct.c b/ircd/m_destruct.c index 632e27a..f5b7dd6 100644 --- a/ircd/m_destruct.c +++ b/ircd/m_destruct.c @@ -1,6 +1,6 @@ /* * 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. @@ -113,7 +113,76 @@ int ms_destruct(struct Client* cptr, struct Client* sptr, int parc, char* parv[] /* 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; } @@ -121,7 +190,8 @@ int ms_destruct(struct Client* cptr, struct Client* sptr, int parc, char* parv[] 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;