wikiutil: replace moin's cgi/urllib wrappers by calls to werkzeug.utils code
authorThomas Waldmann <tw AT waldmann-edv DOT de>
Wed Feb 11 02:34:33 2009 +0100 (18 months ago)
changeset 45693caaa8c74c41
parent 4568def073ae536c
child 4570e86a7b66eb0e
wikiutil: replace moin's cgi/urllib wrappers by calls to werkzeug.utils code
MoinMoin/_tests/test_wikiutil.py
MoinMoin/action/AttachFile.py
MoinMoin/action/Despam.py
MoinMoin/logfile/eventlog.py
MoinMoin/parser/text_creole.py
MoinMoin/parser/text_moin_wiki.py
MoinMoin/script/migration/_conv160.py
MoinMoin/script/migration/_conv160_wiki.py
MoinMoin/script/migration/_conv160a.py
MoinMoin/script/migration/_conv160a_wiki.py
MoinMoin/script/migration/text_moin158_wiki.py
MoinMoin/stats/hitcounts.py
MoinMoin/wikiutil.py
     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 '&quot;'
  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("&", "&amp;")
  13.191 -
  13.192 -    # Then other...
  13.193 -    s = s.replace("<", "&lt;")
  13.194 -    s = s.replace(">", "&gt;")
  13.195 -    if quote:
  13.196 -        s = s.replace('"', "&quot;")
  13.197 -        s = s.replace("'", "&#x27;")
  13.198 -    return s
  13.199  
  13.200  def clean_input(text, max_len=201):
  13.201      """ Clean input: