This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
1 | <?php |
||||
2 | /** |
||||
3 | * Handle data for the current customers session. |
||||
4 | * Implements the WPInv_Session abstract class. |
||||
5 | * |
||||
6 | */ |
||||
7 | |||||
8 | defined( 'ABSPATH' ) || exit; |
||||
9 | |||||
10 | /** |
||||
11 | * Session handler class. |
||||
12 | * |
||||
13 | * @deprecated |
||||
14 | */ |
||||
15 | class WPInv_Session_Handler extends WPInv_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 int 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 old__construct() { |
||||
56 | |||||
57 | $this->_cookie = apply_filters( 'wpinv_cookie', 'wpinv_session_' . COOKIEHASH ); |
||||
58 | add_action( 'init', array( $this, 'init' ), -1 ); |
||||
59 | add_action( 'wp_logout', array( $this, 'destroy_session' ) ); |
||||
60 | add_action( 'wp', array( $this, 'set_customer_session_cookie' ), 10 ); |
||||
61 | add_action( 'shutdown', array( $this, 'save_data' ), 20 ); |
||||
62 | |||||
63 | } |
||||
64 | |||||
65 | /** |
||||
66 | * Init hooks and session data. |
||||
67 | * |
||||
68 | * @since 3.3.0 |
||||
69 | */ |
||||
70 | public function init() { |
||||
71 | $this->init_session_cookie(); |
||||
72 | |||||
73 | if ( ! is_user_logged_in() ) { |
||||
74 | add_filter( 'nonce_user_logged_out', array( $this, 'nonce_user_logged_out' ), 10, 2 ); |
||||
75 | } |
||||
76 | } |
||||
77 | |||||
78 | /** |
||||
79 | * Setup cookie and customer ID. |
||||
80 | * |
||||
81 | * @since 3.6.0 |
||||
82 | */ |
||||
83 | public function init_session_cookie() { |
||||
84 | $cookie = $this->get_session_cookie(); |
||||
85 | |||||
86 | if ( $cookie ) { |
||||
0 ignored issues
–
show
|
|||||
87 | $this->_customer_id = $cookie[0]; |
||||
0 ignored issues
–
show
The property
$_customer_id was declared of type integer , but $cookie[0] is of type string . Maybe add a type cast?
This check looks for assignments to scalar types that may be of the wrong type. To ensure the code behaves as expected, it may be a good idea to add an explicit type cast. $answer = 42;
$correct = false;
$correct = (bool) $answer;
![]() |
|||||
88 | $this->_session_expiration = $cookie[1]; |
||||
89 | $this->_session_expiring = $cookie[2]; |
||||
0 ignored issues
–
show
The property
$_session_expiring was declared of type integer , but $cookie[2] is of type string . Maybe add a type cast?
This check looks for assignments to scalar types that may be of the wrong type. To ensure the code behaves as expected, it may be a good idea to add an explicit type cast. $answer = 42;
$correct = false;
$correct = (bool) $answer;
![]() |
|||||
90 | $this->_has_cookie = true; |
||||
91 | $this->_data = $this->get_session_data(); |
||||
92 | |||||
93 | // If the user logs in, update session. |
||||
94 | if ( is_user_logged_in() && get_current_user_id() != $this->_customer_id ) { |
||||
95 | $this->_customer_id = get_current_user_id(); |
||||
96 | $this->_dirty = true; |
||||
97 | $this->save_data(); |
||||
98 | $this->set_customer_session_cookie( true ); |
||||
99 | } |
||||
100 | |||||
101 | // Update session if its close to expiring. |
||||
102 | if ( time() > $this->_session_expiring ) { |
||||
103 | $this->set_session_expiration(); |
||||
104 | $this->update_session_timestamp( $this->_customer_id, $this->_session_expiration ); |
||||
105 | } |
||||
106 | } else { |
||||
107 | $this->set_session_expiration(); |
||||
108 | $this->_customer_id = $this->generate_customer_id(); |
||||
109 | $this->_data = $this->get_session_data(); |
||||
110 | } |
||||
111 | } |
||||
112 | |||||
113 | /** |
||||
114 | * Sets the session cookie on-demand (usually after adding an item to the cart). |
||||
115 | * |
||||
116 | * Since the cookie name (as of 2.1) is prepended with wp, cache systems like batcache will not cache pages when set. |
||||
117 | * |
||||
118 | * Warning: Cookies will only be set if this is called before the headers are sent. |
||||
119 | * |
||||
120 | * @param bool $set Should the session cookie be set. |
||||
121 | */ |
||||
122 | public function set_customer_session_cookie( $set ) { |
||||
123 | if ( $set ) { |
||||
124 | $to_hash = $this->_customer_id . '|' . $this->_session_expiration; |
||||
125 | $cookie_hash = hash_hmac( 'md5', $to_hash, wp_hash( $to_hash ) ); |
||||
126 | $cookie_value = $this->_customer_id . '||' . $this->_session_expiration . '||' . $this->_session_expiring . '||' . $cookie_hash; |
||||
127 | $this->_has_cookie = true; |
||||
128 | |||||
129 | if ( ! isset( $_COOKIE[ $this->_cookie ] ) || $_COOKIE[ $this->_cookie ] !== $cookie_value ) { |
||||
130 | $this->setcookie( $this->_cookie, $cookie_value, $this->_session_expiration, $this->use_secure_cookie(), true ); |
||||
131 | } |
||||
132 | } |
||||
133 | } |
||||
134 | |||||
135 | public function setcookie( $name, $value, $expire = 0, $secure = false, $httponly = false ) { |
||||
136 | if ( ! headers_sent() ) { |
||||
137 | setcookie( $name, $value, $expire, COOKIEPATH ? COOKIEPATH : '/', COOKIE_DOMAIN, $secure, apply_filters( 'wpinv_cookie_httponly', $httponly, $name, $value, $expire, $secure ) ); |
||||
0 ignored issues
–
show
COOKIE_DOMAIN of type false is incompatible with the type string expected by parameter $domain of setcookie() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
138 | } elseif ( defined( 'WP_DEBUG' ) && WP_DEBUG ) { |
||||
139 | headers_sent( $file, $line ); |
||||
140 | trigger_error( "{$name} cookie cannot be set - headers already sent by {$file} on line {$line}", E_USER_NOTICE ); // @codingStandardsIgnoreLine |
||||
141 | } |
||||
142 | } |
||||
143 | |||||
144 | /** |
||||
145 | * Should the session cookie be secure? |
||||
146 | * |
||||
147 | * @since 3.6.0 |
||||
148 | * @return bool |
||||
149 | */ |
||||
150 | protected function use_secure_cookie() { |
||||
151 | $is_https = false !== strstr( get_option( 'home' ), 'https:' ); |
||||
0 ignored issues
–
show
It seems like
get_option('home') can also be of type false ; however, parameter $haystack of strstr() does only seem to accept string , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
152 | return apply_filters( 'wpinv_session_use_secure_cookie', $is_https && is_ssl() ); |
||||
153 | } |
||||
154 | |||||
155 | /** |
||||
156 | * Return true if the current user has an active session, i.e. a cookie to retrieve values. |
||||
157 | * |
||||
158 | * @return bool |
||||
159 | */ |
||||
160 | public function has_session() { |
||||
161 | return isset( $_COOKIE[ $this->_cookie ] ) || $this->_has_cookie || is_user_logged_in(); // @codingStandardsIgnoreLine. |
||||
162 | } |
||||
163 | |||||
164 | /** |
||||
165 | * Set session expiration. |
||||
166 | */ |
||||
167 | public function set_session_expiration() { |
||||
168 | $this->_session_expiring = time() + intval( apply_filters( 'wpinv_session_expiring', 60 * 60 * 47 ) ); // 47 Hours. |
||||
169 | $this->_session_expiration = time() + intval( apply_filters( 'wpinv_session_expiration', 60 * 60 * 48 ) ); // 48 Hours. |
||||
170 | } |
||||
171 | |||||
172 | /** |
||||
173 | * Generates session ids. |
||||
174 | * |
||||
175 | * @return string |
||||
176 | */ |
||||
177 | public function generate_customer_id() { |
||||
178 | require_once ABSPATH . 'wp-includes/class-phpass.php'; |
||||
179 | $hasher = new PasswordHash( 8, false ); |
||||
180 | return md5( $hasher->get_random_bytes( 32 ) ); |
||||
181 | } |
||||
182 | |||||
183 | /** |
||||
184 | * Get the session cookie, if set. Otherwise return false. |
||||
185 | * |
||||
186 | * Session cookies without a customer ID are invalid. |
||||
187 | * |
||||
188 | * @return bool|array |
||||
189 | */ |
||||
190 | public function get_session_cookie() { |
||||
191 | $cookie_value = isset( $_COOKIE[ $this->_cookie ] ) ? wp_unslash( $_COOKIE[ $this->_cookie ] ) : false; // @codingStandardsIgnoreLine. |
||||
192 | |||||
193 | if ( empty( $cookie_value ) || ! is_string( $cookie_value ) ) { |
||||
194 | return false; |
||||
195 | } |
||||
196 | |||||
197 | list( $customer_id, $session_expiration, $session_expiring, $cookie_hash ) = explode( '||', $cookie_value ); |
||||
198 | |||||
199 | if ( empty( $customer_id ) ) { |
||||
200 | return false; |
||||
201 | } |
||||
202 | |||||
203 | // Validate hash. |
||||
204 | $to_hash = $customer_id . '|' . $session_expiration; |
||||
205 | $hash = hash_hmac( 'md5', $to_hash, wp_hash( $to_hash ) ); |
||||
206 | |||||
207 | if ( empty( $cookie_hash ) || ! hash_equals( $hash, $cookie_hash ) ) { |
||||
208 | return false; |
||||
209 | } |
||||
210 | |||||
211 | return array( $customer_id, $session_expiration, $session_expiring, $cookie_hash ); |
||||
212 | } |
||||
213 | |||||
214 | /** |
||||
215 | * Get session data. |
||||
216 | * |
||||
217 | * @return array |
||||
218 | */ |
||||
219 | public function get_session_data() { |
||||
220 | return $this->has_session() ? (array) $this->get_session( $this->_customer_id ) : array(); |
||||
221 | } |
||||
222 | |||||
223 | public function generate_key( $customer_id ) { |
||||
224 | if ( ! $customer_id ) { |
||||
225 | return; |
||||
226 | } |
||||
227 | |||||
228 | return 'wpi_trans_' . $customer_id; |
||||
229 | } |
||||
230 | |||||
231 | /** |
||||
232 | * Save data. |
||||
233 | */ |
||||
234 | public function save_data() { |
||||
235 | // Dirty if something changed - prevents saving nothing new. |
||||
236 | if ( $this->_dirty && $this->has_session() ) { |
||||
237 | |||||
238 | set_transient( $this->generate_key( $this->_customer_id ), $this->_data, $this->_session_expiration ); |
||||
0 ignored issues
–
show
$this->_session_expiration of type string is incompatible with the type integer expected by parameter $expiration of set_transient() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
239 | |||||
240 | $this->_dirty = false; |
||||
241 | } |
||||
242 | } |
||||
243 | |||||
244 | /** |
||||
245 | * Destroy all session data. |
||||
246 | */ |
||||
247 | public function destroy_session() { |
||||
248 | $this->delete_session( $this->_customer_id ); |
||||
249 | $this->forget_session(); |
||||
250 | } |
||||
251 | |||||
252 | /** |
||||
253 | * Forget all session data without destroying it. |
||||
254 | */ |
||||
255 | public function forget_session() { |
||||
256 | $this->setcookie( $this->_cookie, '', time() - YEAR_IN_SECONDS, $this->use_secure_cookie(), true ); |
||||
257 | |||||
258 | wpinv_empty_cart(); |
||||
0 ignored issues
–
show
The function
wpinv_empty_cart() has been deprecated.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
259 | |||||
260 | $this->_data = array(); |
||||
261 | $this->_dirty = false; |
||||
262 | $this->_customer_id = $this->generate_customer_id(); |
||||
0 ignored issues
–
show
The property
$_customer_id was declared of type integer , but $this->generate_customer_id() is of type string . Maybe add a type cast?
This check looks for assignments to scalar types that may be of the wrong type. To ensure the code behaves as expected, it may be a good idea to add an explicit type cast. $answer = 42;
$correct = false;
$correct = (bool) $answer;
![]() |
|||||
263 | } |
||||
264 | |||||
265 | /** |
||||
266 | * When a user is logged out, ensure they have a unique nonce by using the customer/session ID. |
||||
267 | * |
||||
268 | * @param int $uid User ID. |
||||
269 | * @return string |
||||
270 | */ |
||||
271 | public function nonce_user_logged_out( $uid ) { |
||||
272 | |||||
273 | // Check if one of our nonces. |
||||
274 | if ( substr( $uid, 0, 5 ) === 'wpinv' || substr( $uid, 0, 7 ) === 'getpaid' ) { |
||||
275 | return $this->has_session() && $this->_customer_id ? $this->_customer_id : $uid; |
||||
276 | } |
||||
277 | |||||
278 | return $uid; |
||||
279 | } |
||||
280 | |||||
281 | /** |
||||
282 | * Returns the session. |
||||
283 | * |
||||
284 | * @param string $customer_id Customer ID. |
||||
285 | * @param mixed $default Default session value. |
||||
286 | * @return string|array |
||||
287 | */ |
||||
288 | public function get_session( $customer_id, $default = false ) { |
||||
289 | |||||
290 | if ( defined( 'WP_SETUP_CONFIG' ) ) { |
||||
291 | return array(); |
||||
292 | } |
||||
293 | |||||
294 | $key = $this->generate_key( $customer_id ); |
||||
295 | $value = get_transient( $key ); |
||||
296 | |||||
297 | if ( ! $value ) { |
||||
298 | $value = $default; |
||||
299 | } |
||||
300 | |||||
301 | return maybe_unserialize( $value ); |
||||
302 | } |
||||
303 | |||||
304 | /** |
||||
305 | * Delete the session from the cache and database. |
||||
306 | * |
||||
307 | * @param int $customer_id Customer ID. |
||||
308 | */ |
||||
309 | public function delete_session( $customer_id ) { |
||||
310 | |||||
311 | $key = $this->generate_key( $customer_id ); |
||||
312 | |||||
313 | delete_transient( $key ); |
||||
314 | } |
||||
315 | |||||
316 | /** |
||||
317 | * Update the session expiry timestamp. |
||||
318 | * |
||||
319 | * @param string $customer_id Customer ID. |
||||
320 | * @param int $timestamp Timestamp to expire the cookie. |
||||
321 | */ |
||||
322 | public function update_session_timestamp( $customer_id, $timestamp ) { |
||||
323 | |||||
324 | set_transient( $this->generate_key( $customer_id ), maybe_serialize( $this->_data ), $timestamp ); |
||||
325 | |||||
326 | } |
||||
327 | } |
||||
328 |
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.