diff --git a/wp-mat.php b/wp-mat.php index 1c6ebb88cb8d5f1f22413a3474bb37ecf5a83849..b6b94c07973f32c0dda66737faa852f9492292f5 100644 --- a/wp-mat.php +++ b/wp-mat.php @@ -14,92 +14,139 @@ if (!defined("WP_MAT_ENDPOINT")) { define("WP_MAT_ENDPOINT", "http://localhost:7111/api/cleanup"); } -// Check if the mime type is one of those we want to clean up. -// Use a blacklist, currently empty. Send everything by default -// except video. -function wp_mat_is_supported_mime_type($mimetype) { - if (substr($mimetype, 0, 6) === "video/") { - return false; +// This is generally useful for debugging. +if (!function_exists('wp_handle_upload_error')) { + function wp_handle_upload_error(&$file, $message) { + error_log("wp_handle_upload_error: ".$message); + return array( "error" => $message ); } - return true; } -// Make a POST request to the MAT service with the uploaded file and -// store the results into '$output_path'. -function wp_mat_issue_request($path, $mimetype, $output_path) { - $upfile = new CURLFile($path, $mimetype, 'input'); - - $curl = curl_init(); - curl_setopt($curl, CURLOPT_URL, WP_MAT_ENDPOINT); - curl_setopt($curl, CURLOPT_USERAGENT, 'Wordpress'); - curl_setopt($curl, CURLOPT_POST, true); - curl_setopt($curl, CURLOPT_POSTFIELDS, array( - "file" => $upfile, - "mime_type" => $mimetype, - )); - - if (($fp = fopen($output_path, "wb")) === false) { - throw new Exception("fopen error for filename $output_path"); +class WP_Mat { + + // Check if the mime type is one of those we want to clean up. + // Use a blacklist, currently empty. Send everything by default + // except video. + function is_supported_mime_type($mimetype) { + if (substr($mimetype, 0, 6) === "video/") { + return false; + } + return true; } - curl_setopt($curl, CURLOPT_FILE, $fp); - curl_setopt($curl, CURLOPT_BINARYTRANSFER, true); + + // Make a POST request to the MAT service with the uploaded file and + // store the results into '$output_path'. + function issue_cleanup_request($path, $mimetype, $output_path) { + $upfile = new CURLFile($path, $mimetype, 'input'); - $ret = curl_exec($curl); + $curl = curl_init(); + curl_setopt($curl, CURLOPT_URL, WP_MAT_ENDPOINT); + curl_setopt($curl, CURLOPT_USERAGENT, 'Wordpress'); + curl_setopt($curl, CURLOPT_POST, true); + curl_setopt($curl, CURLOPT_POSTFIELDS, array( + "file" => $upfile, + "mime_type" => $mimetype, + )); - fclose($fp); - curl_close($curl); + if (($fp = fopen($output_path, "wb")) === false) { + throw new Exception("fopen error for filename $output_path"); + } + curl_setopt($curl, CURLOPT_FILE, $fp); + curl_setopt($curl, CURLOPT_BINARYTRANSFER, true); + + $ret = curl_exec($curl); - return $ret; -} + fclose($fp); + curl_close($curl); -function wp_mat_handle_upload_prefilter($file) { - if (isset($file['error']) && $file['error']) { - return $file; + return $ret; } - // Autodetect MIME type if not passed by the browser. - if (!$file['type']) { - $file['type'] = mime_content_type($file['tmp_name']); - } + // Filter uploaded files before they are processed by Wordpress. + function handle_upload_prefilter($file) { + if (isset($file['error']) && $file['error']) { + return $file; + } + if (get_option('wpmat_disabled')) { + return $file; + } + + // Autodetect MIME type if not passed by the browser. + if (!$file['type']) { + $file['type'] = mime_content_type($file['tmp_name']); + } + + // Check if it's one of the MIME types we support. + if (!$this->is_supported_mime_type($file['type'])) { + error_log("wp-mat: unsupported mime type ".$file['type']); + return $file; + } + + // Issue a request to the MAT API, and if successful replace the + // file with the sanitized one. + $new_tmp_file = tempnam("", "wp_mat_"); + if ($this->issue_cleanup_request($file['tmp_name'], $file['type'], $new_tmp_file)) { + // Rename the cleaned up file to the original file, or WP + // will not pass the is_uploaded_file() check in wp_handle_upload(). + unlink($file['tmp_name']); + rename($new_tmp_file, $file['tmp_name']); + + $new_file = array( + "name" => $file['name'], + "type" => $file['type'], + "tmp_name" => $file['tmp_name'], + "size" => filesize($file['tmp_name']), + "error" => 0, + ); + error_log("wp-mat: successfully cleaned file=".json_encode($new_file)); + $file = $new_file; + } else { + error_log("wp-mat: server error for file=".json_encode($file)); + @unlink($new_tmp_file); + } - // Check if it's one of the MIME types we support. - if (!wp_mat_is_supported_mime_type($file['type'])) { - error_log("wp-mat: unsupported mime type ".$file['type']); return $file; } - // Issue a request to the MAT API, and if successful replace the - // file with the sanitized one. - $new_tmp_file = tempnam("", "wp_mat_"); - if (wp_mat_issue_request($file['tmp_name'], $file['type'], $new_tmp_file)) { - // Rename the cleaned up file to the original file, or WP - // will not pass the is_uploaded_file() check in wp_handle_upload(). - unlink($file['tmp_name']); - rename($new_tmp_file, $file['tmp_name']); - - $new_file = array( - "name" => $file['name'], - "type" => $file['type'], - "tmp_name" => $file['tmp_name'], - "size" => filesize($file['tmp_name']), - "error" => 0, + function settings_api_init() { + // Add the section to reading settings so we can add our + // fields to it. + add_settings_section( + 'wpmat_settings_section', + 'Metadata anonymization for uploads', + array($this, 'settings_section_callback'), + 'writing' + ); + + // Add the field with the names and function to use for our new + // settings, put it in our new section. + add_settings_field( + 'wpmat_disabled', + 'Disable metadata anonymization', + array($this, 'settings_field_callback'), + 'writing', + 'wpmat_settings_section' ); - error_log("wp-mat: successfully cleaned file=".json_encode($new_file)); - $file = $new_file; - } else { - error_log("wp-mat: server error for file=".json_encode($file)); - @unlink($new_tmp_file); + + // Register our setting so that $_POST handling is done for us and + // our callback function just has to echo the <input>. + register_setting('writing', 'wpmat_disabled'); } - return $file; -} + function settings_section_callback() { + echo('<p>Control whether uploaded files are run through metadata anonymization (using MAT2).</p>'); + } -add_filter('wp_handle_upload_prefilter', 'wp_mat_handle_upload_prefilter'); + function settings_field_callback() { + echo('<input name="wpmat_disabled" id="wpmat_disabled" type="checkbox" value="1" class="code" ' . checked(1, get_option('wpmat_disabled'), false) . ' /> <label for="wpmat_disabled">Disable metadata anonymization</label>'); + } -// This is generally useful for debugging. -if (!function_exists('wp_handle_upload_error')) { - function wp_handle_upload_error(&$file, $message) { - error_log("wp_handle_upload_error: ".$message); - return array( "error" => $message ); + function __construct() { + add_filter('wp_handle_upload_prefilter', array($this, 'handle_upload_prefilter')); + add_action('admin_init', array($this, 'settings_api_init')); } + } + +new WP_Mat(); +