#!/usr/bin/perl -w # # index.fcgi - main script of fastcgi-gallery # # Developed by Lubomir Host 'rajo' # Copyright (c) 2004-2006 Platon Group, http://platon.sk/ # Licensed under terms of GNU General Public License. # All rights reserved. # # Homepage: http://fastcgi-gallery.platon.sk/ # CVS web interface: http://platon.sk/cvs/cvs.php/web-apps/fastcgi-gallery/ # Development page: http://platon.sk/projects/main_page.php?project_id=13 # # Changelog: # 2004-04-17 - created # # $Id: index.fcgi,v 1.9 2006/03/24 17:34:16 rajo Exp $ use strict; use FindBin; use lib "$FindBin::Bin/_modules"; use vars qw ( $VERSION $DEBUG ) ; $VERSION = sprintf("%d", q$Revision: 1.9 $ =~ /(\d+)/); $DEBUG = 0 unless defined $DEBUG; umask 022; use FCGI; use CGI qw(-compile param cookie url_encode); use Template; use Time::HiRes qw(gettimeofday tv_interval); use POSIX qw(strftime); use English; use Env; use Data::Dumper; use CGI::Carp qw(fatalsToBrowser); use Platon::FastCGI::Restart; use Platon::File::Spec::Unix; use config; use templates; use gallery; use vars qw ( $req $config $restart $template $db @languages $gallery $gallery_config $gallery_data $gallery_cache_time $gallery_cache @messages $lang_hash $in_reply $admin_mode @http_cookie $start_time ); # # Functions declaration # sub MyPage($$;); sub send_content($;); sub cur_date(); $req = FCGI::Request(); $config = config->new(); $restart = Platon::FastCGI::Restart->new({ restart_func => sub { $req->LastCall(); exit 0; }, use_lock => 'true', lock_dir => '/var/tmp', max_restart_interval => 10, CHECK_USER_MODULES => 'true', CHECK_SYSTEM_MODULES => 'false', }); @languages = ( { 'abbrev' => 'en', 'language' => 'English' }, { 'abbrev' => 'sk', 'language' => 'Slovak' }, ); $gallery_config = { # {{{ GalleryRootText => '[lang:en]Gallery[/lang:en][lang:sk]Galéria[/lang:sk]', GalleryRootURI => '', GalleryIconsURI => 'images/icons/gallery', GalleryRootPath => "$FindBin::Bin/gallery/", GalleryDocLocation => '/gallery', GalleryCacheDir => "$FindBin::Bin/cache/", + GalleryDirectCacheAccess => '/cache', GallerySizes => [ qw(320 640 800) ], GallerySlideshowIntervals => [ qw(2 3 5 10 30) ], GalleryThumbnailSize => '140x105', #GalleryMaxThumbnailsPerPage => 2, #GalleryDocFile => '', #GalleryImgFile => '', #GalleryQuality => 95, GalleryAllowOriginal => 1, GalleryThumbnailSizeLS => 1, GalleryMemoize => 0, GalleryInfo => 'Camera => Make, Model => Model, Date => DateTimeOriginal, Shutter speed => ExposureTime, Aperture => FNumber, ISO sensitivity => ISOSpeedRatings, Focal length => FocalLength, Flash => Flash, Digital zoom => Tag-0xa404, Exposure mode => Tag-0xa402, Subject distance range => Tag-0xa40c, ', }; # }}} $gallery = gallery->new($gallery_config); foreach my $lang (@languages) { $lang_hash->{$lang->{abbrev}} = $lang->{language}; $template->{$lang->{abbrev}} = templates->new($config, $lang->{abbrev}); } #$gallery_cache_time = 3600; # seconds #$gallery_cache_time = 600; # seconds $gallery_cache_time = 1; # seconds $gallery_cache = { }; # # MAIN: # $restart->add_loaded_modules(); $restart->add_files( '_modules/Platon/Template/Plugin/Interval.pm', '_modules/obfuscator.pm'); while ( $config->run() && ($req->Accept() >= 0) ) { my %cookie; my %query; @messages = (); $in_reply = 0; $admin_mode = 0; $start_time = Time::HiRes::gettimeofday; my $cache_time = int($start_time / $gallery_cache_time); # # Parse query and cookies # {{{ CGI::_reset_globals; my $cgi = CGI->new(); foreach my $key ($cgi->param()) { my @val = $cgi->param($key); #$query{$key} = scalar(@val) > 1 ? \@val : $val[0]; $query{$key} = $val[0]; } foreach my $key ($cgi->cookie()) { my @val = $cgi->cookie($key); $cookie{$key} = $val[0]; } #warn Dumper(\%query, \%cookie); # }}} if (!defined($query{page}) or $query{page} !~ m/^\d{1,4}$/) { $query{page} = 0; } if ( !defined($query{lang}) or $query{lang} eq '' or !defined($lang_hash->{$query{lang}}) or $lang_hash->{$query{lang}} eq '') { $query{lang} = 'en' } if (!defined($query{gallery}) or $query{gallery} eq '') { $query{gallery} = '/'; } if (exists $query{gallery}) { # {{{ my $filename = $query{gallery} || '/'; $filename = Platon::File::Spec::Unix->canonpath("/$filename"); $filename =~ s|^(\.\./)+||g; # ignore leading ../ $filename =~ s|^\.$|/|g; # . --> / $filename =~ s|^\./$|/|g; # ./ --> / $query{gallery} = $filename; my $topdir = ($gallery_config->{GalleryRootPath} or '.'); my $abs_filename = Platon::File::Spec::Unix->canonpath("$topdir/$filename"); if (-d $abs_filename) { $query{gallery} = "$query{gallery}/"; $query{gallery} =~ s#/*$#/#; } # ignore cached files handled by gallery if ((defined($query{gallery}) and $query{gallery} =~ m/^\.cache\//) or (defined($query{GalleryShowOriginal}) and $query{GalleryShowOriginal} eq '1')) { $gallery_data = $gallery->handler(\%query, \%cookie); } else { my $merge; while (my ($key, $val) = each %cookie) { $merge->{$key} = $val; } while (my ($key, $val) = each %query) { $merge->{$key} = $val; } foreach my $key (qw'lang page template') { delete $merge->{$key}; } my $cache_key = ''; foreach my $key (sort keys %$merge) { $cache_key .= "&$key=" . url_encode($merge->{$key}); } if (exists $gallery_cache->{$cache_time} and exists $gallery_cache->{$cache_time}->{$cache_key}) { #print STDERR "POUZIVAM CACHE\n"; $gallery_data = $gallery_cache->{$cache_time}->{$cache_key}; } else { # cache not found $gallery_data = $gallery->handler(\%query, \%cookie); if (defined($gallery_data) and ref($gallery_data) eq 'HASH' and !exists($gallery_data->{error}) and $gallery_data->{use_cache} == 1 ) { $gallery_cache->{$cache_time}->{$cache_key} = $gallery_data; } elsif (exists($gallery_data->{error})) { warn "NOT using cache, error is: " . Dumper($gallery_data); } } } if (defined($gallery_data) and ref($gallery_data) eq 'HASH') { if (defined $gallery_data->{cookie}) { while (my ($key, $value) = each %{$gallery_data->{cookie}}) { push @http_cookie, CGI::cookie('-name' => $key, '-value' => $value); } } if (defined $gallery_data->{content}) { send_content($gallery_data->{content}); } else { MyPage(\%query, \%cookie); } } } # }}} $restart->restart($ENV{SCRIPT_FILENAME}); $req->Finish(); # cache cleanup foreach my $key (keys %$gallery_cache) { delete $gallery_cache->{$key} if ($key != $cache_time); } #warn Dumper([keys %{$gallery_cache->{$cache_time}}]); my $curr_time = Time::HiRes::gettimeofday; #print STDERR cur_date(), " PAGE GENERATED IN: ", sprintf('%4g', $curr_time - $start_time), "\t$ENV{REMOTE_ADDR}\thttp://$ENV{SERVER_NAME}$ENV{REQUEST_URI}\t$ENV{HTTP_USER_AGENT}\n"; undef $gallery_data; undef @http_cookie; undef %cookie; undef %query; } exit 0; sub MyPage($$;) { # {{{ my ($ref_query, $ref_cookie, $err_array) = @_; #push @http_cookie, CGI::cookie('-name' => 'menu', '-value' => $menu_cookie); my $template_data = { query => $ref_query, cookie => $ref_cookie, messages => \@messages, admin_mode => $admin_mode, start_time => $start_time, languages => \@languages, gallery => $gallery_data, http_cookie => \@http_cookie, }; # slideshow handling if (defined $gallery_data->{refresh} and ref($gallery_data->{refresh}) eq 'HASH') { $template_data->{refresh} = $gallery_data->{refresh}; } $in_reply = 1; $template->{$ref_query->{lang}}->process('index.tt2', $template_data) or die $template->{$ref_query->{lang}}->error(), "\n"; } # }}} sub send_content($;) { # {{{ my ($data) = @_; $in_reply = 1; print "Pragma: No-cache\n"; print "Cache-Control: private\n"; print "Accept-Ranges: bytes\n"; print "Content-Length: " . length($data->{data}) . "\n"; print "Content-Location: $data->{location}\n" if (defined $data->{location}); # print "Content-Location: $filename\n"; print "Content-type: $data->{mime_type}\r\n\r\n"; print $data->{data}; } # }}} sub cur_date() { # {{{ my $time_string = strftime "%Y-%m-%d %X", localtime; return $time_string; } # }}} # vim: ft=perl # vim600: fdm=marker fdl=0 fdc=3