###############################################################################
# Subs.pm #
# $Date: 06.01.16 $ #
###############################################################################
# YaBB: Yet another Bulletin Board #
# Open-Source Community Software for Webmasters #
# Version: YaBB 2.6.13 #
# Packaged: June 1, 2016 #
# Distributed by: http://www.yabbforum.com #
# =========================================================================== #
# Copyright (c) 2000-2016 YaBB (www.yabbforum.com) - All Rights Reserved. #
# Software by: The YaBB Development Team #
# with assistance from the YaBB community. #
###############################################################################
# use strict;
# use warnings;
no warnings qw(uninitialized once);
use CGI::Carp qw(fatalsToBrowser);
use URI::Escape;
use English qw(-no_match_vars);
our $VERSION = '2.6.13';
$subspmver = 'YaBB 2.6.13 $Revision$';
use subs 'exit';
$yymain = q{};
$yyjavascript = q{};
$langopt = q{};
# set line wrap limit in Display.
$linewrap = 80;
$newswrap = 0;
# get the current date/time
$date = int( time() + $timecorrection );
# check if browser accepts encoded output
$gzaccept = $ENV{'HTTP_ACCEPT_ENCODING'} =~ /\bgzip\b/sm || $gzforce;
# parse the query string
readform();
$uid = substr $date, length($date) - 3, 3;
$session_id = $cookiesession_name;
$randaction = substr $date, 0, length($date) - 2;
$user_ip = $ENV{'REMOTE_ADDR'};
if ( $user_ip eq '127.0.0.1' ) {
if ( $ENV{'HTTP_CLIENT_IP'} && $ENV{'HTTP_CLIENT_IP'} ne '127.0.0.1' ) {
$user_ip = $ENV{'HTTP_CLIENT_IP'};
}
elsif ( $ENV{'X_CLIENT_IP'} && $ENV{'X_CLIENT_IP'} ne '127.0.0.1' ) {
$user_ip = $ENV{'X_CLIENT_IP'};
}
elsif ($ENV{'HTTP_X_FORWARDED_FOR'}
&& $ENV{'HTTP_X_FORWARDED_FOR'} ne '127.0.0.1' )
{
$user_ip = $ENV{'HTTP_X_FORWARDED_FOR'};
}
}
if ( -e "$yyexec.cgi" ) { $yyext = 'cgi'; }
else { $yyext = 'pl'; }
if ( -e 'AdminIndex.cgi' ) { $yyaext = 'cgi'; }
else { $yyaext = 'pl'; }
sub automaintenance {
my ( $maction, $mreason ) = @_;
if ( lc($maction) eq 'on' ) {
fopen( MAINT, ">$vardir/maintenance.lock" );
print {MAINT}
qq~$maintxt{'maint'}\n~
or croak qq~$maintxt{'maint'}~;
fclose(MAINT);
if ( $mreason eq 'low_disk' ) {
LoadLanguage('Error');
alertbox( $error_txt{'low_diskspace'} );
}
if ( !$maintenance ) { $maintenance = 2; }
}
elsif ( lc($maction) eq 'off' ) {
unlink "$vardir/maintenance.lock"
or fatal_error( 'cannot_open_dir', "$vardir/maintenance.lock" );
if ( $maintenance == 2 ) { $maintenance = 0; }
}
return;
}
sub getnewid {
my $newid = $date;
while ( -e "$datadir/$newid.txt" ) { ++$newid; }
return $newid;
}
sub undupe {
my (@indup) = @_;
my ( @out, $duped, );
foreach my $check (@indup) {
$duped = 0;
foreach (@out) {
if ( $_ eq $check ) { $duped = 1; last; }
}
if ( !$duped ) { push @out, $check; }
}
return @out;
}
sub exit {
my ($inexit) = @_;
my $OUTPUT_AUTOFLUSH = 1;
my $OUTPUT_RECORD_SEPARATOR = q{};
print q{};
if ($child_pid) { wait; }
CORE::exit( $inexit || 0 );
return;
}
sub print_output_header {
if ($header_already_printed) { return; }
$yyxml_lang = $abbr_lang;
$header_already_printed = 1;
$headerstatus ||= '200 OK';
$contenttype ||= 'text/html';
my $ret = $yyIIS ? "HTTP/1.0 $headerstatus\n" : "Status: $headerstatus\n";
foreach ( $yySetCookies1, $yySetCookies2, $yySetCookies3, @otherCookies ) {
if ($_) { $ret .= "Set-Cookie: $_\n"; }
}
if ( !$no_error_page ) {
if ($yySetLocation) {
$ret .= "Location: $yySetLocation";
}
else {
if ( !$cachebehaviour ) {
$ret .=
"Cache-Control: no-cache, must-revalidate\nPragma: no-cache\n";
}
if ($ETag) { $ret .= "ETag: \"$ETag\"\n"; }
if ($LastModified) { $ret .= "Last-Modified: $LastModified\n"; }
if ( $gzcomp && $gzaccept ) { $ret .= "Content-Encoding: gzip\n"; }
$ret .= "Content-Type: $contenttype";
if ($yycharset) {$yymycharset = $yycharset;}
if ($yymycharset) { $ret .= "; charset=$yymycharset"; }
}
}
print $ret . "\r\n\r\n" or croak "$croak{'print'} ret";
return;
}
sub print_HTML_output_and_finish {
if ( $gzcomp && $gzaccept ) {
my $filehandle_exists = fileno GZIP;
if ( $gzcomp == 1 || $filehandle_exists ) {
$OUTPUT_AUTOFLUSH = 1;
if ( !$filehandle_exists ) {
open GZIP, '| gzip -f' or croak "$croak{'open'} GZIP";
}
print {GZIP} $output or croak "$croak{'print'} GZIP";
close GZIP or croak "$croak{'close'}";
}
else {
require Compress::Zlib;
binmode STDOUT;
print Compress::Zlib::memGzip($output)
or croak "$croak{'print'} ZLib";
}
}
else {
print $output; # or croak "$croak{'print'} output";
}
exit;
}
sub write_cookie {
my %params = @_;
if ( $params{'-expires'} =~ /\+(\d+)m/xsm ) {
my ( $sec, $min, $hour, $mday, $mon, $year, $wday ) =
gmtime( $date + $1 * 60 );
$year += 1900;
my @mos = qw(
Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
);
my @dys = qw( Sun Mon Tue Wed Thu Fri Sat );
$mon = $mos[$mon];
$wday = $dys[$wday];
$params{'-expires'} = sprintf '%s, %02i-%s-%04i %02i:%02i:%02i GMT',
$wday, $mday, $mon, $year, $hour, $min, $sec;
}
if ( $params{'-path'} ) { $params{'-path'} = " path=$params{'-path'};"; }
if ( $params{'-expires'} ) {
$params{'-expires'} = " expires=$params{'-expires'};";
}
return
"$params{'-name'}=$params{'-value'};$params{'-path'}$params{'-expires'}";
}
sub redirectexit {
$headerstatus = '302 Moved Temporarily';
print_output_header();
exit;
}
sub redirectmove {
require Sources::MessageIndex;
MessageIndex();
return;
}
sub redirectinternal {
if ($currentboard) {
if ( $INFO{'num'} ) { require Sources::Display; Display(); }
else { require Sources::MessageIndex; MessageIndex(); }
}
else {
require Sources::BoardIndex;
BoardIndex();
}
return;
}
sub ImgLoc {
@img = @_;
if ( exists $img_locs{ $img[0] } ) {
$img_locs{ $img[0] } = $img_locs{ $img[0] };
}
elsif ( -e "$htmldir/Templates/Forum/$useimages/$img[0]" ) {
$img_locs{ $img[0] } = qq~$imagesdir/$img[0]~;
}
else {
$img_locs{ $img[0] } = qq~$defaultimagesdir/$img[0]~;
}
return $img_locs{ $img[0] };
}
sub template {
print_output_header();
if ( $yytitle ne $maintxt{'error_description'} ) {
if ( ( !$iamguest || ( $iamguest && $guestaccess == 1 ) )
&& !$maintenance )
{
$yyforumjump = jumpto();
}
else { $yyforumjump = ' '; }
}
$yyposition = $yytitle;
$yytitle = "$mbname - $yytitle";
$yyimages = $imagesdir;
$yydefaultimages = $defaultimagesdir;
$yysyntax_js = q{};
$yygreyboxstyle = q{};
$yygrayscript = q{};
if (
$INFO{'num'}
|| $action eq 'post'
|| $action eq 'modify'
|| $action eq 'preview'
|| $action eq 'search2'
|| $action eq 'imshow'
|| $action eq 'imsend'
|| $action eq 'myviewprofile'
|| $action eq 'eventcal'
|| $action eq 'help'
|| $action eq 'recenttopics'
|| $action eq 'recent'
|| $action eq 'usersrecentposts'
|| $action eq 'myusersrecentposts'
)
{
$yysyntax_js = qq~
~;
$yyjsstyle =
qq~\n~;
$yyhigh = q~~;
if ($img_greybox) {
$yygreyboxstyle =
qq~\n~;
$yygrayscript = qq~
~;
}
}
$yystyle =
qq~\n~;
$yystyle =~ s/$usestyle\///gxsm;
$yystyle .= $yyjsstyle;
$yystyle .= $yygreyboxstyle;
$yystyle .= $yyinlinestyle;
if ( $action eq 'register' || $action eq 'guestpm' || $action eq 'modalert' || $action eq 'post' || $action eq 'imsend' || ( $action eq 'eventcal' && $INFO{'addnew'} == 1 ) ) {
$yystyle .= '';
}
# Carsten's 'backtotop';
if ( !$yynavback ) { $yynavback .= q~ ~; }
$yynavback .=
qq~$tabsep $img_txt{'102'} $tabsep~;
if ( !$usehead ) { $usehead = q~default~; }
$yytemplate = "$templatesdir/$usehead/$usehead.html";
fopen( TEMPLATE, $yytemplate ) or croak("$maintxt{'23'}: $yytemplate");
@whole_file = ;
$output = join q{}, @whole_file;
fclose(TEMPLATE);
if ( $iamadmin || $iamgmod ) {
if ($maintenance) {
if ($do_scramble_id) { $user = cloak($username); }
else { $user = $username; }
$yyadmin_alert .=
qq~
$load_txt{'616'}~;
$yyadmin_alert =~ s/USER/$user/sm;
}
$rememberbackup ||= 0;
if ( $iamadmin && $rememberbackup > 0 ) {
if ( $lastbackup && $date > $rememberbackup + $lastbackup ) {
$yyadmin_alert .=
qq~
$load_txt{'617'} ~
. timeformat($lastbackup)
. q~~;
}
}
}
# to top button for fixed menu
$yyfixtop = qq~$img_txt{'to_top'}~;
$yyboardname = "$mbname";
$yyboardlink = qq~$mbname~;
# static/dynamic clock
$yytime = timeformat( $date, 1 );
my $zone = q{};
if ( ($iamguest && $default_tz eq 'UTC') || (${ $uid . $username }{'user_tz'} eq 'UTC') || ( !$default_tz && !${ $uid . $username }{'user_tz'} ) ) {
$zone = qq~ $maintxt{'UTC'}~;
}
my $toffs = 0;
if ( $enabletz ) {
$toffs = toffs($date);
}
if (
$mytimeselected != 7
&& ( ( $iamguest && $dynamic_clock )
|| ${ $uid . $username }{'dynamic_clock'} )
)
{
if ( $yytime =~ /(.*?)\d+:\d+((\w+)|:\d+)?/xsm ) {
( $aa, $bb ) = ( $1, $3 );
}
$aa =~ s/<.+?>//gxsm;
if ( $mytimeselected == 6 ) { $bb = q{ }; }
$yytime =
qq~ ~;
$yyjavascripta .=
qq~
var OurTime = ~
. sprintf( '%d', ( $date + $toffs ) )
. qq~000;\nvar YaBBTime = new Date();\nvar TimeDif = YaBBTime.getTime() - (YaBBTime.getTimezoneOffset() * 60000) - OurTime - 1000; // - 1000 compromise to transmission time~;
}
$yytime .= $zone;
$yyjavascripta .= qq~
var imagedir = "$imagesdir";
function toTop(scrpoint) {
window.scrollTo(0,scrpoint);
}~;
$yyjavascript .= q~
function txtInFields(thefield, defaulttxt) {
if (thefield.value == defaulttxt) thefield.value = "";
else { if (thefield.value === "") thefield.value = defaulttxt; }
}
function selectAllCode(thefield) {
var elem = document.getElementById('code' + thefield);
if (document.selection) {
document.selection.empty();
var txt = document.body.createTextRange();
txt.moveToElementText(elem);
txt.select();
}
else {
window.getSelection().removeAllRanges();
txt = document.createRange();
txt.setStartBefore(elem);
txt.setEndAfter(elem);
window.getSelection().addRange(txt);
}
}
~;
require Sources::TabMenu;
mainMenu();
$yylangChooser = q{};
if ( ( $iamguest && !$guestLang ) && $enable_guestlanguage && $guestaccess )
{
if ( !$langopt ) { guestLangSel(); }
if ( $morelang > 1 ) {
$yylangChooser =
qq~$guest_txt{'sellanguage'}: ~;
}
}
elsif (( $iamguest && $guestLang )
&& $enable_guestlanguage
&& $guestaccess )
{
if ( !$langopt ) { guestLangSel(); }
if ( $morelang > 1 ) {
$yylangChooser =
qq~$guest_txt{'changelanguage'}: ~;
}
}
my $wmessage;
if ( $hour >= 12 && $hour < 18 ) {
$wmessage = $maintxt{'247a'};
} # Afternoon
elsif ( $hour < 12 && $hour >= 0 ) {
$wmessage = $maintxt{'247m'};
} # Morning
else { $wmessage = $maintxt{'247e'}; } # Evening
if ($iamguest) {
$yyuname = qq~$maintxt{'248'} $maintxt{'28'}. $maintxt{'249'} 1)alert('$maintxt{'35'}');jumptologin++;window.scrollTo(0,10000);document.loginform.username.focus();"
: "$scripturl?action=login"
) . qq~">$maintxt{'34'}~;
if ($regtype) {
$yyuname .=
qq~ $maintxt{'377'} $maintxt{'97'}~;
}
$yyjavascript .= q~ jumptologin = 1;~;
}
else {
if ( ${ $uid . $username }{'bday'} ) {
my ( $usermonth, $userday, $useryear ) =
split /\//xsm, ${ $uid . $username }{'bday'};
if ( $usermonth == $mon_num && $userday == $mday ) {
$wmessage = $maintxt{'247bday'};
}
}
$yyuname =
( $PM_level == 0
|| ( $PM_level == 2 && !$staff )
|| ( $PM_level == 3 && !$iamadmin && !$iamgmod )
|| ( $PM_level == 4 && !$iamadmin && !$iamgmod && !$iamfmod ) )
? "$wmessage ${$uid.$username}{'realname'}"
: "$wmessage ${$uid.$username}{'realname'}, ";
}
# Add new notifications if allowed
if ( !$iamguest && $NewNotificationAlert ) {
if ( !$board_notify && !$thread_notify ) {
require Sources::Notify;
( $board_notify, $thread_notify ) = NotificationAlert();
}
my ( $bo_num, $th_num );
foreach ( keys %{$board_notify} ) { # boardname, boardnotifytype , new
if ( ${ $$board_notify{$_} }[2] ) { $bo_num++; }
}
foreach ( keys %{$thread_notify} )
{ # mythread, msub, new, username_link, catname_link, boardname_link, lastpostdate
if ( ${ $$thread_notify{$_} }[2] ) { $th_num++; }
}
if ( $bo_num || $th_num ) {
my $noti_text = (
$bo_num
? "$notify_txt{'201'} $notify_txt{'205'} ($bo_num)"
: q{}
)
. (
$th_num
? ( $bo_num ? " $notify_txt{'202'} " : q{} )
. "$notify_txt{'201'} $notify_txt{'206'} ($th_num)"
: q{}
);
if ( ${ $uid . $username }{'onlinealert'} && $boardindex_template )
{
$yyadmin_alert =
qq~
$notify_txt{'200'} $noti_text.$yyadmin_alert~;
$yymain .= qq~~;
}
}
}
# check for copyright for special error - angle brackets no longer supported for yabb tags
if ( $output =~ m/{yabb\ copyright}/xsm ) {
$yycopyin = 1;
}
$yysearchbox = q{};
$qckage ||= 0;
if ( !$iamguest || $guestaccess != 0 ) {
if ( $maxsearchdisplay > -1 && $qcksearchaccess eq 'granted' ) {
my $blurb = qq~$maintxt{'searchimg'} $qckage $maintxt{'searchimg2'}~;
if ( $qckage == 0 ) {
$blurb = qq~$maintxt{'searchimg3'}~;
}
$yysearchbox = qq~
~;
}
}
if ( $enable_news && ( -s "$vardir/news.txt" ) > 5 ) {
fopen( NEWS, "$vardir/news.txt" );
my @newsmessages = ;
fclose(NEWS);
chomp @newsmessages;
my $startnews = int rand @newsmessages;
$yynewstitle = qq~$maintxt{'102'}: ~;
$yynewstitle =~ s/\x27/\\\x27/gxsm;
$guest_media_disallowed = 0;
$newswrap = 40;
if ($shownewsfader) {
$fadedelay = $maxsteps * $stepdelay;
$yynews .= qq~
~;
}
else {
$message = $newsmessages[$startnews];
wrap();
if ($enable_ubbc) {
enable_yabbc();
DoUBBC();
$message =~ s/ style="display:none"/ style="display:block"/gsm;
}
wrap2();
ToChars($message);
$message =~ s/\x27/&\x2339;/xsm;
$yynews = qq~
~;
}
$newswrap = 0;
}
else {
$yynews = ' ';
}
if ( $debug == 1 || ( $debug == 2 && $iamadmin ) || $debug == 3 ) {
require Sources::Debug;
LoadLanguage('Debug');
Debug();
}
$yyurl = $scripturl;
my $copyright = $output =~ m/{yabb\ copyright}/xsm ? 1 : 0;
while ( $output =~ s/({)yabb\s+(\w+)(})/${"yy$2"}/gxsm ) { }
# check if image exists, otherwise use the default template image
if ( $imagesdir ne $defaultimagesdir ) {
my %img_locs;
$output =~
s/(src|value|url)(=|\()("|'| )$imagesdir\/([^'" ]+)./ "$1$2$3" . ImgLoc($4) . $3 /eisgm;
}
# add formsession to each