Skip to content

Commit

Permalink
fix: null byte serialization issues (#64)
Browse files Browse the repository at this point in the history
  • Loading branch information
atymic authored Sep 10, 2020
1 parent 0ceec8d commit 57aee94
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 25 deletions.
10 changes: 5 additions & 5 deletions src/Models/ScheduledNotification.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public function __construct(array $attributes = [])
parent::__construct($attributes);

$this->table = config('snooze.snooze_table');
$this->serializer = Serializer::create();
$this->serializer = app(Serializer::class);
}

public function send(): void
Expand All @@ -62,8 +62,8 @@ public function send(): void
throw new NotificationAlreadySentException('Cannot Send. Notification already sent.', 1);
}

$notifiable = $this->serializer->unserializeNotifiable($this->target);
$notification = $this->serializer->unserializeNotification($this->notification);
$notifiable = $this->serializer->unserialize($this->target);
$notification = $this->serializer->unserialize($this->notification);

if ($this->shouldInterrupt($notification, $notifiable)) {
$this->cancel();
Expand All @@ -90,11 +90,11 @@ public function send(): void
public function shouldInterrupt(?object $notification = null, ?object $notifiable = null): bool
{
if (! $notification) {
$notification = $this->serializer->unserializeNotification($this->notification);
$notification = $this->serializer->unserialize($this->notification);
}

if (! $notifiable) {
$notifiable = $this->serializer->unserializeNotifiable($this->target);
$notifiable = $this->serializer->unserialize($this->target);
}

if (method_exists($notification, 'shouldInterrupt')) {
Expand Down
12 changes: 7 additions & 5 deletions src/ScheduledNotification.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public static function create(
throw new SchedulingFailedException(sprintf('%s is not notifiable', get_class($notifiable)));
}

$serializer = app(Serializer::class);
$modelClass = self::getScheduledNotificationModelClass();

$targetId = $notifiable instanceof Model ? $notifiable->getKey() : null;
Expand All @@ -56,8 +57,8 @@ public static function create(
'target_id' => $targetId,
'target_type' => $targetType,
'notification_type' => get_class($notification),
'target' => Serializer::create()->serializeNotifiable($notifiable),
'notification' => Serializer::create()->serializeNotification($notification),
'target' => $serializer->serialize($notifiable),
'notification' => $serializer->serialize($notification),
'send_at' => $sendAt,
]));
}
Expand Down Expand Up @@ -132,17 +133,18 @@ public static function cancelByTarget(object $notifiable): int

public static function cancelAnonymousNotificationsByChannel(string $channel, string $route): int
{
$serializer = app(Serializer::class);
$modelClass = self::getScheduledNotificationModelClass();

$notificationsToCancel = $modelClass::whereNull('sent_at')
->whereNull('cancelled_at')
->whereTargetId(null)
->whereTargetType(AnonymousNotifiable::class)
->get()
->map(function (ScheduledNotificationModel $model) {
->map(function (ScheduledNotificationModel $model) use ($serializer) {
return [
'id' => $model->id,
'routes' => Serializer::create()->unserializeNotifiable($model->target)->routes,
'routes' => $serializer->unserialize($model->target)->routes,
];
})
->filter(function (array $item) use ($channel, $route) {
Expand Down Expand Up @@ -214,7 +216,7 @@ public function isRescheduled(): bool
*/
public function getNotification()
{
return Serializer::create()->unserializeNotification($this->scheduleNotificationModel->notification);
return app(Serializer::class)->unserialize($this->scheduleNotificationModel->notification);
}

public function getId()
Expand Down
41 changes: 26 additions & 15 deletions src/Serializer.php
Original file line number Diff line number Diff line change
@@ -1,36 +1,47 @@
<?php

declare(strict_types=1);

namespace Thomasjohnkane\Snooze;

use Illuminate\Notifications\Notification;
use Illuminate\Database\ConnectionInterface;
use Illuminate\Database\PostgresConnection;
use Illuminate\Queue\SerializesAndRestoresModelIdentifiers;
use Illuminate\Support\Str;

class Serializer
{
use SerializesAndRestoresModelIdentifiers;

public static function create(): self
{
return new self();
}
/** @var ConnectionInterface */
protected $connection;

public function serializeNotifiable(object $notifiable): string
public function __construct(ConnectionInterface $connection)
{
return serialize(self::getSerializedPropertyValue(clone $notifiable));
$this->connection = $connection;
}

public function serializeNotification(Notification $notification): string
public function serialize(object $notifiable): string
{
return serialize(clone $notification);
}
$result = serialize($this->getSerializedPropertyValue(clone $notifiable));

public function unserializeNotifiable(string $serialized)
{
return $this->getRestoredPropertyValue(unserialize($serialized));
if ($this->connection instanceof PostgresConnection && Str::contains($result, "\0")) {
$result = base64_encode($result);
}

return $result;
}

public function unserializeNotification(string $serialized)
public function unserialize(string $serialized)
{
return unserialize($serialized);
if ($this->connection instanceof PostgresConnection && ! Str::contains($serialized, [':', ';'])) {
$serialized = base64_decode($serialized);
}

$object = unserialize($serialized);

return $this->getRestoredPropertyValue(
$object
);
}
}

0 comments on commit 57aee94

Please sign in to comment.