Skip to content

Commit

Permalink
Merge pull request nextcloud#29926 from nextcloud/fix/noid/short-acco…
Browse files Browse the repository at this point in the history
…unts-data-value
  • Loading branch information
skjnldsv authored Nov 26, 2021
2 parents aee3bb4 + 998144f commit 7d67de2
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 1 deletion.
9 changes: 8 additions & 1 deletion lib/private/Accounts/AccountManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,10 @@ protected function getUser(IUser $user, bool $insertIfNotExists = true): array {
}

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('*')
Expand Down Expand Up @@ -625,8 +629,11 @@ protected function writeUserDataProperties(IQueryBuilder $query, array $data): v
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();
}
}
Expand Down
24 changes: 24 additions & 0 deletions lib/public/Util.php
Original file line number Diff line number Diff line change
Expand Up @@ -513,4 +513,28 @@ public static function needUpgrade() {
}
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;
}
}
7 changes: 7 additions & 0 deletions tests/lib/UtilTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -310,4 +310,11 @@ public function testAddVendorStyle() {
'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));
}
}

0 comments on commit 7d67de2

Please sign in to comment.