
/***************************************************************************
 *                                                                         *
 *   SYNDARC.CPP                                                           *
 *                                                                         *
 *   Copyright (c) 1998       Galacticomm, Inc.    All Rights Reserved.    *
 *                                                                         *
 *   Active HTML File Library Archive Detail Synthesis                     *
 *   Implementation                                                        *
 *                                                                         *
 *                                                - Phil Henning 11/19/98  *
 *                                                                         *
 ***************************************************************************/

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

#define FILREV "$Revision: 9 $"

IMPORT_VARIABLE(CHAR*) rsptmp;               // vewctn() stores it's data here

enum {LSTITEM};

#define CHUNKSIZE 512                        // size for file data storage

/*--- View transmitter states ---*/
#define VEWNOT    0                               /* not started yet        */
#define VEWOPN    1                               /* open file for transmit */
#define VEWFID    2                            /* check type, output header */
#define VEWFIL    3                             /* output info on each file */
#define VEWEND    4                                              /* wind up */
#define VEWFND    5           /* searching ZIP2 file for end of central dir */

static
dnfStep dnfSuccessSteps[]={
     dnfStep(DNFTABLE),
       dnfStep(DNFCOLUMN,LSTITEM,"LISTITEM"),
     dnfStep(DNFTABLEEND),
     dnfStep(DNFMAPEND)
};
static
dnfMap filSuccessMap(PPFIX "/view/content/index.htm","Success Response",dnfSuccessSteps);

static
dnfStep dnfErrorSteps[]={
     dnfStep(DNFMAPEND)
};
static
dnfMap filErrorMap(PPFIX "/view/content/error.htm","Error Response",dnfErrorSteps);

MARKSOURCE(syndarc);

synArchiveDetail::synArchiveDetail(
acthSession* _ses,
bool anonok,
INT lvlcnt)   : synBaseAuth(_ses,anonok,theFilAgent->m_hfilkey,lvlcnt)
              , m_bDecoded(true)
              , m_dbuf(NULL)
              , m_dbufsiz(0)
              , m_allDone(false)
              , m_curCount(0)
{
     memset(&m_fllib,0,sizeof(struct fllib));
     memset(&m_flfile,0,sizeof(struct flfile));
     memset(&m_fb,0,sizeof(struct ffblk));
     memset(&m_key,0,sizeof(union combo));
}

synArchiveDetail::~synArchiveDetail()
{
     if (m_dbuf != NULL) {
          delete [] m_dbuf;
     }
}

ACTHCODE
synArchiveDetail::proceedRequest()           // setup request context
{
     ACTHCODE rc=synBaseAuth::proceedRequest();

     if (rc != ACTHMORE) {
          return(rc);
     }
     if (ses->param("lib")) {
          INT sz=ses->paramRoom("lib");
          CHAR* val=new CHAR[sz+1];
          ses->param("lib",val,sz);
          struct fllib* libptr=libfind(val);
          if (libptr == NULL) {
               m_err=ERR_INVALIDLIB;
               m_errtext=val;
          }
          else if (m_usr == NULL && strlen(libptr->dlkey) > 0) {
               return(ACTHNOANON);
          }
          else if (!ahHasLibKey(m_usr,libptr,libptr->dlkey)) {
               return(ACTHFORBID);
          }
          else if (libptr->flags&FLGCBD) {
               m_err=ERR_NOTFROMCD;
          }
          delete [] val;
          m_fllib=*libptr;
     }
     else {
          m_err=ERR_PARAMMISSING;
          m_errtext="lib";
     }
     if (m_err == ERR_NOERROR)  {
          if (ses->param("file")) {
               INT sz=ses->paramRoom("file");
               CHAR* val=new CHAR[sz+1];
               ses->param("file",val,sz);
               if (!CheckFileExists(val,m_fllib.flags&FLGDOS)) {
                    m_err=ERR_INVALIDFILE;
                    m_errtext=val;
               }
               else if (!::isArchive(val)) {
                    m_err=ERR_NOTARCHIVE;
                    m_errtext=val;
               }
               delete [] val;
          }
          else {
               m_err=ERR_PARAMMISSING;
               m_errtext="file";
          }
     }
     if (m_err == ERR_NOERROR) {
          flo=(struct fluson*)ptrblok(flomem,usrnum);
          if (flo->cszview.state != VEWNOT) {
               memset(&(flo->cszview),0,sizeof(struct zvdat));
          }
          stzcpy(flo->cszview.libname,m_key.key1.libname,FLNAMESZ);
          stzcpy(flo->cszview.filname,m_key.key1.filname,FLFILENM);
          flo->cszview.state=1;
          if (!vewctn()) {
               flo->cszview.state=VEWOPN;
               m_err=ERR_FILEIO;
               m_errtext=flo->cszview.filname;
          }
     }
     m_SynState=SYNSTATE_SYNTH;
     return(rc);
}

bool
synArchiveDetail::CheckFileExists(              // check if file exists
const CHAR* filname,                         // filename
bool isOSOnly)                               // is file in os only lib?
{
     bool rc=false;
     if (isOSOnly) {
          ostrstream ost;
          ost << libpath(&m_fllib) << SLS << filname << ends;
          rc=fndfile(&m_fb,ost.str(),0);
          ost.rdbuf()->freeze();
     }
     else {
          stlcpy(m_key.key1.libname,m_fllib.libname,FLNAMESZ);
          stlcpy(m_key.key1.filname,filname,FLFILENM);
          dfaSetBlk(flfdat);
          if (dfaQueryEQ(&m_key,COMPLF)) {
               rc=true;
               dfaAbsRec(&m_flfile,COMPLF);
          }
          dfaRstBlk();
     }
     return(rc);
}

ACTHCODE
synArchiveDetail::proceedSynth()             // proceed with synthesis
{
     m_SynState=SYNSTATE_RESPONSE;
     return(ACTHMORE);
}

ACTHCODE
synArchiveDetail::proceedDerivedResponse()   // proceed with response
{
     ACTHCODE rc=ACTHMORE;

     flo=(struct fluson*)ptrblok(flomem,usrnum);
     if (m_err != ERR_NOERROR) {
          if (m_dnf == NULL) {
               rc=errorResponse(filErrorMap,PPFIX "/view/content/");
          }
          else if (m_dnf->process() == DNFEND) {
               rc=ACTHDONE;
          }
          return(rc);
     }
     if (m_dnf == NULL) {
          CHAR ch=m_fllib.flags&FLGDOS ? 'O' : 'N';
          CHAR* fnbuf;
          if (ses->urlargc() > m_lvlcnt) {
               const CHAR* fnptr=ses->urlargv(m_lvlcnt);
               fnbuf=new CHAR[strlen(fnptr)+1];
               strcpy(fnbuf,fnptr);
          }
          else {
               fnbuf=new CHAR[sizeof("INDEX*.HTM")+1];
               strcpy(fnbuf,"INDEX*.HTM");
          }
          m_strTemplate=fnbuf;
          strrpl(fnbuf,'*',ch);
          string strfname=PPFIX "/view/content/";
          strfname+=fnbuf;
          m_dnf=dnfCreateHandler(&bout,&filSuccessMap,strfname.c_str());
          delete [] fnbuf;
     }
     else {
          ::setLibVars(&m_fllib,m_usr);
          if (m_fllib.flags&FLGDOS) {
               ::setOSFileVars(&m_fb,&m_fllib,m_usr);
          }
          else {
               ::setFileVars(&m_flfile,m_usr);
          }
          if (m_fileData.length() > 0) {
               if (!m_bDecoded) {
                    decodeFileData();
                    m_bDecoded=true;
               }
               ::setArchiveFileDetailVars(m_decodedPtrs);
          }
          switch (m_dnf->process()) {
          case DNFROWBEGIN:
               rsptmp[0]='\0';
               if (::vewctn()) {
                    if (rsptmp[0] == '\0') {
                         m_dnf->sayAgain();
                         break;
                    }
                    m_curCount++;
                    m_bDecoded=false;
                    m_fileData=rsptmp;
               }
               else {
                    flo->cszview.state=VEWNOT;
                    m_fileData="";
                    m_dnf->tableDone();
                    m_allDone=true;
               }
               break;
          case LSTITEM:
               break;
          case DNFROWEND:
               m_fileData="";
               break;
          case DNFEND:
               rc=ACTHDONE;
               break;
          }
     }
     return(rc);
}

VOID
synArchiveDetail::abort()                    // synthesis abort
{
     flo=(struct fluson*)ptrblok(flomem,usrnum);
     switch (flo->cszview.state) {
     case VEWNOT:
     case VEWOPN:
          break; /* file closed */
     default:
          fclose(flo->cszview.fp);
     }
     flo->cszview.state=VEWNOT;
}

VOID
synArchiveDetail::decodeFileData()           // decode file data from vewctn()
{
     if (m_dbufsiz <= m_fileData.length()) {
          if (m_dbuf != NULL) {
               delete [] m_dbuf;
          }
          INT reqlen=m_fileData.length()+1;
          m_dbufsiz=((reqlen+(CHUNKSIZE-1))/CHUNKSIZE)*CHUNKSIZE;
          m_dbuf=new CHAR[m_dbufsiz];
     }
     stlcpy(m_dbuf,m_fileData.c_str(),m_dbufsiz);
     CHAR *ptr=m_dbuf;
     INT cnt=0;
     m_decodedPtrs[cnt++]=ptr;
     while (*ptr != '\0') {
          if (*ptr == '\t') {
               *ptr='\0';
               ASSERT(cnt < 8);
               m_decodedPtrs[cnt++]=ptr+1;
          }
          ptr++;
     }
     m_decodedPtrs[cnt]=m_decodedPtrs[cnt-1]+strlen(m_decodedPtrs[cnt-1])+1;
}

INT
synArchiveDetail::translateError()           // translate err to mcv file op
{
     switch (m_err) {
     case ERR_INVALIDLIB:
          return(ERRVC03);
     case ERR_PARAMMISSING:
          return(ERRVC01);
     case ERR_INVALIDFILE:
          return(ERRVC04);
     case ERR_NOTARCHIVE:
          return(ERRVC06);
     case ERR_FILEIO:
          return(ERRVC07);
     case ERR_NOTFROMCD:
          return(ERRVC09);
     default:
          ASSERT(FALSE);
     }
     m_errtext=spr("%d",m_err);
     return(ERROOPS);
}
