wp-mat.php 5.73 KiB
<?php
/**
* Plugin Name: wp-mat
* Plugin URI: https://git.autistici.org/noblogs/wp-mat
* Description: Process uploaded files through MAT
* Version: 0.1.4
* Author: Autistici/Inventati
* Author URI: https://www.autistici.org/
* License: MIT
* License URI: http://opensource.org/licenses/MIT
*/
if (!defined("WP_MAT_ENDPOINT")) {
define("WP_MAT_ENDPOINT", "http://localhost:7111/api/cleanup");
}
// 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 );
}
}
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, and pdf.
function is_supported_mime_type($mimetype) {
if (substr($mimetype, 0, 6) === "video/") {
return false;
}
if ($mimetype === "application/pdf") {
return false;
}
return true;
}
// Make a POST request to the MAT service with the uploaded file and
// store the results into '$output_path'. Returns true on success,
// false on any error.
function issue_cleanup_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");
}
curl_setopt($curl, CURLOPT_FILE, $fp);
curl_setopt($curl, CURLOPT_BINARYTRANSFER, true);
$ret = curl_exec($curl);
if ($ret === false) {
error_log("wp-mat: curl error: ".curl_error($curl));
} else {
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
if ($status != 200) {
error_log("wp-mat: curl error: server returned HTTP status ".$status);
$ret = false;
}
}
fclose($fp);
curl_close($curl);
return $ret;
}
// 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);
}
return $file;
}
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'),
'media'
);
// 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'),
'media',
'wpmat_settings_section'
);
// Register our setting so that $_POST handling is done for us and
// our callback function just has to echo the <input>.
register_setting('media', 'wpmat_disabled');
}
function settings_section_callback() {
echo('<p>Control whether uploaded files are run through metadata anonymization (using <a href="https://0xacab.org/jvoisin/mat2">MAT2</a>). ');
echo('This feature is enabled by default but it can be disabled in case you are experiencing problems uploading files.</p>');
}
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>');
}
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();