#!/usr/bin/perl

use Socket;

%_SERVER=('REMOTE_ADDR','127.0.0.1');

$time_res = 10;

$b32='0123456789abcdefghijklmnopqrstuv';

sub safe_add
{
	my ($a,$b);
	$a=shift;
	while($b=shift) {$a += $b;}
	while(($a&0xffffffff) != $a) {
		if($a<0) {$a+=0xffffffff+1;}
		else {$a-=0xffffffff+1;}
	}
	$a;
}

sub foo
{
	my $a = shift;
	($a ^ ($a >> 9)) & 0x1ff;
}

sub generate_mailaddress
{
	my ($salt,$pepper) = @_;
	my ($s,@c,$x,$i);

	$t=time()>>2; # 29 bits until year 2038
	if($time_res>2) {$t&=(0x1fffffff<<$time_res);}
	
	$long = safe_add(unpack('N',($ip=inet_aton($_SERVER{'REMOTE_ADDR'}))),$salt);
	
	if($ip) {

#		srand(safe_add($long,$t,$pepper));
#		$rand=int(rand(0x200));
		$rand=foo(safe_add($long,$t,$pepper));
		$s='';
		$x=$long; #32 bits
		for($i=0;$i<6;$i++){$s=substr($b32,$x&0x1f,1).$s;$x>>=5;};
		
		$x=($x&0x3)|($t<<2); #2+29=31 bits
		for($i=0;$i<6;$i++){$s=substr($b32,$x&0x1f,1).$s;$x>>=5;};
		
		$x=$x&0x1|$rand<<1; #1+9=10 bits
		for($i=0;$i<2;$i++){$s=substr($b32,$x&0x1f,1).$s;$x>>=5;};
		
		$x=23;
		for($i=0;$i<14;$i++){
			$x+=index($b32,substr($s,$i,1));
			if($x>31){$x-=32;};
			substr($s,$i,1)=substr($b32,$x,1);
		}

		@c=('.','-','_');
		$x=int(rand(4));
		for($i=0;$i<$x;$i++) {
			$y=1+int(rand(14+$i));
			$s=substr($s,0,$y).$c[int(rand(3))].substr($s,$y);
		};
		$s;
	} else { 'invalid' };
}

sub decode_mailaddress
{
	my ($mailaddress, $salt, $pepper, $barf) = @_;

	($s=$mailaddress) =~ s/[-._]//g;;

	$x=23;
	for($i=0;$i<14;$i++){
		$y=index($b32,substr($s,$i,1));
		$x=-$x+$y;
		if($x<0){$x+=32;};
		substr($s,$i,1)=substr($b32,$x,1);
		$x=$y;
	}
	
	$x=0;
	for($i=0;$i<2;$i++){$x=$x<<5|index($b32,substr($s,0,1));$s=substr($s,1);};
	$rnd2=$x>>1;

	$x&=0x1;
	for($i=0;$i<6;$i++){$x=$x<<5|index($b32,substr($s,0,1));$s=substr($s,1);};
	$time2=$x>>2;
	
	for($i=0;$i<6;$i++){$x=($x<<5)|index($b32,substr($s,0,1));$s=substr($s,1);};
	$x &= 0xffffffff;
	
	if($rnd2-foo(safe_add($long,$t,$pepper))) {
		$s="invalid";
	} else {
		$s=join('.',unpack('C4',pack('N',safe_add($x,-$salt)))).' '.
		   gmtime($time2<<2).' GMT';
	}
	$s;
}

$zweiundvierzig=1234567892;
$dreiundzwanzig=3216549874;

$s=generate_mailaddress($dreiundzwanzig,$zweiundvierzig);
print "$s\@nowhere.invalid\n";
print(decode_mailaddress($s,$dreiundzwanzig,$zweiundvierzig).'<br>' . "\n");
#print(decode_mailaddress('x'.$s,$dreiundzwanzig,$zweiundvierzig)."\n");
print(decode_mailaddress($ARGV[0],$dreiundzwanzig,$zweiundvierzig,1)."\n");
