Automatically exported from code.google.com/p/planningalerts
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

134 lines
4.8 KiB

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