diff options
Diffstat (limited to 'tools/python/xen/xend/encode.py')
-rw-r--r-- | tools/python/xen/xend/encode.py | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/tools/python/xen/xend/encode.py b/tools/python/xen/xend/encode.py new file mode 100644 index 0000000000..38c9351db7 --- /dev/null +++ b/tools/python/xen/xend/encode.py @@ -0,0 +1,165 @@ +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com> +"""Encoding for arguments to HTTP calls. + Uses the url-encoding with MIME type 'application/x-www-form-urlencoded' + if the data does not include files. Otherwise it uses the encoding with + MIME type 'multipart/form-data'. See the HTML4 spec for details. + + """ +import sys +import types +from StringIO import StringIO + +import urllib +import httplib +import random +import md5 + +# Extract from HTML4 spec. +## The following example illustrates "multipart/form-data" +## encoding. Suppose we have the following form: + +## <FORM action="http://server.com/cgi/handle" +## enctype="multipart/form-data" +## method="post"> +## <P> +## What is your name? <INPUT type="text" name="submit-name"><BR> +## What files are you sending? <INPUT type="file" name="files"><BR> +## <INPUT type="submit" value="Send"> <INPUT type="reset"> +## </FORM> + +## If the user enters "Larry" in the text input, and selects the text +## file "file1.txt", the user agent might send back the following data: + +## Content-Type: multipart/form-data; boundary=AaB03x + +## --AaB03x +## Content-Disposition: form-data; name="submit-name" + +## Larry +## --AaB03x +## Content-Disposition: form-data; name="files"; filename="file1.txt" +## Content-Type: text/plain + +## ... contents of file1.txt ... +## --AaB03x-- + +## If the user selected a second (image) file "file2.gif", the user agent +## might construct the parts as follows: + +## Content-Type: multipart/form-data; boundary=AaB03x + +## --AaB03x +## Content-Disposition: form-data; name="submit-name" + +## Larry +## --AaB03x +## Content-Disposition: form-data; name="files" +## Content-Type: multipart/mixed; boundary=BbC04y + +## --BbC04y +## Content-Disposition: file; filename="file1.txt" +## Content-Type: text/plain + +## ... contents of file1.txt ... +## --BbC04y +## Content-Disposition: file; filename="file2.gif" +## Content-Type: image/gif +## Content-Transfer-Encoding: binary + +## ...contents of file2.gif... +## --BbC04y-- +## --AaB03x-- + +__all__ = ['encode_data', 'encode_multipart', 'encode_form', 'mime_boundary' ] + +def data_values(d): + if isinstance(d, types.DictType): + return d.items() + else: + return d + +def encode_data(d): + """Encode some data for HTTP transport. + The encoding used is stored in 'Content-Type' in the headers. + + d data - sequence of tuples or dictionary + returns a 2-tuple of the headers and the encoded data + """ + val = ({}, None) + if d is None: return val + multipart = 0 + for (k, v) in data_values(d): + if encode_isfile(v): + multipart = 1 + break + if multipart: + val = encode_multipart(d) + else: + val = encode_form(d) + return val + +def encode_isfile(v): + if isinstance(v, types.FileType): + return 1 + if hasattr(v, 'readlines'): + return 1 + return 0 + +def encode_multipart(d): + boundary = mime_boundary() + hdr = { 'Content-Type': 'multipart/form-data; boundary=' + boundary } + out = StringIO() + for (k,v) in data_values(d): + out.write('--') + out.write(boundary) + out.write('\r\n') + if encode_isfile(v): + out.write('Content-Disposition: form-data; name="') + out.write(k) + if hasattr(v, 'name'): + out.write('"; filename="') + out.write(v.name) + out.write('"\r\n') + out.write('Content-Type: application/octet-stream\r\n') + out.write('\r\n') + for l in v.readlines(): + out.write(l) + else: + out.write('Content-Disposition: form-data; name="') + out.write(k) + out.write('"\r\n') + out.write('\r\n') + out.write(str(v)) + out.write('\r\n') + out.write('--') + out.write(boundary) + out.write('--') + out.write('\r\n') + return (hdr, out.getvalue()) + +def mime_boundary(): + random.seed() + m = md5.new() + for i in range(0, 10): + c = chr(random.randint(1, 255)) + m.update(c) + b = m.hexdigest() + return b[0:16] + +def encode_form(d): + hdr = { 'Content-Type': 'application/x-www-form-urlencoded' } + val = urllib.urlencode(d) + return (hdr, val) + +def main(): + #d = {'a': 1, 'b': 'x y', 'c': file('conf.sxp') } + #d = {'a': 1, 'b': 'x y' } + d = [ ('a', 1), ('b', 'x y'), ('c', file('conf.sxp')) ] + #d = [ ('a', 1), ('b', 'x y')] + v = encode_data(d) + print v[0] + sys.stdout.write(v[1]) + print + +if __name__ == "__main__": + main() |