PluginProbe ʕ •ᴥ•ʔ
All-in-One WP Migration and Backup / 7.99
All-in-One WP Migration and Backup v7.99
trunk 7.100 7.101 7.102 7.103 7.104 7.105 7.97 7.98 7.99
all-in-one-wp-migration / functions.php
all-in-one-wp-migration Last commit date
lib 8 months ago LICENSE 12 years ago all-in-one-wp-migration.php 8 months ago changelog.txt 2 years ago constants.php 8 months ago deprecated.php 1 year ago exceptions.php 9 months ago functions.php 8 months ago loader.php 9 months ago readme.txt 8 months ago uninstall.php 11 months ago
functions.php
2512 lines
1 <?php
2 /**
3 * Copyright (C) 2014-2025 ServMask Inc.
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * Attribution: This code is part of the All-in-One WP Migration plugin, developed by
19 *
20 * ███████╗███████╗██████╗ ██╗ ██╗███╗ ███╗ █████╗ ███████╗██╗ ██╗
21 * ██╔════╝██╔════╝██╔══██╗██║ ██║████╗ ████║██╔══██╗██╔════╝██║ ██╔╝
22 * ███████╗█████╗ ██████╔╝██║ ██║██╔████╔██║███████║███████╗█████╔╝
23 * ╚════██║██╔══╝ ██╔══██╗╚██╗ ██╔╝██║╚██╔╝██║██╔══██║╚════██║██╔═██╗
24 * ███████║███████╗██║ ██║ ╚████╔╝ ██║ ╚═╝ ██║██║ ██║███████║██║ ██╗
25 * ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝
26 */
27
28 if ( ! defined( 'ABSPATH' ) ) {
29 die( 'Kangaroos cannot jump here' );
30 }
31
32 /**
33 * Get storage absolute path
34 *
35 * @param array $params Request parameters
36 * @return string
37 */
38 function ai1wm_storage_path( $params ) {
39 if ( empty( $params['storage'] ) ) {
40 throw new Ai1wm_Storage_Exception(
41 wp_kses(
42 __( 'Could not locate the storage path. The process cannot continue. <a href="https://help.servmask.com/knowledgebase/invalid-storage-path/" target="_blank">Technical details</a>', 'all-in-one-wp-migration' ),
43 ai1wm_allowed_html_tags()
44 )
45 );
46 }
47
48 // Validate storage path
49 if ( ai1wm_validate_file( $params['storage'] ) !== 0 ) {
50 throw new Ai1wm_Storage_Exception(
51 wp_kses(
52 __( 'Your storage directory name contains invalid characters: < > : " | ? * \0. It must not include these characters. The process cannot continue. <a href="https://help.servmask.com/knowledgebase/invalid-storage-name/" target="_blank">Technical details</a>', 'all-in-one-wp-migration' ),
53 ai1wm_allowed_html_tags()
54 )
55 );
56 }
57
58 // Get storage path
59 $storage = AI1WM_STORAGE_PATH . DIRECTORY_SEPARATOR . basename( $params['storage'] );
60 if ( ! is_dir( $storage ) ) {
61 mkdir( $storage, 0777, true );
62 }
63
64 return $storage;
65 }
66
67 /**
68 * Get backup absolute path
69 *
70 * @param array $params Request parameters
71 * @return string
72 */
73 function ai1wm_backup_path( $params ) {
74 if ( empty( $params['archive'] ) ) {
75 throw new Ai1wm_Archive_Exception(
76 wp_kses(
77 __( 'Could not locate the archive path. The process cannot continue. <a href="https://help.servmask.com/knowledgebase/invalid-archive-path/" target="_blank">Technical details</a>', 'all-in-one-wp-migration' ),
78 ai1wm_allowed_html_tags()
79 )
80 );
81 }
82
83 // Validate archive path
84 if ( ai1wm_validate_file( $params['archive'] ) !== 0 ) {
85 throw new Ai1wm_Archive_Exception(
86 wp_kses(
87 __( 'Your archive file name contains invalid characters: < > : " | ? * \0. It must not include these characters. The process cannot continue. <a href="https://help.servmask.com/knowledgebase/invalid-archive-name/" target="_blank">Technical details</a>', 'all-in-one-wp-migration' ),
88 ai1wm_allowed_html_tags()
89 )
90 );
91 }
92
93 // Validate file extension
94 if ( ! ai1wm_is_filename_supported( $params['archive'] ) ) {
95 throw new Ai1wm_Archive_Exception(
96 wp_kses(
97 __( 'Invalid archive file type. Only .wpress files are allowed. The process cannot continue. <a href="https://help.servmask.com/knowledgebase/invalid-file-type/" target="_blank">Technical details</a>', 'all-in-one-wp-migration' ),
98 ai1wm_allowed_html_tags()
99 )
100 );
101 }
102
103 return AI1WM_BACKUPS_PATH . DIRECTORY_SEPARATOR . $params['archive'];
104 }
105
106 /**
107 * Validates a file name and path against an allowed set of rules
108 *
109 * @param string $file File path
110 * @param array $allowed_files Array of allowed files
111 * @return integer
112 */
113 function ai1wm_validate_file( $file, $allowed_files = array() ) {
114 $file = str_replace( '\\', '/', $file );
115
116 // Validates special characters that are illegal in filenames on certain
117 // operating systems and special characters requiring special escaping
118 // to manipulate at the command line
119 $invalid_chars = array( '<', '>', ':', '"', '|', '?', '*', chr( 0 ) );
120 foreach ( $invalid_chars as $char ) {
121 if ( strpos( $file, $char ) !== false ) {
122 return 1;
123 }
124 }
125
126 return validate_file( $file, $allowed_files );
127 }
128
129 /**
130 * Get archive absolute path
131 *
132 * @param array $params Request parameters
133 * @return string
134 */
135 function ai1wm_archive_path( $params ) {
136 if ( empty( $params['archive'] ) ) {
137 throw new Ai1wm_Archive_Exception(
138 wp_kses(
139 __( 'Could not locate the archive path. The process cannot continue. <a href="https://help.servmask.com/knowledgebase/invalid-archive-path/" target="_blank">Technical details</a>', 'all-in-one-wp-migration' ),
140 ai1wm_allowed_html_tags()
141 )
142 );
143 }
144
145 // Validate archive path
146 if ( ai1wm_validate_file( $params['archive'] ) !== 0 ) {
147 throw new Ai1wm_Archive_Exception(
148 wp_kses(
149 __( 'Your archive file name contains invalid characters: < > : " | ? * \0. It must not include these characters. The process cannot continue. <a href="https://help.servmask.com/knowledgebase/invalid-archive-name/" target="_blank">Technical details</a>', 'all-in-one-wp-migration' ),
150 ai1wm_allowed_html_tags()
151 )
152 );
153 }
154
155 // Validate file extension
156 if ( ! ai1wm_is_filename_supported( $params['archive'] ) ) {
157 throw new Ai1wm_Archive_Exception(
158 wp_kses(
159 __( 'Invalid archive file type. Only .wpress files are allowed. The process cannot continue. <a href="https://help.servmask.com/knowledgebase/invalid-file-type/" target="_blank">Technical details</a>', 'all-in-one-wp-migration' ),
160 ai1wm_allowed_html_tags()
161 )
162 );
163 }
164
165 // Get archive path
166 if ( empty( $params['ai1wm_manual_restore'] ) ) {
167 return ai1wm_storage_path( $params ) . DIRECTORY_SEPARATOR . $params['archive'];
168 }
169
170 return ai1wm_backup_path( $params );
171 }
172
173 /**
174 * Get multipart.list absolute path
175 *
176 * @param array $params Request parameters
177 * @return string
178 */
179 function ai1wm_multipart_path( $params ) {
180 return ai1wm_storage_path( $params ) . DIRECTORY_SEPARATOR . AI1WM_MULTIPART_NAME;
181 }
182
183 /**
184 * Get content.list absolute path
185 *
186 * @param array $params Request parameters
187 * @return string
188 */
189 function ai1wm_content_list_path( $params ) {
190 return ai1wm_storage_path( $params ) . DIRECTORY_SEPARATOR . AI1WM_CONTENT_LIST_NAME;
191 }
192
193 /**
194 * Get media.list absolute path
195 *
196 * @param array $params Request parameters
197 * @return string
198 */
199 function ai1wm_media_list_path( $params ) {
200 return ai1wm_storage_path( $params ) . DIRECTORY_SEPARATOR . AI1WM_MEDIA_LIST_NAME;
201 }
202
203 /**
204 * Get plugins.list absolute path
205 *
206 * @param array $params Request parameters
207 * @return string
208 */
209 function ai1wm_plugins_list_path( $params ) {
210 return ai1wm_storage_path( $params ) . DIRECTORY_SEPARATOR . AI1WM_PLUGINS_LIST_NAME;
211 }
212
213 /**
214 * Get themes.list absolute path
215 *
216 * @param array $params Request parameters
217 * @return string
218 */
219 function ai1wm_themes_list_path( $params ) {
220 return ai1wm_storage_path( $params ) . DIRECTORY_SEPARATOR . AI1WM_THEMES_LIST_NAME;
221 }
222
223 /**
224 * Get tables.list absolute path
225 *
226 * @param array $params Request parameters
227 * @return string
228 */
229 function ai1wm_tables_list_path( $params ) {
230 return ai1wm_storage_path( $params ) . DIRECTORY_SEPARATOR . AI1WM_TABLES_LIST_NAME;
231 }
232
233 /**
234 * Get incremental.content.list absolute path
235 *
236 * @param array $params Request parameters
237 * @return string
238 */
239 function ai1wm_incremental_content_list_path( $params ) {
240 return ai1wm_storage_path( $params ) . DIRECTORY_SEPARATOR . AI1WM_INCREMENTAL_CONTENT_LIST_NAME;
241 }
242
243 /**
244 * Get incremental.media.list absolute path
245 *
246 * @param array $params Request parameters
247 * @return string
248 */
249 function ai1wm_incremental_media_list_path( $params ) {
250 return ai1wm_storage_path( $params ) . DIRECTORY_SEPARATOR . AI1WM_INCREMENTAL_MEDIA_LIST_NAME;
251 }
252
253 /**
254 * Get incremental.plugins.list absolute path
255 *
256 * @param array $params Request parameters
257 * @return string
258 */
259 function ai1wm_incremental_plugins_list_path( $params ) {
260 return ai1wm_storage_path( $params ) . DIRECTORY_SEPARATOR . AI1WM_INCREMENTAL_PLUGINS_LIST_NAME;
261 }
262
263 /**
264 * Get incremental.themes.list absolute path
265 *
266 * @param array $params Request parameters
267 * @return string
268 */
269 function ai1wm_incremental_themes_list_path( $params ) {
270 return ai1wm_storage_path( $params ) . DIRECTORY_SEPARATOR . AI1WM_INCREMENTAL_THEMES_LIST_NAME;
271 }
272
273 /**
274 * Get incremental.backups.list absolute path
275 *
276 * @param array $params Request parameters
277 * @return string
278 */
279 function ai1wm_incremental_backups_list_path( $params ) {
280 return ai1wm_storage_path( $params ) . DIRECTORY_SEPARATOR . AI1WM_INCREMENTAL_BACKUPS_LIST_NAME;
281 }
282
283 /**
284 * Get package.json absolute path
285 *
286 * @param array $params Request parameters
287 * @return string
288 */
289 function ai1wm_package_path( $params ) {
290 return ai1wm_storage_path( $params ) . DIRECTORY_SEPARATOR . AI1WM_PACKAGE_NAME;
291 }
292
293 /**
294 * Get multisite.json absolute path
295 *
296 * @param array $params Request parameters
297 * @return string
298 */
299 function ai1wm_multisite_path( $params ) {
300 return ai1wm_storage_path( $params ) . DIRECTORY_SEPARATOR . AI1WM_MULTISITE_NAME;
301 }
302
303 /**
304 * Get blogs.json absolute path
305 *
306 * @param array $params Request parameters
307 * @return string
308 */
309 function ai1wm_blogs_path( $params ) {
310 return ai1wm_storage_path( $params ) . DIRECTORY_SEPARATOR . AI1WM_BLOGS_NAME;
311 }
312
313 /**
314 * Get settings.json absolute path
315 *
316 * @param array $params Request parameters
317 * @return string
318 */
319 function ai1wm_settings_path( $params ) {
320 return ai1wm_storage_path( $params ) . DIRECTORY_SEPARATOR . AI1WM_SETTINGS_NAME;
321 }
322
323 /**
324 * Get database.sql absolute path
325 *
326 * @param array $params Request parameters
327 * @return string
328 */
329 function ai1wm_database_path( $params ) {
330 return ai1wm_storage_path( $params ) . DIRECTORY_SEPARATOR . AI1WM_DATABASE_NAME;
331 }
332
333 /**
334 * Get cookies.txt absolute path
335 *
336 * @param array $params Request parameters
337 * @return string
338 */
339 function ai1wm_cookies_path( $params ) {
340 return ai1wm_storage_path( $params ) . DIRECTORY_SEPARATOR . AI1WM_COOKIES_NAME;
341 }
342
343 /**
344 * Get error log absolute path
345 *
346 * @param string $nonce Log nonce
347 * @return string
348 */
349 function ai1wm_error_path( $nonce ) {
350 return AI1WM_STORAGE_PATH . DIRECTORY_SEPARATOR . sprintf( AI1WM_ERROR_NAME, $nonce );
351 }
352
353 /**
354 * Get archive name
355 *
356 * @param array $params Request parameters
357 * @return string
358 */
359 function ai1wm_archive_name( $params ) {
360 return basename( $params['archive'] );
361 }
362
363 /**
364 * Get backup URL address
365 *
366 * @param array $params Request parameters
367 * @return string
368 */
369 function ai1wm_backup_url( $params ) {
370 static $backups_base_url = '';
371 if ( empty( $backups_base_url ) ) {
372 if ( Ai1wm_Backups::are_in_wp_content_folder() ) {
373 $backups_base_url = str_replace( untrailingslashit( WP_CONTENT_DIR ), '', AI1WM_BACKUPS_PATH );
374 $backups_base_url = content_url(
375 ai1wm_replace_directory_separator_with_forward_slash( $backups_base_url )
376 );
377 } else {
378 $backups_base_url = str_replace( untrailingslashit( ABSPATH ), '', AI1WM_BACKUPS_PATH );
379 $backups_base_url = site_url(
380 ai1wm_replace_directory_separator_with_forward_slash( $backups_base_url )
381 );
382 }
383 }
384
385 return $backups_base_url . '/' . ai1wm_replace_directory_separator_with_forward_slash( $params['archive'] );
386 }
387
388 /**
389 * Get archive size in bytes
390 *
391 * @param array $params Request parameters
392 * @return integer
393 */
394 function ai1wm_archive_bytes( $params ) {
395 return filesize( ai1wm_archive_path( $params ) );
396 }
397
398 /**
399 * Get archive modified time in seconds
400 *
401 * @param array $params Request parameters
402 * @return integer
403 */
404 function ai1wm_archive_mtime( $params ) {
405 return filemtime( ai1wm_archive_path( $params ) );
406 }
407
408 /**
409 * Get backup size in bytes
410 *
411 * @param array $params Request parameters
412 * @return integer
413 */
414 function ai1wm_backup_bytes( $params ) {
415 return filesize( ai1wm_backup_path( $params ) );
416 }
417
418 /**
419 * Get database size in bytes
420 *
421 * @param array $params Request parameters
422 * @return integer
423 */
424 function ai1wm_database_bytes( $params ) {
425 return filesize( ai1wm_database_path( $params ) );
426 }
427
428 /**
429 * Get package size in bytes
430 *
431 * @param array $params Request parameters
432 * @return integer
433 */
434 function ai1wm_package_bytes( $params ) {
435 return filesize( ai1wm_package_path( $params ) );
436 }
437
438 /**
439 * Get multisite size in bytes
440 *
441 * @param array $params Request parameters
442 * @return integer
443 */
444 function ai1wm_multisite_bytes( $params ) {
445 return filesize( ai1wm_multisite_path( $params ) );
446 }
447
448 /**
449 * Get archive size as text
450 *
451 * @param array $params Request parameters
452 * @return string
453 */
454 function ai1wm_archive_size( $params ) {
455 return ai1wm_size_format( filesize( ai1wm_archive_path( $params ) ) );
456 }
457
458 /**
459 * Get backup size as text
460 *
461 * @param array $params Request parameters
462 * @return string
463 */
464 function ai1wm_backup_size( $params ) {
465 return ai1wm_size_format( filesize( ai1wm_backup_path( $params ) ) );
466 }
467
468 /**
469 * Parse file size
470 *
471 * @param string $size File size
472 * @param string $default Default size
473 * @return string
474 */
475 function ai1wm_parse_size( $size, $default = null ) {
476 $suffixes = array(
477 '' => 1,
478 'k' => 1000,
479 'm' => 1000000,
480 'g' => 1000000000,
481 );
482
483 // Parse size format
484 if ( preg_match( '/([0-9]+)\s*(k|m|g)?(b?(ytes?)?)/i', $size, $matches ) ) {
485 return $matches[1] * $suffixes[ strtolower( $matches[2] ) ];
486 }
487
488 return $default;
489 }
490
491 /**
492 * Format file size into human-readable string
493 *
494 * Fixes the WP size_format bug: size_format( '0' ) => false
495 *
496 * @param int|string $bytes Number of bytes. Note max integer size for integers.
497 * @param int $decimals Optional. Precision of number of decimal places. Default 0.
498 * @return string|false False on failure. Number string on success.
499 */
500 function ai1wm_size_format( $bytes, $decimals = 0 ) {
501 if ( strval( $bytes ) === '0' ) {
502 return size_format( 0, $decimals );
503 }
504
505 return size_format( $bytes, $decimals );
506 }
507
508 /**
509 * Get current site name
510 *
511 * @param integer $blog_id Blog ID
512 * @return string
513 */
514 function ai1wm_site_name( $blog_id = null ) {
515 return parse_url( get_site_url( $blog_id ), PHP_URL_HOST );
516 }
517
518 /**
519 * Get archive file name
520 *
521 * @param integer $blog_id Blog ID
522 * @return string
523 */
524 function ai1wm_archive_file( $blog_id = null ) {
525 $name = array();
526
527 // Add domain
528 if ( defined( 'AI1WM_KEEP_DOMAIN_NAME' ) ) {
529 $name[] = parse_url( get_site_url( $blog_id ), PHP_URL_HOST );
530 } elseif ( ( $domain = explode( '.', parse_url( get_site_url( $blog_id ), PHP_URL_HOST ) ) ) ) {
531 foreach ( $domain as $subdomain ) {
532 if ( ( $subdomain = strtolower( $subdomain ) ) ) {
533 $name[] = $subdomain;
534 }
535 }
536 }
537
538 // Add path
539 if ( ( $path = parse_url( get_site_url( $blog_id ), PHP_URL_PATH ) ) ) {
540 foreach ( explode( '/', $path ) as $directory ) {
541 if ( ( $directory = strtolower( preg_replace( '/[^A-Za-z0-9\-]/', '', $directory ) ) ) ) {
542 $name[] = $directory;
543 }
544 }
545 }
546
547 // Add year, month and day
548 $name[] = current_time( 'Ymd' );
549
550 // Add hours, minutes and seconds
551 $name[] = current_time( 'His' );
552
553 // Add unique identifier
554 $name[] = ai1wm_generate_random_string( 12, false );
555
556 return sprintf( '%s.wpress', strtolower( implode( '-', $name ) ) );
557 }
558
559 /**
560 * Get archive folder name
561 *
562 * @param integer $blog_id Blog ID
563 * @return string
564 */
565 function ai1wm_archive_folder( $blog_id = null ) {
566 $name = array();
567
568 // Add domain
569 if ( defined( 'AI1WM_KEEP_DOMAIN_NAME' ) ) {
570 $name[] = parse_url( get_site_url( $blog_id ), PHP_URL_HOST );
571 } elseif ( ( $domain = explode( '.', parse_url( get_site_url( $blog_id ), PHP_URL_HOST ) ) ) ) {
572 foreach ( $domain as $subdomain ) {
573 if ( ( $subdomain = strtolower( $subdomain ) ) ) {
574 $name[] = $subdomain;
575 }
576 }
577 }
578
579 // Add path
580 if ( ( $path = parse_url( get_site_url( $blog_id ), PHP_URL_PATH ) ) ) {
581 foreach ( explode( '/', $path ) as $directory ) {
582 if ( ( $directory = strtolower( preg_replace( '/[^A-Za-z0-9\-]/', '', $directory ) ) ) ) {
583 $name[] = $directory;
584 }
585 }
586 }
587
588 return strtolower( implode( '-', $name ) );
589 }
590
591 /**
592 * Get archive bucket name
593 *
594 * @param integer $blog_id Blog ID
595 * @return string
596 */
597 function ai1wm_archive_bucket( $blog_id = null ) {
598 $name = array();
599
600 // Add domain
601 if ( ( $domain = explode( '.', parse_url( get_site_url( $blog_id ), PHP_URL_HOST ) ) ) ) {
602 foreach ( $domain as $subdomain ) {
603 if ( ( $subdomain = strtolower( $subdomain ) ) ) {
604 $name[] = $subdomain;
605 }
606 }
607 }
608
609 // Add path
610 if ( ( $path = parse_url( get_site_url( $blog_id ), PHP_URL_PATH ) ) ) {
611 foreach ( explode( '/', $path ) as $directory ) {
612 if ( ( $directory = strtolower( preg_replace( '/[^A-Za-z0-9\-]/', '', $directory ) ) ) ) {
613 $name[] = $directory;
614 }
615 }
616 }
617
618 return strtolower( implode( '-', $name ) );
619 }
620
621 /**
622 * Get archive vault name
623 *
624 * @param integer $blog_id Blog ID
625 * @return string
626 */
627 function ai1wm_archive_vault( $blog_id = null ) {
628 $name = array();
629
630 // Add domain
631 if ( ( $domain = explode( '.', parse_url( get_site_url( $blog_id ), PHP_URL_HOST ) ) ) ) {
632 foreach ( $domain as $subdomain ) {
633 if ( ( $subdomain = strtolower( $subdomain ) ) ) {
634 $name[] = $subdomain;
635 }
636 }
637 }
638
639 // Add path
640 if ( ( $path = parse_url( get_site_url( $blog_id ), PHP_URL_PATH ) ) ) {
641 foreach ( explode( '/', $path ) as $directory ) {
642 if ( ( $directory = strtolower( preg_replace( '/[^A-Za-z0-9\-]/', '', $directory ) ) ) ) {
643 $name[] = $directory;
644 }
645 }
646 }
647
648 return strtolower( implode( '-', $name ) );
649 }
650
651 /**
652 * Get archive project name
653 *
654 * @param integer $blog_id Blog ID
655 * @return string
656 */
657 function ai1wm_archive_project( $blog_id = null ) {
658 $name = array();
659
660 // Add domain
661 if ( ( $domain = explode( '.', parse_url( get_site_url( $blog_id ), PHP_URL_HOST ) ) ) ) {
662 foreach ( $domain as $subdomain ) {
663 if ( ( $subdomain = strtolower( $subdomain ) ) ) {
664 $name[] = $subdomain;
665 }
666 }
667 }
668
669 // Add path
670 if ( ( $path = parse_url( get_site_url( $blog_id ), PHP_URL_PATH ) ) ) {
671 foreach ( explode( '/', $path ) as $directory ) {
672 if ( ( $directory = strtolower( preg_replace( '/[^A-Za-z0-9\-]/', '', $directory ) ) ) ) {
673 $name[] = $directory;
674 }
675 }
676 }
677
678 return strtolower( implode( '-', $name ) );
679 }
680
681 /**
682 * Get archive share name
683 *
684 * @param integer $blog_id Blog ID
685 * @return string
686 */
687 function ai1wm_archive_share( $blog_id = null ) {
688 $name = array();
689
690 // Add domain
691 if ( ( $domain = explode( '.', parse_url( get_site_url( $blog_id ), PHP_URL_HOST ) ) ) ) {
692 foreach ( $domain as $subdomain ) {
693 if ( ( $subdomain = strtolower( $subdomain ) ) ) {
694 $name[] = $subdomain;
695 }
696 }
697 }
698
699 // Add path
700 if ( ( $path = parse_url( get_site_url( $blog_id ), PHP_URL_PATH ) ) ) {
701 foreach ( explode( '/', $path ) as $directory ) {
702 if ( ( $directory = strtolower( preg_replace( '/[^A-Za-z0-9\-]/', '', $directory ) ) ) ) {
703 $name[] = $directory;
704 }
705 }
706 }
707
708 return strtolower( implode( '-', $name ) );
709 }
710
711 /**
712 * Generate random string
713 *
714 * @param integer $length String length
715 * @param boolean $mixed_chars Whether to include mixed characters
716 * @param boolean $special_chars Whether to include special characters
717 * @param boolean $extra_special_chars Whether to include extra special characters
718 * @return string
719 */
720 function ai1wm_generate_random_string( $length = 12, $mixed_chars = true, $special_chars = false, $extra_special_chars = false ) {
721 $chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
722 if ( $mixed_chars ) {
723 $chars .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
724 }
725
726 if ( $special_chars ) {
727 $chars .= '!@#$%^&*()';
728 }
729
730 if ( $extra_special_chars ) {
731 $chars .= '-_ []{}<>~`+=,.;:/?|';
732 }
733
734 $str = '';
735 for ( $i = 0; $i < $length; $i++ ) {
736 $str .= substr( $chars, wp_rand( 0, strlen( $chars ) - 1 ), 1 );
737 }
738
739 return $str;
740 }
741
742 /**
743 * Get storage folder name
744 *
745 * @return string
746 */
747 function ai1wm_storage_folder() {
748 return uniqid();
749 }
750
751 /**
752 * Check whether blog ID is main site
753 *
754 * @param integer $blog_id Blog ID
755 * @return boolean
756 */
757 function ai1wm_is_mainsite( $blog_id = null ) {
758 return $blog_id === null || $blog_id === 0 || $blog_id === 1;
759 }
760
761 /**
762 * Get files absolute path by blog ID
763 *
764 * @param integer $blog_id Blog ID
765 * @return string
766 */
767 function ai1wm_blog_files_abspath( $blog_id = null ) {
768 if ( ai1wm_is_mainsite( $blog_id ) ) {
769 return ai1wm_get_uploads_dir();
770 }
771
772 return WP_CONTENT_DIR . DIRECTORY_SEPARATOR . 'blogs.dir' . DIRECTORY_SEPARATOR . $blog_id . DIRECTORY_SEPARATOR . 'files';
773 }
774
775 /**
776 * Get blogs.dir absolute path by blog ID
777 *
778 * @param integer $blog_id Blog ID
779 * @return string
780 */
781 function ai1wm_blog_blogsdir_abspath( $blog_id = null ) {
782 if ( ai1wm_is_mainsite( $blog_id ) ) {
783 return ai1wm_get_uploads_dir();
784 }
785
786 return WP_CONTENT_DIR . DIRECTORY_SEPARATOR . 'blogs.dir' . DIRECTORY_SEPARATOR . $blog_id;
787 }
788
789 /**
790 * Get sites absolute path by blog ID
791 *
792 * @param integer $blog_id Blog ID
793 * @return string
794 */
795 function ai1wm_blog_sites_abspath( $blog_id = null ) {
796 if ( ai1wm_is_mainsite( $blog_id ) ) {
797 return ai1wm_get_uploads_dir();
798 }
799
800 return ai1wm_get_uploads_dir() . DIRECTORY_SEPARATOR . 'sites' . DIRECTORY_SEPARATOR . $blog_id;
801 }
802
803 /**
804 * Get files relative path by blog ID
805 *
806 * @param integer $blog_id Blog ID
807 * @return string
808 */
809 function ai1wm_blog_files_relpath( $blog_id = null ) {
810 if ( ai1wm_is_mainsite( $blog_id ) ) {
811 return 'uploads';
812 }
813
814 return 'blogs.dir' . DIRECTORY_SEPARATOR . $blog_id . DIRECTORY_SEPARATOR . 'files';
815 }
816
817 /**
818 * Get blogs.dir relative path by blog ID
819 *
820 * @param integer $blog_id Blog ID
821 * @return string
822 */
823 function ai1wm_blog_blogsdir_relpath( $blog_id = null ) {
824 if ( ai1wm_is_mainsite( $blog_id ) ) {
825 return 'uploads';
826 }
827
828 return 'blogs.dir' . DIRECTORY_SEPARATOR . $blog_id;
829 }
830
831 /**
832 * Get sites relative path by blog ID
833 *
834 * @param integer $blog_id Blog ID
835 * @return string
836 */
837 function ai1wm_blog_sites_relpath( $blog_id = null ) {
838 if ( ai1wm_is_mainsite( $blog_id ) ) {
839 return 'uploads';
840 }
841
842 return 'uploads' . DIRECTORY_SEPARATOR . 'sites' . DIRECTORY_SEPARATOR . $blog_id;
843 }
844
845 /**
846 * Get files URL by blog ID
847 *
848 * @param integer $blog_id Blog ID
849 * @return string
850 */
851 function ai1wm_blog_files_url( $blog_id = null ) {
852 if ( ai1wm_is_mainsite( $blog_id ) ) {
853 return '/wp-content/uploads/';
854 }
855
856 return sprintf( '/wp-content/blogs.dir/%d/files/', $blog_id );
857 }
858
859 /**
860 * Get blogs.dir URL by blog ID
861 *
862 * @param integer $blog_id Blog ID
863 * @return string
864 */
865 function ai1wm_blog_blogsdir_url( $blog_id = null ) {
866 if ( ai1wm_is_mainsite( $blog_id ) ) {
867 return '/wp-content/uploads/';
868 }
869
870 return sprintf( '/wp-content/blogs.dir/%d/', $blog_id );
871 }
872
873 /**
874 * Get sites URL by blog ID
875 *
876 * @param integer $blog_id Blog ID
877 * @return string
878 */
879 function ai1wm_blog_sites_url( $blog_id = null ) {
880 if ( ai1wm_is_mainsite( $blog_id ) ) {
881 return '/wp-content/uploads/';
882 }
883
884 return sprintf( '/wp-content/uploads/sites/%d/', $blog_id );
885 }
886
887 /**
888 * Get uploads URL by blog ID
889 *
890 * @param integer $blog_id Blog ID
891 * @return string
892 */
893 function ai1wm_blog_uploads_url( $blog_id = null ) {
894 if ( ai1wm_is_mainsite( $blog_id ) ) {
895 return sprintf( '/%s/', ai1wm_get_uploads_path() );
896 }
897
898 return sprintf( '/%s/sites/%d/', ai1wm_get_uploads_path(), $blog_id );
899 }
900
901 /**
902 * Get ServMask table prefix by blog ID
903 *
904 * @param integer $blog_id Blog ID
905 * @return string
906 */
907 function ai1wm_servmask_prefix( $blog_id = null ) {
908 if ( ai1wm_is_mainsite( $blog_id ) ) {
909 return AI1WM_TABLE_PREFIX;
910 }
911
912 return AI1WM_TABLE_PREFIX . $blog_id . '_';
913 }
914
915 /**
916 * Get WordPress table prefix by blog ID
917 *
918 * @param integer $blog_id Blog ID
919 * @return string
920 */
921 function ai1wm_table_prefix( $blog_id = null ) {
922 global $wpdb;
923
924 // Set base table prefix
925 if ( ai1wm_is_mainsite( $blog_id ) ) {
926 return $wpdb->base_prefix;
927 }
928
929 return $wpdb->base_prefix . $blog_id . '_';
930 }
931
932 /**
933 * Get default content filters
934 *
935 * @param array $filters List of files and directories
936 * @return array
937 */
938 function ai1wm_content_filters( $filters = array() ) {
939 return array_merge(
940 $filters,
941 array(
942 AI1WM_BACKUPS_PATH,
943 AI1WM_BACKUPS_NAME,
944 AI1WM_PACKAGE_NAME,
945 AI1WM_MULTISITE_NAME,
946 AI1WM_DATABASE_NAME,
947 AI1WM_W3TC_CONFIG_FILE,
948 )
949 );
950 }
951
952 /**
953 * Get default media filters
954 *
955 * @param array $filters List of files and directories
956 * @return array
957 */
958 function ai1wm_media_filters( $filters = array() ) {
959 return array_merge(
960 $filters,
961 array(
962 AI1WM_BACKUPS_PATH,
963 )
964 );
965 }
966
967 /**
968 * Get default plugin filters
969 *
970 * @param array $filters List of plugins
971 * @return array
972 */
973 function ai1wm_plugin_filters( $filters = array() ) {
974 return array_merge(
975 $filters,
976 array(
977 AI1WM_BACKUPS_PATH,
978 AI1WM_PLUGIN_BASEDIR,
979 AI1WMZE_PLUGIN_BASEDIR,
980 AI1WMAE_PLUGIN_BASEDIR,
981 AI1WMVE_PLUGIN_BASEDIR,
982 AI1WMBE_PLUGIN_BASEDIR,
983 AI1WMIE_PLUGIN_BASEDIR,
984 AI1WMXE_PLUGIN_BASEDIR,
985 AI1WMDE_PLUGIN_BASEDIR,
986 AI1WMTE_PLUGIN_BASEDIR,
987 AI1WMFE_PLUGIN_BASEDIR,
988 AI1WMCE_PLUGIN_BASEDIR,
989 AI1WMGE_PLUGIN_BASEDIR,
990 AI1WMRE_PLUGIN_BASEDIR,
991 AI1WMEE_PLUGIN_BASEDIR,
992 AI1WMME_PLUGIN_BASEDIR,
993 AI1WMOE_PLUGIN_BASEDIR,
994 AI1WMPE_PLUGIN_BASEDIR,
995 AI1WMKE_PLUGIN_BASEDIR,
996 AI1WMNE_PLUGIN_BASEDIR,
997 AI1WMSE_PLUGIN_BASEDIR,
998 AI1WMUE_PLUGIN_BASEDIR,
999 AI1WMLE_PLUGIN_BASEDIR,
1000 AI1WMWE_PLUGIN_BASEDIR,
1001 )
1002 );
1003 }
1004
1005 /**
1006 * Get default theme filters
1007 *
1008 * @param array $filters List of files and directories
1009 * @return array
1010 */
1011 function ai1wm_theme_filters( $filters = array() ) {
1012 return array_merge(
1013 $filters,
1014 array(
1015 AI1WM_BACKUPS_PATH,
1016 )
1017 );
1018 }
1019
1020 /**
1021 * Get active ServMask plugins
1022 *
1023 * @return array
1024 */
1025 function ai1wm_active_servmask_plugins( $plugins = array() ) {
1026 // WP Migration Plugin
1027 if ( defined( 'AI1WM_PLUGIN_BASENAME' ) ) {
1028 $plugins[] = AI1WM_PLUGIN_BASENAME;
1029 }
1030
1031 // Microsoft Azure Extension
1032 if ( defined( 'AI1WMZE_PLUGIN_BASENAME' ) ) {
1033 $plugins[] = AI1WMZE_PLUGIN_BASENAME;
1034 }
1035
1036 // Backblaze B2 Extension
1037 if ( defined( 'AI1WMAE_PLUGIN_BASENAME' ) ) {
1038 $plugins[] = AI1WMAE_PLUGIN_BASENAME;
1039 }
1040
1041 // Backup Plugin
1042 if ( defined( 'AI1WMVE_PLUGIN_BASENAME' ) ) {
1043 $plugins[] = AI1WMVE_PLUGIN_BASENAME;
1044 }
1045
1046 // Box Extension
1047 if ( defined( 'AI1WMBE_PLUGIN_BASENAME' ) ) {
1048 $plugins[] = AI1WMBE_PLUGIN_BASENAME;
1049 }
1050
1051 // DigitalOcean Spaces Extension
1052 if ( defined( 'AI1WMIE_PLUGIN_BASENAME' ) ) {
1053 $plugins[] = AI1WMIE_PLUGIN_BASENAME;
1054 }
1055
1056 // Direct Extension
1057 if ( defined( 'AI1WMXE_PLUGIN_BASENAME' ) ) {
1058 $plugins[] = AI1WMXE_PLUGIN_BASENAME;
1059 }
1060
1061 // Dropbox Extension
1062 if ( defined( 'AI1WMDE_PLUGIN_BASENAME' ) ) {
1063 $plugins[] = AI1WMDE_PLUGIN_BASENAME;
1064 }
1065
1066 // File Extension
1067 if ( defined( 'AI1WMTE_PLUGIN_BASENAME' ) ) {
1068 $plugins[] = AI1WMTE_PLUGIN_BASENAME;
1069 }
1070
1071 // FTP Extension
1072 if ( defined( 'AI1WMFE_PLUGIN_BASENAME' ) ) {
1073 $plugins[] = AI1WMFE_PLUGIN_BASENAME;
1074 }
1075
1076 // Google Cloud Storage Extension
1077 if ( defined( 'AI1WMCE_PLUGIN_BASENAME' ) ) {
1078 $plugins[] = AI1WMCE_PLUGIN_BASENAME;
1079 }
1080
1081 // Google Drive Extension
1082 if ( defined( 'AI1WMGE_PLUGIN_BASENAME' ) ) {
1083 $plugins[] = AI1WMGE_PLUGIN_BASENAME;
1084 }
1085
1086 // Amazon Glacier Extension
1087 if ( defined( 'AI1WMRE_PLUGIN_BASENAME' ) ) {
1088 $plugins[] = AI1WMRE_PLUGIN_BASENAME;
1089 }
1090
1091 // Mega Extension
1092 if ( defined( 'AI1WMEE_PLUGIN_BASENAME' ) ) {
1093 $plugins[] = AI1WMEE_PLUGIN_BASENAME;
1094 }
1095
1096 // Multisite Extension
1097 if ( defined( 'AI1WMME_PLUGIN_BASENAME' ) ) {
1098 $plugins[] = AI1WMME_PLUGIN_BASENAME;
1099 }
1100
1101 // OneDrive Extension
1102 if ( defined( 'AI1WMOE_PLUGIN_BASENAME' ) ) {
1103 $plugins[] = AI1WMOE_PLUGIN_BASENAME;
1104 }
1105
1106 // pCloud Extension
1107 if ( defined( 'AI1WMPE_PLUGIN_BASENAME' ) ) {
1108 $plugins[] = AI1WMPE_PLUGIN_BASENAME;
1109 }
1110
1111 // Pro Plugin
1112 if ( defined( 'AI1WMKE_PLUGIN_BASENAME' ) ) {
1113 $plugins[] = AI1WMKE_PLUGIN_BASENAME;
1114 }
1115
1116 // S3 Client Extension
1117 if ( defined( 'AI1WMNE_PLUGIN_BASENAME' ) ) {
1118 $plugins[] = AI1WMNE_PLUGIN_BASENAME;
1119 }
1120
1121 // Amazon S3 Extension
1122 if ( defined( 'AI1WMSE_PLUGIN_BASENAME' ) ) {
1123 $plugins[] = AI1WMSE_PLUGIN_BASENAME;
1124 }
1125
1126 // Unlimited Extension
1127 if ( defined( 'AI1WMUE_PLUGIN_BASENAME' ) ) {
1128 $plugins[] = AI1WMUE_PLUGIN_BASENAME;
1129 }
1130
1131 // URL Extension
1132 if ( defined( 'AI1WMLE_PLUGIN_BASENAME' ) ) {
1133 $plugins[] = AI1WMLE_PLUGIN_BASENAME;
1134 }
1135
1136 // WebDAV Extension
1137 if ( defined( 'AI1WMWE_PLUGIN_BASENAME' ) ) {
1138 $plugins[] = AI1WMWE_PLUGIN_BASENAME;
1139 }
1140
1141 return $plugins;
1142 }
1143
1144 /**
1145 * Get active sitewide plugins
1146 *
1147 * @return array
1148 */
1149 function ai1wm_active_sitewide_plugins() {
1150 return array_keys( get_site_option( AI1WM_ACTIVE_SITEWIDE_PLUGINS, array() ) );
1151 }
1152
1153 /**
1154 * Get active plugins
1155 *
1156 * @return array
1157 */
1158 function ai1wm_active_plugins() {
1159 return array_values( get_option( AI1WM_ACTIVE_PLUGINS, array() ) );
1160 }
1161
1162 /**
1163 * Set active sitewide plugins (inspired by WordPress activate_plugins() function)
1164 *
1165 * @param array $plugins List of plugins
1166 * @return boolean
1167 */
1168 function ai1wm_activate_sitewide_plugins( $plugins ) {
1169 $current = get_site_option( AI1WM_ACTIVE_SITEWIDE_PLUGINS, array() );
1170
1171 // Add plugins
1172 foreach ( $plugins as $plugin ) {
1173 if ( ! isset( $current[ $plugin ] ) && ! is_wp_error( validate_plugin( $plugin ) ) ) {
1174 $current[ $plugin ] = time();
1175 }
1176 }
1177
1178 return update_site_option( AI1WM_ACTIVE_SITEWIDE_PLUGINS, $current );
1179 }
1180
1181 /**
1182 * Set active plugins (inspired by WordPress activate_plugins() function)
1183 *
1184 * @param array $plugins List of plugins
1185 * @return boolean
1186 */
1187 function ai1wm_activate_plugins( $plugins ) {
1188 $current = get_option( AI1WM_ACTIVE_PLUGINS, array() );
1189
1190 // Add plugins
1191 foreach ( $plugins as $plugin ) {
1192 if ( ! in_array( $plugin, $current ) && ! is_wp_error( validate_plugin( $plugin ) ) ) {
1193 $current[] = $plugin;
1194 }
1195 }
1196
1197 return update_option( AI1WM_ACTIVE_PLUGINS, $current );
1198 }
1199
1200 /**
1201 * Get active template
1202 *
1203 * @return string
1204 */
1205 function ai1wm_active_template() {
1206 return get_option( AI1WM_ACTIVE_TEMPLATE );
1207 }
1208
1209 /**
1210 * Get active stylesheet
1211 *
1212 * @return string
1213 */
1214 function ai1wm_active_stylesheet() {
1215 return get_option( AI1WM_ACTIVE_STYLESHEET );
1216 }
1217
1218 /**
1219 * Set active template
1220 *
1221 * @param string $template Template name
1222 * @return boolean
1223 */
1224 function ai1wm_activate_template( $template ) {
1225 return update_option( AI1WM_ACTIVE_TEMPLATE, $template );
1226 }
1227
1228 /**
1229 * Set active stylesheet
1230 *
1231 * @param string $stylesheet Stylesheet name
1232 * @return boolean
1233 */
1234 function ai1wm_activate_stylesheet( $stylesheet ) {
1235 return update_option( AI1WM_ACTIVE_STYLESHEET, $stylesheet );
1236 }
1237
1238 /**
1239 * Set inactive sitewide plugins (inspired by WordPress deactivate_plugins() function)
1240 *
1241 * @param array $plugins List of plugins
1242 * @return boolean
1243 */
1244 function ai1wm_deactivate_sitewide_plugins( $plugins ) {
1245 $current = get_site_option( AI1WM_ACTIVE_SITEWIDE_PLUGINS, array() );
1246
1247 // Add plugins
1248 foreach ( $plugins as $plugin ) {
1249 if ( isset( $current[ $plugin ] ) ) {
1250 unset( $current[ $plugin ] );
1251 }
1252 }
1253
1254 return update_site_option( AI1WM_ACTIVE_SITEWIDE_PLUGINS, $current );
1255 }
1256
1257
1258 /**
1259 * Set inactive plugins (inspired by WordPress deactivate_plugins() function)
1260 *
1261 * @param array $plugins List of plugins
1262 * @return boolean
1263 */
1264 function ai1wm_deactivate_plugins( $plugins ) {
1265 $current = get_option( AI1WM_ACTIVE_PLUGINS, array() );
1266
1267 // Remove plugins
1268 foreach ( $plugins as $plugin ) {
1269 if ( ( $key = array_search( $plugin, $current ) ) !== false ) {
1270 unset( $current[ $key ] );
1271 }
1272 }
1273
1274 return update_option( AI1WM_ACTIVE_PLUGINS, $current );
1275 }
1276
1277 /**
1278 * Deactivate Jetpack modules
1279 *
1280 * @param array $modules List of modules
1281 * @return boolean
1282 */
1283 function ai1wm_deactivate_jetpack_modules( $modules ) {
1284 $current = get_option( AI1WM_JETPACK_ACTIVE_MODULES, array() );
1285
1286 // Remove modules
1287 foreach ( $modules as $module ) {
1288 if ( ( $key = array_search( $module, $current ) ) !== false ) {
1289 unset( $current[ $key ] );
1290 }
1291 }
1292
1293 return update_option( AI1WM_JETPACK_ACTIVE_MODULES, $current );
1294 }
1295
1296 /**
1297 * Deactivate Swift Optimizer rules
1298 *
1299 * @param array $rules List of rules
1300 * @return boolean
1301 */
1302 function ai1wm_deactivate_swift_optimizer_rules( $rules ) {
1303 $current = get_option( AI1WM_SWIFT_OPTIMIZER_PLUGIN_ORGANIZER, array() );
1304
1305 // Remove rules
1306 foreach ( $rules as $rule ) {
1307 unset( $current['rules'][ $rule ] );
1308 }
1309
1310 return update_option( AI1WM_SWIFT_OPTIMIZER_PLUGIN_ORGANIZER, $current );
1311 }
1312
1313 /**
1314 * Deactivate sitewide Revolution Slider
1315 *
1316 * @param string $basename Plugin basename
1317 * @return boolean
1318 */
1319 function ai1wm_deactivate_sitewide_revolution_slider( $basename ) {
1320 if ( ( $plugins = get_plugins() ) ) {
1321 if ( isset( $plugins[ $basename ]['Version'] ) && ( $version = $plugins[ $basename ]['Version'] ) ) {
1322 if ( version_compare( PHP_VERSION, '7.3', '>=' ) && version_compare( $version, '5.4.8.3', '<' ) ) {
1323 return ai1wm_deactivate_sitewide_plugins( array( $basename ) );
1324 }
1325
1326 if ( version_compare( PHP_VERSION, '7.2', '>=' ) && version_compare( $version, '5.4.6', '<' ) ) {
1327 return ai1wm_deactivate_sitewide_plugins( array( $basename ) );
1328 }
1329
1330 if ( version_compare( PHP_VERSION, '7.1', '>=' ) && version_compare( $version, '5.4.1', '<' ) ) {
1331 return ai1wm_deactivate_sitewide_plugins( array( $basename ) );
1332 }
1333
1334 if ( version_compare( PHP_VERSION, '7.0', '>=' ) && version_compare( $version, '4.6.5', '<' ) ) {
1335 return ai1wm_deactivate_sitewide_plugins( array( $basename ) );
1336 }
1337 }
1338 }
1339
1340 return false;
1341 }
1342
1343 /**
1344 * Deactivate Revolution Slider
1345 *
1346 * @param string $basename Plugin basename
1347 * @return boolean
1348 */
1349 function ai1wm_deactivate_revolution_slider( $basename ) {
1350 if ( ( $plugins = get_plugins() ) ) {
1351 if ( isset( $plugins[ $basename ]['Version'] ) && ( $version = $plugins[ $basename ]['Version'] ) ) {
1352 if ( version_compare( PHP_VERSION, '7.3', '>=' ) && version_compare( $version, '5.4.8.3', '<' ) ) {
1353 return ai1wm_deactivate_plugins( array( $basename ) );
1354 }
1355
1356 if ( version_compare( PHP_VERSION, '7.2', '>=' ) && version_compare( $version, '5.4.6', '<' ) ) {
1357 return ai1wm_deactivate_plugins( array( $basename ) );
1358 }
1359
1360 if ( version_compare( PHP_VERSION, '7.1', '>=' ) && version_compare( $version, '5.4.1', '<' ) ) {
1361 return ai1wm_deactivate_plugins( array( $basename ) );
1362 }
1363
1364 if ( version_compare( PHP_VERSION, '7.0', '>=' ) && version_compare( $version, '4.6.5', '<' ) ) {
1365 return ai1wm_deactivate_plugins( array( $basename ) );
1366 }
1367 }
1368 }
1369
1370 return false;
1371 }
1372
1373 /**
1374 * Initial DB version
1375 *
1376 * @return boolean
1377 */
1378 function ai1wm_initial_db_version() {
1379 if ( ! get_option( AI1WM_DB_VERSION ) ) {
1380 return update_option( AI1WM_DB_VERSION, get_option( AI1WM_INITIAL_DB_VERSION ) );
1381 }
1382
1383 return false;
1384 }
1385
1386 /**
1387 * Discover plugin basename
1388 *
1389 * @param string $basename Plugin basename
1390 * @return string
1391 */
1392 function ai1wm_discover_plugin_basename( $basename ) {
1393 if ( ( $plugins = get_plugins() ) ) {
1394 foreach ( $plugins as $plugin => $info ) {
1395 if ( strpos( dirname( $plugin ), dirname( $basename ) ) !== false ) {
1396 if ( basename( $plugin ) === basename( $basename ) ) {
1397 return $plugin;
1398 }
1399 }
1400 }
1401 }
1402
1403 return $basename;
1404 }
1405
1406 /**
1407 * Validate plugin basename
1408 *
1409 * @param string $basename Plugin basename
1410 * @return boolean
1411 */
1412 function ai1wm_validate_plugin_basename( $basename ) {
1413 if ( ( $plugins = get_plugins() ) ) {
1414 foreach ( $plugins as $plugin => $info ) {
1415 if ( $plugin === $basename ) {
1416 return true;
1417 }
1418 }
1419 }
1420
1421 return false;
1422 }
1423
1424 /**
1425 * Validate theme basename
1426 *
1427 * @param string $basename Theme basename
1428 * @return boolean
1429 */
1430 function ai1wm_validate_theme_basename( $basename ) {
1431 if ( ( $themes = search_theme_directories() ) ) {
1432 foreach ( $themes as $theme => $info ) {
1433 if ( $info['theme_file'] === $basename ) {
1434 return true;
1435 }
1436 }
1437 }
1438
1439 return false;
1440 }
1441
1442 /**
1443 * Flush WP options cache
1444 *
1445 * @return void
1446 */
1447 function ai1wm_cache_flush() {
1448 wp_cache_init();
1449 wp_cache_flush();
1450
1451 // Reset WP options cache
1452 wp_cache_set( 'alloptions', array(), 'options' );
1453 wp_cache_set( 'notoptions', array(), 'options' );
1454
1455 // Reset WP sitemeta cache
1456 wp_cache_set( '1:notoptions', array(), 'site-options' );
1457 wp_cache_set( '1:ms_files_rewriting', false, 'site-options' );
1458 wp_cache_set( '1:active_sitewide_plugins', false, 'site-options' );
1459
1460 // Delete WP options cache
1461 wp_cache_delete( 'alloptions', 'options' );
1462 wp_cache_delete( 'notoptions', 'options' );
1463
1464 // Delete WP sitemeta cache
1465 wp_cache_delete( '1:notoptions', 'site-options' );
1466 wp_cache_delete( '1:ms_files_rewriting', 'site-options' );
1467 wp_cache_delete( '1:active_sitewide_plugins', 'site-options' );
1468
1469 // Remove WP options filter
1470 remove_all_filters( 'sanitize_option_home' );
1471 remove_all_filters( 'sanitize_option_siteurl' );
1472 remove_all_filters( 'default_site_option_ms_files_rewriting' );
1473 }
1474
1475 /**
1476 * Flush Elementor cache
1477 *
1478 * @return void
1479 */
1480 function ai1wm_elementor_cache_flush() {
1481 delete_post_meta_by_key( '_elementor_css' );
1482 delete_post_meta_by_key( '_elementor_element_cache' );
1483 delete_post_meta_by_key( '_elementor_page_assets' );
1484
1485 delete_option( '_elementor_global_css' );
1486 delete_option( '_elementor_assets_data' );
1487 delete_option( 'elementor-custom-breakpoints-files' );
1488 }
1489
1490 /**
1491 * Set WooCommerce Force SSL checkout
1492 *
1493 * @param boolean $yes Force SSL checkout
1494 * @return void
1495 */
1496 function ai1wm_woocommerce_force_ssl( $yes = true ) {
1497 if ( get_option( 'woocommerce_force_ssl_checkout' ) ) {
1498 if ( $yes ) {
1499 update_option( 'woocommerce_force_ssl_checkout', 'yes' );
1500 } else {
1501 update_option( 'woocommerce_force_ssl_checkout', 'no' );
1502 }
1503 }
1504 }
1505
1506 /**
1507 * Set URL scheme
1508 *
1509 * @param string $url URL value
1510 * @param string $scheme URL scheme
1511 * @return string
1512 */
1513 function ai1wm_url_scheme( $url, $scheme = '' ) {
1514 if ( empty( $scheme ) ) {
1515 return preg_replace( '#^\w+://#', '//', $url );
1516 }
1517
1518 return preg_replace( '#^\w+://#', $scheme . '://', $url );
1519 }
1520
1521 /**
1522 * Opens a file in specified mode
1523 *
1524 * @param string $file Path to the file to open
1525 * @param string $mode Mode in which to open the file
1526 * @return resource
1527 * @throws Ai1wm_Not_Accessible_Exception
1528 */
1529 function ai1wm_open( $file, $mode ) {
1530 $file_handle = @fopen( $file, $mode );
1531 if ( false === $file_handle ) {
1532 throw new Ai1wm_Not_Accessible_Exception(
1533 wp_kses(
1534 /* translators: 1: File path, 2: mode */
1535 sprintf( __( 'Could not open %1$s with mode %2$s. The process cannot continue. <a href="https://help.servmask.com/knowledgebase/invalid-file-permissions/" target="_blank">Technical details</a>', 'all-in-one-wp-migration' ), $file, $mode ),
1536 ai1wm_allowed_html_tags()
1537 )
1538 );
1539 }
1540
1541 return $file_handle;
1542 }
1543
1544 /**
1545 * Opens a gzipped file in specified mode
1546 *
1547 * @param string $file Path to the file to open
1548 * @param string $mode Mode in which to open the file
1549 * @return resource
1550 * @throws Ai1wm_Not_Accessible_Exception
1551 */
1552 function ai1wm_gzopen( $file, $mode ) {
1553 $file_handle = @fopen( "compress.zlib://{$file}", $mode );
1554 if ( false === $file_handle ) {
1555 throw new Ai1wm_Not_Accessible_Exception(
1556 wp_kses(
1557 /* translators: 1: File path, 2: mode */
1558 sprintf( __( 'Could not open %1$s with mode %2$s. The process cannot continue. <a href="https://help.servmask.com/knowledgebase/invalid-file-permissions/" target="_blank">Technical details</a>', 'all-in-one-wp-migration' ), $file, $mode ),
1559 ai1wm_allowed_html_tags()
1560 )
1561 );
1562 }
1563
1564 return $file_handle;
1565 }
1566
1567 /**
1568 * Write contents to a file
1569 *
1570 * @param resource $handle File handle to write to
1571 * @param string $content Contents to write to the file
1572 * @return integer
1573 * @throws Ai1wm_Not_Writable_Exception
1574 * @throws Ai1wm_Quota_Exceeded_Exception
1575 */
1576 function ai1wm_write( $handle, $content ) {
1577 $write_result = @fwrite( $handle, $content );
1578 if ( false === $write_result ) {
1579 if ( ( $meta = stream_get_meta_data( $handle ) ) ) {
1580 throw new Ai1wm_Not_Writable_Exception(
1581 wp_kses(
1582 /* translators: 1: Meta data stream URI. */
1583 sprintf( __( 'Could not write to: %s. The process cannot continue. <a href="https://help.servmask.com/knowledgebase/invalid-file-permissions/" target="_blank">Technical details</a>', 'all-in-one-wp-migration' ), $meta['uri'] ),
1584 ai1wm_allowed_html_tags()
1585 )
1586 );
1587 }
1588 } elseif ( null === $write_result ) {
1589 return strlen( $content );
1590 } elseif ( strlen( $content ) !== $write_result ) {
1591 if ( ( $meta = stream_get_meta_data( $handle ) ) ) {
1592 throw new Ai1wm_Quota_Exceeded_Exception(
1593 wp_kses(
1594 /* translators: 1: Meta data stream URI. */
1595 sprintf( __( 'Out of disk space. Could not write to: %s. The process cannot continue. <a href="https://help.servmask.com/knowledgebase/out-of-disk-space/" target="_blank">Technical details</a>', 'all-in-one-wp-migration' ), $meta['uri'] ),
1596 ai1wm_allowed_html_tags()
1597 )
1598 );
1599 }
1600 }
1601
1602 return $write_result;
1603 }
1604
1605 /**
1606 * Read contents from a file
1607 *
1608 * @param resource $handle File handle to read from
1609 * @param integer $length Up to length number of bytes read
1610 * @return string
1611 * @throws Ai1wm_Not_Readable_Exception
1612 */
1613 function ai1wm_read( $handle, $length ) {
1614 if ( $length > 0 ) {
1615 $read_result = @fread( $handle, $length );
1616 if ( false === $read_result ) {
1617 if ( ( $meta = stream_get_meta_data( $handle ) ) ) {
1618 throw new Ai1wm_Not_Readable_Exception(
1619 wp_kses(
1620 /* translators: 1: Meta data stream URI. */
1621 sprintf( __( 'Could not read file: %s. The process cannot continue. <a href="https://help.servmask.com/knowledgebase/invalid-file-permissions/" target="_blank">Technical details</a>', 'all-in-one-wp-migration' ), $meta['uri'] ),
1622 ai1wm_allowed_html_tags()
1623 )
1624 );
1625 }
1626 }
1627
1628 return $read_result;
1629 }
1630
1631 return false;
1632 }
1633
1634 /**
1635 * Seeks on a file pointer
1636 *
1637 * @param resource $handle File handle
1638 * @param integer $offset File offset
1639 * @param integer $mode Offset mode
1640 * @return integer
1641 */
1642 function ai1wm_seek( $handle, $offset, $mode = SEEK_SET ) {
1643 $seek_result = @fseek( $handle, $offset, $mode );
1644 if ( -1 === $seek_result ) {
1645 if ( ( $meta = stream_get_meta_data( $handle ) ) ) {
1646 throw new Ai1wm_Not_Seekable_Exception(
1647 wp_kses(
1648 /* translators: 1: File offset, 2: Meta data stream URI. */
1649 sprintf( __( 'Could not seek to offset %1$d on %2$s. The process cannot continue. <a href="https://help.servmask.com/knowledgebase/php-32bit/" target="_blank">Technical details</a>', 'all-in-one-wp-migration' ), $offset, $meta['uri'] ),
1650 ai1wm_allowed_html_tags()
1651 )
1652 );
1653 }
1654 }
1655
1656 return $seek_result;
1657 }
1658
1659 /**
1660 * Returns the current position of the file read/write pointer
1661 *
1662 * @param resource $handle File handle
1663 * @return integer
1664 */
1665 function ai1wm_tell( $handle ) {
1666 $tell_result = @ftell( $handle );
1667 if ( false === $tell_result ) {
1668 if ( ( $meta = stream_get_meta_data( $handle ) ) ) {
1669 throw new Ai1wm_Not_Tellable_Exception(
1670 wp_kses(
1671 /* translators: 1: Meta data stream URI. */
1672 sprintf( __( 'Could not get current pointer position of %s. The process cannot continue. <a href="https://help.servmask.com/knowledgebase/php-32bit/" target="_blank">Technical details</a>', 'all-in-one-wp-migration' ), $meta['uri'] ),
1673 ai1wm_allowed_html_tags()
1674 )
1675 );
1676 }
1677 }
1678
1679 return $tell_result;
1680 }
1681
1682 /**
1683 * Write fields to a file
1684 *
1685 * @param resource $handle File handle to write to
1686 * @param array $fields Fields to write to the file
1687 * @param string $separator
1688 * @param string $enclosure
1689 * @param string $escape
1690 *
1691 * @return integer
1692 * @throws Ai1wm_Not_Writable_Exception
1693 */
1694 function ai1wm_putcsv( $handle, $fields, $separator = ',', $enclosure = '"', $escape = '\\' ) {
1695 if ( PHP_MAJOR_VERSION >= 7 ) {
1696 $write_result = @fputcsv( $handle, $fields, $separator, $enclosure, $escape );
1697 } else {
1698 $write_result = @fputcsv( $handle, $fields, $separator, $enclosure );
1699 }
1700
1701 if ( false === $write_result ) {
1702 if ( ( $meta = stream_get_meta_data( $handle ) ) ) {
1703 throw new Ai1wm_Not_Writable_Exception(
1704 wp_kses(
1705 /* translators: 1: Meta data stream URI. */
1706 sprintf( __( 'Could not write to: %s. The process cannot continue. <a href="https://help.servmask.com/knowledgebase/invalid-file-permissions/" target="_blank">Technical details</a>', 'all-in-one-wp-migration' ), $meta['uri'] ),
1707 ai1wm_allowed_html_tags()
1708 )
1709 );
1710 }
1711 }
1712
1713 return $write_result;
1714 }
1715
1716 /**
1717 * Read fields from a file
1718 *
1719 * @param resource $handle File handle to read from
1720 * @param int $length
1721 * @param string $separator
1722 * @param string $enclosure
1723 * @param string $escape
1724 *
1725 * @return array|false|null
1726 */
1727 function ai1wm_getcsv( $handle, $length = null, $separator = ',', $enclosure = '"', $escape = '\\' ) {
1728 return fgetcsv( $handle, $length, $separator, $enclosure, $escape );
1729 }
1730
1731 /**
1732 * Closes a file handle
1733 *
1734 * @param resource $handle File handle to close
1735 * @return boolean
1736 */
1737 function ai1wm_close( $handle ) {
1738 return @fclose( $handle );
1739 }
1740
1741 /**
1742 * Deletes a file
1743 *
1744 * @param string $file Path to file to delete
1745 * @return boolean
1746 */
1747 function ai1wm_unlink( $file ) {
1748 return @unlink( $file );
1749 }
1750
1751 /**
1752 * Sets modification time of a file
1753 *
1754 * @param string $file Path to file to change modification time
1755 * @param integer $time File modification time
1756 * @return boolean
1757 */
1758 function ai1wm_touch( $file, $mtime ) {
1759 return @touch( $file, $mtime );
1760 }
1761
1762 /**
1763 * Changes file mode
1764 *
1765 * @param string $file Path to file to change mode
1766 * @param integer $time File mode
1767 * @return boolean
1768 */
1769 function ai1wm_chmod( $file, $mode ) {
1770 return @chmod( $file, $mode );
1771 }
1772
1773 /**
1774 * Copies one file's contents to another
1775 *
1776 * @param string $target_file File to copy the contents from
1777 * @param string $output_file File to copy the contents to
1778 * @param integer $output_file_offset Output file offset bytes
1779 * @return void
1780 */
1781 function ai1wm_copy( $target_file, $output_file, $output_file_offset = 0 ) {
1782 $target_handle = ai1wm_open( $target_file, 'rb' );
1783 $output_handle = ai1wm_open( $output_file, 'cb' );
1784 if ( ai1wm_seek( $output_handle, $output_file_offset, SEEK_SET ) !== -1 ) {
1785 while ( ( $file_buffer = ai1wm_read( $target_handle, 4096 ) ) ) {
1786 ai1wm_write( $output_handle, $file_buffer );
1787 }
1788 }
1789
1790 ai1wm_close( $target_handle );
1791 ai1wm_close( $output_handle );
1792 }
1793
1794 /**
1795 * Copies gzipped file's contents while uncompressing to another
1796 *
1797 * @param string $target_file File to copy the contents from
1798 * @param string $output_file File to copy the contents to
1799 * @param integer $output_file_offset Output file offset bytes
1800 * @return void
1801 */
1802 function ai1wm_copy_gz( $target_file, $output_file, $output_file_offset = 0 ) {
1803 $target_handle = ai1wm_gzopen( $target_file, 'rb' );
1804 $output_handle = ai1wm_open( $output_file, 'cb' );
1805 if ( ai1wm_seek( $output_handle, $output_file_offset, SEEK_SET ) !== -1 ) {
1806 while ( ( $file_buffer = ai1wm_read( $target_handle, 4096 ) ) ) {
1807 ai1wm_write( $output_handle, $file_buffer );
1808 }
1809 }
1810
1811 ai1wm_close( $target_handle );
1812 ai1wm_close( $output_handle );
1813 }
1814
1815
1816 /**
1817 * Check whether file size is supported by current PHP version
1818 *
1819 * @param string $file Path to file
1820 * @param integer $php_int_size Size of PHP integer
1821 * @return boolean $php_int_max Max value of PHP integer
1822 */
1823 function ai1wm_is_filesize_supported( $file, $php_int_size = PHP_INT_SIZE, $php_int_max = PHP_INT_MAX ) {
1824 $size_result = true;
1825
1826 // Check whether file size is less than 2GB in PHP 32bits
1827 if ( $php_int_size === 4 ) {
1828 if ( ( $file_handle = @fopen( $file, 'rb' ) ) ) {
1829 if ( @fseek( $file_handle, $php_int_max, SEEK_SET ) !== -1 ) {
1830 if ( @fgetc( $file_handle ) !== false ) {
1831 $size_result = false;
1832 }
1833 }
1834
1835 @fclose( $file_handle );
1836 }
1837 }
1838
1839 return $size_result;
1840 }
1841
1842 /**
1843 * Check whether file name is supported by All-in-One WP Migration
1844 *
1845 * @param string $file Path to file
1846 * @param array $extensions File extensions
1847 * @return boolean
1848 */
1849 function ai1wm_is_filename_supported( $file, $extensions = array( 'wpress' ) ) {
1850 if ( in_array( pathinfo( $file, PATHINFO_EXTENSION ), $extensions ) ) {
1851 return true;
1852 }
1853
1854 return false;
1855 }
1856
1857 /**
1858 * Check whether file data is supported by All-in-One WP Migration
1859 *
1860 * @param string $file Path to file
1861 * @return boolean
1862 */
1863 function ai1wm_is_filedata_supported( $file ) {
1864 if ( ( $file_handle = @fopen( $file, 'rb' ) ) ) {
1865 if ( ( $file_buffer = @fread( $file_handle, 4377 ) ) ) {
1866 if ( ( $file_data = @unpack( 'a255filename/a14size/a12mtime/a4096path', $file_buffer ) ) !== false ) {
1867 if ( AI1WM_PACKAGE_NAME === trim( $file_data['filename'] ) ) {
1868 return true;
1869 }
1870 }
1871 }
1872
1873 @fclose( $file_handle );
1874 }
1875
1876 return false;
1877 }
1878
1879 /**
1880 * Check whether gzipped file data is supported by All-in-One WP Migration
1881 *
1882 * @param string $file Path to file
1883 * @return boolean
1884 */
1885 function ai1wm_is_gzipped_filedata_supported( $file ) {
1886 if ( ( $file_handle = @gzopen( $file, 'rb' ) ) ) {
1887 if ( ( $file_buffer = @gzread( $file_handle, 4377 ) ) ) {
1888 if ( ( $file_data = @unpack( 'a255filename/a14size/a12mtime/a4096path', $file_buffer ) ) !== false ) {
1889 if ( AI1WM_PACKAGE_NAME === trim( $file_data['filename'] ) ) {
1890 return true;
1891 }
1892 }
1893 }
1894
1895 @gzclose( $file_handle );
1896 }
1897
1898 return false;
1899 }
1900
1901 /**
1902 * Verify secret key
1903 *
1904 * @param string $secret_key Secret key
1905 * @return boolean
1906 * @throws Ai1wm_Not_Valid_Secret_Key_Exception
1907 */
1908 function ai1wm_verify_secret_key( $secret_key ) {
1909 if ( $secret_key !== get_option( AI1WM_SECRET_KEY ) ) {
1910 throw new Ai1wm_Not_Valid_Secret_Key_Exception(
1911 wp_kses(
1912 __( 'Could not authenticate the secret key. The process cannot continue. <a href="https://help.servmask.com/knowledgebase/invalid-secret-key/" target="_blank">Technical details</a>', 'all-in-one-wp-migration' ),
1913 ai1wm_allowed_html_tags()
1914 )
1915 );
1916 }
1917
1918 return true;
1919 }
1920
1921 /**
1922 * Is scheduled backup?
1923 *
1924 * @return boolean
1925 */
1926 function ai1wm_is_scheduled_backup() {
1927 if ( isset( $_GET['ai1wm_manual_export'] ) || isset( $_POST['ai1wm_manual_export'] ) ) {
1928 return false;
1929 }
1930
1931 if ( isset( $_GET['ai1wm_manual_import'] ) || isset( $_POST['ai1wm_manual_import'] ) ) {
1932 return false;
1933 }
1934
1935 if ( isset( $_GET['ai1wm_manual_restore'] ) || isset( $_POST['ai1wm_manual_restore'] ) ) {
1936 return false;
1937 }
1938
1939 if ( isset( $_GET['ai1wm_manual_reset'] ) || isset( $_POST['ai1wm_manual_reset'] ) ) {
1940 return false;
1941 }
1942
1943 return true;
1944 }
1945
1946 /**
1947 * PHP setup environment
1948 *
1949 * @return void
1950 */
1951 function ai1wm_setup_environment() {
1952 // Set whether a client disconnect should abort script execution
1953 @ignore_user_abort( true );
1954
1955 // Set maximum execution time
1956 @set_time_limit( 0 );
1957
1958 // Set maximum time in seconds a script is allowed to parse input data
1959 @ini_set( 'max_input_time', '-1' );
1960
1961 // Set maximum backtracking steps
1962 @ini_set( 'pcre.backtrack_limit', PHP_INT_MAX );
1963
1964 // Set binary safe encoding
1965 if ( @function_exists( 'mb_internal_encoding' ) && ( @ini_get( 'mbstring.func_overload' ) & 2 ) ) {
1966 @mb_internal_encoding( 'ISO-8859-1' );
1967 }
1968
1969 // Clean (erase) the output buffer and turn off output buffering
1970 if ( @ob_get_length() ) {
1971 @ob_end_clean();
1972 }
1973 }
1974
1975 /**
1976 * PHP register error handlers
1977 *
1978 * @return void
1979 */
1980 function ai1wm_setup_errors() {
1981 @set_error_handler( 'Ai1wm_Handler::error' );
1982 @register_shutdown_function( 'Ai1wm_Handler::shutdown' );
1983 }
1984
1985 /**
1986 * Get WordPress time zone string
1987 *
1988 * @return string
1989 */
1990 function ai1wm_get_timezone_string() {
1991 if ( ( $timezone_string = get_option( 'timezone_string' ) ) ) {
1992 return $timezone_string;
1993 }
1994
1995 if ( ( $gmt_offset = get_option( 'gmt_offset' ) ) ) {
1996 if ( $gmt_offset > 0 ) {
1997 return sprintf( 'UTC+%s', abs( $gmt_offset ) );
1998 } elseif ( $gmt_offset < 0 ) {
1999 return sprintf( 'UTC-%s', abs( $gmt_offset ) );
2000 }
2001 }
2002
2003 return 'UTC';
2004 }
2005
2006 /**
2007 * Get WordPress filter hooks
2008 *
2009 * @param string $tag The name of the filter hook
2010 * @return array
2011 */
2012 function ai1wm_get_filters( $tag ) {
2013 global $wp_filter;
2014
2015 // Get WordPress filter hooks
2016 $filters = array();
2017 if ( isset( $wp_filter[ $tag ] ) ) {
2018 if ( ( $filters = $wp_filter[ $tag ] ) ) {
2019 // WordPress 4.7 introduces new class for working with filters/actions called WP_Hook
2020 // which adds another level of abstraction and we need to address it.
2021 if ( isset( $filters->callbacks ) ) {
2022 $filters = $filters->callbacks;
2023 }
2024 }
2025
2026 ksort( $filters );
2027 }
2028
2029 return $filters;
2030 }
2031
2032 /**
2033 * Get WordPress plugins directories
2034 *
2035 * @return array
2036 */
2037 function ai1wm_get_themes_dirs() {
2038 $theme_dirs = array();
2039 foreach ( search_theme_directories() as $theme_name => $theme_info ) {
2040 if ( isset( $theme_info['theme_root'] ) ) {
2041 if ( ! in_array( $theme_info['theme_root'], $theme_dirs ) ) {
2042 $theme_dirs[] = untrailingslashit( $theme_info['theme_root'] );
2043 }
2044 }
2045 }
2046
2047 return $theme_dirs;
2048 }
2049
2050 /**
2051 * Get WordPress plugins directory
2052 *
2053 * @return string
2054 */
2055 function ai1wm_get_plugins_dir() {
2056 return untrailingslashit( WP_PLUGIN_DIR );
2057 }
2058
2059 /**
2060 * Get WordPress uploads directory
2061 *
2062 * @return string
2063 */
2064 function ai1wm_get_uploads_dir() {
2065 if ( ( $upload_dir = wp_upload_dir() ) ) {
2066 if ( isset( $upload_dir['basedir'] ) ) {
2067 return untrailingslashit( $upload_dir['basedir'] );
2068 }
2069 }
2070 }
2071
2072 /**
2073 * Get WordPress uploads URL
2074 *
2075 * @return string
2076 */
2077 function ai1wm_get_uploads_url() {
2078 if ( ( $upload_dir = wp_upload_dir() ) ) {
2079 if ( isset( $upload_dir['baseurl'] ) ) {
2080 return trailingslashit( $upload_dir['baseurl'] );
2081 }
2082 }
2083 }
2084
2085 /**
2086 * Get WordPress uploads path
2087 *
2088 * @return string
2089 */
2090 function ai1wm_get_uploads_path() {
2091 if ( ( $upload_dir = wp_upload_dir() ) ) {
2092 if ( isset( $upload_dir['basedir'] ) ) {
2093 return str_replace( ABSPATH, '', $upload_dir['basedir'] );
2094 }
2095 }
2096 }
2097
2098 /**
2099 * i18n friendly version of basename()
2100 *
2101 * @param string $path File path
2102 * @param string $suffix If the filename ends in suffix this will also be cut off
2103 * @return string
2104 */
2105 function ai1wm_basename( $path, $suffix = '' ) {
2106 return urldecode( basename( str_replace( array( '%2F', '%5C' ), '/', urlencode( $path ) ), $suffix ) );
2107 }
2108
2109 /**
2110 * i18n friendly version of dirname()
2111 *
2112 * @param string $path File path
2113 * @return string
2114 */
2115 function ai1wm_dirname( $path ) {
2116 return urldecode( dirname( str_replace( array( '%2F', '%5C' ), '/', urlencode( $path ) ) ) );
2117 }
2118
2119 /**
2120 * Replace forward slash with current directory separator
2121 *
2122 * @param string $path Path
2123 * @return string
2124 */
2125 function ai1wm_replace_forward_slash_with_directory_separator( $path ) {
2126 return str_replace( '/', DIRECTORY_SEPARATOR, $path );
2127 }
2128
2129 /**
2130 * Replace current directory separator with forward slash
2131 *
2132 * @param string $path Path
2133 * @return string
2134 */
2135 function ai1wm_replace_directory_separator_with_forward_slash( $path ) {
2136 return str_replace( DIRECTORY_SEPARATOR, '/', $path );
2137 }
2138
2139 /**
2140 * Escape Windows directory separator
2141 *
2142 * @param string $path Path
2143 * @return string
2144 */
2145 function ai1wm_escape_windows_directory_separator( $path ) {
2146 return preg_replace( '/[\\\\]+/', '\\\\\\\\', $path );
2147 }
2148
2149 /**
2150 * Should reset WordPress permalinks?
2151 *
2152 * @param array $params Request parameters
2153 * @return boolean
2154 */
2155 function ai1wm_should_reset_permalinks( $params ) {
2156 global $wp_rewrite, $is_apache;
2157
2158 // Permalinks are not supported
2159 if ( empty( $params['using_permalinks'] ) ) {
2160 if ( $wp_rewrite->using_permalinks() ) {
2161 if ( $is_apache ) {
2162 if ( ! apache_mod_loaded( 'mod_rewrite', false ) ) {
2163 return true;
2164 }
2165 }
2166 }
2167 }
2168
2169 return false;
2170 }
2171
2172 /**
2173 * Get .htaccess file content
2174 *
2175 * @return string
2176 */
2177 function ai1wm_get_htaccess() {
2178 if ( is_file( AI1WM_WORDPRESS_HTACCESS ) ) {
2179 return @file_get_contents( AI1WM_WORDPRESS_HTACCESS );
2180 }
2181
2182 return '';
2183 }
2184
2185 /**
2186 * Get web.config file content
2187 *
2188 * @return string
2189 */
2190 function ai1wm_get_webconfig() {
2191 if ( is_file( AI1WM_WORDPRESS_WEBCONFIG ) ) {
2192 return @file_get_contents( AI1WM_WORDPRESS_WEBCONFIG );
2193 }
2194
2195 return '';
2196 }
2197
2198 /**
2199 * Get available space on filesystem or disk partition
2200 *
2201 * @param string $path Directory of the filesystem or disk partition
2202 * @return mixed
2203 */
2204 function ai1wm_disk_free_space( $path ) {
2205 if ( function_exists( 'disk_free_space' ) ) {
2206 return @disk_free_space( $path );
2207 }
2208 }
2209
2210 /**
2211 * Set response header to json end echo data
2212 *
2213 * @param array $data
2214 * @param int $options
2215 * @param int $depth
2216 * @return void
2217 */
2218 function ai1wm_json_response( $data, $options = 0 ) {
2219 if ( ! headers_sent() ) {
2220 header( 'Content-Type: application/json; charset=' . get_option( 'blog_charset', 'utf-8' ) );
2221 }
2222
2223 echo json_encode( $data, $options );
2224 }
2225
2226 /**
2227 * Determines if the server can encrypt backups
2228 *
2229 * @return boolean
2230 */
2231 function ai1wm_can_encrypt() {
2232 if ( ! function_exists( 'openssl_encrypt' ) ) {
2233 return false;
2234 }
2235
2236 if ( ! function_exists( 'openssl_random_pseudo_bytes' ) ) {
2237 return false;
2238 }
2239
2240 if ( ! function_exists( 'openssl_cipher_iv_length' ) ) {
2241 return false;
2242 }
2243
2244 if ( ! function_exists( 'sha1' ) ) {
2245 return false;
2246 }
2247
2248 if ( ! in_array( AI1WM_CIPHER_NAME, array_map( 'strtoupper', openssl_get_cipher_methods() ) ) ) {
2249 return false;
2250 }
2251
2252 return true;
2253 }
2254
2255 /**
2256 * Determines if the server can decrypt backups
2257 *
2258 * @return boolean
2259 */
2260 function ai1wm_can_decrypt() {
2261 if ( ! function_exists( 'openssl_decrypt' ) ) {
2262 return false;
2263 }
2264
2265 if ( ! function_exists( 'openssl_random_pseudo_bytes' ) ) {
2266 return false;
2267 }
2268
2269 if ( ! function_exists( 'openssl_cipher_iv_length' ) ) {
2270 return false;
2271 }
2272
2273 if ( ! function_exists( 'sha1' ) ) {
2274 return false;
2275 }
2276
2277 if ( ! in_array( AI1WM_CIPHER_NAME, array_map( 'strtoupper', openssl_get_cipher_methods() ) ) ) {
2278 return false;
2279 }
2280
2281 return true;
2282 }
2283
2284 /**
2285 * Encrypts a string with a key
2286 *
2287 * @param string $string String to encrypt
2288 * @param string $key Key to encrypt the string with
2289 * @return string
2290 * @throws Ai1wm_Not_Encryptable_Exception
2291 */
2292 function ai1wm_encrypt_string( $string, $key ) {
2293 $iv_length = ai1wm_crypt_iv_length();
2294 $key = substr( sha1( $key, true ), 0, $iv_length );
2295
2296 $iv = openssl_random_pseudo_bytes( $iv_length );
2297 if ( $iv === false ) {
2298 throw new Ai1wm_Not_Encryptable_Exception( esc_html__( 'Could not generate random bytes. The process cannot continue.', 'all-in-one-wp-migration' ) );
2299 }
2300
2301 $encrypted_string = openssl_encrypt( $string, AI1WM_CIPHER_NAME, $key, OPENSSL_RAW_DATA, $iv );
2302 if ( $encrypted_string === false ) {
2303 throw new Ai1wm_Not_Encryptable_Exception( esc_html__( 'Could not encrypt data. The process cannot continue.', 'all-in-one-wp-migration' ) );
2304 }
2305
2306 return sprintf( '%s%s', $iv, $encrypted_string );
2307 }
2308
2309 /**
2310 * Returns encrypt/decrypt iv length
2311 *
2312 * @return int
2313 * @throws Ai1wm_Not_Encryptable_Exception
2314 */
2315 function ai1wm_crypt_iv_length() {
2316 $iv_length = openssl_cipher_iv_length( AI1WM_CIPHER_NAME );
2317 if ( $iv_length === false ) {
2318 throw new Ai1wm_Not_Encryptable_Exception( esc_html__( 'Could not obtain cipher length. The process cannot continue.', 'all-in-one-wp-migration' ) );
2319 }
2320
2321 return $iv_length;
2322 }
2323
2324 /**
2325 * Decrypts a string with a eky
2326 *
2327 * @param string $encrypted_string String to decrypt
2328 * @param string $key Key to decrypt the string with
2329 * @return string
2330 * @throws Ai1wm_Not_Encryptable_Exception
2331 * @throws Ai1wm_Not_Decryptable_Exception
2332 */
2333 function ai1wm_decrypt_string( $encrypted_string, $key ) {
2334 $iv_length = ai1wm_crypt_iv_length();
2335 $key = substr( sha1( $key, true ), 0, $iv_length );
2336 $iv = substr( $encrypted_string, 0, $iv_length );
2337
2338 $decrypted_string = openssl_decrypt( substr( $encrypted_string, $iv_length ), AI1WM_CIPHER_NAME, $key, OPENSSL_RAW_DATA, $iv );
2339 if ( $decrypted_string === false ) {
2340 throw new Ai1wm_Not_Decryptable_Exception( esc_html__( 'Could not decrypt data. The process cannot continue.', 'all-in-one-wp-migration' ) );
2341 }
2342
2343 return $decrypted_string;
2344 }
2345
2346 /**
2347 * Checks if decryption password is valid
2348 *
2349 * @param string $encrypted_signature
2350 * @param string $password
2351 * @return bool
2352 */
2353 function ai1wm_is_decryption_password_valid( $encrypted_signature, $password ) {
2354 try {
2355 $encrypted_signature = base64_decode( $encrypted_signature );
2356
2357 return ai1wm_decrypt_string( $encrypted_signature, $password ) === AI1WM_SIGN_TEXT;
2358 } catch ( Ai1wm_Not_Decryptable_Exception $exception ) {
2359 return false;
2360 }
2361 }
2362
2363 function ai1wm_populate_roles() {
2364 if ( ! function_exists( 'populate_roles' ) && ! function_exists( 'populate_options' ) && ! function_exists( 'populate_network' ) ) {
2365 require_once( ABSPATH . 'wp-admin/includes/schema.php' );
2366 }
2367
2368 if ( function_exists( 'populate_roles' ) ) {
2369 populate_roles();
2370 }
2371 }
2372
2373 /**
2374 * Set basic auth header to request
2375 *
2376 * @param array $headers
2377 *
2378 * @return array
2379 */
2380 function ai1wm_auth_headers( $headers = array() ) {
2381 if ( $hash = get_option( AI1WM_AUTH_HEADER ) ) {
2382 $headers['Authorization'] = sprintf( 'Basic %s', $hash );
2383 }
2384
2385 if ( ( $user = get_option( AI1WM_AUTH_USER ) ) && ( $password = get_option( AI1WM_AUTH_PASSWORD ) ) ) {
2386 if ( ! isset( $headers['Authorization'] ) && ( $hash = base64_encode( sprintf( '%s:%s', $user, $password ) ) ) ) {
2387 update_option( AI1WM_AUTH_HEADER, $hash );
2388 $headers['Authorization'] = sprintf( 'Basic %s', $hash );
2389 }
2390 delete_option( AI1WM_AUTH_USER );
2391 delete_option( AI1WM_AUTH_PASSWORD );
2392 }
2393
2394 return $headers;
2395 }
2396
2397 /**
2398 * Check if direct download of backup supported
2399 *
2400 * @return bool
2401 */
2402 function ai1wm_direct_download_supported() {
2403 return ! ( $_SERVER['SERVER_NAME'] === 'playground.wordpress.net' || $_SERVER['SERVER_SOFTWARE'] === 'PHP.wasm' );
2404 }
2405
2406 /**
2407 * Get allowed HTML tags when output with `wp_kses()`
2408 *
2409 * @return array
2410 */
2411 function ai1wm_allowed_html_tags() {
2412 return array(
2413 'a' => array(
2414 'href' => array(),
2415 'title' => array(),
2416 'target' => array(),
2417 'id' => array(),
2418 'name' => array(),
2419 'aria-label' => array(),
2420 'class' => array(),
2421 'style' => array(),
2422 'disabled' => array(),
2423 'download' => array(),
2424 ),
2425 'p' => array(
2426 'class' => array(),
2427 'style' => array(),
2428 ),
2429 'br' => array(),
2430 'em' => array(),
2431 'strong' => array(),
2432 'input' => array(
2433 'type' => array(),
2434 'name' => array(),
2435 'aria-label' => array(),
2436 'style' => array(),
2437 'id' => array(),
2438 'value' => array(),
2439 'class' => array(),
2440 'disabled' => array(),
2441 ),
2442 );
2443 }
2444
2445 /**
2446 * Wrapper for wp_register_style function
2447 *
2448 * @param string $handle Name of the stylesheet
2449 * @param string $src Path of the stylesheet
2450 * @param array $deps An array of registered stylesheet handles this stylesheet depends on
2451 * @param mixed $ver String specifying stylesheet version number
2452 * @param string $media The media for which this stylesheet has been defined
2453 *
2454 * @return bool
2455 */
2456 function ai1wm_register_style( $handle, $src, $deps = array(), $ver = false, $media = 'all' ) {
2457 if ( is_rtl() ) {
2458 $src = str_replace( '.min.css', '.min.rtl.css', $src );
2459 }
2460
2461 return wp_register_style( $handle, $src, $deps, $ver, $media );
2462 }
2463
2464 /**
2465 * Wrapper for wp_enqueue_style function
2466 *
2467 * @param string $handle Name of the stylesheet
2468 * @param string $src Path of the stylesheet
2469 * @param array $deps An array of registered stylesheet handles this stylesheet depends on
2470 * @param mixed $ver String specifying stylesheet version number
2471 * @param string $media The media for which this stylesheet has been defined
2472 *
2473 * @return void
2474 */
2475 function ai1wm_enqueue_style( $handle, $src = '', $deps = array(), $ver = false, $media = 'all' ) {
2476 if ( is_rtl() ) {
2477 $src = str_replace( '.min.css', '.min.rtl.css', $src );
2478 }
2479
2480 wp_enqueue_style( $handle, $src, $deps, $ver, $media );
2481 }
2482
2483 /**
2484 * Wrapper for wp_register_script function
2485 *
2486 * @param string $handle Name of the script
2487 * @param string $src Path of the script
2488 * @param array $deps An array of registered script handles this script depends on
2489 * @param mixed $ver String specifying script version number
2490 * @param mixed $args An array of additional script loading strategies
2491 *
2492 * @return bool
2493 */
2494 function ai1wm_register_script( $handle, $src, $deps = array(), $ver = false, $args = array() ) {
2495 return wp_register_script( $handle, $src, $deps, $ver, $args );
2496 }
2497
2498 /**
2499 * Wrapper for wp_enqueue_script function
2500 *
2501 * @param string $handle Name of the script
2502 * @param string $src Path of the script
2503 * @param array $deps An array of registered script handles this script depends on
2504 * @param mixed $ver String specifying script version number
2505 * @param mixed $args An array of additional script loading strategies
2506 *
2507 * @return void
2508 */
2509 function ai1wm_enqueue_script( $handle, $src = '', $deps = array(), $ver = false, $args = array() ) {
2510 wp_enqueue_script( $handle, $src, $deps, $ver, $args );
2511 }
2512