I want to display multiple random images on a single page, but when I call the script multiple times the same image shows up for all of them. I can work around this by duplicating the images over several directories, but this is inefficient and isn't cache friendly.
Any ideas how to change how I call the random_image.cgi so that it will give me different images on the same page?
How you're calling random_image.cgi via an img tag, an ssi include, or by some other method?
Can you show us your code that calls random_image.cgi?
There are several issues I have with that script, which we can go over if you wish, but first I'd like to see how you're calling it.
Edit:
I forgot one question.
If it always returns the same image each time it's called, have you checked how many files are in the @allfiles array and which array index it's coming up with in this statement?
Code:
my $img_file = $allfiles[int rand $nlines];
Last edited by FishMonger; 12-07-2008 at 05:34 PM..
where I have 4 frame directories which all have the same images duplicated in all four dirs. This does what I want, in a clunky way, but I want it to be able to call all the images from the same place.
I hope that explains it well enough, this is my first time working with perl.
you can see what I've got right now, live at http://www.cloverpatchwork.com/search/ (NSFW stick figures)
I don't have time to fix all of the problems with that script, but see if this works better. (I've added another module which you may need to install).
Code:
#!/usr/local/bin/perl -T
# DON"T FORGET TO SET THE PATH!
#
##############################################################################
# Random Image: A random image display script
# Copyright (C) 2005 Larry Boyd
# random_image@anolecomputer.com
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
# random_image 2.1
$|= 1;
use CGI qw(:standard);
use CGI::Carp qw(fatalsToBrowser);
use strict;
use warnings;
use List::Util qw/shuffle/;
#################
# Configuration #
#################
# absolute path to your starting point only directories below this can be used
my $base_path = "/path/to/your/images/";
# base URL to your images. DON'T put the trailing "/"
my $image_url = "/images";
###################
## error messages #
###################
## Error Code 1: Missing directory
my $e1 = "<center><b>Error code: 1<p>I'm sorry, but I am unable to complete your request. Please contact the page administrator and provide the error code listed above.</b></center>";
## Error Code 2: Someone tried to use a / or .. in the start of a $path or $directory var
my $e2 = "<center><b>Error code: 2<p>I'm sorry, but I am unable to complete your request. Please contact the page administrator and provide the error code listed above.</b></center>";
##############
# here we go #
##############
my $method = param('method');
my $path = param('path');
my $alt_txt = param('alt_txt');
my $link = param('link');
# let's do some checks on the the supplied path to make sure
# someone doesn't try to do anything tricky
# make sure the parameters are there so the default directories don't get shown
if (!$path) {
&print_error($e1);
} # end if
# check to see if $path starts with a / or \ and error if they do
if ($path =~ /^\//) {
&print_error($e2);
} # end if
if ($path =~ /^\\/) {
&print_error($e2);
} # end if
# make sure we don't allow any tricky stuff using ".." or "."
if ((index $path, "..") != -1) {
&print_error($e2);
} # end if
if ((index $path, ".") != -1) {
&print_error($e2);
} # end if
my $file_dir = $base_path . "$path/";
# open the directory and output the files
opendir(FILES, $file_dir) or die "Couldn't open directory $file_dir for reading!";
my $image_filter = qr/[.](gif|jpeg|jpg|png|bmp|tiff|tif)$/;
my @allfiles = grep { /$image_filter/ } readdir(FILES);
closedir(FILES);
my $img_file = (shuffle @allfiles)[0];
if ($method eq 'ssi') {
if (!$link) {
print "Content-type: text/html \n\n";
print "<img src=\"$image_url\/$path\/$img_file\" alt=\"$alt_txt\" border=\"0\">";
} # end if
else {
print "Content-type: text/html \n\n";
print "<a href=\"$link\"><img src=\"$image_url\/$path\/$img_file\" alt=\"$alt_txt\" border=\"0\"></a>";
} # end else
exit;
} # end if
else {
my %img_type = ("jpg","jpeg", "jpeg","jpeg", "gif","gif", "png","png", "bmp","bmp", "tif","tiff", "tiff","tiff");
my $ext = '';
($ext) = $img_file =~ /\.([^.]+)$/;
$ext = lc($ext);
my $type = $img_type{"$ext"};
open IMG, "$file_dir/$img_file"
or die qq(Image "$file_dir/$img_file" not found);
binmode IMG;
undef $/;
my $img = <IMG>;
close IMG;
print "Content-Type: image/$type\r\n\r\n";
binmode STDOUT;
print STDOUT $img;
} # end else
###################################################################################
# print_error: subroutine to output error messages. Useful for debugging as well. #
###################################################################################
sub print_error {
my $error = shift;
print "content-type: text/html \n\n";
print "<b>$error</b><br>";
exit(0);
} # end sub print_error
Okay, I think I may have explained my problem wrong; the script works OK, I can call for images and each time I call it it gives me a new image. My problem is I want to call the script multiple times in a single page.
Then you need to use a totally different approach. You need the script to produce the html code that displays the images as well assign a random image. The script you have is not designed to do that.
#!/usr/bin/perl
#$|= 1;
#use CGI qw(:standard);
#use CGI::Carp qw(fatalsToBrowser);
#use strict;
#use vars qw(%img_type);
#################
# Configuration #
#################
# absolute path to your starting point only directories below this can be used
my $base_path = "/home/metaphorever/public_html/clover/search/";
# base URL to your images. DON'T put the trailing "/"
my $image_url = "clover1";
my $file_dir = $base_path . "$image_url/";
# open the directory and output the files
opendir(FILES,"$file_dir") or die "Couldn't open directory $file_dir for reading!";
my @allfiles = grep(!/^\.\.?$/,readdir(FILES));
srand();
closedir(FILES);
#########Print###########
print "Content-type: text/html\n\n";
print <<HTML;
<html>
<head>
<title>clover search</title>
<body bgcolor="#000">
</head>
<body>
HTML
my $range = 20;
my $random_number = rand($range);
my $remainder = 20-$random_number;
for ($count = $random_number; $count >= 1; $count--) {
my $nlines=@allfiles;
my $file = int(rand(@ls));
my $img_file = $allfiles[int rand $nlines];
print <<HTML;
<img src="http://www.cloverpatchwork.com/search/clover1/$img_file" alt="a clover">
HTML
}
print <<HTML;
<img src="http://www.cloverpatchwork.com/search/clover2/01.jpg" alt="a clover">
HTML
for ($count = $remainder; $count >= 1; $count--) {
my $nlines=@allfiles;
my $file = int(rand(@ls));
my $img_file = $allfiles[int rand $nlines];
print <<HTML;
<img src="http://www.cloverpatchwork.com/search/clover1/$img_file" alt="a clover">
HTML
}
print <<HTML;
</body>
HTML
exit;
I think the space around the images comes from the line breaks in between images in the generated html, how can I get rid of them? And how would I go about changing the $range to be whatever was called from the url as in /search.cgi?20
Any feedback would be wonderful. Thank you for your time
that should get rid of the space between images that your heredoc blocks are introducing. In the html source code you want to see all the image tags strung together instead of on seperate lines or with any space between them.
use CGI qw(:standard);
my $range = param('r') || 20; #<- 20 is a default range if none is submitted
#here you should filter and validate that $range is what your script expects