changeset 4566:2eaf4b42b400

merged moin/1.8
author Thomas Waldmann <tw AT waldmann-edv DOT de>
date Tue, 10 Feb 2009 13:21:59 +0100
parents 7d8c6d279cff (diff) 68d29223dfa9 (current diff)
children 6ac8b2f4cdac
files .hgtags MoinMoin/Page.py MoinMoin/_tests/test_wikiutil.py MoinMoin/events/notification.py MoinMoin/formatter/_tests/test_formatter.py MoinMoin/formatter/text_html.py MoinMoin/i18n/MoinMoin.pot MoinMoin/i18n/ar.MoinMoin.po MoinMoin/i18n/bg.MoinMoin.po MoinMoin/i18n/ca.MoinMoin.po MoinMoin/i18n/cs.MoinMoin.po MoinMoin/i18n/da.MoinMoin.po MoinMoin/i18n/de.MoinMoin.po MoinMoin/i18n/el.MoinMoin.po MoinMoin/i18n/en.MoinMoin.po MoinMoin/i18n/es.MoinMoin.po MoinMoin/i18n/fa.MoinMoin.po MoinMoin/i18n/fi.MoinMoin.po MoinMoin/i18n/fr.MoinMoin.po MoinMoin/i18n/gl.MoinMoin.po MoinMoin/i18n/he.MoinMoin.po MoinMoin/i18n/hi.MoinMoin.po MoinMoin/i18n/hr.MoinMoin.po MoinMoin/i18n/hu.MoinMoin.po MoinMoin/i18n/id.MoinMoin.po MoinMoin/i18n/it.MoinMoin.po MoinMoin/i18n/ja.MoinMoin.po MoinMoin/i18n/ko.MoinMoin.po MoinMoin/i18n/ku.MoinMoin.po MoinMoin/i18n/lt.MoinMoin.po MoinMoin/i18n/lv.MoinMoin.po MoinMoin/i18n/mk.MoinMoin.po MoinMoin/i18n/mn.MoinMoin.po MoinMoin/i18n/nb.MoinMoin.po MoinMoin/i18n/nl.MoinMoin.po MoinMoin/i18n/pl.MoinMoin.po MoinMoin/i18n/pt-br.MoinMoin.po MoinMoin/i18n/pt.MoinMoin.po MoinMoin/i18n/ro.MoinMoin.po MoinMoin/i18n/ru.MoinMoin.po MoinMoin/i18n/sk.MoinMoin.po MoinMoin/i18n/sl.MoinMoin.po MoinMoin/i18n/sr.MoinMoin.po MoinMoin/i18n/sv.MoinMoin.po MoinMoin/i18n/tr.MoinMoin.po MoinMoin/i18n/uk.MoinMoin.po MoinMoin/i18n/vi.MoinMoin.po MoinMoin/i18n/zh-tw.MoinMoin.po MoinMoin/i18n/zh.MoinMoin.po MoinMoin/macro/__init__.py MoinMoin/parser/_tests/test_text_creole.py MoinMoin/userprefs/oid.py MoinMoin/wikiutil.py docs/CHANGES docs/INSTALL.html docs/UPDATE.html wiki/underlay.tar
diffstat 376 files changed, 115203 insertions(+), 80877 deletions(-) [+]
line wrap: on
line diff
--- a/MANIFEST.in	Tue Feb 10 13:08:03 2009 +0100
+++ b/MANIFEST.in	Tue Feb 10 13:21:59 2009 +0100
@@ -13,6 +13,9 @@
 # include stuff for translators
 recursive-include   MoinMoin/i18n *
 
+# include non-py stuff from werkzeug
+recursive-include   MoinMoin/support/werkzeug/debug *
+
 # contrib stuff
 recursive-include   contrib *
 
--- a/Makefile	Tue Feb 10 13:08:03 2009 +0100
+++ b/Makefile	Tue Feb 10 13:21:59 2009 +0100
@@ -13,33 +13,27 @@
 
 install-docs:
 	-mkdir build
-	wget -U MoinMoin/Makefile -O build/INSTALL.html "http://master18.moinmo.in/MoinMoin/InstallDocs?action=print"
+	wget -U MoinMoin/Makefile -O build/INSTALL.html "http://master19.moinmo.in/InstallDocs?action=print"
 	sed \
-		-e 's#href="/#href="http://master18.moinmo.in/#g' \
-		-e 's#http://[a-z\.]*/wiki/classic/#/wiki/classic/#g' \
-		-e 's#http://[a-z\.]*/wiki/modern/#/wiki/modern/#g' \
-		-e 's#http://[a-z\.]*/wiki/rightsidebar/#/wiki/rightsidebar/#g' \
-		-e 's#/wiki/classic/#wiki/htdocs/classic/#g' \
-		-e 's#/wiki/modern/#wiki/htdocs/modern/#g' \
-		-e 's#/wiki/rightsidebar/#wiki/htdocs/rightsidebar/#g' \
+		-e 's#href="/#href="http://master19.moinmo.in/#g' \
+		-e 's#http://[a-z0-9\.]*/wiki/modernized/#../wiki/htdocs/modernized/#g' \
+		-e 's#/wiki/common/#../wiki/htdocs/common/#g' \
+		-e 's#/wiki/modernized/#../wiki/htdocs/modernized/#g' \
         build/INSTALL.html >docs/INSTALL.html
 	-rm build/INSTALL.html
 
-	wget -U MoinMoin/Makefile -O build/UPDATE.html "http://master18.moinmo.in/HelpOnUpdating?action=print"
+	wget -U MoinMoin/Makefile -O build/UPDATE.html "http://master19.moinmo.in/HelpOnUpdating?action=print"
 	sed \
-		-e 's#href="/#href="http://master18.moinmo.in/#g' \
-		-e 's#http://[a-z\.]*/wiki/classic/#/wiki/classic/#g' \
-		-e 's#http://[a-z\.]*/wiki/modern/#/wiki/modern/#g' \
-		-e 's#http://[a-z\.]*/wiki/rightsidebar/#/wiki/rightsidebar/#g' \
-		-e 's#/wiki/classic/#wiki/htdocs/classic/#g' \
-		-e 's#/wiki/modern/#wiki/htdocs/modern/#g' \
-		-e 's#/wiki/rightsidebar/#wiki/htdocs/rightsidebar/#g' \
+		-e 's#href="/#href="http://master19.moinmo.in/#g' \
+		-e 's#http://[a-z0-9\.]*/wiki/modernized/#../wiki/htdocs/modernized/#g' \
+		-e 's#/wiki/common/#../wiki/htdocs/common/#g' \
+		-e 's#/wiki/modernized/#../wiki/htdocs/modernized/#g' \
         build/UPDATE.html >docs/UPDATE.html
 	-rm build/UPDATE.html
 	-rmdir build
 
 interwiki:
-	wget -U MoinMoin/Makefile -O $(share)/data/intermap.txt "http://master18.moinmo.in/InterWikiMap?action=raw"
+	wget -U MoinMoin/Makefile -O $(share)/data/intermap.txt "http://master19.moinmo.in/InterWikiMap?action=raw"
 	chmod 664 $(share)/data/intermap.txt
 
 check-tabs:
@@ -53,8 +47,8 @@
 # Should be used only on TW machine
 underlay:
 	rm -rf $(share)/underlay
-	MoinMoin/script/moin.py --config-dir=/srv/moin/cfg/1.8 --wiki-url=master18.moinmo.in/ maint globaledit
-	MoinMoin/script/moin.py --config-dir=/srv/moin/cfg/1.8 --wiki-url=master18.moinmo.in/ maint reducewiki --target-dir=$(share)/underlay
+	MoinMoin/script/moin.py --config-dir=/srv/moin/cfg/1.8 --wiki-url=master19.moinmo.in/ maint globaledit
+	MoinMoin/script/moin.py --config-dir=/srv/moin/cfg/1.8 --wiki-url=master19.moinmo.in/ maint reducewiki --target-dir=$(share)/underlay
 	rm -rf $(share)/underlay/pages/InterWikiMap
 	rm -rf $(share)/underlay/pages/MoinPagesEditorGroup
 	cd $(share); rm -f underlay.tar; tar cf underlay.tar underlay
--- a/MoinMoin/Page.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/Page.py	Tue Feb 10 13:21:59 2009 +0100
@@ -109,7 +109,8 @@
             (for 'meta') or the complete cache ('pagelists').
             @param request: the request object
         """
-        elog = request.editlog
+        from MoinMoin.logfile import editlog
+        elog = editlog.EditLog(request)
         old_pos = self.log_pos
         new_pos, items = elog.news(old_pos)
         if items:
@@ -753,6 +754,9 @@
                 url = "%s/%s/%s" % (request.cfg.url_prefix_action, action, url)
             url = '%s?%s' % (url, querystr)
 
+        if not relative:
+            url = '%s/%s' % (request.script_root, url)
+
         # Add anchor
         if anchor:
             fmt = getattr(self, 'formatter', request.html_formatter)
@@ -760,8 +764,6 @@
                 anchor = fmt.sanitize_to_id(anchor)
             url = "%s#%s" % (url, anchor)
 
-        if not relative:
-            url = '%s/%s' % (request.getScriptname(), url)
         return url
 
     def link_to_raw(self, request, text, querystr=None, anchor=None, **kw):
@@ -966,26 +968,25 @@
             offer a dialogue to save it to disk (used by Save action).
         """
         request = self.request
-        request.setHttpHeader("Content-type: text/plain; charset=%s" % config.charset)
+        request.mimetype = 'text/plain'
         if self.exists():
             # use the correct last-modified value from the on-disk file
             # to ensure cacheability where supported. Because we are sending
             # RAW (file) content, the file mtime is correct as Last-Modified header.
-            request.setHttpHeader("Status: 200 OK")
-            request.setHttpHeader("Last-Modified: %s" % util.timefuncs.formathttpdate(os.path.getmtime(self._text_filename())))
+            request.status_code = 200
+            request.last_modified = os.path.getmtime(self._text_filename())
             text = self.encodeTextMimeType(self.body)
             #request.setHttpHeader("Content-Length: %d" % len(text))  # XXX WRONG! text is unicode obj, but we send utf-8!
             if content_disposition:
                 # TODO: fix the encoding here, plain 8 bit is not allowed according to the RFCs
                 # There is no solution that is compatible to IE except stripping non-ascii chars
                 filename_enc = "%s.txt" % self.page_name.encode(config.charset)
-                request.setHttpHeader('Content-Disposition: %s; filename="%s"' % (
-                                      content_disposition, filename_enc))
+                dispo_string = '%s; filename="%s"' % (content_disposition, filename_enc)
+                request.headers.add('Content-Disposition', dispo_string)
         else:
-            request.setHttpHeader('Status: 404 NOTFOUND')
+            request.status_code = 404
             text = u"Page %s not found." % self.page_name
 
-        request.emit_http_headers()
         request.write(text)
 
     def send_page(self, **keywords):
@@ -1010,11 +1011,11 @@
         send_special = keywords.get('send_special', False)
         print_mode = keywords.get('print_mode', 0)
         if print_mode:
-            media = 'media' in request.form and request.form['media'][0] or 'print'
+            media = request.values.get('media', 'print')
         else:
             media = 'screen'
         self.hilite_re = (keywords.get('hilite_re') or
-                          request.form.get('highlight', [None])[0])
+                          request.values.get('highlight'))
 
         # count hit?
         if keywords.get('count_hit', 0):
@@ -1025,7 +1026,7 @@
         pi = self.pi
 
         if 'redirect' in pi and not (
-            'action' in request.form or 'redirect' in request.form or content_only):
+            'action' in request.values or 'redirect' in request.values or content_only):
             # redirect to another page
             # note that by including "action=show", we prevent endless looping
             # (see code in "request") or any cascaded redirection
@@ -1054,8 +1055,8 @@
             try:
                 self.formatter.set_highlight_re(self.hilite_re)
             except re.error, err:
-                if 'highlight' in request.form:
-                    del request.form['highlight']
+                if 'highlight' in request.values:
+                    del request.values['highlight']
                 request.theme.add_msg(_('Invalid highlighting regular expression "%(regex)s": %(error)s') % {
                                           'regex': self.hilite_re,
                                           'error': str(err),
@@ -1080,12 +1081,12 @@
         page_exists = self.exists()
         if not content_only:
             if emit_headers:
-                request.setHttpHeader("Content-Type: %s; charset=%s" % (self.output_mimetype, self.output_charset))
+                request.content_type = "%s; charset=%s" % (self.output_mimetype, self.output_charset)
                 if page_exists:
                     if not request.user.may.read(self.page_name):
-                        request.setHttpHeader('Status: 403 Permission Denied')
+                        request.status_code = 403
                     else:
-                        request.setHttpHeader('Status: 200 OK')
+                        request.status_code = 200
                     if not request.cacheable:
                         # use "nocache" headers if we're using a method that is not simply "display"
                         request.disableHttpCaching(level=2)
@@ -1100,8 +1101,7 @@
                         #request.setHttpHeader("Last-Modified: %s" % util.timefuncs.formathttpdate(lastmod))
                         pass
                 else:
-                    request.setHttpHeader('Status: 404 NOTFOUND')
-                request.emit_http_headers()
+                    request.status_code = 404
 
             if not page_exists and self.request.isSpiderAgent:
                 # don't send any 404 content to bots
@@ -1120,8 +1120,8 @@
 
                 # This redirect message is very annoying.
                 # Less annoying now without the warning sign.
-                if 'redirect' in request.form:
-                    redir = request.form['redirect'][0]
+                if 'redirect' in request.values:
+                    redir = request.values['redirect']
                     request.theme.add_msg('<strong>%s</strong><br>' % (
                         _('Redirected from page "%(page)s"') % {'page':
                             wikiutil.link_tag(request, wikiutil.quoteWikinameURL(redir) + "?action=show", self.formatter.text(redir))}), "info")
--- a/MoinMoin/PageEditor.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/PageEditor.py	Tue Feb 10 13:21:59 2009 +0100
@@ -197,12 +197,11 @@
 
         # Emit http_headers after checks (send_page)
         request.disableHttpCaching(level=2)
-        request.emit_http_headers()
 
         # check if we want to load a draft
         use_draft = None
         if 'button_load_draft' in form:
-            wanted_draft_timestamp = int(form.get('draft_ts', ['0'])[0])
+            wanted_draft_timestamp = int(form.get('draft_ts', '0'))
             if wanted_draft_timestamp:
                 draft = self._load_draft()
                 if draft is not None:
@@ -214,7 +213,7 @@
         if use_draft is not None:
             title = _('Draft of "%(pagename)s"')
             # Propagate original revision
-            rev = int(form['draft_rev'][0])
+            rev = int(form['draft_rev'])
             self.set_raw_body(use_draft, modified=1)
             preview = use_draft
         elif preview is None:
@@ -234,7 +233,7 @@
 
         # get request parameters
         try:
-            text_rows = int(form['rows'][0])
+            text_rows = int(form['rows'])
         except StandardError:
             text_rows = self.cfg.edit_rows
             if request.user.valid:
@@ -276,9 +275,9 @@
             # If the page exists, we get the text from the page.
             # TODO: maybe warn if template argument was ignored because the page exists?
             raw_body = self.get_raw_body()
-        elif 'template' in form:
+        elif 'template' in request.values:
             # If the page does not exist, we try to get the content from the template parameter.
-            template_page = wikiutil.unquoteWikiname(form['template'][0])
+            template_page = wikiutil.unquoteWikiname(request.values['template'])
             if request.user.may.read(template_page):
                 raw_body = Page(request, template_page).get_raw_body()
                 if raw_body:
@@ -332,10 +331,9 @@
             raw_body = _('Describe %s here.') % (self.page_name, )
 
         # send form
-        request.write('<form id="editor" method="post" action="%s/%s#preview" onSubmit="flgChange = false;">' % (
-            request.getScriptname(),
-            wikiutil.quoteWikinameURL(self.page_name),
-            ))
+        request.write('<form id="editor" method="post" action="%s#preview" onSubmit="flgChange = false;">' % (
+                request.href(self.page_name)
+        ))
 
         # yet another weird workaround for broken IE6 (it expands the text
         # editor area to the right after you begin to type...). IE sucks...
@@ -351,7 +349,7 @@
         request.write('<input type="hidden" name="ticket" value="%s">' % wikiutil.createTicket(request))
 
         # Save backto in a hidden input
-        backto = form.get('backto', [None])[0]
+        backto = request.values.get('backto')
         if backto:
             request.write(unicode(html.INPUT(type="hidden", name="backto", value=backto)))
 
@@ -410,7 +408,7 @@
     document.write('<label for="chktrivialtop">%(label)s</label>');
     //-->
 </script> ''' % {
-                'checked': ('', 'checked')[form.get('trivial', ['0'])[0] == '1'],
+                'checked': ('', 'checked')[form.get('trivial', '0') == '1'],
                 'label': _("Trivial change"),
             })
 
@@ -460,7 +458,7 @@
 <label for="chktrivial">%(label)s</label>
 
 ''' % {
-                'checked': ('', 'checked')[form.get('trivial', ['0'])[0] == '1'],
+                'checked': ('', 'checked')[form.get('trivial', '0') == '1'],
                 'label': _("Trivial change"),
                 })
 
@@ -469,7 +467,7 @@
 <input type="checkbox" name="rstrip" id="chkrstrip" value="1" %(checked)s>
 <label for="chkrstrip">%(label)s</label>
 ''' % {
-            'checked': ('', 'checked')[form.get('rstrip', ['0'])[0] == '1'],
+            'checked': ('', 'checked')[form.get('rstrip', '0') == '1'],
             'label': _('Remove trailing whitespace from each line')
             })
         request.write("</p>")
@@ -514,7 +512,7 @@
         self._save_draft(newtext, rev) # shall we really save a draft on CANCEL?
         self.lock.release()
 
-        backto = request.form.get('backto', [None])[0]
+        backto = request.values.get('backto')
         if backto:
             pg = Page(request, backto)
             request.http_redirect(pg.url(request, relative=False))
@@ -672,7 +670,7 @@
 
             # Remove cache entry (if exists)
             pg = Page(self.request, self.page_name)
-            key = self.request.form.get('key', ['text_html'])[0]
+            key = self.request.form.get('key', 'text_html') # XXX see cleanup code in deletePage
             caching.CacheEntry(self.request, pg, key, scope='item').remove()
             caching.CacheEntry(self.request, pg, "pagelinks", scope='item').remove()
 
--- a/MoinMoin/PageGraphicalEditor.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/PageGraphicalEditor.py	Tue Feb 10 13:21:59 2009 +0100
@@ -87,12 +87,11 @@
 
         # Emit http_headers after checks (send_page)
         request.disableHttpCaching(level=2)
-        request.emit_http_headers()
 
         # check if we want to load a draft
         use_draft = None
         if 'button_load_draft' in form:
-            wanted_draft_timestamp = int(form.get('draft_ts', ['0'])[0])
+            wanted_draft_timestamp = int(form.get('draft_ts', '0'))
             if wanted_draft_timestamp:
                 draft = self._load_draft()
                 if draft is not None:
@@ -104,7 +103,7 @@
         if use_draft is not None:
             title = _('Draft of "%(pagename)s"')
             # Propagate original revision
-            rev = int(form['draft_rev'][0])
+            rev = int(form['draft_rev'])
             self.set_raw_body(use_draft, modified=1)
             preview = use_draft
         elif preview is None:
@@ -124,7 +123,7 @@
 
         # get request parameters
         try:
-            text_rows = int(form['rows'][0])
+            text_rows = int(form['rows'])
         except StandardError:
             text_rows = self.cfg.edit_rows
             if request.user.valid:
@@ -168,9 +167,9 @@
             # If the page exists, we get the text from the page.
             # TODO: maybe warn if template argument was ignored because the page exists?
             raw_body = self.get_raw_body()
-        elif 'template' in form:
+        elif 'template' in request.values:
             # If the page does not exist, we try to get the content from the template parameter.
-            template_page = wikiutil.unquoteWikiname(form['template'][0])
+            template_page = wikiutil.unquoteWikiname(request.values['template'])
             if request.user.may.read(template_page):
                 raw_body = Page(request, template_page).get_raw_body()
                 if raw_body:
@@ -224,9 +223,8 @@
             raw_body = _('Describe %s here.') % (self.page_name, )
 
         # send form
-        request.write('<form id="editor" method="post" action="%s/%s#preview">' % (
-            request.getScriptname(),
-            wikiutil.quoteWikinameURL(self.page_name),
+        request.write('<form id="editor" method="post" action="%s#preview">' % (
+                request.href(self.page_name)
             ))
 
         # yet another weird workaround for broken IE6 (it expands the text
@@ -247,7 +245,7 @@
         request.write('<input type="hidden" name="ticket" value="%s">' % wikiutil.createTicket(request))
 
         # Save backto in a hidden input
-        backto = form.get('backto', [None])[0]
+        backto = request.values.get('backto')
         if backto:
             request.write(unicode(html.INPUT(type="hidden", name="backto", value=backto)))
 
@@ -298,7 +296,7 @@
 <input type="checkbox" name="trivial" id="chktrivialtop" value="1" %(checked)s onclick="toggle_trivial(this)">
 <label for="chktrivialtop">%(label)s</label>
 ''' % {
-          'checked': ('', 'checked')[form.get('trivial', ['0'])[0] == '1'],
+          'checked': ('', 'checked')[form.get('trivial', '0') == '1'],
           'label': _("Trivial change"),
        })
 
@@ -315,7 +313,7 @@
         url_prefix_local = request.cfg.url_prefix_local
         wikipage = wikiutil.quoteWikinameURL(self.page_name)
         fckbasepath = url_prefix_local + '/applets/FCKeditor'
-        wikiurl = request.getScriptname()
+        wikiurl = request.script_root
         if not wikiurl or wikiurl[-1] != '/':
             wikiurl += '/'
         themepath = '%s/%s' % (url_prefix_static, request.theme.name)
@@ -377,7 +375,7 @@
 &nbsp;
 <input type="checkbox" name="trivial" id="chktrivial" value="1" %(checked)s onclick="toggle_trivial(this)">
 <label for="chktrivial">%(label)s</label> ''' % {
-                'checked': ('', 'checked')[form.get('trivial', ['0'])[0] == '1'],
+                'checked': ('', 'checked')[form.get('trivial', '0') == '1'],
                 'label': _("Trivial change"),
                 })
 
@@ -386,7 +384,7 @@
 <input type="checkbox" name="rstrip" id="chkrstrip" value="1" %(checked)s>
 <label for="chkrstrip">%(label)s</label>
 </p> ''' % {
-            'checked': ('', 'checked')[form.get('rstrip', ['0'])[0] == '1'],
+            'checked': ('', 'checked')[form.get('rstrip', '0') == '1'],
             'label': _('Remove trailing whitespace from each line')
             })
 
--- a/MoinMoin/_tests/ldap_testbase.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/_tests/ldap_testbase.py	Tue Feb 10 13:21:59 2009 +0100
@@ -41,7 +41,7 @@
 SLAPD_EXECUTABLE = 'slapd'  # filename of LDAP server executable - if it is not
                             # in your PATH, you have to give full path/filename.
 
-import os, shutil, tempfile, time
+import os, shutil, tempfile, time, base64, md5
 from StringIO import StringIO
 import signal
 
@@ -187,6 +187,8 @@
         f.write(db_config)
         f.close()
 
+        rootpw = '{MD5}' + base64.b64encode(md5.new(self.rootpw).digest())
+
         # create slapd.conf from content template in slapd_config
         slapd_config = slapd_config % {
             'ldap_dir': self.ldap_dir,
@@ -194,7 +196,7 @@
             'schema_dir': self.schema_dir,
             'basedn': self.basedn,
             'rootdn': self.rootdn,
-            'rootpw': self.rootpw,
+            'rootpw': rootpw,
         }
         if isinstance(slapd_config, unicode):
             slapd_config = slapd_config.encode(self.coding)
--- a/MoinMoin/_tests/ldap_testdata.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/_tests/ldap_testdata.py	Tue Feb 10 13:21:59 2009 +0100
@@ -78,14 +78,16 @@
 objectClass: account
 objectClass: simpleSecurityObject
 uid: usera
-userPassword: usera
+# this is md5 encoded 'usera' for password
+userPassword: {MD5}aXqgOSc5gSW7YoLi9BSmvg==
 
 dn: uid=userb,ou=Unit B,ou=Users,ou=testing,dc=example,dc=org
 cn: Vorname Nachname
 objectClass: inetOrgPerson
 sn: Nachname
 uid: userb
-userPassword: userb
+# this is md5 encoded 'userb' for password
+userPassword: {MD5}ThvfQsM7OQFjqSUQOX2XsA==
 
 dn: cn=Group A,ou=Groups,ou=testing,dc=example,dc=org
 cn: Group A
--- a/MoinMoin/_tests/test_sourcecode.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/_tests/test_sourcecode.py	Tue Feb 10 13:21:59 2009 +0100
@@ -19,6 +19,7 @@
 EXCLUDE = [
     '/contrib/DesktopEdition/setup_py2exe.py', # has crlf
     '/contrib/TWikiDrawPlugin', # 3rd party java stuff
+    '/contrib/flup-server', # 3rd party WSGI adapters
     '/MoinMoin/support', # 3rd party libs or non-broken stdlib stuff
     '/wiki/htdocs/applets/FCKeditor', # 3rd party GUI editor
     '/tests/wiki', # this is our test wiki
--- a/MoinMoin/_tests/test_user.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/_tests/test_user.py	Tue Feb 10 13:21:59 2009 +0100
@@ -38,11 +38,11 @@
 
     def setup_method(self, method):
         # Save original user and cookie
-        self.saved_cookie = self.request.saved_cookie
+        self.saved_cookie = self.request.cookies
         self.saved_user = self.request.user
 
         # Create anon user for the tests
-        self.request.saved_cookie = ''
+        self.request.cookies = {}
         self.request.user = user.User(self.request)
 
         # Prevent user list caching - we create and delete users too fast for that.
@@ -64,7 +64,7 @@
             del self.user
 
         # Restore original user
-        self.request.saved_cookie = self.saved_cookie
+        self.request.cookies = self.saved_cookie
         self.request.user = self.saved_user
 
         # Remove user name to id cache, or next test will fail
--- a/MoinMoin/_tests/test_wikiutil.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/_tests/test_wikiutil.py	Tue Feb 10 13:21:59 2009 +0100
@@ -9,7 +9,7 @@
 
 import py
 
-from MoinMoin import wikiutil
+from MoinMoin import config, wikiutil
 
 
 class TestQueryStringSupport:
@@ -973,4 +973,80 @@
         assert relative_page == wikiutil.RelPageName(current_page, absolute_page)
 
 
+class TestNormalizePagename(object):
+
+    def testPageInvalidChars(self):
+        """ request: normalize pagename: remove invalid unicode chars
+
+        Assume the default setting
+        """
+        test = u'\u0000\u202a\u202b\u202c\u202d\u202e'
+        expected = u''
+        result = wikiutil.normalize_pagename(test, self.request.cfg)
+        assert result == expected
+
+    def testNormalizeSlashes(self):
+        """ request: normalize pagename: normalize slashes """
+        cases = (
+            (u'/////', u''),
+            (u'/a', u'a'),
+            (u'a/', u'a'),
+            (u'a/////b/////c', u'a/b/c'),
+            (u'a b/////c d/////e f', u'a b/c d/e f'),
+            )
+        for test, expected in cases:
+            result = wikiutil.normalize_pagename(test, self.request.cfg)
+            assert result == expected
+
+    def testNormalizeWhitespace(self):
+        """ request: normalize pagename: normalize whitespace """
+        cases = (
+            (u'         ', u''),
+            (u'    a', u'a'),
+            (u'a    ', u'a'),
+            (u'a     b     c', u'a b c'),
+            (u'a   b  /  c    d  /  e   f', u'a b/c d/e f'),
+            # All 30 unicode spaces
+            (config.chars_spaces, u''),
+            )
+        for test, expected in cases:
+            result = wikiutil.normalize_pagename(test, self.request.cfg)
+            assert result == expected
+
+    def testUnderscoreTestCase(self):
+        """ request: normalize pagename: underscore convert to spaces and normalized
+
+        Underscores should convert to spaces, then spaces should be
+        normalized, order is important!
+        """
+        cases = (
+            (u'         ', u''),
+            (u'  a', u'a'),
+            (u'a  ', u'a'),
+            (u'a  b  c', u'a b c'),
+            (u'a  b  /  c  d  /  e  f', u'a b/c d/e f'),
+            )
+        for test, expected in cases:
+            result = wikiutil.normalize_pagename(test, self.request.cfg)
+            assert result == expected
+
+class TestGroupPages(object):
+
+    def testNormalizeGroupName(self):
+        """ request: normalize pagename: restrict groups to alpha numeric Unicode
+
+        Spaces should normalize after invalid chars removed!
+        """
+        cases = (
+            # current acl chars
+            (u'Name,:Group', u'NameGroup'),
+            # remove than normalize spaces
+            (u'Name ! @ # $ % ^ & * ( ) + Group', u'Name Group'),
+            )
+        for test, expected in cases:
+            # validate we are testing valid group names
+            if wikiutil.isGroupPage(test, self.request.cfg):
+                result = wikiutil.normalize_pagename(test, self.request.cfg)
+                assert result == expected
+
 coverage_modules = ['MoinMoin.wikiutil']
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MoinMoin/_tests/test_wsgiapp.py	Tue Feb 10 13:21:59 2009 +0100
@@ -0,0 +1,42 @@
+# -*- coding: utf-8 -*-
+"""
+    MoinMoin - MoinMoin.wsgiapp Tests
+
+    @copyright: 2008 MoinMoin:FlorianKrupicka
+    @license: GNU GPL, see COPYING for details.
+"""
+from StringIO import StringIO
+
+from MoinMoin import wsgiapp
+
+DOC_TYPE = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">'
+
+class TestApplication:
+    # self.client is made by conftest
+
+    # These should exist
+    PAGES = ('FrontPage', 'RecentChanges', 'HelpContents', 'FindPage')
+    # ... and these should not
+    NO_PAGES = ('FooBar', 'TheNone/ExistantPage/', '%33Strange%74Codes')
+
+    def testWSGIAppExisting(self):
+        for page in self.PAGES:
+            def _test_(page=page):
+                appiter, status, headers = self.client.get('/%s' % page)
+                output = ''.join(appiter)
+                print output
+                assert status[:3] == '200'
+                assert ('Content-Type', 'text/html; charset=utf-8') in headers
+                for needle in (DOC_TYPE, page):
+                    assert needle in output
+            yield _test_
+
+    def testWSGIAppAbsent(self):
+        for page in self.NO_PAGES:
+            def _test_(page=page):
+                appiter, status, headers = self.client.get('/%s' % page)
+                assert status[:3] == '404'
+                output = ''.join(appiter)
+                for needle in ('new empty page', 'page template'):
+                    assert needle in output
+            yield _test_
--- a/MoinMoin/action/AttachFile.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/action/AttachFile.py	Tue Feb 10 13:21:59 2009 +0100
@@ -27,7 +27,8 @@
     @license: GNU GPL, see COPYING for details.
 """
 
-import os, time, zipfile, mimetypes, errno
+import os, time, zipfile, mimetypes, errno, datetime
+from StringIO import StringIO
 
 from MoinMoin import log
 logging = log.getLogger(__name__)
@@ -37,6 +38,7 @@
 from MoinMoin.util import filesys, timefuncs
 from MoinMoin.security.textcha import TextCha
 from MoinMoin.events import FileAttachedEvent, send_event
+from MoinMoin.support import tarfile
 
 action_name = __name__.split('.')[-1]
 
@@ -76,34 +78,20 @@
     else:
         return u"/".join(pieces[:-1]), pieces[-1]
 
-
-def attachUrl(request, pagename, filename=None, **kw):
-    # filename is not used yet, but should be used later to make a sub-item url
-    if kw:
-        qs = '?%s' % wikiutil.makeQueryString(kw, want_unicode=False)
-    else:
-        qs = ''
-    return "%s/%s%s" % (request.getScriptname(), wikiutil.quoteWikinameURL(pagename), qs)
-
-
 def getAttachUrl(pagename, filename, request, addts=0, escaped=0, do='get', drawing='', upload=False):
     """ Get URL that points to attachment `filename` of page `pagename`. """
     if upload:
         if not drawing:
-            url = attachUrl(request, pagename, filename,
-                            rename=wikiutil.taintfilename(filename), action=action_name)
+            url = request.href(pagename, rename=wikiutil.taintfilename(filename),
+                               action=action_name)
         else:
-            url = attachUrl(request, pagename, filename,
-                            rename=wikiutil.taintfilename(filename), drawing=drawing, action=action_name)
+            url = request.href(pagename, rename=wikiutil.taintfilename(filename),
+                               drawing=drawing, action=action_name)
     else:
         if not drawing:
-            url = attachUrl(request, pagename, filename,
-                            target=filename, action=action_name, do=do)
+            url = request.href(pagename, target=filename, action=action_name, do=do)
         else:
-            url = attachUrl(request, pagename, filename,
-                            drawing=drawing, action=action_name)
-    if escaped:
-        url = wikiutil.escape(url)
+            url = request.href(pagename, drawing=drawing, action=action_name)
     return url
 
 
@@ -123,7 +111,7 @@
     fmt = request.formatter
     attach_count = _('[%d attachments]') % len(files)
     attach_icon = request.theme.make_icon('attach', vars={'attach_count': attach_count})
-    attach_link = (fmt.url(1, attachUrl(request, pagename, action=action_name), rel='nofollow') +
+    attach_link = (fmt.url(1, request.href(pagename, action=action_name), rel='nofollow') +
                    attach_icon +
                    fmt.url(0))
     return attach_link
@@ -251,10 +239,10 @@
     _ = request.getText
 
     error = None
-    if not request.form.get('target', [''])[0]:
+    if not request.values.get('target'):
         error = _("Filename of attachment not specified!")
     else:
-        filename = wikiutil.taintfilename(request.form['target'][0])
+        filename = wikiutil.taintfilename(request.values['target'])
         fpath = getFilename(request, pagename, filename)
 
         if os.path.isfile(fpath):
@@ -322,7 +310,7 @@
                          fmt.text(label_get) +
                          fmt.url(0))
 
-            if ext == '.draw':
+            if ext == '.tdraw':
                 links.append(fmt.url(1, getAttachUrl(pagename, file, request, drawing=base)) +
                              fmt.text(label_edit) +
                              fmt.url(0))
@@ -408,14 +396,15 @@
 
     now = time.time()
     pubpath = request.cfg.url_prefix_static + "/applets/TWikiDrawPlugin"
-    basename = request.form['drawing'][0]
-    drawpath = getAttachUrl(pagename, basename + '.draw', request, escaped=1)
-    pngpath = getAttachUrl(pagename, basename + '.png', request, escaped=1)
-    pagelink = attachUrl(request, pagename, '', action=action_name, ts=now)
+    basename = request.values['drawing']
+    ci = ContainerItem(request, pagename, basename + '.tdraw')
+    drawpath = ci.member_url(basename + '.draw')
+    pngpath = ci.member_url(basename + '.png')
+    pagelink = request.href(pagename, action=action_name, ts=now)
     helplink = Page(request, "HelpOnActions/AttachFile").url(request)
-    savelink = attachUrl(request, pagename, '', action=action_name, do='savedrawing')
+    savelink = request.href(pagename, action=action_name, do='savedrawing')
     #savelink = Page(request, pagename).url(request) # XXX include target filename param here for twisted
-                                           # request, {'savename': request.form['drawing'][0]+'.draw'}
+                                           # request, {'savename': request.values['drawing']+'.draw'}
     #savelink = '/cgi-bin/dumpform.bat'
 
     timestamp = '&amp;ts=%s' % now
@@ -460,7 +449,7 @@
     if writeable:
         request.write('<h2>' + _("New Attachment") + '</h2>')
         request.write("""
-<form action="%(baseurl)s/%(pagename)s" method="POST" enctype="multipart/form-data">
+<form action="%(url)s" method="POST" enctype="multipart/form-data">
 <dl>
 <dt>%(upload_label_file)s</dt>
 <dd><input type="file" name="file" size="50"></dd>
@@ -477,14 +466,13 @@
 </p>
 </form>
 """ % {
-    'baseurl': request.getScriptname(),
-    'pagename': wikiutil.quoteWikinameURL(pagename),
+    'url': request.href(pagename),
     'action_name': action_name,
     'upload_label_file': _('File to upload'),
     'upload_label_rename': _('Rename to'),
-    'rename': wikiutil.escape(request.form.get('rename', [''])[0], 1),
+    'rename': wikiutil.escape(request.form.get('rename', ''), 1),
     'upload_label_overwrite': _('Overwrite existing attachment of same name'),
-    'overwrite_checked': ('', 'checked')[request.form.get('overwrite', ['0'])[0] == '1'],
+    'overwrite_checked': ('', 'checked')[request.form.get('overwrite', '0') == '1'],
     'upload_button': _('Upload'),
     'textcha': TextCha(request).render(),
 })
@@ -495,7 +483,7 @@
     if not writeable:
         request.write('<p>%s</p>' % _('You are not allowed to attach a file to this page.'))
 
-    if writeable and request.form.get('drawing', [None])[0]:
+    if writeable and request.values.get('drawing'):
         send_hotdraw(pagename, request)
 
 
@@ -507,12 +495,12 @@
     """ Main dispatcher for the 'AttachFile' action. """
     _ = request.getText
 
-    do = request.form.get('do', ['upload_form'])
-    handler = globals().get('_do_%s' % do[0])
+    do = request.values.get('do', 'upload_form')
+    handler = globals().get('_do_%s' % do)
     if handler:
         msg = handler(pagename, request)
     else:
-        msg = _('Unsupported AttachFile sub-action: %s') % (wikiutil.escape(do[0]), )
+        msg = _('Unsupported AttachFile sub-action: %s') % wikiutil.escape(do)
     if msg:
         error_msg(pagename, request, msg)
 
@@ -524,7 +512,6 @@
 def upload_form(pagename, request, msg=''):
     _ = request.getText
 
-    request.emit_http_headers()
     # Use user interface language for this generated page
     request.setContentLanguage(request.lang)
     request.theme.add_msg(msg, "dialog")
@@ -555,9 +542,15 @@
         return _('TextCha: Wrong answer! Go back and try again...')
 
     form = request.form
-    overwrite = form.get('overwrite', [u'0'])[0]
+
+    file_upload = request.files.get('file')
+    if not file_upload:
+        # This might happen when trying to upload file names
+        # with non-ascii characters on Safari.
+        return _("No file content. Delete non ASCII characters from the file name and try again.")
+
     try:
-        overwrite = int(overwrite)
+        overwrite = int(form.get('overwrite', '0'))
     except:
         overwrite = 0
 
@@ -567,84 +560,122 @@
     if overwrite and not request.user.may.delete(pagename):
         return _('You are not allowed to overwrite a file attachment of this page.')
 
-    filename = form.get('file__filename__')
-    rename = form.get('rename', [u''])[0].strip()
+    rename = form.get('rename', u'').strip()
     if rename:
         target = rename
     else:
-        target = filename
+        target = file_upload.filename
 
-    target = preprocess_filename(target)
     target = wikiutil.clean_input(target)
 
     if not target:
         return _("Filename of attachment not specified!")
 
-    # get file content
-    filecontent = request.form.get('file', [None])[0]
-    if filecontent is None:
-        # This might happen when trying to upload file names
-        # with non-ascii characters on Safari.
-        return _("No file content. Delete non ASCII characters from the file name and try again.")
-
     # add the attachment
     try:
-        target, bytes = add_attachment(request, pagename, target, filecontent, overwrite=overwrite)
+        target, bytes = add_attachment(request, pagename, target, file_upload.stream, overwrite=overwrite)
         msg = _("Attachment '%(target)s' (remote name '%(filename)s')"
                 " with %(bytes)d bytes saved.") % {
-                'target': target, 'filename': filename, 'bytes': bytes}
+                'target': target, 'filename': file_upload.filename, 'bytes': bytes}
     except AttachmentAlreadyExists:
         msg = _("Attachment '%(target)s' (remote name '%(filename)s') already exists.") % {
-            'target': target, 'filename': filename}
+            'target': target, 'filename': file_upload.filename}
 
     # return attachment list
     upload_form(pagename, request, msg)
 
 
+class ContainerItem:
+    """ A storage container (multiple objects in 1 tarfile) """
+
+    def __init__(self, request, pagename, containername):
+        self.request = request
+        self.pagename = pagename
+        self.containername = containername
+        self.container_filename = getFilename(request, pagename, containername)
+
+    def member_url(self, member):
+        """ return URL for accessing container member
+            (we use same URL for get (GET) and put (POST))
+        """
+        url = Page(self.request, self.pagename).url(self.request, {
+            'action': 'AttachFile',
+            'do': 'box',  # shorter to type than 'container'
+            'target': self.containername,
+            #'member': member,
+        })
+        return url + '&member=%s' % member
+        # member needs to be last in qs because twikidraw looks for "file extension" at the end
+
+    def get(self, member):
+        """ return a file-like object with the member file data
+        """
+        tf = tarfile.TarFile(self.container_filename)
+        return tf.extractfile(member)
+
+    def put(self, member, content, content_length=None):
+        """ save data into a container's member """
+        tf = tarfile.TarFile(self.container_filename, mode='a')
+        if isinstance(member, unicode):
+            member = member.encode('utf-8')
+        ti = tarfile.TarInfo(member)
+        if isinstance(content, str):
+            if content_length is None:
+                content_length = len(content)
+            content = StringIO(content) # we need a file obj
+        elif not hasattr(content, 'read'):
+            logging.error("unsupported content object: %r" % content)
+            raise
+        assert content_length >= 0  # we don't want -1 interpreted as 4G-1
+        ti.size = content_length
+        tf.addfile(ti, content)
+        tf.close()
+
+    def truncate(self):
+        f = open(self.container_filename, 'w')
+        f.close()
+
+    def exists(self):
+        return os.path.exists(self.container_filename)
+
 def _do_savedrawing(pagename, request):
     _ = request.getText
 
     if not request.user.may.write(pagename):
         return _('You are not allowed to save a drawing on this page.')
 
-    filename = request.form['filename'][0]
-    filecontent = request.form['filepath'][0]
+    file_upload = request.files.get('filepath')
+    if not file_upload:
+        # This might happen when trying to upload file names
+        # with non-ascii characters on Safari.
+        return _("No file content. Delete non ASCII characters from the file name and try again.")
 
+    filename = request.form['filename']
     basepath, basename = os.path.split(filename)
     basename, ext = os.path.splitext(basename)
 
-    # get directory, and possibly create it
-    attach_dir = getAttachDir(request, pagename, create=1)
-    savepath = os.path.join(attach_dir, basename + ext)
-
-    if ext == '.draw':
-        _addLogEntry(request, 'ATTDRW', pagename, basename + ext)
+    ci = ContainerItem(request, pagename, basename + '.tdraw')
+    filecontent = file_upload.stream
+    content_length = None
+    if ext == '.draw': # TWikiDraw POSTs this first
+        _addLogEntry(request, 'ATTDRW', pagename, basename + '.tdraw')
+        ci.truncate()
         filecontent = filecontent.read() # read file completely into memory
         filecontent = filecontent.replace("\r", "")
     elif ext == '.map':
+        # touch attachment directory to invalidate cache if new map is saved
+        attach_dir = getAttachDir(request, pagename)
+        os.utime(attach_dir, None)
         filecontent = filecontent.read() # read file completely into memory
         filecontent = filecontent.strip()
-
-    if filecontent:
-        # filecontent is either a file or a non-empty string
-        stream = open(savepath, 'wb')
-        try:
-            _write_stream(filecontent, stream)
-        finally:
-            stream.close()
     else:
-        # filecontent is empty string (e.g. empty map file), delete the target file
-        try:
-            os.unlink(savepath)
-        except OSError, err:
-            if err.errno != errno.ENOENT: # no such file
-                raise
+        #content_length = file_upload.content_length
+        # XXX gives -1 for wsgiref :( If this is fixed, we could use the file obj,
+        # without reading it into memory completely:
+        filecontent = filecontent.read()
 
-    # touch attachment directory to invalidate cache if new map is saved
-    if ext == '.map':
-        os.utime(attach_dir, None)
+    ci.put(basename + ext, filecontent, content_length)
 
-    request.emit_http_headers()
     request.write("OK")
 
 
@@ -710,17 +741,17 @@
 
     if 'cancel' in request.form:
         return _('Move aborted!')
-    if not wikiutil.checkTicket(request, request.form['ticket'][0]):
+    if not wikiutil.checkTicket(request, request.form['ticket']):
         return _('Please use the interactive user interface to move attachments!')
     if not request.user.may.delete(pagename):
         return _('You are not allowed to move attachments from this page.')
 
     if 'newpagename' in request.form:
-        new_pagename = request.form.get('newpagename')[0]
+        new_pagename = request.form.get('newpagename')
     else:
         upload_form(pagename, request, msg=_("Move aborted because new page name is empty."))
     if 'newattachmentname' in request.form:
-        new_attachment = request.form.get('newattachmentname')[0]
+        new_attachment = request.form.get('newattachmentname')
         if new_attachment != wikiutil.taintfilename(new_attachment):
             upload_form(pagename, request, msg=_("Please use a valid filename for attachment '%(filename)s'.") % {
                                   'filename': new_attachment})
@@ -728,7 +759,7 @@
     else:
         upload_form(pagename, request, msg=_("Move aborted because new attachment name is empty."))
 
-    attachment = request.form.get('oldattachmentname')[0]
+    attachment = request.form.get('oldattachmentname')
     move_file(request, pagename, new_pagename, attachment, new_attachment)
 
 
@@ -743,11 +774,10 @@
 
     # move file
     d = {'action': action_name,
-         'baseurl': request.getScriptname(),
+         'url': request.href(pagename),
          'do': 'attachment_move',
          'ticket': wikiutil.createTicket(request),
          'pagename': pagename,
-         'pagename_quoted': wikiutil.quoteWikinameURL(pagename),
          'attachment_name': filename,
          'move': _('Move'),
          'cancel': _('Cancel'),
@@ -755,7 +785,7 @@
          'attachment_label': _("New attachment name"),
         }
     formhtml = '''
-<form action="%(baseurl)s/%(pagename_quoted)s" method="POST">
+<form action="%(url)s" method="POST">
 <input type="hidden" name="action" value="%(action)s">
 <input type="hidden" name="do" value="%(do)s">
 <input type="hidden" name="ticket" value="%(ticket)s">
@@ -787,6 +817,46 @@
     return thispage.send_page()
 
 
+def _do_box(pagename, request):
+    _ = request.getText
+
+    pagename, filename, fpath = _access_file(pagename, request)
+    if not request.user.may.read(pagename):
+        return _('You are not allowed to get attachments from this page.')
+    if not filename:
+        return # error msg already sent in _access_file
+
+    timestamp = datetime.datetime.fromtimestamp(os.path.getmtime(fpath))
+    if_modified = request.if_modified_since
+    if if_modified and if_modified >= timestamp:
+        request.status_code = 304
+    else:
+        ci = ContainerItem(request, pagename, filename)
+        filename = wikiutil.taintfilename(request.values['member'])
+        mt = wikiutil.MimeType(filename=filename)
+        content_type = mt.content_type()
+        mime_type = mt.mime_type()
+
+        # TODO: fix the encoding here, plain 8 bit is not allowed according to the RFCs
+        # There is no solution that is compatible to IE except stripping non-ascii chars
+        filename_enc = filename.encode(config.charset)
+
+        # for dangerous files (like .html), when we are in danger of cross-site-scripting attacks,
+        # we just let the user store them to disk ('attachment').
+        # For safe files, we directly show them inline (this also works better for IE).
+        dangerous = mime_type in request.cfg.mimetypes_xss_protect
+        content_dispo = dangerous and 'attachment' or 'inline'
+
+        request.content_type = content_type
+        request.last_modified = timestamp
+        #request.content_length = os.path.getsize(fpath)
+        content_dispo_string = '%s; filename="%s"' % (content_dispo, filename_enc)
+        request.headers.add('Content-Disposition', content_dispo_string)
+
+        # send data
+        request.send_file(ci.get(filename))
+
+
 def _do_get(pagename, request):
     _ = request.getText
 
@@ -796,9 +866,10 @@
     if not filename:
         return # error msg already sent in _access_file
 
-    timestamp = timefuncs.formathttpdate(int(os.path.getmtime(fpath)))
-    if request.if_modified_since == timestamp:
-        request.emit_http_headers(["Status: 304 Not modified"])
+    timestamp = datetime.datetime.fromtimestamp(os.path.getmtime(fpath))
+    if_modified = request.if_modified_since
+    if if_modified and if_modified >= timestamp:
+        request.status_code = 304
     else:
         mt = wikiutil.MimeType(filename=filename)
         content_type = mt.content_type()
@@ -814,12 +885,11 @@
         dangerous = mime_type in request.cfg.mimetypes_xss_protect
         content_dispo = dangerous and 'attachment' or 'inline'
 
-        request.emit_http_headers([
-            'Content-Type: %s' % content_type,
-            'Last-Modified: %s' % timestamp,
-            'Content-Length: %d' % os.path.getsize(fpath),
-            'Content-Disposition: %s; filename="%s"' % (content_dispo, filename_enc),
-        ])
+        request.content_type = content_type
+        request.last_modified = timestamp
+        request.content_length = os.path.getsize(fpath)
+        content_dispo_string = '%s; filename="%s"' % (content_dispo, filename_enc)
+        request.headers.add('Content-Disposition', content_dispo_string)
 
         # send data
         request.send_file(open(fpath, 'rb'))
@@ -1053,7 +1123,6 @@
         return
 
     # send header & title
-    request.emit_http_headers()
     # Use user interface language for this generated page
     request.setContentLanguage(request.lang)
     title = _('attachment:%(filename)s of %(pagename)s') % {
--- a/MoinMoin/action/CopyPage.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/action/CopyPage.py	Tue Feb 10 13:21:59 2009 +0100
@@ -46,20 +46,19 @@
         """ copy this page to "pagename" """
         _ = self._
         form = self.form
-        newpagename = form.get('newpagename', [u''])[0]
-        newpagename = self.request.normalizePagename(newpagename)
-        comment = form.get('comment', [u''])[0]
+        newpagename = form.get('newpagename', u'')
+        newpagename = wikiutil.normalize_pagename(newpagename, self.cfg)
+        comment = form.get('comment', u'')
         comment = wikiutil.clean_input(comment)
 
         self.page = PageEditor(self.request, self.pagename)
         success, msgs = self.page.copyPage(newpagename, comment)
 
         copy_subpages = 0
-        if form.has_key('copy_subpages'):
-            try:
-                copy_subpages = int(form['copy_subpages'][0])
-            except:
-                pass
+        try:
+            copy_subpages = int(form['copy_subpages'])
+        except:
+            pass
 
         if copy_subpages and self.subpages or (not self.users_subpages and self.subpages):
             for name in self.subpages:
@@ -85,7 +84,7 @@
 
             d = {
                 'subpage': subpages,
-                'subpages_checked': ('', 'checked')[self.request.form.get('subpages_checked', ['0'])[0] == '1'],
+                'subpages_checked': ('', 'checked')[self.request.form.get('subpages_checked', '0') == '1'],
                 'subpage_label': _('Copy all /subpages too?'),
                 'pagename': wikiutil.escape(self.pagename, True),
                 'newname_label': _("New name"),
--- a/MoinMoin/action/DeletePage.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/action/DeletePage.py	Tue Feb 10 13:21:59 2009 +0100
@@ -44,7 +44,7 @@
     def do_action(self):
         """ Delete pagename """
         form = self.form
-        comment = form.get('comment', [u''])[0]
+        comment = form.get('comment', u'')
         comment = wikiutil.clean_input(comment)
 
         # Create a page editor that does not do editor backups, because
@@ -53,11 +53,10 @@
         success, msgs = self.page.deletePage(comment)
 
         delete_subpages = 0
-        if 'delete_subpages' in form:
-            try:
-                delete_subpages = int(form['delete_subpages'][0])
-            except:
-                pass
+        try:
+            delete_subpages = int(form['delete_subpages'])
+        except:
+            pass
 
         if delete_subpages and self.subpages:
             for name in self.subpages:
@@ -75,7 +74,7 @@
 
             d = {
                 'subpage': subpages,
-                'subpages_checked': ('', 'checked')[self.request.form.get('subpages_checked', ['0'])[0] == '1'],
+                'subpages_checked': ('', 'checked')[self.request.form.get('subpages_checked', '0') == '1'],
                 'subpage_label': _('Delete all /subpages too?'),
                 'comment_label': _("Optional reason for the deletion"),
                 'buttons_html': buttons_html,
--- a/MoinMoin/action/Despam.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/action/Despam.py	Tue Feb 10 13:21:59 2009 +0100
@@ -66,7 +66,7 @@
             pg.link_to(request, text=_("Select Author"),
                 querystr={
                     'action': 'Despam',
-                    'editor': editor, # was: url_quote_plus()
+                    'editor': repr(editor),
                 })))
 
     table = DataBrowserWidget(request)
@@ -104,14 +104,13 @@
     request.write('''
 </table>
 <p>
-<form method="post" action="%s/%s">
+<form method="post" action="%s">
 <input type="hidden" name="action" value="Despam">
 <input type="hidden" name="editor" value="%s">
 <input type="submit" name="ok" value="%s">
 </form>
 </p>
-''' % (request.getScriptname(), wikiutil.quoteWikinameURL(pagename),
-       wikiutil.url_quote(editor), _("Revert all!")))
+''' % (request.href(pagename), wikiutil.url_quote(editor), _("Revert all!")))
 
 def revert_page(request, pagename, editor):
     if not request.user.may.revert(pagename):
@@ -183,11 +182,10 @@
         request.theme.add_msg(_('You are not allowed to use this action.'), "error")
         return Page.Page(request, pagename).send_page()
 
-    editor = request.form.get('editor', [None])[0]
+    editor = request.form.get('editor')
     timestamp = time.time() - DAYS * 24 * 3600
-    ok = request.form.get('ok', [0])[0]
+    ok = request.form.get('ok', 0)
 
-    request.emit_http_headers()
     request.theme.send_title("Despam", pagename=pagename)
     # Start content (important for RTL support)
     request.write(request.formatter.startContent("content"))
--- a/MoinMoin/action/LikePages.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/action/LikePages.py	Tue Feb 10 13:21:59 2009 +0100
@@ -41,8 +41,6 @@
         return
 
     # more than one match, list 'em
-    request.emit_http_headers()
-
     # This action generate data using the user language
     request.setContentLanguage(request.lang)
 
--- a/MoinMoin/action/Load.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/action/Load.py	Tue Feb 10 13:21:59 2009 +0100
@@ -36,11 +36,17 @@
         form = self.form
         request = self.request
 
-        comment = form.get('comment', [u''])[0]
+        comment = form.get('comment', u'')
         comment = wikiutil.clean_input(comment)
 
-        filename = form.get('file__filename__')
-        rename = form.get('rename', [''])[0].strip()
+        file_upload = request.files.get('file')
+        if not file_upload:
+            # This might happen when trying to upload file names
+            # with non-ascii characters on Safari.
+            return False, _("No file content. Delete non ASCII characters from the file name and try again.")
+
+        filename = file_upload.filename
+        rename = form.get('rename', '').strip()
         if rename:
             target = rename
         else:
@@ -50,9 +56,7 @@
         target = wikiutil.clean_input(target)
 
         if target:
-            filecontent = form['file'][0]
-            if hasattr(filecontent, 'read'): # a file-like object
-                filecontent = filecontent.read() # XXX reads complete file into memory!
+            filecontent = file_upload.stream.read() # XXX reads complete file into memory!
             filecontent = wikiutil.decodeUnknownInput(filecontent)
 
             self.pagename = target
--- a/MoinMoin/action/LocalSiteMap.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/action/LocalSiteMap.py	Tue Feb 10 13:21:59 2009 +0100
@@ -31,7 +31,6 @@
 
 def execute(pagename, request):
     _ = request.getText
-    request.emit_http_headers()
 
     # This action generate data using the user language
     request.setContentLanguage(request.lang)
--- a/MoinMoin/action/MyPages.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/action/MyPages.py	Tue Feb 10 13:21:59 2009 +0100
@@ -58,7 +58,6 @@
     pagecontent = pagecontent.replace('\n', '\r\n')
 
     from MoinMoin.parser.text_moin_wiki import Parser as WikiParser
-    request.emit_http_headers()
 
     # This action generate data using the user language
     request.setContentLanguage(request.lang)
--- a/MoinMoin/action/PackagePages.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/action/PackagePages.py	Tue Feb 10 13:21:59 2009 +0100
@@ -44,9 +44,8 @@
         redirects to new page.
         """
         _ = self.request.getText
-        form = self.request.form
 
-        if 'cancel' in form:
+        if 'cancel' in self.request.values:
             # User canceled
             return self.page.send_page()
 
@@ -65,14 +64,13 @@
     def package(self):
         """ Calls collectpackage() with the arguments specified. """
         _ = self.request.getText
-        form = self.request.form
 
         # Get new name from form and normalize.
-        pagelist = form.get('pagelist', [u''])[0]
-        packagename = form.get('packagename', [u''])[0]
-        include_attachments = form.get('include_attachments', [False])[0]
+        pagelist = self.request.values.get('pagelist', u'')
+        packagename = self.request.values.get('packagename', u'')
+        include_attachments = self.request.values.get('include_attachments', False)
 
-        if not form.get('submit', [None])[0]:
+        if not self.request.values.get('submit'):
             self.request.theme.add_msg(self.makeform(), "dialog")
             raise ActionError
 
@@ -115,11 +113,10 @@
             error = u'<p class="error">%s</p>\n' % error
 
         d = {
-            'baseurl': self.request.getScriptname(),
+            'url': self.request.href(self.pagename),
             'error': error,
             'action': self.__class__.__name__,
             'pagename': wikiutil.escape(self.pagename, True),
-            'pagename_quoted': wikiutil.quoteWikinameURL(self.pagename),
             'include_attachments_label': _('Include all attachments?'),
             'package': _('Package pages'),
             'cancel': _('Cancel'),
@@ -128,7 +125,7 @@
         }
         form = '''
 %(error)s
-<form method="post" action="%(baseurl)s/%(pagename_quoted)s">
+<form method="post" action="%(url)s">
 <input type="hidden" name="action" value="%(action)s">
 <table>
     <tr>
@@ -196,7 +193,7 @@
 
         pages = []
         for pagename in pagelist:
-            pagename = self.request.normalizePagename(pagename)
+            pagename = wikiutil.normalize_pagename(pagename, self.request.cfg)
             if pagename:
                 page = Page(self.request, pagename)
                 if page.exists() and self.request.user.may.read(pagename):
--- a/MoinMoin/action/RenamePage.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/action/RenamePage.py	Tue Feb 10 13:21:59 2009 +0100
@@ -45,20 +45,19 @@
         """ Rename this page to "pagename" """
         _ = self._
         form = self.form
-        newpagename = form.get('newpagename', [u''])[0]
-        newpagename = self.request.normalizePagename(newpagename)
-        comment = form.get('comment', [u''])[0]
+        newpagename = form.get('newpagename', u'')
+        newpagename = wikiutil.normalize_pagename(newpagename, self.cfg)
+        comment = form.get('comment', u'')
         comment = wikiutil.clean_input(comment)
 
         self.page = PageEditor(self.request, self.pagename)
         success, msgs = self.page.renamePage(newpagename, comment)
 
         rename_subpages = 0
-        if 'rename_subpages' in form:
-            try:
-                rename_subpages = int(form['rename_subpages'][0])
-            except:
-                pass
+        try:
+            rename_subpages = int(form['rename_subpages'])
+        except:
+            pass
 
         if rename_subpages and self.subpages:
             for name in self.subpages:
@@ -84,7 +83,7 @@
 
             d = {
                 'subpage': subpages,
-                'subpages_checked': ('', 'checked')[self.request.form.get('subpages_checked', ['0'])[0] == '1'],
+                'subpages_checked': ('', 'checked')[self.request.form.get('subpages_checked', '0') == '1'],
                 'subpage_label': _('Rename all /subpages too?'),
                 'pagename': wikiutil.escape(self.pagename, True),
                 'newname_label': _("New name"),
--- a/MoinMoin/action/RenderAsDocbook.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/action/RenderAsDocbook.py	Tue Feb 10 13:21:59 2009 +0100
@@ -9,5 +9,5 @@
 
 def execute(pagename, request):
     url = Page(request, pagename).url(request, {'action': 'show', 'mimetype': 'text/docbook'})
-    request.http_redirect(url)
+    return request.http_redirect(url)
 
--- a/MoinMoin/action/SpellCheck.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/action/SpellCheck.py	Tue Feb 10 13:21:59 2009 +0100
@@ -102,7 +102,7 @@
     from MoinMoin.PageEditor import PageEditor
     # get the new words as a string (if any are marked at all)
     try:
-        newwords = request.form['newwords']
+        newwords = request.form.getlist('newwords')
     except KeyError:
         # no new words checked
         return
@@ -187,8 +187,8 @@
 
         # add a form containing the bad words
         if own_form:
-            msg = msg + ('<form method="post" action="%s/%s">\n'
-                         '<input type="hidden" name="action" value="%s">\n') % (request.getScriptname(), wikiutil.quoteWikinameURL(page.page_name), action_name)
+            msg = msg + ('<form method="post" action="%s">\n'
+                         '<input type="hidden" name="action" value="%s">\n') % (request.href(page.page_name), action_name)
 
         checkbox = '<input type="checkbox" name="newwords" value="%(word)s">%(word)s&nbsp;&nbsp;'
         msg = msg + (
--- a/MoinMoin/action/SubscribeUser.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/action/SubscribeUser.py	Tue Feb 10 13:21:59 2009 +0100
@@ -16,30 +16,28 @@
 
 def show_form(pagename, request):
     _ = request.getText
-    request.emit_http_headers()
     request.theme.send_title(_("Subscribe users to the page %s") % pagename, pagename=pagename)
 
     request.write("""
-<form action="%s/%s" method="POST" enctype="multipart/form-data">
+<form action="%s" method="POST" enctype="multipart/form-data">
 <input type="hidden" name="action" value="SubscribeUser">
 %s <input type="text" name="users" size="50">
 <input type="submit" value="Subscribe">
 </form>
-""" % (request.getScriptname(), wikiutil.quoteWikinameURL(pagename),
+""" % (request.href(pagename),
       _("Enter user names (comma separated):")))
     request.theme.send_footer(pagename)
     request.theme.send_closing_html()
 
 def show_result(pagename, request):
     _ = request.getText
-    request.emit_http_headers()
 
     request.theme.send_title(_("Subscribed for %s:") % pagename, pagename=pagename)
 
     from MoinMoin.formatter.text_html import Formatter
     formatter = Formatter(request)
 
-    result = subscribe_users(request, request.form['users'][0].split(","), pagename, formatter)
+    result = subscribe_users(request, request.form['users'].split(","), pagename, formatter)
     request.write(result)
 
     request.theme.send_footer(pagename)
@@ -119,9 +117,8 @@
         request_url = "localhost/"
 
     # Setup MoinMoin environment
-    from MoinMoin.request import request_cli
-    request = request_cli.Request(url=request_url)
-    request.form = request.args = request.setup_args()
+    from MoinMoin.web.contexts import ScriptContext
+    request = ScriptContext(url=request_url)
 
     from MoinMoin.formatter.text_plain import Formatter
     formatter = Formatter(request)
--- a/MoinMoin/action/SyncPages.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/action/SyncPages.py	Tue Feb 10 13:21:59 2009 +0100
@@ -122,8 +122,8 @@
     def fix_params(self, params):
         """ Does some fixup on the parameters. """
         # Load the password
-        if "password" in self.request.form:
-            params["password"] = self.request.form["password"][0]
+        if "password" in self.request.values:
+            params["password"] = self.request.values["password"]
 
         # merge the pageList case into the pageMatch case
         if params["pageList"] is not None:
@@ -178,7 +178,7 @@
         params = self.fix_params(self.parse_page())
 
         try:
-            if "cancel" in self.request.form:
+            if "cancel" in self.request.values:
                 raise ActionStatus(_("Operation was canceled."), "error")
 
             if params["direction"] == UP:
--- a/MoinMoin/action/__init__.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/action/__init__.py	Tue Feb 10 13:21:59 2009 +0100
@@ -18,16 +18,19 @@
     Additionally to the usual stuff, we provide an ActionBase class here with
     some of the usual base functionality for an action, like checking
     actions_excluded, making and checking tickets, rendering some form,
-    displaying errors and doing stuff after an action.
+    displaying errors and doing stuff after an action. Also utility functions
+    regarding actions are located here.
 
     @copyright: 2000-2004 Juergen Hermann <jh@web.de>,
                 2006 MoinMoin:ThomasWaldmann
+                2008 MoinMoin:FlorianKrupicka
     @license: GNU GPL, see COPYING for details.
 """
 
 from MoinMoin.util import pysupport
 from MoinMoin import config, wikiutil
 from MoinMoin.Page import Page
+from MoinMoin.support.python_compatibility import set
 
 # create a list of extension actions from the package directory
 modules = pysupport.getPackageModules(__file__)
@@ -88,7 +91,7 @@
             return True
         # Require a valid ticket. Make outside attacks harder by
         # requiring two full HTTP transactions
-        ticket = self.form.get('ticket', [''])[0]
+        ticket = self.form.get('ticket', '')
         return wikiutil.checkTicket(self.request, ticket)
 
     # UI ---------------------------------------------------------------------
@@ -134,19 +137,17 @@
 
         d = {
             'method': self.method,
-            'baseurl': self.request.getScriptname(),
+            'url': self.request.href(self.pagename),
             'enctype': self.enctype,
             'error_html': error_html,
             'actionname': self.actionname,
-            'pagename': self.pagename,
-            'pagename_quoted': wikiutil.quoteWikinameURL(self.pagename),
             'ticket_html': ticket_html,
             'user_html': self.get_form_html(buttons_html),
         }
 
         form_html = '''
 %(error_html)s
-<form action="%(baseurl)s/%(pagename_quoted)s" method="%(method)s" enctype="%(enctype)s">
+<form action="%(url)s" method="%(method)s" enctype="%(enctype)s">
 <div>
 <input type="hidden" name="action" value="%(actionname)s">
 %(ticket_html)s
@@ -236,14 +237,14 @@
         Page(request, pagename, rev=rev).send_raw()
 
 def do_show(pagename, request, content_only=0, count_hit=1, cacheable=1, print_mode=0):
-    """ show a page, either current revision or the revision given by rev form value.
+    """ show a page, either current revision or the revision given by "rev=" value.
         if count_hit is non-zero, we count the request for statistics.
     """
     # We must check if the current page has different ACLs.
     if not request.user.may.read(pagename):
         Page(request, pagename).send_page()
     else:
-        mimetype = request.form.get('mimetype', [u"text/html"])[0]
+        mimetype = request.values.get('mimetype', u"text/html")
         rev = request.rev or 0
         if rev == 0:
             request.cacheable = cacheable
@@ -254,22 +255,21 @@
         )
 
 def do_format(pagename, request):
-    """ send a page using a specific formatter given by mimetype form key.
+    """ send a page using a specific formatter given by "mimetype=" value.
         Since 5.5.2006 this functionality is also done by do_show, but do_format
         has a default of text/plain when no format is given.
         It also does not count in statistics and also does not set the cacheable flag.
         DEPRECATED: remove this action when we don't need it any more for compatibility.
     """
-    if 'mimetype' not in request.form:
-        request.form['mimetype'] = [u"text/plain"]
+    if 'mimetype' not in request.values:
+        request.values['mimetype'] = u"text/plain"
     do_show(pagename, request, count_hit=0, cacheable=0)
 
 def do_content(pagename, request):
     """ same as do_show, but we only show the content """
     # XXX temporary fix to make it work until Page.send_page gets refactored
-    request.setHttpHeader("Content-Type: text/html; charset=%s" % config.charset)
-    request.setHttpHeader('Status: 200 OK')
-    request.emit_http_headers()
+    request.mimetype = 'text/html'
+    request.status_code = 200
     do_show(pagename, request, count_hit=0, content_only=1)
 
 def do_print(pagename, request):
@@ -283,10 +283,10 @@
 def do_refresh(pagename, request):
     """ Handle refresh action """
     # Without arguments, refresh action will refresh the page text_html cache.
-    arena = request.form.get('arena', ['Page.py'])[0]
+    arena = request.values.get('arena', 'Page.py')
     if arena == 'Page.py':
         arena = Page(request, pagename)
-    key = request.form.get('key', ['text_html'])[0]
+    key = request.values.get('key', 'text_html')
 
     # Remove cache entry (if exists), and send the page
     from MoinMoin import caching
@@ -296,27 +296,71 @@
 
 def do_goto(pagename, request):
     """ redirect to another page """
-    target = request.form.get('target', [''])[0]
+    target = request.values.get('target', '')
     request.http_redirect(Page(request, target).url(request))
 
 # Dispatching ----------------------------------------------------------------
-def getNames(cfg):
-    if not hasattr(cfg.cache, 'action_names'):
-        lnames = names[:]
-        lnames.extend(wikiutil.getPlugins('action', cfg))
-        cfg.cache.action_names = lnames # remember it
-    return cfg.cache.action_names
+def get_names(config):
+    """ Get a list of known actions.
 
-def getHandler(request, action, identifier="execute"):
-    """ return a handler function for a given action or None """
+    @param config: a config object
+    @rtype: set
+    @return: set of known actions
+    """
+    if not hasattr(config.cache, 'action_names'):
+        actions = names[:]
+        actions.extend(wikiutil.getPlugins('action', config))
+        actions = set([action for action in actions
+                      if not action in config.actions_excluded])
+        config.cache.action_names = actions # remember it
+    return config.cache.action_names
+
+def getHandler(cfg, action, identifier="execute"):
+    """ return a handler function for a given action or None.
+
+    TODO: remove request dependency
+    """
     # check for excluded actions
-    if action in request.cfg.actions_excluded:
+    if action in cfg.actions_excluded:
         return None
 
     try:
-        handler = wikiutil.importPlugin(request.cfg, "action", action, identifier)
+        handler = wikiutil.importPlugin(cfg, "action", action, identifier)
     except wikiutil.PluginMissingError:
         handler = globals().get('do_' + action)
 
     return handler
 
+def get_available_actions(config, page, user):
+        """ Get a list of actions available on a particular page
+        for a particular user.
+
+        The set does not contain actions that starts with lower case.
+        Themes use this set to display the actions to the user.
+
+        @param config: a config object (for the per-wiki actions)
+        @param page: the page to which the actions should apply
+        @param user: the user which wants to apply an action
+        @rtype: set
+        @return: set of avaiable actions
+        """
+        if not user.may.read(page.page_name):
+            return []
+
+
+        actions = get_names(config)
+
+        # Filter non ui actions (starts with lower case letter)
+        actions = [action for action in actions if not action[0].islower()]
+
+        # Filter actions by page type, acl and user state
+        excluded = []
+        if (page.isUnderlayPage() and not page.isStandardPage()) or \
+                not user.may.write(page.page_name) or \
+                not user.may.delete(page.page_name):
+                # Prevent modification of underlay only pages, or pages
+                # the user can't write and can't delete
+                excluded = [u'RenamePage', u'DeletePage', ] # AttachFile must NOT be here!
+        return set([action for action in actions if not action in excluded])
+
+
--- a/MoinMoin/action/_tests/test_attachfile.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/action/_tests/test_attachfile.py	Tue Feb 10 13:21:59 2009 +0100
@@ -68,7 +68,7 @@
         Tests if AttachFile.getAttachUrl taints a filename
         """
         filename = "<test2.txt>"
-        expect = "rename=_test2.txt_&"
+        expect = "rename=_test2.txt_"
         result = AttachFile.getAttachUrl(self.pagename, filename, self.request, upload=True)
 
         assert expect in result
--- a/MoinMoin/action/backup.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/action/backup.py	Tue Feb 10 13:21:59 2009 +0100
@@ -54,7 +54,7 @@
     request.emit_http_headers()
     request.setContentLanguage(request.lang)
     title = _('Wiki Backup')
-    request.theme.send_title(title, form=request.form, pagename=pagename)
+    request.theme.send_title(title, pagename=pagename)
     request.write(request.formatter.startContent("content"))
 
     request.write(_("""= Downloading a backup =
@@ -103,7 +103,7 @@
         return sendMsg(request, pagename,
                        msg=_('You are not allowed to do remote backup.'), msgtype="error")
 
-    dowhat = request.form.get('do', [None])[0]
+    dowhat = request.form.get('do')
     if dowhat == 'backup':
         sendBackup(request)
     elif dowhat is None:
--- a/MoinMoin/action/bookmark.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/action/bookmark.py	Tue Feb 10 13:21:59 2009 +0100
@@ -19,7 +19,7 @@
         request.theme.add_msg(_("You must login to use this action: %(action)s.") % {"action": actname}, "error")
         return Page(request, pagename).send_page()
 
-    timestamp = request.form.get('time', [None])[0]
+    timestamp = request.values.get('time')
     if timestamp is not None:
         if timestamp == 'del':
             tm = None
--- a/MoinMoin/action/cache.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/action/cache.py	Tue Feb 10 13:21:59 2009 +0100
@@ -41,7 +41,7 @@
 
 action_name = __name__.split('.')[-1]
 
-# Do NOT get this directly from request.form or user would be able to read any cache!
+# Do NOT get this directly from request.values or user would be able to read any cache!
 cache_arena = 'sendcache'  # just using action_name is maybe rather confusing
 
 # We maybe could use page local caching (not 'wiki' global) to have less directory entries.
@@ -196,10 +196,7 @@
 
 def url(request, key, do='get'):
     """ return URL for the object cached for key """
-    return "%s/?%s" % (
-        request.getScriptname(),
-        wikiutil.makeQueryString(dict(action=action_name, do=do, key=key), want_unicode=False))
-
+    return request.href(action=action_name, do=do, key=key)
 
 def _get_headers(request, key):
     """ get last_modified and headers cached for key """
@@ -242,7 +239,7 @@
         _do_remove(request, key)
 
 def execute(pagename, request):
-    do = request.form.get('do', [None])[0]
-    key = request.form.get('key', [None])[0]
+    do = request.values.get('do')
+    key = request.values.get('key')
     _do(request, do, key)
 
--- a/MoinMoin/action/chart.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/action/chart.py	Tue Feb 10 13:21:59 2009 +0100
@@ -19,7 +19,7 @@
         request.theme.add_msg(_("Charts are not available!"), "error")
         return request.page.send_page()
 
-    chart_type = request.form.get('type', [''])[0].strip()
+    chart_type = request.values.get('type', '').strip()
     if not chart_type:
         request.theme.add_msg(_('You need to provide a chart type!'), "error")
         return request.page.send_page()
--- a/MoinMoin/action/diff.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/action/diff.py	Tue Feb 10 13:21:59 2009 +0100
@@ -21,7 +21,7 @@
         return
 
     try:
-        date = request.form['date'][0]
+        date = request.values['date']
         try:
             date = long(date) # must be long for py 2.2.x
         except StandardError:
@@ -30,11 +30,11 @@
         date = 0
 
     try:
-        rev1 = int(request.form.get('rev1', [-1])[0])
+        rev1 = int(request.values.get('rev1', -1))
     except StandardError:
         rev1 = 0
     try:
-        rev2 = int(request.form.get('rev2', [0])[0])
+        rev2 = int(request.values.get('rev2', 0))
     except StandardError:
         rev2 = 0
 
@@ -44,7 +44,7 @@
             rev1 = -1
 
     # spacing flag?
-    ignorews = int(request.form.get('ignorews', [0])[0])
+    ignorews = int(request.values.get('ignorews', 0))
 
     _ = request.getText
 
@@ -71,7 +71,6 @@
     # This action generates content in the user language
     request.setContentLanguage(request.lang)
 
-    request.emit_http_headers()
     request.theme.send_title(_('Diff for "%s"') % (pagename, ), pagename=pagename, allow_doubleclick=1)
 
     if rev1 > 0 and rev2 > 0 and rev1 > rev2 or rev1 == 0 and rev2 > 0:
--- a/MoinMoin/action/dumpform.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/action/dumpform.py	Tue Feb 10 13:21:59 2009 +0100
@@ -12,6 +12,5 @@
     """ dump the form data we received in this request for debugging """
     data = util.dumpFormData(request.form)
 
-    request.emit_http_headers()
     request.write("<html><body>%s</body></html>" % data)
 
--- a/MoinMoin/action/edit.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/action/edit.py	Tue Feb 10 13:21:59 2009 +0100
@@ -33,7 +33,7 @@
     if editor not in valideditors:
         editor = request.cfg.editor_default
 
-    editorparam = request.form.get('editor', [editor])[0]
+    editorparam = request.values.get('editor', editor)
     if editorparam == "guipossible":
         lasteditor = editor
     elif editorparam == "textonly":
@@ -49,11 +49,11 @@
         editor = 'text'
 
     rev = request.rev or 0
-    savetext = request.form.get('savetext', [None])[0]
-    comment = request.form.get('comment', [u''])[0]
-    category = request.form.get('category', [None])[0]
-    rstrip = int(request.form.get('rstrip', ['0'])[0])
-    trivial = int(request.form.get('trivial', ['0'])[0])
+    savetext = request.form.get('savetext')
+    comment = request.form.get('comment', u'')
+    category = request.form.get('category')
+    rstrip = int(request.form.get('rstrip', '0'))
+    trivial = int(request.form.get('trivial', '0'))
 
     if 'button_switch' in request.form:
         if editor == 'text':
@@ -78,7 +78,7 @@
     cancelled = 'button_cancel' in request.form
 
     if request.cfg.edit_ticketing:
-        ticket = request.form.get('ticket', [''])[0]
+        ticket = request.form.get('ticket', '')
         if not wikiutil.checkTicket(request, ticket):
             request.theme.add_msg(_('Please use the interactive user interface to use action %(actionname)s!') % {'actionname': 'edit' }, "error")
             pg.send_page()
@@ -88,7 +88,7 @@
     try:
         if lasteditor == 'gui':
             # convert input from Graphical editor
-            format = request.form.get('format', ['wiki'])[0]
+            format = request.form.get('format', 'wiki')
             if format == 'wiki':
                 converter_name = 'text_html_text_moin_wiki'
             else:
--- a/MoinMoin/action/fckdialog.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/action/fckdialog.py	Tue Feb 10 13:21:59 2009 +0100
@@ -15,7 +15,6 @@
 
 def macro_dialog(request):
     help = get_macro_help(request)
-    request.emit_http_headers()
     request.write(
         '''<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
 <html>
@@ -164,13 +163,12 @@
 
 def page_list(request):
     from MoinMoin import search
-    name = request.form.get("pagename", [""])[0]
+    name = request.values.get("pagename", "")
     if name:
         searchresult = search.searchPages(request, 't:"%s"' % name)
         pages = [p.page_name for p in searchresult.hits]
     else:
         pages = [name]
-    request.emit_http_headers()
     request.write(
         '''<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
 <html>
@@ -201,9 +199,8 @@
 ''' % "".join(["<option>%s</option>\n" % p for p in pages]))
 
 def link_dialog(request):
-    request.emit_http_headers()
     # list of wiki pages
-    name = request.form.get("pagename", [""])[0]
+    name = request.values.get("pagename", "")
     if name:
         from MoinMoin import search
         # XXX error handling!
@@ -242,7 +239,7 @@
 
     # wiki url
     url_prefix_static = request.cfg.url_prefix_static
-    scriptname = request.getScriptname()
+    scriptname = request.script_root
     if not scriptname or scriptname[-1] != "/":
         scriptname += "/"
     action = scriptname
@@ -367,9 +364,8 @@
 ##############################################################################
 
 def attachment_dialog(request):
-    request.emit_http_headers()
     # list of wiki pages
-    name = request.form.get("pagename", [""])[0]
+    name = request.values.get("pagename", "")
     if name:
         from MoinMoin import search
         # XXX error handling!
@@ -393,7 +389,7 @@
 
     # wiki url
     url_prefix_static = request.cfg.url_prefix_static
-    scriptname = request.getScriptname()
+    scriptname = request.script_root
     if not scriptname or scriptname[-1] != "/":
         scriptname += "/"
     action = scriptname
@@ -461,7 +457,6 @@
 ##############################################################################
 
 def image_dialog(request):
-    request.emit_http_headers()
     url_prefix_static = request.cfg.url_prefix_static
     request.write('''
 <!--
@@ -524,7 +519,7 @@
 #############################################################################
 
 def execute(pagename, request):
-    dialog = request.form.get("dialog", [""])[0]
+    dialog = request.values.get("dialog", "")
 
     if dialog == "macro":
         macro_dialog(request)
--- a/MoinMoin/action/fullsearch.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/action/fullsearch.py	Tue Feb 10 13:21:59 2009 +0100
@@ -22,12 +22,12 @@
     'fullsearch' with localized string. If both missing, default to
     True (might happen with Safari) if this isn't an advanced search.
 """
-    form = request.form
+    form = request.values
     if 'titlesearch' in form and 'fullsearch' in form:
         ret = -1 # spammer / bot
     else:
         try:
-            ret = int(form['titlesearch'][0])
+            ret = int(form['titlesearch'])
         except ValueError:
             ret = 1
         except KeyError:
@@ -37,7 +37,7 @@
 def isAdvancedSearch(request):
     """ Return True if advanced search is requested """
     try:
-        return int(request.form['advancedsearch'][0])
+        return int(request.values['advancedsearch'])
     except KeyError:
         return False
 
@@ -66,38 +66,40 @@
 
     advancedsearch = isAdvancedSearch(request)
 
+    form = request.values
+
     # context is relevant only for full search
     if titlesearch:
         context = 0
     elif advancedsearch:
         context = 180 # XXX: hardcoded context count for advancedsearch
     else:
-        context = int(request.form.get('context', [0])[0])
+        context = int(form.get('context', 0))
 
     # Get other form parameters
-    needle = request.form.get(fieldname, [''])[0]
-    case = int(request.form.get('case', [0])[0])
-    regex = int(request.form.get('regex', [0])[0]) # no interface currently
-    hitsFrom = int(request.form.get('from', [0])[0])
+    needle = form.get(fieldname, '')
+    case = int(form.get('case', 0))
+    regex = int(form.get('regex', 0)) # no interface currently
+    hitsFrom = int(form.get('from', 0))
     mtime = None
     msg = ''
     historysearch = 0
 
     # if advanced search is enabled we construct our own search query
     if advancedsearch:
-        and_terms = request.form.get('and_terms', [''])[0].strip()
-        or_terms = request.form.get('or_terms', [''])[0].strip()
-        not_terms = request.form.get('not_terms', [''])[0].strip()
-        #xor_terms = request.form.get('xor_terms', [''])[0].strip()
-        categories = request.form.get('categories', [''])
-        timeframe = request.form.get('time', [''])[0].strip()
-        language = request.form.get('language', [''])
-        mimetype = request.form.get('mimetype', [0])
-        excludeunderlay = request.form.get('excludeunderlay', [0])[0]
-        nosystemitems = request.form.get('nosystemitems', [0])[0]
-        historysearch = request.form.get('historysearch', [0])[0]
+        and_terms = form.get('and_terms', '').strip()
+        or_terms = form.get('or_terms', '').strip()
+        not_terms = form.get('not_terms', '').strip()
+        #xor_terms = form.get('xor_terms', '').strip()
+        categories = form.getlist('categories') or ['']
+        timeframe = form.get('time', '').strip()
+        language = form.getlist('language') or ['']
+        mimetype = form.getlist('mimetype') or [0]
+        excludeunderlay = form.get('excludeunderlay', 0)
+        nosystemitems = form.get('nosystemitems', 0)
+        historysearch = form.get('historysearch', 0)
 
-        mtime = request.form.get('mtime', [''])[0]
+        mtime = form.get('mtime', '')
         if mtime:
             mtime_parsed = None
 
@@ -224,12 +226,10 @@
         Page(request, pagename).send_page()
         return
 
-    request.emit_http_headers()
-
     # This action generates data using the user language
     request.setContentLanguage(request.lang)
 
-    request.theme.send_title(title % needle, form=request.form, pagename=pagename)
+    request.theme.send_title(title % needle, pagename=pagename)
 
     # Start content (important for RTL support)
     request.write(request.formatter.startContent("content"))
--- a/MoinMoin/action/info.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/action/info.py	Tue Feb 10 13:21:59 2009 +0100
@@ -76,7 +76,7 @@
         _ = request.getText
         default_count, limit_max_count = request.cfg.history_count
         try:
-            max_count = int(request.form.get('max_count', [default_count])[0])
+            max_count = int(request.values.get('max_count', default_count))
         except:
             max_count = default_count
         max_count = min(max_count, limit_max_count)
@@ -143,7 +143,7 @@
                     if line.action == 'ATTNEW':
                         actions.append(render_action(_('view'), {'action': 'AttachFile', 'do': 'view', 'target': '%s' % filename}))
                     elif line.action == 'ATTDRW':
-                        actions.append(render_action(_('edit'), {'action': 'AttachFile', 'drawing': '%s' % filename.replace(".draw", "")}))
+                        actions.append(render_action(_('edit'), {'action': 'AttachFile', 'drawing': '%s' % filename.replace(".tdraw", "")}))
 
                     actions.append(render_action(_('get'), {'action': 'AttachFile', 'do': 'get', 'target': '%s' % filename}))
                     if request.user.may.delete(pagename):
@@ -187,8 +187,6 @@
     page = Page(request, pagename)
     title = page.split_title()
 
-    request.emit_http_headers()
-
     request.setContentLanguage(request.lang)
     f = request.formatter
 
@@ -207,14 +205,8 @@
         request.write("[%s] " % page.link_to(request, text=text, querystr=querystr, rel='nofollow'))
     request.write(f.paragraph(0))
 
-    try:
-        show_hitcounts = int(request.form.get('hitcounts', [0])[0]) != 0
-    except ValueError:
-        show_hitcounts = False
-    try:
-        show_general = int(request.form.get('general', [0])[0]) != 0
-    except ValueError:
-        show_general = False
+    show_hitcounts = int(request.values.get('hitcounts', 0)) != 0
+    show_general = int(request.values.get('general', 0)) != 0
 
     if show_hitcounts:
         from MoinMoin.stats import hitcounts
--- a/MoinMoin/action/links.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/action/links.py	Tue Feb 10 13:21:59 2009 +0100
@@ -11,15 +11,9 @@
 
 def execute(pagename, request):
     _ = request.getText
-    form = request.form
-
     # get the MIME type
-    if 'mimetype' in form:
-        mimetype = form['mimetype'][0]
-    else:
-        mimetype = "text/html"
-
-    request.emit_http_headers(["Content-Type: %s; charset=%s" % (mimetype, config.charset)])
+    mimetype = request.values.get('mimetype', 'text/html')
+    request.mimetype = mimetype
 
     if mimetype == "text/html":
         request.theme.send_title(_('Full Link List for "%s"') % request.cfg.sitename)
--- a/MoinMoin/action/login.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/action/login.py	Tue Feb 10 13:21:59 2009 +0100
@@ -38,7 +38,6 @@
         form.append(html.INPUT(type='hidden', name='stage',
                                value=request._login_multistage_name))
 
-        request.emit_http_headers()
         request.theme.send_title(_("Login"), pagename=self.pagename)
         # Start content (important for RTL support)
         request.write(request.formatter.startContent("content"))
@@ -59,7 +58,7 @@
 
         error = None
 
-        islogin = form.get('login', [''])[0]
+        islogin = form.get('login', '')
 
         if islogin: # user pressed login button
             if request._login_multistage:
@@ -74,7 +73,6 @@
             return self.page.send_page()
 
         else: # show login form
-            request.emit_http_headers()
             request.theme.send_title(_("Login"), pagename=self.pagename)
             # Start content (important for RTL support)
             request.write(request.formatter.startContent("content"))
--- a/MoinMoin/action/newaccount.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/action/newaccount.py	Tue Feb 10 13:21:59 2009 +0100
@@ -19,7 +19,7 @@
     _ = request.getText
     form = request.form
 
-    if request.request_method != 'POST':
+    if request.method != 'POST':
         return
 
     if not TextCha(request).check_answer_from_form():
@@ -30,7 +30,7 @@
 
     # Require non-empty name
     try:
-        theuser.name = form['name'][0]
+        theuser.name = form['name']
     except KeyError:
         return _("Empty user name. Please enter a user name.")
 
@@ -45,8 +45,8 @@
         return _("This user name already belongs to somebody else.")
 
     # try to get the password and pw repeat
-    password = form.get('password1', [''])[0]
-    password2 = form.get('password2', [''])[0]
+    password = form.get('password1', '')
+    password2 = form.get('password2', '')
 
     # Check if password is given and matches with password repeat
     if password != password2:
@@ -69,7 +69,7 @@
             return "Can't encode password: %s" % str(err)
 
     # try to get the email, for new users it is required
-    email = wikiutil.clean_input(form.get('email', [''])[0])
+    email = wikiutil.clean_input(form.get('email', ''))
     theuser.email = email.strip()
     if not theuser.email and 'email' not in request.cfg.user_form_remove:
         return _("Please provide your email address. If you lose your"
@@ -172,7 +172,6 @@
         request.theme.add_msg(_create_user(request), "dialog")
         return page.send_page()
     else: # show create form
-        request.emit_http_headers()
         request.theme.send_title(_("Create Account"), pagename=pagename)
 
         request.write(request.formatter.startContent("content"))
--- a/MoinMoin/action/newpage.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/action/newpage.py	Tue Feb 10 13:21:59 2009 +0100
@@ -19,8 +19,8 @@
     def __init__(self, request, referrer):
         self.request = request
         self.referrer = referrer # The page the user came from
-        self.pagename = self.request.form.get('pagename', [None])[0]
-        self.nametemplate = self.request.form.get('nametemplate', ['%s'])[0]
+        self.pagename = self.request.values.get('pagename')
+        self.nametemplate = self.request.values.get('nametemplate', '%s')
         self.nametemplate = self.nametemplate.replace('\x00', '')
 
     def checkAndCombineArguments(self):
@@ -82,11 +82,11 @@
             pagename = self.pagename
             query = {'action': 'edit', 'backto': self.referrer}
 
-            template = self.request.form.get('template', [''])[0]
+            template = self.request.values.get('template', '')
             if template:
                 query['template'] = template
 
-            parent = self.request.form.get('parent', [''])[0]
+            parent = self.request.values.get('parent', '')
             if parent:
                 pagename = "%s/%s" % (parent, pagename)
 
@@ -97,7 +97,7 @@
 
 def execute(pagename, request):
     """ Temporary glue code for current moin action system """
-    if request.request_method != 'POST':
+    if request.method != 'POST':
         return False, u''
 
     return NewPage(request, pagename).render()
--- a/MoinMoin/action/pollsistersites.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/action/pollsistersites.py	Tue Feb 10 13:21:59 2009 +0100
@@ -54,5 +54,5 @@
         except TypeError: # catch bug in python 2.5: "EnvironmentError expected at most 3 arguments, got 4"
             status.append(u"Site: %s Status: Not updated." % sistername)
 
-    request.emit_http_headers(["Content-Type: text/plain; charset=UTF-8"])
+    request.mimetype = 'text/plain'
     request.write("\r\n".join(status).encode("utf-8"))
--- a/MoinMoin/action/recoverpass.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/action/recoverpass.py	Tue Feb 10 13:21:59 2009 +0100
@@ -30,7 +30,7 @@
 Contact the owner of the wiki, who can enable email.""")
 
     try:
-        email = wikiutil.clean_input(form['email'][0].lower())
+        email = wikiutil.clean_input(form['email'].lower())
         if not email:
             # continue if email not given
             raise KeyError
@@ -42,7 +42,7 @@
         pass
 
     try:
-        username = wikiutil.clean_input(form['name'][0])
+        username = wikiutil.clean_input(form['name'])
         if not username:
             # continue if name not given
             raise KeyError
@@ -152,7 +152,7 @@
 
     page = Page(request, pagename)
     _ = request.getText
-    form = request.form
+    form = request.values # link in mail -> GET request
 
     if not request.cfg.mail_enabled:
         request.theme.add_msg(_("""This wiki is not enabled for mail processing.
@@ -160,13 +160,13 @@
         page.send_page()
         return
 
-    submitted = form.get('account_sendmail', [''])[0]
-    token = form.get('token', [''])[0]
-    newpass = form.get('password', [''])[0]
-    name = form.get('name', [''])[0]
+    submitted = form.get('account_sendmail', '')
+    token = form.get('token', '')
+    newpass = form.get('password', '')
+    name = form.get('name', '')
 
     if token and name and newpass:
-        newpass2 = form.get('password_repeat', [''])[0]
+        newpass2 = form.get('password_repeat', '')
         msg = _("Passwords don't match!")
         msg_type = 'error'
         if newpass == newpass2:
@@ -190,7 +190,6 @@
             return
 
     if token and name:
-        request.emit_http_headers()
         request.theme.send_title(_("Password reset"), pagename=pagename)
 
         request.write(request.formatter.startContent("content"))
@@ -205,13 +204,12 @@
         request.theme.send_footer(pagename)
         request.theme.send_closing_html()
     elif submitted: # user pressed create button
-        if request.request_method != 'POST':
+        if request.method != 'POST':
             return
         msg = _do_recover(request)
         request.theme.add_msg(msg, "dialog")
         page.send_page()
     else: # show create form
-        request.emit_http_headers()
         request.theme.send_title(_("Lost password"), pagename=pagename)
 
         request.write(request.formatter.startContent("content"))
--- a/MoinMoin/action/refresh.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/action/refresh.py	Tue Feb 10 13:21:59 2009 +0100
@@ -11,10 +11,10 @@
 def execute(pagename, request):
     """ Handle refresh action """
     # Without arguments, refresh action will refresh the page text_html cache.
-    arena = request.form.get('arena', ['Page.py'])[0]
+    arena = request.values.get('arena', 'Page.py')
     if arena == 'Page.py':
         arena = Page(request, pagename)
-    key = request.form.get('key', ['text_html'])[0]
+    key = request.values.get('key', 'text_html')
 
     # Remove cache entry (if exists), and send the page
     from MoinMoin import caching
--- a/MoinMoin/action/revert.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/action/revert.py	Tue Feb 10 13:21:59 2009 +0100
@@ -48,10 +48,10 @@
     def do_action(self):
         """ revert pagename """
         form = self.form
-        comment = form.get('comment', [u''])[0]
+        comment = form.get('comment', u'')
         comment = wikiutil.clean_input(comment)
 
-        if self.request.request_method != 'POST':
+        if self.request.method != 'POST':
             return False, u''
 
         rev = self.request.rev
--- a/MoinMoin/action/rss_rc.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/action/rss_rc.py	Tue Feb 10 13:21:59 2009 +0100
@@ -24,8 +24,7 @@
     """ Send recent changes as an RSS document
     """
     if not wikixml.ok:
-        httpheaders = ["Content-Type: text/plain; charset=%s" % config.charset]
-        request.emit_http_headers(httpheaders)
+        request.mimetype = 'text/plain'
         request.write("rss_rc action is not supported because of missing pyxml module.")
         return
 
@@ -34,22 +33,22 @@
     # get params
     items_limit = 100
     try:
-        max_items = int(request.form['items'][0])
+        max_items = int(request.values['items'])
         max_items = min(max_items, items_limit) # not more than `items_limit`
     except (KeyError, ValueError):
         # not more than 15 items in a RSS file by default
         max_items = 15
     try:
-        unique = int(request.form.get('unique', [0])[0])
+        unique = int(request.values.get('unique', 0))
     except ValueError:
         unique = 0
     try:
-        diffs = int(request.form.get('diffs', [0])[0])
+        diffs = int(request.values.get('diffs', 0))
     except ValueError:
         diffs = 0
     ## ddiffs inserted by Ralf Zosel <ralf@zosel.com>, 04.12.2003
     try:
-        ddiffs = int(request.form.get('ddiffs', [0])[0])
+        ddiffs = int(request.values.get('ddiffs', 0))
     except ValueError:
         ddiffs = 0
 
@@ -86,31 +85,27 @@
     if request.if_modified_since == timestamp:
         if request.if_none_match:
             if request.if_none_match == etag:
-                request.emit_http_headers(["Status: 304 Not modified"])
+                request.status_code = 304
         else:
-            request.emit_http_headers(["Status: 304 Not modified"])
+            request.status_code = 304
     elif request.if_none_match == etag:
         if request.if_modified_since:
             if request.if_modified_since == timestamp:
-                request.emit_http_headers(["Status: 304 Not modified"])
+                request.status_code = 304
         else:
-            request.emit_http_headers(["Status: 304 Not modified"])
+            request.status_code = 304
     else:
         # generate an Expires header, using whatever setting the admin
         # defined for suggested cache lifetime of the RecentChanges RSS doc
-        expires = timefuncs.formathttpdate(time.time() + cfg.rss_cache)
+        expires = time.time() + cfg.rss_cache
 
-        httpheaders = ["Content-Type: text/xml; charset=%s" % config.charset,
-                       "Expires: %s" % expires,
-                       "Last-Modified: %s" % timestamp,
-                       "Etag: %s" % etag, ]
+        request.mime_type = 'text/xml'
+        request.expires = expires
+        request.last_modified = lastmod
+        request.headers.add('Etag', etag)
 
         # send the generated XML document
-        request.emit_http_headers(httpheaders)
-
-        baseurl = request.getBaseURL()
-        if not baseurl.endswith('/'):
-            baseurl += '/'
+        baseurl = request.url_root
 
         logo = re.search(r'src="([^"]*)"', cfg.logo_string)
         if logo:
@@ -139,7 +134,7 @@
 
         # emit channel description
         handler.startNode('channel', {
-            (handler.xmlns['rdf'], 'about'): request.getBaseURL(),
+            (handler.xmlns['rdf'], 'about'): request.url_root,
             })
         handler.simpleNode('title', cfg.sitename)
         page = Page(request, pagename)
--- a/MoinMoin/action/serveopenid.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/action/serveopenid.py	Tue Feb 10 13:21:59 2009 +0100
@@ -18,7 +18,7 @@
 from openid.server import server
 from openid.message import IDENTIFIER_SELECT
 from MoinMoin.widget import html
-from MoinMoin.request import MoinMoinFinish
+from MoinMoin.web.request import MoinMoinFinish
 
 def execute(pagename, request):
     return MoinOpenIDServer(pagename, request).handle()
@@ -31,9 +31,8 @@
 
     def serveYadisEP(self, endpoint_url):
         request = self.request
-        hdrs = ['Content-type: application/xrds+xml']
+        request.content_type = 'application/xrds+xml'
 
-        request.emit_http_headers(hdrs)
         user_url = request.getQualifiedURL(request.page.url(request))
         self.request.write("""\
 <?xml version="1.0" encoding="UTF-8"?>
@@ -79,9 +78,8 @@
 
     def serveYadisIDP(self, endpoint_url):
         request = self.request
-        hdrs = ['Content-type: application/xrds+xml']
+        request.content_type = 'application/xrds+xml'
 
-        request.emit_http_headers(hdrs)
         user_url = request.getQualifiedURL(request.page.url(request))
         self.request.write("""\
 <?xml version="1.0" encoding="UTF-8"?>
@@ -190,7 +188,7 @@
         server_url = request.getQualifiedURL(
                          request.page.url(request, querystr={'action': 'serveopenid'}))
 
-        yadis_type = form.get('yadis', [None])[0]
+        yadis_type = form.get('yadis')
         if yadis_type == 'ep':
             return self.serveYadisEP(server_url)
         elif yadis_type == 'idp':
@@ -198,7 +196,7 @@
 
         # if the identity is set it must match the server URL
         # sort of arbitrary, but we have to have some restriction
-        identity = form.get('openid.identity', [None])[0]
+        identity = form.get('openid.identity')
         if identity == IDENTIFIER_SELECT:
             identity, server_url = self._make_identity()
             if not identity:
@@ -217,7 +215,7 @@
         openidsrv = server.Server(store, op_endpoint=server_url)
 
         answer = None
-        if form.has_key('dontapprove'):
+        if 'dontapprove' in form:
             answer = self.handle_response(False, username, identity)
             if answer is None:
                 return
@@ -227,8 +225,8 @@
                 return
         else:
             query = {}
-            for key in form.keys():
-                query[key] = form[key][0]
+            for key in form:
+                query[key] = form[key]
             try:
                 openidreq = openidsrv.decodeRequest(query)
             except Exception, e:
@@ -249,10 +247,9 @@
             else:
                 answer = openidsrv.handleRequest(openidreq)
         webanswer = openidsrv.encodeResponse(answer)
-        headers = ['Status: %d OpenID status' % webanswer.code]
+        request.status = '%d OpenID status' % webanswer.code
         for hdr in webanswer.headers:
-            headers += [hdr+': '+webanswer.headers[hdr]]
-        request.emit_http_headers(headers)
+            request.headers.add(hdr, webanswer.headers[hdr])
         request.write(webanswer.body)
         raise MoinMoinFinish
 
@@ -266,7 +263,7 @@
         if session_nonce is not None:
             del self.request.session['openidserver.nonce']
         # use empty string if nothing was sent
-        form_nonce = form.get('nonce', [''])[0]
+        form_nonce = form.get('nonce', '')
         if session_nonce != form_nonce:
             self.request.makeForbidden403()
             self.request.write('invalid nonce')
@@ -285,7 +282,7 @@
             return openidreq.answer(False)
 
 
-        if form.get('remember', ['no'])[0] == 'yes':
+        if form.get('remember', 'no') == 'yes':
             if not hasattr(request.user, 'openid_trusted_roots'):
                 request.user.openid_trusted_roots = []
             request.user.openid_trusted_roots.append(strbase64(openidreq.trust_root))
@@ -324,7 +321,6 @@
 Once you have logged in, simply reload this page.'''))
             return
 
-        request.emit_http_headers()
         request.theme.send_title(_("OpenID Trust verification"), pagename=request.page.page_name)
         # Start content (important for RTL support)
         request.write(request.formatter.startContent("content"))
@@ -397,7 +393,6 @@
         request = self.request
         _ = self._
 
-        request.emit_http_headers()
         request.theme.send_title(_("OpenID not served"), pagename=request.page.page_name)
         # Start content (important for RTL support)
         request.write(request.formatter.startContent("content"))
--- a/MoinMoin/action/showtags.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/action/showtags.py	Tue Feb 10 13:21:59 2009 +0100
@@ -13,9 +13,7 @@
 from MoinMoin.wikisync import TagStore
 
 def execute(pagename, request):
-    mimetype = "text/plain"
-
-    request.emit_http_headers(["Content-Type: %s; charset=%s" % (mimetype, config.charset)])
+    request.mimetype = "text/plain"
 
     page = Page(request, pagename)
     tags = TagStore(page)
--- a/MoinMoin/action/sisterpages.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/action/sisterpages.py	Tue Feb 10 13:21:59 2009 +0100
@@ -32,30 +32,26 @@
     if request.if_modified_since == timestamp:
         if request.if_none_match:
             if request.if_none_match == etag:
-                request.emit_http_headers(["Status: 304 Not modified"])
+                request.status_code = 304
         else:
-            request.emit_http_headers(["Status: 304 Not modified"])
+            request.status_code = 304
     elif request.if_none_match == etag:
         if request.if_modified_since:
             if request.if_modified_since == timestamp:
-                request.emit_http_headers(["Status: 304 Not modified"])
+                request.status_code = 304
         else:
-            request.emit_http_headers(["Status: 304 Not modified"])
+            request.status_code = 304
     else:
         # generate an Expires header, using 1d cache lifetime of sisterpages list
-        expires = timefuncs.formathttpdate(time.time() + 24*3600)
+        expires = time.time() + 24*3600
 
-        httpheaders = ["Content-Type: text/plain; charset=UTF-8",
-                       "Expires: %s" % expires,
-                       "Last-Modified: %s" % timestamp,
-                       "Etag: %s" % etag, ]
+        request.mime_type = 'text/plain'
+        request.expires = expires
+        request.last_modified = timestamp
+        request.headers.add("Etag", etag)
 
         # send the generated XML document
-        request.emit_http_headers(httpheaders)
-
-        baseurl = request.getBaseURL()
-        if not baseurl.endswith('/'):
-            baseurl += '/'
+        baseurl = request.url_root
 
         # Get list of user readable pages
         pages = request.rootpage.getPageList()
--- a/MoinMoin/action/sitemap.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/action/sitemap.py	Tue Feb 10 13:21:59 2009 +0100
@@ -62,10 +62,9 @@
 
 def execute(pagename, request):
     _ = request.getText
-    form = request.form
     request.user.datetime_fmt = datetime_fmt
 
-    request.emit_http_headers(["Content-Type: text/xml; charset=UTF-8"])
+    request.mimetype ='text/xml'
 
     # we emit a piece of data so other side doesn't get bored:
     request.write("""<?xml version="1.0" encoding="UTF-8"?>\r\n""")
@@ -86,7 +85,7 @@
 
     # Get page dict readable by current user
     try:
-        underlay = int(form.get('underlay', [1])[0])
+        underlay = int(request.values.get('underlay', 1))
     except ValueError:
         underlay = 1
     pages = request.rootpage.getPageDict(include_underlay=underlay)
--- a/MoinMoin/action/thread_monitor.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/action/thread_monitor.py	Tue Feb 10 13:21:59 2009 +0100
@@ -33,7 +33,6 @@
     else:
         dump_fname = "nowhere"
 
-    request.emit_http_headers()
     request.write('<html><body>A dump has been saved to %s.</body></html>' % dump_fname)
 
 def execute_wiki(pagename, request):
@@ -44,8 +43,6 @@
         request.theme.add_msg(_('You are not allowed to use this action.'), "error")
         return Page.Page(request, pagename).send_page()
 
-    request.emit_http_headers()
-
     request.theme.send_title("Thread monitor")
     request.write('<pre>')
 
--- a/MoinMoin/action/titleindex.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/action/titleindex.py	Tue Feb 10 13:21:59 2009 +0100
@@ -14,15 +14,9 @@
 
 
 def execute(pagename, request):
-    form = request.form
-
     # get the MIME type
-    if 'mimetype' in form:
-        mimetype = form['mimetype'][0]
-    else:
-        mimetype = "text/plain"
-
-    request.emit_http_headers(["Content-Type: %s; charset=%s" % (mimetype, config.charset)])
+    mimetype = request.values.get('mimetype', "text/plain")
+    request.mimetype = mimetype
 
     # Get list of user readable pages
     pages = request.rootpage.getPageList()
--- a/MoinMoin/action/userprefs.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/action/userprefs.py	Tue Feb 10 13:21:59 2009 +0100
@@ -16,7 +16,7 @@
     Return error msg_class, msg tuple or None, None.
     """
     _ = request.getText
-    sub = request.form.get('handler', [None])[0]
+    sub = request.values.get('handler')
 
     if sub in request.cfg.userprefs_disabled:
         return None, None
@@ -63,12 +63,12 @@
     # returns text, title, msg_class, msg
     pagename = request.page.page_name
 
-    if 'handler' in request.form:
+    if 'handler' in request.values:
         msg_class, msg = _handle_submission(request)
     else:
         msg_class, msg = None, None
 
-    sub = request.form.get('sub', [''])[0]
+    sub = request.args.get('sub', '')
     cls = None
     if sub and sub not in request.cfg.userprefs_disabled:
         try:
@@ -101,7 +101,6 @@
         title = _("Settings") + ":" + title
     else:
         title = _("Settings")
-    request.emit_http_headers()
     request.theme.add_msg(msg, msg_class)
     request.theme.send_title(title, page=request.page, pagename=pagename)
     # Start content (important for RTL support)
--- a/MoinMoin/action/userprofile.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/action/userprofile.py	Tue Feb 10 13:21:59 2009 +0100
@@ -17,9 +17,9 @@
     if not request.user.isSuperUser():
         request.theme.add_msg(_("Only superuser is allowed to use this action."), "error")
     else:
-        user_name = form.get('name', [''])[0]
-        key = form.get('key', [''])[0]
-        val = form.get('val', [''])[0]
+        user_name = form.get('name', '')
+        key = form.get('key', '')
+        val = form.get('val', '')
         if key in cfg.user_checkbox_fields:
             val = int(val)
         uid = user.getUserId(request, user_name)
--- a/MoinMoin/auth/__init__.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/auth/__init__.py	Tue Feb 10 13:21:59 2009 +0100
@@ -128,7 +128,7 @@
     @copyright: 2005-2006 Bastian Blank, Florian Festi,
                           MoinMoin:AlexanderSchremmer, Nick Phillips,
                           MoinMoin:FrankieChow, MoinMoin:NirSoffer,
-                2005-2008 MoinMoin:ThomasWaldmann,
+                2005-2009 MoinMoin:ThomasWaldmann,
                 2007      MoinMoin:JohannesBerg
 
     @license: GNU GPL, see COPYING for details.
@@ -160,9 +160,7 @@
     if request.page:
         return request.page.url(request, querystr=fields)
     else:
-        qstr = wikiutil.makeQueryString(fields)
-        return ''.join([request.getBaseURL(), '?', qstr])
-
+        return request.abs_href(**fields)
 
 class LoginReturn(object):
     """ LoginReturn - base class for auth method login() return value"""
@@ -257,3 +255,204 @@
                'userprefslink': userprefslink,
                'sendmypasswordlink': sendmypasswordlink}
 
+
+class GivenAuth(BaseAuth):
+    """ reuse a given authentication, e.g. http basic auth (or any other auth)
+        done by the web server, that sets REMOTE_USER environment variable.
+        This is the default behaviour.
+        You can also specify to read another environment variable (env_var).
+        Alternatively you can directly give a fixed user name (user_name)
+        that will be considered as authenticated.
+    """
+    name = 'given' # was 'http' in 1.8.x and before
+
+    def __init__(self,
+                 env_var=None,  # environment variable we want to read (default: REMOTE_USER)
+                 user_name=None,  # can be used to just give a specific user name to log in
+                 autocreate=False,  # create/update the user profile for the auth. user
+                 strip_maildomain=False,  # joe@example.org -> joe
+                 strip_windomain=False,  # DOMAIN\joe -> joe
+                 titlecase=False,  # joe doe -> Joe Doe
+                 remove_blanks=False,  # Joe Doe -> JoeDoe
+                 coding=None,  # for decoding REMOTE_USER correctly (default: auto)
+                ):
+        self.env_var = env_var
+        self.user_name = user_name
+        self.autocreate = autocreate
+        self.strip_maildomain = strip_maildomain
+        self.strip_windomain = strip_windomain
+        self.titlecase = titlecase
+        self.remove_blanks = remove_blanks
+        self.coding = coding
+        BaseAuth.__init__(self)
+
+    def decode_username(self, name):
+        """ decode the name we got from the environment var to unicode """
+        if isinstance(name, str):
+            if self.coding:
+                name = name.decode(self.coding)
+            else:
+                # XXX we have no idea about REMOTE_USER encoding, please help if
+                # you know how to do that cleanly
+                name = wikiutil.decodeUnknownInput(name)
+        return name
+
+    def transform_username(self, name):
+        """ transform the name we got (unicode in, unicode out)
+
+            Note: if you need something more special, you could create your own
+                  auth class, inherit from this class and overwrite this function.
+        """
+        assert isinstance(name, unicode)
+        if self.strip_maildomain:
+            # split off mail domain, e.g. "user@example.org" -> "user"
+            name = name.split(u'@')[0]
+
+        if self.strip_windomain:
+            # split off window domain, e.g. "DOMAIN\user" -> "user"
+            name = name.split(u'\\')[-1]
+
+        if self.titlecase:
+            # this "normalizes" the login name, e.g. meier, Meier, MEIER -> Meier
+            name = name.title()
+
+        if self.remove_blanks:
+            # remove blanks e.g. "Joe Doe" -> "JoeDoe"
+            name = u''.join(name.split())
+
+        return name
+
+    def request(self, request, user_obj, **kw):
+        u = None
+        _ = request.getText
+        # always revalidate auth
+        if user_obj and user_obj.auth_method == self.name:
+            user_obj = None
+        # something else authenticated before us
+        if user_obj:
+            logging.debug("already authenticated, doing nothing")
+            return user_obj, True
+
+        if self.user_name is not None:
+            auth_username = self.user_name
+        elif self.env_var is None:
+            auth_username = request.remote_user
+        else:
+            auth_username = request.environ.get(self.env_var)
+
+        logging.debug("auth_username = %r" % auth_username)
+        if auth_username:
+            auth_username = self.decode_username(auth_username)
+            auth_username = self.transform_username(auth_username)
+            logging.debug("auth_username (after decode/transform) = %r" % auth_username)
+            u = user.User(request, auth_username=auth_username,
+                          auth_method=self.name, auth_attribs=('name', 'password'))
+
+        if u and self.autocreate:
+            u.create_or_update()
+        if u and u.valid:
+            return u, True # True to get other methods called, too
+        else:
+            return user_obj, True
+
+
+def handle_login(request, userobj=None, username=None, password=None,
+                 attended=True, openid_identifier=None, stage=None):
+    """
+    Process a 'login' request by going through the configured authentication
+    methods in turn. The passable keyword arguments are explained in more
+    detail at the top of this file.
+    """
+    params = {
+        'username': username,
+        'password': password,
+        'attended': attended,
+        'openid_identifier': openid_identifier,
+        'multistage': (stage and True) or None
+    }
+    for authmethod in request.cfg.auth:
+        if stage and authmethod.name != stage:
+            continue
+        ret = authmethod.login(request, userobj, **params)
+
+        userobj = ret.user_obj
+        cont = ret.continue_flag
+        if stage:
+            stage = None
+            del params['multistage']
+
+        if ret.multistage:
+            request._login_multistage = ret.multistage
+            request._login_multistage_name = authmethod.name
+            return userobj
+
+        if ret.redirect_to:
+            nextstage = auth.get_multistage_continuation_url(request, authmethod.name)
+            url = ret.redirect_to
+            url = url.replace('%return_form', quote_plus(nextstage))
+            url = url.replace('%return', quote(nextstage))
+            abort(redirect(url))
+        msg = ret.message
+        if msg and not msg in request._login_messages:
+            request._login_messages.append(msg)
+
+        if not cont:
+            break
+
+    return userobj
+
+def handle_logout(request, userobj):
+    """ Logout the passed user from every configured authentication method. """
+    if userobj.auth_method == 'setuid':
+        # we have no authmethod object for setuid
+        userobj = request._setuid_real_user
+        del request._setuid_real_user
+        return userobj
+
+    for authmethod in request.cfg.auth:
+        userobj, cont = authmethod.logout(request, userobj, cookie=request.cookies)
+        if not cont:
+            break
+    return userobj
+
+def handle_request(request, userobj):
+    """ Handle the per-request callbacks of the configured authentication methods. """
+    for authmethod in request.cfg.auth:
+        userobj, cont = authmethod.request(request, userobj, cookie=request.cookies)
+        if not cont:
+            break
+    return userobj
+
+def setup_setuid(request, userobj):
+    """ Check for setuid conditions in the session and setup an user
+    object accordingly. Returns a tuple of the new user objects.
+
+    @param request: a moin request object
+    @param userobj: a moin user object
+    @rtype: boolean
+    @return: (new_user, user) or (user, None)
+    """
+    old_user = None
+    if 'setuid' in request.session and userobj.isSuperUser():
+        old_user = userobj
+        uid = request.session['setuid']
+        userobj = user.User(request, uid, auth_method='setuid')
+        userobj.valid = True
+    logging.debug("setup_suid returns %r, %r" % (userobj, old_user))
+    return (userobj, old_user)
+
+def setup_from_session(request, session):
+    userobj = None
+    if 'user.id' in session:
+        auth_userid = session['user.id']
+        auth_method = session['user.auth_method']
+        auth_attrs = session['user.auth_attribs']
+        logging.debug("got from session: %r %r" % (auth_userid, auth_method))
+        logging.debug("current auth methods: %r" % request.cfg.auth_methods)
+        if auth_method and auth_method in request.cfg.auth_methods:
+            userobj = user.User(request, id=auth_userid,
+                                auth_method=auth_method,
+                                auth_attribs=auth_attrs)
+    logging.debug("session started for user %r", userobj)
+    return userobj
+
--- a/MoinMoin/auth/_tests/test_auth.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/auth/_tests/test_auth.py	Tue Feb 10 13:21:59 2009 +0100
@@ -5,14 +5,10 @@
     @copyright: 2008 MoinMoin:ThomasWaldmann
     @license: GNU GPL, see COPYING for details.
 """
-
 import py.test
-py.test.skip("broken due to test Config refactoring, fix later")
 
-import StringIO, urllib
-
-from MoinMoin.server.server_wsgi import WsgiConfig
-from MoinMoin.request import request_wsgi
+from MoinMoin.web.request import TestRequest, evaluate_request
+from MoinMoin import wsgiapp
 from MoinMoin._tests import wikiconfig
 
 
@@ -25,55 +21,34 @@
 
         Some test needs specific config values, or they will fail.
         """
-        config = WsgiConfig() # you MUST create an instance
 
     def teardown_class(cls):
         """ Stuff that should run to clean up the state of this test class
 
         """
-        pass
 
-    def setup_env(self, **kw):
-        default_environ = {
-            'SERVER_NAME': 'localhost',
-            'SERVER_PORT': '80',
-            'SCRIPT_NAME': '',
-            'PATH_INFO': '/',
-            'QUERY_STRING': '',
-            'REQUEST_METHOD': 'GET',
-            'REMOTE_ADDR': '10.10.10.10',
-            'HTTP_HOST': 'localhost',
-            #'HTTP_COOKIE': '',
-            #'HTTP_ACCEPT_LANGUAGE': '',
-        }
-        env = {}
-        env.update(default_environ)
-        env.update(kw)
-        if 'wsgi.input' not in env:
-            env['wsgi.input'] = StringIO.StringIO()
-        return env
-
-    def process_request(self, environ):
-        request = request_wsgi.Request(environ)
-        save_user = request.user # keep a reference, request.finish does "del request.user"
-        request.run()
-        request.user = save_user
-        return request # request.status, request.headers, request.output()
+    def run_request(self, **params):
+        request = TestRequest(**params)
+        #XXX: config passing hack
+        request.given_config = getattr(self, 'Config', wikiconfig.Config)
+        context = wsgiapp.init(request)
+        wsgiapp.run(context)
+        return context
 
 
 class TestNoAuth(AuthTest):
     def testNoAuth(self):
         """ run a simple request, no auth, just check if it succeeds """
-        environ = self.setup_env()
-        request = self.process_request(environ)
+        request = self.run_request()
 
         # anon user?
         assert not request.user.valid
 
+        appiter, status, headers = evaluate_request(request.request)
         # check if the request resulted in normal status, result headers and content
-        assert request.status == '200 OK'
+        assert status[:3] == '200'
         has_ct = has_v = has_cc = False
-        for k, v in request.headers:
+        for k, v in headers:
             if k == 'Content-Type':
                 assert v.startswith('text/html')
                 has_ct = True
@@ -90,8 +65,7 @@
         assert has_v
         # XXX BROKEN?:
         #assert has_cc # cache anon user's content
-        output = request.output()
-        assert '</html>' in output
+        assert '</html>' in ''.join(appiter)
 
 class TestAnonSession(AuthTest):
     class Config(wikiconfig.Config):
@@ -103,20 +77,21 @@
         trail_expected = []
         first = True
         for pagename in self.PAGES:
-            environ = self.setup_env(PATH_INFO='/%s' % pagename,
-                                     HTTP_COOKIE=cookie)
-            request = self.process_request(environ)
+            environ_overrides = {'HTTP_COOKIE': cookie}
+            request = self.run_request(path='/%s' % pagename,
+                                       environ_overrides=environ_overrides)
 
             # anon user?
             assert not request.user.valid
 
             # Do we have a session?
-            assert request.session
+            assert request.session is not None
 
+            appiter, status, headers = evaluate_request(request.request)
             # check if the request resulted in normal status, result headers and content
-            assert request.status == '200 OK'
+            assert status[:3] == '200'
             has_ct = has_v = has_cc = False
-            for k, v in request.headers:
+            for k, v in headers:
                 if k == 'Content-Type':
                     assert v.startswith('text/html')
                     has_ct = True
@@ -134,8 +109,7 @@
             assert has_v
             # XX BROKEN
             #assert not has_cc # do not cache anon user's (with session!) content
-            output = request.output()
-            assert '</html>' in output
+            assert '</html>' in ''.join(appiter)
 
             # The trail is only ever saved on the second page display
             # because otherwise anonymous sessions would be created
@@ -163,24 +137,27 @@
     def testHttpAuthSession(self):
         """ run some requests with http auth, check whether session works """
         username = u'HttpAuthTestUser'
+        auth_info = u'%s:%s' % (username, u'testpass')
+        auth_header = 'Basic %s' % auth_info.encode('base64')
         cookie = ''
         trail_expected = []
         first = True
         for pagename in self.PAGES:
-            environ = self.setup_env(AUTH_TYPE='Basic', REMOTE_USER=str(username),
-                                     PATH_INFO='/%s' % pagename,
-                                     HTTP_COOKIE=cookie)
-            request = self.process_request(environ)
+            environ_overrides = {'HTTP_COOKIE': cookie,
+                                 'HTTP_AUTHORIZATION': auth_header}
+            request = self.run_request(path='/%s' % pagename,
+                                       environ_overrides=environ_overrides)
 
             # Login worked?
             assert request.user.valid
             assert request.user.name == username
 
             # Do we have a session?
-            assert request.session
+            assert request.session is not None
 
+            appiter, status, headers = evaluate_request(request.request)
             # check if the request resulted in normal status, result headers and content
-            assert request.status == '200 OK'
+            assert status[:3] == '200'
             has_ct = has_v = has_cc = False
             for k, v in request.headers:
                 if k == 'Content-Type':
@@ -199,8 +176,7 @@
             assert has_ct
             assert has_v
             assert has_cc # do not cache logged-in user's content
-            output = request.output()
-            assert '</html>' in output
+            assert '</html>' in ''.join(appiter)
 
             # The trail is only ever saved on the second page display
             # because otherwise anonymous sessions would be created
@@ -233,30 +209,29 @@
         first = True
         for pagename in self.PAGES:
             if first:
-                formdata = urllib.urlencode({
-                    'name': username.encode('utf-8'),
-                    'password': password.encode('utf-8'),
+                formdata = {
+                    'name': username,
+                    'password': password,
                     'login': 'login',
-                })
-                environ = self.setup_env(PATH_INFO='/%s' % pagename,
-                                         HTTP_CONTENT_TYPE='application/x-www-form-urlencoded',
-                                         HTTP_CONTENT_LENGTH='%d' % len(formdata),
-                                         QUERY_STRING='action=login', REQUEST_METHOD='POST',
-                                         **{'wsgi.input': StringIO.StringIO(formdata)})
+                }
+                request = self.run_request(path='/%s' % pagename,
+                                           query_string='login=login',
+                                           method='POST', form_data=formdata)
             else: # not first page, use session cookie
-                environ = self.setup_env(PATH_INFO='/%s' % pagename,
-                                         HTTP_COOKIE=cookie)
-            request = self.process_request(environ)
+                environ_overrides = {'HTTP_COOKIE': cookie}
+                request = self.run_request(path='/%s' % pagename,
+                                           environ_overrides=environ_overrides)
 
             # Login worked?
             assert request.user.valid
             assert request.user.name == username
 
             # Do we have a session?
-            assert request.session
+            assert request.session is not None
 
+            appiter, status, headers = evaluate_request(request.request)
             # check if the request resulted in normal status, result headers and content
-            assert request.status == '200 OK'
+            assert status[:3] == '200'
             has_ct = has_v = has_cc = False
             for k, v in request.headers:
                 if k == 'Content-Type':
@@ -275,8 +250,7 @@
             assert has_ct
             assert has_v
             assert has_cc # do not cache logged-in user's content
-            output = request.output()
-            assert '</html>' in output
+            assert '</html>' in ''.join(appiter)
 
             # The trail is only ever saved on the second page display
             # because otherwise anonymous sessions would be created
--- a/MoinMoin/auth/_tests/test_ldap_login.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/auth/_tests/test_ldap_login.py	Tue Feb 10 13:21:59 2009 +0100
@@ -12,6 +12,7 @@
 from MoinMoin._tests.ldap_testbase import LDAPTstBase, LdapEnvironment, check_environ, SLAPD_EXECUTABLE
 from MoinMoin._tests.ldap_testdata import *
 from MoinMoin._tests import nuke_user, wikiconfig
+from MoinMoin.auth import handle_login
 
 # first check if we have python 2.4, python-ldap and slapd:
 msg = check_environ()
@@ -60,21 +61,21 @@
         handle_auth = self.request.handle_auth
 
         # tests that must not authenticate:
-        u = handle_auth(None, username='', password='', login=True)
+        u = handle_login(self.request, None, username='', password='')
         assert u is None
-        u = handle_auth(None, username='usera', password='', login=True)
+        u = handle_login(self.request, None, username='usera', password='')
         assert u is None
-        u = handle_auth(None, username='usera', password='userawrong', login=True)
+        u = handle_login(self.request, None, username='usera', password='userawrong')
         assert u is None
-        u = handle_auth(None, username='userawrong', password='usera', login=True)
+        u = handle_login(self.request, None, username='userawrong', password='usera')
         assert u is None
 
         # tests that must authenticate:
-        u1 = handle_auth(None, username='usera', password='usera', login=True)
+        u1 = handle_login(self.request, None, username='usera', password='usera')
         assert u1 is not None
         assert u1.valid
 
-        u2 = handle_auth(None, username='userb', password='userb', login=True)
+        u2 = handle_login(self.request, None, username='userb', password='userb')
         assert u2 is not None
         assert u2.valid
 
@@ -111,27 +112,25 @@
 
         nuke_user(self.request, u'usera')
 
-        handle_auth = self.request.handle_auth
-
         # do a LDAPAuth login (as a side effect, this autocreates the user profile):
-        u1 = handle_auth(None, username='usera', password='usera', login=True)
+        u1 = handle_login(self.request, None, username='usera', password='usera')
         assert u1 is not None
         assert u1.valid
 
         # now we kill the LDAP server:
-        self.ldap_env.slapd.stop()
+        #self.ldap_env.slapd.stop()
 
         # now try a MoinAuth login:
         # try the default password that worked in 1.7 up to rc1:
-        u2 = handle_auth(None, username='usera', password='{SHA}NotStored', login=True)
+        u2 = handle_login(self.request, None, username='usera', password='{SHA}NotStored')
         assert u2 is None
 
         # try using no password:
-        u2 = handle_auth(None, username='usera', password='', login=True)
+        u2 = handle_login(self.request, None, username='usera', password='')
         assert u2 is None
 
         # try using wrong password:
-        u2 = handle_auth(None, username='usera', password='wrong', login=True)
+        u2 = handle_login(self.request, None, username='usera', password='wrong')
         assert u2 is None
 
 
@@ -221,7 +220,7 @@
         handle_auth = self.request.handle_auth
 
         # authenticate user (with primary slapd):
-        u1 = handle_auth(None, username='usera', password='usera', login=True)
+        u1 = handle_login(self.request, None, username='usera', password='usera')
         assert u1 is not None
         assert u1.valid
 
@@ -229,7 +228,7 @@
         self.ldap_envs[0].slapd.stop()
 
         # try if we can still authenticate (with the second slapd):
-        u2 = handle_auth(None, username='usera', password='usera', login=True)
+        u2 = handle_login(self.request, None, username='usera', password='usera')
         assert u2 is not None
         assert u2.valid
 
--- a/MoinMoin/auth/http.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/auth/http.py	Tue Feb 10 13:21:59 2009 +0100
@@ -1,84 +1,36 @@
 # -*- coding: iso-8859-1 -*-
 """
-    MoinMoin - http authentication
+    MoinMoin - http authentication (or rather: using REMOTE_USER)
 
-    You need either your webserver configured for doing HTTP auth (like Apache
-    reading some .htpasswd file) or Twisted (will accept HTTP auth against
-    password stored in moin user profile, but currently will NOT ask for auth)
-    or Standalone (in which case it will ask for auth and accept auth against
-    stored user profile.)
+    This is just a dummy redirecting to MoinMoin.auth.GivenAuth for backwards
+    compatibility.
 
-    @copyright: 2006 MoinMoin:ThomasWaldmann
-                2007 MoinMoin:JohannesBerg
+    Please fix your setup, this dummy will be removed soon:
+
+    Old (1.8.x):
+    ------------
+    from MoinMoin.auth.http import HTTPAuth
+    auth = [HTTPAuth(autocreate=True)]
+    # any presence (or absence) of 'http' auth name, e.g.:
+    auth_methods_trusted = ['http', 'xmlrpc_applytoken']
+
+    New (1.9.x):
+    ------------
+    from MoinMoin.auth import GivenAuth
+    auth = [GivenAuth(autocreate=True)]
+    # presence (or absence) of 'given' auth name, e.g.:
+    auth_methods_trusted = ['given', 'xmlrpc_applytoken']
+
+    @copyright: 2009 MoinMoin:ThomasWaldmann
     @license: GNU GPL, see COPYING for details.
 """
 
-from MoinMoin import config, user
-from MoinMoin.request import request_twisted, request_cli, request_standalone
-from MoinMoin.auth import BaseAuth
-from base64 import decodestring
-
-class HTTPAuth(BaseAuth):
-    """ authenticate via http basic/digest/ntlm auth """
-    name = 'http'
-
-    def __init__(self, autocreate=False):
-        self.autocreate = autocreate
-        BaseAuth.__init__(self)
-
-    def request(self, request, user_obj, **kw):
-        u = None
-        _ = request.getText
-        # always revalidate auth
-        if user_obj and user_obj.auth_method == self.name:
-            user_obj = None
-        # something else authenticated before us
-        if user_obj:
-            return user_obj, True
+from MoinMoin import log
+logging = log.getLogger(__name__)
 
-        # for standalone, request authorization and verify it,
-        # deny access if it isn't verified
-        if isinstance(request, request_standalone.Request):
-            request.setHttpHeader('WWW-Authenticate: Basic realm="MoinMoin"')
-            auth = request.headers.get('Authorization')
-            if auth:
-                auth = auth.split()[-1]
-                info = decodestring(auth).split(':', 1)
-                if len(info) == 2:
-                    u = user.User(request, auth_username=info[0], password=info[1],
-                                  auth_method=self.name, auth_attribs=[])
-            if not u:
-                request.makeForbidden(401, _('You need to log in.'))
-        # for Twisted, just check
-        elif isinstance(request, request_twisted.Request):
-            username = request.twistd.getUser().decode(config.charset)
-            password = request.twistd.getPassword().decode(config.charset)
-            # when using Twisted http auth, we use username and password from
-            # the moin user profile, so both can be changed by user.
-            u = user.User(request, auth_username=username, password=password,
-                          auth_method=self.name, auth_attribs=())
-        elif not isinstance(request, request_cli.Request):
-            env = request.env
-            auth_type = env.get('AUTH_TYPE', '')
-            if auth_type in ['Basic', 'Digest', 'NTLM', 'Negotiate', ]:
-                username = env.get('REMOTE_USER', '').decode(config.charset)
-                if auth_type in ('NTLM', 'Negotiate', ):
-                    # converting to standard case so the user can even enter wrong case
-                    # (added since windows does not distinguish between e.g.
-                    #  "Mike" and "mike")
-                    username = username.split('\\')[-1] # split off domain e.g.
-                                                        # from DOMAIN\user
-                    # this "normalizes" the login name from {meier, Meier, MEIER} to Meier
-                    # put a comment sign in front of next line if you don't want that:
-                    username = username.title()
-                # when using http auth, we have external user name and password,
-                # we don't use the moin user profile for those attributes.
-                u = user.User(request, auth_username=username,
-                              auth_method=self.name, auth_attribs=('name', 'password'))
+from MoinMoin.auth import GivenAuth
 
-        if u and self.autocreate:
-            u.create_or_update()
-        if u and u.valid:
-            return u, True # True to get other methods called, too
-        else:
-            return user_obj, True
+class HTTPAuth(GivenAuth):
+    name = 'http'  # GivenAuth uses 'given'
+    logging.warning("DEPRECATED use of MoinMoin.auth.http, please read instructions there or docs/CHANGES!")
+
--- a/MoinMoin/auth/openidrp.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/auth/openidrp.py	Tue Feb 10 13:21:59 2009 +0100
@@ -136,7 +136,7 @@
                                         MoinOpenIDStore(request))
         query = {}
         for key in request.form:
-            query[key] = request.form[key][0]
+            query[key] = request.form[key]
         current_url = get_multistage_continuation_url(request, self.name,
                                                       {'oidstage': '1'})
         info = oidconsumer.complete(query, current_url)
@@ -173,7 +173,7 @@
             return CancelLogin(None)
 
         _ = request.getText
-        newname = request.form.get('username', [''])[0]
+        newname = request.form.get('username', '')
         if not newname:
             return MultistageFormLogin(self._get_account_name)
         if not user.isValidName(request, newname):
@@ -198,8 +198,8 @@
             return CancelLogin()
 
         _ = request.getText
-        username = request.form.get('username', [''])[0]
-        password = request.form.get('password', [''])[0]
+        username = request.form.get('username', '')
+        password = request.form.get('password', '')
         if not password:
             return self._handle_name_continuation(request)
         u = user.User(request, name=username, password=password,
@@ -214,7 +214,7 @@
             return MultistageFormLogin(assoc)
 
     def _handle_continuation(self, request):
-        oidstage = request.form.get('oidstage', [0])[0]
+        oidstage = request.form.get('oidstage', '0')
         if oidstage == '1':
             return self._handle_verify_continuation(request)
         elif oidstage == '2':
@@ -282,7 +282,7 @@
 
             return_to = get_multistage_continuation_url(request, self.name,
                                                         {'oidstage': '1'})
-            trust_root = request.getBaseURL()
+            trust_root = request.url_root
             if oidreq.shouldSendRedirect():
                 redirect_url = oidreq.redirectURL(trust_root, return_to)
                 return MultistageRedirectLogin(redirect_url)
--- a/MoinMoin/auth/sslclientcert.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/auth/sslclientcert.py	Tue Feb 10 13:21:59 2009 +0100
@@ -11,7 +11,6 @@
 """
 
 from MoinMoin import config, user
-from MoinMoin.request import request_twisted
 from MoinMoin.auth import BaseAuth
 
 class SSLClientCertAuth(BaseAuth):
@@ -35,60 +34,53 @@
     def request(self, request, user_obj, **kw):
         u = None
         changed = False
-        # check if we are running Twisted
-        if isinstance(request, request_twisted.Request):
-            return user_obj, True # not supported if we run twisted
-            # Addendum: this seems to need quite some twisted insight and coding.
-            # A pointer i got on #twisted: divmod's vertex.sslverify
-            # If you really need this, feel free to implement and test it and
-            # submit a patch if it works.
-        else:
-            env = request.env
-            if env.get('SSL_CLIENT_VERIFY', 'FAILURE') == 'SUCCESS':
-
-                # check authority list if given
-                if self.authorities and env.get('SSL_CLIENT_I_DN_OU') in self.authorities:
-                    return user_obj, True
 
-                email_lower = None
-                if self.email_key:
-                    email = env.get('SSL_CLIENT_S_DN_Email', '').decode(config.charset)
-                    email_lower = email.lower()
-                commonname_lower = None
-                if self.name_key:
-                    commonname = env.get('SSL_CLIENT_S_DN_CN', '').decode(config.charset)
-                    commonname_lower = commonname.lower()
-                if email_lower or commonname_lower:
-                    for uid in user.getUserList(request):
-                        u = user.User(request, uid,
-                                      auth_method=self.name, auth_attribs=())
-                        if self.email_key and email_lower and u.email.lower() == email_lower:
-                            u.auth_attribs = ('email', 'password')
-                            if self.use_name and commonname_lower != u.name.lower():
-                                u.name = commonname
-                                changed = True
-                                u.auth_attribs = ('email', 'name', 'password')
-                            break
-                        if self.name_key and commonname_lower and u.name.lower() == commonname_lower:
-                            u.auth_attribs = ('name', 'password')
-                            if self.use_email and email_lower != u.email.lower():
-                                u.email = email
-                                changed = True
-                                u.auth_attribs = ('name', 'email', 'password')
-                            break
-                    else:
-                        u = None
-                    if u is None:
-                        # user wasn't found, so let's create a new user object
-                        u = user.User(request, name=commonname_lower, auth_username=commonname_lower,
-                                      auth_method=self.name)
+        env = request.environ
+        if env.get('SSL_CLIENT_VERIFY', 'FAILURE') == 'SUCCESS':
+
+            # check authority list if given
+            if self.authorities and env.get('SSL_CLIENT_I_DN_OU') in self.authorities:
+                return user_obj, True
+
+            email_lower = None
+            if self.email_key:
+                email = env.get('SSL_CLIENT_S_DN_Email', '').decode(config.charset)
+                email_lower = email.lower()
+            commonname_lower = None
+            if self.name_key:
+                commonname = env.get('SSL_CLIENT_S_DN_CN', '').decode(config.charset)
+                commonname_lower = commonname.lower()
+            if email_lower or commonname_lower:
+                for uid in user.getUserList(request):
+                    u = user.User(request, uid,
+                                  auth_method=self.name, auth_attribs=())
+                    if self.email_key and email_lower and u.email.lower() == email_lower:
+                        u.auth_attribs = ('email', 'password')
+                        if self.use_name and commonname_lower != u.name.lower():
+                            u.name = commonname
+                            changed = True
+                            u.auth_attribs = ('email', 'name', 'password')
+                        break
+                    if self.name_key and commonname_lower and u.name.lower() == commonname_lower:
                         u.auth_attribs = ('name', 'password')
-                        if self.use_email:
+                        if self.use_email and email_lower != u.email.lower():
                             u.email = email
+                            changed = True
                             u.auth_attribs = ('name', 'email', 'password')
-            elif user_obj and user_obj.auth_method == self.name:
-                user_obj.valid = False
-                return user_obj, False
+                        break
+                else:
+                    u = None
+                if u is None:
+                    # user wasn't found, so let's create a new user object
+                    u = user.User(request, name=commonname_lower, auth_username=commonname_lower,
+                                  auth_method=self.name)
+                    u.auth_attribs = ('name', 'password')
+                    if self.use_email:
+                        u.email = email
+                        u.auth_attribs = ('name', 'email', 'password')
+        elif user_obj and user_obj.auth_method == self.name:
+            user_obj.valid = False
+            return user_obj, False
         if u and self.autocreate:
             u.create_or_update(changed)
         if u and u.valid:
--- a/MoinMoin/config/multiconfig.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/config/multiconfig.py	Tue Feb 10 13:21:59 2009 +0100
@@ -16,13 +16,15 @@
 from MoinMoin import log
 logging = log.getLogger(__name__)
 
-from MoinMoin import config, error, util, wikiutil
+from MoinMoin import config, error, util, wikiutil, web
 from MoinMoin.auth import MoinAuth
+import MoinMoin.auth as authmodule
 import MoinMoin.events as events
 from MoinMoin.events import PageChangedEvent, PageRenamedEvent
 from MoinMoin.events import PageDeletedEvent, PageCopiedEvent
 from MoinMoin.events import PageRevertedEvent, FileAttachedEvent
 from MoinMoin import session
+import MoinMoin.web.session
 from MoinMoin.packages import packLine
 from MoinMoin.security import AccessControlList
 from MoinMoin.support.python_compatibility import set
@@ -249,6 +251,11 @@
             name = dirname + '_dir'
             if not getattr(self, name, None):
                 setattr(self, name, os.path.abspath(os.path.join(data_dir, dirname)))
+        # directories below cache_dir (using __dirname__ to avoid conflicts)
+        for dirname in ('session', ):
+            name = dirname + '_dir'
+            if not getattr(self, name, None):
+                setattr(self, name, os.path.abspath(os.path.join(self.cache_dir, '__%s__' % dirname)))
 
         # Try to decode certain names which allow unicode
         self._decode()
@@ -317,6 +324,7 @@
                 if not input in self.auth_login_inputs:
                     self.auth_login_inputs.append(input)
         self.auth_have_login = len(self.auth_login_inputs) > 0
+        self.auth_methods = found_names
 
         # internal dict for plugin `modules' lists
         self._site_plugin_lists = {}
@@ -693,6 +701,8 @@
      "See HelpOnSessions."),
     ('session_id_handler', DefaultExpression('session.MoinCookieSessionIDHandler()'),
      "Only used by the DefaultSessionHandler, see HelpOnSessions."),
+    ('session_service', DefaultExpression('web.session.FileSessionService()'),
+     "New session service (used by the new WSGI layer)"),
     ('cookie_secure', None,
      'Use secure cookie. (None = auto-enable secure cookie for https, True = ever use secure cookie, False = never use secure cookie).'),
     ('cookie_domain', None,
@@ -710,7 +720,7 @@
      "List of trusted user names with wiki system administration super powers (not to be confused with ACL admin rights!). Used for e.g. software installation, language installation via SystemPagesSetup and more. See also HelpOnSuperUser."),
     ('auth', DefaultExpression('[MoinAuth()]'),
      "list of auth objects, to be called in this order (see HelpOnAuthentication)"),
-    ('auth_methods_trusted', ['http', 'xmlrpc_applytoken'],
+    ('auth_methods_trusted', ['http', 'given', 'xmlrpc_applytoken'], # Note: 'http' auth method is currently just a redirect to 'given'
      'authentication methods for which users should be included in the special "Trusted" ACL group.'),
     ('secrets', None, """Either a long shared secret string used for multiple purposes or a dict {"purpose": "longsecretstring", ...} for setting up different shared secrets for different purposes. If you don't setup own secret(s), a secret string will be auto-generated from other config settings."""),
     ('DesktopEdition',
@@ -893,6 +903,7 @@
     ('data_dir', './data/', "Path to the data directory containing your (locally made) wiki pages."),
     ('data_underlay_dir', './underlay/', "Path to the underlay directory containing distribution system and help pages."),
     ('cache_dir', None, "Directory for caching, by default computed from `data_dir`/cache."),
+    ('session_dir', None, "Directory for session storage, by default computed to be `cache_dir`/__session__."),
     ('user_dir', None, "Directory for user storage, by default computed to be `data_dir`/user."),
     ('plugin_dir', None, "Plugin directory, by default computed to be `data_dir`/plugin."),
     ('plugin_dirs', [], "Additional plugin directories."),
--- a/MoinMoin/conftest.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/conftest.py	Tue Feb 10 13:21:59 2009 +0100
@@ -30,6 +30,8 @@
 sys.path.insert(0, str(moindir))
 
 from MoinMoin.support.python_compatibility import set
+from MoinMoin.web.request import TestRequest, Client
+from MoinMoin.wsgiapp import Application, init
 from MoinMoin._tests import maketestwiki, wikiconfig
 
 coverage_modules = set()
@@ -55,7 +57,6 @@
         coverage.erase()
         coverage.start()
 
-
     py.test.config.addoptions('MoinMoin options', py.test.config.Option('-C',
         '--coverage', action='callback', callback=callback,
         help='Output information about code coverage (slow!)'))
@@ -65,17 +66,12 @@
 
 
 def init_test_request(given_config=None, static_state=[False]):
-    from MoinMoin.request import request_cli
-    from MoinMoin.user import User
-    from MoinMoin.formatter.text_html import Formatter as HtmlFormatter
     if not static_state[0]:
         maketestwiki.run(True)
         static_state[0] = True
-    request = request_cli.Request(given_config=given_config)
-    request.form = request.args = request.setup_args()
-    request.user = User(request)
-    request.html_formatter = HtmlFormatter(request)
-    request.formatter = request.html_formatter
+    request = TestRequest()
+    request.given_config = given_config
+    request = init(request)
     return request
 
 
@@ -98,8 +94,12 @@
         cls = self.obj
         if hasattr(cls, 'Config'):
             cls.request = init_test_request(given_config=cls.Config)
+            cls.client = Client(Application(cls.Config))
         else:
             cls.request = self.parent.request
+            #XXX: this is the extremely messy way to configure the wsgi app
+            #     with the correct testing config
+            cls.client = Client(Application(self.parent.request.cfg.__class__))
         super(MoinClassCollector, self).setup()
 
 
--- a/MoinMoin/converter/_tests/test_text_html_text_moin_wiki.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/converter/_tests/test_text_html_text_moin_wiki.py	Tue Feb 10 13:21:59 2009 +0100
@@ -14,7 +14,7 @@
 from MoinMoin.converter import text_html_text_moin_wiki as converter
 from MoinMoin.parser.text_moin_wiki import Parser
 from MoinMoin.formatter.text_gedit import Formatter
-from MoinMoin.request import Clock
+from MoinMoin.util.clock import Clock
 from MoinMoin.error import ConvertError
 
 convert = converter.convert
--- a/MoinMoin/converter/text_html_text_moin_wiki.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/converter/text_html_text_moin_wiki.py	Tue Feb 10 13:21:59 2009 +0100
@@ -1205,7 +1205,7 @@
         href = attrs.pop('href', None)
         css_class = attrs.get('class')
 
-        scriptname = self.request.getScriptname()
+        scriptname = self.request.script_root
         if scriptname == "":
             scriptname = "/"
 
--- a/MoinMoin/events/emailnotify.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/events/emailnotify.py	Tue Feb 10 13:21:59 2009 +0100
@@ -136,7 +136,7 @@
     for lang in subscribers:
         recipients.extend(subscribers[lang])
 
-    attachlink = request.getBaseURL() + getAttachUrl(event.pagename, event.filename, request)
+    attachlink = request.url_root + getAttachUrl(event.pagename, event.filename, request)
     pagelink = request.getQualifiedURL(page.url(request, {}))
 
     for lang in subscribers:
--- a/MoinMoin/events/jabbernotify.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/events/jabbernotify.py	Tue Feb 10 13:21:59 2009 +0100
@@ -75,7 +75,7 @@
     for lang in subscribers:
         recipients.extend(subscribers[lang])
 
-    attachlink = request.getBaseURL() + getAttachUrl(event.pagename, event.filename, request)
+    attachlink = request.url_root + getAttachUrl(event.pagename, event.filename, request)
     pagelink = request.getQualifiedURL(page.url(request, {}))
 
     for lang in subscribers.keys():
--- a/MoinMoin/events/notification.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/events/notification.py	Tue Feb 10 13:21:59 2009 +0100
@@ -77,7 +77,7 @@
         'The "%(pagename)s" page has been changed by %(editor)s:\n') % {
             'pagename': page.page_name,
             'editor': page.uid_override or user.getUserIdentification(request),
-            'sitename': page.cfg.sitename or request.getBaseURL(),
+            'sitename': page.cfg.sitename or request.url_root,
         }
 
         # append a diff (or append full page text if there is no diff)
@@ -97,7 +97,7 @@
             'The page "%(pagename)s" has been deleted by %(editor)s:\n\n') % {
                 'pagename': page.page_name,
                 'editor': page.uid_override or user.getUserIdentification(request),
-                'sitename': page.cfg.sitename or request.getBaseURL(),
+                'sitename': page.cfg.sitename or request.url_root,
         }
 
     elif msgtype == "page_renamed":
@@ -106,7 +106,7 @@
             'The page "%(pagename)s" has been renamed from "%(oldname)s" by %(editor)s:\n') % {
                 'editor': page.uid_override or user.getUserIdentification(request),
                 'pagename': page.page_name,
-                'sitename': page.cfg.sitename or request.getBaseURL(),
+                'sitename': page.cfg.sitename or request.url_root,
                 'oldname': kwargs['old_name']
         }
 
@@ -149,7 +149,7 @@
 
     data['subject'] = _("New attachment added to page %(pagename)s on %(sitename)s") % {
                 'pagename': page_name,
-                'sitename': request.cfg.sitename or request.getBaseURL(),
+                'sitename': request.cfg.sitename or request.url_root,
                 }
 
     data['text'] = _("Dear Wiki user,\n\n"
--- a/MoinMoin/failure.py	Tue Feb 10 13:08:03 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,208 +0,0 @@
-# -*- coding: iso-8859-1 -*-
-""" MoinMoin failure
-
-    Handle fatal errors by showing a message and debugging information.
-
-    @copyright: 2004-2005 Nir Soffer <nirs@freeshell.org>
-    @license: GNU GPL, see COPYING for details.
-"""
-import sys, os
-import traceback
-
-from MoinMoin import log
-logging = log.getLogger(__name__)
-
-from MoinMoin.support import cgitb
-from MoinMoin.error import ConfigurationError
-
-
-class View(cgitb.View):
-    """ Display an error message and debugging information
-
-    Additions to cgitb.View:
-     - Multiple tracebacks support
-     - Debugging information is shown only in debug mode
-     - Moin application information
-     - General help text and links
-     - Handle multiple paragraphs in exception message
-
-    cgitb is heavily modified cgitb, but fully backward compatible with
-    the standard cgitb. It should not contain any moin specific code.
-
-    cgitb was refactored to be easy to customize by applications
-    developers. This moin specific subclass is an example.
-    """
-    debugInfoID = 'debug-info'
-
-    def formatContent(self):
-        content = (
-            self.script(),
-            self.formatStylesheet(),
-            self.formatTitle(),
-            self.formatMessage(),
-            self.formatButtons(),
-            self.formatDebugInfo(),
-            self.formatTextTraceback()
-            )
-        return ''.join(content)
-
-    def script(self):
-        return '''
-<script type="text/javascript">
-function toggleDebugInfo() {
-    var tb = document.getElementById('%s');
-    if (tb == null) return;
-    tb.style.display = tb.style.display ? '' : 'none';
-}
-</script>
-''' % self.debugInfoID
-
-    def stylesheet(self):
-        return cgitb.View.stylesheet(self) + """
-.cgitb .buttons {margin: 0.5em 0; padding: 5px 10px;}
-.cgitb .buttons li {display: inline; margin: 0; padding: 0 0.25em;}
-"""
-
-    def formatMessage(self):
-        """ handle multiple paragraphs messages and add general help """
-        f = self.formatter
-        text = [self.formatExceptionMessage(self.info)]
-
-        if self.info[0] == ConfigurationError:
-            tbt = traceback.extract_tb(self.info[1].exceptions()[-1][2])[-1]
-            text.append(
-                f.paragraph('Error in your configuration file "%s"'
-                            ' around line %d.' % tbt[:2]))
-        else:
-            text.append(
-                f.paragraph("If you want to report a bug, please save "
-                            "this page and  attach it to your bug report."))
-        return ''.join(text)
-
-    def formatButtons(self):
-        """ Add 'buttons' to the error dialog """
-        f = self.formatter
-        buttons = [f.link('javascript:toggleDebugInfo()',
-                          'Show debugging information')]
-        if self.info[0] != ConfigurationError:
-            buttons.append(
-                   f.link('http://moinmo.in/MoinMoinBugs',
-                          'Report bug'))
-            buttons.append(
-                   f.link('http://moinmo.in/FrontPage',
-                          'Visit MoinMoin wiki'))
-        return f.list(buttons, {'class': 'buttons'})
-
-    def formatDebugInfo(self):
-        """ Put debugging information in a hidden div """
-        attributes = {'id': self.debugInfoID}
-        info = [self.debugInfoHideScript(),
-                self.formatTraceback(),
-                self.formatSystemDetails(), ]
-        return self.formatter.section(''.join(info), attributes)
-
-    def debugInfoHideScript(self):
-        """ Hide debug info for javascript enabled browsers """
-        if self.debug:
-            return ''
-        return '''
-<script type="text/javascript">toggleDebugInfo()</script>
-'''
-
-    def formatTraceback(self):
-        return self.formatAllTracebacks(self.formatOneTraceback)
-
-    def formatTextTraceback(self):
-        template = self.textTracebackTemplate()
-        return template % self.formatAllTracebacks(self.formatOneTextTraceback)
-
-    def formatAllTracebacks(self, formatFuction):
-        """ Format multiple tracebacks using formatFunction """
-        tracebacks = []
-        for ttype, tvalue, tb in self.exceptions():
-            if ttype is None:
-                break
-            tracebacks.append(formatFuction((ttype, tvalue, tb)))
-            del tb
-        return ''.join(tracebacks)
-
-    def exceptions(self):
-        """ Return a list of exceptions info, starting at self.info """
-        try:
-            return [self.info] + self.info[1].exceptions()
-        except AttributeError:
-            return [self.info]
-
-    def applicationDetails(self):
-        """ Add MoinMoin details to system details """
-        from MoinMoin import version
-        return ['MoinMoin: Release %s (%s)' % (version.release,
-                                              version.revision)]
-
-    def formatExceptionMessage(self, info):
-        """ Handle multiple paragraphs in exception message """
-        text = cgitb.View.exceptionMessage(self, info)
-        text = text.split('\n\n')
-        text = ''.join([self.formatter.paragraph(item) for item in text])
-        return text
-
-
-def handle(request, err):
-    """ Handle failures
-
-    Display fancy error view, or fallback to simple text traceback
-    """
-    if 'MOIN_DEBUG' in os.environ:
-        raise err
-
-    savedError = sys.exc_info()
-    logging.exception('An exception occurred, URI was "%s".' % request.request_uri)
-
-    try:
-        display = request.cfg.traceback_show # might fail if we have no cfg yet
-    except:
-        # default to True here to allow an admin setting up the wiki
-        # to see the errors made in the configuration file
-        display = True
-
-    try:
-        debug = 'debug' in request.form
-    except:
-        debug = False
-
-    try:
-        # try to output a nice html error page
-        handler = cgitb.Hook(file=request, display=display, viewClass=View, debug=debug)
-        handler.handle(savedError)
-    except:
-        # if that fails, log the cgitb problem ...
-        logging.exception('cgitb raised this exception')
-        # ... and try again with a simpler output method:
-        request.write('<pre>\n')
-        printTextException(request, savedError, display)
-        request.write('\nAdditionally cgitb raised this exception:\n')
-        printTextException(request, display=display)
-        request.write('</pre>\n')
-
-
-
-def printTextException(request, info=None, display=True):
-    """ Simple text exception that should never fail
-
-    Print all exceptions in a composite error.
-    """
-    if not display:
-        request.write("(Traceback display forbidden by configuration)\n")
-        return
-    from MoinMoin import wikiutil
-    if info is None:
-        info = sys.exc_info()
-    try:
-        exceptions = [info] + info[1].exceptions()
-    except AttributeError:
-        exceptions = [info]
-    for info in exceptions:
-        text = ''.join(traceback.format_exception(*info))
-        text = wikiutil.escape(text)
-        request.write(text)
-
--- a/MoinMoin/formatter/__init__.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/formatter/__init__.py	Tue Feb 10 13:21:59 2009 +0100
@@ -74,12 +74,12 @@
 
     def startContent(self, content_id="content", **kw):
         if self.page:
-            self.request.begin_include(self.page.page_name)
+            self.request.uid_generator.begin(self.page.page_name)
         return ""
 
     def endContent(self):
         if self.page:
-            self.request.end_include()
+            self.request.uid_generator.end()
         return ""
 
     # Links ##############################################################
@@ -93,7 +93,7 @@
             return ''
         if not pagename and page:
             pagename = page.page_name
-        pagename = self.request.normalizePagename(pagename)
+        pagename = wikiutil.normalize_pagename(pagename, self.request.cfg)
         if pagename and pagename not in self.pagelinks:
             self.pagelinks.append(pagename)
 
@@ -407,11 +407,11 @@
         '''
         Take an ID and make it unique in the current namespace.
         '''
-        ns = self.request.include_id
+        ns = self.request.uid_generator.include_id
         if not ns is None:
             ns = self.sanitize_to_id(ns)
         id = self.sanitize_to_id(id)
-        id = self.request.make_unique_id(id, ns)
+        id = self.request.uid_generator(id, ns)
         return id
 
     def qualify_id(self, id):
@@ -421,7 +421,7 @@
         is suitable if the dot ('.') is valid in IDs for your
         formatter.
         '''
-        ns = self.request.include_id
+        ns = self.request.uid_generator.include_id
         if not ns is None:
             ns = self.sanitize_to_id(ns)
             return '%s.%s' % (ns, id)
--- a/MoinMoin/formatter/text_docbook.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/formatter/text_docbook.py	Tue Feb 10 13:21:59 2009 +0100
@@ -364,7 +364,7 @@
     def url(self, on, url=None, css=None, **kw):
         if url and url.startswith("/"):
             # convert to absolute path:
-            url = "%s%s"%(self.request.getBaseURL(), url)
+            url = "%s%s"%(self.request.base_url, url)
 
         if not on:
             self._cleanupUlinkNode()
@@ -457,7 +457,7 @@
             src = kw['src']
             if src.startswith("/"):
                 # convert to absolute path:
-                src = self.request.getBaseURL()+src
+                src = self.request.url_root + src
             image.setAttribute('fileref', src)
         if kw.has_key('width'):
             image.setAttribute('width', str(kw['width']))
--- a/MoinMoin/formatter/text_html.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/formatter/text_html.py	Tue Feb 10 13:21:59 2009 +0100
@@ -410,7 +410,7 @@
         """
 
         if hasattr(self, 'page'):
-            self.request.begin_include(self.page.page_name)
+            self.request.uid_generator.begin(self.page.page_name)
 
         result = []
         # Use the content language
@@ -434,7 +434,7 @@
         result.append(self.anchordef('bottom'))
         result.append(self._close('div', newline=newline))
         if hasattr(self, 'page'):
-            self.request.end_include()
+            self.request.uid_generator.end()
         return ''.join(result)
 
     def lang(self, on, lang_name):
@@ -655,35 +655,25 @@
     def attachment_drawing(self, url, text, **kw):
         # XXX text arg is unused!
         _ = self.request.getText
-        pagename, filename = AttachFile.absoluteName(url, self.page.page_name)
-        fname = wikiutil.taintfilename(filename)
-        drawing = fname
-        fname = fname + u".png"
-        filename = filename + u".png"
-        # fallback for old gif drawings (1.1 -> 1.2)
-        exists = AttachFile.exists(self.request, pagename, fname)
-        if not exists:
-            gfname = fname[:-4] + u".gif"
-            gfilename = filename[:-4] + u".gif"
-            exists = AttachFile.exists(self.request, pagename, gfname)
-            if exists:
-                fname, filename = gfname, gfilename
+        pagename, drawing = AttachFile.absoluteName(url, self.page.page_name)
+        containername = wikiutil.taintfilename(drawing) + ".tdraw"
 
-        # check whether attachment exists, possibly point to upload form
-        drawing_url = AttachFile.getAttachUrl(pagename, fname, self.request, drawing=drawing, upload=True)
-        if not exists:
-            title = _('Create new drawing "%(filename)s (opens in new window)"') % {'filename': fname}
+        drawing_url = AttachFile.getAttachUrl(pagename, containername, self.request, drawing=drawing, upload=True)
+        ci = AttachFile.ContainerItem(self.request, pagename, containername)
+        if not ci.exists():
+            title = _('Create new drawing "%(filename)s (opens in new window)"') % {'filename': drawing}
             img = self.icon('attachimg')  # TODO: we need a new "drawimg" in similar grey style and size
             css = 'nonexistent'
             return self.url(1, drawing_url, css=css, title=title) + img + self.url(0)
 
-        title = _('Edit drawing %(filename)s (opens in new window)') % {'filename': self.text(fname)}
-        kw['src'] = AttachFile.getAttachUrl(pagename, filename, self.request, addts=1)
+        title = _('Edit drawing %(filename)s (opens in new window)') % {'filename': self.text(drawing)}
+        kw['src'] = src = ci.member_url(drawing + u'.png')
         kw['css'] = 'drawing'
 
-        mappath = AttachFile.getFilename(self.request, pagename, drawing + u'.map')
+        mapfile = ci.get(drawing + u'.map')
         try:
-            map = file(mappath, 'r').read()
+            map = mapfile.read()
+            mapfile.close()
         except (IOError, OSError):
             map = ''
         if map:
@@ -691,11 +681,11 @@
             mapid = 'ImageMapOf' + drawing
             map = map.replace('%MAPNAME%', mapid)
             # add alt and title tags to areas
-            map = re.sub('href\s*=\s*"((?!%TWIKIDRAW%).+?)"', r'href="\1" alt="\1" title="\1"', map)
+            map = re.sub(r'href\s*=\s*"((?!%TWIKIDRAW%).+?)"', r'href="\1" alt="\1" title="\1"', map)
             map = map.replace('%TWIKIDRAW%"', '%s" alt="%s" title="%s"' % (drawing_url, title, title))
             # unxml, because 4.01 concrete will not validate />
             map = map.replace('/>', '>')
-            title = _('Clickable drawing: %(filename)s') % {'filename': self.text(fname)}
+            title = _('Clickable drawing: %(filename)s') % {'filename': self.text(drawing)}
             if 'title' not in kw:
                 kw['title'] = title
             if 'alt' not in kw:
--- a/MoinMoin/i18n/MoinMoin.pot	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/i18n/MoinMoin.pot	Tue Feb 10 13:21:59 2009 +0100
@@ -8,7 +8,7 @@
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2009-02-07 14:05+0100\n"
+"POT-Creation-Date: 2008-09-12 23:35+0200\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -473,9 +473,6 @@
 msgid "about"
 msgstr ""
 
-msgid "anonymous"
-msgstr ""
-
 msgid "Language"
 msgstr ""
 
@@ -2048,19 +2045,6 @@
 msgid "You need to be subscribed to unsubscribe."
 msgstr ""
 
-msgid "Password is too short."
-msgstr ""
-
-msgid "Password has not enough different characters."
-msgstr ""
-
-msgid ""
-"Password is too easy (password contains name or name contains password)."
-msgstr ""
-
-msgid "Password is too easy (keyboard sequence)."
-msgstr ""
-
 msgid "Diffs"
 msgstr ""
 
--- a/MoinMoin/i18n/__init__.py	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/i18n/__init__.py	Tue Feb 10 13:21:59 2009 +0100
@@ -362,15 +362,12 @@
     the request, normalizing to lower case.
     """
     fallback = []
-    accepted = request.http_accept_language
+    accepted = request.accept_languages
     if accepted:
-        # Extract the languages names from the string
-        accepted = accepted.split(',')
-        accepted = [lang.split(';')[0] for lang in accepted]
         # Add base language for each sub language. If the user specified
         # a sub language like "en-us", we will try to to provide it or
         # a least the base language "en" in this case.
-        for lang in accepted:
+        for lang, quality in accepted:
             lang = lang.lower()
             fallback.append(lang)
             if '-' in lang:
--- a/MoinMoin/i18n/ar.MoinMoin.po	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/i18n/ar.MoinMoin.po	Tue Feb 10 13:21:59 2009 +0100
@@ -13,7 +13,7 @@
 msgstr ""
 "Project-Id-Version: moin 1.6\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2009-01-24 04:45+0100\n"
+"POT-Creation-Date: 2008-09-12 23:35+0200\n"
 "PO-Revision-Date: 2008-04-12 20:07+0200\n"
 "Last-Translator: Mohamed Yahya <yahya.mohamed@gmail.com>\n"
 "Language-Team: \n"
@@ -26,33 +26,6 @@
 "X-HasWikiMarkup: True\n"
 
 #, python-format
-msgid "Invalid highlighting regular expression \"%(regex)s\": %(error)s"
-msgstr ""
-
-msgid ""
-"The backed up content of this page is deprecated and will not be included in "
-"search results!"
-msgstr ""
-
-#, python-format
-msgid "Revision %(rev)d as of %(date)s"
-msgstr ""
-
-#, python-format
-msgid "Redirected from page \"%(page)s\""
-msgstr ""
-
-#, python-format
-msgid "This page redirects to page \"%(page)s\""
-msgstr ""
-
-msgid "Create New Page"
-msgstr "اخلق صفحة وجديدة"
-
-msgid "You are not allowed to view this page."
-msgstr "لا يسمح لك بنظر هذه الصفحة."
-
-#, python-format
 msgid "Argument \"%s\" must be a boolean value, not \"%s\""
 msgstr ""
 
@@ -114,6 +87,9 @@
 msgid "Expected a value for key \"%(token)s\""
 msgstr "تتوقع قيمة للمفتاح \"%(token)s\""
 
+msgid "Your changes are not saved!"
+msgstr "لم يتم حفظ تغييراتك!"
+
 msgid "You are not allowed to edit this page."
 msgstr "لا يسمح لك بتحرير هذه الصفحة"
 
@@ -126,6 +102,9 @@
 msgid "The lock you held timed out. Be prepared for editing conflicts!"
 msgstr ""
 
+msgid "Page name is too long, try shorter name."
+msgstr "إسم الصفحة طويل، جرب إسما أقصر."
+
 #, fuzzy, python-format
 msgid "Draft of \"%(pagename)s\""
 msgstr "تحرير \"%(pagename)s\""
@@ -209,9 +188,8 @@
 msgid "Preview"
 msgstr "معاينة"
 
-#, fuzzy
-msgid "Text mode"
-msgstr "نص عادي"
+msgid "GUI Mode"
+msgstr "وضعية واجهة المستخدم الرسومية"
 
 #, fuzzy
 msgid "Load Draft"
@@ -233,75 +211,6 @@
 msgid "Remove trailing whitespace from each line"
 msgstr "أزل الفراغ الأبيض في نهاية كل سطر."
 
-#, python-format
-msgid "The package needs a newer version of MoinMoin (at least %s)."
-msgstr ""
-
-msgid "The theme name is not set."
-msgstr ""
-
-msgid "Installing theme files is only supported for standalone type servers."
-msgstr ""
-
-#, python-format
-msgid "Installation of '%(filename)s' failed."
-msgstr ""
-
-#, python-format
-msgid "The file %s is not a MoinMoin package file."
-msgstr ""
-
-#, python-format
-msgid "The page %s does not exist."
-msgstr "الصفحة %s غير موجودة."
-
-msgid "Invalid package file header."
-msgstr ""
-
-msgid "Package file format unsupported."
-msgstr ""
-
-#, python-format
-msgid "Unknown function %(func)s in line %(lineno)i."
-msgstr ""
-
-#, python-format
-msgid "The file %s was not found in the package."
-msgstr ""
-
-msgid "<unknown>"
-msgstr "<مغمور>"
-
-#, python-format
-msgid ""
-"Login Name: %s\n"
-"\n"
-"Password recovery token: %s\n"
-"\n"
-"Password reset URL: %s/?action=recoverpass&name=%s&token=%s\n"
-msgstr ""
-
-msgid ""
-"Somebody has requested to email you a password recovery token.\n"
-"\n"
-"If you lost your password, please go to the password reset URL below or\n"
-"go to the password recovery page again and enter your username and the\n"
-"recovery token.\n"
-msgstr ""
-
-#, python-format
-msgid "[%(sitename)s] Your wiki account data"
-msgstr ""
-
-msgid "Your changes are not saved!"
-msgstr "لم يتم حفظ تغييراتك!"
-
-msgid "Page name is too long, try shorter name."
-msgstr "إسم الصفحة طويل، جرب إسما أقصر."
-
-msgid "GUI Mode"
-msgstr "وضعية واجهة المستخدم الرسومية"
-
 #, fuzzy
 msgid "Edit was cancelled."
 msgstr "تم إلغاء التحرير."
@@ -429,6 +338,36 @@
 "To leave the editor, press the Cancel button."
 msgstr ""
 
+msgid "<unknown>"
+msgstr "<مغمور>"
+
+#, python-format
+msgid "Invalid highlighting regular expression \"%(regex)s\": %(error)s"
+msgstr ""
+
+msgid ""
+"The backed up content of this page is deprecated and will not be included in "
+"search results!"
+msgstr ""
+
+#, python-format
+msgid "Revision %(rev)d as of %(date)s"
+msgstr ""
+
+#, python-format
+msgid "Redirected from page \"%(page)s\""
+msgstr ""
+
+#, python-format
+msgid "This page redirects to page \"%(page)s\""
+msgstr ""
+
+msgid "Create New Page"
+msgstr "اخلق صفحة وجديدة"
+
+msgid "You are not allowed to view this page."
+msgstr "لا يسمح لك بنظر هذه الصفحة."
+
 msgid "The wiki is currently not reachable."
 msgstr "لا يمكن الوصول إلى هذه الويكي حاليا."
 
@@ -441,6 +380,84 @@
 "than you specified (%(localname)s)."
 msgstr ""
 
+#, fuzzy
+msgid "Text mode"
+msgstr "نص عادي"
+
+#, python-format
+msgid "The package needs a newer version of MoinMoin (at least %s)."
+msgstr ""
+
+msgid "The theme name is not set."
+msgstr ""
+
+msgid "Installing theme files is only supported for standalone type servers."
+msgstr ""
+
+#, python-format
+msgid "Installation of '%(filename)s' failed."
+msgstr ""
+
+#, python-format
+msgid "The file %s is not a MoinMoin package file."
+msgstr ""
+
+#, python-format
+msgid "The page %s does not exist."
+msgstr "الصفحة %s غير موجودة."
+
+msgid "Invalid package file header."
+msgstr ""
+
+msgid "Package file format unsupported."
+msgstr ""
+
+#, python-format
+msgid "Unknown function %(func)s in line %(lineno)i."
+msgstr ""
+
+#, python-format
+msgid "The file %s was not found in the package."
+msgstr ""
+
+#, python-format
+msgid ""
+"Login Name: %s\n"
+"\n"
+"Password recovery token: %s\n"
+"\n"
+"Password reset URL: %s/?action=recoverpass&name=%s&token=%s\n"
+msgstr ""
+
+msgid ""
+"Somebody has requested to email you a password recovery token.\n"
+"\n"
+"If you lost your password, please go to the password reset URL below or\n"
+"go to the password recovery page again and enter your username and the\n"
+"recovery token.\n"
+msgstr ""
+
+#, python-format
+msgid "[%(sitename)s] Your wiki account data"
+msgstr ""
+
+msgid "Line"
+msgstr "سطر"
+
+msgid "No differences found!"
+msgstr "لا توجد الاختلافات!"
+
+msgid "Deletions are marked like this."
+msgstr ""
+
+msgid "Additions are marked like this."
+msgstr ""
+
+#, python-format
+msgid ""
+"Sorry, can not save page because \"%(content)s\" is not allowed in this wiki."
+msgstr ""
+
 #, python-format
 msgid ""
 "Results %(bs)s%(hitsFrom)d - %(hitsTo)d%(be)s of %(aboutHits)s %(bs)s%(hits)d"
@@ -481,43 +498,368 @@
 msgid "about"
 msgstr ""
 
-msgid "[all]"
-msgstr ""
-
-msgid "[not empty]"
-msgstr ""
-
-msgid "[empty]"
-msgstr ""
-
-msgid "filter"
-msgstr "مرشح"
+msgid "Language"
+msgstr "لغة"
+
+msgid "<Browser setting>"
+msgstr "<إعدادات المتصفح>"
+
+msgid "Others"
+msgstr ""
+
+msgid "Date"
+msgstr "التاريخ"
+
+msgid "Views/day"
+msgstr ""
+
+msgid "Edits/day"
+msgstr ""
+
+msgid "Page hits and edits"
+msgstr ""
+
+#, python-format
+msgid "%(chart_title)s for %(filterpage)s"
+msgstr ""
+
+msgid ""
+"green=view\n"
+"red=edit"
+msgstr ""
+
+msgid "date"
+msgstr "التاريخ"
+
+msgid "# of hits"
+msgstr ""
+
+msgid "Charts are not available!"
+msgstr ""
+
+msgid "Page Size Distribution"
+msgstr ""
+
+msgid "page size upper bound [bytes]"
+msgstr ""
+
+msgid "# of pages of this size"
+msgstr ""
+
+msgid "User agent"
+msgstr ""
+
+msgid "Distribution of User-Agent Types"
+msgstr ""
+
+msgid "Could not contact botbouncer.com."
+msgstr ""
+
+msgid "Failed to connect to database."
+msgstr "فشلت محاولة الإتصال بقاعدة البيانات."
+
+msgid "Missing password. Please enter user name and password."
+msgstr "لا يوجد كلمة سر. الرجاء إدخال إسم مستخدم و كلمة سر"
+
+#, python-format
+msgid ""
+"If you do not have an account, <a href=\"%(userprefslink)s\">you can create "
+"one now</a>. <a href=\"%(sendmypasswordlink)s\">Forgot your password?</a>"
+msgstr ""
 
 #, fuzzy
-msgid "Change password"
-msgstr "كلمةالسرّ"
-
-msgid "Passwords don't match!"
-msgstr "كلمات السر غير متطابقة!"
-
-msgid "Please specify a password!"
-msgstr "الرجاء إدخال كلمة سر!"
+msgid "You need to log in."
+msgstr "لقد قمت بتسجيل الخروج."
 
 #, python-format
-msgid "Password not acceptable: %s"
-msgstr "كلمة السر غير مقبولة: %s"
-
-msgid "Your password has been changed."
-msgstr "تم تغيير كلمة السر الخاصة بك."
-
-msgid "To change your password, enter a new password twice."
-msgstr "لتغيير كلمة السر الخاصة بك، أدخل كلمة سر جديدة مرتين."
+msgid "LDAP server %(server)s failed."
+msgstr ""
+
+msgid ""
+"Please choose an account name now.\n"
+"If you choose an existing account name you will be asked for the\n"
+"password and be able to associate the account with your OpenID."
+msgstr ""
+
+msgid "Name"
+msgstr "اسم"
+
+msgid "Choose this name"
+msgstr "إختر هذا الإسم"
+
+msgid "This is not a valid username, choose a different one."
+msgstr ""
+
+msgid ""
+"The username you have chosen is already\n"
+"taken. If it is your username, enter your password below to associate\n"
+"the username with your OpenID. Otherwise, please choose a different\n"
+"username and leave the password field blank."
+msgstr ""
 
 msgid "Password"
 msgstr "كلمةالسرّ"
 
-msgid "Password repeat"
-msgstr "اعادة كلمة السر"
+msgid "Associate this name"
+msgstr ""
+
+#, python-format
+msgid "OpenID error: %s."
+msgstr ""
+
+#, fuzzy
+msgid "Verification canceled."
+msgstr "تم إلغاء العملية."
+
+msgid "OpenID failure."
+msgstr ""
+
+msgid "Your account is now associated to your OpenID."
+msgstr ""
+
+msgid "The password you entered is not valid."
+msgstr "كلمة السر التي أدخلتها غير صالحة."
+
+msgid "OpenID verification requires that you click this button:"
+msgstr ""
+
+msgid "Anonymous sessions need to be enabled for OpenID login."
+msgstr ""
+
+msgid "Failed to resolve OpenID."
+msgstr ""
+
+msgid "OpenID discovery failure, not a valid OpenID."
+msgstr ""
+
+msgid "No OpenID."
+msgstr ""
+
+msgid ""
+"If you do not have an account yet, you can still log in with your OpenID and "
+"create one during login."
+msgstr ""
+
+msgid "Page has been modified"
+msgstr "تم تعديل الصفحة"
+
+msgid "Page has been modified in a trivial fashion"
+msgstr "تم تعديل الصفحة بشكل بسيط"
+
+msgid "Page has been renamed"
+msgstr "تم إعادة تسمية الصفحة"
+
+msgid "Page has been deleted"
+msgstr "تم حذف الصفحة"
+
+msgid "Page has been copied"
+msgstr "تم نسخ الصفحة"
+
+#, fuzzy
+msgid "A new attachment has been added"
+msgstr "المرفقات"
+
+msgid "A page has been reverted to a previous state"
+msgstr ""
+
+#, fuzzy
+msgid "A user has subscribed to a page"
+msgstr "لا يسمح لك بتحرير هذه الصفحة"
+
+msgid "A new account has been created"
+msgstr "تم إنشاء حساب جديد"
+
+#, python-format
+msgid "[%(sitename)s] %(trivial)sUpdate of \"%(pagename)s\" by %(username)s"
+msgstr ""
+
+msgid "Trivial "
+msgstr "بديهي"
+
+#, python-format
+msgid ""
+"Attachment link: %(attach)s\n"
+"Page link: %(page)s\n"
+msgstr ""
+
+#, python-format
+msgid ""
+"Dear Wiki user,\n"
+"\n"
+"You have subscribed to a wiki page or wiki category on \"%(sitename)s\" for "
+"change notification.\n"
+"\n"
+"The \"%(pagename)s\" page has been changed by %(editor)s:\n"
+msgstr ""
+
+msgid "New page:\n"
+msgstr "صفحة جديدة\n"
+
+msgid "No differences found!\n"
+msgstr "ْلا توجد اختلافات \n"
+
+#, python-format
+msgid ""
+"Dear wiki user,\n"
+"\n"
+"You have subscribed to a wiki page \"%(sitename)s\" for change "
+"notification.\n"
+"\n"
+"The page \"%(pagename)s\" has been deleted by %(editor)s:\n"
+"\n"
+msgstr ""
+
+#, python-format
+msgid ""
+"Dear wiki user,\n"
+"\n"
+"You have subscribed to a wiki page \"%(sitename)s\" for change "
+"notification.\n"
+"\n"
+"The page \"%(pagename)s\" has been renamed from \"%(oldname)s\" by %(editor)"
+"s:\n"
+msgstr ""
+
+#, python-format
+msgid "New user account created on %(sitename)s"
+msgstr ""
+
+#, python-format
+msgid ""
+"Dear Superuser, a new user has just been created on %(sitename)s\". Details "
+"follow:\n"
+"\n"
+"    User name: %(username)s\n"
+"    Email address: %(useremail)s"
+msgstr ""
+
+#, python-format
+msgid "New attachment added to page %(pagename)s on %(sitename)s"
+msgstr ""
+
+#, python-format
+msgid ""
+"Dear Wiki user,\n"
+"\n"
+"You have subscribed to a wiki page \"%(page_name)s\" for change "
+"notification. An attachment has been added to that page by %(editor)s. "
+"Following detailed information is available:\n"
+"\n"
+"Attachment name: %(attach_name)s\n"
+"Attachment size: %(attach_size)s\n"
+msgstr ""
+
+#, fuzzy
+msgid "Attachment link"
+msgstr "المرفقات"
+
+#, fuzzy
+msgid "Page link"
+msgstr "حجم الصفحة: %d"
+
+#, fuzzy
+msgid "Changed page"
+msgstr "صفحات مشابه"
+
+#, fuzzy
+msgid "Page changed"
+msgstr "إحفظ التغييرات"
+
+msgid ""
+" Emphasis:: <<Verbatim('')>>''italics''<<Verbatim('')>>; <<Verbatim(''')"
+">>'''bold'''<<Verbatim(''')>>; <<Verbatim(''''')>>'''''bold "
+"italics'''''<<Verbatim(''''')>>; <<Verbatim('')>>''mixed ''<<Verbatim(''')"
+">>'''''bold'''<<Verbatim(''')>> and italics''<<Verbatim('')>>; <<Verbatim"
+"(----)>> horizontal rule.\n"
+" Headings:: = Title 1 =; == Title 2 ==; === Title 3 ===; ==== Title 4 ====; "
+"===== Title 5 =====.\n"
+" Lists:: space and one of: * bullets; 1., a., A., i., I. numbered items; 1."
+"#n start numbering at n; space alone indents.\n"
+" Links:: <<Verbatim(JoinCapitalizedWords)>>; <<Verbatim([[target|linktext]])"
+">>.\n"
+" Tables:: || cell text |||| cell text spanning 2 columns ||;    no trailing "
+"white space allowed after tables or titles.\n"
+"\n"
+"(!) For more help, see HelpOnEditing or SyntaxReference.\n"
+msgstr ""
+
+#, python-format
+msgid "Expected \"%(wanted)s\" after \"%(key)s\", got \"%(token)s\""
+msgstr ""
+
+#, python-format
+msgid "Expected an integer \"%(key)s\" before \"%(token)s\""
+msgstr ""
+
+#, python-format
+msgid "Expected an integer \"%(arg)s\" after \"%(key)s\""
+msgstr ""
+
+#, python-format
+msgid "Expected a color value \"%(arg)s\" after \"%(key)s\""
+msgstr ""
+
+msgid "XSLT option disabled, please look at HelpOnConfiguration."
+msgstr ""
+
+msgid "XSLT processing is not available, please install 4suite 1.x."
+msgstr ""
+
+#, python-format
+msgid "%(errortype)s processing error"
+msgstr ""
+
+msgid ""
+"Rendering of reStructured text is not possible, please install Docutils."
+msgstr ""
+
+msgid ""
+"{{{\n"
+"Emphasis: *italic* **bold** ``monospace``\n"
+"\n"
+"Headings: Heading 1  Heading 2  Heading 3\n"
+"          =========  ---------  ~~~~~~~~~\n"
+"\n"
+"Horizontal rule: ----\n"
+"\n"
+"Links: TrailingUnderscore_ `multi word with backticks`_ external_\n"
+"\n"
+".. _external: http://external-site.example.org/foo/\n"
+"\n"
+"Lists: * bullets; 1., a. numbered items.\n"
+"}}}\n"
+"(!) For more help, see the\n"
+"[[http://docutils.sourceforge.net/docs/user/rst/quickref.html|"
+"reStructuredText Quick Reference]].\n"
+msgstr ""
+
+msgid "**Maximum number of allowed includes exceeded**"
+msgstr ""
+
+#, fuzzy, python-format
+msgid "**You are not allowed to read the page: %s**"
+msgstr "!لا يسمح لك بالعودة إلى هذه الصفحة"
+
+#, python-format
+msgid "**Could not find the referenced page: %s**"
+msgstr ""
+
+msgid ""
+" Emphasis:: <<Verbatim(//)>>''italics''<<Verbatim(//)>>; <<Verbatim(**)"
+">>'''bold'''<<Verbatim(**)>>; <<Verbatim(**//)>>'''''bold "
+"italics'''''<<Verbatim(//**)>>; <<Verbatim(//)>>''mixed ''<<Verbatim(**)"
+">>'''''bold'''<<Verbatim(**)>> and italics''<<Verbatim(//)>>;\n"
+" Horizontal Rule:: <<Verbatim(----)>>\n"
+" Force Linebreak:: <<Verbatim(\\\\)>>\n"
+" Headings:: = Title 1 =; == Title 2 ==; === Title 3 ===; ==== Title 4 ====; "
+"===== Title 5 =====.\n"
+" Lists:: * bullets; ** sub-bullets; # numbered items; ## numbered sub "
+"items.\n"
+" Links:: <<Verbatim([[target]])>>; <<Verbatim([[target|linktext]])>>.\n"
+" Tables:: |= header text | cell text | more cell text |;\n"
+"\n"
+"(!) For more help, see HelpOnEditing or HelpOnCreoleSyntax.\n"
+msgstr ""
 
 msgid "Preferences"
 msgstr "التفضيلات"
@@ -559,9 +901,6 @@
 msgid "Default"
 msgstr "إفتراضي"
 
-msgid "<Browser setting>"
-msgstr "<إعدادات المتصفح>"
-
 msgid "the one preferred"
 msgstr "المفضل"
 
@@ -604,6 +943,51 @@
 msgid "Quick links"
 msgstr "روابط سريعة"
 
+msgid "Switch user"
+msgstr ""
+
+msgid "No user selected"
+msgstr ""
+
+msgid ""
+"You can now change the settings of the selected user account; log out to get "
+"back to your account."
+msgstr ""
+
+msgid "You are the only user."
+msgstr "أنت المستخدم الوحيد."
+
+msgid ""
+"As a superuser, you can temporarily assume the identity of another user."
+msgstr ""
+
+#, fuzzy
+msgid "Select User"
+msgstr "إختر مستخدم"
+
+#, fuzzy
+msgid "Change password"
+msgstr "كلمةالسرّ"
+
+msgid "Passwords don't match!"
+msgstr "كلمات السر غير متطابقة!"
+
+msgid "Please specify a password!"
+msgstr "الرجاء إدخال كلمة سر!"
+
+#, python-format
+msgid "Password not acceptable: %s"
+msgstr "كلمة السر غير مقبولة: %s"
+
+msgid "Your password has been changed."
+msgstr "تم تغيير كلمة السر الخاصة بك."
+
+msgid "To change your password, enter a new password twice."
+msgstr "لتغيير كلمة السر الخاصة بك، أدخل كلمة سر جديدة مرتين."
+
+msgid "Password repeat"
+msgstr "اعادة كلمة السر"
+
 msgid "Notification"
 msgstr ""
 
@@ -635,28 +1019,6 @@
 msgid "Subscribed wiki pages<<BR>>(one regex per line)"
 msgstr ""
 
-msgid "Switch user"
-msgstr ""
-
-msgid "No user selected"
-msgstr ""
-
-msgid ""
-"You can now change the settings of the selected user account; log out to get "
-"back to your account."
-msgstr ""
-
-msgid "You are the only user."
-msgstr "أنت المستخدم الوحيد."
-
-msgid ""
-"As a superuser, you can temporarily assume the identity of another user."
-msgstr ""
-
-#, fuzzy
-msgid "Select User"
-msgstr "إختر مستخدم"
-
 msgid "OpenID server"
 msgstr ""
 
@@ -684,36 +1046,31 @@
 msgid "OpenID is already present."
 msgstr ""
 
-msgid "Failed to resolve OpenID."
-msgstr ""
-
-msgid "OpenID discovery failure, not a valid OpenID."
-msgstr ""
-
-#, python-format
-msgid "OpenID error: %s."
-msgstr ""
-
-#, fuzzy
-msgid "Verification canceled."
-msgstr "تم إلغاء العملية."
-
 msgid "This OpenID is already used for another account."
 msgstr ""
 
 msgid "OpenID added successfully."
 msgstr ""
 
-msgid "OpenID failure."
-msgstr ""
-
 msgid "Current OpenIDs"
 msgstr ""
 
 msgid "Add OpenID"
 msgstr ""
 
-msgid "OpenID verification requires that you click this button:"
+msgid "Options --pages and --search are mutually exclusive!"
+msgstr ""
+
+msgid "You must specify an output file!"
+msgstr ""
+
+msgid "No pages specified using --pages or --search, assuming full package."
+msgstr ""
+
+msgid "All attachments included into the package."
+msgstr ""
+
+msgid "Output file already exists! Cowardly refusing to continue!"
 msgstr ""
 
 #, fuzzy
@@ -750,9 +1107,6 @@
 msgid "Mail account data"
 msgstr "إبعث لي بيانات حسابي بالبريد الإلكتروني."
 
-msgid "Name"
-msgstr "اسم"
-
 msgid "OpenID"
 msgstr ""
 
@@ -760,263 +1114,265 @@
 msgid "Login"
 msgstr "ولوج"
 
-msgid ""
-"Rendering of reStructured text is not possible, please install Docutils."
-msgstr ""
-
-msgid ""
-"{{{\n"
-"Emphasis: *italic* **bold** ``monospace``\n"
-"\n"
-"Headings: Heading 1  Heading 2  Heading 3\n"
-"          =========  ---------  ~~~~~~~~~\n"
-"\n"
-"Horizontal rule: ----\n"
-"\n"
-"Links: TrailingUnderscore_ `multi word with backticks`_ external_\n"
-"\n"
-".. _external: http://external-site.example.org/foo/\n"
-"\n"
-"Lists: * bullets; 1., a. numbered items.\n"
-"}}}\n"
-"(!) For more help, see the\n"
-"[[http://docutils.sourceforge.net/docs/user/rst/quickref.html|"
-"reStructuredText Quick Reference]].\n"
-msgstr ""
-
-msgid "**Maximum number of allowed includes exceeded**"
-msgstr ""
-
-#, fuzzy, python-format
-msgid "**You are not allowed to read the page: %s**"
-msgstr "!لا يسمح لك بالعودة إلى هذه الصفحة"
-
 #, python-format
-msgid "**Could not find the referenced page: %s**"
-msgstr ""
-
-msgid "XSLT option disabled, please look at HelpOnConfiguration."
-msgstr ""
-
-msgid "XSLT processing is not available, please install 4suite 1.x."
+msgid "Local Site Map for \"%s\""
+msgstr ""
+
+msgid "Please log in first."
+msgstr "رجاء سجل دخولك أولا."
+
+msgid "Please first create a homepage before creating additional pages."
 msgstr ""
 
 #, python-format
-msgid "%(errortype)s processing error"
-msgstr ""
-
 msgid ""
-" Emphasis:: <<Verbatim(//)>>''italics''<<Verbatim(//)>>; <<Verbatim(**)"
-">>'''bold'''<<Verbatim(**)>>; <<Verbatim(**//)>>'''''bold "
-"italics'''''<<Verbatim(//**)>>; <<Verbatim(//)>>''mixed ''<<Verbatim(**)"
-">>'''''bold'''<<Verbatim(**)>> and italics''<<Verbatim(//)>>;\n"
-" Horizontal Rule:: <<Verbatim(----)>>\n"
-" Force Linebreak:: <<Verbatim(\\\\)>>\n"
-" Headings:: = Title 1 =; == Title 2 ==; === Title 3 ===; ==== Title 4 ====; "
-"===== Title 5 =====.\n"
-" Lists:: * bullets; ** sub-bullets; # numbered items; ## numbered sub "
-"items.\n"
-" Links:: <<Verbatim([[target]])>>; <<Verbatim([[target|linktext]])>>.\n"
-" Tables:: |= header text | cell text | more cell text |;\n"
+"You can add some additional sub pages to your already existing homepage "
+"here.\n"
 "\n"
-"(!) For more help, see HelpOnEditing or HelpOnCreoleSyntax.\n"
-msgstr ""
-
-msgid ""
-" Emphasis:: <<Verbatim('')>>''italics''<<Verbatim('')>>; <<Verbatim(''')"
-">>'''bold'''<<Verbatim(''')>>; <<Verbatim(''''')>>'''''bold "
-"italics'''''<<Verbatim(''''')>>; <<Verbatim('')>>''mixed ''<<Verbatim(''')"
-">>'''''bold'''<<Verbatim(''')>> and italics''<<Verbatim('')>>; <<Verbatim"
-"(----)>> horizontal rule.\n"
-" Headings:: = Title 1 =; == Title 2 ==; === Title 3 ===; ==== Title 4 ====; "
-"===== Title 5 =====.\n"
-" Lists:: space and one of: * bullets; 1., a., A., i., I. numbered items; 1."
-"#n start numbering at n; space alone indents.\n"
-" Links:: <<Verbatim(JoinCapitalizedWords)>>; <<Verbatim([[target|linktext]])"
-">>.\n"
-" Tables:: || cell text |||| cell text spanning 2 columns ||;    no trailing "
-"white space allowed after tables or titles.\n"
+"You can choose how open to other readers or writers those pages shall be,\n"
+"access is controlled by group membership of the corresponding group page.\n"
 "\n"
-"(!) For more help, see HelpOnEditing or SyntaxReference.\n"
+"Just enter the sub page's name and click on the button to create a new "
+"page.\n"
+"\n"
+"Before creating access protected pages, make sure the corresponding group "
+"page\n"
+"exists and has the appropriate members in it. Use HomepageGroupsTemplate for "
+"creating\n"
+"the group pages.\n"
+"\n"
+"||'''Add a new personal page:'''||'''Related access control list "
+"group:'''||\n"
+"||<<NewPage(HomepageReadWritePageTemplate,read-write page,%(username)s)>>||"
+"[[%(username)s/ReadWriteGroup]]||\n"
+"||<<NewPage(HomepageReadPageTemplate,read-only page,%(username)s)>>||[[%"
+"(username)s/ReadGroup]]||\n"
+"||<<NewPage(HomepagePrivatePageTemplate,private page,%(username)s)>>||%"
+"(username)s only||\n"
+"\n"
+msgstr ""
+
+msgid "MyPages management"
 msgstr ""
 
 #, python-format
-msgid "Expected \"%(wanted)s\" after \"%(key)s\", got \"%(token)s\""
-msgstr ""
-
-#, python-format
-msgid "Expected an integer \"%(key)s\" before \"%(token)s\""
-msgstr ""
-
-#, python-format
-msgid "Expected an integer \"%(arg)s\" after \"%(key)s\""
-msgstr ""
-
-#, python-format
-msgid "Expected a color value \"%(arg)s\" after \"%(key)s\""
-msgstr ""
-
-msgid "anonymous"
-msgstr ""
-
-#, fuzzy
-msgid "Password is too short."
-msgstr "اعادة كلمة السر"
-
-msgid "Password has not enough different characters."
-msgstr ""
-
-#, fuzzy
+msgid "Please use the interactive user interface to use action %(actionname)s!"
+msgstr ""
+
+msgid "TextCha: Wrong answer! Go back and try again..."
+msgstr ""
+
+#, fuzzy, python-format
+msgid "You must login to use this action: %(action)s."
+msgstr "يجب عليك تسجيل دخولك لاستعمال الأشتراكات."
+
+msgid "You are not allowed to subscribe to a page you can't read."
+msgstr "لا يسمح لك الإشتراك بصفحة لا تستطيع قرائتها."
+
+msgid "This wiki is not enabled for mail/Jabber processing."
+msgstr ""
+
+msgid "You must log in to use subscriptions."
+msgstr "يجب عليك تسجيل دخولك لاستعمال الأشتراكات."
+
 msgid ""
-"Password is too easy (password contains name or name contains password)."
-msgstr "لا يوجد كلمة سر. الرجاء إدخال إسم مستخدم و كلمة سر"
-
-msgid "Password is too easy (keyboard sequence)."
-msgstr ""
-
-msgid "Diffs"
-msgstr ""
-
-msgid "Info"
+"Add your email address or Jabber ID in your user settings to use "
+"subscriptions."
 msgstr ""
 
 #, fuzzy
-msgid "Edit"
-msgstr "حرّر"
-
-msgid "UnSubscribe"
-msgstr ""
-
-msgid "Subscribe"
-msgstr "اشتراك"
-
-msgid "Raw"
-msgstr ""
-
-msgid "XML"
-msgstr "XML"
-
-msgid "Print"
-msgstr "طباعة"
-
-msgid "View"
-msgstr "اظهر"
-
-msgid "Up"
-msgstr "أعلى"
-
-msgid "Publish my email (not my wiki homepage) in author info"
-msgstr ""
-"انشر رسائلي الإلكترونية (ليس صفحتي الشخصية في الويكي ) في معلومات المؤلف"
-
-msgid "Open editor on double click"
-msgstr "افتح المحرر عند النقر المزدوج"
+msgid "You are already subscribed to this page."
+msgstr "لا يسمح لك بتحرير هذه الصفحة"
+
+msgid "You have been subscribed to this page."
+msgstr ""
 
 #, fuzzy
-msgid "After login, jump to last visited page"
-msgstr "بعد الولوج، إذهب إلى آخر صفحة تمت زيارتها"
-
-msgid "Show comment sections"
-msgstr "أظهر أقسام التعليقات"
-
-msgid "Show question mark for non-existing pagelinks"
-msgstr "أظهر علامة سؤال للروابط التي تؤدي إلى صفحات غير موجودة"
-
-msgid "Show page trail"
-msgstr ""
-
-msgid "Show icon toolbar"
-msgstr "اظهر أيقونات شريط الأدوات"
-
-msgid "Show top/bottom links in headings"
-msgstr ""
-
-msgid "Show fancy diffs"
-msgstr ""
-
-msgid "Add spaces to displayed wiki names"
-msgstr ""
-
-msgid "Remember login information"
-msgstr "تذكر معلومات الدخول"
-
-msgid "Disable this account forever"
-msgstr "عطل هذا الحساب للأبد"
+msgid "You could not get subscribed to this page."
+msgstr "لا يسمح لك بتحرير هذه الصفحة"
+
+msgid ""
+"Cannot create a new page without a page name.  Please specify a page name."
+msgstr ""
+
+msgid "Do it."
+msgstr "نفذ."
+
+#, python-format
+msgid "Execute action %(actionname)s?"
+msgstr "نفذ عملية %(actionname)s?"
+
+#, python-format
+msgid "Action %(actionname)s is excluded in this wiki!"
+msgstr "لا يسمح للويكي بتنفيذ عملية %(actionname)s!"
+
+#, python-format
+msgid "You are not allowed to use action %(actionname)s on this page!"
+msgstr "لا يسمح لك باستخدام عملية %(actionname)s في هذه الصفحة!"
+
+msgid "If this account exists an email was sent."
+msgstr ""
+
+msgid ""
+"This wiki is not enabled for mail processing.\n"
+"Contact the owner of the wiki, who can enable email."
+msgstr ""
 
 #, fuzzy
-msgid "(Use FirstnameLastname)"
-msgstr "(استخدم الاسم الأول الاسم الأخير)"
-
-msgid "Alias-Name"
-msgstr "الأسم المستعار"
-
-msgid "Jabber ID"
-msgstr ""
-
-msgid "User CSS URL"
-msgstr ""
-
-msgid "(Leave it empty for disabling user CSS)"
-msgstr "URL CSS المستخدم"
-
-msgid "Editor size"
-msgstr "حجم المحرر"
-
-#, python-format
-msgid "Upload new attachment \"%(filename)s\""
+msgid "Please provide a valid email address or a username!"
+msgstr "الرجاء تزويد عنوان بريد إلكتروني صحيح!"
+
+msgid "Mail me my account data"
+msgstr "إبعث لي بيانات حسابي بالبريد الإلكتروني."
+
+msgid "Recovery token"
+msgstr ""
+
+#, fuzzy
+msgid "New password"
+msgstr "كلمةالسرّ"
+
+#, fuzzy
+msgid "New password (repeat)"
+msgstr "اعادة كلمة السر"
+
+#, fuzzy
+msgid "Reset my password"
+msgstr "كلمةالسرّ"
+
+#, fuzzy
+msgid "Your password has been changed, you can log in now."
+msgstr "تم تغيير كلمة السر الخاصة بك."
+
+msgid "Your token is invalid!"
+msgstr ""
+
+#, fuzzy
+msgid "Password reset"
+msgstr "اعادة كلمة السر"
+
+#, fuzzy
+msgid ""
+"\n"
+"== Password reset ==\n"
+"Enter a new password below."
+msgstr "لتغيير كلمة السر الخاصة بك، أدخل كلمة سر جديدة مرتين."
+
+#, fuzzy
+msgid "Lost password"
+msgstr "كلمةالسرّ"
+
+msgid ""
+"\n"
+"== Recovering a lost password ==\n"
+"If you have forgotten your password, provide your email address or\n"
+"username and click on '''Mail me my account data'''.\n"
+"You will receive an email containing a recovery token that can be\n"
+"used to change your password. The email will also contain further\n"
+"instructions."
+msgstr ""
+
+msgid ""
+"\n"
+"=== Password reset ===\n"
+"If you already have received the email with the recovery token, enter your\n"
+"username, the recovery token and a new password (twice) below."
+msgstr ""
+
+#, fuzzy
+msgid "Wiki Backup"
+msgstr "نسخ احتياطي"
+
+msgid ""
+"= Downloading a backup =\n"
+"\n"
+"Please note:\n"
+" * Store backups in a safe and secure place - they contain sensitive "
+"information.\n"
+" * Make sure your wiki configuration backup_* values are correct and "
+"complete.\n"
+" * Make sure the backup file you get contains everything you need in case of "
+"problems.\n"
+" * Make sure it is downloaded without problems.\n"
+"\n"
+"To get a backup, just click here:"
+msgstr ""
+
+msgid "Backup"
+msgstr "نسخ احتياطي"
+
+#, fuzzy
+msgid "You are not allowed to do remote backup."
+msgstr "لا يسمح لك القيام بهذا الإجراء."
+
+#, fuzzy, python-format
+msgid "Unknown backup subaction: %s."
+msgstr "نفذ عملية %(actionname)s?"
+
+msgid "You must login to add a quicklink."
+msgstr "يجب عليك تسجيل دخولك لإضافة رابط سريع"
+
+msgid "A quicklink to this page has been added for you."
+msgstr "تم إضافة رابط سريع إلى هذه الصفحة من أجلك."
+
+msgid "A quicklink to this page could not be added for you."
+msgstr ""
+
+#, fuzzy
+msgid "You already have a quicklink to this page."
+msgstr "لقد قمت بحفظ هذه الصفحة مسبقا!"
+
+msgid "You need to provide a chart type!"
 msgstr ""
 
 #, python-format
-msgid "Inlined image: %(url)s"
-msgstr ""
-
-#, python-format
-msgid "Create new drawing \"%(filename)s (opens in new window)\""
-msgstr ""
-
-#, python-format
-msgid "Edit drawing %(filename)s (opens in new window)"
-msgstr ""
-
-#, python-format
-msgid "Clickable drawing: %(filename)s"
-msgstr ""
-
-msgid "Toggle line numbers"
-msgstr ""
-
-#, python-format
-msgid "Revert to revision %(rev)d."
-msgstr ""
-
-#, python-format
-msgid "Renamed from '%(oldpagename)s'."
-msgstr ""
-
-msgid "You are now logged out."
-msgstr "لقد قمت بتسجيل الخروج."
-
-msgid "You are not allowed to use this action."
-msgstr "لا يسمح لك استعمال هذا الإجراء"
-
-#, fuzzy
-msgid "Delete"
-msgstr "احذف الصفحة"
-
-msgid "This page is already deleted or was never created!"
-msgstr ""
-
-msgid "Delete all /subpages too?"
+msgid "Bad chart type \"%s\"!"
+msgstr ""
+
+msgid "Load"
+msgstr "حمّل"
+
+msgid "Pagename not specified!"
+msgstr ""
+
+msgid "Upload page content"
+msgstr ""
+
+msgid ""
+"You can upload content for the page named below. If you change the page "
+"name, you can also upload content for another page. If the page name is "
+"empty, we derive the page name from the file name."
+msgstr ""
+
+msgid "File to load page content from"
 msgstr ""
 
 #, fuzzy
-msgid "Optional reason for the deletion"
-msgstr "سبب إختياري لإعادة التسمية"
+msgid "Comment"
+msgstr "تعليق"
 
 #, fuzzy
-msgid "Really delete this page?"
+msgid "Page Name"
+msgstr "صفحة جديدة\n"
+
+#, fuzzy
+msgid "You are not allowed to create the supplementation page."
 msgstr "!لا يسمح لك بالعودة إلى هذه الصفحة"
 
+#, fuzzy
+msgid "You must login to remove a quicklink."
+msgstr "يجب عليك تسجيل دخولك لإضافة رابط سريع"
+
+msgid "Your quicklink to this page has been removed."
+msgstr "تم إزالة رابطك السريع لهذه الصفحة."
+
+msgid "Your quicklink to this page could not be removed."
+msgstr ""
+
+#, fuzzy
+msgid "You need to have a quicklink to this page to remove it."
+msgstr "تم إزالة رابطك السريع لهذه الصفحة."
+
 #, python-format
 msgid "[%d attachments]"
 msgstr ""
@@ -1098,9 +1454,6 @@
 msgid "Attachments for \"%(pagename)s\""
 msgstr ""
 
-msgid "TextCha: Wrong answer! Go back and try again..."
-msgstr ""
-
 #, fuzzy
 msgid "You are not allowed to overwrite a file attachment of this page."
 msgstr "لا يسمح لك بتحرير هذه الصفحة"
@@ -1257,133 +1610,11 @@
 msgid "attachment:%(filename)s of %(pagename)s"
 msgstr ""
 
-msgid ""
-"Cannot create a new page without a page name.  Please specify a page name."
-msgstr ""
-
 #, python-format
 msgid "Full Link List for \"%s\""
 msgstr ""
 
 #, python-format
-msgid "No pages like \"%s\"!"
-msgstr ""
-
-#, python-format
-msgid "Exactly one page like \"%s\" found, redirecting to page."
-msgstr ""
-
-#, fuzzy, python-format
-msgid "Pages like \"%s\""
-msgstr "حجم الصفحة: %d"
-
-#, python-format
-msgid "%(matchcount)d %(matches)s for \"%(title)s\""
-msgstr ""
-
-msgid ""
-"You need to manually go to your OpenID provider wiki\n"
-"and log in before you can use your OpenID. MoinMoin will\n"
-"never allow you to enter your password here.\n"
-"\n"
-"Once you have logged in, simply reload this page."
-msgstr ""
-
-msgid "OpenID Trust verification"
-msgstr ""
-
-#, python-format
-msgid "The site %s has asked for your identity."
-msgstr ""
-
-#, python-format
-msgid ""
-"\n"
-"If you approve, the site represented by the trust root below will be\n"
-"told that you control the identity URL %s. (If you are using a delegated\n"
-"identity, the site will take care of reversing the\n"
-"delegation on its own.)"
-msgstr ""
-
-msgid "Trust root"
-msgstr ""
-
-msgid "Identity URL"
-msgstr ""
-
-#, fuzzy
-msgid "Remember decision"
-msgstr "تذكر معلومات الدخول"
-
-msgid "Remember this trust decision and don't ask again"
-msgstr ""
-
-msgid "Approve"
-msgstr "إقرار"
-
-#, fuzzy
-msgid "Don't approve"
-msgstr "لا تقرّ"
-
-msgid "OpenID not served"
-msgstr ""
-
-msgid ""
-"\n"
-"Unfortunately you have not created your homepage yet. Therefore,\n"
-"we cannot serve an OpenID for you. Please create your homepage first\n"
-"and then reload this page or click the button below to cancel this\n"
-"verification."
-msgstr ""
-
-#, fuzzy, python-format
-msgid "You must login to use this action: %(action)s."
-msgstr "يجب عليك تسجيل دخولك لاستعمال الأشتراكات."
-
-msgid "Your subscription to this page has been removed."
-msgstr "تم إزالة اشتراكك بهذه الصفحة."
-
-msgid "Can't remove regular expression subscription!"
-msgstr ""
-
-msgid "Edit the subscription regular expressions in your settings."
-msgstr ""
-
-#, fuzzy
-msgid "You need to be subscribed to unsubscribe."
-msgstr "لا يسمح لك بتحرير هذه الصفحة"
-
-#, fuzzy
-msgid "Wiki Backup"
-msgstr "نسخ احتياطي"
-
-msgid ""
-"= Downloading a backup =\n"
-"\n"
-"Please note:\n"
-" * Store backups in a safe and secure place - they contain sensitive "
-"information.\n"
-" * Make sure your wiki configuration backup_* values are correct and "
-"complete.\n"
-" * Make sure the backup file you get contains everything you need in case of "
-"problems.\n"
-" * Make sure it is downloaded without problems.\n"
-"\n"
-"To get a backup, just click here:"
-msgstr ""
-
-msgid "Backup"
-msgstr "نسخ احتياطي"
-
-#, fuzzy
-msgid "You are not allowed to do remote backup."
-msgstr "لا يسمح لك القيام بهذا الإجراء."
-
-#, fuzzy, python-format
-msgid "Unknown backup subaction: %s."
-msgstr "نفذ عملية %(actionname)s?"
-
-#, python-format
 msgid "Subscribe users to the page %s"
 msgstr ""
 
@@ -1400,9 +1631,15 @@
 msgid "You are not allowed to perform this action."
 msgstr "لا يسمح لك القيام بهذا الإجراء."
 
+msgid "You are not allowed to use this action."
+msgstr "لا يسمح لك استعمال هذا الإجراء"
+
 msgid "Rename Page"
 msgstr "أعد تسمية الصفحة"
 
+msgid "This page is already deleted or was never created!"
+msgstr ""
+
 msgid "Rename all /subpages too?"
 msgstr ""
 
@@ -1415,298 +1652,21 @@
 msgid "Really rename this page?"
 msgstr ""
 
-msgid "No older revisions available!"
-msgstr ""
-
-#, python-format
-msgid "Diff for \"%s\""
-msgstr ""
-
-#, python-format
-msgid "Differences between revisions %d and %d"
-msgstr ""
-
-#, python-format
-msgid "(spanning %d versions)"
-msgstr ""
-
-msgid "Revert to this revision"
-msgstr ""
-
-#, fuzzy
-msgid "Previous change"
-msgstr "السابق"
-
-#, fuzzy
-msgid "Next change"
-msgstr "لم يتغير أي شيء"
-
-msgid "No differences found!"
-msgstr "لا توجد الاختلافات!"
-
-#, python-format
-msgid "The page was saved %(count)d times, though!"
-msgstr ""
-
-msgid "(ignoring whitespace)"
-msgstr ""
-
-msgid "Ignore changes in the amount of whitespace"
-msgstr ""
-
 #, python-format
-msgid "(!) Only pages changed since '''%s''' are being displayed!"
-msgstr ""
-
-msgid ""
-"/!\\ The modification date you entered was not recognized and is therefore "
-"not considered for the search results!"
-msgstr ""
-
-#, python-format
-msgid "Please use a more selective search term instead of {{{\"%s\"}}}"
-msgstr ""
-
-#, python-format
-msgid "Title Search: \"%s\""
-msgstr ""
-
-#, python-format
-msgid "Advanced Search: \"%s\""
-msgstr ""
-
-#, python-format
-msgid "Full Text Search: \"%s\""
-msgstr ""
-
-#, python-format
-msgid ""
-"Your search query {{{\"%s\"}}} is invalid. Please refer to HelpOnSearching "
-"for more information."
-msgstr ""
-
-#, python-format
-msgid ""
-"Your search query {{{\"%s\"}}} didn't return any results. Please change some "
-"terms and refer to HelpOnSearching for more information.%s"
-msgstr ""
-
-msgid "(!) Consider performing a"
-msgstr ""
-
-msgid "full-text search with your search terms"
-msgstr ""
-
-msgid ""
-"(!) You're performing a title search that might not include all related "
-"results of your search query in this wiki. <<BR>>"
-msgstr ""
-
-msgid "Click here to perform a full-text search with your search terms!"
-msgstr ""
-
-#, python-format
-msgid "(including %(localwords)d %(pagelink)s)"
+msgid "No pages like \"%s\"!"
 msgstr ""
 
 #, python-format
-msgid ""
-"The following %(badwords)d words could not be found in the dictionary of %"
-"(totalwords)d words%(localwords)s and are highlighted below:"
-msgstr ""
-
-#, fuzzy
-msgid "Add checked words to dictionary"
-msgstr "أضف الكلمات المشار إليها إلى القاموس"
-
-#, fuzzy
-msgid "No spelling errors found!"
-msgstr "لم يتم العثور على أخطاء هجائية!"
-
-msgid "You can't save spelling words."
-msgstr ""
-
-msgid "You can't check spelling on a page you can't read."
-msgstr "لا يمكنك تدقيق الإملاء في صفحة لا تستطيع قرائتها."
-
-#, fuzzy
-msgid "You are not allowed to create the supplementation page."
-msgstr "!لا يسمح لك بالعودة إلى هذه الصفحة"
-
-msgid "General Information"
-msgstr "معلومات عامة"
-
-#, python-format
-msgid "Page size: %d"
+msgid "Exactly one page like \"%s\" found, redirecting to page."
+msgstr ""
+
+#, fuzzy, python-format
+msgid "Pages like \"%s\""
 msgstr "حجم الصفحة: %d"
 
-msgid "SHA digest of this page's content is:"
-msgstr ""
-
-msgid "The following users subscribed to this page:"
-msgstr ""
-
-msgid "This page links to the following pages:"
-msgstr ""
-
-msgid "Date"
-msgstr "التاريخ"
-
-msgid "Diff"
-msgstr "فروقات"
-
-msgid "Editor"
-msgstr "المحرر"
-
-#, fuzzy
-msgid "Comment"
-msgstr "تعليق"
-
-#, fuzzy
-msgid "to previous"
-msgstr "السابق"
-
-#, fuzzy
-msgid "N/A"
-msgstr "غير متاح"
-
-#, fuzzy
-msgid "Revision History"
-msgstr "تاريخ المراجعة"
-
-msgid "No log entries found."
-msgstr ""
-
-#, python-format
-msgid "Info for \"%s\""
-msgstr ""
-
 #, python-format
-msgid "Show \"%(title)s\""
-msgstr ""
-
-msgid "General Page Infos"
-msgstr "معلومات عامة عن الصفحة"
-
-msgid "Page hits and edits"
-msgstr ""
-
-msgid "User account created! You can use this account to login now..."
-msgstr "تم إنشاء حساب المستخدم! بإمكانك إستخدام هذا الحساب للولوج الآن..."
-
-msgid "TextCha (required)"
-msgstr ""
-
-msgid "Create Profile"
-msgstr ""
-
-msgid "Create Account"
-msgstr ""
-
-#, fuzzy
-msgid "Copy Page"
-msgstr "صفحاتي"
-
-msgid "Copy all /subpages too?"
-msgstr ""
-
-#, fuzzy
-msgid "Optional reason for the copying"
-msgstr "سبب إختياري لإعادة التسمية"
-
-#, fuzzy
-msgid "Really copy this page?"
-msgstr "!لا يسمح لك بالعودة إلى هذه الصفحة"
-
-msgid "Revert"
-msgstr ""
-
-#, fuzzy
-msgid "You are not allowed to revert this page!"
-msgstr "!لا يسمح لك بالعودة إلى هذه الصفحة"
-
-msgid ""
-"You were viewing the current revision of this page when you called the "
-"revert action. If you want to revert to an older revision, first view that "
-"older revision and then call revert to this (older) revision again."
-msgstr ""
-
-#, fuzzy
-msgid "Optional reason for reverting this page"
-msgstr "سبب إختياري لإعادة التسمية"
-
-#, fuzzy
-msgid "Really revert this page?"
-msgstr "!لا يسمح لك بالعودة إلى هذه الصفحة"
-
-msgid "You must login to add a quicklink."
-msgstr "يجب عليك تسجيل دخولك لإضافة رابط سريع"
-
-msgid "A quicklink to this page has been added for you."
-msgstr "تم إضافة رابط سريع إلى هذه الصفحة من أجلك."
-
-msgid "A quicklink to this page could not be added for you."
-msgstr ""
-
-#, fuzzy
-msgid "You already have a quicklink to this page."
-msgstr "لقد قمت بحفظ هذه الصفحة مسبقا!"
-
-msgid "Please choose:"
-msgstr ""
-
-msgid "Settings"
-msgstr "إعدادات"
-
-msgid "Charts are not available!"
-msgstr ""
-
-msgid "You need to provide a chart type!"
-msgstr ""
-
-#, python-format
-msgid "Bad chart type \"%s\"!"
-msgstr ""
-
-#, python-format
-msgid "Local Site Map for \"%s\""
-msgstr ""
-
-#, fuzzy
-msgid "You must login to remove a quicklink."
-msgstr "يجب عليك تسجيل دخولك لإضافة رابط سريع"
-
-msgid "Your quicklink to this page has been removed."
-msgstr "تم إزالة رابطك السريع لهذه الصفحة."
-
-msgid "Your quicklink to this page could not be removed."
-msgstr ""
-
-#, fuzzy
-msgid "You need to have a quicklink to this page to remove it."
-msgstr "تم إزالة رابطك السريع لهذه الصفحة."
-
-msgid "Load"
-msgstr "حمّل"
-
-msgid "Pagename not specified!"
-msgstr ""
-
-msgid "Upload page content"
-msgstr ""
-
-msgid ""
-"You can upload content for the page named below. If you change the page "
-"name, you can also upload content for another page. If the page name is "
-"empty, we derive the page name from the file name."
-msgstr ""
-
-msgid "File to load page content from"
-msgstr ""
-
-#, fuzzy
-msgid "Page Name"
-msgstr "صفحة جديدة\n"
+msgid "%(matchcount)d %(matches)s for \"%(title)s\""
+msgstr ""
 
 #, python-format
 msgid "Invalid filename \"%s\"!"
@@ -1730,169 +1690,23 @@
 msgid "List of page names - separated by a comma"
 msgstr ""
 
-msgid "Do it."
-msgstr "نفذ."
-
-#, python-format
-msgid "Execute action %(actionname)s?"
-msgstr "نفذ عملية %(actionname)s?"
-
-#, python-format
-msgid "Action %(actionname)s is excluded in this wiki!"
-msgstr "لا يسمح للويكي بتنفيذ عملية %(actionname)s!"
-
-#, python-format
-msgid "You are not allowed to use action %(actionname)s on this page!"
-msgstr "لا يسمح لك باستخدام عملية %(actionname)s في هذه الصفحة!"
-
-#, python-format
-msgid "Please use the interactive user interface to use action %(actionname)s!"
-msgstr ""
-
-msgid "Please log in first."
-msgstr "رجاء سجل دخولك أولا."
-
-msgid "Please first create a homepage before creating additional pages."
-msgstr ""
-
-#, python-format
-msgid ""
-"You can add some additional sub pages to your already existing homepage "
-"here.\n"
-"\n"
-"You can choose how open to other readers or writers those pages shall be,\n"
-"access is controlled by group membership of the corresponding group page.\n"
-"\n"
-"Just enter the sub page's name and click on the button to create a new "
-"page.\n"
-"\n"
-"Before creating access protected pages, make sure the corresponding group "
-"page\n"
-"exists and has the appropriate members in it. Use HomepageGroupsTemplate for "
-"creating\n"
-"the group pages.\n"
-"\n"
-"||'''Add a new personal page:'''||'''Related access control list "
-"group:'''||\n"
-"||<<NewPage(HomepageReadWritePageTemplate,read-write page,%(username)s)>>||"
-"[[%(username)s/ReadWriteGroup]]||\n"
-"||<<NewPage(HomepageReadPageTemplate,read-only page,%(username)s)>>||[[%"
-"(username)s/ReadGroup]]||\n"
-"||<<NewPage(HomepagePrivatePageTemplate,private page,%(username)s)>>||%"
-"(username)s only||\n"
-"\n"
-msgstr ""
-
-msgid "MyPages management"
-msgstr ""
-
 #, fuzzy
-msgid "Pages"
-msgstr "صفحات"
-
-msgid "Select Author"
-msgstr "إختر المؤلف"
-
-msgid "Revert all!"
+msgid "Delete"
+msgstr "احذف الصفحة"
+
+msgid "Delete all /subpages too?"
 msgstr ""
 
 #, fuzzy
-msgid "Only superuser is allowed to use this action."
-msgstr "لا يسمح لك استعمال هذا الإجراء"
-
-msgid "You are not allowed to subscribe to a page you can't read."
-msgstr "لا يسمح لك الإشتراك بصفحة لا تستطيع قرائتها."
-
-msgid "This wiki is not enabled for mail/Jabber processing."
-msgstr ""
-
-msgid "You must log in to use subscriptions."
-msgstr "يجب عليك تسجيل دخولك لاستعمال الأشتراكات."
-
-msgid ""
-"Add your email address or Jabber ID in your user settings to use "
-"subscriptions."
-msgstr ""
-
-#, fuzzy
-msgid "You are already subscribed to this page."
-msgstr "لا يسمح لك بتحرير هذه الصفحة"
-
-msgid "You have been subscribed to this page."
-msgstr ""
-
-#, fuzzy
-msgid "You could not get subscribed to this page."
-msgstr "لا يسمح لك بتحرير هذه الصفحة"
-
-msgid "If this account exists an email was sent."
-msgstr ""
-
-msgid ""
-"This wiki is not enabled for mail processing.\n"
-"Contact the owner of the wiki, who can enable email."
-msgstr ""
-
-#, fuzzy
-msgid "Please provide a valid email address or a username!"
-msgstr "الرجاء تزويد عنوان بريد إلكتروني صحيح!"
-
-msgid "Mail me my account data"
-msgstr "إبعث لي بيانات حسابي بالبريد الإلكتروني."
-
-msgid "Recovery token"
-msgstr ""
+msgid "Optional reason for the deletion"
+msgstr "سبب إختياري لإعادة التسمية"
 
 #, fuzzy
-msgid "New password"
-msgstr "كلمةالسرّ"
-
-#, fuzzy
-msgid "New password (repeat)"
-msgstr "اعادة كلمة السر"
-
-#, fuzzy
-msgid "Reset my password"
-msgstr "كلمةالسرّ"
-
-#, fuzzy
-msgid "Your password has been changed, you can log in now."
-msgstr "تم تغيير كلمة السر الخاصة بك."
-
-msgid "Your token is invalid!"
-msgstr ""
-
-#, fuzzy
-msgid "Password reset"
-msgstr "اعادة كلمة السر"
-
-#, fuzzy
-msgid ""
-"\n"
-"== Password reset ==\n"
-"Enter a new password below."
-msgstr "لتغيير كلمة السر الخاصة بك، أدخل كلمة سر جديدة مرتين."
-
-#, fuzzy
-msgid "Lost password"
-msgstr "كلمةالسرّ"
-
-msgid ""
-"\n"
-"== Recovering a lost password ==\n"
-"If you have forgotten your password, provide your email address or\n"
-"username and click on '''Mail me my account data'''.\n"
-"You will receive an email containing a recovery token that can be\n"
-"used to change your password. The email will also contain further\n"
-"instructions."
-msgstr ""
-
-msgid ""
-"\n"
-"=== Password reset ===\n"
-"If you already have received the email with the recovery token, enter your\n"
-"username, the recovery token and a new password (twice) below."
-msgstr ""
+msgid "Really delete this page?"
+msgstr "!لا يسمح لك بالعودة إلى هذه الصفحة"
+
+msgid "You are now logged out."
+msgstr "لقد قمت بتسجيل الخروج."
 
 #, python-format
 msgid "Rolled back changes to the page %s."
@@ -2023,653 +1837,401 @@
 msgid "Page %s merged with conflicts."
 msgstr ""
 
-#, python-format
-msgid "Connection to mailserver '%(server)s' failed: %(reason)s"
-msgstr ""
-
-msgid "Mail not sent"
-msgstr "لم يتم ارسال البريد"
-
-msgid "Mail sent OK"
-msgstr "تم ارسال البريد "
-
-msgid "From"
-msgstr "من"
-
-msgid "To"
-msgstr "إلى"
+msgid "Editor"
+msgstr "المحرر"
 
 #, fuzzy
-msgid "Content"
-msgstr "تصريح"
-
-msgid "Attachments"
-msgstr "المرفقات"
-
-msgid "Line"
-msgstr "سطر"
-
-msgid "Deletions are marked like this."
-msgstr ""
-
-msgid "Additions are marked like this."
+msgid "Pages"
+msgstr "صفحات"
+
+msgid "Select Author"
+msgstr "إختر المؤلف"
+
+msgid "Revert all!"
 msgstr ""
 
 #, fuzzy
-msgid "Attachment link"
-msgstr "المرفقات"
-
-#, fuzzy
-msgid "Page link"
-msgstr "حجم الصفحة: %d"
-
-#, fuzzy
-msgid "Changed page"
-msgstr "صفحات مشابه"
-
-#, fuzzy
-msgid "Page changed"
-msgstr "إحفظ التغييرات"
-
-msgid "Page has been modified"
-msgstr "تم تعديل الصفحة"
-
-msgid "Page has been modified in a trivial fashion"
-msgstr "تم تعديل الصفحة بشكل بسيط"
-
-msgid "Page has been renamed"
-msgstr "تم إعادة تسمية الصفحة"
-
-msgid "Page has been deleted"
-msgstr "تم حذف الصفحة"
-
-msgid "Page has been copied"
-msgstr "تم نسخ الصفحة"
-
-#, fuzzy
-msgid "A new attachment has been added"
-msgstr "المرفقات"
-
-msgid "A page has been reverted to a previous state"
+msgid "Only superuser is allowed to use this action."
+msgstr "لا يسمح لك استعمال هذا الإجراء"
+
+msgid "No older revisions available!"
+msgstr ""
+
+#, python-format
+msgid "Diff for \"%s\""
+msgstr ""
+
+#, python-format
+msgid "Differences between revisions %d and %d"
+msgstr ""
+
+#, python-format
+msgid "(spanning %d versions)"
+msgstr ""
+
+msgid "Revert to this revision"
 msgstr ""
 
 #, fuzzy
-msgid "A user has subscribed to a page"
-msgstr "لا يسمح لك بتحرير هذه الصفحة"
-
-msgid "A new account has been created"
-msgstr "تم إنشاء حساب جديد"
+msgid "Previous change"
+msgstr "السابق"
+
+#, fuzzy
+msgid "Next change"
+msgstr "لم يتغير أي شيء"
 
 #, python-format
-msgid ""
-"Dear Wiki user,\n"
-"\n"
-"You have subscribed to a wiki page or wiki category on \"%(sitename)s\" for "
-"change notification.\n"
-"\n"
-"The \"%(pagename)s\" page has been changed by %(editor)s:\n"
-msgstr ""
-
-msgid "New page:\n"
-msgstr "صفحة جديدة\n"
-
-msgid "No differences found!\n"
-msgstr "ْلا توجد اختلافات \n"
-
-#, python-format
-msgid ""
-"Dear wiki user,\n"
-"\n"
-"You have subscribed to a wiki page \"%(sitename)s\" for change "
-"notification.\n"
-"\n"
-"The page \"%(pagename)s\" has been deleted by %(editor)s:\n"
-"\n"
+msgid "The page was saved %(count)d times, though!"
+msgstr ""
+
+msgid "(ignoring whitespace)"
+msgstr ""
+
+msgid "Ignore changes in the amount of whitespace"
 msgstr ""
 
 #, python-format
-msgid ""
-"Dear wiki user,\n"
-"\n"
-"You have subscribed to a wiki page \"%(sitename)s\" for change "
-"notification.\n"
-"\n"
-"The page \"%(pagename)s\" has been renamed from \"%(oldname)s\" by %(editor)"
-"s:\n"
-msgstr ""
-
-#, python-format
-msgid "New user account created on %(sitename)s"
-msgstr ""
-
-#, python-format
-msgid ""
-"Dear Superuser, a new user has just been created on %(sitename)s\". Details "
-"follow:\n"
-"\n"
-"    User name: %(username)s\n"
-"    Email address: %(useremail)s"
-msgstr ""
-
-#, python-format
-msgid "New attachment added to page %(pagename)s on %(sitename)s"
+msgid "(including %(localwords)d %(pagelink)s)"
 msgstr ""
 
 #, python-format
 msgid ""
-"Dear Wiki user,\n"
-"\n"
-"You have subscribed to a wiki page \"%(page_name)s\" for change "
-"notification. An attachment has been added to that page by %(editor)s. "
-"Following detailed information is available:\n"
-"\n"
-"Attachment name: %(attach_name)s\n"
-"Attachment size: %(attach_size)s\n"
-msgstr ""
-
-#, python-format
-msgid "[%(sitename)s] %(trivial)sUpdate of \"%(pagename)s\" by %(username)s"
-msgstr ""
-
-msgid "Trivial "
-msgstr "بديهي"
-
-#, python-format
-msgid ""
-"Attachment link: %(attach)s\n"
-"Page link: %(page)s\n"
-msgstr ""
-
-msgid "FrontPage"
-msgstr ""
-
-msgid "RecentChanges"
-msgstr ""
-
-msgid "TitleIndex"
-msgstr ""
-
-msgid "WordIndex"
-msgstr ""
-
-msgid "FindPage"
-msgstr ""
-
-msgid "SiteNavigation"
-msgstr ""
-
-msgid "HelpContents"
-msgstr ""
-
-msgid "HelpOnFormatting"
-msgstr ""
-
-msgid "WikiLicense"
-msgstr ""
-
-msgid "MissingPage"
-msgstr ""
-
-msgid "MissingHomePage"
-msgstr ""
-
-msgid "Mon"
-msgstr "الإثنين"
-
-msgid "Tue"
-msgstr "الثلاثاء"
-
-msgid "Wed"
-msgstr "الأربعاء"
-
-msgid "Thu"
-msgstr "الخميس"
-
-msgid "Fri"
-msgstr "الجمعة"
-
-msgid "Sat"
-msgstr "السبت"
-
-msgid "Sun"
-msgstr "الأحد"
-
-msgid "AttachFile"
-msgstr ""
-
-msgid "DeletePage"
-msgstr ""
-
-msgid "LikePages"
-msgstr ""
-
-msgid "LocalSiteMap"
-msgstr ""
-
-msgid "RenamePage"
-msgstr ""
-
-msgid "SpellCheck"
-msgstr ""
-
-msgid "Discussion"
-msgstr ""
-
-#, python-format
-msgid "Invalid include arguments \"%s\"!"
-msgstr ""
-
-#, python-format
-msgid "Nothing found for \"%s\"!"
-msgstr ""
-
-#, python-format
-msgid "Upload of attachment '%(filename)s'."
-msgstr ""
-
-#, python-format
-msgid "Drawing '%(filename)s' saved."
-msgstr ""
-
-#, python-format
-msgid "%(mins)dm ago"
-msgstr ""
-
-msgid "(no bookmark set)"
-msgstr ""
-
-#, python-format
-msgid "(currently set to %s)"
+"The following %(badwords)d words could not be found in the dictionary of %"
+"(totalwords)d words%(localwords)s and are highlighted below:"
 msgstr ""
 
 #, fuzzy
-msgid "Delete bookmark"
-msgstr "احذف الصفحة"
-
-msgid "Set bookmark"
-msgstr ""
-
-msgid "[Bookmark reached]"
+msgid "Add checked words to dictionary"
+msgstr "أضف الكلمات المشار إليها إلى القاموس"
+
+#, fuzzy
+msgid "No spelling errors found!"
+msgstr "لم يتم العثور على أخطاء هجائية!"
+
+msgid "You can't save spelling words."
+msgstr ""
+
+msgid "You can't check spelling on a page you can't read."
+msgstr "لا يمكنك تدقيق الإملاء في صفحة لا تستطيع قرائتها."
+
+#, fuzzy
+msgid "Copy Page"
+msgstr "صفحاتي"
+
+msgid "Copy all /subpages too?"
 msgstr ""
 
 #, fuzzy
-msgid "Python Version"
-msgstr "إصدار بايثون"
+msgid "Optional reason for the copying"
+msgstr "سبب إختياري لإعادة التسمية"
 
 #, fuzzy
-msgid "MoinMoin Version"
-msgstr "إصدار موين موين"
-
-#, python-format
-msgid "Release %s [Revision %s]"
-msgstr ""
-
-msgid "4Suite Version"
-msgstr ""
-
-msgid "Number of pages"
-msgstr "عدد الصفحات"
-
-msgid "Number of system pages"
-msgstr "عدد صفحات النظام"
-
-msgid "Accumulated page sizes"
-msgstr "حجم الصفحات التراكمي"
-
-#, python-format
-msgid "Disk usage of %(data_dir)s/pages/"
+msgid "Really copy this page?"
+msgstr "!لا يسمح لك بالعودة إلى هذه الصفحة"
+
+msgid "Revert"
+msgstr ""
+
+#, fuzzy
+msgid "You are not allowed to revert this page!"
+msgstr "!لا يسمح لك بالعودة إلى هذه الصفحة"
+
+msgid ""
+"You were viewing the current revision of this page when you called the "
+"revert action. If you want to revert to an older revision, first view that "
+"older revision and then call revert to this (older) revision again."
+msgstr ""
+
+#, fuzzy
+msgid "Optional reason for reverting this page"
+msgstr "سبب إختياري لإعادة التسمية"
+
+#, fuzzy
+msgid "Really revert this page?"
+msgstr "!لا يسمح لك بالعودة إلى هذه الصفحة"
+
+msgid ""
+"You need to manually go to your OpenID provider wiki\n"
+"and log in before you can use your OpenID. MoinMoin will\n"
+"never allow you to enter your password here.\n"
+"\n"
+"Once you have logged in, simply reload this page."
+msgstr ""
+
+msgid "OpenID Trust verification"
 msgstr ""
 
 #, python-format
-msgid "Disk usage of %(data_dir)s/"
-msgstr ""
-
-msgid "Entries in edit log"
-msgstr ""
-
-msgid "NONE"
-msgstr "لا شيء"
-
-msgid "Global extension macros"
-msgstr ""
-
-msgid "Local extension macros"
-msgstr ""
-
-msgid "Global extension actions"
-msgstr ""
-
-msgid "Local extension actions"
-msgstr ""
-
-msgid "Global parsers"
-msgstr ""
-
-msgid "Local extension parsers"
-msgstr ""
-
-msgid "Disabled"
-msgstr "معطل"
-
-#, fuzzy
-msgid "Enabled"
-msgstr "مفعل"
-
-msgid "index available"
-msgstr ""
-
-msgid "index unavailable"
-msgstr ""
-
-msgid "Xapian and/or Python Xapian bindings not installed"
-msgstr ""
-
-msgid "Xapian search"
-msgstr ""
-
-msgid "Stemming for Xapian"
-msgstr ""
-
-msgid "Active threads"
-msgstr ""
-
-msgid "Include system pages"
-msgstr ""
-
-msgid "Exclude system pages"
-msgstr ""
-
-msgid "No wanted pages in this wiki."
-msgstr ""
-
-#, python-format
-msgid "No quotes on %(pagename)s."
-msgstr ""
-
-msgid "Markup"
-msgstr ""
-
-msgid "Display"
-msgstr "العرض"
-
-msgid "Wiki configuration"
-msgstr ""
-
-msgid ""
-"This table shows all settings in this wiki that do not have default values. "
-"Settings that the configuration system doesn't know about are shown in "
-"''italic'', those may be due to third-party extensions needing configuration "
-"or settings that were removed from Moin."
-msgstr ""
-
-#, fuzzy
-msgid "Variable name"
-msgstr "إسم الملف"
-
-#, fuzzy
-msgid "Setting"
-msgstr "إعدادات"
-
-msgid "Search Titles"
-msgstr "بحث في العناوين"
-
-msgid "Display context of search results"
-msgstr ""
-
-msgid "Case-sensitive searching"
-msgstr ""
-
-msgid "Search Text"
-msgstr ""
-
-msgid "Description"
-msgstr ""
-
-msgid "No orphaned pages in this wiki."
-msgstr ""
-
-msgid "Search for items"
-msgstr ""
-
-msgid "containing all the following terms"
-msgstr "يحوتي على جميع العبارات التالية"
-
-msgid "containing one or more of the following terms"
-msgstr "يحتوي على واحدا أو أكثر من العبارات التالية"
-
-msgid "not containing the following terms"
-msgstr "لا يحتوي على العبارات التالية"
-
-msgid "last modified since (e.g. last 2 weeks)"
-msgstr ""
-
-msgid "any category"
-msgstr ""
-
-msgid "any language"
-msgstr "أي لغة"
-
-msgid "any mimetype"
-msgstr "أي نوع MIME"
-
-msgid "Categories"
-msgstr ""
-
-msgid "Language"
-msgstr "لغة"
-
-msgid "File Type"
-msgstr "نوع الملف"
-
-msgid "Search only in titles"
-msgstr "إبحث في العناوين فقط"
-
-msgid "Case-sensitive search"
-msgstr "بحث حساس لحالة الحرف"
-
-msgid "Exclude underlay"
-msgstr ""
-
-msgid "No system items"
-msgstr ""
-
-msgid "Search in all page revisions"
-msgstr ""
-
-msgid "Go get it!"
-msgstr ""
-
-#, fuzzy
-msgid "Contents"
-msgstr "محتويات"
-
-#, python-format
-msgid "Unsupported navigation scheme '%(scheme)s'!"
-msgstr ""
-
-msgid "No parent page found!"
-msgstr ""
-
-msgid "Wiki"
-msgstr "ويكي"
-
-msgid "Slideshow"
-msgstr ""
-
-#, fuzzy
-msgid "Start"
-msgstr "إبدأ"
-
-#, python-format
-msgid "Slide %(pos)d of %(size)d"
-msgstr ""
-
-#, fuzzy
-msgid "Go To Page"
-msgstr "إذهب إلى الصفحة"
-
-#, fuzzy
-msgid "File attachment browser"
-msgstr "المرفقات"
-
-msgid "User account browser"
+msgid "The site %s has asked for your identity."
 msgstr ""
 
 #, python-format
 msgid ""
-"%(extension_name)s %(extension_type)s: Required argument %(argument_name)s "
-"missing."
-msgstr ""
-
-#, python-format
-msgid ""
-"%(extension_name)s %(extension_type)s: Invalid %(argument_name)s=%"
-"(argument_value)s!"
-msgstr ""
-
-#, python-format
-msgid ""
-"Current configuration does not allow embedding of the file %(file)s because "
-"of its mimetype %(mimetype)s."
+"\n"
+"If you approve, the site represented by the trust root below will be\n"
+"told that you control the identity URL %s. (If you are using a delegated\n"
+"identity, the site will take care of reversing the\n"
+"delegation on its own.)"
+msgstr ""
+
+msgid "Trust root"
+msgstr ""
+
+msgid "Identity URL"
 msgstr ""
 
 #, fuzzy
-msgid "Embedded"
-msgstr "مدمج"
-
-msgid "Missing password. Please enter user name and password."
-msgstr "لا يوجد كلمة سر. الرجاء إدخال إسم مستخدم و كلمة سر"
-
-#, python-format
-msgid "LDAP server %(server)s failed."
-msgstr ""
-
-msgid "Failed to connect to database."
-msgstr "فشلت محاولة الإتصال بقاعدة البيانات."
+msgid "Remember decision"
+msgstr "تذكر معلومات الدخول"
+
+msgid "Remember this trust decision and don't ask again"
+msgstr ""
+
+msgid "Approve"
+msgstr "إقرار"
 
 #, fuzzy
-msgid "You need to log in."
-msgstr "لقد قمت بتسجيل الخروج."
-
-msgid ""
-"Please choose an account name now.\n"
-"If you choose an existing account name you will be asked for the\n"
-"password and be able to associate the account with your OpenID."
-msgstr ""
-
-msgid "Choose this name"
-msgstr "إختر هذا الإسم"
-
-msgid "This is not a valid username, choose a different one."
+msgid "Don't approve"
+msgstr "لا تقرّ"
+
+msgid "OpenID not served"
 msgstr ""
 
 msgid ""
-"The username you have chosen is already\n"
-"taken. If it is your username, enter your password below to associate\n"
-"the username with your OpenID. Otherwise, please choose a different\n"
-"username and leave the password field blank."
-msgstr ""
-
-msgid "Associate this name"
-msgstr ""
-
-msgid "Your account is now associated to your OpenID."
-msgstr ""
-
-msgid "The password you entered is not valid."
-msgstr "كلمة السر التي أدخلتها غير صالحة."
-
-msgid "Anonymous sessions need to be enabled for OpenID login."
-msgstr ""
-
-msgid "No OpenID."
+"\n"
+"Unfortunately you have not created your homepage yet. Therefore,\n"
+"we cannot serve an OpenID for you. Please create your homepage first\n"
+"and then reload this page or click the button below to cancel this\n"
+"verification."
+msgstr ""
+
+msgid "Please choose:"
+msgstr ""
+
+msgid "Settings"
+msgstr "إعدادات"
+
+msgid "General Information"
+msgstr "معلومات عامة"
+
+#, python-format
+msgid "Page size: %d"
+msgstr "حجم الصفحة: %d"
+
+msgid "SHA digest of this page's content is:"
+msgstr ""
+
+msgid "The following users subscribed to this page:"
+msgstr ""
+
+msgid "This page links to the following pages:"
+msgstr ""
+
+msgid "Diff"
+msgstr "فروقات"
+
+#, fuzzy
+msgid "to previous"
+msgstr "السابق"
+
+#, python-format
+msgid "Revert to revision %(rev)d."
+msgstr ""
+
+#, python-format
+msgid "Renamed from '%(oldpagename)s'."
+msgstr ""
+
+#, fuzzy
+msgid "N/A"
+msgstr "غير متاح"
+
+#, fuzzy
+msgid "Revision History"
+msgstr "تاريخ المراجعة"
+
+msgid "No log entries found."
+msgstr ""
+
+#, python-format
+msgid "Info for \"%s\""
+msgstr ""
+
+#, python-format
+msgid "Show \"%(title)s\""
+msgstr ""
+
+msgid "General Page Infos"
+msgstr "معلومات عامة عن الصفحة"
+
+#, python-format
+msgid "(!) Only pages changed since '''%s''' are being displayed!"
 msgstr ""
 
 msgid ""
-"If you do not have an account yet, you can still log in with your OpenID and "
-"create one during login."
+"/!\\ The modification date you entered was not recognized and is therefore "
+"not considered for the search results!"
+msgstr ""
+
+#, python-format
+msgid "Please use a more selective search term instead of {{{\"%s\"}}}"
+msgstr ""
+
+#, python-format
+msgid "Title Search: \"%s\""
+msgstr ""
+
+#, python-format
+msgid "Advanced Search: \"%s\""
+msgstr ""
+
+#, python-format
+msgid "Full Text Search: \"%s\""
 msgstr ""
 
 #, python-format
 msgid ""
-"If you do not have an account, <a href=\"%(userprefslink)s\">you can create "
-"one now</a>. <a href=\"%(sendmypasswordlink)s\">Forgot your password?</a>"
-msgstr ""
-
-msgid "Could not contact botbouncer.com."
-msgstr ""
-
-msgid "User agent"
-msgstr ""
-
-msgid "Others"
-msgstr ""
-
-msgid "Distribution of User-Agent Types"
-msgstr ""
-
-msgid "Views/day"
-msgstr ""
-
-msgid "Edits/day"
+"Your search query {{{\"%s\"}}} is invalid. Please refer to HelpOnSearching "
+"for more information."
 msgstr ""
 
 #, python-format
-msgid "%(chart_title)s for %(filterpage)s"
+msgid ""
+"Your search query {{{\"%s\"}}} didn't return any results. Please change some "
+"terms and refer to HelpOnSearching for more information.%s"
+msgstr ""
+
+msgid "(!) Consider performing a"
+msgstr ""
+
+msgid "full-text search with your search terms"
 msgstr ""
 
 msgid ""
-"green=view\n"
-"red=edit"
-msgstr ""
-
-msgid "date"
-msgstr "التاريخ"
-
-msgid "# of hits"
-msgstr ""
-
-msgid "Page Size Distribution"
-msgstr ""
-
-msgid "page size upper bound [bytes]"
-msgstr ""
-
-msgid "# of pages of this size"
-msgstr ""
-
-msgid "Options --pages and --search are mutually exclusive!"
-msgstr ""
-
-msgid "You must specify an output file!"
-msgstr ""
-
-msgid "No pages specified using --pages or --search, assuming full package."
-msgstr ""
-
-msgid "All attachments included into the package."
-msgstr ""
-
-msgid "Output file already exists! Cowardly refusing to continue!"
-msgstr ""
-
-#, fuzzy, python-format
-msgid "Unknown action %(action_name)s."
-msgstr "نفذ عملية %(actionname)s?"
-
-#, fuzzy, python-format
-msgid "You are not allowed to do %(action_name)s on this page."
-msgstr "لا يسمح لك باستخدام عملية %(actionname)s في هذه الصفحة!"
-
-msgid "Login and try again."
-msgstr "سجل الدخول و حاول مرة أخرى"
-
-#, python-format
-msgid ""
-"Sorry, can not save page because \"%(content)s\" is not allowed in this wiki."
-msgstr ""
-
-msgid "[ATTACH]"
+"(!) You're performing a title search that might not include all related "
+"results of your search query in this wiki. <<BR>>"
+msgstr ""
+
+msgid "Click here to perform a full-text search with your search terms!"
+msgstr ""
+
+msgid "User account created! You can use this account to login now..."
+msgstr "تم إنشاء حساب المستخدم! بإمكانك إستخدام هذا الحساب للولوج الآن..."
+
+#, fuzzy
+msgid "(Use FirstnameLastname)"
+msgstr "(استخدم الاسم الأول الاسم الأخير)"
+
+msgid "TextCha (required)"
+msgstr ""
+
+msgid "Create Profile"
+msgstr ""
+
+msgid "Create Account"
+msgstr ""
+
+msgid "Your subscription to this page has been removed."
+msgstr "تم إزالة اشتراكك بهذه الصفحة."
+
+msgid "Can't remove regular expression subscription!"
+msgstr ""
+
+msgid "Edit the subscription regular expressions in your settings."
+msgstr ""
+
+#, fuzzy
+msgid "You need to be subscribed to unsubscribe."
+msgstr "لا يسمح لك بتحرير هذه الصفحة"
+
+msgid "Diffs"
+msgstr ""
+
+msgid "Info"
+msgstr ""
+
+#, fuzzy
+msgid "Edit"
+msgstr "حرّر"
+
+msgid "UnSubscribe"
+msgstr ""
+
+msgid "Subscribe"
+msgstr "اشتراك"
+
+msgid "Raw"
+msgstr ""
+
+msgid "XML"
+msgstr "XML"
+
+msgid "Print"
+msgstr "طباعة"
+
+msgid "View"
+msgstr "اظهر"
+
+msgid "Up"
+msgstr "أعلى"
+
+msgid "Publish my email (not my wiki homepage) in author info"
+msgstr ""
+"انشر رسائلي الإلكترونية (ليس صفحتي الشخصية في الويكي ) في معلومات المؤلف"
+
+msgid "Open editor on double click"
+msgstr "افتح المحرر عند النقر المزدوج"
+
+#, fuzzy
+msgid "After login, jump to last visited page"
+msgstr "بعد الولوج، إذهب إلى آخر صفحة تمت زيارتها"
+
+msgid "Show comment sections"
+msgstr "أظهر أقسام التعليقات"
+
+msgid "Show question mark for non-existing pagelinks"
+msgstr "أظهر علامة سؤال للروابط التي تؤدي إلى صفحات غير موجودة"
+
+msgid "Show page trail"
+msgstr ""
+
+msgid "Show icon toolbar"
+msgstr "اظهر أيقونات شريط الأدوات"
+
+msgid "Show top/bottom links in headings"
+msgstr ""
+
+msgid "Show fancy diffs"
+msgstr ""
+
+msgid "Add spaces to displayed wiki names"
+msgstr ""
+
+msgid "Remember login information"
+msgstr "تذكر معلومات الدخول"
+
+msgid "Disable this account forever"
+msgstr "عطل هذا الحساب للأبد"
+
+msgid "Alias-Name"
+msgstr "الأسم المستعار"
+
+msgid "Jabber ID"
+msgstr ""
+
+msgid "User CSS URL"
+msgstr ""
+
+msgid "(Leave it empty for disabling user CSS)"
+msgstr "URL CSS المستخدم"
+
+msgid "Editor size"
+msgstr "حجم المحرر"
+
+msgid "Unsubscribe"
+msgstr "إلغاء الإشتراك"
+
+msgid "Home"
 msgstr ""
 
 msgid "[RSS]"
@@ -2705,22 +2267,6 @@
 msgid "Logout"
 msgstr "تسجيل الخروج"
 
-msgid "DeleteCache"
-msgstr ""
-
-#, python-format
-msgid "(cached %s)"
-msgstr ""
-
-msgid "Or try one of these actions:"
-msgstr "أو جرب أحد هذه الأفعال:"
-
-msgid "Unsubscribe"
-msgstr "إلغاء الإشتراك"
-
-msgid "Home"
-msgstr ""
-
 msgid "Clear message"
 msgstr ""
 
@@ -2813,6 +2359,9 @@
 msgid "Add Link"
 msgstr "ضع رابط"
 
+msgid "Attachments"
+msgstr "المرفقات"
+
 #, python-format
 msgid "Show %s days."
 msgstr ""
@@ -2820,12 +2369,445 @@
 msgid "Wiki Markup"
 msgstr ""
 
+msgid "DeleteCache"
+msgstr ""
+
+#, python-format
+msgid "(cached %s)"
+msgstr ""
+
+msgid "Or try one of these actions:"
+msgstr "أو جرب أحد هذه الأفعال:"
+
+msgid "Wiki"
+msgstr "ويكي"
+
 msgid "Page"
 msgstr "الصفحة"
 
 msgid "User"
 msgstr "المستخدم"
 
+msgid "[ATTACH]"
+msgstr ""
+
+#, fuzzy
+msgid "Variable name"
+msgstr "إسم الملف"
+
+msgid "Description"
+msgstr ""
+
+#, python-format
+msgid "Upload new attachment \"%(filename)s\""
+msgstr ""
+
+#, python-format
+msgid ""
+"%(extension_name)s %(extension_type)s: Required argument %(argument_name)s "
+"missing."
+msgstr ""
+
+#, python-format
+msgid ""
+"%(extension_name)s %(extension_type)s: Invalid %(argument_name)s=%"
+"(argument_value)s!"
+msgstr ""
+
+#, python-format
+msgid ""
+"Current configuration does not allow embedding of the file %(file)s because "
+"of its mimetype %(mimetype)s."
+msgstr ""
+
+#, fuzzy
+msgid "Embedded"
+msgstr "مدمج"
+
+msgid "Include system pages"
+msgstr ""
+
+msgid "Exclude system pages"
+msgstr ""
+
+#, fuzzy
+msgid "Go To Page"
+msgstr "إذهب إلى الصفحة"
+
+msgid "Markup"
+msgstr ""
+
+msgid "Display"
+msgstr "العرض"
+
+msgid "Wiki configuration"
+msgstr ""
+
+msgid ""
+"This table shows all settings in this wiki that do not have default values. "
+"Settings that the configuration system doesn't know about are shown in "
+"''italic'', those may be due to third-party extensions needing configuration "
+"or settings that were removed from Moin."
+msgstr ""
+
+#, fuzzy
+msgid "Setting"
+msgstr "إعدادات"
+
+msgid "Search for items"
+msgstr ""
+
+msgid "containing all the following terms"
+msgstr "يحوتي على جميع العبارات التالية"
+
+msgid "containing one or more of the following terms"
+msgstr "يحتوي على واحدا أو أكثر من العبارات التالية"
+
+msgid "not containing the following terms"
+msgstr "لا يحتوي على العبارات التالية"
+
+msgid "last modified since (e.g. last 2 weeks)"
+msgstr ""
+
+msgid "any category"
+msgstr ""
+
+msgid "any language"
+msgstr "أي لغة"
+
+msgid "any mimetype"
+msgstr "أي نوع MIME"
+
+msgid "Categories"
+msgstr ""
+
+msgid "File Type"
+msgstr "نوع الملف"
+
+msgid "Search only in titles"
+msgstr "إبحث في العناوين فقط"
+
+msgid "Case-sensitive search"
+msgstr "بحث حساس لحالة الحرف"
+
+msgid "Exclude underlay"
+msgstr ""
+
+msgid "No system items"
+msgstr ""
+
+msgid "Search in all page revisions"
+msgstr ""
+
+msgid "Go get it!"
+msgstr ""
+
+#, fuzzy
+msgid "File attachment browser"
+msgstr "المرفقات"
+
+msgid "User account browser"
+msgstr ""
+
+msgid "No wanted pages in this wiki."
+msgstr ""
+
+#, python-format
+msgid "Unsupported navigation scheme '%(scheme)s'!"
+msgstr ""
+
+msgid "No parent page found!"
+msgstr ""
+
+msgid "Slideshow"
+msgstr ""
+
+#, fuzzy
+msgid "Start"
+msgstr "إبدأ"
+
+#, python-format
+msgid "Slide %(pos)d of %(size)d"
+msgstr ""
+
+#, fuzzy
+msgid "Contents"
+msgstr "محتويات"
+
+msgid "Search Titles"
+msgstr "بحث في العناوين"
+
+msgid "Display context of search results"
+msgstr ""
+
+msgid "Case-sensitive searching"
+msgstr ""
+
+msgid "Search Text"
+msgstr ""
+
+#, python-format
+msgid "No quotes on %(pagename)s."
+msgstr ""
+
+#, fuzzy
+msgid "Python Version"
+msgstr "إصدار بايثون"
+
+#, fuzzy
+msgid "MoinMoin Version"
+msgstr "إصدار موين موين"
+
+#, python-format
+msgid "Release %s [Revision %s]"
+msgstr ""
+
+msgid "4Suite Version"
+msgstr ""
+
+msgid "Number of pages"
+msgstr "عدد الصفحات"
+
+msgid "Number of system pages"
+msgstr "عدد صفحات النظام"
+
+msgid "Accumulated page sizes"
+msgstr "حجم الصفحات التراكمي"
+
+#, python-format
+msgid "Disk usage of %(data_dir)s/pages/"
+msgstr ""
+
+#, python-format
+msgid "Disk usage of %(data_dir)s/"
+msgstr ""
+
+msgid "Entries in edit log"
+msgstr ""
+
+msgid "NONE"
+msgstr "لا شيء"
+
+msgid "Global extension macros"
+msgstr ""
+
+msgid "Local extension macros"
+msgstr ""
+
+msgid "Global extension actions"
+msgstr ""
+
+msgid "Local extension actions"
+msgstr ""
+
+msgid "Global parsers"
+msgstr ""
+
+msgid "Local extension parsers"
+msgstr ""
+
+msgid "Disabled"
+msgstr "معطل"
+
+#, fuzzy
+msgid "Enabled"
+msgstr "مفعل"
+
+msgid "index available"
+msgstr ""
+
+msgid "index unavailable"
+msgstr ""
+
+msgid "Xapian and/or Python Xapian bindings not installed"
+msgstr ""
+
+msgid "Xapian search"
+msgstr ""
+
+msgid "Stemming for Xapian"
+msgstr ""
+
+msgid "Active threads"
+msgstr ""
+
+#, python-format
+msgid "Upload of attachment '%(filename)s'."
+msgstr ""
+
+#, python-format
+msgid "Drawing '%(filename)s' saved."
+msgstr ""
+
+#, python-format
+msgid "%(mins)dm ago"
+msgstr ""
+
+msgid "(no bookmark set)"
+msgstr ""
+
+#, python-format
+msgid "(currently set to %s)"
+msgstr ""
+
+#, fuzzy
+msgid "Delete bookmark"
+msgstr "احذف الصفحة"
+
+msgid "Set bookmark"
+msgstr ""
+
+msgid "[Bookmark reached]"
+msgstr ""
+
+#, python-format
+msgid "Invalid include arguments \"%s\"!"
+msgstr ""
+
+#, python-format
+msgid "Nothing found for \"%s\"!"
+msgstr ""
+
+msgid "No orphaned pages in this wiki."
+msgstr ""
+
+msgid "From"
+msgstr "من"
+
+msgid "To"
+msgstr "إلى"
+
+#, fuzzy
+msgid "Content"
+msgstr "تصريح"
+
+#, python-format
+msgid "Connection to mailserver '%(server)s' failed: %(reason)s"
+msgstr ""
+
+msgid "Mail not sent"
+msgstr "لم يتم ارسال البريد"
+
+msgid "Mail sent OK"
+msgstr "تم ارسال البريد "
+
+msgid "[all]"
+msgstr ""
+
+msgid "[not empty]"
+msgstr ""
+
+msgid "[empty]"
+msgstr ""
+
+msgid "filter"
+msgstr "مرشح"
+
+#, fuzzy, python-format
+msgid "Unknown action %(action_name)s."
+msgstr "نفذ عملية %(actionname)s?"
+
+#, fuzzy, python-format
+msgid "You are not allowed to do %(action_name)s on this page."
+msgstr "لا يسمح لك باستخدام عملية %(actionname)s في هذه الصفحة!"
+
+msgid "Login and try again."
+msgstr "سجل الدخول و حاول مرة أخرى"
+
+msgid "FrontPage"
+msgstr ""
+
+msgid "RecentChanges"
+msgstr ""
+
+msgid "TitleIndex"
+msgstr ""
+
+msgid "WordIndex"
+msgstr ""
+
+msgid "FindPage"
+msgstr ""
+
+msgid "SiteNavigation"
+msgstr ""
+
+msgid "HelpContents"
+msgstr ""
+
+msgid "HelpOnFormatting"
+msgstr ""
+
+msgid "WikiLicense"
+msgstr ""
+
+msgid "MissingPage"
+msgstr ""
+
+msgid "MissingHomePage"
+msgstr ""
+
+msgid "Mon"
+msgstr "الإثنين"
+
+msgid "Tue"
+msgstr "الثلاثاء"
+
+msgid "Wed"
+msgstr "الأربعاء"
+
+msgid "Thu"
+msgstr "الخميس"
+
+msgid "Fri"
+msgstr "الجمعة"
+
+msgid "Sat"
+msgstr "السبت"
+
+msgid "Sun"
+msgstr "الأحد"
+
+msgid "AttachFile"
+msgstr ""
+
+msgid "DeletePage"
+msgstr ""
+
+msgid "LikePages"
+msgstr ""
+
+msgid "LocalSiteMap"
+msgstr ""
+
+msgid "RenamePage"
+msgstr ""
+
+msgid "SpellCheck"
+msgstr ""
+
+msgid "Discussion"
+msgstr ""
+
+#, python-format
+msgid "Inlined image: %(url)s"
+msgstr ""
+
+#, python-format
+msgid "Create new drawing \"%(filename)s (opens in new window)\""
+msgstr ""
+
+#, python-format
+msgid "Edit drawing %(filename)s (opens in new window)"
+msgstr ""
+
+#, python-format
+msgid "Clickable drawing: %(filename)s"
+msgstr ""
+
+msgid "Toggle line numbers"
+msgstr ""
+
 #~ msgid "Wiki Backup / Restore"
 #~ msgstr "نسخ إحتياطي / إستعادة ويكي"
 
--- a/MoinMoin/i18n/bg.MoinMoin.po	Tue Feb 10 13:08:03 2009 +0100
+++ b/MoinMoin/i18n/bg.MoinMoin.po	Tue Feb 10 13:21:59 2009 +0100
@@ -13,7 +13,7 @@
 msgstr ""
 "Project-Id-Version: MoinMoin 1.6\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2009-01-24 04:45+0100\n"
+"POT-Creation-Date: 2008-09-12 23:35+0200\n"
 "PO-Revision-Date: 2006-02-11 12:20-0800\n"
 "Last-Translator: Hristo Iliev <hristo@phys.uni-sofia.bg>\n"
 "Language-Team: Bulgarian <moin-devel@lists.sourceforge.net>\n"
@@ -26,35 +26,6 @@
 "X-HasWikiMarkup: True\n"
 
 #, python-format
-msgid "Invalid highlighting regular expression \"%(regex)s\": %(error)s"
-msgstr ""
-
-msgid ""
-"The backed up content of this page is deprecated and will not be included in "
-"search results!"
-msgstr ""
-"Архивното съдържание на тази страница е твърде остаряло и няма да бъде "
-"включено в резултатите от търсенето!"
-
-#, python-format
-msgid "Revision %(rev)d as of %(date)s"
-msgstr "Версия %(rev)d от %(date)s"
-
-#, python-format
-msgid "Redirected from page \"%(page)s\""
-msgstr "Пренасочена от страница \"%(page)s\""
-
-#, python-format
-msgid "This page redirects to page \"%(page)s\""
-msgstr "Тази страница пренасочва към \"%(page)s\""
-
-msgid "Create New Page"
-msgstr "Създай нова страница"
-
-msgid "You are not allowed to view this page."
-msgstr "Не е позволено да разглеждате тази страница."
-
-#, python-format
 msgid "Argument \"%s\" must be a boolean value, not \"%s\""
 msgstr ""
 
@@ -117,6 +88,9 @@
 msgid "Expected a value for key \"%(token)s\""
 msgstr "Очаква се стойност на ключа \"%(token)s\""
 
+msgid "Your changes are not saved!"
+msgstr "Вашите промени не са записани!"
+
 msgid "You are not allowed to edit this page."
 msgstr "Не е позволено да редактирате тази страница."
 
@@ -129,6 +103,9 @@
 msgid "The lock you held timed out. Be prepared for editing conflicts!"
 msgstr "Привилегията да редактирате изтече. Гответе се за конфликти!"
 
+msgid "Page name is too long, try shorter name."
+msgstr "Твърде дълго име на страницата, опитайте с нещо по-кратко."
+
 #, python-format
 msgid "Draft of \"%(pagename)s\""
 msgstr "Чернова на \"%(pagename)s\""
@@ -225,8 +202,8 @@
 msgid "Preview"
 msgstr "Предварителен изглед"
 
-msgid "Text mode"
-msgstr "Текстов режим"
+msgid "GUI Mode"
+msgstr "Визуален режим"
 
 msgid "Load Draft"
 msgstr "Зареждане на чернова"
@@ -247,82 +224,6 @@
 msgid "Remove trailing whitespace from each line"
 msgstr "Премахване на крайните интервали от всеки ред"
 
-#, python-format
-msgid "The package needs a newer version of MoinMoin (at least %s)."
-msgstr "Този пакет изисква по-нова версия на MoinMoin (поне %s)."
-
-msgid "The theme name is not set."
-msgstr "Името на темата не е настроено."
-
-msgid "Installing theme files is only supported for standalone type servers."
-msgstr ""
-"Инсталирането на файлове от теми се поддържа само на сървъри от "
-"самостоятелен тип."
-
-#, python-format
-msgid "Installation of '%(filename)s' failed."
-msgstr "Инсталирането на '%(filename)s' пропадна."
-
-#, python-format
-msgid "The file %s is not a MoinMoin package file."
-msgstr "Файлът %s не е пакетен файл на MoinMoin."
-
-#, python-format
-msgid "The page %s does not exist."
-msgstr "Страницата %s не съществува."
-
-msgid "Invalid package file header."
-msgstr "Невалидна заглавна част на пакета."
-
-msgid "Package file format unsupported."
-msgstr "Форматът на файла не се поддържа."
-
-#, python-format
-msgid "Unknown function %(func)s in line %(lineno)i."
-msgstr "Непозната функция %(func)s на ред %(lineno)i."
-
-#, python-format
-msgid "The file %s was not found in the package."
-msgstr "Файлът %s не беше открит в пакета."
-
-msgid "<unknown>"
-msgstr "<неизвестен>"
-
-#, fuzzy, python-format
-msgid ""
-"Login Name: %s\n"
-"\n"
-"Password recovery token: %s\n"
-"\n"
-"Password reset URL: %s/?action=recoverpass&name=%s&token=%s\n"
-msgstr ""
-"Потребителско име: %s\n"
-"\n"
-"Парола за вход: %s\n"
-"\n"
-"URL за вход: %s/%s?action=login\n"
-
-msgid ""
-"Somebody has requested to email you a password recovery token.\n"
-"\n"
-"If you lost your password, please go to the password reset URL below or\n"
-"go to the password recovery page again and enter your username and the\n"
-"recovery token.\n"
-msgstr ""
-
-#, python-format
-msgid "[%(sitename)s] Your wiki account data"
-msgstr "[%(sitename)s] Данни за Вашия уики акаунт"
-
-msgid "Your changes are not saved!"
-msgstr "Вашите промени не са записани!"
-
-msgid "Page name is too long, try shorter name."
-msgstr "Твърде дълго име на страницата, опитайте с нещо по-кратко."
-
-msgid "GUI Mode"
-msgstr "Визуален режим"
-
 msgid "Edit was cancelled."
 msgstr "Редакцията беше отменена."
 
@@ -466,6 +367,38 @@
 "за да избегнете конфликти.'''<<BR>>\n"
 "За да напуснете редактора, натиснете бутона Отказ."
 
+msgid "<unknown>"
+msgstr "<неизвестен>"
+
+#, python-format
+msgid "Invalid highlighting regular expression \"%(regex)s\": %(error)s"
+msgstr ""
+
+msgid ""
+"The backed up content of this page is deprecated and will not be included in "
+"search results!"
+msgstr ""
+"Архивното съдържание на тази страница е твърде остаряло и няма да бъде "
+"включено в резултатите от търсенето!"
+
+#, python-format
+msgid "Revision %(rev)d as of %(date)s"
+msgstr "Версия %(rev)d от %(date)s"
+
+#, python-format
+msgid "Redirected from page \"%(page)s\""
+msgstr "Пренасочена от страница \"%(page)s\""
+
+#, python-format
+msgid "This page redirects to page \"%(page)s\""
+msgstr "Тази страница пренасочва към \"%(page)s\""
+
+msgid "Create New Page"
+msgstr "Създай нова страница"
+
+msgid "You are not allowed to view this page."
+msgstr "Не е позволено да разглеждате тази страница."
+
 msgid "The wiki is currently not reachable."
 msgstr "Уикито не е достъпно в момента."
 
@@ -480,6 +413,92 @@
 "Отдалеченото уики използва вътрешно InterWiki име (%(remotename)s), различно "
 "от указаното (%(localname)s)."
 
+msgid "Text mode"
+msgstr "Текстов режим"
+
+#, python-format
+msgid "The package needs a newer version of MoinMoin (at least %s)."
+msgstr "Този пакет изисква по-нова версия на MoinMoin (поне %s)."
+
+msgid "The theme name is not set."
+msgstr "Името на темата не е настроено."
+
+msgid "Installing theme files is only supported for standalone type servers."
+msgstr ""
+"Инсталирането на файлове от теми се поддържа само на сървъри от "
+"самостоятелен тип."
+
+#, python-format
+msgid "Installation of '%(filename)s' failed."
+msgstr "Инсталирането на '%(filename)s' пропадна."
+
+#, python-format
+msgid "The file %s is not a MoinMoin package file."
+msgstr "Файлът %s не е пакетен файл на MoinMoin."
+
+#, python-format
+msgid "The page %s does not exist."
+msgstr "Страницата %s не съществува."
+
+msgid "Invalid package file header."
+msgstr "Невалидна заглавна част на пакета."
+
+msgid "Package file format unsupported."
+msgstr "Форматът на файла не се поддържа."
+
+#, python-format
+msgid "Unknown function %(func)s in line %(lineno)i."
+msgstr "Непозната функция %(func)s на ред %(lineno)i."
+
+#, python-format
+msgid "The file %s was not found in the package."
+msgstr "Файлът %s не беше открит в пакета."
+
+#, fuzzy, python-format
+msgid ""
+"Login Name: %s\n"
+"\n"
+"Password recovery token: %s\n"
+"\n"
+"Password reset URL: %s/?action=recoverpass&name=%s&token=%s\n"
+msgstr ""
+"Потребителско име: %s\n"
+"\n"
+"Парола за вход: %s\n"
+"\n"
+"URL за вход: %s/%s?action=login\n"
+
+msgid ""
+"Somebody has requested to email you a password recovery token.\n"
+"\n"
+"If you lost your password, please go to the password reset URL below or\n"
+"go to the password recovery page again and enter your username and the\n"
+"recovery token.\n"
+msgstr ""
+
+#, python-format
+msgid "[%(sitename)s] Your wiki account data"
+msgstr "[%(sitename)s] Данни за Вашия уики акаунт"
+
+msgid "Line"
+msgstr "Ред"
+
+msgid "No differences found!"
+msgstr "Не са открити разлики!"
+
+msgid "Deletions are marked like this."
+msgstr "Изтритото е отбелязано така."
+
+msgid "Additions are marked like this."
+msgstr "Добавките са отбелязани така."
+
+#, python-format
+msgid ""
+"Sorry, can not save page because \"%(content)s\" is not allowed in this wiki."
+msgstr ""
+"Съжаляваме, но страницата не може да бъде записана, защото \"%(content)s\" е "
+"непозволено съдържание."
+
 #, python-format
 msgid ""
 "Results %(bs)s%(hitsFrom)d - %(hitsTo)d%(be)s of %(aboutHits)s %(bs)s%(hits)d"
@@ -517,214 +536,111 @@
 msgid "about"
 msgstr ""
 
-msgid "[all]"
-msgstr "[всички]"
-
-msgid "[not empty]"
-msgstr "[не празни]"
-
-msgid "[empty]"
-msgstr "[празни]"
-
-msgid "filter"
-msgstr "филтър"
+msgid "Language"
+msgstr "Език"
+
+msgid "<Browser setting>"
+msgstr "<Настройка на браузъра>"
+
+msgid "Others"
+msgstr "Други"
+
+msgid "Date"
+msgstr "Дата"
+
+msgid "Views/day"
+msgstr "Прегледа/ден"
+
+msgid "Edits/day"
+msgstr "Редакции/ден"
+
+msgid "Page hits and edits"
+msgstr "Попадения и редакции на страницата"
+
+#, python-format
+msgid "%(chart_title)s for %(filterpage)s"
+msgstr "%(chart_title)s за %(filterpage)s"
+
+msgid ""
+"green=view\n"
+"red=edit"
+msgstr ""
+"зелено=преглед\n"
+"червено=редакция"
+
+msgid "date"
+msgstr "дата"
+
+msgid "# of hits"
+msgstr "брой попадения"
+
+msgid "Charts are not available!"
+msgstr "Схемите не са достъпни!"
+
+msgid "Page Size Distribution"
+msgstr "Разпределение по големини на страници"
+
+msgid "page size upper bound [bytes]"
+msgstr "горна граница на големина на страница [байта]"
+
+msgid "# of pages of this size"
+msgstr "брой страници с такъв размер"
+
+msgid "User agent"
+msgstr "Браузър"
+
+msgid "Distribution of User-Agent Types"
+msgstr "Разпределение на типа браузъри"
+
+msgid "Could not contact botbouncer.com."
+msgstr ""
+
+msgid "Failed to connect to database."
+msgstr ""
+
+msgid "Missing password. Please enter user name and password."
+msgstr "Липсва парола. Моля, въведете потребителско име и парола."
+
+#, python-format
+msgid ""
+"If you do not have an account, <a href=\"%(userprefslink)s\">you can create "
+"one now</a>. <a href=\"%(sendmypasswordlink)s\">Forgot your password?</a>"
+msgstr ""
 
 #, fuzzy
-msgid "Change password"
-msgstr "Парола"
-
-msgid "Passwords don't match!"
-msgstr "Паролите не съвпадат!"
-
-msgid "Please specify a password!"
-msgstr "Моля въведете парола!"
+msgid "You need to log in."
+msgstr "Вие излязохте успешно."
 
 #, python-format
-msgid "Password not acceptable: %s"
+msgid "LDAP server %(server)s failed."
 msgstr ""
 
-msgid "Your password has been changed."
+msgid ""
+"Please choose an account name now.\n"
+"If you choose an existing account name you will be asked for the\n"
+"password and be able to associate the account with your OpenID."
 msgstr ""
 
-msgid "To change your password, enter a new password twice."
+msgid "Name"
+msgstr "Име"
+
+msgid "Choose this name"
+msgstr ""
+
+msgid "This is not a valid username, choose a different one."
+msgstr ""
+
+msgid ""
+"The username you have chosen is already\n"
+"taken. If it is your username, enter your password below to associate\n"
+"the username with your OpenID. Otherwise, please choose a different\n"
+"username and leave the password field blank."
 msgstr ""
 
 msgid "Password"
 msgstr "Парола"
 
-msgid "Password repeat"
-msgstr "Повторение на паролата"
-
-msgid "Preferences"
-msgstr "Предпочитания"
-
-#, python-format
-msgid ""
-"Invalid user name {{{'%s'}}}.\n"
-"Name may contain any Unicode alpha numeric character, with optional one\n"
-"space between words. Group page name is not allowed."
-msgstr ""
-"Невалидно потребителско име {{{'%s'}}}.\n"
-"Името може да съдържа произволни Unicode букви и цифри, по желание с един\n"
-"интервал между думите. Не е позволено да се използват имена на групови "
-"страници."
-
-msgid "This user name already belongs to somebody else."
-msgstr "Това потребителско име вече принадлежи на някой друг."
-
-msgid "Empty user name. Please enter a user name."
-msgstr "Празно потребителско име. Моля въведете потребителско име."
-
-msgid ""
-"Please provide your email address. If you lose your login information, you "
-"can get it by email."
-msgstr ""
-"Моля въведете Вашия адрес на ел. поща. Ако загубите информацията за сметката "
-"си, то ще можете да я получите по ел. поща."
-
-msgid "This email already belongs to somebody else."
-msgstr "Този ел. поща вече принадлежи на някой друг."
-
-#, fuzzy
-msgid "This jabber id already belongs to somebody else."
-msgstr "Този ел. поща вече принадлежи на някой друг."
-
-#, python-format
-msgid "The theme '%(theme_name)s' could not be loaded!"
-msgstr "Темата '%(theme_name)s' не може да бъде заредена!"
-
-msgid "User preferences saved!"
-msgstr "Потребителските настройки са записани!"
-
-msgid "Default"
-msgstr "Подразбиращ се"
-
-msgid "<Browser setting>"
-msgstr "<Настройка на браузъра>"
-
-msgid "the one preferred"
-msgstr "предпочитания"
-
-msgid "free choice"
-msgstr "свободен избор"
-
-msgid "Save"
-msgstr "Запис"
-
-msgid "Preferred theme"
-msgstr "Предпочитана тема"
-
-msgid "Editor Preference"
-msgstr "Предпочитан редактор"
-
-msgid "Editor shown on UI"
-msgstr "Редактор, показван при бутоните"
-
-msgid "Time zone"
-msgstr "Часова зона"
-
-msgid "Your time is"
-msgstr "Времето при Вас е"
-
-msgid "Server time is"
-msgstr "Времето на сървъра е"
-
-msgid "Date format"
-msgstr "Формат на датата"
-
-msgid "Preferred language"
-msgstr "Предпочитан език"
-
-msgid "General options"
-msgstr "Общи настройки"
-
-msgid "Quick links"
-msgstr "Бързи връзки"
-
-msgid "Notification"
-msgstr ""
-
-msgid "Notification settings saved!"
-msgstr ""
-
-#, fuzzy
-msgid "'''Email'''"
-msgstr "ел. поща"
-
-msgid "'''Jabber'''"
-msgstr ""
-
-msgid "'''Event type'''"
-msgstr ""
-
-msgid "Select the events you want to be notified about."
-msgstr ""
-
-msgid ""
-"Before you can be notified, you need to provide a way to contact you in the "
-"general preferences."
-msgstr ""
-
-#, fuzzy
-msgid "Subscribed events"
-msgstr "Абониране на потребител"
-
-#, fuzzy
-msgid "Subscribed wiki pages<<BR>>(one regex per line)"
-msgstr "Абонаменти за уики страници (по един шаблон на ред)"
-
-msgid "Switch user"
-msgstr ""
-
-msgid "No user selected"
-msgstr ""
-
-msgid ""
-"You can now change the settings of the selected user account; log out to get "
-"back to your account."
-msgstr ""
-
-msgid "You are the only user."
-msgstr ""
-
-msgid ""
-"As a superuser, you can temporarily assume the identity of another user."
-msgstr ""
-
-msgid "Select User"
-msgstr "Избор на потребител"
-
-msgid "OpenID server"
-msgstr ""
-
-msgid "The selected websites have been removed."
-msgstr ""
-
-msgid "Trusted websites"
-msgstr ""
-
-msgid "Remove selected"
-msgstr ""
-
-msgid "OpenID settings"
-msgstr ""
-
-msgid "Cannot remove all OpenIDs."
-msgstr ""
-
-msgid "The selected OpenIDs have been removed."
-msgstr ""
-
-msgid "No OpenID given."
-msgstr ""
-
-msgid "OpenID is already present."
-msgstr ""
-
-msgid "Failed to resolve OpenID."
-msgstr ""
-
-msgid "OpenID discovery failure, not a valid OpenID."
+msgid "Associate this name"
 msgstr ""
 
 #, python-format
@@ -735,66 +651,248 @@
 msgid "Verification canceled."
 msgstr "Операцията беше отменена."
 
-#, fuzzy
-msgid "This OpenID is already used for another account."
-msgstr "Тази страница вече е изтрита или никога не е била създавана!"
-
-msgid "OpenID added successfully."
-msgstr ""
-
 msgid "OpenID failure."
 msgstr ""
 
-msgid "Current OpenIDs"
+msgid "Your account is now associated to your OpenID."
 msgstr ""
 
-msgid "Add OpenID"
+msgid "The password you entered is not valid."
 msgstr ""
 
 msgid "OpenID verification requires that you click this button:"
 msgstr ""
 
-#, fuzzy
-msgid "Username"
-msgstr "Потребител"
-
-#, fuzzy
-msgid "Member of Groups"
-msgstr "Брой страници"
-
-msgid "Email"
-msgstr "ел. поща"
-
-msgid "Jabber"
+msgid "Anonymous sessions need to be enabled for OpenID login."
 msgstr ""
 
-msgid "Action"
-msgstr "Действие"
+msgid "Failed to resolve OpenID."
+msgstr ""
+
+msgid "OpenID discovery failure, not a valid OpenID."
+msgstr ""
+
+msgid "No OpenID."
+msgstr ""
+
+msgid ""
+"If you do not have an account yet, you can still log in with your OpenID and "
+"create one during login."
+msgstr ""
+
+msgid "Page has been modified"
+msgstr ""
+
+msgid "Page has been modified in a trivial fashion"
+msgstr ""
 
 #, fuzzy
-msgid "Disable user"
-msgstr "Изключен"
-
-#, fuzzy
-msgid "Enable user"
-msgstr "Включен"
+msgid "Page has been renamed"
+msgstr "Попадения и редакции на страницата"
 
 #, fuzzy
-msgid "disabled"
-msgstr "Изключен"
+msgid "Page has been deleted"
+msgstr "Страница \"%s\" беше изтрита успешно!"
 
 #, fuzzy
-msgid "Mail account data"
-msgstr "Изпрати ми моите данни по пощата"
-
-msgid "Name"
-msgstr "Име"
-
-msgid "OpenID"
+msgid "Page has been copied"
+msgstr "Попадения и редакции на страницата"
+
+#, fuzzy
+msgid "A new attachment has been added"
+msgstr "Ново име на приложение"
+
+msgid "A page has been reverted to a previous state"
 msgstr ""
 
-msgid "Login"
-msgstr "Вход"
+#, fuzzy
+msgid "A user has subscribed to a page"
+msgstr "Бяхте абонирани за тази страница."
+
+msgid "A new account has been created"
+msgstr ""
+
+#, python-format
+msgid "[%(sitename)s] %(trivial)sUpdate of \"%(pagename)s\" by %(username)s"
+msgstr "[%(sitename)s] %(trivial)sПромяна на \"%(pagename)s\" от %(username)s"
+
+msgid "Trivial "
+msgstr "Незначителна "
+
+#, python-format
+msgid ""
+"Attachment link: %(attach)s\n"
+"Page link: %(page)s\n"
+msgstr ""
+
+#, fuzzy, python-format
+msgid ""
+"Dear Wiki user,\n"
+"\n"
+"You have subscribed to a wiki page or wiki category on \"%(sitename)s\" for "
+"change notification.\n"
+"\n"
+"The \"%(pagename)s\" page has been changed by %(editor)s:\n"
+msgstr ""
+"Уважаеми Уики потребителю,\n"
+"\n"
+"Вие сте се абонирали да получавате известия за промени в уики страница или "
+"уики категория на \"%(sitename)s\".\n"
+"\n"
+"Следната страница беше променена от %(editor)s:\n"
+"%(pagelink)s\n"
+"\n"
+
+msgid "New page:\n"
+msgstr "Нова страница:\n"
+
+msgid "No differences found!\n"
+msgstr "Не са открити разлики!\n"
+
+#, fuzzy, python-format
+msgid ""
+"Dear wiki user,\n"
+"\n"
+"You have subscribed to a wiki page \"%(sitename)s\" for change "
+"notification.\n"
+"\n"
+"The page \"%(pagename)s\" has been deleted by %(editor)s:\n"
+"\n"
+msgstr ""
+"Уважаеми Уики потребителю,\n"
+"\n"
+"Вие сте се абонирали да получавате известия за промени в уики страница или "
+"уики категория на \"%(sitename)s\".\n"
+"\n"
+"Следната страница беше променена от %(editor)s:\n"
+"%(pagelink)s\n"
+"\n"
+
+#, fuzzy, python-format
+msgid ""
+"Dear wiki user,\n"
+"\n"
+"You have subscribed to a wiki page \"%(sitename)s\" for change "
+"notification.\n"
+"\n"
+"The page \"%(pagename)s\" has been renamed from \"%(oldname)s\" by %(editor)"
+"s:\n"
+msgstr ""
+"Уважаеми Уики потребителю,\n"
+"\n"
+"Вие сте се абонирали да получавате известия за промени в уики страница или "
+"уики категория на \"%(sitename)s\".\n"
+"\n"
+"Следната страница беше променена от %(editor)s:\n"
+"%(pagelink)s\n"
+"\n"
+
+#, python-format
+msgid "New user account created on %(sitename)s"
+msgstr ""
+
+#, python-format
+msgid ""
+"Dear Superuser, a new user has just been created on %(sitename)s\". Details "
+"follow:\n"
+"\n"
+"    User name: %(username)s\n"
+"    Email address: %(useremail)s"
+msgstr ""
+
+#, fuzzy, python-format
+msgid "New attachment added to page %(pagename)s on %(sitename)s"
+msgstr "приложение:%(filename)s към %(pagename)s"
+
+#, python-format
+msgid ""
+"Dear Wiki user,\n"
+"\n"
+"You have subscribed to a wiki page \"%(page_name)s\" for change "
+"notification. An attachment has been added to that page by %(editor)s. "
+"Following detailed information is available:\n"
+"\n"
+"Attachment name: %(attach_name)s\n"
+"Attachment size: %(attach_size)s\n"
+msgstr ""
+
+#, fuzzy
+msgid "Attachment link"
+msgstr "Приложения"
+
+#, fuzzy
+msgid "Page link"
+msgstr "Страници подобни на \"%s\""
+
+#, fuzzy
+msgid "Changed page"
+msgstr "Страници в пакета"
+
+#, fuzzy
+msgid "Page changed"
+msgstr "Запис на промените"
+
+#, fuzzy
+msgid ""
+" Emphasis:: <<Verbatim('')>>''italics''<<Verbatim('')>>; <<Verbatim(''')"
+">>'''bold'''<<Verbatim(''')>>; <<Verbatim(''''')>>'''''bold "
+"italics'''''<<Verbatim(''''')>>; <<Verbatim('')>>''mixed ''<<Verbatim(''')"
+">>'''''bold'''<<Verbatim(''')>> and italics''<<Verbatim('')>>; <<Verbatim"
+"(----)>> horizontal rule.\n"
+" Headings:: = Title 1 =; == Title 2 ==; === Title 3 ===; ==== Title 4 ====; "
+"===== Title 5 =====.\n"
+" Lists:: space and one of: * bullets; 1., a., A., i., I. numbered items; 1."
+"#n start numbering at n; space alone indents.\n"
+" Links:: <<Verbatim(JoinCapitalizedWords)>>; <<Verbatim([[target|linktext]])"
+">>.\n"
+" Tables:: || cell text |||| cell text spanning 2 columns ||;    no trailing "
+"white space allowed after tables or titles.\n"
+"\n"
+"(!) For more help, see HelpOnEditing or SyntaxReference.\n"
+msgstr ""
+" Наблягане:: <<Verbatim('')>>''наклонен''<<Verbatim('')>>; <<Verbatim(''')"
+">>'''удебелен'''<<Verbatim(''')>>; <<Verbatim(''''')>>'''''удебелен и "
+"наклонен'''''<<Verbatim(''''')>>; <<Verbatim('')>>''смесени ''<<Verbatim(''')"
+">>'''''удебелен'''<<Verbatim(''')>> и наклонен''<<Verbatim('')>>; <<Verbatim"
+"(----)>> хоризонтална черта.\n"
+" Заглавия:: <<Verbatim(=)>> Заглавие 1 <<Verbatim(=)>>; <<Verbatim(==)>> "
+"Заглавие 2 <<Verbatim(==)>>; <<Verbatim(===)>> Заглавие 3 <<Verbatim(===)"
+">>;   <<Verbatim(====)>> Заглавие 4 <<Verbatim(====)>>; <<Verbatim(=====)>> "
+"Заглавие 5 <<Verbatim(=====)>>.\n"
+" Списъци:: интервал и едно от: * bullets; 1., a., A., i., I. номерирани "
+"елементи; 1.#n започва номерирането от n; само интервал вмъква навътре.\n"
+" Връзки:: <<Verbatim(СвързаниДумиПървиБуквиГлавни)>>; <<Verbatim"
+"([\"квадратни скоби и кавички\"])>>; url; [url]; [url етикет].\n"
+" Таблици:: || текст на клетка |||| текст на клетка, заемаща 2 колони ||;    "
+"не е позволено оставянето на празно място след таблици или заглавия.\n"
+"\n"
+"(!) За повече помощ вижте ПомощПриРедактиране или СинтактичноУпътване.\n"
+
+#, python-format
+msgid "Expected \"%(wanted)s\" after \"%(key)s\", got \"%(token)s\""
+msgstr "Очаква се \"%(wanted)s\" след \"%(key)s\", а е открит \"%(token)s\""
+
+#, python-format
+msgid "Expected an integer \"%(key)s\" before \"%(token)s\""
+msgstr "Очаква се цяло число \"%(key)s\" преди \"%(token)s\""
+
+#, python-format
+msgid "Expected an integer \"%(arg)s\" after \"%(key)s\""
+msgstr "Очаква се цяло число \"%(arg)s\" след \"%(key)s\""
+
+#, python-format
+msgid "Expected a color value \"%(arg)s\" after \"%(key)s\""
+msgstr "Очаква се стойност на цвят \"%(arg)s\" след \"%(key)s\""
+
+msgid "XSLT option disabled, please look at HelpOnConfiguration."
+msgstr "Опцията за XSLT е забранена, моля погледнете ПомощПриКонфигуриране."
+
+msgid "XSLT processing is not available, please install 4suite 1.x."
+msgstr "XSLT обработката не е достъпна, моля инсталирайте 4suite 1.x."
+
+#, python-format
+msgid "%(errortype)s processing error"
+msgstr "грешка %(errortype)s при обработката"
 
 msgid ""
 "Rendering of reStructured text is not possible, please install Docutils."
@@ -851,16 +949,6 @@
 msgid "**Could not find the referenced page: %s**"
 msgstr "**Сочената страница не е открита: %s**"
 
-msgid "XSLT option disabled, please look at HelpOnConfiguration."
-msgstr "Опцията за XSLT е забранена, моля погледнете ПомощПриКонфигуриране."
-
-msgid "XSLT processing is not available, please install 4suite 1.x."
-msgstr "XSLT обработката не е достъпна, моля инсталирайте 4suite 1.x."
-
-#, python-format
-msgid "%(errortype)s processing error"
-msgstr "грешка %(errortype)s при обработката"
-
 #, fuzzy
 msgid ""
 " Emphasis:: <<Verbatim(//)>>''italics''<<Verbatim(//)>>; <<Verbatim(**)"
@@ -896,214 +984,552 @@
 "\n"
 "(!) За повече помощ вижте ПомощПриРедактиране или СинтактичноУпътване.\n"
 
-#, fuzzy
-msgid ""
-" Emphasis:: <<Verbatim('')>>''italics''<<Verbatim('')>>; <<Verbatim(''')"
-">>'''bold'''<<Verbatim(''')>>; <<Verbatim(''''')>>'''''bold "
-"italics'''''<<Verbatim(''''')>>; <<Verbatim('')>>''mixed ''<<Verbatim(''')"
-">>'''''bold'''<<Verbatim(''')>> and italics''<<Verbatim('')>>; <<Verbatim"
-"(----)>> horizontal rule.\n"
-" Headings:: = Title 1 =; == Title 2 ==; === Title 3 ===; ==== Title 4 ====; "
-"===== Title 5 =====.\n"
-" Lists:: space and one of: * bullets; 1., a., A., i., I. numbered items; 1."
-"#n start numbering at n; space alone indents.\n"
-" Links:: <<Verbatim(JoinCapitalizedWords)>>; <<Verbatim([[target|linktext]])"
-">>.\n"
-" Tables:: || cell text |||| cell text spanning 2 columns ||;    no trailing "
-"white space allowed after tables or titles.\n"
-"\n"
-"(!) For more help, see HelpOnEditing or SyntaxReference.\n"
-msgstr ""
-" Наблягане:: <<Verbatim('')>>''наклонен''<<Verbatim('')>>; <<Verbatim(''')"
-">>'''удебелен'''<<Verbatim(''')>>; <<Verbatim(''''')>>'''''удебелен и "
-"наклонен'''''<<Verbatim(''''')>>; <<Verbatim('')>>''смесени ''<<Verbatim(''')"
-">>'''''удебелен'''<<Verbatim(''')>> и наклонен''<<Verbatim('')>>; <<Verbatim"
-"(----)>> хоризонтална черта.\n"
-" Заглавия:: <<Verbatim(=)>> Заглавие 1 <<Verbatim(=)>>; <<Verbatim(==)>> "
-"Заглавие 2 <<Verbatim(==)>>; <<Verbatim(===)>> Заглавие 3 <<Verbatim(===)"
-">>;   <<Verbatim(====)>> Заглавие 4 <<Verbatim(====)>>; <<Verbatim(=====)>> "
-"Заглавие 5 <<Verbatim(=====)>>.\n"
-" Списъци:: интервал и едно от: * bullets; 1., a., A., i., I. номерирани "
-"елементи; 1.#n започва номерирането от n; само интервал вмъква навътре.\n"
-" Връзки:: <<Verbatim(СвързаниДумиПървиБуквиГлавни)>>; <<Verbatim"
-"([\"квадратни скоби и кавички\"])>>; url; [url]; [url етикет].\n"
-" Таблици:: || текст на клетка |||| текст на клетка, заемаща 2 колони ||;    "
-"не е позволено оставянето на празно място след таблици или заглавия.\n"
-"\n"
-"(!) За повече помощ вижте ПомощПриРедактиране или СинтактичноУпътване.\n"
+msgid "Preferences"
+msgstr "Предпочитания"
 
 #, python-format
-msgid "Expected \"%(wanted)s\" after \"%(key)s\", got \"%(token)s\""
-msgstr "Очаква се \"%(wanted)s\" след \"%(key)s\", а е открит \"%(token)s\""
-
-#, python-format
-msgid "Expected an integer \"%(key)s\" before \"%(token)s\""
-msgstr "Очаква се цяло число \"%(key)s\" преди \"%(token)s\""
+msgid ""
+"Invalid user name {{{'%s'}}}.\n"
+"Name may contain any Unicode alpha numeric character, with optional one\n"
+"space between words. Group page name is not allowed."
+msgstr ""
+"Невалидно потребителско име {{{'%s'}}}.\n"
+"Името може да съдържа произволни Unicode букви и цифри, по желание с един\n"
+"интервал между думите. Не е позволено да се използват имена на групови "
+"страници."
+
+msgid "This user name already belongs to somebody else."
+msgstr "Това потребителско име вече принадлежи на някой друг."
+
+msgid "Empty user name. Please enter a user name."
+msgstr "Празно потребителско име. Моля въведете потребителско име."
+
+msgid ""
+"Please provide your email address. If you lose your login information, you "
+"can get it by email."
+msgstr ""
+"Моля въведете Вашия адрес на ел. поща. Ако загубите информацията за сметката "
+"си, то ще можете да я получите по ел. поща."
+
+msgid "This email already belongs to somebody else."
+msgstr "Този ел. поща вече принадлежи на някой друг."
+
+#, fuzzy
+msgid "This jabber id already belongs to somebody else."
+msgstr "Този ел. поща вече принадлежи на някой друг."
 
 #, python-format
-msgid "Expected an integer \"%(arg)s\" after \"%(key)s\""
-msgstr "Очаква се цяло число \"%(arg)s\" след \"%(key)s\""
+msgid "The theme '%(theme_name)s' could not be loaded!"
+msgstr "Темата '%(theme_name)s' не може да бъде заредена!"
+
+msgid "User preferences saved!"
+msgstr "Потребителските настройки са записани!"
+
+msgid "Default"
+msgstr "Подразбиращ се"
+
+msgid "the one preferred"
+msgstr "предпочитания"
+
+msgid "free choice"
+msgstr "свободен избор"
+
+msgid "Save"
+msgstr "Запис"
+
+msgid "Preferred theme"
+msgstr "Предпочитана тема"
+
+msgid "Editor Preference"
+msgstr "Предпочитан редактор"
+
+msgid "Editor shown on UI"
+msgstr "Редактор, показван при бутоните"
+
+msgid "Time zone"
+msgstr "Часова зона"
+
+msgid "Your time is"
+msgstr "Времето при Вас е"
+
+msgid "Server time is"
+msgstr "Времето на сървъра е"
+
+msgid "Date format"
+msgstr "Формат на датата"
+
+msgid "Preferred language"
+msgstr "Предпочитан език"
+
+msgid "General options"
+msgstr "Общи настройки"
+
+msgid "Quick links"
+msgstr "Бързи връзки"
+
+msgid "Switch user"
+msgstr ""
+
+msgid "No user selected"
+msgstr ""
+
+msgid ""
+"You can now change the settings of the selected user account; log out to get "
+"back to your account."
+msgstr ""
+
+msgid "You are the only user."
+msgstr ""
+
+msgid ""
+"As a superuser, you can temporarily assume the identity of another user."
+msgstr ""
+
+msgid "Select User"
+msgstr "Избор на потребител"
+
+#, fuzzy
+msgid "Change password"
+msgstr "Парола"
+
+msgid "Passwords don't match!"
+msgstr "Паролите не съвпадат!"
+
+msgid "Please specify a password!"
+msgstr "Моля въведете парола!"
 
 #, python-format
-msgid "Expected a color value \"%(arg)s\" after \"%(key)s\""
-msgstr "Очаква се стойност на цвят \"%(arg)s\" след \"%(key)s\""
-
-msgid "anonymous"
+msgid "Password not acceptable: %s"
+msgstr ""
+
+msgid "Your password has been changed."
+msgstr ""
+
+msgid "To change your password, enter a new password twice."
+msgstr ""
+
+msgid "Password repeat"
+msgstr "Повторение на паролата"
+
+msgid "Notification"
+msgstr ""
+
+msgid "Notification settings saved!"
 msgstr ""
 
 #, fuzzy
-msgid "Password is too short."
-msgstr "Повторение на паролата"
-
-msgid "Password has not enough different characters."
+msgid "'''Email'''"
+msgstr "ел. поща"
+
+msgid "'''Jabber'''"
 msgstr ""
 
+msgid "'''Event type'''"
+msgstr ""
+
+msgid "Select the events you want to be notified about."
+msgstr ""
+
+msgid ""
+"Before you can be notified, you need to provide a way to contact you in the "
+"general preferences."
+msgstr ""
+
+#, fuzzy
+msgid "Subscribed events"
+msgstr "Абониране на потребител"
+
+#, fuzzy
+msgid "Subscribed wiki pages<<BR>>(one regex per line)"
+msgstr "Абонаменти за уики страници (по един шаблон на ред)"
+
+msgid "OpenID server"
+msgstr ""
+
+msgid "The selected websites have been removed."
+msgstr ""
+
+msgid "Trusted websites"
+msgstr ""
+
+msgid "Remove selected"
+msgstr ""
+
+msgid "OpenID settings"
+msgstr ""
+
+msgid "Cannot remove all OpenIDs."
+msgstr ""
+
+msgid "The selected OpenIDs have been removed."
+msgstr ""
+
+msgid "No OpenID given."
+msgstr ""
+
+msgid "OpenID is already present."
+msgstr ""
+
+#, fuzzy
+msgid "This OpenID is already used for another account."
+msgstr "Тази страница вече е изтрита или никога не е била създавана!"
+
+msgid "OpenID added successfully."
+msgstr ""
+
+msgid "Current OpenIDs"
+msgstr ""
+
+msgid "Add OpenID"
+msgstr ""
+
+msgid "Options --pages and --search are mutually exclusive!"
+msgstr ""
+
+msgid "You must specify an output file!"
+msgstr ""
+
+msgid "No pages specified using --pages or --search, assuming full package."
+msgstr ""
+
+msgid "All attachments included into the package."
+msgstr ""
+
+msgid "Output file already exists! Cowardly refusing to continue!"
+msgstr ""
+
+#, fuzzy
+msgid "Username"
+msgstr "Потребител"
+
+#, fuzzy
+msgid "Member of Groups"
+msgstr "Брой страници"
+
+msgid "Email"
+msgstr "ел. поща"
+
+msgid "Jabber"
+msgstr ""
+
+msgid "Action"
+msgstr "Действие"
+
+#, fuzzy
+msgid "Disable user"
+msgstr "Изключен"
+
+#, fuzzy
+msgid "Enable user"
+msgstr "Включен"
+
+#, fuzzy
+msgid "disabled"
+msgstr "Изключен"
+
+#, fuzzy
+msgid "Mail account data"
+msgstr "Изпрати ми моите данни по пощата"
+
+msgid "OpenID"
+msgstr ""
+
+msgid "Login"
+msgstr "Вход"
+
+#, python-format
+msgid "Local Site Map for \"%s\""
+msgstr "Карта на околността за \"%s\""
+
+msgid "Please log in first."
+msgstr "Моля първо влезе."
+
+msgid "Please first create a homepage before creating additional pages."
+msgstr ""
+"Моля, създайте Ваша домашна страница преди да започнете да създавате други."
+
+#, fuzzy, python-format
+msgid ""
+"You can add some additional sub pages to your already existing homepage "
+"here.\n"
+"\n"
+"You can choose how open to other readers or writers those pages shall be,\n"
+"access is controlled by group membership of the corresponding group page.\n"
+"\n"
+"Just enter the sub page's name and click on the button to create a new "
+"page.\n"
+"\n"
+"Before creating access protected pages, make sure the corresponding group "
+"page\n"
+"exists and has the appropriate members in it. Use HomepageGroupsTemplate for "
+"creating\n"
+"the group pages.\n"
+"\n"
+"||'''Add a new personal page:'''||'''Related access control list "
+"group:'''||\n"
+"||<<NewPage(HomepageReadWritePageTemplate,read-write page,%(username)s)>>||"
+"[[%(username)s/ReadWriteGroup]]||\n"
+"||<<NewPage(HomepageReadPageTemplate,read-only page,%(username)s)>>||[[%"
+"(username)s/ReadGroup]]||\n"
+"||<<NewPage(HomepagePrivatePageTemplate,private page,%(username)s)>>||%"
+"(username)s only||\n"
+"\n"
+msgstr ""
+"Можете да добавите няколко допълнителни подстраници към вашата вече "
+"съществуваща домашна страница тук.\n"
+"\n"
+"Можете да изберете колко отворени за други читатели или писатели да бъдат "
+"те,\n"
+"като достъпът се контролира от принадлежността към съответното име на "
+"група.\n"
+"\n"
+"Просто въведете името на подстраницата и натиснете бутона за създаване на "
+"нова страница.\n"
+"\n"
+"Преди създаване на защитени страници, моля подсигурете се, че съответната "
+"групова страница\n"
+"съществува, и че съответните членове са в нея. Използвайте "
+"ШаблонГрупиДомашниСтраници за създаване\n"
+"на групови страници.\n"
+"\n"
+"||'''Добавяне на нова персонална страница:'''||'''Свързана ACL група:'''||\n"
+"||<<NewPage(HomepageReadWritePageTemplate,read-write page,%(username)s)>>||"
+"[\"%(username)s/ReadWriteGroup\"]||\n"
+"||<<NewPage(HomepageReadPageTemplate,read-only page,%(username)s)>>||[\"%"
+"(username)s/ReadGroup\"]||\n"
+"||<<NewPage(HomepagePrivatePageTemplate,private page,%(username)s)>>||само %"
+"(username)s||\n"
+"\n"
+
+msgid "MyPages management"
+msgstr "Управление на МоитеСтраници"
+
+#, python-format
+msgid "Please use the interactive user interface to use action %(actionname)s!"
+msgstr "Моля, използвайте интерактивния интерфейс за действие %(actionname)s!"
+
+msgid "TextCha: Wrong answer! Go back and try again..."
+msgstr ""
+
+#, fuzzy, python-format
+msgid "You must login to use this action: %(action)s."
+msgstr "Трябва да влезете за да използвате абонаментите."
+
+msgid "You are not allowed to subscribe to a page you can't read."
+msgstr ""
+"Не Ви е позволено да се абонирате за страници, които не можете да четете."
+
+#, fuzzy
+msgid "This wiki is not enabled for mail/Jabber processing."
+msgstr "Това уики не е настроено да обработва поща."
+
+msgid "You must log in to use subscriptions."
+msgstr "Трябва да влезете за да използвате абонаментите."
+
 #, fuzzy
 msgid ""
-"Password is too easy (password contains name or name contains password)."
-msgstr "Липсва парола. Моля, въведете потребителско име и парола."
-
-msgid "Password is too easy (keyboard sequence)."
+"Add your email address or Jabber ID in your user settings to use "
+"subscriptions."
 msgstr ""
-
-msgid "Diffs"
-msgstr "Разлики"
-
-msgid "Info"
-msgstr "Информация"
-
-msgid "Edit"
-msgstr "Редактиране"
-
-msgid "UnSubscribe"
-msgstr "РазАбониране"
-
-msgid "Subscribe"
-msgstr "Абониране"
-
-msgid "Raw"
-msgstr "Суров"
-
-msgid "XML"
-msgstr "XML"
-
-msgid "Print"
-msgstr "Печат"
-
-msgid "View"
-msgstr "Изглед"
-
-msgid "Up"
-msgstr "Нагоре"
-
-msgid "Publish my email (not my wiki homepage) in author info"
-msgstr ""
-"Публикуване на email адресът ми (вместо уики страницата ми) в авторската "
-"информация."
-
-msgid "Open editor on double click"
-msgstr "Отваряне на редактор при двойно кликане"
-
-msgid "After login, jump to last visited page"
-msgstr "Отиване на последната посетена страница след влизане"
-
-msgid "Show comment sections"
-msgstr "Показване на секциите с коментари"
-
-msgid "Show question mark for non-existing pagelinks"
-msgstr "Показване на въпросителни знаци за връзки към несъществуващи страници"
-
-msgid "Show page trail"
-msgstr "Показване на последните посетени страници"
-
-msgid "Show icon toolbar"
-msgstr "Показване на лента с икони"
-
-msgid "Show top/bottom links in headings"
-msgstr "Показване на горните/долните връзки в заглавията"
-
-msgid "Show fancy diffs"
-msgstr "Показване на украсени разлики"
-
-msgid "Add spaces to displayed wiki names"
-msgstr "Добавяне на интервали към показваните уики имена"
-
-msgid "Remember login information"
-msgstr "Запомняне на информацията ми за вход"
-
-msgid "Disable this account forever"
-msgstr "Вечна забрана на тази потребителска сметка"
+"Добавете Ваш email адрес във Вашите ПотребителскиНастройки, за да използвате "
+"абонаментите."
 
 #, fuzzy
-msgid "(Use FirstnameLastname)"
-msgstr "(използвайте Име''''''Фамилия)"
-
-msgid "Alias-Name"
-msgstr "Псевдоним"
-
-msgid "Jabber ID"
+msgid "You are already subscribed to this page."
+msgstr "Бяхте абонирани за тази страница."
+
+msgid "You have been subscribed to this page."
+msgstr "Бяхте абонирани за тази страница."
+
+msgid "You could not get subscribed to this page."
+msgstr "Не можахте да се абонирате за тази страница."
+
+msgid ""
+"Cannot create a new page without a page name.  Please specify a page name."
 msgstr ""
-
-msgid "User CSS URL"
-msgstr "URL на потребителски CSS"
-
-msgid "(Leave it empty for disabling user CSS)"
-msgstr "(Оставете празно за забрана на потребителския CSS)"
-
-msgid "Editor size"
-msgstr "Размер на редактора"
-
-#, python-format
-msgid "Upload new attachment \"%(filename)s\""
-msgstr "Качване на ново приложение \"%(filename)s\""
-
-#, python-format
-msgid "Inlined image: %(url)s"
-msgstr "Вмъкнато изображение: %(url)s"
-
-#, python-format
-msgid "Create new drawing \"%(filename)s (opens in new window)\""
-msgstr "Създаване на нова рисунка \"%(filename)s (отваря се в нов прозорец)\""
+"Не може да се създават нови страници без име.  Моля, укажете име на "
+"страницата."
+
+msgid "Do it."
+msgstr "Направи го."
 
 #, python-format
-msgid "Edit drawing %(filename)s (opens in new window)"
-msgstr "Редакция