144 lines
5.6 KiB
Python
144 lines
5.6 KiB
Python
import os
|
|
import random
|
|
import shutil
|
|
import subprocess
|
|
from glob import glob
|
|
from pathlib import Path
|
|
|
|
from tqdm import tqdm
|
|
|
|
from breach.parser import parse_to_files
|
|
from breach.query import QueryAPI, get_query_manager
|
|
from breach.splitter import get_output_file, write_line_to_file
|
|
from breach.utils import alpha_num_lookup, shuffle, read_lines
|
|
|
|
|
|
class API:
|
|
|
|
@staticmethod
|
|
def evaluate(old, new):
|
|
hit_count = 0
|
|
total_count = 0
|
|
files = [p for p in Path(old).expanduser().glob('**/*') if p.is_file()]
|
|
for i in range(1000):
|
|
lines = read_lines(random.choice(files))
|
|
shuffle(lines)
|
|
random_lines = lines[0:10]
|
|
for random_line in random_lines:
|
|
password_list = QueryAPI.query(new, random_line.split(':')[0], 'email')
|
|
total_count += 1
|
|
if len(password_list) == 0:
|
|
print(f'OLD: {random_line}, NEW: miss, HIT_RATE = {hit_count / total_count:.3f}.')
|
|
else:
|
|
hit_count += 1
|
|
print(f'OLD: {random_line}, NEW: hit, HIT_RATE = {hit_count / total_count:.3f}.')
|
|
|
|
@staticmethod
|
|
def merge(src, dest):
|
|
src_files = find_files(src)
|
|
dest_files = find_files(dest)
|
|
for src_index, src_file in src_files.items():
|
|
if src_index in dest_files:
|
|
merge(src_file, dest_files[src_index])
|
|
else:
|
|
move(src_file, dest + src_index)
|
|
|
|
@staticmethod
|
|
def parse(path, success_file, failure_file, cython_acceleration=False):
|
|
parse_to_files(path, success_file, failure_file, cython_acceleration)
|
|
|
|
@staticmethod
|
|
def sort(path):
|
|
path = str(Path(path).expanduser())
|
|
paths = [Path(a) for a in glob(path + '/**/*', recursive=True) if Path(a).is_file()
|
|
and Path(a).suffix != '.sorted']
|
|
for path in tqdm(paths, desc='Unique > Sorting > Replacing existing files'):
|
|
output_path = path.with_suffix('.sorted')
|
|
lines = read_lines(path)
|
|
unique_sorted_lines = sorted(set(lines))
|
|
with open(output_path, 'w', encoding='utf8') as w:
|
|
w.write('\n'.join(unique_sorted_lines) + '\n')
|
|
shutil.move(output_path, path)
|
|
|
|
@staticmethod
|
|
def clean(path):
|
|
files = list(find_files(Path(path).expanduser()).values())
|
|
shuffle(files)
|
|
alpha = alpha_num_lookup()
|
|
num_files_moved = 0
|
|
files_handlers = {} # u limit here!
|
|
with tqdm(files, desc='clean') as bar:
|
|
for file in bar:
|
|
lines_to_delete = []
|
|
lines = read_lines(file)
|
|
for line in lines:
|
|
line_split = line.split(':')
|
|
ground_truth_file = get_output_file(alpha, line_split[0])
|
|
key = str(file).replace(path, '')
|
|
if key.startswith('/'):
|
|
key = key[1:]
|
|
if ground_truth_file != key:
|
|
output_file = Path(path) / ground_truth_file
|
|
# print(f'MOVE: {line_split[0]} -> {output_file}.')
|
|
write_line_to_file(files_handlers, line_split, output_file, buffer_scale=10)
|
|
lines_to_delete.append(line)
|
|
num_files_moved += 1
|
|
if num_files_moved % 100_000 == 0:
|
|
truncated_file = str(file).replace(path, "")
|
|
truncated_output_file = str(output_file).replace(path, "")
|
|
bar.set_description(f'clean. {num_files_moved:,} moved. '
|
|
f'move: {line_split[0]}: {truncated_file}'
|
|
f' -> {truncated_output_file}')
|
|
lines2 = sorted(set(lines) - set(lines_to_delete))
|
|
if len(lines) != len(lines2):
|
|
with open(str(file), 'w', encoding='utf8') as w:
|
|
w.write('\n'.join(lines2) + '\n')
|
|
|
|
@staticmethod
|
|
def test(file: str, dataset: str):
|
|
qm = get_query_manager(dataset)
|
|
cracked_rate = 0
|
|
lines = read_lines(file)
|
|
for line in lines:
|
|
results = qm.perform_query(line.strip(), 'email')
|
|
if len(results) > 0:
|
|
passwords = [p.split(':', 1)[-1] for p in results]
|
|
print('FOUND:', line, ':'.join(passwords))
|
|
cracked_rate += 1
|
|
print(f'Cracked rate: {cracked_rate / len(lines)}')
|
|
|
|
@staticmethod
|
|
def chunk_files(path: str, max_size: int):
|
|
# split -b 50000000 file.txt file.txt.
|
|
# -d to have .00 and .01 is not compatible with MacOS...
|
|
files = list(find_files(Path(path).expanduser()).values())
|
|
for f in tqdm(files, desc='chunk large files'):
|
|
if f.stat().st_size / 1e6 > max_size:
|
|
cmd = ['split', '-b', str(int(max_size * 1e6)), str(f), str(f) + '_']
|
|
print(f'File size: {f.stat().st_size / 1e6:.2f} Mb. ' + ' '.join(cmd))
|
|
subprocess.check_output(cmd)
|
|
f.unlink()
|
|
|
|
|
|
def find_files(path: str):
|
|
path2 = Path(path).expanduser()
|
|
files = [p for p in path2.glob('**/*') if p.is_file()]
|
|
index = {str(f).replace(str(path2), ''): f for f in files}
|
|
assert len(index) == len(files)
|
|
return index
|
|
|
|
|
|
def merge(src, dst):
|
|
print(f'merge {src} {dst}')
|
|
with open(src, 'r', encoding='utf8', errors='ignore') as r:
|
|
content1 = r.read()
|
|
with open(dst, 'a', encoding='utf8', errors='ignore') as w:
|
|
w.write(content1)
|
|
print(f'del {src}')
|
|
os.remove(src)
|
|
|
|
|
|
def move(src, dst):
|
|
print(f'mv {src} {dst}')
|
|
shutil.move(src, dst)
|