Skip to content

Commit 414dbde

Browse files
authored
Merge pull request #773 from utopia-php/handle-non-utf-chars
Handle non utf chars
2 parents fbe23a3 + 4d171d3 commit 414dbde

File tree

10 files changed

+94
-2
lines changed

10 files changed

+94
-2
lines changed

src/Database/Adapter.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1464,4 +1464,11 @@ public function enableAlterLocks(bool $enable): self
14641464

14651465
return $this;
14661466
}
1467+
1468+
/**
1469+
* Handle non utf characters supported?
1470+
*
1471+
* @return bool
1472+
*/
1473+
abstract public function getSupportNonUtfCharacters(): bool;
14671474
}

src/Database/Adapter/MariaDB.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Utopia\Database\Database;
88
use Utopia\Database\Document;
99
use Utopia\Database\Exception as DatabaseException;
10+
use Utopia\Database\Exception\Character as CharacterException;
1011
use Utopia\Database\Exception\Duplicate as DuplicateException;
1112
use Utopia\Database\Exception\Limit as LimitException;
1213
use Utopia\Database\Exception\NotFound as NotFoundException;
@@ -1838,6 +1839,10 @@ public function getInternalIndexesKeys(): array
18381839

18391840
protected function processException(PDOException $e): \Exception
18401841
{
1842+
if ($e->getCode() === '22007' && isset($e->errorInfo[1]) && $e->errorInfo[1] === 1366) {
1843+
return new CharacterException('Invalid character', $e->getCode(), $e);
1844+
}
1845+
18411846
// Timeout
18421847
if ($e->getCode() === '70100' && isset($e->errorInfo[1]) && $e->errorInfo[1] === 1969) {
18431848
return new TimeoutException('Query timed out', $e->getCode(), $e);
@@ -2230,4 +2235,9 @@ public function getSupportForAlterLocks(): bool
22302235
{
22312236
return true;
22322237
}
2238+
2239+
public function getSupportNonUtfCharacters(): bool
2240+
{
2241+
return true;
2242+
}
22332243
}

src/Database/Adapter/Mongo.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3221,4 +3221,9 @@ public function getSupportForAlterLocks(): bool
32213221
{
32223222
return false;
32233223
}
3224+
3225+
public function getSupportNonUtfCharacters(): bool
3226+
{
3227+
return false;
3228+
}
32243229
}

src/Database/Adapter/MySQL.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use PDOException;
66
use Utopia\Database\Database;
77
use Utopia\Database\Exception as DatabaseException;
8+
use Utopia\Database\Exception\Character as CharacterException;
89
use Utopia\Database\Exception\Dependency as DependencyException;
910
use Utopia\Database\Exception\Structure as StructureException;
1011
use Utopia\Database\Exception\Timeout as TimeoutException;
@@ -147,6 +148,10 @@ public function getSupportForCastIndexArray(): bool
147148

148149
protected function processException(PDOException $e): \Exception
149150
{
151+
if ($e->getCode() === 'HY000' && isset($e->errorInfo[1]) && $e->errorInfo[1] === 1366) {
152+
return new CharacterException('Invalid character', $e->getCode(), $e);
153+
}
154+
150155
// Timeout
151156
if ($e->getCode() === 'HY000' && isset($e->errorInfo[1]) && $e->errorInfo[1] === 3024) {
152157
return new TimeoutException('Query timed out', $e->getCode(), $e);

src/Database/Adapter/Pool.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -642,4 +642,9 @@ public function getSupportForAlterLocks(): bool
642642
{
643643
return $this->delegate(__FUNCTION__, \func_get_args());
644644
}
645+
646+
public function getSupportNonUtfCharacters(): bool
647+
{
648+
return $this->delegate(__FUNCTION__, \func_get_args());
649+
}
645650
}

src/Database/Adapter/Postgres.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2738,4 +2738,9 @@ protected function bindOperatorParams(\PDOStatement|PDOStatementProxy $stmt, Ope
27382738
break;
27392739
}
27402740
}
2741+
2742+
public function getSupportNonUtfCharacters(): bool
2743+
{
2744+
return false;
2745+
}
27412746
}

src/Database/Adapter/SQLite.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1876,4 +1876,9 @@ public function getSupportForAlterLocks(): bool
18761876
{
18771877
return false;
18781878
}
1879+
1880+
public function getSupportNonUtfCharacters(): bool
1881+
{
1882+
return false;
1883+
}
18791884
}

src/Database/Database.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9358,5 +9358,4 @@ private function rollbackAttributeMetadata(Document $collection, array $attribut
93589358
);
93599359
$collection->setAttribute('attributes', \array_values($filteredAttributes));
93609360
}
9361-
93629361
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
namespace Utopia\Database\Exception;
4+
5+
use Utopia\Database\Exception;
6+
7+
class Character extends Exception
8+
{
9+
}

tests/e2e/Adapter/Scopes/DocumentTests.php

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66
use Throwable;
77
use Utopia\Database\Adapter\SQL;
88
use Utopia\Database\Database;
9-
use Utopia\Database\DateTime;
109
use Utopia\Database\Document;
1110
use Utopia\Database\Exception as DatabaseException;
1211
use Utopia\Database\Exception\Authorization as AuthorizationException;
12+
use Utopia\Database\Exception\Character as CharacterException;
1313
use Utopia\Database\Exception\Conflict as ConflictException;
1414
use Utopia\Database\Exception\Duplicate as DuplicateException;
1515
use Utopia\Database\Exception\Limit as LimitException;
@@ -22,6 +22,48 @@
2222

2323
trait DocumentTests
2424
{
25+
public function testNonUtfChars(): void
26+
{
27+
/** @var Database $database */
28+
$database = $this->getDatabase();
29+
30+
if (!$database->getAdapter()->getSupportNonUtfCharacters()) {
31+
$this->expectNotToPerformAssertions();
32+
return;
33+
}
34+
35+
$database->createCollection(__FUNCTION__);
36+
$this->assertEquals(true, $database->createAttribute(__FUNCTION__, 'title', Database::VAR_STRING, 128, true));
37+
38+
$nonUtfString = "Hello\x00World\xC3\x28\xFF\xFE\xA0Test\x00End";
39+
40+
try {
41+
$database->createDocument(__FUNCTION__, new Document([
42+
'title' => $nonUtfString,
43+
]));
44+
$this->fail('Failed to throw exception');
45+
} catch (Throwable $e) {
46+
$this->assertTrue($e instanceof CharacterException);
47+
}
48+
49+
/**
50+
* Convert to UTF-8 and replace invalid bytes with empty string
51+
*/
52+
$nonUtfString = mb_convert_encoding($nonUtfString, 'UTF-8', 'UTF-8');
53+
54+
/**
55+
* Remove null bytes
56+
*/
57+
$nonUtfString = str_replace("\0", '', $nonUtfString);
58+
59+
$document = $database->createDocument(__FUNCTION__, new Document([
60+
'title' => $nonUtfString,
61+
]));
62+
63+
$this->assertFalse($document->isEmpty());
64+
$this->assertEquals('HelloWorld?(???TestEnd', $document->getAttribute('title'));
65+
}
66+
2567
public function testBigintSequence(): void
2668
{
2769
/** @var Database $database */

0 commit comments

Comments
 (0)