This file is indexed.

/usr/share/pyshared/allmydata/web/operations.py is in tahoe-lafs 1.9.2-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
import time
from zope.interface import implements
from nevow import rend, url, tags as T
from nevow.inevow import IRequest
from twisted.python.failure import Failure
from twisted.internet import reactor, defer
from twisted.web.http import NOT_FOUND
from twisted.web.html import escape
from twisted.application import service

from allmydata.web.common import IOpHandleTable, WebError, \
     get_root, get_arg, boolean_of_arg

MINUTE = 60
HOUR = 60*MINUTE
DAY = 24*HOUR

(MONITOR, RENDERER, WHEN_ADDED) = range(3)

class OphandleTable(rend.Page, service.Service):
    implements(IOpHandleTable)

    UNCOLLECTED_HANDLE_LIFETIME = 4*DAY
    COLLECTED_HANDLE_LIFETIME = 1*DAY

    def __init__(self, clock=None):
        # both of these are indexed by ophandle
        self.handles = {} # tuple of (monitor, renderer, when_added)
        self.timers = {}
        # The tests will provide a deterministic clock
        # (twisted.internet.task.Clock) that they can control so that
        # they can test ophandle expiration. If this is provided, I'll
        # use it schedule the expiration of ophandles.
        self.clock = clock

    def stopService(self):
        for t in self.timers.values():
            if t.active():
                t.cancel()
        del self.handles # this is not restartable
        del self.timers
        return service.Service.stopService(self)

    def add_monitor(self, ctx, monitor, renderer):
        ophandle = get_arg(ctx, "ophandle")
        assert ophandle
        now = time.time()
        self.handles[ophandle] = (monitor, renderer, now)
        retain_for = get_arg(ctx, "retain-for", None)
        if retain_for is not None:
            self._set_timer(ophandle, int(retain_for))
        monitor.when_done().addBoth(self._operation_complete, ophandle)

    def _operation_complete(self, res, ophandle):
        if ophandle in self.handles:
            if ophandle not in self.timers:
                # the client has not provided a retain-for= value for this
                # handle, so we set our own.
                now = time.time()
                added = self.handles[ophandle][WHEN_ADDED]
                when = max(self.UNCOLLECTED_HANDLE_LIFETIME, now - added)
                self._set_timer(ophandle, when)
            # if we already have a timer, the client must have provided the
            # retain-for= value, so don't touch it.

    def redirect_to(self, ctx):
        ophandle = get_arg(ctx, "ophandle")
        assert ophandle
        target = get_root(ctx) + "/operations/" + ophandle
        output = get_arg(ctx, "output")
        if output:
            target = target + "?output=%s" % output
        return url.URL.fromString(target)

    def childFactory(self, ctx, name):
        ophandle = name
        if ophandle not in self.handles:
            raise WebError("unknown/expired handle '%s'" % escape(ophandle),
                           NOT_FOUND)
        (monitor, renderer, when_added) = self.handles[ophandle]

        request = IRequest(ctx)
        t = get_arg(ctx, "t", "status")
        if t == "cancel" and request.method == "POST":
            monitor.cancel()
            # return the status anyways, but release the handle
            self._release_ophandle(ophandle)

        else:
            retain_for = get_arg(ctx, "retain-for", None)
            if retain_for is not None:
                self._set_timer(ophandle, int(retain_for))

            if monitor.is_finished():
                if boolean_of_arg(get_arg(ctx, "release-after-complete", "false")):
                    self._release_ophandle(ophandle)
                if retain_for is None:
                    # this GET is collecting the ophandle, so change its timer
                    self._set_timer(ophandle, self.COLLECTED_HANDLE_LIFETIME)

        status = monitor.get_status()
        if isinstance(status, Failure):
            return defer.fail(status)

        return renderer

    def _set_timer(self, ophandle, when):
        if ophandle in self.timers and self.timers[ophandle].active():
            self.timers[ophandle].cancel()
        if self.clock:
            t = self.clock.callLater(when, self._release_ophandle, ophandle)
        else:
            t = reactor.callLater(when, self._release_ophandle, ophandle)
        self.timers[ophandle] = t

    def _release_ophandle(self, ophandle):
        if ophandle in self.timers and self.timers[ophandle].active():
            self.timers[ophandle].cancel()
        self.timers.pop(ophandle, None)
        self.handles.pop(ophandle, None)

class ReloadMixin:
    REFRESH_TIME = 1*MINUTE

    def render_refresh(self, ctx, data):
        if self.monitor.is_finished():
            return ""
        # dreid suggests ctx.tag(**dict([("http-equiv", "refresh")]))
        # but I can't tell if he's joking or not
        ctx.tag.attributes["http-equiv"] = "refresh"
        ctx.tag.attributes["content"] = str(self.REFRESH_TIME)
        return ctx.tag

    def render_reload(self, ctx, data):
        if self.monitor.is_finished():
            return ""
        req = IRequest(ctx)
        # url.gethere would break a proxy, so the correct thing to do is
        # req.path[-1] + queryargs
        ophandle = req.prepath[-1]
        reload_target = ophandle + "?output=html"
        cancel_target = ophandle + "?t=cancel"
        cancel_button = T.form(action=cancel_target, method="POST",
                               enctype="multipart/form-data")[
            T.input(type="submit", value="Cancel"),
            ]

        return [T.h2["Operation still running: ",
                     T.a(href=reload_target)["Reload"],
                     ],
                cancel_button,
                ]