#!/usr/bin/perl

use Getopt::Std;
$|++;

$VERSION="0.0.1";
$LDIR='./lists';
$FF='fnames.txt';
$LF='lnames.txt';

$TOTALCOUNT=0;
@LETTERS=('a'..'z');

print "Listgen v$VERSION by rain forest puppy [ www.wiretrip.net ]\n";

if (scalar @ARGV == 0) { &usage; exit;}

getopts("ABCDEFPQX:Y:Z", \%args);

$OUT=$ARGV[0]; if($OUT eq ''){&usage; exit;}

if(-e $OUT){print "+ Notice: '$OUT' already exists; we are APPENDING to it.\n".
	"\tIf you want just this list, delete '$OUT' and rerun.\n";}

open(OUT,">>$OUT");

if(defined $args{Y}){
	print "+ Limiting to length $args{Y}\n";
	if($args{Y} < 5){
		print "+ Notice: -Y is low; make sure you 'uniq' the results\n";}
}

if(defined $args{Z}){print "+ Using common name files.\n"; $FF='cfnames.txt'; $LF='clnames.txt';}

if(defined $args{A} || defined $args{B}){
open(FNAMES,"<$LDIR/$FF")||die("! Error: Can't open $LDIR/$FF!\n");

$save='';
while(<FNAMES>){
	$word=$_;
	$word=~tr/\r\n //d;

	if(defined $args{Y}){ # limit size
		$t=substr $word,0,$args{Y};
		$word=$t; undef $t;}

	next if($word eq $save); # kinda helps on -Y ...
	$save=$word;

	if(defined $args{A}){
		print OUT $word,"\n"; $TOTALCOUNT++;
		if(defined $args{X}){
			print OUT $word,$args{X},"\n"; $TOTALCOUNT++;}}

	if(defined $args{B}){
		if(defined $args{Y}){ # limit size -1
			$t=substr $word,0,$args{Y}-1;
			$word=$t; undef $t;}
		for ($c=0; $c<26; $c++){
			print OUT $word, $LETTERS[$c], "\n"; $TOTALCOUNT++;
			if(defined $args{X}){
				print OUT $word,$LETTERS[$c],$args{X},"\n"; $TOTALCOUNT++;}
	}}}
close(FNAMES);}



if(defined $args{C} || defined $args{D}){
open(LNAMES,"<$LDIR/$LF")||die("! Error: Can't open $LDIR/$LF!\n");

$save='';
while(<LNAMES>){
	$word=$_;
	$word=~tr/\r\n //d;

	if(defined $args{Y}){ # limit size
		$t=substr $word,0,$args{Y};
		$word=$t; undef $t;}

	next if($word eq $save); # kinda helps on -Y ...
	$save=$word;

	if(defined $args{C}){
		print OUT $word,"\n"; $TOTALCOUNT++;
		if(defined $args{X}){
			print OUT $word,$args{X},"\n"; $TOTALCOUNT++;}}

	if(defined $args{D}){
		if(defined $args{Y}){ # limit size -1
			$t=substr $word,0,$args{Y}-1;
			$word=$t; undef $t;}
		for ($c=0; $c<26; $c++){
			print OUT $LETTERS[$c],$word,"\n"; $TOTALCOUNT++;
			if(defined $args{X}){
				print OUT $LETTERS[$c],$word,$args{X},"\n"; $TOTALCOUNT++;}
	}}}
close(LNAMES);}

if(defined $args{E}){
	# this is suave and gross all at the same time....
	map { $a=$_; map { $b=$_; map { print OUT $a,$b,$_,"\n";
	} @LETTERS; } @LETTERS; } @LETTERS;
	$TOTALCOUNT += (26 * 26 * 26);

	if(defined $args{X}){
		map { $a=$_; map { $b=$_; map { print OUT $a,$b,$_,$args{X},"\n";
		} @LETTERS; } @LETTERS; } @LETTERS;
		$TOTALCOUNT += (26 * 26 * 26);}
}

if(defined $args{F}){
open(LNAMES,"<$LDIR/$LF")||die("! Error: Can't open $LDIR/$LF!\n");
while(<LNAMES>){ $L=$_; $L=~tr/a-zA-Z0-9//cd;
	open(FNAMES,"<$LDIR/$FF")||die("! Error: Can't open $LDIR/$FF!\n");
	while(<FNAMES>){ $F=$_; $F=~tr/a-zA-Z0-9//cd;
		$word=$F.$L;

		if(defined $args{Y}){ # limit size
			$t=substr $word,0,$args{Y};
			$word=$t; undef $t;}

		print OUT $word,"\n"; $TOTALCOUNT++;
		if(defined $args{X}){
			print OUT $word,$args{X},"\n"; $TOTALCOUNT++;}

}close(FNAMES);}close(LNAMES);}

sleep 1;
print "\n--> Generated $TOTALCOUNT names\n\n";


sub usage {
print <<EOT
Used to brute force user account names

Usage: listgen <however many options> output_file

* Username creation:

	-A  First name (only)
	-B  First name, last initial
	-C  Last name (only)
	-D  First initial, last name
	-E  Three initials (-Y not used)
	-F  First name, last name

* Other accounts:

	-P  Include 'pr0n' accounts
	-Q  Include common technical accounts

* Options:

	-X+ Append string specified (makes copy; after -Y)
	-Y+ Limit to length specified
	-Z  Use only common names (cuts down on volume)
	
	+ requires parameter
EOT
;
}



