aboutsummaryrefslogtreecommitdiff
path: root/gorillanest.pl.cgi
blob: 49a6e4ef2c22964085558412aa779112b11361b7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#!/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();