private static function encodeQuotedPrintable(string $string, int $lineLength, string $lineEnd) : string
{
$encoded = \Jyxo\StringUtil::fixLineEnding(trim($string), $lineEnd);
// Replaces all high ASCII characters, control codes and '='
$encoded = preg_replace_callback('~([\\000-\\010\\013\\014\\016-\\037\\075\\177-\\377])~', function ($matches) {
return '=' . sprintf('%02X', ord($matches[1]));
}, $encoded);
// Replaces tabs and spaces if on line ends
$encoded = preg_replace_callback('~([\\011\\040])' . $lineEnd . '~', function ($matches) use($lineEnd) {
return '=' . sprintf('%02X', ord($matches[1])) . $lineEnd;
}, $encoded);
$output = '';
$lines = explode($lineEnd, $encoded);
// Release from memory
unset($encoded);
foreach ($lines as $line) {
// Line length is less than maximum
if (strlen($line) <= $lineLength) {
$output .= $line . $lineEnd;
continue;
}
do {
$partLength = strlen($line);
if ($partLength > $lineLength) {
$partLength = $lineLength;
}
// Cannot break a line in the middle of a character
$pos = strrpos(substr($line, 0, $partLength), '=');
if (false !== $pos && $pos >= $partLength - 2) {
$partLength = $pos;
}
// If the last char is a break, move one character backwards
if ($partLength > 0 && ' ' == $line[$partLength - 1]) {
$partLength--;
}
// Saves string parts, trims the string and continues
$output .= substr($line, 0, $partLength);
$line = substr($line, $partLength);
// We are in the middle of a line
if (!empty($line)) {
$output .= '=';
}
$output .= $lineEnd;
} while (!empty($line));
}
return $output;
}