/*****************************************************************************/ #ifdef COMMENTS_WITH_COMMENTS /* MapUrl.c Functions supporting mapping of URLs to VMS file specifications and VMS specifications to URLs, uses the HTTPd rule mapping file. The number of rules it can store is not fixed, but is limited by available memory and the practical considerations of processing large, linear rule databases. Comment lines may be provided by beginning a line with a '#' character. Lines may be continued by ensuring the last character on the line is a '\'. Virtual server syntax is the same as for authentication/authorization rules, [[virtual-host]] (all ports of host) or [[virtual-host:virtual-port]] ( matching specified port of host) for a specific host and [[*]] to resume rules for all virtual hosts. Wildcards --------- A single '*' wildcard matches intervening text up until the first character encountered that matches the character immediately following the wildcard. The rule map /one/*/three/* /first/*/third/* would map the following request path /one/two/three/four into /first/two/third/four but would not match the request path /one/two/and-a-half/three/four Two consecutive ('**') wildcards match intervening text up until the next string that matches the string following the wildcard. The rule map /one/**/three/* /first/*/third/* would map the following request paths /one/two/three/four /one/two/and-a-half/three/four respectively into /first/two/third/four /first/two/and-a-half/third/four Historically (pre v8.1) the template wildcard-matched portions of path strings could only be substituted in the positions of corresponding wildcards in the result string. There can be ocassions where there is not a one-to-one relationship between these wildcard sections in the source (template) and target (result) strings. It is sometimes useful to be able to drop one or more strings from the template and/or change the order of substitution. The use of 'positional wildcards' (for want of an even marginally better term) will allow this. When a wildcard is used in the result string it may optionally be followed by a single apostrophe character (') and a single digit character '1'..'9'. The digit is used to indicate which of the template wildcards is intended (first to last). The following request path /one/two/three/four/five.six would be processed by the rule pass /one/*/three/*/* /*'2/one/*'1/*'3 into the mapped path /four/one/two/five.six Using this notation all template wildcards must be specified 'positionally' :^) This rule is not legal. pass /one/*/three/* /two/*'2/four/* Positional wildcards ONLY APPLY to PASS, MAP, REDIRECT and USER rules. They cannot be used with EXEC, SCRIPT and UXEC rules. Extended File Specification --------------------------- Extended file specifications (required for ODS-5) are supported. A rule is used to flag such paths for ODS-5 tailored processing. Things that are not done to ODS-5 paths; case-changes and character substitution. Things that are done to ODS-5 paths; escaping to and from the extended file specification canonical escape syntax (i.e. '^'). Paths located on ODS-5 volumes need to have the ODS-5 rule SET against them. set /extended/* ODS-5 It is possible to explicitly mark a path as ODS-2 also, although as this is the default it is usually unnecessary. One situation where this might be useful is where all paths are ODS-5 except a small minority, in which case a rule such as the following might be used. set /* ODS-5 set /old-path/* ODS-2 Paths derived using the USER rule are specially processed. The SYSUAF user home directory's structure is determined using a sys$getdvi() to determined it's ACPTYPE. Hence no explicit rule is required for these. Mapping Rules ------------- [[virtual-host:optional-virtual-port]] EXEC template result [setting(s)] [conditional(s)] EXEC (runtime)template result [setting(s)] [conditional(s)] EXEC+ template result [setting(s)] [conditional(s)] FAIL template [conditional(s)] MAP template result [setting(s)] [conditional(s)] PASS template [conditional(s)] PASS template result [setting(s)] [conditional(s)] PROTECT template access-control [setting(s)] [conditional(s)] REDIRECT template result [setting(s)] [conditional(s)] SCRIPT template result [setting(s)] [conditional(s)] SCRIPT (runtime)template result [setting(s)] [conditional(s)] SCRIPT+ template result [setting(s)] [conditional(s)] SET template setting(s) [conditional(s)] USER template result [setting(s)] [conditional(s)] UXEC template result [setting(s)] [conditional(s)] UXEC (runtime)template result [setting(s)] [conditional(s)] UXEC+ template result [setting(s)] [conditional(s)] (Somewhat awkwardly the square brackets both denote optional fields and to literally delimit a conditional. Please do not confuse the two!) Note that as of V8.0 path settings (anything that can be set with a SET rule) can also follow the result string. If the rule applies and any conditional is matched then the settings are applied to the path BEFORE the mapping is done. PASS rules can map to a result comprising an HTTP status code (e.g. 403) with a following textual message (including white-space). Just delimit the result string with double or single quotes, or within curly braces. For example: PASS /private/stuff/* "403 Can't go in there!" [!ho:my.host.name] PASS /private/stuff/* '403 "/private/stuff/" is off-limits!' [!ho:my.host.name] EXEC rules can be used to map both directories and file types. The former only requires a single, trailing wildcard (example 1). The latter requires two wildcards (examples 2 and 3). The irst to locate the script, the second to map any path. This format can be used to globally map a file type, or confine that mapping to specified part of a tree. EXEC /cgi-bin/* EXEC *.cgi* *.cgi* EXEC /specified/path/*.cgi* /specified/path/*.cgi* PROTECT rules can be used require authorization for for the matching path. It complements the facility available via the WASD_CONFIG_AUTH configuration file, providing a simpler (and to certain extent less capble) authorization schema. See the relevant section in the description to AUTH.C module. General Run-Time Mapping ------------------------ This is distinct from "Run-Time (RTE) Environment" scripting discussed below. It also uses a similar rule construct and historically came much after RTE mappings. Hence the '!' kludge mentioned shortly. The historical way to map script file types (other than .EXE and .COM which are handled implicitly) has been to add [DclScriptRunTime] entries to WASD_CONFIG_GLOBAL. The (very small) disadvantage to using this is the need to completely restart the server to apply changes. Design-wise the better place for these sorts of mappings (file types to run-time engine) is here in WASD_CONFIG_MAP (it also allows /DO=MAP to change these). From v8.2 we can use an RTE-like construct to specify what non-RTE engine should be activated to process the specified script. It can be an executable, a DCL procedure or even verb. Here's how we might activate Perl using these rules: exec /cgi-bin/*.pl* (!perl)/cgi-bin/*.pl* exec /cgi-bin/*.pl* (!$perl_root:[000000]perl.exe)/cgi-bin/*.pl* exec /cgi-bin/*.pl* (!@cgi-bin:[000000]perl.com)/cgi-bin/*.pl* script /this_one* (!$perl_root:[000000]perl.exe)/cgi-bin/this_one.pl* The first uses a CLI verb, the second activates a specified executable and the last executes a DCL procedure (which in this presumably sets up some environment before activating Perl). Note the leading '!'. This is a bit of a kludge but not too onerous. Mapping Logical-Name Content ---------------------------- Generally logical names only provide concealed devices into the file-system for "root"ing some part of the web-space. That is the value of the logical name is only used in RMS (file-system) parsing, etc. There is a single exception. When template and result patterns contain no wildcard(s) a one-to-one mapping if performed. For example pass /this_is_an_example /dka0/example/this.txt and the file content at DKA0:[EXAMPLE]THIS.TXT is returned. With a one-to-one mapping the result string can represent a logical name and the translation of that name used as the mapping element. For a PASS rule the logical name value is used as the VMS result of the mapping (and therefore a VMS file specification). For a REDIRECT rule it should be a URL undertood by redirection. Here are examples: $ DEFINE /SYSTEM /EXEC EXAMPLE_OF DKA0:[EXAMPLE]ONE.TXT $ DEFINE /SYSTEM /EXEC EXAMPLE_GO "/wasd_root/runtime/httpd/" pass /of EXAMPLE_OF redirect /go EXAMPLE_GO Using this capability, the target of a rule may be changed simply by modifying the translated value of a logical name. Note that the mapping rule logical name translation is case-sensitive, and so common use of logical names (all upper-case) means the rule must be all upper case. With all lower or mixed case the rule must specify exact case, as in this example: $ DEFINE /SYSTEM /EXEC "EXAMPLE_go_two" "/wasd_root/src/httpd/" redirect /go_2 EXAMPLE_go_two Run-Time Environment (RTE) Mapping ---------------------------------- Each persistent run-time environment must have it's own mapping environment. This may, or may not, correspond to physically distinct directory areas. It is the mapping rules that identify run-time environments. A parenthesized interprester specification leads the result component of the rule. This is first extracted and then the EXEC rule behaves as normal. Hence the following example shows two such environments each with it's own interpreter. exec /plbin/* (cgi-bin:[000000]perlrte.exe)/ht_root/perl_local/* exec /pybin/* (cgi-bin:[000000]pyrte.exe)/ht_root/python_local/* script /this_one* (cgi-bin:[000000]oneeng.exe)/cgi-bin/this.one* The "/plbin/*" identifies request paths beginning with this string as a hypothetical, persistent Perl run-time interpreter, with the Perl source scripts available to it from HT_ROOT:[PERL_LOCAL]. Similarly with a hypothetical Java Environment. If a request with the following URI is given to the server http://the.host.name/plbin/plsearch/web/doc/ the following components will be derived run-time interpreter ... CGI-BIN:[000000]PERLRT.EXE Perl source script ..... HT_ROOT:[PERL_LOCAL]PLSEARCH.PL request path-info ...... WEB:[DOC] Mapping User Directories ------------------------ The USER rule effectively PASSes the user's SYSUAF default device and directory as the first wildcard substitution in the rule. Accounts that are disusered, captive or have expired passwords are never mapped, they are always "denied access by default". In the same way privileged accounts (those possessing SYSPRV) cannot be mapped this way (see below for a workaround). An example; if the user name DANIEL has the default device USER$DISK: and default directory [DANIEL] the following request path /~daniel/ would be mapped to the result and VMS file specification /user$disk/daniel/www/ USER$DISK:[DANIEL.WWW] using the following rule. USER /~*/* /*/www/ Note the "/www" subdirectory component. It is recommended that user directories always be mapped to a subdirectory of the physcial area. This effectively "sandboxes" Web access to that subdirectory hierarchy, allowing the user privacy elsewhere in the home area. To accomodate request user paths that do not incorporate a trailing delimiter after the username the following redirect may be used to cause the browser to re-request with a more appropriate path. REDIRECT /~* ///*/www/ WASD also "reverse maps" VMS specifications into paths and so requires additional rules to provides these mappings. (Reverse mapping is required during directory listings and error reporting.) In the above case the following rules would actually be required (and in the stated order). USER /~*/* /*/www/ PASS /~*/* /user$disk/*/www/* Where user home directories are spread over multiple devices (physical or concealed logical) a reverse-mapping rule would be required for each. Consider the following situation, where user directories are distributed across these devices (concealed logicals) USER$GROUP1: USER$GROUP2: USER$GROUP2: USER$OTHER: This would require the following mapping rules (in the stated order). USER /~*/* /*/www/ PASS /~*/* /user$group1/*/www/* PASS /~*/* /user$group2/*/www/* PASS /~*/* /user$group3/*/www/* PASS /~*/* /user$other/*/www/* Of course vanilla mapping rules may be used to provide for special cases. For instance, if there is requirement for a particular, privileged account to have a user mapping that could be provided as in the following (rather exagerated) example. PASS /~system/* /sys$common/sysmgr/www/* USER /~*/* /*/www/ PASS /~*/* /user$disk/*/www/* Path SETings ------------ The SET rule allows characteristics to be set against a particular path. They are then transfered to any request matching the path and applied to the request. This applies to FILES, not necessarily to scripts that supply a full HTTP response. These need to check and act on information provided by relevant CGI variables. Note that as of V8.0 path SETings can be applied with any rule that has a result string (i.e. the setting must follow both a template and a result and preceded any conditional). [NO]ACCEPT=LANG=([DEFAULT=][,CHAR=][,VARIANT=NAME|TYPE]) path will attempt to resolve a language-specific document, with default language (optional), 'char' is a character (optional) separating language from file type (default '_'), if the path template has a file type wildcard included the file content-type does not need to be "text/.." ACCESS=[NO]SERVER access as server account (best effort) ACCESS=[NO]PROFILE access according to SYSUAF profile ACCESS=[NO]READ allowed to read this path ACCESS=[NO]WRITE allowed to write to this path (implied read) [NO]ALERT indicate that a request with this path has been detected, HTTPDMON and OPCOM alert, and the process log gets a record ALERT=MAP alert provided immediately after mapping, ALERT=AUTH or immediately after authorization, ALERT=END or provided at request rundown (the default) ALERT= the integer can be a specific HTTP status value (e.g. 501) or the category (range of values, e.g. 599) alert if match [NO]AUTH=ALL all access must be subject to authorization (or fail) [NO]AUTH=ONCE authorize only the script portion of the request, do not repeat authorization on any path component [NO]AUTH=MAPPED authorize against the mapped path AUTH=REVALIDATE= revalidate authentication for this path at the specified interval AUTH=SYSUAF=PWDEXPURL= redirection URL if s SYSUAF-authenticated user's primary password has expired [NO]CACHE cache files (not any other output) CACHE=NONE do not cache CACHE=[NO]CGI cache CGI-compliant script output CACHE=[NO]COOKIE cache including requests with cookies CACHE=EXPIRES=0 cancels path cache entry expiry CACHE=EXPIRES=DAY entry expires on change of day CACHE=EXPIRES=HOUR entry expires on change of hour CACHE=EXPIRES=MINUTE entry expires on change of minute CACHE=EXPIRES= specify the exact period before expiry CACHE=[NO]FILE cache files CACHE=GUARD= prevent (Pragma:) reloads during these seconds CACHE=MAX= up to kBytes in size (overrides [CacheFileKBytesMax]) CACHE=[NO]NET cache response network output of any kind CACHE=[NO]NPH cache NPH-compliant script output CACHE=[NO]PERMANENT cache this, do not allow it to be flushed CACHE=[NO]QUERY cache including requests with query strings CACHE=[NO]SCRIPT synonym for (both) 'cache=cgi cache=nph' CACHE=[NO]SSI cache Server-Side Includes output CGIPLUSIN=CC=NONE set explicit carriage-control to be added to each CGIPLUSIN=CC=LF CGIPLUSIN record (esoteric? a bit; ask Alex Ivanov :^) CGIPLUSIN=CC=CR CGIPLUSIN=CC=CRLF CGIPLUSIN=EOF terminate each request's CGIPLUSIN stream with an EOF (same comment as immediately above) CGI=PREFIX= instead of the default "WWW_" specify what is needed, to have no prefix at all specify CGI=PREFIX= CHARSET= any "text/..." content-type files use the specified charset CLIENT=FORWARDED replace client IP address with Forwarded: header CLIENT=IF=FORWARDED replace client IP address IF a Forwarded: header CLIENT=LITERAL= really just for ease of testing CLIENT=RESET revert to original (upstream) client data CLIENT=XFORWARDEDFOR replace IP address with X-Forwarded-for: header CLIENT=IF=XFORWARDEDFOR replace IP address IF an X-Forwarded-for: header CORS=AGE= Access-Control-Max-Age: response header CORS=CRED= Access-Control-Allow-Credentials: response header CORS=EXPOSE= Access-Control-Expose-Headers: response header CORS=HEADERS= Access-Control-Allow-Headers: response header CORS=METHODS= Access-Control-Allow-Methods: response header CORS=ORIGIN= Access-Control-Allow-Origin: response header CONTENT= all files have the "Content-Type:" forced to that specified (obvious use is to provide plain-text or binary versions of files using perhaps "set /plain-text/* content=text/plain", then mapping that generally back with "map /plain-text/* /*") another: "set /bogus/* "content=text/html; charset=BLAH" CSS= style sheet to load to customise server-generated pages DICT=[[= directory listing page is given this charset (this could be called the Alex Ivanov rule ;^) DIR=DELIMIT[=BOTH] both top and bottom rule and any readme DIR=DELIMIT=HEADER only top rule and any readme DIR=DELIMIT=FOOTER only bottom rule and any readme DIR=DELIMIT=NONE no top or bottom rule or readme DIR=FONT=INHERIT listing font inherited from browser or document DIR=FONT=MONOSPACE listing font monospace (default) DIR=ILINK icon plain-text link (default) DIR=NOILINK no icon plain-text link DIR=IMPLIEDWILDCARD implied wildcard enabled DIR=NOIMPLIEDWILDCARD implied wildcard disabled DIR=LAYOUT= same as index= DIR=SORT=[+|-] pre-sort directory listing DIR=STYLE[=DEFAULT] current (post-10.4) style DIR=STYLE=ORIGINAL[2] pre-v8.2 WASD style DIR=STYLE=ANCHOR[2] post-v8.2 WASD style DIR=STYLE=HTDIR[2] Alex Ivanov's listing style DIR=STYLE=SORT[2] HTML table and sortable DIR=STYLE=TABLE[2] post-v10.4 WASD style (current, default) DIR=TARGET= open a file in this window (e.g. "_blank") DIR=TITLE= directory name (0 = none, 1 = top, 2, 3..99 = bottom) DIR=TITLE=DEFAULT whatever the default is for the style DIR=TITLE=OWNER the VMS owner DIR=TITLE=REMOTE if authorised access just the remote user name DIR=TITLE=THIS=".." literal string DIR=THESE=[,] one of more wildcard file name selectors DIR=VERSIONS=|* display a maximum of this many file versions DIR=WILDCARD wildcard-forced listing enabled (same as [DirWildcard]) DIR=NOWILDCARD wildcard-forced listing disabled [NO]EXPIRED files in the path are sent "pre-expired" NOHTML cancel any/all previously set html= HTML=BODYTAG= HTML tag HTML=HEADER= HTML page header text (can include markup) HTML=HEADERTAG= HTML header tag (usually colour) HTML=FOOTER= HTML page footer text (can include markup) HTML=FOOTERTAG= HTML footer tag (usually colour) HTTP=ACCEPT-CHARSET= explicitly set the request's accepted charset HTTP=ACCEPT-LANGUAGE= explicitly set the request's accepted language HTTP2=PROTOCOL=1.1 downgrade HTTP/2 to HTTP/1.1 (immediately) HTTP2=SEND=GOAWAY[=] send GOAWAY frame with optional error code HTTP2=SEND=PING send PING frame HTTP2=SEND=RESET[=] send RST_STREAM frame with optional error code HTTP2=STREAMS=MAX= per-path maximum concurrent streams HTTP2=WRITE=[low|normal|high] set response write priority INDEX= "Index of" format string (same as "?httpd=index&...") [NO]LOG requests to this path are not to be access-logged MAP=[NO]AFTER (re)map after authorization MAP=[NO]ELLIPSIS allows mapping of the VMS '...' ellipsis wildcard that provides for tree traversal MAP=[NO]EMPTY traditionally a path must have contained at least one char to be mapped, this allows "empty" paths to be mapped MAP=[NO]METHOD set the path to process an HTTP (/1.1) extension-method e.g. 'if (request-method:QUARK) \ script /quark* /cgi-bin/quark* map=method' MAP=[NO]ONCE normally, when a script has been derived from a path, WASD goes on to map the 'path' portion in a separate pass - this SETing provides the derived path as-is MAP=RESTART begin again at rule number one (limit on this action) MAP=ROOT= prefix all result paths with this string (path) MAP=SET=[NO]REQUEST path SETings affect the request (or only the mapping) MAP=SET=[NO]IGNORE all path SETings are ignored (except 'map=set=noignore') MAP=URI begin to process against raw request URI (path plus query) NOTEPAD=[+] text (perhaps keywords) added to a request during mapping that can be detected during subsequent metacon, mapping and authorization rule processing (not externally visible) NOTEPAD PERSISTS ACROSS INTERNALLY REDIRECTED REQUESTS! ODS=2 path marked as ODS-2 (path default) ODS=5 path marked as ODS-5, with EFS encoded file names ODS=ADS path marked as having filenames Advanced Server (6) encoded ODS=PWK path marked as having filenames PATHWORKS (4 & 5) encoded ODS=SMB same as ODS=ADS (only for the comfort of Samba users) ODS=SRI path marked as having filenames SRI (MultiNet NFS) encoded NOODS reset the path's ODS file naming ODS=NAME=8BIT file name uses native ODS 8 bit encoding (default) ODS=NAME=UTF8 file name uses explicit UTF-8 encoding ODS=NAME=DEFAULT return naming to the default encoding [NO]PROFILE VMS SYSUAF-authenticated security profile applies/does not apply to this path PROXY=[NO]AFFINITY enable/disable affinity PROXY=NOFORWARDED disable the "Forwarded: by" field PROXY=FORWARDED[=BY] enable the field with "by" data PROXY=FORWARDED=FOR enable the field with "by" and "for" data PROXY=FORWARDED=ADDRESS enable the field with "by" and "for" address PROXY=NOXFORWARDEDFOR disable "X-Forwarded-For:" field PROXY=XFORWARDEDFOR[=ENABLED] add client host, propagate any existing PROXY=XFORWARDEDFOR=ADDRESS add client address, propagate any existing PROXY=XFORWARDEDFOR=UNKNOWN hide this host, propagate any existing PROXY=BIND= bind the outgoing proxy socket to this IP address PROXY=CHAIN= chain to this proxy server PROXY=CHAIN=CRED= : credentials for chain PROXY=HEADER=[=] remove or modify this request header PROXY=REVERSE=[NO]AUTH suppress propagation of any "Authorize:" header PROXY=REVERSE=LOCATION rewrite a reverse proxy 302 "Location:" response to contain the proxy server (can ONLY be used following a 'redirect /foo/* /http://foo.bar/*' rule) PROXY=REVERSE=[NO]VERIFY for a locally authorized, reverse proxied request create a verifyable authorization header containing the username and a unique identifier for 'callback' PROXY=TUNNEL=REQUEST= make this the tunnelled request PUT=MAX= maximum Kbytes allowed to be PUT/POSTed is '*' is used instead it means no limit PUT=RFM=[FIX512|STM|STMCR|STMLF|UDF] set the record format for binary PUT/POSTs QUERY-STRING= set the request's query-string (URL-encode if necessary) REGEX= AWK, DEFAULT, ED, EGREP, GREP, POSIX_AWK, POSIX_BASIC, POSIX_EGREP, POSIX_EXTENDED, POSIX_MINIMAL_BASIC, POSIX_MINIMAL_EXTENDED, SED, WASD REPORT=400= bad request reported as (e.g. "report=400=403") REPORT=403= forbidden reported as (e.g. "report=403=404") REPORT=404= not found reported as (e.g. "report=404=403") REPORT=BASIC supply basic error information for requests on this path REPORT=DETAILED supply detailed error information for requests on this path REPORT=TUNNEL supply error message suitable for firewall/raw tunnel RESPONSE=200=203 modify a 200 response to 203 for log analysis RESPONSE=203=200 undoes the above RESPONSE=[NO]CSP= add Content Security Policy to response header RESPONSE=[NO]CSPRO= add CSP Report Only to response header RESPONSE=HEADER=ADD= append this header field to the response header RESPONSE=HEADER=NOADD cancel (potentially) additional header fields RESPONSE=HEADER=FULL revert to normal response header transmission RESPONSE=HEADER=NONE suppress response header transmission (i.e. the file or content contains *full* HTTP response - NPH-like!) RESPONSE=HEADER=BEGIN suppress the end-of-header blank line so that the file or other content can provide additional header lines RESPONSE=GZIP=ALL compress all responses (those possible anyway) RESPONSE=GZIP= compress responses known to be larger than kBytes RESPONSE=GZIP=NONE do not compress any responses RESPONSE=HTTP=ORIGINAL respond with HTTP/1.0 if request was that version RESPONSE=[NO]CHUNKED return applicable responses chunked RESPONSE=STS= Strict-Transport-Security: header RESPONSE=VAR reset variable length record to default () RESPONSE=VAR=CRLF variable length record file append RESPONSE=VAR=LF append (default) RESPONSE=VAR=NONE append nothing RMSCHAR= provides the RMS-invalid substitution character, which unless otherwise specified is the dollar symbol. Any general RMS-valid character may be specified (e.g. alpha-numeric, '$', '-' or '_', although the latter three are probably the only REAL choices). When an RMS-invalid character (e.g. '+') or syntax (e.g. multiple periods) is encountered this character is substituted. NOTE: is not applied to ODS-5 volumes. SCRIPT=AS= the script process will be using this username/account (only applies if detached script processes are enabled) SCRIPT=BIT-BUCKET= per-path equivalent to config file setting SCRIPT=BODY=[NO]DECODE decode any chunked or gzip encoded request body before delivering the content to the script SCRIPT=COMMAND= provide the script activation command-line with qualifiers, parameters, etc. (first character must be an asterisk or it overrides the full verb) SCRIPT=CONTROL= equivalent of "Script-Control:" in CGI response SCRIPT=CPU= CPU limit for each *script's* processing (not a per-process limit like CPULM would be) SCRIPT=DEFAULT= default directory script process should be set to before activation ('#" disables this, can be a U**x style spec beginning '/' in which case it's ignored) SCRIPT=LIFETIME= CGI or CGIplus lifetime for quiescent processes (per-path equivalent of [DclZombieLifetime] and DclCGIplusLifeTime] global directives) SCRIPT=SYMBOLS=[NO]TRUNCATE truncate CGI symbols that would otherwise exceed the maxima of this VMS versions CLI SCRIPT=SYNTAX=[NO]UNIX script file name and path translated is passed in U**x syntax SCRIPT=FIND (default) search for the script file in any 'script' or 'exec' SCRIPT=NOFIND do not search for the script file (for use with RTEs) SCRIPT=PARAMS=[+](name=value) a list of additional (non-CGI) variables assigned and passed to a script [NO]SCRIPT=PATH=FIND check that the PATH_TRANSLATED exists and before invoking the script report 404 if it doesn't [NO]SCRIPT=QUERY=NONE do not parse query string into form or key elements [NO]SCRIPT=QUERY=RELAXED don't error report form-url-encoding issues, let the script deal with it if necessary [NO]SEARCH=NONE do not activate (any) default search script SERVICE= move request to this service (when mapping finished) SSI=PRIV mark a path as allowed to contain SSI documents that can SSI=NOPRIV use privileged SSI statements (e.g. "#dcl") SSI= where string is a list of "#dcl" parameters allowed (this is a finer-grained control that SSI=[NO]PRIV) SSLCGI=NONE sets the style of SSL-related CGI variables SSLCGI=APACHE_MOD_SSL SSLCGI=APACHE_MOD_SSL_CLIENT SSLCGI=APACHE_MOD_SSL_EXTENS SSLCGI=APACHE_MOD_SSL_OID SSLCGI=PURVEYOR [NO]SSLCGI [NO]STMLF files in this path can be converted from variable to stream-LF THROTTLE=FROM= n1, requests after which queuing occurs THROTTLE=TO= n2, requests after which the queue is FIFOed THROTTLE=RESUME= n3, requests after which FIFOing stops THROTTLE=BUSY= n4, requests after which an immediate 503 "busy" THROTTLE=NONE resets previously mapped throttle THROTTLE=TIMEOUT=QUEUE= t/o1, hh:mm:ss before a queued request processes THROTTLE=TIMEOUT=BUSY= t/o2, hh:mm:ss before a queued request terminates THROTTLE=USER= u1, per-user throttling THROTTLE=n1[/u1][,n2,n3,n4,t/o1,t/o2] n1 = 'from', u1 = 'per-user', n2 = 'to', n3 = 'resume', n4 = 'busy', t/o1 = 'timeout-queue', t/o2 = 'timeout-busy' TIMEOUT=PERSISTENT= hh:mm:ss ("none" to disable, formerly 'KEEPALIVE=') TIMEOUT=NOPROGRESS= hh:mm:ss TIMEOUT=OUTPUT= hh:mm:ss TIMEOUT=n,n,n hh:mm:ss; persistent, noprogress, output NOTIMEOUT sets all three (n,n,n) timeouts to infinite (none) WEBDAV=[NO]HIDDEN display (default), do not display, hidden file names WEBDAV=[NO]LOCK allow/apply WebDAV locking to this path WEBDAV=META=DIR= string (subdirectory spec or full directory spec) WEBDAV=[NO]PROFILE WebDAV access according to SYSUAF profile WEBDAV=[NO]PROP allow/apply WebDAV 'dead' property(ies) to this path WEBDAV=[NO]PUT=LOCK a resource must be locked before a PUT is allowed WEBDAV=[NO]READ WebDAV methods allowed read this tree WEBDAV=[NO]SERVER WebDAV access as server account (best effort) WEBDAV=[NO]WINPROP when NOWINPROP windows properties are ignored and emulated WEBDAV=[NO]WRITE WebDAV methods allowed write to this path (implied read) WEBDAV=LOCK=TIMEOUT=DEFAULT= hh:mm:ss WEBDAV=LOCK=TIMEOUT=MAX= hh:mm:ss WEBSOCKET=INPUT= size of WEBSOCKET_INPUT mailbox WEBSOCKET=OUTPUT= size of WEBSOCKET_OUTPUT mailbox [CONFIGFILE] ------------ The non-global [IncludeFile] equivalent [ConfigFile] designed for local, per-service configuration management can include a subset of the full set of mapping rules and settings. The following are ALLOWED: FAIL MAP PASS PROTECT REDIRECT SET [NO]ACCEPT= SET CHARSET= SET [NO]EXPIRED SET [NO]HTML= SET INDEX= SET [NO]MAP=ONCE SET QUERY-STRING= SET RESPONSE=HEADER= Those that cannot be used in [ConfigFile] are reported as errors during configuration load. MAP=ROOT Mapping ---------------- This path SETing allows for the more straight-forward mapping of virtual service paths into a virtual-service-specific directory structure. It ensures that for all applicable rules the specified string is prepended to the mapped path before it is converted into a file-system specification. This remove the need to do it with each virtual-service-specific rule. It needs to be redone or undone (e.g. set to empty) for each virtual service or when reverting to general rules. For example [[a.virtual.host]] set * map=root=/dka0/a/ # 'a' has no access to any scripts at all pass /* /* fail * [[b.virtual.host]] set * map=root=/dka0/b/ # 'b' are allowed to execute their own scripts exec /cgi-bin/* /cgi-bin/* pass /* /* fail * [[c.virtual.host]] # 'c' is allowed to execute the general server scripts exec /cgi-bin/* /cgi-bin/* set * map=root=/dka0/c/ pass /* /* fail * [[*]] set * map=root= exec /cgi-bin/* /cgi-bin/* pass /* /web/* fail * PERSONA-based User Scripting ---------------------------- For use with VMS V6.2 and greater (or 6.0 and 6.1 if compiled with the PERSONA_MACRO build option), with the /PERSONA qualifier active. The following rule set will allow user account based scripting. SET /~*/www/cgi-bin/* script=as=~ UXEC /~*/cgi-bin/* /*/www/cgi-bin/* USER /~*/* /*/www/* REDIRECT /~* /~*/ PASS /~*/* /dka0/users/*/* DECnet-based User Scripting --------------------------- If DECnet/OSU scripting is enabled then the following rule will activate a script in the specified user's directory (all other things being equal). Always map to some unique and specific subdirectory of the home directory. exec /~*/cgi-bin/* /0""::/where/ever/*/cgi-bin/* It's a little like the user-mapping rules: pass /~* /where/ever/* Mapping Conditionals -------------------- *************** * OBSOLESCENT * *************** ALTHOUGH MAPPING RULE CONDITIONALS DESCRIBED BELOW WILL CONTINUE TO BE SUPPORTED IN THE FORESEEABLE FUTURE THE PREFERED POST-7.2 MECHANISM FOR CONDITIONAL PROCESSING OF RULES IS PROVIDED BY THE META-CONFIG CONDITIONAL STRUCTURES AND DIRECTIVES. Conditionals are new to v4.4 and allow mapping rules to be applied conditionally! That is, the conditionals contain strings that are matched to specific elements of the request and only if matched are the corresponding rules applied. The conditionals may contain the '*' and '%' wildcards, and optionally be negated by an '!' at the start of the conditional string. Conditionals must follow the rule and are delimited by '[' and ']'. Multiple, space-separated conditions may be included within one '[...]'. This behaves as a logical OR (i.e. the condition is true if only one is matched). Multiple '[...]' conditionals may be included against a rule. These act as a logical AND (i.e. all must have at least one condition matched). The result of an entire conditional may be optionally negated by prefixing the '[' with a '!'. If a conditional is not met the line is completely ignored. Conditional rules are not used for 'backward' translation (i.e. from VMS to URL path) so another rule must exist somewhere to do these mappings. Conditional rules are only used by the HTTPd server, they are completely ignored by any scripts using the MapUrl.c module. [!]ac:accept 'Accept:' [!]al:accept-language 'Accept-Language:' [!]as:accept-charset 'Accept-Charset:' [!]ca: boolean, callout in progress? [!]ck:cookie 'Cookie:' [!]dr:string document root (set map=root=) [!]ex: boolean, extended file specification path [!]fo:host-name/address 'Forwarded:', proxies/gateways [!]ho:host-name/address client's of course! [!]hm:host network mask client mask, see immediately below [!]me:http-method GET, POST, ?, etc. [!]mp:string derived mapped path (after script or map rule) [!]no:string notepad keywords/tokens [!]pa:digit 1 if first pass, 2 if second pass through rules [!]pi:path-info request path information [!]qs:query-string request query string [!]rc:[digit] internally redirected count, 0..4, or boolean [!]rf:refering-URL 'Referer:' [!]rq:string request field (e.g. "Keep-Alive: 300") [!]ru:string request URI - non-decoded path string [!]sc:scheme request scheme 'http:', 'http', 'https:' or 'https' [!]sn:server-name server host name [!]sp:server-port server port [!]st:script-name if during second pass compare to script name [!]ua:user-agent 'User-Agent:' [!]vs:host-name/address virtual server, "Host:", destination [!]xf:client "X-Forwarded-For:" proxied cleint details The host-mask ('HM') directive is a dotted-decimal network address, a slash, then a dotted-decimal mask. For example "[HM:131.185.250.0/255.255.255.192]". This has a 6 bit subnet. It operates by bitwise-ANDing the client host address with the mask, bitwise-ANDing the network address supplied with the mask, then comparing the two results for equality. Using the above example the host 131.185.250.250 would be accepted, but 131.185.250.50 would be rejected. VERSION HISTORY --------------- 12-FEB-2020 MGD SET response=[no]csp= ("content-security-policy:") SET response=[no]cspro= ("..policy-report-only:") refactor MapUrl_ExplainPathSet() 20-JAN-2020 MGD quieten string overflow reports 30-JAN-2019 MGD SET response=200=203 for request tracking and log analysis 15-AUG-2018 MGD bugfix; for DECnet tasks when StringSliceValue() modified (25-MAY-2017 allow quote-delim inside space-delimited) 13-AUG-2018 MGD SET response=var=crlf SET response=var=lf SET response=var=none 06-APR-2018 MGD MapUrl__Map() allow one-to-one logical name content 05-APR-2018 MGD bugfix; longstanding MapUrl__Map() mutiple template wildcards when reverse mapping (search for the version log date) 25-JAN-2018 MGD SET dir=title=default SET dir=title=owner SET dir=title=remote SET dir=title= SET dir=title=this= 15-JUN-2017 MGD MapUrl_GuaranteeAccess() mapping as well as authorisation 25-MAY-2017 MGD bugfix; MapUrl_ExplainPathSet() response=header=add=.. 07-MAR-2017 MGD SET proxy=header=[=] 26-OCT-2015 MGD SET dict=[=] SET http2=streams=max= SET http2=protocol=1.1 SET http2=write=[low|normal|high] SET http2=send=goaway[=] SET http2=send=ping SET http2=send=reset[=] SET sslcgi=apache_mod_ssl_client SET sslcgi=apache_mod_ssl_extens 17-APR-2015 MGD #define MAP_BUFFER_SIZE for fundamental mapping buffers 04-APR-2015 MGD bugfix; MapUrl_ExplainPathSet() ->ResponseChunked 24-MAR-2015 MGD SET response=sts= (Strict-Transport-Security: header) 21-NOV-2014 MGD MapUrl_SetClientAddress() and MapUrl_ResetClientAddress() call WatchFilterClientService() if client address changed 06-NOV-2014 MGD SET client=[forwarded|if=forwarded|literal=|reset| if=xforwardedfor|xforwardedfor] 06-SEP-2014 MGD SET dir=font=[inherit|monospace(D)] SET dir=style=TABLE (new default) SET ods=name=8bit, ods=name=utf8, ods=name=default SET webdav=[no]hidden SET webdav=meta=dir= 28-SEP-2013 MGD SET cors= 27-SEP-2013 MGD SET dir=versions=|* 17-AUG-2013 MGD put=rfm=[STM|STMCD|UDF] added to FIX512,STMLF bugfix; MapUrl__Map() MAPURL_REPORT_MATCH_RULENOCOND 25-JUN-2013 MGD SET dir=delimit= SET dir=[no]ilink SET dir=style=sort (plus the dir=style=2) SET dir=sort=[+|-] SET dir=target= SET dir=these=[,] 30-MAY-2013 MGD bugfix; MapUrl__Map() reverse mapping wildcard copy 15-SEP-2011 MGD SET map=uri bugfix; map=noonce 06-MAR-2011 MGD SET cache=[no]cookie 26-FEB-2011 MGD bugfix; set rule 'CacheSetting' boolean with any CACHE=.. 02-JAN-2011 MGD SET regex= 07-SEP-2010 MGD SET proxy=tunnel=request= 18-JUL-2010 MGD Uni Malaga pushes report items from !3ZL to !4ZL :-) 01-JUL-2010 MGD bugfix; MapUrl_ControlReload() 19-JUN-2010 MGD put=max=* represents no (effective) limit 27-FEB-2010 MGD SET proxy=chain=cred= 09-FEB-2010 MGD SET script=lifetime= SET response=HTTP=original 23-JAN-2010 MGD SET service= SET websocket= SET notimeout (short-hand for timeout=none,none,none) 11-JAN-2010 JPP MapUrl__Map() increase some buffer sizes 05-SEP-2009 MGD allow "pass:-1" to indicate reverse-mapping 23-AUG-2009 MGD SET css= bugfix; MapUrl__Map() to URL use request ODS not path ODS 21-JUN-2009 MGD SET put=max=, put=rfm=[FIX512|STMLF] 08-OCT-2008 MGD bugfix; MapUrl__Map() proxy 'fall-thru' 19-APR-2008 MGD SET script=agent=as= 23-MAY-2007 MGD refine loading and mapping of path SETings, MapUrl_Map()/__Map() now have a REQUEST_PATHSET parameter (to better decouple file-system mapping and path SETing) 11-MAY-2007 MGD bugfix; MapUrl_Map() auth agent modifying path SETings 01-MAY-2007 MGD SET access=[no]access, access=[no]profile, access=[no]read, access=[no]write, webdav=[no]access, webdav=[no]profile, webdav=[no]read, webdav=[no]write, webdav=[no]lock, webdav=[no]prop, webdav=lock=timeout= 22-APR-2006 MGD SET proxy=[no]affinity 26-JAN-2006 MGD increase MapUrl__Map() WildBuffer[] storage to 4096 26-OCT-2005 MGD bugfix; MapUrl__Map() SCRIPT result copy not checking for null resulting in occasional overflow error status 10-SEP-2005 JPP SET proxy=reverse=[no]auth 01-JUN-2005 MGD SET script=symbol=[no]truncate 21-MAY-2005 MGD SET throttle=/ per-user throttle 08-JAN-2005 MGD SET script=control=<...> 16-DEC-2004 MGD SET response=[no]chunked 04-NOV-2004 MGD SET script=syntax=[no]unix 16-OCT-2004 MGD SET response=gzip=<...>, SET script=body=[no]decode, allow a throttle of zero to be set, throttle=none to reset previously mapped throttle, unbundle some functionality into MAPCON.C, MAPODS.C and MAPUSER.C modules (been wanting to do this for ages) 24-SEP-2004 MGD bugfix; auth=revalidate= is minutes not seconds 31-AUG-2004 MGD SET report=tunnel 12-AUG-2004 MGD bugfix; parse timeout=n,n,n allowing to specify "none" 20-JUL-2004 MGD SET timeout=keepalive= superceded by timeout=persistent= 20-APR-2004 MGD actual on-disk structure for each PASS result (ODS-2 or ODS-5) is applied to a path unless otherwise SET with ODS=, don't bother translating a PASS unless it looks file-system (consumes a few less cycles for things like proxy) 08-MAR-2004 MGD MapUrl_Map() increase wildcard buffer space 26-FEB-2004 MGD SET script=default= 13-JAN-2004 MGD review string SETings for empty string behaviour 10-JAN-2004 MGD SET ssi=exec= 08-JAN-2004 MGD SET response=header=[no]add[=""] 16-DEC-2003 MGD mapping now URL-encodes a redirect wildcard path portions 20-NOV-2003 MGD SET proxy=reverse=location, proxy=reverse=verify 28-SEP-2003 MGD when do a callout path mapping use a 'throw-away' path SETing structure to prevent modification of request itself, SET path=set=[no]ignore, path=set=[no]request prevent ODS-2 directory paths from containing single periods 01-SEP-2003 MGD SET map=root= (groan %^p) 'DR' conditional (parallels metacon "document-root:") 07-JUL-2003 MGD SET script=command=, SET cache=[no]cgi, cache=expires=.., cache=[no]file, cache=[no]net, cache=maxkbytes=.., cache=[no]nph, cache=[no]script, cache=[no]ssi, response=header=[append|full|none] bugfix; do not allow SET mapping during a callout 27-JUN-2003 MGD bugfix; request Html.. memory allocation (jpp@esme.fr) 24-MAY-2003 MGD SET cache=[no]permanent, cache=max= 09-MAY-2003 MGD regular expression support, SET notepad=[+] (associated 'NO' conditional), SET map=restart, SET proxy=unknown 'RQ' conditional (parallels metacon "request:") 22-APR-2003 MGD improve SET rule error reporting (if no rule or no template) 02-APR-2003 MGD SET proxy=xforwardedfor=[disabled|enabled|address|unknown] SET proxy=forwarded=[disabled|by|for|address] added 'XF' conditional, removed 'UD' (meaningless) 26-MAR-2003 MGD SET alert=nnn (were 'nnn' can be 500, 599, 403, etc.) 08-MAR-2003 MGD SET html=[bodytag|header|headertag|footer|footertag]=[..], dir=style[=default|original|anchor|htdir] 15-FEB-2002 MGD SET [no]search=none, script=params=+(name=value) concatenates to any existing 17-JAN-2003 MGD general (non-RTE) run-time allowed with (!..) syntax, both run-time specifications allowed with SCRIPT rule SET cgiplusin=[none|cr|lf|crlf], SET cgiplusin=eof, SET script=query=none, SET script=path=find 10-JAN-2003 MGD SET script=query=relaxed 16-NOV-2002 MGD SET auth=all (all access must be authorized or fail) 06-NOV-2002 MGD added 'MP', 'RC' and 'ST' conditionals 12-OCT-2002 MGD refine metacon reporting, refine mapping rule processing to ensure that paths with forbidden syntax (e.g. multiple '/') generate RMS bad syntax 05-OCT-2002 MGD 'positional' wildcards, SET query-string=, provide 'rqptr->MetaConPass', confine script=as= to first pass (script resolution) added 'PA' conditional 24-SEP-2002 MGD added 'PI' and 'RU' conditionals 16-SEP-2002 MGD MapOdsElementsToVms() excise parent directory syntax, SET path [no]map=ellipsis (off by default), SET report=4nn=nnn for mapping HTTP status 14-SEP-2002 MGD only use MapUrl_VmsUserName() path ODS if not already set, SET dir=charset= directory listing charset mapping rule 10-SEP-2002 MGD add en/decoding for Advanced Server (Samba) file names 15-AUG-2002 MGD SET alert=map, alert=auth, alert=end variants for ALERT, SET ods=2, ods=5, now ods=pwk and ods=sri for below, rework ..UrlToVms() and ..VmsToUrl() to allow for mapping to and from SRI encoding (NFS) and PATHWORKS encoding (and VMS to URL functions no longer explicitly URL-encode) 07-AUG-2002 MGD bugfix; 'script' and 'exec' MetaConParseReset() state 04-AUG-2002 MGD allow for 'pass /* 400' (i.e. no trailing message), bugfix; template/result wildcard checking for scripting rules 31-MAY-2001 MGD SET dir=access, dir=noaccess, dir=access=selective, dir=impliedwildcard, dir=noimpliedwildcard, dir=wildcard, dir=nowildcard 13-MAY-2002 MGD SET auth=SYSUAF=pwdexpURL= 07-APR-2002 MGD exchange DEVICE:[DIRECTORY]FILE.TYPE for the hopefully more informative NO:[REVERSE.MAPPING.FOR.THIS]FILE.PATH 14-MAR-2002 MGD bugfix; throttle report (jf.pieronne@laposte.net) 14-JAN-2002 MGD added '**' and '*!' wildcard match and discard to template, eliminate device:[.directory] (multiple consecutive '/'), bugfix; arrghhh - wildcard substitution in MapUrl__Map() 18-NOV-2001 MGD path SETings may now trail any rule with a result string, and are applied to the matched path before mapping occurs, SET http=accept-charset=, accept=lang 28-OCT-2001 MGD bugfix; DECnet user script mapping 13-OCT-2001 MGD ensure a conditional is not mistaken for a missing template, script=params=(name=value[,name="value1 value2"]), proxy=bind=IP-address, proxy=chain=host:port, alert, auth=revalidate=hh:mm:ss, bugfix; wildcard substitution in MapUrl__Map() 25-AUG-2001 MGD meta-config (even workin' on my birthday, sigh) 04-AUG-2001 MGD support module WATCHing 15-MAY-2001 MGD bugfix; remove 'RU' conditional (mapping before auth!) 10-MAY-2001 MGD modify throttle parameter meanings, set rule SCRIPT=CPU= for limiting script process CPU 13-APR-2001 MGD add queue length to THROTTLE=n[,n,n,hh:mm:ss,hh:mm:ss] add SCRIPT=BIT-BUCKET=hh:mm:ss, bugfix; conditions for NetThisVirtualService() call 05-APR-2001 MGD bugfix; 'HM' network mask processing 28-MAR-2001 MGD EXEC of file type 13-MAR-2001 MGD set rules THROTTLE=n[,n,n,n] & TIMEOUT=n,n,n "hh:mm:ss" for providing a more versatile period 28-FEB-2001 MGD OdsLoadTextFile(), OdsParseTextFile(), [IncludeFile] 22-DEC-2000 MGD use of backslash to escape non-wildcard reserved characters in rule and conditional strings (i.e. \] for ]) 19-NOV-2000 MGD bugfix; mapping '/' 10-NOV-2000 MGD bugfix; MapOdsUrlToVms() final ';' 01-OCT-2000 MGD set rule SCRIPT=AS=, rework mapping code somewhat, MapUrl_VmsUserNameCache() on reset free entries 31-AUG-2000 MGD bugfix; MapOdsUrlToVms() escaped version semi-colon 24-JUN-2000 MGD add network-mask to conditionals, persistent run-time environment in EXEC rule (...), change 'HH' to 'VS' (virtual service) backward compatible 06-APR-2000 MGD set rules SSLCGI= and MAP= 04-MAR-2000 MGD use FaolToNet(), et.al. 02-JAN-2000 MGD config file opened via ODS module, detection of a path's on-disk-structure (ODS-2 or ODS-5), modify URL->VMS and VMS->URL mapping for extended syntax, avoid confusion; redirect indicators changed from '^' and '@' for local and remote, to '<' and '>' respectively, bugfix; trailing wildcard in set rule comparison 24-OCT-1999 MGD groan; ensure storage does not overflow!! (plus copious quantities of self-flagellation), SYSUAF-based user directory mapping via a "USER" rule, CGIprefix, [no]profile and [no]authonce SET rules, happy seventh wedding anniversary 12-SEP-1999 MGD virtual services modifications 10-MAY-1999 MGD conditional mapping on HTTP cookie and referer, increase the size of scratch storage, mapping endless-loop detection 16-JAN-1999 MGD allow for proxy service mappings by removing requirement for template and result paths to be absolute ("/...") paths (every time I have to deal with this module I groan) 10-JAN-1999 MGD bugfix; pass rules not returning mapped path 17-OCT-1998 MGD SET mapping rule, virtual services via "[[virtual-host:virtual-port]]", "qs:" query string conditional, invalid RMS file name/character substitution configurable 12-AUG-1998 MGD MapOdsVmsToUrl() now only optionally absorbs MFD 19-JUL-1998 MGD 'E'xec DECnet-based user scripts 10-MAR-1998 MGD allow for local redirects (using '^' detect character) 07-FEB-1998 MGD added "sc:" scheme/protocol conditional for SSL support 20-DEC-1997 MGD added DECnet support in _UrlToVms(), result paths can now begin with an '*' 25-OCT-1997 MGD added "as:", "fo:", and "hh:" conditionals, bugfix; MsgFor() required request pointer to find langauge 15-SEP-1997 MGD MsgFor() was not returning a leading-null message (does now), HTTP status code rules (e.g. "pass /no/* 403 forbidden"), removed two consecutive slashes inhibiting rule mapping 07-SEP-1997 MGD added "sn:" and "sp:" conditionals 09-AUG-1997 MGD v4.3, message database, mapping "conditionals", more cart-wheels, hand-stands and contortions (see 01-OCT-96) 05-JUN-1997 MGD v4.2, CGIplus "exec+" and "script+" rules 01-FEB-1997 MGD HTTPd version 4, major changes for form-based config 01-OCT-1996 MGD not proud of how I shoe-horned the reporting features in, good example of slop-down or object-disoriented programming, :^( will rework the whole thing one day, sigh! bugfix; requiring use of 'TheFirstRuleWillBeTheNextRule' 06-APR-1996 MGD modified conversion of non-VMS characters in MapOdsUrlToVms() 15-FEB-1995 MGD bugfix; redirect rule 01-DEC-1995 MGD v3.0 24-MAR-1995 MGD bugfix; end-of-string sometimes not detected when matching 20-DEC-1994 MGD revised for multi-threaded HTTP daemon 20-JUN-1994 MGD single-threaded daemon */ #endif /* COMMENTS_WITH_COMMENTS */ /*****************************************************************************/ #ifdef WASD_VMS_V7 #undef _VMS__V6__SOURCE #define _VMS__V6__SOURCE #undef __VMS_VER #undef __VMS_VER #undef __CRTL_VER #define __CRTL_VER 70000000 #endif /* standard C header files */ #include #include #include #include /* VMS related header files */ #include #include #include #include #include #include #include "wasd.h" #define WASD_MODULE "MAPURL" /* fundamental buffer size */ #ifdef __VAX #define MAP_BUFFER_SIZE 8192 #else #ifdef __ALPHA #define MAP_BUFFER_SIZE (8192 * 2) #else /* IA64 and whatever else may follow */ #define MAP_BUFFER_SIZE (8192 * 4) #endif #endif /**********/ /* macros */ /**********/ #define MAPURL_RMS_SUBSTITUTION_DEFAULT '$' #define WATCH_MODULE_DETAIL (WATCH_MODULE(WATCH_MOD_MAPURL) && \ WATCH_MODULE(WATCH_MOD__DETAIL)) /******************/ /* global storage */ /******************/ BOOL MapUrlExtensionMethod, MapUrlPathOds5; MAPPING_META MappingMeta; MAPPING_META *MappingMetaPtr; /********************/ /* external storage */ /********************/ extern BOOL AuthPromiscuous, AuthProtectRule, AuthPolicySysUafRelaxed, CliOdsExtendedDisabled, CliOdsExtendedEnabled, OdsExtended; extern int EfnWait, ServerPort, ServerHostNameLength; extern unsigned long SysPrvMask[]; extern char *FaoUrlEncodeTable[]; extern int ToLowerCase[], ToUpperCase[]; extern char ErrorSanityCheck[], ErrorWatchSysFao[], ServerHostName[], ServerHostPort[], SoftwareID[]; extern LIST_HEAD MapUrlUserNameCacheList; extern int MapUrlUserNameCacheEntries; extern CONFIG_STRUCT Config; extern HTTPD_GBLSEC *HttpdGblSecPtr; extern IPADDRESS TcpIpEmptyAddress; extern META_CONFIG *MetaGlobalMappingPtr; extern MSG_STRUCT Msgs; extern SYS_INFO SysInfo; extern WATCH_STRUCT Watch; /*****************************************************************************/ /* This overly-long function (sorry) is not AST reentrant, but when executed within the context of the HTTPd, is executed either without the possibility of AST interruption, or during AST processing and so provides atomic functionality. Pointers to any strings returned must be used immediately (before leaving AST context), or copied into storage maintained by the calling routine. Maps from URL format to VMS file specification, and REVERSE-MAPS from VMS file specification to URL format. Maps scripts. Always returns a pointer to char. An error message is detected by being returned as a pointer to a string beginning with a null-character! The message begins from character one. Call with 'PathPtr' pointing at a string containing the URL path and 'VmsPtr' pointing to the storage to contain the mapped VMS equivalent. Call with 'VmsPtr' pointing to a VMS file specification (dev:[dir]file.ext) and 'PathPtr' pointing to an empty string, used as storage to contain the REVERSE-MAPPED file specification. Call with 'PathPtr' pointing at a string containing the URL path, 'VmsPtr' pointing to storage to contain the mapped VMS equivalent, 'ScriptPtr' pointing to storage for the URL format script path and 'ScriptVmsPtr' pointing to storage to contain the VMS specification of the script procedure/image. The MapUrl_Map() just wraps MapUrl__Map() so that it's function can be WATCHed. See alter-egos defined in MapUrl.h */ char* MapUrl_Map ( char *PathPtr, int SizeOfPathPtr, char *VmsPtr, int SizeOfVmsPtr, char *ScriptPtr, int SizeOfScriptPtr, char *ScriptVmsPtr, int SizeOfScriptVmsPtr, char *RunTimePtr, int SizeOfRunTimePtr, int *PathOdsPtr, REQUEST_STRUCT *rqptr, REQUEST_PATHSET *PathSetPtr ) { BOOL VmsToPath; char *cptr, *sptr; char OdsNote [32]; /*********/ /* begin */ /*********/ if (!rqptr || !WATCHPNT(rqptr)) { cptr = MapUrl__Map (PathPtr, SizeOfPathPtr, VmsPtr, SizeOfVmsPtr, ScriptPtr, SizeOfScriptPtr, ScriptVmsPtr, SizeOfScriptVmsPtr, RunTimePtr, SizeOfRunTimePtr, PathOdsPtr, rqptr, PathSetPtr); if (rqptr) { rqptr->MetaConPass = 0; rqptr->MetaConMappedPtr = rqptr->MetaConScriptPtr = NULL; } return (cptr); } if (!WATCH_CATEGORY(WATCH_MAPPING)) { cptr = MapUrl__Map (PathPtr, SizeOfPathPtr, VmsPtr, SizeOfVmsPtr, ScriptPtr, SizeOfScriptPtr, ScriptVmsPtr, SizeOfScriptVmsPtr, RunTimePtr, SizeOfRunTimePtr, PathOdsPtr, rqptr, PathSetPtr); if (rqptr) { rqptr->MetaConPass = 0; rqptr->MetaConMappedPtr = rqptr->MetaConScriptPtr = NULL; } return (cptr); } #if WATCH_CAT VmsToPath = false; if (PathPtr && PathPtr[0]) WatchThis (WATCHITM(rqptr), WATCH_MAPPING, "PATH !AZ", PathPtr); else if (VmsPtr && VmsPtr[0]) { VmsToPath = true; WatchThis (WATCHITM(rqptr), WATCH_MAPPING, "VMS !AZ", VmsPtr); } cptr = MapUrl__Map (PathPtr, SizeOfPathPtr, VmsPtr, SizeOfVmsPtr, ScriptPtr, SizeOfScriptPtr, ScriptVmsPtr, SizeOfScriptVmsPtr, RunTimePtr, SizeOfRunTimePtr, PathOdsPtr, rqptr, PathSetPtr); if (VmsToPath) WatchThis (WATCHITM(rqptr), WATCH_MAPPING, "RESULT !AZ", cptr); else { if (!PathPtr) PathPtr = ""; if (!VmsPtr) VmsPtr = ""; if (!ScriptPtr) ScriptPtr = ""; if (!ScriptVmsPtr) ScriptVmsPtr = ""; if (!RunTimePtr) RunTimePtr = ""; WatchThis (WATCHITM(rqptr), WATCH_MAPPING, "RESULT"); if (!cptr[0] && cptr[1]) WatchDataFormatted ("Error: !AZ\n", cptr+1); else if (cptr[0] == '\1') WatchDataFormatted ("Redirect: !AZ\n", cptr+1); else { switch (PathOdsPtr ? *PathOdsPtr : rqptr->PathOds) { case MAPURL_PATH_ODS_2 : sptr = " (ODS-2)"; break; case MAPURL_PATH_ODS_5 : sptr = " (ODS-5)"; break; case MAPURL_PATH_ODS_ADS : sptr = " (ADS)"; break; case MAPURL_PATH_ODS_PWK : sptr = " (PWK)"; break; case MAPURL_PATH_ODS_SMB : sptr = " (SMB)"; break; case MAPURL_PATH_ODS_SRI : sptr = " (SRI)"; break; default : sptr = " (ods-2)"; } WatchDataFormatted ("\ Mapped: !AZ\n\ Translated: !AZ!AZ\n\ Script: !AZ\n\ Script-File: !AZ\n\ Run-Time: !AZ\n", cptr, VmsPtr, VmsPtr[0] ? sptr : "", ScriptPtr, ScriptVmsPtr, RunTimePtr); } } if (rqptr) { rqptr->MetaConPass = 0; rqptr->MetaConMappedPtr = rqptr->MetaConScriptPtr = NULL; } return (cptr); #endif /* WATCH_CAT */ } char* MapUrl__Map ( char *PathPtr, int SizeOfPathPtr, char *VmsPtr, int SizeOfVmsPtr, char *ScriptPtr, int SizeOfScriptPtr, char *ScriptVmsPtr, int SizeOfScriptVmsPtr, char *RunTimePtr, int SizeOfRunTimePtr, int *PathOdsPtr, REQUEST_STRUCT *rqptr, REQUEST_PATHSET *PathSetPtr ) { static char DerivedPathBuffer [MAP_BUFFER_SIZE+128], PathBuffer [MAP_BUFFER_SIZE+128], VmsBuffer [MAP_BUFFER_SIZE+128]; BOOL EvanescentZeroed, ExecFileType, LoadingRules, MapEllipsis, MapPathToVms, StatusCodeMapping, SubstituteForUserName; int idx, widx, status, MapRootLength, MetaConPass, MetaConRestartCount, PathOds, SetPathIgnore, TotalLength, WatchThisMatch, WatchThisOne, WildStringCount; unsigned short Length; char ch, RmsSubChar; char *cptr, *eptr, *pptr, *rptr, *sptr, *tptr, *uptr, *zptr, *MapRootPtr; char *WildString [REGEX_PMATCH_MAX]; char Scratch [MAP_BUFFER_SIZE+128], UserDefault [256], VmsUserMappedBuffer [256], WildBuffer [(MAP_BUFFER_SIZE*4)+128]; MAP_RULE_META *mrptr; MAP_SET_META *mrpsptr; METACON_LINE *mclptr; REQUEST_PATHSET EvanescentPathSet; REQUEST_PATHSET *rqpsptr; regex_t *pregptr; regmatch_t pmatch [REGEX_PMATCH_MAX]; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD_MAPURL)) WatchThis (WATCHITM(rqptr), WATCH_MOD_MAPURL, "MapUrl_Map() !UL !&Z !UL !&Z !UL !&Z !UL", SizeOfPathPtr, PathPtr, SizeOfVmsPtr, VmsPtr, SizeOfScriptPtr, ScriptPtr, SizeOfScriptVmsPtr); /* if just loading the rules then free any previous set */ if (LoadingRules = (!PathPtr && !VmsPtr && !ScriptPtr)) MetaConUnload (&MetaGlobalMappingPtr, &MapUrl_ConfigUnloadLineData); if (!MetaGlobalMappingPtr) { /*********************/ /* read mapping file */ /*********************/ MapUrl_ConfigLoad (&MetaGlobalMappingPtr); } /* if just (re)loading rules then return now */ if (LoadingRules) return ("\0\0"); /*****************************************/ /* map from the URL or VMS to VMS or URL */ /*****************************************/ if (!PathPtr) { SET2(PathBuffer,'\0\0'); PathPtr = PathBuffer + 1; SizeOfPathPtr = sizeof(PathBuffer); } if (!VmsPtr) { *(VmsPtr = VmsBuffer) = '\0'; SizeOfVmsPtr = sizeof(VmsBuffer); } /* making 'ScriptPtr' non-empty means "exec" and "script" are ignored */ if (!ScriptPtr) ScriptPtr = "?"; if (PathPtr[0]) { /* if the URL is not an empty string then force the conversion to VMS */ MapPathToVms = true; *VmsPtr = '\0'; MetaConPass = 1; } else { /* URL was an empty string, convert from VMS to URL */ MapPathToVms = false; /* generate a URL-style version of the VMS specification */ MapOdsVmsToUrl (PathPtr, VmsPtr, SizeOfPathPtr, true, rqptr->PathOds); MetaConPass = -1; } /***********************/ /* loop thru the rules */ /***********************/ if (!MetaGlobalMappingPtr) return (MsgFor(rqptr,MSG_MAPPING_DENIED_NO_RULES)-1); WatchThisOne = WatchThisMatch = 0; if (WATCHPNT(rqptr)) { if (WATCH_CATEGORY(WATCH_MAPPING)) WatchThisOne = WATCH_MAPPING; if (WATCH_CATEGORY(WATCH_MATCH)) WatchThisMatch = WATCH_MATCH; } MapRootLength = PathOds = 0; RmsSubChar = MAPURL_RMS_SUBSTITUTION_DEFAULT; EvanescentZeroed = MapEllipsis = SetPathIgnore = false; MapRootPtr = NULL; MetaConRestartCount = 0; if (rqptr) { rqptr->MetaConPass = MetaConPass; rqptr->MetaConRestartCount = MetaConRestartCount; rqptr->MetaConMappedPtr = rqptr->MetaConScriptPtr = NULL; } if (!PathSetPtr) { PathSetPtr = &EvanescentPathSet; memset (&EvanescentPathSet, 0, sizeof(EvanescentPathSet)); EvanescentZeroed = true; } rqpsptr = PathSetPtr; MetaConParseReset (MetaGlobalMappingPtr, true); for (;;) { mclptr = MetaGlobalMappingPtr->ParsePtr = MetaGlobalMappingPtr->ParseNextPtr; if (WATCH_MODULE_DETAIL) WatchDataFormatted ("!&X !UL !UL !UL !UL !&X !&Z\n", mclptr, mclptr->Size, mclptr->Token, mclptr->Number, mclptr->Length, mclptr->LineDataPtr, mclptr->TextPtr); /* if terminating empty "line" */ if (!mclptr->Size) break; if (mclptr->Token == METACON_TOKEN_TEXT) { /* get required data, adjust the parse context to the next "line" */ cptr = mclptr->TextPtr; mrptr = mclptr->LineDataPtr; MetaGlobalMappingPtr->ParseNextPtr = (METACON_LINE*)((char*)mclptr + mclptr->Size); } else if (mclptr->Token != METACON_TOKEN_DIRECTORY) { /* not a simple text line, have meta-config parse this one for us */ cptr = MetaConParse (rqptr, MetaGlobalMappingPtr, &mclptr, WatchThisOne); /* if the end of rules */ if (!cptr) break; /* if error string */ if (!*cptr && *(cptr+1)) return (cptr); /* if inline rule and expression was false */ if (SAME4 (cptr, '\0\0\0\1')) continue; mrptr = mclptr->LineDataPtr; } if (mclptr->Token == METACON_TOKEN_DIRECTORY) { /* get required data, adjust the parse context to the next "line" */ cptr = mclptr->TextPtr + sizeof("[ConfigDirectory]"); while (*cptr && ISLWS(*cptr)) cptr++; zptr = (sptr = rqptr->ConfigDirectory) + sizeof(rqptr->ConfigDirectory)-1; while (*cptr && sptr < zptr) *sptr++ = *cptr++; *sptr = '\0'; rqptr->ConfigDirectoryLength = sptr - rqptr->ConfigDirectory; MetaGlobalMappingPtr->ParseNextPtr = (METACON_LINE*)((char*)mclptr + mclptr->Size); continue; } /* there was a problem in initializing the rule */ if (!mrptr) { if (WatchThisOne) WatchDataFormatted ("?!AZ\n", cptr); continue; } if (WATCH_MODULE_DETAIL) WatchDataFormatted ("!&X !UL !&Z !&Z !&Z\n", mrptr, mrptr->RuleType, mrptr->TemplatePtr, mrptr->ResultPtr, mrptr->ConditionalPtr); /* hmmm, endless loop!! */ if (MetaConPass > 2) return (MsgFor(rqptr,MSG_MAPPING_DENIED_INTERNAL)-1); if (rqptr->rqPathSet.MapUri) { /* substitute the request URI (raw path plus query) for rewriting */ rqptr->rqPathSet.MapUri = false; zptr = (pptr = PathPtr = PathBuffer+1) + sizeof(PathBuffer)-1; for (cptr = rqptr->rqHeader.RequestUriPtr; *cptr && pptr < zptr; *pptr++ = *cptr++); if (pptr >= zptr) return (MsgFor(rqptr,MSG_MAPPING_DENIED_INTERNAL)-1); *pptr = '\0'; } /* if 'ScriptPtr' is not to be used then ignore "exec" and "script" */ if (ScriptPtr[0] && (mrptr->RuleType == MAPURL_RULE_EXEC || mrptr->RuleType == MAPURL_RULE_SCRIPT || mrptr->RuleType == MAPURL_RULE_UXEC)) { if (WatchThisOne) MapUrl_WatchRule (rqptr, mrptr, PathPtr, PathOds, MAPURL_REPORT_MATCH_NOT, SetPathIgnore); continue; } if (cptr = MapUrl_GuaranteeAccess (rqptr, PathPtr)) return (cptr); /*****************************************************************/ /* compare the URL with the template/result in the mapping entry */ /*****************************************************************/ if (mrptr->RuleType == MAPURL_RULE_SET || mrptr->RuleType == MAPURL_RULE_PROTECT) { /*********************/ /* SET/PROTECT rules */ /*********************/ /* cheap check obvious non-/match before using expensive functions */ tptr = mrptr->TemplatePtr; pregptr = &mrptr->RegexPregTemplate; pptr = PathPtr; if (Config.cfMisc.RegexSyntax && *tptr == REGEX_CHAR) tptr++; /* while matching vanilla characters */ while ((isalnum(*tptr) || *tptr == '/' || *tptr == '-' || *tptr == '_') && TOLO(*pptr) == TOLO(*tptr)) { pptr++; tptr++; } /* if non-matching vanilla character */ if (isalnum(*tptr) || *tptr == '/' || *tptr == '-' || *tptr == '_') { if (WatchThisMatch) WatchThis (WATCHITM(rqptr), WATCH_MATCH, "NO !&Z", tptr); if (WatchThisOne) MapUrl_WatchRule (rqptr, mrptr, PathPtr, PathOds, MAPURL_REPORT_MATCH_NOT, SetPathIgnore); continue; } /* if a trailing wildcard then it's a match already! */ if (SAME2(tptr,'*\0')) { if (WatchThisMatch) WatchThis (WATCHITM(rqptr), WATCH_MATCH, "YES"); } else { /* expensive comparison of path and template */ if (!StringMatchAndRegex (rqptr, PathPtr, mrptr->TemplatePtr, SMATCH_STRING_REGEX, pregptr, NULL)) { /* not matched then straight to next rule */ if (!WatchThisOne) continue; MapUrl_WatchRule (rqptr, mrptr, PathPtr, PathOds, MAPURL_REPORT_MATCH_NOT, SetPathIgnore); continue; } } if (WATCH_MODULE(WATCH_MOD_MAPURL)) WatchThis (WATCHITM(rqptr), WATCH_MOD_MAPURL, "MATCHED"); } else { /***************/ /* other rules */ /***************/ /* when mapping VMS to URL then ignore all BUT "pass" & "set" rules */ if (!MapPathToVms && mrptr->RuleType != MAPURL_RULE_PASS) continue; /* if reverse-mapping VMS to URL use the result if available */ if (!MapPathToVms && mrptr->ResultPtr[0]) { if (MapRootPtr) { /* if a mapping root is set then eliminate this first */ cptr = MapRootPtr; pptr = PathPtr; while (*cptr && *pptr && TOLO(*cptr) == TOLO(*pptr)) { cptr++; pptr++; } if (*cptr || !*pptr) { /* the path and root do not match */ if (!WatchThisMatch) continue; WatchThis (WATCHITM(rqptr), WATCH_MATCH, "NO (root) !&Z", cptr); continue; } } cptr = tptr = mrptr->ResultPtr; pregptr = NULL; } else { cptr = tptr = mrptr->TemplatePtr; pregptr = &mrptr->RegexPregTemplate; } /* cheap check obvious non-/match before using expensive functions */ if (Config.cfMisc.RegexSyntax && *tptr == REGEX_CHAR) tptr++; pptr = PathPtr; /* while matching vanilla characters */ while ((isalnum(*tptr) || *tptr == '/' || *tptr == '-' || *tptr == '_') && TOLO(*pptr) == TOLO(*tptr)) { pptr++; tptr++; } /* if non-matching vanilla character */ if (isalnum(*tptr) || *tptr == '/' || *tptr == '-' || *tptr == '_') { if (WatchThisMatch) WatchThis (WATCHITM(rqptr), WATCH_MATCH, "NO !&Z", tptr); if (WatchThisOne) MapUrl_WatchRule (rqptr, mrptr, PathPtr, PathOds, MAPURL_REPORT_MATCH_NOT, SetPathIgnore); continue; } /* if a trailing wildcard then it's a match already! */ if (SAME2(tptr,'*\0')) { if (WatchThisMatch) WatchThis (WATCHITM(rqptr), WATCH_MATCH, "YES"); /* simulate the setting of the 'pmatch' data */ pmatch[0].rm_so = 0; pmatch[1].rm_so = pptr - PathPtr; while (*pptr) pptr++; pmatch[0].rm_eo = pmatch[1].rm_eo = pptr - PathPtr; for (idx = 2; idx < REGEX_PMATCH_MAX; idx++) pmatch[idx].rm_so = pmatch[idx].rm_eo = -1; } else { /* expensive comparison of path and template */ if (!StringMatchAndRegex (rqptr, PathPtr, cptr, SMATCH_STRING_REGEX, pregptr, &pmatch)) { /* not matched then straight to next rule */ if (!WatchThisOne) continue; MapUrl_WatchRule (rqptr, mrptr, PathPtr, PathOds, MAPURL_REPORT_MATCH_NOT, SetPathIgnore); continue; } } /************/ /* matched! */ /************/ /* copy using 'regmatch_t' data, strings into 'WildBuffer' */ zptr = (sptr = WildBuffer) + sizeof(WildBuffer); for (idx = WildStringCount = 0; idx < REGEX_PMATCH_MAX; idx++) { WildString[idx] = ""; if (pmatch[idx].rm_so == -1 || pmatch[idx].rm_eo == -1) continue; WildString[WildStringCount++] = sptr; pptr = PathPtr + pmatch[idx].rm_so; cptr = PathPtr + pmatch[idx].rm_eo; while (pptr < cptr && sptr < zptr) *sptr++ = *pptr++; if (sptr >= zptr) break; *sptr++ = '\0'; } if (sptr >= zptr) return (MsgFor(rqptr,MSG_MAPPING_DENIED_INTERNAL)-1); /* the actual number of wildcard/group matched strings */ if (WildStringCount) WildStringCount--; if (WATCH_MODULE(WATCH_MOD_MAPURL)) { WatchThis (WATCHITM(rqptr), WATCH_MOD_MAPURL, "MATCHED"); StringWatchPmatch (PathPtr, &pmatch); WatchThis (WATCHITM(rqptr), WATCH_MOD_MAPURL, "WILDSTRING"); for (idx = 1; idx <= WildStringCount; idx++) WatchDataFormatted ("!UL. !&Z\n", idx, WildString[idx]); } } if (mrptr->ConditionalPtr[0]) { /***************/ /* conditional */ /***************/ /* when not mapping using a request then ignore conditionals */ if (rqptr) { /* if condition not met then continue */ if (!MapConString ((REQUEST_STRUCT*)rqptr, mrptr, rqpsptr)) { if (WatchThisOne) MapUrl_WatchRule (rqptr, mrptr, PathPtr, PathOds, MAPURL_REPORT_MATCH_RULE, SetPathIgnore); continue; } /* report rule and conditional matched */ if (WatchThisOne) MapUrl_WatchRule (rqptr, mrptr, PathPtr, PathOds, MAPURL_REPORT_MATCH_RULECOND, SetPathIgnore); } if (WATCH_MODULE_DETAIL) WatchThis (WATCHITM(rqptr), WATCH_MOD_MAPURL, "CONDITIONAL MATCHED"); } else { /* report rule, there was no conditional */ if (WatchThisOne) MapUrl_WatchRule (rqptr, mrptr, PathPtr, PathOds, MAPURL_REPORT_MATCH_RULENOCOND, SetPathIgnore); } if (mrptr->PathSet) { /****************/ /* path SETings */ /****************/ mrpsptr = &mrptr->mpPathSet; if (mrpsptr->MapSetIgnore) { /* takes effect immediately */ SetPathIgnore = true; continue; } else if (mrpsptr->MapSetNoIgnore) SetPathIgnore = false; /* ignoring path SETings (except for the above of course ;^) */ if (SetPathIgnore) continue; /***********************/ /* being ignored? - no */ /***********************/ if (mrpsptr->MapRestart) { MetaConRestartCount++; if (WatchThisOne) WatchThis (WATCHITM(rqptr), WATCH_MAPPING, "RESTART !UL", MetaConRestartCount); if (MetaConRestartCount > MAPURL_RESTART_MAX) return (MsgFor(rqptr,MSG_MAPPING_DENIED_INTERNAL)-1); if (rqptr) rqptr->MetaConRestartCount = MetaConRestartCount; MetaConParseReset (MetaGlobalMappingPtr, true); continue; } /* some SETings must be applied in this function! */ if (!(rqptr->rqCgi.AgentScript || rqptr->rqCgi.CalloutInProgress)) { if (mrpsptr->MapSetRequest) rqpsptr = &PathSetPtr; else if (mrpsptr->MapSetNoRequest) { rqpsptr = &EvanescentPathSet; if (!EvanescentZeroed) { memset (&EvanescentPathSet, 0, sizeof(EvanescentPathSet)); EvanescentZeroed = true; } } } if (mrpsptr->NoMapEllipsis) rqpsptr->MapEllipsis = MapEllipsis = false; else if (mrpsptr->MapEllipsis) rqpsptr->MapEllipsis = MapEllipsis = true; if (mrpsptr->MapRootPtr) { /* empty string resets */ if (mrpsptr->MapRootLength) { MapRootPtr = mrpsptr->MapRootPtr; MapRootLength = mrpsptr->MapRootLength; rqpsptr->MapRootPtr = VmGetHeap (rqptr, mrpsptr->MapRootLength+1); memcpy (rqpsptr->MapRootPtr, mrpsptr->MapRootPtr, mrpsptr->MapRootLength+1); } else { MapRootPtr = rqpsptr->MapRootPtr = NULL; MapRootLength = 0; } } if (mrpsptr->RmsSubChar) RmsSubChar = mrpsptr->RmsSubChar; if (rqptr->rqCgi.AgentScript) { /* bypass evanecsent structure by SETing directly into request! */ if (MetaConPass == 1 && mrpsptr->ScriptAgentAsPtr) { /* empty string resets */ if (mrpsptr->ScriptAgentAsLength) { rqptr->rqPathSet.ScriptAgentAsPtr = VmGetHeap (rqptr, mrpsptr->ScriptAgentAsLength+1); memcpy (rqptr->rqPathSet.ScriptAgentAsPtr, mrpsptr->ScriptAgentAsPtr, mrpsptr->ScriptAgentAsLength+1); } else rqptr->rqPathSet.ScriptAgentAsPtr = NULL; } } if (MetaConPass == 1 && mrpsptr->ScriptAsPtr) { /* empty string resets */ if (mrpsptr->ScriptAsLength) { rqpsptr->ScriptAsPtr = VmGetHeap (rqptr, mrpsptr->ScriptAsLength+1); memcpy (rqpsptr->ScriptAsPtr, mrpsptr->ScriptAsPtr, mrpsptr->ScriptAsLength+1); } else rqpsptr->ScriptAsPtr = NULL; } /* others can be applied in an independent function */ MapUrl_PathSet (rqptr, rqpsptr, mrpsptr); /* when mapping VMS to URL then ignore all BUT "pass" rules */ if (!MapPathToVms && mrptr->RuleType != MAPURL_RULE_PASS) continue; /* must be immediately detected and actioned by the calling routine */ if (rqpsptr->Http2ToHttp11) return ("\0\0"); if (rqpsptr->ClientAddress && rqpsptr == &rqptr->rqPathSet) { if (rqpsptr->ClientAddress == MAPURL_CLIENT_RESET) MapUrl_ResetClientAddress (rqptr); else if (cptr = MapUrl_SetClientAddress (rqptr)) return (cptr); } } /***************/ /* end SETings */ /***************/ if (rqpsptr->PathOds) { /* path file-system has been set, perhaps to turn off ODS-5! */ if (rqpsptr->PathOds == MAPURL_PATH_ODS_0) PathOds = rqptr->PathOds = rqpsptr->PathOds = 0; else PathOds = rqptr->PathOds = rqpsptr->PathOds; } else { /* set from the $GETDVI volume file-system */ PathOds = rqptr->PathOds = mrptr->ResultPathOds; } if (PathOdsPtr) *PathOdsPtr = PathOds; if (MapPathToVms) { /***************************/ /* mapping from URL to VMS */ /***************************/ switch (mrptr->RuleType) { case MAPURL_RULE_EXEC : case MAPURL_RULE_UXEC : /*******************/ /* EXEC/UXEC rule */ /*******************/ if (!WildStringCount) return (MsgFor(rqptr,MSG_MAPPING_DENIED_INTERNAL)-1); /* first get the script component from the request */ tptr = mrptr->TemplatePtr; zptr = (sptr = ScriptPtr) + SizeOfScriptPtr; if (mrptr->RuleType == MAPURL_RULE_UXEC) { if (!rqpsptr->ScriptAsPtr || rqpsptr->ScriptAsPtr[0] != '~') { /* hmmm, not enabled with a mapping rule!! */ return (MsgFor(rqptr,MSG_GENERAL_DISABLED)-1); } /* first insert the /~username component */ while (*tptr && *tptr != '*' && sptr < zptr) *sptr++ = *tptr++; if (*tptr) tptr++; cptr = WildString[1]; while (*cptr && sptr < zptr) *sptr++ = *cptr++; cptr = WildString[2]; } else if (SAME2(tptr,'/~')) { /* mapping a DECnet username based script */ while (*tptr && *tptr != '*' && sptr < zptr) *sptr++ = *tptr++; while (*tptr == '*') tptr++; cptr = WildString[1]; while (*cptr && sptr < zptr) *sptr++ = *cptr++; cptr = WildString[2]; } else { /* mapping a vanilla exec rule */ cptr = WildString[1]; } while (*tptr && *tptr != '*' && sptr < zptr) *sptr++ = *tptr++; while (*tptr && SAME2(tptr,'**')) tptr++; if (SAME2(tptr,'*.')) { /* EXECing a file type here */ ExecFileType = true; while (*cptr && sptr < zptr) *sptr++ = *cptr++; /* now get the script file type (e.g. ".cgi") */ tptr++; while (*tptr && *tptr != '*' && sptr < zptr) *sptr++ = *tptr++; } else { /* EXECing a directory here */ ExecFileType = false; while (*cptr && *cptr != '/' && sptr < zptr) *sptr++ = *cptr++; } if (sptr >= zptr) return (MsgFor(rqptr,MSG_MAPPING_DENIED_INTERNAL)-1); *sptr = '\0'; if (mrptr->RuleType == MAPURL_RULE_UXEC) { /* "append" the username to the circumflex */ rqpsptr->ScriptAsPtr = sptr = VmGetHeap (rqptr, strlen(WildString[1])+2); *sptr++ = '~'; for (cptr = WildString[1]; *cptr; *sptr++ = TOUP(*cptr++)); *sptr = '\0'; } /* now get what it's mapped into (the more complex bit ;^) */ rptr = mrptr->ResultPtr; if (*rptr == '(') { /* run-time, e.g. exec /plbin/@ (ht_exe:pl.exe)/plbin/@ */ rptr++; zptr = (sptr = RunTimePtr) + SizeOfRunTimePtr; while (*rptr && *rptr != ')' && sptr < zptr) *sptr++ = *rptr++; if (sptr >= zptr) return (MsgFor(rqptr,MSG_MAPPING_DENIED_INTERNAL)-1); *sptr = '\0'; if (*rptr) rptr++; } zptr = (sptr = Scratch) + sizeof(Scratch); if (mrptr->RuleType == MAPURL_RULE_UXEC) { /* begin with the mapped user instead of the /~username */ if (rqpsptr->PathOds) uptr = MapUserName (rqptr, WildString[1], NULL); else { uptr = MapUserName (rqptr, WildString[1], &PathOds); rqptr->PathOds = PathOds; if (PathOdsPtr) *PathOdsPtr = PathOds; } if (!uptr[0]) return (uptr); /* copy in the now-mapped username */ while (*uptr && sptr < zptr) *sptr++ = *uptr++; /* skip over the equivalent in the result (i.e. "/~*") */ while (*rptr && *rptr != '*') rptr++; if (*rptr) rptr++; /* skip the first wildcarded string (username) */ cptr = WildString[widx=2]; } else if (SAME2(mrptr->TemplatePtr,'/~')) { /* e.g. exec /~@/cgi-bin/@ /0""::/web/user/@/cgi-bin/@ i.e. the user part must be prepended to the script part. */ while (*rptr && *rptr != '*' && sptr < zptr) { if (*rptr != '\"' || !SAME4(rptr,'\"\"::')) { *sptr++ = *rptr++; continue; } /* mapping a DECnet username based script */ *sptr++ = *rptr++; cptr = WildString[1]; while (*cptr && sptr < zptr) *sptr++ = *cptr++; } while (*rptr == '*') rptr++; cptr = WildString[1]; while (*cptr && sptr < zptr) *sptr++ = *cptr++; cptr = WildString[widx=2]; } else { /* vanilla script exec */ if (MapRootPtr) { if (WATCHING (rqptr, WATCH_MAPPING)) WatchThis (WATCHITM(rqptr), WATCH_MAPPING, "ROOT !AZ", MapRootPtr); for (cptr = MapRootPtr; *cptr && sptr < zptr; *sptr++ = *cptr++); } cptr = WildString[widx=1]; } /* now the leading script-location part of the result */ while (*rptr && *rptr != '*' && sptr < zptr) *sptr++ = *rptr++; while (*rptr == '*') rptr++; if (WATCH_MODULE_DETAIL) WatchThis (WATCHITM(rqptr), WATCH_MOD_MAPURL, "!&Z", cptr); if (ExecFileType) { /* EXECing a file type here, script name (full buffer) */ while (*cptr && sptr < zptr) *sptr++ = *cptr++; cptr = WildString[++widx]; /* now get the script file type (e.g. ".cgi") */ while (*rptr && *rptr != '*' && sptr < zptr) *sptr++ = *rptr++; } else { /* EXECing a directory here, script name */ while (*cptr && *cptr != '/' && sptr < zptr) *sptr++ = *cptr++; } if (sptr >= zptr) return (MsgFor(rqptr,MSG_MAPPING_DENIED_INTERNAL)-1); *sptr = '\0'; /* generate the VMS script name */ MapOdsUrlToVms (Scratch, ScriptVmsPtr, SizeOfScriptVmsPtr, RmsSubChar, MapEllipsis, PathOds); /* indicate CGIplus script via leading '+' instead of '/' */ if (mrptr->IsCgiPlusScript && (!RunTimePtr || !RunTimePtr[0])) ScriptPtr[0] = '+'; /* get all including and after the first slash as the new path */ zptr = (sptr = DerivedPathBuffer) + sizeof(DerivedPathBuffer); rqptr->MetaConMappedPtr = sptr; /* continue copying from the wildcard string */ while (*cptr && sptr < zptr) *sptr++ = *cptr++; if (sptr >= zptr) return (MsgFor(rqptr,MSG_MAPPING_DENIED_INTERNAL)-1); *sptr++ = '\0'; TotalLength = sptr - DerivedPathBuffer; if (WATCH_MODULE_DETAIL) WatchThis (WATCHITM(rqptr), WATCH_MOD_MAPURL, "E/UXEC !&Z !&Z !&Z", ScriptPtr, ScriptVmsPtr, DerivedPathBuffer); if (!rqpsptr->MapEmpty && !DerivedPathBuffer[0]) return ("\0\0"); if (rqpsptr->MapOnce) { /* convert the URL-style to a VMS-style specification */ MapOdsUrlToVms (DerivedPathBuffer, VmsPtr, SizeOfVmsPtr, RmsSubChar, MapEllipsis, PathOds); if (WATCH_MODULE_DETAIL) WatchThis (WATCHITM(rqptr), WATCH_MOD_MAPURL, "E/UXEC !&Z !&Z", DerivedPathBuffer, VmsPtr); return (DerivedPathBuffer); } /* restarting at first rule map the path derived from the script */ MetaConPass++; if (rqptr) { rqptr->MetaConPass = MetaConPass; rqptr->MetaConScriptPtr = ScriptPtr; } *VmsPtr = '\0'; PathPtr = DerivedPathBuffer; RmsSubChar = MAPURL_RMS_SUBSTITUTION_DEFAULT; MapEllipsis = rqpsptr->MapEllipsis = false; MetaConParseReset (MetaGlobalMappingPtr, true); continue; case MAPURL_RULE_FAIL : /*************/ /* FAIL rule */ /*************/ if (WATCH_MODULE_DETAIL) WatchThis (WATCHITM(rqptr), WATCH_MOD_MAPURL, "FAIL !&Z", PathPtr); return (MsgFor(rqptr,MSG_MAPPING_DENIED_RULE)-1); case MAPURL_RULE_MAP : /************/ /* MAP rule */ /************/ /* place this in a buffer so not to overwrite original path */ zptr = (pptr = PathPtr = PathBuffer+1) + sizeof(PathBuffer)-1; rqptr->MetaConMappedPtr = pptr; widx = 1; /* scan through the result string */ rptr = mrptr->ResultPtr; while (*rptr) { while (*rptr && *rptr != '*' && pptr < zptr) *pptr++ = *rptr++; if (!*rptr || pptr >= zptr) break; /* a wildcard asterisk, substitute from original path */ while (*rptr == '*') rptr++; if (*rptr == '\'') { /* specific wildcard component, e.g. "*'1" */ rptr++; if (isdigit(*rptr)) { idx = *rptr++ - '0'; cptr = WildString[idx]; } else cptr = ""; } else if (widx < REGEX_PMATCH_MAX) cptr = WildString[widx++]; else cptr = ""; while (*cptr && pptr < zptr) *pptr++ = *cptr++; } if (pptr >= zptr) return (MsgFor(rqptr,MSG_MAPPING_DENIED_INTERNAL)-1); *pptr = '\0'; /* continue with the substituted URL mapping */ if (WATCH_MODULE_DETAIL) WatchThis (WATCHITM(rqptr), WATCH_MOD_MAPURL, "MAP !&Z", PathPtr); continue; case MAPURL_RULE_PASS : case MAPURL_RULE_REDIRECT : case MAPURL_RULE_USER : /****************************/ /* PASS/REDIRECT/USER rules */ /****************************/ cptr = WildString[widx=1]; rptr = mrptr->ResultPtr; zptr = (pptr = PathBuffer+1) + sizeof(PathBuffer)-1; /* if there is no result to map just pass back the original path */ if (!*rptr) { if (mrptr->RuleType == MAPURL_RULE_PASS && MapRootPtr) { if (WATCHING (rqptr, WATCH_MAPPING)) WatchThis (WATCHITM(rqptr), WATCH_MAPPING, "ROOT !AZ", MapRootPtr); for (cptr = MapRootPtr; *cptr && pptr < zptr; *pptr++ = *cptr++); for (cptr = PathPtr; *cptr && pptr < zptr; *pptr++ = *cptr++); if (pptr >= zptr) return (MsgFor(rqptr,MSG_MAPPING_DENIED_INTERNAL)-1); *pptr = '\0'; pptr = PathBuffer; } else pptr = PathPtr; if (*pptr != '/') { /* doesn't look like file-system, don't bother translating */ return (PathPtr); } /* convert the URL-style to a VMS-style specification */ MapOdsUrlToVms (pptr, VmsPtr, SizeOfVmsPtr, RmsSubChar, MapEllipsis, PathOds); if (WATCH_MODULE_DETAIL) WatchThis (WATCHITM(rqptr), WATCH_MOD_MAPURL, "PASS !&Z !&Z", PathPtr, VmsPtr); return (PathPtr); } /* if redirect rule leave room for the redirection indicator */ if (mrptr->RuleType == MAPURL_RULE_REDIRECT) pptr++; if (mrptr->RuleType == MAPURL_RULE_USER) { /* begin with the mapped user instead of the /~username */ if (rqpsptr->PathOds) uptr = MapUserName (rqptr, WildString[1], NULL); else { uptr = MapUserName (rqptr, WildString[1], &PathOds); rqptr->PathOds = PathOds; if (PathOdsPtr) *PathOdsPtr = PathOds; } if (!uptr[0]) return (uptr); /* copy in the-now mapped username */ while (*uptr && pptr < zptr) *pptr++ = *uptr++; /* skip over the equivalent in the result (i.e. "/~*") */ while (*rptr && *rptr != '*') rptr++; if (*rptr) rptr++; /* skip first wildcard string (username) */ cptr = WildString[widx=2]; } if (mrptr->RuleType == MAPURL_RULE_PASS || mrptr->RuleType == MAPURL_RULE_REDIRECT) { if (!WildStringCount) { if (cptr = SysTrnLnm (mrptr->ResultPtr)) { /****************************/ /* use logical name content */ /****************************/ if (WATCHING (rqptr, WATCH_MAPPING)) WatchThis (WATCHITM(rqptr), WATCH_MAPPING, "TRLNM !AZ \"!AZ\"", mrptr->ResultPtr, cptr); if (mrptr->RuleType == MAPURL_RULE_PASS) { zptr = (sptr = VmsPtr) + SizeOfVmsPtr; while (*cptr && sptr < zptr) *sptr++ = *cptr++; if (sptr >= zptr) return (MsgFor(rqptr,MSG_MAPPING_DENIED_INTERNAL)-1); *sptr = '\0'; zptr = (sptr = PathBuffer+1) + sizeof(PathBuffer)-1; cptr = mrptr->ResultPtr; } else { zptr = (sptr = PathBuffer+1) + sizeof(PathBuffer)-1; /* the redirection indicator */ *sptr++ = '\1'; } while (*cptr && sptr < zptr) *sptr++ = *cptr++; if (sptr >= zptr) return (MsgFor(rqptr,MSG_MAPPING_DENIED_INTERNAL)-1); *sptr = '\0'; return (PathBuffer+1); } } } if (mrptr->RuleType == MAPURL_RULE_PASS) { /* scan through the result string */ if (rptr[0] == '\"' || rptr[0] == '\'') if (isdigit(rptr[1]) && isdigit(rptr[2]) && isdigit(rptr[3]) && (!rptr[4] || rptr[4] == ' ')) StatusCodeMapping = true; else StatusCodeMapping = false; else if (isdigit(rptr[0]) && isdigit(rptr[1]) && isdigit(rptr[2]) && (!rptr[3] || rptr[3] == ' ')) StatusCodeMapping = true; else StatusCodeMapping = false; if (StatusCodeMapping) while (*rptr && pptr < zptr) *pptr++ = *rptr++; } else StatusCodeMapping = false; if (!StatusCodeMapping) { if (mrptr->RuleType == MAPURL_RULE_PASS && MapRootPtr) { if (WATCHING (rqptr, WATCH_MAPPING)) WatchThis (WATCHITM(rqptr), WATCH_MAPPING, "ROOT !AZ", MapRootPtr); for (cptr = MapRootPtr; *cptr && pptr < zptr; *pptr++ = *cptr++); } /* map wildcard asterisks */ while (*rptr) { while (*rptr && *rptr != '*' && pptr < zptr) *pptr++ = *rptr++; if (!*rptr) break; /* wildcard asterisk, substitute from the wildcard buffer */ while (*rptr == '*') rptr++; if (*rptr == '\'') { /* specific wildcard component, e.g. "*'1" */ rptr++; if (isdigit(*rptr)) { idx = *rptr++ - '0'; cptr = WildString[idx]; } else cptr = ""; } else if (widx < REGEX_PMATCH_MAX) cptr = WildString[widx++]; else cptr = ""; if (mrptr->RuleType == MAPURL_RULE_REDIRECT) { /* URL-encode wildcard portions from the path */ while (*cptr && pptr < zptr) { for (eptr = FaoUrlEncodeTable[*(unsigned char*)cptr]; *eptr && pptr < zptr; *pptr++ = *eptr++); cptr++; } } else while (*cptr && pptr < zptr) *pptr++ = *cptr++; if (pptr >= zptr) break; } } if (pptr >= zptr) return (MsgFor(rqptr,MSG_MAPPING_DENIED_INTERNAL)-1); *pptr = '\0'; if (mrptr->RuleType == MAPURL_RULE_PASS || mrptr->RuleType == MAPURL_RULE_USER) { /* if status code mapping return leading null char */ if (StatusCodeMapping) { PathBuffer[0] = '\0'; return (PathBuffer); } if (PathBuffer[1] != '/') { /* doesn't look like file-system, don't bother translating */ return (PathBuffer+1); } /* convert the URL-style to a VMS-style specification */ MapOdsUrlToVms (PathBuffer+1, VmsPtr, SizeOfVmsPtr, RmsSubChar, MapEllipsis, PathOds); if (WATCH_MODULE_DETAIL) WatchThis (WATCHITM(rqptr), WATCH_MOD_MAPURL, "PASS !&Z !&Z", PathPtr, VmsPtr); return (PathBuffer+1); } else { if (WATCH_MODULE_DETAIL) WatchThis (WATCHITM(rqptr), WATCH_MOD_MAPURL, "REDIRECT !&Z !&Z", PathPtr, VmsPtr); /* indicate it's a redirect */ PathBuffer[1] = '\1'; return (PathBuffer+1); } case MAPURL_RULE_SCRIPT : /***************/ /* SCRIPT rule */ /***************/ tptr = mrptr->TemplatePtr; zptr = (pptr = ScriptPtr) + SizeOfScriptPtr; while (*tptr && *tptr != '*' && pptr < zptr) *pptr++ = *tptr++; if (pptr > ScriptPtr && pptr[-1] == '/') pptr--; if (pptr >= zptr) return (MsgFor(rqptr,MSG_MAPPING_DENIED_INTERNAL)-1); *pptr = '\0'; rptr = mrptr->ResultPtr; if (*rptr == '(') { /* run-time, e.g. exec /plbin/@ (ht_exe:pl.exe)/plbin/@ */ rptr++; zptr = (sptr = RunTimePtr) + SizeOfRunTimePtr; while (*rptr && *rptr != ')' && sptr < zptr) *sptr++ = *rptr++; if (sptr >= zptr) return (MsgFor(rqptr,MSG_MAPPING_DENIED_INTERNAL)-1); *sptr = '\0'; if (*rptr) rptr++; } zptr = (sptr = Scratch) + sizeof(Scratch); if (MapRootPtr) { if (WATCHING (rqptr, WATCH_MAPPING)) WatchThis (WATCHITM(rqptr), WATCH_MAPPING, "ROOT !AZ", MapRootPtr); for (cptr = MapRootPtr; *cptr && sptr < zptr; *sptr++ = *cptr++); } while (*rptr && *rptr != '*' && !SAME2(rptr,'/*') && sptr < zptr) *sptr++ = *rptr++; if (sptr >= zptr) return (MsgFor(rqptr,MSG_MAPPING_DENIED_INTERNAL)-1); *sptr = '\0'; /* convert the URL-format script to VMS specification */ MapOdsUrlToVms (Scratch, ScriptVmsPtr, SizeOfScriptVmsPtr, RmsSubChar, MapEllipsis, PathOds); /* indicate CGIplus script via leading '+' instead of '/' */ if (mrptr->IsCgiPlusScript && (!RunTimePtr || !RunTimePtr[0])) ScriptPtr[0] = '+'; /* get wildcard matched second section of path as new path */ zptr = (sptr = DerivedPathBuffer) + sizeof(DerivedPathBuffer); rqptr->MetaConMappedPtr = sptr; if (rqpsptr->MapOnce && MapRootPtr) { if (WATCHING (rqptr, WATCH_MAPPING)) WatchThis (WATCHITM(rqptr), WATCH_MAPPING, "ROOT !AZ", MapRootPtr); for (cptr = MapRootPtr; *cptr && sptr < zptr; *sptr++ = *cptr++); } while (*rptr && *rptr != '*' && sptr < zptr) *sptr++ = *rptr++; cptr = WildString[1]; while (*cptr && sptr < zptr) *sptr++ = *cptr++; if (sptr < zptr) *sptr++ = '\0'; if (sptr >= zptr) return (MsgFor(rqptr,MSG_MAPPING_DENIED_INTERNAL)-1); TotalLength = sptr - DerivedPathBuffer; if (WATCH_MODULE_DETAIL) WatchThis (WATCHITM(rqptr), WATCH_MOD_MAPURL, "SCRIPT !&Z !&Z !&Z", ScriptPtr, ScriptVmsPtr, DerivedPathBuffer); if (!rqpsptr->MapEmpty && !DerivedPathBuffer[0]) return ("\0\0"); if (rqpsptr->MapOnce) { /* convert the URL-style to a VMS-style specification */ MapOdsUrlToVms (DerivedPathBuffer, VmsPtr, SizeOfVmsPtr, RmsSubChar, MapEllipsis, PathOds); if (WATCH_MODULE_DETAIL) WatchThis (WATCHITM(rqptr), WATCH_MOD_MAPURL, "SCRIPT !&Z !&Z", DerivedPathBuffer, VmsPtr); return (DerivedPathBuffer); } /* restarting at first rule map the path derived from the script */ MetaConPass++; if (rqptr) { rqptr->MetaConPass = MetaConPass; rqptr->MetaConScriptPtr = ScriptPtr; } *VmsPtr = '\0'; PathPtr = DerivedPathBuffer; RmsSubChar = MAPURL_RMS_SUBSTITUTION_DEFAULT; MapEllipsis = rqpsptr->MapEllipsis = false; MetaConParseReset (MetaGlobalMappingPtr, true); continue; case MAPURL_RULE_PROTECT : /****************/ /* PROTECT rule */ /****************/ if (MetaConPass == 1) { /* pass one protects the full path or script component */ if (mrptr->ResultLength) { rqptr->rqAuth.Protect1Ptr = VmGetHeap (rqptr, mrptr->ResultLength+1); rqptr->rqAuth.Protect1Length = mrptr->ResultLength; memcpy (rqptr->rqAuth.Protect1Ptr, mrptr->ResultPtr, mrptr->ResultLength+1); } else { /* empty result string cancels any previous authorization */ rqptr->rqAuth.Protect1Ptr = NULL; rqptr->rqAuth.Protect1Length = 0; } } else { /* pass two protects any path following the script component */ if (mrptr->ResultLength) { rqptr->rqAuth.Protect2Ptr = VmGetHeap (rqptr, mrptr->ResultLength+1); rqptr->rqAuth.Protect2Length = mrptr->ResultLength; memcpy (rqptr->rqAuth.Protect2Ptr, mrptr->ResultPtr, mrptr->ResultLength+1); } else { /* empty result string cancels any previous authorization */ rqptr->rqAuth.Protect1Ptr = NULL; rqptr->rqAuth.Protect1Length = 0; } } continue; case MAPURL_RULE_SET : /************/ /* SET rule */ /************/ /* path SETings have already been applied */ continue; } } else { /***************************/ /* mapping from VMS to URL */ /***************************/ /* REVERSE maps a VMS "result" to a "template" :^) */ cptr = WildString[idx = 1]; if (MapRootPtr) { if (WATCHING (rqptr, WATCH_MAPPING)) WatchThis (WATCHITM(rqptr), WATCH_MAPPING, "ROOT !AZ", MapRootPtr); while (MapRootLength-- && *cptr) cptr++; } zptr = (pptr = PathPtr) + SizeOfPathPtr; tptr = mrptr->TemplatePtr; /* scan through the template string */ while (*tptr) { while (*tptr && *tptr != '*' && pptr < zptr) *pptr++ = *tptr++; if (!*tptr) break; /* a wildcard asterisk, substitute from result path */ while (*tptr == '*') tptr++; if (*cptr) while (*cptr && pptr < zptr) *pptr++ = *cptr++; /* three lines fix 05-APR-2018 longstanding bug */ if (!*tptr) break; if (idx < REGEX_PMATCH_MAX) idx++; cptr = WildString[idx]; } if (pptr >= zptr) return (MsgFor(rqptr,MSG_MAPPING_DENIED_INTERNAL)-1); *pptr = '\0'; return (PathPtr); } } /***********************/ /* a mapping not found */ /***********************/ if (WatchThisOne) WatchThis (WATCHITM(rqptr), WATCH_MAPPING, "END of mapping rules"); if (MapPathToVms) return (MsgFor(rqptr,MSG_MAPPING_DENIED_DEFAULT)-1); else return (MAPURL_NO_REVERSE_PATH); } /*****************************************************************************/ /* The path has a setting. Map that onto the request path settings. */ MapUrl_PathSet ( REQUEST_STRUCT *rqptr, REQUEST_PATHSET *rqpsptr, MAP_SET_META *mrpsptr ) { int length; char *cptr, *sptr; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD_MAPURL)) WatchThis (WATCHITM(rqptr), WATCH_MOD_MAPURL, "MapUrl_PathSet()"); if (mrpsptr->NoAcceptLang) { rqpsptr->AcceptLangChar = '\0'; rqpsptr->AcceptLangWildcard = rqpsptr->AcceptLangTypeVariant = false; rqpsptr->AcceptLangPtr = NULL; } else if (mrpsptr->AcceptLangChar) { rqpsptr->AcceptLangChar = mrpsptr->AcceptLangChar; rqpsptr->AcceptLangWildcard = mrpsptr->AcceptLangWildcard; rqpsptr->AcceptLangTypeVariant = mrpsptr->AcceptLangTypeVariant; if (mrpsptr->AcceptLangLength) { rqpsptr->AcceptLangPtr = VmGetHeap (rqptr, mrpsptr->AcceptLangLength+1); memcpy (rqpsptr->AcceptLangPtr, mrpsptr->AcceptLangPtr, mrpsptr->AcceptLangLength+1); } } if (mrpsptr->NoAlert) rqpsptr->Alert = 0; else if (mrpsptr->Alert) rqpsptr->Alert = mrpsptr->Alert; if (mrpsptr->NoAuthAll) rqpsptr->AuthorizeAll = false; else if (mrpsptr->AuthAll) rqpsptr->AuthorizeAll = true; if (mrpsptr->NoAuthMapped) rqpsptr->AuthorizeMapped = false; else if (mrpsptr->AuthMapped) rqpsptr->AuthorizeMapped = true; if (mrpsptr->NoAuthOnce) rqpsptr->AuthorizeOnce = false; else if (mrpsptr->AuthOnce) rqpsptr->AuthorizeOnce = true; /* only if they haven't been set in any previous pass */ if (!rqpsptr->AuthRevalidateTimeout) rqpsptr->AuthRevalidateTimeout = mrpsptr->AuthRevalidateTimeout; if (mrpsptr->AuthSysUafPwdExpUrlLength) { rqpsptr->AuthSysUafPwdExpUrlPtr = VmGetHeap (rqptr, mrpsptr->AuthSysUafPwdExpUrlLength+1); memcpy (rqpsptr->AuthSysUafPwdExpUrlPtr, mrpsptr->AuthSysUafPwdExpUrlPtr, mrpsptr->AuthSysUafPwdExpUrlLength+1); } if (mrpsptr->NoCache) { rqpsptr->NoCache = true; rqpsptr->CacheCGI = rqpsptr->CacheCookie = rqpsptr->CacheNoFile = rqpsptr->CacheNet = rqpsptr->CacheNPH = rqpsptr->CachePermanent = rqpsptr->CacheQuery = false; rqpsptr->CacheExpiresAfter = rqpsptr->CacheGuardSeconds = rqpsptr->CacheMaxKBytes = 0; } else if (mrpsptr->CacheSetting) { if (mrpsptr->Cache) rqpsptr->NoCache = rqpsptr->CacheNoFile = false; if (mrpsptr->CacheNoCGI) rqpsptr->CacheCGI = false; else if (mrpsptr->CacheCGI) rqpsptr->CacheCGI = true; if (mrpsptr->CacheNoCookie) rqpsptr->CacheCookie = false; else if (mrpsptr->CacheCookie) rqpsptr->CacheCookie = true; if (mrpsptr->CacheNoFile) rqpsptr->CacheNoFile = true; else if (mrpsptr->CacheFile) rqpsptr->CacheNoFile = false; if (mrpsptr->CacheNoNet) rqpsptr->CacheNet = false; else if (mrpsptr->CacheNet) rqpsptr->CacheNet = true; if (mrpsptr->CacheNoNPH) rqpsptr->CacheNPH = false; else if (mrpsptr->CacheNPH) rqpsptr->CacheNPH = true; if (mrpsptr->CacheNoPermanent) rqpsptr->CachePermanent = false; else if (mrpsptr->CachePermanent) rqpsptr->CachePermanent = true; if (mrpsptr->CacheNoQuery) rqpsptr->CacheQuery = false; else if (mrpsptr->CacheQuery) rqpsptr->CacheQuery = true; if (mrpsptr->CacheNoScript) rqpsptr->CacheCGI = rqpsptr->CacheNPH = false; else if (mrpsptr->CacheScript) rqpsptr->CacheCGI = rqpsptr->CacheNPH = true; if (mrpsptr->CacheNoSSI) rqpsptr->CacheSSI = false; else if (mrpsptr->CacheSSI) rqpsptr->CacheSSI = true; if (mrpsptr->CacheExpiresAfter) { if (mrpsptr->CacheExpiresAfter == CACHE_EXPIRES_NONE) rqpsptr->CacheExpiresAfter = 0; else rqpsptr->CacheExpiresAfter = mrpsptr->CacheExpiresAfter; } if (mrpsptr->CacheGuardSeconds) { /* negative 1 indicates to revert to configuration maximum */ if (mrpsptr->CacheGuardSeconds == -1) rqpsptr->CacheGuardSeconds = 0; else rqpsptr->CacheGuardSeconds = mrpsptr->CacheGuardSeconds; } if (mrpsptr->CacheMaxKBytes) { /* negative 1 indicates to revert to configuration maximum */ if (mrpsptr->CacheMaxKBytes == -1) rqpsptr->CacheMaxKBytes = 0; else rqpsptr->CacheMaxKBytes = mrpsptr->CacheMaxKBytes; } } if (mrpsptr->CgiPlusInCC[0] || mrpsptr->CgiPlusInCC[1]) { if (mrpsptr->CgiPlusInCC[0]) memcpy (rqpsptr->CgiPlusInCC, mrpsptr->CgiPlusInCC, sizeof(rqpsptr->CgiPlusInCC)); else memset (rqpsptr->CgiPlusInCC, 0, sizeof(rqpsptr->CgiPlusInCC)); } if (mrpsptr->CgiPlusInNoWriteof) rqpsptr->CgiPlusInWriteof = false; else if (mrpsptr->CgiPlusInWriteof) rqpsptr->CgiPlusInWriteof = true; if (mrpsptr->NoDefaultSearch) rqpsptr->NoDefaultSearch = true; else if (mrpsptr->DefaultSearch) rqpsptr->NoDefaultSearch = false; if (mrpsptr->ClientAddress) { rqpsptr->ClientAddress = mrpsptr->ClientAddress; if (mrpsptr->ClientAddress == MAPURL_CLIENT_LITERAL) { rqpsptr->ClientAddressLiteralPtr = VmGetHeap (rqptr, mrpsptr->ClientAddressLiteralLength+1); memcpy (rqpsptr->ClientAddressLiteralPtr, mrpsptr->ClientAddressLiteralPtr, mrpsptr->ClientAddressLiteralLength+1); } } if (mrpsptr->DirNoAccess) { rqpsptr->DirNoAccess = true; rqpsptr->DirAccess = rqpsptr->DirAccessSelective = false; } else if (mrpsptr->DirAccess) { rqpsptr->DirAccess = true; rqpsptr->DirNoAccess = rqpsptr->DirAccessSelective = false; } else if (mrpsptr->DirAccessSelective) { rqpsptr->DirAccessSelective = true; rqpsptr->DirAccess = rqpsptr->DirNoAccess = false; } if (mrpsptr->DirFont == MAPURL_DIR_FONT_INHERIT) rqpsptr->DirFont = MAPURL_DIR_FONT_INHERIT; else if (mrpsptr->DirFont == MAPURL_DIR_FONT_MONOSPACE) rqpsptr->DirFont = 0; if (mrpsptr->DirNoIconLink) rqpsptr->DirNoIconLink = true; else if (mrpsptr->DirIconLink) rqpsptr->DirNoIconLink = false; if (mrpsptr->DirNoImpliedWildcard) rqpsptr->DirNoImpliedWildcard = true; else if (mrpsptr->DirImpliedWildcard) rqpsptr->DirNoImpliedWildcard = false; if (mrpsptr->DirSort[0]) { rqpsptr->DirSort[0] = mrpsptr->DirSort[0]; rqpsptr->DirSort[1] = mrpsptr->DirSort[1]; } if (mrpsptr->DirStyle == MAPURL_DIR_STYLE_DEFAULT || mrpsptr->DirStyle == MAPURL_DIR_STYLE_ANCHOR) rqpsptr->DirStyle = 0; else if (mrpsptr->DirStyle) rqpsptr->DirStyle = mrpsptr->DirStyle; if (mrpsptr->DirTargetPtr) { /* empty string resets */ if (mrpsptr->DirTargetLength) { rqpsptr->DirTargetPtr = VmGetHeap (rqptr, mrpsptr->DirTargetLength+1); memcpy (rqpsptr->DirTargetPtr, mrpsptr->DirTargetPtr, mrpsptr->DirTargetLength+1); } else rqpsptr->DirTargetPtr = NULL; } if (mrpsptr->DirThesePtr) { /* empty string resets */ if (mrpsptr->DirTheseLength) { rqpsptr->DirThesePtr = VmGetHeap (rqptr, mrpsptr->DirTheseLength+1); memcpy (rqpsptr->DirThesePtr, mrpsptr->DirThesePtr, mrpsptr->DirTheseLength+1); } else rqpsptr->DirThesePtr = NULL; } if (mrpsptr->DirTitle == MAPURL_DIR_TITLE_THIS) { /* empty string resets */ if (mrpsptr->DirTitleLength) { rqpsptr->DirTitle = mrpsptr->DirTitle; rqpsptr->DirTitlePtr = VmGetHeap (rqptr, mrpsptr->DirTitleLength+1); memcpy (rqpsptr->DirTitlePtr, mrpsptr->DirTitlePtr, mrpsptr->DirTitleLength+1); } else { rqpsptr->DirTitle = 0; rqpsptr->DirTitlePtr = NULL; } } else if (mrpsptr->DirTitle) rqpsptr->DirTitle = mrpsptr->DirTitle; if (mrpsptr->DirNoWildcard) { rqpsptr->DirNoWildcard = true; rqpsptr->DirWildcard = false; } else if (mrpsptr->DirWildcard) { rqpsptr->DirNoWildcard = false; rqpsptr->DirWildcard = true; } /* negative 1 indicates to revert to zero */ if (mrpsptr->DirVersionsOf) rqpsptr->DirVersionsOf = mrpsptr->DirVersionsOf; if (mrpsptr->DirNoWildcard) { rqpsptr->DirNoWildcard = true; rqpsptr->DirWildcard = false; } else if (mrpsptr->DirWildcard) { rqpsptr->DirNoWildcard = false; rqpsptr->DirWildcard = true; } if (mrpsptr->NoExpired) rqpsptr->Expired = false; else if (mrpsptr->Expired) rqpsptr->Expired = true; if (mrpsptr->NoHtmlEquals) { rqpsptr->HtmlBodyTagPtr = rqpsptr->HtmlFooterPtr = rqpsptr->HtmlFooterTagPtr = rqpsptr->HtmlHeaderPtr = rqpsptr->HtmlHeaderTagPtr = NULL; } if (mrpsptr->HtmlBodyTagPtr) { /* empty string resets */ if (mrpsptr->HtmlBodyTagLength) { rqpsptr->HtmlBodyTagPtr = VmGetHeap (rqptr, mrpsptr->HtmlBodyTagLength+1); memcpy (rqpsptr->HtmlBodyTagPtr, mrpsptr->HtmlBodyTagPtr, mrpsptr->HtmlBodyTagLength+1); } else rqpsptr->HtmlBodyTagPtr = NULL; } if (mrpsptr->HtmlFooterPtr) { /* empty string resets */ if (mrpsptr->HtmlFooterLength) { rqpsptr->HtmlFooterPtr = VmGetHeap (rqptr, mrpsptr->HtmlFooterLength+1); memcpy (rqpsptr->HtmlFooterPtr, mrpsptr->HtmlFooterPtr, mrpsptr->HtmlFooterLength+1); } else rqpsptr->HtmlFooterPtr = NULL; } if (mrpsptr->HtmlFooterTagPtr) { /* empty string resets */ if (mrpsptr->HtmlFooterTagLength) { rqpsptr->HtmlFooterTagPtr = VmGetHeap (rqptr, mrpsptr->HtmlFooterTagLength+1); memcpy (rqpsptr->HtmlFooterTagPtr, mrpsptr->HtmlFooterTagPtr, mrpsptr->HtmlFooterTagLength+1); } else rqpsptr->HtmlFooterTagPtr = NULL; } if (mrpsptr->HtmlHeaderPtr) { /* empty string resets */ if (mrpsptr->HtmlHeaderLength) { rqpsptr->HtmlHeaderPtr = VmGetHeap (rqptr, mrpsptr->HtmlHeaderLength+1); memcpy (rqpsptr->HtmlHeaderPtr, mrpsptr->HtmlHeaderPtr, mrpsptr->HtmlHeaderLength+1); } else rqpsptr->HtmlHeaderPtr = NULL; } if (mrpsptr->HtmlHeaderTagPtr) { /* empty string resets */ if (mrpsptr->HtmlHeaderTagLength) { rqpsptr->HtmlHeaderTagPtr = VmGetHeap (rqptr, mrpsptr->HtmlHeaderTagLength+1); memcpy (rqpsptr->HtmlHeaderTagPtr, mrpsptr->HtmlHeaderTagPtr, mrpsptr->HtmlHeaderTagLength+1); } else rqpsptr->HtmlHeaderTagPtr = NULL; } if (HTTP2_REQUEST(rqptr)) { /* if HTTP/2 request */ if (mrpsptr->Http2MaxStreams) rqpsptr->Http2MaxStreams = mrpsptr->Http2MaxStreams; if (mrpsptr->Http2SendGoAway) rqpsptr->Http2SendGoAway = mrpsptr->Http2SendGoAway; if (mrpsptr->Http2SendPing) rqpsptr->Http2SendPing = true; if (mrpsptr->Http2SendReset) rqpsptr->Http2SendReset = mrpsptr->Http2SendReset; if (mrpsptr->Http2ToHttp11) rqpsptr->Http2ToHttp11 = true; if (mrpsptr->Http2WriteQueue) rqpsptr->Http2WriteQueue = mrpsptr->Http2WriteQueue; } if (mrpsptr->NoLog) rqpsptr->NoLog = true; else if (mrpsptr->Log) rqpsptr->NoLog = false; if (mrpsptr->MapNonEmpty) rqpsptr->MapEmpty = false; else if (mrpsptr->MapEmpty) rqpsptr->MapEmpty = true; if (mrpsptr->MapExtensionMethod) rqpsptr->MapExtensionMethod = true; else if (mrpsptr->MapExtensionMethod) rqpsptr->MapExtensionMethod = false; if (mrpsptr->MapOnce) rqpsptr->MapOnce = true; else if (mrpsptr->NoMapOnce) rqpsptr->MapOnce = false; if (mrpsptr->MapUri) rqpsptr->MapUri = true; if (mrpsptr->PrivSsi) rqpsptr->PrivSsi = true; else if (mrpsptr->NoPrivSsi) rqpsptr->PrivSsi = false; if (mrpsptr->NoProfile) rqpsptr->NoProfile = true; else if (mrpsptr->Profile) rqpsptr->NoProfile = false; if (mrpsptr->ProxyNoAffinity) rqpsptr->ProxyAffinity = false; else if (mrpsptr->ProxyAffinity) rqpsptr->ProxyAffinity = true; if (mrpsptr->ProxyForwardedBy) rqpsptr->ProxyForwardedBy = mrpsptr->ProxyForwardedBy; if (mrpsptr->ProxyXForwardedFor) rqpsptr->ProxyXForwardedFor = mrpsptr->ProxyXForwardedFor; if (mrpsptr->NoProxyReverseVerify) rqpsptr->ProxyReverseVerify = false; else if (mrpsptr->ProxyReverseVerify) rqpsptr->ProxyReverseVerify = true; if (mrpsptr->NoProxyReverseAuthHeader) rqpsptr->ProxyReverseNoAuthHeader = true; else if (mrpsptr->ProxyReverseAuthHeader) rqpsptr->ProxyReverseNoAuthHeader = false; if (mrpsptr->ProxyTunnelRequestLength) { rqpsptr->ProxyTunnelRequestPtr = VmGetHeap (rqptr, mrpsptr->ProxyTunnelRequestLength); memcpy (rqpsptr->ProxyTunnelRequestPtr, mrpsptr->ProxyTunnelRequestPtr, mrpsptr->ProxyTunnelRequestLength); rqpsptr->ProxyTunnelRequestLength = mrpsptr->ProxyTunnelRequestLength; } if (mrpsptr->NoProxyUnknownRequestFields) rqpsptr->ProxyUnknownRequestFields = false; else if (mrpsptr->ProxyUnknownRequestFields) rqpsptr->ProxyUnknownRequestFields = true; if (mrpsptr->ProxyHeaderCount) { rqpsptr->ProxyHeaderCount = mrpsptr->ProxyHeaderCount; for (int idx = 0; idx < mrpsptr->ProxyHeaderCount; idx++) { rqpsptr->ProxyHeader[idx] = VmGetHeap (rqptr, strlen(mrpsptr->ProxyHeader[idx])); strcpy (rqpsptr->ProxyHeader[idx], mrpsptr->ProxyHeader[idx]); } } if (mrpsptr->PutRFM) rqpsptr->PutRFM = mrpsptr->PutRFM; if (mrpsptr->PutMaxKbytes) rqpsptr->PutMaxKbytes = mrpsptr->PutMaxKbytes; if (mrpsptr->RegexSyntax) if ((rqpsptr->RegexSyntax = mrpsptr->RegexSyntax) == -1) rqpsptr->RegexSyntax = 0; if (mrpsptr->ReportType) rqpsptr->ReportType = mrpsptr->ReportType; if (mrpsptr->Report400as) rqpsptr->Report400as = mrpsptr->Report400as; if (mrpsptr->Report403as) rqpsptr->Report403as = mrpsptr->Report403as; if (mrpsptr->Report404as) rqpsptr->Report404as = mrpsptr->Report404as; if (mrpsptr->ResponseGzip) rqpsptr->ResponseGzip = mrpsptr->ResponseGzip; if (mrpsptr->Response200is203) rqpsptr->Response200is203 = mrpsptr->Response200is203; if (mrpsptr->ResponseNoChunked) rqpsptr->ResponseNoChunked = true; else if (mrpsptr->ResponseChunked) rqpsptr->ResponseNoChunked = false; if (mrpsptr->ResponseHeaderNone) rqpsptr->ResponseHeaderNone = true; else if (mrpsptr->ResponseHeaderBegin) rqpsptr->ResponseHeaderBegin = true; else if (mrpsptr->ResponseHeaderFull) rqpsptr->ResponseHeaderBegin = rqpsptr->ResponseHeaderNone = false; if (mrpsptr->ResponseHttpNoOriginal) rqpsptr->ResponseHttpOriginal = false; else if (mrpsptr->ResponseHttpOriginal) rqpsptr->ResponseHttpOriginal = true; if (mrpsptr->ScriptBodyNoDecode) rqpsptr->ScriptBodyDecode = false; else if (mrpsptr->ScriptBodyDecode) rqpsptr->ScriptBodyDecode = true; if (mrpsptr->ScriptSymbolNoTruncate) rqpsptr->ScriptSymbolTruncate = false; else if (mrpsptr->ScriptSymbolTruncate) rqpsptr->ScriptSymbolTruncate = true; if (mrpsptr->ScriptSyntaxNoUnix) rqpsptr->ScriptSyntaxUnix = false; else if (mrpsptr->ScriptSyntaxUnix) rqpsptr->ScriptSyntaxUnix = true; /* careful! this one's a little back-to-front */ if (mrpsptr->ScriptFind) rqpsptr->ScriptNoFind = false; else if (mrpsptr->ScriptNoFind) rqpsptr->ScriptNoFind = true; if (mrpsptr->ScriptNoPathFind) rqpsptr->ScriptPathFind = false; else if (mrpsptr->ScriptPathFind) rqpsptr->ScriptPathFind = true; if (mrpsptr->ScriptNoQueryNone) rqpsptr->ScriptQueryNone = false; else if (mrpsptr->ScriptQueryNone) rqpsptr->ScriptQueryNone = true; if (mrpsptr->ScriptNoQueryRelaxed) rqpsptr->ScriptQueryRelaxed = false; else if (mrpsptr->ScriptQueryRelaxed) rqpsptr->ScriptQueryRelaxed = true; if (mrpsptr->AccessNoProfile) rqpsptr->AccessProfile = false; else if (mrpsptr->AccessProfile) rqpsptr->AccessProfile = true; if (mrpsptr->AccessNoRead) rqpsptr->AccessRead = false; else if (mrpsptr->AccessRead) rqpsptr->AccessRead = true; if (mrpsptr->AccessNoServer) rqpsptr->AccessServer = false; else if (mrpsptr->AccessServer) rqpsptr->AccessServer = true; if (mrpsptr->AccessNoWrite) rqpsptr->AccessWrite = false; else if (mrpsptr->AccessWrite) rqpsptr->AccessWrite = true; if (mrpsptr->WebDavNoHidden) rqpsptr->WebDavNoHidden = true; else if (mrpsptr->WebDavHidden) rqpsptr->WebDavNoHidden = false; if (mrpsptr->WebDavNoLock) rqpsptr->WebDavNoLock = true; else if (mrpsptr->WebDavLock) rqpsptr->WebDavNoLock = false; /* allowed to be an empty string (suppresses directory) */ if (mrpsptr->WebDavMetaDirPtr) { rqpsptr->WebDavMetaDirPtr = VmGetHeap (rqptr, mrpsptr->WebDavMetaDirLength+1); memcpy (rqpsptr->WebDavMetaDirPtr, mrpsptr->WebDavMetaDirPtr, mrpsptr->WebDavMetaDirLength+1); } if (mrpsptr->WebDavNoProfile) rqpsptr->WebDavProfile = false; else if (mrpsptr->WebDavProfile) rqpsptr->WebDavProfile = true; if (mrpsptr->WebDavNoProp) rqpsptr->WebDavNoProp = true; else if (mrpsptr->WebDavProp) rqpsptr->WebDavNoProp = false; if (mrpsptr->WebDavNoPutLock) rqpsptr->WebDavPutLock = false; else if (mrpsptr->WebDavPutLock) rqpsptr->WebDavPutLock = true; if (mrpsptr->WebDavNoRead) rqpsptr->WebDavRead = false; else if (mrpsptr->WebDavRead) rqpsptr->WebDavRead = true; if (mrpsptr->WebDavNoServer) rqpsptr->WebDavServer = false; else if (mrpsptr->WebDavServer) rqpsptr->WebDavServer = true; if (mrpsptr->WebDavNoWinProp) rqpsptr->WebDavNoWinProp = true; else if (mrpsptr->WebDavWinProp) rqpsptr->WebDavNoWinProp = false; if (mrpsptr->WebDavNoWrite) rqpsptr->WebDavWrite = false; else if (mrpsptr->WebDavWrite) rqpsptr->WebDavWrite = true; if (mrpsptr->WebDavLockTimeoutDefault) rqpsptr->WebDavLockTimeoutDefault = mrpsptr->WebDavLockTimeoutDefault; if (mrpsptr->WebDavLockTimeoutMax) rqpsptr->WebDavLockTimeoutMax = mrpsptr->WebDavLockTimeoutMax; if (mrpsptr->WebSocketInputSize) rqpsptr->WebSocketInputSize = mrpsptr->WebSocketInputSize; if (mrpsptr->WebSocketOutputSize) rqpsptr->WebSocketOutputSize = mrpsptr->WebSocketOutputSize; if (rqpsptr->ThrottleSet && mrpsptr->ThrottleNoSet) { /* reset a previously mapped throttle */ rqpsptr->ThrottleSet = false; rqpsptr->ThrottleBusy = rqpsptr->ThrottleFrom = rqpsptr->ThrottleIndex = rqpsptr->ThrottlePerUser = rqpsptr->ThrottleResume = rqpsptr->ThrottleTo = rqpsptr->ThrottleTimeoutBusy = rqpsptr->ThrottleTimeoutQueue = 0; } else if (!rqpsptr->ThrottleSet && mrpsptr->ThrottleSet) { /* only if it hasn't been set in any previous pass */ rqpsptr->ThrottleSet = true; rqpsptr->ThrottleBusy = mrpsptr->ThrottleBusy; rqpsptr->ThrottleFrom = mrpsptr->ThrottleFrom; rqpsptr->ThrottleIndex = mrpsptr->ThrottleIndex; rqpsptr->ThrottlePerUser = mrpsptr->ThrottlePerUser; rqpsptr->ThrottleResume = mrpsptr->ThrottleResume; rqpsptr->ThrottleTo = mrpsptr->ThrottleTo; rqpsptr->ThrottleTimeoutBusy = mrpsptr->ThrottleTimeoutBusy; rqpsptr->ThrottleTimeoutQueue = mrpsptr->ThrottleTimeoutQueue; } /* only if they haven't been set in any previous pass */ if (!rqpsptr->ScriptBitBucketTimeout) rqpsptr->ScriptBitBucketTimeout = mrpsptr->ScriptBitBucketTimeout; if (!rqpsptr->ScriptCpuMax) rqpsptr->ScriptCpuMax = mrpsptr->ScriptCpuMax; if (!rqpsptr->ScriptLifeTime) rqpsptr->ScriptLifeTime = mrpsptr->ScriptLifeTime; /* hmmm, bit of a kludge (but easy) */ if (mrpsptr->TimeoutPersistent < 0) rqptr->PersistentRequest = false; else rqpsptr->TimeoutPersistent = mrpsptr->TimeoutPersistent; if (!rqpsptr->TimeoutNoProgress) rqpsptr->TimeoutNoProgress = mrpsptr->TimeoutNoProgress; if (!rqpsptr->TimeoutOutput) rqpsptr->TimeoutOutput = mrpsptr->TimeoutOutput; if (mrpsptr->NoStmLF) rqpsptr->StmLF = false; else if (mrpsptr->StmLF) rqpsptr->StmLF = true; if (mrpsptr->SSLCGIvar) { if (rqpsptr->SSLCGIvar == SESOLA_CGI_VAR_NONE) rqpsptr->SSLCGIvar = 0; else rqpsptr->SSLCGIvar = mrpsptr->SSLCGIvar; } if (mrpsptr->PathOds) rqpsptr->PathOds = mrpsptr->PathOds; if (mrpsptr->OdsName) if (mrpsptr->OdsName == MAPURL_ODS_DEFAULT) rqpsptr->OdsName = 0; else rqpsptr->OdsName = mrpsptr->OdsName; /* allowed to be an empty string */ if (mrpsptr->CgiPrefixPtr) { rqpsptr->CgiPrefixPtr = VmGetHeap (rqptr, mrpsptr->CgiPrefixLength+1); memcpy (rqpsptr->CgiPrefixPtr, mrpsptr->CgiPrefixPtr, mrpsptr->CgiPrefixLength+1); } /* allowed to be an empty string (suppresses charset) */ if (mrpsptr->CharsetPtr) { rqpsptr->CharsetPtr = VmGetHeap (rqptr, mrpsptr->CharsetLength+1); memcpy (rqpsptr->CharsetPtr, mrpsptr->CharsetPtr, mrpsptr->CharsetLength+1); } /* empty string resets (reverts type, must have a content type) */ if (mrpsptr->ContentTypePtr) { if (mrpsptr->ContentTypeLength) { rqpsptr->ContentTypePtr = VmGetHeap (rqptr, mrpsptr->ContentTypeLength+1); memcpy (rqpsptr->ContentTypePtr, mrpsptr->ContentTypePtr, mrpsptr->ContentTypeLength+1); } else rqpsptr->ContentTypePtr = NULL; } /* allowed to be an empty string (suppresses charset) */ if (mrpsptr->DirCharsetPtr) { rqpsptr->DirCharsetPtr = VmGetHeap (rqptr, mrpsptr->DirCharsetLength+1); memcpy (rqpsptr->DirCharsetPtr, mrpsptr->DirCharsetPtr, mrpsptr->DirCharsetLength+1); } /* allowed to be an empty string */ if (mrpsptr->HttpAcceptCharsetPtr) { if (mrpsptr->HttpAcceptCharsetPtr[0]) { rqptr->rqHeader.AcceptCharsetPtr = VmGetHeap (rqptr, mrpsptr->HttpAcceptCharsetLength+1); memcpy (rqptr->rqHeader.AcceptCharsetPtr, mrpsptr->HttpAcceptCharsetPtr, mrpsptr->HttpAcceptCharsetLength+1); } else { /* empty, as if it had never been part of the request header */ rqptr->rqHeader.AcceptCharsetPtr = NULL; } } /* allowed to be an empty string */ if (mrpsptr->HttpAcceptLangPtr) { if (mrpsptr->HttpAcceptLangPtr[0]) { rqptr->rqHeader.AcceptLangPtr = VmGetHeap (rqptr, mrpsptr->HttpAcceptLangLength+1); memcpy (rqptr->rqHeader.AcceptLangPtr, mrpsptr->HttpAcceptLangPtr, mrpsptr->HttpAcceptLangLength+1); } else { /* empty, as if it had never been part of the request header */ rqptr->rqHeader.AcceptLangPtr = NULL; } } if (mrpsptr->IndexPtr) { /* empty string resets */ if (mrpsptr->IndexLength) { rqpsptr->IndexPtr = VmGetHeap (rqptr, mrpsptr->IndexLength+1); memcpy (rqpsptr->IndexPtr, mrpsptr->IndexPtr, mrpsptr->IndexLength+1); } else rqpsptr->IndexPtr = NULL; } if (mrpsptr->DictionaryPtr) { MetaConDictionary (rqptr, mrpsptr->DictionaryPtr); if (WATCHPNT(rqptr) && (WATCH_CATEGORY(WATCH_MAPPING) && WATCH_CATEGORY(WATCH_INTERNAL))) DictWatch (rqptr->rqDictPtr, DICT_TYPE_CONFIG, "*"); } if (mrpsptr->NotePadPtr) { if (WATCHING (rqptr, WATCH_MAPPING)) { MetaConNotePad (rqptr, mrpsptr->NotePadPtr, true); WatchThis (WATCHITM(rqptr), WATCH_MAPPING, "NOTEPAD !AZ", rqptr->NotePadPtr != NULL ? rqptr->NotePadPtr : "(empty)"); } else MetaConNotePad (rqptr, mrpsptr->NotePadPtr, false); } if (mrpsptr->ProxyReverseLocationPtr) { /* empty string resets */ if (mrpsptr->ProxyReverseLocationLength) { rqpsptr->ProxyReverseLocationPtr = VmGetHeap (rqptr, mrpsptr->ProxyReverseLocationLength+1); memcpy (rqpsptr->ProxyReverseLocationPtr, mrpsptr->ProxyReverseLocationPtr, mrpsptr->ProxyReverseLocationLength+1); } else rqpsptr->ProxyReverseLocationPtr = NULL; } /* query string is allowed to be set empty */ if (mrpsptr->QueryStringPtr) { if (rqptr->rqHeader.QueryStringLength < mrpsptr->QueryStringLength) rqptr->rqHeader.QueryStringPtr = VmGetHeap (rqptr, mrpsptr->QueryStringLength+1); memcpy (rqptr->rqHeader.QueryStringPtr, mrpsptr->QueryStringPtr, mrpsptr->QueryStringLength+1); rqptr->rqHeader.QueryStringLength = mrpsptr->QueryStringLength; } /* also see DCL callout "CSP:" */ if (mrpsptr->ResponseCspLength < 0) { rqpsptr->ResponseCspPtr = NULL; rqpsptr->ResponseCspLength = 0; } else if (length = mrpsptr->ResponseCspLength) { cptr = mrpsptr->ResponseCspPtr; rqpsptr->ResponseCspPtr = sptr = VmReallocHeap (rqptr, rqpsptr->ResponseCspPtr, rqpsptr->ResponseCspLength + length+2, FI_LI); if (rqpsptr->ResponseCspLength) { sptr += rqpsptr->ResponseCspLength; *sptr++ = ' '; } memcpy (sptr, cptr, length); sptr += length; rqpsptr->ResponseCspLength = sptr - rqpsptr->ResponseCspPtr; } /* also see DCL callout "CSPRO:" */ if (mrpsptr->ResponseCsproLength < 0) { rqpsptr->ResponseCsproPtr = NULL; rqpsptr->ResponseCsproLength = 0; } else if (length = mrpsptr->ResponseCsproLength) { cptr = mrpsptr->ResponseCsproPtr; rqpsptr->ResponseCsproPtr = sptr = VmReallocHeap (rqptr, rqpsptr->ResponseCsproPtr, rqpsptr->ResponseCsproLength + length+2, FI_LI); if (rqpsptr->ResponseCsproLength) { sptr += rqpsptr->ResponseCsproLength; *sptr++ = ' '; } memcpy (sptr, cptr, length); sptr += length; rqpsptr->ResponseCsproLength = sptr - rqpsptr->ResponseCsproPtr; } /* leave this in for backward compatibility (but use empty string) */ if (mrpsptr->ResponseHeaderNoAdd) { rqpsptr->ResponseHeaderAddPtr = NULL; rqpsptr->ResponseHeaderAddLength = 0; } if (mrpsptr->ResponseHeaderAddPtr && !mrpsptr->ResponseHeaderAddLength) { /* empty string resets */ rqpsptr->ResponseHeaderAddPtr = NULL; rqpsptr->ResponseHeaderAddLength = 0; } else if (length = mrpsptr->ResponseHeaderAddLength) { cptr = mrpsptr->ResponseHeaderAddPtr; rqpsptr->ResponseHeaderAddPtr = sptr = VmReallocHeap (rqptr, rqpsptr->ResponseHeaderAddPtr, rqpsptr->ResponseHeaderAddLength + mrpsptr->ResponseHeaderAddLength+2, FI_LI); sptr += rqpsptr->ResponseHeaderAddLength; memcpy (sptr, cptr, length); sptr += length; SET2(sptr,'\n\0'); sptr++; rqpsptr->ResponseHeaderAddLength = sptr - rqpsptr->ResponseHeaderAddPtr; } if (mrpsptr->ResponseVarRecord) { if (mrpsptr->ResponseVarRecord == FILE_VAR_DEFAULT) rqpsptr->ResponseVarRecord = 0; else rqpsptr->ResponseVarRecord = mrpsptr->ResponseVarRecord; } if (mrpsptr->ResponseStrictTransSecPtr) { /* must start with an integer or suppresses header */ if (mrpsptr->ResponseStrictTransSecLength) { rqpsptr->ResponseStrictTransSecPtr = VmGetHeap (rqptr, mrpsptr->ResponseStrictTransSecLength+1); memcpy (rqpsptr->ResponseStrictTransSecPtr, mrpsptr->ResponseStrictTransSecPtr, mrpsptr->ResponseStrictTransSecLength+1); } else rqpsptr->ResponseStrictTransSecPtr = NULL; } if (mrpsptr->ScriptCommandPtr) { /* empty string resets */ if (mrpsptr->ScriptCommandLength) { rqpsptr->ScriptCommandPtr = VmGetHeap (rqptr, mrpsptr->ScriptCommandLength+1); memcpy (rqpsptr->ScriptCommandPtr, mrpsptr->ScriptCommandPtr, mrpsptr->ScriptCommandLength+1); } else rqpsptr->ScriptCommandPtr = NULL; } if (mrpsptr->ScriptControlPtr) { /* empty string resets */ if (mrpsptr->ScriptControlLength) { rqpsptr->ScriptControlPtr = VmGetHeap (rqptr, mrpsptr->ScriptControlLength+1); memcpy (rqpsptr->ScriptControlPtr, mrpsptr->ScriptControlPtr, mrpsptr->ScriptControlLength+1); } else rqpsptr->ScriptControlPtr = NULL; } if (mrpsptr->ScriptDefaultPtr) { /* empty string resets */ if (mrpsptr->ScriptDefaultLength) { rqpsptr->ScriptDefaultPtr = VmGetHeap (rqptr, mrpsptr->ScriptDefaultLength+1); memcpy (rqpsptr->ScriptDefaultPtr, mrpsptr->ScriptDefaultPtr, mrpsptr->ScriptDefaultLength+1); } else rqpsptr->ScriptDefaultPtr = NULL; } if (mrpsptr->ScriptParamsPtr && !mrpsptr->ScriptParamsLength) { /* empty string resets */ mrpsptr->ScriptParamsPtr = NULL; mrpsptr->ScriptParamsLength = 0; } else if (mrpsptr->ScriptParamsPtr) { rqpsptr->ScriptParamsPtr = sptr = VmReallocHeap (rqptr, rqpsptr->ScriptParamsPtr, rqpsptr->ScriptParamsLength + mrpsptr->ScriptParamsLength+1, FI_LI); sptr += rqpsptr->ScriptParamsLength; cptr = mrpsptr->ScriptParamsPtr; length = mrpsptr->ScriptParamsLength; if (*cptr == '+') { cptr++; length--; } memcpy (sptr, cptr, length); rqpsptr->ScriptParamsLength += length; } if (mrpsptr->ChangeServicePtr) { /* empty string resets */ if (mrpsptr->ChangeServiceLength) { rqpsptr->ChangeServicePtr = VmGetHeap (rqptr, mrpsptr->ChangeServiceLength+1); memcpy (rqpsptr->ChangeServicePtr, mrpsptr->ChangeServicePtr, mrpsptr->ChangeServiceLength+1); } else rqpsptr->ChangeServicePtr = NULL; } if (mrpsptr->SsiExecPtr) { /* empty string resets */ if (mrpsptr->SsiExecLength) { rqpsptr->SsiExecPtr = VmGetHeap (rqptr, mrpsptr->SsiExecLength+1); memcpy (rqpsptr->SsiExecPtr, mrpsptr->SsiExecPtr, mrpsptr->SsiExecLength+1); } else rqpsptr->SsiExecPtr = NULL; } if (mrpsptr->StyleSheetPtr) { /* empty string resets */ if (mrpsptr->StyleSheetLength) { rqpsptr->StyleSheetPtr = VmGetHeap (rqptr, mrpsptr->StyleSheetLength+1); memcpy (rqpsptr->StyleSheetPtr, mrpsptr->StyleSheetPtr, mrpsptr->StyleSheetLength+1); } else rqpsptr->StyleSheetPtr = NULL; } if (mrpsptr->CorsNoAllowCredentials) rqpsptr->CorsAllowCredentials = false; else if (mrpsptr->CorsAllowCredentials) rqpsptr->CorsAllowCredentials = true; if (mrpsptr->CorsAllowHeadersPtr) { /* empty string resets */ if (mrpsptr->CorsAllowHeadersLength) { rqpsptr->CorsAllowHeadersPtr = VmGetHeap (rqptr, mrpsptr->CorsAllowHeadersLength+1); memcpy (rqpsptr->CorsAllowHeadersPtr, mrpsptr->CorsAllowHeadersPtr, mrpsptr->CorsAllowHeadersLength+1); } else rqpsptr->CorsAllowHeadersPtr = NULL; } if (mrpsptr->CorsAllowMethodsPtr) { /* empty string resets */ if (mrpsptr->CorsAllowMethodsLength) { rqpsptr->CorsAllowMethodsPtr = VmGetHeap (rqptr, mrpsptr->CorsAllowMethodsLength+1); memcpy (rqpsptr->CorsAllowMethodsPtr, mrpsptr->CorsAllowMethodsPtr, mrpsptr->CorsAllowMethodsLength+1); } else rqpsptr->CorsAllowMethodsPtr = NULL; } if (mrpsptr->CorsAllowOriginPtr) { /* empty string resets */ if (mrpsptr->CorsAllowOriginLength) { rqpsptr->CorsAllowOriginPtr = VmGetHeap (rqptr, mrpsptr->CorsAllowOriginLength+1); memcpy (rqpsptr->CorsAllowOriginPtr, mrpsptr->CorsAllowOriginPtr, mrpsptr->CorsAllowOriginLength+1); } else rqpsptr->CorsAllowOriginPtr = NULL; } if (mrpsptr->CorsExposeHeadersPtr) { /* empty string resets */ if (mrpsptr->CorsExposeHeadersLength) { rqpsptr->CorsExposeHeadersPtr = VmGetHeap (rqptr, mrpsptr->CorsExposeHeadersLength+1); memcpy (rqpsptr->CorsExposeHeadersPtr, mrpsptr->CorsExposeHeadersPtr, mrpsptr->CorsExposeHeadersLength+1); } else rqpsptr->CorsExposeHeadersPtr = NULL; } if (mrpsptr->CorsMaxAge) { /* negative 1 indicates to revert to configuration maximum */ if (mrpsptr->CorsMaxAge == -1) rqpsptr->CorsMaxAge = 0; else rqpsptr->CorsMaxAge = mrpsptr->CorsMaxAge; } if (IPADDRESS_IS_RESET(&rqpsptr->ProxyBindIpAddress) && IPADDRESS_IS_SET(&mrpsptr->ProxyBindIpAddress)) rqpsptr->ProxyBindIpAddress = mrpsptr->ProxyBindIpAddress; if (IPADDRESS_IS_RESET(&rqpsptr->ProxyChainIpAddress) && IPADDRESS_IS_SET(&mrpsptr->ProxyChainIpAddress)) { IPADDRESS_COPY (&rqpsptr->ProxyChainIpAddress, &mrpsptr->ProxyChainIpAddress); rqpsptr->ProxyChainPort = mrpsptr->ProxyChainPort; if (mrpsptr->ProxyChainHostPortPtr && mrpsptr->ProxyChainHostPortPtr[0]) { rqpsptr->ProxyChainHostPortPtr = VmGetHeap (rqptr, mrpsptr->ProxyChainHostPortLength+1); memcpy (rqpsptr->ProxyChainHostPortPtr, mrpsptr->ProxyChainHostPortPtr, mrpsptr->ProxyChainHostPortLength+1); } } if (mrpsptr->ProxyChainCredPtr) { /* empty string resets */ if (mrpsptr->ProxyChainCredLength) { rqpsptr->ProxyChainCredPtr = VmGetHeap (rqptr, mrpsptr->ProxyChainCredLength+1); memcpy (rqpsptr->ProxyChainCredPtr, mrpsptr->ProxyChainCredPtr, mrpsptr->ProxyChainCredLength+1); } else rqpsptr->ProxyChainCredPtr = NULL; } } /*****************************************************************************/ /* Modify the client's IP address data using the source indicated by the path setting. Used to support a transparent load balancer/accelerator/proxy upstream from the server while retaining the original client address data. Return a NULL pointer to indicate success. Return an error string if it fails for some reason (e.g. header is not present). A fail should abort mapping and report the error. */ char* MapUrl_SetClientAddress (REQUEST_STRUCT *rqptr) { int ClientAddress; char *cptr, *hptr, *sptr, *zptr; char strbuf [256]; CLIENT_STRUCT *clptr; IPADDRESS IpAddress; REQUEST_PATHSET *rqpsptr; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD_MAPURL)) WatchThis (WATCHITM(rqptr), WATCH_MOD_MAPURL, "MapUrl_SetClientAddress()"); /* do not reproduce again if multiple client data mappings */ if (rqptr->ClientPtr->SetClientAddress) clptr = rqptr->ClientPtr; else { /* reproduce the existing client data and then use that */ clptr = (CLIENT_STRUCT*)VmGetHeap (rqptr, sizeof(CLIENT_STRUCT)); memcpy (clptr, &rqptr->ClientPtr, sizeof(CLIENT_STRUCT)); rqptr->ClientResetPtr = rqptr->ClientPtr; rqptr->ClientPtr = clptr; } rqpsptr = &rqptr->rqPathSet; ClientAddress = rqpsptr->ClientAddress; rqpsptr->ClientAddress = 0; if (ClientAddress == clptr->SetClientAddress && ClientAddress != MAPURL_CLIENT_LITERAL) { if (WATCHING (rqptr, WATCH_MAPPING)) WatchThis (WATCHITM(rqptr), WATCH_MAPPING, "CLIENT already set to this!!"); return (NULL); } if (ClientAddress == MAPURL_CLIENT_XFORWARDEDFOR || ClientAddress == MAPURL_CLIENT_IF_XFORWARDEDFOR) { cptr = rqptr->rqHeader.XForwardedForPtr; hptr = "X-Forwarded-For:"; } else if (ClientAddress == MAPURL_CLIENT_FORWARDED || ClientAddress == MAPURL_CLIENT_IF_FORWARDED) { cptr = rqptr->rqHeader.ForwardedPtr; hptr = "Forwarded:"; } else if (ClientAddress == MAPURL_CLIENT_LITERAL) { /* really just for ease of testing */ cptr = rqpsptr->ClientAddressLiteralPtr; hptr = "X-Literal:"; } else { ErrorNoticed (rqptr, SS$_BUGCHECK, ErrorSanityCheck, FI_LI); return (MsgFor(rqptr,MSG_MAPPING_DENIED_INTERNAL)-1); } if (!cptr) { if (WATCHING (rqptr, WATCH_MAPPING)) WatchThis (WATCHITM(rqptr), WATCH_MAPPING, "CLIENT no !AZ", hptr); if (ClientAddress == MAPURL_CLIENT_IF_XFORWARDEDFOR || ClientAddress == MAPURL_CLIENT_IF_FORWARDED) return (NULL); return (MsgFor(rqptr,MSG_MAPPING_DENIED_RULE)-1); } /* parse out the leading (IP address) string representing the client */ zptr = (sptr = strbuf) + sizeof(strbuf)-1; while (ISLWS(*cptr)) cptr++; if (MATCH4(cptr,"for=")) cptr += 4; if (*cptr == '\"') for (cptr++; *cptr && *cptr != '\"' && sptr < zptr; *sptr++ = *cptr++); else while (*cptr && *cptr != ',' && !ISLWS(*cptr) && sptr < zptr) *sptr++ = *cptr++; *sptr = '\0'; if (VMSnok (TcpIpStringToAddress (strbuf, &IpAddress))) { if (WATCHING (rqptr, WATCH_MAPPING)) WatchThis (WATCHITM(rqptr), WATCH_MAPPING, "CLIENT address error !AZ !AZ", hptr, strbuf); return (MsgFor(rqptr,MSG_MAPPING_DENIED_RULE)-1); } /* when not multiple client data mapping */ if (!clptr->SetClientAddress) { /* buffer the TCP connection data (see MapUrl_ResetClientData()) */ IPADDRESS_COPY (&clptr->UpstreamIpAddress, &clptr->IpAddress); strcpy (clptr->UpstreamIpAddressString, &clptr->IpAddressString); strcpy (clptr->UpstreamHostName, clptr->Lookup.HostName); clptr->UpstreamHostNameLength = clptr->Lookup.HostNameLength; } /* rewrite the client address data */ clptr->SetClientAddress = ClientAddress; IPADDRESS_COPY (&clptr->IpAddress, &IpAddress); /* recreate a "clean" IP address string from the IP address above */ cptr = TcpIpAddressToString (&IpAddress, 0); strcpy (&clptr->IpAddressString, cptr); strcpy (clptr->Lookup.HostName, cptr); clptr->Lookup.HostNameLength = strlen(cptr); if (WATCHMOD (rqptr, WATCH_MOD_MAPURL)) WatchThis (WATCHITM(rqptr), WATCH_MOD_MAPURL, "!AZ !&I !AZ !AZ -> !&I !AZ !AZ", hptr, &clptr->UpstreamIpAddress, clptr->UpstreamIpAddressString, clptr->UpstreamHostName, &clptr->IpAddress, &clptr->IpAddressString, clptr->Lookup.HostName); if (WATCHING (rqptr, WATCH_MAPPING)) WatchThis (WATCHITM(rqptr), WATCH_MAPPING, "CLIENT !AZ !AZ", hptr, cptr); if (Watch.Category && Watch.Category != WATCH_ONE_SHOT_CAT) WatchFilterClientService (rqptr); return (NULL); } /*****************************************************************************/ /* Undo the client address mapping performed by MapUrl_SetClientAddress() above by simply pointing back using the saved original. */ void MapUrl_ResetClientAddress (REQUEST_STRUCT *rqptr) { /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD_MAPURL)) WatchThis (WATCHITM(rqptr), WATCH_MOD_MAPURL, "MapUrl_ResetClientAddress()"); rqptr->ClientPtr = rqptr->ClientResetPtr; } /*****************************************************************************/ /* Load mapping rules into meta-config structure. */ int MapUrl_ConfigLoad (META_CONFIG **MetaConPtrPtr) { int status; /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD_MAPURL)) WatchThis (WATCHALL, WATCH_MOD_MAPURL, "MapUrl_ConfigLoad()"); status = MetaConLoad (MetaConPtrPtr, v10orPrev10(CONFIG_MAP_FILE_NAME,-1), &MapUrl_ConfigLoadCallBack, true, true); if (*MetaConPtrPtr == MetaGlobalMappingPtr) { /* server startup/reload */ MetaConStartupReport (MetaGlobalMappingPtr, "MAP"); if (VMSnok (status)) exit (status); } return (status); } /*****************************************************************************/ /* Called by MetaConUnload() to free resources allocated during mapping rule configuration. */ MapUrl_ConfigUnload (META_CONFIG *mcptr) { int status; MAPPING_META *mmptr; /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD_MAPURL)) WatchThis (WATCHALL, WATCH_MOD_MAPURL, "MapUrl_ConfigUnload()"); if (mcptr->MappingMetaPtr) { if (mcptr->MappingMetaPtr == MappingMetaPtr) { memset (MappingMetaPtr, 0, sizeof(MAPPING_META)); MappingMetaPtr = NULL; } else VmFree (mcptr->MappingMetaPtr, FI_LI); mcptr->MappingMetaPtr = NULL; } } /*****************************************************************************/ /* Called by MetaConUnload() callback for each line's associated data, basically to check for a regular expression structure and free it if present, then just dispose of the line data itself. */ MapUrl_ConfigUnloadLineData (void *LineDataPtr) { int status; MAP_RULE_META *mrptr; /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD_MAPURL)) WatchThis (WATCHALL, WATCH_MOD_MAPURL, "MapUrl_ConfigUnloadLineData()"); mrptr = (MAP_RULE_META*)LineDataPtr; if (mrptr->RegexPregTemplate.buffer) regfree (&mrptr->RegexPregTemplate); VmFree (mrptr, FI_LI); } /*****************************************************************************/ /* 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 MapUrl_ConfigLoadCallBack (META_CONFIG *mcptr) { static char Ods5Disabled [] = "ODS-5 processing CLI disabled", Ods5Enabled [] = "ODS-5 processing enabled", Ods5NotSupported [] = "ODS-5 not supported", ProblemAcceptLang [] = "Set path \'accept=lang\' parameter problem", ProblemConditional [] = "Conditional problem", ProblemConfused [] = "Cannot understand this one at all", ProblemHostNameLookup [] = "Cannot resolve host name !AZ, !&m", ProblemNameValue [] = "Set path \'name=value\' pair problem", ProblemNotAllowed [] = "Rule cannot be used in [ConfigFile]", ProblemOverflow [] = "Storage overflow", ProblemProtect [] = "Protect path problem", ProblemProxyHeader [] = "Proxy header exceeded maximum", ProblemRegex [] = "Regex: !AZ", ProblemResultPath [] = "Problem with \'result\' path", ProblemResultRequired [] = "Requires a \'result\'", ProblemResultStatus [] = "Rule \'result\' cannot be a status", ProblemRmsSubstitution [] = "RMS substitution character", ProblemSetPath [] = "Set path problem", ProblemSpecifiedWildcardCannot [] = "Cannot use \'specified\' wildcards with rule", ProblemSpecifiedWildcardMix [] = "Mix of \'specified\' and non-\'specified\' wildcards", ProblemSpecifiedWildcardRange [] = "Value of \'specified\' wildcard out-of-range", ProblemTemplateRequired [] = "Requires a \'template\'", ProblemThrottleValues [] = "Successive dependent throttle values must be larger", ProblemWildcardMapping [] = "Wildcard mapping problem", ProblemTooManyWildcard [] = "Too many wildcards"; BOOL AllowedInConfigFile, ConfigProblem, IsCgiPlusScript, PathSet, VirtualServerUnknown; int length, status, ConfigFileIndex, ResultPathOds, RuleType, TemplateWildcardCount, ResultWildcardCount, ResultSpecifiedWildcardCount; unsigned short Length; char *cptr, *sptr, *zptr, *ConditionalPtr, *ResultPtr, *RulePtr, *SetPathPtr, *TemplatePtr; char Name [256], DiskDevice [64+1], Value [1024]; MAPPING_META *mmptr; MAP_RULE_META *mrptr; MAP_SET_META *mrpsptr; METACON_LINE *mclptr; regex_t RegexPreg; /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD_MAPURL)) { WatchThis (WATCHALL, WATCH_MOD_MAPURL, "MapUrl_ConfigLoadCallBack() !&F !&X", &MapUrl_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/reload set the global service pointer */ if (mcptr == MetaGlobalMappingPtr) mmptr = mcptr->MappingMetaPtr = MappingMetaPtr = &MappingMeta; else /* if a report then conjure one up through quantum mechanics */ if (!mcptr->MappingMetaPtr) mmptr = mcptr->MappingMetaPtr = VmGet (sizeof(MAPPING_META)); else /* not the first time through */ mmptr = mcptr->MappingMetaPtr; if (mclptr->Token == METACON_TOKEN_PRE) { /******************/ /* pre-initialize */ /******************/ MapUrlPathOds5 = OdsExtended = false; return (true); } if (mclptr->Token == METACON_TOKEN_POST) { /****************/ /* post-process */ /****************/ /* if global service pointer, during server startup or reload */ if (mcptr == MetaGlobalMappingPtr) { /* if no ODS5 paths then EFS can be disabled */ #ifdef ODS_EXTENDED if (CliOdsExtendedDisabled) { OdsExtended = false; MetaConReport (mcptr, METACON_REPORT_INFORM, Ods5Disabled); } else #endif /* ODS_EXTENDED */ if (CliOdsExtendedEnabled || MapUrlPathOds5) { #ifdef ODS_EXTENDED if (SysInfo.VersionInteger >= 720) { OdsExtended = true; MetaConReport (mcptr, METACON_REPORT_INFORM, Ods5Enabled); } else #endif /* ODS_EXTENDED */ { OdsExtended = false; MetaConReport (mcptr, METACON_REPORT_INFORM, Ods5NotSupported); } } else OdsExtended = false; /* reset the username cache */ MapUserNameCache (NULL, NULL, NULL, NULL); /* initialize the throttled paths */ ThrottleInit (); } return (true); } /***********/ /* process */ /***********/ /* if it's not text/inline then mapping's not interested in it */ if (mclptr->Token != METACON_TOKEN_TEXT && !mclptr->InlineTextPtr) return (true); if (mclptr->InlineTextPtr) cptr = mclptr->InlineTextPtr; else cptr = mclptr->TextPtr; for (sptr = cptr; *sptr; sptr++); /* allocate memory for the structure plus the null terminated strings */ mrptr = (MAP_RULE_META*)VmGet (sizeof(MAP_RULE_META)+(sptr-cptr+1)); /* copy to storage the configuration string */ sptr = &mrptr->Storage; while (*cptr) *sptr++ = *cptr++; *sptr = '\0'; /* point to the MAP_RULE_META */ mrpsptr = &mrptr->mpPathSet; AllowedInConfigFile = ConfigProblem = IsCgiPlusScript = PathSet = false; /********/ /* rule */ /********/ for (cptr = &mrptr->Storage; *cptr && ISLWS(*cptr); cptr++); RulePtr = cptr; if (StringSliceValue (&cptr) <= 0) { MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemConfused); VmFree (mrptr, FI_LI); return (true); } IsCgiPlusScript = false; if (strsame (RulePtr, "EXEC", -1)) RuleType = MAPURL_RULE_EXEC; else if (strsame (RulePtr, "EXEC+", -1)) { RuleType = MAPURL_RULE_EXEC; IsCgiPlusScript = true; } else if (strsame (RulePtr, "FAIL", -1)) { RuleType = MAPURL_RULE_FAIL; AllowedInConfigFile = true; } else if (strsame (RulePtr, "MAP", -1)) { RuleType = MAPURL_RULE_MAP; AllowedInConfigFile = true; } else if (strsame (RulePtr, "PASS", -1)) { RuleType = MAPURL_RULE_PASS; AllowedInConfigFile = true; } else if (strsame (RulePtr, "REDIRECT", -1)) { RuleType = MAPURL_RULE_REDIRECT; AllowedInConfigFile = true; } else if (strsame (RulePtr, "SCRIPT", -1)) RuleType = MAPURL_RULE_SCRIPT; else if (strsame (RulePtr, "SCRIPT+", -1)) { RuleType = MAPURL_RULE_SCRIPT; IsCgiPlusScript = true; } else if (strsame (RulePtr, "SET", -1)) RuleType = MAPURL_RULE_SET; else if (strsame (RulePtr, "UXEC", -1) || strsame (RulePtr, "UEXEC", -1)) RuleType = MAPURL_RULE_UXEC; else if (strsame (RulePtr, "UXEC+", -1) || strsame (RulePtr, "UEXEC+", -1)) { RuleType = MAPURL_RULE_UXEC; IsCgiPlusScript = true; } else if (strsame (RulePtr, "USER", -1)) RuleType = MAPURL_RULE_USER; else if (strsame (RulePtr, "PROTECT", -1)) { RuleType = MAPURL_RULE_PROTECT; AllowedInConfigFile = true; } else { MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemConfused); VmFree (mrptr, FI_LI); return (true); } /* ensure a conditional is not mistaken for a missing template */ if (!*cptr || *cptr == '[' || SAME2(cptr,'![')) { /* there must be a "template" to map from */ MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemTemplateRequired); VmFree (mrptr, FI_LI); return (true); } /* extract template (the path the rule is applied to) */ TemplatePtr = cptr; if (StringSliceValue (&cptr) <= 0) { MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemTemplateRequired); VmFree (mrptr, FI_LI); return (true); } /* note the position of an empty string in case none of these! */ ResultPtr = SetPathPtr = ConditionalPtr = RulePtr + strlen(RulePtr); if (RuleType != MAPURL_RULE_SET) { /*********************/ /* path mapping rule */ /*********************/ /* if this doesn't look like a conditional */ if (*cptr && *cptr != '[' && !SAME2(cptr,'![')) { ResultPtr = cptr; if (StringSliceValue (&cptr) <= 0) { MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemConfused); VmFree (mrptr, FI_LI); return (true); } } } /* if it doesn't look like a conditional then assume it's SET directives */ if (*cptr && *cptr != '[' && !SAME2(cptr,'![')) { /****************/ /* path SETings */ /****************/ while (*cptr) { /* break if this looks like a conditional */ if (*cptr == '[' || SAME2(cptr,'![')) break; SetPathPtr = cptr; if ((length = StringSliceValue (&cptr)) <= 0) { MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemSetPath); VmFree (mrptr, FI_LI); return (true); } PathSet = true; if (strsame (SetPathPtr, "ACCEPT=LANG", -1)) mrpsptr->AcceptLangChar = '_'; else if (strsame (SetPathPtr, "NOACCEPT=LANG", -1) || strsame (SetPathPtr, "ACCEPT=NOLANG", -1)) mrpsptr->NoAcceptLang = true; else if (strsame (SetPathPtr, "ACCEPT=LANG=", 12)) { mrpsptr->AcceptLangChar = '_'; sptr = SetPathPtr + 12; if (*sptr == '(') sptr++; while (*sptr) { if (strsame (sptr, "CHAR=", 5)) { mrpsptr->AcceptLangChar = sptr[5]; sptr += 6; } else if (strsame (sptr, "DEFAULT=", 8)) { sptr += 8; mrpsptr->AcceptLangPtr = sptr; while (*sptr && *sptr != ',' && *sptr != ')') sptr++; if (*sptr) *sptr++ = '\0'; mrpsptr->AcceptLangLength = strlen(mrpsptr->AcceptLangPtr); } else if (strsame (sptr, "VARIANT=", 8)) { sptr += 8; if (strsame (sptr, "NAME", 4)) mrpsptr->AcceptLangTypeVariant = false; else if (strsame (sptr, "TYPE", 4)) mrpsptr->AcceptLangTypeVariant = true; else { MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemAcceptLang); VmFree (mrptr, FI_LI); return (true); } while (*sptr && *sptr != ',' && *sptr != ')') sptr++; } else { MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemAcceptLang); VmFree (mrptr, FI_LI); return (true); } if (*sptr == ',' || *sptr == ')') sptr++; } if (mrpsptr->AcceptLangChar != '_' && mrpsptr->AcceptLangChar != '-' && mrpsptr->AcceptLangChar != '.' && mrpsptr->AcceptLangChar != '$') { MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemAcceptLang); VmFree (mrptr, FI_LI); return (true); } /* check if there is a wildcard file type */ for (sptr = TemplatePtr; *sptr; sptr++); while (sptr > TemplatePtr && *sptr != '.' && *sptr != '/') sptr--; if (*sptr == '.') mrpsptr->AcceptLangWildcard = true; } else if (strsame (SetPathPtr, "ALERT", -1)) mrpsptr->Alert = MAPURL_PATH_ALERT_END; else if (strsame (SetPathPtr, "ALERT=END", -1)) mrpsptr->Alert = MAPURL_PATH_ALERT_END; else if (strsame (SetPathPtr, "ALERT=AUTH", -1)) mrpsptr->Alert = MAPURL_PATH_ALERT_AUTH; else if (strsame (SetPathPtr, "ALERT=MAP", -1)) mrpsptr->Alert = MAPURL_PATH_ALERT_MAP; else if (strsame (SetPathPtr, "ALERT=", 6) && isdigit(SetPathPtr[6])) { mrpsptr->Alert = atoi(SetPathPtr+6); if (!mrpsptr->Alert) mrpsptr->NoAlert = true; } else if (strsame (SetPathPtr, "NOALERT", -1)) mrpsptr->NoAlert = true; else if (strsame (SetPathPtr, "AUTH=ALL", -1)) mrpsptr->AuthAll = true; else if (strsame (SetPathPtr, "NOAUTH=ALL", -1)) mrpsptr->NoAuthAll = true; else if (strsame (SetPathPtr, "AUTH=MAPPED", -1)) mrpsptr->AuthMapped = true; else if (strsame (SetPathPtr, "NOAUTH=MAPPED", -1) || strsame (SetPathPtr, "AUTH=REQUEST", -1)) mrpsptr->NoAuthMapped = true; else if (strsame (SetPathPtr, "AUTH=ONCE", -1) || strsame (SetPathPtr, "AUTHONCE", -1)) mrpsptr->AuthOnce = true; else if (strsame (SetPathPtr, "AUTH=NOONCE", -1) || strsame (SetPathPtr, "NOAUTH=ONCE", -1) || strsame (SetPathPtr, "NOAUTHONCE", -1)) mrpsptr->NoAuthOnce = true; else if (strsame (SetPathPtr, "AUTH=REVALIDATE=", 16)) mrpsptr->AuthRevalidateTimeout = MetaConSetSeconds (mcptr, SetPathPtr+16, 60); else if (strsame (SetPathPtr, "AUTH=SYSUAF=PWDEXPURL=", 22)) { mrpsptr->AuthSysUafPwdExpUrlPtr = SetPathPtr + 22; mrpsptr->AuthSysUafPwdExpUrlLength = strlen(mrpsptr->AuthSysUafPwdExpUrlPtr); } else if (strsame (SetPathPtr, "CACHE", -1)) mrpsptr->CacheSetting = mrpsptr->Cache = true; else if (strsame (SetPathPtr, "NOCACHE", -1) || strsame (SetPathPtr, "CACHE=NONE", -1)) mrpsptr->CacheSetting = mrpsptr->NoCache = true; else if (strsame (SetPathPtr, "CACHE=CGI", -1)) mrpsptr->CacheSetting = mrpsptr->CacheCGI = true; else if (strsame (SetPathPtr, "CACHE=NOCGI", -1)) mrpsptr->CacheSetting = mrpsptr->CacheNoCGI = true; else if (strsame (SetPathPtr, "CACHE=COOKIE", -1)) mrpsptr->CacheSetting = mrpsptr->CacheCookie = true; else if (strsame (SetPathPtr, "CACHE=NOCOOKIE", -1)) mrpsptr->CacheSetting = mrpsptr->CacheNoCookie = true; else if (strsame (SetPathPtr, "CACHE=FILE", -1)) mrpsptr->CacheSetting = mrpsptr->CacheFile = true; else if (strsame (SetPathPtr, "CACHE=NOFILE", -1)) mrpsptr->CacheSetting = mrpsptr->CacheNoFile = true; else if (strsame (SetPathPtr, "CACHE=NET", -1)) mrpsptr->CacheSetting = mrpsptr->CacheNet = true; else if (strsame (SetPathPtr, "CACHE=NONET", -1)) mrpsptr->CacheSetting = mrpsptr->CacheNoNet = true; else if (strsame (SetPathPtr, "CACHE=NPH", -1)) mrpsptr->CacheSetting = mrpsptr->CacheNPH = true; else if (strsame (SetPathPtr, "CACHE=NONPH", -1)) mrpsptr->CacheSetting = mrpsptr->CacheNoNPH = true; else if (strsame (SetPathPtr, "CACHE=PERM", 10)) mrpsptr->CacheSetting = mrpsptr->CachePermanent = true; else if (strsame (SetPathPtr, "CACHE=NOPERM", 12)) mrpsptr->CacheSetting = mrpsptr->CacheNoPermanent = true; else if (strsame (SetPathPtr, "CACHE=QUERY", -1)) mrpsptr->CacheSetting = mrpsptr->CacheQuery = true; else if (strsame (SetPathPtr, "CACHE=NOQUERY", -1)) mrpsptr->CacheSetting = mrpsptr->CacheNoQuery = true; else if (strsame (SetPathPtr, "CACHE=SCRIPT", -1)) mrpsptr->CacheSetting = mrpsptr->CacheScript = true; else if (strsame (SetPathPtr, "CACHE=NOSCRIPT", -1)) mrpsptr->CacheSetting = mrpsptr->CacheNoScript = true; else if (strsame (SetPathPtr, "CACHE=SSI", -1)) mrpsptr->CacheSetting = mrpsptr->CacheSSI = true; else if (strsame (SetPathPtr, "CACHE=NOSSI", -1)) mrpsptr->CacheSetting = mrpsptr->CacheNoSSI = true; else if (strsame (SetPathPtr, "CACHE=EXPIRES=", 14)) { sptr = SetPathPtr + 14; if (strsame (sptr, "DAY", -1)) mrpsptr->CacheExpiresAfter = CACHE_EXPIRES_DAY; else if (strsame (sptr, "HOUR", -1)) mrpsptr->CacheExpiresAfter = CACHE_EXPIRES_HOUR; else if (strsame (sptr, "MINUTE", -1)) mrpsptr->CacheExpiresAfter = CACHE_EXPIRES_MINUTE; else if (strsame (sptr, "0", -1)) mrpsptr->CacheExpiresAfter = CACHE_EXPIRES_NONE; else mrpsptr->CacheExpiresAfter = MetaConSetSeconds (mcptr, sptr, 1); mrpsptr->CacheSetting = true; } else if (strsame (SetPathPtr, "CACHE=GUARD=", 12)) { sptr = SetPathPtr + 12; mrpsptr->CacheGuardSeconds = MetaConSetSeconds (mcptr, sptr, 1); /* negative 1 indicates to revert to configuration maximum */ if (!mrpsptr->CacheGuardSeconds) mrpsptr->CacheGuardSeconds = -1; mrpsptr->CacheSetting = true; } else if (strsame (SetPathPtr, "CACHE=MAX=", 10)) { sptr = SetPathPtr + 10; mrpsptr->CacheMaxKBytes = atoi(sptr); while (isdigit(*sptr)) sptr++; if (strsame (sptr, "MB", 2)) mrpsptr->CacheMaxKBytes = mrpsptr->CacheMaxKBytes << 10; /* negative 1 indicates to revert to configuration maximum */ if (!mrpsptr->CacheMaxKBytes) mrpsptr->CacheMaxKBytes = -1; mrpsptr->CacheSetting = true; } else if (strsame (SetPathPtr, "CGI=PREFIX=", 11) || strsame (SetPathPtr, "CGIPREFIX=", 10)) { mrpsptr->CgiPrefixPtr = SetPathPtr + 10; if (*mrpsptr->CgiPrefixPtr == '=') mrpsptr->CgiPrefixPtr++; mrpsptr->CgiPrefixLength = strlen(mrpsptr->CgiPrefixPtr); } else if (strsame (SetPathPtr, "CGIPLUSIN=EOF", -1)) mrpsptr->CgiPlusInWriteof = true; else if (strsame (SetPathPtr, "CGIPLUSIN=NOEOF", -1) || strsame (SetPathPtr, "NOCGIPLUSIN=EOF", -1)) mrpsptr->CgiPlusInNoWriteof = true; else if (strsame (SetPathPtr, "CGIPLUSIN=CC=NONE", -1)) strcpy (mrpsptr->CgiPlusInCC, "\0**"); else if (strsame (SetPathPtr, "CGIPLUSIN=CC=LF", -1)) strcpy (mrpsptr->CgiPlusInCC, "\n\0*"); else if (strsame (SetPathPtr, "CGIPLUSIN=CC=CR", -1)) strcpy (mrpsptr->CgiPlusInCC, "\r\0*"); else if (strsame (SetPathPtr, "CGIPLUSIN=CC=CRLF", -1)) strcpy (mrpsptr->CgiPlusInCC, "\r\n\0"); else if (strsame (SetPathPtr, "CHARSET=", 8)) { mrpsptr->CharsetPtr = SetPathPtr + 8; mrpsptr->CharsetLength = strlen(mrpsptr->CharsetPtr); AllowedInConfigFile = true; } else if (strsame (SetPathPtr, "CLIENT=FORWARDED", -1)) mrpsptr->ClientAddress = MAPURL_CLIENT_FORWARDED; else if (strsame (SetPathPtr, "CLIENT=IF=FORWARDED", -1)) mrpsptr->ClientAddress = MAPURL_CLIENT_IF_FORWARDED; else if (strsame (SetPathPtr, "CLIENT=LITERAL=", 15)) { /* really just for ease of testing */ mrpsptr->ClientAddress = MAPURL_CLIENT_LITERAL; mrpsptr->ClientAddressLiteralPtr = SetPathPtr + 15; mrpsptr->ClientAddressLiteralLength = strlen(mrpsptr->ClientAddressLiteralPtr); } else if (strsame (SetPathPtr, "CLIENT=XFORWARDEDFOR", -1)) mrpsptr->ClientAddress = MAPURL_CLIENT_XFORWARDEDFOR; else if (strsame (SetPathPtr, "CLIENT=IF=XFORWARDEDFOR", -1)) mrpsptr->ClientAddress = MAPURL_CLIENT_IF_XFORWARDEDFOR; else if (strsame (SetPathPtr, "CLIENT=RESET", -1)) mrpsptr->ClientAddress = MAPURL_CLIENT_RESET; else if (strsame (SetPathPtr, "CONTENT=", 8)) { mrpsptr->ContentTypePtr = SetPathPtr + 8; mrpsptr->ContentTypeLength = strlen(mrpsptr->ContentTypePtr); AllowedInConfigFile = true; } else if (strsame (SetPathPtr, "CONTENT-TYPE=", 13)) { /* just a synonym for "content=", bet someone uses it! */ mrpsptr->ContentTypePtr = SetPathPtr + 13; mrpsptr->ContentTypeLength = strlen(mrpsptr->ContentTypePtr); AllowedInConfigFile = true; } else if (strsame (SetPathPtr, "CSS=", 4)) { mrpsptr->StyleSheetPtr = SetPathPtr + 4; mrpsptr->StyleSheetLength = strlen(mrpsptr->StyleSheetPtr); } else if (strsame (SetPathPtr, "CORS=AGE=", 9)) { sptr = SetPathPtr + 9; mrpsptr->CorsMaxAge = MetaConSetSeconds (mcptr, sptr, 1); /* negative 1 indicates to revert to configuration maximum */ if (!mrpsptr->CorsMaxAge) mrpsptr->CorsMaxAge = -1; } else if (strsame (SetPathPtr, "CORS=CRED=TRUE", -1) || strsame (SetPathPtr, "CORS=CRED=YES", -1)) mrpsptr->CorsAllowCredentials = true; else if (strsame (SetPathPtr, "CORS=CRED=FALSE", -1) || strsame (SetPathPtr, "CORS=CRED=NO", -1)) mrpsptr->CorsNoAllowCredentials = true; else if (strsame (SetPathPtr, "CORS=EXPOSE=", 12)) { mrpsptr->CorsExposeHeadersPtr = SetPathPtr + 12; mrpsptr->CorsExposeHeadersLength = strlen(mrpsptr->CorsExposeHeadersPtr); } else if (strsame (SetPathPtr, "CORS=HEADERS=", 13)) { mrpsptr->CorsAllowHeadersPtr = SetPathPtr + 13; mrpsptr->CorsAllowHeadersLength = strlen(mrpsptr->CorsAllowHeadersPtr); } else if (strsame (SetPathPtr, "CORS=METHODS=", 13)) { mrpsptr->CorsAllowMethodsPtr = SetPathPtr + 13; mrpsptr->CorsAllowMethodsLength = strlen(mrpsptr->CorsAllowMethodsPtr); } else if (strsame (SetPathPtr, "CORS=ORIGIN=", 12)) { mrpsptr->CorsAllowOriginPtr = SetPathPtr + 12; mrpsptr->CorsAllowOriginLength = strlen(mrpsptr->CorsAllowOriginPtr); } else if (strsame (SetPathPtr, "DICT=", 5)) mrpsptr->DictionaryPtr = SetPathPtr + 5; else if (strsame (SetPathPtr, "DIR=ACCESS=SELECTIVE", -1)) mrpsptr->DirAccessSelective = true; else if (strsame (SetPathPtr, "DIR=ACCESS", -1)) mrpsptr->DirAccess = true; else if (strsame (SetPathPtr, "DIR=NOACCESS", -1)) mrpsptr->DirNoAccess = true; else if (strsame (SetPathPtr, "DIR=CHARSET=", 12)) { mrpsptr->DirCharsetPtr = SetPathPtr + 12; mrpsptr->DirCharsetLength = strlen(mrpsptr->DirCharsetPtr); } else if (strsame (SetPathPtr, "DIR=DELIMIT", -1) || strsame (SetPathPtr, "DIR=DELIMIT=BOTH", -1)) mrpsptr->DirDelimit = MAPURL_DIR_DELIMIT_BOTH; else if (strsame (SetPathPtr, "DIR=DELIMIT=HEADER", -1)) mrpsptr->DirDelimit = MAPURL_DIR_DELIMIT_HEADER; else if (strsame (SetPathPtr, "DIR=DELIMIT=FOOTER", -1)) mrpsptr->DirDelimit = MAPURL_DIR_DELIMIT_FOOTER; else if (strsame (SetPathPtr, "DIR=DELIMIT=NONE", -1)) mrpsptr->DirDelimit = MAPURL_DIR_DELIMIT_NONE; else if (strsame (SetPathPtr, "DIR=FONT", -1) || strsame (SetPathPtr, "DIR=font=MONOSPACE", -1)) mrpsptr->DirFont = MAPURL_DIR_FONT_MONOSPACE; else if (strsame (SetPathPtr, "DIR=font=INHERIT", -1)) mrpsptr->DirFont = MAPURL_DIR_FONT_INHERIT; else if (strsame (SetPathPtr, "DIR=LAYOUT=", 11)) { mrpsptr->IndexPtr = SetPathPtr + 11; mrpsptr->IndexLength = strlen(mrpsptr->IndexPtr); } else if (strsame (SetPathPtr, "DIR=ILINK", -1)) mrpsptr->DirIconLink = true; else if (strsame (SetPathPtr, "DIR=NOILINK", -1)) mrpsptr->DirNoIconLink = true; else if (strsame (SetPathPtr, "DIR=IMPLIEDWILDCARD", -1)) mrpsptr->DirImpliedWildcard = true; else if (strsame (SetPathPtr, "DIR=NOIMPLIEDWILDCARD", -1)) mrpsptr->DirNoImpliedWildcard = true; else if (strsame (SetPathPtr, "DIR=SORT=", 9)) { mrpsptr->DirSort[0] = TOUP(SetPathPtr[9]); mrpsptr->DirSort[1] = SetPathPtr[10]; } else if (strsame (SetPathPtr, "DIR=STYLE", -1) || strsame (SetPathPtr, "DIR=style=DEFAULT", -1)) mrpsptr->DirStyle = MAPURL_DIR_STYLE_DEFAULT; else if (strsame (SetPathPtr, "DIR=style=DEFAULT2", -1)) mrpsptr->DirStyle = MAPURL_DIR_STYLE_DEFAULT2; else if (strsame (SetPathPtr, "DIR=style=ANCHOR", -1)) mrpsptr->DirStyle = MAPURL_DIR_STYLE_ANCHOR; else if (strsame (SetPathPtr, "DIR=style=ANCHOR2", -1)) mrpsptr->DirStyle = MAPURL_DIR_STYLE_ANCHOR2; else if (strsame (SetPathPtr, "DIR=style=HTDIR", -1)) mrpsptr->DirStyle = MAPURL_DIR_STYLE_HTDIR; else if (strsame (SetPathPtr, "DIR=style=HTDIR2", -1)) mrpsptr->DirStyle = MAPURL_DIR_STYLE_HTDIR2; else if (strsame (SetPathPtr, "DIR=style=ORIGINAL", -1)) mrpsptr->DirStyle = MAPURL_DIR_STYLE_ORIGINAL; else if (strsame (SetPathPtr, "DIR=style=ORIGINAL2", -1)) mrpsptr->DirStyle = MAPURL_DIR_STYLE_ORIGINAL2; else if (strsame (SetPathPtr, "DIR=style=SORT", -1)) mrpsptr->DirStyle = MAPURL_DIR_STYLE_SORT; else if (strsame (SetPathPtr, "DIR=style=SORT2", -1)) mrpsptr->DirStyle = MAPURL_DIR_STYLE_SORT2; else if (strsame (SetPathPtr, "DIR=TARGET=", 11)) { mrpsptr->DirTargetPtr = SetPathPtr + 11; mrpsptr->DirTargetLength = strlen(mrpsptr->DirTargetPtr); } else if (strsame (SetPathPtr, "DIR=title=THIS=", 15)) { mrpsptr->DirTitle = MAPURL_DIR_TITLE_THIS; mrpsptr->DirTitlePtr = SetPathPtr + 15; mrpsptr->DirTitleLength = strlen(mrpsptr->DirTitlePtr); } else if (strsame (SetPathPtr, "DIR=title=DEFAULT", -1)) mrpsptr->DirTitle = MAPURL_DIR_TITLE_DEFAULT; else if (strsame (SetPathPtr, "DIR=title=OWNER", -1)) mrpsptr->DirTitle = MAPURL_DIR_TITLE_OWNER; else if (strsame (SetPathPtr, "DIR=title=REMOTE",- 1)) mrpsptr->DirTitle = MAPURL_DIR_TITLE_REMOTE; else if (strsame (SetPathPtr, "DIR=title=0", -1)) mrpsptr->DirTitle = MAPURL_DIR_TITLE_NONE; else if (strsame (SetPathPtr, "DIR=title=", 10) && isdigit(*(SetPathPtr+10))) mrpsptr->DirTitle = atol(SetPathPtr+10); else if (strsame (SetPathPtr, "DIR=THESE=", 10)) { mrpsptr->DirThesePtr = SetPathPtr + 10; mrpsptr->DirTheseLength = strlen(mrpsptr->DirThesePtr); } else if (strsame (SetPathPtr, "DIR=VERSIONS=", 13)) { sptr = SetPathPtr + 13; if (*sptr == '*') mrpsptr->DirVersionsOf = 65536; else if (*sptr == '0') /* negative one means reset to zero */ mrpsptr->DirVersionsOf = -1; else mrpsptr->DirVersionsOf = atoi(sptr); } else if (strsame (SetPathPtr, "DIR=WILDCARD", -1)) mrpsptr->DirWildcard = true; else if (strsame (SetPathPtr, "DIR=NOWILDCARD", -1)) mrpsptr->DirNoWildcard = true; else if (strsame (SetPathPtr, "NOHTML", 6)) { mrpsptr->NoHtmlEquals = true; AllowedInConfigFile = true; } else if (strsame (SetPathPtr, "HTML=BODYTAG=", 13)) { mrpsptr->HtmlBodyTagPtr = SetPathPtr + 13; mrpsptr->HtmlBodyTagLength = strlen(mrpsptr->HtmlBodyTagPtr); AllowedInConfigFile = true; } else if (strsame (SetPathPtr, "HTML=FOOTER=", 12)) { mrpsptr->HtmlFooterPtr = SetPathPtr + 12; mrpsptr->HtmlFooterLength = strlen(mrpsptr->HtmlFooterPtr); AllowedInConfigFile = true; } else if (strsame (SetPathPtr, "HTML=FOOTERTAG=", 15)) { mrpsptr->HtmlFooterTagPtr = SetPathPtr + 15; mrpsptr->HtmlFooterTagLength = strlen(mrpsptr->HtmlFooterTagPtr); AllowedInConfigFile = true; } else if (strsame (SetPathPtr, "HTML=HEADER=", 12)) { mrpsptr->HtmlHeaderPtr = SetPathPtr + 12; mrpsptr->HtmlHeaderLength = strlen(mrpsptr->HtmlHeaderPtr); AllowedInConfigFile = true; } else if (strsame (SetPathPtr, "HTML=HEADERTAG=", 15)) { mrpsptr->HtmlHeaderTagPtr = SetPathPtr + 15; mrpsptr->HtmlHeaderTagLength = strlen(mrpsptr->HtmlHeaderTagPtr); AllowedInConfigFile = true; } else if (strsame (SetPathPtr, "HTTP2=PROTOCOL=1.1", -1)) mrpsptr->Http2ToHttp11 = true; else if (strsame (SetPathPtr, "HTTP2=STREAMS=MAX=", 18)) mrpsptr->Http2MaxStreams = atoi(SetPathPtr+18); else if (strsame (SetPathPtr, "HTTP2=WRITE=HIGH", -1)) mrpsptr->Http2WriteQueue = HTTP2_WRITE_QUEUE_HIGH; else if (strsame (SetPathPtr, "HTTP2=WRITE=NORMAL", -1)) mrpsptr->Http2WriteQueue = HTTP2_WRITE_QUEUE_NORMAL; else if (strsame (SetPathPtr, "HTTP2=WRITE=LOW", -1)) mrpsptr->Http2WriteQueue = HTTP2_WRITE_QUEUE_LOW; else if (strsame (SetPathPtr, "HTTP2=SEND=GOAWAY", 17)) { /* the optional error code is incremented to allow for zero */ if (*(sptr = SetPathPtr + 17) == '=') mrpsptr->Http2SendGoAway = atoi(sptr+1) + 1; else mrpsptr->Http2SendGoAway = 1; } else if (strsame (SetPathPtr, "HTTP2=SEND=PING", -1)) mrpsptr->Http2SendPing = true; else if (strsame (SetPathPtr, "HTTP2=SEND=RESET", 16)) { /* the optional error code is incremented to allow for zero */ if (*(sptr = SetPathPtr + 16) == '=') mrpsptr->Http2SendReset = atoi(sptr+1) + 1; else mrpsptr->Http2SendReset = 1; } else if (strsame (SetPathPtr, "HTTP=ACCEPT-CHARSET=", 20)) { mrpsptr->HttpAcceptCharsetPtr = SetPathPtr + 20; mrpsptr->HttpAcceptCharsetLength = strlen(mrpsptr->HttpAcceptCharsetPtr); AllowedInConfigFile = true; } else if (strsame (SetPathPtr, "HTTP=ACCEPT-LANGUAGE=", 21)) { mrpsptr->HttpAcceptLangPtr = SetPathPtr + 21; mrpsptr->HttpAcceptLangLength = strlen(mrpsptr->HttpAcceptLangPtr); AllowedInConfigFile = true; } else if (strsame (SetPathPtr, "INDEX=", 6)) { mrpsptr->IndexPtr = SetPathPtr + 6; mrpsptr->IndexLength = strlen(mrpsptr->IndexPtr); AllowedInConfigFile = true; } else if (strsame (SetPathPtr, "EXPIRED", -1)) { mrpsptr->Expired = true; AllowedInConfigFile = true; } else if (strsame (SetPathPtr, "NOEXPIRED", -1)) { mrpsptr->NoExpired = true; AllowedInConfigFile = true; } else if (strsame (SetPathPtr, "LOG", -1)) mrpsptr->Log = true; else if (strsame (SetPathPtr, "NOLOG", -1)) mrpsptr->NoLog = true; else if (strsame (SetPathPtr, "MAP=ELLIPSIS", -1)) mrpsptr->MapEllipsis = true; else if (strsame (SetPathPtr, "NOMAP=ELLIPSIS", -1) || strsame (SetPathPtr, "MAP=NOELLIPSIS", -1)) mrpsptr->NoMapEllipsis = false; else if (strsame (SetPathPtr, "MAPEMPTY", -1) || strsame (SetPathPtr, "MAP=EMPTY", -1)) mrpsptr->MapEmpty = true; else if (strsame (SetPathPtr, "NOMAPEMPTY", -1) || strsame (SetPathPtr, "NOMAP=EMPTY", -1) || strsame (SetPathPtr, "MAP=NONEMPTY", -1)) mrpsptr->MapNonEmpty = true; else if (strsame (SetPathPtr, "MAP=METHOD", -1)) mrpsptr->MapExtensionMethod = true; else if (strsame (SetPathPtr, "MAP=NOMETHOD", -1) || strsame (SetPathPtr, "NOMAP=METHOD", -1)) mrpsptr->NoMapExtensionMethod = true; else if (strsame (SetPathPtr, "MAP=ONCE", -1) || strsame (SetPathPtr, "MAPONCE", -1)) mrpsptr->MapOnce = true; else if (strsame (SetPathPtr, "MAP=NOONCE", -1) || strsame (SetPathPtr, "NOMAP=ONCE", -1) || strsame (SetPathPtr, "NOMAPONCE", -1)) mrpsptr->NoMapOnce = true; else if (strsame (SetPathPtr, "MAP=RESTART", -1)) mrpsptr->MapRestart = true; else if (strsame (SetPathPtr, "MAP=ROOT=", 9)) { mrpsptr->MapRootPtr = SetPathPtr + 9; mrpsptr->MapRootLength = strlen(mrpsptr->MapRootPtr); } else if (strsame (SetPathPtr, "MAP=SET=REQUEST", -1)) mrpsptr->MapSetRequest = true; else if (strsame (SetPathPtr, "NOMAP=SET=REQUEST", -1) || strsame (SetPathPtr, "MAP=SET=NOREQUEST", -1)) mrpsptr->MapSetNoRequest = true; else if (strsame (SetPathPtr, "MAP=SET=IGNORE", -1)) mrpsptr->MapSetIgnore = true; else if (strsame (SetPathPtr, "NOMAP=SET=IGNORE", -1) || strsame (SetPathPtr, "MAP=SET=NOIGNORE", -1)) mrpsptr->MapSetNoIgnore = true; else if (strsame (SetPathPtr, "MAP=URI", -1)) mrpsptr->MapUri = true; else if (strsame (SetPathPtr, "NOTEPAD=", 8)) mrpsptr->NotePadPtr = SetPathPtr + 8; else if (strsame (SetPathPtr, "ODS=0", -1) || strsame (SetPathPtr, "NOODS", -1)) mrpsptr->PathOds = MAPURL_PATH_ODS_0; else if (strsame (SetPathPtr, "ODS=2", -1) || strsame (SetPathPtr, "ODS-2", -1)) mrpsptr->PathOds = MAPURL_PATH_ODS_2; else if (strsame (SetPathPtr, "ODS=5", -1) || strsame (SetPathPtr, "ODS-5", -1)) { mrpsptr->PathOds = MAPURL_PATH_ODS_5; #ifdef ODS_EXTENDED /* indicate that at least one mapping is set ODS-5 */ MapUrlPathOds5 = true; #endif /* ODS_EXTENDED */ } else if (strsame (SetPathPtr, "ODS=ADS", -1)) mrpsptr->PathOds = MAPURL_PATH_ODS_ADS; else if (strsame (SetPathPtr, "ODS=PWK", -1)) mrpsptr->PathOds = MAPURL_PATH_ODS_PWK; else if (strsame (SetPathPtr, "ODS=SMB", -1)) mrpsptr->PathOds = MAPURL_PATH_ODS_SMB; else if (strsame (SetPathPtr, "ODS=SRI", -1)) mrpsptr->PathOds = MAPURL_PATH_ODS_SRI; else if (strsame (SetPathPtr, "ODS=NAME=8BIT", -1)) mrpsptr->OdsName = MAPURL_ODS_8BIT; else if (strsame (SetPathPtr, "ODS=NAME=UTF8", -1)) mrpsptr->OdsName = MAPURL_ODS_UTF8; else if (strsame (SetPathPtr, "ODS=NAME=DEFAULT", -1)) mrpsptr->OdsName = MAPURL_ODS_DEFAULT; else if (strsame (SetPathPtr, "PROFILE", -1)) mrpsptr->Profile = true; else if (strsame (SetPathPtr, "NOPROFILE", -1)) mrpsptr->NoProfile = true; else if (strsame (SetPathPtr, "PROXY=AFFINITY", 14)) mrpsptr->ProxyAffinity = true; else if (strsame (SetPathPtr, "PROXY=NOAFFINITY", 16) || strsame (SetPathPtr, "NOPROXY=AFFINITY", 16)) mrpsptr->ProxyNoAffinity = true; else if (strsame (SetPathPtr, "PROXY=BIND=", 11)) { mrpsptr->ProxyBindIpAddressPtr = SetPathPtr + 11; mrpsptr->ProxyBindIpAddressLength = strlen(mrpsptr->ProxyBindIpAddressPtr); } else if (strsame (SetPathPtr, "PROXY=CHAIN=CRED=", 17)) { mrpsptr->ProxyChainCredPtr = SetPathPtr + 17; mrpsptr->ProxyChainCredLength = strlen(mrpsptr->ProxyChainCredPtr); } else if (strsame (SetPathPtr, "PROXY=CHAIN=", 12)) { mrpsptr->ProxyChainHostPortPtr = SetPathPtr + 12; mrpsptr->ProxyChainHostPortLength = strlen(mrpsptr->ProxyChainHostPortPtr); } else if (strsame (SetPathPtr, "PROXY=NOFORWARDED", -1)) mrpsptr->ProxyForwardedBy = PROXY_FORWARDED_NONE; else if (strsame (SetPathPtr, "PROXY=FORWARDED", -1) || strsame (SetPathPtr, "PROXY=FORWARDED=BY", -1)) mrpsptr->ProxyForwardedBy = PROXY_FORWARDED_BY; else if (strsame (SetPathPtr, "PROXY=FORWARDED=FOR", -1)) mrpsptr->ProxyForwardedBy = PROXY_FORWARDED_FOR; else if (strsame (SetPathPtr, "PROXY=FORWARDED=ADDRESS", -1)) mrpsptr->ProxyForwardedBy = PROXY_FORWARDED_ADDRESS; else if (strsame (SetPathPtr, "PROXY=NOXFORWARDEDFOR", -1)) mrpsptr->ProxyXForwardedFor = PROXY_XFORWARDEDFOR_NONE; else if (strsame (SetPathPtr, "PROXY=XFORWARDEDFOR", -1) || strsame (SetPathPtr, "PROXY=XFORWARDEDFOR=ENABLED", -1)) mrpsptr->ProxyXForwardedFor = PROXY_XFORWARDEDFOR_ENABLED; else if (strsame (SetPathPtr, "PROXY=XFORWARDEDFOR=ADDRESS", -1)) mrpsptr->ProxyXForwardedFor = PROXY_XFORWARDEDFOR_ADDRESS; else if (strsame (SetPathPtr, "PROXY=XFORWARDEDFOR=UNKNOWN", -1)) mrpsptr->ProxyXForwardedFor = PROXY_XFORWARDEDFOR_UNKNOWN; else if (strsame (SetPathPtr, "PROXY=HEADER=", 13)) { if (mrpsptr->ProxyHeaderCount < MAPURL_PROXY_HEADER_MAX) mrpsptr->ProxyHeader[mrpsptr->ProxyHeaderCount++] = SetPathPtr + 13; else MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemProxyHeader); } else if (strsame (SetPathPtr, "PROXY=REVERSE=LOCATION=", 23)) { mrpsptr->ProxyReverseLocationPtr = SetPathPtr + 23; mrpsptr->ProxyReverseLocationLength = strlen(mrpsptr->ProxyReverseLocationPtr); } else if (strsame (SetPathPtr, "PROXY=REVERSE=VERIFY", -1)) mrpsptr->ProxyReverseVerify = true; else if (strsame (SetPathPtr, "PROXY=REVERSE=NOVERIFY", -1) || strsame (SetPathPtr, "NOPROXY=REVERSE=VERIFY", -1)) mrpsptr->NoProxyReverseVerify = true; else if (strsame (SetPathPtr, "PROXY=REVERSE=AUTH", -1)) mrpsptr->ProxyReverseAuthHeader = true; else if (strsame (SetPathPtr, "PROXY=REVERSE=NOAUTH", -1) || strsame (SetPathPtr, "NOPROXY=REVERSE=AUTH", -1)) mrpsptr->NoProxyReverseAuthHeader = true; else if (strsame (SetPathPtr, "PROXY=TUNNEL=REQUEST=", 21)) { mrpsptr->ProxyTunnelRequestPtr = SetPathPtr + 21; mrpsptr->ProxyTunnelRequestLength = strlen(mrpsptr->ProxyTunnelRequestPtr); } else if (strsame (SetPathPtr, "PROXY=UNKNOWN", -1)) mrpsptr->ProxyUnknownRequestFields = true; else if (strsame (SetPathPtr, "PROXY=NOUNKNOWN", -1) || strsame (SetPathPtr, "NOPROXY=UNKNOWN", -1)) mrpsptr->NoProxyUnknownRequestFields = true; else if (strsame (SetPathPtr, "PUT=RFM=FIX512", -1)) mrpsptr->PutRFM = PUT_RFM_FIX512; else if (strsame (SetPathPtr, "PUT=RFM=STM", -1)) mrpsptr->PutRFM = PUT_RFM_STM; else if (strsame (SetPathPtr, "PUT=RFM=STMCR", -1)) mrpsptr->PutRFM = PUT_RFM_STMCR; else if (strsame (SetPathPtr, "PUT=RFM=STMLF", -1)) mrpsptr->PutRFM = PUT_RFM_STMLF; else if (strsame (SetPathPtr, "PUT=RFM=UDF", -1)) mrpsptr->PutRFM = PUT_RFM_UDF; else if (strsame (SetPathPtr, "PUT=MAX=", 8)) { if (*(SetPathPtr+8) == '*') /* no limit is actually 4GB - current HTTP atol() constraint */ mrpsptr->PutMaxKbytes = 999999999; else mrpsptr->PutMaxKbytes = atoi(SetPathPtr+8); } else if (strsame (SetPathPtr, "QUERY-STRING=", 13)) { mrpsptr->QueryStringPtr = SetPathPtr + 13; mrpsptr->QueryStringLength = strlen(mrpsptr->QueryStringPtr); } else if (strsame (SetPathPtr, "REGEX=AWK", 9)) mrpsptr->RegexSyntax = RE_SYNTAX_AWK; else if (strsame (SetPathPtr, "DEFAULT", 7)) mrpsptr->RegexSyntax = -1; else if (strsame (SetPathPtr, "REGEX=ED", 8)) mrpsptr->RegexSyntax = RE_SYNTAX_ED; else if (strsame (SetPathPtr, "REGEX=EGREP", 11)) mrpsptr->RegexSyntax = RE_SYNTAX_EGREP; else if (strsame (SetPathPtr, "REGEX=GREP", 10)) mrpsptr->RegexSyntax = RE_SYNTAX_GREP; else if (strsame (SetPathPtr, "REGEX=POSIX_AWK", 15)) mrpsptr->RegexSyntax = RE_SYNTAX_POSIX_AWK; else if (strsame (SetPathPtr, "REGEX=POSIX_BASIC", 17)) mrpsptr->RegexSyntax = RE_SYNTAX_POSIX_BASIC; else if (strsame (SetPathPtr, "REGEX=POSIX_EGREP", 17)) mrpsptr->RegexSyntax = RE_SYNTAX_POSIX_EGREP; else if (strsame (SetPathPtr, "REGEX=POSIX_EXTENDED", 20)) mrpsptr->RegexSyntax = RE_SYNTAX_POSIX_EXTENDED; else if (strsame (SetPathPtr, "REGEX=POSIX_MINIMAL_BASIC", 25)) mrpsptr->RegexSyntax = RE_SYNTAX_POSIX_MINIMAL_BASIC; else if (strsame (SetPathPtr, "REGEX=POSIX_MINIMAL_EXTENDED", 28)) mrpsptr->RegexSyntax = RE_SYNTAX_POSIX_MINIMAL_EXTENDED; else if (strsame (SetPathPtr, "REGEX=SED", 9)) mrpsptr->RegexSyntax = RE_SYNTAX_AWK; else if (strsame (SetPathPtr, "REGEX=WASD", 10)) mrpsptr->RegexSyntax = REGEX_C_FLAGS; else if (strsame (SetPathPtr, "REGEX=", 6) && isdigit(SetPathPtr[6])) mrpsptr->RegexSyntax = atoi(SetPathPtr+6); else if (strsame (SetPathPtr, "REPORT=BASIC", 10)) mrpsptr->ReportType = ERROR_REPORT_BASIC; else if (strsame (SetPathPtr, "REPORT=DETAILED", 10)) mrpsptr->ReportType = ERROR_REPORT_DETAILED; else if (strsame (SetPathPtr, "REPORT=TUNNEL", 10)) mrpsptr->ReportType = ERROR_REPORT_TUNNEL; else if (strsame (SetPathPtr, "REPORT=400=", 11)) mrpsptr->Report400as = atoi(SetPathPtr+11); else if (strsame (SetPathPtr, "REPORT=403=", 11)) mrpsptr->Report403as = atoi(SetPathPtr+11); else if (strsame (SetPathPtr, "REPORT=404=", 11)) mrpsptr->Report404as = atoi(SetPathPtr+11); else if (strsame (SetPathPtr, "RMSCHAR=", 8)) mrpsptr->RmsSubChar = SetPathPtr[8]; else if (strsame (SetPathPtr, "RESPONSE=200=203", -1)) mrpsptr->Response200is203 = 203; else if (strsame (SetPathPtr, "RESPONSE=203=200", -1)) mrpsptr->Response200is203 = 200; else if (strsame (SetPathPtr, "RESPONSE=CSP=", 13)) { mrpsptr->ResponseCspPtr = SetPathPtr + 13; if (!(mrpsptr->ResponseCspLength = strlen(mrpsptr->ResponseCspPtr))) { mrpsptr->ResponseCspPtr = NULL; mrpsptr->ResponseCspLength = -1; } } else if (strsame (SetPathPtr, "NORESPONSE=CSP", -1) || strsame (SetPathPtr, "RESPONSE=NOCSP", -1)) { mrpsptr->ResponseCspPtr = NULL; mrpsptr->ResponseCspLength = -1; } else if (strsame (SetPathPtr, "RESPONSE=CSPRO=", 15)) { mrpsptr->ResponseCsproPtr = SetPathPtr + 15; if (!(mrpsptr->ResponseCsproLength = strlen(mrpsptr->ResponseCsproPtr))) { mrpsptr->ResponseCspPtr = NULL; mrpsptr->ResponseCspLength = -1; } } else if (strsame (SetPathPtr, "NORESPONSE=CSPRO", -1) || strsame (SetPathPtr, "RESPONSE=NOCSPRO", -1)) { mrpsptr->ResponseCsproPtr = NULL; mrpsptr->ResponseCsproLength = -1; } else if (strsame (SetPathPtr, "RESPONSE=GZIP=ALL", -1) || strsame (SetPathPtr, "RESPONSE=GZIP=0", -1)) mrpsptr->ResponseGzip = MAPURL_RESPONSE_GZIP_ALL; else if (strsame (SetPathPtr, "RESPONSE=GZIP=NONE", -1)) mrpsptr->ResponseGzip = MAPURL_RESPONSE_GZIP_NONE; else if (strsame (SetPathPtr, "RESPONSE=GZIP=", 14)) mrpsptr->ResponseGzip = atoi(SetPathPtr+14); else if (strsame (SetPathPtr, "RESPONSE=CHUNKED", 14)) mrpsptr->ResponseChunked = true; else if (strsame (SetPathPtr, "NORESPONSE=CHUNKED", 16) || strsame (SetPathPtr, "RESPONSE=NOCHUNKED", 16)) mrpsptr->ResponseNoChunked = true; else if (strsame (SetPathPtr, "RESPONSE=HEADER=BEGIN", -1)) mrpsptr->ResponseHeaderBegin = true; else if (strsame (SetPathPtr, "RESPONSE=HEADER=FULL", -1)) mrpsptr->ResponseHeaderFull = true; else if (strsame (SetPathPtr, "RESPONSE=HEADER=NONE", -1)) mrpsptr->ResponseHeaderNone = true; else if (strsame (SetPathPtr, "NORESPONSE=HEADER=ADD", -1) || strsame (SetPathPtr, "RESPONSE=HEADER=NOADD", -1)) mrpsptr->ResponseHeaderNoAdd = true; else if (strsame (SetPathPtr, "RESPONSE=HEADER=ADD=", 20)) { mrpsptr->ResponseHeaderAddPtr = SetPathPtr + 20; mrpsptr->ResponseHeaderAddLength = strlen(mrpsptr->ResponseHeaderAddPtr); } else if (strsame (SetPathPtr, "RESPONSE=HTTP=ORIGINAL", -1)) mrpsptr->ResponseHttpOriginal = true; else if (strsame (SetPathPtr, "NORESPONSE=HTTP=ORIGINAL", -1) || strsame (SetPathPtr, "RESPONSE=HTTP=NOORIGINAL", -1)) mrpsptr->ResponseHttpNoOriginal = true; else if (strsame (SetPathPtr, "RESPONSE=STS=", 13)) { mrpsptr->ResponseStrictTransSecPtr = SetPathPtr+13; mrpsptr->ResponseStrictTransSecLength = strlen(mrpsptr->ResponseStrictTransSecPtr); } else if (strsame (SetPathPtr, "RESPONSE=VAR", -1)) mrpsptr->ResponseVarRecord = FILE_VAR_DEFAULT; else if (strsame (SetPathPtr, "RESPONSE=VAR=CRLF", -1)) mrpsptr->ResponseVarRecord = FILE_VAR_CRLF; else if (strsame (SetPathPtr, "RESPONSE=VAR=LF", -1)) mrpsptr->ResponseVarRecord = FILE_VAR_LF; else if (strsame (SetPathPtr, "RESPONSE=VAR=NONE", -1)) mrpsptr->ResponseVarRecord = FILE_VAR_NONE; else if (strsame (SetPathPtr, "SCRIPT=AGENT=AS=", 16)) { /* while setting the required pointers force to upper-case */ for (sptr = mrpsptr->ScriptAgentAsPtr = SetPathPtr+16; *sptr; sptr++) *sptr = TOUP(*sptr); mrpsptr->ScriptAgentAsLength = strlen(mrpsptr->ScriptAgentAsPtr); } else if (strsame (SetPathPtr, "SCRIPT=AS=", 10)) { /* while setting the required pointers force to upper-case */ for (sptr = mrpsptr->ScriptAsPtr = SetPathPtr+10; *sptr; sptr++) *sptr = TOUP(*sptr); mrpsptr->ScriptAsLength = strlen(mrpsptr->ScriptAsPtr); } else if (strsame (SetPathPtr, "SCRIPT=BIT-BUCKET=", 18)) mrpsptr->ScriptBitBucketTimeout = MetaConSetSeconds (mcptr, SetPathPtr+18, 1); else if (strsame (SetPathPtr, "SCRIPT=BODY=DECODE", -1)) mrpsptr->ScriptBodyDecode = true; else if (strsame (SetPathPtr, "SCRIPT=BODY=NODECODE", -1) || strsame (SetPathPtr, "SCRIPT=NOBODY=DECODE", -1) || strsame (SetPathPtr, "NOSCRIPT=BODY=DECODE", -1)) mrpsptr->ScriptBodyNoDecode = true; else if (strsame (SetPathPtr, "SCRIPT=CPU=", 11)) mrpsptr->ScriptCpuMax = MetaConSetSeconds (mcptr, SetPathPtr+11, 1); else if (strsame (SetPathPtr, "SCRIPT=COMMAND=", 15)) { mrpsptr->ScriptCommandPtr = SetPathPtr + 15; mrpsptr->ScriptCommandLength = strlen(mrpsptr->ScriptCommandPtr); } else if (strsame (SetPathPtr, "SCRIPT=CONTROL=", 15)) { mrpsptr->ScriptControlPtr = SetPathPtr + 15; mrpsptr->ScriptControlLength = strlen(mrpsptr->ScriptControlPtr); } else if (strsame (SetPathPtr, "SCRIPT=DEFAULT=", 15)) { mrpsptr->ScriptDefaultPtr = SetPathPtr + 15; mrpsptr->ScriptDefaultLength = strlen(mrpsptr->ScriptDefaultPtr); } else if (strsame (SetPathPtr, "SCRIPT=FIND", -1)) mrpsptr->ScriptFind = true; else if (strsame (SetPathPtr, "SCRIPT=NOFIND", -1) || strsame (SetPathPtr, "NOSCRIPT=FIND", -1)) mrpsptr->ScriptNoFind = true; else if (strsame (SetPathPtr, "SCRIPT=LIFETIME=", 16)) mrpsptr->ScriptLifeTime = MetaConSetSeconds (mcptr, SetPathPtr+16, 1); else if (strsame (SetPathPtr, "SCRIPT=SYMBOL=TRUNCATE", -1)) mrpsptr->ScriptSymbolTruncate = true; else if (strsame (SetPathPtr, "SCRIPT=SYMBOL=NOTRUNCATE", -1) || strsame (SetPathPtr, "NOSCRIPT=SYMBOL=TRUNCATE", -1)) mrpsptr->ScriptSymbolNoTruncate = true; else if (strsame (SetPathPtr, "SCRIPT=SYNTAX=UNIX", -1)) mrpsptr->ScriptSyntaxUnix = true; else if (strsame (SetPathPtr, "SCRIPT=SYNTAX=NOUNIX", -1) || strsame (SetPathPtr, "NOSCRIPT=SYNTAX=UNIX", -1)) mrpsptr->ScriptSyntaxNoUnix = true; else if (strsame (SetPathPtr, "SCRIPT=PARAM=", 13)) { mrpsptr->ScriptParamsPtr = SetPathPtr + 13; mrpsptr->ScriptParamsLength = strlen(mrpsptr->ScriptParamsPtr); } else if (strsame (SetPathPtr, "SCRIPT=PARAMS=", 14)) { mrpsptr->ScriptParamsPtr = SetPathPtr + 14; mrpsptr->ScriptParamsLength = strlen(mrpsptr->ScriptParamsPtr); } else if (strsame (SetPathPtr, "SCRIPT=PATH=FIND", -1)) mrpsptr->ScriptPathFind = true; else if (strsame (SetPathPtr, "SCRIPT=NOPATH=FIND", -1) || strsame (SetPathPtr, "NOSCRIPT=PATH=FIND", -1)) mrpsptr->ScriptNoPathFind = true; else if (strsame (SetPathPtr, "SCRIPT=QUERY=NONE", -1)) mrpsptr->ScriptQueryNone = true; else if (strsame (SetPathPtr, "SCRIPT=NOQUERY=NONE", -1) || strsame (SetPathPtr, "NOSCRIPT=QUERY=NONE", -1)) mrpsptr->ScriptNoQueryNone = true; else if (strsame (SetPathPtr, "SCRIPT=QUERY=RELAXED", -1)) mrpsptr->ScriptQueryRelaxed = true; else if (strsame (SetPathPtr, "SCRIPT=NOQUERY=RELAXED", -1) || strsame (SetPathPtr, "NOSCRIPT=QUERY=RELAXED", -1)) mrpsptr->ScriptNoQueryRelaxed = true; else if (strsame (SetPathPtr, "SEARCH=NONE", -1)) mrpsptr->NoDefaultSearch = true; else if (strsame (SetPathPtr, "NOSEARCH=NONE", -1) || strsame (SetPathPtr, "SEARCH=NONONE", -1)) mrpsptr->DefaultSearch = true; else if (strsame (SetPathPtr, "SERVICE=", 8)) { mrpsptr->ChangeServicePtr = SetPathPtr + 8; mrpsptr->ChangeServiceLength = strlen(mrpsptr->ChangeServicePtr); } else if (strsame (SetPathPtr, "SSI=PRIV", 8)) mrpsptr->PrivSsi = true; else if (strsame (SetPathPtr, "SSI=NOPRIV", -1) || strsame (SetPathPtr, "NOSSI=PRIV", -1)) mrpsptr->NoPrivSsi = true; else if (strsame (SetPathPtr, "SSI=EXEC=", 9)) { mrpsptr->SsiExecPtr = SetPathPtr + 9; mrpsptr->SsiExecLength = strlen(mrpsptr->SsiExecPtr); } else if (strsame (SetPathPtr, "SSI=DCL=", 8)) { /* synonym for 'ssi=exec=' */ mrpsptr->SsiExecPtr = SetPathPtr + 8; mrpsptr->SsiExecLength = strlen(mrpsptr->SsiExecPtr); } else if (strsame (SetPathPtr, "NOSSLCGI", -1)) mrpsptr->SSLCGIvar = SESOLA_CGI_VAR_NONE; else if (strsame (SetPathPtr, "SSLCGI=NONE", -1)) mrpsptr->SSLCGIvar = SESOLA_CGI_VAR_NONE; else if (strsame (SetPathPtr, "SSLCGI=APACHE_MOD_SSL", -1)) mrpsptr->SSLCGIvar = SESOLA_CGI_VAR_APACHE_MOD_SSL; else if (strsame (SetPathPtr, "SSLCGI=APACHE_MOD_SSL_CLIENT", -1)) mrpsptr->SSLCGIvar = SESOLA_CGI_VAR_APACHE_MOD_SSL_CLIENT; else if (strsame (SetPathPtr, "SSLCGI=APACHE_MOD_SSL_EXTENS", -1)) mrpsptr->SSLCGIvar = SESOLA_CGI_VAR_APACHE_MOD_SSL_EXTENS; else if (strsame (SetPathPtr, "SSLCGI=APACHE_MOD_SSL_OID", -1)) mrpsptr->SSLCGIvar = SESOLA_CGI_VAR_APACHE_MOD_SSL_OID; else if (strsame (SetPathPtr, "SSLCGI=PURVEYOR", -1)) mrpsptr->SSLCGIvar = SESOLA_CGI_VAR_PURVEYOR; else if (strsame (SetPathPtr, "STMLF", -1)) mrpsptr->StmLF = true; else if (strsame (SetPathPtr, "NOSTMLF", -1)) mrpsptr->NoStmLF = true; else if (strsame (SetPathPtr, "THROTTLE=", 9)) { mrpsptr->ThrottleSet = true; SetPathPtr += 9; if (strsame (SetPathPtr, "BUSY=", 5)) mrpsptr->ThrottleBusy = atoi(SetPathPtr+5); else if (strsame (SetPathPtr, "FROM=", 5)) { sptr = SetPathPtr + 5; mrpsptr->ThrottleFrom = atoi(sptr); while (isdigit(*sptr)) sptr++; if (*sptr == '$') mrpsptr->ThrottlePerUser = atoi(sptr+1); } else if (strsame (SetPathPtr, "RESUME=", 7)) mrpsptr->ThrottleResume = atoi(SetPathPtr+7); else if (strsame (SetPathPtr, "TO=", 3)) mrpsptr->ThrottleTo = atoi(SetPathPtr+3); else if (strsame (SetPathPtr, "TIMEOUT=BUSY=", 13)) mrpsptr->ThrottleTimeoutBusy = MetaConSetSeconds (mcptr, SetPathPtr+13, 1); else if (strsame (SetPathPtr, "TIMEOUT=QUEUE=", 14)) mrpsptr->ThrottleTimeoutQueue = MetaConSetSeconds (mcptr, SetPathPtr+14, 1); else if (strsame (SetPathPtr, "USER=", 5)) mrpsptr->ThrottlePerUser = atoi(SetPathPtr+5); else if (strsame (SetPathPtr, "NONE", 4)) mrpsptr->ThrottleNoSet = true; else { /* throttle=from[/user],to,resume,busy,t/o-queue,t/o-busy */ sptr = SetPathPtr; if (*sptr == '(') sptr++; if (isdigit(*sptr)) mrpsptr->ThrottleFrom = atoi(sptr); while (isdigit(*sptr)) *sptr++; if (*sptr == '/') { sptr++; mrpsptr->ThrottlePerUser = atoi(sptr); while (isdigit(*sptr)) *sptr++; } if (*sptr == ',') *sptr++; if (isdigit(*sptr)) mrpsptr->ThrottleTo = atoi(sptr); while (isdigit(*sptr)) *sptr++; if (*sptr == ',') *sptr++; if (isdigit(*sptr)) mrpsptr->ThrottleResume = atoi(sptr); while (isdigit(*sptr)) *sptr++; if (*sptr == ',') *sptr++; if (isdigit(*sptr)) mrpsptr->ThrottleBusy = atoi(sptr); while (isdigit(*sptr)) *sptr++; if (*sptr == ',') *sptr++; if (isdigit(*sptr)) mrpsptr->ThrottleTimeoutQueue = MetaConSetSeconds (mcptr, sptr, 1); while (*sptr && (isdigit(*sptr) || *sptr == ':')) *sptr++; if (*sptr == ',') *sptr++; if (isdigit(*sptr)) mrpsptr->ThrottleTimeoutBusy = MetaConSetSeconds (mcptr, sptr, 1); while (*sptr && (isdigit(*sptr) || *sptr == ':')) *sptr++; } } else if (strsame (SetPathPtr, "TIMEOUT=PERSISTENT=", 19)) mrpsptr->TimeoutPersistent = MetaConSetSeconds (mcptr, SetPathPtr+19, 1); else /* for backward compatibility against the above */ if (strsame (SetPathPtr, "TIMEOUT=KEEPALIVE=", 18)) mrpsptr->TimeoutPersistent = MetaConSetSeconds (mcptr, SetPathPtr+18, 1); else if (strsame (SetPathPtr, "TIMEOUT=NOPROGRESS=", 19)) mrpsptr->TimeoutNoProgress = MetaConSetSeconds (mcptr, SetPathPtr+19, 1); else if (strsame (SetPathPtr, "TIMEOUT=OUTPUT=", 15)) mrpsptr->TimeoutOutput = MetaConSetSeconds (mcptr, SetPathPtr+15, 1); else if (strsame (SetPathPtr, "TIMEOUT=", 8)) { sptr = SetPathPtr+8; mrpsptr->TimeoutPersistent = MetaConSetSeconds (mcptr, sptr, 1); while (*sptr && !ISLWS(*sptr) && *sptr != ',') *sptr++; if (*sptr == ',') *sptr++; mrpsptr->TimeoutNoProgress = MetaConSetSeconds (mcptr, sptr, 1); while (*sptr && !ISLWS(*sptr) && *sptr != ',') *sptr++; if (*sptr == ',') *sptr++; mrpsptr->TimeoutOutput = MetaConSetSeconds (mcptr, sptr, 1); } else if (strsame (SetPathPtr, "NOTIMEOUT", -1)) mrpsptr->TimeoutNoProgress = mrpsptr->TimeoutPersistent = mrpsptr->TimeoutOutput = -1; else if (strsame (SetPathPtr, "ACCESS=PROFILE", -1)) mrpsptr->AccessProfile = true; else if (strsame (SetPathPtr, "ACCESS=NOPROFILE", -1) || strsame (SetPathPtr, "NOACCESS=PROFILE", -1)) mrpsptr->AccessNoProfile = true; else if (strsame (SetPathPtr, "ACCESS=READ", -1)) mrpsptr->AccessRead = true; else if (strsame (SetPathPtr, "ACCESS=NOREAD", -1) || strsame (SetPathPtr, "NOACCESS=READ", -1)) mrpsptr->AccessNoRead = true; else if (strsame (SetPathPtr, "ACCESS=SERVER", -1)) mrpsptr->AccessServer = true; else if (strsame (SetPathPtr, "ACCESS=NOSERVER", -1) || strsame (SetPathPtr, "NOACCESS=SERVER", -1)) mrpsptr->AccessNoServer = true; else if (strsame (SetPathPtr, "ACCESS=WRITE", -1)) mrpsptr->AccessWrite = true; else if (strsame (SetPathPtr, "ACCESS=NOWRITE", -1) || strsame (SetPathPtr, "NOACCESS=WRITE", -1)) mrpsptr->AccessNoWrite = true; else if (strsame (SetPathPtr, "WEBDAV=HIDDEN", -1)) mrpsptr->WebDavHidden = true; else if (strsame (SetPathPtr, "WEBDAV=NOHIDDEN", -1) || strsame (SetPathPtr, "NOWEBDAV=HIDDEN", -1)) mrpsptr->WebDavNoHidden = true; else if (strsame (SetPathPtr, "WEBDAV=LOCKING", 11)) mrpsptr->WebDavLock = true; else if (strsame (SetPathPtr, "WEBDAV=NOLOCKING", 13) || strsame (SetPathPtr, "NOWEBDAV=LOCKING", 13)) mrpsptr->WebDavNoLock = true; else if (strsame (SetPathPtr, "WEBDAV=META=DIR=", 16)) { mrpsptr->WebDavMetaDirPtr = SetPathPtr + 16; mrpsptr->WebDavMetaDirLength = strlen(mrpsptr->WebDavMetaDirPtr); } else if (strsame (SetPathPtr, "WEBDAV=PROFILE", -1)) mrpsptr->WebDavProfile = true; else if (strsame (SetPathPtr, "WEBDAV=NOPROFILE", -1) || strsame (SetPathPtr, "NOWEBDAV=PROFILE", -1)) mrpsptr->WebDavNoProfile = true; else if (strsame (SetPathPtr, "WEBDAV=PROP", -1)) mrpsptr->WebDavProp = true; else if (strsame (SetPathPtr, "WEBDAV=NOPROP", -1) || strsame (SetPathPtr, "NOWEBDAV=PROP", -1)) mrpsptr->WebDavNoProp = true; else if (strsame (SetPathPtr, "WEBDAV=PUT=LOCK", -1)) mrpsptr->WebDavPutLock = true; else if (strsame (SetPathPtr, "WEBDAV=NOPUT=LOCK", -1) || strsame (SetPathPtr, "NOWEBDAV=PUT=LOCK", -1)) mrpsptr->WebDavNoPutLock = true; else if (strsame (SetPathPtr, "WEBDAV=READ", -1)) mrpsptr->WebDavRead = true; else if (strsame (SetPathPtr, "WEBDAV=NOREAD", -1) || strsame (SetPathPtr, "NOWEBDAV=READ", -1)) mrpsptr->WebDavNoRead = true; else if (strsame (SetPathPtr, "WEBDAV=SERVER", -1)) mrpsptr->WebDavServer = true; else if (strsame (SetPathPtr, "WEBDAV=NOSERVER", -1) || strsame (SetPathPtr, "NOWEBDAV=SERVER", -1)) mrpsptr->WebDavNoServer = true; else if (strsame (SetPathPtr, "WEBDAV=WINPROP", -1)) mrpsptr->WebDavWinProp = true; else if (strsame (SetPathPtr, "WEBDAV=NOWINPROP", -1) || strsame (SetPathPtr, "NOWEBDAV=WINPROP", -1)) mrpsptr->WebDavNoWinProp = true; else if (strsame (SetPathPtr, "WEBDAV=WRITE", -1)) mrpsptr->WebDavWrite = true; else if (strsame (SetPathPtr, "WEBDAV=NOWRITE", -1) || strsame (SetPathPtr, "NOWEBDAV=WRITE", -1)) mrpsptr->WebDavNoWrite = true; else if (strsame (SetPathPtr, "WEBDAV=LOCK=TIMEOUT=DEFAULT=", 28)) mrpsptr->WebDavLockTimeoutDefault = MetaConSetSeconds (mcptr, SetPathPtr+28, 1); else if (strsame (SetPathPtr, "WEBDAV=LOCK=TIMEOUT=MAX=", 24)) mrpsptr->WebDavLockTimeoutMax = MetaConSetSeconds (mcptr, SetPathPtr+24, 1); else if (strsame (SetPathPtr, "WEBSOCKET=INPUT=", 16)) mrpsptr->WebSocketInputSize = atoi(SetPathPtr+16); else if (strsame (SetPathPtr, "WEBSOCKET=OUTPUT=", 17)) mrpsptr->WebSocketOutputSize = atoi(SetPathPtr+17); else { MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemSetPath); VmFree (mrptr, FI_LI); return (true); } } } if (RuleType == MAPURL_RULE_SET && !PathSet) { MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemSetPath); VmFree (mrptr, FI_LI); return (true); } if (RuleType == MAPURL_RULE_PROTECT) { /****************/ /* protect rule */ /****************/ /* PROTECT rules are always added to the mapping database, whether correct or not, so that even when incorrect the path is still access controlled (and in an incorrect case always denied!) */ sptr = AuthConfigParseProtectRule (NULL, ResultPtr, strlen(ResultPtr)); if (sptr) { MetaConReport (mcptr, METACON_REPORT_ERROR, sptr); ConfigProblem = true; } AuthProtectRule = true; } /* check for optional mapping conditional(s) */ if (*cptr == '[' || SAME2(cptr,'![')) { /***************/ /* conditional */ /***************/ ConditionalPtr = cptr; while (*cptr == '[' || SAME2(cptr,'![')) { while (*cptr == '[' || *cptr == '!') cptr++; while (*cptr && *cptr != ']') { while (ISLWS(*cptr)) cptr++; sptr = cptr; while (*cptr && *cptr != ':' && !ISLWS(*cptr) && *cptr != ']') { if (*cptr == '\\') cptr++; *cptr = TOUP(*cptr); if (*cptr) cptr++; } /* basic check of conditional rule */ if (*sptr == '!') sptr++; if ((!SAME2(sptr,'AC') && !SAME2(sptr,'AL') && !SAME2(sptr,'AS') && !SAME2(sptr,'CA') && !SAME2(sptr,'CK') && !SAME2(sptr,'DR') && !SAME2(sptr,'EX') && !SAME2(sptr,'FO') && !SAME2(sptr,'HH') && !SAME2(sptr,'HM') && !SAME2(sptr,'HO') && !SAME2(sptr,'ME') && !SAME2(sptr,'MP') && !SAME2(sptr,'NO') && !SAME2(sptr,'PA') && !SAME2(sptr,'PI') && !SAME2(sptr,'QS') && !SAME2(sptr,'RC') && !SAME2(sptr,'RF') && !SAME2(sptr,'RQ') && !SAME2(sptr,'RU') && !SAME2(sptr,'SC') && !SAME2(sptr,'SN') && !SAME2(sptr,'SP') && !SAME2(sptr,'ST') && !SAME2(sptr,'UA') && !SAME2(sptr,'VS') && !SAME2(sptr,'XF')) || sptr[2] != ':') { /***********************/ /* conditional problem */ /***********************/ MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemConditional); VmFree (mrptr, FI_LI); return (true); } while (*cptr && !ISLWS(*cptr) && *cptr != ']') { if (*cptr == '\\') cptr++; if (*cptr) cptr++; } while (ISLWS(*cptr)) cptr++; } if (*cptr == ']') cptr++; while (ISLWS(*cptr)) cptr++; } /* terminate in the white-space following the conditional(s) */ if (*cptr) *cptr = '\0'; } /**********************/ /* allowed rule check */ /**********************/ if (mclptr->MetaFileType == METACON_TYPE_CONFIG) { if (!AllowedInConfigFile) { MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemNotAllowed); VmFree (mrptr, FI_LI); return (true); } } /***************************/ /* rule consistency checks */ /***************************/ if (mrpsptr->RmsSubChar && !isalnum(mrpsptr->RmsSubChar) && mrpsptr->RmsSubChar != '$' && mrpsptr->RmsSubChar != '-' && mrpsptr->RmsSubChar != '_') { MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemRmsSubstitution); VmFree (mrptr, FI_LI); return (true); } TemplateWildcardCount = 0; cptr = TemplatePtr; while (*cptr) { if (*cptr++ != '*') continue; TemplateWildcardCount++; /* contiguous count as one! */ while (*cptr == '*') cptr++; } if (TemplateWildcardCount > REGEX_PMATCH_MAX) { MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemTooManyWildcard); VmFree (mrptr, FI_LI); return (true); } memset (&RegexPreg, 0, sizeof(RegexPreg)); if (Config.cfMisc.RegexSyntax && *TemplatePtr == REGEX_CHAR) { cptr = StringRegexCompile (TemplatePtr+1, &RegexPreg); if (cptr) { MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemRegex, cptr); VmFree (mrptr, FI_LI); return (true); } } ResultWildcardCount = ResultSpecifiedWildcardCount = 0; cptr = ResultPtr; while (*cptr) { if (*cptr++ != '*') continue; ResultWildcardCount++; /* contiguous count as one! */ while (*cptr == '*') cptr++; if (*cptr != '\'') continue; ResultSpecifiedWildcardCount++; cptr++; if (*cptr < '1' || *cptr > '9') { MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemSpecifiedWildcardRange); VmFree (mrptr, FI_LI); return (true); } } if (WATCH_MODULE(WATCH_MOD_MAPURL)) WatchThis (WATCHALL, WATCH_MOD_MAPURL, "!&Z !&Z !&Z !UL !UL !UL", TemplatePtr, ResultPtr, ConditionalPtr, TemplateWildcardCount, ResultWildcardCount, ResultSpecifiedWildcardCount); ResultPathOds = 0; switch (RuleType) { case MAPURL_RULE_SCRIPT : if (!ResultPtr[0]) { MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemResultRequired); VmFree (mrptr, FI_LI); return (true); } if (isdigit(ResultPtr[0])) { MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemResultStatus); VmFree (mrptr, FI_LI); return (true); } if (ResultSpecifiedWildcardCount) { MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemSpecifiedWildcardCannot); VmFree (mrptr, FI_LI); return (true); } if (ResultWildcardCount != TemplateWildcardCount) { MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemWildcardMapping); VmFree (mrptr, FI_LI); return (true); } break; case MAPURL_RULE_EXEC : case MAPURL_RULE_UXEC : if (!ResultPtr[0]) { MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemResultRequired); VmFree (mrptr, FI_LI); return (true); } if (isdigit(ResultPtr[0])) { MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemResultStatus); VmFree (mrptr, FI_LI); return (true); } if (ResultSpecifiedWildcardCount) { MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemSpecifiedWildcardCannot); VmFree (mrptr, FI_LI); return (true); } if (!ResultWildcardCount || !TemplateWildcardCount || ResultWildcardCount != TemplateWildcardCount) { MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemWildcardMapping); VmFree (mrptr, FI_LI); return (true); } break; case MAPURL_RULE_FAIL : break; case MAPURL_RULE_PASS : if (ResultSpecifiedWildcardCount && ResultSpecifiedWildcardCount != ResultWildcardCount) { MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemSpecifiedWildcardMix); VmFree (mrptr, FI_LI); return (true); } if (((ResultPtr[0] == '\"' || ResultPtr[0] == '\'') && !isdigit(ResultPtr[0]) && ResultWildcardCount > TemplateWildcardCount) || ((ResultPtr[0] != '\"' && ResultPtr[0] != '\'') && !isdigit(ResultPtr[0]) && ResultWildcardCount > TemplateWildcardCount)) { MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemWildcardMapping); VmFree (mrptr, FI_LI); return (true); } #ifdef ODS_EXTENDED /* determine the on-disk structure */ zptr = (sptr = DiskDevice) + sizeof(DiskDevice)-1; if (ResultPtr[0]) cptr = ResultPtr; else cptr = TemplatePtr; if (*cptr == '/') cptr++; while (*cptr && *cptr != '/' && sptr < zptr) *sptr++ = *cptr++; if (sptr < zptr) *sptr++ = ':'; *sptr = '\0'; ResultPathOds = OdsVolumeStructure (DiskDevice); #endif /* ODS_EXTENDED */ break; case MAPURL_RULE_MAP : case MAPURL_RULE_REDIRECT : case MAPURL_RULE_USER : if (!ResultPtr[0]) { MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemResultRequired); VmFree (mrptr, FI_LI); return (true); } if (isdigit(ResultPtr[0])) { MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemResultStatus); VmFree (mrptr, FI_LI); return (true); } if (ResultSpecifiedWildcardCount && ResultSpecifiedWildcardCount != ResultWildcardCount) { MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemSpecifiedWildcardMix); VmFree (mrptr, FI_LI); return (true); } if (ResultWildcardCount > TemplateWildcardCount) { MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemWildcardMapping); VmFree (mrptr, FI_LI); return (true); } break; case MAPURL_RULE_PROTECT : case MAPURL_RULE_SET : break; default : MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemConfused); VmFree (mrptr, FI_LI); return (true); } /*****************************/ /* throttle integrity checks */ /*****************************/ if (mrpsptr->ThrottleSet && !mrpsptr->ThrottleNoSet) { /* throttle=from,to,resume,busy,t/o-resume,t/o-busy */ if ((mrpsptr->ThrottleTo && mrpsptr->ThrottleTo <= mrpsptr->ThrottleFrom) || (mrpsptr->ThrottleResume && !mrpsptr->ThrottleTo) || (mrpsptr->ThrottleResume && mrpsptr->ThrottleResume <= mrpsptr->ThrottleTo) || (mrpsptr->ThrottleBusy && mrpsptr->ThrottleTo && mrpsptr->ThrottleBusy <= mrpsptr->ThrottleTo) || (mrpsptr->ThrottleBusy && mrpsptr->ThrottleResume && mrpsptr->ThrottleBusy <= mrpsptr->ThrottleResume)) { MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemThrottleValues); VmFree (mrptr, FI_LI); return (true); } } /************************************/ /* script=param=(name=value) checks */ /************************************/ if (mrpsptr->ScriptParamsPtr) { /* these will generally end up as DCL symbols for a script */ cptr = mrpsptr->ScriptParamsPtr; for (;;) { status = StringParseNameValue (&cptr, true, Name, sizeof(Name), Value, sizeof(Value)); if (VMSnok (status)) break; } if (status != SS$_ENDOFFILE) { MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemNameValue); VmFree (mrptr, FI_LI); return (true); } } /*********************************/ /* add the rule as the line data */ /*********************************/ /* set the meta-config data */ mclptr->LineDataPtr = mrptr; mclptr->ConfigProblem = ConfigProblem; /* set the rule data */ mrptr->MetaConNumber = mclptr->Number; mrptr->RuleType = RuleType; mrptr->TemplatePtr = TemplatePtr; mrptr->ResultPtr = ResultPtr; mrptr->ResultLength = strlen(ResultPtr); mrptr->ConditionalPtr = ConditionalPtr; mrptr->PathSet = PathSet; mrptr->IsCgiPlusScript = IsCgiPlusScript; #ifdef ODS_EXTENDED if (ResultPathOds) { /* indicate that this path is located on an ODS-5 volume */ mrptr->ResultPathOds = ResultPathOds; /* indicate that at least one mapped volume is ODS-5 */ if (ResultPathOds == MAPURL_PATH_ODS_5) MapUrlPathOds5 = true; } #endif /* ODS_EXTENDED */ if (RegexPreg.buffer) { /* the template was a regular expression, create a compiled version */ StringRegexCompile (TemplatePtr+1, &mrptr->RegexPregTemplate); /* free the temporary compiled version */ regfree (&RegexPreg); } if (mrpsptr->ThrottleSet && !mrpsptr->ThrottleNoSet) { mrpsptr->ThrottleIndex = mmptr->ThrottleIndex++; if (mmptr->ThrottleIndex > mmptr->ThrottleTotal) mmptr->ThrottleTotal = mmptr->ThrottleIndex; } if (mrpsptr->ProxyBindIpAddressLength) { status = TcpIpStringToAddress (mrpsptr->ProxyBindIpAddressPtr, &mrpsptr->ProxyBindIpAddress); if (VMSnok (status)) MetaConReport (mcptr, METACON_REPORT_ERROR, "Could not get bind address for !AZ", mrpsptr->ProxyBindIpAddressPtr); } if (mrpsptr->ProxyChainHostPortLength) { IPADDRESS_ZERO4 (&mrpsptr->ProxyChainIpAddress) status = NetHostNameLookup (mrpsptr->ProxyChainHostPortPtr, 0, NULL, NULL, NULL, &mrpsptr->ProxyChainIpAddress, &mrpsptr->ProxyChainPort); if (!mrpsptr->ProxyChainPort) mrpsptr->ProxyChainPort = DEFAULT_HTTP_PROXY_PORT; if (VMSnok (status)) { MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemHostNameLookup, mrpsptr->ProxyChainHostPortPtr, status); /* make sure the connection can't succeed */ IPADDRESS_SET_UNUSABLE (&mrpsptr->ProxyChainIpAddress) mrpsptr->ProxyChainPort = 0; } } /* note that we've got an extension-method rule */ if (mrpsptr->MapExtensionMethod) MapUrlExtensionMethod = true; if (WATCH_MODULE_DETAIL) WatchDataFormatted ("!&X !UL !&Z !&Z (!UL) !&B !&Z\n", mrptr, mrptr->RuleType, mrptr->TemplatePtr, mrptr->ResultPtr, mrptr->ResultPathOds, mrptr->PathSet, mrptr->ConditionalPtr); return (true); } /*****************************************************************************/ /* Given the current document's URL path and the specified document's URL path, generate a resultant URL path based on whether the specified document's path is absolute or relative the the current document's path. Insufficient space to contain the result path will not crash the function and the result will be set to an empty string. */ int MapUrl_VirtualPath ( char *CurrentPath, char *DocumentPath, char *ResultPath, int SizeOfResultPath ) { char *cptr, *dptr, *sptr, *tptr, *zptr; /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD_MAPURL)) WatchThis (WATCHALL, WATCH_MOD_MAPURL, "MapUrl_VirtualPath() !&Z !&Z !UL", CurrentPath, DocumentPath, SizeOfResultPath); if (*(dptr = DocumentPath) == '/' || strstr (DocumentPath, "//")) { /*****************/ /* absolute path */ /*****************/ strcpy (ResultPath, dptr); zptr = (sptr = ResultPath) + SizeOfResultPath; while (*dptr && sptr < zptr) *sptr++ = *dptr++; if (sptr >= zptr) return (-1); *sptr = '\0'; return (sptr - ResultPath); } /* step over any "relative to this directory" syntax ("./") */ if (dptr[0] == '.' && dptr[1] == '/') dptr += 2; if (*dptr != '.') { /*****************/ /* inferior path */ /*****************/ zptr = (sptr = tptr = ResultPath) + SizeOfResultPath; cptr = CurrentPath; while (*cptr && sptr < zptr) { if (*cptr == '/') tptr = sptr+1; *sptr++ = *cptr++; } sptr = tptr; while (*dptr && sptr < zptr) *sptr++ = *dptr++; if (sptr >= zptr) return (-1); *sptr = '\0'; return (sptr - ResultPath); } /*****************/ /* relative path */ /*****************/ zptr = (sptr = tptr = ResultPath) + SizeOfResultPath; cptr = CurrentPath; while (*cptr && sptr < zptr) { if (*cptr == '/') tptr = sptr; *sptr++ = *cptr++; } sptr = tptr; /* loop, stepping back one level for each "../" in the document path */ while (dptr[0] == '.' && dptr[1] == '.' && dptr[2] == '/') { dptr += 3; if (sptr > ResultPath) sptr--; while (sptr > ResultPath && *sptr != '/') sptr--; } if (sptr > ResultPath && sptr < zptr) sptr++; else if (sptr < zptr) *sptr++ = '/'; while (*dptr && sptr < zptr) *sptr++ = *dptr++; if (sptr >= zptr) return (-1); *sptr = '\0'; return (sptr - ResultPath); } /*****************************************************************************/ /* Guarantee access to certain paths under certain conditions. */ char* MapUrl_GuaranteeAccess ( REQUEST_STRUCT *rqptr, char *PathBeingMapped ) { /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD_MAPURL)) WatchThis (WATCHITM(rqptr), WATCH_MOD_MAPURL, "MapUrl_GuaranteeAccess() !&Z", PathBeingMapped); if (AuthPromiscuous || HttpdGblSecPtr->AuthSkelKeyHttpdTickSecond) { /* guarantee access to the administration menu */ if (!strsame (PathBeingMapped, HTTPD_ADMIN, sizeof(HTTPD_ADMIN)-1) && !strsame (PathBeingMapped, WASD_ROOT_LOCAL, sizeof(WASD_ROOT_LOCAL)-1) && !strsame (PathBeingMapped, HT_ROOT_LOCAL, sizeof(HT_ROOT_LOCAL)-1)) return (NULL); if (WATCHING (rqptr, WATCH_MAPPING)) WatchThis (WATCHITM(rqptr), WATCH_MAPPING, "!AZ guarantees access to !AZ", AuthPromiscuous ? "PROMISCUOUS" : "SKELKEY", PathBeingMapped); return (PathBeingMapped); } return (NULL); } /*****************************************************************************/ /* A server administration report on the server's mapping rules. This function just wraps the reporting function, loading a temporary database if necessary for reporting from the rule file. */ MapUrl_Report ( REQUEST_STRUCT *rqptr, BOOL UseServerDatabase, char *VirtualService ) { int status; META_CONFIG *mcptr; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD_MAPURL)) WatchThis (WATCHITM(rqptr), WATCH_MOD_MAPURL, "MapUrl_Report() !UL !&Z", UseServerDatabase, VirtualService); if (UseServerDatabase) { /* use mapping rules already loaded into the server */ MapUrl_ReportNow (rqptr, true, MetaGlobalMappingPtr, VirtualService); } else { /* load temporary set of rules from mapping file */ status = MapUrl_ConfigLoad (&mcptr); if (VMSnok (status)) { /* severe error reported */ rqptr->rqResponse.HttpStatus = 403; ErrorGeneral (rqptr, mcptr->LoadReport.TextPtr, FI_LI); } else MapUrl_ReportNow (rqptr, false, mcptr, VirtualService); MetaConUnload (&mcptr, &MapUrl_ConfigUnloadLineData); } AdminEnd (rqptr); } /*****************************************************************************/ /* Return a report on the HTTPd server's mapping rules ... now! */ MapUrl_ReportNow ( REQUEST_STRUCT *rqptr, BOOL UseServerDatabase, META_CONFIG *mcptr, char *VirtualService ) { static char BeginRules [] = "

Mapping Rules

\n"; static char BeginTable [] = "

\n\ \n\
";

   static char  CommentFao [] = "!4ZL  !#* !AZ\n";

   static char  RuleFao [] =
"!4ZL  !#* !&?\r\r!AZ  !&;AZ!&@!&@!&@!&?\r\r\n";

   static char  NonRuleFao [] =
"!4ZL  !#* !&?\r\r!#AZ  !&;AZ!&?\r\r\n";

   static char  ProblemFao [] = "!4ZL  !#* !&;AZ\n";

   static char  RuleVirtualFao [] =
"!4ZL  !#* !&?\r\r[[!&;AZ]]!&?\r\r\n";

   static char  RuleImplicitVirtualFao [] =
"0000  [[*:*]]\n";

   static char  VersionFao [] = "!4ZL  [[!AZ]]\n";

   static char  UserMappingFao [] =
"!AZ\
----\
\n\
\n\

User Mapping Cache

\n\

\n\ \ \ \ \ \ \ \ \ \n\ \n"; static char EntryFao [] = "\ \ \ \ \ \ \ \ \n"; static char EmptyUserMappingFao [] = "\n"; static char EndPageFao [] = "
NamePathODSHitsLastReuse
!4ZL!AZ  !AZ  !AZ  !UL  !20%D  !UL
0000empty
\n\ \n\ \n\ \n"; BOOL FinalRule, ThisVirtualService; int status, EntryCount; unsigned long FaoVector [32]; unsigned long *vecptr; unsigned short Length; char *cptr; char Buffer [MAP_BUFFER_SIZE], RmsSubChar [2], TimeString [32]; LIST_ENTRY *leptr; MAP_RULE_META *mrptr; MAP_URL_USER_ENTRY *ucptr; METACON_LINE *mclptr; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD_MAPURL)) WatchThis (WATCHITM(rqptr), WATCH_MOD_MAPURL, "MapUrl_ReportNow() !&B !&Z", UseServerDatabase, VirtualService); AdminPageTitle (rqptr, "Path Mapping"); AdminMetaConReport (rqptr, mcptr, MetaGlobalMappingPtr); AdminMetaConSource (rqptr, mcptr, MetaGlobalMappingPtr); /*****************/ /* mapping rules */ /*****************/ status = FaolToNet (rqptr, BeginRules, NULL); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); AdminVirtualServiceForm (rqptr, ADMIN_REPORT_MAPPING, VirtualService, UseServerDatabase); status = FaolToNet (rqptr, BeginTable, NULL); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); status = SS$_NORMAL; EntryCount = 0; FinalRule = false; ThisVirtualService = true; MetaConParseReset (mcptr, true); while (mclptr = MetaConParseRaw (mcptr)) { if (mclptr->Token == METACON_TOKEN_SERVICE) { /* if filtering on a virtual service */ if (VirtualService[0] && !StringMatch (rqptr, VirtualService, mclptr->TextPtr)) { ThisVirtualService = false; continue; } ThisVirtualService = true; vecptr = FaoVector; *vecptr++ = mclptr->Number; *vecptr++ = (mclptr->MetaFileLevel+mclptr->FlowControlLevel) * 3; *vecptr++ = mclptr->ConfigProblem || FinalRule; *vecptr++ = mclptr->TextPtr; *vecptr++ = mclptr->ConfigProblem || FinalRule; status = FaolToNet (rqptr, RuleVirtualFao, &FaoVector); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); continue; } else if (mclptr->Number == 1) { status = FaolToNet (rqptr, RuleImplicitVirtualFao, NULL); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); } if (!ThisVirtualService) continue; EntryCount++; if (mclptr->Token != METACON_TOKEN_TEXT) { for (cptr = mclptr->TextPtr; *cptr && !ISLWS(*cptr); cptr++); vecptr = FaoVector; *vecptr++ = mclptr->Number; if (mclptr->Token == METACON_TOKEN_COMMENT) { *vecptr++ = (mclptr->MetaFileLevel+ mclptr->FlowControlLevel+1) * 3; *vecptr++ = mclptr->TextPtr; status = FaolToNet (rqptr, CommentFao, &FaoVector); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); continue; } if (mclptr->Token == METACON_TOKEN_VERSION) { *vecptr++ = mclptr->TextPtr; status = FaolToNet (rqptr, VersionFao, &FaoVector); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); continue; } switch (mclptr->Token) { case METACON_TOKEN_ELIF : case METACON_TOKEN_ELSE : case METACON_TOKEN_UNIF : case METACON_TOKEN_IFIF : if (mclptr->FlowControlLevel) *vecptr++ = (mclptr->MetaFileLevel+ mclptr->FlowControlLevel) * 3; else *vecptr++ = (mclptr->MetaFileLevel+ mclptr->FlowControlLevel+1) * 3; break; default: *vecptr++ = (mclptr->MetaFileLevel+ mclptr->FlowControlLevel+1) * 3; } *vecptr++ = mclptr->ConfigProblem || FinalRule || (mclptr->InlineTextPtr && !mclptr->LineDataPtr); *vecptr++ = cptr - mclptr->TextPtr; *vecptr++ = mclptr->TextPtr; while (*cptr && ISLWS(*cptr)) cptr++; *vecptr++ = cptr; *vecptr++ = mclptr->ConfigProblem || FinalRule || (mclptr->InlineTextPtr && !mclptr->LineDataPtr); status = FaolToNet (rqptr, NonRuleFao, &FaoVector); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); continue; } vecptr = FaoVector; *vecptr++ = mclptr->Number; *vecptr++ = (mclptr->MetaFileLevel+ mclptr->FlowControlLevel) * 3 + 3; if (!(mrptr = mclptr->LineDataPtr)) { *vecptr++ = mclptr->TextPtr; status = FaolToNet (rqptr, ProblemFao, &FaoVector); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); continue; } if (WATCHMOD (rqptr, WATCH_MODULE_DETAIL)) WatchDataFormatted ("!&X !UL !&Z !&Z !&Z\n", mrptr, mrptr->RuleType, mrptr->TemplatePtr, mrptr->ResultPtr, mrptr->ConditionalPtr); *vecptr++ = mclptr->ConfigProblem || FinalRule; if (mrptr->RuleType == MAPURL_RULE_EXEC) { if (mrptr->IsCgiPlusScript) *vecptr++ = "exec+"; else *vecptr++ = "exec"; } else if (mrptr->RuleType == MAPURL_RULE_FAIL) *vecptr++ = "fail"; else if (mrptr->RuleType == MAPURL_RULE_MAP) *vecptr++ = "map"; else if (mrptr->RuleType == MAPURL_RULE_PASS) *vecptr++ = "pass"; else if (mrptr->RuleType == MAPURL_RULE_PROTECT) *vecptr++ = "protect"; else if (mrptr->RuleType == MAPURL_RULE_REDIRECT) *vecptr++ = "redirect"; else if (mrptr->RuleType == MAPURL_RULE_SCRIPT) { if (mrptr->IsCgiPlusScript) *vecptr++ = "script+"; else *vecptr++ = "script"; } else if (mrptr->RuleType == MAPURL_RULE_SET) *vecptr++ = "set"; else if (mrptr->RuleType == MAPURL_RULE_UXEC) *vecptr++ = "uxec"; else if (mrptr->RuleType == MAPURL_RULE_USER) *vecptr++ = "user"; else *vecptr++ = "*ERROR*"; *vecptr++ = mrptr->TemplatePtr; if (isdigit(*mrptr->ResultPtr)) { *vecptr++ = " "!&;AZ""; *vecptr++ = mrptr->ResultPtr; } else if (mrptr->ResultPtr[0]) { *vecptr++ = " !&;AZ"; *vecptr++ = mrptr->ResultPtr; } else *vecptr++ = ""; if (mrptr->PathSet) { /* just one space, ExplainPathSet() adds it's own leading space */ *vecptr++ = " !&;AZ"; *vecptr++ = MapUrl_ExplainPathSet (rqptr, mrptr); } else *vecptr++ = ""; if (mrptr->ConditionalPtr[0]) { *vecptr++ = " !&;AZ"; *vecptr++ = mrptr->ConditionalPtr; } else *vecptr++ = ""; *vecptr++ = mclptr->ConfigProblem || FinalRule; status = FaolToNet (rqptr, RuleFao, &FaoVector); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); /* stop reporting a specific virtual service if terminating rule */ if (!VirtualService[0]) continue; if ((mrptr->RuleType == MAPURL_RULE_FAIL || mrptr->RuleType == MAPURL_RULE_PASS) && SAME2(mrptr->TemplatePtr,'*\0')) FinalRule = true; } vecptr = FaoVector; if (EntryCount) *vecptr++ = ""; else *vecptr++ = "(none)\n"; *vecptr++ = MapUrlUserNameCacheEntries; status = FaolToNet (rqptr, UserMappingFao, &FaoVector); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); /*****************/ /* user mappings */ /*****************/ EntryCount = 0; /* process the cache entry list from most to least recent */ for (leptr = MapUrlUserNameCacheList.HeadPtr; leptr; leptr = leptr->NextPtr) { ucptr = (MAP_URL_USER_ENTRY*)leptr; /* if empty name, must have been reset, no point in going any further */ if (!ucptr->UserName[0]) break; vecptr = FaoVector; EntryCount++; if (EntryCount % 2) *vecptr++ = " class=\"hlght\""; else *vecptr++ = " class=\"hlght\""; *vecptr++ = EntryCount; *vecptr++ = ucptr->UserName; *vecptr++ = ucptr->UserPath; if (ucptr->PathOds == MAPURL_PATH_ODS_2) *vecptr++ = "ODS-2"; else if (ucptr->PathOds == MAPURL_PATH_ODS_5) *vecptr++ = "ODS-5"; else *vecptr++ = "ods-2"; *vecptr++ = ucptr->HitCount; *vecptr++ = &ucptr->LastBinaryTime; *vecptr++ = ucptr->ReuseCount; status = FaolToNet (rqptr, EntryFao, &FaoVector); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); } if (!MapUrlUserNameCacheList.HeadPtr) { status = FaolToNet (rqptr, EmptyUserMappingFao, NULL); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); } status = FaolToNet (rqptr, EndPageFao, NULL); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); rqptr->rqResponse.PreExpired = PRE_EXPIRE_MAPPING_RULES; ResponseHeader200 (rqptr, "text/html", &rqptr->NetWriteBufferDsc); } /*****************************************************************************/ /* Report an individual rule during processing of a mapping rule check. */ MapUrl_WatchRule ( REQUEST_STRUCT *rqptr, MAP_RULE_META *mrptr, char *PathPtr, int PathOds, int Match, BOOL SetPathIgnore ) { static char RuleFao [] = "!4ZL !AZ!AZ !AZ !8AZ !AZ !&@!&@!&@\n"; int status; unsigned short Length; unsigned long FaoVector [32]; unsigned long *vecptr; char Buffer [8192], RmsSubChar [2]; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD_MAPURL)) WatchThis (WATCHITM(rqptr), WATCH_MOD_MAPURL, "MapUrl_WatchRule() !&Z !UL !UL", PathPtr, PathOds, Match); vecptr = FaoVector; *vecptr++ = mrptr->MetaConNumber; *vecptr++ = PathPtr; if (PathOds == MAPURL_PATH_ODS_0) *vecptr++ = " NOODS"; else if (PathOds == MAPURL_PATH_ODS_2) *vecptr++ = " ODS=2"; else if (PathOds == MAPURL_PATH_ODS_5) *vecptr++ = " ODS=5"; else if (PathOds == MAPURL_PATH_ODS_PWK) *vecptr++ = " ODS=PWK"; else if (PathOds == MAPURL_PATH_ODS_SMB) *vecptr++ = " ODS=SMB"; else if (PathOds == MAPURL_PATH_ODS_SRI) *vecptr++ = " ODS=SRI"; else *vecptr++ = ""; if (Match == MAPURL_REPORT_MATCH_NOT) *vecptr++ = ".."; else if (Match == MAPURL_REPORT_MATCH_RULE) *vecptr++ = "YN"; else if (Match == MAPURL_REPORT_MATCH_RULECOND) *vecptr++ = "YY"; else if (Match == MAPURL_REPORT_MATCH_RULENOCOND) *vecptr++ = "Y-"; else *vecptr++ = "??"; switch (mrptr->RuleType) { case MAPURL_RULE_EXEC : if (mrptr->IsCgiPlusScript) *vecptr++ = "EXEC+"; else *vecptr++ = "EXEC"; break; case MAPURL_RULE_FAIL : *vecptr++ = "FAIL"; break; case MAPURL_RULE_MAP : *vecptr++ = "MAP"; break; case MAPURL_RULE_PASS : *vecptr++ = "PASS"; break; case MAPURL_RULE_PROTECT : *vecptr++ = "PROTECT"; break; case MAPURL_RULE_REDIRECT : *vecptr++ = "REDIRECT"; break; case MAPURL_RULE_SCRIPT : if (mrptr->IsCgiPlusScript) *vecptr++ = "SCRIPT+"; else *vecptr++ = "SCRIPT"; break; case MAPURL_RULE_SET : if (SetPathIgnore) *vecptr++ = "(SET)"; else *vecptr++ = "SET"; break; case MAPURL_RULE_USER : *vecptr++ = "USER"; break; case MAPURL_RULE_UXEC : if (mrptr->IsCgiPlusScript) *vecptr++ = "UXEC+"; else *vecptr++ = "UXEC"; break; default : *vecptr++ = "*ERROR*"; } *vecptr++ = mrptr->TemplatePtr; if (isdigit(*mrptr->ResultPtr)) { *vecptr++ = "\"!AZ\""; *vecptr++ = mrptr->ResultPtr; } else { *vecptr++ = "!AZ"; *vecptr++ = mrptr->ResultPtr; } if (mrptr->PathSet) { *vecptr++ = " !AZ"; *vecptr++ = MapUrl_ExplainPathSet (rqptr, mrptr); } else *vecptr++ = ""; if (mrptr->ConditionalPtr[0]) { *vecptr++ = " !AZ"; *vecptr++ = mrptr->ConditionalPtr; } else *vecptr++ = ""; status = FaolToBuffer (Buffer, sizeof(Buffer), &Length, RuleFao, &FaoVector); if (VMSnok (status) || status == SS$_BUFFEROVF) ErrorNoticed (rqptr, status, NULL, FI_LI); if (WATCHING (rqptr, WATCH_MAPPING)) WatchData (Buffer, Length); } /*****************************************************************************/ /* Display mapping rules used to resolve the path in the query string. Called from the Request.c modules. For HTTP report, uses blocking network write. There are a number of intermediate FaolToBuffer()s. This was done only to make the format strings a bit easier to manage. */ char* MapUrl_ExplainPathSet ( REQUEST_STRUCT *rqptr, MAP_RULE_META *mrptr ) { static char Buffer [MAP_BUFFER_SIZE]; int blen, status; unsigned short slen; unsigned long FaoVector [32]; unsigned long *vecptr; char *bptr; char FaoString [1024], RegexNumString [32]; MAP_SET_META *mrpsptr; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD_MAPURL)) WatchThis (WATCHITM(rqptr), WATCH_MOD_MAPURL, "MapUrl_ExplainPathSet()"); bptr = Buffer; blen = sizeof(Buffer); mrpsptr = &mrptr->mpPathSet; vecptr = FaoVector; FaoString[0] = 0; if (mrpsptr->NoAcceptLang) strcat (FaoString, " NOaccept=LANG"); else if (mrpsptr->AcceptLangChar) { strcat (FaoString, " accept=LANG=(default=!AZ,char=!&C,!&?type\rname\r)"); if (mrpsptr->AcceptLangPtr) *vecptr++ = mrpsptr->AcceptLangPtr; else *vecptr++ = ""; *vecptr++ = mrpsptr->AcceptLangChar; *vecptr++ = mrpsptr->AcceptLangTypeVariant; } if (mrpsptr->NoAlert) strcat (FaoString, " NOALERT"); else if (mrpsptr->Alert == MAPURL_PATH_ALERT_END) strcat (FaoString, " ALERT=end"); else if (mrpsptr->Alert == MAPURL_PATH_ALERT_AUTH) strcat (FaoString, " ALERT=auth"); else if (mrpsptr->Alert == MAPURL_PATH_ALERT_MAP) strcat (FaoString, " ALERT=map"); else if (mrpsptr->Alert) { strcat (FaoString, " ALERT=!UL"); *vecptr++ = mrpsptr->Alert; } if (mrpsptr->NoAuthAll) strcat (FaoString, " NOauth=ALL"); else if (mrpsptr->AuthAll) strcat (FaoString, " auth=ALL"); if (mrpsptr->NoAuthMapped) strcat (FaoString, " NOauth=MAPPED"); else if (mrpsptr->AuthMapped) strcat (FaoString, " auth=MAPPED"); if (mrpsptr->NoAuthOnce) strcat (FaoString, " NOauth=ONCE"); else if (mrpsptr->AuthOnce) strcat (FaoString, " auth=ONCE"); if (mrpsptr->AuthSysUafPwdExpUrlPtr) { strcat (FaoString, " auth=SYSUAF=pwdexpURL=!&\"AZ"); *vecptr++ = mrpsptr->AuthSysUafPwdExpUrlPtr; } if (mrpsptr->AuthRevalidateTimeout) { strcat (FaoString, " auth=REVALIDATE=!AZ"); *vecptr++ = MetaConShowSeconds (rqptr, mrpsptr->AuthRevalidateTimeout); } if (FaoString[0]) { status = FaolToBuffer (bptr, blen, &slen, FaoString, &FaoVector); if (VMSnok (status) || status == SS$_BUFFEROVF) { ErrorNoticed (rqptr, status, NULL, FI_LI); return ("*ERROR*"); } bptr += slen; blen -= slen; vecptr = FaoVector; FaoString[0] = 0; } if (mrpsptr->NoCache) strcat (FaoString, " NOcache"); else if (mrpsptr->Cache) strcat (FaoString, " cache"); if (mrpsptr->CacheNoCGI) strcat (FaoString, " cache=noCGI"); else if (mrpsptr->CacheCGI) strcat (FaoString, " cache=CGI"); if (mrpsptr->CacheNoCookie) strcat (FaoString, " cache=nocookie"); else if (mrpsptr->CacheCookie) strcat (FaoString, " cache=cookie"); if (mrpsptr->CacheNoFile) strcat (FaoString, " cache=NOfile"); else if (mrpsptr->CacheFile) strcat (FaoString, " cache=file"); if (mrpsptr->CacheNoNet) strcat (FaoString, " cache=NOnet"); else if (mrpsptr->CacheNet) strcat (FaoString, " cache=net"); if (mrpsptr->CacheNoNPH) strcat (FaoString, " cache=noNPH"); else if (mrpsptr->CacheNPH) strcat (FaoString, " cache=NPH"); if (mrpsptr->CacheNoPermanent) strcat (FaoString, " cache=NOpermanent"); else if (mrpsptr->CachePermanent) strcat (FaoString, " cache=permanent"); if (mrpsptr->CacheNoQuery) strcat (FaoString, " cache=NOquery"); else if (mrpsptr->CacheQuery) strcat (FaoString, " cache=query"); if (mrpsptr->CacheNoScript) strcat (FaoString, " cache=NOscript"); else if (mrpsptr->CacheScript) strcat (FaoString, " cache=script"); if (mrpsptr->CacheNoSSI) strcat (FaoString, " cache=noSSI"); else if (mrpsptr->CacheSSI) strcat (FaoString, " cache=SSI"); if (mrpsptr->CacheExpiresAfter == CACHE_EXPIRES_NONE) strcat (FaoString, " cache=expires=none"); else if (mrpsptr->CacheExpiresAfter == CACHE_EXPIRES_DAY) strcat (FaoString, " cache=expires=day"); else if (mrpsptr->CacheExpiresAfter == CACHE_EXPIRES_HOUR) strcat (FaoString, " cache=expires=hour"); else if (mrpsptr->CacheExpiresAfter == CACHE_EXPIRES_MINUTE) strcat (FaoString, " cache=expires=minute"); else if (mrpsptr->CacheExpiresAfter) { strcat (FaoString, " cache=expires=!AZ"); *vecptr++ = MetaConShowSeconds (rqptr, mrpsptr->CacheExpiresAfter); } if (mrpsptr->CacheGuardSeconds) { strcat (FaoString, " cache=guard=!UL"); if (mrpsptr->CacheGuardSeconds == -1) *vecptr++ = 0; else *vecptr++ = mrpsptr->CacheGuardSeconds; } if (mrpsptr->CacheMaxKBytes) { strcat (FaoString, " cache=max=!UL"); if (mrpsptr->CacheMaxKBytes == -1) *vecptr++ = 0; else *vecptr++ = mrpsptr->CacheMaxKBytes; } if (mrpsptr->CgiPlusInNoWriteof) strcat (FaoString, " cgiplusin=NOeof"); else if (mrpsptr->CgiPlusInWriteof) strcat (FaoString, " cgiplusin=EOF"); if (mrpsptr->CgiPlusInCC[0] || mrpsptr->CgiPlusInCC[1]) { if (mrpsptr->CgiPlusInCC[0] == '\r' && mrpsptr->CgiPlusInCC[1] == '\n') strcat (FaoString, " cgiplusin=cc=CRLF"); else if (mrpsptr->CgiPlusInCC[0] == '\n') strcat (FaoString, " cgiplusin=cc=LF"); else if (mrpsptr->CgiPlusInCC[0] == '\r') strcat (FaoString, " cgiplusin=cc=CR"); else strcat (FaoString, " cgiplusin=cc=NONE"); } if (mrpsptr->CgiPrefixPtr) { strcat (FaoString, " CGI=prefix=!AZ"); *vecptr++ = mrpsptr->CgiPrefixPtr; } if (mrpsptr->CharsetPtr) { strcat (FaoString, " charset=!&\"AZ"); *vecptr++ = mrpsptr->CharsetPtr; } if (mrpsptr->ClientAddress == MAPURL_CLIENT_FORWARDED) strcat (FaoString, " client=FORWARDED"); else if (mrpsptr->ClientAddress == MAPURL_CLIENT_IF_FORWARDED) strcat (FaoString, " client=IF=FORWARDED"); else if (mrpsptr->ClientAddress == MAPURL_CLIENT_IF_XFORWARDEDFOR) strcat (FaoString, " client=IF=XFORWARDEDFOR"); else if (mrpsptr->ClientAddress == MAPURL_CLIENT_LITERAL) { strcat (FaoString, " client=LITERAL=\"!AZ\""); *vecptr++ = mrpsptr->ClientAddressLiteralPtr; } else if (mrpsptr->ClientAddress == MAPURL_CLIENT_RESET) strcat (FaoString, " client=RESET"); else if (mrpsptr->ClientAddress == MAPURL_CLIENT_XFORWARDEDFOR) strcat (FaoString, " client=XFORWARDEDFOR"); if (mrpsptr->ContentTypePtr) { strcat (FaoString, " content=!&\"AZ"); *vecptr++ = mrpsptr->ContentTypePtr; } if (mrpsptr->CorsMaxAge) { strcat (FaoString, " cors=AGE=!UL"); *vecptr++ = mrpsptr->CorsMaxAge; } if (mrpsptr->CorsAllowCredentials) strcat (FaoString, " cors=CRED=true"); else if (mrpsptr->CorsNoAllowCredentials) strcat (FaoString, " cors=CRED=false"); if (mrpsptr->CorsExposeHeadersPtr) { strcat (FaoString, " cors=EXPOSE=!&\"AZ"); *vecptr++ = mrpsptr->CorsExposeHeadersPtr; } if (mrpsptr->CorsAllowHeadersPtr) { strcat (FaoString, " cors=HEADERS=!&\"AZ"); *vecptr++ = mrpsptr->CorsAllowHeadersPtr; } if (mrpsptr->CorsAllowMethodsPtr) { strcat (FaoString, " cors=METHODS=!&\"AZ"); *vecptr++ = mrpsptr->CorsAllowMethodsPtr; } if (mrpsptr->CorsAllowOriginPtr) { strcat (FaoString, " cors=ORIGIN=!&\"AZ"); *vecptr++ = mrpsptr->CorsAllowOriginPtr; } if (FaoString[0]) { status = FaolToBuffer (bptr, blen, &slen, FaoString, &FaoVector); if (VMSnok (status) || status == SS$_BUFFEROVF) { ErrorNoticed (rqptr, status, NULL, FI_LI); return ("*ERROR*"); } bptr += slen; blen -= slen; vecptr = FaoVector; FaoString[0] = 0; } if (mrpsptr->DictionaryPtr) { strcat (FaoString, " dict=!&\"AZ"); *vecptr++ = mrpsptr->DictionaryPtr; } if (mrpsptr->DirNoAccess) strcat (FaoString, " dir=NOaccess"); else if (mrpsptr->DirAccess) strcat (FaoString, " dir=access"); else if (mrpsptr->DirAccessSelective) strcat (FaoString, " dir=access=selective"); if (mrpsptr->DirCharsetPtr) { strcat (FaoString, " dir=charset=!&\"AZ"); *vecptr++ = mrpsptr->DirCharsetPtr; } if (mrpsptr->DirDelimit == MAPURL_DIR_DELIMIT_BOTH) strcat (FaoString, " dir=DELIMIT=both"); else if (mrpsptr->DirDelimit == MAPURL_DIR_DELIMIT_HEADER) strcat (FaoString, " dir=DELIMIT=header"); else if (mrpsptr->DirDelimit == MAPURL_DIR_DELIMIT_FOOTER) strcat (FaoString, " dir=DELIMIT=footer"); else if (mrpsptr->DirDelimit == MAPURL_DIR_DELIMIT_NONE) strcat (FaoString, " dir=DELIMIT=none"); if (mrpsptr->DirFont == MAPURL_DIR_FONT_INHERIT) strcat (FaoString, " dir=FONT=inherit"); else if (mrpsptr->DirFont == MAPURL_DIR_FONT_MONOSPACE) strcat (FaoString, " dir=FONT=monospace"); if (mrpsptr->DirNoIconLink) strcat (FaoString, " dir=NOilink"); else if (mrpsptr->DirIconLink) strcat (FaoString, " dir=ilink"); if (mrpsptr->DirNoImpliedWildcard) strcat (FaoString, " dir=NOimpliedwildcard"); else if (mrpsptr->DirImpliedWildcard) strcat (FaoString, " dir=impliedwildcard"); if (mrpsptr->DirSort[0]) { strcat (FaoString, " dir=SORT=!AZ"); *vecptr++ = mrpsptr->DirSort; } if (mrpsptr->DirStyle == MAPURL_DIR_STYLE_DEFAULT) strcat (FaoString, " dir=style=default"); else if (mrpsptr->DirStyle == MAPURL_DIR_STYLE_DEFAULT2) strcat (FaoString, " dir=style=default2"); else if (mrpsptr->DirStyle == MAPURL_DIR_STYLE_ANCHOR) strcat (FaoString, " dir=style=anchor"); else if (mrpsptr->DirStyle == MAPURL_DIR_STYLE_ANCHOR2) strcat (FaoString, " dir=style=anchor2"); else if (mrpsptr->DirStyle == MAPURL_DIR_STYLE_HTDIR) strcat (FaoString, " dir=style=htdir"); else if (mrpsptr->DirStyle == MAPURL_DIR_STYLE_HTDIR2) strcat (FaoString, " dir=style=htdir2"); else if (mrpsptr->DirStyle == MAPURL_DIR_STYLE_ORIGINAL) strcat (FaoString, " dir=style=original"); else if (mrpsptr->DirStyle == MAPURL_DIR_STYLE_ORIGINAL2) strcat (FaoString, " dir=style=original2"); else if (mrpsptr->DirStyle == MAPURL_DIR_STYLE_SORT) strcat (FaoString, " dir=style=sort"); else if (mrpsptr->DirStyle == MAPURL_DIR_STYLE_SORT2) strcat (FaoString, " dir=style=sort2"); if (mrpsptr->DirTargetPtr) { strcat (FaoString, " dir=TARGET=\"!AZ\""); *vecptr++ = mrpsptr->DirTargetPtr; } if (mrpsptr->DirThesePtr) { strcat (FaoString, " dir=THESE=\"!AZ\""); *vecptr++ = mrpsptr->DirThesePtr; } if (mrpsptr->DirTitle == MAPURL_DIR_TITLE_THIS) { strcat (FaoString, " dir=TITLE=this=\"!AZ\""); *vecptr++ = mrpsptr->DirTitlePtr; } else if (mrpsptr->DirTitle == MAPURL_DIR_TITLE_DEFAULT) strcat (FaoString, " dir=TITLE=default"); else if (mrpsptr->DirTitle == MAPURL_DIR_TITLE_OWNER) strcat (FaoString, " dir=TITLE=owner"); else if (mrpsptr->DirTitle == MAPURL_DIR_TITLE_REMOTE) strcat (FaoString, " dir=TITLE=remote"); else if (mrpsptr->DirTitle == MAPURL_DIR_TITLE_NONE) strcat (FaoString, " dir=TITLE=0"); else if (mrpsptr->DirTitle) { strcat (FaoString, " dir=TITLE=!UL"); *vecptr++ = mrpsptr->DirTitle; } if (mrpsptr->DirVersionsOf) { if (mrpsptr->DirVersionsOf == 65536) strcat (FaoString, " dir=VERSIONS=*"); else if (mrpsptr->DirVersionsOf == -1) strcat (FaoString, " dir=VERSIONS=0"); else { strcat (FaoString, " dir=VERSIONS=!UL"); *vecptr++ = mrpsptr->DirVersionsOf; } } if (mrpsptr->DirNoWildcard) strcat (FaoString, " dir=NOwildcard"); else if (mrpsptr->DirWildcard) strcat (FaoString, " dir=wildcard"); if (mrpsptr->NoExpired) strcat (FaoString, " NOexpired"); else if (mrpsptr->Expired) strcat (FaoString, " expired"); if (mrpsptr->Http2ToHttp11) strcat (FaoString, " HTTP2=protocol=1.1"); if (mrpsptr->Http2MaxStreams) { strcat (FaoString, " HTTP2=streams=max=!UL"); *vecptr++ = mrpsptr->Http2MaxStreams; } if (mrpsptr->Http2WriteQueue == HTTP2_WRITE_QUEUE_HIGH) strcat (FaoString, " HTTP2=write=high"); else if (mrpsptr->Http2WriteQueue == HTTP2_WRITE_QUEUE_NORMAL) strcat (FaoString, " HTTP2=write=normal"); else if (mrpsptr->Http2WriteQueue == HTTP2_WRITE_QUEUE_LOW) strcat (FaoString, " HTTP2=write=low"); if (mrpsptr->Http2SendGoAway) { strcat (FaoString, " HTTP2=send=goaway=!UL"); *vecptr++ = mrpsptr->Http2SendGoAway - 1; } if (mrpsptr->Http2SendPing) strcat (FaoString, " HTTP2=send=ping"); if (mrpsptr->Http2SendReset) { strcat (FaoString, " HTTP2=send=reset=!UL"); *vecptr++ = mrpsptr->Http2SendReset - 1; } if (mrpsptr->HttpAcceptCharsetPtr) { strcat (FaoString, " http=Accept-Charset=!&\"AZ"); *vecptr++ = mrpsptr->HttpAcceptCharsetPtr; } if (mrpsptr->HtmlBodyTagPtr) { strcat (FaoString, " html=bodytag=!&\"AZ"); *vecptr++ = mrpsptr->HtmlBodyTagPtr; } if (mrpsptr->HtmlHeaderTagPtr) { strcat (FaoString, " html=headertag=!&\"AZ"); *vecptr++ = mrpsptr->HtmlHeaderTagPtr; } if (mrpsptr->HtmlHeaderPtr) { strcat (FaoString, " html=header=!&\"AZ"); *vecptr++ = mrpsptr->HtmlHeaderPtr; } if (mrpsptr->HtmlFooterTagPtr) { strcat (FaoString, " html=footertag=!&\"AZ"); *vecptr++ = mrpsptr->HtmlFooterTagPtr; } if (mrpsptr->HtmlFooterPtr) { strcat (FaoString, " html=footer=!&\"AZ"); *vecptr++ = mrpsptr->HtmlFooterPtr; } if (mrpsptr->HttpAcceptLangPtr) { strcat (FaoString, " http=Accept-Language=!&\"AZ"); *vecptr++ = mrpsptr->HttpAcceptLangPtr; } if (mrpsptr->IndexPtr) { strcat (FaoString, " index=!AZ"); *vecptr++ = mrpsptr->IndexPtr; } if (mrpsptr->NoLog) strcat (FaoString, " NOlog"); else if (mrpsptr->Log) strcat (FaoString, " log"); if (FaoString[0]) { status = FaolToBuffer (bptr, blen, &slen, FaoString, &FaoVector); if (VMSnok (status) || status == SS$_BUFFEROVF) { ErrorNoticed (rqptr, status, NULL, FI_LI); return ("*ERROR*"); } bptr += slen; blen -= slen; vecptr = FaoVector; FaoString[0] = '\0'; } if (mrpsptr->NoMapEllipsis) strcat (FaoString, " map=NOELLIPSIS"); else if (mrpsptr->MapEllipsis) strcat (FaoString, " map=ELLIPSIS"); if (mrpsptr->MapNonEmpty) strcat (FaoString, " map=NOEMPTY"); else if (mrpsptr->MapEmpty) strcat (FaoString, " map=EMPTY"); if (mrpsptr->NoMapExtensionMethod) strcat (FaoString, " map=NOMETHOD"); else if (mrpsptr->MapExtensionMethod) strcat (FaoString, " map=METHOD"); if (mrpsptr->NoMapOnce) strcat (FaoString, " map=NOONCE"); else if (mrpsptr->MapOnce) strcat (FaoString, " map=ONCE"); if (mrpsptr->MapRestart) strcat (FaoString, " map=RESTART"); if (mrpsptr->MapSetNoIgnore) strcat (FaoString, " map=SET=noignore"); else if (mrpsptr->MapSetIgnore) strcat (FaoString, " map=SET=ignore"); if (mrpsptr->MapSetNoRequest) strcat (FaoString, " map=SET=norequest"); else if (mrpsptr->MapSetRequest) strcat (FaoString, " map=SET=request"); if (mrpsptr->MapUri) strcat (FaoString, " map=URI"); if (mrpsptr->MapRootPtr) { strcat (FaoString, " map=ROOT=!AZ"); *vecptr++ = mrpsptr->MapRootPtr; } if (mrpsptr->NotePadPtr) { strcat (FaoString, " notepad=!&\"AZ"); *vecptr++ = mrpsptr->NotePadPtr; } if (mrpsptr->PathOds == MAPURL_PATH_ODS_0) strcat (FaoString, " NOods"); else if (mrpsptr->PathOds == MAPURL_PATH_ODS_2) strcat (FaoString, " ods=2"); else if (mrpsptr->PathOds == MAPURL_PATH_ODS_5) strcat (FaoString, " ods=5"); else if (mrpsptr->PathOds == MAPURL_PATH_ODS_PWK) strcat (FaoString, " ods=PWK"); else if (mrpsptr->PathOds == MAPURL_PATH_ODS_SMB) strcat (FaoString, " ods=SMB"); else if (mrpsptr->PathOds == MAPURL_PATH_ODS_SRI) strcat (FaoString, " ods=SRI"); if (mrpsptr->OdsName == MAPURL_ODS_8BIT) strcat (FaoString, " ods=name=8BIT"); else if (mrpsptr->OdsName == MAPURL_ODS_UTF8) strcat (FaoString, " ods=name=UTF8"); else if (mrpsptr->OdsName == MAPURL_ODS_DEFAULT) strcat (FaoString, " ods=name=DEFAULT"); if (mrpsptr->NoProfile) strcat (FaoString, " NOprofile"); else if (mrpsptr->Profile) strcat (FaoString, " profile"); if (mrpsptr->ProxyNoAffinity) strcat (FaoString, " proxy=NOAFFINITY"); else if (mrpsptr->ProxyAffinity) strcat (FaoString, " proxy=AFFINITY"); if (mrpsptr->ProxyBindIpAddressPtr) { strcat (FaoString, " proxy=BIND=!AZ"); *vecptr++ = mrpsptr->ProxyBindIpAddressPtr; } if (mrpsptr->ProxyChainHostPortPtr) { strcat (FaoString, " proxy=CHAIN=!AZ"); *vecptr++ = mrpsptr->ProxyChainHostPortPtr; } if (mrpsptr->ProxyChainCredPtr) { strcat (FaoString, " proxy=CHAIN=CRED=!AZ"); *vecptr++ = mrpsptr->ProxyChainCredPtr; } if (mrpsptr->ProxyForwardedBy == PROXY_FORWARDED_NONE) strcat (FaoString, " proxy=NOforwarded"); else if (mrpsptr->ProxyForwardedBy == PROXY_FORWARDED_BY) strcat (FaoString, " proxy=FORWARDED=by"); else if (mrpsptr->ProxyForwardedBy == PROXY_FORWARDED_FOR) strcat (FaoString, " proxy=FORWARDED=for"); else if (mrpsptr->ProxyForwardedBy == PROXY_FORWARDED_ADDRESS) strcat (FaoString, " proxy=FORWARDED=address"); if (mrpsptr->ProxyReverseLocationLength) { strcat (FaoString, " proxy=REVERSE=location=!AZ"); *vecptr++ = mrpsptr->ProxyReverseLocationPtr; } if (mrpsptr->ProxyXForwardedFor == PROXY_XFORWARDEDFOR_NONE) strcat (FaoString, " proxy=NOxforwardedfor"); else if (mrpsptr->ProxyXForwardedFor == PROXY_XFORWARDEDFOR_ENABLED) strcat (FaoString, " proxy=XFORWARDEDFOR=enabled"); else if (mrpsptr->ProxyXForwardedFor == PROXY_XFORWARDEDFOR_ADDRESS) strcat (FaoString, " proxy=XFORWARDEDFOR=address"); else if (mrpsptr->ProxyXForwardedFor == PROXY_XFORWARDEDFOR_UNKNOWN) strcat (FaoString, " proxy=XFORWARDEDFOR=unknown"); if (mrpsptr->NoProxyReverseVerify) strcat (FaoString, " proxy=REVERSE=NOverify"); else if (mrpsptr->ProxyReverseVerify) strcat (FaoString, " proxy=REVERSE=verify"); if (mrpsptr->NoProxyReverseAuthHeader) strcat (FaoString, " proxy=REVERSE=NOauth"); else if (mrpsptr->ProxyReverseAuthHeader) strcat (FaoString, " proxy=REVERSE=auth"); if (mrpsptr->ProxyTunnelRequestPtr) { strcat (FaoString, " proxy=tunnel=request=!&\\&\"AZ"); *vecptr++ = mrpsptr->ProxyTunnelRequestPtr; } if (mrpsptr->NoProxyUnknownRequestFields) strcat (FaoString, " proxy=NOUNKNOWN"); else if (mrpsptr->ProxyUnknownRequestFields) strcat (FaoString, " proxy=UNKNOWN"); if (FaoString[0]) { status = FaolToBuffer (bptr, blen, &slen, FaoString, &FaoVector); if (VMSnok (status) || status == SS$_BUFFEROVF) { ErrorNoticed (rqptr, status, NULL, FI_LI); return ("*ERROR*"); } bptr += slen; blen -= slen; vecptr = FaoVector; FaoString[0] = '\0'; } if (mrpsptr->ProxyHeaderCount) { for (int idx = 0; idx < mrpsptr->ProxyHeaderCount; idx++) { *vecptr++ = mrpsptr->ProxyHeader[idx]; status = FaolToBuffer (bptr, blen, &slen, " proxy=HEADER=!AZ", &FaoVector); if (VMSnok (status) || status == SS$_BUFFEROVF) { ErrorNoticed (rqptr, status, NULL, FI_LI); return ("*ERROR*"); } bptr += slen; blen -= slen; vecptr = FaoVector; FaoString[0] = '\0'; } } if (mrpsptr->PutRFM == PUT_RFM_FIX512) strcat (FaoString, " put=FIX512"); else if (mrpsptr->PutRFM == PUT_RFM_STM) strcat (FaoString, " put=STM"); else if (mrpsptr->PutRFM == PUT_RFM_STMCR) strcat (FaoString, " put=STMCR"); else if (mrpsptr->PutRFM == PUT_RFM_STMLF) strcat (FaoString, " put=STMLF"); else if (mrpsptr->PutRFM == PUT_RFM_UDF) strcat (FaoString, " put=UDF"); if (mrpsptr->PutMaxKbytes) { strcat (FaoString, " put=MAX=!UL"); *vecptr++ = mrpsptr->PutMaxKbytes; } if (mrpsptr->RegexSyntax) { strcat (FaoString, " regex=!AZ"); switch (mrpsptr->RegexSyntax) { 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; case REGEX_C_FLAGS : *vecptr++ = "WASD"; break; case -1 : *vecptr++ = "default"; break; default : vecptr--; /** jump back one! **/ *vecptr++ = " regex=!8XL"; *vecptr = mrpsptr->RegexSyntax; } } if (mrpsptr->ReportType == ERROR_REPORT_BASIC) strcat (FaoString, " report=BASIC"); else if (mrpsptr->ReportType == ERROR_REPORT_DETAILED) strcat (FaoString, " report=DETAILED"); else if (mrpsptr->ReportType == ERROR_REPORT_TUNNEL) strcat (FaoString, " report=TUNNEL"); if (mrpsptr->Report400as) { strcat (FaoString, " report=400=!UL"); *vecptr++ = mrpsptr->Report400as; } if (mrpsptr->Report403as) { strcat (FaoString, " report=403=!UL"); *vecptr++ = mrpsptr->Report403as; } if (mrpsptr->Report404as) { strcat (FaoString, " report=404=!UL"); *vecptr++ = mrpsptr->Report404as; } if (mrpsptr->Response200is203 == 203) strcat (FaoString, " response=200=203"); else if (mrpsptr->Response200is203 == 200) strcat (FaoString, " response=203=200"); if (mrpsptr->ResponseGzip == MAPURL_RESPONSE_GZIP_ALL) strcat (FaoString, " response=GZIP=all"); else if (mrpsptr->ResponseGzip == MAPURL_RESPONSE_GZIP_NONE) strcat (FaoString, " response=GZIP=none"); else if (mrpsptr->ResponseGzip) { strcat (FaoString, " response=GZIP=!UL"); *vecptr++ = mrpsptr->ResponseGzip; } if (mrpsptr->ResponseNoChunked) strcat (FaoString, " response=NOchunked"); else if (mrpsptr->ResponseChunked) strcat (FaoString, " response=chunked"); if (mrpsptr->ResponseCspLength) { if (mrpsptr->ResponseCspLength < 0) strcat (FaoString, " response=NOcsp"); else { strcat (FaoString, " response=csp=!&\"AZ"); *vecptr++ = mrpsptr->ResponseCspPtr; } } if (mrpsptr->ResponseCsproLength) { if (mrpsptr->ResponseCsproLength < 0) strcat (FaoString, " response=NOcspro"); else { strcat (FaoString, " response=cspro=!&\"AZ"); *vecptr++ = mrpsptr->ResponseCsproPtr; } } if (mrpsptr->ResponseHeaderNone) strcat (FaoString, " response=header=none"); else if (mrpsptr->ResponseHeaderBegin) strcat (FaoString, " response=header=begin"); else if (mrpsptr->ResponseHeaderFull) strcat (FaoString, " response=header=full"); if (mrpsptr->ResponseHeaderNoAdd) strcat (FaoString, " response=header=NOadd"); if (mrpsptr->ResponseHeaderAddLength) { strcat (FaoString, " response=header=add=!&\"AZ"); *vecptr++ = mrpsptr->ResponseHeaderAddPtr; } if (mrpsptr->ResponseHttpNoOriginal) strcat (FaoString, " response=HTTP=NOoriginal"); else if (mrpsptr->ResponseHttpOriginal) strcat (FaoString, " response=HTTP=original"); if (mrpsptr->ResponseStrictTransSecPtr) { strcat (FaoString, " response=STS=\"!AZ\""); *vecptr++ = mrpsptr->ResponseStrictTransSecPtr; } if (mrpsptr->ResponseVarRecord == FILE_VAR_CRLF) strcat (FaoString, " response=VAR=CRLF"); else if (mrpsptr->ResponseVarRecord == FILE_VAR_LF) strcat (FaoString, " response=VAR=LF"); else if (mrpsptr->ResponseVarRecord == FILE_VAR_NONE) strcat (FaoString, " response=VAR=NONE"); if (FaoString[0]) { status = FaolToBuffer (bptr, blen, &slen, FaoString, &FaoVector); if (VMSnok (status) || status == SS$_BUFFEROVF) { ErrorNoticed (rqptr, status, NULL, FI_LI); return ("*ERROR*"); } bptr += slen; blen -= slen; vecptr = FaoVector; FaoString[0] = '\0'; } if (mrpsptr->ScriptBodyNoDecode) strcat (FaoString, " script=BODY=NOdecode"); else if (mrpsptr->ScriptBodyDecode) strcat (FaoString, " script=BODY=decode"); if (mrpsptr->ScriptSymbolNoTruncate) strcat (FaoString, " script=SYMBOL=NOtruncate"); else if (mrpsptr->ScriptSymbolTruncate) strcat (FaoString, " script=SYMBOL=truncate"); if (mrpsptr->ScriptSyntaxNoUnix) strcat (FaoString, " script=SYNTAX=NOunix"); else if (mrpsptr->ScriptSyntaxUnix) strcat (FaoString, " script=SYNTAX=unix"); if (mrpsptr->ScriptNoFind) strcat (FaoString, " script=NOfind"); else if (mrpsptr->ScriptFind) strcat (FaoString, " script=FIND"); if (mrpsptr->ScriptNoPathFind) strcat (FaoString, " NOscript=PATH=find"); else if (mrpsptr->ScriptPathFind) strcat (FaoString, " script=PATH=find"); if (mrpsptr->ScriptNoQueryNone) strcat (FaoString, " NOscript=QUERY=none"); else if (mrpsptr->ScriptQueryNone) strcat (FaoString, " script=QUERY=none"); if (mrpsptr->ScriptNoQueryRelaxed) strcat (FaoString, " NOscript=QUERY=relaxed"); else if (mrpsptr->ScriptQueryRelaxed) strcat (FaoString, " script=QUERY=relaxed"); if (mrpsptr->NoDefaultSearch) strcat (FaoString, " search=none"); else if (mrpsptr->DefaultSearch) strcat (FaoString, " NOsearch=none"); if (mrpsptr->ChangeServicePtr) { strcat (FaoString, " service=!AZ"); *vecptr++ = mrpsptr->ChangeServicePtr; } if (mrpsptr->NoPrivSsi) strcat (FaoString, " NOssi=PRIV"); else if (mrpsptr->PrivSsi) strcat (FaoString, " ssi=PRIV"); if (mrpsptr->SsiExecPtr) { strcat (FaoString, " ssi=EXEC=!AZ"); *vecptr++ = mrpsptr->SsiExecPtr; } if (mrpsptr->StyleSheetPtr) { strcat (FaoString, " css=!AZ"); *vecptr++ = mrpsptr->StyleSheetPtr; } if (mrpsptr->SSLCGIvar == SESOLA_CGI_VAR_APACHE_MOD_SSL) strcat (FaoString, " SSLCGI=Apache_mod_SSL"); else if (mrpsptr->SSLCGIvar == SESOLA_CGI_VAR_APACHE_MOD_SSL_CLIENT) strcat (FaoString, " SSLCGI=Apache_mod_SSL_client"); else if (mrpsptr->SSLCGIvar == SESOLA_CGI_VAR_APACHE_MOD_SSL_EXTENS) strcat (FaoString, " SSLCGI=Apache_mod_SSL_extens"); else if (mrpsptr->SSLCGIvar == SESOLA_CGI_VAR_APACHE_MOD_SSL_OID) strcat (FaoString, " SSLCGI=Apache_mod_SSL_OID"); else if (mrpsptr->SSLCGIvar == SESOLA_CGI_VAR_PURVEYOR) strcat (FaoString, " SSLCGI=Purveyor"); if (mrpsptr->NoStmLF) strcat (FaoString, " NOstmLF"); else if (mrpsptr->StmLF) strcat (FaoString, " stmLF"); if (FaoString[0]) { status = FaolToBuffer (bptr, blen, &slen, FaoString, &FaoVector); if (VMSnok (status) || status == SS$_BUFFEROVF) { ErrorNoticed (rqptr, status, NULL, FI_LI); return ("*ERROR*"); } bptr += slen; blen -= slen; vecptr = FaoVector; FaoString[0] = '\0'; } if (mrpsptr->QueryStringPtr) { strcat (FaoString, " query-string=!&\"AZ"); *vecptr++ = mrpsptr->QueryStringPtr; } if (mrpsptr->RmsSubChar) { strcat (FaoString, " RMSchar=!&C"); *vecptr++ = mrpsptr->RmsSubChar; } if (mrpsptr->ScriptAgentAsPtr) { strcat (FaoString, " script=AGENT=AS=!AZ"); *vecptr++ = mrpsptr->ScriptAgentAsPtr; } if (mrpsptr->ScriptAsPtr) { strcat (FaoString, " script=AS=!AZ"); *vecptr++ = mrpsptr->ScriptAsPtr; } if (mrpsptr->ScriptCommandPtr) { strcat (FaoString, " script=COMMAND=!&\"AZ"); *vecptr++ = mrpsptr->ScriptCommandPtr; } if (mrpsptr->ScriptControlPtr) { strcat (FaoString, " script=CONTROL=!&\"AZ"); *vecptr++ = mrpsptr->ScriptControlPtr; } if (mrpsptr->ScriptDefaultPtr) { strcat (FaoString, " script=DEFAULT=!AZ"); *vecptr++ = mrpsptr->ScriptDefaultPtr; } if (mrpsptr->ScriptBitBucketTimeout) { strcat (FaoString, " script=BIT-BUCKET=!AZ"); *vecptr++ = MetaConShowSeconds (rqptr, mrpsptr->ScriptBitBucketTimeout); } if (mrpsptr->ScriptCpuMax) { strcat (FaoString, " script=CPU=!UL"); *vecptr++ = mrpsptr->ScriptCpuMax; } if (mrpsptr->ScriptLifeTime) { strcat (FaoString, " script=lifetime=!AZ"); *vecptr++ = MetaConShowSeconds (rqptr, mrpsptr->ScriptLifeTime); } if (mrpsptr->ScriptParamsPtr) { strcat (FaoString, " script=PARAMS=!&\"AZ"); *vecptr++ = mrpsptr->ScriptParamsPtr; } if (mrpsptr->TimeoutPersistent > 0 || mrpsptr->TimeoutNoProgress > 0 || mrpsptr->TimeoutOutput > 0) { strcat (FaoString, " timeout=!AZ(p),!AZ(np),!AZ(o)"); *vecptr++ = MetaConShowSeconds (rqptr, mrpsptr->TimeoutPersistent); *vecptr++ = MetaConShowSeconds (rqptr, mrpsptr->TimeoutNoProgress); *vecptr++ = MetaConShowSeconds (rqptr, mrpsptr->TimeoutOutput); } else if (mrpsptr->TimeoutPersistent < 0 && mrpsptr->TimeoutNoProgress < 0 && mrpsptr->TimeoutOutput < 0) strcat (FaoString, " notimeout"); if (mrpsptr->ThrottleNoSet) strcat (FaoString, " throttle=NONE"); else if (mrpsptr->ThrottleSet) { if (mrpsptr->ThrottlePerUser) { strcat (FaoString, " throttle=!UL$!UL,!UL,!UL,!UL,!AZ,!AZ"); *vecptr++ = mrpsptr->ThrottleFrom; *vecptr++ = mrpsptr->ThrottlePerUser; } else { strcat (FaoString, " throttle=!UL,!UL,!UL,!UL,!AZ,!AZ"); *vecptr++ = mrpsptr->ThrottleFrom; } *vecptr++ = mrpsptr->ThrottleTo; *vecptr++ = mrpsptr->ThrottleResume; *vecptr++ = mrpsptr->ThrottleBusy; *vecptr++ = MetaConShowSeconds (rqptr, mrpsptr->ThrottleTimeoutQueue); *vecptr++ = MetaConShowSeconds (rqptr, mrpsptr->ThrottleTimeoutBusy); } if (mrpsptr->AccessNoProfile) strcat (FaoString, " access=NOprofile"); else if (mrpsptr->AccessProfile) strcat (FaoString, " access=profile"); if (mrpsptr->AccessNoRead) strcat (FaoString, " access=NOread"); else if (mrpsptr->AccessRead) strcat (FaoString, " access=read"); if (mrpsptr->AccessNoServer) strcat (FaoString, " access=NOserver"); else if (mrpsptr->AccessServer) strcat (FaoString, " access=server"); if (mrpsptr->AccessNoWrite) strcat (FaoString, " access=NOwrite"); else if (mrpsptr->AccessWrite) strcat (FaoString, " access=write"); if (FaoString[0]) { status = FaolToBuffer (bptr, blen, &slen, FaoString, &FaoVector); if (VMSnok (status) || status == SS$_BUFFEROVF) { ErrorNoticed (rqptr, status, NULL, FI_LI); return ("*ERROR*"); } bptr += slen; blen -= slen; vecptr = FaoVector; FaoString[0] = '\0'; } if (mrpsptr->WebDavNoServer) strcat (FaoString, " WebDAV=NOserver"); else if (mrpsptr->WebDavServer) strcat (FaoString, " WebDAV=server"); if (mrpsptr->WebDavNoHidden) strcat (FaoString, " WebDAV=NOhidden"); else if (mrpsptr->WebDavHidden) strcat (FaoString, " WebDAV=hidden"); if (mrpsptr->WebDavNoLock) strcat (FaoString, " WebDAV=NOlock"); else if (mrpsptr->WebDavLock) strcat (FaoString, " WebDAV=lock"); if (mrpsptr->WebDavMetaDirPtr) { strcat (FaoString, " webdav=META=dir=!&\"AZ"); *vecptr++ = mrpsptr->WebDavMetaDirPtr; } if (mrpsptr->WebDavNoProfile) strcat (FaoString, " WebDAV=NOprofile"); else if (mrpsptr->WebDavProfile) strcat (FaoString, " WebDAV=profile"); if (mrpsptr->WebDavNoProp) strcat (FaoString, " WebDAV=NOprop"); else if (mrpsptr->WebDavProp) strcat (FaoString, " WebDAV=prop"); if (mrpsptr->WebDavNoPutLock) strcat (FaoString, " WebDAV=NOPUT=lock"); else if (mrpsptr->WebDavPutLock) strcat (FaoString, " WebDAV=PUT=lock"); if (mrpsptr->WebDavNoRead) strcat (FaoString, " WebDAV=NOread"); else if (mrpsptr->WebDavRead) strcat (FaoString, " WebDAV=read"); if (mrpsptr->WebDavNoWinProp) strcat (FaoString, " WebDAV=NOwinprop"); else if (mrpsptr->WebDavWinProp) strcat (FaoString, " WebDAV=winprop"); if (mrpsptr->WebDavNoWrite) strcat (FaoString, " WebDAV=NOwrite"); else if (mrpsptr->WebDavWrite) strcat (FaoString, " WebDAV=write"); if (mrpsptr->WebDavLockTimeoutDefault) { strcat (FaoString, " WebDAV=lock=timeout=default=!AZ"); *vecptr++ = MetaConShowSeconds (rqptr, mrpsptr->WebDavLockTimeoutDefault); } if (mrpsptr->WebDavLockTimeoutMax) { strcat (FaoString, " WebDAV=lock=timeout=max=!AZ"); *vecptr++ = MetaConShowSeconds (rqptr, mrpsptr->WebDavLockTimeoutMax); } if (mrpsptr->WebSocketInputSize) { strcat (FaoString, " WebSocket=input=!UL"); *vecptr++ = mrpsptr->WebSocketInputSize; } if (mrpsptr->WebSocketOutputSize) { strcat (FaoString, " WebSocket=output=!UL"); *vecptr++ = mrpsptr->WebSocketOutputSize; } if (FaoString[0]) { status = FaolToBuffer (bptr, blen, &slen, FaoString, &FaoVector); if (VMSnok (status) || status == SS$_BUFFEROVF) { ErrorNoticed (rqptr, status, NULL, FI_LI); return ("*ERROR*"); } } return (Buffer); } /*****************************************************************************/ /* Supplied with an integer in 'ThrottleIndex' representing the element number of the 'ThrottleArray' path, scan through all the paths in the rule list noting all SET THROTTLE= paths until the count equals that of the integer supplied. This is the rule representing that index. Return a pointer to the rule, or NULL. */ MAP_RULE_META* MapUrl_ThrottleRule (int ThrottleIndex) { int RuleCount; MAP_RULE_META *mrptr; MAP_SET_META *mrpsptr; METACON_LINE *mclptr; /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD_MAPURL)) WatchThis (WATCHALL, WATCH_MOD_MAPURL, "MapUrl_ThrottleRule() !UL", ThrottleIndex); RuleCount = 0; MetaConParseReset (MetaGlobalMappingPtr, true); while (mclptr = MetaConParseRaw (MetaGlobalMappingPtr)) { if (!(mrptr = mclptr->LineDataPtr)) continue; mrpsptr = &mrptr->mpPathSet; if (!mrpsptr->ThrottleSet) continue; if (ThrottleIndex != RuleCount++) continue; return (mrptr); } return (NULL); } /*****************************************************************************/ /* Reload the mapping rules. */ MapUrl_ControlReload () { /*********/ /* begin */ /*********/ if ((WATCH_MODULE(WATCH_MOD_MAPURL))) WatchThis (WATCHALL, WATCH_MOD_MAPURL, "MapUrl_ControlReload()"); MetaConUnload (&MetaGlobalMappingPtr, &MapUrl_ConfigUnloadLineData); MapUrl_ConfigLoad (&MetaGlobalMappingPtr); /* purge DCL module script task list and script name cache */ DclLoadedMappingRules(); } /*****************************************************************************/