Pascal Dreissen
2016-07-08 f1193b43f4c9fd132741d30f03f0b35841011989
commit | author | age
5a43e7 1 <?php
T 2
3 /*
4 Copyright (c) 2012, Till Brehm, ISPConfig UG
5 All rights reserved.
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 backup_plugin {
b1a6a5 32
5a43e7 33     var $plugin_name = 'backup_plugin';
T 34     var $class_name  = 'backup_plugin';
b1a6a5 35
5a43e7 36     //* This function is called during ispconfig installation to determine
T 37     //  if a symlink shall be created for this plugin.
38     public function onInstall() {
39         global $conf;
b1a6a5 40
5a43e7 41         return true;
b1a6a5 42
5a43e7 43     }
b1a6a5 44
MC 45
5a43e7 46     /*
T 47          This function is called when the plugin is loaded
48     */
b1a6a5 49
5a43e7 50     public function onLoad() {
T 51         global $app;
b1a6a5 52
5a43e7 53         //* Register for actions
b1a6a5 54         $app->plugins->registerAction('backup_download', $this->plugin_name, 'backup_action');
MC 55         $app->plugins->registerAction('backup_restore', $this->plugin_name, 'backup_action');
634132 56         $app->plugins->registerAction('backup_delete', $this->plugin_name, 'backup_action');
d2c52b 57         //$app->plugins->registerAction('backup_download_mail', $this->plugin_name, 'backup_action_mail');
D 58         $app->plugins->registerAction('backup_restore_mail', $this->plugin_name, 'backup_action_mail');
634132 59         $app->plugins->registerAction('backup_delete_mail', $this->plugin_name, 'backup_action_mail');
5a43e7 60     }
b1a6a5 61
5a43e7 62     //* Do a backup action
b1a6a5 63     public function backup_action($action_name, $data) {
MC 64         global $app, $conf;
65
5a43e7 66         $backup_id = intval($data);
cc7a82 67         $backup = $app->dbmaster->queryOneRecord("SELECT * FROM web_backup WHERE backup_id = ?", $backup_id);
b1a6a5 68
d2c52b 69         if(is_array($backup)) {
b1a6a5 70
056465 71             $app->uses('ini_parser,file,getconf,system');
b1a6a5 72
cc7a82 73             $web = $app->dbmaster->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ?", $backup['parent_domain_id']);
5a43e7 74             $server_config = $app->getconf->get_server_config($conf['server_id'], 'server');
b48a0b 75             $backup_dir = trim($server_config['backup_dir']);
FS 76             if($backup_dir == '') return;
77             $backup_dir .= '/web'.$web['domain_id'];
056465 78             
FT 79             $backup_dir_is_ready = true;
990ca8 80             //* mount backup directory, if necessary
c41c8f 81             if( $server_config['backup_dir_is_mount'] == 'y' && !$app->system->mount_backup_dir($server_config['backup_dir']) ) $backup_dir_is_ready = false;
bd68aa 82
056465 83             if($backup_dir_is_ready){
FT 84                 //* Make backup available for download
85                 if($action_name == 'backup_download') {
86                     //* Copy the backup file to the backup folder of the website
f75777 87                     if(file_exists($backup_dir.'/'.$backup['filename']) && file_exists($web['document_root'].'/backup/') && !stristr($backup_dir.'/'.$backup['filename'], '..') && !stristr($backup_dir.'/'.$backup['filename'], 'etc')) {
b1a6a5 88                         copy($backup_dir.'/'.$backup['filename'], $web['document_root'].'/backup/'.$backup['filename']);
MC 89                         chgrp($web['document_root'].'/backup/'.$backup['filename'], $web['system_group']);
65ee3a 90                         chmod($web['document_root'].'/backup/'.$backup['filename'],0600);
056465 91                         $app->log('cp '.$backup_dir.'/'.$backup['filename'].' '.$web['document_root'].'/backup/'.$backup['filename'], LOGLEVEL_DEBUG);
5a43e7 92                     }
T 93                 }
ddb461 94
MC 95                 //* Restore a MongoDB backup
96                 if($action_name == 'backup_restore' && $backup['backup_type'] == 'mongodb') {
97                     if(file_exists($backup_dir.'/'.$backup['filename'])) {
98                         //$parts = explode('_',$backup['filename']);
99                         //$db_name = $parts[1];
100                         preg_match('@^db_(.+)_\d{4}-\d{2}-\d{2}_\d{2}-\d{2}\.tar\.gz$@', $backup['filename'], $matches);
101                         $db_name = $matches[1];
102
103                         // extract tar.gz archive
104                         $dump_directory = str_replace(".tar.gz", "", $backup['filename']);
105                         $extracted = "/usr/local/ispconfig/server/temp";
106                         exec("tar -xzvf ".escapeshellarg($backup_dir.'/'.$backup['filename'])." --directory=".escapeshellarg($extracted));
107                         $restore_directory = $extracted."/".$dump_directory."/".$db_name;
108
109                         // mongorestore -h 127.0.0.1 -u root -p 123456 --authenticationDatabase admin -d c1debug --drop ./toRestore
110                         $command = "mongorestore -h 127.0.0.1 --port 27017 -u root -p 123456 --authenticationDatabase admin -d ".$db_name." --drop ".escapeshellarg($restore_directory);
5a43e7 111                         exec($command);
ddb461 112                         exec("rm -rf ".escapeshellarg($extracted."/".$dump_directory));
MC 113                     }
114
115                     unset($clientdb_host);
116                     unset($clientdb_user);
117                     unset($clientdb_password);
118                     $app->log('Restored MongoDB backup '.$backup_dir.'/'.$backup['filename'], LOGLEVEL_DEBUG);
5a43e7 119                 }
056465 120
FT 121                 //* Restore a mysql backup
122                 if($action_name == 'backup_restore' && $backup['backup_type'] == 'mysql') {
123                     //* Load sql dump into db
124                     include 'lib/mysql_clientdb.conf';
125
126                     if(file_exists($backup_dir.'/'.$backup['filename'])) {
127                         //$parts = explode('_',$backup['filename']);
128                         //$db_name = $parts[1];
129                         preg_match('@^db_(.+)_\d{4}-\d{2}-\d{2}_\d{2}-\d{2}\.sql\.gz$@', $backup['filename'], $matches);
130                         $db_name = $matches[1];
676dd1 131                         $command = "gunzip --stdout ".escapeshellarg($backup_dir.'/'.$backup['filename'])." | mysql -h '".escapeshellarg($clientdb_host)."' -u '".escapeshellarg($clientdb_user)."' -p'".escapeshellarg($clientdb_password)."' '".$db_name."'";
5a43e7 132                         exec($command);
056465 133                     }
FT 134                     unset($clientdb_host);
135                     unset($clientdb_user);
136                     unset($clientdb_password);
137                     $app->log('Restored MySQL backup '.$backup_dir.'/'.$backup['filename'], LOGLEVEL_DEBUG);
138                 }
139
140                 //* Restore a web backup
141                 if($action_name == 'backup_restore' && $backup['backup_type'] == 'web') {
d219d4 142                     $app->system->web_folder_protection($web['document_root'], false);
056465 143                     if($backup['backup_mode'] == 'userzip') {
FT 144                         if(file_exists($backup_dir.'/'.$backup['filename']) && $web['document_root'] != '' && $web['document_root'] != '/' && !stristr($backup_dir.'/'.$backup['filename'], '..') && !stristr($backup_dir.'/'.$backup['filename'], 'etc')) {
145                             if(file_exists($web['document_root'].'/backup/'.$backup['filename'])) rename($web['document_root'].'/backup/'.$backup['filename'], $web['document_root'].'/backup/'.$backup['filename'].'.bak');
146                             copy($backup_dir.'/'.$backup['filename'], $web['document_root'].'/backup/'.$backup['filename']);
147                             chgrp($web['document_root'].'/backup/'.$backup['filename'], $web['system_group']);
148                             //chown($web['document_root'].'/backup/'.$backup['filename'],$web['system_user']);
149                             $command = 'sudo -u '.escapeshellarg($web['system_user']).' unzip -qq -o  '.escapeshellarg($web['document_root'].'/backup/'.$backup['filename']).' -d '.escapeshellarg($web['document_root']).' 2> /dev/null';
150                             exec($command);
151                             unlink($web['document_root'].'/backup/'.$backup['filename']);
152                             if(file_exists($web['document_root'].'/backup/'.$backup['filename'].'.bak')) rename($web['document_root'].'/backup/'.$backup['filename'].'.bak', $web['document_root'].'/backup/'.$backup['filename']);
153                             $app->log('Restored Web backup '.$backup_dir.'/'.$backup['filename'], LOGLEVEL_DEBUG);
154                         }
155                     }
156                     if($backup['backup_mode'] == 'rootgz') {
157                         if(file_exists($backup_dir.'/'.$backup['filename']) && $web['document_root'] != '' && $web['document_root'] != '/' && !stristr($backup_dir.'/'.$backup['filename'], '..') && !stristr($backup_dir.'/'.$backup['filename'], 'etc')) {
158                             $command = 'tar xzf '.escapeshellarg($backup_dir.'/'.$backup['filename']).' --directory '.escapeshellarg($web['document_root']);
159                             exec($command);
160                             $app->log('Restored Web backup '.$backup_dir.'/'.$backup['filename'], LOGLEVEL_DEBUG);
161                         }
5a43e7 162                     }
d219d4 163                     $app->system->web_folder_protection($web['document_root'], true);
5a43e7 164                 }
634132 165                 
D 166                 if($action_name == 'backup_delete') {
167                     if(file_exists($backup_dir.'/'.$backup['filename']) && !stristr($backup_dir.'/'.$backup['filename'], '..') && !stristr($backup_dir.'/'.$backup['filename'], 'etc')) {
168                         unlink($backup_dir.'/'.$backup['filename']);
169                         
170                         $sql = "DELETE FROM mail_backup WHERE server_id = ? AND parent_domain_id = ? AND filename = ?";
171                         $app->db->query($sql, $conf['server_id'], $backup['parent_domain_id'], $backup['filename']);
172                         if($app->db->dbHost != $app->dbmaster->dbHost) $app->dbmaster->query($sql);
173                         $app->log('unlink '.$backup_dir.'/'.$backup['filename'], LOGLEVEL_DEBUG);
174                     }
175                 }
176
b73ab0 177                 if( $server_config['backup_dir_is_mount'] == 'y' ) $app->system->umount_backup_dir($backup_dir);
056465 178             } else {
FT 179                 $app->log('Backup directory not ready.', LOGLEVEL_DEBUG);
5a43e7 180             }
d2c52b 181         } else {
D 182             $app->log('No backup with ID '.$backup_id.' found.', LOGLEVEL_DEBUG);
183         }
b1a6a5 184
d2c52b 185         return 'ok';
D 186     }
187
188     //* Restore a mail backup - florian@schaal-24.de
189     public function backup_action_mail($action_name, $data) {
190         global $app, $conf;
191     
192         $backup_id = intval($data);
cc7a82 193         $mail_backup = $app->dbmaster->queryOneRecord("SELECT * FROM mail_backup WHERE backup_id = ?", $backup_id);
d2c52b 194     
634132 195         if (is_array($mail_backup)) {
d2c52b 196             $app->uses('ini_parser,file,getconf');
D 197     
f17718 198             $server_config = $app->getconf->get_server_config($conf['server_id'], 'server');
634132 199             $backup_dir = $server_config['backup_dir'];
f8fda4 200             $backup_dir_is_ready = true;
d2c52b 201     
990ca8 202             //* mount backup directory, if necessary
f8fda4 203             if( $server_config['backup_dir_is_mount'] == 'y' && !$app->system->mount_backup_dir($backup_dir) ) $backup_dir_is_ready = false;
d2c52b 204     
f8fda4 205             if($backup_dir_is_ready){
caee7b 206                 $mail_config = $app->getconf->get_server_config($conf['server_id'], 'mail');
cc7a82 207                 $domain_rec = $app->db->queryOneRecord("SELECT * FROM mail_domain WHERE domain_id = ?", $mail_backup['parent_domain_id']);
d2c52b 208             
caee7b 209                 $backup_dir = $server_config['backup_dir'].'/mail'.$domain_rec['domain_id'];
F 210                 $mail_backup_file = $backup_dir.'/'.$mail_backup['filename'];
d2c52b 211             
cc7a82 212                 $sql = "SELECT * FROM mail_user WHERE server_id = ? AND mailuser_id = ?";
MC 213                 $record = $app->db->queryOneRecord($sql, $conf['server_id'], $mail_backup['mailuser_id']);
d2c52b 214             
caee7b 215                 //* strip mailbox from maildir
F 216                 $domain_dir=explode('/',$record['maildir']);
217                 $_temp=array_pop($domain_dir);unset($_temp);
218                 $domain_dir=implode('/',$domain_dir);
d2c52b 219             
caee7b 220                 if(!is_dir($domain_dir)) {
F 221                     mkdir($domain_dir, 0700); //* never create the full path
222                     chown($domain_dir, $mail_config['mailuser_name']);
223                     chgrp($domain_dir, $mail_config['mailuser_group']);
224                 }
f339eb 225                 if (!is_dir($record['maildir'])) {
D 226                     mkdir($record['maildir'], 0700); //* never create the full path
227                     chown($record['maildir'], $mail_config['mailuser_name']);
228                     chgrp($record['maildir'], $mail_config['mailuser_group']);
229                 }
d2c52b 230             
634132 231                 if ($action_name == 'backup_restore_mail') {
D 232                     if(file_exists($mail_backup_file) && $record['homedir'] != '' && $record['homedir'] != '/' && !stristr($mail_backup_file,'..') && !stristr($mail_backup_file,'etc') && $mail_config['homedir_path'] == $record['homedir'] && is_dir($domain_dir) && is_dir($record['maildir'])) {
233                         if ($record['maildir_format'] == 'mdbox') {
234                             $retval = -1;
235                             // First unzip backupfile to local backup-folder
236                             if($mail_backup['backup_mode'] == 'userzip') {
237                                 copy($mail_backup_file, $record['maildir'].'/'.$mail_backup['filename']);
238                                 chgrp($record['maildir'].'/'.$mail_backup['filename'], $mail_config['mailuser_group']);
239                                 $command = 'sudo -u '.$mail_config['mailuser_name'].' unzip -qq -o  '.escapeshellarg($record['maildir'].'/'.$mail_backup['filename']).' -d '.escapeshellarg($record['maildir']).' 2> /dev/null';
240                                 exec($command,$tmp_output, $retval);
241                                 unlink($record['maildir'].'/'.$mail_backup['filename']);
242                             }
243                             if($mail_backup['backup_mode'] == 'rootgz') {
244                                 $command='tar xfz '.escapeshellarg($mail_backup_file).' --directory '.escapeshellarg($record['maildir']);
245                                 exec($command,$tmp_output, $retval);
246                             }
f339eb 247                             
634132 248                             if($retval == 0) {
D 249                                 // Now import backup-mailbox into special backup-folder
250                                 $backupname = "backup-".date("Y-m-d", $mail_backup['tstamp']);
251                                 exec("doveadm mailbox create -u \"".$record["email"]."\" $backupname");
252                                 exec("doveadm import -u \"".$record["email"]."\" mdbox:".$record['maildir']."/backup $backupname all", $tmp_output, $retval);
253                                 exec("for f in `doveadm mailbox list -u \"".$record["email"]."\" $backupname*`; do doveadm mailbox subscribe -u \"".$record["email"]."\" \$f; done", $tmp_output, $retval);
254                                 exec('rm -rf '.$record['maildir'].'/backup');
255                             }
256                             
f339eb 257                             if($retval == 0){
D 258                                 $app->log('Restored Mail backup '.$mail_backup_file,LOGLEVEL_DEBUG);
259                             } else {
634132 260                                 // cleanup
D 261                                 if (file_exists($record['maildir'].'/'.$mail_backup['filename'])) unlink($record['maildir'].'/'.$mail_backup['filename']);
262                                 if (file_exists($record['maildir']."/backup")) exec('rm -rf '.$record['maildir']."/backup");
263                                 
f339eb 264                                 $app->log('Unable to restore Mail backup '.$mail_backup_file.' '.$tmp_output,LOGLEVEL_ERROR);
D 265                             }
266                         }
634132 267                         else {
D 268                             if($mail_backup['backup_mode'] == 'userzip') {
269                                 copy($mail_backup_file, $domain_dir.'/'.$mail_backup['filename']);
270                                 chgrp($domain_dir.'/'.$mail_backup['filename'], $mail_config['mailuser_group']);
271                                 $command = 'sudo -u '.$mail_config['mailuser_name'].' unzip -qq -o  '.escapeshellarg($domain_dir.'/'.$mail_backup['filename']).' -d '.escapeshellarg($domain_dir).' 2> /dev/null';
272                                 exec($command,$tmp_output, $retval);
273                                 unlink($domain_dir.'/'.$mail_backup['filename']);
274                                 if($retval == 0){
275                                     $app->log('Restored Mail backup '.$mail_backup_file,LOGLEVEL_DEBUG);
276                                 } else {
277                                     $app->log('Unable to restore Mail backup '.$mail_backup_file.' '.$tmp_output,LOGLEVEL_ERROR);
278                                 }
279                             }
280                             if($mail_backup['backup_mode'] == 'rootgz') {
281                                 $command='tar xfz '.escapeshellarg($mail_backup_file).' --directory '.escapeshellarg($domain_dir);
282                                 exec($command,$tmp_output, $retval);
283                                 if($retval == 0){
284                                     $app->log('Restored Mail backup '.$mail_backup_file,LOGLEVEL_DEBUG);
285                                 } else {
286                                     $app->log('Unable to restore Mail backup '.$mail_backup_file.' '.$tmp_output,LOGLEVEL_ERROR);
287                                 }
f339eb 288                             }
caee7b 289                         }
f17718 290                     }
FS 291                 }
634132 292                 
D 293                 if($action_name == 'backup_delete_mail') {
294                     if(file_exists($mail_backup_file) && !stristr($mail_backup_file, '..') && !stristr($mail_backup_file, 'etc')) {
295                         unlink($mail_backup_file);
296                         $sql = "DELETE FROM mail_backup WHERE server_id = ? AND parent_domain_id = ? AND filename = ?";
297                         $app->db->query($sql, $conf['server_id'], $mail_backup['parent_domain_id'], $mail_backup['filename']);
298                         if($app->db->dbHost != $app->dbmaster->dbHost) $app->dbmaster->query($sql);
299                         $app->log('unlink '.$backup_dir.'/'.$mail_backup['filename'], LOGLEVEL_DEBUG);
300                     }
301                 }
302                 
b73ab0 303                 if( $server_config['backup_dir_is_mount'] == 'y' ) $app->system->umount_backup_dir($backup_dir);
f17718 304             } else {
caee7b 305                 $app->log('Backup directory not ready.', LOGLEVEL_DEBUG);
f17718 306             }
5a43e7 307         } else {
caee7b 308             $app->log('No backup with ID '.$backup_id.' found.', LOGLEVEL_DEBUG);
5a43e7 309         }
b1a6a5 310
5a43e7 311         return 'ok';
T 312     }
d2c52b 313             
D 314                 
5a43e7 315 } // end class
T 316
f17718 317 ?>            
FS 318