]>
Commit | Line | Data |
---|---|---|
879aa787 MT |
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 |