#!/usr/bin/perl -w
#
# index.fcgi - main script of fastcgi-gallery
#
# Developed by Lubomir Host 'rajo' <rajo AT platon.sk>
# 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
Platon Group <platon@platon.org> http://platon.org/
|