diff --git a/ChangeLog b/ChangeLog
index cd5029ae7622b354f0540af020b173dbbd933132..73b6e1081d7b05908627c23aaa556000baf8e90d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,41 @@
+1998-06-10  David Byers  <davby@ida.liu.se>
+
+	* src/server/membership.c (sub_member): Return KOM_NOT_MEMBER for
+	secret memberships.
+
+1998-06-08  David Byers  <davby@ida.liu.se>
+
+	* src/server/membership.c (set_membership_type): New function.
+
+	* src/server/prot-a-output.c (prot_a_output_membership): Output
+	added_at. 
+	(prot_a_output_member): Output added_at
+
+	* src/server/membership.c (do_add_member): Set added_at.
+	(get_members): Filter out added_at.
+
+	* src/server/memory.c (init_membership): Init added_at.
+
+	* src/server/ram-output.c (foutput_member_2): Added output of
+ 	added_at.
+
+	* src/server/ram-parse.c (fparse_member_2): Added parsing of added_at.
+
+	* src/include/kom-types.h: Added added_at to Membership och Member.
+
+	* src/server/ram-parse.c (fparse_membership_2): Added parsning of
+ 	added_at.
+
+	* src/server/ram-output.c (foutput_membership_2): Added output of
+ 	added_at.
+
+Fri Jan 16 22:51:52 1998  David Byers  <davby@litefix.ida.liu.se>
+
+	* src/include/kom-types.h (Aux_item_flags): Added dont_garb.
+
+	* src/server/text-garb.c (garb_text): Check dont_garb aux-item
+ 	flag.
+
 Mon Sep 22 19:06:05 1997  David Byers  <davby@litefix.ida.liu.se>
 
 	* src/server/cache-node.h: New flags: snapshot and synced.
diff --git a/configure b/configure
index 9eaece66962b4c10c607377fc176d91a3ef81bd3..59c341b8e1ae98d7c104e087ba29d65db823e959 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 
-# From configure.in Revision: 1.41 
+# From configure.in Revision: 1.42 
 
 # Guess values for system-dependent variables and create Makefiles.
 # Generated automatically using autoconf version 2.12 
diff --git a/db-crypt/db/lyskomd-data b/db-crypt/db/lyskomd-data
index 66b17f1c75df1e88fb3511d353f6ed2beeb89296..3d196a1fb139b16de45da3e0dfcb18969905a7ac 100644
Binary files a/db-crypt/db/lyskomd-data and b/db-crypt/db/lyskomd-data differ
diff --git a/doc/Protocol-A.texi b/doc/Protocol-A.texi
index 4a61cf9ccbf68c72fb28ead9a0a157197722d605..46cacdb5693e69eeae1c52b7ff620b18e3ea46e1 100644
--- a/doc/Protocol-A.texi
+++ b/doc/Protocol-A.texi
@@ -1,5 +1,5 @@
 \input texinfo                         @c -*-texinfo-*-
-@c $Id: Protocol-A.texi,v 1.6 1997/10/23 12:40:35 byers Exp $
+@c $Id: Protocol-A.texi,v 1.7 1998/06/14 14:50:17 byers Exp $
 @c %**start of header
 @setfilename protocol-a.info
 @settitle LysKOM Protocol A
@@ -172,15 +172,23 @@ Lars Aronsson documented the protocol that was in use at the time.
 @item 95=modify-system-info
 @item 96=query-predefined-aux-items
 @item 97=set-expire
+@item 98=query-read-texts
+@item 99=get-membership
+@item 100=add-member
+@item 101=get-members
 @end itemize
 
 @item Removed Server Calls
 @itemize @bullet
 @item  5=create-person
+@item  9=query-read-texts
 @item 10=create-conf
+@item 14=add-member
 @item 26=get-text-stat
 @item 28=create-text
 @item 36=get-info-old
+@item 46=get-membership-old
+@item 48=get-members-old
 @item 50=get-conf-stat
 @item 59=create-anonymous-text
 @end itemize
@@ -191,6 +199,9 @@ Lars Aronsson documented the protocol that was in use at the time.
 @item Aux-item-list
 @item Conference
 @item Info
+@item Member
+@item Membership
+@item Membership-Type
 @item Misc-info
 @item Text-stat
 @end itemize
@@ -1283,7 +1294,7 @@ relating to information about active LysKOM sessions.
                 inherit;
                 secret;
                 hide-creator;
-                reserved1;
+                dont-garb;
                 reserved2;
                 reserved3;
                 reserved4;
@@ -1329,6 +1340,8 @@ supervisors of the creator.
 @item hide-creator
 The item creator will be withheld from everyone but the item's creator
 and supervisors of the creator.
+@item dont-garb
+The object the item is set on will not be garbage-collected.
 @end table
 
 
@@ -1697,8 +1710,85 @@ The numer of conferences the person is a member of.
 @subsection Membership Information
 
 @example
-        Member          ::=     Pers-No;
+        Membership-Type ::=     BITSTRING
+              ( invitation      :       BOOL;
+                passive         :       BOOL;
+                secret          :       BOOL;
+                reserved1       :       BOOL;
+                reserved2       :       BOOL;
+                reserved3       :       BOOL;
+                reserved4       :       BOOL;
+                reserved5       :       BOOL;
+              )
+@end example
+
+The @code{Membership-Type} type contains flags that modify a membership.
+It is passed as part of both @code{Member} and @code{Membership}. The
+flags are:
+
+@table @code
+@item invitation
+The member has been invited, but has not yet accepted membership.
+Clients should set this flag when adding other users as members. The
+server may force this flag to be set when adding another person as a
+member of a conference.
+@item passive
+The member is not actively participating in the conference. Passive
+members do not revceive group messages and should not be displayed as
+active members by clients.
+@item secret
+The member does not wish to disclose the membership. Secret memberships
+and members are cleared before being returned to a person who is not a
+subervisor of the member or has sufficient privileges enabled.
+@end table
+
+The remaining flags in the @code{Membership-Type} structure are reserved
+and should be set to false on all new memberships and retained on all
+existing memberships.
+
+@example
+        Member-Old      ::=     Pers-No;
+        Member-List-Old ::=     ARRAY Member-Old;
+
+        Member          ::=
+              ( member          :       Pers-No;
+                added-by        :       Pers-No;
+                added-at        :       Time;
+                type            :       Membership-Type;
+              )
         Member-List     ::=     ARRAY Member;
+@end example
+
+The @code{Member} structure encodes information about a member in a
+conference. It is returned by the @ref{get-members} call. The fields of
+a @code{Member} structure are
+
+@table @code
+@item member
+The person who is a member of the conference.
+@item added-by
+The person who created the membership. This field is zero only if the
+membership was created before protocol version 10 was introduced.
+@item added-at
+The time when the membership was created. This field is meaningless if
+added-by is zero.
+@item type
+Flags modifying the membership.
+@end table
+
+The contents of a @code{Member} structure can be cleared (all fields set
+to zero) if the person requesting the record has insufficient privileges
+to see the contents of the structure.
+
+
+@example
+        Membership-Old ::=
+              ( last-time-read  :       Time;
+                conference      :       Conf-No;
+                priority        :       INT8;
+                last-text-read  :       Local-Text-No;
+                read-texts      :       ARRAY Local-Text-No;
+              )
 
         Membership ::=
               ( last-time-read  :       Time;
@@ -1706,16 +1796,18 @@ The numer of conferences the person is a member of.
                 priority        :       INT8;
                 last-text-read  :       Local-Text-No;
                 read-texts      :       ARRAY Local-Text-No;
+                added-by        :       Pers-No;
+                added-at        :       Time;
+                type            :       Membership-Type;                
               )
 
+        Membership-List-Old ::= ARRAY Membership-Old;
         Membership-List ::=     ARRAY Membership;
 @end example
 
-These data types contain information about which conferences a person is
-a member of and what that person has unread in the conference.
-@code{Member} represents a member and @code{Member-List} several.
-@code{Membership} is information pertaining to the membership of a
-single person. Its fields are
+The @code{Membership} structure encodes information about a person's
+membership in a conference. It is returned by the @ref{query-read-texts}
+and @ref{get-membership} calls.
 
 @table @code
 @item last-time-read
@@ -1730,8 +1822,21 @@ used to indicate a passive membership.
 The local number of last text read in the conference.
 @item read-texts
 Additional texts beyond @code{last-text-read} that have also been read.
+@item added-by
+The person who created the membership. This field is zero if the
+membership was created before protocol version 10 was introduced.
+@item added-at
+The time when the membership was created. This field is meaningless if
+added-by is zero.
+@item type
+Flags modifying the membership.
 @end table
 
+A membership record may be cleared by the server (all fields set to
+zero) if the person requesting the membership has insufficient
+privileges to see the contents membership, but has sufficient privileges
+to know about the person.
+
 
 @subsection Article Marks
 
@@ -2216,12 +2321,12 @@ in the example.
 * get-person-stat-old::        O Get person information. Use call 49        (6)
 * set-priv-bits::                Set privileges of a person                 (7)
 * set-passwd::                   Set password of a person                   (8)
-* query-read-texts::             Get info on what is read                   (9)
+* query-read-texts-old::       O Get info on what is read                   (9)
 * create-conf-old::            O Create a conference                       (10)
 * delete-conf::                  Delete a conference                       (11)
 * lookup-name::                O Look up a name. Replaced by call 76       (12)
 * get-conf-stat-older::        O Get conference information. Use call 50   (13)
-* add-member::                   Add a member to a conference              (14)
+* add-member-old::             O Add a member to a conference              (14)
 * sub-member::                   Remove a member from a conference         (15)
 * set-presentation::             Set the presentation of a conference      (16)
 * set-etc-motd::                 Set conference notice                     (17)
@@ -2253,9 +2358,9 @@ in the example.
 * sync-kom::                     Save the database                         (43)
 * shutdown-kom::                 Shut LysKOM down                          (44)
 * broadcast::                  O Broadcast a message. Replaced by call 53  (45)
-* get-membership::               Get membership for a person               (46)
+* get-membership-old::         O Get membership for a person               (46)
 * get-created-texts::            Get texts created by a user               (47)
-* get-members::                  Get members of a conference               (48)
+* get-members-old::            O Get members of a conference               (48)
 * get-person-stat::              Get status information for a person       (49)
 * get-conf-stat-old::          O Get status information for a conference   (50)
 * who-is-on::                  O Get current sessions. Replaced by call 63 (51)
@@ -2305,6 +2410,10 @@ in the example.
 * modify-system-info::           Add or delete conference aux items        (95)
 * query-predefined-aux-items::   Get list of aux-items the server knows    (96)
 * set-expire::                   Set the expire field in of conference     (97)
+* query-read-texts::             Get info on what is read                  (98)
+* get-membership::               Get membership for a person               (99)
+* add-member::                   Add a member to a conference             (100)
+* get-members::                  Get members of a conference              (101)
 @end menu
 
 @iftex
@@ -2562,7 +2671,7 @@ and privilege level set to 6 or higher.
 @end table
 
 
-@node set-passwd, query-read-texts, set-priv-bits, Protocol Requests
+@node set-passwd, query-read-texts-old, set-priv-bits, Protocol Requests
 @subsection set-passwd (1) Recommended
 
 @example
@@ -2608,13 +2717,13 @@ privilege level 7 or higher enabled.
 
 
 
-@node query-read-texts, create-conf-old, set-passwd, Protocol Requests
-@subsection query-read-texts (1) Recommended
+@node query-read-texts-old, create-conf-old, set-passwd, Protocol Requests
+@subsection query-read-texts-old (1) Obsolete (10)
 
 @example
-        query-read-texts [9] (( person     : Pers-No;
-                                conference : Conf-No; ))
-                -> ( read-texts : Membership );
+        query-read-texts-old [9] (( person     : Pers-No;
+                                    conference : Conf-No; ))
+                -> ( read-texts : Membership-Old );
 @end example
 
 This call is used to find the number of unread texts in a conference.
@@ -2625,7 +2734,7 @@ be made and @code{conference} is the conference in question.
 
 This call may be issued without logging in.
 
-Calling @code{query-read-texts} does not require the session to be logged in.
+Calling @code{query-read-texts-old} does not require the session to be logged in.
 
 @i{Example:}
 @example
@@ -2656,7 +2765,7 @@ Conference @code{conference} does not exist, or is secret.
 
 
 
-@node create-conf-old, delete-conf, query-read-texts, Protocol Requests
+@node create-conf-old, delete-conf, query-read-texts-old, Protocol Requests
 @subsection create-conf-old (1) Obsolete (10)
 
 @example
@@ -2802,7 +2911,7 @@ lookup-name has been superseded by call 76, @ref{lookup-z-name}.
 This call always succeeds.
 
 
-@node get-conf-stat-older, add-member, lookup-name, Protocol Requests
+@node get-conf-stat-older, add-member-old, lookup-name, Protocol Requests
 @subsection get-conf-stat-older (1) Obsolete
 
 @example
@@ -2829,15 +2938,15 @@ use call 91, @ref{get-conf-stat} instead.
 
 
 
-@node add-member, sub-member, get-conf-stat-older, Protocol Requests
-@subsection add-member (1) Recommended
+@node add-member-old, sub-member, get-conf-stat-older, Protocol Requests
+@subsection add-member-old (1) Obsolete (10)
 
 @i{Example:}
 @example
-        add-member [14] (( conf-no  : Conf-No;
-                           pers-no  : Pers-No;
-                           priority : INT8;
-                           where    : INT16 ))
+        add-member-old [14] (( conf-no  : Conf-No;
+                               pers-no  : Pers-No;
+                               priority : INT8;
+                               where    : INT16 ))
                 -> ( );
 @end example
 
@@ -2893,7 +3002,7 @@ privileges to change the priorities of person @code{pers-no}.
 
 
 
-@node sub-member, set-presentation, add-member, Protocol Requests
+@node sub-member, set-presentation, add-member-old, Protocol Requests
 @subsection sub-member (1) Recommended
 
 @example
@@ -4326,7 +4435,7 @@ Administrator bit not set or privileges not enabled.
 @end table
 
 
-@node broadcast, get-membership, shutdown-kom, Protocol Requests
+@node broadcast, get-membership-old, shutdown-kom, Protocol Requests
 
 @subsection broadcast (1) Obsolete
 
@@ -4350,19 +4459,19 @@ Messages have been disabled.
 @end table
 
 
-@node get-membership, get-created-texts, broadcast, Protocol Requests
+@node get-membership-old, get-created-texts, broadcast, Protocol Requests
 
-@subsection get-membership (1) Recommended
+@subsection get-membership-old (1) Obsolete (10)
 
 @example
-        get-membership [46] (( person       :   Pers-No;
-                               first        :   INT16;
-                               no-of-confs  :   INT16;
-                               mask         :   BITSTRING
-                                                (
-                                                    want-read-texts
-                                                ); ))
-                -> ( result : Membership-List );
+        get-membership-old [46] (( person       :   Pers-No;
+                                   first        :   INT16;
+                                   no-of-confs  :   INT16;
+                                   mask         :   BITSTRING
+                                                    (
+                                                        want-read-texts
+                                                    ); ))
+                    -> ( result : Membership-List-Old );
 @end example
 
 This call retrieves the membership record for a list of conferences for
@@ -4410,7 +4519,7 @@ person's membership list.
 
 
 
-@node get-created-texts, get-members, get-membership, Protocol Requests
+@node get-created-texts, get-members-old, get-membership-old, Protocol Requests
 
 @subsection get-created-texts (1) Recommended
 
@@ -4459,15 +4568,15 @@ text.
 
 
 
-@node get-members, get-person-stat, get-created-texts, Protocol Requests
+@node get-members-old, get-person-stat, get-created-texts, Protocol Requests
 
-@subsection get-members (1) Recommended
+@subsection get-members-old (1) Obsolete (10)
 
 @example
-        get-members [48] (( conf            : Conf-No;
-                            first           : INT16;
-                            no-of-members   : INT16; ))
-                -> ( result : Member-List );
+        get-members-old [48] (( conf            : Conf-No;
+                                first           : INT16;
+                                no-of-members   : INT16; ))
+                -> ( result : Member-List-Old );
 @end example
 
 This call returns a list of members of the conference @code{conf-no}.
@@ -4499,7 +4608,7 @@ The conference @code{conf} does not exist or is secret.
 
 
 
-@node get-person-stat, get-conf-stat-old, get-members, Protocol Requests
+@node get-person-stat, get-conf-stat-old, get-members-old, Protocol Requests
 
 @subsection get-person-stat (1) Recommended
 
@@ -6174,7 +6283,7 @@ This call always succeeds.
 
 
 
-@node set-expire, , query-predefined-aux-items, Protocol Requests
+@node set-expire, query-read-texts, query-predefined-aux-items, Protocol Requests
 @subsection set-expire (10) Recommended
 
 @example
@@ -6199,8 +6308,249 @@ Not supervisor of conference @code{conf-no} and not privileged enough to
 complete the call anyway.
 @end table
 
+@node query-read-texts, get-membership, set-expire, Protocol Requests
+@subsection query-read-texts (10) Recommended
 
+@example
+        query-read-texts [98] (( person     : Pers-No;
+                                 conference : Conf-No; ))
+                -> ( read-texts : Membership );
+@end example
+
+This call is used to find the number of unread texts in a conference.
+The data it returns is actually a membership structure which specifies
+which texts have been read. It is up to the client to transform the data
+to a more usable form. @code{person} is the person being queried is to
+be made and @code{conference} is the conference in question.
 
+This call may be issued without logging in.
+
+Calling @code{query-read-texts-old} does not require the session to be logged in.
+
+@i{Example:}
+@example
+        1 98 6 1
+        @t{=1 32 5 11 12 7 93 1 193 1 1 20 133}
+        @t{   3 @{ 135 136 137 @} 5 01000000}
+@end example
+
+This example finds the read texts for user 6 in conference 1. The
+returned data indicates that the user last read conference 1 (the tenth
+number) on Monday July 12th, 1993 at 11:05:32 (the first nine numbers),
+that the person has assigned priority 20 to the conference (the eleventh
+number) and that all articles up to and including local number 133 plus
+articles 135, 136 and 137 have been read. The membership was added by
+person 5, and it is passive.
+
+
+@unnumberedsubsubsec Error codes
+
+@table @code
+@item undefined-person
+@code{person} does not exist, or no access to person.
+@item undefined-conference 
+Conference @code{conference} does not exist, or is secret.
+@item zero-conference
+@code{conference} is zero.
+@item not-member
+@code{person} is not a member of @code{conference} or insufficient
+privileges to find out if @code{person} is a member.
+@end table
+
+
+@node get-membership, add-member, query-read-texts, Protocol Requests
+@subsection get-membership (10) Recommended
+
+@example
+        get-membership [99] (( person       :   Pers-No;
+                               first        :   INT16;
+                               no-of-confs  :   INT16;
+                               mask         :   BITSTRING
+                                                (
+                                                   want-read-texts
+                                                ); ))
+                    -> ( result : Membership-List );
+@end example
+
+This call retrieves the membership record for a list of conferences for
+a single person. @code{person} is the person whose memberships are to be
+retrieved. @code{first} is the first position in the membership list to
+retrieve, numbered from 0 and up. @code{no-of-confs} is the number of
+membership records to retrieve. @code{mask} is a set of flags. Currently
+the only flag is @code{want-red-texts}, which instructs the server not
+to send the @code{read-texts} array of the memberships.
+
+The server will return a membership list that is shorter than
+@code{no-of-confs} if @code{no-of-confs} + @code{first} is larger than
+the number of conferences the person is a member of. Elements of the
+member list that the person requesting the list does not have sufficient
+privileges to see may be cleared. Cleared elements simply have all
+fields set to zero.
+
+@example
+        1 99 5 0 3 1
+        @t{=1 2 @{ 49 14 17 13 8 91 5 255 1 5 255 0 0 * 5 00000000}
+        @t{   20 14 22 17 6 97 4 197 1 6 100 2 0 * 5 00000000 @}}
+        1 99 5 0 1 1
+        @t{=1 1 @{ 49 14 17 13 8 91 5 255 1 5 255 0 0 * 5 00000000 @}}
+        1 99 5 1 4 1
+        @t{=1 1 @{ 20 14 22 17 6 97 4 197 1 6 100 2 0 * 5 00000000 @}}
+@end example
+
+In this example we retrieve the memberships of person 5. The first call
+asks for three memberships, starting with number 0. Since this person is
+only a member of two conferences, the list returned only contains two
+memberships. The next two calls retrieve a single membership each. The
+first by asking for only one, and the second by asking for four
+memberships, starting with number 1.
+
+@unnumberedsubsubsec Error codes
+
+@table @code
+@item login-first
+Login required before issuing this call.
+@item undefined-person
+The person @code{person} does not exist.
+@item undefined-conference
+The conference @code{person} does not exist or is secret.
+@item index-out-of-range
+@code{first} is higher than the index of the first conference in the
+person's membership list.
+@end table
+
+
+@node add-member, get-members, get-membership, Protocol Requests
+@subsection add-member (10) Recommended
+
+@example
+        add-member [100] (( conf-no  : Conf-No;
+                            pers-no  : Pers-No;
+                            priority : INT8;
+                            where    : INT16;
+                            type     : Membership-Type; ))
+                -> ( );
+@end example
+
+Make the person @code{pers-no} a member of conference @code{conf-no}.
+The membership priority is set to @code{priority} and its position in
+the membership list is set to @code{where}.
+
+This call can be used to change the priority, position and flags of a
+conference in the person's membership list if the person is already a
+member of the conference. The person doing this must either be a
+supervisor of the affected person, or have sufficient privileges
+enabled.
+
+@example
+        1 99 119 0 10 0
+        @t{=1 1 @{ 49 14 17 13 8 91 5 255 1 119 255 0 0 * 119 00001111 @}}
+        1 100 1 119 250 0 10000000
+        @t{=1}
+        1 100 119 119 251 1 00000000
+        @t{=1}
+        1 99 119 0 10 0 
+        @t{=1 2 @{ 52 30 14 11 5 96 2 162 1 1 250 0 0 * 119 00000000
+               49 14 17 13 8 91 5 251 1 119 255 0 0 * 10000000 @}}
+@end example
+
+This example makes person 119 (me) a member of conference number 1 and
+changes the priority and some flags of the preexisting membership in
+conference 119. The priority is set to 250 and the conference is placed
+first in the membership list. The first and last calls of the example
+show the membership list for person 119 before and after the calls.
+
+
+
+@unnumberedsubsubsec Error codes
+
+@table @code
+@item login-first
+Login required before issuing this call.
+
+@item undefined-conference
+Conference @code{conf-no} does not exist or is secret.
+
+@item zero-conference
+@code{conference} is zero.
+
+@item undefined-person
+Person @code{pers-no} does not exist
+
+@item access-denied
+Not enough permissions or privileges to add members to conference or to
+change privileges, position or type of a preexisting membership.
+@code{conf-no}.
+
+@item permission-denied
+Person @code{pers-no} is already a member of conference @code{conf-no},
+but the person logged on is not a supervisor and does not have enough
+privileges to change the priorities of person @code{pers-no}.
+
+@end table
+
+
+
+@node get-members, set-membership-type, add-member, Protocol Requests
+@subsection get-members (10) Recommended
+
+@example
+        get-members [101] (( conf            : Conf-No;
+                             first           : INT16;
+                             no-of-members   : INT16; ))
+                -> ( result : Member-List );
+@end example
+
+This call returns a list of members of the conference @code{conf-no}.
+@code{first} is the first index in the membership to return, numbered
+from zero and up. @code{no-of-members} is the maximum number of members
+to return.
+
+Some of the elements of the result may be cleared if the person
+requesting the information does not have sufficient privileges to see
+the contents. Cleared elements simply have all fields set to zero.
+
+@example
+        1 101 1 0 100
+        @t{=1 4 @{ 7 7 00000000 8 8 00000000 9 8 00000000 }
+        @t{   10 10 00000000 @}}
+        1 101 6 0 100
+        @t{=1 4 @{ 5 5 01000000 7 7 01000000 9 8 10000000 }
+        @t{   10 10 00000000 @}}
+        1 101 6 2 2
+        @t{=1 2 @{ 9 8 10000000 10 10 00000000@}}
+@end example
+
+In this example the client first requests the firat 100 members in
+conference 1. The second request is for the first 100 members of
+conference 6. The last request is for members 2 and 3 in conference 6. 
+
+@unnumberedsubsubsec Error codes
+
+@table @code
+@item undefined-conference
+The conference @code{conf} does not exist or is secret.
+@item index-out-of-range
+@code{first} is higher than the number of members in @code{conf}.
+@end table
+
+
+@node set-membership-type, ,get-members, Protocol Requests
+@subsection set-membership-type (10) Recommended
+
+@example
+        set-membership-type [102] (( pers       : Pers-No;
+                                     conf       : Conf-No;
+                                     type       : Membership-Type; ))
+                -> ( );
+@end example
+
+This call modifies the type of a membership. The person @code{pers}
+membership in conference @code{conf} is affected. The server may impose
+arbitrary restrictions on how the membership type may be changed. 
+Typically it will only be possible to clear the @code{invitation} bit. 
+It is possible that the server will not permit the @code{secret} bit to
+be set. Attempting to set the membership type that does not agree with
+the server's restrictions will result in an error.
 
 
 
@@ -6737,12 +7087,11 @@ HTML.
 
 @menu
 * Reformattable Text (x-kom/basic) ::
-* Unreadable reformattable text (x-kom/�) ::
 * The User Area (x-kom/user-area) ::
 * Conference Lists (x-kom/conflist) ::
 @end menu
 
-@node Reformattable Text (x-kom/basic), The User Area (x-kom/�),, LysKOM Content Types
+@node Reformattable Text (x-kom/basic), The User Area (x-kom/user-area),, LysKOM Content Types
 @section Reformattable Text
 
 This type of content corresponds to the mime type x-kom/basic. It is raw
@@ -6766,15 +7115,7 @@ that matched that regexp is to be prefixed to all lines of the
 paragraph.
 @end itemize
 
-@node Unreadable reformattable text (x-kom/�), The User Area (x-kom/user-area), Reformattable Text (x-kom/basic), LysKOM Content Types
-@section Unreadable reformattable text
-
-In this text format, paragraphs are terminated by a single newline
-character. Lines may be of any length. Indentation at the beginning of
-the line should be preserved.
-
-
-@node The User Area (x-kom/user-area), Conference Lists (x-kom/conflist), Reformattable Text (x-kom/�), LysKOM Content Types
+@node The User Area (x-kom/user-area), Conference Lists (x-kom/conflist), Reformattable Text (x-kom/basic), LysKOM Content Types
 @section The User Area
 
 @node Conference Lists (x-kom/conflist), , The User Area (x-kom/user-area), LysKOM Content Types
diff --git a/doc/man/lyskomd.8 b/doc/man/lyskomd.8
index a8652a334f7ca3502ec080c6c03ebb582874e147..14d3306c2b787a61727e6f4cfccce593c0c8f3df 100644
--- a/doc/man/lyskomd.8
+++ b/doc/man/lyskomd.8
@@ -1,4 +1,4 @@
-.\" $Id: lyskomd.8,v 1.25 1997/09/13 15:31:34 byers Exp $
+.\" $Id: lyskomd.8,v 1.26 1998/06/14 14:50:23 byers Exp $
 .\" Copyright (C) 1991, 1994  Lysator Academic Computer Association.
 .\"
 .\" This file is part of the LysKOM server.
@@ -21,8 +21,8 @@
 .\"
 .\" Please mail bug reports to bug-lyskom@lysator.liu.se. 
 .\"
-.\" $Id: lyskomd.8,v 1.25 1997/09/13 15:31:34 byers Exp $
-.\" $Date: 1997/09/13 15:31:34 $
+.\" $Id: lyskomd.8,v 1.26 1998/06/14 14:50:23 byers Exp $
+.\" $Date: 1998/06/14 14:50:23 $
 .TH lyskomd 8 "January 12, 1994" "Lysator"
 .SH NAME
 lyskomd - LysKOM server
@@ -402,6 +402,23 @@ is not allowed to create any text number
 .I T
 which meets the condition
 .I T \% divident == remainder
+.TP
+.B Add members by invitation: bool
+If this is set, then adding others as members to a conference sets the
+invitation bit of the membership. If this is off, the membership bit is
+set to whatever the caller specifies. The default is to set this.
+.TP
+.B Allow secret memberships: bool
+If this is set, then memberships may be secret. Otherwise any attempt
+to create a secret membership or change an existing membership to a
+secret membership will fail. This is set by default.
+.TP
+.B allow reinvitations: bool
+If this is set, then it is possible to set the invitation bit of a
+membership even after it has been cleared. If it is not set, then the
+invitation bit of a conference type can only be set when the
+membership is created. It can be cleared at any time. This is off by
+default.
 .SH SIGNALS
 There are some signals that have a special meaning to the LysKOM
 server.
diff --git a/run-support/aux-items.conf b/run-support/aux-items.conf
index d0730800ea072b7c82560ab17c0065fdbbaccc50..56f2ecdb3d2d783a60d575361f6a3b73c50af5da 100644
--- a/run-support/aux-items.conf
+++ b/run-support/aux-items.conf
@@ -1,5 +1,5 @@
 # 
-# $Id: aux-items.conf,v 1.2 1997/10/23 12:40:41 byers Exp $
+# $Id: aux-items.conf,v 1.3 1998/06/14 14:50:24 byers Exp $
 # Copyright (C) 1994, 1995, 1996  Lysator Academic Computer Association.
 # 
 # This file is part of the LysKOM server.
@@ -39,6 +39,7 @@
     unique          = true;
     secret          = false;
     hide-creator    = false;
+    dont-garb       = false;
     inherit         = false;
     inherit-limit   = 1;
     validate        = "^.*/.*$";
@@ -53,6 +54,7 @@
 {
     secret          = false;
     hide-creator    = false;
+    dont-garb       = false;
     inherit         = false;
     inherit-limit   = 1;
 }
@@ -64,6 +66,7 @@
 
 3 : cross-reference (text, conference)
 {
+    dont-garb       = false;
     inherit         = false;
     inherit-limit   = 1;
     validate        = "^[CTP][0-9]+";
@@ -79,6 +82,7 @@
     secret          = false;
     hide-creator    = false;
     author-only     = true;
+    dont-garb       = false;
     inherit         = false;
     inherit-limit   = 1;
 }
@@ -93,6 +97,7 @@
     secret          = false;
     hide-creator    = false;
     author-only     = true;
+    dont-garb       = false;
     inherit         = false;
     inherit-limit   = 1;
 }
@@ -106,6 +111,7 @@
 {
     secret          = false;
     unique          = true;
+    dont-garb       = false;
     inherit         = false;
     inherit-limit   = 1;
 }
@@ -119,6 +125,7 @@
 {
     secret          = false;
     hide-creator    = false;
+    dont-garb       = false;
     inherit         = false;
     inherit-limit   = 1;
     permanent       = true;
@@ -131,6 +138,7 @@
 
 8 : redirect (conference)
 {
+    dont-garb       = false;
     supervisor-only = true;
     validate        = "^(LysKOM|E-mail):";
 }
@@ -145,6 +153,7 @@
     secret          = false;
     hide-creator    = false;
     supervisor-only = true;
+    dont-garb       = false;
     inherit         = false;
     inherit-limit   = 1;
 }
@@ -156,6 +165,7 @@
 
 10 : alternate-name (text, conference)
 {
+    dont-garb       = false;
     inherit         = false;
 }
 
@@ -168,6 +178,7 @@
 {
     permanent       = true;
     hide-creator    = false;
+    dont-garb       = false;
     inherit         = false;
     inherit-limit   = 1;
 }
@@ -181,6 +192,7 @@
 {
     author-only     = true;
     hide-creator    = false;
+    dont-garb       = false;
     inherit         = false;
     inherit-limit   = 1;
 }
@@ -194,6 +206,25 @@
 {
     author-only     = true;
     hide-creator    = false;
+    dont-garb       = false;
     inherit         = false;
     inherit-limit   = 1;
 }
+
+#
+# FAQ in Text
+#
+
+14 : faq-text (conference, server)
+{
+    author-only     = true;
+    hide-creator    = false;
+    secret          = false;
+    dont-garb       = false;
+    inherit         = false;
+    inherit-limit   = 1;
+    add-trigger     = mark-text();
+    delete-trigger  = unmark-text();
+    undelete-trigger= mark-text();
+}
+
diff --git a/src/include/kom-errno.h b/src/include/kom-errno.h
index 99b1c9a79c909b7b74a445a546a14ea5404d0461..5c6fe8cc48bb7eada9afa3b53e986641fdae5056 100644
--- a/src/include/kom-errno.h
+++ b/src/include/kom-errno.h
@@ -1,5 +1,5 @@
 /*
- * $Id: kom-errno.h,v 0.14 1997/09/13 15:31:39 byers Exp $
+ * $Id: kom-errno.h,v 0.15 1998/06/14 14:50:25 byers Exp $
  * Copyright (C) 1991, 1992, 1993, 1994, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -91,6 +91,7 @@ typedef enum
     KOM_INTERNAL_ERROR = 51,    /* Internal server error */
     KOM_FEATURE_DISABLED = 52,  /* Server feature is disabled */
     KOM_MESSAGE_NOT_SENT = 53,  /* Message not sent (no recipient found) */
+    KOM_INVALID_MEMBERSHIP_TYPE = 54, /* Invalid membership type */
     KOM_num_errs		/* End marker */
 } Kom_err;
 
diff --git a/src/include/kom-types.h b/src/include/kom-types.h
index dee86264455720e5c16a10814143b552acfb0491..0cf20d89575ad8ac3548ae29838a7e8313f00e33 100644
--- a/src/include/kom-types.h
+++ b/src/include/kom-types.h
@@ -1,5 +1,5 @@
 /*
- * $Id: kom-types.h,v 0.24 1997/09/13 15:31:40 byers Exp $
+ * $Id: kom-types.h,v 0.25 1998/06/14 14:50:27 byers Exp $
  * Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -224,7 +224,7 @@ typedef struct {
     unsigned int        inherit : 1; /* Copy to comments */
     unsigned int        secret : 1; /* Don't show anyone */
     unsigned int        hide_creator : 1; /* Don't show the creator */
-    unsigned int        reserved2 : 1;
+    unsigned int        dont_garb : 1; /* Don't garb object */
     unsigned int        reserved3 : 1;
     unsigned int        reserved4 : 1;
     unsigned int        reserved5 : 1;
@@ -290,7 +290,22 @@ typedef	struct {
 
 
 typedef struct {
-	Pers_no		member;
+    Bool invitation : 1;
+    Bool passive : 1;
+    Bool secret : 1;
+    Bool reserved1 : 1;
+    Bool reserved2 : 1;
+    Bool reserved3 : 1;
+    Bool reserved4 : 1;
+    Bool reserved5 : 1;
+} Membership_type;
+
+
+typedef struct {
+    Pers_no		member;
+    Pers_no             added_by; 
+    Time                added_at;
+   Membership_type     type;
 } Member;
 
 
@@ -304,6 +319,7 @@ typedef struct {
 
 
 /*  Information about a person's membership in a conference  */
+
 typedef struct {
 	Conf_no		conf_no;
 	unsigned char	priority;	/* Interrupt priority */
@@ -314,6 +330,9 @@ typedef struct {
 	unsigned short	no_of_read;
 	Local_text_no * read_texts;	/* Texts after last_text_read. Sorted
 					   in ascending order */
+        Pers_no added_by;
+        Time                added_at;
+        Membership_type type;
 } Membership;
 
 
diff --git a/src/include/services.h b/src/include/services.h
index 9761622cee5e7ac91cb633ec1028db827a283a18..8b05a1933b887c3514252cdbc947b357e1fc62bd 100644
--- a/src/include/services.h
+++ b/src/include/services.h
@@ -1,5 +1,5 @@
 /*
- * $Id: services.h,v 0.32 1997/09/13 15:31:41 byers Exp $
+ * $Id: services.h,v 0.33 1998/06/14 14:50:28 byers Exp $
  * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -173,6 +173,13 @@ KOM_( get_created_texts (Pers_no	  person,
 			 unsigned long	  no_of_texts,
 			 Text_list	* created_texts ));
 
+extern  Success
+KOM_( get_membership_old (Pers_no		  person,
+                          unsigned short	  first,
+                          unsigned short	  no_of_confs,
+                          Bool			  want_read_texts,
+                          Membership_list	* memberships ));
+
 extern  Success
 KOM_( get_membership (Pers_no		  person,
 		      unsigned short	  first,
@@ -180,8 +187,6 @@ KOM_( get_membership (Pers_no		  person,
 		      Bool		  want_read_texts,
 		      Membership_list	* memberships ));
 
-
-
 extern  Success
 KOM_( set_priv_bits (Pers_no	person,
 		     Priv_bits	privileges ));
@@ -197,6 +202,11 @@ KOM_( set_passwd (Pers_no	 person,
 
 
 /* You can query for unread texts without logging in. */
+extern  Success
+KOM_( query_read_texts_old (Pers_no	     pers_no,
+                            Conf_no	     conf_no,
+                            Membership	   * result   ));
+
 extern  Success
 KOM_( query_read_texts (Pers_no	     pers_no,
 			Conf_no	     conf_no,
@@ -306,7 +316,14 @@ extern  Success
 KOM_( get_members (Conf_no	  conf,
 		   unsigned short first,
 		   unsigned short no_of_members,
-		   Member_list	* members	));
+		   Member_list	* members
+    ));
+
+extern  Success
+KOM_( get_members_old (Conf_no	  conf,
+                       unsigned short first,
+                       unsigned short no_of_members,
+                       Member_list	* members	));
 
 
 
@@ -315,7 +332,19 @@ extern  Success
 KOM_( add_member (Conf_no		conf_no,
 		  Pers_no		pers_no,
 		  unsigned char		priority,
-		  unsigned short	where	)); /* Range of where is [0..] */
+		  unsigned short	where, /* Range of where is [0..] */
+                  Membership_type       * type ));
+
+extern  Success
+KOM_( add_member_old (Conf_no		conf_no,
+                      Pers_no		pers_no,
+                      unsigned char	priority,
+                      unsigned short	where	)); /* Range of where is [0..] */
+
+extern Success
+KOM_( set_membership_type (Pers_no      pers_no,
+                           Conf_no      conf_no,
+                           Membership_type *type   ));
 
 
 extern  Success
diff --git a/src/server/Makefile.in b/src/server/Makefile.in
index 03b18730560f65bd85072535769edc1f3573bf34..a171f061ad37d159a43ba9d04b299f7508f6446a 100755
--- a/src/server/Makefile.in
+++ b/src/server/Makefile.in
@@ -161,7 +161,7 @@ fnc-def-init.incl: fnc-def-init.awk fncdef-no-str-limit.txt
 		> fnc-def-init.incl
 
 aux-item-def.tab.c: aux-item-def.y
-	$(BISON) -d -p aux_item_def -o aux-item-def.tab.c aux-item-def.y
+	$(BISON) -d -p aux_item_def_ -o aux-item-def.tab.c aux-item-def.y
 
 aux-item-def.lex.c: aux-item-def.l
 	$(FLEX) -oaux-item-def.lex.c aux-item-def.l
diff --git a/src/server/Makefile.src b/src/server/Makefile.src
index 8322c65662ebdb907104d57e454d09f67ddfac92..d63bf87db14763075982c60fd9d47c0431048510 100644
--- a/src/server/Makefile.src
+++ b/src/server/Makefile.src
@@ -1,5 +1,5 @@
 #
-# $Id: Makefile.src,v 1.30 1997/09/13 15:31:45 byers Exp $
+# $Id: Makefile.src,v 1.31 1998/06/14 14:50:31 byers Exp $
 # Copyright (C) 1991, 1993, 1994, 1995, 1996  Lysator Academic Computer Association.
 #
 # This file is part of the LysKOM server.
@@ -114,7 +114,7 @@ fnc-def-init.incl: fnc-def-init.awk fncdef-no-str-limit.txt
 		> fnc-def-init.incl
 
 aux-item-def.tab.c: aux-item-def.y
-	$(BISON) -d -p aux_item_def -o aux-item-def.tab.c aux-item-def.y
+	$(BISON) -d -p aux_item_def_ -o aux-item-def.tab.c aux-item-def.y
 
 aux-item-def.lex.c: aux-item-def.l
 	$(FLEX) -oaux-item-def.lex.c aux-item-def.l
diff --git a/src/server/To-do b/src/server/To-do
index e77030ad9d539250f887fb130077a2a658be9c33..837004a942a9ca347a4556bbf32801725e927b7a 100644
--- a/src/server/To-do
+++ b/src/server/To-do
@@ -1,3 +1,7 @@
+dbck: Fixa s} att membership-list och member-list st{mmer |verens.
+
+-----------------
+
 Borde ha en skedjuler f|r sync&garb. Sync&garb borde returnera antalet
 millisekunder tills de skall bli anropade igen. Det minsta av dessa
 v{rden borde vara timeout till isc_getnextevent.
diff --git a/src/server/admin.c b/src/server/admin.c
index e41c407fd54d39ac363dedb4cee5273963404ae9..9d9d6a256c27d8e00af3f42211cbc1e33c093e08 100644
--- a/src/server/admin.c
+++ b/src/server/admin.c
@@ -1,5 +1,5 @@
 /*
- * $Id: admin.c,v 0.24 1997/09/13 15:31:47 byers Exp $
+ * $Id: admin.c,v 0.25 1998/06/14 14:50:34 byers Exp $
  * Copyright (C) 1991, 1993, 1994, 1995, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -28,7 +28,7 @@
  * Administrative calls.
  */
 
-static char *rcsid = "$Id: admin.c,v 0.24 1997/09/13 15:31:47 byers Exp $";
+static char *rcsid = "$Id: admin.c,v 0.25 1998/06/14 14:50:34 byers Exp $";
 #include "rcs.h"
 USE(rcsid);
 
@@ -268,6 +268,9 @@ send_message (Conf_no recipient,
 	retval = FAILURE;
 	for (ix = 0; ix < end; ix++)
 	{
+            if (conf_c->members.members[ix].type.passive)
+                continue;
+
 	    if (async_send_group_message(conf_c->members.members[ix].member,
 					 recipient,
                                          ACTPERS,
@@ -352,11 +355,16 @@ modify_server_info(Number_list      *items_to_delete,
     if (check_delete_aux_item_list(items_to_delete,
                                    &kom_info.aux_item_list)!=OK)
         return FAILURE;
-    delete_aux_item_list(items_to_delete, &kom_info.aux_item_list);
+    delete_aux_item_list(items_to_delete,
+                         &kom_info.aux_item_list,
+                         OTHER_OBJECT_TYPE,
+                         0, NULL);
 
     if (system_check_add_aux_item_list(&kom_info, items_to_add, ACTPERS) != OK)
     {
-        undelete_aux_item_list(items_to_delete, &kom_info.aux_item_list);
+        undelete_aux_item_list(items_to_delete, &kom_info.aux_item_list,
+                                   OTHER_OBJECT_TYPE,
+                                   0, NULL);
         return FAILURE;
     }
 
diff --git a/src/server/aux-item-def.l b/src/server/aux-item-def.l
index dda4269aa503f3cf95f9551f617ca24c8d214b90..9fcd6c3a0c8cd97bdc121bef9709b7bf62291d86 100644
--- a/src/server/aux-item-def.l
+++ b/src/server/aux-item-def.l
@@ -1,6 +1,6 @@
 %{
 /*
- * $Id: aux-item-def.l,v 1.1 1997/09/13 15:31:48 byers Exp $
+ * $Id: aux-item-def.l,v 1.2 1998/06/14 14:50:35 byers Exp $
  * Copyright (C) 1994, 1995, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -87,7 +87,16 @@ letterbox                           {
                                     }
 server                              {
                                         yylloc.first_line = yylineno;
-                                        RETURN SERVER;
+                                        RETURN TOK_SERVER;
+                                    }
+create                              {
+                                        yylloc.first_line = yylineno;
+                                        RETURN CREATE;
+                                    }
+
+modify                              {
+                                        yylloc.first_line = yylineno;
+                                        RETURN MODIFY;
                                     }
 
 
@@ -97,6 +106,7 @@ server                              {
 [[:alpha:]][\-[:alnum:]_]*          {
                                         char *s = yytext;
                                         do { *s=tolower(*s); } while(*(++s));
+                                        yylval.str = EMPTY_STRING;
                                         s_crea_str(&yylval.str, yytext);
                                         yylloc.first_line = yylineno;
                                         RETURN ID;
diff --git a/src/server/aux-item-def.lex.c b/src/server/aux-item-def.lex.c
index 0a366db1c1bc0f33dfc792b0ecdade13fc0f29de..ecd0a23d1faa89ce8b2aca9ae9fda14e7dc03179 100644
--- a/src/server/aux-item-def.lex.c
+++ b/src/server/aux-item-def.lex.c
@@ -20,7 +20,7 @@
 /* A lexical scanner generated by flex */
 
 /* Scanner skeleton version:
- * $Header: /home/ceder/convert-lyskomd/cvsroot/lyskom-server/src/server/Attic/aux-item-def.lex.c,v 1.1 1997/09/13 15:31:50 byers Exp $
+ * $Header: /home/ceder/convert-lyskomd/cvsroot/lyskom-server/src/server/Attic/aux-item-def.lex.c,v 1.2 1998/06/14 14:50:36 byers Exp $
  */
 
 #define FLEX_SCANNER
@@ -308,40 +308,42 @@ static void yy_fatal_error YY_PROTO(( yyconst char msg[] ));
 	*yy_cp = '\0'; \
 	yy_c_buf_p = yy_cp;
 
-#define YY_NUM_RULES 28
-#define YY_END_OF_BUFFER 29
-static yyconst short int yy_acclist[133] =
+#define YY_NUM_RULES 30
+#define YY_END_OF_BUFFER 31
+static yyconst short int yy_acclist[148] =
     {   0,
-       29,   27,   28,    9,   27,   28,    9,   28,   12,   27,
-       28,    8,   27,   28,   11,   27,   28,   10,   27,   28,
-       10,   27,   28,   10,   27,   28,   10,   27,   28,   10,
-       27,   28,   10,   27,   28,   10,   27,   28,   10,   27,
-       28,   10,   27,   28,   10,   27,   28,   25,   28,   26,
-       28,   14,   28,   25,   28,   28,    9,    8,   11,   10,
-       10,   10,   10,   10,    2,   10,   10,    1,   10,   10,
-       10,   10,   10,   25,   25,   24,   22,   24,   21,   24,
-       15,   24,   19,   24,   20,   24,   16,   24,   18,   24,
-       17,   24,   10,   10,   10,   10,   10,   10,   10,   25,
-
-       23,   15,   10,   10,   10,   10,   10,    4,   10,   15,
-       10,   10,   10,   10,   10,   10,   10,    7,   10,   13,
-       10,   10,   10,   10,    3,   10,   10,   10,    6,   10,
-        5,   10
+       31,   29,   30,   11,   29,   30,   11,   30,   14,   29,
+       30,   10,   29,   30,   13,   29,   30,   12,   29,   30,
+       12,   29,   30,   12,   29,   30,   12,   29,   30,   12,
+       29,   30,   12,   29,   30,   12,   29,   30,   12,   29,
+       30,   12,   29,   30,   12,   29,   30,   12,   29,   30,
+       27,   30,   28,   30,   16,   30,   27,   30,   30,   11,
+       10,   13,   12,   12,   12,   12,   12,   12,   12,    2,
+       12,   12,    1,   12,   12,   12,   12,   12,   27,   27,
+       26,   24,   26,   23,   26,   17,   26,   21,   26,   22,
+       26,   18,   26,   20,   26,   19,   26,   12,   12,   12,
+
+       12,   12,   12,   12,   12,   12,   27,   25,   17,   12,
+       12,   12,   12,   12,   12,   12,    4,   12,   17,   12,
+       12,   12,   12,   12,   12,   12,    8,   12,   12,   12,
+        9,   12,    7,   12,   15,   12,   12,   12,   12,    3,
+       12,   12,   12,    6,   12,    5,   12
     } ;
 
-static yyconst short int yy_accept[93] =
+static yyconst short int yy_accept[104] =
     {   0,
         1,    1,    1,    1,    1,    2,    4,    7,    9,   12,
        15,   18,   21,   24,   27,   30,   33,   36,   39,   42,
-       45,   48,   50,   52,   54,   56,   57,   58,   59,   60,
-       61,   62,   63,   64,   65,   67,   68,   70,   71,   72,
-       73,   74,   75,   76,   77,   77,   79,   81,   83,   85,
-       87,   89,   91,   93,   94,   95,   96,   97,   98,   99,
-      100,  101,  102,  103,  104,  105,  106,  107,  108,  110,
-      110,  111,  112,  113,  114,  115,  115,  116,  117,  118,
-      120,  121,  122,  123,  124,  125,  127,  128,  129,  131,
-      133,  133
-
+       45,   48,   51,   53,   55,   57,   59,   60,   61,   62,
+       63,   64,   65,   66,   67,   68,   69,   70,   72,   73,
+       75,   76,   77,   78,   79,   80,   81,   82,   82,   84,
+       86,   88,   90,   92,   94,   96,   98,   99,  100,  101,
+      102,  103,  104,  105,  106,  107,  108,  109,  110,  111,
+      112,  113,  114,  115,  116,  117,  119,  119,  120,  121,
+      122,  123,  124,  125,  126,  126,  127,  129,  130,  131,
+      133,  135,  136,  137,  138,  139,  140,  142,  143,  144,
+
+      146,  148,  148
     } ;
 
 static yyconst int yy_ec[256] =
@@ -357,9 +359,9 @@ static yyconst int yy_ec[256] =
        11,   11,   11,   11,   11,   11,   11,   11,   11,   11,
        12,   13,   14,    1,    9,    1,   15,   16,   17,   18,
 
-       19,   20,   11,   11,   21,   11,   11,   22,   11,   23,
-       24,   11,   11,   25,   26,   27,   28,   29,   11,   30,
-       31,   11,    1,    1,    1,    1,    1,    1,    1,    1,
+       19,   20,   11,   11,   21,   11,   11,   22,   23,   24,
+       25,   11,   11,   26,   27,   28,   29,   30,   11,   31,
+       32,   11,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
@@ -376,86 +378,90 @@ static yyconst int yy_ec[256] =
         1,    1,    1,    1,    1
     } ;
 
-static yyconst int yy_meta[32] =
+static yyconst int yy_meta[33] =
     {   0,
         1,    1,    2,    1,    3,    1,    1,    1,    4,    4,
         4,    1,    3,    1,    4,    4,    4,    4,    4,    4,
         4,    4,    4,    4,    4,    4,    4,    4,    4,    4,
-        4
+        4,    4
     } ;
 
-static yyconst short int yy_base[97] =
+static yyconst short int yy_base[108] =
     {   0,
-        0,    0,   29,   32,  130,  131,   36,   44,  131,    0,
-      119,    0,  104,  106,  111,  106,  100,   13,  104,   24,
-      103,    0,  131,  131,  117,   47,   56,    0,  110,    0,
-       96,   92,   95,   89,    0,   95,    0,   89,   83,   84,
-       85,    0,  108,  131,   49,  131,  131,   99,  131,  131,
-      131,  131,  131,   88,   92,   80,   78,   75,   76,   83,
-       98,   60,   90,   80,   82,   78,   77,   76,    0,   80,
-      131,   68,   70,   66,   60,   76,   61,   54,   55,    0,
-      131,   46,   50,   42,   48,    0,   31,   37,    0,    0,
-      131,   74,   78,   51,   82,   86
-
+        0,    0,   30,   33,  141,  142,   37,   45,  142,    0,
+      130,    0,   25,  118,  123,  118,  111,  110,   32,  115,
+       18,  114,    0,  142,  142,  128,   54,   51,    0,  121,
+        0,  106,  110,  101,  105,   98,  107,    0,  104,    0,
+       97,   91,   92,   93,    0,  117,  142,   56,  142,  142,
+      108,  142,  142,  142,  142,  142,   97,  101,  100,   87,
+       85,   91,   81,   82,   90,  105,   61,   97,   87,   77,
+       88,   84,   83,   81,   81,    0,   85,  142,   67,   73,
+       66,   55,   47,   51,   68,   56,    0,   54,   56,    0,
+        0,  142,   47,   51,   43,   50,    0,   35,   43,    0,
+
+        0,  142,   82,   86,   30,   90,   94
     } ;
 
-static yyconst short int yy_def[97] =
+static yyconst short int yy_def[108] =
     {   0,
-       91,    1,   92,   92,   91,   91,   91,   91,   91,   93,
-       91,   94,   94,   94,   94,   94,   94,   94,   94,   94,
-       94,   95,   91,   91,   95,   96,   91,   93,   91,   94,
-       94,   94,   94,   94,   94,   94,   94,   94,   94,   94,
-       94,   95,   95,   91,   91,   91,   91,   91,   91,   91,
-       91,   91,   91,   94,   94,   94,   94,   94,   94,   94,
-       95,   91,   91,   94,   94,   94,   94,   94,   94,   91,
-       91,   94,   94,   94,   94,   91,   94,   94,   94,   94,
-       91,   94,   94,   94,   94,   94,   94,   94,   94,   94,
-        0,   91,   91,   91,   91,   91
-
+      102,    1,  103,  103,  102,  102,  102,  102,  102,  104,
+      102,  105,  105,  105,  105,  105,  105,  105,  105,  105,
+      105,  105,  106,  102,  102,  106,  107,  102,  104,  102,
+      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
+      105,  105,  105,  105,  106,  106,  102,  102,  102,  102,
+      102,  102,  102,  102,  102,  102,  105,  105,  105,  105,
+      105,  105,  105,  105,  105,  106,  102,  102,  105,  105,
+      105,  105,  105,  105,  105,  105,  102,  102,  105,  105,
+      105,  105,  105,  105,  102,  105,  105,  105,  105,  105,
+      105,  102,  105,  105,  105,  105,  105,  105,  105,  105,
+
+      105,    0,  102,  102,  102,  102,  102
     } ;
 
-static yyconst short int yy_nxt[163] =
+static yyconst short int yy_nxt[175] =
     {   0,
         6,    7,    8,    7,    9,   10,    6,    6,    6,   11,
        12,    6,    6,    6,   12,   12,   13,   14,   12,   15,
-       12,   16,   17,   18,   12,   19,   20,   12,   12,   12,
-       21,   23,   36,   24,   23,   37,   24,   27,   27,   27,
-       25,   26,   39,   25,   26,   27,   27,   27,   40,   45,
-       62,   46,   62,   47,   30,   90,   48,   27,   27,   27,
-       89,   62,   49,   62,   88,   87,   50,   86,   85,   51,
-       84,   52,   83,   53,   22,   22,   22,   22,   28,   82,
-       28,   28,   42,   81,   80,   42,   44,   44,   44,   44,
-       79,   78,   77,   76,   75,   74,   35,   73,   72,   71,
-
-       70,   37,   69,   68,   67,   66,   65,   64,   63,   61,
-       37,   60,   59,   58,   35,   57,   56,   55,   54,   29,
-       43,   41,   38,   35,   34,   33,   32,   31,   29,   91,
-        5,   91,   91,   91,   91,   91,   91,   91,   91,   91,
-       91,   91,   91,   91,   91,   91,   91,   91,   91,   91,
-       91,   91,   91,   91,   91,   91,   91,   91,   91,   91,
-       91,   91
+       12,   16,   17,   18,   19,   12,   20,   21,   12,   12,
+       12,   22,   24,   31,   25,   24,   42,   25,   28,   28,
+       28,   26,   27,   43,   26,   27,   28,   28,   28,   32,
+       33,   39,   28,   28,   28,   40,   48,   67,   49,   67,
+       50,  101,   67,   51,   67,  100,   99,   98,   97,   52,
+       96,   95,   94,   53,   93,   92,   91,   54,   90,   55,
+       89,   56,   23,   23,   23,   23,   29,   88,   29,   29,
+       45,   87,   86,   45,   47,   47,   47,   47,   85,   84,
+
+       83,   82,   38,   81,   80,   79,   78,   77,   40,   76,
+       75,   74,   73,   72,   71,   70,   69,   68,   66,   40,
+       65,   64,   63,   38,   62,   61,   60,   59,   58,   57,
+       30,   46,   44,   41,   38,   37,   36,   35,   34,   30,
+      102,    5,  102,  102,  102,  102,  102,  102,  102,  102,
+      102,  102,  102,  102,  102,  102,  102,  102,  102,  102,
+      102,  102,  102,  102,  102,  102,  102,  102,  102,  102,
+      102,  102,  102,  102
     } ;
 
-static yyconst short int yy_chk[163] =
+static yyconst short int yy_chk[175] =
     {   0,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    3,   18,    3,    4,   18,    4,    7,    7,    7,
-        3,    3,   20,    4,    4,    8,    8,    8,   20,   26,
-       45,   26,   45,   26,   94,   88,   26,   27,   27,   27,
-       87,   62,   26,   62,   85,   84,   26,   83,   82,   26,
-       79,   26,   78,   26,   92,   92,   92,   92,   93,   77,
-       93,   93,   95,   76,   75,   95,   96,   96,   96,   96,
-       74,   73,   72,   70,   68,   67,   66,   65,   64,   63,
-
-       61,   60,   59,   58,   57,   56,   55,   54,   48,   43,
-       41,   40,   39,   38,   36,   34,   33,   32,   31,   29,
-       25,   21,   19,   17,   16,   15,   14,   13,   11,    5,
-       91,   91,   91,   91,   91,   91,   91,   91,   91,   91,
-       91,   91,   91,   91,   91,   91,   91,   91,   91,   91,
-       91,   91,   91,   91,   91,   91,   91,   91,   91,   91,
-       91,   91
+        1,    1,    3,  105,    3,    4,   21,    4,    7,    7,
+        7,    3,    3,   21,    4,    4,    8,    8,    8,   13,
+       13,   19,   28,   28,   28,   19,   27,   48,   27,   48,
+       27,   99,   67,   27,   67,   98,   96,   95,   94,   27,
+       93,   89,   88,   27,   86,   85,   84,   27,   83,   27,
+       82,   27,  103,  103,  103,  103,  104,   81,  104,  104,
+      106,   80,   79,  106,  107,  107,  107,  107,   77,   75,
+
+       74,   73,   72,   71,   70,   69,   68,   66,   65,   64,
+       63,   62,   61,   60,   59,   58,   57,   51,   46,   44,
+       43,   42,   41,   39,   37,   36,   35,   34,   33,   32,
+       30,   26,   22,   20,   18,   17,   16,   15,   14,   11,
+        5,  102,  102,  102,  102,  102,  102,  102,  102,  102,
+      102,  102,  102,  102,  102,  102,  102,  102,  102,  102,
+      102,  102,  102,  102,  102,  102,  102,  102,  102,  102,
+      102,  102,  102,  102
     } ;
 
 static yy_state_type yy_state_buf[YY_BUF_SIZE + 2], *yy_state_ptr;
@@ -476,7 +482,7 @@ char *yytext;
 #define INITIAL 0
 #line 2 "aux-item-def.l"
 /*
- * $Id: aux-item-def.lex.c,v 1.1 1997/09/13 15:31:50 byers Exp $
+ * $Id: aux-item-def.lex.c,v 1.2 1998/06/14 14:50:36 byers Exp $
  * Copyright (C) 1994, 1995, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -526,7 +532,7 @@ extern int aux_item_def_error_line;
 #define RETURN aux_item_def_error_line = yylineno; return
 #define string 1
 
-#line 530 "aux-item-def.lex.c"
+#line 536 "aux-item-def.lex.c"
 
 /* Macros after this point can all be overridden by user definitions in
  * section 1.
@@ -680,7 +686,7 @@ YY_DECL
 #line 60 "aux-item-def.l"
 
 
-#line 684 "aux-item-def.lex.c"
+#line 690 "aux-item-def.lex.c"
 
 	if ( yy_init )
 		{
@@ -728,14 +734,14 @@ yy_match:
 			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 				{
 				yy_current_state = (int) yy_def[yy_current_state];
-				if ( yy_current_state >= 92 )
+				if ( yy_current_state >= 103 )
 					yy_c = yy_meta[(unsigned int) yy_c];
 				}
 			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
 			*yy_state_ptr++ = yy_current_state;
 			++yy_cp;
 			}
-		while ( yy_base[yy_current_state] != 131 );
+		while ( yy_base[yy_current_state] != 142 );
 
 yy_find_action:
 		yy_current_state = *--yy_state_ptr;
@@ -826,42 +832,59 @@ YY_RULE_SETUP
 #line 88 "aux-item-def.l"
 {
                                         yylloc.first_line = yylineno;
-                                        RETURN SERVER;
+                                        RETURN TOK_SERVER;
                                     }
 	YY_BREAK
 case 8:
 YY_RULE_SETUP
-#line 94 "aux-item-def.l"
-/* Eat comments */
+#line 92 "aux-item-def.l"
+{
+                                        yylloc.first_line = yylineno;
+                                        RETURN CREATE;
+                                    }
 	YY_BREAK
 case 9:
 YY_RULE_SETUP
-#line 95 "aux-item-def.l"
-/* Eat whitespace */
+#line 97 "aux-item-def.l"
+{
+                                        yylloc.first_line = yylineno;
+                                        RETURN MODIFY;
+                                    }
 	YY_BREAK
 case 10:
 YY_RULE_SETUP
-#line 97 "aux-item-def.l"
+#line 103 "aux-item-def.l"
+/* Eat comments */
+	YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 104 "aux-item-def.l"
+/* Eat whitespace */
+	YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 106 "aux-item-def.l"
 {
                                         char *s = yytext;
                                         do { *s=tolower(*s); } while(*(++s));
+                                        yylval.str = EMPTY_STRING;
                                         s_crea_str(&yylval.str, yytext);
                                         yylloc.first_line = yylineno;
                                         RETURN ID;
                                     }
 	YY_BREAK
-case 11:
+case 13:
 YY_RULE_SETUP
-#line 105 "aux-item-def.l"
+#line 115 "aux-item-def.l"
 {
                                         yylloc.first_line = yylineno;
                                         yylval.num = atoi(yytext);
                                         RETURN NUMBER;
                                     }
 	YY_BREAK
-case 12:
+case 14:
 YY_RULE_SETUP
-#line 111 "aux-item-def.l"
+#line 121 "aux-item-def.l"
 {
                                         BEGIN(string); 
                                         stringBuffer = EMPTY_STRING;
@@ -870,14 +893,14 @@ YY_RULE_SETUP
 	YY_BREAK
 
 
-case 13:
+case 15:
 YY_RULE_SETUP
-#line 118 "aux-item-def.l"
+#line 128 "aux-item-def.l"
 /* Concatenate strings */
 	YY_BREAK
-case 14:
+case 16:
 YY_RULE_SETUP
-#line 119 "aux-item-def.l"
+#line 129 "aux-item-def.l"
 {
                                         BEGIN(INITIAL);
                                         yylval.str = stringBuffer;
@@ -885,9 +908,9 @@ YY_RULE_SETUP
                                         RETURN STRING;
                                     }
 	YY_BREAK
-case 15:
+case 17:
 YY_RULE_SETUP
-#line 125 "aux-item-def.l"
+#line 135 "aux-item-def.l"
 {
                                         unsigned int tmp;
                                         sscanf(yytext+1, "%o", &tmp);
@@ -904,59 +927,59 @@ YY_RULE_SETUP
                                         }
                                     }
 	YY_BREAK
-case 16:
+case 18:
 YY_RULE_SETUP
-#line 140 "aux-item-def.l"
+#line 150 "aux-item-def.l"
 s_strcat(&stringBuffer, s_fcrea_str("\n"));
 	YY_BREAK
-case 17:
+case 19:
 YY_RULE_SETUP
-#line 141 "aux-item-def.l"
+#line 151 "aux-item-def.l"
 s_strcat(&stringBuffer, s_fcrea_str("\t"));
 	YY_BREAK
-case 18:
+case 20:
 YY_RULE_SETUP
-#line 142 "aux-item-def.l"
+#line 152 "aux-item-def.l"
 s_strcat(&stringBuffer, s_fcrea_str("\r"));
 	YY_BREAK
-case 19:
+case 21:
 YY_RULE_SETUP
-#line 143 "aux-item-def.l"
+#line 153 "aux-item-def.l"
 s_strcat(&stringBuffer, s_fcrea_str("\b"));
 	YY_BREAK
-case 20:
+case 22:
 YY_RULE_SETUP
-#line 144 "aux-item-def.l"
+#line 154 "aux-item-def.l"
 s_strcat(&stringBuffer, s_fcrea_str("\f"));
 	YY_BREAK
-case 21:
+case 23:
 YY_RULE_SETUP
-#line 145 "aux-item-def.l"
+#line 155 "aux-item-def.l"
 s_strcat(&stringBuffer, s_fcrea_str("\'"));
 	YY_BREAK
-case 22:
+case 24:
 YY_RULE_SETUP
-#line 146 "aux-item-def.l"
+#line 156 "aux-item-def.l"
 s_strcat(&stringBuffer, s_fcrea_str("\""));
 	YY_BREAK
-case 23:
+case 25:
 YY_RULE_SETUP
-#line 147 "aux-item-def.l"
+#line 157 "aux-item-def.l"
 /* Eat escaped whitespace */
 	YY_BREAK
-case 24:
+case 26:
 YY_RULE_SETUP
-#line 148 "aux-item-def.l"
+#line 158 "aux-item-def.l"
 s_strcat(&stringBuffer, s_fcrea_str(yytext+1));
 	YY_BREAK
-case 25:
+case 27:
 YY_RULE_SETUP
-#line 149 "aux-item-def.l"
+#line 159 "aux-item-def.l"
 s_strcat(&stringBuffer, s_fcrea_str(yytext));
 	YY_BREAK
-case 26:
+case 28:
 YY_RULE_SETUP
-#line 150 "aux-item-def.l"
+#line 160 "aux-item-def.l"
 {
                                         yyerror("unterminated string",
                                                  yylloc.first_line);
@@ -964,17 +987,17 @@ YY_RULE_SETUP
                                     }
 	YY_BREAK
 
-case 27:
+case 29:
 YY_RULE_SETUP
-#line 157 "aux-item-def.l"
+#line 167 "aux-item-def.l"
 RETURN yytext[0];
 	YY_BREAK
-case 28:
+case 30:
 YY_RULE_SETUP
-#line 159 "aux-item-def.l"
+#line 169 "aux-item-def.l"
 ECHO;
 	YY_BREAK
-#line 978 "aux-item-def.lex.c"
+#line 1001 "aux-item-def.lex.c"
 			case YY_STATE_EOF(INITIAL):
 			case YY_STATE_EOF(string):
 				yyterminate();
@@ -1264,7 +1287,7 @@ static yy_state_type yy_get_previous_state()
 		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 			{
 			yy_current_state = (int) yy_def[yy_current_state];
-			if ( yy_current_state >= 92 )
+			if ( yy_current_state >= 103 )
 				yy_c = yy_meta[(unsigned int) yy_c];
 			}
 		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
@@ -1294,11 +1317,11 @@ yy_state_type yy_current_state;
 	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 		{
 		yy_current_state = (int) yy_def[yy_current_state];
-		if ( yy_current_state >= 92 )
+		if ( yy_current_state >= 103 )
 			yy_c = yy_meta[(unsigned int) yy_c];
 		}
 	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-	yy_is_jam = (yy_current_state == 91);
+	yy_is_jam = (yy_current_state == 102);
 	if ( ! yy_is_jam )
 		*yy_state_ptr++ = yy_current_state;
 
@@ -1859,5 +1882,5 @@ int main()
 	return 0;
 	}
 #endif
-#line 159 "aux-item-def.l"
+#line 169 "aux-item-def.l"
 
diff --git a/src/server/aux-item-def.tab.c b/src/server/aux-item-def.tab.c
index f93075c490cbbbcd823391b3df30b1b06c575729..88d7528fd220394b0ed499fec290b9c3c26260d7 100644
--- a/src/server/aux-item-def.tab.c
+++ b/src/server/aux-item-def.tab.c
@@ -22,13 +22,15 @@
 #define	TEXT	263
 #define	CONFERENCE	264
 #define	LETTERBOX	265
-#define	SERVER	266
+#define	TOK_SERVER	266
 #define	VOID	267
+#define	CREATE	268
+#define	MODIFY	269
 
 #line 1 "aux-item-def.y"
 
 /*
- * $Id: aux-item-def.tab.c,v 1.1 1997/09/13 15:31:51 byers Exp $
+ * $Id: aux-item-def.tab.c,v 1.2 1998/06/14 14:50:39 byers Exp $
  * Copyright (C) 1994, 1995, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -69,7 +71,14 @@
 #include "kom-types.h"
 #include "aux-items.h"
 #include "s-string.h"
+#include "server/smalloc.h"
 #include "lyskomd.h"
+#include "debug.h"
+#include "log.h"
+
+BUGDECL;    
+
+#define YYDEBUG 1
     
 static Aux_item_definition      def;
 static Bool                     errorFlag = FALSE;
@@ -119,11 +128,17 @@ static int  aux_item_def_check_assign(char  *,
                                       struct aux_item_def_value_type *,
                                       int);
 static char *aux_item_def_typename(int);
+short aux_item_def_check_trigger(char *check_name,
+                                 int type,
+                                 String trigger_name,
+                                 String function_name,
+                                 unsigned long *counter,
+                                 Aux_item_trigger **triggers);
 
 
 #define YYERROR_VERBOSE
 
-#line 99 "aux-item-def.y"
+#line 112 "aux-item-def.y"
 typedef union
 {
     String          str;
@@ -165,26 +180,26 @@ typedef
 
 
 
-#define	YYFINAL		32
+#define	YYFINAL		38
 #define	YYFLAG		-32768
-#define	YYNTBASE	21
+#define	YYNTBASE	23
 
-#define YYTRANSLATE(x) ((unsigned)(x) <= 267 ? yytranslate[x] : 29)
+#define YYTRANSLATE(x) ((unsigned)(x) <= 269 ? yytranslate[x] : 32)
 
 static const char yytranslate[] = {     0,
      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,     2,     2,    16,
-    17,     2,     2,    18,     2,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,    15,    20,     2,
-    19,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,    18,
+    19,     2,     2,    20,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,    17,    22,     2,
+    21,     2,     2,     2,     2,     2,     2,     2,     2,     2,
      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,    13,     2,    14,     2,     2,     2,     2,     2,
+     2,     2,    15,     2,    16,     2,     2,     2,     2,     2,
      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
@@ -198,30 +213,34 @@ static const char yytranslate[] = {     0,
      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
      2,     2,     2,     2,     2,     1,     2,     3,     4,     5,
-     6,     7,     8,     9,    10,    11,    12
+     6,     7,     8,     9,    10,    11,    12,    13,    14
 };
 
 #if YYDEBUG != 0
 static const short yyprhs[] = {     0,
-     0,     3,     4,     9,    16,    24,    28,    30,    32,    34,
-    36,    38,    41,    44,    45,    50,    52,    54,    56
+     0,     3,     4,     9,    16,    24,    28,    30,    33,    36,
+    39,    41,    44,    47,    48,    51,    54,    55,    60,    62,
+    64,    66,    70
 };
 
-static const short yyrhs[] = {    21,
-    22,     0,     0,    23,    13,    26,    14,     0,     3,    15,
-     5,    16,    24,    17,     0,     3,    15,     5,    16,    24,
-    17,     7,     0,    24,    18,    25,     0,    25,     0,     8,
-     0,     9,     0,    10,     0,    11,     0,    26,    27,     0,
-    26,     1,     0,     0,     5,    19,    28,    20,     0,     4,
-     0,     6,     0,     3,     0,    12,     0
+static const short yyrhs[] = {    23,
+    24,     0,     0,    25,    15,    29,    16,     0,     3,    17,
+     5,    18,    26,    19,     0,     3,    17,     5,    18,    26,
+    19,     7,     0,    26,    20,    27,     0,    27,     0,    28,
+     8,     0,    28,     9,     0,    28,    10,     0,    11,     0,
+    28,    13,     0,    28,    14,     0,     0,    29,    30,     0,
+    29,     1,     0,     0,     5,    21,    31,    22,     0,     4,
+     0,     6,     0,     3,     0,     5,    18,    19,     0,    12,
+     0
 };
 
 #endif
 
 #if YYDEBUG != 0
 static const short yyrline[] = { 0,
-   122,   123,   126,   133,   141,   151,   152,   155,   156,   157,
-   158,   161,   162,   163,   166,   212,   213,   214,   215
+   137,   138,   141,   148,   161,   171,   172,   175,   176,   177,
+   179,   182,   183,   184,   186,   187,   188,   191,   290,   291,
+   292,   293,   294
 };
 #endif
 
@@ -229,61 +248,63 @@ static const short yyrline[] = { 0,
 #if YYDEBUG != 0 || defined (YYERROR_VERBOSE)
 
 static const char * const yytname[] = {   "$","error","$undefined.","NUMBER",
-"BOOLEAN","ID","STRING","DISABLED","TEXT","CONFERENCE","LETTERBOX","SERVER",
-"VOID","'{'","'}'","':'","'('","')'","','","'='","';'","items","item","head",
-"targets","target","body","assign","value", NULL
+"BOOLEAN","ID","STRING","DISABLED","TEXT","CONFERENCE","LETTERBOX","TOK_SERVER",
+"VOID","CREATE","MODIFY","'{'","'}'","':'","'('","')'","','","'='","';'","items",
+"item","head","targets","target","action","body","assign","value", NULL
 };
 #endif
 
 static const short yyr1[] = {     0,
-    21,    21,    22,    23,    23,    24,    24,    25,    25,    25,
-    25,    26,    26,    26,    27,    28,    28,    28,    28
+    23,    23,    24,    25,    25,    26,    26,    27,    27,    27,
+    27,    28,    28,    28,    29,    29,    29,    30,    31,    31,
+    31,    31,    31
 };
 
 static const short yyr2[] = {     0,
-     2,     0,     4,     6,     7,     3,     1,     1,     1,     1,
-     1,     2,     2,     0,     4,     1,     1,     1,     1
+     2,     0,     4,     6,     7,     3,     1,     2,     2,     2,
+     1,     2,     2,     0,     2,     2,     0,     4,     1,     1,
+     1,     3,     1
 };
 
 static const short yydefact[] = {     2,
-     0,     0,     1,     0,     0,    14,     0,     0,     0,    13,
-     0,     3,    12,     8,     9,    10,    11,     0,     7,     0,
-     4,     0,    18,    16,    17,    19,     0,     5,     6,    15,
-     0,     0
+     0,     0,     1,     0,     0,    17,     0,     0,    14,    16,
+     0,     3,    15,    11,     0,     7,     0,     0,     4,    14,
+     8,     9,    10,    12,    13,    21,    19,     0,    20,    23,
+     0,     5,     6,     0,    18,    22,     0,     0
 };
 
 static const short yydefgoto[] = {     1,
-     3,     4,    18,    19,     8,    13,    27
+     3,     4,    15,    16,    17,     8,    13,    31
 };
 
 static const short yypact[] = {-32768,
-    15,   -12,-32768,    -6,    11,-32768,     3,    -1,     1,-32768,
-    -2,-32768,-32768,-32768,-32768,-32768,-32768,   -16,-32768,     2,
-    13,     1,-32768,-32768,-32768,-32768,     4,-32768,-32768,-32768,
-    21,-32768
+    18,   -14,-32768,    -6,     5,-32768,     1,    -1,     9,-32768,
+     4,-32768,-32768,-32768,   -18,-32768,     3,     2,    15,     9,
+-32768,-32768,-32768,-32768,-32768,-32768,-32768,     6,-32768,-32768,
+     7,-32768,-32768,     8,-32768,-32768,    23,-32768
 };
 
 static const short yypgoto[] = {-32768,
--32768,-32768,-32768,     0,-32768,-32768,-32768
+-32768,-32768,-32768,    10,-32768,-32768,-32768,-32768
 };
 
 
-#define	YYLAST		24
+#define	YYLAST		30
 
 
 static const short yytable[] = {    10,
-    21,    22,     5,    11,    23,    24,     6,    25,    14,    15,
-    16,    17,    12,    26,    31,     7,    20,     2,     9,    28,
-    32,    29,     0,    30
+    19,    20,     5,    11,    26,    27,    28,    29,     6,     7,
+    21,    22,    23,    30,    12,    24,    25,    37,     9,    14,
+     2,    32,    38,    34,    18,     0,    36,     0,    35,    33
 };
 
 static const short yycheck[] = {     1,
-    17,    18,    15,     5,     3,     4,    13,     6,     8,     9,
-    10,    11,    14,    12,     0,     5,    19,     3,    16,     7,
-     0,    22,    -1,    20
+    19,    20,    17,     5,     3,     4,     5,     6,    15,     5,
+     8,     9,    10,    12,    16,    13,    14,     0,    18,    11,
+     3,     7,     0,    18,    21,    -1,    19,    -1,    22,    20
 };
 /* -*-C-*-  Note some compilers choke on comments on `#line' lines.  */
-#line 3 "/sw/gnu/share/bison.simple"
+#line 3 "/usr/lib/bison.simple"
 
 /* Skeleton output parser for bison,
    Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc.
@@ -476,7 +497,7 @@ __yy_memcpy (char *to, char *from, int count)
 #endif
 #endif
 
-#line 196 "/sw/gnu/share/bison.simple"
+#line 196 "/usr/lib/bison.simple"
 
 /* The user can define YYPARSE_PARAM as the name of an argument to be passed
    into yyparse.  The argument should have type void *.
@@ -781,24 +802,29 @@ yyreduce:
   switch (yyn) {
 
 case 3:
-#line 127 "aux-item-def.y"
+#line 142 "aux-item-def.y"
 {
                 aux_item_definition_add(&def);
                 def = empty_aux_item_definition;
             ;
     break;}
 case 4:
-#line 134 "aux-item-def.y"
+#line 149 "aux-item-def.y"
 {
                 def.tag = yyvsp[-5].num;
                 def.name = s_crea_c_str(yyvsp[-3].str);
+                if (buglevel)
+                {
+                    log("Parsing definition of aux-iem %ld (%s)\n",
+                        def.tag, def.name);
+                }
                 s_clear(&(yyvsp[-3].str));
                 yyvsp[-3].str = EMPTY_STRING;
                 yylval.str = EMPTY_STRING;
             ;
     break;}
 case 5:
-#line 142 "aux-item-def.y"
+#line 162 "aux-item-def.y"
 {
                 def.tag = 0;
                 def.name = s_crea_c_str(yyvsp[-4].str);
@@ -808,28 +834,41 @@ case 5:
             ;
     break;}
 case 8:
-#line 155 "aux-item-def.y"
-{ def.texts = TRUE; ;
+#line 175 "aux-item-def.y"
+{ def.texts = TRUE; def.text_a = yyvsp[-1].num; ;
     break;}
 case 9:
-#line 156 "aux-item-def.y"
-{ def.confs = TRUE; ;
+#line 176 "aux-item-def.y"
+{ def.confs = TRUE; def.conf_a = yyvsp[-1].num; ;
     break;}
 case 10:
-#line 157 "aux-item-def.y"
-{ def.letterboxes = TRUE; ;
+#line 177 "aux-item-def.y"
+{ def.letterboxes = TRUE;
+                                        def.conf_a = yyvsp[-1].num; ;
     break;}
 case 11:
-#line 158 "aux-item-def.y"
+#line 179 "aux-item-def.y"
 { def.system = TRUE; ;
     break;}
-case 15:
-#line 167 "aux-item-def.y"
+case 12:
+#line 182 "aux-item-def.y"
+{ yyval.num = yyvsp[-1].num | AUX_ITEM_ADD_ON_CREATE; ;
+    break;}
+case 13:
+#line 183 "aux-item-def.y"
+{ yyval.num = yyvsp[-1].num | AUX_ITEM_ADD_ON_MODIFY; ;
+    break;}
+case 14:
+#line 184 "aux-item-def.y"
+{ yyval.num = 0; ;
+    break;}
+case 18:
+#line 192 "aux-item-def.y"
 {
                 int found = 0;
 
                 CHK_ASSIGN("author-only", author_only, BOOLEAN,
-                           yyvsp[-3].str, yyvsp[-1].value,yylsp[-1].first_line);
+                           yyvsp[-3].str, yyvsp[-1].value, yylsp[-1].first_line);
                 CHK_ASSIGN("supervisor-only", supervisor_only,
                            BOOLEAN, yyvsp[-3].str, yyvsp[-1].value, yylsp[-1].first_line);
                 CHK_ASSIGN("inherit-limit", inherit_limit, NUMBER,
@@ -844,10 +883,63 @@ case 15:
                 CHK_FLAG_A("secret", secret, yyvsp[-3].str, yyvsp[-1].value, yylsp[-1].first_line);
                 CHK_FLAG_A("hide-creator", hide_creator,
                            yyvsp[-3].str, yyvsp[-1].value, yylsp[-1].first_line);
-                CHK_FLAG_A("reserved-1", reserved2, yyvsp[-3].str, yyvsp[-1].value, yylsp[-1].first_line);
+                CHK_FLAG_A("dont-garb", dont_garb, yyvsp[-3].str, yyvsp[-1].value, yylsp[-1].first_line);
                 CHK_FLAG_A("reserved-2", reserved3, yyvsp[-3].str, yyvsp[-1].value, yylsp[-1].first_line); 
                 CHK_FLAG_A("reserved-3", reserved4, yyvsp[-3].str, yyvsp[-1].value, yylsp[-1].first_line); 
                 CHK_FLAG_A("reserved-4", reserved5, yyvsp[-3].str, yyvsp[-1].value, yylsp[-1].first_line); 
+
+                if (s_strcmp(s_fcrea_str("add-trigger"), yyvsp[-3].str) == 0)
+                {
+                    found = 1;
+                    if (yyvsp[-1].value.type != ID)
+                    {
+                        yyerror("invalid type: expected %s, got %s", \
+                                aux_item_def_typename(BOOLEAN), \
+                                aux_item_def_typename(ID)); \
+                        found = 0;
+                    }
+                }
+
+                if (s_strcmp(s_fcrea_str("delete-trigger"), yyvsp[-3].str) == 0)
+                {
+                    found = 1;
+                    if (yyvsp[-1].value.type != ID)
+                    {
+                        yyerror("invalid type: expected %s, got %s", \
+                                aux_item_def_typename(BOOLEAN), \
+                                aux_item_def_typename(ID)); \
+                        found = 0;
+                    }
+                }
+
+
+                found = found ? 1 :
+                    aux_item_def_check_trigger("delete-trigger",
+                                               yyvsp[-1].value.type,
+                                               yyvsp[-3].str,
+                                               yyvsp[-1].value.val.str,
+                                               &def.num_delete_triggers,
+                                               &def.delete_triggers);
+
+
+                found = found ? 1 :
+                    aux_item_def_check_trigger("undelete-trigger",
+                                               yyvsp[-1].value.type,
+                                               yyvsp[-3].str,
+                                               yyvsp[-1].value.val.str,
+                                               &def.num_undelete_triggers,
+                                               &def.undelete_triggers);
+
+
+                found = found ? 1 :
+                    aux_item_def_check_trigger("add-trigger",
+                                               yyvsp[-1].value.type,
+                                               yyvsp[-3].str,
+                                               yyvsp[-1].value.val.str,
+                                               &def.num_add_triggers,
+                                               &def.add_triggers);
+
+
                 if (found == 0)
                 {
                     char *tmp;
@@ -869,25 +961,29 @@ case 15:
                 yylval.str = EMPTY_STRING;
             ;
     break;}
-case 16:
-#line 212 "aux-item-def.y"
+case 19:
+#line 290 "aux-item-def.y"
 { yyval.value.val.num = yyvsp[0].num; yyval.value.type = BOOLEAN; ;
     break;}
-case 17:
-#line 213 "aux-item-def.y"
+case 20:
+#line 291 "aux-item-def.y"
 { yyval.value.val.str = yyvsp[0].str; yyval.value.type = STRING;  ;
     break;}
-case 18:
-#line 214 "aux-item-def.y"
+case 21:
+#line 292 "aux-item-def.y"
 { yyval.value.val.num = yyvsp[0].num; yyval.value.type = NUMBER;  ;
     break;}
-case 19:
-#line 215 "aux-item-def.y"
+case 22:
+#line 293 "aux-item-def.y"
+{ yyval.value.val.str = yyvsp[-2].str; yyval.value.type = ID;;
+    break;}
+case 23:
+#line 294 "aux-item-def.y"
 { YYERROR; ;
     break;}
 }
    /* the action file gets copied in in place of this dollarsign */
-#line 498 "/sw/gnu/share/bison.simple"
+#line 498 "/usr/lib/bison.simple"
 
   yyvsp -= yylen;
   yyssp -= yylen;
@@ -1083,7 +1179,7 @@ yyerrhandle:
   yystate = yyn;
   goto yynewstate;
 }
-#line 218 "aux-item-def.y"
+#line 297 "aux-item-def.y"
 
 
 #if defined(HAVE_VFPRINTF) && defined(HAVE_STDARG_H)
@@ -1120,6 +1216,7 @@ static char *aux_item_def_typename(int type)
     case STRING:  return "string";
     case NUMBER:  return "number";
     case BOOLEAN: return "boolean";
+    case ID:      return "identifier";
     default:
         return "unknown";
     }
@@ -1167,6 +1264,51 @@ static int  aux_item_def_check_assign(char  *id,
     }
 }
 
+short aux_item_def_check_trigger(char *check_name,
+                                 int type,
+                                 String trigger_name,
+                                 String function_name,
+                                 unsigned long *counter,
+                                 Aux_item_trigger **triggers)
+{
+    Aux_item_trigger trigger;
+    char *tmp_string;
+
+    if (s_strcmp(s_fcrea_str(check_name), trigger_name) == 0)
+    {
+        if (type != ID)
+        {
+            yyerror("invalid type: expected %s, got %s", 
+                    aux_item_def_typename(ID), 
+                    aux_item_def_typename(type)); 
+            return 0;
+        }
+
+        tmp_string = s_crea_c_str(function_name);
+        trigger = aux_item_find_trigger(tmp_string);
+
+        if (trigger == NULL)
+        {
+            yyerror("undefined function: %s",
+                    tmp_string);
+            sfree(tmp_string);
+            return 1;
+        }
+
+        sfree(tmp_string);
+
+        *counter += 1;
+        *triggers =
+            srealloc(*triggers,
+                     *counter *
+                     sizeof(Aux_item_trigger));
+        *triggers[*counter-1] = trigger;
+
+        return 1;
+    }
+    return 0;
+}
+
 void parse_aux_item_definitions(char *file)
 {
     extern FILE *yyin;
diff --git a/src/server/aux-item-def.tab.h b/src/server/aux-item-def.tab.h
index 91cd2a2355b6e3a165b59b5e2366a4302e80a0fc..50fe35ec75380af835069de5c214229b3a7a1bad 100644
--- a/src/server/aux-item-def.tab.h
+++ b/src/server/aux-item-def.tab.h
@@ -37,8 +37,10 @@ typedef
 #define	TEXT	263
 #define	CONFERENCE	264
 #define	LETTERBOX	265
-#define	SERVER	266
+#define	TOK_SERVER	266
 #define	VOID	267
+#define	CREATE	268
+#define	MODIFY	269
 
 
 extern YYSTYPE aux_item_def_lval;
diff --git a/src/server/aux-item-def.y b/src/server/aux-item-def.y
index 0a307fc7a655c2a66d2882ae314455ae3c05708a..971b7a5ecee314874346692da2d6103cf8652516 100644
--- a/src/server/aux-item-def.y
+++ b/src/server/aux-item-def.y
@@ -1,6 +1,6 @@
 %{
 /*
- * $Id: aux-item-def.y,v 1.1 1997/09/13 15:31:53 byers Exp $
+ * $Id: aux-item-def.y,v 1.2 1998/06/14 14:50:41 byers Exp $
  * Copyright (C) 1994, 1995, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -41,7 +41,14 @@
 #include "kom-types.h"
 #include "aux-items.h"
 #include "s-string.h"
+#include "server/smalloc.h"
 #include "lyskomd.h"
+#include "debug.h"
+#include "log.h"
+
+BUGDECL;    
+
+#define YYDEBUG 1
     
 static Aux_item_definition      def;
 static Bool                     errorFlag = FALSE;
@@ -91,6 +98,12 @@ static int  aux_item_def_check_assign(char  *,
                                       struct aux_item_def_value_type *,
                                       int);
 static char *aux_item_def_typename(int);
+short aux_item_def_check_trigger(char *check_name,
+                                 int type,
+                                 String trigger_name,
+                                 String function_name,
+                                 unsigned long *counter,
+                                 Aux_item_trigger **triggers);
 
 
 #define YYERROR_VERBOSE
@@ -113,9 +126,11 @@ static char *aux_item_def_typename(int);
 
 %token <num>    NUMBER BOOLEAN
 %token <str>    ID STRING
-%token          DISABLED TEXT CONFERENCE LETTERBOX SERVER VOID
+%token          DISABLED TEXT CONFERENCE LETTERBOX TOK_SERVER
+%token          VOID CREATE MODIFY
 
 %type <value>   value
+%type <num>     action
 
 %%
 
@@ -134,6 +149,11 @@ head        :       NUMBER ':' ID '(' targets ')'
             {
                 def.tag = $1;
                 def.name = s_crea_c_str($3);
+                if (buglevel)
+                {
+                    log("Parsing definition of aux-iem %ld (%s)\n",
+                        def.tag, def.name);
+                }
                 s_clear(&($3));
                 $3 = EMPTY_STRING;
                 yylval.str = EMPTY_STRING;
@@ -152,12 +172,17 @@ targets     :       targets ',' target
             |       target
             ;
 
-target      :       TEXT                { def.texts = TRUE; }
-            |       CONFERENCE          { def.confs = TRUE; }
-            |       LETTERBOX           { def.letterboxes = TRUE; }
-            |       SERVER              { def.system = TRUE; }
+target      :       action TEXT       { def.texts = TRUE; def.text_a = $1; }
+            |       action CONFERENCE { def.confs = TRUE; def.conf_a = $1; }
+            |       action LETTERBOX  { def.letterboxes = TRUE;
+                                        def.conf_a = $1; }
+            |       TOK_SERVER        { def.system = TRUE; }
             ;
 
+action      :       action CREATE     { $$ = $1 | AUX_ITEM_ADD_ON_CREATE; }
+            |       action MODIFY     { $$ = $1 | AUX_ITEM_ADD_ON_MODIFY; }
+            |       /* Empty */       { $$ = 0; }
+
 body        :       body assign
             |       body error
             |       /* Empty */
@@ -168,7 +193,7 @@ assign      :   ID '=' value ';'
                 int found = 0;
 
                 CHK_ASSIGN("author-only", author_only, BOOLEAN,
-                           $1, $3,@3.first_line);
+                           $1, $3, @3.first_line);
                 CHK_ASSIGN("supervisor-only", supervisor_only,
                            BOOLEAN, $1, $3, @3.first_line);
                 CHK_ASSIGN("inherit-limit", inherit_limit, NUMBER,
@@ -183,10 +208,63 @@ assign      :   ID '=' value ';'
                 CHK_FLAG_A("secret", secret, $1, $3, @3.first_line);
                 CHK_FLAG_A("hide-creator", hide_creator,
                            $1, $3, @3.first_line);
-                CHK_FLAG_A("reserved-1", reserved2, $1, $3, @3.first_line);
+                CHK_FLAG_A("dont-garb", dont_garb, $1, $3, @3.first_line);
                 CHK_FLAG_A("reserved-2", reserved3, $1, $3, @3.first_line); 
                 CHK_FLAG_A("reserved-3", reserved4, $1, $3, @3.first_line); 
                 CHK_FLAG_A("reserved-4", reserved5, $1, $3, @3.first_line); 
+
+                if (s_strcmp(s_fcrea_str("add-trigger"), $1) == 0)
+                {
+                    found = 1;
+                    if ($3.type != ID)
+                    {
+                        yyerror("invalid type: expected %s, got %s", \
+                                aux_item_def_typename(BOOLEAN), \
+                                aux_item_def_typename(ID)); \
+                        found = 0;
+                    }
+                }
+
+                if (s_strcmp(s_fcrea_str("delete-trigger"), $1) == 0)
+                {
+                    found = 1;
+                    if ($3.type != ID)
+                    {
+                        yyerror("invalid type: expected %s, got %s", \
+                                aux_item_def_typename(BOOLEAN), \
+                                aux_item_def_typename(ID)); \
+                        found = 0;
+                    }
+                }
+
+
+                found = found ? 1 :
+                    aux_item_def_check_trigger("delete-trigger",
+                                               $3.type,
+                                               $1,
+                                               $3.val.str,
+                                               &def.num_delete_triggers,
+                                               &def.delete_triggers);
+
+
+                found = found ? 1 :
+                    aux_item_def_check_trigger("undelete-trigger",
+                                               $3.type,
+                                               $1,
+                                               $3.val.str,
+                                               &def.num_undelete_triggers,
+                                               &def.undelete_triggers);
+
+
+                found = found ? 1 :
+                    aux_item_def_check_trigger("add-trigger",
+                                               $3.type,
+                                               $1,
+                                               $3.val.str,
+                                               &def.num_add_triggers,
+                                               &def.add_triggers);
+
+
                 if (found == 0)
                 {
                     char *tmp;
@@ -212,6 +290,7 @@ assign      :   ID '=' value ';'
 value       :       BOOLEAN             { $$.val.num = $1; $$.type = BOOLEAN; }
             |       STRING              { $$.val.str = $1; $$.type = STRING;  }
             |       NUMBER              { $$.val.num = $1; $$.type = NUMBER;  }
+            |       ID '(' ')'          { $$.val.str = $1; $$.type = ID;}
             |       VOID                { YYERROR; }
             ;
 
@@ -251,6 +330,7 @@ static char *aux_item_def_typename(int type)
     case STRING:  return "string";
     case NUMBER:  return "number";
     case BOOLEAN: return "boolean";
+    case ID:      return "identifier";
     default:
         return "unknown";
     }
@@ -298,6 +378,51 @@ static int  aux_item_def_check_assign(char  *id,
     }
 }
 
+short aux_item_def_check_trigger(char *check_name,
+                                 int type,
+                                 String trigger_name,
+                                 String function_name,
+                                 unsigned long *counter,
+                                 Aux_item_trigger **triggers)
+{
+    Aux_item_trigger trigger;
+    char *tmp_string;
+
+    if (s_strcmp(s_fcrea_str(check_name), trigger_name) == 0)
+    {
+        if (type != ID)
+        {
+            yyerror("invalid type: expected %s, got %s", 
+                    aux_item_def_typename(ID), 
+                    aux_item_def_typename(type)); 
+            return 0;
+        }
+
+        tmp_string = s_crea_c_str(function_name);
+        trigger = aux_item_find_trigger(tmp_string);
+
+        if (trigger == NULL)
+        {
+            yyerror("undefined function: %s",
+                    tmp_string);
+            sfree(tmp_string);
+            return 1;
+        }
+
+        sfree(tmp_string);
+
+        *counter += 1;
+        *triggers =
+            srealloc(*triggers,
+                     *counter *
+                     sizeof(Aux_item_trigger));
+        *triggers[*counter-1] = trigger;
+
+        return 1;
+    }
+    return 0;
+}
+
 void parse_aux_item_definitions(char *file)
 {
     extern FILE *yyin;
diff --git a/src/server/aux-items.c b/src/server/aux-items.c
index 3b1663fef4b1425c16591368d3d4c919949c216f..7457bfed119491d636414f83191fb31d761f778e 100644
--- a/src/server/aux-items.c
+++ b/src/server/aux-items.c
@@ -1,5 +1,5 @@
 /*
- * $Id: aux-items.c,v 1.2 1997/10/23 12:37:20 byers Exp $
+ * $Id: aux-items.c,v 1.3 1998/06/14 14:50:42 byers Exp $
  * Copyright (C) 1994, 1995, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -56,6 +56,18 @@ static Aux_item_definition compiled_aux_items[] =
 {
 };
 
+
+void aux_item_trigger_mark_text(Aux_item_trigger_data *);
+void aux_item_trigger_unmark_text(Aux_item_trigger_data *);
+
+Aux_item_trigger_mapping
+aux_item_triggers [] =
+{
+    { "mark-text", aux_item_trigger_mark_text },
+    { "unmark-text", aux_item_trigger_unmark_text },
+    { NULL, NULL }
+};
+
 Aux_item_definition empty_aux_item_definition =
 {
     NULL,                   /* Name */           
@@ -68,11 +80,16 @@ Aux_item_definition empty_aux_item_definition =
     0,                      /* Can't delete */   
     0,                      /* Inherit limit */  
     FALSE,                  /* Texts */
+    0,
     FALSE,                  /* Confs */
+    0,
     FALSE,                  /* Letterbox */
     FALSE,                  /* System */
     NULL,                   /* Validate */
     NULL,                   /* Cached regexp */
+    0, NULL,
+    0, NULL,
+    0, NULL,
     NULL                    /* Next */
 };
 
@@ -96,11 +113,17 @@ static Aux_item_definition simple_aux_item =
     0,                      /* Can't delete */   
     0,                      /* Inherit limit */  
     TRUE,                   /* Texts */
+    0,
     TRUE,                   /* Confs */
+    0,
     TRUE,                   /* Letterbox */
     TRUE,                   /* System */
     NULL,                   /* Validate regexp */       
-    NULL                    /* Cached regexp */
+    NULL,                   /* Cached regexp */
+    0, NULL,                /* Add triggers */
+    0, NULL,                /* Delete triggers */
+    0, NULL,                /* Undelete triggers */
+    NULL
 };
 
 
@@ -176,6 +199,24 @@ aux_item_default_definition(Aux_item *item)
 }
 
 
+/*
+ * aux_item_find_trigger
+ */
+
+Aux_item_trigger
+aux_item_find_trigger(char *trigger_name)
+{
+    unsigned long i = 0;
+
+    while (aux_item_triggers[i].name != NULL)
+    {
+        if (!strcmp(aux_item_triggers[i].name, trigger_name))
+            return aux_item_triggers[i].function;
+        i += 1;
+    }
+    return NULL;
+}
+
 /*
  * find_aux_item_definition
  *
@@ -300,6 +341,74 @@ initialize_aux_items(char *aux_def_file)
 }
 
 
+/* TRIGGER THINGS */
+
+
+void aux_item_call_add_triggers(Aux_item_definition *def,
+                                short object_type,
+                                unsigned long item_index,
+                                unsigned long integer_argument,
+                                void     * pointer_argument
+                                )
+{
+    unsigned long i;
+    Aux_item_trigger_data data;
+    
+    data.action = AUX_ITEM_ADD_ACTION;
+    data.object_type = object_type;
+    data.item_index = item_index;
+    data.object_no = integer_argument;
+    data.object = pointer_argument;
+
+    for (i = 0; i < def->num_add_triggers; i++)
+    {
+        (*def->add_triggers[i])(&data);
+    }
+}
+
+void aux_item_call_delete_triggers(Aux_item_definition *def,
+                                   short object_type,
+                                   unsigned long item_index,
+                                   unsigned long integer_argument,
+                                   void     * pointer_argument
+    )
+{
+    unsigned long i;
+    Aux_item_trigger_data data;
+    
+    data.action = AUX_ITEM_DELETE_ACTION;
+    data.object_type = object_type;
+    data.item_index = item_index;
+    data.object_no = integer_argument;
+    data.object = pointer_argument;
+
+    for (i = 0; i < def->num_delete_triggers; i++)
+    {
+        (*def->delete_triggers[i])(&data);
+    }
+}
+
+void aux_item_call_undelete_triggers(Aux_item_definition *def,
+                                     short object_type,
+                                     unsigned long item_index,
+                                     unsigned long integer_argument,
+                                     void     * pointer_argument
+    )
+{
+    unsigned long i;
+    Aux_item_trigger_data data;
+    
+    data.action = AUX_ITEM_UNDELETE_ACTION;
+    data.object_type = object_type;
+    data.item_index = item_index;
+    data.object_no = integer_argument;
+    data.object = pointer_argument;
+
+    for (i = 0; i < def->num_undelete_triggers; i++)
+    {
+        (*def->undelete_triggers[i])(&data);
+    }
+}
 
 /*
  * prepare_aux_item_list
@@ -339,7 +448,7 @@ void prepare_aux_item(Aux_item *item,
     AUX_ADJUST_FLAG(inherit);
     AUX_ADJUST_FLAG(secret);
     AUX_ADJUST_FLAG(hide_creator);
-    AUX_ADJUST_FLAG(reserved2);
+    AUX_ADJUST_FLAG(dont_garb);
     AUX_ADJUST_FLAG(reserved3);
     AUX_ADJUST_FLAG(reserved4);
     AUX_ADJUST_FLAG(reserved5);
@@ -373,6 +482,7 @@ void prepare_aux_item(Aux_item *item,
  * ADD_TO_LIST is the item list to add to, or NULL.
  * START_LOOKING_AT is the first index in add_to_list to start
  *     looking at for possible duplicates.
+ * CREATING is true if we are checking while creating an object
  */
 
 Bool
@@ -382,8 +492,13 @@ aux_item_add_perm(Aux_item *item,
                   Pers_no object_creator,
                   Bool owner_check,
                   Aux_item_list *add_to_list,
-                  unsigned long start_looking_at)
+                  unsigned long start_looking_at,
+                  Bool creating,
+                  short object_type
+                  )
 {
+    short can_add_when = 0;
+    
     def = def ? def : def = find_aux_item_definition(item);
 
     /* Can't create an item with no definition */
@@ -391,6 +506,22 @@ aux_item_add_perm(Aux_item *item,
     if (def == NULL)
         return FALSE;
 
+    switch (object_type)
+    {
+    case TEXT_OBJECT_TYPE: can_add_when = def->text_a; break;
+    case CONF_OBJECT_TYPE: can_add_when = def->conf_a; break;
+    default: can_add_when = 0;
+    }
+
+    if (can_add_when)
+    {
+        if (!((creating  && (can_add_when & AUX_ITEM_ADD_ON_CREATE)) ||
+              (!creating && (can_add_when & AUX_ITEM_ADD_ON_MODIFY))))
+        {
+            return FALSE;
+        }
+    }
+
     /* Check the author_only flag, which really is author-or-supervisor
      * How do we handle newly created confs, where we want this to
      * ALWAYS succeed? FIXME +++
@@ -505,7 +636,11 @@ void
 aux_inherit_items(Aux_item_list *target,
                   Aux_item_list *parent,
                   unsigned long *counter,
-                  Pers_no target_creator)
+                  Pers_no target_creator,
+                  Bool creating,
+                  short object_type,
+                  unsigned long object_no,
+                  void *object)
 {
     int i;
     Aux_item item;
@@ -528,7 +663,9 @@ aux_inherit_items(Aux_item_list *target,
                                    target_creator,
                                    TRUE,
                                    target,
-                                   0
+                                   0,
+                                   creating,
+                                   object_type
                                    ))
                 continue;
 
@@ -538,6 +675,12 @@ aux_inherit_items(Aux_item_list *target,
                 item.inherit_limit -= 1;
             
             ADD_AUX_ITEM(*target, item, *counter);
+
+            aux_item_call_add_triggers(def,
+                                       object_type,
+                                       target->length - 1,
+                                       object_no,
+                                       object);
         }
     }
 }
@@ -652,7 +795,10 @@ check_delete_aux_item_list(Number_list *items_to_delete,
  
 void
 delete_aux_item_list(Number_list *items_to_delete,
-                     Aux_item_list *list_to_delete_from)
+                     Aux_item_list *list_to_delete_from,
+                     short object_type,
+                     unsigned long object_no,
+                     void *object)
 {
     unsigned long i;
     Aux_item *item;
@@ -665,12 +811,21 @@ delete_aux_item_list(Number_list *items_to_delete,
         item = find_aux_item(list_to_delete_from,
                              items_to_delete->data[i]);
         item->flags.deleted = 1;
+        aux_item_call_delete_triggers(
+            find_aux_item_definition(item),
+            object_type,
+            items_to_delete->data[i],
+            object_no,
+            object);
     }
 }
 
 void
 undelete_aux_item_list(Number_list *items_to_undelete,
-                       Aux_item_list *list_to_undelete_from)
+                       Aux_item_list *list_to_undelete_from,
+                       short object_type,
+                       unsigned long object_no,
+                       void *object)
 {
     unsigned long i;
     Aux_item *item;
@@ -683,6 +838,11 @@ undelete_aux_item_list(Number_list *items_to_undelete,
         item = find_aux_item(list_to_undelete_from,
                              items_to_undelete->data[i]);
         item->flags.deleted = 0;
+        aux_item_call_delete_triggers(find_aux_item_definition(item),
+                                      object_type,
+                                      items_to_undelete->data[i],
+                                      object_no,
+                                      object);
     }
 }
 
@@ -741,7 +901,8 @@ find_aux_item(Aux_item_list *list, unsigned long aux_no)
 Success
 text_stat_check_add_aux_item_list(Text_stat *text_s,
                                   Aux_item_list *list,
-                                  Pers_no item_creator)
+                                  Pers_no item_creator,
+                                  Bool creating)
 {
     Aux_item *item;
     unsigned long i;
@@ -762,10 +923,15 @@ text_stat_check_add_aux_item_list(Text_stat *text_s,
             return FAILURE;
         }
         
-        if (!aux_item_add_perm(item, def, item_creator,
+        if (!aux_item_add_perm(item,
+                               def,
+                               item_creator,
                                text_s?text_s->author:item_creator,
                                TRUE,
-                               text_s?&text_s->aux_item_list:NULL, 0) ||
+                               text_s?&text_s->aux_item_list:NULL,
+                               0,
+                               creating,
+                               TEXT_OBJECT_TYPE) ||
             !aux_item_check_unique(item, def, list, i + 1) ||
             !def->texts)
         {
@@ -779,6 +945,7 @@ text_stat_check_add_aux_item_list(Text_stat *text_s,
 }
 
 void text_stat_add_aux_item_list(Text_stat *text_s,
+                                 Text_no text_no,
                                  Aux_item_list *item_list,
                                  Pers_no item_creator)
 {
@@ -791,6 +958,7 @@ void text_stat_add_aux_item_list(Text_stat *text_s,
                                            (text_s->aux_item_list.length +
                                             item_list->length) *
                                            sizeof(Aux_item));
+
     for (i = 0; i < item_list->length; i++)
     {
         text_s->highest_aux += 1;
@@ -801,6 +969,12 @@ void text_stat_add_aux_item_list(Text_stat *text_s,
             &text_s->aux_item_list.items[text_s->aux_item_list.length],
             &item_list->items[i]);
         text_s->aux_item_list.length += 1;
+        aux_item_call_add_triggers(
+            find_aux_item_definition(&item_list->items[i]),
+            TEXT_OBJECT_TYPE,
+            text_s->highest_aux,
+            text_no,
+            text_s);
     }
 }
 
@@ -812,7 +986,8 @@ Success
 conf_stat_check_add_aux_item_list(Conference    *conf,
                                   Conf_no        conf_no,
                                   Aux_item_list *list,
-                                  Pers_no        creator)
+                                  Pers_no        creator,
+                                  Bool           creating)
 {
     unsigned long i;
     Aux_item *item;
@@ -846,7 +1021,9 @@ conf_stat_check_add_aux_item_list(Conference    *conf,
                                conf_no,
                                TRUE,
                                &conf->aux_item_list,
-                               0) ||
+                               0,
+                               creating,
+                               CONF_OBJECT_TYPE) ||
             !aux_item_check_unique(item, def, list, i + 1) ||
             !(def->confs || (def->letterboxes && conf->type.letter_box)))
         {
@@ -883,6 +1060,12 @@ conf_stat_add_aux_item_list(Conference    *conf,
         copy_aux_item(&conf->aux_item_list.items[conf->aux_item_list.length],
                       &item_list->items[i]);
         conf->aux_item_list.length += 1;
+        aux_item_call_add_triggers(
+            find_aux_item_definition(&item_list->items[i]),
+            CONF_OBJECT_TYPE,
+            conf->highest_aux,
+            conf_no,
+            conf);
     }
 }
 
@@ -914,7 +1097,9 @@ Success system_check_add_aux_item_list(Info *info,
                                creator,
                                FALSE,
                                &info->aux_item_list,
-                               0) ||
+                               0,
+                               FALSE,
+                               OTHER_OBJECT_TYPE) ||
             !aux_item_check_unique(item, def, list, i + 1) ||
             !def->system)
         {
@@ -978,3 +1163,16 @@ query_predefined_aux_items(Number_list *result)
 
     return OK;
 }
+
+
+void aux_item_trigger_mark_text(Aux_item_trigger_data *data)
+{
+    if (data->object_type != TEXT_OBJECT_TYPE)
+        return;
+}
+
+void aux_item_trigger_unmark_text(Aux_item_trigger_data *data)
+{
+    if (data->object_type != TEXT_OBJECT_TYPE)
+        return;
+}
diff --git a/src/server/aux-items.h b/src/server/aux-items.h
index 45728855ba33c3ab5b91dfa715a926b2e454cc0a..1d28df35531abd062324ce0752d3a3cc218977d2 100644
--- a/src/server/aux-items.h
+++ b/src/server/aux-items.h
@@ -1,5 +1,5 @@
 /*
- * $Id: aux-items.h,v 1.2 1997/10/23 12:37:21 byers Exp $
+ * $Id: aux-items.h,v 1.3 1998/06/14 14:50:44 byers Exp $
  * Copyright (C) 1994, 1995, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -55,6 +55,34 @@
 }
 
 
+/* Valid values for text_a etc. */
+
+#define AUX_ITEM_ADD_ON_CREATE 1
+#define AUX_ITEM_ADD_ON_MODIFY 2
+
+/* Valid values for action trigger data field */
+
+#define AUX_ITEM_ADD_ACTION    1
+#define AUX_ITEM_DELETE_ACTION 2
+#define AUX_ITEM_UNDELETE_ACTION 3
+
+/* Valid values for object_type fields */
+
+#define OTHER_OBJECT_TYPE 0
+#define TEXT_OBJECT_TYPE 1
+#define CONF_OBJECT_TYPE 2
+
+typedef struct Aux_item_trigger_data_s
+{
+    short           action;
+    short           object_type;
+    unsigned long   item_index;
+    unsigned long   object_no;
+    void          * object;
+} Aux_item_trigger_data;
+
+typedef void (*Aux_item_trigger)(Aux_item_trigger_data *);
+
 typedef struct Aux_item_definition_s {
     char                   *name;
     unsigned long           tag;
@@ -66,14 +94,29 @@ typedef struct Aux_item_definition_s {
     Bool                    may_not_delete;
     unsigned long           inherit_limit;
     Bool                    texts;
+    short                   text_a; /* When can we add items of this type */
     Bool                    confs;
+    short                   conf_a; /* When can we add items of this type */
     Bool                    letterboxes;
     Bool                    system;
     char                   *validate_regexp;
     struct re_pattern_buffer *cached_re_buf;
+    unsigned long             num_delete_triggers;
+    Aux_item_trigger        * delete_triggers;
+    unsigned long             num_add_triggers;
+    Aux_item_trigger        * add_triggers;
+    unsigned long             num_undelete_triggers;
+    Aux_item_trigger        * undelete_triggers;
     struct Aux_item_definition_s *next;
 } Aux_item_definition;
 
+typedef struct
+{
+    char *name;
+    Aux_item_trigger function;
+} Aux_item_trigger_mapping;
+
+extern Aux_item_trigger_mapping aux_item_triggers [];
 extern Aux_item_definition empty_aux_item_definition;
 
 /*
@@ -95,7 +138,9 @@ extern Aux_item_definition empty_aux_item_definition;
  * conference for conferences */
 
 void aux_inherit_items(Aux_item_list *target, Aux_item_list *parent,
-                       unsigned long *counter, Pers_no target_creator);
+                       unsigned long *counter, Pers_no target_creator,
+                       Bool creating, short object_type,
+                       unsigned long object_no, void *object);
 
 
 
@@ -114,7 +159,8 @@ void aux_inherit_items(Aux_item_list *target, Aux_item_list *parent,
 Bool aux_item_add_perm(Aux_item *item, Aux_item_definition *def,
                        Pers_no item_creator, Pers_no object_creator,
                        Bool owner_check, Aux_item_list *add_to_list,
-                       unsigned long start_looking_at);
+                       unsigned long start_looking_at, Bool creating,
+                       short object_type);
 
 
 
@@ -136,6 +182,10 @@ void prepare_aux_item(Aux_item *item, Pers_no creator,
 Aux_item_definition *find_aux_item_definition(Aux_item *item);
 
 
+/* Get the function pointer for a named trigger */
+
+Aux_item_trigger aux_item_find_trigger(char *trigger_name);
+
 /* Get a pointer to the item in list with aux-no aux_no. Returns
  * NULL if there is no such item */
 
@@ -158,7 +208,10 @@ void filter_aux_item_list(Aux_item_list *original,
  * list_to_delete_from and its elements may be modified */
 
 void delete_aux_item_list(Number_list *items_to_delete,
-                          Aux_item_list *list_to_delete_from);
+                          Aux_item_list *list_to_delete_from,
+                          short object_type,
+                          unsigned long object_no,
+                          void *object);
 
 
 
@@ -166,7 +219,10 @@ void delete_aux_item_list(Number_list *items_to_delete,
  * list_to_delete_from and its elements may be modified */
 
 void undelete_aux_item_list(Number_list *items_to_undelete,
-                            Aux_item_list *list_to_undelete_from);
+                            Aux_item_list *list_to_undelete_from,
+                            short object_type,
+                            unsigned long object_no,
+                            void *object);
 
 
 
@@ -183,7 +239,9 @@ Success check_delete_aux_item_list(Number_list *items_to_delete,
 /* Att item_list to the aux_item_list of text_s. item_creator is the
  * person who is adding the items. Does not check for permission first */
   
-void text_stat_add_aux_item_list(Text_stat *text_s, Aux_item_list *item_list,
+void text_stat_add_aux_item_list(Text_stat *text_s,
+                                 Text_no text_no,
+                                 Aux_item_list *item_list,
                                  Pers_no item_creator);
 
 
@@ -196,7 +254,8 @@ void text_stat_add_aux_item_list(Text_stat *text_s, Aux_item_list *item_list,
 
 Success text_stat_check_add_aux_item_list(Text_stat *text_s,
                                           Aux_item_list *list,
-                                          Pers_no item_creator);
+                                          Pers_no item_creator,
+                                          Bool creating);
 
 
 
@@ -204,13 +263,15 @@ Success conf_stat_check_add_aux_item(Conference          *conf,
                                      Conf_no        conf_no,
                                      Aux_item            *item,
                                      Pers_no              creator,
-                                     Aux_item_definition *def);
+                                     Aux_item_definition *def,
+                                     Bool creating);
 
 Success
 conf_stat_check_add_aux_item_list(Conference    *conf,
                                   Conf_no        conf_no,
                                   Aux_item_list *list,
-                                  Pers_no        creator);
+                                  Pers_no        creator,
+                                  Bool creating);
 void
 conf_stat_add_aux_item(Conference          *conf,
                        Conf_no              conf_no,
@@ -221,6 +282,7 @@ conf_stat_add_aux_item_list(Conference    *conf,
                             Conf_no        conf_no,
                             Aux_item_list *list,
                             Pers_no        creator);
+
 void
 system_add_aux_item_list(Info    *info,
                          Aux_item_list *item_list,
diff --git a/src/server/call-switch.awk b/src/server/call-switch.awk
index 0c8563e597614628248ea8a90c2181a36857cdea..390509bac54efaa1431ef44b1a7f9b667657424f 100644
--- a/src/server/call-switch.awk
+++ b/src/server/call-switch.awk
@@ -1,5 +1,5 @@
 #
-# $Id: call-switch.awk,v 0.14 1997/09/13 15:31:57 byers Exp $
+# $Id: call-switch.awk,v 0.15 1998/06/14 14:50:45 byers Exp $
 # Copyright (C) 1991, 1993, 1994, 1995, 1996  Lysator Academic Computer Association.
 #
 # This file is part of the LysKOM server.
@@ -22,7 +22,7 @@
 #
 # Please mail bug reports to bug-lyskom@lysator.liu.se. 
 #
-# $Id: call-switch.awk,v 0.14 1997/09/13 15:31:57 byers Exp $
+# $Id: call-switch.awk,v 0.15 1998/06/14 14:50:45 byers Exp $
 BEGIN {
     printf("/* Don't edit this file - it is generated automatically");
     printf(" from\n   call-switch.awk and fncdef.txt */\n");
@@ -57,6 +57,8 @@ $1 != "#" {
 	    printf("client->priv_bits");
 	else if ( $i == "conf_type" )
 	    printf("client->conf_type");
+	else if ( $i == "membership_type" )
+	    printf("&client->membership_type");
 	else if ( $i == "c_local_text_no_p" )
 	    printf("client->c_local_text_no_p");
 	else if ( $i == "c_misc_info_p" )
diff --git a/src/server/conference.c b/src/server/conference.c
index 54a929120f1779569978908a74b2ad9a158e2a1b..2d7d2e8b43e18d394fcde13918e084cb9b039f35 100644
--- a/src/server/conference.c
+++ b/src/server/conference.c
@@ -1,5 +1,5 @@
 /*
- * $Id: conference.c,v 0.36 1997/09/13 15:31:58 byers Exp $
+ * $Id: conference.c,v 0.37 1998/06/14 14:50:46 byers Exp $
  * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -28,7 +28,7 @@
  * All atomic calls that deals with conferences.
  */
 
-static char *rcsid = "$Id: conference.c,v 0.36 1997/09/13 15:31:58 byers Exp $";
+static char *rcsid = "$Id: conference.c,v 0.37 1998/06/14 14:50:46 byers Exp $";
 #include "rcs.h"
 USE(rcsid);
 
@@ -297,7 +297,8 @@ do_create_conf(String	 name,
     if (conf_stat_check_add_aux_item_list(conf_c,
                                           conf_no,
                                           aux,
-                                          creator) != OK)
+                                          creator,
+                                          TRUE) != OK)
     {
         cached_delete_conf(conf_no);
         return 0;
@@ -438,7 +439,7 @@ create_conf_generic(const String  name,
     CHK_LOGIN(0);
 
     if (param.anyone_can_create_new_confs == FALSE
-	&& !ENA(create_conf, 0) )
+	&& !HAVE_PRIV(create_conf) )
     {
         err_stat = 0;
 	kom_errno = KOM_PERM;
@@ -1266,11 +1267,16 @@ modify_conf_info(Conf_no        conf_no,
 
     if (check_delete_aux_item_list(items_to_delete,&conf->aux_item_list)!=OK)
         return FAILURE;
-    delete_aux_item_list(items_to_delete, &conf->aux_item_list);
+    delete_aux_item_list(items_to_delete, &conf->aux_item_list,
+                         CONF_OBJECT_TYPE,
+                         conf_no, conf);
 
-    if (conf_stat_check_add_aux_item_list(conf, conf_no, aux, ACTPERS) != OK)
+    if (conf_stat_check_add_aux_item_list(conf, conf_no, aux, ACTPERS,
+                                          FALSE) != OK)
     {
-        undelete_aux_item_list(items_to_delete, &conf->aux_item_list);
+        undelete_aux_item_list(items_to_delete, &conf->aux_item_list,
+                         CONF_OBJECT_TYPE,
+                         conf_no, conf);
         return FAILURE;
     }
 
diff --git a/src/server/connections.h b/src/server/connections.h
index 95f42ebef7c4bbe8122507c582b6ca401d01a6e6..8208578b685a73c5bc10c382813ccb06d368692e 100644
--- a/src/server/connections.h
+++ b/src/server/connections.h
@@ -1,5 +1,5 @@
 /*
- * $Id: connections.h,v 0.29 1997/09/13 15:32:01 byers Exp $
+ * $Id: connections.h,v 0.30 1998/06/14 14:50:49 byers Exp $
  * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -23,7 +23,7 @@
  * Please mail bug reports to bug-lyskom@lysator.liu.se. 
  */
 /*
- * $Id: connections.h,v 0.29 1997/09/13 15:32:01 byers Exp $
+ * $Id: connections.h,v 0.30 1998/06/14 14:50:49 byers Exp $
  *
   * connections.h -- The top level of the communication packet.
   *
@@ -101,6 +101,7 @@ typedef struct connection {
     Local_text_no      *c_local_text_no_p; /* Freead by free_parsed(). */
     Priv_bits		priv_bits;
     Conf_type		conf_type;
+    Membership_type     membership_type;
     struct tm		time;
     Info                info;
 
@@ -147,6 +148,7 @@ typedef enum {
        of the indicated type. The corresponding types are found in
        kom-types.h */
     rt_person,
+    rt_membership_old,
     rt_membership,
     rt_conf_list,
     rt_conf_no_list,
@@ -159,7 +161,9 @@ typedef enum {
     rt_who_info_list_old,
     rt_info_old,
     rt_membership_list,
+    rt_membership_list_old,
     rt_member_list,
+    rt_member_list_old,
     rt_time_date,
     rt_session_info,
     rt_session_no,
@@ -190,6 +194,7 @@ typedef union {
         unsigned long		  number;
     	Person			  person;
 	Membership		  membership;
+	Membership		  membership_old;
 	Conf_list_old		  conf_list;
 	Conf_no_list		  conf_no_list;
 	Conference		  conference;
@@ -204,7 +209,9 @@ typedef union {
 	Who_info_list		  who_info_list;
 	Who_info_list_old	  who_info_list_old;
 	Membership_list		  membership_list;
+	Membership_list		  membership_list_old;
 	Member_list		  member_list;
+        Member_list               member_list_old;
 	time_t			  time_date;
 	Session_info		  session_info;
 	Session_no		  session_no;
diff --git a/src/server/fncdef.txt b/src/server/fncdef.txt
index cddd67ceff47d1cb3fee2bace163838a6d2dfc53..a9813b3408d3edbf34fe5b46c5f48b6e5e6585d8 100644
--- a/src/server/fncdef.txt
+++ b/src/server/fncdef.txt
@@ -1,5 +1,5 @@
 #
-# $Id: fncdef.txt,v 0.28 1997/09/13 15:32:07 byers Exp $
+# $Id: fncdef.txt,v 0.29 1998/06/14 14:50:50 byers Exp $
 # Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997
 # Lysator Academic Computer Association.
 #
@@ -23,7 +23,7 @@
 #
 # Please mail bug reports to bug-lyskom@lysator.liu.se. 
 #
-# $Id: fncdef.txt,v 0.28 1997/09/13 15:32:07 byers Exp $
+# $Id: fncdef.txt,v 0.29 1998/06/14 14:50:50 byers Exp $
 # 
 # This file is used to describe the functions in services.c. All
 # functions that are reachable from the clients are listed here, together
@@ -49,12 +49,12 @@ number  create_person_old   c_string (param.conf_name_len) c_string (param.pwd_l
 success get_person_stat_old num num : person
 success set_priv_bits       num priv_bits
 success set_passwd          num c_string (param.pwd_len) c_string (param.pwd_len)
-success query_read_texts    num num : membership
+success query_read_texts_old num num : membership_old
 number  create_conf_old     c_string (param.conf_name_len) conf_type
 success delete_conf         num
 success lookup_name         c_string (param.conf_name_len) : conf_list
 success get_conf_stat_older num num : conference_old
-success add_member          num num num num
+success add_member_old      num num num num
 success sub_member          num num
 success set_presentation    num num
 success set_etc_motd        num num
@@ -86,9 +86,9 @@ success enable              num
 success sync_kom
 success shutdown_kom        num
 success broadcast           c_string (param.broadcast_len)
-success get_membership      num num num num : membership_list
+success get_membership_old  num num num num : membership_list_old
 success get_created_texts   num num num : text_list
-success get_members         num num num : member_list
+success get_members_old     num num num : member_list_old
 success get_person_stat     num : person
 success get_conf_stat_old   num : conference_old
 success who_is_on           : who_info_list
@@ -165,3 +165,8 @@ success get_info            : info
 success modify_server_info num_list (param.max_delete_aux) aux_item_list (param.max_add_aux)
 success query_predefined_aux_items : num_list
 success set_expire          num num
+success query_read_texts    num num : membership
+success get_membership      num num num num : membership_list
+success add_member          num num num num membership_type
+success get_members         num num num : member_list
+success set_membership_type num num membership_type
diff --git a/src/server/manipulate.h b/src/server/manipulate.h
index 6521d8669d90be848103fb943e0cd0b4b7477ca4..66b3c3c8fb772e8cebbd85b60f956cfc89dda71d 100644
--- a/src/server/manipulate.h
+++ b/src/server/manipulate.h
@@ -1,5 +1,5 @@
 /*
- * $Id: manipulate.h,v 0.14 1997/09/13 15:32:10 byers Exp $
+ * $Id: manipulate.h,v 0.15 1998/06/14 14:50:52 byers Exp $
  * Copyright (C) 1991, 1992, 1993, 1994, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -23,7 +23,7 @@
  * Please mail bug reports to bug-lyskom@lysator.liu.se. 
  */
 /*
- * $Id: manipulate.h,v 0.14 1997/09/13 15:32:10 byers Exp $
+ * $Id: manipulate.h,v 0.15 1998/06/14 14:50:52 byers Exp $
  *
  * manipulate.h
  *
@@ -143,6 +143,7 @@
 #define ENA(privtype, req_lev)	\
 (active_connection->ena_level >=(req_lev) && (ACT_P)->privileges.privtype)
 
+#define HAVE_PRIV(privtype) ((ACT_P)->privileges.privtype)
 
 
 /*
@@ -320,7 +321,9 @@ do_add_member(Conf_no	     conf_no,  /* Conference to add a new member to. */
 	      Pers_no	     pers_no,  /* Person to be added. */
 	      Person	   * pers_p,   /* Pers. status. Must NOT be NULL. */
 	      unsigned char  priority, /* Priority to assign to this conf */
-	      unsigned short where);    /* Sequence number in the list */
+	      unsigned short where,    /* Sequence number in the list */
+              Membership_type * type   /* Membership type */  
+              );
 
 /*
  * Return TRUE if ACTPERS has enough privileges to access VICTIM's data.
diff --git a/src/server/membership.c b/src/server/membership.c
index 746a66b833214ad3ae1db009bae9e2ee9536010f..6bcf2441560be72a1e80890a1fe8769ddc46138f 100644
--- a/src/server/membership.c
+++ b/src/server/membership.c
@@ -1,5 +1,5 @@
 /*
- * $Id: membership.c,v 0.31 1997/09/13 15:32:12 byers Exp $
+ * $Id: membership.c,v 0.32 1998/06/14 14:50:53 byers Exp $
  * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -31,7 +31,7 @@
 
 #define DEBUG_MARK_AS_READ
 
-static char *rcsid = "$Id: membership.c,v 0.31 1997/09/13 15:32:12 byers Exp $";
+static char *rcsid = "$Id: membership.c,v 0.32 1998/06/14 14:50:53 byers Exp $";
 #include "rcs.h"
 USE(rcsid);
 
@@ -64,12 +64,29 @@ USE(rcsid);
 #include "send-async.h"
 #include "minmax.h"
 #include "kom-memory.h"
+#include "param.h"
 
 #ifdef DEBUG_MARK_AS_READ
 #  include "log.h"
 #  include "ram-output.h"
 #endif
 
+static void
+set_membership_type_bits(Membership_type *type,
+                    Bool invitation, Bool passive, Bool secret,
+                    Bool reserved1, Bool reserved2, Bool reserved3, 
+                    Bool reserved4, Bool reserved5)
+{
+    type->invitation = invitation;
+    type->passive = passive;
+    type->secret = secret;
+    type->reserved1 = reserved1;
+    type->reserved2 = reserved2;
+    type->reserved3 = reserved3;
+    type->reserved4 = reserved4;
+    type->reserved5 = reserved5;
+}
+
 /*
  * Copy all information that ACTPERS is authorized to know about ORIG_P's
  * membership in all conferences to CENSOR_P.
@@ -79,7 +96,8 @@ USE(rcsid);
 static void
 copy_public_confs (Person   * censor_p,	/* The censored Person-struct */
 		   Person   * orig_p,	/* The uncensored Person-struct */
-		   Bool	      want_read) /* Does ACTPERS want to know
+		   Bool	      want_read,
+                   Bool       copy_secret) /* Does ACTPERS want to know
 					  * which texts are read?*/
 {
     int i;			/* Number of mships lefte in ORIG_P */
@@ -98,7 +116,8 @@ copy_public_confs (Person   * censor_p,	/* The censored Person-struct */
 
     for ( i = 0; i < orig_p->conferences.no_of_confs; i++, orig_m++ )
     {
-	if ( fast_access_perm (orig_m->conf_no, ACTPERS, ACT_P) > none )
+	if ( fast_access_perm (orig_m->conf_no, ACTPERS, ACT_P) > none &&
+             (copy_secret || !orig_m->type.secret) )
 	{
 	    *censor_m = *orig_m;
 
@@ -125,14 +144,19 @@ copy_public_confs (Person   * censor_p,	/* The censored Person-struct */
  */
 static void
 do_change_priority (Membership * mship,
+                    Conf_no conf_no,
+                    Conference * conf_c,
 		    unsigned char	 priority,
 		    unsigned short	 where,
 		    Pers_no	 pers_no,
-		    Person     * pers_p)
+		    Person     * pers_p,
+                    Membership_type * type)
 {
     Membership tmp_conf;
+    unsigned short i;
     
     mship->priority = priority;
+    mship->type = *type;
     
     /* Check range of where */
     
@@ -164,6 +188,16 @@ do_change_priority (Membership * mship,
 	*mship = tmp_conf;
     }
 
+    
+    for (i = 0; i < conf_c->members.no_of_members; i++)
+    {
+        if (conf_c->members.members[i].member == pers_no)
+        {
+            conf_c->members.members[i].type = *type;
+            mark_conference_as_changed( conf_no );
+        }
+    }
+
     mark_person_as_changed( pers_no );
 }
 
@@ -466,7 +500,9 @@ do_add_member(Conf_no	   conf_no,  /* Conference to add a new member to. */
 	      Pers_no	   pers_no,  /* Person to be added. */
 	      Person	 * pers_p,   /* Pers. status. Must NOT be NULL. */
 	      unsigned char	   priority, /* Prioritylevel to assign to this conf */
-	      unsigned short	   where)    /* Sequence number in the list */
+	      unsigned short	   where,   /* Sequence number in the list */
+              Membership_type      * type
+              )
 {
     Membership  * mship;
     Member	* member;
@@ -493,13 +529,16 @@ do_add_member(Conf_no	   conf_no,  /* Conference to add a new member to. */
 
     init_membership(mship);
     
+    mship->added_by = ACTPERS;
+    mship->added_at = time(NULL);
     mship->conf_no = conf_no;
     mship->priority = priority;
     mship->last_time_read = time(NULL);
     mship->last_text_read = 0;
     mship->no_of_read = 0;
     mship->read_texts = NULL;
-    
+    mship->type = *type;
+
     /* Make room for the person in the conference */
     
     conf_c->members.members = srealloc( conf_c->members.members,
@@ -511,6 +550,9 @@ do_add_member(Conf_no	   conf_no,  /* Conference to add a new member to. */
     member = (conf_c->members.members
 	      + conf_c->members.no_of_members - 1);
     member->member = pers_no;
+    member->added_by = ACTPERS;
+    member->added_at = time(NULL);
+    member->type = *type;
     
     mark_conference_as_changed( conf_no );
     mark_person_as_changed( pers_no );
@@ -782,7 +824,13 @@ sub_member(	Conf_no		conf_no,
          !ENA(admin, 4) )
     {
         err_stat = conf_no;
-	kom_errno = conf_c->type.secret ? KOM_UNDEF_CONF : KOM_PERM;
+        if (conf_c->type.secret)
+          kom_errno = KOM_UNDEF_CONF;
+        else if (mship->type.secret)
+          kom_errno = KOM_NOT_MEMBER;
+        else
+          kom_errno = KOM_PERM;
+
 	return FAILURE;
     }
 
@@ -805,26 +853,56 @@ sub_member(	Conf_no		conf_no,
  *
  * You can only re-prioritize if you are supervisor of pers_no.
  */
+
+extern Success
+add_member_old(Conf_no	conf_no,
+               Pers_no	pers_no,
+               unsigned char	priority,
+               unsigned short	where)
+{
+    Membership_type type;
+
+    set_membership_type_bits(&type, param.invite_by_default,0,0,0,0,0,0,0);
+    return add_member(conf_no, pers_no, priority, where, &type);
+}
+
+
 extern Success
 add_member(Conf_no	conf_no,
-	   Pers_no	pers_no,
-	   unsigned char	priority,
-	   unsigned short	where)		/* Range of where is [0..] */
+           Pers_no	pers_no,
+           unsigned char	priority,
+           unsigned short	where,		/* Range of where is [0..] */
+           Membership_type     *type
+           )
 {
     Conference  * conf_c, * pers_c;
     Person	* pers_p;
     Membership	* mship;
-    
 
     CHK_LOGIN(FAILURE);
     GET_C_STAT(conf_c, conf_no, FAILURE);
+    GET_C_STAT(pers_c, pers_no, FAILURE);
     GET_P_STAT(pers_p, pers_no, FAILURE);
 
+    if (param.invite_by_default &&
+        !is_supervisor(pers_no, pers_c, ACTPERS, ACT_P) &&
+        !ENA(admin, 4))
+    {
+        type->invitation = 1;
+    }
+
+    if (!param.secret_memberships && type->secret)
+    {
+        err_stat = 0;
+        kom_errno = KOM_INVALID_MEMBERSHIP_TYPE;
+        return FAILURE;
+    }
+
     if ( access_perm(conf_no, conf_c, ACTPERS, ACT_P) < limited
-	&& !ENA(admin, 4) )
+	&& !ENA(wheel, 8) )
     {
         err_stat = conf_no;
-	kom_errno = conf_c->type.secret ? KOM_UNDEF_CONF : KOM_ACCESS;
+	kom_errno = (conf_c->type).secret ? KOM_UNDEF_CONF : KOM_ACCESS;
 	return FAILURE;
     }
 
@@ -844,7 +922,7 @@ add_member(Conf_no	conf_no,
 	    return FAILURE;
 	}
 
-	do_change_priority( mship, priority, where, pers_no, pers_p);
+	do_change_priority( mship, conf_no, conf_c, priority, where, pers_no, pers_p, type);
     }
     else
     {
@@ -854,7 +932,7 @@ add_member(Conf_no	conf_no,
 		(unsigned long)conf_no,
 		(unsigned long)ACTPERS);
 
-	do_add_member(conf_no, conf_c, pers_no, pers_p, priority, where);
+	do_add_member(conf_no, conf_c, pers_no, pers_p, priority, where, type);
     }
 
     return OK;
@@ -1071,12 +1149,28 @@ mark_as_read (Conf_no		      conference,
  * function as GETP_READ_TEXTS in the get_person_stat call.
  * ///
  */
+
 extern  Success
 get_membership (Pers_no		  pers_no,
-		unsigned short		  first,
-		unsigned short		  no_of_confs,
-		Bool		  want_read_texts,
-		Membership_list	* memberships )
+                unsigned short		  first,
+                unsigned short		  no_of_confs,
+                Bool		  want_read_texts,
+                Membership_list	* memberships )
+{
+    return get_membership_old (pers_no,
+                               first,
+                               no_of_confs,
+                               want_read_texts,
+                               memberships );
+}
+
+
+extern  Success
+get_membership_old (Pers_no		  pers_no,
+                    unsigned short		  first,
+                    unsigned short		  no_of_confs,
+                    Bool		  want_read_texts,
+                    Membership_list	* memberships )
 {
     Person		* p_orig;
     Person		  temp_pers;
@@ -1108,7 +1202,7 @@ get_membership (Pers_no		  pers_no,
     /* Delete all secret information. */
 
     if ( acc != unlimited )
-	copy_public_confs (&temp_pers, p_orig, want_read_texts);
+	copy_public_confs (&temp_pers, p_orig, want_read_texts, FALSE);
     else if ( !want_read_texts )
     {
 	/* Delete info about read texts. */
@@ -1147,14 +1241,28 @@ get_membership (Pers_no		  pers_no,
  *
  * first starts at 0.
  */
+
+extern Success
+get_members_old (Conf_no conf_no,
+                 unsigned short first,
+                 unsigned short no_of_members,
+                 Member_list * members)
+{
+    return get_members (conf_no,
+                        first,
+                        no_of_members,
+                        members);
+}
+
 extern  Success
 get_members (Conf_no	  conf_no,
-	     unsigned short	  first,
-	     unsigned short	  no_of_members,
-	     Member_list * members	)
+             unsigned short	  first,
+             unsigned short	  no_of_members,
+             Member_list * members )
 {
     Conference * conf_c;
     Access	 acc;
+    unsigned long src, dst;
         
     GET_C_STAT(conf_c, conf_no, FAILURE);
 
@@ -1170,19 +1278,46 @@ get_members (Conf_no	  conf_no,
 	return FAILURE;
     }
 
-    *members = conf_c->members;
-
-    if ( first >= members->no_of_members )
+    if ( first >= (conf_c->members).no_of_members )
     {
         err_stat = first;
 	kom_errno = KOM_INDEX_OUT_OF_RANGE;
 	return FAILURE;
     }
 
+    *members = conf_c->members;
     members->members += first;
+
     members->no_of_members = min (no_of_members,
 				  members->no_of_members - first);
-    
+    members->members = tmp_alloc(members->no_of_members *
+                                 sizeof(Member));
+    src = first;
+    dst = 0;
+
+    while (dst < members->no_of_members)
+    {
+        if (!(conf_c->members).members[src].type.secret ||
+            is_supervisor((conf_c->members).members[src].member,
+                          NULL,
+                          ACTPERS,
+                          ACT_P))
+        {
+            members->members[dst] = (conf_c->members).members[src];
+        }
+        else
+        {
+            members->members[dst].member = 0;
+            members->members[dst].added_by = 0;
+            members->members[dst].added_at = 0;
+            set_membership_type_bits(&members->members[dst].type,
+                                0,0,0,0,0,0,0,0);
+        }
+
+        src += 1;
+        dst += 1;
+    }
+
     return OK;
 }
 
@@ -1294,5 +1429,88 @@ set_last_read (Conf_no conf_no,
     return OK;
 }
 
+extern Success set_membership_type(Pers_no pers_no,
+                                   Conf_no conf_no,
+                                   Membership_type *type)
+{
+    Conference      *conf_c, *pers_c;
+    Person          *pers_p;
+    Membership      *membership;
+    Member          *member;
+    Access           acc;
+
+    /* Check for logon */
+    CHK_LOGIN(FAILURE);
+
+    /* Find the conference and person in question */
+    GET_C_STAT(conf_c, conf_no, FAILURE);
+    GET_C_STAT(pers_c, pers_no, FAILURE);
+    GET_P_STAT(pers_p, pers_no, FAILURE);
+    
+    /* Make sure that ACTPERS may know about conf */
+    acc = access_perm(conf_no, conf_c, ACTPERS, ACT_P);
+
+    if (acc == error)
+        return FAILURE;
+
+    if (acc == none)
+    {
+        err_stat = conf_no;
+        kom_errno = KOM_UNDEF_CONF;
+        return FAILURE;
+    }
+
+    /* Check that ACTPERS may modify memberships of person */
+    acc = access_perm(pers_no, pers_c, ACTPERS, ACT_P);
+    if (acc != unlimited &&
+        !ENA(wheel, 8) &&
+        !ENA(admin, 6))
+    {
+        err_stat = pers_no;
+        kom_errno = conf_c->type.secret ? KOM_UNDEF_CONF : KOM_PERM;
+        return FAILURE;
+    }
+
+    /* Find person's membership in the conference */
+    membership = locate_membership(conf_no, pers_p);
+    if (membership == NULL)
+    {
+        err_stat = conf_no;
+        kom_errno = KOM_NOT_MEMBER;
+        return FAILURE;
+    }
+
+    /* Find entry in conference's member list */
+    /* FIXME: If this happens we should do something more drastic
+              since it indicates that the database is fucked up. */
+
+    member = locate_member(pers_no, conf_c);
+    if (member == NULL)
+    {
+        err_stat = conf_no;
+        kom_errno = KOM_NOT_MEMBER;
+        return FAILURE;
+    }
+
+    /* Check type restrictions */
+    if ((!param.secret_memberships && type->secret) ||
+        (!param.allow_reinvite && type->invitation && !membership->type.invitation))
+    {
+        err_stat = 0;
+        kom_errno = KOM_INVALID_MEMBERSHIP_TYPE;
+        return FAILURE;
+    }
+
+    /* Modify member and membership */
+    membership->type = *type;
+    member->type     = *type;
+    
+    /* Mark the conference and person as changed */
+    mark_conference_as_changed(conf_no);
+    mark_person_as_changed(pers_no);
+
+    /* Return success */
+    return OK;
+}
 
 
diff --git a/src/server/memory.c b/src/server/memory.c
index a4ef1eabef56557b384abe58706f634e7090192a..7b61ca2f9bf52a46c901fffce48863c93a81766d 100644
--- a/src/server/memory.c
+++ b/src/server/memory.c
@@ -1,5 +1,5 @@
 /*
- * $Id: memory.c,v 0.21 1997/10/23 12:37:25 byers Exp $
+ * $Id: memory.c,v 0.22 1998/06/14 14:50:55 byers Exp $
  * Copyright (C) 1991, 1992, 1993, 1994, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -28,7 +28,7 @@
  * These functions should be used instead of smalloc/srealloc.
  */
 
-static char *rcsid = "$Id: memory.c,v 0.21 1997/10/23 12:37:25 byers Exp $";
+static char *rcsid = "$Id: memory.c,v 0.22 1998/06/14 14:50:55 byers Exp $";
 #include "rcs.h"
 USE(rcsid);
 
@@ -267,6 +267,16 @@ init_membership(Membership *m)
     m->no_of_read = 0;
     m->read_texts = NULL;
     m->last_time_read = NO_TIME;
+    m->added_by = 0;
+    m->added_at = 0;
+    m->type.invitation = 0;
+    m->type.passive = 0;
+    m->type.secret = 0;
+    m->type.reserved1 = 0;
+    m->type.reserved2 = 0;
+    m->type.reserved3 = 0;
+    m->type.reserved4 = 0;
+    m->type.reserved5 = 0;
 }
 
 /* Membership_list */
diff --git a/src/server/param.h b/src/server/param.h
index 03f99a4b6c524d7ff9e0520ead8e4e201dc17fb0..3aaab27156e0f0af6d5a194b4af7b1ec79b5b8b6 100644
--- a/src/server/param.h
+++ b/src/server/param.h
@@ -1,5 +1,5 @@
 /*
- * $Id: param.h,v 1.14 1997/09/13 15:32:14 byers Exp $
+ * $Id: param.h,v 1.15 1998/06/14 14:50:57 byers Exp $
  * Copyright (C) 1994, 1995, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -98,6 +98,9 @@ struct kom_par {
     Bool log_login;
     Bool force_iso_8859_1;
     int no_files;		/* -1=default */
+    Bool invite_by_default;
+    Bool secret_memberships;
+    Bool allow_reinvite;
 };
 
 extern struct kom_par param;
diff --git a/src/server/person.c b/src/server/person.c
index c9acb6991e424fe2bcd3ceb1bceac1779ffcd606..080ce40869bfac7028053113d1dd8e9c1799b608 100644
--- a/src/server/person.c
+++ b/src/server/person.c
@@ -1,5 +1,5 @@
 /*
- * $Id: person.c,v 0.36 1997/09/13 15:32:15 byers Exp $
+ * $Id: person.c,v 0.37 1998/06/14 14:50:59 byers Exp $
  * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -28,7 +28,7 @@
  * All atomic calls that deals with persons.
  */
 
-static char *rcsid = "$Id: person.c,v 0.36 1997/09/13 15:32:15 byers Exp $";
+static char *rcsid = "$Id: person.c,v 0.37 1998/06/14 14:50:59 byers Exp $";
 #include "rcs.h"
 USE(rcsid);
 
@@ -530,6 +530,7 @@ create_person_generic ( const String  name,
     Pers_no 	  new_user;
     Conference	* mailbox;
     Person	* pers_p;
+    Membership_type mship_type;
     
 
     if (ACTPERS == 0)
@@ -544,7 +545,7 @@ create_person_generic ( const String  name,
     else
     {
 	if (param.anyone_can_create_new_persons == FALSE
-	    && !ENA(create_pers, 0) )
+	    && !HAVE_PRIV(create_pers))
 	{
             err_stat = 0;
 	    kom_errno = KOM_PERM;
@@ -630,14 +631,25 @@ create_person_generic ( const String  name,
 
     mark_person_as_changed( new_user );
 
-    do_add_member( new_user, mailbox, new_user, pers_p, UCHAR_MAX, 0 );
+    mship_type.invitation = 0;
+    mship_type.passive = 0;
+    mship_type.secret = 0;
+    mship_type.reserved1 = 0;
+    mship_type.reserved2 = 0;
+    mship_type.reserved3 = 0;
+    mship_type.reserved4 = 0;
+    mship_type.reserved5 = 0;
+
+    do_add_member( new_user, mailbox, new_user, pers_p,
+                   UCHAR_MAX, 0, &mship_type );
 
     prepare_aux_item_list(conf_aux, new_user);
 
     if (conf_stat_check_add_aux_item_list(mailbox,
                                           new_user,
                                           conf_aux,
-                                          new_user) != OK)
+                                          new_user,
+                                          TRUE) != OK)
     {
         cached_delete_conf(new_user);
         cached_delete_person(new_user);
@@ -904,10 +916,19 @@ set_passwd (Pers_no	    person,
  *
  * Will fail if VICTIM is not a member of CONF_NO.
  */
+
 extern Success
 query_read_texts(Pers_no	  victim,
-		 Conf_no	  conf_no,
-		 Membership * result)	/* Points to area to store result in */
+                 Conf_no	  conf_no,
+                 Membership * result)	/* Points to area to store result in */
+{
+    return query_read_texts_old(victim, conf_no, result);
+}
+
+extern Success
+query_read_texts_old(Pers_no	  victim,
+                     Conf_no	  conf_no,
+                     Membership * result)	/* Points to area to store result in */
 {
     Person	* victim_p;
     Membership  * membp;
@@ -937,10 +958,19 @@ query_read_texts(Pers_no	  victim,
 	return FAILURE;
     }
 
+    if (membp->type.secret &&
+        !is_supervisor(victim, NULL, ACTPERS, ACT_P) &&
+        !ENA(admin, 4))
+    {
+        err_stat = conf_no;
+        kom_errno = KOM_NOT_MEMBER;
+        return FAILURE;
+    }
+
     *result = *membp;
 
     if ( victim_p->flags.unread_is_secret &&
-	victim_acc != unlimited)
+         victim_acc != unlimited)
     {
 	result->last_time_read = NO_TIME;
 	result->last_text_read = 0;
diff --git a/src/server/prot-a-output.c b/src/server/prot-a-output.c
index 771a5db6ae01db04225dcb71e1c7d6dd19e94c42..afbc08031511d5fee0042a8142e886c930ba14b8 100644
--- a/src/server/prot-a-output.c
+++ b/src/server/prot-a-output.c
@@ -1,5 +1,5 @@
 /*
- * $Id: prot-a-output.c,v 0.27 1997/09/13 15:32:17 byers Exp $
+ * $Id: prot-a-output.c,v 0.28 1998/06/14 14:51:01 byers Exp $
  * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -28,7 +28,7 @@
  * Written by ceder 1990-07-13
  */
 
-static char *rcsid = "$Id: prot-a-output.c,v 0.27 1997/09/13 15:32:17 byers Exp $";
+static char *rcsid = "$Id: prot-a-output.c,v 0.28 1998/06/14 14:51:01 byers Exp $";
 #include "rcs.h"
 USE(rcsid);
 
@@ -49,6 +49,7 @@ USE(rcsid);
 #include "mux.h"
 #include "prot-a-output.h"
 #include "lyskomd.h"
+#include "param.h"
 
 void
 prot_a_output_person (Connection *fp,
@@ -78,9 +79,32 @@ prot_a_output_person (Connection *fp,
 	     (unsigned long) person -> conferences.no_of_confs);
 }
 
+void prot_a_output_membership_type(Connection *fp,
+                                   const Membership_type type)
+{
+    mux_putc(' ', fp);
+    mux_putc(type.invitation + '0', fp);
+    mux_putc(type.passive    + '0', fp);
+    mux_putc(type.secret     + '0', fp);
+    mux_putc(type.reserved1  + '0', fp);
+    mux_putc(type.reserved2  + '0', fp);
+    mux_putc(type.reserved3  + '0', fp);
+    mux_putc(type.reserved4  + '0', fp);
+    mux_putc(type.reserved5  + '0', fp);
+}
+
+void prot_a_output_membership(Connection *fp,
+                              const Membership *mship)
+{
+    prot_a_output_membership_old(fp, mship);
+    mux_printf(fp, " %lu", (unsigned long)mship->added_by);
+    prot_a_output_time(fp, mship->added_at);
+    prot_a_output_membership_type(fp, mship->type);
+}
+
 void
-prot_a_output_membership(Connection *fp,
-			 const Membership *mship)
+prot_a_output_membership_old(Connection *fp,
+			     const Membership *mship)
 {
     int i;
     
@@ -105,9 +129,28 @@ prot_a_output_membership(Connection *fp,
 }
 
 	
+void
+prot_a_output_membership_list_old (Connection	* fp,
+                                   Membership_list	  mlist)
+{
+    int i;
+    
+    mux_printf(fp, " %lu", (unsigned long)mlist.no_of_confs);
+
+    if ( mlist.confs != NULL && mlist.no_of_confs > 0 )
+    {
+	mux_printf(fp, " {");
+	for ( i = 0; i < mlist.no_of_confs; i++)
+	    prot_a_output_membership_old(fp, mlist.confs + i);
+	mux_printf(fp, " }");
+    }
+    else
+	mux_printf(fp, " *");
+}
+
 void
 prot_a_output_membership_list (Connection	* fp,
-			       Membership_list	  mlist)
+                               Membership_list	  mlist)
 {
     int i;
     
@@ -124,7 +167,6 @@ prot_a_output_membership_list (Connection	* fp,
 	mux_printf(fp, " *");
 }
 
-
 void
 prot_a_output_conf_list(Connection *fp,
 			Conf_list_old conf_list)
@@ -259,7 +301,7 @@ prot_a_output_aux_item_flags(Connection *fp,
     mux_putc(flags.inherit + '0', fp);
     mux_putc(flags.secret + '0', fp);
     mux_putc(flags.hide_creator + '0', fp);
-    mux_putc(flags.reserved2 + '0', fp);
+    mux_putc(flags.dont_garb + '0', fp);
     mux_putc(flags.reserved3 + '0', fp);
     mux_putc(flags.reserved4 + '0', fp);
     mux_putc(flags.reserved5 + '0', fp);
@@ -587,7 +629,7 @@ prot_a_output_extended_conf_type(Connection *fp,
 
 extern void
 prot_a_output_member_list(Connection *fp,
-			  Member_list m_list)
+                          Member_list m_list)
 {
     int i;
 
@@ -603,10 +645,38 @@ prot_a_output_member_list(Connection *fp,
 	mux_printf(fp, " *");
 }
 
+extern void
+prot_a_output_member_list_old(Connection *fp,
+                              Member_list m_list)
+{
+    int i;
+
+    mux_printf(fp, " %lu", (unsigned long)m_list.no_of_members);
+    if ( m_list.members != NULL && m_list.no_of_members > 0 )
+    {
+	mux_printf(fp, " {");
+	for ( i = 0; i < m_list.no_of_members; i++ )
+	    prot_a_output_member_old(fp, m_list.members[ i ]);
+	mux_printf(fp, " }");
+    }
+    else
+	mux_printf(fp, " *");
+}
+
 
 void
 prot_a_output_member(Connection *fp,
 		     Member member)
+{
+    mux_printf(fp, " %lu", (unsigned long)member.member);
+    mux_printf(fp, " %lu", (unsigned long)member.added_by);
+    prot_a_output_time(fp, member.added_at);
+    prot_a_output_membership_type(fp, member.type);
+}
+
+void
+prot_a_output_member_old(Connection *fp,
+		     Member member)
 {
     mux_printf(fp, " %lu", (unsigned long)member.member);
 }
@@ -689,15 +759,15 @@ prot_a_output_time(Connection *fp,
     time = localtime( &clock );
 
     mux_printf(fp, " %lu %lu %lu %lu %lu %lu %lu %lu %lu",
-	    (unsigned long) time -> tm_sec,
-	    (unsigned long) time -> tm_min,
-	    (unsigned long) time -> tm_hour,
-	    (unsigned long) time -> tm_mday,
-	    (unsigned long) time -> tm_mon,
-	    (unsigned long) time -> tm_year,
-	    (unsigned long) time -> tm_wday,
-	    (unsigned long) time -> tm_yday,
-	    (unsigned long) time -> tm_isdst);
+               (unsigned long) time -> tm_sec,
+               (unsigned long) time -> tm_min,
+               (unsigned long) time -> tm_hour,
+               (unsigned long) time -> tm_mday,
+               (unsigned long) time -> tm_mon,
+               (unsigned long) time -> tm_year,
+               (unsigned long) time -> tm_wday,
+               (unsigned long) time -> tm_yday,
+               (unsigned long) time -> tm_isdst);
 }
 
 
diff --git a/src/server/prot-a-output.h b/src/server/prot-a-output.h
index cc898157ff95705c45df28aa6c33bc24e8e38959..b319dbf8557cbb5a8a57168c717774abb8b2fd00 100644
--- a/src/server/prot-a-output.h
+++ b/src/server/prot-a-output.h
@@ -1,5 +1,5 @@
 /*
- * $Id: prot-a-output.h,v 0.15 1997/09/13 15:32:18 byers Exp $
+ * $Id: prot-a-output.h,v 0.16 1998/06/14 14:51:04 byers Exp $
  * Copyright (C) 1991, 1992, 1994, 1995, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -23,7 +23,7 @@
  * Please mail bug reports to bug-lyskom@lysator.liu.se. 
  */
 /*
- * $Id: prot-a-output.h,v 0.15 1997/09/13 15:32:18 byers Exp $
+ * $Id: prot-a-output.h,v 0.16 1998/06/14 14:51:04 byers Exp $
  *
  */
 extern void
@@ -39,10 +39,22 @@ extern void
 prot_a_output_membership(Connection *fp,
 			 const Membership *mship);
 
+extern void
+prot_a_output_membership_old(Connection *fp,
+                             const Membership *mship);
+
 extern void
 prot_a_output_membership_list(Connection *fp,
 			      Membership_list mlist);
 
+extern void
+prot_a_output_membership_list_old(Connection *fp,
+                                  Membership_list mlist);
+
+extern void
+prot_a_output_membership_type(Connection *fp,
+                              const Membership_type type);
+
 extern void
 prot_a_output_conf_list(Connection *fp,
 			Conf_list_old conf_list);
@@ -148,6 +160,10 @@ extern void
 prot_a_output_member_list(Connection *fp,
 			  Member_list m_list);
 
+extern void
+prot_a_output_member_list_old(Connection *fp,
+                              Member_list m_list);
+
 extern void
 prot_a_output_mark(Connection *fp,
 		   Mark mark);
@@ -160,6 +176,10 @@ extern void
 prot_a_output_member(Connection *fp,
 		     Member member);
 
+extern void
+prot_a_output_member_old(Connection *fp,
+                         Member member);
+
 void
 prot_a_output_time(Connection *fp,
 		   time_t clock);
diff --git a/src/server/prot-a-parse-arg-c.awk b/src/server/prot-a-parse-arg-c.awk
index 69149c78d19ff50553066070621232441767258d..76885d5a8eea11e1d55fc5ce4f234202052ac4c2 100644
--- a/src/server/prot-a-parse-arg-c.awk
+++ b/src/server/prot-a-parse-arg-c.awk
@@ -1,5 +1,5 @@
 #
-# $Id: prot-a-parse-arg-c.awk,v 0.17 1997/09/13 15:32:19 byers Exp $
+# $Id: prot-a-parse-arg-c.awk,v 0.18 1998/06/14 14:51:06 byers Exp $
 # Copyright (C) 1991, 1992, 1993, 1994, 1996  Lysator Academic Computer Association.
 #
 # This file is part of the LysKOM server.
@@ -22,7 +22,7 @@
 #
 # Please mail bug reports to bug-lyskom@lysator.liu.se. 
 #
-# $Id: prot-a-parse-arg-c.awk,v 0.17 1997/09/13 15:32:19 byers Exp $
+# $Id: prot-a-parse-arg-c.awk,v 0.18 1998/06/14 14:51:06 byers Exp $
 BEGIN {
     printf("/* Don't edit this file - it is generated automatically");
     printf(" from\n   prot-a-parse-arg-c.awk and fncdef.txt */\n\n");
@@ -71,6 +71,8 @@ $1 != "#" {
 	    printf("\tprot_a_parse_priv_bits(client, &client->priv_bits);\n");
 	else if ( $i == "conf_type" )
 	    printf("\tprot_a_parse_conf_type(client, &client->conf_type);\n");
+	else if ( $i == "membership_type" )
+	    printf("\tprot_a_parse_membership_type(client, &client->membership_type);\n");
 	else if ( $i == "c_local_text_no_p" )
 	{
 	    printf("\tif ( parse_nonwhite_char(client) != '{' )\n");
diff --git a/src/server/prot-a-parse.c b/src/server/prot-a-parse.c
index b43c3eb3ff1bb5d89cf157bf1b424ae650453b81..2e8f00782ec4910e6a84eced601f56a6d0ecf2e8 100644
--- a/src/server/prot-a-parse.c
+++ b/src/server/prot-a-parse.c
@@ -1,5 +1,5 @@
 /*
- * $Id: prot-a-parse.c,v 0.30 1997/09/13 15:32:20 byers Exp $
+ * $Id: prot-a-parse.c,v 0.31 1998/06/14 14:51:07 byers Exp $
  * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -28,7 +28,7 @@
  * BUG: Not all functions are used, I think. /ceder
  */
 
-static char *rcsid = "$Id: prot-a-parse.c,v 0.30 1997/09/13 15:32:20 byers Exp $";
+static char *rcsid = "$Id: prot-a-parse.c,v 0.31 1998/06/14 14:51:07 byers Exp $";
 #include "rcs.h"
 USE(rcsid);
 
@@ -207,6 +207,26 @@ prot_a_parse_priv_bits(Connection *client,
     res->flg16 = token.string[ 15 ] != '0';
 }
 
+void
+prot_a_parse_membership_type(Connection *client,
+                             Membership_type *res)
+{
+    String token;
+
+    token = prot_a_get_token(client);
+    if (s_strlen(token) != 8)
+	longjmp(parse_env, ISC_PROTOCOL_ERR);
+  
+    res->invitation = token.string[ 0 ] != '0';
+    res->passive    = token.string[ 1 ] != '0';
+    res->secret     = token.string[ 2 ] != '0';
+    res->reserved1  = token.string[ 3 ] != '0';
+    res->reserved2  = token.string[ 4 ] != '0';
+    res->reserved3  = token.string[ 5 ] != '0';
+    res->reserved4  = token.string[ 6 ] != '0';
+    res->reserved5  = token.string[ 7 ] != '0';
+}
+
 void
 prot_a_parse_conf_type(Connection *client,
 		Conf_type      *res)
@@ -370,7 +390,7 @@ prot_a_parse_aux_item_flags(Connection *client,
     res->inherit    = token.string[ 1 ] != '0';
     res->secret     = token.string[ 2 ] != '0';
     res->hide_creator = token.string[ 3 ] != '0';
-    res->reserved2  = token.string[ 4 ] != '0';
+    res->dont_garb  = token.string[ 4 ] != '0';
     res->reserved3  = token.string[ 5 ] != '0';
     res->reserved4  = token.string[ 6 ] != '0';
     res->reserved5  = token.string[ 7 ] != '0';
diff --git a/src/server/prot-a-parse.h b/src/server/prot-a-parse.h
index 6b86739d03286364bc9203db24ff7183357b11d9..773f4b2fbdc839a7d63bd369db32a074c9110921 100644
--- a/src/server/prot-a-parse.h
+++ b/src/server/prot-a-parse.h
@@ -1,5 +1,5 @@
 /*
- * $Id: prot-a-parse.h,v 0.14 1997/09/13 15:32:22 byers Exp $
+ * $Id: prot-a-parse.h,v 0.15 1998/06/14 14:51:09 byers Exp $
  * Copyright (C) 1991, 1992, 1994, 1995, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -23,7 +23,7 @@
  * Please mail bug reports to bug-lyskom@lysator.liu.se. 
  */
 /*
- * $Id: prot-a-parse.h,v 0.14 1997/09/13 15:32:22 byers Exp $
+ * $Id: prot-a-parse.h,v 0.15 1998/06/14 14:51:09 byers Exp $
  *
  */
 extern long
@@ -38,6 +38,10 @@ extern void
 prot_a_parse_priv_bits(Connection *client,
 		       Priv_bits  *result);
 
+extern void
+prot_a_parse_membership_type(Connection *client,
+                             Membership_type *res);
+
 extern void
 prot_a_parse_conf_type(Connection *client,
 		       Conf_type      *result);
diff --git a/src/server/prot-a.c b/src/server/prot-a.c
index b4fc40d8432eac4c68caa0170a30694b09f42f2c..ec062b59a459959bf1552cc25064bdd7582f0dff 100644
--- a/src/server/prot-a.c
+++ b/src/server/prot-a.c
@@ -1,5 +1,5 @@
 /*
- * $Id: prot-a.c,v 0.44 1997/09/13 15:32:24 byers Exp $
+ * $Id: prot-a.c,v 0.45 1998/06/14 14:51:10 byers Exp $
  * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -26,7 +26,7 @@
  * Protocol A.
  */
 
-static char *rcsid = "$Id: prot-a.c,v 0.44 1997/09/13 15:32:24 byers Exp $";
+static char *rcsid = "$Id: prot-a.c,v 0.45 1998/06/14 14:51:10 byers Exp $";
 #include "rcs.h"
 USE(rcsid);
 
@@ -90,6 +90,11 @@ prot_a_reply(Connection *client,
 	    BUG(("={Person struct not listed}\n"));
 	    break;
 
+	case rt_membership_old:
+	    prot_a_output_membership_old(client, &res->membership);
+	    BUG(("={Membership struct not listed}\n"));
+	    break;
+
 	case rt_membership:
 	    prot_a_output_membership(client, &res->membership);
 	    BUG(("={Membership struct not listed}\n"));
@@ -178,11 +183,21 @@ prot_a_reply(Connection *client,
 	    BUG (("={Membership_list not listed}\n"));
 	    break;
 	    
+	case rt_membership_list_old:
+	    prot_a_output_membership_list_old (client, res->membership_list);
+	    BUG (("={Membership_list not listed}\n"));
+	    break;
+	    
 	case rt_member_list:
 	    prot_a_output_member_list (client, res->member_list);
 	    BUG(("={Member_list not listed}\n"));
 	    break;
 
+	case rt_member_list_old:
+	    prot_a_output_member_list_old (client, res->member_list);
+	    BUG(("={Member_list not listed}\n"));
+	    break;
+
 	case rt_time_date:
 	    prot_a_output_time (client, res->time_date);
 	    BUG(("=(time_t)%lu\n", (unsigned long)res->time_date));
@@ -331,12 +346,12 @@ prot_a_is_legal_fnc(Call_header fnc)
     case call_fnc_create_person_old:
     case call_fnc_set_priv_bits:
     case call_fnc_set_passwd:
-    case call_fnc_query_read_texts:
+    case call_fnc_query_read_texts_old:
     case call_fnc_create_conf_old:
     case call_fnc_delete_conf:
     case call_fnc_lookup_name:
     case call_fnc_get_conf_stat_older:
-    case call_fnc_add_member:
+    case call_fnc_add_member_old:
     case call_fnc_sub_member:
     case call_fnc_set_presentation:
     case call_fnc_set_etc_motd:
@@ -368,9 +383,9 @@ prot_a_is_legal_fnc(Call_header fnc)
     case call_fnc_sync_kom:
     case call_fnc_shutdown_kom:
     case call_fnc_broadcast:
-    case call_fnc_get_membership:
+    case call_fnc_get_membership_old:
     case call_fnc_get_created_texts:
-    case call_fnc_get_members:
+    case call_fnc_get_members_old:
     case call_fnc_get_person_stat_old:
     case call_fnc_get_conf_stat_old:
     case call_fnc_who_is_on:
@@ -421,6 +436,11 @@ prot_a_is_legal_fnc(Call_header fnc)
     case call_fnc_modify_server_info:
     case call_fnc_query_predefined_aux_items:
     case call_fnc_set_expire:
+    case call_fnc_query_read_texts:
+    case call_fnc_add_member:
+    case call_fnc_get_membership:
+    case call_fnc_get_members:
+    case call_fnc_set_membership_type:
 	return TRUE;
 
     default:
diff --git a/src/server/ram-output.c b/src/server/ram-output.c
index 3f3fcffe61db8401ec86ce1fe4d253aa487bd60a..938b1556d2fc3481c57a04afd299679ff3020faa 100644
--- a/src/server/ram-output.c
+++ b/src/server/ram-output.c
@@ -1,5 +1,5 @@
 /*
- * $Id: ram-output.c,v 0.22 1997/09/13 15:32:26 byers Exp $
+ * $Id: ram-output.c,v 0.23 1998/06/14 14:51:12 byers Exp $
  * Copyright (C) 1991, 1993, 1994, 1995, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -33,7 +33,7 @@
  * (It worked - now saving is twice as fast.)
  */
 
-static char *rcsid = "$Id: ram-output.c,v 0.22 1997/09/13 15:32:26 byers Exp $";
+static char *rcsid = "$Id: ram-output.c,v 0.23 1998/06/14 14:51:12 byers Exp $";
 #include "rcs.h"
 USE(rcsid);
 
@@ -68,7 +68,8 @@ set_output_format(int fmt)
     }   
 }
 
-void foutput_info_0(FILE *fp, Info *info)
+static void
+foutput_info_0(FILE *fp, Info *info)
 {
     fprintf(fp, " %lu %lu %lu %lu %lu",
 	    (unsigned long)info->conf_pres_conf,
@@ -78,7 +79,8 @@ void foutput_info_0(FILE *fp, Info *info)
 	    (unsigned long)info->motd_of_lyskom);
 }
 
-void foutput_info_2(FILE *fp, Info *info)
+static void
+foutput_info_2(FILE *fp, Info *info)
 {
     fprintf(fp, " %lu %lu %lu %lu %lu %lu",
 	    (unsigned long)info->conf_pres_conf,
@@ -109,7 +111,7 @@ void foutput_info(FILE *fp, Info *info)
 }
 
 
-void
+static void
 foutput_person_0 (FILE *fp,
                   Person *person)
 {
@@ -137,7 +139,7 @@ foutput_person_0 (FILE *fp,
 	     (unsigned long) person -> created_confs);
 }
 
-void
+static void
 foutput_person_2 (FILE *fp,
 		Person *person)
 {
@@ -185,7 +187,7 @@ foutput_person (FILE *fp,
 }
 
 
-void
+static void
 foutput_conference_2 (FILE *fp,
 		    Conference *conf_c)
 {
@@ -210,7 +212,7 @@ foutput_conference_2 (FILE *fp,
     foutput_aux_item_list(fp, &conf_c->aux_item_list);
 }
 
-void
+static void
 foutput_conference_1 (FILE *fp,
 		    Conference *conf_c)
 {
@@ -232,14 +234,14 @@ foutput_conference_1 (FILE *fp,
 	     (unsigned long) conf_c -> nice);
 }
 
-void
+static void
 foutput_conference_0 (FILE *fp,
-                        Conference *conf_c)
+                      Conference *conf_c)
 {
     foutput_string(fp, conf_c->name);
     foutput_member_list(fp, conf_c->members);
     foutput_text_list(fp, conf_c->texts);
-    foutput_conf_type_0(fp, conf_c->type);
+    foutput_conf_type(fp, conf_c->type);
 
     foutput_time(fp, conf_c -> creation_time );
     foutput_time(fp, conf_c -> last_written );
@@ -276,7 +278,7 @@ void foutput_conference(FILE *fp,
 
 
 
-void
+static void
 foutput_text_stat_0(FILE *fp,
                     Text_stat *t_stat)
 {
@@ -302,7 +304,7 @@ foutput_text_stat_0(FILE *fp,
 	fputs(" *", fp);
 }
 
-void
+static void
 foutput_text_stat_2(FILE *fp,
                     Text_stat *t_stat)
 {
@@ -361,7 +363,7 @@ foutput_aux_flags(FILE *fp,
     putc(f.inherit + '0', fp);
     putc(f.secret + '0', fp);
     putc(f.hide_creator + '0', fp);
-    putc(f.reserved2 + '0', fp);
+    putc(f.dont_garb + '0', fp);
     putc(f.reserved3 + '0', fp);
     putc(f.reserved4 + '0', fp);
     putc(f.reserved5 + '0', fp);
@@ -399,6 +401,110 @@ foutput_aux_item_list(FILE *fp,
 }
 		      
 
+void
+foutput_membership_type(FILE *fp,
+                        Membership_type type)
+{
+    putc(' ', fp);
+    putc(type.invitation + '0', fp);
+    putc(type.passive    + '0', fp);
+    putc(type.secret     + '0', fp);
+    putc(type.reserved1  + '0', fp);
+    putc(type.reserved2  + '0', fp);
+    putc(type.reserved3  + '0', fp);
+    putc(type.reserved4  + '0', fp);
+    putc(type.reserved5  + '0', fp);
+}
+
+static void
+foutput_membership_0(FILE *fp,
+		   Membership *mship)
+{
+    int i;
+    
+    foutput_time(fp, mship->last_time_read );
+    
+    if ( mship->read_texts == NULL && mship->no_of_read != 0 )
+    {
+	log("%s(): no_of_read forced to 0 in a membership in %lu.\n",
+	    "foutput_membership", (unsigned long)mship->conf_no);
+	mship->no_of_read = 0;
+    }
+    
+    fprintf(fp, " %lu %lu %lu %lu",
+	    (unsigned long)mship->conf_no,
+	    (unsigned long)mship->priority,
+	    (unsigned long)mship->last_text_read,
+	    (unsigned long)mship->no_of_read);
+    
+    if ( mship->read_texts != NULL && mship->no_of_read > 0)
+    {
+	fprintf(fp, " {");
+	for ( i = 0; i < mship->no_of_read; i++)
+	    fprintf(fp, " %lu", (unsigned long)mship->read_texts[ i ]);
+	
+	fprintf(fp, " }");
+    }
+    else
+	fprintf(fp, " *");
+}
+
+static void
+foutput_membership_2(FILE *fp,
+                     Membership *mship)
+{
+    int i;
+    
+    foutput_time(fp, mship->last_time_read );
+    
+    if ( mship->read_texts == NULL && mship->no_of_read != 0 )
+    {
+	log("%s(): no_of_read forced to 0 in a membership in %lu.\n",
+	    "foutput_membership", (unsigned long)mship->conf_no);
+	mship->no_of_read = 0;
+    }
+    
+    fprintf(fp, " %lu %lu %lu %lu",
+	    (unsigned long)mship->conf_no,
+	    (unsigned long)mship->priority,
+	    (unsigned long)mship->last_text_read,
+	    (unsigned long)mship->no_of_read);
+    
+    if ( mship->read_texts != NULL && mship->no_of_read > 0)
+    {
+	fprintf(fp, " {");
+	for ( i = 0; i < mship->no_of_read; i++)
+	    fprintf(fp, " %lu", (unsigned long)mship->read_texts[ i ]);
+	
+	fprintf(fp, " }");
+    }
+    else
+	fprintf(fp, " *");
+    fprintf(fp, " %lu", (unsigned long)mship->added_by);
+    foutput_time(fp, mship->added_at);
+    foutput_membership_type(fp, mship->type);
+}
+
+
+void
+foutput_membership(FILE *fp,
+                   Membership *mship)
+{
+    switch (output_format)
+    {
+    case 0:
+        foutput_membership_0(fp, mship);
+        break;
+    case 1:
+    case 2:
+        foutput_membership_2(fp, mship);
+        break;
+    default:
+        restart_kom("unknown database format: %d", output_format);
+        break;
+    }
+}
+
 
 
 extern void
@@ -500,9 +606,9 @@ foutput_mark(FILE *fp,
     fprintf(fp, " %lu %lu", (unsigned long)mark.text_no, (unsigned long)mark.mark_type);
 }
 
-void
-foutput_membership_list (FILE		* fp,
-			 Membership_list  mlist)
+static void
+foutput_membership_list_0 (FILE		* fp,
+                           Membership_list  mlist)
 {
     int i;
     
@@ -512,48 +618,51 @@ foutput_membership_list (FILE		* fp,
     {
 	fprintf(fp, " {");
 	for ( i = 0; i < mlist.no_of_confs; i++)
-	    foutput_membership(fp, mlist.confs + i);
+	    foutput_membership_0(fp, mlist.confs + i);
 	fprintf(fp, " }");
     }
     else
 	fprintf(fp, " *");
 }
 
-
-
-void
-foutput_membership(FILE *fp,
-		   Membership *mship)
+static void
+foutput_membership_list_2 (FILE		* fp,
+                           Membership_list  mlist)
 {
     int i;
     
-    foutput_time(fp, mship->last_time_read );
-    
-    if ( mship->read_texts == NULL && mship->no_of_read != 0 )
-    {
-	log("%s(): no_of_read forced to 0 in a membership in %lu.\n",
-	    "foutput_membership", (unsigned long)mship->conf_no);
-	mship->no_of_read = 0;
-    }
-    
-    fprintf(fp, " %lu %lu %lu %lu",
-	    (unsigned long)mship->conf_no,
-	    (unsigned long)mship->priority,
-	    (unsigned long)mship->last_text_read,
-	    (unsigned long)mship->no_of_read);
-    
-    if ( mship->read_texts != NULL && mship->no_of_read > 0)
+    fprintf(fp, " %lu", (unsigned long)mlist.no_of_confs);
+
+    if ( mlist.confs != NULL && mlist.no_of_confs > 0 )
     {
 	fprintf(fp, " {");
-	for ( i = 0; i < mship->no_of_read; i++)
-	    fprintf(fp, " %lu", (unsigned long)mship->read_texts[ i ]);
-	
+	for ( i = 0; i < mlist.no_of_confs; i++)
+	    foutput_membership_2(fp, mlist.confs + i);
 	fprintf(fp, " }");
     }
     else
 	fprintf(fp, " *");
 }
 
+void
+foutput_membership_list(FILE        * fp,
+                        Membership_list mlist)
+{
+    switch (output_format)
+    {
+    case 0:
+        foutput_membership_list_0(fp, mlist);
+        break;
+    case 1:
+    case 2:
+        foutput_membership_list_2(fp, mlist);
+        break;
+    default:
+        restart_kom("unknown database format: %d", output_format);
+        break;
+    }    
+}
+
 void
 foutput_time(FILE *fp,
 	     time_t clock)
@@ -581,14 +690,44 @@ foutput_member_list(FILE *fp,
 }
 
 
+static void
+foutput_member_0(FILE *fp,
+                 Member member)
+{
+    fprintf(fp, " %lu", (unsigned long)member.member);
+}
+
+static void
+foutput_member_2(FILE *fp,
+                 Member member)
+{
+    fprintf(fp, " %lu %lu",
+            (unsigned long)member.member,
+            (unsigned long)member.added_by);
+    foutput_time(fp, member.added_at);
+    foutput_membership_type(fp, member.type);
+}
+
 void
 foutput_member(FILE *fp,
 	       Member member)
 {
-    fprintf(fp, " %lu", (unsigned long)member.member);
+    switch (output_format)
+    {
+    case 0:
+    case 1:
+        foutput_member_0(fp, member);
+        break;
+    case 2:
+        foutput_member_2(fp, member);
+        break;
+    default:
+        restart_kom("unknown database format: %d", output_format);
+        break;
+    }
 }
 
-extern void
+static void
 foutput_conf_type_1(FILE *fp,
                     Conf_type type)
 {
@@ -603,9 +742,9 @@ foutput_conf_type_1(FILE *fp,
     putc(type.reserved3 + '0', fp);
 }
 
-extern void
+static void
 foutput_conf_type_0(FILE *fp,
-		  Conf_type type)
+                    Conf_type type)
 {
     putc(' ', fp);
     putc(type.rd_prot + '0', fp);
diff --git a/src/server/ram-output.h b/src/server/ram-output.h
index 9f4b8a638a651defc7fe4dac26c293428ea6a384..de22f68240f69047caf6045892bd07cad1a139d4 100644
--- a/src/server/ram-output.h
+++ b/src/server/ram-output.h
@@ -1,5 +1,5 @@
 /*
- * $Id: ram-output.h,v 0.10 1997/09/13 15:32:27 byers Exp $
+ * $Id: ram-output.h,v 0.11 1998/06/14 14:51:14 byers Exp $
  * Copyright (C) 1991, 1993, 1994, 1995, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -23,7 +23,7 @@
  * Please mail bug reports to bug-lyskom@lysator.liu.se. 
  */
 /*
- * $Id: ram-output.h,v 0.10 1997/09/13 15:32:27 byers Exp $
+ * $Id: ram-output.h,v 0.11 1998/06/14 14:51:14 byers Exp $
  *
  * ram-output.c  -  write objects to disk.
  *
@@ -46,14 +46,6 @@ void
 foutput_conference (FILE *fp,
 		    Conference *conf_c);
 
-void
-foutput_conference_0 (FILE *fp,
-		    Conference *conf_c);
-
-void
-foutput_text_stat_9(FILE *fp,
-                    Text_stat *t_stat);
-
 void
 foutput_aux_item_list(FILE *fp,
 		      Aux_item_list *list);
@@ -95,6 +87,10 @@ void
 foutput_membership_list (FILE		* fp,
 			 Membership_list  mlist);
 
+void
+foutput_membership_type (FILE           * fp,
+                         Membership_type type);
+
 void
 foutput_membership(FILE *fp,
 		   Membership *mship);
@@ -113,10 +109,6 @@ extern void
 foutput_conf_type(FILE *fp,
 		  Conf_type type);
 
-extern void
-foutput_conf_type_0(FILE *fp,
-		  Conf_type type);
-
 extern void
 foutput_misc_info(FILE *fp, 
 		  Misc_info misc);
diff --git a/src/server/ram-parse.c b/src/server/ram-parse.c
index d2811d3a057aed52b4f219a9620d2c1a25a37062..47023b0d5aba6ff30477b093d5bf7c3dbf9cb8a5 100644
--- a/src/server/ram-parse.c
+++ b/src/server/ram-parse.c
@@ -1,5 +1,5 @@
 /*
- * $Id: ram-parse.c,v 0.26 1997/09/13 15:32:29 byers Exp $
+ * $Id: ram-parse.c,v 0.27 1998/06/14 14:51:15 byers Exp $
  * Copyright (C) 1991, 1993, 1994, 1995, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -29,7 +29,7 @@
  * ram-parse.c -- parse objects from disk file.
  */
 
-static char *rcsid = "$Id: ram-parse.c,v 0.26 1997/09/13 15:32:29 byers Exp $";
+static char *rcsid = "$Id: ram-parse.c,v 0.27 1998/06/14 14:51:15 byers Exp $";
 #include "rcs.h"
 USE(rcsid);
 
@@ -532,8 +532,26 @@ fparse_person(FILE *fp,
 }
 
 static Success
-fparse_membership(FILE *fp,
-		 Membership *mship)
+fparse_membership_type(FILE *fp,
+                       Membership_type *result)
+{
+    fskipwhite(fp);
+    
+    result->invitation = getc(fp) != '0';
+    result->passive    = getc(fp) != '0';
+    result->secret     = getc(fp) != '0';
+    result->reserved1  = getc(fp) != '0';
+    result->reserved2  = getc(fp) != '0';
+    result->reserved3  = getc(fp) != '0';
+    result->reserved4  = getc(fp) != '0';
+    result->reserved5  = getc(fp) != '0';
+
+    return OK;
+}
+
+static Success
+fparse_membership_2(FILE *fp,
+                    Membership *mship)
 {
     int i;
     
@@ -611,13 +629,212 @@ fparse_membership(FILE *fp,
 	}
     }
 
+    mship->added_by = fparse_long(fp);
+    mship->added_at = fparse_time(fp);
+    if (fparse_membership_type(fp, &mship->type) != OK)
+        return FAILURE;
+
     return OK;
 }
 
+static Success
+fparse_membership_0(FILE *fp,
+                    Membership *mship)
+{
+    int i;
+    
+    mship->last_time_read = fparse_time(fp);
+
+    mship->conf_no = fparse_long(fp);
+    mship->priority = fparse_long(fp);
+    mship->last_text_read = fparse_long(fp);
+    mship->no_of_read = fparse_long(fp);
+
+    if ( mship->no_of_read > 0)
+    {
+	fskipwhite(fp);
+	switch(getc(fp))
+	{
+	case '{':
+	    mship->read_texts
+		= REALLOC(mship->read_texts, (mship->no_of_read
+					      * sizeof(Local_text_no)));
+	    if ( mship->read_texts == NULL )
+	    {
+                err_stat = 0;
+		kom_errno = KOM_OUT_OF_MEMORY;
+		return FAILURE;
+	    }
+
+	    for ( i = 0; i < mship->no_of_read; i++)
+		mship->read_texts[ i ] = fparse_long(fp);
+
+	    fskipwhite(fp);
+	    if ( getc(fp) != '}' )
+	    {
+                err_stat = 1;
+		kom_errno = KOM_LDB_ERR;
+		log("fparse_membership(): expected '}' at pos %lu.\n",
+		    (unsigned long)ftell(fp));
+		return FAILURE;
+	    }
+	    break;
+	    
+	case '*':
+	    if ( mship->read_texts != NULL )
+	    {
+		sfree(mship->read_texts);
+		mship->read_texts = NULL;
+	    }
+	    log("fparse_membership(): %s with %lu elements (corrected)\n",
+		"empty read_texts", (unsigned long)mship->no_of_read);
+	    mship->no_of_read = 0;
+	    break;
+	default:
+	    log("fparse_membership(): expected '*' or '{' at pos %lu.\n",
+		(unsigned long)ftell(fp));
+            err_stat = 2;
+	    kom_errno = KOM_LDB_ERR;
+	    return FAILURE;
+	}
+    }
+    else
+    {
+	fskipwhite(fp);
+	if ( getc(fp) != '*' ) 
+	{
+	    log("fparse_membership(): expected '*' at pos %lu.\n",
+		(unsigned long)ftell(fp));
+            err_stat = 3;
+	    kom_errno = KOM_LDB_ERR;
+	    return FAILURE;
+	}
+
+	if ( mship->read_texts != NULL )
+	{
+	    sfree(mship->read_texts);
+	    mship->read_texts = NULL;
+	}
+    }
+
+    return OK;
+}
+
+static Success
+fparse_membership(FILE *fp,
+                  Membership *mship)
+{
+    switch(input_format)
+    {
+    case 0:
+    case 1:
+        return fparse_membership_0(fp, mship);
+        break;
+    case 2:
+        return fparse_membership_2(fp, mship);
+        break;
+    default:
+        restart_kom("unknown input format: %d\n", input_format);
+        return FAILURE;
+        break;
+    }
+}
+
+
 	
-extern Success
-fparse_membership_list(FILE *fp,
-		       Membership_list *result)
+static Success
+fparse_membership_list_0(FILE *fp,
+                         Membership_list *result)
+{
+    int i;
+    
+    /* First free all the read_texts. */
+
+    if ( result->confs != NULL )
+    {
+	for ( i = 0; i < result->no_of_confs; i++)
+	    sfree(result->confs[ i ].read_texts);
+    }
+    
+    result->no_of_confs = fparse_long(fp);
+
+    if ( result->no_of_confs > 0 )
+    {
+	fskipwhite(fp);
+	switch(getc(fp))
+	{
+	case '{':
+	    result->confs = REALLOC(result->confs,
+					  (result->no_of_confs
+					   * sizeof(Membership)));
+	    if ( result->confs == NULL && result->no_of_confs > 0 )
+	    {
+                err_stat = 0;
+		kom_errno = KOM_OUT_OF_MEMORY;
+		return FAILURE;
+	    }
+
+	    for ( i = 0; i < result->no_of_confs; i++)
+	    {
+	        init_membership(&result->confs[ i ]);
+		if ( fparse_membership_0(fp, &result->confs[i]) != OK )
+		    return FAILURE;
+	    }
+	    
+	    fskipwhite(fp);
+	    if ( getc(fp) != '}' )
+	    {
+		log("fparse_membership_list(): expected '}' at pos %lu.\n",
+		    (unsigned long)ftell(fp));
+                err_stat = 4;
+		kom_errno = KOM_LDB_ERR;
+		return FAILURE;
+	    }
+	    
+	    break;
+	case '*':
+	    if ( result->confs != NULL )
+	    {
+		sfree(result->confs);
+		result->confs = NULL;
+	    }
+	    log("%s empty list with %lu elements (corrected).\n",
+		"fparse_membership_list():",
+		(unsigned long)result->no_of_confs);
+	    
+	    result->no_of_confs = 0;
+	    break;
+	default:
+	    log("fparse_membership_list(): expected '*' or '{' at pos %lu.\n",
+		(unsigned long)ftell(fp));
+            err_stat = 5;
+	    kom_errno = KOM_LDB_ERR;
+	    return FAILURE;
+	}
+    }
+    else
+    {
+	fskipwhite(fp);
+	if ( getc(fp) != '*' ) 
+	{
+	    log("fparse_membership_list(): expected '*' at pos %lu.\n",
+		(unsigned long)ftell(fp));
+            err_stat = 6;
+	    kom_errno = KOM_LDB_ERR;
+	    return FAILURE;
+	}
+	if ( result->confs != NULL )
+	{
+	    sfree(result->confs);
+	    result->confs = NULL;
+	}
+    }
+    return OK;
+}
+
+static Success
+fparse_membership_list_2(FILE *fp,
+                         Membership_list *result)
 {
     int i;
     
@@ -706,6 +923,28 @@ fparse_membership_list(FILE *fp,
 }
 
 
+extern Success
+fparse_membership_list(FILE *fp,
+                       Membership_list *result)
+{
+    switch(input_format)
+    {
+    case 0:
+    case 1:
+        return fparse_membership_list_0(fp, result);
+        break;
+    case 2:
+        return fparse_membership_list_2(fp, result);
+        break;
+    default:
+        restart_kom("unknown input format: %d\n", input_format);
+        return FAILURE;
+        break;
+    }
+}
+
+
+
 extern Success
 fparse_conf_list(FILE *fp,
 		Conf_list_old *result)
@@ -1423,12 +1662,41 @@ fparse_member_list(FILE *fp,
 }
 
 
+static Success
+fparse_member_0(FILE *fp,
+                Member *result)
+{
+    result->member = fparse_long(fp);
+    return OK;
+}
+
+static Success
+fparse_member_2(FILE *fp,
+                Member *result)
+{
+    result->member = fparse_long(fp);
+    result->added_by = fparse_long(fp);
+    result->added_at = fparse_time(fp);
+    return fparse_membership_type(fp, &result->type);
+}
+
 extern Success
 fparse_member(FILE *fp,
 	     Member *result)
 {
-    result->member = fparse_long(fp);
-    return OK;
+    switch (input_format)
+    {
+    case 0:
+    case 1:
+        return fparse_member_0(fp, result);
+        break;
+    case 2:
+        return fparse_member_2(fp, result);
+        break;
+    default:
+        restart_kom("unknown database format: %d", input_format);
+        return FAILURE;
+    }
 }
 
 extern Success
@@ -1630,7 +1898,7 @@ fparse_aux_item_flags(FILE *fp,
     f->inherit = getc(fp) != '0';
     f->secret = getc(fp) != '0';
     f->hide_creator = getc(fp) != '0';
-    f->reserved2 = getc(fp) != '0';
+    f->dont_garb = getc(fp) != '0';
     f->reserved3 = getc(fp) != '0';
     f->reserved4 = getc(fp) != '0';
     f->reserved5 = getc(fp) != '0';
diff --git a/src/server/server-config.c b/src/server/server-config.c
index 72436dd4accb28953dcee535af07125a5cd47392..4ba5eaf8cdc29ffdff7fbef2d3eca657f375298b 100644
--- a/src/server/server-config.c
+++ b/src/server/server-config.c
@@ -1,5 +1,5 @@
 /*
- * $Id: server-config.c,v 0.43 1997/09/13 15:32:36 byers Exp $
+ * $Id: server-config.c,v 0.44 1998/06/14 14:51:18 byers Exp $
  * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -31,7 +31,7 @@
  *  Compile with -DDEFAULT_PREFIX='"/usr/lyskom"' or something similar.
  */
 
-static char *rcsid = "$Id: server-config.c,v 0.43 1997/09/13 15:32:36 byers Exp $";
+static char *rcsid = "$Id: server-config.c,v 0.44 1998/06/14 14:51:18 byers Exp $";
 #include "rcs.h"
 USE(rcsid);
 
@@ -211,6 +211,12 @@ static const struct parameter parameters[] = {
          jubel,          0, -1, NULL, NULL},
     {"Ident-authentication",
 	ident_param,     0, 1, "try", &param.authentication_level},
+    {"Add members by invitation",
+        assign_bool,     0, 1, "on", &param.invite_by_default},
+    {"Allow secret memberships",
+        assign_bool,     0, 1, "on", &param.secret_memberships},
+    {"Allow reinvitations",
+        assign_bool,     0, 1, "off", &param.allow_reinvite},
     /* end marker */
     {NULL, NULL, 0, 0, NULL, NULL}};
 
diff --git a/src/server/simple-cache.c b/src/server/simple-cache.c
index aa51e5881d365aec9b6059446f341b2853917ccc..bb3722f38c619e99555176a7fb8874b0e6a02283 100644
--- a/src/server/simple-cache.c
+++ b/src/server/simple-cache.c
@@ -1,5 +1,5 @@
 /*
- * $Id: simple-cache.c,v 0.64 1997/10/23 12:37:26 byers Exp $
+ * $Id: simple-cache.c,v 0.65 1998/06/14 14:51:22 byers Exp $
  * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -34,7 +34,7 @@
  * Attempt at newer algorithm by byers (FASTSAVE)
  */
 
-static char *rcsid = "$Id: simple-cache.c,v 0.64 1997/10/23 12:37:26 byers Exp $";
+static char *rcsid = "$Id: simple-cache.c,v 0.65 1998/06/14 14:51:22 byers Exp $";
 #include "rcs.h"
 USE(rcsid);
 
@@ -2034,7 +2034,7 @@ sync_part(void)
     case sync_save_pers:
 	save_one_pers();
 	break;
-#else
+#endif
 
     case sync_save_text:
 	save_one_text();
diff --git a/src/server/text-garb.c b/src/server/text-garb.c
index 1ab864d41e1cccdf77e00c828edd4030b03bb510..888337eb5c70cb66f2902418dd84e3ee3a2d4b66 100644
--- a/src/server/text-garb.c
+++ b/src/server/text-garb.c
@@ -1,5 +1,5 @@
 /*
- * $Id: text-garb.c,v 0.21 1997/09/13 15:32:42 byers Exp $
+ * $Id: text-garb.c,v 0.22 1998/06/14 14:51:24 byers Exp $
  * Copyright (C) 1991, 1992, 1993, 1994, 1995  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -28,7 +28,7 @@
  * Author: Per Cederqvist.
  */
 
-static char *rcsid = "$Id: text-garb.c,v 0.21 1997/09/13 15:32:42 byers Exp $";
+static char *rcsid = "$Id: text-garb.c,v 0.22 1998/06/14 14:51:24 byers Exp $";
 #include "rcs.h"
 USE(rcsid);
 
@@ -102,7 +102,7 @@ garb_text(void)
 
     Text_stat	  *text_s;
     Misc_info 	  *misc;
-    u_short 	   nmisc;
+    u_short 	   nmisc, naux;
     double	   age;			/* How many seconds is this text? */
     double	   limit = 24 * 3600;
 
@@ -147,6 +147,15 @@ garb_text(void)
 	return FALSE;
     }
 
+    for (naux = 0; naux < text_s->aux_item_list.length; --naux)
+    {
+        if (text_s->aux_item_list.items[naux].flags.dont_garb)
+        {
+            tell_cache_garb_text(0);
+            return FALSE;
+        }
+    }
+
     for (nmisc = text_s->no_of_misc, misc = text_s->misc_items;
 	 nmisc > 0;
 	 --nmisc, ++misc )
diff --git a/src/server/text.c b/src/server/text.c
index 1424830ee160c3f6b9a0ff43197e556df9568bf8..e6cf738b4ce7bdd341e35b36da15f92e7017482b 100644
--- a/src/server/text.c
+++ b/src/server/text.c
@@ -1,5 +1,5 @@
 /*
- * $Id: text.c,v 0.47 1997/09/13 15:32:43 byers Exp $
+ * $Id: text.c,v 0.48 1998/06/14 14:51:26 byers Exp $
  * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -28,7 +28,7 @@
  * All atomic calls that deals with texts.
  */
 
-static char *rcsid = "$Id: text.c,v 0.47 1997/09/13 15:32:43 byers Exp $";
+static char *rcsid = "$Id: text.c,v 0.48 1998/06/14 14:51:26 byers Exp $";
 #include "rcs.h"
 USE(rcsid);
 
@@ -2010,13 +2010,14 @@ create_text_check_misc (u_short     * no_of_misc,
  */
 static Success
 create_text_add_aux(Text_stat *t_stat,
+                    Text_no text_no,
                     Aux_item_list *aux,
                     Pers_no creator)
 {
     u_short i;
     Text_stat *parent;
 
-    text_stat_add_aux_item_list(t_stat, aux, creator);
+    text_stat_add_aux_item_list(t_stat, text_no, aux, creator);
 
     for (i = 0; i < t_stat->no_of_misc; i++)
     {
@@ -2032,7 +2033,10 @@ create_text_add_aux(Text_stat *t_stat,
                 aux_inherit_items(&t_stat->aux_item_list,
                                   &parent->aux_item_list,
                                   &t_stat->highest_aux,
-                                  t_stat->author);
+                                  t_stat->author,
+                                  TRUE,
+                                  TEXT_OBJECT_TYPE,
+                                  text_no, t_stat);
             }
             break;
         case comm_to:
@@ -2043,7 +2047,10 @@ create_text_add_aux(Text_stat *t_stat,
                 aux_inherit_items(&t_stat->aux_item_list,
                                   &parent->aux_item_list,
                                   &t_stat->highest_aux,
-                                  t_stat->author);
+                                  t_stat->author,
+                                  TRUE,
+                                  TEXT_OBJECT_TYPE,
+                                  text_no, t_stat);
             }
             break;
         default:
@@ -2408,7 +2415,8 @@ do_create_text(const String  message,
     
     prepare_aux_item_list(aux, anonymous?0:ACTPERS);
     if ( create_text_check_misc(&no_of_misc, misc, anonymous) != OK
-         || text_stat_check_add_aux_item_list(NULL, aux, ACTPERS) != OK
+         || text_stat_check_add_aux_item_list(NULL, aux,
+                                              ACTPERS, TRUE) != OK
          || (text = cached_create_text( message )) == 0)
     {
 	return 0;
@@ -2436,6 +2444,7 @@ do_create_text(const String  message,
     }
 
     if ( create_text_add_aux(t_stat,
+                             text,
                              aux,
                              anonymous?0:ACTPERS ) != OK )
     {
@@ -3104,15 +3113,25 @@ modify_text_info(Text_no        text,
 
     if (check_delete_aux_item_list(items_to_delete,&text_s->aux_item_list)!=OK)
         return FAILURE;
-    delete_aux_item_list(items_to_delete, &text_s->aux_item_list);
-
-    if (text_stat_check_add_aux_item_list(text_s, aux, ACTPERS) != OK)
-    {
-        undelete_aux_item_list(items_to_delete, &text_s->aux_item_list);
+    delete_aux_item_list(items_to_delete,
+                         &text_s->aux_item_list,
+                         TEXT_OBJECT_TYPE,
+                         text, text_s);
+
+    if (text_stat_check_add_aux_item_list(text_s,
+                                          aux,
+                                          ACTPERS,
+                                          FALSE) != OK)
+    {
+        undelete_aux_item_list(items_to_delete,
+                               &text_s->aux_item_list,
+                               TEXT_OBJECT_TYPE,
+                               text,
+                               text_s);
         return FAILURE;
     }
 
-    text_stat_add_aux_item_list(text_s, aux, ACTPERS);
+    text_stat_add_aux_item_list(text_s, text, aux, ACTPERS);
 
     /* FIXME: async_text_changed(text, text_s);  */
     mark_text_as_changed(text);