/*****************************************************************************/ /* 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 patterns or file specification o ActivityDays o 7AddType <.type> [rfm:] [ftp:] [] [] o AddMimeTypesFile o AddIcon o AddDefaultIcon o AddDirIcon o AddBlankIcon o AddUnknownIcon o AddParentIcon o AuthBasic DISABLED | ENABLED o AuthCacheEntriesMax o AuthCacheEntrySize o AuthCacheMinutes o AuthDigest DISABLED | ENABLED o AuthDigestGetLife o AuthDigestPutLife o AuthFailureLimit o AuthFailurePeriod o AuthFailureTimeout o AuthRevalidateUserMinutes o AuthSYSUAFlogonType o AuthSYSUAFacceptExpPwd DISABLED | ENABLED o AuthSYSUAFpwdExpUrl o AuthTokenEntriesMax o BufferSizeDclCgiHeader o BufferSizeDclCgiPlusIn o BufferSizeDclCommand o BufferSizeDclOutput o BufferQuotaDclOutput o BufferSizeNetFile o BufferSizeNetMTU o BufferSizeNetRead o BufferSizeNetWrite o Cache DISABLED | ENABLED o CacheEntriesMax o CacheFileKBytesMax o CacheFrequentHits o CacheFrequentPeriod o CacheGuardPeriod o CacheTotalKBytesMax o CacheValidatePeriod o CgiStrictOutput DISABLED | ENABLED o CharsetDefault o CharsetConvert o ConnectMax o DclBitBucketTimeout o DclCgiPlusLifeTime o DclCleanupScratchMinutesMax o DclCleanupScratchMinutesOld o DclDetachProcess DISABLED | ENABLED o DclDetachProcessPriority o DclGatewayBg DISABLED | ENABLED o DclHardLimit o DclScriptProctor o DclScriptRunTime o DclSoftLimit o DclSpawnAuthPriv DISABLED | ENABLED o DclZombieLifeTime o DECnetReuseLifeTime o DECnetConnectListMax o DirAccess DISABLED | ENABLED | SELECTIVE o DirBodyTag o DirDescription o DirLayout o DirMetaInfo DISABLED | ENABLED o DirOwner DISABLED | ENABLED o DirPreExpired DISABLED | ENABLED o DirReadMe DISABLED | TOP | BOTTOM o DirReadMeFile o DirNoImpliedWildcard DISABLED | ENABLED o DirNoPrivIgnore DISABLED | ENABLED o DirWildcard DISABLED | ENABLED o DNSLookupClient DISABLED | ENABLED o DNSLookupLifeTime o DNSLookupRetry o EntityTag DISABLED | ENABLED o ErrorRecommend DISABLED | ENABLED o ErrorReportPath o GzipAccept o GzipFlushSeconds [,] o GzipResponse [,,] o Http2Protocol DISABLED | ENABLED o Http2FrameSizeMax o Http2HeaderListMax o Http2HeaderTableMax o Http2InitWindowSize o Http2PingSeconds o Http2StreamsMax o HttpTrace DISABLED | ENABLED o IncludeFile o InstanceMax | CPU o InstancePassive DISABLED | ENABLED o Logging DISABLED | ENABLED o LogExcludeHosts o LogFile o LogFileExtend o LogFormat o LogNaming o LogPeriod o LogPerInstance DISABLED | ENABLED o LogPerService DISABLED | ENABLED o LogPerServiceHostOnly DISABLED | ENABLED o LogWriteFail503 DISABLED | ENABLED o MapUserNameCacheEntries o NoticeInvalid o Monitor DISABLED | ENABLED o OpcomAdmin DISABLED | ENABLED o OpcomAuthorization DISABLED | ENABLED o OpcomControl DISABLED | ENABLED o OpcomProxyMaint obsolete from v12.0.0 o OpcomTarget o PersonaCacheEntries o PipelineRequests DISABLED | ENABLED o Port o ProcessMax o ProxyCache obsolete as of v12.0.0 o ProxyCacheDeviceCheckMinutes obsolete as of v12.0.0 o ProxyCacheDeviceDirOrg obsolete as of v12.0.0 o ProxyCacheDeviceMaxPercent obsolete as of v12.0.0 o ProxyCacheDevicePurgePercent obsolete as of v12.0.0 o ProxyCacheFileKBytesMax obsolete as of v12.0.0 o ProxyCacheNegativeSeconds obsolete as of v12.0.0 o ProxyCacheNoReloadSeconds obsolete as of v12.0.0 o ProxyCachePurgeList obsolete as of v12.0.0 o ProxyCacheReloadList obsolete as of v12.0.0 o ProxyCacheRoutineHourOfDay obsolete as of v12.0.0 o ProxyConnectPersistMax obsolete as of v12.3.0 o ProxyConnectPersistSeconds obsolete as of v12.3.0 o ProxyConnectTimeoutSeconds o ProxyForwarded DISABLED | BY | FOR | ADDRESS o ProxyHostLookupRetryCount o ProxyReportCacheLog obsolete as of v12.3.0 o ProxyReportLog obsolete as of v12.3.0 o ProxyServing DISABLED | ENABLED o ProxyUnknownRequestFields obsolete as of v12.3.0 o ProxyVerifyRecordMax o ProxyXForwardedFor obsolete as of v12.3.0 o PutBinaryRFM FIX512|STM|STMCR|STMLF|UDF (default is UDF) o PutMaxKbytes o PutVersionLimit o RegEx DISABLED | ENABLED or AWK, ED, EGREP, GREP, POSIX_AWK, POSIX_BASIC, POSIX_EGREP, POSIX_EXTENDED, POSIX_MINIMAL_BASIC, POSIX_MINIMAL_EXTENDED, SED, WASD o Reject patterns or file specification o ReportBasicOnly DISABLED | ENABLED o ReportMetaInfo DISABLED | ENABLED o RequestHistory o Scripting DISABLED | ENABLED o SearchScript o SearchScriptExclude o SecureSocket DISABLED | ENABLED o ServerAdmin o ServerAdminBodyTag o ServerReportBodyTag o ServerSignature DISABLED | ENABLED o NOTE: "Service" reserved for inline configuration - use [ServiceGlobal] o ServiceListenBacklog o ServiceNotFoundURL o SocketSizeRcvBuf o SocketSizeSndBuf o SSI | Shtml DISABLED | ENABLED o SSIAccesses | ShtmlAccesses DISABLED | ENABLED o SSIExec | ShtmlExec DISABLED | ENABLED o SSISizeMax o SSLcert o SSLcipherList o SSLcipherSuites o SSLinstanceCacheMax o SSLinstanceCacheSize o SSLkey o SSLoptions o SSLsessionCacheMax o SSLsessionLifetime o SSLstrictTransSec [] o SSLverifyPeer DISABLED | ENABLED o SSLverifyPeerCAFile o SSLverifyPeerDataMax o SSLverifyPeerDepth o SSLversion o StreamLf o TimeoutHttp2Idle o TimeoutInput o TimeoutNoProgress o TimeoutOutput o TimeoutPersistent o WebDAV DISABLED | ENABLED o WebDAVlocking DISABLED | ENABLED o WebDAVlockCollectionDepth o WebDAVlockTimeoutDefault o WebDAVlockTimeoutMax o WebDAVquota DISABLED | ENABLED o WebDAVmetaDir o Welcome o WwwImplied DISABLED | ENABLED VERSION HISTORY --------------- 07-AUG-2023 MGD simplify ConfigAddIcon(), ConfigAddTypeNow(), ConfigIconFor() and ConfigContentType() to use simple lists avoiding the complexity and dubious efficiency of the hash table 08-JUN-2023 MGD [SSLcipherSuites] for OpenSSL 3.0 and TLSv1.3 30-MAR-2023 MGD #WASD_CONFIG_GLOBAL [Accept] and [Reject] now accept file specifications allowing files of patterns to be loaded /DO=ACCEPT and /DO=REJECT allow reloading of above ConfigAcceptConnection() broaden wildcard match allow CIDR n.n.n.n/n patterns allow range n.n.n.n-n.n.n.n patterns and add '?' to reject host name resolution fail furthermore, '+' notes the rejection to the server log and, '++' notes the rejection to OPCOM 09-OCT-2022 MGD [NoticeInvalid] 0=none, 1=header, 2..n=dump 03-SEP-2022 MGD [Service] now reseved for inline configuration 14-MAR-2021 MGD proxy caching obsolete 27-DEC-2020 MGD ConfigControlProctorLoad() 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] 22-FEB-2015 MGD [SSLstrictTransSec] 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/ 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; ConfigAcceptConnection() 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 entity impossible use a field name of hidden$lf and ^ 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 #include #include #include #include /* VMS related header files */ #include #include #include #include /* 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, ConfigNoticeInvalid; #define CONFIG_NOTE_NONE "(none)" 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 [] = " (default)", ConfigNoteNone [] = " (none)", ConfigNoteSystem [] = " (system)", ConfigDefaultFileContentType [] = "application/octet-stream", ConfigStringOverflow [] = "*ERROR* string overflow"; char *ConfigBlankIconPtr, *ConfigDirIconPtr, *ConfigDefaultIconPtr, *ConfigParentIconPtr, *ConfigUnknownIconPtr; /* characters 'A' to 'Z' */ static CONTENT_TYPE *ConfigTypeArray [26]; /********************/ /* external storage */ /********************/ extern BOOL DclProctorEnabled, HttpdServerStartup, LoggingEnabled, NetInstancePassive, ProtocolHttpsAvailable; extern int AuthFailureLimit, AuthFailurePeriodSeconds, AuthFailureTimeoutSeconds, DclCgiHeaderSize, DclCgiPlusInSize, DclSysCommandSize, DclSysOutputSize, DclSysOutputQuota, HttpdTickSecond, NetConcurrentMax, NetConcurrentProcessMax, MapUrlUserNameCacheEntries, NetReadBufferSize, OpcomMessages, OpcomTarget, OutputBufferSize, OutputFileBufferSize, PersonaCacheEntries, RequestNoticedInvalid, ServiceLoadFromConfigFile, SsiSizeMax, TcpIpSocketRcvBufSize, TcpIpSocketSndBufSize; extern int64 HttpdTime64; extern unsigned long SysPrvMask[]; extern char *CliAcceptHostsPtr, *CliRejectHostsPtr; extern char SesolaAvailableVersions[], SoftwareID[], TimeGmtString[]; extern ACCOUNTING_STRUCT *AccountingPtr; 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, CONFIG_GLOBAL_FILE_NAME, &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.NoticeInvalid = 999; 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; strzcpy (cfptr->cfDir.DefaultLayout, DEFAULT_DIR_LAYOUT, sizeof(cfptr->cfDir.DefaultLayout)); 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 = ""; 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; ConfigNoticeInvalid = cfptr->cfMisc.NoticeInvalid; 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 = to_upper(*cptr); ConfigContentTypeIcon (mcptr); if (!cfptr->cfDir.BodyTag[0]) strzcpy (cfptr->cfDir.BodyTag, CONFIG_DEFAULT_DIR_BODY_TAG, sizeof(cfptr->cfDir.BodyTag)); 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 (Config.ServerStartup = 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; NetRejectInit (NULL); } return (true); } if (mclptr->Token == METACON_TOKEN_INCLUDE) return (true); if (mclptr->Token == METACON_TOKEN_VERSION) return (true); if (mclptr->Token == METACON_TOKEN_COMMENT) if (SAME4 (mclptr->TextPtr, '!#+#') || SAME4 (mclptr->TextPtr, '!#-#') || SAME4 (mclptr->TextPtr, '!#=#')) 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)) { /* [,] */ 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)) { /* [,,] */ 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.PingSeconds = 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, "NoticeInvalid", -1)) cfptr->cfMisc.NoticeInvalid = MetaConSetInteger (mcptr, sptr); else if (strsame (cptr, "OpcomTarget", -1) || strsame (cptr, "OpcomAdmin", -1) || strsame (cptr, "OpcomAuthorization", -1) || strsame (cptr, "OpcomControl", -1) || strsame (cptr, "OpcomHTTPd", -1)) ConfigSetOpcom (mcptr, cptr, sptr); else if (strsame (cptr, "OpcomProxyMaint", -1)) MetaConReport (mcptr, METACON_REPORT_INFORM, ProblemObsolete); 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)) MetaConReport (mcptr, METACON_REPORT_INFORM, ProblemObsolete); else if (strsame (cptr, "ProxyCacheDeviceCheckMinutes", -1)) MetaConReport (mcptr, METACON_REPORT_INFORM, ProblemObsolete); else if (strsame (cptr, "ProxyCacheDeviceDirOrg", -1)) MetaConReport (mcptr, METACON_REPORT_INFORM, ProblemObsolete); else if (strsame (cptr, "ProxyCacheDeviceMaxPercent", -1)) MetaConReport (mcptr, METACON_REPORT_INFORM, ProblemObsolete); else if (strsame (cptr, "ProxyCacheDevicePurgePercent", -1)) MetaConReport (mcptr, METACON_REPORT_INFORM, ProblemObsolete); else if (strsame (cptr, "ProxyCacheFileKBytesMax", -1)) MetaConReport (mcptr, METACON_REPORT_INFORM, ProblemObsolete); else if (strsame (cptr, "ProxyCacheNegativeSeconds", -1)) MetaConReport (mcptr, METACON_REPORT_INFORM, ProblemObsolete); else if (strsame (cptr, "ProxyCacheNoReloadSeconds", -1)) MetaConReport (mcptr, METACON_REPORT_INFORM, ProblemObsolete); else if (strsame (cptr, "ProxyCacheRoutineHourOfDay", -1)) MetaConReport (mcptr, METACON_REPORT_INFORM, ProblemObsolete); else if (strsame (cptr, "ProxyCachePurgeList", -1)) MetaConReport (mcptr, METACON_REPORT_INFORM, ProblemObsolete); else if (strsame (cptr, "ProxyCacheReloadList", -1)) MetaConReport (mcptr, METACON_REPORT_INFORM, ProblemObsolete); else if (strsame (cptr, "ProxyConnectPersistMax", -1)) MetaConReport (mcptr, METACON_REPORT_INFORM, ProblemObsolete); else if (strsame (cptr, "ProxyConnectPersistSeconds", -1)) MetaConReport (mcptr, METACON_REPORT_INFORM, ProblemObsolete); 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)) MetaConReport (mcptr, METACON_REPORT_INFORM, ProblemObsolete); else if (strsame (cptr, "ProxyReportLog", -1)) MetaConReport (mcptr, METACON_REPORT_INFORM, ProblemObsolete); else if (strsame (cptr, "ProxyServing", -1)) cfptr->cfProxy.ServingEnabled = MetaConSetBoolean (mcptr, sptr); else if (strsame (cptr, "ProxyUnknownRequestFields", -1)) MetaConReport (mcptr, METACON_REPORT_INFORM, ProblemObsolete); 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, "ServiceGlobal", -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, "SSLcipherSuites", -1)) MetaConSetString (mcptr, sptr, cfptr->cfSesola.CipherSuites, sizeof(cfptr->cfSesola.CipherSuites)); 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> [] []" 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, size; uchar ch; 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++ = to_upper(*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 (HttpdServerStartup) { /* shorten the search list by noting first occurance of this character */ ch = ctptr->SuffixPtr[1]; if (ch >= 'A' && ch <= 'Z') if (!ConfigTypeArray[(ch - 'A')]) ConfigTypeArray[(ch - 'A')] = ctptr; } /* special case, default content-type for unknown suffixes */ if (SAME2(ctptr->SuffixPtr,'*\0')) { cfptr->cfContent.ContentTypeDefaultPtr = VmGet (size = strlen(HtmlDescription+1)+1); strzcpy (cfptr->cfContent.ContentTypeDefaultPtr, HtmlDescription, size); 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 ) { uchar ch; char *cptr, *sptr; CONTENT_TYPE *ctptr; /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD_CONFIG)) WatchThis (WATCHALL, WATCH_MOD_CONFIG, "ConfigContentType() !&Z", SuffixPtr); ctptr = Config.cfContent.ContentInfoListHeadPtr; /* shorten the search list by using first occurance of this character */ ch = to_upper(SuffixPtr[1]); if (ch >= 'A' && ch <= 'Z') if (ConfigTypeArray[(ch - 'A')]) ctptr = ConfigTypeArray[(ch - 'A')]; for (; ctptr; ctptr = ctptr->NextPtr) { /* if a later type definition was loaded then ignore this one */ if (ctptr->Superceded) continue; /* 'ctptr->SuffixPtr' has already been converted to upper case! */ cptr = ctptr->SuffixPtr; sptr = SuffixPtr; while (*cptr && *sptr && *sptr != ';' && *cptr == to_upper(*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 != ';' && to_upper(*sptr) != *cptr) sptr++; continue; } /* wildcard at end of list file type, matches all following */ while (*sptr && *sptr != ';') sptr++; } if (*cptr || (*sptr && *sptr != ';')) 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 (to_upper(*sptr1++) != to_upper(*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 " 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; 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 */ 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 */ 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 to_lower() in ConfigIconFor() */ for ( /* above */ ; *pptr && !ISLWS(*pptr); pptr++) *pptr = to_lower(*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, "\"%s\"", IconUrlPtr, AltTextPtr); for (hitptr = cfptr->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; } /*****************************************************************************/ /* 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 [] = "[?]"; char ch; char *cptr, *sptr, *AltTextPtr, *IconUriPtr; ICON_TYPE *itptr; /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD_CONFIG)) WatchThis (WATCHALL, WATCH_MOD_CONFIG, "ConfigIconFor() !&Z !&X !&X", ContentType, IconUriPtrPtr, AltTextPtrPtr); for (cptr = ContentType; *cptr && *cptr != ';' && !ISLWS(*cptr); cptr++); ch = *cptr; *cptr = '\0'; for (itptr = Config.cfContent.IconListHeadPtr; itptr; itptr = itptr->NextPtr) { if (itptr->Superceded) continue; 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); } /*****************************************************************************/ /* 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 count, size, status; 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 = to_upper(*pptr); pptr++; } count = pptr - NamePtr; *pptr = '\0'; if (!*NamePtr) { MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemParameter); return; } cfptr->cfDir.ReadMeFileArray[cfptr->cfDir.ReadMeFileCount] = size = VmGet(count+1); strzcpy (cfptr->cfDir.ReadMeFileArray[cfptr->cfDir.ReadMeFileCount], NamePtr, size); 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 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 [+] 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 = psptr->VmPtr = 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++; } /*****************************************************************************/ /* Implements the reconfiguration setp of /DO=DCL=PROCTOR=LOAD. */ ConfigControlProctorLoad (REQUEST_STRUCT *rqptr) { int count, status; char *cptr, *sptr, *zptr; char StringBuffer [4096]; struct ConfigProctorStruct *psptr; CONFIG_STRUCT *cfptr, *gcfptr; META_CONFIG *gmcptr, *mcptr; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD_CONFIG)) WatchThis (WATCHITM(rqptr), WATCH_MOD_CONFIG, "ConfigProctorLoad()"); status = ConfigLoad (&mcptr); if (VMSnok (status)) { /* severe error reported */ rqptr->rqResponse.HttpStatus = 403; ErrorGeneral (rqptr, mcptr->LoadReport.TextPtr, FI_LI); } else { /* pointer to the global meta-config */ gmcptr = MetaGlobalConfigPtr; gcfptr = gmcptr->ConfigMetaPtr; /* pointer to the loaded meta-config */ cfptr = mcptr->ConfigMetaPtr; /* replace the global proctor config with the newly loaded */ gcfptr->cfScript.ProctorCount = cfptr->cfScript.ProctorCount; for (count = 0; count < CONFIG_SCRIPT_PROCTOR_MAX; count++) { if (gcfptr->cfScript.Proctor[count].VmPtr) VmFree (gcfptr->cfScript.Proctor[count].VmPtr, FI_LI); memcpy (&gcfptr->cfScript.Proctor[count], &cfptr->cfScript.Proctor[count], sizeof(gcfptr->cfScript.Proctor[0])); } } MetaConUnload (&mcptr, NULL); } /*****************************************************************************/ /* 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++ = to_upper(*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 count, size, status; 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 = to_upper(*pptr); pptr++; } count = pptr - WelcomePtr; *pptr = '\0'; cfptr->cfContent.HomePageArray[cfptr->cfContent.HomePageCount] = size = VmGet (count+1); strzcpy (cfptr->cfContent.HomePageArray[cfptr->cfContent.HomePageCount], WelcomePtr, size); 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 count, status; CONFIG_STRUCT *cfptr; 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); cfptr = mcptr->ConfigMetaPtr; for (count = 0; count < CONFIG_SCRIPT_PROCTOR_MAX; count++) if (cfptr->cfScript.Proctor[count].VmPtr) VmFree (cfptr->cfScript.Proctor[count].VmPtr, FI_LI); 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 [] = "(no restriction)\n", ServerOnly [] = "(this server only)\n"; static char ReportGeneralFao [] = "

\n\ \n\ \n\
GMT
\n\ \n\ \n\ \n\
Offset:!AZ
Current:!AZ
\n\
\n\ \

\n\ \n\ \n\
General
\n\ \n\ \ \ \n\ \ \ \ \ \ \ \ \n\ \ \n\ \n\ \ \ \n\ \n\ \n\ \n\ \n\ \n\ \ \ \n\ \ \n\ \n\ \ \n\ \n\ \n\ \n\ \ \n\ \n\ \ \n\ \ \n\ \ \n\ \ \n\
Instance Max:!&@per-node servers
Instance Passive:!AZ
Connect Max:!ULconnections
Process Max:!ULrequests being processed
Listen Backlog:!ULat socket
Request History:!ULrequests
Activity History:!ULdays
Charset Default:!AZ
Charset Convert:!AZ
Monitor:!AZ
Regular Expressions:!&@
Entity Tag:!AZ
Pipeline Requests:!AZ
HTTP TRACE:!AZ
WWW Implied:!AZ
GZIP Accept:!UL
GZIP Flush:!&@interval[,initial] seconds
GZIP Response:!&@level[,memory,window]
IP Port:!UL
StreamLF:!ULkBytes
Search Script:!AZ
Search Script Exclude:!AZfile type
PUT/POST Max:!ULkBytes
PUT/POST binary RFM:!AZ
PUT/POST Files:!ULversion limit
/~username/ Cache Entries:!ULuser names
Persona Cache Entries:!ULusers
Notice Invalid:!UL0=none,1=header,2..n=dump
\n\
\n\ \

\n\ \n\ \n\
Host Resolution
\n\ \n\ \n\ \n\ \n\
Lookup Client:!AZ
Life-Time:!AZ
Retry:!UL
\n\
\n\ \

\n\ \n\ \n\
Log
\n\ \n\ \n\ \ \ \ \ \ \ \ \ \ \n\
Logging:!AZ
Format:!AZ
Naming:!AZ
Period:!AZ
Per-Instance:!AZ
Per-Service:!AZ
Per-Service Host Only:!AZ
Write Fail 503:!AZ
File:!AZ
Extend Blocks:!UL
Exclude Hosts:!AZ
\n\
\n\ \

\n\ \n\ \n\
OPCOM
\n\ \n\ \n\ \ \ \ \
Target:!AZ
Admin:!AZ
Authorization:!AZ
Control:!AZ
HTTPd:!AZ
\n\
\n\ \

\n\ \n\ \n\
File Cache
\n\ \n\ \n\ \ \n\ \ \n\ \ \n\ \ \n\ \n\ \ \n\
Caching:!AZ
Max Entries:!ULfiles
Max Cache Size:!ULkBytes
Max Entry Size:!ULkBytes
Guard:!AZhh:mm:ss
Validate:!AZ
Frequent /Hits:!UL
/Within:!AZ
\n\
\n\ \

\n\ \n\ \n\
Timeouts
\n\ \n\ \ \n\ \n\ \n\ \n\ \n\
Input:!AZhh:mm:ss
Output:!AZ
No-Progress:!AZ
Persistent Connection:!AZ
HTTP/2 Idle:!AZ
\n\
\n\ \

\n\ \n\ \n\
Buffer Sizes !AZ
\n\ \n\ \ \n\ \ \n\ \ \n\ \ \n\ \ \n\ \n\ \ \n\ \ \n\ \n\ \ \n\ \ \n\
DCL SYS$COMMAND:!UL
DCL SYS$OUTPUT:!UL(!UL)
DCL (SYS$OUTPUT) BUFQUO:!UL(!UL)
DCL CGIPLUSIN:!UL
CGI Header:!UL
Network Read:!UL
Network Write:!UL(!UL)
Network File:!UL(!UL)
Network MTU:!UL
Socket SNDBUF:!UL!AZ
Socket RCVBUF:!UL!AZ
\n\
\n"; static char ReportWelcomeFao [] = "

\n\ \n\ \n\
Welcome (Home) Pages
\n\ \n"; static char ReportHostsFao [] = "
\n\
\n\ \

\n\ \n\ \n\
Access Control
\n\ \n\ \n\ \n\
Accept:!AZ
Reject:!AZ
\n\
\n"; static char ReportsFao [] = "

\n\ \n\ \n\
Server Generated Reports
\n\ \n\ \ \n\ \n\ \n\ \n\ \n\ \n\
Server Admin Email:!&@
Server Signature:!&;AZ
Basic Info Only:!AZ
<META> Info:!AZ
Error Report Path:!AZ
Error Recommend:!AZ
\n\
\n\ \

\n\ \n\ \n\
Authorization
\n\ \n\ \n\ \ \n\ \ \n\ \ \n\ \ \n\ \ \n\ \n\ \n\ \n\ \n\ \ \n\ \ \n\ \ \n\ \ \n\ \ \n\
Cache Entries:!UL
Cache Entry Size:!ULbytes
Cache Valid:!ULminutes
Revalidate User:!ULminutes
Failure Limit:!ULattempts
Failure Period:!AZhh:mm:ss
Failure Timeout:!AZ
Token Entries:!SL
Basic!AZ
Digest:!AZ
Digest GET lifetime:!ULminutes
Digest PUT lifetime:!ULminutes
SYSUAF Logon Type:!AZ
SYSUAF Accept Expired Pwd:!AZ
SYSUAF Pwd Expired URL:!AZ
\n\
\n\ \

\n\ \n\ \n\
Proxy Serving
\n\ \n\ \ \n\ \ \n\ \ \n\ \ \n\ \ \n\ \ \n\
Proxy Serving:!AZ
Add "Forwarded: by":!AZ
Add "X-Forwarded-For:":!AZ
Verify Max:!ULrecords
Host Name Lookup Retry:!ULattempts
Connect Timeout:!AZhh:mm:ss
\n\
\n\ \

\n\ \n\ \n\
Scripting (CGI, DCL & DECnet)
\n\ \n\ \n\ \n\ \ \n\ \n\ \n\ \n\ \ \n\ \ \n\ \ \n\ \n\ \n\ \n\ \ \n\ \ \n\ \ \n\ \ \ \n"; static char ReportProctorFao [] = "\ \ \n"; static char ReportSsiFao [] = "
Scripting:!AZ
Detach Process:!AZ
Process Priority:!AZserver,user
Strict CGI Output:!AZ
Spawn Authorized Privileges:!AZ
Gateway BG:!AZ
Soft Limit:!ULscript processes
Hard Limit:!ULscript processes
Bit-Bucket Timeout:!AZhh:mm:ss
Zombie Life-Time:!AZ
CGIplus Life-Time:!AZ
DECnet Reuse Life-Time:!AZ
DECnet Connect List Max:!ULconnections
Cleanup Scratch Max:!ULminutes
Cleanup Older-than:!ULminutes
Script Run-Time:suffixverb
Script Proctor:min+idlepatternactivationnotepad
\n\
\n\ \

\n\ \n\ \n\
Server-Side Includes
\n\ \n\ \n\ \n\ \n\ \ \n\
SSI:!AZ
Exec:!AZ
Accesses:!AZ
Max Size:!ULkBytes
\n\
\n\ \

\n\ \n\ \n\
WebDAV
\n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\
WebDAV:!AZ
Locking:!AZ
Lock Timeout Default:!AZ
Lock Timeout Max:!AZ
Lock Collection Depth:!UL
Quota:!AZ
Meta File Directory:!AZ
\n\
\n\ \

\n\ \n\ \n\
Directory
\n\ \n\ \n\ \n\ \ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n"; static char ReportIconsFao [] = "
Access:!AZ
Layout:!AZ
Listing <BODY>:!&;AZ
HTML Description:!UL lines
<META> Info:!AZ
Owner:!AZ
Pre-Expired:!AZ
Wildcard:!AZ
No Implied Wildcard:!AZ
Prot Violations Ignored:!AZ
Readme:!AZ !AZ
Readme Files:
\n\
\n\ \

\n\ \n\ \n\
Directory Icons
\n\ \n\ \ \ \ \ \ \n"; static char ReportContentTypeFao [] = "
Content-TypeIconPathAlt.Text
\n\
\n\ \

\n\ \n\ \n\
Content-Type
\n\ \n\ \ \ \ \ \ \ \n"; static char EndPageFao [] = "\n\
SuffixContent-TypeIconAuto-scriptDescription
MIME.TYPES File: !AZ
\n\
\n\ \ \n\ \n\ \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++ = "(UDF)"; *vecptr++ = cfptr->cfMisc.PutVersionLimit; if (cfptr == &Config) *vecptr++ = MapUrlUserNameCacheEntries; else *vecptr++ = cfptr->cfMisc.MapUserNameCacheEntries; if (cfptr == &Config) *vecptr++ = PersonaCacheEntries; else *vecptr++ = cfptr->cfMisc.PersonaCacheEntries; if (cfptr == &Config) *vecptr++ = ConfigNoticeInvalid; else *vecptr++ = cfptr->cfMisc.NoticeInvalid; /* 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) /* 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, "!&;AZ\n", cfptr->cfContent.HomePageArray[idx]); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); } /*********************/ /* host access, etc. */ /*********************/ if (mcptr == MetaGlobalConfigPtr) { /* NetRejectReport() allocated memory will need to be freed */ cptr = NetRejectReport ("ACCEPT"); sptr = NetRejectReport ("REJECT"); vecptr = FaoVector; *vecptr++ = cptr; *vecptr++ = sptr; status = FaolToNet (rqptr, ReportHostsFao, &FaoVector); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); /* NetRejectReport() allocated memory needs to be freed */ VmFree (cptr, FI_LI); VmFree (sptr, FI_LI); } else { vecptr = FaoVector; *vecptr++ = cfptr->cfServer.AcceptHostsPtr; *vecptr++ = cfptr->cfServer.RejectHostsPtr; *vecptr++ = ConfigNoteDefault; status = FaolToNet (rqptr, ReportHostsFao, &FaoVector); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); } /*****************/ /* reports, etc. */ /*****************/ vecptr = FaoVector; /* 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) 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; *vecptr++ = cfptr->cfProxy.VerifyRecordMax; *vecptr++ = cfptr->cfProxy.HostLookupRetryCount; *vecptr++ = MetaConShowSeconds (rqptr, cfptr->cfProxy.ConnectTimeoutSeconds); /* 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, ReportsFao, &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, "!#&;AZ!&;AZ\n", &FaoVector); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); } } else { static char NotNone [] = "" CONFIG_NOTE_NONE "\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, "!UL+!UL!AZ!AZ!AZ!AZ\ !AZ!AZ\n", &FaoVector); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); } } else { static char NotNone [] = "" CONFIG_NOTE_NONE "\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, "!&@!AZ\n", idx ? "" : "", 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 = "!AZ\ !AZ\ !AZ\ [!&;AZ]\n"; else cptr = "!AZ\ !AZ\ !AZ\ !AZ\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 = "!AZ\ !AZ!&@!&@\ !AZ\ !AZ\ !AZ\n"; else cptr = "!AZ\ !AZ!&@!&@\ !AZ\ !AZ\ !AZ\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 [] = "

\n\ \n\ \n\ \n\
Service
\n\ !&@\
Service Not Found URL: \ \n\ \n\
\n\ \

\n\ \n\ \n\ \n\
General
\n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\
Instance Max:\ \n\ \n\ per-node servers
Instance Passive:\ \n\ enabled\n\ disabled\n\
Connect Max:\ \n\ \n\ connections
Process Max:\ \n\ \n\ requests being processed
Listen Backlog:\ \n\ \n\ at socket
Request History:\ \n\ \n\
Activity History:\ \n\ \n\ days
Charset Default:\n\ \n\ \n\
Charset Convert:
\n\ \n\ \n\
Monitor:\ \n\ enabled\n\ disabled\n\
Regular Expressions:\ \n\ \n\
Entity Tag:\ \n\ enabled\n\ disabled\n\
Pipeline Requests:\ \n\ enabled\n\ disabled\n\
HTTP TRACE:\ \n\ enabled\n\ disabled\n\
WWW Implied:\ \n\ enabled\n\ disabled\n\
GZIP Accept:\ \n\ \n\ window
GZIP Flush:\ \n\ \n\ interval[,initial] seconds
GZIP Response:\ \n\ \n\ level[,memory,window]
IP Port:\ \n\ \n\ (overridden by "service" directive)
StreamLF:\ \n\ \n\ kBytes
Search Script:\n\ \n\ \n\
Search Script Exclude:
\n\ \n\ \n\
PUT/POST Max:\ \n\ \n\ kBytes
PUT/POST binary RFM:\ \n\ \n\
Put/Post Files:\ \n\ \n\ version limit
/~username/ Cache Entries:\n\ \n\ \n\ user names\
Persona Cache Entries:\n\ \n\ \n\ users\
Notice Invalid:\n\ \n\ \n\ 0=none,1=header,2..n=dump\
\n\
\n\ \

\n\ \n\ \n\ \n\
Host Resolution
\n\ \n\ \n\ \n\ \n\ \
Client Lookup:\ \n\ yes\n\ no\n\
Life-Time:\ \n\ \n\ hh:mm:ss
Retry Count:\ \n\
\n\
\n\

\n\ \n\ \n\ \n\
Log
\n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\
Logging:\ \n\ enabled\n\ disabled\n\
Format:\ \n\
Naming:\ \n\
Period:\ \n\
Per-Instance:\ \n\ enabled\n\ disabled\n\
Per-Service:\ \n\ enabled\n\ disabled\n\
Per-Service Host Only:\ \n\ enabled\n\ disabled\n\
Write Fail 503:\ \n\ enabled\n\ disabled\n\
File:\ \n\
Extend Blocks:\n\ \n\ \n\
Exclude Hosts:
\n\ \n\ \n\
\n\
\n\ \

\n\ \n\ \n\ \n\
OPCOM
\n\ \n\ \n\ \n\ \n\ \n\
Target:\ \n\ \n\
Admin:\ \n\ enabled\n\ disabled\n\
Authorization:\ \n\ enabled\n\ disabled\n\
Control:\ \n\ enabled\n\ disabled\n\
HTTPd:\ \n\ enabled\n\ disabled\n\
\n\
\n\ \

\n\ \n\ \n\ \n\
Cache
\n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\
Caching:\ \n\ enabled\n\ disabled\n\
Max Entries:\ \n\ \n\ files
Max Cache Size:\ \n\ \n\ kBytes
Max Entry Size:\ \n\ \n\ kBytes
Guard:\ \n\ \n\ hh:mm:ss
Validate:\ \n\ \n
Frequent After:\ \n\ \ hits, last within\n\ \n\ \n
\n\
\n\ \

\n\ \n\ \n\ \n\
Timeouts
\n\ \n\ \n\ \n\ \n\ \n\ \n\
Input:\ \n\ \n\ hh:mm:ss
Output:\n\ \n\ \n
No-Progress:\n\ \n\ \n
Persistent Connection:\n\ \n\ \n
HTTP/2 Idle:\n\ \n\ \n
\n\
\n\ \

\n\ \n\ \n\ \n\
Buffer Sizes
\n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \ \n\
DCL SYS$COMMAND:\ \n\ \n\
DCL SYS$OUTPUT:\ \n\ \n\
DCL (SYS$OUTPUT) BUFQUO:\ \n\ \n\
DCL CGIPLUSIN:\ \n\ \n\
CGI Header:\ \n\ \n\
Network Read:\ \n\ \n\
Network Write:\ \n\ \n\
Network File:\ \n\ \n\
Network MTU:\ \n\ \n\
Socket SNDBUF:\ \n\ \n\
Socket RCVBUF:\ \n\ \n\
Note ...adjust with caution!!
\n\
\n"; static char ConfigWelcomeFao [] = "

\n\ \n\ \n\ \n\
Welcome (index/home pages)
\n\ \n\ \n\ \n\
Format: \"file-name.file-type\" \ (e.g. HOME.HTML)
\n\ \n\ \n\
\n\
\n\ \

\n\ \n\ \n\ \n\
Access Control
\n\ \n\ \n\ \n\ \n\ \n\
Accept
\n\ \n\ \n\
Reject
\n\ \n\ \n\
\n\
\n\ \

\n\ \n\ \n\ \n\
Server Generated Reports
\n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\
Server Admin:\n\ \n\ \n\ email
Server Signature:\ \n\ enabled\n\ enabled-email\n\ disabled\n\
Basic Info Only:\n\ \n\ enabled\n\ disabled\n\
<META> Info:\n\ \n\ enabled\n\ disabled\n\
Error Report Path:\n\ \n\ \n\
Error Recommend:\ \n\ enabled\n\ disabled\n\
\n\
\n\ \

\n\ \n\ \n\ \n\
Authorization
\n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\
Cache Entries:\n\ \n\
Cache Entry Size:\ \n\ \n\ bytes
Cache Valid:\n\ \n\ \n\ minutes
Revalidate User:\n\ \n\ \n\ minutes
Failure Limit:\n\ \n\ \n\ attempts
Failure Period:\n\ \n\ \n\ hh:mm:ss
Failure Timeout:\n\ \n\ \n\ hh:mm:ss
Token Entries:\ \n\
Basic Authorization:\n\ \n\ enabled\n\ disabled\n\
Digest Authorization:\n\ \n\ enabled\n\ disabled\n\
GET nonce lifetime:\n\ \n\ \n\ minutes
PUT nonce lifetime:\n\ \n\ \n\ minutes
SYSUAF Logon Type:\n\ \n\ \n\
SYSUAF Accept Expired Pwd:\n\ \n\ enabled\n\ disabled\n\
SYSUAF Pwd Expired URL:\n\ \n\ \n\
\n\
\n\ \

\n\ \n\ \n\ \n\
Proxy Serving
\n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\
Serving:\ \n\ enabled\n\ disabled\n\
Add "Forwarded: by":\ \n\ \n\
Add "X-Forwarded-For:":\ \n\ \n\
Verify Max:\n\ \n\ \n\ records
Host Name Lookup Retry:\n\ \n\ \n\ attempts
Connect Timeout:\n\ \n\ \n\ hh:mm:ss
\n\
\n\ \

\n\ \n\ \n\ \n\
Scripting (CGI, DCL & DECnet)
\n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\
Scripting:\n\ \n\ enabled\n\ disabled\n\
Detach Process:\n\ \n\ enabled\n\ disabled\n\
Process Priority:\n\ \n\ \n\ server,user
Strict CGI Output:\n\ \n\ enabled\n\ disabled\n\
Spawn Authorized Privileges:\n\ \n\ enabled\n\ disabled\n\
Gateway BG:\n\ \n\ enabled\n\ disabled\n\
Soft Limit:\ \n\ \n\ script processes
Hard Limit:\n\ \n\ \n\ script processes
Bit-Bucket Timeout:\n\ \n\ \n\ hh:mm:ss
Zombie Life-Time:\n\ \n\ \n
CGIplus Life-Time:\n\ \n\ \n
DECnet Reuse Life-Time:\n\ \n\ \n
DECnet Connect List Limit:\n\ \n\ \n\ network connections
Cleanup Scratch Max:\n\ \n\ \n\ minutes
Cleanup Older-than:\n\ \n\ \n\ minutes
Script Run-Time:
\ Format: "file-type [SPACE] verb"
\ (e.g. ".PL [SPACE] PERL" or ".PL [SPACE] $PERL_EXE:PERL")\
\
\n\ \n\ \n\
Script Proctor:
\ Format: "minimum[+idle] pattern activation [notepad]"
\ (e.g. "2+0 (*pyrte*) /py-bin/proctor")\
\
\n\ \n\ \n\
\n\
\n\ \

\n\ \n\ \n\ \n\
Server-Side Includes
\n\ \n\ \n\ \n\ \n\ \n\
SSI:\n\ \n\ enabled\n\ disabled\n\
Exec:\n\ \n\ enabled\n\ disabled\n\
Access Counting:\n\ \n\ enabled\n\ disabled\n\
Max Size:\n\ \n\ \n\ kBytes
\n\
\n\ \

\n\ \n\ \n\ \n\
WebDAV
\n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\
WebDAV:\n\ \n\ enabled\n\ disabled\n\
Locking:\n\ \n\ enabled\n\ disabled\n\
Lock Timeout Default:\ \n\ \n\ hh:mm:ss
Lock Timeout Max:\ \n\ \n\ hh:mm:ss
Lock Collection Depth:\ \n\ \n\
Quota:\n\ \n\ enabled\n\ disabled\n\
Meta File Directory:\n\ \n\ \n\
\n\
\n\ \

\n\ \n\ \n\ \n\
Directory (Index of...)
\n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\
Access:\n\ \n\ enabled\n\ selective\n\ disabled\n\
Layout:\n\ \n\ \n\
Listing <BODY>:\n\ \n\ \n\ HTML tag
HTML Description:\n\ \n\ \n\ lines
<META> Info:\n\ \n\ enabled\n\ disabled\n\
Owner:\ \n\ enabled\n\ disabled\n\
Pre-Expired:\ \n\ enabled\n\ disabled\n\
Wildcard:\n\ \n\ enabled\n\ disabled\n\
No Implied Wildcard:\n\ \n\ enabled\n\ disabled\n\
Prot Violations Ignored:\n\ \n\ enabled\n\ disabled\n\
Readme:\n\ \n\ top\n\ bottom\n\ none\n\
Readme Files:
Format: "file-name.file-type" \ (e.g. README.HTML)
\n\ \n\ \n\
\n\
\n\ \

\n\ \n\ \n\ \n\
Icons
\n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\
Format: "icon-path [SPACE] \ alternative-text [SPACE] content-type"
\n\ \n\ \n\
Special Icons:
Format: "icon-path [SPACE] \ alternative-text"
Blank:\n\ \n\ \n\
Default:\n\ \n\ \n\
Directory:\n\ \n\ \n\
Parent Directory:\n\ \n\ \n\
Unknown:\n\ \n\ \n\
\n\
\n"; static char ConfigContentTypesFao [] = "

\n\ \n\ \n\ \n\
Content Types
\n\ \n\ \n\ \n\ \n\
Format: "file-suffix   \ content-type[;charset=]   [ftp:] [rfm:]   \ [/auto-script-path]   description (to-end-of-line)"
\n\ \n\ \n\
MIME.TYPES File:\n\ \n\ \n\
\n\
\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++ = "

(See "Services" Configuration)
\n\ \n"; } else { *vecptr++ = "\n\ \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; if (cfptr == &Config) *vecptr++ = ConfigNoticeInvalid; else *vecptr++ = cfptr->cfMisc.NoticeInvalid; /* 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) /* 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) 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"; *vecptr++ = cfptr->cfProxy.VerifyRecordMax; *vecptr++ = cfptr->cfProxy.HostLookupRetryCount; *vecptr++ = MetaConShowSeconds (rqptr, cfptr->cfProxy.ConnectTimeoutSeconds); /* 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, "\n\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, Http2PingSeconds; 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 [] = "

\n\ \n\ \n\
HTTP/2 !AZ
\n\ \n\ \n\ \ \n\ \ \n\ \ \n\ \ \n\ \ \n\ \n\
HTTP/2:!AZ
Max Concurrent Streams:!UL
Max Frame Size:!UL
Max Header List Size:!UL
Max Header Table Size:!UL
Initial Window Size:!UL
Ping Timer:!AZ
\n\
\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, Http2PingSeconds); } 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.PingSeconds); } 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 [] = "

\n\ \n\ \n\ \n\
HTTP/2
\n\ \n\ \ \n\ \ \n\ \ \n\ \ \n\ \ \n\ \ \n\ \ \n\ \
HTTP/2:\ \n\ enabled\n\ disabled\n\
Concurrent Streams Max:\ \n\ \n\
Frame Size Max:\ \n\ \n\
Header List Max:\ \n\ \n\
Header Table Max:\ \n\ \n\
Initial Window Size:\ \n\ \n\
Ping Timer:\n\ \n\ \n\ hh:mm:ss
\n\
\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.PingSeconds); 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 [] = "

\n\ \n\ \n\
!AZSecure Socket (SSL/TLS)!AZ
\n\ \n\ \n\ \n\ \ \n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \
Secure Socket:!AZ
Protocol:!AZ
Options:!AZ
Cipher List:!AZ
Cipher Suites:!AZ
Server Certificate:!AZ
Private Key:!AZ
Verify Peer:!AZ
Verify Peer Data Max:!SL kBytes !AZ
Verify Peer Depth:!UL
Verify Peer CA File:!AZ
Strict Transport Security:!AZ
Session Lifetime:!AZ!AZ
Session Cache Max:!SL!AZ
Instance Cache Max:!SL!AZ
Instance Cache Size:!SL!AZ
\n\
\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 ? "" : ""; *vecptr++ = ProtocolHttpsAvailable ? "" : ""; /* 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.CipherSuites); 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 [] = "

\n\ \n\ \n\ \n\
!AZSecure Socket (SSL/TLS)!AZ
\n\ \n\ \ \n\ \ \ \n\ \n\ \ \n\ \ \n\ \ \n\ \ \n\ \ \n\ \ \n\ \ \n\ \ \n\ \ \n\ \ \n\ \ \n\ \ \n\ \ \n\ \
Secure Socket:\ \n\ enabled\n\ disabled\n\
Protocol Version(s):\ \n\ \n\
Options:\ \n\ SSLoptions\" value=\"!AZ\">\n\
Cipher List:\ \n\ \n\
Cipher Suites:\ \n\ \n\
Server Certificate:\ \n\ \n\
Certificate Key:\ \n\ \n\
Verify Peer:\ \n\ enabled\n\ disabled\n\
Verify Peer Data Max:\ \n\ \n\ maximum kBytes request data during client certificate renegotiation
Verify Peer Depth:\ \n\ \n\
Verify Peer CA File:\ \n\ \n\
Strict Transport Security:\ \n\ \n\
Session Lifetime:\ \n\ \n\ hh:mm:ss
Session Cache Max:\ \n\ \n\ number of records
Instance Cache Max:\ \n\ \n\ number of shared records
Instance Cache Size:\ \n\ \n\ shared record size in bytes
\n\
\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 ? "" : ""; *vecptr++ = ProtocolHttpsAvailable ? "" : ""; /* 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.CipherSuites) > 80 ? strlen(cfptr->cfSesola.CipherSuites)/2 : 40; *vecptr++ = cfptr->cfSesola.CipherSuites; *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
(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 [16384], HtmlListBuffer [16384]; /*********/ /* 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) { if (*(cptr+1)) *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, "<", 4); sptr += 4; break; case '>' : if (sptr+4 >= zptr) return (ConfigStringOverflow); memcpy (sptr, ">", 4); sptr += 4; break; case '&' : if (sptr+5 >= zptr) return (ConfigStringOverflow); memcpy (sptr, "&", 5); sptr += 5; break; case '\"' : if (sptr+6 >= zptr) return (ConfigStringOverflow); memcpy (sptr, """, 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); } /*****************************************************************************/