commit 50fd088dca681f63321aeb795b6598b32da0562f
Author: Pepijn Over
Date: Tue Jan 7 20:24:48 2014 +0100
Initial import of phpservermon v2.0.0
diff --git a/classes/mod/modConfig.class.php b/classes/mod/modConfig.class.php
new file mode 100644
index 00000000..1f962b83
--- /dev/null
+++ b/classes/mod/modConfig.class.php
@@ -0,0 +1,153 @@
+.
+ */
+
+class modConfig extends modCore {
+
+ function __construct() {
+ parent::__construct();
+
+ if(!empty($_POST)) {
+ $this->executeSave();
+ }
+ }
+
+ public function executeSave() {
+ // save new config
+ $clean = array(
+ 'language' => $_POST['language'],
+ 'show_update' => (isset($_POST['show_update'])) ? '1' : '0',
+ 'email_status' => (isset($_POST['email_status'])) ? '1' : '0',
+ 'email_from_name' => $_POST['email_from_name'],
+ 'email_from_email' => $_POST['email_from_email'],
+ 'sms_status' => (isset($_POST['sms_status'])) ? '1' : '0',
+ 'sms_gateway' => $_POST['sms_gateway'],
+ 'sms_gateway_username' => $_POST['sms_gateway_username'],
+ 'sms_gateway_password' => $_POST['sms_gateway_password'],
+ 'sms_from' => $_POST['sms_from'],
+ 'alert_type' => $_POST['alert_type'],
+ 'log_status' => (isset($_POST['log_status'])) ? '1' : '0',
+ 'log_email' => (isset($_POST['log_email'])) ? '1' : '0',
+ 'log_sms' => (isset($_POST['log_sms'])) ? '1' : '0',
+ );
+
+ // save all values to the database
+ foreach($clean as $key => $value) {
+ $this->db->save(
+ SM_DB_PREFIX . 'config',
+ array('value' => $value),
+ array('key' => $key)
+ );
+ }
+
+ $this->message = sm_get_lang('config', 'updated');
+ }
+
+ public function createHTML() {
+ $this->tpl_id = 'config';
+ $this->tpl->newTemplate($this->tpl_id, 'config.tpl.html');
+
+ $this->createHTMLUpdate();
+ $this->createHTMLLabels();
+
+ $this->populateFields();
+
+ return parent::createHTML();
+ }
+
+ public function createHTMLUpdate() {
+ // get latest version number
+
+ }
+
+ public function populateFields() {
+ $config_db = $this->db->select(
+ SM_DB_PREFIX . 'config',
+ null,
+ array('key', 'value')
+ );
+
+ $config = array();
+ foreach($config_db as $entry) {
+ $config[$entry['key']] = $entry['value'];
+ }
+
+ $this->tpl->addTemplateData(
+ $this->tpl_id,
+ array(
+ 'language_selected_' . $config['language'] => 'selected="selected"',
+ 'email_status_checked' => ($config['email_status'] == '1') ? 'checked="checked"' : '',
+ 'email_from_name' => $config['email_from_name'],
+ 'email_from_email' => $config['email_from_email'],
+ 'sms_status_checked' => ($config['sms_status'] == '1') ? 'checked="checked"' : '',
+ 'sms_selected_' . $config['sms_gateway'] => 'selected="selected"',
+ 'sms_gateway_username' => $config['sms_gateway_username'],
+ 'sms_gateway_password' => $config['sms_gateway_password'],
+ 'sms_from' => $config['sms_from'],
+ 'alert_type_selected_' . $config['alert_type'] => 'selected="selected"',
+ 'log_status_checked' => ($config['log_status'] == '1') ? 'checked="checked"' : '',
+ 'log_email_checked' => ($config['log_email'] == '1') ? 'checked="checked"' : '',
+ 'log_sms_checked' => ($config['log_sms'] == '1') ? 'checked="checked"' : '',
+ 'show_update_checked' => ($config['show_update'] == '1') ? 'checked="checked"' : '',
+ )
+ );
+ }
+
+ public function createHTMLLabels() {
+ $this->tpl->addTemplateData(
+ $this->tpl_id,
+ array(
+ 'label_settings_email' => sm_get_lang('config', 'settings_email'),
+ 'label_settings_sms' => sm_get_lang('config', 'settings_sms'),
+ 'label_settings_notification' => sm_get_lang('config', 'settings_notification'),
+ 'label_settings_log' => sm_get_lang('config', 'settings_log'),
+ 'label_general' => sm_get_lang('config', 'general'),
+ 'label_language' => sm_get_lang('config', 'language'),
+ 'label_language_english' => sm_get_lang('config', 'english'),
+ 'label_language_dutch' => sm_get_lang('config', 'dutch'),
+ 'label_show_update' => sm_get_lang('config', 'show_update'),
+ 'label_email_status' => sm_get_lang('config', 'email_status'),
+ 'label_email_from_email' => sm_get_lang('config', 'email_from_email'),
+ 'label_email_from_name' => sm_get_lang('config', 'email_from_name'),
+ 'label_sms_status' => sm_get_lang('config', 'sms_status'),
+ 'label_sms_gateway' => sm_get_lang('config', 'sms_gateway'),
+ 'label_sms_gateway_mollie' => sm_get_lang('config', 'sms_gateway_mollie'),
+ 'label_sms_gateway_spryng' => sm_get_lang('config', 'sms_gateway_spryng'),
+ 'label_sms_gateway_inetworx' => sm_get_lang('config', 'sms_gateway_inetworx'),
+ 'label_sms_gateway_username' => sm_get_lang('config', 'sms_gateway_username'),
+ 'label_sms_gateway_password' => sm_get_lang('config', 'sms_gateway_password'),
+ 'label_sms_from' => sm_get_lang('config', 'sms_from'),
+ 'label_alert_type' => sm_get_lang('config', 'alert_type'),
+ 'label_alert_type_status' => sm_get_lang('config', 'alert_type_status'),
+ 'label_alert_type_offline' => sm_get_lang('config', 'alert_type_offline'),
+ 'label_alert_type_always' => sm_get_lang('config', 'alert_type_always'),
+ 'label_log_status' => sm_get_lang('config', 'log_status'),
+ 'label_log_email' => sm_get_lang('config', 'log_email'),
+ 'label_log_sms' => sm_get_lang('config', 'log_sms'),
+ 'message' => ($this->message == '') ? ' ' : $this->message,
+ )
+ );
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/classes/mod/modCore.class.php b/classes/mod/modCore.class.php
new file mode 100644
index 00000000..cc225638
--- /dev/null
+++ b/classes/mod/modCore.class.php
@@ -0,0 +1,45 @@
+.
+ */
+
+abstract class modCore {
+ public $db;
+ public $message;
+ public $mode;
+ public $tpl;
+ public $tpl_id;
+
+ function __construct() {
+ global $db, $tpl;
+
+ $this->db = ($db) ? $db : new smDatabase();
+ $this->tpl = ($tpl) ? $tpl : new smTemplate();
+ }
+
+ public function createHTML() {
+ $html = $this->tpl->getTemplate($this->tpl_id);
+ return $html;
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/classes/mod/modLog.class.php b/classes/mod/modLog.class.php
new file mode 100644
index 00000000..fc294e20
--- /dev/null
+++ b/classes/mod/modLog.class.php
@@ -0,0 +1,137 @@
+.
+ */
+
+class modLog extends modCore {
+
+ function __construct() {
+ parent::__construct();
+ }
+
+ public function createHTML() {
+ $this->createHTMLList();
+
+ $this->tpl->addCSS('tabs.css', 'main');
+
+ $this->tpl->addTemplateData(
+ $this->tpl_id,
+ array(
+ 'label_status' => sm_get_lang('log', 'status'),
+ 'label_email' => sm_get_lang('log', 'email'),
+ 'label_sms' => sm_get_lang('log', 'sms'),
+ 'label_title' => sm_get_lang('log', 'title'),
+ 'label_server' => sm_get_lang('servers', 'server'),
+ 'label_type' => sm_get_lang('log', 'type'),
+ 'label_message' => sm_get_lang('system', 'message'),
+ 'label_date' => sm_get_lang('system', 'date'),
+ 'label_users' => ucfirst(sm_get_lang('system', 'users')),
+ )
+ );
+
+ return parent::createHTML();
+ }
+
+ public function createHTMLList() {
+ $this->tpl_id = 'log_list';
+
+ $this->tpl->newTemplate($this->tpl_id, 'log.tpl.html');
+
+ $entries = array();
+ $entries['status'] = $this->getEntries('status');
+ $entries['email'] = $this->getEntries('email');
+ $entries['sms'] = $this->getEntries('sms');
+
+ // get users
+ $users = $this->db->select(SM_DB_PREFIX.'users', null, array('user_id','name'));
+
+ $users_labels = array();
+ foreach ($users as $user) {
+ $users_labels[$user['user_id']] = $user['name'];
+ }
+
+ foreach($entries as $key => $records) {
+ $log_count = count($records);
+
+ for ($x = 0; $x < $log_count; $x++) {
+ $records[$x]['class'] = ($x & 1) ? 'odd' : 'even';
+ $records[$x]['users'] = '';
+ $records[$x]['server'] = $records[$x]['label'] . ' (' . $records[$x]['label_adv'] . ')';
+
+ // fix up user list
+ if($records[$x]['user_id'] == '') continue;
+
+ $users = explode(',', $records[$x]['user_id']);
+ foreach($users as $user_id) {
+ if((int) $user_id == 0 || !isset($users_labels[$user_id])) continue;
+
+ $records[$x]['users'] .= ' '.$users_labels[$user_id];
+ }
+ }
+
+ // add entries to template
+ $this->tpl->newTemplate('log_entries', 'log.tpl.html');
+ $this->tpl->addTemplateDataRepeat('log_entries', 'entries', $records);
+ $this->tpl->addTemplateData(
+ 'log_entries',
+ array(
+ 'logtitle' => $key,
+ )
+ );
+ $this->tpl->addTemplateData(
+ $this->tpl_id,
+ array(
+ 'content_' . $key => $this->tpl->getTemplate('log_entries'),
+ )
+ );
+ }
+
+ }
+
+ public function getEntries($type) {
+ $entries = $this->db->query(
+ 'SELECT '.
+ '`servers`.`label`, '.
+ 'CONCAT_WS('.
+ '\':\','.
+ '`servers`.`ip`, '.
+ '`servers`.`port`'.
+ ') AS `label_adv`, '.
+ '`log`.`type`, '.
+ '`log`.`message`, '.
+ 'DATE_FORMAT('.
+ '`log`.`datetime`, '.
+ '\'%H:%i:%s %d-%m-%y\''.
+ ') AS `datetime_format`, '.
+ '`user_id` '.
+ 'FROM `'.SM_DB_PREFIX.'log` AS `log` '.
+ 'JOIN `'.SM_DB_PREFIX.'servers` AS `servers` ON (`servers`.`server_id`=`log`.`server_id`) '.
+ 'WHERE `log`.`type`=\''.$type.'\' '.
+ 'ORDER BY `datetime` DESC '.
+ 'LIMIT 0,20'
+ );
+ return $entries;
+ }
+
+}
+
+?>
\ No newline at end of file
diff --git a/classes/mod/modServers.class.php b/classes/mod/modServers.class.php
new file mode 100644
index 00000000..20ee7e04
--- /dev/null
+++ b/classes/mod/modServers.class.php
@@ -0,0 +1,219 @@
+.
+ */
+
+class modServers extends modCore {
+
+ function __construct() {
+ parent::__construct();
+
+ // check mode
+ if (isset($_GET['edit']) && is_numeric($_GET['edit'])) {
+ // edit mode or insert mode
+ $this->mode = 'update';
+ } else {
+ $this->mode = 'list';
+
+ if(!empty($_POST)) {
+ $this->executeSave();
+ }
+ if(isset($_GET['delete']) && is_numeric($_GET['delete'])) {
+ $this->executeDelete();
+ }
+ }
+ }
+
+ public function createHTML() {
+ switch($this->mode) {
+ case 'list':
+ $this->createHTMLList();
+ break;
+ case 'update':
+ $this->createHTMLUpdate();
+ break;
+ }
+
+ // add labels
+ $this->tpl->addTemplateData(
+ $this->tpl_id,
+ array(
+ 'label_label' => sm_get_lang('servers', 'label'),
+ 'label_domain' => sm_get_lang('servers', 'domain'),
+ 'label_port' => sm_get_lang('servers', 'port'),
+ 'label_type' => sm_get_lang('servers', 'type'),
+ 'label_last_check' => sm_get_lang('servers', 'last_check'),
+ 'label_rtime' => sm_get_lang('servers', 'rtime'),
+ 'label_last_online' => sm_get_lang('servers', 'last_online'),
+ 'label_monitoring' => sm_get_lang('servers', 'monitoring'),
+ 'label_send_email' => sm_get_lang('servers', 'send_email'),
+ 'label_send_sms' => sm_get_lang('servers', 'send_sms'),
+ 'label_action' => sm_get_lang('system', 'action'),
+ 'label_save' => sm_get_lang('system', 'save'),
+ 'label_edit' => sm_get_lang('system', 'edit') . ' ' . sm_get_lang('servers', 'server'),
+ 'label_delete' => sm_get_lang('system', 'delete') . ' ' . sm_get_lang('servers', 'server'),
+ 'label_yes' => sm_get_lang('system', 'yes'),
+ 'label_no' => sm_get_lang('system', 'no'),
+ 'label_add_new' => sm_get_lang('system', 'add_new'),
+ 'message' => ($this->message == '') ? ' ' : $this->message,
+ )
+ );
+
+ return parent::createHTML();
+ }
+
+
+ public function createHTMLUpdate() {
+ $this->tpl_id = 'servers_update';
+ $this->tpl->newTemplate($this->tpl_id, 'servers.tpl.html');
+
+ $server_id = $_GET['edit'];
+
+ $tpl_data = array();
+
+ switch((int) $server_id) {
+ case 0:
+ // insert mode
+ $tpl_data['titlemode'] = sm_get_lang('system', 'insert');
+ $tpl_data['edit_server_id'] = '0';
+ break;
+ default:
+ // edit mode
+
+ // get server entry
+ $edit_server = $this->db->selectRow(
+ SM_DB_PREFIX.'servers',
+ array('server_id' => $server_id)
+ );
+ if (empty($edit_server)) {
+ $this->message = 'Invalid server id';
+ return $this->createHTMLList();
+ }
+
+ $tpl_data = array_merge($tpl_data, array(
+ 'titlemode' => sm_get_lang('system', 'edit') . ' ' . $edit_server['label'],
+ 'edit_server_id' => $edit_server['server_id'],
+ 'edit_value_label' => $edit_server['label'],
+ 'edit_value_ip' => $edit_server['ip'],
+ 'edit_value_port' => $edit_server['port'],
+ 'edit_type_selected_' . $edit_server['type'] => 'selected="selected"',
+ 'edit_active_selected_' . $edit_server['active'] => 'selected="selected"',
+ 'edit_email_selected_' . $edit_server['email'] => 'selected="selected"',
+ 'edit_sms_selected_' . $edit_server['sms'] => 'selected="selected"',
+ ));
+
+ break;
+ }
+
+ $this->tpl->addTemplateData(
+ $this->tpl_id,
+ $tpl_data
+ );
+ }
+
+ public function createHTMLList() {
+ $this->tpl_id = 'servers_list';
+ $this->tpl->newTemplate($this->tpl_id, 'servers.tpl.html');
+
+ // get servers from database
+ $servers = $this->db->query(
+ 'SELECT '.
+ '`server_id`, '.
+ '`ip`, '.
+ '`port`, '.
+ '`type`, '.
+ '`label`, '.
+ '`status`, '.
+ '`error`, '.
+ '`rtime`, '.
+ 'IF('.
+ '`last_check`=\'0000-00-00 00:00:00\', '.
+ '\'never\', '.
+ 'DATE_FORMAT(`last_check`, \'%d-%m-%y %H:%i\') '.
+ ') AS `last_check`, '.
+ 'IF('.
+ '`last_online`=\'0000-00-00 00:00:00\', '.
+ '\'never\', '.
+ 'DATE_FORMAT(`last_online`, \'%d-%m-%y %H:%i\') '.
+ ') AS `last_online`, '.
+ '`active`, '.
+ '`email`, '.
+ '`sms` '.
+ 'FROM `'.SM_DB_PREFIX.'servers` '.
+ 'ORDER BY `type` ASC, `label` ASC'
+ );
+
+ $server_count = count($servers);
+
+ for ($x = 0; $x < $server_count; $x++) {
+ $servers[$x]['class'] = ($x & 1) ? 'odd' : 'even';
+ $servers[$x]['rtime'] = round((float) $servers[$x]['rtime'], 4);
+ }
+ // add servers to template
+ $this->tpl->addTemplateDataRepeat($this->tpl_id, 'servers', $servers);
+
+ }
+
+ public function executeSave() {
+ // check for add/edit mode
+ if (isset($_POST['label']) && isset($_POST['ip']) && isset($_POST['port'])) {
+ $clean = array(
+ 'label' => $_POST['label'],
+ 'ip' => $_POST['ip'],
+ 'port' => $_POST['port'],
+ 'type' => $_POST['type'],
+ 'active' => $_POST['active'],
+ 'email' => $_POST['email'],
+ 'sms' => $_POST['sms'],
+ );
+
+ // check for edit or add
+ if ((int) $_POST['server_id'] > 0) {
+ // edit
+ $this->db->save(
+ SM_DB_PREFIX.'servers',
+ $clean,
+ array('server_id' => $_POST['server_id'])
+ );
+ $this->message = sm_get_lang('servers', 'updated');
+ } else {
+ // add
+ $clean['status'] = 'on';
+ $this->db->save(SM_DB_PREFIX.'servers', $clean);
+ $this->message = sm_get_lang('servers', 'inserted');
+ }
+ }
+ }
+
+ public function executeDelete() {
+ // do delete
+ $this->db->delete(
+ SM_DB_PREFIX . 'servers',
+ array(
+ 'server_id' => $_GET['delete']
+ )
+ );
+ $this->message = sm_get_lang('system', 'deleted');
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/classes/mod/modUsers.class.php b/classes/mod/modUsers.class.php
new file mode 100644
index 00000000..e9494fee
--- /dev/null
+++ b/classes/mod/modUsers.class.php
@@ -0,0 +1,225 @@
+.
+ */
+
+class modUsers extends modCore {
+ public $servers;
+
+ function __construct() {
+ parent::__construct();
+
+ // check mode
+ if (isset($_GET['edit']) && is_numeric($_GET['edit'])) {
+ // edit mode or insert mode
+ $this->mode = 'update';
+ } else {
+ $this->mode = 'list';
+
+ if(!empty($_POST)) {
+ $this->executeSave();
+ }
+ if(isset($_GET['delete']) && is_numeric($_GET['delete'])) {
+ $this->executeDelete();
+ }
+ }
+
+ $this->servers = $this->db->select(SM_DB_PREFIX.'servers', null, array('server_id', 'label'));
+ }
+
+ public function createHTML() {
+ switch($this->mode) {
+ case 'list':
+ $this->createHTMLList();
+ break;
+ case 'update':
+ $this->createHTMLUpdate();
+ break;
+ }
+
+ // add labels
+ $this->tpl->addTemplateData(
+ $this->tpl_id,
+ array(
+ 'label_users' => sm_get_lang('system', 'users'),
+ 'label_name' => sm_get_lang('users', 'name'),
+ 'label_mobile' => sm_get_lang('users', 'mobile'),
+ 'label_email' => sm_get_lang('users', 'email'),
+ 'label_servers' => sm_get_lang('system', 'servers'),
+ 'label_action' => sm_get_lang('system', 'action'),
+ 'label_save' => sm_get_lang('system', 'save'),
+ 'label_edit' => sm_get_lang('system', 'edit') . ' ' . sm_get_lang('users', 'user'),
+ 'label_delete' => sm_get_lang('system', 'delete') . ' ' . sm_get_lang('users', 'user'),
+ 'label_add_new' => sm_get_lang('system', 'add_new'),
+ 'message' => ($this->message == '') ? ' ' : $this->message,
+ )
+ );
+
+ return parent::createHTML();
+ }
+
+
+ public function createHTMLUpdate() {
+ $this->tpl_id = 'users_update';
+ $this->tpl->newTemplate($this->tpl_id, 'users.tpl.html');
+
+ $user_id = $_GET['edit'];
+
+ $tpl_data = array();
+ $servers_count = count($this->servers);
+
+ switch((int) $user_id) {
+ case 0:
+ // insert mode
+ $tpl_data['titlemode'] = sm_get_lang('system', 'insert');
+ $tpl_data['edit_user_id'] = '0';
+
+ // add inactive class to all servers
+ for ($i = 0; $i < $servers_count; $i++) {
+ $this->servers[$i]['class'] = 'inactive';
+ }
+
+ break;
+ default:
+ // edit mode
+
+ // get user entry
+ $edit_user = $this->db->selectRow(
+ SM_DB_PREFIX.'users',
+ array('user_id' => $user_id)
+ );
+ if (empty($edit_user)) {
+ $this->message = 'Invalid user id';
+ return $this->createHTMLList();
+ }
+
+ $tpl_data = array_merge($tpl_data, array(
+ 'titlemode' => sm_get_lang('system', 'edit') . ' ' . $edit_user['name'],
+ 'edit_user_id' => $edit_user['user_id'],
+ 'edit_value_name' => $edit_user['name'],
+ 'edit_value_mobile' => $edit_user['mobile'],
+ 'edit_value_email' => $edit_user['email'],
+ ));
+
+ // select servers for this user
+ $user_servers = explode(',', $edit_user['server_id']);
+
+ for ($h = 0; $h < $servers_count; $h++) {
+ if(in_array($this->servers[$h]['server_id'], $user_servers)) {
+ $this->servers[$h]['edit_checked'] = 'checked="checked"';
+ $this->servers[$h]['class'] = 'active';
+ }
+ }
+
+ break;
+ }
+
+ $this->tpl->addTemplateData(
+ $this->tpl_id,
+ $tpl_data
+ );
+ // add servers to template for the edit form
+ $this->tpl->addTemplateDataRepeat('users_update', 'servers', $this->servers);
+ }
+
+ public function createHTMLList() {
+ $this->tpl_id = 'users_list';
+ $this->tpl->newTemplate($this->tpl_id, 'users.tpl.html');
+
+ // build label array for the next loop
+ $servers_labels = array();
+ foreach ($this->servers as $server) {
+ $servers_labels[$server['server_id']] = $server['label'];
+ }
+
+ // get users from database
+ $users = $this->db->select(
+ SM_DB_PREFIX.'users',
+ null,
+ null,
+ null,
+ array('name')
+ );
+
+ $user_count = count($users);
+
+ for ($x = 0; $x < $user_count; $x++) {
+ $users[$x]['class'] = ($x & 1) ? 'odd' : 'even';
+
+ $users[$x]['emp_servers'] = '';
+
+ // fix server list
+ $user_servers = explode(',', $users[$x]['server_id']);
+ if (empty($user_servers)) continue;
+
+ foreach ($user_servers as $server) {
+ if (!isset($servers_labels[$server])) continue;
+ $users[$x]['emp_servers'] .= $servers_labels[$server] . ' ';
+ }
+ $users[$x]['emp_servers'] = substr($users[$x]['emp_servers'], 0, -5);
+ }
+ // add servers to template
+ $this->tpl->addTemplateDataRepeat($this->tpl_id, 'users', $users);
+
+ }
+
+ public function executeSave() {
+ // check for add/edit mode
+
+ if (isset($_POST['name']) && isset($_POST['mobile']) && isset($_POST['email'])) {
+ $clean = array(
+ 'name' => $_POST['name'],
+ 'mobile' => $_POST['mobile'],
+ 'email' => $_POST['email'],
+ 'server_id' => (isset($_POST['server_id'])) ? implode(',', $_POST['server_id']) : ''
+ );
+
+ // check for edit or add
+ if ((int) $_POST['user_id'] > 0) {
+ // edit
+ $this->db->save(
+ SM_DB_PREFIX.'users',
+ $clean,
+ array('user_id' => $_POST['user_id'])
+ );
+ $this->message = sm_get_lang('users', 'updated');
+ } else {
+ // add
+ $this->db->save(SM_DB_PREFIX.'users', $clean);
+ $this->message = sm_get_lang('users', 'inserted');
+ }
+ }
+ }
+
+ public function executeDelete() {
+ // do delete
+ $this->db->delete(
+ SM_DB_PREFIX . 'users',
+ array(
+ 'user_id' => $_GET['delete']
+ )
+ );
+ $this->message = sm_get_lang('system', 'deleted');
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/classes/phpmailer.class.php b/classes/phpmailer.class.php
new file mode 100644
index 00000000..0da0e8c9
--- /dev/null
+++ b/classes/phpmailer.class.php
@@ -0,0 +1,1615 @@
+
+//
+// License: LGPL, see LICENSE
+////////////////////////////////////////////////////
+
+/**
+ * phpmailer - PHP email transport class
+ * @author Brent R. Matzelle
+ */
+class phpmailer
+{
+ /////////////////////////////////////////////////
+ // PUBLIC VARIABLES
+ /////////////////////////////////////////////////
+
+ /**
+ * Email priority (1 = High, 3 = Normal, 5 = low). Default value is 3.
+ * @public
+ * @type int
+ */
+ var $Priority = 3;
+
+ /**
+ * Sets the CharSet of the message. Default value is "iso-8859-1".
+ * @public
+ * @type string
+ */
+ var $CharSet = "iso-8859-1";
+
+ /**
+ * Sets the Content-type of the message. Default value is "text/plain".
+ * @public
+ * @type string
+ */
+ var $ContentType = "text/plain";
+
+ /**
+ * Sets the Encoding of the message. Options for this are "8bit" (default),
+ * "7bit", "binary", "base64", and "quoted-printable".
+ * @public
+ * @type string
+ */
+ var $Encoding = "8bit";
+
+ /**
+ * Holds the most recent mailer error message. Default value is "".
+ * @public
+ * @type string
+ */
+ var $ErrorInfo = "";
+
+ /**
+ * Sets the From email address for the message. Default value is "root@localhost".
+ * @public
+ * @type string
+ */
+ var $From = "root@localhost";
+
+ /**
+ * Sets the From name of the message. Default value is "Root User".
+ * @public
+ * @type string
+ */
+ var $FromName = "Root User";
+
+ /**
+ * Sets the Sender email of the message. If not empty, will be sent via -f to sendmail
+ * or as 'MAIL FROM' in smtp mode. Default value is "".
+ * @public
+ * @type string
+ */
+ var $Sender = "";
+
+ /**
+ * Sets the Subject of the message. Default value is "".
+ * @public
+ * @type string
+ */
+ var $Subject = "";
+
+ /**
+ * Sets the Body of the message. This can be either an HTML or text body.
+ * If HTML then run IsHTML(true). Default value is "".
+ * @public
+ * @type string
+ */
+ var $Body = "";
+
+ /**
+ * Sets the text-only body of the message. This automatically sets the
+ * email to multipart/alternative. This body can be read by mail
+ * clients that do not have HTML email capability such as mutt. Clients
+ * that can read HTML will view the normal Body.
+ * Default value is "".
+ * @public
+ * @type string
+ */
+ var $AltBody = "";
+
+ /**
+ * Sets word wrapping on the body of the message to a given number of
+ * characters. Default value is 0 (off).
+ * @public
+ * @type int
+ */
+ var $WordWrap = 0;
+
+ /**
+ * Method to send mail: ("mail", "sendmail", or "smtp").
+ * Default value is "mail".
+ * @public
+ * @type string
+ */
+ var $Mailer = "mail";
+
+ /**
+ * Sets the path of the sendmail program. Default value is
+ * "/usr/sbin/sendmail".
+ * @public
+ * @type string
+ */
+ var $Sendmail = "/usr/sbin/sendmail";
+
+ /**
+ * Turns Microsoft mail client headers on and off. Useful mostly
+ * for older clients. Default value is false (off).
+ * @public
+ * @type bool
+ */
+ var $UseMSMailHeaders = false;
+
+ /**
+ * Path to phpmailer plugins. This is now only useful if the SMTP class
+ * is in a different directory than the PHP include path.
+ * Default is empty ("").
+ * @public
+ * @type string
+ */
+ var $PluginDir = "";
+
+ /**
+ * Holds phpmailer version.
+ * @public
+ * @type string
+ */
+ var $Version = "1.54";
+
+ /**
+ * Sets the email address that a reading confirmation will be sent. Default value is "".
+ * @public
+ * @type string
+ */
+ var $ConfirmReadingTo = "";
+
+ /**
+ * Sets the line endings of the message. Default is "\n";
+ * @public
+ * @type string
+ */
+ var $LE = "\n";
+
+
+ /////////////////////////////////////////////////
+ // SMTP VARIABLES
+ /////////////////////////////////////////////////
+
+ /**
+ * Sets the SMTP hosts. All hosts must be separated by a
+ * semicolon. You can also specify a different port
+ * for each host by using this format: [hostname:port]
+ * (e.g. "smtp1.domain.com:25;smtp2.domain.com").
+ * Hosts will be tried in order.
+ * Default value is "localhost".
+ * @public
+ * @type string
+ */
+ var $Host = "localhost";
+
+ /**
+ * Sets the default SMTP server port. Default value is 25.
+ * @public
+ * @type int
+ */
+ var $Port = 25;
+
+ /**
+ * Sets the SMTP HELO of the message.
+ * Default value is "localhost.localdomain".
+ * @public
+ * @type string
+ */
+ var $Helo = "localhost.localdomain";
+
+ /**
+ * Sets SMTP authentication. Utilizes the Username and Password variables.
+ * Default value is false (off).
+ * @public
+ * @type bool
+ */
+ var $SMTPAuth = false;
+
+ /**
+ * Sets SMTP username. Default value is "".
+ * @public
+ * @type string
+ */
+ var $Username = "";
+
+ /**
+ * Sets SMTP password. Default value is "".
+ * @public
+ * @type string
+ */
+ var $Password = "";
+
+ /**
+ * Sets the SMTP server timeout in seconds. This function will not
+ * work with the win32 version. Default value is 10.
+ * @public
+ * @type int
+ */
+ var $Timeout = 10;
+
+ /**
+ * Sets SMTP class debugging on or off. Default value is false (off).
+ * @public
+ * @type bool
+ */
+ var $SMTPDebug = false;
+
+
+ /////////////////////////////////////////////////
+ // PRIVATE VARIABLES
+ /////////////////////////////////////////////////
+
+ /**
+ * Holds all "To" addresses.
+ * @type array
+ */
+ var $to = array();
+
+ /**
+ * Holds all "CC" addresses.
+ * @type array
+ */
+ var $cc = array();
+
+ /**
+ * Holds all "BCC" addresses.
+ * @type array
+ */
+ var $bcc = array();
+
+ /**
+ * Holds all "Reply-To" addresses.
+ * @type array
+ */
+ var $ReplyTo = array();
+
+ /**
+ * Holds all string and binary attachments.
+ * @type array
+ */
+ var $attachment = array();
+
+ /**
+ * Holds all custom headers.
+ * @type array
+ */
+ var $CustomHeader = array();
+
+ /**
+ * Holds the type of the message.
+ * @type string
+ */
+ var $message_type = "";
+
+ /**
+ * Holds the message boundaries.
+ * @type string array
+ */
+ var $boundary = array();
+
+ /////////////////////////////////////////////////
+ // VARIABLE METHODS
+ /////////////////////////////////////////////////
+
+ /**
+ * Sets message type to HTML. Returns void.
+ * @public
+ * @returns void
+ */
+ function IsHTML($bool) {
+ if($bool == true)
+ $this->ContentType = "text/html";
+ else
+ $this->ContentType = "text/plain";
+ }
+
+ /**
+ * Sets Mailer to send message using SMTP.
+ * Returns void.
+ * @public
+ * @returns void
+ */
+ function IsSMTP() {
+ $this->Mailer = "smtp";
+ }
+
+ /**
+ * Sets Mailer to send message using PHP mail() function.
+ * Returns void.
+ * @public
+ * @returns void
+ */
+ function IsMail() {
+ $this->Mailer = "mail";
+ }
+
+ /**
+ * Sets Mailer to send message using the $Sendmail program.
+ * Returns void.
+ * @public
+ * @returns void
+ */
+ function IsSendmail() {
+ $this->Mailer = "sendmail";
+ }
+
+ /**
+ * Sets Mailer to send message using the qmail MTA. Returns void.
+ * @public
+ * @returns void
+ */
+ function IsQmail() {
+ //$this->Sendmail = "/var/qmail/bin/qmail-inject";
+ $this->Sendmail = "/var/qmail/bin/sendmail";
+ $this->Mailer = "sendmail";
+ }
+
+
+ /////////////////////////////////////////////////
+ // RECIPIENT METHODS
+ /////////////////////////////////////////////////
+
+ /**
+ * Adds a "To" address. Returns void.
+ * @public
+ * @returns void
+ */
+ function AddAddress($address, $name = "") {
+ $cur = count($this->to);
+ $this->to[$cur][0] = trim($address);
+ $this->to[$cur][1] = $name;
+ }
+
+ /**
+ * Adds a "Cc" address. Note: this function works
+ * with the SMTP mailer on win32, not with the "mail"
+ * mailer. This is a PHP bug that has been submitted
+ * on http://bugs.php.net. The *NIX version of PHP
+ * functions correctly. Returns void.
+ * @public
+ * @returns void
+ */
+ function AddCC($address, $name = "") {
+ $cur = count($this->cc);
+ $this->cc[$cur][0] = trim($address);
+ $this->cc[$cur][1] = $name;
+ }
+
+ /**
+ * Adds a "Bcc" address. Note: this function works
+ * with the SMTP mailer on win32, not with the "mail"
+ * mailer. This is a PHP bug that has been submitted
+ * on http://bugs.php.net. The *NIX version of PHP
+ * functions correctly.
+ * Returns void.
+ * @public
+ * @returns void
+ */
+ function AddBCC($address, $name = "") {
+ $cur = count($this->bcc);
+ $this->bcc[$cur][0] = trim($address);
+ $this->bcc[$cur][1] = $name;
+ }
+
+ /**
+ * Adds a "Reply-to" address. Returns void.
+ * @public
+ * @returns void
+ */
+ function AddReplyTo($address, $name = "") {
+ $cur = count($this->ReplyTo);
+ $this->ReplyTo[$cur][0] = trim($address);
+ $this->ReplyTo[$cur][1] = $name;
+ }
+
+
+ /////////////////////////////////////////////////
+ // MAIL SENDING METHODS
+ /////////////////////////////////////////////////
+
+ /**
+ * Creates message and assigns Mailer. If the message is
+ * not sent successfully then it returns false. Use the ErrorInfo
+ * variable to view description of the error. Returns bool.
+ * @public
+ * @returns bool
+ */
+ function Send() {
+ $header = "";
+ $body = "";
+
+ if((count($this->to) + count($this->cc) + count($this->bcc)) < 1)
+ {
+ $this->error_handler("You must provide at least one recipient email address");
+ return false;
+ }
+
+ // Set whether the message is multipart/alternative
+ if(!empty($this->AltBody))
+ $this->ContentType = "multipart/alternative";
+
+ // Attach sender information & date
+ $header = $this->received();
+ $header .= sprintf("Date: %s%s", $this->rfc_date(), $this->LE);
+ $header .= $this->create_header();
+
+ if(!$body = $this->create_body())
+ return false;
+
+ //echo "
".$header . $body . "
"; // debugging
+
+ // Choose the mailer
+ if($this->Mailer == "sendmail")
+ {
+ if(!$this->sendmail_send($header, $body))
+ return false;
+ }
+ elseif($this->Mailer == "mail")
+ {
+ if(!$this->mail_send($header, $body))
+ return false;
+ }
+ elseif($this->Mailer == "smtp")
+ {
+ if(!$this->smtp_send($header, $body))
+ return false;
+ }
+ else
+ {
+ $this->error_handler(sprintf("%s mailer is not supported", $this->Mailer));
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Sends mail message to an assigned queue directory. Has an optional
+ * sendTime argument. This is used when the user wants the
+ * message to be sent from the queue at a predetermined time.
+ * The data must be a valid timestamp like that returned from
+ * the time() or strtotime() functions. Returns false on failure
+ * or the message file name if success.
+ * @public
+ * @returns string
+ */
+ function SendToQueue($queue_path, $send_time = 0) {
+ $message = array();
+ $header = "";
+ $body = "";
+
+ // If invalid or empty just set to the current time
+ if($send_time == 0)
+ $send_time = time();
+
+ if(!is_dir($queue_path))
+ {
+ $this->error_handler("The supplied queue directory does not exist");
+ return false;
+ }
+
+ if((count($this->to) + count($this->cc) + count($this->bcc)) < 1)
+ {
+ $this->error_handler("You must provide at least one recipient email address");
+ return false;
+ }
+
+ // Set whether the message is multipart/alternative
+ if(!empty($this->AltBody))
+ $this->ContentType = "multipart/alternative";
+
+ $header = $this->create_header();
+ if(!$body = $this->create_body())
+ return false;
+
+ // Seed randomizer
+ mt_srand(time());
+ $msg_id = md5(uniqid(mt_rand()));
+
+ $fp = fopen($queue_path . $msg_id . ".pqm", "wb");
+ if(!$fp)
+ {
+ $this->error_handler(sprintf("Could not write to %s directory", $queue_path));
+ return false;
+ }
+
+ $message[] = sprintf("----START PQM HEADER----%s", $this->LE);
+ $message[] = sprintf("SendTime: %s%s", $send_time, $this->LE);
+ $message[] = sprintf("Mailer: %s%s", $this->Mailer, $this->LE);
+
+ // Choose the mailer
+ if($this->Mailer == "sendmail")
+ {
+ $message[] = sprintf("Sendmail: %s%s", $this->Sendmail, $this->LE);
+ $message[] = sprintf("Sender: %s%s", $this->Sender, $this->LE);
+ }
+ elseif($this->Mailer == "mail")
+ {
+ $message[] = sprintf("Sender: %s%s", $this->Sender, $this->LE);
+ $message[] = sprintf("Subject: %s%s", $this->Subject, $this->LE);
+ $message[] = sprintf("to: %s%s", $this->addr_list($this->to), $this->LE);
+ }
+ elseif($this->Mailer == "smtp")
+ {
+ $message[] = sprintf("Host: %s%s", $this->Host, $this->LE);
+ $message[] = sprintf("Port: %d%s", $this->Port, $this->LE);
+ $message[] = sprintf("Helo: %s%s", $this->Helo, $this->LE);
+ $message[] = sprintf("Timeout: %d%s", $this->Timeout, $this->LE);
+
+ if($this->SMTPAuth)
+ $auth_no = 1;
+ else
+ $auth_no = 0;
+ $message[] = sprintf("SMTPAuth: %d%s", $auth_no, $this->LE);
+ $message[] = sprintf("Username: %s%s", $this->Username, $this->LE);
+ $message[] = sprintf("Password: %s%s", $this->Password, $this->LE);
+ $message[] = sprintf("From: %s%s", $this->From, $this->LE);
+
+ $message[] = sprintf("to: %s%s", $this->addr_list($this->to), $this->LE);
+ $message[] = sprintf("cc: %s%s", $this->addr_list($this->cc), $this->LE);
+ $message[] = sprintf("bcc: %s%s", $this->addr_list($this->bcc), $this->LE);
+ }
+ else
+ {
+ $this->error_handler(sprintf("%s mailer is not supported", $this->Mailer));
+ return false;
+ }
+
+ $message[] = sprintf("----END PQM HEADER----%s", $this->LE); // end of pqm header
+ $message[] = $header;
+ $message[] = $body;
+
+ fwrite($fp, join("", $message));
+
+ return ($msg_id . ".pqm");
+ }
+
+ /**
+ * Sends mail using the $Sendmail program. Returns bool.
+ * @private
+ * @returns bool
+ */
+ function sendmail_send($header, $body) {
+ if ($this->Sender != "")
+ $sendmail = sprintf("%s -oi -f %s -t", $this->Sendmail, $this->Sender);
+ else
+ $sendmail = sprintf("%s -oi -t", $this->Sendmail);
+
+ if(!@$mail = popen($sendmail, "w"))
+ {
+ $this->error_handler(sprintf("Could not execute %s", $this->Sendmail));
+ return false;
+ }
+
+ fputs($mail, $header);
+ fputs($mail, $body);
+
+ $result = pclose($mail) >> 8 & 0xFF;
+ if($result != 0)
+ {
+ $this->error_handler(sprintf("Could not execute %s", $this->Sendmail));
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Sends mail using the PHP mail() function. Returns bool.
+ * @private
+ * @returns bool
+ */
+ function mail_send($header, $body) {
+ //$to = substr($this->addr_append("To", $this->to), 4, -2);
+
+ // Cannot add Bcc's to the $to
+ $to = $this->to[0][0]; // no extra comma
+ for($i = 1; $i < count($this->to); $i++)
+ $to .= sprintf(",%s", $this->to[$i][0]);
+
+ if ($this->Sender != "" && PHP_VERSION >= "4.0")
+ {
+ $old_from = ini_get("sendmail_from");
+ ini_set("sendmail_from", $this->Sender);
+ }
+
+ if ($this->Sender != "" && PHP_VERSION >= "4.0.5")
+ {
+ // The fifth parameter to mail is only available in PHP >= 4.0.5
+ $params = sprintf("-oi -f %s", $this->Sender);
+ $rt = @mail($to, $this->Subject, $body, $header, $params);
+ }
+ else
+ {
+ $rt = @mail($to, $this->Subject, $body, $header);
+ }
+
+ if (isset($old_from))
+ ini_set("sendmail_from", $old_from);
+
+ if(!$rt)
+ {
+ $this->error_handler("Could not instantiate mail()");
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Sends mail via SMTP using PhpSMTP (Author:
+ * Chris Ryan). Returns bool. Returns false if there is a
+ * bad MAIL FROM, RCPT, or DATA input.
+ * @private
+ * @returns bool
+ */
+ function smtp_send($header, $body) {
+ // Include SMTP class code, but not twice
+ include_once($this->PluginDir . "class.smtp.php");
+
+ $smtp = new SMTP;
+
+ $smtp->do_debug = $this->SMTPDebug;
+
+ // Try to connect to all SMTP servers
+ $hosts = explode(";", $this->Host);
+ $index = 0;
+ $connection = false;
+ $smtp_from = "";
+ $bad_rcpt = array();
+ $e = "";
+
+ // Retry while there is no connection
+ while($index < count($hosts) && $connection == false)
+ {
+ if(strstr($hosts[$index], ":"))
+ list($host, $port) = explode(":", $hosts[$index]);
+ else
+ {
+ $host = $hosts[$index];
+ $port = $this->Port;
+ }
+
+ if($smtp->Connect($host, $port, $this->Timeout))
+ $connection = true;
+ //printf("%s host could not connect ", $hosts[$index]); //debug only
+ $index++;
+ }
+ if(!$connection)
+ {
+ $this->error_handler("SMTP Error: could not connect to SMTP host server(s)");
+ return false;
+ }
+
+ // Must perform HELO before authentication
+ $smtp->Hello($this->Helo);
+
+ // If user requests SMTP authentication
+ if($this->SMTPAuth)
+ {
+ if(!$smtp->Authenticate($this->Username, $this->Password))
+ {
+ $this->error_handler("SMTP Error: Could not authenticate");
+ return false;
+ }
+ }
+
+ if ($this->Sender == "")
+ $smtp_from = $this->From;
+ else
+ $smtp_from = $this->Sender;
+
+ if(!$smtp->Mail(sprintf("<%s>", $smtp_from)))
+ {
+ $e = sprintf("SMTP Error: From address [%s] failed", $smtp_from);
+ $this->error_handler($e);
+ return false;
+ }
+
+ // Attempt to send attach all recipients
+ for($i = 0; $i < count($this->to); $i++)
+ {
+ if(!$smtp->Recipient(sprintf("<%s>", $this->to[$i][0])))
+ $bad_rcpt[] = $this->to[$i][0];
+ }
+ for($i = 0; $i < count($this->cc); $i++)
+ {
+ if(!$smtp->Recipient(sprintf("<%s>", $this->cc[$i][0])))
+ $bad_rcpt[] = $this->cc[$i][0];
+ }
+ for($i = 0; $i < count($this->bcc); $i++)
+ {
+ if(!$smtp->Recipient(sprintf("<%s>", $this->bcc[$i][0])))
+ $bad_rcpt[] = $this->bcc[$i][0];
+ }
+
+ // Create error message
+ if(count($bad_rcpt) > 0)
+ {
+ for($i = 0; $i < count($bad_rcpt); $i++)
+ {
+ if($i != 0)
+ $e .= ", ";
+ $e .= $bad_rcpt[$i];
+ }
+ $e = sprintf("SMTP Error: The following recipients failed [%s]", $e);
+ $this->error_handler($e);
+
+ return false;
+ }
+
+
+ if(!$smtp->Data(sprintf("%s%s", $header, $body)))
+ {
+ $this->error_handler("SMTP Error: Data not accepted");
+ return false;
+ }
+ $smtp->Quit();
+
+ return true;
+ }
+
+
+ /////////////////////////////////////////////////
+ // MESSAGE CREATION METHODS
+ /////////////////////////////////////////////////
+
+ /**
+ * Creates recipient headers. Returns string.
+ * @private
+ * @returns string
+ */
+ function addr_append($type, $addr) {
+ $addr_str = $type . ": ";
+ $addr_str .= $this->addr_format($addr[0]);
+ if(count($addr) > 1)
+ {
+ for($i = 1; $i < count($addr); $i++)
+ {
+ $addr_str .= sprintf(", %s", $this->addr_format($addr[$i]));
+ }
+ $addr_str .= $this->LE;
+ }
+ else
+ $addr_str .= $this->LE;
+
+ return($addr_str);
+ }
+
+ /**
+ * Creates a semicolon delimited list for use in pqm files.
+ * @private
+ * @returns string
+ */
+ function addr_list($list_array) {
+ $addr_list = "";
+ for($i = 0; $i < count($list_array); $i++)
+ {
+ if($i > 0)
+ $addr_list .= ";";
+ $addr_list .= $list_array[$i][0];
+ }
+
+ return $addr_list;
+ }
+
+ /**
+ * Formats an address correctly.
+ * @private
+ * @returns string
+ */
+ function addr_format($addr) {
+ if(empty($addr[1]))
+ $formatted = $addr[0];
+ else
+ $formatted = sprintf('"%s" <%s>', addslashes($addr[1]), $addr[0]);
+
+ return $formatted;
+ }
+
+ /**
+ * Wraps message for use with mailers that do not
+ * automatically perform wrapping and for quoted-printable.
+ * Original written by philippe. Returns string.
+ * @private
+ * @returns string
+ */
+ function word_wrap($message, $length, $qp_mode = false) {
+ if ($qp_mode)
+ $soft_break = sprintf(" =%s", $this->LE);
+ else
+ $soft_break = $this->LE;
+
+ $message = $this->fix_eol($message);
+ if (substr($message, -1) == $this->LE)
+ $message = substr($message, 0, -1);
+
+ $line = explode($this->LE, $message);
+ $message = "";
+ for ($i=0 ;$i < count($line); $i++)
+ {
+ $line_part = explode(" ", $line[$i]);
+ $buf = "";
+ for ($e = 0; $e $length))
+ {
+ $space_left = $length - strlen($buf) - 1;
+ if ($e != 0)
+ {
+ if ($space_left > 20)
+ {
+ $len = $space_left;
+ if (substr($word, $len - 1, 1) == "=")
+ $len--;
+ elseif (substr($word, $len - 2, 1) == "=")
+ $len -= 2;
+ $part = substr($word, 0, $len);
+ $word = substr($word, $len);
+ $buf .= " " . $part;
+ $message .= $buf . sprintf("=%s", $this->LE);
+ }
+ else
+ {
+ $message .= $buf . $soft_break;
+ }
+ $buf = "";
+ }
+ while (strlen($word) > 0)
+ {
+ $len = $length;
+ if (substr($word, $len - 1, 1) == "=")
+ $len--;
+ elseif (substr($word, $len - 2, 1) == "=")
+ $len -= 2;
+ $part = substr($word, 0, $len);
+ $word = substr($word, $len);
+
+ if (strlen($word) > 0)
+ $message .= $part . sprintf("=%s", $this->LE);
+ else
+ $buf = $part;
+ }
+ }
+ else
+ {
+ $buf_o = $buf;
+ if ($e == 0)
+ $buf .= $word;
+ else
+ $buf .= " " . $word;
+ if (strlen($buf) > $length and $buf_o != "")
+ {
+ $message .= $buf_o . $soft_break;
+ $buf = $word;
+ }
+ }
+ }
+ $message .= $buf . $this->LE;
+ }
+
+ return ($message);
+ }
+
+ /**
+ * Assembles message header. Returns a string if successful
+ * or false if unsuccessful.
+ * @private
+ * @returns string
+ */
+ function create_header() {
+ $header = array();
+
+ // Set the boundaries
+ $uniq_id = md5(uniqid(time()));
+ $this->boundary[1] = "b1_" . $uniq_id;
+ $this->boundary[2] = "b2_" . $uniq_id;
+
+ // To be created automatically by mail()
+ if(($this->Mailer != "mail") && (count($this->to) > 0))
+ $header[] = $this->addr_append("To", $this->to);
+
+ $header[] = sprintf("From: \"%s\" <%s>%s", addslashes($this->FromName),
+ trim($this->From), $this->LE);
+ if(count($this->cc) > 0)
+ $header[] = $this->addr_append("Cc", $this->cc);
+
+ // sendmail and mail() extract Bcc from the header before sending
+ if((($this->Mailer == "sendmail") || ($this->Mailer == "mail")) && (count($this->bcc) > 0))
+ $header[] = $this->addr_append("Bcc", $this->bcc);
+
+ if(count($this->ReplyTo) > 0)
+ $header[] = $this->addr_append("Reply-to", $this->ReplyTo);
+
+ // mail() sets the subject itself
+ if($this->Mailer != "mail")
+ $header[] = sprintf("Subject: %s%s", trim($this->Subject), $this->LE);
+
+ $header[] = sprintf("X-Priority: %d%s", $this->Priority, $this->LE);
+ $header[] = sprintf("X-Mailer: phpmailer [version %s]%s", $this->Version, $this->LE);
+ $header[] = sprintf("Return-Path: %s%s", trim($this->From), $this->LE);
+
+ if($this->ConfirmReadingTo != "")
+ $header[] = sprintf("Disposition-Notification-To: <%s>%s",
+ trim($this->ConfirmReadingTo), $this->LE);
+
+ // Add custom headers
+ for($index = 0; $index < count($this->CustomHeader); $index++)
+ $header[] = sprintf("%s%s", $this->CustomHeader[$index], $this->LE);
+
+ if($this->UseMSMailHeaders)
+ $header[] = $this->AddMSMailHeaders();
+
+ $header[] = sprintf("MIME-Version: 1.0%s", $this->LE);
+
+ // Determine what type of message this is
+ if(count($this->attachment) < 1 && strlen($this->AltBody) < 1)
+ $this->message_type = "plain";
+ else
+ {
+ if(count($this->attachment) > 0)
+ $this->message_type = "attachments";
+ if(strlen($this->AltBody) > 0 && count($this->attachment) < 1)
+ $this->message_type = "alt";
+ if(strlen($this->AltBody) > 0 && count($this->attachment) > 0)
+ $this->message_type = "alt_attachments";
+ }
+
+ switch($this->message_type)
+ {
+ case "plain":
+ $header[] = sprintf("Content-Transfer-Encoding: %s%s",
+ $this->Encoding, $this->LE);
+ $header[] = sprintf("Content-Type: %s; charset = \"%s\"",
+ $this->ContentType, $this->CharSet);
+ break;
+ case "attachments":
+ case "alt_attachments":
+ if($this->EmbeddedImageCount() > 0)
+ {
+ $header[] = sprintf("Content-Type: %s;%s\ttype=\"text/html\";%s\tboundary=\"%s\"%s",
+ "multipart/related", $this->LE, $this->LE,
+ $this->boundary[1], $this->LE);
+ }
+ else
+ {
+ $header[] = sprintf("Content-Type: %s;%s",
+ "multipart/mixed", $this->LE);
+ $header[] = sprintf("\tboundary=\"%s\"%s", $this->boundary[1], $this->LE);
+ }
+ break;
+ case "alt":
+ $header[] = sprintf("Content-Type: %s;%s",
+ "multipart/alternative", $this->LE);
+ $header[] = sprintf("\tboundary=\"%s\"%s", $this->boundary[1], $this->LE);
+ break;
+ }
+
+ // No additional lines when using mail() function
+ if($this->Mailer != "mail")
+ $header[] = $this->LE.$this->LE;
+
+ return(join("", $header));
+ }
+
+ /**
+ * Assembles the message body. Returns a string if successful
+ * or false if unsuccessful.
+ * @private
+ * @returns string
+ */
+ function create_body() {
+ $body = array();
+
+ // wordwrap the message body if set
+ if($this->WordWrap > 0)
+ $this->Body = $this->word_wrap($this->Body, $this->WordWrap);
+
+ switch($this->message_type)
+ {
+ case "alt":
+ // Return text of body
+ $bndry = new Boundary($this->boundary[1]);
+ $bndry->CharSet = $this->CharSet;
+ $bndry->Encoding = $this->Encoding;
+ $body[] = $bndry->GetSource();
+
+ $body[] = sprintf("%s%s", $this->AltBody, $this->LE.$this->LE);
+
+ $bndry = new Boundary($this->boundary[1]);
+ $bndry->CharSet = $this->CharSet;
+ $bndry->ContentType = "text/html";
+ $bndry->Encoding = $this->Encoding;
+ $body[] = $bndry->GetSource();
+
+ $body[] = sprintf("%s%s", $this->Body, $this->LE.$this->LE);
+
+ // End the boundary
+ $body[] = sprintf("%s--%s--%s", $this->LE,
+ $this->boundary[1], $this->LE.$this->LE);
+ break;
+ case "plain":
+ $body[] = $this->Body;
+ break;
+ case "attachments":
+ $bndry = new Boundary($this->boundary[1]);
+ $bndry->CharSet = $this->CharSet;
+ $bndry->ContentType = $this->ContentType;
+ $bndry->Encoding = $this->Encoding;
+ $body[] = sprintf("%s%s%s%s", $bndry->GetSource(false), $this->LE,
+ $this->Body, $this->LE);
+
+ if(!$body[] = $this->attach_all())
+ return false;
+ break;
+ case "alt_attachments":
+ $body[] = sprintf("--%s%s", $this->boundary[1], $this->LE);
+ $body[] = sprintf("Content-Type: %s;%s" .
+ "\tboundary=\"%s\"%s",
+ "multipart/alternative", $this->LE,
+ $this->boundary[2], $this->LE.$this->LE);
+
+ // Create text body
+ $bndry = new Boundary($this->boundary[2]);
+ $bndry->CharSet = $this->CharSet;
+ $bndry->ContentType = "text/plain";
+ $bndry->Encoding = $this->Encoding;
+ $body[] = $bndry->GetSource() . $this->LE;
+
+ $body[] = sprintf("%s%s", $this->AltBody, $this->LE.$this->LE);
+
+ // Create the HTML body
+ $bndry = new Boundary($this->boundary[2]);
+ $bndry->CharSet = $this->CharSet;
+ $bndry->ContentType = "text/html";
+ $bndry->Encoding = $this->Encoding;
+ $body[] = $bndry->GetSource() . $this->LE;
+
+ $body[] = sprintf("%s%s", $this->Body, $this->LE.$this->LE);
+
+ $body[] = sprintf("%s--%s--%s", $this->LE,
+ $this->boundary[2], $this->LE.$this->LE);
+
+ if(!$body[] = $this->attach_all())
+ return false;
+ break;
+ }
+ // Add the encode string code here
+ $sBody = join("", $body);
+ $sBody = $this->encode_string($sBody, $this->Encoding);
+
+ return $sBody;
+ }
+
+
+ /////////////////////////////////////////////////
+ // ATTACHMENT METHODS
+ /////////////////////////////////////////////////
+
+ /**
+ * Adds an attachment from a path on the filesystem.
+ * Checks if attachment is valid and then adds
+ * the attachment to the list.
+ * Returns false if the file could not be found
+ * or accessed.
+ * @public
+ * @returns bool
+ */
+ function AddAttachment($path, $name = "", $encoding = "base64", $type = "application/octet-stream") {
+ if(!@is_file($path))
+ {
+ $this->error_handler(sprintf("Could not access [%s] file", $path));
+ return false;
+ }
+
+ $filename = basename($path);
+ if($name == "")
+ $name = $filename;
+
+ // Append to $attachment array
+ $cur = count($this->attachment);
+ $this->attachment[$cur][0] = $path;
+ $this->attachment[$cur][1] = $filename;
+ $this->attachment[$cur][2] = $name;
+ $this->attachment[$cur][3] = $encoding;
+ $this->attachment[$cur][4] = $type;
+ $this->attachment[$cur][5] = false; // isStringAttachment
+ $this->attachment[$cur][6] = "attachment";
+ $this->attachment[$cur][7] = 0;
+
+ return true;
+ }
+
+ /**
+ * Attaches all fs, string, and binary attachments to the message.
+ * Returns a string if successful or false if unsuccessful.
+ * @private
+ * @returns string
+ */
+ function attach_all() {
+ // Return text of body
+ $mime = array();
+
+ // Add all attachments
+ for($i = 0; $i < count($this->attachment); $i++)
+ {
+ // Check for string attachment
+ $isString = $this->attachment[$i][5];
+ if ($isString)
+ {
+ $string = $this->attachment[$i][0];
+ }
+ else
+ {
+ $path = $this->attachment[$i][0];
+ }
+ $filename = $this->attachment[$i][1];
+ $name = $this->attachment[$i][2];
+ $encoding = $this->attachment[$i][3];
+ $type = $this->attachment[$i][4];
+ $disposition = $this->attachment[$i][6];
+ $cid = $this->attachment[$i][7];
+
+ $mime[] = sprintf("--%s%s", $this->boundary[1], $this->LE);
+ $mime[] = sprintf("Content-Type: %s; name=\"%s\"%s", $type, $name, $this->LE);
+ $mime[] = sprintf("Content-Transfer-Encoding: %s%s", $encoding, $this->LE);
+
+ if($disposition == "inline")
+ $mime[] = sprintf("Content-ID: <%s>%s", $cid, $this->LE);
+ else
+ $mime[] = sprintf("Content-ID: <%s>%s", $name, $this->LE);
+
+ $mime[] = sprintf("Content-Disposition: %s; filename=\"%s\"%s",
+ $disposition, $name, $this->LE.$this->LE);
+
+ // Encode as string attachment
+ if($isString)
+ {
+ if(!$mime[] = sprintf("%s%s", $this->encode_string($string, $encoding),
+ $this->LE.$this->LE))
+ return false;
+ }
+ else
+ {
+ if(!$mime[] = sprintf("%s%s", $this->encode_file($path, $encoding),
+ $this->LE.$this->LE))
+ return false;
+
+ $mime[] = sprintf("--%s--%s", $this->boundary[1], $this->LE);
+
+ }
+ }
+
+ return(join("", $mime));
+ }
+
+ /**
+ * Encodes attachment in requested format. Returns a
+ * string if successful or false if unsuccessful.
+ * @private
+ * @returns string
+ */
+ function encode_file ($path, $encoding = "base64") {
+ if(!@$fd = fopen($path, "rb"))
+ {
+ $this->error_handler(sprintf("File Error: Could not open file %s", $path));
+ return false;
+ }
+ $file = fread($fd, filesize($path));
+ $encoded = $this->encode_string($file, $encoding);
+ fclose($fd);
+
+ return($encoded);
+ }
+
+ /**
+ * Encodes string to requested format. Returns a
+ * string if successful or false if unsuccessful.
+ * @private
+ * @returns string
+ */
+ function encode_string ($str, $encoding = "base64") {
+ switch(strtolower($encoding)) {
+ case "base64":
+ // chunk_split is found in PHP >= 3.0.6
+ $encoded = chunk_split(base64_encode($str));
+ break;
+
+ case "7bit":
+ case "8bit":
+ $encoded = $this->fix_eol($str);
+ if (substr($encoded, -2) != $this->LE)
+ $encoded .= $this->LE;
+ break;
+
+ case "binary":
+ $encoded = $str;
+ break;
+
+ case "quoted-printable":
+ $encoded = $this->encode_qp($str);
+ break;
+
+ default:
+ $this->error_handler(sprintf("Unknown encoding: %s", $encoding));
+ return false;
+ }
+ return($encoded);
+ }
+
+ /**
+ * Encode string to quoted-printable. Returns a string.
+ * @private
+ * @returns string
+ */
+ function encode_qp ($str) {
+ $encoded = $this->fix_eol($str);
+ if (substr($encoded, -2) != $this->LE)
+ $encoded .= $this->LE;
+
+ // Replace every high ascii, control and = characters
+ $encoded = preg_replace("/([\001-\010\013\014\016-\037\075\177-\377])/e",
+ "'='.sprintf('%02X', ord('\\1'))", $encoded);
+ // Replace every spaces and tabs when it's the last character on a line
+ $encoded = preg_replace("/([\011\040])".$this->LE."/e",
+ "'='.sprintf('%02X', ord('\\1')).'".$this->LE."'", $encoded);
+
+ // Maximum line length of 76 characters before CRLF (74 + space + '=')
+ $encoded = $this->word_wrap($encoded, 74, true);
+
+ return $encoded;
+ }
+
+ /**
+ * Adds a string or binary attachment (non-filesystem) to the list.
+ * This method can be used to attach ascii or binary data,
+ * such as a BLOB record from a database.
+ * @public
+ * @returns void
+ */
+ function AddStringAttachment($string, $filename, $encoding = "base64", $type = "application/octet-stream") {
+ // Append to $attachment array
+ $cur = count($this->attachment);
+ $this->attachment[$cur][0] = $string;
+ $this->attachment[$cur][1] = $filename;
+ $this->attachment[$cur][2] = $filename;
+ $this->attachment[$cur][3] = $encoding;
+ $this->attachment[$cur][4] = $type;
+ $this->attachment[$cur][5] = true; // isString
+ $this->attachment[$cur][6] = "attachment";
+ $this->attachment[$cur][7] = 0;
+ }
+
+ /**
+ * Adds an embedded attachment. This can include images, sounds, and
+ * just about any other document.
+ * @param cid this is the Content Id of the attachment. Use this to identify
+ * the Id for accessing the image in an HTML form.
+ * @public
+ * @returns bool
+ */
+ function AddEmbeddedImage($path, $cid, $name = "", $encoding = "base64", $type = "application/octet-stream") {
+
+ if(!@is_file($path))
+ {
+ $this->error_handler(sprintf("Could not access [%s] file", $path));
+ return false;
+ }
+
+ $filename = basename($path);
+ if($name == "")
+ $name = $filename;
+
+ // Append to $attachment array
+ $cur = count($this->attachment);
+ $this->attachment[$cur][0] = $path;
+ $this->attachment[$cur][1] = $filename;
+ $this->attachment[$cur][2] = $name;
+ $this->attachment[$cur][3] = $encoding;
+ $this->attachment[$cur][4] = $type;
+ $this->attachment[$cur][5] = false; // isStringAttachment
+ $this->attachment[$cur][6] = "inline";
+ $this->attachment[$cur][7] = $cid;
+
+ return true;
+ }
+
+ /**
+ * Returns the number of embedded images in an email.
+ * @private
+ * @returns int
+ */
+ function EmbeddedImageCount() {
+ $ret = 0;
+ for($i = 0; $i < count($this->attachment); $i++)
+ {
+ if($this->attachment[$i][6] == "inline")
+ $ret++;
+ }
+
+ return $ret;
+ }
+
+ /////////////////////////////////////////////////
+ // MESSAGE RESET METHODS
+ /////////////////////////////////////////////////
+
+ /**
+ * Clears all recipients assigned in the TO array. Returns void.
+ * @public
+ * @returns void
+ */
+ function ClearAddresses() {
+ $this->to = array();
+ }
+
+ /**
+ * Clears all recipients assigned in the CC array. Returns void.
+ * @public
+ * @returns void
+ */
+ function ClearCCs() {
+ $this->cc = array();
+ }
+
+ /**
+ * Clears all recipients assigned in the BCC array. Returns void.
+ * @public
+ * @returns void
+ */
+ function ClearBCCs() {
+ $this->bcc = array();
+ }
+
+ /**
+ * Clears all recipients assigned in the ReplyTo array. Returns void.
+ * @public
+ * @returns void
+ */
+ function ClearReplyTos() {
+ $this->ReplyTo = array();
+ }
+
+ /**
+ * Clears all recipients assigned in the TO, CC and BCC
+ * array. Returns void.
+ * @public
+ * @returns void
+ */
+ function ClearAllRecipients() {
+ $this->to = array();
+ $this->cc = array();
+ $this->bcc = array();
+ }
+
+ /**
+ * Clears all previously set filesystem, string, and binary
+ * attachments. Returns void.
+ * @public
+ * @returns void
+ */
+ function ClearAttachments() {
+ $this->attachment = array();
+ }
+
+ /**
+ * Clears all custom headers. Returns void.
+ * @public
+ * @returns void
+ */
+ function ClearCustomHeaders() {
+ $this->CustomHeader = array();
+ }
+
+
+ /////////////////////////////////////////////////
+ // MISCELLANEOUS METHODS
+ /////////////////////////////////////////////////
+
+ /**
+ * Adds the error message to the error container.
+ * Returns void.
+ * @private
+ * @returns void
+ */
+ function error_handler($msg) {
+ $this->ErrorInfo = $msg;
+ }
+
+ /**
+ * Returns the proper RFC 822 formatted date. Returns string.
+ * @private
+ * @returns string
+ */
+ function rfc_date() {
+ $tz = date("Z");
+ $tzs = ($tz < 0) ? "-" : "+";
+ $tz = abs($tz);
+ $tz = ($tz/3600)*100 + ($tz%3600)/60;
+ $date = sprintf("%s %s%04d", date("D, j M Y H:i:s"), $tzs, $tz);
+ return $date;
+ }
+
+ /**
+ * Returns received header for message tracing. Returns string.
+ * @private
+ * @returns string
+ */
+ function received() {
+ // Check for vars because they might not exist. Possibly
+ // write a small retrieval function (that mailer can use too!)
+
+ $str = sprintf("Received: from phpmailer ([%s]) by %s " .
+ "with HTTP;%s\t %s%s",
+ $this->get_server_var("REMOTE_ADDR"),
+ $this->get_server_var("SERVER_NAME"),
+ $this->LE,
+ $this->rfc_date(),
+ $this->LE);
+
+ return $str;
+ }
+
+ /**
+ * Returns the appropriate server variable. Should work with both
+ * PHP 4.1.0+ as well as older versions. Returns an empty string
+ * if nothing is found.
+ * @private
+ * @returns mixed
+ */
+ function get_server_var($varName) {
+ global $HTTP_SERVER_VARS;
+ global $HTTP_ENV_VARS;
+
+ if(!isset($_SERVER))
+ {
+ $_SERVER = $HTTP_SERVER_VARS;
+ if(!isset($_SERVER["REMOTE_ADDR"]))
+ $_SERVER = $HTTP_ENV_VARS; // must be Apache
+ }
+
+ if(isset($_SERVER[$varName]))
+ return $_SERVER[$varName];
+ else
+ return "";
+ }
+
+ /**
+ * Changes every end of line from CR or LF to CRLF. Returns string.
+ * @private
+ * @returns string
+ */
+ function fix_eol($str) {
+ $str = str_replace("\r\n", "\n", $str);
+ $str = str_replace("\r", "\n", $str);
+ $str = str_replace("\n", $this->LE, $str);
+ return $str;
+ }
+
+ /**
+ * Adds a custom header. Returns void.
+ * @public
+ * @returns void
+ */
+ function AddCustomHeader($custom_header) {
+ $this->CustomHeader[] = $custom_header;
+ }
+
+ /**
+ * Adds all the Microsoft message headers. Returns string.
+ * @private
+ * @returns string
+ */
+ function AddMSMailHeaders() {
+ $MSHeader = "";
+ if($this->Priority == 1)
+ $MSPriority = "High";
+ elseif($this->Priority == 5)
+ $MSPriority = "Low";
+ else
+ $MSPriority = "Medium";
+
+ $MSHeader .= sprintf("X-MSMail-Priority: %s%s", $MSPriority, $this->LE);
+ $MSHeader .= sprintf("Importance: %s%s", $MSPriority, $this->LE);
+
+ return($MSHeader);
+ }
+
+}
+
+
+/**
+ * Boundary - MIME message boundary class
+ * @author Brent R. Matzelle
+ */
+class Boundary
+{
+ /**
+ * Sets the boundary ID.
+ * @private
+ * @type string
+ */
+ var $ID = 0;
+
+ /**
+ * Sets the boundary Content Type.
+ * @public
+ * @type string
+ */
+ var $ContentType = "text/plain";
+
+ /**
+ * Sets the Encoding.
+ * @public
+ * @type string
+ */
+ var $Encoding = "";
+
+ /**
+ * Sets an attachment disposition.
+ * @public
+ * @type string
+ */
+ var $Disposition = "";
+
+ /**
+ * Sets an attachment file name.
+ * @public
+ * @type string
+ */
+ var $FileName = "";
+
+ /**
+ * Sets the Char set.
+ * @public
+ * @type string
+ */
+ var $CharSet = "";
+
+ /**
+ * Sets the line endings of the message. Default is "\n";
+ * @public
+ * @type string
+ */
+ var $LE = "\n";
+
+ /**
+ * Main constructor.
+ */
+ function Boundary($boundary_id) {
+ $this->ID = $boundary_id;
+ }
+
+ /**
+ * Returns the source of the boundary.
+ * @public
+ * @returns string
+ */
+ function GetSource($bLineEnding = true) {
+ $ret = array();
+ $mime[] = sprintf("--%s%s", $this->ID, $this->LE);
+ $mime[] = sprintf("Content-Type: %s; charset = \"%s\"%s",
+ $this->ContentType, $this->CharSet, $this->LE);
+ //$mime[] = sprintf("Content-Transfer-Encoding: %s%s", $this->Encoding,
+ // $this->LE);
+
+ if(strlen($this->Disposition) > 0)
+ {
+ $mime[] = sprintf("Content-Disposition: %s;");
+ if(strlen($this->FileName) > 0)
+ $mime[] = sprinf("filename=\"%s\"", $this->$this->FileName);
+ }
+
+ if($bLineEnding)
+ $mime[] = $this->LE;
+
+ return join("", $mime);
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/classes/sm/smCore.class.php b/classes/sm/smCore.class.php
new file mode 100644
index 00000000..71809ae6
--- /dev/null
+++ b/classes/sm/smCore.class.php
@@ -0,0 +1,34 @@
+.
+ */
+
+abstract class smCore {
+ public $db;
+
+ function __construct() {
+ // add database handler
+ $this->db = $GLOBALS['db'];
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/classes/sm/smDatabase.class.php b/classes/sm/smDatabase.class.php
new file mode 100644
index 00000000..cc668403
--- /dev/null
+++ b/classes/sm/smDatabase.class.php
@@ -0,0 +1,365 @@
+.
+ */
+
+class smDatabase {
+
+ protected $debug = array();
+ protected $last_inserted_id;
+ protected $link;
+ protected $num_rows_found;
+ protected $num_rows_returned;
+
+ function __construct() {
+ // Initizale connection
+ $this->link = mysql_connect(SM_DB_HOST, SM_DB_USER, SM_DB_PASS);
+
+ if (!mysql_select_db(SM_DB_NAME, $this->link)) {
+ trigger_error(mysql_errno() . ": " . mysql_error());
+ }
+
+ // Setting the utf collection
+ mysql_query("SET NAMES utf8;", $this->getLink());
+ mysql_query("SET CHARACTER SET 'utf8';", $this->getLink());
+ }
+
+ /**
+ * Executes a query
+ *
+ * @param $sql string MySQL query
+ * @return resource mysql resource
+ */
+
+ public function executeQuery($sql) {
+
+ $result = mysql_query($sql, $this->getLink());
+
+ if (mysql_error($this->getLink())) {
+ trigger_error(mysql_errno($this->getLink()) . ': ' . mysql_error($this->getLink()));
+ return false;
+ }
+
+ if (is_resource($result) && mysql_num_rows($result) > 0) {
+ // Rows returned
+ $this->num_rows_returned = mysql_num_rows($result);
+
+ // Rows found
+ $result_num_rows_found = $this->fetchResults(mysql_query('SELECT FOUND_ROWS();'));
+ $this->num_rows_found = $result_num_rows_found[0]['FOUND_ROWS()'];
+ }
+
+ if (substr(strtolower(trim($sql)), 0, 6) == 'insert') {
+ // we have an insert
+ $this->last_inserted_id = mysql_insert_id($this->getLink());
+ $result = $this->last_inserted_id;
+ }
+
+ return $result;
+ }
+
+ /**
+ * Exectues query and fetches result
+ *
+ * @param $query string MySQL query
+ * @return $result array
+ */
+ public function query($query) {
+
+ // Execute query and process results
+ $result_resource = $this->executeQuery($query);
+ $result = $this->fetchResults($result_resource);
+
+ return $result;
+ }
+
+ /**
+ * Fetch results from a query
+ *
+ * @param resource $result result from a mysql query
+ * @return array $array with results (multi-dimimensial) for more than one rows
+ */
+
+ public function fetchResults($result_query){
+
+ if (!is_resource($result_query)) {
+ return array();
+ }
+
+ $num_rows = mysql_num_rows($result_query);
+
+ $result = array();
+ while($record = mysql_fetch_assoc($result_query)) {
+ $result[] = $record;
+ }
+
+ return $result;
+ }
+
+ /**
+ * Performs a select on the given table and returns an multi dimensional associative array with results
+ *
+ * @param string $table tablename
+ * @param mixed $where string or array with where data
+ * @param array $fields array with fields to be retrieved. if empty all fields will be retrieved
+ * @param string $limit limit. for example: 0,30
+ * @param array $orderby fields for the orderby clause
+ * @param string $direction ASC or DESC. Defaults to ASC
+ * @return array multi dimensional array with results
+ */
+
+ public function select($table, $where = null, $fields = null, $limit = '', $orderby = null, $direction = 'ASC'){
+ // build query
+ $query_parts = array();
+ $query_parts[] = 'SELECT SQL_CALC_FOUND_ROWS';
+
+ // Fields
+ if ($fields !== null && !empty($fields)) {
+ $query_parts[] = "`".implode('`,`', $fields)."`";
+ } else {
+ $query_parts[] = ' * ';
+ }
+
+ // From
+ $query_parts[] = "FROM `{$table}`";
+
+ // Where clause
+ $query_parts[] = $this->buildWhereClause($table, $where);
+
+ // Order by
+ if ($orderby !== null && !empty($orderby)) {
+ $orderby_clause = 'ORDER BY ';
+
+ foreach($orderby as $field) {
+ $orderby_clause .= "`{$field}`, ";
+ }
+ $query_parts[] = substr($orderby_clause, 0, -2) . ' ' . $direction;
+ }
+
+ // Limit
+ if ($limit != '') {
+ $query_parts[] = 'LIMIT ' . $limit;
+ }
+
+ $query = implode(' ', $query_parts);
+
+ // Get results
+ $result = $this->query($query);
+
+ return $result;
+ }
+
+ public function selectRow($table, $where = null, $fields = null, $limit = '', $orderby = null, $direction = 'ASC') {
+ $result = $this->select($table, $where, $fields, $limit, $orderby, $direction);
+
+ if ($this->getNumRowsReturned() == '1') {
+ $result = $result[0];
+ }
+ return $result;
+ }
+
+ /**
+ * Remove a record from database
+ *
+ * @param string $table tablename
+ * @param mixed $where Where clause array or primary Id (string) or where clause (string)
+ * @return boolean
+ */
+ public function delete($table, $where = null){
+
+ if ($table != '') {
+
+ $sql = 'DELETE FROM `'.$table.'` ' . $this->buildWhereClause($table, $where);
+
+ $this->query($sql);
+ }
+ }
+
+ /**
+ * Insert or update data to the database
+ *
+ * @param array $table table name
+ * @param array $data data to save or insert
+ * @param mixed $where either string ('user_id=2' or just '2' (works only with primary field)) or array with where clause (only when updating)
+ */
+ public function save($table, $data, $where = null) {
+
+ if ($where === null) {
+ // insert mode
+ $query = "INSERT INTO ";
+ } else {
+ $query = "UPDATE ";
+ }
+
+ $query .= "`{$table}` SET ";
+
+ foreach($data as $field => $value) {
+ $value = $this->escapeValue($value);
+ $query .= "`{$table}`.`{$field}`='{$value}', ";
+ }
+
+ $query = substr($query, 0, -2) . ' ' . $this->buildWhereClause($table, $where);
+
+ return $this->query($query);
+ }
+
+ /**
+ * Build WHERE clause for query
+ *
+ * @param string $table table name
+ * @param mixed $where can be primary id (eg '2'), can be string (eg 'name=pepe') or can be array
+ * @return string sql where clause
+ */
+ public function buildWhereClause($table, $where = null) {
+
+ $query = '';
+
+ if ($where !== null) {
+ if (is_array($where)) {
+ $query .= " WHERE ";
+
+ foreach($where as $field => $value) {
+ $value = $this->escapeValue($value);
+ $query .= "`{$table}`.`{$field}`='{$value}' AND ";
+ }
+ $query = substr($query, 0, -5);
+ } else {
+ if (strpos($where, '=') === false) {
+ // no field given, use primary field
+ $structure = $this->getTableStructure($table);
+ $where = $this->escapeValue($where);
+ $query .= " WHERE `{$table}`.`{$structure['primary']}`='{$where}'";
+ } elseif (strpos(strtolower(trim($where)), 'where') === false) {
+ $query .= " WHERE {$where}";
+ } else {
+ $query .= ' '.$where;
+ }
+ }
+ }
+ return $query;
+ }
+
+ /**
+ * Get table structure and primary key
+ *
+ * @param string $table table name
+ * @return array primary key and database structure
+ */
+ public function getTableStructure($table) {
+ if ($table == '') return false;
+
+ $structure = $this->query("DESCRIBE `{$table}`");
+
+ if (empty($structure)) return false;
+
+ // use arrray search function to get primary key
+ $search_needle = array(
+ 'key' => 'Key',
+ 'value' => 'PRI'
+ );
+ $primary = pep_array_search_key_value(
+ $structure,
+ array(
+ 'key' => 'Key',
+ 'value' => 'PRI'
+ )
+ );
+
+ $primary_field = $structure[$primary[0]['path'][0]]['Field'];
+ return array(
+ 'primary' => $primary_field,
+ 'fields' => $structure
+ );
+ }
+
+ /**
+ * Get information about a field from the database
+ *
+ * @param string $table
+ * @param string $field
+ * @return array mysql field information
+ */
+ public function getFieldInfo($table, $field) {
+ if ($table == '' || $field == '') return array();
+
+ $db_structure = $this->getTableStructure($table);
+
+ $field_info = pep_array_search_key_value(
+ $db_structure,
+ array(
+ 'key' => 'Field',
+ 'value' => $field
+ )
+ );
+
+ if (empty($field_info)) {
+ return array();
+ }
+
+ // return field info
+ return $field_info[0]['result'];
+ }
+
+ /**
+ * Formats the value for the SQL query to secure against injections
+ *
+ * @param string $value
+ * @return string
+ */
+ public function escapeValue($value) {
+ if(get_magic_quotes_gpc()) {
+ $value = stripslashes($value);
+ }
+ $value = mysql_real_escape_string($value, $this->link);
+
+ return $value;
+ }
+
+ /**
+ * Get number of rows found
+ *
+ * @return int number of rows found
+ */
+ public function getNumRowsFound() {
+ return $this->num_rows_found;
+ }
+
+ /**
+ * Get number of rows returned
+ *
+ * @return int number of rows returned
+ */
+ public function getNumRowsReturned() {
+ return $this->num_rows_returned;
+ }
+
+ /**
+ * Get the database connection identifier
+ *
+ * @return object db connection
+ */
+ public function getLink() {
+ return $this->link;
+ }
+}
+
+?>
diff --git a/classes/sm/smTemplate.class.php b/classes/sm/smTemplate.class.php
new file mode 100644
index 00000000..332f0c7d
--- /dev/null
+++ b/classes/sm/smTemplate.class.php
@@ -0,0 +1,307 @@
+.
+ */
+
+class smTemplate {
+ protected $css_files = array();
+ protected $js_files = array();
+ protected $output;
+ protected $templates = array();
+
+ function __construct() {
+ // add the main template
+ $this->newTemplate('main', 'main.tpl.html');
+ }
+
+ /**
+ * Add template
+ *
+ * @param string $id template id used in the tpl file (html)
+ * @param string $filename path to template file, or if file is located in the default template dir just the filename
+ * @return mixed false if template cannot be found, html code on success
+ */
+ public function newTemplate($id, $filename) {
+ if (file_exists($filename)) {
+ $this->templates[$id] = $this->parseFile($filename);
+ } elseif (file_exists(SM_PATH_TPL.$filename)) {
+ $this->templates[$id] = $this->parseFile(SM_PATH_TPL.$filename);
+ } else {
+ // file does not exist
+ trigger_error('Template not found with id: '.$id.' and filename: '.$filename);
+ return false;
+ }
+ $use_tpl = null;
+
+ // only get data from the file that's between the tpl id tags with this id
+ // find "tpl_{$row_id}" in the current template
+ //preg_match_all('{(.*?)}is', $this->templates[$id], $matches);
+ preg_match_all("{(.*?)}is", $this->templates[$id], $matches);
+
+ // no repeat tpl found? skip to next one
+ if (empty($matches)) return false;
+
+ // check if the row_id is in one of the matches (aka whether the supplied row id actually has a template in this file)
+ if (isset($matches[1][0])) {
+ $use_tpl = $matches[1][0];
+ }
+
+ // no template with the given id found..
+ if ($use_tpl === null) return false;
+
+ // remove tpl code tags from original template so it won't be in the source
+ $this->templates[$id] = preg_replace("{(.*?)}is", "", $use_tpl);
+
+ return $this->templates[$id];
+ }
+
+ /**
+ * Add data to the template
+ *
+ * @param string $id template_id used by add_template()
+ * @param array $data
+ * @return string new template
+ */
+ public function addTemplateData($id, $data) {
+ // does the template exist?
+ if (!isset($this->templates[$id])) {
+ // file does not exist
+ trigger_error('Template not found with id: '.$id);
+ return false;
+ }
+
+ foreach($data as $key => $value) {
+ // check if $value is a file
+ $value = (file_exists($value)) ? $this->parseFile($value) : $value;
+
+ $this->templates[$id] = str_replace('{'.$key.'}', $value, $this->templates[$id]);
+ }
+ return $this->templates[$id];
+ }
+
+ /**
+ * Add repeat rows to template
+ *
+ * @param string $id template id used by add_template()
+ * @param string $repeat_id ID used in template file for the repeat template: html
+ * @param array $data
+ * @return mixed false if repeat template cannot be found, html code on success
+ */
+ public function addTemplateDataRepeat($id, $repeat_id, $data) {
+ // does the template exist?
+ if (!isset($this->templates[$id])) {
+ // file does not exist
+ trigger_error('Template not found with id: '.$id);
+ return false;
+ }
+
+ $use_tpl = null;
+
+ // find "tpl_repeat_{$repeat_id}_" in the current template
+ //preg_match_all('{(.*?)}is', $this->templates[$id], $matches);
+ preg_match_all("{(.*?)}is", $this->templates[$id], $matches);
+
+ // no repeat tpl found? skip to next one
+ if (empty($matches)) return false;
+
+ // check if the row_id is in one of the matches (aka whether the supplied row id actually has a repeat template in this file)
+ if (isset($matches[1][0])) {
+ $use_tpl = $matches[1][0];
+ }
+
+ // if we didn't find a repeat template for the row_id supplied, skip the rest..
+ if ($use_tpl === null) return false;
+
+ // remove repeat tpl code from original template so it won't be in the source
+ $this->templates[$id] = preg_replace("{(.*?)}is", "", $this->templates[$id]);
+
+ // now lets go through all the records supplied and put them in the HTML repeat code we just found
+ $result = '';
+
+ foreach($data as $record) {
+ $tmp_string = $use_tpl;
+ foreach($record as $k => $v) {
+ $tmp_string = str_replace('{'.$k.'}', $v, $tmp_string);
+ }
+ $result .= $tmp_string."\n";
+ }
+
+ // add to main template..
+ return $this->addTemplateData($id, array($repeat_id => $result));
+ }
+
+ public function display($id) {
+ // check if there are any unused tpl_repeat templates, and if there are remove them
+ $result = preg_replace('{(.*?)}is', '', $this->templates[$id]);
+
+ // check for tpl variables that have not been replaced. ie: {name}. ignore literal stuff, though. ie: {{name}} is {name} and should not be removed
+ preg_match_all('~{?{(.+?)}}?~', $result, $matches);
+
+ // add css and javascript files to header
+ $result = $this->addHeaderFiles($id, $result);
+
+ foreach($matches[0] as $match) {
+ if (substr($match, 0, 2) == '{{') {
+ // literal! remove only first and last bracket!
+ $result = str_replace($match, substr($match, 1, -1), $result);
+ } else {
+ // unused variable, remove completely
+ $result = str_replace($match, '', $result);
+ }
+ }
+ return $result;
+ }
+
+ /**
+ * Adds a css file to the list which will be added to the template when display() is called
+ *
+ * @param string $template_id
+ * @param string $filename
+ * @param string $path uses default set in config if non specified
+ */
+ public function addCSS($filename, $template_id = 'main', $path = SM_PATH_CSS) {
+ if (!isset($this->css_files[$template_id])) {
+ $this->css_files[$template_id] = array();
+ }
+
+ // if file doesn't exist we assume it's inline
+ $type = (file_exists($path.$filename)) ? 'file' : 'inline';
+
+ $this->css_files[$template_id][$filename] = array(
+ 'file' => ($type == 'file') ? $path.$filename : $filename,
+ 'type' => $type
+ );
+ }
+
+ /**
+ * Adds a javascript file to the list which will be added to the template when display() is called
+ *
+ * @param string $template_id
+ * @param string $filename path to file or CSS code to be added inline
+ * @param string $path uses default set in config if non specified
+ */
+ public function addJS($filename, $template_id = 'main', $path = SM_PATH_JS) {
+ if (!isset($this->js_files[$template_id])) {
+ $this->js_files[$template_id] = array();
+ }
+
+ // if file doesn't exist we assume it's inline
+ $type = (file_exists($path.$filename)) ? 'file' : 'inline';
+
+ $this->js_files[$template_id][$filename] = array(
+ 'file' => ($type == 'file') ? $path.$filename : $filename,
+ 'type' => $type
+ );
+ }
+
+ /**
+ * Get html code for a template, or if no template id given get all templates
+ *
+ * @param string $template_id
+ * @return mixed string when ID given, else array
+ */
+ public function getTemplate($template_id = null) {
+ if ($template_id === null) {
+ return $this->templates;
+ } elseif (isset($this->templates[$template_id])) {
+ return $this->templates[$template_id];
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Adds the CSS and JavaScript files to the header html.
+ *
+ * @param string $template_id
+ * @param string $html
+ * @return string new html code
+ */
+ protected function addHeaderFiles($template_id, $html) {
+ // get code between tags
+ preg_match_all("{(.*?)<\/head>}is", $html, $matches);
+
+ if (isset($matches[1][0]) && $matches[1][0] != '') {
+ $header = $matches[1][0];
+
+ if (isset($this->css_files[$template_id]) && !empty($this->css_files[$template_id])) {
+ $header .= "\t\n";
+
+ foreach($this->css_files[$template_id] as $filename => $info) {
+ switch($info['type']) {
+ case 'file':
+ $header .= "\t\n";
+ break;
+ case 'inline':
+ $header .=
+ "\t\n";
+ break;
+ }
+ }
+ }
+
+ if (isset($this->js_files[$template_id]) && !empty($this->js_files[$template_id])) {
+ $header .= "\t\n";
+
+ foreach($this->js_files[$template_id] as $filename => $info) {
+ switch($info['type']) {
+ case 'file':
+ $header .= "\t\n";
+ break;
+ case 'inline':
+ $header .=
+ "\t\n";
+ break;
+ }
+ }
+ }
+ // add new header to html
+ $html = preg_replace('{'.$matches[1][0].'}is', $header, $html);
+ }
+
+ return $html;
+ }
+
+ /**
+ *
+ * Get file content
+ *
+ * @param string $filename filename
+ * @return string file contents
+ */
+ protected function parseFile($filename) {
+ if (!file_exists($filename)) return false;
+
+ ob_start();
+ include($filename);
+ $file_content = ob_get_contents();
+ ob_end_clean();
+
+ return $file_content;
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/classes/sm/smUpdaterStatus.class.php b/classes/sm/smUpdaterStatus.class.php
new file mode 100644
index 00000000..d1a15589
--- /dev/null
+++ b/classes/sm/smUpdaterStatus.class.php
@@ -0,0 +1,354 @@
+.
+ */
+
+class smUpdaterStatus extends smCore {
+ public $error;
+ public $notify;
+ public $rtime = 0;
+ public $server;
+ public $status_org = false;
+ public $status_new = false;
+
+ /**
+ * Set a new server
+ *
+ * @param array $server
+ * @param string $status_org either 'on' or 'off'
+ */
+ public function setServer($server, $status_org) {
+ $this->clearResults();
+
+ $this->server = $server;
+ $this->status_org = $status_org;
+ }
+
+ /**
+ * Get the new status of the selected server. If the update has not been performed yet it will do so first
+ *
+ * @return string
+ */
+ public function getStatus() {
+ if(!$this->server) {
+ return false;
+ }
+ if(!$this->status_new) {
+ $this->update();
+ }
+ return $this->status_new;
+ }
+
+ /**
+ * The function its all about. This one checks whether the given ip and port are up and running!
+ * If the server check fails it will try one more time
+ *
+ * @param int $max_runs how many times should the script recheck the server if unavailable. default is 2
+ * @return string new status
+ */
+ public function update($max_runs = 2) {
+ switch($this->server['type']) {
+ case 'service':
+ $result = $this->updateService($max_runs);
+ break;
+ case 'website':
+ $result = $this->updateWebsite($max_runs);
+ break;
+ }
+ return $result;
+
+ }
+
+ protected function updateService($max_runs, $run = 1) {
+ // save response time
+ $time = explode(' ', microtime());
+ $starttime = $time[1] + $time[0];
+
+ @$fp = fsockopen ($this->server['ip'], $this->server['port'], $errno, $errstr, 10);
+
+ $time = explode(" ", microtime());
+ $endtime = $time[1] + $time[0];
+ $this->rtime = ($endtime - $starttime);
+
+
+ $this->status_new = ($fp === false) ? 'off' : 'on';
+ $this->error = $errstr;
+ // add the error to the server array for when parsing the messages
+ $this->server['error'] = $this->error;
+
+ @fclose($fp);
+
+ // check if server is available and rerun if asked.
+ if($this->status_new == 'off' && $run < $max_runs) {
+ return $this->updateService($max_runs, $run + 1);
+ }
+
+ return $this->status_new;
+ }
+
+ protected function updateWebsite($max_runs, $run = 1) {
+ // save response time
+ $time = explode(' ', microtime());
+ $starttime = $time[1] + $time[0];
+
+ $ch = curl_init();
+ curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt ($ch, CURLOPT_URL, $this->server['ip']);
+ curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, 10);
+ curl_setopt ($ch, CURLOPT_TIMEOUT, 10);
+ curl_setopt ($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.11) Gecko/20071127 Firefox/2.0.0.11');
+
+ // We're only interested in the header, because that should tell us plenty!
+ curl_setopt($ch, CURLOPT_HEADER, true);
+ curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'HEAD');
+
+ $headers = curl_exec ($ch);
+ curl_close ($ch);
+
+ $time = explode(" ", microtime());
+ $endtime = $time[1] + $time[0];
+ $this->rtime = ($endtime - $starttime);
+
+ // the first line would be the status code..
+ $status_code = strtok($headers, "\r\n");
+ // keep it general
+ // $code[1][0] = status code
+ // $code[2][0] = name of status code
+ preg_match_all("/[A-Z]{2,5}\/\d\.\d\s(\d{3})\s(.*)/", $status_code, $code_matches);
+
+ if(empty($code_matches[0])) {
+ // somehow we dont have a proper response.
+ $this->server['error'] = $this->error = 'no response from server';
+ $this->status_new = 'off';
+ } else {
+ $code = $code_matches[1][0];
+ $msg = $code_matches[2][0];
+
+ // All status codes starting with a 4 mean trouble!
+ if(substr($code, 0, 1) == '4') {
+ $this->server['error'] = $this->error = $code . ' ' . $msg;
+ $this->status_new = 'off';
+ } else {
+ $this->status_new = 'on';
+ }
+ }
+
+ // check if server is available and rerun if asked.
+ if($this->status_new == 'off' && $run < $max_runs) {
+ return $this->updateWebsite($max_runs, $run + 1);
+ }
+
+ return $this->status_new;
+ }
+
+ /**
+ * This function initializes the sending (text msg & email) and logging
+ *
+ */
+ public function notify() {
+ if(sm_get_conf('email_status') == false && sm_get_conf('sms_status') == false && sm_get_conf('log_status') == false) {
+ // seems like we have nothing to do. skip the rest
+ return false;
+ }
+ $notify = false;
+
+ // check which type of alert the user wants
+ switch(sm_get_conf('alert_type')) {
+ case 'always':
+ if($this->status_new == 'off') {
+ // server is offline. we are in error state.
+ $notify = true;
+ }
+ break;
+ case 'offline':
+ // only send a notification if the server goes down for the first time!
+ if($this->status_new == 'off' && $this->status_org == 'on') {
+ $notify = true;
+ }
+ break;
+ case 'status':
+ if($this->status_new != $this->status_org) {
+ // status has been changed!
+ $notify = true;
+ }
+ break;
+ }
+
+ if(!$notify) {
+ return false;
+ }
+
+ // first add to log (we use the same text as the SMS message because its short..)
+ if(sm_get_conf('log_status')) {
+ sm_add_log(
+ $this->server['server_id'],
+ 'status',
+ sm_parse_msg($this->status_new, 'sms', $this->server)
+ );
+ }
+
+ // check if email is enabled for this server
+ if(sm_get_conf('email_status') && $this->server['email'] == 'yes') {
+ // send email
+ $this->notifyByEmail();
+ }
+ // check if sms is enabled for this server
+ if(sm_get_conf('sms_status') && $this->server['sms'] == 'yes') {
+ // yay lets wake those nerds up!
+ $this->notifyByTxtMsg();
+ }
+ return true;
+ }
+
+ /**
+ * This functions performs the email notifications
+ *
+ * @return boolean
+ */
+ protected function notifyByEmail() {
+ $userlist = array();
+
+ // find all the users with this server listed
+ $users = $this->db->select(
+ SM_DB_PREFIX . 'users',
+ 'FIND_IN_SET(\''.$this->server['server_id'].'\', `server_id`) AND `email` != \'\'',
+ array('user_id', 'name', 'email')
+ );
+
+ if (empty($users)) {
+ return false;
+ }
+
+ // build mail object with some default values
+ $mail = new phpmailer();
+
+ $mail->From = sm_get_conf('email_from_email');
+ $mail->FromName = sm_get_conf('email_from_name');
+ $mail->Subject = sm_parse_msg($this->status_new, 'email_subject', $this->server);
+ $mail->Priority = 1;
+
+ $body = sm_parse_msg($this->status_new, 'email_body', $this->server);
+ $mail->Body = $body;
+ $mail->AltBody = str_replace(' ', "\n", $body);
+
+ // go through empl
+ foreach ($users as $user) {
+ // we sent a seperate email to every single user.
+ $userlist[] = $user['user_id'];
+ $mail->AddAddress($user['email'], $user['name']);
+ $mail->Send();
+ $mail->ClearAddresses();
+ }
+
+ if(sm_get_conf('log_email')) {
+ // save to log
+ sm_add_log($this->server['server_id'], 'email', $body, implode(',', $userlist));
+ }
+ }
+
+ /**
+ * This functions performs the text message notifications
+ *
+ * @return unknown
+ */
+ protected function notifyByTxtMsg() {
+ // send sms to all users for this server using defined gateway
+ $users = $this->db->select(
+ SM_DB_PREFIX . 'users',
+ 'FIND_IN_SET(\''.$this->server['server_id'].'\', `server_id`) AND `mobile` != \'\'',
+ array('user_id', 'name', 'mobile')
+ );
+
+ if (empty($users)) {
+ return false;
+ }
+
+ // we have to build an userlist for the log table..
+ $userlist = array();
+
+ // open the right class
+ // not making this any more dynamic, because perhaps some gateways need custom settings (like Mollie)
+ switch(strtolower(sm_get_conf('sms_gateway'))) {
+ case 'inetworx':
+ $sms = new txtmsgInetworx();
+ break;
+ case 'mollie':
+ $sms = new txtmsgMollie();
+ $sms->setGateway(1);
+ break;
+ case 'spryng':
+ $sms = new txtmsgSpryng();
+ break;
+ }
+
+ // copy login information from the config file
+ $sms->setLogin(sm_get_conf('sms_gateway_username'), sm_get_conf('sms_gateway_password'));
+ $sms->setOriginator(sm_get_conf('sms_from'));
+
+ // add all users to the recipients list
+ foreach ($users as $user) {
+ $userlist[] = $user['user_id'];
+ $sms->addRecipients($user['mobile']);
+ }
+
+ $message = sm_parse_msg($this->status_new, 'sms', $this->server);
+
+ // Send sms
+ $result = $sms->sendSMS($message);
+
+ if(sm_get_conf('log_sms')) {
+ // save to log
+ sm_add_log($this->server['server_id'], 'sms', $message, implode(',', $userlist));
+ }
+ return $result;
+ }
+
+ /**
+ * Get the error returned by the update function
+ *
+ * @return string
+ */
+ public function getError() {
+ return $this->error;
+ }
+
+ /**
+ * Get the response time of the server
+ *
+ * @return string
+ */
+ public function getRtime() {
+ return $this->rtime;
+ }
+
+ /**
+ * Clear all the results that are left from the previous run
+ *
+ */
+ protected function clearResults() {
+ $this->error = '';
+ $this->status_org = false;
+ $this->status_new = false;
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/classes/txtmsg/txtmsgCore.class.php b/classes/txtmsg/txtmsgCore.class.php
new file mode 100644
index 00000000..2bc09edd
--- /dev/null
+++ b/classes/txtmsg/txtmsgCore.class.php
@@ -0,0 +1,61 @@
+.
+ */
+
+abstract class txtmsgCore implements txtmsgInterface {
+ protected $originator;
+ protected $password;
+ protected $recipients = array();
+ protected $username;
+
+ /**
+ * Define login information for the gateway
+ *
+ * @param string $username
+ * @param string $password
+ */
+ public function setLogin($username, $password) {
+ $this->username = $username;
+ $this->password = $password;
+ }
+
+ /**
+ * Set the mobile number the text message will be send from
+ *
+ * @param string $originator
+ */
+ public function setOriginator($originator) {
+ $this->originator = $originator;
+ }
+
+ /**
+ * Add new recipient to the list
+ *
+ * @param unknown_type $recipient
+ */
+ public function addRecipients($recipient) {
+ array_push($this->recipients, $recipient);
+ }
+}
+
+?>
diff --git a/classes/txtmsg/txtmsgInetworx.class.php b/classes/txtmsg/txtmsgInetworx.class.php
new file mode 100644
index 00000000..fd922b11
--- /dev/null
+++ b/classes/txtmsg/txtmsgInetworx.class.php
@@ -0,0 +1,142 @@
+.
+ */
+
+class txtmsgInetworx extends txtmsgCore {
+ // =========================================================================
+ // [ Fields ]
+ // =========================================================================
+
+ // =========================================================================
+ // [ Methods ]
+ // =========================================================================
+
+ /**
+ * Send a text message to one or more recipients
+ *
+ * @param string $subject
+ * @param string $body
+ * @return boolean
+ */
+ public function sendSMS($message) {
+
+ if(empty($this->recipients)) {
+ return false;
+ }
+
+ $errors = 0;
+
+ foreach($this->recipients as $receiver) {
+ if(!$this->executeSend($message, $receiver, $this->originator)) {
+ $errors++;
+ }
+ }
+ $this->recipients = array();
+
+ return ($errors > 0) ? false : true;
+ }
+
+ /**
+ * Performs the actual send operation
+ *
+ * @param string $subject
+ * @param string $body
+ * @param string $receiver
+ * @param string $sender
+ * @return unknown
+ */
+ protected function executeSend($message, $receiver, $sender) {
+ $con_https[0] = 'sms.inetworx.ch';
+ $con_https[1] = '443';
+ $con_https[2] = 'inetworxag:conn2smsapp';
+ $posturl = "/smsapp/sendsms.php";
+
+ if(!empty($receiver)) {
+ $postvars = 'user=' . urlencode($this->username) .
+ '&pass=' . urlencode($this->password) .
+ '&sender=' . urldecode($sender) .
+ '&rcpt=' . urlencode($receiver) .
+ '&msgbody=' . urlencode($message)
+ ;
+ //if enabled, it sends a flash-message (not stored in Inbox!!)
+ //$postvars .= "&mclass=1";
+
+ $rtnval = $this->_auth_https_post(array($con_https[0], $con_https[1], $con_https[2], $posturl, $postvars));
+
+ return $rtnval;
+ //echo "SMS-Send-Result: $rtnval";
+ } else {
+ return false;
+ }
+ }
+
+ protected function _auth_https_post($inarray) {
+ // AUTH_HTTPS_POST: Request POST URL using basic authentication and SSL.
+ // Input: inarray[0]: host name
+ // inarray[1]: service port
+ // inarray[2]: user/password
+ // inarray[3]: URL request
+ // inarray[4]: POST variables
+ // Output: Message returned by server.
+
+ // Build the header.
+ $header = "POST ".$inarray[3]." HTTP/1.0\r\n";
+ $header .= "Authorization: Basic ".base64_encode("$inarray[2]")."\r\n";
+ $header .= "Host: ".$inarray[0]."\r\n";
+ $header .= "Content-type: application/x-www-form-urlencoded\r\n";
+ $header .= "Content-length: ".strlen($inarray[4])."\r\n\r\n";
+ // Connect to the server.
+ $connection = fsockopen("ssl://".$inarray[0], $inarray[1], &$errnum, &$errdesc, 10);
+ $msg = "";
+ if (! $connection){
+ $msg = $errdesc." (".$errnum.")";
+ }
+ else
+ {
+ socket_set_blocking($connection,false);
+ fputs($connection,$header.$inarray[4]);
+ while (! feof($connection))
+ {
+ $newline = fgets($connection,128);
+ switch ($newline)
+ {
+ // Skip http headers.
+ case (strstr($newline, 'Content-')): break;
+ case (strstr($newline, 'HTTP/1')): break;
+ case (strstr($newline, 'Date:')): break;
+ case (strstr($newline, 'Server:')): break;
+ case (strstr($newline, 'X-Powered-By:')): break;
+ case (strstr($newline, 'Connection:')): break;
+ case "": break;
+ case "\r\n": break;
+ default: $msg .= $newline;
+ } //end switch
+ } //end while
+ fclose($connection);
+ } //end else
+ return $msg;
+ } //end function auth_https_post
+
+}
+
+?>
\ No newline at end of file
diff --git a/classes/txtmsg/txtmsgInterface.class.php b/classes/txtmsg/txtmsgInterface.class.php
new file mode 100644
index 00000000..6c51e8e8
--- /dev/null
+++ b/classes/txtmsg/txtmsgInterface.class.php
@@ -0,0 +1,34 @@
+.
+ */
+
+interface txtmsgInterface {
+
+ public function setLogin($username, $password);
+ public function setOriginator($originator);
+ public function addRecipients($recipient);
+ public function sendSMS($message);
+
+}
+
+?>
\ No newline at end of file
diff --git a/classes/txtmsg/txtmsgMollie.class.php b/classes/txtmsg/txtmsgMollie.class.php
new file mode 100644
index 00000000..47ebdc37
--- /dev/null
+++ b/classes/txtmsg/txtmsgMollie.class.php
@@ -0,0 +1,96 @@
+.
+ */
+
+class txtmsgMollie extends txtmsgCore {
+ // =========================================================================
+ // [ Fields ]
+ // =========================================================================
+ public $gateway = 1;
+ public $success = false;
+ public $reference = '';
+
+ // =========================================================================
+ // [ Methods ]
+ // =========================================================================
+ /**
+ * Select the gateway to use
+ *
+ * @param unknown_type $gateway
+ */
+ public function setGateway($gateway) {
+ $this->gateway = $gateway;
+ }
+
+ public function setReference ($reference) {
+ $this->reference = $reference;
+ }
+
+ /**
+ * Send a text message to one or more recipients
+ *
+ * @param string $subject
+ * @param string $body
+ * @return boolean
+ */
+ public function sendSMS($message) {
+ $recipients = implode(',', $this->recipients);
+
+ $result = $this->_auth_https_post('www.mollie.nl', '/xml/sms/',
+ 'gateway='.urlencode($this->gateway).
+ '&username='.urlencode($this->username).
+ '&password='.urlencode($this->password).
+ '&originator='.urlencode($this->originator).
+ '&recipients='.urlencode($recipients).
+ '&message='.urlencode($message) .
+ (($this->reference != '') ? '&reference='.$this->reference : '')
+ );
+
+ $this->recipients = array();
+
+ list($headers, $xml) = preg_split("/(\r?\n){2}/", $result, 2);
+ $data = simplexml_load_string($xml);
+
+ $this->success = ($data->item->success == 'true');
+ return $this->success;
+ }
+
+ protected function _auth_https_post($host, $path, $data) {
+ $fp = @fsockopen($host,80);
+ $buf = '';
+ if ($fp) {
+ @fputs($fp, "POST $path HTTP/1.0\n");
+ @fputs($fp, "Host: $host\n");
+ @fputs($fp, "Content-type: application/x-www-form-urlencoded\n");
+ @fputs($fp, "Content-length: " . strlen($data) . "\n");
+ @fputs($fp, "Connection: close\n\n");
+ @fputs($fp, $data);
+ while (!feof($fp)) {
+ $buf .= fgets($fp,128);
+ }
+ fclose($fp);
+ }
+ return $buf;
+ }
+}
+?>
\ No newline at end of file
diff --git a/classes/txtmsg/txtmsgSpryng.class.php b/classes/txtmsg/txtmsgSpryng.class.php
new file mode 100644
index 00000000..f0fd03a6
--- /dev/null
+++ b/classes/txtmsg/txtmsgSpryng.class.php
@@ -0,0 +1,72 @@
+.
+ */
+
+class txtmsgSpryng extends txtmsgCore {
+ // =========================================================================
+ // [ Fields ]
+ // =========================================================================
+ public $gateway = 1;
+ public $resultcode = null;
+ public $resultmessage = null;
+ public $success = false;
+ public $successcount = 0;
+
+ // =========================================================================
+ // [ Methods ]
+ // =========================================================================
+ public function setGateway($gateway) {
+ $this->gateway = $gateway;
+ }
+
+ public function sendSMS($message) {
+ $recipients = implode(',', $this->recipients);
+
+ $result = $this->_auth_https_post('http://www.spryng.nl', '/SyncTextService',
+ '?OPERATION=send' .
+ '&USERNAME=' . $this->username .
+ '&PASSWORD=' . $this->password .
+ '&DESTINATION=' . $recipients .
+ '&SENDER=' . $this->originator .
+ '&BODY=' . $message .
+ '&SMSTYPE=' . 'BUSINESS'
+ );
+ return $result;
+ }
+
+ protected function _auth_https_post($host, $path, $data) {
+
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, $host . $path . $data);
+ //curl_setopt($ch, CURLOPT_HEADER, 1);
+ //curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
+ curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+
+ $data = curl_exec($ch);
+ curl_close($ch);
+ return $data;
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/config.inc.php b/config.inc.php
new file mode 100644
index 00000000..6bafc901
--- /dev/null
+++ b/config.inc.php
@@ -0,0 +1,71 @@
+.
+ */
+
+########################################
+#
+# START SERVER MONITOR CONFIGURATION
+#
+########################################
+
+// Database information
+// Prefix used for tables
+define('SM_DB_PREFIX', 'monitor_');
+// Database username
+define('SM_DB_USER', 'db_user');
+// Database password
+define('SM_DB_PASS', 'db_pass');
+// Database name
+define('SM_DB_NAME', 'db_name');
+// Database host
+define('SM_DB_HOST', 'localhost');
+
+########################################
+#
+# END SERVER MONITOR CONFIGURATION
+#
+########################################
+
+// Include paths
+// Tell the script where to find the templates, css files and javascript files.
+// If you haven't changed anything to the structure you should leave these unchanged
+define('SM_PATH_TPL', 'tpl/');
+define('SM_PATH_CSS', 'inc/');
+define('SM_PATH_JS', 'inc/');
+
+error_reporting(0);
+ini_set('display_errors', '0');
+
+require 'functions.inc.php';
+$db = new smDatabase();
+
+sm_load_conf();
+
+$lang = sm_get_conf('language');
+
+if(!$lang) {
+ $lang = 'en';
+}
+sm_load_lang($lang);
+
+?>
\ No newline at end of file
diff --git a/cron/status.cron.php b/cron/status.cron.php
new file mode 100644
index 00000000..8b930fd1
--- /dev/null
+++ b/cron/status.cron.php
@@ -0,0 +1,70 @@
+.
+ */
+
+// include main configuration and functionality
+require_once dirname(__FILE__) . '/../config.inc.php';
+
+// get the active servers from database
+$servers = $db->select(
+ SM_DB_PREFIX.'servers',
+ array('active' => 'yes'),
+ array('server_id', 'ip', 'port', 'label', 'type', 'status', 'active', 'email', 'sms')
+);
+
+$updater = new smUpdaterStatus();
+
+foreach ($servers as $server) {
+ $status_org = $server['status'];
+ // remove the old status from the array to avoid confusion between the new and old status
+ unset($server['status']);
+
+ $updater->setServer($server, $status_org);
+
+ // check server status
+ // it returns the new status, and performs the update check automatically.
+ $status_new = $updater->getStatus();
+ // notify the nerds if applicable
+ $updater->notify();
+
+ // update server status
+ $save = array(
+ 'last_check' => date('Y-m-d H:i:s'),
+ 'status' => $status_new,
+ 'error' => $updater->getError(),
+ 'rtime' => $updater->getRtime(),
+ );
+
+ // if the server is on, add the last_online value
+ if($save['status'] == 'on') {
+ $save['last_online'] = date('Y-m-d H:i:s');
+ }
+
+ $db->save(
+ SM_DB_PREFIX . 'servers',
+ $save,
+ array('server_id' => $server['server_id'])
+ );
+}
+
+?>
\ No newline at end of file
diff --git a/docs/CHANGELOG b/docs/CHANGELOG
new file mode 100644
index 00000000..6c84ce5b
--- /dev/null
+++ b/docs/CHANGELOG
@@ -0,0 +1,25 @@
+#########################
+#
+# Version 2.0.0
+# October 19, 2009
+#
+#########################
+- server type ("service" or "website")
+- different types of notification
+- new text message gateways
+- code rewrite
+- new layout
+- check for updates function
+
+#########################
+#
+# Version 1.0.1
+# September 18, 2008
+#
+#########################
+
+
+- log.php
+ tpl/log.tpl.html
+ select order by clause used datetime field after DATE_FORMAT had been performed,
+ resulting in a wrong list of log entries shown
\ No newline at end of file
diff --git a/docs/COPYING b/docs/COPYING
new file mode 100644
index 00000000..20d40b6b
--- /dev/null
+++ b/docs/COPYING
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ 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 .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
\ No newline at end of file
diff --git a/docs/README b/docs/README
new file mode 100644
index 00000000..c75dea11
--- /dev/null
+++ b/docs/README
@@ -0,0 +1,176 @@
+ PHP Server Monitor v2.0.0
+ http://phpservermon.sourceforge.net
+ Copyright (c) 2008-2009 Pepijn Over
+
+ PHP Server Monitor 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.
+
+ PHP Server Monitor 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 PHP Server Monitor. If not, see .
+
+#################
+# #
+# SUMMARY #
+# #
+#################
+
+PHP Server Monitor is a script that checks whether the servers on your list are up
+and running on the selected ports.
+It comes with a web based user interface where you can add and remove servers or websites from the MySQL database,
+and you can manage users for each server with a mobile number and email address.
+
+With version 2.0 there's the support for websites as well. On the "Add server" page, you can choose
+whether it's a "service" or a "website":
+* service
+ A connection will be made to the entered ip or domain, on the given port. This way you can check if certain
+ services on your machine are still running. To check your IMAP service for example, enter port 143.
+
+* website
+ The previous version only tried to establish a connection to the server on port 80. If you are running multiple
+ websites on 1 machine, there was no proper way to check each website for possible errors. Also it was impossible to make
+ sure your site was really up and running, all you knew was that the server was still online.
+ This function takes care of that.
+ You can enter a link to a website (for example http://sourceforge.net/index.php), it will use cURL to open the website and
+ check the HTTP status code (see http://en.wikipedia.org/wiki/List_of_HTTP_status_codes for details).
+ If the HTTP status code is in the 4xx range, it means an error occured and the website is not accesible to the public.
+ In that case the script will return a "status offline", and will start sending out notifications.
+
+Each server has it's own settings regarding notification.
+You can choose for email notification or text message (SMS). As of version 2.0, there are 3 gateways
+available:
+* Mollie - http://www.mollie.nl
+* Spryng - http://www.spryng.nl
+* Inetworx - http://www.inetworx.ch
+For these gateways you need an account with sufficient credits.
+
+If logging is enabled in the configuration, it will log any connection errors, emails and text messages sent.
+The latest log records will be displayed on your web interface.
+The cron/status.cron.php can be added as a cronjob which will keep the server status up to date.
+
+I'd appreciate any feedback you might have regarding this script. Please leave it on the sourceforge
+project page (tracker), or send me an email (see top of file for link).
+
+#################
+# #
+# DOWNLOAD #
+# #
+#################
+
+The latest version can be found at http://phpservermon.sourceforge.net
+
+
+#################
+# #
+# REQUIREMENTS #
+# #
+#################
+
+ 1. php 5
+ 2. MySQL Database
+ 3. FTP access
+
+
+#################
+# #
+# INSTALL #
+# #
+#################
+
+By default the PHP Server Monitor does not come with any security methods. After uploading these files to
+your public html folder these will be visible to everyone on the web. It is recommended to put a password
+on this folder to prevent other people from playing with your tool. An example .htaccess login script can
+be found in the example/ dir. To create your own username and password for the .htpasswd file, see
+http://www.htaccesstools.com/htpasswd-generator/
+
+ 1. Configuration
+ Open the config.php file with a plain text editor such as Notepad.
+ The first thing to do now in order to get started, is to get your database login information
+ right. The information is stored using php's define() function. To change these values correctly, only
+ update the second parameter of the function.
+ For example:
+ define('SM_DB_USER', 'db_user');
+ To change your username you should ONLY change the 'db_user' part. Do NOT remove the quotes around
+ your username as that will result in an error.
+
+ 2. Upload files
+ The next step is to get your files onto your webserver where you can reach them. You can rename the
+ folder of the server monitor without trouble, but if you change the structure please make sure
+ to update the settings in the config.php file
+
+ 3. Run install.php
+ Once your database login information is correct, you can run the install.php script located in the
+ root dir. This script will create all the database tables you will need.
+ After running the install.php script you can remove it.
+
+ 4. Configure your installation
+ Open the main page of the server monitor, by simply calling index.php. In the menu on the top find "config",
+ it'll open a page where you can change the necessary information for your tool.
+
+ 5. [optional] Add a cronjob
+ In order to keep the server monitor up to date, the monitor.php file has to run regulary. If you're running
+ this on a linux machine, the easiest way is to add a cronjob. If it's your own server or you have
+ shell access and permission to open the crontab, locate the "crontab" file
+ (usually in /etc/crontab, but depends on distro). Open the file (vi /etc/crontab), and add the following
+ (change the paths to match your installation directories):
+
+ #server monitor every 15 min
+ */15 * * * * root /usr/bin/php /var/www/html/phpservermon/cron/status.cron.php
+
+ As you can see, this line will run the status.cron.php script every 15 minutes. Change the line to suit your
+ needs. If you do not have shell access, ask your webhosting to set it up for you.
+
+ 6. Voila!
+
+
+#################
+# #
+# CUSTOMIZING #
+# #
+#################
+
+ 1. Language
+ The server monitor uses language files. That means that any regular text you see on the screen can easily be
+ changed without having to digg through the code. These language files are stored in the directory "lang".
+ The language that's being used by the monitor is defined in the config table. If you like
+ you can make changes to the language file or even add a new one.
+
+ 1.1 Changing the email or text message
+ Open the language file that corresponds to the selected language
+ (default is English ("en.lang.php")). Scroll all the way to the bottom until you spot this line:
+
+ 'notifications' => array(
+
+ After that you'll see the lines that hold the notification messages. For example:
+
+ 'off_sms' => 'Server \'%LABEL%\' is DOWN: ip=%IP%, port=%PORT%. Error=%ERROR%',
+
+ The first part of this line, 'off_sms', is the name of the notification. You should not change this. The
+ second part is the actual message. There are a few variables you can use in your message:
+ - %LABEL% The name of the server
+ - %IP% The ip of the server
+ - %PORT% The port of the server
+ - %ERROR% This one only works for the off_* messages and contains the error returned by the
+ monitor
+
+ 1.2 Adding a new language
+ It's not the easiest thing to add a new language to the monitor, but if you can spare a few minutes of your time
+ to send in a translation, it can be added to a future release.
+ - Create a new file in the directory "lang" named "mylanguage.lang.php".
+ - Copy the contents of the file "en.lang.php" to your new file.
+ - Translate the English stuff to your own language.
+ - Send a copy to ipdope[at]users.sourceforge.net so I can add it to the next release :)
+
+#################
+# #
+# CREDITS #
+# #
+#################
+
+1. classes/phpmailer.class.php - Brent R. Matzelle
\ No newline at end of file
diff --git a/example/.htaccess b/example/.htaccess
new file mode 100644
index 00000000..93aa72b4
--- /dev/null
+++ b/example/.htaccess
@@ -0,0 +1,4 @@
+AuthUserFile ".htpasswd"
+AuthType Basic
+AuthName "Server Monitor"
+require valid-user
diff --git a/example/.htpasswd b/example/.htpasswd
new file mode 100644
index 00000000..d37bda04
--- /dev/null
+++ b/example/.htpasswd
@@ -0,0 +1 @@
+admin:dGRkPurkuWmW2
\ No newline at end of file
diff --git a/functions.inc.php b/functions.inc.php
new file mode 100644
index 00000000..fc9662f9
--- /dev/null
+++ b/functions.inc.php
@@ -0,0 +1,220 @@
+.
+ */
+
+/**
+ *
+ * Autoload
+ *
+ */
+function __autoload($class) {
+ // first check if a subdir exists for the class
+ // it splits using uppercase chars
+ preg_match_all("/(\P{Lu}+)|(\p{Lu}+\P{Lu}*)/", $class, $subdir_matches);
+
+ if(!empty($subdir_matches) && count($subdir_matches[0]) > 1) {
+ // okay we have some upper case, lets see if a dir exists
+ $dir = dirname(__FILE__) . '/classes/' . trim($subdir_matches[0][0]);
+ $file = $dir . '/' . trim($class) . '.class.php';
+
+ if(is_dir($dir) && file_exists($file)) {
+ require $file;
+ return $file;
+ }
+ } else {
+ $file = dirname(__FILE__).'/classes/'.trim(strtolower($class)).'.class.php';
+
+ if(file_exists($file)){
+ require $file;
+ return $file;
+ }
+ }
+
+ trigger_error("KERNEL_ERR : Unable to find file:\n\t\t[$file]\n\t associated with class:\n\t\t$class", E_USER_ERROR);
+ return false;
+}
+
+###############################################
+#
+# Language functions
+#
+###############################################
+
+/**
+ * Retrieve language settings from the selected language file
+ *
+ * @return unknown
+ */
+function sm_get_lang() {
+ $args = func_get_args();
+
+ if(empty($args)) return $GLOBALS['sm_lang'];
+
+ $result = null;
+ $node = null;
+
+ if($args) {
+ $node = '$GLOBALS[\'sm_lang\'][\'' . implode('\'][\'', $args) . '\']';
+ }
+ eval('if (isset('.$node.')) $result = '.$node.';');
+
+ return $result;
+}
+
+function sm_load_lang($lang) {
+ $lang_file = dirname(__FILE__) . '/lang/' . $lang . '.lang.php';
+
+ if(!file_exists($lang_file)) {
+ die('unable to load language file: ' . $lang_file);
+ }
+
+ require $lang_file;
+
+ $GLOBALS['sm_lang'] = $sm_lang;
+}
+
+function sm_get_conf($key) {
+ $result = (isset($GLOBALS['sm_config'][$key])) ? $GLOBALS['sm_config'][$key] : null;
+
+ return $result;
+}
+
+function sm_load_conf() {
+ global $db;
+
+ // load config from database into global scope
+ $GLOBALS['sm_config'] = array();
+ $config_db = $db->select(SM_DB_PREFIX . 'config', null, array('key', 'value'));
+ foreach($config_db as $setting) {
+ $GLOBALS['sm_config'][$setting['key']] = $setting['value'];
+ }
+
+ if(empty($GLOBALS['sm_config']) && basename($_SERVER['SCRIPT_NAME']) != 'install.php') {
+ // no config found, go to install page
+ die('Failed to load config table. Please run the install.php file');
+ }
+}
+
+
+###############################################
+#
+# Miscellaneous functions
+#
+###############################################
+
+/**
+ * This function merely adds the message to the log table. It does not perform any checks,
+ * everything should have been handled when calling this function
+ *
+ * @param string $server_id
+ * @param string $message
+ */
+function sm_add_log($server_id, $type, $message, $user_id = null) {
+ global $db;
+
+ $db->save(
+ SM_DB_PREFIX.'log',
+ array(
+ 'server_id' => $server_id,
+ 'type' => $type,
+ 'message' => $message,
+ 'user_id' => ($user_id === null) ? '' : $user_id,
+ )
+ );
+}
+
+/**
+ * Parses a string from the language file with the correct variables replaced in the message
+ *
+ * @param string $status is either 'on' or 'off'
+ * @param string $type is either 'sms' or 'email'
+ * @param array $server information about the server which may be placed in a message: %KEY% will be replaced by your value
+ * @return string parsed message
+ */
+function sm_parse_msg($status, $type, $vars) {
+ $message = '';
+
+ $message = sm_get_lang('notifications', $status . '_' . $type);
+
+ if(!$message) {
+ return $message;
+ }
+ $vars['date'] = date('Y-m-d H:i:s');
+
+ foreach($vars as $k => $v) {
+ $message = str_replace('%' . strtoupper($k) . '%', $v, $message);
+ }
+
+ return $message;
+}
+
+function sm_curl_get($href) {
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_HEADER, 0);
+ curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+
+ curl_setopt($ch, CURLOPT_URL, $href);
+ $result = curl_exec($ch);
+ curl_close($ch);
+
+ return $result;
+}
+
+function sm_check_updates() {
+ $latest = sm_curl_get('http://phpservermon.neanderthal-technology.com/version');
+ $current = sm_get_conf('version');
+
+ if((int) $current < (int) $latest) {
+ // new update available
+ return true;
+ }
+ return false;
+}
+
+###############################################
+#
+# Debug functions
+#
+###############################################
+
+/**
+ * Only used for debugging and testing
+ *
+ * @param mixed $arr
+ */
+function pre($arr = null) {
+ echo "
'.
+ '1) Status change '.
+ 'You will receive a notifcation when a server has a change in status. So from online -> offline or offline -> online. '.
+ '2) Offline '.
+ 'You will receive a notification when a server goes offline for the *FIRST TIME ONLY*. For example, '.
+ 'your cronjob is every 15 mins and your server goes down at 1 am and stays down till 6 am. '.
+ 'You will get 1 notification at 1 am and thats it. '.
+ '3) Always '.
+ 'You will receive a notification every time the script runs and a site is down, even if the site has been '.
+ 'offline for hours.'.
+ '
If log status is set to TRUE, the monitor will log the event whenever the Notification settings are passed
',
+ 'log_email' => 'Log emails sent by the script?',
+ 'log_sms' => 'Log text messages sent by the script?',
+ 'updated' => 'The configuration has been updated.',
+ 'settings_email' => 'Email settings',
+ 'settings_sms' => 'Text message settings',
+ 'settings_notification' => 'Notification settings',
+ 'settings_log' => 'Log settings',
+ ),
+ // for newlines in the email messages use
+ 'notifications' => array(
+ 'off_sms' => 'Server \'%LABEL%\' is DOWN: ip=%IP%, port=%PORT%. Error=%ERROR%',
+ 'off_email_subject' => 'IMPORTANT: Server \'%LABEL%\' is DOWN',
+ 'off_email_body' => "Failed to connect to the following server:
Server: %LABEL% IP: %IP% Port: %PORT% Error: %ERROR% Date: %DATE%",
+ 'on_sms' => 'Server \'%LABEL%\' is RUNNING: ip=%IP%, port=%PORT%',
+ 'on_email_subject' => 'IMPORTANT: Server \'%LABEL%\' is RUNNING',
+ 'on_email_body' => "Server '%LABEL%' is running again:
'.
+ '1) Status verandering '.
+ 'Je ontvangt alleen bericht wanneer een server van status verandert. Dus van online -> offline of offline -> online. '.
+ '2) Offline '.
+ 'Je ontvangt bericht wanneer een server offline gaat voor de *EERSTE KEER*. Bijvoorbeeld, '.
+ 'je cronjob draait iedere 15 min en je server gaat down om 01:00 en blijft offline tot 06:00. '.
+ 'Je krijgt 1 bericht om 01:00 en dat is het. '.
+ '3) Altijd '.
+ 'Je krijgt een bericht elke keer dat het script draait en een website is down, ook al is de site al een paar uur offline.'.
+ '
Als de log status op TRUE staat, zal de monitor een log aanmaken elke keer dat hij door de notificatie instellingen komt
',
+ 'log_email' => 'Log emails verstuurd bij het script?',
+ 'log_sms' => 'Log sms berichten verstuurd bij het script?',
+ 'updated' => 'De configuratie is gewijzigd.',
+ 'settings_email' => 'Email instellingen',
+ 'settings_sms' => 'SMS instellingen',
+ 'settings_notification' => 'Notificatie instellingen',
+ 'settings_log' => 'Log instellingen',
+ ),
+ // for newlines in the email messages use
+ 'notifications' => array(
+ 'off_sms' => 'Server %LABEL% is DOWN: ip=%IP%, poort=%PORT%. Fout=%ERROR%',
+ 'off_email_subject' => 'BELANGRIJK: Server %LABEL% is DOWN',
+ 'off_email_body' => "De server kon niet worden bereikt:
Server: %LABEL% IP: %IP% Poort: %PORT% Fout: %ERROR% Datum: %DATE%",
+ 'on_sms' => 'Server %LABEL% is RUNNING: ip=%IP%, poort=%PORT%',
+ 'on_email_subject' => 'BELANGRIJK: Server %LABEL% is RUNNING',
+ 'on_email_body' => "Server %LABEL% is weer online:
Server: %LABEL% IP: %IP% Poort: %PORT% Datum: %DATE%",
+ ),
+);
+
+?>
\ No newline at end of file
diff --git a/tpl/config.tpl.html b/tpl/config.tpl.html
new file mode 100644
index 00000000..e07da956
--- /dev/null
+++ b/tpl/config.tpl.html
@@ -0,0 +1,125 @@
+
+{config_update}
+
+
+
+
+
+ Please update!
+
+
\ No newline at end of file
diff --git a/tpl/install.tpl.html b/tpl/install.tpl.html
new file mode 100644
index 00000000..98d8adc9
--- /dev/null
+++ b/tpl/install.tpl.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+ PHP Server Monitor Installation script
+
+
+
This script will create all the database tables required for PHP Server Monitor.
+
{error}
+
+
+
+ Creating table {name}...
+ {result}
+
+
+ {tables}
+
+ The installation is complete. Please check above if errors have occured.
+ If no errors have occured, you can remove this file and click here to go to your index
+
+
+
\ No newline at end of file
diff --git a/tpl/log.tpl.html b/tpl/log.tpl.html
new file mode 100644
index 00000000..0b887f6d
--- /dev/null
+++ b/tpl/log.tpl.html
@@ -0,0 +1,42 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/tpl/servers.tpl.html b/tpl/servers.tpl.html
new file mode 100644
index 00000000..8f5bcd05
--- /dev/null
+++ b/tpl/servers.tpl.html
@@ -0,0 +1,108 @@
+
+