#!/usr/bin/env perl use strict; use warnings; use CGI; use FCGI; use Switch::Back; use Syntax::Keyword::Try; use Template; use URI::Escape; use Cwd; use Data::Dumper; use Git::Repository; use lib '.'; BEGIN { require 'config.pl'; } sub info { warn join(' ', @_); } # significant dirs only sub GN::directories { my $root = $_[0]; opendir my $dir, $root or die "$root: $!"; my @directories; my %drop = ( '.' => 0, '..' => 0, ); foreach (readdir $dir) { push(@directories, $_) if (-d join('/', $_[0], $_) && ($drop{$_} // 1)); } closedir $dir; return \@directories; } # probably should output all repos recursively, currently just outputs list of users sub GN::index { # / my ($root, $dataref) = @_; my %data = %$dataref; my @directories = map { my $i = $_; map { join('/', $i, $_) } @{GN::directories(join('/', $root, $i))} } @{GN::directories($root)}; $data{directories} = \@directories; if ($data{directories}) { $data{found} = 1; } return \%data; } sub GN::user { # /$username/ my ($root, $dataref) = @_; my %data = %$dataref; my @directories = @{GN::directories(join('/', $root, $data{username}))}; $data{directories} = \@directories; if ($data{directories}) { $data{found} = 1; } return \%data; } sub GN::repository { # /$username/$repository my ($root, $dataref) = @_; my %data = %$dataref; $data{found} = 0; return \%data; } sub GN::main { open STDERR, '>', LOG_FILE or die LOG_FILE . ": $!"; my $sock = FCGI::OpenSocket('/tmp/gorillanest.socket', 100); try { my $root = GIT_ROOT; my $dbfile = DB_FILE; my %data = ( found => 0, access => 0, ); my $request = FCGI::Request(\*STDIN, \*STDOUT, \*STDERR, \%ENV, $sock); my $template = Template->new({INCLUDE_PATH => TEMPLATE_ROOT}); my $head = 0; my $a_template; while($request->Accept() >= 0) { $data{access} += 1; my $cgi = CGI->new; my %header = ( -Content_Type => 'text/html', -charset => 'UTF-8', ); my $method = $ENV{'REQUEST_METHOD'} || ''; my $uri = $ENV{'REQUEST_URI'} || '/'; if ($method eq 'HEAD') { $head = 1; } elsif ($method eq 'GET') { ($data{username}, $data{repository}) = $uri =~ USER_REPOSITORY; info("name:", $data{username} || '', "repo:", $data{repository} || ''); if ($uri eq '/') { %data = %{GN::index($root, \%data)}; $a_template = "index.tt"; } elsif ($data{repository}) { %data = %{GN::repository($root, \%data)}; $a_template = "repository.tt"; } elsif ($data{username}) { %data = %{GN::user($root, \%data)}; $a_template = "index_user.tt"; } if (!$data{found}) { $header{-status} = '404 Not Found'; $a_template = "404.tt"; } print $cgi->header(%header); if ($head) { $head = 0; continue; } $template->process($a_template, \%data) or info("Template: " . $template->error()); } else { $header{-status} = '405 Method Not Allowed'; print $cgi->header(%header); } } } catch ($error) { info("Crashed: $error"); } FCGI::CloseSocket($sock); } GN::main();