Plugin Directory

Changeset 3425008


Ignore:
Timestamp:
12/22/2025 03:16:34 AM (3 months ago)
Author:
mtekk
Message:

Pre-7.5.1 tag commit

Location:
breadcrumb-navxt/trunk
Files:
15 edited

Legend:

Unmodified
Added
Removed
  • breadcrumb-navxt/trunk/breadcrumb-navxt.php

    r3411622 r3425008  
    44Plugin URI: http://mtekk.us/code/breadcrumb-navxt/
    55Description: Adds a breadcrumb navigation showing the visitor&#39;s path to their current location. For details on how to use this plugin visit <a href="http://mtekk.us/code/breadcrumb-navxt/">Breadcrumb NavXT</a>.
    6 Version: 7.5.0
     6Version: 7.5.1
    77Author: John Havlik
    88Author URI: http://mtekk.us/
     
    3434    function bcn_phpold()
    3535    {
    36         printf('<div class="notice notice-error"><p>' . esc_html__('Your PHP version is too old, please upgrade to a newer version. Your version is %1$s, Breadcrumb NavXT requires %2$s', 'breadcrumb-navxt') . '</p></div>', phpversion(), '5.6.0');
     36        /* translators: %1$s: User's version of PHP, %2$s: Breadcrmb NavXT minimuum PHP version */
     37        printf('<div class="notice notice-error"><p>' . esc_html__('Your PHP version is too old, please upgrade to a newer version. Your version is %1$s, Breadcrumb NavXT requires %2$s', 'breadcrumb-navxt') . '</p></div>', esc_html(phpversion()), '7.0.0');
    3738    }
    3839    //If we are in the admin, let's print a warning then return
     
    6465class breadcrumb_navxt
    6566{
    66     const version = '7.5.0';
     67    const version = '7.5.1';
    6768    protected $name = 'Breadcrumb NavXT';
    6869    protected $identifier = 'breadcrumb-navxt';
     
    355356        $settings['Hpaged_template'] = new setting\setting_html(
    356357                'paged_template',
     358                /* translators: %htitle%: The page title which may contain HTML */
    357359                sprintf('<span class="%%type%%">%1$s</span>', esc_attr__('Page %htitle%', 'breadcrumb-navxt')),
    358360                _x('Paged Template', 'Paged as in when on an archive or post that is split into multiple pages', 'breadcrumb-navxt'));
     
    372374                    'post_' . $post_type->name . '_template',
    373375                    bcn_breadcrumb::get_default_template(),
     376                    /* translators: %s: The singular name of the post type */
    374377                    sprintf(__('%s Template', 'breadcrumb-navxt'), $post_type->labels->singular_name));
    375378            $settings['Hpost_' . $post_type->name . '_template_no_anchor'] = new setting\setting_html(
    376379                    'post_' . $post_type->name . '_template_no_anchor',
    377380                    bcn_breadcrumb::default_template_no_anchor,
     381                    /* translators: %s: The singular name of the post type */
    378382                    sprintf(__('%s Template (Unlinked)', 'breadcrumb-navxt'), $post_type->labels->singular_name));
    379383            //Root default depends on post type
     
    393397                    'post_' . $post_type->name . '_root',
    394398                    $default_root,
     399                    /* translators: %s: The singular name of the post type */
    395400                    sprintf(__('%s Root Page', 'breadcrumb-navxt'), $post_type->labels->singular_name));
    396401            //Archive display default depends on post type
     
    406411                    'post_' . $post_type->name . '_archive_display',
    407412                    $default_archive_display,
     413                    /* translators: %s: The singular name of the post type */
    408414                    sprintf(__('%s Archive Display', 'breadcrumb-navxt'), $post_type->labels->singular_name));
    409415            $settings['bpost_' . $post_type->name . '_taxonomy_referer'] = new setting\setting_bool(
    410416                    'post_' . $post_type->name . '_taxonomy_referer',
    411417                    false,
     418                    /* translators: %s: The singular name of the post type */
    412419                    sprintf(__('%s Hierarchy Referer Influence', 'breadcrumb-navxt'), $post_type->labels->singular_name));
    413420            //Hierarchy use parent first depends on post type
     
    427434                    'post_' . $post_type->name . '_hierarchy_parent_first',
    428435                    $default_parent_first,
     436                    /* translators: %s: The singular name of the post type */
    429437                    sprintf(__('%s Hierarchy Use Parent First', 'breadcrumb-navxt'), $post_type->labels->singular_name));
    430438            //Hierarchy depends on post type
     
    470478                    'post_' . $post_type->name . '_hierarchy_display',
    471479                    $default_hierarchy_display,
     480                    /* translators: %s: The singular name of the post type */
    472481                    sprintf(__('%s Hierarchy Display', 'breadcrumb-navxt'), $post_type->labels->singular_name));
    473482            $settings['Epost_' . $post_type->name . '_hierarchy_type'] = new setting\setting_enum(
    474483                    'post_' . $post_type->name . '_hierarchy_type',
    475484                    $hierarchy_type_default,
     485                    /* translators: %s: The singular name of the post type */
    476486                    sprintf(__('%s Hierarchy Referer Influence', 'breadcrumb-navxt'), $post_type->labels->singular_name),
    477487                    false,
     
    484494            $settings['Htax_' . $taxonomy->name. '_template'] = new setting\setting_html(
    485495                    'tax_' . $taxonomy->name. '_template',
    486                     __(sprintf('<span property="itemListElement" typeof="ListItem"><a property="item" typeof="WebPage" title="Go to the %%title%% %s archives." href="%%link%%" class="%%type%%" bcn-aria-current><span property="name">%%htitle%%</span></a><meta property="position" content="%%position%%"></span>', $taxonomy->labels->singular_name), 'breadcrumb-navxt'),
     496                    /* translators: %s: The singular name of the taxonomy */
     497                    sprintf('<span property="itemListElement" typeof="ListItem"><a property="item" typeof="WebPage" title="%s" href="%%link%%" class="%%type%%" bcn-aria-current><span property="name">%%htitle%%</span></a><meta property="position" content="%%position%%"></span>', sprintf(esc_attr__('Go to the %%title%% %s archives.', 'breadcrumb-navxt'), $taxonomy->labels->singular_name)),
     498                    /* translators: %s: The singular name of the taxonomy */
    487499                    sprintf(__('%s Template', 'breadcrumb-navxt'), $taxonomy->labels->singular_name));
    488500            $settings['Htax_' . $taxonomy->name. '_template_no_anchor'] = new setting\setting_html(
    489501                    'tax_' . $taxonomy->name. '_template_no_anchor',
    490502                    bcn_breadcrumb::default_template_no_anchor,
     503                    /* translators: %s: The singular name of the taxonomy */
    491504                    sprintf(__('%s Template (Unlinked)', 'breadcrumb-navxt'), $taxonomy->labels->singular_name));
    492505        }
     
    503516                'search_template',
    504517                sprintf('<span property="itemListElement" typeof="ListItem"><span property="name">%1$s</span><meta property="position" content="%%position%%"></span>',
     518                        /* translators: %s: The searched phrase */
    505519                        sprintf(esc_attr__('Search results for &#39;%1$s&#39;', 'breadcrumb-navxt'),
    506520                                sprintf('<a property="item" typeof="WebPage" title="%1$s" href="%%link%%" class="%%type%%" bcn-aria-current>%%htitle%%</a>', esc_attr__('Go to the first page of search results for %title%.', 'breadcrumb-navxt')))),
     
    509523                'search_template_no_anchor',
    510524                sprintf('<span class="%%type%%">%1$s</span>',
     525                        /* translators: %s: The searched phrase */
    511526                        sprintf(esc_attr__('Search results for &#39;%1$s&#39;', 'breadcrumb-navxt'), '%htitle%')),
    512527                __('Search Template (Unlinked)', 'breadcrumb-navxt'));
     
    522537                'author_template',
    523538                sprintf('<span property="itemListElement" typeof="ListItem"><span property="name">%1$s</span><meta property="position" content="%%position%%"></span>',
     539                        /* translators: %s: The post author name the current archive is for */
    524540                        sprintf(esc_attr__('Articles by: %1$s', 'breadcrumb-navxt'),
    525541                                sprintf('<a title="%1$s" href="%%link%%" class="%%type%%" bcn-aria-current>%%htitle%%</a>', esc_attr__('Go to the first page of posts by %title%.', 'breadcrumb-navxt')))),
     
    528544                'author_template_no_anchor',
    529545                sprintf('<span class="%%type%%">%1$s</span>',
     546                        /* translators: %s: The post author name the current archive is for */
    530547                        sprintf(esc_attr__('Articles by: %1$s', 'breadcrumb-navxt'), '%htitle%')),
    531548                __('Author Template (Unlinked)', 'breadcrumb-navxt'));
     
    594611            //Generate the breadcrumb trail
    595612            $this->breadcrumb_trail->fill_REST($post);
    596             $trail_string = $this->breadcrumb_trail->display($linked, $reverse, $template);
     613            $trail_string_safe = $this->breadcrumb_trail->display($linked, $reverse, $template);
    597614            if($return)
    598615            {
    599                 return $trail_string;
     616                return $trail_string_safe;
    600617            }
    601618            else
    602619            {
    603                 //Helps track issues, please don't remove it
    604                 $credits = "<!-- Breadcrumb NavXT " . $this::version . " -->\n";
    605                 echo $credits . $trail_string;
     620                echo $trail_string_safe;
    606621            }
    607622        }
     
    673688        //Generate the breadcrumb trail
    674689        $this->breadcrumb_trail->fill($force);
    675         $trail_string = $this->breadcrumb_trail->display($linked, $reverse, $template, $outer_template);
     690        $trail_string_safe = $this->breadcrumb_trail->display($linked, $reverse, $template, $outer_template);
    676691        if($return)
    677692        {
    678             return $trail_string;
     693            return $trail_string_safe;
    679694        }
    680695        else
    681696        {
    682             //Helps track issues, please don't remove it
    683             $credits = "<!-- Breadcrumb NavXT " . $this::version . " -->\n";
    684             echo $credits . $trail_string;
     697            echo $trail_string_safe;
    685698        }
    686699    }
     
    722735        //Generate the breadcrumb trail
    723736        $this->breadcrumb_trail->fill($force);
    724         $trail_string = json_encode($this->breadcrumb_trail->display_json_ld($reverse), JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
     737        $trail_string_safe = wp_json_encode($this->breadcrumb_trail->display_json_ld($reverse), JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
    725738        if($return)
    726739        {
    727             return $trail_string;
     740            return $trail_string_safe;
    728741        }
    729742        else
    730743        {
    731             echo $trail_string;
     744            echo $trail_string_safe;
    732745        }
    733746    }
  • breadcrumb-navxt/trunk/class.bcn_admin.php

    r3411622 r3425008  
    2424    function bcn_phpold()
    2525    {
    26         printf('<div class="notice notice-error"><p>' . __('Your PHP version is too old, please upgrade to a newer version. Your version is %1$s, Breadcrumb NavXT requires %2$s', 'breadcrumb-navxt') . '</p></div>', phpversion(), '5.6.0');
     26        /* translators: %1$s: User's version of PHP, %2$s: Breadcrmb NavXT minimuum PHP version */
     27        printf('<div class="notice notice-error"><p>' . esc_html__('Your PHP version is too old, please upgrade to a newer version. Your version is %1$s, Breadcrumb NavXT requires %2$s', 'breadcrumb-navxt') . '</p></div>', esc_html(phpversion()), '7.0.0');
    2728    }
    2829    //If we are in the admin, let's print a warning then return
     
    6061     * @param array $settings The array of settings objects
    6162     */
    62     function __construct(array &$opts, $basename, array &$settings)
     63    public function __construct(array &$opts, $basename, array &$settings)
    6364    {
    6465        $this->plugin_basename = $basename;
     
    6970        parent::__construct();
    7071    }
    71     function is_network_admin()
     72    public function is_network_admin()
    7273    {
    7374        return false;
     
    7879     * @param array $opts The opts array
    7980     */
    80     function setting_merge($opts)
     81    public function setting_merge($opts)
    8182    {
    8283        $unknown = array();
     
    106107        {
    107108            $this->messages[] = new message(
    108                     sprintf(__('Found %u unknown legacy settings: %s','breadcrumb-navxt'), count($unknown), implode(', ', $unknown)),
     109                    /* translators: %u: Number of unknown legacy settings found, %s: comma separated list of the setting names */
     110                    sprintf(__('Found %1$u unknown legacy settings: %2$s','breadcrumb-navxt'), count($unknown), implode(', ', $unknown)),
    109111                    'warning',
    110112                    true,
     
    120122     * @return void
    121123     */
    122     function init()
     124    public function init()
    123125    {
    124126        //We're going to make sure we run the parent's version of this function as well
     
    132134     * @param string $version the version of the passed in options
    133135     */
    134     function opts_upgrade($opts, $version)
     136    public function opts_upgrade($opts, $version)
    135137    {
    136138        //If our version is not the same as in the db, time to update
     
    148150     * @param WP_Screen $screen The screen to add the help tab items to
    149151     */
    150     function help_contents(\WP_Screen &$screen)
     152    public function help_contents(\WP_Screen &$screen)
    151153    {
    152154        $general_tab = '<p>' . esc_html__('Tips for the settings are located below select options.', 'breadcrumb-navxt') .
     
    216218     * enqueue's the tab style sheet on the settings page
    217219     */
    218     function admin_styles()
     220    public function admin_styles()
    219221    {
    220222        wp_enqueue_style('mtekk_adminkit_tabs');
     
    223225     * enqueue's the tab js and translation js on the settings page
    224226     */
    225     function admin_scripts()
     227    public function admin_scripts()
    226228    {
    227229        //Enqueue ui-tabs
     
    242244     * A message function that checks for the BCN_SETTINGS_* define statement
    243245     */
    244     function multisite_settings_warn()
     246    public function multisite_settings_warn()
    245247    {
    246248        if(is_multisite())
     
    272274     * A message function that checks for deprecated settings that are set and warns the user
    273275     */
    274     function deprecated_settings_warn()
     276    public function deprecated_settings_warn()
    275277    {
    276278        //We're deprecating the limit title length setting, let the user know the new method of accomplishing this
     
    279281            $this->messages[] = new message(
    280282                    sprintf(
     283                            /* translators: %1$s: HTML opening tag for link to article, %2$s: HTML closing tag for link to article */
    281284                            esc_html__('Error: The deprecated setting "Title Length" (see Miscellaneous &gt; Deprecated) has no effect in this version Breadcrumb NavXT. Please %1$suse CSS instead%2$s.', 'breadcrumb-navxt'),
    282                             '<a title="' . __('Go to the guide on trimming breadcrumb title lengths with CSS', 'breadcrumb-navxt') . '" href="https://mtekk.us/archives/guides/trimming-breadcrumb-title-lengths-with-css/">', '</a>'),
     285                            '<a title="' . esc_attr__('Go to the guide on trimming breadcrumb title lengths with CSS', 'breadcrumb-navxt') . '" href="https://mtekk.us/archives/guides/trimming-breadcrumb-title-lengths-with-css/">', '</a>'),
    283286                    'error');
    284287        }
     
    306309                    $this->messages[] = new message(
    307310                            sprintf(
     311                                    /* translators: %1$s: Name of the deprecated template tag found, %2$s: Recommended replacement tag for the deprecated tag, %3$s: The setting name where the deprecated tag was found */
    308312                                    esc_html__('Error: The deprecated template tag %1$s found in setting %3$s. Please use %2$s instead.', 'breadcrumb-navxt'),
    309313                                    implode(' and ', $deprecated_tags),
     
    318322     * A message function that checks for post types added after the settings defaults were established
    319323     */
    320     function unknown_custom_types_warn()
     324    public function unknown_custom_types_warn()
    321325    {
    322326        foreach($GLOBALS['wp_post_types'] as $post_type)
     
    326330                $this->messages[] = new message(
    327331                        sprintf(
     332                            /* translators: %1$s: Export of the post_type object of the unexpected CPT */
    328333                            esc_html__('Error: WP_Post_Types global contains non WP_Post_Type object. Debug information: %1$s', 'breadcrumb-navxt'),
    329334                            var_export($post_type, true)),
     
    338343                $this->messages[] = new message(
    339344                        sprintf(
     345                                /* translators: %1$s: Post type singular name, %2$s: Post type name */
    340346                                esc_html__('Warning: The post type %1$s (%2$s) was registered after the Breadcrumb NavXT default settings. It will not show up in the settings.', 'breadcrumb-navxt'),
    341347                                $post_type->labels->singular_name,
     
    353359                $this->messages[] = new message(
    354360                        sprintf(
     361                                /* translators: %1$s: Export of the taxonomy object of the unexpected custom taxonomy */
    355362                                esc_html__('Error: WP_Taxonomies global contains non WP_Taxonomy object. Debug information: %1$s', 'breadcrumb-navxt'),
    356363                                var_export($taxonomy, true)),
     
    365372                $this->messages[] = new message(
    366373                        sprintf(
     374                                /* translators: %1$s: Taxonomy label, %2$s: Taxonomy name */
    367375                                esc_html__('Warning: The taxonomy %1$s (%2$s) was registered after the Breadcrumb NavXT default settings. It will not show up in the settings.', 'breadcrumb-navxt'),
    368376                                $taxonomy->label,
     
    379387     * @return boool Whether or not the blog options should be disabled
    380388     */
    381     function maybe_disable_blog_options()
     389    public function maybe_disable_blog_options()
    382390    {
    383391        return (get_option('show_on_front') !== 'page' || get_option('page_for_posts') < 1);
     
    388396     * @return bool Whether or not the mainsite options should be disabled
    389397     */
    390     function maybe_disable_mainsite_options()
     398    public function maybe_disable_mainsite_options()
    391399    {
    392400        return !is_multisite();
     
    395403     * The administrative page for Breadcrumb NavXT
    396404     */
    397     function admin_page()
     405    public function admin_page()
    398406    {
    399407        global $wp_taxonomies, $wp_post_types;
     
    432440        }
    433441        ?>
    434         <div class="wrap"><h1><?php echo $this->full_name; ?></h1>
     442        <div class="wrap"><h1><?php echo esc_html($this->full_name); ?></h1>
    435443        <?php
    436444        //We exit after the version check if there is an action the user needs to take before saving settings
     
    440448        }
    441449        ?>
    442         <form action="<?php echo $this->admin_url(); ?>" method="post" id="bcn_admin-options">
     450        <form action="<?php echo esc_attr($this->admin_url()); ?>" method="post" id="bcn_admin-options">
    443451            <?php settings_fields('bcn_options');?>
    444452            <div id="hasadmintabs">
    445453            <fieldset id="general" class="bcn_options">
    446                 <legend class="screen-reader-text" data-title="<?php _e( 'A collection of settings most likely to be modified are located under this tab.', 'breadcrumb-navxt' );?>"><?php _e( 'General', 'breadcrumb-navxt' ); ?></legend>
    447                 <h2><?php _e('General', 'breadcrumb-navxt'); ?></h2>
     454                <legend class="screen-reader-text" data-title="<?php esc_attr_e( 'A collection of settings most likely to be modified are located under this tab.', 'breadcrumb-navxt' );?>"><?php esc_html_e( 'General', 'breadcrumb-navxt' ); ?></legend>
     455                <h2><?php esc_html_e('General', 'breadcrumb-navxt'); ?></h2>
    448456                <table class="form-table">
    449457                    <?php
     
    452460                    ?>
    453461                </table>
    454                 <h2><?php _e('Current Item', 'breadcrumb-navxt'); ?></h2>
     462                <h2><?php esc_html_e('Current Item', 'breadcrumb-navxt'); ?></h2>
    455463                <table class="form-table adminkit-enset-top">
    456464                    <?php
     
    476484                    ?>
    477485                </table>
    478                 <h2><?php _e('Home Breadcrumb', 'breadcrumb-navxt'); ?></h2>
     486                <h2><?php esc_html_e('Home Breadcrumb', 'breadcrumb-navxt'); ?></h2>
    479487                <table class="form-table adminkit-enset-top">
    480488                    <?php
     
    500508                    ?>
    501509                </table>
    502                 <h2><?php _e('Blog Breadcrumb', 'breadcrumb-navxt'); ?></h2>
     510                <h2><?php esc_html_e('Blog Breadcrumb', 'breadcrumb-navxt'); ?></h2>
    503511                <table class="form-table adminkit-enset-top">
    504512                    <?php
     
    512520                    ?>
    513521                </table>
    514                 <h2><?php _e('Mainsite Breadcrumb', 'breadcrumb-navxt'); ?></h2>
     522                <h2><?php esc_html_e('Mainsite Breadcrumb', 'breadcrumb-navxt'); ?></h2>
    515523                <table class="form-table adminkit-enset-top">
    516524                    <?php
     
    539547            </fieldset>
    540548            <fieldset id="post" class="bcn_options">
    541                 <legend class="screen-reader-text" data-title="<?php _e( 'The settings for all post types (Posts, Pages, and Custom Post Types) are located under this tab.', 'breadcrumb-navxt' );?>"><?php _e( 'Post Types', 'breadcrumb-navxt' ); ?></legend>
     549                <legend class="screen-reader-text" data-title="<?php esc_attr_e( 'The settings for all post types (Posts, Pages, and Custom Post Types) are located under this tab.', 'breadcrumb-navxt' );?>"><?php esc_html_e( 'Post Types', 'breadcrumb-navxt' ); ?></legend>
    542550            <?php
    543551            //Loop through all of the post types in the array
     
    551559                $singular_name_lc = mb_strtolower($post_type->labels->singular_name, 'UTF-8');
    552560                ?>
    553                 <h2><?php echo $post_type->labels->singular_name; ?></h2>
     561                <h2><?php echo esc_html($post_type->labels->singular_name); ?></h2>
    554562                <table class="form-table adminkit-enset-top">
    555563                    <?php
     
    558566                                '6',
    559567                                false,
     568                                /* translators: %s: Singular name for the CPT */
    560569                                sprintf(__('The template for %s breadcrumbs.', 'breadcrumb-navxt'), $singular_name_lc) . $overridden['Hpost_' . $post_type->name . '_template'],
    561570                                $overridden_style['Hpost_' . $post_type->name . '_template']);
     
    564573                                '4',
    565574                                false,
     575                                /* translators: %s: Singular name for the CPT */
    566576                                sprintf(__('The template for %s breadcrumbs, used only when the breadcrumb is not linked.', 'breadcrumb-navxt'), $singular_name_lc) . $overridden['Hpost_' . $post_type->name . '_template_no_anchor'],
    567577                                $overridden_style['Hpost_' . $post_type->name . '_template_no_anchor']);
     
    571581                    ?>
    572582                    <tr valign="top">
    573                         <th scope="row">
    574                             <label for="<?php echo $optid;?>"><?php printf(esc_html__('%s Root Page', 'breadcrumb-navxt'), $post_type->labels->singular_name);?></label>
     583                        <th scope="row"><?php /* translators: %s: Singular name for the CPT */ ?>
     584                            <label for="<?php echo esc_attr($optid);?>"><?php printf(esc_html__('%s Root Page', 'breadcrumb-navxt'), esc_html($post_type->labels->singular_name));?></label>
    575585                        </th>
    576586                        <td>
     
    580590                                            'id' => $optid,
    581591                                            'echo' => 1,
    582                                             'show_option_none' => __( '&mdash; Select &mdash;' ),
     592                                            'show_option_none' => esc_attr__('&mdash; Select &mdash;', 'breadcrumb-navxt'),
    583593                                            'option_none_value' => '0',
    584594                                            'selected' => $this->settings['apost_' . $post_type->name . '_root']->get_value(),
     
    588598                            if(isset($overridden['apost_' . $post_type->name . '_root']) && $overridden['apost_' . $post_type->name . '_root'] !== '')
    589599                            {
    590                                 printf('<p class="description">%s</p>', $overridden['apost_' . $post_type->name . '_root']);
     600                                printf('<p class="description">%s</p>', esc_html($overridden['apost_' . $post_type->name . '_root']));
    591601                            }
    592602                            ?>
     
    594604                    </tr>
    595605                    <?php
    596                             $this->form->input_check(
     606                        $this->form->input_check(
    597607                                    $this->settings['bpost_' . $post_type->name . '_archive_display'],
     608                                    /* translators: %s: Post type singlar name */
    598609                                    sprintf(__('Show the breadcrumb for the %s post type archives in the breadcrumb trail.', 'breadcrumb-navxt'), $singular_name_lc),
    599610                                    !$post_type->has_archive,
     
    611622                            $this->form->input_check(
    612623                                    $this->settings['bpost_' . $post_type->name . '_hierarchy_display'],
     624                                    /* translators: %s: Singular name for the CPT */
    613625                                    sprintf(__('Show the hierarchy (specified below) leading to a %s in the breadcrumb trail.', 'breadcrumb-navxt'), $singular_name_lc),
    614626                                    false,
     
    617629                            $this->form->input_check(
    618630                                    $this->settings['bpost_' . $post_type->name . '_hierarchy_parent_first'],
     631                                    /* translators: %s: Singular name for the CPT */
    619632                                    sprintf(__('Use the parent of the %s as the primary hierarchy, falling back to the hierarchy selected below when the parent hierarchy is exhausted.', 'breadcrumb-navxt'), $singular_name_lc),
    620633                                    false,
     
    630643                    <tr valign="top">
    631644                        <th scope="row">
    632                             <?php printf(__('%s Hierarchy', 'breadcrumb-navxt'), $post_type->labels->singular_name); ?>
     645                            <?php /* translators: %s: Singular name for the CPT */
     646                            printf(esc_html__('%s Hierarchy', 'breadcrumb-navxt'), esc_html($post_type->labels->singular_name)); ?>
    633647                        </th>
    634648                        <td>
     
    662676                                esc_html_e('The hierarchy which the breadcrumb trail will show. Note that the "Post Parent" option may require an additional plugin to behave as expected since this is a non-hierarchical post type.', 'breadcrumb-navxt');
    663677                            }
    664                             echo $overridden['Epost_' . $post_type->name . '_hierarchy_type'];
     678                            echo esc_html($overridden['Epost_' . $post_type->name . '_hierarchy_type']);
    665679                            ?>
    666680                            </p>
     
    677691            </fieldset>
    678692            <fieldset id="tax" class="bcn_options alttab">
    679                 <legend class="screen-reader-text" data-title="<?php _e( 'The settings for all taxonomies (including Categories, Tags, and custom taxonomies) are located under this tab.', 'breadcrumb-navxt' );?>"><?php _e( 'Taxonomies', 'breadcrumb-navxt' ); ?></legend>
     693                <legend class="screen-reader-text" data-title="<?php esc_attr_e( 'The settings for all taxonomies (including Categories, Tags, and custom taxonomies) are located under this tab.', 'breadcrumb-navxt' );?>"><?php esc_html_e( 'Taxonomies', 'breadcrumb-navxt' ); ?></legend>
    680694            <?php
    681695            //Loop through all of the taxonomies in the array
     
    689703                $label_lc = mb_strtolower($taxonomy->label, 'UTF-8');
    690704                ?>
    691                 <h2><?php echo mb_convert_case($taxonomy->label, MB_CASE_TITLE, 'UTF-8'); ?></h2>
     705                <h2><?php echo esc_html(mb_convert_case($taxonomy->label, MB_CASE_TITLE, 'UTF-8')); ?></h2>
    692706                <table class="form-table">
    693707                    <?php
     
    696710                                '6',
    697711                                false,
     712                                /* translators: %s: Taxonomy name*/
    698713                                sprintf(__('The template for %s breadcrumbs.', 'breadcrumb-navxt') . $overridden['Htax_' . $taxonomy->name . '_template'], $label_lc),
    699714                                $overridden_style['Htax_' . $taxonomy->name . '_template']);
     
    702717                                '4',
    703718                                false,
     719                                /* translators: %s: Taxonomy name */
    704720                                sprintf(__('The template for %s breadcrumbs, used only when the breadcrumb is not linked.', 'breadcrumb-navxt') . $overridden['Htax_' . $taxonomy->name . '_template_no_anchor'], $label_lc),
    705721                                $overridden_style['Htax_' . $taxonomy->name . '_template_no_anchor']);
     
    711727            </fieldset>
    712728            <fieldset id="miscellaneous" class="bcn_options">
    713                 <legend class="screen-reader-text" data-title="<?php _e( 'The settings for author and date archives, searches, and 404 pages are located under this tab.', 'breadcrumb-navxt' );?>"><?php _e( 'Miscellaneous', 'breadcrumb-navxt' ); ?></legend>
    714                 <h2><?php _e('Author Archives', 'breadcrumb-navxt'); ?></h2>
     729                <legend class="screen-reader-text" data-title="<?php esc_attr_e( 'The settings for author and date archives, searches, and 404 pages are located under this tab.', 'breadcrumb-navxt' );?>"><?php esc_html_e( 'Miscellaneous', 'breadcrumb-navxt' ); ?></legend>
     730                <h2><?php esc_html_e('Author Archives', 'breadcrumb-navxt'); ?></h2>
    715731                <table class="form-table">
    716732                    <?php
     
    737753                    <tr valign="top">
    738754                        <th scope="row">
    739                             <label for="<?php echo $optid;?>"><?php esc_html_e('Author Root Page', 'breadcrumb-navxt');?></label>
     755                            <label for="<?php echo esc_attr($optid);?>"><?php esc_html_e('Author Root Page', 'breadcrumb-navxt');?></label>
    740756                        </th>
    741757                        <td>
    742758                            <?php wp_dropdown_pages(array(
    743759                                    'name' => $this->unique_prefix . '_options[aauthor_root]',
    744                                     'id' => $optid,
     760                                    'id' => esc_attr($optid),
    745761                                    'echo' => 1,
    746                                     'show_option_none' => __( '&mdash; Select &mdash;' ),
     762                                    'show_option_none' => esc_attr__('&mdash; Select &mdash;', 'breadcrumb-navxt'),
    747763                                    'option_none_value' => '0',
    748764                                    'selected' => $this->settings['aauthor_root']->get_value(),
     
    751767                            if(isset($overridden['aauthor_root']) && $overridden['aauthor_root'] !== '')
    752768                            {
    753                                 printf('<p class="description">%s</p>', $overridden['aauthor_root']);
     769                                printf('<p class="description">%s</p>', esc_html($overridden['aauthor_root']));
    754770                            }
    755771                            ?>
     
    757773                    </tr>
    758774                </table>
    759                 <h2><?php _e('Miscellaneous', 'breadcrumb-navxt'); ?></h2>
     775                <h2><?php esc_html_e('Miscellaneous', 'breadcrumb-navxt'); ?></h2>
    760776                <table class="form-table">
    761777                    <?php
     
    797813                    ?>
    798814                </table>
    799                 <h2><?php _e('Deprecated', 'breadcrumb-navxt'); ?></h2>
    800                 <table class="form-table">
    801                     <tr valign="top">
    802                         <th scope="row">
    803                             <?php esc_html_e('Title Length', 'breadcrumb-navxt'); ?>
    804                         </th>
    805                         <td>
    806                             <label>
    807                                 <input name="bcn_options[blimit_title]" type="checkbox" id="blimit_title" value="true" class="disabled" <?php checked(true, $this->settings['blimit_title']->get_value()); ?> />
    808                                 <?php printf(esc_html__('Limit the length of the breadcrumb title. (Deprecated, %suse CSS instead%s)', 'breadcrumb-navxt'), '<a title="' . esc_attr__('Go to the guide on trimming breadcrumb title lengths with CSS', 'breadcrumb-navxt') . '" href="https://mtekk.us/archives/guides/trimming-breadcrumb-title-lengths-with-css/">', '</a>');?>
    809                             </label><br />
    810                             <ul>
    811                                 <li>
    812                                     <label for="amax_title_length">
    813                                         <?php esc_html_e('Max Title Length: ','breadcrumb-navxt');?>
    814                                         <input type="number" name="bcn_options[amax_title_length]" id="amax_title_length" min="1" step="1" value="<?php echo esc_html($this->settings['amax_title_length']->get_value(), ENT_COMPAT, 'UTF-8'); ?>" class="small-text disabled" />
    815                                     </label>
    816                                 </li>
    817                             </ul>
    818                         </td>
    819                     </tr>
    820                 </table>
    821815                <?php do_action($this->unique_prefix . '_after_settings_tab_miscellaneous', $this->settings); ?>
    822816            </fieldset>
    823817            <?php do_action($this->unique_prefix . '_after_settings_tabs', $this->settings); ?>
    824818            </div>
    825             <p class="submit"><input type="submit" class="button-primary" name="bcn_admin_options" value="<?php esc_attr_e('Save Changes') ?>" /></p>
     819            <p class="submit"><input type="submit" class="button-primary" name="bcn_admin_options" value="<?php esc_attr_e('Save Changes', 'breadcrumb-navxt') ?>" /></p>
    826820        </form>
    827821        </div>
  • breadcrumb-navxt/trunk/class.bcn_breadcrumb.php

    r3411622 r3425008  
    3535    //The corresponding resource ID
    3636    protected $id = null;
    37     private $_title = null;
    3837    //The type of this breadcrumb
    3938    protected $type;
     
    7271            else
    7372            {
    74                 $this->template_no_anchor =  $this->run_template_kses(apply_filters('bcn_breadcrumb_template_no_anchor', $template, $this->type, $this->id));
     73                $this->template_no_anchor =  $this->kses(apply_filters('bcn_breadcrumb_template_no_anchor', $template, $this->type, $this->id));
    7574                $this->set_template(bcn_breadcrumb::get_default_template());
    7675            }
     
    9796        //Set the title
    9897        $this->title = apply_filters('bcn_breadcrumb_title', $title, $this->type, $this->id);
    99         $this->_title = $this->title;
    10098    }
    10199    /**
     
    149147     * A wrapper for wp_kses which handles getting the allowed html
    150148     *
    151      * @param string $template_str The template string to run through kses
    152      * @return string The template string post cleaning
    153      */
    154     protected function run_template_kses($template_str)
    155     {
    156         return wp_kses($template_str, apply_filters('bcn_allowed_html', wp_kses_allowed_html('post')));
     149     * @param string $string The string to run through kses
     150     * @return string The string post cleaning
     151     */
     152    protected function kses($string)
     153    {
     154        return wp_kses($string, apply_filters('bcn_allowed_html', wp_kses_allowed_html('post')));
    157155    }
    158156    /**
     
    164162    {
    165163        //Assign the breadcrumb template
    166         $this->template = $this->run_template_kses(apply_filters('bcn_breadcrumb_template', $template, $this->type, $this->id));
     164        $this->template = $this->kses(apply_filters('bcn_breadcrumb_template', $template, $this->type, $this->id));
    167165    }
    168166    /**
     
    223221        //Build our replacements array
    224222        $replacements = array(
    225             '%title%' => esc_attr(strip_tags($this->title)),
     223            '%title%' => esc_attr(wp_strip_all_tags($this->title)),
    226224            '%link%' => esc_url($this->url),
    227             '%htitle%' => $this->title,
     225            '%htitle%' => $this->kses($this->title), /*TODO: verify if we want to restrict this more*/
    228226            '%type%' => apply_filters('bcn_breadcrumb_types', $this->type, $this->id),
    229             '%ftitle%' => esc_attr(strip_tags($this->_title)),
    230             '%fhtitle%' => $this->_title,
    231             '%position%' => $position,
     227            '%ftitle%' => esc_attr(wp_strip_all_tags($this->title)),
     228            '%fhtitle%' => $this->kses($this->title), /*TODO: verify if we want to restrict this more*/
     229            '%position%' => esc_attr($position),
    232230            'bcn-aria-current' => $aria_current_str
    233231            );
     
    240238        else
    241239        {
    242             _doing_it_wrong(__CLASS__ . '::' . __FUNCTION__, __('bcn_breadcrumb::type must be an array', 'breadcrumb-navxt'), '6.0.2');
     240            _doing_it_wrong(__CLASS__ . '::' . __FUNCTION__, esc_html__('bcn_breadcrumb::type must be an array', 'breadcrumb-navxt'), '6.0.2');
     241            //Type wasn't an array, throw it through esc_attr
     242            $replacements['%type%'] == esc_attr($replacements['%type%']);
    243243        }
    244244        $replacements = apply_filters('bcn_template_tags', $replacements, $this->type, $this->id);
  • breadcrumb-navxt/trunk/class.bcn_breadcrumb_trail.php

    r3411622 r3425008  
    3131    public function __construct()
    3232    {
    33         //@see https://core.trac.wordpress.org/ticket/10527
    34         if(!is_textdomain_loaded('breadcrumb-navxt'))
    35         {
    36             load_plugin_textdomain('breadcrumb-navxt', false, 'breadcrumb-navxt/languages');
    37         }
    3833        $this->trail = &$this->breadcrumbs;
    3934        //Initialize with default option values
     
    8075            //Paged options
    8176            //The template for paged breadcrumb
     77            /* translators: %htitle%: The page title which may contain HTML, in this case it should be a number as it is when on a paginated archive */
    8278            'Hpaged_template' => sprintf('<span class="%%type%%">%1$s</span>', esc_attr__('Page %htitle%', 'breadcrumb-navxt')),
    8379            //Should we try filling out paged information
     
    121117            //The breadcrumb template for search breadcrumbs
    122118            'Hsearch_template' => sprintf('<span property="itemListElement" typeof="ListItem"><span property="name">%1$s</span><meta property="position" content="%%position%%"></span>',
     119                    /* translators: %1$s: The searched phrase */
    123120                    sprintf(esc_attr__('Search results for &#39;%1$s&#39;', 'breadcrumb-navxt'),
     121                    /* translators: %title%: The searched phrase */
    124122                    sprintf('<a property="item" typeof="WebPage" title="%1$s" href="%%link%%" class="%%type%%" bcn-aria-current>%%htitle%%</a>', esc_attr__('Go to the first page of search results for %title%.', 'breadcrumb-navxt')))),
    125123            //The breadcrumb template for search breadcrumbs, used when an anchor is not necessary
    126124            'Hsearch_template_no_anchor' => sprintf('<span class="%%type%%">%1$s</span>',
     125                    /* translators: %1$s: The searched phrase */
    127126                    sprintf(esc_attr__('Search results for &#39;%1$s&#39;', 'breadcrumb-navxt'), '%htitle%')),
    128127            //Tag related stuff
     
    139138            //The anchor template for author breadcrumbs
    140139            'Hauthor_template' => sprintf('<span property="itemListElement" typeof="ListItem"><span property="name">%1$s</span><meta property="position" content="%%position%%"></span>',
     140                /* translators: %1$s: The post author name the current archive is for */
    141141                sprintf(esc_attr__('Articles by: %1$s', 'breadcrumb-navxt'),
    142142                sprintf('<a title="%1$s" href="%%link%%" class="%%type%%" bcn-aria-current>%%htitle%%</a>', esc_attr__('Go to the first page of posts by %title%.', 'breadcrumb-navxt')))),
    143143            //The anchor template for author breadcrumbs, used when anchors are not needed
    144144            'Hauthor_template_no_anchor' => sprintf('<span class="%%type%%">%1$s</span>',
     145                /* translators: %1$s: The post author name the current archive is for */
    145146                sprintf(esc_attr__('Articles by: %1$s', 'breadcrumb-navxt'), '%htitle%')),
    146147            //Which of the various WordPress display types should the author breadcrumb display
     
    519520        if(!($post instanceof WP_Post))
    520521        {
    521             _doing_it_wrong(__CLASS__ . '::' . __FUNCTION__, __('$post global is not of type WP_Post', 'breadcrumb-navxt'), '5.1.1');
     522            _doing_it_wrong(__CLASS__ . '::' . __FUNCTION__, esc_html__('$post global is not of type WP_Post', 'breadcrumb-navxt'), '5.1.1');
    522523            return;
    523524        }
     
    574575        if(!($term instanceof WP_Term))
    575576        {
    576             _doing_it_wrong(__CLASS__ . '::' . __FUNCTION__, __('$term global is not of type WP_Term', 'breadcrumb-navxt'), '7.0.3');
     577            _doing_it_wrong(__CLASS__ . '::' . __FUNCTION__, esc_html__('$term global is not of type WP_Term', 'breadcrumb-navxt'), '7.0.3');
    577578            return;
    578579        }
     
    12281229        $this->order($reverse);
    12291230        //The main compiling loop
    1230         $trail_str = $this->display_loop($this->breadcrumbs, $linked, $reverse, $template, $outer_template, $this->opt['hseparator']);
    1231         return $trail_str;
     1231        $trail_str_escaped = $this->display_loop($this->breadcrumbs, $linked, $reverse, $template, $outer_template, $this->opt['hseparator']);
     1232        return $trail_str_escaped;
    12321233    }
    12331234    /**
     
    12541255        }
    12551256        //Initialize the string which will hold the assembled trail
    1256         $trail_str = '';
     1257        $trail_str_escaped = '';
    12571258        foreach($breadcrumbs as $key => $breadcrumb)
    12581259        {
     
    12641265            if(is_array($breadcrumb))
    12651266            {
    1266                 $trail_str .= sprintf($outer_template,
     1267                $trail_str_escaped .= sprintf($outer_template,
    12671268                        $this->display_loop($breadcrumb, $linked, $reverse, $template, $outer_template, $this->opt['hseparator_higher_dim'], $depth + 1), $separator);
    12681269            }
     
    12801281                    $attribs .= sprintf(' %1$s="%2$s"', esc_attr($attrib), esc_attr(implode(' ', $value)));
    12811282                }
    1282                 //Filter li_attributes adding attributes to the li element
    1283                 //TODO: Remove the bcn_li_attributes filter
    1284                 $attribs = apply_filters_deprecated('bcn_li_attributes', array($attribs, $breadcrumb->get_types(), $breadcrumb->get_id()), '6.0.0', 'bcn_display_attributes');
    1285                 //TODO: Deprecate this filter in favor of just using bcn_display_attributes_array
    1286                 $attribs = apply_filters('bcn_display_attributes', $attribs, $breadcrumb->get_types(), $breadcrumb->get_id());
     1283                //TODO: Remove this filter in favor of just using bcn_display_attributes_array
     1284                $attribs = apply_filters_deprecated('bcn_display_attributes', array($attribs, $breadcrumb->get_types(), $breadcrumb->get_id()), '7.5.1', 'bcn_display_attribute_array');
    12871285                $separator = apply_filters('bcn_display_separator', $separator, $position, $last_position, $depth);
    12881286                //Assemble the breadcrumb
    1289                 $trail_str .= sprintf($template, $breadcrumb->assemble($linked, $position, ($key === 0)), $separator, $attribs);
     1287                $trail_str_escaped .= sprintf($template, $breadcrumb->assemble($linked, $position, ($key === 0)), wp_kses($separator, apply_filters('bcn_allowed_html', wp_kses_allowed_html('post'))), $attribs);
    12901288            }
    12911289            if($reverse)
     
    12981296            }
    12991297        }
    1300         return $trail_str;
     1298        return $trail_str_escaped;
    13011299    }
    13021300    /**
     
    13121310        //Set trail order based on reverse flag
    13131311        $this->order($reverse);
    1314         $trail_str = (object)array(
     1312        $trail_str_escaped = (object)array(
    13151313            '@context' => 'http://schema.org',
    13161314            '@type' => 'BreadcrumbList',
    13171315            'itemListElement' => $this->json_ld_loop($reverse));
    1318         return $trail_str;
     1316        return $trail_str_escaped;
    13191317    }
    13201318    /**
     
    13311329            $position = count($this->breadcrumbs);
    13321330        }
    1333         $breadcrumbs = array();
     1331        $breadcrumbs_escaped= array();
    13341332        //Loop around our breadcrumbs, call the JSON-LD assembler
    13351333        foreach($this->breadcrumbs as $breadcrumb)
    13361334        {
    1337             $breadcrumbs[] = $breadcrumb->assemble_json_ld($position);
     1335            $breadcrumbs_escaped[] = $breadcrumb->assemble_json_ld($position);
    13381336            if($reverse)
    13391337            {
     
    13451343            }
    13461344        }
    1347         return $breadcrumbs;
     1345        return $breadcrumbs_escaped;
    13481346    }
    13491347    /**
  • breadcrumb-navxt/trunk/class.bcn_network_admin.php

    r3411622 r3425008  
    3838     * @param string $basename The basename of the plugin
    3939     */
    40     function __construct(array &$opts, $basename, array &$settings)
     40    public function __construct(array &$opts, $basename, array &$settings)
    4141    {
    4242        //We're going to make sure we load the parent's constructor
     
    4949        add_action('network_admin_menu', array($this, 'add_page'));
    5050    }
    51     function is_network_admin()
     51    public function is_network_admin()
    5252    {
    5353        return true;
     
    6161     * @return void
    6262     */
    63     function init()
     63    public function init()
    6464    {
    6565        //We're going to make sure we run the parent's version of this function as well
    6666        parent::init();
    6767    }
    68     function wp_loaded()
     68    public function wp_loaded()
    6969    {
    7070        parent::wp_loaded();
     
    7373     * Return the URL of the settings page for the plugin
    7474     */
    75     function admin_url()
     75    public function admin_url()
    7676    {
    7777        return admin_url('network/settings.php?page=' . $this->identifier);
     
    8080     * Adds the adminpage the menu and the nice little settings link
    8181     */
    82     function add_page()
     82    public function add_page()
    8383    {
    8484        //Add the submenu page to "settings" menu
     
    103103     *
    104104     */
    105     function help()
     105    public function help()
    106106    {
    107107        $screen = get_current_screen();
     
    123123     * @return mixed The value of the option
    124124     */
    125     function get_option($option)
     125    public function get_option($option)
    126126    {
    127127        return get_site_option($option);
     
    134134     *
    135135     */
    136     function update_option($option, $newvalue, $autoload = null)
     136    public function update_option($option, $newvalue, $autoload = null)
    137137    {
    138138        return update_site_option($option, $newvalue);
     
    147147     *
    148148     */
    149     function add_option($option, $value = '', $deprecated = '', $autoload = 'yes')
     149    public function add_option($option, $value = '', $deprecated = '', $autoload = 'yes')
    150150    {
    151151        return add_site_option($option, $value);
     
    156156     * @param string $option The name of the option to delete
    157157     */
    158     function delete_option($option)
     158    public function delete_option($option)
    159159    {
    160160        return delete_site_option($option);
     
    163163     * A message function that checks for the BCN_SETTINGS_* define statement
    164164     */
    165     function multisite_settings_warn()
     165    public function multisite_settings_warn()
    166166    {
    167167        if(is_multisite())
     
    194194     * A message function that checks for deprecated settings that are set and warns the user
    195195     */
    196     function deprecated_settings_warn()
     196    public function deprecated_settings_warn()
    197197    {
    198198        parent::deprecated_settings_warn();
     
    203203     * @return boool Whether or not the blog options should be disabled
    204204     */
    205     function maybe_disable_blog_options()
     205    public function maybe_disable_blog_options()
    206206    {
    207207        return false;
     
    212212     * @return bool Whether or not the mainsite options should be disabled
    213213     */
    214     function maybe_disable_mainsite_options()
     214    public function maybe_disable_mainsite_options()
    215215    {
    216216        return false;
  • breadcrumb-navxt/trunk/class.bcn_rest_controller.php

    r3411622 r3425008  
    2424    function bcn_phpold()
    2525    {
    26         printf('<div class="notice notice-error"><p>' . __('Your PHP version is too old, please upgrade to a newer version. Your version is %1$s, Breadcrumb NavXT requires %2$s', 'breadcrumb-navxt') . '</p></div>', phpversion(), '5.3.0');
     26        /* translators: %1$s: User's version of PHP, %2$s: Breadcrmb NavXT minimuum PHP version */
     27        printf('<div class="notice notice-error"><p>' . esc_html__('Your PHP version is too old, please upgrade to a newer version. Your version is %1$s, Breadcrumb NavXT requires %2$s', 'breadcrumb-navxt') . '</p></div>', esc_html(phpversion()), '7.0.0');
    2728    }
    2829    //If we are in the admin, let's print a warning then return
  • breadcrumb-navxt/trunk/class.bcn_widget.php

    r3411622 r3425008  
    2828        //Filter allowed_html array to allow others to add acceptable tags
    2929        $this->allowed_html = apply_filters('bcn_allowed_html', wp_kses_allowed_html('post'));
    30         //@see https://core.trac.wordpress.org/ticket/10527
    31         if(!is_textdomain_loaded('breadcrumb-navxt'))
    32         {
    33             load_plugin_textdomain('breadcrumb-navxt', false, 'breadcrumb-navxt/languages');
    34         }
    3530        $ops = array('classname' => 'widget_breadcrumb_navxt', 'description' => __('Adds a breadcrumb trail to your sidebar', 'breadcrumb-navxt'));
    3631        parent::__construct('bcn_widget', 'Breadcrumb NavXT', $ops);
     
    5247        }
    5348        //Mandatory before widget junk
    54         echo $args['before_widget'];
     49        echo wp_kses($args['before_widget'], wp_kses_allowed_html('post'));
    5550        if(!empty($title))
    5651        {
    57             echo $args['before_title'] . $title . $args['after_title'];
     52            echo wp_kses($args['before_title'], wp_kses_allowed_html('post')) . esc_html($title) . wp_kses($args['after_title'], wp_kses_allowed_html('post'));
    5853        }
    5954        //We'll want to switch between the two breadcrumb output types
     
    9994        }
    10095        //Mandatory after widget junk
    101         echo $args['after_widget'];
     96        echo wp_kses($args['after_widget'], wp_kses_allowed_html('post'));;
    10297    }
    10398    function update($new_instance, $old_instance)
    10499    {
    105100        //Filter out anything that could be invalid
    106         $old_instance['title'] = strip_tags($new_instance['title']);
     101        $old_instance['title'] = wp_strip_all_tags($new_instance['title']);
    107102        $old_instance['pretext'] = wp_kses($new_instance['pretext'], $this->allowed_html);
    108         $old_instance['type'] = strip_tags($new_instance['type']);
     103        $old_instance['type'] = wp_strip_all_tags($new_instance['type']);
    109104        //Have to check more than if it is set as it appears this must effectively run twice since WordPress 5.8
    110105        $old_instance['linked'] = isset($new_instance['linked']) && $new_instance['linked'] !== false;
     
    119114        ?>
    120115        <p>
    121             <label for="<?php echo esc_attr($this->get_field_id('title')); ?>"> <?php _e('Title:', 'breadcrumb-navxt'); ?></label>
     116            <label for="<?php echo esc_attr($this->get_field_id('title')); ?>"> <?php esc_html_e('Title:', 'breadcrumb-navxt'); ?></label>
    122117            <input class="widefat" type="text" name="<?php echo esc_attr($this->get_field_name('title')); ?>" id="<?php echo esc_attr($this->get_field_id('title')); ?>" value="<?php echo esc_attr($instance['title']);?>" />
    123118        </p>
    124119        <p>
    125             <label for="<?php echo esc_attr($this->get_field_id('pretext')); ?>"> <?php _e('Text to show before the trail:', 'breadcrumb-navxt'); ?></label>
     120            <label for="<?php echo esc_attr($this->get_field_id('pretext')); ?>"> <?php esc_html_e('Text to show before the trail:', 'breadcrumb-navxt'); ?></label>
    126121            <input class="widefat" type="text" name="<?php echo esc_attr($this->get_field_name('pretext')); ?>" id="<?php echo esc_attr($this->get_field_id('pretext')); ?>" value="<?php echo esc_attr($instance['pretext']);?>" />
    127122        </p>
    128123        <p>
    129             <label for="<?php echo esc_attr($this->get_field_id('type')); ?>"> <?php _e('Output trail as:', 'breadcrumb-navxt'); ?></label>
     124            <label for="<?php echo esc_attr($this->get_field_id('type')); ?>"> <?php esc_html_e('Output trail as:', 'breadcrumb-navxt'); ?></label>
    130125            <select name="<?php echo esc_attr($this->get_field_name('type')); ?>" id="<?php echo esc_attr($this->get_field_id('type')); ?>">
    131                 <option value="list" <?php selected('list', $instance['type']);?>><?php _e('List', 'breadcrumb-navxt'); ?></option>
    132                 <option value="microdata" <?php selected('microdata', $instance['type']);?>><?php _e('Schema.org BreadcrumbList (RDFa)', 'breadcrumb-navxt'); ?></option>
    133                 <option value="microdata_wai_aria" <?php selected('microdata_wai_aria', $instance['type']);?>><?php _e('Schema.org BreadcrumbList (RDFa) with WAI-ARIA', 'breadcrumb-navxt'); ?></option>
    134                 <option value="breadcrumblist_microdata" <?php selected('breadcrumblist_microdata', $instance['type']);?>><?php _e('Schema.org BreadcrumbList (microdata)', 'breadcrumb-navxt'); ?></option>
    135                 <option value="plain" <?php selected('plain', $instance['type']);?>><?php _e('Plain', 'breadcrumb-navxt'); ?></option>
     126                <option value="list" <?php selected('list', $instance['type']);?>><?php esc_html_e('List', 'breadcrumb-navxt'); ?></option>
     127                <option value="microdata" <?php selected('microdata', $instance['type']);?>><?php esc_html_e('Schema.org BreadcrumbList (RDFa)', 'breadcrumb-navxt'); ?></option>
     128                <option value="microdata_wai_aria" <?php selected('microdata_wai_aria', $instance['type']);?>><?php esc_html_e('Schema.org BreadcrumbList (RDFa) with WAI-ARIA', 'breadcrumb-navxt'); ?></option>
     129                <option value="breadcrumblist_microdata" <?php selected('breadcrumblist_microdata', $instance['type']);?>><?php esc_html_e('Schema.org BreadcrumbList (microdata)', 'breadcrumb-navxt'); ?></option>
     130                <option value="plain" <?php selected('plain', $instance['type']);?>><?php esc_html_e('Plain', 'breadcrumb-navxt'); ?></option>
    136131                <?php do_action('bcn_widget_display_types', $instance);?>
    137132            </select>
     
    139134        <p>
    140135            <input class="checkbox" type="checkbox" name="<?php echo esc_attr($this->get_field_name('linked')); ?>" id="<?php echo esc_attr($this->get_field_id('linked')); ?>"<?php checked(true, $instance['linked']);?> />
    141             <label for="<?php echo esc_attr($this->get_field_id('linked')); ?>"> <?php _e('Link the breadcrumbs', 'breadcrumb-navxt'); ?></label><br />
     136            <label for="<?php echo esc_attr($this->get_field_id('linked')); ?>"> <?php esc_html_e('Link the breadcrumbs', 'breadcrumb-navxt'); ?></label><br />
    142137            <input class="checkbox" type="checkbox" name="<?php echo esc_attr($this->get_field_name('reverse')); ?>" id="<?php echo esc_attr($this->get_field_id('reverse')); ?>"<?php checked(true, $instance['reverse']);?> />
    143             <label for="<?php echo esc_attr($this->get_field_id('reverse')); ?>"> <?php _e('Reverse the order of the trail', 'breadcrumb-navxt'); ?></label><br />
     138            <label for="<?php echo esc_attr($this->get_field_id('reverse')); ?>"> <?php esc_html_e('Reverse the order of the trail', 'breadcrumb-navxt'); ?></label><br />
    144139            <input class="checkbox" type="checkbox" name="<?php echo esc_attr($this->get_field_name('front')); ?>" id="<?php echo esc_attr($this->get_field_id('front')); ?>"<?php checked(true, $instance['front']);?> />
    145             <label for="<?php echo esc_attr($this->get_field_id('front')); ?>"> <?php _e('Hide the trail on the front page', 'breadcrumb-navxt'); ?></label><br />
     140            <label for="<?php echo esc_attr($this->get_field_id('front')); ?>"> <?php esc_html_e('Hide the trail on the front page', 'breadcrumb-navxt'); ?></label><br />
    146141            <input class="checkbox" type="checkbox" name="<?php echo esc_attr($this->get_field_name('force')); ?>" id="<?php echo esc_attr($this->get_field_id('force')); ?>"<?php checked(true, $instance['force']);?> />
    147             <label for="<?php echo esc_attr($this->get_field_id('force')); ?>"> <?php _e('Ignore breadcrumb cache', 'breadcrumb-navxt'); ?></label><br />
     142            <label for="<?php echo esc_attr($this->get_field_id('force')); ?>"> <?php esc_html_e('Ignore breadcrumb cache', 'breadcrumb-navxt'); ?></label><br />
    148143        </p>
    149144        <?php
  • breadcrumb-navxt/trunk/includes/adminKit/class-mtekk_adminkit.php

    r3411622 r3425008  
    8989abstract class adminKit
    9090{
    91     const version = '3.1.1';
     91    const version = '3.1.2';
    9292    protected $full_name;
    9393    protected $short_name;
     
    103103    protected $settings = array();
    104104    protected $form;
    105     function __construct()
     105    public function __construct()
    106106    {
    107107        $this->message = array();
     
    113113        //Installation Script hook
    114114        add_action('activate_' . $this->plugin_basename, array($this, 'install'));
    115         //Initializes l10n domain
    116         $this->local();
    117115        add_action('wp_loaded', array($this, 'wp_loaded'));
    118116        $this->form = new form($this->unique_prefix);
     
    120118        //add_action('add_screen_help_and_options', array($this, 'help'));
    121119    }
    122     function wp_loaded()
     120    public function wp_loaded()
    123121    {
    124122        //Filter our allowed html tags
     
    128126     * Returns the internal mtekk_admin_class version
    129127     */
    130     function get_admin_class_version()
     128    public function get_admin_class_version()
    131129    {
    132130        return adminKit::version;
     
    135133     * Checks if the administrator has the access capability, and adds it if they don't
    136134     */
    137     function add_cap()
     135    public function add_cap()
    138136    {
    139137        $role = get_role('administrator');
     
    146144     * Return the URL of the settings page for the plugin
    147145     */
    148     function admin_url()
     146    public function admin_url()
    149147    {
    150148        return admin_url('options-general.php?page=' . $this->identifier);
     
    158156     * @return string the assembled anchor
    159157     */
    160     function admin_anchor($mode, $title = '', $text = '')
     158    public function admin_anchor($mode, $title = '', $text = '')
    161159    {
    162160        return $this->nonced_anchor($this->admin_url(), 'admin_' . $mode, 'true', $title, $text);
     
    173171     * @return string the assembled anchor
    174172     */
    175     function nonced_anchor($uri, $mode, $value = 'true', $title = '', $text = '', $anchor_extras = '')
     173    public function nonced_anchor($uri, $mode, $value = 'true', $title = '', $text = '', $anchor_extras = '')
    176174    {
    177175        //Assemble our url, nonce and all
    178176        $url = wp_nonce_url(add_query_arg($this->unique_prefix . '_' . $mode, $value, $uri), $this->unique_prefix . '_' . $mode);
    179177        //Return a valid anchor
    180         return ' <a title="' . esc_attr($title) . '" href="' . $url . '" '. $anchor_extras . '>' . esc_html($text) . '</a>';
     178        return ' <a title="' . esc_attr($title) . '" href="' . esc_url($url) . '" '. $anchor_extras . '>' . esc_html($text) . '</a>';
    181179    }
    182180    /**
     
    185183     * @param string $mode The specific nonce "mode" (see nonced_anchor) that is being checked
    186184     */
    187     function check_nonce($mode)
    188     {
    189         check_admin_referer($this->unique_prefix . '_' . $mode);
     185    public function check_nonce($mode)
     186    {
     187        return check_admin_referer($this->unique_prefix . '_' . $mode);
    190188    }
    191189    /**
    192190     * Makes sure the current user can manage options to proceed
    193191     */
    194     function security()
     192    protected function security()
    195193    {
    196194        //If the user can not manage options we will die on them
    197195        if(!current_user_can($this->access_level))
    198196        {
    199             wp_die(__('Insufficient privileges to proceed.', $this->identifier));
    200         }
    201     }
    202     function init()
     197            wp_die(esc_html__('Insufficient privileges to proceed.', $this->identifier));
     198        }
     199    }
     200    public function init()
    203201    {
    204202        $this->add_cap();
     
    262260        wp_register_script('mtekk_adminkit_tabs', plugins_url('/mtekk_adminkit_tabs' . $suffix . '.js', dirname(__FILE__) . '/assets/mtekk_adminkit_tabs' . $suffix . '.js'), array('jquery-ui-tabs'), self::version, true);
    263261        //Register CSS for tabs
    264         wp_register_style('mtekk_adminkit_tabs', plugins_url('/mtekk_adminkit_tabs' . $suffix . '.css', dirname(__FILE__) . '/assets/mtekk_adminkit_tabs' . $suffix . '.css'));
     262        wp_register_style('mtekk_adminkit_tabs', plugins_url('/mtekk_adminkit_tabs' . $suffix . '.css', dirname(__FILE__) . '/assets/mtekk_adminkit_tabs' . $suffix . '.css'), array(), self::version);
    265263        //Register options
    266264        register_setting($this->unique_prefix . '_options', $this->unique_prefix . '_options', '');
     
    273271     * TODO: make this more generic for easier extension
    274272     */
    275     function add_page()
     273    public function add_page()
    276274    {
    277275        //Add the submenu page to "settings" menu
     
    291289    }
    292290    /**
    293      * Initializes localization textdomain for translations (if applicable)
    294      *
    295      * Will conditionally load the textdomain for translations. This is here for
    296      * plugins that span multiple files and have localization in more than one file
    297      *
    298      * @return void
    299      */
    300     function local()
    301     {
    302         global $l10n;
    303         // the global and the check might become obsolete in
    304         // further wordpress versions
    305         // @see https://core.trac.wordpress.org/ticket/10527       
    306         if(!isset($l10n[$this->identifier]))
    307         {
    308             load_plugin_textdomain($this->identifier, false, $this->identifier . '/languages');
    309         }
    310     }
    311     /**
    312291     * Places in a link to the settings page in the plugins listing entry
    313292     *
     
    316295     * @return array  Array of links that are output in the listing.
    317296     */
    318     function filter_plugin_actions($links, $file)
     297    public function filter_plugin_actions($links, $file)
    319298    {
    320299        //Make sure we are adding only for the current plugin
     
    322301        {
    323302            //Add our link to the end of the array to better integrate into the WP 2.8 plugins page
    324             $links[] = '<a href="' . $this->admin_url() . '">' . esc_html__('Settings') . '</a>';
     303            $links[] = '<a href="' . esc_url($this->admin_url()) . '">' . esc_html__('Settings', $this->identifier) . '</a>';
    325304        }
    326305        return $links;
     
    331310     * @return bool whether or not the plugin has been installed
    332311     */
    333     function is_installed()
     312    public function is_installed()
    334313    {
    335314        $opts = $this->get_option($this->unique_prefix . '_options');
     
    341320     * FIXME: seems there is a lot of very similar code in opts_upgrade_wrapper
    342321     */
    343     function install()
     322    public function install()
    344323    {
    345324        //Call our little security function
     
    374353     * This removes database settings upon deletion of the plugin from WordPress
    375354     */
    376     function uninstall()
     355    public function uninstall()
    377356    {
    378357        //Remove the option array setting
     
    387366     * TODO: change this to being auto called in admin_init action
    388367     */
    389     function version_check($version)
     368    public function version_check($version)
    390369    {
    391370        //If we didn't get a version, setup
     
    441420     * @return boolean
    442421     */
    443     function settings_validate(array &$settings)
     422    public function settings_validate(array &$settings)
    444423    {
    445424        foreach($settings as $setting)
     
    452431                }
    453432            }
    454             else if($setting instanceof setting && $setting->get_value() !== $setting->validate($setting->get_value()))
     433            else if($setting instanceof setting && $setting->get_value() !== $setting->validate($setting->get_value())) //FIXME: not sure I like this
    455434            {
    456435                return false;
    457436            }
    458437        }
    459         return true;
     438        return true; //FIXME: Shouldn't the default to be false?
    460439    }
    461440    /**
    462441     * Synchronizes the backup options entry with the current options entry
    463442     */
    464     function opts_backup()
     443    protected function opts_backup()
    465444    {
    466445        //Set the backup options in the DB to the current options
     
    599578     * @return number
    600579     */
    601     function setting_equal_check($a, $b)
     580    public function setting_equal_check($a, $b)
    602581    {
    603582        if(is_array($a) || is_array($b))
     
    641620    }
    642621    /**
    643      * Generates array of the new non-default settings based off of form input
     622     * Generates array of the new non-default settings based off of form $input
    644623     *
    645624     * @param array $input The form input array of setting values
     
    668647     * 4) Save to database the difference generated in #4
    669648     */
    670     function opts_update()
     649    protected function opts_update()
    671650    {
    672651        //Do some security related things as we are not using the normal WP settings API
     
    680659        $this->update_option($this->unique_prefix . '_options_bk', $this->opt, false);
    681660        $opt_prev = $this->opt;
     661        //While this should never happen, if the settings are missing, exit early
     662        if(!isset($_POST[$this->unique_prefix . '_options']))
     663        {
     664            return;
     665        }
    682666        //Grab our incoming array (the data is dirty)
    683667        $input = $_POST[$this->unique_prefix . '_options'];
     
    714698                $temp .= '<br />' . $setting;
    715699            }
    716             $this->messages[] = new message($temp . '<br />' . sprintf(esc_html__('Please include this message in your %sbug report%s.', $this->identifier), '<a title="' . sprintf(esc_attr__('Go to the %s support forum.', $this->identifier), $this->short_name) . '" href="' . $this->support_url . '">', '</a>'), 'info');
     700            /* translators: %1$s: HTML opening tag for link to the support forums, %2$s: HTML closing tag for link to support forums */
     701            $this->messages[] = new message($temp . '<br />' . sprintf(esc_html__('Please include this message in your %1$sbug report%2$s.', $this->identifier), '<a title="' . sprintf(esc_attr__('Go to the %s support forum.', $this->identifier), $this->short_name) . '" href="' . $this->support_url . '">', '</a>'), 'info');
    717702        }
    718703        add_action('admin_notices', array($this, 'messages'));
     
    721706     * Retrieves the settings from database and exports as JSON
    722707     */
    723     function settings_export()
    724     {
     708    public function settings_export()
     709    {
     710        //Check if the user has permissions to do this
     711        $this->security();
    725712        //Do a nonce check, prevent malicious link/form problems
    726         check_admin_referer($this->unique_prefix . '_admin_import_export');
    727         //Must clone the defaults since PHP normally shallow copies
    728         $default_settings = array_map('mtekk\adminKit\adminKit::setting_cloner', $this->settings);
    729         //Get the database options, and load
    730         //FIXME: This changes once we save settings to the db instead of opts
    731         adminKit::load_opts_into_settings($this->get_option($this->unique_prefix . '_options'), $this->settings);
    732         //Get the unique settings
    733         $export_settings = apply_filters($this->unique_prefix . '_settings_to_export', array_udiff_assoc($this->settings, $default_settings, array($this, 'setting_equal_check')));
    734         //Change our header to application/json for direct save
    735         header('Cache-Control: public');
    736         //The next two will cause good browsers to download instead of displaying the file
    737         header('Content-Description: File Transfer');
    738         header('Content-disposition: attachment; filename=' . $this->unique_prefix . '_settings.json');
    739         header('Content-Type: application/json');
    740         //JSON encode our settings array
    741         $output = json_encode(
    742                 (object)array(
    743                         'plugin' => $this->short_name,
    744                         'version' => $this::version,
    745                         'settings' => $export_settings)
    746                 , JSON_UNESCAPED_SLASHES, 32);
    747         //Let the browser know how long the file is
    748         header('Content-Length: ' . strlen($output)); // binary length
    749         //Output the file
    750         echo $output;
    751         //Prevent WordPress from continuing on
    752         die();
     713        if(check_admin_referer($this->unique_prefix . '_admin_import_export'))
     714        {
     715            //Must clone the defaults since PHP normally shallow copies
     716            $default_settings = array_map('mtekk\adminKit\adminKit::setting_cloner', $this->settings);
     717            //Get the database options, and load
     718            //FIXME: This changes once we save settings to the db instead of opts
     719            adminKit::load_opts_into_settings($this->get_option($this->unique_prefix . '_options'), $this->settings);
     720            //Get the unique settings
     721            $export_settings = apply_filters($this->unique_prefix . '_settings_to_export', array_udiff_assoc($this->settings, $default_settings, array($this, 'setting_equal_check')));
     722            //Change our header to application/json for direct save
     723            header('Cache-Control: public');
     724            //The next two will cause good browsers to download instead of displaying the file
     725            header('Content-Description: File Transfer');
     726            header('Content-disposition: attachment; filename=' . $this->unique_prefix . '_settings.json');
     727            header('Content-Type: application/json');
     728            //JSON encode our settings array
     729            $output_escaped= wp_json_encode(
     730                    (object)array(
     731                            'plugin' => $this->short_name,
     732                            'version' => $this::version,
     733                            'settings' => $export_settings)
     734                    , JSON_UNESCAPED_SLASHES, 32);
     735            //Let the browser know how long the file is
     736            header('Content-Length: ' . strlen($output_escaped)); // binary length
     737            //Output the file
     738            echo $output_escaped;
     739            //Prevent WordPress from continuing on
     740            die();
     741        }
    753742    }
    754743    /**
    755744     * Imports JSON settings into database
    756      */
    757     function settings_import()
    758     {
     745     *
     746     */
     747    public function settings_import()
     748    {
     749        //Check if the user has permissions to do this
     750        $this->security();
    759751        //Do a nonce check, prevent malicious link/form problems
    760         check_admin_referer($this->unique_prefix . '_admin_import_export');
    761         //Set the backup options in the DB to the current options
    762         $this->opts_backup();
    763         //Load the user uploaded file, handle failure gracefully
    764         if(is_uploaded_file($_FILES[$this->unique_prefix . '_admin_import_file']['tmp_name']))
    765         {
    766             //Grab the json settings from the temp file, treat as associative array so we can just throw the settings subfield at the update loop
    767             $settings_upload = json_decode(file_get_contents($_FILES[$this->unique_prefix . '_admin_import_file']['tmp_name']), true);
    768             //Only continue if we have a JSON object that is for this plugin (the the WP rest_is_object() function is handy here as the REST API passes JSON)
    769             if(rest_is_object($settings_upload) && isset($settings_upload['plugin']) && $settings_upload['plugin'] === $this->short_name)
    770             {
     752        if(check_admin_referer($this->unique_prefix . '_admin_import_export'))
     753        {
     754            //Set the backup options in the DB to the current options
     755            $this->opts_backup();
     756            //Load the user uploaded file, handle failure gracefully
     757            if(isset($_FILES[$this->unique_prefix . '_admin_import_file']['tmp_name']) && is_uploaded_file($_FILES[$this->unique_prefix . '_admin_import_file']['tmp_name']))
     758            {
     759                //Grab the json settings from the temp file, treat as associative array so we can just throw the settings subfield at the update loop
     760                $settings_upload = json_decode(file_get_contents($_FILES[$this->unique_prefix . '_admin_import_file']['tmp_name']), true);
     761                //Only continue if we have a JSON object that is for this plugin (the the WP rest_is_object() function is handy here as the REST API passes JSON)
     762                if(rest_is_object($settings_upload) && isset($settings_upload['plugin']) && $settings_upload['plugin'] === $this->short_name)
     763                {
     764                    //Act as if the JSON file was just a bunch of POST entries for a settings save
     765                    //Run through the loop and get the diff from defaults
     766                    //this isn't obvious but calls adminkit::settings_update_loop() which calls setting::maybe_update_from_form_input which performs sanitization on a per setting basis
     767                    $new_settings = $this->get_settings_diff($settings_upload['settings'], true);
     768                    //FIXME: Eventually we'll save the object array, but not today
     769                    //Convert to opts array for saving
     770                    $this->opt = adminKit::settings_to_opts($new_settings);
     771                    //Run opts through update script
     772                    //Make sure we safely import and upgrade settings if needed
     773                    $this->opts_upgrade($this->opt, $settings_upload['version']);
     774                    //Commit the option changes
     775                    $updated = $this->update_option($this->unique_prefix . '_options', $this->opt, true);
     776                    //Check if known settings match attempted save
     777                    if($updated && count(array_diff_key($settings_upload['settings'], $this->settings)) == 0)
     778                    {
     779                        //Let the user know everything went ok
     780                        $this->messages[] = new message(esc_html__('Settings successfully imported from the uploaded file.', $this->identifier)
     781                                . $this->admin_anchor('undo', __('Undo the options import.', $this->identifier), __('Undo', $this->identifier)), 'success');
     782                    }
     783                    else
     784                    {
     785                        $this->messages[] = new message(esc_html__('No settings were imported. Settings from uploaded file matched existing settings.', $this->identifier), 'info');
     786                    }
     787                    //Output any messages that there may be
     788                    add_action('admin_notices', array($this, 'messages'));
     789                    //And return as we're successful
     790                    return;
     791                }
     792                //If it wasn't JSON, try XML
     793                else
     794                {
     795                    return $this->opts_import();
     796                }
     797            }
     798            //Throw an error since we could not load the file for various reasons
     799            $this->messages[] = new message(esc_html__('Importing settings from file failed.', $this->identifier), 'error');
     800        }
     801    }
     802    /**
     803     * Exports a XML options document
     804     * @deprecated 7.5.0
     805     */
     806    public function opts_export()
     807    {
     808        _deprecated_function( __FUNCTION__, '7.5.0', '\mtekk\adminKit::settings_export');
     809        //Check if the user has permissions to do this
     810        $this->security();
     811        //Do a nonce check, prevent malicious link/form problems
     812        if(check_admin_referer($this->unique_prefix . '_admin_import_export'))
     813        {
     814            //Update our internal settings
     815            $this->opt = $this->get_option($this->unique_prefix . '_options');
     816            //Create a DOM document
     817            $dom = new \DOMDocument('1.0', 'UTF-8');
     818            //Adds in newlines and tabs to the output
     819            $dom->formatOutput = true;
     820            //We're not using a DTD therefore we need to specify it as a standalone document
     821            $dom->xmlStandalone = true;
     822            //Add an element called options
     823            $node = $dom->createElement('options');
     824            $parnode = $dom->appendChild($node);
     825            //Add a child element named plugin
     826            $node = $dom->createElement('plugin');
     827            $plugnode = $parnode->appendChild($node);
     828            //Add some attributes that identify the plugin and version for the options export
     829            $plugnode->setAttribute('name', $this->short_name);
     830            $plugnode->setAttribute('version', $this::version);
     831            //Change our header to text/xml for direct save
     832            header('Cache-Control: public');
     833            //The next two will cause good browsers to download instead of displaying the file
     834            header('Content-Description: File Transfer');
     835            header('Content-disposition: attachment; filename=' . $this->unique_prefix . '_settings.xml');
     836            header('Content-Type: text/xml');
     837            //Loop through the options array
     838            foreach($this->opt as $key=>$option)
     839            {
     840                if(is_array($option))
     841                {
     842                    continue;
     843                }
     844                //Add a option tag under the options tag, store the option value
     845                $node = $dom->createElement('option', htmlentities($option, ENT_COMPAT | ENT_XML1, 'UTF-8'));
     846                $newnode = $plugnode->appendChild($node);
     847                //Change the tag's name to that of the stored option
     848                $newnode->setAttribute('name', $key);
     849            }
     850            //Prepare the XML for output
     851            $output_escaped = $dom->saveXML();
     852            //Let the browser know how long the file is
     853            header('Content-Length: ' . strlen($output_escaped)); // binary length
     854            //Output the file
     855            echo $output_escaped;
     856            //Prevent WordPress from continuing on
     857            die();
     858        }
     859    }
     860    /**
     861     * Imports a XML options document
     862     *
     863     * FIXME: Where is the input sanitization/validation?
     864     */
     865    public function opts_import()
     866    {
     867        //Check if the user has permissions to do this
     868        $this->security();
     869        //Our quick and dirty error suppressor
     870        $error_handler = function($errno, $errstr, $eerfile, $errline, $errcontext)
     871        {
     872            return true;
     873        };
     874        //Do a nonce check, prevent malicious link/form problems
     875        if(check_admin_referer($this->unique_prefix . '_admin_import_export'))
     876        {
     877            //Set the backup options in the DB to the current options
     878            $this->opts_backup();
     879            //Create a DOM document
     880            $dom = new \DOMDocument('1.0', 'UTF-8');
     881            //We want to catch errors ourselves
     882            set_error_handler($error_handler);
     883            //Load the user uploaded file, handle failure gracefully
     884            if(isset($_FILES[$this->unique_prefix . '_admin_import_file']['tmp_name']) && is_uploaded_file($_FILES[$this->unique_prefix . '_admin_import_file']['tmp_name']) && $dom->load($_FILES[$this->unique_prefix . '_admin_import_file']['tmp_name']))
     885            {
     886                $opts_temp = array();
     887                $version = '';
     888                //Have to use an xpath query otherwise we run into problems
     889                $xpath = new \DOMXPath($dom); 
     890                $option_sets = $xpath->query('plugin');
     891                //Loop through all of the xpath query results
     892                foreach($option_sets as $options)
     893                {
     894                    //We only want to import options for only this plugin
     895                    if($options->getAttribute('name') === $this->short_name)
     896                    {
     897                        //Grab the file version
     898                        $version = $options->getAttribute('version');
     899                        //Loop around all of the options
     900                        foreach($options->getelementsByTagName('option') as $child)
     901                        {
     902                            //Place the option into the option array, DOMDocument decodes html entities for us
     903                            $opts_temp[$child->getAttribute('name')] = $child->nodeValue;
     904                        }
     905                    }
     906                }
    771907                //Act as if the JSON file was just a bunch of POST entries for a settings save
    772908                //Run through the loop and get the diff from defaults
    773                 $new_settings = $this->get_settings_diff($settings_upload['settings'], true);
     909                //this isn't obvious but calls adminkit::settings_update_loop() which calls setting::maybe_update_from_form_input which performs sanitization on a per setting basis
     910                $new_settings = $this->get_settings_diff($opts_temp, true);
    774911                //FIXME: Eventually we'll save the object array, but not today
    775912                //Convert to opts array for saving
     
    778915                //Make sure we safely import and upgrade settings if needed
    779916                $this->opts_upgrade($this->opt, $settings_upload['version']);
    780                 //Commit the option changes
    781                 $updated = $this->update_option($this->unique_prefix . '_options', $this->opt, true);
    782                 //Check if known settings match attempted save
    783                 if($updated && count(array_diff_key($settings_upload['settings'], $this->settings)) == 0)
    784                 {
    785                     //Let the user know everything went ok
    786                     $this->messages[] = new message(esc_html__('Settings successfully imported from the uploaded file.', $this->identifier)
    787                             . $this->admin_anchor('undo', __('Undo the options import.', $this->identifier), __('Undo', $this->identifier)), 'success');
    788                 }
    789                 else
    790                 {
    791                     $this->messages[] = new message(esc_html__('No settings were imported. Settings from uploaded file matched existing settings.', $this->identifier), 'info');
    792                 }
    793                 //Output any messages that there may be
    794                 add_action('admin_notices', array($this, 'messages'));
    795                 //And return as we're successful
    796                 return;
    797             }
    798             //If it wasn't JSON, try XML
     917               
     918                //Commit the loaded options to the database
     919                $this->update_option($this->unique_prefix . '_options', $this->opt, true);
     920                //Everything was successful, let the user know
     921                $this->messages[] = new message(esc_html__('Settings successfully imported from the uploaded file.', $this->identifier)
     922                    . $this->admin_anchor('undo', __('Undo the options import.', $this->identifier), __('Undo', $this->identifier)), 'success');
     923            }
    799924            else
    800925            {
    801                 return $this->opts_import();
    802             }
    803         }
    804         //Throw an error since we could not load the file for various reasons
    805         $this->messages[] = new message(esc_html__('Importing settings from file failed.', $this->identifier), 'error');
    806     }
    807     /**
    808      * Exports a XML options document
    809      * @deprecated 7.5.0
    810      */
    811     function opts_export()
    812     {
    813         _deprecated_function( __FUNCTION__, '7.5.0', '\mtekk\adminKit::settings_export');
    814         //Do a nonce check, prevent malicious link/form problems
    815         check_admin_referer($this->unique_prefix . '_admin_import_export');
    816         //Update our internal settings
    817         $this->opt = $this->get_option($this->unique_prefix . '_options');
    818         //Create a DOM document
    819         $dom = new \DOMDocument('1.0', 'UTF-8');
    820         //Adds in newlines and tabs to the output
    821         $dom->formatOutput = true;
    822         //We're not using a DTD therefore we need to specify it as a standalone document
    823         $dom->xmlStandalone = true;
    824         //Add an element called options
    825         $node = $dom->createElement('options');
    826         $parnode = $dom->appendChild($node);
    827         //Add a child element named plugin
    828         $node = $dom->createElement('plugin');
    829         $plugnode = $parnode->appendChild($node);
    830         //Add some attributes that identify the plugin and version for the options export
    831         $plugnode->setAttribute('name', $this->short_name);
    832         $plugnode->setAttribute('version', $this::version);
    833         //Change our header to text/xml for direct save
    834         header('Cache-Control: public');
    835         //The next two will cause good browsers to download instead of displaying the file
    836         header('Content-Description: File Transfer');
    837         header('Content-disposition: attachment; filename=' . $this->unique_prefix . '_settings.xml');
    838         header('Content-Type: text/xml');
    839         //Loop through the options array
    840         foreach($this->opt as $key=>$option)
    841         {
    842             if(is_array($option))
    843             {
    844                 continue;
    845             }
    846             //Add a option tag under the options tag, store the option value
    847             $node = $dom->createElement('option', htmlentities($option, ENT_COMPAT | ENT_XML1, 'UTF-8'));
    848             $newnode = $plugnode->appendChild($node);
    849             //Change the tag's name to that of the stored option
    850             $newnode->setAttribute('name', $key);
    851         }
    852         //Prepare the XML for output
    853         $output = $dom->saveXML();
    854         //Let the browser know how long the file is
    855         header('Content-Length: ' . strlen($output)); // binary length
    856         //Output the file
    857         echo $output;
    858         //Prevent WordPress from continuing on
    859         die();
    860     }
    861     /**
    862      * Imports a XML options document
    863      */
    864     function opts_import()
    865     {
    866         //Our quick and dirty error suppressor
    867         $error_handler = function($errno, $errstr, $eerfile, $errline, $errcontext)
    868         {
    869             return true;
    870         };
     926                //Throw an error since we could not load the file for various reasons
     927                $this->messages[] = new message(esc_html__('Importing settings from file failed.', $this->identifier), 'error');
     928            }
     929            //Reset to the default error handler after we're done
     930            restore_error_handler();
     931            //Output any messages that there may be
     932            add_action('admin_notices', array($this, 'messages'));
     933        }
     934    }
     935    /**
     936     * Resets the database settings array to the default set in opt
     937     */
     938    public function opts_reset()
     939    {
     940        //Check if the user has permissions to do this
     941        $this->security();
    871942        //Do a nonce check, prevent malicious link/form problems
    872         check_admin_referer($this->unique_prefix . '_admin_import_export');
    873         //Set the backup options in the DB to the current options
    874         $this->opts_backup();
    875         //Create a DOM document
    876         $dom = new \DOMDocument('1.0', 'UTF-8');
    877         //We want to catch errors ourselves
    878         set_error_handler($error_handler);
    879         //Load the user uploaded file, handle failure gracefully
    880         if(is_uploaded_file($_FILES[$this->unique_prefix . '_admin_import_file']['tmp_name']) && $dom->load($_FILES[$this->unique_prefix . '_admin_import_file']['tmp_name']))
    881         {
    882             $opts_temp = array();
    883             $version = '';
    884             //Have to use an xpath query otherwise we run into problems
    885             $xpath = new \DOMXPath($dom); 
    886             $option_sets = $xpath->query('plugin');
    887             //Loop through all of the xpath query results
    888             foreach($option_sets as $options)
    889             {
    890                 //We only want to import options for only this plugin
    891                 if($options->getAttribute('name') === $this->short_name)
    892                 {
    893                     //Grab the file version
    894                     $version = $options->getAttribute('version');
    895                     //Loop around all of the options
    896                     foreach($options->getelementsByTagName('option') as $child)
    897                     {
    898                         //Place the option into the option array, DOMDocument decodes html entities for us
    899                         $opts_temp[$child->getAttribute('name')] = $child->nodeValue;
    900                     }
    901                 }
    902             }
    903             //Make sure we safely import and upgrade settings if needed
    904             $this->opts_upgrade($opts_temp, $version);
    905             //Commit the loaded options to the database
    906             $this->update_option($this->unique_prefix . '_options', $this->opt, true);
    907             //Everything was successful, let the user know
    908             $this->messages[] = new message(esc_html__('Settings successfully imported from the uploaded file.', $this->identifier)
    909                 . $this->admin_anchor('undo', __('Undo the options import.', $this->identifier), __('Undo', $this->identifier)), 'success');
    910         }
    911         else
    912         {
    913             //Throw an error since we could not load the file for various reasons
    914             $this->messages[] = new message(esc_html__('Importing settings from file failed.', $this->identifier), 'error');
    915         }
    916         //Reset to the default error handler after we're done
    917         restore_error_handler();
    918         //Output any messages that there may be
    919         add_action('admin_notices', array($this, 'messages'));
    920     }
    921     /**
    922      * Resets the database settings array to the default set in opt
    923      */
    924     function opts_reset()
    925     {
     943        if(check_admin_referer($this->unique_prefix . '_admin_import_export'))
     944        {
     945            //Set the backup options in the DB to the current options
     946            $this->opts_backup();
     947            //Load in the hard coded default option values
     948            $this->update_option($this->unique_prefix . '_options', array(), true);
     949            //Reset successful, let the user know
     950            $this->messages[] = new message(esc_html__('Settings successfully reset to the default values.', $this->identifier)
     951                . $this->admin_anchor('undo', __('Undo the options reset.', $this->identifier), __('Undo', $this->identifier)), 'success');
     952            add_action('admin_notices', array($this, 'messages'));
     953        }
     954    }
     955    /**
     956     * Undos the last settings save/reset/import
     957     */
     958    public function opts_undo()
     959    {
     960        //Check if the user has permissions to do this
     961        $this->security();
    926962        //Do a nonce check, prevent malicious link/form problems
    927         check_admin_referer($this->unique_prefix . '_admin_import_export');
    928         //Set the backup options in the DB to the current options
    929         $this->opts_backup();
    930         //Load in the hard coded default option values
    931         $this->update_option($this->unique_prefix . '_options', array(), true);
    932         //Reset successful, let the user know
    933         $this->messages[] = new message(esc_html__('Settings successfully reset to the default values.', $this->identifier)
    934             . $this->admin_anchor('undo', __('Undo the options reset.', $this->identifier), __('Undo', $this->identifier)), 'success');
    935         add_action('admin_notices', array($this, 'messages'));
    936     }
    937     /**
    938      * Undos the last settings save/reset/import
    939      */
    940     function opts_undo()
    941     {
    942         //Do a nonce check, prevent malicious link/form problems
    943         check_admin_referer($this->unique_prefix . '_admin_undo');
    944         //Set the options array to the current options
    945         $opt = $this->get_option($this->unique_prefix . '_options');
    946         //Set the options in the DB to the backup options
    947         $this->update_option($this->unique_prefix . '_options', $this->get_option($this->unique_prefix . '_options_bk'), true);
    948         //Set the backup options to the undone options
    949         $this->update_option($this->unique_prefix . '_options_bk', $opt, false);
    950         //Send the success/undo message
    951         $this->messages[] = new message(esc_html__('Settings successfully undid the last operation.', $this->identifier)
    952             . $this->admin_anchor('undo', __('Undo the last undo operation.', $this->identifier), __('Undo', $this->identifier)), 'success');
    953         add_action('admin_notices', array($this, 'messages'));
     963        if(check_admin_referer($this->unique_prefix . '_admin_undo'))
     964        {
     965            //Set the options array to the current options
     966            $opt = $this->get_option($this->unique_prefix . '_options');
     967            //Set the options in the DB to the backup options
     968            $this->update_option($this->unique_prefix . '_options', $this->get_option($this->unique_prefix . '_options_bk'), true);
     969            //Set the backup options to the undone options
     970            $this->update_option($this->unique_prefix . '_options_bk', $opt, false);
     971            //Send the success/undo message
     972            $this->messages[] = new message(esc_html__('Settings successfully undid the last operation.', $this->identifier)
     973                . $this->admin_anchor('undo', __('Undo the last undo operation.', $this->identifier), __('Undo', $this->identifier)), 'success');
     974            add_action('admin_notices', array($this, 'messages'));
     975        }
    954976    }
    955977    /**
     
    959981     * @param string $version the version of the passed in options
    960982     */
    961     function opts_upgrade($opts, $version)
     983    public function opts_upgrade($opts, $version)
    962984    {
    963985        //We don't support using newer versioned option files in older releases
     
    972994     * FIXME: seems there is a lot of very similar code in install
    973995     */
    974     function opts_upgrade_wrapper()
    975     {
     996    public function opts_upgrade_wrapper()
     997    {
     998        //Check if the user has permissions to do this
     999        $this->security();
    9761000        //Do a nonce check, prevent malicious link/form problems
    977         check_admin_referer($this->unique_prefix . '_admin_upgrade');
    978         //Grab the database options
    979         $opts = $this->get_option($this->unique_prefix . '_options');
    980         if(is_array($opts))
    981         {
    982             //Feed the just read options into the upgrade function
    983             $this->opts_upgrade($opts, $this->get_option($this->unique_prefix . '_version'));
    984             //Always have to update the version
    985             $this->update_option($this->unique_prefix . '_version', $this::version, false);
    986             //Store the options
    987             $this->update_option($this->unique_prefix . '_options', $this->opt, true);
    988             //Send the success message
    989             $this->messages[] = new message(esc_html__('Settings successfully migrated.', $this->identifier), 'success');
    990         }
    991         else
    992         {
    993             //Run the install script
    994             $this->install();
    995             //Send the success message
    996             $this->messages[] = new message(esc_html__('Default settings successfully installed.', $this->identifier), 'success');
    997         }
    998         add_action('admin_notices', array($this, 'messages'));
     1001        if(check_admin_referer($this->unique_prefix . '_admin_upgrade'))
     1002        {
     1003            //Grab the database options
     1004            $opts = $this->get_option($this->unique_prefix . '_options');
     1005            if(is_array($opts))
     1006            {
     1007                //Feed the just read options into the upgrade function
     1008                $this->opts_upgrade($opts, $this->get_option($this->unique_prefix . '_version'));
     1009                //Always have to update the version
     1010                $this->update_option($this->unique_prefix . '_version', $this::version, false);
     1011                //Store the options
     1012                $this->update_option($this->unique_prefix . '_options', $this->opt, true);
     1013                //Send the success message
     1014                $this->messages[] = new message(esc_html__('Settings successfully migrated.', $this->identifier), 'success');
     1015            }
     1016            else
     1017            {
     1018                //Run the install script
     1019                $this->install();
     1020                //Send the success message
     1021                $this->messages[] = new message(esc_html__('Default settings successfully installed.', $this->identifier), 'success');
     1022            }
     1023            add_action('admin_notices', array($this, 'messages'));
     1024        }
    9991025    }
    10001026    /**
     
    10041030     *
    10051031     */
    1006     function help()
     1032    public function help()
    10071033    {
    10081034        $screen = get_current_screen();
     
    10181044        }
    10191045    }
    1020     function help_contents(\WP_Screen &$screen)
     1046    public function help_contents(\WP_Screen &$screen)
    10211047    {
    10221048       
    10231049    }
    1024     function dismiss_message()
    1025     {
     1050    //FIXME: There just has to be a better way...
     1051    public function dismiss_message()
     1052    {
     1053        $this->security();
    10261054        //Grab the submitted UID
    1027         $uid = esc_attr($_POST['uid']);
     1055        $uid = sanitize_html_class(wp_unslash($_POST['uid']));
    10281056        //Create a dummy message, with the discovered UID
    10291057        $message = new message('', '', true, $uid);
     
    10351063     * Prints to screen all of the messages stored in the message member variable
    10361064     */
    1037     function messages()
     1065    public function messages()
    10381066    {
    10391067        foreach($this->messages as $message)
     
    10441072        if(is_array($this->message) && count($this->message))
    10451073        {
    1046             _deprecated_function( __FUNCTION__, '2.0.0', __('adminKit::message is deprecated, use new adminkit_messages instead.', $this->identifier) );
     1074            _deprecated_function( __FUNCTION__, '2.0.0', esc_html__('adminKit::message is deprecated, use new adminkit_messages instead.', $this->identifier) );
    10471075            //Loop through our message classes
    10481076            foreach($this->message as $key => $class)
     
    10511079                foreach($class as $message)
    10521080                {
    1053                     printf('<div class="%s"><p>%s</p></div>', esc_attr($key), $message);   
     1081                    printf('<div class="%s"><p>%s</p></div>', esc_attr($key), wp_kses($message, wp_kses_allowed_html('post')));
    10541082                }
    10551083            }
     
    10611089     * Function prototype to prevent errors
    10621090     */
    1063     function admin_styles()
     1091    public function admin_styles()
    10641092    {
    10651093
     
    10681096     * Function prototype to prevent errors
    10691097     */
    1070     function admin_scripts()
     1098    public function admin_scripts()
    10711099    {
    10721100
     
    10751103     * Function prototype to prevent errors
    10761104     */
    1077     function admin_head()
     1105    public function admin_head()
    10781106    {
    10791107
     
    10821110     * Function prototype to prevent errors
    10831111     */
    1084     function admin_page()
     1112    public function admin_page()
    10851113    {
    10861114
     
    11121140        }
    11131141    }
    1114     function import_form()
     1142    public function import_form()
    11151143    {
    11161144        $form = '<div id="mtekk_admin_import_export_relocate">';
     
    11271155        $form .= esc_html__('Select a JSON or XML settings file to upload and import settings from.', $this->identifier);
    11281156        $form .= '</p></td></tr></table><p class="submit">';
    1129         $form .= sprintf('<input type="submit" class="button" name="%1$s_admin_settings_import" value="%2$s"/>', $this->unique_prefix, esc_attr__('Import', $this->identifier));
    1130         $form .= sprintf('<input type="submit" class="button" name="%1$s_admin_settings_export" value="%2$s"/>', $this->unique_prefix, esc_attr__('Export', $this->identifier));
    1131         $form .= sprintf('<input type="submit" class="button" name="%1$s_admin_reset" value="%2$s"/>', $this->unique_prefix, esc_attr__('Reset', $this->identifier));
     1157        $form .= sprintf('<input type="submit" class="button" name="%1$s_admin_settings_import" value="%2$s"/>', esc_attr($this->unique_prefix), esc_attr__('Import', $this->identifier));
     1158        $form .= sprintf('<input type="submit" class="button" name="%1$s_admin_settings_export" value="%2$s"/>', esc_attr($this->unique_prefix), esc_attr__('Export', $this->identifier));
     1159        $form .= sprintf('<input type="submit" class="button" name="%1$s_admin_reset" value="%2$s"/>', esc_attr($this->unique_prefix), esc_attr__('Reset', $this->identifier));
    11321160        $form .= '</p></fieldset></form></div>';
    11331161        return $form;
     
    11401168     * @deprecated 7.0.0
    11411169     */
    1142     function input_hidden($option)
     1170    public function input_hidden($option)
    11431171    {
    11441172        _deprecated_function( __FUNCTION__, '7.0', '\mtekk\adminKit\form::input_hidden');
     
    11551183     * @deprecated 7.0.0
    11561184     */
    1157     function label($opt_id, $label)
     1185    public function label($opt_id, $label)
    11581186    {
    11591187        _deprecated_function( __FUNCTION__, '7.0', '\mtekk\adminKit\form::label');
    1160         printf('<label for="%1$s">%2$s</label>', esc_attr($opt_id), $label);
     1188        printf('<label for="%1$s">%2$s</label>', esc_attr($opt_id), esc_html($label));
    11611189    }
    11621190    /**
     
    11711199     * @deprecated 7.0.0
    11721200     */
    1173     function input_text($label, $option, $class = 'regular-text', $disable = false, $description = '')
     1201    public function input_text($label, $option, $class = 'regular-text', $disable = false, $description = '')
    11741202    {
    11751203        _deprecated_function( __FUNCTION__, '7.0', '\mtekk\adminKit\form::input_text');
     
    11871215            <td>
    11881216                <?php printf('<input type="text" name="%1$s" id="%2$s" value="%3$s" class="%4$s" %5$s/><br />', esc_attr($opt_name), esc_attr($opt_id), esc_attr($this->opt[$option]), esc_attr($class), disabled($disable, true, false));?>
    1189                 <?php if($description !== ''){?><p class="description"><?php echo $description;?></p><?php }?>
     1217                <?php if($description !== ''){?><p class="description"><?php echo esc_html($description);?></p><?php }?>
    11901218            </td>
    11911219        </tr>
     
    12061234     * @deprecated 7.0.0
    12071235     */
    1208     function input_number($label, $option, $class = 'small-text', $disable = false, $description = '', $min = '', $max = '', $step = '')
     1236    public function input_number($label, $option, $class = 'small-text', $disable = false, $description = '', $min = '', $max = '', $step = '')
    12091237    {
    12101238        _deprecated_function( __FUNCTION__, '7.0', '\mtekk\adminKit\form::input_number');
    12111239        $opt_id = adminKit::get_valid_id($option);
    12121240        $opt_name = $this->unique_prefix . '_options[' . $option . ']';
    1213         $extras = '';
     1241        $extras_escaped = '';
    12141242        if($min !== '')
    12151243        {
    1216             $extras .= 'min="' . esc_attr($min) . '" ';
     1244            $extras_escaped .= 'min="' . esc_attr($min) . '" ';
    12171245        }
    12181246        if($max !== '')
    12191247        {
    1220             $extras .= 'max="' . esc_attr($max) . '" ';
     1248            $extras_escaped .= 'max="' . esc_attr($max) . '" ';
    12211249        }
    12221250        if($step !== '')
    12231251        {
    1224             $extras .= 'step="' . esc_attr($step) . '" ';
     1252            $extras_escaped .= 'step="' . esc_attr($step) . '" ';
    12251253        }
    12261254        if($disable)
     
    12341262            </th>
    12351263            <td>
    1236                 <?php printf('<input type="number" name="%1$s" id="%2$s" value="%3$s" class="%4$s" %6$s%5$s/><br />', esc_attr($opt_name), esc_attr($opt_id), esc_attr($this->opt[$option]), esc_attr($class), disabled($disable, true, false), $extras);?>
    1237                 <?php if($description !== ''){?><p class="description"><?php echo $description;?></p><?php }?>
     1264                <?php printf('<input type="number" name="%1$s" id="%2$s" value="%3$s" class="%4$s" %6$s%5$s/><br />', esc_attr($opt_name), esc_attr($opt_id), esc_attr($this->opt[$option]), esc_attr($class), disabled($disable, true, false), $extras_escaped);?>
     1265                <?php if($description !== ''){?><p class="description"><?php echo esc_html($description);?></p><?php }?>
    12381266            </td>
    12391267        </tr>
     
    12511279     * @deprecated 7.0.0
    12521280     */
    1253     function textbox($label, $option, $height = '3', $disable = false, $description = '', $class = '')
     1281    public function textbox($label, $option, $height = '3', $disable = false, $description = '', $class = '')
    12541282    {
    12551283        _deprecated_function( __FUNCTION__, '7.0', '\mtekk\adminKit\form::textbox');
     
    12681296            <td>
    12691297                <?php printf('<textarea rows="%6$s" name="%1$s" id="%2$s" class="%4$s" %5$s/>%3$s</textarea><br />', esc_attr($opt_name), esc_attr($opt_id), esc_textarea($this->opt[$option]), esc_attr($class), disabled($disable, true, false), esc_attr($height));?>
    1270                     <?php if($description !== ''){?><p class="description"><?php echo $description;?></p><?php }?>
     1298                    <?php if($description !== ''){?><p class="description"><?php echo esc_html($description);?></p><?php }?>
    12711299            </td>
    12721300        </tr>
     
    12841312     * @deprecated 7.0.0
    12851313     */
    1286     function tinymce($label, $option, $height = '3', $disable = false, $description = '')
     1314    public function tinymce($label, $option, $height = '3', $disable = false, $description = '')
    12871315    {
    12881316        _deprecated_function( __FUNCTION__, '7.0', '\mtekk\adminKit\form::tinymce');
     
    13001328            <td>
    13011329                <?php printf('<textarea rows="%6$s" name="%1$s" id="%2$s" class="%4$s" %5$s/>%3$s</textarea><br />', esc_attr($opt_name), esc_attr($opt_id), esc_textarea($this->opt[$option]), esc_attr($class), disabled($disable, true, false), esc_attr($height));?>
    1302                 <?php if($description !== ''){?><p class="description"><?php echo $description;?></p><?php }?>
     1330                <?php if($description !== ''){?><p class="description"><?php echo esc_html($description);?></p><?php }?>
    13031331            </td>
    13041332        </tr>
     
    13171345     * @deprecated 7.0.0
    13181346     */
    1319     function input_check($label, $option, $instruction, $disable = false, $description = '', $class = '')
     1347    public function input_check($label, $option, $instruction, $disable = false, $description = '', $class = '')
    13201348    {
    13211349        _deprecated_function( __FUNCTION__, '7.0', '\mtekk\adminKit\form::input_check');
     
    13341362                <label for="<?php echo esc_attr( $opt_id ); ?>">
    13351363                    <?php printf('<input type="checkbox" name="%1$s" id="%2$s" value="%3$s" class="%4$s" %5$s %6$s/>', esc_attr($opt_name), esc_attr($opt_id), esc_attr($this->opt[$option]), esc_attr($class), disabled($disable, true, false), checked($this->opt[$option], true, false));?>
    1336                     <?php echo $instruction; ?>
     1364                    <?php echo esc_html($instruction); ?>
    13371365                </label><br />
    1338                 <?php if($description !== ''){?><p class="description"><?php echo $description;?></p><?php }?>
     1366                <?php if($description !== ''){?><p class="description"><?php echo esc_html($description);?></p><?php }?>
    13391367            </td>
    13401368        </tr>
     
    13521380     * @deprecated 7.0.0
    13531381     */
    1354     function input_radio($option, $value, $instruction, $disable = false, $class = '')
     1382    public function input_radio($option, $value, $instruction, $disable = false, $class = '')
    13551383    {
    13561384        _deprecated_function( __FUNCTION__, '7.0', '\mtekk\adminKit\form::input_radio');
     
    13651393        <label>
    13661394            <?php printf('<input type="radio" name="%1$s" id="%2$s" value="%3$s" class="%4$s" %5$s %6$s/>', esc_attr($opt_name), esc_attr($opt_id), esc_attr($value), esc_attr($class), disabled($disable, true, false), checked($value, $this->opt[$option], false));?>
    1367             <?php echo $instruction; ?>
     1395            <?php echo esc_html($instruction); ?>
    13681396        </label><br/>
    13691397    <?php
     
    13821410     * @deprecated 7.0.0
    13831411     */
    1384     function input_select($label, $option, $values, $disable = false, $description = '', $titles = false, $class = '')
     1412    public function input_select($label, $option, $values, $disable = false, $description = '', $titles = false, $class = '')
    13851413    {
    13861414        _deprecated_function( __FUNCTION__, '7.0', '\mtekk\adminKit\form::input_select');
     
    14031431            <td>
    14041432                <?php printf('<select name="%1$s" id="%2$s" class="%4$s" %5$s>%3$s</select><br />', esc_attr($opt_name), esc_attr($opt_id), $this->select_options($option, $titles, $values), esc_attr($class), disabled($disable, true, false));?>
    1405                 <?php if($description !== ''){?><p class="description"><?php echo $description;?></p><?php }?>
     1433                <?php if($description !== ''){?><p class="description"><?php echo esc_html($description);?></p><?php }?>
    14061434            </td>
    14071435        </tr>
     
    14201448     * @deprecated 7.0.0
    14211449     */
    1422     function select_options($optionname, $options, $values, $exclude = array())
     1450    public function select_options($optionname, $options, $values, $exclude = array())
    14231451    {
    14241452        _deprecated_function( __FUNCTION__, '7.0', '\mtekk\adminKit\form::select_options');
     
    14301458            if(!in_array($option, $exclude))
    14311459            {
    1432                 $options_html .= sprintf('<option value="%1$s" %2$s>%3$s</option>', esc_attr($values[$key]), selected($value, $values[$key], false), $option);
     1460                $options_html .= sprintf('<option value="%1$s" %2$s>%3$s</option>', esc_attr($values[$key]), selected($value, $values[$key], false), esc_html($option));
    14331461            }
    14341462        }
     
    14411469     * @return mixed The value of the option
    14421470     */
    1443     function get_option($option)
     1471    public function get_option($option)
    14441472    {
    14451473        return get_option($option);
     
    14511479     * @param mixed $newvalue The new value to set the option to
    14521480     */
    1453     function update_option($option, $newvalue, $autoload = null)
     1481    public function update_option($option, $newvalue, $autoload = null)
    14541482    {
    14551483        return update_option($option, $newvalue, $autoload);
     
    14631491     * @param string $autoload Whether or not to autoload the option, it's a string because WP is special
    14641492     */
    1465     function add_option($option, $value = '', $deprecated = '', $autoload = 'yes')
    1466     {
    1467         return add_option($option, $value, null, $autoload);
     1493    public function add_option($option, $value = '', $deprecated = '', $autoload = 'yes')
     1494    {
     1495        return add_option($option, $value, '', $autoload);
    14681496    }
    14691497    /**
     
    14721500     * @param string $option The name of the option to delete
    14731501     */
    1474     function delete_option($option)
     1502    public function delete_option($option)
    14751503    {
    14761504        return delete_option($option);
    14771505    }
     1506    /**
     1507     * Initializes localization textdomain for translations (if applicable)
     1508     *
     1509     * Will conditionally load the textdomain for translations. This is here for
     1510     * plugins that span multiple files and have localization in more than one file
     1511     *
     1512     * @return void
     1513     *
     1514     * @deprecated 7.5.1
     1515     */
     1516    public function local()
     1517    {
     1518        //Nothing to see here now that it's deprecated
     1519    }
    14781520}
  • breadcrumb-navxt/trunk/includes/adminKit/class-mtekk_adminkit_form.php

    r3411622 r3425008  
    11<?php
    22/*
    3     Copyright 2015-2023  John Havlik  (email : john.havlik@mtekk.us)
     3    Copyright 2015-2025  John Havlik  (email : john.havlik@mtekk.us)
    44
    55    This program is free software; you can redistribute it and/or modify
     
    7676    public function label($opt_id, $label)
    7777    {
    78         printf('<label for="%1$s">%2$s</label>', esc_attr($opt_id), $label);
     78        printf('<label for="%1$s">%2$s</label>', esc_attr($opt_id), esc_html($label));
    7979    }
    8080    /**
     
    111111                if($description !== '')
    112112                {
    113                     printf('<p class="description">%s</p>', $description);
     113                    printf('<p class="description">%s</p>', esc_html($description));
    114114                }?>
    115115            </td>
     
    134134        $opt_id = form::get_valid_id($option->get_name());
    135135        $opt_name = $this->unique_prefix . '_options[' . $option->get_opt_name(). ']';
    136         $extras = '';
     136        $extras_escaped = '';
    137137        if($min !== '')
    138138        {
    139             $extras .= 'min="' . esc_attr($min) . '" ';
     139            $extras_escaped.= 'min="' . esc_attr($min) . '" ';
    140140        }
    141141        if($max !== '')
    142142        {
    143             $extras .= 'max="' . esc_attr($max) . '" ';
     143            $extras_escaped.= 'max="' . esc_attr($max) . '" ';
    144144        }
    145145        if($step !== '')
    146146        {
    147             $extras .= 'step="' . esc_attr($step) . '" ';
     147            $extras_escaped.= 'step="' . esc_attr($step) . '" ';
    148148        }?>
    149149        <tr valign="top">
     
    164164                        esc_attr($class),
    165165                        disabled($disable, true, false),
    166                         $extras);
    167                 if($description !== '')
    168                 {
    169                             printf('<p class="description">%s</p>', $description);
     166                        $extras_escaped);
     167                if($description !== '')
     168                {
     169                            printf('<p class="description">%s</p>', esc_html($description));
    170170                }?>
    171171            </td>
     
    206206                if($description !== '')
    207207                {
    208                     printf('<p class="description">%s</p>', $description);
     208                    printf('<p class="description">%s</p>', esc_html($description));
    209209                }?>
    210210            </td>
     
    245245                if($description !== '')
    246246                {
    247                     printf('<p class="description">%s</p>', $description);
     247                    printf('<p class="description">%s</p>', esc_html($description));
    248248                }?>
    249249            </td>
     
    283283                            disabled($disable, true, false),
    284284                            checked($option->get_value(), true, false));
    285                     echo $instruction;?>
     285                    echo esc_html($instruction);?>
    286286                </label><br />
    287287                <?php
    288288                if($description !== '')
    289289                {
    290                     printf('<p class="description">%s</p>', $description);
     290                    printf('<p class="description">%s</p>', esc_html($description));
    291291                }?>
    292292            </td>
     
    322322                    disabled($disable, true, false),
    323323                    checked($value, $option->get_value(), false));
    324             echo $instruction; ?>
     324            echo esc_html($instruction); ?>
    325325        </label><br/>
    326326    <?php
     
    364364                if($description !== '')
    365365                {
    366                     printf('<p class="description">%s</p>', $description);
     366                    printf('<p class="description">%s</p>', esc_html($description));
    367367                }?>
    368368            </td>
     
    391391                        esc_attr($values[$key]),
    392392                        selected($current_value, $values[$key], false),
    393                         $option);
     393                        esc_html($option));
    394394            }
    395395        }
  • breadcrumb-navxt/trunk/includes/adminKit/class-mtekk_adminkit_message.php

    r2862997 r3425008  
    11<?php
    22/*
    3     Copyright 2015-2023  John Havlik  (email : john.havlik@mtekk.us)
     3    Copyright 2015-2025  John Havlik  (email : john.havlik@mtekk.us)
    44
    55    This program is free software; you can redistribute it and/or modify
     
    4242        {
    4343            //Let the user know they're doing it wrong
    44             _doing_it_wrong(__CLASS__ . '::' . __FUNCTION__, __('$uid must not be null if message is dismissible', 'mtekk_adminKit'), '1.0.0');
     44            _doing_it_wrong(__CLASS__ . '::' . __FUNCTION__, esc_html__('$uid must not be null if message is dismissible', 'mtekk_adminKit'), '1.0.0');
    4545            //Treat the message as non-dismissible
    4646            $dismissible = false;
     
    7070    public function dismiss()
    7171    {
    72         if($this->dismissible && isset($_POST['uid']) && esc_attr($_POST['uid']) === $this->uid)
     72        if($this->dismissible && isset($_POST['uid']) && sanitize_html_class($_POST['uid']) === $this->uid && check_ajax_referer($this->uid . '_dismiss', 'nonce'))
    7373        {
    74             check_ajax_referer($this->uid . '_dismiss', 'nonce');
    7574            $this->dismissed = true;
    7675            //If the message was dismissed, update the transient for 30 days
     
    9190            }
    9291            wp_enqueue_script('mtekk_adminkit_messages');
    93             printf('<div class="notice notice-%1$s is-dismissible"><p>%2$s</p><meta property="uid" content="%3$s"><meta property="nonce" content="%4$s"></div>', esc_attr($this->type), $this->contents, esc_attr($this->uid), wp_create_nonce($this->uid . '_dismiss'));
     92            printf('<div class="notice notice-%1$s is-dismissible"><p>%2$s</p><meta property="uid" content="%3$s"><meta property="nonce" content="%4$s"></div>', esc_attr($this->type),  wp_kses_post($this->contents), esc_attr($this->uid), esc_attr(wp_create_nonce($this->uid . '_dismiss')));
    9493        }
    9594        else
    9695        {
    97             printf('<div class="notice notice-%1$s"><p>%2$s</p></div>', esc_attr($this->type), $this->contents);
     96            printf('<div class="notice notice-%1$s"><p>%2$s</p></div>', esc_attr($this->type), wp_kses_post($this->contents));
    9897        }
    9998    }
  • breadcrumb-navxt/trunk/includes/adminKit/setting/class-mtekk_adminkit_setting_string.php

    r2862997 r3425008  
    4848            return $this->value;
    4949        }
    50         return esc_html($new_value);
     50        return sanitize_text_field($new_value);
    5151    }
    5252    /**
  • breadcrumb-navxt/trunk/includes/blocks/build/breadcrumb-trail/block.json

    r3411622 r3425008  
    7575  },
    7676  "usesContext": [
    77     "groupId"
     77    "postId"
    7878  ],
    7979  "selectors": {
  • breadcrumb-navxt/trunk/includes/blocks/build/breadcrumb-trail/render.php

    r3411622 r3425008  
    1414    return;
    1515}
    16 //Handle previews
    17 if(isset($_REQUEST['post_id']))
     16//Handle in-editor previews, function check to prevent requiring WP6.5
     17if(function_exists('wp_is_serving_rest_request') && wp_is_serving_rest_request() && current_user_can('read_post', absint($block->context['postId'])))
    1818{
    19     $post_id = $_REQUEST['post_id'];
    20     $preview_post = get_post($post_id);
     19    $preview_post = get_post(absint($block->context['postId']));
    2120    if($attributes['format'] === 'list')
    2221    {
     
    2928        $outer_template = '%1$s';
    3029    }
    31     $trail_string = $GLOBALS['breadcrumb_navxt']->_display_post($preview_post, true, $attributes['link'], $attributes['reverseOrder'], $attributes['ignoreCache'], $template, $outer_template);
     30    $trail_string_safe = $GLOBALS['breadcrumb_navxt']->_display_post($preview_post, true, $attributes['link'], $attributes['reverseOrder'], $attributes['ignoreCache'], $template, $outer_template);
    3231}
    3332else if($attributes['format'] === 'list')
    3433{
    35     $trail_string = bcn_display_list(true, $attributes['link'], $attributes['reverseOrder'], $attributes['ignoreCache']);
     34    $trail_string_safe = bcn_display_list(true, $attributes['link'], $attributes['reverseOrder'], $attributes['ignoreCache']);
    3635}
    3736else
    3837{
    39     $trail_string = bcn_display(true, $attributes['link'], $attributes['reverseOrder'], $attributes['ignoreCache']);
     38    $trail_string_safe = bcn_display(true, $attributes['link'], $attributes['reverseOrder'], $attributes['ignoreCache']);
    4039}
    4140if($attributes['format'] === 'list')
     
    4443<span><?php echo wp_kses_post($attributes['pretext']);?></span>
    4544<ol <?php echo wp_kses_data( get_block_wrapper_attributes( array('class' => 'breadcrumbs') ) );?>>
    46     <?php echo $trail_string; ?>
     45    <?php echo $trail_string_safe; ?>
    4746</ol>
    4847<?php
     
    6059);?>>
    6160    <span><?php echo wp_kses_post($attributes['pretext']);?></span>
    62     <?php echo $trail_string;?>
     61    <?php echo $trail_string_safe;?>
    6362</nav>
    6463<?php
     
    7776);?>>
    7877    <span><?php echo wp_kses_post($attributes['pretext']);?></span>
    79     <?php echo $trail_string;?>
     78    <?php echo $trail_string_safe;?>
    8079</div>
    8180<?php
     
    9190);?>>
    9291    <span><?php echo wp_kses_post($attributes['pretext']);?></span>
    93     <?php echo $trail_string; ?>
     92    <?php echo $trail_string_safe; ?>
    9493</div>
    9594<?php
     
    104103);?>>
    105104    <span><?php echo wp_kses_post($attributes['pretext']);?></span>
    106     <?php echo $trail_string; ?>
     105    <?php echo $trail_string_safe; ?>
    107106</div>
    108107<?php
  • breadcrumb-navxt/trunk/options_upgrade.php

    r3219937 r3425008  
    2424    function bcn_phpold()
    2525    {
    26         printf('<div class="notice notice-error"><p>' . __('Your PHP version is too old, please upgrade to a newer version. Your version is %1$s, Breadcrumb NavXT requires %2$s', 'breadcrumb-navxt') . '</p></div>', phpversion(), '5.3.0');
     26        /* translators: %1$s: User's version of PHP, %2$s: Breadcrmb NavXT minimuum PHP version */
     27        printf('<div class="notice notice-error"><p>' . esc_html__('Your PHP version is too old, please upgrade to a newer version. Your version is %1$s, Breadcrumb NavXT requires %2$s', 'breadcrumb-navxt') . '</p></div>', esc_html(phpversion()), '7.0.0');
    2728    }
    2829    //If we are in the admin, let's print a warning then return
  • breadcrumb-navxt/trunk/readme.txt

    r3411640 r3425008  
    55Requires at least: 5.8
    66Tested up to: 6.9
    7 Stable tag: 7.5.0
     7Stable tag: 7.5.1
    88Requires PHP: 7.0
    99License: GPLv2 or later
     
    5050
    5151== Changelog ==
     52= 7.5.1 =
     53Release date: December, 21st 2025
     54
     55* Behavior change: Removed deprecated `bcn_li_attributes` filter.
     56* Bug fix: Fixed issue where the block could be used to generate breadcrumb trails that were not for the current resource.
     57* Bug fix: Removed deprecated title length setting from settings page.
     58* Bug fix: Fixed issue where XML settings import did not properly validate imported settings.
     59
    5260= 7.5.0 =
    5361Release date: December, 4th 2025
Note: See TracChangeset for help on using the changeset viewer.