wp/lib/blobfolio/wp/bm/svg/svg_fallback.php
public static function kses_hair($attr) {
		$attributes = array();
		$mode = 0;
		$attribute = '';
		$iri_attributes = static::get_iri_attributes();

		$attr = \trim($attr);

		// Loop through the whole attribute list.
		while (\strlen($attr) !== 0) {
			$working = 0; // Was the last operation successful?

			switch ($mode) {
				case 0 : // Attribute name, href for instance.

					if (\preg_match('/^([-a-zA-Z:]+)/', $attr, $match)) {
						$attribute = $match[1];
						$working = $mode = 1;
						$attr = \preg_replace('/^[-a-zA-Z:]+/', '', $attr);
					}

					break;

				case 1 : // Equals sign or valueless ("selected").

					if (\preg_match('/^\s*=\s*/', $attr)) {
						$working = 1;
						$mode = 2;
						$attr = \preg_replace('/^\s*=\s*/', '', $attr);
						break;
					}

					if (\preg_match('/^\s+/', $attr)) {
						$working = 1;
						$mode = 0;
						if (false === \array_key_exists($attribute, $attributes)) {
							$attributes[$attribute] = array('name'=>$attribute, 'value'=>'', 'whole'=>$attribute, 'vless'=>'y');
						}
						$attr = \preg_replace('/^\s+/', '', $attr);
					}

					break;

				case 2 : // Attribute value, a URL after href= for instance.

					$attribute_value = false;

					// Double-quote.
					if (\preg_match('%^"([^"]*)"(\s+|/?$)%', $attr, $match)) {
						$attribute_value = \trim($match[1]);
						$attr = \preg_replace('/^"[^"]*"(\s+|$)/', '', $attr);
					} // Single-quote.
					elseif (\preg_match("%^'([^']*)'(\s+|/?$)%", $attr, $match)) {
						$attribute_value = \trim($match[1]);
						$attr = \preg_replace("/^'[^']*'(\s+|$)/", '', $attr);
					} // No quote.
					elseif (\preg_match("%^([^\s\"']+)(\s+|/?$)%", $attr, $match)) {
						$attribute_value = \trim($match[1]);
						$attr = \preg_replace("%^[^\s\"']+(\s+|$)%", '', $attr);
					}

					// We found a value?
					if (false !== $attribute_value) {
						$working = 1;
						$mode = 0;
						$iri = false;

						$attribute_value = static::sanitize_attribute_value($attribute_value);

						// Validate protocols.
						// IRI attributes get the full KSES treatment.
						if (
							\in_array(mb::strtolower($attribute), $iri_attributes, true) ||
							\preg_match('/^xmlns:/i', $attribute)

						) {
							$iri = true;
							$attribute_value = static::sanitize_iri_value($attribute_value);
						} // For others, we are specifically interested in removing scripty bits.
						elseif (\preg_match('/(?:\w+script):/xi', $attribute_value)) {
							$attribute_value = '';
						}

						// Save it.
						if (
							false === \array_key_exists($attribute, $attributes) &&
							(! $iri || \strlen($attribute_value))
						) {
							if (\strlen($attribute_value)) {
								$attribute_value = \esc_attr($attribute_value);
								$attributes[$attribute] = array(
									'name'=>$attribute,
									'value'=>$attribute_value,
									'whole'=>"$attribute=\"$attribute_value\"",
									'vless'=>'n',
								);
							} else {
								$attributes[$attribute] = array(
									'name'=>$attribute,
									'value'=>'',
									'whole'=>"$attribute",
									'vless'=>'y',
								);
							}
						}
					}

					break;
			} // Switch.

			if (0 === $working) {
				$attr = \wp_kses_html_error($attr);
				$mode = 0;
			}
		} // While.

		if (1 === $mode && false === \array_key_exists($attribute, $attributes)) {
			// Special case, for when the attribute list ends with a valueless
			// attribute like "selected".
			$attributes[$attribute] = array('name'=>$attribute, 'value'=>'', 'whole'=>$attribute, 'vless'=>'y');
		}

		return $attributes;
	}
public static function kses_hair($attr) {
		$attributes = array();
		$mode = 0;
		$attribute = '';
		$iri_attributes = static::get_iri_attributes();

		$attr = \trim($attr);

		// Loop through the whole attribute list.
		while (\strlen($attr) !== 0) {
			$working = 0; // Was the last operation successful?

			switch ($mode) {
				case 0 : // Attribute name, href for instance.

					if (\preg_match('/^([-a-zA-Z:]+)/', $attr, $match)) {
						$attribute = $match[1];
						$working = $mode = 1;
						$attr = \preg_replace('/^[-a-zA-Z:]+/', '', $attr);
					}

					break;

				case 1 : // Equals sign or valueless ("selected").

					if (\preg_match('/^\s*=\s*/', $attr)) {
						$working = 1;
						$mode = 2;
						$attr = \preg_replace('/^\s*=\s*/', '', $attr);
						break;
					}

					if (\preg_match('/^\s+/', $attr)) {
						$working = 1;
						$mode = 0;
						if (false === \array_key_exists($attribute, $attributes)) {
							$attributes[$attribute] = array('name'=>$attribute, 'value'=>'', 'whole'=>$attribute, 'vless'=>'y');
						}
						$attr = \preg_replace('/^\s+/', '', $attr);
					}

					break;

				case 2 : // Attribute value, a URL after href= for instance.

					$attribute_value = false;

					// Double-quote.
					if (\preg_match('%^"([^"]*)"(\s+|/?$)%', $attr, $match)) {
						$attribute_value = \trim($match[1]);
						$attr = \preg_replace('/^"[^"]*"(\s+|$)/', '', $attr);
					} // Single-quote.
					elseif (\preg_match("%^'([^']*)'(\s+|/?$)%", $attr, $match)) {
						$attribute_value = \trim($match[1]);
						$attr = \preg_replace("/^'[^']*'(\s+|$)/", '', $attr);
					} // No quote.
					elseif (\preg_match("%^([^\s\"']+)(\s+|/?$)%", $attr, $match)) {
						$attribute_value = \trim($match[1]);
						$attr = \preg_replace("%^[^\s\"']+(\s+|$)%", '', $attr);
					}

					// We found a value?
					if (false !== $attribute_value) {
						$working = 1;
						$mode = 0;
						$iri = false;

						$attribute_value = static::sanitize_attribute_value($attribute_value);

						// Validate protocols.
						// IRI attributes get the full KSES treatment.
						if (
							\in_array(mb::strtolower($attribute), $iri_attributes, true) ||
							\preg_match('/^xmlns:/i', $attribute)

						) {
							$iri = true;
							$attribute_value = static::sanitize_iri_value($attribute_value);
						} // For others, we are specifically interested in removing scripty bits.
						elseif (\preg_match('/(?:\w+script):/xi', $attribute_value)) {
							$attribute_value = '';
						}

						// Save it.
						if (
							false === \array_key_exists($attribute, $attributes) &&
							(! $iri || \strlen($attribute_value))
						) {
							if (\strlen($attribute_value)) {
								$attribute_value = \esc_attr($attribute_value);
								$attributes[$attribute] = array(
									'name'=>$attribute,
									'value'=>$attribute_value,
									'whole'=>"$attribute=\"$attribute_value\"",
									'vless'=>'n',
								);
							} else {
								$attributes[$attribute] = array(
									'name'=>$attribute,
									'value'=>'',
									'whole'=>"$attribute",
									'vless'=>'y',
								);
							}
						}
					}

					break;
			} // Switch.

			if (0 === $working) {
				$attr = \wp_kses_html_error($attr);
				$mode = 0;
			}
		} // While.

		if (1 === $mode && false === \array_key_exists($attribute, $attributes)) {
			// Special case, for when the attribute list ends with a valueless
			// attribute like "selected".
			$attributes[$attribute] = array('name'=>$attribute, 'value'=>'', 'whole'=>$attribute, 'vless'=>'y');
		}

		return $attributes;
	}
Reworking of wp_kses_hair() for SVG

@see { wp_kses_hair() }

@param string $attr Attribute(s) string.
@return array Attribute details.