home *** CD-ROM | disk | FTP | other *** search
- #
- # Copyright 2004 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.
- #
- # Originally developed by Gregory Trubetskoy.
- #
- # $Id: apache.py,v 1.82 2004/02/16 19:47:27 grisha Exp $
-
- import sys
- import traceback
- import time
- import os
- import pdb
- import stat
- import imp
- import types
- import _apache
-
- # a small hack to improve PythonPath performance. This
- # variable stores the last PythonPath in raw (unevaled) form.
- _path = None
-
- class CallBack:
- """
- A generic callback object.
- """
-
- class HStack:
- """
- The actual stack string lives in the request object so
- it can be manipulated by both apache.py and mod_python.c
- """
-
- def __init__(self, req):
- self.req = req
-
- def pop(self):
-
- handlers = self.req.hstack.split()
-
- if not handlers:
- return None
- else:
- self.req.hstack = " ".join(handlers[1:])
- return handlers[0]
-
- def ConnectionDispatch(self, conn):
-
- # config
- config = conn.base_server.get_config()
- debug = int(config.get("PythonDebug", 0))
-
- try:
-
- handler = conn.hlist.handler
-
- # split module::handler
- l = handler.split('::', 1)
- module_name = l[0]
- if len(l) == 1:
- # no oject, provide default
- object_str = "connectionhandler"
- else:
- object_str = l[1]
-
- # add the directory to pythonpath if
- # not there yet, or pythonpath specified
-
- if config.has_key("PythonPath"):
- # we want to do as little evaling as possible,
- # so we remember the path in un-evaled form and
- # compare it
- global _path
- pathstring = config["PythonPath"]
- if pathstring != _path:
- _path = pathstring
- newpath = eval(pathstring)
- if sys.path != newpath:
- sys.path[:] = newpath
-
- # import module
- module = import_module(module_name,
- autoreload=int(config.get("PythonAutoReload", 1)),
- log=debug)
- # find the object
- object = resolve_object(module, object_str,
- arg=conn, silent=0)
-
- if object:
-
- # call the object
- if config.has_key("PythonEnablePdb"):
- result = pdb.runcall(object, conn)
- else:
- result = object(conn)
-
- assert (type(result) == type(int())), \
- "ConnectionHandler '%s' returned invalid return code." % handler
-
- except PROG_TRACEBACK, traceblock:
- # Program run-time error
- try:
- (etype, value, traceback) = traceblock
- result = self.ReportError(etype, value, traceback, srv=conn.base_server,
- phase="ConnectionHandler",
- hname=handler, debug=debug)
- finally:
- traceback = None
-
- except:
- # Any other rerror (usually parsing)
- try:
- exc_type, exc_value, exc_traceback = sys.exc_info()
- result = self.ReportError(exc_type, exc_value, exc_traceback, srv=conn.base_server,
- phase="ConnectionHandler",
- hname=handler, debug=debug)
- finally:
- exc_traceback = None
-
- return result
-
- def FilterDispatch(self, filter):
-
- req = filter.req
-
- # config
- config = req.get_config()
- debug = int(config.get("PythonDebug", 0))
-
- try:
-
- # split module::handler
- l = filter.handler.split('::', 1)
- module_name = l[0]
- if len(l) == 1:
- # no oject, provide default
- if filter.is_input:
- object_str = "inputfilter"
- else:
- object_str = "outputfilter"
- else:
- object_str = l[1]
-
- # add the directory to pythonpath if
- # not there yet, or pythonpath specified
-
- if config.has_key("PythonPath"):
- # we want to do as little evaling as possible,
- # so we remember the path in un-evaled form and
- # compare it
- global _path
- pathstring = config["PythonPath"]
- if pathstring != _path:
- _path = pathstring
- newpath = eval(pathstring)
- if sys.path != newpath:
- sys.path[:] = newpath
- else:
- if filter.dir and (filter.dir not in sys.path):
- sys.path[:0] = [filter.dir]
-
- # import module
- module = import_module(module_name,
- autoreload=int(config.get("PythonAutoReload", 1)),
- log=debug)
-
- # find the object
- object = resolve_object(module, object_str, arg=filter, silent=0)
-
- if object:
-
- # call the object
- if config.has_key("PythonEnablePdb"):
- pdb.runcall(object, filter)
- else:
- object(filter)
-
- # always flush the filter. without a FLUSH or EOS bucket,
- # the content is never written to the network.
- # XXX an alternative is to tell the user to flush() always
- filter.flush()
-
- except SERVER_RETURN, value:
- # SERVER_RETURN indicates a non-local abort from below
- # with value as (result, status) or (result, None) or result
- try:
- if len(value.args) == 2:
- (result, status) = value.args
- if status:
- req.status = status
- else:
- result = value.args[0]
-
- if type(result) != type(7):
- s = "Value raised with SERVER_RETURN is invalid. It is a "
- s = s + "%s, but it must be a tuple or an int." % type(result)
- _apache.log_error(s, APLOG_NOERRNO|APLOG_ERR, req.server)
-
- return
-
- except:
- pass
-
- except PROG_TRACEBACK, traceblock:
- # Program run-time error
- try:
- (etype, value, traceback) = traceblock
- filter.disable()
- result = self.ReportError(etype, value, traceback, req=req, filter=filter,
- phase="Filter: " + filter.name,
- hname=filter.handler, debug=debug)
- finally:
- traceback = None
-
- except:
- # Any other rerror (usually parsing)
- try:
- exc_type, exc_value, exc_traceback = sys.exc_info()
- filter.disable()
- result = self.ReportError(exc_type, exc_value, exc_traceback, req=req, filter=filter,
- phase=filter.name, hname=filter.handler,
- debug=debug)
- finally:
- exc_traceback = None
-
- return OK
-
- def HandlerDispatch(self, req):
- """
- This is the handler dispatcher.
- """
-
- # be cautious
- result = HTTP_INTERNAL_SERVER_ERROR
-
- # config
- config = req.get_config()
- debug = int(config.get("PythonDebug", 0))
-
- try:
- hlist = req.hlist
-
- while hlist.handler:
-
- # split module::handler
- l = hlist.handler.split('::', 1)
-
- module_name = l[0]
- if len(l) == 1:
- # no oject, provide default
- object_str = req.phase[len("python"):].lower()
- else:
- object_str = l[1]
-
- # add the directory to pythonpath if
- # not there yet, or pythonpath specified
- if config.has_key("PythonPath"):
- # we want to do as little evaling as possible,
- # so we remember the path in un-evaled form and
- # compare it
- global _path
- pathstring = config["PythonPath"]
- if pathstring != _path:
- _path = pathstring
- newpath = eval(pathstring)
- if sys.path != newpath:
- sys.path[:] = newpath
- else:
- dir = hlist.directory
- if dir and (dir not in sys.path):
- sys.path[:0] = [dir]
-
- # import module
- module = import_module(module_name,
- autoreload=int(config.get("PythonAutoReload", 1)),
- log=debug)
-
- # find the object
- object = resolve_object(module, object_str,
- arg=req, silent=hlist.silent)
-
- if object:
-
- # call the object
- if config.has_key("PythonEnablePdb"):
- result = pdb.runcall(object, req)
- else:
- result = object(req)
-
- assert (type(result) == type(int())), \
- "Handler '%s' returned invalid return code." % hlist.handler
-
- # stop cycling through handlers
- if result != OK:
- break
-
- elif hlist.silent:
- result = DECLINED
-
- hlist.next()
-
- except SERVER_RETURN, value:
- # SERVER_RETURN indicates an abort from below
- # with value as (result, status) or (result, None) or result
- try:
- if len(value.args) == 2:
- (result, status) = value.args
- if status:
- req.status = status
- else:
- result = value.args[0]
-
- if type(result) != type(7):
- s = "Value raised with SERVER_RETURN is invalid. It is a "
- s = s + "%s, but it must be a tuple or an int." % type(result)
- _apache.log_error(s, APLOG_NOERRNO|APLOG_ERR, req.server)
- return HTTP_INTERNAL_SERVER_ERROR
-
- except:
- pass
-
- except PROG_TRACEBACK, traceblock:
- # Program run-time error
- try:
- (etype, value, traceback) = traceblock
- result = self.ReportError(etype, value, traceback, req=req,
- phase=req.phase, hname=hlist.handler,
- debug=debug)
- finally:
- traceback = None
-
- except:
- # Any other rerror (usually parsing)
- try:
- exc_type, exc_value, exc_traceback = sys.exc_info()
- result = self.ReportError(exc_type, exc_value, exc_traceback, req=req,
- phase=req.phase, hname=hlist.handler, debug=debug)
- finally:
- exc_traceback = None
-
- return result
-
-
- def ReportError(self, etype, evalue, etb, req=None, filter=None, srv=None,
- phase="N/A", hname="N/A", debug=0):
- """
- This function is only used when debugging is on.
- It sends the output similar to what you'd see
- when using Python interactively to the browser
- """
-
- try: # try/finally
- try: # try/except
-
- if str(etype) == "exceptions.IOError" \
- and str(evalue)[:5] == "Write":
- # if this is an IOError while writing to client,
- # it is probably better not to try to write to the cleint
- # even if debug is on.
- debug = 0
-
- # write to log
- for e in traceback.format_exception(etype, evalue, etb):
- s = "%s %s: %s" % (phase, hname, e[:-1])
- if req:
- req.log_error(s, APLOG_NOERRNO|APLOG_ERR)
- else:
- _apache.log_error(s, APLOG_NOERRNO|APLOG_ERR, srv)
-
- if not debug or not req:
- return HTTP_INTERNAL_SERVER_ERROR
- else:
- # write to client
- req.content_type = 'text/html'
-
- s = '\n<pre>\nMod_python error: "%s %s"\n\n' % (phase, hname)
- for e in traceback.format_exception(etype, evalue, etb):
- s = s + e + '\n'
- s = s + "</pre>\n"
-
- if filter:
- filter.write(s)
- filter.flush()
- else:
- req.write(s)
-
- return DONE
- except:
- # last try
- traceback.print_exc()
-
- finally:
- # erase the traceback
- etb = None
- # we do not return anything
-
- def import_module(module_name, autoreload=1, log=0, path=None):
- """
- Get the module to handle the request. If
- autoreload is on, then the module will be reloaded
- if it has changed since the last import.
- """
-
- # (Re)import
- if sys.modules.has_key(module_name):
-
- # The module has been imported already
- module = sys.modules[module_name]
-
- # but is it in the path?
- file = module.__dict__.get("__file__")
-
- # the "and not" part of this condition is to prevent execution
- # of arbitrary already imported modules, such as os. The
- # reason we use startswith as opposed to exact match is that
- # modules inside packages are actually in subdirectories.
-
- if not file or (path and not filter(file.startswith, path)):
- # there is a script by this name already imported, but it's in
- # a different directory, therefore it's a different script
- mtime, oldmtime = 0, -1
- elif autoreload:
- oldmtime = module.__dict__.get("__mtime__", 0)
- mtime = module_mtime(module)
- else:
- mtime, oldmtime = 0, 0
-
- else:
- mtime, oldmtime = 0, -1
-
- if mtime > oldmtime:
-
- # Import the module
- if log:
- if path:
- s = "mod_python: (Re)importing module '%s' with path set to '%s'" % (module_name, path)
- else:
- s = "mod_python: (Re)importing module '%s'" % module_name
- _apache.log_error(s, APLOG_NOERRNO|APLOG_NOTICE)
-
- parts = module_name.split('.')
- for i in range(len(parts)):
- f, p, d = imp.find_module(parts[i], path)
- try:
- mname = ".".join(parts[:i+1])
- module = imp.load_module(mname, f, p, d)
- finally:
- if f: f.close()
- if hasattr(module, "__path__"):
- path = module.__path__
-
- if mtime == 0:
- mtime = module_mtime(module)
-
- module.__mtime__ = mtime
-
- return module
-
- def module_mtime(module):
- """Get modification time of module"""
- mtime = 0
- if module.__dict__.has_key("__file__"):
-
- filepath = module.__file__
-
- try:
- # this try/except block is a workaround for a Python bug in
- # 2.0, 2.1 and 2.1.1. See
- # http://sourceforge.net/tracker/?group_id=5470&atid=105470&func=detail&aid=422004
-
- if os.path.exists(filepath):
- mtime = os.path.getmtime(filepath)
-
- if os.path.exists(filepath[:-1]) :
- mtime = max(mtime, os.path.getmtime(filepath[:-1]))
-
- except OSError: pass
-
- return mtime
-
- def resolve_object(module, object_str, arg=None, silent=0):
- """
- This function traverses the objects separated by .
- (period) to find the last one we're looking for:
-
- From left to right, find objects, if it is
- an unbound method of a class, instantiate the
- class passing the request as single argument
-
- 'arg' is sometimes req, sometimes filter,
- sometimes connection
- """
-
- obj = module
-
- for obj_str in object_str.split('.'):
-
- parent = obj
-
- # don't throw attribute errors when silent
- if silent and not hasattr(obj, obj_str):
- return None
-
- # this adds a little clarity if we have an attriute error
- if obj == module and not hasattr(module, obj_str):
- if hasattr(module, "__file__"):
- s = "module '%s' contains no '%s'" % (module.__file__, obj_str)
- raise AttributeError, s
-
- obj = getattr(obj, obj_str)
-
- if hasattr(obj, "im_self") and not obj.im_self:
- # this is an unbound method, its class
- # needs to be instantiated
- instance = parent(arg)
- obj = getattr(instance, obj_str)
-
- return obj
-
- def build_cgi_env(req):
- """
- Utility function that returns a dictionary of
- CGI environment variables as described in
- http://hoohoo.ncsa.uiuc.edu/cgi/env.html
- """
-
- req.add_common_vars()
- env = req.subprocess_env.copy()
-
- if len(req.path_info) > 0:
- env["SCRIPT_NAME"] = req.uri[:-len(req.path_info)]
- else:
- env["SCRIPT_NAME"] = req.uri
-
- env["GATEWAY_INTERFACE"] = "Python-CGI/1.1"
-
- # you may want to comment this out for better security
- if req.headers_in.has_key("authorization"):
- env["HTTP_AUTHORIZATION"] = req.headers_in["authorization"]
-
- return env
-
- class NullIO:
- """ Abstract IO
- """
- def tell(self): return 0
- def read(self, n = -1): return ""
- def readline(self, length = None): return ""
- def readlines(self): return []
- def write(self, s): pass
- def writelines(self, list):
- self.write("".join(list))
- def isatty(self): return 0
- def flush(self): pass
- def close(self): pass
- def seek(self, pos, mode = 0): pass
-
- class CGIStdin(NullIO):
-
- def __init__(self, req):
- self.pos = 0
- self.req = req
- self.BLOCK = 65536 # 64K
- # note that self.buf sometimes contains leftovers
- # that were read, but not used when readline was used
- self.buf = ""
-
- def read(self, n = -1):
- if n == 0:
- return ""
- if n == -1:
- s = self.req.read(self.BLOCK)
- while s:
- self.buf = self.buf + s
- self.pos = self.pos + len(s)
- s = self.req.read(self.BLOCK)
- result = self.buf
- self.buf = ""
- return result
- else:
- if self.buf:
- s = self.buf[:n]
- n = n - len(s)
- else:
- s = ""
- s = s + self.req.read(n)
- self.pos = self.pos + len(s)
- return s
-
- def readlines(self):
- s = (self.buf + self.read()).split('\n')
- return map(lambda s: s + '\n', s)
-
- def readline(self, n = -1):
-
- if n == 0:
- return ""
-
- # fill up the buffer
- self.buf = self.buf + self.req.read(self.BLOCK)
-
- # look for \n in the buffer
- i = self.buf.find('\n')
- while i == -1: # if \n not found - read more
- if (n != -1) and (len(self.buf) >= n): # we're past n
- i = n - 1
- break
- x = len(self.buf)
- self.buf = self.buf + self.req.read(self.BLOCK)
- if len(self.buf) == x: # nothing read, eof
- i = x - 1
- break
- i = self.buf.find('\n', x)
-
- # carve out the piece, then shorten the buffer
- result = self.buf[:i+1]
- self.buf = self.buf[i+1:]
- self.pos = self.pos + len(result)
- return result
-
-
- class CGIStdout(NullIO):
-
- """
- Class that allows writing to the socket directly for CGI.
- """
-
- def __init__(self, req):
- self.pos = 0
- self.req = req
- self.headers_sent = 0
- self.headers = ""
-
- def write(self, s):
-
- if not s: return
-
- if not self.headers_sent:
- self.headers = self.headers + s
-
- # are headers over yet?
- headers_over = 0
-
- # first try RFC-compliant CRLF
- ss = self.headers.split('\r\n\r\n', 1)
- if len(ss) < 2:
- # second try with \n\n
- ss = self.headers.split('\n\n', 1)
- if len(ss) >= 2:
- headers_over = 1
- else:
- headers_over = 1
-
- if headers_over:
- # headers done, process them
- ss[0] = ss[0].replace('\r\n', '\n')
- lines = ss[0].split('\n')
- for line in lines:
- h, v = line.split(":", 1)
- v = v.strip()
- if h.lower() == "status":
- status = int(v.split()[0])
- self.req.status = status
- elif h.lower() == "content-type":
- self.req.content_type = v
- self.req.headers_out[h] = v
- else:
- self.req.headers_out.add(h, v)
-
- self.headers_sent = 1
-
- # write the body if any at this point
- self.req.write(ss[1])
- else:
- self.req.write(str(s))
-
- self.pos = self.pos + len(s)
-
- def tell(self): return self.pos
-
- def setup_cgi(req):
- """
- Replace sys.stdin and stdout with an objects that read/write to
- the socket, as well as substitute the os.environ.
- Returns (environ, stdin, stdout) which you must save and then use
- with restore_nocgi().
- """
-
- # save env
- save_env = os.environ.copy()
-
- si = sys.stdin
- so = sys.stdout
-
- os.environ.update(build_cgi_env(req))
-
- sys.stdout = CGIStdout(req)
- sys.stdin = CGIStdin(req)
-
- sys.argv = [] # keeps cgi.py happy
-
- return save_env, si, so
-
- def restore_nocgi(sav_env, si, so):
- """ see setup_cgi() """
-
- osenv = os.environ
-
- # restore env
- for k in osenv.keys():
- del osenv[k]
- for k in sav_env:
- osenv[k] = sav_env[k]
-
- sys.stdout = si
- sys.stdin = so
-
- def init():
- """
- This function is called by the server at startup time
- """
-
- return CallBack()
-
- ## Some functions made public
- make_table = _apache.table
- log_error = _apache.log_error
- table = _apache.table
- config_tree = _apache.config_tree
- server_root = _apache.server_root
- mpm_query = _apache.mpm_query
-
- ## Some constants
-
- HTTP_CONTINUE = 100
- HTTP_SWITCHING_PROTOCOLS = 101
- HTTP_PROCESSING = 102
- HTTP_OK = 200
- HTTP_CREATED = 201
- HTTP_ACCEPTED = 202
- HTTP_NON_AUTHORITATIVE = 203
- HTTP_NO_CONTENT = 204
- HTTP_RESET_CONTENT = 205
- HTTP_PARTIAL_CONTENT = 206
- HTTP_MULTI_STATUS = 207
- HTTP_MULTIPLE_CHOICES = 300
- HTTP_MOVED_PERMANENTLY = 301
- HTTP_MOVED_TEMPORARILY = 302
- HTTP_SEE_OTHER = 303
- HTTP_NOT_MODIFIED = 304
- HTTP_USE_PROXY = 305
- HTTP_TEMPORARY_REDIRECT = 307
- HTTP_BAD_REQUEST = 400
- HTTP_UNAUTHORIZED = 401
- HTTP_PAYMENT_REQUIRED = 402
- HTTP_FORBIDDEN = 403
- HTTP_NOT_FOUND = 404
- HTTP_METHOD_NOT_ALLOWED = 405
- HTTP_NOT_ACCEPTABLE = 406
- HTTP_PROXY_AUTHENTICATION_REQUIRED= 407
- HTTP_REQUEST_TIME_OUT = 408
- HTTP_CONFLICT = 409
- HTTP_GONE = 410
- HTTP_LENGTH_REQUIRED = 411
- HTTP_PRECONDITION_FAILED = 412
- HTTP_REQUEST_ENTITY_TOO_LARGE = 413
- HTTP_REQUEST_URI_TOO_LARGE = 414
- HTTP_UNSUPPORTED_MEDIA_TYPE = 415
- HTTP_RANGE_NOT_SATISFIABLE = 416
- HTTP_EXPECTATION_FAILED = 417
- HTTP_UNPROCESSABLE_ENTITY = 422
- HTTP_LOCKED = 423
- HTTP_FAILED_DEPENDENCY = 424
- HTTP_INTERNAL_SERVER_ERROR = 500
- HTTP_NOT_IMPLEMENTED = 501
- HTTP_BAD_GATEWAY = 502
- HTTP_SERVICE_UNAVAILABLE = 503
- HTTP_GATEWAY_TIME_OUT = 504
- HTTP_VERSION_NOT_SUPPORTED = 505
- HTTP_VARIANT_ALSO_VARIES = 506
- HTTP_INSUFFICIENT_STORAGE = 507
- HTTP_NOT_EXTENDED = 510
-
- # The APLOG constants in Apache are derived from syslog.h
- # constants, so we do same here.
-
- try:
- import syslog
- APLOG_EMERG = syslog.LOG_EMERG # system is unusable
- APLOG_ALERT = syslog.LOG_ALERT # action must be taken immediately
- APLOG_CRIT = syslog.LOG_CRIT # critical conditions
- APLOG_ERR = syslog.LOG_ERR # error conditions
- APLOG_WARNING = syslog.LOG_WARNING # warning conditions
- APLOG_NOTICE = syslog.LOG_NOTICE # normal but significant condition
- APLOG_INFO = syslog.LOG_INFO # informational
- APLOG_DEBUG = syslog.LOG_DEBUG # debug-level messages
- except ImportError:
- APLOG_EMERG = 0
- APLOG_ALERT = 1
- APLOG_CRIT = 2
- APLOG_ERR = 3
- APLOG_WARNING = 4
- APLOG_NOTICE = 5
- APLOG_INFO = 6
- APLOG_DEBUG = 7
-
- APLOG_NOERRNO = 8
-
- OK = REQ_PROCEED = 0
- DONE = -2
- DECLINED = REQ_NOACTION = -1
-
- # constants for get_remote_host
- REMOTE_HOST = 0
- REMOTE_NAME = 1
- REMOTE_NOLOOKUP = 2
- REMOTE_DOUBLE_REV = 3
-
- # legacy/mod_python things
- REQ_ABORTED = HTTP_INTERNAL_SERVER_ERROR
- REQ_EXIT = "REQ_EXIT"
- SERVER_RETURN = _apache.SERVER_RETURN
- PROG_TRACEBACK = "PROG_TRACEBACK"
-
- # the req.finfo tuple
- FINFO_MODE = 0
- FINFO_INO = 1
- FINFO_DEV = 2
- FINFO_NLINK = 3
- FINFO_UID = 4
- FINFO_GID = 5
- FINFO_SIZE = 6
- FINFO_ATIME = 7
- FINFO_MTIME = 8
- FINFO_CTIME = 9
- FINFO_FNAME = 10
- FINFO_NAME = 11
- #FINFO_FILEHAND = 14
-
- # the req.parsed_uri
- URI_SCHEME = 0
- URI_HOSTINFO = 1
- URI_USER = 2
- URI_PASSWORD = 3
- URI_HOSTNAME = 4
- URI_PORT = 5
- URI_PATH = 6
- URI_QUERY = 7
- URI_FRAGMENT = 8
-
- # for req.proxyreq
- PROXYREQ_NONE = 0 # No proxy
- PROXYREQ_PROXY = 1 # Standard proxy
- PROXYREQ_REVERSE = 2 # Reverse proxy
-
- # methods for req.allow_method()
- M_GET = 0 # RFC 2616: HTTP
- M_PUT = 1
- M_POST = 2
- M_DELETE = 3
- M_CONNECT = 4
- M_OPTIONS = 5
- M_TRACE = 6 # RFC 2616: HTTP
- M_PATCH = 7
- M_PROPFIND = 8 # RFC 2518: WebDAV
- M_PROPPATCH = 9
- M_MKCOL = 10
- M_COPY = 11
- M_MOVE = 12
- M_LOCK = 13
- M_UNLOCK = 14 # RFC2518: WebDAV
- M_VERSION_CONTROL = 15 # RFC3253: WebDAV Versioning
- M_CHECKOUT = 16
- M_UNCHECKOUT = 17
- M_CHECKIN = 18
- M_UPDATE = 19
- M_LABEL = 20
- M_REPORT = 21
- M_MKWORKSPACE = 22
- M_MKACTIVITY = 23
- M_BASELINE_CONTROL = 24
- M_MERGE = 25
- M_INVALID = 26 # RFC3253: WebDAV Versioning
-
- # for req.used_path_info
- AP_REQ_ACCEPT_PATH_INFO = 0 # Accept request given path_info
- AP_REQ_REJECT_PATH_INFO = 1 # Send 404 error if path_info was given
- AP_REQ_DEFAULT_PATH_INFO = 2 # Module's choice for handling path_info
-
-
- # for mpm_query
- AP_MPMQ_NOT_SUPPORTED = 0 # This value specifies whether
- # an MPM is capable of
- # threading or forking.
- AP_MPMQ_STATIC = 1 # This value specifies whether
- # an MPM is using a static # of
- # threads or daemons.
- AP_MPMQ_DYNAMIC = 2 # This value specifies whether
- # an MPM is using a dynamic # of
- # threads or daemons.
-
- AP_MPMQ_MAX_DAEMON_USED = 1 # Max # of daemons used so far
- AP_MPMQ_IS_THREADED = 2 # MPM can do threading
- AP_MPMQ_IS_FORKED = 3 # MPM can do forking
- AP_MPMQ_HARD_LIMIT_DAEMONS = 4 # The compiled max # daemons
- AP_MPMQ_HARD_LIMIT_THREADS = 5 # The compiled max # threads
- AP_MPMQ_MAX_THREADS = 6 # # of threads/child by config
- AP_MPMQ_MIN_SPARE_DAEMONS = 7 # Min # of spare daemons
- AP_MPMQ_MIN_SPARE_THREADS = 8 # Min # of spare threads
- AP_MPMQ_MAX_SPARE_DAEMONS = 9 # Max # of spare daemons
- AP_MPMQ_MAX_SPARE_THREADS = 10 # Max # of spare threads
- AP_MPMQ_MAX_REQUESTS_DAEMON= 11 # Max # of requests per daemon
- AP_MPMQ_MAX_DAEMONS = 12 # Max # of daemons by config
-
-