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} ||= "&nbsp;";
    }
    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 )