PluginProbe
QuadMenu – Mega Menu / 3.3.8
QuadMenu – Mega Menu v3.3.8
3.3.8 3.3.7 3.3.6 trunk 1.8.4 1.8.5 1.8.7 1.8.8 1.8.9 1.9.0 1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 All 88 releases
quadmenu / jetpack_vendor / automattic / jetpack-status / src / class-visitor.php

class-visitor.php in QuadMenu – Mega Menu 3.3.8, at jetpack_vendor/automattic/jetpack-status/src/class-visitor.php

125 lines 4.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Status and information regarding the site visitor.
4 *
5 * @package automattic/jetpack-status
6 */
7
8 namespace Automattic\Jetpack\Status;
9
10 use Automattic\Jetpack\IP\Utils as IP_Utils;
11
12 /**
13 * Visitor class.
14 */
15 class Visitor {
16
17 /**
18 * Gets current user IP address.
19 *
20 * Only a value that parses as an IP address is returned. With `$check_all_headers`, the
21 * forwarded headers are tried in order, a comma-separated list yields its first valid entry,
22 * and a header holding no valid address is skipped.
23 *
24 * A site with a trusted header configured does not use that sweep at all. Brute force
25 * protection stores which header carries the visitor address, how far back to count in its
26 * list, and whether that list runs in reverse, all worked out for this site's own proxy
27 * setup. Once that answer exists it is the answer, including when the request did not carry
28 * the header — `IP\Utils::get_ip()` falls back to `REMOTE_ADDR` itself in that case. Reading
29 * the sweep afterwards would let a request that simply omits the trusted header pick its own
30 * address out of a header it fully controls, and would hand Jetpack two answers for one
31 * request, since brute force protection resolves the same visitor through `IP\Utils`.
32 *
33 * That is a guarantee about which source is consulted, not about the address itself: it
34 * still assumes the proxy named in the stored configuration rewrites the header. A request
35 * reaching the origin directly can present that header itself.
36 *
37 * The address is normalized by `IP\Utils::clean_ip()`: it is lowercased, anything following an
38 * " unless " separator is dropped, and a port suffix, IPv6 brackets, or an `::ffff:` IPv4
39 * mapping are reduced to the bare address. Code comparing this value against a stored or
40 * configured address should normalize that address the same way.
41 *
42 * @param bool $check_all_headers Check all headers? Default is `false`.
43 *
44 * @return string Current user IP address, or an empty string if no valid address could be determined.
45 */
46 public function get_ip( $check_all_headers = false ) {
47 if ( $check_all_headers ) {
48 $trusted_header_data = get_site_option( 'trusted_ip_header' );
49 if ( isset( $trusted_header_data->trusted_header ) ) {
50 $trusted_ip = IP_Utils::get_ip();
51 return false !== $trusted_ip ? $trusted_ip : '';
52 }
53
54 foreach ( array(
55 'HTTP_CF_CONNECTING_IP',
56 'HTTP_CLIENT_IP',
57 'HTTP_X_FORWARDED_FOR',
58 'HTTP_X_FORWARDED',
59 'HTTP_X_CLUSTER_CLIENT_IP',
60 'HTTP_FORWARDED_FOR',
61 'HTTP_FORWARDED',
62 'HTTP_VIA',
63 ) as $key ) {
64 if ( empty( $_SERVER[ $key ] ) ) {
65 continue;
66 }
67 // Proxies append to the list, so the leftmost entry is the client.
68 foreach ( explode( ',', (string) wp_unslash( $_SERVER[ $key ] ) ) as $candidate ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Each entry is validated by clean_ip() below.
69 $ip = IP_Utils::clean_ip( $candidate );
70 if ( false !== $ip ) {
71 return $ip;
72 }
73 }
74 }
75 }
76
77 $ip = empty( $_SERVER['REMOTE_ADDR'] ) ? false : IP_Utils::clean_ip( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- clean_ip() validates it.
78 return false !== $ip ? $ip : '';
79 }
80
81 /**
82 * Simple gate check for a11n feature testing purposes using AT_PROXIED_REQUEST constant.
83 * IMPORTANT: Only use it for internal feature test purposes, not authorization.
84 *
85 * The goal of this function is to help us gate features by using a similar function name
86 * we find on simple sites: is_automattician().
87 *
88 * @return bool True if the current request is PROXIED, false otherwise.
89 */
90 public function is_automattician_feature_flags_only() {
91 return ( defined( 'AT_PROXIED_REQUEST' ) && AT_PROXIED_REQUEST );
92 }
93
94 /**
95 * Whether the current request should be attributed to an Automattician in analytics.
96 *
97 * True for an identified Automattician on WordPress.com Simple, and for A8C-proxied
98 * requests on both Simple and WoA. Use it to tag Tracks events as internal traffic so
99 * it can be filtered out of product reporting — this matters most for newly launched
100 * features, where a small amount of internal testing is a large share of the totals
101 * and there is no way to separate it after the fact.
102 *
103 * IMPORTANT: Reporting signal only, never authorization. A proxied request says
104 * something about where the request came from, not who the user is.
105 *
106 * @since 6.4.0
107 *
108 * @return bool True if the request looks like Automattician traffic, false otherwise.
109 */
110 public function is_tracking_automattician() {
111 // Identified Automattician on WordPress.com Simple.
112 if ( function_exists( 'is_automattician' ) && \is_automattician() ) {
113 return true;
114 }
115
116 // Proxied A8C request on WordPress.com Simple.
117 if ( function_exists( 'wpcom_is_proxied_request' ) && \wpcom_is_proxied_request() ) {
118 return true;
119 }
120
121 // Proxied A8C request on WoA.
122 return $this->is_automattician_feature_flags_only();
123 }
124 }
125