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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
|
<?php
/**
* This class provides a class with behaviour similar to the $_SESSION variable.
* Data is automatically saved on exit.
*
* Care should be taken when using this class to store objects. It will not detect changes to objects
* automatically. Instead, a call to set(...) should be done to notify this class of changes.
*
* @author Olav Morken, UNINETT AS.
* @package simpleSAMLphp
* @version $Id$
*/
class SimpleSAML_MemcacheStore {
/**
* This variable contains the id for this data.
*
* This variable is serialized.
*/
private $id = NULL;
/**
* This variable contains an array with all key-value pairs stored
* in this object.
*
* This variable is serialized.
*/
private $data = NULL;
/**
* This variable indicates whether our shutdown function has been registered.
*
* This variable isn't serialized.
*/
private $shutdownFunctionRegistered = FALSE;
/**
* This function is used to find an existing storage object. It will return NULL if no storage object
* with the given id is found.
*
* @param $id The id of the storage object we are looking for. A id consists of lowercase
* alphanumeric characters.
* @return The corresponding MemcacheStorage object if the data is found or NULL if it isn't found.
*/
public static function find($id) {
assert(self::isValidID($id));
$serializedData = SimpleSAML_Memcache::get($id);
if($serializedData === NULL) {
return NULL;
}
$data = unserialize($serializedData);
if(!($data instanceof self)) {
SimpleSAML_Logger::warning('Retrieved key from memcache did not contain a MemcacheStore object.');
return NULL;
}
return $data;
}
/**
* This constructor is used to create a new storage object. The storage object will be created with the
* specified id and the initial content passed in the data argument.
*
* If there exists a storage object with the specified id, then it will be overwritten.
*
* @param $id The id of the storage object.
* @param $data An array containing the initial data of the storage object.
*/
public function __construct($id, $data = array()) {
/* Validate arguments. */
assert(self::isValidID($id));
assert(is_array($data));
$this->id = $id;
$this->data = $data;
}
/**
* This magic function is called on serialization of this class. It returns a list of the names of the
* variables which should be serialized.
*
* @return List of variables which should be serialized.
*/
private function __sleep() {
return array('id', 'data');
}
/**
* This function retrieves the specified key from this storage object.
*
* @param $key The key we should retrieve the value of.
* @return The value of the specified key, or NULL of the key wasn't found.
*/
public function get($key) {
if(!array_key_exists($key, $this->data)) {
return NULL;
}
return $this->data[$key];
}
/**
* This function sets the specified key to the specified value in this
* storage object.
*
* @param $key The key we should set.
* @param $value The value we should set the key to.
*/
public function set($key, $value) {
$this->data[$key] = $value;
/* Register the shutdown function if it isn't registered yet. */
if(!$this->shutdownFunctionRegistered) {
$this->registerShutdownFunction();
}
}
/**
* This function stores this storage object to the memcache servers.
*/
public function save() {
/* Write to the memcache servers. */
SimpleSAML_Memcache::set($this->id, serialize($this));
}
/**
* This function determines whether the argument is a valid id.
* A valid id is a string containing lowercase alphanumeric
* characters.
*
* @param $id The id we should validate.
* @return TRUE if the id is valid, FALSE otherwise.
*/
private static function isValidID($id) {
if(!is_string($id)) {
return FALSE;
}
if(strlen($id) < 1) {
return FALSE;
}
if(preg_match('/[^0-9a-z]/', $id)) {
return FALSE;
}
return TRUE;
}
/**
* Register our shutdown function.
*/
private function registerShutdownFunction() {
register_shutdown_function(array($this, 'shutdown'));
$this->shutdownFunctionRegistered = TRUE;
}
/**
* Shutdown function. Calls save and updates flag indicating that the function has been called.
*
* This function is only public because this is a requirement of the way callbacks work in PHP.
*/
public function shutdown() {
$this->save();
$this->shutdownFunctionRegistered = FALSE;
}
}
?>
|