/usr/share/forg/Cache.py is in forg 0.5.1-7.2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 | # Cache.py
# $Id: Cache.py,v 1.14 2001/07/14 22:50:28 s2mdalle Exp $
# Written by David Allen <mda@idatar.com>
# Released under the terms of the GNU General Public License
#
# Handles cache-file related operations.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
############################################################################
import os
import utils
import string
from gopher import *
from Tkinter import *
import GopherResponse
import Pmw
import Options
CacheException = "Error"
class Cache:
verbose = None
def __init__(self, *args):
self._d = None
return None
def getCacheDirectory(self):
try:
dir = Options.program_options.getOption('cache_directory')
return os.path.abspath(dir)
except:
return os.path.abspath("cache")
def getCachePrefix(self):
try:
dir = Options.program_options.getOption('cache_prefix')
return os.path.abspath(dir)
except:
return os.path.abspath("cache%scache" % os.sep)
def getCacheStats(self):
cdir = self.getCacheDirectory()
[filecount, totalBytes, dircount] = utils.summarize_directory(cdir)
kbcount = float(totalBytes)/float(1024)
mbcount = kbcount/float(1024)
kbcount = "%0.2fKB" % kbcount
mbcount = "%0.2fMB" % mbcount
datasize = "There is %s (%s) of data" % (kbcount, mbcount)
fdcount = "in %s files (%s directories total)" % (filecount, dircount)
closer = "underneath %s" % cdir
return "%s\n%s\n%s" % (datasize, fdcount, closer)
def emptyCache(self, parentTk):
pref = self.getCachePrefix()
self.dialog = Pmw.Dialog(parent=parentTk,
title="Really delete cache?",
buttons=('OK', 'Cancel'),
defaultbutton='Cancel',
command=self.__confirmDelete)
fr = Frame(self.dialog.interior())
fr.pack(side='top', fill='both', expand=1)
lab1 = Label(fr, text="Are you sure you want to empty the cache?")
lab2 = Label(fr, text="WARNING: THIS WILL DELETE ALL FILES AND")
lab3 = Label(fr, text="ALL SUBDIRECTORIES IN YOUR CACHE DIRECTORY,")
lab4 = Label(fr, text="%s" % pref)
lab5 = Label(fr, text=" ")
lab6 = Label(fr, text="Continue?")
lab1.grid(row=1, column=0, columnspan=5)
lab2.grid(row=2, column=0, columnspan=5)
lab3.grid(row=3, column=0, columnspan=5)
lab4.grid(row=4, column=0, columnspan=5)
lab5.grid(row=5, column=0, columnspan=5)
lab6.grid(row=6, column=0, columnspan=5)
# self.dialog.activate()
def deleteCacheNoPrompt(self, *args):
"""Delete the cache without asking the user. Do not do this unless
you know what you're doing."""
return self.__deleteCache()
def __confirmDelete(self, button):
if button != 'OK':
self.dialog.destroy()
return None
self.dialog.destroy() # Destroy the dialog anyway
self.__deleteCache() # Clean the files out
return None
def __deleteCache(self):
pref = self.getCachePrefix()
if not utils.dir_exists(pref):
raise CacheException, "Cache prefix %s doesn't exist." % pref
cache_directories = os.listdir(pref)
# I've been told that there's a shell utility module that does this
# probably safer and better, but I'm not sure where it is, or whether
# or not it's portable to crappy no-name 32 bit operating systems
# out of Redmond, Washington.
for item in cache_directories:
item = "%s%s%s" % (pref, os.sep, item)
if os.path.isdir(item):
print "Recursively deleting \"%s\"" % item
utils.recursive_delete(item)
else:
print "Eh? \"%s\" isn't a directory. That's odd..." % item
def isInCache(self, resource):
"""Takes a resource, and returns true if the resource seems to have
an available cache file associated with it, and None otherwise."""
pref = self.getCachePrefix()
filename = resource.toCacheFilename()
if pref[len(pref)-1] != os.sep and filename[0] != os.sep:
# When joining together, separate paths with os.sep
pref = "%s%s" % (pref, os.sep)
# Now join together, and they will be properly joined.
filename = pref + filename
try:
info = os.stat(os.path.abspath(filename))
return [os.path.abspath(filename), info[6]]
except OSError:
return None
return None
def uncache(self, resource):
"""Takes a resource, and returns either None if the given resource
is not cached on disk, or it returns a GopherResponse corresponding
to what would have been gotten if it had been fetched from the
server."""
pref = self.getCachePrefix()
file = resource.toCacheFilename()
if pref[len(pref)-1] != os.sep and file[0] != os.sep:
# When joining together, separate paths with os.sep
pref = "%s%s" % (pref, os.sep)
filename = pref + file
try:
# See if the file exists...
tuple = os.stat(filename)
if self.verbose:
print "File %s of size %d exists." % (filename, tuple[6])
except OSError:
# The file doesn't exist, we can't uncache it.
return None
print "===> Uncaching \"%s\"" % filename
resp = GopherResponse.GopherResponse()
resp.setType(resource.getTypeCode())
resp.setHost(resource.getHost())
resp.setPort(resource.getPort())
resp.setLocator(resource.getLocator())
resp.setName(resource.getName())
try:
fp = open(filename, "r")
# Consider reworking this somehow. Slurp the entire file into
# buffer.
buffer = fp.read()
fp.close()
try:
resp.parseResponse(buffer)
resp.setData(None)
# print "Loaded cache is a directory entry."
except:
# print "Loaded cache is not a directory."
resp.setData(buffer)
# Got it! Loaded from cache anyway...
# print "UNCACHE found data for use."
return resp
except IOError, errstr:
raise CacheException, "Couldn't read data on\n%s:\n%s" % (filename,
errstr)
# We failed. Oh well...
return None
def cache(self, resp, resource):
"""Takes a GopherResponse and a GopherResource. Saves the content of
the response to disk, and returns the filename saved to."""
if resource.isAskType():
# Don't cache ASK blocks. This is because if you do, the program
# will interpret it as data, and put the question structure inside
# a text box. Plus, since these may be dynamic, caching could
# lead to missing out on things.
raise CacheException, "Do not cache AskTypes. Not a good idea."
basedir = self.getCachePrefix()
basefilename = resource.toCacheFilename()
# Problem - basedir is our base directory, but basefilename contains
# trailing filename info that shouldn't be part of the directories
# we're creating.
filenamecopy = basefilename[:]
ind = string.rfind(filenamecopy, os.sep)
# Chop off extra info so "/home/x/foobar" becomes "/home/x/foobar"
# this is because make_directories will otherwise create foobar as
# a directory when it's actually a filename
filenamecopy = filenamecopy[0:ind]
# Create the directory structure where necessary
utils.make_directories(filenamecopy, basedir)
basedirlastchar = basedir[len(basedir)-1]
if basedirlastchar == os.sep:
filename = "%s%s" % (basedir, basefilename)
else:
filename = "%s%s%s" % (basedir, os.sep, basefilename)
# print "Cache: caching data to \"%s\"" % filename
try:
fp = open(filename, "w")
if resp.getData() == None: # This is a directory entry.
response_lines = resp.getResponses()
# Each response line is a GopherResource
# write them as if it was a file served by the gopher server.
# that way it can be easily reparsed when loaded from the
# cache.
for response_line in response_lines:
fp.write(response_line.toProtocolString())
# write the string terminator. This isn't really needed
# since it isn't data, but it helps fool our other objects
# into thinking that it's dealing with data off of a socket
# instead of data from a file. So do it.
fp.write("\r\n.\r\n")
else:
fp.write(resp.getData())
fp.flush()
fp.close()
except IOError, errstr:
# Some error writing data to the file. Bummer.
raise CacheException, "Couldn't write to\n%s:\n%s" % (filename,
errstr)
# Successfully wrote the data - return the filename that was used
# to save the data into. (Absolute path)
return os.path.abspath(filename)
|