Заменить защищенный член в декодированной строке base64

Допустим, у меня есть такой класс

class ClassA {
public $publicMember;
private $privateMember;
protected $protected;
}

И я закодировал объект ClassA так:

$objectA = new ClassA();
$stringA = base64_encode(serialize($objectA));

Я хочу заменить всех защищенных членов, но я не знаю как. Я пытался так:

$newString = str_replace('�*�', '', base64_decode($stringA));

Мне очень жаль, что этот вопрос прост, но я действительно не знаю, как с этим справиться. Спасибо!

0

Решение

Имя свойства предшествует длине.

string(92) "O:6:"ClassA":3:{s:12:"publicMember";N;s:21:"\000ClassA\000privateMember";N;s:12:"\000*\000protected";N;}"| property name length        ^                     ^                                    ^
| we will try to capture this part                                                      ^         ^

Вы должны уменьшить эту длину, если хотите «конвертировать» защищенные в общедоступные. Например.

class ClassA
{

public $publicMember;
private $privateMember;
protected $protected;

}

$objectA = new ClassA();
$stringA = serialize($objectA);
$converted = preg_replace_callback('@:(\d+):"\x00\*\x00@', function($match)
//                                     ^ catch the number
//                                           ^     ^    null symbols
{
$property_name_length = $match[1];
return ':' . ($property_name_length - 3) . ':"'; // reduce catched number and do not return \x00*\x00
}, $stringA);
var_dump(unserialize($converted));

Производит

class ClassA#2 (4) {
public $publicMember =>
NULL
private $privateMember =>
NULL
protected $protected =>
NULL
public $protected =>
NULL
}

Постскриптум Но этот код потерпит неудачу, когда вы начнете хранить сериализованные данные как значения членов.

1

Другие решения

Давайте попробуем другой способ:

  1. преобразовать сериализованный класс в stdClass
  2. десериализации
  3. добавить общедоступные защищенные свойства
  4. сериализации
  5. преобразовать сериализованный stdClass в оригинальный

class ClassA
{

public $publicMember;
private $privateMember;
protected $protected;

}

$objectA = new ClassA();
$stringA = serialize($objectA);

// 1. convert serialzed class to stdClass
$stringA = preg_replace('/' . strlen('ClassA') . '/', strlen('stdClass'), $stringA, 1);
$stringA = preg_replace('/ClassA/', 'stdClass', $stringA, 1);

// 2. unserialize
$object = unserialize($stringA);

// 3. add public protected properties
while (list($key, $value) = each($object)) // hack with each
{
if (strpos($key, "\x00*\x00") === 0)
{
$key = str_replace("\x00*\x00", '', $key);
$object->$key = $value;
}
}

// 4. serialize
$stringB = serialize($object);

// 5. convert serialized stdClass to original
$stringB = preg_replace('/' . strlen('stdClass') . '/', strlen('ClassA'), $stringB, 1);
$stringB = preg_replace('/stdClass/', 'ClassA', $stringB, 1);

var_dump(unserialize($stringB));

Производит

class ClassA#3 (4) {
public $publicMember =>
NULL
private $privateMember =>
NULL
protected $protected =>
NULL
public $protected =>
NULL
}

Постскриптум это безопаснее, чем первый, но … 🙂

0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector