wikiupload 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. #!/usr/bin/env python
  2. # wikiupload --- Put a wiki page on an Oddmuse wiki
  3. #
  4. # Copyright (C) 2004 Jorgen Schaefer <forcer@forcix.cx>
  5. # Copyright (C) 2005 Alex Schroeder <alex@emacswiki.org>
  6. #
  7. # This program is free software; you can redistribute it and/or modify
  8. # it under the terms of the GNU General Public License as published by
  9. # the Free Software Foundation; either version 3 of the License, or
  10. # (at your option) any later version.
  11. #
  12. # This program is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. # GNU General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU General Public License
  18. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. import mimetypes, httplib, urllib, re, urlparse, sys, getopt
  20. from time import time
  21. def main():
  22. summary="upload"
  23. username=""
  24. password=""
  25. type=""
  26. recent_edit="off"
  27. try:
  28. opts, args = getopt.getopt(sys.argv[1:],
  29. "ht:s:u:p:m:",
  30. ["help", "summary=", "user=", "password=", "type=", "minor-edit="])
  31. except getopt.GetoptError:
  32. usage(sys.stderr)
  33. sys.exit(1)
  34. if len(args) != 2:
  35. usage(sys.stderr)
  36. sys.exit(1)
  37. for opt, arg in opts:
  38. if opt in ("-h", "--help"):
  39. usage(sys.stdout)
  40. if opt in ("-s", "--summary"):
  41. summary = arg
  42. if opt in ("-u", "--user"):
  43. username = arg
  44. if opt in ("-p", "--password"):
  45. password = arg
  46. if opt in ("-t", "--type"):
  47. type = arg
  48. if opt in ("-m", "--minor-edit"):
  49. recent_edit="on"
  50. wikiput(args[1], args[0], summary=summary, username=username, password=password,
  51. type=type, recent_edit=recent_edit)
  52. def usage(out):
  53. """Display the usage information for this script.
  54. Options:
  55. out -- The file descriptor where to write the info.
  56. """
  57. out.write("Usage: wikiupload [OPTIONS] file wikipage\n"
  58. "Post the data in the file onto the wikipage described by wikipage.\n"
  59. "\n"
  60. "Example: wikiupload foaf.rdf http://your.domain.here/cgi-bin/wiki.pl/FOAF\n"
  61. "\n"
  62. "Options:\n"
  63. " -h --help Display this help\n"
  64. " -s --summary=S The summary line (default: upload)\n"
  65. " -u --user=U The username to use (default: none)\n"
  66. " -p --password=P The password to use (default: none)\n"
  67. " -t --type=T The MIME type to use (default: guessed)\n"
  68. " -m --minor-edit=B Whether this is a minor edit (default: no)\n")
  69. def wikiput(where, filename,
  70. summary="upload", username="", password="", type="", recent_edit="no"):
  71. (host, path, title) = parse_wiki_location(where)
  72. content = open(filename, "rb").read()
  73. files = [['file', filename, content]]
  74. params = [[ 'title', title ],
  75. [ 'summary', summary ],
  76. [ 'username', username ],
  77. [ 'pwd', password ],
  78. [ 'question', "1" ],
  79. [ 'recent_edit', recent_edit ]]
  80. (content_type, body) = encode_multipart_formdata(params, type, files);
  81. headers = {'Content-Type': content_type}
  82. conn = httplib.HTTPConnection(host)
  83. conn.request("POST", path, body, headers)
  84. response = conn.getresponse()
  85. data = response.read()
  86. conn.close()
  87. if response.status != 302:
  88. print "Uploading", filename, get_content_type(filename, type)
  89. print response.status, response.reason
  90. print response.read()
  91. if response.status == 415:
  92. print "Check your MIME types in one of these files:"
  93. print mimetypes.knownfiles
  94. sys.exit(1)
  95. def encode_multipart_formdata(fields, type, files):
  96. """
  97. fields is a sequence of (name, value) elements for regular form fields.
  98. files is a sequence of (name, filename, value) elements for data to be uploaded as files.
  99. Return (content_type, body) ready for httplib.HTTP instance
  100. """
  101. BOUNDARY = '----------ThIs_Is_tHe_bouNdaRY_$'
  102. CRLF = '\r\n'
  103. L = []
  104. for (key, value) in fields:
  105. L.append('--' + BOUNDARY)
  106. L.append('Content-Disposition: form-data; name="%s"' % key)
  107. L.append('')
  108. L.append(value)
  109. for (key, filename, value) in files:
  110. L.append('--' + BOUNDARY)
  111. L.append('Content-Disposition: form-data; name="%s"; filename="%s"' % (key, filename))
  112. L.append('Content-Type: %s' % get_content_type(filename, type))
  113. L.append('')
  114. L.append(value)
  115. L.append('--' + BOUNDARY + '--')
  116. L.append('')
  117. body = CRLF.join(L)
  118. content_type = 'multipart/form-data; boundary=%s' % BOUNDARY
  119. return content_type, body
  120. def get_content_type(filename, type):
  121. return type or mimetypes.guess_type(filename)[0] or 'application/octet-stream'
  122. def parse_wiki_location(where):
  123. """Return a tuple of host, path and page name for the wiki page
  124. WHERE.
  125. """
  126. (scheme, host, path, params, query, fragment) = urlparse.urlparse(where)
  127. if not query:
  128. list = path.split("/")
  129. query = list.pop()
  130. path = "/".join(list)
  131. return (host, path+params, query)
  132. if __name__ == "__main__":
  133. main()