]> git.mxchange.org Git - quix0rs-gnu-social.git/commitdiff
[SESSION] Implement SessionHandlerInterface instead of setting custom handlers by...
authorDiogo Cordeiro <diogo@fc.up.pt>
Tue, 14 May 2019 21:57:45 +0000 (22:57 +0100)
committerDiogo Cordeiro <diogo@fc.up.pt>
Wed, 22 May 2019 21:29:33 +0000 (22:29 +0100)
classes/Session.php
lib/internalsessionhandler.php [new file with mode: 0644]
lib/util.php

index 5744051a9d14d19cd7a4ab9ddd94bb46ef6df0fa..c6df9d12ffbc67341291e9de8fabd384b8661b6f 100644 (file)
@@ -28,7 +28,7 @@ require_once INSTALLDIR . '/classes/Memcached_DataObject.php';
 /**
  * Table definition for Session
  *
- * Superclass representing a saved session as it exists in the database and the associated interfaces.
+ * Superclass representing a saved session as it exists in the database.
  *
  * @author GNU social
  */
@@ -53,10 +53,10 @@ class Session extends Managed_DataObject
     {
         return [
             'fields' => [
-                'id'           => ['type' => 'varchar', 'length' => 32, 'not null' => true, 'description' => 'session ID'],
+                'id' => ['type' => 'varchar', 'length' => 32, 'not null' => true, 'description' => 'session ID'],
                 'session_data' => ['type' => 'text', 'description' => 'session data'],
-                'created'      => ['type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'],
-                'modified'     => ['type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'],
+                'created' => ['type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'],
+                'modified' => ['type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'],
             ],
             'primary key' => ['id'],
             'indexes' => [
@@ -64,228 +64,4 @@ class Session extends Managed_DataObject
             ],
         ];
     }
-
-    /**
-     * A helper function to print a session-related message to the debug log if
-     * the site session debug configuration option is enabled.
-     * @param $msg
-     * @return void
-     */
-    public static function logdeb($msg)
-    {
-        if (common_config('sessions', 'debug')) {
-            common_debug("Session: " . $msg);
-        }
-    }
-
-    /**
-     * Dummy option for saving to file needed for full PHP adherence.
-     *
-     * @param $save_path
-     * @param $session_name
-     * @return bool true
-     */
-    public static function open($save_path, $session_name)
-    {
-        return true;
-    }
-
-    /**
-     * Dummy option for saving to file needed for full PHP adherence.
-     *
-     * @return bool true
-     */
-    public static function close()
-    {
-        return true;
-    }
-
-    /**
-     * Fetch the session data for the session with the given $id.
-     *
-     * @param $id
-     * @return string Returns an encoded string of the read data. If nothing was read, it must return an empty string. Note this value is returned internally to PHP for processing.
-     */
-    public static function read($id)
-    {
-        self::logdeb("Fetching session '$id'");
-
-        $session = Session::getKV('id', $id);
-
-        if (empty($session)) {
-            self::logdeb("Couldn't find '$id'");
-            return '';
-        } else {
-            self::logdeb("Found '$id', returning " .
-                         strlen($session->session_data) .
-                         " chars of data");
-            return (string)$session->session_data;
-        }
-    }
-
-    /**
-     * Write the session data for session with given $id as $session_data.
-     *
-     * @param $id
-     * @param $session_data
-     * @return bool Returns TRUE on success or FALSE on failure.
-     */
-    public static function write($id, $session_data)
-    {
-        self::logdeb("Writing session '$id'");
-
-        $session = Session::getKV('id', $id);
-
-        if (empty($session)) {
-            self::logdeb("'$id' doesn't yet exist; inserting.");
-            $session = new Session();
-
-            $session->id = $id;
-            $session->session_data = $session_data;
-            $session->created = common_sql_now();
-
-            $result = $session->insert();
-
-            if (!$result) {
-                common_log_db_error($session, 'INSERT', __FILE__);
-                self::logdeb("Failed to insert '$id'.");
-            } else {
-                self::logdeb("Successfully inserted '$id' (result = $result).");
-            }
-            return (bool) $result;
-        } else {
-            self::logdeb("'$id' already exists; updating.");
-            if (strcmp($session->session_data, $session_data) == 0) {
-                self::logdeb("Not writing session '$id'; unchanged");
-                return true;
-            } else {
-                self::logdeb("Session '$id' data changed; updating");
-
-                $orig = clone($session);
-
-                $session->session_data = $session_data;
-
-                $result = $session->update($orig);
-
-                if (!$result) {
-                    common_log_db_error($session, 'UPDATE', __FILE__);
-                    self::logdeb("Failed to update '$id'.");
-                } else {
-                    self::logdeb("Successfully updated '$id' (result = $result).");
-                }
-
-                return (bool) $result;
-            }
-        }
-    }
-
-    /**
-     * Find sessions that have persisted beyond $maxlifetime and delete them.
-     * This will be limited by config['sessions']['gc_limit'] - it won't delete
-     * more than the number of sessions specified there at a single pass.
-     *
-     * @param $maxlifetime
-     * @return bool Returns TRUE on success or FALSE on failure.
-     */
-    public static function gc($maxlifetime)
-    {
-        self::logdeb("garbage collection (maxlifetime = $maxlifetime)");
-
-        $epoch = common_sql_date(time() - $maxlifetime);
-
-        $ids = [];
-
-        $session = new Session();
-        $session->whereAdd('modified < "' . $epoch . '"');
-        $session->selectAdd();
-        $session->selectAdd('id');
-
-        $limit = common_config('sessions', 'gc_limit');
-        if ($limit > 0) {
-            // On large sites, too many sessions to expire
-            // at once will just result in failure.
-            $session->limit($limit);
-        }
-
-        $session->find();
-
-        while ($session->fetch()) {
-            $ids[] = $session->id;
-        }
-
-        $session->free();
-
-        self::logdeb("Found " . count($ids) . " ids to delete.");
-
-        foreach ($ids as $id) {
-            self::logdeb("Destroying session '$id'.");
-            self::destroy($id);
-        }
-
-        return true;
-    }
-
-    /**
-     * Deletes session with given id $id.
-     *
-     * @param $id
-     * @return bool Returns TRUE on success or FALSE on failure.
-     */
-    public static function destroy($id)
-    {
-        self::logdeb("Deleting session $id");
-
-        $session = Session::getKV('id', $id);
-
-        if (empty($session)) {
-            self::logdeb("Can't find '$id' to delete.");
-            return false;
-        } else {
-            $result = $session->delete();
-            if (!$result) {
-                common_log_db_error($session, 'DELETE', __FILE__);
-                self::logdeb("Failed to delete '$id'.");
-            } else {
-                self::logdeb("Successfully deleted '$id' (result = $result).");
-            }
-            return (bool) $result;
-        }
-    }
-
-    /**
-     * Set our session handler as the handler for PHP session handling in the context of GNU social.
-     *
-     * @return bool Returns TRUE on success or FALSE on failure.
-     */
-    public static function setSaveHandler()
-    {
-        self::logdeb("setting save handlers");
-        $result = session_set_save_handler(
-            'Session::open',
-            'Session::close',
-            'Session::read',
-            'Session::write',
-            'Session::destroy',
-            'Session::gc'
-        );
-        self::logdeb("save handlers result = $result");
-
-        // PHP 5.3 with APC ends up destroying a bunch of object stuff before the session
-        // save handlers get called on request teardown.
-        // Registering an explicit shutdown function should take care of this before
-        // everything breaks on us.
-        register_shutdown_function('Session::cleanup');
-
-        return $result;
-    }
-
-    /**
-     * Stuff to do before the request teardown.
-     *
-     * @return void
-     */
-    public static function cleanup()
-    {
-        session_write_close();
-    }
 }
diff --git a/lib/internalsessionhandler.php b/lib/internalsessionhandler.php
new file mode 100644 (file)
index 0000000..248e7b3
--- /dev/null
@@ -0,0 +1,219 @@
+<?php
+/**
+ * GNU social's implementation of SessionHandler
+ *
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2009, StatusNet, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+if (!defined('GNUSOCIAL')) {
+    exit(1);
+}
+
+/**
+ * Superclass representing the associated interfaces of session handling.
+ *
+ * @author GNU social
+ */
+class InternalSessionHandler implements SessionHandlerInterface
+{
+    /**
+     * A helper function to print a session-related message to the debug log if
+     * the site session debug configuration option is enabled.
+     * @param $msg
+     * @return void
+     */
+    public static function logdeb($msg)
+    {
+        if (common_config('sessions', 'debug')) {
+            common_debug("Session: " . $msg);
+        }
+    }
+
+    /**
+     * Dummy option for saving to file needed for full PHP adherence.
+     *
+     * @param $save_path
+     * @param $session_name
+     * @return bool true
+     */
+    public function open($save_path, $session_name)
+    {
+        return true;
+    }
+
+    /**
+     * Dummy option for saving to file needed for full PHP adherence.
+     *
+     * @return bool true
+     */
+    public function close()
+    {
+        return true;
+    }
+
+    /**
+     * Fetch the session data for the session with the given $id.
+     *
+     * @param $id
+     * @return string Returns an encoded string of the read data. If nothing was read, it must return an empty string. Note this value is returned internally to PHP for processing.
+     */
+    public function read($id)
+    {
+        self::logdeb("Fetching session '$id'");
+
+        $session = Session::getKV('id', $id);
+
+        if (empty($session)) {
+            self::logdeb("Couldn't find '$id'");
+            return '';
+        } else {
+            self::logdeb("Found '$id', returning " .
+                         strlen($session->session_data) .
+                         " chars of data");
+            return (string)$session->session_data;
+        }
+    }
+
+    /**
+     * Write the session data for session with given $id as $session_data.
+     *
+     * @param $id
+     * @param $session_data
+     * @return bool Returns TRUE on success or FALSE on failure.
+     */
+    public function write($id, $session_data)
+    {
+        self::logdeb("Writing session '$id'");
+
+        $session = Session::getKV('id', $id);
+
+        if (empty($session)) {
+            self::logdeb("'$id' doesn't yet exist; inserting.");
+            $session = new Session();
+
+            $session->id = $id;
+            $session->session_data = $session_data;
+            $session->created = common_sql_now();
+
+            $result = $session->insert();
+
+            if (!$result) {
+                common_log_db_error($session, 'INSERT', __FILE__);
+                self::logdeb("Failed to insert '$id'.");
+            } else {
+                self::logdeb("Successfully inserted '$id' (result = $result).");
+            }
+            return (bool) $result;
+        } else {
+            self::logdeb("'$id' already exists; updating.");
+            if (strcmp($session->session_data, $session_data) == 0) {
+                self::logdeb("Not writing session '$id'; unchanged");
+                return true;
+            } else {
+                self::logdeb("Session '$id' data changed; updating");
+
+                $orig = clone($session);
+
+                $session->session_data = $session_data;
+
+                $result = $session->update($orig);
+
+                if (!$result) {
+                    common_log_db_error($session, 'UPDATE', __FILE__);
+                    self::logdeb("Failed to update '$id'.");
+                } else {
+                    self::logdeb("Successfully updated '$id' (result = $result).");
+                }
+
+                return (bool) $result;
+            }
+        }
+    }
+
+    /**
+     * Find sessions that have persisted beyond $maxlifetime and delete them.
+     * This will be limited by config['sessions']['gc_limit'] - it won't delete
+     * more than the number of sessions specified there at a single pass.
+     *
+     * @param $maxlifetime
+     * @return bool Returns TRUE on success or FALSE on failure.
+     */
+    public function gc($maxlifetime)
+    {
+        self::logdeb("garbage collection (maxlifetime = $maxlifetime)");
+
+        $epoch = common_sql_date(time() - $maxlifetime);
+
+        $ids = [];
+
+        $session = new Session();
+        $session->whereAdd('modified < "' . $epoch . '"');
+        $session->selectAdd();
+        $session->selectAdd('id');
+
+        $limit = common_config('sessions', 'gc_limit');
+        if ($limit > 0) {
+            // On large sites, too many sessions to expire
+            // at once will just result in failure.
+            $session->limit($limit);
+        }
+
+        $session->find();
+
+        while ($session->fetch()) {
+            $ids[] = $session->id;
+        }
+
+        $session->free();
+
+        self::logdeb("Found " . count($ids) . " ids to delete.");
+
+        foreach ($ids as $id) {
+            self::logdeb("Destroying session '$id'.");
+            self::destroy($id);
+        }
+
+        return true;
+    }
+
+    /**
+     * Deletes session with given id $id.
+     *
+     * @param $id
+     * @return bool Returns TRUE on success or FALSE on failure.
+     */
+    public function destroy($id)
+    {
+        self::logdeb("Deleting session $id");
+
+        $session = Session::getKV('id', $id);
+
+        if (empty($session)) {
+            self::logdeb("Can't find '$id' to delete.");
+            return false;
+        } else {
+            $result = $session->delete();
+            if (!$result) {
+                common_log_db_error($session, 'DELETE', __FILE__);
+                self::logdeb("Failed to delete '$id'.");
+            } else {
+                self::logdeb("Successfully deleted '$id' (result = $result).");
+            }
+            return (bool) $result;
+        }
+    }
+}
index 9466d9c0524457afd1c244a9bddb7e815ee49275..1668634020eb40f17e711b8d2583121c00d601a4 100644 (file)
@@ -283,7 +283,7 @@ function common_ensure_session()
     }
     if (!common_have_session()) {
         if (common_config('sessions', 'handle')) {
-            Session::setSaveHandler();
+            session_set_save_handler(new InternalSessionHandler(), true);
         }
         if (array_key_exists(session_name(), $_GET)) {
             $id = $_GET[session_name()];