def _modifier_wrapper(self, tmp_path: Path, name: str, impact: str, ask: bool, modifier: Callable[[int], None]) -> None: count = count_lines(tmp_path) if ask and not pause( f'{cyan(name)} keywords (impact: {impact} => {eval(f"{count}{impact}")})', cancel=True): return modifier(tmp_path, count) new_count = count_lines(tmp_path) pr(f'{name} added {cyan(new_count - count)} new keywords, total: {cyan(new_count)}' )
def clear(self, args: tuple) -> None: if not pause('truncatete wordlist', cancel=True): return f = self._get_wordlist_path() if not f: return with f.open('w') as file: file.truncate() pr('Wordlist truncateted!')
def aur_deploy(args): if args.directory: directory = Path(args.directory) if directory.is_file(): directory = directory.parent else: directory = Path.cwd() if not directory.is_dir(): pr(f'Cnnot run in directory, No such directory {directory} !', 'X') return 1 pr(f'Running in: {directory} directory') if not directory.joinpath('setup.py').is_file(): pr( 'No setup.py found in directory, ' + 'Please prepare setup.py for deployment!', 'X') return 1 # Load setup.py title, new_ver, description = check_output( ['python3', 'setup.py', '--name', '--version', '--description'], cwd=directory).decode().splitlines() pr(f'Project {title} {new_ver} in: {directory}') # Check PyPI if args.force or version.parse(new_ver) > version.parse( get_pypi_ver(title)): if not pause('publish to PyPI', cancel=True) \ or not pypi_procedure(directory): return 1 # Check AUR if args.no_aur: return aur_ver = get_aur_ver(title) if args.force or version.parse(new_ver) > version.parse(aur_ver): if not pause('publish to AUR', cancel=True) \ or not aur_procedure(aur_ver == '0', args.aur_depends, directory, title, new_ver): return 1
def duplicate(self, args: tuple) -> None: if not args: return pr('Usage: duplicate <copy_name>', '*') f = self._get_wordlist_path() if not f: return dst = Path(args[0]) if dst.is_file(): pr(f'File {cyan(dst)} already exists, overwrite?', '!') if not pause(cancel=True): return copy(f, dst) pr(f'Copied to {cyan(dst)}!')
def crunch(self, args: tuple) -> None: if not is_package('crunch'): return pr('Package "crunch" not installed!', 'X') # Get args is_mask = args and args[0] == 'mask' # Mode switch: [Mask / Charset] if is_mask: mask = prompt_mask() if not mask: return pr('Invalid mask!', '!') file_name = f'mask_{ask("Enter save name:")}.dict' l = str(len(mask)) return self._crunch( lambda: self._gen(file_name, ['crunch', l, l, '-t', mask])) # Get min and max seq len min_len = prompt_int('Enter minimum length') max_len = prompt_int('Enter maximum length') if not min_len or not max_len or \ min_len < 1 or max_len < min_len: return pr('Invalid paramenters!', '!') # Ask for a charset to use with CHAR_FILE.open(encoding='utf-8') as char_file: sets = [n[:-1] for n in char_file if '=' in n and 'sv' not in n] select = choose(sets, 'Choose charset:', default=26) # Actually 27 if select < 0: exit(-1) charset = sets[select].split(' ')[0] # Confirm if not pause( f'generate ({cyan(min_len)}-{cyan(max_len)}) length dict via "{cyan(charset)}" charset', cancel=True): return file_name = f'{charset}_{min_len}-{max_len}.dict' return self._crunch(lambda: self._gen(file_name, [ 'crunch', str(min_len), str(max_len), '-f', CHAR_FILE, charset ]))
def use(self, args: tuple) -> None: if self.current: if not pause( f'Switching from {cyan(self.current)} to new wordlist', cancel=True): return f = choose_file(self.workspace) if not f: return sb, lc, txt = file_volume(f) pr(txt) # if sb > 1*1024**3: # 1 GB # pr(f'File is too larget to be loaded into RAM!', '!') # return self.current = f pr(f'Now using {cyan(self.current)} wordlist!')
def ask_two_wl(self, _total_calc=Callable[[int, int], int], _write_action=Callable[[Path, Path, Path, IterationTimer], None]): def _select_wordlist(title: str): pr(f'Select {title} wordlist:') f = choose_file(self.workspace) if not f: raise KeyboardInterrupt fsb, flc, ftxt = file_volume(f) pr(f' {ftxt}') return f, fsb, flc # Get wordlists try: f1, f1sb, f1lc = _select_wordlist('first') f2, f2sb, f2lc = _select_wordlist('secund') except KeyboardInterrupt: print() return pr('Interrupted', '!') # Calculate impact and let the user accept the facts tsb = _total_calc(f1sb, f2sb) tlc = _total_calc(f1lc, f2lc) pr(f'Mixing will allocate {cyan(human_bytes(tsb))} for {cyan("{:,}".format(tlc))} lines') free = disk_usage(self.workspace.resolve()).free pr(f"Available space on workspace's disk: " + cyan(human_bytes(free))) if tsb > free: pr('Not enough space on the workspace disk for allocation!', '!') return max_size = self.config['max_created_file_size'] if tsb > max_size: return pr(f'Calculation resulted in an oversized file (>{human_bytes(max_size)}), aborting!', '!') if not pause(cancel=True): return out_path = self.dest_dir.joinpath(f'{f1.stem}_{f2.stem}') with out_path.open('w', encoding='utf-8') as out_file: itmr = IterationTimer(tlc, init_interval=1, max_interval=15) _write_action(f1, f2, out_file, itmr) # Finalize pr('Wordlist written into: ' + cyan(out_path.name)) show_ebt({ # TODO Move to config 'WPA2': 57000 }, tlc)
def print_all(self, args: tuple) -> None: f = self._get_wordlist_path() if not f: return lc = count_lines(f) if not lc: return pr('Wordlist is empty!', '!') # Get arguments total = False if args: total = args[0] == 'total' # Print relevant info if not total: if lc > self.config['list_treshold']: if not pause(f'show all {cyan(lc)} keywords', cancel=True): return for v in self._gen_wordlist(f): cprint(' ' + v, "yellow") pr(f'Total keywords count: ' + cyan(lc))
def expand(self, args: tuple) -> None: f = self._get_wordlist_path() if not f: return lc = count_lines(f) if not self: return pr('Wordlist is empty!', '!') # Get new wordlist name try: print('Enter name for new expanded wordlist:') save_path = input(colored('>', 'yellow')) if not save_path: return save_path = self.workspace.joinpath('expand_' + str(save_path)) if save_path.is_file(): pr(f'File {cyan(save_path)} already exists, overwrite?', '!') if not pause(cancel=True): return except KeyboardInterrupt: return # Get arguments auto_all = False if args: auto_all = args[0] == 'all' _, tmp_path = mkstemp('stargen') tmp_path = Path(tmp_path) # Copy initial content tmp_path.write_bytes(f.read_bytes()) def _capitalize(tmp_p: Path, count: int) -> None: with tmp_p.open('a', encoding='utf8') as file: for k in self._gen_wordlist(f): file.write(k.capitalize() + '\n') self._modifier_wrapper(tmp_path, 'Capitalize', '*2', not auto_all, _capitalize) def _leetify(tmp_p: Path, count: int) -> None: with tmp_p.open('a', encoding='utf8') as file: for k in self._gen_wordlist(f): file.write(leetify(k) + '\n') self._modifier_wrapper(tmp_path, '13371fy', '*2', not auto_all, _leetify) def _mockify(tmp_p: Path, count: int) -> None: with tmp_p.open('a', encoding='utf8') as file: for k in self._gen_wordlist(f): file.write(mockify(k, True) + '\n') file.write(mockify(k, False) + '\n') self._modifier_wrapper(tmp_path, 'MoCkIfY', '*3', not auto_all, _mockify) def _intermix(tmp_p: Path, count: int) -> None: itmr = IterationTimer(count**2) with tmp_p.open('a', encoding='utf8') as file: for a in self._gen_wordlist(f): for b in self._gen_wordlist(f): file.write(a + b + '\n') file.write(b + a + '\n') itmr.tick() self._modifier_wrapper(tmp_path, 'Intermix', '**2', not auto_all, _intermix) # Save as pr(f'Saving as: {cyan(save_path)}') move(tmp_path, save_path) new_lc = count_lines(save_path) # Show current status print() a = [] if new_lc > self.config['list_treshold']: a += ['total'] self.print_all(a)
def aur_procedure(new_package: bool, aur_deps: iter, directory: Path, title: str, new_ver: str): aur_subdir = directory.joinpath('aur') create = False if not aur_subdir.is_dir(): pr('No "aur" subdirectory found, initiate?', '!') if not pause(cancel=True): return create = True pkgbuild = aur_subdir.joinpath('PKGBUILD') aur_remote_url = f'ssh://[email protected]/python-{title}.git' if not create: # Only update pkgbuild version info if not update_pkgbuild_version(pkgbuild, directory, title, new_ver): return else: if not new_package: # clone pr('Cloning existing AUR repo') call(['git', 'clone', aur_remote_url, 'aur'], cwd=directory) # Update pkgbuild version info if not update_pkgbuild_version(pkgbuild, directory, title, new_ver): return else: pr('Creating submodule named aur which will host AUR repo') aur_subdir.mkdir() call(['git', 'init'], cwd=aur_subdir) call(['git', 'remote', 'add', 'aur', aur_remote_url], cwd=aur_subdir) # Get deps: requires = { 'python-' + i for i in check_output(['python3', 'setup.py', '--requires'], cwd=directory).decode().splitlines() if i } lreq = len(requires) pr(f'Added {lreq} dependencies from setup.py') if aur_deps: if 'python' in aur_deps: aur_deps.remove('python') requires.update(aur_deps) pr(f'Added {len(requires) - lreq} dependencies from cli arguments' ) for i in requires: print('\t', i) pr('Using pip2pkgbuild to create a new PKGBUILD in ./aur directory' ) pkgbuild.write_bytes( check_output(['pip2pkgbuild', '-d'] + list(requires) + ['-o', title])) # TODO Insert Maintainer tag pr('Created, go edit it as you see fit and then continue') if not pause(cancel=True): return # TODO Check with namcap # makepkg_srcinfo pr('Dumping SRCINFO') with aur_subdir.joinpath('.SRCINFO').open('w') as srcinfo: if 0 != call( ['makepkg', '--printsrcinfo'], cwd=aur_subdir, stdout=srcinfo): return pr('Bad exit code from makepkg!', 'X') # Commit and push changes to AUR branch_name = check_output(['git', 'branch', '--show-current'], cwd=aur_subdir).decode().strip() if branch_name != 'master': # Currently AUR declines other names pr(f'Renaming branch: {branch_name} to "master" (per AUR policy)') call(['git', 'branch', '-m', 'master'], cwd=aur_subdir) branch_name = check_output(['git', 'branch', '--show-current'], cwd=aur_subdir).decode().strip() pr('Staging updated files') call(['git', 'add', 'PKGBUILD', '.SRCINFO'], cwd=aur_subdir) commit_msg = f'"Updated to v{new_ver}"' pr(f'Committing: {commit_msg}') call(['git', 'commit', '-m', commit_msg], cwd=aur_subdir) pr('Pushing to AUR!') remote_name = check_output(['git', 'remote', 'show'], cwd=aur_subdir).decode().strip() call(['git', 'push', '--set-upstream', remote_name, branch_name], cwd=aur_subdir) if create: if 128 == call(['git', 'status'], stdout=DEVNULL, cwd=directory): return pr( 'No git repo initialized so cannot register the "aur" submodule', '!') pr('Registering a submodule "aur"') call(['git', 'submodule', 'add', aur_remote_url, 'aur'], cwd=directory) return 1 # Success