PluginProbe
MxChat – AI Chatbot & Content Generation for WordPress / 3.2.24
MxChat – AI Chatbot & Content Generation for WordPress v3.2.24
3.2.25 3.2.24 3.2.23 3.2.22 3.2.21 3.2.20 3.2.19 3.2.18 3.2.17 3.2.16 3.2.15 3.2.14 3.2.12 3.2.13 3.2.11 3.2.10 3.2.9 3.2.8 3.2.7 3.2.6 3.2.5 3.2.4 3.2.3 3.2.2 3.2.1 All 156 releases
mxchat-basic / includes / class-mxchat-user.php

class-mxchat-user.php in MxChat – AI Chatbot & Content Generation for WordPress 3.2.24, at includes/class-mxchat-user.php

126 lines 5.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if (!defined('ABSPATH')) {
3 exit; // Exit if accessed directly
4 }
5
6 class MxChat_User {
7
8 // Function to get user identifier (username, email, or session ID)
9 public static function mxchat_get_user_identifier() {
10 if (is_user_logged_in()) {
11 $current_user = wp_get_current_user();
12 //error_log('Current User: ' . print_r($current_user, true));
13 return $current_user->user_login; // Use username as identifier
14 } else {
15 //error_log('User is not logged in. Using IP as identifier.');
16 // Same resolver the rate limiter keys on, so the transcript
17 // identifier and the rate-limit counter name the same address.
18 return self::mxchat_get_client_ip();
19 }
20 }
21
22 // Function to get user email
23 public static function mxchat_get_user_email() {
24 if (is_user_logged_in()) {
25 $current_user = wp_get_current_user();
26 return $current_user->user_email;
27 }
28 return null; // No email if not logged in
29 }
30
31 /**
32 * The visitor's address, from a source the visitor cannot choose.
33 *
34 * REMOTE_ADDR is the answer. Client-IP and X-Forwarded-For are set by
35 * whoever sends the request, so a counter keyed on them can be reset
36 * with a header. The one exception is Cloudflare: when the connection
37 * really comes from a Cloudflare edge (REMOTE_ADDR inside the ranges
38 * Cloudflare publishes), CF-Connecting-IP is the visitor. Hosts behind
39 * some other proxy can supply their own resolver with the
40 * `mxchat_client_ip` filter; whatever comes back must still be a valid
41 * address or REMOTE_ADDR is used.
42 *
43 * @return string A validated IP address, or 'unknown' when there is none.
44 */
45 public static function mxchat_get_client_ip() {
46 $remote = isset($_SERVER['REMOTE_ADDR']) ? trim((string) wp_unslash($_SERVER['REMOTE_ADDR'])) : '';
47 $remote = filter_var($remote, FILTER_VALIDATE_IP) ? $remote : '';
48
49 $ip = $remote;
50 if ($remote !== '' && !empty($_SERVER['HTTP_CF_CONNECTING_IP']) && self::mxchat_ip_is_cloudflare($remote)) {
51 $candidate = trim((string) wp_unslash($_SERVER['HTTP_CF_CONNECTING_IP']));
52 if (filter_var($candidate, FILTER_VALIDATE_IP)) {
53 $ip = $candidate;
54 }
55 }
56
57 /**
58 * Override the resolved visitor address, e.g. for a host behind a
59 * trusted proxy that is not Cloudflare. Return a valid IP.
60 *
61 * @param string $ip The address MxChat resolved.
62 * @param string $remote REMOTE_ADDR as received (validated, may be '').
63 */
64 $filtered = apply_filters('mxchat_client_ip', $ip, $remote);
65 if (is_string($filtered) && filter_var(trim($filtered), FILTER_VALIDATE_IP)) {
66 $ip = trim($filtered);
67 }
68
69 return $ip !== '' ? $ip : 'unknown';
70 }
71
72 /**
73 * Cloudflare's published edge ranges (cloudflare.com/ips-v4, /ips-v6),
74 * as of 2026-09-16. Refresh with the plugin.
75 */
76 public static function mxchat_cloudflare_ranges() {
77 return array(
78 '173.245.48.0/20', '103.21.244.0/22', '103.22.200.0/22', '103.31.4.0/22',
79 '141.101.64.0/18', '108.162.192.0/18', '190.93.240.0/20', '188.114.96.0/20',
80 '197.234.240.0/22', '198.41.128.0/17', '162.158.0.0/15', '104.16.0.0/13',
81 '104.24.0.0/14', '172.64.0.0/13', '131.0.72.0/22',
82 '2400:cb00::/32', '2606:4700::/32', '2803:f800::/32', '2405:b500::/32',
83 '2405:8100::/32', '2a06:98c0::/29', '2c0f:f248::/32',
84 );
85 }
86
87 public static function mxchat_ip_is_cloudflare($ip) {
88 foreach (self::mxchat_cloudflare_ranges() as $cidr) {
89 if (self::mxchat_ip_in_cidr($ip, $cidr)) {
90 return true;
91 }
92 }
93 return false;
94 }
95
96 /**
97 * Does $ip fall inside $cidr? Works for IPv4 and IPv6; families must match.
98 */
99 public static function mxchat_ip_in_cidr($ip, $cidr) {
100 if (strpos($cidr, '/') === false) {
101 return false;
102 }
103 list($subnet, $bits) = explode('/', $cidr, 2);
104 $ip_bin = @inet_pton($ip);
105 $subnet_bin = @inet_pton($subnet);
106 if ($ip_bin === false || $subnet_bin === false || strlen($ip_bin) !== strlen($subnet_bin)) {
107 return false;
108 }
109 $bits = (int) $bits;
110 $max = strlen($ip_bin) * 8;
111 if ($bits < 0 || $bits > $max) {
112 return false;
113 }
114 $full_bytes = intdiv($bits, 8);
115 if ($full_bytes > 0 && substr($ip_bin, 0, $full_bytes) !== substr($subnet_bin, 0, $full_bytes)) {
116 return false;
117 }
118 $rest = $bits % 8;
119 if ($rest === 0) {
120 return true;
121 }
122 $mask = (0xFF << (8 - $rest)) & 0xFF;
123 return ((ord($ip_bin[$full_bytes]) & $mask) === (ord($subnet_bin[$full_bytes]) & $mask));
124 }
125 }
126