]> git.ipfire.org Git - people/shoehn/ipfire.org.git/blob - www/pages/torrent/client/parsedir.py
Change Color of Menuitem CeBIT.
[people/shoehn/ipfire.org.git] / www / pages / torrent / client / parsedir.py
1 # Written by John Hoffman and Uoti Urpala
2 # see LICENSE.txt for license information
3 from bencode import bencode, bdecode
4 from BT1.btformats import check_info
5 from os.path import exists, isfile
6 from sha import sha
7 import sys, os
8
9 try:
10 True
11 except:
12 True = 1
13 False = 0
14
15 NOISY = False
16
17 def _errfunc(x):
18 print ":: "+x
19
20 def parsedir(directory, parsed, files, blocked,
21 exts = ['.torrent'], return_metainfo = False, errfunc = _errfunc):
22 if NOISY:
23 errfunc('checking dir')
24 dirs_to_check = [directory]
25 new_files = {}
26 new_blocked = {}
27 torrent_type = {}
28 while dirs_to_check: # first, recurse directories and gather torrents
29 directory = dirs_to_check.pop()
30 newtorrents = False
31 for f in os.listdir(directory):
32 newtorrent = None
33 for ext in exts:
34 if f.endswith(ext):
35 newtorrent = ext[1:]
36 break
37 if newtorrent:
38 newtorrents = True
39 p = os.path.join(directory, f)
40 new_files[p] = [(os.path.getmtime(p), os.path.getsize(p)), 0]
41 torrent_type[p] = newtorrent
42 if not newtorrents:
43 for f in os.listdir(directory):
44 p = os.path.join(directory, f)
45 if os.path.isdir(p):
46 dirs_to_check.append(p)
47
48 new_parsed = {}
49 to_add = []
50 added = {}
51 removed = {}
52 # files[path] = [(modification_time, size), hash], hash is 0 if the file
53 # has not been successfully parsed
54 for p,v in new_files.items(): # re-add old items and check for changes
55 oldval = files.get(p)
56 if not oldval: # new file
57 to_add.append(p)
58 continue
59 h = oldval[1]
60 if oldval[0] == v[0]: # file is unchanged from last parse
61 if h:
62 if blocked.has_key(p): # parseable + blocked means duplicate
63 to_add.append(p) # other duplicate may have gone away
64 else:
65 new_parsed[h] = parsed[h]
66 new_files[p] = oldval
67 else:
68 new_blocked[p] = 1 # same broken unparseable file
69 continue
70 if parsed.has_key(h) and not blocked.has_key(p):
71 if NOISY:
72 errfunc('removing '+p+' (will re-add)')
73 removed[h] = parsed[h]
74 to_add.append(p)
75
76 to_add.sort()
77 for p in to_add: # then, parse new and changed torrents
78 new_file = new_files[p]
79 v,h = new_file
80 if new_parsed.has_key(h): # duplicate
81 if not blocked.has_key(p) or files[p][0] != v:
82 errfunc('**warning** '+
83 p +' is a duplicate torrent for '+new_parsed[h]['path'])
84 new_blocked[p] = 1
85 continue
86
87 if NOISY:
88 errfunc('adding '+p)
89 try:
90 ff = open(p, 'rb')
91 d = bdecode(ff.read())
92 check_info(d['info'])
93 h = sha(bencode(d['info'])).digest()
94 new_file[1] = h
95 if new_parsed.has_key(h):
96 errfunc('**warning** '+
97 p +' is a duplicate torrent for '+new_parsed[h]['path'])
98 new_blocked[p] = 1
99 continue
100
101 a = {}
102 a['path'] = p
103 f = os.path.basename(p)
104 a['file'] = f
105 a['type'] = torrent_type[p]
106 i = d['info']
107 l = 0
108 nf = 0
109 if i.has_key('length'):
110 l = i.get('length',0)
111 nf = 1
112 elif i.has_key('files'):
113 for li in i['files']:
114 nf += 1
115 if li.has_key('length'):
116 l += li['length']
117 a['numfiles'] = nf
118 a['length'] = l
119 a['name'] = i.get('name', f)
120 def setkey(k, d = d, a = a):
121 if d.has_key(k):
122 a[k] = d[k]
123 setkey('failure reason')
124 setkey('warning message')
125 setkey('announce-list')
126 if return_metainfo:
127 a['metainfo'] = d
128 except:
129 errfunc('**warning** '+p+' has errors')
130 new_blocked[p] = 1
131 continue
132 try:
133 ff.close()
134 except:
135 pass
136 if NOISY:
137 errfunc('... successful')
138 new_parsed[h] = a
139 added[h] = a
140
141 for p,v in files.items(): # and finally, mark removed torrents
142 if not new_files.has_key(p) and not blocked.has_key(p):
143 if NOISY:
144 errfunc('removing '+p)
145 removed[v[1]] = parsed[v[1]]
146
147 if NOISY:
148 errfunc('done checking')
149 return (new_parsed, new_files, new_blocked, added, removed)
150