#!/usr/bin/perl ################################################################################ # Created : Martin Foster # Modified : 27/01/2003 ################################################################################ # # Board - Messages/discussion board functionality for Ethereal 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 ST NE # Calgary, Alberta # T2E 3W9 # ################################################################################ use CGI qw(:standard); # Common gateway interface use CGI::Carp qw(fatalsToBrowser); # CGI Error logs use Text::Wrap; # Text wrapping functionality use strict; # Strict variable enforcement use Ethereal::Audit; # Auditing handler use Ethereal::Database; # Database handler use Ethereal::Date; # Date processing use Ethereal::Filter; # Filter processing use Ethereal::Login; # Login functionality use Ethereal::Mail; # Mail handler use Ethereal::Param; # Parameter control use Ethereal::Table; # Table creation use Ethereal::Template; # Template handler ################################################################################ # Data Members ################################################################################ my $cgi; # Common gateway interface handle my $database; # Database handle my $login; # Login handle my $param; # Parameter handle my $tmpl; # Template my $ban; # Banned status my $sname; # Script name my $sparam; # Script parameter my %board; # Board hash my %system; # System 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(); # Retreive hash $database->GetHashBoard(\%board); $database->GetHashSystem(\%system); # Login handle $login = new Ethereal::Login($database, $cgi, $param); $tmpl = new Ethereal::Template(\%board); # Alternate addressing # Pull addresses $sname = $cgi->url(-full=>1); $sparam = $cgi->url(-path_info=>1); # Escape characters $sname = quotemeta($sname); # Needed addition $sparam = ($sparam =~ /\/$/) ? $sparam : "$sparam/"; # Truncate $sparam =~ s/^$sname\///; $sparam =~ s/\/$//; # Warp config if ((length($sparam) > 3) && ($sparam ne 'system')) { # Unescape $sparam = $cgi->unescape($sparam); # Retrieve information my ($realm, $public, $alias) = $database->DataGetRealmExistence($sparam); # Only if needed if ((defined($realm)) && (!defined($alias)) && (($public eq 'yes') || ($public eq 'hybrid'))) { # Set realm name to whatever was specified $param->{'ROOM'} = $realm; } } elsif ((length($sparam) > 3) && ($sparam eq 'system')) { # Set room name to system default $param->{'ROOM'} = $system{'SetBoardAlias'}; } # Handle headers HandleAlternate($database, $cgi, $param); # Document header $database->DocumentGetHeader(); # Determin need to select a realm if (RealmSelect($database, $cgi, $param, $tmpl, \%board)) { # Logic handling # Writer PostWrite($database, $login, $cgi, $param, \%board, \%system) if (defined($param->{'WRITE'})); # Removal PostPurge($database, $login, $cgi, $param) if (defined($param->{'PURGE'})); # Composer if ((defined($param->{'REPLY'})) || (defined($param->{'POST'}))) { # Composition PostComposer($database, $login, $cgi, $param, $tmpl, \%board); } # Posts viewer (default) elsif (!defined($param->{'PASSGO'})) { # Adjust title # Standard behaviour if ($param->{'ROOM'} !~ $system{'SetBoardName'}) { # Display realm name $tmpl->Show('TmplHead', MTITLE => $param->{'ROOM'}, MTOPIC => ucfirst($param->{'TOPIC'}) ); } # System board else { # Display system specific name $tmpl->Show('TmplHead', MTITLE => $system{'SetBoardName'}, MTOPIC => ucfirst($param->{'TOPIC'}) ); } # Handling of viewing PostView($database, $cgi, $param, \%board, \%system); } } # Document footer $database->DocumentGetFooter(); ################################################################################# # Sub-Routines ################################################################################# ##################### # Handle Alternates # # Will handle how alternate boards are displayed. Essentially, this will simply # create a redirect header sending it to the alternate board if such a thing # was specified. sub HandleAlternate { ##################### # Data members my $database = shift; # Database handle my $cgi = shift; # CGI handle my $param = shift; # Parameter list my $public; # Public status my $altboard; # Alternate message board ##################### # Program area # Verification of acceptance if (defined($param->{'ROOM'})) { # Retreive public status ($public) = $database->DataGetRealmPublic($param->{'ROOM'}); # Verify existence and nature if ((defined($public)) && ($public ne 'no')) { # Retreive alternate ($altboard) = $database->DataGetRealmAltBoard($param->{'ROOM'}); # Exitence of alternate header if (defined($altboard)) { # Retriect header print $cgi->redirect($altboard); # End script exit; } } # Private or nonexistent else { # Dispose of value $param->Cleanup('ROOM'); } } # Display standard header print $cgi->header(); } ##################### # Realm Selection # # Realms are needed in order to complete operations for the message board. This # is for the primary reason that the board grants one topic area for each specific # realm. Without a public realm, the board topic will not exist. sub RealmSelect { ##################### # Data members my $database = shift; # Database handle my $cgi = shift; # CGI handle my $param = shift; # Parameter list my $tmpl = shift; # Template handler my $board = shift; # Board hash handle my $data = $database->{'HANDLE'}; # Direct handle my $statement; # Query statement my $choice; # Choice of the matter my $count; # Topic counter my $table; # Table handle my $title; # Title to display my $descr; # Description my $posts; # Posts found my $topic; # Topic of discussion my $url; # Self referencing link my $inline; # Inline parameters my $dis; # Display realms my @dis; # Display selection my %topics; # Hash of topics ##################### # Program area # Create instance $table = new Ethereal::Table($cgi); # Handle specifics # Realm selection unless (defined($param->{'ROOM'})) { # Retreive realm list $database->GetListPublicRealms(\@dis); # Generate widget $dis = $cgi->scrolling_list('ROOM', \@dis, $dis[0], 10); # Display # Title $tmpl->ShowMain($board->{'TagRealm'}); # Beginning of form print $cgi->start_form(); print $param->EmbedNormal($param->Flat()) if (defined($param->{'USER'})); # Top title $table->MakeTop(); # Widgets and end $table->MakeValid($dis, $cgi->submit($board->{'TxtSelect'}), 'middle'); $table->MakeBottom(); # End of form print $cgi->end_form(), "\n"; # Return false return 0; } # Topic selection elsif (!defined($param->{'TOPIC'})) { # Retreive number of topics ($count) = $database->DataGet("SELECT COUNT(*) AS Topics FROM BoardTopic WHERE RealmName=?", $param->{'ROOM'}); # If there is a need if ($count > 0) { # Populate hash # Prepare and execute $statement = $data->prepare("SELECT BoardTopic AS Topic, COUNT(BoardTopic) AS 'Posts' FROM Board WHERE RealmName=? GROUP BY BoardTopic ORDER BY BoardTopic"); $statement->execute($param->{'ROOM'}); # Loop and finish while (($topic, $posts) = $statement->fetchrow()) { # Assign hash value $topics{$topic} = $posts; } $statement->finish(); # Display information # Prepare and execute $statement = $data->prepare("SELECT BoardTopic AS Topic, BoardDescription AS Description FROM BoardTopic WHERE RealmName=? ORDER BY BoardTopic"); $statement->execute($param->{'ROOM'}); # Something there if (($topic, $descr) = $statement->fetchrow()) { # Display # Title $tmpl->ShowMain($board->{'TagTopic'}); # Top $table->MakeTop(); # Capture link $url = $cgi->url(-absolute=>1); # Loop and display do { # Generate link $inline = (defined($param->{'USER'})) ? $param->EmbedInline($param->Flat(), TOPIC=>$topic) : $param->Crypt(ROOM=>$param->{ROOM}, TOPIC=>$topic); # Main body # Ensure setting $topics{$topic} = 0 unless (defined($topics{$topic})); # Display row $table->MakeSingle($tmpl->Pass('TmplStatic', MTITLE => $topic, MPOSTS => $topics{$topic}, MLINK => "$url$inline" )); # Description # Ensure setting $descr = $board->{'TxtDescr'} unless (defined($descr)); # Carriage returns $descr =~ s/\n/
/gs; # Display row $table->MakeSingle($descr); $table->MakeBlank(); } while (($topic, $descr) = $statement->fetchrow()); # End $table->MakeBottom(); # Return False return 0; } } # Assign the default parameter $param->{'TOPIC'} = 'system'; } # True if reached return 1; } ##################### # Post Viewer # # The viewing sub-routine for the message board. Of course the specific realm is needed # which is why that this is called after the ROOM is determined. sub PostView { ##################### # Data members my $database = shift; # Database handle my $cgi = shift; # CGI handle my $param = shift; # Parameter list my $board = shift; # Board hash my $system = shift; # System hash my $data = $database->{'HANDLE'}; # Database connection handly my $date; # Time handler my $statement; # Query handle my $res; # Results hash my $dtime = 86400; # Measurement of a day my $time = time; # Time my $stime; # Search time my $left; # Rows left of entry my $space; # Spacing my $right; # Rows for entry my $choice; # Choice of the matter my $user; # Username my $rows = 10; # Complete set of rows my $count = 0; # Rows retreived my $order; # Order to take on my $activity; # Activity based searching my $ibio; # Biographical link my $idirect; # Direct link to post my $inline; # Inline parameter list my $isuper; # Supervisory parameter list my $url = $cgi->url(-absolute=>1); # Self referencing link my %args; # Basic arguments ##################### # Program area # Create instance $date = new Ethereal::Date(); # Logged on specific if (defined($param->{'USER'})) { # Determine supervisory ($choice) = $database->DataGetRoomPrivs($param->{'ROOM'}, $param->{'USER'}); # Base arguments %args = ( USER => $param->{'USER'}, CRYPT => $param->{'CRYPT'}, ); } # Generate parameter lines # Nav variables my ($back, $topc, $post, $actv, $desc, $asc, $day, $week, $mnth, $year); # Back button if (defined($param->{'USER'})) { $back = $param->EmbedInline(%args); } else { $back = ''; } # Add additional arguments $args{'ROOM'} = $param->{'ROOM'}; # Default behaviour if (defined($param->{'USER'})) { $topc = $param->EmbedInline(%args); } else { $topc = $param->Crypt(ROOM=>$param->{'ROOM'}); } # Add topic as argument $args{'TOPIC'} = $param->{'TOPIC'}; # Default search # Activity based search if ((!defined($param->{'ORDER'})) && (!defined($param->{'ACTV'})) && (!defined($param->{'TIME'}))) { # Create to cause default $param->{'ACTV'} = 'True'; } # Maintain directional state $param->{'ORDER'} = (defined($param->{'ORDER'})) ? $param->{'ORDER'} : 'ASC'; # Fucntional # User defined if (defined($param->{'USER'})) { $post = $param->EmbedInline(%args, POST=>'True'); # Activity based $actv = $param->EmbedInline(%args, ACTV=>'True'); # Order $desc = $param->EmbedInline(%args, ORDER=>'DESC'); $asc = $param->EmbedInline(%args, ORDER=>'ASC'); # Append order $args{'ORDER'} = $param->{'ORDER'}; # Time based $day = $param->EmbedInline(%args, TIME=>'1'); $week = $param->EmbedInline(%args, TIME=>'7'); $mnth = $param->EmbedInline(%args, TIME=>'31'); $year = $param->EmbedInline(%args, TIME=>'365'); } # General else { $post = $param->Crypt(%args, POST=>'True'); # Activity based $actv = $param->Crypt(%args, ACTV=>'True'); # Order $desc = $param->Crypt(%args, ORDER=>'DESC'); $asc = $param->Crypt(%args, ORDER=>'ASC'); # Append order $args{'ORDER'} = $param->{'ORDER'}; # Time based $day = $param->Crypt(%args, TIME=>'1'); $week = $param->Crypt(%args, TIME=>'7'); $mnth = $param->Crypt(%args, TIME=>'31'); $year = $param->Crypt(%args, TIME=>'365'); } # Additional searching $stime = (defined($param->{'TIME'})) ? ($time - ($param->{'TIME'} * $dtime)) : 0; $activity = (defined($param->{'ACTV'})) ? 'BoardUpdate DESC,' : ''; # Generate direct link $idirect = $param->Crypt(ROOM=>$param->{'ROOM'}, TOPIC=>$param->{'TOPIC'}); # Prepare and execute $statement = $data->prepare("SELECT BoardIDNumber, PuppetName, BoardSubject, BoardTimestamp, BoardMessage, BoardLevel, LevelZero, LevelOne, LevelTwo, LevelThree, LevelFour, LevelFive FROM Board WHERE RealmName=? AND BoardTopic=? AND BoardUpdate > $stime ORDER BY $activity LevelZero $param->{ORDER}, LevelOne, LevelTwo, LevelThree, LevelFour, LevelFive"); $statement->execute($param->{'ROOM'}, $param->{'TOPIC'}); # HTML Display print "
\n\n
\n"; # Status view if ($param->{'ROOM'} ne $system->{'SetBoardAlias'}) { # Includes a back button print " \n", " \n", " \n"; } else { # Cannot go beyond initial stage print " \n", " \n"; } # Retreive and display while ($res = $statement->fetchrow_hashref()) { # Increment counter $count++; # Biographical links # Retreive puppeteer login ($user) = $database->DataGetPuppeteerLogin($res->{'PuppetName'}); # Inline parameter ($ibio) = $param->Crypt(CHAR=>$res->{'PuppetName'}, USER=>$user); # Determine rows $right = $rows - $res->{'BoardLevel'}; $left = $rows - $right; $space = $left * 50; # Generate parameters if (defined($param->{'USER'})) { # Generate inline $inline = $param->EmbedInline($param->Flat(), REPLY=>$res->{'BoardIDNumber'}); # Supervisory $isuper = $param->EmbedInline($param->Flat(), PURGE=>$res->{'BoardIDNumber'}) if (defined($choice)); } else { # Lesser form of inline $inline = $param->Crypt($param->Flat(), 'REPLY', $res->{'BoardIDNumber'}); } # Header print " \n"; # Handling based on level # Header # Childer if ($res->{'BoardLevel'} != 0) { print " \n"; print " \n"; # Kill button if (defined($isuper)) { # Administrative login print " \n", " \n", " \n", " \n"; } } # Parent else { # Spacer if ($count != 1) { print " \n", " \n", " \n"; } # Actual header print " \n"; # Kill button if (defined($isuper)) { # Administrative login print " \n", " \n", " \n"; } } print " \n"; # Second part # Message print " \n"; # Handling based on level # Children of threads if ($res->{'BoardLevel'} != 0) { print " \n"; print " \n"; } # Threads parent else { print " \n"; } print " \n"; } # Status view if ($param->{'ROOM'} ne $system->{'SetBoardAlias'}) { # Default view print "\t", "\t\t\n", "\t\n"; } else { # System realm print "\t", "\t\t\n"; } # Spacer row print " \n"; for (my $i; $i < $rows; $i++) { print " \n"; } # End of table print " \n
\n", " $board->{TagPost} - \n", " $board->{TagActv} - \n", " $board->{TagAsc} \n", " $board->{TagDesc} - \n", " $board->{TagTimeDay} \n", " $board->{TagTimeWeek} \n", " $board->{TagTimeMonth} \n", " $board->{TagTimeYear} - \n", " $board->{TagSlct} - \n", " $board->{TagBack}
\n", " $board->{TagPost} - \n", " $board->{TagActv} - \n", " $board->{TagAsc} \n", " $board->{TagDesc} - \n", " $board->{TagTimeDay} \n", " $board->{TagTimeWeek} \n", " $board->{TagTimeMonth} \n", " $board->{TagTimeYear} - \n", " $board->{TagSlct}\n", "
 {BoardIDNumber}\">\n", " $board->{TagHeadSubject}$res->{BoardSubject}
$board->{TagHeadFrom}\n", " $res->{PuppetName}\n", " $board->{TagHeadDate} ", $date->GetDate($res->{'BoardTimestamp'}), " ({BoardIDNumber}\" TARGET=\"_new\" CLASS=\"BOARD\">\#$res->{BoardIDNumber})
\n", "
 \n", " $board->{TagKillThread}\n", "
 
{BoardIDNumber}\">\n", " $board->{TagHeadSubject}$res->{BoardSubject}
$board->{TagHeadFrom}\n", " $res->{PuppetName}\n", " $board->{TagHeadDate} ", $date->GetDate($res->{'BoardTimestamp'}), " ({BoardIDNumber}\" TARGET=\"_new\" CLASS=\"BOARD\">\#$res->{BoardIDNumber})
\n", "
\n", " $board->{TagKillThread}\n", "
 \n", " $res->{BoardMessage}
\n", " $board->{TagReply}\n", "
\n", " $res->{BoardMessage}
\n", " $board->{TagReply}\n", "
$board->{TagCount} $count
", "$board->{TagPost} - ", "$board->{TagSlct} - ", "$board->{TagBack}
$board->{TagCount} $count
", "$board->{TagPost} - ", "$board->{TagSlct}", "\t
 
\n"; # Close query handle $statement->finish(); } ##################### # Post Composer # # As the name would imply, this subroutine allows for the addition of posts to the # existing set of posts. Provided that there are posts to reply to, one can # reply under the parent post. sub PostComposer { ##################### # Data members my $database = shift; # Database handle my $login = shift; # Login handler my $cgi = shift; # CGI handle my $param = shift; # Parameter list my $tmpl = shift; # Template handler my $board = shift; # Board hash handle my $acc; # Realm access my $ban; # User banned status my $def; # Default page my $subj; # Subject of message my $table; # Table handle my $puppets; # Prepared output my @puppets; # List of puppets ##################### # Program area # User logged on if ($login->GetVerificationNormal()) { # Determine ban ($acc) = $database->DataGetRealmAccess($param->{'ROOM'}); ($ban) = $database->DataGetBannedStatus($param->{'USER'}, $param->{'ROOM'}); # Default ($def) = $database->DataGetDefault($param->{'USER'}); # Define instance $table = new Ethereal::Table($cgi); # Allow if not banned unless ((defined($ban)) && ($acc eq 'relaxed')) { # Gather information if (defined($param->{'REPLY'})) { # Prepare and execute ($subj) = $database->DataGet("SELECT BoardSubject FROM Board WHERE BoardIDNumber=?", $param->{'REPLY'}); # Adapt subject if ($subj !~ /^\(RE\)/) { $subj =~ s/(.+)/(RE) $1/; } # Assign ID for next pass $param->{'PID'} = $param->{'REPLY'}; } # Cleanup $param->Cleanup('REPLY', 'POST'); # Puppet list # Retreive puppet list $database->GetListPuppetYours(\@puppets, $param->{'USER'}); # Determine puppets $puppets = $cgi->popup_menu('PFROM', \@puppets, $def); # Display area # Display title $tmpl->ShowMain($board->{'TagTitlePost'}); # Start of form print $cgi->start_form(); print $param->EmbedNormal($param->Flat(), 'WRITE', 'True'), "\n"; # Table top $table->MakeTop(); # Header $table->MakeSingle($tmpl->PassTitle($board->{'TagPostHead'})); $table->MakeValid( $tmpl->PassSub($board->{'TagPostFrom'}), $puppets); $table->MakeValid( $tmpl->PassSub($board->{'TagPostSubject'}), $cgi->textfield('PSUBJ', $subj,25,250)); # Body $table->MakeBlank(); $table->MakeSingle($tmpl->PassTitle($board->{'TagPostMessage'})); $table->MakeSingle($cgi->textarea(-name=>'PTEXT',-rows=>10,-columns=>60,-wrap=>'SOFT')); # Submit and clear $table->MakeBlank(); $table->MakeValid($cgi->submit($board->{'TxtPost'}), $cgi->reset($board->{'TxtReset'})); $table->MakeBottom(); # End form print $cgi->end_form(), "\n"; } # Banner users else { # Simple table # Display the news $table->MakeTop(); $table->MakeSingle($board->{'MsgBanned'}); $table->MakeBottom(); } } } ##################### # Post Purge # # Handles the purging or killing of post and any children associated with it. As one can # see this is useful for giving the message board a more youthful look and cleaning out # unwanted material. sub PostPurge { ##################### # Data members my $database = shift; # Database handle my $login = shift; # Login handle my $cgi = shift; # Common gateway interface my $param = shift; # Parameter list my $data = $database->{'HANDLE'}; # Database connection handle my $super; # Supervisory access ##################### # Program Area # Only if login credentials are valid if ($login->GetVerificationNormal()) { # Audit handle my $audit = new Ethereal::Audit($database, $cgi, $param); # Superisory access ($super) = $database->DataGetRoomPrivs($param->{'ROOM'}, $param->{'USER'}); # Ensure they are supervisors if (defined($super)) { # Pruge posts $data->do("DELETE FROM Board WHERE RealmName=? AND BoardTopic=? AND (LevelZero=? OR LevelOne=? OR LevelTwo=? OR LevelThree=? OR LevelFive=?)", {}, $param->{'ROOM'}, $param->{'TOPIC'}, $param->{'PURGE'}, $param->{'PURGE'}, $param->{'PURGE'}, $param->{'PURGE'}, $param->{'PURGE'}); } # Auditing table $audit->BoardRem($param->{'PURGE'}); # Cleanup $param->Cleanup('PURGE'); } # Kill switch else { # Do not collect 100$ $param->{'PASSGO'} = 'No'; } } ##################### # Post Writer # # Handles the eventual cleanup and posting of the post to the threads and tree. This includes # language filtering and removal of HTML to keep this clean. sub PostWrite # Database, CGI, Parameter list { ##################### # Data members my $database = shift; # Database handle my $login = shift; # Login handle my $cgi = shift; # CGI handle my $param = shift; # Parameter list my $board = shift; # Board hash handle my $system = shift; # System board my $data = $database->{'HANDLE'}; # Database connection handle my $date = new Ethereal::Date(); # Date handler my $filter = new Ethereal::Filter(); # Filter handler my $send; # Mail sender my $statement; # Query statement my $time; # Date of handling my $email; # Email address my $name; # Full name my $notice; # Notice my $post; # Pre modified post my $puppet; # Puppet name my $puppeteer; # Puppeteer name my $level; # Level my $res; # Results my $id = 'LAST_INSERT_ID()'; # ID insertion function my $url = $cgi->url(); # Location to self my @levels; # Levels and depth ##################### # Program area # Wrapper $Text::Wrap::columns = 72; # Link with hash $database->GetHashSystem(\%system); # Ensure authenthication if ($login->GetVerificationNormal()) { # Information handling # Retreive post information if (defined($param->{'PID'})) { # Prepare and execute $statement = $data->prepare("SELECT PuppetName, BoardLevel, LevelZero, LevelOne, LevelTwo, LevelThree, LevelFour, LevelFive FROM Board WHERE BoardIDNumber=?"); $statement->execute($param->{'PID'}); # Retreive and adapt $res = $statement->fetchrow_hashref(); # Determine levels $levels[0] = $res->{'LevelZero'}; $levels[1] = ($res->{'LevelOne'} != $res->{'LevelZero'}) ? $res->{'LevelOne'} : $id; $levels[2] = ($res->{'LevelTwo'} != $res->{'LevelOne'}) ? $res->{'LevelTwo'} : $id; $levels[3] = ($res->{'LevelThree'} != $res->{'LevelTwo'}) ? $res->{'LevelThree'} : $id; $levels[4] = ($res->{'LevelFour'} != $res->{'LevelThree'}) ? $res->{'LevelFour'} : $id; $levels[5] = ($res->{'LevelFive'} != $res->{'LevelFour'}) ? $res->{'LevelFive'} : $id; # Determin response level $level = $res->{'BoardLevel'} + 1; $level = ($level > 5) ? 5 : $level; # Determin puppet name $puppet = $res->{'PuppetName'}; # Finish query $statement->finish(); } # Parent (root level) posts else { # Assign levels and level for root @levels = ($id, $id, $id, $id, $id, $id); $level = 0; } # Sanity check $param->{'PTEXT'} = $filter->MakeSane($param->{'PTEXT'}, $board->{'SetTruncate'}); # Mold subject and body # Strip HTML $param->{'PSUBJ'} =~ s/<[^>]*>//gs; $param->{'PTEXT'} =~ s/<[^>]*>//gs; # Buffer for Emails $post = fill(' ', ' ', $param->{'PTEXT'}); # Replace carriage returns $param->{'PTEXT'} =~ s/\n/
/gs; # Create hyperlinks $param->{'PTEXT'} =~ s/(http:\/\/.*?)(\s|$)/$board->{TagHyperlink}<\/A> /gm; $param->{'PTEXT'} =~ s/([\w\.\-]*?\@[\w\.\-]*?\..*?)(\s|$)/$board->{TagEmail}<\/A> /gm; # Database insertion $data->do("INSERT INTO Board (BoardIDNumber, PuppetName, RealmName, BoardTopic, BoardSubject, BoardTimestamp, BoardMessage, BoardUpdate, BoardLevel, LevelZero, LevelOne, LevelTwo, LevelThree, LevelFour, LevelFive) VALUES (NULL,?,?,?,?,?,?,?,?,0,0,0,0,0,0)", {}, $param->{'PFROM'}, $param->{'ROOM'}, $param->{'TOPIC'}, $param->{'PSUBJ'}, time, $param->{'PTEXT'}, time, $level); # MySQL kludge $data->do("UPDATE Board SET LevelZero=$levels[0], LevelOne=$levels[1], LevelTwo=$levels[2], LevelThree=$levels[3], LevelFour=$levels[4], LevelFive=$levels[5] WHERE BoardIDNumber=LAST_INSERT_ID()", {}); # Bump up thread $data->do("UPDATE Board SET BoardUpdate=? WHERE LevelZero=?", {}, time, $levels[0]); # Generate date $time = $date->GetDate(time); # Administrative message # Determine need ($email) = $database->DataGetRealmBoard($param->{'ROOM'}); # Generate if (defined($email)) { # Pull ($notice) = $database->DocumentGetBoardAdmin(); # Send Mail # Handle initiation $send = tie(*MAIL, 'Ethereal::Mail', $database); # Initial setup $send->SetSubject("$system->{SetBoardPrefix} $param->{PSUBJ}"); $send->SetSearch( MDATE => $time, MFROM => $param->{'PFROM'}, MLINK => $url, MMAIL => "$system->{SetInfoContactName}\n$system->{SetInfoContactAddress}", MMESG => $post, MROOM => $param->{'ROOM'}, MSUBJ => $param->{'PSUBJ'}, MTOPC => $param->{'TOPIC'} ); # Recipients $send->AddTo("$name <$email>"); # Add message print MAIL $notice; # Close and send close(MAIL); } # Email notification if (defined($puppet)) { # Retreive login ($puppeteer) = $database->DataGetPuppeteerLogin($puppet); # Complete if defined if (defined($puppeteer)) { # Retreive name and Email ($name) = $database->DataGetPuppeteerName($puppeteer); ($email) = $database->DataGetPuppeteerEmail($puppeteer); ($notice) = $database->DocumentGetBoardNotice(); if (defined($notice)) { # Send Email # Iniate instance $send = tie(*MAIL, 'Ethereal::Mail', $database); # Initial setup $send->SetSubject("You have a reply on $param->{ROOM} message board from: $param->{'PFROM'}"); $send->SetSearch( MDATE => $time, MFROM => $param->{'PFROM'}, MLINK => $url, MMAIL => "$system->{SetInfoContactName}\n$system->{SetInfoContactAddress}", MMESG => $post, MROOM => $param->{'ROOM'}, MSUBJ => $param->{'PSUBJ'}, MTOPC => $param->{'TOPIC'} ); # Recipients $send->AddTo("$name <$email>"); # Message print MAIL $notice; # Close and send close(MAIL); } } } # Cleanup $param->Cleanup( 'PID', 'PFROM', 'PSUBJ', 'PTEXT', 'WRITE' ); } # Kill switch else { # Do not collect 100$ $param->{'PASSGO'} = 'No'; } }