a3cb3f00560926d57adb82613fb61a33e31f741b
[pub/Android/ownCloud.git] / third_party / transifex-client / txclib / web.py
1 # -*- coding: utf-8 -*-
2 import urllib2
3 import itertools, mimetools, mimetypes
4 import platform
5 from txclib import get_version
6
7 # Helper class to enable urllib2 to handle PUT/DELETE requests as well
8 class RequestWithMethod(urllib2.Request):
9 """Workaround for using DELETE with urllib2"""
10 def __init__(self, url, method, data=None, headers={},
11 origin_req_host=None, unverifiable=False):
12 self._method = method
13 urllib2.Request.__init__(self, url, data=data, headers=headers,
14 origin_req_host=None, unverifiable=False)
15
16 def get_method(self):
17 return self._method
18
19 import urllib
20 import os, stat
21 from cStringIO import StringIO
22
23 class Callable:
24 def __init__(self, anycallable):
25 self.__call__ = anycallable
26
27 # Controls how sequences are uncoded. If true, elements may be given multiple
28 # values by assigning a sequence.
29 doseq = 1
30
31 class MultipartPostHandler(urllib2.BaseHandler):
32 handler_order = urllib2.HTTPHandler.handler_order - 10 # needs to run first
33
34 def http_request(self, request):
35 data = request.get_data()
36 if data is not None and type(data) != str:
37 v_files = []
38 v_vars = []
39 try:
40 for(key, value) in data.items():
41 if type(value) == file:
42 v_files.append((key, value))
43 else:
44 v_vars.append((key, value))
45 except TypeError:
46 systype, value, traceback = sys.exc_info()
47 raise TypeError, "not a valid non-string sequence or mapping object", traceback
48
49 if len(v_files) == 0:
50 data = urllib.urlencode(v_vars, doseq)
51 else:
52 boundary, data = self.multipart_encode(v_vars, v_files)
53
54 contenttype = 'multipart/form-data; boundary=%s' % boundary
55 if(request.has_header('Content-Type')
56 and request.get_header('Content-Type').find('multipart/form-data') != 0):
57 print "Replacing %s with %s" % (request.get_header('content-type'), 'multipart/form-data')
58 request.add_unredirected_header('Content-Type', contenttype)
59
60 request.add_data(data)
61
62 return request
63
64 def multipart_encode(vars, files, boundary = None, buf = None):
65 if boundary is None:
66 boundary = mimetools.choose_boundary()
67 if buf is None:
68 buf = StringIO()
69 for(key, value) in vars:
70 buf.write('--%s\r\n' % boundary)
71 buf.write('Content-Disposition: form-data; name="%s"' % key)
72 buf.write('\r\n\r\n' + value + '\r\n')
73 for(key, fd) in files:
74 file_size = os.fstat(fd.fileno())[stat.ST_SIZE]
75 filename = fd.name.split('/')[-1]
76 contenttype = mimetypes.guess_type(filename)[0] or 'application/octet-stream'
77 buf.write('--%s\r\n' % boundary)
78 buf.write('Content-Disposition: form-data; name="%s"; filename="%s"\r\n' % (key, filename))
79 buf.write('Content-Type: %s\r\n' % contenttype)
80 # buffer += 'Content-Length: %s\r\n' % file_size
81 fd.seek(0)
82 buf.write('\r\n' + fd.read() + '\r\n')
83 buf.write('--' + boundary + '--\r\n\r\n')
84 buf = buf.getvalue()
85 return boundary, buf
86 multipart_encode = Callable(multipart_encode)
87
88 https_request = http_request
89
90
91 def user_agent_identifier():
92 """Return the user agent for the client."""
93 client_info = (get_version(), platform.system(), platform.machine())
94 return "txclient/%s (%s %s)" % client_info