Commit e35182f6 authored by Marius Burkard's avatar Marius Burkard
Browse files

- added new hooks/actions/events for addons to hook into the core

- TODO: the server services plugin is not capable of enabling and disabling addon plugins, yet
parent c02b7e4b
......@@ -211,9 +211,9 @@ if(is_dir('/usr/local/ispconfig')) {
}
//** Detect the installed applications
$this->call_hook('find_installed_apps', false);
$inst->raiseEvent('find_installed_apps::before');
$inst->find_installed_apps();
$this->call_hook('find_installed_apps', true);
$inst->raiseEvent('find_installed_apps::after');
//** Select the language and set default timezone
$conf['language'] = $inst->simple_query('Select language', array('en', 'de'), 'en','language');
......@@ -499,7 +499,7 @@ if($install_mode == 'standard' || strtolower($inst->simple_query('Configure Web
}
}
$inst->call_hook('configure_webserver_selection', true);
$inst->raiseEvent('configure_webserver_selection::after');
if($install_mode == 'standard' || strtolower($inst->simple_query('Configure Firewall Server', array('y', 'n'), 'y','configure_firewall')) == 'y') {
//* Check for Firewall
......@@ -592,9 +592,9 @@ if($install_mode == 'standard' || strtolower($inst->simple_query('Install ISPCon
$inst->install_ispconfig_interface = false;
}
$inst->call_hook('install_ispconfig', false);
$inst->raiseEvent('install_ispconfig::before');
$inst->install_ispconfig();
$inst->call_hook('install_ispconfig', true);
$inst->raiseEvent('install_ispconfig::after');
//* Configure DBServer
swriteln('Configuring DBServer');
......
......@@ -2827,40 +2827,61 @@ class installer_base {
return $tContents;
}
public function call_hook($hook_name, $after = true) {
if(is_null($this->addon_classes)) {
// load addon libs
$this->addon_classes = array();
$libpath = realpath(dirname(__FILE__).'/..') . '/lib.d';
if(($dir = opendir($libpath))) {
while(false !== ($cur = readdir($dir))) {
if(strpos($cur, '..') !== false || !is_file($libpath . '/' . $cur) || substr($cur, -8) !== '.lib.php') {
continue;
}
$class_name = substr($cur, 0, -8) . '_addon_installer';
include_once $libpath . '/' . $cur;
if(!class_exists($class_name)) {
continue;
}
$this->addon_classes[] = new $class_name;
private function loadAddonClasses($path) {
$libpath = $conf['ispconfig_install_dir'] . '/addons';
if(($dir = opendir($libpath))) {
while(false !== ($cur = readdir($dir))) {
if($cur === '.' || $cur === '..' || strpos($cur, '..') !== false || !is_dir($libpath . '/' . $cur)) {
continue;
}
$addon_file = $libpath . '/' . $cur . '/' . $cur . '.addon.php';
if(!is_file($addon_file)) {
continue;
}
$class_name = $cur . '_addon_installer';
if(isset($this->addon_classes[$class_name]) && is_object($this->addon_classes[$class_name])) {
// don't override
continue;
}
include_once $addon_file;
if(!class_exists($class_name)) {
continue;
}
if(!is_array($this->addon_classes)) {
$this->addon_classes = array();
}
closedir($dir);
$this->addon_classes[$class_name] = new $class_name;
}
closedir($dir);
}
}
public function raiseEvent($event_name) {
global $conf;
$call_method = 'onBefore';
if($after === true) {
$call_method = 'onAfter';
if(is_null($this->addon_classes)) {
// load addon libs
$this->addon_classes = array();
$addonpath = $conf['ispconfig_install_dir'] . '/addons';
$this->loadAddonClasses($addonpath);
// check for addon libs in install dir
$addonpath = realpath(dirname(__FILE__) . '/..') . '/addons';
$this->loadAddonClasses($addonpath);
}
$call_method = 'onRaisedEvent';
reset($this->addon_classes);
foreach($this->addon_classes as $cl) {
if(method_exists($cl, $call_method)) {
call_user_func(array($cl, $call_method), $hook_name);
call_user_func(array($cl, $call_method), $event_name);
}
}
}
}
?>
......@@ -434,11 +434,16 @@ function setDefaultServers(){
* @param $servicename string the name of the Database-Field in "servers" for this service
* @param $detected_value boolean The result of service detection
*/
function check_service_config_state($servicename, $detected_value) {
global $current_svc_config, $inst, $conf;
function check_service_config_state($servicename, $detected_value, $use_current_config = null) {
global $current_svc_config, $inst;
if ($current_svc_config[$servicename] == 1) $current_state = 1;
else $current_state = 0;
if(is_array($use_current_config)) {
if ($use_current_config[$servicename] == 1) $current_state = 1;
else $current_state = 0;
} else {
if ($current_svc_config[$servicename] == 1) $current_state = 1;
else $current_state = 0;
}
if ($detected_value) $detected_value = 1;
else $detected_value = 0;
......
......@@ -340,9 +340,9 @@ checkDbHealth();
/*
* dump the new Database and reconfigure the server.ini
*/
$inst->call_hook('updateDbAndIni', false);
$inst->raiseEvent('updateDbAndIni::before');
updateDbAndIni();
$inst->call_hook('updateDbAndIni', true);
$inst->raiseEvent('updateDbAndIni::after');
//** read server config from db into $conf['server_config']
$tmp = $inst->db->queryOneRecord("SELECT config FROM ?? WHERE server_id = ?", $conf["mysql"]["database"] . '.server', $conf['server_id']);
......@@ -364,11 +364,12 @@ if($reconfigure_master_database_rights_answer == 'yes') {
//}
//** Detect the installed applications
$this->call_hook('find_installed_apps', false);
$inst->raiseEvent('find_installed_apps::before');
$inst->find_installed_apps();
$this->call_hook('find_installed_apps', true);
$inst->raiseEvent('find_installed_apps::after');
//** Check for current service config state and compare to our results
$inst->raiseEvent('check_service_config_state::before');
if ($conf['mysql']['master_slave_setup'] == 'y') $current_svc_config = $inst->dbmaster->queryOneRecord("SELECT mail_server,web_server,dns_server,firewall_server,db_server FROM ?? WHERE server_id=?", $conf['mysql']['master_database'] . '.server', $conf['server_id']);
else $current_svc_config = $inst->db->queryOneRecord("SELECT mail_server,web_server,dns_server,firewall_server,db_server FROM ?? WHERE server_id=?", $conf["mysql"]["database"] . '.server', $conf['server_id']);
$conf['services']['mail'] = check_service_config_state('mail_server', $conf['postfix']['installed']);
......@@ -377,6 +378,7 @@ $conf['services']['web'] = check_service_config_state('web_server', ($conf['apac
$conf['services']['firewall'] = check_service_config_state('firewall_server', ($conf['ufw']['installed'] || $conf['firewall']['installed']));
$conf['services']['db'] = check_service_config_state('db_server', true); /* Will always offer as MySQL is of course installed on this host as it's a requirement for ISPC to work... */
unset($current_svc_config);
$inst->raiseEvent('check_service_config_state::after');
//** Write new decisions into DB
$sql = "UPDATE ?? SET mail_server = '{$conf['services']['mail']}', web_server = '{$conf['services']['web']}', dns_server = '{$conf['services']['dns']}', file_server = '{$conf['services']['file']}', db_server = '{$conf['services']['db']}', proxy_server = '{$conf['services']['proxy']}', firewall_server = '$firewall_server_enabled' WHERE server_id = ?";
......@@ -539,7 +541,9 @@ if ($inst->install_ispconfig_interface) {
}
}
$inst->raiseEvent('install_ispconfig::before');
$inst->install_ispconfig();
$inst->raiseEvent('install_ispconfig::after');
// Cleanup
$inst->cleanup_ispconfig();
......
......@@ -253,6 +253,12 @@ class functions {
}
}
}
$tmp_ips = $app->plugin->raiseEvent('get_server_ips', 0, true);
if(is_array($tmp_ips) && !empty($tmp_ips)) {
$ips = array_merge($ips, $tmp_ips);
}
$results = $groupid != 1 ? $app->db->queryAllRecords("SELECT database_name as name,remote_ips as ip FROM web_database WHERE remote_ips != '' AND sys_groupid = ?", $groupid) : $results = $app->db->queryAllRecords("SELECT database_name as name,remote_ips as ip FROM web_database WHERE remote_ips != ''");
......
......@@ -66,6 +66,70 @@ class listform {
$this->wordbook = $wb;
$module = (isset($_SESSION['s']['module']['name']) ? $_SESSION['s']['module']['name'] : '');
// load wordbook/lang files from addons
if($module == '') {
$lng_path = 'lib/lang.d';
} else {
$lng_path = '../' . $module . '/lib/lang.d';
}
if(($dir = opendir($lng_path))) {
$fallback_files = array();
$use_files = array();
while(false !== ($cur = readdir($dir))) {
$lng_file = $lng_path . '/' . $cur;
if(is_file($lng_file) && substr($cur, -strlen('.'.$app->listform->listDef["name"].".lng")) === '.'.$app->listform->listDef["name"].".lng") {
if(substr($cur, 0, 3) === 'en_') {
$fallback_files[] = $cur;
} elseif(substr($cur, 0, 3) === $app->functions->check_language($_SESSION["s"]["language"]) . '_') {
$use_files[] = $cur;
}
}
}
closedir($dir);
foreach($fallback_files as $cur) {
$cur_lng = $app->functions->check_language($_SESSION["s"]["language"]) . '_' . substr($cur, 3);
if(in_array($cur_lng, $use_files, true) == false) {
$use_files[] = $cur;
}
}
unset($fallback_files);
reset($use_files);
foreach($use_files as $cur) {
$lng_file = $lng_path . '/' . $cur;
include $lng_file;
if(isset($wb) && is_array($wb)) {
$this->wordbook = $app->functions->array_merge($this->wordbook, $wb);
}
}
unset($use_files);
}
if($module) {
// load list files from addons
$listform_path = '../' . $module . '/lib/form.d';
if(($dir = opendir($listform_path))) {
$items = null;
while(false !== ($cur = readdir($dir))) {
$listform_file = $listform_path . '/' . $cur;
if(is_file($listform_file) && substr($cur, -strlen('.'.$app->listform->listDef["name"].".list.php")) === '.'.$app->listform->listDef["name"].".list.php") {
unset($items); // just in case someone does not create a new array in the list file
include($listform_file);
if(isset($items) && is_array($items) && !empty($items)) {
$this->listDef['item'] = array_merge($this->listDef['item'], $items);
}
}
}
closedir($dir);
}
}
return true;
}
......
......@@ -124,17 +124,35 @@ class plugin {
$tmp_event = $sub_events[2];
if($this->debug) $app->log("Called Event '$tmp_event'", LOGLEVEL_DEBUG);
$tmpresult = $this->callPluginEvent($tmp_event, $data, $return_data);
if($return_data == true && $tmpresult) $result .= $tmpresult;
if($return_data == true && $tmpresult) {
if(is_array($tmpresult) && (!$result || is_array($result))) {
$result = array_merge($result, $tmpresult);
} elseif(!is_array($tmpresult)) {
$result .= $tmpresult;
}
}
$tmp_event = $sub_events[0].':'.$sub_events[2];
if($this->debug) $app->log("Called Event '$tmp_event'", LOGLEVEL_DEBUG);
$tmpresult = $this->callPluginEvent($tmp_event, $data, $return_data);
if($return_data == true && $tmpresult) $result .= $tmpresult;
if($return_data == true && $tmpresult) {
if(is_array($tmpresult) && (!$result || is_array($result))) {
$result = array_merge($result, $tmpresult);
} elseif(!is_array($tmpresult)) {
$result .= $tmpresult;
}
}
$tmp_event = $sub_events[0].':'.$sub_events[1].':'.$sub_events[2];
if($this->debug) $app->log("Called Event '$tmp_event'", LOGLEVEL_DEBUG);
$tmpresult = $this->callPluginEvent($tmp_event, $data, $return_data);
if($return_data == true && $tmpresult) $result .= $tmpresult;
if($return_data == true && $tmpresult) {
if(is_array($tmpresult) && (!$result || is_array($result))) {
$result = array_merge($result, $tmpresult);
} elseif(!is_array($tmpresult)) {
$result .= $tmpresult;
}
}
/*$sub_events = array_reverse($sub_events);
$tmp_event = '';
......@@ -147,7 +165,13 @@ class plugin {
} else {
if($this->debug) $app->log("Called Event '$sub_events[0]'", LOGLEVEL_DEBUG);
$tmpresult = $this->callPluginEvent($sub_events[0], $data, $return_data);
if($return_data == true && $tmpresult) $result .= $tmpresult;
if($return_data == true && $tmpresult) {
if(is_array($tmpresult) && (!$result || is_array($result))) {
$result = array_merge($result, $tmpresult);
} elseif(!is_array($tmpresult)) {
$result .= $tmpresult;
}
}
}
}
......@@ -187,7 +211,13 @@ class plugin {
// call_user_method($function_name,$app->loaded_plugins[$plugin_name],$event_name,$data);
$tmpresult = call_user_func(array($app->loaded_plugins[$plugin_name], $function_name), $event_name, $data);
if($return_data == true && $tmpresult) $result .= $tmpresult;
if($return_data == true && $tmpresult) {
if(is_array($tmpresult) && (!$result || is_array($result))) {
$result = array_merge($result, $tmpresult);
} elseif(!is_array($tmpresult)) {
$result .= $tmpresult;
}
}
}
}
......
......@@ -203,7 +203,6 @@ class remoting_server extends remoting {
global $app;
if(!$this->checkPerm($session_id, 'server_get')) {
throw new SoapFault('permission_denied', 'You do not have the permissions to access this function.');
return false;
}
if (!empty($session_id) && !empty($server_name)) {
$sql = "SELECT server_id FROM server WHERE server_name = ?";
......@@ -225,12 +224,22 @@ class remoting_server extends remoting {
global $app;
if(!$this->checkPerm($session_id, 'server_get')) {
throw new SoapFault('permission_denied', 'You do not have the permissions to access this function.');
return false;
}
if (!empty($session_id) && !empty($server_id)) {
$sql = "SELECT mail_server, web_server, dns_server, file_server, db_server, proxy_server, firewall_server, mirror_server_id FROM server WHERE server_id = ?";
$sql = "SELECT * FROM server WHERE server_id = ?";
$all = $app->db->queryOneRecord($sql, $server_id);
return $all;
if(empty($all)) return false;
$func = array();
foreach($all as $key => $value) {
if($key === 'mirror_server_id' || substr($key, -7) === '_server') {
if($value == 0 || $value == 1) {
$func[$key] = $value;
}
}
}
return $func;
} else {
return false;
}
......@@ -241,7 +250,6 @@ class remoting_server extends remoting {
global $app;
if(!$this->checkPerm($session_id, 'server_get')) {
throw new SoapFault('permission_denied', 'You do not have the permissions to access this function.');
return false;
}
if (!empty($session_id)) {
if($server_id == 0) $ispc_app_version = array('ispc_app_version' => ISPC_APP_VERSION);
......
......@@ -155,6 +155,66 @@ class tform_base {
$this->wordbook = $wb;
// load wordbook/lang files from addons
if($module == '') {
$lng_path = 'lib/lang.d';
} else {
$lng_path = '../' . $module . '/lib/lang.d';
}
if(($dir = opendir($lng_path))) {
$fallback_files = array();
$use_files = array();
while(false !== ($cur = readdir($dir))) {
$lng_file = $lng_path . '/' . $cur;
if(is_file($lng_file) && substr($cur, -strlen('.'.$this->formDef["name"].".lng")) === '.'.$this->formDef["name"].".lng") {
if(substr($cur, 0, 3) === 'en_') {
$fallback_files[] = $cur;
} elseif(substr($cur, 0, 3) === $app->functions->check_language($_SESSION["s"]["language"]) . '_') {
$use_files[] = $cur;
}
}
}
closedir($dir);
foreach($fallback_files as $cur) {
$cur_lng = $app->functions->check_language($_SESSION["s"]["language"]) . '_' . substr($cur, 3);
if(in_array($cur_lng, $use_files, true) == false) {
$use_files[] = $cur;
}
}
unset($fallback_files);
reset($use_files);
foreach($use_files as $cur) {
$lng_file = $lng_path . '/' . $cur;
include $lng_file;
if(isset($wb) && is_array($wb)) {
$this->wordbook = $app->functions->array_merge($this->wordbook, $wb);
}
}
unset($use_files);
}
if($module != '') {
// load tform files from addons
$tform_path = '../' . $module . '/lib/form.d';
if(($dir = opendir($tform_path))) {
$tabs = null;
while(false !== ($cur = readdir($dir))) {
$tform_file = $tform_path . '/' . $cur;
if(is_file($tform_file) && substr($cur, -strlen('.'.$this->formDef["name"].".tform.php")) === '.'.$this->formDef["name"].".tform.php") {
unset($tabs); // just in case someone does not create a new array in the tform file
include($tform_file);
if(isset($tabs) && is_array($tabs) && !empty($tabs)) {
$this->tform['tabs'] = array_replace_recursive($this->tform['tabs'], $tabs);
}
}
}
closedir($dir);
}
}
$app->plugin->raiseEvent($_SESSION['s']['module']['name'].':'.$app->tform->formDef['name'] . ':on_after_formdef', $this);
$this->dateformat = $app->lng('conf_format_dateshort');
......
......@@ -4,7 +4,7 @@
<p><tmpl_var name="list_desc_txt"></p>
{tmpl_hook name="begin_form"}
<div class="form-group">
<label for="server_name" class="col-sm-3 control-label">{tmpl_var name='server_name_txt'}</label>
<div class="col-sm-9"><input type="text" name="server_name" id="server_name" value="{tmpl_var name='server_name'}" class="form-control" /></div></div>
......@@ -38,6 +38,8 @@
{tmpl_var name='db_server'}
</div>
</div>
{tmpl_hook name="field_db_server"}
{tmpl_hook name="end_service_fields"}
<tmpl_if name="id" op="!=" value="1">
<div class="form-group">
<label for="mirror_server_id" class="col-sm-3 control-label">{tmpl_var name='mirror_server_id_txt'}</label>
......@@ -52,7 +54,7 @@
{tmpl_var name='active'}
</select></div>
</div>
{tmpl_hook name="end_form"}
<input type="hidden" name="id" value="{tmpl_var name='id'}">
......
......@@ -15,6 +15,7 @@
<th data-column="dns_server"><tmpl_var name="dns_server_txt"></th>
<th data-column="file_server"><tmpl_var name="file_server_txt"></th>
<th data-column="db_server"><tmpl_var name="db_server_txt"></th>
{tmpl_hook name="end_table_headers"}
<th class="small-col text-right">{tmpl_var name='search_limit'}</th>
</tr>
<tr>
......@@ -24,9 +25,10 @@
<td><select class="form-control" name="search_active">{tmpl_var name='search_dns_server'}</select></td>
<td><select class="form-control" name="search_active">{tmpl_var name='search_file_server'}</select></td>
<td><select class="form-control" name="search_active">{tmpl_var name='search_db_server'}</select></td>
{tmpl_hook name="end_table_filters"}
<td class="text-right">
<button type="button" class="btn btn-default formbutton-default formbutton-narrow" name="Filter" id="Filter" value="{tmpl_var name="filter_txt"}" data-submit-form="pageForm" data-form-action="admin/server_list.php"><span class="icon icon-filter"></span></button>
</td>
</td>"}
</tr>
</thead>
<tbody>
......@@ -38,6 +40,7 @@
<td>{tmpl_var name="dns_server"}</td>
<td>{tmpl_var name="file_server"}</td>
<td>{tmpl_var name="db_server"}</td>
{tmpl_hook name="end_table_columns"}
<td class="text-right">
<a class="btn btn-default formbutton-danger formbutton-narrow" href="javascript: ISPConfig.confirm_action('admin/server_del.php?id={tmpl_var name='id'}&phpsessid={tmpl_var name='phpsessid'}','{tmpl_var name='delete_confirmation'}');"><span class="icon icon-delete"></span></a>
</td>
......
......@@ -445,6 +445,11 @@ class page_action extends tform_actions {
'web_folder' => 'web_folder_id',
'web_folder_user' => 'web_folder_user_id'
);
$addons_disable = $app->plugin->raiseEvent('client::get_lockable_data', $this->id, true);
if(is_array($addons_disable) && !empty($addons_disable)) {
$to_disable = array_merge($to_disable, $addons_disable);
}
$udata = $app->db->queryOneRecord('SELECT `userid` FROM `sys_user` WHERE `client_id` = ?', $this->id);
$gdata = $app->db->queryOneRecord('SELECT `groupid` FROM `sys_group` WHERE `client_id` = ?', $this->id);
......
......@@ -349,6 +349,7 @@
</div>
</div>
</div>
{tmpl_hook name="end_form"}
</div>
<input type="hidden" name="id" value="{tmpl_var name='id'}">
......
......@@ -307,6 +307,7 @@
</div>
</div>
</div>
{tmpl_hook name="end_form"}
<tmpl_if name="is_admin">
<!-- Client -->
<div class="panel panel-default">
......
......@@ -352,6 +352,7 @@
</div>
</div>
</div>
{tmpl_hook name="end_form"}
<!-- Client -->
<div class="panel panel-default">
<div class="panel-heading" role="tab" id="headingClient">
......
......@@ -114,6 +114,23 @@ if($type == 'globalsearch'){
// directive snippets
$result[] = _search('admin', 'directive_snippets');
$data = $app->plugin->raiseEvent('dashboard:get_searchable_data', false, true);
if(is_array($data) && !empty($data)) {
foreach($data as $add_result) {
if(!isset($add_result['module']) || !isset($add_result['section'])) {
continue;
}
if(!isset($add_result['sql']) || !$add_result['sql']) {
$add_result['sql'] = '';
}
if(!isset($add_result['params']) || !$add_result['params']) {
$add_result['params'] = '';
}
$result[] = _search($add_result['module'], $add_result['section'], $add_result['sql'], $add_result['params']);
}
}
$json = $app->functions->json_encode($result);
}
......@@ -206,4 +223,3 @@ function _search($module, $section, $additional_sql = '', $params = ''){
header('Content-type: application/json');
echo $json;
?>
......@@ -53,6 +53,7 @@ if(isset($_GET['nav']) && $_GET['nav'] == 'top') {
$modules = array_merge(array('dashboard'), $modules);
}
*/