# irclogger_web # Copyright (C) 2023 mrkubax10 # 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 . package frontend_routes; use lib "."; use frontend_session; use Digest::SHA; use Data::Dumper; 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 = "$username"; $userbar.="Log out"; $logged = 1; } } if(!$logged) { $userbar = "
"; $userbar.=" "; $userbar.=" "; $userbar.=""; $userbar.="
"; } 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.="$channelName$serverName"; } 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 = Digest::SHA::sha256_hex(sprintf("%x", rand(0xFFFFFFFF)%0xFF)); $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.="$entry"; } 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;