Skip to content

Instantly share code, notes, and snippets.

@Jiab77
Last active July 8, 2022 02:10
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Jiab77/b7eff1dc6c0996b339c753c82e9daa42 to your computer and use it in GitHub Desktop.
Save Jiab77/b7eff1dc6c0996b339c753c82e9daa42 to your computer and use it in GitHub Desktop.
Using GoAccess with PHP

Using GoAccess with PHP

This file will contain instructions to run goaccess from a PHP instance.

For more details on GoAccess check these links:

Installation

For this project, I'm using a compiled version of GoAccess with enabled options to reduce the memory usage.

Install dependencies

This is the package list for Ubuntu 18.04 based distrib.

sudo apt install libncursesw5-dev libglib2.0-dev libgeoip-dev libtokyocabinet-dev libbz2-dev libssl1.0-dev

Download the latest version

I'm using version 1.3 of GoAccess which is the latest at the time I'm writing this gist.

wget https://tar.goaccess.io/goaccess-1.3.tar.gz
tar -xzvf goaccess-1.3.tar.gz

Compilation

Now you got everything you need, you can proceed to the compilation.

cd goaccess-1.3/
./configure --enable-utf8 --enable-geoip=legacy --enable-tcb=btree --with-openssl
make -j $(nproc)

The compilation should be not very long but that would depend on your device capabilities.

Install the compiled version

Once the compilation finished, you can install GoAccess on your system.

sudo make install

Firewall

The default running port of goaccess is 7890. This port should be open in your firewall config.

If your server is virtualized, make sure that the port is forwarded from the host to the guest VM.

Add port using UFW

sudo ufw allow 7890 comment "GoAccess"

Remove port using UFW

sudo ufw delete allow 7890 comment "GoAccess"

Add port range using UFW

For my testing, I needed a port range 7890:7899.

sudo ufw allow from any to any port 7890:7899 proto tcp comment "GoAccess"

Delete port range using UFW

To remove the created port range 7890:7899.

sudo ufw delete allow from any to any port 7890:7899 proto tcp comment "GoAccess"

Notice the delete argument on delete commands. This is the easiest way to remove UFW entries.

Display UFW config

To display the actual UFW config, you can run two commands:

Verbose output

sudo ufw status verbose

Numbered output

sudo ufw status numbered

Script

The given PHP script goaccess.php will generate a web interface with all discovered log files.

image

Generated Report

Here is a screenshot of the generated report for my default host.

image

Setup

To run the PHP script goaccess.php on your server, you will need to do some minor changes.

This is required only for my own script based on goaccess.

Nobody should follow these instructions if nobody is using my script.

Reports folder

You will need to create the destination folder, where all generated reports will be stored and read.

# Create destination folder
sudo mkdir -v /var/www/html/reports

# Assign required permissions
sudo setfacl -m u:www-data:rwx /var/www/html/reports

# To display assigned permissions
getfacl /var/www/html/reports/

Script configuration

The file goaccess.php need some initial configuration. Please edit the following lines:

// Global config
$timeout = 10;
$start_port = 7890;
$end_port = 7899;
$reports = '/var/www/html/reports/';
$apache_logs = '/var/log/apache2';
$goaccess = '/usr/local/bin/goaccess';

Make sure that the given $start_port and $end_port are corresponding to the range specified in the firewall configuration.

The $reports path must have write permissions granted to the apache2 user.

Permissions

By default the main access.log file is protected and the default apache2 and PHP processes don't have access to it.

I've found two ways to give them access to this file but one of them would grant way too much powers to apache2 and PHP...

There are even more dangerous ways to give apache2 access to the system but I won't explain them.

They are considered as dangerous for many reasons.

1. Low security risk way

Using ACL's to limit apache2 filesystem access.

# Grant 'read' over the main log folder contents
sudo setfacl -R -m u:www-data:r /var/log/apache2

# Grant 'read' and 'crossing' access over the main log folder
sudo setfacl -m u:www-data:r-x /var/log/apache2

# Grant 'read' and 'crossing' access over sub log folders
find /var/log/apache2 -type d -name "*.*" -exec sudo setfacl -m u:www-data:r-x {} \;

To display defined ACL's on the filesystem:

getfacl -R /var/log/apache2

To remove defined ACL's from the filesystem:

sudo setfacl -R -x u:www-data /var/log/apache2

This is the prefered way to do.

2. Moderate security risk way

Add apache2 running user to the adm group.

sudo usermod -a -G adm www-data

To remove from the adm group:

sudo deluser www-data adm

All users from the adm group have access to all log files and can do some monitoring actions.

See here for more details: https://wiki.debian.org/SystemGroups

This is why this method is considered as moderate risk and should be used only if the low risk method does not work.

Apply changes

To let the servers know that filesystem permissions has changed, you need to restart running services.

sudo systemctl restart apache2 php7.1-fpm

Change the version of php-fpm according to the one running on your system.

Check

To check if everything is working correctly, you can try to access to the page generated by the PHP script.

Open your browser to this address: http://server-ip/goaccess.php.

Replace server-ip by your server IP address or server name.

Limitations

The PHP script goaccess.php can only be placed at the root of the web server.

I'm actually trying to find a way to make it running from everywhere on the web server.

The actual version of the script does not check for any existing goaccess running processes. This might be fixed in the futures versions.

Issues

Sometimes the script won't work and will display an error page with debug info instead of the HTML report.

  • Permissions on the file access.log has changed.
    • Cause: This is due to the log rotation, for now I have no idea how to fix it safely.
    • Solution: sudo setfacl -m u:www-data:r /var/log/apache2/access.log
  • Permissions on the folder /var/www/html/reports are not correct.
    • Cause: Error during the initial setup.
    • Solution: sudo setfacl -m u:www-data:rwx /var/www/html/reports
  • Timeout issue.
    • Cause: The generated command line takes too long to be executed.
    • Solution: Increase value defined in the PHP script, $timeout.
  • Port already used.
    • Cause: The generated command has partially crashed and the defined port stays used.
    • Solution: Kill the existing process.
      • pstree -pst | grep -i goaccess (Display as process tree)
      • ps aux | grep -v grep | grep -i goaccess (Display as process list)
      • sudo pkill [pid] (Kill the found process id)
      • sudo killall -KILL goaccess (Kill all existing goaccess instances)
    • Solution: Run the clean script.
      • goaccess-clean.sh (It will ask for sudo password)

Clean script

To clean everything related to this project on the server, I just wrote a quick script to do the job.

#!/bin/bash

echo "Killing all existing GoAccess instances..."
sudo killall -KILL goaccess

echo "Removing all existing GoAccess reports..."
sudo rm -fv /var/www/html/reports/*.html

echo "Removing all existing GoAccess pipe files..."
sudo rm -fv /tmp/wspipe*

echo "Removing all existing GoAccess data files..."
sudo rm -Rfv /tmp/goaccess*

echo "Check for existing GoAccess instances in memory..."
ps aux | grep -v grep | grep -i goaccess

echo "Done."
echo ""

Save it as goaccess-clean.sh and make it executable: chmod -v u+x goaccess-clean.sh.

<?php
// Global config
$timeout = 30;
$debug = (isset($_GET['d']) ? filter_input(INPUT_GET, 'd', FILTER_VALIDATE_BOOLEAN) : false);
$start_port = 7890;
$end_port = 7899;
$reports = '/var/www/html/reports/';
$base_url = 'http://' . gethostbyname($_SERVER['HTTP_HOST']) . '/reports/';
$report_url = '';
$apache_logs = '/var/log/apache2';
$goaccess = '/usr/local/bin/goaccess';
if (!function_exists('get_loading_time')) {
// Return used loading time
function get_loading_time() {
return number_format(microtime(true) - $_SERVER["REQUEST_TIME_FLOAT"], 4);
}
}
if (!function_exists('sanitize')) {
// Sanitize external data, never trust the user...
// v2
function sanitize($string, $html = false, $extra = false) {
if (isset($string) && !empty($string)) {
// Remove all HTML tags
if ($html === true) {
// Convert all possible chars to HTML entites
$string = htmlentities(strip_tags(trim($string)), ENT_QUOTES, 'UTF-8');
}
else {
// Convert all special chars to HTML entites
$string = htmlspecialchars(strip_tags(trim($string)), ENT_QUOTES, 'UTF-8');
}
// Extra clean
if ($extra === true) {
// Potentialy dangerous items
$danger = ["'", '"', '`', '../', '..\\', 'javascript:', 'script'];
// Safe replacement
$replace = '';
// Cleaning
$string = str_replace($danger, $replace, $string);
}
return $string;
}
return false;
}
}
// Process given website / action
if (isset($_GET['site']) && !empty($_GET['site'])) {
// Local config
$site = htmlentities(strip_tags($_GET['site']));
$report_file = '';
$cmdline = '';
// Clean all generated files
function clean($path, $verbose = false) {
foreach (glob($path) as $garbage) {
if ($verbose) {
echo 'Removing file "' . $garbage . '"...<br>' . PHP_EOL;
}
@unlink($garbage);
}
foreach (glob(sys_get_temp_dir() . '/goaccess*', GLOB_ONLYDIR) as $garbage_dir) {
foreach (glob($garbage_dir . '/*') as $garbage_file) {
if ($verbose) {
echo 'Removing file "' . $garbage_file . '"...<br>' . PHP_EOL;
}
@unlink($garbage_file);
}
if ($verbose) {
echo 'Removing directory "' . $garbage_dir . '"...<br>' . PHP_EOL;
}
@rmdir($garbage_dir);
}
foreach (glob(sys_get_temp_dir() . '/wspipe*') as $garbage) {
if ($verbose) {
echo 'Removing pipe file "' . $garbage . '"...<br>' . PHP_EOL;
}
@unlink($garbage);
}
}
// Remove given report file
function clear_report($report) {
@unlink($report);
}
// Return free port from authorized range
function get_free_port($start, $end, $debug = false) {
$free_port = 0;
for ($i = $start; $i <= $end ; $i++) {
$cmd = 'netstat -tuna | grep ' . $i . ' | grep -i listen';
$test = shell_exec($cmd);
if ($debug === true) {
echo 'Exec "' . $cmd . '"...<br>' . PHP_EOL;
echo '<pre>' . PHP_EOL;
var_dump($test);
echo '</pre>' . PHP_EOL;
}
if (is_null($test)) {
$free_port = (int)$i;
if ($debug === true) {
echo 'Return free port: ' . $free_port . '<br>' . PHP_EOL;
}
break;
}
}
if ($free_port !== 0) {
return $free_port;
}
else {
return false;
}
}
// Check given website / action
if (!empty($site)) {
// Clean all generated files
if ($site === 'clean') {
clean($reports . '*.html', true);
}
// Return free open authorized port
elseif ($site === 'port') {
get_free_port($start_port, $end_port, true);
}
// Return existing goacces version
elseif ($site === 'version') {
echo '<pre>' . PHP_EOL;
echo shell_exec($goaccess . ' --version');
echo '</pre>' . PHP_EOL;
}
// Create report for default apache2 domain
elseif ($site === 'default') {
$report_file = 'report-default.html';
$cmdline = $goaccess . ' ';
// $cmdline .= '--log-file=' . $apache_logs . '/access.log ';
$cmdline .= $apache_logs . '/access.log ';
$cmdline .= '--no-global-config ';
$cmdline .= '--log-format=COMBINED --date-format="%d/%b/%Y" --time-format="%H:%M:%S" ';
$cmdline .= '--anonymize-ip --real-os --keep-db-files --compression bz2 --exclude-ip ::1 ';
$cmdline .= '--fifo-in=/tmp/wspipein-default.fifo --fifo-out=/tmp/wspipeout-default.fifo ';
$cmdline .= '--real-time-html ';
$cmdline .= '--daemonize ';
$cmdline .= '--html-report-title="GoAccess report for default" ';
$cmdline .= '--port=' . get_free_port($start_port, $end_port) . ' ';
$cmdline .= '-o ' . $reports . $report_file;
}
// Create report for given apache2 domain
else {
// Check if exists some log files for the given domain
if (is_dir($apache_logs . '/' . $site)) {
$formatted_site_name = str_replace('.', '-', $site);
$report_file = 'report-' . $formatted_site_name . '.html';
$cmdline = $goaccess . ' ';
// $cmdline .= '--log-file=' . $apache_logs . '/' . $site . '/access.log ';
$cmdline .= $apache_logs . '/' . $site . '/access.log ';
$cmdline .= '--no-global-config ';
$cmdline .= '--log-format=COMBINED --date-format="%d/%b/%Y" --time-format="%H:%M:%S" ';
$cmdline .= '--anonymize-ip --real-os --keep-db-files --compression bz2 --exclude-ip ::1 ';
$cmdline .= '--fifo-in=/tmp/wspipein-' . $formatted_site_name . '.fifo --fifo-out=/tmp/wspipeout-' . $formatted_site_name . '.fifo ';
$cmdline .= '--real-time-html ';
$cmdline .= '--daemonize ';
$cmdline .= '--html-report-title="GoAccess report for ' . $site . '" ';
$cmdline .= '--port=' . get_free_port($start_port, $end_port) . ' ';
$cmdline .= '-o ' . $reports . $report_file;
}
// Ouch, that sucks, nothing found...
else {
echo 'Log directory "' . $apache_logs . '/' . $site . '" does not exists.<br>' . PHP_EOL;
}
}
}
// Define report URL
$report_url = $base_url . $report_file;
// Check generated command line
if (!empty($cmdline)) {
// Clean existing report file
clear_report($reports . $report_file);
// Execute generated command line
if (isset($debug) && filter_var($debug, FILTER_VALIDATE_BOOLEAN)) {
// exec(escapeshellcmd($cmdline) . ' 2>&1 &', $output, $return);
exec(escapeshellcmd($cmdline) . ' 2>&1', $output, $return);
}
else {
// exec(escapeshellcmd($cmdline) . ' >/dev/null 2>/dev/null &', $output, $return);
exec(escapeshellcmd($cmdline) . ' >/dev/null 2>/dev/null', $output, $return);
}
// Minor sleep to be sure that the command was executed
sleep(1);
// Display running status
echo 'Generating report file...<br>' . PHP_EOL;
// Wait until the report file is created...
$run = 0;
while (!is_readable($reports . $report_file) && $run <= $timeout) {
sleep(1);
$run++;
}
// Report file created and readable, redirecting.
if (is_readable($reports . $report_file)) {
header('Location: ' . $report_url);
}
// Error while creating report file, display debug info.
else {
echo 'Can not access to the generated report file. <a href="' . $report_url . '" target="_blank">Try anyway?</a><br>' . PHP_EOL;
echo '<br>Using:<br>' . PHP_EOL;
echo $cmdline . '<br>' . PHP_EOL;
// Advanced debug
// Can reveal private data, use it with caution!
if ($debug === true) {
echo '<br>Debug Mode: <strong style="color: red;">enabled</strong> <em>(Can reveal private data, don\'t keep it enabled)</em><br>' . PHP_EOL;
if (isset($output)) {
echo '<br>Output:<br>' . PHP_EOL;
// var_dump($output);
$lines = 0;
foreach ($output as $line) {
echo $line . '<br>' . PHP_EOL;
$lines++;
}
/* if ($lines === 1) {
$fpid = explode(': ', $output)[1];
echo '<br>Found PID: ' . $fpid . '<br>' . PHP_EOL;
} */
}
if (isset($return)) {
echo 'Return code:<br>' . PHP_EOL;
echo '<pre>' . PHP_EOL;
var_dump($return);
echo '</pre>' . PHP_EOL;
}
$pid = posix_getpid();
$parent_pid = posix_getppid();
echo 'Last error: ' . posix_strerror(posix_get_last_error()) . '<br><br>' . PHP_EOL;
echo 'System:<br>' . PHP_EOL;
echo '<pre>' . PHP_EOL;
print_r(posix_uname());
echo '</pre>' . PHP_EOL;
echo 'Script:<br>' . PHP_EOL;
echo ' - User Name: ' . get_current_user() . '<br>' . PHP_EOL;
echo ' - User ID: ' . getmyuid() . '<br>' . PHP_EOL;
echo '<br>User:<br>' . PHP_EOL;
echo '<pre>' . PHP_EOL;
print_r(posix_getpwuid(getmyuid()));
echo '</pre>' . PHP_EOL;
echo '<br>Env:<br>' . PHP_EOL;
echo ' - Who am I: ' . exec('whoami') . '<br>' . PHP_EOL;
echo ' - Parent PID: ' . $parent_pid . '<br>' . PHP_EOL;
echo ' - Process ID: ' . $pid . '<br>' . PHP_EOL;
echo ' - Process Session ID: ' . posix_getsid($pid) . '<br>' . PHP_EOL;
echo ' - Process group ID: ' . posix_getpgid($pid) . '<br>' . PHP_EOL;
echo ' - User ID: ' . posix_getuid() . '<br>' . PHP_EOL;
/* echo '<pre>' . PHP_EOL;
print_r(posix_getpwuid(posix_getuid()));
echo '</pre>' . PHP_EOL;
echo ' - Login: <br>' . PHP_EOL;
echo '<pre>' . PHP_EOL;
var_dump(posix_getlogin());
echo '</pre>' . PHP_EOL;
echo ' - Effective User ID: ' . posix_geteuid() . '<br>' . PHP_EOL;
echo '<pre>' . PHP_EOL;
print_r(posix_getpwuid(posix_geteuid()));
echo '</pre>' . PHP_EOL;
echo ' - Effective Group ID: ' . posix_getegid() . '<br>' . PHP_EOL;
echo '<pre>' . PHP_EOL;
print_r(posix_getgrgid(posix_getegid()));
echo '</pre>' . PHP_EOL;
echo ' - Error Group ID: 4<br>' . PHP_EOL;
echo '<pre>' . PHP_EOL;
print_r(posix_getgrgid(4));
echo '</pre>' . PHP_EOL;
echo ' - Existing Groups:<br>' . PHP_EOL;
echo '<pre>' . PHP_EOL;
print_r(posix_getgroups());
echo '</pre>' . PHP_EOL; */
if (!empty($site)) {
if ($site === 'default') {
echo '<br>Access:<br>' . PHP_EOL;
echo ' - File: ' . $apache_logs . '/access.log<br>' . PHP_EOL;
echo ' - Exist:<br>' . PHP_EOL;
echo '<pre>' . PHP_EOL;
var_dump(posix_access($apache_logs . '/access.log', POSIX_F_OK));
echo '</pre>' . PHP_EOL;
echo ' - Read:<br>' . PHP_EOL;
echo '<pre>' . PHP_EOL;
var_dump(posix_access($apache_logs . '/access.log', POSIX_R_OK));
echo '</pre>' . PHP_EOL;
echo ' - Write:<br>' . PHP_EOL;
echo '<pre>' . PHP_EOL;
var_dump(posix_access($apache_logs . '/access.log', POSIX_W_OK));
echo '</pre>' . PHP_EOL;
}
else {
echo '<br>Access:<br>' . PHP_EOL;
echo ' - File: ' . $apache_logs . '/' . $site . '/access.log<br>' . PHP_EOL;
echo ' - Exist:<br>' . PHP_EOL;
echo '<pre>' . PHP_EOL;
var_dump(posix_access($apache_logs . '/' . $site . '/access.log', POSIX_F_OK));
echo '</pre>' . PHP_EOL;
echo ' - Read:<br>' . PHP_EOL;
echo '<pre>' . PHP_EOL;
var_dump(posix_access($apache_logs . '/' . $site . '/access.log', POSIX_R_OK));
echo '</pre>' . PHP_EOL;
echo ' - Write:<br>' . PHP_EOL;
echo '<pre>' . PHP_EOL;
var_dump(posix_access($apache_logs . '/' . $site . '/access.log', POSIX_W_OK));
echo '</pre>' . PHP_EOL;
}
echo ' - File: ' . $reports . $report_file . '<br>' . PHP_EOL;
echo ' - Exist:<br>' . PHP_EOL;
echo '<pre>' . PHP_EOL;
var_dump(posix_access($reports . $report_file, POSIX_F_OK));
echo '</pre>' . PHP_EOL;
echo ' - Read:<br>' . PHP_EOL;
echo '<pre>' . PHP_EOL;
var_dump(posix_access($reports . $report_file, POSIX_R_OK));
echo '</pre>' . PHP_EOL;
echo ' - Write:<br>' . PHP_EOL;
echo '<pre>' . PHP_EOL;
var_dump(posix_access($reports . $report_file, POSIX_W_OK));
echo '</pre>' . PHP_EOL;
}
}
echo '<br>Process Tree:<br>' . PHP_EOL;
echo '<pre>' . PHP_EOL;
passthru('pstree -pst | grep goaccess');
echo '</pre>' . PHP_EOL;
}
}
}
else {
?>
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Default Metas -->
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta http-equiv="x-dns-prefetch-control" content="on">
<!-- Mobile Support -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- SEO -->
<meta name="author" content="Jonathan Barda (@Jiab77)">
<!-- Robots Metas -->
<meta name="robots" content="noindex,nofollow,nosnippet,noodp,noarchive,noimageindex">
<meta name="google" content="nositelinkssearchbox">
<!-- Pre-Things -->
<link rel="dns-prefetch" href="//cdnjs.cloudflare.com">
<link rel="dns-prefetch" href="//fonts.googleapis.com">
<link rel="dns-prefetch" href="//fonts.gstatic.com">
<link rel="dns-prefetch" href="//www.google.com">
<!-- Import Google Icon Font -->
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" media="all">
<!-- Import FontAwesome Icon Font -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.9.0/css/fontawesome.min.css" media="all">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.9.0/css/brands.min.css" media="all">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.9.0/css/solid.min.css" media="all">
<!-- Import Normalizecss -->
<link type="text/css" rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css" media="all">
<!-- Import Materialize -->
<link type="text/css" rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/css/materialize.min.css" media="screen,projection">
<!-- Import Style -->
<link type="text/css" rel="stylesheet" href="/cms-base/admin/main.css" media="all">
<title>GoAccess Realtime Reports</title>
<style>
body {
display: flex;
min-height: 100vh;
flex-direction: column;
}
main {
flex: 1 0 auto;
min-height: 50vh;
}
i.material-icons {
vertical-align: middle;
}
.fa-anim {
-webkit-transition: font-size .4s;
transition: font-size .4s;
}
.parallax-container {
height: 50vh;
}
blockquote {
border-left-color: #0091ea;
}
</style>
</head>
<body>
<header>
<div class="navbar-fixed">
<nav class="grey darken-4">
<div class="nav-wrapper">
<a class="brand-logo" href="<?php echo sanitize($_SERVER['PHP_SELF'], true, true); ?>"><i class="material-icons hide-on-med-and-down">assessment</i>GoAccess Realtime Reports</a>
<ul class="right hide-on-med-and-down">
<li><a href="#!" class="tooltipped" data-position="bottom" data-tooltip="Refresh" onclick="window.location.reload();"><i class="material-icons">refresh</i></a></li>
<li><a href="https://gist.github.com/Jiab77/b7eff1dc6c0996b339c753c82e9daa42" rel="noreferrer" class="tooltipped" data-position="bottom" data-tooltip="Fork me on github" target="_blank"><i class="fab fa-github-alt fa-anim" onmouseover="$(this).addClass('fa-2x');" onmouseout="$(this).removeClass('fa-2x');"></i></a></li>
</ul>
</div>
</nav>
</div>
</header>
<main>
<div class="container">
<div class="row">
<div class="col s12">
<p class="flow-text">List of available reports.</p>
<fieldset>
<legend>Reports</legend>
<table class="highlight">
<thead>
<tr>
<th>Host</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<?php
$table_content = '';
$table_content .= '<tr>' . PHP_EOL;
$table_content .= '<td>' . PHP_EOL;
$table_content .= '<a href="http://' . gethostbyname($_SERVER['SERVER_NAME']) . '/" target="_blank"><i class="material-icons tiny">public</i> default</a>' . PHP_EOL;
$table_content .= '<span class="tooltipped" style="cursor: default;" data-position="right" data-tooltip="This link will be opened in new window"><i class="material-icons tiny">launch</i></span>' . PHP_EOL;
$table_content .= '</td>' . PHP_EOL;
$table_content .= '<td>' . PHP_EOL;
$table_content .= '<a href="?site=default" target="_blank"><i class="material-icons tiny">assessment</i> View report</a>' . PHP_EOL;
$table_content .= '<span class="tooltipped" style="cursor: default;" data-position="right" data-tooltip="This link will be opened in new window"><i class="material-icons tiny">launch</i></span>' . PHP_EOL;
$table_content .= '</td>' . PHP_EOL;
$table_content .= '</tr>' . PHP_EOL;
foreach (glob($apache_logs . '/*', GLOB_ONLYDIR) as $dir) {
$table_content .= '<tr>' . PHP_EOL;
$table_content .= '<td>' . PHP_EOL;
$table_content .= '<a href="http://' . basename($dir) . '/" target="_blank"><i class="material-icons tiny">public</i> ' . basename($dir) . '</a>' . PHP_EOL;
$table_content .= '<span class="tooltipped" style="cursor: default;" data-position="right" data-tooltip="This link will be opened in new window"><i class="material-icons tiny">launch</i></span>' . PHP_EOL;
$table_content .= '</td>' . PHP_EOL;
$table_content .= '<td>' . PHP_EOL;
$table_content .= '<a href="?site=' . basename($dir) . '" target="_blank"><i class="material-icons tiny">assessment</i> View report</a>' . PHP_EOL;
$table_content .= '<span class="tooltipped" style="cursor: default;" data-position="right" data-tooltip="This link will be opened in new window"><i class="material-icons tiny">launch</i></span>' . PHP_EOL;
$table_content .= '</td>' . PHP_EOL;
$table_content .= '</tr>' . PHP_EOL;
}
echo $table_content;
?>
</tbody>
</table>
</fieldset>
</div>
</div>
<div class="row">
<div class="col s12">
<p class="flow-text">List of available actions.</p>
<fieldset>
<legend>Actions</legend>
<table class="highlight">
<thead>
<tr>
<th>Title</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr>
<td>Display installed version</td>
<td>
<a href="?site=version" target="_blank"><i class="material-icons tiny">code</i> Execute</a>
<span class="tooltipped" style="cursor: default;" data-position="right" data-tooltip="This link will be opened in new window"><i class="material-icons tiny">launch</i></span>
</td>
</tr>
<tr>
<td>Clean generated files</td>
<td>
<a href="?site=clean" target="_blank"><i class="material-icons tiny">code</i> Execute</a>
<span class="tooltipped" style="cursor: default;" data-position="right" data-tooltip="This link will be opened in new window"><i class="material-icons tiny">launch</i></span>
</td>
</tr>
<tr>
<td>Find free open port</td>
<td>
<a href="?site=port" target="_blank"><i class="material-icons tiny">code</i> Execute</a>
<span class="tooltipped" style="cursor: default;" data-position="right" data-tooltip="This link will be opened in new window"><i class="material-icons tiny">launch</i></span>
</td>
</tr>
</tbody>
</table>
</fieldset>
</div>
</div>
</div>
</main>
<footer class="page-footer grey darken-3">
<div class="container">
<div class="row">
<div class="col l8 s12">
<h5 class="white-text">Loading time</h5>
<p class="grey-text text-lighten-4"><?php echo 'Generated in: ' . get_loading_time() . ' seconds'; ?></p>
</div>
<div class="col l2 offset-l2 s12">
<h5 class="white-text">Links</h5>
<ul>
<li><a class="grey-text text-lighten-3" href="https://gist.github.com/Jiab77/b7eff1dc6c0996b339c753c82e9daa42" rel="noreferrer" target="_blank"><i class="material-icons tiny">code</i> Project</a></li>
<li><a class="grey-text text-lighten-3" href="https://github.com/Jiab77" rel="noreferrer" target="_blank"><i class="fab fa-github"></i> Profile</a></li>
<li><a class="grey-text text-lighten-3" href="https://gist.github.com/Jiab77" rel="noreferrer" target="_blank"><i class="material-icons tiny">library_books</i> Gists</a></li>
<li><a class="grey-text text-lighten-3" href="https://twitter.com/jiab77" rel="noreferrer" target="_blank"><i class="fab fa-twitter"></i> Twitter</a></li>
<li><a class="grey-text text-lighten-3" href="https://goaccess.io/" rel="noreferrer" target="_blank"><i class="fas fa-chart-bar"></i> GoAccess</a></li>
</ul>
</div>
</div>
</div>
<div class="footer-copyright grey darken-4">
<div class="container">
<?php echo '&copy; ' . date("Y") . ' &ndash; <a href="https://twitter.com/jiab77" rel="noreferrer" target="_blank">Jiab77</a>' . PHP_EOL; ?>
<span class="grey-text text-lighten-4 right">Made with <span class="pink-text text-accent-3 tooltipped" data-position="top" data-tooltip="love" style="cursor: default;"><i class="material-icons">favorite</i></span> of <span class="white-text tooltipped" data-position="top" data-tooltip="code" style="cursor: default;"><i class="material-icons">code</i></span> and <span class="brown-text text-accent-3 tooltipped" data-position="top" data-tooltip="coffee" style="cursor: default;"><i class="material-icons">local_cafe</i></span></span>
</div>
</div>
</footer>
<script type="text/javascript" id="jquery-js" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
<script type="text/javascript" id="materialize-js" src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/js/materialize.min.js"></script>
<script type="text/javascript" id="main-js">
"use strict";
// Boot stuff when DOM is loaded
$(function (event) {
console.group('App');
console.info('DOM Loaded.', event);
// $(".button-collapse").sideNav();
// $('.materialboxed').materialbox();
// $('.scrollspy').scrollSpy();
// $('.parallax').parallax();
$('.tooltipped').tooltip({delay: 50});
// $('.modal').modal({
// dismissible: true, // Modal can be dismissed by clicking outside of the modal
// opacity: .5, // Opacity of modal background
// inDuration: 300, // Transition in duration
// outDuration: 200, // Transition out duration
// startingTop: '4%', // Starting top style attribute
// endingTop: '10%', // Ending top style attribute
// ready: function(modal, trigger) { // Callback for Modal open. Modal and trigger parameters available.
// console.log('Modal -- Open', modal, trigger);
// },
// complete: function() { // Callback for Modal close
// console.log('Modal -- Close');
// }
// });
// $('.dropdown-button').dropdown({
// inDuration: 300,
// outDuration: 225,
// constrainWidth: false, // Does not change width of dropdown to that of the activator
// hover: true, // Activate on hover
// gutter: 0, // Spacing from edge
// belowOrigin: false, // Displays dropdown below the button
// alignment: 'left', // Displays dropdown with edge aligned to the left of button
// stopPropagation: false // Stops event propagation
// });
// $('.collapsible').collapsible({
// accordion: false, // A setting that changes the collapsible behavior to expandable instead of the default accordion style
// onOpen: function(el) { console.log('Collapsible -- Open', el); }, // Callback for Collapsible open
// onClose: function(el) { console.log('Collapsible -- Close', el); } // Callback for Collapsible close
// });
// Disable click on empty links
$('a[href="#!"]').on('click', function (event) {
event.preventDefault();
});
// Toggle container
// $('#toggle-container').on('click', function (event) {
// event.preventDefault();
// $('#dyn-container').toggleClass('container');
// });
// Display progress bar
// $('.progress').eq(0).show('slow');
console.groupEnd();
});
</script>
</body>
</html>
<?php
}
?>
@Jiab77
Copy link
Author

Jiab77 commented Aug 8, 2019

I'm sorry about the PHP file indentation, I was not able to set it up correctly from here. 😞

@Jiab77
Copy link
Author

Jiab77 commented Sep 4, 2019

Updated the code to fix bugs and security issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment