#!/usr/bin/perl use lib '/home/thestrangers/erealms/ethereal/mgmt/perl'; ################################################################################ # Created : Martin Foster # Modified : 01-Jan-2007 ################################################################################ # # Gallery View - Script part of Ethereal Realms, designed to display and list # galleries and associated works # Copyright (C) 2000-2007 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 : 4-3526 Wolfe Cres # Halifax, Nova Soctia # B3L 3S2 # ################################################################################# use CGI qw(-no_debug -nosticky); # Common gateway interface use CGI::Carp qw(fatalsToBrowser); # CGI Error logs use Number::Format qw(:subs); # Number formatting library use strict; # Strict variable enforcement use Ethereal::Database; # Database handler use Ethereal::Filter; # Filter handling use Ethereal::Login; # Login functionality use Ethereal::Mail; # Mail handler use Ethereal::Menu; # Consistent menu use Ethereal::Option; # Option handler use Ethereal::Param; # Parameter control use Ethereal::Template; # Template handler use Ethereal::Words; # Word processing and stemming ################################################################################# # Gobal override ################################################################################# $CGI::POST_MAX=1024 * 50; # Maximum posts $CGI::DISABLE_UPLOADS = 1; # Disable uploads ################################################################################ # Data Members ################################################################################ my $cgi; # Common gateway interface handle my $database; # Database handle my $login; # Login handle my $menu; # Menu handle my $param; # Parameter hash my $tmpl; # Template handle my $ready = 'False'; # Ready for processing my $sparam; # Scripted parameter string my @pass; # Passage of variables my %gal; # Gallery hash my %sparam; # Scripted parameters ################################################################################ # Program Area ################################################################################ # Initial handles $cgi = new CGI; $database = new Ethereal::Database(); # Connect and fetch $database->Connect($cgi); # Kill switch exit if $database->{'COMP_GALLERY'} eq 'false'; # Set title $database->{'TITLE'} = $database->{'SYS'}{'TitGallery'}; # Parameter handling $param = new Ethereal::Param($database, $cgi); $param->GetParam(); # Link with hash $database->GetHashGallery(\%gal); # Create instances $tmpl = new Ethereal::Template(\%gal); $menu = new Ethereal::Menu($database, $param); $login = new Ethereal::Login($database, $cgi, $param, $menu, \%gal); # Enable custom header and footer $login->{'HEADER'} = $database->DocumentGetGalleryHeader(); $login->{'FOOTER'} = $database->DocumentGetGalleryFooter(); # Fetch and format $sparam = $cgi->path_info(); $sparam =~ s/^(\/)(.*)(\/)?$/$2\//; # Differs based on what is pulled if ($sparam =~ /^(image|text)/i) { # This requires a tree-like depth in order to move freely # between galleries and genres. ($sparam{'TYP'}, $sparam{'SUB'}, $sparam{'GRE'}, $sparam{'GAL'}, $sparam{'LYR'}, $sparam{'WRK'}, $sparam{'POS'}) = split(/\//, $cgi->unescape($sparam)); } else { # This is more direct, works have no need for that depth # as they are viewed indepepdantly. ($sparam{'ACT'}, $sparam{'GAL'}, $sparam{'LYR'}, $sparam{'WRK'}, $sparam{'ADD'}) = split(/\//, $cgi->unescape($sparam)); } # Possible authentication methods # Determine state of readiness if (defined($param->{'USER'})) { # Authenticate # Assign if true $ready = 'True' if ($login->GetVerificationNormal()); } else { # Require a header print $cgi->header(); # Change state $ready = 'True'; } # Bypass if necessary if ($ready eq 'True') { # Disable certain features # Disable independance and header generation $login->{'AUTOMATE'} = 0; $login->{'NODEPEND'} = 0; # Page header HeaderRewrite($database, $cgi, $tmpl, $menu, \%sparam, \%gal); # Generate cleaner parameter list push(@pass, $database, $login, $cgi, $param, $tmpl, \%sparam, \%gal); # Gallery's root definition # Root defined if ((defined($sparam{'GRE'})) && (length($sparam{'GRE'}) > 3)) { # Work details # Shows works allowing linear movement if ((defined($sparam{'GAL'})) && (defined($sparam{'WRK'})) && ($sparam{'GAL'} =~ /^\d+$/) && ($sparam{'WRK'} =~ /^\d+$/)) { # Work specific display WorkDetail(@pass); } # Work listing # Lists all works within gallery elsif ((defined($sparam{'GAL'})) && ($sparam{'GAL'} =~ /^\d+$/)) { # Work list WorkList(@pass); } # Final step of the puzzle else { # List galleries GalleryList(@pass); } } # Searching capability # Work search elsif ((defined($sparam{'ACT'})) && ($sparam{'ACT'} eq 'search')) { # Simply one window WorkSearch(@pass); } # Commenting ability # Comment viewer elsif ((defined($sparam{'ACT'})) && ($sparam{'ACT'} eq 'comment')) { # Basic check if ((defined($sparam{'GAL'})) && (defined($sparam{'WRK'}))) { # Verify for operation # Removal of comment if ((defined($sparam{'ADD'})) && ($sparam{'ADD'} =~ /^\d+$/)) { # Remove comment CommentRemove(@pass); } # Creation of a new comment elsif ((defined($sparam{'ADD'})) && ($sparam{'ADD'} eq 'new')) { # Remove comment # Create comments CommentWrite(@pass); } # Simply display else { # Display comments # Directly display to screen print CommentDisplay(@pass); } } } # Default behaviour # Show member which genres are available else { # Select the genre TYP and SUB-type GenreList(@pass); } # Document footer print $database->DocumentGetGalleryFooter(), "\n"; } ################################################################################ # 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 ##################### # 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'}) { # Invalid if ($database->{'USR'}{'Verified'} eq 'no') { # Display error $tmpl->Show('TmplMsg', MMESSAGE => $gal->{'MsgRestricted'} ); # False 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 $res; # Results my $rsth; # Query handle my $comment; # Comment settings my $name; # Name of work my $access; # Username my $gummy; # Gummy name my $rate; # Rating my $vote; # Votes my $ibio; # Biographical line my $idelete; # Delete link my $inline; # Inline parameters my $url; # Self referencing link my $listing; # Comments listing my $nav; # Navigational business my $return; # Returned template my $votes; # Votes generated ##################### # Program Area # Initialize $return = ''; # Make sure values are sane if (($sparam->{'WRK'} =~ /^\d+$/) && ($sparam->{'GAL'} =~ /^\d+$/)) { # 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'}); ($access) = $database->DataGetGalleryJanitor($sparam->{'GAL'}, $param->{'USER'}) if (defined($param->{'USER'})); # Initialize elements $nav = ''; $listing = ''; $votes = ''; # 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 $database->Pull(\$rsth, "SELECT c.CommentID AS \"CommentID\", c.PuppetName AS \"PuppetName\", p.PuppetShort AS \"PuppetShort\", p.PuppetGummy AS \"PuppetGummy\", c.PuppeteerLogin AS \"PuppeteerLogin\", c.CommentPost AS \"CommentPost\", getDate(c.CommentTimestamp) AS \"CommentTimestamp\" FROM Comment c INNER JOIN Puppet p ON (c.PuppetName=p.PuppetName AND PuppetPool='system') WHERE WorkID=? AND GalleryID=? AND CommentPost IS NOT NULL ORDER BY CommentTimestamp DESC $limit", $sparam->{'WRK'}, $sparam->{'GAL'} ); # Self referencing links $url = $database->{'SYS'}{'LnkIntGallery'} . '/comment/' . $sparam->{'GAL'} . '/' . $sparam->{'LYR'} . '/' . $sparam->{'WRK'}; # Inline parameters general $inline = (defined($param->{'USER'})) ? $param->EmbedInline(USER=>$param->{'USER'}, CRYPT=>$param->{'CRYPT'}) : ''; # Necessary fetching # Initial acid test if ($res = $rsth->fetchrow_hashref()) { # Initialize $idelete = ''; # Loop and retrieve do { # Biographical link $ibio = '/' . $res->{'PuppetShort'} . '/system' . $inline; # Deletion handle $idelete = $tmpl->Pass('TagDelete', MLINK => $url . '/' . $res->{'CommentID'} . $inline ) if ((defined($param->{'USER'})) && (defined($access))); # Check gummy $gummy = (defined($res->{'PuppetGummy'})) ? $res->{'PuppetGummy'} : $gal->{'TagGummyDef'}; # Subsequent rows $listing .= $tmpl->Pass('TmplCommentList', MCOMMENT => $res->{'CommentPost'}, MDATE => $res->{'CommentTimestamp'}, MDELE => $idelete, MPUPPET => $res->{'PuppetName'}, MGUMMY => $gummy, MLINK => $database->{'SYS'}{'LnkIntBio'} . $ibio ); } while ($res = $rsth->fetchrow_hashref()); } # Finish $rsth->finish(); # Navigational propreties # Complete listing $nav .= $tmpl->Pass('TagNavTarget', MNAME => $gal->{'TagNavComplete'}, MLINK => $url. $inline, MTARGET => 'COMMENT_' . $sparam->{'GAL'} . 'x' . $sparam->{'WRK'} ) if ($limit =~ /^LIMIT/); # Write to comment $nav .= $tmpl->Pass('TagNavTarget', MNAME => $gal->{'TagNavComment'}, MLINK => $url . '/new' . $inline, MTARGET => 'COMMENT_' . $sparam->{'GAL'} . 'x' . $sparam->{'WRK'} ) if ($sparam->{'WRK'} != 1); } # Rating if (($comment eq 'rating') || ($comment eq 'combo')) { # Retrieve values ($rate, $vote) = $database->DataGetWorkAvg($sparam->{'GAL'}, $sparam->{'WRK'}); # Display $votes .= $tmpl->Pass('TmplVotes', MITENAME => $name, MOLVOTES => $vote, MRATINGS => $rate ); } # Generate final template $return = $tmpl->Pass('TmplComment', MNAME => $name, MCOMMENT => $listing, MNAV => $nav, MVOTES => $votes ); } } # Return comments return $return; } ##################### # 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 $comment; # Comment settings my $access; # Access privs ##################### # Program Area # Force authenthication reguardless return 0 unless (CheckAuth($database, $login, $param, $sparam, $tmpl, $gal, 'true')); # Retreive values ($comment) = $database->DataGetGalleryComment($sparam->{'GAL'}); ($access) = $database->DataGetGalleryJanitor($sparam->{'GAL'}, $param->{'USER'}) if (defined($param->{'USER'})); # Only display if needed if (($comment eq 'comment') || ($comment eq 'combo')) { # User matches if (defined($access)) { # Remove entry $database->Quick("DELETE FROM Comment WHERE CommentID=? AND WorkID=? AND GalleryID=?", $sparam->{'ADD'}, $sparam->{'WRK'}, $sparam->{'GAL'} ); } } # Standard entrance print 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 $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 $mail; # Mail comment my $post; # Post my $rate; # Rating my $wcomment; # Commenting field 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 ##################### # 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->{'CPUPPET'})) { # Evaluate change eval { # Post handling if (($comment eq 'comment') || ($comment eq 'combo')) { # Create instance $filter = new Ethereal::Filter(); # Safety $post = $filter->StripHTML($param->{'CPOST'}); $mail = $post; # Verify if (length($post) > 3) { # 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 $database->Write("INSERT INTO Comment (WorkID, GalleryID, PuppetName, PuppeteerLogin, CommentPost, CommentRating) VALUES(?,?,?,?,?,?)", $sparam->{'WRK'}, $sparam->{'GAL'}, $param->{'CPUPPET'}, $param->{'USER'}, $post, $rate); # Rating update if (($comment eq 'rate') || ($comment eq 'combo')) { # Calculate average ($rate) = $database->DataGetWorkAvg($sparam->{'GAL'}, $sparam->{'WRK'}); # Update $database->Write("UPDATE Work SET WorkRating=? WHERE WorkID=? AND GalleryID=?", $rate, $sparam->{'WRK'}, $sparam->{'GAL'}); } # Commit $database->Commit(); }; # If block failed if ($@) { # Issue warning warn("Transaction aborted: $@"); # Undo incomplete changes $database->Rollback(); } else { # Mail notification to user if ((defined($mail)) && (length($mail) > 3)) { # Postage handling # 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 $send = tie(*MAIL, 'Ethereal::Mail', $database); # Initial setup $send->SetSubject($database->{'SYS'}{'SetGalleryPrefix'} . $name); # Search and replace $send->SetSearch( MDATE => $database->DataGetDate(), MFROM => $param->{'CPUPPET'}, MMESG => $mail, MMAIL => "$database->{SYS}{SetInfoContactName}\n$database->{SYS}{SetInfoContactAddress}", MWORK => $name ); # Recipients $send->AddTo("$fname <$email>"); # Add message print MAIL $notice; # Close and send close(MAIL); } # Normal works # Simply display here and now print CommentDisplay($database, $login, $cgi, $param, $tmpl, $sparam, $gal); } } # Display form # Necessary for people to post comments else { # Puppet names $database->GetListPuppetYours(\@puppet, $param->{'USER'}); # Puppet default ($puppet) = $database->DataGetDefault($param->{'USER'}); # Append abstaining unshift(@rating, $gal->{'TxtAbstain'}); # Generate widget $wpuppet = (defined($database->{'DEFAULT'})) ? $cgi->hidden('CPUPPET', $database->{'DEFAULT'}) : $cgi->popup_menu('CPUPPET', \@puppet, $puppet); $wrating = $cgi->popup_menu('CRATING', \@rating, $rating[0]); # Submit button $wsubmit = ($comment eq 'rating') ? $gal->{'TxtRate'} : $gal->{'TxtPost'}; # Display information # Form print $cgi->start_form(); print $param->EmbedNormal($param->Flat()); # Rating indicator $wrating = (($comment eq 'rating') || ($comment eq 'combo')) ? $tmpl->Pass('TmplWriterRate', WRATING=>$wrating) : ''; # Comments $wcomment = (($comment eq 'comment') || ($comment eq 'combo')) ? $tmpl->Pass('TmplWriterComment', WCOMMENT => $cgi->textarea( -name => 'CPOST', -rows => 3, -columns => 75, -wrap => 'SOFT' ) ) : ''; # Display completed template $tmpl->Show('TmplWriter', MRATE => $wrating, MCOMMENT => $wcomment, WPUPPET => $wpuppet, WSUBMIT => $cgi->submit($wsubmit) ); # 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 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 $statement; # Query statement my $res; # Query results my $descr; # Description field my $highlight; # Highlighted image my $list; # List of galleries my $newness; # Newness factor my $page; # Nav page my $url; # Self-referencing url my $link; # Generated link my $inline; # Standard inline my $genre; # Gallery genre my $pos; # Positional handling my $sub; # Gallery sub type my $type; # Gallery type my $sort; # Sort order my $osort; # Original sort order my $offset; # Starting position my $total; # Amount of entries ##################### # Program area # Capture self-referencing link $url = $database->{'SYS'}{'LnkIntGallery'}; # Sorting method # Determine sort $sort = (defined($sparam->{'ACT'})) ? $sparam->{'ACT'} : 'name'; $osort = $sort; # Translate to query if ($sort eq 'date') { $sort = 'GalleryUpdated DESC'; } elsif ($sort eq 'rating') { $sort = 'GalleryRating ASC, GalleryName ASC'; } else { $sort = '"GalleryNewness" DESC, GalleryName ASC' } # Quickly grab total entries ($total) = $database->DataGet("SELECT COUNT(*) FROM Exhibition WHERE GalleryType=? AND GallerySub=? AND GalleryGenre=?", $sparam->{'TYP'}, $sparam->{'SUB'}, $sparam->{'GRE'} ); # Position based handling # Adjusting $pos = $sparam->{'GAL'}; # Determine position $pos = ((defined($pos)) && ($pos =~ /^\d+$/)) ? $pos : 1; # Determine offset $offset = ($pos - 1) * $gal->{'SetRetrieve'}; # Information display # Main display $database->Pull(\$statement, "SELECT GalleryID AS \"GalleryID\", PuppeteerLogin AS \"PuppeteerLogin\", GalleryName AS \"GalleryName\", GalleryRating AS \"GalleryRating\", GalleryDescription AS \"GalleryDescription\", GalleryThumbnail AS \"GalleryThumbnail\", getDate(GalleryCreated) AS \"GalleryCreated\", getDate(GalleryUpdated) AS \"GalleryUpdated\", getNew(GalleryUpdated) AS \"GalleryNewness\", WorkCount AS \"WorkCount\" FROM Exhibition WHERE GalleryType=? AND GallerySub=? AND GalleryGenre=? ORDER BY $sort LIMIT $gal->{SetRetrieve} OFFSET $offset", $sparam->{'TYP'}, $sparam->{'SUB'}, $sparam->{'GRE'} ); # Quick verification if ($res = $statement->fetchrow_hashref()) { # Navigational menu $type = $cgi->escape($sparam->{'TYP'}); $sub = $cgi->escape($sparam->{'SUB'}); $genre = $cgi->escape($sparam->{'GRE'}); # Self referencing link $link = $url . '/' . $type . '/' . $sub . '/' . $genre . '/' . $osort; # Inline parameter enbed $inline = (defined($param->{'USER'})) ? $param->EmbedInline($param->Flat()) : ''; # Capture nav line $page = Navigation($tmpl, $gal, $gal->{'SetRetrieve'}, $total, $pos, $link, $inline); # Initialize $list = ''; # Continue do { # Determine highlighting $highlight = (($sparam->{'TYP'} =~ /image/i) && (defined($res->{'GalleryThumbnail'}))) ? $tmpl->Pass('TmplGalleryHighlight', LTHUMB => $res->{'GalleryThumbnail'}) : ''; # Newness calculation $newness = ($res->{'GalleryNewness'} != 0) ? $gal->{'TagNewness'} : ''; # Link creation $link = $url . '/' . $type . '/' . $sub . '/' . $genre . '/' . $res->{'GalleryID'}; # Description $descr = (defined($res->{'GalleryDescription'})) ? $res->{'GalleryDescription'} : $gal->{'TxtDescription'}; # Display information $list .= $tmpl->Pass('TmplGalleryList', MAUTHOR => PenNames($database, $param, $tmpl, $gal, $res->{'GalleryID'}, $inline), MCREATED => $res->{'GalleryCreated'}, MDESCR => $descr, MHLIGHT => $highlight, MLINK => $link . $inline, MNAME => $res->{'GalleryName'}, MCOUNT => $res->{'WorkCount'}, MRATING => $res->{'GalleryRating'}, MUPDATED => $res->{'GalleryUpdated'}, MNEWNESS => $newness ); } while ($res = $statement->fetchrow_hashref()); # Self referencing link $link = $url . '/' . $type . '/' . $sub . '/' . $genre; # Display template $tmpl->Show('TmplGallery', LSTGAL => $list, LSTNAV => $page, LSTSORT => $sort, MSUB => $sparam->{'SUB'}, MGENRE => $sparam->{'GRE'}, LTYPE => $url . $inline, LSUB => $url . '/' . $type . '/' . $sub . $inline, LGENRE => $url . '/' . $type . '/' . $sub . '/' . $genre . $inline, LSDATE => $link . '/date' . $inline, LSRATE => $link . '/rate' . $inline, LSNAME => $link . '/name' . $inline, LSEARCH => $url . '/search' . $inline ); } # Nothing to see # Move along else { # Display error message $tmpl->Show('TmplSrch', MMESSAGE=>$gal->{'MsgListing'}); } # End statement $statement->finish(); } ##################### # Genre List # # Exists to provide a fuller front-end to the galleries. Which would allow for # spidering and even a nicer interface for people to use when wanting to see what # is available. sub GenreList { ##################### # 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 $statement; # Query handle my $cres; # Count results my $dres; # Description results list my $gres; # Genres results list my $tres; # Types results list my $count; # Occurences of type my $description; # Description my $inline; # Inline parameter set my $link; # Temporary constructed url my $url; # Self referencing link my %descr; # Description hash my %num; # Number of entries reached ##################### # Program Area # Self-referencing link $url = $database->{'SYS'}{'LnkIntGallery'}; # Inline parameter enbed $inline = (defined($param->{'USER'})) ? $param->EmbedInline($param->Flat()) : ''; # Type definition # Users have selected a type if ((defined($sparam->{'TYP'})) && (defined($sparam->{'SUB'}))) { # Descriptions handling # Decriptions are not native to exhibition table $database->Pull(\$statement, "SELECT GenreName AS \"Genre\", GenreDescription AS \"Description\" FROM Genre WHERE GenreType ILIKE ? AND GenreSub ILIKE ?", $sparam->{'TYP'}, $sparam->{'SUB'} ); # Loop and place in a hash while ($dres = $statement->fetchrow_hashref()) { # Creation of hash $descr{$dres->{'Genre'}} = $dres->{'Description'}; } # End query $statement->finish(); # Main display # Initialize my $list = ''; # Retreive sections list # Prepare and execute $database->Pull(\$statement, "SELECT GalleryGenre AS \"Genre\", COUNT(*) AS \"Count\" FROM Exhibition WHERE GalleryType ILIKE ? AND GallerySub ILIKE ? GROUP BY GalleryGenre ORDER BY GalleryGenre", $sparam->{'TYP'}, $sparam->{'SUB'} ); # Display all available genres # Loop and display while ($gres = $statement->fetchrow_hashref()) { # Generate link $link = $url . '/' . $sparam->{'TYP'} . '/' . $cgi->escape($sparam->{'SUB'}) . '/' . $cgi->escape($gres->{'Genre'}); # Description $description = (defined($descr{$gres->{'Genre'}})) ? $descr{$gres->{'Genre'}} : $gal->{'TxtDescription'}; # Append output $list .= $tmpl->Pass('TmplGenreDescription', MCOUNT => $gres->{'Count'}, MDESCR => $description, MGENRE => $gres->{'Genre'}, LGENRE => $link . $inline ); } # Finish up $statement->finish(); # Generate link $link = $url . '/' . $sparam->{'TYP'} . '/' . $cgi->escape($sparam->{'SUB'}); # Display wrapper template $tmpl->Show('TmplGenreSub', LSTSUB => $list, MSUB => $sparam->{'SUB'}, LSUB => $link . $inline, LTYPE => $url, LSEARCH => $url . '/search' ); } # No major-type selected # Mostly users coming in from cold else { # Get a count for every subtype $database->Pull(\$statement, "SELECT GalleryType AS \"Type\", GallerySub AS \"Sub\", COUNT(*) AS \"Count\" FROM Exhibition GROUP BY GalleryType, GallerySub"); # Populate hash while ($cres = $statement->fetchrow_hashref()) { # Put in the number $num{"$cres->{Type}.$cres->{Sub}"} = $cres->{'Count'}; } # Finish query $statement->finish(); # Main display # Initialize my $img = ''; my $txt = ''; # Define my $count = 0; # Retreive sections list # Prepare and execute $database->Pull(\$statement, "SELECT GenreType AS \"Type\", GenreName AS \"Sub\", GenreDescription AS \"Description\" FROM Genre WHERE GenreType IN ('image','text') AND GenreSub='' GROUP BY GenreType, GenreName, GenreDescription ORDER BY GenreName", ); # Display all available genres # Loop and display while ($tres = $statement->fetchrow_hashref()) { # Define count $count = (defined($num{"$tres->{Type}.$tres->{Sub}"})) ? $num{"$tres->{Type}.$tres->{Sub}"} : 0; # Skip if necessary next if ($count == 0); # Generate link $link = $url . '/' . $tres->{'Type'} . '/' . $cgi->escape($tres->{'Sub'}); # Description $description = (defined($tres->{'Description'})) ? $tres->{'Description'} : $gal->{'TxtDescription'}; # Append output # Reason why grouping was not necessary if ($tres->{'Type'} eq 'image') { # Append to image list $img .= $tmpl->Pass('TmplGenreDescription', MCOUNT => $count, MDESCR => $description, MGENRE => $tres->{'Sub'}, LGENRE => $link . $inline ); } else { # Append to text list $txt .= $tmpl->Pass('TmplGenreDescription', MCOUNT => $count, MDESCR => $description, MGENRE => $tres->{'Sub'}, LGENRE => $link . $inline ); } } # Finish up $statement->finish(); # Display wrapper template $tmpl->Show('TmplGenreType', LSTIMAGE => $img, LSTTEXT => $txt, LSEARCH => $url . '/search' ); } # Return return 1; } ##################### # Header rewrite # # Used to rewrite the HTML header as to properly list the Authors name # and gallery name in the title field. sub HeaderRewrite { ##################### # Data members my $database = shift; # Database handler my $cgi = shift; # Common gateway interface my $tmpl = shift; # Template handler my $menu = shift; # Menu rewrite my $sparam = shift; # Parameter line hash my $gal = shift; # Gallery parameter my $link; # Link name my $tree; # Tree interface my $author; # Author of gallery my $id; # Gallery ID my $name; # Gallery/Work name my $header; # HTML Header ##################### # Program area # Retrieve header ($header) = $database->DocumentGet('GalleryHeader'); # Tree link handling # Base link if ((defined($sparam->{'SUB'})) && (length($sparam->{'SUB'}) > 3)) { # The root # Self referencing link $link = $database->{'SYS'}{'LnkIntGallery'}; # Template $tree = $tmpl->Pass('TagTree', MNAME => '', MLINK => $link ); # Listing for genre # Additional link $link .= '/' . $sparam->{'TYP'} . '/' . $sparam->{'SUB'}; # Template $tree .= $tmpl->Pass('TagTree', MNAME => $sparam->{'SUB'}, MLINK => $link ); if ((defined($sparam->{'GRE'})) && (length($sparam->{'GRE'}) > 3)) { # Listing for galleries # Additional link $link .= '/' . $sparam->{'GRE'}; # Template $tree .= $tmpl->Pass('TagTree', MNAME => $sparam->{'GRE'}, MLINK => $link ); } } # Check for rewrite if ((defined($sparam->{'GAL'})) && ($sparam->{'GAL'} =~ /^\d+$/)) { # Gallery details # Pull details ($id, $author, $name) = $database->DataGet("SELECT GalleryID, GalleryPenName, GalleryName FROM Gallery WHERE GalleryID=?", $sparam->{'GAL'}); # Addition to the tree if (defined($name)) { # Listing for galleries if (defined($tree)) { # Additional link $link .= '/' . $sparam->{'GAL'}; # Template $tree .= $tmpl->Pass('TagTree', MNAME => $name, MLINK => $link ); } # Work takes over title if ((defined($sparam->{'WRK'})) && ($sparam->{'WRK'} =~ /^\d+$/)) { # Pull details ($id, $author, $name) = $database->DataGet("SELECT g.GalleryID, g.GalleryPenName, w.WorkName FROM Gallery g, Work w WHERE w.GalleryID=g.GalleryID AND g.GalleryID=? AND w.WorkID=?", $sparam->{'GAL'}, $sparam->{'WRK'} ); # Replace if need be if (defined($name)) { # Listing for galleries if (defined($tree)) { # Additional link $link .= '/' . $sparam->{'WRK'}; # Template $tree .= $tmpl->Pass('TagTree', MNAME => $name, MLINK => $link ); } # Reset title $database->{'TITLE'} = "$name by $author"; } } # Galleries # This is the default else { # Reset title $database->{'TITLE'} = "$author: $name"; } } } # Safety $tree = (defined($tree)) ? $tree : $gal->{'TagTreeBlank'}; # Replace $header =~ s/MTREE/$tree/gs; # Print out modified header print $menu->Rewrite($header); } ##################### # Navigation # # Used to consolidate navigational methods on the site employing OFFSET and LIMIT # which are available on PostgreSQL. sub Navigation { ##################### # Data members my $tmpl = shift; # Template handler my $gal = shift; # Gallery hash my $display = shift; # Entries to show off my $total = shift; # Total entries my $offset = shift; # Current position my $url = shift; # Link to display my $inline = shift; # Inline parameters my $count; # Basic counter my $frst; # First entry my $last; # Last entry my $next; # Next entry my $prev; # Prev entry my $link; # Generated link my $nav; # Completed navigational page my $pass; # What is passed ##################### # Program area # Set values $count = 0; $nav = ''; $pass = ' '; # Calculate next and previous $frst = 1; $last = (($total - ($total % $display)) / $display) + 1; $prev = (($offset - 1) > 0) ? $offset - 1 : 1; $next = (($offset + 1) <= $last) ? $offset + 1 : $last; # Loop do { # Remove mount to verify spacing $total -= $display; # Increment $count++; # Assign $link = $url . '/' . $count . $inline; # Append $nav .= ($offset == $count) ? $tmpl->Pass('TagNavView', MNAME=>$count, MLINK=>$link) : $tmpl->Pass('TagNav', MNAME=>$count, MLINK=>$link); } while ($total > 0); # Generate template # Only if there is a need $pass = $tmpl->Pass('TagNav', MNAME=>$gal->{'TxtFirst'}, MLINK=>$url . '/' . $frst . $inline) . $tmpl->Pass('TagNav', MNAME=>$gal->{'TxtPrev'}, MLINK=>$url . '/' . $prev . $inline) . $nav . $tmpl->Pass('TagNav', MNAME=>$gal->{'TxtNext'}, MLINK=>$url . '/' . $next . $inline) . $tmpl->Pass('TagNav', MNAME=>$gal->{'TxtLast'}, MLINK=>$url . '/' . $last . $inline) if ($count > 1); # Return completed return $pass; } ##################### # Pen Names # # Will take a list of all contributors and make it in such a way that it # can display all of the contributors on one line. sub PenNames { ##################### # Data members my $database = shift; # Database handler my $param = shift; # Parameter list my $tmpl = shift; # Template handler my $gal = shift; # Gallery parameter my $id = shift; # Gallery ID my $inline = shift; # Predefined inlines my $owner = shift; # Rightful owner my $count; # Basic counter my $entries; # Number entries my $ibio; # Link to the bio my $consol; # Consolidated lines my $spacer; # Employed spacer my @args; # Arguments to send my @contribs; # Complete list of contributors ##################### # Program area # Owner of gallery # Owner specified if (defined($owner)) { # Pass arguments push(@args, $id, $owner); # Throw in additional formatting $owner = 'AND PuppeteerLogin=? '; } # Normal dual entry else { # Normal passage push(@args, $id); # Nothing to see $owner = ''; } # Pull list of all contributors $database->GetList(\@contribs, "SELECT PuppetName FROM GalleryAccess WHERE GalleryID=? $owner ORDER BY AccessOwner DESC, PuppetName", @args); # Amount of entries $entries = @contribs; # Initiate $consol = ''; # Loop and search for ($count=0; $count < $entries; $count++) { # Generate biographical link $ibio = '/' . join('', $database->DataGetPuppetShortname($contribs[$count])) . '/system' . $inline; # Information handling # Initialize if ($count == 0) { # Set authors information first $consol .= $tmpl->Pass('TagPenName', MNAME => $contribs[$count], MLINK => $database->{'SYS'}{'LnkIntBio'} . $ibio ); } # Appending else { # Spacer $spacer = ($count != ($entries-1)) ? $gal->{'TagPenNameSpacer'} : $gal->{'TagPenNameFinalize'}; # Additional contributors $consol .= $spacer . $tmpl->Pass('TagPenName', MNAME => $contribs[$count], MLINK => $database->{'SYS'}{'LnkIntBio'} . $ibio ); } } # Return consolidated line return $consol; } ##################### # Work Detail # # Work display allows a user to view the works themselves in full # detail. sub WorkDetail { ##################### # 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 $option; # Option handler my $layer; # Layer management my $res; # Results my $revisions; # Query for revisions my $statement; # Query statement my $cmnt; # Comment preferences my $name; # Verification check my $type; # Gallery type my $view; # Type of view my $order; # Sort order my $sort; # Sort type my $comments; # Comments template my $descr; # Description my $pen; # Pen names formatted my $work; # Work template my $next = 0; # Next sequence my $curr = 0; # Current position my $prev = 0; # Previous record my $totl = 0; # Total amount of works my $rate; # Rating my $user; # Username my $vote; # Votes my $url; # Self referencing link my $inline; # Inline parameters 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)); # Create instance $option = new Ethereal::Option; # Determine layer handling $layer = ($sparam->{'LYR'} > 0) ? 'AND WorkLayer=' . $sparam->{'LYR'} : 'AND WorkLayer IS NULL'; # Information gathering # Retreive gallery basics ($sort, $cmnt, $type, $user) = $database->DataGet("SELECT GallerySort, GalleryComments, GalleryType, PuppeteerLogin FROM Gallery WHERE GalleryID=?", $sparam->{'GAL'} ); # Ordering type $order = $option->GallerySortReal($sort); # Retrieve next of kin $database->GetList(\@seq, "SELECT WorkID FROM Work WHERE GalleryID=? $layer AND WorkID > 1 ORDER BY $order", $sparam->{'GAL'} ); # Total $totl = @seq; # Where we are for ($curr=0; $curr < $totl; $curr++) { # Find and leave loop last unless ($seq[$curr] != $sparam->{'WRK'}); } # Position of cousins $next = ($curr+1 >= $totl) ? $seq[0] : $seq[$curr+1]; $prev = $seq[$curr-1]; # Linking # Fetch link $url = $database->{'SYS'}{'LnkIntGallery'} . '/' . $cgi->escape($sparam->{'TYP'}) . '/' . $cgi->escape($sparam->{'SUB'}) . '/' . $cgi->escape($sparam->{'GRE'}) . '/' . $sparam->{'GAL'} . '/' . $sparam->{'LYR'}; # Inline parameters general $inline = (defined($param->{'USER'})) ? $param->EmbedInline(USER=>$param->{'USER'}, CRYPT=>$param->{'CRYPT'}) : ''; # Works of art # Retrieve rating ($rate, $vote) = $database->DataGetWorkAvg($sparam->{'WRK'}, $sparam->{'GAL'}); # Prepare and execute $database->Pull(\$statement, "SELECT PuppeteerLogin AS \"WorkOwner\", WorkName AS \"WorkName\", WorkDescription AS \"WorkDescription\", WorkSort AS \"WorkSort\", WorkImage AS \"WorkImage\", WorkImageThumbnail AS \"WorkImageThumbnail\", WorkImageSize AS \"WorkImageSize\", WorkImageWidth AS \"WorkImageWidth\", WorkImageHeight AS \"WorkImageHeight\", WorkImageView AS \"WorkImageView\", WorkImageFull AS \"WorkImageFull\", WorkImageExif AS \"WorkImageExif\", WorkText AS \"WorkText\", WorkTextPreserve AS \"WorkTextPreserve\", getDate(WorkTimestamp) AS \"WorkTimestamp\" FROM Work WHERE WorkID=? AND GalleryID=?", $sparam->{'WRK'}, $sparam->{'GAL'} ); # Make available if ($res = $statement->fetchrow_hashref()) { # Fork for gallery styles # Image gallery if ($type eq 'image') { # Exif information my $exif = (defined($res->{'WorkImageExif'})) ? $tmpl->Pass('TmplImageExif', MEXIF=>$res->{'WorkImageExif'}) : ''; # View related plesantries # Full view if ((defined($sparam->{'POS'})) && ($sparam->{'POS'} eq 'full')) { # Adjust link to work $view = $res->{'WorkImage'}; # Replace appropriatly $view =~ s/^(.+\/)(view-)(work\.\w+)$/$1$3/; # Display image specific # Full view $work = $tmpl->Pass('TmplImageWork', LSTEXIF => $exif, LIMAGE => $view, LTOGGLE => $url . '/' . $sparam->{'WRK'}, MNAME => $res->{'WorkName'}, MWDHT => $res->{'WorkImageFull'}, MTOGGLE => $gal->{'TagImageView'} ); } # Regular view else { # Display image specific # Normal view $work = $tmpl->Pass('TmplImageWork', LSTEXIF => $exif, LIMAGE => $res->{'WorkImage'}, LTOGGLE => $url . '/' . $sparam->{'WRK'} . '/full', MNAME => $res->{'WorkName'}, MWDHT => $res->{'WorkImageView'}, MTOGGLE => $gal->{'TagImageFull'} ); } } # Text based galleries elsif ($type eq 'text') { # Local variables my ($rdate, $rstamp); # Initial assignment my $print = ''; my $revs = ''; my $post = $res->{'WorkText'}; # Make use of revision instead if ((defined($sparam->{'POS'})) && ($sparam->{'POS'} =~ /^\w{30,}/)) { # Make use of revision ($post, $rdate) = $database->DataGet("SELECT RevisionText, getDate(RevisionTimestamp) FROM Revision WHERE WorkID=? AND GalleryID=? AND RevisionTimestamp=?", $sparam->{'WRK'}, $sparam->{'GAL'}, pack('H*', $sparam->{'POS'}) ); # Append notice $post .= $tmpl->Pass('TagRevNotice', MDATE => $rdate ); } # Rewriting # Basic replacements $post =~ s/$/\n/; # Maintain spacing $post =~ s/\n/
/gs; # Revision control if ($type eq 'text') { # Pull new list $database->Pull(\$revisions, "SELECT RevisionTimestamp AS \"Timestamp\", getDate(RevisionTimestamp) AS \"Date\" FROM Revision WHERE WorkID=? AND GalleryID=?", $sparam->{'WRK'}, $sparam->{'GAL'} ); # Verification if (($rstamp, $rdate) = $revisions->fetchrow()) { # Initialize template $revs = $gal->{'TagRevTitle'}; # Initial link $revs .= $tmpl->Pass('TagRevLink', MLINK => $url . '/' . $sparam->{'WRK'} . $inline, MNAME => $gal->{'TxtRecent'} ); # Check first do { # Append additional links $revs .= $tmpl->Pass('TagRevLink', MLINK => $url . '/' . $sparam->{'WRK'} . '/' . unpack('H*', $rstamp) . $inline, MNAME => $rdate ); } while (($rstamp, $rdate) = $revisions->fetchrow()); # Close off $revs .= $gal->{'TagRevClose'}; # Close handle $revisions->finish(); } } # Printing option if (-f "$database->{SYS}{SetGalleryRoot}/$sparam->{GAL}/$sparam->{WRK}/work.pdf") { # Show print option $print = $tmpl->Pass('TagPrint', MLINK => "$database->{SYS}{SetGalleryLink}/$sparam->{GAL}/$sparam->{WRK}/work.pdf" ); } # Display image specific $work = $tmpl->Pass('TmplTextWork', MTEXT => $post, MREVS => $revs, MPRINT => $print ); } # Additional information # List comments $comments = CommentDisplay( $database, $login, $cgi, $param, $tmpl, $sparam, $gal, $gal->{'SetRetrieve'} ); # Pen names $pen = PenNames( $database, $param, $tmpl, $gal, $sparam->{'GAL'}, $inline, $res->{'WorkOwner'} ); # Establishment of views $view = ($sparam->{'POS'} eq 'full') ? '/full' : ''; # Safety $descr = (defined($res->{'WorkDescription'})) ? $res->{'WorkDescription'} : $gal->{'TxtDescription'}; # Common display # Header $tmpl->Show('TmplWork', MAUTHOR => $pen, MCOMMENT => $comments, MCURR => $curr+1, MDESC => $descr, MNAME => $res->{'WorkName'}, MWORK => $work, MTOTAL => $totl, LGTOP => $url . '/' . $inline, LNEXT => $url . '/' . $next . $view . $inline, LPREV => $url . '/' . $prev . $view . $inline ); } # Finish query $statement->finish(); } # Signal error else { # Invalid entry $tmpl->Show('TmplMsg', MMESSAGE=>$gal{'MsgParam'}); } } ##################### # Work Listing # # Work listing will allow casual viewers to see an overview of every # work available. This includes a naivgational system, and an overview of # the more recent comments made on works. sub WorkList { ##################### # 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 $filter; # Filtering options my $option; # Option handler my $gsth; # Gallery query my $lsth; # Link query my $msth; # Map query my $nsth; # News query my $ssth; # Layers query my $wsth; # Works query my $gres; # Information on gallery my $lres; # Link results page my $mres; # Mapping results my $nres; # Information on news items my $sres; # Information on layers my $wres; # Information on works my $descr; # Description my $length; # Text length my $rating; # Rating my $thumb; # Thumbnail config my $expand; # Expansion handling my $layer; # Layer to search through my $newness; # Newness factor my $offset; # Where to start from my $order; # Searching order my $parent; # Parent layer my $total; # Entries to look out for my $user; # Username of owner my $watch; # Watch gallery my $authors; # Author management my $comments; # Comments template my $genres; # Formatted genres my $intro; # Intro section my $layers; # Layer page my $links; # Links page my $map; # The map action button/menu my $news; # News entry my $page; # Navigational page my $single; # Single line to work with my $works; # Works page my $int_id; # Intro's used identifier my $int_name; # Intro's used name my $int_descr; # Intro's used description my $int_level; # Intro's used level my $int_light; # Intro's used highlight my $int_short; # Intro's used short name my $int_thumb; # Intro's used thumbnail my $inline; # Inline parameters my $iwatch; # Puppet watch option my $link_work; # Link pertaining to works my $link; # Managed link my @genres; # Multiple genres my @layers = qw(Zero One Two Three Four Five); # Levels for layers my @levels; # Levels captured my %pass; # Temporary passthrough for parameters ##################### # Program Area # Authentication # Exit unless things are proper return 0 unless (CheckAuth($database, $login, $param, $sparam, $tmpl, $gal)); # Create instance $option = new Ethereal::Option(); # Safety $sparam->{'LYR'} = 0 unless ((defined($sparam->{'LYR'})) && ($sparam->{'LYR'} =~ /^(\d+|map)$/)); # Work cannot be defined # If made it this far $sparam->{'WRK'} = 0; # Link management # Generate primary working link $link = $database->{'SYS'}{'LnkIntGallery'} . '/' . $cgi->escape($sparam->{'TYP'}) . '/' . $cgi->escape($sparam->{'SUB'}) . '/' . $cgi->escape($sparam->{'GRE'}) . '/' . $sparam->{'GAL'}; # Generate link required for works $link_work = $database->{'SYS'}{'LnkIntGallery'} .'/' . $cgi->escape( $sparam->{'TYP'}) . '/' . $cgi->escape($sparam->{'SUB'}) . '/' . $cgi->escape($sparam->{'GRE'}) . '/' . $sparam->{'GAL'} . '/' . $sparam->{'LYR'}; # Inline parameters general $inline = (defined($param->{'USER'})) ? $param->EmbedInline(USER=>$param->{'USER'}, CRYPT=>$param->{'CRYPT'}) : ''; # Mapping option # General to both $map = $tmpl->Pass('TagNav', MNAME => $gal->{'TxtMap'}, MLINK => $link . '/map' . $inline ); # Base information # Gallery information $database->Pull(\$gsth, "SELECT PuppeteerLogin AS \"PuppeteerLogin\", GalleryName AS \"GalleryName\", GalleryRating AS \"GalleryRating\", GalleryDescription AS \"GalleryDescription\", GalleryHighlight AS \"GalleryHighlight\", GalleryThumbnail AS \"GalleryThumbnail\", GallerySort AS \"GallerySort\", GalleryType AS \"GalleryType\", GalleryComments AS \"GalleryComments\", GalleryDisplay AS \"GalleryDisplay\", getDate(GalleryCreated) AS \"GalleryCreated\", getDate(GalleryUpdated) AS \"GalleryUpdated\" FROM Gallery WHERE GalleryID=?", $sparam->{'GAL'} ); # Common controls without depth # Check values if ($gres = $gsth->fetchrow_hashref()) { # Genres # Genre searching $database->GetListEstablished(\@genres, $sparam->{'GAL'}); # Format genre line $genres = join("/", @genres); # Authors # Determine authors $authors = PenNames( $database, $param, $tmpl, $gal, $sparam->{'GAL'}, $inline ); # Watchful processing # Watch allows the notification of changes to user if (defined($param->{'USER'})) { # Determine watch ($watch) = $database->DataGetGalleryWatch($sparam->{'GAL'}, $param->{'USER'}); # Toggle watch if (defined($param->{'WATCH'})) { # Change standing behaviour if (defined($watch)) { # Remove database entry $database->Quick("DELETE FROM GalleryNotify WHERE GalleryID=? AND PuppeteerLogin=?", $sparam->{'GAL'}, $param->{'USER'} ); # Change logic $watch = undef; } else { # Create entry $database->Quick("INSERT INTO GalleryNotify (GalleryID, PuppeteerLogin) VALUES (?,?)", $sparam->{'GAL'}, $param->{'USER'} ); # Change logic $watch = $param->{'USER'}; } # Cleanup $param->Cleanup('WATCH'); } # Generate inline $iwatch = $param->EmbedInline( USER => $param->{'USER'}, CRYPT => $param->{'CRYPT'}, WATCH => 'True' ); # Change langauge $watch = (defined($watch)) ? $tmpl->Pass('TagGalIgnore', MLINK=>$link . $iwatch) : $tmpl->Pass('TagGalWatch', MLINK=>$link . $iwatch); } # Safety # Generate widget $watch = $tmpl->Pass('TagGalWatch', MLINK=>"$link\?USER\=\&WATCH\=True") unless (defined($watch)); } # Pull in values # Do not show a site map if ((defined($gres)) && ($sparam->{'LYR'} =~ /^\d+$/)) { # Assign username $user = $gres->{'PuppeteerLogin'}; # Sorting order # Ordering type $order = $option->GallerySortReal($gres->{'GallerySort'}); # Offset management # Starting point $sparam->{'POS'} = 1 unless ((defined($sparam->{'POS'})) && ($sparam->{'POS'} =~ /^\d+$/)); # Offset $offset = ($sparam->{'POS'} - 1) * $gres->{'GalleryDisplay'}; # Layer handling $layer = ($sparam->{'LYR'} > 0) ? 'AND WorkLayer=' . $sparam->{'LYR'} . ' ' : 'AND WorkLayer IS NULL '; # Layer information if ($sparam->{'LYR'} != 0) { # Get specific information in case ($int_id, $int_short, $int_name, $int_descr, $int_light, $int_thumb, $int_level, @levels) = $database->DataGet("SELECT LayerID AS \"LayerID\", LayerShort AS \"LayerShort\", LayerFull AS \"LayerFull\", LayerDescription AS \"LayerDescription\", LayerHighlight AS \"LayerHighlight\", LayerThumbnail AS \"LayerThumbnail\", LayerLevel AS \"LayerLevel\", LevelZero AS \"LevelZero\", LevelOne AS \"LevelOne\", LevelTwo AS \"LevelTwo\", LevelThree AS \"LevelThree\", LevelFour AS \"LevelFour\", LevelFive AS \"LevelFive\" FROM Layer WHERE GalleryID=? AND LayerID=?", $sparam->{'GAL'}, $sparam->{'LYR'} ); # Determine parent $parent = $levels[$int_level-1] if ($int_level > 0); } # Make sure information is present # Else override with gallery information $int_descr = (defined($int_descr)) ? $int_descr : $gres->{'GalleryDescription'}; $int_light = (defined($int_light)) ? $int_light : $gres->{'GalleryHighlight'}; $int_name = (defined($int_name)) ? $int_name : $gres->{'GalleryName'}; # Images may have issues $int_thumb = (defined($int_thumb)) ? $int_thumb : $gres->{'GalleryThumbnail'}; $int_thumb = (defined($int_thumb)) ? $int_thumb : $gal->{'SetImgBlank'}; # No description then put one in $int_descr = (defined($int_descr)) ? $int_descr : $gal->{'TxtDescription'}; # Embeded Layers # No need for a sub-page if ($sparam->{'POS'} == 1) { # Safety $int_level = (defined($int_level)) ? $int_level : 0; # Expand query as necessary $expand = (defined($int_id)) ? "AND LayerLevel=" . ($int_level+1) . " AND Level$layers[$int_level]=" . DBI::neat($int_short) : "AND LayerLevel=" . $int_level; # Prepare query as these are # general to both types $database->Pull(\$ssth, "SELECT LayerID AS \"LayerID\", LayerFull AS \"LayerFull\", LayerDescription AS \"LayerDescription\", LayerThumbnail AS \"LayerThumbnail\" FROM Layer WHERE GalleryID=? $expand ORDER BY LayerFull", $sparam->{'GAL'} ); } # Specific type processing # Image galleries if ($gres->{'GalleryType'} eq 'image') { # Information display # Intro and summary $intro = $tmpl->Pass('TmplImageIntro', MDESCR => $int_descr, MHLIGHT => $int_light, MTHUMB => $int_thumb, MGENRE => $genres, MAUTHOR => $authors, MRATING => $gres->{'GalleryRating'}, MTITLE => $int_name, MCREATED => $gres->{'GalleryCreated'}, MUPDATED => $gres->{'GalleryUpdated'}, MWATCH => $watch ); # Work information # Amount of works ($total) = $database->DataGet("SELECT COUNT(*) FROM Work WHERE GalleryID=? AND WorkImage IS NOT NULL $layer", $sparam->{'GAL'} ); # Capture nav line $page = Navigation( $tmpl, $gal, $gres->{'GalleryDisplay'}, $total, $sparam->{'POS'}, $link . '/' . $sparam->{'LYR'} .'/', $inline ); # Layer management if (defined($ssth)) { # Parent return # Parent is a layer if (defined($parent)) { # Get specific information in case ($int_id, $int_name, $int_descr, $int_light, $int_thumb) = $database->DataGet("SELECT LayerID AS \"LayerID\", LayerFull AS \"LayerFull\", LayerDescription AS \"LayerDescription\", LayerHighlight AS \"LayerHighlight\", LayerThumbnail AS \"LayerThumbnail\", LayerLevel AS \"LayerLevel\" FROM Layer WHERE GalleryID=? AND LayerShort=?", $sparam->{'GAL'}, $parent ); # Make sure thumnail is assigned $thumb = (defined($int_thumb)) ? $int_thumb : $gal->{'SetImgBlank'}; # Layer has a layer parent $works = $tmpl->Pass('TmplImageLayer', MNAME => $int_name, MDESCR => $int_descr, MIMAGE => $thumb, MTYPE => $gal->{'SetLayerParent'}, MLINK => $link . '/' . $int_id . $inline ); } # Parent is the root elsif ((!defined($parent)) && ($sparam->{'LYR'} != 0)) { # Make sure thumnail is assigned $thumb = (defined($gres->{'GalleryThumbnail'})) ? $gres->{'GalleryThumbnail'} : $gal->{'SetImgBlank'}; # Layer has the root as a parent $works = $tmpl->Pass('TmplImageLayer', MNAME => $gres->{'GalleryName'}, MDESCR => $gres->{'GalleryDescription'}, MIMAGE => $gres->{'GalleryThumbnail'}, MTYPE => $gal->{'SetLayerParent'}, MLINK => $link . $inline ); } # Children layers # Loop and manage while ($sres = $ssth->fetchrow_hashref()) { # Make sure thumnail is assigned $thumb = (defined($sres->{'LayerThumbnail'})) ? $sres->{'LayerThumbnail'} : $gal->{'SetImgBlank'}; # Generate template # Store for addition into main list $works .= $tmpl->Pass('TmplImageLayer', MNAME => $sres->{'LayerFull'}, MDESCR => $sres->{'LayerDescription'}, MIMAGE => $thumb, MTYPE => $gal->{'SetLayerChild'}, MLINK => $link . '/' . $sres->{'LayerID'} . $inline ); } # End query $ssth->finish(); } # Works # Prepare query $database->Pull(\$wsth, "SELECT WorkID AS \"WorkID\", WorkName AS \"WorkName\", WorkDescription AS \"WorkDescription\", WorkRating AS \"WorkRating\", WorkImageThumbnail AS \"WorkImageThumbnail\", WorkImageSize AS \"WorkImageSize\", WorkImageWidth AS \"WorkImageWidth\", WorkImageHeight AS \"WorkImageHeight\", WorkImageView AS \"WorkImageView\", WorkImageFull AS \"WorkImageFull\", getDate(WorkTimestamp) AS \"WorkTimestamp\", getNew(WorkTimestamp) AS \"WorkNewness\" FROM Work WHERE GalleryID=? AND WorkImage IS NOT NULL $layer ORDER BY \"WorkNewness\" DESC, $order LIMIT $gres->{GalleryDisplay} OFFSET $offset", $sparam->{'GAL'} ); # Test the waters # Cycle through while ($wres = $wsth->fetchrow_hashref()) { # Tag adjustements # Newness tag $newness = ($wres->{'WorkNewness'} != 0) ? $gal->{'TagNewness'} : ''; # If need exists if (($gres->{'GalleryComments'} eq 'comment') || ($gres->{'GalleryComments'} eq 'combo')) { # Caculate $rating = $wres->{'WorkRating'}; } else { # Assign nil $rating = $gal->{'SetNil'}; } # Generate template # Store for addition into main list $works .= $tmpl->Pass('TmplImageList', MNAME => $wres->{'WorkName'}, MDESCR => $wres->{'WorkDescription'}, MIMAGE => $wres->{'WorkImageThumbnail'}, MLINK => $link_work . '/' . $wres->{'WorkID'} . $inline, MRATING => $rating, MSIZE => $wres->{'WorkImageSize'}, MHEIGHT => $wres->{'WorkImageHeight'}, MWIDTH => $wres->{'WorkImageWidth'}, MTHUMB => $database->{'SYS'}{'SetThumbnail'}, MVIEW => $wres->{'WorkImageView'}, MUPDATED => $wres->{'WorkTimestamp'}, MNEWNESS => $newness, MWINDOW => 'WIN' . $sparam->{'GAL'} . 'x' . $sparam->{'LYR'} ); } # Finish query $wsth->finish(); } # Text based galleries elsif ($gres->{'GalleryType'} eq 'text') { # Information display # Intro and summary $intro = $tmpl->Pass('TmplTextIntro', MDESCR => $int_descr, MGENRE => $genres, MAUTHOR => $authors, MRATING => $gres->{'GalleryRating'}, MTITLE => $int_name, MCREATED => $gres->{'GalleryCreated'}, MUPDATED => $gres->{'GalleryUpdated'}, MWATCH => $watch ); # Work information # Calculate totals ($total) = $database->DataGet("SELECT COUNT(*) FROM Work WHERE GalleryID=? AND WorkText IS NOT NULL $layer", $sparam->{'GAL'} ); # Capture nav line $page = Navigation( $tmpl, $gal, $gres->{'GalleryDisplay'}, $total, $sparam->{'POS'}, $link . '/' . $sparam->{'LYR'} . '/', $inline ); # Layer management if (defined($ssth)) { # Parent return # Parent is a layer if (defined($parent)) { # Get specific information in case ($int_id, $int_name, $int_descr) = $database->DataGet("SELECT LayerID AS \"LayerID\", LayerFull AS \"LayerFull\", LayerDescription AS \"LayerDescription\" FROM Layer WHERE GalleryID=? AND LayerID=?", $sparam->{'GAL'}, $parent ); # Layer has a layer parent $works = $tmpl->Pass('TmplTextLayer', MNAME => $int_name, MDESCR => $int_descr, MTYPE => $gal->{'SetLayerParent'}, MLINK => $link . '/' . $int_id . $inline ); } # Parent is the root elsif ((!defined($parent)) && ($sparam->{'LYR'} != 0)) { # Layer has the root as a parent $works = $tmpl->Pass('TmplTextLayer', MNAME => $gres->{'GalleryName'}, MDESCR => $gres->{'GalleryDescription'}, MTYPE => $gal->{'SetLayerParent'}, MLINK => $link . $inline ); } # Loop and manage while ($sres = $ssth->fetchrow_hashref()) { # Generate template # Store for addition into main list $works .= $tmpl->Pass('TmplTextLayer', MNAME => $sres->{'LayerFull'}, MDESCR => $sres->{'LayerDescription'}, MTYPE => $gal->{'SetLayerChild'}, MLINK => $link . '/' . $sres->{'LayerID'} . $inline ); } # End query $ssth->finish(); } # Work management # Detailed information $database->Pull(\$wsth, "SELECT WorkID AS \"WorkID\", WorkName AS \"WorkName\", WorkDescription AS \"WorkDescription\", WorkRating AS \"WorkRating\", WorkText AS \"WorkText\", getDate(WorkTimestamp) AS \"WorkTimestamp\", getNew(WorkTimestamp) AS \"WorkNewness\" FROM Work WHERE GalleryID=? AND WorkText IS NOT NULL $layer ORDER BY \"WorkNewness\" DESC, $order LIMIT $gres->{GalleryDisplay} OFFSET $offset", $sparam->{'GAL'} ); # Create instance $filter = new Ethereal::Filter(); # Safety check while ($wres = $wsth->fetchrow_hashref()) { # Newness tag $newness = ($wres->{'WorkNewness'} != 0) ? $gal->{'TagNewness'} : ''; # Tag assignments # If need exists if (($gres->{'GalleryComments'} eq 'comment') || ($gres->{'GalleryComments'} eq 'combo')) { # Calculate $rating = $wres->{'WorkRating'}; } else { # Assign nil $rating = $gal->{'SetNil'}; } # Description $descr = $wres->{'WorkDescription'}; $descr = (defined($descr)) ? $descr : $filter->StripHTML(substr(DBI::neat($wres->{'WorkText'}, 252), 1, -1)); # Length $length = length($wres->{'WorkText'}); # Display $works .= $tmpl->Pass('TmplTextList', MNAME => $wres->{'WorkName'}, MDESCR => $descr, MLENGTH => format_number($length, 0), MLINK => $link_work . '/' . $wres->{'WorkID'} . $inline, MRATING => $rating, MUPDATED => $wres->{'WorkTimestamp'}, MNEWNESS => $newness, MWINDOW => 'WIN' . $sparam->{'GAL'} . 'x' . $sparam->{'LYR'} ); } # Finish query $wsth->finish(); } # Additional features # Generate and display if (($sparam->{'POS'} == 1) && ($sparam->{'LYR'} == 0)) { # Gallery Comments # Passing of temporary values %pass = (%{$sparam}, WRK=>0); # Comments # Initialize $comments = ''; # List comments $comments = CommentDisplay( $database, $login, $cgi, $param, $tmpl, \%pass, $gal, $gal->{'SetRetrieve'} ); # News Items # Initalize $news = ''; # Expansion handling $expand = (defined($param->{'EXPAND'})) ? '' : 'LIMIT 5'; # Prepare query $database->Pull(\$nsth, "SELECT CommentID AS \"CommentID\", CommentPost AS \"CommentPost\", getDate(CommentTimestamp) AS \"CommentTimestamp\" FROM Comment WHERE GalleryID=? AND WorkID=1 ORDER BY CommentTimestamp DESC $expand", $sparam->{'GAL'}); # Pull information # Verify need if ($nres = $nsth->fetchrow_hashref()) { # Ability to expand $expand = $param->EmbedInline($param->Flat(), EXPAND=>'True'); $expand = $link . '/' . $sparam->{'LYR'} . $expand; # Self referencing links my $idelete = ''; my $ldelete = $database->{'SYS'}{'LnkIntGallery'} . '/comment/' . $sparam->{'GAL'} . '/' . 1; # Initialize $single = ''; # Loop and display do { # Check for need to generate $idelete = $tmpl->Pass('TagDelete', MLINK => $ldelete . '/' . $nres->{'CommentID'} . $inline ) if ((defined($param->{'USER'})) && ($user eq $param->{'USER'})); # Display $single .= $tmpl->Pass('TmplQNewsEntry', MDATE => $nres->{'CommentTimestamp'}, MTEXT => $nres->{'CommentPost'}, MDELL => $idelete ); } while ($nres = $nsth->fetchrow_hashref()); # Run through final template $news .= $tmpl->Pass('TmplQNews', LSTNEWS => $single, LNEXP => $expand ); } # Finish query $nsth->finish(); # Quick Links # Initalize $links = ''; # Prepare retreival $database->Pull(\$lsth, "SELECT LinkName AS \"LinkName\", LinkAddress AS \"LinkAddress\" FROM Link WHERE GalleryID=? ORDER BY LinkName", $sparam->{'GAL'} ); # Check and initial setup if ($lres = $lsth->fetchrow_hashref()) { # Intialize $single = ''; # Loop and populate main body do { # Display $single .= $tmpl->Pass('TmplQLinksEntry', MLINK => $lres->{'LinkAddress'}, MNAME => $lres->{'LinkName'} ); } while ($lres = $lsth->fetchrow_hashref()); # Generate final template $links .= $tmpl->Pass('TmplQLinks', LSTLINKS => $single ); } # Finish query $lsth->finish(); # Is there still a need # All necessary components in place if ((length($news) > 5) && (length($links) > 5)) { # Complete view $tmpl->Show('TmplListingPri', MINTRO => $intro, MNAV => $page, MMAP => $map, MNEWS => $news, MQUICK => $links, MCOMMENT => $comments, LSTWORKS => $works ); } else { # Simplified view $tmpl->Show('TmplListingSec', MINTRO => $intro, MNAV => $page, MMAP => $map, LSTWORKS => $works ); } } # Simple view # Simply display appropriate template else { # Display final work # Simplified view $tmpl->Show('TmplListingSec', MINTRO => $intro, MNAV => $page, MMAP => $map, LSTWORKS => $works ); } } # Do not show a site map elsif ((defined($gres)) && ($sparam->{'LYR'} =~ /^map$/)) { # Pull necessary information for data map $database->Pull(\$msth, "SELECT l.LayerID AS \"LayerID\", l.LayerFull AS \"LayerFull\", l.LayerLevel AS \"LayerLevel\", COUNT(w.GalleryID) AS \"LayerCount\" FROM Layer l LEFT OUTER JOIN Work w ON (l.GalleryID=w.GalleryID AND l.LayerID=w.WorkLayer) WHERE l.GalleryID=? GROUP BY l.LayerID, l.LayerFull, l.LayerLevel, l.LevelZero, l.LevelOne, l.LevelTwo, l.LevelThree, l.LevelFour, l.LevelFive ORDER BY l.LevelZero, l.LevelOne, l.LevelTwo, l.LevelThree, l.LevelFour, l.LevelFive", $sparam->{'GAL'} ); # Initialize $map = ''; # There is mapping information if ($mres = $msth->fetchrow_hashref()) { # Initliaze my $count; my $spacer; my $olayer = $mres->{'LayerLevel'}; # Loop through do { # Level additions # Change based on up or down if ($olayer > $mres->{'LayerLevel'}) { # Drop as far as necessary $count = $olayer; # Go down, way down do { # Generate spacer $spacer = ' ' x ($count-1); # Move down a level $map .= $spacer . $gal->{'TagMapStepDown'} . "\n"; # Decrement $count--; } while ($count > $mres->{'LayerLevel'}); } # Moving up elsif ($olayer < $mres->{'LayerLevel'}) { # Generate spacer $spacer = ' ' x ($mres->{'LayerLevel'}); # Move up a level $map .= $spacer . $gal->{'TagMapStepUp'} . "\n"; } # General statement # Spacer for this level $spacer = ' ' x ($mres->{'LayerLevel'}+1); # Addition of unit $map .= $spacer . $tmpl->Pass('TmplMapStep', MNAME => $mres->{'LayerFull'}, MCOUNT => $mres->{'LayerCount'}, MLINK => $link . '/' . $mres->{'LayerID'} . $inline ); # Re-assign for next pass $olayer = $mres->{'LayerLevel'}; } while ($mres = $msth->fetchrow_hashref()); # Close up properly # Assign $count = $olayer; # Look until the end while ($count > 0) { # Generate spacer $spacer = ' ' x ($count-1); # Move down a level $map .= $spacer . $gal->{'TagMapStepDown'} . "\n"; # Decrement $count--; } } # End query if defined $msth->finish() if (defined($msth)); # Irrelevant if there are no layers # Generate template $works = $tmpl->Pass('TmplMap', LSTMAP => $map, MROOT => $gres->{'GalleryName'}, LROOT => $link . $inline ); # Generate introduction # Gallery type if ($gres->{'GalleryType'} eq 'image') { # Image galleries # Paste the introductions first $intro = $tmpl->Pass('TmplImageIntro', MDESCR => $gres->{'GalleryDescription'}, MHLIGHT => $gres->{'GalleryHighlight'}, MTHUMB => $gres->{'GalleryThumbnail'}, MGENRE => $genres, MAUTHOR => $authors, MRATING => $gres->{'GalleryRating'}, MTITLE => $gres->{'GalleryName'}, MCREATED => $gres->{'GalleryCreated'}, MUPDATED => $gres->{'GalleryUpdated'}, MWATCH => $watch ); } # Text based galleries else { # Text galleries $intro = $tmpl->Pass('TmplTextIntro', MDESCR => $gres->{'GalleryDescription'}, MGENRE => $genres, MAUTHOR => $authors, MRATING => $gres->{'GalleryRating'}, MTITLE => $gres->{'GalleryName'}, MCREATED => $gres->{'GalleryCreated'}, MUPDATED => $gres->{'GalleryUpdated'}, MWATCH => $watch ); } # Display final work # Use all of the toys $tmpl->Show('TmplListingSec', MINTRO => $intro, LSTWORKS => $works, MNAV => '', MMAP => '' ); } # End query if defined $gsth->finish() if (defined($gsth)); } ##################### # 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 $res; # Work results my $statement; # Work query statement my $words; # Words handler my $length; # Length of string my $offset; # Where to begin my $total; # Total amount of entries my $where; # Where clause my $url; # Base URL my $link; # Self-referencing link my $inline; # Inline parameters my $descr; # Description my $layer; # LayerID my $newness; # Newness factor my $page; # Page number my $text; # Text type my $window; # Window to open to my $genre; # Genre sort my $sub; # Sub-types my $type; # Search type my $sgnre; # Search genre my $ssmbt; # Submit my $stext; # Text handler my $list; # List of works my $body; # Search results body my $search; # Search bar my $nav; # Navigational bar my @genre; # Option for genres my @sub; # Sub genres my @type; # Gallery Types ##################### # Data members # Genres list # Pull genre lists $database->GetList(\@type, "SELECT GenreName || '/' FROM Genre WHERE GenreSub='' AND GenreType IN ('image','text')"); # Sub-genres $database->GetList(\@sub, "SELECT GenreSub || '/' || GenreName FROM Genre WHERE GenreSub != ''"); # Merge push(@genre, sort(@type, @sub)); # Generate widgets # Pupup menu $sgnre = $cgi->popup_menu('SGNRE', \@genre, $param->{'SGNRE'}); # Submit and submit text field $ssmbt = $cgi->submit($gal->{'TxtSearch'}); $stext = $cgi->textfield('STEXT', $param->{'STEXT'}, 25, 75); # Searching template $search = $tmpl->Pass('TmplSearchForm', WGENRE => $sgnre, WSEARCH => $ssmbt, WTEXT => $stext ); # Need exists if (length($param->{'STEXT'}) > 2) { # Determine position $sparam->{'POS'} = ($sparam->{'GAL'} =~ /\d+/) ? $sparam->{'GAL'} : 1; # Pull text $text = $param->{'STEXT'}; # Generate query base # Create new instance $words = new Ethereal::Words(); # Determine where statement $where = $words->Query($text); # Type and sub-types ($type, $genre) = split(/\//, $param->{'SGNRE'}); # Ensure definition $genre = ((defined($genre)) && (length($genre) > 2)) ? "GenreSub=\'$type\' AND GenreName=\'$genre\'" : "GenreSub=\'$type\'"; # Fetching of necessary information # Need weights $database->Write("SELECT GalleryID AS GalleryID, WorkID AS WorkID, SUM(IndexScore) AS IndexScore, COUNT(IndexScore) AS IndexMatches INTO TEMP Weight FROM Index WHERE IndexWord IN ($where) AND EXISTS (SELECT GalleryID FROM GalleryGenre WHERE $genre AND GalleryGenre.GalleryID=Index.GalleryID) GROUP BY WorkID, GalleryID LIMIT $gal->{SetMax}"); # Pull total ($total) = $database->DataGet("SELECT COUNT(*) FROM Weight"); # Run based on a temp table # Prepare query if ($total > 0) { # Navigational # Self referencing link $url = $database->{'SYS'}{'LnkIntGallery'}. '/search'; $inline = (defined($param->{'USER'})) ? $param->EmbedInline($param->Flat()) : $param->Crypt($param->Flat()); # Generate template $nav = Navigation( $tmpl, $gal, $gal->{'SetRetrieve'}, $total, $sparam->{'POS'}, $url, $inline ); # Calculate offset $offset = ($sparam->{'POS'} - 1) * $gal->{'SetRetrieve'}; # Type and sub-types ($type, $genre) = split(/\//, $param->{'SGNRE'}); # This has enough info for a direct query if (length($genre) > 2) { # Fetch direct match ($type, $sub, $genre) = $database->DataGet("SELECT GenreType, GenreSub, GenreName FROM Genre WHERE GenreSub=? AND GenreName=?", $type, $genre); } # Make use of temp table # Pull full list $database->Pull(\$statement, "SELECT wrk.GalleryID AS \"GalleryID\", wrk.WorkID AS \"WorkID\", wrk.WorkName AS \"WorkName\", wrk.WorkLayer AS \"WorkLayer\", wrk.WorkDescription AS \"WorkDescription\", wrk.WorkRating AS \"WorkRating\", wrk.WorkImage AS \"WorkImage\", wrk.WorkImageSize AS \"WorkImageSize\", wrk.WorkImageWidth AS \"WorkImageWidth\", wrk.WorkImageHeight AS \"WorkImageHeight\", wrk.WorkImageThumbnail AS \"WorkImageThumbnail\", wrk.WorkText AS \"WorkText\", getDate(wrk.WorkTimestamp) AS \"WorkTimestamp\", getNew(wrk.WorkTimestamp) AS \"WorkNewness\" FROM Work wrk INNER JOIN Weight wgt ON wrk.GalleryID=wgt.GalleryID AND wrk.WorkID=wgt.WorkID ORDER BY wgt.IndexMatches, wgt.IndexScore LIMIT $gal->{SetRetrieve} OFFSET $offset"); # Pull all records if ($res = $statement->fetchrow_hashref()) { # Adjustment # Self referencing link $url = $database->{'SYS'}{'LnkIntGallery'}; # Inline parameters $inline = (defined($param->{'USER'})) ? $param->EmbedInline( USER=>$param->{'USER'}, CRYPT=>$param->{'CRYPT'}) : ''; # Loop through do { # Last ditch genre find ($type, $sub, $genre) = $database->DataGet("SELECT GenreType, GenreSub, GenreName FROM GalleryGenre WHERE GalleryID=?", $res->{'GalleryID'} ) unless (defined($sub)); # Determine newness $newness = ($res->{'WorkNewness'} != 0) ? $gal->{'TagNewness'} : ''; # Handle layers $layer = (defined($res->{'WorkLayer'})) ? $res->{'WorkLayer'} : 0; # Specific link adjustment $link = $url . '/' . $type . '/' . $sub . '/' . $genre . '/' . $res->{'GalleryID'} . '/' . $layer . '/' . $res->{'WorkID'}; # Window generation $window = 'WIN' . $res->{'GalleryID'} . 'x' . $res->{'WorkLayer'}; # Display # Image gallery if ($res->{'GenreType'} eq 'image') { # Display $list .= $tmpl->Pass('TmplImageList', MNAME => $res->{'WorkName'}, MDESCR => $res->{'WorkDescription'}, MIMAGE => $res->{'WorkImageThumbnail'}, MLINK => $link . $inline, MRATING => $res->{'WorkRating'}, MSIZE => $res->{'WorkImageSize'}, MWIDTH => $res->{'WorkImageWidth'}, MHEIGHT => $res->{'WorkImageHeight'}, MTHUMB => $database->{'SYS'}{'SetThumbnail'}, MUPDATED => $res->{'WorkTimestamp'}, MNEWNESS => $newness, MWINDOW => $window ); } # Text gallery else { # Description $descr = (defined($res->{'WorkDescription'})) ? $res->{'WorkDescription'} : substr(DBI::neat($res->{'WorkText'}, 252), 1, -1); # Length $length = length($res->{'WorkText'}); # Display information $list .= $tmpl->Pass('TmplTextList', MNAME => $res->{'WorkName'}, MDESCR => $descr, MLENGTH => $length, MLINK => $link .$inline, MRATING => $res->{'WorkRating'}, MUPDATED => $res->{'WorkTimestamp'}, MNEWNESS => $newness, MWINDOW => $window ); } } while ($res = $statement->fetchrow_hashref()); # Compose body $body = $tmpl->Pass('TmplSearchBody', MNAV => $nav, LSTWORKS => $list ); } else { # No results $body = $tmpl->Pass('TmplSearchNotice', MMESSAGE=>$gal->{'MsgSrchResults'} ); } # End execution $statement->finish(); } else { # Error in execution $body = $tmpl->Pass('TmplSearchNotice', MMESSAGE=>$gal->{'MsgSrchResults'} ); } # Commit changes # Ensures that things drop $database->Write("DROP TABLE Weight"); $database->Commit(); } # Dsplay to user # Forms print $cgi->start_form(-action=>$database->{'SYS'}{'LnkIntGallery'} . '/search'); print $cgi->hidden('SNEW', 'True'), "\n"; print $param->EmbedNormal($param->Flat()) if (defined($param->{'USER'})); # Display $tmpl->Show('TmplSearch', MBODY => $body, MSEARCH => $search ); # End form print $cgi->end_form(), "\n"; }