文字

quoted_printable_decode

(PHP 4, PHP 5)

quoted_printable_decode将 quoted-printable 字符串转换为 8-bit 字符串

说明

string quoted_printable_decode ( string $str )

该函数返回 quoted-printable 解码之后的 8-bit 字符串 (参考 » RFC2045 的6.7章节,而不是 » RFC2821 的4.5.2章节,so additional periods are not stripped from the beginning of line)

该函数与 imap_qprint() 函数十分相似,但是该函数不需要依赖 IMAP 模块。

参数

str

输入的字符串。

返回值

返回的 8-bit 二进制字符串。

参见

  • quoted_printable_encode() - 将 8-bit 字符串转换成 quoted-printable 字符串

用户评论:

[#1] yual at inbox dot ru [2013-10-23 20:38:18]

I use a hack for this bug:

$str = str_replace("=\r\n", '', quoted_printable_encode($str));
if (strlen($str) > 73) {$str = substr($str,0,74)."=\n".substr($str,74);}

[#2] feedr [2009-03-06 14:39:37]

Another (improved) version of quoted_printable_encode(). Please note the order of the array elements in str_replace().
I've just rewritten the previous function for better readability.

<?php
if (!function_exists("quoted_printable_encode")) {
  

  
function quoted_printable_encode($string) {
        
$string str_replace(array('%20''%0D%0A''%'), array(' '"\r\n"'='), rawurlencode($string));
        
$string preg_replace('/[^\r\n]{73}[^=\r\n]{2}/'"$0=\r\n"$string);

        return 
$string;
  }
}
?>

[#3] andre at luyer dot nl [2008-11-02 12:36:51]

A small update for Andrew's code below. This one leaves the original CRLF pairs intact (and allowing the preg_replace to work as intended):

<?php
if (!function_exists("quoted_printable_encode")) {
  

  
function quoted_printable_encode($string) {
    return 
preg_replace('/[^\r\n]{73}[^=\r\n]{2}/'"$0=\r\n",
      
str_replace("%""="str_replace("%0D%0A""\r\n"
        
str_replace("%20"," ",rawurlencode($string)))));
  }
}
?>


Regards, Andr??

[#4] Karora [2008-10-19 20:27:15]

Taking a bunch of the earlier comments together, you can synthesize a nice short and reasonably efficient quoted_printable_encode function like this:

Note that I put this in my standard library file, so I wrap it in a !function_exists in order that if there is a pre-existing PHP one it will just work and this will evaluate to a noop.

<?php
if ( !function_exists("quoted_printable_encode") ) {
  

  
function quoted_printable_encode($string) {
    return 
preg_replace('/[^\r\n]{73}[^=\r\n]{2}/'"$0=\r\n"str_replace("%","=",str_replace("%20"," ",rawurlencode($string))));
  }
}
?>


Regards,
Andrew McMillan.

[#5] zg [2008-09-27 06:48:09]

<?php

function quoted_printable_encode$str$chunkLen 72 )
{
    
$offset 0;
    
    
$str strtr(rawurlencode($str), array('%' => '='));
    
$len strlen($str);
    
$enc '';
    
    while ( 
$offset $len )
    {
        if ( 
$str$offset $chunkLen } === '=' )
        {
            
$line substr($str$offset$chunkLen 1);
            
$offset += $chunkLen 1;
        }
        elseif ( 
$str$offset $chunkLen } === '=' )
        {
            
$line substr($str$offset$chunkLen 2);
            
$offset += $chunkLen 2;
        }
        else 
        {
            
$line substr($str$offset$chunkLen);
            
$offset += $chunkLen;
        }
        
        if ( 
$offset $chunkLen $len )
            
$enc .= $line ."=\n";
        else 
            
$enc .= $line;
    }
    
    return 
$enc;
}

?>

[#6] Christian Albrecht [2008-09-24 15:10:25]

In Addition to david lionhead's function:

<?php
function quoted_printable_encode($txt) {
    

    
$txt rawurldecode($txt);
    
$tmp="";
    
$line="";
    for (
$i=0;$i<strlen($txt);$i++) {
        if ((
$txt[$i]>='a' && $txt[$i]<='z') || ($txt[$i]>='A' && $txt[$i]<='Z') || ($txt[$i]>='0' && $txt[$i]<='9')) {
            
$line.=$txt[$i];
            if (
strlen($line)>=75) {
                
$tmp.="$line=\n";
                
$line="";
            }
        }
        else {
            

            
if (strlen($line)>=72) {
            
$tmp.="$line=\n";
            
$line="";
            }
            
$line.="=".sprintf("%02X",ord($txt[$i]));
        }
    }
    
$tmp.="$line\n";
    return 
$tmp;
}
?>

[#7] david at lionhead dot nl [2008-08-18 05:54:48]

My version of quoted_printable encode, as the convert.quoted-printable-encode filter breaks on outlook express. This one seems to work on express/outlook/thunderbird/gmail.

function quoted_printable_encode($txt) {
$tmp="";
$line="";
for ($i=0;$i<strlen($txt);$i++) {
if (($txt[$i]>='a' && $txt[$i]<='z') || ($txt[$i]>='A' && $txt[$i]<='Z') || ($txt[$i]>='0' && $txt[$i]<='9'))
$line.=$txt[$i];
else
$line.="=".sprintf("%02X",ord($txt[$i]));
if (strlen($line)>=75) {
$tmp.="$line=\n";
$line="";
}
}
$tmp.="$line\n";
return $tmp;
}

[#8] Bobo [2008-07-12 09:20:22]

Following up to Hoffa's function, return the result like:

chunk_split($string, 76, "=\n");

to conform to the RFC, which requires that lines are no longer than 76 chars.

[#9] h atnospam hoffa dotelidot se [2008-03-31 17:32:10]

I do like this to encode

function quoted_printable_encode($string) {
  $string = rawurlencode($string);
  $string = str_replace("%","=",$string);
  RETURN $string;
}

best regards / Hoffa

[#10] vita dot plachy at seznam dot cz [2008-03-23 08:22:46]

<?php
$text = <<<EOF
This function enables you to convert text to a quoted-printable string as well as to create encoded-words used in email headers (see http://www.faqs.org/rfcs/rfc2047.html).

No line of returned text will be longer than specified. Encoded-words will not contain a newline character. Special characters are removed.
EOF;

define('QP_LINE_LENGTH', 75);
define('QP_LINE_SEPARATOR', "\r\n");

function quoted_printable_encode($string, $encodedWord = false)
{
if(!preg_match('//u', $string)) {
throw new Exception('Input string is not valid UTF-8');
}

static $wordStart = '=?UTF-8?Q?';
static $wordEnd = '?=';
static $endl = QP_LINE_SEPARATOR;

$lineLength = $encodedWord
? QP_LINE_LENGTH - strlen($wordStart) - strlen($wordEnd)
: QP_LINE_LENGTH;

$string = $encodedWord
? preg_replace('~[\r\n]+~', ' ', $string) // we need encoded word to be single line
: preg_replace('~\r\n?~', "\n", $string); // normalize line endings
$string = preg_replace('~[\x00-\x08\x0B-\x1F]+~', '', $string); // remove control characters

$output = $encodedWord ? $wordStart : '';
$charsLeft = $lineLength;

$chr = isset($string{0}) ? $string{0} : null;
$ord = ord($chr);

for ($i = 0; isset($chr); $i++) {
$nextChr = isset($string{$i + 1}) ? $string{$i + 1} : null;
$nextOrd = ord($nextChr);

if (
$ord > 127 or // high byte value
$ord === 95 or // underscore "_"
$ord === 63 && $encodedWord or // "?" in encoded word
$ord === 61 or // equal sign "="
// space or tab in encoded word or at line end
$ord === 32 || $ord === 9 and $encodedWord || !isset($nextOrd) || $nextOrd === 10
) {
$chr = sprintf('=%02X', $ord);
}

if ($ord === 10) { // line feed
$output .= $endl;
$charsLeft = $lineLength;
} elseif (
strlen($chr) < $charsLeft or
strlen($chr) === $charsLeft and $nextOrd === 10 || $encodedWord
) { // add character
$output .= $chr;
$charsLeft-=strlen($chr);
} elseif (isset($nextOrd)) { // another line needed
$output .= $encodedWord
? $wordEnd . $endl . "\t" . $wordStart . $chr
: '=' . $endl . $chr;
$charsLeft = $lineLength - strlen($chr);
}

$chr = $nextChr;
$ord = $nextOrd;
}

return $output . ($encodedWord ? $wordEnd : '');
}

echo quoted_printable_encode($text);

[#11] ludwig at gramberg-webdesign dot de [2007-09-24 12:13:03]

my approach for quoted printable encode using the stream converting abilities

<?php

function quoted_printable_encode($str) {
    
$fp fopen('php://temp''w+');
    
stream_filter_append($fp'convert.quoted-printable-encode');
    
fwrite($fp$str);    
    
fseek($fp0);
    
$result '';
    while(!
feof($fp))
        
$result .= fread($fp1024);
    
fclose($fp);
    return 
$result;
}
?>

[#12] roelof [2007-07-24 07:06:29]

I modified the below version of legolas558 at users dot sausafe dot net and added a wrapping option.

<?php


function quoted_printable_encode($str$wrap=true)
{
    
$return '';
    
$iL strlen($str);
    for(
$i=0$i<$iL$i++)
    {
        
$char $str[$i];
        if(
ctype_print($char) && !ctype_punct($char)) $return .= $char;
        else 
$return .= sprintf('=%02X'ord($char));
    }
    return (
$wrap === true)
        ? 
wordwrap($return74" =\n")
        : 
$return;
}

?>

[#13] legolas558 at users dot sausafe dot net [2007-02-21 11:09:07]

As soletan at toxa dot de reported, that function is very bad and does not provide valid enquoted printable strings. While using it I saw spam agents marking the emails as QP_EXCESS and sometimes the email client did not recognize the header at all; I really lost time :(. This is the new version (we use it in the Drake CMS core) that works seamlessly:

<?php

//L: note $encoding that is uppercase
//L: also your PHP installation must have ctype_alpha, otherwise write it yourself
function quoted_printable_encode($string$encoding='UTF-8') {
// use this function with headers, not with the email body as it misses word wrapping
       
$len strlen($string);
       
$result '';
       
$enc false;
       for(
$i=0;$i<$len;++$i) {
        
$c $string[$i];
        if (
ctype_alpha($c))
            
$result.=$c;
        else if (
$c==' ') {
            
$result.='_';
            
$enc true;
        } else {
            
$result.=sprintf("=%02X"ord($c));
            
$enc true;
        }
       }
       
//L: so spam agents won't mark your email with QP_EXCESS
       
if (!$enc) return $string;
       return 
'=?'.$encoding.'?q?'.$result.'?=';
}

I hope it helps ;)

?>

[#14] soletan at toxa dot de [2007-02-20 15:54:02]

Be warned! The method below for encoding text does not work as requested by RFC1521!

Consider a line consisting of 75 'A' and a single ?? (or similar non-ASCII character) ... the method below would encode and return a line of 78 octets, breaking with RFC 1521, 5.1 Rule #5: "The Quoted-Printable encoding REQUIRES that encoded lines be no more than 76 characters long."

Good QP-encoding takes a bit more than this.

[#15] legolas558 [2007-02-12 10:32:59]

Please note that in the below encode function there is a bug!

<?php
if (($c==0x3d) || ($c>=0x80) || ($c<0x20))
?>


$c should be checked against less or equal to encode spaces!

so the correct code is

<?php
if (($c==0x3d) || ($c>=0x80) || ($c<=0x20))
?>


Fix the code or post this note, please

[#16] Thomas Pequet / Memotoo.com [2006-10-19 06:15:38]

If you want a function to do the reverse of "quoted_printable_decode()", follow the link you will find the "quoted_printable_encode()" function:
http://www.memotoo.com/softs/public/PHP/quoted printable_encode.inc.php

Compatible "ENCODING=QUOTED-PRINTABLE"
Example: 
quoted_printable_encode(ut8_encode("c'est quand l'??t?? ?")) 
-> "c'est quand l'=C3=A9t=C3=A9 ?"

[#17] steffen dot weber at computerbase dot de [2005-07-22 14:08:09]

As the two digit hexadecimal representation SHOULD be in uppercase you want to use "=%02X" (uppercase X) instead of "=%02x" as the first argument to sprintf().

[#18] dmitry at koterov dot ru [2005-02-19 05:26:50]

Previous comment has a bug: encoding of short test does not work because of incorrect usage of preg_match_all(). Have somebody read it at all? :-)

Correct version (seems), with additional imap_8bit() function emulation:

if (!function_exists('imap_8bit')) {
 function imap_8bit($text) {
   return quoted_printable_encode($text);
 }
}

function quoted_printable_encode_character ( $matches ) {
   $character = $matches[0];
   return sprintf ( '=%02x', ord ( $character ) );
}

// based on http://www.freesoft.org/CIE/RFC/1521/6.htm
function quoted_printable_encode ( $string ) {
   // rule #2, #3 (leaves space and tab characters in tact)
   $string = preg_replace_callback (
     '/[^\x21-\x3C\x3E-\x7E\x09\x20]/',
     'quoted_printable_encode_character',
     $string
   );
   $newline = "=\r\n"; // '=' + CRLF (rule #4)
   // make sure the splitting of lines does not interfere with escaped characters
   // (chunk_split fails here)
   $string = preg_replace ( '/(.{73}[^=]{0,3})/', '$1'.$newline, $string);
   return $string;
}

[#19] pob at medienrecht dot NOSPAM dot org [2001-07-18 13:06:09]

[#20] madmax at express dot ru [2000-08-03 17:41:08]

Some  browser (netscape, for example)
send 8-bit quoted printable text like this:
=C5=DD=A3=D2=C1= =DA

"= =" means continuos word.
 php function not detect this situations and translate in string like:
 abcde=f

上一篇: 下一篇: