This file is indexed.

/usr/share/pyshared/scgi/quixote_handler.py is in python-scgi 1.13-1.1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
"""
A SCGI handler that uses Quixote to publish dynamic content.
"""

import sys
import time
import os
import getopt
import signal
from quixote import enable_ptl, publish
import scgi_server

pidfilename = None # set by main()

def debug(msg):
    timestamp = time.strftime("%Y-%m-%d %H:%M:%S",
                              time.localtime(time.time()))
    sys.stderr.write("[%s] %s\n" % (timestamp, msg))


class QuixoteHandler(scgi_server.SCGIHandler):

    # override in subclass
    publisher_class = publish.Publisher
    root_namespace = None
    prefix = ""

    def __init__(self, *args, **kwargs):
        debug("%s created" % self.__class__.__name__)
        scgi_server.SCGIHandler.__init__(self, *args, **kwargs)
        assert self.root_namespace, "You must provide a namespace to publish"
        self.publisher = self.publisher_class(self.root_namespace)

    def handle_connection (self, conn):
        input = conn.makefile("r")
        output = conn.makefile("w")

        env = self.read_env(input)

        # mod_scgi never passes PATH_INFO, fake it
        prefix = self.prefix
        path = env['SCRIPT_NAME']
        assert path[:len(prefix)] == prefix, (
                "path %r doesn't start with prefix %r" % (path, prefix))
        env['SCRIPT_NAME'] = prefix
        env['PATH_INFO'] = path[len(prefix):] + env.get('PATH_INFO', '')

        self.publisher.publish(input, output, sys.stderr, env)

        try:
            input.close()
            output.close()
            conn.close()
        except IOError, err:
            debug("IOError while closing connection ignored: %s" % err)

        if self.publisher.config.run_once:
            sys.exit(0)


class DemoHandler(QuixoteHandler):

    root_namespace = "quixote.demo"
    prefix = "/dynamic" # must match Location directive

    def __init__(self, *args, **kwargs):
        enable_ptl()
        QuixoteHandler.__init__(self, *args, **kwargs)


def change_uid_gid(uid, gid=None):
    "Try to change UID and GID to the provided values"
    # This will only work if this script is run by root.

    # Try to convert uid and gid to integers, in case they're numeric
    import pwd, grp
    try:
        uid = int(uid)
        default_grp = pwd.getpwuid(uid)[3]
    except ValueError:
        uid, default_grp = pwd.getpwnam(uid)[2:4]

    if gid is None:
        gid = default_grp
    else:
        try:
            gid = int(gid)
        except ValueError:
            gid = grp.getgrnam(gid)[2]

    os.setgid(gid)
    os.setuid(uid)


def term_signal(signum, frame):
    global pidfilename
    try:
        os.unlink(pidfilename)
    except OSError:
        pass
    sys.exit()

def main(handler=DemoHandler):
    usage = """Usage: %s [options]

    -F -- stay in foreground (don't fork)
    -P -- PID filename
    -l -- log filename
    -m -- max children
    -p -- TCP port to listen on
    -u -- user id to run under
    """ % sys.argv[0]
    nofork = 0
    global pidfilename
    pidfilename = "/var/tmp/quixote-scgi.pid"
    logfilename = "/var/tmp/quixote-scgi.log"
    max_children = 5    # scgi default
    uid = "nobody"
    port = 4000
    host = "127.0.0.1"
    try:
        opts, args = getopt.getopt(sys.argv[1:], 'FP:l:m:p:u:')
    except getopt.GetoptError, exc:
        print >>sys.stderr, exc
        print >>sys.stderr, usage
        sys.exit(1)
    for o, v in opts:
        if o == "-F":
            nofork = 1
        elif o == "-P":
            pidfilename = v
        elif o == "-l":
            logfilename = v
        elif o == "-m":
            max_children = int(v)
        elif o == "-p":
            port = int(v)
        elif o == "-u":
            uid = v

    log = open(logfilename, "a", 1)
    os.dup2(log.fileno(), 1)
    os.dup2(log.fileno(), 2)
    os.close(0)

    if os.getuid() == 0:
        change_uid_gid(uid)

    if nofork:
        scgi_server.SCGIServer(handler, host=host, port=port,
                               max_children=max_children).serve()
    else:
        pid = os.fork()
        if pid == 0:
            pid = os.getpid()
            pidfile = open(pidfilename, 'w')
            pidfile.write(str(pid))
            pidfile.close()
            signal.signal(signal.SIGTERM, term_signal)
            try:
                scgi_server.SCGIServer(handler, host=host, port=port,
                                       max_children=max_children).serve()
            finally:
                # grandchildren get here too, don't let them unlink the pid
                if pid == os.getpid():
                    try:
                        os.unlink(pidfilename)
                    except OSError:
                        pass

if __name__ == '__main__':
    main()