1 # -*- coding: iso-8859-1 -*- 2 """ 3 MoinMoin - MoinRemoteSupport library 4 5 @copyright: 2011, 2012, 2013 by Paul Boddie <paul@boddie.org.uk> 6 @license: GNU GPL (v2 or later), see COPYING.txt for details. 7 """ 8 9 from ContentTypeSupport import getContentTypeAndEncoding 10 from MoinMoin.action import cache 11 from MoinMoin import caching 12 import urllib2, time 13 14 def getCachedResource(request, url, arena, scope, max_cache_age): 15 16 """ 17 Using the given 'request', return the resource data for the given 'url', 18 accessing a cache entry with the given 'arena' and 'scope' where the data 19 has already been downloaded. The 'max_cache_age' indicates the length in 20 seconds that a cache entry remains valid. 21 22 If the resource cannot be downloaded and cached, None is returned. 23 Otherwise, the form of the data is as follows: 24 25 url <newline> 26 [ content-type-header ] <newline> 27 [ other-header <newline> ]* 28 <newline> 29 content-body 30 """ 31 32 # See if the URL is cached. 33 34 cache_key = cache.key(request, content=url) 35 cache_entry = caching.CacheEntry(request, arena, cache_key, scope=scope) 36 37 # If no entry exists, or if the entry is older than the specified age, 38 # create one with the response from the URL. 39 40 now = time.time() 41 mtime = cache_entry.mtime() 42 43 # NOTE: The URL could be checked and the 'If-Modified-Since' header 44 # NOTE: (see MoinMoin.action.pollsistersites) could be checked. 45 46 if not cache_entry.exists() or now - mtime >= max_cache_age: 47 48 # Access the remote data source. 49 50 cache_entry.open(mode="w") 51 52 try: 53 f = urllib2.urlopen(url) 54 try: 55 cache_entry.write(url + "\n") 56 cache_entry.write((f.headers.get("content-type") or "") + "\n") 57 for key, value in f.headers.items(): 58 if key.lower() != "content-type": 59 cache_entry.write("%s: %s\n" % (key, value)) 60 cache_entry.write("\n") 61 cache_entry.write(f.read()) 62 finally: 63 cache_entry.close() 64 f.close() 65 66 # In case of an exception, return None. 67 68 except IOError: 69 if cache_entry.exists(): 70 cache_entry.remove() 71 return None 72 73 # Open the cache entry and read it. 74 75 cache_entry.open() 76 try: 77 return cache_entry.read() 78 finally: 79 cache_entry.close() 80 81 def getCachedResourceMetadata(f): 82 83 "Return a metadata dictionary for the given resource file-like object 'f'." 84 85 url = f.readline() 86 content_type, encoding = getContentTypeAndEncoding(f.readline()) 87 88 metadata = {} 89 line = f.readline() 90 91 while line.strip(): 92 key, value = [v.strip() for v in line.split(":", 1)] 93 metadata[key] = value 94 line = f.readline() 95 96 return url, content_type, encoding, metadata 97 98 # vim: tabstop=4 expandtab shiftwidth=4