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");
 /*
  *
  *
