function replace_invalid_with_pct_encoding($string, $valid_chars, $case = SIMPLEPIE_SAME_CASE)
{
// Normalise case
if ($case & SIMPLEPIE_LOWERCASE) {
$string = strtolower($string);
} elseif ($case & SIMPLEPIE_UPPERCASE) {
$string = strtoupper($string);
}
// Store position and string length (to avoid constantly recalculating this)
$position = 0;
$strlen = strlen($string);
// Loop as long as we have invalid characters, advancing the position to the next invalid character
while (($position += strspn($string, $valid_chars, $position)) < $strlen) {
// If we have a % character
if ($string[$position] === '%') {
// If we have a pct-encoded section
if ($position + 2 < $strlen && strspn($string, '0123456789ABCDEFabcdef', $position + 1, 2) === 2) {
// Get the the represented character
$chr = chr(hexdec(substr($string, $position + 1, 2)));
// If the character is valid, replace the pct-encoded with the actual character while normalising case
if (strpos($valid_chars, $chr) !== false) {
if ($case & SIMPLEPIE_LOWERCASE) {
$chr = strtolower($chr);
} elseif ($case & SIMPLEPIE_UPPERCASE) {
$chr = strtoupper($chr);
}
$string = substr_replace($string, $chr, $position, 3);
$strlen -= 2;
$position++;
} else {
$string = substr_replace($string, strtoupper(substr($string, $position + 1, 2)), $position + 1, 2);
$position += 3;
}
} else {
$string = substr_replace($string, '%25', $position, 1);
$strlen += 2;
$position += 3;
}
} else {
$replacement = sprintf("%%%02X", ord($string[$position]));
$string = str_replace($string[$position], $replacement, $string);
$strlen = strlen($string);
}
}
return $string;
}