• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
Keine Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

allura


Commit MetaInfo

Revision5b7bb04f125bf5c323c9b7b79d571dc9cfb21bde (tree)
Zeit2010-06-03 23:40:48
AutorWolf <wolf@geek...>
CommiterWolf

Log Message

Teach the REST API authentication to better handle Unicode

Ändern Zusammenfassung

Diff

--- a/pyforge/pyforge/model/auth.py
+++ b/pyforge/pyforge/model/auth.py
@@ -23,6 +23,49 @@ from .session import project_doc_session, project_orm_session
2323
2424 log = logging.getLogger(__name__)
2525
26+def smart_str(s, encoding='utf-8', strings_only=False, errors='strict'):
27+ """
28+ Returns a bytestring version of 's', encoded as specified in 'encoding'.
29+
30+ If strings_only is True, don't convert (some) non-string-like objects.
31+
32+ This function was borrowed from Django
33+ """
34+ if strings_only and isinstance(s, (types.NoneType, int)):
35+ return s
36+ elif not isinstance(s, basestring):
37+ try:
38+ return str(s)
39+ except UnicodeEncodeError:
40+ if isinstance(s, Exception):
41+ # An Exception subclass containing non-ASCII data that doesn't
42+ # know how to print itself properly. We shouldn't raise a
43+ # further exception.
44+ return ' '.join([smart_str(arg, encoding, strings_only,
45+ errors) for arg in s])
46+ return unicode(s).encode(encoding, errors)
47+ elif isinstance(s, unicode):
48+ r = s.encode(encoding, errors)
49+ return r
50+ elif s and encoding != 'utf-8':
51+ return s.decode('utf-8', errors).encode(encoding, errors)
52+ else:
53+ return s
54+
55+def generate_smart_str(params):
56+ for (key, value) in params:
57+ if value is None: continue
58+ yield smart_str(key), smart_str(value)
59+
60+def urlencode(params):
61+ """
62+ A version of Python's urllib.urlencode() function that can operate on
63+ unicode strings. The parameters are first case to UTF-8 encoded strings and
64+ then encoded as per normal.
65+ """
66+ return urllib.urlencode([i for i in generate_smart_str(params)])
67+
68+
2669 class ApiToken(MappedClass):
2770 class __mongometa__:
2871 name='api_token'
@@ -45,7 +88,7 @@ class ApiToken(MappedClass):
4588 # Validate signature
4689 api_signature = params['api_signature']
4790 params = sorted((k,v) for k,v in params.iteritems() if k != 'api_signature')
48- string_to_sign = path + '?' + urllib.urlencode(params)
91+ string_to_sign = path + '?' + urlencode(params)
4992 digest = hmac.new(self.secret_key, string_to_sign, hashlib.sha256)
5093 return digest.hexdigest() == api_signature
5194 except KeyError:
@@ -62,7 +105,7 @@ class ApiToken(MappedClass):
62105 if not has_api_timestamp:
63106 params.append(('api_timestamp', datetime.utcnow().isoformat()))
64107 if not has_api_signature:
65- string_to_sign = path + '?' + urllib.urlencode(sorted(params))
108+ string_to_sign = path + '?' + urlencode(sorted(params))
66109 digest = hmac.new(self.secret_key, string_to_sign, hashlib.sha256)
67110 params.append(('api_signature', digest.hexdigest()))
68111 return params
--- a/scripts/wiki-post.py
+++ b/scripts/wiki-post.py
@@ -4,12 +4,55 @@ from sys import stdin, stdout
44 import hmac, hashlib
55 from datetime import datetime
66 import os
7-from urllib import urlencode
8-from urllib2 import urlopen
7+import urllib
8+from urllib2 import urlopen, HTTPError
99 from urlparse import urlparse, urljoin
1010 from optparse import OptionParser
1111 from ConfigParser import ConfigParser
1212
13+def smart_str(s, encoding='utf-8', strings_only=False, errors='strict'):
14+ """
15+ Returns a bytestring version of 's', encoded as specified in 'encoding'.
16+
17+ If strings_only is True, don't convert (some) non-string-like objects.
18+
19+ This function was borrowed from Django
20+ """
21+ if strings_only and isinstance(s, (types.NoneType, int)):
22+ return s
23+ elif not isinstance(s, basestring):
24+ try:
25+ return str(s)
26+ except UnicodeEncodeError:
27+ if isinstance(s, Exception):
28+ # An Exception subclass containing non-ASCII data that doesn't
29+ # know how to print itself properly. We shouldn't raise a
30+ # further exception.
31+ return ' '.join([smart_str(arg, encoding, strings_only,
32+ errors) for arg in s])
33+ return unicode(s).encode(encoding, errors)
34+ elif isinstance(s, unicode):
35+ r = s.encode(encoding, errors)
36+ return r
37+ elif s and encoding != 'utf-8':
38+ return s.decode('utf-8', errors).encode(encoding, errors)
39+ else:
40+ return s
41+
42+def generate_smart_str(params):
43+ for (key, value) in params:
44+ if value is None: continue
45+ yield smart_str(key), smart_str(value)
46+
47+def urlencode(params):
48+ """
49+ A version of Python's urllib.urlencode() function that can operate on
50+ unicode strings. The parameters are first case to UTF-8 encoded strings and
51+ then encoded as per normal.
52+ """
53+ return urllib.urlencode([i for i in generate_smart_str(params)])
54+
55+
1356 class Signer(object):
1457
1558 def __init__(self, secret_key, api_key):
@@ -34,7 +77,7 @@ def main():
3477 (options, args) = op.parse_args()
3578
3679 page = args[0]
37- f = open(args[1], 'r') if len(args)>=1 else stdin
80+ f = open(args[1], 'r') if len(args)>1 else stdin
3881 markdown = f.read()
3982
4083 config = ConfigParser()
@@ -48,8 +91,11 @@ def main():
4891
4992 sign = Signer(secret_key, api_key)
5093 params = sign(urlparse(url).path, [('text', markdown)])
51- result = urlopen(url, urlencode(params))
52- stdout.write(result.read())
94+ try:
95+ result = urlopen(url, urlencode(params))
96+ stdout.write(result.read())
97+ except HTTPError, e:
98+ stdout.write(e.read())
5399
54100 if __name__ == '__main__':
55101 main()