Unserialize PHP string with obsolete MongoId and MongoDate Objects

456 Views Asked by At

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?

2

There are 2 best solutions below

1
On BEST ANSWER

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.

4
On

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