1.1 --- a/MoinMoin/_tests/test_wikiutil.py Tue Feb 10 16:18:59 2009 +0100
1.2 +++ b/MoinMoin/_tests/test_wikiutil.py Wed Feb 11 02:34:33 2009 +0100
1.3 @@ -11,6 +11,8 @@
1.4
1.5 from MoinMoin import config, wikiutil
1.6
1.7 +from werkzeug.utils import MultiDict
1.8 +
1.9
1.10 class TestQueryStringSupport:
1.11 tests = [
1.12 @@ -21,17 +23,13 @@
1.13 ]
1.14 def testParseQueryString(self):
1.15 for qstr, expected_str, expected_unicode in self.tests:
1.16 - assert wikiutil.parseQueryString(qstr, want_unicode=False) == expected_str
1.17 - assert wikiutil.parseQueryString(qstr, want_unicode=True) == expected_unicode
1.18 - assert wikiutil.parseQueryString(unicode(qstr), want_unicode=False) == expected_str
1.19 - assert wikiutil.parseQueryString(unicode(qstr), want_unicode=True) == expected_unicode
1.20 + assert wikiutil.parseQueryString(qstr) == MultiDict(expected_unicode)
1.21 + assert wikiutil.parseQueryString(unicode(qstr)) == MultiDict(expected_unicode)
1.22
1.23 def testMakeQueryString(self):
1.24 for qstr, in_str, in_unicode in self.tests:
1.25 - assert wikiutil.parseQueryString(wikiutil.makeQueryString(in_unicode, want_unicode=False), want_unicode=False) == in_str
1.26 - assert wikiutil.parseQueryString(wikiutil.makeQueryString(in_str, want_unicode=False), want_unicode=False) == in_str
1.27 - assert wikiutil.parseQueryString(wikiutil.makeQueryString(in_unicode, want_unicode=True), want_unicode=True) == in_unicode
1.28 - assert wikiutil.parseQueryString(wikiutil.makeQueryString(in_str, want_unicode=True), want_unicode=True) == in_unicode
1.29 + assert wikiutil.parseQueryString(wikiutil.makeQueryString(in_unicode)) == MultiDict(in_unicode)
1.30 + assert wikiutil.parseQueryString(wikiutil.makeQueryString(in_str)) == MultiDict(in_unicode)
1.31
1.32
1.33 class TestTickets:
2.1 --- a/MoinMoin/action/AttachFile.py Tue Feb 10 16:18:59 2009 +0100
2.2 +++ b/MoinMoin/action/AttachFile.py Wed Feb 11 02:34:33 2009 +0100
2.3 @@ -219,7 +219,7 @@
2.4 """
2.5 from MoinMoin.logfile import editlog
2.6 t = wikiutil.timestamp2version(time.time())
2.7 - fname = wikiutil.url_quote(filename, want_unicode=True)
2.8 + fname = wikiutil.url_quote(filename)
2.9
2.10 # Write to global log
2.11 log = editlog.EditLog(request)
3.1 --- a/MoinMoin/action/Despam.py Tue Feb 10 16:18:59 2009 +0100
3.2 +++ b/MoinMoin/action/Despam.py Wed Feb 11 02:34:33 2009 +0100
3.3 @@ -149,7 +149,7 @@
3.4 def revert_pages(request, editor, timestamp):
3.5 _ = request.getText
3.6
3.7 - editor = wikiutil.url_unquote(editor, want_unicode=False)
3.8 + editor = wikiutil.url_unquote(editor)
3.9 timestamp = int(timestamp * 1000000)
3.10 log = editlog.EditLog(request)
3.11 pages = {}
4.1 --- a/MoinMoin/logfile/eventlog.py Tue Feb 10 16:18:59 2009 +0100
4.2 +++ b/MoinMoin/logfile/eventlog.py Wed Feb 11 02:34:33 2009 +0100
4.3 @@ -46,7 +46,7 @@
4.4 # Save those http headers in UPPERcase
4.5 values[key.upper()] = value
4.6 # Encode values in a query string TODO: use more readable format
4.7 - values = wikiutil.makeQueryString(values, want_unicode=True)
4.8 + values = wikiutil.makeQueryString(values)
4.9 self._add(u"%d\t%s\t%s\n" % (mtime_usecs, eventtype, values))
4.10
4.11 def parser(self, line):
5.1 --- a/MoinMoin/parser/text_creole.py Tue Feb 10 16:18:59 2009 +0100
5.2 +++ b/MoinMoin/parser/text_creole.py Wed Feb 11 02:34:33 2009 +0100
5.3 @@ -297,7 +297,7 @@
5.4 # link to an attachment
5.5 scheme = m.group('attach_scheme')
5.6 attachment = m.group('attach_addr')
5.7 - url = wikiutil.url_unquote(attachment, want_unicode=True)
5.8 + url = wikiutil.url_unquote(attachment)
5.9 text = self.get_text(node)
5.10 return ''.join([
5.11 self.formatter.attachment_link(1, url),
5.12 @@ -321,7 +321,7 @@
5.13 if m:
5.14 if m.group('page_name'):
5.15 # inserted anchors
5.16 - url = wikiutil.url_unquote(target, want_unicode=True)
5.17 + url = wikiutil.url_unquote(target)
5.18 if target.startswith('#'):
5.19 return self.formatter.anchordef(url[1:])
5.20 # default to images
5.21 @@ -331,14 +331,14 @@
5.22 # external link
5.23 address = m.group('extern_addr')
5.24 proto = m.group('extern_proto')
5.25 - url = wikiutil.url_unquote(address, want_unicode=True)
5.26 + url = wikiutil.url_unquote(address)
5.27 return self.formatter.image(
5.28 src=url, alt=text, html_class='external_image')
5.29 elif m.group('attach_scheme'):
5.30 # link to an attachment
5.31 scheme = m.group('attach_scheme')
5.32 attachment = m.group('attach_addr')
5.33 - url = wikiutil.url_unquote(attachment, want_unicode=True)
5.34 + url = wikiutil.url_unquote(attachment)
5.35 if scheme == 'image':
5.36 return self.formatter.attachment_image(
5.37 url, alt=text, html_class='image')
5.38 @@ -350,19 +350,19 @@
5.39 # interwiki link
5.40 pass
5.41 # return "".join(["{{", self.formatter.text(target), "}}"])
5.42 - url = wikiutil.url_unquote(node.content, want_unicode=True)
5.43 + url = wikiutil.url_unquote(node.content)
5.44 return self.formatter.attachment_inlined(url, text)
5.45
5.46 # Not used
5.47 # def drawing_emit(self, node):
5.48 -# url = wikiutil.url_unquote(node.content, want_unicode=True)
5.49 +# url = wikiutil.url_unquote(node.content)
5.50 # text = self.get_text(node)
5.51 # return self.formatter.attachment_drawing(url, text)
5.52
5.53 # Not used
5.54 # def figure_emit(self, node):
5.55 # text = self.get_text(node)
5.56 -# url = wikiutil.url_unquote(node.content, want_unicode=True)
5.57 +# url = wikiutil.url_unquote(node.content)
5.58 # return ''.join([
5.59 # self.formatter.rawHTML('<div class="figure">'),
5.60 # self.get_image(url, text), self.emit_children(node),
6.1 --- a/MoinMoin/parser/text_moin_wiki.py Tue Feb 10 16:18:59 2009 +0100
6.2 +++ b/MoinMoin/parser/text_moin_wiki.py Wed Feb 11 02:34:33 2009 +0100
6.3 @@ -692,7 +692,7 @@
6.4 def _transclude_repl(self, word, groups):
6.5 """Handles transcluding content, usually embedding images."""
6.6 target = groups.get('transclude_target', '')
6.7 - target = wikiutil.url_unquote(target, want_unicode=True)
6.8 + target = wikiutil.url_unquote(target)
6.9 desc = groups.get('transclude_desc', '') or ''
6.10 params = groups.get('transclude_params', u'') or u''
6.11 acceptable_attrs_img = ['class', 'title', 'longdesc', 'width', 'height', 'align', ] # no style because of JS
6.12 @@ -723,7 +723,7 @@
6.13
6.14 elif m.group('attach_scheme'):
6.15 scheme = m.group('attach_scheme')
6.16 - url = wikiutil.url_unquote(m.group('attach_addr'), want_unicode=True)
6.17 + url = wikiutil.url_unquote(m.group('attach_addr'))
6.18 if scheme == 'attachment':
6.19 mt = wikiutil.MimeType(filename=url)
6.20 if mt.major == 'text':
6.21 @@ -894,7 +894,7 @@
6.22
6.23 elif mt.group('attach_scheme'):
6.24 scheme = mt.group('attach_scheme')
6.25 - url = wikiutil.url_unquote(mt.group('attach_addr'), want_unicode=True)
6.26 + url = wikiutil.url_unquote(mt.group('attach_addr'))
6.27 tag_attrs, query_args = self._get_params(params,
6.28 tag_attrs={'title': desc, },
6.29 acceptable_attrs=acceptable_attrs)
7.1 --- a/MoinMoin/script/migration/_conv160.py Tue Feb 10 16:18:59 2009 +0100
7.2 +++ b/MoinMoin/script/migration/_conv160.py Wed Feb 11 02:34:33 2009 +0100
7.3 @@ -108,7 +108,7 @@
7.4 pagename = kvdict.get('pagename')
7.5 if pagename and ('PAGE', pagename) in self.renames:
7.6 kvdict['pagename'] = self.renames[('PAGE', pagename)]
7.7 - kvpairs = wikiutil.makeQueryString(kvdict, want_unicode=False)
7.8 + kvpairs = wikiutil.makeQueryString(kvdict)
7.9 fields = str(timestamp), action, kvpairs
7.10 line = '\t'.join(fields) + '\n'
7.11 f.write(line)
8.1 --- a/MoinMoin/script/migration/_conv160_wiki.py Tue Feb 10 16:18:59 2009 +0100
8.2 +++ b/MoinMoin/script/migration/_conv160_wiki.py Wed Feb 11 02:34:33 2009 +0100
8.3 @@ -332,7 +332,7 @@
8.4 pagename, fname = AttachFile.absoluteName(fname, self.pagename)
8.5 from_this_page = pagename == self.pagename
8.6 fname = self._replace(('FILE', pagename, fname))
8.7 - fname = wikiutil.url_unquote(fname, want_unicode=True)
8.8 + fname = wikiutil.url_unquote(fname)
8.9 fname = self._replace(('FILE', pagename, fname))
8.10 pagename = self._replace(('PAGE', pagename))
8.11 if from_this_page:
9.1 --- a/MoinMoin/script/migration/_conv160a.py Tue Feb 10 16:18:59 2009 +0100
9.2 +++ b/MoinMoin/script/migration/_conv160a.py Wed Feb 11 02:34:33 2009 +0100
9.3 @@ -108,7 +108,7 @@
9.4 pagename = kvdict.get('pagename')
9.5 if pagename and ('PAGE', pagename) in self.renames:
9.6 kvdict['pagename'] = self.renames[('PAGE', pagename)]
9.7 - kvpairs = wikiutil.makeQueryString(kvdict, want_unicode=False)
9.8 + kvpairs = wikiutil.makeQueryString(kvdict)
9.9 fields = str(timestamp), action, kvpairs
9.10 line = '\t'.join(fields) + '\n'
9.11 f.write(line)
10.1 --- a/MoinMoin/script/migration/_conv160a_wiki.py Tue Feb 10 16:18:59 2009 +0100
10.2 +++ b/MoinMoin/script/migration/_conv160a_wiki.py Wed Feb 11 02:34:33 2009 +0100
10.3 @@ -322,7 +322,7 @@
10.4 pagename, fname = AttachFile.absoluteName(fname, self.pagename)
10.5 from_this_page = pagename == self.pagename
10.6 fname = self._replace(('FILE', pagename, fname))
10.7 - #fname = wikiutil.url_unquote(fname, want_unicode=True)
10.8 + #fname = wikiutil.url_unquote(fname)
10.9 #fname = self._replace(('FILE', pagename, fname))
10.10 pagename = self._replace(('PAGE', pagename))
10.11 if from_this_page:
11.1 --- a/MoinMoin/script/migration/text_moin158_wiki.py Tue Feb 10 16:18:59 2009 +0100
11.2 +++ b/MoinMoin/script/migration/text_moin158_wiki.py Wed Feb 11 02:34:33 2009 +0100
11.3 @@ -217,7 +217,7 @@
11.4 inline = url[0] == 'i'
11.5 drawing = url[0] == 'd'
11.6 url = url.split(":", 1)[1]
11.7 - url = wikiutil.url_unquote(url, want_unicode=True)
11.8 + url = wikiutil.url_unquote(url)
11.9 text = text or url
11.10
11.11 from MoinMoin.action import AttachFile
12.1 --- a/MoinMoin/stats/hitcounts.py Tue Feb 10 16:18:59 2009 +0100
12.2 +++ b/MoinMoin/stats/hitcounts.py Wed Feb 11 02:34:33 2009 +0100
12.3 @@ -146,9 +146,7 @@
12.4 # check params
12.5 filterpage = None
12.6 if params.startswith('page='):
12.7 - params = params[len('page='):]
12.8 - params = wikiutil.url_unquote(params, want_unicode=False)
12.9 - filterpage = wikiutil.decodeUserInput(params)
12.10 + filterpage = wikiutil.url_unquote(params[len('page='):])
12.11
12.12 if request and request.values and 'page' in request.values:
12.13 filterpage = request.values['page']
13.1 --- a/MoinMoin/wikiutil.py Tue Feb 10 16:18:59 2009 +0100
13.2 +++ b/MoinMoin/wikiutil.py Wed Feb 11 02:34:33 2009 +0100
13.3 @@ -25,6 +25,8 @@
13.4 from MoinMoin.support.python_compatibility import rsplit
13.5 from inspect import getargspec, isfunction, isclass, ismethod
13.6
13.7 +from MoinMoin import web # needed so that next line works:
13.8 +import werkzeug.utils
13.9
13.10 # Exceptions
13.11 class InvalidFileNameError(Exception):
13.12 @@ -88,107 +90,67 @@
13.13 raise UnicodeError('The string %r cannot be decoded.' % s)
13.14
13.15
13.16 -# this is a thin wrapper around urllib (urllib only handles str, not unicode)
13.17 -# with py <= 2.4.1, it would give incorrect results with unicode
13.18 -# with py == 2.4.2, it crashes with unicode, if it contains non-ASCII chars
13.19 -def url_quote(s, safe='/', want_unicode=False):
13.20 - """
13.21 - Wrapper around urllib.quote doing the encoding/decoding as usually wanted:
13.22 +def url_quote(s, safe='/', want_unicode=None):
13.23 + """ see werkzeug.utils.url_quote, we use a different safe param default value """
13.24 + try:
13.25 + assert want_unicode is None
13.26 + except AssertionError:
13.27 + log.exception("call with deprecated want_unicode param, please fix caller")
13.28 + return werkzeug.utils.url_quote(s, charset=config.charset, safe=safe)
13.29
13.30 - @param s: the string to quote (can be str or unicode, if it is unicode,
13.31 - config.charset is used to encode it before calling urllib)
13.32 - @param safe: just passed through to urllib
13.33 - @param want_unicode: for the less usual case that you want to get back
13.34 - unicode and not str, set this to True
13.35 - Default is False.
13.36 - """
13.37 - if isinstance(s, unicode):
13.38 - s = s.encode(config.charset)
13.39 - elif not isinstance(s, str):
13.40 - s = str(s)
13.41 - s = urllib.quote(s, safe)
13.42 - if want_unicode:
13.43 - s = s.decode(config.charset) # ascii would also work
13.44 - return s
13.45 +def url_quote_plus(s, safe='/', want_unicode=None):
13.46 + """ see werkzeug.utils.url_quote_plus, we use a different safe param default value """
13.47 + try:
13.48 + assert want_unicode is None
13.49 + except AssertionError:
13.50 + log.exception("call with deprecated want_unicode param, please fix caller")
13.51 + return werkzeug.utils.url_quote_plus(s, charset=config.charset, safe=safe)
13.52
13.53 -def url_quote_plus(s, safe='/', want_unicode=False):
13.54 - """
13.55 - Wrapper around urllib.quote_plus doing the encoding/decoding as usually wanted:
13.56 +def url_unquote(s, want_unicode=None):
13.57 + """ see werkzeug.utils.url_unquote """
13.58 + try:
13.59 + assert want_unicode is None
13.60 + except AssertionError:
13.61 + log.exception("call with deprecated want_unicode param, please fix caller")
13.62 + return werkzeug.utils.url_unquote(s, charset=config.charset, errors='fallback:iso-8859-1')
13.63
13.64 - @param s: the string to quote (can be str or unicode, if it is unicode,
13.65 - config.charset is used to encode it before calling urllib)
13.66 - @param safe: just passed through to urllib
13.67 - @param want_unicode: for the less usual case that you want to get back
13.68 - unicode and not str, set this to True
13.69 - Default is False.
13.70 - """
13.71 - if isinstance(s, unicode):
13.72 - s = s.encode(config.charset)
13.73 - elif not isinstance(s, str):
13.74 - s = str(s)
13.75 - s = urllib.quote_plus(s, safe)
13.76 - if want_unicode:
13.77 - s = s.decode(config.charset) # ascii would also work
13.78 - return s
13.79
13.80 -def url_unquote(s, want_unicode=True):
13.81 - """
13.82 - Wrapper around urllib.unquote doing the encoding/decoding as usually wanted:
13.83 +def parseQueryString(qstr, want_unicode=None):
13.84 + """ see werkzeug.utils.url_decode """
13.85 + try:
13.86 + assert want_unicode is None
13.87 + except AssertionError:
13.88 + log.exception("call with deprecated want_unicode param, please fix caller")
13.89 + return werkzeug.utils.url_decode(qstr, charset=config.charset, errors='fallback:iso-8859-1',
13.90 + decode_keys=False, include_empty=False)
13.91
13.92 - @param s: the string to unquote (can be str or unicode, if it is unicode,
13.93 - config.charset is used to encode it before calling urllib)
13.94 - @param want_unicode: for the less usual case that you want to get back
13.95 - str and not unicode, set this to False.
13.96 - Default is True.
13.97 - """
13.98 - if isinstance(s, unicode):
13.99 - s = s.encode(config.charset) # ascii would also work
13.100 - s = urllib.unquote(s)
13.101 - if want_unicode:
13.102 - try:
13.103 - s = decodeUserInput(s, [config.charset, 'iso-8859-1', ]) # try hard
13.104 - except UnicodeError:
13.105 - s = s.decode('ascii', 'replace') # better than crashing
13.106 - return s
13.107 -
13.108 -def parseQueryString(qstr, want_unicode=True):
13.109 - """ Parse a querystring "key=value&..." into a dict.
13.110 - """
13.111 - is_unicode = isinstance(qstr, unicode)
13.112 - if is_unicode:
13.113 - qstr = qstr.encode(config.charset)
13.114 - values = {}
13.115 - for key, value in cgi.parse_qs(qstr).items():
13.116 - if len(value) < 2:
13.117 - v = ''.join(value)
13.118 - if want_unicode:
13.119 - try:
13.120 - v = unicode(v, config.charset)
13.121 - except UnicodeDecodeError:
13.122 - v = unicode(v, 'iso-8859-1', 'replace')
13.123 - values[key] = v
13.124 - return values
13.125 -
13.126 -def makeQueryString(qstr=None, want_unicode=False, **kw):
13.127 +def makeQueryString(qstr=None, want_unicode=None, **kw):
13.128 """ Make a querystring from arguments.
13.129
13.130 kw arguments overide values in qstr.
13.131
13.132 - If a string is passed in, it's returned verbatim and
13.133 - keyword parameters are ignored.
13.134 + If a string is passed in, it's returned verbatim and keyword parameters are ignored.
13.135 +
13.136 + See also: werkzeug.utils.url_encode
13.137
13.138 @param qstr: dict to format as query string, using either ascii or unicode
13.139 @param kw: same as dict when using keywords, using ascii or unicode
13.140 @rtype: string
13.141 @return: query string ready to use in a url
13.142 """
13.143 + try:
13.144 + assert want_unicode is None
13.145 + except AssertionError:
13.146 + log.exception("call with deprecated want_unicode param, please fix caller")
13.147 if qstr is None:
13.148 qstr = {}
13.149 + elif isinstance(qstr, (str, unicode)):
13.150 + return qstr
13.151 if isinstance(qstr, dict):
13.152 qstr.update(kw)
13.153 - items = ['%s=%s' % (url_quote_plus(key, want_unicode=want_unicode), url_quote_plus(value, want_unicode=want_unicode)) for key, value in qstr.items()]
13.154 - qstr = '&'.join(items)
13.155 - return qstr
13.156 + return werkzeug.utils.url_encode(qstr, charset=config.charset, encode_keys=True)
13.157 + else:
13.158 + raise ValueError("Unsupported argument type, should be dict.")
13.159
13.160
13.161 def quoteWikinameURL(pagename, charset=config.charset):
13.162 @@ -203,35 +165,13 @@
13.163 @rtype: string
13.164 @return: the quoted filename, all unsafe characters encoded
13.165 """
13.166 - pagename = pagename.encode(charset)
13.167 - return urllib.quote(pagename)
13.168 + # XXX please note that urllib.quote and werkzeug.utils.url_quote have
13.169 + # XXX different defaults for safe=...
13.170 + return werkzeug.utils.url_quote(pagename, charset=charset, safe='/')
13.171
13.172
13.173 -def escape(s, quote=0):
13.174 - """ Escape possible html tags
13.175 +escape = werkzeug.utils.escape
13.176
13.177 - Replace special characters '&', '<' and '>' by SGML entities.
13.178 - (taken from cgi.escape so we don't have to include that, even if we
13.179 - don't use cgi at all)
13.180 -
13.181 - @param s: (unicode) string to escape
13.182 - @param quote: bool, should transform '\"' to '"'
13.183 - @rtype: when called with a unicode object, return unicode object - otherwise return string object
13.184 - @return: escaped version of s
13.185 - """
13.186 - if not isinstance(s, (str, unicode)):
13.187 - s = str(s)
13.188 -
13.189 - # Must first replace &
13.190 - s = s.replace("&", "&")
13.191 -
13.192 - # Then other...
13.193 - s = s.replace("<", "<")
13.194 - s = s.replace(">", ">")
13.195 - if quote:
13.196 - s = s.replace('"', """)
13.197 - s = s.replace("'", "'")
13.198 - return s
13.199
13.200 def clean_input(text, max_len=201):
13.201 """ Clean input: