diff -r e4c4ee9e3abc MoinMoin/Page.py
--- a/MoinMoin/Page.py	Sun Jul 06 08:07:40 2008 +0200
+++ b/MoinMoin/Page.py	Sun Jul 06 08:28:15 2008 +0200
@@ -1079,6 +1079,7 @@
                 request.setHttpHeader("Content-Type: %s; charset=%s" % (self.output_mimetype, self.output_charset))
                 if page_exists:
                     if not request.user.may.read(self.page_name):
+                        logging.info(u'Error 403: User "%s" is not allowed to read the page "%s(page_name)s"' % {'user': request.user.name, 'page_name': self.page_name})
                         request.setHttpHeader('Status: 403 Permission Denied')
                     else:
                         request.setHttpHeader('Status: 200 OK')
@@ -1096,6 +1097,7 @@
                         #request.setHttpHeader("Last-Modified: %s" % util.timefuncs.formathttpdate(lastmod))
                         pass
                 else:
+                    logging.info(u'Error 404: Page "%(page_name)s" does not exists.' % {'page_name': self.page_name})
                     request.setHttpHeader('Status: 404 NOTFOUND')
                 request.emit_http_headers()
 
diff -r e4c4ee9e3abc MoinMoin/action/edit.py
--- a/MoinMoin/action/edit.py	Sun Jul 06 08:07:40 2008 +0200
+++ b/MoinMoin/action/edit.py	Sun Jul 06 08:28:15 2008 +0200
@@ -16,8 +16,7 @@
     _ = request.getText
 
     if 'button_preview' in request.form and 'button_spellcheck' in request.form:
-        # multiple buttons pressed at once? must be some spammer/bot
-        request.makeForbidden403()
+        request.makeForbidden(403, u'Multiple buttons pressed at once. Maybe a spammer/bot!')
         request.surge_protect(kick_him=True) # get rid of him
         return
 
diff -r e4c4ee9e3abc MoinMoin/action/fullsearch.py
--- a/MoinMoin/action/fullsearch.py	Sun Jul 06 08:07:40 2008 +0200
+++ b/MoinMoin/action/fullsearch.py	Sun Jul 06 08:28:15 2008 +0200
@@ -60,7 +60,7 @@
     _ = request.getText
     titlesearch = checkTitleSearch(request)
     if titlesearch < 0:
-        request.makeForbidden403()
+        request.makeForbidden(403, u'Spammer try to press text and title search at once!')
         request.surge_protect(kick_him=True) # get rid of spammer
         return
 
diff -r e4c4ee9e3abc MoinMoin/action/newaccount.py
--- a/MoinMoin/action/newaccount.py	Sun Jul 06 08:07:40 2008 +0200
+++ b/MoinMoin/action/newaccount.py	Sun Jul 06 08:28:15 2008 +0200
@@ -167,7 +167,7 @@
 
     if not found:
         # we will not have linked, so forbid access
-        request.makeForbidden403()
+        request.makeForbidden(403, u'Missconfiguration of authentication (HelpOnAuthentication)!')
         return
 
     page = Page(request, pagename)
diff -r e4c4ee9e3abc MoinMoin/action/recoverpass.py
--- a/MoinMoin/action/recoverpass.py	Sun Jul 06 08:07:40 2008 +0200
+++ b/MoinMoin/action/recoverpass.py	Sun Jul 06 08:28:15 2008 +0200
@@ -147,7 +147,7 @@
 
     if not found:
         # we will not have linked, so forbid access
-        request.makeForbidden403()
+        request.makeForbidden(403, u'Missconfiguration of authentication (HelpOnAuthentication)!')
         return
 
     page = Page(request, pagename)
diff -r e4c4ee9e3abc MoinMoin/action/serveopenid.py
--- a/MoinMoin/action/serveopenid.py	Sun Jul 06 08:07:40 2008 +0200
+++ b/MoinMoin/action/serveopenid.py	Sun Jul 06 08:28:15 2008 +0200
@@ -184,7 +184,7 @@
             # since we didn't put any openid.server into
             # the page to start with, this is someone trying
             # to abuse us. No need to give a nice error
-            request.makeForbidden403()
+            request.makeForbidden(403, 'OpenID server support disabled!')
             return
 
         server_url = request.getQualifiedURL(
@@ -206,8 +206,7 @@
             username = request.user.name
         elif identity is not None:
             if not self._verify_endpoint_identity(identity):
-                request.makeForbidden403()
-                request.write('verification failed')
+                request.makeForbidden(403, 'OpenID verification failed!')
                 return
 
         if 'openid.user' in request.page.pi:
@@ -236,8 +235,7 @@
                 return
 
             if openidreq is None:
-                request.makeForbidden403()
-                request.write('no request')
+                request.makeForbidden(403, 'There is no OpenID request!')
                 return
 
             if request.user.valid and username != request.user.name:
@@ -268,14 +266,12 @@
         # use empty string if nothing was sent
         form_nonce = form.get('nonce', [''])[0]
         if session_nonce != form_nonce:
-            self.request.makeForbidden403()
-            self.request.write('invalid nonce')
+            self.request.makeForbidden(403, 'Invalid OpenID nonce!')
             return None
 
         openidreq = request.session.get('openidserver.request')
         if not openidreq:
-            request.makeForbidden403()
-            request.write('no response request')
+            request.makeForbidden(403, 'No OpenID response request!')
             return None
         del request.session['openidserver.request']
 
diff -r e4c4ee9e3abc MoinMoin/request/__init__.py
--- a/MoinMoin/request/__init__.py	Sun Jul 06 08:07:40 2008 +0200
+++ b/MoinMoin/request/__init__.py	Sun Jul 06 08:28:15 2008 +0200
@@ -152,7 +152,7 @@
         # not on external non-Apache servers
         self.forbidden = False
         if self.request_uri.startswith('http://'):
-            self.makeForbidden403()
+            self.makeForbidden(403, u'Request URI %(request_uri)s starts with http://!' % {'request_uri': self.request_uri})
 
         # Init
         else:
@@ -165,7 +165,7 @@
             try:
                 self._load_multi_cfg()
             except error.NoConfigMatchedError:
-                self.makeForbidden(404, 'No wiki configuration matching the URL found!\r\n')
+                self.makeForbidden(404, u'No wiki configuration matching the URL found!')
                 return
 
             self.isSpiderAgent = self.check_spider()
@@ -184,7 +184,7 @@
                 try:
                     self.args = self.form = self.setup_args()
                 except UnicodeError:
-                    self.makeForbidden(403, "The input you sent could not be understood.")
+                    self.makeForbidden(403, u'The input you sent could not be understood!')
                     return
                 self.action = self.form.get('action', ['show'])[0]
                 try:
@@ -233,7 +233,7 @@
 
             if self.action != 'xmlrpc':
                 if not self.forbidden and self.isForbidden():
-                    self.makeForbidden403()
+                    self.makeForbidden(403, u'Remote request is forbidden by configuration or spider detected!')
                 if not self.forbidden and self.surge_protect():
                     self.makeUnavailable503()
 
@@ -1040,17 +1040,18 @@
             action != 'sitemap'
             ):
             forbidden = self.isSpiderAgent
+            logging.info("Query %(query_string)s with request method %(request_method)s and action %(action)s detected as spider which is forbidden." % {'query_string': qs, 'request_method': self.request_method, 'action': action})
 
         if not forbidden and self.cfg.hosts_deny:
             ip = self.remote_addr
             for host in self.cfg.hosts_deny:
                 if host[-1] == '.' and ip.startswith(host):
                     forbidden = 1
-                    logging.debug("hosts_deny (net): %s" % str(forbidden))
+                    logging.info("Remote address %(remote_addr)s match %(host_deny) which is forbidden." % {'remote_addr': self.remote_addr, 'host_deny': host})
                     break
                 if ip == host:
                     forbidden = 1
-                    logging.debug("hosts_deny (ip): %s" % str(forbidden))
+                    logging.info("Remote address %(remote_addr)s match %(host_deny) which is forbidden." % {'remote_addr': self.remote_addr, 'host_deny': host})
                     break
         return forbidden
 
@@ -1155,21 +1156,21 @@
             'Status: %d %s' % (resultcode, statusmsg[resultcode]),
             'Content-Type: text/plain; charset=utf-8'
         ]
+        if resultcode == 403 and msg == None:
+            msg = u'You are not allowed to access this!'
+        logging.info('Error %d: %s' % (resultcode, statusmsg[resultcode], msg,))
         # when surge protection triggered, tell bots to come back later...
         if resultcode == 503:
             headers.append('Retry-After: %d' % self.cfg.surge_lockout_time)
         self.emit_http_headers(headers)
-        self.write(msg)
+        self.write(msg + u'\r\n')
         self.forbidden = True
-
-    def makeForbidden403(self):
-        self.makeForbidden(403, 'You are not allowed to access this!\r\n')
 
     def makeUnavailable503(self):
         self.makeForbidden(503, "Warning:\r\n"
                    "You triggered the wiki's surge protection by doing too many requests in a short time.\r\n"
                    "Please make a short break reading the stuff you already got.\r\n"
-                   "When you restart doing requests AFTER that, slow down or you might get locked out for a longer time!\r\n")
+                   "When you restart doing requests AFTER that, slow down or you might get locked out for a longer time!")
 
     def initTheme(self):
         """ Set theme - forced theme, user theme or wiki default """
