* looking for arch@arch.thinkmo.de--2003-archives/moin--main--1.3--patch-730 to compare with
* comparing to arch@arch.thinkmo.de--2003-archives/moin--main--1.3--patch-730
M  MoinMoin/action/rss_rc.py
M  MoinMoin/server/standalone.py
M  MoinMoin/Page.py
M  MoinMoin/multiconfig.py
M  MoinMoin/i18n/__init__.py
M  MoinMoin/request.py
M  MoinMoin/util/datetime.py
M  MoinMoin/wikiaction.py

* modified files

--- orig/MoinMoin/Page.py
+++ mod/MoinMoin/Page.py
@@ -13,6 +13,7 @@
 from MoinMoin import config, caching, user, util, wikiutil
 from MoinMoin.logfile import eventlog
 from MoinMoin.util import filesys, web
+from MoinMoin.util.datetime import formathttpdate
 
 
 # There are many places accessing ACLs even without actually sending
@@ -1068,8 +1069,20 @@
         page_exists = self.exists()
         if not content_only:
             # send the document leader
+
+            # use "nocache" headers if we're using a method that
+            # is not simply "display", or if a user is logged in
+            # (which triggers personalisation features)
+
             if page_exists:
-                request.http_headers()
+                if (request.bust_cache or request.user.valid):
+                    request.http_headers(request.nocache)
+                else:
+                    # use the correct last-modified value from the on-disk file
+                    # to ensure cacheability where supported
+                    request.http_headers(["Last-Modified: " +
+                         formathttpdate(os.path.getmtime(self._text_filename()))]);
+
             else:
                 request.http_headers(['Status: 404 NOTFOUND'])
                 request.setResponseCode(404)


--- orig/MoinMoin/action/rss_rc.py
+++ mod/MoinMoin/action/rss_rc.py
@@ -7,9 +7,10 @@
 
     @license: GNU GPL, see COPYING for details.
 """
-import StringIO, re, os
+import StringIO, re, os, time
 from MoinMoin import wikixml, config, wikiutil, util
 from MoinMoin.logfile import editlog
+from MoinMoin.util.datetime import formathttpdate
 from MoinMoin.Page import Page
 from MoinMoin.wikixml.util import RssGenerator
 
@@ -59,6 +60,7 @@
     logdata = []
     counter = 0
     pages = {}
+    lastmod = 0
     for line in log.reverse():
         if not request.user.may.read(line.pagename):
             continue
@@ -69,6 +71,10 @@
         line.time = util.datetime.tmtuple(wikiutil.version2timestamp(line.ed_time_usecs)) # UTC
         logdata.append(line)
         pages[line.pagename] = None
+
+        if not lastmod:
+            lastmod = wikiutil.version2timestamp(line.ed_time_usecs)
+
         counter += 1
         if counter >= max_items:
             break
@@ -197,8 +203,20 @@
     # end SAX stream
     handler.endDocument()
 
+    # generate an Expires header, using whatever setting the admin
+    # defined for suggested cache lifetime of the RecentChanges RSS doc
+    expires = formathttpdate(time.time() + cfg.rss_cache)
+
+    httpheaders = ["Content-Type: text/xml; charset=%s" % config.charset,
+                        "Expires: "+expires]
+
+    # use a correct Last-Modified header, set to whatever the mod date
+    # on the most recent page was; if there were no mods, don't send one
+    if lastmod:
+        httpheaders.append("Last-Modified: "+formathttpdate(lastmod))
+
     # send the generated XML document
-    request.http_headers(["Content-Type: text/xml; charset=%s" % config.charset] + request.nocache)
+    request.http_headers(httpheaders)
     request.write(out.getvalue())
     request.finish()
     request.no_closing_html_code = 1


--- orig/MoinMoin/i18n/__init__.py
+++ mod/MoinMoin/i18n/__init__.py
@@ -204,6 +204,8 @@
     available = wikiLanguages()
     for lang in browserLanguages(request):
         if available.has_key(lang):
+            if request.http_accept_language:
+                request.setHttpHeader('Vary: Accept-Language')
             return lang
     
     # Or return the wiki default language...


--- orig/MoinMoin/multiconfig.py
+++ mod/MoinMoin/multiconfig.py
@@ -240,6 +240,7 @@
         'up':          ("%(q_page_parent_page)s", _("Up"), "up"),
         }
     refresh = None # (minimum_delay, type), e.g.: (2, 'internal')
+    rss_cache = 60 # suggested caching time for RecentChanges RSS, in seconds
     shared_intermap = None # can be string or list of strings (filenames)
     show_hosts = 1
     show_section_numbers = 1


--- orig/MoinMoin/request.py
+++ mod/MoinMoin/request.py
@@ -71,6 +71,7 @@
                     
         self.sent_headers = 0
         self.user_headers = []
+        self.bust_cache = 0
         self.page = None
 
         # Fix dircaching problems on Windows 9x


--- orig/MoinMoin/server/standalone.py
+++ mod/MoinMoin/server/standalone.py
@@ -35,12 +35,12 @@
 # Imports
 import os, signal, sys, time, urllib, socket, errno
 import BaseHTTPServer, SimpleHTTPServer, SocketServer
-from email.Utils import formatdate
 
 # MoinMoin imports
 from MoinMoin import version
 from MoinMoin.server import Config, switchUID
 from MoinMoin.request import RequestStandAlone
+from MoinMoin.util.datetime import formathttpdate
 
 # Set threads flag, so other code can use proper locking
 from MoinMoin import config
@@ -204,7 +204,7 @@
         if self.expires:
             now = time.time()
             expires = now + self.expires
-            self.send_header('Expires', formatdate(expires))
+            self.send_header('Expires', formathttpdate(expires))
         SimpleHTTPServer.SimpleHTTPRequestHandler.end_headers(self)
         
 


--- orig/MoinMoin/util/datetime.py
+++ mod/MoinMoin/util/datetime.py
@@ -8,7 +8,8 @@
 
 # we guarantee that time is always imported!
 import time
-
+import re
+from email.Utils import formatdate
 
 def tmtuple(tmsecs=None):
     """ Return a time tuple.
@@ -20,3 +21,12 @@
         tmsecs = 0                # 0 initially, so reset it to 0.
     return time.gmtime(tmsecs or time.time())
 
+def formathttpdate(tmsecs=None):
+    """ Return a HTTP date/time stamp as defined in
+        http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3 .
+    """
+    stamp = formatdate(tmsecs, False)
+    # replace non-standard "-0000" at end with http-mandated "GMT"
+    stamp = re.match('^(.*) [\-\+]0000$', stamp).group(1) + " GMT"
+    return stamp
+


--- orig/MoinMoin/wikiaction.py
+++ mod/MoinMoin/wikiaction.py
@@ -30,6 +30,7 @@
 #############################################################################
 
 def do_diff(pagename, request):
+    request.bust_cache = 1
     """ Handle "action=diff"
         checking for either a "rev=formerrevision" parameter
         or rev1 and rev2 parameters
@@ -194,6 +195,7 @@
 
 
 def do_info(pagename, request):
+    request.bust_cache = 1
     if not request.user.may.read(pagename):
         Page(request, pagename).send_page(request)
         return
@@ -426,6 +428,7 @@
 
 
 def do_recall(pagename, request):
+    request.bust_cache = 1
     # We must check if the current page has different ACLs.
     if not request.user.may.read(pagename):
         Page(request, pagename).send_page(request)
@@ -464,6 +467,7 @@
 
 
 def do_refresh(pagename, request):
+    request.bust_cache = 1
     """ Handle refresh action """
     # Without arguments, refresh action will refresh the page text_html
     # cache.
@@ -480,10 +484,12 @@
 
 
 def do_print(pagename, request):
+    request.bust_cache = 1
     do_show(pagename, request)
 
 
 def do_content(pagename, request):
+    request.bust_cache = 1
     request.http_headers()
     page = Page(request, pagename)
     request.write('<!-- Transclusion of %s -->' % request.getQualifiedURL(page.url(request)))
@@ -492,6 +498,7 @@
 
 
 def do_edit(pagename, request):
+    request.bust_cache = 1
     if not request.user.may.write(pagename):
         _ = request.getText
         Page(request, pagename).send_page(request,
@@ -502,6 +509,7 @@
 
 
 def do_revert(pagename, request):
+    request.bust_cache = 1
     from MoinMoin.PageEditor import PageEditor
     _ = request.getText
 
@@ -525,6 +533,7 @@
     return None
 
 def do_savepage(pagename, request):
+    request.bust_cache = 1
     from MoinMoin.PageEditor import PageEditor
 
     _ = request.getText
@@ -639,6 +648,7 @@
         
 
 def do_subscribe(pagename, request):
+    request.bust_cache = 1
     """ Add the current wiki page to the subscribed_page property in
         current user profile.
     """
@@ -683,11 +693,13 @@
 
 
 def do_userform(pagename, request):
+    request.bust_cache = 1
     from MoinMoin import userform
     savemsg = userform.savedata(request)
     Page(request, pagename).send_page(request, msg=savemsg)
 
 def do_bookmark(pagename, request):
+    request.bust_cache = 1
     if request.form.has_key('time'):
         if request.form['time'][0] == 'del':
             tm = None
@@ -707,6 +719,7 @@
   
 
 def do_formtest(pagename, request):
+    request.bust_cache = 1
     # test a user defined form
     from MoinMoin import wikiform
     wikiform.do_formtest(pagename, request)
@@ -735,6 +748,7 @@
 #############################################################################
 
 def do_raw(pagename, request):
+    request.bust_cache = 1
     if not request.user.may.read(pagename):
         Page(request, pagename).send_page(request)
         return
@@ -761,6 +775,7 @@
 
 
 def do_format(pagename, request):
+    request.bust_cache = 1
     # get the MIME type
     if request.form.has_key('mimetype'):
         mimetype = request.form['mimetype'][0]
@@ -785,6 +800,7 @@
 
 
 def do_chart(pagename, request):
+    request.bust_cache = 1
     if request.user.may.read(pagename) and request.cfg.chart_options:
         chart_type = request.form['type'][0]
         func = pysupport.importName("MoinMoin.stats." + chart_type, "draw")
@@ -793,6 +809,7 @@
 
 
 def do_dumpform(pagename, request):
+    request.bust_cache = 1
     data = util.dumpFormData(request.form)
 
     request.http_headers()
@@ -801,6 +818,7 @@
 
 
 def do_export(pagename, request):
+    request.bust_cache = 1
     import shutil, StringIO
     from MoinMoin.wikixml import wikiexport
 
@@ -840,6 +858,7 @@
 
 
 def do_test(pagename, request):
+    request.bust_cache = 1
     from MoinMoin.wikitest import runTest
     request.http_headers(["Content-type: text/plain;charset=%s" % config.charset])
     request.write('MoinMoin Diagnosis\n======================\n\n')



