Files
server/usr/lib/python3/dist-packages/mod_python/httpdconf.py
2026-01-07 20:52:11 +01:00

546 lines
18 KiB
Python

#
# Copyright (C) 2000, 2001, 2013 Gregory Trubetskoy
# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Apache Software Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License"); you
# may not use this file except in compliance with the License. You
# may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied. See the License for the specific language governing
# permissions and limitations under the License.
#
#
# Config maker, a la HTMLGen. This could grow into something useful.
#
from __future__ import print_function
import sys
import os
import shutil
# this is so that it could be referred to in a Container only_if
import mod_python
class Directive:
def __init__(self, name, val, flipslash=1):
self.name = name
self.val = val
self.indent = 0
self.flipslash = flipslash
def __repr__(self):
i = " " * self.indent
s = i + '%s(%s)' % (self.name, repr(self.val))
if self.flipslash:
s = s.replace("\\", "/")
return s
def __str__(self):
i = " " * self.indent
s = i + '%s %s\n' % (self.name, self.val)
if self.flipslash:
s = s.replace("\\", "/")
return s
class Container:
def __init__(self, *args, **kwargs):
self.args = list(args)
self.indent = 0
self.only_if = kwargs.get('only_if')
def append(self, value):
if not (isinstance(value, Directive) or
isinstance(value, Container) or
isinstance(value, ContainerTag) or
isinstance(value, Comment)):
raise TypeError("appended value must be an instance of Directive, Container, ContainerTag or Comment")
self.args.append(value)
def __repr__(self):
i = " " * self.indent
s = i + 'Container('
for arg in self.args:
arg.indent = self.indent + 4
s += "\n%s," % repr(arg)
s += "\n" + i + (self.only_if and (' only_if=%s)' % repr(self.only_if)) or ')')
return s
def __str__(self):
if self.only_if and not eval(self.only_if):
return ""
s = ""
for arg in self.args:
arg.indent = self.indent
s += "%s" % str(arg)
return s
class ContainerTag:
def __init__(self, tag, attr, args, flipslash=1):
self.tag = tag
self.attr = attr
self.args = args
self.indent = 0
self.flipslash = flipslash
def __repr__(self):
i = " " * self.indent
s = i + "%s(%s," % (self.tag, repr(self.attr))
if self.flipslash:
s = s.replace("\\", "/")
for arg in self.args:
arg.indent = self.indent + 4
s += "\n%s," % repr(arg)
s += "\n" + i + ")"
return s
def __str__(self):
i = " " * self.indent
s = i + "<%s %s>\n" % (self.tag, self.attr)
if self.flipslash:
s = s.replace("\\", "/")
for arg in self.args:
arg.indent = self.indent + 2
s += "%s" % str(arg)
s += i + "</%s>\n" % self.tag
return s
class Comment:
def __init__(self, comment):
self.comment = comment
self.indent = 0
def __repr__(self):
i = " " * self.indent
lines = self.comment.splitlines()
s = i + "Comment(%s" % repr(lines[0]+"\n")
for line in lines[1:]:
s += "\n " + i + repr(line+"\n")
s += ")"
return s
def __str__(self):
i = " " * self.indent
s = ""
for line in self.comment.splitlines():
s += i + '# %s\n' % line
return s
## directives
class AddHandler(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class AddOutputFilter(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class AddType(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class AuthBasicAuthoritative(Directive):
# New in Apache 2.2
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class AuthBasicProvider(Directive):
# New in Apache 2.2
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class AuthType(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class AuthName(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class CustomLog(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class Directory(ContainerTag):
def __init__(self, dir, *args):
ContainerTag.__init__(self, self.__class__.__name__, dir, args)
class DirectoryIndex(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class DocumentRoot(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class ErrorLog(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class Files(ContainerTag):
def __init__(self, dir, *args):
ContainerTag.__init__(self, self.__class__.__name__, dir, args)
class IfModule(ContainerTag):
def __init__(self, dir, *args):
ContainerTag.__init__(self, self.__class__.__name__, dir, args)
class KeepAliveTimeout(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class Listen(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class LoadModule(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class Location(ContainerTag):
def __init__(self, dir, *args):
ContainerTag.__init__(self, self.__class__.__name__, dir, args)
class LogLevel(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class LogFormat(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val, flipslash=0)
class LockFile(Directive):
def __init__(self, val):
import sys
if sys.platform!='win32':
Directive.__init__(self, self.__class__.__name__, val)
else:
Directive.__init__(self, '#'+self.__class__.__name__, val)
class MaxConnectionsPerChild(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class MaxClients(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class MaxRequestsPerChild(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class MaxSpareServers(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class MaxSpareThreads(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class MaxThreadsPerChild(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class MinSpareThreads(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class Mutex(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class NameVirtualHost(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class NumServers(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class Options(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class PidFile(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class PythonAuthenHandler(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class PythonAuthzHandler(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class PythonCleanupHandler(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class PythonConnectionHandler(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class PythonDebug(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class PythonHandler(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class PythonAccessHandler(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class PythonPostReadRequestHandler(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class PythonTransHandler(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class PythonFixupHandler(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class PythonImport(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class PythonPath(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val, flipslash=0)
class PythonOutputFilter(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class PythonOption(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class Require(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class SetHandler(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class ServerAdmin(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class ServerName(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class ServerPath(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class ServerRoot(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class StartServers(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class StartThreads(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class ThreadsPerChild(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class Timeout(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class TypesConfig(Directive):
def __init__(self, val):
Directive.__init__(self, self.__class__.__name__, val)
class PythonInterpPerDirectory(Directive):
def __init__(self, val='Off'):
Directive.__init__(self, self.__class__.__name__, val)
class PythonInterpPerDirective(Directive):
def __init__(self, val='Off'):
Directive.__init__(self, self.__class__.__name__, val)
class VirtualHost(ContainerTag):
def __init__(self, addr, *args):
ContainerTag.__init__(self, self.__class__.__name__, addr, args)
## utility functions
def quote_if_space(s):
# Windows doesn't like quotes when there are
# no spaces, but needs them otherwise,
# TODO: Is this still true?
if s.find(" ") != -1:
s = '"%s"' % s
return s
def write_basic_config(server_root, listen='0.0.0.0:8888', conf="conf", logs="logs",
htdocs="public", pythonhandler="mod_python.publisher",
pythonpath=[], pythonoptions=[], mp_comments=[],
conf_name='httpd_conf.py', createdirs=True, replace_config=False):
"""This generates a sensible Apache configuration"""
conf_path = os.path.join(server_root, conf, conf_name)
if os.path.exists(conf_path) and not replace_config:
print('Error: %s already exists, aborting.' % repr(conf_path), file=sys.stderr)
return
if createdirs:
for dirname in [server_root,
os.path.join(server_root, htdocs),
os.path.join(server_root, conf),
os.path.join(server_root, logs)]:
if os.path.isdir(dirname):
print("Warning: directory %s already exists, continuing." % repr(dirname), file=sys.stderr)
else:
print("Creating directory %s." % repr(dirname), file=sys.stderr)
os.mkdir(dirname)
# try to find mime.types
mime_types_dest = os.path.join(server_root, conf, 'mime.types')
if os.path.isfile(mime_types_dest):
print("Warning: file %s already exists, continuing." % repr(mime_types_dest), file=sys.stderr)
else:
for mime_types_dir in [mod_python.version.SYSCONFDIR, '/etc']:
mime_types_src = os.path.join(mime_types_dir, 'mime.types')
if os.path.isfile(mime_types_src):
print("Copying %s to %s" % (repr(mime_types_src), repr(mime_types_dest)), file=sys.stderr)
shutil.copy(mime_types_src, mime_types_dest)
break
mime_types = os.path.join(conf, "mime.types")
if not os.path.exists(os.path.join(server_root, mime_types)):
print("Warning: file %s does not exist." % repr(os.path.join(server_root, mime_types)), file=sys.stderr)
if not os.path.isdir(os.path.join(server_root, htdocs)):
print("Warning: %s does not exist or not a directory." % repr(os.path.join(server_root, htdocs)), file=sys.stderr)
modpath = mod_python.version.LIBEXECDIR
modules = Container(Comment("\nLoad the necessary modules (this is the default httpd set):\n\n"))
for module in [
['authn_file_module', 'mod_authn_file.so'],
['authn_core_module', 'mod_authn_core.so'],
['authz_host_module', 'mod_authz_host.so'],
['authz_groupfile_module', 'mod_authz_groupfile.so'],
['authz_user_module', 'mod_authz_user.so'],
['authz_core_module', 'mod_authz_core.so'],
['access_compat_module', 'mod_access_compat.so'],
['auth_basic_module', 'mod_auth_basic.so'],
['reqtimeout_module', 'mod_reqtimeout.so'],
['include_module', 'mod_include.so'],
['filter_module', 'mod_filter.so'],
['mime_module', 'mod_mime.so'],
['log_config_module', 'mod_log_config.so'],
['env_module', 'mod_env.so'],
['headers_module', 'mod_headers.so'],
['setenvif_module', 'mod_setenvif.so'],
['version_module', 'mod_version.so'],
['unixd_module', 'mod_unixd.so'],
['status_module', 'mod_status.so'],
['autoindex_module', 'mod_autoindex.so'],
['dir_module', 'mod_dir.so'],
['alias_module', 'mod_alias.so'],
]:
modules.append(
LoadModule("%s %s" % (module[0], quote_if_space(os.path.join(modpath, module[1]))))
)
main = Container(Comment("\nMain configuration options:\n\n"),
ServerRoot(server_root),
Container(MaxConnectionsPerChild('65536'),
only_if="mod_python.version.HTTPD_VERSION[0:3] == '2.4'"),
Container(MaxRequestsPerChild('65536'),
only_if="mod_python.version.HTTPD_VERSION[0:3] < '2.4'"),
LogFormat(r'"%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined'),
CustomLog("%s combined" % quote_if_space(os.path.join(logs, "access_log"))),
ErrorLog(quote_if_space(os.path.join(logs, "error_log"))),
LogLevel("warn"),
PidFile(quote_if_space(os.path.join(logs, "httpd.pid"))),
TypesConfig(quote_if_space(mime_types)),
# The only reason we need a ServerName is so that Apache does not
# generate a warning about being unable to determine its name.
ServerName("127.0.0.1"),
Listen(listen),
DocumentRoot(quote_if_space(os.path.join(server_root, htdocs))),
Container(LockFile(quote_if_space(os.path.join(logs, "accept.lock"))),
only_if="mod_python.version.HTTPD_VERSION[0:3] == '2.2'"),
)
mp = Container(Comment("\nmod_python-specific options:\n\n"),
LoadModule("python_module %s" % quote_if_space(quote_if_space(os.path.join(modpath, 'mod_python.so')))),
SetHandler("mod_python"),
Comment("PythonDebug On"),
PythonHandler(pythonhandler),
)
if pythonpath:
pp = "sys.path+["
for p in pythonpath:
pp += repr(p)+","
pp += "]"
mp.append(PythonPath('"%s"' % pp))
for po in pythonoptions:
mp.append(PythonOption(po))
for c in mp_comments:
mp.append(Comment(c))
config = Container()
config.append(Comment(
"\n"
"This config was auto-generated, do not edit!\n"
"\n"
))
config.append(modules)
config.append(main)
config.append(mp)
s = """#!%s
#
# This config was auto-generated, but you can edit it!
# It can be used to generate an Apache config by simply
# running it. We recommend you run it like this:
# $ mod_python genconfig <this filename> > <new apache confg>
#\n
""" % mod_python.version.PYTHON_BIN
s += "from mod_python.httpdconf import *\n\n"
s += "config = " + repr(config)
s += "\n\nprint(config)\n"
print("Writing %s." % repr(conf_path), file=sys.stderr)
open(conf_path, 'w').write(s)
return conf_path