// // File: hdsConfig.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. //
#include <iostream> #include <fstream>
#include <unistd.h> #include <stdarg.h> #include <dirent.h> #include <netdb.h> #include <signal.h>
#include "hzErrcode.h" #include "hzDissemino.h"
using namespace std ;
global hzMapS<hzString,uint32_t> _hzGlobal_JS_Events ;
//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 = "resXML" ; // Name of Resource member XML //static hzString s_mbr_Resource_HTM = "resHTML" ; // 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
void InitJS_Events (void) { if (_hzGlobal_JS_Events.Count()) return ;
hzString S ; // For storing JS event uint32_t n = 0 ; // Event number
S = "onpageshow" ; _hzGlobal_JS_Events.Insert(S, n++) ; // Page has completed loading
S = "onchange" ; _hzGlobal_JS_Events.Insert(S, n++) ; // An HTML element has been changed S = "onclick" ; _hzGlobal_JS_Events.Insert(S, n++) ; // The user clicks an HTML element S = "onmouseover" ; _hzGlobal_JS_Events.Insert(S, n++) ; // The user moves the mouse over an HTML element S = "onmouseout" ; _hzGlobal_JS_Events.Insert(S, n++) ; // The user moves the mouse away from an HTML element S = "onkeydown" ; _hzGlobal_JS_Events.Insert(S, n++) ; // The user pushes a keyboard key S = "onload" ; _hzGlobal_JS_Events.Insert(S, n++) ; // The browser has finished loading the page }
/* ** SECTION 1: Minor Config Read Functions */
hzEcode hdsApp::_readRgxType (hzXmlNode* pN) { // Category: Minor Config Read Functions // // The <rgxtype> tag defines an APPDEF data type, and add it to the available data types for HDB use. An APPDEF data type is a simple regular expression that constrains string // values to a particular format, that is of meaning to the application. It is acknowledged that the treatment of regular expressions by the HDB, is not comprehensive. // // The <rgxtype> attributes name the datatype, set the maximum length, and set out the regex. // // Arguments: 1) pN Pointer to XML node <rgxType> // // Returns: E_SYNTAX In the event of incorrect parameters // E_OK If the field type parameters are valid
_hzfunc("hdsApp::_readRgxType") ; hzAttrset ai ; // Attribute iterator hdbRgxtype* pType ; // Fldtype hzString name ; // Name of new data type hzString regex ; // Controlling expression hzString limit ; // Size limit uint32_t max ; // Size limit hzEcode rc = E_OK ; // Return code
if (!pN) Fatal("No node supplied\n") ; if (!pN->NameEQ("rgxtype")) Fatal("Wrong call") ;
// Type parameters (name) for (ai = pN ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("typename")) name = ai.Value() ; else if (ai.NameEQ("regex")) regex = ai.Value() ; else if (ai.NameEQ("limit")) limit = ai.Value() ; else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <rgxtype> tag: Bad param (%s=%s)\n", pN->Fname(), pN->Line(), ai.Name(), ai.Value()) ; } }
if (!name) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <rgxtype>: No data type name supplied\n", pN->Fname(), pN->Line()) ; } if (!regex) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <rgxtype>: No regex supplied\n", pN->Fname(), pN->Line()) ; }
if (!limit) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <rgxtype>: No size limit supplied\n", pN->Fname(), pN->Line()) ; } else { max = atol(*limit) ; if (!max) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <rgxtype>: No size limit could be established\n", pN->Fname(), pN->Line()) ; } }
if (m_ADP.GetDatatype(name)) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <rgxtype>: Already have data type %s\n", pN->Fname(), pN->Line(), *name) ; }
// Type subtags if (rc == E_OK) { pType = new hdbRgxtype() ; pType->SetTypename(name) ;
rc = m_ADP.RegisterRegexType(pType) ; m_pLog->Log("File %s Line %d: Added %s\n", pN->Fname(), pN->Line(), pType->txtType()) ; }
return rc ; }
#if 0 hzEcode hdsApp::_readInitstate (hzXmlNode* pN) { // Category: Minor Config Read Functions // // Read the <initstate> tag. This is only applied in the event of Dissemino being called with the -newData command line argument. The tag has subtags of // <newdataCSV> which name repositories and files to be loaded into them. The upload will be incremental rather than a truncation // // Arguments: 1) pN Pointer to XML node <initstate> // // Returns: E_SYNTAX In the event of incorrect parameters // E_OK If the <initstate> parameters are valid
_hzfunc("hdsApp::_readInitstate") ;
const hdbClass* pClass_host ; // Host (repository) class const hdbMember* pMbr_csv ; // Data class member of CSV class const hdbMember* pMbr_host ; // Data class member of Repository class
//hdsLoad ld ; // Load command hzAttrset ai ; // Attribute iterator hzXmlNode* pN1 ; // Class member subnodes hzString rep ; // Named repository hzString cls ; // Load data command uint32_t memNo ; // Member number uint32_t nMatches ; // Number of member matches hzEcode rc = E_OK ; // Return code
// Check arguments if (!pN) Fatal("No node supplied\n") ;
// Process <initstate> tag for (pN1 = pN->GetFirstChild() ; rc == E_OK && pN1 ; pN1 = pN1->Sibling()) { ld.Clear() ;
if (pN1->NameEQ("newdataCSV")) { for (ai = pN1 ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("repos")) rep = ai.Value() ; else if (ai.NameEQ("class")) cls = ai.Value() ; else if (ai.NameEQ("load")) ld.m_Filepath = ai.Value() ; else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <newdataCSV> Illegal attribute (%s=%s)\n", pN->Fname(), pN1->Line(), ai.Name(), ai.Value()) ; break ; } }
// Check that filepath, repos and if supplied the class exists and if so add to app's initstate stack if (!ld.m_Filepath) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <newdataCSV> No source data file named\n", pN->Fname(), pN1->Line()) ; break ; } if (!rep) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <newdataCSV> No repository named\n", pN->Fname(), pN1->Line()) ; break ; }
ld.m_pRepos = m_ADP.GetObjRepos(rep) ; if (!ld.m_pRepos) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <newdataCSV> Named repository %s not declared\n", pN->Fname(), pN->Line(), *rep) ; break ; } pClass_host = ld.m_pRepos->Class() ;
if (!cls) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <newdataCSV> No source data class named\n", pN->Fname(), pN1->Line()) ; break ; } ld.m_pClass = m_ADP.GetPureClass(cls) ; if (!ld.m_pClass) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <newdataCSV> Named class %s not defined\n", pN->Fname(), pN->Line(), *cls) ; break ; }
/* ** Now check for commonality between members. There must be at least member in the guest class which matches (on both name and data type) to a member of the host class ** and of the matched members, at least one must serve as a unique index into the host repository. */
for (memNo = 0 ; memNo < ld.m_pClass->MbrCount() ; memNo++) { pMbr_csv = ld.m_pClass->GetMember(memNo) ;
// Check the CSV class member is not a subclasses if (pMbr_csv->Basetype() == BASETYPE_CLASS) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <newdataCSV> Named CSV class %s has subclass member %s\n", pN->Fname(), pN->Line(), *cls, pMbr_csv->txtName()) ; break ; }
// Look the CSV member up in the host class pMbr_host = pClass_host->GetMember(pMbr_csv->strName()) ; if (pMbr_host) { if (pMbr_host->Basetype() != pMbr_csv->Basetype()) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <newdataCSV> CSV class member %s conflicts on type\n", pN->Fname(), pN->Line(), pMbr_csv->txtName()) ; break ; } nMatches++ ; } }
if (!nMatches) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <newdataCSV> Named CSV class %s has no member matches in repository %s\n", pN->Fname(), pN1->Line(), *cls, pClass_host->txtType()) ; }
if (rc == E_OK) m_InitstateLoads.Add(ld) ; continue ; }
rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <initstate> Illegal subtag %s\n", pN->Fname(), pN1->Line(), pN1->txtName()) ; }
m_pLog->Log("Completed Initstate Directive\n") ; return rc ; } #endif
hzEcode hdsApp::_readScript (hzXmlNode* pN) { // Category: Minor Config Read Functions // // Read in a JaveScript from an <xscript> tag and place the script in m_rawScripts (if it does not already exist) // // Arguments: 1) pN Current XML node expected to be <xscript> tag // // Returns: E_SYNTAX If there is a syntax error // E_OK If no errors occured
_hzfunc("hdsApp::_readScript") ;
ifstream is ; // For reading in script file (if applicable) hzChain Z ; // Script content hzChain X ; // Script content (zipped) hzAttrset ai ; // Attribute iterator hzString name ; // Name of script hzString fname ; // Filename of script (if applicable) hzString S ; // Temp string hzEcode rc = E_OK ; // Return code
if (!pN) Fatal("No node supplied\n") ; if (!pN->NameEQ("xscript")) Fatal("Wrong call\n") ;
for (ai = pN ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("name")) name = ai.Value() ; else if (ai.NameEQ("file")) fname = ai.Value() ; else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <xscript>: Invalid param (%s=%s)\n", pN->Fname(), pN->Line(), ai.Name(), ai.Value()) ; } }
if (!name) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <xscript>: No name supplied\n", pN->Fname(), pN->Line()) ; } if (m_rawScripts.Exists(name)) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <xscript>: Name %s in use\n", pN->Fname(), pN->Line(), *name) ; }
if (!fname) Z = pN->m_fixContent ; else { is.open(*fname) ; if (is.fail()) { rc = E_OPENFAIL ; m_pLog->Log("File %s Line %d <xcript> File %s not opened\n", pN->Fname(), pN->Line(), *fname) ; } else { Z << is ; is.close() ; } }
if (!Z.Size()) { m_pLog->Log("File %s Line %d <xcript> No content\n", pN->Fname(), pN->Line()) ; return E_NODATA ; }
S = Z ; m_rawScripts.Insert(name, S) ; Gzip(X, Z) ; S = X ; m_zipScripts.Insert(name, S) ;
m_pLog->Log("Added script %s of %d bytes (%d zipped)\n", *name, Z.Size(), X.Size()) ;
return rc ; }
hzEcode hdsApp::_readSiteLangs (hzXmlNode* pN) { // Category: Minor Config Read Functions // // Read in a site language directive. This comprises the whole set of languages the site will support. The directive starts with a <siteLangusges> tag and // names each language with a <language> tag. These in turn comprise the language code, the image for the display flag and the language name // // Arguments: 1) pN Current XML node expected to be <siteLangauges> tag // // Returns: E_SYNTAX If there is a syntax error // E_OK If no errors occured
_hzfunc("hdsApp::_readSiteLangs") ;
hzAttrset ai ; // Attribute iterator hzXmlNode* pN1 ; // For <subject> tags hdsLang* pLang ; // Supported language hzString code ; // For language code hzString name ; // For language name (in default language e.g. 'German') hzString natv ; // For language name (in target language e.g. 'Duetsch') hzString imgf ; // For language flag image hzEcode rc = E_OK ; // Return code
if (!pN) Fatal("No node supplied\n") ; if (!pN->NameEQ("siteLanguages")) Fatal("File %s Line %d Expected <siteLangauges> tag. Got <%s>\n", pN->Fname(), pN->Line()) ;
for (ai = pN ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("default")) m_DefaultLang = ai.Value() ; else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d. Illegal <siteLanguages> attribute (%s=%s)\n", pN->Fname(), pN1->Line(), ai.Name(), ai.Value()) ; } }
if (!m_DefaultLang) { rc=E_NOINIT; m_pLog->Log("File %s Line %d. <siteLanguages> No default language specified\n", pN->Fname(), pN1->Line()) ; }
for (pN1 = pN->GetFirstChild() ; rc == E_OK && pN1 ; pN1 = pN1->Sibling()) { if (!pN1->NameEQ("language")) { m_pLog->Log("File %s Line %d. <%s> Illegal. Only <language> can be a subtag of <siteLanguages>\n", pN->Fname(), pN1->Line(), pN1->txtName()) ; rc = E_SYNTAX ; continue ; }
// Page attributes name = code = imgf = (char*)0 ;
for (ai = pN1 ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("code")) code = ai.Value() ; else if (ai.NameEQ("name")) name = ai.Value() ; else if (ai.NameEQ("native")) natv = ai.Value() ; else if (ai.NameEQ("flag")) imgf = ai.Value() ; else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d. Illegal <language> attribute (%s=%s)\n", pN->Fname(), pN1->Line(), ai.Name(), ai.Value()) ; } }
if (!name) { rc=E_NOINIT; m_pLog->Log("File %s Line %d. <language> No language name supplied\n", pN->Fname(), pN1->Line()) ; } if (!natv) { rc=E_NOINIT; m_pLog->Log("File %s Line %d. <language> No native language name supplied\n", pN->Fname(), pN1->Line()) ; } if (!code) { rc=E_NOINIT; m_pLog->Log("File %s Line %d. <language> No language code supplied\n", pN->Fname(), pN1->Line()) ; } if (!imgf) { rc=E_NOINIT; m_pLog->Log("File %s Line %d. <language> No language image file supplied\n", pN->Fname(), pN1->Line()) ; }
if (rc != E_OK) continue ;
pLang = m_Languages[code] ;
if (!pLang) { pLang = new hdsLang() ; pLang->m_Code = code ; pLang->m_flag = imgf ; pLang->m_name = name ; pLang->m_natv = natv ;
m_Languages.Insert(pLang->m_Code, pLang) ; m_pLog->Log("File %s Line %d. <language> INSERTED New Language\n", pN->Fname(), pN1->Line(), *pLang->m_Code) ; } else { pLang->m_Code = code ; pLang->m_flag = imgf ; pLang->m_name = name ; pLang->m_natv = natv ; }
if (pLang->m_name == m_DefaultLang) m_pDfltLang = pLang ; }
if (!m_pDfltLang) { rc = E_NOINIT; m_pLog->Log("File %s Line %d. <siteLanguages> No Default language\n", pN->Fname(), pN->Line()) ; }
return rc ; }
hzEcode hdsApp::_readNav (hzXmlNode* pN) { // Category: Minor Config Read Functions // // Read in <navigation> tag and its set of <subject> tags. These set the order for the subject headings for a navbar pull down menu // // Arguments: 1) pN Current XML node expected to be <navigation> tag // // Returns: E_SYNTAX If there is a syntax error // E_OK If no errors occured
_hzfunc("hdsApp::_readNav") ;
hzAttrset ai ; // Attribute iterator hzXmlNode* pN1 ; // For <subject> tags //hdsSubject* pSubj ; // Page subject hzString subj ; // For subject name hzEcode rc = E_OK ; // Return code
if (!pN) Fatal("No node supplied\n") ;
ai = pN ; if (ai.Valid()) { m_pLog->Log("File %s Line %d. <navigation> does not require attributes.\n", pN->Fname(), pN->Line()) ; return E_SYNTAX ; }
m_pLog->Log("File %s Line %d. <navigation> directive\n", pN->Fname(), pN->Line()) ;
for (pN1 = pN->GetFirstChild() ; pN1 ; pN1 = pN1->Sibling()) { if (!pN1->NameEQ("subject")) { m_pLog->Log("File %s Line %d. <%s> Illegal. Only <subject> is allowed as a subtag of <navigation>\n", pN->Fname(), pN1->Line(), pN1->txtName()) ; rc = E_SYNTAX ; continue ; }
// Page attributes for (ai = pN1 ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("name")) subj = ai.Value() ; else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d. Illegal <subject> attribute (%s=%s)\n", pN->Fname(), pN1->Line(), ai.Name(), ai.Value()) ; } }
if (rc != E_OK) continue ;
if (!m_setPgSubjects.Exists(subj)) m_pLog->Log("File %s Line %d. WARNING Duplicate subject [%s] ignored\n", pN->Fname(), pN->Line(), *subj) ; else { m_setPgSubjects.Insert(subj) ; m_lstPgSubjects.Add(subj) ; m_pLog->Log("File %s Line %d. Added subject %s\n", pN->Fname(), pN->Line(), *subj) ; } #if 0 pSubj = m_setPgSubjects[subj] ;
if (pSubj) m_pLog->Log("File %s Line %d. WARNING Duplicate subject [%s] ignored\n", pN->Fname(), pN->Line(), *subj) ; else { pSubj = new hdsSubject() ; pSubj->subject = subj ;
m_setPgSubjects.Insert(pSubj->subject, pSubj) ; m_vecPgSubjects.Add(pSubj) ; //pSubj->m_USL.SetSubj(m_setPgSubjects.Count()) ; m_pLog->Log("File %s Line %d. Added subject %s\n", pN->Fname(), pN->Line(), *subj) ; } #endif }
return rc ; }
hzEcode hdsApp::_readCSS (hzXmlNode* pN) { // Category: Minor Config Read Functions // // Process the singleton <xstyle> tag. This tag is the same as a HTML style tag except that the style definitions can all be in the XML config file(s) instead of a .css file. // The original plan was twofold; To ensure there was only one CSS resource for the website instead of many, thereby reducing demand on the server AND at some future point to // manage the styles so that warnings could be generated if a style was redundant or did not exist. This latter objective has yet to be implimented, largely because CSS has // undergone significant evolution since the <xstyle> tag was concocted and style management does not have a high priority. // // The tag has been considered for deprecation but this is unlikely. It has become an established Dissemino 'habit'. // // Arguments: 1) pN Pointer to XML node <xstyle> // // Returns: E_SYNTAX In the event of incorrect parameters // E_OK If the <xstyle> parameters are valid
_hzfunc("hdsApp::_readCSS") ;
hzAttrset ai ; // Attribute iterator
if (!pN) Fatal("No node supplied\n") ;
if (m_namCSS) { m_pLog->Log("File %s Line %d Only one stylesheet allowed\n", pN->Fname(), pN->Line()) ; return E_SYNTAX ; }
if (!pN->NameEQ("xstyle")) { m_pLog->Log("File %s Line %d Expected <xstyle> got <%s>\n", pN->Fname(), pN->Line(), pN->txtName()) ; return E_SYNTAX ; }
if (pN->GetFirstChild()) { m_pLog->Log("File %s Line %d <xstyle> tag should not have sub-tags\n", pN->Fname(), pN->Line()) ; return E_SYNTAX ; }
// The <style> tag should define a stylesheet that can be stored as a page in it's own right. It has a single attribute of name which must not // conflict with any of the pages. The page produced (the stylesheet) must nessesarily be public (accesseble to all) for (ai = pN ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("name")) m_namCSS = ai.Value() ; else { m_pLog->Log("ile %s Line %d: <xstyle> Illegal attr (%s=%s)\n", pN->Fname(), pN->Line(), ai.Name(), ai.Value()) ; return E_SYNTAX ; } }
if (!m_namCSS) { m_pLog->Log("ile %s Line %d: <xstyle> requires a name sttribute\n", pN->Fname(), pN->Line()) ; return E_SYNTAX ; }
m_txtCSS << "<style>\n<!--\n" ;
if (!pN->GetFirstChild()) m_txtCSS << pN->m_fixContent ;
m_txtCSS << "-->\n</style>\n" ; Gzip(m_zipCSS, m_txtCSS) ;
return E_OK ; }
hzEcode hdsApp::_readInclude (hzXmlNode* pN, hdsVE* parent, uint32_t nLevel) { // Category: Minor Config Read Functions // // The <xinclude> tag describes a block of HTML which can subsequently be included in webpages and form responses. <xinclude> is a legal subtag of <webappCfg> only. It may not // appear in a page definition. Within an <xpage> tag, <xblock name="blockname"/> names the block of tags to be included. // // Note that virtually all tags that are legal within an <xpage> tag, are also legal within an <xinclude> tag. This function is thus very similar to the _readPage() function. // // Arguments: 1) pN Pointer to XML node <xinclude> // 2) parent Parent visible entity // 3) nLevel Node level // // Returns: E_SYNTAX In the event of incorrect parameters // E_OK If the <xinclude> parameters are valid
_hzfunc("hdsApp::_readInclude") ;
_tagArg tga ; // Tag argument for _readTag() hzAttrset ai ; // Attribute iterator hzXmlNode* pN1 ; // Current XML node hdsVE* thisVE ; // Current visual entity hdsVE* newVE ; // Subordinate visual entity hdsBlock* pIncl ; // This include block hzString name ; // Name of block //hdsUSL usl ; // Temp string for USL hzEcode rc = E_OK ; // Return code
if (!pN) Fatal("No node supplied\n") ; if (!pN->NameEQ("xinclude")) { m_pLog->Log("File %s Line %d Expected <xinclude> got <%s>\n", pN->Fname(), pN->Line(), pN->txtName()) ; return E_SYNTAX ; }
m_pLog->Log("Level %d Node %s File %s Line %d\n", nLevel, pN->txtName(), pN->Fname(), pN->Line()) ;
// The attr will be the name of the form to which the handler applies for (ai = pN ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("name")) name = ai.Value() ; else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <xinclude> Illegal attr %s=%s\n", pN->Fname(), pN->Line(), ai.Name(), ai.Value()) ; } }
if (!name) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d Reading <xinclude> tag: No name supplied\n", pN->Fname(), pN->Line()) ; }
if (m_Includes.Exists(name)) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d Reading <xinclude> tag: %s already exists\n", pN->Fname(), pN->Line(), *name) ; }
if (rc != E_OK) return rc ;
thisVE = pIncl = new hdsBlock(this) ; thisVE->m_Line = pN->Line() ; thisVE->m_Indent = pN->Level() ; thisVE->m_Tag = pN->txtName() ; pIncl->m_Refname = name ; //pIncl->m_USL.SetBlock(m_Includes.Count()) ; m_pLog->Log("File %s Line %d Inserting xinclude %s\n", pN->Fname(), pN->Line(), *pIncl->m_Refname) ; m_Includes.Insert(pIncl->m_Refname, pIncl) ;
for (pN1 = pN->GetFirstChild() ; rc == E_OK && pN1 ; pN1 = pN1->Sibling()) { tga.m_pCaller = *_fn ; newVE = _readTag(&tga, pN1, pIncl->m_bScriptFlags, 0, 0) ;
if (!newVE) rc = E_SYNTAX ; else { m_pLog->Log("added child %s to xinclude %s\n", *newVE->m_Tag, *pIncl->m_Refname) ; pIncl->AddVisent(newVE) ; } }
if (rc != E_OK) return rc ;
//usl = pIncl->m_USL ; //AssignVisentIDs(pIncl->m_VEs, pIncl->m_flagVE, usl) ;
// if (pIncl->m_flagVE & VE_ACTIVE) // m_pLog->Log("Assigned VE ids. Include Block %s deemed ACTIVE\n", *usl) ; // else // m_pLog->Log("Assigned VE ids. Include Block %s deemed INACTIVE\n", *usl) ;
pIncl->Complete() ;
return rc ; }
hdsVE* hdsApp::_readTag (hdsApp::_tagArg* tga, hzXmlNode* pN, uint32_t& bScrFlags, hdsVE* parent, uint32_t level) { // Category: Minor Config Read Functions // // Support function to the following:- // // 1) _readInclude() which reads the <xinclude> tag to create blocks of tags that can be included in pages and articles. // 2) _readDirlist() which reads the <xdirlist> tag to define how a listing of directory entries should be presented. // 3) _readTable() which reads the <xtable> tag to define how aselection of objects in a repository should be presented. // 5) _readFormDef() which reads the <xformDef> tag to create a form definition. // 5) _readPage() which defines a page // 6) _readArticle() which defines an article // // All the above functions expect to process a mix of Dissemino and supportive HTML tags. Certain Dissemino tags are of particular importance to particular functions but since // the tags are mixed, these are commonly parented by ordinary HTML tags. This means a recursive support function of some form is required to process the mix of tags on behalf // of the above functions. Furthermore, many of the Dissemino tags are also only supportive and their use is widely permitted. This means the range of tags a recursive support // functions would have to handle, would be extensive. This would mean the recursive support functions would themselves be extensive. // // In some respects, there would be greater clarity if each of the six functions in the above list had their own recursive support function. If this were the approach however, // all the recursive support functions would be extensive and similar to each other, thereby undermining clarity. This function was written to merge recursive tag processing // in order to avoid such verbosity. // // Note the recusion is limited in the case of particular tags. This is where the function called to process the tag, is expected to process the entire set // of sub-tags and calls _readTag() in order to acheive this. For example, an <xformDef> tag results in a call to _readFormDef() but before this, a flag is // set to block recursion of <xformDef> sub-tags within this invokation of this function. The _readFormDef() function will separately invoke this function // to process all the sub-tags and return having completed a form definition. It would not make sense for the same sub-tags to be processed again. // // Arguments: 1) pN The current XML node // 2) bScrFlags Script flags - set if the presence of a tag in a page implies the page must have a script // 3) pPage The page in which the tag resides // 4) pFormdef If the tag falls within a <xformDef> this will be the form definition in progress. // 6) parent The parent visible entity // // Returns: Pointer to diagram visual entity
_hzfunc("hdsApp::_readTag") ;
hzAttrset ai ; // Attribute iterator hzXmlNode* pN1 ; // Subtag probe hdsVE* thisVE = 0 ; // Visible entity hdsVE* newVE = 0 ; // Subtag visible entity hdsRecap* pRecap = 0 ; // Google recaptcha hdsButton* pButt = 0 ; // Dissemino form button hdsXdiv* pXdiv = 0 ; // Dissemino user-status dependent tag set hdsCond* pCond = 0 ; // Dissemino value dependent tag set hdsNavbar* pNavbar = 0 ; // Dissemino Navigation pull-down menu hdsHtag* pHtag = 0 ; // Standard HTML tag hdsXtag* pXtag = 0 ; // Language support tag hdsBlock* pIncl = 0 ; // Included block of tags hdsPage* pPage = 0 ; // Set if resource is a page hdsFldspec vd ; // Variable prototype hzPair P ; // Attr/value pair const char* i ; // Iterator for active tag tests hzString cnam ; // Class name hzString vnam ; // Variable name hzString vdef ; // Variable definition (from which name can be used) hzString iname ; // Index name hzString name ; // Tag/visible entity name hzString title ; // Text visible hzString page ; // Expected page (to go to) hzString whom ; // Allowed users hzString css ; // Allowed CSS style hzString hname ; // Form action (handler name) hzString faUrl ; // Form action URL hzString pcntEnt ; // Percent entity uint32_t aflags ; // Access flags uint32_t bErr = 0 ; // Error condition bool bBlock = false ; // This is set for tags where the function called to process the tag, itself calls _readTag (see above note) hzEcode rc = E_OK ; // Return code
if (!this) Fatal("No instance\n") ; if (!pN) Fatal("No node supplied\n") ;
if (tga) pPage = dynamic_cast<hdsPage*>(tga->m_pLR) ;
// m_pLog->Log("File %s Line %d:%d level %d: Doing tag %s parent %p (tga %p page %p)\n", pN->Fname(), pN->Line(), pN->Level(), level, pN->txtName(), parent, tga, pPage) ;
// Tags that apply to pages and articles generally if (pN->NameEQ("xtable")) { bBlock = true ; thisVE = _readTable(pN, pPage) ; } else if (pN->NameEQ("xdirlist")) { bBlock = true ; thisVE = _readDirlist(pN, pPage) ; } else if (pN->NameEQ("xchartPie")) { bBlock = true ; thisVE = _readChartPie(pN) ; } else if (pN->NameEQ("xchartBar")) { bBlock = true ; thisVE = _readChartBar(pN) ; } else if (pN->NameEQ("xchartStd")) { bBlock = true ; thisVE = _readChartStd(pN) ; } else if (pN->NameEQ("xdiagram")) { bBlock = true ; thisVE = _readDiagram(pN) ; } else if (pN->NameEQ("xflowchart")) { bBlock = true ; thisVE = _readFlowchart(pN) ; }
else if (pN->NameEQ("xtreeCtl")) { bBlock = true ; if (pPage) pPage->m_bScriptFlags |= INC_SCRIPT_NAVTREE ; thisVE = _readXtreeCtl(pN) ; }
else if (pN->NameEQ("xblock")) { for (ai = pN ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("name")) name = ai.Value() ; else { m_pLog->Log("File %s Line %d <xblock> Bad param (%s=%s)\n", pN->Fname(), pN->Line(), ai.Name(), ai.Value()) ; return 0 ; } }
if (!name) { m_pLog->Log("File %s Line %d <xblock> no name attr supplied\n", pN->Fname(), pN->Line()) ; return 0 ; }
if (!m_Includes.Exists(name)) { m_pLog->Log("File %s Line %d xblock %s non-existant xinclude\n", pN->Fname(), pN->Line(), *name) ; return 0 ; }
thisVE = pIncl = m_Includes[name] ; thisVE->m_Tag = pN->txtName() ;
if (pPage) pPage->m_bScriptFlags |= pIncl->m_bScriptFlags ; bScrFlags |= pIncl->m_bScriptFlags ;
m_pLog->Log("Added block (%s)(%s)\n", *pIncl->m_Refname, *name) ; bBlock = true ; }
else if (pN->NameEQ("xdiv")) { // Read in an <xdiv> tag. This has a single attribute of user whose value must either be public (no user logged on) or one of the declared // user types. The effect of an <xdiv> is to make the displaying of its subtags conditional on who is logged on.
whom.Clear() ; for (ai = pN ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("user")) whom = ai.Value() ; else { m_pLog->Log("File %s Line %d: Invalid attribute for <xdiv> (%s=%s)\n", pN->Fname(), pN->Line(), ai.Name(), ai.Value()) ; return 0 ; } }
if (!whom) { m_pLog->Log("File %s Line %d: <xdiv> No user specified\n", pN->Fname(), pN->Line()) ; return 0 ; }
aflags = _calcAccessFlgs(whom) ; if (aflags == 0xffffffff) { m_pLog->Log("File %s Line %d: Bad access specification (%s)\n", pN->Fname(), pN->Line(), *whom) ; return 0 ; }
// All is well insert the <xdiv> into the page thisVE = pXdiv = new hdsXdiv(this) ; thisVE->m_strPretext = pN->txtPtxt() ; thisVE->m_Line = pN->Line() ; thisVE->m_Indent = pN->Level() ; pXdiv->m_Tag = pN->txtName() ; pXdiv->m_Access = aflags ; m_pLog->Log("Added xdiv (%s, %08x)\n", *whom, pXdiv->m_Access) ; }
else if (pN->NameEQ("xcond")) { // Read in an <xcond> tag. This has a single attribute of either 'exists', 'isnull' or 'equal' whose value must name a variable. The effect // of <xcond> is to conditionally display it's subtags.
thisVE = pCond = new hdsCond(this) ; thisVE->m_strPretext = pN->txtPtxt() ; thisVE->m_Line = pN->Line() ; thisVE->m_Indent = pN->Level() ;
pCond->m_cflags = 0 ; for (ai = pN ; ai.Valid() ; ai.Advance()) { rc = thisVE->AddAttr(ai.Name(), ai.Value()) ; if (rc == E_SYNTAX) { m_pLog->Log("File %s Line %d (%d) Malformed percent entity in tag attribute\n", pN->Fname(), pN->Line(), thisVE->m_Line) ; delete pCond ; return 0 ; }
if (ai.NameEQ("exists")) { pCond->m_cflags |= XCOND_EXISTS ; cnam = ai.Value() ; } else if (ai.NameEQ("isnull")) { pCond->m_cflags |= XCOND_ISNULL ; cnam = ai.Value() ; } else if (ai.NameEQ("action")) { pCond->m_cflags |= XCOND_ACTION ; cnam = ai.Value() ; } else { m_pLog->Log("File %s Line %d: <xcond> Invalid attribute (%s=%s)\n", pN->Fname(), pN->Line(), ai.Name(), ai.Value()) ; delete pCond ; return 0 ; } }
if (!pCond->m_cflags) { m_pLog->Log("File %s Line %d: <xcond> No condition specified\n", pN->Fname(), pN->Line()) ; return 0 ; } if (CountBits(&pCond->m_cflags, sizeof(uint32_t)) > 1) { m_pLog->Log("File %s Line %d: <xcond> ambiguous condition specified\n", pN->Fname(), pN->Line()) ; return 0 ; }
// All is well insert the <xcond> into the page pCond->m_Tag = pN->txtName() ; }
else if (pN->NameEQ("navbar")) { thisVE = pNavbar = new hdsNavbar(this) ; thisVE->m_Line = pN->Line() ; thisVE->m_Indent = pN->Level() ; thisVE->m_Tag = pN->txtName() ;
if (pPage) pPage->m_bScriptFlags |= INC_SCRIPT_NAVBAR ; else { // Run back to hdsBlock (as this is the only other possible root) bScrFlags |= INC_SCRIPT_NAVBAR ; } }
else if (pN->NameEQ("x")) { // Language support tag
thisVE = pXtag = new hdsXtag(this) ; pXtag->m_strPretext = pN->txtPtxt() ; pXtag->m_Tag = pN->txtName() ; pXtag->m_strContent = pN->m_fixContent ; pXtag->m_Line = pN->Line() ; pXtag->m_Indent = pN->Level() ; }
// Tags mostly applicable to forms
else if (pN->NameEQ("xformDef")) { m_pLog->Log("File %s Line %d: invoked _readFormDef by %s\n", pN->Fname(), pN->Line(), tga->m_pCaller) ; bBlock = true ; thisVE = _readFormDef(pN, tga->m_pLR) ; } else if (pN->NameEQ("xformRef")) { bBlock = true ; thisVE = _readFormRef(pN, tga->m_pLR) ; }
else if (pN->NameEQ("xfield")) { if (!tga->m_pFormdef) { bErr=1 ; m_pLog->Log("File %s Line %d: Error: <xfield> not within <xformDef> (caller %s)\n", pN->Fname(), pN->Line(), tga->m_pCaller) ; } thisVE = _readField(pN, tga->m_pFormdef) ; }
else if (pN->NameEQ("xhide")) { if (!tga->m_pFormdef) { bErr=1 ; m_pLog->Log("File %s Line %d: Error: <xhide> not within <xformDef> (caller %s)\n", pN->Fname(), pN->Line(), tga->m_pCaller) ; } thisVE = _readXhide(pN, tga->m_pFormdef) ; }
else if (pN->NameEQ("recaptcha")) { if (!tga->m_pFormdef) { bErr=1 ; m_pLog->Log("File %s Line %d: Error: <recaptcha> not within <xformDef> (caller %s)\n", pN->Fname(), pN->Line(), tga->m_pCaller) ; } else { thisVE = pRecap = new hdsRecap(this) ; thisVE->m_Line = pN->Line() ; thisVE->m_Indent = pN->Level() ; thisVE->m_Tag = pN->txtName() ;
pPage->m_bScriptFlags |= INC_SCRIPT_RECAPTCHA ; tga->m_pFormdef->m_bScriptFlags |= INC_SCRIPT_RECAPTCHA ; } m_pLog->Log("Added recapture placement\n") ; // bBlock = true ; }
else if (pN->NameEQ("xlinkBut")) { // The link button manifests as a button but is purely a link. Common in pages but in forms is usually limited to triggering help popups and tha abort // button for abandoning an edit. <xlinkBut> in a form is thus considered as part of the supporting HTML of the form. The <xlinkBut> tag does not add // a form action and so it is not necessary for there to be a form definition in progress.
for (ai = pN ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("title")) title = ai.Value() ; else if (ai.NameEQ("goto")) page = ai.Value() ; else if (ai.NameEQ("css")) css = ai.Value() ; else { bErr=1 ; m_pLog->Log("File %s Line %d Adding <%s> tag: Bad param (%s=%s)\n", pN->Fname(), pN->Line(), pN->txtName(), ai.Name(), ai.Value()) ; } }
if (!title) { bErr=1 ; m_pLog->Log("File %s Line %d <xlinkBut> No title supplied\n", pN->Fname(), pN->Line()) ; } if (!page) { bErr=1 ; m_pLog->Log("File %s Line %d <xlinkBut> No destination supplied\n", pN->Fname(), pN->Line()) ; }
thisVE = pButt = new hdsButton(this) ; thisVE->m_strPretext = pN->txtPtxt() ; thisVE->m_Line = pN->Line() ; thisVE->m_Indent = pN->Level() ; thisVE->m_Tag = pN->txtName() ; pButt->m_strContent = title ; pButt->m_Linkto = page ; pButt->m_CSS = css ; m_pLog->Log("Added link button (%s)\n", *pButt->m_strContent) ; }
else if (pN->NameEQ("xformBut")) { thisVE = _readFormBut(pN, tga->m_pFormdef, tga->m_pFormref) ;
// The <xformBut> adds an action to a form definition and thus a form definition must be supplied
#if 0 if (!tga->m_pFormdef) { m_pLog->Log("File %s Line %d <xformBut> No form definition applies\n", pN->Fname(), pN->Line()) ; return 0 ; }
for (ai = pN ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("title")) title = ai.Value() ; else if (ai.NameEQ("handler")) hname = ai.Value() ; else if (ai.NameEQ("url")) faUrl = ai.Value() ; else if (ai.NameEQ("css")) css = ai.Value() ; else { bErr=1 ; m_pLog->Log("File %s Line %d Adding <%s> tag: Bad param (%s=%s)\n", pN->Fname(), pN->Line(), pN->txtName(), ai.Name(), ai.Value()) ; } }
if (!title) { bErr=1 ; m_pLog->Log("File %s Line %d <xformBut> No title supplied\n", pN->Fname(), pN->Line()) ; }
if (hname || faUrl) { // If either action or URL are supplied, both must be if (!hname) { bErr=1 ; m_pLog->Log("File %s Line %d: <xformDef> URL but no action supplied\n", pN->Fname(), pN->Line()) ; } if (!faUrl) { bErr=1 ; m_pLog->Log("File %s Line %d: <xformDef> Action but no URL supplied\n", pN->Fname(), pN->Line()) ; } }
if (hname && faUrl) { if (!m_FormHdls.Exists(hname)) { m_FormHdls.Insert(hname,0) ; tga->m_pFormdef->m_nActions++ ; } m_FormUrl2Hdl.Insert(faUrl,hname) ; m_FormUrl2Ref.Insert(faUrl, tga->m_pFormref) ; m_FormRef2Url.Insert(tga->m_pFormref, faUrl) ; }
if (!hname && !faUrl) { // OK for the button to have no action or submission URL as long as the form definition has these and the form is single action. if (!tga->m_pFormdef->m_DfltAct) { bErr=1 ; m_pLog->Log("File %s Line %d <xformBut> No action supplied\n", pN->Fname(), pN->Line()) ; } else { hname = tga->m_pFormdef->m_DfltAct ; faUrl = tga->m_pFormdef->m_DfltURL ; tga->m_pFormdef->m_DfltAct = 0 ; tga->m_pFormdef->m_DfltURL = 0 ; } }
if (bErr) return 0 ;
// if (page) // { // Lookup the page and check that it exists and is not the same as the page in which the button appears // if (page != "%x_referer;" && !m_PagesName.Exists(page)) // m_pLog->Log("Warning: File %s Line %d Adding <button> tag: Page %s not found\n", pN->Fname(), pN->Line(), *page) ; // }
thisVE = pButt = new hdsButton(this) ; thisVE->m_strPretext = pN->txtPtxt() ; thisVE->m_Line = pN->Line() ; thisVE->m_Indent = pN->Level() ; thisVE->m_Tag = pN->txtName() ; thisVE->m_Resv = tga->m_pFormdef->m_nActions ; pButt->m_strContent = title ; pButt->m_CSS = css ; pButt->m_Linkto = hname ; pButt->m_Formname = tga->m_pFormdef->m_Formname ; m_pLog->Log("Added form button (%s)\n", *pButt->m_strContent) ; #endif }
else { // Tag must be a valid HTML tag
name = pN->txtName() ; if (Txt2Tagtype(name) == HTAG_NULL) { m_pLog->Log("File %s Line %d: Illegal tag <%s> (caller %s)\n", pN->Fname(), pN->Line(), pN->txtName(), tga->m_pCaller) ; return 0 ; }
// m_pLog->Log("DFLT to HTML: File %s Line %d: Doing Tag <%s> (caller %s)\n", pN->Fname(), pN->Line(), pN->txtName(), tga->m_pCaller) ;
// Deal with the special case of the <input> tag as this will add to the host form's fields ??? thisVE = pHtag = new hdsHtag(this) ; pHtag->m_strPretext = pN->txtPtxt() ; pHtag->m_Tag = pN->txtName() ; pHtag->m_strContent = pN->m_fixContent ; pHtag->m_Line = pN->Line() ; pHtag->m_Indent = pN->Level() ;
for (ai = pN ; ai.Valid() ; ai.Advance()) { // Check first for JavaScript events name = ai.Name() ; if (_hzGlobal_JS_Events.Exists(name)) { // Add JS function to list for page. This will later be checked against standard Dissemino scripts and scripts appearing within the <xscript> tag if (pPage) pPage->m_Scripts.Add(ai.Value()) ; }
rc = pHtag->AddAttr(ai.Name(), ai.Value()) ; if (rc == E_SYNTAX) { m_pLog->Log("File %s Line %d (%d) Malformed percent entity in tag attribute\n", pN->Fname(), pN->Line(), thisVE->m_Line) ; delete pHtag ; return 0 ; }
if (ai.NameEQ("href")) { m_pLog->Log("File %s Line %d: Adding link %s\n", pN->Fname(), pN->Line(), ai.Value()) ; m_Links.Insert(ai.Value()) ; } } }
if (!thisVE) { m_pLog->Log("File %s Line %d: Failed to proces <%s> tag\n", pN->Fname(), pN->Line(), pN->txtName()) ; return 0 ; }
if (!thisVE->m_Line) { m_pLog->Log("File %s Line %d. Visible entity %s has no line number\n", pN->Fname(), pN->Line(), *thisVE->m_Tag) ; return 0 ; } if (!thisVE->m_Indent) { m_pLog->Log("File %s Line %d. Visible entity %s has no indentation\n", pN->Fname(), pN->Line(), *thisVE->m_Tag) ; return 0 ; }
// if (bBlock) // return thisVE ;
// If a parent tag supplied, add this entity to the parent list of childen if (parent) parent->AddChild(thisVE) ;
// If current tag has sub-tags, recurse to process them if (!bBlock) { for (pN1 = pN->GetFirstChild() ; rc == E_OK && pN1 ; pN1 = pN1->Sibling()) { newVE = _readTag(tga, pN1, bScrFlags, thisVE, level+1) ; if (!newVE) return 0 ; } }
// If the visible entity has content, we strip leading tabs and insert remainder into m_Strings (the universal collection of strings). Then the content is tested for percent // entities. If any are found the VE is deemed active.
if (thisVE->m_strContent) { // Case where visible entity content is in the form of a string
for (i = thisVE->m_strContent ; *i && *i < CHAR_SPACE ; i++) ; if (!*i) thisVE->m_strContent.Clear() ; else { for (i = thisVE->m_strContent ; *i ; i++) { if (*i == CHAR_PERCENT) { if (i[1] == CHAR_PERCENT) { i++ ; continue ; } if (IsAlpha(i[1]) && i[2] == CHAR_COLON) { if (IsPcEnt(pcntEnt, i)) thisVE->m_flagVE |= VE_CT_ACTIVE ; else { bErr=1 ; m_pLog->Log("File %s Line %d (%d) Malformed percent entity in tag content\n", pN->Fname(), pN->Line(), thisVE->m_Line) ; } i += 2 ; } } } } }
if (thisVE->m_strPretext) { for (i = thisVE->m_strPretext ; *i && *i < CHAR_SPACE ; i++) ; if (!*i) thisVE->m_strPretext.Clear() ; else { for (i = thisVE->m_strPretext ; *i ; i++) { if (*i == CHAR_PERCENT) { if (i[1] == CHAR_PERCENT) { i++ ; continue ; } if (IsAlpha(i[1]) && i[2] == CHAR_COLON) { if (IsPcEnt(pcntEnt, i)) thisVE->m_flagVE |= VE_PT_ACTIVE ; else { bErr=1 ; m_pLog->Log("File %s Line %d (%d) Malformed percent entity in tag pretext\n", pN->Fname(), pN->Line(), thisVE->m_Line) ; } i += 2 ; } } } } }
thisVE->Complete() ;
return bErr ? 0 : thisVE ; }
/* ** SECTION 2: Database and Data Class Config Read Functions */
hzEcode hdsApp::_readDataEnum (hzXmlNode* pN) { // Category: Database and Data Class Config Read Functions // // Process the <enum> tag to establish a new enum (enumerated data type). Enums are internally manifest as hdbEnum instances. Externally enum values can be manifest as set of // check boxes or radio buttons, or as HTML selectors. // // The <enum> tag has attributes of name, xple and var. As enums are data types, the enum name must be unique among all data types. The xple attribute indicates if multiple options // can be selected. // // For the purpose of clarity, neither the <selector> tag nor the hbdSelector instance it specifies, are the same thing as a HTML <select> tag. The latter // can appear in HTML output in respect of the hdbSlector, only when the HTML for a form having a field whose data type is the hdbSelctor, is produced. It // should be noted, that the hdbEnum may not necessarily manifest as a HTML <select> tag at all. It could manifest as a set of check boxes or as a set // of radio buttons. // // Because in processing the <selector> tag, we are only defining the set of strings, we cannot say at this stage, what the default should be. That has to // be done in the configs for the field within the form. // // Likewise the option for multiple selection is not vested with the hdbEnum. That is a matter for any data class member that uses the hdbEnum as it type. // items may be selected from it when it is manifest in a form. // // The only thing that is determined here is whether the enum is fixed once loaded with values - or can have values added during runtime. // // Arguments: 1) pN Pointer to XML node <selector> // // Returns: E_SYNTAX In the event of incorrect parameters // E_OK If the <selector> parameters are valid
_hzfunc("hdsApp::_readDataEnum") ;
hzArray<hzString> ar ; // Vect of items found so far hzSet<hzString> items ; // Set of items found so far to ensure no repeats
hzAttrset ai ; // Attribute iterator hzXmlNode* pN1 ; // For iteraton of options hdbEnum* pSlct ; // The selector to be added hzString S ; // Temp string uint32_t n ; // Iterator hzEcode rc = E_OK ; // Return code
if (!pN) Fatal("No node supplied\n") ;
if (!pN->NameEQ("enum")) { m_pLog->Log("File %s Line %d. Expected <enum>. Tag <%s> unexpected\n", pN->Fname(), pN->Line(), pN->txtName()) ; return E_SYNTAX ; }
pSlct = new hdbEnum() ;
// Type parameters (name) for (ai = pN ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("name")) pSlct->SetTypename(ai.Value()) ; else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d Reading <selector> tag: Bad param (%s=%s)\n", pN->Fname(), pN->Line(), ai.Name(), ai.Value()) ; } }
// Check all attributes have been supplied if (!pSlct->strType()) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d Reading <selector> tag: No name supplied\n", pN->Fname(), pN->Line()) ; }
if (m_ADP.GetDatatype(pSlct->strType())) { rc = E_DUPLICATE ; m_pLog->Log("File %s Line %d: Name %s already data-type\n", pN->Fname(), pN->Line(), pSlct->txtType()) ; }
// Selector Items for (pN1 = pN->GetFirstChild() ; rc == E_OK && pN1 ; pN1 = pN1->Sibling()) { if (pN1->NameEQ("option")) { ai = pN1 ; if (!ai.Valid()) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d Tag <option> requires an attr of 'show' or 'dflt'\n", pN->Fname(), pN1->Line()) ; break ; }
if (ai.NameEQ("dflt") || ai.NameEQ("show")) { if (ai.NameEQ("dflt")) pSlct->m_Default = pSlct->Count() ;
if (items.Exists(ai.Value())) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: Duplicate option of %s\n", pN->Fname(), pN->Line(), ai.Value()) ; break ; } items.Insert(ai.Value()) ;
S = ai.Value() ; if (S.Length() > pSlct->m_nMax) pSlct->m_nMax = S.Length() ;
//strNo = _hzGlobal_setStrings->IntVal(ai.Value()) ; //if (!strNo) // strNo = _hzGlobal_setStrings->Insert(ai.Value()) ; _hzGlobal_setStrings.Insert(ai.Value()) ;
//pSlct->AddItem(strNo) ; pSlct->AddItem(ai.Value()) ; continue ; }
rc = E_SYNTAX ; m_pLog->Log("File %s Line %d Invalid attr (%s) for <option> tag\n", pN->Fname(), pN->Line(), ai.Name()) ; } }
if (rc == E_OK && !items.Count()) { // The enum should be comma-separated in the <enum> tag value SplitCSV(ar, pN->m_fixContent) ;
for (n = 0 ; n < ar.Count() ; n++) { S = ar[n] ;
if (items.Exists(S)) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: Duplicate option of %s\n", pN->Fname(), pN->Line(), *S) ; break ; } items.Insert(S) ;
if (S.Length() > pSlct->m_nMax) pSlct->m_nMax = S.Length() ; _hzGlobal_setStrings.Insert(S) ; pSlct->AddItem(S) ; } }
if (rc != E_OK) { delete pSlct ; return rc ; }
// Add the selector if (rc == E_OK) { m_ADP.RegisterDataEnum(pSlct) ;
m_pLog->Log("Added data enums %s\n", pSlct->txtType()) ; }
return rc ; }
hzEcode hdsApp::_readUser (hzXmlNode* pN) { // Database and Data Class Config Read Functions // // A user class is a special case of data class, which defines data class members for a particular type of application user. In general, creation of a data class is a separate // act from creating a repository. All classes declared should be used to create repositories otherwise there is no point defining // them, but a class can be used to form a member of another class. This is not the case with a user class. For each <user> tag in the config files, there // will be exactly one user class and one user repository and the repository will bear the same name as the class. It is not possible to use a user class // as a member of another class. // // This function adds the user class to m_ADP.mapClasses and adds the user repository to m_ADP.mapRepositories. The user repository must be // cached so storage method is not an attribute of the <user> tag as it is with <repos>. The user class must also name exactly one member to serve as the // primary unique identifier (username). This is specified as an attribute of <user> namely 'primeKey'. // // Arguments: 1) pN Pointer to XML node <user> // // Returns: E_SYNTAX In the event of incorrect parameters // E_NOTFOUND If there is not a setting of project param m_UserBase // E_OK If the <user> parameters are valid
_hzfunc("hdsApp::_readUser") ;
const hdbMember* pMbr ; // Class member
hzAttrset ai ; // Attribute iterator hzXmlNode* pN1 ; // Class member subnodes hdbClass* pClass ; // The class hdbObjRepos* pRepos ; // The object cache/store hzString cnam ; // Class or user class name hzString prime ; // Name of member to be used as primary key hzString memname ; // User class member name hzString S ; // Intermeadiate string hzEcode rc = E_OK ; // Return code
// Must be a node if (!pN) Fatal("No node supplied\n") ; if (!pN->NameEQ("user")) { m_pLog->Log("File %s Line %d. Expected <user>. Tag <%s> unexpected\n", pN->Fname(), pN->Line(), pN->txtName()) ; return E_SYNTAX ; }
if (!(m_OpFlags & DS_APP_SUBSCRIBERS)) { m_pLog->Log("File %s Line %d. <user> tag without a prior declaration of 'userbase' as a project param. Assuming value of 'subscriber'\n", pN->Fname(), pN->Line()) ; return E_NOTFOUND ; }
// Read class or user class params from attributes for (ai = pN ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("type")) cnam = ai.Value() ; else if (ai.NameEQ("prime")) prime = ai.Value() ; else { m_pLog->Log("File %s Line %d <user> Only <type|prime> attributes allowed. Bad param (%s=%s)\n", pN->Fname(), pN->Line(), ai.Name(), ai.Value()) ; return E_SYNTAX ; } }
// Check all atributes are supplied if (!cnam) { m_pLog->Log("File %s Line %d <class> No user type supplied\n", pN->Fname(), pN->Line()) ; return E_SYNTAX ; } if (!prime) { m_pLog->Log("File %s Line %d <class> No primary key supplied\n", pN->Fname(), pN->Line()) ; return E_SYNTAX ; }
// Check user class is unique among classes if (m_ADP.GetPureClass(cnam)) { m_pLog->Log("File %s Line %d <user> Already have class of %s\n", pN->Fname(), pN->Line(), *cnam) ; return E_SYNTAX ; } if (m_ADP.GetObjRepos(cnam)) { m_pLog->Log("File %s Line %d <user> Already have repository of %s\n", pN->Fname(), pN->Line(), *cnam) ; return E_SYNTAX ; }
// Add the user type and set access code AddUserType(cnam) ; if (rc != E_OK) { m_pLog->Log("File %s Line %d <user> Already have user type of %s\n", pN->Fname(), pN->Line(), *cnam) ; return E_SYNTAX ; }
// Read class members from subnodes pClass = new hdbClass(m_ADP, HDB_CLASS_DESIG_USR) ; pClass->InitStart(cnam) ;
for (pN1 = pN->GetFirstChild() ; rc == E_OK && pN1 ; pN1 = pN1->Sibling()) { if (pN1->NameEQ("member")) { rc = _readMember(pClass, pN1) ; if (rc != E_OK) m_pLog->Log("File %s Line %d <member> error\n", pN->Fname(), pN1->Line()) ; continue ; }
rc = E_SYNTAX ; m_pLog->Log("File %s Line %d Reading <user> tag: Subnode <%s> invalid\n", pN->Fname(), pN1->Line(), pN1->txtName()) ; }
if (rc == E_OK) { if (!pClass->MbrCount()) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: Class %s has no members\n", pN->Fname(), pN->Line(), *cnam) ; } }
if (rc == E_OK) { pClass->InitDone() ; pMbr = pClass->GetMember(prime) ;
if (!pMbr) { m_pLog->Log("File %s Line %d: No index. Member of %s not found in user class %s\n", pN->Fname(), pN->Line(), *prime, pClass->txtType()) ; rc = E_SYNTAX ; } }
if (rc == E_OK) rc = m_ADP.RegisterDataClass(pClass) ;
if (rc == E_OK) { // Set up repository pRepos = new hdbObjRepos(m_ADP) ; pRepos->InitStart(pClass, pClass->strType(), m_Datadir, HDB_REPOS_CACHE) ;
//m_ADP.RegisterObjRepos(pRepos) ;
rc = pRepos->InitMbrIndex(prime, true) ; if (rc != E_OK) m_pLog->Log("File %s Line %d: ERROR Cannot add %s indexable member\n", pN->Fname(), pN->Line(), *S) ; else m_pLog->Log("Added index %s to cache\n", *S) ;
if (rc == E_OK) { rc = pRepos->InitDone() ; if (rc != E_OK) m_pLog->Log("Could not finalize class %s. Err=%s\n", *cnam, Err2Txt(rc)) ; } }
if (rc == E_OK) m_pLog->Log("Completed User Class %p %s\n", pClass, *cnam) ; else m_pLog->Log("Failed User Class %s\n", *cnam) ; return rc ; }
hzEcode hdsApp::_readClass (hzXmlNode* pN) { // Database and Data Class Config Read Functions // // Process a <class> tag to define a data class. The class may then be used to initialize a repository, or used as a member of another class which may then // be used to initialize a repository. // // Arguments: 1) pN Pointer to XML node <class> // // Returns: E_SYNTAX In the event of incorrect parameters // E_OK If the <class> parameters are valid
_hzfunc("hdsApp::_readClass") ;
hzAttrset ai ; // Attribute iterator hzXmlNode* pN1 ; // Class member subnodes hdbClass* pClass ; // The class //hdsUsertype utype ; // User type hzString cnam ; // Class or user class name hzString cat ; // Class category (optional, used to drive page/form formation) //hzString repos ; // Used to direct which form of repository (if any) should be created (hdbObjCache/hdbObjStore/none) hzString memname ; // User class member name hzString S ; // Intermeadiate string hzEcode rc = E_OK ; // Return code
// Must be a node if (!pN) Fatal("No node supplied\n") ; if (!pN->NameEQ("class")) { m_pLog->Log("File %s Line %d. Expected <class>. Tag of <%s> unexpected\n", pN->Fname(), pN->Line(), pN->txtName()) ; return E_SYNTAX ; }
// Read class or user class params from attributes for (ai = pN ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("cat")) cat = ai.Value() ; else if (ai.NameEQ("name")) cnam = ai.Value() ; else { m_pLog->Log("File %s Line %d <class> Bad param (%s=%s)\n", pN->Fname(), pN->Line(), ai.Name(), ai.Value()) ; return E_SYNTAX ; } }
if (!cnam) { m_pLog->Log("File %s Line %d <class> No class name supplied\n", pN->Fname(), pN->Line()) ; return E_SYNTAX ; } if (m_ADP.GetPureClass(cnam)) { m_pLog->Log("File %s Line %d <class> Already have class of %s\n", pN->Fname(), pN->Line(), *cnam) ; return E_SYNTAX ; } if (m_ADP.GetDatatype(cnam)) { m_pLog->Log("File %s Line %d <class> Already have datatype of %s\n", pN->Fname(), pN->Line(), *cnam) ; return E_SYNTAX ; }
// Read class members from subnodes pClass = new hdbClass(m_ADP, HDB_CLASS_DESIG_CFG) ; pClass->InitStart(cnam) ; pClass->m_Category = cat ;
for (pN1 = pN->GetFirstChild() ; rc == E_OK && pN1 ; pN1 = pN1->Sibling()) { if (pN1->NameEQ("member")) { rc = _readMember(pClass, pN1) ; if (rc != E_OK) m_pLog->Log("File %s Line %d <member> error\n", pN->Fname(), pN1->Line()) ; continue ; }
rc = E_SYNTAX ; m_pLog->Log("File %s Line %d Reading <class> tag: Subnode <%s> invalid\n", pN->Fname(), pN1->Line(), pN1->txtName()) ; }
if (rc == E_OK) { if (!pClass->MbrCount()) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: Class %s has no members\n", pN->Fname(), pN->Line(), *cnam) ; } m_pLog->Log("Class %s has %d members\n", *cnam, pClass->MbrCount()) ; }
if (rc == E_OK) { pClass->InitDone() ; rc = m_ADP.RegisterDataClass(pClass) ; }
if (rc == E_OK) m_pLog->Log("Completed Class %p %s\n", pClass, *cnam) ; else m_pLog->Log("Failed Class %s\n", *cnam) ; return rc ; }
hzEcode hdsApp::_readRepos (hzXmlNode* pN) { // Database and Data Class Config Read Functions // // Process the <repos> tag which to construct a repository. // // Arguments: 1) pN Pointer to XML node <repos> // // Returns: E_SYNTAX In the event of incorrect parameters // E_OK If the <repos> parameters are valid
_hzfunc("hdsApp::_readRepos") ;
const hdbClass* pClass ; // The class hzAttrset ai ; // Attribute iterator hzXmlNode* pN1 ; // Class member subnodes hdbObjRepos* pRepos = 0 ; // The object cache/store hzString rnam ; // Repository name hzString cnam ; // Class name hzString method ; // Used to state if RAM Primacy is to be used hzString memName ; // User class member name hzString S ; // Intermeadiate string bool bUnique ; // Index is unique hzEcode rc = E_OK ; // Return code
// Must be a node if (!pN) Fatal("No node supplied\n") ;
if (!pN->NameEQ("repos")) { m_pLog->Log("File %s Line %d. Expected <repos>. Tag of <%s> unexpected\n", pN->Fname(), pN->Line(), pN->txtName()) ; return E_SYNTAX ; }
// Read class or user class params from attributes for (ai = pN ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("name")) rnam = ai.Value() ; else if (ai.NameEQ("class")) cnam = ai.Value() ; else if (ai.NameEQ("method")) method = ai.Value() ; else { m_pLog->Log("File %s Line %d <repos> Bad param (%s=%s)\n", pN->Fname(), pN->Line(), ai.Name(), ai.Value()) ; return E_SYNTAX ; } }
if (!rnam) { m_pLog->Log("File %s Line %d <repos> No repository name supplied\n", pN->Fname(), pN->Line()) ; return E_SYNTAX ; } if (!cnam) { m_pLog->Log("File %s Line %d <repos> No class name supplied\n", pN->Fname(), pN->Line()) ; return E_SYNTAX ; } if (!method) { m_pLog->Log("File %s Line %d <repos> No store method supplied\n", pN->Fname(), pN->Line()) ; return E_SYNTAX ; }
if (m_ADP.GetObjRepos(rnam)) { m_pLog->Log("File %s Line %d <repos> Repository %s already exists\n", pN->Fname(), pN->Line(), *rnam) ; return E_SYNTAX ; }
pClass = m_ADP.GetPureClass(cnam) ; if (!pClass) { m_pLog->Log("File %s Line %d <repos> No such class as %s\n", pN->Fname(), pN->Line(), *cnam) ; return E_SYNTAX ; }
// Create repository
pRepos = new hdbObjRepos(m_ADP) ;
if (method == "cache") pRepos->InitStart(pClass, pClass->strType(), m_Datadir, HDB_REPOS_CACHE) ; else if (method == "hard") pRepos->InitStart(pClass, pClass->strType(), m_Datadir, HDB_REPOS_HARD) ; else if (method == "dual") pRepos->InitStart(pClass, pClass->strType(), m_Datadir, HDB_REPOS_DUAL) ; else { m_pLog->Log("File %s Line %d <repos, method> Bad method (%s). Must be cache|hard|dual\n", pN->Fname(), pN->Line(), *method) ; return E_SYNTAX ; }
// Add indexes for (pN1 = pN->GetFirstChild() ; rc == E_OK && pN1 ; pN1 = pN1->Sibling()) { if (pN1->NameEQ("index")) { // Note that a name member is to be indexed memName = (char*) 0 ; bUnique = false ;
for (ai = pN1 ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("member")) { if (!memName) memName = ai.Value() ; else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <idx> tag, attr member must be set only once", pN->Fname(), pN1->Line()) ; } } else if (ai.NameEQ("unique")) { if (ai.ValEQ("true")) bUnique = true ; else if (ai.ValEQ("false")) bUnique = false ; else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <idx> tag, attr unique must be either true or false", pN->Fname(), pN1->Line()) ; } } else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <index>: member|unique - Bad param (%s=%s)\n", pN->Fname(), pN1->Line(), ai.Name(), ai.Value()) ; } }
if (rc != E_OK) break ;
rc = pRepos->InitMbrIndex(memName, bUnique) ; if (rc != E_OK) { m_pLog->Log("File %s Line %d: ERROR Cannot add %s indexable member\n", pN->Fname(), pN->Line(), *S) ; break ; } continue ; }
rc = E_SYNTAX ; m_pLog->Log("File %s Line %d Reading <class> tag: Subnode <%s> invalid\n", pN->Fname(), pN1->Line(), pN1->txtName()) ; }
if (rc == E_OK) { rc = pRepos->InitDone() ; if (rc != E_OK) m_pLog->Log("Could not finalize repository %s. Err=%s\n", *cnam, Err2Txt(rc)) ; else { //m_ADP.RegisterObjRepos(pRepos) ; m_pLog->Log("Completed Repository %s\n", *rnam) ; } }
return rc ; }
hzEcode hdsFldspec::Validate (hzLogger* pLog, const hzString& cfgFname, const char* caller, uint32_t ln) { // Database and Data Class Config Read Functions // // Validate a field specification // // Arguments: 1) pSpec The field specification to test // 2) cfgFname The source config filename // 3) ln The source config line number // // Returns: E_ARGUMENT If no field specification, config file or caller is supplied. // E_SYNTAX If there are any omissions or inconsistancies. // E_OK If the field specification is validated.
_hzfunc("hdsApp::_testFldspec") ;
hzEcode rc = E_OK ; // Return code
if (!cfgFname) { rc = E_ARGUMENT ; pLog->Log("No config file supplied\n") ; } if (!caller) { rc = E_ARGUMENT ; pLog->Log("No caller func supplied\n") ; }
if (rc != E_OK) return rc ;
if (!m_pType) { pLog->Log("(%s) File %s Line %d <fldspec> No data type established\n", caller, *cfgFname, ln) ; return E_SYNTAX ; }
if (htype == HTMLTYPE_NULL) { pLog->Log("(%s) File %s Line %d <fldspec> No HTML type established\n", caller, *cfgFname, ln) ; return E_SYNTAX ; }
if (!m_Refname) { pLog->Log("(%s) File %s Line %d <fldspec> No refname supplied\n", caller, *cfgFname, ln) ; return E_SYNTAX ; }
switch (htype) { case HTMLTYPE_TEXT: // Full range of printable chars case HTMLTYPE_PASSWORD: // As text but char's won't print if (nRows) pLog->Log("(%s) File %s Line %d: Note. Rows for TEXT/PASSWORD are always 1 so not required\n", caller, *cfgFname, ln) ; if (!nCols) nCols = 1 ; if (!nSize) { rc = E_SYNTAX ; pLog->Log("(%s) File %s Line %d: No max size supplied\n", caller, *cfgFname, ln) ; } nRows = 1 ; break ;
case HTMLTYPE_TEXTAREA: // As text but a text area is described if (!nRows) { rc = E_SYNTAX ; pLog->Log("(%s) File %s Line %d: No row size supplied\n", caller, *cfgFname, ln) ; } if (!nCols) { rc = E_SYNTAX ; pLog->Log("(%s) File %s Line %d: No col size supplied\n", caller, *cfgFname, ln) ; } if (!nSize) { rc = E_SYNTAX ; pLog->Log("(%s) File %s Line %d: No max size supplied\n", caller, *cfgFname, ln) ; } break ;
case HTMLTYPE_SELECT: // A HTML selector
if (m_pType->Basetype() == BASETYPE_ENUM || m_pType->Basetype() == BASETYPE_STRING) { if (nRows || nCols || nSize) pLog->Log("(%s) File %s Line %d: Note. For Select field dimensions are not required\n", caller, *cfgFname, ln) ; break ; }
rc = E_SYNTAX ; pLog->Log("(%s) File %s Line %d: <fldspec>: Data type of %s is incompatible to HTMLTYPE_SELECT\n", caller, *cfgFname, ln, m_pType->txtType()) ; break ;
case HTMLTYPE_CHECKBOX: // A HTML checkbox. Could be a boolean data type with just one checkbox or it could be a data enumeration meaning there will be // one checkbox per item in the enumeration. if (nSize) pLog->Log("(%s) File %s Line %d: Note. For Check-box field size is not required\n", caller, *cfgFname, ln) ;
if (m_pType->Basetype() == BASETYPE_BOOL) { if (!nRows) nRows = 1 ; if (!nCols) nCols = 1 ; break ; } if (m_pType->Basetype() == BASETYPE_ENUM) { if (!nRows) { rc = E_SYNTAX ; pLog->Log("(%s) File %s Line %d: No row size supplied\n", caller, *cfgFname, ln) ; } if (!nCols) { rc = E_SYNTAX ; pLog->Log("(%s) File %s Line %d: No col size supplied\n", caller, *cfgFname, ln) ; } break ; }
rc = E_SYNTAX ; pLog->Log("File %s Line %d: <fldspec>: Data type of %s is incompatible to HTMLTYPE_CHECKBOX\n", m_pType->txtType()) ; break ;
case HTMLTYPE_RADIO: // A HTML radio button set must necessarily represent a data enumeration and have min/max population of 1 if (nSize) pLog->Log("(%s) File %s Line %d: Note. For Check-box/Radio field size is not required\n", caller, *cfgFname, ln) ;
if (m_pType->Basetype() == BASETYPE_ENUM) { if (!nRows) { rc = E_SYNTAX ; pLog->Log("(%s) File %s Line %d: No row size supplied\n", caller, *cfgFname, ln) ; } if (!nCols) { rc = E_SYNTAX ; pLog->Log("(%s) File %s Line %d: No col size supplied\n", caller, *cfgFname, ln) ; } break ; }
rc = E_SYNTAX ; pLog->Log("(%s) File %s Line %d: <fldspec>: Data type of %s is incompatible to HTMLTYPE_RADIO\n", caller, m_pType->txtType()) ; break ;
case HTMLTYPE_FILE: // File uploaded (as for text) if (nRows) pLog->Log("(%s) File %s Line %d: Note. Rows for FILE are always 1 so not required\n", caller, *cfgFname, ln) ; if (!nCols) { rc = E_SYNTAX ; pLog->Log("(%s) File %s Line %d: No col size supplied\n", caller, *cfgFname, ln) ; } if (!nSize) { rc = E_SYNTAX ; pLog->Log("(%s) File %s Line %d: No max size supplied\n", caller, *cfgFname, ln) ; } nRows = 1 ; break ;
case HTMLTYPE_HIDDEN: // Hidden field if (nRows || nCols || nSize) pLog->Log("(%s) File %s Line %d: Note. For Hidden field dimensions are not required\n", caller, *cfgFname, ln) ; break ; }
return rc ; }
hzEcode hdsApp::_readFldspec (hzXmlNode* pN) { // Database and Data Class Config Read Functions // // Create a new field specification in accordance with the <fldspec> tag. The field specification defines what is needed to present the field as part of a // HTML form. // // Note that a field specification can be supplied as an attribute to the <member> tag used to define data class members within a <class> tag, exept where // the intended member is itself a class. This is possible because the field specification contains where applicable, the fundamental data type of the data // enum (hdbEnum instance). // // This practice is recommended as a convienient short form and because it facilitates the generation of default forms and form-handlers when Dissemino is // run with the -forms option. // // Arguments: 1) pN Pointer to XML node <fldspec> // // Returns: E_SYNTAX In the event of incorrect parameters // E_OK If the <fldspec> parameters are valid
_hzfunc("hdsApp::_readFldspec") ;
hzAttrset ai ; // Attribute iterator hdsFldspec fs ; // Field spec hzEcode rc = E_OK ; // Return code
for (ai = pN ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("name")) fs.m_Refname = ai.Value() ; else if (ai.NameEQ("cols")) fs.nCols = atoi(ai.Value()) ; else if (ai.NameEQ("rows")) fs.nRows = atoi(ai.Value()) ; else if (ai.NameEQ("size")) fs.nSize = atoi(ai.Value()) ;
else if (ai.NameEQ("html")) { if (ai.ValEQ("TEXT")) fs.htype = HTMLTYPE_TEXT ; else if (ai.ValEQ("PASSWORD")) fs.htype = HTMLTYPE_PASSWORD ; else if (ai.ValEQ("TEXTAREA")) fs.htype = HTMLTYPE_TEXTAREA ; else if (ai.ValEQ("CHECKBOX")) fs.htype = HTMLTYPE_CHECKBOX ; else if (ai.ValEQ("RADIO")) fs.htype = HTMLTYPE_RADIO ; else if (ai.ValEQ("SELECT")) fs.htype = HTMLTYPE_SELECT ; else if (ai.ValEQ("HIDDEN")) fs.htype = HTMLTYPE_HIDDEN ; else if (ai.ValEQ("FILE")) fs.htype = HTMLTYPE_FILE ; else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <fldtype> tag: Invalid HTML type (%s)\n", pN->Fname(), pN->Line(), ai.Value()) ; } } else if (ai.NameEQ("enum")) { // The attribute value will name the enum (note, not strictly necessary to use 'enum' one can use 'type' or 'fldtype')
fs.m_pType = m_ADP.GetDataEnum(ai.Value()) ; if (!fs.m_pType) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <fldspec>: Invalid ENUM type (%s)\n", pN->Fname(), pN->Line(), ai.Value()) ; } } else if (ai.NameEQ("type") || ai.NameEQ("fldtype")) { // The attribute value will name the datatype
fs.m_pType = m_ADP.GetDatatype(ai.Value()) ; if (!fs.m_pType) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d Reading <fldspec> tag: Invalid DATA type (%s)\n", pN->Fname(), pN->Line(), ai.Value()) ; } } else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d Reading <fldspec> param (%s=%s)\n", pN->Fname(), pN->Line(), ai.Name(), ai.Value()) ; } }
if (rc == E_OK) rc = fs.Validate(m_pLog, pN->Fname(), *_fn, pN->Line()) ;
if (rc != E_OK) m_pLog->Log("Failed to add fldspec %s dataType %s htype %s rows=%03d cols=%03d size=%04d\n", *fs.m_Refname, fs.m_pType->txtType(), Htmltype2Txt(fs.htype), fs.nRows, fs.nCols, fs.nSize) ; else { // Add Field Specification to collection m_Fldspecs.Insert(fs.m_Refname, fs) ; m_pLog->Log("Added fldspec %s dataType %s htype %s rows=%03d cols=%03d size=%04d\n", *fs.m_Refname, fs.m_pType->txtType(), Htmltype2Txt(fs.htype), fs.nRows, fs.nCols, fs.nSize) ; }
return rc ; }
hzEcode hdsApp::_readMember (hdbClass* pClass, hzXmlNode* pN) { // Database and Data Class Config Read Functions // // Process a <member> tag to read in details of a class member. This will be as part of reading in a data or user class definition under either a <class> or <user> tag so this // function must only ever be called by _readClass() or _readUser(). // // The <member> tag contains database parameters necessary to define the data class member, namely member name, data type and population constraints. In addition, the <member> // tag can supply parameters that direct how the member is to be displayed in HTML - This is for the purposes of enhancing default forms for the data class. // // NOTE that if a member has a 'class' attribute, this must name a predefined data class. The member is then defined as having the named class as its data type. // // Arguments: 1) pClass The data class for which a member is being specified // 1) pN Pointer to XML node <member> // // Returns: E_SYNTAX In the event of incorrect parameters // E_OK If the <member> parameters are valid
_hzfunc("hdsApp::_readMember") ;
const hdbDatatype* pType = 0 ; // Data type const hdbClass* pComposite = 0 ; // Variable class (if applicable) const hdbMember* pMbr ; // Class member
hdsFldspec fs ; // Field specification that will be applied to member (will copy params from any supplied) hzAttrset ai ; // Attribute iterator hdsFldspec* pThisSpec = 0 ; // Pre-existing Field specification (if supplied) hzXmlNode* pN1 ; // Child nodes hzString str_Html ; // Html type hzString str_Vnam ; // Variable name hzString str_Title ; // Member title (As shown on scree before entry field) hzString str_Desc ; // Member description hzString str_Tab ; // Tab heading hzString str_Spec ; // Field specification if supplied hzString str_Src ; // Foreign key source - Specifies a pre-defined search to derive a HTML selector or other form of menu to aid filling in of the field. hzString str_pop ; // Member population control as string hzString str_Num_lo ; // Min value if supplied hzString str_Num_hi ; // Max value if supplied hzString str_FldSeq ; // Display order if supplied hzString str_ExpSeq ; // Export order if supplied hzString str_Dtype ; // Names a data type (expected alongside HTML display info) hzString str_Class ; // Names a pre-defined class (must not have HTML display info) //hzString str_Repos ; // Names a pre-defined class (must not have HTML display info) hzString str_Context ; // Name of this class and member - used for assigning class delta ids //uint32_t minPop = 0 ; // Minimum number of values the member can have //uint32_t maxPop = 1 ; // Maximum number of values the member can have uint32_t nRows = 0 ; // Display info: Number of rows uint32_t nCols = 0 ; // Display info: Number of columns uint32_t nSize = 0 ; // Display info: Max size (e.g of textarea) uint32_t pCount = 0 ; // Count of parameters hzHtmltype htype ; // HTML type hdbPopCtl popCtl ; // Member population control as enum bool bHtml = false ; // Set if any HTML display params are supplied hzEcode rc = E_OK ; // Return code
if (!pClass) Fatal("No hdbClass supplied\n") ; if (!pN) Fatal("No XML node supplied\n") ;
if (!pN->NameEQ("member")) Fatal("Incorrect node (%s) supplied. Must be <member>\n", pN->txtName()) ;
htype = HTMLTYPE_NULL ;
// Read the parameters for (ai = pN ; ai.Valid() ; ai.Advance()) { // Member name or class if (ai.NameEQ("name")) str_Vnam = ai.Value() ; else if (ai.NameEQ("class")) str_Class = ai.Value() ; //else if (ai.NameEQ("repos")) str_Repos = ai.Value() ;
// Population else if (ai.NameEQ("popCtl")) str_pop = ai.Value() ;
// Ranges else if (ai.NameEQ("numLo")) str_Num_lo = ai.Value() ; else if (ai.NameEQ("numHi")) str_Num_hi = ai.Value() ;
// Display and export order else if (ai.NameEQ("seq")) str_FldSeq = ai.Value() ; else if (ai.NameEQ("exp")) str_ExpSeq = ai.Value() ;
// Field spec referal else if (ai.NameEQ("spec")) str_Spec = ai.Value() ; else if (ai.NameEQ("fldspec")) str_Spec = ai.Value() ;
// OR field spec and data type explicit else if (ai.NameEQ("cols")) { bHtml = true ; nCols = ai.Value() ? atoi(ai.Value()) : 0 ; } else if (ai.NameEQ("rows")) { bHtml = true ; nRows = ai.Value() ? atoi(ai.Value()) : 0 ; } else if (ai.NameEQ("size")) { bHtml = true ; nSize = ai.Value() ? atoi(ai.Value()) : 0 ; } else if (ai.NameEQ("html")) { bHtml = true ; str_Html = ai.Value() ; } else if (ai.NameEQ("type")) { bHtml = true ; str_Dtype = ai.Value() ; }
// OR foreign entities (No fldspec if class specified) else if (ai.NameEQ("fldclass")) str_Class = ai.Value() ; // Pre-defined class. No display data needed so no fldspec allowed
// Desc is optional but rejected if a fldspec is supplied else if (ai.NameEQ("desc")) str_Desc = ai.Value() ;
// Tab is optional and wil be placed in the fldspec else if (ai.NameEQ("tab")) str_Tab = ai.Value() ; else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <member> Illegal param (%s=%s)\n", pN->Fname(), pN->Line(), ai.Name(), ai.Value()) ; }
pCount++ ; }
// If parameters are defined in sub-nodes for (pN1 = pN->GetFirstChild() ; rc == E_OK && pN1 ; pN1 = pN1->Sibling()) { if (pN1->NameEQ("tab")) str_Tab = pN1->m_fixContent ; else if (pN1->NameEQ("title")) str_Title = pN1->m_fixContent ; else if (pN1->NameEQ("desc")) str_Desc = pN1->m_fixContent ; else if (pN1->NameEQ("source")) str_Src = pN1->m_fixContent ; else if (pN1->NameEQ("range")) { for (ai = pN1 ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("numLo")) str_Num_lo = ai.Value() ; else if (ai.NameEQ("numHi")) str_Num_hi = ai.Value() ; else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <range> Illegal param (%s=%s)\n", pN->Fname(), pN1->Line(), ai.Name(), ai.Value()) ; } } } else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <member> Illegal subtag (%s)\n", pN->Fname(), pN1->Line(), ai.Name(), ai.Value()) ; } }
// Name is compulsory unless a class or repos attribute has been supplied in which case name is not allowed //if (str_Vnam && (str_Class || str_Repos)) if (str_Vnam && str_Class) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <member> If a member is named it cannot have an attribute of either 'class' or 'repos'\n", pN->Fname(), pN->Line()) ; }
if (!str_Vnam) { // if (str_Class && str_Repos) // { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <member> Either 'class' or 'repos' is allowed, not both\n", pN->Fname(), pN->Line()) ; }
// if (!str_Class && !str_Repos) if (!str_Class) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <member>, no name supplied\n", pN->Fname(), pN->Line()) ; } }
// Must be population data. Either 'lim' shorthand or both minPop and maxPop if (!str_pop) { rc = E_SYNTAX ; threadLog("Line %d: Population control not specified\n") ; } else { if (str_pop == "SingleOptional") popCtl = HDB_MBR_POP_SINGLE_OPTIONAL ; else if (str_pop == "SingleCompulsory") popCtl = HDB_MBR_POP_SINGLE_COMPULSORY ; else if (str_pop == "ArrayOptional") popCtl = HDB_MBR_POP_SINGLE_COMPULSORY ; else if (str_pop == "ArrayCompulsory") popCtl = HDB_MBR_POP_SINGLE_COMPULSORY ; else { rc = E_SYNTAX ; threadLog("Line %d: Population control must be either SingleOptional, SingleCompulsory, ArrayOptional or ArrayCompulsory. %s not accepted\n", *str_pop) ; } }
// Do we have a field spec? if (str_Spec) { // Field spec supplied so we just copy this. if (m_Fldspecs.Exists(str_Spec)) { fs = m_Fldspecs[str_Spec] ; pType = fs.m_pType ; } else { rc=E_SYNTAX ; m_pLog->Log("File %s Line %d <member> %s fldspec %s not defined\n", pN->Fname(), pN->Line(), *str_Vnam, *str_Spec) ; }
if (bHtml) { rc=E_SYNTAX ; m_pLog->Log("File %s Line %d <member> %s fldspec cannot co-exist with HTML info or data type\n", pN->Fname(), pN->Line(), *str_Vnam) ; } if (str_Src) { rc=E_SYNTAX ; m_pLog->Log("File %s Line %d <member> %s is a foreign class. No fldspec permitted\n", pN->Fname(), pN->Line(), *str_Vnam) ; }
// Init member rc = pClass->InitMember(str_Vnam, pType, popCtl) ; if (rc != E_OK) m_pLog->Log("File %s Line %d: <member> Could not add atomic member %s to class %s\n", pN->Fname(), pN->Line(), *str_Vnam, pClass->txtType()) ; else m_pLog->Log("Added atomic member %s of type %s to class %s\n", *str_Vnam, pType->txtType(), pClass->txtType()) ;
if (rc == E_OK) { pThisSpec = new hdsFldspec() ; *pThisSpec = fs ;
pMbr = pClass->GetMember(str_Vnam) ; pMbr->SetSpec(pThisSpec) ; pMbr->m_dsmTabSubject = str_Tab ; } }
// OR a class? // else if (str_Class || str_Repos) else if (str_Class) { // No field spec wanted and the member will in fact not use one.
if (str_Class) { pType = pComposite = m_ADP.GetPureClass(str_Class) ; if (!pComposite) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <member> %s class %s not defined\n", pN->Fname(), pN->Line(), *str_Vnam, *str_Class) ; } str_Vnam = str_Class ; }
/* if (str_Repos) { pRepos = m_ADP.GetObjRepos(str_Repos) ; if (pRepos) { pComposite = pRepos->Class() ; pType = pComposite ; } else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <member> %s class %s not defined\n", pN->Fname(), pN->Line(), *str_Vnam, *str_Class) ; } str_Vnam = str_Repos ; } */
if (str_Spec) { rc=E_SYNTAX ; m_pLog->Log("File %s Line %d <member> %s is a foreign class. No fldspec permitted\n", pN->Fname(), pN->Line(), *str_Vnam) ; } if (str_Src) { rc=E_SYNTAX ; m_pLog->Log("File %s Line %d <member> %s is a foreign class. No source permitted\n", pN->Fname(), pN->Line(), *str_Vnam) ; } if (bHtml) { rc=E_SYNTAX ; m_pLog->Log("File %s Line %d <member> %s is a foreign class. No HTML info permitted\n", pN->Fname(), pN->Line(), *str_Vnam) ; }
if (rc == E_OK && pComposite) { rc = pClass->InitMember(str_Vnam, pComposite, popCtl) ; if (rc != E_OK) m_pLog->Log("File %s Line %d: <member> Could not add composite variable %s to class %s\n", pN->Fname(), pN->Line(), *str_Vnam, pClass->txtType()) ; else m_pLog->Log("Added composite member %s of class %s to class %s\n", *str_Vnam, pComposite->txtType(), pClass->txtType()) ;
str_Context = pClass->txtType() ; str_Context += "." ; str_Context += str_Vnam ;
m_ADP.RegisterComposite(str_Context, pComposite) ; } }
// OR an explicit setting of data type and HTML info? else if (bHtml) { // Must be a type and all the HTML info. Must not be a class or a supplied field spec (as that is created here)
if (str_Spec) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <member> Cannot have fldspec with data type and HTML info\n", pN->Fname(), pN->Line()) ; } if (str_Class) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <member> Cannot have class with data type and HTML info\n", pN->Fname(), pN->Line()) ; }
if (!str_Dtype) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <member> %s No type supplied\n", pN->Fname(), pN->Line(), *str_Vnam) ; } else { pType = m_ADP.GetDatatype(str_Dtype) ; if (!pType) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <member> %s Type %s not defined\n", pN->Fname(), pN->Line(), *str_Vnam, *str_Dtype) ; } }
if (!str_Html) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <member> %s No HTML type supplied\n", pN->Fname(), pN->Line(), *str_Vnam) ; } else { if (str_Html == "TEXT") htype = HTMLTYPE_TEXT ; else if (str_Html == "PASSWORD") htype = HTMLTYPE_PASSWORD ; else if (str_Html == "TEXTAREA") htype = HTMLTYPE_TEXTAREA ; else if (str_Html == "CHECKBOX") htype = HTMLTYPE_CHECKBOX ; else if (str_Html == "RADIO") htype = HTMLTYPE_RADIO ; else if (str_Html == "SELECT") htype = HTMLTYPE_SELECT ; else if (str_Html == "HIDDEN") htype = HTMLTYPE_HIDDEN ; else if (str_Html == "FILE") htype = HTMLTYPE_FILE ; else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <member>: Invalid HTML type (%s)\n", pN->Fname(), pN->Line(), *str_Html) ; } }
// Validate HTML info switch (htype) { case HTMLTYPE_TEXT: // Full range of printable chars case HTMLTYPE_PASSWORD: // As text but char's won't print
if (nRows) m_pLog->Log("File %s Line %d: Note. Rows for TEXT/PASSWORD are always 1 so not required\n", pN->Fname(), pN->Line()) ; if (!nCols) nCols = 1 ; if (!nSize) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: No max size supplied\n", pN->Fname(), pN->Line()) ; } nRows = 1 ; break ;
case HTMLTYPE_TEXTAREA: // As text but a text area is described
if (!nRows) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: No row size supplied\n", pN->Fname(), pN->Line()) ; } if (!nCols) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: No col size supplied\n", pN->Fname(), pN->Line()) ; } if (!nSize) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: No max size supplied\n", pN->Fname(), pN->Line()) ; } break ;
case HTMLTYPE_SELECT: // A HTML selector
if (pType->Basetype() == BASETYPE_ENUM || pType->Basetype() == BASETYPE_STRING) { if (nRows || nCols || nSize) m_pLog->Log("File %s Line %d: Note. For Select field dimensions are not required\n", pN->Fname(), pN->Line()) ; break ; }
rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: <fldspec>: Data type of %s is incompatible to HTMLTYPE_SELECT\n", pN->Fname(), pN->Line(), pType->txtType()) ; break ;
case HTMLTYPE_CHECKBOX: // A HTML checkbox. Could be a boolean data type with just one checkbox or it could be a data enumeration meaning there will be // one checkbox per item in the enumeration. if (nSize) m_pLog->Log("File %s Line %d: Note. For Check-box field size is not required\n", pN->Fname(), pN->Line()) ;
if (pType->Basetype() == BASETYPE_BOOL) { if (!nRows) nRows = 1 ; if (!nCols) nCols = 1 ; break ; } if (pType->Basetype() == BASETYPE_ENUM) { if (!nRows) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: No row size supplied\n", pN->Fname(), pN->Line()) ; } if (!nCols) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: No col size supplied\n", pN->Fname(), pN->Line()) ; } break ; }
rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: <fldspec>: Data type of %s is incompatible to HTMLTYPE_CHECKBOX\n", pType->txtType()) ; break ;
case HTMLTYPE_RADIO: // A HTML radio button set must necessarily represent a data enumeration and have min/max population of 1 if (nSize) m_pLog->Log("File %s Line %d: Note. For Check-box/Radio field size is not required\n", pN->Fname(), pN->Line()) ;
if (pType->Basetype() == BASETYPE_ENUM) { if (!nRows) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: No row size supplied\n", pN->Fname(), pN->Line()) ; } if (!nCols) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: No col size supplied\n", pN->Fname(), pN->Line()) ; } break ; }
rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: <fldspec>: Data type of %s is incompatible to HTMLTYPE_RADIO\n", pType->txtType()) ; break ;
case HTMLTYPE_FILE: // File uploaded (as for text)
if (nRows) m_pLog->Log("File %s Line %d: Note. Rows for FILE are always 1 so not required\n", pN->Fname(), pN->Line()) ; if (!nCols) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: No col size supplied\n", pN->Fname(), pN->Line()) ; } if (!nSize) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: No max size supplied\n", pN->Fname(), pN->Line()) ; } nRows = 1 ; break ;
case HTMLTYPE_HIDDEN: // Hidden field
if (nRows || nCols || nSize) m_pLog->Log("File %s Line %d: Note. For Hidden field dimensions are not required\n", pN->Fname(), pN->Line()) ; break ; }
// Init member rc = pClass->InitMember(str_Vnam, pType, popCtl) ; if (rc != E_OK) m_pLog->Log("File %s Line %d: <member> Could not add atomic variable %s to class %s\n", pN->Fname(), pN->Line(), *str_Vnam, pClass->txtType()) ; else m_pLog->Log("Added atomic variable %s of type %s to class %s\n", *str_Vnam, pType->txtType(), pClass->txtType()) ;
// Create the field spec. pThisSpec = new hdsFldspec() ; pThisSpec->m_Refname = pClass->strType() + "." + str_Vnam ;
if (nCols) pThisSpec->nCols = nCols ; if (nRows) pThisSpec->nRows = nRows ; if (nSize) pThisSpec->nSize = nSize ; if (htype) pThisSpec->htype = htype ; if (pType) pThisSpec->m_pType = pType ; if (str_Title) pThisSpec->m_Desc = str_Title ; if (str_Desc) pThisSpec->m_Desc = str_Desc ; if (str_Tab) pThisSpec->m_Tab = str_Desc ; if (str_Src) pThisSpec->m_Source = str_Src ;
pMbr = pClass->GetMember(str_Vnam) ; pMbr->SetSpec(pThisSpec) ; pMbr->m_dsmTabSubject = str_Tab ; }
// If none of the above then invalid else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d Member %s Must have either fldspec, class, source OR data type plus HTML info\n", pN->Fname(), pN->Line(), *str_Vnam) ; }
return rc ; }
/* ** SECTION 3: Tables and Dirlist Config Read Functions */
hzEcode hdsApp::_readColumn (hdsCol& col, hzXmlNode* pN) { // Category: Tables and Dirlist Config Read Functions // // Obtain the table columns
_hzfunc("hdsApp::_readColumn") ;
hzAttrset ai ; // Attribute iterator hzString css ; // Default css hzString bgcol_head ; // Background color for column header hzString bgcol_data ; // Background color for column data (even) hzString bgcol_alt ; // Background color for column data (odd) hzString bgcol ; // Default Background color hzEcode rc = E_OK ; // Return code
col.Clear() ;
if (!pN->NameEQ("xcol")) { m_pLog->Log("File %s Line %d <xcol> Illegal subtag <%s> Only <xcol> allowed\n", pN->Fname(), pN->Line(), pN->txtName()) ; return E_SYNTAX ; }
css = bgcol_head = bgcol_data = bgcol_alt = bgcol = (char*) 0 ;
for (ai = pN ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("title")) col.m_Title = ai.Value() ; else if (ai.NameEQ("member")) col.m_Member = ai.Value() ; else if (ai.NameEQ("css_head")) col.m_CSS_head = ai.Value() ; else if (ai.NameEQ("css_data")) col.m_CSS_data = ai.Value() ; else if (ai.NameEQ("css")) css = ai.Value() ; else if (ai.NameEQ("bgcol_head")) bgcol_head = ai.Value() ; else if (ai.NameEQ("bgcol_data")) bgcol_data = ai.Value() ; else if (ai.NameEQ("bgcol_alt")) bgcol_alt = ai.Value() ; else if (ai.NameEQ("bgcolor")) bgcol = ai.Value() ; else if (ai.NameEQ("size")) col.m_nSize = ai.Value() ? atoi(ai.Value()) : 0 ; else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: <xcol> Bad param (%s=%s)\n", pN->Fname(), pN->Line(), ai.Name(), ai.Value()) ; } }
// Check column title if (!col.m_Title) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <xcol> No title suplied\n", pN->Fname(), pN->Line()) ; } if (!col.m_Member) col.m_Member = col.m_Title ;
// Assert/check CSS settings if (css) { if (!col.m_CSS_head) col.m_CSS_head = css ; if (!col.m_CSS_data) col.m_CSS_data = css ; } if (!col.m_CSS_head) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <xcol> No title suplied\n", pN->Fname(), pN->Line()) ; } if (!col.m_CSS_data) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <xcol> No title suplied\n", pN->Fname(), pN->Line()) ; }
// Assert/check background colors if (bgcol) { if (!bgcol_head) bgcol_head = bgcol ; if (!bgcol_data) bgcol_data = bgcol ; if (!bgcol_alt) bgcol_alt = bgcol ; } if (!bgcol_head) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <xcol> No bgcolor for head suplied\n", pN->Fname(), pN->Line()) ; } if (!bgcol_data) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <xcol> No bgcolor for data suplied\n", pN->Fname(), pN->Line()) ; } if (!bgcol_alt) bgcol_alt = bgcol_data ;
col.m_bgcol_head = bgcol_head ? atoi(*bgcol_head) : 0 ; col.m_bgcol_data = bgcol_data ? atoi(*bgcol_data) : 0 ; col.m_bgcol_alt = bgcol_alt ? atoi(*bgcol_alt) : 0 ;
return rc ; }
hdsVE* hdsApp::_readDirlist (hzXmlNode* pN, hdsResource* pPage) { // Category: Tables and Dirlist Config Read Functions // // Read the <xdirlist> tag. // // The <xdirlist> tag translates a directory listing into a HTML table. <xdirlist> is an active tag and so any page or article containing an <xdirlist> is automatically deemed // active and will always be generated. // // <xdirlist> has a compulsory attribute of (directory) path, and optional attributes to specify filtering criteria and sort order, as well the CSS class, number of rows, row // height and table width. // // The resulting HTML table automatically displays a scroll bar on the right, if there are too many directory entries to fit the stated display area. Display colunms are added // with the <xcol> subtag. The <ifnone> subtag specifies what HTML is be produced in the event of no entries found. There can also be <header> and <footer> subtags. // // Argument: pN The current XML node expected to be a <xdirlist> tag // // Returns: Pointer to diagram visual entity
_hzfunc("hdsApp::_readDirlist") ;
_tagArg tga ; // Tag argument for _readTag() hdsCol col ; // Column hzAttrset ai ; // Attribute iterator hdsDirlist* pDirlist ; // Table hzXmlNode* pN1 ; // Subtag probe hzXmlNode* pN2 ; // Subtag probe hdsVE* thisVE ; // Visible entity/active entity uint32_t flags ; // Needed for read tag function hzEcode rc = E_OK ; // Return code
if (!pN) Fatal("No node supplied\n") ; if (!pPage) Fatal("No page supplied\n") ;
thisVE = pDirlist = new hdsDirlist(this) ; thisVE->m_strPretext = pN->txtPtxt() ; thisVE->m_Line = pN->Line() ; thisVE->m_Indent = pN->Level() ; thisVE->m_flagVE |= VE_CT_ACTIVE ;
// Clear the column col.Clear() ;
for (ai = pN ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("directory")) pDirlist->m_Directory = ai.Value() ; else if (ai.NameEQ("criteria")) pDirlist->m_Criteria = ai.Value() ; else if (ai.NameEQ("css")) pDirlist->m_CSS = ai.Value() ; else if (ai.NameEQ("rows")) pDirlist->m_nRows = ai.Value() ? atoi(ai.Value()) : 0 ; else if (ai.NameEQ("height")) pDirlist->m_Height = ai.Value() ? atoi(ai.Value()) : 0 ; else if (ai.NameEQ("width")) pDirlist->m_Width = ai.Value() ? atoi(ai.Value()) : 0 ; else if (ai.NameEQ("order")) { if (ai.ValEQ("name/asc")) pDirlist->m_Order = 1 ; else if (ai.ValEQ("name/dec")) pDirlist->m_Order = 2 ; else if (ai.ValEQ("date/asc")) pDirlist->m_Order = 3 ; else if (ai.ValEQ("date/dec")) pDirlist->m_Order = 4 ; else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: <xdirlist> Bad sort param. Only date/asc|date/dec|name/asc|name/dec allowed\n", pN->Fname(), pN->Line()) ; } } else { m_pLog->Log("File %s Line %d: <xdirlist> Only attrs allowed are method|source|criteria|rows|edit. Bad param (%s=%s)\n", pN->Fname(), pN->Line(), ai.Name(), ai.Value()) ; rc = E_SYNTAX ; } }
if (!pDirlist->m_Directory) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <xdirlist> Directory not suplied\n", pN->Fname(), pN->Line()) ; } if (!pDirlist->m_Criteria) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <xdirlist> Criteria not suplied\n", pN->Fname(), pN->Line()) ; } if (!pDirlist->m_Order) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <xdirlist> Sort order not suplied\n", pN->Fname(), pN->Line()) ; }
if (!pDirlist->m_Height) pDirlist->m_Height = 500 ; if (!pDirlist->m_Width) pDirlist->m_Width = 90 ;
// Obtain the table columns tga.m_pLR = pPage ; for (pN1 = pN->GetFirstChild() ; rc == E_OK && pN1 ; pN1 = pN1->Sibling()) { pN2 = pN1->GetFirstChild() ;
if (pN1->NameEQ("xcol")) { rc = _readColumn(col, pN1) ;
if (rc == E_OK) pDirlist->m_Cols.Add(col) ; } else if (pN1->NameEQ("ifnone")) { // Gather subtags to be rendered in the event of no files/directories found if (pDirlist->m_pNone) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <xdirlist> Non-singular <ifnone>\n", pN->Fname(), pN1->Line(), pN1->txtName()) ; break ; }
pDirlist->m_pNone = _readTag(&tga, pN2, flags, 0, 0) ; if (!pDirlist->m_pNone) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <xdirlist> Empty <ifnone>\n", pN->Fname(), pN1->Line(), pN1->txtName()) ; break ; } } else if (pN1->NameEQ("header")) { // Gather subtags to be rendered before the list in the event of files/directories found if (pDirlist->m_pHead) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <xdirlist> Non-singular <header>\n", pN->Fname(), pN1->Line(), pN1->txtName()) ; break ; }
pDirlist->m_pHead = _readTag(&tga, pN1, flags, 0, 0) ; if (!pDirlist->m_pHead) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <xdirlist> Empty <header>\n", pN->Fname(), pN1->Line(), pN1->txtName()) ; break ; } } else if (pN1->NameEQ("footer")) { // Gather subtags to be rendered after the list in the event of files/directories found if (pDirlist->m_pFoot) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <xdirlist> Non-singular <footer>\n", pN->Fname(), pN1->Line(), pN1->txtName()) ; break ; }
pDirlist->m_pFoot = _readTag(&tga, pN1, flags, 0, 0) ; if (!pDirlist->m_pFoot) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <xdirlist> Empty <footer>\n", pN->Fname(), pN1->Line(), pN1->txtName()) ; break ; } } else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <xdirlist> Illegal subtag <%s> Only <xcol> allowed\n", pN->Fname(), pN1->Line(), pN1->txtName()) ; } }
// Check the colums for the correct file directives
if (rc != E_OK) { delete pDirlist ; return 0 ; }
return thisVE ; }
hdsVE* hdsApp::_readTable (hzXmlNode* pN, hdsResource* pPage) { // Category: Tables and Dirlist Config Read Functions // // Read the <xtable> tag. // // The <xtable> tag defines how a list of items is to be compiled and presented as a HTML table. Currently the items can only be data objects selected from // a repository. However the intention is to extend the remit of <xtable> to include other items. Directory entries will not be included however, as these // would be handled by the <xdirlist> tag. // // In its present form, the <xtable> tag has two compulsory attributes to specify the respository and the filtering criteria. It has other non-compulsory // attributes to specify CSS class, the number of rows, row height and overall width. // // The HTML table produced will automatically display a scroll bar on the right hand side if there are too many directory entries to fit the stated display // area. The colunms to be displayed are all standard directory entry properties and are specified with the <xcol> sub-tag. The <ifnone> sub-tag specifies // what HTML is be produced in the event of no entries found. There can also be <header> and <footer> sub-tags to define what HTML goes above and below the // directory entry table. // // Argument: pN The current XML node in the configs, expected to be a <xtable> tag // // Returns: Pointer to diagram visual entity
_hzfunc("hdsApp::_readTable") ;
const hdbMember* pMbr ; // Data class member
_tagArg tga ; // Tag argument for _readTag() hdsCol col ; // Column hzAttrset ai ; // Attribute iterator const hdbClass* pClass ; // Data class hdsTable* pTable ; // Table hzXmlNode* pN1 ; // Subtag probe hdsVE* thisVE ; // Visible entity/active entity hzString css ; // Default css hzString bgcol_head ; // Background color for column header hzString bgcol_data ; // Background color for column data (even) hzString bgcol_alt ; // Background color for column data (odd) hzString bgcol ; // Default Background color uint32_t flags ; // Needed for read tag function uint32_t bErr = 0 ; // Error condition hzEcode rc = E_OK ; // Return code
thisVE = pTable = new hdsTable(this) ; thisVE->m_strPretext = pN->txtPtxt() ; thisVE->m_Line = pN->Line() ; thisVE->m_Indent = pN->Level() ; thisVE->m_flagVE |= VE_CT_ACTIVE ;
for (ai = pN ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("repos")) pTable->m_Repos = ai.Value() ; else if (ai.NameEQ("criteria")) pTable->m_Criteria = ai.Value() ; else if (ai.NameEQ("css")) pTable->m_CSS = ai.Value() ; else if (ai.NameEQ("rows")) pTable->m_nRows = ai.Value() ? atoi(ai.Value()) : 0 ; else if (ai.NameEQ("width")) pTable->m_nWidth = ai.Value() ? atoi(ai.Value()) : 0 ; else if (ai.NameEQ("height")) pTable->m_nHeight = ai.Value() ? atoi(ai.Value()) : 0 ; else if (ai.NameEQ("edit")) pTable->m_bEdit = ai.ValEQ("true") ; else { bErr=1 ; m_pLog->Log("File %s Line %d: <xtable> Only attrs allowed are method|source|criteria|rows|edit. Bad param (%s=%s)\n", pN->Fname(), pN->Line(), ai.Name(), ai.Value()) ; } }
if (!pTable->m_Repos) { bErr=1; m_pLog->Log("File %s Line %d <xtable> Source not suplied\n", pN->Fname(), pN->Line()) ; } if (!pTable->m_Criteria) { bErr=1; m_pLog->Log("File %s Line %d <xtable> Criteria not suplied\n", pN->Fname(), pN->Line()) ; }
if (pTable->m_nWidth < 1 || pTable->m_nWidth > 100) { bErr=1 ; m_pLog->Log("File %s Line %d: <xtable> Width is a percentage and must be between 1 and 100\n", pN->Fname(), pN->Line()) ; }
if (pTable->m_nHeight < 100 || pTable->m_nHeight > 900) { bErr=1 ; m_pLog->Log("File %s Line %d: <xtable> Hight (in pixels) must be between 100 and 900\n", pN->Fname(), pN->Line()) ; }
if (bErr) { delete pTable ; return 0 ; }
pClass = m_ADP.GetPureClass(pTable->m_Repos) ; if (!pClass) { bErr=1; m_pLog->Log("File %s Line %d <xtable> Class not established for repos %s\n", pN->Fname(), pN->Line(), *pTable->m_Repos) ; } else { pTable->m_pRepos = m_ADP.GetObjRepos(pTable->m_Repos) ; if (!pTable->m_pRepos) { bErr=1 ; m_pLog->Log("File %s Line %d <xtable> Repository %s not defined\n", pN->Fname(), pN->Line(), *pTable->m_Repos) ; } }
if (bErr) { delete pTable ; return 0 ; }
// Obtain the table columns tga.m_pLR = pPage ; for (pN1 = pN->GetFirstChild() ; rc == E_OK && pN1 ; pN1 = pN1->Sibling()) { if (pN1->NameEQ("xcol")) { rc = _readColumn(col, pN1) ;
if (rc == E_OK) { pMbr = pClass->GetMember(col.m_Member) ; if (!pMbr) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <xcol> No such member as %s\n", pN->Fname(), pN1->Line(), *col.m_Member) ; break ; } col.m_mbrNo = pMbr->Posn() ; pTable->m_Cols.Add(col) ; } } else if (pN1->NameEQ("ifnone")) { // Gather subtags to be rendered in the event of no files/directories found if (pTable->m_pNone) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <xtable> Non-singular <ifnone>\n", pN->Fname(), pN1->Line(), pN1->txtName()) ; break ; }
if (pN1->GetFirstChild()) pTable->m_pNone = _readTag(&tga, pN1->GetFirstChild(), flags, 0, 0) ;
if (!pTable->m_pNone) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <xtable> Empty <ifnone>\n", pN->Fname(), pN1->Line(), pN1->txtName()) ; break ; } } else if (pN1->NameEQ("header")) { // Gather subtags to be rendered before the list in the event of files/directories found if (pTable->m_pHead) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <xtable> Non-singular <header>\n", pN->Fname(), pN1->Line(), pN1->txtName()) ; break ; }
pTable->m_pHead = _readTag(&tga, pN1, flags, 0, 0) ; if (!pTable->m_pHead) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <xtable> Empty <header>\n", pN->Fname(), pN1->Line(), pN1->txtName()) ; break ; } } else if (pN1->NameEQ("footer")) { // Gather subtags to be rendered after the list in the event of files/directories found if (pTable->m_pFoot) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <xtable> Non-singular <footer>\n", pN->Fname(), pN1->Line(), pN1->txtName()) ; break ; }
pTable->m_pFoot = _readTag(&tga, pN1, flags, 0, 0) ; if (!pTable->m_pFoot) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <xtable> Empty <footer>\n", pN->Fname(), pN1->Line(), pN1->txtName()) ; break ; } } else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <xtable> Illegal subtag <%s> Only <xcol> allowed\n", pN->Fname(), pN1->Line(), pN1->txtName()) ; } }
return rc == E_OK ? thisVE : 0 ; }
hzEcode hdsApp::_readFixDir (hzXmlNode* pN) { // Category: Tables and Dirlist Config Read Functions // // Read in an <xfixdir> tag and place the content as a fixed file in the app's m_Fixed map of URLs to fixed HTML or text content // // Arguments: 1) pN Current XML node // // Returns: E_SYNTAX If there is a syntax error // E_OK If no errors occured
_hzfunc("hdsApp::_readFixDir") ;
hzVect<hzDirent> files ; // All files found in the directory matching the criteria
ifstream is ; // Input stream hzDirent de ; // Individual directory entry hzAttrset ai ; // Attribute iterator const char* j ; // For file endings and MIME type hdsFile* pFix ; // Passive file uint64_t now ; // Start of zip uint64_t then ; // End of zip hzString absPath ; // Fixed file source directory (absolute, incl doc root) hzString directory ; // Fixed file source directory (relative, not incl doc root) hzString criteria ; // File search criteria uint32_t ln ; // Line number uint32_t n ; // File iterator hzEcode rc = E_OK ; // Return code
if (!pN) Fatal("No node supplied\n") ;
ln = pN->Line() ;
if (!pN->NameEQ("xfixdir")) { m_pLog->Log("File %s Line %d Expected <xfixdir> got <%s>\n", pN->Fname(), ln, pN->txtName()) ; return E_SYNTAX ; }
for (ai = pN ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("dir")) directory = ai.Value() ; else if (ai.NameEQ("criteria")) criteria = ai.Value() ; else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <xfixdir> Bad params (%s=%s)\n", pN->Fname(), ln, ai.Name(), ai.Value()) ; } }
// Obtain the directory listing absPath = m_Docroot + "/" + directory ;
rc = ReadDir(files, absPath, criteria) ; if (rc != E_OK) { m_pLog->Log("File %s Line %d <xfixdir> Could not read directory %s. err=%s\n", pN->Fname(), ln, *absPath, Err2Txt(rc)) ; return rc ; }
// Read in content - Either by loading file or from the node content for (n = 0 ; n < files.Count() ; n++) { de = files[n] ;
if (!de.Size()) { m_pLog->Log("File %s Line %d <xfixdir> Igoring empty file %s\n", pN->Fname(), ln, de.txtName()) ; continue ; }
// Load each file pFix = new hdsFile() ;
pFix->m_Url = "/" + directory + "/" + de.strName() ; pFix->m_filepath = absPath + "/" + de.strName() ; pFix->m_Title = de.strName() ;
j = strrchr(de.txtName(), CHAR_PERIOD) ; if (j) pFix->m_Mimetype = Str2Mimetype(j) ;
is.open(*pFix->m_filepath) ; if (is.fail()) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <xfixdir> Content file %s cannot be opened\n", pN->Fname(), ln, *pFix->m_filepath) ; } else { pFix->m_rawValue << is ; is.close() ; m_pLog->Log("File %s Line %d <xfixdir> Content file %s opened and has %d bytes\n", pN->Fname(), ln, *pFix->m_filepath, pFix->m_rawValue.Size()) ; } is.clear() ;
if (!pFix->m_rawValue.Size()) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <xfixdir> Content file %s empty\n", pN->Fname(), ln, *pFix->m_filepath) ; }
if (rc == E_OK) { now = RealtimeNano() ; Gzip(pFix->m_zipValue, pFix->m_rawValue) ; then = RealtimeNano() ; //m_Fixed.Insert(pFix->m_Path, pFix) ; m_ResourcesPath.Insert(pFix->m_Url, pFix) ; m_pLog->Log("Added fixed page %s (%d,%d) %u nS\n", *pFix->m_Url, pFix->m_rawValue.Size(), pFix->m_zipValue.Size(), then - now) ; } }
return rc ; }
hzEcode hdsApp::_readMiscDir (hzXmlNode* pN) { // Category: Tables and Dirlist Config Read Functions // // Read in an <xfixdir> tag and place the content as a fixed file in the app's m_Fixed map of URLs to fixed HTML or text content // // Arguments: 1) pN Current XML node // // Returns: E_SYNTAX If there is a syntax error // E_OK If no errors occured
_hzfunc("hdsApp::_readMiscDir") ;
hzVect<hzDirent> files ; // All files found in the directory matching the criteria (if any)
ifstream is ; // Input stream hzDirent de ; // Individual directory entry hzAttrset ai ; // Attribute iterator hzString directory ; // Fixed file source directory (relative, not incl doc root) hzString criteria ; // File search criteria hzString fpath ; // File path uint32_t ln ; // Line number uint32_t n ; // File iterator hzEcode rc = E_OK ; // Return code
if (!pN) Fatal("No node supplied\n") ;
ln = pN->Line() ;
if (!pN->NameEQ("xmiscdir")) { m_pLog->Log("File %s Line %d Expected <xmiscdir> got <%s>\n", pN->Fname(), ln, pN->txtName()) ; return E_SYNTAX ; }
for (ai = pN ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("dir")) directory = ai.Value() ; else if (ai.NameEQ("criteria")) criteria = ai.Value() ; else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <xmiscdir> Bad params (%s=%s)\n", pN->Fname(), ln, ai.Name(), ai.Value()) ; } }
// Obtain the directory listing rc = ReadDir(files, directory, criteria) ; if (rc != E_OK) { m_pLog->Log("File %s Line %d <xmiscdir> Could not read directory %s. err=%s\n", pN->Fname(), ln, *directory, Err2Txt(rc)) ; return E_SYNTAX ; }
// Read in content - Either by loading file or from the node content for (n = 0 ; n < files.Count() ; n++) { de = files[n] ;
if (!de.Size()) { m_pLog->Log("File %s Line %d <xmiscdir> Igoring empty file %s\n", pN->Fname(), ln, de.txtName()) ; continue ; }
// Load each file fpath = de.Path() + "/" + de.strName() ; m_Misc.Insert(fpath, de) ; }
return rc ; }
/* ** SECTION 4: hdsNavtree Config Read Functions */
hzEcode hdsApp::_readXtreeItem (hzXmlNode* pN, hdsNavtree* pAG) { // Category: Config Read Functions (Navtree) // // Process an <xtreeItem> tag to add an article (tree item) to an article group (navtree) // // Each article must have a title (what the user sees), a URL for an AJAX GET, a node identifier (unique within the article group), and a parent node identifier (to facilitate // article hierarchy within the group. // can be effected. Article content is supplied as the <xtreeItem> content and the parameters given in attributes as follows:- // // 1) parent Parent node id. This will be null if the item(s) to be added are to be added directly to the root. // 2) id This is name that will also be used as URL. It has to be unique. // 3) link True/false. If true the added item will have a link in the resultant navigation tree. // 4) title The title that will appear as the selectable item name in the navigation tree. // // Arguments: 1) pN Current node, expected to be <xtreeItem> tag // 2) pAG Current article group // // Returns: E_SYNTAX If there is a syntax error // E_OK If no errors occured
_hzfunc("hdsApp::_readXtreeItem") ;
hzList<hdsVE*>::Iter ih ; // Html entity iterator
hzHttpEvent httpEv ; // Artificial HTTP event (for language) _tagArg tga ; // Tag argument for _readTag() hzAttrset ai ; // Attribute iterator hdsArticleStd* pArt ; // Article pointer hzXmlNode* pN1 ; // Subtag probe hdsVE* pVE ; // Set if a HTML entity is found hzMD5 artMD5 ; // Article MD5 digest hzChain artXML ; // Article XML hzChain Z ; // For generating article HTML hzChain X ; // For generating article HTML uint64_t now ; // Start of zip uint64_t then ; // Start of zip hzString parent ; // Article parent name (if null, parent is the article group) hzString refname ; // Article ref name (compulsory) hzString title ; // Article title (compulsory as without, no entry in tree) hzString strVal ; // Temp string for text value uint32_t bScripts = 0 ; // Needed for read tag bool bHead = false ; // Add item/head bool bDisp = false ; // Display open/close by default hzEcode rc = E_OK ; // Return code
if (!pN) Fatal("No node supplied\n") ; if (!pAG) Fatal("No article group supplied\n") ;
if (pN->NameEQ("xtreeItem")) bHead = false ; else if (pN->NameEQ("xtreeHead")) bHead = true ; else { m_pLog->Log("File %s Line %d Expected <xtreeItem> or <xtreeHead> got <%s>\n", pN->Fname(), pN->Line(), pN->txtName()) ; return E_SYNTAX ; }
// Get XML value of the xpage tag and obtain digest pN->Export(artXML) ; artMD5.CalcMD5(artXML) ;
// The attr will be the name of the form to which the handler applies for (ai = pN ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("parent")) parent = ai.Value() ; else if (ai.NameEQ("id")) refname = ai.Value() ; else if (ai.NameEQ("tdstamp")) strVal = ai.Value() ; else if (ai.NameEQ("hdln")) title = ai.Value() ; else if (ai.NameEQ("display")) bDisp = ai.ValEQ("open") ; else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <xtreeItem> tag: Illegal attribute %s=%s\n", pN->Fname(), pN->Line(), ai.Name(), ai.Value()) ; } }
if (!refname) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <%s> tag: No name supplied\n", pN->Fname(), pN->Line(), pN->txtName()) ; } if (!title) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <%s> tag: No title supplied\n", pN->Fname(), pN->Line(), pN->txtName()) ; }
if (pAG->Exists(refname)) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <xtreeItem> tag: %s already exists\n", pN->Fname(), pN->Line(), *refname) ; }
if (parent) { if (!pAG->Exists(parent)) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <%s> tag: parent tag %s not found\n", pN->Fname(), pN->Line(), pN->txtName(), *parent) ; } }
if (rc != E_OK) return rc ;
if (bHead) { pAG->AddHead(parent, refname, title, bDisp) ; m_pLog->Log("Added header ref-%s (%s)\n", *refname, *title) ; return rc ; }
// Adding an article pArt = new hdsArticleStd() ; pArt->m_Refname = refname ; pArt->m_Title = title ; pArt->m_Url = refname ;
pAG->AddItem(parent, refname, title, pArt, bDisp) ;
//rc = pArt->m_USL.SetArticle(pAG->m_USL, pAG->Count()) ; pArt->m_Stamp = strVal ;
// Get article content from subtags tga.m_pLR = pArt ; for (pN1 = pN->GetFirstChild() ; rc == E_OK && pN1 ; pN1 = pN1->Sibling()) { if (pN->NameEQ("xobject")) { // Handle <xobject> tag for (ai = pN ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("repos")) {} else if (ai.NameEQ("class")) {} else if (ai.NameEQ("objId")) {} else //{ rc = E_SYNTAX ; m_cfgErr.Printf("%s. File %s Line %d. <xobject> Illegal param (%s=%s)\n", pN->Fname(), pN->Line(), ai.Name(), ai.Value()) ; } { rc = E_SYNTAX ; m_pLog->Log("%s. File %s Line %d. <xobject> Illegal param (%s=%s)\n", pN->Fname(), pN->Line(), ai.Name(), ai.Value()) ; } } continue ; }
pVE = _readTag(&tga, pN1, bScripts, 0, 0) ; if (!pVE) rc = E_SYNTAX ; else pArt->AddVisent(pVE) ; }
if (rc != E_OK) return rc ;
// Assign language uids to the article's page elements //AssignVisentIDs(pArt->m_VEs, pArt->m_flagVE, pArt->m_USL) ;
httpEv.m_pContextLang = m_pDfltLang ; if (!(pArt->m_flagVE & VE_ACTIVE)) { //pArt->Generate(Z, &httpEv) ; pArt->EvalHtml(Z) ;
if (Z.Size()) { // Assign article content to fixed buffers, one for unzipped and the other as zipped.
//strVal = Z ; pArt->m_rawHTML = Z ; //m_pDfltLang->m_rawHTML.Insert(pArt->m_USL, strVal) ;
now = RealtimeNano() ; Gzip(X, Z) ; then = RealtimeNano() ;
//strVal = X ; pArt->m_zipHTML = X ; //m_pDfltLang->m_zipHTML.Insert(pArt->m_USL, strVal) ; } }
m_pLog->Log("Added article ref-%s (%s) of %d %d bytes %u nS\n", *pArt->m_Url, *pArt->m_Title, X.Size(), Z.Size(), then - now) ; return rc ; }
hzEcode hdsApp::_readXtreeDcl (hzXmlNode* pN, hdsPage* pPage) { // Category: Config Read Functions (Navtree) // // Process an <xtreeDcl> tag to declare a hdsNavtree instance. Note that an <xtreeDcl> tag appearing OUTSIDE the scope of an <xpage> tag declares a public navtree (that can be // referenced by multiple pages), while an <xtreeDcl> tag WITHIN an <xpage> declares a private tree (may only be used within the page). // // Arguments: 1) pN Current config node, expected to be <xtree> tag // 2) pPage The Host page, if applicable // // Returns: E_SYNTAX If there is a syntax error // E_OK If no errors occured
_hzfunc("hdsApp::_readXtreeDcl") ;
hzAttrset ai ; // Attribute iterator hzXmlNode* pN1 ; // Subtag probe hdsNavtree* pAG ; // Article group pointer hzString name ; // Article group name hzString page ; // Article group hostpage) hzEcode rc = E_OK ; // Return code
if (!pN) Fatal("No node supplied\n") ;
if (!pN->NameEQ("xtreeDcl")) { m_pLog->Log("File %s Line %d Expected <xtreeDcl> got <%s>\n", pN->Fname(), pN->Line(), pN->txtName()) ; return E_SYNTAX ; }
// The attr will be the name of the article group for (ai = pN ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("name")) name = ai.Value() ; else if (ai.NameEQ("page")) page = ai.Value() ; else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <xtreeDcl> tag: Illegal attr %s=%s\n", pN->Fname(), pN->Line(), ai.Name(), ai.Value()) ; } }
if (!name) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <xtreeDcl> tag: No name attr\n", pN->Fname(), pN->Line()) ; } if (!page) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <xtreeDcl> tag: No host page\n", pN->Fname(), pN->Line()) ; }
if (rc != E_OK) return rc ;
pAG = new hdsNavtree() ; pAG->m_Groupname = name ; //rc = pAG->m_USL.SetGroup(m_ArticleGroups.Count()) ; pAG->m_Hostpage = page ; m_ArticleGroups.Insert(pAG->m_Groupname, pAG) ;
// Read in list of related articles for (pN1 = pN->GetFirstChild() ; rc == E_OK && pN1 ; pN1 = pN1->Sibling()) { if (pN1->NameEQ("xArticle")) rc = _readXtreeItem(pN1, pAG) ; else if (pN1->NameEQ("xtreeItem")) rc = _readXtreeItem(pN1, pAG) ; else if (pN1->NameEQ("xtreeHead")) rc = _readXtreeItem(pN1, pAG) ; else if (pN1->NameEQ("xpage")) rc = _readPage(pN) ; else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <xtreeDcl> Illegal subtag <%s>\n", pN->Fname(), pN1->Line(), pN1->txtName()) ; } }
return rc ; }
hdsVE* hdsApp::_readXtreeCtl (hzXmlNode* pN) { // Category: Config Read Functions (Navtree) // // Process an <xtreeCtl> tag, which controls navtree manifestation. <xtreeCtl> should appear only within the page that hosts the navtree. The <xtreeCtl> tag has the following // attributes:- // // group Name of group. This is compulsory and must name an existing article group, i.e. the group must be defined in the configs prior to use of the <xtreeCtl> tag. // article The initial display article for the host page. // show Display directive. This is compulsory and must have a value of 'title', 'content' or 'navtree'. If show is not 'navtree' the article attribute is compulsory. // // Argument: pN Current XML node (expected to be an <xtreectl> tag). // // Returns: Pointer to visible entity
_hzfunc("hdsApp::_readXtreeCtl") ;
hzAttrset ai ; // Attribute iterator hdsNavtree* pAG ; // Article group pointer hdsArtref* pAR ; // Article pointer hdsVE* thisVE ; // Visible entity hzString grpName ; // Article group name hzString artName ; // Article name hzString vname ; // Article name uint32_t nShow = 0 ; // Show title or content uint32_t bErr = 0 ; // Error
if (!pN) Fatal("No node supplied\n") ;
if (!pN->NameEQ("xtreeCtl")) { m_pLog->Log("File %s Line %d Expected <xtreeCtl> got <%s>\n", pN->Fname(), pN->Line(), pN->txtName()) ; return 0 ; }
for (ai = pN ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("group")) grpName = ai.Value() ; else if (ai.NameEQ("article")) artName = ai.Value() ; else if (ai.NameEQ("show")) { if (ai.ValEQ("title")) nShow = 100 ; else if (ai.ValEQ("content")) nShow = 200 ; else if (ai.ValEQ("navtree")) nShow = 300 ; else { bErr=1 ; m_pLog->Log("File %s Line %d <xtreeCtl> Bad show value (must be title/content) not %s\n", pN->Fname(), pN->Line(), ai.Value()) ; } } else { bErr=1 ; m_pLog->Log("File %s Line %d <xtreeCtl> Bad param (%s=%s)\n", pN->Fname(), pN->Line(), ai.Name(), ai.Value()) ; } }
if (!grpName) { bErr=1 ; m_pLog->Log("File %s Line %d <xtreeCtl> no group name attr supplied\n", pN->Fname(), pN->Line()) ; } if (!nShow) { bErr=1 ; m_pLog->Log("File %s Line %d <xtreeCtl> no show directive supplied\n", pN->Fname(), pN->Line()) ; }
if (nShow < 300) //{ if (!artName) { bErr=1 ; m_pLog->Log("File %s Line %d <xtreeCtl> no article name attr supplied\n", pN->Fname(), pN->Line()) ; } //}
if (bErr) return 0 ;
pAG = m_ArticleGroups[grpName] ; if (!pAG) //{ bErr=1 ; m_pLog->Log("File %s Line %d article group %s non-existant\n", pN->Fname(), pN->Line(), *grpName) ; } { m_pLog->Log("File %s Line %d article group %s non-existant\n", pN->Fname(), pN->Line(), *grpName) ; } else { if (nShow < 300) { if (!memcmp(*artName, "@resarg;/", 9)) { vname = *artName + 9 ; if (!pAG->Exists(vname)) { bErr=1 ; m_pLog->Log("File %s Line %d <xtreeCtl> Default article %s non-existant\n", pN->Fname(), pN->Line(), *vname) ; } } else { if (!pAG->Exists(artName)) { bErr=1 ; m_pLog->Log("File %s Line %d <xtreeCtl> Article %s non-existant\n", pN->Fname(), pN->Line(), *artName) ; } } } }
if (bErr) return 0 ;
thisVE = pAR = new hdsArtref(this) ; thisVE->m_Line = pN->Line() ; thisVE->m_Indent = pN->Level() ; thisVE->m_flagVE |= VE_CT_ACTIVE ; pAR->m_Group = grpName ; pAR->m_Article = artName ; pAR->m_Show = nShow ;
return pAR ; }
/* ** SECTION 5: Forms Config Read Functions */
hzEcode hdsApp::_readExec (hzXmlNode* pN, hzList<hdsExec*>& execList, hdsPage* pPage, hdsFormhdl* pFhdl) { // Read in a set of one or more Dissemino exec commands in a <procdata> tag. // // Arguments: 1) pN Current XML node being a <procdata> tag // 2) execList The list of executive commands (in the form handler, page or article) // 3) pPage Current page (must be 0 if there is a form handler) // 4) pFhdl Current form handler (must be 0 if there is a page) // // Returns: E_SYNTAX If there is a syntax error // E_OK If no errors occured
_hzfunc("hdsApp::_readExec") ;
const hdbClass* pClass ; // Class named in command const hdbClass* pEstClass ; // Class established in the m_ObjKeys map. const hdbClass* pFormClass ; // Class of Commit/Fetch/Select const hdbDatatype* pDT ; // Data type const hdbMember* pMbr ; // Member of Commit/Fetch/Select
hzAttrset ai ; // Attribute iterator hzXmlNode* pN1 ; // Level 1 nodes hzXmlNode* pN2 ; // Level 2 nodes hdsExec* pExec ; // Instruction hzPair pair ; // For use in adduser hzString err ; // Error report from PcEntTest/Scan hzString strA ; // Primary member name hzString strB ; // Secondary member name hzString pcntEnt ; // Percent entity hzString from ; // Email originator hzString addr ; // Recipient address hzString subj ; // Email subject hzString name ; // Email subject hzString input ; // Email subject hzString typeStr ; // Email subject hzString param1 ; // Array of parameters hzString param2 ; // Array of parameters hzString param3 ; // Array of parameters hzString param4 ; // Array of parameters hzString param5 ; // Array of parameters hzString param6 ; // Array of parameters hzString param7 ; // Array of parameters uint32_t cmd ; // Command instruction uint32_t bErr = 0 ; // Error condition uint32_t nParams = 0 ; // Error condition //int32_t val_Lo ; // First index into ADP m_mapSubs //int32_t val_Hi ; // Last index into ADP m_mapSubs hdbBasetype peType ; // Percent entity type hdbBasetype peType_b ; // Percent entity type (second value) hzEcode rc = E_OK ; // Return code
// Check call validity if (!pN) Fatal("No node supplied\n") ; if (!pN->NameEQ("procdata")) Fatal("Expected <procdata> got <%s>\n", pN->txtName()) ; if (!pFhdl && !pPage) Fatal("No form handler or page supplied\n") ; if (pFhdl && !pFhdl->m_pFormdef) Fatal("No form supplied\n") ;
pFormClass = pFhdl ? pFhdl->m_pFormdef->m_pClass : 0 ;
// If the form to which this is the formhandler is the 'root', clear vars in scope. These will be populated by <setvar> // // All form handlers are associated with a form which in turn is associated with a host page. In the case where the host page is not defined // as a page in it's own right but is instead is a response/error page defined as part of a form handler for another form, then the page's // m_pParentForm member will point to this other form. This function returns true in this instance. False otherwise.
// Get instructions in the order they are to be executed for (pN1 = pN->GetFirstChild() ; rc == E_OK && pN1 ; pN1 = pN1->Sibling()) { bErr = nParams = 0 ;
m_pLog->Log("File %s line %d: doing %s (form hdl %p)\n", pN->Fname(), pN1->Line(), pN1->txtName(), pFhdl) ;
if (pN1->NameEQ("sendemail")) { if (!pFhdl) { rc = E_SYNTAX ; m_pLog->Log("File %s line %d: <sendemail> can only appear in a form handler\n", pN->Fname(), pN1->Line()) ; break ; }
pExec = new hdsExec(this, EXEC_SENDEMAIL) ; nParams = 4 ;
for (ai = pN1 ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("from")) param1 = ai.Value() ; else if (ai.NameEQ("to")) param2 = ai.Value() ; else if (ai.NameEQ("subject")) param3 = ai.Value() ; else { m_pLog->Log("File %s line %d: <sendemail> has attr of %s=%s. Only <from|to|subject> allowed\n", pN->Fname(), pN1->Line(), ai.Name(), ai.Value()) ; rc = E_SYNTAX ; } }
param4 = pN1->m_fixContent ;
if (!param1) { bErr = 1 ; m_pLog->Log("File %s line %d: <sendemail> No sender specified\n", pN->Fname(), pN1->Line()) ; } if (!param2) { bErr = 1 ; m_pLog->Log("File %s line %d: <sendemail> No recipient specified\n", pN->Fname(), pN1->Line()) ; } if (!param3) { bErr = 1 ; m_pLog->Log("File %s line %d: <sendemail> No subject specified\n", pN->Fname(), pN1->Line()) ; } if (!param4) { bErr = 1 ; m_pLog->Log("File %s line %d: <sendemail> No message specified\n", pN->Fname(), pN1->Line()) ; }
// Email FROM address if (param1) { if (IsPcEnt(pcntEnt, param1)) { peType = PcEntTest(err, pFhdl->m_pFormdef, 0, param1) ; if (peType == BASETYPE_UNDEF) { bErr = 1 ; m_pLog->Log("File %s line %d: <sendemail> Sender %s %s\n", pN->Fname(), pN1->Line(), *param1, *err) ; }
if (peType != BASETYPE_EMADDR) { m_pLog->Log("File %s line %d: <sendemail> Sender %s is type %s instead of TYPE_EMAIL\n", pN->Fname(), pN1->Line(), *param1, Basetype2Txt(peType)) ; bErr = 1 ; } } else { if (!IsEmaddr(param1)) { bErr = 1 ; m_pLog->Log("File %s line %d: <sendemail> Sender %s invalid email address\n", pN->Fname(), pN1->Line(), *param1) ; } } }
// Email TO address if (param2) { if (IsPcEnt(pcntEnt, param2)) { peType = PcEntTest(err, pFhdl->m_pFormdef, 0, param2) ; if (peType == BASETYPE_UNDEF) { bErr = 1 ; m_pLog->Log("File %s line %d: <sendemail> Recipient %s %s\n", pN->Fname(), pN1->Line(), *param2, *err) ; }
if (peType != BASETYPE_EMADDR) { m_pLog->Log("File %s line %d: <sendemail> Recipient %s is type %s instead of TYPE_EMAIL\n", pN->Fname(), pN1->Line(), *param2, Basetype2Txt(peType)) ; bErr = 1 ; } } else { if (!IsEmaddr(param2)) { bErr = 1 ; m_pLog->Log("File %s line %d: <sendemail> Recipient %s invalid email address\n", pN->Fname(), pN1->Line(), *param2) ; } } }
if (param3) { rc = PcEntScanStr(err, pFhdl->m_pFormdef, 0, param3) ; if (rc != E_OK) { bErr = 1 ; m_pLog->Log("File %s line %d: <sendemail> Subject: %s\n", pN->Fname(), pN1->Line(), *err) ; } }
if (param4) { rc = PcEntScanStr(err, pFhdl->m_pFormdef, 0, param4) ; if (rc != E_OK) { bErr = 1 ; m_pLog->Log("File %s line %d: <sendemail> Content: %s\n", pN->Fname(), pN1->Line(), *err) ; } }
pN2 = pN1->GetFirstChild() ; if (pN2) { // Only allowed child is 'error' to specify error response if (!pN2->NameEQ("error")) { m_pLog->Log("File %s Line %d: <sendemail> Only allowed subtag is <error>, tag of <%s> unexpected\n", pN->Fname(), pN1->Line(), pN2->txtName()) ; rc = E_SYNTAX ; }
m_pLog->Log("File %s Line %d: CALL _readResponse case 1\n", pN->Fname(), pN1->Line()) ; rc = _readResponse(pN2, pFhdl, pExec->m_FailGoto, &pExec->m_pFailResponse) ; } }
else if (pN1->NameEQ("setvar")) { pExec = new hdsExec(this, EXEC_SETVAR) ; nParams = 3 ;
for (ai = pN1 ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("name")) param1 = ai.Value() ; else if (ai.NameEQ("value")) param2 = ai.Value() ; else if (ai.NameEQ("type")) param3 = ai.Value() ; else { bErr = 1 ; m_pLog->Log("File %s Line %d: <setvar> Illegal attr %s=%s. Only <name|type|value> allowed\n", pN->Fname(), pN1->Line(), ai.Name(), ai.Value()) ; } }
if (!param1) { bErr = 1 ; m_pLog->Log("File %s Line %d: <setvar> No var name supplied\n", pN->Fname(), pN1->Line()) ; } if (!param2) { bErr = 1 ; m_pLog->Log("File %s Line %d: <setvar> No value supplied\n", pN->Fname(), pN1->Line()) ; } if (!param3) { bErr = 1 ; m_pLog->Log("File %s Line %d: <setvar> No var type supplied\n", pN->Fname(), pN1->Line()) ; }
if (bErr) rc = E_SYNTAX ; else { pDT = m_ADP.GetDatatype(typeStr) ; if (pDT) pExec->m_type = pDT->Basetype() ; else { pExec->m_type = Str2Basetype(param3) ; if (!pExec->m_type) { bErr = 1 ; m_pLog->Log("File %s Line %d: <setvar> Unknown var type %s\n", pN->Fname(), pN1->Line(), *param3) ; } }
m_tmpVarsSess.Insert(param1, pExec->m_type) ; }
if (!bErr) { if (IsPcEnt(pcntEnt, param2)) { peType = PcEntTest(err, pFhdl->m_pFormdef, pFhdl->m_pFormdef->m_pClass, param2) ; if (peType == BASETYPE_UNDEF) { bErr = 1 ; m_pLog->Log("File %s line %d: <setvar> Value (%s) error %s\n", pN->Fname(), pN1->Line(), *param2, *err) ; }
if (peType != pExec->m_type) { m_pLog->Log("File %s line %d: <setvar> Value %s is type %s instead of %s\n", pN->Fname(), pN1->Line(), *param2, Basetype2Txt(peType), Basetype2Txt(pExec->m_type)) ; bErr = 1 ; } } } }
else if (pN1->NameEQ("addSubscriber")) { // This instructs the system to add a new user. The <addSubscriber> tag has attribute of 'class' to name the user-class and thus the user class repository (if the user // class has its own members). There will be a set of subtags to assign values to the members of the user-class if these exist.
pExec = new hdsExec(this, EXEC_ADDUSER) ; nParams = 4 ;
for (ai = pN1 ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("class")) param1 = ai.Value() ; else if (ai.NameEQ("username")) param2 = ai.Value() ; else if (ai.NameEQ("userpass")) param3 = ai.Value() ; else if (ai.NameEQ("email")) param4 = ai.Value() ; else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: <addSubscriber> Illegal attr %s=%s\n", pN->Fname(), pN1->Line(), ai.Name(), ai.Value()) ; } }
if (!param1) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: <setusr> No user class named\n", pN->Fname(), pN1->Line()) ; } if (!param2) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: <setusr> No user name source\n", pN->Fname(), pN1->Line()) ; } if (!param3) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: <setusr> No password source\n", pN->Fname(), pN1->Line()) ; } if (!param4) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: <setusr> No email source\n", pN->Fname(), pN1->Line()) ; }
if (rc != E_OK) break ;
// Check user-class exists pClass = m_ADP.GetPureClass(param1) ; if (!pClass) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: <addSubscriber class=\"%s\"> Invalid class\n", pN->Fname(), pN1->Line(), *param1) ; break ; }
if (bErr) rc = E_SYNTAX ; else { pFhdl->m_Exec.Add(pExec) ; m_ExecParams.Add(param1) ; m_ExecParams.Add(param2) ; m_ExecParams.Add(param3) ; }
// Obtain the user-class member assignments for (pN2 = pN1->GetFirstChild() ; rc == E_OK && pN2 ; pN2 = pN2->Sibling()) { // Tag 'error' to specify error response if (pN2->NameEQ("error")) { m_pLog->Log("File %s Line %d: CALL _readResponse case 2\n", pN->Fname(), pN2->Line()) ; rc = _readResponse(pN2, pFhdl, pExec->m_FailGoto, &pExec->m_pFailResponse) ; continue ; }
if (!pN2->NameEQ("seteq")) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: Expected seteq instruction. Got <%s>\n", pN->Fname(), pN2->Line(), pN2->txtName()) ; break ; }
pMbr = 0 ; for (ai = pN2 ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("member")) pair.name = ai.Value() ; else if (ai.NameEQ("input")) pair.value = ai.Value() ; else { m_pLog->Log("File %s Line %d: <seteq> has attr of %s=%s. Only <member|input> allowed\n", pN->Fname(), pN2->Line(), ai.Name(), ai.Value()) ; rc = E_SYNTAX ; } }
if (!pair.name) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: <seteq> No var name supplied\n", pN->Fname(), pN2->Line()) ; break ; }
// Check member exists pMbr = pClass->GetMember(pair.name) ; if (!pMbr) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: <seteq> No class member identified\n", pN->Fname(), pN2->Line()) ; break ; }
if (pMbr && pMbr->Multiple() && cmd == COMMIT_SETEQ) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: <seteq> is illegal for array member %s\n", pN->Fname(), pN2->Line(), *pair.name) ; break ; }
if (!pair.value) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: <seteq> No input supplied\n", pN->Fname(), pN2->Line()) ; break ; }
if (pair.value[0] == CHAR_PERCENT) { peType = PcEntTest(err, pFhdl->m_pFormdef, pClass, pair.value) ; if (peType == BASETYPE_UNDEF) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: <seteq> %s=%s: %s\n", pN->Fname(), pN2->Line(), *pair.name, *pair.value, *err) ; }
if (peType != pMbr->Basetype()) { m_pLog->Log("File %s Line %d: <seteq> %s is of type %s (member requires %s) case 1\n", pN->Fname(), pN2->Line(), *pair.value, Basetype2Txt(peType), Basetype2Txt(pMbr->Basetype())) ; rc = E_TYPE ; } } } }
else if (pN1->NameEQ("logon")) { pExec = new hdsExec(this, EXEC_LOGON) ; nParams = 1 ;
for (ai = pN1 ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("user")) param1 = ai.Value() ; else if (ai.NameEQ("pass")) param2 = ai.Value() ; else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: <logon> Illegal attr of %s=%s\n", pN->Fname(), pN1->Line(), ai.Name(), ai.Value()) ; } }
if (!param1) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: <logon> No username source\n", pN->Fname(), pN1->Line()) ; } if (!param2) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: <logon> No userpass source\n", pN->Fname(), pN1->Line()) ; }
if (bErr) rc = E_SYNTAX ; else { pFhdl->m_Exec.Add(pExec) ; m_ExecParams.Add(param1) ; m_ExecParams.Add(param2) ; } }
else if (pN1->NameEQ("testeq")) { pExec = new hdsExec(this, EXEC_TEST) ; nParams = 2 ;
for (ai = pN1 ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("param1")) param1 = ai.Value() ; else if (ai.NameEQ("param2")) param2 = ai.Value() ; else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: <testeq> Illegal attr of %s=%s. Only param1/param2 allowed\n", pN->Fname(), pN1->Line(), ai.Name(), ai.Value()) ; } }
if (!param1 || !param2) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: <testeq> must have both param1 and param2 set\n", pN->Fname(), pN->Line()) ; }
peType = PcEntTest(err, pFhdl->m_pFormdef, pFormClass, param1) ; if (peType == BASETYPE_UNDEF) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: <testeq> param1 %s: %s (rc=%s)\n", pN->Fname(), pN1->Line(), *name, *err, Err2Txt(rc)) ; }
peType_b = PcEntTest(err, pFhdl->m_pFormdef, pFormClass, param2) ; if (peType_b == BASETYPE_UNDEF) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: <testeq> param2 %s: %s (rc=%s)\n", pN->Fname(), pN1->Line(), *name, *err, Err2Txt(rc)) ; }
if (peType != peType_b) { m_pLog->Log("File %s Line %d: <testeq> param 1 is %s and param 2 is %s\n", pN->Fname(), pN1->Line(), Basetype2Txt(peType), Basetype2Txt(peType_b)) ; rc = E_SYNTAX ; }
pN2 = pN1->GetFirstChild() ; if (pN2) { // Only allowed child is 'error' to specify error response if (!pN2->NameEQ("error")) { m_pLog->Log("File %s Line %d: <testeq> Only allowed subtag is <error>, tag of <%s> unexpected\n", pN->Fname(), pN1->Line(), pN2->txtName()) ; rc = E_SYNTAX ; }
m_pLog->Log("File %s Line %d: CALL _readResponse case 3\n", pN->Fname(), pN2->Line()) ; rc = _readResponse(pN2, pFhdl, pExec->m_FailGoto, &pExec->m_pFailResponse) ; }
if (rc == E_OK) { pFhdl->m_Exec.Add(pExec) ; m_ExecParams.Add(param1) ; m_ExecParams.Add(param2) ; } }
else if (pN1->NameEQ("extract")) { // Extract text from a src and place in a tgt
pExec = new hdsExec(this, EXEC_EXTRACT) ; nParams = 2 ;
for (ai = pN1 ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("src")) param1 = ai.Value() ; else if (ai.NameEQ("tgt")) param2 = ai.Value() ; else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: <extract> Invalid parameter %s=%s\n", pN->Fname(), pN1->Line(), ai.Name(), ai.Value()) ; } }
if (!param1) { bErr = 1 ; m_pLog->Log("File %s Line %d: <extract> No source input specified\n", pN->Fname(), pN1->Line()) ; } if (!param2) { bErr = 1 ; m_pLog->Log("File %s Line %d: <extract> No target specified\n", pN->Fname(), pN1->Line()) ; } }
else if (pN1->NameEQ("xobjTemp")) { pExec = new hdsExec(this, EXEC_OBJ_TEMP) ; nParams = 3 ;
for (ai = pN1 ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("objkey")) param1 = ai.Value() ; else if (ai.NameEQ("class")) param2 = ai.Value() ; else if (ai.NameEQ("repos")) param3 = ai.Value() ; else { bErr = 1 ; m_pLog->Log("File %s Line %d: <xobjTemp> Invalid parameter %s=%s\n", pN->Fname(), pN1->Line(), ai.Name(), ai.Value()) ; } }
if (!param1) { bErr = 1 ; m_pLog->Log("File %s Line %d: <xobjTemp> No identifier specified\n", pN->Fname(), pN1->Line()) ; } else { if (m_SObj2Class.Exists(param1)) { bErr = 1 ; m_pLog->Log("File %s Line %d: <xobjTemp> Illegal reuse of object key %s\n", pN->Fname(), pN1->Line(), *param1) ; break ; } }
if (!param2) pClass = pFormClass ; else { pClass = m_ADP.GetPureClass(param2) ; if (!pClass) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: <xobjTemp> class %s not found\n", pN->Fname(), pN1->Line(), *param2) ; break ; } }
pExec->m_ClassId = pClass->ClassId() ;
// Place the refname in the project's map of object specifiers m_SObj2Class.Insert(param1, param2) ; }
else if (pN1->NameEQ("xobjStart")) { pExec = new hdsExec(this, EXEC_OBJ_START) ; nParams = 3 ;
for (ai = pN1 ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("objkey")) param1 = ai.Value() ; else if (ai.NameEQ("class")) param2 = ai.Value() ; else if (ai.NameEQ("repos")) param3 = ai.Value() ; else { bErr = 1 ; m_pLog->Log("File %s Line %d: <xobjStart> Invalid parameter %s=%s\n", pN->Fname(), pN1->Line(), ai.Name(), ai.Value()) ; } }
if (!param1) { bErr = 1 ; m_pLog->Log("File %s Line %d: <xobjStart> No identifier specified\n", pN->Fname(), pN1->Line()) ; } else { if (m_SObj2Class.Exists(param1)) { bErr = 1 ; m_pLog->Log("File %s Line %d: <xobjStart> Illegal reuse of object key %s\n", pN->Fname(), pN1->Line(), *param1) ; break ; } }
if (!param2) { if (pFhdl) pClass = pFormClass ; else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: <xobjStart> No form and no class\n", pN->Fname(), pN1->Line()) ; break ; } } else { pClass = m_ADP.GetPureClass(param2) ; if (!pClass) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: <xobjTemp> class %s not found\n", pN->Fname(), pN1->Line(), *param2) ; break ; } }
pExec->m_ClassId = pClass->ClassId() ;
// Place the refname in the project's map of object specifiers m_SObj2Class.Insert(param1, param2) ; }
else if (pN1->NameEQ("xobjImport")) { // An import is specifically where the source is a file and not a repository. The file must be named and will commonly use a percent entity pExec = new hdsExec(this, EXEC_OBJ_IMPORT) ; nParams = 2 ;
for (ai = pN1 ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("objkey")) param1 = ai.Value() ; else if (ai.NameEQ("source")) param2 = ai.Value() ; else { bErr = 1 ; m_pLog->Log("File %s Line %d: <xobjImport> Invalid parameter %s=%s\n", pN->Fname(), pN1->Line(), ai.Name(), ai.Value()) ; } }
if (!param1) { bErr = 1 ; m_pLog->Log("File %s Line %d: <xobjImport> No object name specified\n", pN->Fname(), pN1->Line()) ; } if (!param2) { bErr = 1 ; m_pLog->Log("File %s Line %d: <xobjImport> No repository specified\n", pN->Fname(), pN1->Line()) ; }
if (!m_SObj2Class.Exists(param1)) m_pLog->Log("File %s Line %d: <xobjImport> No such object key as %s\n", pN->Fname(), pN1->Line(), *param1) ; }
else if (pN1->NameEQ("xobjExport")) { // An import is specifically where the source is a file and not a repository. The file must be named and will commonly use a percent entity pExec = new hdsExec(this, EXEC_OBJ_EXPORT) ; nParams = 2 ;
for (ai = pN1 ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("objkey")) param1 = ai.Value() ; else if (ai.NameEQ("source")) param2 = ai.Value() ; else { bErr = 1 ; m_pLog->Log("File %s Line %d: <xobjExport> Invalid parameter %s=%s\n", pN->Fname(), pN1->Line(), ai.Name(), ai.Value()) ; } }
if (!param1) { bErr = 1 ; m_pLog->Log("File %s Line %d: <xobjExport> No object name specified\n", pN->Fname(), pN1->Line()) ; } if (!param2) { bErr = 1 ; m_pLog->Log("File %s Line %d: <xobjExport> No repository specified\n", pN->Fname(), pN1->Line()) ; }
if (!m_SObj2Class.Exists(param1)) m_pLog->Log("File %s Line %d: <xobjExport> No such object key as %s\n", pN->Fname(), pN1->Line(), *param1) ; }
else if (pN1->NameEQ("xobjSetMbr")) { // For the object named in param 1, set the member named in param 3 to the value of or from the source specified in param 4. The applicable data class will be the form // native unless otherwise specified in param 2. When setting a member of a sub-class instance // // The current object (hdsObect) is a one to many map of hzDelta instances to values. hzDelta identifies an object, either of the hdbObject's host // class or a sub-class), by naming the class and stating the object id. hzDelta also states the applicable class member. When writing form handlers // the class and member can be known but the object id cannot be known as this will depend on the object being viewed. // // Here then we only specify class and member and the variable that the object member is to be set to - so 3 parameters. The class and member must // exist. The class name can be blank if the class is the current object host class. The variable must necessarily be a percent entity.
pExec = new hdsExec(this, EXEC_OBJ_SETMBR) ; nParams = 4 ;
for (ai = pN1 ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("objkey")) param1 = ai.Value() ; else if (ai.NameEQ("class")) param2 = ai.Value() ; else if (ai.NameEQ("member")) param3 = ai.Value() ; else if (ai.NameEQ("input")) param4 = ai.Value() ; else { bErr = 1 ; m_pLog->Log("File %s Line %d: <xobjSetMbr> Invalid parameter %s=%s\n", pN->Fname(), pN1->Line(), ai.Name(), ai.Value()) ; } }
if (!param1) { bErr = 1 ; m_pLog->Log("File %s Line %d: <xobjSetMbr> No object key specified\n", pN->Fname(), pN1->Line()) ; } if (!param3) { bErr = 1 ; m_pLog->Log("File %s Line %d: <xobjSetMbr> No member name specified\n", pN->Fname(), pN1->Line()) ; } if (!param4) { bErr = 1 ; m_pLog->Log("File %s Line %d: <xobjSetMbr> No input specified\n", pN->Fname(), pN1->Line()) ; }
if (!m_SObj2Class.Exists(param1)) //{ bErr = 1 ; m_pLog->Log("File %s Line %d: <xobjSetMbr> No such object key as %s\n", pN->Fname(), pN1->Line(), *param1) ; } m_pLog->Log("File %s Line %d: <xobjSetMbr> No such object key as %s\n", pN->Fname(), pN1->Line(), *param1) ;
// Get class if (!param2) pClass = pFormClass ; else { pClass = m_ADP.GetPureClass(param2) ; if (!pClass) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: <xobjSetMbr> class %s not found\n", pN->Fname(), pN1->Line(), *param2) ; break ; } }
if (param2 != m_SObj2Class[param1]) { // Class only matches if it is the same as the established object class or a sub-class of it. pEstClass = m_ADP.GetPureClass(m_SObj2Class[param1]) ;
pClass = 0 ;
/* * FIX * val_Lo = m_ADP.m_mapSubs.First(pEstClass->strType()) ; if (val_Lo >= 0) { val_Hi = m_ADP.m_mapSubs.Last(pEstClass->strType()) ;
for (; val_Lo <= val_Hi ; val_Lo++) { pClass = m_ADP.m_mapSubs.GetObj(val_Lo) ; if (pClass->strType() == param2) break ; pClass = 0 ; } } */
if (pClass) pClass = pEstClass ; else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: <xobjSetMbr> wrong class %s\n", pN->Fname(), pN1->Line(), *param2) ; break ; } }
if (!param4) { bErr = 1 ; m_pLog->Log("File %s Line %d: <xobjSetMbr> No input specified\n", pN->Fname(), pN1->Line()) ; }
// Now we have the object specifier name we can get the repos and class from the
// Obtain the member assignments if (param3.Contains("->")) { strA = strB = param3 ; strA.TruncateUpto("->") ; strB.TruncateBeyond("->") ;
pMbr = pClass->GetMember(strA) ; if (!pMbr) { m_pLog->Log("File %s Line %d: <%s> %s not a member of class %s\n", pN->Fname(), pN1->Line(), pN1->txtName(), *strA, pClass->txtType()) ; rc = E_NOTFOUND ; } else { if (pMbr->IsClass()) { m_pLog->Log("File %s Line %d: <%s> Composite %s is not a class\n", pN->Fname(), pN1->Line(), pN1->txtName(), *strA) ; rc = E_NOTFOUND ; } else { pMbr = pClass->GetMember(strB) ; if (!pMbr) { m_pLog->Log("File %s Line %d: <%s> Member %s does not exists in class %s\n", pN->Fname(), pN1->Line(), pN1->txtName(), *strB, pClass->txtType()) ; rc = E_NOTFOUND ; } } } } else { pMbr = pClass->GetMember(param3) ; if (!pMbr) { m_pLog->Log("File %s Line %d: <%s> Member %s does not exists in class %s\n", pN->Fname(), pN1->Line(), pN1->txtName(), ai.Value(), pClass->txtType()) ; rc = E_NOTFOUND ; } name = ai.Value() ; }
if (pMbr && pMbr->Multiple() && cmd == COMMIT_SETEQ) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: <%s> is illegal for list member %s\n", pN->Fname(), pN1->Line(), pN1->txtName(), *param3) ; break ; }
if (input[0] == CHAR_PERCENT) { peType = PcEntTest(err, pFhdl->m_pFormdef, pClass, input) ; if (peType == BASETYPE_UNDEF) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: <%s> %s: %s\n", pN->Fname(), pN1->Line(), pN1->txtName(), *param3, *err) ; }
if (peType != pMbr->Basetype()) { m_pLog->Log("File %s Line %d: <%s> [%s] is of type %x->%s (member requires %x->%s) case 2\n", pN->Fname(), pN1->Line(), pN1->txtName(), *input, peType, Basetype2Txt(peType), pMbr->Basetype(), Basetype2Txt(pMbr->Basetype())) ; rc = E_TYPE ; } } }
else if (pN1->NameEQ("xobjCommit")) { // This commits the named object to its repository.
pExec = new hdsExec(this, EXEC_OBJ_COMMIT) ; nParams = 1 ;
for (ai = pN1 ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("objkey")) param1 = ai.Value() ; else { bErr = 1 ; m_pLog->Log("File %s Line %d: <xobjCommit> Invalid parameter %s=%s\n", pN->Fname(), pN1->Line(), ai.Name(), ai.Value()) ; } }
if (!m_SObj2Class.Exists(param1)) m_pLog->Log("File %s Line %d: <xobjCommit> No such object key as %s\n", pN->Fname(), pN1->Line(), *param1) ; }
else if (pN1->NameEQ("xobjClose")) { // This commits the named object to its repository.
pExec = new hdsExec(this, EXEC_OBJ_CLOSE) ; nParams = 1 ;
for (ai = pN1 ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("objkey")) param1 = ai.Value() ; else { bErr = 1 ; m_pLog->Log("File %s Line %d: <xobjClose> Invalid parameter %s=%s\n", pN->Fname(), pN1->Line(), ai.Name(), ai.Value()) ; } }
if (!m_SObj2Class.Exists(param1)) m_pLog->Log("File %s Line %d: <xobjClose> No such object key as %s\n", pN->Fname(), pN1->Line(), *param1) ; }
else if (pN1->NameEQ("xtreeDcl")) { pExec = new hdsExec(this, EXEC_TREE_DCL) ; nParams = 2 ;
for (ai = pN1 ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("treeid")) param1 = ai.Value() ; else if (ai.NameEQ("copy")) param2 = ai.Value() ; else { bErr = 1 ; m_pLog->Log("File %s Line %d: <treeDcl> Illegal param (%s=%s)\n", pN->Fname(), pN1->Line(), ai.Name(), ai.Value()) ; } }
if (!param1) { bErr = 1 ; m_pLog->Log("File %s Line %d: <treeDcl> No tree id supplied\n", pN->Fname(), pN1->Line()) ; } m_ArticleGroups.Insert(param1, (hdsNavtree*) 0) ; } else if (pN1->NameEQ("xtreeHead")) { // Adds a tree header (no active link) pExec = new hdsExec(this, EXEC_TREE_HEAD) ; nParams = 4 ;
for (ai = pN1 ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("treeid")) param1 = ai.Value() ; else if (ai.NameEQ("parent")) param2 = ai.Value() ; else if (ai.NameEQ("refname")) param3 = ai.Value() ; else if (ai.NameEQ("title")) param4 = ai.Value() ; else { bErr = 1 ; m_pLog->Log("File %s Line %d: <treeHdr> Illegal param (%s=%s)\n", pN->Fname(), pN1->Line(), ai.Name(), ai.Value()) ; } }
if (!param1) { bErr = 1 ; m_pLog->Log("File %s Line %d: <treeHdr> No tree id supplied\n", pN->Fname(), pN1->Line()) ; } if (!param3) { bErr = 1 ; m_pLog->Log("File %s Line %d: <treeHdr> No refname supplied\n", pN->Fname(), pN1->Line()) ; } if (!param4) { bErr = 1 ; m_pLog->Log("File %s Line %d: <treeHdr> No title supplied\n", pN->Fname(), pN1->Line()) ; } } else if (pN1->NameEQ("xtreeItem")) { // Adds a tree article (refname acts as URL) pExec = new hdsExec(this, EXEC_TREE_ITEM) ; nParams = 4 ;
for (ai = pN1 ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("treeid")) param1 = ai.Value() ; else if (ai.NameEQ("parent")) param2 = ai.Value() ; else if (ai.NameEQ("refname")) param3 = ai.Value() ; else if (ai.NameEQ("title")) param4 = ai.Value() ; else { bErr = 1 ; m_pLog->Log("File %s Line %d: <treeAdd> Illegal param (%s=%s)\n", pN->Fname(), pN1->Line(), ai.Name(), ai.Value()) ; } }
if (!param1) { bErr = 1 ; m_pLog->Log("File %s Line %d: <treeAdd> No tree id supplied\n", pN->Fname(), pN1->Line()) ; } if (!param3) { bErr = 1 ; m_pLog->Log("File %s Line %d: <treeAdd> No refname supplied\n", pN->Fname(), pN1->Line()) ; } if (!param4) { bErr = 1 ; m_pLog->Log("File %s Line %d: <treeAdd> No title supplied\n", pN->Fname(), pN1->Line()) ; } } else if (pN1->NameEQ("xtreeForm")) { pExec = new hdsExec(this, EXEC_TREE_FORM) ; nParams = 6 ;
for (ai = pN1 ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("treeid")) param1 = ai.Value() ; else if (ai.NameEQ("parent")) param2 = ai.Value() ; else if (ai.NameEQ("refname")) param3 = ai.Value() ; else if (ai.NameEQ("title")) param4 = ai.Value() ; else if (ai.NameEQ("form")) param5 = ai.Value() ; else if (ai.NameEQ("class")) param6 = ai.Value() ; else { bErr = 1 ; m_pLog->Log("File %s Line %d: <treeAdd> Illegal param (%s=%s)\n", pN->Fname(), pN1->Line(), ai.Name(), ai.Value()) ; } }
if (!param1) { bErr = 1 ; m_pLog->Log("File %s Line %d: <treeAdd> No tree id supplied\n", pN->Fname(), pN1->Line()) ; } if (!param3) { bErr = 1 ; m_pLog->Log("File %s Line %d: <treeAdd> No refname supplied\n", pN->Fname(), pN1->Line()) ; } if (!param4) { bErr = 1 ; m_pLog->Log("File %s Line %d: <treeAdd> No title supplied\n", pN->Fname(), pN1->Line()) ; } if (!param5) { bErr = 1 ; m_pLog->Log("File %s Line %d: <treeAdd> No form supplied\n", pN->Fname(), pN1->Line()) ; } if (!param6) { bErr = 1 ; m_pLog->Log("File %s Line %d: <treeAdd> No class supplied\n", pN->Fname(), pN1->Line()) ; }
// Need to check form exists - and that to stated form class is compatible } else if (pN1->NameEQ("xtreeSync")) { pExec = new hdsExec(this, EXEC_TREE_SYNC) ; nParams = 2 ;
for (ai = pN1 ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("treeid")) param1 = ai.Value() ; else if (ai.NameEQ("objkey")) param2 = ai.Value() ; else { bErr = 1 ; m_pLog->Log("File %s Line %d: <treeAdd> Illegal param (%s=%s)\n", pN->Fname(), pN1->Line(), ai.Name(), ai.Value()) ; } }
if (!param1) { bErr = 1 ; m_pLog->Log("File %s Line %d: <treeAdd> No tree id supplied\n", pN->Fname(), pN1->Line()) ; } if (!param2) { bErr = 1 ; m_pLog->Log("File %s Line %d: <treeAdd> No object key supplied\n", pN->Fname(), pN1->Line()) ; } } else if (pN1->NameEQ("xtreeDel")) { pExec = new hdsExec(this, EXEC_TREE_DEL) ; nParams = 2 ;
for (ai = pN1 ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("treeid")) param1 = ai.Value() ; else if (ai.NameEQ("nodeid")) param2 = ai.Value() ; else { bErr = 1 ; m_pLog->Log("File %s Line %d: <treeDel> Illegal param (%s=%s)\n", pN->Fname(), pN1->Line(), ai.Name(), ai.Value()) ; } }
if (!param1) { bErr = 1 ; m_pLog->Log("File %s Line %d: <treeDel> No tree id supplied\n", pN->Fname(), pN1->Line()) ; } if (!param2) { bErr = 1 ; m_pLog->Log("File %s Line %d: <treeDel> No node id supplied\n", pN->Fname(), pN1->Line()) ; } } else if (pN1->NameEQ("xtreeExp")) { pExec = new hdsExec(this, EXEC_TREE_EXP) ; nParams = 2 ;
for (ai = pN1 ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("treeid")) param1 = ai.Value() ; else if (ai.NameEQ("nodeid")) param2 = ai.Value() ; else { bErr = 1 ; m_pLog->Log("File %s Line %d: <treeExp> Illegal param (%s=%s)\n", pN->Fname(), pN1->Line(), ai.Name(), ai.Value()) ; } }
if (!param1) { bErr = 1 ; m_pLog->Log("File %s Line %d: <treeExp> No tree id supplied\n", pN->Fname(), pN1->Line()) ; } if (!param2) { bErr = 1 ; m_pLog->Log("File %s Line %d: <treeExp> No node id supplied\n", pN->Fname(), pN1->Line()) ; } } else if (pN1->NameEQ("xtreeClr")) { pExec = new hdsExec(this, EXEC_TREE_CLR) ; nParams = 2 ;
for (ai = pN1 ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("treeid")) param1 = ai.Value() ; else if (ai.NameEQ("nodeid")) param2 = ai.Value() ; else { bErr = 1 ; m_pLog->Log("File %s Line %d: <treeClr> Illegal param (%s=%s)\n", pN->Fname(), pN1->Line(), ai.Name(), ai.Value()) ; } }
if (!param1) { bErr = 1 ; m_pLog->Log("File %s Line %d: <treeClr> No tree id supplied\n", pN->Fname(), pN1->Line()) ; } if (!param2) { bErr = 1 ; m_pLog->Log("File %s Line %d: <treeClr> No node id supplied\n", pN->Fname(), pN1->Line()) ; } }
else if (pN1->NameEQ("filesys")) { // A file operation allows one to create and delete files and directories, list directories and load files
pExec = new hdsExec(this, EXEC_FILESYS) ;
for (ai = pN1 ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("action")) { if (ai.ValEQ("mkdir") || ai.ValEQ("rmdir") || ai.ValEQ("save") || ai.ValEQ("delete")) param1 = ai.Value() ; else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: <fileop> Illegal operation (%s=%s)\n", pN->Fname(), pN1->Line(), ai.Name(), ai.Value()) ; } } else if (ai.NameEQ("resource")) param2 = ai.Value() ; else if (ai.NameEQ("content")) param3 = ai.Value() ; else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: <fileop> Illegal param (%s=%s)\n", pN->Fname(), pN1->Line(), ai.Name(), ai.Value()) ; } }
if (!param1) { bErr = 1 ; m_pLog->Log("File %s line %d: <filesys> No action specified\n", pN->Fname(), pN1->Line()) ; } if (!param2) { bErr = 1 ; m_pLog->Log("File %s line %d: <filesys> No resource specified\n", pN->Fname(), pN1->Line()) ; }
if (!param3 && (param1 == "save" || param1 == "delete")) { bErr = 1 ; m_pLog->Log("File %s line %d: <filesys> No content specified\n", pN->Fname(), pN1->Line()) ; } } else if (pN1->NameEQ("srchPages")) { pExec = new hdsExec(this, EXEC_SRCH_PAGES) ;
for (ai = pN1 ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("limit")) param1 = ai.Value() ; else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: <srchPages> Illegal attr (%s=%s)\n", pN->Fname(), pN1->Line(), ai.Name(), ai.Value()) ; } }
if (!param1) param1 = "0" ; } else if (pN1->NameEQ("srchRepos")) { pExec = new hdsExec(this, EXEC_SRCH_REPOS) ;
for (ai = pN1 ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("items")) param1 = ai.Value() ; else if (ai.NameEQ("action")) param2 = ai.Value() ; else if (ai.NameEQ("criteria")) param3 = ai.Value() ; else if (ai.NameEQ("count")) param4 = ai.Value() ; else if (ai.NameEQ("found")) param5 = ai.Value() ; else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: <search> Illegal attr (%s=%s)\n", pN->Fname(), pN1->Line(), ai.Name(), ai.Value()) ; } }
if (!param1) { bErr = 1 ; m_pLog->Log("File %s line %d: <search> No source specified\n", pN->Fname(), pN1->Line()) ; } if (!param2) { bErr = 1 ; m_pLog->Log("File %s line %d: <search> No action specified\n", pN->Fname(), pN1->Line()) ; } if (!param3) { bErr = 1 ; m_pLog->Log("File %s line %d: <search> No criteria specified\n", pN->Fname(), pN1->Line()) ; } } else { m_pLog->Log("File %s Line %d: Unrecognized command <%s>\n", pN->Fname(), pN1->Line(), pN1->txtName()) ; rc = E_SYNTAX ; }
// If all OK, add the exec command to the form handler if (rc != E_OK || bErr) rc = E_SYNTAX ; else { execList.Add(pExec) ; pExec->m_FstParam = m_ExecParams.Count() ;
if (nParams > 0) { m_pLog->Log("ExecParam %d %s\n", m_ExecParams.Count(), *param1) ; m_ExecParams.Add(param1) ; param1.Clear() ; } if (nParams > 1) { m_pLog->Log("ExecParam %d %s\n", m_ExecParams.Count(), *param2) ; m_ExecParams.Add(param2) ; param2.Clear() ; } if (nParams > 2) { m_pLog->Log("ExecParam %d %s\n", m_ExecParams.Count(), *param3) ; m_ExecParams.Add(param3) ; param3.Clear() ; } if (nParams > 3) { m_pLog->Log("ExecParam %d %s\n", m_ExecParams.Count(), *param4) ; m_ExecParams.Add(param4) ; param4.Clear() ; } if (nParams > 4) { m_pLog->Log("ExecParam %d %s\n", m_ExecParams.Count(), *param5) ; m_ExecParams.Add(param5) ; param5.Clear() ; } if (nParams > 5) { m_pLog->Log("ExecParam %d %s\n", m_ExecParams.Count(), *param6) ; m_ExecParams.Add(param6) ; param6.Clear() ; } } }
return rc ; }
hzEcode hdsApp::_readFormHdl (hzXmlNode* pN) { // Process a <xformHdl> tag to create a hdsFormhdl (form handler) instance. // // Form handlers are always invoked upon form submissions to process the submitted data and formulate a HTML response. The configs for the form handler set // out a series of processing instructions. Each of these may contain a response directive in the event of failure. There is also a response directive for // failure of the series as a whole and another for success. To see the latter, every instruction in the series must succeed. // // Argument: pN Pointer to XML node <formhdl> // // Returns: E_SYNTAX In the event of incorrect parameters // E_OK If the <formhdl> parameters are valid
_hzfunc("hdsApp::_readFormHdl") ;
hzAttrset ai ; // Attribute iterator hzXmlNode* pN1 ; // Current XML node hdsFormdef* pForm ; // Named form (which must per-exist) hdsFormhdl* pFhdl ; // Form handler hzString hname ; // Name of form handler hzString fname ; // Name of form hzString fops ; // Operational flags uint32_t state = 0 ; // Instruction context hzEcode rc = E_OK ; // Return code
if (!pN) Fatal("No node supplied\n") ;
m_pLog->Log("Node %s line %d\n", pN->txtName(), pN->Line()) ;
// The attr will be the name of the form to which the handler applies for (ai = pN ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("name")) hname = ai.Value() ; else if (ai.NameEQ("form")) fname = ai.Value() ; else if (ai.NameEQ("ops")) fops = ai.Value() ; else { m_pLog->Log("File %s Line %d Reading <formhdl> tag: Bad attribute (%s=%s)\n", pN->Fname(), pN->Line(), ai.Name(), ai.Value()) ; return E_SYNTAX ; } }
if (!hname) { m_pLog->Log("File %s Line %d <formhdl> No form handler name supplied\n", pN->Fname(), pN->Line()) ; return E_SYNTAX ; } if (!fname) { m_pLog->Log("File %s Line %d <formhdl> No form name supplied\n", pN->Fname(), pN->Line()) ; return E_SYNTAX ; }
pForm = m_FormDefs[fname] ; if (!pForm) { m_pLog->Log("File %s Line %d <formhdl> Form %s not found\n", pN->Fname(), pN->Line(), *fname) ; return E_SYNTAX ; }
if (!m_FormHdls.Exists(hname)) { m_pLog->Log("File %s Line %d. No formhandler of %s expected\n", pN->Fname(), pN->Line(), *hname) ; return E_NOTFOUND ; }
pFhdl = m_FormHdls[hname] ; if (pFhdl) { m_pLog->Log("File %s Line %d. Already have a formhandler named %s\n", pN->Fname(), pN->Line(), *hname) ; return E_DUPLICATE ; }
pFhdl = new hdsFormhdl() ; pFhdl->m_Refname = hname ; pFhdl->m_pFormdef = pForm ; m_FormHdls.Insert(hname, pFhdl) ;
if (fops) { if (fops != "cookie") { m_pLog->Log("File %s Line %d. Only allowed value for ops attr is cookie. %s illegal\n", pN->Fname(), pN->Line(), *fops) ; return E_SYNTAX ; }
pFhdl->m_flgFH |= VE_COOKIES ; }
// Get the <procdata> and <response> directives for (pN1 = pN->GetFirstChild() ; rc == E_OK && pN1 ; pN1 = pN1->Sibling()) { if (pN1->NameEQ("procdata")) { if (state & 1) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d Reading <formhdl> tag: Only one <procdata> allowed\n", pN->Fname(), pN1->Line()) ; break ; } state |= 1 ; rc = _readExec(pN1, pFhdl->m_Exec, 0, pFhdl) ; continue ; }
if (pN1->NameEQ("response")) { if (state & 2) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d Reading <formhdl> tag: Only one <response> or <showpage> allowed\n", pN->Fname(), pN1->Line()) ; break ; } state |= 2 ; m_pLog->Log("File %s Line %d: CALL _readResponse case 4\n", pN->Fname(), pN1->Line()) ; rc = _readResponse(pN1, pFhdl, pFhdl->m_CompleteGoto, &pFhdl->m_pCompletePage) ; continue ; }
if (pN1->NameEQ("error")) { if (state & 4) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d Reading <formhdl> tag: Only one <error> allowed\n", pN->Fname(), pN1->Line()) ; break ; } state |= 4 ; m_pLog->Log("File %s Line %d: CALL _readResponse case 5\n", pN->Fname(), pN1->Line()) ; rc = _readResponse(pN1, pFhdl, pFhdl->m_FailDfltGoto, &pFhdl->m_pFailDfltPage) ; continue ; } }
if (rc != E_OK) return rc ;
if (!pFhdl->m_pCompletePage && !pFhdl->m_CompleteGoto) { m_pLog->Log("Form handler for form %s starting line %d has no success state response page or destintion\n", *pFhdl->m_Refname, pN->Line()) ; rc = E_NODATA ; }
if (!pFhdl->m_pFailDfltPage && !pFhdl->m_FailDfltGoto) { m_pLog->Log("Form handler for form %s starting line %d has no failue state error page or destination\n", *pFhdl->m_Refname, pN->Line(), *pFhdl->m_FailDfltGoto) ; rc = E_NODATA ; }
m_pLog->Log("Form handler form %s has success response/destination (%p, %s) and failure response/destination (%p, %s)\n", *pFhdl->m_Refname, pFhdl->m_pCompletePage, *pFhdl->m_CompleteGoto, pFhdl->m_pFailDfltPage, *pFhdl->m_FailDfltGoto) ;
m_pLog->Log("Returning er=%s\n", Err2Txt(rc)) ;
return rc ; }
hdsVE* hdsApp::_readFormBut (hzXmlNode* pN, hdsFormdef* pFormdef, hdsFormref* pFormref) { // Support function to hdsApp::_readFormDef called via hdsApp::_readTag, to add an action to the supplied form definition.
_hzfunc("hdsApp::_readFormBut") ;
hzAttrset ai ; // Attribute iterator hdsVE* thisVE = 0 ; // Visible entity hdsButton* pButt ; // Dissemino form button hzString title ; // Text visible hzString page ; // Expected page (to go to) hzString whom ; // Allowed users hzString css ; // Allowed CSS style hzString hname ; // Form action (handler name) hzString faUrl ; // Form action URL uint32_t bErr = 0 ; // Error condition
//hzXmlNode* pN1 ; // Subtag probe //hdsVE* newVE ; // Subtag visible entity //hdsRecap* pRecap ; // Google recaptcha
if (!pN->NameEQ("xformBut")) Fatal("Wrong call\n") ;
if (!pFormdef) { m_pLog->Log("File %s Line %d <xformBut> No form definition applies\n", pN->Fname(), pN->Line()) ; return 0 ; }
for (ai = pN ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("title")) title = ai.Value() ; else if (ai.NameEQ("handler")) hname = ai.Value() ; else if (ai.NameEQ("url")) faUrl = ai.Value() ; else if (ai.NameEQ("css")) css = ai.Value() ; else { bErr=1 ; m_pLog->Log("File %s Line %d Adding <%s> tag: Bad param (%s=%s)\n", pN->Fname(), pN->Line(), pN->txtName(), ai.Name(), ai.Value()) ; } }
if (!title) { bErr=1 ; m_pLog->Log("File %s Line %d <xformBut> No title supplied\n", pN->Fname(), pN->Line()) ; }
if (hname || faUrl) { // If either action or URL are supplied, both must be if (!hname) { bErr=1 ; m_pLog->Log("File %s Line %d: <xformDef> URL but no action supplied\n", pN->Fname(), pN->Line()) ; } if (!faUrl) { bErr=1 ; m_pLog->Log("File %s Line %d: <xformDef> Action but no URL supplied\n", pN->Fname(), pN->Line()) ; } }
if (hname && faUrl) { if (!m_FormHdls.Exists(hname)) { m_FormHdls.Insert(hname,0) ; pFormdef->m_nActions++ ; } m_FormUrl2Hdl.Insert(faUrl,hname) ; m_FormUrl2Ref.Insert(faUrl, pFormref) ; m_FormRef2Url.Insert(pFormref, faUrl) ; }
if (!hname && !faUrl) { // OK for the button to have no action or submission URL as long as the form definition has these and the form is single action. if (!pFormdef->m_DfltAct) { bErr=1 ; m_pLog->Log("File %s Line %d <xformBut> No action supplied\n", pN->Fname(), pN->Line()) ; } else { hname = pFormdef->m_DfltAct ; faUrl = pFormdef->m_DfltURL ; pFormdef->m_DfltAct.Clear() ; pFormdef->m_DfltURL.Clear() ; } }
if (bErr) return 0 ;
// if (page) // { // Lookup the page and check that it exists and is not the same as the page in which the button appears // if (page != "%x_referer;" && !m_PagesName.Exists(page)) // m_pLog->Log("Warning: File %s Line %d Adding <button> tag: Page %s not found\n", pN->Fname(), pN->Line(), *page) ; // }
thisVE = pButt = new hdsButton(this) ; thisVE->m_strPretext = pN->txtPtxt() ; thisVE->m_Line = pN->Line() ; thisVE->m_Indent = pN->Level() ; thisVE->m_Tag = pN->txtName() ; thisVE->m_Resv = pFormdef->m_nActions ; pButt->m_strContent = title ; pButt->m_CSS = css ; pButt->m_Linkto = hname ; pButt->m_Formname = pFormdef->m_Formname ; m_pLog->Log("Added form button (%s)\n", *pButt->m_strContent) ;
return thisVE ; }
hzEcode hdsApp::_readFormDef (hzXmlNode* pN) { // Process an <xformDef> tag to define a form (create a hdsFormdef instance), in the INDEPENDENT case where the <xformDef> tag lays outside any page or article definition. The // expectation is that the defined form will later be referred to by means of an <xformRef> tag within one or more pages or articles. // // In the independent case <xformDef> has three attributes of 'name' which names the form, 'class' which sets the host data class, and 'action' which names a yet to be defined // form handler. The first two are compulsory but if the action is not set in the <xformDef> tag itself, it must be set for each active button in the form. Both the form name // and form handler name(s) are required to be unique across the entire configs. // // The following occurs within this function: // // 1) A new form definition is created placed in hdsApp::m_FormDefs. This map is purely to ensure forms are given unique names. // // 2) For each form action, a form handler is named and a URL supplied. The form handler name is added to hdsApp::m_FormHdl, ensuring it is unique. No actual form handler // is created however. This must await processing of a later <xformHdl> tag. In the meantime the form handler pointer in the entry in hdsApp::m_FormHdl, is NULL. // // If <xformDef> processes successfully, a form definition is created and entered into the hdsApp map m_FormDefs, thereby facilitation form referencing. // // Argument: pN Current XML node // // Returns: E_SYNTAX If supplied attributes or sub-tags are in error. // E_OK If the <xformDef> tag is processed successfully.
_hzfunc("hdsApp::_readFormDef:1") ;
_tagArg tga ; // Tag argument for _readTag() hzAttrset ai ; // Attribute iterator hzXmlNode* pN1 ; // For processing child nodes hdsVE* pVE ; // Generic visible entity hdsFormdef* pFormdef ; // This form const hdbClass* pClass = 0 ; // Data class refered to in xform declaration hzString fname ; // Name (of this form) hzString cname ; // Class name hzString hname ; // Form handler name hzString faUrl ; // Form action URL specified in <xformBut> sub-tag hzString title ; // Button title hzString page ; // Expected page (to go to) hzString whom ; // Allowed users hzString css ; // Allowed CSS style uint32_t flags ; // For _readTag() call bool bRecap = false ; // Google Recaptcha Indicator hzEcode rc = E_OK ; // Return code
if (!this) Fatal("No instance\n") ; if (!pN) Fatal("No node supplied\n") ;
if (!pN->NameEQ("xformDef")) Fatal("Incorrect node (%s) supplied. Must be <xformDef>\n", pN->txtName()) ;
m_pLog->Log("File %s Line %d: XFORMDEF tag\n", pN->Fname(), pN->Line()) ;
// Form parameters for (ai = pN ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("name")) fname = ai.Value() ; else if (ai.NameEQ("class")) cname = ai.Value() ; else if (ai.NameEQ("handler")) hname = ai.Value() ; else if (ai.NameEQ("recaptcha")) bRecap = ai.ValEQ("true") ; else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: <form> Bad param (%s=%s)\n", pN->Fname(), pN->Line(), ai.Name(), ai.Value()) ; } }
if (!fname) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: <xformDef> No name supplied\n", pN->Fname(), pN->Line()) ; } if (!cname) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: <xformDef> No default class\n", pN->Fname(), pN->Line()) ; } if (!hname) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: <xformDef> No action supplied\n", pN->Fname(), pN->Line()) ; }
if (m_FormDefs.Exists(fname)) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: Form %s already exists\n", pN->Fname(), pN->Line(), *fname) ; }
if (rc != E_OK) return rc ;
// Deal with the form's default class pClass = m_ADP.GetPureClass(cname) ; if (!pClass) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: <xformDef> Class %s does not exist\n", pN->Fname(), pN->Line(), *cname) ; } m_pLog->Log("File %s Line %d: XFORMDEF tag\n", pN->Fname(), pN->Line()) ;
if (rc != E_OK) return rc ;
// Create new form pFormdef = new hdsFormdef() ; pFormdef->m_Formname = fname ; pFormdef->m_DfltAct = hname ; pFormdef->m_pClass = pClass ;
if (bRecap) pFormdef->m_bScriptFlags |= INC_SCRIPT_RECAPTCHA ;
m_FormDefs.Insert(pFormdef->m_Formname, pFormdef) ;
// Check and add the form handler name if (!m_FormHdls.Exists(hname)) m_FormHdls.Insert(hname, (hdsFormhdl*) 0) ;
m_pLog->Log("Added <xform name=%s>\n", *pFormdef->m_Formname) ;
// Now process sub-nodes tga.m_pFormdef = pFormdef ; for (pN1 = pN->GetFirstChild() ; rc == E_OK && pN1 ; pN1 = pN1->Sibling()) { pVE = _readTag(&tga, pN1, flags, 0, 0) ;
if (!pVE) { rc = E_SYNTAX ; break ; }
pFormdef->m_VEs.Add(pVE) ; m_pLog->Log("Added VE of %s\n", *pVE->m_Tag) ; }
if (rc != E_OK) delete pFormdef ; return rc ; }
hdsFormref* hdsApp::_readFormDef (hzXmlNode* pN, hdsResource* pLR) { // Process an <xformDef> tag occuring WITHIN a page or article definition. This produces both a form definition (hdsFormdef) and a form reference (hdsFormref), as described in // the section on Forms in the Library Overview. // // Accordingly, in addition to the three attributes necessary for the form definition, the submission URL needed for the form reference // // For the form definition there are three attributes of 'name' which names the form, 'class' which sets the host data class, and 'action' which names a yet to be defined form // handler. The first two are compulsory but if the action is not set in the <xformDef> tag itself, it must be set for each active button in the form. Both the form definition // name and form handler name(s) are required to be unique across the entire configs. // // For the form reference an additional attribute of 'url' is needed to supply the submission URL. // // The following occurs within this function: // // 1) A new form definition is created placed in hdsApp::m_FormDefs. This map is purely to ensure forms are given unique names. // // 2) A new form reference is created and will point to the form definition. A pointer to this is returned if no errors occur. // // 3) For each form action, a form handler is named and a URL supplied. The form handler name is added to hdsApp::m_FormHdl, ensuring it is unique. No actual form handler // is created however. This must await processing of a <xformHdl> tag. In the meantime the form handler pointer in the entry in hdsApp::m_FormHdl, is NULL. // // 4) The URL and the form handler name are added to hdsApp::m_FormUrl2Hdl // // 5) Each form action URL, together with the form reference, is added to both hdsApp::m_FormUrl2Ref and hdsApp::m_FormRef2Url // // Arguments: 1) pN Current XML node // 2) pLR Current locatable resoure (page or article) // // Returns: Pointer to the form reference // NULL if a syntax error occurs
_hzfunc("hdsApp::_readFormDef:2") ;
hzArray <hzString> hnames ; // Proposed form handler names
_tagArg tga ; // Tag argument for _readTag() hzAttrset ai ; // Attribute iterator hzXmlNode* pN1 ; // For processing child nodes hdsVE* thisVE ; // Generic visible entity hdsVE* pVE ; // Generic visible entity hdsFormdef* pFormdef ; // This form definition hdsFormref* pFormref ; // Implicit form reference const hdbClass* pClass = 0 ; // Data class refered to in xform declaration hdsPage* pPage ; // If locatable resource is a page hzString fname ; // Name (of this form) hzString cname ; // Class name hzString hname ; // Form handler name hzString faUrl ; // Form action URL hzString title ; // Button title hzString page ; // Expected page (to go to) hzString whom ; // Allowed users hzString css ; // Allowed CSS style uint32_t flags ; // For _readTag() call uint32_t bErr = 0 ; // Error condition bool bRecap = false ; // Google Recaptcha Indicator
// Check params if (!pN) Fatal("No node supplied\n") ; if (!pN->NameEQ("xformDef")) Fatal("Incorrect node (%s) supplied. Must be <xformDef>\n", pN->txtName()) ; if (!pLR) Fatal("No locatable resource supplied\n", pN->txtName()) ;
pPage = dynamic_cast<hdsPage*>(pLR) ;
// Create new form definition and a form reference pFormdef = new hdsFormdef() ; pFormref = new hdsFormref(this) ; m_pLog->Log("File %s Line %d: XFORMDEF tag (%p in-page ref at %p)\n", pN->Fname(), pN->Line(), pFormdef, pFormref) ; thisVE = pFormref ; thisVE->m_strPretext = pN->txtPtxt() ; pFormref->m_Line = pN->Line() ; pFormref->m_Indent = pN->Level() ; pFormref->m_Tag = pN->txtName() ; pFormref->m_Formname = pFormdef->m_Formname ;
// Process attributes for (ai = pN ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("name")) fname = ai.Value() ; else if (ai.NameEQ("class")) cname = ai.Value() ; else if (ai.NameEQ("handler")) hname = ai.Value() ; else if (ai.NameEQ("url")) faUrl = ai.Value() ; else if (ai.NameEQ("recaptcha")) bRecap = ai.ValEQ("true") ; else { bErr=1 ; m_pLog->Log("File %s Line %d: <form> Bad param (%s=%s)\n", pN->Fname(), pN->Line(), ai.Name(), ai.Value()) ; } }
if (!fname) { bErr=1 ; m_pLog->Log("File %s Line %d: <xformDef> No form name supplied\n", pN->Fname(), pN->Line()) ; } if (!cname) { bErr=1 ; m_pLog->Log("File %s Line %d: <xformDef> No native class supplied\n", pN->Fname(), pN->Line()) ; }
if (hname || faUrl) { // If either action or URL are supplied, both must be if (!hname) { bErr=1 ; m_pLog->Log("File %s Line %d: <xformDef> URL supplied but no form handler\n", pN->Fname(), pN->Line()) ; } if (!faUrl) { bErr=1 ; m_pLog->Log("File %s Line %d: <xformDef> Form handler supplied but no URL\n", pN->Fname(), pN->Line()) ; } }
if (m_FormDefs.Exists(fname)) { bErr=1 ; m_pLog->Log("File %s Line %d: Form %s already exists\n", pN->Fname(), pN->Line(), *fname) ; }
// Deal with the form's default class pClass = m_ADP.GetPureClass(cname) ; if (!pClass) { bErr=1 ; m_pLog->Log("File %s Line %d: <xformDef> Class %s does not exist\n", pN->Fname(), pN->Line(), *cname) ; }
// Check form handler name and URL are either both present or both absent if (hname) { if (!faUrl) { faUrl = hname ; m_pLog->Log("File %s Line %d: NOTE: URL assuming Form handler name of %s\n", pN->Fname(), pN->Line(), *hname) ; }
if (faUrl && m_FormUrl2Hdl.Exists(faUrl)) { // Note that it is not illegal to reuse a submission URL as long as it points to the same form handler if (hname != m_FormUrl2Hdl[faUrl]) { bErr=1 ; m_pLog->Log("File %s Line %d: Form action URL %s already points to another form handler (%s)\n", pN->Fname(), pN->Line(), *faUrl, *m_FormUrl2Hdl[faUrl]) ; } }
// Reserve form handler name and associate URL and form handler. if (!bErr) { pFormdef->m_DfltAct = hname ; pFormdef->m_DfltURL = faUrl ;
if (!m_FormHdls.Exists(hname)) { m_FormHdls.Insert(hname,0) ; pFormdef->m_nActions++ ; } m_FormUrl2Hdl.Insert(faUrl,hname) ; m_FormUrl2Ref.Insert(faUrl, pFormref) ; m_FormRef2Url.Insert(pFormref, faUrl) ; } } else { if (faUrl) { bErr=1 ; m_pLog->Log("File %s Line %d: Form action URL %s supplied but no form handler named\n", pN->Fname(), pN->Line(), *hname) ; } }
if (bErr) { delete pFormdef ; delete pFormref ; return 0 ; }
// Name the new form definition and copy the form definition name to the form reference pFormdef->m_Formname = fname ; pFormref->m_Formname = fname ;
// Set the form definition class pFormdef->m_pClass = pClass ;
if (bRecap) { if (pPage) pPage->m_bScriptFlags |= INC_SCRIPT_RECAPTCHA ; pFormdef->m_bScriptFlags |= INC_SCRIPT_RECAPTCHA ; } m_FormDefs.Insert(pFormdef->m_Formname, pFormdef) ;
if (pPage) pPage->m_xForms.Add(pFormref) ;
if (pLR) pLR->m_flagVE |= VE_CT_ACTIVE ;
if (pPage) m_pLog->Log("Added <xform name=%s to page %s>\n", *pFormdef->m_Formname, *pPage->m_Title) ; else m_pLog->Log("Added <xform name=%s>\n", *pFormdef->m_Formname) ;
// Now process sub-nodes (form substance) tga.m_pLR = pLR ; tga.m_pFormdef = pFormdef ; tga.m_pFormref = pFormref ; for (pN1 = pN->GetFirstChild() ; !bErr && pN1 ; pN1 = pN1->Sibling()) { m_pLog->Log("Processing a %s tag\n", pN1->txtName()) ;
pVE = _readTag(&tga, pN1, flags, 0, 0) ; //pLR, pFormdef, pFormref, 0, 0) ;
if (!pVE) { bErr=1 ; break ; }
pFormdef->m_VEs.Add(pVE) ; m_pLog->Log("Added VE of %s\n", *pVE->m_Tag) ; } m_pLog->Log("File %s Line %d: XFORMDEF tag COMPLETE (in-page ref at %p)\n", pN->Fname(), pN->Line(), pFormref) ;
if (bErr) { delete pFormdef ; delete pFormref ; return 0 ; }
return pFormref ; }
hdsFormref* hdsApp::_readFormRef (hzXmlNode* pN, hdsResource* pLR) { // Category: Dissemino configs // // Process a <xformRef> tag. // // The <xformRef> tag imports a form as a complete, self contained visual entity into a page or article. Accordingly, the tag is legal only within the definitions of a page or // article or within the definition of an entity that can only be a part of a page or article such as an include block. As the form is self contained, <xformRef> has no legal // sub-tags. The form being imported must have been defined previously and in the project space, outside the definitions of any page or article. // // The following occurs within this function: // // 1) A new form reference is created and will point to the named form definition. A pointer to this is returned if no errors occur. // // 2) For each form action listed in the form definition, a URL supplied. The URL and the form handler name are added to hdsApp::m_FormUrl2Hdl // // 3) Each form action URL, together with the form reference, is added to both hdsApp::m_FormUrl2Ref and hdsApp::m_FormRef2Url // // Arguments: 1) pN Current XML node // 2) pLR The host resource (page or article) // // Returns: Pointer to the form // NULL if a syntax error occurs
_hzfunc("hdsApp::_readFormRef") ;
hzArray<hzString> urls ; // Form action URLs (form may be multiple action)
hzAttrset ai ; // Attribute iterator hdsFormref* pFormref ; // Form reference hzString fname ; // Name (of pre-defined form) hzString faUrl ; // Form action URL hzString faCtx ; // Form context hzString hnam ; // Name of form reference (multiple button forms only) uint32_t bErr = 0 ; // Error condition uint16_t clsDtId ; // Data class delta id
// Check parameters if (!pN) Fatal("No node supplied\n") ; if (!pN->NameEQ("xformRef")) Fatal("Incorrect node (%s) supplied. Must be <xformRef>\n", pN->txtName()) ;
// Allocate the form references and place them in hdsApp::m_FormRefs pFormref = new hdsFormref(this) ; pFormref->m_Line = pN->Line() ; pFormref->m_Indent = pN->Level() ; pFormref->m_Tag = pN->txtName() ;
// Process <xformRef> attributes for (ai = pN ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("form")) fname = ai.Value() ; else if (ai.NameEQ("context")) faCtx = ai.Value() ; else if (ai.NameEQ("url")) { faUrl = ai.Value() ; if (m_FormUrl2Ref.Exists(faUrl)) { m_pLog->Log("File %s Line %d: <xformRef> Form action URL %s already in use\n", pN->Fname(), pN->Line(), *faUrl) ; return 0 ; } else m_FormUrl2Ref.Insert(faUrl, pFormref) ; } else { bErr=1 ; m_pLog->Log("File %s Line %d: <xformRef> Bad param (%s=%s)\n", pN->Fname(), pN->Line(), ai.Name(), ai.Value()) ; } }
if (!fname) { bErr=1 ; m_pLog->Log("File %s Line %d: <xformRef> No form definition name supplied\n", pN->Fname(), pN->Line()) ; } if (!faCtx) { bErr=1 ; m_pLog->Log("File %s Line %d: <xformRef> No form context supplied\n", pN->Fname(), pN->Line()) ; } if (!faUrl) { bErr=1 ; m_pLog->Log("File %s Line %d: <xformRef> No submission URLs supplied\n", pN->Fname(), pN->Line()) ; }
if (bErr) { delete pFormref ; return 0 ; }
// Check form exists if (!m_FormDefs.Exists(fname)) { m_pLog->Log("File %s Line %d: <xformRef> Form %s not yet defined\n", pN->Fname(), pN->Line(), *fname) ; return 0 ; }
pFormref->m_Formname = fname ; m_FormRef2Url.Insert(pFormref, faUrl) ;
if (pLR) pLR->m_flagVE |= VE_CT_ACTIVE ;
// Check context exists pFormref->m_ClsId = clsDtId = m_ADP.GetDataClassID(faCtx) ; if (!pFormref->m_ClsId) { m_pLog->Log("File %s Line %d: <xformRef> Context %s not found\n", pN->Fname(), pN->Line(), *faCtx) ; return 0 ; }
m_pLog->Log("File %s Line %d: <xformRef> Added OK to resource\n", pN->Fname(), pN->Line()) ; return pFormref ; }
hdsVE* hdsApp::_readField (hzXmlNode* pN, hdsFormdef* pFormdef) { // Process an <xfield> tag within a <xformDef> tag, thereby adding a field (hdsField) to a HTML form (hdsFormdef). Fields within forms must relate to a data object member, OR // an independent variable. The <xfield> tag must identify the member or variable concerned, then it must supply the necessary parameters for a viable HTML <input> tag. These // parameters can be supplied directly, or as a predefined fldspec (field specification). // // Arguments: 1) pN The current node // 2) pForm Current hdsFormdef in progress // // Returns: Pointer to the visible entity // NULL if a syntax error occurs
_hzfunc("hdsApp::_readField") ;
const hdbMember* pMbr = 0 ; // Class member const hdbClass* pClass = 0 ; // Data class refered to in xform declaration
hdsField* pFld = 0 ; // Mkapp form field hzAttrset ai ; // Attribute iterator hzString vnam ; // Variable name (from attr var) which can be standalone or class member hzString spec ; // fldspec name (from attr spec) hzString cnam ; // Variable name (from attr var) hzString memb ; // Member name (if not to be infered from 'var' attribute) hzString S ; // Temp string hzString dtS ; // Data type string hzString htS ; // Html type string uint32_t nRows = 0 ; // No of rows (only if fldspec not supplied) uint32_t nCols = 0 ; // No of cols (only if fldspec not supplied) uint32_t nSize = 0 ; // Max size (only if fldspec not supplied) uint32_t flags = 0 ; // Additional field flags (eg compulsory) uint32_t bErr = 0 ; // Error condition
// Check node if (!pN) Fatal("No node supplied\n") ;
// Check form (an <xfield> must be a subtag of <xformDef>) if (!pFormdef) { m_pLog->Log("Line %d: No form supplied\n", pN->Line()) ; return 0 ; }
// Create hdsField instance pFld = new hdsField(this) ; pFld->m_strPretext = pN->txtPtxt() ; pFld->m_Line = pN->Line() ; pFld->m_Indent = pN->Level() ; pFld->m_Tag = pN->txtName() ;
// Obtain the settings. Note that in the for (ai = pN ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("var")) vnam = ai.Value() ; else if (ai.NameEQ("fldspec")) spec = ai.Value() ; else if (ai.NameEQ("class")) cnam = ai.Value() ; else if (ai.NameEQ("member")) memb = ai.Value() ; else if (ai.NameEQ("type")) dtS = ai.Value() ; else if (ai.NameEQ("rows")) nRows = atoi(ai.Value()) ; else if (ai.NameEQ("cols")) nCols = atoi(ai.Value()) ; else if (ai.NameEQ("size")) nSize = atoi(ai.Value()) ; else if (ai.NameEQ("data")) { pFld->m_Source = ai.Value() ; flags |= VE_CT_ACTIVE ; } else if (ai.NameEQ("flags")) { if (ai.ValEQ("req")) flags |= VE_COMPULSORY ; else if (ai.ValEQ("opt")) flags &= ~VE_COMPULSORY ; else if (ai.ValEQ("multiple")) flags |= VE_MULTIPLE ; else if (ai.ValEQ("unique")) flags |= VE_UNIQUE ; else if (ai.ValEQ("unique/req")) flags |= (VE_UNIQUE + VE_COMPULSORY) ; else { m_pLog->Log("File %s Line %d: <xfield> tag: Bad flag (%s)\n", pN->Fname(), pN->Line(), ai.Value()) ; bErr=1 ; } } else if (ai.NameEQ("newin")) { // Expect arg to name a class.member S = ai.Value() ; if (!S.Contains(CHAR_PERIOD)) { bErr=1 ; m_pLog->Log("File %s Line %d: <xfield> newin attr must name class.member\n", pN->Fname(), pN->Line()) ; } S.TruncateUpto(".") ; pClass = m_ADP.GetPureClass(S) ; if (!pClass) { bErr=1 ; m_pLog->Log("File %s Line %d: <xfield> newin attr class %s not found\n", pN->Fname(), pN->Line(), *S) ; } } else { bErr=1 ; m_pLog->Log("File %s Line %d: <xfield> Bad param (%s=%s)\n", pN->Fname(), pN->Line(), ai.Name(), ai.Value()) ; } }
if (bErr) goto failed ;
// Resolve/Validate parameters. ... if (memb) { // The member attribute is supplied so no vnam or spec allowed. The member must be of the class in the form and the spec will be the member default if (vnam) { bErr=1 ; m_pLog->Log("File %s Line %d <xfield> tag has 'member' attr. 'vnam' not permitted\n", pN->Fname(), pN->Line()) ; } if (spec) { bErr=1 ; m_pLog->Log("File %s Line %d <xfield> tag has 'member' attr. 'spec' not permitted\n", pN->Fname(), pN->Line()) ; }
// Check the meber exists if (cnam) { // Guest class pClass = m_ADP.GetPureClass(cnam) ; if (!pClass) { bErr=1 ; m_pLog->Log("File %s Line %d: <xfield> class %s not found\n", pN->Fname(), pN->Line(), *cnam) ; } } else { pClass = pFormdef->m_pClass ; if (!pClass) { bErr=1 ; m_pLog->Log("File %s Line %d: <xfield> class not set in form\n", pN->Fname(), pN->Line()) ; } }
if (pClass) { pFld->m_pClass = pClass ; pMbr = pFld->m_pClass->GetMember(memb) ; if (!pMbr) { bErr=1 ; m_pLog->Log("File %s Line %d: <xfield> NOTE no such class member as %s\n", pN->Fname(), pN->Line(), *memb) ; } pFld->m_pMem = pMbr ; }
if (pMbr) { pFld->m_Fldspec = *pMbr->GetSpec() ; pFld->m_Varname = pMbr->strName() ; }
if (bErr) goto failed ;
m_pLog->Log("Using member spec %s Set field %s rows=%d cols=%d size=%d flags=%08x dtype=%s htype=%d\n", *pFld->m_Fldspec.m_Refname, *pFld->m_Varname, pFld->m_Fldspec.nRows, pFld->m_Fldspec.nCols, pFld->m_Fldspec.nSize, pFld->m_flagVE, pFld->m_Fldspec.m_pType->txtType(), pFld->m_Fldspec.htype) ; } else if (spec) { // A spec is supplied so vnam is needed, either to name the member or just be an independent variable if (!vnam) { m_pLog->Log("File %s Line %d: <xfield> tag has 'spec' attr but no 'vnam'\n", pN->Fname(), pN->Line()) ; goto failed ; }
if (htS || dtS) { m_pLog->Log("File %s Line %d: <xfield> spec (%s) not allowed with dtype or htype\n", pN->Fname(), pN->Line(), *spec) ; goto failed ; }
if (!m_Fldspecs.Exists(spec)) { m_pLog->Log("File %s Line %d field fldspec %s not previously declared\n", pN->Fname(), pN->Line(), *spec) ; goto failed ; }
pFld->m_Fldspec = m_Fldspecs[spec] ; pFld->m_Varname = vnam ; pFld->m_flagVE |= flags ;
m_pLog->Log("Using pre-def spec %s Set field %s rows=%d cols=%d size=%d flags=%08x dtype=%s htype=%d\n", *pFld->m_Fldspec.m_Refname, *pFld->m_Varname, pFld->m_Fldspec.nRows, pFld->m_Fldspec.nCols, pFld->m_Fldspec.nSize, pFld->m_flagVE, pFld->m_Fldspec.m_pType->txtType(), pFld->m_Fldspec.htype) ; } else { // No member or pre-defined field specification supplied, must have the HTML params if (!nRows || !nCols || !nSize || !dtS) { if (!vnam) m_pLog->Log("File %s Line %d: xfield is missing variable name\n", pN->Fname(), pN->Line()) ; if (!nRows) m_pLog->Log("File %s Line %d: xfield is missing rows attribte\n", pN->Fname(), pN->Line()) ; if (!nCols) m_pLog->Log("File %s Line %d: xfield is missing cols attribte\n", pN->Fname(), pN->Line()) ; if (!nSize) m_pLog->Log("File %s Line %d: xfield is missing size attribte\n", pN->Fname(), pN->Line()) ; if (!dtS) m_pLog->Log("File %s Line %d: xfield is missing type attribte\n", pN->Fname(), pN->Line()) ;
goto failed ; }
pFld->m_Fldspec.m_pType = m_ADP.GetDatatype(dtS) ; if (!pFld->m_Fldspec.m_pType) { m_pLog->Log("File %s Line %d: xfield %s: Illegal fld type %s\n", pN->Fname(), pN->Line(), *vnam, *dtS) ; goto failed ; }
pFld->m_Fldspec.m_Refname = pFormdef->m_Formname + "->" + vnam ; pFld->m_Varname = vnam ; pFld->m_flagVE |= flags ; pFld->m_Fldspec.nRows = nRows ; pFld->m_Fldspec.nCols = nCols ; pFld->m_Fldspec.nSize = nSize ; }
if (bErr) goto failed ;
if (vnam) { if (vnam.Contains(".")) { if (!pFormdef->m_pClass) { m_pLog->Log("File %s Line %d: <xfield> Note the form var=\"composite.member\" is not allowed where the parent <xformDef> lacks a class\n", pN->Fname(), pN->Line()) ; goto failed ; }
cnam = vnam ; cnam.TruncateUpto(".") ; memb = vnam ; memb.TruncateBeyond(".") ;
pMbr = pFormdef->m_pClass->GetMember(cnam) ; if (!pMbr) { m_pLog->Log("File %s Line %d: <xfield> %s is not a member of class %s\n", pN->Fname(), pN->Line(), *cnam, pFormdef->m_pClass->txtType()) ; goto failed ; }
// Now set the class of this <xfield> to that of the composite member if (pMbr->Basetype() != BASETYPE_CLASS) { m_pLog->Log("File %s Line %d: <xfield> %s has an atomic datatype of %s and so is non-coposite\n", pN->Fname(), pN->Line(), *cnam) ; goto failed ; } pFld->m_pClass = (hdbClass*) pMbr->Datatype() ;
// Now set the member of this <xfield> to that of the composite's member (RHS) pFld->m_pMem = pFld->m_pClass->GetMember(memb) ; } else { if (pFormdef->m_pClass) { pFld->m_pClass = pFormdef->m_pClass ; pMbr = pFld->m_pClass->GetMember(vnam) ; if (!pMbr) m_pLog->Log("File %s Line %d: <xfield> NOTE no such class member as %s\n", pN->Fname(), pN->Line(), *vnam) ; pFld->m_pMem = pMbr ; } } }
if (bErr) goto failed ;
if (!pFormdef->m_mapFlds.Exists(pFld->m_Varname)) pFormdef->m_mapFlds.Insert(pFld->m_Varname, pFld) ; pFormdef->m_vecFlds.Add(pFld) ;
m_pLog->Log("Added field %s fldspec %s rows=%d cols=%d size=%d flags=%08x dtype=%s htype=%d to form %s\n", *pFld->m_Varname, *pFld->m_Fldspec.m_Refname, pFld->m_Fldspec.nRows, pFld->m_Fldspec.nCols, pFld->m_Fldspec.nSize, pFld->m_flagVE, pFld->m_Fldspec.m_pType->txtType(), pFld->m_Fldspec.htype, *pFormdef->m_Formname) ; return pFld ;
failed: delete pFld ; return 0 ; }
hdsVE* hdsApp::_readXhide (hzXmlNode* pN, hdsFormdef* pForm) { // Process an <xhide> tag. // // This tag may only exist within an <xformDef> tag and has two attributes, 'name' and 'value'. Its effect is to insert a hidden feild into the output HTML // of the form. The latter attribute is commonly a percent entity. // // The <xhide> tag is sometimes used in Dissemino applications to give a path back to some starting point. This could be after the user either completes or // aborts, a series of one or more forms, or it could be to 'rescue' the user after a timeout. // // One example would be where a user is on a page they wish to comment on but to submit a comment they need to be logged in. They have either forgotton to // log in or have been timed out. The login is available from the pull-down menu. By using such as <xhide name="lastpage" value="%x:referer;"> as a sub-tag // of <xformDef> in the login page, the login form's 'Log-In' button can take the user back to the page of interest using the percent entity %e:lastpage; // // Hidden fields are notable because they have null field specifications. Only the m_Varname and m_Source members have values. // // Arguments: 1) pN The current node // 2) pForm Current hdsFormdef in progress // // Returns: Pointer to the visible entity // NULL if a syntax error occurs
_hzfunc("hdsApp::_readXhide") ;
hzAttrset ai ; // Attribute iterator hdsField* pFld ; // Mkapp form field hzString dtS ; // Data type/HTML type identifier (for hidden type) uint32_t bErr = 0 ; // Error condition
if (!this) Fatal("No instance\n") ; if (!pN) Fatal("No node supplied\n") ;
if (!pForm) { m_pLog->Log("Line %d: No form supplied\n", pN->Line()) ; return 0 ; }
// Create the field pFld = new hdsField(this) ;
// Create or fetch the field specification dtS = "string" ; pFld->m_Fldspec.m_pType = m_ADP.GetDatatype(dtS) ; pFld->m_Fldspec.m_Refname = "No refname (form _readXhide)" ; pFld->m_Fldspec.htype = HTMLTYPE_HIDDEN ;
pFld->m_strPretext = pN->txtPtxt() ; pFld->m_Line = pN->Line() ; pFld->m_Indent = pN->Level() ;
for (ai = pN ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("name")) pFld->m_Varname = ai.Value() ; else if (ai.NameEQ("value")) pFld->m_Source = ai.Value() ; else { bErr=1 ; m_pLog->Log("File %s Line %d: <xhide> Bad param (%s=%s)\n", pN->Fname(), pN->Line(), ai.Name(), ai.Value()) ; } }
if (!pFld->m_Varname) { bErr=1 ; m_pLog->Log("File %s Line %d: <xhide> No name supplied\n", pN->Fname(), pN->Line()) ; } if (!pFld->m_Source) { bErr=1 ; m_pLog->Log("File %s Line %d: <xhide> No source supplied\n", pN->Fname(), pN->Line()) ; }
if (bErr) { delete pFld ; return 0 ; }
if (!pForm->m_mapFlds.Exists(pFld->m_Varname)) pForm->m_mapFlds.Insert(pFld->m_Varname, pFld) ; pForm->m_vecFlds.Add(pFld) ;
m_pLog->Log("Added hidden field %s src=%s to form %s\n", *pFld->m_Varname, *pFld->m_Source, *pForm->m_Formname) ; return pFld ; }
hzEcode hdsApp::_readResponse (hzXmlNode* pN, hdsFormhdl* pFhdl, hzString& pageGoto, hdsResource** pPageGoto) { // // Read in all tags for a page (with or without forms). All tags begining with an 'x' are mkapp active tags (eg xform and xfield) and these // tags produce the associated mkapp classes. All other tags must be valid HTML tags and are there only for presentation. Since the config // files are XML a successful load means all the tags are balenced. This means we only need to mirror the structure of XML tags to visual // entities. // // Arguments: 1) pN Current XML node expected to be <response> tag // 2) pFhdl Applicable form handler // // Returns: E_SYNTAX If there is a syntax error // E_OK If no errors occured
_hzfunc("hdsApp::_readResponse") ;
_tagArg tga ; // Tag argument for _readTag() hzAttrset ai ; // Attribute iterator hzXmlNode* pN1 ; // Subtag probe hdsResource* pRes = 0 ; // Resource hdsPage* pPage = 0 ; // Page in progress hdsVE* pVE ; // Set if a HTML entity is found hzString name ; // Page name from params hzString url ; // Page URL from params hzString color ; // Background color hzString gopag ; // Goto (page name) hzEcode rc = E_OK ; // Return code
if (!pN) Fatal("No node supplied\n") ;
if (!pN->NameEQ("response") && !pN->NameEQ("error")) Fatal("Wrong Call - Expected <response> or <error>, got <%s>\n", pN->txtName()) ;
if (!pFhdl) Fatal("No form supplied for <response>\n") ;
m_pLog->Log("Node %s line %d\n", pN->txtName(), pN->Line()) ;
// Page attributes for (ai = pN ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("name")) name = ai.Value() ; else if (ai.NameEQ("path")) url = ai.Value() ; else if (ai.NameEQ("bgcolor")) color = ai.Value() ; else if (ai.NameEQ("goto")) gopag = ai.Value() ; else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <response> Invalid param (%s=%s)\n", pN->Fname(), pN->Line(), ai.Name(), ai.Value()) ; } }
if (rc != E_OK) return rc ;
// Validate attribute combinations. If there is a goto (page) set, we need to check if its value is either 'hostpage' (meaning the page hosting // the current form) or '%lastpage' (meaning the referer to the hostpage) or that the page already exists as a defined page. If none of these // conditions are met, this is an error. Also if there is a goto set then there should not be any other attribute since we are not defining a // response or error page!
if (gopag) { pageGoto = gopag ;
// if (gopag[0] == CHAR_PERCENT) // pageGoto = gopag ; // else
if (gopag[0] != CHAR_PERCENT) { //pRes = m_PagesPath[gopag] ; pRes = m_ResourcesPath[gopag] ; if (!pRes) m_pLog->Log("File %s Line %d: WARNING Response page goto directive (%s) does not exist\n", pN->Fname(), pN->Line(), *gopag) ; else *pPageGoto = pRes ; }
if (name || url || color) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: Response page goto directive excludes other attributes\n", pN->Fname(), pN->Line()) ; }
if (pN->GetFirstChild()) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: Response page goto directive excludes other subtags\n", pN->Fname(), pN->Line()) ; }
return rc ; }
// There is no goto set so we are defining a response or an error page if (!name) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d: Response has no name\n", pN->Fname(), pN->Line()) ; } else { // A response page must have a name but not that of an existing page (the opposite of the goto scenario). //if (m_PagesName.Exists(name)) if (m_ResourcesName.Exists(name)) { rc = E_DUPLICATE ; m_pLog->Log("File %s Line %d: Response page name (%s) already used by a formal page\n", pN->Fname(), pN->Line(), *name) ; }
if (m_Responses.Exists(name)) { rc = E_DUPLICATE ; m_pLog->Log("File %s Line %d: Response page name (%s) already used as a response page\n", pN->Fname(), pN->Line(), *name) ; } }
if (rc != E_OK) return rc ;
pPage = new hdsPage(this) ;
pN->Export(pPage->m_XML) ; pPage->m_Digest.CalcMD5(pPage->m_XML) ;
pPage->m_Title = name ; pPage->m_Url = url ; pPage->m_resAccess = pFhdl->m_Access ; if (color) IsHexnum(pPage->m_BgColor, *color) ; pPage->m_Line = pN->Line() ; m_Responses.Insert(name, pPage) ;
*pPageGoto = pPage ; // Page forms and other objects for (pN1 = pN->GetFirstChild() ; rc == E_OK && pN1 ; pN1 = pN1->Sibling()) { m_pLog->Log("File %s Line %d:%d Tag is %s\n", pN->Fname(), pN1->Line(), pN1->Level(), pN1->txtName()) ; }
tga.m_pLR = pPage ; for (pN1 = pN->GetFirstChild() ; rc == E_OK && pN1 ; pN1 = pN1->Sibling()) { if (pN1->NameEQ("desc")) { pPage->m_Desc = pN1->m_fixContent ; continue ; }
pVE = _readTag(&tga, pN1, pPage->m_bScriptFlags, 0, 0) ; //pPage, 0, 0, 0, 0) ;
if (!pVE) rc = E_SYNTAX ; else pPage->AddVisent(pVE) ; }
return rc ; }
/* ** SECTION 6: Page and Article Config Read Functions */
hzEcode hdsApp::_readPageBody (hdsPage* pPage, hzXmlNode* pN) { // Category: Page and Article Config Read Functions // // Process an <xbody> tag to read a page body. The page body can contain a mixture of Dissemino and HTML tags. // // Arguments: 1) pN Current XML node expected to be <xbody> tag // // Returns: E_SYNTAX If there is a syntax error // E_OK If no errors occured
_hzfunc("hdsApp::_readPageBody") ;
hzVect<hzXmlNode*> result ; // Used by FindSubnodes to extract bodytext
_tagArg tga ; // Tag argument for _readTag() hzAttrset ai ; // Attribute iterator hzXmlNode* pN1 ; // Subtag probe hdsVE* pVE ; // Set if a HTML entity is found hzString color ; // Background color hzEcode rc = E_OK ; // Return code
if (!pPage) Fatal("No page supplied\n") ; if (!pN) Fatal("No node supplied\n") ;
if (!pN->NameEQ("xbody")) Fatal("Wrong Call. Expected <xbody> got <%s>\n", pN->txtName()) ;
//m_cfgErr.Clear() ;
// Body attributes for (ai = pN ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("bgcolor")) color = ai.Value() ; else if (ai.NameEQ("css")) pPage->m_CSS = ai.Value() ; else if (ai.NameEQ("onpageshow")) pPage->m_Onpage = ai.Value() ; else if (ai.NameEQ("onload")) pPage->m_Onload = ai.Value() ; else if (ai.NameEQ("onresize")) pPage->m_Resize = ai.Value() ; else //{ rc = E_SYNTAX ; m_cfgErr.Printf("%s. File %s Line %d. Invalid <xbody> param (%s=%s)\n", pN->Fname(), pN->Line(), ai.Name(), ai.Value()) ; } { rc = E_SYNTAX ; m_pLog->Log("%s. File %s Line %d. Invalid <xbody> param (%s=%s)\n", pN->Fname(), pN->Line(), ai.Name(), ai.Value()) ; } }
if (rc != E_OK) return rc ;
if (color) IsHexnum(pPage->m_BgColor, *color) ;
// Page forms and other objects tga.m_pLR = pPage ; for (pN1 = pN->GetFirstChild() ; rc == E_OK && pN1 ; pN1 = pN1->Sibling()) { if (pN1->NameEQ("xformDef")) pVE = _readFormDef(pN1, pPage) ; else if (pN1->NameEQ("xformRef")) pVE = _readFormRef(pN1, pPage) ; else pVE = _readTag(&tga, pN1, pPage->m_bScriptFlags, 0, 0) ;
if (!pVE) rc = E_SYNTAX ; else pPage->AddVisent(pVE) ; }
return rc ; }
hzEcode hdsApp::_readPage (hzXmlNode* pN) { // Category: Page and Article Config Read Functions // // Process an <xpage> tag (a web page definition). (with or without forms). All tags begining with an 'x' are Dissemino active tags (eg xform and xfield) and these // tags produce the associated Dissemino classes. All other tags must be valid HTML tags and are there only for presentation. Since the config // files are XML a successful load means all the tags are balanced. This means we only need to mirror the structure of XML tags to visual // entities. // // Arguments: 1) pN Current XML node expected to be <xpage> tag // // Returns: E_SYNTAX If there is a syntax error // E_OK If no errors occured
_hzfunc("hdsApp::_readPage") ;
hzVect<hzXmlNode*> result ; // Used by FindSubnodes to extract bodytext
_tagArg tga ; // Tag argument for _readTag() hzAttrset ai ; // Attribute iterator hzChain H ; // Page HTML hzChain Z ; // Zipped page HTML hzChain pageXML ; // Page XML as per the supplied <xpage> node hzMD5 pageMD5 ; // The MD5 of the pageXML hzMD5 prevMD5 ; // Previously recorded MD5 of the pageXML hzAtom atom ; // For reading resource object member values hzXmlNode* pN1 ; // Subtag probe hzXmlNode* pN2 ; // Subtag probe hzXmlNode* pN3 ; // Subtag probe hdsPage* pPage ; // Page in progress hdsVE* pVE ; // Set if a HTML entity is found hzXDate now ; // Current time hzString pgTitle ; // Page title hzString pgUrl ; // Page URL hzString pgSubj ; // Page subject hzString pgAccess ; // Page access criteria hzString color ; // Background color uint32_t resAccess ; // Access flags uint32_t x ; // Tag iterator (for bodytext garnering) uint32_t resObjId ; // Resource respository object id bool bIndex = true ; // Index page by default bool bLang = true ; // Language support by default hzEcode rc = E_OK ; // Return code
// Check call if (!pN) Fatal("No node supplied\n") ; if (!pN->NameEQ("xpage")) Fatal("Wrong Call. Expected <xpage> got <%s>\n", pN->txtName()) ;
// Clear error report //m_cfgErr.Clear() ;
// Get XML value of the xpage tag and obtain digest pN->Export(pageXML) ; pageMD5.CalcMD5(pageXML) ; m_pLog->Log("Reading PAGE\n") ;
// Read page attributes from the <xpage> tag for (ai = pN ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("ops")) { if (ai.ValEQ("noindex")) bIndex = false ; } else if (ai.NameEQ("title")) pgTitle = ai.Value() ; else if (ai.NameEQ("path")) pgUrl = ai.Value() ; else if (ai.NameEQ("subject")) pgSubj = ai.Value() ; else if (ai.NameEQ("access")) pgAccess = ai.Value() ; else if (ai.NameEQ("lang")) bLang = ai.ValEQ("on") ; else { rc = E_SYNTAX ; //m_cfgErr.Printf("%s. File %s Line %d. Invalid <xpage> param (%s=%s)\n", pN->Fname(), pN->Line(), ai.Name(), ai.Value()) ; m_pLog->Log("%s. File %s Line %d. Invalid <xpage> param (%s=%s)\n", pN->Fname(), pN->Line(), ai.Name(), ai.Value()) ; } }
//if (!pgTitle) { rc = E_SYNTAX ; m_cfgErr.Printf("%s. File %s Line %d. No title supplied\n", pN->Fname(), pN->Line()) ; } //if (!pgUrl) { rc = E_SYNTAX ; m_cfgErr.Printf("%s. File %s Line %d. No URL supplied\n", pN->Fname(), pN->Line()) ; } if (!pgTitle) { rc = E_SYNTAX ; m_pLog->Log("%s. File %s Line %d. No title supplied\n", pN->Fname(), pN->Line()) ; } if (!pgUrl) { rc = E_SYNTAX ; m_pLog->Log("%s. File %s Line %d. No URL supplied\n", pN->Fname(), pN->Line()) ; }
if (!pgAccess) //{ rc = E_SYNTAX ; m_cfgErr.Printf("%s. File %s Line %d. No access criteria supplied\n", pN->Fname(), pN->Line()) ; } { rc = E_SYNTAX ; m_pLog->Log("%s. File %s Line %d. No access criteria supplied\n", pN->Fname(), pN->Line()) ; } else { resAccess = _calcAccessFlgs(pgAccess) ; if (resAccess == 0xffffffff) //{ rc = E_SYNTAX ; m_cfgErr.Printf("%s. File %s Line %d: Bad access specification (%s)\n", pN->Fname(), pN->Line(), *pgAccess) ; } { rc = E_SYNTAX ; m_pLog->Log("%s. File %s Line %d: Bad access specification (%s)\n", pN->Fname(), pN->Line(), *pgAccess) ; } }
if (rc != E_OK) return rc ;
// Check against existing pages. This function could be reloading the page as a result of an edit config in which case the page may exist. If not reloading // then the page must not exist by name or path or be a response page. If reloading the page can exist by name, path or both but if by both, then the page // by name must be the same as that by path.
if (!m_nLoadComplete) { if (m_ResourcesPath.Exists(pgUrl)) { //m_cfgErr.Printf("%s File %s Line %d: Illegal duplicate URL (%s) of an earlier page\n", pN->Fname(), pN->Line(), *pgUrl) ; m_pLog->Log("%s File %s Line %d: Illegal duplicate URL (%s) of an earlier page\n", pN->Fname(), pN->Line(), *pgUrl) ; rc = E_DUPLICATE ; }
if (m_ResourcesName.Exists(pgTitle)) { //m_cfgErr.Printf("%s File %s Line %d: Illegal duplicate title (%s) of an earlier page\n", pN->Fname(), pN->Line(), *pgTitle) ; m_pLog->Log("%s File %s Line %d: Illegal duplicate title (%s) of an earlier page\n", pN->Fname(), pN->Line(), *pgTitle) ; rc = E_DUPLICATE ; } }
if (rc != E_OK) return rc ;
m_pLog->Log("Page %s XML %u bytes, MD5 is %s\n", *pgUrl, pageXML.Size(), pageMD5.Txt()) ;
/* ** If there is already an entry for the page in the resources repository. If there is and the MD5 matches the above, then there is no need to process the <xpage> subtags. The ** page XML and HTML will be as per the resource repository entry. */
// If digest is the same as the previous known digest, the page data can be retrieved from the page repository
// rc = resObj.Init(m_pRepos_Resource) ; // if (rc != E_OK) // return hzerr(rc, "Could not init resource object") ;
atom.SetValue(BASETYPE_STRING, pgUrl) ; rc = m_pRepos_Resource->Exists(resObjId, m_pMbr_Resource_PATH, atom) ; if (rc != E_OK) m_pLog->Log("case 1 No resource repos entry for page %s\n", *pgUrl) ; else { // Previous entry found in resource repository if (!resObjId) { m_pLog->Log("case 2 No resource repos entry for page %s\n", *pgUrl) ; } else { m_pRepos_Resource->Fetch(m_objResource, resObjId) ; m_objResource.GetValue(atom, m_pMbr_Resource_MD5) ; prevMD5 = atom.MD5() ;
if (pageMD5 == prevMD5) { m_pLog->Log("Prev known MD5 is %s, the same as current MD5\n", prevMD5.Txt()) ; return E_OK ; } m_pLog->Log("Prev known MD5 is %s, curr is %s\n", prevMD5.Txt(), pageMD5.Txt()) ; } } rc = E_OK ;
/* ** No match on previous digest, so creat the page from the configs */
pPage = new hdsPage(this) ; pPage->m_Title = pgTitle ; pPage->m_Url = pgUrl ; pPage->m_Subj = pgSubj ; pPage->m_resAccess = resAccess ;
if (color) IsHexnum(pPage->m_BgColor, *color) ; pPage->m_Line = pN->Line() ; if (bLang) pPage->m_flagVE |= VE_LANG ;
//pPage->m_USL.SetPage(pPage->m_RID) ;
// Page forms and other objects tga.m_pLR = pPage ; for (pN1 = pN->GetFirstChild() ; rc == E_OK && pN1 ; pN1 = pN1->Sibling()) { if (pN1->NameEQ("desc")) { pPage->m_Desc = pN1->m_fixContent ; continue ; } if (pN1->NameEQ("keys")) { pPage->m_Keys = pN1->m_fixContent ; continue ; } if (pN1->NameEQ("xbody")) { rc = _readPageBody(pPage, pN1) ; continue ; } if (pN1->NameEQ("procdata")) { rc = _readExec(pN1, pPage->m_Exec, pPage, 0) ; continue ; } if (pN1->NameEQ("xtreeDcl")) { rc = _readXtreeDcl(pN1, pPage) ; continue ; }
if (pN1->NameEQ("xformDef")) pVE = _readFormDef(pN1, pPage) ; else if (pN1->NameEQ("xformRef")) pVE = _readFormRef(pN1, pPage) ; else pVE = _readTag(&tga, pN1, pPage->m_bScriptFlags, 0, 0) ;
if (!pVE) rc = E_SYNTAX ; else pPage->AddVisent(pVE) ; }
if (rc != E_OK) return rc ;
// Get the body text (everything within <p> tags) if (bIndex) { for (pN1 = pN->GetFirstChild() ; pN1 ; pN1 = pN1->Sibling()) { pN1->FindSubnodes(result, "p") ;
for (x = 0 ; x < result.Count() ; x++) { pN2 = result[x] ; for (pN3 = pN2->GetFirstChild() ; pN3 ; pN3 = pN3->Sibling()) { pPage->m_Bodytext << pN3->txtPtxt() ; pPage->m_Bodytext.AddByte(CHAR_NL) ; } pPage->m_Bodytext << pN2->m_fixContent ; } } }
rc = m_vecPages.Add(pPage) ; if (rc == E_OK) { // 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 %s (%s) into m_ResourcesPath\n", *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 %s (%s) into m_ResourcesName\n", *pPage->m_Url, *pPage->m_Title) ; }
// Sets page activity status AssignVisentIDs(pPage->m_VEs, pPage->m_flagVE) ;
pPage->EvalHtml(H) ;
if (pPage->m_flagVE & VE_ACTIVE) m_pLog->Out("Assigned VE ids. Page %s (%s) deemed ACTIVE\n", *pPage->m_Url, *pPage->m_Title) ; else { m_pLog->Out("Assigned VE ids. Page %s (%s) deemed INACTIVE\n", *pPage->m_Url, *pPage->m_Title) ; Gzip(Z, H) ; }
pPage->m_rawHTML = H ; pPage->m_zipHTML = Z ;
// End of _insertPage }
m_pLog->Log("Added page name %s (%s) with XML of %d bytes. Now have (%d names %d urls)\n", *pPage->m_Url, *pPage->m_Title, pPage->m_XML.Size(), m_ResourcesName.Count(), m_ResourcesPath.Count()) ;
/* ** Place page in formal resources repository */
if (rc == E_OK) { m_objResource.Clear() ; now.SysDateTime() ; rc = m_objResource.SetMbrValue(m_pMbr_Resource_DATE, now) ; if (rc != E_OK) m_pLog->Log("Could not set dtstamp\ni") ; }
if (rc == E_OK) { rc = m_objResource.SetMbrValue(m_pMbr_Resource_PATH, pPage->m_Url) ; if (rc != E_OK) m_pLog->Log("Could not set resObj PATH\n") ; }
if (rc == E_OK) { //atom.SetValue(BASETYPE_DIGEST, currMD5) ; rc = m_objResource.SetMbrValue(m_pMbr_Resource_MD5, pageMD5) ; if (rc != E_OK) m_pLog->Log("Could not set resObj MD5\n") ; }
if (rc == E_OK) { rc = m_objResource.SetBinary(m_pMbr_Resource_XML, pageXML) ; if (rc != E_OK) m_pLog->Log("Could not set resXML\n") ; }
if (rc == E_OK) { rc = m_objResource.SetBinary(m_pMbr_Resource_HTM, H) ; if (rc != E_OK) m_pLog->Log("Could not set resXML\n") ; }
if (rc == E_OK) { rc = m_objResource.SetBinary(m_pMbr_Resource_Zip, Z) ; if (rc != E_OK) m_pLog->Log("Could not set resXML\n") ; }
if (rc == E_OK) { //resObject.SetBinary("resHTML") ; m_pRepos_Resource->Insert(resObjId, m_objResource) ; if (rc != E_OK) m_pLog->Log("Could not insert page data into resource repos\n") ; else m_pLog->Log("Inserted page data into resource repos\n") ; }
threadLog("Clearing res obj\n") ; m_objResource.Clear() ; threadLog("Cleared res obj\n") ;
return rc ; }
hzEcode hdsApp::_readStdLogin (hzXmlNode* pN) { // Category: Dissemino Configuration // // Read in the standard login declaration which defines the URLs for the following:- // // - the URL for login form submissions // - the URL to go to in the event of authentication failure // - the URL to go to in the event of authentication success // - the URL to go to upon session resumption // // Argument: pN Current XML node expected to be <loginpage> tag // // Returns: E_SYNTAX If there is a syntax error // E_OK If no errors occured
_hzfunc("hdsApp::_readStdLogin") ;
hzAttrset ai ; // Attribute iterator hzString urlForm ; // Form submission URL hzString urlFail ; // Form submission URL hzString urlAuth ; // Form submission URL hzString urlResume ; // Form submission URL hzEcode rc = E_OK ; // Return code
if (!pN) Fatal("No node supplied\n") ; if (!pN->NameEQ("login")) Fatal("Wrong Call. Expected <loginpage> got <%s>\n", pN->txtName()) ;
if (m_LoginPost) { m_pLog->Log("File %s Line %d <login> tag: Illegal Duplicate\n", *pN->Filename(), pN->Line()) ; return E_DUPLICATE ; }
for (ai = pN ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("formURL")) urlForm = ai.Value() ; else if (ai.NameEQ("failURL")) urlFail = ai.Value() ; else if (ai.NameEQ("authURL")) urlAuth = ai.Value() ; else if (ai.NameEQ("resumeURL")) urlResume = ai.Value() ; else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <login> tag: Invalid param (%s=%s)\n", *pN->Filename(), pN->Line(), ai.Name(), ai.Value()) ; } }
// Test attributes if (!urlForm) { rc = E_NODATA ; m_pLog->Log("ile %s Line %d: No login form URL supplied\n", *pN->Filename(), pN->Line()) ; } if (!urlFail) { rc = E_NODATA ; m_pLog->Log("ile %s Line %d: No login failure URL supplied\n", *pN->Filename(), pN->Line()) ; } if (!urlAuth) { rc = E_NODATA ; m_pLog->Log("ile %s Line %d: No login success URL supplied\n", *pN->Filename(), pN->Line()) ; } if (!urlResume) { rc = E_NODATA ; m_pLog->Log("ile %s Line %d: No login resume URL supplied\n", *pN->Filename(), pN->Line()) ; }
if (rc != E_OK) return rc ;
return SetLoginPost(urlForm, urlFail, urlAuth, urlResume) ; }
hzEcode hdsApp::_readLogout (hzXmlNode* pN) { // Category: Page and Article Config Read Functions // // When a user logs out, they cannot remain on a page that requires a login to view. It is essential the user lands on a publicly available page, such as the home page or the // login page. // // Arguments: 1) pN Current XML node expected to be <logout> tag // // Returns: E_SYNTAX If there is a syntax error // E_OK If no errors occured
_hzfunc("hdsApp::_readLogout") ;
hzAttrset ai ; // Attribute iterator hzString path ; // Page URL from params hzString dest ; // Destination page on logout (must already exist as a defined page) hzEcode rc = E_OK ; // Return code
if (!pN) Fatal("No node supplied\n") ; if (!pN->NameEQ("logout")) Fatal("Wrong Call. Expected <logout> got <%s>\n", pN->txtName()) ;
// Page attributes for (ai = pN ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("path")) path = ai.Value() ; else if (ai.NameEQ("goto")) dest = ai.Value() ; else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <logout> Invalid param (%s=%s)\n", pN->Fname(), pN->Line(), ai.Name(), ai.Value()) ; } }
if (!path) { rc = E_NODATA ; m_pLog->Log("ile %s Line %d: No logout submission URL supplied\n", pN->Fname(), pN->Line()) ; } if (!dest) { rc = E_NODATA ; m_pLog->Log("ile %s Line %d: No logout destination URL supplied\n", pN->Fname(), pN->Line()) ; }
if (rc != E_OK) return rc ;
// Test for duplicate names or URLs if (m_ResourcesPath.Exists(path)) { m_pLog->Log("ile %s Line %d: Illegal duplicate URL (%s) of an earlier page\n", pN->Fname(), pN->Line(), *path) ; rc = E_DUPLICATE ; } if (!m_ResourcesPath.Exists(dest)) { m_pLog->Log("ile %s Line %d: Stated destination page (%s) does not exist\n", pN->Fname(), pN->Line(), *dest) ; rc = E_DUPLICATE ; }
// Set logout path if (rc == E_OK) { m_LogoutURL = path ; m_LogoutDest = dest ; }
return rc ; }
hzEcode hdsApp::LoadPassives (void) { // Category: Page and Article Config Read Functions // // Load all passive HTML files found in the document root (recurses to sub-dirs) // // Arguments: None // // Returns: E_SYNTAX If there is a syntax error // E_OK If no errors occured
_hzfunc("hdsApp::loadPassives") ;
hzList<hzPair>::Iter lp ; // Passives iterator
hzVect <hzString> dirs ; // Needed for ListDir call hzArray <hzString> files ; // Passive files matching the criteria
ifstream is ; // For reading in file const char* i ; // Filename with/without leading slash hdsFile* pFile ; // Passive file hzChain Z ; // For storing file content hzPair p ; // File criteria and HTML type hzString S ; // Current criteria hzString path ; // Current path hzString fpath ; // Current full path (docroot + path) uint32_t n ; // File iterator hzEcode rc ; // Return code
for (lp = m_Passives ; lp.Valid() ; lp++) { p = lp.Element() ;
i = *p.name ; if (*i == CHAR_FWSLASH) i++ ; rc = FindfilesStd(files, i) ;
if (rc == E_NOTFOUND) { m_pLog->Log("WARNING: file garner: Cannot find files matching %s\n", *p.name) ; continue ; }
if (rc != E_OK) { m_pLog->Log("ERROR in file garner: Cannot utilize [%s], error=%s\n", *S, Err2Txt(rc)) ; break ; }
for (n = 0 ; n < files.Count() ; n++) { S = files[n] ; is.open(*S) ; if (is.fail()) { m_pLog->Log("WARNING: file %s cannot be opened\n", *p.name) ; continue ; } Z << is ; is.close() ; is.clear() ;
if (memcmp(*S, *m_Docroot, m_Docroot.Length())) m_pLog->Log("Please check basis for file [%s]\n", *p.name) ; else { pFile = new hdsFile() ; pFile->m_filepath = p.name ; pFile->m_Mimetype = Str2Mimetype(p.value) ;
pFile->m_rawValue = Z ; if (pFile->m_Mimetype == HMTYPE_TXT_HTML) Gzip(pFile->m_zipValue, Z) ;
m_ResourcesPath.Insert(pFile->m_filepath, pFile) ; m_pLog->Log("Added passive file %s (%d,%d)\n", *pFile->m_filepath, pFile->m_rawValue.Size(), pFile->m_zipValue.Size()) ; }
Z.Clear() ; } }
return rc ; }
hzEcode hdsApp::_readFixFile (hzXmlNode* pN) { // Category: Page and Article Config Read Functions // // Read in an <xfixfile> tag and place the content as a fixed file in the app's m_Fixed map of URLs to fixed HTML or text content // // Arguments: 1) pN Current XML node // // Returns: E_SYNTAX If there is a syntax error // E_OK If no errors occured
_hzfunc("hdsApp::_readFixFile") ;
hzAttrset ai ; // Attribute iterator hdsFile* pFix ; // Passive file uint64_t now ; // Start of zip uint64_t then ; // End of zip hzEcode rc = E_OK ; // Return code
if (!pN) Fatal("No node supplied\n") ;
if (!pN->NameEQ("xfixfile")) { m_pLog->Log("File %s Line %d Expected <xfixfile> got <%s>\n", pN->Fname(), pN->Line(), pN->txtName()) ; return E_SYNTAX ; }
pFix = new hdsFile() ;
for (ai = pN ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("url")) pFix->m_Url = ai.Value() ; else if (ai.NameEQ("title")) pFix->m_Title = ai.Value() ; else if (ai.NameEQ("path")) pFix->m_filepath = ai.Value() ; else if (ai.NameEQ("relpath")) { pFix->m_filepath = m_Docroot + "/" ; pFix->m_filepath += ai.Value() ; } else if (ai.NameEQ("mtype")) pFix->m_Mimetype = Str2Mimetype(ai.Value()) ; else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <xfixfile> Bad params (%s=%s)\n", pN->Fname(), pN->Line(), ai.Name(), ai.Value()) ; } }
// Read in content - Either by loading file or from the node content pFix->m_rawValue = pN->m_fixContent ;
if (pFix->m_rawValue.Size()) { if (pFix->m_filepath) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <xfixfile> Conflicting content\n", pN->Fname(), pN->Line()) ; } } else { // No content from node
if (!pFix->m_filepath) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <xfixfile> No content\n", pN->Fname(), pN->Line()) ; } else { // Load file ifstream is ; // Input stream
is.open(*pFix->m_filepath) ; if (is.fail()) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <xfixfile> Content file %s cannot be opened\n", pN->Fname(), pN->Line(), *pFix->m_filepath) ; } else pFix->m_rawValue << is ; is.close() ;
if (!pFix->m_rawValue.Size()) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <xfixfile> Content file %s empty\n", pN->Fname(), pN->Line(), *pFix->m_filepath) ; } } }
if (rc == E_OK) { now = RealtimeNano() ; Gzip(pFix->m_zipValue, pFix->m_rawValue) ; then = RealtimeNano() ; //m_Fixed.Insert(pFix->m_Path, pFix) ; m_ResourcesPath.Insert(pFix->m_Url, pFix) ; m_pLog->Log("Added fixed page %s (%d,%d) %u nS\n", *pFix->m_Url, pFix->m_rawValue.Size(), pFix->m_zipValue.Size(), then - now) ; }
return rc ; }
/* ** SECTION 7: Project Level Config Read Functions */
hzEcode hdsApp::_readInclFile (hzXmlNode* pN) { // Category: Project Level Config Read Functions // // Parse the content of an included config file, named in an <includeCfg> tag. // // Included config files allow application configs to be broken down into more managable sections. The set of allowed tags in an included config file, and the rules that apply // to them, are the same as in the root config file - except for the <includeCfg> tag itself. This is only allowed in the root config file, limiting included config files to a // single level. // // As the same set of tags and rules apply, the core of this function is the basically same as that of hdsApp::_readProject() which reads the root config. When a <includeCfg> // tag is encountered in the root config file, the hdsApp::_loadInclFile() function is first called to load the config to be included into a separate hzDocXml instance. Then // hdsApp::_loadInclFile() calls this function. // // As the included config is an XML document it must have a root node. In the webapp root config file this is always <webappCfg> which sets the webapp core parameters. However // within an included config file, the root node can be anything as long as it exists and is properly closed. It is otherwise redundant and is ignored. // // Arguments: 1) filepath Filepath of HTML include file // // Returns: E_ARGUMENT If no include file is supplied // E_OPENFAIL If the include file could not be loaded // E_SYNTAX If there are errors in the include // E_OK If the include was read in
_hzfunc("hdsApp::_readInclFile") ;
hzXmlNode* pN1 ; // Child node of document hzEcode rc = E_OK ; // Return code
//m_cfgErr.Clear() ;
m_pLog->Log("File %s Line %d: Reading <%s>\n", pN->Fname(), pN->Line(), pN->txtName()) ;
// Read in XML for (pN1 = pN->GetFirstChild() ; rc == E_OK && pN1 ; pN1 = pN1->Sibling()) { if (pN1->NameEQ("fldspec")) rc = _readFldspec(pN1) ; else if (pN1->NameEQ("rgxtype")) rc = _readRgxType(pN1) ; else if (pN1->NameEQ("enum")) rc = _readDataEnum(pN1) ; else if (pN1->NameEQ("class")) rc = _readClass(pN1) ; else if (pN1->NameEQ("repos")) rc = _readRepos(pN1) ; else if (pN1->NameEQ("xscript")) rc = _readScript(pN1) ; else if (pN1->NameEQ("xpage")) rc = _readPage(pN1) ; else if (pN1->NameEQ("xstyle")) rc = _readCSS(pN1) ; else if (pN1->NameEQ("xformHdl")) rc = _readFormHdl(pN1) ; else if (pN1->NameEQ("xformDef")) rc = _readFormDef(pN1) ; else if (pN1->NameEQ("xtreeDcl")) rc = _readXtreeDcl(pN1, 0) ; else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d tag <%s> unexpected\n", pN->Fname(), pN1->Line(), pN1->txtName()) ; } }
if (rc != E_OK) { m_pLog->Log("Aborted in config. Err=%s\n", Err2Txt(rc)) ; // if (m_cfgErr.Size()) // m_pLog->Log(m_cfgErr) ; }
return rc ; }
hzEcode hdsApp::_loadInclFile (const hzString& dir, const hzString& fname) { // Category: Project Level Config Read Functions // // Read in an included config file on the condition that it either has no entry in the config repository, or has a later date than the config repository entry indicates. Once // read in, the config repository is updated. // // Apply the same per-page logic as readProject() does to tags except that there will be no project wide info or further includes in an included file. // // Arguments: 1) filepath Filepath of HTML include file // // Returns: E_ARGUMENT If no include file is supplied // E_OPENFAIL If the include file could not be loaded // E_SYNTAX If there are errors in the include // E_OK If the include was read in
_hzfunc("hdsApp::_loadInclFile") ;
hzDocXml X ; // Included sub-document FSTAT fs ; // File status hzAtom atom ; // Needed for lookup hzXmlNode* pRoot ; // Root node of document hzString fpath ; // File name (without path) uint32_t fdate ; // Config file epoch date bool bLoad = false ; // Load file hzEcode rc = E_OK ; // Return code
if (!fname) { m_pLog->Log("No filename supplied\n") ; rc = E_NODATA ; }
if (!dir) fpath = m_Configdir + "/" + fname ; else fpath = dir + "/" + fname ;
if (lstat(*fpath, &fs) < 0) { m_pLog->Log("Filepath %s does not exist\n", *fpath) ; return E_NODATA ; }
// Look up config file in m_Configs // obj.Init(m_pClass_Config) ; if (m_Configs.Exists(fpath)) { fdate = m_Configs[fpath] ; if (fs.st_mtime > fdate) { // Config file has a later date bLoad = true ; } } else { // No entry yet for config file bLoad = true ; }
if (!bLoad) { m_pLog->Log("Skiping included project file [%s]\n", *fpath) ; return rc ; }
// Go ahead and load file fdate = fs.st_mtime ; m_pLog->Log("Reading included project file [%s] %u\n", *fpath, fdate) ; m_Configs.Insert(fpath, fdate) ; m_pLog->Log("m_Configs population now %d\n", m_Configs.Count()) ;
rc = X.Load(fpath) ; if (rc != E_OK) { m_pLog->Log("Could not load included project file %s. Err=%s\n", *fpath, Err2Txt(rc)) ; m_pLog->Log(X.Error()) ; return rc ; }
m_pLog->Log("Loaded included project file [%s]\n", *fpath) ;
pRoot = X.GetRoot() ; if (!pRoot) { m_pLog->Log("Could not obtain included project file root [%s]\n", *fpath) ; return E_OPENFAIL ; }
m_pLog->Log("Obtained included project file XML root\n") ;
rc = _readInclFile(pRoot) ; return rc ; }
hzEcode hdsApp::ReloadConfig (const char* cfgfile) { // Category: Project Level Config Read Functions // // In the event of a config file being changed, this function allows the config to be reloaded, thereby changing the website content without a restart. The // function is called once for each changed config file.
_hzfunc("hdsApp::reloadProject") ;
hzDocXml doc ; // XML document for reading and loading configs hzXmlNode* pRoot ; // Root node of document hzString fpath ; // Full file path of changed config file hzEcode rc = E_OK ; // Return code
fpath = m_Configdir + "/" + cfgfile ; m_pLog->Log("NOTE: Reloading Config %s\n", *fpath) ;
rc = doc.Load(fpath) ; if (rc != E_OK) { m_pLog->Log("NOTE: Config %s did not load\n", *fpath) ; m_pLog->Log(doc.Error()) ; return rc ; }
m_pLog->Log("Loaded Config %s\n", *fpath) ;
pRoot = doc.GetRoot() ; if (!pRoot) { m_pLog->Log("NOTE: Config %s Document has no root\n", *fpath) ; return E_NODATA ; }
m_pLog->Log("Parsed Config %s\n", *fpath) ; rc = _readInclFile(pRoot) ; if (rc == E_OK) m_pLog->Log("NOTE: Accepted Config %s\n", *fpath) ;
return rc ; }
/* ** Top level config read functions */
hzEcode hdsApp::CheckProject (void) { // Category: Project Level Config Read Functions // // Checks that all pages are refered to. Writes out synopsis of the application. // // Arguments: None // // Returns: E_OK In all cases
_hzfunc("hdsApp::checkProject") ;
hzList<hdsFormref*>::Iter fi ; // Forms iteration (within page)
hzChain report ; // Chain for ADP report hzChain Z ; // For building robots.txt etc hdsFldspec vd ; // Variable (in a class) hzPair p ; // For adding name/link to navbar //hdsSubject* pSubj ; // Page subject hdsResource* pRes ; // Resource hdsPage* pPage ; // Page hdsFormdef* pFormdef ; // Form hdsFormref* pFormref ; // Form reference hdsFormhdl* pFormHdl ; // Form handler hdsField* pFld ; // Field hdsNavtree* pAG ; // Article group const hdsArticle* pArt ; // Article pointer hzString S_key ; // Temp string hzString S_obj ; // Temp string uint32_t x ; // General iterator uint32_t y ; // General iterator hzEcode rc = E_OK ; // Return code
m_pLog->Log("APPLICATION REPORT: %s\n", *m_Appname) ;
if (!m_nPortSTD) { if (_hzGlobal_Dissemino) { m_nPortSTD = _hzGlobal_Dissemino->m_nCommonPortSTD ; m_pLog->Log("Inheriting HTTP port %d\n", m_nPortSTD) ; } else { rc = E_INITFAIL ; m_pLog->Log("No HTTP port specified and no overriding dissemino instance to inherit from\n") ; } }
if (!m_nPortSSL) { if (_hzGlobal_Dissemino) { m_nPortSSL = _hzGlobal_Dissemino->m_nCommonPortSSL ; m_pLog->Log("Inheriting HTTPS port %d\n", m_nPortSSL) ; } else { rc = E_INITFAIL ; m_pLog->Log("No HTTPS port specified and no overriding dissemino instance to inherit from\n") ; } }
if (rc != E_OK) return E_OK ;
m_pLog->Log("User Categories\n") ; for (x = 0 ; x < m_UserTypes.Count() ; x++) { S_key = m_UserTypes.GetKey(x) ; m_pLog->Log(" -- %s (%08x)\n", *S_key, m_UserTypes.GetObj(x)) ; } ///{ ut = m_UserTypes.GetObj(x) ; m_pLog->Log(" -- %s\n", *ut.m_Refname) ; }
m_ADP.Report(report) ; m_pLog->Log(report) ;
/* ** Forms report */
m_pLog->Log("Form Definitions\n") ; for (x = 0 ; x < m_FormDefs.Count() ; x++) { S_key = m_FormDefs.GetKey(x) ; pFormdef = m_FormDefs.GetObj(x) ;
if (pFormdef) m_pLog->Log("\t\t -- Form def %s - %s (%p)\n", *S_key, *pFormdef->m_Formname, pFormdef) ; else m_pLog->Log("\t\t -- Form def %s - NULL\n", *S_key) ; }
m_pLog->Log("Form Handlers\n") ; for (x = 0 ; x < m_FormHdls.Count() ; x++) { S_key = m_FormHdls.GetKey(x) ; pFormHdl = m_FormHdls.GetObj(x) ;
if (pFormHdl) m_pLog->Log("\t\t -- Form handler %s applied to form %p %s\n", *S_key, pFormHdl->m_pFormdef, *pFormHdl->m_pFormdef->m_Formname) ; else m_pLog->Log("\t\t -- Form handler %s not created\n", *S_key) ; }
m_pLog->Log("Form References\n") ; for (x = 0 ; x < m_FormRef2Url.Count() ; x++) { pFormref = m_FormRef2Url.GetKey(x) ; S_obj = m_FormRef2Url.GetObj(x) ;
//pFormdef = pFormref->m_pFormdef ; pFormdef = m_FormDefs[pFormref->m_Formname] ;
if (pFormdef) m_pLog->Log("\t\t -- Ref [%p] -> %p %s on %s\n", pFormref, pFormdef, *pFormdef->m_Formname, *S_obj) ; else m_pLog->Log("\t\t -- Ref [%p] -> NULL_FORM_DEF on %s\n", *S_obj) ; }
m_pLog->Log("Submission URLs to Form Handlers\n") ; for (x = 0 ; x < m_FormUrl2Hdl.Count() ; x++) { S_key = m_FormUrl2Hdl.GetKey(x) ; S_obj = m_FormUrl2Hdl.GetObj(x) ;
pFormHdl = m_FormHdls[S_obj] ; pFormref = m_FormUrl2Ref[S_obj] ;
if (!pFormHdl) m_pLog->Log("\t\t -- URL %s -> NULL (ref %p)\n", *S_key, pFormref) ; else m_pLog->Log("\t\t -- URL %s -> %s (ref %p)\n", *S_key, *pFormHdl->m_Refname, pFormref) ; }
/* ** Pages report */
m_pLog->Log("Pages (by incidence) Total %u\n", m_vecPages.Count()) ; for (x = 0 ; x < m_vecPages.Count() ; x++) { pPage = m_vecPages[x] ; m_pLog->Log(" -- access=%08x %s (%s) subj=%s\n", pPage->m_resAccess, *pPage->m_Url, *pPage->m_Title, *pPage->m_Subj) ;
if (pPage->m_Subj) { if (!m_setPgSubjects.Exists(pPage->m_Subj)) { m_setPgSubjects.Insert(pPage->m_Subj) ; m_lstPgSubjects.Add(pPage->m_Subj) ; } m_mapSubj2Res.Insert(pPage->m_Subj, pPage) ; /* pSubj = m_setPgSubjects[pPage->m_Subj] ; if (!pSubj) { pSubj = new hdsSubject() ; pSubj->subject = pPage->m_Subj ; pSubj->first = pPage->m_Url ;
m_setPgSubjects.Insert(pSubj->subject, pSubj) ; m_vecPgSubjects.Add(pSubj) ; }
pSubj->pglist.Add(pPage) ; */ }
for (fi = pPage->m_xForms ; fi.Valid() ; fi++) { pFormref = fi.Element() ; pFormdef = m_FormDefs[pFormref->m_Formname] ;
// if (!pForm->m_valJS) // pForm->WriteValidationJS() ; if (pFormdef) pPage->m_bScriptFlags |= pFormdef->m_bScriptFlags ; }
pPage->WriteValidationJS() ; }
m_pLog->Log("Pages (by name) Total %u\n", m_ResourcesName.Count()) ; //for (x = 0 ; x < m_PagesName.Count() ; x++) for (x = 0 ; x < m_ResourcesName.Count() ; x++) { pRes = m_ResourcesName.GetObj(x) ;
pPage = dynamic_cast<hdsPage*>(pRes) ; if (!pPage) continue ;
m_pLog->Log(" -- access=%08x %s (%s)\n", pPage->m_resAccess, *pPage->m_Url, *pPage->m_Title) ;
for (fi = pPage->m_xForms ; fi.Valid() ; fi++) { pFormref = fi.Element() ; pFormdef = m_FormDefs[pFormref->m_Formname] ;
if (!pFormdef) m_pLog->Log("\t -- form ref %p NULL form def\n", pFormref) ; else { m_pLog->Log("\t -- form ref %p -> %s\n", pFormref, *pFormdef->m_Formname) ; for (y = 0 ; y < pFormdef->m_vecFlds.Count() ; y++) { pFld = pFormdef->m_vecFlds[y] ; m_pLog->Log("\t\t -- fld %s\n", *pFld->m_Varname) ; } } } }
m_pLog->Log("Pages (by path) Total %u\n", m_ResourcesPath.Count()) ; //for (x = 0 ; x < m_PagesPath.Count() ; x++) for (x = 0 ; x < m_ResourcesPath.Count() ; x++) { //pRes = m_PagesPath.GetObj(x) ; pRes = m_ResourcesPath.GetObj(x) ; pPage = dynamic_cast<hdsPage*>(pRes) ; if (!pPage) continue ;
m_pLog->Log(" -- access=%08x %s (%s)\n", pPage->m_resAccess, *pPage->m_Url, *pPage->m_Title) ;
for (fi = pPage->m_xForms ; fi.Valid() ; fi++) { pFormref = fi.Element() ; pFormdef = m_FormDefs[pFormref->m_Formname] ;
if (!pFormdef) m_pLog->Log("\t -- form ref %p NULL form def\n", pFormref) ; else { m_pLog->Log("\t -- form ref %p -> %s\n", pFormref, *pFormdef->m_Formname) ; for (y = 0 ; y < pFormdef->m_vecFlds.Count() ; y++) { pFld = pFormdef->m_vecFlds[y] ; m_pLog->Log("\t\t -- fld %s\n", *pFld->m_Varname) ; } } } }
m_pLog->Log("Verifying %u Links\n", m_Links.Count()) ; for (x = 0 ; x < m_Links.Count() ; x++) { S_obj = m_Links.GetObj(x) ; pRes = m_ResourcesPath[S_obj] ;
if (!pRes) m_pLog->Log("ERROR: %u No such link as %s\n", x, *S_obj) ; else m_pLog->Log("Verified link %u %s\n", x, *S_obj) ; } m_pLog->Log("Verifying %u Links\n", m_Links.Count()) ;
m_nLoadComplete++ ;
/* ** Build Sitemap */
if (m_OpFlags & DS_APP_ROBOT) { Z.Clear() ; Z << "User-agent: *\r\nDisallow:\r\n" ; Z.Printf("Sitemap: http://%s/sitemap.xml\r\n", *m_Domain) ; Z.Printf("Sitemap: http://%s/sitemap.txt\r\n", *m_Domain) ; m_Robot = Z ;
m_rawSitemapXml << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n" "<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\" " "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " "xsi:schemaLocation=\"http://www.sitemaps.org/schemas/sitemap/0.9 " "http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd\">\r\n" ;
m_pLog->Log("Checking %u Pages\n", m_ResourcesPath.Count()) ; for (x = 0 ; x < m_ResourcesPath.Count() ; x++) { pRes = m_ResourcesPath.GetObj(x) ; pPage = dynamic_cast<hdsPage*>(pRes) ; if (!pPage) continue ;
if (!pPage->m_Subj) continue ;
if (pPage->m_Title == "Login") continue ; if (pPage->m_Title == "Logout") continue ;
m_rawSitemapTxt.Printf("http://%s%s\r\n", *m_Domain, *pPage->m_Url) ; m_rawSitemapXml.Printf("\t<url><loc>http://%s%s</loc><changefreq>daily</changefreq></url>\r\n", *m_Domain, *pPage->m_Url) ; }
m_pLog->Log("Checking %u Article Groups\n", m_ArticleGroups.Count()) ; for (y = 0 ; y < m_ArticleGroups.Count() ; y++) { pAG = m_ArticleGroups.GetObj(y) ; if (!pAG) continue ;
m_pLog->Log("Checking Article Group %s\n", *pAG->m_Groupname) ; for (x = 0 ; x < pAG->Count() ; x++) { pArt = pAG->GetItem(x) ; if (pArt) { m_pLog->Log("Exporting article link %s\n", *pArt->m_Title) ; //txtPath()) ;
m_rawSitemapTxt.Printf("http://%s%s?%s=%s\r\n", *m_Domain, *pAG->m_Hostpage, *pAG->m_Groupname, *pArt->m_Url) ; m_rawSitemapXml.Printf("\t<url><loc>http://%s%s?%s=%s</loc><changefreq>daily</changefreq></url>\r\n", *m_Domain, *pAG->m_Hostpage, *pAG->m_Groupname, *pArt->m_Url) ; } } m_pLog->Log("Checking Article Group %s\n", *pAG->m_Groupname) ; }
m_rawSitemapXml << "</urlset>\r\n" ;
Gzip(m_zipSitemapTxt, m_rawSitemapTxt) ; Gzip(m_zipSitemapXml, m_rawSitemapXml) ; }
if (m_OpFlags & DS_APP_GUIDE) { m_rawSiteguide << "<!DOCTYPE html>\n<head>\n<title>Site Guide</title>\n</head>\n<body>\n" ; m_rawSiteguide << "<p>Main Pages</p>\n" ;
for (x = 0 ; x < m_ResourcesPath.Count() ; x++) { pRes = m_ResourcesPath.GetObj(x) ; pPage = dynamic_cast<hdsPage*>(pRes) ; if (!pPage) continue ;
if (!pPage->m_Subj) continue ; m_rawSiteguide.Printf("<p><a href=\"http://%s%s\">%s</a></p>\n", *m_Domain, *pPage->m_Url, *pPage->m_Title) ; }
for (y = 0 ; y < m_ArticleGroups.Count() ; y++) { pAG = m_ArticleGroups.GetObj(y) ; if (!pAG) continue ;
m_rawSiteguide.Printf("<p>Article from %s</p>\n", *pAG->m_Groupname) ;
for (x = 0 ; x < pAG->Count() ; x++) { pArt = (hdsArticle*) pAG->GetItem(x) ; if (pArt) m_rawSiteguide.Printf("<p><a href=\"http://%s%s-%s\">%s</a></p>\n", *m_Domain, *pAG->m_Hostpage, *pArt->m_Title, *pArt->m_Title) ; } } m_rawSiteguide << "</body>\n</html>\n" ;
Gzip(m_zipSiteguide, m_rawSiteguide) ; }
/* ** Add the webmaster admin functions as CIFs */
/* if (rc == E_OK) rc = AddCIFunc(&_masterMainMenu, "/masterMainMenu", ACCESS_ADMIN, HTTP_GET) ; if (rc == E_OK) rc = AddCIFunc(&_masterCfgList, "/masterCfgList", ACCESS_ADMIN, HTTP_GET) ; if (rc == E_OK) rc = AddCIFunc(&_masterCfgEdit, "/masterCfgEdit", ACCESS_ADMIN, HTTP_POST) ; if (rc == E_OK) rc = AddCIFunc(&_masterResList, "/masterResList", ACCESS_ADMIN, HTTP_GET) ; if (rc == E_OK) rc = AddCIFunc(&_masterVisList, "/masterVisList", ACCESS_ADMIN, HTTP_GET) ; if (rc == E_OK) rc = AddCIFunc(&_masterDomain, "/masterDomain", ACCESS_ADMIN, HTTP_GET) ; if (rc == E_OK) rc = AddCIFunc(&_masterEmaddr, "/masterEmaddr", ACCESS_ADMIN, HTTP_GET) ; if (rc == E_OK) rc = AddCIFunc(&_masterStrFix, "/masterStrFix", ACCESS_ADMIN, HTTP_GET) ; if (rc == E_OK) rc = AddCIFunc(&_masterStrGen, "/masterStrGen", ACCESS_ADMIN, HTTP_GET) ; if (rc == E_OK) rc = AddCIFunc(&_masterBanned, "/masterBanned", ACCESS_ADMIN, HTTP_GET) ; if (rc == E_OK) rc = AddCIFunc(&_masterMemstat, "/masterMemstat", ACCESS_ADMIN, HTTP_GET) ; if (rc == E_OK) rc = AddCIFunc(&_masterUSL, "/masterUSL", ACCESS_ADMIN, HTTP_GET) ; if (rc == E_OK) rc = AddCIFunc(&_masterFileList, "/masterFileList", ACCESS_ADMIN, HTTP_GET) ; if (rc == E_OK) rc = AddCIFunc(&_masterFileEdit, "/masterFileEdit", ACCESS_ADMIN, HTTP_POST) ; //if (rc == E_OK) rc = AddCIFunc(&_masterDataModel, "/masterDataModel", ACCESS_ADMIN, HTTP_GET) ; if (rc == E_OK) rc = AddCIFunc(&_masterCfgRestart, "/masterCfgRestart", ACCESS_ADMIN, HTTP_GET) ; if (rc == E_OK) rc = AddCIFunc(&_masterLogout, "/masterLogout", ACCESS_ADMIN, HTTP_GET) ; */
m_pLog->Log(" -- END of REPORT --\n") ; return rc ; }
hzEcode hdsApp::ReadWebappCfg (void) { // Category: Dissemino Application Configuration // // Load a webapp config file into an XML document, then call ReadWebapp() with the root node, which is expected to be a <webappCfg> tag. // // Note this function is called only within the ReadSphere() function, which is currently only called by the Dissemino Web Engine - the only official HadronZoo program capable // of handling multiple webapps. This function could in theory be called by any HadronZoo program offering a web front end, however this is not the practice as the expectation // of a <webappCfg> root tag, precludes the use of application specific tags. // // Arguments: None // // Returns: E_ARGUMENT If no project file is supplied // E_OPENFAIL If the project file could not be loaded // E_SYNTAX If there are errors in the XML config // E_OK If the project config was read in
hzDocXml X ; // The config document hzXmlNode* pRoot ; // Config document root hzString S ; // Intermeadiate string hzEcode rc = E_OK ; // Return code
if (!m_BaseDir || !m_RootFile) return hzerr(E_NOINIT, "No project file") ;
S = m_BaseDir ; S += "/config/" ; S += m_RootFile ; m_pLog->Log("Processing Project File [%s]\n", *S) ;
rc = X.Load(*S) ; if (rc != E_OK) { m_pLog->Log(X.Error()) ; return hzerr(rc, "Could not load project file [%s]", *S) ; } m_pLog->Log("Loaded project file [%s]\n", *S) ;
pRoot = X.GetRoot() ; if (!pRoot) { hzerr(E_OPENFAIL, "Could not obtain project file root [%s]", *S) ; return E_OPENFAIL ; } m_pLog->Log("Obtained project's XML root %s\n", pRoot->txtName()) ;
rc = ReadWebapp(pRoot) ; return rc ; }
hzEcode hdsApp::ReadWebapp (hzXmlNode* pRoot) { // Category: Dissemino Application Configuration // // Process a Dissemino webapp config XML document. This function is called once the XML document has been loaded, and the root node is found to be a <webappCfg> tag. // // Arguments: None // // Returns: E_ARGUMENT If no project file is supplied // E_OPENFAIL If the project file could not be loaded // E_SYNTAX If there are errors in the XML config // E_OK If the project config was read in
_hzfunc("hdsApp::ReadWebapp") ;
hzDocXml X ; // The config document hzChain Z ; // For robot.txt etc hzAttrset ai ; // XML node attribute iterator hzXmlNode* pN ; // Current node hdbClass* pClass ; // Resource class hzPair p ; // Misc name/value pair hzString S ; // Intermeadiate string hzString appname ; // Application name hzString cookieBase ; // Cookie base name hzString basedir ; // Base dir hzDomain domain ; // Domain name hzDomain subdom ; // Domain name //uint32_t n ; // Resource counter hzEcode rc = E_OK ; // Return code
// No base dir or project file? if (!pRoot->NameEQ("webappCfg")) { m_pLog->Log("Expected root tag of <webappCfg>. Tag <%s> disallowed\n", pRoot->txtName()) ; return E_SYNTAX ; } m_pLog->Log("Obtained project's XML root %s\n", pRoot->txtName()) ;
// Get project params for (ai = pRoot ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("name")) appname = ai.Value() ; else if (ai.NameEQ("sslPvtKey")) m_SSL_PvtKey = ai.Value() ; else if (ai.NameEQ("sslCert")) m_SSL_Cert = ai.Value() ; else if (ai.NameEQ("sslCertCA")) m_SSL_CertCA = ai.Value() ; else if (ai.NameEQ("domain")) domain = ai.Value() ; else if (ai.NameEQ("subdom")) subdom = ai.Value() ; else if (ai.NameEQ("basedir")) basedir = ai.Value() ; else if (ai.NameEQ("docroot")) m_Docroot = ai.Value() ; else if (ai.NameEQ("configs")) m_Configdir = ai.Value() ; else if (ai.NameEQ("datadir")) m_Datadir = ai.Value() ; else if (ai.NameEQ("logroot")) m_Logroot = ai.Value() ; else if (ai.NameEQ("cookieName")) cookieBase = ai.Value() ; else if (ai.NameEQ("masterpath")) m_MasterPath = ai.Value() ; else if (ai.NameEQ("masteruser")) m_MasterUser = ai.Value() ; else if (ai.NameEQ("masterpass")) m_MasterPass = ai.Value() ; else if (ai.NameEQ("smtpAddr")) m_SmtpAddr = ai.Value() ; else if (ai.NameEQ("smtpUser")) m_SmtpUser = ai.Value() ; else if (ai.NameEQ("smtpPass")) m_SmtpPass = ai.Value() ; else if (ai.NameEQ("usernameFld")) m_UsernameFld = ai.Value() ; else if (ai.NameEQ("userpassFld")) m_UserpassFld = ai.Value() ; else if (ai.NameEQ("loghits")) m_AllHits = ai.Value() ; else if (ai.NameEQ("language")) m_DefaultLang = ai.Value() ; else if (ai.NameEQ("login")) m_OpFlags |= ai.ValEQ("true") ? DS_APP_SUBSCRIBERS : 0 ; else if (ai.NameEQ("robot")) m_OpFlags |= ai.ValEQ("true") ? DS_APP_ROBOT : 0 ; else if (ai.NameEQ("siteGuide")) m_OpFlags |= ai.ValEQ("true") ? DS_APP_GUIDE : 0 ; else if (ai.NameEQ("portSTD")) m_nPortSTD = ai.Value() ? atoi(ai.Value()) : 0 ; else if (ai.NameEQ("portSSL")) m_nPortSSL = ai.Value() ? atoi(ai.Value()) : 0 ; else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <webappCfg> tag: Invalid param (%s=%s)\n", pRoot->Fname(), pRoot->Line(), ai.Name(), ai.Value()) ; } }
if (basedir) { m_pLog->Log("Have basedir of %s\n", *basedir) ; if (basedir[basedir.Length()-1] != CHAR_FWSLASH) basedir += "/" ; m_pLog->Log("Have basedir of %s\n", *basedir) ;
m_Docroot = basedir + "docroot" ; m_Datadir = basedir + "data" ; m_Logroot = basedir + "logs" ; m_Configdir = basedir + "config" ; }
if (cookieBase) SetCookieName(cookieBase) ; else m_CookieName = "_hz_dissemino_" ;
if (rc == E_OK) { if (!m_Appname) { rc = E_NOINIT ; m_pLog->Log("No Project/Application name\n") ; } if (!m_Domain) { rc = E_NOINIT ; m_pLog->Log("No Project Domain\n") ; } if (!m_Docroot) { rc = E_NOINIT ; m_pLog->Log("No document root directory\n") ; } if (!m_Datadir) { rc = E_NOINIT ; m_pLog->Log("No data repos directory\n") ; } if (!m_Logroot) { rc = E_NOINIT ; m_pLog->Log("No logs root directory\n") ; } if (!m_MasterUser) { rc = E_NOINIT ; m_pLog->Log("No admin usename\n") ; } if (!m_MasterPass) { rc = E_NOINIT ; m_pLog->Log("No admin password\n") ; } if (!m_DefaultLang) { rc = E_NOINIT ; m_pLog->Log("No default language\n") ; } //if (!m_nPortSTD) { rc = E_NOINIT ; m_pLog->Log("No port specified\n") ; } }
if (rc != E_OK) return rc ;
if (!m_Configdir) m_Configdir = m_Docroot ;
// Hit recorder? if (m_AllHits) { // Set up the hits repository pClass = new hdbClass(m_ADP, HDB_CLASS_DESIG_SYS) ; pClass->InitStart(m_AllHits) ; pClass->InitMember("tdstamp", datatype_XDATE, HDB_MBR_POP_SINGLE_COMPULSORY) ; pClass->InitMember("ipaddr", datatype_IPADDR, HDB_MBR_POP_SINGLE_COMPULSORY) ; pClass->InitMember("url", datatype_STRING, HDB_MBR_POP_SINGLE_COMPULSORY) ; pClass->InitDone() ; rc = m_ADP.RegisterDataClass(pClass) ; }
// If no default language, set to en-US if (!m_pDfltLang) { m_DefaultLang = "en-US" ;
m_pDfltLang = new hdsLang() ; m_pDfltLang->m_Code = m_DefaultLang ; m_Languages.Insert(m_pDfltLang->m_Code, m_pDfltLang) ; }
// Set up the subscriber class and repository if (m_OpFlags & DS_APP_SUBSCRIBERS) { rc = m_ADP.InitSubscribers(m_Datadir) ; if (rc != E_OK) { m_pLog->Log("The subscriber cache is not found in the ADP\n") ; return E_NOINIT ; } }
// Set up the app resources database rc = InitResources() ; if (rc != E_OK) return hzerr(rc, "Resource Initialization Failed") ;
m_Images = m_Docroot + "/img" ;
// Read in XML for (pN = pRoot->GetFirstChild() ; rc == E_OK && pN ; pN = pN->Sibling()) { if (pN->NameEQ("fldspec")) rc = _readFldspec(pN) ; else if (pN->NameEQ("rgxtype")) rc = _readRgxType(pN) ; else if (pN->NameEQ("enum")) rc = _readDataEnum(pN) ; else if (pN->NameEQ("user")) rc = _readUser(pN) ; else if (pN->NameEQ("class")) rc = _readClass(pN) ; else if (pN->NameEQ("repos")) rc = _readRepos(pN) ; else if (pN->NameEQ("login")) rc = _readStdLogin(pN) ; else if (pN->NameEQ("logout")) rc = _readLogout(pN) ; else if (pN->NameEQ("xpage")) rc = _readPage(pN) ; else if (pN->NameEQ("xstyle")) rc = _readCSS(pN) ; else if (pN->NameEQ("xinclude")) rc = _readInclude(pN, 0, 0) ; else if (pN->NameEQ("xscript")) rc = _readScript(pN) ; else if (pN->NameEQ("xtreeDcl")) rc = _readXtreeDcl(pN, 0) ; else if (pN->NameEQ("xfixfile")) rc = _readFixFile(pN) ; else if (pN->NameEQ("xfixdir")) rc = _readFixDir(pN) ; else if (pN->NameEQ("xmiscdir")) rc = _readMiscDir(pN) ; else if (pN->NameEQ("siteLanguages")) rc = _readSiteLangs(pN) ; else if (pN->NameEQ("navigation")) rc = _readNav(pN) ; else if (pN->NameEQ("xformHdl")) rc = _readFormHdl(pN) ; else if (pN->NameEQ("xformDef")) rc = _readFormDef(pN) ;
else if (pN->NameEQ("includeCfg")) { // Get directory and filename for included file p.Clear() ; for (ai = pN ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("dir")) p.name = ai.Value() ; else if (ai.NameEQ("fname")) p.value = ai.Value() ; else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d Reading <include> tag: Invalid param (%s=%s)\n", pN->Fname(), pN->Line(), ai.Name(), ai.Value()) ; } }
rc = _loadInclFile(p.name, p.value) ; } else if (pN->NameEQ("passive")) { p.Clear() ; for (ai = pN ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("files")) p.name = ai.Value() ; else if (ai.NameEQ("htype")) p.value = ai.Value() ; else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d Reading <passive> tag: Invalid param (%s=%s)\n", pN->Fname(), pN->Line(), ai.Name(), ai.Value()) ; } }
if (!p.name) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <passive> No files specified\n", pN->Fname(), pN->Line()) ; } if (!p.value) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <passive> No HTML type specified\n", pN->Fname(), pN->Line()) ; }
if (rc == E_OK) m_Passives.Add(p) ; } else if (pN->NameEQ("recaptcha")) { for (ai = pN ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("public")) m_KeyPublic = ai.Value() ; else if (ai.NameEQ("private")) m_KeyPrivate = ai.Value() ; else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d Reading <recaptcha> tag: Invalid param (%s=%s)\n", pN->Fname(), pN->Line(), ai.Name(), ai.Value()) ; } }
m_pLog->Log("File %s Line %d Set Google Recaptcha keys to public %s private %s\n", pN->Fname(), pN->Line(), *m_KeyPublic, *m_KeyPrivate) ; } else { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d tag <%s> unexpected. Only the following are allowed\n", pN->Fname(), pN->Line(), pN->txtName()) ; m_pLog->Out("\tfldspec|rgxtype|enum|user|class|repos|login|logout|xpage|xstyle|xinclude|xscript|xtreeDcl|xfixfile|xfixdir|xmiscdir OR\n") ; m_pLog->Out("\tsiteLanguages|navigation|initstate|xformHdl|xformDef|includeCfg|passive|recaptcha\n") ; } }
if (rc != E_OK) { m_pLog->Log("Aborted in config. Err=%s\n", Err2Txt(rc)) ; //m_pLog->Log(m_cfgErr) ; return rc ; }
/* ** Set up the subscriber class and repository */
// If no default language, set to en-US if (!m_DefaultLang) m_DefaultLang = "en-US" ;
// Assert the document root rc = AssertDir(m_Docroot, 0777) ; if (rc != E_OK) { m_pLog->Log("Cannot assert document root %s\n", *m_Docroot) ; return E_WRITEFAIL ; }
// Assert the data directory rc = AssertDir(m_Datadir, 0777) ; if (rc != E_OK) { m_pLog->Log("Cannot assert data directory %s\n", *m_Datadir) ; return E_WRITEFAIL ; }
if (chdir(*m_Docroot) < 0) { m_pLog->Log("Cannot CD to docroot [%s]\n", *m_Docroot) ; rc = E_NOINIT ; } else m_pLog->Log("Now operating in docroot [%s]\n", *m_Docroot) ;
// if (rc == E_OK) // ImportStrings() ;
m_pLog->Log("Status=%s\n", Err2Txt(rc)) ; return rc ; }
/* ** Config Entry Point */
hzEcode hdsSphere::ReadSphere (hzXmlNode* pRoot) { // Category: Dissemino Config // // Read and process a Dissemino Sphere config XML document. // // Programs which make use of the Dissemino method to serve HTTP/S, most noteably the Dissemino Web Engine, are usually invoked with an XML config file - either supplied via a // command line argument or located at a prearranged path. The config file must be either that of a single webapp with a <webappCfg> root tag, or that of a Dissemino Sphere (a // set of one or more webapps), with a <sphereCfg> root tag. This function only processes the latter case. // // Within the <sphereCfg> tag, each webapp is declared by a <webapp> tag. Webapps are hosted internally or by proxy but in all cases, the program must be able to accept client // connections. Listening ports for the HTTP and/or HTTPS service must be specified, as must the location of any webapp specific security certificates. These parameters in the // internal case, are supplied in the webapp config file. In the by proxy case, they are supplied in the <webapp> tag. Indeed, it is the presence of a listening port attribute // in the <webapp> tag, that indicates that the webapp is by proxy. // // Note that should a multiple domain certificate apply, the files for this will be specified as attributes in the <sphereCfg> tag. // // Note also that webapps are usually in their own directory so where multiple webapps are to be hosted, the sphere file (containing the <sphereCfg> tag), should ideally be in // none of them.
_hzfunc("hdsSphere::ReadSphere") ;
hzDocXml X ; // The config document hzXmlNode* pN ; // Current node hdsApp* pApp ; // Webapp pointer hzAttrset ai ; // XML node attribute iterator hzDomain domain ; // Webapp domain name hzDomain subdom ; // ALternative way of reaching site hzString name ; // Webapp name hzString baseDir ; // Webapp base directory hzString rootFile ; // Webapp root filename hzString cookieBase ; // Cookie base is set at global level hzString pvtKey ; // Webapp private key hzString cert ; // Webapp certificate hzString certCA ; // Webapp certificate authority uint32_t nA ; // Webapp iterator uint32_t portSTD ; // HTTP port uint32_t portSSL ; // HTTPS port uint32_t bOpFlags ; // Flags for robot, index pages etc hzEcode rc = E_OK ; // Return code
InitJS_Events() ;
if (!pRoot->NameEQ("sphereCfg")) { m_pLog->Log("Expected root tag of <sphereCfg>. Tag <%s> disallowed\n", pRoot->txtName()) ; return E_SYNTAX ; }
/* ** Get sphere parameters */
for (ai = pRoot ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("name")) m_Name = ai.Value() ; else if (ai.NameEQ("basedir")) m_Basedir = ai.Value() ; else if (ai.NameEQ("logroot")) m_Logroot = ai.Value() ; else if (ai.NameEQ("sslPvtKey")) m_dfltSSL_PvtKey = ai.Value() ; else if (ai.NameEQ("sslCert")) m_dfltSSL_Cert = ai.Value() ; else if (ai.NameEQ("sslCertCA")) m_dfltSSL_CertCA = ai.Value() ; else if (ai.NameEQ("portSTD")) m_nCommonPortSTD = ai.Value() ? atoi(ai.Value()) : 0 ; else if (ai.NameEQ("portSSL")) m_nCommonPortSSL = ai.Value() ? atoi(ai.Value()) : 0 ; else { m_pLog->Log("File %s Line %d <sphereCfg> tag: Expect name|basedir|sslPvtKey|sslCert|sslCertCA|portSTD|portSSL only. Invalid param (%s=%s)\n", pRoot->Fname(), pRoot->Line(), ai.Name(), ai.Value()) ; rc = E_SYNTAX ; } }
if ((m_dfltSSL_PvtKey || m_dfltSSL_Cert || m_dfltSSL_CertCA) && !(m_dfltSSL_PvtKey && m_dfltSSL_Cert && m_dfltSSL_CertCA)) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <sphereCfg> Must set NONE or ALL SSL params\n", pRoot->Fname(), pRoot->Line()) ; }
if (rc != E_OK) return rc ;
/* ** Get initial parameters for each application */
for (pN = pRoot->GetFirstChild() ; rc == E_OK && pN ; pN = pN->Sibling()) { if (!pN->NameEQ("webapp")) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d. Expected <webapp> tag, not <%s>\n", pN->Fname(), pN->Line(), pN->txtName()) ; break ; }
bOpFlags = portSTD = portSSL = 0 ;
for (ai = pN ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("name")) name = ai.Value() ; else if (ai.NameEQ("domain")) domain = ai.Value() ; else if (ai.NameEQ("subdom")) subdom = ai.Value() ; else if (ai.NameEQ("basedir")) baseDir = ai.Value() ; else if (ai.NameEQ("rootfile")) rootFile = ai.Value() ; else if (ai.NameEQ("robot")) bOpFlags |= ai.ValEQ("true") ? DS_APP_ROBOT : 0 ; else if (ai.NameEQ("index")) bOpFlags |= ai.ValEQ("true") ? DS_APP_SITEINDEX : 0 ; else if (ai.NameEQ("login")) bOpFlags |= ai.ValEQ("true") ? DS_APP_SUBSCRIBERS : 0 ; else if (ai.NameEQ("sslPvtKey")) pvtKey = ai.Value() ; else if (ai.NameEQ("sslCert")) cert = ai.Value() ; else if (ai.NameEQ("sslCertCA")) certCA = ai.Value() ; else if (ai.NameEQ("portSTD")) portSTD = ai.Value() ? atoi(ai.Value()) : 0 ; else if (ai.NameEQ("portSSL")) portSSL = ai.Value() ? atoi(ai.Value()) : 0 ; else { m_pLog->Log("File %s Line %d <webapp> tag: Expect name|domain|basedir|rootfile|index|portSTD|portSSL only. Invalid param (%s=%s)\n", pRoot->Fname(), pRoot->Line(), ai.Name(), ai.Value()) ; rc = E_SYNTAX ; } }
// Check port settings do not conflict if (portSTD) { if (portSTD > 0xffff) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <webapp> HTTP port illegal (%u)\n", pRoot->Fname(), pRoot->Line(), portSTD) ; }
// if (m_nCommonPortSTD) // { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <webapp> HTTP port set for sphere. App setting illegal\n", pRoot->Fname(), pRoot->Line()) ; } } else { if (!m_nCommonPortSTD) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <webapp> No HTTP port set in the Sphere or the APP\n", pRoot->Fname(), pRoot->Line()) ; } }
if (portSSL) { if (portSSL > 0xffff) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <webapp> HTTP port illegal (%u)\n", pRoot->Fname(), pRoot->Line(), portSTD) ; }
// if (m_nCommonPortSSL) // { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <webapp> HTTP port set for sphere. App setting illegal\n", pRoot->Fname(), pRoot->Line()) ; } } else { if (!m_nCommonPortSSL) { rc = E_SYNTAX ; m_pLog->Log("File %s Line %d <webapp> No HTTP port set in the Sphere or the APP\n", pRoot->Fname(), pRoot->Line()) ; } }
if (rc != E_OK) break ;
rc = _hzGlobal_Dissemino->AddApplication(domain, baseDir, rootFile, pvtKey, cert, certCA, portSTD, portSSL, bOpFlags) ; if (rc == E_OK) m_pLog->Log("Added webapp %s %s %s\n", *domain, *baseDir, *rootFile) ; else m_pLog->Log("Failed to ADD webapp %s %s %s\n", *domain, *baseDir, *rootFile) ;
if (subdom) { rc = _hzGlobal_Dissemino->AddApplication(subdom, baseDir, rootFile, pvtKey, cert, certCA, portSTD, portSSL, bOpFlags) ; if (rc == E_OK) m_pLog->Log("Added webapp %s %s %s\n", *subdom, *baseDir, *rootFile) ; else m_pLog->Log("Failed to ADD webapp %s %s %s\n", *subdom, *baseDir, *rootFile) ; } }
// INIT the Apps for (nA = 1 ; rc == E_OK && nA <= _hzGlobal_Dissemino->Count() ; nA++) { pApp = _hzGlobal_Dissemino->GetApplication(nA) ;
if (pApp->m_nPortSTD || pApp->m_nPortSSL) { // These are to be hosted by proxy pApp->m_OpFlags |= DS_APP_BYPROXY ; m_pLog->Log("Webapp %s:- Hosted by proxy\n", *pApp->m_Appname) ; continue ; }
// App is to be hosted internally pApp->m_ADP.InitStandard(pApp->m_Appname) ;
if (pApp->m_OpFlags & DS_APP_SITEINDEX) pApp->m_ADP.InitSiteIndex("../data") ;
pApp->SetStdTypeValidations() ; m_pLog->Log("Webapp %s:- Standard Types created\n", *pApp->m_Appname) ;
rc = pApp->ReadWebappCfg() ; if (rc == E_OK) { pApp->SetupMasterMenu() ; m_pLog->Log("Webapp %s:- Data Model Editing initialized\n", *pApp->m_Domain) ;
rc = pApp->CheckProject() ; } }
return rc ; }