compression, argparse
This commit is contained in:
66
README.md
66
README.md
@@ -21,23 +21,55 @@ virtualenv .
|
|||||||
source bin/activate
|
source bin/activate
|
||||||
pip install -r requirements.txt
|
pip install -r requirements.txt
|
||||||
```
|
```
|
||||||
|
# Fork()
|
||||||
|
|
||||||
## Usage
|
Patched pgpfs code from https://github.com/aestetix/pgpfs.
|
||||||
pgpfs is simple to use. It is able to both `store` and `fetch` documents from
|
Has now:
|
||||||
the keyserver. Here are examples of usage:
|
|
||||||
|
|
||||||
### `store`
|
- argparse
|
||||||
To store the file sample.mp3 and save the Key Allocation Table (kat) in
|
- compression / decompression
|
||||||
sample.kat, run:
|
|
||||||
```
|
|
||||||
python pgpfs.py store sample.mp3 sample.kat
|
|
||||||
```
|
|
||||||
This will create a file called sample.kat to be used when you want to retrieve
|
|
||||||
your file.
|
|
||||||
|
|
||||||
### `fetch`
|
# TODO
|
||||||
To fetch the file sample.mp3 from the keyserver, assuming the kat file is called
|
|
||||||
sample.kat, run:
|
- add threading
|
||||||
```
|
- add encryption
|
||||||
python pgpfs.py fetch sample.kat sample.mp3
|
|
||||||
```
|
# TODO for someone with time and skills
|
||||||
|
|
||||||
|
- Building an vfs based on pgpfs, implementation ideas welcome :)
|
||||||
|
|
||||||
|
# USAGE
|
||||||
|
|
||||||
|
./pgpfs.py -h
|
||||||
|
usage: pgpfs.py [-h] -a ACTION [-k KAT] [-s STORE] [--keyserver KEYSERVER]
|
||||||
|
[--pgpfspath PGPFSPATH] [--gpgbinary PGPFSBIN]
|
||||||
|
|
||||||
|
https://github.com/aestetix/pgpfs
|
||||||
|
|
||||||
|
optional arguments:
|
||||||
|
-h, --help show this help message and exit
|
||||||
|
-a ACTION, --action ACTION
|
||||||
|
action to do: store or fetch
|
||||||
|
-k KAT, --katfile KAT
|
||||||
|
if fetch specify KAT file
|
||||||
|
-s STORE, --storefile STORE
|
||||||
|
if store specify file for upload
|
||||||
|
--keyserver KEYSERVER
|
||||||
|
specify keyserver
|
||||||
|
--pgpfspath PGPFSPATH
|
||||||
|
specify path for pgpfs
|
||||||
|
--gpgbinary PGPFSBIN specify path for pgpfs binary(patched gpg bin)
|
||||||
|
|
||||||
|
# Upload
|
||||||
|
./pgpfs.py -a store -s somefile.ext -k somefile.kat
|
||||||
|
|
||||||
|
# Download
|
||||||
|
./pgpfs.py -a store -s example.gif -k sample.kat
|
||||||
|
|
||||||
|
# NOTE
|
||||||
|
Please note that you need the gpg patched code from here:
|
||||||
|
https://github.com/aestetix/gpg
|
||||||
|
Compile and place somewhere. Adjust --gpgbinary accoringly.
|
||||||
|
|
||||||
|
Also you need to run an entropy source:
|
||||||
|
rndg -r /dev/urandom
|
||||||
|
|||||||
119
pgpfs.py
119
pgpfs.py
@@ -1,23 +1,59 @@
|
|||||||
#!bin/python
|
#!/usr/bin/env python2
|
||||||
|
#
|
||||||
|
# watch out, this is only possible with modified gpg version
|
||||||
|
# download this version as well from aestetix repo
|
||||||
|
|
||||||
""" pgpfs is a tool to turn your friendly pgp keyserver into a redundant
|
""" pgpfs is a tool to turn your friendly pgp keyserver into a redundant
|
||||||
persistant filesystem."""
|
persistant filesystem."""
|
||||||
|
|
||||||
|
import re
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import re
|
|
||||||
import base64
|
|
||||||
from hashlib import sha256
|
|
||||||
import gnupg
|
import gnupg
|
||||||
|
import base64
|
||||||
|
import pylzma
|
||||||
|
import argparse
|
||||||
|
import threading
|
||||||
|
|
||||||
os.system('rm -rf gpg')
|
from hashlib import sha256
|
||||||
GPG = gnupg.GPG(gnupghome='gpg')
|
|
||||||
KEYSERVER = 'pgp.mit.edu'
|
# TODO adjust with pgpfspath
|
||||||
|
os.system('rm -fr .pgpfs')
|
||||||
|
|
||||||
# trial and error lead to this number
|
# trial and error lead to this number
|
||||||
SPLIT_LENGTH = 986
|
SPLIT_LENGTH = 986
|
||||||
|
|
||||||
# store file
|
# pack file
|
||||||
|
def pack_file_to_disk(source_file):
|
||||||
|
''' takes the file and packs it '''
|
||||||
|
print 'Compressing file'
|
||||||
|
# TODO gen random temp here
|
||||||
|
target_file='tempfile.tmp'
|
||||||
|
with open(source_file, 'r') as source, open(target_file,'wb') as target:
|
||||||
|
lz = pylzma.compressfile(source, eos=1)
|
||||||
|
while True:
|
||||||
|
b =lz.read(1)
|
||||||
|
if not b:
|
||||||
|
break
|
||||||
|
target.write(b)
|
||||||
|
target.close()
|
||||||
|
return target_file
|
||||||
|
|
||||||
|
def unpack_file_from_disk(packed_file, out_file):
|
||||||
|
''' unpack file '''
|
||||||
|
print 'Uncompressing file'
|
||||||
|
with open(packed_file, 'rb') as packed, open(out_file,'wb') as out:
|
||||||
|
obj = pylzma.decompressobj()
|
||||||
|
decompress = ''
|
||||||
|
while True:
|
||||||
|
b = packed.read(1)
|
||||||
|
if not b:
|
||||||
|
break
|
||||||
|
dec = obj.decompress(b)
|
||||||
|
out.write(dec)
|
||||||
|
return True
|
||||||
|
|
||||||
|
# store file
|
||||||
def read_file_into_list(source_file):
|
def read_file_into_list(source_file):
|
||||||
""" reads file into list"""
|
""" reads file into list"""
|
||||||
with open(source_file, 'r') as source:
|
with open(source_file, 'r') as source:
|
||||||
@@ -54,6 +90,10 @@ def send_key(key_id):
|
|||||||
def store_file(filename1, filename2):
|
def store_file(filename1, filename2):
|
||||||
""" overall function to upload file to keyserver"""
|
""" overall function to upload file to keyserver"""
|
||||||
print 'Splitting ', filename1, ' into encoded comments for keys'
|
print 'Splitting ', filename1, ' into encoded comments for keys'
|
||||||
|
|
||||||
|
# watch out return value is the name of the newly packed file now
|
||||||
|
filename1 = pack_file_to_disk(filename1)
|
||||||
|
|
||||||
file_list = read_file_into_list(filename1)
|
file_list = read_file_into_list(filename1)
|
||||||
output_file = open(filename2, 'w')
|
output_file = open(filename2, 'w')
|
||||||
counter_length = len(file_list)
|
counter_length = len(file_list)
|
||||||
@@ -63,9 +103,14 @@ def store_file(filename1, filename2):
|
|||||||
counter = counter + 1
|
counter = counter + 1
|
||||||
key_id = create_key(chunk)
|
key_id = create_key(chunk)
|
||||||
output_file.write(send_key(key_id)+'\n')
|
output_file.write(send_key(key_id)+'\n')
|
||||||
|
output_file.flush()
|
||||||
print '--> key has been created and uploaded'
|
print '--> key has been created and uploaded'
|
||||||
print 'File has been successfully uploaded to ', KEYSERVER
|
print 'File has been successfully uploaded to ', KEYSERVER
|
||||||
|
|
||||||
|
# TODO adjust with args
|
||||||
|
# tempfile is created at packing stage
|
||||||
|
os.system('tempfile.tmp')
|
||||||
|
|
||||||
# fetch file
|
# fetch file
|
||||||
|
|
||||||
def get_key_comment(key_id):
|
def get_key_comment(key_id):
|
||||||
@@ -82,8 +127,9 @@ def parse_key(key_id):
|
|||||||
|
|
||||||
def fetch_file(index_file, filename):
|
def fetch_file(index_file, filename):
|
||||||
""" overall function to fetch component file parts from keyserver"""
|
""" overall function to fetch component file parts from keyserver"""
|
||||||
with open(index_file, 'r') as index, open(filename, 'w+') as download:
|
filelzma='%s.lzma' % filename
|
||||||
print 'Fetching keys from ', KEYSERVER, ' to create ', filename
|
with open(index_file, 'r') as index, open(filelzma, 'w+') as download:
|
||||||
|
print 'Fetching keys from ', KEYSERVER, ' to create ', filelzma
|
||||||
fetched_file = ''
|
fetched_file = ''
|
||||||
index_length = len(index.readlines())
|
index_length = len(index.readlines())
|
||||||
index.seek(0) # because python is stupid
|
index.seek(0) # because python is stupid
|
||||||
@@ -94,11 +140,16 @@ def fetch_file(index_file, filename):
|
|||||||
fetched_file = fetched_file + parse_key(key.rstrip('\n'))
|
fetched_file = fetched_file + parse_key(key.rstrip('\n'))
|
||||||
print 'All keys have been downloaded'
|
print 'All keys have been downloaded'
|
||||||
download.write(base64.b64decode(fetched_file))
|
download.write(base64.b64decode(fetched_file))
|
||||||
|
# hook in here and unpack the data
|
||||||
|
# filename == original outname
|
||||||
|
# filelzma == packed file here as download
|
||||||
|
unpack_file_from_disk(filelzma,filename)
|
||||||
print 'File has been decoded and saved as ', filename
|
print 'File has been decoded and saved as ', filename
|
||||||
|
|
||||||
# handle command line input
|
# remove lzma
|
||||||
|
os.unlink(filelzma)
|
||||||
|
|
||||||
if len(sys.argv) < 3:
|
def usage():
|
||||||
print """Usage: ./pgpfs.py [action] filename1 filename2'
|
print """Usage: ./pgpfs.py [action] filename1 filename2'
|
||||||
action can be either ''store'' or ''fetch'''
|
action can be either ''store'' or ''fetch'''
|
||||||
|
|
||||||
@@ -115,13 +166,45 @@ if len(sys.argv) < 3:
|
|||||||
"""
|
"""
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
ACTION = sys.argv[1]
|
def run(args):
|
||||||
|
''' run function, do all the magic '''
|
||||||
|
|
||||||
if ACTION not in ['store', 'fetch']:
|
global KEYSERVER
|
||||||
|
global GPG
|
||||||
|
|
||||||
|
|
||||||
|
pgpfspath = args.pgpfspath
|
||||||
|
pgpfsbin = args.pgpfsbin
|
||||||
|
KEYSERVER = args.keyserver
|
||||||
|
ACTION = args.action
|
||||||
|
kat = args.kat
|
||||||
|
store = args.store
|
||||||
|
|
||||||
|
GPG = gnupg.GPG(gnupghome=pgpfspath,gpgbinary=pgpfsbin)
|
||||||
|
|
||||||
|
if ACTION not in ['store', 'fetch']:
|
||||||
print 'Please specific either ''store'' or ''fetch'''
|
print 'Please specific either ''store'' or ''fetch'''
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
if ACTION == 'store':
|
if ACTION == 'store':
|
||||||
store_file(sys.argv[2], sys.argv[3])
|
store_file(store, kat)
|
||||||
elif ACTION == 'fetch':
|
elif ACTION == 'fetch':
|
||||||
fetch_file(sys.argv[2], sys.argv[3])
|
fetch_file(kat, store)
|
||||||
|
pass
|
||||||
|
|
||||||
|
def main():
|
||||||
|
prog_name='pgpfs.py'
|
||||||
|
prog_desc='https://github.com/aestetix/pgpfs'
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(prog=prog_name, description=prog_desc)
|
||||||
|
parser.add_argument('-a','--action',help='action to do: store or fetch',dest='action',required=True)
|
||||||
|
parser.add_argument('-k','--katfile',help='if fetch specify KAT file',dest='kat',required=False)
|
||||||
|
parser.add_argument('-s','--storefile',help='if store specify file for upload',dest='store',required=False)
|
||||||
|
parser.add_argument('--keyserver',help='specify keyserver',dest='keyserver',required=False, default='pgp.mit.edu')
|
||||||
|
parser.add_argument('--pgpfspath',help='specify path for pgpfs',dest='pgpfspath',required=False, default='.pgpfs')
|
||||||
|
parser.add_argument('--gpgbinary',help='specify path for pgpfs binary(patched gpg bin)',dest='pgpfsbin',required=False, default='/root/fuzzygpg/bin/gpg2')
|
||||||
|
args = parser.parse_args()
|
||||||
|
run(args)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
|
|||||||
@@ -1 +1,5 @@
|
|||||||
|
# for crypto
|
||||||
python-gnupg
|
python-gnupg
|
||||||
|
|
||||||
|
# for compression
|
||||||
|
pip2 install pylzma
|
||||||
|
|||||||
158
sample.kat
158
sample.kat
@@ -1,152 +1,6 @@
|
|||||||
FC7E32931156981F45C8921403FC6E2E71437504
|
2272C34D08040FE9192224098D48A96E2C86C1DC
|
||||||
AEFD299201F29D9A214F12A6ED67FD5C097D395E
|
68ED1D9AF827F06BA229AC8791C7903A86AC78AF
|
||||||
77D8C204A22D1B95A94F8F968B7D7D6C067F03D0
|
8DB3A3662748A13102B8A954BF825A6CCD4E4515
|
||||||
DC1860F1F31B97CF0B4C810CC93F45CBF53899DF
|
9D3961DA2CDE3DF6736AE4520F2A93A9A5B8D6F7
|
||||||
7F2DB84F62FB6FB92DDAEBF2C72CE0BEFF30B39C
|
A08233ACEB11F2ADBA48075E1F8D6337889E8BCF
|
||||||
6855D9307D0D028EC9331D2035A7073251DA8706
|
5913148227C69CEA0C7B15DC7ABA0182E569A9B9
|
||||||
8D9F2349B9985C9ABAA8CFEB97D7987A2E590F51
|
|
||||||
C2A4FA1711BA44AE4FA4BD6D64968C33EBD48804
|
|
||||||
1A14F953CF068E31B024B14C9E32560C66B72DE6
|
|
||||||
9761655B70B37C151A0F8BF91DC037FE91467EB5
|
|
||||||
381ADF37F08AD6EC68C29C2BD5D8C50ECB9D2C92
|
|
||||||
6E02EF0894D791B14763C3F9C08DE00FF0FAC72C
|
|
||||||
83BAB626A749B42BFB0DD9A089C1C980B54BFADD
|
|
||||||
70172D0D8250348D39A8DCC35BBCAEA9CEAD5095
|
|
||||||
5641A421CC6EC4D653A5DF7A7E7E6310223F40BB
|
|
||||||
B18D5207DB52F67B8B887C2EF29F46D59EB47057
|
|
||||||
B61017BB57CD67E799F00030F4DA2ABC40AD954F
|
|
||||||
553A1FA1BC4B2E134FD8B599EE1DD665ADDBA5F3
|
|
||||||
C784F793E7F5227E5DE0990C9A974A93412D38F0
|
|
||||||
C21D729AB22E32E8D099805F7CD229CE467C1070
|
|
||||||
85327227E8F88651D289585306D03094A219DAFB
|
|
||||||
15BCDE4302088E55E4BD0F350802FDCDF9EFCBE9
|
|
||||||
713E962F520A26E4053E2BC6651D639B47AC77C2
|
|
||||||
43D14E04CDD79D91F170AFE4CC1E9F4C98C5ADA5
|
|
||||||
54F165ED18B2AE530646EFFF0C3148F8FFBC2BAF
|
|
||||||
E20BC2E85EF4710D865ACED955BD03C4BC1242CF
|
|
||||||
DFB4A066437EA239C214B8A1029F1C141CECAB4B
|
|
||||||
C35F3F42A0EE1CD4D667DFB54265422B6F59D6D2
|
|
||||||
EBCF384AE04B4819825DB50274CF2B8B25013663
|
|
||||||
DA50EF1B63294B0F0C8F3EB8E764A10D813D6161
|
|
||||||
504929CCB20136D2C4F6EBE000AAD0977A175F76
|
|
||||||
C3E57059241C861E776D2C67E5C355A967BC95C7
|
|
||||||
25F9417ADD87117A6F7142FDFE376CC87EA544AC
|
|
||||||
C12E9E766A9171CB308D2A13043CBC2ED8DD46FC
|
|
||||||
C342DE30EC6C4EABB9ECA01921C3F45C9E113BA3
|
|
||||||
ABCBCF7C746F88C62599373850D271251650DA5E
|
|
||||||
3A8915A4E29751BF9749CCDE8994FD78F9BD69D8
|
|
||||||
1DE994F81F3BF045D0BAA2F3BA569CF9D577522F
|
|
||||||
D14A65F9C9BD9B7DB809BA75A014CF92C9099A15
|
|
||||||
A66CCEC87D2086A7076DB7A9F727E06B4DD0F1CB
|
|
||||||
98C2188983492CD882094E13899D5A303B2D4699
|
|
||||||
EF736B36CB5BD35676251A25165E198CE0E50B0B
|
|
||||||
9A0B6A1716BE118373E44A196FF6E04971BF30B5
|
|
||||||
4D600F90080B05F3556896A51D50FFE827650A1A
|
|
||||||
5E04FE85AEB4EBC5B7EBEC1DD6795EEAE7255BEC
|
|
||||||
9FF2074D485AB4F9EE10261C497EB569D2826268
|
|
||||||
A8F4F7279CDBBBC8F8CAE7655EA0C8261B474D63
|
|
||||||
77AE3944D5D3F29BB6DEE7417DE5AD276BB812FE
|
|
||||||
BF510C2FCD094E326016EF3F1D68B879C07A3554
|
|
||||||
3FEEB6AD801F0D890BDC1E856AEA8066240F72CC
|
|
||||||
74EF6FDC61394F11B3D30BAAB2E0D0E03B90FD9A
|
|
||||||
E8743554CE30989683BA6968183E80E5530955C9
|
|
||||||
1D916686C99DA213922A2AA3C92E09DAF83ADFA6
|
|
||||||
9C68F90DDD04573E01CC784095E8AD7AFBD3A958
|
|
||||||
1D7D8F2E058AF51D259E40889E1F54F298C9CF39
|
|
||||||
B62E99A68496D7BC364DD6AA078EA3575D0C9BC1
|
|
||||||
A27EBF1A05F69D35D31C7D7D0BD466AD4FD2632B
|
|
||||||
17F0964EC2CBDC03DB95DAA41C2F125B7F959119
|
|
||||||
D2D5A6C6811E010FB704EAA6FF6436C30F7C0A8D
|
|
||||||
231A76CFF6A01447CC10C402AEF4FB526EEBE04F
|
|
||||||
F51F6DD8E7C54F38F44BFF28F2EE02A71D7DCA05
|
|
||||||
6C7F4EA5A1D5389A285576A5059B7508FF62A143
|
|
||||||
3240819055A4C33C63038C07AB074E7B1193A46E
|
|
||||||
E212CE4C6AF43342869D63069FD534087F60E0DD
|
|
||||||
840460655FB874FF8F9A80F3AF200143EDE39C01
|
|
||||||
7D397CF95C2390FEFFC992A1A27CC1069E6B430F
|
|
||||||
34760DE6285F5BE3A1CD587BC780D2C719D32EA4
|
|
||||||
FFBE5077A12BB8F634C3443D62EC8D0C5B8EB58E
|
|
||||||
396B6CD12626EF54B60EBF3EB8E741069F505795
|
|
||||||
F92215F565A48FF1CE555430DFC12645D735BB4D
|
|
||||||
9186E87CD5268E242BB741B504C3F6E6A68D8DB5
|
|
||||||
C8B2AAE555130CD59DADB4D1ADC481E2CF4F22F9
|
|
||||||
3027B0DF6EFC9A65CC0C96B03C529763A9DF0441
|
|
||||||
888D93910A811942A08849917630E274C7B25212
|
|
||||||
A54FF2D620F7FFB2C8BAE3D1FE5BA6D0E011A85C
|
|
||||||
3C3682B68B081467D238ABF533FAE9DC18023471
|
|
||||||
236373230F09D348F4297B930286CF184DB8D58D
|
|
||||||
0E8EA256ACB357FAE5EEE7CBF4FCD45553D9B5FD
|
|
||||||
9382FEB1F294763DAEE1B3A2E0447BC888F372D6
|
|
||||||
5C7DC7EE295B4526D931B9960D7BFC942A406849
|
|
||||||
B021623CA67F9D9FEC2F185980C61BF5FB794FEF
|
|
||||||
17570A0A21DF24ECD23798378EA6BFA5435E88FC
|
|
||||||
2E2DEDB85EF6CBEFE52FAD7FD361BC7B659A993F
|
|
||||||
0619E510B69066E2D905AA8196C45E01B8B88AFD
|
|
||||||
46B542E6C1C052971A9600A157587967E6B06949
|
|
||||||
5B5B738391ADC1E399E8D4E90E1056C5E5466261
|
|
||||||
71B97797C1D4BEC8D5C5F94DA64595EC29ACB387
|
|
||||||
0273561D3A2E4EBA7052C4306E18F92BEEB5CADE
|
|
||||||
74E59E4DFAB3AD26FD7F2A929A574B2C9EC8B307
|
|
||||||
7436750D2DCF366EA438B9CAF67D8491E0CCFD83
|
|
||||||
2336143F7FFEE099A562C79F940E1FB8B5185CBD
|
|
||||||
E19149A9A44C0930CADA2B00A4E159A380B82CF4
|
|
||||||
69588D2817EDE5A47EB76C95D996B5FC32559BCD
|
|
||||||
99A36ACEE0AAC24636E9C352206162305D3AF7D5
|
|
||||||
025CE5B6CD9ED7C7E155CFA71DCEE7230FF06C92
|
|
||||||
923BC863D50ADFB81D59216187818104A4FA6647
|
|
||||||
78A648F27596C388342AF41FABC12C3EF8D19419
|
|
||||||
0BFC560C358749C97B27455B3725A2B7B2170A44
|
|
||||||
0FB6FC2AB8203DC1B766B35B13E223590AAE0E62
|
|
||||||
5246CBB8A6BC2A1940FA5C1EB33CE9AD5678E6F1
|
|
||||||
B3CDB213917711608B10F67623FF8BC2990FB01A
|
|
||||||
8E9DCDF64E34576F508B2AC1160DF9EB39753351
|
|
||||||
729C7801E2B34E43F8677840C62892C25EAB9C31
|
|
||||||
CCAF6D87C4367C6D411A416AE47DCD9100CFCC87
|
|
||||||
11CB8E5E9632470811409CA26D76D79EB014E736
|
|
||||||
E300526068BC9859B801E044EB04C2FFEE00A325
|
|
||||||
5FDD54931FB220529B3E239BCB39E20E6AB49E6D
|
|
||||||
1620368CA99E94FE680691929A9EC6963AAF981E
|
|
||||||
BA150F4D664C3FF2D0EBEAD54D6B84D86C546D92
|
|
||||||
3CCE2C670F46C85A438CC74C93EC3DCE6B61E397
|
|
||||||
63D5A2432B606145AFDC033A335FEC7F906E83B3
|
|
||||||
CE93757422A3B579FCDEE93B377210563332F891
|
|
||||||
177B9AA184E5E9BA6E242C876011ABF4979F4BAF
|
|
||||||
FC46D820A1ADC9D377A5AF3D3669B7F0A590D9F8
|
|
||||||
8E507A347FEFA1BCC694A8A8834240896566791A
|
|
||||||
B0A28BD84FD258881AE543FF4F3A00C91FC4A734
|
|
||||||
BBF485E9CA9E81AA048BA19B2635E10063ACF01E
|
|
||||||
CFBCEE242835D4FAB673C5FE1E16657256582989
|
|
||||||
583E7794847191DBD38183873F633627D0508A26
|
|
||||||
DDD1EC1314122342EB547F8C541157A89945D3E7
|
|
||||||
120D681444A7B4F59E39FFFD2DAB5E0B4DC17009
|
|
||||||
4FDCBCF0C75B35DF4F570E921892BB17B16D8062
|
|
||||||
D736015EB64E9FBE622CCEC7B9EF951E8C2D3E3A
|
|
||||||
D36DB784C7A565E76C9C40776017D134B4447C6F
|
|
||||||
343B530F95B2CAFB8620A4FD4B31102D02061543
|
|
||||||
90AB64DFE7D280E96EAF2B7DA5E522634012C79E
|
|
||||||
DAA9CE75C9A1F8AB54C51CA153AC4C95C3C6EE6B
|
|
||||||
F18D849F47A56A55DD00B21C638B2212C7518CDC
|
|
||||||
F7C035D8A5C597BB579E591EDE497BA0E1162B09
|
|
||||||
CC48F8C613A12DE9AD9CFE6B195320FDBDE38F31
|
|
||||||
745730E07AF64A794CDBEA9739726598CB17327B
|
|
||||||
79118B75E03CED3485F715DA9DA60399AEBEBCFE
|
|
||||||
90D01EB404B84FCA5BF12E183C2D178E076DB003
|
|
||||||
4EF9B48377F764E46E3599FF7917A48396D59870
|
|
||||||
2F75D55AED2691AE70A90CE3D85D872AB02EE17D
|
|
||||||
987F3F0A5746FCC011B565E2D7BDE6A4BA3E1E70
|
|
||||||
51172E0EE67884A08DFD14628B334CCE66A5B2A5
|
|
||||||
0D161D7D63FA04BB6A74214347677220DBAD0E34
|
|
||||||
3554DC686D53C10C4C847A4DED57FEEBBC609A67
|
|
||||||
3D66E2C78F486457596F8819FDFBBD8E3409E9D7
|
|
||||||
B94447C1FC5172C2E8877699E1EEA744F052220B
|
|
||||||
A1AB1EAC0E84A116D348E04CA44EEA033F5AC4AD
|
|
||||||
A3CB4E3827F195B6FDC8ECCF6D036631AF1D1866
|
|
||||||
56FEB79F69F10DDB33E778ADE835AA029804292B
|
|
||||||
E827BF52999953B93214F796760B8C3771490129
|
|
||||||
CBD1C8C8B3946A83A5D8233876CA0CFA5D4302C2
|
|
||||||
8A65DBFD30294CF8AB556D89E04D7D476AEBF597
|
|
||||||
96F4EABCF809FD1802C1BF0A8000A3FAF9C1C6F5
|
|
||||||
CDED5632BC11999E545D981CCFFCDD3ACC04BA17
|
|
||||||
9B524CCB9647E4FE6ED79D129049AA1FAD18DA23
|
|
||||||
4D296FBBB9FB6732EC3CD24C674BAA29B827002C
|
|
||||||
11D08E00DBC668225E6AA084AF1C68F6519C4C31
|
|
||||||
|
|||||||
Reference in New Issue
Block a user