]> git.mxchange.org Git - friendica.git/commitdiff
Fix multiple serialized values
authorPhilipp <admin@philipp.info>
Sun, 19 Feb 2023 11:57:39 +0000 (12:57 +0100)
committerPhilipp <admin@philipp.info>
Mon, 20 Feb 2023 16:22:59 +0000 (17:22 +0100)
src/Core/Config/Model/DatabaseConfig.php
src/Core/Config/Util/SerializeUtil.php
tests/src/Core/Config/ConfigTest.php
update.php

index 01366cf71a82a03528f2bc52f2d9efd0b8bdcf4f..7167ccbf8e686bee2bddcef327b83ad8543462ea 100644 (file)
@@ -61,15 +61,13 @@ class DatabaseConfig implements IManageConfigValues
 
                foreach ($setCache->getAll() as $category => $data) {
                        foreach ($data as $key => $value) {
-                               $this->cache->set($category, $key, $value, Cache::SOURCE_DATA);
-                               $this->database->insert('config', ['cat' => $category, 'k' => $key, 'v' => serialize($value)], Database::INSERT_UPDATE);
+                               $this->set($category, $key, $value);
                        }
                }
 
                foreach ($delCache->getAll() as $category => $keys) {
                        foreach ($keys as $key => $value) {
-                               $this->cache->delete($category, $key);
-                               $this->database->delete('config', ['cat' => $category, 'k' => $key]);
+                               $this->delete($category, $key);
                        }
                }
 
@@ -85,6 +83,10 @@ class DatabaseConfig implements IManageConfigValues
        /** {@inheritDoc} */
        public function set(string $cat, string $key, $value): bool
        {
+               // In case someone or something already serialized a config entry, unserialize it first
+               // We serialize values just once
+               $value = SerializeUtil::maybeUnserialize($value);
+
                $this->cache->set($cat, $key, $value, Cache::SOURCE_DATA);
                return $this->database->insert('config', ['cat' => $cat, 'k' => $key, 'v' => serialize($value)], Database::INSERT_UPDATE);
        }
index 0a886e2305fa44a50c706fa8e1b87244d982e7d7..1d944f264ba5f800494a4fa3e5f8535fceef4572 100644 (file)
@@ -28,10 +28,24 @@ namespace Friendica\Core\Config\Util;
  */
 class SerializeUtil
 {
+       /**
+        * Checks if the value needs to get unserialized and returns the unserialized value
+        *
+        * @param mixed $value A possible serialized value
+        *
+        * @return mixed The unserialized value
+        */
        public static function maybeUnserialize($value)
        {
-               if (static::isSerialized($value)) {
-                       return @unserialize(trim($value));
+               // This checks for possible multiple serialized values
+               while (SerializeUtil::isSerialized($value)) {
+                       $oldValue = $value;
+                       $value = @unserialize($value);
+
+                       // If there's no change after the unserialize call, break the loop (avoid endless loops)
+                       if ($oldValue === $value) {
+                               break;
+                       }
                }
 
                return $value;
index 643c73754892bdc151f1559bf30eb35ac21d7fa3..cf13ea05ae19494db81bcf02400648c4edf655e1 100644 (file)
@@ -537,4 +537,33 @@ class ConfigTest extends DatabaseTest
 
                self::assertEquals($assertion, $config->get($category));
        }
+
+       public function dataSerialized(): array
+       {
+               return [
+                       'default' => [
+                               'value' => ['test' => ['array']],
+                               'assertion' => ['test' => ['array']],
+                       ],
+                       'issue-12803' => [
+                               'value' => 's:48:"s:40:"s:32:"https://punkrock-underground.com";";";',
+                               'assertion' => 'https://punkrock-underground.com',
+                       ],
+                       'double-serialized-array' => [
+                               'value' => 's:53:"a:1:{s:9:"testArray";a:1:{s:4:"with";s:7:"entries";}}";',
+                               'assertion' => ['testArray' => ['with' => 'entries']],
+                       ],
+               ];
+       }
+
+       /**
+        * @dataProvider dataSerialized
+        */
+       public function testSerializedValues($value, $assertion)
+       {
+               $config = $this->getInstance();
+
+               $config->set('test', 'it', $value);
+               self:self::assertEquals($assertion, $config->get('test', 'it'));
+       }
 }
index 15ef8b1dc0194e401ecf8f56f0d7164aa92304d7..672c11a4f49097342f8a3d78fd16074ab6ce7ad7 100644 (file)
@@ -1295,3 +1295,23 @@ function update_1515()
        DBA::update('verb', ['name' => Activity::VIEW], ['name' => 'https://joinpeertube.org/view']);
        return Update::SUCCESS;
 }
+
+function update_1516()
+{
+       // Fixes https://github.com/friendica/friendica/issues/12803
+       // de-serialize multiple serialized values
+       $configTrans = DI::config()->beginTransaction();
+       $configArray = DI::config()->getCache()->getDataBySource(Cache::SOURCE_DATA);
+
+       foreach ($configArray as $category => $keyValues) {
+               if (is_array($keyValues)) {
+                       foreach ($keyValues as $key => $value) {
+                               $configTrans->set($category, $key, $value);
+                       }
+               }
+       }
+
+       $configTrans->commit();
+
+       return Update::SUCCESS;
+}