forked from iambus/xunlei-lixian
-
Notifications
You must be signed in to change notification settings - Fork 0
/
lixian_hash_ed2k.py
72 lines (60 loc) · 2.21 KB
/
lixian_hash_ed2k.py
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
import hashlib
chunk_size = 9728000
buffer_size = 1024*1024
def md4():
return hashlib.new('md4')
def hash_stream(stream):
total_md4 = None
while True:
chunk_md4 = md4()
chunk_left = chunk_size
while chunk_left:
n = min(chunk_left, buffer_size)
part = stream.read(n)
chunk_md4.update(part)
if len(part) < n:
if total_md4:
total_md4.update(chunk_md4.digest())
return total_md4.hexdigest()
else:
return chunk_md4.hexdigest()
chunk_left -= n
if total_md4 is None:
total_md4 = md4()
total_md4.update(chunk_md4.digest())
return total_md4.hexdigest()
def hash_string(s):
from cStringIO import StringIO
return hash_stream(StringIO(s))
def hash_file(path):
with open(path, 'rb') as stream:
return hash_stream(stream)
def parse_ed2k_link(link):
import re, urllib
ed2k_re = r'ed2k://\|file\|[^|]*\|(\d+)\|([a-fA-F0-9]{32})\|.*/'
m = re.match(ed2k_re, link) or re.match(ed2k_re, urllib.unquote(link))
if not m:
raise Exception('not an acceptable ed2k link: '+link)
file_size, hash_hex = m.groups()
return hash_hex.lower(), int(file_size)
def verify_ed2k_link(path, link):
hash_hex, file_size = parse_ed2k_link(link)
import os.path
if os.path.getsize(path) != file_size:
return False
return hash_file(path).lower() == hash_hex.lower()
def generate_ed2k_link(path):
import sys, os.path, urllib
filename = os.path.basename(path)
encoding = sys.getfilesystemencoding()
if encoding.lower() != 'ascii':
filename = filename.decode(encoding).encode('utf-8')
return 'ed2k://|file|%s|%d|%s|/' % (urllib.quote(filename), os.path.getsize(path), hash_file(path))
def test_md4():
assert hash_string("") == '31d6cfe0d16ae931b73c59d7e0c089c0'
assert hash_string("a") == 'bde52cb31de33e46245e05fbdbd6fb24'
assert hash_string("abc") == 'a448017aaf21d8525fc10ae87aa6729d'
assert hash_string("message digest") == 'd9130a8164549fe818874806e1c7014b'
assert hash_string("abcdefghijklmnopqrstuvwxyz") == 'd79e1c308aa5bbcdeea8ed63df412da9'
assert hash_string("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") == '043f8582f241db351ce627e153e7f0e4'
assert hash_string("12345678901234567890123456789012345678901234567890123456789012345678901234567890") == 'e33b4ddc9c38f2199c3e7b164fcc0536'