/** * Formats text for emphasized display in a placeholder inside a sentence. * * Used automatically by self::format(). * * @param string $text * The text to format (plain-text). * * @return string * The formatted text (html). */ public static function placeholder($text) { return SafeMarkup::set('<em class="placeholder">' . static::checkPlain($text) . '</em>'); }
/** * Processes an HTML attribute value and strips dangerous protocols from URLs. * * @param string $string * The string with the attribute value. * * @return string * Cleaned up and HTML-escaped version of $string. */ public static function filterBadProtocol($string) { // Get the plain text representation of the attribute value (i.e. its // meaning). $string = Html::decodeEntities($string); return SafeMarkup::checkPlain(static::stripDangerousProtocols($string)); }
/** * Replaces all occurrences of the search string with the replacement string. * * Functions identically to str_replace(), but marks the returned output as * safe if all the inputs and the subject have also been marked as safe. * * @param string|array $search * The value being searched for. An array may be used to designate multiple * values to search for. * @param string|array $replace * The replacement value that replaces found search values. An array may be * used to designate multiple replacements. * @param string $subject * The string or array being searched and replaced on. * * @return string * The passed subject with replaced values. */ public static function replace($search, $replace, $subject) { $output = str_replace($search, $replace, $subject); // If any replacement is unsafe, then the output is also unsafe, so just // return the output. if (!is_array($replace)) { if (!SafeMarkup::isSafe($replace)) { return $output; } } else { foreach ($replace as $replacement) { if (!SafeMarkup::isSafe($replacement)) { return $output; } } } // If the subject is unsafe, then the output is as well, so return it. if (!SafeMarkup::isSafe($subject)) { return $output; } else { // If we have reached this point, then all replacements were safe. If the // subject was also safe, then mark the entire output as safe. return SafeMarkup::set($output); } }
/** * Filters HTML to prevent cross-site-scripting (XSS) vulnerabilities. * * Based on kses by Ulf Harnhammar, see http://sourceforge.net/projects/kses. * For examples of various XSS attacks, see: http://ha.ckers.org/xss.html. * * This code does five things: * - Removes characters and constructs that can trick browsers. * - Makes sure all HTML entities are well-formed. * - Makes sure all HTML tags and attributes are well-formed. * - Makes sure no HTML tags contain URLs with a disallowed protocol (e.g. * javascript:). * - Marks the sanitized, XSS-safe version of $string as safe markup for * rendering. * * @param $string * The string with raw HTML in it. It will be stripped of everything that * can cause an XSS attack. * @param array $html_tags * An array of HTML tags. * @param bool $mode * (optional) Defaults to FILTER_MODE_WHITELIST ($html_tags is used as a * whitelist of allowed tags), but can also be set to FILTER_MODE_BLACKLIST * ($html_tags is used as a blacklist of disallowed tags). * * @return string * An XSS safe version of $string, or an empty string if $string is not * valid UTF-8. * * @see \Drupal\Component\Utility\Unicode::validateUtf8() * @see \Drupal\Component\Utility\SafeMarkup * * @ingroup sanitization */ public static function filter($string, $html_tags = array('a', 'em', 'strong', 'cite', 'blockquote', 'code', 'ul', 'ol', 'li', 'dl', 'dt', 'dd'), $mode = Xss::FILTER_MODE_WHITELIST) { // Only operate on valid UTF-8 strings. This is necessary to prevent cross // site scripting issues on Internet Explorer 6. if (!Unicode::validateUtf8($string)) { return ''; } // Remove NULL characters (ignored by some browsers). $string = str_replace(chr(0), '', $string); // Remove Netscape 4 JS entities. $string = preg_replace('%&\\s*\\{[^}]*(\\}\\s*;?|$)%', '', $string); // Defuse all HTML entities. $string = str_replace('&', '&', $string); // Change back only well-formed entities in our whitelist: // Decimal numeric entities. $string = preg_replace('/&#([0-9]+;)/', '&#\\1', $string); // Hexadecimal numeric entities. $string = preg_replace('/&#[Xx]0*((?:[0-9A-Fa-f]{2})+;)/', '&#x\\1', $string); // Named entities. $string = preg_replace('/&([A-Za-z][A-Za-z0-9]*;)/', '&\\1', $string); $html_tags = array_flip($html_tags); $splitter = function ($matches) use($html_tags, $mode) { return static::split($matches[1], $html_tags, $mode); }; return SafeMarkup::set(preg_replace_callback('% ( <(?=[^a-zA-Z!/]) # a lone < | # or <!--.*?--> # a comment | # or <[^>]*(>|$) # a string that starts with a <, up until the > or the end of the string | # or > # just a > )%x', $splitter, $string)); }
/** * Filters HTML to prevent cross-site-scripting (XSS) vulnerabilities. * * Based on kses by Ulf Harnhammar, see http://sourceforge.net/projects/kses. * For examples of various XSS attacks, see: http://ha.ckers.org/xss.html. * * This code does five things: * - Removes characters and constructs that can trick browsers. * - Makes sure all HTML entities are well-formed. * - Makes sure all HTML tags and attributes are well-formed. * - Makes sure no HTML tags contain URLs with a disallowed protocol (e.g. * javascript:). * - Marks the sanitized, XSS-safe version of $string as safe markup for * rendering. * * @param $string * The string with raw HTML in it. It will be stripped of everything that * can cause an XSS attack. * @param array $html_tags * An array of HTML tags. * * @return string * An XSS safe version of $string, or an empty string if $string is not * valid UTF-8. * * @see \Drupal\Component\Utility\Unicode::validateUtf8() * @see \Drupal\Component\Utility\SafeMarkup * * @ingroup sanitization */ public static function filter($string, $html_tags = array('a', 'em', 'strong', 'cite', 'blockquote', 'code', 'ul', 'ol', 'li', 'dl', 'dt', 'dd')) { // Only operate on valid UTF-8 strings. This is necessary to prevent cross // site scripting issues on Internet Explorer 6. if (!Unicode::validateUtf8($string)) { return ''; } // Remove NULL characters (ignored by some browsers). $string = str_replace(chr(0), '', $string); // Remove Netscape 4 JS entities. $string = preg_replace('%&\\s*\\{[^}]*(\\}\\s*;?|$)%', '', $string); // Defuse all HTML entities. $string = str_replace('&', '&', $string); // Change back only well-formed entities in our whitelist: // Decimal numeric entities. $string = preg_replace('/&#([0-9]+;)/', '&#\\1', $string); // Hexadecimal numeric entities. $string = preg_replace('/&#[Xx]0*((?:[0-9A-Fa-f]{2})+;)/', '&#x\\1', $string); // Named entities. $string = preg_replace('/&([A-Za-z][A-Za-z0-9]*;)/', '&\\1', $string); $html_tags = array_flip($html_tags); // Late static binding does not work inside anonymous functions. $class = get_called_class(); $splitter = function ($matches) use($html_tags, $class) { return $class::split($matches[1], $html_tags, $class); }; // Strip any tags that are not in the whitelist, then mark the text as safe // for output. All other known XSS vectors have been filtered out by this // point and any HTML tags remaining will have been deliberately allowed, so // it is acceptable to call SafeMarkup::set() on the resultant string. return SafeMarkup::set(preg_replace_callback('% ( <(?=[^a-zA-Z!/]) # a lone < | # or <!--.*?--> # a comment | # or <[^>]*(>|$) # a string that starts with a <, up until the > or the end of the string | # or > # just a > )%x', $splitter, $string)); }
/** * Asserts that a select option in the current page is checked. * * @param string $id * ID of select field to assert. * @param string $option * Option to assert. * @param string $message * (optional) A message to display with the assertion. Do not translate * messages: use format_string() to embed variables in the message text, not * t(). If left blank, a default message will be displayed. * @param string $group * (optional) The group this message is in, which is displayed in a column * in test output. Use 'Debug' to indicate this is debugging output. Do not * translate this string. Defaults to 'Browser'; most tests do not override * this default. * * @return bool * TRUE on pass, FALSE on fail. * * @todo Remove function once core issue is resolved: https://www.drupal.org/node/2530092 */ protected function assertOptionSelected($id, $option, $message = '', $group = 'Browser') { $elements = $this->xpath('//select[contains(@id, :id)]//option[@value=:option]', array(':id' => $id, ':option' => $option)); return $this->assertTrue(isset($elements[0]) && !empty($elements[0]['selected']), $message ? $message : SafeMarkup::format('Option @option for field @id is selected.', array('@option' => $option, '@id' => $id)), $group); }
/** * Formats a string for HTML display by replacing variable placeholders. * * This function replaces variable placeholders in a string with the requested * values and escapes the values so they can be safely displayed as HTML. It * should be used on any unknown text that is intended to be printed to an * HTML page (especially text that may have come from untrusted users, since * in that case it prevents cross-site scripting and other security problems). * * In most cases, you should use t() rather than calling this function * directly, since it will translate the text (on non-English-only sites) in * addition to formatting it. * * @param string $string * A string containing placeholders. The string itself is not escaped, any * unsafe content must be in $args and inserted via placeholders. * @param array $args * An associative array of replacements to make. Occurrences in $string of * any key in $args are replaced with the corresponding value, after * optional sanitization and formatting. The type of sanitization and * formatting depends on the first character of the key: * - @variable: Escaped to HTML using self::escape(). Use this as the * default choice for anything displayed on a page on the site. * - %variable: Escaped to HTML wrapped in <em> tags, which makes the * following HTML code: * @code * <em class="placeholder">text output here.</em> * @endcode * - !variable: Inserted as is, with no sanitization or formatting. Only * use this when the resulting string is being generated for one of: * - Non-HTML usage, such as a plain-text email. * - Non-direct HTML output, such as a plain-text variable that will be * printed as an HTML attribute value and therefore formatted with * self::checkPlain() as part of that. * - Some other special reason for suppressing sanitization. * * @return string * The formatted string, which is marked as safe unless sanitization of an * unsafe argument was suppressed (see above). * * @ingroup sanitization * * @see t() */ public static function format($string, array $args) { $safe = TRUE; // Transform arguments before inserting them. foreach ($args as $key => $value) { switch ($key[0]) { case '@': // Escaped only. if (!SafeMarkup::isSafe($value)) { $args[$key] = Html::escape($value); } break; case '%': default: // Escaped and placeholder. if (!SafeMarkup::isSafe($value)) { $value = Html::escape($value); } $args[$key] = '<em class="placeholder">' . $value . '</em>'; break; case '!': // Pass-through. if (!static::isSafe($value)) { $safe = FALSE; } } } $output = strtr($string, $args); if ($safe) { static::$safeStrings[$output]['html'] = TRUE; } return $output; }
/** * {@inheritdoc} */ public function orderView(OrderInterface $order) { $build = array(); // Add the hidden span for the CC details if possible. $account = \Drupal::currentUser(); if ($account->hasPermission('view cc details')) { $rows = array(); if (!empty($order->payment_details['cc_type'])) { $rows[] = t('Card type') . ': ' . SafeMarkup::checkPlain($order->payment_details['cc_type']); } if (!empty($order->payment_details['cc_owner'])) { $rows[] = t('Card owner') . ': ' . SafeMarkup::checkPlain($order->payment_details['cc_owner']); } if (!empty($order->payment_details['cc_number'])) { $rows[] = t('Card number') . ': ' . uc_credit_display_number($order->payment_details['cc_number']); } if (!empty($order->payment_details['cc_start_month']) && !empty($order->payment_details['cc_start_year'])) { $rows[] = t('Start date') . ': ' . $order->payment_details['cc_start_month'] . '/' . $order->payment_details['cc_start_year']; } if (!empty($order->payment_details['cc_exp_month']) && !empty($order->payment_details['cc_exp_year'])) { $rows[] = t('Expiration') . ': ' . $order->payment_details['cc_exp_month'] . '/' . $order->payment_details['cc_exp_year']; } if (!empty($order->payment_details['cc_issue'])) { $rows[] = t('Issue number') . ': ' . SafeMarkup::checkPlain($order->payment_details['cc_issue']); } if (!empty($order->payment_details['cc_bank'])) { $rows[] = t('Issuing bank') . ': ' . SafeMarkup::checkPlain($order->payment_details['cc_bank']); } $build['cc_info'] = array('#prefix' => '<a href="#" onclick="jQuery(this).hide().next().show();">' . t('Show card details') . '</a><div style="display: none;">', '#markup' => implode('<br />', $rows), '#suffix' => '</div>'); // Add the form to process the card if applicable. if ($account->hasPermission('process credit cards')) { $build['terminal'] = \Drupal::formBuilder()->getForm('uc_credit_order_view_form', $order->id()); } } return $build; }
/** * Formats text for emphasized display in a placeholder inside a sentence. * * @param string $text * The text to format (plain-text). * * @return string * The formatted text (html). * * @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0. * Use \Drupal\Component\Utility\SafeMarkup::placeholder() instead. */ public static function placeholder($text) { return SafeMarkup::placeholder($text); }
/** * Formats the address for display based on the country's address format. * * @return * A formatted string containing the address. */ public function __toString() { $variables = array('!company' => $this->company, '!first_name' => $this->first_name, '!last_name' => $this->last_name, '!street1' => $this->street1, '!street2' => $this->street2, '!city' => $this->city, '!postal_code' => $this->postal_code); $country = \Drupal::service('country_manager')->getCountry($this->country); if ($country) { $variables += array('!zone_code' => $this->zone ?: t('N/A'), '!zone_name' => isset($country->getZones()[$this->zone]) ? $country->getZones()[$this->zone] : t('Unknown'), '!country_name' => t($country->getName()), '!country_code2' => $country->id(), '!country_code3' => $country->getAlpha3()); $format = implode("\r\n", $country->getAddressFormat()); } else { $variables += array('!zone_code' => t('N/A'), '!zone_name' => t('Unknown'), '!country_name' => t('Unknown'), '!country_code2' => t('N/A'), '!country_code3' => t('N/A')); $format = "!company\r\n!first_name !last_name\r\n!street1\r\n!street2\r\n!city, !zone_code !postal_code\r\n!country_name_if"; } if (uc_store_default_country() != $this->country) { $variables['!country_name_if'] = $variables['!country_name']; $variables['!country_code2_if'] = $variables['!country_code2']; $variables['!country_code3_if'] = $variables['!country_code3']; } else { $variables['!country_name_if'] = ''; $variables['!country_code2_if'] = ''; $variables['!country_code3_if'] = ''; } $address = SafeMarkup::checkPlain(strtr($format, $variables)); $address = preg_replace("/\r/", '', $address); $address = preg_replace("/\n +\n/", "\n", $address); $address = trim($address, "\n"); if (\Drupal::config('uc_store.settings')->get('capitalize_address')) { $address = Unicode::strtoupper($address); } // <br> instead of <br />, because Twig will change it to <br> anyway and it's nice // to be able to test the Raw output. return nl2br($address, FALSE); }