diff options
author | blizzz <blizzz@arthur-schiwon.de> | 2021-11-26 22:58:36 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-11-26 22:58:36 +0300 |
commit | 842e22f8829227d54175656408c49729d786e7c8 (patch) | |
tree | 4a747a2f5d7011e989e0f420ae0f6eb65ed321a0 | |
parent | df961fa2f3e12e8115ecc755f0af6c384bae421b (diff) | |
parent | 09014ec6d1c0106b95df9fc35a0f4d341fbb3730 (diff) |
Merge pull request #29928 from nextcloud/backport/29926/stable23
[stable23] obey accounts_data column length when inserting and searching
-rw-r--r-- | lib/private/Accounts/AccountManager.php | 9 | ||||
-rw-r--r-- | lib/public/Util.php | 24 | ||||
-rw-r--r-- | tests/lib/UtilTest.php | 7 |
3 files changed, 39 insertions, 1 deletions
diff --git a/lib/private/Accounts/AccountManager.php b/lib/private/Accounts/AccountManager.php index cbd51e71c4a..2c7641243fa 100644 --- a/lib/private/Accounts/AccountManager.php +++ b/lib/private/Accounts/AccountManager.php @@ -343,6 +343,10 @@ class AccountManager implements IAccountManager { } public function searchUsers(string $property, array $values): array { + // the value col is limited to 255 bytes. It is used for searches only. + $values = array_map(function (string $value) { + return Util::shortenMultibyteString($value, 255); + }, $values); $chunks = array_chunk($values, 500); $query = $this->connection->getQueryBuilder(); $query->select('*') @@ -625,8 +629,11 @@ class AccountManager implements IAccountManager { continue; } + // the value col is limited to 255 bytes. It is used for searches only. + $value = $property['value'] ? Util::shortenMultibyteString($property['value'], 255) : ''; + $query->setParameter('name', $property['name']) - ->setParameter('value', $property['value'] ?? ''); + ->setParameter('value', $value); $query->executeStatement(); } } diff --git a/lib/public/Util.php b/lib/public/Util.php index 5165846707a..103b65fe874 100644 --- a/lib/public/Util.php +++ b/lib/public/Util.php @@ -513,4 +513,28 @@ class Util { } return self::$needUpgradeCache; } + + /** + * Sometimes a string has to be shortened to fit within a certain maximum + * data length in bytes. substr() you may break multibyte characters, + * because it operates on single byte level. mb_substr() operates on + * characters, so does not ensure that the shortend string satisfies the + * max length in bytes. + * + * For example, json_encode is messing with multibyte characters a lot, + * replacing them with something along "\u1234". + * + * This function shortens the string with by $accurancy (-5) from + * $dataLength characters, until it fits within $dataLength bytes. + * + * @since 23.0.0 + */ + public static function shortenMultibyteString(string $subject, int $dataLength, int $accuracy = 5): string { + $temp = mb_substr($subject, 0, $dataLength); + // json encodes encapsulates the string in double quotes, they need to be substracted + while ((strlen(json_encode($temp)) - 2) > $dataLength) { + $temp = mb_substr($temp, 0, -$accuracy); + } + return $temp; + } } diff --git a/tests/lib/UtilTest.php b/tests/lib/UtilTest.php index bb328c5998d..ca7a4ad1442 100644 --- a/tests/lib/UtilTest.php +++ b/tests/lib/UtilTest.php @@ -310,4 +310,11 @@ class UtilTest extends \Test\TestCase { 'myApp/vendor/myFancyCSSFile2', ], \OC_Util::$styles); } + + public function testShortenMultibyteString() { + $this->assertEquals('Short nuff', \OCP\Util::shortenMultibyteString('Short nuff', 255)); + $this->assertEquals('ABC', \OCP\Util::shortenMultibyteString('ABCDEF', 3)); + // each of the characters is 12 bytes + $this->assertEquals('🙈', \OCP\Util::shortenMultibyteString('🙈🙊🙉', 16, 2)); + } } |