Menu

#341 EncodeQ() cant handle some characters

5.0
closed
nobody
None
5
2015-01-01
2010-01-24
Raul Dias
No

This is old as EncodeQ() probably. Just spoted it in a 2003 version.

The problem is that that ord() can only handle 1character at a time.
And when used in preg_replace ith the /e moifier. Some character are backslashed.
When this happens, ord() only see the slash and not the real character.

So stripping slashes is necessary before calling ord. So:

public function EncodeQ ($str, $position = 'text') {
// There should not be any EOL in the string
$encoded = preg_replace('/[\r\n]*/', '', $str);

switch (strtolower($position)) {
  case 'phrase':
    $encoded = preg_replace("/([^A-Za-z0-9!*+\/ -])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded);
    break;
  case 'comment':
    $encoded = preg_replace("/([\(\)\"])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded);
  case 'text':
  default:
    // Replace every high ascii, control =, ? and _ characters
    //TODO using /e (equivalent to eval()) is probably not a good idea
    $encoded = preg_replace('/([\000-\011\013\014\016-\037\075\077\137\177-\377])/e',
          "'='.sprintf('%02X', ord('\\1'))", $encoded);
    break;
}

becomes:

public function EncodeQ ($str, $position = 'text') {
// There should not be any EOL in the string
$encoded = preg_replace('/[\r\n]*/', '', $str);

switch (strtolower($position)) {
  case 'phrase':
    $encoded = preg_replace("/([^A-Za-z0-9!*+\/ -])/e", "'='.sprintf('%02X', ord(stripslashes('\\1')))", $encoded);
    break;
  case 'comment':
    $encoded = preg_replace("/([\(\)\"])/e", "'='.sprintf('%02X', ord(stripslashes('\\1')))", $encoded);
  case 'text':
  default:
    // Replace every high ascii, control =, ? and _ characters
    //TODO using /e (equivalent to eval()) is probably not a good idea
    $encoded = preg_replace('/([\000-\011\013\014\016-\037\075\077\137\177-\377])/e',
          "'='.sprintf('%02X', ord(stripslashes('\\1')))", $encoded);
    break;
}

Discussion

  • Stefan Kudwien

    Stefan Kudwien - 2010-08-16

    I was hit by this bug, too, and the proposed change is both correct and works.
    What Raul is referring to is this text passage in the manual for preg_replace() http://php.net/manual/en/function.preg-replace.php:

    "When using the e modifier, this function escapes some characters (namely ', ", \ and NULL) in the strings that replace the backreferences."

    A simple test case would be sending an e-mail using display name, for example:

    $mail->AddAddress('foo@example.com', 'Tim "The Book" O\'Reilly');

    At the recipient, however, the address appears as:

    Tim \The Book\ O'Reilly foo@example.com

    since the quotes are automatically escaped by preg_replace() and only the backslash comes through ord().

     
  • Marcus Bointon

    Marcus Bointon - 2013-03-21
    • status: open --> closed
    • milestone: --> 5.0
     
  • Marcus Bointon

    Marcus Bointon - 2013-03-21

    Fixed in later versions, added to unit tests on GitHub

     

Log in to post a comment.