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();
+