PluginProbe ʕ •ᴥ•ʔ
Everest Forms – Contact Form, Payment Form, Quiz, Survey & Custom Form Builder with AI / 3.0.8
Everest Forms – Contact Form, Payment Form, Quiz, Survey & Custom Form Builder with AI v3.0.8
3.5.1 3.5.0 3.4.8 3.4.7 3.4.6 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.5.1 1.1.6 1.1.7 1.1.8 1.1.9 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.5.0 1.5.1 1.5.10 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.6.1 1.6.7 1.7.0 1.7.0.1 1.7.0.2 1.7.0.3 1.7.1 1.7.2 1.7.2.1 1.7.2.2 1.7.3 1.7.4 1.7.5 1.7.5.1 1.7.5.2 1.7.6 1.7.7 1.7.7.1 1.7.7.2 1.7.8 1.7.9 1.8.0 1.8.0.1 1.8.1 1.8.2 1.8.2.1 1.8.2.2 1.8.2.3 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 1.9.0 1.9.0.1 1.9.1 1.9.2 1.9.3 1.9.4 1.9.4.1 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.0.1 2.0.1 2.0.2 2.0.3 2.0.3.1 2.0.4 2.0.4.1 2.0.5 2.0.6 2.0.7 2.0.8 2.0.8.1 2.0.9 3.0.0 3.0.0.1 3.0.1 3.0.2 3.0.3 3.0.3.1 3.0.4 3.0.4.1 3.0.4.2 3.0.5 3.0.5.1 3.0.5.2 3.0.6 3.0.6.1 3.0.7.1 3.0.8 3.0.8.1 3.0.9 3.0.9.1 3.0.9.2 3.0.9.3 3.0.9.4 3.0.9.5 3.1.0 3.1.1 3.1.2 3.2.0 3.2.1 3.2.2 3.2.3 3.2.4 3.2.5 3.2.6 3.3.0 3.4.0 3.4.1 3.4.2 3.4.2.1 3.4.3 3.4.4 3.4.5 trunk 1.0 1.0.1 1.0.2 1.0.3
everest-forms / includes / class-evf-session-handler.php
everest-forms / includes Last commit date
RestApi 1 year ago abstracts 1 year ago admin 1 year ago blocks 1 year ago elementor 2 years ago export 1 year ago fields 1 year ago interfaces 8 years ago libraries 2 years ago log-handlers 4 years ago shortcodes 1 year ago stats 3 years ago templates 5 years ago class-everest-forms.php 1 year ago class-evf-ajax.php 1 year ago class-evf-autoloader.php 7 years ago class-evf-background-process-import-entries.php 1 year ago class-evf-background-updater.php 7 years ago class-evf-cache-helper.php 6 years ago class-evf-cron.php 2 years ago class-evf-deprecated-action-hooks.php 6 years ago class-evf-deprecated-filter-hooks.php 5 years ago class-evf-emails.php 1 year ago class-evf-fields.php 2 years ago class-evf-form-handler.php 1 year ago class-evf-form-task.php 1 year ago class-evf-forms-features.php 1 year ago class-evf-frontend-scripts.php 1 year ago class-evf-install.php 2 years ago class-evf-integrations.php 2 years ago class-evf-log-levels.php 8 years ago class-evf-logger.php 5 years ago class-evf-post-types.php 5 years ago class-evf-privacy.php 6 years ago class-evf-report-cron.php 2 years ago class-evf-reporting.php 2 years ago class-evf-session-handler.php 7 years ago class-evf-shortcodes.php 4 years ago class-evf-smart-tags.php 1 year ago class-evf-template-loader.php 2 years ago class-evf-validation.php 6 years ago evf-conditional-functions.php 6 years ago evf-core-functions.php 1 year ago evf-deprecated-functions.php 6 years ago evf-entry-functions.php 1 year ago evf-formatting-functions.php 4 years ago evf-notice-functions.php 4 years ago evf-template-functions.php 4 years ago evf-template-hooks.php 7 years ago evf-update-functions.php 5 years ago
class-evf-session-handler.php
313 lines
1 <?php
2 /**
3 * Handle data for the current customers session.
4 * Implements the EVF_Session abstract class.
5 *
6 * @package EverestForms\Classes
7 * @since 1.0.0
8 */
9
10 defined( 'ABSPATH' ) || exit;
11
12 /**
13 * Session handler class.
14 */
15 class EVF_Session_Handler extends EVF_Session {
16
17 /**
18 * Cookie name used for the session.
19 *
20 * @var string cookie name
21 */
22 protected $_cookie;
23
24 /**
25 * Stores session expiry.
26 *
27 * @var string session due to expire timestamp
28 */
29 protected $_session_expiring;
30
31 /**
32 * Stores session due to expire timestamp.
33 *
34 * @var string session expiration timestamp
35 */
36 protected $_session_expiration;
37
38 /**
39 * True when the cookie exists.
40 *
41 * @var bool Based on whether a cookie exists.
42 */
43 protected $_has_cookie = false;
44
45 /**
46 * Table name for session data.
47 *
48 * @var string Custom session table name
49 */
50 protected $_table;
51
52 /**
53 * Constructor for the session class.
54 */
55 public function __construct() {
56 $this->_cookie = apply_filters( 'everest_forms_cookie', 'wp_everest_forms_session_' . COOKIEHASH );
57 $this->_table = $GLOBALS['wpdb']->prefix . 'evf_sessions';
58 }
59
60 /**
61 * Init hooks and session data.
62 */
63 public function init() {
64 $cookie = $this->get_session_cookie();
65
66 if ( $cookie ) {
67 $this->_customer_id = $cookie[0];
68 $this->_session_expiration = $cookie[1];
69 $this->_session_expiring = $cookie[2];
70 $this->_has_cookie = true;
71
72 // Update session if its close to expiring.
73 if ( time() > $this->_session_expiring ) {
74 $this->set_session_expiration();
75 $this->update_session_timestamp( $this->_customer_id, $this->_session_expiration );
76 }
77 } else {
78 $this->set_session_expiration();
79 $this->_customer_id = $this->generate_customer_id();
80 }
81
82 $this->_data = $this->get_session_data();
83
84 add_action( 'shutdown', array( $this, 'save_data' ), 20 );
85 add_action( 'wp_logout', array( $this, 'destroy_session' ) );
86
87 if ( ! is_user_logged_in() ) {
88 add_filter( 'nonce_user_logged_out', array( $this, 'nonce_user_logged_out' ) );
89 }
90 }
91
92 /**
93 * Return true if the current user has an active session, i.e. a cookie to retrieve values.
94 *
95 * @return bool
96 */
97 public function has_session() {
98 return isset( $_COOKIE[ $this->_cookie ] ) || $this->_has_cookie || is_user_logged_in(); // @codingStandardsIgnoreLine.
99 }
100
101 /**
102 * Set session expiration.
103 */
104 public function set_session_expiration() {
105 $this->_session_expiring = time() + intval( apply_filters( 'evf_session_expiring', 60 * 60 * 47 ) ); // 47 Hours.
106 $this->_session_expiration = time() + intval( apply_filters( 'evf_session_expiration', 60 * 60 * 48 ) ); // 48 Hours.
107 }
108
109 /**
110 * Generate a unique customer ID for guests, or return user ID if logged in.
111 *
112 * Uses Portable PHP password hashing framework to generate a unique cryptographically strong ID.
113 *
114 * @return string
115 */
116 public function generate_customer_id() {
117 $customer_id = '';
118
119 if ( is_user_logged_in() ) {
120 $customer_id = get_current_user_id();
121 }
122
123 if ( empty( $customer_id ) ) {
124 require_once ABSPATH . 'wp-includes/class-phpass.php';
125 $hasher = new PasswordHash( 8, false );
126 $customer_id = md5( $hasher->get_random_bytes( 32 ) );
127 }
128
129 return $customer_id;
130 }
131
132 /**
133 * Get the session cookie, if set. Otherwise return false.
134 *
135 * Session cookies without a customer ID are invalid.
136 *
137 * @return bool|array
138 */
139 public function get_session_cookie() {
140 $cookie_value = isset( $_COOKIE[ $this->_cookie ] ) ? wp_unslash( $_COOKIE[ $this->_cookie ] ) : false; // @codingStandardsIgnoreLine.
141
142 if ( empty( $cookie_value ) || ! is_string( $cookie_value ) ) {
143 return false;
144 }
145
146 list( $customer_id, $session_expiration, $session_expiring, $cookie_hash ) = explode( '||', $cookie_value );
147
148 if ( empty( $customer_id ) ) {
149 return false;
150 }
151
152 // Validate hash.
153 $to_hash = $customer_id . '|' . $session_expiration;
154 $hash = hash_hmac( 'md5', $to_hash, wp_hash( $to_hash ) );
155
156 if ( empty( $cookie_hash ) || ! hash_equals( $hash, $cookie_hash ) ) {
157 return false;
158 }
159
160 return array( $customer_id, $session_expiration, $session_expiring, $cookie_hash );
161 }
162
163 /**
164 * Get session data.
165 *
166 * @return array
167 */
168 public function get_session_data() {
169 return $this->has_session() ? (array) $this->get_session( $this->_customer_id, array() ) : array();
170 }
171
172 /**
173 * Gets a cache prefix. This is used in session names so the entire cache can be invalidated with 1 function call.
174 *
175 * @return string
176 */
177 private function get_cache_prefix() {
178 return EVF_Cache_Helper::get_cache_prefix( EVF_SESSION_CACHE_GROUP );
179 }
180
181 /**
182 * Save data.
183 */
184 public function save_data() {
185 // Dirty if something changed - prevents saving nothing new.
186 if ( $this->_dirty && $this->has_session() ) {
187 global $wpdb;
188
189 $wpdb->query(
190 $wpdb->prepare(
191 "INSERT INTO {$wpdb->prefix}evf_sessions (`session_key`, `session_value`, `session_expiry`) VALUES (%s, %s, %d)
192 ON DUPLICATE KEY UPDATE `session_value` = VALUES(`session_value`), `session_expiry` = VALUES(`session_expiry`)",
193 $this->_customer_id,
194 maybe_serialize( $this->_data ),
195 $this->_session_expiration
196 )
197 );
198
199 wp_cache_set( $this->get_cache_prefix() . $this->_customer_id, $this->_data, EVF_SESSION_CACHE_GROUP, $this->_session_expiration - time() );
200 $this->_dirty = false;
201 }
202 }
203
204 /**
205 * Destroy all session data.
206 */
207 public function destroy_session() {
208 evf_setcookie( $this->_cookie, '', time() - YEAR_IN_SECONDS, apply_filters( 'evf_session_use_secure_cookie', false ) );
209
210 $this->delete_session( $this->_customer_id );
211
212 $this->_data = array();
213 $this->_dirty = false;
214 $this->_customer_id = $this->generate_customer_id();
215 }
216
217 /**
218 * When a user is logged out, ensure they have a unique nonce by using the customer/session ID.
219 *
220 * @param int $uid User ID.
221 * @return string
222 */
223 public function nonce_user_logged_out( $uid ) {
224 return $this->has_session() && $this->_customer_id ? $this->_customer_id : $uid;
225 }
226
227 /**
228 * Cleanup session data from the database and clear caches.
229 */
230 public function cleanup_sessions() {
231 global $wpdb;
232
233 $wpdb->query( $wpdb->prepare( "DELETE FROM $this->_table WHERE session_expiry < %d", time() ) ); // @codingStandardsIgnoreLine.
234
235 if ( class_exists( 'EVF_Cache_Helper' ) ) {
236 EVF_Cache_Helper::incr_cache_prefix( EVF_SESSION_CACHE_GROUP );
237 }
238 }
239
240 /**
241 * Returns the session.
242 *
243 * @param string $customer_id Customer ID.
244 * @param mixed $default Default session value.
245 * @return string|array
246 */
247 public function get_session( $customer_id, $default = false ) {
248 global $wpdb;
249
250 if ( defined( 'WP_SETUP_CONFIG' ) ) {
251 return false;
252 }
253
254 // Try to get it from the cache, it will return false if not present or if object cache not in use.
255 $value = wp_cache_get( $this->get_cache_prefix() . $customer_id, EVF_SESSION_CACHE_GROUP );
256
257 if ( false === $value ) {
258 $value = $wpdb->get_var( $wpdb->prepare( "SELECT session_value FROM $this->_table WHERE session_key = %s", $customer_id ) ); // @codingStandardsIgnoreLine.
259
260 if ( is_null( $value ) ) {
261 $value = $default;
262 }
263
264 wp_cache_add( $this->get_cache_prefix() . $customer_id, $value, EVF_SESSION_CACHE_GROUP, $this->_session_expiration - time() );
265 }
266
267 return maybe_unserialize( $value );
268 }
269
270 /**
271 * Delete the session from the cache and database.
272 *
273 * @param int $customer_id Customer ID.
274 */
275 public function delete_session( $customer_id ) {
276 global $wpdb;
277
278 wp_cache_delete( $this->get_cache_prefix() . $customer_id, EVF_SESSION_CACHE_GROUP );
279
280 $wpdb->delete( // @codingStandardsIgnoreLine.
281 $this->_table,
282 array(
283 'session_key' => $customer_id,
284 )
285 );
286 }
287
288 /**
289 * Update the session expiry timestamp.
290 *
291 * @param string $customer_id Customer ID.
292 * @param int $timestamp Timestamp to expire the cookie.
293 */
294 public function update_session_timestamp( $customer_id, $timestamp ) {
295 global $wpdb;
296
297 // @codingStandardsIgnoreStart.
298 $wpdb->update(
299 $this->_table,
300 array(
301 'session_expiry' => $timestamp,
302 ),
303 array(
304 'session_key' => $customer_id,
305 ),
306 array(
307 '%d'
308 )
309 );
310 // @codingStandardsIgnoreEnd.
311 }
312 }
313