home *** CD-ROM | disk | FTP | other *** search
/ PC Professionell 2004 December / PCpro_2004_12.ISO / files / webserver / tsw / TSW_3.4.0.exe / Apache2 / python / apache.py < prev    next >
Encoding:
Python Source  |  2004-02-16  |  29.2 KB  |  926 lines

  1.  #
  2.  # Copyright 2004 Apache Software Foundation 
  3.  # 
  4.  # Licensed under the Apache License, Version 2.0 (the "License"); you
  5.  # may not use this file except in compliance with the License.  You
  6.  # may obtain a copy of the License at
  7.  #
  8.  #      http://www.apache.org/licenses/LICENSE-2.0
  9.  #
  10.  # Unless required by applicable law or agreed to in writing, software
  11.  # distributed under the License is distributed on an "AS IS" BASIS,
  12.  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
  13.  # implied.  See the License for the specific language governing
  14.  # permissions and limitations under the License.
  15.  #
  16.  # Originally developed by Gregory Trubetskoy.
  17.  #
  18.  # $Id: apache.py,v 1.82 2004/02/16 19:47:27 grisha Exp $
  19.  
  20. import sys
  21. import traceback
  22. import time
  23. import os
  24. import pdb
  25. import stat
  26. import imp
  27. import types
  28. import _apache
  29.  
  30. # a small hack to improve PythonPath performance. This
  31. # variable stores the last PythonPath in raw (unevaled) form.
  32. _path = None
  33.  
  34. class CallBack:
  35.     """
  36.     A generic callback object.
  37.     """
  38.  
  39.     class HStack:
  40.         """
  41.         The actual stack string lives in the request object so
  42.         it can be manipulated by both apache.py and mod_python.c
  43.         """
  44.         
  45.         def __init__(self, req):
  46.             self.req = req
  47.  
  48.         def pop(self):
  49.  
  50.             handlers = self.req.hstack.split()
  51.  
  52.             if not handlers:
  53.                 return None
  54.             else:
  55.                 self.req.hstack = " ".join(handlers[1:])
  56.                 return handlers[0]
  57.  
  58.     def ConnectionDispatch(self, conn):
  59.  
  60.         # config
  61.         config = conn.base_server.get_config()
  62.         debug = int(config.get("PythonDebug", 0))
  63.  
  64.         try:
  65.  
  66.             handler = conn.hlist.handler
  67.  
  68.             # split module::handler
  69.             l = handler.split('::', 1)
  70.             module_name = l[0]
  71.             if len(l) == 1:
  72.                 # no oject, provide default
  73.                 object_str = "connectionhandler"
  74.             else:
  75.                 object_str = l[1]
  76.  
  77.             # add the directory to pythonpath if
  78.             # not there yet, or pythonpath specified
  79.  
  80.             if config.has_key("PythonPath"):
  81.                 # we want to do as little evaling as possible,
  82.                 # so we remember the path in un-evaled form and
  83.                 # compare it
  84.                 global _path
  85.                 pathstring = config["PythonPath"]
  86.                 if pathstring != _path:
  87.                     _path = pathstring
  88.                     newpath = eval(pathstring)
  89.                     if sys.path != newpath:
  90.                         sys.path[:] = newpath
  91.  
  92.             # import module
  93.             module = import_module(module_name,
  94.                                    autoreload=int(config.get("PythonAutoReload", 1)),
  95.                                    log=debug)
  96.             # find the object
  97.             object = resolve_object(module, object_str,
  98.                                     arg=conn, silent=0)
  99.  
  100.             if object:
  101.  
  102.                 # call the object
  103.                 if config.has_key("PythonEnablePdb"):
  104.                     result = pdb.runcall(object, conn)
  105.                 else:
  106.                     result = object(conn)
  107.  
  108.                 assert (type(result) == type(int())), \
  109.                        "ConnectionHandler '%s' returned invalid return code." % handler
  110.  
  111.         except PROG_TRACEBACK, traceblock:
  112.             # Program run-time error
  113.             try:
  114.                 (etype, value, traceback) = traceblock
  115.                 result = self.ReportError(etype, value, traceback, srv=conn.base_server,
  116.                                           phase="ConnectionHandler",
  117.                                           hname=handler, debug=debug)
  118.             finally:
  119.                 traceback = None
  120.  
  121.         except:
  122.             # Any other rerror (usually parsing)
  123.             try:
  124.                 exc_type, exc_value, exc_traceback = sys.exc_info()
  125.                 result = self.ReportError(exc_type, exc_value, exc_traceback, srv=conn.base_server,
  126.                                           phase="ConnectionHandler",
  127.                                           hname=handler, debug=debug)
  128.             finally:
  129.                 exc_traceback = None
  130.  
  131.     return result
  132.  
  133.     def FilterDispatch(self, filter):
  134.  
  135.         req = filter.req
  136.  
  137.         # config
  138.         config = req.get_config()
  139.         debug = int(config.get("PythonDebug", 0))
  140.  
  141.         try:
  142.  
  143.             # split module::handler
  144.             l = filter.handler.split('::', 1)
  145.             module_name = l[0]
  146.             if len(l) == 1:
  147.                 # no oject, provide default
  148.                 if filter.is_input:
  149.                     object_str = "inputfilter"
  150.                 else:
  151.                     object_str = "outputfilter"
  152.             else:
  153.                 object_str = l[1]
  154.  
  155.             # add the directory to pythonpath if
  156.             # not there yet, or pythonpath specified
  157.             
  158.             if config.has_key("PythonPath"):
  159.                 # we want to do as little evaling as possible,
  160.                 # so we remember the path in un-evaled form and
  161.                 # compare it
  162.                 global _path
  163.                 pathstring = config["PythonPath"]
  164.                 if pathstring != _path:
  165.                     _path = pathstring
  166.                     newpath = eval(pathstring)
  167.                     if sys.path != newpath:
  168.                         sys.path[:] = newpath
  169.             else:
  170.                 if filter.dir and (filter.dir not in sys.path):
  171.                     sys.path[:0] = [filter.dir]
  172.  
  173.             # import module
  174.             module = import_module(module_name,
  175.                                    autoreload=int(config.get("PythonAutoReload", 1)),
  176.                                    log=debug)
  177.  
  178.             # find the object
  179.             object = resolve_object(module, object_str, arg=filter, silent=0)
  180.  
  181.             if object:
  182.  
  183.                 # call the object
  184.                 if config.has_key("PythonEnablePdb"):
  185.                     pdb.runcall(object, filter)
  186.                 else:
  187.                     object(filter)
  188.  
  189.                 # always flush the filter. without a FLUSH or EOS bucket,
  190.                 # the content is never written to the network.
  191.                 # XXX an alternative is to tell the user to flush() always
  192.                 filter.flush()
  193.  
  194.         except SERVER_RETURN, value:
  195.             # SERVER_RETURN indicates a non-local abort from below
  196.             # with value as (result, status) or (result, None) or result
  197.             try:
  198.                 if len(value.args) == 2:
  199.                     (result, status) = value.args
  200.                     if status:
  201.                         req.status = status
  202.                 else:
  203.                     result = value.args[0]
  204.                     
  205.                 if type(result) != type(7):
  206.                     s = "Value raised with SERVER_RETURN is invalid. It is a "
  207.                     s = s + "%s, but it must be a tuple or an int." % type(result)
  208.                     _apache.log_error(s, APLOG_NOERRNO|APLOG_ERR, req.server)
  209.  
  210.                     return
  211.  
  212.             except:
  213.                 pass
  214.  
  215.         except PROG_TRACEBACK, traceblock:
  216.             # Program run-time error
  217.             try:
  218.                 (etype, value, traceback) = traceblock
  219.                 filter.disable()
  220.                 result = self.ReportError(etype, value, traceback, req=req, filter=filter,
  221.                                           phase="Filter: " + filter.name,
  222.                                           hname=filter.handler, debug=debug)
  223.             finally:
  224.                 traceback = None
  225.  
  226.         except:
  227.             # Any other rerror (usually parsing)
  228.             try:
  229.                 exc_type, exc_value, exc_traceback = sys.exc_info()
  230.                 filter.disable()
  231.                 result = self.ReportError(exc_type, exc_value, exc_traceback, req=req, filter=filter,
  232.                                           phase=filter.name, hname=filter.handler,
  233.                                           debug=debug)
  234.             finally:
  235.                 exc_traceback = None
  236.  
  237.     return OK
  238.  
  239.     def HandlerDispatch(self, req):
  240.         """
  241.         This is the handler dispatcher.
  242.         """
  243.  
  244.         # be cautious
  245.         result = HTTP_INTERNAL_SERVER_ERROR
  246.  
  247.         # config
  248.         config = req.get_config()
  249.         debug = int(config.get("PythonDebug", 0))
  250.  
  251.         try:
  252.             hlist = req.hlist
  253.  
  254.             while hlist.handler:
  255.  
  256.                 # split module::handler
  257.                 l = hlist.handler.split('::', 1)
  258.  
  259.                 module_name = l[0]
  260.                 if len(l) == 1:
  261.                     # no oject, provide default
  262.                     object_str = req.phase[len("python"):].lower()
  263.                 else:
  264.                     object_str = l[1]
  265.  
  266.                 # add the directory to pythonpath if
  267.                 # not there yet, or pythonpath specified
  268.                 if config.has_key("PythonPath"):
  269.                     # we want to do as little evaling as possible,
  270.                     # so we remember the path in un-evaled form and
  271.                     # compare it
  272.                     global _path
  273.                     pathstring = config["PythonPath"]
  274.                     if pathstring != _path:
  275.                         _path = pathstring
  276.                         newpath = eval(pathstring)
  277.                         if sys.path != newpath:
  278.                             sys.path[:] = newpath
  279.                 else:
  280.                     dir = hlist.directory
  281.                     if dir and (dir not in sys.path):
  282.                         sys.path[:0] = [dir]
  283.  
  284.                 # import module
  285.                 module = import_module(module_name,
  286.                                        autoreload=int(config.get("PythonAutoReload", 1)),
  287.                                        log=debug)
  288.  
  289.                 # find the object
  290.                 object = resolve_object(module, object_str,
  291.                                         arg=req, silent=hlist.silent)
  292.  
  293.                 if object:
  294.  
  295.                     # call the object
  296.                     if config.has_key("PythonEnablePdb"):
  297.                         result = pdb.runcall(object, req)
  298.                     else:
  299.                         result = object(req)
  300.  
  301.                     assert (type(result) == type(int())), \
  302.                            "Handler '%s' returned invalid return code." % hlist.handler
  303.  
  304.                     # stop cycling through handlers
  305.                     if result != OK:
  306.                         break
  307.                     
  308.                 elif hlist.silent:
  309.                     result = DECLINED
  310.  
  311.                 hlist.next()
  312.  
  313.         except SERVER_RETURN, value:
  314.             # SERVER_RETURN indicates an abort from below
  315.             # with value as (result, status) or (result, None) or result
  316.             try:
  317.                 if len(value.args) == 2:
  318.                     (result, status) = value.args
  319.                     if status:
  320.                         req.status = status
  321.                 else:
  322.                     result = value.args[0]
  323.                     
  324.                 if type(result) != type(7):
  325.                     s = "Value raised with SERVER_RETURN is invalid. It is a "
  326.                     s = s + "%s, but it must be a tuple or an int." % type(result)
  327.                     _apache.log_error(s, APLOG_NOERRNO|APLOG_ERR, req.server)
  328.                     return HTTP_INTERNAL_SERVER_ERROR
  329.  
  330.             except:
  331.                 pass
  332.  
  333.         except PROG_TRACEBACK, traceblock:
  334.             # Program run-time error
  335.             try:
  336.                 (etype, value, traceback) = traceblock
  337.                 result = self.ReportError(etype, value, traceback, req=req,
  338.                                           phase=req.phase, hname=hlist.handler,
  339.                                           debug=debug)
  340.             finally:
  341.                 traceback = None
  342.  
  343.         except:
  344.             # Any other rerror (usually parsing)
  345.             try:
  346.                 exc_type, exc_value, exc_traceback = sys.exc_info()
  347.                 result = self.ReportError(exc_type, exc_value, exc_traceback, req=req,
  348.                                           phase=req.phase, hname=hlist.handler, debug=debug)
  349.             finally:
  350.                 exc_traceback = None
  351.  
  352.     return result
  353.  
  354.  
  355.     def ReportError(self, etype, evalue, etb, req=None, filter=None, srv=None,
  356.                     phase="N/A", hname="N/A", debug=0):
  357.     """ 
  358.     This function is only used when debugging is on.
  359.     It sends the output similar to what you'd see
  360.     when using Python interactively to the browser
  361.     """
  362.  
  363.         try:       # try/finally
  364.             try:        # try/except
  365.  
  366.                 if str(etype) == "exceptions.IOError" \
  367.                    and str(evalue)[:5] == "Write":
  368.                     # if this is an IOError while writing to client,
  369.                     # it is probably better not to try to write to the cleint
  370.                     # even if debug is on.
  371.                     debug = 0
  372.  
  373.                 # write to log
  374.                 for e in traceback.format_exception(etype, evalue, etb):
  375.                     s = "%s %s: %s" % (phase, hname, e[:-1])
  376.                     if req:
  377.                         req.log_error(s, APLOG_NOERRNO|APLOG_ERR)
  378.                     else:
  379.                         _apache.log_error(s, APLOG_NOERRNO|APLOG_ERR, srv)
  380.  
  381.                 if not debug or not req:
  382.                     return HTTP_INTERNAL_SERVER_ERROR
  383.                 else:
  384.                     # write to client
  385.                     req.content_type = 'text/html'
  386.  
  387.                     s = '\n<pre>\nMod_python error: "%s %s"\n\n' % (phase, hname)
  388.                     for e in traceback.format_exception(etype, evalue, etb):
  389.                         s = s + e + '\n'
  390.                     s = s + "</pre>\n"
  391.                         
  392.                     if filter:
  393.                         filter.write(s)
  394.                         filter.flush()
  395.                     else:
  396.                         req.write(s)
  397.  
  398.                     return DONE
  399.             except:
  400.                 # last try
  401.                 traceback.print_exc()
  402.  
  403.         finally:
  404.             # erase the traceback
  405.             etb = None
  406.             # we do not return anything
  407.  
  408. def import_module(module_name, autoreload=1, log=0, path=None):
  409.     """
  410.     Get the module to handle the request. If
  411.     autoreload is on, then the module will be reloaded
  412.     if it has changed since the last import.
  413.     """
  414.  
  415.     # (Re)import
  416.     if sys.modules.has_key(module_name):
  417.  
  418.         # The module has been imported already
  419.         module = sys.modules[module_name]
  420.  
  421.         # but is it in the path?
  422.         file = module.__dict__.get("__file__")
  423.  
  424.         # the "and not" part of this condition is to prevent execution
  425.         # of arbitrary already imported modules, such as os. The
  426.         # reason we use startswith as opposed to exact match is that
  427.         # modules inside packages are actually in subdirectories.
  428.  
  429.         if not file or (path and not filter(file.startswith, path)):
  430.             # there is a script by this name already imported, but it's in
  431.             # a different directory, therefore it's a different script
  432.             mtime, oldmtime = 0, -1
  433.         elif autoreload: 
  434.             oldmtime = module.__dict__.get("__mtime__", 0)
  435.             mtime = module_mtime(module)
  436.         else:
  437.             mtime, oldmtime = 0, 0
  438.  
  439.     else:
  440.         mtime, oldmtime = 0, -1
  441.  
  442.     if mtime > oldmtime:
  443.  
  444.         # Import the module
  445.         if log:
  446.             if path:
  447.                 s = "mod_python: (Re)importing module '%s' with path set to '%s'" % (module_name, path)
  448.             else:
  449.                 s = "mod_python: (Re)importing module '%s'" % module_name
  450.             _apache.log_error(s, APLOG_NOERRNO|APLOG_NOTICE)
  451.  
  452.         parts = module_name.split('.')
  453.         for i in range(len(parts)):
  454.             f, p, d = imp.find_module(parts[i], path)
  455.             try:
  456.                 mname = ".".join(parts[:i+1])
  457.                 module = imp.load_module(mname, f, p, d)
  458.             finally:
  459.                 if f: f.close()
  460.             if hasattr(module, "__path__"):
  461.                 path = module.__path__
  462.  
  463.         if mtime == 0:
  464.             mtime = module_mtime(module)
  465.  
  466.         module.__mtime__ = mtime
  467.  
  468.     return module
  469.  
  470. def module_mtime(module):
  471.     """Get modification time of module"""
  472.     mtime = 0
  473.     if module.__dict__.has_key("__file__"):
  474.         
  475.        filepath = module.__file__
  476.        
  477.        try:
  478.            # this try/except block is a workaround for a Python bug in
  479.            # 2.0, 2.1 and 2.1.1. See
  480.            # http://sourceforge.net/tracker/?group_id=5470&atid=105470&func=detail&aid=422004
  481.  
  482.            if os.path.exists(filepath):
  483.                mtime = os.path.getmtime(filepath)
  484.  
  485.            if os.path.exists(filepath[:-1]) :
  486.                mtime = max(mtime, os.path.getmtime(filepath[:-1]))
  487.  
  488.        except OSError: pass
  489.  
  490.     return mtime
  491.  
  492. def resolve_object(module, object_str, arg=None, silent=0):
  493.     """
  494.     This function traverses the objects separated by .
  495.     (period) to find the last one we're looking for:
  496.  
  497.        From left to right, find objects, if it is
  498.        an unbound method of a class, instantiate the
  499.        class passing the request as single argument
  500.  
  501.     'arg' is sometimes req, sometimes filter,
  502.     sometimes connection
  503.     """
  504.  
  505.     obj = module
  506.  
  507.     for obj_str in  object_str.split('.'):
  508.  
  509.         parent = obj
  510.  
  511.         # don't throw attribute errors when silent
  512.         if silent and not hasattr(obj, obj_str):
  513.             return None
  514.  
  515.         # this adds a little clarity if we have an attriute error
  516.         if obj == module and not hasattr(module, obj_str):
  517.             if hasattr(module, "__file__"):
  518.                 s = "module '%s' contains no '%s'" % (module.__file__, obj_str)
  519.                 raise AttributeError, s
  520.  
  521.         obj = getattr(obj, obj_str)
  522.  
  523.         if hasattr(obj, "im_self") and not obj.im_self:
  524.             # this is an unbound method, its class
  525.             # needs to be instantiated
  526.             instance = parent(arg)
  527.             obj = getattr(instance, obj_str)
  528.  
  529.     return obj
  530.  
  531. def build_cgi_env(req):
  532.     """
  533.     Utility function that returns a dictionary of
  534.     CGI environment variables as described in
  535.     http://hoohoo.ncsa.uiuc.edu/cgi/env.html
  536.     """
  537.  
  538.     req.add_common_vars()
  539.     env = req.subprocess_env.copy()
  540.         
  541.     if len(req.path_info) > 0:
  542.         env["SCRIPT_NAME"] = req.uri[:-len(req.path_info)]
  543.     else:
  544.         env["SCRIPT_NAME"] = req.uri
  545.  
  546.     env["GATEWAY_INTERFACE"] = "Python-CGI/1.1"
  547.  
  548.     # you may want to comment this out for better security
  549.     if req.headers_in.has_key("authorization"):
  550.         env["HTTP_AUTHORIZATION"] = req.headers_in["authorization"]
  551.  
  552.     return env
  553.  
  554. class NullIO:
  555.     """ Abstract IO
  556.     """
  557.     def tell(self): return 0
  558.     def read(self, n = -1): return ""
  559.     def readline(self, length = None): return ""
  560.     def readlines(self): return []
  561.     def write(self, s): pass
  562.     def writelines(self, list):
  563.         self.write("".join(list))
  564.     def isatty(self): return 0
  565.     def flush(self): pass
  566.     def close(self): pass
  567.     def seek(self, pos, mode = 0): pass
  568.  
  569. class CGIStdin(NullIO):
  570.  
  571.     def __init__(self, req):
  572.         self.pos = 0
  573.         self.req = req
  574.         self.BLOCK = 65536 # 64K
  575.         # note that self.buf sometimes contains leftovers
  576.         # that were read, but not used when readline was used
  577.         self.buf = ""
  578.  
  579.     def read(self, n = -1):
  580.         if n == 0:
  581.             return ""
  582.         if n == -1:
  583.             s = self.req.read(self.BLOCK)
  584.             while s:
  585.                 self.buf = self.buf + s
  586.                 self.pos = self.pos + len(s)
  587.                 s = self.req.read(self.BLOCK)
  588.             result = self.buf
  589.             self.buf = ""
  590.             return result
  591.         else:
  592.             if self.buf:
  593.                 s = self.buf[:n]
  594.                 n = n - len(s)
  595.             else:
  596.                 s = ""
  597.             s = s + self.req.read(n)
  598.             self.pos = self.pos + len(s)
  599.             return s
  600.  
  601.     def readlines(self):
  602.         s = (self.buf + self.read()).split('\n')
  603.         return map(lambda s: s + '\n', s)
  604.  
  605.     def readline(self, n = -1):
  606.  
  607.         if n == 0:
  608.             return ""
  609.  
  610.         # fill up the buffer
  611.         self.buf = self.buf + self.req.read(self.BLOCK)
  612.  
  613.         # look for \n in the buffer
  614.         i = self.buf.find('\n')
  615.         while i == -1: # if \n not found - read more
  616.             if (n != -1) and (len(self.buf) >= n): # we're past n
  617.                 i = n - 1
  618.                 break
  619.             x = len(self.buf)
  620.             self.buf = self.buf + self.req.read(self.BLOCK)
  621.             if len(self.buf) == x: # nothing read, eof
  622.                 i = x - 1
  623.                 break 
  624.             i = self.buf.find('\n', x)
  625.         
  626.         # carve out the piece, then shorten the buffer
  627.         result = self.buf[:i+1]
  628.         self.buf = self.buf[i+1:]
  629.         self.pos = self.pos + len(result)
  630.         return result
  631.         
  632.  
  633. class CGIStdout(NullIO):
  634.  
  635.     """
  636.     Class that allows writing to the socket directly for CGI.
  637.     """
  638.     
  639.     def __init__(self, req):
  640.         self.pos = 0
  641.         self.req = req
  642.         self.headers_sent = 0
  643.         self.headers = ""
  644.         
  645.     def write(self, s):
  646.  
  647.         if not s: return
  648.  
  649.         if not self.headers_sent:
  650.             self.headers = self.headers + s
  651.  
  652.             # are headers over yet?
  653.             headers_over = 0
  654.  
  655.             # first try RFC-compliant CRLF
  656.             ss = self.headers.split('\r\n\r\n', 1)
  657.             if len(ss) < 2:
  658.                 # second try with \n\n
  659.                 ss = self.headers.split('\n\n', 1)
  660.                 if len(ss) >= 2:
  661.                     headers_over = 1
  662.             else:
  663.                 headers_over = 1
  664.                     
  665.             if headers_over:
  666.                 # headers done, process them
  667.                 ss[0] = ss[0].replace('\r\n', '\n')
  668.                 lines = ss[0].split('\n')
  669.                 for line in lines:
  670.                     h, v = line.split(":", 1)
  671.                     v = v.strip()
  672.                     if h.lower() == "status":
  673.                         status = int(v.split()[0])
  674.                         self.req.status = status
  675.                     elif h.lower() == "content-type":
  676.                         self.req.content_type = v
  677.                         self.req.headers_out[h] = v
  678.                     else:
  679.                         self.req.headers_out.add(h, v)
  680.  
  681.                 self.headers_sent = 1
  682.  
  683.                 # write the body if any at this point
  684.                 self.req.write(ss[1])
  685.         else:
  686.             self.req.write(str(s))
  687.         
  688.         self.pos = self.pos + len(s)
  689.  
  690.     def tell(self): return self.pos
  691.  
  692. def setup_cgi(req):
  693.     """
  694.     Replace sys.stdin and stdout with an objects that read/write to
  695.     the socket, as well as substitute the os.environ.
  696.     Returns (environ, stdin, stdout) which you must save and then use
  697.     with restore_nocgi().
  698.     """
  699.  
  700.     # save env
  701.     save_env = os.environ.copy()
  702.     
  703.     si = sys.stdin
  704.     so = sys.stdout
  705.  
  706.     os.environ.update(build_cgi_env(req))
  707.  
  708.     sys.stdout = CGIStdout(req)
  709.     sys.stdin = CGIStdin(req)
  710.  
  711.     sys.argv = [] # keeps cgi.py happy
  712.  
  713.     return save_env, si, so
  714.         
  715. def restore_nocgi(sav_env, si, so):
  716.     """ see setup_cgi() """
  717.  
  718.     osenv = os.environ
  719.  
  720.     # restore env
  721.     for k in osenv.keys():
  722.         del osenv[k]
  723.     for k in sav_env:
  724.         osenv[k] = sav_env[k]
  725.  
  726.     sys.stdout = si
  727.     sys.stdin = so
  728.  
  729. def init():
  730.     """ 
  731.         This function is called by the server at startup time
  732.     """
  733.  
  734.     return CallBack()
  735.  
  736. ## Some functions made public
  737. make_table = _apache.table
  738. log_error = _apache.log_error
  739. table = _apache.table
  740. config_tree = _apache.config_tree
  741. server_root = _apache.server_root
  742. mpm_query = _apache.mpm_query
  743.  
  744. ## Some constants
  745.  
  746. HTTP_CONTINUE                     = 100
  747. HTTP_SWITCHING_PROTOCOLS          = 101
  748. HTTP_PROCESSING                   = 102
  749. HTTP_OK                           = 200
  750. HTTP_CREATED                      = 201
  751. HTTP_ACCEPTED                     = 202
  752. HTTP_NON_AUTHORITATIVE            = 203
  753. HTTP_NO_CONTENT                   = 204
  754. HTTP_RESET_CONTENT                = 205
  755. HTTP_PARTIAL_CONTENT              = 206
  756. HTTP_MULTI_STATUS                 = 207
  757. HTTP_MULTIPLE_CHOICES             = 300
  758. HTTP_MOVED_PERMANENTLY            = 301
  759. HTTP_MOVED_TEMPORARILY            = 302
  760. HTTP_SEE_OTHER                    = 303
  761. HTTP_NOT_MODIFIED                 = 304
  762. HTTP_USE_PROXY                    = 305
  763. HTTP_TEMPORARY_REDIRECT           = 307
  764. HTTP_BAD_REQUEST                  = 400
  765. HTTP_UNAUTHORIZED                 = 401
  766. HTTP_PAYMENT_REQUIRED             = 402
  767. HTTP_FORBIDDEN                    = 403
  768. HTTP_NOT_FOUND                    = 404
  769. HTTP_METHOD_NOT_ALLOWED           = 405
  770. HTTP_NOT_ACCEPTABLE               = 406
  771. HTTP_PROXY_AUTHENTICATION_REQUIRED= 407
  772. HTTP_REQUEST_TIME_OUT             = 408
  773. HTTP_CONFLICT                     = 409
  774. HTTP_GONE                         = 410
  775. HTTP_LENGTH_REQUIRED              = 411
  776. HTTP_PRECONDITION_FAILED          = 412
  777. HTTP_REQUEST_ENTITY_TOO_LARGE     = 413
  778. HTTP_REQUEST_URI_TOO_LARGE        = 414
  779. HTTP_UNSUPPORTED_MEDIA_TYPE       = 415
  780. HTTP_RANGE_NOT_SATISFIABLE        = 416
  781. HTTP_EXPECTATION_FAILED           = 417
  782. HTTP_UNPROCESSABLE_ENTITY         = 422
  783. HTTP_LOCKED                       = 423
  784. HTTP_FAILED_DEPENDENCY            = 424
  785. HTTP_INTERNAL_SERVER_ERROR        = 500
  786. HTTP_NOT_IMPLEMENTED              = 501
  787. HTTP_BAD_GATEWAY                  = 502
  788. HTTP_SERVICE_UNAVAILABLE          = 503
  789. HTTP_GATEWAY_TIME_OUT             = 504
  790. HTTP_VERSION_NOT_SUPPORTED        = 505
  791. HTTP_VARIANT_ALSO_VARIES          = 506
  792. HTTP_INSUFFICIENT_STORAGE         = 507
  793. HTTP_NOT_EXTENDED                 = 510
  794.  
  795. # The APLOG constants in Apache are derived from syslog.h
  796. # constants, so we do same here.
  797.  
  798. try:
  799.     import syslog
  800.     APLOG_EMERG = syslog.LOG_EMERG     # system is unusable
  801.     APLOG_ALERT = syslog.LOG_ALERT     # action must be taken immediately
  802.     APLOG_CRIT = syslog.LOG_CRIT       # critical conditions
  803.     APLOG_ERR = syslog.LOG_ERR         # error conditions 
  804.     APLOG_WARNING = syslog.LOG_WARNING # warning conditions
  805.     APLOG_NOTICE = syslog.LOG_NOTICE   # normal but significant condition
  806.     APLOG_INFO = syslog.LOG_INFO       # informational
  807.     APLOG_DEBUG = syslog.LOG_DEBUG     # debug-level messages
  808. except ImportError:
  809.     APLOG_EMERG = 0
  810.     APLOG_ALERT = 1
  811.     APLOG_CRIT = 2
  812.     APLOG_ERR = 3
  813.     APLOG_WARNING = 4
  814.     APLOG_NOTICE = 5
  815.     APLOG_INFO = 6
  816.     APLOG_DEBUG = 7
  817.     
  818. APLOG_NOERRNO = 8
  819.  
  820. OK = REQ_PROCEED = 0
  821. DONE = -2
  822. DECLINED = REQ_NOACTION = -1
  823.  
  824. # constants for get_remote_host
  825. REMOTE_HOST = 0
  826. REMOTE_NAME = 1
  827. REMOTE_NOLOOKUP = 2
  828. REMOTE_DOUBLE_REV = 3
  829.  
  830. # legacy/mod_python things
  831. REQ_ABORTED = HTTP_INTERNAL_SERVER_ERROR
  832. REQ_EXIT = "REQ_EXIT"         
  833. SERVER_RETURN = _apache.SERVER_RETURN
  834. PROG_TRACEBACK = "PROG_TRACEBACK"
  835.  
  836. # the req.finfo tuple
  837. FINFO_MODE = 0
  838. FINFO_INO = 1
  839. FINFO_DEV = 2
  840. FINFO_NLINK = 3
  841. FINFO_UID = 4
  842. FINFO_GID = 5
  843. FINFO_SIZE = 6
  844. FINFO_ATIME = 7
  845. FINFO_MTIME = 8
  846. FINFO_CTIME = 9
  847. FINFO_FNAME = 10
  848. FINFO_NAME = 11
  849. #FINFO_FILEHAND = 14
  850.  
  851. # the req.parsed_uri
  852. URI_SCHEME = 0
  853. URI_HOSTINFO = 1
  854. URI_USER = 2
  855. URI_PASSWORD = 3
  856. URI_HOSTNAME = 4
  857. URI_PORT = 5
  858. URI_PATH = 6
  859. URI_QUERY = 7
  860. URI_FRAGMENT = 8
  861.  
  862. # for req.proxyreq
  863. PROXYREQ_NONE = 0       # No proxy
  864. PROXYREQ_PROXY = 1    # Standard proxy
  865. PROXYREQ_REVERSE = 2    # Reverse proxy
  866.  
  867. # methods for req.allow_method()
  868. M_GET = 0               # RFC 2616: HTTP
  869. M_PUT = 1
  870. M_POST = 2
  871. M_DELETE = 3
  872. M_CONNECT = 4
  873. M_OPTIONS = 5
  874. M_TRACE = 6             # RFC 2616: HTTP
  875. M_PATCH = 7 
  876. M_PROPFIND = 8          # RFC 2518: WebDAV
  877. M_PROPPATCH = 9         
  878. M_MKCOL = 10
  879. M_COPY = 11
  880. M_MOVE = 12
  881. M_LOCK = 13
  882. M_UNLOCK = 14           # RFC2518: WebDAV
  883. M_VERSION_CONTROL = 15  # RFC3253: WebDAV Versioning
  884. M_CHECKOUT = 16
  885. M_UNCHECKOUT = 17
  886. M_CHECKIN = 18
  887. M_UPDATE = 19
  888. M_LABEL = 20
  889. M_REPORT = 21
  890. M_MKWORKSPACE = 22
  891. M_MKACTIVITY = 23
  892. M_BASELINE_CONTROL = 24
  893. M_MERGE = 25
  894. M_INVALID = 26           # RFC3253: WebDAV Versioning
  895.  
  896. # for req.used_path_info
  897. AP_REQ_ACCEPT_PATH_INFO = 0  # Accept request given path_info
  898. AP_REQ_REJECT_PATH_INFO = 1  # Send 404 error if path_info was given
  899. AP_REQ_DEFAULT_PATH_INFO = 2 # Module's choice for handling path_info
  900.  
  901.  
  902. # for mpm_query
  903. AP_MPMQ_NOT_SUPPORTED      = 0  # This value specifies whether 
  904.                                 # an MPM is capable of         
  905.                                 # threading or forking.        
  906. AP_MPMQ_STATIC             = 1  # This value specifies whether 
  907.                                 # an MPM is using a static # of
  908.                                 # threads or daemons.          
  909. AP_MPMQ_DYNAMIC            = 2  # This value specifies whether 
  910.                                 # an MPM is using a dynamic # of
  911.                                 # threads or daemons.          
  912.  
  913. AP_MPMQ_MAX_DAEMON_USED    = 1  # Max # of daemons used so far 
  914. AP_MPMQ_IS_THREADED        = 2  # MPM can do threading         
  915. AP_MPMQ_IS_FORKED          = 3  # MPM can do forking           
  916. AP_MPMQ_HARD_LIMIT_DAEMONS = 4  # The compiled max # daemons   
  917. AP_MPMQ_HARD_LIMIT_THREADS = 5  # The compiled max # threads   
  918. AP_MPMQ_MAX_THREADS        = 6  # # of threads/child by config 
  919. AP_MPMQ_MIN_SPARE_DAEMONS  = 7  # Min # of spare daemons       
  920. AP_MPMQ_MIN_SPARE_THREADS  = 8  # Min # of spare threads       
  921. AP_MPMQ_MAX_SPARE_DAEMONS  = 9  # Max # of spare daemons       
  922. AP_MPMQ_MAX_SPARE_THREADS  = 10 # Max # of spare threads       
  923. AP_MPMQ_MAX_REQUESTS_DAEMON= 11 # Max # of requests per daemon 
  924. AP_MPMQ_MAX_DAEMONS        = 12 # Max # of daemons by config   
  925.                                                                                                                                                                                                                                     
  926.