/***************************************************************************
 *                                                                         *
 *   SYNFILAH.CPP                                                          *
 *                                                                         *
 *   Copyright (c) 1998       Galacticomm, Inc.    All Rights Reserved.    *
 *                                                                         *
 *   Active HTML File Library Base Synthesis                               *
 *   Implementation                                                        *
 *                                                                         *
 *                                                - Phil Henning 10/16/98  *
 *                                                                         *
 ***************************************************************************/

#include "gcomm.h"
#include "majorbbs.h"
#include "galacth.h"
#include "dnf.h"
#include "dnfmgr.h"
#include "ahutil.h"
#include "synfilah.h"
#include "filagent.h"
#include "filtvb.h"

#define FILREV "$Revision: 8 $"
#define DFTSUCCESS "index.htm"
#define DFTERROR   "error.htm"

//
// Base Synthesis Member Functions
//

synBase::synBase(acthSession* _ses) : acthSynthesis(_ses)
                                    , m_SynState(SYNSTATE_REQUEST)
                                    , m_timer(theFilAgent->m_timeslice)

{
}

synBase::~synBase()
{
}

ACTHCODE
synBase::proceed()                 // proceed with synthesis
{
     ACTHCODE rc=ACTHMORE;
     if (startProc()) {
          do {
               switch (m_SynState) {
               case SYNSTATE_REQUEST:
                    rc=proceedRequest();
                    break;
               case SYNSTATE_SYNTH:
                    rc=proceedSynth();
                    break;
               case SYNSTATE_RESPONSE:
                    rc=proceedResponse();
                    break;
               }
          } while (contProc(rc));
     }
     return(rc);
}

bool
synBase::startProc()               // cycle timer start
{
     return(m_timer.start());
}

bool
synBase::contProc(                 // cycle timer ok to continue
ACTHCODE rc)
{
     return(rc == ACTHMORE && m_timer.haveTime() && btuoba(usrnum) > 512);
}

// synBase Auth

synBaseAuth::synBaseAuth(
acthSession* _ses,
bool anonok,
CHAR const * reqkey,
INT lvlcnt)   : synBase(_ses)
              , m_anonok(anonok)
              , m_lvlcnt(lvlcnt)
              , m_succRedir(false)
              , m_errRedir(false)
              , m_onsuccessFile(NULL)
              , m_onerrorFile(DFTERROR)
              , m_inframes(false)
              , m_reqKey(reqkey)
              , m_err(ERR_NOERROR)
              , m_SynSubState(SYNSUB_BUILDMAP)
              , m_dnf(NULL)
              , m_fluloaded(false)
              , m_usr(NULL)
              , m_prefloaded(false)
              , m_errParam(NULL)

{
    memset(&m_usaptr,0,sizeof(struct usracc));
    memset(&m_curfllib,0,sizeof(struct fllib));
    memset(&m_fluser,0,sizeof(struct fluser));
}


synBaseAuth::~synBaseAuth()
{
    if (m_dnf != NULL) {
          delete m_dnf;
    }
    if (m_onsuccessFile != NULL) {
          delete [] m_onsuccessFile;
    }
    if (m_errParam != NULL) {
          delete [] m_errParam;
    }

}


ACTHCODE
synBaseAuth::proceedRequest()      // get common params, check authentication
{
     ACTHCODE rc=ACTHMORE;
     if (ses->urlargc() == m_lvlcnt && ses->forceDir()) {
          rc=ACTHDONE;
     }
     else if ((m_usr=ses->getUser()) == NULL && !m_anonok) {
          rc=ACTHNOANON;
     }
     else if (m_usr == NULL && strlen(m_reqKey) != 0) {
          rc=ACTHNOANON;
     }
     else if (m_usr != NULL && !m_usr->hasKey(m_reqKey)) {
          rc=ACTHFORBID;
     }
     else if (m_usr == NULL && ses->param("forceauth")) {
          rc=ACTHNOANON;
     }
     if (m_usr != NULL) {
          setusaptr();
     }
     if (!m_fluloaded) {
          LoadUserRecord();
     }
     initTemplates();
     const CHAR* value=getCookie(FRAMECOOKIE,ses);
     m_inframes=(value != NULL && sameas(value,"1"));
     usaptr=uacoff(usrnum);
     return(rc);
}

ACTHCODE
synBaseAuth::proceedResponse()     // proceed with response
{
     ACTHCODE rc;
     clearVars();
     if (m_usr != NULL) {
          setusaptr();
     }
     setTarget(m_inframes);
     setErrorVars();
     dnfSetTemplateTvb(m_dnf);
     ::setTemplateMask(m_strTemplate,m_dnf);
     if (!m_fluloaded) {
          LoadUserRecord();
     }
     if (m_curfllib.libname[0] != '\0') {
          ::setCurLibVars(&m_curfllib,m_usr);
     }
     setPreferenceVariables();
     if (m_usr != NULL) {
          ::setAdminLinks(m_usr->hasKey(flsysop));
     }
     rc=proceedDerivedResponse();
     if (rc == ACTHDONE) {
          SaveUserRecord();
     }
     clearVars();
     usaptr=uacoff(usrnum);
     return(rc);
}

VOID
synBaseAuth::setusaptr()           // set usaptr for use with global Tvars
{
     if (::onsysn(m_usr->userid(),TRUE)) {
          usaptr=othuap;
          return;
     }
     if (*(m_usaptr.userid) == '\0') {
          ::dfaSetBlk(::accbb);
          dfaAcqEQ(&m_usaptr,m_usr->userid(),0);
          ::dfaRstBlk();
     }
     usaptr=&m_usaptr;
}

VOID
synBaseAuth::initTemplates()       // get onxxx parameter values
{
     m_succRedir=getOnParam("onsuccess",DFTSUCCESS,&m_onsuccessFile);
     if (ses->param("onerror")) {
          INT sz=ses->paramRoom("onerror");
          m_errParam=new CHAR[sz];
          ses->param("onerror",m_errParam,sz);
     }
     m_onerrorFile=DFTERROR;
}

bool                               //   is a redirct?
synBaseAuth::getOnParam(           // get onxxx parameter
CHAR const * paramName,            //   parameter to get
CHAR const * dftFileName,          //   dft file name to use
CHAR** pStorePtr)                  //   store redir path here
{
     if (ses->param(paramName)) {
          if (*pStorePtr != NULL) {
               delete [] *pStorePtr;
          }
          INT sz=ses->paramRoom(paramName);
          *pStorePtr=new CHAR[sz];
          ses->param(paramName,*pStorePtr,sz);
          if (isProtocol(*pStorePtr) || **pStorePtr == '/') {
               return(true);
          }
          return(false);
     }
     else if (*pStorePtr != NULL) {
          delete [] *pStorePtr;
          *pStorePtr=NULL;
     }
     return(false);
}

ACTHCODE                           //   continue synthesis?
synBaseAuth::errorResponse(        // process an error
dnfMap& map,                       //   map to use
CHAR const * path)                 //   path to template directory
{
     if (m_errParam != NULL) {
          INT items=itemcntd(m_errParam,",");
          for (int i=0 ; i < items ; i++) {
               CHAR* errcs=itemidxd(m_errParam,i,",");
               CHAR* restr=strchr(errcs,' ');
               if (atoi(errcs) == 0 && restr == NULL) {
                    // found default redir
                    strmove(errcs,unpad(skpwht(errcs)));
                    if (strlen(errcs) > 0) {
                         m_onerrorFile=errcs;
                    }
               }
               else if (atoi(errcs) == m_err && restr != NULL) {
                    strmove(restr,unpad(skpwht(restr)));
                    if (strlen(restr) > 0) {
                         m_onerrorFile=restr;
                         break;
                    }
               }
          }

     }
     m_errRedir=(isProtocol(m_onerrorFile.c_str()) || m_onerrorFile[0] == '/');
     if (m_errRedir) {
          ostrstream ost;
          if (m_onerrorFile[0] == '/') {
               ost << "http://" << ses->host();
          }
          ost << m_onerrorFile.c_str() << ends;
          ses->redirect(ost.str());
          ost.rdbuf()->freeze(0);
          return(ACTHDONE);
     }
     ASSERT(path != NULL);
     string dest=path;
     dest+=m_onerrorFile;
     m_dnf=dnfCreateHandler(&bout,&map,dest.c_str());
     return(ACTHMORE);
}

ACTHCODE                           //   continue synthesis?
synBaseAuth::successResponse(      // process an onsuccess
dnfMap& map,                       //   map to use
CHAR const * path)                 //   path to template directory
{
     if (m_succRedir) {
          ostrstream ost;
          if (m_onsuccessFile[0] == '/') {
               ost << "http://" << ses->host();
          }
          ost << m_onsuccessFile << ends;
          ses->redirect(ost.str());
          ost.rdbuf()->freeze(0);
          return(ACTHDONE);
     }
     ASSERT(path != NULL);
     if (m_onsuccessFile == NULL) {
          m_dnf=dnfCreateHandlerURL(ses,&map,PPFIX);
     }
     else {
          string dest=path;
          dest+=m_onsuccessFile;
          m_dnf=dnfCreateHandler(&bout,&map,dest.c_str());
     }
     return(ACTHMORE);
}

VOID
synBaseAuth::LoadUserRecord()      // load user record
{
     if (m_usr != NULL) {
          flu=&fluarr[usrnum];
          flo=(struct fluson*)ptrblok(flomem,usrnum);
          memset(flu,0,sizeof(struct fluser));
          memset(flo,0,sizeof(struct fluson));
          flo->nlibaxs=-1;
          dfaSetBlk(genbb);
          stzcpy(flusmem.userid,m_usr->userid(),UIDSIZ);
          stzcpy(flusmem.modnam,"File Library",MNMSIZ);
          if (!dfaAcqEQ(&flusmem,&flusmem,0)) {
               memset(&flusmem.udata,0,sizeof(struct fluser));
          }
          movmem(&flusmem.udata,flu,sizeof(struct fluser));
          struct fllib* clib=setuaxs();
          if (clib != NULL) {
               m_curfllib=*clib;
          }
          movmem(flu,&m_fluser,sizeof(struct fluser));
          updusr(flu);
          dfaRstBlk();
          m_fluloaded=true;
     }
     else {
          struct fllib* pLib=libfind(deflname);
          if (pLib != NULL) {
               m_curfllib=*pLib;
          }
     }
}

VOID
synBaseAuth::SaveUserRecord()      // save user record
{
     if (m_fluloaded && m_curfllib.libname[0] != '\0') {
          strcpy(m_fluser.lib,m_curfllib.libname);
          updusr(&m_fluser);
     }
}


VOID
synBaseAuth::setPreferenceVariables()   // set preference vars
{
     if (!m_prefloaded) {
          if (m_usr != NULL) {
               theFilAgent->LoadPrefs(m_usr->userid(),&m_pref);
          }
          else {
               m_pref.m_lorder=theFilAgent->LoadLibOrder(NULL);
               m_pref.m_forder=theFilAgent->LoadFileOrder(NULL);
               m_pref.m_browse=theFilAgent->LoadSearchType(NULL);
          }
          m_prefloaded=true;
     }
     ::setPrefVars(m_pref.m_lorder,m_pref.m_forder,m_pref.m_browse);
}

VOID
synBaseAuth::setErrorVars()             // set error variables
{
     if (m_err > 0) {
          setmbk(filahmb);
          prfmsg(translateError(),m_errtext.c_str());
          ::setErrorVars((INT)m_err,prfbuf);
          clrprf();
          rstmbk();
     }
}

