This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace HM\BackUpWordPress; |
||
4 | |||
5 | use Symfony\Component\Process\Process as Process; |
||
6 | |||
7 | /** |
||
8 | * Perform a file backup using the zip cli command |
||
9 | */ |
||
10 | class Zip_File_Backup_Engine extends File_Backup_Engine { |
||
11 | |||
12 | /** |
||
13 | * The path to the zip executable |
||
14 | * |
||
15 | * @var string |
||
16 | */ |
||
17 | private $zip_executable_path = ''; |
||
18 | |||
19 | public function __construct() { |
||
20 | parent::__construct(); |
||
21 | } |
||
22 | |||
23 | /** |
||
24 | * Calculate the path to the zip executable. |
||
25 | * |
||
26 | * The executable path can be overridden using either the `HMBKP_ZIP_PATH` |
||
27 | * Constant or the `hmbkp_zip_executable_path` filter. |
||
28 | * |
||
29 | * If neither of those are set then we fallback to checking a number of |
||
30 | * common locations. |
||
31 | * |
||
32 | * @return string|false The path to the executable or false. |
||
33 | */ |
||
34 | public function get_zip_executable_path() { |
||
35 | |||
36 | if ( defined( 'HMBKP_ZIP_PATH' ) ) { |
||
37 | return HMBKP_ZIP_PATH; |
||
38 | } |
||
39 | |||
40 | /** |
||
41 | * Allow the executable path to be set via a filter |
||
42 | * |
||
43 | * @param string The path to the zip executable |
||
44 | */ |
||
45 | $this->zip_executable_path = apply_filters( 'hmbkp_zip_executable_path', '' ); |
||
46 | |||
47 | if ( ! $this->zip_executable_path ) { |
||
48 | |||
49 | // List of possible zip locations |
||
50 | $paths = array( |
||
51 | 'zip', |
||
52 | '/usr/bin/zip', |
||
53 | '/usr/local/bin/zip', |
||
54 | '/opt/local/bin/zip', |
||
55 | ); |
||
56 | |||
57 | $this->zip_executable_path = Backup_Utilities::get_executable_path( $paths ); |
||
0 ignored issues
–
show
|
|||
58 | |||
59 | } |
||
60 | |||
61 | return $this->zip_executable_path; |
||
62 | |||
63 | } |
||
64 | |||
65 | /** |
||
66 | * Perform the file backup. |
||
67 | * |
||
68 | * @return bool Whether the backup completed successfully or not. |
||
69 | */ |
||
70 | public function backup() { |
||
71 | |||
72 | if ( ! $this->get_zip_executable_path() ) { |
||
0 ignored issues
–
show
The expression
$this->get_zip_executable_path() of type string|false is loosely compared to false ; this is ambiguous if the string can be empty. You might want to explicitly use === false instead.
In PHP, under loose comparison (like For '' == false // true
'' == null // true
'ab' == false // false
'ab' == null // false
// It is often better to use strict comparison
'' === false // false
'' === null // false
![]() |
|||
73 | return false; |
||
74 | } |
||
75 | |||
76 | // cd to the site root |
||
77 | $command[] = 'cd ' . escapeshellarg( Path::get_root() ); |
||
0 ignored issues
–
show
Coding Style
Comprehensibility
introduced
by
$command was never initialized. Although not strictly required by PHP, it is generally a good practice to add $command = array(); before regardless.
Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code. Let’s take a look at an example: foreach ($collection as $item) {
$myArray['foo'] = $item->getFoo();
if ($item->hasBar()) {
$myArray['bar'] = $item->getBar();
}
// do something with $myArray
}
As you can see in this example, the array This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop. ![]() |
|||
78 | |||
79 | // Run the zip command with the recursive and quiet flags |
||
80 | $command[] = '&& ' . escapeshellcmd( $this->get_zip_executable_path() ) . ' -rq'; |
||
81 | |||
82 | // Save the zip file to the correct path |
||
83 | $command[] = escapeshellarg( $this->get_backup_filepath() ) . ' ./'; |
||
84 | |||
85 | // Pass exclude rules in if we have them |
||
86 | if ( $this->get_exclude_string() ) { |
||
87 | $command[] = '-x ' . $this->get_exclude_string(); |
||
88 | } |
||
89 | |||
90 | $command = implode( ' ', $command ); |
||
91 | |||
92 | $process = new Process( $command ); |
||
93 | $process->setTimeout( HOUR_IN_SECONDS ); |
||
94 | |||
95 | try { |
||
96 | $process->run(); |
||
97 | } catch ( \Exception $e ) { |
||
98 | $this->error( __CLASS__, $e->getMessage() ); |
||
99 | } |
||
100 | |||
101 | if ( ! $process->isSuccessful() ) { |
||
102 | |||
103 | /** |
||
104 | * Exit Code 18 is returned when an unreadable file is encountered during the zip process. |
||
105 | * |
||
106 | * Given the zip process still completes correctly and the unreadable file is simple skipped |
||
107 | * we don't want to treat 18 as an actual error. |
||
108 | */ |
||
109 | if ( $process->getExitCode() !== 18 ) { |
||
110 | $this->error( __CLASS__, $process->getErrorOutput() ); |
||
111 | } |
||
112 | } |
||
113 | |||
114 | return $this->verify_backup(); |
||
115 | |||
116 | } |
||
117 | |||
118 | /** |
||
119 | * Convert the exclude rules to a format zip accepts |
||
120 | * |
||
121 | * @return string The exclude string ready to pass to `zip -x` |
||
122 | */ |
||
123 | public function get_exclude_string() { |
||
124 | |||
125 | if ( ! $this->excludes ) { |
||
0 ignored issues
–
show
The expression
$this->excludes of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using ![]() |
|||
126 | return ''; |
||
127 | } |
||
128 | |||
129 | $excludes = $this->excludes->get_excludes(); |
||
0 ignored issues
–
show
|
|||
130 | |||
131 | foreach ( $excludes as $key => &$rule ) { |
||
132 | |||
133 | $file = $absolute = $fragment = false; |
||
134 | |||
135 | // Files don't end with / |
||
136 | if ( ! in_array( substr( $rule, - 1 ), array( '\\', '/' ) ) ) { |
||
137 | $file = true; |
||
138 | } // If rule starts with a / then treat as absolute path |
||
139 | View Code Duplication | elseif ( in_array( substr( $rule, 0, 1 ), array( '\\', '/' ) ) ) { |
|
140 | $absolute = true; |
||
141 | } // Otherwise treat as dir fragment |
||
142 | else { |
||
143 | $fragment = true; |
||
144 | } |
||
145 | |||
146 | $rule = str_ireplace( Path::get_root(), '', untrailingslashit( wp_normalize_path( $rule ) ) ); |
||
147 | |||
148 | // Strip the preceeding slash |
||
149 | View Code Duplication | if ( in_array( substr( $rule, 0, 1 ), array( '\\', '/' ) ) ) { |
|
150 | $rule = substr( $rule, 1 ); |
||
151 | } |
||
152 | |||
153 | // Wrap directory fragments and files in wildcards for zip |
||
154 | if ( $fragment || $file ) { |
||
155 | $rule = '*' . $rule . '*'; |
||
156 | } |
||
157 | |||
158 | // Add a wildcard to the end of absolute url for zips |
||
159 | if ( $absolute ) { |
||
160 | $rule .= '*'; |
||
161 | } |
||
162 | } |
||
163 | |||
164 | // Escape shell args for zip command |
||
165 | $excludes = array_map( 'escapeshellarg', array_unique( $excludes ) ); |
||
166 | |||
167 | return implode( ' -x ', $excludes ); |
||
168 | |||
169 | } |
||
170 | } |
||
171 |
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountId
that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theid
property of an instance of theAccount
class. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.