PluginProbe ʕ •ᴥ•ʔ
AI Engine – The Chatbot, AI Framework & MCP for WordPress / 1.9.99
AI Engine – The Chatbot, AI Framework & MCP for WordPress v1.9.99
3.5.8 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 / modules / files.php
ai-engine / classes / modules Last commit date
assistants.php 3 years ago chatbot.php 2 years ago chatbot_legacy.php 2 years ago discussions.php 2 years ago files.php 2 years ago security.php 3 years ago
files.php
256 lines
1 <?php
2
3 class Meow_MWAI_Modules_Files {
4 private $core = null;
5 private $wpdb = null;
6 private $namespace = 'mwai-ui/v1';
7 private $db_check = false;
8 private $table_files = null;
9
10 public function __construct( $core ) {
11 global $wpdb;
12 $this->core = $core;
13 $this->wpdb = $wpdb;
14 $this->table_files = $this->wpdb->prefix . 'mwai_files';
15 add_action( 'rest_api_init', [ $this, 'rest_api_init' ] );
16 if ( !wp_next_scheduled( 'mwai_files_cleanup' ) ) {
17 wp_schedule_event( time(), 'hourly', 'mwai_files_cleanup' );
18 }
19 add_action( 'mwai_files_cleanup', [ $this, 'cleanup_expired_files' ] );
20 }
21
22 public function cleanup_expired_files() {
23 if ( $this->check_db() ) {
24 $current_time = current_time( 'mysql' );
25 $expired_files = $this->wpdb->get_results(
26 "SELECT * FROM $this->table_files WHERE expires IS NOT NULL AND expires < '{$current_time}'"
27 );
28 }
29 $expired_posts = get_posts( [
30 'post_type' => 'attachment',
31 'meta_key' => '_mwai_file_expires',
32 'meta_value' => $current_time,
33 'meta_compare' => '<'
34 ] );
35 $fileIds = [];
36 foreach ( $expired_files as $file ) {
37 $fileIds[] = $file->fileId;
38 }
39 foreach ( $expired_posts as $post ) {
40 $fileIds[] = get_post_meta( $post->ID, '_mwai_file_id', true );
41 }
42 $this->files_processed( $fileIds );
43 }
44
45 public function files_processed( $fileIds ) {
46 if ( !is_array( $fileIds ) ) {
47 $fileIds = [ $fileIds ];
48 }
49 foreach ( $fileIds as $fileId ) {
50 $file = null;
51 if ( $this->check_db() ) {
52 $file = $this->wpdb->get_row( $this->wpdb->prepare( "SELECT *
53 FROM $this->table_files
54 WHERE fileId = %s", $fileId
55 ) );
56 }
57 if ( $file ) {
58 $this->wpdb->delete( $this->table_files, [ 'fileId' => $fileId ] );
59 if ( file_exists( $file->path ) ) {
60 unlink( $file->path );
61 }
62 }
63 else {
64 $posts = get_posts( [ 'post_type' => 'attachment', 'meta_key' => '_mwai_file_id', 'meta_value' => $fileId ] );
65 if ( $posts ) {
66 foreach ( $posts as $post ) {
67 wp_delete_attachment( $post->ID, true );
68 }
69 }
70 }
71 }
72 }
73
74 public function get_path( $fileId ) {
75 $file = null;
76 if ( $this->check_db() ) {
77 $file = $this->wpdb->get_row( $this->wpdb->prepare( "SELECT *
78 FROM $this->table_files
79 WHERE fileId = %s", $fileId
80 ) );
81 }
82 if ( $file ) {
83 return $file->path;
84 }
85 else {
86 $posts = get_posts( [ 'post_type' => 'attachment', 'meta_key' => '_mwai_file_id', 'meta_value' => $fileId ] );
87 if ( $posts ) {
88 foreach ( $posts as $post ) {
89 return get_attached_file( $post->ID );
90 }
91 }
92 }
93 return null;
94 }
95
96 public function get_base64_data( $fileId ) {
97 $path = $this->get_path( $fileId );
98 if ( $path ) {
99 $content = file_get_contents( $path );
100 $data = base64_encode( $content );
101 return $data;
102 }
103 return null;
104 }
105
106 public function get_url( $fileId ) {
107 $file = null;
108 if ( $this->check_db() ) {
109 $file = $this->wpdb->get_row( $this->wpdb->prepare( "SELECT *
110 FROM $this->table_files
111 WHERE fileId = %s", $fileId
112 ) );
113 }
114 if ( $file ) {
115 return $file->url;
116 }
117 else {
118 $posts = get_posts( [ 'post_type' => 'attachment', 'meta_key' => '_mwai_file_id', 'meta_value' => $fileId ] );
119 if ( $posts ) {
120 foreach ( $posts as $post ) {
121 return wp_get_attachment_url( $post->ID );
122 }
123 }
124 }
125 return null;
126 }
127
128 #region REST endpoints
129
130 public function check_permission( $request ) {
131 $nonce = $request->get_header( 'X-WP-Nonce' );
132 if ( !wp_verify_nonce( $nonce, 'wp_rest' ) ) {
133 return new WP_REST_Response( [ 'success' => false, 'message' => 'Invalid nonce.' ], 403 );
134 }
135 return true;
136 }
137
138 public function rest_api_init() {
139 register_rest_route( $this->namespace, '/files/upload', array(
140 'methods' => 'POST',
141 'callback' => array( $this, 'rest_upload' ),
142 'permission_callback' => array( $this, 'check_permission' )
143 ) );
144 register_rest_route( $this->namespace, '/files/delete', array(
145 'methods' => 'POST',
146 'callback' => array( $this, 'rest_delete' ),
147 'permission_callback' => array( $this, 'check_permission' )
148 ) );
149 }
150
151 public function rest_upload() {
152 require_once( ABSPATH . 'wp-admin/includes/image.php' );
153 require_once( ABSPATH . 'wp-admin/includes/file.php' );
154 require_once( ABSPATH . 'wp-admin/includes/media.php' );
155 $file = $_FILES['file'];
156 $error = null;
157 if ( empty( $file ) ) {
158 return new WP_REST_Response( [ 'success' => false, 'message' => 'No file provided.' ], 400 );
159 }
160
161 // File validation by WordPress Media Library
162 $fileTypeCheck = wp_check_filetype_and_ext( $file['tmp_name'], $file['name'] );
163 if ( !$fileTypeCheck['type'] ) {
164 return new WP_REST_Response( [ 'success' => false, 'message' => 'Invalid file type.' ], 400 );
165 }
166
167 $local_upload = $this->core->get_option( 'image_local_upload' );
168 $image_expires_seconds = $this->core->get_option( 'image_expires' );
169 $expires = ( empty( $image_expires_seconds ) || $image_expires_seconds === 'never' ) ? null :
170 date( 'Y-m-d H:i:s', time() + $image_expires_seconds );
171 $fileId = null;
172 $url = null;
173 if ( $local_upload === 'uploads' ) {
174 if ( !$this->check_db() ) {
175 return new WP_REST_Response( [ 'success' => false, 'message' => 'Could not create database table.' ], 500 );
176 }
177 $extension = pathinfo( $file['name'], PATHINFO_EXTENSION );
178 $randomFileName = wp_generate_password( 20, false ) . '.' . $extension;
179 $upload_dir = wp_upload_dir();
180 $path = $upload_dir['path'] . '/' . $randomFileName;
181 $filename = wp_unique_filename( $upload_dir['path'], $randomFileName );
182 $path = $upload_dir['path'] . '/' . $filename;
183 if ( !move_uploaded_file( $file['tmp_name'], $path ) ) {
184 return new WP_REST_Response( [ 'success' => false, 'message' => 'Could not move the file.' ], 500 );
185 }
186 $url = $upload_dir['url'] . '/' . $filename;
187 $fileId = md5( $url );
188 $this->wpdb->insert( $this->table_files, [
189 'fileId' => $fileId,
190 'type' => 'image',
191 'status' => 'uploaded',
192 'created' => date( 'Y-m-d H:i:s' ),
193 'updated' => date( 'Y-m-d H:i:s' ),
194 'expires' => $expires,
195 'path' => $path,
196 'url' => $url
197 ]);
198 }
199 else if ( $local_upload === 'library' ) {
200 $id = media_handle_upload( 'file', 0 );
201 if ( is_wp_error( $id ) ) {
202 $error = $id->get_error_message();
203 return new WP_REST_Response([ 'success' => false, 'message' => $error ], 500);
204 }
205 $url = wp_get_attachment_url( $id );
206 $fileId = md5( $url );
207 update_post_meta( $id, '_mwai_file_id', $fileId );
208 update_post_meta( $id, '_mwai_file_expires', $expires );
209 }
210 return new WP_REST_Response( [
211 'success' => true,
212 'data' => [ 'id' => $fileId, 'url' => $url ]
213 ], 200 );
214 }
215
216 #endregion
217
218 #region Database functions
219
220 function create_db() {
221 $charset_collate = $this->wpdb->get_charset_collate();
222 $sql = "CREATE TABLE $this->table_files (
223 id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
224 fileId VARCHAR(64) NOT NULL,
225 type VARCHAR(32) NULL,
226 status VARCHAR(32) NULL,
227 created DATETIME NOT NULL,
228 updated DATETIME NOT NULL,
229 expires DATETIME NULL,
230 path TEXT NOT NULL,
231 url TEXT NULL,
232 metadata TEXT NULL,
233 PRIMARY KEY (id),
234 UNIQUE KEY unique_file_id (fileId)
235 ) $charset_collate;";
236 require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
237 dbDelta( $sql );
238 }
239
240 function check_db() {
241 if ( $this->db_check ) {
242 return true;
243 }
244 $sql = $this->wpdb->prepare( "SHOW TABLES LIKE %s", $this->table_files );
245 $table_exists = strtolower( $this->wpdb->get_var( $sql )) === strtolower( $this->table_files );
246 if ( !$table_exists ) {
247 $this->create_db();
248 $table_exists = strtolower( $this->wpdb->get_var( $sql ) ) === strtolower( $this->table_files );
249 }
250 $this->db_check = $table_exists;
251 return $this->db_check;
252 }
253
254 #endregion
255
256 }