aboutsummaryrefslogtreecommitdiffstats
path: root/Zotlabs/Web/SessionRedis.php
blob: f32e6a4f46e3d269b24da76b21149f656cbd2f54 (plain) (blame)
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
117
118
119
120
121
122
123
124
<?php

namespace Zotlabs\Web;


class SessionRedis implements \SessionHandlerInterface {

        private $redis = null;


        function __construct($connection) {

                $this->redis = new \Redis();

                $credentials = parse_url($connection);

                try {
                        if (isset($credentials['path']))
                                $this->redis->connect($credentials['path']);
                        else {

                                if (isset($credentials['query']))
                                        parse_str($credentials['query'], $vars);
                                else
                                        $vars = [];

                                $this->redis->connect(
                                        (isset($credentials['scheme']) ? $credentials['scheme'] . '://' : '') . $credentials['host'],
                                        (isset($credentials['port']) ? $credentials['port'] : 6379),
                                        (isset($vars['timeout']) ? $vars['timeout'] : 1),
                                        null,
                                        0,
                                        (isset($vars['read_timeout']) ? $vars['read_timeout'] : 0)
                                );

                                if (isset($vars['auth']))
                                        $this->redis->auth($vars['auth']);
                        }
                }
                catch(\RedisException $ex) {
                        logger('Error connecting to Redis: ' . $ex->getMessage());
                }
        }

        #[\ReturnTypeWillChange]
        function open($s, $n) {

                return true;
        }

        // IMPORTANT: if we read the session and it doesn't exist, create an empty record.
        // We rely on this due to differing PHP implementation of session_regenerate_id()
        // some which call read explicitly and some that do not. So we call it explicitly
        // just after sid regeneration to force a record to exist.

        #[\ReturnTypeWillChange]
        function read($id) {

                if ($id) {
                        $data = $this->redis->get($id);

                        if ($data)
                                return $data;
                        else
                                $this->redis->setEx($id, 300, '');
                }

                return '';
        }

        #[\ReturnTypeWillChange]
        function write($id, $data) {

                // Pretend everything is hunky-dory, even though it isn't.
                // There probably isn't anything we can do about it in any event.
                // See: https://stackoverflow.com/a/43636110

                if(! $id || ! $data)
                        return true;


                // Unless we authenticate somehow, only keep a session for 5 minutes
                // The viewer can extend this by performing any web action using the
                // original cookie, but this allows us to cleanup the hundreds or
                // thousands of empty sessions left around from web crawlers which are
                // assigned cookies on each page that they never use.

                $expire = 300;

                if($_SESSION) {
                        if(array_key_exists('remember_me',$_SESSION) && intval($_SESSION['remember_me']))
                                $expire = 60 * 60 * 24 * 365;
                        elseif(local_channel())
                                $expire = 60 * 60 * 24 * 3;
                        elseif(remote_channel())
                                $expire = 60 * 60 * 24 * 1;
                }

                $this->redis->setEx($id, $expire, $data);

                return true;
        }

        #[\ReturnTypeWillChange]
        function close() {

                return true;
        }

        #[\ReturnTypeWillChange]
        function destroy ($id) {

                $this->redis->del($id);

                return true;
        }

        #[\ReturnTypeWillChange]
        function gc($expire) {

                return true;
        }

}