New CSS class 'topic_index'.
[gruta.git] / Gruta / CGI.pm
blob66a1806d57a6045744533508f2e3c1eb8d929cea
1 package Gruta::CGI;
3 use CGI;
4 use Carp;
6 sub vars { return $_[0]->{cgi}->Vars(); }
7 sub upload_dirs { return @{ $_[0]->{upload_dirs} }; }
9 sub http_headers {
10 my $self = shift;
11 my %headers = @_;
13 foreach my $k (keys(%headers)) {
14 $self->{http_headers}->{$k} = $headers{$k};
17 return $self->{http_headers};
20 sub cookie {
21 my $self = shift;
23 if (@_) {
24 $self->http_headers( 'Set-Cookie', shift );
27 return $ENV{HTTP_COOKIE};
30 sub status { $_[0]->http_headers( 'Status', $_[1] ); }
32 sub redirect {
33 my $self = shift;
34 my $dir = shift;
36 $self->http_headers( 'Location', $self->data->base_url() . $dir );
39 sub data {
40 my $self = shift;
41 my $data = shift;
43 if (defined($data)) {
44 $self->{data} = $data;
47 return $self->{data};
51 sub upload {
52 my $self = shift;
53 my $dir = shift;
54 my $field = shift;
56 my $file = $self->{cgi}->param($field);
57 my ($basename) = ($file =~ /([^\/\\]+)$/);
59 if (! grep(/^$dir$/, $self->upload_dirs())) {
60 croak "Unauthorized upload directory $dir";
63 my $filename = $dir . '/' . $basename;
65 open F, '>' . $filename or croak "Can't write $filename";
66 while(<$file>) {
67 print F $_;
70 close F;
74 sub new {
75 my $class = shift;
77 my $obj = bless( { @_ }, $class );
79 $obj->{charset} ||= 'UTF-8';
81 $obj->{http_headers} = {
82 'Content-Type' => 'text/html; charset=' . $obj->{charset},
83 'X-Gateway-Interface' => $ENV{'GATEWAY_INTERFACE'},
84 'X-Server-Name' => $ENV{'SERVER_NAME'}
87 $obj->{upload_dirs} ||= [];
89 $obj->{cgi} = CGI->new();
91 return $obj;
95 sub run {
96 my $self = shift;
98 my $data = $self->data();
99 my $vars = $self->vars();
101 $data->template->cgi_vars($vars);
103 if ($ENV{REMOTE_USER} and my $u = $data->user($ENV{REMOTE_USER})) {
104 $data->auth( $u );
106 elsif (my $cookie = $self->cookie()) {
107 if (my ($sid) = ($cookie =~ /^sid\s*=\s*(\d+)$/)) {
108 $data->auth_from_sid( $sid );
112 my $st = 'INDEX';
114 if ($vars->{t}) {
115 $st = uc($vars->{t});
118 $st = 'INDEX' unless $st =~ /^[-\w0-9_]+$/;
120 # not identified nor users found?
121 if (!$data->auth() && ! $data->users()) {
123 # create the admin user
124 my $u = Gruta::Data::User->new(
125 id => 'admin',
126 is_admin => 1,
127 can_upload => 1,
128 username => 'Admin',
129 email => 'webmaster@localhost'
132 # set a random password (to be promptly changed)
133 $u->password(rand());
135 # insert the user
136 $data->insert_user($u);
138 # create a new session
139 my $session = Gruta::Data::Session->new(user_id => 'admin');
140 $u->source->insert_session($session);
142 my $sid = $session->get('id');
143 $self->cookie("sid=$sid");
145 $data->auth($u);
147 $st = 'ADMIN';
150 my $body = undef;
152 eval { $body = $data->template->process( $st ) };
154 if ($@) {
155 $data->log($@);
156 # $self->redirect('?t=INDEX');
158 $self->status(500);
159 $body = "<h1>500 Internal Server Error</h1><p>$@</p>";
162 $self->http_headers('X-Powered-By' => 'Gruta ' . $self->data->version());
164 if (!$data->auth()) {
165 use Digest::MD5;
166 use Encode qw(encode_utf8);
168 my $md5 = Digest::MD5->new();
169 $md5->add(encode_utf8($body));
170 my $etag = $md5->hexdigest();
172 my $inm = $ENV{HTTP_IF_NONE_MATCH} || '';
174 if ($inm eq $etag) {
175 $self->status(304);
176 $body = '';
178 else {
179 $self->http_headers('ETag' => $etag);
183 # does the client accept compression?
184 if (length($body) > 10000 && $ENV{HTTP_ACCEPT_ENCODING} =~ /gzip/) {
185 # compress!!
186 use Compress::Zlib;
188 if (my $cbody = Compress::Zlib::memGzip($body)) {
189 $self->http_headers('Content-encoding' => 'gzip');
190 $body = $cbody;
194 my $h = $self->http_headers();
195 foreach my $k (keys(%{ $h })) {
196 print $k, ': ', $h->{$k}, "\n";
198 print "\n";
200 print $body;