+++ /dev/null
- Citadel Server Extension API Documentation
- ---------------------------------------------
-
- This is a VERY INCOMPLETE documentation of the API for extending the
-Citadel server using dynamically loaded modules. It really isn't an API at
-all, but rather a list of some of the functions available in the server which
-are likely to be of use to module writers.
-
- The current trend is to move as much stuff as possible out of the server
-proper and into loadable modules. This makes the code much easier to read and
-understand.
-
- Expect this document to become more complete over time, as both the API and
-the person documenting it have a chance to mature a bit. :)
-
-
-
- USER RELATED FUNCTIONS
- ----------------------
-
- The fundamental user data is stored in "struct ctdluser" which is defined
-in citadel.h. The following functions are available:
-
-
- int getuser(struct ctdluser *usbuf, char name[])
-
- Given the name of a requested user and a buffer to store the user
-record in, getuser() will search the userlog for the named user and load its
-data into the buffer. getuser() returns 0 upon success or a nonzero error
-code if the requested operation could not be performed.
-
-
- void putuser(struct ctdluser *usbuf, char *name)
-
- After reading in a user record with getuser() and perhaps modifying the data
-in some way, a program may use putuser() to write it back to disk.
-
-
- int lgetuser(struct ctdluser *usbuf, char *name)
- void lputuser(struct ctdluser *usbuf, char *name)
-
- If critical-section operation is required, this pair of calls may be used.
-They function the same as getuser() and putuser(), except that lgetuser()
-locks the user file immediately after retrieving the record and lputuser()
-unlocks it. This will guarantee that no other threads manipulate the same
-user record at the same time.
-
- NOTE: do NOT attempt to combine the locking lgetuser/lputuser calls with any
-other locking calls in this API. Attempting to obtain concurrent locks on
-multiple files may result in a deadlock condition which would freeze the
-entire server.
-
-
- void ForEachUser(void (*CallBack)(struct ctdluser *EachUser))
-
- This allows a user-supplied function to be called once for each user on
-the system. The user-supplied function will be called with a pointer to a
-user structure as its only argument.
-
-
- int getuserbynumber(struct ctdluser *usbuf, long int number)
-
- getuserbynumber() functions similarly to getuser(), except that it is
-supplied with a user number rather than a name. Calling this function
-results in a sequential search of the user file, so use it sparingly if at
-all.
-
-
- int purge_user(char *pname)
-
- This function deletes the named user off the system and erases all related
-objects: bio, photo, etc. It returns 0 upon success or a nonzero error code
-if the requested operation could not be performed.
-
-
-
- HOW TO REGISTER FUNCTION HOOKS
- ------------------------------
-
- The truly powerful part of the Citadel API is the ability for extensions to
-register "hooks" -- user-supplied functions will be called while the server
-is performing various tasks. Here are the API calls to register hooks:
-
-
- void CtdlRegisterProtoHook(void (*handler)(char *), char *cmd, char *desc)
- void CtdlUnregisterProtoHook(void (*handler)(char *), char *cmd)
-
- CtdlRegisterProtoHook() adds a new server command to the system. The
-handler function should accept a single string parameter, which will be set
-to a string containing any parameters the client software sent along with
-the server command. "cmd" should be the four-character mnemonic the server
-command is known by, and "desc" is a description of the new command.
-
- CtdlUnregisterProtoHook() removes a server command from the system. It
-must be called with the same handler and cmd which were previously registered.
-
-
- void CtdlRegisterCleanupHook(void *fcn_ptr)
- void CtdlUnregisterCleanupHook(void *fcn_ptr)
-
- CtdlRegisterCleanupHook() registers a new function to be called whenever the
-server is shutting down. Cleanup functions accept no parameters.
-
- CtdlUnregsiterCleanupHook() removes a cleanup function from the system. It
-must be called with the same fcn_ptr which was previously registered.
-
-
-void CtdlRegisterSessionHook(void *fcn_ptr, int EventType)
-void CtdlUnregisterSessionHook(void *fcn_ptr, int EventType)
-
- CtdlRegisterSessionHook() registers a session hook. Session hooks accept
-no parameters. There are multiple types of session hooks; the server
-extension registers which one it is interested in by setting the value of
-EventType. The available session hook types are:
-
-#define EVT_STOP 0 /* Session is terminating */
-#define EVT_START 1 /* Session is starting */
-#define EVT_LOGIN 2 /* A user is logging in */
-#define EVT_NEWROOM 3 /* Changing rooms */
-#define EVT_LOGOUT 4 /* A user is logging out */
-#define EVT_SETPASS 5 /* Setting or changing password */
-#define EVT_CMD 6 /* Called after each server command */
-#define EVT_RWHO 7 /* An RWHO command is being executed */
-#define EVT_ASYNC 8 /* Doing asynchronous message */
-
-#define EVT_TIMER 50 /* Timer events are called once per minute */
-#define EVT_HOUSE 51 /* Housekeeping event */
-
- CtdlUnregisterSessionHook() removes a session hook. It must be called with
-the same fcn_ptr and EventTYpe which were previously registered.
-
-
-void CtdlRegisterUserHook(void *fcn_ptr, int EventType)
-void CtdlUnregisterUserHook(void *fcn_ptr, int EventType)
-
- CtdlRegisterUserHook() registers a user hook. User hooks accept two
-parameters: a string pointer containing the user name, and a long which *may*
-contain a user number (only applicable for certain types of hooks). The
-available user hook types are:
-
-#define EVT_PURGEUSER 100 /* Deleting a user */
-#define EVT_OUTPUTMSG 101 /* Outputting a message */
-
- CtdlUnregisterUserHook() removes a user hook from the system. It must be
-called with the same fcn_ptr and EventType which were previously registered.
-
-
- void CtdlRegisterLogHook(void (*fcn_ptr) (char *), int loglevel)
- void CtdlUnregisterLogHook(void (*fcn_ptr) (char *), int loglevel)
-
- CtdlRegisterLogHook() adds a new logging function to the system. The
-handler function should accept a single string as a parameter. Logging
-functions can be used to implement additional logging facilities in
-addition to the Citadel trace file, which is output on stderr, or
-redirected to a file with the -t command line option. The handler
-function will be called if the loglevel is greater than or equal to
-loglevel.
-
- Security considerations: Logs may contain plain text passwords and
-other sensitive information. It is your responsibility to ensure that
-your logs have appropriate access protection. The Citadel trace file
-is readable only by the superuser when the -t option is used.
-
- CtdlUnregisterLogHook() removes a logging function from the system. It
-must be called with the same fcn_ptr and loglevel which were previously
-registered.
-
-
- void CtdlRegisterMessageHook(int (*handler) (struct CtdlMessage *),
- int EventType)
- void CtdlUnregisterMessageHook(int (*handler) (struct CtdlMessage *),
- int EventType)
-
-
- CtdlRegisterMessageHook() registers a function with the message
-handling subsystem. This function will be called with one parameter,
-a pointer to a CtdlMessage structure, when the message triggers an event
-of type EventType. The registered function should return non zero if it
-has handled the event to prevent other hook functions from also processing
-the event.
-
- CtdlUnregisterMessageHook() removes a function from the list of registered
-message handlers. To successfully remove a function registered with
-CtdlRegisterMessageHook() CtdlUnregisterMessageHook() must be called with
-the same parameters.
-
- Possible values for EventType are:
- EVT_BEFOREREAD Called after a message is loaded from disk but before
-it is presented for reading.
- EVT_BEFORESAVE Called before the message is saved to disk. returning
-non zero for this event will prevent the message being saved to disk in the
-normal manner.
- EVT_AFTERSAVE Called after the message is saved to disk but before
-any IGnet spooling is carried out.
- EVT_SMTPSCAN Called during the SMTP reception of a message after the
-message is received and before the response is sent to the sender. This is
-intended for spam filters and virus checkers. A positive return code will
-cause the message to be rejected by the SMTP server.
-
-
- void CtdlRegisterRoomHook(int (*fcn_ptr) (char *))
- void CtdlUnregisterRoomHook(int (*fcn_ptr) (char *))
-
- Register or remove a function with the room processing system.
-Registered functions are called in the order they are registered when a message
-is added to a room. This allows modules such as Sieve to process new messages
-appearing in a room.
-
-
- void CtdlRegisterXmsgHook(int (*fcn_ptr) (char *, char *, char *), int order)
- void CtdlUnregisterXmsgHook(int (*fcn_ptr) (char *, char *, char *), int order)
-
- Please write documentation for me!
-
-
- void CtdlRegisterServiceHook(int tcp_port, char *sockpath,
- void (*h_greeting_function) (void),
- void (*h_command_function) (void))
- void CtdlUnregisterServiceHook(int tcp_port, char *sockpath,
- void (*h_greeting_function) (void),
- void (*h_command_function) (void))
-
- Please write documentation for me!
-
-
- FUNCTIONS WHICH MANIPULATE USER/ROOM RELATIONSHIPS
-
- void CtdlGetRelationship(struct visit *vbuf,
- struct ctdluser *rel_user,
- struct ctdlroom *rel_room);
- void CtdlSetRelationship(struct visit *newvisit,
- struct ctdluser *rel_user,
- struct ctdlroom *rel_room);
-
- These functions get/set a "struct visit" structure which may contain
-information about the relationship between a user and a room. Specifically:
-
-struct visit {
- char v_roomname[20];
- long v_generation;
- long v_lastseen;
- unsigned int v_flags;
- };
-
-#define V_FORGET 1 /* User has zapped this room */
-#define V_LOCKOUT 2 /* User is locked out of this room */
-#define V_ACCESS 4 /* Access is granted to this room */
-
- Don't change v_roomname or v_generation; they're used to identify the room
-being referred to. A room is unique to the system by its combination of room
-name and generation number. If a new room is created with the same name as
-a recently deleted room, it will have a new generation number, and therefore
-stale "visit" records will not be applied (and will eventually be purged).
-
- v_lastseen contains the number of the newest message the user has read in
-this room. Any existing messages higher than this number can be considered
-as "new messages."
-
- v_flags contains information regarding access to the room.
-
-
-
- int CtdlRoomAccess(struct ctdlroom *roombuf, struct ctdluser *userbuf)
-
- This is a convenience function which uses CtdlGetRelationship() to determine
-whether a user has access to a room. It returns a bucket of bits which may
-contain:
-
-#define UA_INUSE 1 /* Room exists */
-#define UA_KNOWN 2 /* Room is in user's Known list */
-#define UA_GOTOALLOWED 4 /* User may <.G>oto this room */
-#define UA_HASNEWMSGS 8 /* Room contains new messages */
-#define UA_ZAPPED 16 /* User has forgotten this room */
-
-
-
-
- ROOM RELATED FUNCTIONS
- ----------------------
-
-
-unsigned create_room(char *new_room_name,
- int new_room_type,
- char *new_room_pass,
- int new_room_floor,
- int really_create)
-
- This function is used to create a new room. new_room_name should be set to
-the desired name for the new room.
-
- new_room_type should be set to one of the following values:
- 0 = public room
- 1 = guess-name room
- 2 = passworded room
- 3 = invitation-only room
- 4 = personal (mailbox) room
- 5 = personal (mailbox) room, and new_room_name already contains
- the namespace prefix (use with caution!)
-
- new_room_pass should be set to the desired password for the room (obviously
-this is only valid for passworded rooms).
-
- If the room is really to be created, set really_create to 1. Otherwise, the
-caller may merely check to see if it's possible to create the room without
-actually creating it by setting really_create to 0.
-
- create_room() returns the flags associated with the new room (as in the
-data structure item room.QRflags). If the room cannot be created (for
-example, a room with the name already exists), it returns 0.
-
-