diff -Nurp ircu2.10.12.08/include/channel.h ircu2.10.12.08-chanpersist/include/channel.h --- ircu2.10.12.08/include/channel.h 2005-12-23 18:15:01.000000000 +0100 +++ ircu2.10.12.08-chanpersist/include/channel.h 2007-01-13 10:49:05.000000000 +0100 @@ -110,12 +110,13 @@ struct Client; #define MODE_APASS 0x200000 #define MODE_WASDELJOINS 0x400000 /**< Not DELJOINS, but some joins * pending */ +#define MODE_PERSIST 0x800000 /**< +z Persistent channel */ /** mode flags which take another parameter (With PARAmeterS) */ #define MODE_WPARAS (MODE_CHANOP|MODE_VOICE|MODE_BAN|MODE_KEY|MODE_LIMIT|MODE_APASS|MODE_UPASS) /** Available Channel modes */ -#define infochanmodes feature_bool(FEAT_OPLEVELS) ? "AbiklmnopstUvrD" : "biklmnopstvrD" +#define infochanmodes feature_bool(FEAT_OPLEVELS) ? "AbiklmnopstUvrDz" : "biklmnopstvrDz" /** Available Channel modes that take parameters */ #define infochanmodeswithparams feature_bool(FEAT_OPLEVELS) ? "AbkloUv" : "bklov" diff -Nurp ircu2.10.12.08/ircd/channel.c ircu2.10.12.08-chanpersist/ircd/channel.c --- ircu2.10.12.08/ircd/channel.c 2006-04-05 01:09:47.000000000 +0200 +++ ircu2.10.12.08-chanpersist/ircd/channel.c 2007-01-13 10:40:34.000000000 +0100 @@ -258,6 +258,9 @@ int sub1_from_channel(struct Channel* ch chptr->users = 0; + if (chptr->mode.mode & MODE_PERSIST) + return 1; + /* * Also channels without Apass set need to be kept alive, * otherwise Bad Guys(tm) would be able to takeover @@ -547,6 +550,9 @@ static int channel_all_zombies(struct Ch { struct Membership* member; + if (chptr->mode.mode & MODE_PERSIST) + return 0; + for (member = chptr->members; member; member = member->next_member) { if (!IsZombie(member)) return 0; @@ -832,6 +838,8 @@ void channel_modes(struct Client *cptr, *mbuf++ = 'D'; else if (MyUser(cptr) && (chptr->mode.mode & MODE_WASDELJOINS)) *mbuf++ = 'd'; + if (chptr->mode.mode & MODE_PERSIST) + *mbuf++ = 'z'; if (chptr->mode.limit) { *mbuf++ = 'l'; ircd_snprintf(0, pbuf, buflen, "%u", chptr->mode.limit); @@ -1542,6 +1550,7 @@ modebuf_flush_int(struct ModeBuf *mbuf, MODE_LIMIT, 'l', /* MODE_APASS, 'A', */ /* MODE_UPASS, 'U', */ + MODE_PERSIST, 'z', 0x0, 0x0 }; static int local_flags[] = { @@ -1951,7 +1960,7 @@ modebuf_mode(struct ModeBuf *mbuf, unsig mode &= (MODE_ADD | MODE_DEL | MODE_PRIVATE | MODE_SECRET | MODE_MODERATED | MODE_TOPICLIMIT | MODE_INVITEONLY | MODE_NOPRIVMSGS | MODE_REGONLY | - MODE_DELJOINS | MODE_WASDELJOINS); + MODE_DELJOINS | MODE_WASDELJOINS | MODE_PERSIST); if (!(mode & ~(MODE_ADD | MODE_DEL))) /* don't add empty modes... */ return; @@ -2098,6 +2107,7 @@ modebuf_extract(struct ModeBuf *mbuf, ch MODE_LIMIT, 'l', MODE_REGONLY, 'r', MODE_DELJOINS, 'D', + MODE_PERSIST, 'z', 0x0, 0x0 }; unsigned int add; @@ -3176,6 +3186,7 @@ mode_parse(struct ModeBuf *mbuf, struct MODE_LIMIT, 'l', MODE_REGONLY, 'r', MODE_DELJOINS, 'D', + MODE_PERSIST, 'z', MODE_ADD, '+', MODE_DEL, '-', 0x0, 0x0 @@ -3265,6 +3276,11 @@ mode_parse(struct ModeBuf *mbuf, struct mode_parse_client(&state, flag_p); break; + case 'z': /* only let remote clients or opmode change persistence */ + if (!MyUser(state.sptr) || (state.flags & MODE_PARSE_FORCE)) + mode_parse_mode(&state, flag_p); + break; + default: /* deal with other modes */ mode_parse_mode(&state, flag_p); break; diff -Nurp ircu2.10.12.08/ircd/m_endburst.c ircu2.10.12.08-chanpersist/ircd/m_endburst.c --- ircu2.10.12.08/ircd/m_endburst.c 2005-05-30 15:14:53.000000000 +0200 +++ ircu2.10.12.08-chanpersist/ircd/m_endburst.c 2007-01-13 10:33:17.000000000 +0100 @@ -126,7 +126,7 @@ int ms_end_of_burst(struct Client* cptr, /* Count through channels... */ for (chan = GlobalChannelList; chan; chan = next_chan) { next_chan = chan->next; - if (!chan->members && (chan->mode.mode & MODE_BURSTADDED)) { + if (!chan->members && ((chan->mode.mode & (MODE_PERSIST | MODE_BURSTADDED)) == MODE_BURSTADDED)) { /* Newly empty channel, schedule it for removal. */ chan->mode.mode &= ~MODE_BURSTADDED; sub1_from_channel(chan); diff -Nurp ircu2.10.12.08/ircd/m_join.c ircu2.10.12.08-chanpersist/ircd/m_join.c --- ircu2.10.12.08/ircd/m_join.c 2006-02-05 01:50:22.000000000 +0100 +++ ircu2.10.12.08-chanpersist/ircd/m_join.c 2007-01-13 11:46:21.000000000 +0100 @@ -188,7 +188,7 @@ int m_join(struct Client *cptr, struct C flags = CHFL_CHANOP | CHFL_CHANNEL_MANAGER; else if (key && !strcmp(key, chptr->mode.upass)) flags = CHFL_CHANOP; - else if (chptr->users == 0 && !chptr->mode.apass[0]) { + else if (chptr->users == 0 && !chptr->mode.apass[0] && !(chptr->mode.mode & MODE_PERSIST)) { /* Joining a zombie channel (zannel): give ops and increment TS. */ flags = CHFL_CHANOP; chptr->creationtime++; diff -Nurp ircu2.10.12.08/ircd/m_kick.c ircu2.10.12.08-chanpersist/ircd/m_kick.c --- ircu2.10.12.08/ircd/m_kick.c 2005-11-14 22:17:07.000000000 +0100 +++ ircu2.10.12.08-chanpersist/ircd/m_kick.c 2007-01-13 10:42:15.000000000 +0100 @@ -221,7 +221,7 @@ int ms_kick(struct Client *cptr, struct * here), if kicker is not on channel, or if kicker is not a channel * operator, bounce the kick */ - if (!IsServer(sptr) && member && cli_from(who) != cptr && + if (!IsServer(sptr) && !IsChannelService(sptr) && member && cli_from(who) != cptr && (!(sptr_link = find_member_link(chptr, sptr)) || !IsChanOp(sptr_link))) { sendto_opmask_butone(0, SNO_HACK2, "HACK: %C KICK %H %C %s", sptr, chptr, who, comment); diff -Nurp ircu2.10.12.08/ircd/m_mode.c ircu2.10.12.08-chanpersist/ircd/m_mode.c --- ircu2.10.12.08/ircd/m_mode.c 2006-03-18 16:52:58.000000000 +0100 +++ ircu2.10.12.08-chanpersist/ircd/m_mode.c 2007-01-13 19:24:50.000000000 +0100 @@ -140,7 +140,17 @@ m_mode(struct Client *cptr, struct Clien (MODE_PARSE_SET | /* Set the mode */ MODE_PARSE_FORCE), /* Force it to take */ member); - return modebuf_flush(&mbuf); + modebuf_flush(&mbuf); + + if(!(chptr->mode.mode & MODE_PERSIST) && chptr->users == 0) // Destruct emtpy, non-persistent channel + { + // other servers also get this MODE and will destruct the channel if it's empty and not persistent + if(chptr->destruct_event) + remove_destruct_event(chptr); + destruct_channel(chptr); + } + + return 0; } else mode_parse(0, cptr, sptr, chptr, parc - 2, parv + 2, (member ? MODE_PARSE_NOTOPER : MODE_PARSE_NOTMEMBER), member); @@ -151,7 +161,17 @@ m_mode(struct Client *cptr, struct Clien (MODEBUF_DEST_CHANNEL | /* Send mode to channel */ MODEBUF_DEST_SERVER)); /* Send mode to servers */ mode_parse(&mbuf, cptr, sptr, chptr, parc - 2, parv + 2, MODE_PARSE_SET, member); - return modebuf_flush(&mbuf); + modebuf_flush(&mbuf); + + if(!(chptr->mode.mode & MODE_PERSIST) && chptr->users == 0) // Destruct emtpy, non-persistent channel + { + // other servers also get this MODE and will destruct the channel if it's empty and not persistent + if(chptr->destruct_event) + remove_destruct_event(chptr); + destruct_channel(chptr); + } + + return 0; } int @@ -197,7 +217,7 @@ ms_mode(struct Client *cptr, struct Clie MODE_PARSE_FORCE), /* And force it to be accepted */ NULL); } else { - if (!(member = find_member_link(chptr, sptr))) { + if (!IsChannelService(sptr) && !(member = find_member_link(chptr, sptr))) { modebuf_init(&mbuf, sptr, cptr, chptr, (MODEBUF_DEST_SERVER | /* Send mode to server */ MODEBUF_DEST_HACK2 | /* Send a HACK(2) message */ @@ -219,5 +239,15 @@ ms_mode(struct Client *cptr, struct Clie } } - return modebuf_flush(&mbuf); + modebuf_flush(&mbuf); + + if(!(chptr->mode.mode & MODE_PERSIST) && chptr->users == 0) // Destruct emtpy, non-persistent channel + { + // other servers also get this MODE and will destruct the channel if it's empty and not persistent + if(chptr->destruct_event) + remove_destruct_event(chptr); + destruct_channel(chptr); + } + + return 0; } diff -Nurp ircu2.10.12.08/ircd/m_opmode.c ircu2.10.12.08-chanpersist/ircd/m_opmode.c --- ircu2.10.12.08/ircd/m_opmode.c 2005-09-13 17:17:46.000000000 +0200 +++ ircu2.10.12.08-chanpersist/ircd/m_opmode.c 2007-01-13 10:43:35.000000000 +0100 @@ -130,6 +130,14 @@ int ms_opmode(struct Client* cptr, struc modebuf_flush(&mbuf); /* flush the modes */ + if(!(chptr->mode.mode & MODE_PERSIST) && chptr->users == 0) // Destruct emtpy, non-persistent channel + { + // other servers also get this MODE and will destruct the channel if it's empty and not persistent + if(chptr->destruct_event) + remove_destruct_event(chptr); + destruct_channel(chptr); + } + return 0; } @@ -184,6 +192,14 @@ int mo_opmode(struct Client* cptr, struc modebuf_flush(&mbuf); /* flush the modes */ + if(!(chptr->mode.mode & MODE_PERSIST) && chptr->users == 0) // Destruct emtpy, non-persistent channel + { + // other servers also get this MODE and will destruct the channel if it's empty and not persistent + if(chptr->destruct_event) + remove_destruct_event(chptr); + destruct_channel(chptr); + } + return 0; }