/*****************************************************************************/
/*
                                Config.c

This module performs three functions.

  1.  It reads the HTTPD configuration file, converting the directives
      into internal representations.

  2.  Provides functions, accessed by other modules, returning the
      original directive information as appropriate.

  3.  Provides HTML form-based configuration and reports.

Configuration can only be performed at server startup.  To reset the 
configuration the server must be restarted.

WASD HTTPd Configuration is a relevant subset of the CERN configuration 
directives (sort-of, well it started that way anyhow!)  Although there are
some  differences (beware!) the CERN documentation can be consulted for a
general discussion of the purpose and functioning some of these directives. 

The file formats may be IN ONE OF TWO possible formats (not mixed).  The
older format contains one directive at the start of a line, followed by a
mandatory parameter.  The newer format (in part to support forms-based
configuration) has the directive contained within square brackets (e.g.
"[accept]") followed on the same line, or by one or more lines containing
comments, containing parameter information, or empty.  The directive applies
to all lines following up until another directive (square bracket in column
one) is encountered.

DIRECTIVES
----------

  o  Accept             <host/domain>
  o  ActivityDays       <integer>
  o  AddType            <.type> <content> [rfm:] [ftp:] [</script>] [<descript>]
  o  AddMimeTypesFile   <filename>
  o  AddIcon            <URL> <alternative-text> <content-type-template>
  o  AddDefaultIcon     <URL> <alternative-text>
  o  AddDirIcon         <URL> <alternative-text>
  o  AddBlankIcon       <URL> <alternative-text>
  o  AddUnknownIcon     <URL> <alternative-text>
  o  AddParentIcon      <URL> <alternative-text>
  o  AuthBasic          DISABLED | ENABLED
  o  AuthCacheEntriesMax         <integer>
  o  AuthCacheEntrySize          <integer>
  o  AuthCacheMinutes   <integer>
  o  AuthDigest         DISABLED | ENABLED
  o  AuthDigestGetLife  <integer>
  o  AuthDigestPutLife  <integer>
  o  AuthFailureLimit   <integer>
  o  AuthFailurePeriod  <integer>
  o  AuthFailureTimeout <integer>
  o  AuthRevalidateUserMinutes   <integer>
  o  AuthSYSUAFlogonType         <keyword>
  o  AuthSYSUAFacceptExpPwd      DISABLED | ENABLED
  o  AuthSYSUAFpwdExpUrl         <string>
  o  AuthTokenEntriesMax         <integer>
  o  BufferSizeDclCgiHeader      <integer>
  o  BufferSizeDclCgiPlusIn      <integer>
  o  BufferSizeDclCommand        <integer>
  o  BufferSizeDclOutput         <integer>
  o  BufferQuotaDclOutput        <integer>
  o  BufferSizeNetFile           <integer>
  o  BufferSizeNetMTU            <integer>
  o  BufferSizeNetRead           <integer>
  o  BufferSizeNetWrite          <integer>
  o  Cache              DISABLED | ENABLED
  o  CacheEntriesMax    <integer>
  o  CacheFileKBytesMax <integer>
  o  CacheFrequentHits      <integer>
  o  CacheFrequentPeriod    <hh:mm:ss>
  o  CacheGuardPeriod       <hh:mm:ss>
  o  CacheTotalKBytesMax    <integer>
  o  CacheValidatePeriod    <hh:mm:ss>
  o  CgiStrictOutput    DISABLED | ENABLED
  o  CharsetDefault     <string>
  o  CharsetConvert     <string>
  o  ConnectMax         <integer>
  o  DclBitBucketTimeout    <hh:mm:ss>
  o  DclCgiPlusLifeTime     <hh:mm:ss>
  o  DclCleanupScratchMinutesMax      <integer>
  o  DclCleanupScratchMinutesOld      <integer>
  o  DclDetachProcess   DISABLED | ENABLED
  o  DclDetachProcessPriority         <string>
  o  DclGatewayBg       DISABLED | ENABLED
  o  DclHardLimit       <integer>
  o  DclScriptProctor   <string>
  o  DclScriptRunTime   <string>
  o  DclSoftLimit       <integer>
  o  DclSpawnAuthPriv   DISABLED | ENABLED
  o  DclZombieLifeTime      <hh:mm:ss>
  o  DECnetReuseLifeTime    <hh:mm:ss>
  o  DECnetConnectListMax   <integer>
  o  DirAccess          DISABLED | ENABLED | SELECTIVE
  o  DirBodyTag         <string>
  o  DirDescription     <integer>
  o  DirLayout          <string>
  o  DirMetaInfo        DISABLED | ENABLED
  o  DirOwner           DISABLED | ENABLED
  o  DirPreExpired      DISABLED | ENABLED
  o  DirReadMe          DISABLED | TOP | BOTTOM
  o  DirReadMeFile      <file.suffix>
  o  DirNoImpliedWildcard   DISABLED | ENABLED
  o  DirNoPrivIgnore    DISABLED | ENABLED
  o  DirWildcard        DISABLED | ENABLED
  o  DNSLookupClient    DISABLED | ENABLED
  o  DNSLookupLifeTime  <hh:mm:ss>
  o  DNSLookupRetry     <integer>
  o  EntityTag          DISABLED | ENABLED
  o  ErrorRecommend     DISABLED | ENABLED
  o  ErrorReportPath    <path-to-report>
  o  GzipAccept         <integer>
  o  GzipFlushSeconds   <integer>[,<integer>]
  o  GzipResponse       <integer>[,<integer>,<integer>]
  o  Http2Protocol      DISABLED | ENABLED
  o  Http2FrameSizeMax      <integer>
  o  Http2HeaderListMax     <integer>
  o  Http2HeaderTableMax    <integer>
  o  Http2InitWindowSize    <integer>
  o  Http2PingSeconds       <hh:mm:ss>
  o  Http2StreamsMax        <integer>
  o  HttpTrace          DISABLED | ENABLED
  o  IncludeFile        <filename>
  o  InstanceMax        <integer> | CPU
  o  InstancePassive    DISABLED | ENABLED
  o  Logging            DISABLED | ENABLED
  o  LogExcludeHosts    <string>
  o  LogFile            <string>
  o  LogFileExtend      <integer>
  o  LogFormat          <string>
  o  LogNaming          <string>
  o  LogPeriod          <string>
  o  LogPerInstance                   DISABLED | ENABLED
  o  LogPerService                    DISABLED | ENABLED
  o  LogPerServiceHostOnly            DISABLED | ENABLED
  o  LogWriteFail503                  DISABLED | ENABLED
  o  MapUserNameCacheEntries          <integer>
  o  Monitor            DISABLED | ENABLED
  o  OpcomAdmin         DISABLED | ENABLED
  o  OpcomAuthorization DISABLED | ENABLED
  o  OpcomControl       DISABLED | ENABLED
  o  OpcomProxyMaint    DISABLED | ENABLED
  o  OpcomTarget        <string>
  o  PersonaCacheEntries              <integer>
  o  PipelineRequests                 DISABLED | ENABLED
  o  Port               <integer>
  o  ProcessMax         <integer>
  o  ProxyCache                       DISABLED | ENABLED
  o  ProxyCacheDeviceCheckMinutes     <integer>
  o  ProxyCacheDeviceDirOrg           flat256 | 64x64
  o  ProxyCacheDeviceMaxPercent       <integer>
  o  ProxyCacheDevicePurgePercent     <integer>
  o  ProxyCacheFileKBytesMax          <integer>
  o  ProxyCacheNegativeSeconds        <integer>
  o  ProxyCacheNoReloadSeconds        <integer>
  o  ProxyCachePurgeList              <string>
  o  ProxyCacheReloadList             <string>
  o  ProxyCacheRoutineHourOfDay       <integer> (or empty to disabled)
  o  ProxyConnectPersistMax           <integer>
  o  ProxyConnectPersistSeconds       <integer>
  o  ProxyConnectTimeoutSeconds       <integer>
  o  ProxyForwarded                   DISABLED | BY | FOR | ADDRESS
  o  ProxyHostLookupRetryCount        <integer>
  o  ProxyReportCacheLog              DISABLED | ENABLED
  o  ProxyReportLog                   DISABLED | ENABLED
  o  ProxyServing                     DISABLED | ENABLED
  o  ProxyUnknownRequestFields        DISABLED | ENABLED
  o  ProxyVerifyRecordMax             <integer>
  o  ProxyXForwardedFor               DISABLED | ENABLED | UNKNOWN | ADDRESS
  o  PutBinaryRFM       FIX512|STM|STMCR|STMLF|UDF  (default is UDF)
  o  PutMaxKbytes       <integer>
  o  PutVersionLimit    <integer>
  o  RegEx              DISABLED | ENABLED or <keyword>
                        AWK, ED, EGREP, GREP, POSIX_AWK, POSIX_BASIC,
                        POSIX_EGREP, POSIX_EXTENDED, POSIX_MINIMAL_BASIC,
                        POSIX_MINIMAL_EXTENDED, SED, WASD
  o  Reject             <host/domain>
  o  ReportBasicOnly    DISABLED | ENABLED
  o  ReportMetaInfo     DISABLED | ENABLED
  o  RequestHistory     <integer>
  o  Scripting          DISABLED | ENABLED
  o  SearchScript       <path-to-search-script>
  o  SearchScriptExclude              <string>
  o  SecureSocket       DISABLED | ENABLED
  o  ServerAdmin        <string>
  o  ServerAdminBodyTag               <string>
  o  ServerReportBodyTag              <string>
  o  ServerSignature    DISABLED | ENABLED
  o  Service            <string>
  o  ServiceListenBacklog             <integer>
  o  ServiceNotFoundURL <string>
  o  SocketSizeRcvBuf   <integer>
  o  SocketSizeSndBuf   <integer>
  o  SSI | Shtml                      DISABLED | ENABLED
  o  SSIAccesses | ShtmlAccesses      DISABLED | ENABLED
  o  SSIExec | ShtmlExec              DISABLED | ENABLED
  o  SSISizeMax            <integer>
  o  SSLcert               <string>
  o  SSLcipherList         <string>
  o  SSLinstanceCacheMax   <integer>
  o  SSLinstanceCacheSize  <integer>
  o  SSLkey                <string>
  o  SSLoptions            <string>
  o  SSLsessionCacheMax    <integer>
  o  SSLsessionLifetime    <hh:mm:ss>
  o  SSLstrictTransSec     <integer> [<string>]
  o  SSLverifyPeer         DISABLED | ENABLED
  o  SSLverifyPeerCAFile   <string>
  o  SSLverifyPeerDataMax  <integer>
  o  SSLverifyPeerDepth    <integer>
  o  SSLversion            <string>
  o  StreamLf           <integer>
  o  TimeoutHttp2Idle   <hh:mm:ss>
  o  TimeoutInput       <hh:mm:ss>
  o  TimeoutNoProgress  <hh:mm:ss>
  o  TimeoutOutput      <hh:mm:ss>
  o  TimeoutPersistent  <hh:mm:ss>
  o  WebDAV             DISABLED | ENABLED
  o  WebDAVlocking      DISABLED | ENABLED
  o  WebDAVlockCollectionDepth          <integer>
  o  WebDAVlockTimeoutDefault           <hh:mm:ss>
  o  WebDAVlockTimeoutMax               <hh:mm:ss>
  o  WebDAVquota        DISABLED | ENABLED
  o  WebDAVmetaDir      <string>
  o  Welcome            <file.suffix>
  o  WwwImplied         DISABLED | ENABLED


VERSION HISTORY
---------------
17-MAR-2018  MGD  [BufferQuotaDclOutput] BUFQUO value for SYS$OUTPUT mailbox
05-JUN-2016  MGD  [SSLsessionLifetime] lifetime of session ticket or ID
                  [SSLverifyPeerDataMax] maximum application data buffered
09-APR-2016  MGD  [Track..] obsolete with WASD v11.0
05-AUG-2015  MGD  [Http2...] HTTP/2 configuration
                  [TimeoutHttp2Idle] <seconds>
22-FEB-2015  MGD  [SSLstrictTransSec] <string>
17-JAN-2015  MGD  ConfigLoadCallback()  StringBuffer[4096]
20-DEC-2014  MGD  bugfix; ConfigReportSecureSocket() FaoVector[32]
18-OCT-2014  MGD  [SecureSocket] and [SSL...] (overridden by /SSL=)
21-JUN-2014  MGD  [WebDAVmetaDir] (sub)directory
17-AUG-2013  MGD  [PutBinaryRFM] add STM and STMCR
                  [AddType] add RFM: keyword after content type
25-MAY-2013  MGD  [AuthRevalidateLoginCookie] deprecated
09-SEP-2012  MGD  [AuthTokenEntriesMax]
02-JAN-2011  MGD  [RegEx] enabled/disabled/<keyword>
30-OCT-2010  MGD  [WwwImplied] "Host:" www.host.name and host.name are treated
                    as equivalent (implemented by ServiceFindVirtual())
13-JUN-2010  MGD  [DclScriptProctor] and ConfigSetScriptProctor()
                    manages proactive scripting
                  ConfigSetScriptRunTime() minor rework
10-JUN-2010  MGD  bugfix; allow METACON_TOKEN_INCLUDE for [IncludeFile]
17-DEC-2009  MGD  bugfix; ConfigAcceptClientHostName() reject
11-OCT-2009  MGD  [AuthSYSUAFlogonType] sets logon source (NETWORK, etc.)
                  [BufferSizeNetFile] tailors file transfer size
                  [BufferSizeNetMTU] adjusts buffer to even number of MTUs
21-JUN-2009  MGD  [PutBinaryRFM]
09-JAN-2009  MGD  [HttpTrace]
24-NOV-2007  MGD  [AuthSYSUAFuseACME] obsolete
04-OCT-2007  MGD  [SocketSizeRcvBuf] and [SocketSizeSndBuf]
17-FEB-2007  MGD  bugfix; ConfigLoadCallback() post-process sanity checking
                    for 'NetConcurrentMax' and 'NetConcurrentProcessMax'
29-DEC-2006  MGD  WebDAV support starts with [WebDAV]
05-OCT-2006  MGD  ConfigReviseNow() ensure icon alt text contains no spaces
12-JUL-2006  MGD  [InstancePassive]
20-JUL-2005  MGD  [ProxyConnectTimeoutSeconds]
04-FEB-2005  MGD  [GzipFlushSeconds]
01-NOV-2004  MGD  [ConnectMax] (supercedes [Busy]) max concurrent connections
                  [ProcessMax] max requests concurrently being processed
16-OCT-2004  MGD  [GzipAccept] windows-bits,
                  [GzipResponse] comp-level[,mem-level,window-bits],
                  [LogWriteFail503] suspends server processing on access
                  log write failure (returns 503 service unavailable)
20-SEP-2004  MGD  [EntityTag] enables the generation of file "ETag:",
                  [PipelineRequests] enables pipeline processing
                  [ProxyCacheNegativeSeconds] for non-success responses
                  [ProxyConnectPersistMax] and [ProxyConnectPersistSeconds]
                     for controlling proxy->server connection persistence
                  [ServiceProxyTunnel] connect | firewall | raw
                  [ServiceClientSSLcert] and others allow outgoing SSL config
                  [TimeoutPersistent] supercedes [TimeoutKeepAlive]
22-MAR-2004  MGD  [AuthSYSUAFuseACME]
22-NOV-2003  MGD  [ProxyVerifyRecordMax]
15-AUG-2003  MGD  where CDATA constraints make using &#10; entity impossible
                  use a field name of hidden$lf and &#94; substituted for it
07-JUL-2003  MGD  [CacheGuardPeriod]
08-JUL-2003  MGD  [CacheChunkKBytes] obsolete
15-MAY-2003  MGD  [AuthFailurePeriod], [AuthFailureTimeout],
                  [ProxyUnknownRequestFields]
02-APR-2003  MGD  [ProxyXForwardedFor], [ProxyForwarded] supercedes
                  [ProxyAddForwardedBy] (with backward compatibility)
08-MAR-2003  MGD  ConfigAddIcon() just exit if empty string
12-OCT-2002  MGD  refine metacon reporting
10-SEP-2002  MGD  bugfix; ConfigIconFor() terminate on content-type
26-MAY-2002  MGD  [LogPerInstance]
13-MAY-2002  MGD  [AuthSysUafPwdExpUrl], [AuthSysUafAllowdExpPwd]
27-APR-2002  MGD  use sys$setprv()
11-MAR-2002  MGD  content-type include FTP transfer mode (WASD and MIME.TYPES)
10-NOV-2001  MGD  [CharsetConvert]
29-SEP-2001  MGD  instance support,
                  [AuthCacheEntriesMax], [AuthCacheEntrySize]
15-SEP-2001  MGD  meta-config,
                  [SsiSizeMax] and [ProxyCacheNoReloadSeconds]
04-AUG-2001  MGD  support module WATCHing,
                  [CacheHashTableEntries] obsolete
13-APR-2001  MGD  [DclBitBucketTimeout]
20-MAR-2001  MGD  [LogFileExtend] (DEQ blocks) see LOGGING.C same date,
                  "hh:mm:ss" for providing a more versatile period
28-FEB-2001  MGD  [AddMimeTypesFile], [AddDefaultIcon],
                  [AddType] autoscript now indicated by leading '/',
                  OdsLoadTextFile(), OdsParseTextFile(), [IncludeFile]
06-DEC-2000  MGD  [DclCleanupScratchMinutes...]
01-NOV-2000  MGD  [DclDetachProcessPriority]
02-OCT-2000  MGD  [DclDetachProcess], [PersonaCacheEntries]
01-SEP-2000  MGD  [AuthRequestPath] (pre-7.1 compatibility)
19-AUG-2000  MGD  [DclGatewayBg] to enable raw socket,
                  [DclFullRequest] removed (HTTPD_DCL_FULL_REQUEST environment
                  variable can be defined for backward compatbility)
15-JUN-2000  MGD  [ServiceListenBacklog] for TCP/IP v5.0 or greater
06-MAY-2000  MGD  reorganise configuration data structures,
                  allow continuation lines ('\') in comma lists,
                  [AuthRevalidateLoginCookie],
                  [Track...]
07-APR-2000  MGD  [ServerAdmin], [ServerSignature], [CgiStrictOutput],
                  [DirMetaInfo], [Scripting], [ReportBasicOnly] and
                  [ReportMetaInfo] (which replaces [IncludedCommentedInfo]
                  and [ErrorSourceInfo]).
04-MAR-2000  MGD  use FaolToNet(), et.al.
16-FEB-2000  MGD  [SearchScriptExclude] directive,
                  [LogPerServiceHostOnly] directive,
                  allow wildcards in content-type file suffix specifications
02-JAN-2000  MGD  [Opcom...] directives,
                  config file opened via ODS module
30-OCT-1999  MGD  include IP address for services in ConfigReportNow(),
                  'Buffer...', 'MapUserNameCacheEntries', 'ServiceNotFoundURL',
                  'Timeout...' directives (with backward compatibility),
                  increase buffer space for ConfigCommaList()
03-MAR-1999  MGD  improve [AddType] and [AddIcon] directive checking
18-JAN-1999  MGD  [Proxy...] configuration parameters
                  bugfix; ignore empty lines (even with spaces in them!)
17-OCT-1998  MGD  [ErrorReportPath] added,
                  [Search] changed to [SearchScript],
                  [StreamLfPaths] obsoleted in favour of SET mapping rule
29-SEP-1998  MGD  [AddType] now allows "text/html; charset=ISO8859-5",
                  [CharsetDefault] text and server character set
27-AUG-1998  MGD  generic ConfigSetCommaList(),
                  add [AuthRevalidateUserMinutes], [LogExcludeHosts],
                      [DECnetReuseLifeTime], [DECnetConnectListMax],
                      [StreamLfPaths]
08-AUG-1998  MGD  add [DirNoImpliedWildcard]
17-JUN-1998  MGD  add [LogNaming], [LogPerService]
28-FEB-1998  MGD  improved icon handling efficiency
07-FEB-1998  MGD  v5.0 hash table for content-type suffix and icon searches,
                  default content type (for unknowns) configurable,
                  HTTP protocol name in [service] (for SSL),
                  [DirDescription] changed from boolean to integer
05-OCT-1997  MGD  cache parameters,
                  DCL script run-time parameter,
                  additional logging parameters
09-AUG-1997  MGD  v4.4 retired "ErrorInfo", "ErrorSysAdmin" (now in messages)
                  and AuthVMS (now /SYSUAF qualifier);  introduced
                  "DirDescription", "DirNoPrivIgnore", "ErrorSourceInfo",
                  bugfix; memory leak in file-based report and revise
01-AUG-1997  MGD  v4.3 activity number of days, DCL supply full request,
                  bugfix; annoying repeated instances of "unknown" content type
01-JUN-1997  MGD  v4.2 required additional DCL/scripting parameters
01-FEB-1997  MGD  HTTPd version 4;
                  major changes for form-based config;
                  added error message URLs
01-OCT-1996  MGD  HTML configuration report
01-AUG-1996  MGD  StreamLF conversion directive;
                  AuthBasic and AuthDigest directives;
12-APR-1996  MGD  file record/binary now determined by record format
                  (has removed the need of the text/binary, etc., in "AddType")
01-DEC-1995  MGD  HTTPd version 3
27-SEP-1995  MGD  added auto-scripting funtionality
07-AUG-1995  MGD  added support for VMS-style directory listing
16-JUN-1995  MGD  file contents description in 'AddType' (also see DIR.C)
20-DEC-1994  MGD  developed for multi-threaded HTTP daemon
*/
/*****************************************************************************/

#ifdef WASD_VMS_V7
#undef _VMS__V6__SOURCE
#define _VMS__V6__SOURCE
#undef __VMS_VER
#define __VMS_VER 70000000
#undef __CRTL_VER
#define __CRTL_VER 70000000
#endif

/* standard C header files */
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* VMS related header files */
#include <opcdef.h>
#include <ssdef.h>
#include <stsdef.h>

/* application related header */
#include "wasd.h"
#include "gzip.h"

#define WASD_MODULE "CONFIG"

/******************/
/* global storage */
/******************/

CONFIG_STRUCT  Config;
CONFIG_STRUCT  *ConfigMetaPtr;

struct OpcomStruct {
   int  Number;
   char  *Name;
} ConfigOpcomTarget [] = {
   0, "none",
   OPC$M_NM_CARDS, "CARDS",
   OPC$M_NM_CENTRL, "CENTRAL",
   OPC$M_NM_CLUSTER, "CLUSTER",
   OPC$M_NM_DEVICE, "DEVICE",
   OPC$M_NM_DISKS, "DISKS",
   OPC$M_NM_NTWORK, "NETWORK",
   OPC$M_NM_PRINT, "PRINT",
   OPC$M_NM_SECURITY, "SECURITY",
   OPC$M_NM_TAPES, "TAPES",
   OPC$M_NM_OPER1, "OPER1",
   OPC$M_NM_OPER2, "OPER2",
   OPC$M_NM_OPER3, "OPER3",
   OPC$M_NM_OPER4, "OPER4",
   OPC$M_NM_OPER5, "OPER5",
   OPC$M_NM_OPER6, "OPER6",
   OPC$M_NM_OPER7, "OPER7",
   OPC$M_NM_OPER8, "OPER8",
   OPC$M_NM_OPER9, "OPER9",
   OPC$M_NM_OPER10, "OPER10",
   OPC$M_NM_OPER11, "OPER11",
   OPC$M_NM_OPER12, "OPER12",
   -1, NULL
};

int  ConfigDnsLookupRetryCount;

#define CONFIG_NOTE_NONE "<i>(none)</i>"

char  ConfigContentTypeBlank [] = "x-internal/blank",
      ConfigContentTypeDefaultIcon [] = "x-internal/default-icon",
      ConfigContentTypeDir [] = "x-internal/directory",
      ConfigContentTypeParent [] = "x-internal/parent",
      ConfigContentTypeSsi [] = "text/x-shtml",
      ConfigContentTypeUnknown [] = "x-internal/unknown",
      ConfigContentTypeUrl [] = "x-internal/url",
      ConfigNoteDefault [] = " <i>(default)</i>",
      ConfigNoteNone [] = " <i>(none)</i>",
      ConfigNoteSystem [] = " <i>(system)</i>",
      ConfigDefaultFileContentType [] = "application/octet-stream",
      ConfigStringOverflow [] = "*ERROR* string overflow";

char  *ConfigBlankIconPtr,
      *ConfigDirIconPtr,
      *ConfigDefaultIconPtr,
      *ConfigParentIconPtr,
      *ConfigUnknownIconPtr;

/********************/
/* external storage */
/********************/

extern BOOL  DclProctorEnabled,
             HttpdServerStartup,
             NetInstancePassive,
             ProtocolHttpsAvailable;

extern int  AuthFailureLimit,
            AuthFailurePeriodSeconds,
            AuthFailureTimeoutSeconds,
            DclCgiHeaderSize,
            DclCgiPlusInSize,
            DclSysCommandSize,
            DclSysOutputSize,
            DclSysOutputQuota,
            NetConcurrentMax,
            NetConcurrentProcessMax,
            MapUrlUserNameCacheEntries,
            NetReadBufferSize,
            OpcomMessages,
            OpcomTarget,
            OutputBufferSize,
            OutputFileBufferSize,
            PersonaCacheEntries,
            ServiceLoadFromConfigFile,
            SsiSizeMax,
            TcpIpSocketRcvBufSize,
            TcpIpSocketSndBufSize;

extern int  ToLowerCase[],
            ToUpperCase[];

extern unsigned long  SysPrvMask[];

extern char  *CliAcceptHostsPtr,
             *CliRejectHostsPtr;

extern char  SesolaAvailableVersions[],
             SoftwareID[],
             TimeGmtString[];

extern HTTPD_PROCESS  HttpdProcess;
extern MSG_STRUCT  Msgs;
extern META_CONFIG  *MetaGlobalConfigPtr;
extern WATCH_STRUCT  Watch;

/*****************************************************************************/
/*
*/ 
 
int ConfigLoad (META_CONFIG **MetaConPtrPtr)

{
   int  status;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (WATCHALL, WATCH_MOD_CONFIG, "ConfigLoad()");

   status = MetaConLoad (MetaConPtrPtr,
                         v10orPrev10(CONFIG_FILE_NAME,-1),
                         &ConfigLoadCallback, true, false);
   if (*MetaConPtrPtr == MetaGlobalConfigPtr)
   {
      /* server startup */
      MetaConStartupReport (MetaGlobalConfigPtr, "CONFIG");
      if (VMSnok (status)) exit (status);
   }
   return (status);
}

/*****************************************************************************/
/*
Called by MetaConUnload() to free resources allocated during service
configuration.
*/ 
 
ConfigUnload (META_CONFIG *mcptr)

{
   int  status;
   MAPPING_META  *mmptr;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (WATCHALL, WATCH_MOD_CONFIG, "ConfigUnload()");

   if (mcptr->ConfigMetaPtr &&
       mcptr->ConfigMetaPtr != ConfigMetaPtr)
   {
      VmFree (mcptr->ConfigMetaPtr, FI_LI);
      mcptr->ConfigMetaPtr = NULL;
   }
}

/*****************************************************************************/
/*
For each non-meta-config directive line read by MetaConLoad() this function is
called to parse the line text's contents and to configure the private data
structure associated with each rule.
*/

BOOL ConfigLoadCallback (META_CONFIG *mcptr)

{
   static char  ProblemMixed [] = "Mixed directive formats",
                ProblemObsolete [] = "Directive is obsolete",
                ProblemOverflow [] = "Storage overflow",
                ProblemParameter [] = "Parameter confusing",
                ProblemDirective [] = "Unknown directive",
                ProblemUsage [] = "Cannot use during global configuration";

   int  idx, status,
        ProctorTotal;
   char  *cptr, *sptr, *zptr;
   char  StringBuffer [4096];
   CONFIG_STRUCT  *cfptr;
   METACON_LINE  *mclptr;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
   {
      WatchThis (WATCHALL, WATCH_MOD_CONFIG,
                 "ConfigLoadCallback() !&F !&X", &ConfigLoadCallback, mcptr);
      if (WATCH_MODULE(WATCH_MOD__DETAIL))
      {
         mclptr = mcptr->ParsePtr;
         WatchDataFormatted ("!&X !UL !UL !UL !UL !&X !&Z !&Z\n",
            mclptr, mclptr->Size, mclptr->Token, mclptr->Number,
            mclptr->Length, mclptr->LineDataPtr, mclptr->TextPtr,
            mclptr->InlineTextPtr);
      }
   }

   /* get a pointer to the current "line" */
   mclptr = mcptr->ParsePtr;

   /* if this is during server startup then set the global service pointer */
   if (HttpdServerStartup)
      cfptr = mcptr->ConfigMetaPtr = ConfigMetaPtr = &Config;
   else
   /* if a report then conjure one up ex cathedra */
   if (!mcptr->ConfigMetaPtr)
      cfptr = mcptr->ConfigMetaPtr = VmGet (sizeof(CONFIG_STRUCT));
   else
      /* not the first time through */
      cfptr = mcptr->ConfigMetaPtr;

   if (mclptr->Token == METACON_TOKEN_PRE)
   {
      /******************/
      /* pre-initialize */
      /******************/

      /* must be explicitly enabled in the configuration file */
      cfptr->cfHttp2.Enabled = false;

      cfptr->cfMisc.EntityTag =
         cfptr->cfMisc.PipelineRequests =
         cfptr->cfScript.Enabled = true;

      cfptr->BracketDirectives =
         cfptr->EquateDirectives = false;

      cfptr->cfAuth.CacheMinutes =
         cfptr->cfAuth.RevalidateUserMinutes = 60;

      cfptr->cfMisc.GzipFlushSeconds = GZIP_DEFAULT_FLUSH_SECONDS;
      cfptr->cfMisc.GzipFlushInitialSeconds = GZIP_INITIAL_FLUSH_SECONDS;
      cfptr->cfDir.PreExpired = PRE_EXPIRE_INDEX_OF;
      strcpy (cfptr->cfDir.DefaultLayout, DEFAULT_DIR_LAYOUT);

      cfptr->cfServer.AcceptHostsPtr =
         cfptr->cfContent.ContentInfoListHeadPtr =
         cfptr->cfContent.IconListHeadPtr =
         cfptr->cfLog.ExcludeHostsPtr =
         cfptr->cfServer.RejectHostsPtr = NULL;

      cfptr->cfContent.ContentTypeStructOverhead = sizeof(CONTENT_TYPE);
      cfptr->cfContent.IconStructOverhead = sizeof(ICON_TYPE);
      cfptr->cfContent.ContentTypeDefaultPtr = "";
      cfptr->cfProxy.ConnectPersistMax = PROXY_CONNECT_PERSIST_MAX;
      cfptr->cfProxy.ConnectPersistSeconds = PROXY_CONNECT_PERSIST_SECONDS;
      cfptr->cfProxy.CacheNegativeSeconds = PROXY_CACHE_NEGATIVE_SECONDS;

      return (true);
   }

   if (mclptr->Token == METACON_TOKEN_POST)
   {
      /****************/
      /* post-process */
      /****************/

      if (!cfptr->cfMisc.PutMaxKbytes)
         cfptr->cfMisc.PutMaxKbytes = PUT_DEFAULT_KBYTES_MAX;
      if (!cfptr->cfMisc.PutVersionLimit)
         cfptr->cfMisc.PutVersionLimit = PUT_DEFAULT_VERSION_LIMIT;

      if (cfptr->cfAuth.CacheMinutes > CONFIG_REVALIDATE_MINUTES_MAX)
         cfptr->cfAuth.CacheMinutes = CONFIG_REVALIDATE_MINUTES_MAX;

      if (cfptr->cfAuth.RevalidateUserMinutes >
          CONFIG_REVALIDATE_MINUTES_MAX)
          cfptr->cfAuth.RevalidateUserMinutes =
             CONFIG_REVALIDATE_MINUTES_MAX;

      if (CliAcceptHostsPtr)
         cfptr->cfServer.AcceptHostsPtr = CliAcceptHostsPtr;

      if (CliRejectHostsPtr)
         cfptr->cfServer.RejectHostsPtr = CliRejectHostsPtr;

      /* push these to all upper case (just cause it looks uniform) */
      if (cfptr->cfScript.DefaultSearchExcludePtr)
         for (cptr = cfptr->cfScript.DefaultSearchExcludePtr; *cptr; cptr++)
            *cptr = TOUP(*cptr);

      ConfigContentTypeIcon (mcptr);

      if (!cfptr->cfDir.BodyTag[0])
         strcpy (cfptr->cfDir.BodyTag, CONFIG_DEFAULT_DIR_BODY_TAG);

      if (cfptr->cfServer.ListenBacklog <= 0 ||
          cfptr->cfServer.ListenBacklog > 999)
         cfptr->cfServer.ListenBacklog = DEFAULT_LISTEN_BACKLOG;

      /* for backward compatibility with pre-v4.3 behaviour (see DCL.C) */
      if (getenv ("HTTPD_DCL_FULL_REQUEST"))
         cfptr->cfScript.FullRequest = true;

      ProctorTotal = 0;
      for (idx = 0; idx < cfptr->cfScript.ProctorCount; idx++)
      {
         ProctorTotal += cfptr->cfScript.Proctor[idx].NumberMin;
         ProctorTotal += cfptr->cfScript.Proctor[idx].NumberIdle;
      }
      if (ProctorTotal > cfptr->cfScript.ScriptProcessSoftLimit ||
          ProctorTotal > cfptr->cfScript.ScriptProcessHardLimit)
         MetaConReport (mcptr, METACON_REPORT_ERROR,
             "Total proctored exceeds DCL soft/hard-limit - DISABLED");

      if (HttpdServerStartup)
      {
         /*************************/
         /* during server startup */
         /*************************/

         if (Config.cfServer.ConnectMax)
            NetConcurrentMax = Config.cfServer.ConnectMax;
         if (NetConcurrentMax <= 0)
            NetConcurrentMax = DEFAULT_CONCURRENT_CONNECT_MAX;

         if (Config.cfServer.ProcessMax)
            NetConcurrentProcessMax = Config.cfServer.ProcessMax;
         if (NetConcurrentProcessMax <= 0)
            NetConcurrentProcessMax = DEFAULT_CONCURRENT_PROCESS_MAX;

         if (OpcomTarget = Config.cfOpcom.Target)
            OpcomMessages = Config.cfOpcom.Messages;
         else
            OpcomMessages = 0;

         /* command line overrides configuration, default fallbacks */
         if (!NetReadBufferSize)
            NetReadBufferSize = Config.cfBuffer.SizeNetRead;
         if (!NetReadBufferSize)
            NetReadBufferSize = DEFAULT_NET_READ_BUFFER_SIZE;
         if (NetReadBufferSize < 1024)
            NetReadBufferSize = DEFAULT_NET_READ_BUFFER_SIZE;

         if (!OutputBufferSize)
            OutputBufferSize = Config.cfBuffer.SizeNetWrite;
         if (!OutputBufferSize)
            OutputBufferSize = DEFAULT_OUTPUT_BUFFER_SIZE;
         if (Config.cfBuffer.SizeNetMTU)
         {
            /* MTU has been specified, adjust to an even number of MTUs */
            OutputBufferSize /= Config.cfBuffer.SizeNetMTU;
            OutputBufferSize++;
            OutputBufferSize *= Config.cfBuffer.SizeNetMTU;
            /*
               Chunked output is so common allow for the overhead.
               The trade-off is losing 8 bytes from non-chunked MTU.
            */
            if (OutputBufferSize > 8) OutputBufferSize -= 8;
         }
         /* let's not get too silly */
         if (OutputBufferSize < 1024)
            OutputBufferSize = DEFAULT_OUTPUT_BUFFER_SIZE;

         if (!OutputFileBufferSize)
            OutputFileBufferSize = Config.cfBuffer.SizeNetFile;
         if (!OutputFileBufferSize)
            OutputFileBufferSize = OutputBufferSize;
         if (Config.cfBuffer.SizeNetMTU)
         {
            /*
               MTU has been specified, adjust to an even number of MTUs.
               File buffers are rounded down to 512 byte blocks - maximise!
            */
            while (OutputFileBufferSize % Config.cfBuffer.SizeNetMTU > 512)
               OutputFileBufferSize += 512; 
            OutputFileBufferSize /= Config.cfBuffer.SizeNetMTU;
            OutputFileBufferSize *= Config.cfBuffer.SizeNetMTU;
         }
         /* again, let reason prevail */
         if (OutputFileBufferSize < 1024)
            OutputFileBufferSize = OutputBufferSize;

         TcpIpSocketRcvBufSize = Config.cfBuffer.SizeSocketRcvBuf;
         TcpIpSocketSndBufSize = Config.cfBuffer.SizeSocketSndBuf;

         SsiSizeMax = cfptr->cfSsi.SizeMax * 1024;
         if (!SsiSizeMax) SsiSizeMax = FILE_TYPE_SSI_SIZE_MAX;

         if (Config.cfContent.CharsetConvertPtr)
            ResponseCharsetConfig (mcptr);

         if (Config.cfMisc.DnsLookupRetryCount)
            ConfigDnsLookupRetryCount = Config.cfMisc.DnsLookupRetryCount;
         else
            ConfigDnsLookupRetryCount = TCPIP_LOOKUP_RETRY_COUNT;
         if (ConfigDnsLookupRetryCount < 0 || ConfigDnsLookupRetryCount > 100)
            ConfigDnsLookupRetryCount = TCPIP_LOOKUP_RETRY_COUNT;

         if (ProctorTotal <= cfptr->cfScript.ScriptProcessSoftLimit &&
             ProctorTotal <= cfptr->cfScript.ScriptProcessHardLimit)
            DclProctorEnabled = true;
      }

      return (true);
   }

   if (mclptr->Token == METACON_TOKEN_INCLUDE) return (true);

   if (mclptr->Token == METACON_TOKEN_VERSION) return (true);

   if (mclptr->Token != METACON_TOKEN_TEXT)
   {
      /* only interested in directive text */
      MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemUsage);
      return (true);
   }

   /***********/
   /* process */
   /***********/

   /* buffer the text associated with the current "line" */
   zptr = (sptr = StringBuffer) + sizeof(StringBuffer);
   cptr = mclptr->TextPtr;
   while (*cptr && sptr < zptr) *sptr++ = *cptr++;
   if (sptr >= zptr)
   {
      MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemOverflow);
      return (false);
   }
   *sptr = '\0';
   cptr = StringBuffer;

   while (*cptr && ISLWS(*cptr)) cptr++;
   if (*cptr == '[')
   {
      if (cfptr->EquateDirectives)
      {
         MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemMixed);
         return (false);
      }
      cfptr->BracketDirectives = true;
      cptr++;
      zptr = (sptr = cfptr->DirectiveName) + sizeof(cfptr->DirectiveName)-1;
      while (*cptr && *cptr != ']' && sptr < zptr) *sptr++ = *cptr++;
      if (sptr > zptr)
      {
         MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemOverflow);
         return (false);
      }
      *sptr = '\0';
      if (*cptr) cptr++;
      while (*cptr && ISLWS(*cptr)) cptr++;
   }
   else
   if (!cfptr->BracketDirectives)
   {
      cfptr->EquateDirectives = true;
      zptr = (sptr = cfptr->DirectiveName) + sizeof(cfptr->DirectiveName)-1;
      while (*cptr && !ISLWS(*cptr) && *cptr != '=' && sptr < zptr)
         *sptr++ = *cptr++;
      while (*cptr && *cptr != '=') cptr++;
      if (sptr > zptr)
      {
         MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemOverflow);
         return (false);
      }
      *sptr = '\0';
      if (*cptr) cptr++;
      while (*cptr && ISLWS(*cptr)) cptr++;
   }
   sptr = cptr;
   cptr = cfptr->DirectiveName; 
   if (cfptr->BracketDirectives && !*sptr) return (true);
   if (!*sptr)
   {
      MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemParameter);
      return (true);
   }

   /**************/
   /* directives */
   /**************/

   if (strsame (cptr, "Accept", -1))
      StringListAdd (sptr, &cfptr->cfServer.AcceptHostsPtr,
                           &cfptr->cfServer.AcceptHostsLength);
   else
   if (strsame (cptr, "ActivityDays", -1))
      cfptr->cfMisc.ActivityNumberOfDays = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "AddType", -1))
      ConfigAddType (mcptr, sptr);
   else
   if (strsame (cptr, "AddMimeTypesFile", -1))
      ConfigAddMimeTypesFile (mcptr, sptr);
   else
   if (strsame (cptr, "AddIcon", -1))
      ConfigAddIcon (mcptr, sptr, NULL, false);
   else
   if (strsame (cptr, "AddBlankIcon", -1))
      ConfigAddIcon (mcptr, sptr, ConfigContentTypeBlank, false);
   else
   if (strsame (cptr, "AddDirIcon", -1))
      ConfigAddIcon (mcptr, sptr, ConfigContentTypeDir, false);
   else
   if (strsame (cptr, "AddDefaultIcon", -1))
      ConfigAddIcon (mcptr, sptr, ConfigContentTypeDefaultIcon, false);
   else
   if (strsame (cptr, "AddParentIcon", -1))
      ConfigAddIcon (mcptr, sptr, ConfigContentTypeParent, false);
   else
   if (strsame (cptr, "AddUnknownIcon", -1))
      ConfigAddIcon (mcptr, sptr, ConfigContentTypeUnknown, false);
   else
   if (strsame (cptr, "AuthBasic", -1))
      cfptr->cfAuth.BasicEnabled = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "AuthCacheEntriesMax", -1))
      cfptr->cfAuth.CacheEntriesMax = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "AuthCacheEntrySize", -1))
      cfptr->cfAuth.CacheEntrySize = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "AuthCacheMinutes", -1))
      cfptr->cfAuth.CacheMinutes = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "AuthDigestGetLife", -1))
      cfptr->cfAuth.DigestNonceGetLifeTime = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "AuthDigestPutLife", -1))
      cfptr->cfAuth.DigestNoncePutLifeTime = MetaConSetInteger (mcptr, sptr);
   else
   /* "AuthDigest" MUST come after other AuthDigests for obvious reasons */
   if (strsame (cptr, "AuthDigest", -1))
      cfptr->cfAuth.DigestEnabled = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "AuthFailureLimit", -1))
      cfptr->cfAuth.FailureLimit = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "AuthFailurePeriod", -1))
      cfptr->cfAuth.FailurePeriodSeconds = MetaConSetSeconds (mcptr, sptr, 1);
   else
   if (strsame (cptr, "AuthFailureTimeout", -1))
      cfptr->cfAuth.FailureTimeoutSeconds = MetaConSetSeconds (mcptr, sptr, 1);
   else
   if (strsame (cptr, "AuthRevalidateUserMinutes", -1))
      cfptr->cfAuth.RevalidateUserMinutes = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "AuthRevalidateLoginCookie", -1))
      MetaConReport (mcptr, METACON_REPORT_INFORM, ProblemObsolete);
   else
   if (strsame (cptr, "AuthSYSUAFlogonType", -1))
   {
      if (strsame (sptr, "NETWORK", -1))
         cfptr->cfAuth.SysUafLogonType = AUTH_LOGON_TYPE_NETWORK;
      else
      if (strsame (sptr, "BATCH", -1))
         cfptr->cfAuth.SysUafLogonType = AUTH_LOGON_TYPE_BATCH;
      else
      if (strsame (sptr, "LOCAL", -1))
         cfptr->cfAuth.SysUafLogonType = AUTH_LOGON_TYPE_LOCAL;
      else
      if (strsame (sptr, "DIALUP", -1))
         cfptr->cfAuth.SysUafLogonType = AUTH_LOGON_TYPE_DIALUP;
      else
      if (strsame (sptr, "REMOTE", -1))
         cfptr->cfAuth.SysUafLogonType = AUTH_LOGON_TYPE_REMOTE;
      else
      {
         cfptr->cfAuth.SysUafLogonType = 0;
         MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemParameter);
      }
   }
   else
   if (strsame (cptr, "AuthSYSUAFacceptExpPwd", -1))
      cfptr->cfAuth.SysUafAcceptExpPwd = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "AuthSYSUAFpwdExpUrl", -1))
      MetaConSetString (mcptr, sptr, cfptr->cfAuth.SysUafPwdExpUrl,
                                     sizeof(cfptr->cfAuth.SysUafPwdExpUrl));
   else
   if (strsame (cptr, "AuthSYSUAFuseACME", -1))
      MetaConReport (mcptr, METACON_REPORT_INFORM, ProblemObsolete);
   else
   if (strsame (cptr, "AuthTokenEntriesMax", -1))
      cfptr->cfAuth.TokenEntriesMax = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "BufferQuotaDclOutput", -1))
      cfptr->cfBuffer.QuotaDclOutput = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "BufferSizeDclCommand", -1))
      cfptr->cfBuffer.SizeDclCommand = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "BufferSizeDclOutput", -1))
      cfptr->cfBuffer.SizeDclOutput = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "BufferSizeDclCgiHeader", -1))
      cfptr->cfBuffer.SizeDclCgiHeader = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "BufferSizeDclCgiPlusIn", -1))
      cfptr->cfBuffer.SizeDclCgiPlusIn = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "BufferSizeNetFile", -1))
      cfptr->cfBuffer.SizeNetFile = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "BufferSizeNetMTU", -1))
      cfptr->cfBuffer.SizeNetMTU = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "BufferSizeNetRead", -1))
      cfptr->cfBuffer.SizeNetRead = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "BufferSizeNetWrite", -1))
      cfptr->cfBuffer.SizeNetWrite = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "CacheChunkKBytes", -1))
      MetaConReport (mcptr, METACON_REPORT_INFORM, ProblemObsolete);
   else
   if (strsame (cptr, "CacheEntriesMax", -1))
      cfptr->cfCache.EntriesMax = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "CacheFileKBytesMax", -1))
      cfptr->cfCache.FileKBytesMax = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "CacheFrequentHits", -1))
      cfptr->cfCache.FrequentHits = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "CacheFrequentPeriod", -1))
      cfptr->cfCache.FrequentSeconds = MetaConSetSeconds (mcptr, sptr, 1);
   else
   /* "CacheFrequentSeconds" for backward compatibility */
   if (strsame (cptr, "CacheFrequentSeconds", -1))
      cfptr->cfCache.FrequentSeconds = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "CacheGuardPeriod", -1))
      cfptr->cfCache.GuardSeconds = MetaConSetSeconds (mcptr, sptr, 1);
   else
   if (strsame (cptr, "CacheTotalKBytesMax", -1))
      cfptr->cfCache.TotalKBytesMax = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "CacheValidatePeriod", -1))
      cfptr->cfCache.ValidateSeconds = MetaConSetSeconds (mcptr, sptr, 1);
   else
   /* "CacheValidateSeconds" for backward compatibility */
   if (strsame (cptr, "CacheValidateSeconds", -1))
      cfptr->cfCache.ValidateSeconds = MetaConSetInteger (mcptr, sptr);
   else
   /* "cache" must follow all the others for the obvious reason */
   if (strsame (cptr, "Cache", -1))
      cfptr->cfCache.Enabled = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "CgiStrictOutput", -1))
      cfptr->cfScript.CgiStrictOutput = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "CharsetDefault", -1))
      MetaConSetString (mcptr, sptr, cfptr->cfContent.CharsetDefault,
                                     sizeof(cfptr->cfContent.CharsetDefault));
   else
   if (strsame (cptr, "CharsetConvert", -1))
      StringListAdd (sptr, &cfptr->cfContent.CharsetConvertPtr,
                           &cfptr->cfContent.CharsetConvertLength);
   else
   /* "Busy" for backward compatibility */
   if (strsame (cptr, "ConnectMax", -1) ||
       strsame (cptr, "Busy", -1))
      cfptr->cfServer.ConnectMax = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "DclDetachProcess", -1))
      cfptr->cfScript.DetachProcess = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "DclDetachProcessPriority", -1))
      MetaConSetString (mcptr, sptr, cfptr->cfScript.DetachProcessPriority,
                               sizeof(cfptr->cfScript.DetachProcessPriority));
   else
   if (strsame (cptr, "DclGatewayBg", -1))
      cfptr->cfScript.GatewayBg = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "DclHardLimit", -1))
      cfptr->cfScript.ScriptProcessHardLimit =
         MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "DclScriptProctor", -1))
      ConfigSetScriptProctor (mcptr, sptr);
   else
   if (strsame (cptr, "DclScriptRunTime", -1))
      ConfigSetScriptRunTime (mcptr, sptr);
   else
   if (strsame (cptr, "DclSoftLimit", -1))
      cfptr->cfScript.ScriptProcessSoftLimit = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "DclBitBucketTimeout", -1))
      cfptr->cfScript.BitBucketTimeout = MetaConSetSeconds (mcptr, sptr, 60);
   else
   if (strsame (cptr, "DclCgiPlusLifeTime", -1))
      cfptr->cfScript.CgiPlusLifeTime = MetaConSetSeconds (mcptr, sptr, 60);
   else
   if (strsame (cptr, "DclCleanupScratchMinutesMax", -1))
      cfptr->cfScript.CleanupScratchMinutesMax =
         MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "DclCleanupScratchMinutesOld", -1))
      cfptr->cfScript.CleanupScratchMinutesOld =
         MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "DclZombieLifeTime", -1))
      cfptr->cfScript.ZombieLifeTime = MetaConSetSeconds (mcptr, sptr, 60);
   else
   if (strsame (cptr, "DclSpawnAuthPriv", -1))
      cfptr->cfScript.SpawnAuthPriv = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "DECnetReuseLifeTime", -1))
      cfptr->cfScript.DECnetReuseLifeTime = MetaConSetSeconds (mcptr, sptr, 60);
   else
   if (strsame (cptr, "DECnetConnectListMax", -1))
      cfptr->cfScript.DECnetConnectListMax = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "DirAccess", -1))
      ConfigSetDirAccess (mcptr, sptr);
   else
   if (strsame (cptr, "DirBodyTag", -1))
      MetaConSetString (mcptr, sptr,
                        cfptr->cfDir.BodyTag, sizeof(cfptr->cfDir.BodyTag));
   else
   if (strsame (cptr, "DirDescription", -1))
   {
      /*
         [DirDescription] boolean deprecated in v5.0, noow using
         integer [DirDescriptionLines], provide fallback behaviour.
      */
      if (MetaConSetBoolean (mcptr, sptr))
         cfptr->cfDir.DescriptionLines = 30;
      else
         cfptr->cfDir.DescriptionLines = 0;
   }
   else
   if (strsame (cptr, "DirDescriptionLines", -1))
      cfptr->cfDir.DescriptionLines = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "DirLayout", -1))
      MetaConSetString (mcptr, sptr,
                        cfptr->cfDir.DefaultLayout,
                        sizeof(cfptr->cfDir.DefaultLayout));
   else
   if (strsame (cptr, "DirMetaInfo", -1))
      cfptr->cfDir.MetaInfoEnabled = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "DirOwner", -1))
      cfptr->cfDir.OwnerEnabled = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "DirPreExpired", -1))
      cfptr->cfDir.PreExpired = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "DirNoImpliedWildcard", -1))
      cfptr->cfDir.NoImpliedWildcard = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "DirNoPrivIgnore", -1))
      cfptr->cfDir.NoPrivIgnore = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "DirReadMeFile", -1))
      ConfigSetDirReadMeFile (mcptr, sptr);
   else
   /* "ReadMe" MUST come after the other ReadMes for obvious reasons */
   if (strsame (cptr, "DirReadMe", -1))
      ConfigSetDirReadMe (mcptr, sptr);
   else
   if (strsame (cptr, "DirWildcard", -1))
      cfptr->cfDir.WildcardEnabled = MetaConSetBoolean (mcptr, sptr);
   else
   /* "DNSLookup" for backward compatibility */
   if (strsame (cptr, "DNSLookupClient", -1) ||
       strsame (cptr, "DNSLookup", -1))
      cfptr->cfMisc.DnsLookupClient = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "DNSLookupRetry", -1))
      cfptr->cfMisc.DnsLookupRetryCount = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "DNSLookupLifeTime", -1))
      cfptr->cfMisc.DnsLookupLifeTimeSeconds =
         MetaConSetSeconds (mcptr, sptr, 1);
   else
   if (strsame (cptr, "EntityTag", -1))
      cfptr->cfMisc.EntityTag = MetaConSetBoolean (mcptr, sptr);
   else
   /* "Recommend" for backward compatibility */
   if (strsame (cptr, "ErrorRecommend", -1) ||
       strsame (cptr, "Recommend", -1))
      cfptr->cfReport.ErrorRecommend = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "ErrorReportPath", -1))
   {
      MetaConSetString (mcptr, sptr,
                        cfptr->cfReport.ErrorReportPath,
                        sizeof(cfptr->cfReport.ErrorReportPath));
      cfptr->cfReport.ErrorReportPathLength =
         strlen(cfptr->cfReport.ErrorReportPath);
   }
   else
   if (strsame (cptr, "GzipAccept", -1))
      cfptr->cfMisc.GzipAcceptWindowBits = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "GzipFlushSeconds", -1))
   {
      /* <interval>[,<initial-interval>] */
      cfptr->cfMisc.GzipFlushSeconds = MetaConSetInteger (mcptr, sptr);
      while (*sptr && isdigit(*sptr)) sptr++;
      while (*sptr && (*sptr == ',' || ISLWS(*sptr))) sptr++;
      if (isdigit(*sptr))
         cfptr->cfMisc.GzipFlushInitialSeconds =
            MetaConSetInteger (mcptr, sptr);
   }
   else
   if (strsame (cptr, "GzipResponse", -1))
   {
      /* <compression-level>[,<memory-level>,<window-bits>] */
      cfptr->cfMisc.GzipResponseCompLevel = MetaConSetInteger (mcptr, sptr);
      while (*sptr && isdigit(*sptr)) sptr++;
      while (*sptr && (*sptr == ',' || ISLWS(*sptr))) sptr++;
      if (isdigit(*sptr))
         cfptr->cfMisc.GzipResponseMemLevel = MetaConSetInteger (mcptr, sptr);
      while (*sptr && isdigit(*sptr)) sptr++;
      while (*sptr && (*sptr == ',' || ISLWS(*sptr))) sptr++;
      if (isdigit(*sptr))
         cfptr->cfMisc.GzipResponseWindowBits = MetaConSetInteger (mcptr, sptr);
   }
   else
   if (strsame (cptr, "Http2Protocol", -1))
      cfptr->cfHttp2.Enabled = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "Http2FrameSizeMax", -1))
      cfptr->cfHttp2.MaxFrameSize = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "Http2HeaderListMax", -1))
      cfptr->cfHttp2.MaxHeaderListSize = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "Http2HeaderTableMax", -1))
      cfptr->cfHttp2.MaxHeaderTableSize = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "Http2PingSeconds", -1))
      cfptr->cfHttp2.PingTimerSeconds = MetaConSetSeconds (mcptr, sptr, 1);
   else
   if (strsame (cptr, "Http2StreamsMax", -1))
      cfptr->cfHttp2.MaxConcurrentStreams = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "Http2InitWindowSize", -1))
      cfptr->cfHttp2.InitialWindowSize = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "HttpTrace", -1))
      cfptr->cfMisc.HttpTraceEnabled = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "WwwImplied", -1))
      cfptr->cfMisc.WwwImplied = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "InstanceMax", -1))
   {
      if (strsame (sptr, "CPU", 3))
         cfptr->cfServer.InstanceMax = INSTANCE_PER_CPU;
      else
         cfptr->cfServer.InstanceMax = MetaConSetInteger (mcptr, sptr);
   }
   else
   if (strsame (cptr, "InstancePassive", -1))
      cfptr->cfServer.InstancePassive = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "Logging", -1))
      cfptr->cfLog.Enabled = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "LogExcludeHosts", -1))
      StringListAdd (sptr, &cfptr->cfLog.ExcludeHostsPtr,
                           &cfptr->cfLog.ExcludeHostsLength);
   else
   if (strsame (cptr, "LogFile", -1))
      MetaConSetString (mcptr, sptr,
                        cfptr->cfLog.FileName, sizeof(cfptr->cfLog.FileName));
   else
   if (strsame (cptr, "LogFileExtend", -1))
      cfptr->cfLog.ExtendBlocks = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "LogFormat", -1))
      MetaConSetString (mcptr, sptr,
                        cfptr->cfLog.Format, sizeof(cfptr->cfLog.Format));
   else
   if (strsame (cptr, "LogNaming", -1))
      MetaConSetString (mcptr, sptr,
                        cfptr->cfLog.Naming, sizeof(cfptr->cfLog.Naming));
   else
   if (strsame (cptr, "LogPeriod", -1))
      MetaConSetString (mcptr, sptr,
                        cfptr->cfLog.Period, sizeof(cfptr->cfLog.Period));
   else
   if (strsame (cptr, "LogPerInstance", -1))
      cfptr->cfLog.PerInstance = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "LogPerService", -1))
      cfptr->cfLog.PerService = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "LogPerServiceHostOnly", -1))
      cfptr->cfLog.PerServiceHostOnly = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "LogWriteFail503", -1))
      cfptr->cfLog.WriteFail503 = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "MapUserNameCacheEntries", -1))
      cfptr->cfMisc.MapUserNameCacheEntries = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "Monitor", -1))
      cfptr->cfMisc.MonitorEnabled = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "OpcomTarget", -1) ||
       strsame (cptr, "OpcomAdmin", -1) ||
       strsame (cptr, "OpcomAuthorization", -1) ||
       strsame (cptr, "OpcomControl", -1) ||
       strsame (cptr, "OpcomHTTPd", -1) ||
       strsame (cptr, "OpcomProxyMaint", -1))
      ConfigSetOpcom (mcptr, cptr, sptr);
   else
   if (strsame (cptr, "PersonaCacheEntries", -1))
      cfptr->cfMisc.PersonaCacheEntries = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "PipelineRequests", -1))
      cfptr->cfMisc.PipelineRequests = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "ProcessMax", -1))
      cfptr->cfServer.ProcessMax = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "ProxyCache", -1))
      cfptr->cfProxy.CacheEnabled = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "ProxyCacheDeviceCheckMinutes", -1))
      cfptr->cfProxy.CacheDeviceCheckMinutes = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "ProxyCacheDeviceDirOrg", -1))
   {
      if (strsame (sptr, "flat256", 7))
         cfptr->cfProxy.CacheDeviceDirOrg = PROXY_CACHE_DIR_ORG_FLAT256;
      else
      if (strsame (sptr, "64x64", 5))
         cfptr->cfProxy.CacheDeviceDirOrg = PROXY_CACHE_DIR_ORG_64X64;
      else
      {
         cfptr->cfProxy.CacheDeviceDirOrg = 0;
         MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemParameter);
      }
   }
   else
   if (strsame (cptr, "ProxyCacheDeviceMaxPercent", -1))
      cfptr->cfProxy.CacheDeviceMaxPercent = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "ProxyCacheDevicePurgePercent", -1))
      cfptr->cfProxy.CacheDevicePurgePercent = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "ProxyCacheFileKBytesMax", -1))
      cfptr->cfProxy.CacheFileKBytesMax = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "ProxyCacheNegativeSeconds", -1))
      cfptr->cfProxy.CacheNegativeSeconds = MetaConSetSeconds (mcptr, sptr, 1);
   else
   if (strsame (cptr, "ProxyCacheNoReloadSeconds", -1))
      cfptr->cfProxy.CacheNoReloadSeconds = MetaConSetSeconds (mcptr, sptr, 1);
   else
   if (strsame (cptr, "ProxyCacheRoutineHourOfDay", -1))
      MetaConSetString (mcptr, sptr,
                        cfptr->cfProxy.CacheRoutineHourOfDayString,
                        sizeof(cfptr->cfProxy.CacheRoutineHourOfDayString));
   else
   if (strsame (cptr, "ProxyCachePurgeList", -1))
      MetaConSetString (mcptr, sptr,
                        cfptr->cfProxy.CachePurgeList,
                        sizeof(cfptr->cfProxy.CachePurgeList));
   else
   if (strsame (cptr, "ProxyCacheReloadList", -1))
      MetaConSetString (mcptr, sptr,
                        cfptr->cfProxy.CacheReloadList,
                        sizeof(cfptr->cfProxy.CacheReloadList));
   else
   if (strsame (cptr, "ProxyConnectPersistMax", -1))
      cfptr->cfProxy.ConnectPersistMax = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "ProxyConnectPersistSeconds", -1))
      cfptr->cfProxy.ConnectPersistSeconds = MetaConSetSeconds (mcptr, sptr, 1);
   else
   if (strsame (cptr, "ProxyConnectTimeoutSeconds", -1))
      cfptr->cfProxy.ConnectTimeoutSeconds = MetaConSetSeconds (mcptr, sptr, 1);
   else
   if (strsame (cptr, "ProxyForwarded", -1))
   {
      if (strsame (sptr, "BY", 2))
         cfptr->cfProxy.ForwardedBy = PROXY_FORWARDED_BY;
      else
      if (strsame (sptr, "DISABLED", 8))
         cfptr->cfProxy.ForwardedBy = PROXY_FORWARDED_DISABLED;
      else
      if (strsame (sptr, "FOR", 3))
         cfptr->cfProxy.ForwardedBy = PROXY_FORWARDED_FOR;
      else
      if (strsame (sptr, "ADDRESS", 7))
         cfptr->cfProxy.ForwardedBy = PROXY_FORWARDED_ADDRESS;
      else
      {
         cfptr->cfProxy.ForwardedBy = PROXY_FORWARDED_DISABLED;
         MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemParameter);
      }
   }
   else
   /* "ProxyAddForwardedBy" for backward compatibility with 'ProxyForwarded' */
   if (strsame (cptr, "ProxyAddForwardedBy", -1))
   {
      if (MetaConSetBoolean (mcptr, sptr))
         cfptr->cfProxy.ForwardedBy = PROXY_FORWARDED_BY;
      else
         cfptr->cfProxy.ForwardedBy = PROXY_FORWARDED_DISABLED;
   }
   else
   if (strsame (cptr, "ProxyHostCachePurgeHours", -1))
      MetaConReport (mcptr, METACON_REPORT_INFORM, ProblemObsolete);
   else
   if (strsame (cptr, "ProxyHostLookupRetryCount", -1))
      cfptr->cfProxy.HostLookupRetryCount = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "ProxyReportCacheLog", -1))
      cfptr->cfProxy.ReportCacheLog = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "ProxyReportLog", -1))
      cfptr->cfProxy.ReportLog = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "ProxyServing", -1))
      cfptr->cfProxy.ServingEnabled = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "ProxyUnknownRequestFields", -1))
      cfptr->cfProxy.UnknownRequestFields = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "ProxyVerifyRecordMax", -1))
      cfptr->cfProxy.VerifyRecordMax = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "ProxyXForwardedFor", -1))
   {
      if (strsame (sptr, "ENABLED", 7))
         cfptr->cfProxy.XForwardedFor = PROXY_XFORWARDEDFOR_ENABLED;
      else
      if (strsame (sptr, "UNKNOWN", 7))
         cfptr->cfProxy.XForwardedFor = PROXY_XFORWARDEDFOR_UNKNOWN;
      else
      if (strsame (sptr, "ADDRESS", 7))
         cfptr->cfProxy.XForwardedFor = PROXY_XFORWARDEDFOR_ADDRESS;
      else
      if (strsame (sptr, "DISABLED", 8))
         cfptr->cfProxy.XForwardedFor = PROXY_XFORWARDEDFOR_DISABLED;
      else
      {
         cfptr->cfProxy.XForwardedFor = PROXY_XFORWARDEDFOR_DISABLED;
         MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemParameter);
      }
   }
   else
   if (strsame (cptr, "Port", -1))
      cfptr->cfServer.DefaultPort = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "PutRFM", -1))
   {
      if (*sptr)
      {
         if (strsame (sptr, "FIX512", -1))
            cfptr->cfMisc.PutBinaryRFM = PUT_RFM_FIX512;
         else
         if (strsame (sptr, "STM", -1))
            cfptr->cfMisc.PutBinaryRFM = PUT_RFM_STM;
         else
         if (strsame (sptr, "STMCR", -1))
            cfptr->cfMisc.PutBinaryRFM = PUT_RFM_STMCR;
         else
         if (strsame (sptr, "STMLF", -1))
            cfptr->cfMisc.PutBinaryRFM = PUT_RFM_STMLF;
         else
         if (strsame (sptr, "UDF", -1))
            cfptr->cfMisc.PutBinaryRFM = PUT_RFM_UDF;
         else
            MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemDirective);
      }
   }
   else
   if (strsame (cptr, "PutMaxKbytes", -1))
      cfptr->cfMisc.PutMaxKbytes = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "PutVersionLimit", -1))
      cfptr->cfMisc.PutVersionLimit = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "RegEx", -1))
   {
     if (strsame (sptr, "ENABLED", 7))
        cfptr->cfMisc.RegexSyntax = REGEX_C_FLAGS;
     else
     if (strsame (sptr, "DISABLED", 8))
        cfptr->cfMisc.RegexSyntax = 0;
     else
     if (isdigit(*sptr))
        cfptr->cfMisc.RegexSyntax = atoi(sptr);
     else
     if (strsame (sptr, "AWK", 3))
         cfptr->cfMisc.RegexSyntax = RE_SYNTAX_AWK;
     else
     if (strsame (sptr, "ED", 2))
        cfptr->cfMisc.RegexSyntax = RE_SYNTAX_ED;
     else
     if (strsame (sptr, "EGREP", 5))
        cfptr->cfMisc.RegexSyntax = RE_SYNTAX_EGREP;
     else
     if (strsame (sptr, "GREP", 4))
        cfptr->cfMisc.RegexSyntax = RE_SYNTAX_GREP;
     else
     if (strsame (sptr, "POSIX_AWK", 9))
        cfptr->cfMisc.RegexSyntax = RE_SYNTAX_POSIX_AWK;
     else
     if (strsame (sptr, "POSIX_BASIC", 11))
        cfptr->cfMisc.RegexSyntax = RE_SYNTAX_POSIX_BASIC;
     else
     if (strsame (sptr, "POSIX_EGREP", 11))
        cfptr->cfMisc.RegexSyntax = RE_SYNTAX_POSIX_EGREP;
     else
     if (strsame (sptr, "POSIX_EXTENDED", 14))
         cfptr->cfMisc.RegexSyntax = RE_SYNTAX_POSIX_EXTENDED;
     else
     if (strsame (sptr, "POSIX_MINIMAL_BASIC", 19))
        cfptr->cfMisc.RegexSyntax = RE_SYNTAX_POSIX_MINIMAL_BASIC;
     else
     if (strsame (sptr, "POSIX_MINIMAL_EXTENDED", 22))
        cfptr->cfMisc.RegexSyntax = RE_SYNTAX_POSIX_MINIMAL_EXTENDED;
     else
     if (strsame (sptr, "SED", 3))
        cfptr->cfMisc.RegexSyntax = RE_SYNTAX_SED;
     else
     if (strsame (sptr, "WASD", 10))
        cfptr->cfMisc.RegexSyntax = REGEX_C_FLAGS;
     else
        cfptr->cfMisc.RegexSyntax = 0;
   }
   else
   if (strsame (cptr, "Reject", -1))
      StringListAdd (sptr, &cfptr->cfServer.RejectHostsPtr,
                           &cfptr->cfServer.RejectHostsLength);
   else
   if (strsame (cptr, "ReportBasicOnly", -1))
      cfptr->cfReport.BasicOnly = MetaConSetBoolean (mcptr, sptr);
   else
   /* "CommentedInfo" & "ErrorSourceInfo" for backward compatibility */
   if (strsame (cptr, "ReportMetaInfo", -1) ||
       strsame (cptr, "CommentedInfo", -1) ||
       strsame (cptr, "ErrorSourceInfo", -1))
      cfptr->cfReport.MetaInfoEnabled = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "RequestHistory", -1))
      cfptr->cfMisc.RequestHistory = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "Scripting", -1))
      cfptr->cfScript.Enabled = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "Search", -1) ||
       strsame (cptr, "SearchScript", -1))
   {
      MetaConSetString (mcptr, sptr,
                        cfptr->cfScript.DefaultSearch,
                        sizeof(cfptr->cfScript.DefaultSearch));
      cfptr->cfScript.DefaultSearchLength =
         strlen(cfptr->cfScript.DefaultSearch);
   }
   else
   if (strsame (cptr, "SearchScriptExclude", -1))
      StringListAdd (sptr, &cfptr->cfScript.DefaultSearchExcludePtr,
                           &cfptr->cfScript.DefaultSearchExcludeLength);
   else
   if (strsame (cptr, "ServerAdmin", -1))
      MetaConSetString (mcptr, sptr,
                        cfptr->cfServer.AdminEmail,
                        sizeof(cfptr->cfServer.AdminEmail));
   else
   if (strsame (cptr, "ServerAdminBodyTag", -1))
      MetaConReport (mcptr, METACON_REPORT_INFORM, ProblemObsolete);
   else
   if (strsame (cptr, "ServerReportBodyTag", -1))
      MetaConReport (mcptr, METACON_REPORT_INFORM, ProblemObsolete);
   else
   if (strsame (cptr, "ServerSignature", -1))
      cfptr->cfProxy.ServingEnabled = ConfigSetServerSignature (mcptr, sptr);
   else
   if (strsame (cptr, "Service", -1))
      StringListAdd (sptr, &cfptr->cfServer.ServicePtr,
                           &cfptr->cfServer.ServiceLength);
   else
   if (strsame (cptr, "ServiceListenBacklog", -1))
      cfptr->cfServer.ListenBacklog = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "ServiceNotFoundURL", -1))
      MetaConSetString (mcptr, sptr,
                        cfptr->cfServer.ServiceNotFoundUrl,
                        sizeof(cfptr->cfServer.ServiceNotFoundUrl));
   else
   if (strsame (cptr, "SocketSizeRcvBuf", -1))
      cfptr->cfBuffer.SizeSocketRcvBuf = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "SocketSizeSndBuf", -1))
      cfptr->cfBuffer.SizeSocketSndBuf = MetaConSetInteger (mcptr, sptr);
   else
   /* "ShtmlAccesses" for backward compatibility */
   if (strsame (cptr, "SSIAccesses", -1) ||
       strsame (cptr, "ShtmlAccesses", -1))
      cfptr->cfSsi.AccessesEnabled = MetaConSetBoolean (mcptr, sptr);
   else
   /* "ShtmlExec" for backward compatibility */
   if (strsame (cptr, "SSIExec", -1) ||
       strsame (cptr, "ShtmlExec", -1))
      cfptr->cfSsi.ExecEnabled = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "SSISizeMax", -1))
      cfptr->cfSsi.SizeMax = MetaConSetInteger (mcptr, sptr);
   else
   /* "SSI" MUST come after the other SSIs for obvious reasons */
   /* "Shtml" for backward compatibility */
   if (strsame (cptr, "SSI", -1) ||
       strsame (cptr, "Shtml", -1))
      cfptr->cfSsi.Enabled = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "SecureSocket", -1) ||
       strsame (cptr, "SecureSockets", -1))
   {
      /* somewhat back-to-front from the usual and if empty ignored */
      for (zptr = sptr; *zptr && isspace(*zptr); zptr++);
      if (*zptr) cfptr->cfSesola.Disabled = !MetaConSetBoolean (mcptr, sptr);
   }
   else
   if (strsame (cptr, "SSLcipherList", -1))
      MetaConSetString (mcptr, sptr,
                        cfptr->cfSesola.CipherList,
                        sizeof(cfptr->cfSesola.CipherList));
   else
   if (strsame (cptr, "SSLcert", -1))
      MetaConSetString (mcptr, sptr,
                        cfptr->cfSesola.ServerCert,
                        sizeof(cfptr->cfSesola.ServerCert));
   else
   if (strsame (cptr, "SSLkey", -1))
      MetaConSetString (mcptr, sptr,
                        cfptr->cfSesola.PrivateKey,
                        sizeof(cfptr->cfSesola.PrivateKey));
   else
   if (strsame (cptr, "SSLoptions", -1))
      MetaConSetString (mcptr, sptr,
                        cfptr->cfSesola.ProtocolOptions,
                        sizeof(cfptr->cfSesola.ProtocolOptions));
   else
   if (strsame (cptr, "SSLsessionCacheMax", -1))
      cfptr->cfSesola.SessionCacheMax = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "SSLsessionLifetime", -1))
      cfptr->cfSesola.SessionLifetime = MetaConSetSeconds (mcptr, sptr, 1);
   else
   if (strsame (cptr, "SSLstrictTransSec", -1))
      MetaConSetString (mcptr, sptr,
                        cfptr->cfSesola.StrictTransSec,
                        sizeof(cfptr->cfSesola.StrictTransSec));
   else
   if (strsame (cptr, "SSLinstanceCacheMax", -1))
      cfptr->cfSesola.InstanceSessionCacheMax = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "SSLinstanceCacheSize", -1))
      cfptr->cfSesola.InstanceSessionCacheSize = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "SSLverifyPeer", -1))
      cfptr->cfSesola.VerifyPeer = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "SSLverifyPeerCAFile", -1))
      MetaConSetString (mcptr, sptr,
                        cfptr->cfSesola.VerifyPeerCAFile,
                        sizeof(cfptr->cfSesola.VerifyPeerCAFile));
   else
   if (strsame (cptr, "SSLverifyPeerDepth", -1))
      cfptr->cfSesola.VerifyPeerDepth = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "SSLversion", -1))
      MetaConSetString (mcptr, sptr,
                        cfptr->cfSesola.ProtocolVersion,
                        sizeof(cfptr->cfSesola.ProtocolVersion));
   else
   if (strsame (cptr, "SSLverifyPeerDataMax", -1))
      cfptr->cfSesola.VerifyPeerDataMax = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "StreamLF", -1))
      cfptr->cfMisc.StreamLfConversionMaxKbytes =
         MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "TimeoutHttp2Idle", -1))
      cfptr->cfTimeout.Http2Idle = MetaConSetSeconds (mcptr, sptr, 60);
   else
   if (strsame (cptr, "TimeoutInput", -1) ||
       strsame (cptr, "InputTimeout", -1))
      cfptr->cfTimeout.Input = MetaConSetSeconds (mcptr, sptr, 60);
   else
   if (strsame (cptr, "TimeoutNoProgress", -1))
      cfptr->cfTimeout.NoProgress =
         MetaConSetSeconds (mcptr, sptr, 60);
   else
   if (strsame (cptr, "TimeoutOutput", -1) ||
       strsame (cptr, "OutputTimeout", -1))
      cfptr->cfTimeout.Output = MetaConSetSeconds (mcptr, sptr, 60);
   else
   if (strsame (cptr, "TimeoutPersistent", -1) ||
       strsame (cptr, "TimeoutKeepAlive", -1) ||
       strsame (cptr, "KeepAliveTimeout", -1))
      cfptr->cfTimeout.Persistent = MetaConSetSeconds (mcptr, sptr, 1);
   else
   if (strsame (cptr, "Track", -1))
      MetaConReport (mcptr, METACON_REPORT_INFORM, ProblemObsolete);
   else
   if (strsame (cptr, "TrackDomain", -1))
      MetaConReport (mcptr, METACON_REPORT_INFORM, ProblemObsolete);
   else
   if (strsame (cptr, "TrackMultiSession", -1))
      MetaConReport (mcptr, METACON_REPORT_INFORM, ProblemObsolete);
   else
   if (strsame (cptr, "WebDav", -1))
      cfptr->cfWebDav.DavEnabled = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "WebDavLocking", -1))
      cfptr->cfWebDav.LockingEnabled = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "WebDavQuota", -1))
      cfptr->cfWebDav.QuotaEnabled = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "WebDavLockCollectionDepth", -1))
      cfptr->cfWebDav.LockCollectionDepth = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "WebDAVlockTimeoutDefault", -1))
      cfptr->cfWebDav.LockTimeoutDefaultSeconds =
         MetaConSetSeconds (mcptr, sptr, 1);
   else
   if (strsame (cptr, "WebDAVlockTimeoutMax", -1))
      cfptr->cfWebDav.LockTimeoutMaxSeconds =
         MetaConSetSeconds (mcptr, sptr, 1);
   else
   if (strsame (cptr, "WebDAVmetaDir", -1))
   {
      MetaConSetString (mcptr, sptr,
                        cfptr->cfWebDav.MetaFileDirectory,
                        sizeof(cfptr->cfWebDav.MetaFileDirectory));
      cfptr->cfWebDav.MetaFileDirectoryLength =
         strlen(cfptr->cfWebDav.MetaFileDirectory);
   }
   else
   if (strsame (cptr, "Welcome", -1))
      ConfigSetWelcome (mcptr, sptr);
   else
      MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemDirective);

   return (true);

#undef REP_ENDIS
}

/*****************************************************************************/
/*
Free all memory allocated for a configuration.  Only used after file-based
configuration report or revision.
*/

ConfigFree (META_CONFIG *mcptr)

{
   int  Count;
   char  *cptr;
   CONFIG_STRUCT  *cfptr;
   CONTENT_TYPE  *ctptr;
   ICON_TYPE  *itptr;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (WATCHALL, WATCH_MOD_CONFIG, "ConfigFree()");

   /* get a pointer to the meta-config data */
   cfptr = mcptr->ConfigMetaPtr;

   ctptr = cfptr->cfContent.ContentInfoListHeadPtr;
   while (ctptr)
   {
      cptr = (char*)ctptr;
      ctptr = ctptr->NextPtr;
      VmFree (cptr, FI_LI);
   }

   itptr = cfptr->cfContent.IconListHeadPtr;
   while (itptr)
   {
      cptr = (char*)itptr;
      itptr = itptr->NextPtr;
      VmFree (cptr, FI_LI);
   }

   for (Count = 0; Count < cfptr->cfContent.HomePageCount; Count++)
      if (cfptr->cfContent.HomePageArray[Count])
         VmFree (cfptr->cfContent.HomePageArray[Count], FI_LI);

   if (cfptr->cfContent.CharsetConvertPtr)
      VmFree (cfptr->cfContent.CharsetConvertPtr, FI_LI);
   if (cfptr->cfServer.AcceptHostsPtr)
      VmFree (cfptr->cfServer.AcceptHostsPtr, FI_LI);
   if (cfptr->cfLog.ExcludeHostsPtr)
      VmFree (cfptr->cfLog.ExcludeHostsPtr, FI_LI);
   if (cfptr->cfServer.RejectHostsPtr)
      VmFree (cfptr->cfServer.RejectHostsPtr, FI_LI);
   if (cfptr->cfScript.DefaultSearchExcludePtr)
      VmFree (cfptr->cfScript.DefaultSearchExcludePtr, FI_LI);
   if (cfptr->cfServer.ServicePtr)
      VmFree (cfptr->cfServer.ServicePtr, FI_LI);
}

/*****************************************************************************/
/*
Add a mime content type corresponding to the file suffix (extension, type). 
The file suffix can contain the asterisk wildcard character, matching zero or
more characters.  The content-type can be quoted and can include additional
characteristics, including an FTP transfer mode (ASCII - 'A', binary/Image -
'B'/'I' as shown in the final example), and a PUT Record Format (RFM:blah).

Format: "AddType <.suffix> <type[;forw
charset=]> [</script>] [<description>]"

Examples: "AddType .html text/html HTML"
          "AddType .html text/html;charset=ISO8859-5 HTML"
          "AddType .html "text/html; charset=ISO8859-5" HTML"
          "AddType .txt text/plain plain text"
          "AddType .read* text/plain plain text"
          "AddType .hlb text/x-script /cgi-bin/conan VMS help library"
          "AddType .gif image/gif GIF image"
          "AddType .ps application/postscript(FTP:A) Postscript document"
          "AddType .ps application/postscript RFM:STMCR Postscript doc"
          "AddType .ps application/postscript FTP:A RFM:STMCR Postscript doc"

The directive is stored as a linked list of structures of dynamically
allocated memory containing a reformatted version of the directive string.
Function ConfigContentType() searches this list to get pointers to the content
type, any auto-script, and description, into the client request data
structure. A hash table is used to more rapidy index into the list.
*/ 

ConfigAddType
(
META_CONFIG *mcptr,
char *pptr
)
{
   static char  ProblemFtpMode [] = "unknown FTP mode",
                ProblemPutRFM [] = "unknown PUT RFM";

   int  PutRFM;
   char  FtpMode;
   char  *AutoScriptPtr,
         *DescriptionPtr,
         *MimeTypePtr,
         *SuffixPtr;
   CONFIG_STRUCT  *cfptr;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (WATCHALL, WATCH_MOD_CONFIG,
                 "ConfigAddType() !&Z", pptr);

   /* get a pointer to the meta-config data */
   cfptr = mcptr->ConfigMetaPtr;

   AutoScriptPtr = DescriptionPtr = MimeTypePtr = SuffixPtr = "";
   FtpMode = PutRFM = 0;

   for (SuffixPtr = pptr; *pptr && !ISLWS(*pptr); pptr++);
   if (*pptr) *pptr++ = '\0';

   /* content type (can include quotes, e.g. "text/html; charset=ISO-8859-5" */
   while (*pptr && ISLWS(*pptr)) pptr++;
   if (*pptr == '\"')
   {
      pptr++;
      MimeTypePtr = pptr;
      while (*pptr && *pptr != '\"') pptr++;
   }
   else
   {
      MimeTypePtr = pptr;
      while (*pptr && !ISLWS(*pptr) && *pptr != '(') pptr++;
   }

   if (*pptr == '\"') *pptr++ = '\0';
   if (*pptr == '(')
   {
      /* backward compatibility */
      *pptr++ = '\0';
      if (strsame (pptr, "FTP:", 4))
      {
         pptr += 4;
         if (*pptr == 'A' || *pptr == 'B' || *pptr == 'I') FtpMode = *pptr++;
         if (!FtpMode)
            MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemFtpMode);
      }
   }
   while (*pptr && !ISLWS(*pptr)) pptr++;
   if (ISLWS(*pptr)) *pptr++ = '\0';

   while (strsame (pptr, "RFM:", 4) ||
          strsame (pptr, "FTP:", 4))
   {
      if (strsame (pptr, "RFM:", 4))
      {
         pptr += 4;
         PutRFM = 0;
         if (strsame (pptr, "FIX512", 6))
            PutRFM = PUT_RFM_FIX512;
         else
         if (strsame (pptr, "STMCR", 5))
            PutRFM = PUT_RFM_STMCR;
         else
         if (strsame (pptr, "STMLF", 5))
            PutRFM = PUT_RFM_STMLF;
         else
         if (strsame (pptr, "STM", 3))
            PutRFM = PUT_RFM_STM;
         else
         if (strsame (pptr, "UDF", 3))
            PutRFM = PUT_RFM_UDF;
         if (!PutRFM)
            MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemPutRFM);
      }
      else
      if (strsame (pptr, "FTP:", 4))
      {
         pptr += 4;
         FtpMode = 0;
         if (*pptr == 'A' || *pptr == 'B' || *pptr == 'I') FtpMode = *pptr++;
         if (!FtpMode)
            MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemFtpMode);
      }
      while (*pptr && !ISLWS(*pptr)) pptr++;
      while (*pptr && ISLWS(*pptr)) pptr++;
   }

   /* (optional) script activation indicated by leading slash */
   while (*pptr && ISLWS(*pptr)) pptr++;
   if (*pptr == '/')
   {
      AutoScriptPtr = pptr;
      while (*pptr && !ISLWS(*pptr)) pptr++;
      if (*pptr) *pptr++ = '\0';
   }
   else
   if (*pptr == '-')
   {
      /* backward compatibility for those still place-holding with '-' */
      while (*pptr && !ISLWS(*pptr)) pptr++;
      AutoScriptPtr = "";
   }
   else
      AutoScriptPtr = "";

   /* (optional) description, to end of line */
   while (*pptr && ISLWS(*pptr)) pptr++;
   DescriptionPtr = pptr;
   /* find the end-of-line */
   while (*pptr) pptr++;
   if (*pptr) *pptr++ = '\0';

   ConfigAddTypeNow (mcptr, MimeTypePtr, SuffixPtr, AutoScriptPtr,
                     DescriptionPtr, FtpMode, PutRFM, false);
}

/*****************************************************************************/
/*
MIME.TYPES file (with WASD 'commented' extensions).

Format: mime/type file-ext [file-ext file-ext]
        #! optional descriptive text    (applies to above)
        #!/optional/auto-script         (applies to above)
        #[alt] /optional/icon.gif       (applies to above)
        mime/type file-ext [file-ext file-ext]

Examples: text/html          html htm
          #! HTML markup
          text/plain         asc txt
          #! plain text
          #[TXT] /httpd/-/text.gif
          application/x-script   bks decw$bookshelf
          #/cgi-bin/hypershelf
          #! Bookreader shelf
          application/x-script   bkb decw$book
          #/cgi-bin/hypershelf
          #! Bookreader book
*/ 

ConfigAddMimeTypesFile
(
META_CONFIG *mcptr,
char *pptr
)
{
   static char  ProblemParameter [] = "Parameter confusing";

   int  status;
   char  *cptr, *sptr, *zptr;
   CONFIG_STRUCT  *cfptr;
   ODS_STRUCT  MimeTypesFileOds;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (WATCHALL, WATCH_MOD_CONFIG,
                 "ConfigAddMimeTypesFile() !&Z", pptr);

   /* get a pointer to the meta-config data */
   cfptr = mcptr->ConfigMetaPtr;

   zptr = (sptr = cfptr->cfContent.MimeTypesFileName) +
          sizeof(cfptr->cfContent.MimeTypesFileName);
   for (cptr = pptr; *cptr && sptr < zptr; *sptr++ = *cptr++);
   if (sptr >= zptr)
   {
      MetaConReport (mcptr, METACON_REPORT_ERROR, ConfigStringOverflow);
      return (false);
   }

   /* use SYSPRV to allow access to possibly protected file */
   sys$setprv (1, &SysPrvMask, 0, 0);

   status = OdsLoadTextFile (&MimeTypesFileOds,
                             cfptr->cfContent.MimeTypesFileName);

   sys$setprv (0, &SysPrvMask, 0, 0);

   if (VMSnok (status))
   {
      MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemParameter);
      return (true);
   }

   while ((cptr = OdsParseTextFile (&MimeTypesFileOds, '*')))
      ConfigAddMimeType (mcptr, cptr);

   VmFree (MimeTypesFileOds.DataPtr, FI_LI);

   /* ensure the final MIME type and file suffix(es) is configured */
   ConfigAddMimeType (mcptr, NULL);
}

/*****************************************************************************/
/*
Process a single line from a MIME.TYPES file (with WASD extensions).

  "#!/" ... an auto-script/presentation-script (e.g. "#!/cgi-bin/script-name")
  "#![" ... an icon specification (e.g. "#![ALT] /httpd/-/icon.gif")
  "#! " ... a file suffix (file type) description (e.g. "#! plain text")
  "#!%" ... reserved for local viewers (ignored by WASD)
  "#!+A ... FTP transfer mode ASCII
  "#!+B ... FTP transfer mode binary (Image)
  "#!+I ... FTP transfer mode binary (Image)
  "#!!" ... WASD-specific MIME type (should be ignored by non-WASD)

This function expects the WASD-specific information to follow a MIME type and
it's file suffixes.  The detection of another MIME type causes the previous one
and any following WASD-specifics to be configured.
*/ 

ConfigAddMimeType
(
META_CONFIG *mcptr,
char *pptr
)
{
   static char  ProblemAutoScript [] = "autoscript too large",
                ProblemDescription [] = "description too large",
                ProblemFtpMode [] = "unknown FTP mode",
                ProblemIcon [] = "icon too large",
                ProblemMimeType [] = "MIME type too large";

   static char  FtpMode;

   static char  AutoScript [64],
                CurrentMimeType [128],
                Description [64],
                IconUrl [64];

   char  *cptr, *sptr, *zptr,
         *MimeTypePtr,
         *SuffixPtr;
   CONFIG_STRUCT  *cfptr;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (WATCHALL, WATCH_MOD_CONFIG,
                 "ConfigAddMimeType() !&Z", pptr);

   /* get a pointer to the meta-config data */
   cfptr = mcptr->ConfigMetaPtr;

   /* loop is never actually used, just somthing to break out of */
   if (pptr)
   {
      while (*pptr && ISLWS(*pptr)) pptr++;
      if (!*pptr) return;

      if (*pptr == '#')
      {
         pptr++;

         if (SAME2(pptr,'!%'))
            return;
         else
         if (SAME2(pptr,'!/'))
         {
            /* autoscript */
            pptr++;
            zptr = (sptr = AutoScript) + sizeof(AutoScript)-1;
            while (*pptr && !ISLWS(*pptr) && sptr < zptr) *sptr++ = *pptr++;
            if (sptr >= zptr)
            {
               AutoScript[0] = '\0';
               MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemAutoScript);
            }
            *sptr = '\0';
            return;
         }
         else
         if (SAME2(pptr,'! '))
         {
            /* descriptive text, begins with space */
            pptr += 2;
            while (*pptr && ISLWS(*pptr)) pptr++;
            zptr = (sptr = Description) + sizeof(Description)-1;
            while (*pptr && sptr < zptr) *sptr++ = *pptr++;
            if (sptr >= zptr)
            {
               Description[0] = '\0';
               MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemDescription);
               return;
            }
            *sptr = '\0';
            return;
         }
         else
         if (SAME2(pptr,'!['))
         {
            /* icon URL */
            pptr++;
            /* must reverse the order of the string for WASD icon processing */
            for (cptr = pptr; *cptr && !ISLWS(*cptr); cptr++);
            while (*cptr && ISLWS(*cptr)) cptr++;
            zptr = (sptr = IconUrl) + sizeof(IconUrl)-1;
            while (*cptr && sptr < zptr) *sptr++ = *cptr++;
            if (sptr < zptr) *sptr++ = ' ';
            while (*pptr && !ISLWS(*pptr) && sptr < zptr) *sptr++ = *pptr++;
            if (sptr >= zptr)
            {
               IconUrl[0] = '\0';
               MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemIcon);
               return;
            }
            *sptr = '\0';
            return;
         }
         else
         if (SAME2(pptr,'!+'))
         {
            /* FTP transfer mode */
            pptr += 2;
            if (*pptr == 'A' || *pptr == 'B' || *pptr == 'I')
               FtpMode = *pptr++;
            else
            {
               MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemFtpMode);
               return;
            }
            return;
         }
         else
         if (SAME2(pptr,'!!'))
         {
            /* WASD-specific MIME type */
            pptr += 2;
            /* to continue processing MIME type */
         }
         else
         {
            /* nothing WASD is interested in */
            return;
         }
      }
   }

   /*************/                       
   /* MIME type */
   /*************/

   if (CurrentMimeType[0])
   {
      /* new MIME type and file suffixes, configure the current one */
      for (cptr = CurrentMimeType; *cptr && !ISLWS(*cptr); cptr++);
      if (*cptr) *cptr++ = '\0';

      while (*cptr && ISLWS(*cptr)) cptr++;
      while (*cptr)
      {
         SuffixPtr = cptr;
         while (*cptr && !ISLWS(*cptr)) cptr++;
         if (*cptr) *cptr++ = '\0';
         while (*cptr && ISLWS(*cptr)) cptr++;
         ConfigAddTypeNow (mcptr, CurrentMimeType, SuffixPtr, AutoScript,
                           Description, FtpMode, 0, true);
      }

      if (IconUrl[0])
      {
         /*******************/
         /* associated icon */
         /*******************/

         ConfigAddIcon (mcptr, IconUrl, CurrentMimeType, true);
      }
   }

   AutoScript[0] = Description[0] = IconUrl[0] = CurrentMimeType[0] = '\0';
   FtpMode = 0;

   if (pptr)
   {
      /* buffer this MIME type and file suffixes */
      zptr = (sptr = CurrentMimeType) + sizeof(CurrentMimeType)-1;
      while (*pptr && sptr < zptr) *sptr++ = *pptr++;
      if (sptr >= zptr)
      {
         CurrentMimeType[0] = '\0';
         MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemMimeType);
         return;
      }
      *sptr = '\0';
   }
}

/*****************************************************************************/
/*
Add the following content-type to the list and hash table.  Later definitions
of the same file suffix supercedes earlier ones.
*/ 

ConfigAddTypeNow
(
META_CONFIG *mcptr,
char *MimeType,
char *FileSuffix,
char *AutoScript,
char *Description,
char FtpMode,
int PutRFM,
BOOL FromMimeTypes
)
{
   BOOL  ContainsWildcard;
   int  Count;
   unsigned long  HashValue;
   char  *cptr, *sptr;
   char  HtmlDescription [256];
   CONTENT_TYPE  *ctptr, *hctptr;
   CONFIG_STRUCT  *cfptr;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (WATCHALL, WATCH_MOD_CONFIG,
                 "ConfigAddTypeNow() !&Z !&Z !&Z !&Z !UL !UL",
                 MimeType, FileSuffix, AutoScript, Description,
                 FtpMode, PutRFM);

   /* get a pointer to the meta-config data */
   cfptr = mcptr->ConfigMetaPtr;

   /* escape any HTML-forbidden characters */
   FaoToBuffer (HtmlDescription, sizeof(HtmlDescription), NULL,
                "!&;AZ", Description);

   Count = strlen (MimeType);
   Count += strlen (FileSuffix);
   Count += strlen (AutoScript);
   Count += strlen (HtmlDescription);

   /* plus structure overhead, plus 4 x null terminators, plus possible '.' */
   Count += cfptr->cfContent.ContentTypeStructOverhead + 5;
   ctptr = (CONTENT_TYPE*)VmGet (Count);

   sptr = (char*)ctptr + cfptr->cfContent.ContentTypeStructOverhead;

   ctptr->FromMimeTypes = FromMimeTypes;

   ContainsWildcard = false;
   ctptr->SuffixPtr = sptr;
   cptr = FileSuffix;
   if (*cptr != '.' && !SAME2(cptr,'*\0')) *sptr++ = '.';
   while (*cptr)
   {
      if (*cptr == '*') ContainsWildcard = true;
      /* ensure suffix is in upper-case so we don't have to do it matching */
      *sptr++ = TOUP(*cptr++);
   }
   *sptr++ = '\0';

   ctptr->ContentTypePtr = sptr;
   cptr = MimeType;
   while (*cptr) *sptr++ = *cptr++;
   *sptr++ = '\0';
   if (strsame (MimeType, "text/", 5)) ctptr->TypeText = true;

   ctptr->AutoScriptNamePtr = sptr;
   cptr = AutoScript;
   while (*cptr) *sptr++ = *cptr++;
   *sptr++ = '\0';

   ctptr->DescriptionPtr = sptr;
   cptr = HtmlDescription;
   while (*cptr) *sptr++ = *cptr++;
   *sptr = '\0';

   /* check if there is a previous entry of this suffix */
   for (hctptr = cfptr->cfContent.ContentInfoListHeadPtr;
        hctptr;
        hctptr = hctptr->NextPtr)
   {
      /* if a later type definition was loaded then ignore this one */
      if (strsame (hctptr->SuffixPtr, ctptr->SuffixPtr, -1))
         hctptr->Superceded = true;
   }

   /* add to list */
   if (!cfptr->cfContent.ContentInfoListHeadPtr)
      cfptr->cfContent.ContentInfoListHeadPtr = ctptr; 
   else
      cfptr->cfContent.ContentInfoListTailPtr->NextPtr = ctptr; 
   cfptr->cfContent.ContentInfoListTailPtr = ctptr;
   ctptr->NextPtr = NULL;

   if (ContainsWildcard)
   {
      /* all wildcarded types are listed from hash value 0 */
      HashValue = 0;
   }
   else
   {
      /* generates an upper-case hash */
      HashValue = 1;
      for (cptr = ctptr->SuffixPtr; *cptr && *cptr != ';'; cptr++)
         HashValue = (((*cptr)*541)^(HashValue*3)) &
                     CONTENT_TYPE_HASH_TABLE_MASK;
   }
   if (cfptr->cfContent.ContentInfoHashTable[HashValue])
   {
      /* add to the hash-collision list */
      for (hctptr = cfptr->cfContent.ContentInfoHashTable[HashValue];
           hctptr->HashCollisionPtr;
           hctptr = hctptr->HashCollisionPtr);
      hctptr->HashCollisionPtr = ctptr;
   }
   else
      cfptr->cfContent.ContentInfoHashTable[HashValue] = ctptr;

   /* special case, default content-type for unknown suffixes */
   if (SAME2(ctptr->SuffixPtr,'*\0'))
   {
      cfptr->cfContent.ContentTypeDefaultPtr =
         VmGet (strlen(HtmlDescription+1));
      strcpy (cfptr->cfContent.ContentTypeDefaultPtr, HtmlDescription);
      ctptr->TypeUnknown = true;
      /* cancel type description */
      *ctptr->DescriptionPtr = '\0';
   }
   else
      ctptr->TypeUnknown = false;

   ctptr->FtpMode = FtpMode;
   ctptr->PutRFM = PutRFM;

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchDataFormatted ("!&Z !&Z !&Z !&Z !&B !&B !UL !UL\n",
               ctptr->SuffixPtr, ctptr->ContentTypePtr,
               ctptr->AutoScriptNamePtr, ctptr->DescriptionPtr, 
               ctptr->TypeText, ctptr->TypeUnknown,
               ctptr->FtpMode, ctptr->PutRFM);
}

/*****************************************************************************/
/*
After loading all content-types (i.e. after configuration) this function sets
the corresponding icon for each type.
*/ 

ConfigContentTypeIcon (META_CONFIG *mcptr)

{
   CONTENT_TYPE  *ctptr;
   CONFIG_STRUCT  *cfptr;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (WATCHALL, WATCH_MOD_CONFIG, "ConfigContentTypeIcon()");

   /* get a pointer to the meta-config data */
   cfptr = mcptr->ConfigMetaPtr;

   /* do the default icon first (needless-to-say) */
   ConfigDefaultIconPtr = ConfigIconFor (ConfigContentTypeDefaultIcon, 0, 0);
   ConfigBlankIconPtr = ConfigIconFor (ConfigContentTypeBlank, 0, 0);
   ConfigDirIconPtr = ConfigIconFor (ConfigContentTypeDir, 0, 0);
   ConfigParentIconPtr = ConfigIconFor (ConfigContentTypeParent, 0, 0);
   ConfigUnknownIconPtr = ConfigIconFor (ConfigContentTypeUnknown, 0, 0);

   for (ctptr = cfptr->cfContent.ContentInfoListHeadPtr;
        ctptr;
        ctptr = ctptr->NextPtr)
   {
      if (ctptr->TypeUnknown)
         ctptr->IconPtr = ConfigIconFor (ConfigContentTypeUnknown, 0, 0);
      else
         ctptr->IconPtr = ConfigIconFor (ctptr->ContentTypePtr, 0, 0);
   }
}

/*****************************************************************************/
/*
Using the hash table this function searches the list of file suffixes (types,
extensions) and content-types, returning a pointer to the content-type string
and if supplied with a content-type structure fills out the appropriate
fields.  Wildcarded file types are always stored in the list beginning with
hash table zero (i.e. [0]).
*/ 

char* ConfigContentType
(
CONTENT_TYPE *ciptr,
char *SuffixPtr
)
{
   BOOL  CheckedForWildcards;
   char  *cptr, *sptr;
   unsigned long  HashValue;
   CONTENT_TYPE  *ctptr;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (WATCHALL, WATCH_MOD_CONFIG,
                 "ConfigContentType() !&Z", SuffixPtr);

   /* generate an upper-case hash */
   if (*SuffixPtr != '.') SuffixPtr = ".";
   HashValue = 1;
   for (cptr = SuffixPtr; *cptr && *cptr != ';'; cptr++)
      HashValue = ((TOUP(*cptr)*541)^(HashValue*3)) &
                  CONTENT_TYPE_HASH_TABLE_MASK;

   CheckedForWildcards = false;

   if (!(ctptr = Config.cfContent.ContentInfoHashTable[HashValue]))
      ctptr = Config.cfContent.ContentInfoHashTable[0];
   while (ctptr)
   {
      /* if a later type definition was loaded then ignore this one */
      if (ctptr->Superceded)
      {
         if ((ctptr = ctptr->HashCollisionPtr)) continue;
         /* end of collision list, check for wildcarded file types */
         if (!CheckedForWildcards)
         {
            CheckedForWildcards = true;
            ctptr = Config.cfContent.ContentInfoHashTable[0];
         }
         continue;
      }

      /* 'ctptr->SuffixPtr' has already been converted to upper case! */
      cptr = ctptr->SuffixPtr;
      sptr = SuffixPtr;
      while (*cptr && *sptr && *sptr != ';' && *cptr == TOUP(*sptr))
      {
         if (*cptr != '*')
         {
            /* not a wildcard */
            cptr++;
            sptr++;
            if (*cptr != '*') continue;
         }
         /* consecutive wildcards are the same as a single wildcard */
         while (*cptr && *cptr == '*') cptr++;
         if (*cptr)
         {
            /* find first matching the character following the wildcard */
            while (*sptr && *sptr != ';' && TOUP(*sptr) != *cptr) sptr++;
            continue;
         }
         /* wildcard at end of list file type, matches all following */
         while (*sptr && *sptr != ';') sptr++;
      }

      if (*cptr || (*sptr && *sptr != ';'))
      {
         /* didn't match, traversing the hash-collision list */
         if ((ctptr = ctptr->HashCollisionPtr)) continue;
         /* end of collision list, check for wildcarded file types */
         if (!CheckedForWildcards)
         {
            CheckedForWildcards = true;
            ctptr = Config.cfContent.ContentInfoHashTable[0];
         }
         continue;
      }

      /**********/
      /* match! */
      /**********/

      /* if just getting a pointer to a content type then just return that */
      if (!ciptr)
      {
         if (WATCH_MODULE(WATCH_MOD_CONFIG))
            WatchThis (WATCHALL, WATCH_MOD_CONFIG, "!&Z",
                       ctptr->ContentTypePtr);
         return (ctptr->ContentTypePtr);
      }

      ciptr->TypeUnknown = false;
      ciptr->TypeText = ctptr->TypeText;
      ciptr->IconPtr = ctptr->IconPtr;
      ciptr->ContentTypePtr = ctptr->ContentTypePtr;
      ciptr->AutoScriptNamePtr = ctptr->AutoScriptNamePtr;
      ciptr->DescriptionPtr = ctptr->DescriptionPtr;
      ciptr->FtpMode = ctptr->FtpMode;
      ciptr->PutRFM = ctptr->PutRFM;

      if (WATCH_MODULE(WATCH_MOD_CONFIG))
         WatchThis (WATCHALL, WATCH_MOD_CONFIG, "!UL !UL !&Z !&Z !&Z",
                    ciptr->FtpMode, ciptr->PutRFM, ciptr->ContentTypePtr,
                    ciptr->AutoScriptNamePtr, ciptr->DescriptionPtr);

      return (ctptr->ContentTypePtr);
   }

   /*************/
   /* no match! */
   /*************/

   /* if just getting a pointer to a content type then just return that */
   if (!ciptr)
   {
      if (WATCH_MODULE(WATCH_MOD_CONFIG))
         WatchThis (WATCHALL, WATCH_MOD_CONFIG, "!&Z",
                    ConfigContentTypeUnknown);
      return (ConfigContentTypeUnknown);
   }

   ciptr->TypeUnknown = true;
   ciptr->TypeText = false;
   ciptr->IconPtr = ConfigUnknownIconPtr;
   ciptr->ContentTypePtr = ConfigContentTypeUnknown;
   ciptr->FtpMode = ciptr->PutRFM = 0;
   ciptr->AutoScriptNamePtr = ciptr->DescriptionPtr = "";
   return (ConfigContentTypeUnknown);
}

/****************************************************************************/
/*
Compare two MIME content-types where only the type is compared (i.e. only the
"text/html" from something like "text/html;charset=ISO8859-5").  It works much
the same as strsame(), except a semi-colon or white-space in either string will
terminate a comparison, as will an exhausted count value.
*/ 
 
BOOL ConfigSameContentType
(
char *sptr1,
char *sptr2,
int count
)
{
   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (WATCHALL, WATCH_MOD_CONFIG,
                 "ConfigSameContentType() !&Z !&Z !SL",
                 sptr1, sptr2, count);

   if (!sptr1 || !sptr2) return (false);

   while (*sptr1 && *sptr1 != ';' && !ISLWS(*sptr1) &&
          *sptr2 && *sptr2 != ';' && !ISLWS(*sptr2))
   {
      if (TOUP(*sptr1++) != TOUP(*sptr2++)) return (false);
      if (count)
         if (!--count) return (true);
   }
   if ((!*sptr1 && (!*sptr2 || *sptr2 == ';')) ||
       (!*sptr2 && (!*sptr1 || *sptr1 == ';')))
      return (true);
   else
      return (false);
}
 
/*****************************************************************************/
/*
Add a URL for an icon corresponding to the mime content type.

Format:   "AddIcon <URL> <alternative-text> <content-type-template>"

Examples: "AddIcon /icon/httpd/text.xbm [TXT] text/plain"
          "AddIcon /icon/httpd/doc.xbm [HTM] text/html"
          "AddIcon /icon/httpd/image.xbm [IMG] image/jpeg"

The template can contain a wildcard in place of a string in either side of the 
template slash.  In this case the wildcard matches any string on that side.

The directive is stored as a linked-list of structures of dynamically
allocated memory containing a reformatted version of the directive string,
including a complete HTML anchor for the URL. Function ConfigIconFor()
searches this list to return a pointer to the anchor. A hash table is used to
more rapidy index into the list.
*/ 

ConfigAddIcon
(
META_CONFIG *mcptr,
char *pptr,
char *TypePtr,
BOOL FromMimeTypes
)
{
   static char  ProblemParameter [] = "Parameter confusing";

   int  Count = 0;
   unsigned long  HashValue;
   char  *cptr, *sptr,
         *AltTextPtr,
         *IconUrlPtr,
         *ContentTypePtr;
   CONFIG_STRUCT  *cfptr;
   ICON_TYPE  *itptr, *hitptr;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (WATCHALL, WATCH_MOD_CONFIG,
                 "ConfigAddIcon() !&Z !&Z !UL", pptr, TypePtr, FromMimeTypes);

   /* get a pointer to the meta-config data */
   cfptr = mcptr->ConfigMetaPtr;

   IconUrlPtr = pptr;
   while (*pptr && ISLWS(*pptr)) pptr++;
   if (!*pptr) return;
   while (*pptr && !ISLWS(*pptr)) pptr++;
   /* storing the icon URI twice, as the URI plus within the <IMG..> */
   Count = (pptr - IconUrlPtr) * 2;
   if (*pptr) *pptr++ = '\0';

   /* alternative text */
   while (*pptr && ISLWS(*pptr)) pptr++;
   AltTextPtr = pptr;
   while (*pptr && !ISLWS(*pptr))
   {
      /* underscores represent spaces! (especially for the "blank" icon) */
      if (*pptr == '_') *pptr = ' ';
      pptr++;
   }
   /* storing the alternate text twice, as it is plus within the <IMG..> */
   Count += (pptr - AltTextPtr) * 2;
   if (*pptr) *pptr++ = '\0';

   /* content-type  */
   if (TypePtr) pptr = TypePtr;
   while (*pptr && ISLWS(*pptr)) pptr++;
   ContentTypePtr = pptr;
   /* force to lower case to save a TOLO() in ConfigIconFor() */
   for ( /* above */ ; *pptr && !ISLWS(*pptr); pptr++)
      *pptr = TOLO(*pptr);
   Count += pptr - ContentTypePtr;
   if (*pptr) *pptr = '\0';

   if (!*IconUrlPtr && *IconUrlPtr != '/' ||
       !*AltTextPtr ||
       !*ContentTypePtr || !strchr(ContentTypePtr, '/'))
   {
      MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemParameter);
      return;
   }

   /* plus structure overhead, plus the HTML IMG element used below */
   Count += cfptr->cfContent.IconStructOverhead + 48;
   itptr = (ICON_TYPE*)VmGet (Count);                  

   itptr->FromMimeTypes = FromMimeTypes;

   sptr = (char*)itptr + cfptr->cfContent.IconStructOverhead;

   itptr->ContentTypePtr = sptr;
   for (cptr = ContentTypePtr; *cptr; *sptr++ = *cptr++);
   *sptr++ = '\0';

   itptr->IconUriPtr = sptr;
   for (cptr = IconUrlPtr; *cptr; *sptr++ = *cptr++);
   *sptr++ = '\0';

   itptr->AltTextPtr = sptr;
   for (cptr = AltTextPtr; *cptr; *sptr++ = *cptr++);
   *sptr++ = '\0';

   itptr->IconUrlPtr = sptr;
   sprintf (sptr, "<img align=\"top\" border=\"0\" src=\"%s\" alt=\"%s\">",
            IconUrlPtr, AltTextPtr);

   for (hitptr = Config.cfContent.IconListHeadPtr;
        hitptr;
        hitptr = hitptr->NextPtr)
   {
      if (strsame (hitptr->ContentTypePtr, ContentTypePtr, -1))
      {
         hitptr->Superceded = true;
         break;
      }
   }

   /* add to list */
   if (!cfptr->cfContent.IconListHeadPtr)
      cfptr->cfContent.IconListHeadPtr = itptr; 
   else
      cfptr->cfContent.IconListTailPtr->NextPtr = itptr; 
   cfptr->cfContent.IconListTailPtr = itptr;
   itptr->NextPtr = NULL;

   /* generates a lower-case hash */
   HashValue = 1;
   for (cptr = ContentTypePtr; *cptr; cptr++)
      HashValue = (((*cptr)*541)^(HashValue*3)) &
                  ICON_HASH_TABLE_MASK;
   if (cfptr->cfContent.IconHashTable[HashValue])
   {
      /* add to the hash-collision list */
      for (hitptr = cfptr->cfContent.IconHashTable[HashValue];
           hitptr->HashCollisionPtr;
           hitptr = hitptr->HashCollisionPtr);
      hitptr->HashCollisionPtr = itptr;
   }
   else
      cfptr->cfContent.IconHashTable[HashValue] = itptr;
}

/*****************************************************************************/
/*
Using the hash table this function searches the icons for one corresponding to
the supplied mime content type. The directive content type and associated HTML
anchor (containing the original configuration-supplied URL) is stored as an
list of structures dynamically allocated memory containing a string.
*/

char* ConfigIconFor
(
char *ContentType,
char **IconUriPtrPtr,
char **AltTextPtrPtr
)
{
   static BOOL  DefaultIconFlipFlop;
   static char  IconNotFound [] = "<font color=\"#ff0000\"><b>[?]</b></font>";

   char  ch;
   char  *cptr, *sptr,
         *AltTextPtr, *IconUriPtr;
   unsigned long  HashValue;
   ICON_TYPE  *itptr;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (WATCHALL, WATCH_MOD_CONFIG,
                 "ConfigIconFor() !&Z !&X !&X",
                 ContentType, IconUriPtrPtr, AltTextPtrPtr);

   /* generates a lower-case hash */
   HashValue = 1;
   for (cptr = ContentType; *cptr && *cptr != ';' && !ISLWS(*cptr); cptr++)
      HashValue = ((TOLO(*cptr)*541)^(HashValue*3)) & ICON_HASH_TABLE_MASK;
   ch = *cptr;
   *cptr = '\0';

   for (itptr = Config.cfContent.IconHashTable[HashValue];
        itptr;
        itptr = itptr->HashCollisionPtr)
   {
      if (itptr->Superceded) continue;
      /* only need to match the content types if there was a collision */
      if (itptr->HashCollisionPtr)
         if (!StringMatch (NULL, ContentType, itptr->ContentTypePtr))
            continue;
      if (IconUriPtrPtr) *IconUriPtrPtr = itptr->IconUriPtr;
      if (AltTextPtrPtr) *AltTextPtrPtr = itptr->AltTextPtr;
      *cptr = ch;
      return (itptr->IconUrlPtr);
   }
   *cptr = ch;

   if (ConfigDefaultIconPtr && (IconUriPtrPtr || AltTextPtrPtr))
   {
      if (DefaultIconFlipFlop = !DefaultIconFlipFlop)
      {
         ConfigIconFor (ConfigContentTypeDefaultIcon, &IconUriPtr, &AltTextPtr);
         if (IconUriPtrPtr) *IconUriPtrPtr = IconUriPtr;
         if (AltTextPtrPtr) *AltTextPtrPtr = AltTextPtr;
         return (ConfigDefaultIconPtr);
      }
      if (IconUriPtrPtr) *IconUriPtrPtr = "";
      if (AltTextPtrPtr) *AltTextPtrPtr = "";
   }
   if (ConfigDefaultIconPtr) return (ConfigDefaultIconPtr);
   return (IconNotFound);
}

/*****************************************************************************/
/*
Accept or reject the client connection.  Lists of hosts must be a comma-
separated string.  A wildcard '*' in a domain specification matches any string 
that occurs between the dots.
Example: "host1.network1.domain1,*.network2.domain1,*.*.domain2". 
*/ 

BOOL ConfigAcceptClientHostName
(
char *ClientIpAddressString,
char *ClientHostName
)
{
   char  *cptr, *sptr;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (WATCHALL, WATCH_MOD_CONFIG,
                 "ConfigAcceptConnection() !&Z", ClientHostName);

   if (!Config.cfServer.AcceptHostsPtr &&
       !Config.cfServer.RejectHostsPtr)
      return (true);

   if (!ClientHostName[0] || ClientHostName[0] == '?') return (false);

   /******************/
   /* hosts accepted */
   /******************/

   if (Config.cfServer.AcceptHostsPtr)
   {
      sptr = Config.cfServer.AcceptHostsPtr;
      while (*sptr)
      {
         if (isdigit(*sptr))
            cptr = ClientIpAddressString;
         else
            cptr = ClientHostName;
         while (*cptr)
         {
            if (*sptr == STRING_LIST_CHAR) break;
            if (*sptr == '*')
            {
               while (*sptr && *sptr == '*' && *sptr != STRING_LIST_CHAR)
                  sptr++;
               while (*cptr && *cptr != *sptr) cptr++;
            }
            if (TOLO(*cptr) != TOLO(*sptr)) break;
            if (*cptr) cptr++;
            if (*sptr) sptr++;
         }
         if (!*cptr && (!*sptr || *sptr == STRING_LIST_CHAR)) break;
         while (*sptr && *sptr != STRING_LIST_CHAR) sptr++;
         if (*sptr) sptr++;
      }
      /* if it was NOT found then reject the connection request */
      if (!(!*cptr && (!*sptr || *sptr == STRING_LIST_CHAR)))
         return (false);
   }

   /******************/
   /* hosts rejected */
   /******************/

   if (Config.cfServer.RejectHostsPtr)
   {
      sptr = Config.cfServer.RejectHostsPtr;
      while (*sptr)
      {
         if (isdigit(*sptr))
            cptr = ClientIpAddressString;
         else
            cptr = ClientHostName;
         while (*cptr)
         {
            if (*sptr == STRING_LIST_CHAR) break;
            if (*sptr == '*')
            {
               while (*sptr && *sptr == '*' && *sptr != STRING_LIST_CHAR)
                  sptr++;
               while (*cptr && *cptr != *sptr) cptr++;
            }
            if (TOLO(*cptr) != TOLO(*sptr)) break;
            if (*cptr) cptr++;
            if (*sptr) sptr++;
         }
         if (!*cptr && (!*sptr || *sptr == STRING_LIST_CHAR)) break;
         while (*sptr && *sptr != STRING_LIST_CHAR) sptr++;
         if (*sptr) sptr++;
      }
      /* if it WAS found then reject the connection request */
      if (!*cptr && (!*sptr || *sptr == STRING_LIST_CHAR))
         return (false);
   }

   /* accept the connection */
   return (true);
}

/*****************************************************************************/
/*
Set directory access booleans.  Allowed values OFF, ON, SELECTIVE.
*/

ConfigSetDirAccess
(
META_CONFIG *mcptr,
char *pptr
)
{
   static char  ProblemParameter [] = "Parameter confusing";

   CONFIG_STRUCT  *cfptr;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (WATCHALL, WATCH_MOD_CONFIG,
                 "ConfigSetDirAccess() !&Z", pptr);

   /* get a pointer to the meta-config data */
   cfptr = mcptr->ConfigMetaPtr;

   if (strsame (pptr, "YES", 3) ||
       strsame (pptr, "ON", 2) ||
       strsame (pptr, "ENABLED", 7))
   {
      cfptr->cfDir.Access = true;
      cfptr->cfDir.AccessSelective = false;
   }
   else
   if (strsame (pptr, "NO", 2) ||
       strsame (pptr, "OFF", 3) ||
       strsame (pptr, "DISABLED", 8))
      cfptr->cfDir.Access = cfptr->cfDir.AccessSelective = false;
   else
   if (strsame (pptr, "SELECTIVE", 9))
      cfptr->cfDir.Access = cfptr->cfDir.AccessSelective = true;
   else
      MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemParameter);
}

/*****************************************************************************/
/*
Set directory README file booleans.  Allowed values OFF, TOP, BOTTOM.
*/

ConfigSetDirReadMe
(
META_CONFIG *mcptr,
char *pptr
)
{
   static char  ProblemParameter [] = "Parameter confusing";

   CONFIG_STRUCT  *cfptr;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (WATCHALL, WATCH_MOD_CONFIG,
                 "ConfigSetDirReadMe() !&Z", pptr);

   /* get a pointer to the meta-config data */
   cfptr = mcptr->ConfigMetaPtr;

   if (strsame (pptr, "NO", 2) ||
       strsame (pptr, "OFF", 3) ||
       strsame (pptr, "DISABLED", 8))
      cfptr->cfDir.ReadMeBottom = cfptr->cfDir.ReadMeTop = false;
   else
   if (strsame (pptr, "BOTTOM", 6))
   {
      cfptr->cfDir.ReadMeTop = false;
      cfptr->cfDir.ReadMeBottom = true;
   }
   else
   if (strsame (pptr, "TOP", 3))
   {
      cfptr->cfDir.ReadMeTop = true;
      cfptr->cfDir.ReadMeBottom = false;
   }
   else
      MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemParameter);
}

/*****************************************************************************/
/*
Add a "read-me" file name.

Format:   "ReadMeFile file.suffix"

Examples: "ReadMeFile README.HTML"
          "ReadMeFile README.TXT"
          "ReadMeFile README."

The directive is stored as an array of pointers to dynamically allocated 
memory containing the "read-me" file name.  Function ConfigReadMeFile() gets 
these by index number.
*/

ConfigSetDirReadMeFile
(
META_CONFIG *mcptr,
char *pptr
)
{
   static char  ProblemParameter [] = "Parameter confusing",
                ProblemReadMeMax [] = "Maximum read-me exceeded";

   int  status,
        Count;
   char  *NamePtr;
   CONFIG_STRUCT  *cfptr;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (WATCHALL, WATCH_MOD_CONFIG,
                 "ConfigSetDirReadMeFile() !&Z", pptr);

   /* get a pointer to the meta-config data */
   cfptr = mcptr->ConfigMetaPtr;

   if (cfptr->cfDir.ReadMeFileCount >= CONFIG_README_FILES_MAX)
   {
      MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemReadMeMax);
      return;
   }

   NamePtr = pptr;
   while (*pptr && !ISLWS(*pptr))
   {
      *pptr = TOUP(*pptr);
      pptr++;
   }
   Count = pptr - NamePtr;
   *pptr = '\0';

   if (!*NamePtr)
   {
      MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemParameter);
      return;
   }

   cfptr->cfDir.ReadMeFileArray[cfptr->cfDir.ReadMeFileCount] = VmGet(Count+1);

   strcpy (cfptr->cfDir.ReadMeFileArray[cfptr->cfDir.ReadMeFileCount], NamePtr);
   cfptr->cfDir.ReadMeFileCount++;
}

/*****************************************************************************/
/*
Return a pointer to the "read-me" file name stored against the index number of 
the array.  If none exists return a null string.  The calling function would 
use this by stepping through the index numbers 0 to n, until the null string 
was returned indicating the possible "read-me" file names were exhausted.
*/

char* ConfigReadMeFile (int Number)

{
   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (WATCHALL, WATCH_MOD_CONFIG,
                 "ConfigReadMeFile !UL", Number);

   if (Number >= 0 && Number < Config.cfDir.ReadMeFileCount)
      return (Config.cfDir.ReadMeFileArray[Number]);
   else
      return ("");
}

/*****************************************************************************/
/*
Set OPCOM target and message categories.
*/

ConfigSetOpcom
(
META_CONFIG *mcptr,
char *cptr,
char *sptr
)
{
   static char  ProblemParameter [] = "Parameter confusing";

   int  idx;
   CONFIG_STRUCT  *cfptr;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (WATCHALL, WATCH_MOD_CONFIG,
                 "ConfigSetOpcom() !&Z !&Z", cptr, sptr);

   /* get a pointer to the meta-config data */
   cfptr = mcptr->ConfigMetaPtr;

   if (strsame (cptr, "OpcomTarget", -1))
   {
      for (idx = 0; ConfigOpcomTarget[idx].Number >= 0; idx++)
         if (strsame (ConfigOpcomTarget[idx].Name, sptr, -1)) break;
      if (ConfigOpcomTarget[idx].Number >= 0)
      {
         cfptr->cfOpcom.Target =
            ConfigOpcomTarget[cfptr->cfOpcom.Index = idx].Number;
         return;
      }
      MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemParameter);
      return;
   }

   if (strsame (cptr, "OpcomAdmin", -1))
   {
      if (MetaConSetBoolean (mcptr, sptr))
         cfptr->cfOpcom.Messages |= OPCOM_ADMIN;
   }
   else
   if (strsame (cptr, "OpcomAuthorization", -1))
   {
      if (MetaConSetBoolean (mcptr, sptr))
         cfptr->cfOpcom.Messages |= OPCOM_AUTHORIZATION;
   }
   else
   if (strsame (cptr, "OpcomControl", -1))
   {
      if (MetaConSetBoolean (mcptr, sptr))
         cfptr->cfOpcom.Messages |= OPCOM_CONTROL;
   }
   else
   if (strsame (cptr, "OpcomHTTPd", -1))
   {
      if (MetaConSetBoolean (mcptr, sptr))
         cfptr->cfOpcom.Messages |= OPCOM_HTTPD;
   }
   else
   if (strsame (cptr, "OpcomProxyMaint", -1))
   {
      if (MetaConSetBoolean (mcptr, sptr))
         cfptr->cfOpcom.Messages |= OPCOM_PROXY_MAINT;
   }
   else
      MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemParameter);
}

/*****************************************************************************/
/*
Proctoring ensures a minimum number of a particular script or scripting
environment (e.g. RTE) exists at all times.  It is implemented by
DclScriptProctor().  The format is

  <min-count>[+<idle-count>] <pattern> <activation> <notepad>

  2+1 (*pyrte) /py-bin/proctor
  1 (*pyrte)/py-bin/whatever /py-bin/proctor  notepad-string
  3 /cgiplus-bin/another /cgiplus-bin/another?proctor

where min-count is the minimum number of the script or environment should be
present at all times, the optional idle-count the minimum idle at any one time,
pattern is a string matching pattern used to match with the script URL (e.g.
"($cgi_exe:pyrte.exe)*"), activation is the 'do-nothing' URI used to activate
the script or scripting environment, and notepad an optional string that can be
detected using mapping.  These are stored as four null-terminated strings.
*/ 

ConfigSetScriptProctor
(
META_CONFIG *mcptr,
char *pptr
)
{
   static char  ProblemParameter [] = "Proctor parameter confusing",
                ProblemProctorMax [] = "Maximum proctor exceeded";

   int  len;
   char  *cptr, *sptr;
   CONFIG_STRUCT  *cfptr;
   struct ConfigProctorStruct  *psptr;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (WATCHALL, WATCH_MOD_CONFIG,
                 "ConfigSetScriptProctor() !&Z", pptr);

   if (*pptr == '#') return;

   cfptr = mcptr->ConfigMetaPtr;

   if (cfptr->cfScript.ProctorCount >= CONFIG_SCRIPT_PROCTOR_MAX)
   {
      MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemProctorMax);
      return;
   }

   psptr = &cfptr->cfScript.Proctor[cfptr->cfScript.ProctorCount];
   sptr = VmGet(strlen(pptr)+4+1);

   if (*pptr == '+')
      psptr->NumberIdle = atoi(++pptr);
   else
      psptr->NumberMin = atoi(pptr);
   while (*pptr && isdigit(*pptr)) pptr++;
   if (*pptr == '+')
   {
      psptr->NumberIdle = atoi(++pptr);
      while (*pptr && isdigit(*pptr)) pptr++;
   }
   while (ISLWS(*pptr)) pptr++;

   psptr->RunTimePtr = sptr;
   if (*pptr == '(')
   {
      /* run-time pattern */
      pptr++;
      while (*pptr && !ISLWS(*pptr) && *pptr != ')') *sptr++ = *pptr++;
      if (*pptr == ')') pptr++;
   }
   *sptr++ ='\0';

   /* script pattern (no white-space between this and any run-time!) */
   psptr->ScriptPtr = sptr;
   while (*pptr && !ISLWS(*pptr)) *sptr++ = *pptr++;
   *sptr++ ='\0';

   /* activation script */
   while (ISLWS(*pptr)) pptr++;
   psptr->ActivatePtr = sptr;
   while (*pptr && !ISLWS(*pptr)) *sptr++ = *pptr++;
   *sptr++ ='\0';

   /* optional mapping notepad (to end of line) */
   while (ISLWS(*pptr)) pptr++;
   psptr->NotePadPtr = sptr;
   while (*pptr) *sptr++ = *pptr++;
   *sptr = '\0';
   psptr->NotePadLength = sptr - psptr->NotePadPtr;

   if (*psptr->ScriptPtr != '*' &&
       ((!*psptr->RunTimePtr && !*psptr->ScriptPtr) || !*psptr->ActivatePtr))
   {
      /* must have run-time and/or script along with activation */
      MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemParameter);
      psptr->Problem = true;
   }

   cfptr->cfScript.ProctorCount++;
}

/*****************************************************************************/
/*
Add a script type.

Format:   "file-type verb"

Examples: ".PL PERL"
          ".PL $PERL_EXE:PERL.EXE"
          ".CGI $HT_EXE:CGIPERLUS.EXE"

Function DclFindScript() uses this information. The array entries comprise a
reconstructed string from the directive.  The verb part of the directive can
have a leading '@' or '$' indicating that the verb should be created before
invoking the script.  If not having these leading characters the verb is
considered to be globally available.  The leading '@' and '$' verbs are
reconstructed from "$perl_exe:perl.exe" into "PERL=\"$perl_exe:perl.exe\"". 
From this the DCL module creates an excecutable DCL command sequence.
*/ 

ConfigSetScriptRunTime
(
META_CONFIG *mcptr,
char *pptr
)
{
   static char  ProblemParameter [] = "Parameter confusing",
                ProblemRunTimeMax [] = "Maximum runtime exceeded";

   char  *cptr, *sptr;
   CONFIG_STRUCT  *cfptr;
   struct ConfigRunTimeStruct  *rtptr;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (WATCHALL, WATCH_MOD_CONFIG,
                 "ConfigSetScriptRunTime() !&Z", pptr);

   if (*pptr == '#') return;

   cfptr = mcptr->ConfigMetaPtr;

   if (cfptr->cfScript.RunTimeCount >= CONFIG_SCRIPT_RUNTIME_MAX)
   {
      MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemRunTimeMax);
      return;
   }
   rtptr = &cfptr->cfScript.RunTime[cfptr->cfScript.RunTimeCount];
   sptr = rtptr->StringPtr = VmGet(strlen(pptr)+3+1);

   if (*pptr != '.') *sptr++ = '.';
   while (*pptr && !ISLWS(*pptr) && *pptr != ';') *sptr++ = TOUP(*pptr++);
   *sptr++ = ';';
   rtptr->FileTypeLength = sptr - rtptr->StringPtr;
   while (*pptr && (ISLWS(*pptr) || *pptr == ';')) pptr++;
   if (!*pptr)
   {
      MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemParameter);
      return;
   }
   *sptr++ = ' ';
   while (*pptr) *sptr++ = *pptr++;
   *sptr = '\0';

   cfptr->cfScript.RunTimeCount++;
}

/*****************************************************************************/
/*
Set directory access booleans.  Allowed values OFF, ON, EMAIL.
*/

ConfigSetServerSignature
(
META_CONFIG *mcptr,
char *pptr
)
{
   static char  ProblemParameter [] = "Parameter confusing";

   CONFIG_STRUCT  *cfptr;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (WATCHALL, WATCH_MOD_CONFIG,
                 "ConfigSetServerSignature() !&Z", pptr);

   /* get a pointer to the meta-config data */
   cfptr = mcptr->ConfigMetaPtr;

   if (strsame (pptr, "YES", 3) ||
       strsame (pptr, "ON", 2) ||
       strsame (pptr, "ENABLED", 7))
      cfptr->cfServer.Signature = CONFIG_SERVER_SIGNATURE_ON;
   else
   if (strsame (pptr, "NO", 2) ||
       strsame (pptr, "OFF", 3) ||
       strsame (pptr, "DISABLED", 8))
      cfptr->cfServer.Signature = CONFIG_SERVER_SIGNATURE_OFF;
   else
   if (strsame (pptr, "EMAIL", 5))
      cfptr->cfServer.Signature = CONFIG_SERVER_SIGNATURE_EMAIL;
   else
      MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemParameter);
}

/*****************************************************************************/
/*
Add a welcome (home) page file name.

Format:   "Welcome file.suffix"

Examples: "Welcome HOME.HTML"
          "Welcome HOME.HTM"
          "Welcome HOME.MENU"

The directive is stored as an array of pointers to dynamically allocated 
memory containing the home page file name.  Function ConfigHomePage() gets 
these by index number.
*/ 

ConfigSetWelcome
(
META_CONFIG *mcptr,
char *pptr
)
{
   static char  ProblemWelcomeMax [] = "Maximum welcome exceeded";

   int  status,
        Count;
   char  *WelcomePtr;
   CONFIG_STRUCT  *cfptr;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (WATCHALL, WATCH_MOD_CONFIG,
                 "ConfigSetWelcome() !&Z", pptr);

   /* get a pointer to the meta-config data */
   cfptr = mcptr->ConfigMetaPtr;

   if (cfptr->cfContent.HomePageCount >= CONFIG_HOME_PAGES_MAX)
   {
      MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemWelcomeMax);
      return;
   }

   WelcomePtr = pptr;
   while (*pptr && !ISLWS(*pptr))
   {
      *pptr = TOUP(*pptr);
      pptr++;
   }
   Count = pptr - WelcomePtr;
   *pptr = '\0';

   cfptr->cfContent.HomePageArray[cfptr->cfContent.HomePageCount] =
      VmGet (Count+1);

   strcpy (cfptr->cfContent.HomePageArray[cfptr->cfContent.HomePageCount],
           WelcomePtr);
   cfptr->cfContent.HomePageCount++;
}

/*****************************************************************************/
/*
Return a pointer to the home page (welcome) file name stored against the index 
number of the array.  If none exists return a null string.  The calling 
function would use this by stepping through the index numbers 0 to n, until 
the null string was returned indicating the possible home page file names were 
exhausted.
*/

char* ConfigHomePage (int Number)

{
   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (WATCHALL, WATCH_MOD_CONFIG, "ConfigHomePage !UL", Number);

   if (Number >= 0 && Number < Config.cfContent.HomePageCount)
      return (Config.cfContent.HomePageArray[Number]);
   else
      return ("");
}

/*****************************************************************************/
/*
A server administration report on the server's configuration. This function
just wraps the reporting function, loading a temporary database if necessary
for reporting from the configuration file.
*/ 

ConfigReport
(
REQUEST_STRUCT *rqptr,
BOOL UseServerDatabase
)
{
   int  status;
   META_CONFIG  *mcptr;

   /*********/
   /* begin */
   /*********/

   if (WATCHMOD (rqptr, WATCH_MOD_CONFIG))
      WatchThis (WATCHITM(rqptr), WATCH_MOD_CONFIG,
                 "ConfigReport() !&F !UL",  &ConfigReport, UseServerDatabase);

   if (UseServerDatabase)
      ConfigReportNow (rqptr, MetaGlobalConfigPtr);
   else
   {
      status = ConfigLoad (&mcptr);
      if (VMSnok (status))
      {
         /* severe error reported */
         rqptr->rqResponse.HttpStatus = 403;
         ErrorGeneral (rqptr, mcptr->LoadReport.TextPtr, FI_LI);
      }
      else
         ConfigReportNow (rqptr, mcptr);
      MetaConUnload (&mcptr, NULL);
   }

   AdminEnd (rqptr);
}

/*****************************************************************************/
/*
Return a report on the HTTPd server's configuration ... now!  This function
blocks while executing.
*/ 

ConfigReportNow
(
REQUEST_STRUCT *rqptr,
META_CONFIG *mcptr
)
{
/* macro to push booleans onto the parameter list */
#define REP_ENDIS(b) \
if (b) *vecptr++ = "[enabled]"; else *vecptr++ = "[disabled]";

/* report a string, or if empty as "(none)" */
#define REP_NOTNONE(s) \
if (s[0]) *vecptr++ = s; else *vecptr++ = ConfigNoteNone;

   static char
      NoRestriction [] = "<i>(no restriction)</i>\n",
      ServerOnly [] = "<i>(this server only)</i>\n";

   static char ReportGeneralFao [] =
"<p><table class=\"ctgry\">\n\
<tr><th class=\"ctttl\">GMT</th></tr>\n\
<tr><td>\n\
<table class=\"rghtlft\">\n\
<tr><th>Offset:</th><td>!AZ</td></tr>\n\
<tr><th>Current:</th><td>!AZ</td></tr>\n\
</table>\n\
</td></tr>\n\
</table>\n\
\
<p><table class=\"ctgry\">\n\
<tr><th class=\"ctttl\">General</th></tr>\n\
<tr><td>\n\
<table class=\"rghtlft\">\n\
<tr><th>Instance Max:</th><td>!&@</td>\
<td><i>per-node servers</i></tr>\
<tr><th>Instance Passive:</th><td colspan=\"2\">!AZ</td></tr>\n\
<tr><th>Connect Max:</th><td>!UL</td>\
<td><i>connections</i></tr>\
<tr><th>Process Max:</th><td>!UL</td>\
<td><i>requests being processed</i></tr>\
<tr><th>Listen Backlog:</th><td>!UL</td>\
<td><i>at socket</i></tr>\
<tr><th>Request History:</th><td>!UL</td>\
<td><i>requests</i></td></tr>\n\
<tr><th>Activity History:</th><td>!UL</td>\
<td><i>days</i></td></tr>\n\
<tr><th>Charset Default:</th><td colspan=\"2\">!AZ</td></tr>\n\
<tr><th>Charset Convert:</th>\
<td colspan=\"2\">!AZ</td></tr>\
<tr><th>Monitor:</th><td colspan=\"2\">!AZ</td></tr>\n\
<tr><th>Regular Expressions:</th><td colspan=\"2\">!&@</td></tr>\n\
<tr><th>Entity Tag:</th><td colspan=\"2\">!AZ</td></tr>\n\
<tr><th>Pipeline Requests:</th><td colspan=\"2\">!AZ</td></tr>\n\
<tr><th>HTTP TRACE:</th><td colspan=\"2\">!AZ</td></tr>\n\
<tr><th>WWW Implied:</th><td colspan=\"2\">!AZ</td></tr>\n\
<tr><th>GZIP Accept:</th><td>!UL</td>\
<tr><th>GZIP Flush:</th><td>!&@</td>\
<td><i>interval[,initial] seconds</i></td></tr>\n\
<tr><th>GZIP Response:</th><td>!&@</td>\
<td><i>level[,memory,window]</i></td></tr>\n\
<tr><th>IP Port:</th><td>!UL</td></tr>\n\
<tr><th>StreamLF:</th><td>!UL</td>\
<td><i>kBytes</i></td></tr>\n\
<tr><th>Search Script:</th><td colspan=\"2\">!AZ</td></tr>\n\
<tr><th>Search Script Exclude:</th><td>!AZ</td>\n\
<td><i>file type</i></td></tr>\n\
<tr><th>PUT/POST Max:</th><td>!UL</td>\
<td><i>kBytes</i></td></tr>\n\
<tr><th>PUT/POST binary RFM:</th><td>!AZ</td></tr>\n\
<tr><th>PUT/POST Files:</th><td>!UL</td>\
<td><i>version limit</i></td></tr>\n\
<tr><th>/~username/ Cache Entries:</th><td>!UL</td>\
<td><i>user names</i></td></tr>\n\
<tr><th>Persona Cache Entries:</th><td>!UL</td>\
<td><i>users</i></td></tr>\n\
</table>\n\
</td></tr>\n\
</table>\n\
\
<p><table class=\"ctgry\">\n\
<tr><th class=\"ctttl\">Host Resolution</th></tr>\n\
<tr><td>\n\
<table class=\"rghtlft\">\n\
<tr><th>Lookup Client:</th><td colspan=\"2\">!AZ</td></tr>\n\
<tr><th>Life-Time:</th><td colspan=\"2\">!AZ</td></tr>\n\
<tr><th>Retry:</th><td colspan=\"2\">!UL</td></tr>\n\
</table>\n\
</td></tr>\n\
</table>\n\
\
<p><table class=\"ctgry\">\n\
<tr><th class=\"ctttl\">Log</th></tr>\n\
<tr><td>\n\
<table class=\"rghtlft\">\n\
<tr><th>Logging:</th><td>!AZ</td></tr>\n\
<tr><th>Format:</th><td>!AZ</td>\
<tr><th>Naming:</th><td>!AZ</td>\
<tr><th>Period:</th><td>!AZ</td>\
<tr><th>Per-Instance:</th><td>!AZ</td>\
<tr><th>Per-Service:</th><td>!AZ</td>\
<tr><th>Per-Service Host Only:</th><td>!AZ</td>\
<tr><th>Write Fail 503:</th><td>!AZ</td>\
<tr><th>File:</th><td>!AZ</td>\
<tr><th>Extend Blocks:</th><td>!UL</td>\
<tr><th>Exclude Hosts:</th><td>!AZ</td></tr>\n\
</table>\n\
</td></tr>\n\
</table>\n\
\
<p><table class=\"ctgry\">\n\
<tr><th class=\"ctttl\">OPCOM</th></tr>\n\
<tr><td>\n\
<table class=\"rghtlft\">\n\
<tr><th>Target:</th><td>!AZ</td></tr>\n\
<tr><th>Admin:</th><td>!AZ</td></tr>\
<tr><th>Authorization:</th><td>!AZ</td></tr>\
<tr><th>Control:</th><td>!AZ</td></tr>\
<tr><th>HTTPd:</th><td>!AZ</td></tr>\
<tr><th>ProxyMaint:</th><td>!AZ</td></tr>\
</table>\n\
</td></tr>\n\
</table>\n\
\
<p><table class=\"ctgry\">\n\
<tr><th class=\"ctttl\">File Cache</th></tr>\n\
<tr><td>\n\
<table class=\"rghtlft\">\n\
<tr><th>Caching:</th><td colspan=\"2\">!AZ</td></tr>\n\
<tr><th>Max Entries:</th><td>!UL</td>\
<td><i>files</i></td></tr>\n\
<tr><th>Max Cache Size:</th><td>!UL</td>\
<td><i>kBytes</i></td></tr>\n\
<tr><th>Max Entry Size:</th><td>!UL</td>\
<td><i>kBytes</i></td></tr>\n\
<tr><th>Guard:</th><td>!AZ</td>\
<td><i>hh:mm:ss</i></td></tr>\n\
<tr><th>Validate:</th><td>!AZ</td></tr>\n\
<tr><th>Frequent /Hits:</th><td>!UL</td></tr>\
<tr><th>/Within:</th><td>!AZ</td></tr>\n\
</table>\n\
</td></tr>\n\
</table>\n\
\
<p><table class=\"ctgry\">\n\
<tr><th class=\"ctttl\">Timeouts</th></tr>\n\
<tr><td>\n\
<table class=\"rghtlft\">\n\
<tr><th>Input:</th><td>!AZ</td>\
<td><i>hh:mm:ss</i></td></tr>\n\
<tr><th>Output:</th><td>!AZ</td></tr>\n\
<tr><th>No-Progress:</th><td>!AZ</td></tr>\n\
<tr><th>Persistent Connection:</th><td>!AZ</td></tr>\n\
<tr><th>HTTP/2 Idle:</th><td>!AZ</td></tr>\n\
</table>\n\
</td></tr>\n\
</table>\n\
\
<p><table class=\"ctgry\">\n\
<tr><th class=\"ctttl\">Buffer Sizes !AZ</th></tr>\n\
<tr><td>\n\
<table class=\"rghtlft\">\n\
<tr><th>DCL <font size=\"-1\">SYS$COMMAND</font>:</th>\
<td>!UL</td></tr>\n\
<tr><th>DCL <font size=\"-1\">SYS$OUTPUT</font>:</th>\
<td>!UL</td><td>(!UL)</td></tr>\n\
<tr><th>DCL <font size=\"-1\">(SYS$OUTPUT) BUFQUO</font>:</th>\
<td>!UL</td><td>(!UL)</td></tr>\n\
<tr><th>DCL <font size=\"-1\">CGIPLUSIN</font>:</th>\
<td>!UL</td></tr>\n\
<tr><th>CGI Header:</th>\
<td>!UL</td></tr>\n\
<tr><th>Network Read:</th><td>!UL</td></tr>\n\
<tr><th>Network Write:</th><td>!UL</td>\
<td>(!UL)</td></tr>\n\
<tr><th>Network File:</th><td>!UL</td>\
<td>(!UL)</td></tr>\n\
<tr><th>Network MTU:</th><td>!UL</td></tr>\n\
<tr><th>Socket SNDBUF:</th><td>!UL</td>\
<td>!AZ</td></tr>\n\
<tr><th>Socket RCVBUF:</th><td>!UL</td>\
<td>!AZ</td></tr>\n\
</table>\n\
</td></tr>\n\
</table>\n"; 

   static char ReportWelcomeFao [] =
"<p><table class=\"ctgry\">\n\
<tr><th class=\"ctttl\">Welcome (Home) Pages</th></tr>\n\
<tr><td>\n\
<table class=\"lftlft\">\n";

   static char ReportHostsFao [] =
"</table>\n\
</td></tr>\n\
</table>\n\
\
<p><table class=\"ctgry\">\n\
<tr><th class=\"ctttl\">Hosts</th></tr>\n\
<tr><td>\n\
<table class=\"rghtlft\">\n\
<tr><th>Accept:</th><td>!AZ</td></tr>\n\
<tr><th>Reject:</th><td>!AZ</td></tr>\n\
</table>\n\
</td></tr>\n\
</table>\n\
\
<p><table class=\"ctgry\">\n\
<tr><th class=\"ctttl\">Server Generated Reports</th></tr>\n\
<tr><td>\n\
<table class=\"rghtlft\">\n\
<tr><th>Server Admin Email:</th>\
<td colspan=\"2\">!&@</td></tr>\n\
<tr><th>Server Signature:</th><td>!&;AZ</td></tr>\n\
<tr><th>Basic Info Only:</th><td>!AZ</td></tr>\n\
<tr><th>&lt;META&gt; Info:</th><td>!AZ</td></tr>\n\
<tr><th>Error Report Path:</th><td colspan=\"2\">!AZ</td></tr>\n\
<tr><th>Error Recommend:</th><td>!AZ</td></tr>\n\
</table>\n\
</td></tr>\n\
</table>\n\
\
<p><table class=\"ctgry\">\n\
<tr><th class=\"ctttl\">Authorization</th></tr>\n\
<tr><td>\n\
<table class=\"rghtlft\">\n\
<tr><th>Cache Entries:</th><td>!UL</td></tr>\n\
<tr><th>Cache Entry Size:</th><td>!UL</td>\
<td><i>bytes</i></td></tr>\n\
<tr><th>Cache Valid:</th><td>!UL</td>\
<td><i>minutes</i></td></tr>\n\
<tr><th>Revalidate User:</th><td>!UL</td>\
<td><i>minutes</i></td></tr>\n\
<tr><th>Failure Limit:</th><td>!UL</td>\
<td><i>attempts</i></td></tr>\n\
<tr><th>Failure Period:</th><td>!AZ</td>\
<td><i>hh:mm:ss</i></td></tr>\n\
<tr><th>Failure Timeout:</th><td>!AZ</td></tr>\n\
<tr><th>Token Entries:</th><td>!SL</td></tr>\n\
<tr><th>Basic</th><td colspan=\"2\">!AZ</td></tr>\n\
<tr><th>Digest:</th><td colspan=\"2\">!AZ</td></tr>\n\
<tr><th>Digest GET lifetime:</th><td>!UL</td>\
<td><i>minutes</i></td></tr>\n\
<tr><th>Digest PUT lifetime:</th><td>!UL</td>\
<td><i>minutes</i></td></tr>\n\
<tr><th>SYSUAF Logon Type:</th>\
<td colspan=\"2\">!AZ</td></tr>\n\
<tr><th>SYSUAF Accept Expired Pwd:</th>\
<td colspan=\"2\">!AZ</td></tr>\n\
<tr><th>SYSUAF Pwd Expired URL:</th>\
<td colspan=\"2\">!AZ</td></tr>\n\
</table>\n\
</td></tr>\n\
</table>\n\
\
<p><table class=\"ctgry\">\n\
<tr><th class=\"ctttl\">Proxy Serving</th></tr>\n\
<tr><td>\n\
<table class=\"rghtlft\">\n\
<tr><th>Proxy Serving:</th>\
<td colspan=\"2\">!AZ</td></tr>\n\
<tr><th>Cache:</th>\
<td colspan=\"2\">!AZ</td></tr>\n\
<tr><th>Unknown Request Fields:</th>\
<td colspan=\"2\">!AZ</td></tr>\n\
<tr><th>Add &quot;Forwarded: by&quot;:</th>\
<td colspan=\"2\">!AZ</td></tr>\n\
<tr><th>Add &quot;X-Forwarded-For:&quot;:</th>\
<td colspan=\"2\">!AZ</td></tr>\n\
<tr><th>Report Events To Log:</th>\
<td colspan=\"2\">!AZ</td></tr>\n\
<tr><th>Report Cache Events To Log:</th>\
<td colspan=\"2\">!AZ</td></tr>\n\
<tr><th>Verify Max:</th><td>!UL</td>\
<td><i>records</i></td></tr>\n\
<tr><th>Host Name Lookup Retry:</th><td>!UL</td>\
<td><i>attempts</i></td></tr>\n\
<tr><th>Connect Timeout:</th><td>!AZ</td>\
<td><i>hh:mm:ss</i></td></tr>\n\
<tr><th>Connect Persist Max:</th><td>!UL</td>\
<td><i>connections</i></td></tr>\n\
<tr><th>Connect Persist Timeout:</th><td>!AZ</td>\
<td><i>hh:mm:ss</i></td></tr>\n\
<tr><th><u>Cache</u></th></tr>\n\
<tr><th>Max Load:</th><td>!UL</td>\
<td><i>kBytes</i></td></tr>\n\
<tr><th>Negative:</th><td>!AZ</td>\
<td><i>hh:mm:ss</i></td></tr>\n\
<tr><th>No Reload:</th><td>!AZ</td>\
</tr>\n\
<tr><th>Reload List:</th><td colspan=\"2\">!AZ</td></tr>\n\
<tr><th>Routine Purge:</th><td>!AZ</td>\
<td><i>hour-of-day</i></td></tr>\n\
<tr><th>Purge List:</th><td colspan=\"2\">!AZ</td></tr>\n\
<tr><th><u>Cache Device</u></th></tr>\n\
<tr><th>Directory Organization:</th><td colspan=\"2\">!AZ</td>\
<tr><th>Usage Check:</th><td>!UL</td>\
<td><i>minutes</i></td></tr>\n\
<tr><th>Usage Max:</th><td>!UL</td>\
<td><i>percent</i></td></tr>\n\
<tr><th>Reduce By:</th><td>!UL</td>\
<td><i>percent</i></td></tr>\n\
</table>\n\
</td></tr>\n\
</table>\n\
\
<p><table class=\"ctgry\">\n\
<tr><th class=\"ctttl\">Scripting  (CGI, DCL & DECnet)</th></tr>\n\
<tr><td>\n\
<table class=\"rghtlft\">\n\
<tr><th>Scripting:</th><td colspan=\"3\">!AZ</td></tr>\n\
<tr><th>Detach Process:</th><td colspan=\"3\">!AZ</td></tr>\n\
<tr><th>Process Priority:</th><td>!AZ</td>\
<td><i>server,user</i></td></tr>\n\
<tr><th>Strict CGI Output:</th><td colspan=\"3\">!AZ</td></tr>\n\
<tr><th>Spawn Authorized Privileges:</th><td colspan=\"3\">!AZ</td></tr>\n\
<tr><th>Gateway BG:</th><td colspan=\"3\">!AZ</td></tr>\n\
<tr><th>Soft Limit:</th><td>!UL</td>\
<td><i>script processes</i></td></tr>\n\
<tr><th>Hard Limit:</th><td>!UL</td>\
<td><i>script processes</i></td></tr>\n\
<tr><th>Bit-Bucket Timeout:</th><td>!AZ</td>\
<td><i>hh:mm:ss</i></td></tr>\n\
<tr><th>Zombie Life-Time:</th><td>!AZ</td></tr>\n\
<tr><th>CGIplus Life-Time:</th><td>!AZ</td></tr>\n\
<tr><th>DECnet Reuse Life-Time:</th><td>!AZ</td></tr>\n\
<tr><th>DECnet Connect List Max:</th><td>!UL</td>\
<td><i>connections</i></td></tr>\n\
<tr><th>Cleanup Scratch Max:</th><td>!UL</td>\
<td><i>minutes</i></td></tr>\n\
<tr><th>Cleanup Older-than:</th><td>!UL</td>\
<td><i>minutes</i></td></tr>\n\
<tr><th>Script Run-Time:</th>\
<td class=\"sbttl\">suffix</td>\
<td class=\"sbttl\" colspan=\"3\">verb</td></tr>\n";

   static char ReportProctorFao [] =
"<tr><th>Script Proctor:</th>\
<td class=\"sbttl\">min+idle</td><td class=\"sbttl\">pattern</td>\
<td class=\"sbttl\">activation</td><td class=\"sbttl\">notepad</td></tr>\n";

   static char ReportSsiFao [] =
"</table>\n\
</td></tr>\n\
</table>\n\
\
<p><table class=\"ctgry\">\n\
<tr><th class=\"ctttl\">Server-Side Includes</th></tr>\n\
<tr><td>\n\
<table class=\"rghtlft\">\n\
<tr><th>SSI:</th><td>!AZ</td></tr>\n\
<tr><th>Exec:</th><td>!AZ</td></tr>\n\
<tr><th>Accesses:</th><td>!AZ</td></tr>\n\
<tr><th>Max Size:</th><td>!UL</td>\
<td><i>kBytes</i></td></tr>\n\
</table>\n\
</td></tr>\n\
</table>\n\
\
<p><table class=\"ctgry\">\n\
<tr><th class=\"ctttl\">WebDAV</th></tr>\n\
<tr><td>\n\
<table class=\"rghtlft\">\n\
<tr><th>WebDAV:</th><td>!AZ</td></tr>\n\
<tr><th>Locking:</th><td>!AZ</td></tr>\n\
<tr><th>Lock Timeout Default:</th><td>!AZ</td></tr>\n\
<tr><th>Lock Timeout Max:</th><td>!AZ</td></tr>\n\
<tr><th>Lock Collection Depth:</th><td>!UL</td></tr>\n\
<tr><th>Quota:</th><td>!AZ</td></tr>\n\
<tr><th>Meta File Directory:</th><td>!AZ</td></tr>\n\
</table>\n\
</td></tr>\n\
</table>\n\
\
<p><table class=\"ctgry\">\n\
<tr><th class=\"ctttl\">Directory</th></tr>\n\
<tr><td>\n\
<table class=\"rghtlft\">\n\
<tr><th>Access:</th><td>!AZ</td></tr>\n\
<tr><th>Layout:</th><td>!AZ</td></tr>\n\
<tr><th>Listing &lt;BODY&gt;:</th>\
<td><tt>!&;AZ</tt></td></tr>\n\
<tr><th>HTML Description:</th><td>!UL <i>lines</i></td></tr>\n\
<tr><th>&lt;META&gt; Info:</th><td>!AZ</td></tr>\n\
<tr><th>Owner:</th><td>!AZ</td></tr>\n\
<tr><th>Pre-Expired:</th><td>!AZ</td></tr>\n\
<tr><th>Wildcard:</th><td>!AZ</td></tr>\n\
<tr><th>No Implied Wildcard:</th><td>!AZ</td></tr>\n\
<tr><th>Prot Violations Ignored:</th><td>!AZ</td></tr>\n\
<tr><th>Readme:</th><td>!AZ !AZ</td></tr>\n\
<tr><th>Readme Files:</th>\n";

   static char  ReportIconsFao [] =
"</table>\n\
</td></tr>\n\
</table>\n\
\
<p><table class=\"ctgry\">\n\
<tr><th class=\"ctttl\">Directory Icons</th></tr>\n\
<tr><td>\n\
<table class=\"lftlft\">\n\
<tr>\
<th class=\"sbttl\">Content-Type</th>\
<th class=\"sbttl\">Icon</th>\
<th class=\"sbttl\">Path</th>\
<th class=\"sbttl\">Alt.Text</th>\
</tr>\n";

   static char  ReportContentTypeFao [] =
"</table>\n\
</td></tr>\n\
</table>\n\
\
<p><table class=\"ctgry\">\n\
<tr><th class=\"ctttl\">Content-Type</th></tr>\n\
<tr><td>\n\
<table class=\"lftlft\">\n\
<tr>\
<th class=\"sbttl\">Suffix</th>\
<th class=\"sbttl\">Content-Type</th>\
<th class=\"sbttl\">Icon</th>\
<th class=\"sbttl\">Auto-script</th>\
<th class=\"sbttl\">Description</th>\
</tr>\n";

   static char  EndPageFao [] =
"<tr><td colspan=\"5\"><b><u>MIME.TYPES File</u>:</b> !AZ</td></tr>\n\
</table>\n\
</td></tr>\n\
</table>\n\
\
</div>\n\
</body>\n\
</html>\n";

   int  idx, status;
   unsigned long  *vecptr;
   unsigned long  FaoVector [128];
   char  HtmlIconAltText [256],
         IconAltText [256],
         IconPath [256];
   char  *cptr, *sptr, *zptr;
   CONFIG_STRUCT  *cfptr;
   CONTENT_TYPE  ContentType;
   CONTENT_TYPE  *ctptr;
   ICON_TYPE  *itptr;

   /*********/
   /* begin */
   /*********/

   if (WATCHMOD (rqptr, WATCH_MOD_CONFIG))
      WatchThis (WATCHITM(rqptr), WATCH_MOD_CONFIG, "ConfigReportNow()");

   /* get a pointer to the meta-config data */
   cfptr = mcptr->ConfigMetaPtr;

   AdminPageTitle (rqptr, "Server Configuration");
   AdminMetaConReport (rqptr, mcptr, MetaGlobalConfigPtr);
   AdminMetaConSource (rqptr, mcptr, MetaGlobalConfigPtr);

   /************/
   /* services */
   /************/

   if (VMSnok (ServiceReportConfigFromString (rqptr, cfptr)))
      return;

   /***********/
   /* general */
   /***********/

   vecptr = FaoVector;

   /* GMT */
   *vecptr++ = TimeGmtString;
   *vecptr++ = rqptr->rqTime.GmDateTime;

   /* general */
   if (cfptr->cfServer.InstanceMax == INSTANCE_PER_CPU)
      *vecptr++ = "CPU";
   else
   {
      *vecptr++ = "!UL";
      *vecptr++ = cfptr->cfServer.InstanceMax;
   }
   REP_ENDIS (cfptr->cfServer.InstancePassive)
   if (cfptr->cfServer.ConnectMax && !NetInstancePassive)
      *vecptr++ = cfptr->cfServer.ConnectMax;
   else
      *vecptr++ = NetConcurrentMax;
   if (cfptr->cfServer.ProcessMax && !NetInstancePassive)
      *vecptr++ = cfptr->cfServer.ProcessMax;
   else
      *vecptr++ = NetConcurrentProcessMax;
   if (cfptr->cfServer.ListenBacklog)
      *vecptr++ = cfptr->cfServer.ListenBacklog;
   else
      *vecptr++ = DEFAULT_LISTEN_BACKLOG;
   *vecptr++ = cfptr->cfMisc.RequestHistory;
   *vecptr++ = cfptr->cfMisc.ActivityNumberOfDays;
   REP_NOTNONE (cfptr->cfContent.CharsetDefault)
   if (cfptr->cfContent.CharsetConvertPtr)
      *vecptr++ = ConfigStringList (rqptr,
                     cfptr->cfContent.CharsetConvertPtr, '\r');
   else
      *vecptr++ = ConfigNoteNone;
   REP_ENDIS (cfptr->cfMisc.MonitorEnabled)

   *vecptr++ = "!AZ";
   switch (cfptr->cfMisc.RegexSyntax)
   {
      case 0 : *vecptr++ = "[disabled]"; break; 
      case REGEX_C_FLAGS : *vecptr++ = "[enabled]"; break; 
      case RE_SYNTAX_AWK : *vecptr++ = "AWK"; break; 
      case RE_SYNTAX_EGREP : *vecptr++ = "EGREP"; break; 
      case RE_SYNTAX_GREP : *vecptr++ = "GREP"; break; 
      case RE_SYNTAX_POSIX_AWK : *vecptr++ = "POSIX_AWK"; break; 
      case RE_SYNTAX_POSIX_BASIC : *vecptr++ = "POSIX_BASIC/ED/SED"; break; 
      case RE_SYNTAX_POSIX_EGREP : *vecptr++ = "POSIX_EGREP"; break; 
      case RE_SYNTAX_POSIX_EXTENDED : *vecptr++ = "POSIX_EXTENDED"; break; 
      case RE_SYNTAX_POSIX_MINIMAL_BASIC :
                *vecptr++ = "POSIX_MINIMAL_BASIC"; break; 
      case RE_SYNTAX_POSIX_MINIMAL_EXTENDED :
                *vecptr++ = "POSIX_MINIMAL_EXTENDED"; break; 
      default : vecptr--;
                *vecptr++ = "!8XL";
                *vecptr = cfptr->cfMisc.RegexSyntax;
   }

   REP_ENDIS (cfptr->cfMisc.EntityTag)
   REP_ENDIS (cfptr->cfMisc.PipelineRequests)
   REP_ENDIS (cfptr->cfMisc.HttpTraceEnabled)
   REP_ENDIS (cfptr->cfMisc.WwwImplied)
   *vecptr++ = cfptr->cfMisc.GzipAcceptWindowBits;
   if (cfptr->cfMisc.GzipFlushSeconds &&
       cfptr->cfMisc.GzipFlushInitialSeconds)
   {
      *vecptr++ = "!UL,!UL";
      *vecptr++ = cfptr->cfMisc.GzipFlushSeconds;
      *vecptr++ = cfptr->cfMisc.GzipFlushInitialSeconds;
   }
   else
   {
      *vecptr++ = "!UL";
      *vecptr++ = cfptr->cfMisc.GzipFlushSeconds;
   }
   if (cfptr->cfMisc.GzipResponseMemLevel ||
       cfptr->cfMisc.GzipResponseWindowBits)
   {
      *vecptr++ = "!UL,!UL,!UL";
      *vecptr++ = cfptr->cfMisc.GzipResponseCompLevel;
      *vecptr++ = cfptr->cfMisc.GzipResponseMemLevel;
      *vecptr++ = cfptr->cfMisc.GzipResponseWindowBits;
   }
   else
   {
      *vecptr++ = "!UL";
      *vecptr++ = cfptr->cfMisc.GzipResponseCompLevel;
   }
   *vecptr++ = cfptr->cfServer.DefaultPort;
   *vecptr++ = cfptr->cfMisc.StreamLfConversionMaxKbytes;
   *vecptr++ = cfptr->cfScript.DefaultSearch;
   if (cfptr->cfScript.DefaultSearchExcludePtr)
      *vecptr++ = ConfigStringList (rqptr,
                     cfptr->cfScript.DefaultSearchExcludePtr, '\r');
   else
      *vecptr++ = ConfigNoteNone;

   *vecptr++ = cfptr->cfMisc.PutMaxKbytes;
   if (cfptr->cfMisc.PutBinaryRFM == PUT_RFM_FIX512)
      *vecptr++ = "FIX512";
   else
   if (cfptr->cfMisc.PutBinaryRFM == PUT_RFM_STM)
      *vecptr++ = "STM";
   else
   if (cfptr->cfMisc.PutBinaryRFM == PUT_RFM_STMCR)
      *vecptr++ = "STMCR";
   else
   if (cfptr->cfMisc.PutBinaryRFM == PUT_RFM_STMLF)
      *vecptr++ = "STMLF";
   else
   if (cfptr->cfMisc.PutBinaryRFM == PUT_RFM_UDF)
      *vecptr++ = "UDF";
   else
      *vecptr++ = "<i>(UDF)</i>";
   *vecptr++ = cfptr->cfMisc.PutVersionLimit;

   if (cfptr == &Config)
      *vecptr++ = MapUrlUserNameCacheEntries;
   else
      *vecptr++ = cfptr->cfMisc.MapUserNameCacheEntries;
   if (cfptr == &Config)
      *vecptr++ = PersonaCacheEntries;
   else
      *vecptr++ = cfptr->cfMisc.PersonaCacheEntries;

   /* DNS host resolution */
   REP_ENDIS (cfptr->cfMisc.DnsLookupClient)
   *vecptr++ = MetaConShowSeconds (rqptr, cfptr->cfMisc.DnsLookupLifeTimeSeconds);
   *vecptr++ = cfptr->cfMisc.DnsLookupRetryCount;

   /* logging */
   REP_ENDIS (cfptr->cfLog.Enabled)
   REP_NOTNONE (cfptr->cfLog.Format)
   REP_NOTNONE (cfptr->cfLog.Naming)
   REP_NOTNONE (cfptr->cfLog.Period)
   REP_ENDIS (cfptr->cfLog.PerInstance)
   REP_ENDIS (cfptr->cfLog.PerService)
   REP_ENDIS (cfptr->cfLog.PerServiceHostOnly)
   REP_ENDIS (cfptr->cfLog.WriteFail503)
   REP_NOTNONE (cfptr->cfLog.FileName)
   *vecptr++ = cfptr->cfLog.ExtendBlocks;
   if (cfptr->cfLog.ExcludeHostsPtr)
      *vecptr++ = ConfigStringList (rqptr, cfptr->cfLog.ExcludeHostsPtr, '\n');
   else
      *vecptr++ = ConfigNoteNone;

   /* OPCOM messages */
   *vecptr++ = ConfigOpcomTarget[cfptr->cfOpcom.Index].Name;
   REP_ENDIS (cfptr->cfOpcom.Messages & OPCOM_ADMIN)
   REP_ENDIS (cfptr->cfOpcom.Messages & OPCOM_AUTHORIZATION)
   REP_ENDIS (cfptr->cfOpcom.Messages & OPCOM_CONTROL)
   REP_ENDIS (cfptr->cfOpcom.Messages & OPCOM_HTTPD)
   REP_ENDIS (cfptr->cfOpcom.Messages & OPCOM_PROXY_MAINT)

   /* cache */
   REP_ENDIS (cfptr->cfCache.Enabled)
   *vecptr++ = cfptr->cfCache.EntriesMax;
   *vecptr++ = cfptr->cfCache.TotalKBytesMax;
   *vecptr++ = cfptr->cfCache.FileKBytesMax;
   *vecptr++ = MetaConShowSeconds (rqptr, cfptr->cfCache.GuardSeconds);
   *vecptr++ = MetaConShowSeconds (rqptr, cfptr->cfCache.ValidateSeconds);
   *vecptr++ = cfptr->cfCache.FrequentHits;
   *vecptr++ = MetaConShowSeconds (rqptr, cfptr->cfCache.FrequentSeconds);

   /* timeouts */
   *vecptr++ = MetaConShowSeconds (rqptr, cfptr->cfTimeout.Input);
   *vecptr++ = MetaConShowSeconds (rqptr, cfptr->cfTimeout.Output);
   *vecptr++ = MetaConShowSeconds (rqptr, cfptr->cfTimeout.NoProgress);
   *vecptr++ = MetaConShowSeconds (rqptr, cfptr->cfTimeout.Persistent);
   *vecptr++ = MetaConShowSeconds (rqptr, cfptr->cfTimeout.Http2Idle);

   /* buffer sizes */
   if (cfptr == &Config)
   {
      /* in-use values */
      *vecptr++ = "(in-use)";
      *vecptr++ = DclSysCommandSize;
      *vecptr++ = DclSysOutputSize;
      *vecptr++ = cfptr->cfBuffer.SizeDclOutput;
      *vecptr++ = DclSysOutputQuota;
      *vecptr++ = cfptr->cfBuffer.QuotaDclOutput;
      *vecptr++ = DclCgiPlusInSize;
      *vecptr++ = DclCgiHeaderSize;
      *vecptr++ = NetReadBufferSize;
      *vecptr++ = OutputBufferSize;
      *vecptr++ = cfptr->cfBuffer.SizeNetWrite;
      *vecptr++ = OutputFileBufferSize;
      *vecptr++ = cfptr->cfBuffer.SizeNetFile;
      *vecptr++ = cfptr->cfBuffer.SizeNetMTU;
      *vecptr++ = TcpIpSocketSndBufSize;
      *vecptr++ = TcpIpSocketSndBufSize ? "" : ConfigNoteSystem;
      *vecptr++ = TcpIpSocketRcvBufSize;
      *vecptr++ = TcpIpSocketRcvBufSize ? "" : ConfigNoteSystem;
   }
   else
   {
      /* file values */
      *vecptr++ = "(config)";
      *vecptr++ = cfptr->cfBuffer.SizeDclCommand;
      *vecptr++ = cfptr->cfBuffer.SizeDclOutput;
      *vecptr++ = DclSysOutputSize;
      *vecptr++ = cfptr->cfBuffer.QuotaDclOutput;
      *vecptr++ = DclSysOutputQuota;
      *vecptr++ = cfptr->cfBuffer.SizeDclCgiPlusIn;
      *vecptr++ = cfptr->cfBuffer.SizeDclCgiHeader;
      *vecptr++ = cfptr->cfBuffer.SizeNetRead;
      *vecptr++ = cfptr->cfBuffer.SizeNetWrite;
      *vecptr++ = OutputBufferSize;
      *vecptr++ = cfptr->cfBuffer.SizeNetFile;
      *vecptr++ = OutputFileBufferSize;
      *vecptr++ = cfptr->cfBuffer.SizeNetMTU;
      *vecptr++ = cfptr->cfBuffer.SizeSocketSndBuf;
      *vecptr++ = cfptr->cfBuffer.SizeSocketSndBuf ? "" : ConfigNoteSystem;
      *vecptr++ = cfptr->cfBuffer.SizeSocketRcvBuf;
      *vecptr++ = cfptr->cfBuffer.SizeSocketRcvBuf ? "" : ConfigNoteSystem;
   }

   FaoCheck (sizeof(FaoVector), &FaoVector, vecptr, FI_LI);
   status = FaolToNet (rqptr, ReportGeneralFao, &FaoVector);
   if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI);

   /**********/
   /* HTTP/2 */
   /**********/

   ConfigReportHttp2 (rqptr, mcptr);

   /******************/
   /* Secure Sockets */
   /******************/

   ConfigReportSecureSocket (rqptr, mcptr);

   /*****************************/
   /* welcome (home page) files */
   /*****************************/

   status = FaolToNet (rqptr, ReportWelcomeFao, NULL);
   if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI);

   for (idx = 0; idx < cfptr->cfContent.HomePageCount; idx++)
   {
      status = FaoToNet (rqptr, "<tr><td><tt>!&;AZ</tt></td></tr>\n",
                         cfptr->cfContent.HomePageArray[idx]);
      if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI);
   }

   /*********************/
   /* host access, etc. */
   /*********************/

   vecptr = FaoVector;

   if (cfptr->cfServer.AcceptHostsPtr)
      *vecptr++ = ConfigStringList (rqptr, cfptr->cfServer.AcceptHostsPtr, ',');
   else
      *vecptr++ = ConfigNoteNone;

   if (cfptr->cfServer.RejectHostsPtr)
      *vecptr++ = ConfigStringList (rqptr, cfptr->cfServer.RejectHostsPtr, ',');
   else
      *vecptr++ = ConfigNoteNone;

   /* reports */
   if (cfptr->cfServer.AdminEmail[0])
   {
      *vecptr++ = "!&;AZ";
      *vecptr++ = cfptr->cfServer.AdminEmail;
   }
   else
   {
      *vecptr++ = "!AZ";
      *vecptr++ = ConfigNoteNone;
   }
   if (cfptr->cfServer.Signature == CONFIG_SERVER_SIGNATURE_ON)
      *vecptr++ = "[enabled]";
   else
   if (cfptr->cfServer.Signature == CONFIG_SERVER_SIGNATURE_EMAIL)
      *vecptr++ = "[enabled] [email]";
   else
      *vecptr++ = "[disabled]";
   REP_ENDIS (cfptr->cfReport.BasicOnly)
   REP_ENDIS (cfptr->cfReport.MetaInfoEnabled)
   REP_NOTNONE (cfptr->cfReport.ErrorReportPath)
   REP_ENDIS (cfptr->cfReport.ErrorRecommend)

   /* authentication */
   *vecptr++ = cfptr->cfAuth.CacheEntriesMax;
   *vecptr++ = cfptr->cfAuth.CacheEntrySize;
   *vecptr++ = cfptr->cfAuth.CacheMinutes;
   *vecptr++ = cfptr->cfAuth.RevalidateUserMinutes;
   if (mcptr == MetaGlobalConfigPtr)
   {
      /* server, show the values in use */
      *vecptr++ = AuthFailureLimit;
      *vecptr++ = MetaConShowSeconds (rqptr, AuthFailurePeriodSeconds);
      *vecptr++ = MetaConShowSeconds (rqptr, AuthFailureTimeoutSeconds);
   }
   else
   {
      /* from file, show the config values */
      *vecptr++ = cfptr->cfAuth.FailureLimit;
      *vecptr++ = MetaConShowSeconds (rqptr, cfptr->cfAuth.FailurePeriodSeconds);
      *vecptr++ = MetaConShowSeconds (rqptr, cfptr->cfAuth.FailureTimeoutSeconds);
   }
   *vecptr++ = cfptr->cfAuth.TokenEntriesMax;
   REP_ENDIS (cfptr->cfAuth.BasicEnabled)
   REP_ENDIS (cfptr->cfAuth.DigestEnabled)
   *vecptr++ = cfptr->cfAuth.DigestNonceGetLifeTime;
   *vecptr++ = cfptr->cfAuth.DigestNonceGetLifeTime;
   switch (cfptr->cfAuth.SysUafLogonType)
   {
      case AUTH_LOGON_TYPE_NETWORK :
           *vecptr++ = "NETWORK"; break;
      case AUTH_LOGON_TYPE_BATCH :
           *vecptr++ = "BATCH";
           break;
      case AUTH_LOGON_TYPE_LOCAL :
           *vecptr++ = "LOCAL";
           break;
      case AUTH_LOGON_TYPE_DIALUP :
           *vecptr++ = "DIALUP";
           break;
      case AUTH_LOGON_TYPE_REMOTE :
           *vecptr++ = "REMOTE";
           break;
      default :
           *vecptr++ = ConfigNoteDefault;
   }
   REP_ENDIS (cfptr->cfAuth.SysUafAcceptExpPwd)
   REP_NOTNONE (cfptr->cfAuth.SysUafPwdExpUrl)

   /* proxy serving */
   REP_ENDIS (cfptr->cfProxy.ServingEnabled)
   REP_ENDIS (cfptr->cfProxy.CacheEnabled)
   REP_ENDIS (cfptr->cfProxy.UnknownRequestFields)
   if (cfptr->cfProxy.ForwardedBy == PROXY_FORWARDED_BY)
      *vecptr++ = "BY";
   else
   if (cfptr->cfProxy.ForwardedBy == PROXY_FORWARDED_FOR)
      *vecptr++ = "FOR";
   else
   if (cfptr->cfProxy.ForwardedBy == PROXY_FORWARDED_ADDRESS)
      *vecptr++ = "ADDRESS";
   else
      *vecptr++ = ConfigNoteNone;
   if (cfptr->cfProxy.XForwardedFor == PROXY_XFORWARDEDFOR_ENABLED)
      *vecptr++ = "ENABLED";
   else
   if (cfptr->cfProxy.XForwardedFor == PROXY_XFORWARDEDFOR_UNKNOWN)
      *vecptr++ = "UNKNOWN";
   else
   if (cfptr->cfProxy.XForwardedFor == PROXY_XFORWARDEDFOR_ADDRESS)
      *vecptr++ = "ADDRESS";
   else
      *vecptr++ = ConfigNoteNone;
   REP_ENDIS (cfptr->cfProxy.ReportLog)
   REP_ENDIS (cfptr->cfProxy.ReportCacheLog)
   *vecptr++ = cfptr->cfProxy.VerifyRecordMax;
   *vecptr++ = cfptr->cfProxy.HostLookupRetryCount;
   *vecptr++ = MetaConShowSeconds (rqptr, cfptr->cfProxy.ConnectTimeoutSeconds);
   *vecptr++ = cfptr->cfProxy.ConnectPersistMax;
   *vecptr++ = MetaConShowSeconds (rqptr, cfptr->cfProxy.ConnectPersistSeconds);
   *vecptr++ = cfptr->cfProxy.CacheFileKBytesMax;
   *vecptr++ = MetaConShowSeconds (rqptr, cfptr->cfProxy.CacheNegativeSeconds);
   *vecptr++ = MetaConShowSeconds (rqptr, cfptr->cfProxy.CacheNoReloadSeconds);
   REP_NOTNONE (cfptr->cfProxy.CacheReloadList)
   *vecptr++ = cfptr->cfProxy.CacheRoutineHourOfDayString;
   REP_NOTNONE (cfptr->cfProxy.CachePurgeList)
   if (cfptr->cfProxy.CacheDeviceDirOrg == PROXY_CACHE_DIR_ORG_FLAT256)
      *vecptr++ = "flat256";
   else
   if (cfptr->cfProxy.CacheDeviceDirOrg == PROXY_CACHE_DIR_ORG_64X64)
      *vecptr++ = "64x64";
   else
      *vecptr++ = "";
   *vecptr++ = cfptr->cfProxy.CacheDeviceCheckMinutes;
   *vecptr++ = cfptr->cfProxy.CacheDeviceMaxPercent;
   *vecptr++ = cfptr->cfProxy.CacheDevicePurgePercent;

   /* scripting */
   REP_ENDIS (cfptr->cfScript.Enabled)
   REP_ENDIS (cfptr->cfScript.DetachProcess)
   *vecptr++ = cfptr->cfScript.DetachProcessPriority;
   REP_ENDIS (cfptr->cfScript.CgiStrictOutput)
   REP_ENDIS (cfptr->cfScript.SpawnAuthPriv)
   REP_ENDIS (cfptr->cfScript.GatewayBg)
   *vecptr++ = cfptr->cfScript.ScriptProcessSoftLimit;
   *vecptr++ = cfptr->cfScript.ScriptProcessHardLimit;
   *vecptr++ = MetaConShowSeconds (rqptr, cfptr->cfScript.BitBucketTimeout);
   *vecptr++ = MetaConShowSeconds (rqptr, cfptr->cfScript.ZombieLifeTime);
   *vecptr++ = MetaConShowSeconds (rqptr, cfptr->cfScript.CgiPlusLifeTime);
   *vecptr++ = MetaConShowSeconds (rqptr, cfptr->cfScript.DECnetReuseLifeTime);
   *vecptr++ = cfptr->cfScript.DECnetConnectListMax;
   *vecptr++ = cfptr->cfScript.CleanupScratchMinutesMax;
   *vecptr++ = cfptr->cfScript.CleanupScratchMinutesOld;

   FaoCheck (sizeof(FaoVector), &FaoVector, vecptr, FI_LI);
   status = FaolToNet (rqptr, ReportHostsFao, &FaoVector);
   if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI);

   /****************/
   /* script types */
   /****************/

   if (cfptr->cfScript.RunTimeCount)
   {
      for (idx = 0; idx < cfptr->cfScript.RunTimeCount; idx++)
      {
         vecptr = FaoVector;

         cptr = sptr = cfptr->cfScript.RunTime[idx].StringPtr;
         /* length of and location of the file type */
         while (*cptr && *cptr != ';') cptr++;
         *vecptr++ = cptr - sptr;
         *vecptr++ = sptr;
         /*  location of verb */
         cptr += 2;
         *vecptr++ = cptr;

         status = FaolToNet (rqptr,
"<tr><td></td><td>!#&;AZ</td><td colspan=\"3\"><tt>!&;AZ</tt></td></tr>\n",
                             &FaoVector);
         if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI);
      }
   }
   else
   {
      static char  NotNone [] =
"<tr><td colspan=\"2\">" CONFIG_NOTE_NONE "</td></tr>\n";

      status = FaolToNet (rqptr, NotNone, NULL);
      if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI);
   }

   status = FaolToNet (rqptr, ReportProctorFao, &FaoVector);
   if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI);

   /******************/
   /* script proctor */
   /******************/

   if (cfptr->cfScript.ProctorCount)
   {
      for (idx = 0; idx < cfptr->cfScript.ProctorCount; idx++)
      {
         vecptr = FaoVector;

         *vecptr++ = cfptr->cfScript.Proctor[idx].NumberMin;
         *vecptr++ = cfptr->cfScript.Proctor[idx].NumberIdle;
         *vecptr++ = *cfptr->cfScript.Proctor[idx].RunTimePtr ? "(" : "";
         *vecptr++ = cfptr->cfScript.Proctor[idx].RunTimePtr;
         *vecptr++ = *cfptr->cfScript.Proctor[idx].RunTimePtr ? ")" : "";
         *vecptr++ = cfptr->cfScript.Proctor[idx].ScriptPtr;
         *vecptr++ = cfptr->cfScript.Proctor[idx].ActivatePtr;
         *vecptr++ = cfptr->cfScript.Proctor[idx].NotePadPtr;

         status = FaolToNet (rqptr,
"<tr><td></td><td>!UL+!UL</td><td>!AZ!AZ!AZ!AZ</td>\
<td>!AZ</td><td>!AZ</td></tr>\n",
                             &FaoVector);
         if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI);
      }
   }
   else
   {
      static char  NotNone [] =
"<tr><td></td><td colspan=\"3\">" CONFIG_NOTE_NONE "</td></tr>\n";

      status = FaolToNet (rqptr, NotNone, NULL);
      if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI);
   }

   /**********************/
   /* Reports, SSI, etc. */
   /**********************/

   vecptr = FaoVector;

   /* SSI (.shtml) */
   REP_ENDIS (cfptr->cfSsi.Enabled)
   REP_ENDIS (cfptr->cfSsi.ExecEnabled)
   REP_ENDIS (cfptr->cfSsi.AccessesEnabled)
   *vecptr++ = cfptr->cfSsi.SizeMax;

   REP_ENDIS (cfptr->cfWebDav.DavEnabled)
   REP_ENDIS (cfptr->cfWebDav.LockingEnabled)
   *vecptr++ = MetaConShowSeconds (rqptr,
                  cfptr->cfWebDav.LockTimeoutDefaultSeconds);
   *vecptr++ = MetaConShowSeconds (rqptr,
                  cfptr->cfWebDav.LockTimeoutMaxSeconds);
   *vecptr++ = cfptr->cfWebDav.LockCollectionDepth;
   REP_ENDIS (cfptr->cfWebDav.QuotaEnabled)
   if (cfptr->cfWebDav.MetaFileDirectoryLength)
      *vecptr++ = cfptr->cfWebDav.MetaFileDirectory;
   else
      *vecptr++ = ConfigNoteNone;


   REP_ENDIS (cfptr->cfDir.Access)
   REP_NOTNONE (cfptr->cfDir.DefaultLayout)
   *vecptr++ = cfptr->cfDir.BodyTag;
   *vecptr++ = cfptr->cfDir.DescriptionLines;
   REP_ENDIS (cfptr->cfDir.MetaInfoEnabled)
   REP_ENDIS (cfptr->cfDir.OwnerEnabled)
   REP_ENDIS (cfptr->cfDir.PreExpired)
   REP_ENDIS (cfptr->cfDir.WildcardEnabled)
   REP_ENDIS (cfptr->cfDir.NoImpliedWildcard)
   REP_ENDIS (cfptr->cfDir.NoPrivIgnore)
   REP_ENDIS (cfptr->cfDir.ReadMeTop | cfptr->cfDir.ReadMeBottom)
   if (cfptr->cfDir.ReadMeTop)
      *vecptr++ = "[top]";
   else
   if (cfptr->cfDir.ReadMeBottom)
      *vecptr++ = "[bottom]";
   else
      *vecptr++ = "";

   FaoCheck (sizeof(FaoVector), &FaoVector, vecptr, FI_LI);
   status = FaolToNet (rqptr, ReportSsiFao, &FaoVector);
   if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI);

   /*********************/
   /* directory (contd) */
   /*********************/

   for (idx = 0; idx < cfptr->cfDir.ReadMeFileCount; idx++)
   {
      status = FaoToNet (rqptr, "!&@<td><tt>!AZ</tt></td></tr>\n",
                         idx ? "<tr><td></td>" : "",
                         cfptr->cfDir.ReadMeFileArray[idx]);
      if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI);
   }

   /*********/
   /* icons */
   /*********/

   status = FaolToNet (rqptr, ReportIconsFao, NULL);
   if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI);

   itptr = cfptr->cfContent.IconListHeadPtr;
   while (itptr)
   {
      vecptr = FaoVector;
      *vecptr++ = itptr->ContentTypePtr;
      *vecptr++ = itptr->IconUrlPtr;
      *vecptr++ = itptr->IconUriPtr;
      *vecptr++ = itptr->AltTextPtr;

      if (itptr->Superceded)
         cptr =
"<tr><td><i><strike>!AZ</strike></i></td>\
<td class=\"talft\">!AZ</td>\
<td><i><strike>!AZ</strike></i></td>\
<td><i><strike>[!&;AZ]</strike></i></td></tr>\n";
      else
         cptr =
"<tr><td>!AZ</td>\
<td class=\"talft\">!AZ</td>\
<td>!AZ</td>\
<td>!AZ</td></tr>\n";

      status = FaolToNet (rqptr, cptr, &FaoVector);
      if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI);

      itptr = itptr->NextPtr;
   }

   /*****************/
   /* content-types */
   /*****************/

   status = FaolToNet (rqptr, ReportContentTypeFao, NULL);
   if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI);

   for (ctptr = cfptr->cfContent.ContentInfoListHeadPtr;
        ctptr;
        ctptr = ctptr->NextPtr)
   {
      vecptr = &FaoVector;
      if (ctptr->FromMimeTypes)
         if (*ctptr->SuffixPtr == '.')
            *vecptr++ = ctptr->SuffixPtr+1;
         else
            *vecptr++ = ctptr->SuffixPtr;
      else
         *vecptr++ = ctptr->SuffixPtr;
      *vecptr++ = ctptr->ContentTypePtr;

      if (ctptr->PutRFM)
      {
         *vecptr++ = " RFM:!AZ";
         if (ctptr->PutRFM == PUT_RFM_FIX512)
            *vecptr++ = "FIX512";
         else
         if (ctptr->PutRFM == PUT_RFM_STM)
            *vecptr++ = "STM";
         else
         if (ctptr->PutRFM == PUT_RFM_STMCR)
            *vecptr++ = "STMCR";
         else
         if (ctptr->PutRFM == PUT_RFM_STMLF)
            *vecptr++ = "STMLF";
         else
         if (ctptr->PutRFM == PUT_RFM_UDF)
            *vecptr++ = "UDF";
         else
            *vecptr++ = "?";
      }
      else
         *vecptr++ = "";

      if (ctptr->FtpMode)
      {
         *vecptr++ = " FTP:!&C";
         *vecptr++ = ctptr->FtpMode;
      }
      else
         *vecptr++ = "";

      *vecptr++ = ctptr->IconPtr;
      *vecptr++ = ctptr->AutoScriptNamePtr;
      if (ctptr->TypeUnknown)
         *vecptr++ = cfptr->cfContent.ContentTypeDefaultPtr;
      else
         *vecptr++ = ctptr->DescriptionPtr;

      if (ctptr->Superceded)
         cptr = 
"<tr><td><i><strike>!AZ</strike></i></td>\
<td><i><strike>!AZ!&@!&@</strike></i></td>\
<td>!AZ</td>\
<td><i><strike>!AZ</strike></i></td>\
<td><i><strike>!AZ</strike></i></td></tr>\n";
      else
         cptr =
"<tr><td>!AZ</td>\
<td>!AZ!&@!&@</td>\
<td>!AZ</td>\
<td>!AZ</td>\
<td>!AZ</td></tr>\n";

      FaoCheck (sizeof(FaoVector), &FaoVector, vecptr, FI_LI);
      status = FaolToNet (rqptr, cptr, &FaoVector);
      if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI);
   }

   vecptr = &FaoVector;
   if (cfptr->cfContent.MimeTypesFileName[0])
      *vecptr++ = cfptr->cfContent.MimeTypesFileName;
   else
      *vecptr++ = ConfigNoteNone;

   status = FaolToNet (rqptr, EndPageFao, &FaoVector);
   if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI);

   rqptr->rqResponse.PreExpired = PRE_EXPIRE_ADMIN;
   ResponseHeader200 (rqptr, "text/html", &rqptr->NetWriteBufferDsc);

#undef REP_ENDIS
#undef REP_NOTNONE
}

/*****************************************************************************/
/*
This function just wraps the revision function, loading a temporary database
if necessary for reporting from the configuration file.
*/ 

ConfigRevise
(
REQUEST_STRUCT *rqptr,
BOOL UseServerDatabase
)
{
   int  status;
   META_CONFIG  *mcptr;

   /*********/
   /* begin */
   /*********/

   if (WATCHMOD (rqptr, WATCH_MOD_CONFIG))
      WatchThis (WATCHITM(rqptr), WATCH_MOD_CONFIG,
                 "ConfigRevise() !&F !UL", &ConfigRevise, UseServerDatabase);

   if (UseServerDatabase)
      ConfigReviseNow (rqptr, MetaGlobalConfigPtr);
   else
   {
      status = ConfigLoad (&mcptr);
      if (VMSnok (status))
      {
         /* severe error reported */
         rqptr->rqResponse.HttpStatus = 403;
         ErrorGeneral (rqptr, mcptr->LoadReport.TextPtr, FI_LI);
      }
      else
         ConfigReviseNow (rqptr, mcptr);
      MetaConUnload (&mcptr, NULL);
   }

   AdminEnd (rqptr);
}

/*****************************************************************************/
/*
Return a form for the HTTPd server's configuration.  POSTing the form to the
server results in the URL-decoded form as a configuration file.  This function
blocks while executing.
*/ 

ConfigReviseNow
(
REQUEST_STRUCT *rqptr,
META_CONFIG *mcptr
)
{
#define SIZEOF_SPECIAL_ICON 256

#define REP_BOOL_RADIO(b)\
if (b)\
{\
   *vecptr++ = RadioButtonChecked;\
   *vecptr++ = RadioButtonUnchecked;\
}\
else\
{\
   *vecptr++ = RadioButtonUnchecked;\
   *vecptr++ = RadioButtonChecked;\
}

   static char  ConfigGeneralFao [] =
"<p><table class=\"ctgry\">\n\
<tr><th class=\"ctttl\">Service</th></tr>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;# -SERVICE-&#94;\">\n\
<tr><td>\n\
!&@\
<br><b>Service Not Found URL:</b>&nbsp;\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[ServiceNotFoundURL]&#32;&#32;\">\n\
<input type=\"text\" size=\"40\" name=\"ServiceNotFoundURL\" value=\"!AZ\">\n\
</td></tr>\n\
</table>\n\
\
<p><table class=\"ctgry\">\n\
<tr><th class=\"ctttl\">General</th></tr>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;&#94;# -GENERAL-&#94;\">\n\
<tr><td>\n\
<table class=\"rghtlft\">\n\
<tr><th>Instance Max:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[InstanceMax]&#32;&#32;\">\n\
<input type=\"text\" size=\"3\" name=\"InstanceMax\" value=\"!&@\">\n\
<i>per-node servers</i></td></tr>\n\
<tr><th>Instance Passive:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[InstancePassive]&#32;&#32;\">\n\
<input type=\"radio\" name=\"InstancePassive\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"InstancePassive\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
<tr><th>Connect Max:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[ConnectMax]&#32;&#32;\">\n\
<input type=\"text\" size=\"3\" name=\"ConnectMax\" value=\"!UL\">\n\
<i>connections</i></td></tr>\n\
<tr><th>Process Max:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[ProcessMax]&#32;&#32;\">\n\
<input type=\"text\" size=\"3\" name=\"ProcessMax\" value=\"!UL\">\n\
<i>requests being processed</i></td></tr>\n\
<tr><th>Listen Backlog:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[ServiceListenBacklog]&#32;&#32;\">\n\
<input type=\"text\" size=\"3\" name=\"ServiceListenBacklog\" value=\"!UL\">\n\
<i>at socket</i></td></tr>\n\
<tr><th>Request History:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[RequestHistory]&#32;&#32;\">\n\
<input type=\"text\" size=\"3\" name=\"RequestHistory\" value=\"!UL\">\n\
</td></tr>\n\
<tr><th>Activity History:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[ActivityDays]&#32;&#32;\">\n\
<input type=\"text\" size=\"3\" name=\"ActivityDays\" value=\"!UL\">\n\
<i>days</i></td></tr>\n\
<tr><th>Charset Default:</th><td colspan=\"2\">\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[CharsetDefault]&#32;&#32;\">\n\
<input type=\"text\" size=\"40\" name=\"CharsetDefault\" value=\"!AZ\">\n\
</td></tr>\n\
<tr><th>Charset Convert:</th></tr>\n\
<tr><td colspan=\"2\">\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[CharsetConvert]&#94;\">\n\
<textarea name=\"CharsetConvert\" rows=\"4\" cols=\"60\" nowrap>\
!AZ\
</textarea>\n\
</td></tr>\n\
<tr><th>Monitor:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[Monitor]&#32;&#32;\">\n\
<input type=\"radio\" name=\"Monitor\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"Monitor\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
<tr><th>Regular Expressions:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[RegEx]&#32;&#32;\">\n\
<input type=\"text\" size=\"10\" name=\"RegEx\" value=\"!&@\">\n\
</td></tr>\n\
<tr><th>Entity Tag:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[EntityTag]&#32;&#32;\">\n\
<input type=\"radio\" name=\"EntityTag\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"EntityTag\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
<tr><th>Pipeline Requests:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[PipelineRequests]&#32;&#32;\">\n\
<input type=\"radio\" name=\"PipelineRequests\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"PipelineRequests\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
<tr><th>HTTP TRACE:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[HttpTrace]&#32;&#32;\">\n\
<input type=\"radio\" name=\"HttpTrace\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"HttpTrace\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
<tr><th>WWW Implied:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[WwwImplied]&#32;&#32;\">\n\
<input type=\"radio\" name=\"WwwImplied\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"WwwImplied\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
<tr><th>GZIP Accept:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[GzipAccept]&#32;&#32;\">\n\
<input type=\"text\" size=\"5\" name=\"GzipAccept\" value=\"!UL\">\n\
<i>window</i></td></tr>\n\
<tr><th>GZIP Flush:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[GzipFlushSeconds]&#32;&#32;\">\n\
<input type=\"text\" size=\"7\" name=\"GzipFlushSeconds\" value=\"!&@\">\n\
<i>interval[,initial] seconds</i></td></tr>\n\
<tr><th>GZIP Response:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[GzipResponse]&#32;&#32;\">\n\
<input type=\"text\" size=\"7\" name=\"GzipResponse\" value=\"!&@\">\n\
<i>level[,memory,window]</i></td></tr>\n\
<tr><th>IP Port:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[Port]&#32;&#32;\">\n\
<input type=\"text\" size=\"5\" name=\"Port\" value=\"!UL\">\n\
<i>(overridden by &quot;service&quot; directive)</i></td></tr>\n\
<tr><th>StreamLF:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[StreamLF]&#32;&#32;\">\n\
<input type=\"text\" size=\"3\" name=\"StreamLF\" value=\"!UL\">\n\
<i>kBytes</i></td></tr>\n\
<tr><th>Search Script:</th><td colspan=\"2\">\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[SearchScript]&#32;&#32;\">\n\
<input type=\"text\" size=\"40\" name=\"SearchScript\" value=\"!AZ\">\n\
</td></tr>\n\
<tr><th>Search Script Exclude:</th></tr>\n\
<tr><td colspan=\"2\">\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[SearchScriptExclude]&#94;\">\n\
<textarea name=\"SearchScriptExclude\" rows=\"4\" cols=\"40\" nowrap>\
!AZ\
</textarea>\n\
</td></tr>\n\
<tr><th>PUT/POST Max:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[PutMaxKbytes]&#32;&#32;\">\n\
<input type=\"text\" size=\"5\" name=\"PutMaxKbytes\" value=\"!UL\">\n\
<i>kBytes</i></td></tr>\n\
<tr><th>PUT/POST binary RFM:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[PutBinaryRFM]&#32;&#32;\">\n\
<select name=\"PutBinaryRFM\">\n\
<option value=\"\"!AZ>(UDF)\n\
<option value=\"FIX512\"!AZ>FIX512\n\
<option value=\"STM\"!AZ>STM\n\
<option value=\"STMCR\"!AZ>STMCR\n\
<option value=\"STMLF\"!AZ>STMLF\n\
<option value=\"UDF\"!AZ>UDF\n\
</select>\n\
</td></tr>\n\
<tr><th>Put/Post Files:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[PutVersionLimit]&#32;&#32;\">\n\
<input type=\"text\" size=\"5\" name=\"PutVersionLimit\" value=\"!UL\">\n\
<i>version limit</i></td></tr>\n\
</td></tr>\n\
<tr><th>/~username/ Cache Entries:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[MapUserNameCacheEntries]&#32;&#32;\">\n\
<input type=\"text\" size=\"3\" name=\"MapUserNameCacheEntries\" value=\"!UL\">\n\
<i>user names</i>\
</td></tr>\n\
<tr><th>Persona Cache Entries:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[PersonaCacheEntries]&#32;&#32;\">\n\
<input type=\"text\" size=\"3\" name=\"PersonaCacheEntries\" value=\"!UL\">\n\
<i>users</i>\
</td></tr>\n\
</table>\n\
</td></tr>\n\
</table>\n\
\
<p><table class=\"ctgry\">\n\
<tr><th class=\"ctttl\">Host Resolution</th></tr>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;&#94;# -DNS-&#94;\">\n\
<tr><td>\n\
<table class=\"rghtlft\">\n\
<tr><th>Client Lookup:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[DNSLookupClient]&#32;&#32;\">\n\
<input type=\"radio\" name=\"DNSLookupClient\" value=\"enabled\"!AZ>yes\n\
<input type=\"radio\" name=\"DNSLookupClient\" value=\"disabled\"!AZ>no\n\
</td></tr>\n\
<tr><th>Life-Time:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[DNSLookupLifeTime]&#32;&#32;\">\n\
<input type=\"text\" size=\"7\" name=\"DNSLookupLifeTime\" value=\"!AZ\">\n\
<i>hh:mm:ss</i></td></tr>\n\
<tr><th>Retry Count:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[DNSLookupRetry]&#32;&#32;\">\n\
<input type=\"text\" size=\"3\" name=\"DNSLookupRetry\" value=\"!UL\"></td></tr>\n\
\
</table>\n\
</td></tr>\n\
</table>\n\
<p><table class=\"ctgry\">\n\
<tr><th class=\"ctttl\">Log</th></tr>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;&#94;# -LOGGING-&#94;\">\n\
<tr><td>\n\
<table class=\"rghtlft\">\n\
<tr><th>Logging:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[Logging]&#32;&#32;\">\n\
<input type=\"radio\" name=\"Logging\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"Logging\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
<tr><th>Format:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[LogFormat]&#32;&#32;\">\n\
<input type=\"text\" size=\"10\" name=\"LogFormat\" value=\"!AZ\"></td></tr>\n\
<tr><th>Naming:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[LogNaming]&#32;&#32;\">\n\
<input type=\"text\" size=\"10\" name=\"LogNaming\" value=\"!AZ\"></td></tr>\n\
</td></tr>\n\
<tr><th>Period:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[LogPeriod]&#32;&#32;\">\n\
<input type=\"text\" size=\"10\" name=\"LogPeriod\" value=\"!AZ\"></td></tr>\n\
</td></tr>\n\
<tr><th>Per-Instance:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[LogPerInstance]&#32;&#32;\">\n\
<input type=\"radio\" name=\"LogPerInstance\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"LogPerInstance\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
<tr><th>Per-Service:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[LogPerService]&#32;&#32;\">\n\
<input type=\"radio\" name=\"LogPerService\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"LogPerService\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
<tr><th>Per-Service Host Only:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[LogPerServiceHostOnly]&#32;&#32;\">\n\
<input type=\"radio\" name=\"LogPerServiceHostOnly\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"LogPerServiceHostOnly\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
<tr><th>Write Fail 503:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[LogWriteFail503]&#32;&#32;\">\n\
<input type=\"radio\" name=\"LogWriteFail503\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"LogWriteFail503\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
<tr><th>File:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[LogFile]&#32;&#32;\">\n\
<input type=\"text\" size=\"40\" name=\"LogFile\" value=\"!AZ\"></td></tr>\n\
<tr><th>Extend Blocks:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[LogFileExtend]&#32;&#32;\">\n\
<input type=\"text\" size=\"5\" name=\"LogFileExtend\" value=\"!UL\">\n\
</td></tr>\n\
<tr><th>Exclude Hosts:</th></tr>\n\
<tr><td colspan=\"2\">\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[LogExcludeHosts]&#94;\">\n\
<textarea name=\"LogExcludeHosts\" rows=\"4\" cols=40 nowrap>\
!AZ\
</textarea>\n\
</td></tr>\n\
</table>\n\
</td></tr>\n\
</table>\n\
\
<p><table class=\"ctgry\">\n\
<tr><th class=\"ctttl\">OPCOM</th></tr>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;&#94;# -OPCOM-&#94;\">\n\
<tr><td>\n\
<table class=\"rghtlft\">\n\
<tr><th>Target:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[OpcomTarget]&#32;&#32;\">\n\
<select name=\"OpcomTarget\">\n";

   static char  ConfigOpcomTargetFao [] =
"<option value=\"!AZ\"!&? SELECTED\r\r>!AZ\n";

   static char  ConfigOpcomFao [] =
"</select>\n\
<tr><th>Admin:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[OpcomAdmin]&#32;&#32;\">\n\
<input type=\"radio\" name=\"OpcomAdmin\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"OpcomAdmin\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
<tr><th>Authorization:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[OpcomAuthorization]&#32;&#32;\">\n\
<input type=\"radio\" name=\"OpcomAuthorization\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"OpcomAuthorization\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
<tr><th>Control:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[OpcomControl]&#32;&#32;\">\n\
<input type=\"radio\" name=\"OpcomControl\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"OpcomControl\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
<tr><th>HTTPd:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[OpcomHTTPd]&#32;&#32;\">\n\
<input type=\"radio\" name=\"OpcomHTTPd\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"OpcomHTTPd\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
<tr><th>ProxyMaint:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[OpcomProxyMaint]&#32;&#32;\">\n\
<input type=\"radio\" name=\"OpcomProxyMaint\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"OpcomProxyMaint\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
</table>\n\
</td></tr>\n\
</table>\n\
\
<p><table class=\"ctgry\">\n\
<tr><th class=\"ctttl\">Cache</th></tr>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;&#94;# -CACHE-&#94;\">\n\
<tr><td>\n\
<table class=\"rghtlft\">\n\
<tr><th>Caching:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[Cache]&#32;&#32;\">\n\
<input type=\"radio\" name=\"Cache\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"Cache\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
<tr><th>Max Entries:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[CacheEntriesMax]&#32;&#32;\">\n\
<input type=\"text\" size=\"4\" name=\"CacheEntriesMax\" value=\"!UL\">\n\
<i>files</i></td></tr>\n\
<tr><th>Max Cache Size:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[CacheTotalKBytesMax]&#32;&#32;\">\n\
<input type=\"text\" size=\"4\" name=\"CacheTotalKBytesMax\" value=\"!UL\">\n\
<i>kBytes</i></td></tr>\n\
<tr><th>Max Entry Size:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[CacheFileKBytesMax]&#32;&#32;\">\n\
<input type=\"text\" size=\"3\" name=\"CacheFileKBytesMax\" value=\"!UL\">\n\
<i>kBytes</i></td></tr>\n\
<tr><th>Guard:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[CacheGuardPeriod]&#32;&#32;\">\n\
<input type=\"text\" size=\"7\" name=\"CacheGuardPeriod\" value=\"!AZ\">\n\
<i>hh:mm:ss</i></td></tr>\n\
<tr><th>Validate:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[CacheValidatePeriod]&#32;&#32;\">\n\
<input type=\"text\" size=\"7\" name=\"CacheValidatePeriod\" value=\"!AZ\">\n</tr>\n\
<tr><th>Frequent After:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[CacheFrequentHits]&#32;&#32;\">\n\
<input type=\"text\" size=\"3\" name=\"CacheFrequentHits\" value=\"!UL\"> \
<i>hits, last within</i>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[CacheFrequentPeriod]&#32;&#32;\">\n\
<input type=\"text\" size=\"7\" name=\"CacheFrequentPeriod\" value=\"!AZ\">\n</tr>\n\
</table>\n\
</td></tr>\n\
</table>\n\
\
<p><table class=\"ctgry\">\n\
<tr><th class=\"ctttl\">Timeouts</th></tr>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;&#94;# -TIMEOUTS-&#94;\">\n\
<tr><td>\n\
<table class=\"rghtlft\">\n\
<tr><th>Input:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[TimeoutInput]&#32;&#32;\">\n\
<input type=\"text\" size=\"7\" name=\"TimeoutInput\" value=\"!AZ\">\n\
<i>hh:mm:ss</i></td></tr>\n\
<tr><th>Output:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[TimeoutOutput]&#32;&#32;\">\n\
<input type=\"text\" size=\"7\" name=\"TimeoutOutput\" value=\"!AZ\">\n</tr>\n\
<tr><th>No-Progress:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[TimeoutNoProgress]&#32;&#32;\">\n\
<input type=\"text\" size=\"7\" name=\"TimeoutNoProgress\" value=\"!AZ\">\n</tr>\n\
<tr><th>Persistent Connection:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[TimeoutPersistent]&#32;&#32;\">\n\
<input type=\"text\" size=\"7\" name=\"TimeoutPersistent\" value=\"!AZ\">\n</tr>\n\
<tr><th>HTTP/2 Idle:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[TimeoutHttp2Idle]&#32;&#32;\">\n\
<input type=\"text\" size=\"7\" name=\"TimeoutHttp2Idle\" value=\"!AZ\">\n</tr>\n\
</table>\n\
</td></tr>\n\
</table>\n\
\
<p><table class=\"ctgry\">\n\
<tr><th class=\"ctttl\">Buffer Sizes</th></tr>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;&#94;# -BUFFER SIZES-&#94;\">\n\
<tr><td>\n\
<table class=\"rghtlft\">\n\
<tr><th>DCL <font size=\"-1\">SYS$COMMAND</font>:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[BufferSizeDclCommand]&#32;&#32;\">\n\
<input type=\"text\" size=\"6\" name=\"BufferSizeDclCommand\" value=\"!UL\">\n\
</td></tr>\n\
<tr><th>DCL <font size=\"-1\">SYS$OUTPUT</font>:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[BufferSizeDclOutput]&#32;&#32;\">\n\
<input type=\"text\" size=\"6\" name=\"BufferSizeDclOutput\" value=\"!UL\">\n\
</td></tr>\n\
<tr><th>DCL <font size=\"-1\">(SYS$OUTPUT) BUFQUO</font>:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[BufferQuotaDclOutput]&#32;&#32;\">\n\
<input type=\"text\" size=\"6\" name=\"BufferQuotaDclOutput\" value=\"!UL\">\n\
</td></tr>\n\
<tr><th>DCL <font size=\"-1\">CGIPLUSIN</font>:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[BufferSizeDclCgiPlusIn]&#32;&#32;\">\n\
<input type=\"text\" size=\"6\" name=\"BufferSizeDclCgiPlusIn\" value=\"!UL\">\n\
</td></tr>\n\
<tr><th>CGI Header:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[BufferSizeDclCgiHeader]&#32;&#32;\">\n\
<input type=\"text\" size=\"6\" name=\"BufferSizeDclCgiHeader\" value=\"!UL\">\n\
</td></tr>\n\
<tr><th>Network Read:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[BufferSizeNetRead]&#32;&#32;\">\n\
<input type=\"text\" size=\"6\" name=\"BufferSizeNetRead\" value=\"!UL\">\n\
</td></tr>\n\
<tr><th>Network Write:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[BufferSizeNetWrite]&#32;&#32;\">\n\
<input type=\"text\" size=\"6\" name=\"BufferSizeNetWrite\" value=\"!UL\">\n\
</td></tr>\n\
<tr><th>Network File:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[BufferSizeNetFile]&#32;&#32;\">\n\
<input type=\"text\" size=\"6\" name=\"BufferSizeNetFile\" value=\"!UL\">\n\
</td></tr>\n\
<tr><th>Network MTU:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[BufferSizeNetMTU]&#32;&#32;\">\n\
<input type=\"text\" size=\"6\" name=\"BufferSizeNetMTU\" value=\"!UL\">\n\
</td></tr>\n\
<tr><th>Socket SNDBUF:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[SocketSizeSndBuf]&#32;&#32;\">\n\
<input type=\"text\" size=\"6\" name=\"SocketSizeSndBuf\" value=\"!UL\">\n\
</td></tr>\n\
<tr><th>Socket RCVBUF:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[SocketSizeRcvBuf]&#32;&#32;\">\n\
<input type=\"text\" size=\"6\" name=\"SocketSizeRcvBuf\" value=\"!UL\">\n\
</td></tr>\n\
<tr><th>Note ...</a></th>\
<td>adjust with caution!!</td></tr>\n\
</table>\n\
</td></tr>\n\
</table>\n";

   static char  ConfigWelcomeFao [] = 
"<p><table class=\"ctgry\">\n\
<tr><th class=\"ctttl\">Welcome (index/home pages)</th></tr>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;&#94;# -INDEX PAGES-&#94;\">\n\
<tr><td>\n\
<table class=\"rghtlft\">\n\
<tr><td colspan=\"2\"><i>Format: \"file-name.file-type\" \
(e.g. HOME.HTML)</i></td></tr>\n\
<tr><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[Welcome]&#94;\">\n\
<textarea name=\"Welcome\" rows=\"5\" cols=\"40\" nowrap>";

   static char  ConfigAcceptFao [] = 
"</textarea>\n\
</td></tr>\n\
</table>\n\
</td></tr>\n\
</table>\n\
\
<p><table class=\"ctgry\">\n\
<tr><th class=\"ctttl\">Host Access Control</th></tr>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;&#94;# -HOST ACCESS-&#94;\">\n\
<tr><td>\n\
<table class=\"lftlft\">\n\
<tr><th>Accept</th></tr>\n\
<tr><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[Accept]&#94;\">\n\
<textarea name=\"Accept\" rows=\"4\" cols=\"40\" nowrap>\
!AZ\
</textarea>\n\
</td></tr>\n\
<tr><th>Reject</th></tr>\n\
<tr><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[Reject]&#94;\">\n\
<textarea name=\"Reject\" rows=\"4\" cols=\"40\" nowrap>\
!AZ\
</textarea>\n\
</td></tr>\n\
</table>\n\
</td></tr>\n\
</table>\n\
\
<p><table class=\"ctgry\">\n\
<tr><th class=\"ctttl\">Server Generated Reports</th></tr>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;&#94;# -REPORTS-&#94;\">\n\
<tr><td>\n\
<table class=\"rghtlft\">\n\
<tr><th>Server Admin:</th><td colspan=\"2\">\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[ServerAdmin]&#32;&#32;\">\n\
<input type=\"text\" size=\"40\" name=\"ServerAdmin\" value=\"!&;AZ\">\n\
<i>email</i></td></tr>\n\
</td></tr>\n\
<tr><th>Server Signature:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[ServerSignature]&#32;&#32;\">\n\
<input type=\"radio\" name=\"ServerSignature\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"ServerSignature\" value=\"email\"!AZ>enabled-email\n\
<input type=\"radio\" name=\"ServerSignature\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
<tr><th>Basic Info Only:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[ReportBasicOnly]&#32;&#32;\">\n\
<input type=\"radio\" name=\"ReportBasicOnly\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"ReportBasicOnly\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
<tr><th>&lt;META&gt; Info:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[ReportMetaInfo]&#32;&#32;\">\n\
<input type=\"radio\" name=\"ReportMetaInfo\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"ReportMetaInfo\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
<tr><th>Error Report Path:</th><td colspan=\"2\">\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[ErrorReportPath]&#32;&#32;\">\n\
<input type=\"text\" size=\"40\" name=\"ErrorReportPath\" value=\"!AZ\">\n\
</td></tr>\n\
<tr><th>Error Recommend:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[ErrorRecommend]&#32;&#32;\">\n\
<input type=\"radio\" name=\"ErrorRecommend\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"ErrorRecommend\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
</table>\n\
</td></tr>\n\
</table>\n\
\
<p><table class=\"ctgry\">\n\
<tr><th class=\"ctttl\">Authorization</th></tr>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;&#94;# -AUTHORIZATION-&#94;\">\n\
<tr><td>\n\
<table class=\"rghtlft\">\n\
<tr><th>Cache Entries:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[AuthCacheEntriesMax]&#32;&#32;\">\n\
<input type=\"text\" size=\"3\" name=\"AuthCacheEntriesMax\" value=\"!UL\"></td></tr>\n\
<tr><th>Cache Entry Size:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[AuthCacheEntrySize]&#32;&#32;\">\n\
<input type=\"text\" size=\"4\" name=\"AuthCacheEntrySize\" value=\"!UL\">\n\
<i>bytes</i></td></tr>\n\
<tr><th>Cache Valid:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[AuthCacheMinutes]&#32;&#32;\">\n\
<input type=\"text\" size=\"3\" name=\"AuthCacheMinutes\" value=\"!UL\">\n\
<i>minutes</i></td></tr>\n\
<tr><th>Revalidate User:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[AuthRevalidateUserMinutes]&#32;&#32;\">\n\
<input type=\"text\" size=\"3\" name=\"AuthRevalidateUserMinutes\" value=\"!UL\">\n\
<i>minutes</i></td></tr>\n\
<tr><th>Failure Limit:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[AuthFailureLimit]&#32;&#32;\">\n\
<input type=\"text\" size=\"3\" name=\"AuthFailureLimit\" value=\"!UL\">\n\
<i>attempts</i></td></tr>\n\
<tr><th>Failure Period:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[AuthFailurePeriod]&#32;&#32;\">\n\
<input type=\"text\" size=\"7\" name=\"AuthFailurePeriod\" value=\"!AZ\">\n\
<i>hh:mm:ss</i></td></tr>\n\
<tr><th>Failure Timeout:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[AuthFailureTimeout]&#32;&#32;\">\n\
<input type=\"text\" size=\"7\" name=\"AuthFailureTimeout\" value=\"!AZ\">\n\
<i>hh:mm:ss</i></td></tr>\n\
<tr><th>Token Entries:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[AuthTokenEntriesMax]&#32;&#32;\">\n\
<input type=\"text\" size=\"4\" name=\"AuthTokenEntriesMax\" value=!SL></td></tr>\n\
<tr><th>Basic Authorization:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[AuthBasic]&#32;&#32;\">\n\
<input type=\"radio\" name=\"AuthBasic\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"AuthBasic\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
<tr><th>Digest Authorization:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[AuthDigest]&#32;&#32;\">\n\
<input type=\"radio\" name=\"AuthDigest\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"AuthDigest\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
<tr><th>GET nonce lifetime:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[AuthDigestGetLife]&#32;&#32;\">\n\
<input type=\"text\" size=\"3\" name=\"AuthDigestGetLife\" value=\"!UL\">\n\
<i>minutes</i></td>\n\
</td></tr>\n\
<tr><th>PUT nonce lifetime:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[AuthDigestPutLife]&#32;&#32;\">\n\
<input type=\"text\" size=\"3\" name=\"AuthDigestPutLife\" value=\"!UL\">\n\
<i>minutes</i></td></tr>\n\
<tr><th>SYSUAF Logon Type:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[AuthSYSUAFlogonType]&#32;&#32;\">\n\
<select name=\"AuthSYSUAFlogonType\">\n\
<option value=\"\"!&? SELECTED\r\r>default\n\
<option value=\"NETWORK\"!&? SELECTED\r\r>NETWORK\n\
<option value=\"BATCH\"!&? SELECTED\r\r>BATCH\n\
<option value=\"LOCAL\"!&? SELECTED\r\r>LOCAL\n\
<option value=\"DIALUP\"!&? SELECTED\r\r>DIALUP\n\
<option value=\"REMOTE\"!&? SELECTED\r\r>REMOTE\n\
</select>\n\
</td></tr>\n\
<tr><th>SYSUAF Accept Expired Pwd:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[AuthSYSUAFacceptExpPwd]&#32;&#32;\">\n\
<input type=\"radio\" name=\"AuthSYSUAFacceptExpPwd\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"AuthSYSUAFacceptExpPwd\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
<tr><th>SYSUAF Pwd Expired URL:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[AuthSYSUAFpwdExpURL]&#32;&#32;\">\n\
<input type=\"text\" size=\"40\" name=\"AuthSYSUAFpwdExpURL\" value=\"!AZ\">\n\
</td></tr>\n\
</td></tr>\n\
</table>\n\
</td></tr>\n\
</table>\n\
\
<p><table class=\"ctgry\">\n\
<tr><th class=\"ctttl\">Proxy Serving</th></tr>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;&#94;# -PROXY SERVING-&#94;\">\n\
<tr><td>\n\
<table class=\"rghtlft\">\n\
<tr><th>Serving:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[ProxyServing]&#32;&#32;\">\n\
<input type=\"radio\" name=\"ProxyServing\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"ProxyServing\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
<tr><th>Cache:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[ProxyCache]&#32;&#32;\">\n\
<input type=\"radio\" name=\"ProxyCache\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"ProxyCache\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
<tr><th>Unknown Request Fields:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[ProxyUnknownRequestFields]&#32;&#32;\">\n\
<input type=\"radio\" name=\"ProxyUnknownRequestFields\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"ProxyProxyUnknownRequestFields\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
<tr><th>Add &quot;Forwarded: by&quot;:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[ProxyForwarded]&#32;&#32;\">\n\
<input type=\"text\" size=\"10\" name=\"ProxyForwarded\" value=\"!AZ\">\n\
</td></tr>\n\
<tr><th>Add &quot;X-Forwarded-For:&quot;:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[ProxyXForwardedFor]&#32;&#32;\">\n\
<input type=\"text\" size=\"10\" name=\"ProxyXForwardedFor\" value=\"!AZ\">\n\
</td></tr>\n\
<tr><th>Report Events To Log:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[ProxyReportLog]&#32;&#32;\">\n\
<input type=\"radio\" name=\"ProxyReportLog\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"ProxyReportLog\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
<tr><th>Report Cache Events To Log:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[ProxyReportCacheLog]&#32;&#32;\">\n\
<input type=\"radio\" name=\"ProxyReportCacheLog\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"ProxyReportCacheLog\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
<tr><th>Verify Max:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[ProxyVerifyRecordMax]&#32;&#32;\">\n\
<input type=\"text\" size=\"3\" name=ProxyVerifyRecordMax value=\"!UL\">\n\
<i>records</i></td></tr>\n\
<tr><th>Host Name Lookup Retry:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[ProxyHostLookupRetryCount]&#32;&#32;\">\n\
<input type=\"text\" size=\"3\" name=\"ProxyHostLookupRetryCount\" value=\"!UL\">\n\
<i>attempts</i></td></tr>\n\
<tr><th>Connect Timeout:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[ProxyConnectTimeoutSeconds]&#32;&#32;\">\n\
<input type=\"text\" size=\"7\" name=\"ProxyConnectTimeoutSeconds\" value=\"!AZ\">\n\
<i>hh:mm:ss</i></td></tr>\n\
<tr><th>Connect Persist Max:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[ProxyConnectPersistMax]&#32;&#32;\">\n\
<input type=\"text\" size=\"3\" name=\"ProxyConnectPersistMax\" value=\"!UL\">\n\
<i>network connections</i></td></tr>\n\
<tr><th>Connect Persist Seconds:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[ProxyConnectPersistSeconds]&#32;&#32;\">\n\
<input type=\"text\" size=\"7\" name=\"ProxyConnectPersistSeconds\" value=\"!AZ\">\n\
<i>hh:mm:ss</i></td></tr>\n\
<tr><th>Maximum Load Size:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[ProxyCacheFileKBytesMax]&#32;&#32;\">\n\
<input type=\"text\" size=\"3\" name=\"ProxyCacheFileKBytesMax\" value=\"!UL\">\n\
<i>kBytes</i></td></tr>\n\
<tr><th>Negative:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[ProxyCacheNegativeSeconds]&#32;&#32;\">\n\
<input type=\"text\" size=\"7\" name=\"ProxyCacheNegativeSeconds\" value=\"!AZ\">\n\
<i>hh:mm:ss</i></td></tr>\n\
<tr><th>No Reload:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[ProxyCacheNoReloadSeconds]&#32;&#32;\">\n\
<input type=\"text\" size=\"7\" name=\"ProxyCacheNoReloadSeconds\" value=\"!AZ\">\n\
<i>hh:mm:ss</i></td></tr>\n\
<tr><th>Reload List:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[ProxyCacheReloadList]&#32;&#32;\">\n\
<input type=\"text\" size=\"30\" name=\"ProxyCacheReloadList\" value=\"!AZ\">\n\
<i>hours</i></td></tr>\n\
<tr><th>Routine Purge:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[ProxyCacheRoutineHourOfDay]&#32;&#32;\">\n\
<input type=\"text\" size=\"3\" name=ProxyCacheRoutineHourOfDay value=\"!AZ\">\n\
<i>hour-of-day (00-23 or 24)</i></td></tr>\n\
<tr><th>Purge List:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[ProxyCachePurgeList]&#32;&#32;\">\n\
<input type=\"text\" size=\"30\" name=\"ProxyCachePurgeList\" value=\"!AZ\">\n\
<i>hours</i></td></tr>\n\
<tr><th>Device Directory Organization:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[ProxyCacheDeviceDirOrg]&#32;&#32;\">\n\
<input type=\"text\" size=\"5\" name=\"ProxyCacheDeviceDirOrg\" value=\"!AZ\">\n\
<i>flat256 or 64x64</i></td></tr>\n\
<tr><th>Device Usage Check:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[ProxyCacheDeviceCheckMinutes]&#32;&#32;\">\n\
<input type=\"text\" size=\"3\" name=ProxyCacheDeviceCheckMinutes value=\"!UL\">\n\
<i>minutes</i></td></tr>\n\
<tr><th>Device Usage Max:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[ProxyCacheDeviceMaxPercent]&#32;&#32;\">\n\
<input type=\"text\" size=\"3\" name=ProxyCacheDeviceMaxPercent value=\"!UL\">\n\
<i>percent</i></td></tr>\n\
<tr><th>Device Reduce By:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[ProxyCacheDevicePurgePercent]&#32;&#32;\">\n\
<input type=\"text\" size=\"3\" name=\"ProxyCacheDevicePurgePercent\" value=\"!UL\">\n\
<i>percent</i></td></tr>\n\
</table>\n\
</td></tr>\n\
</table>\n\
\
<p><table class=\"ctgry\">\n\
<tr><th class=\"ctttl\">Scripting  (CGI, DCL & DECnet)</th></tr>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;&#94;# -SCRIPTING-&#94;\">\n\
<tr><td>\n\
<table class=\"rghtlft\">\n\
<tr><th>Scripting:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[Scripting]&#32;&#32;\">\n\
<input type=\"radio\" name=\"Scripting\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"Scripting\" value=\"disabled\"!AZ>disabled\n\
</td><td></td></tr>\n\
<tr><th>Detach Process:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[DclDetachProcess]&#32;&#32;\">\n\
<input type=\"radio\" name=\"DclDetachProcess\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"DclDetachProcess\" value=\"disabled\"!AZ>disabled\n\
</td><td></td></tr>\n\
<tr><th>Process Priority:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[DclDetachProcessPriority]&#32;&#32;\">\n\
<input type=\"text\" size=\"6\" name=\"DclDetachProcessPriority\" value=\"!AZ\">\n\
<i>server,user</i></td></tr>\n\
<tr><th>Strict CGI Output:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[CgiStrictOutput]&#32;&#32;\">\n\
<input type=\"radio\" name=\"CgiStrictOutput\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"CgiStrictOutput\" value=\"disabled\"!AZ>disabled\n\
</td><td></td></tr>\n\
<tr><th>Spawn Authorized Privileges:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[DclSpawnAuthPriv]&#32;&#32;\">\n\
<input type=\"radio\" name=\"DclSpawnAuthPriv\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"DclSpawnAuthPriv\" value=\"disabled\"!AZ>disabled\n\
</td><td></td></tr>\n\
<tr><th>Gateway BG:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[DclGatewayBg]&#32;&#32;\">\n\
<input type=\"radio\" name=\"DclGatewayBg\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"DclGatewayBg\" value=\"disabled\"!AZ>disabled\n\
</td><td></td></tr>\n\
<tr><th>Soft Limit:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[DclSoftLimit]&#32;&#32;\">\n\
<input type=\"text\" size=\"3\" name=\"DclSoftLimit\" value=\"!UL\">\n\
<i>script processes</i></td></tr>\n\
<tr><th>Hard Limit:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[DclHardLimit]&#32;&#32;\">\n\
<input type=\"text\" size=\"3\" name=\"DclHardLimit\" value=\"!UL\">\n\
<i>script processes</i></td></tr>\n\
<tr><th>Bit-Bucket Timeout:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[DclBitBucketTimeout]&#32;&#32;\">\n\
<input type=\"text\" size=\"7\" name=\"DclBitBucketTimeout\" value=\"!AZ\">\n\
<i>hh:mm:ss</i></tr>\n\
<tr><th>Zombie Life-Time:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[DclZombieLifeTime]&#32;&#32;\">\n\
<input type=\"text\" size=\"7\" name=\"DclZombieLifeTime\" value=\"!AZ\">\n</tr>\n\
<tr><th>CGIplus Life-Time:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[DclCgiPlusLifeTime]&#32;&#32;\">\n\
<input type=\"text\" size=\"7\" name=\"DclCgiPlusLifeTime\" value=\"!AZ\">\n</tr>\n\
<tr><th>DECnet Reuse Life-Time:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[DECnetReuseLifeTime]&#32;&#32;\">\n\
<input type=\"text\" size=\"7\" name=\"DECnetReuseLifeTime\" value=\"!AZ\">\n</tr>\n\
<tr><th>DECnet Connect List Limit:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[DECnetConnectListMax]&#32;&#32;\">\n\
<input type=\"text\" size=\"4\" name=\"DECnetConnectListMax\" value=\"!UL\">\n\
<i>network connections</i></td></tr>\n\
<tr><th>Cleanup Scratch Max:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[DclCleanupScratchMinutesMax]&#32;&#32;\">\n\
<input type=\"text\" size=\"4\" name=\"DclCleanupScratchMinutesMax\" value=\"!UL\">\n\
<i>minutes</i></td></tr>\n\
<tr><th>Cleanup Older-than:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[DclCleanupScratchMinutesOld]&#32;&#32;\">\n\
<input type=\"text\" size=\"4\" name=\"DclCleanupScratchMinutesOld\" value=\"!UL\">\n\
<i>minutes</i></td></tr>\n\
<tr><th>Script Run-Time:</th></tr>\n\
<tr><td colspan=\"2\"><i>\
Format: &quot;file-type [SPACE] verb&quot;<br>\
(e.g. &quot;.PL [SPACE] PERL&quot; or &quot;.PL [SPACE] $PERL_EXE:PERL&quot)\
</i>\
</td></tr>\n\
<tr><td colspan=\"2\">\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[DclScriptRunTime]&#94;\">\n\
<textarea name=\"DclScriptRunTime\" rows=\"5\" cols=\"60\" nowrap>";

   static char  ConfigProctorFao [] =
"</textarea>\n\
<tr><th>Script Proctor:</th></tr>\n\
<tr><td colspan=\"2\"><i>\
Format: &quot;minimum[+idle] pattern activation [notepad]&quot;<br>\
(e.g. &quot;2+0 (*pyrte*) /py-bin/proctor&quot)\
</i>\
</td></tr>\n\
<tr><td colspan=\"2\">\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[DclScriptProctor]&#94;\">\n\
<textarea name=\"DclScriptProctor\" rows=\"5\" cols=\"60\" nowrap>";

   static char  ConfigSsiFao [] =
"</textarea>\n\
</table>\n\
</td></tr>\n\
</table>\n\
\
<p><table class=\"ctgry\">\n\
<tr><th class=\"ctttl\">Server-Side Includes</th></tr>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;&#94;# -SSI-&#94;\">\n\
<tr><td>\n\
<table class=\"rghtlft\">\n\
<tr><th>SSI:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[SSI]&#32;&#32;\">\n\
<input type=\"radio\" name=\"SSI\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"SSI\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
<tr><th>Exec:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[SSIexec]&#32;&#32;\">\n\
<input type=\"radio\" name=\"SSIexec\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"SSIexec\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
<tr><th>Access Counting:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[SSIaccesses]&#32;&#32;\">\n\
<input type=\"radio\" name=\"SSIaccesses\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"SSIaccesses\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
<tr><th>Max Size:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[SSISizeMax]&#32;&#32;\">\n\
<input type=\"text\" size=\"4\" name=\"SSISizeMax\" value=\"!UL\">\n\
<i>kBytes</i></td></tr>\n\
</table>\n\
</td></tr>\n\
</table>\n\
\
<p><table class=\"ctgry\">\n\
<tr><th class=\"ctttl\">WebDAV</th></tr>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;&#94;# -WebDAV-&#94;\">\n\
<tr><td>\n\
<table class=\"rghtlft\">\n\
<tr><th>WebDAV:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[WebDAV]&#32;&#32;\">\n\
<input type=\"radio\" name=\"WebDAV\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"WebDAV\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
<tr><th>Locking:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[WebDAVlocking]&#32;&#32;\">\n\
<input type=\"radio\" name=\"WebDAVlocking\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"WebDAVlocking\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
<tr><th>Lock Timeout Default:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[WebDAVlockTimeoutDefault]&#32;&#32;\">\n\
<input type=\"text\" size=\"7\" name=\"WebDAVlockTimeoutDefault\" value=\"!AZ\">\n\
<i>hh:mm:ss</i></td></tr>\n\
<tr><th>Lock Timeout Max:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[WebDAVlockTimeoutMax]&#32;&#32;\">\n\
<input type=\"text\" size=\"7\" name=\"WebDAVlockTimeoutMax\" value=\"!AZ\">\n\
<i>hh:mm:ss</i></td></tr>\n\
<tr><th>Lock Collection Depth:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[WebDAVlockCollectionDepth]&#32;&#32;\">\n\
<input type=\"text\" size=\"3\" name=\"WebDAVlockCollectionDepth\" value=\"!UL\">\n\
</td></tr>\n\
<tr><th>Quota:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[WebDAVquota]&#32;&#32;\">\n\
<input type=\"radio\" name=\"WebDAVquota\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"WebDAVquota\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
<tr><th>Meta File Directory:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[WebDAVmetaDir]&#32;&#32;\">\n\
<input type=\"text\" size=\"40\" name=\"WebDAVmetaDir\" value=\"!AZ\">\n\
</td></tr>\n\
</table>\n\
</td></tr>\n\
</table>\n\
\
<p><table class=\"ctgry\">\n\
<tr><th class=\"ctttl\">Directory (Index of...)</th></tr>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;&#94;# -DIRECTORY-&#94;\">\n\
<tr><td>\n\
<table class=\"rghtlft\">\n\
<tr><th>Access:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[DirAccess]&#32;&#32;\">\n\
<input type=\"radio\" name=\"DirAccess\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"DirAccess\" value=\"selective\"!AZ>selective\n\
<input type=\"radio\" name=\"DirAccess\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
<tr><th>Layout:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[DirLayout]&#32;&#32;\">\n\
<input type=\"text\" size=\"30\" name=\"DirLayout\" value=\"!AZ\">\n\
</td></tr>\n\
<tr><th>Listing &lt;BODY&gt;:</th><td colspan=\"2\">\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[DirBodyTag]&#32;&#32;\">\n\
<input type=\"text\" size=\"40\" name=\"DirBodyTag\" value=\"!&;AZ\">\n\
<i>HTML tag</i></td></tr>\n\
</td></tr>\n\
<tr><th>HTML Description:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[DirDescriptionLines]&#32;&#32;\">\n\
<input type=\"text\" size=\"6\" name=\"DirDescriptionLines\" value=\"!UL\">\n\
<i>lines</i></td></tr>\n\
</td></tr>\n\
<tr><th>&lt;META&gt; Info:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[DirMetaInfo]&#32;&#32;\">\n\
<input type=\"radio\" name=\"DirMetaInfo\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"DirMetaInfo\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
<tr><th>Owner:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[DirOwner]&#32;&#32;\">\n\
<input type=\"radio\" name=\"DirOwner\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"DirOwner\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
<tr><th>Pre-Expired:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[DirPreExpired]&#32;&#32;\">\n\
<input type=\"radio\" name=\"DirPreExpired\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"DirPreExpired\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
<tr><th>Wildcard:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[DirWildcard]&#32;&#32;\">\n\
<input type=\"radio\" name=\"DirWildcard\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"DirWildcard\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
<tr><th>No Implied Wildcard:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[DirNoImpliedWildcard]&#32;&#32;\">\n\
<input type=\"radio\" name=\"DirNoImpliedWildcard\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"DirNoImpliedWildcard\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
<tr><th>Prot Violations Ignored:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[DirNoPrivIgnore]&#32;&#32;\">\n\
<input type=\"radio\" name=\"DirNoPrivIgnore\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"DirNoPrivIgnore\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
<tr><th>Readme:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[DirReadme]&#32;&#32;\">\n\
<input type=\"radio\" name=\"DirReadme\" value=\"top\"!AZ>top\n\
<input type=\"radio\" name=\"DirReadme\" value=\"bottom\"!AZ>bottom\n\
<input type=\"radio\" name=\"DirReadme\" value=\"disabled\"!AZ>none\n\
</td></tr>\n\
<tr><th>Readme Files:</th></tr>\n\
<tr><td colspan=\"2\"><i>Format: &quot;file-name.file-type&quot; \
(e.g. README.HTML)</i></td></tr>\n\
<tr><td colspan=\"2\">\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[DirReadmeFile]&#94;\">\n\
<textarea name=\"DirReadmeFile\" rows=\"5\" cols=\"40\" nowrap>";

   static char  ConfigIconsFao [] =
"</textarea>\n\
</td></tr>\n\
</table>\n\
</td></tr>\n\
</table>\n\
\
<p><table class=\"ctgry\">\n\
<tr><th class=\"ctttl\">Icons</th></tr>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;&#94;# -ICONS-&#94;\">\n\
<tr><td>\n\
<table class=\"rghtlft\">\n\
<tr><td colspan=\"2\"><i>Format: &quot;icon-path [SPACE] \
alternative-text [SPACE] content-type&quot;</i></td></tr>\n\
<tr><td colspan=\"2\">\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[AddIcon]&#94;\">\n\
<textarea name=\"AddIcon\" rows=\"7\" cols=\"60\" nowrap>";

   static char  ConfigSpecialIconsFao [] =
"</textarea>\n\
</td></tr>\n\
<tr><th class=\"talft\" colspan=\"2\">Special Icons:</th></tr>\n\
<tr><td colspan=\"2\"><i>Format: &quot;icon-path [SPACE] \
alternative-text&quot;</i></td></tr>\n\
<tr><th>Blank:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[AddBlankIcon]&#32;&#32;\">\n\
<input type=\"text\" size=\"40\" name=\"AddBlankIcon\" value=\"!&;AZ\">\n\
</td></tr>\n\
<tr><th>Default:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[AddDefaultIcon]&#32;&#32;\">\n\
<input type=\"text\" size=\"40\" name=\"AddDefaultIcon\" value=\"!&;AZ\">\n\
</td></tr>\n\
<tr><th>Directory:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[AddDirIcon]&#32;&#32;\">\n\
<input type=\"text\" size=\"40\" name=\"AddDirIcon\" value=\"!&;AZ\">\n\
</td></tr>\n\
<tr><th>Parent Directory:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[AddParentIcon]&#32;&#32;\">\n\
<input type=\"text\" size=\"40\" name=\"AddParentIcon\" value=\"!&;AZ\">\n\
</td></tr>\n\
<tr><th>Unknown:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[AddUnknownIcon]&#32;&#32;\">\n\
<input type=\"text\" size=\"40\" name=\"AddUnknownIcon\" value=\"!&;AZ\">\n\
</td></tr>\n\
</table>\n\
</td></tr>\n\
</table>\n";

   static char  ConfigContentTypesFao [] =
"<p><table class=\"ctgry\">\n\
<tr><th class=\"ctttl\" colspan=\"2\">Content Types</th></tr>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;&#94;# -CONTENT TYPES-&#94;\">\n\
<tr><td>\n\
<table class=\"lftlft\">\n\
<tr><td colspan=\"2\"><i>Format: &quot;file-suffix &nbsp; \
content-type[;charset=] &nbsp; [ftp:] [rfm:] &nbsp; \
[/auto-script-path] &nbsp; description (to-end-of-line)&quot;</i></td></tr>\n\
<tr><td colspan=\"2\">\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[AddType]&#94;\">\n\
<textarea name=\"AddType\" rows=\"7\" cols=\"60\" nowrap>";

   static char  AddMimeTypesFao [] =
"</textarea>\n\
</td></tr>\n\
<tr><th colspan=\"2\">MIME.TYPES File:\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[AddMimeTypesFile]&#32;&#32;\">\n\
<input type=\"text\" size=\"40\" name=\"AddMimeTypesFile\" value=\"!&;AZ\">\n\
</th></tr>\n\
</table>\n\
</td></tr>\n\
</table>\n";

   static char  RadioButtonChecked [] = " CHECKED",
                RadioButtonUnchecked [] = "";

   int  idx,
        status;
   unsigned short  Length;
   unsigned long  *vecptr;
   unsigned long  FaoVector [128];
   char  *cptr, *sptr, *zptr,
         *IconAltPtr,
         *IconAltEndPositionPtr,
         *IconAltStartPositionPtr,
         *IconUrlPtr,
         *IconTypePtr,
         *IconTypePositionPtr,
         *SpecialIconPtr;
   char  AltTextBuffer [32],
         HtmlIconUrl [256],
         Scratch [256],
         SpecialIconBlank [SIZEOF_SPECIAL_ICON],
         SpecialIconDir [SIZEOF_SPECIAL_ICON],
         SpecialIconDefault [SIZEOF_SPECIAL_ICON],
         SpecialIconParent [SIZEOF_SPECIAL_ICON],
         SpecialIconUnknown [SIZEOF_SPECIAL_ICON],
         TimeCurrent [32];
   CONFIG_STRUCT  *cfptr;
   CONTENT_TYPE  ContentType;
   CONTENT_TYPE  *ctptr;
   ICON_TYPE  *itptr;

   /*********/
   /* begin */
   /*********/

   if (WATCHMOD (rqptr, WATCH_MOD_CONFIG))
      WatchThis (WATCHITM(rqptr), WATCH_MOD_CONFIG, "ConfigReviseNow()");

   /* get a pointer to the meta-config data */
   cfptr = mcptr->ConfigMetaPtr;

   AdminPageTitle (rqptr, "Server Configuration");
   AdminMetaConReport (rqptr, mcptr, MetaGlobalConfigPtr);
   AdminMetaConSource (rqptr, mcptr, MetaGlobalConfigPtr);

   AdminMetaConBeginUpdateForm (rqptr);

   vecptr = FaoVector;

   /* services */
   if (ServiceLoadFromConfigFile)
   {
      *vecptr++ =
"<center><b>(See &quot;Services&quot; Configuration)</b></center>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[Service]&#94;!AZ\">\n";
   }
   else
   {
      *vecptr++ =
"<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[Service]&#94;\">\n\
<textarea name=\"Service\" rows=\"5\" cols=\"60\" nowrap>\
!AZ\
</textarea>\n";
   }                   \
   *vecptr++ = ConfigStringList (rqptr, cfptr->cfServer.ServicePtr, '\n');
   *vecptr++ = cfptr->cfServer.ServiceNotFoundUrl;

   /* general */
   if (cfptr->cfServer.InstanceMax == INSTANCE_PER_CPU)
      *vecptr++ = "CPU";
   else
   {
      *vecptr++ = "!UL";
      *vecptr++ = cfptr->cfServer.InstanceMax;
   }
   REP_BOOL_RADIO (cfptr->cfServer.InstancePassive)
   if (cfptr->cfServer.ConnectMax)
      *vecptr++ = cfptr->cfServer.ConnectMax;
   else
      *vecptr++ = NetConcurrentMax;
   if (cfptr->cfServer.ProcessMax)
      *vecptr++ = cfptr->cfServer.ProcessMax;
   else
      *vecptr++ = NetConcurrentProcessMax;
   if (cfptr->cfServer.ListenBacklog)
      *vecptr++ = cfptr->cfServer.ListenBacklog;
   else
      *vecptr++ = DEFAULT_LISTEN_BACKLOG;
   *vecptr++ = cfptr->cfMisc.RequestHistory;
   *vecptr++ = cfptr->cfMisc.ActivityNumberOfDays;
   *vecptr++ = cfptr->cfContent.CharsetDefault;
   *vecptr++ = ConfigStringList (rqptr,
                  cfptr->cfContent.CharsetConvertPtr, '\n');
   REP_BOOL_RADIO (cfptr->cfMisc.MonitorEnabled)

   *vecptr++ = "!AZ";
   switch (cfptr->cfMisc.RegexSyntax)
   {
      case 0 : *vecptr++ = "disabled"; break; 
      case REGEX_C_FLAGS : *vecptr++ = "enabled"; break; 
      case RE_SYNTAX_AWK : *vecptr++ = "AWK"; break; 
      case RE_SYNTAX_EGREP : *vecptr++ = "EGREP"; break; 
      case RE_SYNTAX_GREP : *vecptr++ = "GREP"; break; 
      case RE_SYNTAX_POSIX_AWK : *vecptr++ = "POSIX_AWK"; break; 
      case RE_SYNTAX_POSIX_BASIC : *vecptr++ = "POSIX_BASIC/ED/SED"; break; 
      case RE_SYNTAX_POSIX_EGREP : *vecptr++ = "POSIX_EGREP"; break; 
      case RE_SYNTAX_POSIX_EXTENDED : *vecptr++ = "POSIX_EXTENDED"; break; 
      case RE_SYNTAX_POSIX_MINIMAL_BASIC :
                *vecptr++ = "POSIX_MINIMAL_BASIC"; break; 
      case RE_SYNTAX_POSIX_MINIMAL_EXTENDED :
                *vecptr++ = "POSIX_MINIMAL_EXTENDED"; break; 
      default : vecptr--;
                *vecptr++ = "!8XL";
                *vecptr = cfptr->cfMisc.RegexSyntax;
   }

   REP_BOOL_RADIO (cfptr->cfMisc.EntityTag)
   REP_BOOL_RADIO (cfptr->cfMisc.PipelineRequests)
   REP_BOOL_RADIO (cfptr->cfMisc.HttpTraceEnabled)
   REP_BOOL_RADIO (cfptr->cfMisc.WwwImplied)
   *vecptr++ = cfptr->cfMisc.GzipAcceptWindowBits;
   if (cfptr->cfMisc.GzipFlushSeconds &&
       cfptr->cfMisc.GzipFlushInitialSeconds)
   {
      *vecptr++ = "!UL,!UL";
      *vecptr++ =cfptr->cfMisc.GzipFlushSeconds;
      *vecptr++ =cfptr->cfMisc.GzipFlushInitialSeconds;
   }
   else
   {
      *vecptr++ = "!UL";
      *vecptr++ = cfptr->cfMisc.GzipFlushSeconds;
   }
   if (cfptr->cfMisc.GzipResponseMemLevel ||
       cfptr->cfMisc.GzipResponseWindowBits)
   {
      *vecptr++ = "!UL,!UL,!UL";
      *vecptr++ = cfptr->cfMisc.GzipResponseCompLevel;
      *vecptr++ = cfptr->cfMisc.GzipResponseMemLevel;
      *vecptr++ = cfptr->cfMisc.GzipResponseWindowBits;
   }
   else
   {
      *vecptr++ = "!UL";
      *vecptr++ = cfptr->cfMisc.GzipResponseCompLevel;
   }
   *vecptr++ = cfptr->cfServer.DefaultPort;
   *vecptr++ = cfptr->cfMisc.StreamLfConversionMaxKbytes;
   *vecptr++ = cfptr->cfScript.DefaultSearch;
   *vecptr++ = ConfigStringList (rqptr,
                  cfptr->cfScript.DefaultSearchExcludePtr, '\n');

   *vecptr++ = cfptr->cfMisc.PutMaxKbytes;
   if (cfptr->cfMisc.PutBinaryRFM == PUT_RFM_FIX512)
   {
      *vecptr++ = "";
      *vecptr++ = "";
      *vecptr++ = "";
      *vecptr++ = "";
      *vecptr++ = " SELECT";
      *vecptr++ = "";
   }
   else
   if (cfptr->cfMisc.PutBinaryRFM == PUT_RFM_STM)
   {
      *vecptr++ = "";
      *vecptr++ = " SELECT";
      *vecptr++ = "";
      *vecptr++ = "";
      *vecptr++ = "";
      *vecptr++ = "";
   }
   else
   if (cfptr->cfMisc.PutBinaryRFM == PUT_RFM_STMCR)
   {
      *vecptr++ = "";
      *vecptr++ = "";
      *vecptr++ = " SELECT";
      *vecptr++ = "";
      *vecptr++ = "";
      *vecptr++ = "";
   }
   else
   if (cfptr->cfMisc.PutBinaryRFM == PUT_RFM_STMLF)
   {
      *vecptr++ = "";
      *vecptr++ = "";
      *vecptr++ = "";
      *vecptr++ = " SELECT";
      *vecptr++ = "";
      *vecptr++ = "";
   }
   else
   if (cfptr->cfMisc.PutBinaryRFM == PUT_RFM_UDF)
   {
      *vecptr++ = "";
      *vecptr++ = "";
      *vecptr++ = "";
      *vecptr++ = "";
      *vecptr++ = "";
      *vecptr++ = " SELECT";
   }
   else
   {
      *vecptr++ = " SELECT";
      *vecptr++ = "";
      *vecptr++ = "";
      *vecptr++ = "";
      *vecptr++ = "";
      *vecptr++ = "";
   }
   *vecptr++ = cfptr->cfMisc.PutVersionLimit;

   if (cfptr == &Config)
      *vecptr++ = MapUrlUserNameCacheEntries;
   else
      *vecptr++ = cfptr->cfMisc.MapUserNameCacheEntries;
   if (cfptr == &Config)
      *vecptr++ = PersonaCacheEntries;
   else
      *vecptr++ = cfptr->cfMisc.PersonaCacheEntries;

   /* DNS host resolution */
   REP_BOOL_RADIO (cfptr->cfMisc.DnsLookupClient)
   *vecptr++ = MetaConShowSeconds (rqptr, cfptr->cfMisc.DnsLookupLifeTimeSeconds);
   *vecptr++ = cfptr->cfMisc.DnsLookupRetryCount;

   /* logging */
   REP_BOOL_RADIO (cfptr->cfLog.Enabled)
   *vecptr++ = cfptr->cfLog.Format;
   *vecptr++ = cfptr->cfLog.Naming;
   *vecptr++ = cfptr->cfLog.Period;
   REP_BOOL_RADIO (cfptr->cfLog.PerInstance)
   REP_BOOL_RADIO (cfptr->cfLog.PerService)
   REP_BOOL_RADIO (cfptr->cfLog.PerServiceHostOnly)
   REP_BOOL_RADIO (cfptr->cfLog.WriteFail503)
   *vecptr++ = cfptr->cfLog.FileName;
   *vecptr++ = cfptr->cfLog.ExtendBlocks;
   *vecptr++ = ConfigStringList (rqptr, cfptr->cfLog.ExcludeHostsPtr, '\n');

   FaoCheck (sizeof(FaoVector), &FaoVector, vecptr, FI_LI);
   status = FaolToNet (rqptr, ConfigGeneralFao, &FaoVector);
   if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI);

   /* OPCOM messages */
   for (idx = 0; ConfigOpcomTarget[idx].Number >= 0; idx++)
   {
      vecptr = FaoVector;
      *vecptr++ = ConfigOpcomTarget[idx].Name;
      *vecptr++ = (OpcomTarget == ConfigOpcomTarget[idx].Number);
      *vecptr++ = ConfigOpcomTarget[idx].Name;

      status = FaolToNet (rqptr, ConfigOpcomTargetFao, &FaoVector);
      if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI);
   }

   vecptr = FaoVector;

   REP_BOOL_RADIO (cfptr->cfOpcom.Messages & OPCOM_ADMIN)
   REP_BOOL_RADIO (cfptr->cfOpcom.Messages & OPCOM_AUTHORIZATION)
   REP_BOOL_RADIO (cfptr->cfOpcom.Messages & OPCOM_CONTROL)
   REP_BOOL_RADIO (cfptr->cfOpcom.Messages & OPCOM_HTTPD)
   REP_BOOL_RADIO (cfptr->cfOpcom.Messages & OPCOM_PROXY_MAINT)

   /* cache */
   REP_BOOL_RADIO (cfptr->cfCache.Enabled)
   *vecptr++ = cfptr->cfCache.EntriesMax;
   *vecptr++ = cfptr->cfCache.TotalKBytesMax;
   *vecptr++ = cfptr->cfCache.FileKBytesMax;
   *vecptr++ = MetaConShowSeconds (rqptr, cfptr->cfCache.GuardSeconds);
   *vecptr++ = MetaConShowSeconds (rqptr, cfptr->cfCache.ValidateSeconds);
   *vecptr++ = cfptr->cfCache.FrequentHits;
   *vecptr++ = MetaConShowSeconds (rqptr, cfptr->cfCache.FrequentSeconds);

   /* timeouts */
   *vecptr++ = MetaConShowSeconds (rqptr, cfptr->cfTimeout.Input);
   *vecptr++ = MetaConShowSeconds (rqptr, cfptr->cfTimeout.Output);
   *vecptr++ = MetaConShowSeconds (rqptr, cfptr->cfTimeout.NoProgress);
   *vecptr++ = MetaConShowSeconds (rqptr, cfptr->cfTimeout.Persistent);
   *vecptr++ = MetaConShowSeconds (rqptr, cfptr->cfTimeout.Http2Idle);

   /* buffer sizes */
   if (cfptr == &Config)
   {
      /* in-use values */
      *vecptr++ = DclSysCommandSize;
      *vecptr++ = DclSysOutputSize;
      *vecptr++ = DclSysOutputQuota;
      *vecptr++ = DclCgiPlusInSize;
      *vecptr++ = DclCgiHeaderSize;
      *vecptr++ = NetReadBufferSize;
      *vecptr++ = OutputBufferSize;
      *vecptr++ = OutputFileBufferSize;
      *vecptr++ = cfptr->cfBuffer.SizeNetMTU;
      *vecptr++ = TcpIpSocketSndBufSize;
      *vecptr++ = TcpIpSocketRcvBufSize;
   }
   else
   {
      /* file values */
      *vecptr++ = cfptr->cfBuffer.SizeDclCommand;
      *vecptr++ = cfptr->cfBuffer.SizeDclOutput;
      *vecptr++ = cfptr->cfBuffer.QuotaDclOutput;
      *vecptr++ = cfptr->cfBuffer.SizeDclCgiPlusIn;
      *vecptr++ = cfptr->cfBuffer.SizeDclCgiHeader;
      *vecptr++ = cfptr->cfBuffer.SizeNetRead;
      *vecptr++ = cfptr->cfBuffer.SizeNetWrite;
      *vecptr++ = cfptr->cfBuffer.SizeNetFile;
      *vecptr++ = cfptr->cfBuffer.SizeNetMTU;
      *vecptr++ = cfptr->cfBuffer.SizeSocketSndBuf;
      *vecptr++ = cfptr->cfBuffer.SizeSocketRcvBuf;
   }

   FaoCheck (sizeof(FaoVector), &FaoVector, vecptr, FI_LI);
   status = FaolToNet (rqptr, ConfigOpcomFao, &FaoVector);
   if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI);

   /**********/
   /* HTTP/2 */
   /**********/

   ConfigReviseHttp2 (rqptr, mcptr);

   /*****************/
   /* secure socket */
   /*****************/

   ConfigReviseSecureSocket (rqptr, mcptr);

   /*****************************/
   /* welcome (home page) files */
   /*****************************/

   status = FaolToNet (rqptr, ConfigWelcomeFao, NULL);
   if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI);

   for (idx = 0; idx < cfptr->cfContent.HomePageCount; idx++)
   {
      status = FaoToNet (rqptr, "!&;AZ\n", cfptr->cfContent.HomePageArray[idx]);
      if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI);
   }

   /********/
   /* more */
   /********/

   vecptr = FaoVector;

   /* accept and reject hosts */
   *vecptr++ = ConfigStringList (rqptr, cfptr->cfServer.AcceptHostsPtr, '\n');
   *vecptr++ = ConfigStringList (rqptr, cfptr->cfServer.RejectHostsPtr, '\n');

   *vecptr++ = cfptr->cfServer.AdminEmail;
   if (cfptr->cfServer.Signature == CONFIG_SERVER_SIGNATURE_ON)
      *vecptr++ = " CHECKED";
   else
      *vecptr++ = "";
   if (cfptr->cfServer.Signature == CONFIG_SERVER_SIGNATURE_EMAIL)
      *vecptr++ = " CHECKED";
   else
      *vecptr++ = "";
   if (cfptr->cfServer.Signature == CONFIG_SERVER_SIGNATURE_OFF)
      *vecptr++ = " CHECKED";
   else
      *vecptr++ = "";
   REP_BOOL_RADIO (cfptr->cfReport.BasicOnly)
   REP_BOOL_RADIO (cfptr->cfReport.MetaInfoEnabled)
   *vecptr++ = cfptr->cfReport.ErrorReportPath;
   REP_BOOL_RADIO (cfptr->cfReport.ErrorRecommend)

   /* authorization */
   *vecptr++ = cfptr->cfAuth.CacheEntriesMax;
   *vecptr++ = cfptr->cfAuth.CacheEntrySize;
   *vecptr++ = cfptr->cfAuth.CacheMinutes;
   *vecptr++ = cfptr->cfAuth.RevalidateUserMinutes;
   *vecptr++ = cfptr->cfAuth.FailureLimit;
   *vecptr++ = MetaConShowSeconds (rqptr, cfptr->cfAuth.FailurePeriodSeconds);
   *vecptr++ = MetaConShowSeconds (rqptr, cfptr->cfAuth.FailureTimeoutSeconds);
   *vecptr++ = cfptr->cfAuth.TokenEntriesMax;
   REP_BOOL_RADIO (cfptr->cfAuth.BasicEnabled)
   REP_BOOL_RADIO (cfptr->cfAuth.DigestEnabled)
   *vecptr++ = cfptr->cfAuth.DigestNonceGetLifeTime;
   *vecptr++ = cfptr->cfAuth.DigestNonceGetLifeTime;

   if (!cfptr->cfAuth.SysUafLogonType)
      *vecptr++ = TRUE;
   else
      *vecptr++ = FALSE;
   if (cfptr->cfAuth.SysUafLogonType == AUTH_LOGON_TYPE_NETWORK)
      *vecptr++ = TRUE;
   else
      *vecptr++ = FALSE;
   if (cfptr->cfAuth.SysUafLogonType == AUTH_LOGON_TYPE_BATCH)
      *vecptr++ = TRUE;
   else
      *vecptr++ = FALSE;
   if (cfptr->cfAuth.SysUafLogonType == AUTH_LOGON_TYPE_LOCAL)
      *vecptr++ = TRUE;
   else
      *vecptr++ = FALSE;
   if (cfptr->cfAuth.SysUafLogonType == AUTH_LOGON_TYPE_DIALUP)
      *vecptr++ = TRUE;
   else
      *vecptr++ = FALSE;
   if (cfptr->cfAuth.SysUafLogonType == AUTH_LOGON_TYPE_REMOTE)
      *vecptr++ = TRUE;
   else
      *vecptr++ = FALSE;

   REP_BOOL_RADIO (cfptr->cfAuth.SysUafAcceptExpPwd)
   *vecptr++ = cfptr->cfAuth.SysUafPwdExpUrl;

   /* proxy serving */
   REP_BOOL_RADIO (cfptr->cfProxy.ServingEnabled)
   REP_BOOL_RADIO (cfptr->cfProxy.CacheEnabled)
   REP_BOOL_RADIO (cfptr->cfProxy.UnknownRequestFields)
   if (cfptr->cfProxy.ForwardedBy == PROXY_FORWARDED_BY)
      *vecptr++ = "BY";
   else
   if (cfptr->cfProxy.ForwardedBy == PROXY_FORWARDED_FOR)
      *vecptr++ = "FOR";
   else
   if (cfptr->cfProxy.ForwardedBy == PROXY_FORWARDED_ADDRESS)
      *vecptr++ = "ADDRESS";
   else
      *vecptr++ = "disabled";
   if (cfptr->cfProxy.XForwardedFor == PROXY_XFORWARDEDFOR_ENABLED)
      *vecptr++ = "ENABLED";
   else
   if (cfptr->cfProxy.XForwardedFor == PROXY_XFORWARDEDFOR_UNKNOWN)
      *vecptr++ = "UNKNOWN";
   else
   if (cfptr->cfProxy.XForwardedFor == PROXY_XFORWARDEDFOR_ADDRESS)
      *vecptr++ = "ADDRESS";
   else
      *vecptr++ = "disabled";
   REP_BOOL_RADIO (cfptr->cfProxy.ReportLog)
   REP_BOOL_RADIO (cfptr->cfProxy.ReportCacheLog)
   *vecptr++ = cfptr->cfProxy.VerifyRecordMax;
   *vecptr++ = cfptr->cfProxy.HostLookupRetryCount;
   *vecptr++ = MetaConShowSeconds (rqptr, cfptr->cfProxy.ConnectTimeoutSeconds);
   *vecptr++ = cfptr->cfProxy.ConnectPersistMax;
   *vecptr++ = MetaConShowSeconds (rqptr, cfptr->cfProxy.ConnectPersistSeconds);
   *vecptr++ = cfptr->cfProxy.CacheFileKBytesMax;
   *vecptr++ = MetaConShowSeconds (rqptr, cfptr->cfProxy.CacheNegativeSeconds);
   *vecptr++ = MetaConShowSeconds (rqptr, cfptr->cfProxy.CacheNoReloadSeconds);
   *vecptr++ = cfptr->cfProxy.CacheReloadList;
   *vecptr++ = cfptr->cfProxy.CacheRoutineHourOfDayString;
   *vecptr++ = cfptr->cfProxy.CachePurgeList;
   if (cfptr->cfProxy.CacheDeviceDirOrg == PROXY_CACHE_DIR_ORG_FLAT256)
      *vecptr++ = "flat256";
   else
   if (cfptr->cfProxy.CacheDeviceDirOrg == PROXY_CACHE_DIR_ORG_64X64)
      *vecptr++ = "64x64";
   else
      *vecptr++ = "";
   *vecptr++ = cfptr->cfProxy.CacheDeviceCheckMinutes;
   *vecptr++ = cfptr->cfProxy.CacheDeviceMaxPercent;
   *vecptr++ = cfptr->cfProxy.CacheDevicePurgePercent;

   /* scripting */
   REP_BOOL_RADIO (cfptr->cfScript.Enabled)
   REP_BOOL_RADIO (cfptr->cfScript.DetachProcess)
   *vecptr++ = cfptr->cfScript.DetachProcessPriority;
   REP_BOOL_RADIO (cfptr->cfScript.CgiStrictOutput)
   REP_BOOL_RADIO (cfptr->cfScript.SpawnAuthPriv)
   REP_BOOL_RADIO (cfptr->cfScript.GatewayBg)
   *vecptr++ = cfptr->cfScript.ScriptProcessSoftLimit;
   *vecptr++ = cfptr->cfScript.ScriptProcessHardLimit;
   *vecptr++ = MetaConShowSeconds (rqptr, cfptr->cfScript.BitBucketTimeout);
   *vecptr++ = MetaConShowSeconds (rqptr, cfptr->cfScript.ZombieLifeTime);
   *vecptr++ = MetaConShowSeconds (rqptr, cfptr->cfScript.CgiPlusLifeTime);
   *vecptr++ = MetaConShowSeconds (rqptr, cfptr->cfScript.DECnetReuseLifeTime);
   *vecptr++ = cfptr->cfScript.DECnetConnectListMax;
   *vecptr++ = cfptr->cfScript.CleanupScratchMinutesMax;
   *vecptr++ = cfptr->cfScript.CleanupScratchMinutesOld;

   FaoCheck (sizeof(FaoVector), &FaoVector, vecptr, FI_LI);
   status = FaolToNet (rqptr, ConfigAcceptFao, &FaoVector);
   if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI);

   /****************/
   /* script types */
   /****************/

   for (idx = 0; idx < cfptr->cfScript.RunTimeCount; idx++)
   {
      vecptr = FaoVector;

      cptr = sptr = cfptr->cfScript.RunTime[idx].StringPtr;
      /* length of and location of the file type */
      while (*cptr && *cptr != ';') cptr++;
      *vecptr++ = cptr - sptr;
      *vecptr++ = sptr;
      /* location of verb */
      cptr += 2;
      *vecptr++ = cptr;

      status = FaolToNet (rqptr, "!#&;AZ !&;AZ\n", &FaoVector);
      if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI);
   }

   status = FaolToNet (rqptr, ConfigProctorFao, &FaoVector);
   if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI);

   /******************/
   /* script proctor */
   /******************/

   if (cfptr->cfScript.ProctorCount)
   {
      for (idx = 0; idx < cfptr->cfScript.ProctorCount; idx++)
      {
         vecptr = FaoVector;

         *vecptr++ = cfptr->cfScript.Proctor[idx].NumberMin;
         *vecptr++ = cfptr->cfScript.Proctor[idx].NumberIdle;
         *vecptr++ = *cfptr->cfScript.Proctor[idx].RunTimePtr ? "(" : "";
         *vecptr++ = cfptr->cfScript.Proctor[idx].RunTimePtr;
         *vecptr++ = *cfptr->cfScript.Proctor[idx].RunTimePtr ? ")" : "";
         *vecptr++ = cfptr->cfScript.Proctor[idx].ScriptPtr;
         *vecptr++ = cfptr->cfScript.Proctor[idx].ActivatePtr;
         *vecptr++ = *cfptr->cfScript.Proctor[idx].NotePadPtr ? "  " : "";
         *vecptr++ = cfptr->cfScript.Proctor[idx].NotePadPtr;

         status = FaolToNet (rqptr, "!UL+!UL  !AZ!AZ!AZ!AZ  !AZ!AZ!AZ\n",
                             &FaoVector);
         if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI);
      }
   }

   /********/
   /* more */
   /********/

   vecptr = FaoVector;

   /* SSI (.shtml) */
   REP_BOOL_RADIO (cfptr->cfSsi.Enabled)
   REP_BOOL_RADIO (cfptr->cfSsi.ExecEnabled)
   REP_BOOL_RADIO (cfptr->cfSsi.AccessesEnabled)
   *vecptr++ = cfptr->cfSsi.SizeMax;

   /* WebDAV */
   REP_BOOL_RADIO (cfptr->cfWebDav.DavEnabled)
   REP_BOOL_RADIO (cfptr->cfWebDav.LockingEnabled)
   *vecptr++ = MetaConShowSeconds (rqptr,
                  cfptr->cfWebDav.LockTimeoutDefaultSeconds);
   *vecptr++ = MetaConShowSeconds (rqptr,
                  cfptr->cfWebDav.LockTimeoutMaxSeconds);
   *vecptr++ = cfptr->cfWebDav.LockCollectionDepth;
   REP_BOOL_RADIO (cfptr->cfWebDav.QuotaEnabled)
   *vecptr++ = cfptr->cfWebDav.MetaFileDirectory;

   /* directory */
   if (cfptr->cfDir.Access)
   {
      *vecptr++ = " CHECKED";
      *vecptr++ = "";
      *vecptr++ = "";
   }
   else
   if (cfptr->cfDir.AccessSelective)
   {
      *vecptr++ = "";
      *vecptr++ = " CHECKED";
      *vecptr++ = "";
   }
   else
   {
      *vecptr++ = "";
      *vecptr++ = "";
      *vecptr++ = " CHECKED";
   }
   *vecptr++ = cfptr->cfDir.DefaultLayout;
   *vecptr++ = cfptr->cfDir.BodyTag;
   *vecptr++ = cfptr->cfDir.DescriptionLines;
   REP_BOOL_RADIO (cfptr->cfDir.MetaInfoEnabled)
   REP_BOOL_RADIO (cfptr->cfDir.OwnerEnabled)
   REP_BOOL_RADIO (cfptr->cfDir.PreExpired)
   REP_BOOL_RADIO (cfptr->cfDir.WildcardEnabled)
   REP_BOOL_RADIO (cfptr->cfDir.NoImpliedWildcard)
   REP_BOOL_RADIO (cfptr->cfDir.NoPrivIgnore)
   if (cfptr->cfDir.ReadMeTop)
   {
      *vecptr++ = " CHECKED";
      *vecptr++ = "";
      *vecptr++ = "";
   }
   else
   if (cfptr->cfDir.ReadMeBottom)
   {
      *vecptr++ = "";
      *vecptr++ = " CHECKED";
      *vecptr++ = "";
   }
   else
   {
      *vecptr++ = "";
      *vecptr++ = "";
      *vecptr++ = " CHECKED";
   }
   REP_BOOL_RADIO (cfptr->cfDir.WildcardEnabled)

   FaoCheck (sizeof(FaoVector), &FaoVector, vecptr, FI_LI);
   status = FaolToNet (rqptr, ConfigSsiFao, &FaoVector);
   if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI);

   /****************/
   /* readme files */
   /****************/

   for (idx = 0; idx < cfptr->cfDir.ReadMeFileCount; idx++)
   {
      status = FaoToNet (rqptr, "!&@!&;AZ",
                         idx ? "\n" : "", cfptr->cfDir.ReadMeFileArray[idx]);
      if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI);
   }

   /*********/
   /* icons */
   /*********/

   status = FaolToNet (rqptr, ConfigIconsFao, NULL);
   if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI);

   SpecialIconBlank[0] = SpecialIconDefault[0] = SpecialIconDir[0] =
      SpecialIconParent[0] = SpecialIconUnknown[0] = '\n';
   SpecialIconBlank[1] = SpecialIconDefault[0] = SpecialIconDir[1] =
      SpecialIconParent[1] = SpecialIconUnknown[1] = '\0';

   for (itptr = cfptr->cfContent.IconListHeadPtr;
        itptr;
        itptr = itptr->NextPtr)
   {
      if (itptr->FromMimeTypes) continue;

      SpecialIconPtr = NULL;
      if (strsame (itptr->ContentTypePtr, ConfigContentTypeBlank, -1))
         SpecialIconPtr = SpecialIconBlank;
      else
      if (strsame (itptr->ContentTypePtr, ConfigContentTypeDir, -1))
         SpecialIconPtr = SpecialIconDir;
      else
      if (strsame (itptr->ContentTypePtr, ConfigContentTypeDefaultIcon, -1))
         SpecialIconPtr = SpecialIconDefault;
      else
      if (strsame (itptr->ContentTypePtr, ConfigContentTypeParent, -1))
         SpecialIconPtr = SpecialIconParent;
      else
      if (strsame (itptr->ContentTypePtr, ConfigContentTypeUnknown, -1))
         SpecialIconPtr = SpecialIconUnknown;

      zptr = (sptr = AltTextBuffer) + sizeof(AltTextBuffer)-1;
      for (cptr = itptr->AltTextPtr; *cptr && sptr < zptr; cptr++)
         if (*cptr == ' ') *sptr++ = '_'; else *sptr++ = *cptr;

      vecptr = FaoVector;
      *vecptr++ = itptr->IconUriPtr;
      *vecptr++ = AltTextBuffer;
      *vecptr++ = itptr->ContentTypePtr;
      status = FaolToNet (rqptr, "!AZ  !AZ  !&;AZ\n", &FaoVector);
      if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI);
   }

   vecptr = FaoVector;
   *vecptr++ = SpecialIconBlank;
   *vecptr++ = SpecialIconDefault;
   *vecptr++ = SpecialIconDir;
   *vecptr++ = SpecialIconParent;
   *vecptr++ = SpecialIconUnknown;

   status = FaolToNet (rqptr, ConfigSpecialIconsFao, &FaoVector);
   if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI);

   /*****************/
   /* content types */
   /*****************/

   status = FaolToNet (rqptr, ConfigContentTypesFao, NULL);
   if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI);

   for (ctptr = cfptr->cfContent.ContentInfoListHeadPtr;
        ctptr;
        ctptr = ctptr->NextPtr)
   {
      if (ctptr->FromMimeTypes) continue;

      vecptr = &FaoVector;
      *vecptr++ = ctptr->SuffixPtr;
      if (!strchr (ctptr->ContentTypePtr, ';'))
         *vecptr++ = "  !AZ";
      else
         *vecptr++ = "  \"!AZ\"";
      *vecptr++ = ctptr->ContentTypePtr;

      if (ctptr->PutRFM)
      {
         *vecptr++ = " RFM:!AZ";
         if (ctptr->PutRFM == PUT_RFM_FIX512)
            *vecptr++ = "FIX512";
         else
         if (ctptr->PutRFM == PUT_RFM_STM)
            *vecptr++ = "STM";
         else
         if (ctptr->PutRFM == PUT_RFM_STMCR)
            *vecptr++ = "STMCR";
         else
         if (ctptr->PutRFM == PUT_RFM_STMLF)
            *vecptr++ = "STMLF";
         else
         if (ctptr->PutRFM == PUT_RFM_UDF)
            *vecptr++ = "UDF";
         else
            *vecptr++ = "?";
      }
      else
         *vecptr++ = "";

      if (ctptr->FtpMode)
      {
         *vecptr++ = " FTP:!&C";
         *vecptr++ = ctptr->FtpMode;
      }
      else
         *vecptr++ = "";

      if (ctptr->AutoScriptNamePtr[0])
      {
         *vecptr++ = "  !AZ";
         *vecptr++ = ctptr->AutoScriptNamePtr;
      }
      else
         *vecptr++ = "";
      *vecptr++ = "  !&;AZ";
      if (ctptr->TypeUnknown)
         *vecptr++ = cfptr->cfContent.ContentTypeDefaultPtr;
      else
         *vecptr++ = ctptr->DescriptionPtr;

      status = FaolToNet (rqptr, "!AZ!&@!&@!&@!&@!&@\n", &FaoVector);
      if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI);
   }

   vecptr = FaoVector;
   *vecptr++ = cfptr->cfContent.MimeTypesFileName;
   status = FaolToNet (rqptr, AddMimeTypesFao, &FaoVector);
   if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI);

   AdminMetaConEndUpdateForm (rqptr);

   status = FaolToNet (rqptr, "</body>\n</html>\n", NULL);
   if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI);

   rqptr->rqResponse.PreExpired = PRE_EXPIRE_ADMIN;
   ResponseHeader200 (rqptr, "text/html", &rqptr->NetWriteBufferDsc);

#undef REP_BOOL_RADIO
}

/*****************************************************************************/
/*
Server Admin SSL configuration report.
*/

extern int  Http2MaxConcurrentStreams,
            Http2MaxFrameSize,
            Http2MaxHeaderListSize,
            Http2MaxHeaderTableSize,
            Http2InitialWindowSize,
            Http2PingTimerSeconds;

ConfigReportHttp2
(
REQUEST_STRUCT *rqptr,
META_CONFIG *mcptr
)
{
/* macro to push booleans onto the parameter list */
#define REP_ENDIS(b) \
if (b) *vecptr++ = "[enabled]"; else *vecptr++ = "[disabled]";

   static char ReportHttp2Fao [] =
"<p><table class=\"ctgry\">\n\
<tr><th class=\"ctttl\">HTTP/2 !AZ</th></tr>\n\
<tr><td>\n\
<table class=\"rghtlft\">\n\
<tr><th>HTTP/2:</th><td>!AZ</td></tr>\n\
<tr><th>Max Concurrent Streams:</th><td>!UL</td>\
<td><i></i></td></tr>\n\
<tr><th>Max Frame Size:</th><td>!UL</td>\
<td><i></i></td></tr>\n\
<tr><th>Max Header List Size:</th><td>!UL</td>\
<td><i></i></td></tr>\n\
<tr><th>Max Header Table Size:</th><td>!UL</td>\
<td><i></i></td></tr>\n\
<tr><th>Initial Window Size:</th><td>!UL</td>\
<td><i></i></td></tr>\n\
<tr><th>Ping Timer:</th><td>!AZ</td></tr>\n\
</table>\n\
</td></tr>\n\
</table>\n";

   int  status;
   unsigned long  *vecptr;
   unsigned long  FaoVector [32];
   CONFIG_STRUCT  *cfptr;

   /*********/
   /* begin */
   /*********/

   if (WATCHMOD (rqptr, WATCH_MOD_CONFIG))
      WatchThis (WATCHITM(rqptr), WATCH_MOD_CONFIG, "ConfigReportHttp2()");

   /* get a pointer to the meta-config data */
   cfptr = mcptr->ConfigMetaPtr;

   vecptr = FaoVector;

   /* buffer sizes */
   if (cfptr == &Config)
   {
      /* in-use values */
      *vecptr++ = "(in-use)";
      REP_ENDIS (cfptr->cfHttp2.Enabled);
      *vecptr++ = Http2MaxConcurrentStreams;
      *vecptr++ = Http2MaxFrameSize;
      *vecptr++ = Http2MaxHeaderListSize;
      *vecptr++ = Http2MaxHeaderTableSize;
      *vecptr++ = Http2InitialWindowSize;
      *vecptr++ = MetaConShowSeconds (rqptr, Http2PingTimerSeconds);
   }
   else
   {
      /* file values */
      *vecptr++ = "(config)";
      REP_ENDIS (cfptr->cfHttp2.Enabled);
      *vecptr++ = cfptr->cfHttp2.MaxConcurrentStreams;
      *vecptr++ = cfptr->cfHttp2.MaxFrameSize;
      *vecptr++ = cfptr->cfHttp2.MaxHeaderListSize;
      *vecptr++ = cfptr->cfHttp2.MaxHeaderTableSize;
      *vecptr++ = cfptr->cfHttp2.InitialWindowSize;
      *vecptr++ = MetaConShowSeconds (rqptr, cfptr->cfHttp2.PingTimerSeconds);
   }

   status = FaolToNet (rqptr, ReportHttp2Fao, &FaoVector);
   if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI);

#undef REP_ENDIS
}

/*****************************************************************************/
/*
Server Admin HTTP/2 configuration menu.
*/

ConfigReviseHttp2
(
REQUEST_STRUCT *rqptr,
META_CONFIG *mcptr
)
{
#define REP_BOOL_RADIO(b)\
if (b)\
{\
   *vecptr++ = RadioButtonChecked;\
   *vecptr++ = RadioButtonUnchecked;\
}\
else\
{\
   *vecptr++ = RadioButtonUnchecked;\
   *vecptr++ = RadioButtonChecked;\
}

   static char ReviseHttp2Fao [] =
"<p><table class=\"ctgry\">\n\
<tr><th class=\"ctttl\">HTTP/2</th></tr>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;&#94;# -HTTP/2-&#94;\">\n\
<tr><td>\n\
<table class=\"rghtlft\">\n\
\
<tr><th>HTTP/2:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[Http2Protocol]&#32;\">\n\
<input type=\"radio\" name=\"Http2Protocol\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"Http2Protocol\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
\
<tr><th>Concurrent Streams Max:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[Http2StreamsMax]&#32;&#32;\">\n\
<input type=\"text\" size=\"5\" name=\"Http2StreamsMax\" value=\"!UL\">\n\
<i></i></td></tr>\n\
\
<tr><th>Frame Size Max:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[Http2FrameSizeMax]&#32;&#32;\">\n\
<input type=\"text\" size=\"5\" name=\"Http2FrameSizeMax\" value=\"!UL\">\n\
<i></i></td></tr>\n\
\
<tr><th>Header List Max:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[Http2HeaderListMax]&#32;&#32;\">\n\
<input type=\"text\" size=\"5\" name=\"Http2HeaderListMax\" value=\"!UL\">\n\
<i></i></td></tr>\n\
\
<tr><th>Header Table Max:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[Http2HeaderTableMax]&#32;&#32;\">\n\
<input type=\"text\" size=\"5\" name=\"Http2HeaderTableMax\" value=\"!UL\">\n\
<i></i></td></tr>\n\
\
<tr><th>Initial Window Size:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[Http2InitWindowSize]&#32;&#32;\">\n\
<input type=\"text\" size=\"5\" name=\"Http2InitWindowSize\" value=\"!UL\">\n\
<i></i></td></tr>\n\
\
<tr><th>Ping Timer:</th><td>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[Http2PingSeconds]&#32;&#32;\">\n\
<input type=\"text\" size=\"7\" name=\"Http2PingSeconds\" value=\"!AZ\">\n\
<i>hh:mm:ss</i></td></tr>\n\
\
</table>\n\
</td></tr>\n\
</table>\n";

   static char  RadioButtonChecked [] = " CHECKED",
                RadioButtonUnchecked [] = "";

   int  status;
   unsigned long  *vecptr;
   unsigned long  FaoVector [32];
   CONFIG_STRUCT  *cfptr;

   /*********/
   /* begin */
   /*********/

   if (WATCHMOD (rqptr, WATCH_MOD_CONFIG))
      WatchThis (WATCHITM(rqptr), WATCH_MOD_CONFIG, "ConfigReviseHttp2()");

   /* get a pointer to the meta-config data */
   cfptr = mcptr->ConfigMetaPtr;

   vecptr = FaoVector;

   REP_BOOL_RADIO (cfptr->cfHttp2.Enabled);
   *vecptr++ = cfptr->cfHttp2.MaxConcurrentStreams;
   *vecptr++ = cfptr->cfHttp2.MaxFrameSize;
   *vecptr++ = cfptr->cfHttp2.MaxHeaderListSize;
   *vecptr++ = cfptr->cfHttp2.MaxHeaderTableSize;
   *vecptr++ = cfptr->cfHttp2.InitialWindowSize;
   *vecptr++ = MetaConShowSeconds (rqptr, cfptr->cfHttp2.PingTimerSeconds);

   status = FaolToNet (rqptr, ReviseHttp2Fao, &FaoVector);
   if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI);

#undef REP_BOOL_RADIO
}

/*****************************************************************************/
/*
Server Admin SSL configuration report.
*/

ConfigReportSecureSocket
(
REQUEST_STRUCT *rqptr,
META_CONFIG *mcptr
)
{
/* macro to push booleans onto the parameter list */
#define REP_ENDIS(b) \
if (b) *vecptr++ = "[enabled]"; else *vecptr++ = "[disabled]";

/* report a string, or if empty as "(none)" */
#define REP_DEFAULT(s) \
if (s[0]) *vecptr++ = s; else *vecptr++ = ConfigNoteDefault;

   static char ReportSslFao [] =
"<p><table class=\"ctgry\">\n\
<tr><th class=\"ctttl\">!AZSecure Socket (SSL/TLS)!AZ</th></tr>\n\
<tr><td>\n\
<table class=\"rghtlft\">\n\
<tr><th>Secure Socket:</th><td>!AZ</td></tr>\n\
<tr><th>Protocol:</th><td>!AZ</td></tr>\n\
<tr><th>Options:</th>\
<td style=\"white-space:normal;\">!AZ</td></tr>\n\
<tr><th>Cipher List:</th>\
<td style=\"white-space:normal;\">!AZ</td>\
<tr><th>Server Certificate:</th><td>!AZ</td>\
<tr><th>Private Key:</th><td>!AZ</td>\
<tr><th>Verify Peer:</th><td>!AZ</td>\
<tr><th>Verify Peer Data Max:</th><td>!SL <i>kBytes</i> !AZ</td>\
<tr><th>Verify Peer Depth:</th><td>!UL</td>\
<tr><th>Verify Peer CA File:</th><td>!AZ</td>\
<tr><th>Strict Transport Security:</th><td>!AZ</td>\
<tr><th>Session Lifetime:</th><td>!AZ!AZ</td>\
<tr><th>Session Cache Max:</th><td>!SL!AZ</td>\
<tr><th>Instance Cache Max:</th><td>!SL!AZ</td>\
<tr><th>Instance Cache Size:</th><td>!SL!AZ</td>\
</table>\n\
</td></tr>\n\
</table>\n";

   int  status;
   unsigned long  *vecptr;
   unsigned long  FaoVector [32];
   CONFIG_STRUCT  *cfptr;

   /*********/
   /* begin */
   /*********/

   if (WATCHMOD (rqptr, WATCH_MOD_CONFIG))
      WatchThis (WATCHITM(rqptr), WATCH_MOD_CONFIG,
                 "ConfigReportSecureSocket()");

   /* get a pointer to the meta-config data */
   cfptr = mcptr->ConfigMetaPtr;

   vecptr = FaoVector;

   *vecptr++ = ProtocolHttpsAvailable ? "" : "<strike>";
   *vecptr++ = ProtocolHttpsAvailable ? "" : "</strike>";
   /* somewhat back-to-front from the usual enab/disab */
   REP_ENDIS (!cfptr->cfSesola.Disabled);
   REP_DEFAULT (cfptr->cfSesola.ProtocolVersion);
   REP_DEFAULT (cfptr->cfSesola.ProtocolOptions);
   REP_DEFAULT (cfptr->cfSesola.CipherList);
   REP_DEFAULT (cfptr->cfSesola.ServerCert);
   REP_DEFAULT (cfptr->cfSesola.PrivateKey);
   REP_ENDIS (cfptr->cfSesola.VerifyPeer);
   *vecptr++ = cfptr->cfSesola.VerifyPeerDataMax;
   *vecptr++ = cfptr->cfSesola.VerifyPeerDataMax ? "" : ConfigNoteDefault;
   *vecptr++ = cfptr->cfSesola.VerifyPeerDepth;
   REP_DEFAULT (cfptr->cfSesola.VerifyPeerCAFile);
   *vecptr++ = cfptr->cfSesola.StrictTransSec;
   *vecptr++ = MetaConShowSeconds (rqptr, cfptr->cfSesola.SessionLifetime);
   *vecptr++ = cfptr->cfSesola.SessionLifetime ? "" : ConfigNoteDefault;
   *vecptr++ = cfptr->cfSesola.SessionCacheMax;
   *vecptr++ = cfptr->cfSesola.SessionCacheMax ? "" : ConfigNoteDefault;
   *vecptr++ = cfptr->cfSesola.InstanceSessionCacheMax;
   *vecptr++ = cfptr->cfSesola.InstanceSessionCacheMax ? "" : ConfigNoteDefault;
   *vecptr++ = cfptr->cfSesola.InstanceSessionCacheSize;
   *vecptr++ = cfptr->cfSesola.InstanceSessionCacheSize ? "" : ConfigNoteDefault;

   status = FaolToNet (rqptr, ReportSslFao, &FaoVector);
   if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI);

#undef REP_ENDIS
#undef REP_DEFAULT
}

/*****************************************************************************/
/*
Server Admin SSL configuration menu.
*/

ConfigReviseSecureSocket
(
REQUEST_STRUCT *rqptr,
META_CONFIG *mcptr
)
{
#define REP_BOOL_RADIO(b)\
if (b)\
{\
   *vecptr++ = RadioButtonChecked;\
   *vecptr++ = RadioButtonUnchecked;\
}\
else\
{\
   *vecptr++ = RadioButtonUnchecked;\
   *vecptr++ = RadioButtonChecked;\
}

   static char ReviseSslFao [] =
"<p><table class=\"ctgry\">\n\
<tr><th class=\"ctttl\">!AZSecure Socket (SSL/TLS)!AZ</th></tr>\n\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;&#94;# -SECURE SOCKET-&#94;\">\n\
<tr><td>\n\
<table class=\"rghtlft\">\n\
\
<tr><th>Secure Socket:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[SecureSocket]&#32;&#32;\">\n\
<input type=\"radio\" name=\"SecureSocket\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"SecureSocket\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
\
<tr><th>Protocol Version(s):</th>\
<td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[SSLversion]&#32;&#32;\">\n\
<input type=\"text\" size=\"40\" name=\"SSLversion\" value=\"!AZ\">\n\
</td></tr>\n\
<tr><th>Options:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[SSLoptions]&#32;&#32;\">\n\
<input type=\"text\" size=\"!UL\" name=\">SSLoptions\" value=\"!AZ\">\n\
</td></tr>\n\
\
<tr><th>Cipher List:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[SSLcipherList]&#32;\">\n\
<input type=\"text\" size=\"!UL\" name=\"SSLcipherList\" value=\"!AZ\">\n\
</td></tr>\n\
<tr><th>Server Certificate:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[SSLcert]&#32;&#32;\">\n\
<input type=\"text\" size=\"40\" name=\"SSLcert\" value=\"!AZ\">\n\
</td></tr>\n\
\
<tr><th>Certificate Key:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[SSLkey]&#32;&#32;\">\n\
<input type=\"text\" size=\"40\" name=\"SSLkey\" value=\"!AZ\">\n\
</td></tr>\n\
\
<tr><th>Verify Peer:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[SSLverifyPeer]&#32;&#32;\">\n\
<input type=\"radio\" name=\"SSLverifyPeer\" value=\"enabled\"!AZ>enabled\n\
<input type=\"radio\" name=\"SSLverifyPeer\" value=\"disabled\"!AZ>disabled\n\
</td></tr>\n\
\
<tr><th>Verify Peer Data Max:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[SSLVerifyPeerDataMax]&#32;&#32;\">\n\
<input type=\"text\" size=\"5\" name=\"SSLVerifyPeerDataMax\" value=\"!SL\">\n\
<i>maximum kBytes request data during client certificate renegotiation</i></td></tr>\n\
\
<tr><th>Verify Peer Depth:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[SSLverifyPeerDepth]&#32;&#32;\">\n\
<input type=\"text\" size=\"5\" name=\"SSLverifyPeerDepth\" value=\"!UL\">\n\
</td></tr>\n\
\
<tr><th>Verify Peer CA File:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[SSLverifyPeerCAFile]&#32;&#32;\">\n\
<input type=\"text\" size=\"40\" name=\"SSLverifyPeerCAFile\" value=\"!AZ\">\n\
</td></tr>\n\
\
<tr><th>Strict Transport Security:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[SSLstrictTransSec]&#32;&#32;\">\n\
<input type=\"text\" size=\"60\" name=\"SSLstrictTransSec\" value=\"!AZ\">\n\
</td></tr>\n\
\
<tr><th>Session Lifetime:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[SSLsessionLifetime]&#32;&#32;\">\n\
<input type=\"text\" size=\"7\" name=\"SSLsessionLifetime\" value=\"!AZ\">\n\
<i>hh:mm:ss</i></td></tr>\n\
\
<tr><th>Session Cache Max:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[SSLsessionCacheMax]&#32;&#32;\">\n\
<input type=\"text\" size=\"5\" name=\"SSLsessionCacheMax\" value=\"!SL\">\n\
<i>number of records</i></td></tr>\n\
\
<tr><th>Instance Cache Max:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[SSLinstanceCacheMax]&#32;&#32;\">\n\
<input type=\"text\" size=\"5\" name=\"SSLinstanceCacheMax\" value=\"!SL\">\n\
<i>number of shared records</i></td></tr>\n\
\
<tr><th>Instance Cache Size:</th><td>\
<input type=\"hidden\" name=\"hidden$lf\" value=\"&#94;[SSLinstanceCacheSize]&#32;&#32;\">\n\
<input type=\"text\" size=\"5\" name=\"SSLinstanceCacheSize\" value=\"!SL\">\n\
<i>shared record size in bytes</i></td></tr>\n\
\
</table>\n\
</td></tr>\n\
</table>\n";

   static char  RadioButtonChecked [] = " CHECKED",
                RadioButtonUnchecked [] = "";

   int  status;
   unsigned long  *vecptr;
   unsigned long  FaoVector [32];
   CONFIG_STRUCT  *cfptr;

   /*********/
   /* begin */
   /*********/

   if (WATCHMOD (rqptr, WATCH_MOD_CONFIG))
      WatchThis (WATCHITM(rqptr), WATCH_MOD_CONFIG, "ConfigReviseSecureSocket()");

   /* get a pointer to the meta-config data */
   cfptr = mcptr->ConfigMetaPtr;

   vecptr = FaoVector;

   *vecptr++ = ProtocolHttpsAvailable ? "" : "<strike>";
   *vecptr++ = ProtocolHttpsAvailable ? "" : "</strike>";
   /* somewhat back-to-front from the usual enab/disab */
   REP_BOOL_RADIO (!cfptr->cfSesola.Disabled);
   *vecptr++ = cfptr->cfSesola.ProtocolVersion;
   *vecptr++ = strlen(cfptr->cfSesola.ProtocolOptions) > 30 ? 80 : 40;
   *vecptr++ = cfptr->cfSesola.ProtocolOptions;
   *vecptr++ = strlen(cfptr->cfSesola.CipherList) > 80 ?
      strlen(cfptr->cfSesola.CipherList)/2 : 40;
   *vecptr++ = cfptr->cfSesola.CipherList;
   *vecptr++ = cfptr->cfSesola.ServerCert;
   *vecptr++ = cfptr->cfSesola.PrivateKey;
   REP_BOOL_RADIO (cfptr->cfSesola.VerifyPeer);
   *vecptr++ = cfptr->cfSesola.VerifyPeerDataMax;
   *vecptr++ = cfptr->cfSesola.VerifyPeerDepth;
   *vecptr++ = cfptr->cfSesola.VerifyPeerCAFile;
   *vecptr++ = cfptr->cfSesola.StrictTransSec;
   *vecptr++ = MetaConShowSeconds (rqptr, cfptr->cfSesola.SessionLifetime);
   *vecptr++ = cfptr->cfSesola.SessionCacheMax;
   *vecptr++ = cfptr->cfSesola.InstanceSessionCacheMax;
   *vecptr++ = cfptr->cfSesola.InstanceSessionCacheSize;

   status = FaolToNet (rqptr, ReviseSslFao, &FaoVector);
   if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI);

#undef REP_BOOL_RADIO
}

/*****************************************************************************/
/*
Takes a comma-separated list of elements and returns a pointer to a dynamically
allocated string with that list reformated for inclusion in HTML.  The
separator is intended to be either a newline or comma character.  If a comma an
extra space is added after each (so that when displayed in HTML it will be
wrapped).  If a carriage-return ('\r'), it is converted into an HTML <br> (new
line) tag so that each appears on a new line in areas where '\n' doesn't behave
that way.
*/

char* ConfigStringList
(
REQUEST_STRUCT *rqptr,
char *ListPtr,
char Separator
)
{
   int  Length;
   char  *cptr, *sptr, *zptr;
   char  ListBuffer [8192],
         HtmlListBuffer [8192];

   /*********/
   /* begin */
   /*********/
   
   if (WATCHMOD (rqptr, WATCH_MOD_CONFIG))
      WatchThis (WATCHITM(rqptr), WATCH_MOD_CONFIG,
                 "ConfigStringList() !&Z !UL", ListPtr, Separator);

   if (!ListPtr) return ("");

   zptr = (sptr = ListBuffer) + sizeof(ListBuffer);
   for (cptr = ListPtr; *cptr && sptr < zptr; cptr++)
   {
      if (*cptr == STRING_LIST_CHAR)
         *sptr++ = Separator;
      else
         *sptr++ = *cptr;
      if (Separator == ',' && *cptr == STRING_LIST_CHAR && sptr < zptr)
         *sptr++ = ' ';
   }
   if (sptr >= zptr) return (ConfigStringOverflow);
   *sptr = '\0';

   /* now HTML-escape */
   zptr = (sptr = HtmlListBuffer) + sizeof(HtmlListBuffer);
   for (cptr = ListBuffer; *cptr && sptr < zptr; cptr++)
   {
      if (*cptr == '\r')
      {
         *sptr++ = '<';
         if (sptr < zptr) *sptr++ = 'B';
         if (sptr < zptr) *sptr++ = 'R';
         if (sptr < zptr) *sptr++ = '>';
      }
      else
      {
         switch (*cptr)
         {
            case '<' :
               if (sptr+4 >= zptr) return (ConfigStringOverflow);
               memcpy (sptr, "&lt;", 4); sptr += 4; break;
            case '>' :
               if (sptr+4 >= zptr) return (ConfigStringOverflow);
               memcpy (sptr, "&gt;", 4); sptr += 4; break;
            case '&' :
               if (sptr+5 >= zptr) return (ConfigStringOverflow);
               memcpy (sptr, "&amp;", 5); sptr += 5; break;
            case '\"' :
               if (sptr+6 >= zptr) return (ConfigStringOverflow);
               memcpy (sptr, "&quot;", 6); sptr += 6; break;
            default :
               *sptr++ = *cptr;
         }
      }

      if (Separator == ',' && *cptr == STRING_LIST_CHAR && sptr < zptr)
         *sptr++ = ' ';
   }
   if (sptr >= zptr) return (ConfigStringOverflow);
   *sptr = '\0';
   Length = sptr - HtmlListBuffer; 

   sptr = VmGetHeap (rqptr, Length+1);
   memcpy (sptr, HtmlListBuffer, Length+1);

   return (sptr);
}

/*****************************************************************************/
