irclogger_web/frontend_routes.pm

194 lines
6.7 KiB
Perl
Raw Normal View History

2023-09-08 22:05:21 +02:00
# irclogger_web
# Copyright (C) 2023 mrkubax10 <mrkubax10@onet.pl>
# 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 3 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, see <http://www.gnu.org/licenses/>.
package frontend_routes;
use lib ".";
use frontend_session;
use Digest::SHA;
use feature qw(switch);
use strict;
use warnings;
sub handlePath {
my $aClient = $_[0];
my $aPath = $_[1];
my $aRequest = $_[2];
my $aConnection = $_[3];
given($aPath) {
when("/") {
my $userbar;
my $logged = 0;
if(defined($aRequest->{"cookies"}) && defined($aRequest->{"cookies"}{"session"})) {
my $session = $aRequest->{"cookies"}{"session"};
if(frontend_session::isValidSession($session) && defined($frontend_session::sessions{$session}{"username"}) && $frontend_session::sessions{$session}{"logged"}) {
my $username = $frontend_session::sessions{$session}{"username"};
$userbar = "<a href=\"panel\">$username</a>";
$userbar.="<a href=\"logout_action\">Log out</a>";
$logged = 1;
}
}
if(!$logged) {
$userbar = "<form action=\"login_action\" method=\"POST\">";
$userbar.="<input name=\"username\" type=\"text\" placeholder=\"Username\" /> ";
$userbar.="<input name=\"password\" type=\"password\" placeholder=\"Password\" /> ";
$userbar.="<input name=\"login\" type=\"submit\" value=\"Login\" />";
$userbar.="</form>";
}
my $query = $aConnection->prepare(qq(select channels.id, channels.name, servers.name from channels inner join servers on channels.server_id=servers.id where channels.public=1;));
$query->execute();
my $table = "";
while(my @row = $query->fetchrow_array()) {
my $channelID = $row[0];
my $channelName = $row[1];
my $serverName = $row[2];
$table.="<tr><td><a href=\"view_logs?channel=$channelID\">$channelName</a></td><td>$serverName</td></tr>";
}
frontend::sendTemplate("templates/index.html", $aClient, {"userbar"=>$userbar, "publicChannels"=>$table});
return 1;
}
when("/login_action") {
if(defined($aRequest->{"cookies"}{"session"}) && frontend_session::isValidSession($aRequest->{"cookies"}{"session"})) {
frontend::redirect($aClient, "/");
return 1;
}
if(defined($aRequest->{"headers"}{"Content-Type"}) && $aRequest->{"headers"}{"Content-Type"} ne "application/x-www-form-urlencoded") {
frontend::sendBadRequest($aClient, "Unsupported form Content-Type (application/x-www-form-urlencoded required)");
return 1;
}
if(!defined($aRequest->{"content"})) {
frontend::sendBadRequest($aClient, "Request content required");
return 1;
}
my %parameters = frontend::parsePathParameters($aRequest->{"content"});
if(!defined($parameters{"username"})) {
frontend::sendBadRequest($aClient, "Username parameter required");
return 1;
}
if(!defined($parameters{"password"})) {
frontend::sendBadRequest($aClient, "Password parameter required");
return 1;
}
my $username = $parameters{'username'};
#my $hashedPassword = Digest::SHA::sha256_hex($parameters{"password"});
my $hashedPassword = $parameters{"password"};
my $query = $aConnection->prepare(qq(select name, password from users where name=?;));
$query->execute($username);
my @row = $query->fetchrow_array();
if(scalar(@row)==0) {
frontend::sendBadRequest($aClient, "Unknown user $username");
return 1;
}
if($row[1] ne $hashedPassword) {
frontend::sendBadRequest($aClient, "Wrong password");
return 1;
}
my $token = frontend_session::newSessionToken();
2023-09-08 22:05:21 +02:00
$frontend_session::sessions{$token}{"username"} = $username;
$frontend_session::sessions{$token}{"logged"} = 1;
my $response = frontend::getBaseResponse(301, "OK");
$response.="Location: /\r\n";
$response.="Content-Length: 0\r\n";
$response.="Set-Cookie: session=$token\r\n\r\n";
$aClient->send($response);
return 1;
}
when("/view_logs") {
my $channelID = $aRequest->{"path"}{"parameters"}{"channel"};
if(!defined($channelID)) {
frontend::sendBadRequest($aClient, "view_logs requires channel URL parameter");
return 1;
}
my $query = $aConnection->prepare(qq(select channels.name, servers.name from channels inner join servers on channels.server_id=servers.id where channels.id=?;));
$query->execute($channelID);
my @row = $query->fetchrow_array();
if(scalar(@row)==0) {
frontend::sendBadRequest($aClient, "Unknown channel with ID $channelID");
return 1;
}
my $channelName = $row[0];
my $serverName = $row[1];
my $logsPath = "logs/".$serverName."/".$channelName;
my $result = opendir(my $folder, $logsPath);
if(!$result) {
frontend::sendBadRequest($aClient, "Channel $channelName on $serverName doesn't have any logs");
return 1;
}
my @entries = grep(!/^\.\.?$/, readdir($folder));
my $table = "";
foreach my $entry (@entries) {
$table.="<tr><td><a href=\"view_log?channel=$channelID&file=$entry\">$entry</a></td></tr>";
}
frontend::sendTemplate("templates/view_logs.html", $aClient, {"channel"=>$channelName, "server"=>$serverName, "logs"=>$table});
return 1;
}
when("/view_log") {
my $channelID = $aRequest->{"path"}{"parameters"}{"channel"};
if(!defined($channelID)) {
frontend::sendBadRequest($aClient, "view_log requires channel URL parameter");
return 1;
}
my $logFile = $aRequest->{"path"}{"parameters"}{"file"};
if(!defined($channelID)) {
frontend::sendBadRequest($aClient, "view_log requires file URL parameter");
return 1;
}
my $query = $aConnection->prepare(qq(select channels.name, servers.name from channels inner join servers on channels.server_id=servers.id where channels.id=?;));
$query->execute($channelID);
my @row = $query->fetchrow_array();
if(scalar(@row)==0) {
frontend::sendBadRequest($aClient, "Unknown channel with ID $channelID");
return 1;
}
my $channelName = $row[0];
my $serverName = $row[1];
my $logFilePath = "logs/".$serverName."/".$channelName."/".$logFile;
my $result = open(my $file, "<", $logFilePath);
if(!$result) {
frontend::sendBadRequest($aClient, "No log file $logFile for channel $channelName at $serverName");
return 1;
}
my $content = frontend::readFullFile($file);
close($file);
my $response = frontend::getBaseResponse(200, "OK");
$response.="Content-Type: text/plain;charset=utf-8\r\n";
$response.="Content-Length: ".length($content)."\r\n\r\n";
$response.=$content;
$aClient->send($response);
}
}
return 0;
}
1;