PluginProbe ʕ •ᴥ•ʔ
AI Engine – The Chatbot, AI Framework & MCP for WordPress / 2.9.5
AI Engine – The Chatbot, AI Framework & MCP for WordPress v2.9.5
3.5.7 3.5.6 3.5.5 3.5.4 3.5.3 3.5.2 3.5.1 3.5.0 3.4.9 3.4.8 3.4.7 0.2.1 1.6.91 0.2.2 1.6.92 0.2.3 1.6.93 0.2.4 1.6.94 0.2.5 1.6.95 0.2.6 1.6.96 0.2.7 1.6.97 0.2.8 1.6.98 0.2.9 1.6.99 0.3.0 1.7.0 0.3.1 1.7.1 0.3.2 1.7.2 0.3.3 1.7.3 0.3.4 1.7.4 0.3.5 1.7.5 0.3.6 1.7.6 0.4.0 1.7.7 0.4.1 1.7.8 0.4.2 1.7.9 0.4.3 1.8.0 0.4.4 1.8.1 0.4.5 1.8.2 0.4.6 1.8.3 0.4.7 1.8.4 0.4.8 1.8.5 0.4.9 1.8.6 0.5.0 1.8.7 0.5.1 1.8.8 0.5.2 1.8.9 0.5.3 1.9.0 0.5.4 1.9.1 0.5.5 1.9.2 0.5.6 1.9.3 0.5.7 1.9.4 0.5.8 1.9.5 0.5.9 1.9.6 0.6.0 1.9.7 0.6.1 1.9.8 0.6.2 1.9.81 0.6.3 1.9.82 0.6.4 1.9.83 0.6.5 1.9.84 0.6.6 1.9.85 0.6.7 1.9.86 0.6.8 1.9.87 0.6.9 1.9.88 0.7.0 1.9.89 0.7.1 1.9.90 0.7.2 1.9.91 0.7.3 1.9.92 0.7.4 1.9.93 0.7.5 1.9.94 0.7.6 1.9.95 0.7.7 1.9.96 0.7.8 1.9.97 0.7.9 1.9.98 0.8.0 1.9.99 0.8.1 2.0.0 0.8.2 2.0.1 0.8.3 2.0.2 0.8.4 2.0.3 0.8.5 2.0.4 0.8.6 2.0.5 0.8.7 2.0.6 0.8.8 2.0.7 0.8.9 2.0.8 0.9.0 2.0.9 0.9.2 2.1.0 0.9.3 2.1.1 0.9.4 2.1.2 0.9.5 2.1.3 0.9.6 2.1.4 0.9.7 2.1.5 0.9.8 2.1.6 0.9.81 2.1.7 0.9.82 2.1.8 0.9.83 2.1.9 0.9.84 2.2.0 0.9.85 2.2.1 0.9.86 2.2.2 0.9.87 2.2.3 0.9.88 2.2.4 0.9.89 2.2.5 0.9.9 2.2.51 0.9.91 2.2.52 0.9.92 2.2.53 0.9.93 2.2.54 0.9.94 2.2.56 0.9.95 2.2.57 0.9.96 2.2.6 0.9.97 2.2.60 0.9.98 2.2.61 0.9.99 2.2.62 1.0.0 2.2.63 1.0.01 2.2.70 1.0.1 2.2.80 1.0.2 2.2.81 1.0.3 2.2.90 1.0.4 2.2.91 1.0.5 2.2.92 1.0.6 2.2.93 1.0.7 2.2.94 1.0.8 2.2.95 1.0.9 2.3.0 1.1.0 2.3.1 1.1.1 2.3.2 1.1.2 2.3.3 1.1.3 2.3.4 1.1.4 2.3.5 1.1.5 2.3.6 1.1.6 2.3.7 1.1.7 2.3.8 1.1.8 2.3.9 1.1.9 2.4.0 1.2.0 2.4.1 1.2.1 2.4.2 1.2.2 2.4.3 1.2.21 2.4.4 1.2.3 2.4.5 1.2.30 2.4.6 1.3.0 2.4.7 1.3.1 2.4.8 1.3.2 2.4.9 1.3.3 2.5.0 1.3.31 2.5.1 1.3.32 2.5.2 1.3.33 2.5.3 1.3.34 2.5.4 1.3.35 2.5.5 1.3.36 2.5.6 1.3.37 2.5.7 1.3.38 2.5.8 1.3.39 2.5.9 1.3.40 2.6.0 1.3.41 2.6.1 1.3.42 2.6.2 1.3.43 2.6.3 1.3.44 2.6.5 1.3.45 2.6.6 1.3.46 2.6.7 1.3.47 2.6.8 1.3.48 2.6.9 1.3.49 2.7.0 1.3.50 2.7.1 1.3.51 2.7.2 1.3.52 2.7.3 1.3.53 2.7.4 1.3.54 2.7.5 1.3.56 2.7.6 1.3.57 2.7.7 1.3.58 2.7.8 1.3.59 2.7.9 1.3.60 2.8.0 1.3.61 2.8.1 1.3.62 2.8.2 1.3.63 2.8.3 1.3.64 2.8.4 1.3.65 2.8.5 1.3.66 2.8.6 1.3.67 2.8.7 1.3.68 2.8.8 1.3.69 2.8.9 1.3.70 2.9.0 1.3.71 2.9.1 1.3.72 2.9.2 1.3.73 2.9.3 1.3.74 2.9.4 1.3.75 2.9.5 1.3.76 2.9.6 1.3.77 2.9.7 1.3.78 2.9.8 1.3.79 2.9.9 1.3.80 3.0.0 1.3.81 3.0.1 1.3.82 3.0.2 1.3.83 3.0.3 1.3.84 3.0.4 1.3.85 3.0.5 1.3.86 3.0.6 1.3.87 3.0.7 1.3.88 3.0.8 1.3.89 3.0.9 1.3.90 3.1.0 1.3.91 3.1.1 1.3.92 3.1.2 1.3.93 3.1.3 1.3.94 3.1.4 1.3.95 3.1.5 1.3.96 3.1.6 1.3.97 3.1.7 1.3.98 3.1.8 1.3.99 3.1.9 1.4.0 3.2.0 1.4.1 3.2.1 1.4.2 3.2.2 1.4.3 3.2.3 1.4.4 3.2.4 1.4.5 3.2.5 1.4.6 3.2.6 1.4.7 3.2.7 1.4.8 3.2.8 1.4.9 3.2.9 1.5.0 3.3.0 1.5.1 3.3.1 1.5.2 3.3.2 1.5.3 3.3.3 1.5.4 3.3.4 1.5.5 3.3.5 1.5.6 3.3.6 1.5.7 3.3.7 1.5.8 3.3.8 1.5.9 3.3.9 1.6.0 3.4.0 1.6.1 3.4.1 1.6.2 3.4.2 1.6.3 3.4.3 1.6.5 3.4.4 1.6.51 3.4.5 1.6.52 3.4.6 1.6.53 1.6.54 1.6.55 1.6.56 1.6.57 1.6.58 1.6.59 1.6.60 1.6.61 1.6.62 1.6.63 1.6.64 1.6.65 1.6.66 1.6.67 1.6.68 trunk 1.6.69 0.0.1 1.6.70 0.0.2 1.6.71 0.0.3 1.6.72 0.0.4 1.6.73 0.0.5 1.6.74 0.0.6 1.6.75 0.0.7 1.6.76 0.0.8 1.6.77 0.0.9 1.6.78 0.1.0 1.6.79 0.1.1 1.6.81 0.1.2 1.6.82 0.1.3 1.6.83 0.1.4 1.6.84 0.1.5 1.6.85 0.1.6 1.6.86 0.1.7 1.6.87 0.1.8 1.6.88 0.1.9 1.6.89 0.2.0 1.6.90
ai-engine / classes / services / session.php
ai-engine / classes / services Last commit date
image.php 11 months ago message-builder.php 11 months ago model-environment.php 11 months ago response-id-manager.php 11 months ago session.php 11 months ago usage-stats.php 11 months ago
session.php
176 lines
1 <?php
2
3 class Meow_MWAI_Services_Session {
4 private $core;
5 private $nonce = null;
6
7 public function __construct( $core ) {
8 $this->core = $core;
9 }
10
11 public function can_start_session() {
12 // Check if session already started
13 if ( session_status() !== PHP_SESSION_NONE ) {
14 return false;
15 }
16
17 // Check if we're in a context where sessions shouldn't be started
18 if ( wp_doing_cron() || defined( 'DOING_AUTOSAVE' ) ) {
19 return false;
20 }
21
22 // For AI Engine REST endpoints only - check if it's actually our endpoint
23 if ( $this->core->is_rest ) {
24 $request_uri = $_SERVER['REQUEST_URI'] ?? '';
25 // Only start sessions for actual AI Engine endpoints
26 if ( strpos( $request_uri, '/mwai/' ) === false && strpos( $request_uri, 'rest_route=/mwai/' ) === false ) {
27 return false;
28 }
29 }
30
31 // Allow developers to override
32 return apply_filters( 'mwai_allow_session', true );
33 }
34
35 public function get_nonce( $force = false ) {
36 // NONCE GENERATION LOGIC:
37 // - For logged-out users (unless forced): Return null - they must use /start_session endpoint
38 // - For logged-in users: Create user-specific nonce tied to their WP session
39 // - With $force=true: Always create nonce (used by /start_session endpoint)
40 //
41 // This ensures logged-in users get a nonce matching their auth context on page load,
42 // preventing rest_cookie_invalid_nonce errors when cookies are present.
43 if ( !$force && !is_user_logged_in() ) {
44 return null;
45 }
46 if ( isset( $this->nonce ) ) {
47 return $this->nonce;
48 }
49 $this->nonce = wp_create_nonce( 'wp_rest' );
50 return $this->nonce;
51 }
52
53 // ChatID
54 public function fix_chat_id( $query, $params ) {
55 if ( isset( $query->chatId ) && $query->chatId !== 'N/A' ) {
56 return $query->chatId;
57 }
58 $chatId = isset( $params['chatId'] ) ? $params['chatId'] : $query->session;
59 if ( $chatId === 'N/A' ) {
60 $chatId = $this->core->get_random_id( 8 );
61 }
62 $query->set_chat_id( $chatId );
63 return $chatId;
64 }
65
66 public function get_session_id() {
67 // Check if we have the session cookie
68 if ( isset( $_COOKIE['mwai_session_id'] ) ) {
69 return $_COOKIE['mwai_session_id'];
70 }
71
72 // If no cookie exists and we can set one, create it now (lazy initialization)
73 if ( !headers_sent() && !wp_doing_cron() ) {
74 $sessionId = uniqid();
75 @setcookie( 'mwai_session_id', $sessionId, [
76 'expires' => 0,
77 'path' => '/',
78 'secure' => is_ssl(),
79 'httponly' => true,
80 ] );
81 return $sessionId;
82 }
83
84 // For cron jobs or when headers are sent, return a temporary session ID
85 return wp_doing_cron() ? 'wp-cron' : 'N/A';
86 }
87
88 public function get_ip_address( $force = false ) {
89 // Get the actual IP address
90 $ip_keys = [ 'HTTP_CF_CONNECTING_IP', 'HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR',
91 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_X_REAL_IP', 'HTTP_FORWARDED_FOR',
92 'HTTP_FORWARDED', 'REMOTE_ADDR' ];
93 $actual_ip = null;
94 foreach ( $ip_keys as $key ) {
95 if ( array_key_exists( $key, $_SERVER ) === true ) {
96 $ips = explode( ',', $_SERVER[$key] );
97 foreach ( $ips as $ip ) {
98 $ip = trim( $ip );
99 if ( $this->validate_ip( $ip ) ) {
100 $actual_ip = $ip;
101 break 2;
102 }
103 }
104 }
105 }
106 if ( !$actual_ip ) {
107 $actual_ip = isset( $_SERVER['REMOTE_ADDR'] ) ? $_SERVER['REMOTE_ADDR'] : '127.0.0.1';
108 }
109
110 // If privacy_first is enabled and not forced, return hashed IP
111 if ( !$force && $this->core->get_option( 'privacy_first' ) ) {
112 // Use a salt that's unique per site but consistent
113 $salt = wp_salt( 'auth' );
114 // Create a hash that's consistent for the same IP but anonymized
115 return 'hashed_' . substr( hash( 'sha256', $actual_ip . $salt ), 0, 16 );
116 }
117
118 return $actual_ip;
119 }
120
121 public function get_user_data() {
122 $user = wp_get_current_user();
123 if ( empty( $user ) || empty( $user->ID ) ) {
124 return null;
125 }
126
127 // Return both the new format (for frontend) and placeholder format (for do_placeholders)
128 $userData = [
129 'ID' => $user->ID,
130 'name' => $user->display_name,
131 'email' => $user->user_email,
132 'avatar' => get_avatar_url( $user->ID ),
133 'type' => 'logged-in',
134 // Add placeholder keys for do_placeholders function
135 'FIRST_NAME' => get_user_meta( $user->ID, 'first_name', true ),
136 'LAST_NAME' => get_user_meta( $user->ID, 'last_name', true ),
137 'USER_LOGIN' => isset( $user->data ) && isset( $user->data->user_login ) ?
138 $user->data->user_login : null,
139 'DISPLAY_NAME' => isset( $user->data ) && isset( $user->data->display_name ) ?
140 $user->data->display_name : null,
141 'AVATAR_URL' => get_avatar_url( $user->ID ),
142 ];
143
144 return $userData;
145 }
146
147 public function get_user_id() {
148 // This function has to be re-thinked for all other API endpoints
149 $userId = null;
150 // If there is a current session, we probably know the current user
151 if ( is_user_logged_in() ) {
152 $userId = get_current_user_id();
153 }
154 // For guest users, return null instead of generating a string ID
155 // This allows the database to store NULL for guests, which displays as "Guest" in the UI
156 return $userId;
157 }
158
159 public function get_admin_user() {
160 $users = get_users( [ 'role' => 'administrator' ] );
161 if ( !empty( $users ) ) {
162 return $users[0];
163 }
164 return null;
165 }
166
167 // Private helper methods
168 private function validate_ip( $ip ) {
169 if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE ) === false ) {
170 return false;
171 }
172 return true;
173 }
174
175 }
176