#!/usr/bin/perl # # # # # # Warning WARNING Warning WARNING Warning # # This is not the file you want to edit. # # the original can be found at: # /afs/csail.mit.edu/u/g/gremio/public_html/pics # # # # # # # # # # # # use strict; use File::Basename; use Cwd; $|=1; #< deny my %deny = ("65.75.152.120" => 1, "66.111.215.196" => 1 ); if (defined $deny{$ENV{REMOTE_ADDR}}) { exit 0; } #> my $diricon = "/~gremio/icons/directory.jpg"; my $logdir = "/afs/csail/u/g/gremio/public_html/pics/.log/"; my $default_height = 300; my $lighterPrefix = ".l-"; # Standard CGI stuff: $debug, debug_info(), space(n) #< htesc(str), uriesc(str), a/url_button(uri,str,opts) use Data::Dumper; use CGI qw/:all/; print header; use CGI::Carp qw(fatalsToBrowser); my $input= new CGI; $input->import_names('in'); my $debug = $in::debug if (defined $in::debug); #< Postgres -- commented out -- # use Postgres; my $conn; # if (defined $database and $database ne "") { # $conn = Postgres::db_connect($database) # or die "could not connect -- $Postgres::error"; # } #> #< htesc (text) sub htesc { my $text = shift; $text =~ s/\&/&/g; $text =~ s/\/>/g; # $text =~ s/\'/'/g; $text =~ s/\"/"/g; $text =~ s/([^\s\x20-\x7e])/sprintf("\&%x;", ord($1))/ge; $text =~ s/\n/
\n/gs; $text =~ s/\t/&space(8)/ges; $text =~ s/ /&space(1)/ges; return $text; } #> #< uriesc (text) sub uriesc { my ($url) = @_; my ($olink) = ($url =~ /\?(.*)$/); my $link = $olink; foreach my $badchar ($link =~ /([^\w=&:;+\.])/g) { my $goodchar = sprintf "%%%x", ord($badchar); $link =~ s/\Q$badchar\E/$goodchar/g; } $url =~ s/\Q$olink\E$/$link/; return $url; } #> #< a (url, text [, %options]) sub a { my ($url, $text, %options) = @_; $url = uriesc($url); my $link = qq($text); return $link; } #> #< space(n): return n HTML non-breaking spaces sub space { my ($n) = @_; my $s=""; $n=1 unless $n; $s .= "\n"; for (my $i=0; $i < $n; $i++) { $s .= " "; } $s .= "\n"; return $s; } #> #< debug_info() some environment info for debugging sub dUmper { my $varstr = shift; use Data::Dumper; my $string = Dumper(@_); $string =~ s/^\$VAR1/$varstr/; return htesc $string; } sub debug_info { return unless $debug; my %options = @_; print "\n"; #NOTE: required if you haven't printed anything yet!!! my ($cpack, $cfile, $cline) = caller(); print qq(

[$cfile:$cline] package $cpack

); if (%options) { foreach (keys %options) { print dUmper("\$$_", $options{$_}); } } if (defined $conn or defined $options{conn}) { print qq(

Database Connection Information

); $conn ||= $options{conn}; print "Connected Database: ", $conn->db(), "\n
"; print "Connected Host: ", $conn->host(), "\n
"; print "Connection Options: ", $conn->options(), "\n
"; print "Connected Port: ", $conn->port(), "\n
"; print "Connected tty: ", $conn->tty(), "\n
"; print "Connection Error Message: ", $conn->errorMessage(), "\n
"; } print qq(

Package 'in::' Variables

); foreach my $symname (sort keys %in::) { no strict 'vars'; local *sym = $in::{$symname}; print dUmper("\$in::$symname", $sym) if defined $sym; print dUmper("\@in::$symname", \@sym) if defined @sym and scalar @sym > 1; } print qq(

Environment Variables:

); print dUmper("\\\%ENV", \%ENV) . "
\n"; print qq(
); } #> #< url_button (url, text, %options) sub url_button { my ($url, $text, %opts) = @_; my $out = qq(
); foreach (keys %opts) { $out .= qq(); } # $out .= qq(); $out .= qq(); $out .= qq(
); return $out; } #> #< self_url my $self_url; { my $SELFURL = "http://" . $ENV{SERVER_NAME} . $ENV{SCRIPT_NAME}; my @params = param(); my %opts; foreach my $param (@params) { $opts{$param}=param($param); } $self_url = sub { my %newopts = @_; my $data={ %opts }; my $url = $SELFURL . "?"; foreach my $opt (keys %newopts) { $data->{$opt} = $newopts{$opt}; } foreach my $opt (keys %$data) { $url .= $opt ."=". $data->{$opt} . ";"; } return uriesc($url); } } #> &debug_info(); #> #< unesc (text) sub unesc { my ($str) = @_; foreach my $badchar ($str =~ /%([0-9A-F][0-9A-F])/g) { my $goodchar = sprintf("%c", hex($badchar)); $str =~ s/\Q%$badchar\E/$goodchar/g; } return $str; } #> #< acc(text) convert flying accents to html # Note: as I've been lazy, I've only implemented Hungarian flying # accents, and I've changed the standard single quote a' to ,a with a # comma, so as to reduce confusion with words like "I've" and "Olya's". sub acc { local $_ = join('',@_); s/(? my %photos = (); my %folders = (); my %captions = (); my %thumbs = (); my %northumbs = (); my %brithumbs = (); my %hilights = (); my %hashilights = (); my %ages = (); my %other = (); my %hilighted = (); my $title = "Photos"; my $havebrighter=0; # bool : brightened photos are available in this directory my $hilightfilename = ".hilights"; if (not $in::height or $in::height !~ /^\d+$/) { $in::height = $default_height; } my $height = ""; if ($in::height != $default_height) { $height = qq(height=$in::height); } if ($in::url) { #< read everything from a url that gives me a pure directory list $height = q(&).$height if $height; use LWP::Simple; my $loc = $ENV{REQUEST_URI}; $loc =~ s/\?.*//; my $urlfilepart = $in::url; $urlfilepart =~ s|\w+://[\w\.-]+/||; $urlfilepart =~ s|/$||; $title = basename($urlfilepart); my @listing = (); if ($in::url =~ m|^\w+://\w+|) { @listing = split /[\r\n]+/, get($in::url); } $in::url =~ s|/$||; #strip trailing slash local $_; my $thumbsdir; foreach (@listing) { #< directories #print qq($_\n); if (/\[DIR\]/) { next if />Parent Directory #< images elsif (/\[IMG\]/) { my ($photo) = (/HREF="(.+?)"/i); unless ($photo) { warm("could not read IMG line [$_]"); next; } next if /\s1k\s*$/; #construct name my $name = $photo; $name =~ s/\.[^\.]+$//; # remove dot extension #keep current of duplicate iff I'm sure I can display it: next if (defined $photos{$name} and $photos{$name} =~ /\.(gif|jpg)$/i); #assign target $photos{$name}=qq($in::url/$photo); } #> #< captions elsif (/.cap\b/) { my ($caption) = (/HREF="(.+?)"/); next unless $caption =~ /\.cap$/; #construct name my $name = $caption; $name =~ s/\.[^\.]+$//; # remove dot extension #assign target $captions{$name} = get(qq($in::url/$caption)); } #> #< other file types else { my ($url) = (/HREF="(.+?)"/i); next unless $url; next if $url =~ /(~|\.cgi)$/; next if $url =~ /\?/; # avoid passing args to cgi #construct name my $name = $url; $name =~ s/\.[^\.]+$//; # remove dot extension #assign target $other{$name} ||= []; push @{$other{$name}}, $url; } #> } #< nothing here? Display a form for a new url if (scalar(keys %folders) + scalar(keys %photos) == 0) { print <<"EOT";

Did not find a standard Apache directory listing to process at URL $in::url.

URL:      image height:
EOT ; } #> #< read thumbnails from thumbsdir if (defined $thumbsdir) { @listing = split /[\r\n]+/, get($in::url."/".$thumbsdir); foreach (@listing) { if (/\[IMG\]/) { my ($photo) = (/HREF="(.+?)"/); next if /\s1k\s*$/; #construct name my $name = $photo; $name =~ s/\.[^\.]+$//; # remove dot extension #assign target $thumbs{$name}=qq($in::url/$thumbsdir/$photo); } } } #> #> #< edit? no if ($in::edit) { print qq(Cannot edit a remote location
\n); undef $in::edit; } #> } else { #< read everything locally my $cwd = cwd(); opendir(DIR, $cwd) or die "cannot read directory $cwd: $!\n"; my @listing = readdir(DIR); closedir(DIR); my $loc = dirname($ENV{SCRIPT_NAME}); $title = basename($loc); my $thumbsdir; my $unreadable=0; foreach (grep {!/^\./ and !/RCS/} @listing) { if (not -r $_) { $unreadable++; next; } #< directories (and find thumbsdir if any) if ( -d _ and -x _ ) { my $dir = $_; if ($dir eq "Thumbs") { $thumbsdir=$dir; next; } my $target = qq($loc/$dir); if (-x qq($dir/index.cgi)) { $target .= qq(/index.cgi?$height); } else { $target = qq($ENV{REQUEST_URI}?url=http://$ENV{SERVER_NAME}$target&$height); } my $hilightfile = qq($dir/$hilightfilename); if (open(HILIGHT, $hilightfile)) { $hilights{$dir} = []; while () { next unless /\S/ and !/^\#/; chomp; push @{$hilights{$dir}}, $_ if -r qq($dir/$_); } $hashilights{$dir}=1; } else { # back off to a randomly selected image. my @all; if (-r qq($dir/Thumbs) and -x _ and opendir(HDIR, qq($dir/Thumbs))) { @all = grep /^[^\.].*\.(gif|jpg)$/i, readdir(HDIR); @all = grep { s|^|Thumbs/|; } @all; } elsif (opendir(HDIR, $dir)) { # @all = grep /^[^\.].*\.(gif|jpg)$/i, readdir(HDIR); # loading and scaling these takes too long. } $hilights{$dir} = [ @all ] if @all; } $ages{$dir} = -M $dir; $folders{$dir} = $target; } #> #< read photos elsif (/(\w.+)\.(gif|jpg|png)$/i) { my $photo = $_; my $name = $1; #assign target $photos{$name}=qq($loc/$photo); if (-r qq($lighterPrefix$photo)) { if ($in::l) { $photos{$name}=qq($loc/$lighterPrefix$photo); } else { $havebrighter=1; } } $ages{$name} = -M $photo; } #> #< read captions elsif (/(\w.+)\.(cap)$/i) { my $caption = $_; my $name = $1; #assign target open(CAPTION, "<".$caption) or next; $captions{$name} = join ("", ); close CAPTION; } #> #< other file types else { my $url = $_; next if $url =~ /(~|\.cgi)$/; #construct name my $name = $url; $name =~ s/\.[^\.]+$//; # remove dot extension #assign target $other{$name} ||= []; push @{$other{$name}}, $url; } #> } #< read thumbnails from thumbsdir if (defined $thumbsdir and opendir(DIR, $thumbsdir)) { my @thentries = readdir(DIR); closedir DIR; my @phos = grep { !/^\./ and /\w.+\.(gif|jpg|png)$/i } @thentries; foreach my $photo (@phos) { #check readable next unless -r $photo; #construct name my $name = $photo; $name =~ s/\.[^\.]+$//; # remove dot extension #assign target $northumbs{$name} = qq($thumbsdir/$photo); $thumbs{$name}=qq($loc/$thumbsdir/$photo); if (-r qq($thumbsdir/$lighterPrefix$photo)) { $brithumbs{$name} = qq($thumbsdir/$lighterPrefix$photo); if ($in::l) { $thumbs{$name}=qq($loc/$thumbsdir/$lighterPrefix$photo); } else { $havebrighter=1; } } } } #> print qq($unreadable files were unreadable
\n) if $unreadable; #> #< edit? writeable? if (not -w $cwd) { print qq(Cannot write to this directory
\n) if $in::edit; undef $in::edit; } else { $in::editable=1; } #> #< %hilighted if (open(H,"<$hilightfilename")) { while() { chomp; my $base = $_; $base =~ s|.*/||; $base =~ s|\.\w+$||; $hilighted{$base} = $_; } } #> } my @photoorder = (&range(values %ages) > 7) ? sort { $ages{$a} <=> $ages{$b} } keys %photos : sort keys %photos; my $numhilights = scalar(grep { /^Thumbs/ or !/\// } values %hilighted); $numhilights = 0 if $in::edit or $in::all; my $bright = ($in::l?"l=1":"l=0"); $in::all = "&all=1" if $in::all; #< slideshow find prev and next my $prevphoto = ""; my $nextphoto = ""; if ($in::photo) { my $photo_index = 0; foreach my $photo (@photoorder) { if ($photo eq $in::photo) { # find the next photo $photo_index++; # start with next one while (not $nextphoto and $photo_index < scalar @photoorder) { my $cand = $photoorder[$photo_index++]; $nextphoto = $cand if $hilighted{$cand} or not $numhilights or $in::all; } last; } else { $prevphoto = $photo if $hilighted{$photo} or not $numhilights or $in::all; } $photo_index++; } } #> #< save edits if ($in::edit eq "save") { my $cwd = cwd(); foreach my $item ("_header", "_footer", "_copyright", keys %photos) { my $prm = param($item); if ($prm) { my $filename = "$cwd/$item.cap"; open (CAP, ">".$filename) or die "cannot write $filename: $@$!\n"; print CAP $prm; print CAP "\n"; close CAP; system qq(chmod a+w $filename\n); #print qq(saved $filename.
\n); $captions{$item}=$prm; } } foreach my $item (keys %photos) { my $photofile = $photos{$item}; $photofile =~ s|.*$item([^/]+)$|$item$1|; #remove loc, just file. my $prm = param("hide-$item"); if ($prm) { if (-e $photofile) { system qq(mv $photofile .$photofile) and die "could not hide $photofile: $!$@\n"; } else { die "$photofile does not exist?\n"; } if (-e $lighterPrefix.$photofile) { unlink $lighterPrefix.$photofile or die "cannot unlink $lighterPrefix$photofile: $!$@\n"; } if (defined $northumbs{$item}) { unlink $northumbs{$item} or die "cannot unlink $northumbs{$item}: $!$@\n"; } if (defined $brithumbs{$item}) { unlink qq($brithumbs{$item}) or die "cannot unlink $brithumbs{$item}: $!$@\n"; } } $prm = param("hilight-$item"); if ($prm) { if (defined $thumbs{$item}) { $hilighted{$item} = "Thumbs/".$photofile; } else { $hilighted{$item} = $photofile; } } else { if (defined $hilighted{$item}) { delete $hilighted{$item}; } } } if (scalar keys %hilighted) { open(H, ">$hilightfilename") or &cgidie("cannot save hilights: $!\n"); foreach my $h (values %hilighted) { print H qq($h\n); } close H; } else { if (-e "$hilightfilename") { unlink "$hilightfilename"; } } undef $in::edit; my $SELFURL = "http://" . $ENV{SERVER_NAME} . $ENV{SCRIPT_NAME}; print <<"EOT"; Saved captions. Refreshing, one moment... EOT ; exit 0; } #> #< save feedback if ($in::feedback eq "save") { my $cwd = cwd(); my $time = time(); my $ip = $ENV{REMOTE_ADDR}; my $ua = $ENV{HTTP_USER_AGENT}; my $logfile = qq($logdir/$ip-$time); while (-e $logfile) { sleep 1; $time = time(); $logfile = qq($logdir/$ip-$time); } open(LOG, ">", $logfile) or die "cannot write logfile: $!\n"; print LOG qq(cwd=$cwd\n); print LOG qq(useragent=$ua\n); print LOG qq(localtime=).localtime()."\n"; foreach my $g (qw(name contact share overall)) { my $p = param("feedback-$g"); $p||=""; print LOG qq($g=$p\n); } foreach my $g (qw(rate adj comment)) { foreach my $ph (keys %photos) { my $prm = param("$g-$ph"); print LOG qq($g\t$ph\t$prm\n) if $prm; } } exit 0 if $debug; undef $in::feedback; my $SELFURL = "http://" . $ENV{SERVER_NAME} . $ENV{SCRIPT_NAME}; print <<"EOT"; Sent feedback. Thank you! Refreshing, one moment... EOT ; exit 0; } #> #< generate html $title = acc($title); my $js = "&js=$in::js"; $js="" unless $in::js; #< html head print <<"EOH"; Photos: $title EOH ; unless ($in::js or $in::photo) { print <<"EOH"; EOH ; } #> #< title and buttons print <<"EOH";

$title

EOH ; &button_bar(); print <<"EOH";
EOH ; #> #< debug_info &debug_info("photos", \%photos, "thumbs", \%thumbs, "captions", \%captions, "folders", \%folders, "other", \%other); #> #< edit header. if ($in::edit) { print qq(
\n); print qq(\n); print qq(\n); print qq(\n); print qq(\n); print qq(\n); print qq(\n); print qq(\n); } #> #< _header and _copyright $captions{_header} ||= ""; if (defined $captions{_header} and not $in::edit and not $in::photo) { print acc($captions{_header}); } elsif ($in::edit) { print qq(Copyright info: e.g. 2005 Gregory Marton, can also: include a url on its own line; more text; leave blank for default
\n); print qq(

\n); print qq(Header appears at top of page:
\n); print qq(

\n); } if ($in::feedback) { print qq(

Thank you for offering your feedback!); } #> if ((scalar(keys %folders) or scalar(keys %other)) and not $in::photo and not $in::edit and not $in::feedback) { #< folders print qq(
). scalar(keys %folders) . " folders:
\n"; #< @folderorder = sort the folders in some good way: print ""; my @folderorder = (&range(values %ages) > 7) ? sort { if ($a =~ /^\d+-/ and $b =~ /^\d+-/) { $b cmp $a; } elsif ($a =~ /^\d+-/) { -1; } elsif ($b =~ /^\d+-/) { 1; } else { $b cmp $a; } } keys %folders : sort keys %folders; #> my $iter=0; print qq(); foreach my $dir (@folderorder) { print qq(\n) unless ($iter % 4); $iter++; print qq(\n); } else { print qq(); print qq(); print qq(\n); print qq(\ \ \ ); print acc($dir).qq(\n); } print qq(\n) unless ($iter % 4); } print qq(
); if (defined $hilights{$dir} and scalar @{$hilights{$dir}}) { print qq(
); print qq(); my @choice = @{$hilights{$dir}}; my $hilight = $dir ."/". $choice[rand(scalar @choice)]; if ($in::l) { my (@parts) = split "/", $hilight; my $f = pop @parts; my $lighter = join("/", @parts)."/.l-".$f; $hilight = $lighter if (-e $lighter); print qq(\n); } print qq(
); print qq(
\n); print qq(); if ($hashilights{$dir}) { print acc($dir).qq(); print qq(\().scalar(@choice).qq(\)); } else { print qq().acc($dir).qq(); } print qq(
\n); #> } if ($in::photo) { #< show slide #< get slide size ($w, $h) my ($winW, $winH)= (640, 480); my ($w, $h) = (640, 480); if ($photos{$in::photo} !~ m|^http://|) { my $photo_file = $photos{$in::photo}; my $current_dir = dirname($ENV{SCRIPT_NAME}); $photo_file =~ s|\Q$current_dir\E/||; push @INC, qw(/afs/csail/u/g/gremio/.cpan/keepers/Data-Dump-1.06/lib/ /afs/csail/u/g/gremio/.cpan/keepers/IO-String-1.06/blib/lib/ /afs/csail/u/g/gremio/.cpan/keepers/Image-Info-1.21/lib/); require Image::Info; #print $photo_file; ($w,$h) = Image::Info::dim(Image::Info::image_info($photo_file)); #print $w."x".$h."
\n"; } #> #< caption if (defined $captions{$in::photo}) { print qq().acc($captions{$in::photo}).qq(
); } #> print qq(
); print qq(); # print qq(); if ($in::js) { #< javascript resizer (to window size) and show img my $photofile = $photos{$in::photo}; $photofile =~ s|\'|\\\'|g; print <<"EOJ"; EOJ ; #print qq( border=1>
); print qq(\n
); print qq(











\n); print qq(\(); print qq(click here if there is no image\)
\n); #> } else { #< perl resizer (to defaults) my $sizec; if ($h > $w) { if ($h > $winH) { $sizec = ' height='.$winH; } } elsif ($w > $winW) { $sizec = ' width='.$winW; } print qq(); #> } print qq(
); #> } elsif (scalar keys %photos) { print qq(); #< photos if ($in::edit or $in::feedback) { print qq(\n); #> print qq(
\n); } else { print qq(\n); } print qq(
); print "$numhilights of " if $numhilights; print scalar(keys %photos) . " photos:"; print &url_button(&self_url(), "Show All", "all"=>1) if $numhilights; print "
\n"; #< feedback header # radio buttons and nested forms don't work well together in firefox # (Safari handles them correctly) so I have to be careful not to open # this form until I've closed the previous form (Show All) above. if ($in::feedback) { print qq(\n); print qq(\n); print qq(\n); print qq(\n); print qq(\n); print qq(\n); print qq(\n); print qq(\n); print qq(


); print qq(); print qq(



); } #> print qq(\n); foreach my $photo (@photoorder) { next if $numhilights and not $hilighted{$photo}; print qq(); } print qq(
\n); # print qq(); print qq(); #< thumbnail if (defined $thumbs{$photo}) { print qq(); } else { print qq(); } #> print qq(); #< related files/formats if (defined $other{$photo}) { foreach my $file (@{$other{$photo}}) { print qq( \ \ \  $file); } delete $other{$photo}; } print qq(\n); #> #< caption if (defined $captions{$photo} and not $in::edit) { print acc($captions{$photo}); } #> #< edit form elsif ($in::edit) { print qq(hide
); my $hilight_checked = "checked" if $hilighted{$photo}; print qq(hilight
); print qq(
); } #> #< feedback form if ($in::feedback) { print qq(

rate this photo:    ); print qq(terrific ); my $scale=5; for my $i (0 .. ($scale-1)) { my $n = $scale-$i; print qq($n ); } print qq( terrible ); # print qq(       ); # print qq(); print qq(

); print qq(your comments?
); print qq(); } #> #< thirdcol (image link) if ("thirdcol") { my $ext = $photos{$photo}; $ext =~ s/.*\.//; print qq(
$ext); } #> print qq(\n
\n); } if (scalar(keys %other) and not $in::photo and not $in::feedback) { #< other print qq(
). scalar(keys %other) . " files:
\n"; foreach my $name (sort keys %other) { foreach my $file (@{$other{$name}}) { print qq($file \ \ \  ); } print qq(
\n); print acc($captions{$name}) if defined $captions{$name}; print qq(\n

); } #> } #< _footer if (defined $captions{_footer} and not $in::edit and not $in::photo) { print acc($captions{_footer}); } elsif ($in::edit) { print qq(

\n); } #> #< edit: submit if ($in::edit) { print qq(); print qq(
\n); } elsif ($in::editable) { # print qq(
); # print qq(); # print qq(
\n); } #> #< feedback: submit if (not $in::edit and $in::feedback) { print qq(

); print qq(
); print qq(

); print qq(
); print qq(What is your name?); print qq(

); print qq(Would you like a response? If so, how may I reach you?
); print qq(

); print qq(Do you have overall comments about this album?
); print qq(
); print qq(May I share your feedback with other readers?); print qq( Yes.
); print qq(Thanks again for your comments!       ); print qq(); print qq(
); print qq(\n); } #> #< title and buttons print <<"EOH";

$title

EOH ; &button_bar(); print <<"EOH";
EOH ; #> print qq(\n); #< button_bar sub button_bar { #< slideshow buttons if ($in::photo) { print qq(\n); print qq(prev); print qq(up); print qq(detail); print qq(next\n); # print qq(
click photo = next
\n); } elsif (scalar @photoorder) { print qq(\n); $nextphoto=$photoorder[0]; print qq(next\n); } #> #< send feedback if (scalar keys %photos) { print <<"EOT";         EOT ; } #> #< up-a-dir my $upurl = ""; if ($in::url) { $upurl = $in::url; $upurl =~ s|/[^/]+/?$|/|; } elsif ($ENV{SCRIPT_NAME} !~ m|gremio/pics/[^/]+(/[^/]+)?$|) { $upurl = "../index.cgi?$bright$in::all$js"; } if ($upurl) { print <<"EOH";
up a directory
EOH ; } #> #< back to Grem's photos unless ($in::url) { print <<"EOH";
back to
Grem's
photos
EOH ; } #> #< copyright info { my $copyright = $captions{_copyright}; if ($copyright or $in::url) { #< show copyright as promised. my $copyicon = "/~gremio/logos/copyright.gif"; if ($copyright =~ /creativecommons.org/) { $copyicon = "/~gremio/logos/cc.png"; } my $copyurl = "http://www.whatiscopyright.org/"; if ($copyright =~ m|^(http://[\w\.-]+/\S+)$|m) { $copyurl = $1; } my $copytext = "copyright"; if ($copyright =~ m@^(\d*(\s|\ )*[A-Z][a-z]+[^\n]*)\n@s) { $copytext = $1; } print <<"EOH";

$copytext
EOH ; #> } else { #< creative commons copyright info print <<"EOH"; Creative Commons License
Distributed under a Creative Commons License EOH ; #> } } #> #< brightness icon print <<"EOH"; EOH ; if ($in::l) { print qq( darker\n); } elsif ($havebrighter) { # put up the golden brightness icon with the title print qq( brighter\n); } #> } #> #> #< range(@numeric-list) returns max - min sub range { my @list = @_; return undef unless @list; my $min = shift @list; my $max = $min; foreach my $ele (@list) { $min = $ele if $ele < $min; $max = $ele if $ele > $max; } return $max - $min; } #>