This file is indexed.

/usr/lib/python3/dist-packages/crank/restdispatcher.py is in python3-crank 0.7.2-3.

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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
"""
This module contains the RestDispatcher implementation

Rest controller provides a RESTful dispatch mechanism, and
combines controller decoration for TG-Controller behavior.
"""
from inspect import ismethod
from webob.exc import HTTPMethodNotAllowed
from crank.util import get_argspec, method_matches_args
from crank.objectdispatcher import ObjectDispatcher

class RestDispatcher(ObjectDispatcher):
    """Defines a restful interface for a set of HTTP verbs.
    Please see RestController for a rundown of the controller
    methods used.
    """

    def _find_first_exposed(self, controller, methods):
        for method in methods:
            if self._is_exposed(controller, method):
                return getattr(controller, method)

    def _handle_put_or_post(self, http_method, state, remainder):
        current_controller = state.controller
        if remainder:
            current_path = remainder[0]
            if self._is_exposed(current_controller, current_path):
                state.add_method(getattr(current_controller, current_path), remainder[1:])
                return state

            if self._is_controller(current_controller, current_path):
                current_controller = getattr(current_controller, current_path)
                return self._dispatch_controller(current_path, current_controller, state, remainder[1:])

        method = self._find_first_exposed(current_controller, [http_method])
        if method and method_matches_args(method, state.params, remainder, self._use_lax_params):
            state.add_method(method, remainder)
            return state

        return self._dispatch_first_found_default_or_lookup(state, remainder)

    def _handle_delete(self, http_method, state, remainder):
        current_controller = state.controller
        method = self._find_first_exposed(current_controller, ('post_delete', 'delete'))

        if method and method_matches_args(method, state.params, remainder, self._use_lax_params):
            state.add_method(method, remainder)
            return state

        #you may not send a delete request to a non-delete function
        if remainder and self._is_exposed(current_controller, remainder[0]):
            raise HTTPMethodNotAllowed

        # there might be a sub-controller with a delete method, let's go see
        if remainder:
            sub_controller = getattr(current_controller, remainder[0], None)
            if sub_controller:
                remainder = remainder[1:]
                state.current_controller = sub_controller
                state.path = remainder
                r = self._dispatch_controller(remainder[0], sub_controller, state, remainder)
                if r:
                    return r
        return self._dispatch_first_found_default_or_lookup(state, remainder)

    def _check_for_sub_controllers(self, state, remainder):
        current_controller = state.controller
        method = None
        for find in ('get_one', 'get'):
            if hasattr(current_controller, find):
                method = find
                break

        if method is None:
            return

        fixed_args, var_args, kws, kw_args = get_argspec(getattr(current_controller, method))
        fixed_arg_length = len(fixed_args)
        if var_args:
            for i, item in enumerate(remainder):
                item = state.path_translator(item)
                if hasattr(current_controller, item) and self._is_controller(current_controller, item):
                    current_controller = getattr(current_controller, item)
                    state.add_routing_args(item, remainder[:i], fixed_args, var_args)
                    return self._dispatch_controller(item, current_controller, state, remainder[i+1:])
        elif fixed_arg_length< len(remainder) and hasattr(current_controller, remainder[fixed_arg_length]):
            item = state.path_translator(remainder[fixed_arg_length])
            if hasattr(current_controller, item):
                if self._is_controller(current_controller, item):
                    state.add_routing_args(item, remainder, fixed_args, var_args)
                    return self._dispatch_controller(item, getattr(current_controller, item),
                                                     state, remainder[fixed_arg_length+1:])

    def _handle_delete_edit_or_new(self, state, remainder):
        method_name = remainder[-1]
        if method_name not in ('new', 'edit', 'delete'):
            return

        if method_name == 'delete':
            method_name = 'get_delete'

        current_controller = state.controller

        if self._is_exposed(current_controller, method_name):
            method = getattr(current_controller, method_name)
            new_remainder = remainder[:-1]
            if method and method_matches_args(method, state.params, new_remainder, self._use_lax_params):
                state.add_method(method, new_remainder)
                return state

    def _handle_custom_get(self, state, remainder):
        controller = state.controller
        method_name = remainder[-1]

        current_controller = state.controller

        get_method = self._find_first_exposed(current_controller, ('get_%s' % method_name, method_name))
        if get_method:
            new_remainder = remainder[:-1]
            if method_matches_args(get_method, state.params, new_remainder, self._use_lax_params):
                state.add_method(get_method, new_remainder)
                return state

    def _handle_custom_method(self, method, state, remainder):
        current_controller = state.controller
        method_name = method
        http_method = state.request.method
        method = self._find_first_exposed(current_controller, ('%s_%s' %(http_method, method_name), method_name, 'post_%s' %method_name))

        if method and method_matches_args(method, state.params, remainder, self._use_lax_params):
            state.add_method(method, remainder)
            return state

        # there might be a sub-controller with a custom method, let's go see
        if remainder:
            sub_controller = getattr(current_controller, remainder[0], None)
            if sub_controller:
                current = remainder[0]
                remainder = remainder[1:]
                state.current_controller = sub_controller
                state.path = remainder
                r = self._dispatch_controller(current, sub_controller, state, remainder)
                if r:
                    return r
        return self._dispatch_first_found_default_or_lookup(state, remainder)

    def _handle_get(self, method, state, remainder):
        current_controller = state.controller
        if not remainder:
            method = self._find_first_exposed(current_controller, ('get_all', 'get'))
            if method:
                state.add_method(method, remainder)
                return state
            if self._is_exposed(current_controller, 'get_one'):
                method = current_controller.get_one
                if method and method_matches_args(method, state.params, remainder, self._use_lax_params):
                    state.add_method(method, remainder)
                    return state
            return self._dispatch_first_found_default_or_lookup(state, remainder)

        #test for "delete", "edit" or "new"
        r = self._handle_delete_edit_or_new(state, remainder)
        if r is not None:
            return r

        #test for custom REST-like attribute
        r = self._handle_custom_get(state, remainder)
        if r is not None:
            return r

        current_path = state.path_translator(remainder[0])
        if self._is_exposed(current_controller, current_path):
            state.add_method(getattr(current_controller, current_path), remainder[1:])
            return state

        if self._is_controller(current_controller, current_path):
            current_controller = getattr(current_controller, current_path)
            return self._dispatch_controller(current_path, current_controller, state, remainder[1:])

        method = self._find_first_exposed(current_controller, ('get_one', 'get'))
        if method and method_matches_args(method, state.params, remainder, self._use_lax_params):
            state.add_method(method, remainder)
            return state

        return self._dispatch_first_found_default_or_lookup(state, remainder)

    _handler_lookup = {
        'put':_handle_put_or_post,
        'post':_handle_put_or_post,
        'delete':_handle_delete,
        'get':_handle_get,
        }

    def _is_controller(self, controller, name):
        """
        Override this function to define how an object is determined to be a
        controller.
        """
        method = getattr(controller, name, None)
        if method is not None:
            return not ismethod(method)

    def _dispatch(self, state, remainder=None):
        """
        This method defines how the object dispatch mechanism works, including
        checking for security along the way.
        """
        if state.dispatcher is None:
            state.dispatcher = self
            state.add_controller('/', self)
        if remainder is None:
            remainder = state.path

        self._enter_controller(state, remainder)

        #log.debug('Entering dispatch for remainder: %s in controller %s'%(remainder, self))
        if not hasattr(state, 'http_method'):
            method = state.request.method.lower()
            params = state.params

            #conventional hack for handling methods which are not supported by most browsers
            request_method = params.get('_method', None)
            if request_method:
                request_method = request_method.lower()
                #make certain that DELETE and PUT requests are not sent with GET
                if method == 'get' and request_method == 'put':
                    raise HTTPMethodNotAllowed
                if method == 'get' and request_method == 'delete':
                    raise HTTPMethodNotAllowed
                method = request_method
                del state.params['_method']
            state.http_method = method

        r = self._check_for_sub_controllers(state, remainder)
        if r is not None:
            return r

        if state.http_method in self._handler_lookup.keys():
            r = self._handler_lookup[state.http_method](self, state.http_method, state, remainder)
        else:
            r = self._handle_custom_method(state.http_method, state, remainder)
        return r