//
//  File:   hdsCore.cpp
//
//  Legal Notice:   This file is part of the HadronZoo C++ Class Library. Copyright 2025 HadronZoo Project (http://www.hadronzoo.com)
//
//  The HadronZoo C++ Class Library is free software: You can redistribute it, and/or modify it under the terms of the GNU Lesser General Public License, as published by the Free
//  Software Foundation, either version 3 of the License, or any later version.
//
//  The HadronZoo C++ Class Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
//  A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public License along with the HadronZoo C++ Class Library. If not, see http://www.gnu.org/licenses.
//
//  Description: Dissemino Web-Masters Management Facility
//
//  Resources such as pages, articles and include blocks have inherently unique and human readable identifiers such as pathname and title but internal operation
//  is enhanced by allocation of a unique numeric id. This is best done internally as it is a nuicence to have to allocate ids to these entities in the configs.
//  Instead, the human operator only needs to set the version number of each resource. This will be ver="1" in all cases to begin with but will be increased by
//  1 if editied.
//
//  It is important to understand that Dissemino makes a distinction between resorces that are explicitly defined in the configs and those that are derived from
//  other sources such as uploads from users. While the latter may amount to whole pages or articles to Dissemino they are meaningless binaries to be stored in
//  the database and given addresses accordingly. The regime herein described applies only to config defined resources.
//
//  To this end, Dissemino manages a series of files in the document root as follows:-
//
//  1) website.res.xml: This lists all config defined resources and adds the internally assigned id, the date and time stamp and the version to the pathname and
//  title. The 
//
//  2) website.$$.txt:  Where $$ in this case is the default language code. This file will contain a series of strings extracted from the currently applicable
//                      resources.
//
//  If ANY of the above files do not exist in the document root, Dissemino will take the configs as autorative and create a complete set of new files missing files from the configs
//  a veriety of reasons, it is these have practical limitations. In
//  particular, change over time
#include <iostream>
#include <fstream>
#include <unistd.h>
#include <stdarg.h>
#include <dirent.h>
#include <netdb.h>
#include <signal.h>
#include "hzErrcode.h"
#include "hzTokens.h"
#include "hzTextproc.h"
#include "hzDissemino.h"
using namespace std ;
/*
**  Variables
*/
//static    hdsNavtree  s_treeDataModel ;       //  Tree for object model display
extern  hzString    _dsmScript_tog ;            //  Navtree toggle script
extern  hzString    _dsmScript_loadArticle ;    //  Navtree load article script
extern  hzString    _dsmScript_navtree ;        //  Navtree script
static  hzString    s_cls_Config        = "config" ;        //  Class name of the Config class
static  hzString    s_mbr_Config_DATE   = "dtstamp" ;       //  Name of Resource member DATE
static  hzString    s_mbr_Config_PATH   = "relPath" ;       //  Name of Resource member DATE
static  hzString    s_rep_Config        = "configs" ;       //  Name of the Resource Object Repository
static  hzString    s_cls_Resource      = "resource" ;      //  Class name of the Resource class
static  hzString    s_mbr_Resource_DATE = "dtstamp" ;       //  Name of Resource member DATE
static  hzString    s_mbr_Resource_PATH = "relPath" ;       //  Name of Resource member DATE
static  hzString    s_mbr_Resource_MD5  = "resMD5" ;        //  Name of Resource member MD5
static  hzString    s_mbr_Resource_XML  = "rawXML" ;        //  Name of Resource member XML
static  hzString    s_mbr_Resource_HTM  = "rawHTML" ;       //  Name of Resource member HTM
static  hzString    s_mbr_Resource_Zip  = "zipHTML" ;       //  Name of Resource member HTM
static  hzString    s_bin_Resource      = "resourceBin" ;   //  Name of binary datum repository used by the Resource Object Repository
static  hzString    s_rep_Resource      = "resources" ;     //  Name of the Resource Object Repository
/*
**  Dissemino Application Container
*/
hdsSphere*  hdsSphere::GetInstance  (hzLogger& pLog)
{
    //  Category:   Dissemino System Initialization
    //
    //  Obtain the singleton hdsApp instance
    //
    //  Arguments:  1)  pLog    Pointer to an established logger to log config errors and events
    //
    //  Returns:    Pointer to the singleton HTML application
    //              NULL if the logger is not supplied
    _hzfunc("hdsSphere::GetInstance") ;
    if (_hzGlobal_Dissemino)
        hzwarn(E_SETONCE, "hdsApp is a singleton class") ;
    else
    {
        _hzGlobal_Dissemino = new hdsSphere() ;
        _hzGlobal_Dissemino->m_pLog = &pLog ;
    }
    return _hzGlobal_Dissemino ;
}
hzEcode hdsSphere::AddApplication
    (
    const hzDomain& domain,
    const hzString& baseDir,
    const hzString& rootFile,
    const hzString& sslPvtKey,
    const hzString& sslCert,
    const hzString& sslCertCA,
    uint32_t nPortSTD,
    uint32_t nPortSSL,
    uint32_t bOpFlags
    )
{
    //  Category:   Dissemino System Initialization
    //
    //  Add a Dissemino application
    //
    //  Argument:   appHost The application hostname e.g. www.mydomain.com. This will be supplied in the header of HTTP requests and is the means by which Dissemino identifies the
    //                      application to send the request to.
    //
    //  Returns:    E_DUPLICATE If the named application already exists
    //              E_OK        If the operation was successful
    _hzfunc("hdsSphere::AddApplication") ;
    hdsApp*     pApp ;  //  Dissemino application visible entity belongs to
    hzEcode     rc ;    //  Return code
    if (!domain || !baseDir || !rootFile)
        return hzerr(E_ARGUMENT, "domain=[%s] baseDir=[%s] rootFile=[%s]", *domain, *baseDir, *rootFile) ;
    if (m_AppsByHost.Exists(domain))
        return E_DUPLICATE ;
    pApp = hdsApp::GetInstance(*m_pLog) ;
    rc = pApp->InitApp(domain, baseDir, rootFile) ;
    if (rc == E_OK)
    {
        m_AppsByHost.Insert(domain, pApp) ;
        pApp->m_AppID = m_AppsByHost.Count() ;
        pApp->m_OpFlags |= bOpFlags ;
        pApp->m_SSL_PvtKey = sslPvtKey ;
        pApp->m_SSL_Cert = sslCert ;
        pApp->m_SSL_CertCA = sslCertCA ;
        pApp->m_nPortSTD = nPortSTD ;
        pApp->m_nPortSSL = nPortSSL ;
        m_AppsByID.Insert(pApp->m_AppID, pApp) ;
    }
    threadLog("Added Dissemino app %s with baseDir %s and root file %s\n", *domain, *baseDir, *rootFile) ;
    return rc ;
}
hdsApp* hdsSphere::GetApplication   (const hzString& domain)
{
    _hzfunc("hdsSphere::GetApplication(str)") ;
    return m_AppsByHost[domain] ;
}
hdsApp* hdsSphere::GetApplication   (uint32_t appId)
{
    _hzfunc("hdsSphere::GetApplication(int)") ;
    return m_AppsByID[appId] ;
}
/*
**  Dissemino Applications
*/
hdsApp::hdsApp  (void)
{
    //  Application logfile
    m_pLog = 0 ;
    //  Resources DB
    m_pClass_Resource = 0 ;
    m_pMbr_Resource_DATE = 0 ;
    m_pMbr_Resource_PATH = 0 ;
    m_pMbr_Resource_MD5 = 0 ;
    m_pMbr_Resource_XML = 0 ;
    m_pMbr_Resource_HTM = 0 ;
    m_pMbr_Resource_Zip = 0 ;
    m_pRepos_Resource = 0 ;
    m_pStore_Resource = 0 ;
    //  Config file DB
    m_pClass_CfgFile = 0 ;
    m_pMbr_CfgFile_DATE = 0 ;
    m_pMbr_CfgFile_PATH = 0 ;
    m_pRepos_CfgFile = 0 ;
    //  Application parameters
    m_MasterLogin = 0 ;
    m_MasterPage = 0 ;
    m_pDfltLang = 0 ;
    m_nPortSTD = 0 ;
    m_nPortSSL = 0 ;
    m_nLoadComplete = 0 ;
    m_OpFlags |= DS_APP_NORMFILE ;
}
hdsApp* hdsApp::GetInstance (hzLogger& pLog)
{
    //  Category:   Dissemino System Initialization
    //
    //  Create a hdsApp instance
    //
    //  Arguments:  1)  pLog    Pointer to an established logger to log config errors and events
    //
    //  Returns:    Pointer to the new Dissamino application
    _hzfunc("hdsApp::GetInstance") ;
    hdsApp*     pApp ;  //  Dissemino application visible entity belongs to
    pApp = new hdsApp() ;
    pApp->m_pLog = &pLog ;
    return pApp ;
}
hzEcode hdsApp::InitApp (const hzDomain& domain, const hzString& baseDir, const hzString& rootFile)
{
    //  Category:   Dissemino System Initialization
    //
    //  Sets the application name, the domain and base directories for the Dissemino application. These are as per the following arguments:-
    //
    //  Arguments:  1)  appname The application name. This must be unique as seen by the delta server
    //              2)  domain  The domain name the application will act as part or whole website for
    //              3)  baseDir The base directory. From this a number of directories including the document root, will be set
    //
    //  Returns:    E_SETONCE   If this function has already been called
    //              E_ARGUMENT  If any of the arguments are NULL
    //              E_FORMAT    If the domain name is not a valid domain
    //              E_NOTFOUND  If the base directory does not exist
    //              E_OK        If success
    _hzfunc("hdsApp::Init") ;
    if (m_Domain)
        return E_SETONCE ;
    if (!domain || !baseDir || !rootFile)
        return E_ARGUMENT ;
    m_Appname = domain ;
    m_Domain = domain ;
    m_BaseDir = baseDir ;
    m_RootFile = rootFile ;
    return E_OK ;
}
hzEcode hdsApp::InitResources   (void)
{
    //  Category:   Dissemino System Initialization
    //
    //  Set up both config file and resouce database for the application.
    _hzfunc("hdsApp::InitResources") ;
    hzMD5       valMD5 ;        //  MD5 value for resource
    hzString    valURL ;        //  Resource URL/Path
    hzString    cfgs ;          //  Config delta file
    uint32_t    fdate ;         //  Epoch date of config file
    uint32_t    n ;             //  Resource counter
    hzEcode     rc = E_OK ;     //  Return code
    //  Define class for config files
    if (!m_Datadir)
        return hzerr(E_NOINIT, "No data directory") ;
    threadLog("m_Configs Population %u\n", m_Configs.Count()) ;
    cfgs = m_Datadir ;
    cfgs += "/config.cache" ;
    m_Configs.DeltaSet(cfgs) ;
    m_Configs.DeltaOpen() ;
    threadLog("Opened file %s\n", *cfgs) ;
    threadLog("m_Configs Population %u\n", m_Configs.Count()) ;
    for (n = 0 ; n < m_Configs.Count() ; n++)
    {
        valURL = m_Configs.GetKey(n) ;
        fdate = m_Configs.GetObj(n) ;
        threadLog("Have config of %010u [%s]\n", fdate, *valURL) ;
    }
    //  Define class for resources
    if (!m_pClass_Resource)
    {
        if (rc == E_OK) m_pClass_Resource = new hdbClass(m_ADP, HDB_CLASS_DESIG_CFG) ;
        if (rc == E_OK) rc = m_pClass_Resource->InitStart(s_cls_Resource) ;
        if (rc == E_OK) rc = m_pClass_Resource->InitMember(s_mbr_Resource_DATE, "xdate",   HDB_MBR_POP_SINGLE_COMPULSORY) ;     //  Date of last update
        if (rc == E_OK) rc = m_pClass_Resource->InitMember(s_mbr_Resource_PATH, "string",  HDB_MBR_POP_SINGLE_COMPULSORY) ;     //  Resource URL
        if (rc == E_OK) rc = m_pClass_Resource->InitMember(s_mbr_Resource_MD5,  "hashMD5", HDB_MBR_POP_SINGLE_COMPULSORY) ;     //  MD5 of the resource config XML
        if (rc == E_OK) rc = m_pClass_Resource->InitMember(s_mbr_Resource_XML,  "binary",  HDB_MBR_POP_SINGLE_COMPULSORY) ;     //  Resource config XML (as previously accepted)
        if (rc == E_OK) rc = m_pClass_Resource->InitMember(s_mbr_Resource_HTM,  "binary",  HDB_MBR_POP_SINGLE_OPTIONAL) ;       //  Resource proforma HTML (as per the config XML)
        if (rc == E_OK) rc = m_pClass_Resource->InitMember(s_mbr_Resource_Zip,  "binary",  HDB_MBR_POP_SINGLE_OPTIONAL) ;       //  Zipped HTML if page is inactive
        if (rc == E_OK) rc = m_pClass_Resource->InitDone() ;
        if (rc == E_OK) rc = m_ADP.RegisterDataClass(m_pClass_Resource) ;
        if (rc == E_OK)
            m_pLog->Log("Registered resource class\n") ;
        else
        {
            m_pLog->Log("Could not register resource class\n") ;
            return rc ;
        }
        m_pMbr_Resource_DATE = m_pClass_Resource->GetMember(s_mbr_Resource_DATE) ;
        m_pMbr_Resource_PATH = m_pClass_Resource->GetMember(s_mbr_Resource_PATH) ;
        m_pMbr_Resource_MD5  = m_pClass_Resource->GetMember(s_mbr_Resource_MD5) ;
        m_pMbr_Resource_XML  = m_pClass_Resource->GetMember(s_mbr_Resource_XML) ;
        m_pMbr_Resource_HTM  = m_pClass_Resource->GetMember(s_mbr_Resource_HTM) ;
        m_pMbr_Resource_Zip  = m_pClass_Resource->GetMember(s_mbr_Resource_Zip) ;
    }
    //  Set up resources repository
    if (!m_pRepos_Resource)
    {
        if (rc == E_OK) m_pRepos_Resource = new hdbObjRepos(m_ADP) ;
        if (rc == E_OK) m_pStore_Resource = new hdbBinRepos(m_ADP) ;
        m_pLog->Log("Resource Repos %p, Binary %p\n", m_pRepos_Resource, m_pStore_Resource) ;
        rc = m_pStore_Resource->Init(s_bin_Resource, m_Datadir) ;
        if (rc != E_OK)
            { m_pLog->Log("Could not init resource binary datum repository\n") ; return rc ; }
        rc = m_pStore_Resource->Open() ;
        if (rc != E_OK)
            { m_pLog->Log("Could not open resource binary datum repository\n") ; return rc ; }
        rc = m_pStore_Resource->Integ(*m_pLog) ;
        if (rc != E_OK)
            { m_pLog->Log("Could not integrity check resource binary datum repository\n") ; return rc ; }
        if (rc == E_OK) rc = m_pRepos_Resource->InitStart(m_pClass_Resource, s_rep_Resource, m_Datadir, HDB_REPOS_CACHE) ;
        if (rc == E_OK) rc = m_pRepos_Resource->InitMbrIndex(s_mbr_Resource_PATH, false) ;
        if (rc == E_OK) rc = m_pRepos_Resource->InitDone() ;
        if (rc == E_OK) rc = m_pRepos_Resource->Open() ;
        if (rc == E_OK)
            m_pLog->Log("Initialized and opened resource repository\n") ;
        else
        {
            m_pLog->Log("Could not init/open resource repository\n") ;
            return rc ;
        }
    }
    //  Load the resources into the m_ResourceMD5 map
    rc = m_objResource.Init(m_pClass_Resource) ;
    if (rc != E_OK)
        m_pLog->Log("Could not init resource object\n") ;
    for (n = 0 ; n < m_pRepos_Resource->Count() ; n++)
    {
        //m_pResourceRepos->Fetchval(atom, 0, n) ;
        rc = m_pRepos_Resource->Fetch(m_objResource, n+1) ;
        if (rc != E_OK)
        {
            m_pLog->Log("Could not fetch resource item %d (err=%s)\n", n+1, Err2Txt(rc)) ;
            continue ;
        }
        //romid.m_ObjId = n ;
        m_objResource.GetMbrValue(valURL, m_pMbr_Resource_PATH) ;
        m_objResource.GetMbrValue(valMD5, m_pMbr_Resource_MD5) ;
        //m_ResourcesMD5.Insert(valURL, valMD5) ;
        m_pLog->Log("Inserted Resource %s %s\n", valMD5.Txt(), *valURL) ;
    }
    return rc ;
}
/*
**  USL (Universal String Label)
*/
#if 0
hzEcode hdsUSL::SetBlock    (uint32_t blkNo)
{
    //  Category:   Dissemino System Initialization
    //
    _hzfunc("hdsUSL::SetBlock") ;
    if (m_Value)        return E_SEQUENCE ;
    if (blkNo > 255)    return E_RANGE ;
    m_Value = USL_B_MARK ;
    m_Value |= (blkNo << 14) ;
    return E_OK ;
}
hzEcode hdsUSL::SetGroup    (uint32_t grpNo)
{
    //  Category:   Dissemino System Initialization
    //
    _hzfunc("hdsUSL::SetGroup") ;
    if (m_Value)        return E_SEQUENCE ;
    if (grpNo > 15)     return E_RANGE ;
    m_Value = USL_G_MARK ;
    m_Value |= (grpNo << 27) ;
    return E_OK ;
}
hzEcode hdsUSL::SetArticle  (const hdsUSL base, uint32_t artNo)
{
    //  Category:   Dissemino System Initialization
    //
    _hzfunc("hdsUSL::SetArticle") ;
    if (!(base.m_Value & USL_G_MARK))   return E_TYPE ;
    if (m_Value)                        return E_SEQUENCE ;
    if (artNo > 16383)                  return E_RANGE ;
    m_Value = base.m_Value ;
    m_Value |= (artNo << 14) ;
    return E_OK ;
}
hzEcode hdsUSL::SetPage (uint32_t pageNo)
{
    //  Category:   Dissemino System Initialization
    //
    _hzfunc("hdsUSL::SetPage") ;
    if (m_Value)        return E_SEQUENCE ;
    if (pageNo > 16383) return E_RANGE ;
    m_Value = USL_P_MARK ;
    m_Value |= (pageNo << 14) ;
    return E_OK ;
}
hzEcode hdsUSL::SetSubj (uint32_t subjNo)
{
    //  Category:   Dissemino System Initialization
    //
    _hzfunc("hdsUSL::SetSubj") ;
    if (m_Value)        return E_SEQUENCE ;
    if (subjNo > 16383) return E_RANGE ;
    m_Value = USL_S_MARK ;
    m_Value |= (subjNo << 14) ;
    return E_OK ;
}
hzEcode hdsUSL::SetBlockVE  (uint32_t veNo)
{
    //  Category:   Dissemino System Initialization
    //
    _hzfunc("hdsUSL::SetBlockVE") ;
    if (!(m_Value & USL_B_MARK))    return E_TYPE ;
    if (veNo & 0xfffffb00)          return E_RANGE ;
    m_Value |= veNo ;
    return E_OK ;
}
hzEcode hdsUSL::SetPageVE   (uint32_t veNo)
{
    //  Category:   Dissemino System Initialization
    //
    _hzfunc("hdsUSL::SetPageVE") ;
    if (!(m_Value & USL_P_MARK))    return E_TYPE ;
    if (veNo & 0xfffffb00)          return E_RANGE ;
    m_Value |= veNo ;
    return E_OK ;
}
hzEcode hdsUSL::SetVE_Pretext   (const hdsUSL base, uint32_t veNo)
{
    //  Category:   Dissemino System Initialization
    //
    _hzfunc("hdsUSL::SetVE_Pretext") ;
    if (!base.m_Value)
        return E_NOINIT ;
    if (veNo > 8191)
        return hzwarn(E_RANGE, "Attempting a VE number of %u on base of %s", veNo, *base) ;
    m_Value = base.m_Value ;
    m_Value |= (veNo << 1) ;
    m_Value |= USL_X_MASK ;
    return E_OK ;
}
hzEcode hdsUSL::SetVE_Content   (const hdsUSL base, uint32_t veNo)
{
    //  Category:   Dissemino System Initialization
    //
    _hzfunc("hdsUSL::SetVE_Content") ;
    if (!base.m_Value)
        return E_NOINIT ;
    if (veNo > 8191)
        return hzwarn(E_RANGE, "Attempting a VE number of %u on base of %s", veNo, *base) ;
    m_Value = base.m_Value ;
    m_Value |= (veNo << 1) ;
    return E_OK ;
}
hzEcode hdsUSL::SetByText   (const char* usl)
{
    //  Category:   Dissemino System Initialization
    //
    //  Set a USL by text value. The only source of the text value anticipated is during mass string import after an external language translation.
    _hzfunc("hdsUSL::SetByText") ;
    return E_OK ;
}
const char* hdsUSL::operator* (void) const
{
    _hzfunc("hdsUSL::operator const char*") ;
    char*       pBuf ;  //  Scratchpad buffer for text output
    uint32_t    co ;    //  Container number (from bits 08 thru 21 inclusive)
    uint32_t    ve ;    //  Visual entity number (from bits 22 thru 30 inclusive)
    pBuf = _thisfn.ScratchPad(32) ;
    co = (m_Value & USL_C_MASK) >> 14 ;
    ve = (m_Value & USL_V_MASK) >> 1 ;
    if (m_Value & USL_G_MARK)
    {
        if (m_Value & USL_X_MASK)
            sprintf(pBuf, "g%u.%u.p%u", (m_Value & USL_G_MASK)>>27, co, ve) ;
        else
            sprintf(pBuf, "g%u.%u.c%u", (m_Value & USL_G_MASK)>>27, co, ve) ;
        return pBuf ;
    }
    if (m_Value & USL_P_MARK)
    {
        if (!ve)
            sprintf(pBuf, "p%u", co) ;
        else
        {
            if (m_Value & USL_X_MASK)
                sprintf(pBuf, "p%u.p%u", co, ve) ;
            else
                sprintf(pBuf, "p%u.c%u", co, ve) ;
        }
        return pBuf ;
    }
    if (m_Value & USL_S_MARK)
    {
        sprintf(pBuf, "s%u", co) ;
        return pBuf ;
    }
    if (m_Value & USL_B_MARK)
    {
        if (!ve)
            sprintf(pBuf, "b%u", co) ;
        else
        {
            if (m_Value & USL_X_MASK)
                sprintf(pBuf, "b%u.p%u", co, ve) ;
            else
                sprintf(pBuf, "b%u.c%u", co, ve) ;
        }
        return pBuf ;
    }
    sprintf(pBuf, "?%u.%u", co, ve) ;
    return pBuf ;
}
hdsUSL::operator const char* (void) const
{
    return operator*() ;
}
#endif
hzEcode hdsApp::SetCookieName   (const hzString& cookieBase)
{
    //  Category:   Dissemino System Initialization
    //
    //  Sets the application name and base directories for the Dissemino application. These are as per the following arguments:-
    //
    //  Arguments:  1)  appname The application name. This must be unique as seen by the delta server
    //              2)  baseDir The base directory. From this a number of directories including the document root, will be set
    //
    //  Returns:    E_SETONCE   If this function has already been called
    //              E_ARGUMENT  If any of the arguments are NULL
    //              E_NOTFOUND  If the base directory does not exist
    //              E_OK        If success
    _hzfunc("hdsSphere::SetCookieName") ;
    if (!cookieBase)    return E_ARGUMENT ;
    if (m_CookieName)   return E_SETONCE ;
    hzChain     Z ;     //  For building cookie name
    const char* i ;     //  Iterator
    Z << "_hz_" ;
    for (i = *cookieBase ; *i ; i++)
    {
        if (*i > CHAR_SPACE)
            Z.AddByte(*i) ;
    }
    m_CookieName = Z ;
    Z.Clear() ;
    return E_OK ;
}
/*
**  Visual Entities
*/
static  uint32_t    s_absResource = 0 ;     //  Absoute resource id
hdsVE::hdsVE    (void)
{
    m_pApp = 0 ;
    m_Children = m_Sibling = 0 ;
    m_BgColor = 0 ;
    m_FgColor = 0 ;
    m_Access = 0 ;
    m_Line = 0 ;
    m_Indent = 0 ;
    m_nAttrs = 0 ;
    m_nChildren = 0 ;
    m_flagVE = 0 ;
    m_VID = 0 ;
}
hdsBlock::hdsBlock  (hdsApp* pApp)
{
    InitVE(pApp) ;
    //m_EID = ++s_absResource ;
    m_bScriptFlags = 0 ;
}
hdsPage::hdsPage    (hdsApp* pApp)
{
    m_pApp = pApp ;
    m_RID = ++s_absResource ;
    m_resAccess = 0 ;
    m_flagVE = 0 ;
    m_HitCount = 0 ;
    m_bScriptFlags = 0 ;
    m_BgColor = 0 ;
    m_Line = 0 ;
    m_Width = m_Height = m_Left = m_Top = 0 ;
}
hzEcode hdsVE::InitVE   (hdsApp* pApp)
{
    //  Category:   Dissemino System Initialization
    //
    _hzfunc("hdsVE::InitVE") ;
    if (!pApp)
        hzexit(E_CORRUPT, "%s: No Application supplied", *m_Tag) ;
    if (!pApp->m_AppID)
        return hzerr(E_ARGUMENT, "Supplied application has no app ID") ;
    if (m_pApp)
        return hzerr(E_DUPLICATE, "Duplicate call %p but already at %p", pApp, m_pApp) ;
    m_pApp = pApp ;
    m_pApp->m_arrVEs.Add(this) ;
    m_VID = m_pApp->m_arrVEs.Count() ;
    return E_OK ;
}
hzEcode hdsVE::SetSibling   (hdsVE* pSib)
{
    //  Category:   Dissemino System Initialization
    _hzfunc("hdsVE::SetSibling") ;
    if (!this)          { threadLog("ugh A\n") ; hzexit(E_CORRUPT, "No instance") ; }
    if (!pSib)          { threadLog("ugh a\n") ; hzexit(E_ARGUMENT, "No sibling supplied") ; }
    if (pSib == this)   { threadLog("ugh B\n") ; hzexit(E_CORRUPT, "%s: Attempt to set sibling of this to this", *m_Tag) ; }
    if (m_Sibling)      { threadLog("ugh C\n") ; hzexit(E_CORRUPT, "%s: Already have sibling", *m_Tag) ; }
    m_Sibling = pSib->m_VID ;
    return E_OK ;
}
hzEcode hdsVE::AddChild (hdsVE* pChild)
{
    //  Category:   Dissemino System Initialization
    //
    //  Add a child to this visible entity.
    //
    //  Arguments:  1)  pChild  The pointer to the child visible entity
    //
    //  Returns:    E_OK
    _hzfunc("hdsVE::AddChild") ;
    hdsVE*  pVE ;   //  Visible entity pointer
    if (!pChild)
        hzexit(E_ARGUMENT, "%s: Null child supplied to Visible Entity", *m_Tag) ;
    if (m_flagVE & VE_COMPLETE)
        hzexit(E_SEQUENCE, "%s: Visible Entity is already complete, cannot add child %s", *m_Tag, *pChild->m_Tag) ;
    if (pChild == this)
        hzexit(E_CORRUPT, "%s: Child is same as parent", *m_Tag) ;
    if (!pChild->m_VID)
        hzexit(E_CORRUPT, "%s: Supplied child (%s) has no ID", *m_Tag, *pChild->m_Tag) ;
    //  Child VEs?
    if (!m_Children)
    {
        //  The current VE has no children so add the first
        m_Children = pChild->m_VID ;
    }
    else
    {
        //  Run through existing children and set the sibling of the last child to the new child. Note that if the child VE we are adding is already among existing children, we note
        //  the duplicate and return without adding.
        pVE = Children() ;
        if (pVE->Sibling())
        {
            for (; pVE && pVE->Sibling() ; pVE = pVE->Sibling())
            {
                if (pVE == pChild)
                    return E_OK ;
            }
        }
        if (!pVE)
            hzexit(E_CORRUPT, "Last child already had a sibling value") ;
        pVE->m_Sibling = pChild->m_VID ;
        //pVE->SetSibling(pChild) ;
    }
    m_nChildren++ ;
    return E_OK ;
}
hdsVE*  hdsVE::Children (void) const
{
    //  Return first child of the current VE
    if (!m_Children)
        return 0 ;
    if (!m_pApp)
        return 0 ;
    return m_pApp->m_arrVEs[m_Children-1] ;
}
hdsVE*  hdsVE::Sibling  (void) const
{
    if (!m_Sibling)
        return 0 ;
    if (!m_pApp)
        return 0 ;
    return m_pApp->m_arrVEs[m_Sibling-1] ;
}
hzEcode hdsVE::AddAttr  (const hzString& name, const hzString& value)
{
    //  Category:   Dissemino System Initialization
    //
    //  Add an attribute to the visible entity
    //
    _hzfunc("hdsVE::AddAttr") ;
    const char*     i ;             //  Attribute value iterator
    hzString        pcntEnt ;       //  Percent entity
    //hzFixPair     pa ;            //  Attribute
    hzPair          pa ;            //  Attribute
    hzEcode         rc = E_OK ;     //  Return code
    if (!m_pApp)
        return E_CORRUPT ;
    //  Check attribute for impact on flags: Does it make the tag active?
    for (i = *value ; *i ; i++)
    {
        if (*i != CHAR_PERCENT)
            continue ;
        if (i[1] == CHAR_PERCENT)
            { i++ ; continue ; }
        if (IsAlpha(i[1]) && i[2] == CHAR_COLON)
        {
            if (m_pApp->IsPcEnt(pcntEnt, i))
                m_flagVE |= VE_AT_ACTIVE ;
            else
                { rc = E_SYNTAX ; break ; }
            i += 2 ;
        }
    }
    //  Add the attribute
    pa.name = name ;
    pa.value = value ;
    m_nAttrs++ ;
    rc = m_pApp->m_VE_attrs.Insert(m_VID, pa) ;
    return rc ;
}
hzEcode hdsBlock::AddVisent (hdsVE* pChild)
{
    //  Category:   Dissemino System Initialization
    //
    _hzfunc("hdsBlock::AddVisent") ;
    uint32_t    nV ;    //  VE iterator
    if (!pChild)                    hzexit(E_ARGUMENT, "%s: Null child supplied to block", *m_Refname) ;
    if (m_flagVE & VE_COMPLETE)     hzexit(E_SEQUENCE, "%s: Block is already complete, cannot add more entities", *m_Refname) ;
    if (pChild == this)             hzexit(E_CORRUPT, "%s: Case 1 Child is include block pointing to itself", *m_Refname) ;
    if (m_VID == pChild->m_VID)     hzexit(E_CORRUPT, "%s: Case 2 Child is include block pointing to itself", *m_Refname) ;
    //  Run through array looking for duplicates
    for (nV = 0 ; nV < m_VEs.Count() ; nV++)
    {
        if (m_VEs[nV] == pChild)
            hzexit(E_CORRUPT, "%s: Child is already in include block", *m_Refname) ;
    }
    //  threadLog("ADDED CHILD %s TO XINCLUDE %p %s\n", *pChild->m_Tag, this, *m_Refname) ;
    m_VEs.Add(pChild) ;
    return E_OK ;
}
hzEcode hdsArticleStd::AddVisent    (hdsVE* pChild)
{
    //  Category:   Dissemino System Initialization
    //
    _hzfunc("hdsArticle::AddVisent") ;
    uint32_t    nV ;    //  VE iterator
    if (!pChild)
        hzexit(E_ARGUMENT, "%s: Null child supplied to article", *m_Title) ;
    if (m_flagVE & VE_COMPLETE)
        hzexit(E_SEQUENCE, "%s: Article is already complete, cannot add %s", *m_Title, *pChild->m_Tag) ;
    //  Run through array looking for duplicates
    for (nV = 0 ; nV < m_VEs.Count() ; nV++)
    {
        if (m_VEs[nV] == pChild)
            hzexit(E_CORRUPT, "%s: Child %s is already in include block", *m_Title, *pChild->m_Tag) ;
    }
    //  threadLog("ADDED CHILD %s TO ARTICLE %p %s\n", *pChild->m_Tag, this, *m_Refname) ;
    m_VEs.Add(pChild) ;
    return E_OK ;
}
hzEcode hdsArticleStd::AddFormref   (hdsFormref* pFR)
{
    //  Category:   Dissemino System Initialization
    //
    if (!m_pFormref)
        { m_pFormref = pFR ; m_flagVE |= VE_CT_ACTIVE ; return E_OK ; }
    if (m_pFormref != pFR)
        return E_DUPLICATE ;
    return E_OK ;
}
void    hdsApp::_assignveids_r  (hdsVE* pVE, uint32_t& flags, uint32_t& nId)
{
    //  Category:   Dissemino System Initialization
    //
    //  Recursive support function to non recursive AssignVEids() function
    //  This will assign numeric 'positional' identifiers to a VE according to incidence within a page, article or block
    //
    //  Arguments:  1)  pVE     Pointer to the visible entity
    //              2)  flags   Page activity flags
    //              3)  nId     ID so far
    //
    //  Returns:    None
    _hzfunc("hdsApp::_assignveids_r") ;
    hdsVE*  pSub ;      //  Visible entity (child)
    hzEcode rc ;        //  Return code
    if (!pVE)
        hzexit(E_CORRUPT, "No VE supplied") ;
    //  Set flags so if any VE active, host becomes active
    if (pVE->m_flagVE & VE_AT_ACTIVE)   flags |= VE_AT_ACTIVE ;
    if (pVE->m_flagVE & VE_PT_ACTIVE)   flags |= VE_PT_ACTIVE ;
    if (pVE->m_flagVE & VE_CT_ACTIVE)   flags |= VE_CT_ACTIVE ;
    //  Ensure no repeat
    if (pVE->m_flagVE & VE_EVALUATED)
        return ;
    pVE->m_flagVE |= VE_EVALUATED ;
    //  Assing uid
    nId++ ;
    //  Handle pre-text
    if (pVE->m_strPretext)
        pVE->m_strPretext.DelWhiteTrail() ;
    if (pVE->m_strContent)
        pVE->m_strContent.DelWhiteTrail() ;
    //  if (pVE->m_strPretext)
    //  {
    //  }
    //  Handle content
    //  if (pVE->m_strContent)
    //  {
    //  }
    //  Recurse
    for (pSub = pVE->Children() ; pSub ; pSub = pSub->Sibling())
    {
        nId++ ;
        _assignveids_r(pSub, flags, nId) ;
    }
}
void    hdsApp::AssignVisentIDs (hzArray<hdsVE*>& listVE, uint32_t& flags)
{
    //  Category:   Dissemino System Initialization
    //
    //  As the assignment of positional identifiers to a VE is a recursive process, this function acts as the root.
    //
    //  Arguments:  1)  LVE     List of visual entities
    //              2)  flags   Cumulative page operational flags
    //              3)  base    HTML/Internet application base name
    //
    //  Returns:    None
    _hzfunc("hdsApp::AssignVEids(2)") ;
    hzList<hdsVE*>::Iter    vi ;    //  Visible entity iterator
    hdsVE*      pVE ;               //  Visible entity pointer
    uint32_t    n ;                 //  Visible entity iterator
    uint32_t    nId = 0 ;           //  Visible entity id. Set by _assignveids()
    m_pLog->Out("Processing Visual Entities: Flags are %x\n", flags) ;
    for (n = 0 ; n < listVE.Count() ; n++)
    {
        pVE = listVE[n] ;
        _assignveids_r(pVE, flags, nId) ;
    }
}
hdsFldspec::hdsFldspec  (void)
{
    m_pType = 0 ;
    nSize = 0 ;
    nCols = nRows = 0 ;
    nFldSeq = nExpSeq = 0 ;
    //  _hzGlobal_numFldspecs++ ;
}
hdsFldspec::~hdsFldspec (void)
{
    //  _hzGlobal_numFldspecs-- ;
}
hdsFldspec& hdsFldspec::operator=   (const hdsFldspec& op)
{
    m_pType = op.m_pType ;
    m_Refname = op.m_Refname ;
    m_Desc = op.m_Desc ;
    m_Default = op.m_Default ;
    valJS = op.valJS ;
    m_Source = op.m_Source ;
    htype = op.htype ;
    valJS = op.valJS ;
    nSize = op.nSize ;
    nCols = op.nCols ;
    nRows = op.nRows ;
    nFldSeq = op.nFldSeq ;
    nExpSeq = op.nExpSeq ;
    return *this ;
}
hdsHtag::hdsHtag        (hdsApp* pApp)  { InitVE(pApp) ; }
hdsXtag::hdsXtag        (hdsApp* pApp)  { InitVE(pApp) ; }
hdsXdiv::hdsXdiv        (hdsApp* pApp)  { InitVE(pApp) ; }
hdsCond::hdsCond        (hdsApp* pApp)  { InitVE(pApp) ; }
hdsNavbar::hdsNavbar    (hdsApp* pApp)  { InitVE(pApp) ; }
hdsArtref::hdsArtref    (hdsApp* pApp)  { InitVE(pApp) ; m_Show = 0 ; }
hdsField::hdsField      (hdsApp* pApp)
{
    _hzfunc("hdsField::hdsField") ;
    InitVE(pApp) ;
    m_pClass = 0 ;
    m_pMem = 0 ;
}
hdsField::~hdsField     (void)
{
    m_pClass = 0 ;
    m_pMem = 0 ;
}
hdsFormref::hdsFormref  (hdsApp* pApp)  { InitVE(pApp) ; m_ClsId = 0 ; }
hdsFormref::~hdsFormref (void)          {}
hdsButton::hdsButton    (hdsApp* pApp)  { InitVE(pApp) ; }
hdsButton::~hdsButton   (void)          {} 
hdsRecap::hdsRecap      (hdsApp* pApp)  { InitVE(pApp) ; }
hdsDirlist::hdsDirlist  (hdsApp* pApp)
{
    InitVE(pApp) ;
    m_pNone = m_pHead = m_pFoot = 0 ;
    m_Width = m_Height = m_nRows = m_Order = 0 ;
}
hdsDirlist::~hdsDirlist (void)
{
    m_pNone = m_pHead = m_pFoot = 0 ;
}
hdsTable::hdsTable      (hdsApp* pApp)
{
    InitVE(pApp) ;
    m_pRepos = 0 ;
    m_pNone = m_pHead = m_pFoot = 0 ;
    m_nWidth = m_nHeight = m_nRows = 0 ;
    m_bEdit = false ;
}
hdsTable::~hdsTable (void)
{
    m_pRepos = 0 ;
    m_pNone = m_pHead = m_pFoot = 0 ;
}
hzEcode hdsApp::AddUserType (const hzString& utname)
{
    //  Category:   Dissemino System Initialization
    //
    //  Reserve the user type name and set an access code mask for that user type.
    //
    //  Argument:   utname  The user type name
    //
    //  Returns:    E_DUPLICATE If the user type name has already been added to the collection of known user types for the application (m_UserTypes).
    //              E_OK        If the new user type name is added and the aceess mask set.
    _hzfunc("hdsApp::AddUserType") ;
    uint32_t    utype ;     //  User type
    uint32_t    x ;         //  Indexes iterator
    if (m_UserTypes.Exists(utname))
        return E_DUPLICATE ;
    //  Set use access code
    utype = 1 ;
    for (x = 0 ; x < m_UserTypes.Count() ; x++)
        utype *= 2 ;
    m_UserTypes.Insert(utname, utype) ;
    m_pLog->Out("Added USER TYPE %s access %d\n", *utname, utype) ;
    return E_OK ;
}
uint32_t    hdsApp::_calcAccessFlgs (hzString& a)
{
    //  Category:   Dissemino System Initialization
    //
    //  Determine access flags on the basis of user. No user or a user of 'public' means in the case of a resource, that the resource will always be
    //  visible in the browser unless rendered invisible by other means. A user of 'any' means that the user has to be logged in but it does not in
    //  what capacity. Any other setting must nessesarily be a user type and in this case, only users logged in as that type would see the resource.
    //  If more than one type of user is to be authorized then this has to be stated as user="typeA|typeB"
    //
    //  The display logic as applied to resources is always as follows:-
    //      - If the access value of (the resource) is 0 then show
    //      - If the access value is non-zero then the access value of the user must match on a bitwise AND
    //
    //  To facilitate this public will produce an access value of 0, any (or all) an access value of 0x7fffffff and specific user type will each set
    //  one bit.
    //  
    //  Arguments:  1)  a   The access directive
    //
    //  Returns:    Number being the bitwise access flags
    _hzfunc("hdsApp::_calcAccessFlgs") ;
    hzArray<hzString>   types ;     //  User types in specification
    //hdsUsertype   ut ;            //  User types
    hzString    S ;             //  Working string
    uint32_t    x ;             //  User type selector
    uint32_t    z = 0 ;         //  Calculated net access flags
    if (a == "public")  return ACCESS_PUBLIC ;
    if (a == "none")    return ACCESS_NOBODY ;
    if (a == "admin")   return ACCESS_ADMIN ;
    if (a == "any")     return ACCESS_MASK ;
    if (a.Contains(CHAR_OR))
    {
        SplitStrOnChar(types, a, '|') ;
        for (z = x = 0 ; x < types.Count() ; x++)
        {
            S = types[x] ;
            if (!m_UserTypes.Exists(S))
                return 0xffffffff ;
            //ut = m_UserTypes[S] ;
            //z |= ut.m_Access ;
            z |= m_UserTypes[S] ;
        }
    }
    else
    {
        if (!m_UserTypes.Exists(a))
            return 0xffffffff ;
        //ut = m_UserTypes[a] ;
        //z = ut.m_Access ;
        z = m_UserTypes[a] ;
    }
    m_pLog->Out("set access for %s to %d\n", *a, z) ;
    return z ;
}
#if 0
hzEcode hdsApp::_insertPage (hdsPage* pPage, const char* fn)
{
    //  Category:   Dissemino System Initialization
    //
    //  Unified insert page operation to add pages to various page collections belonging in the hdsApp
    //
    //  Arguments:  1)  pPage   The page to insert
    //              2)  fn      The caller function name
    //
    //  Returns:    E_SYNTAX    If there is a syntax error
    //              E_OK        If no errors occured
    _hzfunc("hdsApp::_insertPage") ;
    hzChain     Z ;         //  For building page HTML (inactive pages only)
    hzChain     X ;         //  For zipping page HTML if applicable
    hdsUSL      usl ;       //  Temp string
    hzString    strVal ;    //  Temp string
    hzEcode     rc = E_OK ; //  Return code
    //  By path
    if (rc == E_OK)
    {
        rc = m_ResourcesPath.Insert(pPage->m_Url, pPage) ;
        if (rc != E_OK)
            m_pLog->Out("%s. Could not insert page url=%s title=%s into m_ResourcesPath\n", fn, *pPage->m_Url, *pPage->m_Title) ;
    }
    //  By name
    if (rc == E_OK)
    {
        rc = m_ResourcesName.Insert(pPage->m_Title, pPage) ;
        if (rc != E_OK)
            m_pLog->Out("%s. Could not insert page url=%s title=%s into m_ResourcesName\n", fn, *pPage->m_Url, *pPage->m_Title) ;
    }
    //usl = *pPage->m_USL ;
    //usl = pPage->m_USL ;
    AssignVisentIDs(pPage->m_VEs, pPage->m_flagVE, usl) ;
    /*  CHANGE
    if (pPage->m_flagVE & VE_ACTIVE)
        m_pLog->Out("Assigned VE ids. Page %s (%s, %s) deemed ACTIVE\n", *usl, *pPage->m_Title, *pPage->m_Url) ;
    else
    {
        m_pLog->Out("Assigned VE ids. Page %s (%s, %s) deemed INACTIVE\n", *usl, *pPage->m_Title, *pPage->m_Url) ;
        pPage->EvalHtml(Z, m_pDfltLang) ;
        Gzip(X, Z) ;
        strVal = Z ; m_pDfltLang->m_rawHTML.Insert(pPage->m_USL, strVal) ;
        strVal = X ; m_pDfltLang->m_zipHTML.Insert(pPage->m_USL, strVal) ;
    }
    */
    if (pPage->m_flagVE & VE_ACTIVE)
        m_pLog->Out("Assigned VE ids. Page %d (%s, %s) deemed ACTIVE\n", usl, *pPage->m_Title, *pPage->m_Url) ;
    else
        m_pLog->Out("Assigned VE ids. Page %d (%s, %s) deemed INACTIVE\n", usl, *pPage->m_Title, *pPage->m_Url) ;
    pPage->EvalHtml(Z) ;
    Gzip(X, Z) ;
    pPage->m_rawHTML = Z ;
    pPage->m_zipHTML = X ;
    //  End of change
    return rc ;
}
#endif
/*
**  User Sessions
*/
hdsInfo::hdsInfo    (void)
{
    m_pTree = 0 ;
    //m_pObjects = 0 ;
    m_pObj = 0 ;
    m_pMisc = 0 ;
    m_Access = 0 ;
    m_SubId = 0 ;
    m_UserId = 0 ;
    m_CurrObj = 0 ;
    m_UserRepos = 0 ;
    m_CurrRepos = 0 ;
    m_CurrClass = 0 ;
}
hdsInfo::~hdsInfo   (void)
{
    delete m_pTree ;
    delete m_pObj ;
}
hzEcode hdsInfo::ObjectAssert   (const hzString& objKey, const hdbClass* pClass)
{
    //  Category:   Dissemino Operation
    //
    //  Assert (create if not found), the required hdbObject
    //
    //  Arguments:  1)  objKey      The application name for the hdbObject instance
    //              2)  classname   The object host class
    //
    //  Returns:    E_CORRUPT   If the class does not exist or the objKey exists but for a different class
    //              E_OK        If the user session either has or can add the object
    hzList<hdbObject*>::Iter    objI ;  //  Object iterator
    //  const hdbClass* pClass ;        //  Host class of object
    hdbObject*      pObj_test ;     //  Test object pointer
    if (!m_Objects.Count())
    {
        m_pObj = new hdbObject() ;
        m_pObj->Init(pClass) ;
        if (objKey)
            m_pObj->SetName(objKey) ;
        m_Objects.Add(m_pObj) ;
        return E_OK ;
    }
    m_pObj = 0 ;
    for (objI = m_Objects ; objI.Valid() ; objI++)
    {
        pObj_test = objI.Element() ;
        if (pObj_test->ObjKey() != objKey)
            continue ;
        m_pObj = pObj_test ;
        break ;
    }
    if (!m_pObj)
    {
        m_pObj = new hdbObject() ;
        m_pObj->Init(pClass) ;
        if (objKey)
            m_pObj->SetName(objKey) ;
        m_Objects.Add(m_pObj) ;
    }
    return E_OK ;
}
hdbObject*  hdsInfo::ObjectSelect   (const hzString& objKey)
{
    //  Category:   Dissemino Operation
    //
    //  Return a pointer to an already asserted hdbObject instance
    //
    //  Argument:   objKey  The application name for the hdbObject instance
    //
    //  Returns:    Pointer to the hdbObject if it has been asserted.
    //              Null otherwise.
    hzList<hdbObject*>::Iter    objI ;  //  Object iterator
    hdbObject*  pObj_test ;     //  Test object pointer
    m_pObj = 0 ;
    for (objI = m_Objects ; objI.Valid() ; objI++)
    {
        pObj_test = objI.Element() ;
        if (pObj_test->ObjKey() != objKey)
            continue ;
        m_pObj = pObj_test ;
        break ;
    }
    return m_pObj ;
}
hzEcode hdsInfo::ObjectClose    (const hzString& objKey)
{
    //  Category:   Dissemino Operation
    //
    //  Remove the hdbObject from the user session
    //
    //  Argument:   objKey  The application name for the hdbObject instance
    //
    //  Returns:    E_NOTFOUND  If the named object does not exist in the user session
    //              E_OK        If the named object was removed
    return E_OK ;
}
hzEcode hdsApp::AddCIFunc   (hzEcode (*pFunc)(hzHttpEvent*), const hzString path, uint32_t access, HttpMethod eMethod)
{
    //  Category:   Dissemino System Initialization
    //
    //  Add a function that effects a Dissemino page to the application's resource map. In this case only a path is available and not a resource name so only the m_ResourcesPath
    //  map is aggregated.
    //
    //  Arguments:  1)  pFunc   Pointer to the function. This must return hzEcode and accept a hzHttpEvent pointer as its only argument
    //              2)  path    The 'page' path the function is associated with
    //              3)  access  The access level the website user is expected to have to access the resource
    //              4)  method  Either HTTP_GET (if the function shows a page) or HTTP_POST if the function acts as form handler 
    //
    //  Returns:    E_DUPLICATE If the path is already in use
    //              E_OK        If the operation was successful
    _hzfunc("hdsApp::AddCIFunc") ;
    hdsCIFunc*      pCIF ;          //  C-Interface function
    hdsResource*    pDupRes ;       //  For illegal dupliacte reporting, existing article by name
    if (m_ResourcesPath.Exists(path))
    {
        pDupRes = m_ResourcesPath[path] ;
        hzerr(E_DUPLICATE, "Duplicate resource (%s) previous path %s\n", *path, *pDupRes->m_Url) ;
        return E_DUPLICATE ;
    }
    pCIF = new hdsCIFunc() ;
    pCIF->m_Url = path ;
    pCIF->m_pFunc = pFunc ;
    pCIF->m_resAccess = access ;
    m_ResourcesPath.Insert(path, pCIF) ;
    return E_OK ;
}
hzEcode hdsApp::SetLoginPost    (const hzString& post, const hzString& fail, const hzString& auth, const hzString& resume)
{
    //  Category:   Dissemino System Initialization
    //
    //  Add the login POST URL. This 
    m_LoginPost = post ;        //  The URL to which login form submissions must be posted
    m_LoginFail = fail ;        //  The URL the user will be directed to in event of username/password mismatch
    m_LoginAuth = auth ;        //  The URL the user will be directed to in event of successful authentication
    m_LoginResume = resume ;    //  The URL the user will be directed to in event of successful session resumption
    return E_OK ;
}
#if 0
hzEcode hdsApp::SetLoginAJAX    (const hzString& cmd)
{
    m_LoginAJAX = cmd ;         //  The URL to which AJAX login form submissions must be posted
    return E_OK ;
}
#endif