wiki.pl: Port some fixes from upstream
[Orgmuse.git] / wikiupload
blob5af16ab0a12fbdf550992761f0e3aa2eb2606fba
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
8 # modify it under the terms of the GNU General Public License
9 # as published by the Free Software Foundation; either version 2
10 # of the License, or (at your option) any later version.
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.
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, write to the Free Software
19 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 # 02111-1307, USA.
22 # $Id: wikiupload,v 1.8 2010/02/08 13:40:59 as Exp $
24 import mimetypes, httplib, urllib, re, urlparse, sys, getopt
25 from time import time
27 def main():
28 summary="upload"
29 username=""
30 password=""
31 type=""
32 recent_edit="off"
33 try:
34 opts, args = getopt.getopt(sys.argv[1:],
35 "ht:s:u:p:m:",
36 ["help", "summary=", "user=", "password=", "type=", "minor-edit="])
37 except getopt.GetoptError:
38 usage(sys.stderr)
39 sys.exit(1)
40 if len(args) != 2:
41 usage(sys.stderr)
42 sys.exit(1)
43 for opt, arg in opts:
44 if opt in ("-h", "--help"):
45 usage(sys.stdout)
46 if opt in ("-s", "--summary"):
47 summary = arg
48 if opt in ("-u", "--user"):
49 username = arg
50 if opt in ("-p", "--password"):
51 password = arg
52 if opt in ("-t", "--type"):
53 type = arg
54 if opt in ("-m", "--minor-edit"):
55 recent_edit="on"
56 wikiput(args[1], args[0], summary=summary, username=username, password=password,
57 type=type, recent_edit=recent_edit)
59 def usage(out):
60 """Display the usage information for this script.
62 Options:
63 out -- The file descriptor where to write the info.
64 """
65 out.write("Usage: wikiupload [OPTIONS] file wikipage\n"
66 "Post the data in the file onto the wikipage described by wikipage.\n"
67 "\n"
68 "Example: wikiupload foaf.rdf http://your.domain.here/cgi-bin/wiki.pl/FOAF\n"
69 "\n"
70 "Options:\n"
71 " -h --help Display this help\n"
72 " -s --summary=S The summary line (default: upload)\n"
73 " -u --user=U The username to use (default: none)\n"
74 " -p --password=P The password to use (default: none)\n"
75 " -t --type=T The MIME type to use (default: guessed)\n"
76 " -m --minor-edit=B Whether this is a minor edit (default: no)\n")
78 def wikiput(where, filename,
79 summary="upload", username="", password="", type="", recent_edit="no"):
80 (host, path, title) = parse_wiki_location(where)
81 content = open(filename, "rb").read()
82 files = [['file', filename, content]]
83 params = [[ 'title', title ],
84 [ 'summary', summary ],
85 [ 'username', username ],
86 [ 'pwd', password ],
87 [ 'question', "1" ],
88 [ 'recent_edit', recent_edit ]]
89 (content_type, body) = encode_multipart_formdata(params, type, files);
90 headers = {'Content-Type': content_type}
91 conn = httplib.HTTPConnection(host)
92 conn.request("POST", path, body, headers)
93 response = conn.getresponse()
94 data = response.read()
95 conn.close()
96 if response.status != 302:
97 print "Uploading", filename, get_content_type(filename, type)
98 print response.status, response.reason
99 print response.read()
100 if response.status == 415:
101 print "Check your MIME types in one of these files:"
102 print mimetypes.knownfiles
103 sys.exit(1)
105 def encode_multipart_formdata(fields, type, files):
107 fields is a sequence of (name, value) elements for regular form fields.
108 files is a sequence of (name, filename, value) elements for data to be uploaded as files.
109 Return (content_type, body) ready for httplib.HTTP instance
111 BOUNDARY = '----------ThIs_Is_tHe_bouNdaRY_$'
112 CRLF = '\r\n'
113 L = []
114 for (key, value) in fields:
115 L.append('--' + BOUNDARY)
116 L.append('Content-Disposition: form-data; name="%s"' % key)
117 L.append('')
118 L.append(value)
119 for (key, filename, value) in files:
120 L.append('--' + BOUNDARY)
121 L.append('Content-Disposition: form-data; name="%s"; filename="%s"' % (key, filename))
122 L.append('Content-Type: %s' % get_content_type(filename, type))
123 L.append('')
124 L.append(value)
125 L.append('--' + BOUNDARY + '--')
126 L.append('')
127 body = CRLF.join(L)
128 content_type = 'multipart/form-data; boundary=%s' % BOUNDARY
129 return content_type, body
131 def get_content_type(filename, type):
132 return type or mimetypes.guess_type(filename)[0] or 'application/octet-stream'
134 def parse_wiki_location(where):
135 """Return a tuple of host, path and page name for the wiki page
136 WHERE.
138 (scheme, host, path, params, query, fragment) = urlparse.urlparse(where)
139 if not query:
140 list = path.split("/")
141 query = list.pop()
142 path = "/".join(list)
143 return (host, path+params, query)
145 if __name__ == "__main__":
146 main()