PluginProbe ʕ •ᴥ•ʔ
JetBackup – Backup, Restore & Migrate / trunk
JetBackup – Backup, Restore & Migrate vtrunk
3.1.22.3 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.8.1 1.4.9 1.5.0 1.5.1 1.5.1.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.6.0 1.6.10 1.6.11 1.6.12 1.6.13 1.6.15 1.6.5.1 1.6.8.8 1.6.9 1.6.9.1 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7.5 2.0.8.7 2.0.9.11 2.0.9.14 2.0.9.15 2.0.9.6 2.0.9.7 2.0.9.9 3.1.10.7 3.1.11.1 3.1.12.3 3.1.13.4 3.1.14.17 3.1.15.4 3.1.16.1 3.1.17.5 3.1.18.10 3.1.18.8 3.1.18.9 3.1.19.8 3.1.20.3 3.1.21.3 3.1.7.9 3.1.9.2 trunk 1.1.90 1.1.91 1.2.0 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2
backup / src / JetBackup / Export / Vendor / DirectAdmin.php
backup / src / JetBackup / Export / Vendor Last commit date
.htaccess 1 year ago CPanel.php 1 year ago DirectAdmin.php 1 year ago Vendor.php 1 year ago index.html 1 year ago web.config 1 year ago
DirectAdmin.php
439 lines
1 <?php
2
3 namespace JetBackup\Export\Vendor;
4
5 use JetBackup\Archive\Archive;
6 use JetBackup\Archive\Gzip;
7 use JetBackup\DirIterator\DirIterator;
8 use JetBackup\Entities\Util;
9 use JetBackup\Exception\ArchiveException;
10 use JetBackup\Exception\DirIteratorFileVanishedException;
11 use JetBackup\Exception\ExportException;
12 use JetBackup\Factory;
13 use JetBackup\JetBackup;
14 use JetBackup\Wordpress\Wordpress;
15
16 if (!defined( '__JETBACKUP__')) die('Direct access is not allowed');
17
18 class DirectAdmin extends Vendor {
19
20 private string $_destination;
21 private string $_target;
22
23 public function _build():string {
24
25 $this->_destination = $this->getDestination() . JetBackup::SEP . 'tmp';
26 $this->_target = $this->getDestination() . JetBackup::SEP . $this->getUsername() . Archive::ARCHIVE_EXT;
27
28 if(!file_exists($this->_destination)) mkdir($this->_destination, 0700);
29
30 /**
31 * Structure
32 * Filename: username.tar.gz
33 *
34 * |-- backup/
35 * | |-- username_database.conf
36 * | |-- username_database.sql
37 * | |-- apache_owned_files.list
38 * | |-- backup_options.list
39 * | |-- crontab.conf
40 * | |-- ticket.conf
41 * | |-- user.conf
42 * | |-- user.usage
43 * | +-- domain.com/
44 * | +-- domain.conf
45 * +-- domains/
46 * +-- domain.com/
47 * |-- public_html/
48 * +-- private_html -> ./public_html
49 */
50 $this->getTask()->func([$this, '_createSkeleton']);
51 $this->getTask()->func([$this, '_createHomedir']);
52 $this->getTask()->func([$this, '_createJetBackupPlugin']);
53 $this->getTask()->func([$this, '_createUserConf']);
54 $this->getTask()->func([$this, '_createUserUsage']);
55 $this->getTask()->func([$this, '_createTicketConf']);
56 $this->getTask()->func([$this, '_createCrontabConf']);
57 $this->getTask()->func([$this, '_createBackupOptionsList']);
58 $this->getTask()->func([$this, '_createApacheOwnedFiles']);
59 $this->getTask()->func([$this, '_createDomainConf']);
60 $this->getTask()->func([$this, '_createDatabaseConf' ]);
61 $this->getTask()->func([$this, '_createMySQLDump']);
62 $this->getTask()->func([$this, '_archive']);
63 $this->getTask()->func([$this, '_compress']);
64
65 return $this->_target . '.gz';
66 }
67
68 public function _archive():void {
69
70 $archive = new Archive($this->_target, false, Archive::OPT_SPARSE, 0, $this->getDestination());
71 $archive->setLogController($this->getLogController());
72
73 $this->getTask()->scan($this->_destination, function(DirIterator $scan, $data) use ($archive) {
74
75 if (!$data->total_size) throw new ArchiveException('Invalid total tree size');
76
77 $archive->setAppend(!($data->total_size == $data->current_pos));
78
79 try {
80 $fd = $archive->getFileFD();
81 $current_file = $scan->next($fd ? $fd->tell() : 0);
82 } catch (DirIteratorFileVanishedException $e) {
83 $this->getLogController()->logMessage('[ WARNING ] File Vanished : ' . $e->getMessage());
84 return;
85 }
86
87 if($scan->getSource() == $current_file->getName()) return;
88
89 $this->getLogController()->logMessage("[". ($data->total_size - $data->current_pos)."/$data->total_size] Archiving: {$current_file->getName()}");
90
91 try {
92
93 $file = substr($current_file->getName(), strlen($this->_destination)+1);
94 $archive->appendFileChunked($current_file, $file, function() use ($data) {
95
96 $progress = $this->getTask()->getQueueItem()->getProgress();
97 $progress->setMessage("Building DirectAdmin Backup Archive");
98 $progress->setSubMessage("");
99 $progress->setTotalSubItems($data->total_size);
100 $progress->setCurrentSubItem($data->total_size - $data->current_pos);
101 $this->getTask()->getQueueItem()->save();
102
103 $this->getTask()->checkExecutionTime(function() use ($data) {
104
105 $progress = $this->getTask()->getQueueItem()->getProgress();
106 $progress->setMessage("Waiting for next cron iteration");
107 $progress->setTotalSubItems($data->total_size);
108 $progress->setCurrentSubItem($data->total_size - $data->current_pos);
109 $this->getTask()->getQueueItem()->save();
110
111 });
112
113 return false;
114
115 }, Factory::getSettingsPerformance()->getReadChunkSizeBytes());
116 } catch(\Exception|ArchiveException $e) {
117 //this will throw exception if the file has been changed more than 3 times
118 $this->getLogController()->logError('[Export/DirectAdmin] Error while trying to archive: ' . $e->getMessage());
119 }
120 });
121
122 $archive->save();
123
124 }
125
126 public function _compress():void {
127 Gzip::compress(
128 $this->_target,
129 Gzip::DEFAULT_COMPRESS_CHUNK_SIZE,
130 Gzip::DEFAULT_COMPRESSION_LEVEL,
131 function() { $this->getTask()->checkExecutionTime(); }
132 );
133 }
134
135 public function _createMySQLDump():void {
136
137 $this->getLogController()->logMessage("Creating mysql dump file");
138
139 $this->getTask()->foreach($this->getDatabaseTables(), function($i, $table_path) {
140
141 $total_size = sizeof($this->getDatabaseTables());
142 $progress = $this->getTask()->getQueueItem()->getProgress();
143 $progress->setMessage("Building SQL dump");
144 $progress->setSubMessage("Adding " . basename($table_path));
145 $progress->setTotalSubItems($total_size);
146 $progress->setCurrentSubItem($i + 1); // Increment progress
147 $this->getTask()->getQueueItem()->save();
148
149 $this->getTask()->checkExecutionTime(function() use ($table_path, $total_size, $i) {
150
151 $progress = $this->getTask()->getQueueItem()->getProgress();
152 $progress->setSubMessage("Waiting for next cron iteration");
153 $progress->setTotalSubItems($total_size);
154 $progress->setCurrentSubItem($i + 1); // Maintain progress state
155 $this->getTask()->getQueueItem()->save();
156
157 });
158 $this->getLogController()->logDebug("[_createMySQLDump] $i/$total_size table_path: $table_path");
159 $this->getLogController()->logMessage("\t- Adding table " . basename($table_path) . " to dump file");
160 $dump_file = $this->_destination . JetBackup::SEP . 'backup' . JetBackup::SEP . $this->getDatabase() . '.sql';
161 $this->getTask()->fileMerge($table_path, $dump_file, 'combine_table_' . basename($table_path));
162 }, 'combine_tables');
163 }
164
165 public function _createDatabaseConf():void {
166
167 $this->getLogController()->logMessage("Creating database configuration file");
168
169 $conf_params = [
170 'alter_priv' => 'Y',
171 'alter_routine_priv' => 'Y',
172 'create_priv' => 'Y',
173 'create_routine_priv' => 'Y',
174 'create_tmp_table_priv' => 'Y',
175 'create_view_priv' => 'Y',
176 'delete_priv' => 'Y',
177 'drop_priv' => 'Y',
178 'event_priv' => 'Y',
179 'execute_priv' => 'Y',
180 'grant_priv' => 'N',
181 'index_priv' => 'Y',
182 'insert_priv' => 'Y',
183 'lock_tables_priv' => 'Y',
184 'passwd' => '*' . $this->getHashedPassword(),
185 'references_priv' => 'Y',
186 'select_priv' => 'Y',
187 'show_view_priv' => 'Y',
188 'trigger_priv' => 'Y',
189 'update_priv' => 'Y',
190 ];
191
192 $rows = [];
193 foreach ($conf_params as $key => $value) $rows[] = str_replace('_', '%5F', $key) . '=' . urlencode($value);
194 $conf = $this->getUsername() . "=" . implode("&", $rows) . "\n";
195 $conf .= $this->getDatabaseUser() . "=" . implode("&", $rows) . "\n";
196 $conf .= "accesshosts=0=localhost\n";
197 $conf .= "db_collation=CATALOG_NAME=def&DEFAULT_CHARACTER_SET_NAME=utf8&DEFAULT_COLLATION_NAME=utf8_general_ci&SCHEMA_COMMENT=&SCHEMA_NAME={$this->getDatabase()}&SQL_PATH=\n";
198
199 file_put_contents($this->_destination . JetBackup::SEP . 'backup' . JetBackup::SEP . $this->getDatabase() . '.conf', $conf);
200 }
201
202 public function _createHomedir():void {
203
204 $this->getLogController()->logMessage("Moving homedir to location");
205 $public_folder = JetBackup::SEP . 'domains' . JetBackup::SEP . $this->getDomainOnly() . JetBackup::SEP . 'public_html';
206 if($nested_folder = $this->getDomainSubFolder()) $public_folder .= JetBackup::SEP . $nested_folder;
207
208 if (!file_exists(dirname($this->_destination . $public_folder))) mkdir(dirname($this->_destination . $public_folder), 0755, true);
209 chmod($this->getHomedir(), 0755);
210 rename($this->getHomedir(), $this->_destination . $public_folder);
211
212 chdir($this->_destination);
213 if (!file_exists('public_html') && !is_link('public_html')) {
214 if (function_exists('symlink')) {
215 symlink('.' .$public_folder, 'public_html');
216 } else {
217 $this->getLogController()->logError("Failed to link $public_folder to 'public_html' (PHP function symlink disabled)" );
218 $this->getTask()->getQueueItem()->addError();
219 }
220 }
221
222 }
223
224 /**
225 * @return void
226 * @throws ExportException
227 *
228 * By default, JetBackup plugin is excluded during backup (to prevent issues during restore, not to 'cut our own branch')
229 * For an export package, we want to include JetBackup plugin as part of the package
230 *
231 */
232 public function _createJetBackupPlugin():void {
233
234 $this->getLogController()->logMessage("Adding JetBackup plugin to the package");
235 $public_folder = $this->_destination . JetBackup::SEP . 'domains' . JetBackup::SEP . $this->getDomainOnly() . JetBackup::SEP . 'public_html';
236 if($nested_folder = $this->getDomainSubFolder()) $public_folder .= JetBackup::SEP . $nested_folder;
237
238 $plugin_local_path = Factory::getWPHelper()->getWordPressHomedir() .
239 Wordpress::WP_CONTENT . JetBackup::SEP .
240 Wordpress::WP_PLUGINS . JetBackup::SEP .
241 JetBackup::PLUGIN_NAME;
242
243 $public_folder .= JetBackup::SEP . Wordpress::WP_CONTENT . JetBackup::SEP .
244 Wordpress::WP_PLUGINS . JetBackup::SEP .
245 JetBackup::PLUGIN_NAME;
246
247 if (!file_exists($plugin_local_path)) throw new ExportException("Plugin local path not found [$plugin_local_path]");
248 if (!file_exists($public_folder)) mkdir($public_folder, 0755, true);
249
250 try {
251 Util::cp($plugin_local_path, $public_folder, 0755, ['config.php']);
252 } catch (Exception $e) {
253 throw new ExportException($e->getMessage());
254 }
255
256 }
257
258 public function _createSkeleton():void {
259
260 $this->getLogController()->logMessage("Creating skeleton");
261
262 $skeleton = [
263 'backup' => 0700,
264 'backup' . JetBackup::SEP . $this->getDomainOnly() => 0755,
265 'domains' => 0711,
266 'domains' . JetBackup::SEP . $this->getDomainOnly() => 0711,
267 ];
268
269 foreach($skeleton as $directory => $mode) mkdir($this->_destination . JetBackup::SEP . $directory, $mode);
270 }
271
272 public function _createDomainConf():void {
273 $this->getLogController()->logMessage("Creating domain configuration file");
274 $target = $this->_destination . JetBackup::SEP . 'backup' . JetBackup::SEP . $this->getDomainOnly() . JetBackup::SEP . 'domain.conf';
275
276 $data = [
277 'UseCanonicalName' => 'OFF',
278 'active' => 'yes',
279 'bandwidth' => 'unlimited',
280 'cgi' => 'OFF',
281 'defaultdomain' => 'yes',
282 'domain' => $this->getDomainOnly(),
283 'ip' => '10.0.0.1',
284 'local_domain' => '1',
285 'open_basedir' => 'ON',
286 'php' => 'ON',
287 'private_html_is_link' => '1',
288 'quota' => 'unlimited',
289 'safemode' => 'OFF',
290 'ssl' => 'ON',
291 'suspended' => 'no',
292 'username' => $this->getUsername(),
293 ];
294
295 $output = [];
296 foreach ($data as $key => $value) $output[] = "$key=$value";
297 if(!file_exists(dirname($target))) mkdir(dirname($target), 0755, true);
298 file_put_contents($target, implode("\n", $output));
299 }
300
301 public function _createApacheOwnedFiles():void {
302 $this->getLogController()->logMessage("Creating apache owned files file");
303 touch($this->_destination . JetBackup::SEP . 'backup' . JetBackup::SEP . 'apache_owned_files.list');
304 }
305
306 public function _createBackupOptionsList():void {
307 $this->getLogController()->logMessage("Creating backup options file");
308
309 $data = [
310 'database',
311 'database_data',
312 'database_data_aware',
313 'domain',
314 'email_data_aware',
315 'trash_aware',
316 ];
317
318 file_put_contents($this->_destination . JetBackup::SEP . 'backup' . JetBackup::SEP . 'backup_options.list', implode("\n", $data));
319 }
320
321 public function _createCrontabConf():void {
322 $this->getLogController()->logMessage("Creating crontab");
323 file_put_contents($this->_destination . JetBackup::SEP . 'backup' . JetBackup::SEP . 'crontab.conf', 'MAILTO=' . PHP_EOL);
324 }
325
326 public function _createTicketConf():void {
327
328 $this->getLogController()->logMessage("Creating ticket configuration file");
329
330 $data = [
331 'ON' => 'yes',
332 'active' => 'no',
333 'email' => $this->getEmailAddress(),
334 'html' => '',
335 'new' => 1,
336 'newticket' => 0,
337 ];
338
339 $output = [];
340 foreach ($data as $key => $value) $output[] = "$key=$value";
341 file_put_contents($this->_destination . JetBackup::SEP . 'backup' . JetBackup::SEP . 'ticket.conf', implode("\n", $output));
342 }
343
344 public function _createUserUsage():void {
345
346 $this->getLogController()->logMessage("Creating user usage file");
347
348 $data = [
349 'bandwidth' => 0.0,
350 'db_quota' => 0,
351 'domainptr' => 0,
352 'email_deliveries' => 0,
353 'email_deliveries_incoming' => 0,
354 'email_deliveries_outgoing' => 0,
355 'email_quota' => 36,
356 'ftp' => 0,
357 'inode' => 23,
358 'mysql' => 1,
359 'nemailf' => 0,
360 'nemailml' => 0,
361 'nemailr' => 0,
362 'nemails' => 0,
363 'nsubdomains' => 0,
364 'other_quota' => 0,
365 'quota' => 0.1328,
366 'quota_without_system' => 0.0000,
367 'vdomains' => 1,
368 ];
369
370 $output = [];
371 foreach ($data as $key => $value) $output[] = "$key=$value";
372 file_put_contents($this->_destination . JetBackup::SEP . 'backup' . JetBackup::SEP . 'user.usage', implode("\n", $output));
373 }
374
375 public function _createUserConf():void {
376
377 $this->getLogController()->logMessage("Creating user configuration file");
378
379 $data = [
380 'account' => 'ON',
381 'additional_bandwidth' => 0,
382 'aftp' => 'OFF',
383 'api_with_password' => 'yes',
384 'bandwidth' => 'unlimited',
385 'catchall' => 'OFF',
386 'cgi' => 'OFF',
387 'clamav' => 'OFF',
388 'creator' => 'admin',
389 'cron' => 'ON',
390 'date_created' => date('D M j Y'),
391 'demo' => 'no',
392 'dnscontrol' => 'OFF',
393 'docsroot' => './data/skins/evolution',
394 'skin' => 'evolution',
395 'domain' => $this->getDomainOnly(),
396 'domainptr' => 'unlimited',
397 'email' => $this->getEmailAddress(),
398 'ftp' => 'unlimited',
399 'git' => 'OFF',
400 'inode' => 'unlimited',
401 'jail' => 'OFF',
402 'language' => 'en',
403 'login_keys' => 'OFF',
404 'mysql' => 'unlimited',
405 'name' => $this->getUsername(),
406 'nemailf' => 'unlimited',
407 'nemailml' => 'unlimited',
408 'nemailr' => 'unlimited',
409 'nemails' => 'unlimited',
410 'notify_on_all_question_failures' => 'yes',
411 'notify_on_all_twostep_auth_failures' => 'yes',
412 'ns1' => 'ns1.' . $this->getUsername() . '.da.direct',
413 'ns2' => 'ns2.' . $this->getUsername() . '.da.direct',
414 'nsubdomains' => 'unlimited',
415 'package' => 'default',
416 'php' => 'ON',
417 'quota' => 'unlimited',
418 'redis' => 'OFF',
419 'security_questions' => 'no',
420 'spam' => 'OFF',
421 'ssh' => 'OFF',
422 'ssl' => 'ON',
423 'suspend_at_limit' => 'OFF',
424 'suspended' => 'no',
425 'sysinfo' => 'OFF',
426 'twostep_auth' => 'no',
427 'username' => $this->getUsername(),
428 'usertype' => 'user',
429 'vdomains' => 'unlimited',
430 'wordpress' => 'ON',
431 'zoom' => 100,
432 'ip' => '10.0.0.1',
433 ];
434
435 $output = [];
436 foreach ($data as $key => $value) $output[] = "$key=$value";
437 file_put_contents($this->_destination . JetBackup::SEP . 'backup' . JetBackup::SEP . 'user.conf', implode("\n", $output));
438 }
439 }