Marius Burkard
2016-07-01 49441bdd0f3ff75d5092d5b832b97ea722a66363
commit | author | age
f17718 1 <?php
FS 2 /*
3 Copyright (c) 2013, Florian Schaal, info@schaal-24.de
4 All rights reserved.
5
6 Redistribution and use in source and binary forms, with or without modification,
7 are permitted provided that the following conditions are met:
8
9     * Redistributions of source code must retain the above copyright notice,
10       this list of conditions and the following disclaimer.
11     * Redistributions in binary form must reproduce the above copyright notice,
12       this list of conditions and the following disclaimer in the documentation
13       and/or other materials provided with the distribution.
14     * Neither the name of ISPConfig nor the names of its contributors
15       may be used to endorse or promote products derived from this software without
16       specific prior written permission.
17
18 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
22 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
25 OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
27 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
955491 30 class cronjob_backup_mail extends cronjob {
f17718 31
FS 32     // job schedule
33     protected $_schedule = '0 0 * * *';
f339eb 34     private $tmp_backup_dir = '';
f17718 35
FS 36     /* this function is optional if it contains no custom code */
37     public function onPrepare() {
38         global $app;
39
40         parent::onPrepare();
41     }
42
43     /* this function is optional if it contains no custom code */
44     public function onBeforeRun() {
45         global $app;
46
47         return parent::onBeforeRun();
48     }
49
50     public function onRunJob() {
51         global $app, $conf;
52
53         $server_config = $app->getconf->get_server_config($conf['server_id'], 'server');
c220da 54         $mail_config = $app->getconf->get_server_config($conf['server_id'], 'mail');
6b166b 55         $global_config = $app->getconf->get_global_config('sites');
DM 56         
b48a0b 57         $backup_dir = trim($server_config['backup_dir']);
c220da 58         $backup_dir_permissions =0750;
FS 59
f17718 60         $backup_mode = $server_config['backup_mode'];
FS 61         if($backup_mode == '') $backup_mode = 'userzip';
62
63         if($backup_dir != '') {
64             $run_backups = true;
990ca8 65             //* mount backup directory, if necessary
FS 66             if( $server_config['backup_dir_is_mount'] == 'y' && !$app->system->mount_backup_dir($backup_dir) ) $run_backups = false;
f17718 67
cc7a82 68             $records = $app->db->queryAllRecords("SELECT * FROM mail_user WHERE server_id = ? AND maildir != ''", intval($conf['server_id']));
2e1453 69             if(is_array($records) && $run_backups) {
c220da 70                 if(!is_dir($backup_dir)) {
FS 71                     mkdir(escapeshellcmd($backup_dir), $backup_dir_permissions, true);
72                 } else {
73                     chmod(escapeshellcmd($backup_dir), $backup_dir_permissions);
74                 }
75
f17718 76                 foreach($records as $rec) {
FS 77                     //* Do the mailbox backup
66fa9b 78                     $email = $rec['email'];
FS 79                     $temp = explode("@",$email);
80                     $domain = $temp[1];
81                     unset($temp);
82                     $domain_rec=$app->db->queryOneRecord("SELECT * FROM mail_domain WHERE domain = ?", $domain);
83
f17718 84                     if($rec['backup_interval'] == 'daily' or ($rec['backup_interval'] == 'weekly' && date('w') == 0) or ($rec['backup_interval'] == 'monthly' && date('d') == '01')) {
370c6a 85                         
D 86                         $backupusername = 'root';
87                         $backupgroup = 'root';
88                         if ($global_config['backups_include_into_web_quota'] == 'y') {
89                             // this only works, if mail and webdomains are on the same server
90                             // find webdomain fitting to maildomain
cc7a82 91                             $sql = "SELECT * FROM web_domain WHERE domain = ?";
MC 92                             $webdomain = $app->db->queryOneRecord($sql, $domain_rec['domain']);
370c6a 93                             // if this is not also the website, find website now
D 94                             if ($webdomain && ($webdomain['parent_domain_id'] != 0)) {
95                                 do {
cc7a82 96                                     $sql = "SELECT * FROM web_domain WHERE domain_id = ?";
MC 97                                     $webdomain = $app->db->queryOneRecord($sql, $webdomain['parent_domain_id']);
370c6a 98                                 } while ($webdomain && ($webdomain['parent_domain_id'] != 0));
D 99                             }
100                             // if webdomain is found, change username/group now
101                             if ($webdomain) {
102                                 $backupusername = $webdomain['system_user'];
103                                 $backupgroup = $webdomain['system_group'];
104                             }
105                         }                        
f17718 106
c220da 107                         $mail_backup_dir = $backup_dir.'/mail'.$domain_rec['domain_id'];
f17718 108                         if(!is_dir($mail_backup_dir)) mkdir($mail_backup_dir, 0750);
FS 109                         chmod($mail_backup_dir, $backup_dir_permissions);
370c6a 110                         chown($mail_backup_dir, $backupusername);
D 111                         chgrp($mail_backup_dir, $backupgroup);
c220da 112
FS 113                         $mail_backup_file = 'mail'.$rec['mailuser_id'].'_'.date('Y-m-d_H-i');
f17718 114
f339eb 115                         // in case of mdbox -> create backup with doveadm before zipping
D 116                         if ($rec['maildir_format'] == 'mdbox') {
117                             if (empty($this->tmp_backup_dir)) $this->tmp_backup_dir = $rec['maildir'];
118                             // Create temporary backup-mailbox
119                             exec("su -c 'dsync backup -u \"".$rec["email"]."\" mdbox:".$this->tmp_backup_dir."/backup'", $tmp_output, $retval);
120         
121                             if($backup_mode == 'userzip') {
122                                 $mail_backup_file.='.zip';
123                                 exec('cd '.$this->tmp_backup_dir.' && zip '.$mail_backup_dir.'/'.$mail_backup_file.' -b /tmp -r backup > /dev/null && rm -rf backup', $tmp_output, $retval);
124                             }
125                             else {
126                                 $mail_backup_file.='.tar.gz';
127                                 exec(escapeshellcmd('tar pczf '.$mail_backup_dir.'/'.$mail_backup_file.' --directory '.$this->tmp_backup_dir.' backup && rm -rf '.$this->tmp_backup_dir.'/backup'), $tmp_output, $retval);
128                             }
129                             
130                             if ($retval != 0) {
131                                 // Cleanup
132                                 if (file_exists($this->tmp_backup_dir.'/backup')) exec('rm -rf '.$this->tmp_backup_dir.'/backup');
133                             }
f17718 134                         }
f339eb 135                         else {
D 136                             $domain_dir=explode('/',$rec['maildir']);
137                             $_temp=array_pop($domain_dir);unset($_temp);
138                             $domain_dir=implode('/',$domain_dir);
139                             
140                             $parts=explode('/',$rec['maildir']);
141                             $source_dir=array_pop($parts);
142                             unset($parts);
143                             
144                             //* create archives
145                             if($backup_mode == 'userzip') {
146                                 $mail_backup_file.='.zip';
147                                 exec('cd '.$domain_dir.' && zip '.$mail_backup_dir.'/'.$mail_backup_file.' -b /tmp -r '.$source_dir.' > /dev/null', $tmp_output, $retval);
148                             } else {
149                                 /* Create a tar.gz backup */
150                                 $mail_backup_file.='.tar.gz';
151                                 exec(escapeshellcmd('tar pczf '.$mail_backup_dir.'/'.$mail_backup_file.' --directory '.$domain_dir.' '.$source_dir), $tmp_output, $retval);
152                             }
153                         }
154                         
f17718 155                         if($retval == 0){
6b166b 156                             chown($mail_backup_dir.'/'.$mail_backup_file, $backupusername);
DM 157                             chgrp($mail_backup_dir.'/'.$mail_backup_file, $backupgroup);
f17718 158                             chmod($mail_backup_dir.'/'.$mail_backup_file, 0640);
FS 159                             /* Insert mail backup record in database */
6b166b 160                             $filesize = filesize($mail_backup_dir.'/'.$mail_backup_file);
bc0ad0 161                             $sql = "INSERT INTO mail_backup (server_id, parent_domain_id, mailuser_id, backup_mode, tstamp, filename, filesize) VALUES (?, ?, ?, ?, ?, ?, ?)";
6b166b 162                             $app->db->query($sql, $conf['server_id'], $domain_rec['domain_id'], $rec['mailuser_id'], $backup_mode, time(), $mail_backup_file, $filesize);    
DM 163                             if($app->db->dbHost != $app->dbmaster->dbHost) $app->dbmaster->query($sql, $conf['server_id'], $domain_rec['domain_id'], $rec['mailuser_id'], $backup_mode, time(), $mail_backup_file, $filesize);
164                             unset($filesize);
f17718 165                         } else {
FS 166                             /* Backup failed - remove archive */
167                             if(is_file($mail_backup_dir.'/'.$mail_backup_file)) unlink($mail_backup_dir.'/'.$mail_backup_file);
f339eb 168                             // And remove backup-mdbox
D 169                             if ($rec['maildir_format'] == 'mdbox') {
170                                 if(file_exists($rec['maildir'].'/backup'))  exec("su -c 'rm -rf ".$rec['maildir']."/backup'");
171                             }
2e1453 172                             $app->log($mail_backup_file.' NOK:'.implode('',$tmp_output), LOGLEVEL_DEBUG);
f17718 173                         }
FS 174                         /* Remove old backups */
175                         $backup_copies = intval($rec['backup_copies']);
176                         $dir_handle = dir($mail_backup_dir);
177                         $files = array();
178                         while (false !== ($entry = $dir_handle->read())) {
e336d6 179                             if($entry != '.' && $entry != '..' && substr($entry,0,5+strlen($rec['mailuser_id'])) == 'mail'.$rec['mailuser_id'].'_' && is_file($mail_backup_dir.'/'.$entry)) {
f17718 180                                 $files[] = $entry;
FS 181                             }
182                         }
183                         $dir_handle->close();
184                         rsort($files);
185                         for ($n = $backup_copies; $n <= 10; $n++) {
186                             if(isset($files[$n]) && is_file($mail_backup_dir.'/'.$files[$n])) {
187                                 unlink($mail_backup_dir.'/'.$files[$n]);
bc0ad0 188                                 $sql = "DELETE FROM mail_backup WHERE server_id = ? AND parent_domain_id = ? AND filename = ?";
FS 189                                 $app->db->query($sql, $conf['server_id'], $domain_rec['domain_id'], $files[$n]);
190                                 if($app->db->dbHost != $app->dbmaster->dbHost) $app->dbmaster->query($sql, $conf['server_id'], $domain_rec['domain_id'], $files[$n]);
f17718 191                             }
FS 192                         }
193                         unset($files);
194                         unset($dir_handle);
195                     }
196                     /* Remove inactive backups */
66fa9b 197                     if($rec['backup_interval'] == 'none' || $rec['backup_interval'] == '') {
FS 198
199                         /* remove archives */
200                         $mail_backup_dir = realpath($backup_dir.'/mail'.$domain_rec['domain_id']);
f56297 201                         $mail_backup_file = 'mail'.$rec['mailuser_id'].'_';
66fa9b 202                         if(is_dir($mail_backup_dir)) {
FS 203                             $dir_handle = opendir($mail_backup_dir.'/');
204                             while ($file = readdir($dir_handle)) {
205                                 if(!is_dir($file)) {
ef5c45 206                                     if(substr($file,0,strlen($mail_backup_file)) == $mail_backup_file) {
FS 207                                         unlink ($mail_backup_dir.'/'.$file);
208                                     }
66fa9b 209                                 }
FS 210                             }
ef5c45 211                             if(count(glob($mail_backup_dir."/*", GLOB_NOSORT)) === 0) {
FS 212                                 rmdir($mail_backup_dir);
213                             }
66fa9b 214                         }
f17718 215                         /* remove backups from db */
bc0ad0 216                         $sql = "DELETE FROM mail_backup WHERE server_id = ? AND parent_domain_id = ? AND mailuser_id = ?";
FS 217                         $app->db->query($sql, $conf['server_id'], $domain_rec['domain_id'], $rec['mailuser_id']);
218                         if($app->db->dbHost != $app->dbmaster->dbHost) $app->dbmaster->query($sql, $conf['server_id'], $domain_rec['domain_id'], $rec['mailuser_id']);
66fa9b 219
f17718 220                     }
FS 221                 }
634132 222
D 223                 // remove non-existing backups from database
224                 $backups = $app->db->queryAllRecords("SELECT * FROM mail_backup WHERE server_id = ?", $conf['server_id']);
225                 if(is_array($backups) && !empty($backups)){
226                     foreach($backups as $backup){
2bc9e1 227                         $mail_backup_dir = $backup_dir.'/mail'.$backup['parent_domain_id'];
R 228                         if(!is_file($mail_backup_dir.'/'.$backup['filename'])){
634132 229                             $sql = "DELETE FROM mail_backup WHERE server_id = ? AND parent_domain_id = ? AND filename = ?";
D 230                             $app->db->query($sql, $conf['server_id'], $backup['parent_domain_id'], $backup['filename']);
231                             if($app->db->dbHost != $app->dbmaster->dbHost) $app->dbmaster->query($sql);
232                         }
233                     }
234                 }
52fe9e 235                 if( $server_config['backup_dir_is_mount'] == 'y' ) $app->system->umount_backup_dir($backup_dir);
66fa9b 236                 //* end run_backups
FS 237             }
f17718 238         }
FS 239
240         parent::onRunJob();
241     }
242
243     /* this function is optional if it contains no custom code */
244     public function onAfterRun() {
245         global $app;
246
247         parent::onAfterRun();
248     }
249
250 }
251
252 ?>