Category: | CGI Programming |
Author/Contact Info | /msg Coruscate |
Description: | A script that allows you to serve images to html pages based on catagory. A catagory simply consists of one or more directories which contain related images. The two required parameters to the script are 'm' and 'c'. 'm' is the method of invocation, 'c' is the catagory. The script currently supports 3 methods of invocation:
Notes: To add an image to a page, simply use <img src="/cgi-bin/image.pl?m=random&c=all"> (replacing the arguments with your own). Catagory 'all' is added by default and consists of all the catagories. This allows you to display a random or image from all catagories, as well as rotating through the entire collection. Caveats: The 'image' method of invocation will show the first image that it finds with the filename supplied. So if catagory 'cars' points to directories '/var/www/images/cars' and '/var/www/images/vehicles' and both of these directories contain a 'toyota.jpg' (perhaps these are two different images), there is currently no way to specify which image you want to show. You have to do 'c=cars/toyota', and the script will display the first one it finds. Todo list: Improve code (if possible?), allow specific pointing to any image within a catagory (even if they have the same name) with the 'image' method of invocation (see 'Caveats' above for more info). Also, add File::Find to the mix to have catagories dive into all sub-directories of the specified directories. Last, make this help stuff into POD within the code to minimize this description :) I will be adding support for merlyn's suggestion (see below). Updates:
|
#!/usr/bin/perl -Tw use strict; use Storable qw/lock_store lock_retrieve/; use CGI qw/:standard/; ######################### # Begin Config # File to store 'rotate' data in. # CGI instance must have read/write access my $data_file = '/var/www/images.dat'; # Image to show if there's an error # ie: "Error", "404 Not Found" image my $err_img = '/var/www/images/err.jpg'; # Catagories for 'rotate' and 'random' # Keys are the catagory names to pass as 'c' argument, # arrays are the directories for that catagory. my $cat = { 'banners' => ['/home/user/imgs/banners', '/home/user/imgs/banners2'], 'logos' => ['/home/user/imgs/logos', '/home/user/imgs/logos2'] }; ######################### # End Config # Automatically generate an 'all' catagory @{$cat->{'all'}} = map{@{$cat->{$_}}}keys %{$cat}; # Rotate the image number for a catagory sub rotate_img { my $q = shift; my @imgs = get_imgs(@{$cat->{$q}}); my $data = -e $data_file ? lock_retrieve($data_file) : {}; $data->{$q} = 0 if $data->{$q}++ == $#imgs; lock_store $data, $data_file; return $imgs[$data->{$q}]; } # Get list of images from directories sub get_imgs { sort grep {-f && /(?:\.gif|jpe?g|png)$/i } map{ glob("$_/*") } @_ } # Output an image to the browser sub show_img { my $img = shift; my ($mime) = $img =~ /\.(gif|jpe?g|png)$/; $mime = 'jpeg' if $mime eq 'jpg'; open my $fh, '<', $img or die "Could not open $img for read: $!"; binmode $fh; my $img_data = do { local $/; <$fh> }; close $fh; print header('image/' . $mime), $img_data; exit; } my $m = param('m') || ''; # Mode my $c = param('c') || ''; # Catagory # Rotated image if ($m eq 'rotate') { show_img( $cat->{$c} ? rotate_img($c) : $err_img ); } # Random image elsif ($m eq 'random') { show_img($err_img) unless $cat->{$c}; my @imgs = get_imgs(@{$cat->{$c}}); show_img($imgs[rand @imgs]); } # Specific Image elsif ($m eq 'image') { ($m,$c) = split(/\//, $c, 2); show_img($err_img) unless $cat->{$m} && $c; for ( get_imgs(@{$cat->{$m}}) ) { show_img($_) if m#/\Q$c\E\.(?:gif|jpe?g|png)$#; } show_img($err_img); } # Invalid Call else { show_img($err_img); } |