--- /dev/null
+IRC wouldn't be of much interest without the ability for users to join
+channels. Of course, they must also be able to leave those channels
+when they get bored of the conversation there. Users can join or
+leave multiple channels at once. Sometimes these JOIN and PART
+messages can be ganged together into a single message. This is
+facilitated by the JoinBuf system.
+
+<struct>
+struct JoinBuf;
+
+This structure is used to accumulate and describe several channel
+joins or parts. None of its fields are directly or indirectly
+accessible to the application; a struct JoinBuf is only suitable for
+passing to the joinbuf_*() suite of functions. JoinBuf structures
+must be allocated by the caller.
+</struct>
+
+<macro>
+#define JOINBUF_TYPE_JOIN 0 /* send JOINs */
+
+This macro tells joinbuf_init() that the JoinBuf is being used to
+generate several channel joins.
+</macro>
+
+<macro>
+#define JOINBUF_TYPE_CREATE 1 /* send CREATEs */
+
+This macro tells joinbuf_init() that the JoinBuf is being used to
+generate several channel creations.
+</macro>
+
+<macro>
+#define JOINBUF_TYPE_PART 2 /* send PARTs */
+
+This macro tells joinbuf_init() that the JoinBuf is being used to
+generate several channel parts.
+</macro>
+
+<macro>
+#define JOINBUF_TYPE_PARTALL 3 /* send local PARTs, but not remote */
+
+This macro tells joinbuf_init() that the JoinBuf is being used to
+record PARTs for all the user's channels. That fact is communicated
+to servers through a more efficient means than sending several PARTs,
+but local clients can only be made aware of it with standard PART
+messages.
+</macro>
+
+<function>
+void joinbuf_init(struct JoinBuf *jbuf, struct Client *source,
+ struct Client *connect, unsigned int type, char *comment,
+ time_t create);
+
+This function is used to initialize a caller allocated JoinBuf,
+specified by _jbuf_. The originating user is specified by _source_;
+the connection on which the message was received is specified by
+_connect_; the type (one of the JOINBUF_TYPE_* macros described above)
+is specified by _type_. PART messages may have an optional comment,
+which is passed through the _comment_ parameter. JOIN and CREATE
+messages require a timestamp, passed through the _create_ parameter.
+</function>
+
+<function>
+void joinbuf_join(struct JoinBuf *jbuf, struct Channel *chan,
+ unsigned int flags);
+
+This function adds a channel to the JoinBuf. The _chan_ parameter
+specifies the channel, and may only be NULL if the JoinBuf type is
+JOINBUF_TYPE_JOIN--this will cause a "JOIN 0" message to be sent to
+all servers. The _flags_ parameter is used to specify the user's
+current channel flags. For JOINBUF_TYPE_PART and JOINBUF_TYPE_PARTALL
+JoinBufs, passing CHFL_ZOMBIE will inhibit sending the PART to all
+channel users, and CHFL_BANNED will inhibit sending the user's
+specified PART comment. For JOINBUF_TYPE_JOIN or JOINBUF_TYPE_CREATE
+JoinBufs, the _flags_ parameter is used to set the initial channel
+modes for the user.
+</function>
+
+<function>
+int joinbuf_flush(struct JoinBuf *jbuf);
+
+This function simply flushes the contents of the struct JoinBuf to the
+appropriate destinations.
+</function>
+
+<authors>
+Kev <klmitch@mit.edu>
+</authors>
+
+<changelog>
+[2001-6-15 Kev] Initial documentation of the JoinBuf subsystem.
+</changelog>
--- /dev/null
+Occasionally, a server will become incorrectly configured or will
+start behaving incorrectly. Even more rarely, a server will be
+compromised, and a modified version of the server put in place to
+cause problems. These cases are the reason for the _jupe_, a
+temporary server ban. This is similar to the G-line, which is a
+temporary user ban, and indeed, the jupe API is very similar to the
+G-line API.
+
+<macro>
+#define JUPE_MAX_EXPIRE 604800 /* max expire: 7 days */
+
+This macro lists the maximum expire time a jupe is permitted to have.
+This value is limited to 7 days to prevent abuse of the system.
+</macro>
+
+<macro>
+#define JUPE_ACTIVE 0x0001
+
+This flag is used to indicate that a given jupe is globally active.
+</macro>
+
+<macro>
+#define JUPE_LOCAL 0x0002
+
+This flag is used to indicate that a given jupe is a local one. Local
+jupes do not affect users on other servers.
+</macro>
+
+<macro>
+#define JUPE_LDEACT 0x0004 /* locally deactivated */
+
+This flag is set on global jupes that have been locally deactivated.
+This flag is maintained internally by the jupe subsystem.
+</macro>
+
+<struct>
+struct Jupe;
+
+The struct Jupe describes everything about a given jupe. None of its
+fields may be directly accessed by the application; use the functions
+and macros described below instead.
+</struct>
+
+<function>
+int JupeIsActive(struct Jupe* j);
+
+This macro returns a non-zero value if the jupe is active, or 0
+otherwise. If a jupe is locally deactivated, this macro will always
+return 0.
+</function>
+
+<function>
+int JupeIsRemActive(struct Jupe* j);
+
+This macro returns a non-zero value if the jupe is active, ignoring
+whether or not it is locally deactivated.
+</function>
+
+<function>
+int JupeIsLocal(struct Jupe* j);
+
+This macro returns a non-zero value if the jupe is local only.
+</function>
+
+<function>
+char* JupeServer(struct Jupe* j);
+
+This macro returns the server name associated with the jupe.
+</function>
+
+<function>
+char* JupeReason(struct Jupe* j);
+
+This macro returns the reason that was given when the jupe was set.
+</function>
+
+<function>
+time_t JupeLastMod(struct Jupe* j);
+
+Jupes have a modification time that must be monotonically increasing.
+This macro simply returns that modification time.
+</function>
+
+<function>
+int jupe_add(struct Client *cptr, struct Client *sptr, char *server,
+ char *reason, time_t expire, time_t lastmod, unsigned int flags);
+
+This function simply adds a jupe, set by _sptr_ and with a _server_,
+_reason_, _expire_, and _lastmod_ as specified. The _flags_ parameter
+is a bit mask consisting of the binary OR of JUPE_LOCAL and
+JUPE_ACTIVE, as appropriate. The jupe_add() function will propagate
+the jupe to all servers (assuming JUPE_LOCAL was not passed), and will
+break its link to the server specified by _server_ (assuming that the
+JUPE_ACTIVE flag _was_ passed).
+</function>
+
+<function>
+int jupe_activate(struct Client *cptr, struct Client *sptr, struct Jupe *jupe,
+ time_t lastmod, unsigned int flags);
+
+This function activates the jupe specified by _jupe_, setting its
+_lastmod_ time as specified. If _flags_ is JUPE_LOCAL and if the jupe
+is locally deactivated, this function will turn off the local
+deactivation flag, but will not modify _lastmod_. If the jupe is
+globally deactivated, passing this function the JUPE_LOCAL flag will
+have no effect.
+</function>
+
+<function>
+int jupe_deactivate(struct Client *cptr, struct Client *sptr,
+ struct Jupe *jupe, time_t lastmod, unsigned int flags);
+
+This function is similar to jupe_activate() except that it deactivates
+the jupe. If the given jupe is local, then the jupe is deleted from
+memory. In all other cases, the jupe is simply deactivated, either
+locally (if JUPE_LOCAL was passed via _flags_) or globally. Global
+deactivation will update the _lastmod_ time.
+</function>
+
+<function>
+struct Jupe* jupe_find(char *server);
+
+This function searches for a jupe matching the given _server_.
+</function>
+
+<function>
+void jupe_free(struct Jupe *jupe);
+
+This function releases all storage associated with a given jupe.
+</function>
+
+<function>
+void jupe_burst(struct Client *cptr);
+
+This function generates a burst of all existing global jupes and sends
+them to the server specified by _cptr_.
+</function>
+
+<function>
+int jupe_resend(struct Client *cptr, struct Jupe *jupe);
+
+This function resends the _jupe_ to a server specified by _cptr_.
+This may be used if, for instance, it is discovered that a server is
+not synchronized with respect to a particular jupe.
+</function>
+
+<function>
+int jupe_list(struct Client *sptr, char *server);
+
+This function sends the information about a jupe matching _server_ to
+the client specified by _sptr_. If _server_ is a NULL pointer, a list
+of all jupes is sent.
+</function>
+
+<authors>
+Kev <klmitch@mit.edu>
+</authors>
+
+<changelog>
+[2001-6-15 Kev] Initial documentation of the jupe API.
+</changelog>
--- /dev/null
+Generating and parsing channel mode strings is often a very
+complicated process. The ModeBuf interface, along with the associated
+mode parsing functions, attempt to make this much more programmatic.
+The interface to the functions in this suite is itself very
+complicated, unfortunately, though most of the complication is in the
+effects of various flags on the operation of the functions.
+
+<struct>
+struct ModeBuf;
+
+This structure is used to accumulate and describe several mode
+changes. None of its fields are directly or indirectly accessible to
+the application; a struct ModeBuf is only suitable for passing to the
+modebuf_*() suite of functions. ModeBuf structures must be allocated
+by the caller.
+</struct>
+
+<function>
+void modebuf_init(struct ModeBuf *mbuf, struct Client *source,
+ struct Client *connect, struct Channel *chan,
+ unsigned int dest);
+
+This function initializes a caller-allocated ModeBuf, _mbuf_, with the
+given parameters. If the mode should not be sent to a particular
+server, perhaps because it was received from that server, that server
+should be specified by the _connect_ parameter. The channel the mode
+change will take place on is given by the _chan_ parameter, and the
+disposition of the mode is given by the _dest_ parameter, which is the
+binary OR of the MODEBUF_DEST_* flags described below.
+</function>
+
+<macro>
+#define MODEBUF_DEST_CHANNEL 0x0001 /* Mode is flushed to channel */
+
+This flag, when set in a call to modebuf_init(), causes the accumulated
+mode change to be sent to the channel (in client<->server protocol, of
+course).
+</macro>
+
+<macro>
+#define MODEBUF_DEST_SERVER 0x0002 /* Mode is flushed to server */
+
+If other servers should be made aware of the mode change, this flag
+should be passed to modebuf_init(). One time when the mode change may
+not be passed is when processing the mode in a BURST message.
+</macro>
+
+<macro>
+#define MODEBUF_DEST_OPMODE 0x0100 /* Send server mode as OPMODE */
+
+This flag is used to tell the modebuf_*() suite to send an OPMODE
+message to other servers, rather than an ordinary MODE message.
+</macro>
+
+<macro>
+#define MODEBUF_DEST_DEOP 0x0200 /* Deop the offender */
+
+When bouncing a mode change, giving this flag to modebuf_init() causes
+the originating user to be deopped on the channel as part of the mode
+bounce.
+</macro>
+
+<macro>
+#define MODEBUF_DEST_BOUNCE 0x0400 /* Bounce the modes */
+
+When a mode change is illegitimate, that is, when it originates from a
+user that is not (as far as this server knows) a channel operator, the
+mode change should be bounced. This involves reversing the sense of
+the mode and sending it back to the originating server. This flag is
+used to tell the modebuf_*() suite to do just that.
+</macro>
+
+<macro>
+#define MODEBUF_DEST_LOG 0x0800 /* Log the mode changes to OPATH */
+
+The OPMODE command is reserved for IRC operators. When it is used,
+the server should log the command for accountability purposes. This
+flag, given to modebuf_init(), will cause the ModeBuf system to log
+the exact mode change to a log file.
+</macro>
+
+<macro>
+#define MODEBUF_DEST_HACK2 0x2000 /* Send a HACK(2) notice, reverse */
+
+When a remote user that this server does not think is a channel
+operator proceeds to change a channel mode, that mode must be
+bounced. In addition, in order to provide some debugging capability,
+a server notice may be sent, called a "HACK(2)" notice. Passing
+modebuf_init() this flag causes that notice to be sent.
+</macro>
+
+<macro>
+#define MODEBUF_DEST_HACK3 0x4000 /* Send a HACK(3) notice, TS == 0 */
+
+When the origin of a mode change is a server, we should always accept
+the mode change. To provide accountability, however, a server notice
+should be sent. This flag will cause the server to generate a
+"HACK(3)" notice.
+</macro>
+
+<macro>
+#define MODEBUF_DEST_HACK4 0x8000 /* Send a HACK(4) notice, TS == 0 */
+
+Some servers are special. When a server that has a U-line issues a
+mode change, we send a "HACK(4)" message to differentiate it from an
+ordinary server changing a channel mode. This is the flag that must
+be passed to modebuf_init() to cause that behavior.
+</macro>
+
+<function>
+void modebuf_mode(struct ModeBuf *mbuf, unsigned int mode);
+
+Certain channel modes take no arguments. Those mode changes can be
+fed to the ModeBuf system using modebuf_mode(). The _mode_ parameter
+is a bit mask of the mode changes, and must have one of MODE_ADD or
+MODE_DEL set.
+</function>
+
+<function>
+void modebuf_mode_uint(struct ModeBuf *mbuf, unsigned int mode,
+ unsigned int uint);
+
+One channel mode, the "limit" mode ("+l"), takes a single integer
+argument. This limit can be fed to the ModeBuf system with the
+modebuf_mode_uint() function. The _mode_ parameter must be the binary
+OR of one of MODE_ADD or MODE_DEL with the MODE_LIMIT flag. The
+_uint_ parameter specifies the limit.
+</function>
+
+<function>
+void modebuf_mode_string(struct ModeBuf *mbuf, unsigned int mode,
+ char *string, int free);
+
+Some channel modes take a string parameter. These can be fed to
+ModeBuf with modebuf_mode_string(). The _mode_ parameter should be
+the binary OR of one of MODE_ADD or MODE_DEL with the flag for the
+mode. The _string_ parameter specifies the string, and the _free_
+parameter indicates whether the ModeBuf system should call MyFree() on
+the string once it is done with it.
+</function>
+
+<function>
+void modebuf_mode_client(struct ModeBuf *mbuf, unsigned int mode,
+ struct Client *client);
+
+The remaining channel modes take a parameter specifying a client.
+These can be fed to ModeBuf with modebuf_mode_client(). The _mode_
+parameter should be the binary OR of one of MODE_ADD or MODE_DEL with
+the flag for the mode. The _client_ parameter should be a pointer to
+a struct Client specifying which client the mode is supposed to act
+upon.
+</function>
+
+<function>
+int modebuf_flush(struct ModeBuf *mbuf);
+
+This function simply flushes the contents of the struct ModeBuf
+specified by _mbuf_ to the appropriate destinations, as was specified
+by the _dest_ parameter in the call to modebuf_init(). This function
+returns 0 for the convenience of callers that must return an integer.
+</function>
+
+<function>
+void modebuf_extract(struct ModeBuf *mbuf, char *buf);
+
+One use of the ModeBuf within ircd requires the ability to pull a
+simple mode string out of the struct ModeBuf for use elsewhere. This
+can be accomplished with this function. The _buf_ parameter should be
+large enough to accommodate the simple mode string.
+</function>
+
+<function>
+void mode_ban_invalidate(struct Channel *chan);
+
+Looking up bans affecting a particular user can be a fairly expensive
+operation, so the server caches the result of the lookup. Should the
+ban list for a channel change, all the cached results must be
+invalidated to force rechecking. This may be done with the
+mode_ban_invalidate() function, which acts upon the channel given by
+_chan_.
+</function>
+
+<function>
+void mode_invite_clear(struct Channel *chan);
+
+When a channel that was invite-only has the "+i" channel mode removed,
+the invite list that the server keeps is no longer necessary. The
+mode_invite_clear() function flushes that invite list for the channel
+given by _chan_, reclaiming the memory used by the invite list.
+</function>
+
+<function>
+int mode_parse(struct ModeBuf *mbuf, struct Client *cptr, struct Client *sptr,
+ struct Channel *chptr, int parc, char *parv[],
+ unsigned int flags);
+
+This function parses a mode change command, given by the contents of
+_parv[]_, and under the control of _flags_. The channel being modified
+is given by _chptr_, the source of the change is given by _sptr_, and
+the connection the change was received from is given by _cptr_. The
+_parc_ parameter gives the count of the number of elements in the
+_parv[]_ array. The ModeBuf must have already been initialized by a
+call to modebuf_init(), described above. For more information on
+_flags_, see the MODE_PARSE_* macros described below. This function
+returns an integer indicating the number of elements of _parv[]_ it
+used. The modebuf_flush() function must be called upon return from
+mode_parse() to flush the mode changes to the channel.
+</function>
+
+<macro>
+#define MODE_PARSE_SET 0x01 /* actually set channel modes */
+
+When this flag is passed to mode_parse(), the channel mode being
+parsed will actually be effected on the channel.
+</macro>
+
+<macro>
+#define MODE_PARSE_STRICT 0x02 /* +m +n +t style not supported */
+
+Users are permitted to send complicated mode commands like "MODE #foo
++m +n +t +k foo +i"; servers are not. Passing this flag to
+mode_parse() causes it to strictly enforce this restriction.
+</macro>
+
+<macro>
+#define MODE_PARSE_FORCE 0x04 /* force the mode to be applied */
+
+Some mode changes are not permitted under normal circumstances. When
+this flag is passed to mode_parse(), these mode changes will be
+accepted.
+</macro>
+
+<macro>
+#define MODE_PARSE_BOUNCE 0x08 /* we will be bouncing the modes */
+
+This flag warns mode_parse() that the mode is to be bounced. This
+will cause it to systematically feed each mode into ModeBuf in order
+for that interface to generate the proper bounce messages.
+</macro>
+
+<macro>
+#define MODE_PARSE_NOTOPER 0x10 /* send "not chanop" to user */
+
+This flag is used to warn mode_parse() that the user generating the
+mode change is not a channel operator. If the user attempts to change
+a mode, an appropriate error message will be sent to the user (once).
+</macro>
+
+<macro>
+#define MODE_PARSE_NOTMEMBER 0x20 /* send "not member" to user */
+
+This flag is used to warn mode_parse() that the user generating the
+mode change is not even on the channel. If the user attempts to
+change a mode, an appropriate error message will be sent to the user
+(once).
+</macro>
+
+<macro>
+#define MODE_PARSE_WIPEOUT 0x40 /* wipe out +k and +l during burst */
+
+When this flag is passed to mode_parse(), the channel key and limit
+will be reversed if the mode string doesn't update them. This is used
+for processing BURST messages.
+</macro>
+
+<macro>
+#define MODE_PARSE_BURST 0x80 /* be even more strict w/extra args */
+
+The BURST message is even more strict than a standard MODE message.
+Processing *must* stop after reading the mode string itself, or
+mode_parse() could gobble up arguments not intended for it. This flag
+tells mode_parse() about this restriction.
+</macro>
+
+<authors>
+Kev <klmitch@mit.edu>
+</authors>
+
+<changelog>
+[2001-6-15 Kev] Initial documentation of the ModeBuf and mode parsing
+subsystems.
+</changelog>