Commit 50de65ef authored by Hugo Leisink's avatar Hugo Leisink

Release 1.6

parent ae94ce61
monitor (1.6) stable; urgency=low
* Stronger password encryption.
* Bugfix: reports weren't filtered per webserver.
* Small improvements.
-- Hugo Leisink <hugo@leisink.net> Tue, 11 Sep 2018 20:28:41 +0200
monitor (1.5) stable; urgency=low
* Integrated Hiawatha weblog in dashboard.
* Added hour selector to filter.
* Changed value unity from percentage to factor.
* Small improvements and bugfixes.
-- Hugo Leisink <hugo@leisink.net> Mon, 17 Apr 2017 12:37:09 +0200
monitor (1.4) stable; urgency=low
* Daily report optimized for mobile devices.
......@@ -18,13 +35,6 @@ monitor (1.2) stable; urgency=low
* Banshee framework updated to 5.0.
* Design made responsive.
* Database changes:
CREATE TABLE `organisations` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(50) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `name` (`name`), UNIQUE KEY `name_2` (`name`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `users` ADD `organisation_id` INT UNSIGNED NOT NULL AFTER `id`, ADD INDEX ( `organisation_id` );
ALTER TABLE `users` ADD `cert_serial` INT UNSIGNED NULL AFTER `one_time_key`;
ALTER TABLE `users` CHANGE `password` `password` VARCHAR( 128 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;
Run 'database/private_pages' to update the table 'roles'.
Run 'database/fix_settings' to add missing settings.
* Small improvements.
-- Hugo Leisink <hugo@leisink.net> Sun, 21 Jun 2015 11:53:02 +0200
......@@ -35,9 +45,6 @@ monitor (1.1) stable; urgency=low
* Hostname selection in CMS per user.
* Improved XML output filter. Add JSON output filter.
* Reports use median instead of average.
* Database changes:
ALTER TABLE `webservers` CHANGE `ssl` `tls` TINYINT(1) NOT NULL;
ALTER TABLE `host_statistics` ADD `failed_logins` INT UNSIGNED NOT NULL AFTER `exploit_attempts`;
* Small bugfixes.
-- Hugo Leisink <hugo@leisink.net> Sun, 10 May 2015 09:47:41 +0200
......
Installation
============
The Hiawatha Monitor has been built upon the Banshee PHP framework. Use the
following steps to install a Banshee based website.
Configure your webserver
------------------------
Use the following Hiawatha configuration for this website.
UrlToolkit {
ToolkitID = monitor
RequestURI isfile Return
Match ^/(css|files|fonts|images|js)(/|$) Return
Match ^/(favicon.ico|robots.txt)$ Return
Match [^?]*(\?.*)? Rewrite /index.php$1
}
VirtualHost {
Hostname = monitor.domain.com
WebsiteRoot = /var/www/monitor/public
StartFile = index.php
AccessLogfile = /var/www/monitor/logfiles/access.log
ErrorLogfile = /var/www/monitor/logfiles/error.log
ExecuteCGI = yes
UseFastCGI = PHP # Use if you use PHP as a FastCGI daemon
TimeForCGI = 15
UseToolkit = monitor
}
Configure PHP
-------------
The Hiawatha Monitor requires at least PHP v5.6 and needs the MySQL and XML/XSLT
PHP modules.
Configure your database
-----------------------
Open the website in your browser and follow the instructions on your screen. In
case of an error, add /setup to the URL.
Configure the Cron daemon
-------------------------
Use the following crontab settings to fetch the information from the webservers
and to send the daily reports:
*/5 * * * * /path/to/monitor/website/database/fetch_webserver_logs
0 0 * * * /path/to/monitor/website/database/delete_old_logs
59 23 * * * /path/to/monitor/website/database/send_reports
Using the Hiawatha Monitor
--------------------------
Login with username 'admin' and password 'monitor' and start adding webservers
in the Webserver Administration page. Add the following line to the
configuration file of your Hiawatha webservers.
MonitorServer = <IP of monitor server>
Don't forget to change the admin password and to check out the settings in the
Settings administration CMS page. When you're done testing, set DEBUG_MODE in
the file settings/website.conf to 'no' and remove the setup module from the
file settings/public_pages.conf.
This diff is collapsed.
UNDERSTAND HOW TO HIAWATHA MONITOR WORKS
=========================================
Read the information at https://www.hiawatha-webserver.org/howto/monitor to understand what the Hiawatha Monitor is and how it works.
CONFIGURE YOUR WEBSERVER
=========================
Use the following Hiawatha configuration for this website.
```
UrlToolkit {
ToolkitID = monitor
RequestURI isfile Return
Match ^/(css|files|fonts|images|js)(/|$) Return
Match ^/(favicon.ico|robots.txt)$ Return
Match [^?]*(\?.*)? Rewrite /index.php$1
}
VirtualHost {
Hostname = monitor.domain.com
WebsiteRoot = /var/www/monitor/public
StartFile = index.php
AccessLogfile = /var/www/monitor/logfiles/access.log
ErrorLogfile = /var/www/monitor/logfiles/error.log
ExecuteCGI = yes
UseFastCGI = PHP5 # Use if you use PHP as a FastCGI daemon
TimeForCGI = 15
UseToolkit = monitor
}
```
CONFIGURE PHP
==============
The Hiawatha Monitor requires the php5-mysql and php5-xsl PHP modules.
Use the following PHP settings:
allow_url_include = Off
cgi.fix_pathinfo = 0 (when using FastCGI PHP), 1 (otherwise)
date.timezone = <your timezone>
magic_quotes_gpc = Off
register_globals = Off
CONFIGURE YOUR DATABASE
========================
Open the website in your browser and follow the instructions on your screen. In case of an error, add /setup to the URL.
CONFIGURE CRON DAEMON
======================
Use the following crontab settings to fetch the information from the webservers and to send the daily reports:
*/5 * * * * /path/to/monitor/website/database/fetch_webserver_logs
0 0 * * * /path/to/monitor/website/database/delete_old_logs
59 23 * * * /path/to/monitor/website/database/send_reports
USING THE HIAWATHA MONITOR
===========================
Login with username 'admin' and password 'monitor' and start adding webservers in the Webserver Administration page. Add "MonitorServer = <IP of monitor server> to the configuration file of your Hiawatha webservers.
Don't forget to change the admin password and to check out the settings in the Settings administration page. When you're done testing, set DEBUG_MODE in settings/website.conf to 'no' and remove the setup module from settings/public_pages.conf.
The Hiawatha Monitor
====================
The Hiawatha Monitor is a monitoring tool for the Hiawatha webserver. It can
be used to keep track of the performance and security of all your Hiawatha
webservers via one single interface. It's not a replacement for analytics
software or the local logfiles, but it gives you a quick and easy overview
of how your webservers are performing and which ones require some attention.
Read the information at https://www.hiawatha-webserver.org/howto/monitor for
compilation instructions for the Hiawatha webserver.
......@@ -7,9 +7,7 @@
$this->output->keywords = "login";
$this->output->title = "Login";
$this->output->add_javascript("banshee/".PASSWORD_HASH.".js");
$this->output->add_javascript("banshee/login.js");
$this->output->run_javascript("set_focus(); hash = window['".PASSWORD_HASH."'];");
$this->output->open_tag("login");
......@@ -25,7 +23,6 @@
}
$this->output->add_tag("remote_addr", $_SERVER["REMOTE_ADDR"]);
$this->output->add_tag("challenge", $_SESSION["challenge"]);
if ($_SERVER["REQUEST_METHOD"] == "POST") {
if (strpos($_POST["username"], "'") !== false) {
......
......@@ -21,14 +21,6 @@
/* Show warnings
*/
if ($this->user->is_admin) {
if (($this->user->id == 1) && ($this->user->password == "610706e9a48f85476e04d270bd6dc7492cdcd9ad7e91878007dff629ab11f195")) {
$this->output->add_system_warning("Don't forget to change the password of the admin account!");
}
if ($this->settings->secret_website_code == "CHANGE_ME_INTO_A_RANDOM_STRING") {
$this->output->add_system_warning("Don't forget to change the secret_website_code setting.");
}
if (is_true(DEBUG_MODE)) {
$this->output->add_system_warning("Website is running in debug mode. Set DEBUG_MODE in settings/website.conf to 'no'.");
}
......
......@@ -51,18 +51,18 @@
$user["webservers"] = array();
}
if (($roles = $this->model->get_roles()) == false) {
if (($roles = $this->model->get_roles()) === false) {
$this->output->add_tag("result", "Database error.");
return;
}
if (($webservers = $this->model->get_all_webservers()) == false) {
if (($webservers = $this->model->get_all_webservers()) === false) {
$this->output->add_tag("result", "Database error.");
return;
}
if ($this->user->is_admin) {
if (($organisations = $this->model->get_organisations()) == false) {
if (($organisations = $this->model->get_organisations()) === false) {
$this->output->add_tag("result", "Database error.");
return;
}
......@@ -78,9 +78,7 @@
}
}
$this->output->add_javascript("banshee/".PASSWORD_HASH.".js");
$this->output->add_javascript("cms/user.js");
$this->output->run_javascript("hash = window['".PASSWORD_HASH."'];");
$this->output->open_tag("edit");
......@@ -137,15 +135,10 @@
public function execute() {
if ($_SERVER["REQUEST_METHOD"] == "POST") {
if ($_POST["submit_button"] == "Save user") {
/* Fix password
/* Generate password
*/
if (is_true($_POST["generate"])) {
$_POST["password"] = random_string(10);
$_POST["password_hashed"] = false;
}
if (is_false($_POST["password_hashed"]) && ($_POST["password"] != "")) {
$_POST["plaintext"] = $_POST["password"];
$_POST["password"] = hash(PASSWORD_HASH, $_POST["password"].hash(PASSWORD_HASH, $_POST["username"]));
}
/* Save user
......
......@@ -34,11 +34,34 @@
foreach ($list as $name => $item) {
$this->output->add_tag("item", $name, array(
"count" => $item["today"],
"change" => $item["change"]));
"change" => sprintf("%0.1f", $item["change"])));
}
$this->output->close_tag();
}
private function show_hiawatha_weblog() {
if ($this->output->fetch_from_cache("weblog")) {
return;
}
$hostname = "www.hiawatha-webserver.org";
$hiawatha_website = new HTTPS($hostname);
if (($result = $hiawatha_website->GET("/weblog?output=xml")) == false) {
return;
}
if (substr($result["headers"]["content-type"], 0, 8) != "text/xml") {
return;
}
$result["body"] = str_replace("&lt;img src=&quot;/", "&lt;img src=&quot;https://".$hostname."/", $result["body"]);
$result["body"] = str_replace("&lt;a href=&quot;/", "&lt;a href=&quot;https://".$hostname."/", $result["body"]);
$this->output->start_caching("weblog", 300);
$this->output->add_xml($result["body"], "weblogs");
$this->output->stop_caching();
}
public function execute() {
if ($this->page->ajax_request) {
if ($this->page->pathinfo[1] == null) {
......@@ -69,6 +92,9 @@
if (($webservers = $this->model->get_webservers()) === false) {
return;
}
if (count($webservers) == 0) {
$this->output->add_system_message("No webservers have been configured yet. ".($this->user->is_admin ? "Add them via the Webserver administration page in the CMS." : "Ask an administrator to add them for you."));
}
$webservers_offline = false;
......@@ -94,7 +120,10 @@
if ($webserver["version"] != "") {
$parts = explode(",", $webserver["version"]);
list(, $version) = explode("v", $parts[0], 2);
$webserver["version"] = array_shift($parts);
$webserver["modules"] = $parts;
list(, $version) = explode("v", $webserver["version"], 2);
$comparison = version_compare($version, $_SESSION["latest_hiawatha_version"], ">=");
$webserver["uptodate"] = show_boolean($comparison);
......@@ -108,11 +137,23 @@
}
}
$this->output->record($webserver, "webserver");
$this->output->open_tag("webserver", array("id" => $webserver["id"]));
$this->output->record($webserver);
if (is_array($webserver["modules"])) {
$this->output->open_tag("modules");
foreach ($webserver["modules"] as $module) {
$this->output->add_tag("module", trim($module));
}
$this->output->close_tag();
}
$this->output->close_tag();
}
if ($webservers_offline) {
$this->output->add_system_message("Warning, one or more webservers are unavailable!");
$this->output->add_system_warning("Warning, one or more webservers are unavailable or caused errors during syncing of the statistics!");
}
/* Alerts
......@@ -124,6 +165,10 @@
$this->output->add_tag("threshold_change", $this->settings->dashboard_threshold_change);
$this->output->add_tag("threshold_value", $this->settings->dashboard_threshold_value);
$this->output->add_tag("page_refresh", $this->settings->dashboard_page_refresh);
if ($this->settings->dashboard_show_weblog) {
$this->show_hiawatha_weblog();
}
}
}
?>
......@@ -12,7 +12,7 @@
$this->output->add_css("banshee/filter.css");
$filter = new filter($this->db, $this->output, $this->user);
$filter->to_output($this->model->table, false);
$filter->to_output($this->model->table, false, false);
if (($count = $this->model->count_events($filter->webserver, $_SERVER["hide_ss"])) === false) {
$this->output->add_tag("result", "Database error.");
......
<?php
class password_controller extends controller {
private function show_password_form($key) {
$this->output->add_javascript("banshee/".PASSWORD_HASH.".js");
$this->output->add_javascript("password.js");
$this->output->run_javascript("hash = window['".PASSWORD_HASH."'];");
$this->output->open_tag("reset");
$this->output->add_tag("key", $key);
$this->output->add_tag("username", $_SESSION["reset_password_username"]);
......@@ -32,7 +28,7 @@
*/
if ($this->model->key_oke($_POST["key"]) == false) {
$this->output->add_tag("request");
} else if ($this->model->password_oke($_SESSION["reset_password_username"], $_POST) == false) {
} else if ($this->model->password_oke($_POST) == false) {
$this->show_password_form($_POST["key"]);
} else if ($this->model->save_password($_SESSION["reset_password_username"], $_POST) == false) {
$this->output->add_message("Error while saving password.");
......
<?php
class profile_controller extends controller {
private function show_profile_form($profile) {
$this->output->add_javascript("banshee/".PASSWORD_HASH.".js");
$this->output->add_javascript("profile.js");
$this->output->run_javascript("hash = window['".PASSWORD_HASH."'];");
$this->output->open_tag("edit");
$this->output->add_tag("username", $this->user->username);
......
......@@ -12,6 +12,8 @@
$this->model->import_sql();
} else if ($_POST["submit_button"] == "Update database") {
$this->model->update_database();
} else if ($_POST["submit_button"] == "Set password") {
$this->model->set_admin_credentials($_POST);
}
}
......@@ -39,6 +41,13 @@
case "update_db":
ob_clean();
break;
case "credentials":
if ($_POST["submit_button"] != "Set password") {
$_POST["username"] = "admin";
}
$this->output->add_tag("username", $_POST["username"]);
ob_clean();
break;
case "done":
break;
}
......
......@@ -19,21 +19,21 @@
/* Server statistics
*/
$query = "delete from server_statistics where date<%s";
$query = "delete from server_statistics where date<=%s";
if ($db->query($query, $date) == false) {
exit("Error deleting server statistics.\n");
}
/* Host statistics
*/
$query = "delete from host_statistics where date<%s";
$query = "delete from host_statistics where date<=%s";
if ($db->query($query, $date) == false) {
exit("Error deleting host statistics.\n");
}
/* CGI statistics
*/
$query = "delete from cgi_statistics where date<%s";
$query = "delete from cgi_statistics where date<=%s";
if ($db->query($query, $date) == false) {
exit("Error deleting CGI statistics.\n");
}
......
......@@ -265,16 +265,16 @@
/* HTTP class extensions
*/
class HTTP_monitor extends HTTP {
public function __call($method, $parameters) {
public function __construct($host, $port = null) {
parent::__construct($host, $port);
$this->host = "monitor";
return parent::__call($method, $parameters);
}
}
class HTTPS_monitor extends HTTPS {
public function __call($method, $parameters) {
public function __construct($host, $port = null) {
parent::__construct($host, $port);
$this->host = "monitor";
return parent::__call($method, $parameters);
}
}
......@@ -311,7 +311,7 @@
$result = $http->GET("/");
if ($result["status"] != 200) {
$db->update("webservers", $webserver_id, array("errors" => $webserver["errors"] + 1));
$event = "Error while getting statistics logfile index from webserver";
$event = "HTTP error while downloading statistics index";
log_event($db, $event, $webserver_id);
if ($debug_mode) {
printf("%s\n", $event);
......@@ -322,20 +322,21 @@
continue;
}
if ($webserver["errors"] != 0) {
$db->update("webservers", $webserver_id, array("errors" => 0));
}
if ($result["headers"]["content-type"] != "text/xml") {
$db->update("webservers", $webserver_id, array("errors" => $webserver["errors"] + 1));
log_event($db, "Invalid Content-Type for statistics index", $webserver_id);
continue;
}
$index = new DomDocument();
if ($index->loadXML($result["body"]) == false) {
$db->update("webservers", $webserver_id, array("errors" => $webserver["errors"] + 1));
log_event($db, "Invalid XML for statistics index", $webserver_id);
continue;
}
$files = $index->getElementsByTagName("file");
$file_error = false;
foreach ($files as $file) {
if ($debug_mode) {
......@@ -343,16 +344,22 @@
}
$result = $http->GET("/".$file->nodeValue);
if ($result["status"] != 200) {
$event = "Error while getting data file from webserver";
$event = "HTTP error while downloading statistics file";
log_event($db, $event, $webserver_id);
if ($debug_mode) {
printf("%s\n", $event);
}
$file_error = true;
continue;
}
if ($result["headers"]["content-type"] == "application/x-gzip") {
if (($result["body"] = gzdecode($result["body"])) === false) {
printf("Invalid gzipped data received from %s.\n", $webserver["name"]);
$event = "GZip error while unpacking statistics file";
log_event($db, $event, $webserver_id);
if ($debug_mode) {
printf("%s\n", $event);
}
$file_error = true;
continue;
}
}
......@@ -386,10 +393,18 @@
$db->update("webservers", $webserver_id, array("version" => $version));
break;
default:
/* For compatibility with Hiawatha version <= 9.4
*/
list($event, $timestamp) = $field;
log_event($db, $event, $webserver_id, (int)$timestamp);
}
}
}
if ($file_error) {
$db->update("webservers", $webserver_id, array("errors" => $webserver["errors"] + 1));
} else if ($webserver["errors"] != 0) {
$db->update("webservers", $webserver_id, array("errors" => 0));
}
}
?>
......@@ -293,7 +293,7 @@ DROP TABLE IF EXISTS `sessions`;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `sessions` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`session_id` varchar(100) NOT NULL,
`session_id` varchar(128) NOT NULL,
`content` text,
`expire` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`user_id` int(10) unsigned DEFAULT NULL,
......@@ -326,7 +326,7 @@ CREATE TABLE `settings` (
LOCK TABLES `settings` WRITE;
/*!40000 ALTER TABLE `settings` DISABLE KEYS */;
INSERT INTO `settings` VALUES (1,'admin_page_size','integer','25'),(2,'page_after_login','string','dashboard'),(3,'start_page','string','dashboard'),(4,'webmaster_email','string','root@localhost'),(5,'head_title','string','Hiawatha Monitor'),(6,'head_description','string','Security and performance monitoring tool for the Hiawatha webserver.'),(7,'head_keywords','string','monitor, hiawatha'),(34,'default_language','string','en'),(42,'session_persistent','boolean','true'),(38,'event_page_size','integer','25'),(39,'top_connections','integer','15'),(46,'hiawatha_cache_default_time','integer','3600'),(43,'session_timeout','integer','38400'),(44,'hiawatha_cache_enabled','boolean','false'),(45,'secret_website_code','string','CHANGE_ME_INTO_A_RANDOM_STRING'),(55,'dashboard_page_refresh','integer','1'),(48,'report_history_days','integer','15'),(49,'report_alert_medium','integer','150'),(50,'report_alert_high','float','3'),(51,'report_use_median','boolean','true'),(52,'report_skip_normal','boolean','true'),(53,'dashboard_threshold_change','integer','150'),(54,'dashboard_threshold_value','integer','10'),(56,'database_version','integer','103');
INSERT INTO `settings` VALUES (1,'admin_page_size','integer','25'),(2,'page_after_login','string','dashboard'),(3,'start_page','string','dashboard'),(4,'webmaster_email','string','root@localhost'),(5,'head_title','string','Hiawatha Monitor'),(6,'head_description','string','Security and performance monitoring tool for the Hiawatha webserver.'),(7,'head_keywords','string','monitor, hiawatha'),(8,'default_language','string','en'),(9,'session_persistent','boolean','true'),(10,'event_page_size','integer','25'),(11,'top_connections','integer','15'),(12,'hiawatha_cache_default_time','integer','3600'),(13,'session_timeout','integer','38400'),(14,'hiawatha_cache_enabled','boolean','false'),(15,'secret_website_code','string','CHANGE_ME_INTO_A_RANDOM_STRING'),(16,'dashboard_page_refresh','integer','1'),(17,'report_history_days','integer','15'),(18,'report_alert_medium','float','2'),(19,'report_alert_high','float','5'),(20,'report_use_median','boolean','true'),(21,'report_skip_normal','boolean','true'),(22,'dashboard_threshold_change','float','2.5'),(23,'dashboard_threshold_value','integer','10'),(24,'database_version','integer','105'),(25,'dashboard_show_weblog','boolean','true');
/*!40000 ALTER TABLE `settings` ENABLE KEYS */;
UNLOCK TABLES;
......@@ -390,7 +390,7 @@ CREATE TABLE `users` (
LOCK TABLES `users` WRITE;
/*!40000 ALTER TABLE `users` DISABLE KEYS */;
INSERT INTO `users` VALUES (1,1,'admin','610706e9a48f85476e04d270bd6dc7492cdcd9ad7e91878007dff629ab11f195',NULL,NULL,1,'Administrator','root@localhost','','none',0);
INSERT INTO `users` VALUES (1,1,'admin','none',NULL,NULL,1,'Administrator','root@localhost','','none',0);
/*!40000 ALTER TABLE `users` ENABLE KEYS */;
UNLOCK TABLES;
......
......@@ -35,6 +35,27 @@
}
}
/* Filter class
*/
class filter {
private $webserver_id = null;
public function __construct($webserver_id) {
$this->webserver_id = $webserver_id;
}
public function __get($key) {
switch ($key) {
case "webserver": return $this->webserver_id;
case "hostname" : return 0;
case "hour_from": return 0;
case "hour_to" : return 23;
}
return null;
}
}
/* Calculate median
*/
function get_median($data, $key) {
......@@ -75,11 +96,12 @@
function get_information($db, $settings, $table, $columns, $user_id, $webserver_id, $hostnames) {
$user = new dummy_user($user_id);
$model = new stats_model($db, $user, $table, $columns, $hostnames);
$filter = new filter($webserver_id);
$begin = date("Y-m-d", strtotime("-".($settings->report_history_days - 1)." days"));
$today = date("Y-m-d");
if (($stats = $model->get_statistics($begin, $today, 0, $webserver_id)) === false) {
if (($stats = $model->get_statistics($begin, $today, $filter)) === false) {
return false;
}
......@@ -103,11 +125,11 @@
}
if ($result[$idx]["previous"] != 0) {
$change = round($stat["today"] / $result[$idx]["previous"] * 100) - 100;
$result[$idx]["change"] = $change." %";
$change = round(($stat["today"] - $result[$idx]["previous"]) / $result[$idx]["previous"], 2);
$result[$idx]["change"] = $change." x";
} else if ($result["today"] == 0) {
$change = $stat["today"] * 100;
$result[$idx]["change"] = $change." %";
$change = $stat["today"];
$result[$idx]["change"] = $change." x";
} else {
$change = 0;
$result[$idx]["change"] = "&#8734;";
......@@ -176,7 +198,7 @@
foreach ($stats as $label => $stat) {
$header = "<h3>".$label."</h3>\n".
"<table class=\"stats\">\n".
"<thead>\n<tr><th>Type</th><th>Value</th><th>= &#916;% of</th><th>".$type."</th></tr>\n</thead>\n<tbody>\n";
"<thead>\n<tr><th>Type</th><th>Value</th><th>= &#916; of</th><th>".$type."</th></tr>\n</thead>\n<tbody>\n";
$header_set = false;
$columns = array_keys($stat["details"]);
......
#!/usr/bin/php
<?php
chdir(__DIR__);
require("../libraries/banshee.php");
require("../libraries/security.php");
error_reporting(E_ALL & ~E_NOTICE);
$db = new MySQLi_connection(DB_HOSTNAME, DB_DATABASE, DB_USERNAME, DB_PASSWORD);
if ($db->connected == false) {
exit("Internal error: database not available.\n");
}
if (count($argv) <= 1) {
exit("Usage: ".$argv[0]." <username> [-t(test)]\n");
}
$username = $argv[1];
$test = ($argv[2] === "-t");
/* Check username
*/
if ($test == false) {
$query = "select count(*) as count from users where username=%s";
if (($result = $db->execute($query, $username)) === false) {
exit("Error while checking username.\n");
}
if ($result[0]["count"] == 0) {
exit("User ".$username." not found.\n");
}
}
do {
print "Enter password: ";
system("/bin/stty -echo");
$password = trim(fgets(STDIN));
system