OpenIndex
view release on metacpan or search on metacpan
OpenIndex.pm view on Meta::CPAN
$iconfig->{thumb_min_size} = $r->dir_config("ThumbMinSize") || 5000;
$iconfig->{thumb_width} = $r->dir_config("ThumbWidth");
$iconfig->{thumb_height} = $r->dir_config("ThumbHeight");
$iconfig->{thumb_height} = $r->dir_config("ThumbHeight");
$iconfig->{thumb_scale_width} = $r->dir_config("ThumbScaleWidth");
$iconfig->{thumb_scale_height} = $r->dir_config("ThumbScaleHeight");
$iconfig->{changed} = 0;
foreach (keys %$iconfig){
next unless /^thumb/;
if ($iconfig->{$_} != $oldopts->{$_}) {
$iconfig->{changed} = 1;
last;
}
}
unless ($iconfig->{cache_ok} && ((not -e "$cachedir/.config") || -w _) && store $iconfig, "$cachedir/.config") {
$iconfig->{changed} = 0;
}
}
sub read_dir {
my ($r,$args,$dirhandle) = @_;
my $cfg = Apache::ModuleConfig->get($r);
my @listing;
my %list;
my @accept;
my $size;
my $hide=!($args->{isadmin} && $dodump);
my $ignore_regex;
$ignore_regex = join('$|^',@{$cfg->{ignore}}) if $cfg->{ignore};
if($cfg->{options} & THUMBNAILS) {
#Decode the content-encoding accept field of the client
foreach (split(',\s*',$r->header_in('Accept'))) {
push @accept, $_ if m:^image/:o;
}
}
$args->{bytes}=0;
while(my $file = readdir $dirhandle) {
next if $file=~m/^\.$/o; # Never display '.' directory
next if $hide && $file=~m/^$ignore_regex$/;
push @listing, $file;
my $subr = $r->lookup_file($file);
$list{$file}{uid}=(stat $subr->finfo)[4];
$list{$file}{gid}=(stat _)[5];
$size = -s _;
$list{$file}{size} = $size;
$args->{bytes}+=$size;
if (-d _) {
$list{$file}{size} = -1;
$list{$file}{sizenice} = '-';
} else {
$list{$file}{sizenice} = size_string($list{$file}{size});
$list{$file}{sizenice} =~ s/\s*//;
}
$list{$file}{mod} = (stat _)[9];
$list{$file}{modnice} = ht_time($list{$file}{mod}, "%d-%b-%Y %H:%M", 0);
$list{$file}{modnice} =~ s/\s/ /g;
$list{$file}{mode} = write_mod((stat _)[2]);
$list{$file}{type} = $subr->content_type;
if(($list{$file}{type} =~ m:^image/:o) &&
($cfg->{options} & THUMBNAILS ) &&
Apache->module("Image::Magick")) {
if ($iconfig->{cache_ok}) {
($list{$file}{icon},$list{$file}{width},$list{$file}{height}) = get_thumbnail($r, $file, $list{$file}{mod}, $list{$file}{type}, @accept);
}
}
$list{$file}{height} ||= $cfg->{icon_height};
$list{$file}{width} ||= $cfg->{icon_width};
# icons size might be calculated on the fly and cached...
my $icon = Apache::Icon->new($subr);
$list{$file}{icon} ||= $icon->find;
if (-d _) {
$list{$file}{icon} ||= $icon->default('^^DIRECTORY^^');
$list{$file}{alt} = "DIR";
}
$list{$file}{icon} ||= $icon->default;
$list{$file}{alt} ||= $icon->alt;
$list{$file}{alt} ||= "???";
foreach (keys %{$cfg->{desc}}) {
$list{$file}{desc} = $cfg->{desc}{$_} if $subr->filename =~ /$_/;
}
if($list{$file}{type} eq "text/html" and
($cfg->{options} & SCAN_HTML_TITLES) and
not $list{$file}{desc}) {
use HTML::HeadParser;
my $parser = HTML::HeadParser->new;
open FILE, $subr->filename;
while (<FILE>) {
last unless $parser->parse($_);
}
$list{$file}{desc} = $parser->header('Title');
close FILE;
}
$list{$file}{desc} ||= " ";
}
return \%list;
}
sub do_sort {
my ($list,$query,$default,$foldersfirst) = @_;
my @names = sort keys %$list;
shift @names; #removes '..'
#handle default sorting
unless ($query->{N} || $query->{S} || $query->{D} || $query->{M}) {
$default =~ /(.)(.)/;
$query->{$1} = $2;
}
if($query->{N}) {
@names = sort file_ext @names if $query->{N} eq 'E';
@names = sort @names if $query->{N} eq 'D';
@names = reverse sort @names if $query->{N} eq "A";
} elsif($query->{S}) {
@names = sort { $list->{$b}{size} <=> $list->{$a}{size} } @names if $query->{S} eq "D";
@names = sort { $list->{$a}{size} <=> $list->{$b}{size} } @names if $query->{S} eq "A";
} elsif($query->{M}) {
@names = sort { $list->{$b}{mod} <=> $list->{$a}{mod} } @names if $query->{M} eq "D";
@names = sort { $list->{$a}{mod} <=> $list->{$b}{mod} } @names if $query->{M} eq "A";
} elsif($query->{D}) {
@names = sort { $list->{$b}{desc} cmp $list->{$a}{desc} } @names if $query->{D} eq "D";
@names = sort { $list->{$a}{desc} cmp $list->{$b}{desc} } @names if $query->{D} eq "A";
}
unshift @names, '..'; #puts back '..' on top of the pile
if($foldersfirst) {
my @folders;
for(my $n=0; $n<@names; ) {
if($list->{$names[$n]}{sizenice} eq '-') {
push @folders,$names[$n];# Add dir to @folders
splice(@names,$n,1); # Remove dir from @names
} else {
$n++;
}
}
splice(@names,0,0,@folders);
}
return \@names;
}
sub file_ext {
my @aa=split /\./,$a;
my @ba=split /\./,$b;
my $an=$#aa;
my $bn=$#ba;
my $retval=0;
while($an>=1 && $bn>=1) {
return $retval if($retval=$aa[$an--] cmp $ba[$bn--]);
}
return $aa[$an] cmp $ba[$bn] if $an==$bn;
return 1 if $bn<1;
return -1 if $an<1;
0;
}
sub get_thumbnail {
my ($r, $filename, $mod, $content, @accept) = @_;
my $accept = join('|', @accept);
my $dir = $r->filename;
#these should sound better.
my $cachedir = $iconfig->{cache_dir};
my $xresize;
my $yresize;
my $img = Image::Magick->new;
my($imgx, $imgy, $img_size, $img_type) = split(',', $img->Ping($dir . $filename));
#Is the image OK?
return "/icons/broken.gif" unless ($imgx && $imgy);
if (($content =~ /$content/) && ($img_type =~ /JPE?G|GIF|PNG/i)) {
if ($dir =~ /$cachedir\/$/) { #We know that what we'll generate will be seen.
return $filename, $imgx, $imgy #Avoiding recursive thumbnails from Hell
}
return undef if $img_size > $iconfig->{thumb_max_size}; #The image is way too big to try to process...
if(defined $iconfig->{thumb_scale_width} ||
defined $iconfig->{thumb_scale_height}) {
#Factor scaling
$xresize = $iconfig->{thumb_scale_width} * $imgx if defined $iconfig->{thumb_scale_width};
$yresize = $iconfig->{thumb_scale_height} * $imgy if defined $iconfig->{thumb_scale_height};
} elsif(defined $iconfig->{thumb_width} ||
defined $iconfig->{thumb_height}) {
#Absolute scaling
$xresize = $iconfig->{thumb_width}
if defined $iconfig->{thumb_width};
$yresize = $iconfig->{thumb_height}
if defined $iconfig->{thumb_height};
}
#preserve ratio if we can
$xresize ||= $yresize * ($imgx/$imgy);
$yresize ||= $xresize * ($imgy/$imgx);
#default if values are missing.
$xresize ||= DEFAULT_ICON_WIDTH;
$yresize ||= DEFAULT_ICON_HEIGHT;
#round off for picky browsers
$xresize = int($xresize);
$yresize = int($yresize);
#Image is too small to actually resize. Simply resize with the WIDTH and HEIGHT attributes of the IMG tag
return ($filename, $xresize , $yresize) if $img_size < $iconfig->{thumb_min_size};
if ($iconfig->{changed} || $mod > (stat "$dir$cachedir/$filename")[9]) {
#We should actually resize the image
if ($img->Read($dir . $filename)) { #Image is broken
return "/icons/broken.gif";
}
$nThumb++;
$img->Sample(width=>$xresize, height=>$yresize);
$img->Write("$dir$cachedir/$filename");
}
return "$cachedir/$filename", $xresize , $yresize;
}
return undef;
}
sub write_mod {
my $mod = shift ;
$mod = $mod & 4095;
my $letters;
my %modes = (
1 => 'x',
2 => 'w',
4 => 'r',
);
foreach my $f (64,8,1){
foreach my $key (4,2,1) {
if ($mod & ($key * $f)){
$letters .= $modes{$key};
} else {
$letters .= '-';
}
}
}
return $letters;
}
sub new{bless{},shift;}
1;
__END__
=head1 NAME
Apache::OpenIndex - Perl Open Index manager for a Apache Web server
=head1 SYNOPSIS
PerlModule Apache::Icon
PerlModule Apache::OpenIndex
(PerlModule Apache::Language) optional
(PerlModule Image::Magick) optional
=head1 DESCRIPTION
OpenIndex provides a file manager for a web sites through a web
browser. It is a extensive rewrite of the Apache::AutoIndex.pm
module which in turn was a remake of the autoindex Apache
module. OpenIndex can provide the same functionality as
AutoIndex.pm and can be used to both navigate and manage the web
site.
OpenIndex has dropped the mod_dir support provided by AutoIndex.
In order to activate the file manager functionality, two things
have to happen. First, the proper http.conf directives need to
be placed into a <Location area> section. Second, there has to
be a directory stub (.XOI) created off of the directory where
the file manager is to be provided.
Within the ROOT directory stub (.XOI), a MARK sub-directory
(.XOI/.MARK) can also be provided to present a MARK directory
tree by the file manager. The MARK (.XOI/.MARK) directory
provides a physical directory where files can be managed,
unzipped, moved, copied, deleted, and renamed. New directories
can be created with the mkdir command. The MARK directory can
be mapped to any path location on the Apache server or to any
site path location. To activate the MARK directory access
the "mark" directive needs to be set to '1'. The ROOT (.XOI)
directory is actually a fake path of the site's root directory.
For example to access "http://www.site.com/bob/" the following
URL would be required:
"http://www.site.com/bob/.XOI/"
This would in turn would display the file manager for bob. To
Bob, the ROOT directory appears to be his actual web root
directory.
If the above description does not make sense, just follow the
examples provided, and perhaps it will become clearer once you
see some results.
Since a URL fake path (.XOI) is provided, authentication and
authorization can be used to only allow authorized users to
have access to the OpenIndex module.
In short, you will no longer need to use ftp to upload and
manage the web site files. Since OpenIndex is web based, you can
use all of your other Apache functionality, such as SSL,
proxies, and etc.
The best procedure to get OpenIndex loaded and working is to first
have the Apache mod_perl and autoindex modules loaded and
working properly. Then remove the httpd.conf
"AddModule autoindex"
directive and add the Apache::Icon and Apache::OpenIndex module
directives.
=head1 DIRECTIVES
=head2 Loading the Modules
OpenIndex.pm view on Meta::CPAN
Is the maximum number of items that must be selected
by the OpenIndex user. A value of 0, means there is no
maximum number.
src=>arg
This tells OpenIndex which argument contains the source
string for the command. Normally this is the list of
items from the directory index listing. However, you
can use any input you like by perhaps setting an @args
string in the before=>routine.
dst=>arg
This tells OpenIndex which argument contains the destination
string for the command. Normally this is the text in
"Destination" text form field. However, you can use
any input you like by perhaps setting an @args string
in the before=>routine.
req=>arg
This tells OpenIndex to check and make sure that a value
is contained in the argument. The default is to have
an item selected from the directory index listing.
admin=>1
Requires that user is the admin user in order to execute
the commands submitted.
=item * OpenIndexOptions Always package subroutine arguments
"This is another real cool directive!" It allows you to
specify an external command to run before each OpenIndex
managed page is processed. This is where you would hook
in a quota check routine and so forth. The arguments
are only for use by the command specified.
=back
=head1 THUMBNAILS
Generation of thumbnails is possible. This means that listing a
directory that contains images can be listed with little reduced
thumbnails beside each image name instead of the standard
'image' icon.
To enable this you simply need to preload Image::Macick in
Apache. The IndexOption option Thumbnails controls thumbnails
generation for specific directories like any other IndexOption
directive.
=head2 USAGE
The way thumbnails are generated/produced can be configured in
many ways. A general overview of the procedure follows.
For each directory containing pictures, there will be a
.thumbnails directory created in it that will hold the thumbnails.
Each time the directory is accessed, and if thumbnail generation
is active, small thumbnails will be produced, shown beside each
image name, instead of the normal , generic, image icon.
That can be done in 2 ways. In the case the image is pretty
small, no actual thumbnail will be created. Instead the image
will resize the HEIGHT and WIDTH attributes of the IMG tag.
If the image is big enough, Image::Magick will resize it and
save (cache) it in the .thumbnails directory for the next
requests.
Changing configuration options will correctly refresh the cached
thumbnails. Also, if the original image is modified, the
thumbnail will be updated accordingly. Still, the browser might
screw things up if it preserves the cached images.
=head2 Thumbnail DIRECTIVES
=over
=item * IndexCacheDir dir
This is the name of the directory where the generated thumbnails
will be created. Make sure the user under which the web server
runs has read and write permissions. Defaults to .thumbnails
=item * IndexCreateDir 0|1
Specifies that when a cache directory isn't found, should an
attempt to be made to create it. Defaults to 1(true), meaning if
possible, a missing cache directories will be created.
=item * ThumbMaxFilesize bytes
This value fixes the maximum size of an image at which thumbnail
processing isn't even attempted. Trying to process a few
very big images could bring a server down to it's knees.
Defaults to 500,000
=item * ThumbMinFilesize bytes
This value fixes the minimum size of an image at which thumbnail
processing isn't actually done. Since trying to process already
very small images could be an overkill, the image is simply
resized with the size attributes of the IMG tag. Defaults to
5,000.
=item * ThumbMaxWidth pixels
This value fixes the maximum x-size of an image at which
thumbnail processing isn't actually done. Since trying to
process already very small images would be an overkill, the
image is simply resized with the size attributes of the IMG tag.
Defaults to 4 times the default icon width.
=item * ThumbMaxHeight pixels
This value fixes the maximum y-size of an image at which
thumbnail processing isn't actually done. Since trying to
process already very small images would be an overkill, the
image is simply resized with the size attributes of the IMG tag.
Defaults to 4 times the default icon height
=item * ThumbScaleWidth scaling-factor
Preserved only if there is no scaling factor for the other axis
of the image.
=item * ThumbScaleHeight scaling-factor
This value fixes an y-scaling factor between 0 and 1 to resize
the images. The image ratio will be preserved only if there is
no scaling factor for the other axis of the image.
=item * ThumbWidth pixels
This value fixes a fixed x-dimension to resize the image. The
image ratio will be preserved only if there is no fixed scaling
factor for the other axis of the image. This has no effect if a
scaling factor is defined.
=item * ThumbHeight pixels
This value fixes a fixed x-dimension to resize the image. The
image ratio will be preserved only if there is no fixed scaling
factor for the other axis of the image. This has no effect if a
scaling factor is defined.
=back
=head1 TODO
The thumbnail support needs to be tested. It was provide with
Apache:: AutoIndex, but I have not tested it yet.
Some minor changes to the thumbnails options will still have the
thumbnails regenerated. This should be avoided by checking the
attributes of the already existing thumbnail.
Some form of garbage collection should be performed on thumbnail
cache or the directories will fill up.
=head1 SEE ALSO
perl(1), L<Apache>(3), L<Apache::Icon>(3), L<Image::Magick>(3) .
L<Apache::AutoIndex>(3)
=head1 SUPPORT
Please send any questions or comments to the Apache modperl
mailing list <modperl@apache.org> or to me at <perler@xorgate.com>
=head1 NOTES
This code was made possible by :
=over
=item Philippe M. Chiasson
<gozer@ectoplasm.dyndns.com> Creator of Apache::AutoIndex.
=item Doug MacEachern
<dougm@pobox.com> Creator of Apache::Icon, and of course, mod_perl.
=item Rob McCool
Who produced the final mod_autoindex.c I copied, hrm.., well,
translated to perl.
=item The mod_perl mailing-list
at <modperl@apache.org> for all your mod_perl related problems.
=back
=head1 AUTHOR
George Sanderson <george@xorgate.com>
=head1 COPYRIGHT
Copyright (c) 2000-2001 George Sanderson All rights reserved.
This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.
Copyright (c) 1999 Philippe M. Chiasson. All rights reserved.
This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.
=cut
( run in 1.354 second using v1.01-cache-2.11-cpan-39bf76dae61 )