00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 """
00020 Usage:
00021 Enables the use of multipart/form-data for posting forms
00022
00023 Inspirations:
00024 Upload files in python:
00025 http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/146306
00026 urllib2_file:
00027 Fabien Seisen: <fabien@seisen.org>
00028
00029 Example:
00030 import MultipartPostHandler, urllib2, cookielib
00031
00032 cookies = cookielib.CookieJar()
00033 opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookies),
00034 MultipartPostHandler.MultipartPostHandler)
00035 params = { "username" : "bob", "password" : "riviera",
00036 "file" : open("filename", "rb") }
00037 opener.open("http://wwww.bobsite.com/upload/", params)
00038
00039 Further Example:
00040 The main function of this file is a sample which downloads a page and
00041 then uploads it to the W3C validator.
00042 """
00043
00044 import urllib
00045 import urllib2
00046 import mimetools, mimetypes
00047 import os, stat
00048 from cStringIO import StringIO
00049
00050 class Callable:
00051 def __init__(self, anycallable):
00052 self.__call__ = anycallable
00053
00054
00055
00056 doseq = 1
00057
00058 class MultipartPostHandler(urllib2.BaseHandler):
00059 handler_order = urllib2.HTTPHandler.handler_order - 10
00060
00061 def http_request(self, request):
00062 data = request.get_data()
00063 if data is not None and type(data) != str:
00064 v_files = []
00065 v_vars = []
00066 try:
00067 for(key, value) in data.items():
00068 if type(value) == file:
00069 v_files.append((key, value))
00070 else:
00071 v_vars.append((key, value))
00072 except TypeError:
00073 systype, value, traceback = sys.exc_info()
00074 raise TypeError, "not a valid non-string sequence or mapping object", traceback
00075
00076 if len(v_files) == 0:
00077 data = urllib.urlencode(v_vars, doseq)
00078 else:
00079 boundary, data = self.multipart_encode(v_vars, v_files)
00080
00081 contenttype = 'multipart/form-data; boundary=%s' % boundary
00082 if(request.has_header('Content-Type')
00083 and request.get_header('Content-Type').find('multipart/form-data') != 0):
00084 print "Replacing %s with %s" % (request.get_header('content-type'), 'multipart/form-data')
00085 request.add_unredirected_header('Content-Type', contenttype)
00086
00087 request.add_data(data)
00088
00089 return request
00090
00091 def multipart_encode(vars, files, boundary = None, buf = None):
00092 if boundary is None:
00093 boundary = mimetools.choose_boundary()
00094 if buf is None:
00095 buf = StringIO()
00096 for(key, value) in vars:
00097 buf.write('--%s\r\n' % boundary)
00098 buf.write('Content-Disposition: form-data; name="%s"' % key)
00099 buf.write('\r\n\r\n' + value + '\r\n')
00100 for(key, fd) in files:
00101 file_size = os.fstat(fd.fileno())[stat.ST_SIZE]
00102 filename = fd.name.split('/')[-1]
00103 contenttype = mimetypes.guess_type(filename)[0] or 'application/octet-stream'
00104 buf.write('--%s\r\n' % boundary)
00105 buf.write('Content-Disposition: form-data; name="%s"; filename="%s"\r\n' % (key, filename))
00106 buf.write('Content-Type: %s\r\n' % contenttype)
00107
00108 fd.seek(0)
00109 buf.write('\r\n' + fd.read() + '\r\n')
00110 buf.write('--' + boundary + '--\r\n\r\n')
00111 buf = buf.getvalue()
00112 return boundary, buf
00113 multipart_encode = Callable(multipart_encode)
00114
00115 https_request = http_request
00116
00117 def main():
00118 import tempfile, sys
00119
00120 validatorURL = "http://validator.w3.org/check"
00121 opener = urllib2.build_opener(MultipartPostHandler)
00122
00123 def validateFile(url):
00124 temp = tempfile.mkstemp(suffix=".html")
00125 os.write(temp[0], opener.open(url).read())
00126 params = { "ss" : "0",
00127 "doctype" : "Inline",
00128 "uploaded_file" : open(temp[1], "rb") }
00129 print opener.open(validatorURL, params).read()
00130 os.remove(temp[1])
00131
00132 if len(sys.argv[1:]) > 0:
00133 for arg in sys.argv[1:]:
00134 validateFile(arg)
00135 else:
00136 validateFile("http://www.google.com")
00137
00138 if __name__=="__main__":
00139 main()