PHP Conference Japan 2024

quoted_printable_encode

(PHP 5 >= 5.3.0, PHP 7, PHP 8)

quoted_printable_encode将8位字符串转换为quoted-printable字符串

描述

quoted_printable_encode(string $string): string

根据» RFC2045的6.7节返回一个quoted-printable字符串。

此函数类似于imap_8bit(),不同之处在于此函数不需要IMAP模块即可工作。

参数

string

输入字符串。

返回值

返回编码后的字符串。

范例

示例 #1 quoted_printable_encode() 示例

<?php

$encoded
= quoted_printable_encode('Möchten Sie ein paar Äpfel?');

var_dump($encoded);
var_dump(quoted_printable_decode($encoded));
?>

以上示例将输出

string(37) "M=C3=B6chten Sie ein paar =C3=84pfel?"
string(29) "Möchten Sie ein paar Äpfel?"

参见

添加笔记

用户贡献笔记 6条笔记

jurgen at edesign dot nl
10年前
PHP的原生实现和ericth at NOSPAM dot pennyworth dot com(如下)的函数都包含一个特性/错误(SMTP不匹配的使用),在我的以下调整中已解决。

该错误会导致包含句点字符的文本在通过这些函数后,最终以句点字符开头的编码行结束,当它通过SMTP传输时,该行上的第一个句点字符将被丢弃。

解决方案:为那些在编码后会成为行首字符的句点字符添加(另一个)前导句点。

参见 http://stackoverflow.com/a/13949483: “这是一个传输层的脏污产物……SMTP是最可能的罪魁祸首(参见邮件函数文档中的谨慎提示),但也可能存在其他类似行为的低级机制。例如,如果您调整了sendmail_path设置或使用了有问题的sendmail程序,您可能会遇到类似的问题。”

<?php
define
('PHP_QPRINT_MAXL', 75);

function
leading_dot_fixed_php_quot_print_encode($str)
{
$lp = 0;
$ret = '';
$hex = "0123456789ABCDEF";
$length = strlen($str);
$str_index = 0;

while (
$length--) {
if (((
$c = $str[$str_index++]) == "\015") && ($str[$str_index] == "\012") && $length > 0) {
$ret .= "\015";
$ret .= $str[$str_index++];
$length--;
$lp = 0;
} else {
if (
ctype_cntrl($c)
|| (
ord($c) == 0x7f)
|| (
ord($c) & 0x80)
|| (
$c == '=')
|| ((
$c == ' ') && ($str[$str_index] == "\015")))
{
if ((
$lp += 3) > PHP_QPRINT_MAXL)
{
$ret .= '=';
$ret .= "\015";
$ret .= "\012";
$lp = 3;
}
$ret .= '=';
$ret .= $hex[ord($c) >> 4];
$ret .= $hex[ord($c) & 0xf];
}
else
{
if ((++
$lp) > PHP_QPRINT_MAXL)
{
$ret .= '=';
$ret .= "\015";
$ret .= "\012";
$lp = 1;
}
$ret .= $c;
if(
$lp == 1 && $c == '.') {
$ret .= '.';
$lp++;
}
}
}
}

return
$ret;
}

?>
arnaudv6
13年前
人们希望知道并清楚地阅读RFC2045指定一行不应超过75个字符。
因此,quoted_printable_encode()在此限制处分割行。
Thorsten Glaser
14年前
两个错误

1) 你的换行符是错误的

$linebreak = "\r\n";

2) 没有空格的行继续是错误的

/*
* 空格后的文本将不得不
* 再次读取(+在空格后编码过程中产生的任何附加字符)
*
*
*
* 空格,则不要从 0 开始。
* 整行没有空格
*/
如果 (($i + $addtl_chars) > $whitesp_diff) {
$output .= substr($cur_conv_line, 0,
(strlen($cur_conv_line) - $whitesp_diff)) .
$linebreak;
$i = $i - $whitesp_diff + $addtl_chars;
} 否则 {
/* 输出续行 --mirabilos */
$output .= $cur_conv_line .
'=' . $linebreak;
}
ericth at NOSPAM dot pennyworth dot com
13年前
我已经将 PHP 5.3.8 的 quoted_printable_encode 函数重写为可在 PHP < 5.3 中使用的 PHP 函数。已在 PHP 5.2.11 上测试。

<?php
define
('PHP_QPRINT_MAXL', 75);

function
php_quot_print_encode($str)
{
$lp = 0;
$ret = '';
$hex = "0123456789ABCDEF";
$length = strlen($str);
$str_index = 0;

while (
$length--) {
if (((
$c = $str[$str_index++]) == "\015") && ($str[$str_index] == "\012") && $length > 0) {
$ret .= "\015";
$ret .= $str[$str_index++];
$length--;
$lp = 0;
} else {
if (
ctype_cntrl($c)
|| (
ord($c) == 0x7f)
|| (
ord($c) & 0x80)
|| (
$c == '=')
|| ((
$c == ' ') && ($str[$str_index] == "\015")))
{
if ((
$lp += 3) > PHP_QPRINT_MAXL)
{
$ret .= '=';
$ret .= "\015";
$ret .= "\012";
$lp = 3;
}
$ret .= '=';
$ret .= $hex[ord($c) >> 4];
$ret .= $hex[ord($c) & 0xf];
}
else
{
if ((++
$lp) > PHP_QPRINT_MAXL)
{
$ret .= '=';
$ret .= "\015";
$ret .= "\012";
$lp = 1;
}
$ret .= $c;
}
}
}

return
$ret;
}

?>
marcus at synchromedia dot co dot uk
7年前
请注意,此函数返回带有 Windows/RFC822 CRLF 换行符的 Quoted-Printable 字符串。如果将此函数的输出传递给 mail(),则可能需要先将其换行符转换为 Unix LF 样式。
tzangerl [dot] pdc {dot} kth dot se
14年前
一个对输入字符串进行 QP 编码(为 PHP < 5.3 编写的)并
同时进行自动换行的函数,目的是为了避免根据 SpamAssassin 的 MIME QP 长行规则进行分类。感谢 Matt Jeffers 指出下面 quoted_printable 脚本中的错误!

<?php
function quoted_printable_encode($input, $line_max = 75) {
$hex = array('0','1','2','3','4','5','6','7',
'8','9','A','B','C','D','E','F');
$lines = preg_split("/(?:\r\n|\r|\n)/", $input);
$linebreak = "=0D=0A=\r\n";
/* the linebreak also counts as characters in the mime_qp_long_line
* rule of spam-assassin */
$line_max = $line_max - strlen($linebreak);
$escape = "=";
$output = "";
$cur_conv_line = "";
$length = 0;
$whitespace_pos = 0;
$addtl_chars = 0;

// 迭代行
for ($j=0; $j<count($lines); $j++) {
$line = $lines[$j];
$linlen = strlen($line);

// 迭代字符
for ($i = 0; $i < $linlen; $i++) {
$c = substr($line, $i, 1);
$dec = ord($c);

$length++;

if (
$dec == 32) {
// 空格出现在行尾,需要编码
if (($i == ($linlen - 1))) {
$c = "=20";
$length += 2;
}

$addtl_chars = 0;
$whitespace_pos = $i;
} elseif ( (
$dec == 61) || ($dec < 32 ) || ($dec > 126) ) {
$h2 = floor($dec/16); $h1 = floor($dec%16);
$c = $escape . $hex["$h2"] . $hex["$h1"];
$length += 2;
$addtl_chars += 2;
}

// 超出换行长度限制,添加换行符
if ($length >= $line_max) {
$cur_conv_line .= $c;

// 只读取当前行到空格处的内容
$whitesp_diff = $i - $whitespace_pos + $addtl_chars;

/* 空格后的文本需要重新读取
* (加上编码过程中空格后产生的额外字符)
*
* 如果整行没有空格,则不要从0开始 */
if (($i + $addtl_chars) > $whitesp_diff) {
$output .= substr($cur_conv_line, 0, (strlen($cur_conv_line) -
$whitesp_diff)) . $linebreak;
$i = $i - $whitesp_diff + $addtl_chars;
} else {
$output .= $cur_conv_line . $linebreak;
}

$cur_conv_line = "";
$length = 0;
$whitespace_pos = 0;
} else {
// 未达到换行长度限制,继续读取
$cur_conv_line .= $c;
}
}
// for循环结束

$length = 0;
$whitespace_pos = 0;
$output .= $cur_conv_line;
$cur_conv_line = "";

if (
$j<=count($lines)-1) {
$output .= $linebreak;
}
}
// for循环结束

return trim($output);
}
// quoted_printable_encode函数结束
?>
To Top