quoted_printable_decode

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

quoted_printable_decode --  Convert a quoted-printable string to an 8 bit string

Description

string quoted_printable_decode ( string str )

This function returns an 8-bit binary string corresponding to the decoded quoted printable string (according to RFC2045, section 6.7, not RFC2821, section 4.5.2, so additional periods are not stripped from the beginning of line). This function is similar to imap_qprint(), except this one does not require the IMAP module to work.


add a note add a note User Contributed Notes
Thomas Pequet / Memotoo.com
19-Oct-2006 09:15
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 ?"
umu
07-Feb-2006 06:38
...deed.ztinmehc-ut.zrh@umuumu@hrz.tu-chemnitz.deed...

and write [^=]{0,2} in the last regular expression
to avoid the soft linebreak "=" being the 77th char in line,
see my imap_8bit() emulation at   
http://www.php.net/manual/en/function.imap-8bit.php#61216
steffen dot weber at computerbase dot de
23-Jul-2005 05:08
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().
bendi at interia dot pl
29-Mar-2005 05:08
This function appeared twice already and in both versions it's got error in rule replacing chunk_split, because it misses the last line in encoded text if it's shorter than 73 characters.

My solution (got rid of replace_callback)
<?
function quoted_printable_encode( $sString ) {
  
/*instead of replace_callback i used <b>e</b> modifier for regex rule, which works as eval php function*/
  
$sString = preg_replace( '/[^\x21-\x3C\x3E-\x7E\x09\x20]/e', 'sprintf( "=%02x", ord ( "$0" ) ) ;'$sString );
  
/*now added to this rule one or more chars which lets last line to be matched and included in results*/
  
preg_match_all( '/.{1,73}([^=]{0,3})?/', $sString, $aMatch );
   return
implode( '=' . CR, $aMatch[0] );
}

?>
dmitry at koterov dot ru
19-Feb-2005 09:26
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;
}
drm at melp dot nl
09-Feb-2005 07:32
A easier, improved way of encoding for quoted-printable transfer:

------
function quoted_printable_encode_character ( $matches ) {
   $character = end ( $matches );
   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)
   preg_match_all ( '/.{73}([^=]{0,3})/', $string, $match ); // Rule #1
   return implode ( $newline, $match[0] );
}
-----
tamas dot tompa at kirowski dot com
20-Feb-2004 11:46
i have found a bug in pob at medienrecht dot NOSPAM dot org
's qp_enc function. in quoted printable messages need to convert the first pont in the lines too...
here is the fixed code:

function qp_enc( $input = "", $line_max = 76, $space_conv = false ) {

   $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);
   $eol = "\r\n";
   $escape = "=";
   $output = "";

       while( list(, $line) = each($lines) ) {
               //$line = rtrim($line); // remove trailing white
space -> no =20\r\n necessary
               $linlen = strlen($line);
               $newline = "";
               for($i = 0; $i < $linlen; $i++) {
                       $c = substr( $line, $i, 1 );
                       $dec = ord( $c );
                       if ( ( $i == 0 ) && ( $dec == 46 ) ) { //
convert first point in the line into =2E
                               $c = "=2E";
                       }
                       if ( $dec == 32 ) {
                               if ( $i == ( $linlen - 1 ) ) { // convert
 space at eol only
                                       $c = "=20";
                               } else if ( $space_conv ) {
                                       $c = "=20";
                               }
                       } elseif ( ($dec == 61) || ($dec < 32 ) ||
($dec > 126) ) { // always encode "\t", which is *not* required
                               $h2 = floor($dec/16);
                               $h1 = floor($dec%16);
                               $c = $escape.$hex["$h2"].$hex["$h1"];
                       }
                       if ( (strlen($newline) + strlen($c)) >=
$line_max ) { // CRLF is not counted
                               $output .= $newline.$escape.$eol; //
soft line break; " =\r\n" is okay
                               $newline = "";
                               // check if newline first character will
be point or not
                               if ( $dec == 46 ) {
                                       $c = "=2E";
                               }
                       }
                       $newline .= $c;
               } // end of for
               $output .= $newline.$eol;
       } // end of while
       return trim($output);
}
pinkpanther at swissonline dot ch
05-Jan-2003 07:31
Sorry, above I mixed up QP-Decode and UrlDecode, the example I gave above is in fact UrlDecode:

function UrlDecode($string) {
return preg_replace("/%([0-9A-Fa-f]{2})/e", "chr(hexdec('\\1'))", $string);
}

f.e. replaces '%3F' with '?'

Quoted-printable would be:

function qp_decode($string) {
return preg_replace("/=([0-9A-F]{2})/e", "chr(hexdec('\\1'))", $string);
}

f.e. replaces '=20' with ' '
pob at medienrecht dot NOSPAM dot org
19-Jul-2001 04:06
If you do not have access to imap_* and do not want to use
$message = chunk_split( base64_encode($message) );
because you want to be able to read the source of your mails, you might want to try this:
(any suggestions very welcome!)


function qp_enc($input = "quoted-printable encoding test string", $line_max = 76) {

   $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);
   $eol = "\r\n";
   $escape = "=";
   $output = "";

   while( list(, $line) = each($lines) ) {
       //$line = rtrim($line); // remove trailing white space -> no =20\r\n necessary
       $linlen = strlen($line);
       $newline = "";
       for($i = 0; $i < $linlen; $i++) {
           $c = substr($line, $i, 1);
           $dec = ord($c);
           if ( ($dec == 32) && ($i == ($linlen - 1)) ) { // convert space at eol only
               $c = "=20";
           } elseif ( ($dec == 61) || ($dec < 32 ) || ($dec > 126) ) { // always encode "\t", which is *not* required
               $h2 = floor($dec/16); $h1 = floor($dec%16);
               $c = $escape.$hex["$h2"].$hex["$h1"];
           }
           if ( (strlen($newline) + strlen($c)) >= $line_max ) { // CRLF is not counted
               $output .= $newline.$escape.$eol; // soft line break; " =\r\n" is okay
               $newline = "";
           }
           $newline .= $c;
       } // end of for
       $output .= $newline.$eol;
   }
   return trim($output);

}

$eight_bit = "\xA7 \xC4 \xD6 \xDC \xE4 \xF6 \xFC \xDF        =          xxx            yyy      zzz          \r\n"
           ." \xA7      \r \xC4 \n \xD6 \x09    ";
print $eight_bit."\r\n---------------\r\n";
$encoded = qp_enc($eight_bit);
print $encoded;
madmax at express dot ru
04-Aug-2000 08:41
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
gustavf at spamstop dot com
08-Jul-2000 01:25
This function does not recognize lowercase letters as part of the Quoted Printable encoding. RFC 1521 specifies:

Uppercase letters must be used when sending hexadecimal data, though a robust implementation may choose to recognize lowercase letters on receipt.
thomas at kenne dot dk
12-Apr-2000 07:09
Try the imap_8bit function, for converting an 8bit string to a quotad printable string.
sunil at nanjang dot com
12-Oct-1999 10:52
hi. i'm php developer in korean.

quoted print decode works well,

but <font color=blue>quoted_printable_decode(str_replace("=\r\n","",$string)</font> works better when MIME email decode.

MIME mail feeds every 76 char (maybe).
and feeding line tlanslate "=\r\n"

so, it better that use <font color=blue>quoted_printable_decode(str_replace("=\r\n","",$line)</font>
when quoted printable MIME decoding.

I test under php3.0.11,..