PluginProbe
WP Smart Import : Import any XML File to WordPress / trunk
WP Smart Import : Import any XML File to WordPress vtrunk
2.0.0 trunk 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6
wp-smart-import / includes / upload.php

upload.php in WP Smart Import : Import any XML File to WordPress trunk, at includes/upload.php

265 lines 10.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if (!defined('ABSPATH')) { exit; }
3 if(!class_exists('wpSmartImportUpload')){
4 class wpSmartImportUpload {
5
6 static function wpsi_file_upload() {
7 // Check for Security if current request Not from ajax Or nonce is not match die this request
8 $rnonce = isset( $_REQUEST['_nonce'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['_nonce'] ) ) : '';
9 if ( ! wp_verify_nonce( $rnonce, 'wpsi_nonce' ) ) {
10 wp_die( esc_html__( 'Security check failed. Please try again.', 'wp-smart-import' ) );
11 }
12 wpSmartImportCommon::verify_ajax( $rnonce );
13 $response = array('response' => "ERROR", 'msg' => 'File Not Found');
14 $extension_array = array('xml');
15 $upload_dir = wp_upload_dir();
16 $wpsi_fd_path = $upload_dir["basedir"]. "/". wpSmartImport::getVar('folder_name') . "/";
17 $request = wpsi_helper::recursive_sanitize_text_field($_POST);
18 if (isset($request['file_from']) && $request['file_from'] == 'download') {
19 $file = esc_url_raw($request['file']);
20 preg_match( '/[^\?]+\.(xml)\b/i', $file, $matches );
21
22 if ( ! $matches ) {
23 $response['msg'] = "File url is not valid";
24 echo json_encode( $response );
25 wp_die();
26 }
27 // check remote file is Exist and responce code == 200
28 if (wp_remote_retrieve_response_code(wp_safe_remote_get($file)) == 200) {
29 $path = explode("?", $file);
30 $file_data = pathinfo(trim($path[0]));
31 $file_name = sanitize_file_name(str_replace(" ", "_", basename($path[0])));
32 if (isset($file_data['extension']) && in_array($file_data['extension'], $extension_array)) {
33 $new_folder = uniqid();
34 $destination = $wpsi_fd_path. $new_folder ."/";
35 if (!file_exists($destination)) {
36 // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_mkdir
37 mkdir($destination, 0777, true);
38 }
39 $destination_path = $destination.$file_name;
40 $status = self::download_file($file, $destination_path);
41 if ($status) {
42 $file_size = filesize($destination_path);
43 $response = array(
44 'response' => "SUCCESS",
45 'msg' => "File is Ready to use",
46 'filename' => $file_name,
47 'file_size' => self::format_size_units($file_size),
48 'type' => $file_data['extension'],
49 'filepath' => $new_folder.'/'.$file_name
50 );
51 } else {
52 $response['msg'] = "File Download Error";
53 }
54 } else {
55 $response['msg'] = "File is Not Valid" ;
56 }
57 }
58 } else {
59 $fileErrors = array(
60 0 => 'There is no error, the file uploaded with success',
61 1 => 'The uploaded file exceeds the upload_max_filesize directive in php.ini',
62 2 => 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form',
63 3 => 'The uploaded file was only partially uploaded',
64 4 => 'No file was uploaded',
65 6 => 'Missing a temporary folder',
66 7 => 'Failed to write file to disk.',
67 8 => 'A PHP extension stopped the file upload.',
68 );
69 $file_data = isset($_FILES) ? $_FILES : array();
70 $data = array_merge($_REQUEST, $file_data);
71
72 if (!empty($data) && is_array($data)) {
73 global $wp_filesystem;
74
75 if (empty($wp_filesystem)) {
76 require_once ABSPATH . '/wp-admin/includes/file.php';
77 WP_Filesystem();
78 }
79
80 // Check if WP_Filesystem initialization was successful
81 if (!$wp_filesystem) {
82 // WP_Filesystem initialization failed, handle error
83 $response['msg'] = "Failed to initialize WP_Filesystem";
84 $response["response"] = "ERROR";
85 } else {
86 // WP_Filesystem initialization successful, proceed with file operations
87 $xml_temp_file = $data['wpsi_file_upload']['tmp_name'];
88
89 // Check if the file exists
90 if ($wp_filesystem->exists($xml_temp_file)) {
91 // Fetch the file contents
92 $xml_content = $wp_filesystem->get_contents($xml_temp_file);
93
94 // Sanitize XML content
95 $sanitized_xml_content = self::sanitize_xml($xml_content);
96
97 // Extract file information
98 $f_data = pathinfo($data['wpsi_file_upload']['name']);
99
100 // Check if file extension is valid
101 if (isset($f_data['extension']) && in_array($f_data['extension'], $extension_array)) {
102 $new_folder = uniqid();
103 $upload_path = $wpsi_fd_path . $new_folder . "/";
104
105 // Create the upload directory using WP_Filesystem
106 if (!$wp_filesystem->is_dir($upload_path)) {
107 $wp_filesystem->mkdir($upload_path, 0777);
108 }
109
110 // Prepare sanitized file name
111 $fileName = sanitize_file_name(str_replace(" ", "_", $data["wpsi_file_upload"]["name"]));
112
113 // Define target path
114 $targetPath = $upload_path . $fileName;
115
116 // Save the sanitized XML content to the target path using WP_Filesystem
117 if ($wp_filesystem->put_contents($targetPath, $sanitized_xml_content, FS_CHMOD_FILE) !== false) {
118 // File saving successful
119 $response['msg'] = "File Ready to run";
120 $response["response"] = "SUCCESS";
121 $response["filename"] = $fileName;
122 $response["filepath"] = $new_folder . '/' . $fileName;
123 $response["file_size"] = self::format_size_units($wp_filesystem->size($targetPath));
124 $response["type"] = $f_data['extension']; // Assuming you want to include the file extension
125 } else {
126 // Error occurred while saving the file
127 $response["response"] = "ERROR";
128 $response["msg"] = "Failed to save the file.";
129 }
130 } else {
131 // Invalid file extension
132 $response['msg'] = "File extension is not valid";
133 $response["response"] = "ERROR";
134 }
135 } else {
136 // File does not exist
137 $response['msg'] = "File does not exist";
138 $response["response"] = "ERROR";
139 }
140 }
141 } else {
142 // No valid data found
143 $response['msg'] = "No valid data found";
144 }
145 }
146 echo json_encode( $response );
147 wp_die();
148 }
149
150 static function sanitize_xml($xml_content) {
151 // Load XML securely
152 $dom = new DOMDocument();
153 $dom->recover = true; // Enable recovery mode to handle parsing errors gracefully
154 $dom->strictErrorChecking = false; // Disable strict error checking to prevent errors on malformed XML
155
156 $prev_errors_setting = libxml_use_internal_errors(true);
157 $dom->loadXML( $xml_content, LIBXML_PARSEHUGE );
158
159 // Check for parsing errors
160 if (libxml_get_last_error() !== false) {
161 // Log or handle parsing errors
162 // error_log("XML sanitization error: " . libxml_get_last_error()->message);
163 libxml_clear_errors();
164 libxml_use_internal_errors($prev_errors_setting);
165 return false;
166 }
167 libxml_use_internal_errors($prev_errors_setting);
168
169 // Remove script elements, including namespaced and nested ones
170 $xpath = new DOMXPath($dom);
171 $scripts = $xpath->query('//script | //*[namespace-uri() != "" and local-name() = "script"]');
172 foreach ($scripts as $script) {
173 $script->parentNode->removeChild($script);
174 }
175
176 // Remove JavaScript event attributes
177 foreach ($xpath->query('//@*[starts-with(name(), "on")]') as $attr) {
178 $attr->ownerElement->removeAttributeNode($attr);
179 }
180
181 // Encode user-controlled data (attributes and text content)
182 $nodes = $dom->getElementsByTagName('*');
183 foreach ($nodes as $node) {
184 foreach ($node->attributes as $attr) {
185 $attr->value = htmlspecialchars( $attr->value, ENT_QUOTES | ENT_XML1, 'UTF-8' );
186 }
187 if ($node->nodeType === XML_TEXT_NODE) {
188 $node->nodeValue = htmlspecialchars( $node->nodeValue, ENT_QUOTES | ENT_XML1, 'UTF-8' );
189 }
190 }
191
192 // Return sanitized XML content
193 return $dom->saveXML();
194 }
195
196
197 /**
198 * Download helper to download files in chunks and save it.
199 *
200 * @param string $srcName Source Path/URL to the file you want to download
201 * @param string $dstName Destination Path to save your file
202 * @param integer $chunkSize (Optional) How many bytes to download per chunk (In MB). Defaults to 1 MB.
203 * @param boolean $returnbytes (Optional) Return number of bytes saved. Default: true
204 *
205 * @return integer Returns number of bytes delivered.
206 */
207 static function download_file($srcName, $dstName, $chunkSize = 1, $returnbytes = true) {
208 $chunksize = $chunkSize*(1024*1024); // How many bytes per chunk
209 $data = '';
210 $bytesCount = 0;
211 $handle = fopen($srcName, 'rb'); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen
212 $fp = fopen($dstName, 'w'); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen
213 if ($handle === false) {
214 return false;
215 }
216 while (!feof($handle)) {
217 $data = fread($handle, $chunksize); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fread
218 if (fwrite($fp, $data, strlen($data)) == false){ // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fwrite
219 return false;
220 }
221
222 if ($returnbytes) {
223 $bytesCount += strlen($data);
224 }
225 }
226 $status = fclose($handle); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose
227 fclose($fp); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose
228
229 if ($status && file_exists($dstName)) {
230 $file_content = file_get_contents($dstName);
231 $sanitized_content = self::sanitize_xml($file_content);
232 if ($sanitized_content !== false) {
233 file_put_contents($dstName, $sanitized_content);
234 }
235 }
236
237 if ($returnbytes && $status) {
238 return $bytesCount; // Return number of bytes delivered like readfile() does.
239 }
240 return $status;
241 }
242
243 static function format_size_units($bytes) {
244 if ($bytes >= 1073741824) {
245 $bytes = number_format($bytes / 1073741824, 2) . ' GB';
246 }
247 elseif ($bytes >= 1048576) {
248 $bytes = number_format($bytes / 1048576, 2) . ' MB';
249 }
250 elseif ($bytes >= 1024) {
251 $bytes = number_format($bytes / 1024, 2) . ' KB';
252 }
253 elseif ($bytes > 1) {
254 $bytes = $bytes . ' bytes';
255 }
256 elseif ($bytes == 1) {
257 $bytes = $bytes . ' byte';
258 }
259 else{
260 $bytes = '0 bytes';
261 }
262 return $bytes;
263 }
264 }
265 }