Example #1
0
 /**
  * Handle menu uploads and downloads.
  * This is a callback for the 'admin_menu_editor_header' action.
  * 
  * @param string $action
  * @return void
  */
 function menu_editor_header($action = '')
 {
     $wp_menu_editor = $this->wp_menu_editor;
     //Handle menu download requests
     if ($action == 'download_menu') {
         $export = $this->get_exported_menu();
         if (empty($export['menu']) || empty($export['filename'])) {
             die("Exported data not found");
         }
         //Force file download
         header("Content-Description: File Transfer");
         header('Content-Disposition: attachment; filename="' . $export['filename'] . '"');
         header("Content-Type: application/force-download");
         header("Content-Transfer-Encoding: binary");
         header("Content-Length: " . strlen($export['menu']));
         /* The three lines below basically make the download non-cacheable */
         header("Cache-control: private");
         header("Pragma: private");
         header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
         echo $export['menu'];
         die;
         //Handle menu uploads
     } elseif ($action == 'upload_menu') {
         header('Content-Type: text/html');
         if (empty($_FILES['menu'])) {
             echo $wp_menu_editor->json_encode(array('error' => "No file specified"));
             die;
         }
         $file_data = $_FILES['menu'];
         if (filesize($file_data['tmp_name']) > $this->export_settings['max_file_size']) {
             $this->output_for_jquery_form($wp_menu_editor->json_encode(array('error' => "File too big")));
             die;
         }
         //Check for general upload errors.
         if ($file_data['error'] != UPLOAD_ERR_OK) {
             switch ($file_data['error']) {
                 case UPLOAD_ERR_INI_SIZE:
                     $message = sprintf('The uploaded file exceeds the upload_max_filesize directive in php.ini. Limit: %s', strval(ini_get('upload_max_filesize')));
                     break;
                 case UPLOAD_ERR_FORM_SIZE:
                     $message = "The uploaded file exceeds the internal file size limit. Please contact the developer.";
                     break;
                 case UPLOAD_ERR_PARTIAL:
                     $message = "The file was only partially uploaded";
                     break;
                 case UPLOAD_ERR_NO_FILE:
                     $message = "No file was uploaded";
                     break;
                 case UPLOAD_ERR_NO_TMP_DIR:
                     $message = "Missing a temporary folder";
                     break;
                 case UPLOAD_ERR_CANT_WRITE:
                     $message = "Failed to write file to disk";
                     break;
                 case UPLOAD_ERR_EXTENSION:
                     $message = "File upload stopped by a PHP extension";
                     break;
                 default:
                     $message = 'Unknown upload error #' . $file_data['error'];
                     break;
             }
             $this->output_for_jquery_form($wp_menu_editor->json_encode(array('error' => $message)));
             die;
         }
         $file_contents = file_get_contents($file_data['tmp_name']);
         //Check if this file could plausibly contain an exported menu
         if (strpos($file_contents, $this->export_settings['old_format_string']) !== false) {
             //This is an exported menu in the old format.
             $data = $wp_menu_editor->json_decode($file_contents, true);
             if (!(isset($data['menu']) && is_array($data['menu']))) {
                 $this->output_for_jquery_form($wp_menu_editor->json_encode(array('error' => "Unknown or corrupted file format")));
                 die;
             }
             try {
                 $menu = ameMenu::load_array($data['menu'], false, true);
             } catch (InvalidMenuException $ex) {
                 $this->output_for_jquery_form($wp_menu_editor->json_encode(array('error' => $ex->getMessage())));
                 die;
             }
         } else {
             if (strpos($file_contents, ameMenu::format_name) !== false) {
                 //This is an export file in the new format.
                 try {
                     $menu = ameMenu::load_json($file_contents, false, true);
                 } catch (InvalidMenuException $ex) {
                     $this->output_for_jquery_form($wp_menu_editor->json_encode(array('error' => $ex->getMessage())));
                     die;
                 }
             } else {
                 //This is an unknown file.
                 $this->output_for_jquery_form($wp_menu_editor->json_encode(array('error' => "Unknown file format")));
                 die;
             }
         }
         //Merge the imported menu with the current one.
         $menu['tree'] = $wp_menu_editor->menu_merge($menu['tree']);
         //Everything looks okay, send back the menu data
         $this->output_for_jquery_form(ameMenu::to_json($menu));
         die;
     }
 }
 private function handle_form_submission($post, $action = '')
 {
     if ($action == 'save_menu') {
         //Save the admin menu configuration.
         if (isset($post['data'])) {
             check_admin_referer('menu-editor-form');
             //Try to decode a menu tree encoded as JSON
             $url = remove_query_arg(array('noheader'));
             try {
                 $menu = ameMenu::load_json($post['data'], true);
             } catch (InvalidMenuException $ex) {
                 $debugData = '';
                 $debugData .= "Exception:\n" . $ex->getMessage() . "\n\n";
                 $debugData .= "Used POST data:\n" . print_r($this->post, true) . "\n\n";
                 $debugData .= "Original POST:\n" . print_r($this->originalPost, true) . "\n\n";
                 $debugData .= "\$_POST global:\n" . print_r($_POST, true);
                 $debugData = sprintf("<textarea rows=\"30\" cols=\"100\">%s</textarea>", htmlentities($debugData));
                 wp_die("Error: Failed to decode menu data!<br><br>\n" . "Please send this debugging information to the developer: <br>" . $debugData);
                 return;
             }
             //Sanitize menu item properties.
             $menu['tree'] = ameMenu::sanitize($menu['tree']);
             //Discard capabilities that refer to unregistered post types or taxonomies.
             if (!empty($menu['granted_capabilities'])) {
                 $capFilter = new ameGrantedCapabilityFilter();
                 $menu['granted_capabilities'] = $capFilter->clean_up($menu['granted_capabilities']);
             }
             //Save the custom menu
             $this->set_custom_menu($menu);
             //Redirect back to the editor and display the success message.
             //Also, automatically select the last selected actor (convenience feature).
             $query = array('message' => 1);
             if (isset($post['selected_actor']) && !empty($post['selected_actor'])) {
                 $query['selected_actor'] = rawurlencode(strval($post['selected_actor']));
             }
             wp_redirect(add_query_arg($query, $url));
             die;
         } else {
             $message = "Failed to save the menu. ";
             if (isset($this->post['data_length']) && is_numeric($this->post['data_length'])) {
                 $message .= sprintf('Expected to receive %d bytes of menu data in $_POST[\'data\'], but got nothing.', intval($this->post['data_length']));
             }
             wp_die($message);
         }
     } else {
         if ($action == 'save_settings') {
             //Save overall plugin configuration (permissions, etc).
             check_admin_referer('save_settings');
             //Plugin access setting.
             $valid_access_settings = array('super_admin', 'manage_options');
             //On Multisite only Super Admins can choose the "Only the current user" option.
             if (!is_multisite() || is_super_admin()) {
                 $valid_access_settings[] = 'specific_user';
             }
             if (isset($this->post['plugin_access']) && in_array($this->post['plugin_access'], $valid_access_settings)) {
                 $this->options['plugin_access'] = $this->post['plugin_access'];
                 if ($this->options['plugin_access'] === 'specific_user') {
                     $this->options['allowed_user_id'] = get_current_user_id();
                 } else {
                     $this->options['allowed_user_id'] = null;
                 }
             }
             //Whether to hide the plugin on the "Plugins" admin page.
             if (!is_multisite() || is_super_admin()) {
                 if (!empty($this->post['hide_plugin_from_others'])) {
                     $this->options['plugins_page_allowed_user_id'] = get_current_user_id();
                 } else {
                     $this->options['plugins_page_allowed_user_id'] = null;
                 }
             }
             //Configuration scope. The Super Admin is the only one who can change it since it affects all sites.
             if (is_multisite() && is_super_admin()) {
                 $valid_scopes = array('global', 'site');
                 if (isset($this->post['menu_config_scope']) && in_array($this->post['menu_config_scope'], $valid_scopes)) {
                     $this->options['menu_config_scope'] = $this->post['menu_config_scope'];
                 }
             }
             //Security logging.
             $this->options['security_logging_enabled'] = !empty($this->post['security_logging_enabled']);
             //Hide some menu options by default.
             $this->options['hide_advanced_settings'] = !empty($this->post['hide_advanced_settings']);
             //Enable the now-obsolete "Hide" button.
             if ($this->is_pro_version()) {
                 $this->options['show_deprecated_hide_button'] = !empty($this->post['show_deprecated_hide_button']);
             }
             //Menu editor colour scheme.
             if (!empty($this->post['ui_colour_scheme'])) {
                 $valid_colour_schemes = array('classic', 'wp-grey', 'modern-one');
                 $scheme = strval($this->post['ui_colour_scheme']);
                 if (in_array($scheme, $valid_colour_schemes)) {
                     $this->options['ui_colour_scheme'] = $scheme;
                 }
             }
             //Enable submenu icons.
             if (!empty($this->post['submenu_icons_enabled'])) {
                 $submenu_icons_enabled = strval($this->post['submenu_icons_enabled']);
                 $valid_icon_settings = array('never', 'if_custom', 'always');
                 if (in_array($submenu_icons_enabled, $valid_icon_settings, true)) {
                     $this->options['submenu_icons_enabled'] = $submenu_icons_enabled;
                 }
             }
             //Where to put new or unused menu items.
             if (!empty($this->post['unused_item_position'])) {
                 $unused_item_position = strval($this->post['unused_item_position']);
                 $valid_position_settings = array('relative', 'bottom');
                 if (in_array($unused_item_position, $valid_position_settings, true)) {
                     $this->options['unused_item_position'] = $unused_item_position;
                 }
             }
             //How verbose "access denied" errors should be.
             if (!empty($this->post['error_verbosity'])) {
                 $error_verbosity = intval($this->post['error_verbosity']);
                 $valid_verbosity_levels = array(self::VERBOSITY_LOW, self::VERBOSITY_NORMAL, self::VERBOSITY_VERBOSE);
                 if (in_array($error_verbosity, $valid_verbosity_levels)) {
                     $this->options['error_verbosity'] = $error_verbosity;
                 }
             }
             $this->save_options();
             wp_redirect(add_query_arg('updated', 1, $this->get_settings_page_url()));
         }
     }
 }
 private function handle_form_submission($post, $action = '')
 {
     if ($action == 'save_menu') {
         //Save the admin menu configuration.
         if (isset($post['data'])) {
             check_admin_referer('menu-editor-form');
             //Try to decode a menu tree encoded as JSON
             $url = remove_query_arg(array('noheader'));
             try {
                 $menu = ameMenu::load_json($post['data'], true);
             } catch (InvalidMenuException $ex) {
                 //Or redirect & display the error message
                 wp_redirect(add_query_arg('message', 2, $url));
                 die;
             }
             //Save the custom menu
             $this->set_custom_menu($menu);
             //Redirect back to the editor and display the success message.
             //Also, automatically select the last selected actor (convenience feature).
             $query = array('message' => 1);
             if (isset($post['selected_actor']) && !empty($post['selected_actor'])) {
                 $query['selected_actor'] = rawurlencode(strval($post['selected_actor']));
             }
             wp_redirect(add_query_arg($query, $url));
             die;
         } else {
             $message = "Failed to save the menu. ";
             if (isset($this->post['data_length']) && is_numeric($this->post['data_length'])) {
                 $message .= sprintf('Expected to receive %d bytes of menu data in $_POST[\'data\'], but got nothing.', intval($this->post['data_length']));
             }
             wp_die($message);
         }
     } else {
         if ($action == 'save_settings') {
             //Save overall plugin configuration (permissions, etc).
             check_admin_referer('save_settings');
             //Plugin access setting.
             $valid_access_settings = array('super_admin', 'manage_options');
             //On Multisite only Super Admins can choose the "Only the current user" option.
             if (!is_multisite() || is_super_admin()) {
                 $valid_access_settings[] = 'specific_user';
             }
             if (isset($this->post['plugin_access']) && in_array($this->post['plugin_access'], $valid_access_settings)) {
                 $this->options['plugin_access'] = $this->post['plugin_access'];
                 if ($this->options['plugin_access'] === 'specific_user') {
                     $this->options['allowed_user_id'] = get_current_user_id();
                 } else {
                     $this->options['allowed_user_id'] = null;
                 }
             }
             //Whether to hide the plugin on the "Plugins" admin page.
             if (!is_multisite() || is_super_admin()) {
                 if (!empty($this->post['hide_plugin_from_others'])) {
                     $this->options['plugins_page_allowed_user_id'] = get_current_user_id();
                 } else {
                     $this->options['plugins_page_allowed_user_id'] = null;
                 }
             }
             //Configuration scope. The Super Admin is the only one who can change it since it affects all sites.
             if (is_multisite() && is_super_admin()) {
                 $valid_scopes = array('global', 'site');
                 if (isset($this->post['menu_config_scope']) && in_array($this->post['menu_config_scope'], $valid_scopes)) {
                     $this->options['menu_config_scope'] = $this->post['menu_config_scope'];
                 }
             }
             //Security logging.
             $this->options['security_logging_enabled'] = !empty($this->post['security_logging_enabled']);
             //Hide some menu options by default.
             $this->options['hide_advanced_settings'] = !empty($this->post['hide_advanced_settings']);
             //Enable the now-obsolete "Hide" button.
             if ($this->is_pro_version()) {
                 $this->options['show_deprecated_hide_button'] = !empty($this->post['show_deprecated_hide_button']);
             }
             //Menu editor colour scheme.
             if (!empty($this->post['ui_colour_scheme'])) {
                 $valid_colour_schemes = array('classic', 'wp-grey');
                 $scheme = strval($this->post['ui_colour_scheme']);
                 if (in_array($scheme, $valid_colour_schemes)) {
                     $this->options['ui_colour_scheme'] = $scheme;
                 }
             }
             //Enable submenu icons.
             if (!empty($this->post['submenu_icons_enabled'])) {
                 $submenu_icons_enabled = strval($this->post['submenu_icons_enabled']);
                 $valid_icon_settings = array('never', 'if_custom', 'always');
                 if (in_array($submenu_icons_enabled, $valid_icon_settings, true)) {
                     $this->options['submenu_icons_enabled'] = $submenu_icons_enabled;
                 }
             }
             $this->save_options();
             wp_redirect(add_query_arg('updated', 1, $this->get_settings_page_url()));
         }
     }
 }
            }
        } elseif ($second[$key] !== $value) {
            $difference[$key] = $value;
        }
    }
    return $difference;
}
add_action('admin_init', function () {
    global $wp_menu_editor;
    $menu = $wp_menu_editor->load_custom_menu();
    if (empty($menu)) {
        return;
    }
    $compressed = ameMenu::compress($menu);
    $loaded = ameMenu::load_json(ameMenu::to_json($compressed));
    $expected = ameMenu::load_json(ameMenu::to_json($menu));
    $diff1 = ame_test_array_diff_assoc_recursive($expected, $loaded);
    $diff2 = ame_test_array_diff_assoc_recursive($loaded, $expected);
    if (!empty($diff1) || !empty($diff2)) {
        header('X-AME-Test-Failed: compression', true, 500);
        echo "<h1>Test failed: Compression causes data loss!</h1>";
        echo "<p>Loading compressed and uncompressed versions of the same menu configuration produced different results.</p>";
        echo '<p>Keys that are missing or different in the compressed configuration (expected vs compressed):</p>';
        echo '<pre>';
        echo htmlentities(print_r($diff1, true));
        echo '</pre>';
        echo '<h2>Reverse diff (compressed vs expected):</h2>';
        echo '<pre>';
        echo htmlentities(print_r($diff2, true));
        echo '</pre>';
        exit;
 private function handle_form_submission($post, $action = '')
 {
     if ($action == 'save_menu') {
         if (isset($post['data'])) {
             check_admin_referer('menu-editor-form');
             //Try to decode a menu tree encoded as JSON
             $url = remove_query_arg(array('noheader'));
             try {
                 $menu = ameMenu::load_json($post['data'], true);
             } catch (InvalidMenuException $ex) {
                 //Or redirect & display the error message
                 wp_redirect(add_query_arg('message', 2, $url));
                 die;
             }
             //Save the custom menu
             $this->set_custom_menu($menu);
             //Redirect back to the editor and display the success message
             wp_redirect(add_query_arg('message', 1, $url));
             die;
         } else {
             $message = "Failed to save the menu. ";
             if (isset($this->post['data_length']) && is_numeric($this->post['data_length'])) {
                 $message .= sprintf('Expected to receive %d bytes of menu data in $_POST[\'data\'], but got nothing.', intval($this->post['data_length']));
             }
             wp_die($message);
         }
     }
 }
Example #6
0
 /**
  * Handle menu uploads and downloads.
  * This is a callback for the 'admin_menu_editor_header' action.
  * 
  * @param string $action
  * @return void
  */
 function menu_editor_header($action = '')
 {
     $wp_menu_editor = $this->wp_menu_editor;
     //Handle menu download requests
     if ($action == 'download_menu') {
         $export = $this->get_exported_menu();
         if (empty($export['menu']) || empty($export['filename'])) {
             die("Exported data not found");
         }
         //Force file download
         header("Content-Description: File Transfer");
         header('Content-Disposition: attachment; filename="' . $export['filename'] . '"');
         header("Content-Type: application/force-download");
         header("Content-Transfer-Encoding: binary");
         header("Content-Length: " . strlen($export['menu']));
         /* The three lines below basically make the download non-cacheable */
         header("Cache-control: private");
         header("Pragma: private");
         header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
         echo $export['menu'];
         die;
         //Handle menu uploads
     } elseif ($action == 'upload_menu') {
         header('Content-Type: text/html');
         if (empty($_FILES['menu'])) {
             echo $wp_menu_editor->json_encode(array('error' => "No file specified"));
             die;
         }
         $file_data = $_FILES['menu'];
         if (filesize($file_data['tmp_name']) > $this->export_settings['max_file_size']) {
             echo '<textarea cols="50" rows="5">', $wp_menu_editor->json_encode(array('error' => "File too big")), '</textarea>';
             die;
         }
         $file_contents = file_get_contents($file_data['tmp_name']);
         //Check if this file could plausibly contain an exported menu
         if (strpos($file_contents, $this->export_settings['old_format_string']) !== false) {
             //This is an exported menu in the old format.
             $data = $wp_menu_editor->json_decode($file_contents, true);
             if (!(isset($data['menu']) && is_array($data['menu']))) {
                 echo '<textarea cols="50" rows="5">', $wp_menu_editor->json_encode(array('error' => "Unknown or corrupted file format")), '</textarea>';
                 die;
             }
             try {
                 $menu = ameMenu::load_array($data['menu']);
             } catch (InvalidMenuException $ex) {
                 echo '<textarea cols="50" rows="5">', $wp_menu_editor->json_encode(array('error' => $ex->getMessage())), '</textarea>';
                 die;
             }
         } else {
             if (strpos($file_contents, ameMenu::format_name) !== false) {
                 //This is an export file in the new format.
                 try {
                     $menu = ameMenu::load_json($file_contents);
                 } catch (InvalidMenuException $ex) {
                     echo '<textarea cols="50" rows="5">', $wp_menu_editor->json_encode(array('error' => $ex->getMessage())), '</textarea>';
                     die;
                 }
             } else {
                 //This is an unknown file.
                 echo '<textarea cols="50" rows="5">', $wp_menu_editor->json_encode(array('error' => "Unknown file format")), '</textarea>';
                 die;
             }
         }
         //Merge the imported menu with the current one.
         $menu['tree'] = $wp_menu_editor->menu_merge($menu['tree']);
         //Everything looks okay, send back the menu data
         die('<textarea>' . ameMenu::to_json($menu) . '</textarea>');
     }
 }
 /**
  * Import admin menu configuration from a JSON file.
  *
  * ## OPTIONS
  *
  * <file>
  * : Import file name.
  *
  * @param array $args
  */
 public function import($args)
 {
     $fileName = $args[0];
     if (!is_readable($fileName)) {
         WP_CLI::error('The file doesn\'t exist or isn\'t readable.');
         return;
     }
     $json = file_get_contents($fileName);
     try {
         $loadedMenu = ameMenu::load_json($json);
     } catch (Exception $ex) {
         WP_CLI::error($ex->getMessage());
         return;
     }
     $menuEditor = $this->getMenuEditor();
     $menuEditor->set_custom_menu($loadedMenu);
     WP_CLI::success('Import completed.');
 }
Example #8
0
 private function handle_form_submission($post)
 {
     if (isset($post['data'])) {
         check_admin_referer('menu-editor-form');
         //Try to decode a menu tree encoded as JSON
         $url = remove_query_arg('noheader');
         try {
             $menu = ameMenu::load_json($post['data'], true);
         } catch (InvalidMenuException $ex) {
             //Or redirect & display the error message
             wp_redirect(add_query_arg('message', 2, $url));
             die;
         }
         //Save the custom menu
         $this->set_custom_menu($menu);
         //Redirect back to the editor and display the success message
         wp_redirect(add_query_arg('message', 1, $url));
         die;
     }
 }