zProUser
=============================================================================

    The zProUser class provides complete access to the ProBoard userbase.
    It manages all the complex interactions with the several data files
    used by the software. The class permits both read and write access,
    with a very fast search engine to locate a specific user by name or
    alias. As an added bonus, the whole userbase can be backed up on
    request as well.

    ProBoard uses several data files to store its userbase information.
    The RemoteAccess compatible USERS.BBS, USERSIDX.BBS, and USERSXI.BBS,
    as well as its own USERSPB.BBS. All the files are binary but there
    are several quirks - the RA-compatible data files are in Pascal binary
    format and some of the structures are native to RA and without an
    equivalent in ProBoard. This requires some fancy conversions that must
    be done on the fly when reading or writing. Fortunately, the overhead
    is avoided in the SDK version of the class which simply uses ProBoard
    to do its job. I am very proud to say that zProUser manages to produce
    bit-equivalent data records with ProBoard (and this is given the poor
    documentation of the formats of the data files!).

    The class provides a publicly-accessible record of type USER_REC which
    is the same as the structure pointed to by CurUser in the SDK. You can
    freely update this record and when you call the Save() method, the
    changes will be committed to the userbase.

    For records that don't have an alias field, the alias is set to the
    user's name. This is what ProBoard does as well. However, an alias
    which is the same as the name will not be saved to the userbase. It
    will be cleared to NUL before writing the record. Again, this is what
    ProBoard itself does.

    The 32-bit CRCs are not complemented after the calculations as the ANSI
    algorithm requires. This is what Andrew Milner did in RA, and this is
    what Philippe Leybaert copied in ProBoard. This is what I did as well.
    The CRCs are calculated for the name and alias converted to uppercase.

	ZPROUSER::ZPROUSER
	-------------------------------------------------------------------------

	    Summary  Constructs the zProUser object

	    Syntax   zProUser();

	    Remarks  The constructor does not load any data in the internal
	             records. It only initializes them. The caller must use
	             the Load() method to actually read a user record from the
	             userbase. However, this constructor locates the userbase
	             and verifies that all necessary files are present. You can
	             use any of the static functions.

	    Return   n/a


	ZPROUSER::LOAD
	-------------------------------------------------------------------------

	    Summary  Loads a user record from the userbase

	    Syntax   Boolean Load(long recno);

	    Remarks  This method loads the record 'recno' from the userbase.
	             Records are numbered from 0 to GetTotal() - 1 (as this
	             is how ProBoard apparently handles them). If the call is
	             successful, the 'm_rec' field will contain the user record.
	             Note that if you have made any changes to the record which
	             is loaded at the time this function is called, all changes
	             will be lost. You must explicitly call the Save() method
	             to commit the changes to the userbase.

	    Return   On success, returns True; False otherwise


	ZPROUSER::SAVE
	-------------------------------------------------------------------------

	    Summary  Saves the current record to the userbase

	    Syntax   Boolean Save(Boolean backup = True);

	    Remarks  This function writes out the current user record to the
	             userbase. It handles all necessary data conversions and
	             updates all respective files. Note that you must NOT alter
	             the record number field in 'm_rec' after calling Load()
	             because Save() will not know where to write the data and
	             will certainly corrupt the userbase. The caller can also
	             (optionally) backup all user data files. If the 'backup'
	             parameter is True (default), the files will be copied to
	             new files with same names but with ".BAK" extension. This
	             is quite safe, but may slow down your program, especially
	             if you are doing a lot of intense updating.

	    Return   On success, returns True; False otherwise


	ZPROUSER::CALCUSERCRC
	-------------------------------------------------------------------------

	    Summary  Calculates the 32-bit CRC for the current user

	    Syntax   ulong CalcUserCrc(Boolean alias = False);

	    Remarks  This function calculates the 32-bit CRC of the user name
	             (default, when 'alias' is False) or the user alias (set
	             the 'alias' parameter to True) and returns the number.
	             This function generates values which are compatible with
	             the way RA and PB handle the CRC calculations. Note that
	             you must have a valid user record loaded before you can
	             use this function. It can be useful for password checking
	             and simiar tasks.

	    Return   The 32-bit CRC of the name or alias


	ZPROUSER::GETTOTAL
	-------------------------------------------------------------------------

	    Summary  Retrieve the number of users in the userbase

	    Syntax   static ushort GetTotal();

	    Remarks  This function can be called without loading a user record
	             first. As a matter of fact, it can be called without even
	             instantiating an zProUser object. It calculates the total
	             number of user records in the userbase. That way the caller
	             will be able to scan the whole userbase if needed.

	    Return   Number of user records


	ZPROUSER::BACKUP
	-------------------------------------------------------------------------

	    Summary  Backups the userbase data files

	    Syntax   static void Backup();

	    Remarks  This function will copy all data files to new files with
	             the same names, but with ".BAK" extensions. If the backup
	             files already exist, they will be overwritten. This method
	             can be called without a zProUser object.

	    Return   Nothing


	ZPROUSER::FIND
	-------------------------------------------------------------------------

	    Summary  Locates a user record by name or alias

	    Syntax   static long Find(const char *s, Boolean alias = False);

	    Remarks  This is a very fast userbase scanner which can locate a
	             user record by name or alias. The string 's' specifies the
	             text of the name (if 'alias' is set to False, which is the
	             default behavior) or the alias (if 'alias' is True). If
	             successful, this function will return the record number
	             which can be used in the Load() method. This routine can
	             be used without creating a zProUser object first. The
	             records are numbered from 0.

	    Return	 On success, returns the record number; -1 otherwise


	ZPROUSER::M_REC
	-------------------------------------------------------------------------

	    Summary  The actual user record

	    Syntax   USER_REC m_rec;

	    Remarks  This is the publicly accessible user record. This is the
	             same as the structure pointed to by SDK's CurUser. You can
	             use the contents of this record only after a successful
	             call to the Load() member function. You can also modify all
	             fields in this record except the 'record' field, especially
	             if you want to save the modifications back to the userbase.
	             This field stores the record number and if you alter it,
	             the Save() method will overwrite the wrong user record and
	             will certainly corrupt the userbase.

	    Return   n/a

