--- /dev/null
+diff -burN eggdrop1.6.15/doc/USERS eggdrop1.6.15-multilevel_sharing/doc/USERS
+--- eggdrop1.6.15/doc/USERS Mon May 5 00:05:32 2003
++++ eggdrop1.6.15-multilevel_sharing/doc/USERS Fri May 9 18:44:33 2003
+@@ -75,6 +75,11 @@
+
+ u (unshared) user record is not sent to other bots.
+
++ s (protected) is working similar like u flag, but changes can be made
++ only from bot that is aggressively sharing with us (Hub).
++ User cannot be changed by bot that is connected below
++ this bot. (This flag can be useful in multilevel sharing)
++
+ h (highlight) use bold text in help/text files.
+
+ All global flags other then u, h, b, c, x, j, and p are also
+diff -burN eggdrop1.6.15/doc/tcl-commands.doc eggdrop1.6.15-multilevel_sharing/doc/tcl-commands.doc
+--- eggdrop1.6.15/doc/tcl-commands.doc Mon May 5 00:05:32 2003
++++ eggdrop1.6.15-multilevel_sharing/doc/tcl-commands.doc Fri May 9 18:44:33 2003
+@@ -1245,6 +1245,17 @@
+ Module: filesys
+
+
++
++***### SHARE MODULE COMMANDS ###***
++
++ noshare <command> [<arg1> <arg2> ...]
++ Description: executes command with setting noshare = 1 in code,
++ that means, if you i.e. do chattr using this command,
++ bot will make changes on his userlist, but won't send changes
++ to other bots. This is useful in some situations.
++ Returns: whatever is returned by <command>
++ Module: share
++
+ *** MISCELLANEOUS COMMANDS ***
+
+ bind <type> <flags> <keyword/mask> [proc-name]
+diff -burN eggdrop1.6.15/eggdrop.conf eggdrop1.6.15-multilevel_sharing/eggdrop.conf
+--- eggdrop1.6.15/eggdrop.conf Mon May 5 00:05:32 2003
++++ eggdrop1.6.15-multilevel_sharing/eggdrop.conf Fri May 9 18:44:33 2003
+@@ -1139,11 +1139,21 @@
+ # changes from other bots should be ignored?
+ #set private-globals "mnot"
+
++# When sharing user lists, which channel flags changes from other bots
++# should be ignored?
++#set private-chanflags "mn"
++
+ # When sharing user lists, don't accept ANY userfile changes from other
+ # bots? Paranoid people should use this feature on their hub bot. This
+ # will force all userlist changes to be made via the hub.
+ #set private-user 0
+
++# When you have multilevel botnet, this option permits hub, to make changes,
++# even when private-global, private-chanflags and/or private-user are set.
++# NOTE: this option doesn't permit hub to force flags filtered by
++# private-globals
++#set permit-hub 1
++
+ # This setting makes the bot discard its own bot records in favor of
+ # the ones sent by the hub.
+ # NOTE: No passwords or botflags are shared, only ports and
+diff -burN eggdrop1.6.15/help/cmds2.help eggdrop1.6.15-multilevel_sharing/help/cmds2.help
+--- eggdrop1.6.15/help/cmds2.help Mon May 5 00:05:32 2003
++++ eggdrop1.6.15-multilevel_sharing/help/cmds2.help Fri May 9 18:44:33 2003
+@@ -336,6 +336,7 @@
+ p party-line (user has access to the partyline)
+ q global quiet (user does not get voice on +autovoice channels.)
+ r global dehalfop (user cannot gain halfops on any of the bot's channels)
++ s protected (when sharing changes can be made only by hub)
+ t botnet master (user has access to all features dealing with the botnet.)
+ u unshared (user record is not sent to other bots.)
+ v global voice (user get +v automatically on +autovoice channels)
+diff -burN eggdrop1.6.15/src/cmds.c eggdrop1.6.15-multilevel_sharing/src/cmds.c
+--- eggdrop1.6.15/src/cmds.c Mon May 5 00:05:32 2003
++++ eggdrop1.6.15-multilevel_sharing/src/cmds.c Fri May 9 18:46:00 2003
+@@ -1556,8 +1556,8 @@
+ mns.chan &= ~(BOT_SHARE);
+ }
+ if (!glob_owner(user)) {
+- pls.global &=~(USER_OWNER | USER_MASTER | USER_BOTMAST | USER_UNSHARED);
+- mns.global &=~(USER_OWNER | USER_MASTER | USER_BOTMAST | USER_UNSHARED);
++ pls.global &=~(USER_OWNER | USER_MASTER | USER_BOTMAST | USER_UNSHARED | USER_PROTECTED);
++ mns.global &=~(USER_OWNER | USER_MASTER | USER_BOTMAST | USER_UNSHARED | USER_PROTECTED);
+
+ if (chan) {
+ pls.chan &= ~USER_OWNER;
+diff -burN eggdrop1.6.15/src/flags.h eggdrop1.6.15-multilevel_sharing/src/flags.h
+--- eggdrop1.6.15/src/flags.h Mon May 5 00:05:32 2003
++++ eggdrop1.6.15-multilevel_sharing/src/flags.h Fri May 9 18:48:57 2003
+@@ -44,8 +44,8 @@
+
+ /*
+ * userflags:
+- * abcdefgh?jklmnopqr?tuvwxyz + user defined A-Z
+- * unused letters: is
++ * abcdefgh?jklmnopqrstuvwxyz + user defined A-Z
++ * unused letters: i
+ *
+ * botflags:
+ * 0123456789ab????ghi??l???p?rs???????
+@@ -55,7 +55,7 @@
+ * a??defg???klmno?qr??uv??yz + user defined A-Z
+ * unused letters: bchijpstwx
+ */
+-#define USER_VALID 0x03fbfeff /* Sum of all USER_ flags */
++#define USER_VALID 0x03fffeff /* Sum of all USER_ flags */
+ #define CHAN_VALID 0x03777c79 /* Sum of all CHAN_ flags */
+ #define BOT_VALID 0x7fe689C1 /* Sum of all BOT_ flags */
+
+@@ -78,7 +78,7 @@
+ #define USER_PARTY 0x00008000 /* p user has party line access */
+ #define USER_QUIET 0x00010000 /* q user is global de-voice */
+ #define USER_DEHALFOP 0x00020000 /* r user is global de-halfop */
+-#define USER_S 0x00040000 /* s unused */
++#define USER_PROTECTED 0x00040000 /* s user is protected (cannot be removed/changed by downlinks */
+ #define USER_BOTMAST 0x00080000 /* t user is botnet master */
+ #define USER_UNSHARED 0x00100000 /* u not shared with sharebots */
+ #define USER_VOICE 0x00200000 /* v user is +v on all channels */
+@@ -166,6 +166,7 @@
+ #define glob_hilite(x) ((x).global & USER_HIGHLITE)
+ #define chan_exempt(x) ((x).chan & USER_EXEMPT)
+ #define glob_exempt(x) ((x).global & USER_EXEMPT)
++#define glob_protected(x) ((x).global & USER_PROTECTED)
+
+ #define bot_global(x) ((x).bot & BOT_GLOBAL)
+ #define bot_chan(x) ((x).chan & BOT_AGGRESSIVE)
+diff -burN eggdrop1.6.15/src/mod/share.mod/Makefile eggdrop1.6.15-multilevel_sharing/src/mod/share.mod/Makefile
+--- eggdrop1.6.15/src/mod/share.mod/Makefile Mon May 5 00:05:33 2003
++++ eggdrop1.6.15-multilevel_sharing/src/mod/share.mod/Makefile Fri May 9 18:49:41 2003
+@@ -20,7 +20,7 @@
+ mv share.o ../
+
+ ../../../share.$(MOD_EXT): ../share.o
+- $(LD) -o ../../../share.$(MOD_EXT) ../share.o
++ $(LD) -o ../../../share.$(MOD_EXT) ../share.o ${XLIBS}
+ $(STRIP) ../../../share.$(MOD_EXT)
+
+ depend:
+diff -burN eggdrop1.6.15/src/mod/share.mod/share.c eggdrop1.6.15-multilevel_sharing/src/mod/share.mod/share.c
+--- eggdrop1.6.15/src/mod/share.mod/share.c Mon May 5 00:05:33 2003
++++ eggdrop1.6.15-multilevel_sharing/src/mod/share.mod/share.c Fri May 9 19:10:34 2003
+@@ -50,11 +50,14 @@
+ static int private_global = 0;
+ static int private_user = 0;
+ static char private_globals[50];
++static char private_chanflags[50];
+ static int allow_resync = 0;
+ static struct flag_record fr = { 0, 0, 0, 0, 0, 0 };
+ static int resync_time = 900;
+ static int overr_local_bots = 0; /* Override local bots? */
+
++static int permit_hub = 0; /* Permit hub to do changes even, when we use private_*, */
++ /* but not private_globals (this have a reason) */
+
+ struct delay_mode {
+ struct delay_mode *next;
+@@ -93,6 +96,7 @@
+ static void q_resync(char *, struct chanset_t *);
+ static void cancel_user_xfer(int, void *);
+ static int private_globals_bitmask();
++static int private_chanflags_bitmask();
+
+ #include "share.h"
+
+@@ -307,7 +311,7 @@
+ char *hand;
+ struct userrec *u;
+
+- if ((dcc[idx].status & STAT_SHARE) && !private_user) {
++ if ((dcc[idx].status & STAT_SHARE) && (!private_user || PERMIT_HUB(idx))) {
+ hand = newsplit(&par);
+ u = get_user_by_handle(userlist, hand);
+ if (u && !(u->flags & USER_UNSHARED)) {
+@@ -329,26 +333,33 @@
+ int bfl, ofl;
+ module_entry *me;
+
+- if ((dcc[idx].status & STAT_SHARE) && !private_user) {
++ if ((dcc[idx].status & STAT_SHARE) && (!private_user || PERMIT_HUB(idx))) {
+ hand = newsplit(&par);
+ u = get_user_by_handle(userlist, hand);
+- if (u && !(u->flags & USER_UNSHARED)) {
++ if (u && !(u->flags & USER_UNSHARED) && !IS_USER_PROTECTED(u, idx)) {
+ atr = newsplit(&par);
+ cst = findchan_by_dname(par);
+ if (!par[0] || (cst && channel_shared(cst))) {
+- if (!(dcc[idx].status & STAT_GETTING) && (cst || !private_global))
+- shareout_but(cst, idx, "a %s %s %s\n", hand, atr, par);
+ noshare = 1;
+ if (par[0] && cst) {
++ int pchbm = 0;
++ if (!PERMIT_HUB(idx))
++ pchbm = private_chanflags_bitmask();
+ fr.match = (FR_CHAN | FR_BOT);
++ /* bot's sharing flags */
+ get_user_flagrec(dcc[idx].user, &fr, par);
+ if (bot_chan(fr) || bot_global(fr)) {
+ fr.match = FR_CHAN;
+ fr2.match = FR_CHAN;
+ break_down_flags(atr, &fr, 0);
+ get_user_flagrec(u, &fr2, par);
+- fr.chan = (fr2.chan & BOT_AGGRESSIVE) |
+- (fr.chan & ~BOT_AGGRESSIVE);
++ fr.chan = (fr2.chan & BOT_AGGRESSIVE) | (fr.chan & ~BOT_AGGRESSIVE);
++ /* Checking for forced flags */
++ if ( (pchbm & USER_OWNER) && chan_owner(fr) && !chan_owner(fr2))
++ fr.chan &= ~(USER_MASTER | USER_OP);
++ else if ( (pchbm & USER_MASTER) && chan_master(fr) && !chan_master(fr2))
++ fr.chan &= ~USER_OP;
++ fr.chan = (fr2.chan & pchbm) | (fr.chan & ~pchbm);
+ set_user_flagrec(u, &fr, par);
+ check_dcc_chanattrs(u, par, fr.chan, fr2.chan);
+ noshare = 0;
+@@ -365,7 +376,7 @@
+ putlog(LOG_CMDS, "*",
+ "Rejected flags for unshared channel %s from %s",
+ par, dcc[idx].nick);
+- } else if (!private_global) {
++ } else if (!private_global || PERMIT_HUB(idx)) {
+ int pgbm = private_globals_bitmask();
+
+ /* Don't let bot flags be altered */
+@@ -384,15 +395,17 @@
+ if (!(dcc[idx].status & STAT_GETTING))
+ putlog(LOG_CMDS, "*", "%s: chattr %s %s", dcc[idx].nick, hand, s);
+ if ((me = module_find("irc", 0, 0))) {
++ struct chanset_t *tmpcst;
+ Function *func = me->funcs;
+-
+- for (cst = chanset; cst; cst = cst->next)
+- (func[IRC_RECHECK_CHANNEL]) (cst, 0);
++ for (tmpcst = chanset; tmpcst; tmpcst = tmpcst->next)
++ (func[IRC_RECHECK_CHANNEL]) (tmpcst, 0);
+ }
+ } else
+ putlog(LOG_CMDS, "*", "Rejected global flags for %s from %s",
+ hand, dcc[idx].nick);
+ noshare = 0;
++ if (!(dcc[idx].status & STAT_GETTING) && (cst || !private_global || PERMIT_HUB(idx)))
++ shareout_but(cst, idx, "a %s %s %s\n", hand, s, par);
+ }
+ }
+ }
+@@ -404,7 +417,7 @@
+ struct chanset_t *chan;
+ struct userrec *u;
+
+- if ((dcc[idx].status & STAT_SHARE) && !private_user) {
++ if ((dcc[idx].status & STAT_SHARE) && (!private_user || PERMIT_HUB(idx))) {
+ user = newsplit(&par);
+ if ((u = get_user_by_handle(userlist, user))) {
+ chan = findchan_by_dname(par);
+@@ -433,7 +446,7 @@
+ struct chanset_t *chan;
+ struct userrec *u;
+
+- if ((dcc[idx].status & STAT_SHARE) && !private_user) {
++ if ((dcc[idx].status & STAT_SHARE) && (!private_user || PERMIT_HUB(idx))) {
+ user = newsplit(&par);
+ if ((u = get_user_by_handle(userlist, user))) {
+ chan = findchan_by_dname(par);
+@@ -459,13 +472,13 @@
+ char *nick, *host, *pass, s[100];
+ struct userrec *u;
+
+- if ((dcc[idx].status & STAT_SHARE) && !private_user) {
++ if ((dcc[idx].status & STAT_SHARE) && (!private_user || PERMIT_HUB(idx))) {
+ nick = newsplit(&par);
+ host = newsplit(&par);
+ pass = newsplit(&par);
+
+ if (!(u = get_user_by_handle(userlist, nick)) ||
+- !(u->flags & USER_UNSHARED)) {
++ !((u->flags & USER_UNSHARED) || IS_USER_PROTECTED(u, idx))) {
+ fr.global = 0;
+
+ fr.match = FR_GLOBAL;
+@@ -510,9 +523,9 @@
+ struct userrec *u;
+
+ /* If user is a share bot, ignore command */
+- if ((dcc[idx].status & STAT_SHARE) && !private_user &&
++ if ((dcc[idx].status & STAT_SHARE) && (!private_user || PERMIT_HUB(idx)) &&
+ (u = get_user_by_handle(userlist, par)) &&
+- !(u->flags & USER_UNSHARED) &&
++ !(u->flags & USER_UNSHARED) && !IS_USER_PROTECTED(u, idx) &&
+ !((u->flags & USER_BOT) && (bot_flags(u) & BOT_SHARE))) {
+ noshare = 1;
+ if (deluser(par)) {
+@@ -528,10 +541,10 @@
+ char *hand;
+ struct userrec *u;
+
+- if ((dcc[idx].status & STAT_SHARE) && !private_user) {
++ if ((dcc[idx].status & STAT_SHARE) && (!private_user || PERMIT_HUB(idx))) {
+ hand = newsplit(&par);
+ if ((u = get_user_by_handle(userlist, hand)) &&
+- !(u->flags & USER_UNSHARED)) {
++ !(u->flags & USER_UNSHARED) && !IS_USER_PROTECTED(u, idx)) {
+ shareout_but(NULL, idx, "+h %s %s\n", hand, par);
+ set_user(&USERENTRY_HOSTS, u, par);
+ putlog(LOG_CMDS, "*", "%s: +host %s %s", dcc[idx].nick, hand, par);
+@@ -544,10 +557,10 @@
+ char *hand, p[32];
+ struct userrec *u;
+
+- if ((dcc[idx].status & STAT_SHARE) && !private_user) {
++ if ((dcc[idx].status & STAT_SHARE) && (!private_user || PERMIT_HUB(idx))) {
+ hand = newsplit(&par);
+ if (!(u = get_user_by_handle(userlist, hand)) ||
+- !(u->flags & USER_UNSHARED)) {
++ !((u->flags & USER_UNSHARED) || IS_USER_PROTECTED(u, idx))) {
+ if (!(dcc[idx].status & STAT_GETTING))
+ shareout_but(NULL, idx, "+bh %s %s\n", hand, par);
+ /* Add bot to userlist if not there */
+@@ -570,10 +583,10 @@
+ char *hand;
+ struct userrec *u;
+
+- if ((dcc[idx].status & STAT_SHARE) && !private_user) {
++ if ((dcc[idx].status & STAT_SHARE) && (!private_user || PERMIT_HUB(idx))) {
+ hand = newsplit(&par);
+ if ((u = get_user_by_handle(userlist, hand)) &&
+- !(u->flags & USER_UNSHARED)) {
++ !(u->flags & USER_UNSHARED) && !IS_USER_PROTECTED(u, idx)) {
+ shareout_but(NULL, idx, "-h %s %s\n", hand, par);
+ noshare = 1;
+ delhost_by_handle(hand, par);
+@@ -590,11 +603,11 @@
+ struct user_entry_type *uet;
+ struct user_entry *e;
+
+- if ((dcc[idx].status & STAT_SHARE) && !private_user) {
++ if ((dcc[idx].status & STAT_SHARE) && (!private_user || PERMIT_HUB(idx))) {
+ key = newsplit(&par);
+ hand = newsplit(&par);
+ if (!(u = get_user_by_handle(userlist, hand)) ||
+- !(u->flags & USER_UNSHARED)) {
++ !((u->flags & USER_UNSHARED) || IS_USER_PROTECTED(u,idx))) {
+ if (!(uet = find_entry_type(key)))
+ /* If it's not a supported type, forget it */
+ debug2("Ignore ch %s from %s (unknown type)", key, dcc[idx].nick);
+@@ -638,10 +651,10 @@
+ struct chanset_t *cst;
+ struct userrec *u;
+
+- if ((dcc[idx].status & STAT_SHARE) && !private_user) {
++ if ((dcc[idx].status & STAT_SHARE) && (!private_user || PERMIT_HUB(idx))) {
+ hand = newsplit(&par);
+ if ((u = get_user_by_handle(userlist, hand)) &&
+- !(u->flags & USER_UNSHARED) && share_greet) {
++ !(u->flags & USER_UNSHARED) && !IS_USER_PROTECTED(u, idx) && share_greet) {
+ chan = newsplit(&par);
+ cst = findchan_by_dname(chan);
+ fr.match = (FR_CHAN | FR_BOT);
+@@ -2033,11 +2046,13 @@
+ {"private-global", &private_global},
+ {"private-user", &private_user},
+ {"override-bots", &overr_local_bots},
++ {"permit-hub", &permit_hub},
+ {NULL, NULL}
+ };
+
+ static tcl_strings my_strings[] = {
+ {"private-globals", private_globals, 50, 0},
++ {"private-chanflags", private_chanflags, 50, 0},
+ {NULL, NULL, 0, 0}
+ };
+
+@@ -2056,6 +2071,39 @@
+ {NULL, NULL, NULL, NULL}
+ };
+
++static int tcl_noshare STDVAR
++{
++ int res;
++ char *x;
++
++ if (argc < 2) {
++ Tcl_AppendResult(irp, "wrong # args: should be \"",
++ argv[0], " arg ?arg ...?\"", NULL);
++ return TCL_ERROR;
++ }
++
++ Context;
++
++ noshare = 1;
++
++ x = Tcl_Merge(argc - 1, argv + 1);
++ res = Tcl_Eval(irp, x);
++ Tcl_Free((char *) x);
++
++ noshare = 0;
++
++ Context;
++ return res;
++}
++
++
++static tcl_cmds my_tclcmds[] =
++{
++ {"noshare", tcl_noshare},
++ {NULL, NULL}
++};
++
++
+ static char *share_close()
+ {
+ int i;
+@@ -2088,6 +2136,7 @@
+ delay_free_mem();
+ rem_tcl_ints(my_ints);
+ rem_tcl_strings(my_strings);
++ rem_tcl_commands(my_tclcmds);
+ rem_builtins(H_dcc, my_cmds);
+ rem_help_reference("share.help");
+ return NULL;
+@@ -2207,6 +2256,7 @@
+ DCC_BOT.kill = cancel_user_xfer;
+ add_tcl_ints(my_ints);
+ add_tcl_strings(my_strings);
++ add_tcl_commands(my_tclcmds);
+ add_builtins(H_dcc, my_cmds);
+ uff_init();
+ uff_addtable(internal_uff_table);
+@@ -2220,3 +2270,11 @@
+ break_down_flags(private_globals, &fr, 0);
+ return fr.global;
+ }
++
++int private_chanflags_bitmask()
++{
++ struct flag_record fr = {FR_CHAN, 0, 0, 0, 0, 0};
++
++ break_down_flags(private_chanflags, &fr, 0);
++ return fr.chan;
++}
+diff -burN eggdrop1.6.15/src/mod/share.mod/share.h eggdrop1.6.15-multilevel_sharing/src/mod/share.mod/share.h
+--- eggdrop1.6.15/src/mod/share.mod/share.h Mon May 5 00:05:33 2003
++++ eggdrop1.6.15-multilevel_sharing/src/mod/share.mod/share.h Fri May 9 19:11:25 2003
+@@ -52,6 +52,11 @@
+ * `priority'. */
+ } uff_table_t;
+
++/* Do we allow hub to change user value <TaKeDa> */
++#define PERMIT_HUB(x) (permit_hub && (dcc[x].status & STAT_AGGRESSIVE))
++/* Is user protected and if he is do we allow changes? <TaKeDa> */
++#define IS_USER_PROTECTED(user,idx) (!(dcc[idx].status & STAT_AGGRESSIVE) && (user->flags & USER_PROTECTED))
++
+ #ifndef MAKING_SHARE
+ /* 4 - 7 */
+ #define finish_share ((void (*) (int))share_funcs[4])
+diff -burN eggdrop1.6.15/src/patch.h eggdrop1.6.15-multilevel_sharing/src/patch.h
+--- eggdrop1.6.15/src/patch.h Mon May 5 00:08:01 2003
++++ eggdrop1.6.15-multilevel_sharing/src/patch.h Fri May 9 19:11:50 2003
+@@ -36,7 +36,7 @@
+ *
+ *
+ */
+-/* PATCH GOES HERE */
++patch("multilevel_sharing");
+ /*
+ *
+ *