#!/usr/bin/perl -w
# huw@munted.org 2005
# A very basic tinyurl-a-like
# TODO improve error checking, especially for the database connection.
# TODO produce debug output ;)
# TODO make pretty
use strict;

use CGI;
use HTML::Form;
use HTTP::Cookies;
use HTTP::Headers;
#use LWP::Debug qw(+);
use DBI;

# config

# 0 = off, 1 = on
my $debug = 1;

# database
my $dbname = 'shrinkurl';
my $dbhost = 'somehost';
my $dbuser = 'shrinkurl';
my $dbpass = 'somepassword';
my $dbport = '3306';

# urlbase should be the host serving this
my $urlbase = "http://shrinkurl.example.com\n";
my $surl_length = 6; # the url key length
# config end

my $cgi = CGI->new;
my $dbh;

if ($cgi->param('id')) {
	database_connect();
	my $sql = "SELECT url from Url where rid=?";
	my $sth = $dbh->prepare($sql);
	$sth->execute($cgi->param('id'));
	my @row = $sth->fetchrow_array();
	if (!$row[0]) {
		# invalid url
		print $cgi->header('text/html'),	
		$cgi->html("This url is invalid") if !$row[0];
		print $cgi->html("<p><a href=\"$urlbase\">Enter a new url</a>");
		exit;
	}
	print $cgi->redirect(-uri => "$row[0]", -status => 301 -nph => 1);
	exit;
}
elsif ($cgi->param('url2shrink')) {
    database_connect();
    my $rid = get_rid();
	if (!$rid) {
		$rid = get_rid() while !$rid;
	}
    my $sth = $dbh->prepare("INSERT into Url (rid,url) VALUES (?, ?)");
    $sth->execute($rid, $cgi->param('url2shrink')) if ($cgi->param('url2shrink') =~ /^http.*$/);
    $cgi->hidden('suburl', $cgi->param('url2shrink'));
	print $cgi->header('text/html');
    print $cgi->html("<p>") if $rid;
    print $cgi->html("Your shrunk url is <a href=\"$urlbase?id=$rid\">$urlbase?id=$rid</a>\n") if $rid;
	print $cgi->html('</p><p>') if $rid;
	print $cgi->html("<a href=\"$urlbase\">Enter a new url</a>") if $rid;
	exit;
}
else {
	print $cgi->header('text/html'),
		$cgi->html("Enter a url :- "),
		$cgi->start_form,
		$cgi->textfield(-name => 'url2shrink', -size => 40),
		$cgi->submit(-name => "Submit"),
		$cgi->reset,
		$cgi->end_form,
		$cgi->end_html;
}

sub get_rid {
	my $rid;
	my $length = $surl_length;
	while (1) {
		($rid .= sprintf("%x", int(rand(16)))) while ($length--);
		my $check_sql = "SELECT count(*) FROM Url where rid='".$rid."'";
		my $sth = $dbh->prepare($check_sql);
		$sth->execute or die "Could not execute query $check_sql : $!\n";
		my @row = $sth->fetchrow_array();
		return $rid if (@row != 0);
	}
}

sub database_connect {
	$dbh = DBI->connect("DBI:mysql:$dbname:$dbhost:$dbport", $dbuser, $dbpass) or die "Cant connect to database\n";
}
