This file is indexed.

/usr/share/pyshared/pypump/pypump.py is in python-pypump 0.3+git20130823.1.97bffc6-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
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
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
# -*- coding: utf-8 -*-

##
#   Copyright (C) 2010-2012 Reality <tinmachin3@gmail.com> and Psychedelic Squid <psquid@psquid.net>
#   Copyright (C) 2013 Jessica T. (Tsyesika) <xray7224@googlemail.com>
# 
#   This program is free software: you can redistribute it and/or modify 
#   it under the terms of the GNU General Public License as published by 
#   the Free Software Foundation, either version 3 of the License, or 
#   (at your option) any later version. 
# 
#   This program is distributed in the hope that it will be useful, 
#   but WITHOUT ANY WARRANTY; without even the implied warranty of 
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
#   GNU General Public License for more details. 
# 
#   You should have received a copy of the GNU General Public License 
#   along with this program. If not, see <http://www.gnu.org/licenses/>.
##

from __future__ import absolute_import

import json

import requests
from requests_oauthlib import OAuth1
import pypump.openid as openid

from pypump.compatability import *
from pypump.exception import PyPumpException

# load models
from pypump.models.note import Note
from pypump.models.comment import Comment
from pypump.models.person import Person
from pypump.models.image import Image
from pypump.models.inbox import Inbox
from pypump.models.outbox import Outbox
from pypump.models.location import Location
from pypump.models.list import List, Public, Followers, Following
from pypump.models.activity import Activity

class PyPump(object):

    PARAM_VERIFER = to_bytes("oauth_verifier")
    PARAM_TOKEN = to_bytes("oauth_token")
    PARAM_TOKEN_SECRET = to_bytes("oauth_token_secret")

    URL_CLIENT_REGISTRATION = "/api/client/register"

    loader = None
    protocol = "https"
    client = None

    def __init__(self, server, key=None, secret=None, 
                client_name="", client_type="native", token=None, 
                token_secret=None, verifier_callback=None,
                callback_uri="oob"):
        """
            This is the main pump instance, this handles the oauth,
            this also holds the models.

            Don't forget if you want to use https ensure the secure flag is True
        """
        openid.OpenID.pypump = self # pypump uses PyPump.requester.
        self.verifier_callback = verifier_callback
        self.client_name = client_name
        self.client_type = client_type
        self.callback_uri = callback_uri

        if "@" in server:
            # it's a web fingerprint!
            self.nickname, self.server = server.split("@")
        else:
            self.server = server
            self.nickname = None # should be set with <instance>.set_nickname(<nickname>)

        # Fix #24 by checking
        if (key is None or secret is None) and (token or token_secret):
            raise Exception("If token and/or token_secret are supplied you must supply key and secret too")

        self.populate_models()

        # first, if we need to register our client
        if not (key or secret):
            oid = openid.OpenID(
                    server=server,
                    client_name=client_name,
                    application_type=client_type
                    )
            self.consumer = oid.register_client()
        else:
            self.consumer = openid.Consumer()
            self.consumer.key = key
            self.consumer.secret = secret

        if not (token and token_secret):
            # we need to make a new oauth request
            self.oauth_request() # this does NOT return access tokens but None
        else:
            self.token = token
            self.token_secret = token_secret

    def populate_models(self):
        # todo: change me
        self.Note = Note
        self.Note._pump = self

        self.Comment = Comment
        self.Comment._pump = self
        
        self.Inbox = Inbox
        self.Inbox._pump = self

        self.Outbox = Outbox
        self.Outbox._pump = self

        self.Image = Image
        self.Image._pump = self

        self.Person = Person
        self.Person._pump = self

        self.Location = Location
        self.Location._pump = self

        self.List = List
        self.List._pump = self

        self.Public = Public
        self.Public._pump = self

        self.Following = Following
        self.Following._pump = self

        self.Followers = Followers
        self.Followers._pump = self

        self.Activity = Activity
        self.Activity._pump = self

    ##
    # getters to expose some data which might be useful
    ##
    def get_registration(self):
        """ This is if key and secret weren't specified at instansiation so we registered them """
        return (self.consumer.key, self.consumer.secret, self.consumer.expirey)

    def get_token(self):
        """ This is for when we don't have a token but we've registered one (by asking the user) """
        return (self.token, self.token_secret)

    def set_nickname(self, nickname):
        """ This sets the nickname being used """
        if nickname:
            self.nickname = str(nickname) # everything in python can be converted to a string right?
        else:
            # they didn't enter a nickname?
            raise Exception("Nickname can't be of length 0")

    ## 
    # server 
    ##
    def build_url(self, endpoint):
        """ Returns a fully qualified URL """
        server = None
        if "://" in endpoint:
            #looks like an url, let's break it down
            server, endpoint = self.deconstruct_url(endpoint)

        endpoint = endpoint.lstrip("/")
        url = "{proto}://{server}/{endpoint}".format(
                proto=self.protocol,
                server=self.server if server is None else server,
                endpoint=endpoint
                )
        return url

    def deconstruct_url(self, url):
        """ Breaks down URL and returns server and endpoint """
        proto, url = url.split("://")
        server, endpoint = url.split("/", 1)
        return (server, endpoint)

    def request(self, endpoint, method="GET", data="", 
                raw=False, params=None, attempts=10, client=None):
        """ This will make a request to <self.protocol>://<self.server>/<endpoint> with oauth headers
        method = GET (default), POST or PUT
        attempts = this is how many times it'll try re-attempting
        """

        if client is None:
            client = self.client

        # check client has been setup
        if client is None:
            self.setup_oauth_client()
            client = self.client

        params = {} if params is None else params

        if endpoint.startswith("/"):
            endpoint = endpoint[1:] # remove inital / as we add it

        if data and isinstance(data, dict):
            # we actually need to make it into a json object as that's what pump.io deals with.
            data = json.dumps(data)

        data = to_unicode(data)

        if not raw:
            url = self.build_url(endpoint)
        else:
            url = endpoint

        lastresponse = ""
        for attempt in range(attempts):
            if method == "POST":
                request = {
                        "auth": client,
                        "headers": {"Content-Type": "application/json"},
                        "params": params,
                        "data": data,
                        }
                response = self._requester(requests.post, endpoint, raw, **request)
            elif method == "GET":
                request = {
                        "params": params,
                        "auth": client,
                        }
  
                response = self._requester(requests.get, endpoint, raw, **request)

            if response.status_code == 200:
                # huray!
                return response.json() 

            ##
            # Debugging
            ##
            if response.content != lastresponse:
                lastresponse = response.content
                print response
                print response.content
 
            if response.status_code == 400:
                # can't do much
                try:
                    try:
                        data = response.json()
                        error = data["error"]
                    except ValueError:
                        error = response.content
                    
                    if not error:
                        raise IndexError # yesss i know.
                except IndexError:
                    error = "Received a 400 bad request error. This is likely due to an OAuth failure"
                raise PyPumpException(error)
        
        # failed, oh no!
        error = "Failed to make request to {0} ({1} {2})".format(url, method, data)
        raise PyPumpException(error)
    def _requester(self, fnc, endpoint, raw=False, **kwargs):
        if not raw:
            url = self.build_url(endpoint)
        else:
            url = endpoint

        try:
            response = fnc(url, **kwargs)
            return response
        except requests.exceptions.ConnectionError:
            if self.protocol == "http" or raw:
                raise # shoot this seems real.
            else:
                # rebuild url using http for raw request then go back to https as default
                self.set_http()
                url = self.build_url(endpoint)
                self.set_https()
                raw = True
                return self._requester(fnc, url, raw, **kwargs)

    def set_https(self):
        """ Enforces protocol to be https """
        self.protocol = "https"

    def set_http(self):
        """ Sets protocol to be http """
        self.protocol = "http"

    ##
    # OAuth specific stuff
    ##
    def oauth_request(self):
        """ Makes a oauth connection """
        # get tokens from server and make a dict of them.
        self.__server_tokens = self.request_token()
        
        self.token = self.__server_tokens["token"]
        self.token_secret = self.__server_tokens["token_secret"]

        url = self.build_url("oauth/authorize?oauth_token={token}".format(
                protocol=self.protocol,
                server=self.server,
                token=self.token.decode("utf-8")
                ))

        # now we need the user to authorize me to use their pump.io account
        if self.verifier_callback is None:
            verifier = self.get_access(url)
            self.verifier(verifier)
        else:    
            self.verifier_callback(url)
 
    def verifier(self, verifier):
        """ Called once verifier has been retrived """
        self.__server_tokens["verifier"] = verifier
        self.request_access(**self.__server_tokens)

    def setup_oauth_client(self):
        """ Sets up client for requests to pump """
        self.client = OAuth1(
                client_key=to_unicode(self.consumer.key),
                client_secret=to_unicode(self.consumer.secret),
                resource_owner_key=to_unicode(self.token),
                resource_owner_secret=to_unicode(self.token_secret)
                )

    def get_access(self, url):
        """ this asks the user to let us use their account """

        print("To allow us to use your pump.io please follow the instructions at:")
        print(url)

        code = raw_input("Verifier Code: ").lstrip(" ").rstrip(" ")
        return code

    def request_token(self):
        """ Gets a request token so that we can then ask the user for access to the accoutn """
        client = OAuth1(
                client_key=self.consumer.key,
                client_secret=self.consumer.secret,
                callback_uri=self.callback_uri
                )
        
        request = {"auth": client}
        response = self._requester(requests.post, "oauth/request_token", **request)
        data = parse_qs(response.content)
        data = {
            'token': data[self.PARAM_TOKEN][0],
            'token_secret': data[self.PARAM_TOKEN_SECRET][0]
            }

        return data

    def request_access(self, **auth_info):
        """ This is for when we've got the user's access value and we're asking the server for our access token """
        client = OAuth1(
                client_key=self.consumer.key,
                client_secret=self.consumer.secret,
                resource_owner_key=auth_info['token'],
                resource_owner_secret=auth_info['token_secret'],
                verifier=auth_info['verifier']
                )

        request = {"auth": client}
        response = self._requester(requests.post, "oauth/access_token", **request)        
        data = parse_qs(response.content)

        self.token = data[self.PARAM_TOKEN][0]
        self.token_secret = data[self.PARAM_TOKEN_SECRET][0]
        self.__server_tokens = None # clean up code.

class WebPump(PyPump):
    """
        This is a PyPump class which is aimed at mainly web developers.
        Allowing you to avoid the callbacks making the oauth portion of
        PyPump instanciation blocking.

        After initialisation you will be able to do `PyPump.verifier_url`
        allowing you to get the url to direct your user to. That method
        will return None if the oauth handshake was successful and no
        verifier callback needs to be done.
    
        Once you have the verifier instanciate this class again and
        call the verifier method alike what you do using the PyPump class
    """

    url = None

    def __init__(self, *args, **kwargs):
        """
            This is exactly the same as PyPump.__init__ apart from 
            verifier_callback is no longer an option for kwargs and
            if specified will be ignored.
        """
        kwargs["verifier_callback"] = self._callback_verifier
        super(WebPump, self).__init__(*args, **kwargs)

    def _callback_verifier(self, url):
        """ This is used to catch the url and store it at `self.url` """
        self.url = url