#!/usr/bin/env python3
# Generated by "pythonizer -d5 -v3 -saM ../CGI.pm" v1.025 run by SNOOPYJC on Fri Feb 10 13:57:17 2023
__author__ = """Joe Cool"""
__email__ = "snoopyjc@gmail.com"
__version__ = "1.025"
import builtins, os, perllib, re, sys, types
_bn = lambda s: "" if s is None else s
_pb = lambda b: 1 if b else ""
_str = lambda s: "" if s is None else str(s)
_locals_stack = []
from perllib import Die
[docs]class EvalReturn(Exception):
pass
[docs]class LoopControl(Exception):
pass
[docs]class LoopControl_METHOD(Exception):
pass
[docs]class LoopControl_REDIRECT(Exception):
pass
[docs]class LoopControl_UPLOADS(Exception):
pass
from CGI.Util import (
ascii2ebcdic,
ebcdic2ascii,
escape,
expires,
make_attributes,
rearrange,
rearrange_header,
unescape,
)
perllib.init_package("CGI", is_class=True)
perllib.init_package("CGI.MultipartBuffer", is_class=True)
perllib.init_package("MultipartBuffer")
# Return true when we've finished reading
[docs]def eof(*_args):
[self] = perllib.list_of_n(_args, 1)
if (len(_str(self.get("BUFFER"))) == 0) and (perllib.num(self.get("LENGTH")) <= 0):
return 1
return None
CGI.MultipartBuffer.eof = lambda *_args, **_kwargs: perllib.tie_call(eof, _args, _kwargs)
# This fills up our internal buffer in such a way that the
# boundary is never split between reads
[docs]def fillBuffer(*_args):
[self, bytes_] = perllib.list_of_n(_args, 2)
if not (self.get("CHUNKED") or self.get("LENGTH")):
return
[boundaryLength] = perllib.list_of_n(len(_str(self.get("BOUNDARY"))), 1)
[bufferLength] = perllib.list_of_n(len(_str(self.get("BUFFER"))), 1)
[bytesToRead] = perllib.list_of_n(
perllib.num(bytes_) - perllib.num(bufferLength) + perllib.num(boundaryLength) + 2, 1
)
if not self.get("CHUNKED") and perllib.num(self.get("LENGTH")) < perllib.num(bytesToRead):
bytesToRead = self.get("LENGTH")
# Try to read some data. We may hang here if the browser is screwed up.
bytesRead = (
perllib.method_call(
self.get("INTERFACE"),
"read_from_client",
self.get("BUFFER"),
bytesToRead,
bufferLength,
),
perllib.set_element(self, "BUFFER", perllib.fetch_out_parameter(1)),
)[0]
if CGI.MultipartBuffer._DEBUG_v:
perllib.perl_print(
f"bytesToRead={_bn(bytesToRead)}, bufferLength={_bn(bufferLength)}, buffer={_bn(self).get('BUFFER','')}\n",
file=sys.stderr,
)
if not (self.get("BUFFER") is not None):
self["BUFFER"] = ""
# An apparent bug in the Apache server causes the read()
# to return zero bytes repeatedly without blocking if the
# remote user aborts during a file transfer. I don't know how
# they manage this, but the workaround is to abort if we get
# more than SPIN_LOOP_MAX consecutive zero reads.
if perllib.num(bytesRead) <= 0:
if (perllib.add_element(self, "ZERO_LOOP_COUNTER", 1) - 1) >= perllib.num(
CGI.MultipartBuffer.SPIN_LOOP_MAX_v
):
raise Die("CGI.pm: Server closed socket during multipart read (client aborted?).\n")
else:
self["ZERO_LOOP_COUNTER"] = 0
if not self.get("CHUNKED") and bytesRead:
self["LENGTH"] = perllib.num(self["LENGTH"]) - perllib.num(bytesRead)
return self.get("LENGTH")
CGI.MultipartBuffer.fillBuffer = lambda *_args, **_kwargs: perllib.tie_call(
fillBuffer, _args, _kwargs
)
# This will read $bytes or until the boundary is hit, whichever happens
# first. After the boundary is hit, we return undef. The next read will
# skip over the boundary and begin reading again;
[docs]def read(*_args):
[self, bytes_] = perllib.list_of_n(_args, 2)
# default number of bytes to read
bytes_ = bytes_ or CGI.MultipartBuffer.FILLUNIT_v
# Fill up our internal buffer in such a way that the boundary
# is never split between reads.
self.fillBuffer(bytes_)
boundary_start = (
CGI.Util.ebcdic2ascii(self.get("BOUNDARY")) if CGI.EBCDIC_v else self.get("BOUNDARY")
)
boundary_end = (
CGI.Util.ebcdic2ascii(_str(self.get("BOUNDARY")))
if CGI.EBCDIC_v
else _str(self.get("BOUNDARY")) + "--"
)
# Find the boundary in the buffer (it may not be there).
start = _str(self.get("BUFFER")).find(_str(boundary_start))
if CGI.MultipartBuffer._DEBUG_v:
perllib.perl_print(
f"boundary={_bn(self).get('BOUNDARY','')} length={_bn(self).get('LENGTH','')} start={start}\n",
file=sys.stderr,
)
# protect against malformed multipart POST operations
if not (self.get("CHUNKED") or (start >= 0 or perllib.num(self.get("LENGTH")) > 0)):
raise Die("Malformed multipart POST\n")
# EBCDIC NOTE: want to translate boundary search into ASCII here.
# If the boundary begins the data, then skip past it
# and return undef.
if start == 0:
# clear us out completely if we've hit the last boundary.
if _str(self.get("BUFFER")).find(_str(boundary_end)) == 0:
self["BUFFER"] = ""
self["LENGTH"] = 0
return None
# just remove the boundary.
self["BUFFER"] = (
_str(self["BUFFER"])[:0] + _str(self["BUFFER"])[0 + len(_str(boundary_start)) :]
)
perllib.substitute_element(self, "BUFFER", r"^\012\015?", r"", count=1)
return None
bytesToReturn = None
if start > 0: # read up to the boundary
bytesToReturn = bytes_ if start - 2 > perllib.num(bytes_) else start
else:
# read the requested number of bytes
# leave enough bytes in the buffer to allow us to read
# the boundary. Thanks to Kevin Hendrick for finding
# this one.
bytesToReturn = perllib.num(bytes_) - (len(_str(boundary_start)) + 1)
returnval = _str(self.get("BUFFER"))[0 : 0 + perllib.int_(bytesToReturn)]
self["BUFFER"] = (
_str(self["BUFFER"])[:0] + _str(self["BUFFER"])[0 + perllib.int_(bytesToReturn) :]
)
# If we hit the boundary, remove the CRLF from the end.
return returnval[0:-2] if (perllib.num(bytesToReturn) == start) else returnval
CGI.MultipartBuffer.read = lambda *_args, **_kwargs: perllib.tie_call(read, _args, _kwargs)
# This reads and returns the body as a single scalar value.
[docs]def readBody(*_args):
[self] = perllib.list_of_n(_args, 1)
data_v = None
[returnval] = perllib.list_of_n("", 1)
# EBCDIC NOTE: want to translate returnval into EBCDIC HERE
while (data_v := self.read()) is not None:
returnval = _str(returnval) + _str(data_v)
if CGI.EBCDIC_v:
if CGI.MultipartBuffer._DEBUG_v:
perllib.perl_print(f"untranslated body={_bn(returnval)}\n", file=sys.stderr)
returnval = CGI.Util.ascii2ebcdic(returnval)
if CGI.MultipartBuffer._DEBUG_v:
perllib.perl_print(f"translated body={_bn(returnval)}\n", file=sys.stderr)
return returnval
CGI.MultipartBuffer.readBody = lambda *_args, **_kwargs: perllib.tie_call(
readBody, _args, _kwargs
)
# internal routine, don't use
def _set_attributes(*_args):
_args = list(_args)
self = _args.pop(0) if _args else None
[element, attributes] = perllib.list_of_n(_args, 2)
if not (attributes.get(_str(element)) is not None):
return ""
CGI.attribs_v = " "
for attrib_l in sorted(list(attributes[_str(element)].keys())):
clean_attrib = re.sub(r"^-", r"", attrib_l, count=1)
CGI.attribs_v = (
_str(CGI.attribs_v)
+ f"""{perllib.LIST_SEPARATOR.join(map(_str,[clean_attrib.lower()]))}="{_bn(attributes)[_str(element)].get(attrib_l,'')}" """
)
CGI.attribs_v = re.sub(r" $", r"", _str(CGI.attribs_v), count=1)
return CGI.attribs_v
CGI._set_attributes = lambda *_args, **_kwargs: perllib.tie_call(_set_attributes, _args, _kwargs)
#########################################################
# Globals and stubs for other packages that we use.
#########################################################
######################## CGI::MultipartBuffer ####################
# internal routine, don't use
def _set_values_and_labels(*_args):
_args = list(_args)
perllib.init_out_parameters(_args, 2) # refs: 2
self = _args.pop(0) if _args else None
[v_v, l, n] = perllib.list_of_n(_args, 3)
if perllib.refs(v_v) == "HASH" and not perllib.ref(l):
perllib.store_out_parameter(None, 2, (l := v_v))
if v_v is None:
return self.param(n)
if not perllib.ref_scalar(v_v):
return v_v
return (
(sorted((v_v if v_v is not None else perllib.Hash()).keys()))
if perllib.refs(v_v) == "HASH"
else v_v
)
CGI._set_values_and_labels = lambda *_args, **_kwargs: perllib.tie_call(
_set_values_and_labels, _args, _kwargs
)
def _mp_value_parse(*_args):
[string, field] = perllib.list_of_n(_args, 2)
is_quoted = (
1 if (_m := re.search(rf"""[\s;]{_bn(field)}=\"""", _str(string)), _pb(_m))[1] else 0
)
param_v = ""
if is_quoted:
# a quoted token cannot contain anything but an unescaped quote
[param_v] = perllib.list_of_n(
(
_m := re.search(rf"""[\s;]{_bn(field)}="((?:\\"|[^"])*)\"""", _str(string)),
_m.groups() if _m else [],
)[1],
1,
)
else:
# a plain token cannot contain any reserved characters
# https://tools.ietf.org/html/rfc2616#section-2.2
# separators = "(" | ")" | "<" | ">" | "@"
# | "," | ";" | ":" | "\" | <">
# | "/" | "[" | "]" | "?" | "="
# | "{" | "}" | SP | HT
[param_v] = perllib.list_of_n(
(
_m := re.search(
rf"""[\s;]{_bn(field)}=([^\(\)<>@,;:\\"/\[\]\?=\{{\}} \015\n\t]*)""",
_str(string),
),
_m.groups() if _m else [],
)[1],
1,
)
return param_v
CGI._mp_value_parse = lambda *_args, **_kwargs: perllib.tie_call(_mp_value_parse, _args, _kwargs)
#####
# subroutine: read_multipart_related
#
# Read multipart/related data and store it into our parameters. The
# first parameter sets the start of the data. The part identified by
# this Content-ID will not be stored as a file upload, but will be
# returned by this method. All other parts will be available as file
# uploads accessible by their Content-ID
#####
[docs]def read_from_cmdline(*_args):
global _d
input_ = ""
words = perllib.Array()
query_string_v = ""
subpath = ""
if CGI.DEBUG_v and sys.argv[1:]:
words = sys.argv[1:].copy()
elif perllib.num(CGI.DEBUG_v) > 1:
import Text.ParseWords as _Text_ParseWords
perllib.perl_print(
"(offline mode: enter name=value pairs on standard input; press ^D or ^Z when done)",
file=sys.stderr,
)
CGI.lines_a = sys.stdin.readlines() # remove newlines
for _i in range(len(CGI.lines_a)):
CGI.lines_a[_i] = _str(CGI.lines_a[_i]).rstrip("\n") # remove newlines
input_ = " ".join(map(_str, CGI.lines_a))
words = perllib.Array(Text.ParseWords.old_shellwords(input_))
for _i3314, _d in enumerate(words):
_d = re.sub(re.compile(r"\\="), r"%3D", _str(_d), count=0)
words[_i3314] = _d
_d = re.sub(re.compile(r"\\&"), r"%26", _str(_d), count=0)
words[_i3314] = _d
if re.search(r"=", f"{perllib.LIST_SEPARATOR.join(map(_str,words))}"):
query_string_v = "&".join(map(_str, words))
else:
query_string_v = "+".join(map(_str, words))
if _m := re.search(r"^(.*?)\?(.*)$", query_string_v):
query_string_v = _m.group(2)
subpath = _m.group(1)
return perllib.Hash({"query_string": query_string_v, "subpath": subpath})
CGI.read_from_cmdline = lambda *_args, **_kwargs: perllib.tie_call(
read_from_cmdline, _args, _kwargs
)
#####
# subroutine: read_multipart
#
# Read multipart data and store it into our parameters.
# An interesting feature is that if any of the parts is a file, we
# create a temporary file and open up a filehandle on it so that the
# caller can read from it if necessary.
#####
[docs]def register_parameter(*_args):
[self, param_v] = perllib.list_of_n(_args, 2)
self[".parametersToAdd"][_s0] = (
perllib.num(self[".parametersToAdd"].get(_s0 := _str(param_v))) + 1
)
return perllib.num(self[".parametersToAdd"].get(_str(param_v))) - 1
CGI.register_parameter = lambda *_args, **_kwargs: perllib.tie_call(
register_parameter, _args, _kwargs
)
[docs]def previous_or_default(*_args):
global _d
[self, name, defaults_v, override] = perllib.list_of_n(_args, 4)
selected = perllib.Hash()
if not override and (self[".fieldnames"].get(_str(name)) or self.param(name) is not None):
for _d in perllib.flatten([self.param(name, wantarray=True)]):
selected[_s0] = perllib.num(selected.get(_s0 := _str(_d))) + 1
elif (
defaults_v is not None
and perllib.ref_scalar(defaults_v)
and (perllib.refs(defaults_v) == "ARRAY")
):
for _d in defaults_v:
selected[_s0] = perllib.num(selected.get(_s0 := _str(_d))) + 1
else:
if defaults_v is not None:
selected[_s0] = perllib.num(selected.get(_s0 := _str(defaults_v))) + 1
return selected
CGI.previous_or_default = lambda *_args, **_kwargs: perllib.tie_call(
previous_or_default, _args, _kwargs
)
#### Method: private_tempfiles
# Set or return the private_tempfiles global flag
####
[docs]def private_tempfiles(*_args):
perllib.perl_print("private_tempfiles has been deprecated", file=sys.stderr)
return 0
CGI.private_tempfiles = lambda *_args, **_kwargs: perllib.tie_call(
private_tempfiles, _args, _kwargs
)
#### Method: close_upload_files
# Set or return the close_upload_files global flag
####
#### Method: remote_user
# Return the authorization name used for user
# verification.
####
[docs]def remote_user(*_args):
return os.environ.get("REMOTE_USER") if (os.environ.get("REMOTE_USER") is not None) else None
CGI.remote_user = lambda *_args, **_kwargs: perllib.tie_call(remote_user, _args, _kwargs)
#### Method: user_name
# Try to return the remote user's name by hook or by
# crook
####
#### Method: auth_type
# Return the type of use verification/authorization in use, if any.
####
[docs]def auth_type(*_args):
return os.environ.get("AUTH_TYPE") if (os.environ.get("AUTH_TYPE") is not None) else None
CGI.auth_type = lambda *_args, **_kwargs: perllib.tie_call(auth_type, _args, _kwargs)
#### Method: remote_ident
# Return the identity of the remote user
# (but only if his host is running identd)
####
[docs]def remote_ident(*_args):
return (
os.environ.get("REMOTE_IDENT") if (os.environ.get("REMOTE_IDENT") is not None) else None
)
CGI.remote_ident = lambda *_args, **_kwargs: perllib.tie_call(remote_ident, _args, _kwargs)
#### Method: server_protocol
# Return the protocol (usually HTTP/1.0)
####
[docs]def server_protocol(*_args):
return os.environ.get("SERVER_PROTOCOL") or "HTTP/1.0" # for debugging
CGI.server_protocol = lambda *_args, **_kwargs: perllib.tie_call(server_protocol, _args, _kwargs)
#### Method: http
# Return the value of an HTTP variable, or
# the list of variables if none provided
####
#### Method: server_port
# Return the tcp/ip port the server is running on
####
[docs]def server_port(*_args):
return os.environ.get("SERVER_PORT") or 80 # for debugging
CGI.server_port = lambda *_args, **_kwargs: perllib.tie_call(server_port, _args, _kwargs)
#### Method: server_software
# Return the name of the server software
####
[docs]def server_software(*_args):
return os.environ.get("SERVER_SOFTWARE") or "cmdline"
CGI.server_software = lambda *_args, **_kwargs: perllib.tie_call(server_software, _args, _kwargs)
#### Method: virtual_port
# Return the server port, taking virtual hosts into account
####
#### Method: server_name
# Return the name of the server
####
[docs]def server_name(*_args):
return os.environ.get("SERVER_NAME") or "localhost"
CGI.server_name = lambda *_args, **_kwargs: perllib.tie_call(server_name, _args, _kwargs)
#### Method: remote_addr
# Return the IP addr of the remote host.
####
[docs]def remote_addr(*_args):
return os.environ.get("REMOTE_ADDR") or "127.0.0.1"
CGI.remote_addr = lambda *_args, **_kwargs: perllib.tie_call(remote_addr, _args, _kwargs)
#### Method: script_name
# Return the partial URL to this script for
# self-referencing scripts. Also see
# self_url(), which returns a URL with all state information
# preserved.
####
#### Method: remote_host
# Return the name of the remote host, or its IP
# address if unavailable. If this variable isn't
# defined, it returns "localhost" for debugging
# purposes.
####
[docs]def remote_host(*_args):
return os.environ.get("REMOTE_HOST") or os.environ.get("REMOTE_ADDR") or "localhost"
CGI.remote_host = lambda *_args, **_kwargs: perllib.tie_call(remote_host, _args, _kwargs)
[docs]def env_query_string(*_args):
return (
os.environ.get("QUERY_STRING") if (os.environ.get("QUERY_STRING") is not None) else None
)
CGI.env_query_string = lambda *_args, **_kwargs: perllib.tie_call(
env_query_string, _args, _kwargs
)
#### Method: accept
# Without parameters, returns an array of the
# MIME types the browser accepts.
# With a single parameter equal to a MIME
# type, will return undef if the browser won't
# accept it, 1 if the browser accepts it but
# doesn't give a preference, or a floating point
# value between 0.0 and 1.0 if the browser
# declares a quantitative score for it.
# This handles MIME type globs correctly.
####
#### Method: request_uri
# Return the literal request URI
####
[docs]def request_uri(*_args):
return os.environ.get("REQUEST_URI") if (os.environ.get("REQUEST_URI") is not None) else None
CGI.request_uri = lambda *_args, **_kwargs: perllib.tie_call(request_uri, _args, _kwargs)
#### Method: query_string
# Synthesize a query string from our current
# parameters
####
#### Method: path_translated
# Return the physical path information provided
# by the URL (if any)
####
[docs]def path_translated(*_args):
return (
os.environ.get("PATH_TRANSLATED")
if (os.environ.get("PATH_TRANSLATED") is not None)
else None
)
CGI.path_translated = lambda *_args, **_kwargs: perllib.tie_call(path_translated, _args, _kwargs)
#### Method: content_type
# Returns the content_type string
####
[docs]def content_type(*_args):
return (
os.environ.get("CONTENT_TYPE") if (os.environ.get("CONTENT_TYPE") is not None) else None
)
CGI.content_type = lambda *_args, **_kwargs: perllib.tie_call(content_type, _args, _kwargs)
#### Method: request_method
# Returns 'POST', 'GET', 'PUT', 'PATCH' or 'HEAD'
####
[docs]def request_method(*_args):
return (
os.environ.get("REQUEST_METHOD")
if (os.environ.get("REQUEST_METHOD") is not None)
else None
)
CGI.request_method = lambda *_args, **_kwargs: perllib.tie_call(request_method, _args, _kwargs)
# This function returns a potentially modified version of SCRIPT_NAME
# and PATH_INFO. Some HTTP servers do sanitise the paths in those
# variables. It is the case of at least Apache 2. If for instance the
# user requests: /path/./to/script.cgi/x//y/z/../x?y, Apache will set:
# REQUEST_URI=/path/./to/script.cgi/x//y/z/../x?y
# SCRIPT_NAME=/path/to/env.cgi
# PATH_INFO=/x/y/x
#
# This is all fine except that some bogus CGI scripts expect
# PATH_INFO=/http://foo when the user requests
# http://xxx/script.cgi/http://foo
#
# Old versions of this module used to accomodate with those scripts, so
# this is why we do this here to keep those scripts backward compatible.
# Basically, we accomodate with those scripts but within limits, that is
# we only try to preserve the number of / that were provided by the user
# if $REQUEST_URI and "$SCRIPT_NAME$PATH_INFO" only differ by the number
# of consecutive /.
#
# So for instance, in: http://foo/x//y/script.cgi/a//b, we'll return a
# script_name of /x//y/script.cgi and a path_info of /a//b, but in:
# http://foo/./x//z/script.cgi/a/../b//c, we'll return the versions
# possibly sanitised by the HTTP server, so in the case of Apache 2:
# script_name == /foo/x/z/script.cgi and path_info == /b/c.
#
# Future versions of this module may no longer do that, so one should
# avoid relying on the browser, proxy, server, and CGI.pm preserving the
# number of consecutive slashes as no guarantee can be made there.
def _name_and_path_from_env(*_args):
_args = list(_args)
path_info_pattern = ""
script_name_pattern = ""
self = _args.pop(0) if _args else None
script_name_v = os.environ.get("SCRIPT_NAME") or ""
path_info_v = os.environ.get("PATH_INFO") or ""
uri = self.request_uri() or ""
uri = re.sub(re.compile(r"\?.*", re.S), r"", _str(uri), count=1)
uri = unescape(uri)
if CGI.IIS_v:
# IIS doesn't set $ENV{PATH_INFO} correctly. It sets it to
# $ENV{SCRIPT_NAME}path_info
# IIS also doesn't set $ENV{REQUEST_URI} so we don't want to do
# the test below, hence this comes first
def _f2886(_m_):
global _m
_m = _m_
return _m.expand(r"\g<1>")
path_info_v = re.sub(
re.compile(rf"^{perllib.quotemeta(_bn(script_name_v))}(.*)"),
_f2886,
_str(path_info_v),
count=1,
)
elif _str(uri) != f"{_bn(script_name_v)}{_bn(path_info_v)}":
script_name_pattern = perllib.quotemeta(_str(script_name_v))
path_info_pattern = perllib.quotemeta(_str(path_info_v))
script_name_pattern = re.sub(re.compile(r"(?:\\/)+"), r"/+", script_name_pattern, count=0)
path_info_pattern = re.sub(re.compile(r"(?:\\/)+"), r"/+", path_info_pattern, count=0)
if _m := re.search(
re.compile(rf"^({script_name_pattern})({path_info_pattern})$", re.S), _str(uri)
):
# REQUEST_URI and SCRIPT_NAME . PATH_INFO only differ by the
# numer of consecutive slashes, so we can extract the info from
# REQUEST_URI:
[script_name_v, path_info_v] = (_m.group(1), _m.group(2))
return perllib.Array([script_name_v, path_info_v])
CGI._name_and_path_from_env = lambda *_args, **_kwargs: perllib.tie_call(
_name_and_path_from_env, _args, _kwargs
)
[docs]def parse_keywordlist(*_args):
[self, tosplit] = perllib.list_of_n(_args, 2)
tosplit = unescape(tosplit) # unescape the keywords
tosplit = _str(tosplit).translate(str.maketrans("+", " ")) # pluses to spaces
keywords_a = perllib.Array(perllib.split(r"\s+", _str(tosplit)))
return keywords_a
CGI.parse_keywordlist = lambda *_args, **_kwargs: perllib.tie_call(
parse_keywordlist, _args, _kwargs
)
# Internal procedure - don't use
def _tableize(*_args):
global _d
[rows, columns, rowheaders, colheaders, *elements] = perllib.list_of_at_least_n(_args, 4)
elements = perllib.Array(elements)
rowheaders_a = perllib.Array(rowheaders if rowheaders else perllib.Array())
colheaders_a = perllib.Array(colheaders if colheaders else perllib.Array())
result_v = ""
if columns is not None:
if rows is None:
rows = perllib.int_(0.99 + len(elements) / perllib.num(columns))
if rows is not None:
if columns is None:
columns = perllib.int_(0.99 + len(elements) / perllib.num(rows))
# rearrange into a pretty table
result_v = "<table>"
row = 0
column = 0
if colheaders_a and rowheaders_a:
colheaders_a[0:0] = [""]
if colheaders_a:
result_v += "<tr>"
for _d in colheaders_a:
result_v += f"<th>{_bn(_d)}</th>"
for row in range(0, perllib.num(rows)):
result_v += "<tr>"
if rowheaders_a:
result_v += f"<th>{rowheaders_a[row]}</th>"
for column in range(0, perllib.num(columns)):
if (
elements.get(
column * perllib.int_(rows) + row
if column * perllib.int_(rows) + row >= 0
else len(elements) + column * perllib.int_(rows) + row
)
is not None
):
result_v += "<td>" + _str(elements[column * perllib.int_(rows) + row]) + "</td>"
result_v += "</tr>"
result_v += "</table>"
return result_v
CGI._tableize = lambda *_args, **_kwargs: perllib.tie_call(_tableize, _args, _kwargs)
#### Method: radio_group
# Create a list of logically-linked radio buttons.
# Parameters:
# $name -> Common name for all the buttons.
# $values -> A pointer to a regular array containing the
# values for each button in the group.
# $default -> (optional) Value of the button to turn on by default. Pass '-'
# to turn _nothing_ on.
# $linebreak -> (optional) Set to true to place linebreaks
# between the buttons.
# $labels -> (optional)
# A pointer to a hash of labels to print next to each checkbox
# in the form $label{'value'}="Long explanatory label".
# Otherwise the provided values are used as the labels.
# Returns:
# An ARRAY containing a series of <input type="radio"> fields
####
#### Method: end_html
# End an HTML document.
# Trivial method for completeness. Just returns "</body>"
####
[docs]def end_html(*_args):
return "\n</body>\n</html>"
CGI.end_html = lambda *_args, **_kwargs: perllib.tie_call(end_html, _args, _kwargs)
################################
# METHODS USED IN BUILDING FORMS
################################
#### Method: isindex
# Just prints out the isindex tag.
# Parameters:
# $action -> optional URL of script to run
# Returns:
# A string containing a <isindex> tag
def _script(*_args):
[self, script] = perllib.list_of_n(_args, 2)
result = perllib.Array()
scripts = perllib.Array(script if perllib.refs(script) == "ARRAY" else (script))
for script_l in scripts:
src = code = language = charset_v = None
if perllib.ref_scalar(script_l): # script is a hash
[src, code, CGI.type_v, charset_v] = perllib.list_of_n(
rearrange(
perllib.Array(["SRC", "CODE", ["LANGUAGE", "TYPE"], "CHARSET"]),
"-foo",
"bar",
script_l if perllib.refs(script_l) == "ARRAY" else script_l,
),
4,
)
# a trick to allow the '-' to be omitted
CGI.type_v = CGI.type_v or "text/javascript"
if not ((re.search(r"\w+/\w+", _str(CGI.type_v)))):
CGI.type_v = re.sub(r"[\d.]+$", r"", _str(CGI.type_v), count=1)
CGI.type_v = f"text/{_bn(CGI.type_v)}"
else:
[src, code, CGI.type_v, charset_v] = ("", script_l, "text/javascript", "")
comment_v = "//" # javascript by default
if re.search(re.compile(r"perl|tcl", re.I), _str(CGI.type_v)):
comment_v = "#"
if re.search(re.compile(r"vbscript", re.I), _str(CGI.type_v)):
comment_v = "'"
cdata_start = ""
cdata_end = ""
if CGI.XHTML_v:
cdata_start = f"{comment_v}<![CDATA[\n"
cdata_end += f"\n{comment_v}]]>"
else:
cdata_start = "\n<!-- Hide script\n"
cdata_end = comment_v
cdata_end += " End script hiding -->\n"
satts = perllib.Array()
if src:
satts.extend(perllib.make_list("src", src))
satts.extend(perllib.make_list("type", CGI.type_v))
if src and charset_v:
satts.extend(perllib.make_list("charset", charset_v))
if code is not None:
code = cdata_start + _str(code) + cdata_end
result.extend(
perllib.make_list(
self.script(
perllib.Hash(
perllib.Hash({satts[_i]: satts[_i + 1] for _i in range(0, len(satts), 2)})
),
code or "",
)
)
)
return result
CGI._script = lambda *_args, **_kwargs: perllib.tie_call(_script, _args, _kwargs)
#### Method: restore_parameters
# A way to restore CGI parameters from an initializer.
# Only intended to be used with the function (non-OO) interface.
####
[docs]def restore_parameters(*_args):
CGI.Q_v = perllib.method_call(CGI.DefaultClass_v, "new", *_args)
return CGI.Q_v
CGI.restore_parameters = lambda *_args, **_kwargs: perllib.tie_call(
restore_parameters, _args, _kwargs
)
#### Method: multipart_init
# Return a Content-Type: style header for server-push
# This has to be NPH on most web servers, and it is advisable to set $| = 1
#
# Many thanks to Ed Jordan <ed@fidalgo.net> for this
# contribution, updated by Andrew Benham (adsb@bigfoot.com)
####
#### Method: version
# Return the current version
####
[docs]def version(*_args):
return CGI.VERSION_v
CGI.version = lambda *_args, **_kwargs: perllib.tie_call(version, _args, _kwargs)
#### Method: url_param
# Return a parameter in the QUERY_STRING, regardless of
# whether this was a POST or a GET
####
[docs]def CLEAR(*_args):
_args[0] = perllib.Hash()
return _args[0]
CGI.CLEAR = lambda *_args, **_kwargs: perllib.tie_call(CLEAR, _args, _kwargs)
####
####
# Append a new value to an existing query
####
[docs]def DELETE(*_args):
[self, param_v] = perllib.list_of_n(_args, 2)
value_v = self.FETCH(param_v)
self.delete(param_v)
return value_v
CGI.DELETE = lambda *_args, **_kwargs: perllib.tie_call(DELETE, _args, _kwargs)
[docs]def EXISTS(*_args):
return _str(_args[1]) in _args[0]["param"]
CGI.EXISTS = lambda *_args, **_kwargs: perllib.tie_call(EXISTS, _args, _kwargs)
[docs]def NEXTKEY(*_args):
return _args[0][".parameters"][
(perllib.int_(perllib.add_element(_args[0], ".iterator", 1)) - 1)
]
CGI.NEXTKEY = lambda *_args, **_kwargs: perllib.tie_call(NEXTKEY, _args, _kwargs)
[docs]def FIRSTKEY(*_args):
_args[0][".iterator"] = 0
return _args[0][".parameters"][
(perllib.int_(perllib.add_element(_args[0], ".iterator", 1)) - 1)
]
CGI.FIRSTKEY = lambda *_args, **_kwargs: perllib.tie_call(FIRSTKEY, _args, _kwargs)
[docs]def STORE(*_args):
_args = list(_args)
self = _args.pop(0) if _args else None
tag = _args.pop(0) if _args else None
vals = _args.pop(0) if _args else None
vals_a = perllib.Array(
_str(vals).split("\0") if vals is not None and _str(vals).find("\0") != -1 else vals
)
return self.param("-name", tag, "-value", vals_a)
CGI.STORE = lambda *_args, **_kwargs: perllib.tie_call(STORE, _args, _kwargs)
[docs]def MethPut(*_args):
return _pb(_str(request_method()) == "PUT")
CGI.MethPut = lambda *_args, **_kwargs: perllib.tie_call(MethPut, _args, _kwargs)
[docs]def MethPost(*_args):
return _pb(_str(request_method()) == "POST")
CGI.MethPost = lambda *_args, **_kwargs: perllib.tie_call(MethPost, _args, _kwargs)
[docs]def MethPatch(*_args):
return _pb(_str(request_method()) == "PATCH")
CGI.MethPatch = lambda *_args, **_kwargs: perllib.tie_call(MethPatch, _args, _kwargs)
[docs]def MethGet(*_args):
return _pb(_str(request_method()) == "GET")
CGI.MethGet = lambda *_args, **_kwargs: perllib.tie_call(MethGet, _args, _kwargs)
[docs]def SplitParam(*_args, wantarray=False):
[param_v] = perllib.list_of_n(_args, 1)
params = perllib.Array(_str(param_v).split("\0"))
return params if wantarray else params[0]
CGI.SplitParam = lambda *_args, **_kwargs: perllib.tie_call(SplitParam, _args, _kwargs)
[docs]def SERVER_PUSH(*_args):
_args = list(_args)
return 'multipart/x-mixed-replace;boundary="' + _str(_args.pop(0) if _args else None) + '"'
CGI.SERVER_PUSH = lambda *_args, **_kwargs: perllib.tie_call(SERVER_PUSH, _args, _kwargs)
# Create a new multipart buffer
[docs]def MULTIPART(*_args):
return "multipart/form-data"
CGI.MULTIPART = lambda *_args, **_kwargs: perllib.tie_call(MULTIPART, _args, _kwargs)
[docs]def URL_ENCODED(*_args):
return "application/x-www-form-urlencoded"
CGI.URL_ENCODED = lambda *_args, **_kwargs: perllib.tie_call(URL_ENCODED, _args, _kwargs)
def _checked(*_args):
_args = list(_args)
self = _args.pop(0) if _args else None
value_v = _args.pop(0) if _args else None
if not value_v:
return ""
return 'checked="checked" ' if CGI.XHTML_v else "checked "
CGI._checked = lambda *_args, **_kwargs: perllib.tie_call(_checked, _args, _kwargs)
def _selected(*_args):
_args = list(_args)
self = _args.pop(0) if _args else None
value_v = _args.pop(0) if _args else None
if not value_v:
return ""
return 'selected="selected" ' if CGI.XHTML_v else "selected "
CGI._selected = lambda *_args, **_kwargs: perllib.tie_call(_selected, _args, _kwargs)
def _all_html_tags(*_args):
return "a abbr acronym address applet Area b base basefont bdo big blink blockquote body br caption center cite code col colgroup dd del dfn div dl dt em embed fieldset font fontsize frame frameset h1 h2 h3 h4 h5 h6 head hr html i iframe ilayer img input ins kbd label layer legend li Link Map menu meta nextid nobr noframes noscript object ol option p Param pre Q samp script Select small span strike strong style Sub sup table tbody td tfoot th thead title Tr TR tt u ul var".split()
CGI._all_html_tags = lambda *_args, **_kwargs: perllib.tie_call(_all_html_tags, _args, _kwargs)
# back compatibility html tag generation functions - noop
# since this is now the default having removed AUTOLOAD
[docs]def compile_(*_args):
return 1
CGI.compile_ = lambda *_args, **_kwargs: perllib.tie_call(compile_, _args, _kwargs)
# put a filehandle into binary mode (DOS)
[docs]def binmode(*_args):
_args = list(_args)
perllib.init_out_parameters(_args, 1)
if not (
(1 < len(_args) and _args[1] is not None)
and perllib.ref_scalar(_args[1])
and perllib.fileno(_args[1]) is not None
):
return
return perllib.store_out_parameter(
_args, 1, perllib.binmode(_args[1], mode="b", encoding=None, errors=None)
)
CGI.binmode = lambda *_args, **_kwargs: perllib.tie_call(binmode, _args, _kwargs)
[docs]def all_parameters(*_args, wantarray=False):
_args = list(_args)
self = _args.pop(0) if _args else None
if not (self is not None and self.get(".parameters")):
return perllib.Array() if wantarray else None
if not self.get(".parameters"):
return perllib.Array() if wantarray else None
return self.get(".parameters")
CGI.all_parameters = lambda *_args, **_kwargs: perllib.tie_call(all_parameters, _args, _kwargs)
[docs]def save_request(*_args):
global _d
[self] = perllib.list_of_n(_args, 1)
# We're going to play with the package globals now so that if we get called
# again, we initialize ourselves in exactly the same way. This allows
# us to have several of these objects.
CGI.QUERY_PARAM_a = perllib.Array(self.param(wantarray=True)) # save list of parameters
for _d in CGI.QUERY_PARAM_a:
if _d is None:
continue
CGI.QUERY_PARAM_h[_str(_d)] = self["param"].get(_str(_d))
CGI.QUERY_CHARSET_v = self.charset()
CGI.QUERY_FIELDNAMES_h = perllib.Hash(self.get(".fieldnames"))
CGI.QUERY_TMPFILES_h = perllib.Hash(self.get(".tmpfiles") or perllib.Hash())
return CGI.QUERY_TMPFILES_h
CGI.save_request = lambda *_args, **_kwargs: perllib.tie_call(save_request, _args, _kwargs)
# print to standard output (for overriding in mod_perl)
[docs]def print_(*_args):
_args = list(_args)
(_args.pop(0) if _args else None)
return perllib.perl_print(*_args, end="")
CGI.print_ = lambda *_args, **_kwargs: perllib.tie_call(print_, _args, _kwargs)
# get/set last cgi_error
# FUNCTIONS TO OVERRIDE:
# Turn a string into a filehandle
[docs]def to_filehandle(*_args):
_args = list(_args)
caller = 0
package = None
tmp = None
thingy = _args.pop(0) if _args else None
if not thingy:
return None
if perllib.isa(thingy, "GLOB"):
return thingy
if perllib.isa(thingy, "FileHandle"):
return thingy
if not perllib.ref_scalar(thingy):
caller = 1
while package := perllib.caller_s((caller := caller + 1) - 1):
[tmp] = perllib.list_of_n(
thingy
if (re.search(r"[\':]", _str(thingy)))
else f"{_bn(package)}::{_bn(thingy)}",
1,
)
if perllib.fileno(tmp) is not None:
return tmp
return None
CGI.to_filehandle = lambda *_args, **_kwargs: perllib.tie_call(to_filehandle, _args, _kwargs)
# send output to the browser
def _get_query_string_from_env(*_args):
_args = list(_args)
key = ""
prev = None
self = _args.pop(0) if _args else None
query_string_v = ""
if CGI.MOD_PERL_v:
query_string_v = perllib.method_call(self.r(), "args")
if not query_string_v and perllib.num(CGI.MOD_PERL_v) == 2:
# possibly a redirect, inspect prev request
# (->prev only supported under mod_perl2)
if prev := perllib.method_call(self.r(), "prev"):
query_string_v = prev.args()
if os.environ.get("QUERY_STRING") is not None:
query_string_v = query_string_v or os.environ.get("QUERY_STRING")
if not query_string_v:
# try to get from REDIRECT_ env variables, support
# 5 levels of redirect and no more (RT #36312)
# REDIRECT
for r_l in range(1, 5 + 1):
key = "".join(map(_str, ("REDIRECT_" * r_l)))
if os.environ.get(f"{key}QUERY_STRING") is not None:
query_string_v = query_string_v or os.environ.get(f"{key}QUERY_STRING")
if query_string_v:
break
return query_string_v
CGI._get_query_string_from_env = lambda *_args, **_kwargs: perllib.tie_call(
_get_query_string_from_env, _args, _kwargs
)
[docs]def self_or_default(*_args, wantarray=False):
_args = list(_args)
if (
(0 < len(_args) and _args[0] is not None)
and (not perllib.ref_scalar(_args[0]))
and (_str(_args[0]) == "CGI")
):
return _args
if not (
(0 < len(_args) and _args[0] is not None)
and (perllib.ref_scalar(_args[0]) == "CGI" or perllib.isa(_args[0], "CGI"))
): # slightly optimized for common case
if CGI.Q_v is None:
CGI.Q_v = perllib.method_call(CGI.DefaultClass_v, "new")
_args[0:0] = [CGI.Q_v]
return _args if wantarray else CGI.Q_v
CGI.self_or_default = lambda *_args, **_kwargs: perllib.tie_call(self_or_default, _args, _kwargs)
[docs]def uploadInfo(*_args):
[self, filename] = perllib.list_of_n(self_or_default(*_args, wantarray=True), 2)
if filename is None:
return
return self[".tmpfiles"][_str(filename) + _str(filename)].get("info")
CGI.uploadInfo = lambda *_args, **_kwargs: perllib.tie_call(uploadInfo, _args, _kwargs)
[docs]def tmpFileName(*_args):
[self, filename] = perllib.list_of_n(self_or_default(*_args, wantarray=True), 2)
# preferred calling convention: $filename came directly from param or upload
if perllib.ref_scalar(filename):
return self[".tmpfiles"][_str(filename) + _str(filename)].get("name") or ""
# backwards compatible with older versions: $filename is merely equal to
# one of our filenames when compared as strings
for param_name_l in perllib.flatten([self.param(wantarray=True)]):
for filehandle_l in perllib.flatten([self.multi_param(param_name_l)]):
if _str(filehandle_l) == _str(filename):
return (
self[".tmpfiles"][_str(filehandle_l) + _str(filehandle_l)].get("name") or ""
)
return ""
CGI.tmpFileName = lambda *_args, **_kwargs: perllib.tie_call(tmpFileName, _args, _kwargs)
[docs]def upload(*_args, wantarray=False):
global _d
[self, param_name] = perllib.list_of_n(self_or_default(*_args, wantarray=True), 2)
param_a = perllib.Array(
list(
filter(
lambda _d: perllib.ref_scalar(_d) and perllib.fileno(_d) is not None,
perllib.make_list(self.param(param_name, wantarray=True)),
)
)
)
if not param_a:
return perllib.Array() if wantarray else None
return param_a if wantarray else param_a[0]
CGI.upload = lambda *_args, **_kwargs: perllib.tie_call(upload, _args, _kwargs)
[docs]def virtual_port(*_args):
[self] = perllib.list_of_n(self_or_default(*_args, wantarray=True), 1)
vh = self.http("x_forwarded_host") or self.http("host")
protocol_v = self.protocol()
if vh:
return ((_m := re.search(r":(\d+)$", _str(vh)), _m.groups() if _m else [])[1])[0] or (
443 if _str(protocol_v) == "https" else 80
)
else:
return self.server_port()
CGI.virtual_port = lambda *_args, **_kwargs: perllib.tie_call(virtual_port, _args, _kwargs)
[docs]def script_name(*_args):
path_info_v = None
script_name_v = None
[self, *p] = perllib.list_of_at_least_n(self_or_default(*_args, wantarray=True), 1)
p = perllib.Array(p)
if p:
self[".script_name"] = p.pop(0) if p else None
elif not ".script_name" in self:
[script_name_v, path_info_v] = perllib.list_of_n(self._name_and_path_from_env(), 2)
self[".script_name"] = script_name_v
return self.get(".script_name")
CGI.script_name = lambda *_args, **_kwargs: perllib.tie_call(script_name, _args, _kwargs)
#### Method: referer
# Return the HTTP_REFERER: useful for generating
# a GO BACK button.
####
###############################################
# OTHER INFORMATION PROVIDED BY THE ENVIRONMENT
###############################################
#### Method: path_info
# Return the extra virtual path information provided
# after the URL (if any)
####
[docs]def path_info(*_args):
path_info_v = None
[self, info] = perllib.list_of_n(self_or_default(*_args, wantarray=True), 2)
if info is not None:
if _str(info) != "" and _str(info)[0:1] != "/":
info = f"/{_bn(info)}"
self[".path_info"] = info
elif self.get(".path_info") is None:
[_, path_info_v] = perllib.list_of_n(self._name_and_path_from_env(), 2)
self[".path_info"] = path_info_v or ""
return self.get(".path_info")
CGI.path_info = lambda *_args, **_kwargs: perllib.tie_call(path_info, _args, _kwargs)
[docs]def param_fetch(*_args):
[self, *p] = perllib.list_of_at_least_n(self_or_default(*_args, wantarray=True), 1)
p = perllib.Array(p)
[name] = perllib.list_of_n(rearrange(perllib.Array(["NAME"]), *p), 1)
if name is None:
return perllib.Array()
if not (_str(name) in self["param"]):
self.add_parameter(name)
self["param"][_str(name)] = perllib.Array()
return self["param"].get(_str(name))
CGI.param_fetch = lambda *_args, **_kwargs: perllib.tie_call(param_fetch, _args, _kwargs)
#### Method: self_url
# Returns a URL containing the current script and all its
# param/value pairs arranged as a query. You can use this
# to create a link that, when selected, will reinvoke the
# script with all its state information preserved.
####
[docs]def self_url(*_args):
[self, *p] = perllib.list_of_at_least_n(self_or_default(*_args, wantarray=True), 1)
p = perllib.Array(p)
return self.url("-path_info", 1, "-query", 1, "-full", 1, *p)
CGI.self_url = lambda *_args, **_kwargs: perllib.tie_call(self_url, _args, _kwargs)
# This is provided as a synonym to self_url() for people unfortunate
# enough to have incorporated it into their programs already!
[docs]def state(*_args):
return self_url(*_args)
CGI.state = lambda *_args, **_kwargs: perllib.tie_call(state, _args, _kwargs)
#### Method: url
# Like self_url, but doesn't return the query string part of
# the URL.
####
#### Method: image_button
# Parameters:
# $name -> Name of the button
# $src -> URL of the image source
# $align -> Alignment style (TOP, BOTTOM or MIDDLE)
# Returns:
# A string containing a <input type="image" name="name" src="url" align="alignment">
####
CGI.image_button = lambda *_args, **_kwargs: perllib.tie_call(image_button, _args, _kwargs)
#### Method: scrolling_list
# Create a scrolling list.
# Parameters:
# $name -> name for the list
# $values -> A pointer to a regular array containing the
# values for each option line in the list.
# $defaults -> (optional)
# 1. If a pointer to a regular array of options,
# then this will be used to decide which
# lines to turn on by default.
# 2. Otherwise holds the value of the single line to turn on.
# $size -> (optional) Size of the list.
# $multiple -> (optional) If set, allow multiple selections.
# $labels -> (optional)
# A pointer to a hash of labels to print next to each checkbox
# in the form $label{'value'}="Long explanatory label".
# Otherwise the provided values are used as the labels.
# Returns:
# A string containing the definition of a scrolling list.
####
CGI.scrolling_list = lambda *_args, **_kwargs: perllib.tie_call(scrolling_list, _args, _kwargs)
#### Method: hidden
# Parameters:
# $name -> Name of the hidden field
# @default -> (optional) Initial values of field (may be an array)
# or
# $default->[initial values of field]
# Returns:
# A string containing a <input type="hidden" name="name" value="value">
####
#### Method: optgroup
# Create a optgroup.
# Parameters:
# $name -> Label for the group
# $values -> A pointer to a regular array containing the
# values for each option line in the group.
# $labels -> (optional)
# A pointer to a hash of labels to print next to each item
# in the form $label{'value'}="Long explanatory label".
# Otherwise the provided values are used as the labels.
# $labeled -> (optional)
# A true value indicates the value should be used as the label attribute
# in the option elements.
# The label attribute specifies the option label presented to the user.
# This defaults to the content of the <option> element, but the label
# attribute allows authors to more easily use optgroup without sacrificing
# compatibility with browsers that do not support option groups.
# $novals -> (optional)
# A true value indicates to suppress the val attribute in the option elements
# Returns:
# A string containing the definition of an option group.
####
[docs]def optgroup(*_args):
global _d
attribs_v = None
label = None
selectit = ""
value_v = None
[self, *p] = perllib.list_of_at_least_n(self_or_default(*_args, wantarray=True), 1)
p = perllib.Array(p)
[name, values_v, attributes, labeled, noval, labels, *other] = perllib.list_of_at_least_n(
rearrange(
perllib.Array(
["NAME", ["VALUES", "VALUE"], "ATTRIBUTES", "LABELED", "NOVALS", "LABELS"]
),
*p,
),
6,
)
other = perllib.Array(other)
result_v = ""
values_ = perllib.Array()
values_ = perllib.Array(
(
self._set_values_and_labels(values_v, labels, name, labeled, CGI.novals_v),
(labels := perllib.fetch_out_parameter(2)),
)[0]
)
[other_v] = perllib.list_of_n(
f" {perllib.LIST_SEPARATOR.join(map(_str,other))}" if other else "", 1
)
name = self._maybe_escapeHTML(name) or ""
result_v = f"""<optgroup label="{_bn(name)}"{_bn(other_v)}>\n"""
for _d in values_:
if re.search(r"<optgroup", _str(_d)):
for _i2516, _d in enumerate(_s2516 := perllib.split(r"\n", _d)):
selectit = 'selected="selected"' if CGI.XHTML_v else "selected"
if CGI.selected_v is not None:
def _f2518(_m_):
global _m
_m = _m_
return _m.expand(rf"{_bn(selectit)} \g<1>")
_s2516[_i2516] = _d
_d = re.sub(
re.compile(rf'(value="{_bn(CGI.selected_v)}")'), _f2518, _d, count=1
)
_s2516[_i2516] = _d
result_v += f"{_bn(_d)}\n"
else:
attribs_v = self._set_attributes(_d, attributes)
[label] = perllib.list_of_n(_d, 1)
if labels is not None and labels.get(_str(_d)) is not None:
label = labels.get(_str(_d))
label = self._maybe_escapeHTML(label)
[value_v] = perllib.list_of_n(self._maybe_escapeHTML(_d, 1), 1)
result_v += (
(
f"""<option{_bn(attribs_v)} label="{_bn(value_v)}">{_bn(label)}</option>\n"""
if CGI.novals_v
else f"""<option{_bn(attribs_v)} label="{_bn(value_v)}" value="{_bn(value_v)}">{_bn(label)}</option>\n"""
)
if labeled
else f"<option{_bn(attribs_v)}>{_bn(label)}</option>\n"
if CGI.novals_v
else f"""<option{_bn(attribs_v)} value="{_bn(value_v)}">{_bn(label)}</option>\n"""
)
result_v += "</optgroup>"
return result_v
CGI.optgroup = lambda *_args, **_kwargs: perllib.tie_call(optgroup, _args, _kwargs)
#### Method: popup_menu
# Create a popup menu.
# Parameters:
# $name -> Name for all the menu
# $values -> A pointer to a regular array containing the
# text of each menu item.
# $default -> (optional) Default item to display
# $labels -> (optional)
# A pointer to a hash of labels to print next to each checkbox
# in the form $label{'value'}="Long explanatory label".
# Otherwise the provided values are used as the labels.
# Returns:
# A string containing the definition of a popup menu.
####
CGI.popup_menu = lambda *_args, **_kwargs: perllib.tie_call(popup_menu, _args, _kwargs)
#### Method: checkbox_group
# Create a list of logically-linked checkboxes.
# Parameters:
# $name -> Common name for all the check boxes
# $values -> A pointer to a regular array containing the
# values for each checkbox in the group.
# $defaults -> (optional)
# 1. If a pointer to a regular array of checkbox values,
# then this will be used to decide which
# checkboxes to turn on by default.
# 2. If a scalar, will be assumed to hold the
# value of a single checkbox in the group to turn on.
# $linebreak -> (optional) Set to true to place linebreaks
# between the buttons.
# $labels -> (optional)
# A pointer to a hash of labels to print next to each checkbox
# in the form $label{'value'}="Long explanatory label".
# Otherwise the provided values are used as the labels.
# Returns:
# An ARRAY containing a series of <input type="checkbox"> fields
####
[docs]def checkbox_group(*_args):
[self, *p] = perllib.list_of_at_least_n(self_or_default(*_args, wantarray=True), 1)
p = perllib.Array(p)
return self._box_group("checkbox", *p)
CGI.checkbox_group = lambda *_args, **_kwargs: perllib.tie_call(checkbox_group, _args, _kwargs)
[docs]def radio_group(*_args):
[self, *p] = perllib.list_of_at_least_n(self_or_default(*_args, wantarray=True), 1)
p = perllib.Array(p)
return self._box_group("radio", *p)
CGI.radio_group = lambda *_args, **_kwargs: perllib.tie_call(radio_group, _args, _kwargs)
#### Method: checkbox
# Create a checkbox that is not logically linked to any others.
# The field value is "on" when the button is checked.
# Parameters:
# $name -> Name of the checkbox
# $checked -> (optional) turned on by default if true
# $value -> (optional) value of the checkbox, 'on' by default
# $label -> (optional) a user-readable label printed next to the box.
# Otherwise the checkbox name is used.
# Returns:
# A string containing a <input type="checkbox"> field
####
[docs]def checkbox(*_args):
global _d
[self, *p] = perllib.list_of_at_least_n(self_or_default(*_args, wantarray=True), 1)
p = perllib.Array(p)
[
name,
checked,
value_v,
label,
labelattributes,
override,
tabindex,
*other,
] = perllib.list_of_at_least_n(
rearrange(
perllib.Array(
[
"NAME",
["CHECKED", "SELECTED", "ON"],
"VALUE",
"LABEL",
"LABELATTRIBUTES",
["OVERRIDE", "FORCE"],
"TABINDEX",
]
),
*p,
),
7,
)
other = perllib.Array(other)
value_v = value_v if value_v is not None else "on"
if not override and (self[".fieldnames"].get(_str(name)) or self.param(name) is not None):
checked = (
self._checked(1)
if len(
list(
filter(
lambda _d: _pb(_str(_d) == _str(value_v)),
perllib.make_list(self.param(name)),
)
)
)
else ""
)
else:
checked = self._checked(checked)
[the_label] = perllib.list_of_n(label if label is not None else name, 1)
name = self._maybe_escapeHTML(name)
value_v = self._maybe_escapeHTML(value_v, 1)
the_label = self._maybe_escapeHTML(the_label)
[other_v] = perllib.list_of_n(
f"{perllib.LIST_SEPARATOR.join(map(_str,other))} " if other else "", 1
)
tabindex = self.element_tab(tabindex)
self.register_parameter(name)
return (
CGI.label(
labelattributes,
f'<input type="checkbox" name="{_bn(name)}" value="{_bn(value_v)}" {_bn(tabindex)}{_bn(checked)}{_bn(other_v)}/>{_bn(the_label)}',
)
if CGI.XHTML_v
else f'<input type="checkbox" name="{_bn(name)}" value="{_bn(value_v)}"{_bn(checked)}{_bn(other_v)}>{_bn(the_label)}'
)
CGI.checkbox = lambda *_args, **_kwargs: perllib.tie_call(checkbox, _args, _kwargs)
# Escape HTML
#### Method: defaults
# Create a "defaults" button.
# Parameters:
# $name -> (optional) Name for the button.
# Returns:
# A string containing a <input type="submit" name=".defaults"> tag
#
# Note: this button has a special meaning to the initialization script,
# and tells it to ERASE the current query string so that your defaults
# are used again!
####
[docs]def defaults(*_args):
[self, *p] = perllib.list_of_at_least_n(self_or_default(*_args, wantarray=True), 1)
p = perllib.Array(p)
[label, tabindex, *other] = perllib.list_of_at_least_n(
rearrange(perllib.Array([["NAME", "VALUE"], "TABINDEX"]), *p), 2
)
other = perllib.Array(other)
label = self._maybe_escapeHTML(label, 1)
label = label or "Defaults"
[value_v] = perllib.list_of_n(f' value="{_bn(label)}"', 1)
[other_v] = perllib.list_of_n(
f" {perllib.LIST_SEPARATOR.join(map(_str,other))}" if other else "", 1
)
tabindex = self.element_tab(tabindex)
return (
f'<input type="submit" name=".defaults" {_bn(tabindex)}{_bn(value_v)}{_bn(other_v)} />'
if CGI.XHTML_v
else f'<input type="submit" NAME=".defaults"{_bn(value_v)}{_bn(other_v)}>'
)
CGI.defaults = lambda *_args, **_kwargs: perllib.tie_call(defaults, _args, _kwargs)
#### Method: comment
# Create an HTML <!-- comment -->
# Parameters: a string
#### Method: reset
# Create a "reset" button.
# Parameters:
# $name -> (optional) Name for the button.
# Returns:
# A string containing a <input type="reset"> tag
####
[docs]def reset(*_args):
[self, *p] = perllib.list_of_at_least_n(self_or_default(*_args, wantarray=True), 1)
p = perllib.Array(p)
[label, value_v, tabindex, *other] = perllib.list_of_at_least_n(
rearrange(perllib.Array(["NAME", ["VALUE", "LABEL"], "TABINDEX"]), *p), 3
)
other = perllib.Array(other)
label = self._maybe_escapeHTML(label)
value_v = self._maybe_escapeHTML(value_v, 1)
[name] = perllib.list_of_n(' name=".reset"', 1)
if label is not None:
name = f' name="{_bn(label)}"'
value_v = value_v if value_v is not None else label
[val] = perllib.list_of_n("", 1)
if value_v is not None:
val = f' value="{_bn(value_v)}"'
[other_v] = perllib.list_of_n(
f" {perllib.LIST_SEPARATOR.join(map(_str,other))}" if other else "", 1
)
tabindex = self.element_tab(tabindex)
return (
f'<input type="reset" {_bn(tabindex)}{_bn(name)}{_bn(val)}{_bn(other_v)} />'
if CGI.XHTML_v
else f'<input type="reset"{_bn(name)}{_bn(val)}{_bn(other_v)}>'
)
CGI.reset = lambda *_args, **_kwargs: perllib.tie_call(reset, _args, _kwargs)
#### Method: submit
# Create a "submit query" button.
# Parameters:
# $name -> (optional) Name for the button.
# $value -> (optional) Value of the button when selected (also doubles as label).
# $label -> (optional) Label printed on the button(also doubles as the value).
# Returns:
# A string containing a <input type="submit"> tag
####
[docs]def submit(*_args):
[self, *p] = perllib.list_of_at_least_n(self_or_default(*_args, wantarray=True), 1)
p = perllib.Array(p)
[label, value_v, tabindex, *other] = perllib.list_of_at_least_n(
rearrange(perllib.Array(["NAME", ["VALUE", "LABEL"], "TABINDEX"]), *p), 3
)
other = perllib.Array(other)
label = self._maybe_escapeHTML(label)
value_v = self._maybe_escapeHTML(value_v, 1)
name = "" if CGI.NOSTICKY_v else 'name=".submit" '
if label is not None:
name = f'name="{_bn(label)}" '
value_v = value_v if value_v is not None else label
val = ""
if value_v is not None:
val = f'value="{_bn(value_v)}" '
tabindex = self.element_tab(tabindex)
[other_v] = perllib.list_of_n(
f"{perllib.LIST_SEPARATOR.join(map(_str,other))} " if other else "", 1
)
return (
f'<input type="submit" {_bn(tabindex)}{name}{val}{_bn(other_v)}/>'
if CGI.XHTML_v
else f'<input type="submit" {name}{val}{_bn(other_v)}>'
)
CGI.submit = lambda *_args, **_kwargs: perllib.tie_call(submit, _args, _kwargs)
#### Method: button
# Create a javascript button.
# Parameters:
# $name -> (optional) Name for the button. (-name)
# $value -> (optional) Value of the button when selected (and visible name) (-value)
# $onclick -> (optional) Text of the JavaScript to run when the button is
# clicked.
# Returns:
# A string containing a <input type="button"> tag
####
CGI.button = lambda *_args, **_kwargs: perllib.tie_call(button, _args, _kwargs)
#### Method: textarea
# Parameters:
# $name -> Name of the text field
# $default -> Optional default value of the field if not
# already defined.
# $rows -> Optional number of rows in text area
# $columns -> Optional number of columns in text area
# Returns:
# A string containing a <textarea></textarea> tag
#
[docs]def textarea(*_args):
[self, *p] = perllib.list_of_at_least_n(self_or_default(*_args, wantarray=True), 1)
p = perllib.Array(p)
[name, default, rows, cols, override, tabindex, *other] = perllib.list_of_at_least_n(
rearrange(
perllib.Array(
[
"NAME",
["DEFAULT", "VALUE"],
"ROWS",
["COLS", "COLUMNS"],
["OVERRIDE", "FORCE"],
"TABINDEX",
]
),
*p,
),
6,
)
other = perllib.Array(other)
[current] = perllib.list_of_n(
default
if override
else (
self.param(name, wantarray=True)
if self.param(name, wantarray=True) is not None
else default
),
1,
)
name = self._maybe_escapeHTML(name) if name is not None else ""
current = self._maybe_escapeHTML(current) if current is not None else ""
[r_v] = perllib.list_of_n(f' rows="{_bn(rows)}"' if rows else "", 1)
[c_v] = perllib.list_of_n(f' cols="{_bn(cols)}"' if cols else "", 1)
[other_v] = perllib.list_of_n(
f" {perllib.LIST_SEPARATOR.join(map(_str,other))}" if other else "", 1
)
tabindex = self.element_tab(tabindex)
return f'<textarea name="{_bn(name)}" {_bn(tabindex)}{_bn(r_v)}{_bn(c_v)}{_bn(other_v)}>{_bn(current)}</textarea>'
CGI.textarea = lambda *_args, **_kwargs: perllib.tie_call(textarea, _args, _kwargs)
#### Method: password
# Create a "secret password" entry field
# Parameters:
# $name -> Name of the field
# $default -> Optional default value of the field if not
# already defined.
# $size -> Optional width of field in characters.
# $maxlength -> Optional maximum characters that can be entered.
# Returns:
# A string containing a <input type="password"> field
#
[docs]def password_field(*_args):
[self, *p] = perllib.list_of_at_least_n(self_or_default(*_args, wantarray=True), 1)
p = perllib.Array(p)
return self._textfield("password", *p)
CGI.password_field = lambda *_args, **_kwargs: perllib.tie_call(password_field, _args, _kwargs)
#### Method: filefield
# Parameters:
# $name -> Name of the file upload field
# $size -> Optional width of field in characaters.
# $maxlength -> Optional maximum number of characters.
# Returns:
# A string containing a <input type="file"> field
#
[docs]def filefield(*_args):
[self, *p] = perllib.list_of_at_least_n(self_or_default(*_args, wantarray=True), 1)
p = perllib.Array(p)
return self._textfield("file", *p)
CGI.filefield = lambda *_args, **_kwargs: perllib.tie_call(filefield, _args, _kwargs)
#### Method: textfield
# Parameters:
# $name -> Name of the text field
# $default -> Optional default value of the field if not
# already defined.
# $size -> Optional width of field in characaters.
# $maxlength -> Optional maximum number of characters.
# Returns:
# A string containing a <input type="text"> field
#
[docs]def textfield(*_args):
[self, *p] = perllib.list_of_at_least_n(self_or_default(*_args, wantarray=True), 1)
p = perllib.Array(p)
return self._textfield("text", *p)
CGI.textfield = lambda *_args, **_kwargs: perllib.tie_call(textfield, _args, _kwargs)
def _textfield(*_args):
[self, tag, *p] = perllib.list_of_at_least_n(self_or_default(*_args, wantarray=True), 2)
p = perllib.Array(p)
[name, default, size, maxlength, override, tabindex, *other] = perllib.list_of_at_least_n(
rearrange(
perllib.Array(
[
"NAME",
["DEFAULT", "VALUE", "VALUES"],
"SIZE",
"MAXLENGTH",
["OVERRIDE", "FORCE"],
"TABINDEX",
]
),
*p,
),
6,
)
other = perllib.Array(other)
current = (
default if override else (self.param(name) if self.param(name) is not None else default)
)
current = self._maybe_escapeHTML(current, 1) if current is not None else ""
name = self._maybe_escapeHTML(name) if name is not None else ""
[s_v] = perllib.list_of_n(f' size="{_bn(size)}"' if size is not None else "", 1)
[m] = perllib.list_of_n(f' maxlength="{_bn(maxlength)}"' if maxlength is not None else "", 1)
[other_v] = perllib.list_of_n(
f" {perllib.LIST_SEPARATOR.join(map(_str,other))}" if other else "", 1
)
# this entered at cristy's request to fix problems with file upload fields
# and WebTV -- not sure it won't break stuff
[value_v] = perllib.list_of_n(f'value="{_bn(current)}"' if _str(current) != "" else "", 1)
tabindex = self.element_tab(tabindex)
return (
f'<input type="{_bn(tag)}" name="{_bn(name)}" {_bn(tabindex)}{_bn(value_v)}{_bn(s_v)}{_bn(m)}{_bn(other_v)} />'
if CGI.XHTML_v
else f'<input type="{_bn(tag)}" name="{_bn(name)}" {_bn(value_v)}{_bn(s_v)}{_bn(m)}{_bn(other_v)}>'
)
CGI._textfield = lambda *_args, **_kwargs: perllib.tie_call(_textfield, _args, _kwargs)
#### Method: end_form
# End a form
# Note: This repeated below under the older name.
CGI.end_form = lambda *_args, **_kwargs: perllib.tie_call(end_form, _args, _kwargs)
#### Method: end_multipart_form
# end a multipart form
CGI.end_multipart_form = lambda *_args, **_kwargs: perllib.tie_call(
end_multipart_form, _args, _kwargs
)
#### Method: start_multipart_form
CGI.start_multipart_form = lambda *_args, **_kwargs: perllib.tie_call(
start_multipart_form, _args, _kwargs
)
#### Method: start_form
# Start a form
# Parameters:
# $method -> optional submission method to use (GET or POST)
# $action -> optional URL of script to run
# $enctype ->encoding to use (URL_ENCODED or MULTIPART)
CGI.start_form = lambda *_args, **_kwargs: perllib.tie_call(start_form, _args, _kwargs)
[docs]def isindex(*_args):
[self, *p] = perllib.list_of_at_least_n(self_or_default(*_args, wantarray=True), 1)
p = perllib.Array(p)
[action, *other] = perllib.list_of_at_least_n(rearrange(perllib.Array(["ACTION"]), *p), 1)
other = perllib.Array(other)
if action:
action = f' action="{_bn(action)}"'
[other_v] = perllib.list_of_n(
f" {perllib.LIST_SEPARATOR.join(map(_str,other))}" if other else "", 1
)
return (
f"<isindex{_bn(action)}{_bn(other_v)} />"
if CGI.XHTML_v
else f"<isindex{_bn(action)}{_bn(other_v)}>"
)
CGI.isindex = lambda *_args, **_kwargs: perllib.tie_call(isindex, _args, _kwargs)
#### Method: redirect
# Return a Location: style header
#
####
[docs]def redirect(*_args):
global _d
[self, *p] = perllib.list_of_at_least_n(self_or_default(*_args, wantarray=True), 1)
p = perllib.Array(p)
[url_v, target, status, cookie_v, nph_v, *other] = perllib.list_of_at_least_n(
rearrange(
perllib.Array(
[
["LOCATION", "URI", "URL"],
"TARGET",
"STATUS",
["COOKIE", "COOKIES", "SET-COOKIE"],
"NPH",
]
),
*p,
),
5,
)
other = perllib.Array(other)
if status is None:
status = "302 Found"
url_v = url_v or self.self_url()
o = perllib.Array()
for _d in other:
_d = _str(_d).translate(str.maketrans("", "", '"'))
o.extend(perllib.make_list(_str(_d).split("=", 2 - 1)))
o[0:0] = ["-Status", status, "-Location", url_v, "-nph", nph_v]
if target:
o[0:0] = ["-Target", target]
o[0:0] = ["-Type", ""]
unescaped = perllib.Array()
if cookie_v:
unescaped[0:0] = ["-Cookie", cookie_v]
return self.header(*(perllib.flatten(map(lambda _d: self.unescapeHTML(_d), o))), *unescaped)
CGI.redirect = lambda *_args, **_kwargs: perllib.tie_call(redirect, _args, _kwargs)
#### Method: start_html
# Canned HTML header
#
# Parameters:
# $title -> (optional) The title for this HTML document (-title)
# $author -> (optional) e-mail address of the author (-author)
# $base -> (optional) if set to true, will enter the BASE address of this document
# for resolving relative references (-base)
# $xbase -> (optional) alternative base at some remote location (-xbase)
# $target -> (optional) target window to load all links into (-target)
# $script -> (option) Javascript code (-script)
# $no_script -> (option) Javascript <noscript> tag (-noscript)
# $meta -> (optional) Meta information tags
# $head -> (optional) any other elements you'd like to incorporate into the <head> tag
# (a scalar or array ref)
# $style -> (optional) reference to an external style sheet
# @other -> (optional) any other named parameters you'd like to incorporate into
# the <body> tag.
####
#### Method: cache
# Control whether header() will produce the no-cache
# Pragma directive.
####
[docs]def cache(*_args):
[self, new_value] = perllib.list_of_n(self_or_default(*_args, wantarray=True), 2)
if not new_value:
new_value = ""
if _str(new_value) != "":
self["cache"] = new_value
return self.get("cache")
CGI.cache = lambda *_args, **_kwargs: perllib.tie_call(cache, _args, _kwargs)
#### Method: multipart_final
# Return a MIME boundary separator for server-push, end of all sections
#
# Contributed by Andrew Benham (adsb@bigfoot.com)
####
[docs]def multipart_final(*_args):
[self, *p] = perllib.list_of_at_least_n(self_or_default(*_args, wantarray=True), 1)
p = perllib.Array(p)
return (
_str(self.get("final_separator"))
+ "WARNING: YOUR BROWSER DOESN'T SUPPORT THIS SERVER-PUSH TECHNOLOGY."
+ _str(CGI.CRLF_v)
)
CGI.multipart_final = lambda *_args, **_kwargs: perllib.tie_call(multipart_final, _args, _kwargs)
#### Method: header
# Return a Content-Type: style header
#
####
#### Method: multipart_end
# Return a MIME boundary separator for server-push, end of section
#
# Many thanks to Ed Jordan <ed@fidalgo.net> for this
# contribution
####
[docs]def multipart_end(*_args):
[self, *p] = perllib.list_of_at_least_n(self_or_default(*_args, wantarray=True), 1)
p = perllib.Array(p)
return self.get("separator")
CGI.multipart_end = lambda *_args, **_kwargs: perllib.tie_call(multipart_end, _args, _kwargs)
[docs]def multipart_init(*_args):
global _d
chrs = perllib.Array()
[self, *p] = perllib.list_of_at_least_n(self_or_default(*_args, wantarray=True), 1)
p = perllib.Array(p)
[boundary, charset_v, *other] = perllib.list_of_at_least_n(
rearrange_header(perllib.Array(["BOUNDARY", "CHARSET"]), *p), 2
)
other = perllib.Array(other)
if not boundary:
boundary = "------- =_"
chrs = perllib.Array(
[
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"A",
"B",
"C",
"D",
"E",
"F",
"G",
"H",
"I",
"J",
"K",
"L",
"M",
"N",
"O",
"P",
"Q",
"R",
"S",
"T",
"U",
"V",
"W",
"X",
"Y",
"Z",
"a",
"b",
"c",
"d",
"e",
"f",
"g",
"h",
"i",
"j",
"k",
"l",
"m",
"n",
"o",
"p",
"q",
"r",
"s",
"t",
"u",
"v",
"w",
"x",
"y",
"z",
]
)
for _d in range(1, 17 + 1):
boundary = _str(boundary) + _str(chrs[perllib.int_(perllib.rand(len(chrs)))])
self["separator"] = f"{_bn(CGI.CRLF_v)}--{_bn(boundary)}{_bn(CGI.CRLF_v)}"
self["final_separator"] = f"{_bn(CGI.CRLF_v)}--{_bn(boundary)}--{_bn(CGI.CRLF_v)}"
CGI.type_v = SERVER_PUSH(boundary)
return (
_str(
self.header(
"-nph",
0,
"-type",
CGI.type_v,
"-charset",
charset_v,
*(perllib.flatten(map(lambda _d: _d.split("=", 2 - 1), other))),
)
)
+ "WARNING: YOUR BROWSER DOESN'T SUPPORT THIS SERVER-PUSH TECHNOLOGY."
+ _str(self.multipart_end())
)
CGI.multipart_init = lambda *_args, **_kwargs: perllib.tie_call(multipart_init, _args, _kwargs)
#### Method: multipart_start
# Return a Content-Type: style header for server-push, start of section
#
# Many thanks to Ed Jordan <ed@fidalgo.net> for this
# contribution, updated by Andrew Benham (adsb@bigfoot.com)
####
#### Method: autoescape
# If you want to turn off the autoescaping features,
# call this method with undef as the argument
[docs]def autoEscape(*_args):
[self, escape_v] = perllib.list_of_n(self_or_default(*_args, wantarray=True), 2)
d = self.get("escape")
self["escape"] = escape_v
return d
CGI.autoEscape = lambda *_args, **_kwargs: perllib.tie_call(autoEscape, _args, _kwargs)
[docs]def Delete_all(*_args):
[self, *p] = perllib.list_of_at_least_n(self_or_default(*_args, wantarray=True), 1)
p = perllib.Array(p)
return self.delete_all(*p)
CGI.Delete_all = lambda *_args, **_kwargs: perllib.tie_call(Delete_all, _args, _kwargs)
[docs]def Delete(*_args):
[self, *p] = perllib.list_of_at_least_n(self_or_default(*_args, wantarray=True), 1)
p = perllib.Array(p)
return self.delete(*p)
CGI.Delete = lambda *_args, **_kwargs: perllib.tie_call(Delete, _args, _kwargs)
#### Method: delete_all
# Delete all parameters
####
[docs]def delete_all(*_args):
[self] = perllib.list_of_n(self_or_default(*_args, wantarray=True), 1)
param_a = perllib.Array(self.param(wantarray=True))
return self.delete(*param_a)
CGI.delete_all = lambda *_args, **_kwargs: perllib.tie_call(delete_all, _args, _kwargs)
[docs]def append(*_args):
[self, *p] = perllib.list_of_at_least_n(self_or_default(*_args, wantarray=True), 1)
p = perllib.Array(p)
[name, value_v] = perllib.list_of_n(
rearrange(perllib.Array(["NAME", ["VALUE", "VALUES"]]), *p), 2
)
values_ = perllib.Array(
(value_v if perllib.ref_scalar(value_v) else value_v)
if value_v is not None
else perllib.Array()
)
if values_:
self.add_parameter(name)
self["param"].get(_str(name)).extend(values_)
return self.param(name)
CGI.append = lambda *_args, **_kwargs: perllib.tie_call(append, _args, _kwargs)
CGI.MultipartBuffer.readHeader = lambda *_args, **_kwargs: perllib.tie_call(
readHeader, _args, _kwargs
)
# -------------- really private subroutines -----------------
def _maybe_escapeHTML(*_args):
_args = list(_args)
# hack to work around earlier hacks
if len(_args) == 1 and _str(_args[0]) == "CGI":
_args.append(_args[0])
[self, toencode, newlinestoo] = perllib.list_of_n(
CGI.self_or_default(*_args, wantarray=True), 3
)
if toencode is None:
return None
if perllib.ref_scalar(self) and not self.get("escape"):
return toencode
return self.escapeHTML(toencode, newlinestoo)
CGI._maybe_escapeHTML = lambda *_args, **_kwargs: perllib.tie_call(
_maybe_escapeHTML, _args, _kwargs
)
#### Method: protocol
# Return the protocol (http or https currently)
####
[docs]def protocol(*_args):
_args = list(_args)
try:
_locals_stack.append(perllib.WARNING)
[perllib.WARNING] = perllib.list_of_n(0, 1)
self = _args.pop(0) if _args else None
if _str(self.https()).upper() == "ON":
return "https"
if perllib.num(self.server_port()) == 443:
return "https"
prot = self.server_protocol()
[protocol_v, version_v] = perllib.list_of_n(_str(prot).split("/"), 2)
return f"{(_bn(protocol_v)).lower()}"
finally:
perllib.WARNING = _locals_stack.pop()
CGI.protocol = lambda *_args, **_kwargs: perllib.tie_call(protocol, _args, _kwargs)
[docs]def query_string(*_args):
global _d, param_l, value_l
[self] = perllib.list_of_n(self_or_default(*_args, wantarray=True), 1)
param_v = None
value_v = None
pairs = perllib.Array()
for param_l in perllib.flatten([self.param(wantarray=True)]):
[eparam] = perllib.list_of_n(escape(param_l), 1)
for _i2941, value_l in enumerate(
_s2941 := perllib.flatten([self.param(param_l, wantarray=True)])
):
value_l = escape(value_l)
_s2941[_i2941] = value_l
if value_l is None:
continue
pairs.append(f"{_bn(eparam)}={_bn(value_l)}")
for _d in sorted(list(self[".fieldnames"].keys())):
pairs.extend(perllib.make_list(".cgifields=" + _str(escape(f"{_bn(_d)}"))))
return (";" if CGI.USE_PARAM_SEMICOLONS_v else "&").join(map(_str, pairs))
CGI.query_string = lambda *_args, **_kwargs: perllib.tie_call(query_string, _args, _kwargs)
[docs]def hidden(*_args, wantarray=False):
global _d
[self, *p] = perllib.list_of_at_least_n(self_or_default(*_args, wantarray=True), 1)
p = perllib.Array(p)
# this is the one place where we departed from our standard
# calling scheme, so we have to special-case (darn)
result = perllib.Array()
value_a = perllib.Array()
[name, default, override, *other] = perllib.list_of_at_least_n(
rearrange(
perllib.Array(["NAME", ["DEFAULT", "VALUE", "VALUES"], ["OVERRIDE", "FORCE"]]), *p
),
3,
)
other = perllib.Array(other)
do_override = 0
if perllib.ref_scalar(p[0]) or _str(p[0])[0:1] == "-":
value_a = perllib.Array(default if perllib.ref_scalar(default) else default)
do_override = override
else:
for _d in (default, override, other):
if _d is not None:
value_a.append(_d)
other = perllib.Array()
# use previous values if override is not set
prev_a = perllib.Array(self.param(name, wantarray=True))
if not do_override and prev_a:
value_a = prev_a.copy()
name = self._maybe_escapeHTML(name)
for _i2638, _d in enumerate(value_a):
_d = self._maybe_escapeHTML(_d, 1) if _d is not None else ""
value_a[_i2638] = _d
result.extend(
perllib.make_list(
f'<input type="hidden" name="{_bn(name)}" value="{_bn(_d)}" {perllib.LIST_SEPARATOR.join(map(_str,other))} />'
if CGI.XHTML_v
else f'<input type="hidden" name="{_bn(name)}" value="{_bn(_d)}" {perllib.LIST_SEPARATOR.join(map(_str,other))}>'
)
)
return result if wantarray else "".join(map(_str, result))
CGI.hidden = lambda *_args, **_kwargs: perllib.tie_call(hidden, _args, _kwargs)
[docs]def get_fields(*_args):
[self] = perllib.list_of_n(_args, 1)
return CGI.hidden(
self,
"-name",
".cgifields",
"-values",
(sorted(self[".parametersToAdd"].keys())),
"-override",
1,
)
CGI.get_fields = lambda *_args, **_kwargs: perllib.tie_call(get_fields, _args, _kwargs)
def _box_group(*_args, wantarray=False):
_args = list(_args)
global _d
self = _args.pop(0) if _args else None
box_type = _args.pop(0) if _args else None
[
name,
values_v,
defaults_v,
linebreak,
labels,
labelattributes,
attributes,
rows,
columns,
rowheaders,
colheaders,
override,
nolabels,
tabindex,
disabled,
*other,
] = perllib.list_of_at_least_n(
rearrange(
perllib.Array(
[
"NAME",
["VALUES", "VALUE"],
["DEFAULT", "DEFAULTS"],
"LINEBREAK",
"LABELS",
"LABELATTRIBUTES",
"ATTRIBUTES",
"ROWS",
["COLUMNS", "COLS"],
["ROWHEADERS", "ROWHEADER"],
["COLHEADERS", "COLHEADER"],
["OVERRIDE", "FORCE"],
"NOLABELS",
"TABINDEX",
"DISABLED",
]
),
*_args,
),
15,
)
other = perllib.Array(other)
result_v = None
checked = None
elements = perllib.Array()
values_ = perllib.Array()
values_ = perllib.Array(
(
self._set_values_and_labels(values_v, labels, name),
(labels := perllib.fetch_out_parameter(2)),
)[0]
)
checked_h = perllib.Hash(self.previous_or_default(name, defaults_v, override))
# If no check array is specified, check the first by default
if _str(box_type) == "radio" and not checked_h:
checked_h[_s0] = perllib.num(checked_h.get(_s0 := _str(values_[0]))) + 1
name = self._maybe_escapeHTML(name)
tabs = perllib.Hash()
if CGI.TABINDEX_v and tabindex:
if not perllib.ref_scalar(tabindex):
self.element_tab(tabindex)
elif perllib.refs(tabindex) == "ARRAY":
tabs = perllib.Hash(
perllib.list_to_hash(
perllib.flatten(
map(lambda _d: [_d, self.element_tab()], perllib.make_list(tabindex))
)
)
)
elif perllib.refs(tabindex) == "HASH":
tabs = tabindex
if not tabs:
tabs = perllib.Hash(
perllib.list_to_hash(
perllib.flatten(map(lambda _d: [_d, self.element_tab()], values_))
)
)
other_v = f"{perllib.LIST_SEPARATOR.join(map(_str,other))} " if other else ""
radio_checked = 0
# for disabling groups of radio/checkbox buttons
disabled_h = perllib.Hash()
for _d in disabled:
disabled_h[_str(_d)] = 1
for _i2376, _d in enumerate(values_):
disable = ""
if disabled_h.get(_str(_d)):
disable = "disabled='1'"
checkit = self._checked(
(checked_h.get(_d) and not ((radio_checked := radio_checked + 1) - 1))
if box_type == "radio"
else checked_h.get(_d)
)
break_ = ""
if linebreak:
break_ = "<br />" if CGI.XHTML_v else "<br>"
else:
break_ = ""
[label] = perllib.list_of_n("", 1)
if not (nolabels is not None and nolabels):
label = _d
if labels is not None and labels.get(_str(_d)) is not None:
label = labels.get(_str(_d))
label = self._maybe_escapeHTML(label, 1)
if disabled_h.get(_str(_d)):
label = f'<span style="color:gray">{_bn(label)}</span>'
attribs_v = self._set_attributes(_d, attributes)
tab = tabs.get(_str(_d))
_d = self._maybe_escapeHTML(_d)
values_[_i2376] = _d
if CGI.XHTML_v:
elements.extend(
perllib.make_list(
_str(
CGI.label(
labelattributes,
f'<input type="{_bn(box_type)}" name="{_bn(name)}" value="{_bn(_d)}" {_bn(checkit)}{other_v}{_bn(tab)}{_bn(attribs_v)}{disable}/>{_bn(label)}',
)
)
+ break_
)
)
else:
elements.append(
f"""<input type="{_bn(box_type)}" name="{_bn(name)}" value="{_bn(_d)}" {_bn(checkit)}{other_v}{_bn(tab)}{_bn(attribs_v)}{disable}>{_bn(label)}{break_}"""
)
self.register_parameter(name)
if not (columns is not None or rows is not None):
return elements if wantarray else f"{perllib.LIST_SEPARATOR.join(map(_str,elements))}"
return _tableize(rows, columns, rowheaders, colheaders, *elements)
CGI._box_group = lambda *_args, **_kwargs: perllib.tie_call(_box_group, _args, _kwargs)
# unescape HTML -- used internally
[docs]def unescapeHTML(*_args):
_args = list(_args)
import HTML.Entities as _HTML_Entities
# hack to work around earlier hacks
if len(_args) == 1 and _str(_args[0]) == "CGI":
_args.append(_args[0])
[self, string] = perllib.list_of_n(CGI.self_or_default(*_args, wantarray=True), 2)
if string is None:
return None
return (HTML.Entities.decode_entities(string), (string := perllib.fetch_out_parameter(0)))[0]
CGI.unescapeHTML = lambda *_args, **_kwargs: perllib.tie_call(unescapeHTML, _args, _kwargs)
[docs]def escapeHTML(*_args):
_args = list(_args)
import HTML.Entities as _HTML_Entities
# hack to work around earlier hacks
if len(_args) == 1 and _str(_args[0]) == "CGI":
_args.append(_args[0])
[self, toencode, newlinestoo] = perllib.list_of_n(
CGI.self_or_default(*_args, wantarray=True), 3
)
if toencode is None:
return None
encode_entities_v = CGI.ENCODE_ENTITIES_v
if encode_entities_v and newlinestoo:
encode_entities_v = _str(encode_entities_v) + "\012\015"
return (
HTML.Entities.encode_entities(toencode, encode_entities_v),
(toencode := perllib.fetch_out_parameter(0)),
)[0]
CGI.escapeHTML = lambda *_args, **_kwargs: perllib.tie_call(escapeHTML, _args, _kwargs)
### Method: _style
# internal method for generating a CSS style section
####
def _style(*_args):
global _d, src_l
alternate = None
c = perllib.Array()
code = None
foo = None
other = perllib.Array()
src = None
stype = None
v = perllib.Array()
verbatim = None
[self, style] = perllib.list_of_n(_args, 2)
result = perllib.Array()
type_v = "text/css"
rel = "stylesheet"
cdata_start = "\n<!--/* <![CDATA[ */" if CGI.XHTML_v else "\n<!-- "
cdata_end = "\n/* ]]> */-->\n" if CGI.XHTML_v else " -->\n"
s = perllib.Array(style if perllib.refs(style) == "ARRAY" else style)
other_v = ""
for s_l in s:
if perllib.ref_scalar(s_l):
[src, code, verbatim, stype, alternate, foo, *other] = perllib.list_of_at_least_n(
rearrange(
"SRC CODE VERBATIM TYPE ALTERNATE FOO".split(),
("-foo", "bar", s_l if perllib.refs(s_l) == "ARRAY" else s_l),
),
6,
)
other = perllib.Array(other)
type_v = stype if stype is not None else "text/css"
rel = "alternate stylesheet" if alternate else "stylesheet"
if other:
other_v = f"{perllib.LIST_SEPARATOR.join(map(_str,other))}"
if (
perllib.refs(src) == "ARRAY"
): # Check to see if the $src variable is an array reference # If it is, push a LINK tag for each one
for src_l in src_l:
if src_l:
result.extend(
perllib.make_list(
f'<link rel="{rel}" type="{_bn(type_v)}" href="{_bn(src_l)}" {other_v}/>'
if CGI.XHTML_v
else f'<link rel="{rel}" type="{_bn(type_v)}" href="{_bn(src_l)}"{other_v}>'
)
)
else:
# Otherwise, push the single -src, if it exists.
if src:
result.extend(
perllib.make_list(
f'<link rel="{rel}" type="{_bn(type_v)}" href="{_bn(src)}" {other_v}/>'
if CGI.XHTML_v
else f'<link rel="{rel}" type="{_bn(type_v)}" href="{_bn(src)}"{other_v}>'
)
)
if verbatim:
v = perllib.Array(verbatim if perllib.refs(verbatim) == "ARRAY" else verbatim)
for _d in v:
result.append(f"""<style type="text/css">\n{_bn(_d)}\n</style>""")
if code:
c = perllib.Array(code if perllib.refs(code) == "ARRAY" else code)
for _d in c:
result.extend(
perllib.make_list(
CGI.style({"type": type_v}, f"{cdata_start}\n{_bn(_d)}\n{cdata_end}")
)
)
else:
src = s_l
result.extend(
perllib.make_list(
f'<link rel="{rel}" type="{_bn(type_v)}" href="{_bn(src)}" {other_v}/>'
if CGI.XHTML_v
else f'<link rel="{rel}" type="{_bn(type_v)}" href="{_bn(src)}"{other_v}>'
)
)
return result
CGI._style = lambda *_args, **_kwargs: perllib.tie_call(_style, _args, _kwargs)
[docs]def start_html(*_args):
global _d
href = None
meta_bits = None
t = ""
[self, *p] = perllib.list_of_at_least_n(self_or_default(*_args, wantarray=True), 1)
p = perllib.Array(p)
[
title,
author,
base,
xbase,
script,
noscript,
target,
meta,
head,
style,
dtd,
lang,
encoding,
declare_xml,
*other,
] = perllib.list_of_at_least_n(
rearrange(
perllib.Array(
[
"TITLE",
"AUTHOR",
"BASE",
"XBASE",
"SCRIPT",
"NOSCRIPT",
"TARGET",
"META",
"HEAD",
"STYLE",
"DTD",
"LANG",
"ENCODING",
"DECLARE_XML",
]
),
*p,
),
14,
)
other = perllib.Array(other)
self.element_id(0)
self.element_tab(0)
if encoding is None:
encoding = _str(self.charset()).lower()
# Need to sort out the DTD before it's okay to call escapeHTML().
result = perllib.Array()
xml_dtd = 0
if dtd:
if perllib.ref_scalar(dtd) is not None and (perllib.refs(dtd) == "ARRAY"):
if not ((re.search(r"^-//", _str(dtd[0])))):
dtd = CGI.DEFAULT_DTD_v
else:
if not ((re.search(r"^-//", _str(dtd)))):
dtd = CGI.DEFAULT_DTD_v
else:
dtd = CGI._XHTML_DTD_v if CGI.XHTML_v else CGI.DEFAULT_DTD_v
if perllib.refs(dtd) == "ARRAY" and (re.search(re.compile(r"\bXHTML\b", re.I), _str(dtd[0]))):
xml_dtd += 1
if perllib.ref_scalar(dtd) == "" and (re.search(re.compile(r"\bXHTML\b", re.I), _str(dtd))):
xml_dtd += 1
if xml_dtd and declare_xml:
result.append(f'<?xml version="1.0" encoding="{_bn(encoding)}"?>')
if perllib.ref_scalar(dtd) and perllib.refs(dtd) == "ARRAY":
result.append(f"""<!DOCTYPE html\n\tPUBLIC "{_bn(dtd)[0]}"\n\t "{_bn(dtd)[1]}">""")
CGI.DTD_PUBLIC_IDENTIFIER_v = dtd[0]
else:
result.append(f"""<!DOCTYPE html\n\tPUBLIC "{_bn(dtd)}">""")
CGI.DTD_PUBLIC_IDENTIFIER_v = dtd
# Now that we know whether we're using the HTML 3.2 DTD or not, it's okay to
# call escapeHTML(). Strangely enough, the title needs to be escaped as
# HTML while the author needs to be escaped as a URL.
title = self._maybe_escapeHTML(title or "Untitled Document")
author = self.escape(author)
if _m := re.search(
re.compile(r"[^X]HTML (2\.0|3\.2|4\.01?)", re.I), _str(CGI.DTD_PUBLIC_IDENTIFIER_v)
):
if lang is None:
lang = ""
CGI.XHTML_v = 0
else:
if lang is None:
lang = "en-US"
lang_bits = f' lang="{_bn(lang)}" xml:lang="{_bn(lang)}"' if _str(lang) != "" else ""
if CGI.XHTML_v and encoding and not declare_xml:
meta_bits = (
f'<meta http-equiv="Content-Type" content="text/html; charset={_bn(encoding)}" />'
)
result.extend(
perllib.make_list(
f"""<html xmlns="http://www.w3.org/1999/xhtml"{lang_bits}>\n<head>\n<title>{_bn(title)}</title>"""
if CGI.XHTML_v
else (f'<html lang="{_bn(lang)}">' if lang else "<html>")
+ f"<head><title>{_bn(title)}</title>"
)
)
if author is not None:
result.extend(
perllib.make_list(
f'<link rev="made" href="mailto:{_bn(author)}" />'
if CGI.XHTML_v
else f'<link rev="made" href="mailto:{_bn(author)}">'
)
)
if base or xbase or target:
href = xbase or self.url("-path", 1)
t = f' target="{_bn(target)}"' if target else ""
result.extend(
perllib.make_list(
f'<base href="{_bn(href)}"{t} />'
if CGI.XHTML_v
else f'<base href="{_bn(href)}"{t}>'
)
)
if meta and perllib.ref_scalar(meta) and (perllib.refs(meta) == "HASH"):
for _d in sorted(list((meta if meta is not None else perllib.Hash()).keys())):
result.extend(
perllib.make_list(
f"""<meta name="{_bn(_d)}" content="{_bn(meta).get(_str(_d),'')}" />"""
if CGI.XHTML_v
else f"""<meta name="{_bn(_d)}" content="{_bn(meta).get(_str(_d),'')}">"""
)
)
meta_bits_set = 0
if head:
if perllib.ref_scalar(head):
result.append(head)
if list(
filter(lambda _d: r"""http-equiv=["']Content-Type""" "i", perllib.make_list(head))
):
meta_bits_set = 1
else:
result.append(head)
if re.search(re.compile(r"""http-equiv=["']Content-Type""", re.I), _str(head)):
meta_bits_set = 1
# handle the infrequently-used -style and -script parameters
if style is not None:
result.extend(perllib.make_list(self._style(style)))
if script is not None:
result.extend(perllib.make_list(self._script(script)))
if meta_bits is not None and not meta_bits_set:
result.append(meta_bits)
# handle -noscript parameter
if noscript:
result.append(
f"""<noscript>
{_bn(noscript)}
</noscript>
"""
)
[other_v] = perllib.list_of_n(
f" {perllib.LIST_SEPARATOR.join(map(_str,other))}" if other else "", 1
)
result.append(f"</head>\n<body{_bn(other_v)}>\n")
return "\n".join(map(_str, result))
CGI.start_html = lambda *_args, **_kwargs: perllib.tie_call(start_html, _args, _kwargs)
[docs]def multipart_start(*_args):
global CRLF_v, _d
header_a = perllib.Array()
[self, *p] = perllib.list_of_at_least_n(self_or_default(*_args, wantarray=True), 1)
p = perllib.Array(p)
[type_v, charset_v, *other] = perllib.list_of_at_least_n(
rearrange(perllib.Array(["TYPE", "CHARSET"]), *p), 2
)
other = perllib.Array(other)
type_v = type_v or "text/html"
if charset_v:
header_a.append(f"Content-Type: {_bn(type_v)}; charset={_bn(charset_v)}")
else:
header_a.append(f"Content-Type: {_bn(type_v)}")
# rearrange() was designed for the HTML portion, so we
# need to fix it up a little.
for _i1503, _d in enumerate(other):
# Don't use \s because of perl bug 21951
[CGI.header_v, CGI.value_v] = perllib.list_of_n(
(
(_m := re.search(r"([^ \r\n\t=]+)=\"?(.+?)\"?$", _str(_d))),
_m.groups() if _m else [],
)[1],
2,
)
if not _m:
continue
def _f1506(_m_):
global _m
_m = _m_
nonlocal self
return _m.group(1) + _m.group(2).lower() + ": " + _str(self.unescapeHTML(CGI.value_v))
other[_i1503] = _d
_d = re.sub(re.compile(r"^(\w)(.*)"), _f1506, _str(CGI.header_v), count=1)
other[_i1503] = _d
header_a.extend(other)
header_v = (_str(CGI.CRLF_v)).join(
map(_str, header_a)
) + f"{_bn(CGI.CRLF_v)}{_bn(CGI.CRLF_v)}"
return header_v
CGI.multipart_start = lambda *_args, **_kwargs: perllib.tie_call(multipart_start, _args, _kwargs)
#### Method: save
# Write values out to a filehandle in such a way that they can
# be reinitialized by the filehandle form of the new() method
####
[docs]def save(*_args):
global _d, param_l, value_l
try:
_locals_stack.append(perllib.OUTPUT_FIELD_SEPARATOR)
_locals_stack.append(perllib.OUTPUT_RECORD_SEPARATOR)
[self, filehandle] = perllib.list_of_n(self_or_default(*_args, wantarray=True), 2)
filehandle = to_filehandle(filehandle)
param_v = None
[perllib.OUTPUT_FIELD_SEPARATOR] = perllib.list_of_n(
"", 1
) # set print field separator back to a sane value
[perllib.OUTPUT_RECORD_SEPARATOR] = perllib.list_of_n(
"", 1
) # set output line separator to a sane value
for param_l in perllib.flatten([self.param(wantarray=True)]):
[escaped_param] = perllib.list_of_n(escape(param_l), 1)
value_v = None
for value_l in perllib.flatten([self.param(param_l, wantarray=True)]):
if len(_str(escaped_param)) or len(_str(value_l)):
perllib.perl_print(
f"{_bn(escaped_param)}=", escape(f"{_bn(value_l)}"), "", file=filehandle
)
for _d in sorted(list(self[".fieldnames"].keys())):
perllib.perl_print(".cgifields=", escape(f"{_bn(_d)}"), "", file=filehandle)
return perllib.perl_print("=", file=filehandle) # end of record
finally:
perllib.OUTPUT_RECORD_SEPARATOR = _locals_stack.pop()
perllib.OUTPUT_FIELD_SEPARATOR = _locals_stack.pop()
CGI.save = lambda *_args, **_kwargs: perllib.tie_call(save, _args, _kwargs)
#### Method: save_parameters
# An alias for save() that is a better name for exportation.
# Only intended to be used with the function (non-OO) interface.
####
[docs]def save_parameters(*_args):
_args = list(_args)
fh = _args.pop(0) if _args else None
return save(to_filehandle(fh))
CGI.save_parameters = lambda *_args, **_kwargs: perllib.tie_call(save_parameters, _args, _kwargs)
#### Method: Dump
# Returns a string in which all the known parameter/value
# pairs are represented as nested lists, mainly for the purposes
# of debugging.
####
[docs]def Dump(*_args):
global param_l, value_l
[self] = perllib.list_of_n(self_or_default(*_args, wantarray=True), 1)
param_v = None
value_v = None
result = perllib.Array()
if not self.param():
return "<ul></ul>"
result.append("<ul>")
for param_l in perllib.flatten([self.param(wantarray=True)]):
[name] = perllib.list_of_n(self._maybe_escapeHTML(param_l), 1)
result.append(f"<li><strong>{_bn(name)}</strong></li>")
result.append("<ul>")
for _i1395, value_l in enumerate(
_s1395 := perllib.flatten([self.param(param_l, wantarray=True)])
):
value_l = self._maybe_escapeHTML(value_l)
_s1395[_i1395] = value_l
value_l = re.sub(re.compile(r"\n"), r"<br />\n", _str(value_l), count=0)
_s1395[_i1395] = value_l
result.append(f"<li>{_bn(value_l)}</li>")
result.append("</ul>")
result.append("</ul>")
return "\n".join(map(_str, result))
CGI.Dump = lambda *_args, **_kwargs: perllib.tie_call(Dump, _args, _kwargs)
#### Method as_string
#
# synonym for "dump"
####
[docs]def as_string(*_args):
return Dump(*_args)
CGI.as_string = lambda *_args, **_kwargs: perllib.tie_call(as_string, _args, _kwargs)
CGI.header = lambda *_args, **_kwargs: perllib.tie_call(header, _args, _kwargs)
[docs]def url_param(*_args, wantarray=False):
_args = list(_args)
global _d
keywords_a = perllib.Array()
pairs = perllib.Array()
param_v = None
value_v = None
[self, *p] = perllib.list_of_at_least_n(self_or_default(*_args, wantarray=True), 1)
p = perllib.Array(p)
name = p.pop(0) if p else None
if not ("QUERY_STRING" in os.environ):
return None
if not (".url_param" in self):
self[".url_param"] = perllib.Hash() # empty hash
if re.search(r"=", _str(os.environ.get("QUERY_STRING"))):
pairs = perllib.Array(perllib.split(r"[&;]", _str(os.environ.get("QUERY_STRING"))))
param_v = value_v = None
for _d in pairs:
[param_v, value_v] = perllib.list_of_n(_str(_d).split("=", 2 - 1), 2)
if param_v is None:
continue
param_v = unescape(param_v)
value_v = unescape(value_v)
self[".url_param"].get(_str(param_v)).append(value_v)
else:
keywords_a = perllib.Array(self.parse_keywordlist(os.environ.get("QUERY_STRING")))
if keywords_a:
self[".url_param"]["keywords"] = keywords_a
if name is None:
return self[".url_param"].keys()
if not (self[".url_param"].get(_str(name))):
return perllib.Array() if wantarray else None
return self[".url_param"].get(_str(name)) if wantarray else self[".url_param"][_str(name)][0]
CGI.url_param = lambda *_args, **_kwargs: perllib.tie_call(url_param, _args, _kwargs)
# Read data from a file handle
[docs]def read_from_client(*_args):
perllib.init_out_parameters(_args, 1) # refs: 1
try:
_locals_stack.append(perllib.WARNING)
[self, buff, len_, offset] = perllib.list_of_n(_args, 4)
perllib.WARNING = 0 # prevent a warning
return (
(perllib.method_call(self.r(), "read", buff, len_, offset))
if CGI.MOD_PERL_v
else (
(
perllib.store_out_parameter(
None,
1,
(
buff := (
_s := perllib.read(
sys.stdin,
buff,
perllib.int_(len_),
perllib.int_(offset),
need_len=True,
)
)[0]
),
)
),
_s[1],
)[1]
)
finally:
perllib.WARNING = _locals_stack.pop()
CGI.read_from_client = lambda *_args, **_kwargs: perllib.tie_call(
read_from_client, _args, _kwargs
)
#### Method: delete
# Deletes the named parameter entirely.
####
[docs]def add_parameter(*_args):
[self, param_v] = perllib.list_of_n(_args, 2)
if param_v is None:
return
if not (self["param"].get(_str(param_v)) is not None):
return self.get(".parameters").append(param_v)
CGI.add_parameter = lambda *_args, **_kwargs: perllib.tie_call(add_parameter, _args, _kwargs)
[docs]def parse_params(*_args):
global _d
[self, tosplit] = perllib.list_of_n(_args, 2)
pairs = perllib.Array(perllib.split(r"[&;]", _str(tosplit)))
param_v = value_v = None
for _d in pairs:
[param_v, value_v] = perllib.list_of_n(_str(_d).split("=", 2 - 1), 2)
if param_v is None:
continue
if CGI.NO_UNDEF_PARAMS_v and value_v is None:
continue
if value_v is None:
value_v = ""
param_v = unescape(param_v)
value_v = unescape(value_v)
self.add_parameter(param_v)
self["param"].get(_str(param_v)).append(value_v)
CGI.parse_params = lambda *_args, **_kwargs: perllib.tie_call(parse_params, _args, _kwargs)
########################################
# THESE METHODS ARE MORE OR LESS PRIVATE
# GO TO THE __DATA__ SECTION TO SEE MORE
# PUBLIC METHODS
########################################
# Initialize the query object from the environment.
# If a parameter list is found, this object will be set
# to a hash in which parameter names are keys
# and the values are stored as lists
# If a keyword list is found, this method creates a bogus
# parameter list with the single parameter 'keywords'.
[docs]def init(*_args):
_args = list(_args)
global _d
boundary = None
cmdline_ret = perllib.Hash()
line = None
param_v = None
postOrPut = ""
start = ""
val = None
value_v = None
try:
_locals_stack.append(perllib.INPUT_RECORD_SEPARATOR)
self = _args.pop(0) if _args else None
[query_string_v, meth, content_length, fh, *lines_a] = perllib.list_of_at_least_n(
("", "", "", ""), 4
)
lines_a = perllib.Array(lines_a)
is_xforms = 0
initializer_v = _args.pop(0) if _args else None # for backward compatibility
[perllib.INPUT_RECORD_SEPARATOR] = perllib.list_of_n("\n", 1)
# set autoescaping on by default
self["escape"] = 1
# if we get called more than once, we want to initialize
# ourselves from the original query (which may be gone
# if it was read from STDIN originally.)
if CGI.QUERY_PARAM_a and initializer_v is None:
for name_l in CGI.QUERY_PARAM_a:
val = CGI.QUERY_PARAM_h.get(_str(name_l)) # always an arrayref;
self.param("-name", name_l, "-value", val)
if val is not None and perllib.refs(val) == "ARRAY":
for fh_l in list(
filter(
lambda _d: _d is not None
and perllib.ref_scalar(_d)
and perllib.fileno(_d) is not None,
perllib.make_list(val),
)
):
perllib.seek(fh_l, 0, 0) # reset the filehandle.
self.charset(CGI.QUERY_CHARSET_v)
self[".fieldnames"] = CGI.QUERY_FIELDNAMES_h.copy()
self[".tmpfiles"] = CGI.QUERY_TMPFILES_h.copy()
return
if os.environ.get("REQUEST_METHOD") is not None:
meth = os.environ.get("REQUEST_METHOD")
content_length = (
os.environ.get("CONTENT_LENGTH")
if os.environ.get("CONTENT_LENGTH") is not None
else 0
)
if initializer_v:
fh = to_filehandle(initializer_v)
# set charset to the safe ISO-8859-1
self.charset("ISO-8859-1")
# METHOD
for _ in range(1):
try:
# avoid unreasonably large postings
if (perllib.num(CGI.POST_MAX_v) > 0) and (
perllib.num(content_length) > perllib.num(CGI.POST_MAX_v)
):
# discard the post, unread
self.cgi_error("413 Request entity too large")
break
# Process multipart postings, but only if the initializer is
# not defined.
if (
_str(meth) == "POST"
and os.environ.get("CONTENT_TYPE") is not None
and (re.search(r"^multipart/form-data", _str(os.environ.get("CONTENT_TYPE"))))
and initializer_v is None
):
[boundary] = perllib.list_of_n(
(
_m := re.search(
r"boundary=\"?([^\";,]+)\"?", _str(os.environ.get("CONTENT_TYPE"))
),
_m.groups() if _m else [],
)[1],
1,
)
self.read_multipart(boundary, content_length)
if CGI.APPEND_QUERY_STRING_v:
# Some people want to have their cake and eat it too!
# Set $APPEND_QUERY_STRING = 1 to have the contents of the query string
# APPENDED to the POST data.
if os.environ.get("QUERY_STRING") is not None:
query_string_v = _str(query_string_v) + (
("&" if len(_str(query_string_v)) else "")
+ _str(os.environ.get("QUERY_STRING"))
)
break
# Process XForms postings. We know that we have XForms in the
# following cases:
# method eq 'POST' && content-type eq 'application/xml'
# method eq 'POST' && content-type =~ /multipart\/related.+start=/
# There are more cases, actually, but for now, we don't support other
# methods for XForm posts.
# In a XForm POST, the QUERY_STRING is parsed normally.
# If the content-type is 'application/xml', we just set the param
# XForms:Model (referring to the xml syntax) param containing the
# unparsed XML data.
# In the case of multipart/related we set XForms:Model as above, but
# the other parts are available as uploads with the Content-ID as the
# the key.
# See the URL below for XForms specs on this issue.
# http://www.w3.org/TR/2006/REC-xforms-20060314/slice11.html#submit-options
if _str(meth) == "POST" and os.environ.get("CONTENT_TYPE") is not None:
if _str(os.environ.get("CONTENT_TYPE")) == "application/xml":
[param_v] = perllib.list_of_n("XForms:Model", 1)
[value_v] = perllib.list_of_n("", 1)
self.add_parameter(param_v)
if perllib.num(content_length) > 0:
(
self.read_from_client(value_v, content_length, 0),
(value_v := perllib.fetch_out_parameter(1)),
)[0]
self["param"].get(_str(param_v)).append(value_v)
is_xforms = 1
elif _m := re.search(
r"multipart/related.+boundary=\"?([^\";,]+)\"?.+start=\"?<?([^\">]+)>?\"?",
_str(os.environ.get("CONTENT_TYPE")),
):
[boundary, start] = (_m.group(1), _m.group(2))
[param_v] = perllib.list_of_n("XForms:Model", 1)
self.add_parameter(param_v)
[value_v] = perllib.list_of_n(
self.read_multipart_related(start, boundary, content_length, 0), 1
)
self["param"].get(_str(param_v)).append(value_v)
query_string_v = self._get_query_string_from_env()
is_xforms = 1
# If initializer is defined, then read parameters
# from it.
if not is_xforms and initializer_v is not None:
if perllib.isa(initializer_v, "CGI"):
query_string_v = initializer_v.query_string()
break
if (
perllib.ref_scalar(initializer_v)
and perllib.refs(initializer_v) == "HASH"
):
for _d in sorted(
list(
(
initializer_v if initializer_v is not None else perllib.Hash()
).keys()
)
):
self.param("-name", _d, "-value", initializer_v.get(_d))
break
if fh is not None and (_str(fh) != ""):
while line := perllib.readline_full(fh):
line = line.rstrip("\n")
if re.search(r"^=$", _str(line)):
break
lines_a.append(line)
# massage back into standard format
if re.search(r"=", f"{perllib.LIST_SEPARATOR.join(map(_str,lines_a))}"):
query_string_v = "&".join(map(_str, lines_a))
else:
query_string_v = "+".join(map(_str, lines_a))
break
# last chance -- treat it as a string
if perllib.refs(initializer_v) == "SCALAR":
initializer_v = initializer_v
query_string_v = initializer_v
break
# If method is GET, HEAD or DELETE, fetch the query from
# the environment.
if is_xforms or (_m := re.search(r"^(GET|HEAD|DELETE)$", _str(meth))):
query_string_v = self._get_query_string_from_env()
if is_xforms:
self.param(meth + "DATA", self.param("XForms:Model", wantarray=True))
break
if _str(meth) == "POST" or _str(meth) == "PUT" or _str(meth) == "PATCH":
if perllib.num(content_length) > 0:
if (
(CGI.PUTDATA_UPLOAD_v or self.get(".upload_hook"))
and not is_xforms
and (
_str(meth) == "POST"
or _str(meth) == "PUT"
or _str(meth) == "PATCH"
)
and os.environ.get("CONTENT_TYPE") is not None
and not (
re.search(
r"^application/x-www-form-urlencoded",
_str(os.environ.get("CONTENT_TYPE")),
)
)
and not (
re.search(
r"^multipart/form-data", _str(os.environ.get("CONTENT_TYPE"))
)
)
):
postOrPut = _str(meth) + "DATA" # POSTDATA/PUTDATA
self.read_postdata_putdata(
postOrPut, content_length, os.environ.get("CONTENT_TYPE")
)
meth = "" # to skip xform testing
query_string_v = None
else:
(
self.read_from_client(query_string_v, content_length, 0),
(query_string_v := perllib.fetch_out_parameter(1)),
)[0]
if CGI.APPEND_QUERY_STRING_v:
# Some people want to have their cake and eat it too!
# Set $APPEND_QUERY_STRING = 1 to have the contents of the query string
# APPENDED to the POST data.
if os.environ.get("QUERY_STRING") is not None:
query_string_v = _str(query_string_v) + (
("&" if len(_str(query_string_v)) else "")
+ _str(os.environ.get("QUERY_STRING"))
)
break
# If $meth is not of GET, POST, PUT or HEAD, assume we're
# being debugged offline.
# Check the command line and then the standard input for data.
# We use the shellwords package in order to behave the way that
# UN*X programmers expect.
if CGI.DEBUG_v:
cmdline_ret = read_from_cmdline()
query_string_v = cmdline_ret.get("query_string")
if cmdline_ret.get("subpath") is not None:
self.path_info(cmdline_ret.get("subpath"))
except LoopControl_METHOD as _l:
if _l.args[0] == "break":
break
continue
# YL: Begin Change for XML handler 10/19/2001
if (
not is_xforms
and (_str(meth) == "POST" or _str(meth) == "PUT" or _str(meth) == "PATCH")
and os.environ.get("CONTENT_TYPE") is not None
and not (
re.search(
r"^application/x-www-form-urlencoded", _str(os.environ.get("CONTENT_TYPE"))
)
)
and not (re.search(r"^multipart/form-data", _str(os.environ.get("CONTENT_TYPE"))))
):
[param_v] = perllib.list_of_n(_str(meth) + "DATA", 1)
self.add_parameter(param_v)
self["param"].get(_str(param_v)).append(query_string_v)
query_string_v = None
# YL: End Change for XML handler 10/19/2001
# We now have the query string in hand. We do slightly
# different things for keyword lists and parameter lists.
if query_string_v is not None and len(_str(query_string_v)):
if re.search(r"[&=;]", _str(query_string_v)):
self.parse_params(query_string_v)
else:
self.add_parameter("keywords")
self["param"]["keywords"] = perllib.Array(
[self.parse_keywordlist(query_string_v)]
)
# Special case. Erase everything if there is a field named
# .defaults.
if self.param(".defaults"):
self.delete_all()
# hash containing our defined fieldnames
self[".fieldnames"] = perllib.Hash()
for _d in perllib.flatten([self.param(".cgifields", wantarray=True)]):
self[".fieldnames"][_s0] = perllib.num(self[".fieldnames"].get(_s0 := _str(_d))) + 1
# Clear out our default submission button flag if present
self.delete(".submit")
self.delete(".cgifields")
if initializer_v is None:
return self.save_request()
finally:
perllib.INPUT_RECORD_SEPARATOR = _locals_stack.pop()
CGI.init = lambda *_args, **_kwargs: perllib.tie_call(init, _args, _kwargs)
[docs]def self_or_CGI(*_args):
try:
_locals_stack.append(perllib.WARNING)
perllib.WARNING = 0 # prevent a warning
if (0 < len(_args) and _args[0] is not None) and (
perllib.ref_scalar(_args[0])[0:3] == "CGI" or perllib.isa(_args[0], "CGI")
):
return _args
else:
return perllib.Array([CGI.DefaultClass_v, _args])
finally:
perllib.WARNING = _locals_stack.pop()
CGI.self_or_CGI = lambda *_args, **_kwargs: perllib.tie_call(self_or_CGI, _args, _kwargs)
#### Method: default_dtd
# Set or return the default_dtd global
####
[docs]def default_dtd(*_args):
[self, param_v, param2] = perllib.list_of_n(self_or_CGI(*_args), 3)
if param2 is not None and param_v is not None:
CGI.DEFAULT_DTD_v = perllib.Array([param_v, param2])
elif param_v is not None:
CGI.DEFAULT_DTD_v = param_v
return CGI.DEFAULT_DTD_v
CGI.default_dtd = lambda *_args, **_kwargs: perllib.tie_call(default_dtd, _args, _kwargs)
[docs]def close_upload_files(*_args):
[self, param_v] = perllib.list_of_n(self_or_CGI(*_args), 2)
if param_v is not None:
CGI.CLOSE_UPLOAD_FILES_v = param_v
return CGI.CLOSE_UPLOAD_FILES_v
CGI.close_upload_files = lambda *_args, **_kwargs: perllib.tie_call(
close_upload_files, _args, _kwargs
)
#### Method: nph
# Set or return the NPH global flag
####
[docs]def nph(*_args):
[self, param_v] = perllib.list_of_n(self_or_CGI(*_args), 2)
if param_v is not None:
CGI.NPH_v = param_v
return CGI.NPH_v
CGI.nph = lambda *_args, **_kwargs: perllib.tie_call(nph, _args, _kwargs)
#### Method: nosticky
# Set or return the NOSTICKY global flag
####
[docs]def nosticky(*_args):
[self, param_v] = perllib.list_of_n(self_or_CGI(*_args), 2)
if param_v is not None:
CGI.NOSTICKY_v = param_v
return CGI.NOSTICKY_v
CGI.nosticky = lambda *_args, **_kwargs: perllib.tie_call(nosticky, _args, _kwargs)
[docs]def user_name(*_args):
[self] = perllib.list_of_n(self_or_CGI(*_args), 1)
return self.http("from") or os.environ.get("REMOTE_IDENT") or os.environ.get("REMOTE_USER")
CGI.user_name = lambda *_args, **_kwargs: perllib.tie_call(user_name, _args, _kwargs)
#### Method: https
# Return the value of HTTPS, or
# the value of an HTTPS variable, or
# the list of variables
####
[docs]def https(*_args, wantarray=False):
[self, parameter] = perllib.list_of_n(self_or_CGI(*_args), 2)
if parameter is not None:
parameter = _str(parameter).translate(
str.maketrans("-abcdefghijklmnopqrstuvwxyz", "_ABCDEFGHIJKLMNOPQRSTUVWXYZ")
)
if re.search(rf"^HTTPS(?:_|$)", _str(parameter)):
return os.environ.get(_str(parameter))
return os.environ.get(f"HTTPS_{_bn(parameter)}")
return (
(
list(
filter(
lambda _d: re.search(rf"^HTTPS(?:_|$)", _d),
perllib.make_list(sorted(os.environ.keys())),
)
)
)
if wantarray
else os.environ.get("HTTPS")
)
CGI.https = lambda *_args, **_kwargs: perllib.tie_call(https, _args, _kwargs)
[docs]def http(*_args):
[self, parameter] = perllib.list_of_n(self_or_CGI(*_args), 2)
if parameter is not None:
parameter = _str(parameter).translate(
str.maketrans("-abcdefghijklmnopqrstuvwxyz", "_ABCDEFGHIJKLMNOPQRSTUVWXYZ")
)
if re.search(rf"^HTTP(?:_|$)", _str(parameter)):
return os.environ.get(_str(parameter))
return os.environ.get(f"HTTP_{_bn(parameter)}")
return list(
filter(
lambda _d: re.search(rf"^HTTP(?:_|$)", _d),
perllib.make_list(sorted(os.environ.keys())),
)
)
CGI.http = lambda *_args, **_kwargs: perllib.tie_call(http, _args, _kwargs)
#### Method: virtual_host
# Return the name of the virtual_host, which
# is not always the same as the server
######
[docs]def virtual_host(*_args):
vh = http("x_forwarded_host") or http("host") or server_name()
vh = re.sub(r":\d+$", r"", _str(vh), count=1) # get rid of port number
return vh
CGI.virtual_host = lambda *_args, **_kwargs: perllib.tie_call(virtual_host, _args, _kwargs)
[docs]def url(*_args):
port = None
protocol_v = None
vh = None
[self, *p] = perllib.list_of_at_least_n(self_or_default(*_args, wantarray=True), 1)
p = perllib.Array(p)
[relative, absolute, full, path_info_v, query, base, rewrite] = perllib.list_of_n(
rearrange(
perllib.Array(
[
"RELATIVE",
"ABSOLUTE",
"FULL",
["PATH", "PATH_INFO"],
["QUERY", "QUERY_STRING"],
"BASE",
"REWRITE",
]
),
*p,
),
7,
)
url_v = ""
if base or not (relative or absolute):
full = perllib.num(full) + 1
if rewrite is None:
rewrite = perllib.num(rewrite) + 1
path = self.path_info()
script_name_v = self.script_name()
request_uri_v = self.request_uri() or ""
query_str = (self.query_string()) if query else ""
script_name_v = re.sub(
re.compile(r"\?.*$", re.S), r"", _str(script_name_v), count=1
) # remove query string
request_uri_v = re.sub(
re.compile(r"\?.*$", re.S), r"", _str(request_uri_v), count=1
) # remove query string
request_uri_v = unescape(request_uri_v)
uri = request_uri_v if rewrite and request_uri_v else script_name_v
if os.environ.get("PATH_INFO") is not None:
# IIS sometimes sets PATH_INFO to the same value as SCRIPT_NAME so only sub it out
# if SCRIPT_NAME isn't defined or isn't the same value as PATH_INFO
if os.environ.get("SCRIPT_NAME") is None or _str(os.environ.get("PATH_INFO")) != _str(
os.environ.get("SCRIPT_NAME")
):
def _f2711(_m_):
global _m
_m = _m_
return _m.expand(r"")
uri = re.sub(
re.compile(rf"{perllib.quotemeta(os.environ.get('PATH_INFO',''))}$"),
_f2711,
_str(uri),
count=1,
)
# if we're not IIS then keep to spec, the relevant info is here:
# https://tools.ietf.org/html/rfc3875#section-4.1.13, namely
# "No PATH_INFO segment (see section 4.1.5) is included in the
# SCRIPT_NAME value." (see GH #126, GH #152, GH #176)
if not CGI.IIS_v:
def _f2718(_m_):
global _m
_m = _m_
return _m.expand(r"")
uri = re.sub(
re.compile(rf"{perllib.quotemeta(os.environ.get('PATH_INFO',''))}$"),
_f2718,
_str(uri),
count=1,
)
if full:
protocol_v = self.protocol()
url_v = f"{_bn(protocol_v)}://"
vh = http("x_forwarded_host") or http("host") or ""
vh = re.sub(
r"^.*,\s*", r"", _str(vh), count=1
) # x_forwarded_host may be a comma-separated list (e.g. when the request has
# passed through multiple reverse proxies. Take the last one.
vh = re.sub(
r":\d+$", r"", _str(vh), count=1
) # some clients add the port number (incorrectly). Get rid of it.
url_v = _str(url_v) + _str(vh or server_name())
port = self.virtual_port()
# add the port to the url unless it's the protocol's default port
if not (
(_str(protocol_v).lower() == "http" and perllib.num(port) == 80)
or (_str(protocol_v).lower() == "https" and perllib.num(port) == 443)
):
url_v = _str(url_v) + (":" + _str(port))
if base:
return url_v
url_v = _str(url_v) + _str(uri)
elif relative:
[url_v] = perllib.list_of_n(
(_m := re.search(r"([^/]+)$", _str(uri)), _m.groups() if _m else [])[1], 1
)
elif absolute:
url_v = uri
if path_info_v and path is not None:
url_v = _str(url_v) + _str(path)
if query and _str(query_str) != "":
url_v = _str(url_v) + f"?{_bn(query_str)}"
url_v = url_v or ""
def _f2750(_m_):
global _m
_m = _m_
return perllib.format_("%%%02X", ord(_m.group(1)))
url_v = re.sub(re.compile(r"([^a-zA-Z0-9_.%;&?/\\:+=~-])"), _f2750, _str(url_v), count=0)
return url_v
CGI.url = lambda *_args, **_kwargs: perllib.tie_call(url, _args, _kwargs)
#### Method: cookie
# Set or read a cookie from the specified name.
# Cookie can then be passed to header().
# Usual rules apply to the stickiness of -value.
# Parameters:
# -name -> name for this cookie (optional)
# -value -> value of this cookie (scalar, array or hash)
# -path -> paths for which this cookie is valid (optional)
# -domain -> internet domain in which this cookie is valid (optional)
# -secure -> if true, cookie only passed through secure channel (optional)
# -expires -> expiry date in format Wdy, DD-Mon-YYYY HH:MM:SS GMT (optional)
####
[docs]def referer(*_args):
[self] = perllib.list_of_n(self_or_CGI(*_args), 1)
return self.http("referer")
CGI.referer = lambda *_args, **_kwargs: perllib.tie_call(referer, _args, _kwargs)
#### Method: raw_cookie
# Returns the magic cookies for the session.
# The cookies are not parsed or altered in any way, i.e.
# cookies are returned exactly as given in the HTTP
# headers. If a cookie name is given, only that cookie's
# value is returned, otherwise the entire raw cookie
# is returned.
####
[docs]def raw_cookie(*_args, wantarray=False):
[self, key] = perllib.list_of_n(self_or_CGI(*_args), 2)
import CGI.Cookie as _CGI_Cookie
if key is not None:
if not self.get(".raw_cookies"):
self[".raw_cookies"] = CGI.Cookie.raw_fetch(CGI.Cookie)
if not self.get(".raw_cookies"):
return perllib.Array() if wantarray else None
if not (self[".raw_cookies"].get(_str(key))):
return perllib.Array() if wantarray else None
return self[".raw_cookies"].get(_str(key))
return self.http("cookie") or os.environ.get("COOKIE") or ""
CGI.raw_cookie = lambda *_args, **_kwargs: perllib.tie_call(raw_cookie, _args, _kwargs)
#### Method: user_agent
# If called with no parameters, returns the user agent.
# If called with one parameter, does a pattern match (case
# insensitive) on the user agent.
####
[docs]def user_agent(*_args):
[self, match] = perllib.list_of_n(self_or_CGI(*_args), 2)
user_agent_v = self.http("user_agent")
if not (match is not None and match and user_agent_v):
return user_agent_v
return (_m := re.search(re.compile(rf"{_bn(match)}", re.I), _str(user_agent_v)))
CGI.user_agent = lambda *_args, **_kwargs: perllib.tie_call(user_agent, _args, _kwargs)
[docs]def Accept(*_args):
global _d
[self, search] = perllib.list_of_n(self_or_CGI(*_args), 2)
prefs = perllib.Hash()
type_v = None
pref = None
pat = ""
accept = perllib.Array(
_str(self.http("accept")).split(",")
if self.http("accept") is not None
else perllib.Array()
)
for _d in accept:
[pref] = perllib.list_of_n(
((_m := re.search(r"q=(\d\.\d+|\d+)", _str(_d))), _m.groups() if _m else [])[1], 1
)
[type_v] = perllib.list_of_n(
((_m := re.search(r"(\S+/[^;]+)", _str(_d))), _m.groups() if _m else [])[1], 1
)
if not type_v:
continue
prefs[_str(type_v)] = pref or 1
if not search:
return prefs.keys()
# if a search type is provided, we may need to
# perform a pattern matching operation.
# The MIME types use a glob mechanism, which
# is easily translated into a perl pattern match
# First return the preference for directly supported
# types:
if prefs.get(_str(search)):
return prefs.get(_str(search))
# Didn't get it, so try pattern matching.
for _d in sorted(list(prefs.keys())):
if not (re.search(r"\*", _str(_d))): # not a pattern match
continue
def _f2997(_m_):
global _m
_m = _m_
return _m.expand(r"\\\g<1>")
pat = re.sub(re.compile(r"([^\w*])"), _f2997, _str(_d), count=0) # escape meta characters
pat = re.sub(re.compile(r"\*"), r".*", pat, count=0) # turn it into a pattern
if _m := re.search(_str(pat), _str(search)):
return prefs.get(_str(_d))
CGI.Accept = lambda *_args, **_kwargs: perllib.tie_call(Accept, _args, _kwargs)
CGI.comment = lambda *_args, **_kwargs: perllib.tie_call(comment, _args, _kwargs)
[docs]def HtmlBot(*_args):
[self, *p] = perllib.list_of_at_least_n(self_or_default(*_args, wantarray=True), 1)
p = perllib.Array(p)
return self.end_html(*p)
CGI.HtmlBot = lambda *_args, **_kwargs: perllib.tie_call(HtmlBot, _args, _kwargs)
[docs]def HtmlTop(*_args):
[self, *p] = perllib.list_of_at_least_n(self_or_default(*_args, wantarray=True), 1)
p = perllib.Array(p)
return self.start_html(*p)
CGI.HtmlTop = lambda *_args, **_kwargs: perllib.tie_call(HtmlTop, _args, _kwargs)
CGI.PrintHeader = lambda *_args, **_kwargs: perllib.tie_call(PrintHeader, _args, _kwargs)
#### Method: keywords
# Keywords acts a bit differently. Calling it in a list context
# returns the list of keywords.
# Calling it in a scalar context gives you the size of the list.
####
[docs]def keywords(*_args):
[self, *values_] = perllib.list_of_at_least_n(self_or_default(*_args, wantarray=True), 1)
values_ = perllib.Array(values_)
# If values is provided, then we set it.
if values_:
self["param"]["keywords"] = values_.copy()
result = perllib.Array(
self["param"].get("keywords")
if self["param"].get("keywords") is not None
else perllib.Array()
)
return result
CGI.keywords = lambda *_args, **_kwargs: perllib.tie_call(keywords, _args, _kwargs)
# These are some tie() interfaces for compatibility
# with Steve Brenner's cgi-lib.pl routines
#### Method: import_names
# Import all parameters into the given namespace.
# Assumes namespace 'Q' if not specified
####
[docs]def import_names(*_args):
global _d, param_l
[self, namespace, delete_v] = perllib.list_of_n(self_or_default(*_args, wantarray=True), 3)
if namespace is None:
namespace = "Q"
if perllib.fetch_perl_global(f"{_bn(namespace)}::" + "_h") == builtins.main.__dict__:
raise Die("""Can't import names into "main"\n""")
if delete_v or CGI.MOD_PERL_v or "FCGI_ROLE" in os.environ:
# can anyone find an easier way to do this?
for _d in sorted(list(perllib.fetch_perl_global(f"{_bn(namespace)}::" + "_h").keys())):
try:
_locals_stack.append(CGI.symbol_v)
_locals_stack.append(CGI.symbol_a)
_locals_stack.append(CGI.symbol_h)
CGI.symbol_h = f"{_bn(namespace)}::{_bn(_d)}"
CGI.symbol_v = None
CGI.symbol_a = perllib.Array()
CGI.symbol_h = perllib.Hash()
finally:
CGI.symbol_h = _locals_stack.pop()
CGI.symbol_a = _locals_stack.pop()
CGI.symbol_v = _locals_stack.pop()
param_v = None
value_a = perllib.Array()
var = ""
for param_l in perllib.flatten([self.param(wantarray=True)]):
try:
_locals_stack.append(CGI.symbol_v)
_locals_stack.append(CGI.symbol_a)
_locals_stack.append(CGI.symbol_h)
# protect against silly names
var = perllib.translate(
perllib.maketrans_c(
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", "_"
),
complement=True,
var=_str(param_l),
)
def _f1170(_m_):
global _m
_m = _m_
return _m.expand(r"_")
var = re.sub(re.compile(r"^(?=\d)"), _f1170, var, count=1)
CGI.symbol_h = f"{_bn(namespace)}::{var}"
value_a = perllib.Array(self.param(param_l, wantarray=True))
CGI.symbol_a = value_a.copy()
CGI.symbol_v = value_a[0]
finally:
CGI.symbol_h = _locals_stack.pop()
CGI.symbol_a = _locals_stack.pop()
CGI.symbol_v = _locals_stack.pop()
CGI.import_names = lambda *_args, **_kwargs: perllib.tie_call(import_names, _args, _kwargs)
[docs]def delete(*_args):
global _d
[self, *p] = perllib.list_of_at_least_n(self_or_default(*_args, wantarray=True), 1)
p = perllib.Array(p)
names = perllib.Array(rearrange(perllib.Array(["NAME"]), *p))
to_delete = perllib.Array(CGI.names_v[0] if perllib.refs(names[0]) == "ARRAY" else names)
to_delete_h = perllib.Hash()
for name_l in to_delete:
self["param"].pop(_str(name_l), None)
self[".fieldnames"].pop(_str(name_l), None)
to_delete_h[_s0] = perllib.num(to_delete_h.get(_s0 := _str(name_l))) + 1
perllib.assign_hash(
self,
".parameters",
perllib.Array(
list(
filter(
lambda _d: not _str(_d) in to_delete_h,
perllib.make_list(self.param(wantarray=True)),
)
)
),
)
return
CGI.delete = lambda *_args, **_kwargs: perllib.tie_call(delete, _args, _kwargs)
[docs]def element_tab(*_args):
[self, new_value] = perllib.list_of_n(self_or_default(*_args, wantarray=True), 2)
self[".etab"] = self[".etab"] or 1
if new_value is not None:
self[".etab"] = new_value
tab = perllib.add_element(self, ".etab", 1) - 1
if not (CGI.TABINDEX_v or new_value is not None):
return ""
return f'tabindex="{_bn(tab)}" '
CGI.element_tab = lambda *_args, **_kwargs: perllib.tie_call(element_tab, _args, _kwargs)
#####
# subroutine: read_postdata_putdata
#
# Unless file uploads are disabled
# Reads BODY of POST/PUT request and stuffs it into tempfile
# accessible as param POSTDATA/PUTDATA
#
# Also respects upload_hook
#
# based on subroutine read_multipart_related
#####
[docs]def element_id(*_args):
[self, new_value] = perllib.list_of_n(self_or_default(*_args, wantarray=True), 2)
if new_value is not None:
self[".elid"] = new_value
return perllib.format_("%010d", (perllib.add_element(self, ".elid", 1) - 1))
CGI.element_id = lambda *_args, **_kwargs: perllib.tie_call(element_id, _args, _kwargs)
[docs]def charset(*_args):
[self, charset_v] = perllib.list_of_n(self_or_default(*_args, wantarray=True), 2)
if charset_v is not None:
self[".charset"] = charset_v
return self[".charset"]
CGI.charset = lambda *_args, **_kwargs: perllib.tie_call(charset, _args, _kwargs)
def _tag_func(*_args):
_args = list(_args)
global _d
attr_a = perllib.Array()
result = perllib.Array()
tag = ""
untag = ""
tagname = _args.pop(0) if _args else None
[q, a, *rest] = perllib.list_of_at_least_n(self_or_default(*_args, wantarray=True), 2)
rest = perllib.Array(rest)
[attr] = perllib.list_of_n("", 1)
if perllib.ref_scalar(a) and perllib.refs(a) == "HASH":
attr_a = perllib.Array(make_attributes(a, q.get("escape"), wantarray=True))
if attr_a:
attr = f" {perllib.LIST_SEPARATOR.join(map(_str,attr_a))}"
else:
if a is not None:
rest[0:0] = [a]
tagname = _str(tagname).lower()
if _m := re.search(re.compile(r"start_(\w+)", re.I), _str(tagname)):
return f"<{_m.group(1)}{_bn(attr)}>"
elif _m := re.search(re.compile(r"end_(\w+)", re.I), _str(tagname)):
return f"</{_m.group(1)}>"
else:
if not rest:
return (
f"<{_bn(tagname)}{_bn(attr)} />"
if CGI.XHTML_v
else f"<{_bn(tagname)}{_bn(attr)}>"
)
[tag, untag] = (f"<{_bn(tagname)}{_bn(attr)}>", f"</{_bn(tagname)}>")
result = perllib.Array(
perllib.flatten(
map(
lambda _d: f"{tag}{_bn(_d)}{untag}",
perllib.make_list(
rest[0]
if (perllib.refs(rest[0]) == "ARRAY")
else f"{perllib.LIST_SEPARATOR.join(map(_str,rest))}"
),
)
)
)
return f"{perllib.LIST_SEPARATOR.join(map(_str,result))}"
CGI._tag_func = lambda *_args, **_kwargs: perllib.tie_call(_tag_func, _args, _kwargs)
[docs]def cgi_error(*_args):
[self, err] = perllib.list_of_n(self_or_default(*_args, wantarray=True), 2)
if err is not None:
self[".cgi_error"] = err
return self.get(".cgi_error")
CGI.cgi_error = lambda *_args, **_kwargs: perllib.tie_call(cgi_error, _args, _kwargs)
[docs]def put(*_args):
[self, *p] = perllib.list_of_at_least_n(self_or_default(*_args, wantarray=True), 1)
p = perllib.Array(p)
return self.print_(*p)
CGI.put = lambda *_args, **_kwargs: perllib.tie_call(put, _args, _kwargs)
def _decode_utf8(*_args):
[self, val] = perllib.list_of_n(_args, 2)
if perllib.is_utf8(_str(val)):
return val
else:
return perllib.decode("utf8", _str(val))
CGI._decode_utf8 = lambda *_args, **_kwargs: perllib.tie_call(_decode_utf8, _args, _kwargs)
[docs]def param(*_args, wantarray=False):
global _d
filename = None
line = None
package = None
values_ = perllib.Array()
[self, *p] = perllib.list_of_at_least_n(self_or_default(*_args, wantarray=True), 1)
p = perllib.Array(p)
if not p:
return self.all_parameters(wantarray=wantarray)
# list context can be dangerous so warn:
# http://blog.gerv.net/2014.10/new-class-of-vulnerability-in-perl-web-applications
if wantarray and perllib.num(CGI.LIST_CONTEXT_WARN_v) == 1:
[package, filename, line] = perllib.list_of_n(perllib.caller(), 3)
if _str(package) != "CGI":
CGI.LIST_CONTEXT_WARN_v = perllib.num(CGI.LIST_CONTEXT_WARN_v) + 1 # only warn once
perllib.perl_print(
f"CGI::param called in list context from {_bn(filename)} line {_bn(line)}, this can lead to vulnerabilities. "
+ 'See the warning in "Fetching the value or values of a single named parameter"',
file=sys.stderr,
)
name = None
value_v = None
other = perllib.Array()
# For compatibility between old calling style and use_named_parameters() style,
# we have to special case for a single parameter present.
if len(p) > 1:
[name, value_v, *other] = perllib.list_of_at_least_n(
rearrange(perllib.Array(["NAME", ["DEFAULT", "VALUE", "VALUES"]]), *p), 2
)
other = perllib.Array(other)
values_ = perllib.Array()
if _str(p[0])[0:1] == "-":
values_ = perllib.Array(
(
value_v
if perllib.ref_scalar(value_v) and perllib.refs(value_v) == "ARRAY"
else value_v
)
if value_v is not None
else perllib.Array()
)
else:
for _d in (value_v, other):
if _d is not None:
values_.append(_d)
# If values is provided, then we set it.
if values_ or value_v is not None:
self.add_parameter(name)
self["param"][_str(name)] = values_.copy()
else:
name = p[0]
if not (name is not None and self["param"].get(_str(name))):
return perllib.Array() if wantarray else None
result = perllib.Array(self["param"].get(_str(name)))
if (
CGI.PARAM_UTF8_v
and _str(name) != "PUTDATA"
and _str(name) != "POSTDATA"
and _str(name) != "PATCHDATA"
):
if not perllib.can(Encode, "decode"): # bring in these functions
try:
pass # SKIPPED: require Encode; 1;
_eval_result449 = 1
raise EvalReturn
except EvalReturn:
pass
except Exception:
pass
result = perllib.Array(
perllib.flatten(
map(lambda _d: _d if perllib.ref_scalar(_d) else self._decode_utf8(_d), result)
)
)
return result if wantarray else result[0]
CGI.param = lambda *_args, **_kwargs: perllib.tie_call(param, _args, _kwargs)
[docs]def FETCH(*_args):
if _str(_args[1]) == "CGI":
return _args[0]
if not (0 < len(_args) and _args[0] is not None):
return None
return "\0".join(map(_str, (_args[0].param(_args[1], wantarray=True))))
CGI.FETCH = lambda *_args, **_kwargs: perllib.tie_call(FETCH, _args, _kwargs)
#### Method: param / multi_param
# Returns the value(s)of a named parameter.
# If invoked in a list context, returns the
# entire list. Otherwise returns the first
# member of the list.
# If name is not provided, return a list of all
# the known parameters names available.
# If more than one argument is provided, the
# second and subsequent arguments are used to
# set the value of the parameter.
#
# note that calling param() in list context
# will raise a warning about potential bad
# things, hence the multi_param method
####
[docs]def multi_param(*_args):
# we don't need to set $LIST_CONTEXT_WARN to 0 here
# because param() will check the caller before warning
list_of_params = perllib.Array(param(*_args, wantarray=True))
return list_of_params
CGI.multi_param = lambda *_args, **_kwargs: perllib.tie_call(multi_param, _args, _kwargs)
[docs]def upload_hook(*_args):
_args = list(_args)
self = None
if perllib.ref_scalar(_args[0]) == "CODE":
CGI.Q_v = self = perllib.method_call(CGI.DefaultClass_v, "new", *_args)
else:
self = _args.pop(0) if _args else None
[hook, data_v, use_tempfile] = perllib.list_of_n(_args, 3)
self[".upload_hook"] = hook
self[".upload_data"] = data_v
if use_tempfile is not None:
self["use_tempfile"] = use_tempfile
return self.get("use_tempfile")
CGI.upload_hook = lambda *_args, **_kwargs: perllib.tie_call(upload_hook, _args, _kwargs)
[docs]def r(*_args):
_args = list(_args)
self = _args.pop(0) if _args else None
r_v = self.get(".r")
if _args:
self[".r"] = _args.pop(0) if _args else None
return r_v
CGI.r = lambda *_args, **_kwargs: perllib.tie_call(r, _args, _kwargs)
CGI.expand_tags = lambda *_args, **_kwargs: perllib.tie_call(expand_tags, _args, _kwargs)
#### Method: new
# The new routine. This will check the current environment
# for an existing query string, and initialize itself, if so.
####
def _setup_symbols(*_args):
_args = list(_args)
global _d
self = _args.pop(0) if _args else None
# to avoid reexporting unwanted variables
CGI.EXPORT_h = perllib.Hash()
for _d in _args:
try:
if re.search(r"^[:-]any$", _str(_d)):
perllib.perl_print(
"CGI -any pragma has been REMOVED. You should audit your code for any use "
+ "of none supported / incorrectly spelled tags and remove them",
file=sys.stderr,
)
continue
if re.search(r"^[:-]unique_headers$", _str(_d)):
(
perllib.assign_global(
"CGI", "HEADERS_ONCE_v", perllib.num(CGI.HEADERS_ONCE_v) + 1
)
- 1
), perllib.raise_(LoopControl("continue"))
if re.search(r"^[:-]nph$", _str(_d)):
(
perllib.assign_global("CGI", "NPH_v", perllib.num(CGI.NPH_v) + 1) - 1
), perllib.raise_(LoopControl("continue"))
if re.search(r"^[:-]nosticky$", _str(_d)):
(
perllib.assign_global("CGI", "NOSTICKY_v", perllib.num(CGI.NOSTICKY_v) + 1)
- 1
), perllib.raise_(LoopControl("continue"))
if re.search(r"^[:-]no_?[Dd]ebug$", _str(_d)):
perllib.assign_global("CGI", "DEBUG_v", 0), perllib.raise_(
LoopControl("continue")
)
if re.search(r"^[:-][Dd]ebug$", _str(_d)):
perllib.assign_global("CGI", "DEBUG_v", 2), perllib.raise_(
LoopControl("continue")
)
if re.search(r"^[:-]newstyle_urls$", _str(_d)):
(
perllib.assign_global(
"CGI",
"USE_PARAM_SEMICOLONS_v",
perllib.num(CGI.USE_PARAM_SEMICOLONS_v) + 1,
)
- 1
), perllib.raise_(LoopControl("continue"))
if re.search(r"^[:-](?:putdata_upload|postdata_upload|patchdata_upload)$", _str(_d)):
(
perllib.assign_global(
"CGI", "PUTDATA_UPLOAD_v", perllib.num(CGI.PUTDATA_UPLOAD_v) + 1
)
- 1
), perllib.raise_(LoopControl("continue"))
if re.search(r"^[:-]utf8$", _str(_d)):
(
perllib.assign_global(
"CGI", "PARAM_UTF8_v", perllib.num(CGI.PARAM_UTF8_v) + 1
)
- 1
), perllib.raise_(LoopControl("continue"))
if re.search(r"^[:-]xhtml$", _str(_d)):
(
perllib.assign_global("CGI", "XHTML_v", perllib.num(CGI.XHTML_v) + 1) - 1
), perllib.raise_(LoopControl("continue"))
if re.search(r"^[:-]no_?xhtml$", _str(_d)):
perllib.assign_global("CGI", "XHTML_v", 0), perllib.raise_(
LoopControl("continue")
)
if re.search(r"^[:-]oldstyle_urls$", _str(_d)):
perllib.assign_global("CGI", "USE_PARAM_SEMICOLONS_v", 0), perllib.raise_(
LoopControl("continue")
)
if re.search(r"^[:-]tabindex$", _str(_d)):
(
perllib.assign_global("CGI", "TABINDEX_v", perllib.num(CGI.TABINDEX_v) + 1)
- 1
), perllib.raise_(LoopControl("continue"))
if re.search(r"^[:-]close_upload_files$", _str(_d)):
(
perllib.assign_global(
"CGI", "CLOSE_UPLOAD_FILES_v", perllib.num(CGI.CLOSE_UPLOAD_FILES_v) + 1
)
- 1
), perllib.raise_(LoopControl("continue"))
if re.search(r"^[:-]no_undef_params$", _str(_d)):
(
perllib.assign_global(
"CGI", "NO_UNDEF_PARAMS_v", perllib.num(CGI.NO_UNDEF_PARAMS_v) + 1
)
- 1
), perllib.raise_(LoopControl("continue"))
for _d in expand_tags(_d):
_d = perllib.translate(
perllib.maketrans_c(
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",
"",
delete=True,
),
complement=True,
var=_str(_d),
) # don't allow weird function names
CGI.EXPORT_h[_s0] = perllib.num(CGI.EXPORT_h.get(_s0 := _str(_d))) + 1
except LoopControl as _l:
if _l.args[0] == "break":
break
continue
CGI.SAVED_SYMBOLS_a = _args.copy()
return CGI.SAVED_SYMBOLS_a
CGI._setup_symbols = lambda *_args, **_kwargs: perllib.tie_call(_setup_symbols, _args, _kwargs)
# to import symbols into caller
[docs]def import_(*_args):
_args = list(_args)
self = _args.pop(0) if _args else None
# This causes modules to clash.
CGI.EXPORT_OK_h = perllib.Hash()
CGI.EXPORT_h = perllib.Hash()
perllib.method_call(self, "_setup_symbols", *_args)
[callpack, callfile, callline] = perllib.list_of_n(perllib.caller(), 3)
if _str(callpack) == "CGI::Fast":
# fixes GH #11 (and GH #12 in CGI::Fast since
# sub import was added to CGI::Fast in 9537f90
# so we need to move up a level to export the
# routines to the namespace of whatever is using
# CGI::Fast
[callpack, callfile, callline] = perllib.list_of_n(perllib.caller(1), 3)
# To allow overriding, search through the packages
# Till we find one in which the correct subroutine is defined.
packages = perllib.Array([self, perllib.fetch_perl_global(f"{_bn(self)}::ISA" + "_a")])
try:
_locals_stack.append(CGI.sym_v)
for CGI.sym_v in sorted(list(CGI.EXPORT_h.keys())):
pck = None
def_ = CGI.DefaultClass_v
for pck_l in packages:
if perllib.fetch_perl_global(f"{_bn(pck_l)}::{_bn(CGI.sym_v)}") is not None:
def_ = pck_l
break
perllib.store_perl_global(
f"{_bn(callpack)}::{_bn(CGI.sym_v)}",
perllib.fetch_perl_global(f"{_bn(def_)}::{_bn(CGI.sym_v)}"),
infer_suffix=True,
)
finally:
CGI.sym_v = _locals_stack.pop()
CGI.import_ = import_
def _set_binmode(*_args):
global _d
# rt #57524 - don't set binmode on filehandles if there are
# already none default layers set on them
default_layers = perllib.Hash(
{
"unix": 1,
"perlio": 1,
"stdio": 1,
"crlf": 1,
}
)
for fh_l in (
sys.stdout,
sys.stdin,
sys.stderr,
):
modes = perllib.Array(
list(
filter(
lambda _d: not default_layers.get(_str(_d)),
perllib.make_list(perllib.get_layers(fh_l)),
)
)
)
if not modes:
(
perllib.method_call(CGI.DefaultClass_v, "binmode", fh_l),
(fh_l := perllib.fetch_out_parameter(1)),
)[0]
CGI._set_binmode = lambda *_args, **_kwargs: perllib.tie_call(_set_binmode, _args, _kwargs)
# >>>>> Here are some globals that you might want to adjust <<<<<<
[docs]def initialize_globals(*_args):
# Set this to 1 to generate XTML-compatible output
CGI.XHTML_v = 1
# Change this to the preferred DTD to print in start_html()
# or use default_dtd('text of DTD to use');
CGI.DEFAULT_DTD_v = perllib.Array(
["-//W3C//DTD HTML 4.01 Transitional//EN", "http://www.w3.org/TR/html4/loose.dtd"]
)
# Set this to 1 to enable NOSTICKY scripts
# or:
# 1) use CGI '-nosticky';
# 2) $CGI::NOSTICKY = 1;
CGI.NOSTICKY_v = 0
# Set this to 1 to enable NPH scripts
# or:
# 1) use CGI qw(-nph)
# 2) CGI::nph(1)
# 3) print header(-nph=>1)
CGI.NPH_v = 0
# Set this to 1 to enable debugging from @ARGV
# Set to 2 to enable debugging from STDIN
CGI.DEBUG_v = 1
# Set this to 1 to generate automatic tab indexes
CGI.TABINDEX_v = 0
# Set this to 1 to cause files uploaded in multipart documents
# to be closed, instead of caching the file handle
# or:
# 1) use CGI qw(:close_upload_files)
# 2) $CGI::close_upload_files(1);
# Uploads with many files run out of file handles.
# Also, for performance, since the file is already on disk,
# it can just be renamed, instead of read and written.
CGI.CLOSE_UPLOAD_FILES_v = 0
# Automatically determined -- don't change
CGI.EBCDIC_v = 0
# Change this to 1 to suppress redundant HTTP headers
CGI.HEADERS_ONCE_v = 0
# separate the name=value pairs by semicolons rather than ampersands
CGI.USE_PARAM_SEMICOLONS_v = 1
# Do not include undefined params parsed from query string
# use CGI qw(-no_undef_params);
CGI.NO_UNDEF_PARAMS_v = 0
# return everything as utf-8
CGI.PARAM_UTF8_v = 0
# make param('PUTDATA') act like file upload
CGI.PUTDATA_UPLOAD_v = 0
# Add QUERY_STRING to POST request
CGI.APPEND_QUERY_STRING_v = 0
# Other globals that you shouldn't worry about.
CGI.Q_v = None
CGI.BEEN_THERE_v = 0
CGI.DTD_PUBLIC_IDENTIFIER_v = ""
CGI.QUERY_PARAM_a = perllib.Array()
CGI.QUERY_PARAM_h = perllib.Hash()
CGI.EXPORT_h = perllib.Hash()
CGI.QUERY_CHARSET_v = None
CGI.QUERY_FIELDNAMES_h = perllib.Hash()
CGI.QUERY_TMPFILES_h = perllib.Hash()
# prevent complaints by mod_perl
return 1
CGI.initialize_globals = lambda *_args, **_kwargs: perllib.tie_call(
initialize_globals, _args, _kwargs
)
# ------------------ START OF THE LIBRARY ------------
# make mod_perlhappy
def _reset_globals(*_args):
return initialize_globals()
CGI._reset_globals = lambda *_args, **_kwargs: perllib.tie_call(_reset_globals, _args, _kwargs)
def new(*_args):
old = None
r_v = None
[package, interface, boundary, length] = perllib.list_of_n(_args, 4)
CGI.MultipartBuffer.FILLUNIT_v = CGI.MultipartBuffer.INITIAL_FILLUNIT_v
(
perllib.method_call(CGI.DefaultClass_v, "binmode", CGI.MultipartBuffer.IN_v),
perllib.assign_global("CGI.MultipartBuffer", "IN_v", perllib.fetch_out_parameter(1)),
)[
0
] # if $CGI::needs_binmode; # just do it always
# If the user types garbage into the file upload field,
# then Netscape passes NOTHING to the server (not good).
# We may hang on this read in that case. So we implement
# a read timeout. If nothing is ready to read
# by then, we return.
# Netscape seems to be a little bit unreliable
# about providing boundary strings.
boundary_read = 0
if boundary:
# Under the MIME spec, the boundary consists of the
# characters "--" PLUS the Boundary string
# BUG: IE 3.01 on the Macintosh uses just the boundary -- not
# the two extra hyphens. We do a special case here on the user-agent!!!!
if not CGI.user_agent("MSIE\s+3\.0[12];\s*Mac|DreamPassport"):
boundary = f"--{_bn(boundary)}"
else:
# otherwise we find it ourselves
old = None
[old, perllib.INPUT_RECORD_SEPARATOR] = (
perllib.INPUT_RECORD_SEPARATOR,
CGI.MultipartBuffer.CRLF_v,
) # read a CRLF-delimited line
boundary = perllib.readline_full(
sys.stdin
) # BUG: This won't work correctly under mod_perl
length = perllib.num(length) - len(_str(boundary))
boundary = boundary.rstrip("\n") # remove the CRLF
perllib.INPUT_RECORD_SEPARATOR = old # restore old line separator
boundary_read += 1
self = perllib.Hash(
{
"LENGTH": length,
"CHUNKED": not length,
"BOUNDARY": boundary,
"INTERFACE": interface,
"BUFFER": "",
}
)
if len(_str(boundary)) > perllib.num(CGI.MultipartBuffer.FILLUNIT_v):
CGI.MultipartBuffer.FILLUNIT_v = len(_str(boundary))
retval = perllib.bless(self, perllib.ref_scalar(package) or package)
# Read the preamble and the topmost (boundary) line plus the CRLF.
if not boundary_read:
while self.read(0):
pass
if self.eof():
raise Die("Malformed multipart POST: data truncated\n")
return retval
CGI.MultipartBuffer.new = types.MethodType(new, CGI.MultipartBuffer)
CGI.read_multipart_related = lambda *_args, **_kwargs: perllib.tie_call(
read_multipart_related, _args, _kwargs
)
[docs]def read_multipart(*_args):
global CRLF_v, _d
value_v = None
[self, boundary, length] = perllib.list_of_n(_args, 3)
[buffer] = perllib.list_of_n(self.new_MultipartBuffer(boundary, length), 1)
if not buffer:
return
header_h = perllib.Hash()
body = None
filenumber = 0
while not buffer.eof():
header_h = perllib.Hash(buffer.readHeader(wantarray=True))
if not header_h:
self.cgi_error("400 Bad request (malformed multipart POST)")
return
header_h["Content-Disposition"] = (
header_h["Content-Disposition"] or ""
) # quench uninit variable warning
param_v = _mp_value_parse(header_h.get("Content-Disposition"), "name")
param_v = _str(param_v) + _str(CGI.TAINTED_v)
# See RFC 1867, 2183, 2045
# NB: File content will be loaded into memory should
# content-disposition parsing fail.
[filename] = perllib.list_of_n(
(
_m := re.search(
re.compile(r""" filename=(("[^"]*")|([a-z\d!#'\*\+,\.^_`\{\}\|~]*))""", re.I),
_str(header_h.get("Content-Disposition")),
),
_m.groups() if _m else [],
)[1],
1,
)
filename = filename or "" # quench uninit variable warning
def _f3367(_m_):
global _m
_m = _m_
return _m.expand(r"\g<1>")
filename = re.sub(re.compile(r'^"([^"]*)"$'), _f3367, _str(filename), count=1)
# Test for Opera's multiple upload feature
[multipart] = perllib.list_of_n(
1
if (
header_h.get("Content-Type") is not None
and (re.search(r"multipart/mixed", _str(header_h.get("Content-Type"))))
)
else 0,
1,
)
# add this parameter to our list
self.add_parameter(param_v)
# If no filename specified, then just read the data and assign it
# to our parameter list.
if (filename is None or _str(filename) == "") and not multipart:
[value_v] = perllib.list_of_n(buffer.readBody(), 1)
value_v = _str(value_v) + _str(CGI.TAINTED_v)
self["param"].get(_str(param_v)).append(value_v)
continue
# UPLOADS
for _ in range(1):
try:
_locals_stack.append(perllib.OUTPUT_RECORD_SEPARATOR)
# If we get here, then we are dealing with a potentially large
# uploaded form. Save the data to a temporary file, then open
# the file for reading.
# skip the file if uploads disabled
if CGI.DISABLE_UPLOADS_v:
while perllib.assign_global("CGI", "data_v", buffer.read()) is not None:
pass
break
# set the filename to some recognizable value
if (filename is None or _str(filename) == "") and multipart:
filename = "multipart/mixed"
tmp_dir = (
(
os.environ.get("TEMP")
or os.environ.get("TMP")
or (
(_str(os.environ.get("WINDIR")) + _str(CGI.SL_v) + "TEMP")
if os.environ.get("WINDIR")
else None
)
)
if _str(CGI.OS_v) == "WINDOWS"
else None
) # File::Temp defaults to TMPDIR
import CGI.File.Temp as _CGI_File_Temp
filehandle = CGI.File.Temp.new(
"UNLINK",
CGI.UNLINK_TMP_FILES_v,
"DIR",
tmp_dir,
)
filehandle._mp_filename(filename)
if CGI.needs_binmode_v and perllib.fileno(filehandle) is not None:
(
perllib.method_call(CGI.DefaultClass_v, "binmode", filehandle),
(filehandle := perllib.fetch_out_parameter(1)),
)[0]
# if this is an multipart/mixed attachment, save the header
# together with the body for later parsing with an external
# MIME parser module
if multipart:
for _d in sorted(list(header_h.keys())):
perllib.perl_print(
f"{_bn(_d)}: {header_h.get(_str(_d),'')}{_bn(CGI.CRLF_v)}",
end="",
file=filehandle,
)
perllib.perl_print(f"{_bn(CGI.CRLF_v)}", end="", file=filehandle)
data_v = None
[perllib.OUTPUT_RECORD_SEPARATOR] = perllib.list_of_n("", 1)
totalbytes = 0
while (data_v := buffer.read()) is not None:
if self.get(".upload_hook") is not None:
totalbytes += len(_str(data_v))
perllib.get_subref(self.get(".upload_hook"))(
filename, data_v, totalbytes, self.get(".upload_data")
)
if self.get("use_tempfile"):
perllib.perl_print(data_v, end="", file=filehandle)
# back up to beginning of file
perllib.seek(filehandle, 0, 0)
## Close the filehandle if requested this allows a multipart MIME
## upload to contain many files, and we won't die due to too many
## open file handles. The user can access the files using the hash
## below.
if CGI.CLOSE_UPLOAD_FILES_v:
perllib.close_(filehandle)
if CGI.needs_binmode_v:
(
perllib.method_call(CGI.DefaultClass_v, "binmode", filehandle),
(filehandle := perllib.fetch_out_parameter(1)),
)[0]
# Save some information about the uploaded file where we can get
# at it later.
# Use the typeglob + filename as the key, as this is guaranteed to be
# unique for each filehandle. Don't use the file descriptor as
# this will be re-used for each filehandle if the
# close_upload_files feature is used.
self[".tmpfiles"][_str(filehandle) + _str(filehandle)] = perllib.Hash(
{
"hndl": filehandle,
"name": filehandle.filename(),
"info": header_h.copy(),
}
)
self["param"].get(_str(param_v)).append(filehandle)
except LoopControl_UPLOADS as _l:
if _l.args[0] == "break":
break
continue
finally:
perllib.OUTPUT_RECORD_SEPARATOR = _locals_stack.pop()
CGI.read_multipart = lambda *_args, **_kwargs: perllib.tie_call(read_multipart, _args, _kwargs)
[docs]def cookie(*_args, wantarray=False):
[self, *p] = perllib.list_of_at_least_n(self_or_default(*_args, wantarray=True), 1)
p = perllib.Array(p)
[
name,
value_v,
path,
domain,
secure,
expires_v,
httponly,
max_age,
samesite,
] = perllib.list_of_n(
rearrange(
perllib.Array(
[
"NAME",
["VALUE", "VALUES"],
"PATH",
"DOMAIN",
"SECURE",
"EXPIRES",
"HTTPONLY",
"MAX-AGE",
"SAMESITE",
]
),
*p,
),
9,
)
import CGI.Cookie as _CGI_Cookie
# if no value is supplied, then we retrieve the
# value of the cookie, if any. For efficiency, we cache the parsed
# cookies in our state variables.
if value_v is None:
if not (CGI.COOKIE_CACHE_v and ".cookies" in self):
self[".cookies"] = CGI.Cookie.fetch(CGI.Cookie)
# If no name is supplied, then retrieve the names of all our cookies.
if not self.get(".cookies"):
return perllib.Array() if wantarray else None
if not name:
return self[".cookies"].keys()
if not (self[".cookies"].get(_str(name))):
return perllib.Array() if wantarray else None
if name is not None and _str(name) != "":
return perllib.method_call(self[".cookies"].get(_str(name)), "value")
# If we get here, we're creating a new cookie
if not (name is not None and _str(name) != ""): # this is an error
return None
param_a = perllib.Array()
param_a.extend(perllib.make_list("-name", name))
param_a.extend(perllib.make_list("-value", value_v))
if domain:
param_a.extend(perllib.make_list("-domain", domain))
if path:
param_a.extend(perllib.make_list("-path", path))
if expires_v:
param_a.extend(perllib.make_list("-expires", expires_v))
if secure:
param_a.extend(perllib.make_list("-secure", secure))
if httponly:
param_a.extend(perllib.make_list("-httponly", httponly))
if max_age:
param_a.extend(perllib.make_list("-max-age", max_age))
if samesite:
param_a.extend(perllib.make_list("-samesite", samesite))
return CGI.Cookie.new(*param_a)
CGI.cookie = lambda *_args, **_kwargs: perllib.tie_call(cookie, _args, _kwargs)
[docs]def TIEHASH(*_args):
_args = list(_args)
class_ = _args.pop(0) if _args else None
arg = _args[0]
if perllib.ref_scalar(arg) and perllib.isa(arg, "CGI"):
return perllib.add_tie_methods(arg)
return perllib.add_tie_methods(
perllib.assign_global("CGI", "Q_v", CGI.Q_v or class_.new(*_args))
)
CGI.TIEHASH = types.MethodType(TIEHASH, CGI)
# These are some tie() interfaces for compatibility
# with Steve Brenner's cgi-lib.pl routines
[docs]def ReadParse(*_args):
pkg = perllib.Array()
try:
_locals_stack.append(CGI.in_h)
CGI.in_h = perllib.Hash()
CGI.in_ = None
if _args:
CGI.in_ = _args[0]
else:
pkg = perllib.caller_s()
CGI.in_ = perllib.fetch_perl_global(f"{_bn(pkg)}::in")
CGI.in_h = CGI.TIEHASH()
return len(CGI.in_h.keys())
finally:
CGI.in_h = _locals_stack.pop()
CGI.ReadParse = lambda *_args, **_kwargs: perllib.tie_call(ReadParse, _args, _kwargs)
[docs]def Vars(*_args, wantarray=False):
_args = list(_args)
q = _args.pop(0) if _args else None
in_h = None
in_h = CGI.TIEHASH(q)
if wantarray:
return in_h
return in_h
CGI.Vars = lambda *_args, **_kwargs: perllib.tie_call(Vars, _args, _kwargs)
[docs]def new_MultipartBuffer(*_args):
[self, boundary, length] = perllib.list_of_n(_args, 3)
return CGI.MultipartBuffer.new(self, boundary, length)
CGI.new_MultipartBuffer = lambda *_args, **_kwargs: perllib.tie_call(
new_MultipartBuffer, _args, _kwargs
)
[docs]def read_postdata_putdata(*_args):
buf = ""
len_ = None
read_v = None
unit = ""
[self, postOrPut, content_length, content_type_v] = perllib.list_of_n(_args, 4)
header_h = perllib.Hash(
{
"Content-Type": content_type_v,
}
)
param_v = postOrPut
# add this parameter to our list
self.add_parameter(param_v)
# UPLOADS
for _ in range(1):
try:
_locals_stack.append(perllib.OUTPUT_RECORD_SEPARATOR)
# If we get here, then we are dealing with a potentially large
# uploaded form. Save the data to a temporary file, then open
# the file for reading.
# skip the file if uploads disabled
if CGI.DISABLE_UPLOADS_v:
buf = None
unit = CGI.MultipartBuffer.INITIAL_FILLUNIT_v
len_ = content_length
while perllib.num(len_) > 0:
read_v = (
self.read_from_client(buf, unit, 0),
(buf := perllib.fetch_out_parameter(1)),
)[0]
len_ = perllib.num(len_) - perllib.num(read_v)
break
# SHOULD PROBABLY SKIP THIS IF NOT $self->{'use_tempfile'}
# BUT THE REST OF CGI.PM DOESN'T, SO WHATEVER
tmp_dir = (
(
os.environ.get("TEMP")
or os.environ.get("TMP")
or (
(_str(os.environ.get("WINDIR")) + _str(CGI.SL_v) + "TEMP")
if os.environ.get("WINDIR")
else None
)
)
if _str(CGI.OS_v) == "WINDOWS"
else None
) # File::Temp defaults to TMPDIR
import CGI.File.Temp as _CGI_File_Temp
filehandle = CGI.File.Temp.new(
"UNLINK",
CGI.UNLINK_TMP_FILES_v,
"DIR",
tmp_dir,
)
filehandle._mp_filename(postOrPut)
if CGI.needs_binmode_v and perllib.fileno(filehandle) is not None:
(
perllib.method_call(CGI.DefaultClass_v, "binmode", filehandle),
(filehandle := perllib.fetch_out_parameter(1)),
)[0]
data_v = None
[perllib.OUTPUT_RECORD_SEPARATOR] = perllib.list_of_n("", 1)
totalbytes = 0
unit = CGI.MultipartBuffer.INITIAL_FILLUNIT_v
len_ = content_length
unit = len_
ZERO_LOOP_COUNTER = 0
while perllib.num(len_) > 0:
bytesRead = (
self.read_from_client(data_v, unit, 0),
(data_v := perllib.fetch_out_parameter(1)),
)[0]
len_ = perllib.num(len_) - perllib.num(bytesRead)
# An apparent bug in the Apache server causes the read()
# to return zero bytes repeatedly without blocking if the
# remote user aborts during a file transfer. I don't know how
# they manage this, but the workaround is to abort if we get
# more than SPIN_LOOP_MAX consecutive zero reads.
if perllib.num(bytesRead) <= 0:
if ((ZERO_LOOP_COUNTER := ZERO_LOOP_COUNTER + 1) - 1) >= perllib.num(
CGI.SPIN_LOOP_MAX_v
):
raise Die(
"CGI.pm: Server closed socket during read_postdata_putdata (client aborted?).\n"
)
else:
ZERO_LOOP_COUNTER = 0
if self.get(".upload_hook") is not None:
totalbytes += len(_str(data_v))
perllib.get_subref(self[".upload_hook"])(
param_v, data_v, totalbytes, self.get(".upload_data")
)
if self.get("use_tempfile"):
perllib.perl_print(data_v, end="", file=filehandle)
data_v = None
# back up to beginning of file
perllib.seek(filehandle, 0, 0)
## Close the filehandle if requested this allows a multipart MIME
## upload to contain many files, and we won't die due to too many
## open file handles. The user can access the files using the hash
## below.
if CGI.CLOSE_UPLOAD_FILES_v:
perllib.close_(filehandle)
if CGI.needs_binmode_v:
(
perllib.method_call(CGI.DefaultClass_v, "binmode", filehandle),
(filehandle := perllib.fetch_out_parameter(1)),
)[0]
# Save some information about the uploaded file where we can get
# at it later.
# Use the typeglob + filename as the key, as this is guaranteed to be
# unique for each filehandle. Don't use the file descriptor as
# this will be re-used for each filehandle if the
# close_upload_files feature is used.
self[".tmpfiles"][_str(filehandle) + _str(filehandle)] = perllib.Hash(
{
"hndl": filehandle,
"name": filehandle.filename(),
"info": header_h.copy(),
}
)
self["param"].get(_str(param_v)).append(filehandle)
except LoopControl_UPLOADS as _l:
if _l.args[0] == "break":
break
continue
finally:
perllib.OUTPUT_RECORD_SEPARATOR = _locals_stack.pop()
return
CGI.read_postdata_putdata = lambda *_args, **_kwargs: perllib.tie_call(
read_postdata_putdata, _args, _kwargs
)
CGI.APPEND_QUERY_STRING_v = perllib.init_global("CGI", "APPEND_QUERY_STRING_v", "")
CGI.CGI_v = perllib.init_global("CGI", "CGI_v", "")
CGI.CLOSE_UPLOAD_FILES_v = perllib.init_global("CGI", "CLOSE_UPLOAD_FILES_v", None)
CGI.COOKIE_CACHE_v = perllib.init_global("CGI", "COOKIE_CACHE_v", 0)
CGI.CRLF_v = perllib.init_global("CGI", "CRLF_v", None)
CGI.DEBUG_v = perllib.init_global("CGI", "DEBUG_v", None)
CGI.DEFAULT_DTD_v = perllib.init_global("CGI", "DEFAULT_DTD_v", None)
CGI.DISABLE_UPLOADS_v = perllib.init_global("CGI", "DISABLE_UPLOADS_v", None)
CGI.DTD_PUBLIC_IDENTIFIER_v = perllib.init_global("CGI", "DTD_PUBLIC_IDENTIFIER_v", None)
CGI.DefaultClass_v = perllib.init_global("CGI", "DefaultClass_v", None)
CGI.EBCDIC_v = perllib.init_global("CGI", "EBCDIC_v", None)
CGI.ENCODE_ENTITIES_v = perllib.init_global("CGI", "ENCODE_ENTITIES_v", "")
CGI.EXPORT_OK_h = perllib.init_global("CGI", "EXPORT_OK_h", perllib.Hash())
CGI.EXPORT_TAGS_h = perllib.init_global("CGI", "EXPORT_TAGS_h", perllib.Hash())
CGI.EXPORT_h = perllib.init_global("CGI", "EXPORT_h", perllib.Hash())
CGI.HEADERS_ONCE_v = perllib.init_global("CGI", "HEADERS_ONCE_v", None)
CGI.IIS_v = perllib.init_global("CGI", "IIS_v", None)
CGI.LIST_CONTEXT_WARN_v = perllib.init_global("CGI", "LIST_CONTEXT_WARN_v", 0)
CGI.MOD_PERL_v = perllib.init_global("CGI", "MOD_PERL_v", None)
CGI.MultipartBuffer.CRLF_v = perllib.init_global("CGI.MultipartBuffer", "CRLF_v", "")
CGI.MultipartBuffer.FILLUNIT_v = perllib.init_global("CGI.MultipartBuffer", "FILLUNIT_v", "")
CGI.MultipartBuffer.INITIAL_FILLUNIT_v = perllib.init_global(
"CGI.MultipartBuffer", "INITIAL_FILLUNIT_v", None
)
CGI.MultipartBuffer.IN_v = perllib.init_global("CGI.MultipartBuffer", "IN_v", "")
CGI.MultipartBuffer.SPIN_LOOP_MAX_v = perllib.init_global(
"CGI.MultipartBuffer", "SPIN_LOOP_MAX_v", 0
)
CGI.MultipartBuffer._DEBUG_v = perllib.init_global("CGI.MultipartBuffer", "_DEBUG_v", None)
CGI.NOSTICKY_v = perllib.init_global("CGI", "NOSTICKY_v", None)
CGI.NO_UNDEF_PARAMS_v = perllib.init_global("CGI", "NO_UNDEF_PARAMS_v", None)
CGI.NPH_v = perllib.init_global("CGI", "NPH_v", None)
CGI.OS_v = perllib.init_global("CGI", "OS_v", None)
CGI.PARAM_UTF8_v = perllib.init_global("CGI", "PARAM_UTF8_v", None)
CGI.PERLEX_v = perllib.init_global("CGI", "PERLEX_v", None)
CGI.POST_MAX_v = perllib.init_global("CGI", "POST_MAX_v", 0)
CGI.PUTDATA_UPLOAD_v = perllib.init_global("CGI", "PUTDATA_UPLOAD_v", None)
CGI.QUERY_CHARSET_v = perllib.init_global("CGI", "QUERY_CHARSET_v", None)
CGI.QUERY_FIELDNAMES_h = perllib.init_global("CGI", "QUERY_FIELDNAMES_h", perllib.Hash())
CGI.QUERY_PARAM_a = perllib.init_global("CGI", "QUERY_PARAM_a", perllib.Array())
CGI.QUERY_PARAM_h = perllib.init_global("CGI", "QUERY_PARAM_h", perllib.Hash())
CGI.QUERY_TMPFILES_h = perllib.init_global("CGI", "QUERY_TMPFILES_h", perllib.Hash())
CGI.Q_v = perllib.init_global("CGI", "Q_v", None)
CGI.SAVED_SYMBOLS_a = perllib.init_global("CGI", "SAVED_SYMBOLS_a", perllib.Array())
CGI.SL_v = perllib.init_global("CGI", "SL_v", perllib.Hash())
CGI.SPIN_LOOP_MAX_v = perllib.init_global("CGI", "SPIN_LOOP_MAX_v", "")
CGI.TABINDEX_v = perllib.init_global("CGI", "TABINDEX_v", None)
CGI.TAINTED_v = perllib.init_global("CGI", "TAINTED_v", None)
CGI.UNLINK_TMP_FILES_v = perllib.init_global("CGI", "UNLINK_TMP_FILES_v", None)
CGI.USE_PARAM_SEMICOLONS_v = perllib.init_global("CGI", "USE_PARAM_SEMICOLONS_v", None)
CGI.VERSION_v = perllib.init_global("CGI", "VERSION_v", "")
CGI.XHTML_v = perllib.init_global("CGI", "XHTML_v", None)
CGI._XHTML_DTD_v = perllib.init_global("CGI", "_XHTML_DTD_v", "")
CGI.data_v = perllib.init_global("CGI", "data_v", None)
CGI.in_h = perllib.init_global("CGI", "in_h", perllib.Hash())
CGI.lines_a = perllib.init_global("CGI", "lines_a", perllib.Array())
CGI.names_v = perllib.init_global("CGI", "names_v", perllib.Array())
CGI.needs_binmode_v = perllib.init_global("CGI", "needs_binmode_v", perllib.Array())
CGI.novals_v = perllib.init_global("CGI", "novals_v", "")
CGI.selected_v = perllib.init_global("CGI", "selected_v", None)
CGI.sym_v = perllib.init_global("CGI", "sym_v", None)
CGI.symbol = perllib.init_global("CGI", "symbol", None)
CGI.symbol_a = perllib.init_global("CGI", "symbol_a", perllib.Array())
CGI.symbol_h = perllib.init_global("CGI", "symbol_h", perllib.Hash())
CGI.symbol_v = perllib.init_global("CGI", "symbol_v", "")
CGI.type_v = perllib.init_global("CGI", "type_v", None)
CRLF_v = ""
MultipartBuffer.CRLF_v = perllib.init_global("MultipartBuffer", "CRLF_v", 0)
MultipartBuffer.INITIAL_FILLUNIT_v = perllib.init_global(
"MultipartBuffer", "INITIAL_FILLUNIT_v", 0
)
MultipartBuffer.SPIN_LOOP_MAX_v = perllib.init_global("MultipartBuffer", "SPIN_LOOP_MAX_v", 0)
MultipartBuffer.TIMEOUT_v = perllib.init_global("MultipartBuffer", "TIMEOUT_v", 0)
_args = perllib.Array()
_d = None
src_l = ""
sym_v = None
sys.argv = perllib.Array(sys.argv)
builtins.__PACKAGE__ = "CGI"
# SKIPPED: require 5.008001;
# SKIPPED: use Carp 'croak';
appease_cpants_kwalitee = """
use strict;
use warnings;
#"""
CGI.VERSION_v = "4.54"
CGI.ascii2ebcdic = ascii2ebcdic
CGI.ebcdic2ascii = ebcdic2ascii
CGI.escape = escape
CGI.expires = expires
CGI.make_attributes = make_attributes
CGI.rearrange = rearrange
CGI.rearrange_header = rearrange_header
CGI.unescape = unescape
CGI._XHTML_DTD_v = perllib.Array(
[
"-//W3C//DTD XHTML 1.0 Transitional//EN",
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd",
]
)
for _ in range(1):
try:
_locals_stack.append(perllib.WARNING)
perllib.WARNING = 0
CGI.TAINTED_v = f"{sys.argv[0]}{sys.executable}"[0:0]
finally:
perllib.WARNING = _locals_stack.pop()
CGI.MOD_PERL_v = 0 # no mod_perl by default
# global settings
CGI.POST_MAX_v = -1 # no limit to uploaded files
CGI.DISABLE_UPLOADS_v = 0
CGI.UNLINK_TMP_FILES_v = 1
CGI.LIST_CONTEXT_WARN_v = 1
CGI.ENCODE_ENTITIES_v = """&<>"'"""
CGI.ALLOW_DELETE_CONTENT_v = 0
CGI.COOKIE_CACHE_v = 0 # backcompat: cache was broken for years
CGI.SAVED_SYMBOLS_a = perllib.Array()
initialize_globals()
# FIGURE OUT THE OS WE'RE RUNNING UNDER
# Some systems support the $^O variable. If not
# available then require() the Config library
if not CGI.OS_v:
if not (perllib.assign_global("CGI", "OS_v", perllib.os_name())):
import Config as _Config
CGI.OS_v = Config.Config_h.get("osname")
if re.search(re.compile(r"^MSWin", re.I), _str(CGI.OS_v)):
CGI.OS_v = "WINDOWS"
elif re.search(re.compile(r"^VMS", re.I), _str(CGI.OS_v)):
CGI.OS_v = "VMS"
elif re.search(re.compile(r"^dos", re.I), _str(CGI.OS_v)):
CGI.OS_v = "DOS"
elif re.search(re.compile(r"^MacOS", re.I), _str(CGI.OS_v)):
CGI.OS_v = "MACINTOSH"
elif re.search(re.compile(r"^os2", re.I), _str(CGI.OS_v)):
CGI.OS_v = "OS2"
elif re.search(re.compile(r"^epoc", re.I), _str(CGI.OS_v)):
CGI.OS_v = "EPOC"
elif re.search(re.compile(r"^cygwin", re.I), _str(CGI.OS_v)):
CGI.OS_v = "CYGWIN"
elif re.search(re.compile(r"^NetWare", re.I), _str(CGI.OS_v)):
CGI.OS_v = "NETWARE"
else:
CGI.OS_v = "UNIX"
# Some OS logic. Binary mode enabled on DOS, NT and VMS
CGI.needs_binmode_v = (
_m := re.search(r"^(WINDOWS|DOS|OS2|MSWin|CYGWIN|NETWARE)", _str(CGI.OS_v)),
_pb(_m),
)[1]
# This is the default class for the CGI object to use when all else fails.
if CGI.DefaultClass_v is None:
CGI.DefaultClass_v = "CGI"
# The path separator is a slash, backslash or semicolon, depending
# on the platform.
CGI.SL_v = {
"UNIX": "/",
"OS2": "\\",
"EPOC": "/",
"CYGWIN": "/",
"NETWARE": "/",
"WINDOWS": "\\",
"DOS": "\\",
"MACINTOSH": ":",
"VMS": "/",
}[CGI.OS_v]
# This no longer seems to be necessary
# Turn on NPH scripts by default when running under IIS server!
# $NPH++ if defined($ENV{'SERVER_SOFTWARE'}) && $ENV{'SERVER_SOFTWARE'}=~/IIS/;
if os.environ.get("SERVER_SOFTWARE") is not None and (
re.search(r"IIS", _str(os.environ.get("SERVER_SOFTWARE")))
):
CGI.IIS_v = perllib.num(CGI.IIS_v) + 1
# Turn on special checking for ActiveState's PerlEx
if os.environ.get("GATEWAY_INTERFACE") is not None and (
re.search(r"^CGI-PerlEx", _str(os.environ.get("GATEWAY_INTERFACE")))
):
CGI.PERLEX_v = perllib.num(CGI.PERLEX_v) + 1
# Turn on special checking for Doug MacEachern's modperl
# PerlEx::DBI tries to fool DBI by setting MOD_PERL
if "MOD_PERL" in os.environ and not CGI.PERLEX_v:
# mod_perl handlers may run system() on scripts using CGI.pm;
# Make sure so we don't get fooled by inherited $ENV{MOD_PERL}
if (
"MOD_PERL_API_VERSION" in os.environ
and perllib.num(os.environ.get("MOD_PERL_API_VERSION")) == 2
):
CGI.MOD_PERL_v = 2
import Apache2.Response as _Apache2_Response
import Apache2.RequestRec as _Apache2_RequestRec
import Apache2.RequestUtil as _Apache2_RequestUtil
import Apache2.RequestIO as _Apache2_RequestIO
import APR.Pool as _APR_Pool
else:
CGI.MOD_PERL_v = 1
import Apache as _Apache
# Define the CRLF sequence. I can't use a simple "\r\n" because the meaning
# of "\n" is different on different OS's (sometimes it generates CRLF, sometimes LF
# and sometimes CR). The most popular VMS web server
# doesn't accept CRLF -- instead it wants a LR. EBCDIC machines don't
# use ASCII, so \015\012 means something different. I find this all
# really annoying.
CGI.EBCDIC_v = _pb("\t" != "\011")
if _str(CGI.OS_v) == "VMS":
CGI.CRLF_v = "\n"
elif CGI.EBCDIC_v:
CGI.CRLF_v = "\r\n"
else:
CGI.CRLF_v = "\015\012"
if CGI.needs_binmode_v:
_set_binmode()
CGI.EXPORT_TAGS_h = perllib.Hash(
{
":html2": [
"h1",
"h2",
"h3",
"h4",
"h5",
"h6",
*"p br hr ol ul li dl dt dd menu code var strong em tt u i b blockquote pre img a address cite samp dfn html head base body Link nextid title meta kbd start_html end_html input Select option comment charset escapeHTML".split(),
],
":html3": "div table caption th td TR Tr sup Sub strike applet Param nobr embed basefont style span layer ilayer font frameset frame script small big Area Map".split(),
":html4": "abbr acronym bdo col colgroup del fieldset iframe ins label legend noframes noscript object optgroup Q thead tbody tfoot".split(),
":form": "textfield textarea filefield password_field hidden checkbox checkbox_group submit reset defaults radio_group popup_menu button autoEscape scrolling_list image_button start_form end_form start_multipart_form end_multipart_form isindex tmpFileName uploadInfo URL_ENCODED MULTIPART".split(),
":cgi": "param multi_param upload path_info path_translated request_uri url self_url script_name cookie Dump raw_cookie request_method query_string Accept user_agent remote_host content_type remote_addr referer server_name server_software server_port server_protocol virtual_port virtual_host remote_ident auth_type http append save_parameters restore_parameters param_fetch remote_user user_name header redirect import_names put Delete Delete_all url_param cgi_error env_query_string".split(),
":netscape": "blink fontsize center".split(),
":ssl": "https".split(),
":cgi-lib": "ReadParse PrintHeader HtmlTop HtmlBot SplitParam Vars".split(),
":push": "multipart_init multipart_start multipart_end multipart_final".split(),
# bulk export/import
":html": ":html2 :html3 :html4 :netscape".split(),
":standard": ":html2 :html3 :html4 :form :cgi :ssl".split(),
":all": ":html2 :html3 :html4 :netscape :form :cgi :ssl :push".split(),
}
)
[docs]def new(*_args):
old = None
r_v = None
[class_, *initializer] = perllib.list_of_at_least_n(_args, 1)
initializer = perllib.Array(initializer)
self = perllib.Hash()
self = perllib.bless(self, perllib.ref_scalar(class_) or class_ or CGI.DefaultClass_v)
# always use a tempfile
self["use_tempfile"] = 1
if perllib.ref_scalar(initializer[0]) and (
perllib.isa(initializer[0], "Apache")
or perllib.isa(initializer[0], "Apache2::RequestRec")
):
self.r(initializer.pop(0) if initializer else None)
if perllib.ref_scalar(initializer[0]) and (perllib.isa(initializer[0], "CODE")):
self.upload_hook(
(initializer.pop(0) if initializer else None),
(initializer.pop(0) if initializer else None),
)
if len(initializer) > 0:
self["use_tempfile"] = initializer.pop(0) if initializer else None
if CGI.MOD_PERL_v:
if perllib.num(CGI.MOD_PERL_v) == 1:
if not self.r():
self.r(Apache.request(Apache))
r_v = self.r()
r_v.register_cleanup(CGI._reset_globals)
if CGI.SAVED_SYMBOLS_a:
self._setup_symbols(*CGI.SAVED_SYMBOLS_a)
else:
# XXX: once we have the new API
# will do a real PerlOptions -SetupEnv check
if not self.r():
self.r(Apache2.RequestUtil.request(Apache2.RequestUtil))
r_v = self.r()
if not ("REQUEST_METHOD" in os.environ):
r_v.subprocess_env()
perllib.method_call(r_v.pool(), "cleanup_register", CGI._reset_globals)
if CGI.SAVED_SYMBOLS_a:
self._setup_symbols(*CGI.SAVED_SYMBOLS_a)
CGI.NPH_v = None
if CGI.PERLEX_v:
self._reset_globals()
self.init(*initializer)
return self
CGI.new = types.MethodType(new, CGI)
for tag_l in _all_html_tags():
def _f880(tag_l):
def _f880template(*_args):
nonlocal tag_l
return _tag_func(tag_l, *_args)
return _f880template
setattr(CGI, tag_l, _f880(tag_l))
# start_html and end_html already exist as custom functions
if tag_l == "html":
continue
for start_end in "start end".split():
start_end_function = f"{start_end}_{tag_l}"
def _f887(start_end_function):
def _f887template(*_args):
nonlocal start_end_function
return _tag_func(start_end_function, *_args)
return _f887template
setattr(CGI, start_end_function, _f887(start_end_function))
builtins.__PACKAGE__ = "CGI.MultipartBuffer"
CGI.MultipartBuffer._DEBUG_v = 0
# how many bytes to read at a time. We use
# a 4K buffer by default.
MultipartBuffer.INITIAL_FILLUNIT_v = MultipartBuffer.INITIAL_FILLUNIT_v or 1024 * 4
MultipartBuffer.TIMEOUT_v = MultipartBuffer.TIMEOUT_v or 240 * 60 # 4 hour timeout for big files
MultipartBuffer.SPIN_LOOP_MAX_v = (
MultipartBuffer.SPIN_LOOP_MAX_v or 2000
) # bug fix for some Netscape servers
MultipartBuffer.CRLF_v = MultipartBuffer.CRLF_v or CGI.CRLF_v
CGI.MultipartBuffer.INITIAL_FILLUNIT_v = MultipartBuffer.INITIAL_FILLUNIT_v
CGI.MultipartBuffer.TIMEOUT_v = MultipartBuffer.TIMEOUT_v
CGI.MultipartBuffer.SPIN_LOOP_MAX_v = MultipartBuffer.SPIN_LOOP_MAX_v
CGI.MultipartBuffer.CRLF_v = MultipartBuffer.CRLF_v
builtins.__PACKAGE__ = "CGI"
# We get a whole bunch of warnings about "possibly uninitialized variables"
# when running with the -w switch. Touch them all once to get rid of the
# warnings. This is ugly and I hate it.
if perllib.WARNING:
CGI.CGI_v = ""
CGI.CGI_v = f""" {_bn(CGI.VERSION_v)};
{_bn(CGI.MultipartBuffer.SPIN_LOOP_MAX_v)};
{_bn(CGI.MultipartBuffer.CRLF_v)};
{_bn(CGI.MultipartBuffer.TIMEOUT_v)};
{_bn(CGI.MultipartBuffer.INITIAL_FILLUNIT_v)};
"""