tags:

views:

79

answers:

4

Hi,

I am working on a PHP application that has to parse strings being sent by another program. the problem is that some strings have octal characters and some other escapes in the middle.

So instead of "script>XYZ", I am getting:

\103RI\120T>XYZ%6En \151\156 d%6Fcu\155%65n..

And I need to print back this string decoded... I tried using octdec, url_decode, etc, but one only works with one char and the other doesn't decode octal... Anyone have suggestions?

A: 

Try this:

$str = '\103RI\120T>XYZ%6En \151\156 d%6Fcu\155%65n..';

// CRIPT>XYZnn in documen..
echo preg_replace(array('~\\\(\d+)~e', '~%([0-9A-F]{2})~e'), array('chr(octdec("$1"))', 'chr(hexdec("$1"))'), $str);

Regarding the %AD parts, I'm not sure what are meant to representing, could you explain?

Alix Axel
A: 
urldecode(stripcslashes("\103RI\120T>XYZ%6En \151\156 d%6Fcu\155%65n.."));
Martin Wickman
`stripcslashes()` doesn't handle `%AE`; it handles `\xAE`.
kiamlaluno
Yes, hence the urldecode...
Martin Wickman
+1  A: 

Use preg_replace_callback(). Use a pattern that matches both the octal number, and the escapes (being sure to match also the \, and % characters. Basing on the first character, the callback should be able to understand if to convert a octal number, or to convert an escape sequence.

The callback can convert the number from octal, or hexadecimal, using base_convert() (base_convert($match, 8, 10) in the first case; base_convert($match, 16, 10) in the second case).

kiamlaluno
How should the latter be handled?
Alix Axel
@Alix Axel: The difference is that the first is a octal number, and the other is a hexadecimal number. If the callback receive the character before the number, it should be able to understand if received an octal number (the number starts with `)`, or a hexadecimal number (it starts with `%`).
kiamlaluno
That's what I though, `hexdec()` as throwing an error but I've solved it now. There is no need to use a callback, `preg_replace()` will do just fine, check my answer.
Alix Axel
A: 
$octstr = '\103RI\120T>XYZ%6En \151\156 d%6Fcu\155%65n';

preg_match_all('/\\\[0-9]{3}/',$octstr,$matches);

$oct = $matches[0];

foreach($oct as $o){
    $octstr = str_replace($o,chr(octdec($o)),$octstr);
}

echo urldecode($octstr);

outputs:

CRIPT>XYZnn in documen
acmatos