changeset 101:2202f548cbb0

use own urllib wrapper, see wikiutil imported from: moin--main--1.5--patch-103
author Thomas Waldmann <tw@waldmann-edv.de>
date Sat, 15 Oct 2005 16:56:39 +0000
parents 9aa2836c997b
children a54cebaab73e
files MoinMoin/Page.py MoinMoin/action/AttachFile.py MoinMoin/action/Despam.py MoinMoin/converter/text_html_text_x_moin.py MoinMoin/formatter/text_html.py MoinMoin/macro/FullSearch.py MoinMoin/macro/RecentChanges.py MoinMoin/macro/WantedPages.py MoinMoin/parser/wiki.py MoinMoin/request.py MoinMoin/scripts/reducewiki/reducewiki.py MoinMoin/server/standalone.py MoinMoin/util/web.py MoinMoin/wikiaction.py MoinMoin/wikirpc.py MoinMoin/wikiutil.py docs/CHANGES
diffstat 17 files changed, 116 insertions(+), 87 deletions(-) [+]
line wrap: on
line diff
--- a/MoinMoin/Page.py	Sat Oct 15 14:55:25 2005 +0000
+++ b/MoinMoin/Page.py	Sat Oct 15 16:56:39 2005 +0000
@@ -6,7 +6,7 @@
     @license: GNU GPL, see COPYING for details.
 """
 
-import StringIO, os, re, urllib, random, codecs
+import StringIO, os, re, random, codecs
 
 from MoinMoin import config, caching, user, util, wikiutil
 from MoinMoin.logfile import eventlog
@@ -842,7 +842,7 @@
 
         # Add anchor
         if anchor:
-            url = "%s#%s" % (url, urllib.quote_plus(anchor.encode(config.charset)))
+            url = "%s#%s" % (url, wikiutil.url_quote_plus(anchor))
 
         # Add css class for non existing page
         if not self.exists():
@@ -1034,7 +1034,7 @@
                 request.http_redirect('%s/%s?action=show&redirect=%s' % (
                     request.getScriptname(),
                     wikiutil.quoteWikinameURL(pi_redirect),
-                    urllib.quote_plus(self.page_name.encode(config.charset), ''),))
+                    wikiutil.url_quote_plus(self.page_name, ''),))
                 return
             elif verb == "deprecated":
                 # deprecated page, append last backup version to current contents
@@ -1122,7 +1122,7 @@
                 link = '%s/%s?action=fullsearch&amp;value=%s&amp;context=180' % (
                     request.getScriptname(),
                     wikiutil.quoteWikinameURL(self.page_name),
-                    urllib.quote_plus(full_text_query.encode(config.charset)))
+                    wikiutil.url_quote_plus(full_text_query))
 
                 title = self.split_title(request)
                 if self.rev:
--- a/MoinMoin/action/AttachFile.py	Sat Oct 15 14:55:25 2005 +0000
+++ b/MoinMoin/action/AttachFile.py	Sat Oct 15 16:56:39 2005 +0000
@@ -25,7 +25,7 @@
     @license: GNU GPL, see COPYING for details.
 """
 
-import os, mimetypes, time, urllib, zipfile
+import os, mimetypes, time, zipfile
 from MoinMoin import config, user, util, wikiutil, packages
 from MoinMoin.Page import Page
 from MoinMoin.util import MoinMoinNoFooter, filesys, web
@@ -83,12 +83,12 @@
 
         url = "%s/%s/attachments/%s%s" % (
             request.cfg.attachments['url'], wikiutil.quoteWikinameFS(pagename),
-            urllib.quote(filename.encode(config.charset)), timestamp)
+            wikiutil.url_quote(filename), timestamp)
     else:
         # send file via CGI
         url = "%s/%s?action=%s&do=get&target=%s" % (
             request.getScriptname(), wikiutil.quoteWikinameURL(pagename),
-            action_name, urllib.quote_plus(filename.encode(config.charset)))
+            action_name, wikiutil.url_quote_plus(filename))
     if escaped:
         url = wikiutil.escape(url)
     return url
@@ -147,8 +147,7 @@
     """
     from MoinMoin.logfile import editlog
     t = wikiutil.timestamp2version(time.time())
-    # urllib always return ascii
-    fname = unicode(urllib.quote(filename.encode(config.charset)))
+    fname = wikiutil.url_quote(filename, want_unicode=True)
 
     # TODO: for now we simply write 2 logs, maybe better use some multilog stuff
     # Write to global log
@@ -214,7 +213,7 @@
             baseurl = request.getScriptname()
             action = action_name
             urlpagename = wikiutil.quoteWikinameURL(pagename)
-            urlfile = urllib.quote_plus(file.encode(config.charset))
+            urlfile = wikiutil.url_quote_plus(file)
 
             base, ext = os.path.splitext(file)
             get_url = getAttachUrl(pagename, file, request, escaped=1)
@@ -290,7 +289,7 @@
         for file in files:
             url = "%s/%s?action=%s&do=view&target=%s" % (
                 scriptName, pagename_quoted,
-                action_name, urllib.quote_plus(file.encode(config.charset)))
+                action_name, wikiutil.url_quote_plus(file))
 
             request.write(u'<link rel="Appendix" title="%s" href="%s">\n' % (
                 wikiutil.escape(file), wikiutil.escape(url)))
--- a/MoinMoin/action/Despam.py	Sat Oct 15 14:55:25 2005 +0000
+++ b/MoinMoin/action/Despam.py	Sat Oct 15 16:56:39 2005 +0000
@@ -8,7 +8,7 @@
     @license: GNU GPL, see COPYING for details.
 """
 
-import time, urllib
+import time
 
 from MoinMoin.logfile import editlog
 from MoinMoin.util.dataset import TupleDataset, Column
@@ -46,7 +46,7 @@
                        Column('pages', label=_("Pages"), align='right'),
                        Column('link', label='', align='left')]
     for nr, editor in editors:
-        dataset.addRow((editor, unicode(nr), pg.link_to(request, text=_("Select Author"), querystr="action=Despam&editor=%s" % urllib.quote_plus(editor))))
+        dataset.addRow((editor, unicode(nr), pg.link_to(request, text=_("Select Author"), querystr="action=Despam&editor=%s" % wikiutil.url_quote_plus(editor))))
     
     table = DataBrowserWidget(request)
     table.setData(dataset)
@@ -91,7 +91,7 @@
 </form>
 </p>
 ''' % (request.getScriptname(), wikiutil.quoteWikinameURL(pagename),
-       urllib.quote(editor), _("Revert all!")))
+       wikiutil.url_quote(editor), _("Revert all!")))
 
 def revert_page(request, pagename, editor):
     if not request.user.may.revert(pagename):
@@ -122,7 +122,7 @@
 def revert_pages(request, editor, timestamp):
     _ =  request.getText
 
-    editor = urllib.unquote(editor)
+    editor = wikiutil.url_unquote(editor, want_unicode=False)
     timestamp = int(timestamp * 1000000)
     log = editlog.EditLog(request)
     pages = {}
--- a/MoinMoin/converter/text_html_text_x_moin.py	Sat Oct 15 14:55:25 2005 +0000
+++ b/MoinMoin/converter/text_html_text_x_moin.py	Sat Oct 15 16:56:39 2005 +0000
@@ -5,9 +5,9 @@
     @license: GNU GPL, see COPYING for details.
 """
 
+import re
 import xml.dom.minidom
 from xml.dom import Node
-import re, urllib
 
 from MoinMoin import config, wikiutil, error
 
@@ -714,11 +714,6 @@
                     raise ConvertError("process_table_record: Don't support %s element" % name)
         self.text.append("||\n")
 
-    def _unquote_url(self, url): # XXX is it necessary to have "yet another unquote function"?
-        url = str(url)
-        url = urllib.unquote(url)
-        return unicode(url, 'utf-8', 'replace')
-
     def process_a(self, node):
         scriptname = self.request.getScriptname()
         if scriptname == "":
@@ -726,7 +721,7 @@
         # can either be a link (with href) or an anchor (with e.g. id)
         href = node.attributes.get("href", None)
         if href:
-            href = self._unquote_url(href.nodeValue)
+            href = wikiutil.url_unquote(href.nodeValue)
         id = node.attributes.get("id", None)
         if id:
             id = id.nodeValue
@@ -772,7 +767,7 @@
 
             # Attachments
             if title and title.startswith("attachment:"):
-                url = self._unquote_url(title[len("attachment:"):])
+                url = wikiutil.url_unquote(title[len("attachment:"):])
                 if url != text:
                     self.text.append("[%s %s]" % (title, text))
                 else:
@@ -816,7 +811,7 @@
     def process_img(self, node):
         src = None
         if node.attributes.has_key("src"):
-            src = self._unquote_url(node.attributes.get("src").nodeValue)
+            src = wikiutil.url_unquote(node.attributes.get("src").nodeValue)
         title = None
         if node.attributes.has_key("title"):
             title = node.attributes.get("title").nodeValue
@@ -826,14 +821,14 @@
 
         # Attachment image
         if (title and title.startswith("attachment:") and
-            wikiutil.isPicture(self._unquote_url(title[len("attachment:"):]))):
+            wikiutil.isPicture(wikiutil.url_unquote(title[len("attachment:"):]))):
             self.text.extend([self.white_space,
-                              self._unquote_url(title),
+                              wikiutil.url_unquote(title),
                               self.white_space])
         # Drawing image
         elif title and title.startswith("drawing:"):
             self.text.extend([self.white_space,
-                              self._unquote_url(title),
+                              wikiutil.url_unquote(title),
                               self.white_space])
         # Smiley
         elif src and (self.request.cfg.url_prefix in src or '../' in src) and "img/" in src: # XXX this is dirty!
--- a/MoinMoin/formatter/text_html.py	Sat Oct 15 14:55:25 2005 +0000
+++ b/MoinMoin/formatter/text_html.py	Sat Oct 15 16:56:39 2005 +0000
@@ -5,7 +5,7 @@
     @copyright: 2000 - 2004 by Jürgen Hermann <jh@web.de>
     @license: GNU GPL, see COPYING for details.
 """
-import os.path, urllib, re
+import os.path, re
 from MoinMoin.formatter.base import FormatterBase
 from MoinMoin import wikiutil, i18n, config
 from MoinMoin.Page import Page
@@ -242,10 +242,9 @@
         wikitag, wikiurl, wikitail, wikitag_bad = wikiutil.resolve_wiki(self.request, '%s:%s' % (interwiki, pagename))
         wikiurl = wikiutil.mapURL(self.request, wikiurl)
         if wikitag == 'Self': # for own wiki, do simple links
-            import urllib
             if wikitail.find('#') > -1:
                 wikitail, kw['anchor'] = wikitail.split('#', 1)
-            wikitail = urllib.unquote(wikitail)
+            wikitail = wikiutil.url_unquote(wikitail, want_unicode=False)
             try: # XXX this is the only place where we access self.page - do we need it? Crashes silently on actions!
                 return apply(self.pagelink, (on, wikiutil.AbsPageName(self.request, self.page.page_name, wikitail)), kw)
             except:
@@ -311,7 +310,7 @@
                 self.request,
                 self.text('%s?action=AttachFile&rename=%s' %
                           (wikiutil.quoteWikinameURL(pagename),
-                           urllib.quote_plus(fname.encode(config.charset)))),
+                           wikiutil.url_quote_plus(fname))),
                 linktext % {'filename': self.text(fname)})
         target = AttachFile.getAttachUrl(pagename, url, self.request)
         return (self.url(1, target, title="attachment:%s" % url) +
@@ -329,7 +328,7 @@
                 self.request,
                 self.text('%s?action=AttachFile&rename=%s' %
                           (wikiutil.quoteWikinameURL(pagename),
-                           urllib.quote_plus(fname.encode(config.charset)))),
+                           wikiutil.url_quote_plus(fname))),
                 linktext % {'filename': self.text(fname)})
         return self.image(
             title="attachment:%s" % url,
@@ -357,12 +356,15 @@
             return wikiutil.link_tag(self.request,
                 self.text('%s?action=AttachFile&rename=%s%s' % (
                     wikiutil.quoteWikinameURL(pagename),
-                    urllib.quote_plus(fname.encode(config.charset)),
-                    drawing and ('&drawing=%s' % urllib.quote(drawing.encode(config.charset))) or '')),
+                    wikiutil.url_quote_plus(fname),
+                    drawing and ('&drawing=%s' % wikiutil.url_quote(drawing)) or '')),
                 linktext % {'filename': self.text(fname)})
 
         mappath = AttachFile.getFilename(self.request, pagename, drawing + '.map')
-        edit_link = self.text('%s?action=AttachFile&rename=%s&drawing=%s' % (wikiutil.quoteWikinameURL(pagename), urllib.quote_plus(fname.encode(config.charset)), urllib.quote(drawing.encode(config.charset))))
+        edit_link = self.text('%s?action=AttachFile&rename=%s&drawing=%s' % (
+            wikiutil.quoteWikinameURL(pagename),
+            wikiutil.url_quote_plus(fname),
+            wikiutil.url_quote(drawing)))
 
         # check for map file
         if os.path.exists(mappath):
--- a/MoinMoin/macro/FullSearch.py	Sat Oct 15 14:55:25 2005 +0000
+++ b/MoinMoin/macro/FullSearch.py	Sat Oct 15 16:56:39 2005 +0000
@@ -27,7 +27,7 @@
     @license: GNU GPL, see COPYING for details.
 """
 
-import re, urllib
+import re
 from MoinMoin import config, wikiutil, search
 
 Dependencies = ["pages"]
--- a/MoinMoin/macro/RecentChanges.py	Sat Oct 15 14:55:25 2005 +0000
+++ b/MoinMoin/macro/RecentChanges.py	Sat Oct 15 16:56:39 2005 +0000
@@ -27,15 +27,7 @@
     comment = line.comment
     _ = request.getText
     if line.action.startswith('ATT'):
-        import urllib
-
-        # TODO: refactor this into the log in 1.5
-        # line.extra is urlencoded then converted to unicode.
-        # urllib.unquote require ascii - unquote(u'%xx') == u'%xx'
-        filename = line.extra.encode('ascii', 'replace')
-        filename = unicode(urllib.unquote(filename), config.charset,
-                           'replace')
-
+        filename = wikiutil.url_unquote(line.extra)
         if line.action == 'ATTNEW':
             comment = _("Upload of attachment '%(filename)s'.") % {
                 'filename': filename}
--- a/MoinMoin/macro/WantedPages.py	Sat Oct 15 14:55:25 2005 +0000
+++ b/MoinMoin/macro/WantedPages.py	Sat Oct 15 16:56:39 2005 +0000
@@ -6,7 +6,6 @@
     @license: GNU GPL, see COPYING for details.
 """
 
-import urllib
 from MoinMoin import config, wikiutil
 
 Dependencies = ["pages"]
@@ -75,7 +74,7 @@
         where.sort()
         if macro.formatter.page.page_name in where:
             where.remove(macro.formatter.page.page_name)
-        querystr='highlight=%s' % urllib.quote_plus(name.encode(config.charset))
+        querystr='highlight=%s' % wikiutil.url_quote_plus(name)
         wherelinks = [pages[pagename].link_to(request, querystr=querystr)
                       for pagename in where]
         result.append(": " + ', '.join(wherelinks))
--- a/MoinMoin/parser/wiki.py	Sat Oct 15 14:55:25 2005 +0000
+++ b/MoinMoin/parser/wiki.py	Sat Oct 15 16:56:39 2005 +0000
@@ -195,7 +195,6 @@
     def attachment(self, url_and_text, **kw):
         """ This gets called on attachment URLs.
         """
-        import urllib
         _ = self._
         if len(url_and_text) == 1:
             url = url_and_text[0]
@@ -206,7 +205,7 @@
         inline = url[0] == 'i'
         drawing = url[0] == 'd'
         url = url.split(":", 1)[1]
-        url = urllib.unquote(url)
+        url = wikiutil.url_unquote(url, want_unicode=False)
         text = text or url
 
         parts = url.split('/')
@@ -215,7 +214,6 @@
             pagename = '/'.join(parts[:-1])
             url = parts[-1]
 
-        import urllib
         from MoinMoin.action import AttachFile
         if drawing:
             return self.formatter.attachment_drawing(url, text)
--- a/MoinMoin/request.py	Sat Oct 15 14:55:25 2005 +0000
+++ b/MoinMoin/request.py	Sat Oct 15 16:56:39 2005 +0000
@@ -319,10 +319,10 @@
         # Fix path_info
         if os.name != 'posix' and self.request_uri != '':
             # Try to recreate path_info from request_uri.
-            import urlparse, urllib
+            import urlparse
             scriptAndPath = urlparse.urlparse(self.request_uri)[2]
             path = scriptAndPath.replace(self.script_name, '', 1)            
-            self.path_info = urllib.unquote(path)
+            self.path_info = wikiutil.url_unquote(path, want_unicode=False)
         elif os.name == 'nt':
             # Recode path_info to utf-8
             path = wikiutil.decodeWindowsPath(self.path_info)
@@ -410,8 +410,7 @@
 
     def makeURI(self):
         """ Return uri created from uri parts """
-        import urllib
-        uri = self.script_name + urllib.quote(self.path_info)
+        uri = self.script_name + wikiutil.url_quote(self.path_info)
         if self.query_string:
             uri += '?' + self.query_string
         return uri
@@ -422,12 +421,11 @@
         Just like CGI environment, the path is unquoted, the query is
         not.
         """
-        import urllib
         if '?' in uri:
             path, query = uri.split('?', 1)
         else:
             path, query = uri, ''
-        return urllib.unquote(path), query        
+        return wikiutil.url_unquote(path, want_unicode=False), query        
                 
     def get_user(self):
         for auth in self.cfg.auth:
@@ -538,8 +536,7 @@
         solving path_info encodig problems by calling with the page
         name as a query.
         """
-        import urllib
-        pagename = urllib.unquote(self.query_string)
+        pagename = wikiutil.url_unquote(self.query_string, want_unicode=False)
         pagename = self.decodePagename(pagename)
         pagename = self.normalizePagename(pagename)
         return pagename
--- a/MoinMoin/scripts/reducewiki/reducewiki.py	Sat Oct 15 14:55:25 2005 +0000
+++ b/MoinMoin/scripts/reducewiki/reducewiki.py	Sat Oct 15 16:56:39 2005 +0000
@@ -41,7 +41,7 @@
 sys.path.insert(0, '/org/de.wikiwikiweb.moinmaster/bin') # farmconfig/wikiconfig location
 sys.path.insert(0, '../../..')
 
-import os.path, urllib, codecs
+import os.path, codecs
 from MoinMoin import config
 from MoinMoin import wikiutil
 from MoinMoin.request import RequestCLI
--- a/MoinMoin/server/standalone.py	Sat Oct 15 14:55:25 2005 +0000
+++ b/MoinMoin/server/standalone.py	Sat Oct 15 16:56:39 2005 +0000
@@ -35,11 +35,11 @@
 """
 
 # Imports
-import os, sys, time, urllib, socket, errno, shutil
+import os, sys, time, socket, errno, shutil
 import BaseHTTPServer, SimpleHTTPServer, SocketServer
 
 # MoinMoin imports
-from MoinMoin import version
+from MoinMoin import version, wikiutil
 from MoinMoin.server import Config, switchUID
 from MoinMoin.request import RequestStandAlone
 from MoinMoin.util.datetime import formathttpdate
@@ -344,7 +344,7 @@
         Components that mean special things to the local file system
         (e.g. drive or directory names) are ignored.
         """
-        file = urllib.unquote(uri)
+        file = wikiutil.url_unquote(uri, want_unicode=False)
         file.replace('\\', '/')
         words = file.split('/')
         words = filter(None, words)
--- a/MoinMoin/util/web.py	Sat Oct 15 14:55:25 2005 +0000
+++ b/MoinMoin/util/web.py	Sat Oct 15 16:56:39 2005 +0000
@@ -6,8 +6,8 @@
     @license: GNU GPL, see COPYING for details.
 """
 
-import re, urllib
-from MoinMoin import config
+import re
+from MoinMoin import config, wikiutil
 
 def isSpiderAgent(request):
     """ Return True if user agent appears to be a spider.
@@ -50,7 +50,7 @@
         qstr = {}
     if isinstance(qstr, type({})):
         qstr.update(kw)        
-        q = lambda x: urllib.quote_plus(unicode(x).encode(config.charset))
+        q = lambda x: wikiutil.url_quote_plus(x)
         items = ['%s=%s' % (q(key), q(value)) for key, value in qstr.items()]
         qstr = '&'.join(items)
     
--- a/MoinMoin/wikiaction.py	Sat Oct 15 14:55:25 2005 +0000
+++ b/MoinMoin/wikiaction.py	Sat Oct 15 16:56:39 2005 +0000
@@ -19,7 +19,7 @@
     @license: GNU GPL, see COPYING for details.
 """
 
-import os, re, time, urllib
+import os, re, time
 from MoinMoin import config, util, wikiutil
 from MoinMoin.Page import Page
 from MoinMoin.util import MoinMoinNoFooter, pysupport
@@ -317,13 +317,7 @@
                 rev = '-'
                 diff = '-'
                 
-                # TODO: refactor this into the log in 1.5
-                # line.extra is urlencoded then converted to unicode.
-                # urllib.unquote require ascii - unquote(u'%xx') == u'%xx'
-                filename = line.extra.encode('ascii', 'replace')
-                filename = unicode(urllib.unquote(filename), config.charset,
-                                   'replace')
-
+                filename = wikiutil.url_unquote(line.extra)
                 comment = "%s: %s %s" % (line.action, filename, line.comment)
                 size = 0
                 if line.action != 'ATTDEL':
@@ -418,7 +412,7 @@
     
     if show_hitcounts:
         from MoinMoin.stats import hitcounts
-        request.write(hitcounts.linkto(pagename, request, 'page=' + urllib.quote_plus(pagename.encode(config.charset))))
+        request.write(hitcounts.linkto(pagename, request, 'page=' + wikiutil.url_quote_plus(pagename)))
     elif show_general:
         general(page, pagename, request)
     else:
--- a/MoinMoin/wikirpc.py	Sat Oct 15 14:55:25 2005 +0000
+++ b/MoinMoin/wikirpc.py	Sat Oct 15 16:56:39 2005 +0000
@@ -24,7 +24,7 @@
     @license: GNU GPL, see COPYING for details
 """
 
-import sys, urllib, time, xmlrpclib
+import sys, time, xmlrpclib
 
 from MoinMoin import config, user, wikiutil
 from MoinMoin.Page import Page
@@ -460,11 +460,7 @@
         @rtype: unicode
         @return: text
         """
-        if isinstance(text, unicode):
-            text = text.encode('utf-8') # ascii should also work
-        text = urllib.unquote(text)
-        text = unicode(text, 'utf-8')
-        return text
+        return wikiutil.url_unquote(text) # config.charset must be utf-8
 
     def _outstr(self, text):
         """ Convert string from internal representation to xmlrpc
@@ -473,12 +469,7 @@
         @rtype: str
         @return: text encoded in utf-8 and quoted
         """
-        if isinstance(text, unicode):
-            text = text.encode('utf-8')
-        elif config.charset != 'utf-8':        
-            text = unicode(text, config.charset).encode('utf-8')
-        text = urllib.quote(text)
-        return text
+        return wikiutil.url_quote(text) # config.charset must be utf-8
 
     
 class XmlRpc2(XmlRpcBase):
--- a/MoinMoin/wikiutil.py	Sat Oct 15 14:55:25 2005 +0000
+++ b/MoinMoin/wikiutil.py	Sat Oct 15 16:56:39 2005 +0000
@@ -94,6 +94,66 @@
     raise UnicodeError('The string %r cannot be decoded.' % s)
 
 
+# this is a thin wrapper around urllib (urllib only handles str, not unicode)
+# with py <= 2.4.1, it would give incorrect results with unicode
+# with py == 2.4.2, it crashes with unicode, if it contains non-ASCII chars
+def url_quote(s, safe='/', want_unicode=False):
+    """
+    Wrapper around urllib.quote doing the encoding/decoding as usually wanted:
+    
+    @param s: the string to quote (can be str or unicode, if it is unicode,
+              config.charset is used to encode it before calling urllib)
+    @param safe: just passed through to urllib
+    @param want_unicode: for the less usual case that you want to get back
+                         unicode and not str, set this to True
+                         Default is False.
+    """
+    is_unicode = isinstance(s, unicode)
+    if is_unicode:
+        s = s.encode(config.charset)
+    s = urllib.quote(s, safe)
+    if want_unicode:
+        s = s.decode(config.charset) # ascii would also work
+    return s
+
+def url_quote_plus(s, safe='/', want_unicode=False):
+    """
+    Wrapper around urllib.quote_plus doing the encoding/decoding as usually wanted:
+    
+    @param s: the string to quote (can be str or unicode, if it is unicode,
+              config.charset is used to encode it before calling urllib)
+    @param safe: just passed through to urllib
+    @param want_unicode: for the less usual case that you want to get back
+                         unicode and not str, set this to True
+                         Default is False.
+    """
+    is_unicode = isinstance(s, unicode)
+    if is_unicode:
+        s = s.encode(config.charset)
+    s = urllib.quote_plus(s, safe)
+    if want_unicode:
+        s = s.decode(config.charset) # ascii would also work
+    return s
+
+def url_unquote(s, want_unicode=True):
+    """
+    Wrapper around urllib.unquote doing the encoding/decoding as usually wanted:
+    
+    @param s: the string to unquote (can be str or unicode, if it is unicode,
+              config.charset is used to encode it before calling urllib)
+    @param want_unicode: for the less usual case that you want to get back
+                         str and not unicode, set this to False.
+                         Default is True.
+    """
+    is_unicode = isinstance(s, unicode)
+    if is_unicode:
+        s = s.encode(config.charset) # ascii would also work
+    s = urllib.unquote(s)
+    if want_unicode:
+        s = s.decode(config.charset)
+    return s
+
+
 # FIXME: better name would be quoteURL, as this is useful for any
 # string, not only wiki names.
 def quoteWikinameURL(pagename, charset=config.charset):
--- a/docs/CHANGES	Sat Oct 15 14:55:25 2005 +0000
+++ b/docs/CHANGES	Sat Oct 15 16:56:39 2005 +0000
@@ -239,7 +239,9 @@
     * Fixed formatter usage in the ShowSmileys macro.
     * Fixed updating pagelinks cache for [:page:text] or [wiki:Self:page text],
       fixes display of LocalSiteMap and rendering of such links.
-    
+    * Hopefully fixed urllib problems (esp. with py 2.4.2, but also before) by
+      using our own urllib wrapper that handles encoding/decoding to/from
+      unicode, see wikiutil.py.
     
 Version 1.4: