public static function qEncode($input, $max_length = 75)
    {
        // Don't encode empty strings
        if (empty($input)) {
            return $input;
        }

        // Don't encode if all code points are in ASCII range 0-127
        if (!preg_match('/[\\x80-\\xff]+/', $input)) {
            return $input;
        }

        $qpHexDigits  = '0123456789ABCDEF';
        $input_length = strlen($input);
        // Substract delimiters, character set and encoding
        $line_limit   = $max_length - 12;
        $line_length  = 0;

        $output = '=?UTF-8?Q?';

        for ($i=0; $i < $input_length; $i++) {
            $char = $input[$i];
            $ascii = ord($char);

            // No encoding for all 62 alphanumeric characters
            if (48 <= $ascii && $ascii <= 57 || 65 <= $ascii && $ascii <= 90 || 97 <= $ascii && $ascii <= 122) {
                $replace_length = 1;
                $replace_char = $char;

                // Encode space as underscore (means better readability for humans)
            } elseif ($ascii == 32) {
                $replace_length = 1;
                $replace_char = '_';

                // Encode
            } else {
                $replace_length = 3;
                // Bit operation is around 10 percent faster
                // than 'strtoupper(dechex($ascii))'
                $replace_char = '='
                              . $qpHexDigits[$ascii >> 4]
                              . $qpHexDigits[$ascii & 0x0f];

                // Account for following bytes of UTF8-multi-byte
                // sequence (max. length is 4 octets, RFC3629)
                $lookahead_limit = min($i+4, $input_length);

                for ($lookahead = $i+1; $lookahead < $lookahead_limit; $lookahead++) {
                    $ascii_ff = ord($input[$lookahead]);
                    if (128 <= $ascii_ff && $ascii_ff <= 191) {
                        $replace_char .= '='
                                       . $qpHexDigits[$ascii_ff >> 4]
                                       . $qpHexDigits[$ascii_ff & 0x0f];
                        $replace_length += 3;
                        $i++;
                    } else {
                        break;
                    }
                }
            }

            // Would the line become too long?
            if ($line_length + $replace_length > $line_limit) {
                $output .= "?= =?UTF-8?Q?";
                $line_length = 0;
            }

            $output .= $replace_char;
            $line_length += $replace_length;
        }

        $output .= '?=';
        return $output;
    }
public static function qEncode($input, $max_length = 75)
    {
        // Don't encode empty strings
        if (empty($input)) {
            return $input;
        }

        // Don't encode if all code points are in ASCII range 0-127
        if (!preg_match('/[\\x80-\\xff]+/', $input)) {
            return $input;
        }

        $qpHexDigits  = '0123456789ABCDEF';
        $input_length = strlen($input);
        // Substract delimiters, character set and encoding
        $line_limit   = $max_length - 12;
        $line_length  = 0;

        $output = '=?UTF-8?Q?';

        for ($i=0; $i < $input_length; $i++) {
            $char = $input[$i];
            $ascii = ord($char);

            // No encoding for all 62 alphanumeric characters
            if (48 <= $ascii && $ascii <= 57 || 65 <= $ascii && $ascii <= 90 || 97 <= $ascii && $ascii <= 122) {
                $replace_length = 1;
                $replace_char = $char;

                // Encode space as underscore (means better readability for humans)
            } elseif ($ascii == 32) {
                $replace_length = 1;
                $replace_char = '_';

                // Encode
            } else {
                $replace_length = 3;
                // Bit operation is around 10 percent faster
                // than 'strtoupper(dechex($ascii))'
                $replace_char = '='
                              . $qpHexDigits[$ascii >> 4]
                              . $qpHexDigits[$ascii & 0x0f];

                // Account for following bytes of UTF8-multi-byte
                // sequence (max. length is 4 octets, RFC3629)
                $lookahead_limit = min($i+4, $input_length);

                for ($lookahead = $i+1; $lookahead < $lookahead_limit; $lookahead++) {
                    $ascii_ff = ord($input[$lookahead]);
                    if (128 <= $ascii_ff && $ascii_ff <= 191) {
                        $replace_char .= '='
                                       . $qpHexDigits[$ascii_ff >> 4]
                                       . $qpHexDigits[$ascii_ff & 0x0f];
                        $replace_length += 3;
                        $i++;
                    } else {
                        break;
                    }
                }
            }

            // Would the line become too long?
            if ($line_length + $replace_length > $line_limit) {
                $output .= "?= =?UTF-8?Q?";
                $line_length = 0;
            }

            $output .= $replace_char;
            $line_length += $replace_length;
        }

        $output .= '?=';
        return $output;
    }
public static function qEncode ( $ input , $ max_length = 75 ) { // Don't encode empty strings if ( empty ( $ input ) ) { return $ input ; } // Don't encode if all code points are in ASCII range 0-127 if ( ! preg_match ( '/[\\x80-\\xff]+/' , $ input ) ) { return $ input ; } $ qpHexDigits = '0123456789ABCDEF' ; $ input_length = strlen ( $ input ) ; // Substract delimiters, character set and encoding $ line_limit = $ max_length - 12 ; $ line_length = 0 ; $ output = '=?UTF-8?Q?' ; for ( $ i = 0 ; $ i < $ input_length ; $ i ++ ) { $ char = $ input [ $ i ] ; $ ascii = ord ( $ char ) ; // No encoding for all 62 alphanumeric characters if ( 48 <= $ ascii && $ ascii <= 57 || 65 <= $ ascii && $ ascii <= 90 || 97 <= $ ascii && $ ascii <= 122 ) { $ replace_length = 1 ; $ replace_char = $ char ; // Encode space as underscore (means better readability for humans) } elseif ( $ ascii == 32 ) { $ replace_length = 1 ; $ replace_char = '_' ; // Encode } else { $ replace_length = 3 ; // Bit operation is around 10 percent faster // than 'strtoupper(dechex($ascii))' $ replace_char = '=' . $ qpHexDigits [ $ ascii >> 4 ] . $ qpHexDigits [ $ ascii & 0x0f ] ; // Account for following bytes of UTF8-multi-byte // sequence (max. length is 4 octets, RFC3629) $ lookahead_limit = min ( $ i + 4 , $ input_length ) ; for ( $ lookahead = $ i + 1 ; $ lookahead < $ lookahead_limit ; $ lookahead ++ ) { $ ascii_ff = ord ( $ input [ $ lookahead ] ) ; if ( 128 <= $ ascii_ff && $ ascii_ff <= 191 ) { $ replace_char .= '=' . $ qpHexDigits [ $ ascii_ff >> 4 ] . $ qpHexDigits [ $ ascii_ff & 0x0f ] ; $ replace_length += 3 ; $ i ++ ; } else { break ; } } } // Would the line become too long? if ( $ line_length + $ replace_length > $ line_limit ) { $ output .= "?= =?UTF-8?Q?" ; $ line_length = 0 ; } $ output .= $ replace_char ; $ line_length += $ replace_length ; } $ output .= '?=' ; return $ output ; }
Q-encoding of a header field 'text' token or 'word' entity
within a 'phrase', according to RFC2047. The output is called
an 'encoded-word'; it must not be longer than 75 characters.

This might be achieved with PHP's `mbstring` functions, but
`mbstring` is a non-default extension.

For simplicity reasons this function encodes every character
except upper and lower case letters and decimal digits.

RFC: 'While there is no limit to the length of a multiple-line
header field, each line of a header field that contains one or
more 'encoded-word's is limited to 76 characters.'
The required 'folding' will not be done here, but in another
helper function.

This function must be 'multi-byte-sensitive' in a way that it
must never scatter a multi-byte character representation across
multiple encoded-words. So a 'lookahead' has been implemented,
based on the fact that for UTF-8 encoded characters any byte
except the first byte will have a leading '10' bit pattern,
which means an ASCII value >=128 and <=191.

@author Elmar Bartel
@author Michael Eichelsdoerfer
@param string $input
string to encode
@param integer $max_length
maximum line length (default: 75 chars)
@return string $output
encoded string
Q - encoding of a header field text token or word entity within a phrase according to RFC2047 . The output is called an encoded - word ; it must not be longer than 75 characters .