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