1

I have this string in database. I need to unserialize it with php. The problem is that it returns some "__PHP_Incomplete_Class_Name" Objects.

I know that this string was serialized with old MongoDB PHP extension and I try to unserialized with newer MongoDB extension.

So MongoId and MongoDate are obsolete.

This is the string:

$string = 'a:2:{i:0;a:3:{s:4:"name";s:52:"----------------------------------------------------";s:6:"amount";s:5:"53.09";s:10:"service_id";s:24:"------------------------";}i:1;a:6:{s:2:"id";C:7:"MongoId":24:{5b2276372a4ef288038b45ba}s:4:"name";s:21:"---------------------";s:4:"type";s:8:"one time";s:10:"service_id";s:20:"thisrhietingcfffffff";s:6:"amount";s:6:"139.29";s:10:"added_date";O:9:"MongoDate":2:{s:3:"sec";i:1528985143;s:4:"usec";i:917000;}}}';

When I do:

$result =  @unserialize($string);
var_dump($result);

The result is:

array(2) {
  [0]=>
  array(3) {
    ["name"]=>
    string(52) "----------------------------------------------------"
    ["amount"]=>
    string(5) "53.09"
    ["service_id"]=>
    string(24) "------------------------"
  }
  [1]=>
  array(6) {
    ["id"]=>
    object(__PHP_Incomplete_Class)#1 (1) {
      ["__PHP_Incomplete_Class_Name"]=>
      string(7) "MongoId"
    }
    ["name"]=>
    string(21) "---------------------"
    ["type"]=>
    string(8) "one time"
    ["service_id"]=>
    string(20) "thisrhietingcfffffff"
    ["amount"]=>
    string(6) "139.29"
    ["added_date"]=>
    object(__PHP_Incomplete_Class)#2 (3) {
      ["__PHP_Incomplete_Class_Name"]=>
      string(9) "MongoDate"
      ["sec"]=>
      int(1528985143)
      ["usec"]=>
      int(917000)
    }
  }
}

I have tried to class_alias MongoId to ObjectId. No working. I Have tried to create new class MongoId to extend ObjectId. I am not allowed because ObjectId is a final class.

I have tried to replace C:7:"MongoId" with C:8:"ObjectID".

Still same result: __PHP_Incomplete_Class_Name

Maybe a posibility is to return result like an array not an object?

koAndy
  • 27
  • 6

2 Answers2

1

Your approach points in the right direction for MongoDate, because it uses normal O-type serialization. For MongoId it is more difficult since it has custom C-type serialize handlers.

If this was my task I would roughly start like this:

  • Declare a class MongoId and implement the Serializable interface. For the unserialize function try and mimic the original function (available here on L407->L220).

  • For the serialize function find out what ObjectId serialization looks like and mimic it. (Available here L187)

  • unserialize the string from the database, and serialize it again.

  • Replace C:7:"MongoId" with C:21:"MongoDb\BSON\ObjectID" in the re-serialized string. You need the namespace along with the class name.

  • unserialize again and pray.

The MongoId class should look something like this; but the code is not tested at all:

class MongoId implements Serializable {
  public $id;
  public function serialize() {
    return serialize(['oid' => $this->id]);
  }
  public function unserialize($str) {
    $this->id = $str;
  }
}

I hope this helps a little at least.

jh1711
  • 2,288
  • 1
  • 12
  • 20
0

Depending on your needs it might be easier to just define the classes. Then it will unserialize just fine. This unserializes the value of the object that implemented Serializable denoted by the C in C:7:"MongoId" as id in the unserialized object:

class MongoId implements Serializable { 
    public function unserialize($str) {
        $this->id = $str; 
    }
    public function serialize() {}
}
class MongoDate {}
AbraCadaver
  • 78,200
  • 7
  • 66
  • 87
  • If I define classes as stated, a warning is thrown: Class MongoID has no unserializer. In your output ObjectID should be 5b2276372a4ef288038b45ba. None is shown. – koAndy Jun 14 '18 at 18:00
  • I forgot @ silencer in front of serialize function. – koAndy Jun 14 '18 at 18:01
  • You should be able to add `public function __wakeup() {}` to get rid of the warning. – AbraCadaver Jun 14 '18 at 18:10
  • Adding public function __wakeup() or public function unserialize() {} still yields Class MongoId has no unserializer. It appears that MongoDate does not need unserializer. It works just fine if class MongoDate {} is defined. – koAndy Jun 14 '18 at 18:17