/** * Filter POST variables. * * @param string $var_name * * @return mixed */ private function filter_input_post($var_name) { $val = filter_input(INPUT_POST, $var_name); if ($val) { return YMBESEO_Utils::sanitize_text_field($val); } return ''; }
/** * Clean a given option value * * @param array $option_value Old (not merged with defaults or filtered) option value to * clean according to the rules for this option. * @param string $current_version (optional) Version from which to upgrade, if not set, * version specific upgrades will be disregarded. * @param array $all_old_option_values (optional) Only used when importing old options to have * access to the real old values, in contrast to the saved ones. * * @return array Cleaned option */ protected function clean_option($option_value, $current_version = null, $all_old_option_values = null) { static $original = null; // Double-run this function to ensure renaming of the taxonomy options will work. if (!isset($original) && has_action('YMBESEO_double_clean_titles', array($this, 'clean')) === false) { add_action('YMBESEO_double_clean_titles', array($this, 'clean')); $original = $option_value; } /* Move options from very old option to this one @internal Don't rename to the 'current' names straight away as that would prevent the rename/unset combi below from working @todo [JRF] maybe figure out a smarter way to deal with this */ $old_option = null; if (isset($all_old_option_values)) { // Ok, we have an import. if (isset($all_old_option_values['YMBESEO_indexation']) && is_array($all_old_option_values['YMBESEO_indexation']) && $all_old_option_values['YMBESEO_indexation'] !== array()) { $old_option = $all_old_option_values['YMBESEO_indexation']; } } else { $old_option = get_option('YMBESEO_indexation'); } if (is_array($old_option) && $old_option !== array()) { $move = array('noindexauthor' => 'noindex-author', 'disableauthor' => 'disable-author', 'noindexdate' => 'noindex-archive', 'noindexcat' => 'noindex-category', 'noindextag' => 'noindex-post_tag', 'noindexpostformat' => 'noindex-post_format', 'noindexsubpages' => 'noindex-subpages', 'hidersdlink' => 'hide-rsdlink', 'hidefeedlinks' => 'hide-feedlinks', 'hidewlwmanifest' => 'hide-wlwmanifest', 'hideshortlink' => 'hide-shortlink'); foreach ($move as $old => $new) { if (isset($old_option[$old]) && !isset($option_value[$new])) { $option_value[$new] = $old_option[$old]; } } unset($move, $old, $new); } unset($old_option); // Fix wrongness created by buggy version 1.2.2. if (isset($option_value['title-home']) && $option_value['title-home'] === '%%sitename%% - %%sitedesc%% - 12345') { $option_value['title-home-wpseo'] = '%%sitename%% - %%sitedesc%%'; } /* Renaming these options to avoid ever overwritting these if a (bloody stupid) user / programmer would use any of the following as a custom post type or custom taxonomy: 'home', 'author', 'archive', 'search', '404', 'subpages' Similarly, renaming the tax options to avoid a custom post type and a taxonomy with the same name occupying the same option */ $rename = array('title-home' => 'title-home-wpseo', 'title-author' => 'title-author-wpseo', 'title-archive' => 'title-archive-wpseo', 'title-search' => 'title-search-wpseo', 'title-404' => 'title-404-wpseo', 'metadesc-home' => 'metadesc-home-wpseo', 'metadesc-author' => 'metadesc-author-wpseo', 'metadesc-archive' => 'metadesc-archive-wpseo', 'metakey-home' => 'metakey-home-wpseo', 'metakey-author' => 'metakey-author-wpseo', 'noindex-subpages' => 'noindex-subpages-wpseo', 'noindex-author' => 'noindex-author-wpseo', 'noindex-archive' => 'noindex-archive-wpseo'); foreach ($rename as $old => $new) { if (isset($option_value[$old]) && !isset($option_value[$new])) { $option_value[$new] = $option_value[$old]; unset($option_value[$old]); } } unset($rename, $old, $new); /** * @internal This clean-up action can only be done effectively once the taxonomies and post_types * have been registered, i.e. at the end of the init action. */ if (isset($original) && current_filter() === 'YMBESEO_double_clean_titles' || did_action('YMBESEO_double_clean_titles') > 0) { $rename = array('title-' => 'title-tax-', 'metadesc-' => 'metadesc-tax-', 'metakey-' => 'metakey-tax-', 'noindex-' => 'noindex-tax-', 'tax-hideeditbox-' => 'hideeditbox-tax-'); $taxonomy_names = get_taxonomies(array('public' => true), 'names'); $post_type_names = get_post_types(array('public' => true), 'names'); $defaults = $this->get_defaults(); if ($taxonomy_names !== array()) { foreach ($taxonomy_names as $tax) { foreach ($rename as $old_prefix => $new_prefix) { if (isset($original[$old_prefix . $tax]) && !isset($original[$new_prefix . $tax]) && (!isset($option_value[$new_prefix . $tax]) || isset($option_value[$new_prefix . $tax]) && $option_value[$new_prefix . $tax] === $defaults[$new_prefix . $tax])) { $option_value[$new_prefix . $tax] = $original[$old_prefix . $tax]; /* Check if there is a cpt with the same name as the tax, if so, we should make sure that the old setting hasn't been removed */ if (!isset($post_type_names[$tax]) && isset($option_value[$old_prefix . $tax])) { unset($option_value[$old_prefix . $tax]); } else { if (isset($post_type_names[$tax]) && !isset($option_value[$old_prefix . $tax])) { $option_value[$old_prefix . $tax] = $original[$old_prefix . $tax]; } } if ($old_prefix === 'tax-hideeditbox-') { unset($option_value[$old_prefix . $tax]); } } } } } unset($rename, $taxonomy_names, $post_type_names, $defaults, $tax, $old_prefix, $new_prefix); } /* Make sure the values of the variable option key options are cleaned as they may be retained and would not be cleaned/validated then */ if (is_array($option_value) && $option_value !== array()) { foreach ($option_value as $key => $value) { $switch_key = $this->get_switch_key($key); // Similar to validation routine - any changes made there should be made here too. switch ($switch_key) { /* text fields */ case 'title-': case 'metadesc-': case 'metakey-': case 'bctitle-ptarchive-': $option_value[$key] = YMBESEO_Utils::sanitize_text_field($value); break; case 'separator': if (!array_key_exists($value, $this->get_separator_options())) { $option_value[$key] = false; } break; /* Boolean fields */ /* Covers: * 'noindex-' * 'showdate-' * 'hideeditbox-' */ /* Boolean fields */ /* Covers: * 'noindex-' * 'showdate-' * 'hideeditbox-' */ default: $option_value[$key] = YMBESEO_Utils::validate_bool($value); break; } } unset($key, $value, $switch_key); } return $option_value; }
/** * Validate the post meta values * * @static * * @param mixed $meta_value The new value. * @param string $meta_key The full meta key (including prefix). * * @return string Validated meta value */ public static function sanitize_post_meta($meta_value, $meta_key) { $field_def = self::$meta_fields[self::$fields_index[$meta_key]['subset']][self::$fields_index[$meta_key]['key']]; $clean = self::$defaults[$meta_key]; switch (true) { case $meta_key === self::$meta_prefix . 'linkdex': $int = YMBESEO_Utils::validate_int($meta_value); if ($int !== false && $int >= 0) { $clean = strval($int); // Convert to string to make sure default check works. } break; case $field_def['type'] === 'checkbox': // Only allow value if it's one of the predefined options. if (in_array($meta_value, array('on', 'off'), true)) { $clean = $meta_value; } break; case $field_def['type'] === 'select' || $field_def['type'] === 'radio': // Only allow value if it's one of the predefined options. if (isset($field_def['options'][$meta_value])) { $clean = $meta_value; } break; case $field_def['type'] === 'multiselect' && $meta_key === self::$meta_prefix . 'meta-robots-adv': $clean = self::validate_meta_robots_adv($meta_value); break; case $field_def['type'] === 'text' && $meta_key === self::$meta_prefix . 'canonical': case $field_def['type'] === 'text' && $meta_key === self::$meta_prefix . 'redirect': // Validate as url(-part). $url = YMBESEO_Utils::sanitize_url($meta_value); if ($url !== '') { $clean = $url; } break; case $field_def['type'] === 'upload' && $meta_key === self::$meta_prefix . 'opengraph-image': // Validate as url. $url = YMBESEO_Utils::sanitize_url($meta_value, array('http', 'https', 'ftp', 'ftps')); if ($url !== '') { $clean = $url; } break; case $field_def['type'] === 'textarea': if (is_string($meta_value)) { // Remove line breaks and tabs. // @todo [JRF => Yoast] verify that line breaks and the likes aren't allowed/recommended in meta header fields. $meta_value = str_replace(array("\n", "\r", "\t", ' '), ' ', $meta_value); $clean = YMBESEO_Utils::sanitize_text_field(trim($meta_value)); } break; case 'multiselect' === $field_def['type']: $clean = $meta_value; break; case $field_def['type'] === 'text': default: if (is_string($meta_value)) { $clean = YMBESEO_Utils::sanitize_text_field(trim($meta_value)); } break; } $clean = apply_filters('YMBESEO_sanitize_post_meta_' . $meta_key, $clean, $meta_value, $field_def, $meta_key); return $clean; }
/** * Validate the meta data for one individual term and removes default values (no need to save those) * * @static * * @param array $meta_data New values. * @param array $old_meta The original values. * * @return array Validated and filtered value */ public static function validate_term_meta_data($meta_data, $old_meta) { $clean = self::$defaults_per_term; $meta_data = array_map(array('YMBESEO_Utils', 'trim_recursive'), $meta_data); if (!is_array($meta_data) || $meta_data === array()) { return $clean; } foreach ($clean as $key => $value) { switch ($key) { case 'YMBESEO_noindex': if (isset($meta_data[$key])) { if (isset(self::$no_index_options[$meta_data[$key]])) { $clean[$key] = $meta_data[$key]; } } elseif (isset($old_meta[$key])) { // Retain old value if field currently not in use. $clean[$key] = $old_meta[$key]; } break; case 'YMBESEO_sitemap_include': if (isset($meta_data[$key], self::$sitemap_include_options[$meta_data[$key]])) { $clean[$key] = $meta_data[$key]; } break; case 'YMBESEO_canonical': if (isset($meta_data[$key]) && $meta_data[$key] !== '') { $url = YMBESEO_Utils::sanitize_url($meta_data[$key]); if ($url !== '') { $clean[$key] = $url; } unset($url); } break; case 'YMBESEO_metakey': case 'YMBESEO_bctitle': if (isset($meta_data[$key])) { $clean[$key] = YMBESEO_Utils::sanitize_text_field(stripslashes($meta_data[$key])); } elseif (isset($old_meta[$key])) { // Retain old value if field currently not in use. $clean[$key] = $old_meta[$key]; } break; case 'YMBESEO_title': case 'YMBESEO_desc': default: if (isset($meta_data[$key]) && is_string($meta_data[$key])) { $clean[$key] = YMBESEO_Utils::sanitize_text_field(stripslashes($meta_data[$key])); } break; } $clean[$key] = apply_filters('YMBESEO_sanitize_tax_meta_' . $key, $clean[$key], isset($meta_data[$key]) ? $meta_data[$key] : null, isset($old_meta[$key]) ? $old_meta[$key] : null); } // Only save the non-default values. return array_diff_assoc($clean, self::$defaults_per_term); }
/** * Validate the option * * @param array $dirty New value for the option. * @param array $clean Clean value for the option, normally the defaults. * @param array $old Old value of the option. * * @return array Validated clean value for the option to be saved to the database */ protected function validate_option($dirty, $clean, $old) { foreach ($clean as $key => $value) { switch ($key) { /* Automagic Facebook connect key */ case 'fbconnectkey': if (isset($old[$key]) && $old[$key] !== '' && preg_match('`^[a-f0-9]{32}$`', $old[$key]) > 0) { $clean[$key] = $old[$key]; } else { $clean[$key] = self::get_fbconnectkey(); } break; /* Will not always exist in form */ /* Will not always exist in form */ case 'fb_admins': if (isset($dirty[$key]) && is_array($dirty[$key])) { if ($dirty[$key] === array()) { $clean[$key] = array(); } else { foreach ($dirty[$key] as $user_id => $fb_array) { /* * @todo [JRF/JRF => Yoast/whomever] add user_id validation - * are these WP user-ids or FB user-ids ? Probably FB user-ids, * if so, find out the rules for FB user-ids */ if (is_array($fb_array) && $fb_array !== array()) { foreach ($fb_array as $fb_key => $fb_value) { switch ($fb_key) { case 'name': /** * @todo [JRF => whomever] add validation for name based * on rules if there are any * Input comes from: $_GET['userrealname'] */ $clean[$key][$user_id][$fb_key] = sanitize_text_field($fb_value); break; case 'link': $clean[$key][$user_id][$fb_key] = YMBESEO_Utils::sanitize_url($fb_value); break; } } } } unset($user_id, $fb_array, $fb_key, $fb_value); } } elseif (isset($old[$key]) && is_array($old[$key])) { $clean[$key] = $old[$key]; } break; /* text fields */ /* text fields */ case 'og_frontpage_desc': case 'og_frontpage_title': if (isset($dirty[$key]) && $dirty[$key] !== '') { $clean[$key] = YMBESEO_Utils::sanitize_text_field($dirty[$key]); } break; /* url text fields - no ftp allowed */ /* url text fields - no ftp allowed */ case 'facebook_site': case 'instagram_url': case 'linkedin_url': case 'myspace_url': case 'pinterest_url': case 'plus-publisher': case 'og_default_image': case 'og_frontpage_image': case 'youtube_url': case 'google_plus_url': $this->validate_url($key, $dirty, $old, $clean); break; case 'pinterestverify': $this->validate_verification_string($key, $dirty, $old, $clean); break; /* twitter user name */ /* twitter user name */ case 'twitter_site': if (isset($dirty[$key]) && $dirty[$key] !== '') { $twitter_id = sanitize_text_field(ltrim($dirty[$key], '@')); /** * From the Twitter documentation about twitter screen names: * Typically a maximum of 15 characters long, but some historical accounts * may exist with longer names. * A username can only contain alphanumeric characters (letters A-Z, numbers 0-9) * with the exception of underscores * @link https://support.twitter.com/articles/101299-why-can-t-i-register-certain-usernames * @link https://dev.twitter.com/docs/platform-objects/users */ if (preg_match('`^[A-Za-z0-9_]{1,25}$`', $twitter_id)) { $clean[$key] = $twitter_id; } elseif (preg_match('`^http(?:s)?://(?:www\\.)?twitter\\.com/(?P<handle>[A-Za-z0-9_]{1,25})/?$`', $twitter_id, $matches)) { $clean[$key] = $matches['handle']; } else { if (isset($old[$key]) && $old[$key] !== '') { $twitter_id = sanitize_text_field(ltrim($old[$key], '@')); if (preg_match('`^[A-Za-z0-9_]{1,25}$`', $twitter_id)) { $clean[$key] = $twitter_id; } } if (function_exists('add_settings_error')) { add_settings_error($this->group_name, '_' . $key, sprintf(__('%s does not seem to be a valid Twitter user-id. Please correct.', 'ymbeseo'), '<strong>' . esc_html(sanitize_text_field($dirty[$key])) . '</strong>'), 'error'); } } unset($twitter_id); } break; case 'twitter_card_type': if (isset($dirty[$key], self::$twitter_card_types[$dirty[$key]]) && $dirty[$key] !== '') { $clean[$key] = $dirty[$key]; } break; /* boolean fields */ /* boolean fields */ case 'googleplus': case 'opengraph': case 'twitter': $clean[$key] = isset($dirty[$key]) ? YMBESEO_Utils::validate_bool($dirty[$key]) : false; break; } } /** * Only validate 'fbadminapp', so leave the clean default. */ if (isset($dirty['fbadminapp']) && !empty($dirty['fbadminapp'])) { $clean['fbadminapp'] = $dirty['fbadminapp']; } return $clean; }
/** * Emulate the WP native sanitize_text_field function in a %%variable%% safe way * * @see https://core.trac.wordpress.org/browser/trunk/src/wp-includes/formatting.php for the original * * @deprecated 1.5.6.1 * @deprecated use YMBESEO_Utils::sanitize_text_field() * @see YMBESEO_Utils::sanitize_text_field() * * @param string $value * * @return string */ public static function sanitize_text_field($value) { _deprecated_function(__FUNCTION__, 'WPSEO 1.5.6.1', 'YMBESEO_Utils::sanitize_text_field()'); return YMBESEO_Utils::sanitize_text_field($value); }