#!/v/openpkg/sw/bin/perl
##
##  openpkg-sf.cgi -- SourceForge Dynamic URL Redirection
##

require 5.008;
use CGI;
use CGI::GuruMeditation (-name => "openpkg-sf", -debug => 1);

my $cgi = new CGI;

my $pi = $cgi->path_info();
(my ($sf_project, $sf_url_type, $sf_url_other) = ($pi =~ m/^\/?([A-Za-z0-9-]+)\/(source|track)(\/.*)?$/))
    or die "invalid path info"; 
$sf_url_other ||= "";

my $sf_url;
if ($sf_url_type eq 'source') {
    $sf_url = "http://osdn.dl.sourceforge.net/sourceforge/$sf_project$sf_url_other";
}
elsif ($sf_url_type eq 'track') {
    eval {
        use DBI;
        use DBD::SQLite;
        use DBIx::Simple;
    };
    my $database = "openpkg-sf.d/openpkg-sf.db";
    my $db_init = (-f $database ? 0 : 1);
    (my $db = DBIx::Simple->connect(
        "dbi:SQLite:dbname=$database", "", "",
        { RaiseError => 0, AutoCommit => 0 }
    )) or die "unable to connect to database \"$database\"";
    if ($db_init) {
        $db->query(q{
            CREATE TABLE name2id (
                name    TEXT PRIMARY KEY NOT NULL,
                id      INTEGER,
                expires INTEGER
            );
        }) or die $db->error();
        $db->commit();
    }
    $db->query(q{
        DELETE FROM name2id WHERE expires <= ?;
    }, time());
    my ($id) = $db->query(q{
        SELECT id FROM name2id WHERE name = ?;
    }, $sf_project)->flat();
    if (not defined $id) {
        eval {
            use LWP::Simple;
        };
        my $html = get("http://sourceforge.net/projects/$sf_project/") || "";
        (($id) = ($html =~ m/<a\s+href="\/project\/showfiles\.php\?group_id=(\d+)">/s))
            or die "unable to map SF name to SF group id";
        $db->query(q{
            INSERT INTO name2id (name, id, expires) VALUES (??);
        }, $sf_project, $id, time()+(60*60*24*30)) or die $db->error();
    }
    $db->commit();
    $db->disconnect();
    undef $db;
    $sf_url = sprintf("http://sourceforge.net/project/showfiles.php?group_id=%d%s", $id, $sf_url_other);
}
print $cgi->redirect(
    -uri => $sf_url,
    -status => 302
);

