]>
Commit | Line | Data |
---|---|---|
1 | from __future__ import print_function | |
2 | ||
3 | from twitter.auth import Auth | |
4 | ||
5 | from time import time | |
6 | from random import getrandbits | |
7 | ||
8 | try: | |
9 | import urllib.parse as urllib_parse | |
10 | from urllib.parse import urlencode | |
11 | PY3 = True | |
12 | except ImportError: | |
13 | import urllib2 as urllib_parse | |
14 | from urllib import urlencode | |
15 | PY3 = False | |
16 | ||
17 | import hashlib | |
18 | import hmac | |
19 | import base64 | |
20 | ||
21 | ||
22 | ||
23 | def write_token_file(filename, oauth_token, oauth_token_secret): | |
24 | """ | |
25 | Write a token file to hold the oauth token and oauth token secret. | |
26 | """ | |
27 | oauth_file = open(filename, 'w') | |
28 | print(oauth_token, file=oauth_file) | |
29 | print(oauth_token_secret, file=oauth_file) | |
30 | oauth_file.close() | |
31 | ||
32 | def read_token_file(filename): | |
33 | """ | |
34 | Read a token file and return the oauth token and oauth token secret. | |
35 | """ | |
36 | f = open(filename) | |
37 | return f.readline().strip(), f.readline().strip() | |
38 | ||
39 | ||
40 | class OAuth(Auth): | |
41 | """ | |
42 | An OAuth authenticator. | |
43 | """ | |
44 | def __init__(self, token, token_secret, consumer_key, consumer_secret): | |
45 | """ | |
46 | Create the authenticator. If you are in the initial stages of | |
47 | the OAuth dance and don't yet have a token or token_secret, | |
48 | pass empty strings for these params. | |
49 | """ | |
50 | self.token = token | |
51 | self.token_secret = token_secret | |
52 | self.consumer_key = consumer_key | |
53 | self.consumer_secret = consumer_secret | |
54 | ||
55 | def encode_params(self, base_url, method, params): | |
56 | params = params.copy() | |
57 | ||
58 | if self.token: | |
59 | params['oauth_token'] = self.token | |
60 | ||
61 | params['oauth_consumer_key'] = self.consumer_key | |
62 | params['oauth_signature_method'] = 'HMAC-SHA1' | |
63 | params['oauth_version'] = '1.0' | |
64 | params['oauth_timestamp'] = str(int(time())) | |
65 | params['oauth_nonce'] = str(getrandbits(64)) | |
66 | ||
67 | enc_params = urlencode_noplus(sorted(params.items())) | |
68 | ||
69 | key = self.consumer_secret + "&" + urllib_parse.quote(self.token_secret, '') | |
70 | ||
71 | message = '&'.join( | |
72 | urllib_parse.quote(i, '') for i in [method.upper(), base_url, enc_params]) | |
73 | ||
74 | signature = (base64.b64encode(hmac.new( | |
75 | key.encode('ascii'), message.encode('ascii'), hashlib.sha1) | |
76 | .digest())) | |
77 | return enc_params + "&" + "oauth_signature=" + urllib_parse.quote(signature, '') | |
78 | ||
79 | def generate_headers(self): | |
80 | return {} | |
81 | ||
82 | # apparently contrary to the HTTP RFCs, spaces in arguments must be encoded as | |
83 | # %20 rather than '+' when constructing an OAuth signature (and therefore | |
84 | # also in the request itself.) | |
85 | # So here is a specialized version which does exactly that. | |
86 | def urlencode_noplus(query): | |
87 | if not PY3: | |
88 | new_query = [] | |
89 | for k,v in query: | |
90 | if type(k) is unicode: k = k.encode('utf-8') | |
91 | if type(v) is unicode: v = v.encode('utf-8') | |
92 | new_query.append((k, v)) | |
93 | query = new_query | |
94 | return urlencode(query).replace("+", "%20") |