ia64/xen-unstable

view tools/python/xen/xend/encode.py @ 6538:84ee014ebd41

Merge xen-vtx-unstable.hg
author adsharma@los-vmm.sc.intel.com
date Wed Aug 17 12:34:38 2005 -0800 (2005-08-17)
parents 23979fb12c49 f40c6650152e
children 99914b54f7bf
line source
1 #============================================================================
2 # This library is free software; you can redistribute it and/or
3 # modify it under the terms of version 2.1 of the GNU Lesser General Public
4 # License as published by the Free Software Foundation.
5 #
6 # This library is distributed in the hope that it will be useful,
7 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 # Lesser General Public License for more details.
10 #
11 # You should have received a copy of the GNU Lesser General Public
12 # License along with this library; if not, write to the Free Software
13 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
14 #============================================================================
15 # Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com>
16 #============================================================================
18 """Encoding for arguments to HTTP calls.
19 Uses the url-encoding with MIME type 'application/x-www-form-urlencoded'
20 if the data does not include files. Otherwise it uses the encoding with
21 MIME type 'multipart/form-data'. See the HTML4 spec for details.
23 """
24 import sys
25 import types
26 from StringIO import StringIO
28 import urllib
29 import httplib
30 import random
31 import md5
33 # Extract from HTML4 spec.
34 ## The following example illustrates "multipart/form-data"
35 ## encoding. Suppose we have the following form:
37 ## <FORM action="http://server.com/cgi/handle"
38 ## enctype="multipart/form-data"
39 ## method="post">
40 ## <P>
41 ## What is your name? <INPUT type="text" name="submit-name"><BR>
42 ## What files are you sending? <INPUT type="file" name="files"><BR>
43 ## <INPUT type="submit" value="Send"> <INPUT type="reset">
44 ## </FORM>
46 ## If the user enters "Larry" in the text input, and selects the text
47 ## file "file1.txt", the user agent might send back the following data:
49 ## Content-Type: multipart/form-data; boundary=AaB03x
51 ## --AaB03x
52 ## Content-Disposition: form-data; name="submit-name"
54 ## Larry
55 ## --AaB03x
56 ## Content-Disposition: form-data; name="files"; filename="file1.txt"
57 ## Content-Type: text/plain
59 ## ... contents of file1.txt ...
60 ## --AaB03x--
62 ## If the user selected a second (image) file "file2.gif", the user agent
63 ## might construct the parts as follows:
65 ## Content-Type: multipart/form-data; boundary=AaB03x
67 ## --AaB03x
68 ## Content-Disposition: form-data; name="submit-name"
70 ## Larry
71 ## --AaB03x
72 ## Content-Disposition: form-data; name="files"
73 ## Content-Type: multipart/mixed; boundary=BbC04y
75 ## --BbC04y
76 ## Content-Disposition: file; filename="file1.txt"
77 ## Content-Type: text/plain
79 ## ... contents of file1.txt ...
80 ## --BbC04y
81 ## Content-Disposition: file; filename="file2.gif"
82 ## Content-Type: image/gif
83 ## Content-Transfer-Encoding: binary
85 ## ...contents of file2.gif...
86 ## --BbC04y--
87 ## --AaB03x--
89 __all__ = ['encode_data', 'encode_multipart', 'encode_form', 'mime_boundary' ]
91 def data_values(d):
92 if isinstance(d, types.DictType):
93 return d.items()
94 else:
95 return d
97 def encode_data(d):
98 """Encode some data for HTTP transport.
99 The encoding used is stored in 'Content-Type' in the headers.
101 d data - sequence of tuples or dictionary
102 returns a 2-tuple of the headers and the encoded data
103 """
104 val = ({}, None)
105 if d is None: return val
106 multipart = 0
107 for (k, v) in data_values(d):
108 if encode_isfile(v):
109 multipart = 1
110 break
111 if multipart:
112 val = encode_multipart(d)
113 else:
114 val = encode_form(d)
115 return val
117 def encode_isfile(v):
118 if isinstance(v, types.FileType):
119 return 1
120 if hasattr(v, 'readlines'):
121 return 1
122 return 0
124 def encode_multipart(d):
125 boundary = mime_boundary()
126 hdr = { 'Content-Type': 'multipart/form-data; boundary=' + boundary }
127 out = StringIO()
128 for (k,v) in data_values(d):
129 out.write('--')
130 out.write(boundary)
131 out.write('\r\n')
132 if encode_isfile(v):
133 out.write('Content-Disposition: form-data; name="')
134 out.write(k)
135 if hasattr(v, 'name'):
136 out.write('"; filename="')
137 out.write(v.name)
138 out.write('"\r\n')
139 out.write('Content-Type: application/octet-stream\r\n')
140 out.write('\r\n')
141 for l in v.readlines():
142 out.write(l)
143 else:
144 out.write('Content-Disposition: form-data; name="')
145 out.write(k)
146 out.write('"\r\n')
147 out.write('\r\n')
148 out.write(str(v))
149 out.write('\r\n')
150 out.write('--')
151 out.write(boundary)
152 out.write('--')
153 out.write('\r\n')
154 return (hdr, out.getvalue())
156 def mime_boundary():
157 random.seed()
158 m = md5.new()
159 for i in range(0, 10):
160 c = chr(random.randint(1, 255))
161 m.update(c)
162 b = m.hexdigest()
163 return b[0:16]
165 def encode_form(d):
166 hdr = { 'Content-Type': 'application/x-www-form-urlencoded' }
167 val = urllib.urlencode(d)
168 return (hdr, val)
170 def main():
171 #d = {'a': 1, 'b': 'x y', 'c': file('conf.sxp') }
172 #d = {'a': 1, 'b': 'x y' }
173 d = [ ('a', 1), ('b', 'x y'), ('c', file('conf.sxp')) ]
174 #d = [ ('a', 1), ('b', 'x y')]
175 v = encode_data(d)
176 print v[0]
177 sys.stdout.write(v[1])
178 print
180 if __name__ == "__main__":
181 main()