From 25054c4e0fd6686172e3ed9c6fb1a85f1bc09078 Mon Sep 17 00:00:00 2001
From: Dmitriy Simushev <simushevds@ossg.ru>
Date: Fri, 5 Jun 2015 11:33:19 +0000
Subject: [PATCH] Add "_instance_id" setting

---
 .../classes/Mibew/Maintenance/Installer.php   | 40 +++++++++++++++++++
 .../classes/Mibew/Maintenance/Updater.php     |  9 +++++
 .../libs/classes/Mibew/Maintenance/Utils.php  | 34 ++++++++++++++++
 src/mibew/libs/classes/Mibew/Settings.php     |  4 ++
 4 files changed, 87 insertions(+)

diff --git a/src/mibew/libs/classes/Mibew/Maintenance/Installer.php b/src/mibew/libs/classes/Mibew/Maintenance/Installer.php
index cb0d8625..12b9551d 100644
--- a/src/mibew/libs/classes/Mibew/Maintenance/Installer.php
+++ b/src/mibew/libs/classes/Mibew/Maintenance/Installer.php
@@ -440,6 +440,46 @@ class Installer
             return false;
         }
 
+        // Generate Unique ID for Mibew Instance
+        try {
+            list($count) = $db->query(
+                'SELECT COUNT(*) FROM {config} WHERE vckey = :key',
+                array(':key' => '_instance_id'),
+                array(
+                    'return_rows' => Database::RETURN_ONE_ROW,
+                    'fetch_type' => Database::FETCH_NUM,
+                )
+            );
+
+            if ($count == 0) {
+                $db->query(
+                    'INSERT INTO {config} (vckey, vcvalue) VALUES (:key, :value)',
+                    array(
+                        ':key' => '_instance_id',
+                        ':value' => Utils::generateInstanceId(),
+                    )
+                );
+            } else {
+                // The option is already in the database. It seems that
+                // something went wrong with the previous installation attempt.
+                // Just update the instance ID.
+                $db->query(
+                    'UPDATE {config} SET vcvalue = :value WHERE vckey = :key',
+                    array(
+                        ':key' => '_instance_id',
+                        ':value' => Utils::generateInstanceId(),
+                    )
+                );
+            }
+        } catch (\Exception $e) {
+            $this->errors[] = getlocal(
+                'Cannot store instance ID. Error {0}',
+                array($e->getMessage())
+            );
+
+            return false;
+        }
+
         return true;
     }
 
diff --git a/src/mibew/libs/classes/Mibew/Maintenance/Updater.php b/src/mibew/libs/classes/Mibew/Maintenance/Updater.php
index 6936f3e5..a66c6f2c 100644
--- a/src/mibew/libs/classes/Mibew/Maintenance/Updater.php
+++ b/src/mibew/libs/classes/Mibew/Maintenance/Updater.php
@@ -350,6 +350,15 @@ class Updater
                 . 'description text, '
                 . 'UNIQUE KEY target (target) '
                 . ') charset utf8 ENGINE=InnoDb');
+
+            // Generate Unique ID of Mibew instance.
+            $db->query(
+                'INSERT INTO {config} (vckey, vcvalue) VALUES (:key, :value)',
+                array(
+                    ':key' => '_instance_id',
+                    ':value' => Utils::generateInstanceId(),
+                )
+            );
         } catch (\Exception $e) {
             $this->errors[] = getlocal('Cannot update tables: {0}', $e->getMessage());
 
diff --git a/src/mibew/libs/classes/Mibew/Maintenance/Utils.php b/src/mibew/libs/classes/Mibew/Maintenance/Utils.php
index 603be88e..ce122abb 100644
--- a/src/mibew/libs/classes/Mibew/Maintenance/Utils.php
+++ b/src/mibew/libs/classes/Mibew/Maintenance/Utils.php
@@ -101,6 +101,40 @@ class Utils
         return $updates;
     }
 
+    /**
+     * Generates random unique 64 characters length ID for Mibew instance.
+     *
+     * WARNING: This ID should not be used for any security/cryptographic. If
+     * you need an ID for such purpose you have to use PHP's
+     * {@link openssl_random_pseudo_bytes()} function instead.
+     *
+     * @return string
+     */
+    public static function generateInstanceId()
+    {
+        $chars = '0123456789abcdefghijklmnopqrstuvwxyz';
+        $rnd = (string)microtime(true);
+
+        // Add ten random characters before and after the timestamp
+        $max_char = strlen($chars) - 1;
+        for ($i = 0; $i < 10; $i++) {
+            $rnd = $chars[rand(0, $max_char)] . $rnd . $chars[rand(0, $max_char)];
+        }
+
+        if (function_exists('hash')) {
+            // There is hash function that can give us 64-length hash.
+            return hash('sha256', $rnd);
+        }
+
+        // We should build random 64 character length hash using old'n'good md5
+        // function.
+        $middle = (int)floor(strlen($rnd) / 2);
+        $rnd_left = substr($rnd, 0, $middle);
+        $rnd_right = substr($rnd, $middle);
+
+        return md5($rnd_left) . md5($rnd_right);
+    }
+
     /**
      * This class should not be instantiated
      */
diff --git a/src/mibew/libs/classes/Mibew/Settings.php b/src/mibew/libs/classes/Mibew/Settings.php
index dca40a87..2a547748 100644
--- a/src/mibew/libs/classes/Mibew/Settings.php
+++ b/src/mibew/libs/classes/Mibew/Settings.php
@@ -115,6 +115,10 @@ class Settings
             // underscore sign(_).
             // Unix timestamp when cron job ran last time.
             '_last_cron_run' => 0,
+            // Random unique ID which is used for getting info about new
+            // updates. This value is initialized during Installation or Update
+            // process.
+            '_instance_id' => '',
         );
 
         // Load values from database