aboutsummaryrefslogtreecommitdiff
path: root/lib/session/DbSessionHandler.php
blob: d64fe464be821b1d7e8d8dd2e183c84ef3d9182e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
<?php
/**
 * Session handler for using Stud.IP database as session storage
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * @author      André Noack <noack@data-quest.de>
 */

namespace Studip\Session;
use DBManager;
use Config;
use CronjobTask;
use SessionGcJob;
use SessionHandlerInterface;
use SessionIdInterface;
use SessionUpdateTimestampHandlerInterface;

class DbSessionHandler implements
    SessionHandlerInterface,
    SessionIdInterface,
    SessionUpdateTimestampHandlerInterface
{
    private ?string $exists = null;

    public function close(): bool
    {
        return true;
    }

    public function destroy(string $id): bool
    {
        return (bool) DBManager::get()->execute(
            "DELETE FROM session_data WHERE sid = ? LIMIT 1",
            [$id]
        );
    }

    public function gc(int $max_lifetime): false|int
    {
        // bail out if cronjob activated and not called in cli context
        if (
            Config::getInstance()->getValue('CRONJOBS_ENABLE')
            && ($task = CronjobTask::findOneByClass(SessionGcJob::class))
            && count($task->schedules->findBy('active', 1))
            && PHP_SAPI !== 'cli'
        ) {
            return false;
        }
        return DBManager::get()->execute(
            "DELETE FROM session_data WHERE changed < FROM_UNIXTIME(?) ",
            [time() - $max_lifetime]
        );
    }

    public function open(string $path, string $name): bool
    {
        return true;
    }

    public function read(string $id): false|string
    {
        $str = DBManager::get()->fetchColumn(
            "SELECT val FROM session_data where sid  = ?",
            [$id]
        );
        if ($str) {
            $this->exists = $id;
        }
        return $str ?: '';
    }

    public function write(string $id, string $data): bool
    {
        $db = DBManager::get();
        if ($this->exists === $id) {
            $stmt = $db->prepare("UPDATE session_data SET val = ? WHERE sid = ?");
        } else {
            $stmt = $db->prepare("REPLACE INTO session_data ( val, sid ) VALUES (?, ?)");
        }
        return (bool) $stmt->execute([$data, $id]);
    }

    public function exists(string $id): bool
    {
        return (bool) DBManager::get()->fetchColumn(
            "SELECT 1 FROM session_data where sid  = ?",
            [$id]
        );
    }

    public function create_sid(): string
    {
        do {
            $new_id = md5(bin2hex(random_bytes(128)));
        } while ($this->exists($new_id));
        $this->exists = null;
        return $new_id;
    }

    public function updateTimestamp(string $id, string $data): bool
    {
        DBManager::get()->execute("UPDATE session_data SET changed = CURRENT_TIMESTAMP() WHERE sid = ?", [$id]);
        return true;
    }

    public function validateId(string $id): bool
    {
        return $this->exists($id);
    }


}