ONO::ToolBox::Screen

package ONO::ToolBox::Screen;
################################################################################
# COPYRIGHT / LICENSE #
################################################################################
#
# This file is part of the ONO Software Project.
#
# Copyright (C) 2000-2025 Jos KIRPS [ www.kirps.com | jos_AT_kirps_DOT_com ]
# and The Joopita Project [ www.joopita.org | contact_AT_joopita_DOT_com ]
#
# This file, as well as other parts of the ONO Software Project or related
# elements, are FREE SOFTWARE available under the ARTISTIC LICENSE 2.0.
#
# 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.
#
# For the full license, see /ono/osr/license/LICENSE.txt, or write to
# jos_AT_kirps_DOT_com or contact_AT_joopita_DOT_com.
#
################################################################################
# END OF COPYRIGHT / LICENSE, HERE COMES THE CODE ... #
################################################################################


use strict;

use ONO::IO;
use ONO::DB;

use ONO::Lib::UI::MSG;
use ONO::Lib::UI::Check;
use ONO::Lib::UI::Page;

use ONO::Core::Version;

use ONO::ToolBox::SendMail;
use ONO::ToolBox::ONO;

use ONO::Lib::Web::Client;
use ONO::Lib::DateTime::ToolBox;

###############################################################################
# msg
###############################################################################

#: This module helps building the ONO Admin and ONO desk interface.

sub build {

my (
$self,
$TITLE,
$SUBTITLE,
$TOOLS,
$SCREEN,
$LEFT,
$RIGHT,
$MODE,
) = @_;

#: This will glue page parts in order to build a stanard ONO Admin or ONO
#: Desk interface screen.

my $WEB;

# build the title link

if ($TITLE && $ENV{'REQUEST_URI'} =~ m~/ono/admin/\?/(.*?)/~) {
$TITLE = qq~<a href="/ono/admin/?/$1/" class="col6">$TITLE</a>~
}
if ($TITLE && $ENV{'REQUEST_URI'} =~ m~/ono/admin/~ && $MODE) {
$TITLE = qq~<a href="/ono/admin/?/$MODE/" class="col6">$TITLE</a>~
}

# merge everything...

if ($SUBTITLE && $SUBTITLE =~ /^\(/) {
$TITLE = qq~$TITLE <span class="small colc">$SUBTITLE</span>~;
}
if ($TITLE) {
$TITLE = qq~<h1 class="m0">$TITLE</h1>~;
}
if ($SUBTITLE && $SUBTITLE !~ /^\(/) {
$TITLE .= qq~<h2 class="m0" style="font-size:140%">$SUBTITLE</h2>~;
}
if ($TITLE) {
$TITLE = qq~<div class="mb10">$TITLE</div>~;
}
if ($TOOLS) {
$TOOLS = qq~<div class="fr">$TOOLS</div>~;
}

if (!$LEFT && !$RIGHT) {

$WEB = qq~<div class="p10">$TOOLS$TITLE$SCREEN</div>~;

} else {

if ($LEFT && $RIGHT) {
if ($RIGHT !~ m~\<\!-- ono_disable_frame_right --\>~) {
$RIGHT = qq~<div class="box_paper">$RIGHT</div>~;
}
if ($LEFT !~ m~\<\!-- ono_disable_frame_left --\>~) {
$LEFT = qq~<div class="box_paper">$LEFT</div>~;
}
$WEB = ONO::Lib::UI::Page->layout("280,d,1000:100%:280,d,1000",$LEFT,"$TITLE$SCREEN",$RIGHT);
}
if (!$LEFT && $RIGHT) {
if ($RIGHT !~ m~\<\!-- ono_disable_frame_right --\>~) {
$RIGHT = qq~<div class="box_paper">$RIGHT</div>~;
}
$WEB = ONO::Lib::UI::Page->layout("100%:280,d,1000","$TITLE$SCREEN",$RIGHT);
}
if ($LEFT && !$RIGHT) {
if ($LEFT !~ m~\<\!-- ono_disable_frame_left --\>~) {
$LEFT = qq~<div class="box_paper">$LEFT</div>~;
}
$WEB = ONO::Lib::UI::Page->layout("280,d,1000:100%",$LEFT,"$TITLE$SCREEN");
}

$WEB = qq~<div class="inline w100 mt10">$WEB</div>~;

}

return $WEB;

}

sub menu {

my (
$self,
$LINK,
$ICON,
$TEXT,
$class,
$sel,
) = @_;

#: Generate a menu item.

$TEXT =~ s~ \&\; (.*?)$~<span class="hide1300"> \&\; $1</span>~;

return qq~<td class="nowrap p0" onclick="window.location='$LINK';">
<div style="$sel">
<table class="default_table">
<tr>
<td class="hide600"></td>
<td class="hide720"></td>
<td><a href="$LINK"><img class="block16 community_screen_mini" src="/ono/osr/images/icons/crystal/32x32/$ICON.png" alt=""></a></td>
<td class="hide1000 p5"><a href="$LINK" class="$class">$TEXT</a></td>
<td class="hide600"></td>
<td class="hide720"></td>
</tr>
</table>
</div>
</td>
~;

}

sub submenu {

#: Generate a submenu item.

my (
$self,
$LINK,
$ICON,
$TEXT,
$class,
$sel,
) = @_;

if ($TEXT =~ /^(.*?) & (.*?)$/) {
$TEXT = qq~$1<span class="hide800"> & $2</span>~;
}

return qq~<td class="nowrap p0" onclick="window.location='$LINK';">
<div class="pad10_2 pad5_2_800" style="$sel">
<a href="$LINK" class="$class">$TEXT</a>
</div>
</td>
~;

}

sub menu_pack {

my (
$self,
$MENU,
$SUB,
$SUB_PHONE,
$SIZE,
) = @_;

#: Glue menu elements

# Why isn't phone being used?

my $PHONE = qq~<td>
<div class="rel">
<input type="hidden" id="phone_nav_toggle" name="phone_nav_toggle" value="">
<table class="default_table mr10">
<tr>
<td class="p10" onclick="onojs_phone_nav_toggle();">
<div class="trans80 auto w80" style="width:40px">
<div class="p2" style="background-color:#eeeeee"></div>
<div style="padding:3px"></div>
<div class="p2" style="background-color:#eeeeee"></div>
<div style="padding:3px"></div>
<div class="p2" style="background-color:#eeeeee"></div>
</div>
</td>
</tr>
</table>
<div id="phone_nav" class="abs hide" style="z-index:99;top:-6px;left:70px;width:320px;background-color:#636363">
<table class="default_table">$SUB_PHONE</table>
</div>
</div>
</td>
$SUB
~;

$MENU .= qq~<td class="p5 w100"></td>~;

return (
$MENU,
qq~<div style="background-color:#444444;padding-top:4px">
<table class="wide_table" style="background-color:#444444;font-size:${SIZE}%">
<tr class="vbot">
<td class="pad10_2"></td>
$SUB
<td class="w100"></td>
</tr>
</table>
</div>
~
);

}

sub user {

my (
$self,
$db,
$community,
$LINK,
$LOGOUT,
$username,
$logout,
) = @_;

#: Username + logout button

return qq~<td><a href="$LINK"><img class="block16 community_screen_mini ml10" src="/ono/osr/images/icons/crystal/32x32/kdm/user_male.png" alt=""></a></td>
<td class="hide800"><a href="$LINK" class="col3">$username</a></td>
<td><a href="$LOGOUT"><img class="block16 community_screen_mini ml10" src="/ono/osr/images/icons/ono/32x32/logout.png" alt=""></a></td>
<td class="hide800" style="padding-right:10px"><a href="$LOGOUT" class="col3">$logout</a></td>
~;

}

sub copyright {

my (
$self,
$username,
$time,
$year,
) = @_;

#: Generate the copyright notice.

my ($ver,$rev) = ONO::Core::Version->ver;

return qq~<table class="wide_table mt10">
<tr>
<td class="w50 p5 small tar" style="line-height:130%">
<div>User $username is logged in</div>
<div>Screen loaded on $time</div>
</td>
<td><img class="block" src="/ono/osr/images/ono/banner_130_40.png" style="width:130px;height:40px" alt=""></td>
<td class="w50 p5 small" style="line-height:130%">
<div>ONO $ver$rev</div>
<div>© 2000-$year <a href="https://kirps.com" target="_blank" class="col6">Jos KIRPS</a> & <a href="https://joopita.com" target="_blank" class="col6">The JOOPITA Project</a></div>
</td>
</tr>
</table>
~;

}

sub login {

my (
$self,
$lang,
$BLK_ref,
$vars_ref,
$mode,
$ono_ref,
) = @_;

#: The default ONO login screen, as used by ONO Admin and ONO Desk.
#: Note that is screen also offers both PIN and IP based access protection
#: (before you may even try to login using username and password).

my %BLK = %$BLK_ref;
my %vars = %$vars_ref;
my %ono;
if ($ono_ref) {
%ono = %$ono_ref;
}

my ($badlogin,$dis);
my ($ver,$rev,$build) = ONO::Core::Version->ver;

my $BUTTON = $BLK{'submit_login'};

my $TITLE = "Administration";
my $TYPE = "ONOdesk";
my $LINK = "desk";

if ($mode eq "desk") {
$TITLE = "ONOdesk";
$TYPE = "Administration";
$LINK = "admin";
}

my ($HEADER,$WARN);
if ($ono{'site'}) {
$HEADER = "$ono{'site'} • ";
}
$HEADER .= $TITLE;
if (!$ENV{'HTTPS'} && ONO::IO->load("etc/https.conf") !~ /https on/) {
$WARN = qq~<div class="lightred center bold">This connection is not secure!</div>~;
}
if ($vars{'login_blocked'}) {
$WARN = qq~<div class="lightred center bold">$vars{'login_blocked'}</div>~;
$dis = "d";
$BUTTON = "";
}

my $SWITCH = ONO::Lib::UI::Check->switch("keep_session",0,"r$dis");

my $PINCODE;
my $USERPWD = qq~<tr>
<td class="w33 tar">$BLK{'username'}:</td>
<td class="w66"><input type="text" name="username" id="username" value="$vars{'username'}" maxlength="16" required class="w66"$dis></td>
</tr>
<tr>
<td class="tar">$BLK{'password'}:</td>
<td><input type="password" name="password" value="" maxlength="16" required class="w66"$dis></td>
</tr>
<tr>
<td class="tar">$SWITCH</td>
<td class="small col9">$BLK{'keep_me_logged_in'}</td>
</tr>
~;

if (ONO::IO->exists("etc/security/onologin.conf")) {
my %security = ONO::IO->confread("etc/security/onologin.conf","L");
my $pinprotect;
if ((!$mode || $mode eq "admin") && $security{'AdminLoginPIN'}) {
$pinprotect = $security{'AdminLoginPIN'};
}
if ($mode eq "desk" && $security{'UserLoginPIN'}) {
$pinprotect = $security{'UserLoginPIN'};
}
my $pincheck;
for (my $i = 0; $i < 256; $i++) {
$pincheck .= $vars{"pin_$i"};
}
if ($pinprotect) {
my $PIN;
for (my $i = 0; $i < length $pinprotect; $i++) {
$PIN .= qq~<td><input type="password" name="pin_$i" value="$vars{"pin_$i"}" class="center" style="width:20px" placeholder="?"></td>~;
}
$PINCODE = qq~<tr>
<td class="w33 tar">PIN:</td>
<td class="w66 p0"><table class="default_table">$PIN</table></td>
</tr>
~;

if ($pincheck ne $pinprotect) {
$USERPWD = "";

if ($pincheck =~ /[A-Za-z0-9]/ && ((((!$mode || $mode eq "admin") && $security{'AdminReportLoginAttempts'}) || ($mode eq "desk" && $security{'UserReportLoginAttempts'})))) {

my $MODE = uc $mode;
my $domain = $ENV{'SERVER_NAME'};

my %site = ONO::ToolBox::ONO->get();
if ($site{'domain'}) {
$domain = $site{'domain'};
}

ONO::ToolBox::SendMail->sendmail(
"<noreply\@$domain>",
"mail:tracker",
"[$domain] FAILED ONO $MODE PIN ATTEMPT",
"PIN: $pincheck\n\nIP: $ENV{'REMOTE_ADDR'}",
);

$PINCODE .= qq~<tr>
<td></td>
<td class="lightred">Bad PIN code.<div class="bold">This incident has been reported!</div></td>
</tr>
~;

}

}

}

}

my $year = ONO::Lib::DateTime::ToolBox->num("year");

if ($vars{'ono_blocked_ip'}) {

my $IP = ONO::Lib::Web::Client->ip();

return qq~<div class="hide600" style="padding:50px"></div>
<div class="auto rel box_paper center lightred bold" style="max-width:500px">
ACCESS DENIED [ $IP ]
</div>
<div class="center small cola mt5">
<a href="/ono/$LINK/" class="cola">$TYPE</a> • ONO v$ver$rev [$build] •
©2000-$year <a href="https://www.joopita.com" class="cola">Jos Kirps & The Joopita Project</a>
</div>
~;

} else {

return qq~<div class="hide600" style="padding:50px"></div>
<div class="auto rel box_paper" style="max-width:500px">
<a href="/ono/">
<img class="block24 abs hide600" src="/ono/osr/images/icons/crystal/32x32/ono/close.png" style="right:-10px;top:-10px" alt="">
<img class="block32 abs hide inline600" src="/ono/osr/images/icons/crystal/32x32/ono/close.png" style="right:10px;top:10px" alt="">
</a>
<img class="block auto hide600" src="/ono/osr/images/ono/logo_480_150.png" style="max-width:480px;height:auto" alt="">
<img class="block auto hide block600" src="/ono/osr/images/ono/logo_480_150.png" style="max-width:320px;height:auto" alt="">
<div class="p5 bt bb bold large col6 bg_fabric center mt10 mb20">$HEADER</div>
$WARN
<form action="$ENV{'SCRIPT_NAME'}" method="post" id="form" name="form">
<input type="hidden" name="site" value="$vars{'site'}">
<table class="wide_table auto">
$badlogin
$PINCODE
$USERPWD
<tr>
<td></td>
<td>$BUTTON</td>
</tr>
</table>
</form>
</div>
<div class="center small cola mt5">
<a href="/ono/$LINK/" class="cola">$TYPE</a> • ONO v$ver$rev [$build] •
©2000-$year <a href="https://www.joopita.com" class="cola">Jos Kirps & The Joopita Project</a>
</div>
~;
}

}

###############################################################################
# end of script
###############################################################################

1;

__END__