/***************************************************************************
 *                                                                         *
 *   GALRSYAH.CPP                                                          *
 *                                                                         *
 *   Copyright (c) 1997 Galacticomm, Inc.                                  *
 *                                                                         *
 *   Remote Management Active HTML.                                        *
 *                                                  - N.C. Osterc  4/9/97  *
 *                                                                         *
 ***************************************************************************/

#include <windows.h>
#include "gcomm.h"
#include "majorbbs.h"
#include "gcspsrv.h"
#include "gcsasys.h"
#include "galacth.h"
#include "galrsy.h"
#include "tvb.h"
#include "dnf.h"
#include "remote.h"
#include "galrsyah.h"
#include "remhdl.h"
#include <cstring.h>
#include "cmdparse.h"
#include "ahutil.h"
#include "ahusrxrf.h"
#include "webd.h"
#include "direct.h"
#include "oprlow.h"
#include "wgsuext.h"

#define FILREV "$Revision: 30 $"

static
GBOOL
hasDirSpec(
CHAR const * ptr);

static GBOOL                       //   TRUE if char should be encoded
urlNeedEncode(                     // does char require encoding for URL?
CHAR c);                           //   character to check

static CHAR *                      //   returns pointer to destination
urlEncodeBuf(                      // encode special characters in URL
CHAR * buf,                        //   buffer to receive encoded string
CHAR const * src,                  //   unencoded URL
size_t bufSiz);                    //   size of destination buffer

static CHAR *                      //   returns pointer to destination
urlDecodeBuf(                      // decode special characters in URL
CHAR *buf,                         //   buffer to receive decoded string
const CHAR *src,                   //   unencoded URL
size_t bufSiz);                    //   size of destination buffer

class rsyAgent : public acthAgent {              // rsy agent
public:
     VOID
     init_rsm();

     rsyAgent() : acthAgent("Galacticomm Remote Management","remote")
     {
          registerAgent(acthVersion);
          oldshomal=shomal_hook;
          shomal_hook=acthshomal;
          init_rsm();
     }

     ~rsyAgent()
     {
          free(rsmahkey);
     }

     acthSynthesis *               // my session info (NULL=can't)
     newSynthesis(                 // instantiate my Synthesis class
     acthSession *ses);            // for passing to acthSynthesis's ctor

     private:

};

class rsySynthesis : public acthSynthesis {      // rsyah response synthesis
public:
     rsySynthesis(acthSession *_ses) :
          acthSynthesis(_ses),
          dnf(NULL)
     {
          usr=NULL;
          monhdl=NULL;
          xrfptr=NULL;
          sfptr=NULL;
          dfptr=NULL;
          keyptr=NULL;
          savclsptr=NULL;
          wrkclsptr=NULL;
          tempuid=NULL;
          xrfptr=NULL;
          tacptr=NULL;
          monhdl = new RemHdl();
          indnf=matchflg=drvflg=okdrvflg=nonfnd=multifil=incpyflg=FALSE;
          abspos=incdemo=matchcnt=0;
          tablecnt=dnfcnt=keycnt=rown=large=trval=0;
          totibm=totmac=totapp=tototh=0;
          dem19=dem29=dem39=dem49=dem99=0;
          clsbuf[0]='\0';
          strcpy(deflang,"0");
          dfname[0]=sfname[0]=dfpath[0]=sfpath[0]=delspec[0]='\0';
          m_pathbuf[0]=m_nambuf[0]='\0';
          ::memset(&uaccext,0,sizeof(struct uaccext));
     }

     ~rsySynthesis()
     {
          if (dnf != NULL) {
               delete dnf;
               dnf = NULL;
          }
          if (monhdl != NULL) {
               delete monhdl;
               monhdl=NULL;
          }
          if (xrfptr != NULL) {
               delete xrfptr;
               xrfptr = NULL;
          }
     }

private:

     struct usracc uac;            // Instance of usracc struct
     struct usracc tempacc;        // Usracc struct temporary storage
     struct usracc othacc;         // Other usracc struct (for settacptr())
     struct acclass cls;           // Instance of acclass struct
     struct bbsgen gbuf;           // Instance of bbsgen struct
     dnfHandler *dnf;              // Pointer to DNF handler Class
     acthUserID *usr;              // Pointer to acthUserID class
     RemHdl *remptr;               // Pointer to Remote Object Class
     RemHdl *monhdl;               // Pointer to Remote Object Class
     LONG abspos;                  // Absolute position pointer
     SHORT tablecnt;               // Which table are we on?
     GBOOL indnf;                  // Current in a dnf?
     GBOOL matchflg;               // Is there a match?
     GBOOL drvflg;                 // Is this a root dir?
     GBOOL okdrvflg;               // Is drive is ok?
     GBOOL nonfnd;                 // Are any users found?
     CHAR deflang[14];             // Default Language buffer
     CHAR tempBday[LDATSIZ];       // buffer for decoding birth date
     INT dnfcnt;                   // Bug in dnf->rowNumber using dnfcnt
                                   // for multiple tables in one dynafile
     SHORT keycnt;                 // Which key are we on? (-1 == done)
     struct clstab *savclsptr;     // Save class pointer
     struct clstab *wrkclsptr;     // Working class pointer
     struct usracc *tacptr;        // Temporary accounting pointer
     acthUserXrf *xrfptr;          // Pointer to Xrf Class
     CHAR *tempuid;                // Pointer to UID need to stick around
     CHAR keepkeybuf[KEYLEN];      // Buffer for gotten key (between cycs)
     CHAR *keyptr;                 // Pointer to key name
     INT matchcnt;                 // Number of matches found
     CHAR clsbuf[KEYLEN];          // Buffer for class name
     CHAR tab_user[UIDSIZ];        // Buffer for UID (between cycles)
     CHAR tab_chan[3];             // Buffer for Channel
     CHAR tab_loc[MNMSIZ];         // Buffer for location
     CHAR tab_cls[KEYLEN];         // Buffer for Class
     CHAR tab_cred[10];            // Buffer for Credits
     CHAR tab_timeon[10];          // Buffer for Timeon
     CHAR tab_invis[2];            // Buffer for Invis
     CHAR delspec[GCMAXPTH];       // Delete file
     CHAR dirnam[GCMAXPTH];        // Directory name
     CHAR sfpath[GCMAXPTH];        // Source path
     CHAR dfpath[GCMAXPTH];        // Destination path
     CHAR sfname[GCMAXPTH];        // Source file
     CHAR dfname[GCMAXPTH];        // Destination file
     CHAR cpybuf[CPYSIZ];          // Copy buffer
     struct ffblk dirblk;          // Instance of ffblk struct
     FILE *sfptr, *dfptr;          // Source and dest. file pointers
     GBOOL multifil,incpyflg;      // Multiple files?  Are we copying?
     INT rown;                     // Row number count
     LONG large,trval;             // Graph calculation storage
     LONG totals[24];              // Statistic total storage
     INT totibm,totmac,totapp,tototh;     // Demographic totals
     INT dem19,dem29,dem39,dem49,dem99;   // Demographic totals
     USHORT incdemo;               // Needed for demographic DNF
     INT end;                      // End channel keeper
     CHAR m_nambuf[FNDSIZE];       // Name buffer
     CHAR m_pathbuf[GCMAXPTH];     // Path buffer
     struct uaccext uaccext;       // User account extension buffer

     ACTHCODE                      // enumerated response (see galacth.h)
     proceed();                    // process request, synthesize response

     ACTHCODE                      // enumerated response (see galacth.h)
     proceedGet();                 // proceed synthesizing response to GET

     ACTHCODE                      // enumerated response (see galacth.h)
     proceedPost();                // proceed synthesizing response to POST

     GBOOL
     proceedAccPost(               // Process Account Post
     struct usracc *uptr);

     ACTHCODE
     proceedAccpdnf(               // Intermediate dnf function for Accpost
     struct usracc *uptr);

     VOID
     proceedAccOp(                 // Process Access Options
     struct usracc *uptr);

     ACTHCODE
     proceedAddkey(                // Handle adding key
     struct usracc *uptr);

     ACTHCODE
     proceedImpkey(                // Handle import key
     struct usracc *uptr);

     ACTHCODE
     proceedAddImpkey(             // Handle adding an import key
     struct usracc *uptr);

     ACTHCODE
     proceedRemovekey(             // Handle remove key
     struct usracc *uptr);

     VOID
     proceedPostcred(              // Post credits
     struct usracc *uptr);

     VOID
     proceedPostday(               // Post days
     struct usracc *uptr);

     VOID
     proceedCopyuser(              // Copy user
     struct usracc *uptr);

     VOID
     proceedChanop(                // Perform a channel op
     INT chnum,
     SHORT op);

     GBOOL
     SubmitClassVerify();          // Field checking for class creation/mods

     GBOOL
     HandleSubmitTime();           // Analyze Time options

     GBOOL
     HandleSubmitCredit();         // Analyze Credit Options

     GBOOL
     HandleSubmitClass();          // Analyze Class Options

     GBOOL
     HandleSubmitKeys();           // Handle key stuff

     CHAR *
     StpNDWhite(                   // Strip spaces from end of string
     CHAR *str);

     CHAR *
     StpBGWhite(                   // Strip spaces from beginning of string
     CHAR *str);

     ACTHCODE                      // enumerated response (see galacth.h)
     proceedNoFrame();             // proceed with no-frame main page

     ACTHCODE                      // enumerated response (see galacth.h)
     proceedFrame();               // proceed with frameified rsy main page

     INT
     checkAxs(                     // Access to remote option?
     struct usracc *uptr,
     INT op);

     VOID
     secs2StdTime(                 // Convert seconds to HH:MM:SS
     LONG secs);

     VOID
     offLineSave(                  // Save to disk if necessary
     struct usracc *uptr);

     CHAR *
     displayKeys(                  // Display keys for user/keyring
     CHAR *keyr,
     INT ring);

     GBOOL
     userHasKey(                   // Determine if uid already has key
     CHAR *uid,
     CHAR *key);

     ACTHCODE
     dnf_msg2user(                 // Send a message to user dynafile
     CHAR *user);

     ACTHCODE
     dnf_classlist();              // List of Classes Dynafile

     ACTHCODE
     dnf_CEClass(                  // Create/Edit Class Dynafile
     CHAR *clas,                   // The class name
     SHORT optype);                // Create or Edit

     ACTHCODE
     dnf_audend();                 // Audit Trail End for Summary

     ACTHCODE
     dnf_audit();                  // Audit Trail End for Summary

     ACTHCODE
     dnf_variables();              // Variables Dynafile

     ACTHCODE
     dnf_logano();                 // Logon Announcement Dynafile

     ACTHCODE
     dnf_dir(                      // Directory listing Dynafile
     SHORT list_type);

     ACTHCODE
     processDir(                   // Directory processing
     CHAR const * dir);

     VOID
     setCurWrkDir();               // Set user's cwd (e.g. "\WGNT\")

     VOID
     processCd(                    // Process "CD" command
     CHAR const * cwd);

     VOID
     processDel(                   // Process "DEL" command
     CHAR const * wrd);

     VOID
     processRd(                    // Process "RD" command
     CHAR const * wrd);

     VOID
     processMd(                    // Procss "MD" command
     CHAR const * wrd);

     GBOOL
     processRename(                // Process "RENAME" command
     CHAR const * wrd,
     CHAR const * nxtwrd);

     GBOOL
     processCopy(                  // Process "COPY" command
     CHAR const * op,
     GBOOL sd);

     VOID
     processType(                  // Process "TYPE" command
     CHAR const * wrd);

     CHAR *
     normDir(                      // Fix up directory
     CHAR *fixdir);

     ACTHCODE
     dnf_delete();                 // Delete file(s) Dynafile

     GBOOL
     strtdel();                    // Start the delete process

     GBOOL
     strtfil();                    // Start the dir. list process

     GBOOL
     strtcpy();                    // Start the delete process

     GBOOL
     dodelt();                     // Do delete

     GBOOL
     prepcpy();                    // Prepare to copy

     GBOOL
     docopy();                     // Actually do the copy

     ACTHCODE
     dnf_copy();                   // Copy file DNF

     ACTHCODE
     dnf_searchproc(               // Actually do a search Dynafile
     CHAR *keyval,
     CHAR *fldval,
     CHAR *opval);

     GBOOL
     isMatch(                      // Do we have a match?
     CHAR *keyval,
     CHAR *fldval,
     CHAR *opval);

     ACTHCODE
     dnf_userson();                // Users online dynafile

     ACTHCODE
     dnf_legend();                 // Legend Dnf

     ACTHCODE
     dnf_demog();                  // Demographics Dynafile

     ACTHCODE
     dnf_clsstats();               // Class Statistics Dynafile

     ACTHCODE
     dnf_miscstats();              // Miscellaneous Statistics Dynafile

     VOID
     switchsnd(                    // Switch statement
     SHORT field,
     SHORT val1,
     SHORT val2,
     SHORT val3,
     SHORT val4);

     ACTHCODE
     dnf_users();                  // Users Dynafile

     ACTHCODE
     dnf_about();                  // About Dynafile

     ACTHCODE
     dnf_accmain(                  // Main account dynafile
     struct usracc *uptr);

     ACTHCODE
     dnf_accframe(                 // Account Frame Dynafile
     CHAR *uid);

     ACTHCODE
     dnf_accfuncs(                 // Functions Dynafile
     CHAR *uid);

     ACTHCODE
     accback(                      // Go to previous user
     CHAR *uid);

     ACTHCODE
     accnext(                      // Go to next user
     CHAR *uid);

     ACTHCODE                      // List of users
     dnf_accfind();

     ACTHCODE
     dnf_accremote(                // Remote access flags
     struct usracc *uptr);

     ACTHCODE
     dnf_acckeys(                  // Pull up key info for user
     struct usracc *uptr,
     CHAR *keyr);

     ACTHCODE
     dnf_accpost(                  // Post credits to account
     struct usracc *uptr);

     ACTHCODE
     dnf_acccopy(                  // Copy one user to another id
     struct usracc *uptr);

     VOID
     about_os();                   // OS-specific info

     VOID
     handlelang(
     CHAR *uid);                   // language update

     VOID
     handleed();                   // handle editor type

     VOID
     handlesex();                  // handle sex

     VOID
     handlecomp(                   // handle computer type
     struct usracc *uptr);

     VOID
     handleflags();                // handle flags

     VOID
     handleclass(                  // handle class switching
     struct usracc *uptr);

     GBOOL
     okscnbrk();                   // pause output ok?

     GBOOL
     okcollin();                   // column/line size ok?

     GBOOL
     okField(                      // general purpose form field tester
     CHAR *data,                   // entered data
     INT minlen,                   // minimum length (0=no min)
     INT maxlen,                   // maximum length
     CHAR *called);                // what this field is called

     GBOOL                         // TRUE=ok, FALSE=error, explained
     okBday();                     // check birthday form entry

     GBOOL
     okUidPsw();                   // Is psw ok?

     GBOOL
     okPhone();                    // Is phone number ok?

     GBOOL
     okCountry();                  // Country is ok?

     GBOOL
     okAddr2();                    // Addr2 is ok?

     GBOOL
     okAddr1();                    // Addr1 is ok?

     GBOOL
     okCompany();                  // company is ok?

     GBOOL
     okName();                     // Name is ok?

     struct
     clstab *
     nxtcls(                       // Get next class
     struct clstab *from);

     GBOOL
     chkcdt(                       // compare database credits to search key
     CHAR *keyval,
     LONG credits,
     INT opval);

     GBOOL
     chkdte(                       // compare database date with search key
     CHAR *keyval,
     LONG date,
     INT opval);

     GBOOL
     chknum(                       // compare database number with search key
     CHAR *keyval,
     INT number,
     INT opval);

     GBOOL
     isdrive(                      // Is this a valid drive?
     CHAR *drv);

     CHAR *
     curWrkDirOp(                  // Do a Current Directory Operation
     SHORT optype,
     CHAR *cwd);

     GBOOL
     rootDir(                      // Determine if root dir
     CHAR const * cwd);

     VOID
     drivelet(                     // Ensure drive letter precedes path
     CHAR *cwd);

     VOID
     TrackLog(                     // Handle Audit Trail posting
     ULONG logval,
     INT argi,
     CHAR const * arg1,
     CHAR const * arg2);

     VOID
     settacptr();                  // Set our temporary account pointer

     CHAR const *
     normalizeFSpec(               // normalize file spec
     CHAR const * str);

     VOID
     getFilePath();                // Get filename and path

     const CHAR *
     getShortFileName(             // return short file name
     CHAR *fptr);
};

rsyAgent thersyAgent;              // the one and only instance of rsyAgent

acthSynthesis *                    // new session-specific structure
rsyAgent::newSynthesis(            // instantiate Synthesis class
acthSession *ses)                  // passed to acthSynthesis's constructor
{
     return(new rsySynthesis(ses));
}

MARKSOURCE(galrsyah);

ACTHCODE
rsySynthesis::proceed()            // proceed with HTML synthesis
{
     ACTHCODE retval;

     if ((usr=ses->getUser()) == NULL) {
          return(ACTHNOANON);
     }
     if (usr->hasKey(rsmahkey)) {   // make sure they have AH key
         settacptr();
         if (sameas(ses->method(),"GET")) {
              retval=proceedGet();
         }
         else if (sameas(ses->method(),"POST")) {
              retval=proceedPost();
         }
         else {
              ses->setStatus("501 Not implemented");
              retval=ACTHDONE;
         }
     }
     else {
          bout << "You do not have access to Remote System Management.";
          retval=ACTHDONE;
     }
     return(retval);
}

ACTHCODE
rsySynthesis::proceedGet()         // proceed synthesizing response to GET
{
     INT narg;
     ACTHCODE retval=ACTHMORE;

     if ((narg=ses->urlargc()) == 0) {
          if (ses->forceDir()) {
               retval=ACTHDONE;
          }
          else if (ses->param("noframe")) {
               retval=proceedNoFrame();
          }
          else {
               retval=proceedFrame();
          }
     }
     else if (narg == 1 && strchr(ses->urlargv(0),'.') != NULL &&
              !ses->param("name")) {
          if (ses->getUser() == NULL) {
               retval=ACTHNOANON;
          }
          else {
               ostrstream ost;
               ost << PPFIX << ses->urlargv(0) << ends;
               ses->sndfile(ost.str());
               ost.rdbuf()->freeze(0);
               retval=ACTHDONE;
          }
     }
     else if (narg == 1) {
          if (sameas(ses->urlargv(0),"rsycledit")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPACCT)) {
                   if (dnf == NULL) {
                        dnf = new dnfHandler(rsyEditClassMap,bout);
                   }
                   else {
                        retval=dnf_classlist();
                   }
               }
               else {
                    bout << "You don't have access to Edit a Class.";
                    retval=ACTHDONE;
               }
          }
          else if (sameas(ses->urlargv(0),"chanop")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPCHNG) ||
                   checkAxs(tacptr,OPHNGP)) {
                    ses->sndfile(PPFIX "rsychanl.htm");
               }
               else {
                    bout << "You don't have access to Channel Operations.";
               }
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"rsyclcreate")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPACCT)) {
                    ses->sndfile(PPFIX "rsyiclsc.htm");
               }
               else {
                    bout << "You don't have access to Create a Class.";
               }
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"remsearch")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPSRCH)) {
                    ses->sndfile(PPFIX "rsysrch.htm");
               }
               else {
                    bout << "You don't have access to Search.";
               }
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"remcpevt")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPCLNP)) {
                    ses->sndfile(PPFIX "rsycpevt.htm");
               }
               else {
                    bout << "You don't have access to force an event.";
               }
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"remkilsys")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPSHDN)) {
                    ses->sndfile(PPFIX "rsyklsys.htm");
               }
               else {
                    bout << "You don't have access to System Shutdown.";
               }
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"msgtoall")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPSALL)) {
                    ses->sndfile(PPFIX "rsymsgal.htm");
               }
               else {
                    bout << "You don't have access to send a system-wide "
                            "message.";
               }
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"rsycldelete")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPACCT)) {
                   if (dnf == NULL) {
                        dnf = new dnfHandler(rsyKillClassMap,bout);
                   }
                   else {
                        retval=dnf_classlist();
                   }
               }
               else {
                    bout << "You don't have access to Delete a Class.";
                    retval=ACTHDONE;
               }
          }
          else if (sameas(ses->urlargv(0),"sysmon")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPMNTR)) {
                    ses->sndfile(PPFIX "rsymon.htm");
               }
               else {
                    bout << "You don't have access to System Monitor.";
               }
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"account")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPACCT) ||
                   checkAxs(tacptr,OPDETL)) {
                   if (dnf == NULL) {
                        dnf = new dnfHandler(rsyAccframeMap,bout);
                   }
                   else {
                        dfaSetBlk(accbb);
                        if (dfaAcqLO(&uac,NULL)) {
                             retval=dnf_accframe(spc2pls(uac.userid));
                        }
                        else {
                             retval=dnf_accframe("Sysop");
                        }
                        dfaRstBlk();
                   }
               }
               else {
                    bout << "You don't have access to Account Functions.";
                    retval=ACTHDONE;
               }
          }
          else if (sameas(ses->urlargv(0),"accfind")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPACCT) ||
                   checkAxs(tacptr,OPDETL)) {
                    ses->sndfile(PPFIX "rsyaccfu.htm");
               }
               else {
                    bout << "You don't have access to find a user.";
               }
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"audittrl")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPAUDT)) {
                   if (dnf == NULL) {
                        dnf = new dnfHandler(rsyAuditTrailMap,bout);
                   }
                   else {
                        retval=dnf_audit();
                   }
               }
               else {
                    bout << "You don't have access to the Audit Trail.";
                    retval=ACTHDONE;
               }
          }
          else if (sameas(ses->urlargv(0),"audend")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPAUDT)) {
                   if (dnf == NULL) {
                        dnf = new dnfHandler(rsyAudEndMap,bout);
                   }
                   else {
                        retval=dnf_audend();
                   }
               }
               else {
                    bout << "You don't have access to the Audit Trail.";
                    retval=ACTHDONE;
               }
          }
          else if (sameas(ses->urlargv(0),"systime")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPAUDT)) {
                    bout << dtmin(now()) << endl;
               }
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"sysload")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPAUDT)) {
                   for (INT i=0; i < 60 ; i++) {
                        bout << sysload[i] << endl;
                   }
               }
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"sysnterms")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPAUDT)) {
                    bout << nterms << endl;
               }
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"liniu")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPSYSS)) {
                    ses->sndfile(PPFIX "rsyliniu.htm");
               }
               else {
                    bout << "You don't have access to this graph.";
               }
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"clsbd")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPSYSS)) {
                    ses->sndfile(PPFIX "rsyclsbd.htm");
               }
               else {
                    bout << "You don't have access to this graph.";
               }
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"mnusd")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPSYSS)) {
                    ses->sndfile(PPFIX "rsymnusd.htm");
               }
               else {
                    bout << "You don't have access to this graph.";
               }
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"avghr")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPSYSS)) {
                    ses->sndfile(PPFIX "rsyavghr.htm");
               }
               else {
                    bout << "You don't have access to this graph.";
               }
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"cred")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPSYSS)) {
                    ses->sndfile(PPFIX "rsycred.htm");
               }
               else {
                    bout << "You don't have access to this graph.";
               }
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"credg")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPSYSS)) {
                    ses->sndfile(PPFIX "rsycredg.htm");
               }
               else {
                    bout << "You don't have access to this graph.";
               }
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"hiliniu")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPSYSS)) {
                   for (INT i=0; i < 48 ; i++) {
                        large=max(large,(LONG)(sv2.nliniu[i]));
                   }
                   large=(large+track/2)/track;
                   bout << large << endl;
               }
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"liniuvals")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPSYSS)) {
                   for (INT i=0; i < 48 ; i++) {
                        bout << (sv2.nliniu[i]+track/2)/track << endl;
                   }
               }
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"himinu")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPSYSS)) {
                   INT i,j;
                   setmem(totals,sizeof(totals),0);
                   for (i=0 ; i < 24 ; i++) {
                        for (j=0 ; j < NUMGRPS-1 ; j++) {
                             totals[i]+=sv3.secghr[j][i];
                        }
                        totals[i]=((totals[i]+30L)/60L+track/2)/track;
                   }
                   for (i=0; i < 24 ; i++) {
                        large=max(large,(totals[i]));
                   }
                   bout << large << endl;
               }
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"minuvals")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPSYSS)) {
                   INT i,j;
                   setmem(totals,sizeof(totals),0);
                   for (i=0 ; i < 24 ; i++) {
                        for (j=0 ; j < NUMGRPS-1 ; j++) {
                             totals[i]+=sv3.secghr[j][i];
                        }
                        bout << ((totals[i]+30L)/60L+track/2)/track << endl;
                   }
               }
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"hitimu")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPSYSS)) {
                   INT i,j,temp;
                   setmem(totals,sizeof(totals),0);
                   for (i=0 ; i < NUMGRPS-1 ; i++) {
                        for (j=0 ; j < 24 ; j++) {
                             totals[i]+=sv3.secghr[i][j];
                        }
                        totals[i]=(temp=((totals[i]+1800L)/3600L+track/2)/track) > 9999L
                             ? 9999L : temp;
                   }
                   for (i=0; i < NUMGRPS-1 ; i++) {
                        large=max(large,totals[i]);
                   }
                   bout << large << endl;
               }
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"timuvals")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPSYSS)) {
                   INT i,j,temp;
                   setmem(totals,sizeof(totals),0);
                   for (i=0 ; i < NUMGRPS-1 ; i++) {
                        for (j=0 ; j < 24 ; j++) {
                             totals[i]+=sv3.secghr[i][j];
                        }
                        totals[i]=(temp=((totals[i]+1800L)/3600L+track/2)/track) > 9999L
                             ? 9999L : temp;
                        bout << totals[i] << endl;
                   }
               }
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"hicredu")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPSYSS)) {
                   INT i,j;
                   setmem(totals,sizeof(totals),0);
                   for (i=0 ; i < 24 ; i++) {
                        for (j=0 ; j < NUMGRPS-1 ; j++) {
                             totals[i]+=sv3.crdghr[j][i];
                        }
                        totals[i]=((totals[i]+500L)/1000L+track/2)/track;
                   }
                   for (i=0; i < NUMGRPS-1 ; i++) {
                        large=max(large,totals[i]);
                   }
                   bout << large << endl;
               }
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"hicreduvals")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPSYSS)) {
                   INT i,j;
                   setmem(totals,sizeof(totals),0);
                   for (i=0 ; i < 24 ; i++) {
                        for (j=0 ; j < NUMGRPS-1 ; j++) {
                             totals[i]+=sv3.crdghr[j][i];
                        }
                        bout << ((totals[i]+500L)/1000L+track/2)/track << endl;
                   }
               }
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"hicredugr")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPSYSS)) {
                   INT i,j,temp;
                   setmem(totals,sizeof(totals),0);
                   for (i=0 ; i < NUMGRPS-1 ; i++) {
                        for (j=0 ; j < 24 ; j++) {
                             totals[i]+=sv3.crdghr[i][j];
                        }
                        totals[i]=(temp=((totals[i]+500L)/1000L+track/2)/track) > 9999L
                             ? 9999L : temp;
                   }
                   for (i=0; i < NUMGRPS-1 ; i++) {
                        large=max(large,totals[i]);
                   }
                   bout << large << endl;
               }
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"hicredugrvals")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPSYSS)) {
                   INT i,j,temp;
                   setmem(totals,sizeof(totals),0);
                   for (i=0 ; i < NUMGRPS-1 ; i++) {
                        for (j=0 ; j < 24 ; j++) {
                             totals[i]+=sv3.crdghr[i][j];
                        }
                        totals[i]=(temp=((totals[i]+500L)/1000L+track/2)/track) > 9999L
                             ? 9999L : temp;
                        bout << totals[i] << endl;
                   }
               }
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"hicallsbaud")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPSYSS)) {
                   for (INT i=0; i < 8 ; i++) {
                        large=max(large,(LONG)(sv.calls[i]));
                   }
                   bout << large << endl;
               }
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"hicallsbaudvals")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPSYSS)) {
                   for (INT i=0; i < 8 ; i++) {
                        bout << sv.calls[i] << endl;
                   }
               }
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"demograph")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPDEMS)) {
                   if (dnf == NULL) {
                        dnf = new dnfHandler(rsyDemoMap,bout);
                   }
                   else {
                        retval=dnf_demog();
                   }
               }
               else {
                    bout << "You don't have access to System Demographics.";
                    retval=ACTHDONE;
               }
          }
          else if (sameas(ses->urlargv(0),"classtats")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPCLSS)) {
                    if (dnf == NULL) {
                         dnf = new dnfHandler(rsyCstMap,bout);
                    }
                    else {
                         retval=dnf_clsstats();
                    }
               }
               else {
                    bout << "You don't have access to Class Statistics.";
                    retval=ACTHDONE;
               }
          }
          else if (sameas(ses->urlargv(0),"miscstats")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPMODS)) {
                   if (dnf == NULL) {
                        dnf = new dnfHandler(rsyMstMap,bout);
                   }
                   else {
                        retval=dnf_miscstats();
                   }
               }
               else {
                    bout << "You don't have access to view Module Usage.";
                    retval=ACTHDONE;
               }
          }
          else if (sameas(ses->urlargv(0),"monlines")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPMNTR)) {
                    RemHdl tmpobj;
                    bout << tmpobj.TotObj() << endl;
               }
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"monitor")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPMNTR)) {
                   while ((remptr=monhdl->GetObj()) != NULL) {
                        bout << remptr->GetUser();
                        bout << ",";
                        bout << remptr->GetChannel();
                        bout << ",";
                        bout << remptr->GetStatus();
                        bout << ",";
                        bout << remptr->GetData();
                        bout << endl;
                        monhdl->DelObj();
                   }
               }
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"systemusage")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPAUDT)) {
                    ses->sndfile(PPFIX "rsysyuse.htm");
               }
               else {
                    bout << "You don't have access to System Usage.";
               }
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"variables")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPAUDT)) {
                   if (dnf == NULL) {
                        dnf = new dnfHandler(rsyVariableMap,bout);
                   }
                   else {
                        retval=dnf_variables();
                   }
               }
               else {
                    bout << "You don't have access to System Variables.";
                    retval=ACTHDONE;
               }
          }
          else if (sameas(ses->urlargv(0),"about")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPAUDT)) {
                    if (dnf == NULL) {
                         dnf = new dnfHandler(rsyAboutMap,bout);
                    }
                    else {
                         retval=dnf_about();
                    }
               }
               else {
                    bout << "You don't have access to the About screen.";
                    retval=ACTHDONE;
               }
          }
          else if (sameas(ses->urlargv(0),"loganno")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPLOGN)) {
                    if (dnf == NULL) {
                         dnf = new dnfHandler(rsyLoganoMap,bout);
                    }
                    else {
                         retval=dnf_logano();
                    }
               }
               else {
                    bout << "You don't have access to set the logon message.";
                    retval=ACTHDONE;
               }
          }
          else if (sameas(ses->urlargv(0),"userson")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPUSRS)) {
                    if (dnf == NULL) {
                         dnf = new dnfHandler(rsyUsersonMap,bout);
                    }
                    else {
                         retval=dnf_userson();
                    }
               }
               else {
                    bout << "You don't have access to the user listing.";
                    retval=ACTHDONE;
               }
          }
          else if (sameas(ses->urlargv(0),"matchnone") ||
                   sameas(ses->urlargv(0),"rsyintrp") ||
                   sameas(ses->urlargv(0),"rsyinmsg") ||
                   sameas(ses->urlargv(0),"empty")) {
               bout << " ";
               retval=ACTHDONE;
          }
          else if(sameas(ses->urlargv(0),"syscmd")) {
               CHAR cmdbuf[2*GCMAXPTH];
               cmdbuf[0]='\0';
               setCurWrkDir();
               ses->param("NAM_SYSCMD",cmdbuf,sizeof(cmdbuf));
               if (cmdbuf[0] != '\0') {
                    rsyCommandParser parser;
                    CHAR const * wrd=parser.GetCommand(cmdbuf);
                    if (sameas(wrd,"TYPE")) {
                         if (tacptr->flags&HASMST || checkAxs(tacptr,OPTYPE)) {
                             wrd=parser.GetNextArg();
                             if (samend(wrd,".TXT")) {
                                  TrackLog(TYPTRK,0,wrd,NULL);
                                  if (isfile(wrd)) {
                                       ses->sndfile(wrd);
                                  }
                                  else {
                                       processType(wrd);
                                  }
                             }
                             else {
                                  bout << "Can't type this file.";
                             }
                         }
                         else {
                              bout << "You don't have access to the TYPE command.";
                         }
                         retval=ACTHDONE;
                    }
                    else if (sameas(wrd,"COPY")) {
                         if (tacptr->flags&HASMST || checkAxs(tacptr,OPCOPY)) {
                              if (dnf == NULL) {
                                   CHAR op1[GCMAXPTH], op2[GCMAXPTH];
                                   CHAR const * op=parser.GetNextArg();
                                   if (strlen(op) > 0) {
                                        op=normalizeFSpec(op);
                                        stlcpy(op1,op,GCMAXPTH);
                                        if (!processCopy(op1,0)) {
                                             bout << "First operand is invalid.";
                                             return(ACTHDONE);
                                        }
                                   }
                                   else {
                                        bout << "You must specify at least one operand";
                                        return(ACTHDONE);
                                   }
                                   op=parser.GetNextArg();
                                   if (strlen(op) > 0) {
                                        op=normalizeFSpec(op);
                                        stlcpy(op2,op,GCMAXPTH);
                                        if (!processCopy(op2,1)) {
                                             bout << "Second operand is invalid.";
                                             return(ACTHDONE);
                                        }
                                   }
                                   else {
                                        stlcpy(dfname,curWrkDirOp(GET,NULL),GCMAXPTH);
                                   }
                                   if (strtcpy()) {
                                       dnf=new dnfHandler(rsyDeleteMap,bout);
                                       TrackLog(CPYTRK,0,sfname,dfname);
                                   }
                                   else {
                                       bout << "Can't complete copy" <<
                                               " operation.";
                                       retval=ACTHDONE;
                                   }
                              }
                              else {
                                   retval=dnf_copy();
                              }
                         }
                         else {
                              bout << "You don't have access to the "
                                      "COPY command.";
                              retval=ACTHDONE;
                         }
                    }
                    else if (sameas(wrd,"RENAME") || sameas(wrd,"REN")) {
                         if (tacptr->flags&HASMST || checkAxs(tacptr,OPRENM)) {
                             CHAR op1[GCMAXPTH], op2[GCMAXPTH];
                             CHAR const * op=parser.GetNextArg();
                             if (strlen(op) > 0) {
                                  if (!hasDirSpec(op)) {
                                       stlcpy(op1,curWrkDirOp(GET,NULL),GCMAXPTH);
                                       stlcat(op1,op,GCMAXPTH);
                                  }
                                  else {
                                       stlcpy(op1,op,GCMAXPTH);
                                  }
                                  op=parser.GetNextArg();
                                  if (strlen(op) > 0) {
                                       if (!hasDirSpec(op)) {
                                            stlcpy(op2,curWrkDirOp(GET,NULL),GCMAXPTH);
                                            stlcat(op2,op,GCMAXPTH);
                                       }
                                       else {
                                            stlcpy(op2,op,GCMAXPTH);
                                       }
                                  }
                             }
                             if (strlen(op) == 0) {
                                  bout << "You must specify two filenames!";
                             }
                             else {
                                  ASSERT(*op1 != '\0' && *op2 != '\0');
                                  if (!processRename(op1,op2)) {
                                       bout << "Can't rename file";
                                  }
                             }
                         }
                         else {
                              bout << "You don't have access to the RENAME "
                                      "command.";
                         }
                         retval=ACTHDONE;
                    }
                    else if (sameas(wrd,"DIR")) {
                         if (tacptr->flags&HASMST || checkAxs(tacptr,OPDIR)) {
                              CHAR const * curDir=parser.GetNextArg();
                              if (strlen(curDir) == 0) {
                                   curDir=curWrkDirOp(GET,NULL);
                              }
                              else if (!hasDirSpec(curDir)) {
                                   stlcpy(m_pathbuf,curWrkDirOp(GET,NULL),GCMAXPTH);
                                   stlcat(m_pathbuf,curDir,GCMAXPTH);
                                   curDir=m_pathbuf;
                              }
                              retval=processDir(curDir);
                         }
                         else {
                              bout << "You don't have access to the DIR "
                                      "command.";
                              retval=ACTHDONE;
                         }
                    }
                    else if (sameas(wrd,"MD")) {
                         if (tacptr->flags&HASMST || checkAxs(tacptr,OPMD)) {
                              processMd(parser.GetNextArg());
                         }
                         else {
                              bout << "You don't have access to the MD "
                                      "command.";
                         }
                         retval=ACTHDONE;
                    }
                    else if (sameas(wrd,"RD")) {
                         if (tacptr->flags&HASMST || checkAxs(tacptr,OPRD)) {
                              processRd(parser.GetNextArg());
                         }
                         else {
                              bout << "You don't have access to the RD "
                                      "command.";
                         }
                         retval=ACTHDONE;
                    }
                    else if (sameas(wrd,"DEL")) {
                         if (tacptr->flags&HASMST || checkAxs(tacptr,OPDEL)) {
                             if (dnf == NULL) {
                                  processDel(parser.GetNextArg());
                                  if (strtdel()) {
                                       dnf=new dnfHandler(rsyDeleteMap,bout);
                                       TrackLog(DELTRK,0,delspec,NULL);
                                  }
                                  else {
                                       bout << "Delete failed.";
                                       retval=ACTHDONE;
                                  }
                             }
                             else {
                                  retval=dnf_delete();
                             }
                         }
                         else {
                              bout << "You don't have access to the DELETE "
                                      "command.";
                              retval=ACTHDONE;
                         }
                    }
                    else if (sameas(wrd,"CD")) {
                         if (tacptr->flags&HASMST || checkAxs(tacptr,OPDIR)) {
                              processCd(parser.GetNextArg());
                              retval=ACTHDONE;
                         }
                         else {
                              bout << "You don't have access to the CD command.";
                         }
                    }
                    else if (sameas(wrd,"CWD")) {
                         if (tacptr->flags&HASMST || checkAxs(tacptr,OPDIR)) {
                              bout << "Current working directory is: " <<
                                      curWrkDirOp(GET,NULL);
                              retval=ACTHDONE;
                         }
                         else {
                              bout << "You don't have access to the CWD command.";
                         }
                    }
                    else if (sameas(wrd,"HELP")) {
                         if (tacptr->flags&HASMST || checkAxs(tacptr,OPDIR)) {
                              bout << "DIR {filespec}<br>" << crlf;
                              bout << "TYPE {filename}<br>" << crlf;
                              bout << "COPY {filespec} {filespec}<br>" << crlf;
                              bout << "RENAME {filename} {filename}<br>" << crlf;
                              bout << "MD {dirname}<br>" << crlf;
                              bout << "RD {dirname}<br>" << crlf;
                              bout << "DEL {filespec}<br>" << crlf;
                              bout << "CD {dirname}<br>" << crlf;
                              bout << "CWD <br>";
                              retval=ACTHDONE;
                         }
                         else {
                              bout << "You don't have access to help.";
                         }
                    }
                    else {
                         bout << "Command not recognized!";
                         retval=ACTHDONE;
                    }
               }
               else {
                    bout << "You must enter a command!";
                    retval=ACTHDONE;
               }
          }
          else {
               retval=ACTHNOTFND;
          }
     }
     else if (narg == 2) {
          if (sameas(ses->urlargv(0),"legend")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPAUDT)) {
                    if (dnf == NULL) {
                        INT legval;
                        RemHdl temphdl;
                        if ((legval=temphdl.GetLegend((
                              CHAR *)usr->userid())) == 16) {
                              temphdl.PutLegend((CHAR *)usr->userid(),0);
                        }
                        else {
                              if (sameas(ses->urlargv(1),"up")) {
                                  if (legval < 15) {
                                        ++legval;
                                  }
                                  else {
                                        legval=0;
                                  }
                                  temphdl.UpdLegend(
                                  (CHAR *)usr->userid(),legval);
                              }
                              else if (sameas(ses->urlargv(1),"down")) {
                                  if (legval > 0) {
                                        --legval;
                                  }
                                  else {
                                        legval=15;
                                  }
                                  temphdl.UpdLegend(
                                  (CHAR *)usr->userid(),legval);
                              }
                        }
                        dnf = new dnfHandler(rsyLegendMap,bout);
                    }
                    else {
                        retval=dnf_legend();
                    }
               }
               else {
                    bout << "You don't have access to the User Legend.";
                    retval=ACTHDONE;
               }
          }
          else if (sameas(ses->urlargv(0),"msg2user")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPSEND)) {
                   if (uidxst(pls2spc((CHAR *)ses->urlargv(1)))) {
                        if (dnf == NULL) {
                             dnf = new dnfHandler(rsyMsg2UserMap,bout);
                        }
                        else {
                             retval=dnf_msg2user((CHAR *)ses->urlargv(1));
                        }
                   }
                   else {
                        bout << "Cannot locate user!";
                        retval=ACTHDONE;
                   }
               }
               else {
                    bout << "You don't have access to send messages to users.";
                    retval=ACTHDONE;
               }
          }
          else {
               if (!tacptr->flags&HASMST && !checkAxs(tacptr,OPACCT) &&
                   !checkAxs(tacptr,OPDETL)) {
                    bout << "You don't have access to account functions!";
                    return(ACTHDONE);
               }
               struct usracc *uptr;
               stzcpy(tab_user,pls2spc((CHAR *)ses->urlargv(1)),UIDSIZ);
               if (tab_user[0] == '\0') {
                    return(ACTHNOTFND);
               }
               if ((uptr=GetAccPtr(tab_user)) == NULL) {
                    return(ACTHNOTFND);
               }
               if (sameas(ses->urlargv(0),"accmain")) {
                    if (!tacptr->flags&HASMST && !checkAxs(tacptr,OPDETL)) {
                         bout << "You don't have access to account details!";
                         return(ACTHDONE);
                    }
                    if (dnf == NULL) {
                         ::dfaSetBlk(::dfaUserExt);
                         ::dfaAcqEQ(&uaccext,uptr->userid,0);
                         ::dfaRstBlk();

                         dnf = new dnfHandler(rsyAccmainMap,bout);
                         return(ACTHMORE);
                    }
                    else {
                         return(dnf_accmain(uptr));
                    }
               }
               if (sameas(ses->urlargv(0),"accfuncs")) {
                    if (dnf == NULL) {
                         dnf = new dnfHandler(rsyAccfuncMap,bout);
                         return(ACTHMORE);
                    }
                    else {
                         return(dnf_accfuncs(uptr->userid));
                    }
               }
               if (sameas(ses->urlargv(0),"accback")) {
                    return(accback(uptr->userid));
               }
               if (sameas(ses->urlargv(0),"accnext")) {
                    return(accnext(uptr->userid));
               }
               if (sameas(ses->urlargv(0),"founduser") ||
                        sameas(ses->urlargv(0),"accjump")) {
                    if (dnf == NULL) {
                         dnf = new dnfHandler(rsyAccframeMap,bout);
                         return(ACTHMORE);
                    }
                    else {
                         return(dnf_accframe(spc2pls(tab_user)));
                    }
               }
               if (!tacptr->flags&HASMST && !checkAxs(tacptr,OPACCT)) {
                    bout << "You don't have access to this account function!";
                    return(ACTHDONE);
               }
               if (sameas(ses->urlargv(0),"accremote")) {
                    if (dnf == NULL) {
                         dnf = new dnfHandler(rsyAccopMap,bout);
                         return(ACTHMORE);
                    }
                    else {
                         return(dnf_accremote(uptr));
                    }
               }
               if (sameas(ses->urlargv(0),"acckeys")) {
                    if (dnf == NULL) {
                         dnf = new dnfHandler(rsyAcckeyMap,bout);
                         return(ACTHMORE);
                    }
                    else {
                         return(dnf_acckeys(uptr,NULL));
                    }
               }
               if (sameas(ses->urlargv(0),"accpost")) {
                    if (dnf == NULL) {
                         dnf = new dnfHandler(rsyAccpostMap,bout);
                         return(ACTHMORE);
                    }
                    else {
                         return(dnf_accpost(uptr));
                    }
               }
               if (sameas(ses->urlargv(0),"accopy")) {
                    if (dnf == NULL) {
                         dnf = new dnfHandler(rsyAcccpyMap,bout);
                         return(ACTHMORE);
                    }
                    else {
                         return(dnf_acccopy(uptr));
                    }
               }
               retval=ACTHNOTFND;
          }
     }
     else if (narg >= 3) {
          if (sameas(ses->urlargv(0),"filepath")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPDIR)) {
                   getFilePath();

                   if ( m_pathbuf == NULL ) {
                        return (ACTHDONE);
                   }

                   if (indnf) {

                        if (sameas(m_nambuf,"BACK DIR")) {
                             INT idx = findstg("BACK DIR",m_pathbuf);
                             ASSERT(idx != 0);
                             m_pathbuf[idx-CSTRLEN("BACK DIR")]='\0';
                             stzcat(m_pathbuf,"..",GCMAXPTH);
                        }
                        else if (sameas(m_nambuf,"SAME DIR")) {
                             INT idx = findstg("SAME DIR",m_pathbuf);
                             ASSERT(idx != 0);
                             m_pathbuf[idx-CSTRLEN("SAME DIR")]='\0';
                        }

                        ASSERT(m_pathbuf != NULL);

                        if (m_pathbuf == NULL) {
                             return(ACTHDONE);
                        }

                        if (m_nambuf != NULL && sameas(m_nambuf,"DRVLST")) {
                             if (dnf == NULL) {
                                  dnf = new dnfHandler(rsyDirMap,bout);
                             }
                             else {
                                  retval=dnf_dir(DRVLST);
                             }
                        }
                        else {
                             retval=processDir(m_pathbuf);
                             if (retval == ACTHDONE) {
                                  curWrkDirOp(UPDATE,m_pathbuf);
                             }
                        }
                   }
                   else {
                        if (isfile(m_pathbuf)) {
                             if (tacptr->flags&HASMST ||
                                 checkAxs(tacptr,OPTRNF)) {
                                  ses->sndfile(m_pathbuf);
                             }
                             else {
                                  bout << "You don't have access to download "
                                          "files.";
                             }
                             retval=ACTHDONE;
                        }
                        else {
                             indnf=TRUE;
                        }
                   }
               }
               else {
                    bout << "You don't have access to this function.";
                    retval=ACTHDONE;
               }
          }

     }
     else {
          retval=ACTHNOTFND;
     }
     return(retval);
}

ACTHCODE
rsySynthesis::proceedPost()        // proceed synthesizing response to POST
{
     ACTHCODE retval=ACTHMORE;
     INT narg;

     if ((narg=ses->urlargc()) == 1) {
          if (sameas(ses->urlargv(0),"msgtouser")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPSEND)) {
                    CHAR usrbuf[UIDSIZ];
                    CHAR msgbuf[INPSIZ];
                    ses->param("HID_USER",usrbuf,UIDSIZ);
                    ses->param("NAM_MSG2USER",msgbuf,INPSIZ);
                    if (usrbuf[0] != '\0' && onsysn(usrbuf,TRUE)) {
                         if (msgbuf[0] != '\0') {
                              snd2ch(othusn,StpBGWhite(StpNDWhite(msgbuf)));
                              bout << "Message has been sent to " << usrbuf;
                              TrackLog(MSGTRK,0,usrbuf,NULL);
                         }
                         else {
                              bout << "You must enter a message!";
                         }
                    }
                    else {
                         bout << usrbuf << " is not currently online.";
                    }
               }
               else {
                    bout << "You don't have access to send a message to a "
                            "user.";
               }
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"gotouser")) {

               if (tacptr->flags&HASMST || checkAxs(tacptr,OPDETL)) {
                   CHAR uidbuf[UIDSIZ];
                   uidbuf[0]='\0';
                   if (ses->param("NAM_USER",uidbuf,UIDSIZ) && uidbuf[0] != '\0') {
                        if (!indnf) {
                             xrfptr = new acthUserXrf(pls2spc(uidbuf),10);
                             if (xrfptr->ismatch()) {
                                  delete xrfptr;
                                  xrfptr = new acthUserXrf(pls2spc(uidbuf),1);
                                  matchflg=TRUE;
                                  tempuid=xrfptr->getmatch();
                             }
                        }
                        indnf=TRUE;
                        if (matchflg) {
                             if (dnf == NULL) {
                                  dnf = new dnfHandler(rsyAccframeMap,bout);
                             }
                             else {
                                  retval=dnf_accframe(spc2pls(tempuid));
                             }
                        }
                        else {
                             if (dnf == NULL) {
                                  dnf = new dnfHandler(rsyAccfindMap,bout);
                             }
                             else {
                                  retval=dnf_accfind();
                             }
                        }
                   }
                   else {
                        bout << "Blank entries are not allowed!";
                        retval=ACTHDONE;
                   }
               }
               else {
                    bout << "You don't have access to this function.";
                    retval=ACTHDONE;
               }
          }
          else if (sameas(ses->urlargv(0),"busyout")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPCHNG)) {
                    CHAR busychn[3];
                    if (ses->param("NAM_BUSYOUT",busychn,3) && allhex(busychn)) {
                         INT chn=usridx(htoi(busychn));
                         if (chn == -1) {
                              bout << "That is an invalid channel";
                         }
                         else {
                              proceedChanop(chn,BUSYOUT);
                         }
                    }
                    else {
                         bout << "You cannot perform that operation on this "
                                "channel.";
                    }
               }
               else {
                    bout << "You don't have access to this operation.";
               }
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"noanswer")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPCHNG)) {
                    CHAR noanschn[3];
                    if (ses->param("NAM_NOANSWER",noanschn,3) && allhex(noanschn)) {
                         INT chn=usridx(htoi(noanschn));
                         if (chn == -1) {
                              bout << "That is not a valid channel.";
                         }
                         else {
                              proceedChanop(chn,NOANSWER);
                         }
                   }
                   else {
                        bout << "You cannot perform that operation on this "
                                "channel.";
                   }
               }
               else {
                    bout << "You don't have access to this operation.";
               }
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"normal")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPCHNG)) {
                    CHAR normalchn[3];
                    if (ses->param("NAM_NORMAL",normalchn,3) && allhex(normalchn)) {
                         INT chn=usridx(htoi(normalchn));
                         if (chn == -1) {
                              bout << "That is not a valid channel.";
                         }
                         else {
                              proceedChanop(chn,NORMALIZE);
                         }
                   }
                   else {
                        bout << "You cannot perform that operation on this "
                                "channel.";
                   }
               }
               else {
                    bout << "You don't have access to this operation.";
               }
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"hangup")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPHNGP)) {
                    CHAR hangchn[3];
                    if (ses->param("NAM_HANGUP",hangchn,3) && allhex(hangchn)) {
                         INT chn=usridx(htoi(hangchn));
                         if (chn != -1 && incusr(chn,TRUE,TRUE) > VACANT) {
                              proceedChanop(chn,HANGUP);
                         }
                         else {
                              bout << "That is not a valid channel.";
                         }
                    }
                    else {
                         bout << "You cannot hang-up this channel.";
                    }
               }
               else {
                    bout << "You don't have access to hangup users.";
               }
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"cupevt")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPCLNP)) {
                   CHAR checkbuf[max(sizeof("EVENT#"),sizeof("CLEANUP"))];
                   CHAR dlybuf[3];
                   SHORT dly, clntyp=NOEVENT;
                   INT savcur;
                   ses->param("NAM_CLEANUP",checkbuf,sizeof(checkbuf));
                   if (sameas(checkbuf,"EVENT1")) {
                        clntyp=EVENT1;
                   }
                   else if (sameas(checkbuf,"EVENT2")) {
                        clntyp=EVENT2;
                   }
                   else if (sameas(checkbuf,"EVENT3")) {
                        clntyp=EVENT3;
                   }
                   else if (sameas(checkbuf,"EVENT4")) {
                        clntyp=EVENT4;
                   }
                   else if (sameas(checkbuf,"CLEANUP")) {
                        clntyp=CLEANUP;
                   }
                   if (clntyp == NOEVENT) {
                        bout << "Invalid selection.";
                        return(ACTHDONE);
                   }
                   if (ses->param("NAM_DLYEVT",dlybuf,sizeof(dlybuf))
                    && alldgs(dlybuf) && (dly=atoi(dlybuf)) > 0 && dly < 11) {
                        TrackLog(EVTTRK,atoi(checkbuf)-10,NULL,NULL);
                        savcur=usrnum;
                        errcod=clntyp;
                        rsykil=dly+1;
                        rsmode=rsetop;
                        prepff();
                        curusr(savcur);
                        rsyevt();         // rtkicks down event (rsykil --)
                        bout << "System set for event.";
                   }
                   else {
                        bout << "An error occured.  Please review "
                                "your input";
                   }
               }
               else {
                    bout << "You don't have access to initiate a System Event";
               }
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"kilsys")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPSHDN)) {
                   CHAR kilbuf[6];
                   ses->param("NAM_KIL",kilbuf,6);
                   if (kilbuf[0] != '\0') {
                        if (sameas(kilbuf,"1MIN")) {
                             kilctr=1;
                        }
                        else if (sameas(kilbuf,"2MIN")) {
                             kilctr=2;
                        }
                        else if (sameas(kilbuf,"5MIN")) {
                             kilctr=5;
                        }
                        else if (sameas(kilbuf,"10MIN")) {
                             kilctr=10;
                        }
                        else {
                             bout << "That's an invalid selection!";
                             return(ACTHDONE);
                        }
                        bout << "System is set for kill.";
                        TrackLog(KSYTRK,0,NULL,NULL);
                        kilsrc=usrnum;
                        errcod=8;
                        fupkil();
                        return(ACTHDONE);
                   }
                   bout << "That's an invalid selection!";
               }
               else {
                    bout << "You don't have access to kill the system.";
               }
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"loganno")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPLOGN)) {
                    CHAR logbuf[MTXSIZ];
                    ses->param("NAM_LOGANO",logbuf,MTXSIZ);
                    if (logbuf[0] == '\0') {
                         sv.lonmsg[0]='\0';
                         bout << "Logon message has been cleared.";
                    }
                    else {
                         stzcpy(sv.lonmsg,StpBGWhite(StpNDWhite(logbuf)),
                                MTXSIZ);
                         bout << "Logon message is set.";
                         TrackLog(LOGTRK,0,NULL,NULL);
                    }
               }
               else {
                    bout << "You don't have access to set the logon "
                            "announcement.";
               }
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"msgtoall")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPSALL)) {
                   CHAR msgbuf[MTXSIZ];
                   ses->param("NAM_MSGTOALL",msgbuf,MTXSIZ);
                   if (msgbuf[0] == '\0') {
                        bout << "You must enter a message!";
                   }
                   else {
                        snd2al(StpBGWhite(StpNDWhite(msgbuf)));
                        bout << "Message has been sent!";
                        TrackLog(AMSTRK,0,NULL,NULL);
                   }
               }
               else {
                    bout << "You don't have access to send a message to all "
                            "users.";
               }
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"search")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPSRCH)) {
                   CHAR fldnumbuf[3], keybuf[40], opbuf[2];
                   ses->param("NAM_FIELD",fldnumbuf,3);
                   ses->param("NAM_KEY",keybuf,40);
                   ses->param("NAM_RELATE",opbuf,2);
                   if (fldnumbuf[0] == '\0' || !alldgs(fldnumbuf) ||
                       atoi(fldnumbuf) < 0 || atoi(fldnumbuf) > 17 ||
                       opbuf[0] == '\0' || !alldgs(opbuf) || atoi(opbuf) < 1
                       || atoi(opbuf) > 5 || keybuf[0] == '\0') {
                        bout << "Input is invalid.  Please double-check "
                             << "and try again.";
                        retval=ACTHDONE;
                   }
                   else {
                        if (dnf == NULL) {
                             dnf = new dnfHandler(rsySearchProcMap,bout);
                        }
                        else {
                             retval=dnf_searchproc(keybuf,fldnumbuf,opbuf);
                        }
                   }
               }
               else {
                    bout << "You don't have access to Search.";
                    retval=ACTHDONE;
               }
          }
          else if (sameas(ses->urlargv(0),"classtodelete")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPACCT)) {
                   CHAR clsbuf[KEYLEN];
                   if (ses->param("NAM_DELCLASS",clsbuf,sizeof(clsbuf)) &&
                       clsbuf[0] != '\0') {
                        if ((savclsptr=fndcls(clsbuf)) != NULL) {
                             dltcls(savclsptr);
                             bout << "The " << clsbuf << " class has been deleted.";
                             return(ACTHDONE);
                        }
                   }
                   bout << "Unable to delete class.";
               }
               else {
                    bout << "You don't have access to Delete a Class.";
               }
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"classtoedit")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPACCT)) {
                    CHAR clsbuf[KEYLEN];
                    if (ses->param("NAM_EDCLASS",clsbuf,sizeof(clsbuf)) &&
                        clsbuf[0] != '\0') {
                         if ((savclsptr=fndcls(clsbuf)) != NULL) {
                              if (dnf == NULL) {
                                   dnf = new dnfHandler(rsyDoEditMap,bout);
                              }
                              else {
                                   retval=dnf_CEClass(clsbuf,EDITCLASS);
                              }
                         }
                         else {
                              bout << "Can't find class.";
                              return(ACTHDONE);
                         }
                    }
                    else {
                         bout << "Can't find class.";
                         return(ACTHDONE);
                    }
               }
               else {
                    bout << "You don't have access to Edit a Class.";
                    retval=ACTHDONE;
               }
          }
          else if (sameas(ses->urlargv(0),"classtocreate")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPACCT)) {
                   CHAR clsbuf[KEYLEN];
                   if (ses->param("NAM_CREATE",clsbuf,sizeof(clsbuf)) &&
                       clsbuf[0] != '\0') {
                        if ((savclsptr=fndcls(clsbuf)) != NULL) {
                             bout << "Class already exists!";
                             return(ACTHDONE);
                        }
                        else if (namacls(clsbuf)) {
                             if (dnf == NULL) {
                                  dnf = new dnfHandler(rsyDoCreateMap,bout);
                             }
                             else {
                                  retval=dnf_CEClass(clsbuf,CREATECLASS);
                             }
                        }
                        else {
                             bout << "Class name is not accepted.";
                             return(ACTHDONE);
                        }
                   }
                   else {
                        bout << "Can't find class.";
                        return(ACTHDONE);
                   }
               }
               else {
                    bout << "You don't have access to Create a Class.";
                    retval=ACTHDONE;
               }
          }
          else if (sameas(ses->urlargv(0),"submitclasscreate")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPACCT)) {
                   CHAR clsbuf[KEYLEN];
                   CHAR newring[KEYLEN+2];
                   if (ses->param("NAM_HIDCLS",clsbuf,KEYLEN) &&
                       clsbuf[0] != '\0' && namacls(clsbuf) &&
                       fndcls(clsbuf) == NULL) {
                        setmem(&cls,sizeof(acclass),0);
                        stlcpy(cls.clname,clsbuf,sizeof(cls.clname));
                        if (SubmitClassVerify()) {
                             if (crtclass(&cls)) {
                                  bout << clsbuf << " class created." << endl;
                                  newring[0]=RINGID;
                                  newring[1]='\0';
                                  stlcat(newring,clsbuf,KEYLEN+2);
                                  nkyrec(newring);
                                  HandleSubmitKeys();
                             }
                             else {
                                  bout << "Failed to create class!";
                             }
                        }
                   }
                   else {
                        bout << "Class name is invalid";
                   }
               }
               else {
                    bout << "You don't have access to Create a Class.";
               }
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"submitclassedit")) {
               if (tacptr->flags&HASMST || checkAxs(tacptr,OPACCT)) {
                   CHAR clsbuf[KEYLEN];
                   if (ses->param("NAM_HIDCLS",clsbuf,KEYLEN) &&
                       clsbuf[0] != '\0' && (savclsptr=fndcls(clsbuf)) != NULL) {
                        setmem(&cls,sizeof(acclass),0);
                        dfaSetBlk(clsbb);
                        dfaGetEQ(&cls,clsbuf,0);
                        if (SubmitClassVerify()) {
                             movmem(&cls,savclsptr,
                                    sizeof(struct clstab)-
                                    sizeof(struct clstab *));
                             dfaUpdate(&cls);
                             bout << clsbuf <<
                                     " class has been updated." << endl;
                             HandleSubmitKeys();
                        }
                        dfaRstBlk();
                   }
                   else {
                        bout << "Class name is invalid.";
                   }
               }
               else {
                    bout << "You don't have access to Edit a Class.";
               }
               retval=ACTHDONE;
          }
          else {
               retval=ACTHNOTFND;
          }
     }
     else if (narg == 2) {
          if (!tacptr->flags&HASMST && !checkAxs(tacptr,OPACCT)) {
               bout << "You don't have access to this function.";
               return(ACTHDONE);
          }
          CHAR uidbuf[UIDSIZ];
          struct usracc *uptr;
          stzcpy(uidbuf,pls2spc((CHAR *)ses->urlargv(1)),UIDSIZ);
          if (uidbuf[0] == '\0') {
               return(ACTHNOTFND);
          }
          if ((uptr=GetAccPtr(uidbuf)) == NULL) {
               return(ACTHNOTFND);
          }
          if (sameas(ses->urlargv(0),"accpost")) {
               retval=proceedAccpdnf(uptr);
          }
          else if (sameas(ses->urlargv(0),"accop")) {
               if (sameas(uptr->userid,"Sysop")) {
                    bout << "Sysop automatically has full remote access.";
               }
               else {
                    proceedAccOp(uptr);
               }
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"impkey")) {
               retval=proceedImpkey(uptr);
          }
          else if (sameas(ses->urlargv(0),"addimpkey")) {
               retval=proceedAddImpkey(uptr);
          }
          else if (sameas(ses->urlargv(0),"addkey")) {
               retval=proceedAddkey(uptr);
          }
          else if (sameas(ses->urlargv(0),"removekey")) {
               retval=proceedRemovekey(uptr);
          }
          else if (sameas(ses->urlargv(0),"postcred")) {
               proceedPostcred(uptr);
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"postday")) {
               proceedPostday(uptr);
               retval=ACTHDONE;
          }
          else if (sameas(ses->urlargv(0),"newuser")) {
               proceedCopyuser(uptr);
               retval=ACTHDONE;
          }
          else {
               retval=ACTHNOTFND;
          }
     }
     else {
          retval=ACTHNOTFND;
     }
     return(retval);
}

ACTHCODE
rsySynthesis::proceedNoFrame()     // proceed with no-frame main page
{
     // not being implement in this release
     bout << "No frame Remote Management has not " <<
             "been implemented in this version.";
     return(ACTHDONE);
}

ACTHCODE
rsySynthesis::proceedFrame()       // proceed with frameified rsy main page
{
     ses->redirect("/remote/rsyframe.htm");
     return(ACTHDONE);
}

ACTHCODE
rsySynthesis::dnf_about()          // About Dynafile
{
     ACTHCODE retval=ACTHMORE;

     switch (dnf->process()) {
     case ABOUTITLE:
          bout << SVR_NAME " -- Online Applications Server<br>" <<
                  "Copyright (c) 1986-1999 Galacticomm, Inc." <<
                  "  All Rights Reserved.";
          break;
     case REGNO:
          bout << bturno;
          break;
     case BTRPARM:
          bout << "(See System Registry)";
          break;
     case VERSINF:
          bout << version << subvers;
          break;
     case DSKFRE:
          bout << dbytes(dskfre("."));
          break;
     case CHANS:
          bout << nterms;
          break;
     case DLLSONSYS:
          bout << curdlls;
          break;
     case OSINF:
          about_os();
          break;
     case CREDTITLE:
          bout << "Credits";
          break;
     case CREDITS:
          bout << SVR_NAME << " developed by: " <<
          "Jack Alvrus, Joe Delekto, Phil Henning, Wally Muharsky, " <<
          "<br>Nathan Osterc, Richard Skurnick, and Vincent Toscano";
          break;
     case COPYRIGHT:
          bout << "Portions of this program Copyright 1982-1995 " <<
                  "Btrieve Technologies, Inc.  All Rights Reserved";
          break;
     case DNFEND:
          retval=ACTHDONE;
          break;
     }
     return(retval);
}

ACTHCODE
rsySynthesis::dnf_msg2user(        // Message to user dynafile
CHAR *user)
{
     ACTHCODE retval=ACTHMORE;

     switch(dnf->process()) {
     case NAM_USER:
          bout << pls2spc(user);
          break;
     case DNFEND:
          retval=ACTHDONE;
          break;
     }
     return(retval);
}

ACTHCODE
rsySynthesis::dnf_logano()         // Logon message dynafile
{
     ACTHCODE retval=ACTHMORE;

     switch(dnf->process()) {
     case TXT_LOGMSG:
          bout << sv.lonmsg;
          break;
     case DNFEND:
          retval=ACTHDONE;
          break;
     }
     return(retval);
}

ACTHCODE
rsySynthesis::dnf_classlist()      // Class-listing for Delete/Edit
{
     ACTHCODE retval=ACTHMORE;

     switch(dnf->process()) {
     case DNFROWBEGIN:
          if (dnf->rowNumber() == 0) {
              savclsptr=clshead;
              if (savclsptr->flags&HASCRD && savclsptr->flags&NOCRED) {
                    savclsptr=nxtcls(savclsptr);
              }
          }
          if (savclsptr == NULL || strlen(savclsptr->clname) == 0) {
              dnf->tableDone();
              break;
          }
          break;
     case CLASSDESC:
          bout << savclsptr->clname;
          savclsptr=nxtcls(savclsptr);
          break;
     case DNFROWEND:
          if (savclsptr == NULL || strlen(savclsptr->clname) == 0) {
               dnf->tableDone();
          }
          break;
     case DNFEND:
          retval=ACTHDONE;
          break;
     }
     return(retval);
}

ACTHCODE
rsySynthesis::dnf_CEClass(         // Create/Edit Class dynafile
CHAR *clas,
SHORT optype)
{
     ACTHCODE retval=ACTHMORE;

     switch(dnf->process()) {
     case DNFBEGIN:
          savclsptr=fndcls(clas);
          dnfcnt=-1;
          break;
     case DNFROWBEGIN:
          dnfcnt++;
          switch(optype) {
          case EDITCLASS:
               if (dnfcnt == 2) {
                    wrkclsptr=clshead;
                    if (wrkclsptr->flags&HASCRD && wrkclsptr->flags&NOCRED) {
                         wrkclsptr=nxtcls(wrkclsptr);
                    }
               }
               if (dnfcnt >= 2) {
                    while (wrkclsptr != NULL && savclsptr != NULL &&
                           (sameas(wrkclsptr->clname,savclsptr->clname) ||
                           sameas(wrkclsptr->clname,
                           savclsptr->nxtcls[tablecnt]))) {
                         wrkclsptr=nxtcls(wrkclsptr);
                    }
               }
               if (dnfcnt >= 2) {
                    if (wrkclsptr == NULL) {
                         dnfcnt=-1;
                         tablecnt++;
                         dnf->tableDone();
                    }
               }
               break;
          case CREATECLASS:
               if (dnfcnt == 1) {
                    wrkclsptr=clshead;
                    if (wrkclsptr->flags&HASCRD && wrkclsptr->flags&NOCRED) {
                         wrkclsptr=nxtcls(wrkclsptr);
                    }
                    if (wrkclsptr == NULL) {
                         dnfcnt=-1;
                         tablecnt++;
                         dnf->tableDone();
                    }
               }
          }
          break;
     case VAL_HIDCLS:
     case CLASSWATCH:
          bout << clas;
          break;
     case VAL_MINPERSESS:
          switch(optype) {
          case EDITCLASS:
               if (savclsptr->limcal == -1) {
                    bout << "";
               }
               else {
                    bout << savclsptr->limcal;
               }
               break;
          case CREATECLASS:
               bout << "60";
               break;
          }
          break;
     case MINPERSESSCHECKED:
          switch(optype) {
          case EDITCLASS:
               if (savclsptr->limcal == -1) {
                    bout << "CHECKED";
               }
               else {
                    bout << "";
               }
               break;
          case CREATECLASS:
               bout << "";
               break;
          }
          break;
     case VAL_MINPERDAY:
          switch(optype) {
          case EDITCLASS:
               if (savclsptr->limday == -1) {
                    bout << "";
               }
               else {
                    bout << savclsptr->limday;
               }
               break;
          case CREATECLASS:
               bout << "60";
               break;
          }
          break;
     case MINPERDAYCHECKED:
          switch(optype) {
          case EDITCLASS:
               if (savclsptr->limday == -1) {
                    bout << "CHECKED";
               }
               else {
                    bout << "";
               }
               break;
          case CREATECLASS:
               bout << "";
               break;
          }
          break;
     case SOFFCHECKED:
          switch (optype) {
          case EDITCLASS:
               if (savclsptr->flags&KCKOFF) {
                    bout << "CHECKED";
               }
               else {
                    bout << "";
               }
               break;
          case CREATECLASS:
               bout << "CHECKED";
               break;
          }
          break;
     case RESTOFDAYCHECKED:
          switch(optype) {
          case EDITCLASS:
               if (savclsptr->flags&CLSCHG) {
                    bout << "CHECKED";
               }
               else {
                    bout << "";
               }
               break;
          case CREATECLASS:
               bout << "";
               break;
          }
          break;
     case VAL_CLASSTRANS:
          switch (optype) {
          case EDITCLASS:
               dfaSetBlk(clsbb);
               dfaGetEQ(&cls,clas,0);
               bout << StpBGWhite(StpNDWhite(cls.msgs[0]));
               dfaRstBlk();
               break;
          case CREATECLASS:
               bout << "";
               break;
          }
          break;
     case CREDEXEMPTCHECKED:
          switch (optype) {
          case EDITCLASS:
               if (savclsptr->flags&CRDXMT) {
                    bout << "CHECKED";
               }
               else {
                    bout << "";
               }
               break;
          case CREATECLASS:
               bout << "";
               break;
          }
          break;
     case ACCRUECHECKED:
          switch (optype) {
          case EDITCLASS:
               if (savclsptr->dbtlmt != 0) {
                    bout << "CHECKED";
               }
               else {
                    bout << "";
               }
               break;
          case CREATECLASS:
               bout << "";
               break;
          }
          break;
     case NOCHECKED:
          switch (optype) {
          case EDITCLASS:
               if (savclsptr->dbtlmt == 0 && !(savclsptr->flags&CRDXMT)) {
                    bout << "CHECKED";
               }
               else {
                    bout << "";
               }
               break;
          case CREATECLASS:
               bout << "CHECKED";
               break;
          }
          break;
     case VAL_DEBTLIMIT:
          switch (optype) {
          case EDITCLASS:
               if (savclsptr->dbtlmt != -1 && savclsptr->dbtlmt != 0) {
                    bout << savclsptr->dbtlmt;
               }
               else {
                    bout << "";
               }
               break;
          case CREATECLASS:
               bout << "36000";
               break;
          }
          break;
     case DEBTLIMITCHECKED:
          switch (optype) {
          case EDITCLASS:
               if (savclsptr->dbtlmt == -1) {
                    bout << "CHECKED";
               }
               else {
                    bout << "";
               }
               break;
          case CREATECLASS:
               bout << "";
               break;
          }
          break;
     case VAL_GENREP:
          switch (optype) {
          case EDITCLASS:
               if (savclsptr->flags&REPDBT) {
                    bout << "CHECKED";
               }
               else {
                    bout << "";
               }
               break;
          case CREATECLASS:
               bout << "";
               break;
          }
          break;
     case RADGENREP0CHECKED:
          switch(optype) {
          case EDITCLASS:
               if (savclsptr->flags&FSTMTH) {
                    bout << "CHECKED";
               }
               else {
                    bout << "";
               }
               break;
          case CREATECLASS:
               bout << "";
               break;
          }
          break;
     case RADGENREP1CHECKED:
          switch(optype) {
          case EDITCLASS:
               if (savclsptr->flags&HITLMT) {
                    bout << "CHECKED";
               }
               else {
                    bout << "";
               }
               break;
          case CREATECLASS:
               bout << "";
               break;
          }
          break;
     case RADGENREP2CHECKED:
          switch(optype) {
          case EDITCLASS:
               if (savclsptr->flags&MONDAY) {
                    bout << "CHECKED";
               }
               else {
                    bout << "";
               }
               break;
          case CREATECLASS:
               bout << "";
               break;
          }
          break;
     case RADGENREP3CHECKED:
          switch(optype) {
          case EDITCLASS:
               if (savclsptr->flags&NUMDAY) {
                    bout << "CHECKED";
               }
               else {
                    bout << "";
               }
               break;
          case CREATECLASS:
               bout << "";
               break;
          }
          break;
     case VAL_REPDAYS:
          switch(optype) {
          case EDITCLASS:
               if (savclsptr->flags&NUMDAY) {
                    bout << savclsptr->fgvday;
               }
               else {
                    bout << "";
               }
               break;
          case CREATECLASS:
               bout << "90";
               break;
          }
          break;
     case LOGGEDINCHECKED:
          switch(optype) {
          case EDITCLASS:
               if (savclsptr->flags&IDLEXP) {
                    bout << "CHECKED";
               }
               else {
                    bout << "";
               }
               break;
          case CREATECLASS:
               bout << "90";
               break;
          }
          break;
     case VAL_DAYSNOLOG:
          switch(optype) {
          case EDITCLASS:
               if (savclsptr->flags&IDLEXP) {
                    bout << savclsptr->idlday;
               }
               else {
                    bout << "";
               }
               break;
          case CREATECLASS:
               bout << "90";
               break;
          }
          break;
     case CLASDESC:
          switch (optype) {
          case EDITCLASS:
              if (dnfcnt == 0) {
                   bout << savclsptr->nxtcls[tablecnt];
              }
              if (dnfcnt == 1) {
                   if (savclsptr->nxtcls[tablecnt] == NULL ||
                       !sameas(savclsptr->nxtcls[tablecnt],"DELETE_ACCOUNT")) {
                        bout << "DELETE_ACCOUNT";
                   }
                   else {
                        wrkclsptr=clshead;
                        if (wrkclsptr->flags&HASCRD && wrkclsptr->flags&NOCRED) {
                             wrkclsptr=nxtcls(wrkclsptr);
                        }
                        if (wrkclsptr == NULL) {
                             break;
                        }
                        dnfcnt++;
                   }
              }
              if (dnfcnt >= 2) {
                   bout << wrkclsptr->clname;
              }
              break;
          case CREATECLASS:
              if (dnfcnt == 0) {
                  bout << "DELETE_ACCOUNT";
              }
              else {
                  bout << wrkclsptr->clname;
                  wrkclsptr=nxtcls(wrkclsptr);
              }
              break;
          }
          break;
     case DAYSINCHECKED:
          switch(optype) {
          case EDITCLASS:
               if (savclsptr->flags&DAYEXP) {
                    bout << "CHECKED";
               }
               else {
                    bout << "";
               }
               break;
          case CREATECLASS:
               bout << "90";
               break;
          }
          break;
     case VAL_DAYSIN:
          switch(optype) {
          case EDITCLASS:
               if (savclsptr->flags&DAYEXP) {
                    bout << savclsptr->dftday;
               }
               else {
                    bout << "";
               }
               break;
          case CREATECLASS:
               bout << "90";
               break;
          }
          break;
     case CREDOUTCHECKED:
          switch(optype) {
          case EDITCLASS:
               if (savclsptr->flags&NOCRED) {
                    bout << "CHECKED";
               }
               else {
                    bout << "";
               }
               break;
          case CREATECLASS:
               bout << "90";
               break;
          }
          break;
     case CREDPOSTCHECKED:
          switch(optype) {
          case EDITCLASS:
               if (savclsptr->flags&HASCRD) {
                    bout << "CHECKED";
               }
               else {
                    bout << "";
               }
               break;
          case CREATECLASS:
               bout << "90";
               break;
          }
          break;
     case REACHLIMCHECKED:
          switch(optype) {
          case EDITCLASS:
               if (savclsptr->flags&DBTLMT) {
                    bout << "CHECKED";
               }
               else {
                    bout << "";
               }
               break;
          case CREATECLASS:
               bout << "";
               break;
          }
          break;
     case NONECHECKED:
          switch(optype) {
          case EDITCLASS:
               if (!(savclsptr->flags&NOCRED) && !(savclsptr->flags&HASCRD)
                   && !(savclsptr->flags&DBTLMT)) {
                    bout << "CHECKED";
               }
               else {
                    bout << "";
               }
               break;
          case CREATECLASS:
               bout << "CHECKED";
          }
          break;
     case VAL_CLASSTRANS1:
          switch (optype) {
          case EDITCLASS:
               dfaSetBlk(clsbb);
               dfaGetEQ(&cls,clas,0);
               bout << StpBGWhite(StpNDWhite(cls.msgs[1]));
               dfaRstBlk();
               break;
          case CREATECLASS:
               bout << "";
               break;
          }
          break;
     case VAL_TXTKEYLIST:
          wrkclsptr=clshead;
          if (wrkclsptr->flags&HASCRD && wrkclsptr->flags&NOCRED) {
                wrkclsptr=nxtcls(wrkclsptr);
          }
          while (wrkclsptr != NULL) {
               CHAR *keyn;
               bout << endl;
               bout << wrkclsptr->clname << endl;
               bout << "----------------" << endl;
               keycnt=0;
               while (keycnt != -1) {
                    if ((keyn=displayKeys(wrkclsptr->clname,1)) != NULL) {
                         bout << strupr(keyn) << endl;
                    }
               }
               bout << endl;
               wrkclsptr=nxtcls(wrkclsptr);
          }
          break;
     case DNFROWEND:
          switch(optype) {
          case EDITCLASS:
               if (dnfcnt >= 2) {
                    if (wrkclsptr == NULL) {
                         dnfcnt=-1;
                         tablecnt++;
                         dnf->tableDone();
                         break;
                    }
                    wrkclsptr=nxtcls(wrkclsptr);
               }
               break;
          case CREATECLASS:
               if (dnfcnt > 0) {
                    if (wrkclsptr == NULL) {
                         dnfcnt=-1;
                         tablecnt++;
                         dnf->tableDone();
                    }
               }
               break;
          }
          break;
     case DNFEND:
          retval=ACTHDONE;
          break;
     }
     return(retval);
}

ACTHCODE
rsySynthesis::dnf_dir(             // Directory Listing dynafile
SHORT list_type)
{
     ACTHCODE retval=ACTHMORE;

     switch(dnf->process()) {
     case DNFBEGIN:
          if (list_type == DIRLST && dirnam[1] == ':' &&
              dirnam[2] == '\\' && dirnam[3] == '\0') {
               drvflg=TRUE;
          }
          break;
     case DNFROWBEGIN:
          if (list_type == DRVLST) {
               if (++dnfcnt > 26) {
                    dnf->tableDone();
               }
          }
          break;
     case URL:
          bout << ses->host();
          break;
     case DIRNAM:
          if (list_type == DRVLST) {
               bout << "All Drives";
          }
          else {
               bout << dirnam;
          }
          break;
     case FULDIR:
          if (drvflg == TRUE) {
               bout << "listing/" << "DRVLST";
          }
          else if (list_type == DRVLST) {
               CHAR cwd[GCMAXPTH];
               getcwd(cwd,GCMAXPTH);
               if (!_chdrive(dnfcnt)) {
                    bout << htmldrvs[dnfcnt-1] << "/" << "SAME+DIR";
                    okdrvflg=TRUE;
               }
               chdir(cwd);
          }
          else {
               CHAR tmpbuf[2*GCMAXPTH];
               strrpl(dirnam,'\\','/');
               bout << urlEncodeBuf(tmpbuf,dirnam,sizeof(tmpbuf));

               if (sameas(dirblk.ff_name,"." )) {
                    bout << "SAME+DIR";
               }
               else if (sameas(dirblk.ff_name,"..")) {
                    bout << "BACK+DIR";
               }
               else {
                    bout << urlEncodeBuf(tmpbuf,dirblk.ff_name,sizeof(tmpbuf));
               }
          }
          break;
     case FDIR:
          if (drvflg == TRUE) {
               bout << "..";
          }
          else if (list_type == DRVLST) {
               if (okdrvflg) {
                    bout << drvs[dnfcnt-1];
                    okdrvflg=FALSE;
               }
          }
          else {
               if (dirblk.ff_name[0] != '.') {
                    bout << getShortFileName(dirblk.ff_name);
               }
               else {
                    bout << dirblk.ff_name;
               }
          }
          break;
     case FSIZ:
          if (drvflg == TRUE) {
               bout << "[ALL DRIVES]";
          }
          else if (list_type == DIRLST) {
               bout << spr("%8.8s ",(dirblk.ff_attrib&FAMDIR) ? "[DIR]" :
                       l2as(dirblk.ff_fsize));
          }
          break;
     case FDATE:
          if (!drvflg && list_type == DIRLST) {
               bout << spr("%8.8s ",ncdate(dirblk.ff_fdate));
          }
          break;
     case FTIME:
          if (!drvflg && list_type == DIRLST) {
               INT hr;

               hr=dthour(dirblk.ff_ftime)%12;
               if (hr == 0) {
                    hr=12;
               }
               bout << spr("%2d:%02d%s",hr,dtmin(dirblk.ff_ftime),
                       ((dthour(dirblk.ff_ftime)/12) ? "p" : "a"));
          }
          break;
     case FLONGNAME:
          if (drvflg == FALSE && list_type != DRVLST) {
               bout << dirblk.ff_name;
          }
          break;
     case DNFROWEND:
          if (drvflg == TRUE) {
               drvflg=FALSE;
          }
          else if (list_type == DIRLST && !fndnxt(&dirblk)) {
               dnf->tableDone();
          }
          break;
     case DNFEND:
          retval=ACTHDONE;
          break;
     }
     return(retval);
}

ACTHCODE
rsySynthesis::dnf_copy()           // "Dummy" copy dnf
{
     ACTHCODE retval=ACTHMORE;

     switch(dnf->process()) {
     case DNFROWBEGIN:
          if (!docopy()) {
               dnf->tableDone();
          }
          break;
     case DNFEND:
          if (dnfcnt > 0) {
               bout << dnfcnt << " file(s) copied";
          }
          else {
               bout << "Unable to complete copy operation!";
          }
          retval=ACTHDONE;
          break;
     }
     return(retval);
}

ACTHCODE
rsySynthesis::dnf_delete()         // "Dummy" delete DNF
{
     ACTHCODE retval=ACTHMORE;

     switch(dnf->process()) {
     case DNFROWBEGIN:
          if (!dodelt()) {
               dnf->tableDone();
          }
          break;
     case DNFEND:
          if (dnfcnt > 0) {
               bout << dnfcnt << " file(s) deleted.";
          }
          else {
               bout << "Unable to complete delete operation!";
          }
          retval=ACTHDONE;
          break;
     }
     return(retval);
}

ACTHCODE
rsySynthesis::dnf_searchproc(      // Search for requested data
CHAR *keyval,
CHAR *fldval,
CHAR *opval)
{
     ACTHCODE retval=ACTHMORE;

     switch(dnf->process()) {
     case DNFBEGIN:
          dfaSetBlk(accbb);
          dfaStepLO(NULL);
          abspos=dfaAbs();
          dfaRstBlk();
          break;
     case DNFROWBEGIN:
          dfaSetBlk(accbb);
          dfaGetAbs(&uac,abspos,0);
          if (!isMatch(keyval,fldval,opval)) {
               if (dfaStepNX(&uac)) {
                    abspos=dfaAbs();
               }
               else {
                    dnf->tableDone();
                    dfaRstBlk();
                    break;
               }
               dnf->sayAgain();
          }
          dfaRstBlk();
          break;
     case SRCH_UID:
          matchcnt++;
          bout << uac.userid;
          break;
     case SRCHLNK_UID:
          bout << spc2pls(uac.userid);
          break;
     case SRCH_UIDNAM:
          bout << uac.usrnam;
          break;
     case DNFROWEND:
          dfaSetBlk(accbb);
          dfaGetAbs(NULL,abspos,0);
          if (dfaStepNX(&uac)) {
               abspos=dfaAbs();
          }
          else {
               dnf->tableDone();
          }
          dfaRstBlk();
          break;
     case DNFEND:
          if (!matchcnt) {
               bout << "<p align=center>No matches found";
          }
          retval=ACTHDONE;
          break;
     }
     return(retval);
}

ACTHCODE
rsySynthesis::dnf_userson()        // List users that are online
{
     ACTHCODE retval=ACTHMORE;

     switch (dnf->process()) {
     case DNFROWBEGIN:
          tab_user[0]=tab_chan[0]=tab_loc[0]=tab_cls[0]=tab_cred[0]=
          tab_timeon[0]=tab_invis[0]='\0';
          if (rown >= nterms) {
               dnf->tableDone();
               break;
          }
          othuap=uacoff(rown);
          othusp=usroff(rown);
          switch (incusr(rown,TRUE,TRUE)) {
          case UIDNGD:
          case VACANT:
               dnf->sayAgain();
               break;
          case ONLINE:
               stzcpy(tab_user,"Log-on in progress",UIDSIZ);
               stzcpy(tab_chan,spr("%2x",channel[rown]),3);
               break;
          case BBSPRV:
               stzcpy(tab_chan,spr("%2x",channel[rown]),3);
               stzcpy(tab_user,othuap->userid,UIDSIZ);
               stzcpy(tab_timeon,spr("%d",(othusp->minut4+2)>>2),10);
               stzcpy(tab_loc,module[othusp->state]->descrp,MNMSIZ);
               break;
          case SUPIPG:
               stzcpy(tab_user,"(sign-up in progress)",UIDSIZ);
               stzcpy(tab_chan,spr("%2x",channel[rown]),3);
               break;
          case SUPLON:
          case SUPLOF:
          case ACTUSR:
               stzcpy(tab_user,othuap->userid,UIDSIZ);
               stzcpy(tab_chan,spr("%2x",channel[rown]),3);
               stzcpy(tab_cred,l2as(othuap->creds),10);
               stzcpy(tab_timeon,spr("%d",(othusp->minut4+2)>>2),10);
               stzcpy(tab_loc,module[othusp->state]->descrp,MNMSIZ);
               stzcpy(tab_cls,othuap->curcls,KEYLEN);
               if (othuap->flags&INVISB) {
                    stzcpy(tab_invis,"Y",2);
               }
               else {
                    stzcpy(tab_invis,"N",2);
               }
               break;
          default:
               dnf->sayAgain();
               break;
          }
          rown++;
          break;
     case TAB_USER:
          if (tab_user[0] == '\0') {
               bout << "*";
          }
          else if (!uidxst(tab_user)) {
               bout << tab_user;
          }
          else {
               if (onsysn(tab_user,TRUE)) {
                    bout << "<a href=\"/remote/msg2user/" <<
                            spc2pls(tab_user) << "\" target=\"usermain\">" <<
                            tab_user << "</a>";
               }
               else {
                    bout << tab_user;
               }
          }
          break;
     case TAB_CHAN:
          if (tab_chan[0] == '\0') {
               bout << "*";
          }
          bout << tab_chan;
          break;
     case TAB_LOC:
          if (tab_loc[0] == '\0') {
               bout << "*";
          }
          bout << tab_loc;
          break;
     case TAB_CLS:
          if (tab_cls[0] == '\0') {
               bout << "*";
          }
          bout << tab_cls;
          break;
     case TAB_CRED:
          if (tab_cred[0] == '\0') {
               bout << "*";
          }
          bout << tab_cred;
          break;
     case TAB_TIMEON:
          if (tab_timeon[0] == '\0') {
               bout << "*";
          }
          bout << tab_timeon;
          break;
     case TAB_INVIS:
          if (tab_invis[0] == '\0') {
               bout << "*";
          }
          bout << tab_invis;
          break;
     case DNFEND:
          retval=ACTHDONE;
          break;
     }
     return(retval);
}

ACTHCODE
rsySynthesis::dnf_legend()
{
     ACTHCODE retval=ACTHMORE;
     RemHdl tmphdl;
     INT cusr;

     switch(dnf->process()) {
     case DNFBEGIN:
          dnfcnt=tmphdl.GetLegend((CHAR *)usr->userid());
          if (dnfcnt == 16) {
               dnfcnt = 0;
          }
          end=(dnfcnt*16)+16;
          dnfcnt=dnfcnt*16;
          break;
     case DNFROWBEGIN:
          if (dnfcnt >= end) {
               dnf->tableDone();
          }
          break;
     case LGD_USER:
          cusr=usridx(dnfcnt);
          if (cusr != -1) {
               INT state=-1;
               if (dnfcnt != 0 && (state=incusr(cusr,TRUE,TRUE)) > BBSPRV ) {
                    INT savusr = usrnum;
                    curusr(cusr);
                    bout << "<a href=\"/remote/accjump/" <<
                            spc2pls(usaptr->userid) <<
                            "\" target=\"rsymain\">" <<
                            uidarr[dnfcnt].labl << "</a>";
                    curusr(savusr);
               }
               else if ( state == BBSPRV )  // for Active H sessions
               {
                    if (uidarr[dnfcnt].labl[0] == '(') {
                         CHAR *uptr;
                         CHAR lbltemp[LGNSIZ];

                         stzcpy(lbltemp,uidarr[dnfcnt].labl,LGNSIZ);
                         depad(lbltemp);
                         uptr=lbltemp;
                         lbltemp[strlen(lbltemp)-1]='\0';
                         uptr++;

                         ASSERT(uptr != NULL);

                         if (uptr != NULL && uidxst(uptr)) {
                              bout << "<a href=\"/remote/accjump/" <<
                                      spc2pls(uptr) <<
                                      "\" target=\"rsymain\">" <<
                                      uidarr[dnfcnt].labl << "</a>";
                         }
                         else {
                              bout << uidarr[dnfcnt].labl;
                         }
                    }
                    else {
                         bout << uidarr[dnfcnt].labl;
                    }
               }
               else {
                    bout << uidarr[dnfcnt].labl;
               }
          }
          else {
               bout << "*";
          }
          break;
     case LGD_CHAN:
          bout << spr("%X",dnfcnt);
          break;
     case DNFROWEND:
          dnfcnt++;
          break;
     case DNFEND:
          retval=ACTHDONE;
          break;
     }
     return(retval);
}

ACTHCODE
rsySynthesis::dnf_variables()      // System Variables dynafile
{
     ACTHCODE retval=ACTHMORE;
     ULONG eavl;

     switch(dnf->process()) {
     case VAR_TIME:
          bout << nctime(now());
          break;
     case VAR_DATE:
          bout << ::prndat(PRND_MMDYY,today(),0);
          break;
     case VAR_MEMAVAIL:
          bout << "N/A";
          break;
     case VAR_RESPONSE:
          bout << rtmfmt(rsptim);
          break;
     case VAR_HDROOM:
          eavl=dskfre(".");
          bout << dbytes(eavl);
          break;
     case VAR_OPENEMAIL:
          bout << sv.emlopn;
          break;
     case VAR_OPENFORUM:
          bout << sv.sigopn;
          break;
     case VAR_TOTMSG:
          bout << sv.msgtot;
          break;
     case VAR_ACTIVEACCTS:
          bout << sv2.numact;
          break;
     case VAR_TOTCALLS:
          bout << sv2.totcalls;
          break;
     case VAR_UPLOADS:
          bout << sv.uplds;
          break;
     case VAR_DOWNLOADS:
          bout << sv.dwnlds;
          break;
     case DNFEND:
          retval=ACTHDONE;
          break;
     }
     return(retval);
}

ACTHCODE
rsySynthesis::dnf_accframe(        // Intermediate Account Dynafile function
CHAR *uid)
{
     ACTHCODE retval=ACTHMORE;

     switch(dnf->process()) {
     case UID:
          bout << uid;
          break;
     case DNFEND:
          retval=ACTHDONE;
          break;
     }
     return(retval);
}

ACTHCODE
rsySynthesis::dnf_accmain(         // Account info dynafile
struct usracc *uptr)
{
     ACTHCODE retval=ACTHMORE;

     switch(dnf->process()) {
     case DNFROWBEGIN:
          if (tablecnt == 0) {
               if (dnf->rowNumber() == (nlingo+1)) {
                    dnf->tableDone();
                    dnfcnt=0;
                    tablecnt++;
               }
          }
          else if (tablecnt == 1) {
               if (dnfcnt == 0) {
                    savclsptr=clshead;
                    if (savclsptr->flags&HASCRD && savclsptr->flags&NOCRED) {
                         savclsptr=nxtcls(savclsptr);
                    }
               }
               if (savclsptr == NULL || strlen(savclsptr->clname) == 0) {
                    dnf->tableDone();
                    tablecnt++;
                    break;
               }
               if (sameas(savclsptr->clname,uptr->curcls)) {
                    savclsptr=nxtcls(savclsptr);
                    if (savclsptr == NULL) {
                         dnf->tableDone();
                         tablecnt++;
                    }
               }
          }
          break;
     case POSTUID:
          bout << spc2pls(uptr->userid);
          break;
     case ACC_USERID:
          bout << uptr->userid;
          break;
     case ACC_CREATE:
          bout << ::prndat(PRND_MMDYY,uptr->credat,0);
          break;
     case ACC_NAME:
          bout << uptr->usrnam;
          break;
     case ACC_DAYLEFT:
          uptr->daystt == 0 ? bout << "Unlimited": bout << uptr->daystt;
          break;
     case ACC_ADDR1:
          bout << uptr->usrad1;
          break;
     case ACC_LASTLOG:
          bout << ::prndat(PRND_MMDYY,uptr->usedat,0);
          break;
     case ACC_ADDR2:
          bout << uptr->usrad2;
          break;
     case ACC_USEDTDY:
          secs2StdTime(uptr->timtdy);
          break;
     case ACC_ADDR3:
          bout << uptr->usrad3;
          break;
     case ACC_COLUMNS:
          bout << spr("%d",uptr->scnwid);
          break;
     case ACC_LINES:
          bout << spr("%d",uptr->scnfse);
          break;
     case ACC_PAUSE:
          bout << spr("%d",uptr->scnbrk);
          break;
     case ACC_ADDR4:
          bout << uptr->usrad4;
          break;
     case VISPSW:
          if (vispsw) {
               bout << "text";
          }
          else {
               bout << "password";
          }
          break;
     case ACC_PSW:
          bout << uptr->psword;
          break;
     case ACC_PHONE:
          bout << uptr->usrpho;
          break;
     case ACC_BORN:
          bout << strBirthdate(uptr->birthd);
          break;
     case ACC_COMP1:
          switchsnd(uptr->systyp,1,2,3,0);
          break;
     case ACC_COMP2:
          switchsnd(uptr->systyp,2,3,0,1);
          break;
     case ACC_COMP3:
          switchsnd(uptr->systyp,3,0,1,2);
          break;
     case ACC_COMP4:
          switchsnd(uptr->systyp,0,1,2,3);
          break;
     case ACC_EDITORCHECK1:
          uptr->usrprf&PRFLIN ? bout << "CHECKED" : bout << "";
          break;
     case ACC_EDITORCHECK2:
          uptr->usrprf&PRFLIN ? bout << "" : bout << "CHECKED";
          break;
     case ACC_SEXCHECK1:
          switch(uptr->sex) {
          case 'M':
              bout << "CHECKED";
              break;
          }
          break;
     case ACC_SEXCHECK2:
          switch(uptr->sex) {
          case 'F':
                bout << "CHECKED";
                break;
          }
          break;
     case ACC_CREDAVAIL:
          bout << uptr->creds;
          break;
     case ACC_MASTCHECK:
          if (uptr->flags&HASMST) {
               bout << "CHECKED";
          }
          break;
     case ACC_SUSPENDCHECK:
          if (uptr->flags&SUSPEN) {
               bout << "CHECKED";
          }
          break;
     case ACC_CREDTOTAL:
          bout << uptr->totcreds;
          break;
     case ACC_TAG4KILCHECK:
          if (uptr->flags&DELTAG) {
               bout << "CHECKED";
          }
          break;
     case ACC_PROTECTCHECK:
          if (uptr->flags&UNDAXS) {
               bout << "CHECKED";
          }
          break;
     case ACC_CREDPAID:
          bout << uptr->totpaid;
          break;
     case ACC_CLASSDESC:
          if (dnfcnt == 0) {
               bout << uptr->curcls;
          }
          else {
               bout << savclsptr->clname;
               savclsptr=nxtcls(savclsptr);
          }
          dnfcnt++;
          break;
     case ACC_LANGVAL:
          bout << dnf->rowNumber();
          break;
     case ACC_LANGDESC:
          if (dnf->rowNumber() == 0) {
                getgen(&gbuf,uptr->userid);
                if (gbuf.lngnam[0] == '\0') {
                    strcpy(deflang,"AUTOMATIC");
                    bout << "AUTOMATIC";
                }
                else {
                    strcpy(deflang,gbuf.lngnam);
                    bout << gbuf.lngnam;
                }
          }
          else if (!sameas(deflang,languages[dnf->rowNumber()-1]->name)) {
                    bout << languages[dnf->rowNumber()-1]->name;
                    break;
          }
          else if (!sameas(deflang,"AUTOMATIC")) {
                    bout << "AUTOMATIC";
          }
          break;
     case ACC_PSWHINT:
          bout << uaccext.pwdhint;
          break;
     case ACC_ALTEMAIL:
          bout << uaccext.alteml;
          break;
     case DNFROWEND:
          if (tablecnt == 1 && (savclsptr == NULL ||
              strlen(savclsptr->clname) == 0)) {
               dnf->tableDone();
          }
          break;
     case DNFEND:
          retval=ACTHDONE;
          break;
     }
     return(retval);
}

ACTHCODE
rsySynthesis::dnf_accfind()        // Find account dynafile
{
     ACTHCODE retval=ACTHMORE;

     switch (dnf->process()) {
     case DNFROWBEGIN:
          if ((tempuid=xrfptr->getmatch()) == NULL) {
               if (dnf->rowNumber() == 0) {
                    nonfnd=TRUE;
               }
               dnf->tableDone();
          }
          break;
     case RSYLINK:
          bout << spc2pls(tempuid);
          break;
     case RSYUSER:
          bout << tempuid;
          break;
     case DNFEND:
          if (nonfnd) {
               bout << "<p align=center>No users found.";
          }
          retval=ACTHDONE;
          break;
     }
     return(retval);
}

ACTHCODE
rsySynthesis::dnf_accfuncs(        // Account functions Dynafile
CHAR *uid)
{
     ACTHCODE retval=ACTHMORE;

     switch(dnf->process()) {
     case FUNCUID:
          bout << uid;
          break;
     case FUID:
          bout << spc2pls(uid);
          break;
     case DNFEND:
          retval=ACTHDONE;
          break;
     }
     return(retval);
}

ACTHCODE
rsySynthesis::accback(             // Go to previous user
CHAR *uid)
{
     ACTHCODE retval=ACTHMORE;

     dfaSetBlk(accbb);
     if (dfaAcqEQ(NULL,uid,0)) {
          if (dfaQueryPR()) {
               if (dnf == NULL) {
                    dnf = new dnfHandler(rsyAccframeMap,bout);
               }
               else {
                    dfaAbsRec(&tempacc,0);
                    retval=dnf_accframe(spc2pls(tempacc.userid));
               }
          }
          else {
               bout << "Couldn't find previous user!";
               retval=ACTHDONE;
          }
     }
     else {
         bout << "Couldn't find user";
         retval=ACTHDONE;
     }
     dfaRstBlk();
     return(retval);
}

ACTHCODE
rsySynthesis::accnext(             // Go to next user
CHAR *uid)
{
     ACTHCODE retval=ACTHMORE;

     dfaSetBlk(accbb);
     if (dfaAcqEQ(NULL,uid,0)) {
          if (dfaQueryNX()) {
               if (dnf == NULL) {
                    dnf = new dnfHandler(rsyAccframeMap,bout);
               }
               else {
                    dfaAbsRec(&tempacc,0);
                    retval=dnf_accframe(spc2pls(tempacc.userid));
               }
          }
          else {
               bout << "Couldn't find next user!";
               retval=ACTHDONE;
          }
     }
     else {
         bout << "Couldn't find user";
         retval=ACTHDONE;
     }
     dfaRstBlk();
     return(retval);
}

ACTHCODE
rsySynthesis::dnf_accremote(       // Remote access flags
struct usracc *uptr)
{
     ACTHCODE retval=ACTHMORE;

     switch (dnf->process()) {
     case ACCOPUID:
          bout << spc2pls(uptr->userid);
          break;
     case CHK_SENDALL:
          if (checkAxs(uptr,AccOps[dnfcnt].op)) {
               bout << "CHECKED";
          }
          else {
               bout << "";
          }
          break;
     case CHK_OVERALL:
          if (checkAxs(uptr,AccOps[dnfcnt].op)) {
               bout << "CHECKED";
          }
          else {
               bout << "";
          }
          break;
     case CHK_CHANEMU:
          if (checkAxs(uptr,AccOps[dnfcnt].op)) {
               bout << "CHECKED";
          }
          else {
               bout << "";
          }
          break;
     case CHK_SENDUSER:
          if (checkAxs(uptr,AccOps[dnfcnt].op)) {
               bout << "CHECKED";
          }
          else {
               bout << "";
          }
          break;
     case CHK_MODSTATS:
          if (checkAxs(uptr,AccOps[dnfcnt].op)) {
               bout << "CHECKED";
          }
          else {
               bout << "";
          }
          break;
     case CHK_CHANIO:
          if (checkAxs(uptr,AccOps[dnfcnt].op)) {
               bout << "CHECKED";
          }
          else {
               bout << "";
          }
          break;
     case CHK_LOGONMSG:
          if (checkAxs(uptr,AccOps[dnfcnt].op)) {
               bout << "CHECKED";
          }
          else {
               bout << "";
          }
          break;
     case CHK_SYSDEMO:
          if (checkAxs(uptr,AccOps[dnfcnt].op)) {
               bout << "CHECKED";
          }
          else {
               bout << "";
          }
          break;
     case CHK_CHANINP:
          if (checkAxs(uptr,AccOps[dnfcnt].op)) {
               bout << "CHECKED";
          }
          else {
               bout << "";
          }
          break;
     case CHK_CLSSTAT:
          if (checkAxs(uptr,AccOps[dnfcnt].op)) {
               bout << "CHECKED";
          }
          else {
               bout << "";
          }
          break;
     case CHK_CHANSTAT:
          if (checkAxs(uptr,AccOps[dnfcnt].op)) {
               bout << "CHECKED";
          }
          else {
               bout << "";
          }
          break;
     case CHK_DISFCON:
          if (checkAxs(uptr,AccOps[dnfcnt].op)) {
               bout << "CHECKED";
          }
          else {
               bout << "";
          }
          break;
     case CHK_DISCONU:
          if (checkAxs(uptr,AccOps[dnfcnt].op)) {
               bout << "CHECKED";
          }
          else {
               bout << "";
          }
          break;
     case CHK_DETAIL:
          if (checkAxs(uptr,AccOps[dnfcnt].op)) {
               bout << "CHECKED";
          }
          else {
               bout << "";
          }
          break;
     case CHK_LISTFDIR:
          if (checkAxs(uptr,AccOps[dnfcnt].op)) {
               bout << "CHECKED";
          }
          else {
               bout << "";
          }
          break;
     case CHK_SUSPENU:
          if (checkAxs(uptr,AccOps[dnfcnt].op)) {
               bout << "CHECKED";
          }
          else {
               bout << "";
          }
          break;
     case CHK_INFONU:
          if (checkAxs(uptr,AccOps[dnfcnt].op)) {
               bout << "CHECKED";
          }
          else {
               bout << "";
          }
          break;
     case CHK_COPYFIL:
          if (checkAxs(uptr,AccOps[dnfcnt].op)) {
               bout << "CHECKED";
          }
          else {
               bout << "";
          }
          break;
     case CHK_UNDAXS:
          if (checkAxs(uptr,AccOps[dnfcnt].op)) {
               bout << "CHECKED";
          }
          else {
               bout << "";
          }
          break;
     case CHK_SEARCH:
          if (checkAxs(uptr,AccOps[dnfcnt].op)) {
               bout << "CHECKED";
          }
          else {
               bout << "";
          }
          break;
     case CHK_RENFIL:
          if (checkAxs(uptr,AccOps[dnfcnt].op)) {
               bout << "CHECKED";
          }
          else {
               bout << "";
          }
          break;
     case CHK_DELETEU:
          if (checkAxs(uptr,AccOps[dnfcnt].op)) {
               bout << "CHECKED";
          }
          else {
               bout << "";
          }
          break;
     case CHK_AUDIT:
          if (checkAxs(uptr,AccOps[dnfcnt].op)) {
               bout << "CHECKED";
          }
          else {
               bout << "";
          }
          break;
     case CHK_DELFIL:
          if (checkAxs(uptr,AccOps[dnfcnt].op)) {
               bout << "CHECKED";
          }
          else {
               bout << "";
          }
          break;
     case CHK_SHUTDWN:
          if (checkAxs(uptr,AccOps[dnfcnt].op)) {
               bout << "CHECKED";
          }
          else {
               bout << "";
          }
          break;
     case CHK_ACCOUNT:
          if (checkAxs(uptr,AccOps[dnfcnt].op)) {
               bout << "CHECKED";
          }
          else {
               bout << "";
          }
          break;
     case CHK_CREATEDIR:
          if (checkAxs(uptr,AccOps[dnfcnt].op)) {
               bout << "CHECKED";
          }
          else {
               bout << "";
          }
          break;
     case CHK_FORCE:
          if (checkAxs(uptr,AccOps[dnfcnt].op)) {
               bout << "CHECKED";
          }
          else {
               bout << "";
          }
          break;
     case CHK_REMDIR:
          if (checkAxs(uptr,AccOps[dnfcnt].op)) {
               bout << "CHECKED";
          }
          else {
               bout << "";
          }
          break;
     case CHK_ACCFLG:
          if (checkAxs(uptr,AccOps[dnfcnt].op)) {
               bout << "CHECKED";
          }
          else {
               bout << "";
          }
          break;
     case CHK_FTOP:
          if (checkAxs(uptr,AccOps[dnfcnt].op)) {
               bout << "CHECKED";
          }
          else {
               bout << "";
          }
          break;
     case DNFEND:
          retval=ACTHDONE;
          break;
     }
     return(retval);
}

ACTHCODE
rsySynthesis::dnf_acckeys(         // Pull up key info for user
struct usracc *uptr,
CHAR *keyr)
{
     ACTHCODE retval=ACTHMORE;

     switch (dnf->process()) {
     case DNFROWBEGIN:
          if (tablecnt == 0) {
               if (dnfcnt == 0) {
                    savclsptr=clshead;
                    if (savclsptr->flags&HASCRD && savclsptr->flags&NOCRED) {
                         savclsptr=nxtcls(savclsptr);
                    }
                    if (savclsptr == NULL) {
                         dnf->tableDone();
                         tablecnt++;
                         dnfcnt=0;
                    }
               }
               else if ((savclsptr=nxtcls(savclsptr)) == NULL) {
                    dnf->tableDone();
                    dnfcnt=0;
                    tablecnt++;
               }
          }
          else if (tablecnt == 1) {
               if (keyr == NULL) {
                    dnf->tableDone();
                    dnfcnt=0;
                    tablecnt++;
                    break;
               }
               if ((keyptr=displayKeys(keyr,1)) != NULL) {
                    stzcpy(keepkeybuf,keyptr,KEYLEN);
               }
          }
          else if (tablecnt == 2) {
               if ((keyptr=displayKeys(uptr->userid,0)) != NULL) {
                    stzcpy(keepkeybuf,keyptr,KEYLEN);
               }
          }
          break;
     case HID_IMPCLS:
          bout << keyr;
          break;
     case KEYUIDS:
          bout << uptr->userid << "'s";
          break;
     case KEYUID:
          bout << spc2pls(uptr->userid);
          break;
     case CLS_OPDESC:
          bout << savclsptr->clname;
          break;
     case KEY_OPDESC:
          bout << keepkeybuf;
          break;
     case LST_KEYDESC:
          bout << keepkeybuf;
          break;
     case DNFROWEND:
          dnfcnt++;
          if (keycnt == -1) {
              dnf->tableDone();
              dnfcnt=0;
              tablecnt++;
              keycnt = 0;
          }
          break;
     case DNFEND:
          retval=ACTHDONE;
          break;
     }
     return(retval);
}

ACTHCODE
rsySynthesis::dnf_accpost(         // Post credits to account
struct usracc *uptr)
{
     ACTHCODE retval=ACTHMORE;

     switch (dnf->process()) {
     case PUID:
          bout << uptr->userid << "'s";
          break;
     case PSTUID:
          bout << spc2pls(uptr->userid);
          break;
     case CHK_CREDFREE:
          bout << "";
          break;
     case CHK_CREDPAID:
          bout << "CHECKED";
          break;
     case VAL_DAYSLEFT:
          uptr->daystt == 0 ? bout << "UNLIMITED" : bout << uptr->daystt;
          break;
     case DNFEND:
          retval=ACTHDONE;
          break;
     }
     return(retval);
}

ACTHCODE
rsySynthesis::dnf_acccopy(         // Copy one user to another id
struct usracc *uptr)
{
     ACTHCODE retval=ACTHMORE;

     switch (dnf->process()) {
     case COPYUID:
          bout << spc2pls(uptr->userid);
          break;
     case VISNEWPSW:
          if (vispsw) {
               bout << "text";
          }
          else {
               bout << "password";
          }
          break;
     case VAL_NEWPAS:
          bout << uptr->psword;
          break;
     case DNFEND:
          retval=ACTHDONE;
          break;
     }
     return(retval);
}

ACTHCODE
rsySynthesis::dnf_audend()         // Audit Trail DNF
{
     ACTHCODE retval=ACTHMORE;
     USHORT dosDate,dosTime;
     CHAR audbuf[155];
     struct audEntry buf;

     switch (dnf->process()) {
     case DNFBEGIN:
          abspos=(LONG)::audfNumRecs(::hAuditTrail);
          if (abspos < NUMAUD) {
               abspos=0;
          }
          else {
               abspos-=NUMAUD;
          }
          break;
     case AUDENTRY:
          ::audfReadEntry(::hAuditTrail,(ULONG)abspos,&buf,sizeof(buf));
          ::sDecodeDTDOS(buf.stamp,&dosDate,&dosTime);
          ::sprintf(audbuf,"%s %s %32.32s <em>%s</em><br>",
                    ::prntim(PRNT_HMS,dosTime),::prndat(PRND_MMDYY,dosDate,0),
                    buf.brief,buf.channel);
          bout << audbuf;
          dfaRstBlk();
          break;
     case DNFROWEND:
          if (++abspos >= ::audfNumRecs(::hAuditTrail)
           || dnf->rowNumber() >= NUMAUD-1) {
              dnf->tableDone();
          }
          break;
     case DNFEND:
          retval=ACTHDONE;
          break;
     }
     return(retval);
}

ACTHCODE
rsySynthesis::dnf_audit()          // Audit Trail Applet DNF
{
     ACTHCODE retval=ACTHMORE;

     switch (dnf->process()) {
          case AUDITZIP:
               {
                    CHAR      agentBuf[ 1024 ];
                    GBOOL     isNetscape = FALSE;
                    INT       version = 0;

                    if (ses->header( "User-Agent", agentBuf, sizeof( agentBuf )))
                    {
                         isNetscape = (getClientType( agentBuf ) == BROWSER_NETSCAPE);
                         version = getClientVer( agentBuf );
                    }

                    if (isNetscape && (version >= 4))
                    {
                         bout << "jar";
                    }
                    else
                    {
                         bout << "zip";
                    }
               }
               break;

          case DNFEND:
               retval=ACTHDONE;
               break;
     }
     return(retval);
}

ACTHCODE
rsySynthesis::dnf_demog()          // System Demographics
{
     ACTHCODE retval=ACTHMORE;
     INT i;

     switch (dnf->process()) {
     case DNFROWBEGIN:
          if (dnf->rowNumber() == 0) {
               incdemo=1;
          }
          else if (dnf->rowNumber() == 3) {
               incdemo=0;
          }
          else if (dnf->rowNumber() == 4) {
               incdemo=4;
          }
          else {
               incdemo++;
          }
          break;
     case DEM_COMP:
          switch (dnf->rowNumber()) {
          case 0:
               bout << "IBM PC";
               break;
          case 1:
               bout << "Macintosh";
               break;
          case 2:
               bout << "Apple";
               break;
          case 3:
               bout << "Other";
               break;
          case 4:
               bout << "Total";
               break;
          }
          break;
     case DEM_19:
          if (dnf->rowNumber() < 4) {
               bout << sv2.matrix[incdemo][0];
               dem19+=sv2.matrix[incdemo][0];
          }
          else {
               bout << dem19;
          }
          break;
     case DEM_29:
          if (dnf->rowNumber() < 4) {
               bout << sv2.matrix[incdemo][1];
               dem29+=sv2.matrix[incdemo][1];
          }
          else {
               bout << dem29;
          }
          break;
     case DEM_39:
          if (dnf->rowNumber() < 4) {
               bout << sv2.matrix[incdemo][2];
               dem39+=sv2.matrix[incdemo][2];
          }
          else {
               bout << dem39;
          }
          break;
     case DEM_49:
          if (dnf->rowNumber() < 4) {
               bout << sv2.matrix[incdemo][3];
               dem49+=sv2.matrix[incdemo][3];
          }
          else {
               bout << dem49;
          }
          break;
     case DEM_99:
          if (dnf->rowNumber() < 4) {
               bout << sv2.matrix[incdemo][4];
               dem99+=sv2.matrix[incdemo][4];
          }
          else {
               bout << dem99;
          }
          break;
     case DEM_TOTAL:
          switch (incdemo) {
          case 0:
               for (i=0 ; i < NAGEBK ; i++) {
                     tototh+=sv2.matrix[0][i];
               }
               bout << tototh;
               break;
          case 1:
               for (i=0 ; i < NAGEBK ; i++) {
                     totibm+=sv2.matrix[1][i];
               }
               bout << totibm;
               break;
          case 2:
               for (i=0 ; i < NAGEBK ; i++) {
                     totmac+=sv2.matrix[2][i];
               }
               bout << totmac;
               break;
          case 3:
               for (i=0 ; i < NAGEBK ; i++) {
                     totapp+=sv2.matrix[3][i];
               }
               bout << totapp;
               break;
          case 4:
               bout << totibm+totmac+totapp+tototh;
               break;
          }
          break;
     case DNFROWEND:
          if (dnf->rowNumber() == 4) {
               dnf->tableDone();
          }
          break;
     case DEM_MALE:
          bout << sv2.numact-sv2.numfem;
          break;
     case DEM_FEMALE:
          bout << sv2.numfem;
          break;
     case DEM_CORPORATE:
          bout << sv2.numcor;
          break;
     case DEM_ANSI:
          bout << sv2.numans;
          break;
     case DNFEND:
          retval=ACTHDONE;
          break;
     }
     return(retval);
}

ACTHCODE
rsySynthesis::dnf_clsstats()       // Class Statistics
{
     ACTHCODE retval=ACTHMORE;
     LONG val;

     switch (dnf->process()) {
     case DNFBEGIN:
          savclsptr=clshead;
          if (savclsptr->flags&HASCRD && savclsptr->flags&NOCRED) {
               savclsptr=nxtcls(savclsptr);
          }
          if (clshead == NULL) {
               retval=ACTHDONE;
          }
          break;
     case CST_NAME:
          bout << savclsptr->clname;
          break;
     case CST_HRSU:
          bout << (savclsptr->seconds+1800L)/3600L;
          break;
     case CST_AVGDAY:
          bout << (((savclsptr->seconds+1800L)/3600L)*24+dtrack/2)/dtrack;
          break;
     case CST_TOTU:
          bout << savclsptr->users;
          break;
     case CST_AVGMINDAY:
          val=((savclsptr->seconds)*24+dtrack/2)/dtrack;
          val=(val/(savclsptr->users > 0 ? savclsptr->users : 1)+30L)/60L;
          bout << val;
          break;
     case DNFROWEND:
          if ((savclsptr=nxtcls(savclsptr)) == NULL) {
               dnf->tableDone();
          }
          break;
     case DNFEND:
          retval=ACTHDONE;
          break;
     }
     return(retval);
}

ACTHCODE
rsySynthesis::dnf_miscstats()      // Misc (module) statistics
{
     ACTHCODE retval=ACTHMORE;

     switch (dnf->process()) {
     case DNFROWBEGIN:
          if (dnf->rowNumber() >= nmods) {
               dnf->tableDone();
          }
          break;
     case MST_NAME:
          bout << mdstats[dnf->rowNumber()].mdname;
          break;
     case MST_HRSU:
          bout << (mdstats[dnf->rowNumber()].seconds+1800L)/3600L;
          break;
     case MST_CRSU:
          bout << mdstats[dnf->rowNumber()].creds;
          break;
     case MST_CALLS:
          bout << sv2.totcalls;
          break;
     case MST_UPLOADS:
          bout << sv.uplds;
          break;
     case MST_DOWNLOADS:
          bout << sv.dwnlds;
          break;
     case MST_MESSAGES:
          bout << sv.msgtot;
          break;
     case MST_EMAIL:
          bout << sv.emlopn;
          break;
     case MST_FORUMS:
          bout << sv.sigopn;
          break;
     case MST_FREECRED:
          bout << sv2.freepst;
          break;
     case MST_PAIDCRED:
          bout << sv2.paidpst;
          break;
     case DNFEND:
          retval=ACTHDONE;
          break;
     }
     return(retval);
}

VOID
rsySynthesis::about_os(VOID)       // OS specific about information
{
     OSVERSIONINFO versionInfo;
     SYSTEM_INFO systemInfo;

     versionInfo.dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
     GetVersionEx(&versionInfo);
     GetSystemInfo(&systemInfo);
     if (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) {
          bout << spr("Windows NT v%d.%d (Build %d)<br>",
                         versionInfo.dwMajorVersion,
                         versionInfo.dwMinorVersion,
                         versionInfo.dwBuildNumber);
          bout << "Processor Type: ";
          switch(systemInfo.dwOemId) {
          case PROCESSOR_ARCHITECTURE_INTEL:
               bout << "Intel ";
               switch(systemInfo.dwProcessorType) {
               case PROCESSOR_INTEL_386:
                    bout << "80386";
                    break;
               case PROCESSOR_INTEL_486:
                    bout << "80486";
                    break;
               case PROCESSOR_INTEL_PENTIUM:
                    bout << "Pentium";
                    break;
               default:
                    bout << "Unknown Type";
                    break;
               }
               break;
          case PROCESSOR_ARCHITECTURE_MIPS:
               bout << "MIPS";
               break;
          case PROCESSOR_ARCHITECTURE_ALPHA:
               bout << "ALPHA";
               break;
          case PROCESSOR_ARCHITECTURE_PPC:
               bout << "PPC ";
               break;
          case PROCESSOR_ARCHITECTURE_UNKNOWN:
          default:
               bout << "UNKNOWN";
               break;
          }
          bout << spr(" (%d Processor%s)<br>",systemInfo.dwNumberOfProcessors,
                 systemInfo.dwNumberOfProcessors == 1 ? "" : "s");
          bout << "Execution Mode: ";
          bout << spr("NT %s",isRunAsService() ? "Service" : "Application");
     }
     else {
          bout << spr ("Windows 95 v%d.%d (Build %d)<br>",
                         versionInfo.dwMajorVersion,
                         versionInfo.dwMinorVersion,
                         LOWORD(versionInfo.dwBuildNumber));
          bout <<"Processor Type: ";
          bout << "Intel ";
          switch (systemInfo.dwProcessorType) {
          case PROCESSOR_INTEL_386:
               bout << "80386 ";
               break;
          case PROCESSOR_INTEL_486:
               bout << "80486 ";
               break;
          case PROCESSOR_INTEL_PENTIUM:
               bout << "Pentium ";
               break;
          default:
               bout << "Unknown Type ";
               break;
          }
          bout << "(1 Processor)";
     }
}

VOID
acthshomal(VOID)                   // show "monitor all" channel status
{
     CHAR acth_data[INPSIZ], acth_user[UIDSIZ];
     SHORT acth_status;
     SHORT acth_channel;

     setmem(acth_data,sizeof(acth_data),0);
     setmem(acth_user,sizeof(acth_user),0);
     if (status == CRSTG) {
            stzcpy(acth_user,uacoff(usrnum)->userid,UIDSIZ);
     }
     acth_channel=channel[usrnum];
     acth_status=status;
     switch(status) {
     case CRSTG:
          CHAR myput[INPSIZ];
          stzcpy(myput,input,INPSIZ);
          if (myput[0] == '<') {
               myput[0] = '(';
          }
          if (myput[strlen(myput)-1] == '>') {
               myput[strlen(myput)-1] = ')';
          }
          copydata(myput);
          break;
     case 6:
          copydata("(User aborted output)");
          break;
     case 11:
          copydata("(Lost Carrier)");
          break;
     case 13:
          copydata("(Invalid Command)");
          break;
     case 251:
          copydata("(Data Input Buffer Overflow)");
          break;
     case 252:
          copydata("(Echo Output Buffer Overflow)");
          break;
     case 253:
          copydata("(Data Output Buffer Overflow)");
          break;
     case 254:
          copydata("(Status Input Buffer Overflow)");
          break;
     case 255:
          copydata("(Command Output Buffer Overflow)");
          break;
     default:
          break;
     }
     if (acth_user[0] == '\0') {
          stzcpy(acth_user,"*",UIDSIZ);
     }
     if (acth_data[0] == '\0') {
          stzcpy(acth_data,"*",INPSIZ);
     }
     RemHdl temphdl;
     temphdl.PutObj(acth_user,acth_data,acth_channel,acth_status);
     if (temphdl.TotObj() > 60) {
          temphdl.CullObj();
     }
     (*oldshomal)();
}

VOID
rsySynthesis::switchsnd(           // Handle computer type
SHORT field,
SHORT val1,
SHORT val2,
SHORT val3,
SHORT val4)
{
     CHAR *comparr[4]=
          {"None of the above",
           "IBM PC or compatible",
           "Apple Macintosh",
           "Apple other than Macintosh"};

     switch(field) {
     case 1:
         bout << comparr[val1];
         break;
     case 2:
         bout << comparr[val2];
         break;
     case 3:
         bout << comparr[val3];
         break;
     case 0:
         bout << comparr[val4];
         break;
     }
}

GBOOL
rsySynthesis::proceedAccPost(      // Make account modifications
struct usracc *uptr)
{
     if (!indnf) {
          movmem(uptr,&tempacc,sizeof(struct usracc));
          handlecomp(uptr);         // These can't fail because
          handlesex();              // they are either radio button
          handleed();               // or drop-down select or checkbox
          handlelang(uptr->userid);
          handleflags();
          ses->param("NAM_NAME",tempacc.usrnam,sizeof(tempacc.usrnam));
          ses->param("NAM_ADDR1", tempacc.usrad1,sizeof(tempacc.usrad1));
          ses->param("NAM_ADDR2",tempacc.usrad2,sizeof(tempacc.usrad2));
          ses->param("NAM_ADDR3",tempacc.usrad3,sizeof(tempacc.usrad3));
          ses->param("NAM_ADDR4",tempacc.usrad4,sizeof(tempacc.usrad4));
          ses->param("NAM_PHONE",tempacc.usrpho,sizeof(tempacc.usrpho));
          ses->param("NAM_PSW",tempacc.psword,sizeof(tempacc.psword));
          ses->param("NAM_BORN",tempBday,sizeof(tempBday));

          if ((!sameas(tempacc.usrnam,uptr->usrnam) && !okName())
           || (!sameas(tempacc.usrad1,uptr->usrad1) && !okCompany())
           || (!sameas(tempacc.usrad2,uptr->usrad2) && !okAddr1())
           || (!sameas(tempacc.usrad3,uptr->usrad3) && !okAddr2())
           || (!sameas(tempacc.usrad4,uptr->usrad4) && !okCountry())
           || (!sameas(tempacc.usrpho,uptr->usrpho) && !okPhone())
           || (!sameas(tempacc.psword,uptr->psword) && !okUidPsw())
           || !okBday() || !okcollin() || !okscnbrk())
          {
               return(FALSE);
          }
          if (!onsysn(uptr->userid,1)) {
               uptr=&tempacc;
               handleclass(uptr);
               offLineSave(uptr);
          }
          else {
               movmem(&tempacc,uptr,sizeof(struct usracc));
               handleclass(uptr);
          }
          ::stlcpy(uaccext.userid,uptr->userid,UIDSIZ);
          ses->param("NAM_PSWHINT",uaccext.pwdhint,HINTSIZ);
          ses->param("NAM_ALTEMAIL",uaccext.alteml,ALTEMLSIZ);
          ::dfaSetBlk(::dfaUserExt);
          if (::dfaAcqEQ(NULL,uptr->userid,0)) {
               ::dfaUpdate(&uaccext);
          }
          else {
               ::dfaInsert(&uaccext);
          }
          ::dfaRstBlk();
     }
     return(TRUE);
}

VOID
rsySynthesis::proceedAccOp(        // Process Access Options
struct usracc *uptr)
{
     GBOOL changes=FALSE;
     SHORT i;

     CHAR opbuf[2];
     INT opdiv,opmod;
     for (i=0 ; i <= NUMROPTS ; i++) {
          ses->param(AccOps[i].opname,opbuf,sizeof(opbuf));
          opdiv=AccOps[i].op>>4;
          opmod=AccOps[i].op%16;
          if (opbuf[0] != '\0' && !checkAxs(uptr,AccOps[i].op)) {
               changes=TRUE;
               uptr->access[opdiv]|=(1<<opmod);
               if (AccOps[i].op == 99) {
                    uptr->flags|=HASMST;
               }
          }
          else if (opbuf[0] == '\0' && checkAxs(uptr,AccOps[i].op)) {
               changes=TRUE;
               uptr->access[opdiv]&=~(1<<opmod);
               if (AccOps[i].op == 99) {
                    uptr->flags&~HASMST;
               }
          }
     }
     if (!onsysn(uptr->userid,1)) {
          offLineSave(uptr);
     }
     if (changes) {
          bout << "The changes were accepted.";
          bout << "  Reselect the 'Remote' button to verify changes.";
     }
     else {
          bout << "No changes were made!";
     }
}

VOID
rsySynthesis::handlecomp(          // handle computer type
struct usracc *uptr)
{
     CHAR compbuf[2];
     USHORT ibm, app, appoth, none;

     ses->param("NAM_COMPUTER",compbuf,sizeof(compbuf)+1);
     switch(uptr->systyp) {
     case 1:
         ibm=1;
         app=2;
         appoth=3;
         none=0;
         break;
     case 2:
         app=1;
         appoth=2;
         none=3;
         ibm=0;
         break;
     case 3:
         appoth=1;
         none=2;
         ibm=3;
         app=0;
         break;
     case 0:
         none=1;
         ibm=2;
         app=3;
         appoth=0;
         break;
     }
     tempacc.systyp=0;
     if ((atoi(compbuf)) == none) {
           tempacc.systyp=0;
     }
     if ((atoi(compbuf)) == ibm) {
           tempacc.systyp=1;
     }
     if ((atoi(compbuf)) == app) {
           tempacc.systyp=2;
     }
     if ((atoi(compbuf)) == appoth) {
           tempacc.systyp=3;
     }
}

VOID
rsySynthesis::handlesex()          // handle sex field
{
     CHAR sexbuf[2];
     ses->param("NAM_SEX",sexbuf,sizeof(sexbuf));
     sexbuf[0]=toupper(sexbuf[0]);
     if (sexbuf[0] == 'M' || sexbuf[0] == 'F') {
          tempacc.sex=sexbuf[0];
     }
}

VOID
rsySynthesis::handleed()           // handle the editor field
{
     CHAR ed[2];
     ses->param("NAM_DEFED",ed,sizeof(ed));
     toupper(ed[0]);
     if (ed[0] == 'F') {
          tempacc.usrprf&=~PRFLIN;
     }
     else {
          tempacc.usrprf|=PRFLIN;
     }
}

VOID
rsySynthesis::handleclass(         // Handle switching class
struct usracc *uptr)
{
     CHAR clsbuf[KEYLEN];

     ses->param("NAM_CLASS",clsbuf,KEYLEN);
     if (!sameas(clsbuf,uptr->curcls) && fndcls(clsbuf) != NULL) {
          swtcls(uptr,1,clsbuf,3,0);
     }
}

GBOOL
rsySynthesis::okName()             // check name form entry
{
     return(okField(tempacc.usrnam,(namdft == 1 || namdft == 2 ? minuid : 5),
                            NADSIZ,"name"));
}

GBOOL
rsySynthesis::okCompany()          // check company form entry
{
     return(okField(tempacc.usrad1,0,NADSIZ,"company name"));
}

GBOOL
rsySynthesis::okAddr1()            // check address line 1 form entry
{
     return(okField(tempacc.usrad2,5,NADSIZ,"address line 1"));
}

GBOOL
rsySynthesis::okAddr2()            // check address line 2 form entry
{
     return(okField(tempacc.usrad3,5,NADSIZ,"address line 2"));
}

GBOOL
rsySynthesis::okCountry()          // check country form entry
{
     return(okField(tempacc.usrad4,0,NADSIZ,"country"));
}

GBOOL
rsySynthesis::okPhone()            // check phone number form entry
{
     return(okField(tempacc.usrpho,7,PHOSIZ,"phone number"));
}

GBOOL
rsySynthesis::okUidPsw()           // check User-ID and password form entries
{
     GBOOL retval=FALSE;

          if (strlen(tempacc.psword) == 0) {
               bout << "You must choose a password.";
          }
          else if (strlen(tempacc.psword) < minpwd) {
               bout << "Sorry, that password is too short.";
          }
          else if (strlen(tempacc.psword) > PSWSIZ-1) {
               bout << "Sorry, that password is too long.";
          }
          else if (!safpsw && (sameas(tempacc.userid,tempacc.psword)
                            || sameas("PASSWORD",tempacc.psword))) {
               bout << "That would not be a very secure password.";
          }
          else {
               retval=TRUE;
          }
     return(retval);
}

GBOOL
rsySynthesis::okField(             // general purpose form field tester
CHAR *data,                        //   entered data
INT minlen,                        //   minimum length (0=no min)
INT maxlen,                        //   maximum length
CHAR *called)                      //   what this field is called
{
     (*setpfn)(data);
     if (pfnlvl > 1) {
          bout << "Sorry, that " << called << " is not appropriate.";
     }
     else if (strlen(data) < minlen) {
          if (strlen(data) == 0) {
               bout << "You must supply a valid " << called << ".";
          }
          else {
               bout << "Sorry, that " << called << " is too short.";
          }
     }
     else if (strlen(data) > maxlen) {
          bout << "Sorry, that " << called << " is too long.";
     }
     else {
          return(TRUE);
     }
     return(FALSE);
}

GBOOL
rsySynthesis::okcollin()           // Check columns and lines
{
     CHAR collin[3];
     INT cl;
     ses->param("NAM_COLUMNS",collin,sizeof(collin));
     cl=atoi(collin);
     if (cl == tempacc.scnwid) {
          return(TRUE);
     }
     if (cl > 39 && cl < 137) {
           tempacc.scnwid=cl;
     }
     else {
           bout << "Column setting is invalid!  Must be between 40 and 136";
           return(FALSE);
     }
     ses->param("NAM_LINES",collin,sizeof(collin)+1);
     cl=atoi(collin);
     if (cl > 2 && cl < 255) {
           tempacc.scnfse=cl;
           return(TRUE);
     }
     else {
           bout << "Line setting is invalid! Must be between 3 and 254";
           return(FALSE);
     }
}

GBOOL
rsySynthesis::okscnbrk()           // Check screen break setting
{
     CHAR cp[3];
     INT brk;
     ses->param("NAM_SCNBRK",cp,sizeof(cp)+1);
     brk=atoi(cp);
     if (brk == tempacc.scnbrk) {
          return(TRUE);
     }
     if (brk > 2 && brk < 255) {
          tempacc.scnbrk=brk;
          return(TRUE);
     }
     else {
          bout << "Page setting is invalid.  Must be between 3 and 254";
          return(FALSE);
     }
}

GBOOL                              //   TRUE=ok, FALSE=error, explained
rsySynthesis::okBday()             // check birthday form entry
{
     stripb(tempBday);
     if (!sameas(strBirthdate(tempacc.birthd),tempBday)) {
          if (!okbday(tempBday)) {
               bout << "That is not a valid date of birth.  "
                    "Example:  2/5/1959 for February 5th, 1959.";
               return(FALSE);
          }
          stlcpy(tempacc.birthd,tempBday,DATSIZ);
     }
     return(TRUE);
}

VOID
rsySynthesis::handlelang(          // Language form-submittal handler
CHAR *uid)
{
     SHORT i;
     CHAR lang[2];
     CHAR defl[MAXLANG+1][14];

     ses->param("NAM_LANGPREF",lang,sizeof(lang)+1);
     getgen(&gbuf,uid);
     if (atoi(lang) == 0) {
          return;
     }
     for (i=0 ; i <= nlingo ; i++) {
          if (i == 0) {
               if (gbuf.lngnam[0] == '\0') {
                    strcpy(defl[i],"AUTOMATIC");
               }
               else {
                    strcpy(defl[i],gbuf.lngnam);
               }
          }
          else if (!sameas(defl[0],languages[i-1]->name)) {
               strcpy(defl[i],languages[i-1]->name);
          }
          else if (!sameas(defl[0],"AUTOMATIC")) {
               strcpy(defl[i],"AUTOMATIC");
          }
     }
     if (sameas(defl[atoi(lang)],"AUTOMATIC")) {
          gbuf.lngnam[0] = '\0';
     }
     else {
          strcpy(gbuf.lngnam,defl[atoi(lang)]);
     }
     setgen(&gbuf);
}

VOID
rsySynthesis::handleflags()        // Handle setting/negating flags
{
     CHAR flbuf[2];

     if (tacptr->flags&HASMST || checkAxs(tacptr,OPSYSP)) {
          ses->param("NAM_MASTKEY",flbuf,8);
          if (flbuf[0] != '\0') {
               tempacc.flags|=HASMST;
          }
          else {
               tempacc.flags&=~HASMST;
          }
     }
     if (tacptr->flags&HASMST || checkAxs(tacptr,OPSUSP)) {
          ses->param("NAM_SUSPEND",flbuf,8);
          if (flbuf[0] != '\0') {
               tempacc.flags|=SUSPEN;
          }
          else {
               tempacc.flags&=~SUSPEN;
          }
     }
     if (tacptr->flags&HASMST || checkAxs(tacptr,OPDELT)) {
          ses->param("NAM_TAG4KIL",flbuf,8);
          if (flbuf[0] != '\0') {
               tempacc.flags|=DELTAG;
          }
          else {
               tempacc.flags&=~DELTAG;
          }
     }
     if (tacptr->flags&HASMST || checkAxs(tacptr,OPPROT)) {
          ses->param("NAM_PROTECT",flbuf,8);
          if (flbuf[0] != '\0') {
               tempacc.flags|=UNDAXS;
          }
          else {
               tempacc.flags&=~UNDAXS;
          }
     }
}

struct
clstab *
rsySynthesis::nxtcls(              // Grab the next class
struct clstab *from)
{
     struct clstab *ptr=from;

     while (ptr != NULL) {
          ptr=ptr->next;
          if (ptr == NULL || !(ptr->flags&HASCRD && ptr->flags&NOCRED)) {
               break;
          }
     }
     return(ptr);
}

INT
rsySynthesis::checkAxs(            // Does user have access to this rem op?
struct usracc *uptr,
INT op)
{
     if (sameas(uptr->userid,"Sysop")
         || (uptr->access[99>>4]&(1<<99%16) && uptr->flags&HASMST)) {
          return(1);
     }
     return(uptr->access[op>>4]&(1<<(op%16)));
}

VOID
rsySynthesis::offLineSave(          // Save if user is offline
struct usracc *uptr)
{
     dfaSetBlk(accbb);
     if (dfaAcqEQ(NULL,uptr->userid,0)) {
          dfaUpdate(uptr);
     }
     else {
          bout <<  "Unable to find user!";
     }
     dfaRstBlk();
}

CHAR *
rsySynthesis::displayKeys(         // Display a key
CHAR *keyr,                        // The keyring in question (or UID)
INT ring)                          // Is it a keyring?
{
     CHAR *bas,*ptr,keyring[UIDSIZ];
     INT keyinc=0;

     if (ring) {
          keyring[0]=RINGID;
          strcpy(keyring+1,keyr);
          if (!namacls(keyring+1)) {
               bout << "This in not a valid keyring";
               keycnt=-1;
               return(NULL);
          }
     }
     else {
          strcpy(keyring,keyr);
     }
     if (!getlst(keyring,NULL)) {
          bout << "Can't find keyring!";
          keycnt=-1;
          return(NULL);
     }
     ptr=&kysbuf[KLSTOF];
     bas=ptr;
     GBOOL done=FALSE;
     do {
          if (*ptr++ == ' ' || *ptr == '\0') {
               if (*ptr == '\0') {
                    keycnt = -1;
                    return(bas);
               }
               if (keyinc == keycnt) {
                    keycnt++;
                    *(ptr-1) = '\0';
                    return(bas);
               }
               keyinc++;
               bas=ptr;
          }
     } while (!done);
     keycnt=-1;
     return(NULL);
}

ACTHCODE
rsySynthesis::proceedAccpdnf(      // Intermediate Accounting function
struct usracc *uptr)
{
     ACTHCODE retval=ACTHMORE;

     if (dnf == NULL) {
         if (proceedAccPost(uptr)) {
               dnf = new dnfHandler(rsyAccframeMap,bout);
         }
         else {
               retval=ACTHDONE;
         }
     }
     else {
         retval=dnf_accframe(spc2pls(uptr->userid));
     }
     return(retval);
}

ACTHCODE
rsySynthesis::proceedImpkey(       // Import a keyring
struct usracc *uptr)
{
     ACTHCODE retval=ACTHMORE;
     CHAR clsbuf[KEYLEN];

     ses->param("NAM_IMPCLASS",clsbuf,KEYLEN);
     if (dnf == NULL) {
          if (fndcls(clsbuf) != NULL) {
               dnf = new dnfHandler(rsyAcckeyMap,bout);
          }
          else {
               retval=ACTHNOTFND;
          }
     }
     else {
          retval=dnf_acckeys(uptr,clsbuf);
     }
     return(retval);
}

ACTHCODE
rsySynthesis::proceedAddImpkey(    // Add an imported key
struct usracc *uptr)
{
     ACTHCODE retval=ACTHMORE;
     CHAR clsbuf[KEYLEN];
     CHAR keybuf[KEYLEN];

     ses->param("HID_CLS",clsbuf,KEYLEN);
     ses->param("NAM_IMPKEY",keybuf,KEYLEN);
     if (dnf == NULL) {
         if (userHasKey(uptr->userid,keybuf)) {
              bout << "<p align=center>User already has key!";
         }
         else if (!givkey(uptr->userid,keybuf)) {
              bout << "<p align=center>Failed to give key to user.";
         }
         dnf = new dnfHandler(rsyAcckeyMap,bout);
     }
     else {
          retval=dnf_acckeys(uptr,clsbuf);
     }
     return(retval);
}

ACTHCODE
rsySynthesis::proceedAddkey(       // Add a key to an account
struct usracc *uptr)
{
     ACTHCODE retval=ACTHMORE;

     CHAR cls[KEYLEN];
     ses->param("HID_CLS",cls,KEYLEN);
     if (dnf == NULL) {
          CHAR keyadd[KEYLEN];
          ses->param("NAM_ADDKEY",keyadd,KEYLEN);
          if (keyadd[0] != '\0' && keynam(keyadd)) {
                if (userHasKey(uptr->userid,keyadd)) {
                     bout << "<p align=center>User already has key!";
                }
                else if (!givkey(uptr->userid,keyadd)) {
                     bout << "<p align=center>Failed to give key to user.";
                }
          }
          else {
                bout << "<p align=center>Key name is not accepted";
          }
          dnf = new dnfHandler(rsyAcckeyMap,bout);
     }
     else {
          retval=dnf_acckeys(uptr,cls);
     }
     return(retval);
}

ACTHCODE
rsySynthesis::proceedRemovekey(    // Remove a key from account
struct usracc *uptr)
{
     ACTHCODE retval=ACTHMORE;
     CHAR clsbuf[KEYLEN];
     CHAR keybuf[KEYLEN];

     ses->param("HID_CLS",clsbuf,KEYLEN);
     ses->param("NAM_KEYLIST",keybuf,KEYLEN);
     if (dnf == NULL) {
          rmvkey(uptr->userid,keybuf);
          dnf = new dnfHandler(rsyAcckeyMap,bout);
     }
     else {
          retval=dnf_acckeys(uptr,clsbuf);
     }
     return(retval);
}

VOID
rsySynthesis::proceedPostcred(     // Post Credits to account
struct usracc *uptr)
{
     CHAR creds[10];
     CHAR chkbuf[3];
     if (ses->param("NAM_POSTCRED",creds,10) && creds[0] != '\0') {
          if (creds[0] == '-' && alldgs(creds+1)) {
               ;
          }
          else if (!alldgs(creds)) {
               bout << "Invalid credit value!";
               return;
          }
          ses->param("NAM_CREDTYPE",chkbuf,2);
          if (chkbuf[0] == 'P') {
                addcrd(uptr->userid,creds,1);
          }
          else {
                addcrd(uptr->userid,creds,0);
          }
          bout << "Credits have been posted!";
          TrackLog(PSTTRK,0,uptr->usrnam,NULL);
     }
     else {
          bout << "You must specify a credit amount";
     }
}

VOID
rsySynthesis::proceedPostday(      // Post days to account
struct usracc *uptr)
{
    CHAR days[5];
    INT dft;
    GBOOL neg=FALSE;

    if (ses->param("NAM_POSTDAY",days,5) && days[0] != '\0') {
        if (days[0] == '-' && alldgs(days+1)) {
             neg=TRUE;
        }
        else if (!alldgs(days)) {
             bout << "Day amount must be numeric.";
             return;
        }
        if (uptr->daystt == 0) {
              bout << "User already has unlimited days.";
        }
        else {
              savclsptr=fndcls(uptr->curcls);
              dft=savclsptr->dftday;
              if (dft == -1) {
                   bout << "User's current class doesn't expire due to days.";
                   return;
              }
              if (!neg) {
                  if (dft <= uptr->daystt+atoi(days)) {
                       uptr->daystt=dft; // ensure not over top
                       bout << "User's days are set to class maximum.";
                  }
                  else {
                        uptr->daystt+=atoi(days);
                        bout << "Specified days have been posted.";
                  }
              }
              else {
                   CHAR *dayptr=&days[1];
                   if (uptr->daystt-atoi(dayptr) <= 1) {
                       uptr->daystt=1;
                       bout << "User's days are set to class minimum.";
                   }
                   else {
                        uptr->daystt-=atoi(dayptr);
                        bout << "Specified days have been posted.";
                   }
              }
              bout << "<br>Reselect the 'Post' button to "
                      "verify changes.";
              if (!onsysn(uptr->userid,1)) {
                  offLineSave(uptr);
              }
         }
    }
    else {
         bout << "The amount of days specified is invalid.";
    }
}

VOID
rsySynthesis::proceedCopyuser(     // Actually copy the user account
struct usracc *uptr)
{
    CHAR *retstg;
    CHAR newuid[UIDSIZ];
    CHAR newpas[PSWSIZ];
    if (ses->param("NAM_NEWUSER",newuid,UIDSIZ) &&
        ses->param("NAM_NEWPAS",newpas,PSWSIZ) &&
        newuid[0] != '\0' && newpas[0] != '\0') {
        if ((retstg=copyuser(uptr->userid,newuid,newpas,uptr))
            != NULL) {
              bout << retstg;
        }
        else {
              bout << "User successfully copied!";
        }
    }
    else {
         bout << "Invalid information.  Try again.";
    }
}

VOID
rsySynthesis::proceedChanop(       // Complete the channel operation
INT chnum,
SHORT op)
{
     if (usroff(chnum)->usrcls == VACANT && op == HANGUP) {
          bout << "This channel is VACANT!  Can't hangup.";
          return;
     }
     switch(op) {
     case BUSYOUT:
          rsmodes[chnum]=BUSYRS;
          TrackLog(CHPTRK,chnum,"busyout",NULL);
          break;
     case NOANSWER:
          rsmodes[chnum]=NANSRS;
          TrackLog(CHPTRK,chnum,"noanswer",NULL);
          break;
     case NORMALIZE:
          rsmodes[chnum]=NORMRS;
          TrackLog(CHPTRK,chnum,"normal",NULL);
          break;
     case HANGUP:
          btuinj(chnum,RING);
          othuap=uacoff(chnum);
          bout << "Killed user: " << othuap->userid;
          TrackLog(KILTRK,0,othuap->userid,NULL);
          return;
     }
     bout << "Channel Operation successful!";
     kilchn(chnum);
}

VOID
rsySynthesis::secs2StdTime(           // Seconds to std. time
LONG secs)
{
     bout << spr("%2.2d",secs/3600);
     bout << ":";
     bout << spr("%2.2d",(secs%3600)/60);
     bout << ":";
     bout << spr("%2.2d",((secs%3600)%60));
}

GBOOL
rsySynthesis::userHasKey(       // Does the user have this key?
CHAR *uid,
CHAR *key)
{
     CHAR *keyp;


     ASSERT (uid != NULL && key != NULL);
     while (keycnt != -1) {
          keyp=displayKeys(uid,0);
          if (sameas(key,keyp)) {
               keycnt=0;
               return (TRUE);
          }
     }
     keycnt=0;
     return(FALSE);
}

GBOOL
rsySynthesis::isMatch(               // Do we have a match?
CHAR *keyval,
CHAR *fldval,
CHAR *opval)
{
     switch(atoi(fldval)) {
     case 0:
          return(findstg(keyval,uac.userid));
     case 1:
          return(findstg(keyval,uac.usrnam));
     case 2:
          return(findstg(keyval,uac.psword));
     case 3:
          return(findstg(keyval,uac.usrad1));
     case 4:
          return(findstg(keyval,uac.usrad2));
     case 5:
          return(findstg(keyval,uac.usrad3));
     case 6:
          return(findstg(keyval,uac.usrad4));
     case 7:
          return(findstg(keyval,uac.usrpho));
     case 8:
          return(findstg(keyval,sysstg[(SHORT)uac.systyp]));
     case 9:
          return(chknum(keyval,uac.age,atoi(opval)));
     case 10:
          return(toupper(keyval[0]) == uac.sex);
     case 11:
          return(findstg(keyval,uac.curcls));
     case 12:
          return(chkcdt(keyval,uac.totcreds,atoi(opval)));
     case 13:
          return(chkcdt(keyval,uac.totpaid,atoi(opval)));
     case 14:
          return(chkcdt(keyval,uac.creds,atoi(opval)));
     case 15:
          return(chkdte(keyval,uac.credat,atoi(opval)));
     case 16:
          return(chkdte(keyval,uac.usedat,atoi(opval)));
     case 17:
          return(chknum(keyval,uac.daystt,atoi(opval)));
     }
     return(FALSE);
}

GBOOL
rsySynthesis::chkcdt(              // compare database credits to search key
CHAR *keyval,
LONG credits,                      // number of credits to compare with
INT opval)
{
     LONG a;

     a=atol(keyval);
     if ((opval >= 1) && (opval <= 5)) {
          return(glthrv[opval-1]
                 [(credits >= a ? 1 : 0)+(credits > a ? 1 : 0)]);
     }
     return(FALSE);
}

GBOOL
rsySynthesis::chkdte(              // compare database date with search key
CHAR *keyval,                      // dos date format to comare with
LONG date,
INT opval)
{
     INT a;

     a=dcdate(keyval);
     if ((opval >= 1) && (opval <= 5)) {
          return(glthrv[opval-1]
                 [(date >= a ? 1 : 0)+(date > a ? 1 : 0)]);
     }
     return(FALSE);
}

GBOOL
rsySynthesis::chknum(              // compare database number with search key
CHAR *keyval,                      // number to compare with
INT number,
INT opval)
{
     INT a;

     a=atoi(keyval);
     if ((opval >= 1) && (opval <= 5)) {
          return(glthrv[opval-1]
                 [(number >= a ? 1 : 0)+(number > a ? 1 : 0)]);
     }
     return(FALSE);
}

GBOOL
rsySynthesis::strtdel()            // get first filename for delete operation
{
     if (iswild(delspec)) {
          multifil=TRUE;
     }
     else if (isdir(delspec)) {
          stlcat(delspec,"\\*.*",GCMAXPTH);
          multifil=TRUE;
     }
     if (multifil) {
          stzcpy(dfpath,stppath(delspec),GCMAXPTH);
     }
     if (fnd1st(&dirblk,delspec,0)) {
          return(TRUE);
     }
     return(FALSE);
}

GBOOL
rsySynthesis::dodelt()             // handle the cycled deleting process
{
     if (multifil) {
          stzcpy(delspec,dfpath,GCMAXPTH);
          stlcat(delspec,dirblk.ff_name,GCMAXPTH);
     }
     if (unlink(delspec) == 0) {
          dnfcnt++;
          bout << delspec << " deleted!<br>";
     }
     else {
          bout << "Couldn't delete file: " << delspec;
     }
     if (multifil && fndnxt(&dirblk)) {
         return(TRUE);
     }
     return(FALSE);
}

GBOOL
rsySynthesis::strtcpy()            // get first filename for file copy
{
     if ((multifil=iswild(sfname)) != FALSE) {
          if (dfname[strlen(dfname)-1] == '\\') {
               dfname[strlen(dfname)-1]='\0';   // isdir fails if end slash
          }                                     // isdir fails on rootDir
          if (!isdir(dfname)) {
               *(dfname+2)='\0';
               if (!isdrive(spr("%s\\",dfname))) {
                    return(FALSE);
               }
          }
     }
     else if ((multifil=isdir(sfname)) != FALSE) {
          stlcat(sfname,"\\*.*",GCMAXPTH);
          if (dfname[strlen(dfname)-1] == '\\') {
               dfname[strlen(dfname)-1]='\0';    // isdir fails if end slash
          }                                      // isdir fails on rootDir
          if (!isdir(dfname)) {
               *(dfname+2)='\0';
               if (!isdrive(spr("%s\\",dfname))) {
                    return(FALSE);
               }
          }
     }
     else {
          multifil=iswild(fixfil(sfname));
     }
     if (multifil || isdir(dfname) || isdir(spr("%s*.*",dfname)) ||
         isdir(spr("%s\\*.*",dfname))) {
          stzcpy(sfpath,stppath(sfname),GCMAXPTH);
          stzcpy(dfpath,makpath(dfname),GCMAXPTH);
          if (!multifil) {
               stzcpy(dfname,dfpath,GCMAXPTH);
               stlcat(dfname,stpname(sfname),GCMAXPTH);
          }
     }
     if (fnd1st(&dirblk,sfname,0)) {
          return(TRUE);
     }
     return(FALSE);
}

GBOOL
rsySynthesis::prepcpy()            // prepare for cycled copy processing
{
     if (!incpyflg) {
          if (multifil) {
               stzcpy(dfname,dfpath,GCMAXPTH);
               stlcat(dfname,dirblk.ff_name,GCMAXPTH);
               stzcpy(sfname,sfpath,GCMAXPTH);
               stlcat(sfname,dirblk.ff_name,GCMAXPTH);
          }
          if (rsvnam(sfname) || rsvnam(dfname)) {
               sfptr=NULL;
               dfptr=NULL;
               return(FALSE);
          }
          sfptr=fopen(sfname,FOPRB);
          dfptr=fopen(dfname,FOPWB);
          if ((sfptr == NULL) || (dfptr == NULL)) {
               if (sfptr != NULL) {
                    fclose(sfptr);
               }
               if (dfptr != NULL) {
                    fclose(dfptr);
               }
               return(FALSE);
          }
     }
     return(TRUE);
}

GBOOL
rsySynthesis::docopy()             // perform the actual copy process
{
     INT siz;
     LONG tdstamp;
     GBOOL retval=TRUE;

     if (prepcpy()) {
          if ((sfptr != NULL) && (dfptr != NULL)) {
               incpyflg=TRUE;
               siz=fread(cpybuf,1,CPYSIZ,sfptr);
               if (siz > 0) {
                    fwrite(cpybuf,1,siz,dfptr);
               }
               if (siz <= 0) {
                    incpyflg=FALSE;
                    dnfcnt++;
                    bout << sfname << " copied to " << dfname << "<br>";
                    if (sfptr != NULL) {
                         tdstamp=getFileGMT(sfname);
                         fclose(sfptr);
                         sfptr=NULL;
                         setFileGMT(dfname,tdstamp);
                    }
                    if (dfptr != NULL) {
                         fclose(dfptr);
                         dfptr=NULL;
                    }
                    if (multifil) {
                         if (!fndnxt(&dirblk)) {
                              retval=FALSE;
                         }
                    }
                    else {
                         retval=FALSE;
                    }
               }
          }
     }
     else {
          if (multifil) {
               if (!fndnxt(&dirblk)) {
                    retval=FALSE;
               }
          }
          else {
               retval=FALSE;
          }
     }
     return(retval);
}

GBOOL
rsySynthesis::strtfil()            // get first file name for a directory list
{
     CHAR *slptr, *savptr;

     if (!iswild(sfname)) {
          if (isdir(sfname)) {
               stlcat(sfname,"\\*.*",GCMAXPTH);
          }
          else {
               fixfil(sfname);
          }
     }
     savptr=slptr=sfname;
     while ((slptr=strchr(slptr,'\\')) != NULL) {
          slptr++;
          savptr=slptr;
     }
     if (savptr != sfname) {
          stzcpy(dirnam,sfname,savptr-sfname+1);
     }
     else {
          stzcpy(dirnam,".\\",GCMAXPTH);
     }
     if (fnd1st(&dirblk,sfname,FAMDIR)) {
          return(TRUE);
     }
     return(FALSE);
}

VOID
rsySynthesis::processCd(             // Change Directory processing
CHAR const * cwd)
{
     if (strlen(cwd) != 0) {
          if (sameas(cwd,"..")) {
               CHAR * cp=curWrkDirOp(GET,NULL);
               if (cp != NULL) {
                    if (!rootDir(cp)) {
                         stlcat(cp,"..",GCMAXPTH);
                         normDir(cp);
                         curWrkDirOp(UPDATE,cp);
                    }
                    bout << "Current working directory"
                         << " is " << cp << ".";
               }
          }
          else {
               CHAR destpath[GCMAXPTH];
               CHAR wrkpath[GCMAXPTH];
               CHAR *dptr;
               CHAR *getcur;

               if (!sameas(cwd,".")) {
                    getcur = curWrkDirOp(GET,NULL);
                    normspec(destpath,".");
                    chdir(getcur);
                    normspec(wrkpath,cwd);
                    chdir(destpath);
                    dptr=&wrkpath[0];
                    drivelet(dptr);
                    if (isdir(dptr) ||
                         isdir(spr("%s*.*",dptr)) || isdrive(dptr)) {
                         curWrkDirOp(UPDATE,dptr);
                         bout << "Current working directory"
                              << " is " << dptr << ".";
                    }
                    else {
                         bout << "Unable to change to specified"
                              << " directory.";
                    }
               }
               else {
                    bout << "Current working directory is " <<
                            curWrkDirOp(GET,NULL);
               }
          }
     }
     else {
          bout << "You must specify a valid directory";
     }
}

ACTHCODE
rsySynthesis::processDir(            // Directory processing
CHAR const * dir)
{
     ACTHCODE retval=ACTHMORE;
     CHAR *cwd;

     if (dnf == NULL) {
          dir=normspec(dirnam,dir);
          if ((cwd=curWrkDirOp(GET,NULL)) != NULL) {
               if (strlen(dir) == 0) {              // Bout default dir
                     stzcpy(sfname,cwd,GCMAXPTH);
               }
               else {
                    CHAR *dirptr;
                    CHAR tempdir[GCMAXPTH];
                    CHAR tempdir1[GCMAXPTH];
                    stzcpy(tempdir,dir,GCMAXPTH);
                    if (tempdir[strlen(tempdir)-1] != '\\') {
                         stlcat(tempdir,"\\",GCMAXPTH);
                    }
                    stlcat(tempdir,"..",GCMAXPTH);
                    stzcpy(tempdir1,tempdir,GCMAXPTH);
                    dirptr=normDir(tempdir);
                    if (dirptr != NULL && sameas(dirptr,tempdir1)) {
                         stzcpy(sfname,cwd,GCMAXPTH);    //  Handle wildcards
                         stzcat(sfname,dir,GCMAXPTH);    //  etc in cur. dir
                    }
                    else {
                         stzcpy(sfname,dir,GCMAXPTH);     // Copy directory
                    }
               }
          }
          drivelet(sfname);
          if (strtfil()) {
               dnf = new dnfHandler(rsyDirMap,bout);
               TrackLog(DIRTRK,0,sfname,NULL);
          }
          else {
               bout << "Unable to find file(s) or directory";
               retval=ACTHDONE;
          }
     }
     else {
          retval=dnf_dir(DIRLST);
     }
     return(retval);
}

CHAR *
rsySynthesis::normDir(            // Fix up path for our needs
CHAR *fixdir)
{
     CHAR *ptr;
     INT i=0;

     ptr=fixdir;
     ptr=ptr+strlen(fixdir);
     if (*(ptr-1) == '.' && *(ptr-2) == '.' && *(ptr-3) == '\\' &&
         *(ptr-4) != ':') {
           ptr=ptr-4;
           while (*ptr-- != ':' && i++ < strlen(fixdir)-4) {
               if (*ptr == '\\') {
                     *(ptr+1)='\0';
                     break;
               }
           }
     }
     else if(*(ptr-1) == '.' && *(ptr-2) == '\\') {
          *(ptr-1)='\0';
     }
     else if (*(ptr-1) == '.' && *(ptr-2) == '.' && *(ptr-3) == '\\' &&
          *(ptr-4) == ':') {
          return(NULL);
     }
     return(fixdir);
}

VOID
rsySynthesis::processDel(            // Do some Delete processing
CHAR const * wrd)
{
     CHAR *cwd;

     wrd=normalizeFSpec(wrd);
     if ((cwd=curWrkDirOp(GET,NULL)) != NULL) {
          if (strchr(wrd,'\\') == NULL) {
               stzcpy(delspec,cwd,GCMAXPTH);
               stlcat(delspec,wrd,GCMAXPTH);
               drivelet(delspec);
          }
          else {
               stzcpy(delspec,wrd,GCMAXPTH);
          }
     }
}

VOID
rsySynthesis::processType(            // Do the TYPE processing
CHAR const * wrd)
{
    CHAR tempfd[GCMAXPTH];
    CHAR *cwd;

    if ((cwd=curWrkDirOp(GET,NULL)) != NULL) {
          stzcpy(tempfd,cwd,GCMAXPTH);
          stlcat(tempfd,wrd,GCMAXPTH);
          if (isfile(tempfd)) {
               ses->sndfile(tempfd);
               return;
          }
    }
    bout << "Can't type file.";
}

VOID
rsySynthesis::processRd(             // Do the RD processing
CHAR const * wrd)
{
    CHAR tempfd[GCMAXPTH];
    CHAR *cwd;

    if ((cwd=curWrkDirOp(GET,NULL)) != NULL) {
          stzcpy(tempfd,cwd,GCMAXPTH);
          stlcat(tempfd,wrd,GCMAXPTH);
          if (rmdir(tempfd) == 0) {
               bout << tempfd << " directory removed.";
               TrackLog(RDTRK,0,tempfd,NULL);
               return;
          }
          else if (rmdir(wrd) == 0) {
               bout << wrd << " directory removed";
               TrackLog(RDTRK,0,wrd,NULL);
               return;
          }
    }
    bout << "Failed to remove directory.";
}

VOID
rsySynthesis::processMd(             // Do the MD processing
CHAR const * wrd)
{
    CHAR tempfd[GCMAXPTH];
    CHAR *cwd;

    if ((cwd=curWrkDirOp(GET,NULL)) != NULL) {
          stzcpy(tempfd,cwd,GCMAXPTH);
          stlcat(tempfd,wrd,GCMAXPTH);
          if (mkdir(tempfd) == 0) {
               bout << tempfd << " directory created!";
               TrackLog(MDTRK,0,tempfd,NULL);
               return;
          }
          else if (mkdir(wrd) == 0) {
               bout << wrd << " directory created!";
               TrackLog(MDTRK,0,wrd,NULL);
               return;
          }
    }
    bout << "Failed to remove directory.";
}

GBOOL
rsySynthesis::processCopy(            // Do some copy work
CHAR const * op,
GBOOL sd)
{
    CHAR *cwd;

    if ((cwd=curWrkDirOp(GET,NULL)) != NULL) {
         CHAR *dirptr;
         CHAR tempdir[GCMAXPTH];
         CHAR tempdir1[GCMAXPTH];
         stzcpy(tempdir,op,GCMAXPTH);
         if (tempdir[strlen(tempdir)-1] != '\\') {
               stlcat(tempdir,"\\",GCMAXPTH);
         }
         stlcat(tempdir,"..",GCMAXPTH);
         stzcpy(tempdir1,tempdir,GCMAXPTH);
         dirptr=normDir(tempdir);
         if (dirptr != NULL && sameas(dirptr,tempdir1)) {
               switch (sd) {
               case 0:
                    stzcpy(sfname,cwd,GCMAXPTH);   //  Handle wildcards
                    stzcat(sfname,op,GCMAXPTH);    //  etc in cur. dir
                    drivelet(sfname);
                    break;
               case 1:
                    stzcpy(dfname,cwd,GCMAXPTH);   //  Handle wildcards
                    stzcat(dfname,op,GCMAXPTH);    //  etc in cur. dir
                    drivelet(dfname);
                    break;
               }
         }
         else {
               switch (sd) {
               case 0:
                    stzcpy(sfname,op,GCMAXPTH);     // Copy directory
                    drivelet(sfname);
                    break;
               case 1:
                    stzcpy(dfname,op,GCMAXPTH);
                    drivelet(dfname);
                    break;
               }
         }
         return(TRUE);
    }
    return(FALSE);
}

GBOOL
rsySynthesis::processRename(             // Do the rename work
CHAR const * wrd,
CHAR const * nxtwrd)
{
    CHAR tempfd[GCMAXPTH];
    CHAR renfd[GCMAXPTH];
    CHAR *cwd;
    CHAR tempwrd[GCMAXPTH];

    stzcpy(tempwrd,wrd,GCMAXPTH);
    if ((cwd=curWrkDirOp(GET,NULL)) != NULL) {
          if (isfile(wrd)) {
               stzcpy(renfd,nxtwrd,GCMAXPTH);
               if (strchr(renfd,'\\') == NULL) {
                    stzcpy(renfd,cwd,GCMAXPTH);
                    stlcat(renfd,nxtwrd,GCMAXPTH);
               }
               if (rename(wrd,renfd) == 0) {
                    bout << wrd << " renamed to " << renfd;
                    TrackLog(RENTRK,0,wrd,renfd);
                    return(TRUE);
               }
          }
          else {
               stzcpy(tempfd,cwd,GCMAXPTH);
               stlcat(tempfd,wrd,GCMAXPTH);
               stzcpy(renfd,nxtwrd,GCMAXPTH);
               if (strchr(nxtwrd,'\\') == NULL) {
                    stzcpy(renfd,cwd,GCMAXPTH);
                    stlcat(renfd,nxtwrd,GCMAXPTH);
               }
               if (rename(tempfd,renfd) == 0) {
                    bout << tempfd << " renamed to " << renfd;
                    TrackLog(RENTRK,0,tempfd,renfd);
                    return(TRUE);
               }
          }
    }
    return(FALSE);
}

VOID
rsySynthesis::setCurWrkDir()            // Set the current CWD
{
     if (curWrkDirOp(GET,NULL) == NULL) {
          CHAR cwd[GCMAXPTH];
          getcwd(cwd,GCMAXPTH);
          curWrkDirOp(PUT,cwd);
     }
}

GBOOL
rsySynthesis::isdrive(             // Is this a valid drive?
CHAR *drv)
{
     INT i;
     CHAR cwd[GCMAXPTH];

     getcwd(cwd,GCMAXPTH);
     for (i=1 ; i < 26 ; i++) {
          if (sameas(drvs[i-1],drv)) {
               if(_chdrive(i) == 0) {
                   chdir(cwd);
                   return(TRUE);
               }
               chdir(cwd);
               break;
          }
     }
     return(FALSE);
}

CHAR *
rsySynthesis::curWrkDirOp(            // CWD Object Operation Handler
SHORT optype,
CHAR *cwd)
{
     RemHdl tmphdl;
     CHAR *wd=NULL;

     switch (optype) {
     case PUT:
          if (cwd[strlen(cwd)-1] != '\\') {
               stlcat(cwd,"\\",GCMAXPTH);  // ensure backslash on init. cwd
          }
          tmphdl.PutCwd((CHAR *)usr->userid(),cwd);
          break;
     case UPDATE:
          drivelet(cwd);              // Ensure drive letter
          normspec(dirnam,cwd);
          cwd = dirnam;
          if (cwd[strlen(cwd)-1] != '\\') {
               stlcat(cwd,"\\",GCMAXPTH);  // ensure backslash on upd cwd
          }
          tmphdl.UpdCwd((CHAR *)usr->userid(),cwd);
          break;
     case GET:
          wd=tmphdl.GetCwd((CHAR *)usr->userid());
          break;
     }
     return(wd);
}

GBOOL
rsySynthesis::rootDir(             // Is this a root dir?
CHAR const * cwd)
{
     return(strlen(cwd) == 3);
}

VOID
rsySynthesis::drivelet(            // Make sure drive letter is on path
CHAR *cwd)
{
     CHAR *iniptr;
     iniptr=cwd;
     if (*(cwd+1) != ':') {
           INT trval;
           if (*(cwd+2) == '\\') {
                trval=2;
           }
           else {
                trval=3;
           }
           INT len=strlen(cwd);
           INT i=0;
           if (len+trval <= GCMAXPTH) {
               cwd=cwd+len;
               while (i < len+trval) {
                     *(cwd+trval)=*cwd;
                     cwd--;
                     i++;
               }
               CHAR *drv;
               drv=curWrkDirOp(GET,NULL);
               if (trval == 2) {
                    *iniptr=*drv;
                    *(iniptr+1)=*(drv+1);
               }
               else {
                    *iniptr=*drv;
                    *(iniptr+1)=*(drv+1);
                    *(iniptr+2)=*(drv+2);
               }
           }
     }
}

VOID
rsyAgent::init_rsm()               // Do some initializing
{
     if (sv2.lstzer == 0) {
          sv2.lstzer=today();
          track=1;
     }
     else {
          track=cofdat(today())-cofdat(sv2.lstzer);
          track=(track == 0 ? 1 : track);
     }
     setmbk(rsymb);
     rsmahkey=stgopt(RSMAHKEY);    // get AH access key
     rstmbk();
}

GBOOL
rsySynthesis::HandleSubmitTime()   // Analyze time options
{
    CHAR chkbuf[3];
    CHAR minsbuf[5];
    CHAR msgbuf[XMSGSZ];
    cls.flags|=KCKOFF;             // set Kick-off initially (default)
    if (ses->param("NAM_CHKMINPERSESS",chkbuf,3) &&
        chkbuf[0] != '\0') {
         cls.limcal=-1;   // set to unlimited
    }
    else if (ses->param("NAM_MINPERSESS",minsbuf,5) && minsbuf[0] != '\0'
             && alldgs(minsbuf) && atoi(minsbuf) >= -1 &&
             atoi(minsbuf) <= 1440) {
         cls.limcal=atoi(minsbuf);
    }
    else {
         bout << "Call limit is invalid.  Maxmium is 1440.  Minimum is 0.";
         return(FALSE);
    }
    // Check limit per day
    if (ses->param("NAM_CHKMINPERDAY",chkbuf,3) &&
        chkbuf[0] != '\0') {
         cls.limday=-1;   // set to unlimited
         // If there is no daily limit, then we force users to log off
         // automatically, so set KCKOFF flag
         cls.flags&=~CLSCHG;
         cls.nxtcls[DOUTTIM][0]='\0';
    }
    else if (ses->param("NAM_MINPERDAY",minsbuf,5) && minsbuf[0] != '\0'
             && alldgs(minsbuf) && atoi(minsbuf) >= -1 &&
             atoi(minsbuf) <= 1440) {
         cls.limday=atoi(minsbuf);
         // Since we have a daily limit, check to see if user
         // specified a class change
         CHAR dlimit[2];
         if (ses->param("NAM_DLIMITACT",dlimit,2) && dlimit[0] != '4') {
              // they have selected a class to switch to.  Get
              // Class they have selected and class trans message
              CHAR clsbuf[KEYLEN];
              if (ses->param("SEL_DAILYSWITCH",clsbuf,KEYLEN) &&
                  (fndcls(clsbuf) != NULL || sameas(clsbuf,"DELETE_ACCOUNT"))) { // valid switch class
                   stlcpy(cls.nxtcls[DOUTTIM],clsbuf,sizeof(cls.nxtcls[DOUTTIM]));
                   cls.flags|=CLSCHG; // Set class change flag
                   cls.flags&=~KCKOFF;
              }
              if (ses->param("TXT_CLASSTRANS",msgbuf,XMSGSZ) &&
                  msgbuf[0] != '\0') {   // there is a class trans message
                   stlcpy(cls.msgs[0],StpBGWhite(StpNDWhite(msgbuf)),XMSGSZ);
              }
              else {
                   setmem(cls.msgs[0],XMSGSZ,0);
              }
         }
    }
    else {
         bout << "Daily limit is invalid. Maxmium is 1440.  Minimum is 0.";
         return(FALSE);
    }
    return(TRUE);
}

GBOOL
rsySynthesis::HandleSubmitCredit() // Analyze Credit options
{
    CHAR debtbuf[10];
    CHAR chkbuf[3];
    debtbuf[0]='\0';
    // negate existing flags
    cls.flags&=~(REPDBT|FSTMTH|HITLMT|MONDAY|NUMDAY);
    if (ses->param("NAM_CREDSTATUS",chkbuf,3) && chkbuf[0] == '2') {
         cls.dbtlmt=0;
         cls.flags&=~CRDXMT;
    }
    else if (chkbuf[0] == '1') {
         // Check if they selected unlimited
         if (ses->param("NAM_CHKDEBTLIMIT",chkbuf,3) && chkbuf[0] != '\0') {
              cls.dbtlmt=-1; // set unlimited
              cls.flags&=~CRDXMT;
         }
         else if (ses->param("NAM_DEBTLIMIT",debtbuf,10) && alldgs(debtbuf) &&
                  atol(debtbuf) >= 0 && atol(debtbuf) <= 9999999L) {
              cls.dbtlmt=atol(debtbuf); // set to valid debt limit value
              cls.flags&=~CRDXMT;
         }
         else {
              bout << "You've selected debt accrual, but haven't specified" <<
                      " an appropriate debt limit.  Try again.";
              return(FALSE);
         }
         // Check on Report Generation options
         if (ses->param("NAM_GENREP",chkbuf,3) && chkbuf[0] != '\0') {
              CHAR forgivebuf[10];
              cls.flags|=REPDBT; // set flag
              // check which type of reporting they want
              if (ses->param("NAM_RADGENREP",chkbuf,3) && chkbuf[0] != '\0') {
                   switch (atoi(chkbuf)) {
                   case 0:
                        cls.flags|=FSTMTH;
                        break;
                   case 1:
                        if (debtbuf[0] == '\0') {
                            bout << "You can't generate a report based"
                                    " on debt limit if debt is unlimited!";
                            return(FALSE);
                        }
                        cls.flags|=HITLMT;
                        break;
                   case 2:
                        cls.flags|=MONDAY;
                        break;
                   case 3:
                        cls.flags|=NUMDAY;
                        // They've selected a number of days.  Check
                        // number of days value
                        if (ses->param("NAM_REPDAYS",forgivebuf,10) &&
                            forgivebuf[0] != '\0' && alldgs(forgivebuf)
                            && atoi(forgivebuf) <= GCMAXSHORT) {
                             cls.fgvday=atoi(forgivebuf);
                        }
                        else {
                             bout << "You've specified an invalid number "
                                     "of days to generate reports on.  Try "
                                     "again.";
                             return(FALSE);
                        }
                        break;
                   default:
                        cls.flags|=FSTMTH;
                   }
              }
              else {
                   bout  << "You've selected report generation, but haven't "
                         << "selected which type of report.  Try again.";
                   return(FALSE);
              }
         }
         else {
             cls.flags&=~REPDBT;
         }
    }
    else {
         cls.flags|=CRDXMT;  // set credit exempt flag
         cls.dbtlmt=0;
    }
    return(TRUE);
}

GBOOL
rsySynthesis::HandleSubmitClass()  // Analyze Class options
{
     CHAR numbuf[5];
     CHAR clsbuf[KEYLEN];
     CHAR msgbuf[XMSGSZ];
     CHAR chkbuf[3];

     ses->param("NAM_CREDSWITCH",chkbuf,3);
     if (chkbuf[0] == '0') {
          // expire when out of credits
          if (!(cls.flags&CRDXMT)) {
               cls.flags|=NOCRED;
          }
          else {
               bout << "This class is credit exempt!  You cannot switch"
                       " classes based on credits.";
               return(FALSE);
          }
          if (ses->param("SEL_REACHLIM",clsbuf,KEYLEN) &&
                   (fndcls(clsbuf) != NULL || sameas(clsbuf,"DELETE_ACCOUNT"))) {
               stlcpy(cls.nxtcls[DCREDIT],clsbuf,sizeof(cls.nxtcls[DCREDIT]));
          }
          else {
               bout << "You've specified an invalid class.";
               return(FALSE);
          }
     }
     else {
          cls.flags&=~NOCRED;  // negate flag
     }

     if (chkbuf[0] == '1') {
          // expire when credits are paid
          if (!(cls.flags&CRDXMT)) {
               cls.flags|=HASCRD;
          }
          else {
          bout << "This class is credit exempt!  You cannot switch"
                  " classes based on credits.";
                  return(FALSE);
          }
          if (ses->param("SEL_REACHLIM",clsbuf,KEYLEN) &&
              (fndcls(clsbuf) != NULL || sameas(clsbuf,"DELETE_ACCOUNT"))) {
               stlcpy(cls.nxtcls[DCREDIT],clsbuf,sizeof(cls.nxtcls[DCREDIT]));
          }
          else {
               bout << "You've specified an invalid class.";
               return(FALSE);
          }
     }
     else {
          cls.flags&=~HASCRD; // negate flag
     }

     if (chkbuf[0] == '2') {
          // expire when debt limit is reached only allowable
          // if 1) this Class allows debt accrual (and not exempt from cr charges)
          // if 2) NOCRED and HASCRD are not set
          if (cls.flags&CRDXMT) {
               bout << "You can't switch classes based on credits.  This"
                       " class is set for credit exemption.";
               return(FALSE);
          }
          cls.flags|=DBTLMT;
          if (cls.flags&HASCRD || cls.flags&NOCRED) {
               bout << "You cannot switch to another class due to debt " <<
                       "accrual in addition to switching due to credit " <<
                       "amounts.";
               return(FALSE);
          }
          else if (cls.dbtlmt == 0 || cls.dbtlmt == -1) {
               bout << "This class is not currently set to accrue debt or"
                       " is set for unlimited debt; neither setting coincides"
                       " with switching classes based on a debt limit.";
               return(FALSE);
          }
          else if (ses->param("SEL_REACHLIM",clsbuf,KEYLEN) &&
                   (fndcls(clsbuf) != NULL || sameas(clsbuf,"DELETE_ACCOUNT"))) {
               stlcpy(cls.nxtcls[DCREDIT],clsbuf,sizeof(cls.nxtcls[DCREDIT]));
          }
          else {
               bout << "You've specified an invalid class.";
               return(FALSE);
          }
     }
     else {
          cls.flags&=~DBTLMT;
     }

     if (chkbuf[0] == '3') {
          cls.flags&=~(NOCRED|HASCRD|DBTLMT);
          cls.nxtcls[DCREDIT][0]='\0';
          setmem(cls.nxtcls[DCREDIT],sizeof(cls.nxtcls[DCREDIT]),0);
     }

     // Check for switch class due to idle
     if (ses->param("NAM_CHKLOGGEDIN",chkbuf,3) && chkbuf[0] !='\0') {
          cls.flags|=IDLEXP;   // set idle expiration
          ses->param("NAM_DAYSNOLOG",numbuf,5);
          if (numbuf[0] != '\0' && alldgs(numbuf) &&
              atoi(numbuf) <= GCMAXSHORT) {
              cls.idlday=atoi(numbuf); // set to number of days
               if (ses->param("SEL_SWTCLSDAYS",clsbuf,KEYLEN) &&
                   (fndcls(clsbuf) != NULL || sameas(clsbuf,"DELETE_ACCOUNT"))) {
                    stlcpy(cls.nxtcls[DLOAFER],clsbuf,sizeof(cls.nxtcls[DLOAFER]));
               }
               else {
                    bout << "You must specify a valid class to switch to!";
                    return(FALSE);
               }
          }
          else {
               bout << "You've specified an invalid amount of idle " <<
                       "expiration days.  Try again.";
               return(FALSE);
          }
     }
     else {
          cls.idlday=-1; // doesn't expire via idle
          cls.flags&=~IDLEXP;
          cls.nxtcls[DLOAFER][0]='\0';
     }
     // Check for switch class due to number of days
     if (ses->param("NAM_CHKDAYSIN",chkbuf,3) && chkbuf[0] !='\0') {
          cls.flags|=DAYEXP;   // set day number expire
          ses->param("NAM_DAYSIN",numbuf,5);
          if (numbuf[0] != '\0' && alldgs(numbuf) &&
              atoi(numbuf) <= GCMAXSHORT) {
              cls.dftday=atoi(numbuf); // set to number of days
               if (ses->param("SEL_SWTCLSDAYSIN",clsbuf,KEYLEN) &&
                   (fndcls(clsbuf) != NULL || sameas(clsbuf,"DELETE_ACCOUNT"))) {
                    stlcpy(cls.nxtcls[DEXPIRE],clsbuf,sizeof(cls.nxtcls[DEXPIRE]));
               }
               else {
                    bout << "You must specify a valid class to switch to!";
                    return(FALSE);
               }
          }
          else {
               bout << "You've specified an invalid amount of " <<
                       "expiration days.  Try again.";
               return(FALSE);
          }
     }
     else {
          cls.dftday=-1; // doesn't expire
          cls.flags&=~DAYEXP;
          cls.nxtcls[DEXPIRE][0]='\0';
     }
     ses->param("TXT_CLASSTRANS1",msgbuf,XMSGSZ);
     if (msgbuf[0] != '\0' && (cls.flags&NOCRED || cls.flags&HASCRD ||
         cls.flags&DBTLMT || cls.flags&IDLEXP || cls.flags&DAYEXP)) {
          stlcpy(cls.msgs[1],StpBGWhite(StpNDWhite(msgbuf)),XMSGSZ);
     }
     else if ((!(cls.flags&NOCRED) && !(cls.flags&HASCRD) &&
              !(cls.flags&DBTLMT) && !(cls.flags&IDLEXP) &&
              !(cls.flags&DAYEXP)) || msgbuf[0] == '\0') {
          setmem(cls.msgs[1],XMSGSZ,0);
     }
     return(TRUE);
}

GBOOL
rsySynthesis::SubmitClassVerify()  // Validify Class info
{
     return(HandleSubmitTime() && HandleSubmitCredit() &&
            HandleSubmitClass());
}

GBOOL
rsySynthesis::HandleSubmitKeys()   // Add/Remove Keys from class
{
     CHAR keybuf[100];
     CHAR *curwrd;
     setmem(keybuf,sizeof(keybuf),0);
     if (ses->param("NAM_ADDKEY",keybuf,100) && keybuf[0] != '\0') {
          curwrd=firstwd(keybuf);
          if (*curwrd != '\0') {
               if (!givkey(spr("&%s",cls.clname),strupr(curwrd))) {
                    bout << "Unable to give key " << curwrd;
                    return(FALSE);
               }
               curwrd=nextwd();
               while (*curwrd != '\0') {
                    if (!givkey(spr("&%s",cls.clname),strupr(curwrd))) {
                         bout << "Unable to give key " << curwrd <<
                                 ".  Preceeding key(s) are accepted";
                         return(FALSE);
                    }
                    curwrd=nextwd();
               }
          }
     }
     if (ses->param("NAM_REMVKEY",keybuf,100) && keybuf[0] != '\0') {
          curwrd=firstwd(keybuf);
          if (*curwrd != '\0') {
               rmvkey(strupr(spr("&%s",cls.clname)),curwrd);
               curwrd=nextwd();
               while (*curwrd !='\0') {
                    rmvkey(strupr(spr("&%s",cls.clname)),curwrd);
                    curwrd=nextwd();
               }
          }
     }
     return(TRUE);
}

VOID
rsySynthesis::TrackLog(            // Operation tracking
ULONG logval,
INT argi,
CHAR const * arg1,
CHAR const * arg2)
{
     switch(logval) {
     case CHPTRK:
          if (trkflgs&CHPTRK) {
              shocst("REMOTE CHANNEL OPERATION",
                     "[%-33s]  Channel: %-2x  Op: %-9s",
                     usaptr->userid,argi,arg1);
          }
          break;
     case KILTRK:
          if (trkflgs&KILTRK) {
              shocst("USER KICKED OFF OF SERVER",
                     "[%-24s] User kicked: %-23s",
                     usaptr->userid,arg1);
          }
          break;
     case EVTTRK:
          if (trkflgs&EVTTRK) {
              shocst("REMOTE CLEANUP/EVENT SHUTDOWN",
                     "[%-23s]  Op: %-25s",usaptr->userid,
                     ((argi < 1) ? "SYSTEM CLEANUP" :
                     spr("TIMED EVENT %d",argi)));
          }
          break;
     case KSYTRK:
          if (trkflgs&KSYTRK) {
              shocst("REMOTE SHUTDOWN INITIATED",
                      "[%-35s]",usaptr->userid);
          }
          break;
     case PSTTRK:
          if (trkflgs&PSTTRK) {
              shocst("REMOTE POSTING OF CREDITS",
                    "[%-23s]  Posted to: %-23s",usaptr->userid,
                    arg1);
          }
          break;
     case LOGTRK:
          if (trkflgs&LOGTRK) {
              shocst("SYSTEM LOGON MESSAGE CHANGED",
                    "[%-35s]",usaptr->userid);
          }
          break;
     case MSGTRK:
          if (trkflgs&MSGTRK) {
              shocst("REMOTE MESSAGE SENT TO USER",
                    "[%-23s]  Message to: %-23s",
                    usaptr->userid,arg1);
          }
          break;
     case AMSTRK:
          if (trkflgs&AMSTRK) {
              shocst("REMOTE MESSAGE SENT TO ALL",
                     "[%-35s]",usaptr->userid);
          }
          break;
     case DIRTRK:
          if (trkflgs&DIRTRK) {
              shocst("REMOTE DIR COMMAND USED",
                      "[%-23s]  arg: %-29s",usaptr->userid,
                      arg1);
          }
          break;
     case CPYTRK:
          if (trkflgs&CPYTRK) {
              shocst("REMOTE COPY COMMAND USED",
                    "[%-15s] arg1: %-15s arg2: %-15s",
                    usaptr->userid,arg1,arg2);
          }
          break;
     case DELTRK:
          if (trkflgs&DELTRK) {
              shocst("REMOTE DEL COMMAND USED",
                    "[%-23s] arg: %-20s",usaptr->userid,
                    arg1);
          }
          break;
     case TYPTRK:
          if (trkflgs&TYPTRK) {
              shocst("REMOTE TYPE COMMAND USED",
                      "[%-23s] arg: %-20s",usaptr->userid,
                      arg1);
          }
          break;
     case MDTRK:
          if (trkflgs&MDTRK) {
              shocst("REMOTE MD COMMAND USED",
                      "[%-23s] arg: %-20s",usaptr->userid,
                      arg1);
          }
          break;
     case RDTRK:
          if (trkflgs&RDTRK) {
              shocst("REMOTE RD COMMAND USED",
                      "[%-23s] arg: %-20s",usaptr->userid,
                      arg1);
          }
          break;
     case RENTRK:
          if (trkflgs&RENTRK) {
              shocst("REMOTE RENAME COMMAND USED",
                        "[%-15s] arg1: %-15s arg2: %-15s",
                        usaptr->userid,arg1,arg2);
          }
          break;
     case GETTRK:
          if (trkflgs&GETTRK) {
              shocst("REMOTE GET COMMAND USED",
                      "[%-23s] arg: %-20s",usaptr->userid,
                      arg1);
              }
          break;
     }
}

VOID
rsySynthesis::settacptr()          // Set temporary account pointer
{
     if (onsysn((CHAR *)usr->userid(),TRUE)) {
          tacptr=uacoff(othusn);
     }
     else {
          dfaSetBlk(accbb);
          dfaAcqEQ(&othacc,(CHAR *)usr->userid(),0);
          tacptr=&othacc;
          dfaRstBlk();
     }
}

CHAR *
rsySynthesis::StpNDWhite(          // Strip end white space
CHAR *str)
{
     CHAR *ptr;

     ptr=str+(strlen(str)-1);
     while (ptr >= str) {
          if (*ptr != ' ' && *ptr != '\n' && *ptr != '\r' && *ptr != 0x0D) {
               *(ptr+1)='\0';
               break;
          }
          ptr--;
     }
     return(str);
}

CHAR *
rsySynthesis::StpBGWhite(          // Strip beginning white space
CHAR *str)
{
     CHAR *ptr;

     ptr=str;

     while (*ptr == ' ' || *ptr == '\n' || *ptr == '\r' || *ptr == 0x0D) {
          ptr++;
     }
     return(ptr);
}

VOID
rsySynthesis::getFilePath()
{
     INT args = ses->urlargc();

     m_pathbuf[0]=m_nambuf[0]='\0';

     for ( int i = 1 ; i < args ; i++ ) {
          CHAR tmpbuf[GCMAXPTH];
          urlDecodeBuf(tmpbuf,ses->urlargv(i),sizeof(tmpbuf));
          stlcat(m_pathbuf,tmpbuf,GCMAXPTH);
          if (i < args-1) {
               stlcat(m_pathbuf,SLS,GCMAXPTH);
          }
     }
     urlDecodeBuf(m_nambuf,ses->urlargv(args-1),GCMAXPTH);
}

CHAR const *
rsySynthesis::normalizeFSpec(             // normalize file spec
CHAR const * str)
{
     CHAR const * tptr;
     static CHAR dbuf[5];

     tptr=str;
     if (strlen(str) == 1 && *str == '\\') {
          tptr=::stlcpy(dbuf,curWrkDirOp(GET,NULL),3);
     }
     else if (strlen(str) == 2 && str[1] == ':') {
          strcpy(dbuf,str);
          dbuf[2]='\\';
          dbuf[3]='\0';
          tptr=dbuf;
     }
     else if (strlen(str) == 4
           && str[1] == ':' && str[2] == '\\' && str[3] == '.') {
          tptr=::stlcpy(dbuf,str,3);
     }
     if (*tptr == '\\') {
          ++tptr;
     }
     return(tptr);
}

GBOOL
hasDirSpec(
CHAR const * ptr)
{
     ASSERT(ptr != NULL);
     return(strchr(ptr,'\\') != NULL || strchr(ptr,':') != NULL);
}

const CHAR *
rsySynthesis::getShortFileName(
CHAR *fptr)
{
     ASSERT(fptr != NULL);
     ASSERT(dirnam != NULL);

     static CHAR dosfbuf[GCSTRFNM];

     setmem(dosfbuf,sizeof(dosfbuf),0);
     stzcpy(dfname,dirnam,GCMAXPTH);
     stzcat(dfname,fptr,GCMAXPTH);
     if (::getShortName(dosfbuf,(const CHAR *)dfname,GCSTRFNM)) {
          return(&dosfbuf[0]);
     }
     return(fptr);
}

static GBOOL                       //   TRUE if char should be encoded
urlNeedEncode(                     // does char require encoding for URL?
CHAR c)                            //   character to check
{
     return(c <= ' ' || c > '~' || strchr("\"#%<>?[\\]^`'{|}",c) != NULL);
}

static CHAR *                      //   returns pointer to destination
urlEncodeBuf(                      // encode special characters in URL
CHAR * buf,                        //   buffer to receive encoded string
CHAR const * src,                  //   unencoded URL
size_t bufSiz)                     //   size of destination buffer
{
     if (bufSiz > 0) {
          size_t i=0;
          CHAR c;
          ASSERT(src != NULL);
          ASSERT(buf != NULL);
          while ((c=*src++) != '\0' && i < bufSiz-1) {
               if (c == ' ') {
                    buf[i++]='+';
               }
               else if (urlNeedEncode(c)) {
                    if (i >= bufSiz-CSTRLEN("%XX")) {
                         break;
                    }
                    buf[i++]='%';
                    buf[i++]=hexdig((c>>4)&0x0F);
                    buf[i++]=hexdig(c&0x0F);
               }
               else {
                    buf[i++]=c;
               }
          }
          buf[i]='\0';
     }
     return(buf);
}

static CHAR *                      //   returns pointer to destination
urlDecodeBuf(                      // decode special characters in URL
CHAR *buf,                         //   buffer to receive decoded string
const CHAR *src,                   //   unencoded URL
size_t bufSiz)                     //   size of destination buffer
{
     if (bufSiz > 0) {
          size_t i=0;
          CHAR c;
          ASSERT(src != NULL);
          ASSERT(buf != NULL);
          while ((c=*src++) != '\0' && i < bufSiz-1) {
               if (c == '+') {
                    c=' ';
               }
               else if (c == '%' && isxdigit(*src) && isxdigit(*(src+1))) {
                    c=(hexval(*src++)<<4)|(hexval(*src++));
               }
               buf[i++]=c;
          }
          buf[i]='\0';
     }
     return(buf);
}
