Remove EncodeUTF8 infavour of using attribute casting only. The implementation of EncodeUTF8 was not correct, essentially removing any previous casting causing issues when saving a record.

This commit is contained in:
Deon George 2024-06-01 10:46:02 +10:00
parent b5047c52f0
commit 73cf421739
10 changed files with 66 additions and 164 deletions

View File

@ -5,20 +5,19 @@ namespace App\Casts;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
use Illuminate\Database\Eloquent\Model;
class CompressedString implements CastsAttributes
class CompressedStringOrNull implements CastsAttributes
{
/**
* Cast the given value.
*
* For postgresl bytea columns the value is a resource stream
*
* @param Model $model
* @param string $key
* @param mixed $value
* @param array $attributes
* @return string
* @return string|null
* @note postgres bytea columns the value is a resource stream
*/
public function get($model,string $key,mixed $value,array $attributes): string
public function get(Model $model,string $key,mixed $value,array $attributes): ?string
{
// For stream resources, we to fseek in case we've already read it.
if (is_resource($value))
@ -28,13 +27,7 @@ class CompressedString implements CastsAttributes
? stream_get_contents($value)
: $value;
// If we get an error decompressing, it might not be zstd (or its already been done)
try {
return $value ? zstd_uncompress(base64_decode($value)) : '';
} catch (\ErrorException $e) {
return $value;
}
return $value ? zstd_uncompress(base64_decode($value)) : NULL;
}
/**
@ -44,10 +37,10 @@ class CompressedString implements CastsAttributes
* @param string $key
* @param mixed $value
* @param array $attributes
* @return string
* @return string|null
*/
public function set($model,string $key,$value,array $attributes): string
public function set(Model $model,string $key,$value,array $attributes): ?string
{
return $value ? base64_encode(zstd_compress($value)) : '';
return $value ? base64_encode(zstd_compress($value)) : NULL;
}
}

View File

@ -0,0 +1,29 @@
<?php
namespace App\Casts;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
use Illuminate\Database\Eloquent\Model;
class UTF8StringOrNull implements CastsAttributes
{
/**
* Cast the given value.
*
* @param array<string, mixed> $attributes
*/
public function get(Model $model,string $key,mixed $value,array $attributes): ?string
{
return $value ? utf8_decode($value) : NULL;
}
/**
* Prepare the given value for storage.
*
* @param array<string, mixed> $attributes
*/
public function set(Model $model,string $key,mixed $value,array $attributes): ?string
{
return $value ? utf8_encode($value) : NULL;
}
}

View File

@ -14,21 +14,17 @@ use Illuminate\Support\Facades\Notification;
use App\Classes\FTN\Message;
use App\Models\{Echomail,Netmail,User};
use App\Notifications\Netmails\{EchoareaNotExist,EchoareaNotSubscribed,EchoareaNoWrite,NetmailForward,NetmailHubNoUser};
use App\Traits\{EncodeUTF8,ParseAddresses};
use App\Traits\ParseAddresses;
class MessageProcess implements ShouldQueue
{
private const LOGKEY = 'JMP';
use Dispatchable,InteractsWithQueue,Queueable,SerializesModels,ParseAddresses,EncodeUTF8;
use Dispatchable,InteractsWithQueue,Queueable,SerializesModels,ParseAddresses;
private Echomail|Netmail|string $mo;
private bool $skipbot;
private const cast_utf8 = [
'mo',
];
/**
* Process a message from a packet
*
@ -54,16 +50,6 @@ class MessageProcess implements ShouldQueue
}
}
public function __serialize()
{
return $this->encode();
}
public function __unserialize(array $values)
{
$this->decode($values);
}
/**
* At this point, we know that the packet is from a system we know about, and the packet is to us:
* + From a system that is configured with us, and the password has been validated
@ -144,8 +130,8 @@ class MessageProcess implements ShouldQueue
// Check if the netmail is to a user, with netmail forwarding enabled
$uo = User::active()
->where(function($query) {
return $query->whereRaw(sprintf("LOWER(name)='%s'",strtolower($this->mo->to)))
->orWhereRaw(sprintf("LOWER(alias)='%s'",strtolower($this->mo->to)));
return $query->whereRaw(sprintf("LOWER(name)='%s'",strtolower(utf8_encode($this->mo->to))))
->orWhereRaw(sprintf("LOWER(alias)='%s'",strtolower(utf8_encode($this->mo->to))));
})
->whereNotNull('system_id')
->single();

View File

@ -139,7 +139,7 @@ class PacketProcess implements ShouldQueue
$count++;
} catch (\Exception $e) {
Log::error(sprintf('%s:! Got error dispatching message [%s] (%d:%s-%s).',self::LOGKEY,$msg->msgid,$e->getLine(),$e->getFile(),$e->getMessage()));
Log::error(sprintf('%s:! Got error [%s] dispatching message [%s] (%d:%s-%s).',self::LOGKEY,get_class($e),$msg->msgid,$e->getLine(),$e->getFile(),$e->getMessage()));
}
}

View File

@ -11,7 +11,7 @@ use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use App\Casts\CompressedString;
use App\Casts\CompressedStringOrNull;
use App\Traits\{QueryCacheableConfig,ScopeActive};
class Domain extends Model
@ -22,7 +22,7 @@ class Domain extends Model
private const STATS_MONTHS = 6;
protected $casts = [
'homepage' => CompressedString::class,
'homepage' => CompressedStringOrNull::class,
];
/* SCOPES */

View File

@ -9,7 +9,7 @@ use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use App\Casts\{CollectionOrNull,CompressedString};
use App\Casts\{CollectionOrNull,CompressedStringOrNull,UTF8StringOrNull};
use App\Classes\FTN\Message;
use App\Interfaces\Packet;
use App\Traits\{MessageAttributes,MsgID,ParseAddresses,QueryCacheableConfig};
@ -32,10 +32,16 @@ final class Echomail extends Model implements Packet
public Address $tftn;
protected $casts = [
'to' => UTF8StringOrNull::class,
'from' => UTF8StringOrNull::class,
'subject' => UTF8StringOrNull::class,
'origin' => UTF8StringOrNull::class,
'tearline' => UTF8StringOrNull::class,
'tagline' => UTF8StringOrNull::class,
'datetime' => 'datetime:Y-m-d H:i:s',
'kludges' => CollectionOrNull::class,
'msg' => CompressedString::class,
'msg_src' => CompressedString::class,
'msg' => CompressedStringOrNull::class,
'msg_src' => CompressedStringOrNull::class,
'rogue_seenby' => CollectionOrNull::class,
'rogue_path' => CollectionOrNull::class, // @deprecated?
];

View File

@ -11,12 +11,11 @@ use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use App\Casts\{CollectionOrNull,CompressedString};
use App\Traits\EncodeUTF8;
use App\Casts\{CollectionOrNull,CompressedStringOrNull};
class File extends Model
{
use SoftDeletes,EncodeUTF8;
use SoftDeletes;
private const LOGKEY = 'MF-';
private bool $no_export = FALSE;
@ -28,18 +27,13 @@ class File extends Model
protected $casts = [
'kludges' => CollectionOrNull::class,
'datetime' => 'datetime:Y-m-d H:i:s',
'desc' => CompressedString::class,
'ldesc' => CompressedString::class,
'desc' => CompressedStringOrNull::class,
'ldesc' => CompressedStringOrNull::class,
'rogue_seenby' => CollectionOrNull::class,
'rogue_path' => CollectionOrNull::class,
'size' => 'int',
];
private const cast_utf8 = [
'desc',
'ldesc',
];
public static function boot()
{
parent::boot();

View File

@ -10,7 +10,7 @@ use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use App\Casts\{CollectionOrNull,CompressedString};
use App\Casts\{CollectionOrNull,CompressedStringOrNull,UTF8StringOrNull};
use App\Interfaces\Packet;
use App\Pivots\ViaPivot;
use App\Traits\{MessageAttributes,MsgID};
@ -32,10 +32,16 @@ final class Netmail extends Model implements Packet
];
protected $casts = [
'to' => UTF8StringOrNull::class,
'from' => UTF8StringOrNull::class,
'subject' => UTF8StringOrNull::class,
'origin' => UTF8StringOrNull::class,
'tearline' => UTF8StringOrNull::class,
'tagline' => UTF8StringOrNull::class,
'datetime' => 'datetime:Y-m-d H:i:s',
'kludges' => CollectionOrNull::class,
'msg' => CompressedString::class,
'msg_src' => CompressedString::class,
'msg' => CompressedStringOrNull::class,
'msg_src' => CompressedStringOrNull::class,
'sent_at' => 'datetime:Y-m-d H:i:s',
];

View File

@ -1,99 +0,0 @@
<?php
/**
* Encode our data so that it can be serialised
*/
namespace App\Traits;
use Illuminate\Support\Arr;
trait EncodeUTF8
{
private array $_encoded = []; // Remember what we've decoded - when calling getAttribute()
private function decode(array $values): void
{
$properties = (new \ReflectionClass($this))->getProperties();
$class = get_class($this);
foreach ($properties as $property) {
if ($property->isStatic())
continue;
$name = $property->getName();
$decode = in_array($name,self::cast_utf8);
if ($property->isPrivate())
$name = "\0{$class}\0{$name}";
elseif ($property->isProtected())
$name = "\0*\0{$name}";
if (! array_key_exists($name,$values))
continue;
$property->setAccessible(true);
try {
$property->setValue(
$this,$decode ? utf8_decode($values[$name]) : $values[$name]
);
} catch (\Exception $e) {
dd(['e'=>$e->getMessage(),'name'=>$name,'values'=>$values[$name],'decode'=>$decode]);
}
}
}
private function encode(): array
{
$values = [];
$properties = (new \ReflectionClass($this))->getProperties();
$class = get_class($this);
foreach ($properties as $property) {
// Dont serialize the validation error
if (($property->name === 'errors') || $property->isStatic())
continue;
$property->setAccessible(true);
if (! $property->isInitialized($this))
continue;
$name = $property->getName();
$encode = in_array($name,self::cast_utf8);
if ($property->isPrivate())
$name = "\0{$class}\0{$name}";
elseif ($property->isProtected())
$name = "\0*\0{$name}";
$property->setAccessible(true);
$value = $property->getValue($this);
$values[$name] = $encode ? utf8_encode($value) : $value;
}
return $values;
}
public function getAttribute($key)
{
if (in_array($key,self::cast_utf8) && Arr::get($this->attributes,$key) && (! Arr::get($this->_encoded,$key))) {
// We need to get it from the parent first, taking into account any casting
$this->attributes[$key] = utf8_decode(parent::getAttribute($key));
$this->_encoded[$key] = TRUE;
return $this->attributes[$key];
}
return Arr::get($this->_encoded,$key) ? $this->attributes[$key] : parent::getAttribute($key);
}
public function setAttribute($key,$value)
{
return parent::setAttribute($key,in_array($key,self::cast_utf8) ? utf8_encode($value) : $value);
}
}

View File

@ -15,24 +15,11 @@ use App\Models\{Address,Echomail};
trait MessageAttributes
{
use EncodeUTF8;
// Items we need to set when creating()
public Collection $set;
// Validation Errors
public ?MessageBag $errors = NULL;
private const cast_utf8 = [
'to',
'from',
'subject',
'msg',
'msg_src',
'origin',
'tearline',
'tagline',
];
public function __construct()
{
parent::__construct();