Delicious Bookmark this on Delicious Share on Facebook SlashdotSlashdot It! Digg! Digg



PHP : Function Reference : String Functions : quoted_printable_decode

quoted_printable_decode

Convert a quoted-printable string to an 8 bit string (PHP 4, PHP 5)
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.

Parameters

str

The input string.

Return Values

Returns the 8-bit binary string.

Code Examples / Notes » quoted_printable_decode

thomas

Try the imap_8bit function, for converting an 8bit string to a quotad printable string.

gustavf

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.


bendi

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] );
}
?>


pinkpanther

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 ' '


madmax

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


dmitry

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;
}


legolas558

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


ludwig

my approach for quoted printable encode using the stream converting abilities
<?php
/**
* @param string $str
* @return string
* */
function quoted_printable_encode($str) {
$fp = fopen('php://temp', 'w+');
stream_filter_append($fp, 'convert.quoted-printable-encode');
fwrite($fp, $str);
fseek($fp, 0);
$result = '';
while(!feof($fp))
$result .= fread($fp, 1024);
fclose($fp);
return $result;
}
?>


thomas pequet / memotoo.com

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 ?"


pob

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;


roelof

I modified the below version of legolas558 at users dot sausafe dot net and added a wrapping option.
<?php
/**
* Codeer een String naar zogenaamde 'quoted printable'. Dit type van coderen wordt
* gebruikt om de content van 8 bit e-mail berichten als 7 bits te versturen.
*
* @access public
* @param string    $str    De String die we coderen
* @param bool      $wrap   Voeg linebreaks toe na 74 tekens?
* @return string
*/
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($return, 74, " =\n")
: $return;
}
?>


tamas dot tompa

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);
}


magicaltux

I checked Thomas Pequet / Memotoo.com's quoted_printable_encode() function, and it's rather non-respective to standards...
Here's my own, fixed version :
<?php
function quoted_printable_encode($string, $linelen = 0, $linebreak="=\r\n", $breaklen = 0, $encodecrlf = false) {
       // Quoted printable encoding is rather simple.
       // Each character in the string $string should be encoded if:
       //  Character code is <0x20 (space)
       //  Character is = (as it has a special meaning: 0x3d)
       //  Character is over ASCII range (>=0x80)
       $len = strlen($string);
       $result = '';
       for($i=0;$i<$len;$i++) {
               if ($linelen >= 76) { // break lines over 76 characters, and put special QP linebreak
                       $linelen = $breaklen;
                       $result.= $linebreak;
               }
               $c = ord($string[$i]);
               if (($c==0x3d) || ($c>=0x80) || ($c<0x20)) { // in this case, we encode...
                       if ((($c==0x0A) || ($c==0x0D)) && (!$encodecrlf)) { // but not for linebreaks
                               $result.=chr($c);
                               $linelen = 0;
                               continue;
                       }
                       $result.='='.str_pad(strtoupper(dechex($c)), 2, '0');
                       $linelen += 3;
                       continue;
               }
               $result.=chr($c); // normal characters aren't encoded
               $linelen++;
       }
       return $result;
}
$test = 'This is a test !! héhéhé ....'."\r\n";
$test.= 'You can write really long pieces of text without having to worry about mail transfert. Quoted printable supports special way to handle such lines,  by instering an escaped linebreak. This linebreak, once converted back to 8bit, will disappear.';
echo quoted_printable_encode(utf8_encode($test))."\r\n";
?>
By default, the function encodes text to be used as a quoted-printable-encoded body, however by tweaking the parameters, you can get subject-header encoding and stuff like that.


sunil

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,..


soletan

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.


steffen dot weber

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().

legolas558

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 ;)
?>


drm

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] );
}
-----


umu

...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


Change Language


Follow Navioo On Twitter
addcslashes
addslashes
bin2hex
chop
chr
chunk_split
convert_cyr_string
convert_uudecode
convert_uuencode
count_chars
crc32
crypt
echo
explode
fprintf
get_html_translation_table
hebrev
hebrevc
html_entity_decode
htmlentities
htmlspecialchars_decode
htmlspecialchars
implode
join
levenshtein
localeconv
ltrim
md5_file
md5
metaphone
money_format
nl_langinfo
nl2br
number_format
ord
parse_str
print
printf
quoted_printable_decode
quotemeta
rtrim
setlocale
sha1_file
sha1
similar_text
soundex
sprintf
sscanf
str_getcsv
str_ireplace
str_pad
str_repeat
str_replace
str_rot13
str_shuffle
str_split
str_word_count
strcasecmp
strchr
strcmp
strcoll
strcspn
strip_tags
stripcslashes
stripos
stripslashes
stristr
strlen
strnatcasecmp
strnatcmp
strncasecmp
strncmp
strpbrk
strpos
strrchr
strrev
strripos
strrpos
strspn
strstr
strtok
strtolower
strtoupper
strtr
substr_compare
substr_count
substr_replace
substr
trim
ucfirst
ucwords
vfprintf
vprintf
vsprintf
wordwrap
eXTReMe Tracker