#!/usr/bin/perl ################################################################################ # Created : Martin Foster # Modified : 17/03/2003 ################################################################################ # # Portal - Script part of Ethereal Realms designed to authenthicate and and # lead them to realms # 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 Digest::MD5 qw(md5_hex); # MD5 digest cryptographic algorithm use strict; # Strict variable enforcement use Ethereal::Database; # Database handler use Ethereal::Login; # Login functionality use Ethereal::Param; # Parameter control use Ethereal::Table; # Table handler use Ethereal::Template; # Template handler use Ethereal::Weather; # Weather handler use Ethereal::Who; # Who is on ################################################################################ # 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 $scriptname; # Simply the script name my $scriptpara; # Scripted parameters my %portal; # Portal hash ################################################################################ # 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->GetHashPortal(\%portal); # Initial hash $tmpl = new Ethereal::Template(\%portal); # Pull script name $scriptname = $cgi->url(-relative=>1); # Regular operation unless ($scriptname =~ /^static/si) { # Document header print $cgi->header(); $database->DocumentGetHeader(); # Login and template instance $login = new Ethereal::Login($database, $cgi, $param); # Authenthication if ($login->GetVerificationNormal()) { # Quick launch if ($scriptname =~ /^go/si) { # Pull script name $scriptname = $cgi->url(-full=>1); $scriptpara = $cgi->url(-path_info=>1); # Determine need # Escape $scriptname = quotemeta($scriptname); # Truncate $scriptpara =~ s/^$scriptname\///; $scriptpara =~ s/\/$//; # Warp config # Need exists if (length($scriptpara) > 3) { # Unescape $scriptpara = $cgi->unescape($scriptpara); # Parameter assignment $param->{'ROOM'} = $scriptpara; $param->{'THIRDCHAPTER'} = 'True'; } } # If undefined list realms, puppets and links unless (defined($param->{'THIRDCHAPTER'})) { SecondChapter($database, $cgi, $param, $tmpl, \%portal); } # Otherwise open gateway elsif (defined($param->{'THIRDCHAPTER'})) { ThirdChapter($database, $cgi, $param, $tmpl, \%portal); } } # Document footer $database->DocumentGetFooter(); } # Static/Non Interactive/SSI handler else { # Pointless but needed print "
\n\n"; # Call for operation DescriptionStatic($database, $cgi, $tmpl, \%portal); } ################################################################################ # Sub-Routines ################################################################################ ##################### # Description Handler # # If javascript is enabled, this function will be called. Once that is done # the necessary components will be filled in as to allow for use of the # javascript descriptions/ sub DescriptionHandler { ##################### # Data members my $database = shift; # Database handle my $js = shift; # Javascript aware ##################### # Program Area # Only if necessary if ($js = 'yes') { ##################### # Local data members my $data = $database->{'HANDLE'}; # Direct handle my $res; # Query results my $statement; # Query statements my $macro =''; # Generate macro replacement my $descr; # Description # Retreive results # Description $descr = $database->DocumentGetDescription(); # Realms and descriptions $statement = $data->prepare("SELECT RealmName, RealmDescription, RealmGenre, RealmRating FROM Realm WHERE (RealmPublic='yes' OR RealmVerified='yes') AND RealmDescription IS NOT NULL"); $statement->execute(); # Loop and generate while ($res = $statement->fetchrow_hashref()) { # Append to macro $macro = "$macro\tcase \"$res->{RealmName}\":\n\t" . " mes='$res->{RealmDescription}'\;\n\t" . " rat='$res->{RealmRating}'\;\n\t" . " gre='$res->{RealmGenre}'\;\n\t" . " break\;\n"; } # Complete query $statement->finish(); # Replace macro $descr =~ s/MDESCRCASE/$macro/gs; # Display print "$descr\n\n"; } } ##################### # Description Static # # A variant of the above with purpose of displaying this to mostly # static pages. Meaning being used in Server Side Includes (SSI) # et cetera. sub DescriptionStatic { ##################### # Data members my $database = shift; # Database handle my $cgi = shift; # Common Gateway Interface my $tmpl = shift; # Template handler my $portal = shift; # Portal handler my $data = $database->{'HANDLE'}; # Direct handle my $res; # Query results my $statement; # Query statements my $table; # Table handler my $escape; # Escaped title my $genre; # Current genre my $title; # Displayed title my $url; # Quick access link my @genres; # List of genres ##################### # Program Area # Define instance $table = new Ethereal::Table($cgi); # Genres # Pull values $database->GetList(\@genres, "SELECT RealmGenre FROM Realm WHERE (RealmPublic=? OR RealmVerified=?) GROUP BY RealmGenre ORDER BY RealmGenre", 'yes', 'yes'); # Push push(@genres, $portal->{'TxtGlobal'}); # Generate nav links QuickLink($cgi, $tmpl, \@genres); # Clear value $genre = $genres[0]; # Realm specific # Retreive results # Realms and descriptions $statement = $data->prepare("SELECT RealmName, RealmHomepage, RealmDescription, RealmGenre, RealmRating FROM Realm WHERE RealmPublic <> ? AND RealmDescription IS NOT NULL AND RealmHomepage IS NOT NULL ORDER BY RealmGenre, RealmName"); $statement->execute('no'); # Title for first genre # Escape $escape = $cgi->escape($genre); # Title $tmpl->Show('TmplGenre', MTITLE => $genre, MANCHOR => "NAME=\"$escape\"" ); # Table top $table->MakeTop("98%"); # Loop and generate while ($res = $statement->fetchrow_hashref()) { # Genre handling if ($genre ne $res->{'RealmGenre'}) { # Assign and escape $genre = $res->{'RealmGenre'}; $escape = $cgi->escape($genre); # Spacer $table->MakeBottom(); # Quick nav QuickLink($cgi, $tmpl, \@genres, $genre); # Title $tmpl->Show('TmplGenre', MTITLE => $genre, MANCHOR => "NAME=\"$escape\"" ); # Start anew $table->MakeTop("98%"); } # Main generation # Generate link $url = $cgi->escape($res->{'RealmName'}); $url = $portal->{'LnkQuickLink'} . "/" . $url; # Information and spacer $table->MakeSingle( $tmpl->Pass('TmplStatic', MHOME => $res->{'RealmHomepage'}, MLINK => $url, MRATING => $res->{'RealmRating'}, MTITLE => $res->{'RealmName'} ) ); $table->MakeSingle("

$res->{RealmDescription}

"); $table->MakeBlank(); } # Table bottom $table->MakeBottom(); # Global list # Retreive results # Realms and descriptions $statement = $data->prepare("SELECT RealmName, RealmHomepage, RealmDescription, RealmRating FROM Realm WHERE RealmPublic <> ? AND RealmDescription IS NOT NULL AND RealmHomepage IS NOT NULL ORDER BY RealmName"); $statement->execute('no'); # Quick nav QuickLink($cgi, $tmpl, \@genres, $portal->{'TxtGlobal'}); # Title for first genre # Escape $escape = $cgi->escape($portal->{'TxtGlobal'}); # Title $tmpl->Show('TmplGenre', MTITLE => $portal->{'TxtGlobal'}, MANCHOR => "NAME=\"$escape\"" ); # Table top $table->MakeTop("98%"); # Loop and generate while ($res = $statement->fetchrow_hashref()) { # Main generation # Generate link $url = $cgi->escape($res->{'RealmName'}); $url = $portal->{'LnkQuickLink'} . "/" . $url; # Information and spacer $table->MakeSingle( $tmpl->Pass('TmplStatic', MHOME => $res->{'RealmHomepage'}, MLINK => $url, MRATING => $res->{'RealmRating'}, MTITLE => $res->{'RealmName'} ) ); $table->MakeSingle("

$res->{RealmDescription}

"); $table->MakeBlank(); } # Table bottom $table->MakeBottom(); # Generate nav links QuickLink($cgi, $tmpl, \@genres); } ##################### # Quick Link # # Dirt simple and is used simply to clean up the static pages list of elements # allowing for quick navigation. sub QuickLink { ##################### # Data members my $cgi = shift; # CGI handle my $tmpl = shift; # Template handle my $array = shift; # Referenced array my $exclude = shift; # Exclusion my $escape; # Escaped name my $genre; # Genre ##################### # Program area # Pre-Display print "
"; # Loop and display foreach $genre (@{$array}) { unless ((defined($exclude)) && ($genre eq $exclude)) { # Escape link $escape = $cgi->escape($genre); # Simply display from a format $tmpl->Show('TagLnkGen', 'MTITLE', "$genre", 'MLINK', "HREF=\"\#$escape\"" ); } } # Post print "
\n\n"; # Spacer print "
\n"; } ##################### # Second Chapter # # Unusual name given to a part of the script that will be exected once the user # has been authenthicated. sub SecondChapter { ##################### # Data members my $database = shift; # Database handle my $cgi = shift; # CGI handle my $param = shift; # Parameter list my $tmpl = shift; # Template handler my $portal = shift; # Portal hash my $table = new Ethereal::Table($cgi); # Table handler my $who; # Who is on handle my $def_pup; # Default puppet my $def_realm; # Default realm my $inline; # Inline embeding of data my $mail; # Mail count my $news; # News entries my $puppets; # Formatted list of puppets my $realms; # Formatted list of realms my $title; # Title for user my $url; # Self referencing link my $sup; # Supervisory my $adm; # Administrative my $mod; # Moderators my $ver; # Verified users my $js; # Javascript control my $jscode; # Javascript code my @realms; # List of realms my @puppets; # List of puppets my @ver; # Verified realms ##################### # Program area # Retreive URL $url = $cgi->url(-absolute=>1); # Who is on handle $who = new Ethereal::Who($database, $cgi, $param); # Javascript Options # Retreive Javascript choice ($js) = $database->DataGetJavascript($param->{'USER'}); # Possibly display Javascript if ($js eq 'yes') { # Display header $database->DocumentGetJavascript(); } # Generate javascript code $jscode = ($js eq 'yes') ? "ONCLICK='window.open(this.href,this.target,settings); return false'" : ''; # Retreive puppet default ($def_pup, $def_realm) = $database->DataGetDefault($param->{'USER'}); # Retreive numbers ($mail) = $database->DataGetPuppeteerMailCount($param->{'USER'}); ($news) = $database->DataGetWeblogEntries(); # Determine priviliges ($sup, $adm, $mod, $ver) = $database->DataGetPrivs($param->{'USER'}); # Retreive and format values for Realms and Puppets $database->GetListPublicRealms(\@realms); $database->GetListPuppetYours(\@puppets, $param->{'USER'}); # Verified realms if ($ver eq 'yes') { # Pull list $database->GetListVerifiedRealms(\@ver); # Append and sort @realms = sort(@realms, @ver); } # Final mangling $who->Portal(\@realms, \$def_realm); # Widget handling # Puppets $puppets = $cgi->scrolling_list('CHAR', \@puppets, $def_pup, 5); # Realms if ($js eq 'yes') { # Javascript aware $realms = $cgi->scrolling_list( -name=>'ROOM', -values=>\@realms, -default=>$def_realm, -size=>10, -onchange=>'createContent()' ); } else { # Ignorant of javascript # To avoid any error messages $realms = $cgi->scrolling_list( -name=>'ROOM', -values=>\@realms, -default=>$def_realm, -size=>10 ); } # Create inline link $inline = $param->EmbedInline($param->Flat()); # Display of information # Table top print "
\n", "\n", " \n", " \n", " \n", " \n", "
\n"; # Only display if puppets exist if (defined($def_pup)) { # Realm Section # Start form print $cgi->start_form(-NAME=>'PORTAL'); print $param->EmbedNormal($param->Flat(), 'THIRDCHAPTER', 'true'), "\n"; # Table top $table->MakeTop(400); $table->MakeSingle($tmpl->PassTitle($portal->{'TagSecRealm'})); $table->MakeSingle( $tmpl->Pass('TagLnkGlobalWho', 'MLINK', "$portal->{LnkGlobalWho}$inline", 'JSCODE', $jscode ) ); $table->MakeBlank(); $table->MakeValid($tmpl->PassSub($portal->{'TagSelectPuppet'}), $puppets); $table->MakeBlank(); $table->MakeValid($tmpl->PassSub($portal->{'TagSelectRealm'}), $realms); $table->MakeBlank(); $table->MakeValid($tmpl->PassSub($portal->{'TagSelectPrivate'}), $cgi->textfield('ALTROOM', '', 20, 30)); $table->MakeBlank(); $table->MakeValid($cgi->submit($portal->{'TxtSubmitRealms'}), $cgi->reset($portal->{'TxtResetRealms'})); $table->MakeBottom(); # End form print $cgi->end_form(), "\n"; # Spacer print "
\n"; # Show descriptions DescriptionHandler($database, $js); # Spacer print "
\n"; } # Row bottom print "
\n"; # Links # Puppeteer Section # Title $tmpl->Show('TmplSideTop', 'MTITLE', $portal->{'TagSecPuppeteer'}); # Puppteer configuration $tmpl->Show('TmplSideMid', 'MLINK', "$portal->{LnkPuppeteer}$inline", 'JSCODE', $jscode, 'MTITLE', $portal->{'TagLnkPuppeteer'} ); # Puppet configuration $tmpl->Show('TmplSideMid', 'MLINK', "$portal->{LnkPuppet}$inline", 'JSCODE', $jscode, 'MTITLE', $portal->{'TagLnkPuppet'} ); # Gallery page administration $tmpl->Show('TmplSideMid', 'MLINK', "$portal->{LnkGallery}$inline", 'JSCODE', $jscode, 'MTITLE', $portal->{'TagLnkGallery'} ); # Home page administration $tmpl->Show('TmplSideMid', 'MLINK', "$portal->{LnkHome}$inline", 'JSCODE', $jscode, 'MTITLE', $portal->{'TagLnkHome'} ); # Cookie administration $tmpl->Show('TmplSideMid', 'MLINK', "$portal->{LnkCookie}$inline", 'JSCODE', $jscode, 'MTITLE', $portal->{'TagLnkCookie'} ); # Bottom $tmpl->Show('TmplSideBottom'); # Community # Title $tmpl->Show('TmplSideTop', 'MTITLE', $portal->{'TagSecCommunity'}); # Gallery Viewer $tmpl->Show('TmplSideMid', 'MLINK', "$portal->{LnkViewer}$inline", 'JSCODE', '', 'MTITLE', $portal->{'TagLnkViewer'} ); # Gallery Search $tmpl->Show('TmplSideMid', 'MLINK', "$portal->{LnkSearch}$inline", 'JSCODE', '', 'MTITLE', $portal->{'TagLnkSearch'} ); # System message boards $tmpl->Show('TmplSideMid', 'MLINK', "$portal->{LnkSysboard}$inline", 'JSCODE', $jscode, 'MTITLE', $portal->{'TagLnkSysboard'} ); # Bottom $tmpl->Show('TmplSideBottom'); # Messaging # Title $tmpl->Show('TmplSideTop', 'MTITLE', $portal->{'TagSecMessage'}); # Internal Mail $tmpl->Show('TmplSideMid', 'MLINK', "$portal->{LnkMail}$inline", 'JSCODE', $jscode, 'MTITLE', "$portal->{TagLnkMail} ($mail)" ); # Message boards $tmpl->Show('TmplSideMid', 'MLINK', "$portal->{LnkBoard}$inline", 'JSCODE', $jscode, 'MTITLE', $portal->{'TagLnkBoard'} ); # Weblog $tmpl->Show('TmplSideMid', 'MLINK', "$portal->{LnkWeblog}", 'JSCODE', $jscode, 'MTITLE', "$portal->{TagLnkWeblog} ($news)" ); # Bottom $tmpl->Show('TmplSideBottom'); # Administrative area if ($adm eq 'yes') { # Generate # Title $tmpl->Show('TmplSideTop', 'MTITLE', $portal->{'TagSecAdmin'}); # System administration script $tmpl->Show('TmplSideMid', 'MLINK', "$portal->{LnkAdmSystem}$inline", 'JSCODE', '', 'MTITLE', $portal->{'TagLnkAdmSystem'} ); # System who $tmpl->Show('TmplSideMid', 'MLINK', "$portal->{LnkAdmWho}$inline", 'JSCODE', '', 'MTITLE', $portal->{'TagLnkAdmWho'} ); # Bottom $tmpl->Show('TmplSideBottom'); } # Supervisory Area if (($sup eq 'yes') || ($mod eq 'yes')) { # Determine title $title = ($sup eq 'yes') ? $portal->{'TagSecSuper'} : $portal->{'TagSecMod'}; # Generate # Title $tmpl->Show('TmplSideTop', 'MTITLE', $title); # Control Panel $tmpl->Show('TmplSideMid', 'MLINK', "$portal->{LnkRealm}$inline", 'JSCODE', $jscode, 'MTITLE', $portal->{'TagLnkSupervisor'} ); # Bottom $tmpl->Show('TmplSideBottom'); } # Additional HTML # For adds et cetera $tmpl->Show('TmplAdditional'); # End table print "
\n", "
\n"; } ##################### # Third Chapter # # Unusual name given to a part of the script that will be exected once the user # in his infinit wisdom has selected a puppet and realm sub ThirdChapter { ##################### # Data members my $database = shift; # Database handle my $cgi = shift; # CGI handle my $param = shift; # Parameter list my $tmpl = shift; # Template handler my $portal = shift; # Portal hash my $data = $database->{'HANDLE'}; # Database connection handler my $who; # Who is on handle my $access; # Access control my $alias; # Room alias my $room; # Room name my $info; # Room information my $pub; # Public status my $rand; # Random password my $status; # Room status my $ver; # Verified requirement ##################### # Program area # Cleanup delete $param->{'THIRDCHAPTER'}; # Determine need to create a room if (defined($param->{'ALTROOM'}) && (length(($param->{'ALTROOM'})) > 2)) { # Existence of password if ($param->{'ALTROOM'} =~ /@/) { # Seperate into password and realm ($param->{'RPASS'}, $param->{'ALTROOM'}) = split(/@/, $param->{'ALTROOM'}); # Meets length requirements $param->{'ROOM'} = (length(($param->{'ALTROOM'})) > 2) ? $param->{'ALTROOM'} : $param->{'ROOM'}; } # Default else { # Assign ROOM $param->{'ROOM'} = $param->{'ALTROOM'}; } # Retreive query information ($room, $status, $alias) = $database->DataGetRealmExistence($param->{'ROOM'}); # Create if not found unless (defined($room)) { # Handle realm password if ((defined($param->{'RPASS'})) && (length($param->{'RPASS'}) > 2)) { # Generate password $rand = md5_hex(rand()); $rand = substr($rand, 0, 14); # Generated encrypted password $param->{'RCRYPT'} = crypt($param->{'RPASS'}, $rand); # Cleanup $param->Cleanup('RPASS'); } else { # Undefine parameter $param->{'RCRYPT'} = undef; } # Realm creation $data->do("INSERT INTO Realm (RealmName, RealmPassword, RealmImageHeight, RealmImageWidth, RealmImageSize, RealmTimestamp) VALUES(?,?,0,0,0,?)", {}, $param->{'ROOM'}, $param->{'RCRYPT'}, time); } # Realm exists else { # Handle alias $room = ($status eq 'alias') ? $alias : $room; # Consistent naming $param->{'ROOM'} = $room; } } # Remove number information $param->{'ROOM'} =~ s/ \(\d+\)$//s; # Access control ($access) = $database->DataGetRealmAccess($param->{'ROOM'}); # Ensure puppet is defined if (($access eq 'restricted') or (!defined($param->{'CHAR'}))) { # Retreive default puppet ($param->{'CHAR'}) = $database->DataGetDefault($param->{'USER'}, $param->{'ROOM'}, $access); } # Retreive realm information ($info) = $database->DataGetRealmDescription($param->{'ROOM'}); ($pub, $ver) = $database->DataGetRealmPublic($param->{'ROOM'}); # Update default realm if (($pub eq 'yes') || ($ver eq 'yes')) { # Update default realm if public or adult $data->do("UPDATE Puppeteer SET PuppeteerRealm=? WHERE PuppeteerLogin=?", {}, $param->{'ROOM'}, $param->{'USER'}); } # who is on handles $who = new Ethereal::Who($database, $cgi, $param); # Wrap with tables if (defined($info)) { # Wrap with tables print "\n", " \n", " \n", " \n", " \n", "
"; # Retreive realm information $tmpl->ShowSub($param->{'ROOM'}); $who->WhoEntrance(); # Warn before entering $database->DocumentGetCanon() if ($access eq 'restricted'); # Weather forcast WeatherHandler($database, $cgi, $param, $tmpl, $portal); # Mid section print " "; # Splash page print "$info\n"; # Hind quarter print "\n
"; } # Simply display else { # Retreive realm information $tmpl->ShowSub($param->{'ROOM'}); $who->WhoEntrance(); # Warn before entering $database->DocumentGetCanon() if ($access eq 'restricted'); # Weather forcast WeatherHandler($database, $cgi, $param, $portal); } } ##################### # Weather Handler # # The weather heandler is realm specific for which is it not listed on the # module directly. This will essentially show off the specific weather # patterns for the realm if found sub WeatherHandler { ##################### # Data members my $database = shift; # Database handle my $cgi = shift; # CGI handle my $param = shift; # Parameter list my $tmpl = shift; # Template my $portal = shift; # Portal handle my $table = new Ethereal::Table($cgi); # Table handle my $for; # Forcast handle my $metar; # Coded weather forcast my $cond; # Weather conditions my $sky; # Sky conditions my %cond; # Specific conditions ##################### # Program area # Retreive forcast ($metar) = $database->DataGetWeather($param->{'ROOM'}); # Only complete if forcast if (defined($metar)) { # Initialize handle $for = new Ethereal::Weather(); # Parse $for->Parse($metar, \%cond); # Forcast handling $sky = lc(join(", ", @{$cond{SKY}})); $cond = lc(join(", ", @{$cond{HUMAN}})); # Conditions $cond = (length($cond) > 2) ? ucfirst("$cond, $sky") : ucfirst("$sky"); $cond =~ s/,([^,.]+?)$/ and $1/s; # Title print "
\n"; $tmpl->ShowSub($portal->{'TagForcastTitle'}); # Display area $table->MakeTop("100%"); $table->MakeSingle("$portal->{TagForcastCond}
$cond"); # Wind if ($cond{WIND_MPH} != 0) { $table->MakeSingle("$portal->{TagForcastWind}
$cond{WIND_DIR_ENG} at $cond{WIND_KPH} KPH - $cond{WIND_MPH} MPH"); } # Temperature if ($cond{F_TEMP} != 0) { $table->MakeSingle("$portal->{TagForcastTemp}
$cond{C_TEMP}°C - $cond{F_TEMP}°F" ); } # Dew points if ($cond{F_DEW} != 0) { $table->MakeSingle("$portal->{TagForcastDew}
$cond{C_DEW}°C - $cond{F_DEW}°F"); } # Visibility if ($cond{VIS_MILE} != 0) { $table->MakeSingle("$portal->{TagForcastVis}
$cond{VIS_KILO} Km - $cond{VIS_MILE} Mi"); } # Barometer if ($cond{ALTI} != 0) { $table->MakeSingle("$portal->{TagForcastBaro}
$cond{ALTI} Inches - $cond{ALTK} Kilopascals"); } # Table bottom $table->MakeBottom(); } }