home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / share / pyshared / launchpadbugs / multipartpost_handler.py < prev    next >
Encoding:
Python Source  |  2007-07-05  |  4.7 KB  |  133 lines

  1. #!/usr/bin/python
  2.  
  3. ####
  4. # 02/2006 Will Holcomb <wholcomb@gmail.com>
  5. # This library is free software; you can redistribute it and/or
  6. # modify it under the terms of the GNU Lesser General Public
  7. # License as published by the Free Software Foundation; either
  8. # version 2.1 of the License, or (at your option) any later version.
  9. # This library is distributed in the hope that it will be useful,
  10. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12. # Lesser General Public License for more details.
  13. #
  14. """
  15. Usage:
  16.   Enables the use of multipart/form-data for posting forms
  17.  
  18. Inspirations:
  19.   Upload files in python:
  20.     http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/146306
  21.   urllib2_file:
  22.     Fabien Seisen: <fabien@seisen.org>
  23.  
  24. Example:
  25.   import MultipartPostHandler, urllib2, cookielib
  26.  
  27.   cookies = cookielib.CookieJar()
  28.   opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookies),
  29.                                 MultipartPostHandler.MultipartPostHandler)
  30.   params = { "username" : "bob", "password" : "riviera",
  31.              "file" : open("filename", "rb") }
  32.   opener.open("http://wwww.bobsite.com/upload/", params)
  33.  
  34. Further Example:
  35.   The main function of this file is a sample which downloads a page and
  36.   then uploads it to the W3C validator.
  37. """
  38.  
  39. import urllib
  40. import urllib2
  41. import mimetools, mimetypes
  42. import os, stat
  43.  
  44. class Callable:
  45.     def __init__(self, anycallable):
  46.         self.__call__ = anycallable
  47.  
  48. # Controls how sequences are uncoded. If true, elements may be given multiple values by
  49. #  assigning a sequence.
  50. doseq = 1
  51.  
  52. class MultipartPostHandler(urllib2.BaseHandler):
  53.     handler_order = urllib2.HTTPHandler.handler_order - 10 # needs to run first
  54.  
  55.     def http_request(self, request):
  56.         data = request.get_data()
  57.         if data is not None and type(data) != str:
  58.             v_files = []
  59.             v_vars = []
  60.             try:
  61.                  for(key, value) in data.items():
  62.                      if type(value) == file:
  63.                          v_files.append((key, value))
  64.                      else:
  65.                          v_vars.append((key, value))
  66.             except TypeError:
  67.                 systype, value, traceback = sys.exc_info()
  68.                 raise TypeError, "not a valid non-string sequence or mapping object", traceback
  69.  
  70.             if len(v_files) == 0:
  71.                 data = urllib.urlencode(v_vars, doseq)
  72.             else:
  73.                 boundary, data = self.multipart_encode(v_vars, v_files)
  74.                 contenttype = 'multipart/form-data; boundary=%s' % boundary
  75.                 if(request.has_header('Content-Type')
  76.                    and request.get_header('Content-Type').find('multipart/form-data') != 0):
  77.                     print "Replacing %s with %s" % (request.get_header('content-type'), 'multipart/form-data')
  78.                 request.add_unredirected_header('Content-Type', contenttype)
  79.  
  80.             request.add_data(data)
  81.         return request
  82.  
  83.     def multipart_encode(vars, files, boundary = None, buffer = None):
  84.         if boundary is None:
  85.             boundary = mimetools.choose_boundary()
  86.         if buffer is None:
  87.             buffer = ''
  88.         for(key, value) in vars:
  89.             buffer += '--%s\r\n' % boundary
  90.             buffer += 'Content-Disposition: form-data; name="%s"' % key
  91.             buffer += '\r\n\r\n' + value + '\r\n'
  92.         for(key, fd) in files:
  93.             file_size = os.fstat(fd.fileno())[stat.ST_SIZE]
  94.             filename = fd.name.split('/')[-1]
  95.             contenttype = mimetypes.guess_type(filename)[0] or 'application/octet-stream'
  96.             buffer += '--%s\r\n' % boundary
  97.             buffer += 'Content-Disposition: form-data; name="%s"; filename="%s"\r\n' % (key, filename)
  98.             buffer += 'Content-Type: %s\r\n' % contenttype
  99.             # buffer += 'Content-Length: %s\r\n' % file_size
  100.             fd.seek(0)
  101.             buffer += '\r\n' + fd.read() + '\r\n'
  102.         buffer += '--%s--\r\n\r\n' % boundary
  103.         return boundary, buffer
  104.     multipart_encode = Callable(multipart_encode)
  105.  
  106.     https_request = http_request
  107.  
  108. def main():
  109.     import tempfile, sys
  110.  
  111.     validatorURL = "http://validator.w3.org/check"
  112.     opener = urllib2.build_opener(MultipartPostHandler)
  113.  
  114.     def validateFile(url):
  115.         temp = tempfile.mkstemp(suffix=".html")
  116.         os.write(temp[0], opener.open(url).read())
  117.         params = { "ss" : "0",            # show source
  118.                    "doctype" : "Inline",
  119.                    "uploaded_file" : open(temp[1], "rb") }
  120.         print opener.open(validatorURL, params).read()
  121.         os.remove(temp[1])
  122.  
  123.     if len(sys.argv[1:]) > 0:
  124.         for arg in sys.argv[1:]:
  125.             validateFile(arg)
  126.     else:
  127.         validateFile("http://www.google.com")
  128.  
  129. if __name__=="__main__":
  130.     main()
  131.