/*
 * SYNBASE.CPP
 *
 * Base Synthesis Class
 *
 */

#include "gcomm.h"
#include "majorbbs.h"
#include "galacth.h"
#include "dnf.h"
#include "dnfmgr.h"
#include "ahutil.h"
#include "synbase.h"
#include "wlmsg.h"
#include "tvb.h"
#include "wltvar.h"

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

//
// Base Synthesis Member Functions
//

MARKSOURCE(synbase);

synBase::synBase(acthSession* _ses) : acthSynthesis(_ses)
                                    , m_SynState(SYNSTATE_REQUEST)
                                    , m_timer(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_reqKey(reqkey)
              , m_err(ERR_NOERROR)
              , m_SynSubState(SYNSUB_BUILDMAP)
              , m_dnf(NULL)
              , m_usr(NULL)
              , m_errParam(NULL)
              , m_bActive(false)
{
    memset(&m_usracc,0,sizeof(struct usracc));
}

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()) {
     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();
     }
     initTemplates();
     usaptr=uacoff(usrnum);
     return(rc);
}

ACTHCODE
synBaseAuth::proceedResponse()     // proceed with response
{
     ACTHCODE rc;
     clearTextVars();
     if (m_usr != NULL) {
          setusaptr();
     }
     setErrorVars();
     dnfSetTemplateTvb(m_dnf);
     ::setTemplateMask(m_strTemplate,m_dnf); // ??

     rc=proceedDerivedResponse();

     clearTextVars();
     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_usracc.userid) == '\0') {
#ifdef ODBC
          readAcct(m_usr->userid(),&m_usracc);
#else
          ::dfaSetBlk(::accbb);
          dfaAcqEQ(&m_usracc,m_usr->userid(),0);
          ::dfaRstBlk();
#endif
     }
     usaptr=&m_usracc;
}

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;
     }
     (VOID)dftFileName;
     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::setErrorVars()             // set error variables
{
     if (m_err > 0) {
          setmbk(wlMsgFile);
          prfmsg(translateError(),m_errtext.c_str());
          ::setErrorVars((INT)m_err,prfbuf);  // this func in text variables
          clrprf();
          rstmbk();
     }
}


