#!/usr/bin/perl ################################################################################ # Created : Martin Foster # Modified : 24/03/2003 ################################################################################ # # Gallery View - Script part of Ethereal Realms, designed to display and list # galleries and associated works # Copyright (C) 2000-2003 Martin Foster # # 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. # # Author of this script can be contacted at the following: # E-Mail : martin@ethereal-realms.org # Address : 204 - 817, 5th Street NE # Calgary, Alberta # T2E 3W9 # ################################################################################ use CGI qw(:standard); # Common gateway interface use CGI::Carp qw(fatalsToBrowser); # CGI Error logs use strict; # Strict variable enforcement use Ethereal::Database; # Database handler use Ethereal::Date; # Date handler use Ethereal::Filter; # Filter handling use Ethereal::Login; # Login functionality use Ethereal::Mail; # Mail handler use Ethereal::Param; # Parameter control use Ethereal::Table; # Table handler use Ethereal::Template; # Template handler ################################################################################ # Data Members ################################################################################ my $cgi; # Common gateway interface handle my $database; # Database handle my $login; # Login handle my $param; # Parameter hash my $tmpl; # Template handle my $sname; # Simply the script name my $sparam; # Scripted parameter string my %gal; # Gallery hash my %sparam; # Scripted parameters ################################################################################ # Program Area ################################################################################ # Initial handles $cgi = new CGI; $database = new Ethereal::Database(); # Connect and fetch $database->Connect(); # Parameter handling $param = new Ethereal::Param($database, $cgi); $param->GetParam(); # Link with hash $database->GetHashGallery(\%gal); # Initial hash $tmpl = new Ethereal::Template(\%gal); # Document header print $cgi->header(); $database->DocumentGetGalleryHeader(); # Authenthication instance $login = new Ethereal::Login($database, $cgi, $param, \%gal); # Pull script name $sname = $cgi->url(-full=>1); $sparam = $cgi->url(-path_info=>1); # Determine need # Escape $sname = quotemeta($sname); # Needed addition $sparam = ($sparam =~ /\/$/) ? $sparam : "$sparam/"; # Truncate $sparam =~ s/^$sname\///; # Retreive parameters ($sparam{'ACT'}, $sparam{'GAL'}, $sparam{'WRK'}, $sparam{'POS'}) = split(/\//, $sparam); # Action decisions # Specific work/gallery views if ((defined($sparam{'ACT'})) && ($sparam{'ACT'} eq 'view')) { # Speficied gallery if ((defined($sparam{'GAL'})) && ($sparam{'GAL'} =~ /^\d+$/)) { # Specific work if ((defined($sparam{'WRK'})) && ($sparam{'WRK'} =~ /^\d+$/)) { # Work specific display WorkDisplay($database, $login, $cgi, $param, $tmpl, \%sparam, \%gal); } # General gallery else { # Display gallery GalleryDisplay($database, $login, $cgi, $param, $tmpl, \%sparam, \%gal); } } # Invalid entry else { # Display appropriate error message $tmpl->Show('TmplMsg', MMESSAGE=>$gal{'MsgParam'}); } } # Comment viewer elsif ((defined($sparam{'ACT'})) && ($sparam{'ACT'} eq 'comment')) { # Basic checK if ((defined($sparam{'GAL'})) && (defined($sparam{'WRK'}))) { # Verify for operation if ((defined($sparam{'POS'})) && ($sparam{'POS'} =~ /^\d+$/)) { # Remove comment CommentRemove($database, $login, $cgi, $param, $tmpl, \%sparam, \%gal); } elsif ((defined($sparam{'POS'})) && ($sparam{'POS'} eq 'new')) { # Create comments CommentWrite($database, $login, $cgi, $param, $tmpl, \%sparam, \%gal); } else { # Display comments CommentDisplay($database, $login, $cgi, $param, $tmpl, \%sparam, \%gal); } } # Invalid entry else { # Display appropriate error message $tmpl->Show('TmplMsg', MMESSAGE=>$gal{'MsgParam'}); } } # Work search elsif ((defined($sparam{'ACT'})) && ($sparam{'ACT'} eq 'search')) { # Simply one window WorkSearch($database, $login, $cgi, $param, $tmpl, \%sparam, \%gal); } # Display behaviour else { # List galleries GalleryList($database, $login, $cgi, $param, $tmpl, \%sparam, \%gal); } # Document footer $database->DocumentGetGalleryFooter(); ################################################################################ # Sub-Routines ################################################################################ ##################### # Check Authorization # # In certain causes, realms will choose to carry an adult rating. In such a # case, there is a need to prevent people from using the system when such # a circumstance takes place. sub CheckAuth { ##################### # Data members my $database = shift; # Database handler my $login = shift; # Authenthication handler my $param = shift; # Paramater handler my $sparam = shift; # Parameter line hash my $tmpl = shift; # Template handle my $gal = shift; # Gallery hash my $choice = shift; # Choice of the matter my $rating; # Rating to realm my $verify; # Verified access ##################### # Program area # Retreive information ($rating) = $database->DataGet("SELECT GalleryRating FROM Gallery WHERE GalleryID=?", $sparam->{'GAL'}); # Reasons to check if ((defined($param->{'USER'})) || ($rating eq $gal->{'SetRestricted'}) || (defined($choice))) { # Authenthicate if ($login->GetVerificationNormal()) { # More checks if ($rating eq $gal->{'SetRestricted'}) { # Retreive verification ($verify) = $database->DataGetVerified($param->{'USER'}); # Invalid if ($verify eq 'no') { # Display error $tmpl->Show('TmplMsg', MMESSAGE=>$gal->{'MsgRestricted'} ); # Flase return 0; } } # Return true return 1; } # Return false return 0; } # Always return true return 1; } ##################### # Comment Display # # If one has the capability of composing messages, then one will also need to # be able to view them. This is a general, all purpose method that allows # for attached and semi-independant use. sub CommentDisplay { ##################### # Data members my $database = shift; # Database handler my $login = shift; # Authenthication handler my $cgi = shift; # CGI interface my $param = shift; # Paramater handler my $tmpl = shift; # Template handler my $sparam = shift; # Parameter line hash my $gal = shift; # Gallery hash my $limit = shift; # Retreival limit my $data = $database->{'HANDLE'}; # Database handle my $date; # Date/time handle my $res; # Results my $rsth; # Query handle my $comment; # Comment settings my $name; # Name of work my $user; # Username my $rate; # Rating my $vote; # Votes my $ibio; # Biographical line my $idelete; # Delete link my $inline; # Inline parameters my $uri; # Secondary name my $url; # Self referencing link ##################### # Program Area # Things are in order ($name) = $database->DataGetWorkName($sparam->{'WRK'}, $sparam->{'GAL'}); # Continue as planned if (defined($name)) { # Force authenthication reguardless return 0 unless (CheckAuth($database, $login, $param, $sparam, $tmpl, $gal)); # Retreive values ($comment) = $database->DataGetGalleryComment($sparam->{'GAL'}); ($user) = $database->DataGetGalleryOwner($sparam->{'GAL'}); # Only display if needed # Comments if (($comment eq 'comment') || ($comment eq 'combo')) { # Determine limit $limit = (defined($limit)) ? "LIMIT $limit" : ""; # Prepare query # Set handle if need be $rsth = $data->prepare("SELECT CommentID, PuppetName, PuppeteerLogin, CommentTimestamp, CommentPost FROM Comment WHERE WorkID=? AND GalleryID=? AND CommentPost IS NOT NULL ORDER BY CommentTimestamp DESC $limit"); # Execute said query $rsth->execute($sparam->{'WRK'}, $sparam->{'GAL'}); # Self referencing links # Capture link $url = $cgi->url(-absolute=>1); # Generate appropriate $uri = $url . '/view/' . $sparam->{'GAL'} . '/' . $sparam->{'WRK'}; $url = $url . '/comment/' . $sparam->{'GAL'} . '/' . $sparam->{'WRK'}; # Inline parameters general $inline = (defined($param->{'USER'})) ? $param->EmbedInline(USER=>$param->{'USER'}, CRYPT=>$param->{'CRYPT'}) : ""; # Display title $tmpl->Show('TmplComments', MNAME => $name ); # Initial acid test if ($res = $rsth->fetchrow_hashref()) { # Initiate handle $date = new Ethereal::Date(); # Display table header $tmpl->Show('TmplTblTop'); # First row # Generate link $ibio = $param->Crypt( CHAR=>$res->{'PuppetName'}, USER=>$res->{'PuppeteerLogin'} ); # Deletion handle $idelete = ((defined($param->{'USER'})) && ($user eq $param->{'USER'})) ? "{CommentID}$inline\">[$gal->{TxtDelete}]" : ""; # First row $tmpl->Show('TmplTblMid', MCMNT => $res->{'CommentPost'}, MDATE => $date->GetDateShort($res->{'CommentTimestamp'}), MDELE => $idelete, MFROM => $res->{'PuppetName'}, MLINK => "$gal->{LnkBio}$ibio" ); # Second and so forth # Loop and retrieve while ($res = $rsth->fetchrow_hashref()) { # Generate link $ibio = $param->Crypt( CHAR=>$res->{'PuppetName'}, USER=>$res->{'PuppeteerLogin'} ); # Deletion handle $idelete = ((defined($param->{'USER'})) && ($user eq $param->{'USER'})) ? "{CommentID}$inline\">[$gal->{TxtDelete}]" : ""; # Subsequent rows $tmpl->Show('TmplTblMid', MCMNT => $res->{'CommentPost'}, MDATE => $date->GetDateShort($res->{'CommentTimestamp'}), MDELE => $idelete, MFROM => $res->{'PuppetName'}, MLINK => "$gal->{LnkBio}$ibio" ); } # Close table $tmpl->Show('TmplTblBottom'); } # Display options print "
"; print "$gal->{'TagNavComplete'} " if ($limit =~ /^LIMIT/); print "$gal->{'TagNavReturn'} " if ($limit !~ /^LIMIT/); print "$gal->{'TagNavComment'} "; print "
"; # Finish $rsth->finish(); } # Rating if (($comment eq 'rating') || ($comment eq 'combo')) { # Retrieve values ($rate, $vote) = $database->DataGetWorkAvg($sparam->{'GAL'}, $sparam->{'WRK'}); # Display $tmpl->Show('TmplVotes', MITENAME => $name, MOLVOTES => $vote, MRATINGS => $rate ); } } } ##################### # Comment Remove # # In order to cope with double posts, annoying messages or things that the artists # simply cannot agree upon, the comments can be managed by owner. sub CommentRemove { ##################### # Data members my $database = shift; # Database handler my $login = shift; # Authenthication handler my $cgi = shift; # CGI interface my $param = shift; # Paramater handler my $tmpl = shift; # Template handler my $sparam = shift; # Parameter line hash my $gal = shift; # Gallery hash my $data = $database->{'HANDLE'}; # Database handle my $comment; # Comment settings my $user; # Username ##################### # Program Area # Force authenthication reguardless return 0 unless (CheckAuth($database, $login, $param, $sparam, $tmpl, $gal, 'true')); # Retreive values ($comment) = $database->DataGetGalleryComment($sparam->{'GAL'}); ($user) = $database->DataGetGalleryOwner($sparam->{'GAL'}); # Only display if needed if (($comment eq 'comment') || ($comment eq 'combo')) { # User matches if ($user eq $param->{'USER'}) { # Remove entry $data->do("DELETE FROM Comment WHERE CommentID=? AND WorkID=? AND GalleryID=?", {}, $sparam->{'POS'}, $sparam->{'WRK'}, $sparam->{'GAL'} ); } } # Give them light CommentDisplay($database, $login, $cgi, $param, $tmpl, $sparam, $gal); } ##################### # Comment Write # # Part of the system, as to allow for rating and commenting of works themselves. sub CommentWrite { ##################### # Data members my $database = shift; # Database handler my $login = shift; # Authenthication handler my $cgi = shift; # CGI interface my $param = shift; # Paramater handler my $tmpl = shift; # Template handler my $sparam = shift; # Parameter line hash my $gal = shift; # Gallery hash my $data = $database->{'HANDLE'}; # Database handle my $date; # Date hander my $filter; # Filter handler my $send; # Mail sender my $table; # Table handler my $comment; # Comment settings my $name; # Name of work my $puppet; # Puppet default my $post; # Post my $rate; # Rating my $wpuppet; # Puppet popup my $wrating; # Puppet popup my $wsubmit; # Post submit my @puppet; # List of puppets my @rating = qw(1 2 3 4 5 6 7 8 9 10); # Rating scale my %system; # System hash ##################### # Program Area # Things are in order ($name) = $database->DataGetWorkName($sparam->{'WRK'}, $sparam->{'GAL'}); # Continue as planned if (defined($name)) { # Force authenthication reguardless return 0 unless (CheckAuth($database, $login, $param, $sparam, $tmpl, $gal, 'true')); # Retreive gallery comment ($comment) = $database->DataGetGalleryComment($sparam->{'GAL'}); # Proceed with comment generation if ($comment ne 'none') { # Write post if (defined($param->{'POST'})) { # Post handling if (($comment eq 'comment') || ($comment eq 'combo')) { # Create instance $filter = new Ethereal::Filter(); # Safety $post = $filter->StripHTML($param->{'CPOST'}); # Verify if (length($post) > 3) { # Postage handling # Link with hash $database->GetHashSystem(\%system); # Retreive notice message and contact my ($notice) = $database->DocumentGetGalleryNotice(); my ($user) = $database->DataGetGalleryOwner($sparam->{'GAL'}); # Full contact my ($email) = $database->DataGetPuppeteerEmail($user); my ($fname) = $database->DataGetPuppeteerName($user); # Create instance $date = new Ethereal::Date(); $send = tie(*MAIL, 'Ethereal::Mail', $database); # Initial setup $send->SetSubject($system{'SetGalleryPrefix'} . $name); # Search and replace $send->SetSearch( MDATE => $date->GetDate(time), MFROM => $param->{'CPUPPET'}, MMESG => $post, MMAIL => "$system{SetInfoContactName}\n$system{SetInfoContactAddress}", MWORK => $name ); # Recipients $send->AddTo("$fname <$email>"); # Add message print MAIL $notice; # Close and send close(MAIL); # Post handling $post =~ s/$/\n/; # Truncate Length $post = substr(DBI::neat($post, 1026), 1, -1); # Hyperlinks $post =~ s/(http:\/\/.*?)(\s|$)/$gal->{TagHyperlink}<\/A> /gm; $post =~ s/([\w\.\-]*?\@[\w\.\-]*?\..*?)(\s|$)/$gal->{TagEmail}<\/A> /gm; # Human readability $post =~ s/\n/
/gs; } else { # Undefine as to not see $post = undef; } } # Basic ranting handling $rate = ((defined($param->{'CRATING'})) || ($param->{'CRATING'} =~ /^\d+$/)) ? $param->{'CRATING'} : 0; # Insert row $data->do("INSERT INTO Comment (WorkID, GalleryID, PuppetName, PuppeteerLogin, CommentPost, CommentRating, CommentTimestamp) VALUES(?,?,?,?,?,?,?)", {}, $sparam->{'WRK'}, $sparam->{'GAL'}, $param->{'CPUPPET'}, $param->{'USER'}, $post, $rate, time); # Rating update if (($comment eq 'rate') || ($comment eq 'combo')) { # Calculate average ($rate) = $database->DataGetWorkAvg($sparam->{'GAL'}, $sparam->{'WRK'}); # Update $data->do("UPDATE Work SET WorkRating=? WHERE WorkID=? AND GalleryID=?", {}, $rate, $sparam->{'WRK'}, $sparam->{'GAL'}); } # Comment display WorkDisplay($database, $login, $cgi, $param, $tmpl, \%sparam, \%gal); } # Display form else { # Create instance $table = new Ethereal::Table($cgi); # Puppet names $database->GetListPuppetYours(\@puppet, $param->{'USER'}); # Puppet default ($puppet) = $database->DataGetDefault($param->{'USER'}); # Append abstaining unshift(@rating, $gal->{'TxtAbstain'}); # Generate widget $wpuppet = $cgi->popup_menu('CPUPPET', \@puppet, $puppet); $wrating = $cgi->popup_menu('CRATING', \@rating, $rating[0]); # Submit button $wsubmit = ($comment eq 'rating') ? $gal->{'TxtRate'} : $gal->{'TxtPost'}; # Title $tmpl->ShowMain($gal->{'TagPostTitle'} . $name); # Display information # Form print $cgi->start_form(); print $param->EmbedNormal($param->Flat(), POST=>'True'); # Table creation $table->MakeTop(); # Puppet selection $table->MakeValid( $tmpl->PassSub($gal->{'TagPostPuppet'}), $wpuppet ); # Rating indicator if (($comment eq 'rating') || ($comment eq 'combo')) { # Rating widget and title $table->MakeValid( $tmpl->PassSub($gal->{'TagPostRating'}), $wrating ); } # Comments if (($comment eq 'comment') || ($comment eq 'combo')) { # Spacer $table->MakeBlank(); # Widget and Title $table->MakeSingle( $tmpl->PassTitle($gal->{'TagPostComment'}) ); $table->MakeSingle( $cgi->textarea(-name=>'CPOST',-rows=>3,-columns=>75,-wrap=>'SOFT') ); } # Spacer $table->MakeBlank(); # Display submit $table->MakeSingle($cgi->submit($wsubmit)); # End of table $table->MakeBottom(); # Form print $cgi->end_form(), "\n"; } } # Warn author has disabled comments else { # Warn users comments are disabled $tmpl->Show('TmplMsg', MMESSAGE=>$gal->{'MsgComment'}); } } # Invalid entry else { # Warn that things are off $tmpl->Show('TmplMsg', MMESSAGE=>$gal{'MsgParam'}); } } ##################### # Gallery Display # # Gallery Display will allow casual viewers to see an overview of every # work available. This includes a naivgational system, and an overview of # the move recent comments made on works. sub GalleryDisplay { ##################### # Data members my $database = shift; # Database handler my $login = shift; # Authenthication handler my $cgi = shift; # CGI interface my $param = shift; # Paramater handler my $tmpl = shift; # Template handler my $sparam = shift; # Parameter line hash my $gal = shift; # Gallery hash my $data = $database->{'HANDLE'}; # Database handle my $date; # Date/time handler my $gsth; # Gallery query my $wsth; # Works query my $gres; # Information on gallery my $wres; # Information on works my $icount; # Internal counter my $wcount; # Work counter my $descr; # Description my $length; # Text length my $rating; # Rating my $modulus; # Remainder of values my $order; # Searching order my $pos; # Position my $size; # Size of array my $inline; # Inline parameters my $ipuppet; # Puppet specific parameters my $url; # Command line interface my %val; # Referecing to array my %system; # System hash ##################### # Program Area # Things are proper return 0 unless (CheckAuth($database, $login, $param, $sparam, $tmpl, $gal)); # Gallery information # Prepare and execute $gsth = $data->prepare("SELECT PuppeteerLogin, GalleryPenName, GalleryName, GalleryRating, GalleryGenre, GalleryDescription, GallerySort, GalleryType, GalleryComments, GalleryDisplay, GalleryCreated, GalleryUpdated FROM Gallery WHERE GalleryID=?"); $gsth->execute($sparam->{'GAL'}); # Retreive if ($gres = $gsth->fetchrow_hashref()) { # Create instance $date = new Ethereal::Date(); # Ordering type if ($gres->{'GallerySort'} eq 'date') { $order = 'WorkTimestamp DESC'; } elsif ($gres->{'GallerySort'} eq 'manual') { $order = 'WorkSort'; } elsif ($gres->{'GallerySort'} eq 'rating') { $order = 'WorkRating, WorkName'; } else { $order = 'WorkName'; } # Linking # Fetch link $url = $cgi->url(-absolute=>1) . '/view/' . $sparam->{'GAL'}; # Inline parameters general $inline = (defined($param->{'USER'})) ? $param->EmbedInline(USER=>$param->{'USER'}, CRYPT=>$param->{'CRYPT'}) : ''; # Biographical link $ipuppet = $param->Crypt( CHAR=>$gres->{'GalleryPenName'}, USER=>$gres->{'PuppeteerLogin'} ); # Information display # Intro and summary $tmpl->Show('TmplIntro', MDESCR => $gres->{'GalleryDescription'}, MGENRE => $gres->{'GalleryGenre'}, MLINK => "$gal->{LnkBio}$ipuppet", MPUPPET => $gres->{'GalleryPenName'}, MRATING => $gres->{'GalleryRating'}, MTITLE => $gres->{'GalleryName'}, MCREATED => $date->GetDateShort($gres->{'GalleryCreated'}), MUPDATED => $date->GetDateShort($gres->{'GalleryUpdated'}) ); # Image galleries if ($gres->{'GalleryType'} eq 'image') { # Link with hash $database->GetHashSystem(\%system); # Work information # Prepare and execute $wsth = $data->prepare("SELECT WorkID, WorkName, WorkDescription, WorkRating, WorkImageThumbnail, WorkImageHeight, WorkImageWidth, WorkImageSize, WorkTimestamp FROM Work WHERE GalleryID=? AND WorkImage IS NOT NULL ORDER BY $order"); $wsth->execute($sparam->{'GAL'}); # Sanity %val = ( WorkID => 0, WorkName => 1, WorkDescription => 2, WorkRating => 3, WorkImageThumbnail => 4, WorkImageHeight => 5, WorkImageWidth => 6, WorkImageSize => 7, WorkTimestamp => 8 ); # Retrieve all values if ($wres = $wsth->fetchall_arrayref()) { # Define values # Current value $sparam->{'POS'} = (defined($sparam->{'POS'})) ? $sparam->{'POS'} : $wres->[0]->[$val{'WorkID'}]; # Results $size = @{$wres}; # Cycle for ($icount=0; $icount < $size; $icount++) { # Verify for need if (($wres->[$icount]->[$gal{'WorkID'}] != $sparam->{'POS'}) && (!defined($wcount))) { # Skip operation next; } # Activate and calculate else { # Placeholders $pos = (defined($pos)) ? $pos : $icount; $wcount = (defined($wcount)) ? $wcount + 1 : 0; # As long as needed if ($wcount < $gres->{'GalleryDisplay'}) { # If need exists if (($gres->{'GalleryComments'} eq 'comment') || ($gres->{'GalleryComments'} eq 'combo')) { # Caculate $rating = $wres->[$icount]->[$val{'WorkRating'}]; } else { # Assign nil $rating = $gal->{'SetNil'}; } # Display $tmpl->Show('TmplDisImage', MNAME => $wres->[$icount]->[$val{WorkName}], MDESCR => $wres->[$icount]->[$val{WorkDescription}], MHEIGHT => $wres->[$icount]->[$val{WorkImageHeight}], MIMAGE => $wres->[$icount]->[$val{WorkImageThumbnail}], MLINK => "$url/$wres->[$icount]->[$gal{WorkID}]$inline", MRATING => $rating, MSIZE => $wres->[$icount]->[$val{WorkImageSize}], MTHUMB => $system{'SetThumbnail'}, MWIDTH => $wres->[$icount]->[$val{WorkImageWidth}], MUPDATED => $date->GetDateShort($wres->[$icount]->[$val{WorkTimestamp}]) ); } else { # Leave loop last; } } } } } # Text based galleries elsif ($gres->{'GalleryType'} eq 'text') { # Work information # Prepare and execute $wsth = $data->prepare("SELECT WorkID, WorkName, WorkDescription, WorkRating, WorkText, WorkTimestamp FROM Work WHERE GalleryID=? AND WorkText IS NOT NULL ORDER BY $order"); $wsth->execute($sparam->{'GAL'}); # Sanity %val = ( WorkID => 0, WorkName => 1, WorkDescription => 2, WorkRating => 3, WorkText => 4, WorkTimestamp => 5 ); # Retrieve all values if ($wres = $wsth->fetchall_arrayref()) { # Define values # Current value $sparam->{'POS'} = (defined($sparam->{'POS'})) ? $sparam->{'POS'} : $wres->[0]->[$val{'WorkID'}]; # Results $size = @{$wres}; # Cycle for ($icount=0; $icount < $size; $icount++) { # Verify for need if (($wres->[$icount]->[$gal{'WorkID'}] != $sparam->{'POS'}) && (!defined($wcount))) { # Skip operation next; } # Activate and calculate else { # Placeholders $pos = (defined($pos)) ? $pos : $icount; $wcount = (defined($wcount)) ? $wcount + 1 : 0; # As long as needed if ($wcount < $gres->{'GalleryDisplay'}) { # If need exists if (($gres->{'GalleryComments'} eq 'comment') || ($gres->{'GalleryComments'} eq 'combo')) { # Calculate $rating = $wres->[$icount]->[$val{'WorkRating'}]; } else { # Assign nil $rating = $gal->{'SetNil'}; } # Description $descr = $wres->[$icount]->[$val{WorkDescription}]; $descr = (defined($descr)) ? $descr : substr(DBI::neat($wres->[$icount]->[$val{WorkText}], 252), 1, -1); # Length $length = length($wres->[$icount]->[$val{WorkText}]); # Display $tmpl->Show('TmplDisText', MNAME => $wres->[$icount]->[$val{WorkName}], MDESCR => $descr, MLENGTH => $length, MLINK => "$url/$wres->[$icount]->[$gal{WorkID}]$inline", MRATING => $rating, MUPDATED => $date->GetDateShort($wres->[$icount]->[$val{WorkTimestamp}]) ); } else { # Leave loop last; } } } } } # Calculations # What is left $modulus = $size % $gres->{'GalleryDisplay'}; $modulus *= -1; # Previous position $pos = $pos - $gres->{'GalleryDisplay'}; # Absolute nav # First value my $ifirst = $wres->[0]->[$val{'WorkID'}]; # Last value my $ilast = $wres->[$modulus]->[$val{'WorkID'}]; # Relative nav # Next my $inext = $wres->[$icount]->[$val{'WorkID'}]; # Defined my $iprev = $wres->[$pos]->[$val{'WorkID'}] if ($pos > -1); # End works query $wsth->finish(); # Construct navigational system if ($size > $gres->{'GalleryDisplay'}) { # Display print "
$gal->{'TagNavFirst'} "; # Possible # Previous if (defined($iprev)) { print "$gal->{'TagNavPrev'} "; } # Next if (defined($inext)) { print "$gal->{'TagNavNext'} "; } # Display print "$gal->{'TagNavLast'}
\n"; } } # End gallery query $gsth->finish(); } ##################### # Gallery List # # Provides the front end to the gallery system itself. Will allow the user # to select from a list of galleries and move on from there. sub GalleryList { ##################### # Data members my $database = shift; # Database handler my $login = shift; # Authenthication handler my $cgi = shift; # CGI interface my $param = shift; # Paramater handler my $tmpl = shift; # Template handler my $sparam = shift; # Parameter line hash my $gal = shift; # Gallery hash my $data = $database->{'HANDLE'}; # Database handle my $date; # Date/time handler my $option; # Option handler my $table; # Table hander my $sections; # Section handling my $statement; # Query statement my $res; # Query results my $ibio; # Biographical my $inline; # Standard inline my $page; # Nav page my $url; # Link my $type; # Gallery type my $genre; # Gallery genre my $default; # Default list my $count; # Counter my $icount; # Internal counter my $size; # Size of retrieval my $section; # Section generation my $sort; # Sort type my @sections; # Selectable sections my @sorts; # Sorting types my %val; # Referencing values ##################### # Program area # Option handling $date = new Ethereal::Date(); $option = new Ethereal::Option(); $table = new Ethereal::Table($cgi); # Give more meaniful names $sparam->{'TYP'} = $sparam->{'GAL'} if defined($sparam->{'GAL'}); $sparam->{'GRE'} = $sparam->{'WRK'} if defined($sparam->{'WRK'}); # Determine type if ((defined($param->{'LSELECT'})) && ($param->{'LSELECT'} =~ /(\w+)\s\-\s([\w\s]+)\s\(/)) { # Set values $sparam->{'TYP'} = $1; $sparam->{'GRE'} = $2; } # Retreive sections list # Prepare and execute $sections = $data->prepare("SELECT GalleryType, GalleryGenre, COUNT(*) AS GalleryCount FROM Gallery WHERE GalleryUpdated <> 0 GROUP BY GalleryType, GalleryGenre ORDER BY GalleryType, GalleryGenre"); $sections->execute(); # Loop and gather while ($res = $sections->fetchrow_hashref()) { # Determine type $type = $option->GalleryTypeRev($gal->{'OptSrchType'}, $res->{'GalleryType'}); # Determine rest $genre = $res->{'GalleryGenre'}; $count = $res->{'GalleryCount'}; # Append push(@sections, "$type - $genre ($count)"); # Check for match if ((defined($sparam->{'TYP'})) && (defined($sparam->{'GRE'})) && ($sparam->{'TYP'} eq $type) && ($sparam->{'GRE'} eq $genre)) { # Assign default value $default = "$type - $genre ($count)"; } } $sections->finish(); # Sort list $option->Split(\@sorts, $gal->{'OptSrchSort'}); # Defaults $default = (defined($default)) ? $default : $sections[0]; $param->{'LSORT'} = (defined($param->{'LSORT'})) ? $param->{'LSORT'} : $sorts[0]; # Generate widget $section = $cgi->popup_menu('LSELECT', \@sections, $default); $sort = $cgi->popup_menu('LSORT', \@sorts, $param->{'LSORT'}); # Display # Title $tmpl->ShowMain($gal->{'TagListing'}); # From generation print $cgi->start_form(); print $param->EmbedNormal($param->Flat()); # Display nav $table->MakeTop(); $table->MakeValid( $tmpl->PassSub($gal->{'TagListingSelect'}), $section ); $table->MakeValid( $tmpl->PassSub($gal->{'TagListingSort'}), $sort ); $table->MakeSingle($cgi->submit($gal->{'TxtSelect'})); $table->MakeBottom(); # End of form print $cgi->end_form(); # Information display # Something to do if ((defined($sparam->{'TYP'})) && (defined($sparam->{'GRE'}))) { # Determine type and sort $type = $option->GalleryType($gal->{'OptSrchType'}, $sparam->{'TYP'}); $sort = $option->GallerySort($gal->{'OptSrchSort'}, $param->{'LSORT'}); # Discover if ($sort eq 'date') { $sort = 'GalleryUpdated DESC'; } elsif ($sort eq 'rating') { $sort = 'GalleryRating ASC, GalleryName ASC'} else { $sort = 'GalleryName ASC' } # Main display # Prepare and execute $statement = $data->prepare("SELECT GalleryID, PuppeteerLogin, GalleryPenName, GalleryName, GalleryRating, GalleryDescription, GalleryCreated, GalleryUpdated FROM Gallery WHERE GalleryType=? AND GalleryGenre=? AND GalleryUpdated <> 0 ORDER BY $sort"); $statement->execute($type, $sparam->{'GRE'}); # Sanity %val = ( GalleryID => 0, PuppeteerLogin => 1, GalleryPenName => 2, GalleryName => 3, GalleryRating => 4, GalleryDescription => 5, GalleryCreated => 6, GalleryUpdated => 7 ); # Retrieve if ($res = $statement->fetchall_arrayref()) { # Retreive size $size = @{$res}; # We can do something if ($size > 0) { # Determine position $sparam->{'POS'} = (defined($sparam->{'POS'})) ? $sparam->{'POS'} : $res->[0]->[$val{'GalleryID'}]; # Self referencing link $url = $cgi->url(-absolute=>1) . '/view'; $inline = (defined($param->{'USER'})) ? $param->EmbedInline(USER=>$param->{'USER'}, CRYPT=>$param->{'CRYPT'}) : ''; # Set $icount = 1; # Loop for ($count=0; $count < $size; $count++) { # Skip if needed if (($icount==1) && ($res->[$count]->[$val{'GalleryID'}] != $sparam->{'POS'})) { # Skip next; } # Display else { # Increment $icount++; # Generate biographical link $ibio = $param->Crypt( CHAR=>$res->[$count]->[$val{'GalleryPenName'}], USER=>$res->[$count]->[$val{'PuppeteerLogin'}] ); # Display information $tmpl->Show('TmplDisGallery', MAUTHOR => $res->[$count]->[$val{'GalleryPenName'}], MBIOL => "$gal->{LnkBio}$ibio", MCREATED => $date->GetDateShort($res->[$count]->[$val{'GalleryCreated'}]), MDESCR => $res->[$count]->[$val{'GalleryDescription'}], MLINK => "$url/$res->[$count]->[$val{GalleryID}]/$inline", MNAME => $res->[$count]->[$val{'GalleryName'}], MRATING => $res->[$count]->[$val{'GalleryRating'}], MUPDATED => $date->GetDateShort($res->[$count]->[$val{'GalleryUpdated'}]) ); # Stop the presses if ($icount > $gal->{'SetRetrieve'}) { # Leave loop last; } } } # Nav Pages if ($size > $gal->{'SetRetrieve'}) { # Escape $type = $cgi->escape($sparam->{'TYP'}); $genre = $cgi->escape($sparam->{'GRE'}); # Self referencing link $url = $cgi->url(-absolute=>1) . '/list/' . $type . '/' . $genre; $inline = (defined($param->{'USER'})) ? $param->EmbedInline($param->Flat()) : $param->Crypt($param->Flat()); # Prep print "
"; # Reset $icount = 1; # Loop as needed for ($count = 0; $count < $size; $count+=$gal->{'SetRetrieve'}) { # Set page $page = $gal->{'TagNavPage'}; $page =~ s/MPAGE/$icount/gs; # Display print "[$count]->[$val{GalleryID}]/$inline\">$page "; # Increment $icount++; } # Finish print "<\CENTER>\n"; } } else { # Display error message $tmpl->Show('TmplSrch', MMESSAGE=>$gal->{'MsgListing'}); } } else { # Display error message $tmpl->Show('TmplSrch', MMESSAGE=>$gal->{'MsgListing'}); } # End statement $statement->finish(); } } ##################### # Work Display # # Work display allows a user to view the works themselves in full # detail. sub WorkDisplay { ##################### # Data members my $database = shift; # Database handler my $login = shift; # Authenthication handler my $cgi = shift; # CGI interface my $param = shift; # Paramater handler my $tmpl = shift; # Template handler my $sparam = shift; # Parameter line hash my $gal = shift; # Gallery hash my $data = $database->{'HANDLE'}; # Database handle my $date; # Date/time handler my $res; # Results my $statement; # Query statement my $cmnt; # Comment preferences my $name; # Verification check my $type; # Gallery type my $order; # Sort order my $sort; # Sort type my $next = 0; # Next sequence my $curr = 0; # Current position my $prev = 0; # Previous record my $totl = 0; # Total amount of works my $char; # Character my $rate; # Rating my $user; # Username my $vote; # Votes my $url; # Self referencing link my $inline; # Inline parameters my $ipuppet; # Biographical link my @seq; # Logical squence ##################### # Program Area # Things are in order ($name) = $database->DataGetWorkName($sparam->{'WRK'}, $sparam->{'GAL'}); # Continue as planned if (defined($name)) { # Things are proper return 0 unless (CheckAuth($database, $login, $param, $sparam, $tmpl, $gal)); # Information gathering # Retreive gallery basics ($sort, $cmnt, $type, $char, $user) = $database->DataGet("SELECT GallerySort, GalleryComments, GalleryType, GalleryPenName, PuppeteerLogin FROM Gallery WHERE GalleryID=?", $sparam->{'GAL'}); # Ordering type if ($sort eq 'date') { $order = 'WorkTimestamp DESC'; } elsif ($sort eq 'manual') { $order = 'WorkSort'; } elsif ($sort eq 'rating') { $order = 'WorkRating, WorkName'; } else { $order = 'WorkName'; } # Retrieve next of kin $database->GetList(\@seq, "SELECT WorkID FROM Work WHERE GalleryID=? ORDER BY $order", $sparam->{'GAL'}); # Where we are while ($seq[$curr] != $sparam->{'WRK'}) { $curr++; } # Total $totl = @seq; # Position of cousins $next = ($curr+1 >= $totl) ? $seq[0] : $seq[$curr+1]; $prev = $seq[$curr-1]; # Linking # Fetch link $url = $cgi->url(-absolute=>1) . '/view/' . $sparam->{'GAL'}; # Inline parameters general $inline = (defined($param->{'USER'})) ? $param->EmbedInline(USER=>$param->{'USER'}, CRYPT=>$param->{'CRYPT'}) : ''; # Biographical link $ipuppet = $param->Crypt( CHAR=>$char, USER=>$user ); # Works of art # Retrieve rating ($rate, $vote) = $database->DataGetWorkAvg($sparam->{'WRK'}, $sparam->{'GAL'}); # Prepare and execute $statement = $data->prepare("SELECT WorkName, WorkDescription, WorkSort, WorkImage, WorkImageThumbnail, WorkImageHeight, WorkImageWidth, WorkImageSize, WorkText, WorkTextPreserve, WorkTimestamp FROM Work WHERE WorkID=? AND GalleryID=?"); $statement->execute($sparam->{'WRK'}, $sparam->{'GAL'}); # Make available if ($res = $statement->fetchrow_hashref()) { # Common display # Header $tmpl->Show('TmplWrkHeader', MDISAUTH => $char, MDISCURR => $curr+1, MDISDESC => $res->{'WorkDescription'}, MDISNAME => $res->{'WorkName'}, MDISTOTL => $totl, MLNKBIOG => "$gal->{LnkBio}$ipuppet" , MLNKGTOP => "$url/$inline", MLNKNEXT => "$url/$next$inline", MLNKPREV => "$url/$prev$inline" ); # Fork for gallery styles # Image gallery if ($type eq 'image') { # Display image specific $tmpl->Show('TmplWrkImage', MDISIMAG => $res->{'WorkImage'}, MDISHGHT => $res->{'WorkImageHeight'}, MDISWDTH => $res->{'WorkImageWidth'}, MDISNAME => $res->{'WorkName'} ); } # Text based galleries elsif ($type eq 'text') { # Posting assignment my $post = $res->{'WorkText'}; # Filtering and safety if ($res->{'WorkTextPreserve'} eq 'no') { # Basic replacements $post =~ s/$/\n/; # Hyperlinks $post =~ s/(http:\/\/.*?)(\s|$)/$gal->{TagHyperlink}<\/A> /gm; $post =~ s/([\w\.\-]*?\@[\w\.\-]*?\..*?)(\s|$)/$gal->{TagEmail}<\/A> /gm; # Maintain directories $post =~ s/\n/
/gs; } # Display image specific $tmpl->Show('TmplWrkText', MDISTEXT => $post ); } } # Finish query $statement->finish(); # List comments CommentDisplay($database, $login, $cgi, $param, $tmpl, $sparam, $gal, $gal->{'SetRetrieve'}); } # Signal error else { # Invalid entry $tmpl->Show('TmplMsg', MMESSAGE=>$gal{'MsgParam'}); } } ##################### # Work Search # # Allows for searchign through works for specific words and phrases # reguardless of standard word search of boolean searches. sub WorkSearch { ##################### # Data members my $database = shift; # Database handler my $login = shift; # Authenthication handler my $cgi = shift; # CGI interface my $param = shift; # Paramater handler my $tmpl = shift; # Template handler my $sparam = shift; # Parameter line hash my $gal = shift; # Gallery hash my $data = $database->{'HANDLE'}; # Database handle my $date; # Date/time handler my $option; # Option handler my $res; # Results my $statement; # Query statement my $page; # Page number my $panel; # Search panel my $count; # Counter my $icount; # Internal counter my $length; # Length of string my $number; # Number my $size; # Size of results my $query; # Main query my $where; # Where clause my $url; # Self referencing my $inline; # Inline parameters my $descr; # Description my $field; # Search field my $genre; # Genre sort my $sort; # Sort type my $text; # Text type my $type; # Serach type my $sgnre; # Search genre my $sfild; # Search field my $ssort; # Search sort my $ssmbt; # Submit my $stext; # Text handler my $stype; # Search type my @field; # Option search field my @genre; # Option for genres my @sort; # Option for sort type my @type; # Option search type my %system; # System hash my %val; # Value hash ##################### # Data members # Create instances $date = new Ethereal::Date(); $option = new Ethereal::Option(); # Options lists $option->Split(\@field, $gal->{'OptSrchField'}); $option->Split(\@genre, $gal->{'OptGenre'}); $option->Split(\@sort, $gal->{'OptSrchSort'}); $option->Split(\@type, $gal->{'OptSrchType'}); # Append unshift(@genre, '------'); # Definition $param->{'SFILD'} = (defined($param->{'SFILD'})) ? $param->{'SFILD'} : $field[0]; $param->{'SGNRE'} = (defined($param->{'SGNRE'})) ? $param->{'SGNRE'} : $genre[0]; $param->{'SSORT'} = (defined($param->{'SSORT'})) ? $param->{'SSORT'} : $sort[0]; $param->{'STYPE'} = (defined($param->{'STYPE'})) ? $param->{'STYPE'} : $type[0]; $param->{'STEXT'} = (defined($param->{'STEXT'})) ? $param->{'STEXT'} : ''; # Generate widgets $sfild = $cgi->popup_menu('SFILD', \@field, $param->{'SFILD'}); $sgnre = $cgi->popup_menu('SGNRE', \@genre, $param->{'SGNRE'}); $ssort = $cgi->popup_menu('SSORT', \@sort, $param->{'SSORT'}); $stype = $cgi->popup_menu('STYPE', \@type, $param->{'STYPE'}); $ssmbt = $cgi->submit($gal->{'TxtSearch'}); $stext = $cgi->textfield('STEXT', $param->{'STEXT'}, 50, 75); # New query if (defined($param->{'SNEW'})) { # Reset for new query $sparam->{'GAL'} = undef; $sparam->{'WRK'} = undef; # Cleanup $param->Cleanup('SNEW'); } # Display $tmpl->PassTitle($gal->{'TagSrch'}); # Search panel ($panel) = $database->DocumentGetGallerySearch(); # Search and replace $panel =~ s/MSRCHRESL/ /gs; $panel =~ s/WSRCHFILD/$sfild/gs; $panel =~ s/WSRCHGNRE/$sgnre/gs; $panel =~ s/WSRCHSORT/$ssort/gs; $panel =~ s/WSRCHSMBT/$ssmbt/gs; $panel =~ s/WSRCHTEXT/$stext/gs; $panel =~ s/WSRCHTYPE/$stype/gs; # Forms print $cgi->start_form(); print $cgi->hidden('SNEW', 'True'), "\n"; print $param->EmbedNormal($param->Flat()) if (defined($param->{'USER'})); # Display print "$panel\n"; # End form print $cgi->end_form(), "\n"; # Need exists if (length($param->{'STEXT'}) > 2) { # Determine useable $field = $option->GalleryField($gal->{'OptSrchField'}, $param->{'SFILD'}); $sort = $option->GallerySort($gal->{'OptSrchSort'}, $param->{'SSORT'}); $type = $data->quote($option->GalleryType($gal->{'OptSrchType'}, $param->{'STYPE'})); # Genre $genre = ($param->{'SGNRE'} =~ /^\w+/) ? "AND gal.GalleryGenre=\'$param->{'SGNRE'}\'" : ""; # Discover if ($sort eq 'date') { $sort = 'wrk.WorkTimestamp DESC'; } elsif ($sort eq 'rating') { $sort = 'wrk.WorkRating DESC, wrk.WorkName ASC'} else { $sort = 'wrk.WorkName ASC' } # Pull text $text = $param->{'STEXT'}; # Determine where statement $where = $database->Query($text, $field); # Generate query $query = "SELECT wrk.GalleryID, wrk.WorkID, wrk.WorkName, wrk.WorkDescription, wrk.WorkRating, wrk.WorkImage, wrk.WorkImageHeight, wrk.WorkImageWidth, wrk.WorkImageSize, wrk.WorkImageThumbnail, wrk.WorkText, wrk.WorkTimestamp, gal.GalleryPenName FROM Gallery gal, Work wrk WHERE gal.GalleryID=wrk.GalleryID AND gal.GalleryType=$type $genre AND ($where) GROUP BY wrk.WorkName ORDER BY $sort"; # Sanity %val = ( GalleryID => 0, WorkID => 1, WorkName => 2, WorkDescription => 3, WorkRating => 4, WorkImage => 5, WorkImageHeight => 6, WorkImageWidth => 7, WorkImageSize => 8, WorkImageThumbnail => 9, WorkText => 10, WorkTimestamp => 11, GalleryPenName => 12 ); # Prepare query $statement = $data->prepare($query); # Executed fine if ($statement->execute()) { # Pull all records if ($res = $statement->fetchall_arrayref()) { # Records received $size = @{$res}; # Worth a look if ($size > 0) { # Self referencing link $url = $cgi->url(-absolute=>1) . '/view'; # Inline parameters $inline = (defined($param->{'USER'})) ? $param->EmbedInline( USER=>$param->{'USER'}, CRYPT=>$param->{'CRYPT'}) : ''; # Associate with hash $database->GetHashSystem(\%system); # Number of pages $number = int($size / $gal->{'SetRetrieve'}); # Define references $sparam->{'GAL'} = (defined($sparam->{'GAL'})) ? $sparam->{'GAL'} : $res->[0]->[$val{'GalleryID'}]; $sparam->{'WRK'} = (defined($sparam->{'WRK'})) ? $sparam->{'WRK'} : $res->[0]->[$val{'WorkID'}]; # Set $icount = 1; # Display appropriate values for ($count=0; $count < $size; $count++) { # Skips if ((($res->[$count]->[$val{'GalleryID'}] != $sparam->{'GAL'}) || ($res->[$count]->[$val{'WorkID'}] != $sparam->{'WRK'})) && ($icount==1)) { # Next pass next; } # Process else { # Set limitation last if ($icount > $gal->{'SetRetrieve'}); # Increment $icount++; # Display # Image gallery if ($type =~ /image/) { # Display $tmpl->Show('TmplDisImage', MNAME => $res->[$count]->[$val{WorkName}], MDESCR => $res->[$count]->[$val{WorkDescription}], MHEIGHT => $res->[$count]->[$val{WorkImageHeight}], MIMAGE => $res->[$count]->[$val{WorkImageThumbnail}], MLINK => "$url/$res->[$count]->[$val{GalleryID}]/$res->[$count]->[$val{WorkID}]/$inline", MRATING => $res->[$count]->[$val{WorkRating}], MSIZE => $res->[$count]->[$val{WorkImageSize}], MTHUMB => $system{'SetThumbnail'}, MWIDTH => $res->[$count]->[$val{WorkImageWidth}], MUPDATED => $date->GetDateShort($res->[$count]->[$val{WorkTimestamp}]) ); } # Text gallery elsif ($type =~ /text/) { # Description $descr = $res->[$count]->[$val{WorkDescription}]; $descr = (defined($descr)) ? $descr : substr(DBI::neat($res->[$count]->[$val{WorkText}], 252), 1, -1); # Length $length = length($res->[$count]->[$val{WorkText}]); # Display information $tmpl->Show('TmplDisText', MNAME => $res->[$count]->[$val{WorkName}], MDESCR => $descr, MLENGTH => $length, MLINK => "$url/$res->[$count]->[$val{GalleryID}]/$res->[$count]->[$val{WorkID}]/$inline", MRATING => $res->[$count]->[$val{WorkRating}], MUPDATED => $date->GetDateShort($res->[$count]->[$val{WorkTimestamp}]) ); } } } # Nav Pages if ($size > $gal->{'SetRetrieve'}) { # Self referencing link $url = $cgi->url(-absolute=>1) . '/search'; $inline = (defined($param->{'USER'})) ? $param->EmbedInline($param->Flat()) : $param->Crypt($param->Flat()); # Prep print "
"; # Reset $icount = 1; # Loop as needed for ($count = 0; $count < $size; $count+=$gal->{'SetRetrieve'}) { # Set page $page = $gal->{'TagNavPage'}; $page =~ s/MPAGE/$icount/gs; # Display print "[$count]->[$val{GalleryID}]/$res->[$count]->[$val{WorkID}]/$inline\">$page "; # Increment $icount++; } # Finish print "<\CENTER>\n"; } } else { # No results $tmpl->Show('TmplSrch', MMESSAGE=>$gal->{'MsgSrchResults'} ); } } else { # No results $tmpl->Show('TmplSrch', MMESSAGE=>$gal->{'MsgSrchResults'} ); } # End execution $statement->finish(); } else { # Error in execution $tmpl->Show('TmplSrch', MMESSAGE=>$gal->{'MsgSrchError'} ); } } }