Marius Burkard
2016-04-20 4569cae57f127afd093794310ccd290d2d9fdf36
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']);
056465 90                         $app->log('cp '.$backup_dir.'/'.$backup['filename'].' '.$web['document_root'].'/backup/'.$backup['filename'], LOGLEVEL_DEBUG);
5a43e7 91                     }
T 92                 }
ddb461 93
MC 94                 //* Restore a MongoDB backup
95                 if($action_name == 'backup_restore' && $backup['backup_type'] == 'mongodb') {
96                     if(file_exists($backup_dir.'/'.$backup['filename'])) {
97                         //$parts = explode('_',$backup['filename']);
98                         //$db_name = $parts[1];
99                         preg_match('@^db_(.+)_\d{4}-\d{2}-\d{2}_\d{2}-\d{2}\.tar\.gz$@', $backup['filename'], $matches);
100                         $db_name = $matches[1];
101
102                         // extract tar.gz archive
103                         $dump_directory = str_replace(".tar.gz", "", $backup['filename']);
104                         $extracted = "/usr/local/ispconfig/server/temp";
105                         exec("tar -xzvf ".escapeshellarg($backup_dir.'/'.$backup['filename'])." --directory=".escapeshellarg($extracted));
106                         $restore_directory = $extracted."/".$dump_directory."/".$db_name;
107
108                         // mongorestore -h 127.0.0.1 -u root -p 123456 --authenticationDatabase admin -d c1debug --drop ./toRestore
109                         $command = "mongorestore -h 127.0.0.1 --port 27017 -u root -p 123456 --authenticationDatabase admin -d ".$db_name." --drop ".escapeshellarg($restore_directory);
5a43e7 110                         exec($command);
ddb461 111                         exec("rm -rf ".escapeshellarg($extracted."/".$dump_directory));
MC 112                     }
113
114                     unset($clientdb_host);
115                     unset($clientdb_user);
116                     unset($clientdb_password);
117                     $app->log('Restored MongoDB backup '.$backup_dir.'/'.$backup['filename'], LOGLEVEL_DEBUG);
5a43e7 118                 }
056465 119
FT 120                 //* Restore a mysql backup
121                 if($action_name == 'backup_restore' && $backup['backup_type'] == 'mysql') {
122                     //* Load sql dump into db
123                     include 'lib/mysql_clientdb.conf';
124
125                     if(file_exists($backup_dir.'/'.$backup['filename'])) {
126                         //$parts = explode('_',$backup['filename']);
127                         //$db_name = $parts[1];
128                         preg_match('@^db_(.+)_\d{4}-\d{2}-\d{2}_\d{2}-\d{2}\.sql\.gz$@', $backup['filename'], $matches);
129                         $db_name = $matches[1];
676dd1 130                         $command = "gunzip --stdout ".escapeshellarg($backup_dir.'/'.$backup['filename'])." | mysql -h '".escapeshellarg($clientdb_host)."' -u '".escapeshellarg($clientdb_user)."' -p'".escapeshellarg($clientdb_password)."' '".$db_name."'";
5a43e7 131                         exec($command);
056465 132                     }
FT 133                     unset($clientdb_host);
134                     unset($clientdb_user);
135                     unset($clientdb_password);
136                     $app->log('Restored MySQL backup '.$backup_dir.'/'.$backup['filename'], LOGLEVEL_DEBUG);
137                 }
138
139                 //* Restore a web backup
140                 if($action_name == 'backup_restore' && $backup['backup_type'] == 'web') {
d219d4 141                     $app->system->web_folder_protection($web['document_root'], false);
056465 142                     if($backup['backup_mode'] == 'userzip') {
FT 143                         if(file_exists($backup_dir.'/'.$backup['filename']) && $web['document_root'] != '' && $web['document_root'] != '/' && !stristr($backup_dir.'/'.$backup['filename'], '..') && !stristr($backup_dir.'/'.$backup['filename'], 'etc')) {
144                             if(file_exists($web['document_root'].'/backup/'.$backup['filename'])) rename($web['document_root'].'/backup/'.$backup['filename'], $web['document_root'].'/backup/'.$backup['filename'].'.bak');
145                             copy($backup_dir.'/'.$backup['filename'], $web['document_root'].'/backup/'.$backup['filename']);
146                             chgrp($web['document_root'].'/backup/'.$backup['filename'], $web['system_group']);
147                             //chown($web['document_root'].'/backup/'.$backup['filename'],$web['system_user']);
148                             $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';
149                             exec($command);
150                             unlink($web['document_root'].'/backup/'.$backup['filename']);
151                             if(file_exists($web['document_root'].'/backup/'.$backup['filename'].'.bak')) rename($web['document_root'].'/backup/'.$backup['filename'].'.bak', $web['document_root'].'/backup/'.$backup['filename']);
152                             $app->log('Restored Web backup '.$backup_dir.'/'.$backup['filename'], LOGLEVEL_DEBUG);
153                         }
154                     }
155                     if($backup['backup_mode'] == 'rootgz') {
156                         if(file_exists($backup_dir.'/'.$backup['filename']) && $web['document_root'] != '' && $web['document_root'] != '/' && !stristr($backup_dir.'/'.$backup['filename'], '..') && !stristr($backup_dir.'/'.$backup['filename'], 'etc')) {
157                             $command = 'tar xzf '.escapeshellarg($backup_dir.'/'.$backup['filename']).' --directory '.escapeshellarg($web['document_root']);
158                             exec($command);
159                             $app->log('Restored Web backup '.$backup_dir.'/'.$backup['filename'], LOGLEVEL_DEBUG);
160                         }
5a43e7 161                     }
d219d4 162                     $app->system->web_folder_protection($web['document_root'], true);
5a43e7 163                 }
634132 164                 
D 165                 if($action_name == 'backup_delete') {
166                     if(file_exists($backup_dir.'/'.$backup['filename']) && !stristr($backup_dir.'/'.$backup['filename'], '..') && !stristr($backup_dir.'/'.$backup['filename'], 'etc')) {
167                         unlink($backup_dir.'/'.$backup['filename']);
168                         
169                         $sql = "DELETE FROM mail_backup WHERE server_id = ? AND parent_domain_id = ? AND filename = ?";
170                         $app->db->query($sql, $conf['server_id'], $backup['parent_domain_id'], $backup['filename']);
171                         if($app->db->dbHost != $app->dbmaster->dbHost) $app->dbmaster->query($sql);
172                         $app->log('unlink '.$backup_dir.'/'.$backup['filename'], LOGLEVEL_DEBUG);
173                     }
174                 }
175
b73ab0 176                 if( $server_config['backup_dir_is_mount'] == 'y' ) $app->system->umount_backup_dir($backup_dir);
056465 177             } else {
FT 178                 $app->log('Backup directory not ready.', LOGLEVEL_DEBUG);
5a43e7 179             }
d2c52b 180         } else {
D 181             $app->log('No backup with ID '.$backup_id.' found.', LOGLEVEL_DEBUG);
182         }
b1a6a5 183
d2c52b 184         return 'ok';
D 185     }
186
187     //* Restore a mail backup - florian@schaal-24.de
188     public function backup_action_mail($action_name, $data) {
189         global $app, $conf;
190     
191         $backup_id = intval($data);
cc7a82 192         $mail_backup = $app->dbmaster->queryOneRecord("SELECT * FROM mail_backup WHERE backup_id = ?", $backup_id);
d2c52b 193     
634132 194         if (is_array($mail_backup)) {
d2c52b 195             $app->uses('ini_parser,file,getconf');
D 196     
f17718 197             $server_config = $app->getconf->get_server_config($conf['server_id'], 'server');
634132 198             $backup_dir = $server_config['backup_dir'];
f8fda4 199             $backup_dir_is_ready = true;
d2c52b 200     
990ca8 201             //* mount backup directory, if necessary
f8fda4 202             if( $server_config['backup_dir_is_mount'] == 'y' && !$app->system->mount_backup_dir($backup_dir) ) $backup_dir_is_ready = false;
d2c52b 203     
f8fda4 204             if($backup_dir_is_ready){
caee7b 205                 $mail_config = $app->getconf->get_server_config($conf['server_id'], 'mail');
cc7a82 206                 $domain_rec = $app->db->queryOneRecord("SELECT * FROM mail_domain WHERE domain_id = ?", $mail_backup['parent_domain_id']);
d2c52b 207             
caee7b 208                 $backup_dir = $server_config['backup_dir'].'/mail'.$domain_rec['domain_id'];
F 209                 $mail_backup_file = $backup_dir.'/'.$mail_backup['filename'];
d2c52b 210             
cc7a82 211                 $sql = "SELECT * FROM mail_user WHERE server_id = ? AND mailuser_id = ?";
MC 212                 $record = $app->db->queryOneRecord($sql, $conf['server_id'], $mail_backup['mailuser_id']);
d2c52b 213             
caee7b 214                 //* strip mailbox from maildir
F 215                 $domain_dir=explode('/',$record['maildir']);
216                 $_temp=array_pop($domain_dir);unset($_temp);
217                 $domain_dir=implode('/',$domain_dir);
d2c52b 218             
caee7b 219                 if(!is_dir($domain_dir)) {
F 220                     mkdir($domain_dir, 0700); //* never create the full path
221                     chown($domain_dir, $mail_config['mailuser_name']);
222                     chgrp($domain_dir, $mail_config['mailuser_group']);
223                 }
f339eb 224                 if (!is_dir($record['maildir'])) {
D 225                     mkdir($record['maildir'], 0700); //* never create the full path
226                     chown($record['maildir'], $mail_config['mailuser_name']);
227                     chgrp($record['maildir'], $mail_config['mailuser_group']);
228                 }
d2c52b 229             
634132 230                 if ($action_name == 'backup_restore_mail') {
D 231                     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'])) {
232                         if ($record['maildir_format'] == 'mdbox') {
233                             $retval = -1;
234                             // First unzip backupfile to local backup-folder
235                             if($mail_backup['backup_mode'] == 'userzip') {
236                                 copy($mail_backup_file, $record['maildir'].'/'.$mail_backup['filename']);
237                                 chgrp($record['maildir'].'/'.$mail_backup['filename'], $mail_config['mailuser_group']);
238                                 $command = 'sudo -u '.$mail_config['mailuser_name'].' unzip -qq -o  '.escapeshellarg($record['maildir'].'/'.$mail_backup['filename']).' -d '.escapeshellarg($record['maildir']).' 2> /dev/null';
239                                 exec($command,$tmp_output, $retval);
240                                 unlink($record['maildir'].'/'.$mail_backup['filename']);
241                             }
242                             if($mail_backup['backup_mode'] == 'rootgz') {
243                                 $command='tar xfz '.escapeshellarg($mail_backup_file).' --directory '.escapeshellarg($record['maildir']);
244                                 exec($command,$tmp_output, $retval);
245                             }
f339eb 246                             
634132 247                             if($retval == 0) {
D 248                                 // Now import backup-mailbox into special backup-folder
249                                 $backupname = "backup-".date("Y-m-d", $mail_backup['tstamp']);
250                                 exec("doveadm mailbox create -u \"".$record["email"]."\" $backupname");
251                                 exec("doveadm import -u \"".$record["email"]."\" mdbox:".$record['maildir']."/backup $backupname all", $tmp_output, $retval);
252                                 exec("for f in `doveadm mailbox list -u \"".$record["email"]."\" $backupname*`; do doveadm mailbox subscribe -u \"".$record["email"]."\" \$f; done", $tmp_output, $retval);
253                                 exec('rm -rf '.$record['maildir'].'/backup');
254                             }
255                             
f339eb 256                             if($retval == 0){
D 257                                 $app->log('Restored Mail backup '.$mail_backup_file,LOGLEVEL_DEBUG);
258                             } else {
634132 259                                 // cleanup
D 260                                 if (file_exists($record['maildir'].'/'.$mail_backup['filename'])) unlink($record['maildir'].'/'.$mail_backup['filename']);
261                                 if (file_exists($record['maildir']."/backup")) exec('rm -rf '.$record['maildir']."/backup");
262                                 
f339eb 263                                 $app->log('Unable to restore Mail backup '.$mail_backup_file.' '.$tmp_output,LOGLEVEL_ERROR);
D 264                             }
265                         }
634132 266                         else {
D 267                             if($mail_backup['backup_mode'] == 'userzip') {
268                                 copy($mail_backup_file, $domain_dir.'/'.$mail_backup['filename']);
269                                 chgrp($domain_dir.'/'.$mail_backup['filename'], $mail_config['mailuser_group']);
270                                 $command = 'sudo -u '.$mail_config['mailuser_name'].' unzip -qq -o  '.escapeshellarg($domain_dir.'/'.$mail_backup['filename']).' -d '.escapeshellarg($domain_dir).' 2> /dev/null';
271                                 exec($command,$tmp_output, $retval);
272                                 unlink($domain_dir.'/'.$mail_backup['filename']);
273                                 if($retval == 0){
274                                     $app->log('Restored Mail backup '.$mail_backup_file,LOGLEVEL_DEBUG);
275                                 } else {
276                                     $app->log('Unable to restore Mail backup '.$mail_backup_file.' '.$tmp_output,LOGLEVEL_ERROR);
277                                 }
278                             }
279                             if($mail_backup['backup_mode'] == 'rootgz') {
280                                 $command='tar xfz '.escapeshellarg($mail_backup_file).' --directory '.escapeshellarg($domain_dir);
281                                 exec($command,$tmp_output, $retval);
282                                 if($retval == 0){
283                                     $app->log('Restored Mail backup '.$mail_backup_file,LOGLEVEL_DEBUG);
284                                 } else {
285                                     $app->log('Unable to restore Mail backup '.$mail_backup_file.' '.$tmp_output,LOGLEVEL_ERROR);
286                                 }
f339eb 287                             }
caee7b 288                         }
f17718 289                     }
FS 290                 }
634132 291                 
D 292                 if($action_name == 'backup_delete_mail') {
293                     if(file_exists($mail_backup_file) && !stristr($mail_backup_file, '..') && !stristr($mail_backup_file, 'etc')) {
294                         unlink($mail_backup_file);
295                         $sql = "DELETE FROM mail_backup WHERE server_id = ? AND parent_domain_id = ? AND filename = ?";
296                         $app->db->query($sql, $conf['server_id'], $mail_backup['parent_domain_id'], $mail_backup['filename']);
297                         if($app->db->dbHost != $app->dbmaster->dbHost) $app->dbmaster->query($sql);
298                         $app->log('unlink '.$backup_dir.'/'.$mail_backup['filename'], LOGLEVEL_DEBUG);
299                     }
300                 }
301                 
b73ab0 302                 if( $server_config['backup_dir_is_mount'] == 'y' ) $app->system->umount_backup_dir($backup_dir);
f17718 303             } else {
caee7b 304                 $app->log('Backup directory not ready.', LOGLEVEL_DEBUG);
f17718 305             }
5a43e7 306         } else {
caee7b 307             $app->log('No backup with ID '.$backup_id.' found.', LOGLEVEL_DEBUG);
5a43e7 308         }
b1a6a5 309
5a43e7 310         return 'ok';
T 311     }
d2c52b 312             
D 313                 
5a43e7 314 } // end class
T 315
f17718 316 ?>            
FS 317