--- index.cgi 2011-09-06 17:47:32.000000000 -0500 +++ index-cache.cgi 2011-09-07 06:37:51.000000000 -0500 @@ -136,15 +136,34 @@ # Encode parameters in utf-8 before passing to standard functions. def utf8_exists(filename): - return path.exists(filename.encode('utf-8')) + # If the item exists, depend on it + # If the item does not exist, dependon the directory + # cache.cgi requires that the thing listed in dep exist, and for the file + # that didn't exist to start existing, the directory must change + result = path.exists(filename.encode('utf-8')) + if result: + dependencies[filename.encode('utf-8')] = 1 + else: + filename = os.path.dirname(filename) + dependencies[filename.encode('utf-8')] = 1 + return result def utf8_isdir(filename): + # Depend on the containing directory + # If item doesn't exist, this is necessary---cache.cgi requires that things + # listed in dep exist. If it does exist, it's OK, because something can't + # change from existing as one kind of thing to not existing without changing + # the directory timestamp, and likewise for changing between file and + # directory. + dependencies[os.path.dirname(filename.encode('utf-8'))] = 1 return path.isdir(filename.encode('utf-8')) def utf8_isfile(filename): + dependencies[os.path.dirname(filename).encode('utf-8')] = 1 return path.isfile(filename.encode('utf-8')) def utf8_listdir(filename): + dependencies[filename.encode('utf-8')] = 1 result = os.listdir(filename.encode('utf-8')) for i in xrange(len(result)): @@ -165,9 +184,11 @@ os.rmdir(dir.encode('utf-8')) def utf8_open(filename, mode): + dependencies[filename.encode('utf-8')] = 1 return __builtins__.open(filename.encode('utf-8'), mode) def utf8_gzip_open(filename, *args): + dependencies[filename.encode('utf-8')] = 1 import gzip return gzip.open(filename.encode('utf-8'), *args) @@ -180,7 +201,13 @@ Do not communicate with Apache while the lock is held, as network traffic can take arbitrary time. """ - filename = (data_dir+u'/_lock').encode('utf-8') + lockdir = (data_dir+u'/_lock').encode('utf-8') + filename = lockdir + "/lock" + + try: + os.mkdir(lockdir) + except: + pass try: begin = os.stat(filename).st_mtime @@ -208,7 +235,9 @@ def unlock(): """ Release lock on access to files. """ - utf8_rmdir(data_dir+u'/_lock') + lockdir = (data_dir+u'/_lock').encode('utf-8') + filename = lockdir + "/lock" + utf8_rmdir(filename) @@ -235,6 +264,8 @@ """ Ensure a directory exists, move file out of way if necessary. (rename to dir/_index). """ + dir = dir.rstrip("/") + if utf8_isdir(dir): return @@ -1982,7 +2013,17 @@ fields = cgi.FieldStorage() query = decode_fields(fields) - sys.stdout.write(perform_request(name, query).encode('utf-8')) + result = perform_request(name, query).encode('utf-8') + + if (os.environ.get('REQUEST_METHOD', '') in ['GET', 'HEAD'] and + (not os.environ.get('QUERY_STRING')) + and (result.startswith("Status: 200\n") or not result.startswith("Status:"))): + depstr = "\0".join(dependencies.keys()) + depdir = os.path.join( cache_dir, (name or '__index__').strip("/") ) + ensure_dir_exists( depdir ) + + open(os.path.join(depdir, "_cache"), "wb").write(depstr + "\0\0" + result) + sys.stdout.write( result ) if __name__ == '__main__': @@ -2008,11 +2053,14 @@ script_filename = path.join(os.getcwd().decode('utf-8'), sys.argv[0].decode('utf-8')) - file_dir = '/var/www/emergent/index.cgi-files' - data_dir = '/var/www/emergent/index.cgi-data' + aether_base = os.environ.get('AETHER_BASE', script_filename) + data_dir = aether_base + u'-data' + file_dir = aether_base + u'-files' + cache_dir = aether_base + u'-cache' + dependencies = {} host_url = 'http://' + os.environ.get('HTTP_HOST','').decode('utf-8') media_url = 'http://media.unpythonic.net/emergent-files/' script_base = os.environ.get('SCRIPT_NAME','').decode('utf-8') or "/" file_base = '/files'