| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401 |
- #written by John Hoffman
- from inifile import ini_write, ini_read
- from bencode import bencode, bdecode
- from types import IntType, LongType, StringType, FloatType
- from CreateIcons import GetIcons, CreateIcon
- from parseargs import defaultargs
- from __init__ import product_name, version_short
- import sys,os
- from time import time, strftime
- try:
- True
- except:
- True = 1
- False = 0
- try:
- realpath = os.path.realpath
- except:
- realpath = lambda x:x
- OLDICONPATH = os.path.abspath(os.path.dirname(realpath(sys.argv[0])))
- DIRNAME = '.'+product_name
- hexchars = '0123456789abcdef'
- hexmap = []
- revmap = {}
- for i in xrange(256):
- x = hexchars[(i&0xF0)/16]+hexchars[i&0x0F]
- hexmap.append(x)
- revmap[x] = chr(i)
- def tohex(s):
- r = []
- for c in s:
- r.append(hexmap[ord(c)])
- return ''.join(r)
- def unhex(s):
- r = [ revmap[s[x:x+2]] for x in xrange(0, len(s), 2) ]
- return ''.join(r)
- def copyfile(oldpath, newpath): # simple file copy, all in RAM
- try:
- f = open(oldpath,'rb')
- r = f.read()
- success = True
- except:
- success = False
- try:
- f.close()
- except:
- pass
- if not success:
- return False
- try:
- f = open(newpath,'wb')
- f.write(r)
- except:
- success = False
- try:
- f.close()
- except:
- pass
- return success
- class ConfigDir:
- ###### INITIALIZATION TASKS ######
- def __init__(self, config_type = None):
- self.config_type = config_type
- if config_type:
- config_ext = '.'+config_type
- else:
- config_ext = ''
- def check_sysvars(x):
- y = os.path.expandvars(x)
- if y != x and os.path.isdir(y):
- return y
- return None
- for d in ['${APPDATA}', '${HOME}', '${HOMEPATH}', '${USERPROFILE}']:
- dir_root = check_sysvars(d)
- if dir_root:
- break
- else:
- dir_root = os.path.expanduser('~')
- if not os.path.isdir(dir_root):
- dir_root = os.path.abspath(os.path.dirname(sys.argv[0]))
- dir_root = os.path.join(dir_root,DIRNAME)
- self.dir_root = dir_root
- if not os.path.isdir(self.dir_root):
- os.mkdir(self.dir_root,0700) # exception if failed
- self.dir_icons = os.path.join(dir_root,'icons')
- if not os.path.isdir(self.dir_icons):
- os.mkdir(self.dir_icons)
- for icon in GetIcons():
- i = os.path.join(self.dir_icons,icon)
- if not os.path.exists(i):
- if not copyfile(os.path.join(OLDICONPATH,icon),i):
- CreateIcon(icon,self.dir_icons)
- self.dir_torrentcache = os.path.join(dir_root,'torrentcache')
- if not os.path.isdir(self.dir_torrentcache):
- os.mkdir(self.dir_torrentcache)
- self.dir_datacache = os.path.join(dir_root,'datacache')
- if not os.path.isdir(self.dir_datacache):
- os.mkdir(self.dir_datacache)
- self.dir_piececache = os.path.join(dir_root,'piececache')
- if not os.path.isdir(self.dir_piececache):
- os.mkdir(self.dir_piececache)
- self.configfile = os.path.join(dir_root,'config'+config_ext+'.ini')
- self.statefile = os.path.join(dir_root,'state'+config_ext)
- self.TorrentDataBuffer = {}
- ###### CONFIG HANDLING ######
- def setDefaults(self, defaults, ignore=[]):
- self.config = defaultargs(defaults)
- for k in ignore:
- if self.config.has_key(k):
- del self.config[k]
- def checkConfig(self):
- return os.path.exists(self.configfile)
- def loadConfig(self):
- try:
- r = ini_read(self.configfile)['']
- except:
- return self.config
- l = self.config.keys()
- for k,v in r.items():
- if self.config.has_key(k):
- t = type(self.config[k])
- try:
- if t == StringType:
- self.config[k] = v
- elif t == IntType or t == LongType:
- self.config[k] = long(v)
- elif t == FloatType:
- self.config[k] = float(v)
- l.remove(k)
- except:
- pass
- if l: # new default values since last save
- self.saveConfig()
- return self.config
- def saveConfig(self, new_config = None):
- if new_config:
- for k,v in new_config.items():
- if self.config.has_key(k):
- self.config[k] = v
- try:
- ini_write( self.configfile, self.config,
- 'Generated by '+product_name+'/'+version_short+'\n'
- + strftime('%x %X') )
- return True
- except:
- return False
- def getConfig(self):
- return self.config
- ###### STATE HANDLING ######
- def getState(self):
- try:
- f = open(self.statefile,'rb')
- r = f.read()
- except:
- r = None
- try:
- f.close()
- except:
- pass
- try:
- r = bdecode(r)
- except:
- r = None
- return r
- def saveState(self, state):
- try:
- f = open(self.statefile,'wb')
- f.write(bencode(state))
- success = True
- except:
- success = False
- try:
- f.close()
- except:
- pass
- return success
- ###### TORRENT HANDLING ######
- def getTorrents(self):
- d = {}
- for f in os.listdir(self.dir_torrentcache):
- f = os.path.basename(f)
- try:
- f, garbage = f.split('.')
- except:
- pass
- d[unhex(f)] = 1
- return d.keys()
- def getTorrentVariations(self, t):
- t = tohex(t)
- d = []
- for f in os.listdir(self.dir_torrentcache):
- f = os.path.basename(f)
- if f[:len(t)] == t:
- try:
- garbage, ver = f.split('.')
- except:
- ver = '0'
- d.append(int(ver))
- d.sort()
- return d
- def getTorrent(self, t, v = -1):
- t = tohex(t)
- if v == -1:
- v = max(self.getTorrentVariations(t)) # potential exception
- if v:
- t += '.'+str(v)
- try:
- f = open(os.path.join(self.dir_torrentcache,t),'rb')
- r = bdecode(f.read())
- except:
- r = None
- try:
- f.close()
- except:
- pass
- return r
- def writeTorrent(self, data, t, v = -1):
- t = tohex(t)
- if v == -1:
- try:
- v = max(self.getTorrentVariations(t))+1
- except:
- v = 0
- if v:
- t += '.'+str(v)
- try:
- f = open(os.path.join(self.dir_torrentcache,t),'wb')
- f.write(bencode(data))
- except:
- v = None
- try:
- f.close()
- except:
- pass
- return v
- ###### TORRENT DATA HANDLING ######
- def getTorrentData(self, t):
- if self.TorrentDataBuffer.has_key(t):
- return self.TorrentDataBuffer[t]
- t = os.path.join(self.dir_datacache,tohex(t))
- if not os.path.exists(t):
- return None
- try:
- f = open(t,'rb')
- r = bdecode(f.read())
- except:
- r = None
- try:
- f.close()
- except:
- pass
- self.TorrentDataBuffer[t] = r
- return r
- def writeTorrentData(self, t, data):
- self.TorrentDataBuffer[t] = data
- try:
- f = open(os.path.join(self.dir_datacache,tohex(t)),'wb')
- f.write(bencode(data))
- success = True
- except:
- success = False
- try:
- f.close()
- except:
- pass
- if not success:
- self.deleteTorrentData(t)
- return success
- def deleteTorrentData(self, t):
- try:
- os.remove(os.path.join(self.dir_datacache,tohex(t)))
- except:
- pass
- def getPieceDir(self, t):
- return os.path.join(self.dir_piececache,tohex(t))
- ###### EXPIRATION HANDLING ######
- def deleteOldCacheData(self, days, still_active = [], delete_torrents = False):
- if not days:
- return
- exptime = time() - (days*24*3600)
- names = {}
- times = {}
- for f in os.listdir(self.dir_torrentcache):
- p = os.path.join(self.dir_torrentcache,f)
- f = os.path.basename(f)
- try:
- f, garbage = f.split('.')
- except:
- pass
- try:
- f = unhex(f)
- assert len(f) == 20
- except:
- continue
- if delete_torrents:
- names.setdefault(f,[]).append(p)
- try:
- t = os.path.getmtime(p)
- except:
- t = time()
- times.setdefault(f,[]).append(t)
-
- for f in os.listdir(self.dir_datacache):
- p = os.path.join(self.dir_datacache,f)
- try:
- f = unhex(os.path.basename(f))
- assert len(f) == 20
- except:
- continue
- names.setdefault(f,[]).append(p)
- try:
- t = os.path.getmtime(p)
- except:
- t = time()
- times.setdefault(f,[]).append(t)
- for f in os.listdir(self.dir_piececache):
- p = os.path.join(self.dir_piececache,f)
- try:
- f = unhex(os.path.basename(f))
- assert len(f) == 20
- except:
- continue
- for f2 in os.listdir(p):
- p2 = os.path.join(p,f2)
- names.setdefault(f,[]).append(p2)
- try:
- t = os.path.getmtime(p2)
- except:
- t = time()
- times.setdefault(f,[]).append(t)
- names.setdefault(f,[]).append(p)
- for k,v in times.items():
- if max(v) < exptime and not k in still_active:
- for f in names[k]:
- try:
- os.remove(f)
- except:
- try:
- os.removedirs(f)
- except:
- pass
- def deleteOldTorrents(self, days, still_active = []):
- self.deleteOldCacheData(days, still_active, True)
- ###### OTHER ######
- def getIconDir(self):
- return self.dir_icons
|