#! /usr/bin/perl

use strict;
use warnings;
use Data::Dumper;
use WWW::Curl;
use WWW::Curl::Easy;
use URI::Escape;

use lib "/usr/share/doc/libapache2-mod-auth-pubtkt/examples/perl-login/";
use mod_auth_pubtkt;

my $privkey = shift;
my $failed = 0;

my %defaults = (
		privatekey => $privkey,
		keytype    => "rsa",
		digest     => "sha512",
		clientip   => undef,  # or a valid IP address
		userid     => "someuser",  # or any ID that makes sense to your application, e.g. email
		validuntil => time() + 86400, # valid for one day
		graceperiod=> 3600,   # grace period of an hour
		tokens     => undef,  # comma separated string of tokens.
		userdata   => undef   # any application specific data to pass.
);

sub test_url {
	my $url = shift;
	my $expected_resp = shift;
	my $cookie = shift;

	my $curl = WWW::Curl::Easy->new;

	$curl->setopt(CURLOPT_URL, $url);

	my $response_body = '';
	my $response_header = '';

	$curl->setopt(CURLOPT_WRITEDATA,\$response_body);
	$curl->setopt(CURLOPT_HEADERDATA,\$response_header);
	if ($cookie) {
		$curl->setopt(CURLOPT_COOKIE,"auth_pubtkt=".uri_escape($cookie));
	}

	my $retcode = $curl->perform;

	if ($retcode != 0) {
		print("An error happened for $url: $retcode ".$curl->strerror($retcode)." ".$curl->errbuf."\n");
		exit 1;
	}

	my $response_code = $curl->getinfo(CURLINFO_HTTP_CODE);
	if ($response_code != $expected_resp) {
		$failed = 1;
		print("url $url, got $response_code but expected $expected_resp\n")
	} else {
		print("url $url: $response_code\n")
	}
	#print("Received headers: $response_header\n");
	#print("Received response: $response_body\n");
}

sub get_ticket {
	my $opts = shift;
	return pubtkt_generate(%defaults, %$opts);
}

test_url("http://localhost/public/",200);
test_url("http://localhost/anyuser/",403);
test_url("http://localhost/testuser/",403);

# user someuser
my $ticket = get_ticket({});
print "ticket for user someuser\n";

test_url("http://localhost/anyuser/",200,$ticket);
test_url("http://localhost/testuser/",401,$ticket);


# manually try to edit ticket - this should fail
$ticket =~ s/uid=[^;]*;/uid=testuser/;
print "manually modified ticket\n";

test_url("http://localhost/anyuser/",403,$ticket);
test_url("http://localhost/testuser/",403,$ticket);


# user testuser
$ticket = get_ticket({"userid" => "testuser"});
print "ticket for user testuser\n";

test_url("http://localhost/anyuser/",200,$ticket);
test_url("http://localhost/testuser/",200,$ticket);


# expired ticket
$ticket = get_ticket({"validuntil" => time()-86400});
print "expired ticket\n";

test_url("http://localhost/anyuser/",403,$ticket);
test_url("http://localhost/testuser/",403,$ticket);


# set ip to localhost
$ticket = get_ticket({"clientip" => "127.0.0.1"});
print "ticket for ip 127.0.0.1\n";

test_url("http://127.0.0.1/anyuser/",200,$ticket);
test_url("http://[::1]/testuser/",403,$ticket);


# set ip to localhost
$ticket = get_ticket({"clientip" => "1.2.3.4"});
print "ticket for ip 1.2.3.4\n";

test_url("http://127.0.0.1/anyuser/",403,$ticket);
test_url("http://[::1]/testuser/",403,$ticket);


if ($failed) {
	print("failures found\n");
	exit($failed);
} else {
	print("all ok\n");
}
