Marius Burkard
2016-04-20 4569cae57f127afd093794310ccd290d2d9fdf36
commit | author | age
48ced1 1 <?php
T 2
3 /*
5a43e7 4 Copyright (c) 2007-2012, Till Brehm, projektfarm Gmbh, Oliver Vogel www.muv.com
48ced1 5 All rights reserved.
T 6
7 Redistribution and use in source and binary forms, with or without modification,
8 are permitted provided that the following conditions are met:
9
10     * Redistributions of source code must retain the above copyright notice,
11       this list of conditions and the following disclaimer.
12     * Redistributions in binary form must reproduce the above copyright notice,
13       this list of conditions and the following disclaimer in the documentation
14       and/or other materials provided with the distribution.
15     * Neither the name of ISPConfig nor the names of its contributors
16       may be used to endorse or promote products derived from this software without
17       specific prior written permission.
18
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
26 OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
28 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 class software_update_plugin {
b1a6a5 32
48ced1 33     var $plugin_name = 'software_update_plugin';
T 34     var $class_name  = 'software_update_plugin';
b1a6a5 35
392450 36     //* This function is called during ispconfig installation to determine
T 37     //  if a symlink shall be created for this plugin.
5a43e7 38     public function onInstall() {
392450 39         global $conf;
b1a6a5 40
392450 41         return true;
b1a6a5 42
392450 43     }
b1a6a5 44
MC 45
48ced1 46     /*
T 47          This function is called when the plugin is loaded
48     */
b1a6a5 49
5a43e7 50     public function onLoad() {
48ced1 51         global $app;
b1a6a5 52
48ced1 53         /*
T 54         Register for the events
55         */
b1a6a5 56
MC 57         $app->plugins->registerEvent('software_update_inst_insert', $this->plugin_name, 'process');
48ced1 58         //$app->plugins->registerEvent('software_update_inst_update',$this->plugin_name,'process');
T 59         //$app->plugins->registerEvent('software_update_inst_delete',$this->plugin_name,'process');
b1a6a5 60
5a43e7 61         //* Register for actions
b1a6a5 62         $app->plugins->registerAction('os_update', $this->plugin_name, 'os_update');
MC 63
64
48ced1 65     }
b1a6a5 66
5a43e7 67     private function set_install_status($inst_id, $status) {
b1a6a5 68         global $app;
MC 69
cc7a82 70         $app->db->query("UPDATE software_update_inst SET status = ? WHERE software_update_inst_id = ?", $status, $inst_id);
MC 71         $app->dbmaster->query("UPDATE software_update_inst SET status = ? WHERE software_update_inst_id = ?", $status, $inst_id);
b1a6a5 72     }
MC 73
74     public function process($event_name, $data) {
48ced1 75         global $app, $conf;
b1a6a5 76
df8a46 77         //* Get the info of the package:
8e725d 78         $software_update_id = intval($data["new"]["software_update_id"]);
cc7a82 79         $software_update = $app->db->queryOneRecord("SELECT * FROM software_update WHERE software_update_id = ?", $software_update_id);
MC 80         $software_package = $app->db->queryOneRecord("SELECT * FROM software_package WHERE package_name = ?", $software_update['package_name']);
b1a6a5 81
df8a46 82         if($software_package['package_type'] == 'ispconfig' && !$conf['software_updates_enabled'] == true) {
b1a6a5 83             $app->log('Software Updates not enabled on this server. To enable updates, set $conf["software_updates_enabled"] = true; in config.inc.php', LOGLEVEL_WARN);
MC 84             $this->set_install_status($data["new"]["software_update_inst_id"], "failed");
48ced1 85             return false;
T 86         }
b1a6a5 87
df8a46 88         $installuser = '';
T 89         if($software_package['package_type'] == 'ispconfig') {
90             $installuser = '';
91         } elseif ($software_package['package_type'] == 'app') {
92             $installuser = 'ispapps';
93         } else {
b1a6a5 94             $app->log('package_type not supported', LOGLEVEL_WARN);
MC 95             $this->set_install_status($data["new"]["software_update_inst_id"], "failed");
df8a46 96             return false;
T 97         }
b1a6a5 98
MC 99         $temp_dir = '/tmp/'.md5(uniqid(rand()));
100         $app->log("The temp dir is $temp_dir", LOGLEVEL_DEBUG);
48ced1 101         mkdir($temp_dir);
8e725d 102         if($installuser != '') chown($temp_dir, $installuser);
b1a6a5 103
48ced1 104         if(!is_dir($temp_dir)) {
b1a6a5 105             $app->log("Unable to create temp directory.", LOGLEVEL_WARN);
MC 106             $this->set_install_status($data["new"]["software_update_inst_id"], "failed");
48ced1 107             return false;
T 108         }
b1a6a5 109
1390c8 110         //* Replace placeholders in download URL
b1a6a5 111         $software_update["update_url"] = str_replace('{key}', $software_package['package_key'], $software_update["update_url"]);
MC 112
1390c8 113         //* Download the update package
df8a46 114         $cmd = "cd $temp_dir && wget ".$software_update["update_url"];
T 115         if($installuser == '') {
116             exec($cmd);
117         } else {
118             exec("su -c ".escapeshellarg($cmd)." $installuser");
119         }
b1a6a5 120         $app->log("Downloading the update file from: ".$software_update["update_url"], LOGLEVEL_DEBUG);
MC 121
1390c8 122         //$url_parts = parse_url($software_update["update_url"]);
T 123         //$update_filename = basename($url_parts["path"]);
124         //* Find the name of the zip file which contains the app.
125         $tmp_dir_handle = dir($temp_dir);
126         $update_filename = '';
127         while (false !== ($t = $tmp_dir_handle->read())) {
b1a6a5 128             if($t != '.' && $t != '..' && is_file($temp_dir.'/'.$t) && substr($t, -4) == '.zip') {
1390c8 129                 $update_filename = $t;
T 130             }
131         }
132         $tmp_dir_handle->close();
133         unset($tmp_dir_handle);
134         unset($t);
b1a6a5 135
1390c8 136         if($update_filename == '') {
b1a6a5 137             $app->log("No package file found. Download failed? Installation aborted.", LOGLEVEL_WARN);
1390c8 138             exec("rm -rf $temp_dir");
b1a6a5 139             $app->log("Deleting the temp directory $temp_dir", LOGLEVEL_DEBUG);
8e725d 140             $this->set_install_status($data["new"]["software_update_inst_id"], "failed");
1390c8 141             return false;
T 142         }
143
b1a6a5 144         $app->log("The update filename is $update_filename", LOGLEVEL_DEBUG);
MC 145
48ced1 146         if(is_file($temp_dir.'/'.$update_filename)) {
b1a6a5 147
48ced1 148             //* Checking the md5sum
T 149             if(md5_file($temp_dir.'/'.$update_filename) != $software_update["update_md5"]) {
b1a6a5 150                 $app->log("The md5 sum of the downloaded file is incorrect. Update aborted.", LOGLEVEL_WARN);
48ced1 151                 exec("rm -rf $temp_dir");
b1a6a5 152                 $app->log("Deleting the temp directory $temp_dir", LOGLEVEL_DEBUG);
8e725d 153                 $this->set_install_status($data["new"]["software_update_inst_id"], "failed");
48ced1 154                 return false;
3f133e 155             } else {
b1a6a5 156                 $app->log("MD5 checksum of the downloaded file verified.", LOGLEVEL_DEBUG);
48ced1 157             }
b1a6a5 158
MC 159
48ced1 160             //* unpacking the update
df8a46 161             $cmd = "cd $temp_dir && unzip $update_filename";
T 162             if($installuser == '') {
163                 exec($cmd);
164             } else {
165                 exec("su -c ".escapeshellarg($cmd)." $installuser");
1390c8 166             }
b1a6a5 167
1390c8 168             //* Create a database, if the package requires one
T 169             if($software_package['package_type'] == 'app' && $software_package['package_requires_db'] == 'mysql') {
b1a6a5 170
1390c8 171                 $app->uses('ini_parser');
T 172                 $package_config = $app->ini_parser->parse_ini_string(stripslashes($software_package['package_config']));
b1a6a5 173
1390c8 174                 $this->create_app_db($package_config['mysql']);
b1a6a5 175                 $app->log("Creating the app DB.", LOGLEVEL_DEBUG);
MC 176
1390c8 177                 //* Load the sql dump into the database
T 178                 if(is_file($temp_dir.'/setup.sql')) {
179                     $db_config = $package_config['mysql'];
b1a6a5 180                     if( $db_config['database_user'] != '' &&
1390c8 181                         $db_config['database_password'] != '' &&
T 182                         $db_config['database_name'] != '' &&
183                         $db_config['database_host'] != '') {
184                         system("mysql --default-character-set=utf8 --force -h '".$db_config['database_host']."' -u '".$db_config['database_user']."' ".$db_config['database_name']." < ".escapeshellcmd($temp_dir.'/setup.sql'));
b1a6a5 185                         $app->log("Loading setup.sql dump into the app db.", LOGLEVEL_DEBUG);
1390c8 186                     }
T 187                 }
b1a6a5 188
1390c8 189             }
b1a6a5 190
1390c8 191             //* Save the package config file as app.ini
T 192             if($software_package['package_config'] != '') {
b1a6a5 193                 file_put_contents($temp_dir.'/app.ini', $software_package['package_config']);
MC 194                 $app->log("Writing ".$temp_dir.'/app.ini', LOGLEVEL_DEBUG);
df8a46 195             }
b1a6a5 196
48ced1 197             if(is_file($temp_dir.'/setup.sh')) {
T 198                 // Execute the setup script
199                 exec('chmod +x '.$temp_dir.'/setup.sh');
b1a6a5 200                 $app->log("Executing setup.sh file in directory $temp_dir", LOGLEVEL_DEBUG);
df8a46 201                 $cmd = 'cd '.$temp_dir.' && ./setup.sh > package_install.log';
T 202                 if($installuser == '') {
203                     exec($cmd);
204                 } else {
205                     exec("su -c ".escapeshellarg($cmd)." $installuser");
206                 }
b1a6a5 207
MC 208                 $log_data = @file_get_contents("{$temp_dir}/package_install.log");
209                 if(preg_match("'.*\[OK\]\s*$'is", $log_data)) {
210                     $app->log("Installation successful", LOGLEVEL_DEBUG);
211                     $app->log($log_data, LOGLEVEL_DEBUG);
212                     $this->set_install_status($data["new"]["software_update_inst_id"], "installed");
213                 } else {
214                     $app->log("Installation failed:\n\n" . $log_data, LOGLEVEL_WARN);
215                     $this->set_install_status($data["new"]["software_update_inst_id"], "failed");
216                 }
48ced1 217             } else {
b1a6a5 218                 $app->log("setup.sh file not found", LOGLEVEL_ERROR);
MC 219                 $this->set_install_status($data["new"]["software_update_inst_id"], "failed");
48ced1 220             }
T 221         } else {
b1a6a5 222             $app->log("Download of the update file failed", LOGLEVEL_WARN);
MC 223             $this->set_install_status($data["new"]["software_update_inst_id"], "failed");
48ced1 224         }
b1a6a5 225
1390c8 226         if($temp_dir != '' && $temp_dir != '/') exec("rm -rf $temp_dir");
b1a6a5 227         $app->log("Deleting the temp directory $temp_dir", LOGLEVEL_DEBUG);
48ced1 228     }
b1a6a5 229
1390c8 230     private function create_app_db($db_config) {
T 231         global $app, $conf;
b1a6a5 232
MC 233         if( $db_config['database_user'] != '' &&
1390c8 234             $db_config['database_password'] != '' &&
T 235             $db_config['database_name'] != '' &&
236             $db_config['database_host'] != '') {
b1a6a5 237
MC 238             if(!include ISPC_LIB_PATH.'/mysql_clientdb.conf') {
239                 $app->log('Unable to open'.ISPC_LIB_PATH.'/mysql_clientdb.conf', LOGLEVEL_ERROR);
1390c8 240                 return;
T 241             }
b1a6a5 242
1390c8 243             if($db_config['database_user'] == 'root') {
b1a6a5 244                 $app->log('User root not allowed for App databases', LOGLEVEL_WARNING);
1390c8 245                 return;
T 246             }
b1a6a5 247
1390c8 248             //* Connect to the database
f1926a 249             $link = mysqli_connect($clientdb_host, $clientdb_user, $clientdb_password);
1390c8 250             if (!$link) {
8a8cc2 251                 $app->log('Unable to connect to the database'.mysqli_connect_error(), LOGLEVEL_ERROR);
1390c8 252                 return;
T 253             }
254
255             $query_charset_table = '';
256
257             //* Create the new database
f1926a 258             if (mysqli_query($link,'CREATE DATABASE '.mysqli_real_escape_string($link, $db_config['database_name']).$query_charset_table, $link)) {
b1a6a5 259                 $app->log('Created MySQL database: '.$db_config['database_name'], LOGLEVEL_DEBUG);
1390c8 260             } else {
f1926a 261                 $app->log('Unable to connect to the database'.mysqli_error($link), LOGLEVEL_ERROR);
1390c8 262             }
T 263
f1926a 264             if(mysqli_query("GRANT ALL ON ".mysqli_real_escape_string($link, $db_config['database_name']).".* TO '".mysqli_real_escape_string($link, $db_config['database_user'])."'@'".$db_config['database_host']."' IDENTIFIED BY '".mysqli_real_escape_string($link, $db_config['database_password'])."';", $link)) {
b1a6a5 265                 $app->log('Created MySQL user: '.$db_config['database_user'], LOGLEVEL_DEBUG);
MC 266             } else {
f1926a 267                 $app->log('Unable to create database user'.$db_config['database_user'].' '.mysqli_error($link), LOGLEVEL_ERROR);
b1a6a5 268             }
MC 269
f1926a 270             mysqli_close($link);
b1a6a5 271
1390c8 272         }
b1a6a5 273
1390c8 274     }
b1a6a5 275
5a43e7 276     //* Operating system update
b1a6a5 277     public function os_update($action_name, $data) {
5a43e7 278         global $app;
b1a6a5 279
5a43e7 280         //** Debian and compatible Linux distributions
T 281         if(file_exists('/etc/debian_version')) {
282             exec("aptitude update");
283             exec("aptitude safe-upgrade -y");
b1a6a5 284             $app->log('Execeuted Debian / Ubuntu update', LOGLEVEL_DEBUG);
5a43e7 285         }
T 286
287         //** Gentoo Linux
288         if(file_exists('/etc/gentoo-release')) {
289             exec("glsa-check -f --nocolor affected");
b1a6a5 290             $app->log('Execeuted Gentoo update', LOGLEVEL_DEBUG);
5a43e7 291         }
b1a6a5 292
5a43e7 293         return 'ok';
T 294     }
48ced1 295
T 296 } // end class
297
8e725d 298 ?>