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