/***************************************************************************
 *                                                                         *
 *   SYNLFILS.CPP                                                          *
 *                                                                         *
 *   Copyright (c) 1998       Galacticomm, Inc.    All Rights Reserved.    *
 *                                                                         *
 *   Active HTML File List Files Synthesis                                 *
 *   Implementation                                                        *
 *                                                                         *
 *                                                - Phil Henning 10/27/98  *
 *                                                                         *
 ***************************************************************************/

#include "gcomm.h"
#include "majorbbs.h"
#include <windows.h>
#include "galacth.h"
#include "dnf.h"
#include "dnfmgr.h"
#include "ahutil.h"
#include "filtvb.h"
#include "synlfils.h"
#include "filagent.h"
#include "galfilah.h"

#define FILREV "$Revision: 21 $"

enum {LSTITEM};

const CHAR STARTDELIM[]=";";

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

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

MARKSOURCE(synlfils);

INT                                     //  number of occurances
countchr(                               // count num of spec. chars within str
const CHAR* str,                        //  str to check
CHAR ch);                               //  char to match

const CHAR*                             //  found file name
getFDFileName(                          // get found file name
const WIN32_FIND_DATA& fd);             //  find data struct

//
//  List Files Synthesis Member Functions
//

synListFiles::synListFiles(
acthSession* _ses,
bool anonok,
INT lvlcnt)   : synBaseAuth(_ses,anonok,theFilAgent->m_hfilkey,lvlcnt)
              , m_listOrder(ORDER_ASCEND)
              , m_listDirection(DIR_GE)
              , m_listCount(theFilAgent->m_dftlst)
              , m_searchType(STYPE_NAME)
              , m_popStart(PS_NONE)
              , m_nameStart(NS_NONE)
              , m_dateType(DTYPE_NONE)
              , m_curCount(0)
              , m_started(false)
              , m_listAll(false)
              , m_moreLow(false)
              , m_moreHigh(false)
              , m_searchAllLibs(false)
              , m_searchOnlyUnapproved(false)
              , m_init(false)
              , m_bEndOfLib(false)
              , m_contextState(INIT_LOW)
              , m_previous(0)
              , m_allDone(false)
              , m_fh(INVALID_HANDLE_VALUE)
              , m_popit(false)
              , m_libCount(0)
{
     memset(&m_ffile,0,sizeof(struct flfile));
     memset(&m_fllib,0,sizeof(struct fllib));
     memset(&m_searchLib,0,sizeof(struct fllib));
     memset(&m_fb,0,sizeof(struct ffblk));
}

synListFiles::~synListFiles()
{
     if (m_fh != INVALID_HANDLE_VALUE) {
          FindClose(m_fh);
     }
}


ACTHCODE
synListFiles::proceedRequest()          // setup request context
{
     ACTHCODE rc=synBaseAuth::proceedRequest();
     bool bSearchChanged=false;
     bool bOrderChanged=false;
     bool wasOrderSpecified=false;
     bool bDirSpec=false;
     bool isOS=false;
     bool isSearch=false;

     if (rc != ACTHMORE) {
          return(rc);
     }
     if (!ses->param("lib") || ses->param("liball")) {
          m_searchAllLibs=true;
     }
     else {
          INT sz=ses->paramRoom("lib");
          CHAR* val=new CHAR[sz];
          ses->param("lib",val,sz);
          if (strlen(val) == 0 || sameas(val,"*")) {
               m_searchAllLibs=true;
          }
          else {
               struct fllib* libptr;
               if (sameas(val,".")) {
                    if (validateLib(&m_curfllib,m_usr)) {
                         libptr=libfind(m_curfllib.libname);
                    }
                    else {
                         libptr=libfind(deflname);
                    }
               }
               else {
                    libptr=libfind(val);
               }
               if (libptr == NULL) {
                    m_err=ERR_INVALIDLIB;
                    m_errtext=val;
               }
               else if (m_usr == NULL && strlen(libptr->keyreq) > 0) {
                    return(ACTHNOANON);
               }
               else if (!ahHasLibKey(m_usr,libptr,libptr->keyreq)) {
                    return(ACTHFORBID);
               }
               else {
                    m_searchLib=*libptr;
                    m_curfllib=*libptr;
                    isOS=(m_curfllib.flags&FLGDOS) != 0;
               }
          }
          delete [] val;

     }
     if (m_err == ERR_NOERROR && !isOS) {
          bool bIsAuth=(m_usr != NULL);
          m_searchType=LoadDftSearch(m_usr);
          if (ses->param("search")) {
               INT sz=ses->paramRoom("search");
               CHAR* val=new CHAR[sz];
               ses->param("search",val,sz);
               if (sameas(val,"name")) {
                    m_searchType=STYPE_NAME;
               }
               else if (sameas(val,"name set")) {
                    m_searchType=STYPE_NAME;
                    bSearchChanged=bIsAuth;
               }
               else if (sameas(val,"date")) {
                    m_searchType=STYPE_DATE;
               }
               else if (sameas(val,"date set")) {
                    m_searchType=STYPE_DATE;
                    bSearchChanged=bIsAuth;
               }
               else if (sameas(val,"popularity")) {
                    m_searchType=STYPE_POPULARITY;
               }
               else if (sameas(val,"popularity set")) {
                    m_searchType=STYPE_POPULARITY;
                    bSearchChanged=bIsAuth;
               }
               else if (sameas(val,"keywords")
                || sameas(val,"keywords set")
                || sameas(val,"keyword")
                || sameas(val,"keyword set")) {
                    m_searchType=STYPE_KEYWORDS;
                    isSearch=true;
               }
               else {
                    m_err=ERR_INVALIDPARAM;
                    m_errtext="search";
               }
               delete [] val;
          }
     }
     if (m_err == ERR_NOERROR && !isOS && !isSearch) {
          bool bIsAuth=(m_usr != NULL);
          m_listOrder=LoadDftOrder(m_usr);
          if (ses->param("order")) {
               wasOrderSpecified=true;
               INT sz=ses->paramRoom("order");
               CHAR* val=new CHAR[sz];
               ses->param("order",val,sz);
               if (sameas(val,"~ascending") || sameas(val,"descending")) {
                    m_listOrder=ORDER_DESC;
               }
               else if (sameas(val,"~ascending set") || sameas(val,"descending set")) {
                    m_listOrder=ORDER_DESC;
                    bOrderChanged=bIsAuth;
               }
               else if (sameas(val,"~descending") || sameas(val,"ascending")) {
                    m_listOrder=ORDER_ASCEND;
               }
               else if (sameas(val,"~descending set") || sameas(val,"ascending set")) {
                    m_listOrder=ORDER_ASCEND;
                    bOrderChanged=bIsAuth;
               }
               else if (sameas(val,"~")) {
                    m_listOrder=(m_listOrder == ORDER_DESC ? ORDER_ASCEND : ORDER_DESC);
               }
               else if (sameas(val,"~ set")) {
                    m_listOrder=(m_listOrder == ORDER_DESC ? ORDER_ASCEND : ORDER_DESC);
                    bOrderChanged=bIsAuth;
               }
               else {
                    m_err=ERR_INVALIDPARAM;
                    m_errtext="order";
               }
               delete [] val;
          }
          m_listDirection=m_listOrder == ORDER_DESC ? DIR_LT : DIR_GT;
     }

     if (m_err == ERR_NOERROR && ses->param("all")) {
          m_listAll=true;
     }
     if (m_err == ERR_NOERROR && !m_listAll && ses->param("direction")) {
          INT sz=ses->paramRoom("direction");
          CHAR* val=new CHAR[sz];
          if (ses->param("direction",val,sz)) {
               bDirSpec=true;
               if (sameas(val,"gt")) {
                    m_listDirection=DIR_GT;
               }
               else if (sameas(val,"ge")) {
                    m_listDirection=DIR_GE;
               }
               else if (sameas(val,"lt")) {
                    m_listDirection=DIR_LT;
               }
               else if (sameas(val,"le")) {
                    m_listDirection=DIR_LE;
               }
               else {
                    m_err=ERR_INVALIDPARAM;
                    m_errtext="direction";
               }
          }
          delete [] val;
     }
     if (m_err == ERR_NOERROR && !m_listAll && ses->param("start")) {
          INT sz=ses->paramRoom("start");
          CHAR* val=new CHAR[sz];
          ses->param("start",val,sz);
          m_searchStart=val;
          delete [] val;
     }
     if (m_err == ERR_NOERROR && m_searchType == STYPE_NAME && !isOS) {
          if (ses->param("namestart")) {
               INT sz=ses->paramRoom("namestart");
               CHAR* val=new CHAR[sz];
               ses->param("namestart",val,sz);
               if (sameas("first",val)) {
                    m_nameStart=NS_FIRST;
               }
               else if (sameas("last",val)) {
                    m_nameStart=NS_LAST;
               }
               else {
                    m_err=ERR_INVALIDPARAM;
                    m_errtext="namestart";
               }
               delete [] val;
          }
          else if (*(m_searchStart.c_str()) == '\0') {
               m_nameStart=GetDftNameStart();
          }
          if (m_nameStart == NS_LAST && !bDirSpec) {
               m_listDirection=DIR_LE;
          }
     }
     if (m_err == ERR_NOERROR && (m_searchType == STYPE_NAME || isOS)) {
          if (ses->param("wildcard")) {
               INT sz=ses->paramRoom("wildcard");
               CHAR* val=new CHAR[sz];
               ses->param("wildcard",val,sz);
               if (strlen(val) > 0)  {
                    m_searchWildcard=val;
               }
               delete [] val;
          }
     }
     if (m_err == ERR_NOERROR && m_searchType == STYPE_DATE) {
          if (ses->param("datestart")) {
               INT sz=ses->paramRoom("datestart");
               CHAR* val=new CHAR[sz];
               ses->param("datestart",val,sz);
               if (strlen(val) > 0) {
                    if (isdigit(*val)) {
                         m_dateType=DTYPE_ABS;
                         m_dateStart=validateDate(val);
                    }
                    else if (*val == '-' && strlen(val) > 1) {
                         m_dateType=DTYPE_ABS;
                         m_dateStart=relativeDate(val);
                    }
                    else if (sameas("first",val)) {
                         m_dateType=DTYPE_FIRST;
                    }
                    else if (sameas("last",val)) {
                         m_dateType=DTYPE_LAST;
                    }
                    else if (sameas("new",val)) {
                         m_dateType=DTYPE_ABS;
                         m_dateStart=sinceLastScanDate();
                    }
                    else {
                         m_err=ERR_INVALIDPARAM;
                         m_errtext="datestart";
                    }
               }
               delete [] val;
          }
          else if (*(m_searchStart.c_str()) == '\0') {
               m_dateType=GetDftDateType();
          }
          if (!bDirSpec && m_dateType != DTYPE_ABS) {
               m_listDirection=(m_dateType == DTYPE_FIRST ? DIR_GE : DIR_LE);
          }
     }
     if (m_err == ERR_NOERROR && ses->param("unapproved")
       && ahIsFlop(m_usr,&m_curfllib) && !isOS) {
          m_searchOnlyUnapproved=true;
     }

     if (m_err == ERR_NOERROR && m_searchType == STYPE_POPULARITY && !isOS) {
          if (ses->param("popstart")) {
               INT sz=ses->paramRoom("popstart");
               CHAR* val=new CHAR[sz];
               ses->param("popstart",val,sz);
               if (sameas(val,"first")) {
                    m_popStart=PS_FIRST;
               }
               else if (sameas(val,"last")) {
                    m_popStart=PS_LAST;
               }
               else {
                    m_err=ERR_INVALIDPARAM;
                    m_errtext="popstart";
               }
               delete [] val;
          }
          else {
               m_popStart=GetDftPopStart();
          }
          if (!bDirSpec) {
               m_listDirection=m_popStart == PS_FIRST ? DIR_GE : DIR_LE;
          }
          if (!wasOrderSpecified) {
               m_listOrder=m_popStart == PS_FIRST ? ORDER_ASCEND : ORDER_DESC;
          }
     }
     if (m_err == ERR_NOERROR && m_searchType == STYPE_KEYWORDS) {
          INT sz;
          CHAR* val=NULL;
          if (ses->param("keywords")) {
               sz=ses->paramRoom("keywords");
               val=new CHAR[sz];
               ses->param("keywords",val,sz);
               if (strlen(val) > 0) {
                    m_searchKeywords=val;
               }
          }
          else if (ses->param("keyword")) {
               sz=ses->paramRoom("keyword");
               val=new CHAR[sz];
               ses->param("keyword",val,sz);
               if (strlen(val) > 0) {
                    m_searchKeywords=val;
               }
          }
          if (val != NULL) {
               delete [] val;
          }
     }
     if (m_err == ERR_NOERROR && !m_listAll && ses->param("count")) {
          INT sz=ses->paramRoom("count");
          CHAR* val=new CHAR[sz];
          ses->param("count",val,sz);
          if (strlen(val) > 0) {
               INT tmpcnt=atoi(val);
               if (tmpcnt > 0) {
                    m_listCount=min(tmpcnt,theFilAgent->m_maxlst);
               }
          }
          delete [] val;
     }
     m_SynState=((m_err == ERR_NOERROR) ? SYNSTATE_SYNTH : SYNSTATE_RESPONSE);
     if (m_err == ERR_NOERROR && bOrderChanged) {
          SaveDftOrder(m_usr,m_listOrder);
     }
     if (m_err == ERR_NOERROR && bSearchChanged) {
          SaveDftSearch(m_usr,m_searchType);
     }
     return(rc);
}

VOID
synListFiles::buildOSMap()              // build OS file map
{
     bool addfb=false;
     bool lastone=false;
     if ((m_curCount >= m_listCount) && !m_listAll) {
          m_SynSubState=SYNSUB_LISTCONTEXT;
          return;
     }
     if (!m_init) {
          ostrstream ost;
          ost << libpath(&m_searchLib) << SLS;
          ost << (m_searchWildcard.length() > 0 ? m_searchWildcard.c_str() : "*.*");
          ost << ends;

          if ((m_fh=FindFirstFile(ost.str(),&m_findData)) != INVALID_HANDLE_VALUE) {
               // find first non directory or hidden file.
               // also exclude system files
               while ((m_findData.dwFileAttributes&FILE_ATTRIBUTE_HIDDEN)
                 || (m_findData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
                 || (m_findData.dwFileAttributes&FILE_ATTRIBUTE_SYSTEM)) {
                    if (!FindNextFile(m_fh,&m_findData)) {
                          m_init=true;
                          break;
                    }
               }
               if (!m_init) {
                    addfb=(m_searchStart.length() == 0 || (m_listDirection&DIR_LT));
                    if (!addfb && m_listDirection&DIR_GT) {
                         bool result=true;
                         ostrstream ost;
                         ost << libpath(&m_searchLib) << SLS;
                         ost << m_fb.ff_name << ends;
                         fndfile(&m_fb,ost.str(),0);
                         ost.rdbuf()->freeze(0);
                         strcpy(m_fb.ff_name,getFDFileName(m_findData));
                         while (!sameas(m_fb.ff_name,m_searchStart.c_str())
                           && (result=FindNextFile(m_fh,&m_findData)) != false) {
                              if (!(m_findData.dwFileAttributes&FILE_ATTRIBUTE_HIDDEN)
                               && !(m_findData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
                               && !(m_findData.dwFileAttributes&FILE_ATTRIBUTE_SYSTEM)) {
                                   ostrstream ost;
                                   ost << libpath(&m_searchLib) << SLS;
                                   ost << getFDFileName(m_findData);
                                   ost << ends;
                                   fndfile(&m_fb,ost.str(),0);
                                   ost.rdbuf()->freeze(0);
                                   m_previous++;
                                   strcpy(m_fb.ff_name
                                         ,getFDFileName(m_findData));
                              }
                         }
                         addfb=(result && (m_listDirection&DIR_EQ));
                         lastone=!result;
                    }
                    else if (addfb) {
                         ostrstream ost;
                         ost << libpath(&m_searchLib);
                         ost << SLS << getFDFileName(m_findData);
                         ost << ends;
                         fndfile(&m_fb,ost.str(),0);
                         strcpy(m_fb.ff_name
                                   ,getFDFileName(m_findData));
                         ost.rdbuf()->freeze(0);
                    }
                    m_init=true;
               }
          }
          else {
               m_fb.ff_name[0]='\0';
               lastone=true;
               m_init=true;
          }
          ost.rdbuf()->freeze(0);
     }
     else {
          if (FindNextFile(m_fh,&m_findData)) {
               if (!(m_findData.dwFileAttributes&FILE_ATTRIBUTE_HIDDEN)
                && !(m_findData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
                && !(m_findData.dwFileAttributes&FILE_ATTRIBUTE_SYSTEM)) {

                    CHAR fname[GCMAXFNM];
                    ostrstream ost;
                    ost << libpath(&m_searchLib) << SLS;
                    ost << getFDFileName(m_findData) << ends;
                    fndfile(&m_fb,ost.str(),0);
                    strcpy(m_fb.ff_name
                              ,getFDFileName(m_findData));
                    addfb=true;
                    if (sameas(m_searchStart.c_str(),fname)) {
                         if (m_listDirection&DIR_LT) {
                              lastone=true;
                              addfb=(m_listDirection&DIR_EQ != 0);
                         }
                    }
                    if (m_popit) {
                         if (addfb) {
                              m_OSqueue.pop_front();
                              ++m_previous;
                         }
                         else {
                              ++m_curCount;
                         }
                         m_popit=false;
                    }
               }
          }
          else {
               m_fb.ff_name[0]='\0';
               lastone=true;
          }
     }
     if (addfb) {
          if (m_listAll) {
               m_SynState=SYNSTATE_RESPONSE;
               return;
          }
          else {
               addToOSQueue(m_fb);
          }
          ++m_curCount;
          if (m_curCount == m_listCount && m_listDirection&DIR_LT) {
               if (m_listDirection == DIR_LT) {
                    m_popit=true;
                    --m_curCount;
               }
               // DIR_LE
               else if (!sameas(m_fb.ff_name,m_searchStart.c_str())) {
                    m_OSqueue.pop_front();
                    --m_curCount;
                    ++m_previous;
               }
          }
     }
     if (lastone) {
          m_SynSubState=SYNSUB_LISTCONTEXT;
     }
}

ACTHCODE
synListFiles::proceedSynth()            // proceed with synthesis
{
     if (!m_searchAllLibs && (m_searchLib.flags&FLGDOS)) {
          // handle dos only libs.
          if (m_SynSubState == SYNSUB_BUILDMAP) {
               buildOSMap();
          }
          else {
               buildOSContext();
          }
     }
     else {
           if (m_SynSubState == SYNSUB_BUILDMAP) {
               if (!m_init) {
                    InitSyn();
               }
               else if (m_err != ERR_NOERROR) {
                    m_SynState=SYNSTATE_RESPONSE;
               }
               else {
                    buildMap();
               }
          }
          else {
               buildContext() ;
          }
     }
     return(ACTHMORE);
}

VOID
synListFiles::InitSyn()                 // initialize synthesis
{
     m_libMap.Init(m_searchAllLibs ? NULL : &m_searchLib,m_usr);
     m_libCount=m_libMap.GetNumberLibs();
     if (m_libCount == 0 && m_searchAllLibs) {
          m_SynState=SYNSTATE_RESPONSE;
     }
     else {
          initKeys();
     }
     m_init=true;
}

string
synListFiles::getFileName(              // get file name from string
const string& str)                      // string to extract from
{
     int i=0;
     string deststr;
     while (str[i] != '\0' && str[i] != *STARTDELIM) {
          deststr+=str[i++];
     }
     return(deststr);
}

string
synListFiles::getLibName(               // get lib name from string
const string& str)                      // string to extract from
{
     size_t i;
     string deststr;
     if ((i=str.find_first_of(*STARTDELIM)) > 0 && ++i < str.length()) {
          while (i < str.length() && str[i] != *STARTDELIM) {
               deststr+=str[i++];
          }
     }
     return(deststr);
}


string
synListFiles::getUDate(                 // get uploaded date from string
const string& str)                      // string to extract from
{
     size_t i;
     string deststr;
     if ((i=str.find_last_of(*STARTDELIM)) > 0 && ++i < str.length()) {
          while (i < str.length()) {
               deststr+=str[i++];
          }
     }
     return(deststr);
}

string
synListFiles::getPop(                   // get popularity from string
const string& str)                      // string to extract from
{
     size_t i;
     string deststr;
     if ((i=str.find_last_of(*STARTDELIM)) > 0 && ++i < str.length()) {
          while (i < str.length()) {
               deststr+=str[i++];
          }
     }
     return(deststr);
}

VOID
synListFiles::initKeys()                // init btrieve keys
{
     memset(&m_key,0,sizeof(union combo));
     switch(m_searchType) {
     case STYPE_NAME:
          if (m_nameStart == NS_NONE) {
               if (m_libCount == 1) {
                    setKey1();
               }
               else {
                    setKey4();
               }
          }
          else {
               LIBMAP::iterator iter;
               if (m_nameStart == NS_LAST) {
                    memset(m_libCount == 1 ? m_key.key1.filname : m_key.key4.filname
                          ,0xff,FLFILENM);
                    iter=m_libMap.m_map.end();
                    iter--;
               }
               else {
                    stlcpy(m_libCount == 1 ? m_key.key1.filname : m_key.key4.filname
                          ,"",FLFILENM);
                    iter=m_libMap.m_map.begin();
               }
               if (m_libCount == 1) {
                    stlcpy(m_key.key1.libname,(*iter).second.c_str(),FLNAMESZ);
               }
               else {
                    stlcpy(m_key.key4.libkey,(*iter).second.c_str(),FLNAMESZ);
               }
          }
          break;
     case STYPE_DATE:
          if (m_dateType == DTYPE_NONE) {
               if (m_libCount == 1) {
                    setKey0();
               }
               else {
                    setKey3();
               }
          }
          else if (m_dateType == DTYPE_FIRST) {
               memset(m_key.key3.udate,0xff,DATESZ-1);
          }
          else if (m_dateType == DTYPE_LAST) {
               stlcpy(m_key.key3.udate,"",DATESZ);
          }
          else {
               if (m_listDirection&DIR_GE) {
                    memset(m_key.key3.filname,0xff,FLFILENM-1);
                    memset(m_key.key3.libkey,0xff,FLNAMESZ-1);
               }
               stlcpy(m_key.key3.udate,m_dateStart.c_str(),DATESZ);
          }
          break;
     case STYPE_POPULARITY:
          if (*(m_searchStart.c_str()) != '\0') {
               setKey5();
          }
          else if (m_popStart == PS_FIRST) {
               memset(m_key.key5.numdls,0xff,NUMSZ-1);
          }
          else {
               memset(m_key.key5.numdls,0x00,NUMSZ-1);
          }
          break;
     case STYPE_KEYWORDS:
          {
               m_moreLow=(*m_searchStart.c_str() != '\0');
               m_moreHigh=true;
               flkwStatus rc
                    =m_KwdSearcher.Init(m_searchAllLibs ? NULL
                                                        : m_searchLib.libname
                                       ,m_searchStart.c_str()
                                       ,m_searchKeywords.c_str()
                                       ,&m_libMap);
               if (rc != FLKWS_OK) {
                    setKwdSrchError(rc);
               }
          }
          break;
     default:
          break;
     }
}

VOID
synListFiles::buildContext()            // build non-os list context
{
     if (m_listAll) {
          m_SynState=SYNSTATE_RESPONSE;
          return;
     }
     switch (m_searchType) {
     case STYPE_NAME:
          handleContext(m_libCount == 1 ? COMPLF : COMPFL);
          break;
     case STYPE_DATE:
          handleContext(m_libCount == 1 ? COMPLUF : COMPUF);
          break;
     case STYPE_POPULARITY:
          handleContext(COMPNLF);
          break;
     case STYPE_KEYWORDS:
          handleKeywordContext();
          break;
     default:
          ASSERT(FALSE);
     }
}

VOID
synListFiles::buildMap()                // build non-os map
{
     switch (m_searchType) {
     case STYPE_NAME:
          handleSearch(m_libCount == 1 ? COMPLF : COMPFL);
          break;
     case STYPE_DATE:
          handleDateSearch(m_libCount == 1 ? COMPLUF : COMPUF);
          break;
     case STYPE_POPULARITY:
          handlePopSearch(COMPNLF);
          break;
     case STYPE_KEYWORDS:
          handleKeywordSearch();
          break;
     default:
          ASSERT(FALSE);
     }
}

VOID
synListFiles::setMoreString(            // build more string from file data
string* str,                            // ptr to string to hold more string
const flfile& file)                     // file to build string from
{
     ASSERT(str != NULL);
     string& rStr=*str;

     switch (m_searchType) {
     case STYPE_NAME:
          rStr=file.filname;
          rStr+=STARTDELIM;
          rStr+=file.libname;
          break;
     case STYPE_POPULARITY:
          rStr=file.filname;
          rStr+=STARTDELIM;
          rStr+=file.libname;
          rStr+=STARTDELIM;
          rStr+=file.numdls;
          break;
     case STYPE_DATE:
          rStr=file.filname;
          rStr+=STARTDELIM;
          rStr+=file.libname;
          rStr+=STARTDELIM;
          rStr+=file.udate;
          break;
     default:
          ASSERT(FALSE);
     }
}

VOID
synListFiles::buildOSContext()          // build os list context
{
     if (m_listAll) {
          memset(&m_fb,0,sizeof(struct ffblk));
          m_SynState=SYNSTATE_RESPONSE;
          return;
     }
     CHAR fname[GCMAXFNM];
     if (!m_OSqueue.empty()) {
          struct ffblk fb;
          fb=m_OSqueue.front();
          fileparts(GCPART_FNAM,fb.ff_name,fname,GCMAXFNM);
          m_strLow=fname;
          if (m_previous > 0) {
               m_moreLow=true;
          }
          fb=m_OSqueue.back();
          fileparts(GCPART_FNAM,fb.ff_name,fname,GCMAXFNM);
          m_strHigh=fname;
          while (FindNextFile(m_fh,&m_findData)) {
               if (!(m_findData.dwFileAttributes&FILE_ATTRIBUTE_HIDDEN)
                && !(m_findData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
                && !(m_findData.dwFileAttributes&FILE_ATTRIBUTE_SYSTEM)) {
                    m_moreHigh=true;
                    break;
               }
          }
          memset(&m_fb,0,sizeof(struct ffblk));
     }
     m_SynState=SYNSTATE_RESPONSE;
}

VOID
synListFiles::handleContext(            // handle context for name,date,pop srchs
INT keynum)                             // btrieve key
{
     if (m_listAll || m_queue.empty()) {
          m_SynState=SYNSTATE_RESPONSE;
          return;
     }
     dfaSetBlk(flfdat);
     switch (m_contextState) {
     case INIT_LOW:
          {
               struct flfile File;
               File=m_queue.front();
               setMoreString(&m_strLow,File);
               m_ffile=File;
               updateKeys();
               //setInitialLib();
               m_contextState=READ_LOW;
          }
          // fall through intentional;
     case READ_LOW:
          {
               bool found;
               switch (m_searchType) {
               case STYPE_DATE:
               case STYPE_POPULARITY:
                    found=dfaQueryGT(&m_key,keynum);
                    break;
               default:
                    found=dfaQueryLT(&m_key,keynum);
               }
               if (found) {
                    dfaAbsRec(&m_ffile,keynum);
                    if (okToAdd(&m_ffile)) {
                         m_moreLow=true;
                         m_contextState=INIT_HIGH;
                    }
                    else if (m_bEndOfLib && keynum != COMPNLF) {
                         m_contextState=INIT_HIGH;
                    }
                    updateKeys();
                    m_bEndOfLib=false;
               }
               else {
                    m_contextState=INIT_HIGH;
               }
          }
          break;
     case INIT_HIGH:
          {
               struct flfile File;
               File=m_queue.back();
               setMoreString(&m_strHigh,File);
               m_ffile=File;
               updateKeys();
               //setInitialLib();
               m_contextState=READ_HIGH;
          }
          // fall through intentional;
     case READ_HIGH:
          {
               bool found;
               switch (m_searchType) {
               case STYPE_DATE:
               case STYPE_POPULARITY:
                    found=dfaQueryLT(&m_key,keynum);
                    break;
               default:
                    found=dfaQueryGT(&m_key,keynum);
               }
               if (found) {
                    dfaAbsRec(&m_ffile,keynum);
                    if (okToAdd(&m_ffile)) {
                         m_moreHigh=true;
                         m_SynState=SYNSTATE_RESPONSE;
                    }
                    else if (m_bEndOfLib && keynum != COMPNLF) {
                         m_SynState=SYNSTATE_RESPONSE;
                    }
                    updateKeys();
               }
               else {
                    m_SynState=SYNSTATE_RESPONSE;
               }
          }
          break;
     }
     memset(&m_ffile,0,sizeof(struct flfile));
     dfaRstBlk();
}

VOID
synListFiles::handleDateSearch(         // handle date search
INT key)
{
     memset(&m_ffile,0,sizeof(struct flfile));
     dfaSetBlk(flfdat);
     if (!m_started) {
          bool found=false;
          m_started=true;
          if (m_dateType == DTYPE_ABS || m_dateType == DTYPE_NONE) {
               if (m_listDirection&DIR_EQ) {
                    found=dfaQueryEQ(&m_key,key);
               }
               if (m_listDirection&DIR_GT && !found) {
                    found=dfaQueryLT(&m_key,key);
               }
               else if (m_listDirection&DIR_LT && !found) {
                    found=dfaQueryGT(&m_key,key);
               }
          }
          else if (m_listDirection&DIR_GT) {
               found=dfaQueryLE(&m_key,key);
          }
          else {
               found=dfaQueryGE(&m_key,key);
          }
          if (found) {
               dfaAbsRec(&m_ffile,key);
               if (okToAdd(&m_ffile)) {
                    if (m_listAll) {
                         m_SynState=SYNSTATE_RESPONSE;
                    }
                    else {
                         addToQueue(m_ffile);
                    }
                    ++m_curCount;
               }
               updateKeys();
          }
          else {
               m_SynSubState=SYNSUB_LISTCONTEXT;
          }
     }
     else {
          bool found;
          if (m_listDirection&DIR_GT) {
               found=dfaQueryLT(&m_key,key);
          }
          else {
               found=dfaQueryGT(&m_key,key);
          }
          if (found) {
               dfaAbsRec(&m_ffile,key);
               if (okToAdd(&m_ffile)) {
                    if (m_listAll) {
                         m_SynState=SYNSTATE_RESPONSE;
                    }
                    else {
                         addToQueue(m_ffile);
                    }
                    ++m_curCount;
               }
               else if (m_bEndOfLib) {
                    memset(&m_ffile,0,sizeof(struct flfile));
                    m_SynSubState=SYNSUB_LISTCONTEXT;
                    m_bEndOfLib=false;
               }
               updateKeys();
          }
          else {
               m_SynSubState=SYNSUB_LISTCONTEXT;
          }
     }
     dfaRstBlk();
     if (m_curCount >= m_listCount && !m_listAll) {
          m_SynSubState=SYNSUB_LISTCONTEXT;
     }
}


bool
synListFiles::handleContinuingList(     // handle continuing list in search
INT keynum)                             // btrieve key
{
     bool found=false;

     if ((m_searchType == STYPE_POPULARITY && m_popStart == PS_NONE)
      || (m_searchType == STYPE_NAME && m_nameStart == NS_NONE)) {
          if (m_listDirection&DIR_EQ) {
               found=dfaQueryEQ(&m_key,keynum);
          }
          if (!found
           && ((m_searchType == STYPE_NAME && m_listDirection&DIR_GT)
            || (m_searchType == STYPE_POPULARITY && m_listDirection&DIR_LT))) {
               found=dfaQueryGT(&m_key,keynum);
          }
          else if (!found
           && ((m_searchType == STYPE_NAME && m_listDirection&DIR_LT)
            || (m_searchType == STYPE_POPULARITY && m_listDirection&DIR_GT))) {
               found=dfaQueryLT(&m_key,keynum);
          }
     }
     return(found);
}

VOID
synListFiles::handleSearch(             // handle pop and name searches
INT keynum)                             // btrieve key
{
     memset(&m_ffile,0,sizeof(struct flfile));
     dfaSetBlk(flfdat);
     if (!m_started) {
          bool found;
          m_started=true;
          if (!(found=handleContinuingList(keynum))) {
               if (m_listDirection&DIR_GT) {
                    found=dfaQueryGE(&m_key,keynum);
               }
               else {
                    found=dfaQueryLE(&m_key,keynum);
               }
          }
          if (found) {
               dfaAbsRec(&m_ffile,keynum);
               if (okToAdd(&m_ffile)) {
                    if (m_listAll) {
                         m_SynState=SYNSTATE_RESPONSE;
                    }
                    else {
                         addToQueue(m_ffile);
                    }
                    ++m_curCount;
               }
               else if (m_bEndOfLib) {
                    memset(&m_ffile,0,sizeof(struct flfile));
                    m_SynSubState=SYNSUB_LISTCONTEXT;
                    m_bEndOfLib=false;
               }
               updateKeys();
          }
          else {
               m_SynSubState=SYNSUB_LISTCONTEXT;
          }
     }
     else {
          bool found;
          if (m_listDirection&DIR_GT) {
               found=dfaQueryGT(&m_key,keynum);
          }
          else {
               found=dfaQueryLT(&m_key,keynum);
          }
          if (found) {
               dfaAbsRec(&m_ffile,keynum);
               if (okToAdd(&m_ffile)) {
                    if (m_listAll) {
                         m_SynState=SYNSTATE_RESPONSE;
                    }
                    else {
                         addToQueue(m_ffile);
                    }
                    ++m_curCount;
               }
               else if (m_bEndOfLib) {
                    memset(&m_ffile,0,sizeof(struct flfile));
                    m_SynSubState=SYNSUB_LISTCONTEXT;
                    m_bEndOfLib=false;
               }
               updateKeys();
          }
          else {
               m_SynSubState=SYNSUB_LISTCONTEXT;
          }
     }
     dfaRstBlk();
     if (m_curCount >= m_listCount && !m_listAll) {
          m_SynSubState=SYNSUB_LISTCONTEXT;
     }
}

VOID
synListFiles::handlePopSearch(          // handle pop searches
INT keynum)                             // btrieve key
{
     memset(&m_ffile,0,sizeof(struct flfile));
     dfaSetBlk(flfdat);
     if (!m_started) {
          bool found;
          m_started=true;
          if (!(found=handleContinuingList(keynum))) {
               if (m_listDirection&DIR_GT) {
                    found=dfaQueryLE(&m_key,keynum);
               }
               else {
                    found=dfaQueryGE(&m_key,keynum);
               }
          }
          if (found) {
               dfaAbsRec(&m_ffile,keynum);
               if (okToAdd(&m_ffile)) {
                    if (m_listAll) {
                         m_SynState=SYNSTATE_RESPONSE;
                    }
                    else {
                         addToQueue(m_ffile);
                    }
                    ++m_curCount;
               }
               else if (m_bEndOfLib) {
                    memset(&m_ffile,0,sizeof(struct flfile));
                    m_SynSubState=SYNSUB_LISTCONTEXT;
                    m_bEndOfLib=false;
               }
               updateKeys();
          }
          else {
               m_SynSubState=SYNSUB_LISTCONTEXT;
          }
     }
     else {
          bool found;
          if (m_listDirection&DIR_GT) {
               found=dfaQueryLT(&m_key,keynum);
          }
          else {
               found=dfaQueryGT(&m_key,keynum);
          }
          if (found) {
               dfaAbsRec(&m_ffile,keynum);
               if (okToAdd(&m_ffile)) {
                    if (m_listAll) {
                         m_SynState=SYNSTATE_RESPONSE;
                    }
                    else {
                         addToQueue(m_ffile);
                    }
                    ++m_curCount;
               }
               else if (m_bEndOfLib) {
                    memset(&m_ffile,0,sizeof(struct flfile));
                    m_SynSubState=SYNSUB_LISTCONTEXT;
                    m_bEndOfLib=false;
               }
               updateKeys();
          }
          else {
               m_SynSubState=SYNSUB_LISTCONTEXT;
          }
     }
     dfaRstBlk();
     if (m_curCount >= m_listCount && !m_listAll) {
          m_SynSubState=SYNSUB_LISTCONTEXT;
     }
}

VOID
synListFiles::handleKeywordContext()    // build context for keyword searches
{
     // context is set up during the search
     if (!m_moreLow) {
          m_strLow="";
     }
     if (!m_moreHigh) {
          m_strHigh="";
     }
     m_SynState=SYNSTATE_RESPONSE;
}

VOID
synListFiles::handleKeywordSearch()     // do the keyword search
{
     flkwStatus rc=m_KwdSearcher.Find(m_listDirection,&m_ffile);
     switch (rc) {
     case FLKWS_FILE:
          if (!okToAdd(&m_ffile)) {
               memset(&m_ffile,0,sizeof(struct flfile));
               break;
          }
          if (m_listAll) {
               m_SynState=SYNSTATE_RESPONSE;
               ++m_curCount;
          }
          else {
               if (m_curCount >= m_listCount) {
                    m_SynSubState=SYNSUB_LISTCONTEXT;
                    break;
               }
               ++m_curCount;
               addToQueue(m_ffile);
               // we find one extra, to see if there are any more,
               // just don't add it to the queue
               if (m_curCount == 1) {   // bottom (GT) or top (LT)
                    if (m_listDirection&DIR_GT) {
                         m_strLow=m_KwdSearcher.GetState();
                    }
                    else {
                         m_strHigh=m_KwdSearcher.GetState();
                    }
               }
               else {
                    if (m_listDirection&DIR_GT) {
                         m_strHigh=m_KwdSearcher.GetState();
                    }
                    else {
                         m_strLow=m_KwdSearcher.GetState();
                    }
               }
          }
     case FLKWS_OK:
          // keep trying
          break;
     case FLKWS_DONE:
          if (!m_listAll) {
               if (m_listDirection&DIR_GT) {
                    m_moreHigh=false;
               }
               else {
                    m_moreLow=false;
               }
          }
          m_SynSubState=SYNSUB_LISTCONTEXT;
          break;
     default:
          setKwdSrchError(rc);
          break;
     }
}

VOID
synListFiles::updateKeys()              // update btrieve keys
{
     switch (m_searchType) {
     case STYPE_NAME:
          if (m_libCount == 1) {
               stlcpy(m_key.key1.filname,m_ffile.filname,FLFILENM);
               stlcpy(m_key.key1.libname,m_ffile.libname,FLNAMESZ);
          }
          else {
               stlcpy(m_key.key4.filname,m_ffile.filname,FLFILENM);
               stlcpy(m_key.key4.libkey,m_ffile.libname,FLNAMESZ);
          }
          break;
     case STYPE_DATE:
          if (m_libCount == 1) {
               stlcpy(m_key.key0.filname,m_ffile.filname,FLFILENM);
               stlcpy(m_key.key0.libname,m_ffile.libname,FLNAMESZ);
               stlcpy(m_key.key0.udate,m_ffile.udate,DATESZ);
          }
          else {
               stlcpy(m_key.key3.filname,m_ffile.filname,FLFILENM);
               stlcpy(m_key.key3.libkey,m_ffile.libname,FLNAMESZ);
               stlcpy(m_key.key3.udate,m_ffile.udate,DATESZ);
          }
          break;
     case STYPE_POPULARITY:
          stlcpy(m_key.key5.filname,m_ffile.filname,FLFILENM);
          stlcpy(m_key.key5.libkey,m_ffile.libname,FLNAMESZ);
          stlcpy(m_key.key5.numdls,m_ffile.numdls,NUMSZ);
     default:
          break;
     }
}


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

     if (m_err != ERR_NOERROR) {
          if (m_dnf == NULL) {
               rc=errorResponse(filErrorMap,PPFIX "/list/files/");
          }
          else if (m_dnf->process() == DNFEND) {
               rc=ACTHDONE;
          }
          return(rc);
     }
     if (m_dnf == NULL) {
          CHAR ch=m_searchAllLibs ? 'M' : m_searchLib.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 "/list/files/";
          strfname+=fnbuf;
          m_dnf=dnfCreateHandler(&bout,&filSuccessMap,strfname.c_str());
          delete [] fnbuf;
     }
     else {
          if (!m_listAll) {
               ::setListContextVars(m_listCount,m_listOrder,m_strLow.c_str()
                                   ,m_strHigh.c_str(),m_moreLow,m_moreHigh
                                   ,(m_curCount > 0) != 0,LTYPE_FILE);
          }
          else {
               ::setListContextVars(0,ORDER_DESC,"","",false,false
                                   ,(m_curCount > 0) != 0,LTYPE_FILE);
          }
          ::setSearchVars(m_searchType,m_searchWildcard,m_searchKeywords);
          if (m_searchLib.libname[0] != '\0') {
               ::setLibVars(&m_searchLib,m_usr);
          }
          if (m_searchLib.flags&FLGDOS) {
               if (m_fb.ff_name[0] != '\0') {
                    ::setLibVars(&m_searchLib,m_usr);
                    ::setOSFileVars(&m_fb,&m_searchLib,m_usr);
               }
          }
          else {
               if (m_ffile.filname[0] != '\0') {
                    if (!sameas(m_fllib.libname,m_ffile.libname)) {
                         struct fllib* libptr=libfind(m_ffile.libname);
                         ASSERT(libptr != NULL);
                         m_fllib=*libptr;
                    }
                    ::setLibVars(&m_fllib,m_usr);
                    ::setFileVars(&m_ffile,m_usr);
                    ::setFileDetailVars(m_strDesc,m_strDetail,m_strDetailLine,m_strDetailRaw,m_strDetailJS);
               }
          }
          if (!m_listAll || m_allDone)  {
               ::setNoList(m_curCount != 0,g_pszNoList);
          }
          switch(m_dnf->process()) {
          case DNFROWBEGIN:
               if (!m_listAll) {
                    if (!m_queue.empty()) {
                         if (m_listOrder == ORDER_ASCEND) {
                              m_ffile=m_queue.front();
                              m_queue.pop_front();
                         }
                         else {
                              m_ffile=m_queue.back();
                              m_queue.pop_back();
                         }
                    }
                    else if (!m_OSqueue.empty()) {
                         m_fb=m_OSqueue.front();
                         m_OSqueue.pop_front();
                    }
               }
               if (m_searchLib.flags&FLGDOS) {
                    if (*(m_fb.ff_name) == '\0') {
                         m_dnf->tableDone();
                         m_allDone=m_listAll;
                    }
               }
               else if (*(m_ffile.filname) == '\0') {
                    m_dnf->tableDone();
                    m_allDone=m_listAll;
               }
               else {
                    buildAllDetail(m_ffile.desc,&m_strDesc,&m_strDetail
                        ,&m_strDetailLine,&m_strDetailRaw,&m_strDetailJS);
               }
               break;
          case LSTITEM:
               break;
          case DNFROWEND:
               if (m_listAll) {
                    m_SynState=SYNSTATE_SYNTH;
               }
               else {
                    memset(&m_fb,0,sizeof(struct ffblk));
               }
               *(m_ffile.filname)='\0';
               break;
          case DNFEND:
               rc=ACTHDONE;
               break;
          default:
               break;
          }
     }
     return(rc);
}

bool
synListFiles::setNextLib()              // set next lib to search
{
     if (m_listDirection&DIR_GT) {
          m_iterLib++;
          if (m_iterLib == m_libMap.m_map.end()) {
               return(false);
          }
     }
     else {
          if (m_iterLib == m_libMap.m_map.begin()) {
               return(false);
          }
          m_iterLib--;
     }
     stlcpy(m_ffile.libname,((*m_iterLib).second).c_str(),FLNAMESZ);
     return(true);
}

VOID
synListFiles::setInitialLib()           // set initial lib to search in
{
     switch (m_searchType) {
     case STYPE_NAME:
          m_iterLib=m_libMap.m_map.find(STRSTORE(string(m_key.key1.libname)));
          if (m_iterLib == m_libMap.m_map.end()) {
               // find gt or lt
               if (m_listDirection != DIR_EQ) {
                    m_iterLib=m_libMap.m_map.begin();
                    while  (m_iterLib != m_libMap.m_map.end()) {
                         if ((*m_iterLib).second == m_key.key1.libname) {
                              break;
                         }
                         if (m_listDirection&DIR_GT) {
                              m_iterLib++;
                         }
                         else {
                              m_iterLib--;
                         }
                    }
               }
          }
          break;
     default:
          break;
     }
}

bool
synListFiles::okToAdd(                  // ok to add this file?
const struct flfile* pFile)             // file struct to add
{
     struct fllib* lib=libfind((pFile->libname));

     switch (m_searchType) {
     case STYPE_NAME:
          {
               LIBMAP::iterator iter;
               iter=m_libMap.m_map.find(STRSTORE(string(pFile->libname)));
               if (!m_searchAllLibs && iter == m_libMap.m_map.end()) {
                    if (m_SynSubState == SYNSUB_LISTCONTEXT) {
                         m_bEndOfLib=true;
                    }
                    return(false);
               }
          }
          if (m_searchWildcard.length() > 0
           && !compwild(const_cast<CHAR*>(m_searchWildcard.c_str()),
                        const_cast<CHAR*>(pFile->filname))) {
               return(false);
          }
          break;
     case STYPE_DATE:
     case STYPE_POPULARITY:
     case STYPE_KEYWORDS:
          {
               LIBMAP::iterator iter;
               iter=m_libMap.m_map.find(STRSTORE(string(pFile->libname)));
               if (!m_searchAllLibs && iter == m_libMap.m_map.end()) {
                    if ((m_SynSubState == SYNSUB_LISTCONTEXT)
                     || (m_searchType != STYPE_POPULARITY
                      && m_searchType != STYPE_DATE)) {
                         m_bEndOfLib=true;
                    }
                    return(false);
               }
          }
          break;
     }
     /* applies to all types of searches.. */
     if (lib == NULL || !ahHasLibKey(m_usr,lib,lib->keyreq)) {
          return(false);
     }
     if (sameas(NOTAPPED,pFile->udate) && !ahIsFlop(m_usr,lib)) {
          return(false);
     }
     // m_searchOnlyUnapproved should only be set if user has access
     if (m_searchOnlyUnapproved && !sameas(NOTAPPED,pFile->udate)) {
          return(false);
     }
     return(true);
}

VOID
synListFiles::addToQueue(               // add to file list queue
const struct flfile& ff)                // file to add
{
     if (m_listDirection&DIR_GT) {
          m_queue.push_back(ff);
     }
     else {
          m_queue.push_front(ff);
     }
}

VOID
synListFiles::addToOSQueue(             // add to os file list queue
const struct ffblk& ff)                 // file to add
{
     m_OSqueue.push_back(ff);
}


LISTORDER
synListFiles::LoadDftOrder(             // load default order
acthUserID* uid)                        // for this User-ID
{
     return(theFilAgent->LoadFileOrder(uid == NULL ? NULL : uid->userid()));
}

VOID
synListFiles::SaveDftOrder(             // save default order
acthUserID* uid,                        // for this User-ID
LISTORDER neworder)                     // new list order
{
     theFilAgent->SaveFileOrder(uid == NULL ? NULL : uid->userid(),neworder);
}

SEARCHTYPE
synListFiles::LoadDftSearch(            // load default search type
acthUserID* uid)                        // for this User-ID
{
     return(theFilAgent->LoadSearchType(uid == NULL ? NULL : uid->userid()));
}

VOID
synListFiles::SaveDftSearch(            // save default search type
acthUserID* uid,                        // for this User-ID
SEARCHTYPE neworder)                    // new search order
{
     theFilAgent->SaveSearchType(uid == NULL ? NULL : uid->userid(),neworder);
}

NAMESTART
synListFiles::GetDftNameStart()         // get default namestart
{
     return(m_listOrder == ORDER_ASCEND ? NS_FIRST : NS_LAST);
}

POPSTART
synListFiles::GetDftPopStart()          // get default popstart
{
     return(m_listOrder == ORDER_ASCEND ? PS_FIRST : PS_LAST);
}

DATETYPE
synListFiles::GetDftDateType()          // get default datestart
{
     return(m_listOrder == ORDER_ASCEND ? DTYPE_FIRST : DTYPE_LAST);
}

string
synListFiles::validateDate(             // validate a date
const CHAR* stg)                        // date to validate
{
     ASSERT(stg != NULL);
     string destString;

     CHAR* dateString=new CHAR[strlen(stg)+1];
     strcpy(dateString,stg);
     CHAR* ptr=dateString;
     while (*ptr != '\0') {
          if (ispunct(*ptr) && *ptr != '/') {
               *ptr='/';
          }
          ptr++;
     }
     USHORT theDate=dcdate(dateString);
     if (theDate == GCINVALIDDOT) {
          m_err=ERR_INVALIDPARAM;
          m_errtext="datestart";
     }
     else {
          destString=ddat2srt(theDate);
     }
     delete [] dateString;
     return(destString);
}

string
synListFiles::relativeDate(             // calculate relative date
const CHAR* stg)                        // date to calculate
{
     LONG daysago=atol(stg);
     USHORT tdy=today();
     INT year=ddyear(tdy);
     INT month=ddmon(tdy);
     INT day=ddmon(tdy);
     ASSERT(daysago <= 0);
     addDaysToDate(daysago,&year,&month,&day);
     CHAR buf[LDATSIZ];
     return(validateDate(prnDate(year,month,day,buf,LDATSIZ,PRND_MDYY ,'/')));
}

string
synListFiles::sinceLastScanDate()       // calculate last scan date
{
     string retval;
     if (m_usr == NULL) {
          m_dateType=DTYPE_FIRST;
     }
     else {
          if (m_fluser.cdayin == 0) {
               m_fluser.cdayin=cofdat(today());
          }
          USHORT lday=m_fluser.cdayin;
          if (m_dateType != DTYPE_FIRST) {
               retval=validateDate(ncdatel(datofc(lday)));
          }
     }
     return(retval);
}

VOID
synListFiles::setKey0()                 // set key 0
{
     if (m_searchStart.length() != 0
      && countchr(m_searchStart.c_str(),*STARTDELIM) == 2) {
          string strFname=getFileName(m_searchStart);
          stlcpy(m_key.key0.filname,strFname.c_str(),FLFILENM);
          string strLname=getLibName(m_searchStart);
          stlcpy(m_key.key0.libname,strLname.c_str(),FLNAMESZ);
          string strUDate=getUDate(m_searchStart);
          stlcpy(m_key.key0.udate,strUDate.c_str(),DATESZ);
          if (strFname.length() == 0
           || strLname.length() == 0
           || strUDate.length() == 0) {
              m_err=ERR_INVALIDPARAM;
              m_errtext="start";
          }
     }
     else {
          m_err=ERR_INVALIDPARAM;
          m_errtext="start";
     }
}

VOID
synListFiles::setKey1()                 // set key 1
{
     if (m_searchStart.length() != 0
      && countchr(m_searchStart.c_str(),*STARTDELIM) == 1) {
          string strFname=getFileName(m_searchStart);
          stlcpy(m_key.key1.filname,strFname.c_str(),FLFILENM);
          string strLname=getLibName(m_searchStart);
          stlcpy(m_key.key1.libname,strLname.c_str(),FLNAMESZ);
          if (strFname.length() == 0 || strLname.length() == 0) {
              m_err=ERR_INVALIDPARAM;
              m_errtext="start";
          }
     }
     else {
          m_err=ERR_INVALIDPARAM;
          m_errtext="start";
     }
}

VOID
synListFiles::setKey3()                 // set key 3
{
     if (m_searchStart.length() != 0
      && countchr(m_searchStart.c_str(),*STARTDELIM) == 2) {
          string strFname=getFileName(m_searchStart);
          stlcpy(m_key.key3.filname,strFname.c_str(),FLFILENM);
          string strLname=getLibName(m_searchStart);
          stlcpy(m_key.key3.libkey,strLname.c_str(),FLNAMESZ);
          string strUDate=getUDate(m_searchStart);
          stlcpy(m_key.key3.udate,strUDate.c_str(),DATESZ);
          if (strFname.length() == 0
           || strLname.length() == 0
           || strUDate.length() == 0) {
              m_err=ERR_INVALIDPARAM;
              m_errtext="start";
          }
     }
     else {
          m_err=ERR_INVALIDPARAM;
          m_errtext="start";
     }
}

VOID
synListFiles::setKey4()                 // set key 4
{
     if (m_searchStart.length() != 0
      && countchr(m_searchStart.c_str(),*STARTDELIM) == 1) {
          string strFname=getFileName(m_searchStart);
          stlcpy(m_key.key4.filname,strFname.c_str(),FLFILENM);
          string strLname=getLibName(m_searchStart);
          stlcpy(m_key.key4.libkey,strLname.c_str(),FLNAMESZ);
          if (strFname.length() == 0 || strLname.length() == 0) {
              m_err=ERR_INVALIDPARAM;
              m_errtext="start";
          }
     }
     else {
          m_err=ERR_INVALIDPARAM;
          m_errtext="start";
     }
}


VOID
synListFiles::setKey5()                 // set key 5
{
     if (m_searchStart.length() != 0) {
          string strFname=getFileName(m_searchStart);
          stlcpy(m_key.key5.filname,strFname.c_str(),FLFILENM);
          string strLname=getLibName(m_searchStart);
          stlcpy(m_key.key5.libkey,strLname.c_str(),FLNAMESZ);
          string strPop=getPop(m_searchStart);
          stlcpy(m_key.key5.numdls,strPop.c_str(),NUMSZ);
          if (strFname.length() == 0
           || strLname.length() == 0
           || strPop.length() == 0
           || countchr(m_searchStart.c_str(),*STARTDELIM) != 2) {
              m_err=ERR_INVALIDPARAM;
              m_errtext="start";
          }
     }
     else {
          m_err=ERR_INVALIDPARAM;
          m_errtext="start";
     }
}

VOID
synListFiles::setKwdSrchError(          // map keyword error to agent error
flkwStatus st)                          // keyword search status
{
     m_errtext="keywords";
     switch (st) {
     case FLKWS_LENGTH:
          m_err=ERR_KWDTOOLONG;
          break;
     case FLKWS_SYNTAX:
          m_err=ERR_KWDSYNTAX;
          break;
     case FLKWS_PARENS:
          m_err=ERR_KWDPARENS;
          break;
     case FLKWS_NOWORD:
          m_err=ERR_KWDNOWORD;
          m_errtext=m_KwdSearcher.GetMisc();
          break;
     case FLKWS_BADSTART:
          m_err=ERR_INVALIDPARAM;
          m_errtext="start";
          break;
     default:
          m_err=ERR_INVALIDPARAM;
          break;
     }
}

INT
synListFiles::translateError()          // translate err to mcv file op
{
     switch (m_err) {
     case ERR_INVALIDLIB:
          return(ERRLF03);
     case ERR_INVALIDPARAM:
          return(ERRLF02);
     case ERR_KWDTOOLONG:
          return(ERRLF18);
     case ERR_KWDSYNTAX:
          return(ERRLF19);
     case ERR_KWDPARENS:
          return(ERRLF20);
     case ERR_KWDNOWORD:
          return(ERRLF21);
     default:
          ASSERTM(FALSE,spr("Err: %d",m_err));
     }
     m_errtext=spr("%d",m_err);
     return(ERROOPS);
}

INT                                     //  number of occurances
countchr(                               // count num of spec. chars within str
const CHAR* str,                        //  str to check
CHAR ch)                                //  char to match
{
     INT cnt=0;

     ASSERT(str != NULL);
     while (*str != '\0') {
          if (*str == ch) {
               ++cnt;
          }
          ++str;
     }
     return(cnt);
}

const CHAR*                             //  found file name
getFDFileName(                          // get found file name
const WIN32_FIND_DATA& fd)              //  find data struct
{
     if (fd.cAlternateFileName[0] == '\0') {
          return(fd.cFileName);
     }
     else {
          return(fd.cAlternateFileName);
     }
}


