Skip to content

Commit 18e78b2

Browse files
committed
Merge branch 'develop' of git.ispconfig.org:ispconfig/ispconfig3 into develop
2 parents d9cd0ab + 906679d commit 18e78b2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+268
-402
lines changed

install/dist/tpl/gentoo/apache_ispconfig.vhost.master

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55
######################################################
66

77
{vhost_port_listen} Listen {vhost_port}
8-
NameVirtualHost *:{vhost_port}
8+
<tmpl_if name='apache_version' op='<' value='2.4' format='version'>
9+
NameVirtualHost *:{vhost_port}
10+
</tmpl_if>
911

1012
<VirtualHost _default_:{vhost_port}>
1113
ServerAdmin webmaster@localhost
12-
14+
1315
<IfModule mod_fcgid.c>
1416
DocumentRoot /var/www/ispconfig/
1517
SuexecUserGroup ispconfig ispconfig
@@ -25,7 +27,7 @@ NameVirtualHost *:{vhost_port}
2527
</Directory>
2628
DirectoryIndex index.php
2729
</IfModule>
28-
30+
2931
<IfModule mod_php5.c>
3032
DocumentRoot /usr/local/ispconfig/interface/web/
3133
AddType application/x-httpd-php .php
@@ -37,11 +39,11 @@ NameVirtualHost *:{vhost_port}
3739
php_value magic_quotes_gpc 0
3840
</Directory>
3941
</IfModule>
40-
42+
4143
# ErrorLog /var/log/apache2/error.log
4244
# CustomLog /var/log/apache2/access.log combined
4345
ServerSignature Off
44-
46+
4547
<IfModule mod_security2.c>
4648
SecRuleEngine Off
4749
</IfModule>
@@ -64,4 +66,3 @@ NameVirtualHost *:{vhost_port}
6466
Order Deny,Allow
6567
Deny from all
6668
</Directory>
67-

install/lib/installer_base.lib.php

Lines changed: 46 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2853,21 +2853,21 @@ public function make_ispconfig_ssl_cert() {
28532853

28542854
// This script is needed earlier to check and open http port 80 or standalone might fail
28552855
// Make executable and temporary symlink latest letsencrypt pre, post and renew hook script before install
2856-
if(file_exists(dirname(getcwd()) . '/server/scripts/letsencrypt_pre_hook.sh') && !file_exists('/usr/local/bin/letsencrypt_pre_hook.sh')) {
2857-
symlink(dirname(getcwd()) . '/server/scripts/letsencrypt_pre_hook.sh', '/usr/local/bin/letsencrypt_pre_hook.sh');
2856+
if(file_exists(ISPC_INSTALL_ROOT . '/server/scripts/letsencrypt_pre_hook.sh') && !file_exists('/usr/local/bin/letsencrypt_pre_hook.sh')) {
2857+
symlink(ISPC_INSTALL_ROOT . '/server/scripts/letsencrypt_pre_hook.sh', '/usr/local/bin/letsencrypt_pre_hook.sh');
2858+
chown('/usr/local/bin/letsencrypt_pre_hook.sh', 'root');
2859+
chmod('/usr/local/bin/letsencrypt_pre_hook.sh', 0700);
28582860
}
2859-
if(file_exists(dirname(getcwd()) . '/server/scripts/letsencrypt_post_hook.sh') && !file_exists('/usr/local/bin/letsencrypt_post_hook.sh')) {
2860-
symlink(dirname(getcwd()) . '/server/scripts/letsencrypt_post_hook.sh', '/usr/local/bin/letsencrypt_post_hook.sh');
2861+
if(file_exists(ISPC_INSTALL_ROOT . '/server/scripts/letsencrypt_post_hook.sh') && !file_exists('/usr/local/bin/letsencrypt_post_hook.sh')) {
2862+
symlink(ISPC_INSTALL_ROOT . '/server/scripts/letsencrypt_post_hook.sh', '/usr/local/bin/letsencrypt_post_hook.sh');
2863+
chown('/usr/local/bin/letsencrypt_post_hook.sh', 'root');
2864+
chmod('/usr/local/bin/letsencrypt_post_hook.sh', 0700);
28612865
}
2862-
if(file_exists(dirname(getcwd()) . '/server/scripts/letsencrypt_renew_hook.sh') && !file_exists('/usr/local/bin/letsencrypt_renew_hook.sh')) {
2863-
symlink(dirname(getcwd()) . '/server/scripts/letsencrypt_renew_hook.sh', '/usr/local/bin/letsencrypt_renew_hook.sh');
2866+
if(file_exists(ISPC_INSTALL_ROOT . '/server/scripts/letsencrypt_renew_hook.sh') && !file_exists('/usr/local/bin/letsencrypt_renew_hook.sh')) {
2867+
symlink(ISPC_INSTALL_ROOT . '/server/scripts/letsencrypt_renew_hook.sh', '/usr/local/bin/letsencrypt_renew_hook.sh');
2868+
chown('/usr/local/bin/letsencrypt_renew_hook.sh', 'root');
2869+
chmod('/usr/local/bin/letsencrypt_renew_hook.sh', 0700);
28642870
}
2865-
chown('/usr/local/bin/letsencrypt_pre_hook.sh', 'root');
2866-
chown('/usr/local/bin/letsencrypt_post_hook.sh', 'root');
2867-
chown('/usr/local/bin/letsencrypt_renew_hook.sh', 'root');
2868-
chmod('/usr/local/bin/letsencrypt_pre_hook.sh', 0700);
2869-
chmod('/usr/local/bin/letsencrypt_post_hook.sh', 0700);
2870-
chmod('/usr/local/bin/letsencrypt_renew_hook.sh', 0700);
28712871

28722872
// Check http port 80 status as it cannot be determined at post hook stage
28732873
$port80_status=exec('true &>/dev/null </dev/tcp/127.0.0.1/80 && echo open || echo close');
@@ -2999,6 +2999,10 @@ public function make_ispconfig_ssl_cert() {
29992999
rename($ssl_pem_file, $ssl_pem_file . '-' . $date->format('YmdHis') . '.bak');
30003000
}
30013001

3002+
$acme_cert_dir = '/etc/letsencrypt/live/' . $hostname;
3003+
symlink($acme_cert_dir . '/fullchain.pem', $ssl_crt_file);
3004+
symlink($acme_cert_dir . '/privkey.pem', $ssl_key_file);
3005+
30023006
$issued_successfully = true;
30033007
} else {
30043008
swriteln('Issuing certificate via certbot failed. Please check log files and make sure that your hostname can be verified by letsencrypt');
@@ -3043,42 +3047,44 @@ public function make_ispconfig_ssl_cert() {
30433047
}
30443048

30453049
// Build ispserver.pem file and chmod it
3046-
exec("cat $ssl_key_file $ssl_crt_file > $ssl_pem_file; chmod 600 $ssl_pem_file");
3050+
if(file_exists($ssl_key_file)) {
3051+
exec("cat $ssl_key_file $ssl_crt_file > $ssl_pem_file; chmod 600 $ssl_pem_file");
30473052

3048-
// Extend LE SSL certs to postfix
3049-
if ($conf['postfix']['installed'] == true && strtolower($this->simple_query('Symlink ISPConfig SSL certs to Postfix?', array('y', 'n'), 'y','ispconfig_postfix_ssl_symlink')) == 'y') {
3053+
// Extend LE SSL certs to postfix
3054+
if ($conf['postfix']['installed'] == true && strtolower($this->simple_query('Symlink ISPConfig SSL certs to Postfix?', array('y', 'n'), 'y','ispconfig_postfix_ssl_symlink')) == 'y') {
30503055

3051-
// Define folder, file(s)
3052-
$cf = $conf['postfix'];
3053-
$postfix_dir = $cf['config_dir'];
3054-
if(!is_dir($postfix_dir)) $this->error("The Postfix configuration directory '$postfix_dir' does not exist.");
3055-
$smtpd_crt = $postfix_dir.'/smtpd.cert';
3056-
$smtpd_key = $postfix_dir.'/smtpd.key';
3056+
// Define folder, file(s)
3057+
$cf = $conf['postfix'];
3058+
$postfix_dir = $cf['config_dir'];
3059+
if(!is_dir($postfix_dir)) $this->error("The Postfix configuration directory '$postfix_dir' does not exist.");
3060+
$smtpd_crt = $postfix_dir.'/smtpd.cert';
3061+
$smtpd_key = $postfix_dir.'/smtpd.key';
30573062

3058-
// Backup existing postfix ssl files
3059-
if (file_exists($smtpd_crt)) rename($smtpd_crt, $smtpd_crt . '-' .$date->format('YmdHis') . '.bak');
3060-
if (file_exists($smtpd_key)) rename($smtpd_key, $smtpd_key . '-' .$date->format('YmdHis') . '.bak');
3063+
// Backup existing postfix ssl files
3064+
if (file_exists($smtpd_crt)) rename($smtpd_crt, $smtpd_crt . '-' .$date->format('YmdHis') . '.bak');
3065+
if (file_exists($smtpd_key)) rename($smtpd_key, $smtpd_key . '-' .$date->format('YmdHis') . '.bak');
30613066

3062-
// Create symlink to ISPConfig SSL files
3063-
symlink($ssl_crt_file, $smtpd_crt);
3064-
symlink($ssl_key_file, $smtpd_key);
3065-
}
3067+
// Create symlink to ISPConfig SSL files
3068+
symlink($ssl_crt_file, $smtpd_crt);
3069+
symlink($ssl_key_file, $smtpd_key);
3070+
}
30663071

3067-
// Extend LE SSL certs to pureftpd
3068-
if ($conf['pureftpd']['installed'] == true && strtolower($this->simple_query('Symlink ISPConfig SSL certs to Pure-FTPd? Creating dhparam file may take some time.', array('y', 'n'), 'y','ispconfig_pureftpd_ssl_symlink')) == 'y') {
3072+
// Extend LE SSL certs to pureftpd
3073+
if ($conf['pureftpd']['installed'] == true && strtolower($this->simple_query('Symlink ISPConfig SSL certs to Pure-FTPd? Creating dhparam file may take some time.', array('y', 'n'), 'y','ispconfig_pureftpd_ssl_symlink')) == 'y') {
30693074

3070-
// Define folder, file(s)
3071-
$pureftpd_dir = '/etc/ssl/private';
3072-
if(!is_dir($pureftpd_dir)) mkdir($pureftpd_dir, 0755, true);
3073-
$pureftpd_pem = $pureftpd_dir.'/pure-ftpd.pem';
3075+
// Define folder, file(s)
3076+
$pureftpd_dir = '/etc/ssl/private';
3077+
if(!is_dir($pureftpd_dir)) mkdir($pureftpd_dir, 0755, true);
3078+
$pureftpd_pem = $pureftpd_dir.'/pure-ftpd.pem';
30743079

3075-
// Backup existing pureftpd ssl files
3076-
if (file_exists($pureftpd_pem)) rename($pureftpd_pem, $pureftpd_pem . '-' .$date->format('YmdHis') . '.bak');
3080+
// Backup existing pureftpd ssl files
3081+
if (file_exists($pureftpd_pem)) rename($pureftpd_pem, $pureftpd_pem . '-' .$date->format('YmdHis') . '.bak');
30773082

3078-
// Create symlink to ISPConfig SSL files
3079-
symlink($ssl_pem_file, $pureftpd_pem);
3080-
if (!file_exists("$pureftpd_dir/pure-ftpd-dhparams.pem"))
3081-
exec("cd $pureftpd_dir; openssl dhparam -out dhparam2048.pem 2048; ln -sf dhparam2048.pem pure-ftpd-dhparams.pem");
3083+
// Create symlink to ISPConfig SSL files
3084+
symlink($ssl_pem_file, $pureftpd_pem);
3085+
if (!file_exists("$pureftpd_dir/pure-ftpd-dhparams.pem"))
3086+
exec("cd $pureftpd_dir; openssl dhparam -out dhparam2048.pem 2048; ln -sf dhparam2048.pem pure-ftpd-dhparams.pem");
3087+
}
30823088
}
30833089

30843090
exec("chown -R root:root $ssl_dir");

install/tpl/apache_ispconfig.conf.master

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -132,11 +132,13 @@ CustomLog "| /usr/local/ispconfig/server/scripts/vlogger -s access.log -t \"%Y%m
132132

133133
Alias /awstats-icon "/usr/share/awstats/icon"
134134

135-
NameVirtualHost *:80
136-
NameVirtualHost *:443
137-
<tmpl_loop name="ip_adresses">
138-
NameVirtualHost {tmpl_var name="ip_address"}:{tmpl_var name="port"}
139-
</tmpl_loop>
135+
<tmpl_if name='apache_version' op='<' value='2.4' format='version'>
136+
NameVirtualHost *:80
137+
NameVirtualHost *:443
138+
<tmpl_loop name="ip_adresses">
139+
NameVirtualHost {tmpl_var name="ip_address"}:{tmpl_var name="port"}
140+
</tmpl_loop>
141+
</tmpl_if>
140142

141143
<tmpl_if name='apache_version' op='>=' value='2.3.3' format='version'>
142144
<IfModule mod_ssl.c>
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
try_fallback = false;
2+
use_esld = false;
23
path_map = "/etc/rspamd/local.d/dkim_domains.map";
3-
selector_map = "/etc/rspamd/local.d/dkim_selectors.map";
4+
selector_map = "/etc/rspamd/local.d/dkim_selectors.map";

interface/lib/classes/validate_server_directive_snippets.inc.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,11 @@ function get_error($errmsg) {
4242

4343
function validate_snippet($field_name, $field_value, $validator) {
4444
global $app;
45-
$type=(isset($app->remoting_lib->dataRecord['type']))?$app->remoting_lib->dataRecord['type']:$_POST['type'];
45+
$id = (isset($app->remoting_lib->dataRecord['directive_snippets_id']))?$app->remoting_lib->dataRecord['directive_snippets_id']:$_POST['id'];
46+
$type=(isset($app->remoting_lib->dataRecord['type']))?$app->remoting_lib->dataRecord['type']:$_POST['type'];
4647
$types = array('apache','nginx','php','proxy');
4748
if(!in_array($type,$types)) return $this->get_error('directive_snippets_invalid_type');
48-
$check = $app->db->queryAllRecords('SELECT * FROM directive_snippets WHERE name = ? AND type = ?', $field_value, $type);
49+
$check = $app->db->queryAllRecords('SELECT * FROM directive_snippets WHERE name = ? AND type = ? AND directive_snippets_id != ?', $field_value, $type, $id);
4950
if(!empty($check)) return $this->get_error('directive_snippets_name_error_unique');
5051
}
5152

interface/web/admin/directive_snippets_del.php

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,31 @@
4545
//* Check permissions for module
4646
$app->auth->check_module_permissions('admin');
4747

48-
$app->uses("tform_actions");
49-
$app->tform_actions->onDelete();
48+
$app->load("tform_actions");
49+
50+
class page_action extends tform_actions {
51+
function onBeforeDelete() {
52+
global $app, $conf;
53+
54+
if($this->dataRecord['type'] === 'php') {
55+
$rlike = $this->dataRecord['directive_snippets_id'].'|,'.$this->dataRecord['directive_snippets_id'].'|'.$this->dataRecord['directive_snippets_id'].',';
56+
$affected_snippets = $app->db->queryAllRecords('SELECT directive_snippets_id FROM directive_snippets WHERE required_php_snippets REGEXP ? AND type = ?', $rlike, 'apache');
57+
if(is_array($affected_snippets) && !empty($affected_snippets)) {
58+
foreach($affected_snippets as $snippet) {
59+
$sql_in[] = $snippet['directive_snippets_id'];
60+
}
61+
$affected_sites = $app->db->queryAllRecords('SELECT domain_id FROM web_domain WHERE server_id = ? AND directive_snippets_id IN ?', $conf['server_id'], $sql_in);
62+
}
63+
} elseif($this->dataRecord['type'] === 'apache' || $this->dataRecord['type'] === 'nginx') {
64+
$affected_sites = $app->db->queryAllRecords('SELECT domain_id FROM web_domain WHERE server_id = ? AND directive_snippets_id = ?', $conf['server_id'], $this->dataRecord['directive_snippets_id']);
65+
}
66+
67+
if(!empty($affected_sites)) {
68+
$app->error($app->tform->lng('error_delete_snippet_active_sites'));
69+
}
70+
}
71+
}
72+
73+
$page = new page_action();
74+
$page->onDelete();
5075

51-
?>

interface/web/admin/directive_snippets_edit.php

Lines changed: 40 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -49,81 +49,58 @@
4949

5050
class page_action extends tform_actions {
5151

52-
function onShow() {
52+
private function getAffectedSites() {
5353
global $app, $conf;
54-
55-
if($this->id > 0){
56-
$record = $app->db->queryOneRecord("SELECT * FROM directive_snippets WHERE directive_snippets_id = ?", $this->id);
57-
if($record['master_directive_snippets_id'] > 0){
58-
unset($app->tform->formDef["tabs"]['directive_snippets']['fields']['name'], $app->tform->formDef["tabs"]['directive_snippets']['fields']['type'], $app->tform->formDef["tabs"]['directive_snippets']['fields']['snippet'], $app->tform->formDef["tabs"]['directive_snippets']['fields']['required_php_snippets']);
54+
55+
if($this->dataRecord['type'] === 'php') {
56+
$rlike = $this->dataRecord['id'].'|,'.$this->dataRecord['id'].'|'.$this->dataRecord['id'].',';
57+
$affected_snippets = $app->db->queryAllRecords('SELECT directive_snippets_id FROM directive_snippets WHERE required_php_snippets REGEXP ? AND type = ?', $rlike, 'apache');
58+
if(is_array($affected_snippets) && !empty($affected_snippets)) {
59+
foreach($affected_snippets as $snippet) {
60+
$sql_in[] = $snippet['directive_snippets_id'];
61+
}
62+
$affected_sites = $app->db->queryAllRecords('SELECT domain_id FROM web_domain WHERE server_id = ? AND directive_snippets_id IN ?', $conf['server_id'], $sql_in);
5963
}
60-
unset($record);
64+
} elseif($this->dataRecord['type'] === 'apache' || $this->dataRecord['type'] === 'nginx') {
65+
$affected_sites = $app->db->queryAllRecords('SELECT domain_id FROM web_domain WHERE server_id = ? AND directive_snippets_id = ?', $conf['server_id'], $this->dataRecord['id']);
6166
}
62-
63-
parent::onShow();
67+
68+
return $affected_sites;
6469
}
65-
66-
function onShowEnd() {
67-
global $app, $conf;
68-
69-
$is_master = false;
70-
if($this->id > 0){
71-
if($this->dataRecord['master_directive_snippets_id'] > 0){
72-
$is_master = true;
73-
$app->tpl->setVar("name", $this->dataRecord['name'], true);
74-
$app->tpl->setVar("type", $this->dataRecord['type'], true);
75-
$app->tpl->setVar("snippet", $this->dataRecord['snippet'], true);
70+
71+
public function onBeforeUpdate() {
72+
global $app;
73+
74+
$oldRecord = $app->tform->getDataRecord($this->id);
75+
76+
if($this->dataRecord['active'] !== 'y' && $oldRecord['active'] === 'y') {
77+
$affected_sites = $this->getAffectedSites();
78+
if(!empty($affected_sites)) {
79+
$app->tform->errorMessage .= $app->tform->lng('error_disable_snippet_active_sites');
80+
}
81+
} elseif($this->dataRecord['customer_viewable'] !== 'y' && $oldRecord['customer_viewable'] === 'y') {
82+
$affected_sites = $this->getAffectedSites();
83+
if(!empty($affected_sites)) {
84+
$app->tform->errorMessage .= $app->tform->lng('error_hide_snippet_active_sites');
7685
}
7786
}
78-
79-
$app->tpl->setVar("is_master", $is_master);
80-
81-
parent::onShowEnd();
8287
}
83-
84-
function onSubmit() {
85-
global $app, $conf;
8688

87-
if($this->id > 0){
88-
$record = $app->db->queryOneRecord("SELECT * FROM directive_snippets WHERE directive_snippets_id = ?", $this->id);
89-
if($record['master_directive_snippets_id'] > 0){
90-
unset($app->tform->formDef["tabs"]['directive_snippets']['fields']['name'], $app->tform->formDef["tabs"]['directive_snippets']['fields']['type'], $app->tform->formDef["tabs"]['directive_snippets']['fields']['snippet'], $app->tform->formDef["tabs"]['directive_snippets']['fields']['required_php_snippets']);
91-
}
92-
93-
if(isset($this->dataRecord['update_sites'])) {
94-
parent::onSubmit();
95-
} else {
96-
$app->db->query('UPDATE directive_snippets SET name = ?, type = ?, snippet = ?, customer_viewable = ?, required_php_snippets = ?, active = ? WHERE directive_snippets_id = ?', $this->dataRecord['name'], $this->dataRecord['type'], $this->dataRecord['snippet'], $this->dataRecord['customer_viewable'], implode(',', $this->dataRecord['required_php_snippets']), $this->dataRecord['active'], $this->id);
97-
98-
if($_REQUEST["next_tab"] == '') {
99-
$list_name = $_SESSION["s"]["form"]["return_to"];
100-
if($list_name != '' && $_SESSION["s"]["list"][$list_name]["parent_name"] != $app->tform->formDef["name"]) {
101-
$redirect = "Location: ".$_SESSION["s"]["list"][$list_name]["parent_script"]."?id=".$_SESSION["s"]["list"][$list_name]["parent_id"]."&next_tab=".$_SESSION["s"]["list"][$list_name]["parent_tab"];
102-
$_SESSION["s"]["form"]["return_to"] = '';
103-
session_write_close();
104-
header($redirect);
105-
} elseif (isset($_SESSION["s"]["form"]["return_to_url"]) && $_SESSION["s"]["form"]["return_to_url"] != '') {
106-
$redirect = $_SESSION["s"]["form"]["return_to_url"];
107-
$_SESSION["s"]["form"]["return_to_url"] = '';
108-
session_write_close();
109-
header("Location: ".$redirect);
110-
exit;
111-
} else {
112-
header("Location: ".$app->tform->formDef['list_default']);
113-
}
114-
exit;
89+
public function onAfterUpdate() {
90+
global $app;
91+
92+
if(isset($this->dataRecord['update_sites']) && $this->dataRecord['update_sites'] === 'y' && $this->dataRecord['active'] === 'y') {
93+
$affected_sites = $this->getAffectedSites();
94+
95+
if(is_array($affected_sites) && !empty($affected_sites)) {
96+
foreach($affected_sites as $site) {
97+
$website = $app->db->queryOneRecord('SELECT * FROM web_domain WHERE domain_id = ?', $site['domain_id']);
98+
$app->db->datalogUpdate('web_domain', $website, 'domain_id', $site['domain_id'], true);
11599
}
116100
}
117-
118-
unset($record);
119101
}
120-
121-
parent::onSubmit();
122102
}
123-
124103
}
125104

126105
$page = new page_action;
127-
$page->onLoad();
128-
129-
?>
106+
$page->onLoad();

interface/web/admin/directive_snippets_list.php

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,6 @@ public function prepareDataRow($rec)
5757
//* Alternating datarow colors
5858
$this->DataRowColor = ($this->DataRowColor == '#FFFFFF') ? '#EEEEEE' : '#FFFFFF';
5959
$rec['bgcolor'] = $this->DataRowColor;
60-
61-
$rec['is_master'] = $rec['master_directive_snippets_id'];
6260

6361
//* substitute value for select fields
6462
if(is_array($app->listform->listDef['item']) && count($app->listform->listDef['item']) > 0) {
@@ -79,15 +77,8 @@ public function prepareDataRow($rec)
7977
$rec['id'] = $rec[$this->idx_key];
8078
return $rec;
8179
}
82-
80+
8381
}
8482
$list = new list_action;
8583
$list->SQLOrderBy = 'ORDER BY directive_snippets.name';
8684
$list->onLoad();
87-
88-
//$app->listform_actions->SQLExtWhere = 'master_directive_snippets_id = 0';
89-
/*
90-
$app->listform_actions->SQLOrderBy = 'ORDER BY directive_snippets.name';
91-
$app->listform_actions->onLoad();
92-
*/
93-
?>

0 commit comments

Comments
 (0)