forked from yuki-kimoto/perlzemitut
-
Notifications
You must be signed in to change notification settings - Fork 0
/
serve.pl
106 lines (87 loc) · 2.62 KB
/
serve.pl
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
use strict;
use warnings;
use utf8;
use Giblog;
use Mojolicious::Lite;
use Mojo::Message::Response;
use File::Temp 'tempfile';
# render CGI
app->hook(before_dispatch => sub {
my $c = shift;
my $req = $c->req;
my $path = $req->url->path->clone;
if ($path =~ /\.cgi$/) {
# Prevent directory traversal
$path->canonicalize;
if ($path =~ /^[\\\/]\./) {
die "Can't contain \. in path \"$path\"";
}
my $method = $c->req->method;
my $script_name = $c->app->home->rel_file("public/$path");
# CGI Environment variable
local $ENV{AUTH_TYPE} = '';
local $ENV{CONTENT_LENGTH} = $req->headers->content_length;
local $ENV{CONTENT_TYPE} = $req->headers->content_type;
local $ENV{GATEWAY_INTERFACE} = 'CGI/1.1';
local $ENV{PATH_INFO} = $req->url->path;
local $ENV{PATH_TRANSLATED} = $req->url->path;
local $ENV{QUERY_STRING} = $req->url->query->to_string;
local $ENV{REMOTE_ADDR} = $c->tx->remote_address;
local $ENV{REMOTE_HOST} = $c->tx->remote_address;
local $ENV{REMOTE_IDENT} = '';
local $ENV{REMOTE_USER} = '';
local $ENV{REQUEST_METHOD} = $method;
local $ENV{SCRIPT_NAME} = $script_name;
local $ENV{SERVER_NAME} = 'localhost';
local $ENV{SERVER_PORT} = $c->tx->remote_port;
local $ENV{SERVER_SOFTWARE} = "Mojolicious (Perl)";
local $ENV{SERVER_PROTOCOL} = 'HTTP/1.1';
# Check script name
unless ($script_name =~ /^[a-zA-Z_0-9\/\-\.]+$/) {
die "Invalid script name";
}
# Check existance of CGI script
unless (-f $script_name) {
die "Not found CGI script";
}
# Run CGI script
my $output;
if ($method eq 'GET') {
# GET requst
$output = `$^X $script_name`;
if ($?) {
$c->res->code('505');
$c->render(text => "Internal Server Error");
}
}
elsif ($method eq 'POST') {
# POST request
my $body = $req->body;
my ($in_fh, $in_file) = tempfile;
print $in_fh $body;
close $in_fh;
$output = `$^X -pe "" $in_file | $^X $script_name`;
if ($?) {
$c->res->code('505');
$c->render(text => "Internal Server Error");
}
unlink $in_file;
}
# Header part and body part
my ($header_part, $body_part) = split("\n\n", $output, 2);
# Response
my $res = Mojo::Message::Response->new;
while (!$res->is_finished) {
$res->parse($header_part);
}
$c->res->code($res->code);
$c->res->headers($res->headers);
$c->render(data => $body_part);
}
});
# Build
Giblog->build;
# Mojolicious::Lite Application
my $app = app;
# Serve
Giblog->serve($app);