# 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 Affero 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 Affero General Public License for more details. # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . package frontend_routes; use lib "."; use frontend_session; use logger; use Digest::SHA; use threads::shared; use feature qw(switch); use strict; use warnings; no warnings qw(experimental::smartmatch); sub verifyRequestPrivileges { my $aRequest = $_[0]; my $aClient = $_[1]; my $aPrivileges = $_[2]; my $aConnection = $_[3]; if(!defined($aRequest->{"cookies"}{"session"}) || !frontend_session::isValidSession($aRequest->{"cookies"}{"session"})) { frontend::redirect($aClient, "/"); return 0; } 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 0; } if(!defined($aRequest->{"content"})) { frontend::sendBadRequest($aClient, "Request content required"); return 0; } my $session = $frontend_session::sessions{$aRequest->{"cookies"}{"session"}}; my $query = $aConnection->prepare(qq(select privileges from users where name=?;)); $query->execute($session->{"username"}); my @row = $query->fetchrow_array(); if($row[0]<$aPrivileges) { frontend::sendForbidden($aClient, "Insufficient permissions to perform this operation"); return 0; } return 1; } sub verifyChannelAccess { my $aRequest = $_[0]; my $aClient = $_[1]; my $aConnection = $_[2]; my $aChannelID = $_[3]; if(!defined($aRequest->{"cookies"}{"session"}) || !frontend_session::isValidSession($aRequest->{"cookies"}{"session"})) { frontend::sendUnauthorized($aClient, "You need to log in to view this resource"); return 0; } my $session = $frontend_session::sessions{$aRequest->{"cookies"}{"session"}}; my $query = $aConnection->prepare(qq(select id, privileges from users where name=?;)); $query->execute($session->{"username"}); my @row = $query->fetchrow_array(); my $userID = $row[0]; my $privileges = $row[1]; if($privileges>0) { return 1; } $query = $aConnection->prepare(qq(select user_id from accessors where channel_id=$aChannelID and user_id=$userID;)); $query->execute(); @row = $query->fetchrow_array(); if(scalar(@row)==0) { frontend::sendForbidden($aClient, "You don't have access to this channel logs"); return 0; } return 1; } sub enumerateServers { my $aConnection = $_[0]; my $output = ""; return $output; } sub enumerateChannels { my $aConnection = $_[0]; my $output = ""; return $output; } sub enumerateUsers { my $aConnection = $_[0]; my $aSession = $_[1]; my $output = ""; return $output; } 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, channels.enabled, servers.name, servers.enabled 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 $channelEnabled = $row[2] && $row[4]; my $serverName = $row[3]; $channelName =~ s/%23/#/; my $status = $channelEnabled?"Enabled":"Disabled"; $table.="$channelName$serverName$status"; } my $privateChannels = ""; if($logged) { $query = $aConnection->prepare(qq(select id, privileges from users where name=?;)); $query->execute($frontend_session::sessions{$aRequest->{"cookies"}{"session"}}{"username"}); my @row = $query->fetchrow_array(); if(scalar(@row)==0) { frontend::redirect($aClient, "/"); return 1; } my $id = $row[0]; my $privileges = $row[1]; if($privileges>0) { $query = $aConnection->prepare(qq(select id from channels where public=0;)); $query->execute(); } else { $query = $aConnection->prepare(qq(select channel_id from accessors where user_id=?;)); $query->execute($id); } while(@row = $query->fetchrow_array()) { my $channelID = $row[0]; my $channelQuery = $aConnection->prepare(qq(select channels.name, channels.enabled, servers.name, servers.enabled from channels inner join servers on channels.server_id=servers.id where channels.id=$channelID;)); $channelQuery->execute(); @row = $channelQuery->fetchrow_array(); my $channelName = $row[0]; $channelName =~ s/%23/#/; my $channelEnabled = $row[1] && $row[3]; my $serverName = $row[2]; my $status = $channelEnabled?"Enabled":"Disabled"; $privateChannels.="$channelName$serverName$status"; } } frontend::sendTemplate("templates/index.html", $aClient, {"userbar"=>$userbar, "publicChannels"=>$table, "privateChannels"=>$privateChannels}); 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 $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(); $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;expires=".localtime(time()+7*24*3600)."\r\n\r\n"; $aClient->send($response); return 1; } when("/logout_action") { if(defined($aRequest->{"cookies"}{"session"})) { frontend_session::deleteSession($aRequest->{"cookies"}{"session"}); } frontend::redirect($aClient, "/"); return 1; } when("/panel") { if(!defined($aRequest->{"cookies"}{"session"}) || !frontend_session::isValidSession($aRequest->{"cookies"}{"session"})) { frontend::redirect($aClient, "/"); return 1; } my $session = $frontend_session::sessions{$aRequest->{"cookies"}{"session"}}; my $query = $aConnection->prepare(qq(select privileges from users where name=?;)); $query->execute($session->{"username"}); my @row = $query->fetchrow_array(); if(scalar(@row)==0) { frontend::redirect($aClient, "/"); return 1; } my $privileges = $row[0]; my $manageChannelAccess = ""; my $addUser = ""; my $updateUser = ""; if($privileges>=1) { # moderator $manageChannelAccess.="

Manage channel access

"; $manageChannelAccess.="
"; $manageChannelAccess.=enumerateUsers($aConnection, $session)." "; $manageChannelAccess.=enumerateChannels($aConnection)."
"; $manageChannelAccess.=" "; $manageChannelAccess.=""; $manageChannelAccess.="
"; $addUser.="

Add user

"; $addUser.="
"; $addUser.="
"; $addUser.="
"; $addUser.="
"; $addUser.="Operator
"; $addUser.=""; $addUser.="
"; $updateUser.="

Update user

"; $updateUser.="
"; $updateUser.=enumerateUsers($aConnection, $session)."
"; $updateUser.="Operator
"; $updateUser.=" "; $updateUser.=""; $updateUser.="
"; } my $addServer = ""; my $updateServer = ""; if($privileges==2) { $addServer.="

Add server

"; $addServer.="
"; $addServer.="
"; $addServer.=" "; $addServer.="
"; $addServer.=""; $addServer.="
"; $updateServer.="

Update server

"; $updateServer.="
"; $updateServer.=enumerateServers($aConnection)."
"; $updateServer.="Enabled
"; $updateServer.=""; $updateServer.="
"; } my $addChannel = ""; my $updateChannel = ""; if($privileges==2) { $addChannel.="

Add channel

"; $addChannel.="
"; $addChannel.=" at "; $addChannel.="
"; $addChannel.="Public
"; $addChannel.=""; $addChannel.="
"; $updateChannel.="

Update channel

"; $updateChannel.="
"; $updateChannel.=enumerateChannels($aConnection)."
"; $updateChannel.="Public
"; $updateChannel.="Enabled
"; $updateChannel.=""; $updateChannel.="
"; } frontend::sendTemplate("templates/panel.html", $aClient, { "username"=>$session->{"username"}, "manageChannelAccess"=>$manageChannelAccess, "addUser"=>$addUser, "updateUser"=>$updateUser, "addServer"=>$addServer, "updateServer"=>$updateServer, "addChannel"=>$addChannel, "updateChannel"=>$updateChannel }); return 1; } when("/change_password_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 $session = $frontend_session::sessions{$aRequest->{"cookies"}{"session"}}; my %parameters = frontend::parsePathParameters($aRequest->{"content"}); if(!defined($parameters{"currentPassword"})) { frontend::sendBadRequest($aClient, "Current password parameter required"); return 1; } if(!defined($parameters{"newPassword"})) { frontend::sendBadRequest($aClient, "New password parameter required"); return 1; } my $query = $aConnection->prepare(qq(select password from users where name=?;)); $query->execute($session->{"username"}); my @row = $query->fetchrow_array(); my $password = $row[0]; if($password ne Digest::SHA::sha256_hex($parameters{"currentPassword"})) { frontend::sendBadRequest($aClient, "Wrong password"); return 1; } if($parameters{"newPassword"} eq $password) { frontend::sendBadRequest($aClient, "New password and current password match"); return 1; } $query = $aConnection->prepare(qq(update users set password=? where name=?;)); $query->execute(Digest::SHA::sha256_hex($parameters{"newPassword"}), $session->{"username"}); frontend::redirect($aClient, "/password_changed.html"); return 1; } when("/delete_account_action") { if(!defined($aRequest->{"cookies"}{"session"}) || !frontend_session::isValidSession($aRequest->{"cookies"}{"session"})) { frontend::redirect($aClient, "/"); return 1; } my $session = $frontend_session::sessions{$aRequest->{"cookies"}{"session"}}; my %parameters = frontend::parsePathParameters($aRequest->{"content"}); if(!defined($parameters{"password"})) { frontend::sendBadRequest($aClient, "Password parameter required"); return 1; } my $query = $aConnection->prepare(qq(select id, password from users where name=?;)); $query->execute($session->{"username"}); my @row = $query->fetchrow_array(); my $id = $row[0]; my $password = $row[1]; if($id==0) { frontend::sendBadRequest($aClient, "Cannot delete user with ID 0 (admin)"); return 1; } if($password ne Digest::SHA::sha256_hex($parameters{"password"})) { frontend::sendBadRequest($aClient, "Wrong password"); return 1; } frontend::deleteUser($id, $aConnection); frontend_session::deleteSession($aRequest->{"cookies"}{"session"}); frontend::redirect($aClient, "/account_deleted.html"); return 1; } when("/manage_access_action") { if(!verifyRequestPrivileges($aRequest, $aClient, 1, $aConnection)) { return 1; } my %parameters = frontend::parsePathParameters($aRequest->{"content"}); if(!defined($parameters{"user"}) || length($parameters{"user"})==0) { frontend::sendBadRequest($aClient, "User required"); return 1; } if(!defined($parameters{"channel"}) || length($parameters{"channel"})==0) { frontend::sendBadRequest($aClient, "Channel required"); return 1; } if(defined($parameters{"grant"})) { my $query = $aConnection->prepare(qq(select id from channels where id=?;)); $query->execute($parameters{"channel"}); my @row = $query->fetchrow_array(); if(scalar(@row)==0) { frontend::sendBadRequest($aClient, "Channel with ID $parameters{'channel'} doesn't exist"); return 1; } if($row[0]==1) { frontend::sendBadRequest($aClient, "Channel with ID $parameters{'channel'} is public"); return 1; } $query = $aConnection->prepare(qq(select id from users where id=?;)); $query->execute($parameters{"user"}); @row = $query->fetchrow_array(); if(scalar(@row)==0) { frontend::sendBadRequest($aClient, "User with ID $parameters{'user'} doesn't exist"); return 1; } $query = $aConnection->prepare(qq(select user_id from accessors where user_id=? and channel_id=?;)); $query->execute($parameters{"user"}, $parameters{"channel"}); @row = $query->fetchrow_array(); if(scalar(@row)>0) { frontend::sendBadRequest($aClient, "User with ID $parameters{'user'} already has access to channel with ID $parameters{'channel'}"); return 1; } $query = $aConnection->prepare(qq(insert into accessors values(?, ?);)); $query->execute($parameters{"user"}, $parameters{"channel"}); frontend::redirect($aClient, "/channel_access_granted.html"); } elsif(defined($parameters{"revoke"})) { my $query = $aConnection->prepare(qq(select id from channels where id=?;)); $query->execute($parameters{"channel"}); my @row = $query->fetchrow_array(); if(scalar(@row)==0) { frontend::sendBadRequest($aClient, "Channel with ID $parameters{'channel'} doesn't exist"); return 1; } $query = $aConnection->prepare(qq(select id from users where id=?;)); $query->execute($parameters{"user"}); @row = $query->fetchrow_array(); if(scalar(@row)==0) { frontend::sendBadRequest($aClient, "User with ID $parameters{'user'} doesn't exist"); return 1; } $query = $aConnection->prepare(qq(select user_id from accessors where user_id=? and channel_id=?;)); $query->execute($parameters{"user"}, $parameters{"channel"}); @row = $query->fetchrow_array(); if(scalar(@row)==0) { frontend::sendBadRequest($aClient, "User with ID $parameters{'user'} doesn't have access to channel with ID $parameters{'channel'}"); return 1; } $query = $aConnection->prepare(qq(delete from accessors where user_id=? and channel_id=?;)); $query->execute($parameters{"user"}, $parameters{"channel"}); frontend::redirect($aClient, "/channel_access_revoked.html"); } else { frontend::sendBadRequest($aClient, "Action (grant or revoke) required"); } return 1; } when("/add_user_action") { if(!verifyRequestPrivileges($aRequest, $aClient, 1, $aConnection)) { return 1; } my %parameters = frontend::parsePathParameters($aRequest->{"content"}); if(!defined($parameters{"name"}) || length($parameters{"name"})==0) { frontend::sendBadRequest($aClient, "Username required"); return 1; } if(!defined($parameters{"password"}) || length($parameters{"password"})==0) { frontend::sendBadRequest($aClient, "Password required"); return 1; } if(!defined($parameters{"confirmPassword"}) || length($parameters{"confirmPassword"})==0) { frontend::sendBadRequest($aClient, "Confirm password required"); return 1; } if($parameters{"password"} ne $parameters{"confirmPassword"}) { frontend::sendBadRequest($aClient, "Password and confirm password don't match"); return 1; } my $query = $aConnection->prepare(qq(select id from users where name=?;)); $query->execute($parameters{"name"}); my @row = $query->fetchrow_array(); if(scalar(@row)>0) { frontend::sendConflict($aClient, "User $parameters{'name'} already exists"); return 1; } frontend::createUser($parameters{"name"}, $parameters{"password"}, defined($parameters{"operator"}), $aConnection); frontend::redirect($aClient, "/user_added.html"); return 1; } when("/update_user_action") { if(!verifyRequestPrivileges($aRequest, $aClient, 1, $aConnection)) { return 1; } my %parameters = frontend::parsePathParameters($aRequest->{"content"}); if(!defined($parameters{"user"}) || length($parameters{"user"})==0) { frontend::sendBadRequest($aClient, "User required"); return 1; } my $query = $aConnection->prepare(qq(select privileges from users where id=?;)); $query->execute($parameters{"user"}); my @row = $query->fetchrow_array(); if(scalar(@row)==0) { frontend::sendBadRequest($aClient, "User with ID $parameters{'user'} doesn't exist"); return 1; } if($row[0]>1 && !verifyRequestPrivileges($aRequest, $aClient, 2, $aConnection)) { return 1; } if(defined($parameters{"update"})) { $query = $aConnection->prepare(qq(update users set privileges=? where id=?;)); $query->execute(defined($parameters{"operator"})?1:0, $parameters{"user"}); } elsif(defined($parameters{"delete"})) { frontend::deleteUser($parameters{"user"}, $aConnection); } else { frontend::sendBadRequest($aClient, "Action (update or delete) required"); return 1; } frontend::redirect($aClient, "/user_updated.html"); return 1; } when("/add_server_action") { if(!verifyRequestPrivileges($aRequest, $aClient, 2, $aConnection)) { return 1; } my %parameters = frontend::parsePathParameters($aRequest->{"content"}); if(!defined($parameters{"name"}) || length($parameters{"name"})==0) { frontend::sendBadRequest($aClient, "Server name required"); return 1; } if(!defined($parameters{"address"}) || length($parameters{"address"})==0) { frontend::sendBadRequest($aClient, "Server address required"); return 1; } my $port = 6667; if(defined($parameters{"port"}) && length($parameters{"port"})>0) { $port = $parameters{"port"}; } my $query = $aConnection->prepare(qq(select id from servers where name=?;)); $query->execute($parameters{"name"}); my @row = $query->fetchrow_array(); if(scalar(@row)>0) { frontend::sendConflict($aClient, "Server with name $parameters{'name'} already exists"); return 1; } $query = $aConnection->prepare(qq(select id from servers order by rowid desc limit 1;)); $query->execute(); @row = $query->fetchrow_array(); my $lastID = 0; if(scalar(@row)>0) { $lastID = $row[0]+1; } $query = $aConnection->prepare(qq(insert into servers values($lastID, ?, ?, ?, 1);)); $query->execute($parameters{"name"}, $parameters{"address"}, $port); frontend::redirect($aClient, "/server_added.html"); logger::createLogger($parameters{"name"}, $parameters{"address"}, $port, ()); return 1; } when("/update_server_action") { if(!verifyRequestPrivileges($aRequest, $aClient, 2, $aConnection)) { return 1; } my %parameters = frontend::parsePathParameters($aRequest->{"content"}); if(!defined($parameters{"server"}) || length($parameters{"server"})==0) { frontend::sendBadRequest($aClient, "Server required"); return 1; } my $query = $aConnection->prepare(qq(select name, host, port, enabled from servers where id=?;)); $query->execute($parameters{"server"}); my @row = $query->fetchrow_array(); if(scalar(@row)==0) { frontend::sendBadRequest($aClient, "Server with ID $parameters{'server'} doesn't exist"); return 1; } my $server = $row[0]; my $serverEnabled = $row[3]; if(defined($parameters{"enabled"}) && !$serverEnabled) { my $host = $row[1]; my $port = $row[2]; $query = $aConnection->prepare(qq(select name, enabled from channels where server_id=?;)); $query->execute($parameters{"server"}); my @channels; while(@row = $query->fetchrow_array()) { if(!$row[1]) { next; } push(@channels, $row[0]); } logger::createLogger($server, $host, $port, \@channels); } elsif($serverEnabled) { my $actionQueue = logger::getActionQueueByServerName($server); push(@$actionQueue, "QUIT"); } $query = $aConnection->prepare(qq(update servers set enabled=? where id=?;)); $query->execute(defined($parameters{"enabled"})?1:0, $parameters{"server"}); frontend::redirect($aClient, "/server_updated.html"); return 1; } when("/add_channel_action") { if(!verifyRequestPrivileges($aRequest, $aClient, 2, $aConnection)) { return 1; } my %parameters = frontend::parsePathParameters($aRequest->{"content"}); if(!defined($parameters{"channel"}) || length($parameters{"channel"})==0) { frontend::sendBadRequest($aClient, "Channel name required"); return 1; } if(!defined($parameters{"server"}) || length($parameters{"server"})==0) { frontend::sendBadRequest($aClient, "Server ID required"); return 1; } my $query = $aConnection->prepare(qq(select name from servers where id=?;)); $query->execute($parameters{"server"}); my @row = $query->fetchrow_array(); if(scalar(@row)==0) { frontend::sendBadRequest($aClient, "Invalid server ID"); return 1; } my $serverName = $row[0]; $query = $aConnection->prepare(qq(select id from channels where name=? and server_id=?;)); $query->execute($parameters{"channel"}, $parameters{"server"}); @row = $query->fetchrow_array(); $parameters{"channel"}=~s/%23/#/; if(scalar(@row)>0) { frontend::sendConflict($aClient, "Channel $parameters{'channel'} already exists on server $serverName"); return 1; } $query = $aConnection->prepare(qq(select id from channels order by rowid desc limit 1;)); $query->execute(); @row = $query->fetchrow_array(); my $lastID = 0; if(scalar(@row)>0) { $lastID = $row[0]+1; } $query = $aConnection->prepare(qq(insert into channels values($lastID, ?, ?, ?, 1);)); $query->execute($parameters{"server"}, $parameters{"channel"}, defined($parameters{"public"})?1:0); my $actionQueue = logger::getActionQueueByServerName($serverName); push(@$actionQueue, "JOIN", $parameters{"channel"}); frontend::redirect($aClient, "/channel_added.html"); return 1; } when("/update_channel_action") { if(!verifyRequestPrivileges($aRequest, $aClient, 2, $aConnection)) { return 1; } my %parameters = frontend::parsePathParameters($aRequest->{"content"}); if(!defined($parameters{"channel"}) || length($parameters{"channel"})==0) { frontend::sendBadRequest($aClient, "Channel required"); return 1; } my $query = $aConnection->prepare(qq(select name, server_id, enabled from channels where id=?;)); $query->execute($parameters{"channel"}); my @row = $query->fetchrow_array(); if(scalar(@row)==0) { frontend::sendBadRequest($aClient, "Channel with ID $parameters{'channel'} doesn't exist"); return 1; } my $channel = $row[0]; my $channelEnabled = $row[2]; $query = $aConnection->prepare(qq(select name from servers where id=?;)); $query->execute($row[1]); @row = $query->fetchrow_array(); my $actionQueue = logger::getActionQueueByServerName($row[0]); if(defined($parameters{"enabled"}) && !$channelEnabled) { push(@$actionQueue, "JOIN", $channel); } elsif($channelEnabled) { push(@$actionQueue, "PART", $channel); } $query = $aConnection->prepare(qq(update channels set public=?, enabled=? where id=?;)); $query->execute(defined($parameters{"public"})?1:0, defined($parameters{"enabled"})?1:0, $parameters{"channel"}); frontend::redirect($aClient, "/channel_updated.html"); 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, channels.public, 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]; $channelName =~ s/%23/#/; my $channelPublic = $row[1]; if(!$channelPublic && !verifyChannelAccess($aRequest, $aClient, $aConnection, $channelID)) { return 1; } my $serverName = $row[2]; 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, channels.public, 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]; $channelName =~ s/%23/#/; my $channelPublic = $row[1]; if(!$channelPublic && !verifyChannelAccess($aRequest, $aClient, $aConnection, $channelID)) { return 1; } my $serverName = $row[2]; 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;