PluginProbe
MxChat – AI Chatbot & Content Generation for WordPress / 1.6.3
MxChat – AI Chatbot & Content Generation for WordPress v1.6.3
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 2.0.3 2.0.4 2.0.5 2.0.6 All 152 releases
← All changes | includes/class-mxchat-word-handler.php +25 -75 3.2.141.6.3 View file →
@@ -15,41 +15,19 @@
15 15 /**
16 16 * Handle Word document upload and processing
17 17 */
18 18 public function mxchat_handle_word_upload() {
19 - // Match the PDF handler's nonce verification: the widget sends the chat-send
20 - // nonce (action 'mxchat_chat_send'), which the old check_ajax_referer('mxchat_chat_nonce')
21 - // rejected with -1. mxchat_verify_chat_send_nonce accepts both chat-send and chat nonces.
22 - if (!isset($_POST['nonce']) || !MxChat_Integrator::mxchat_verify_chat_send_nonce(wp_unslash((string) $_POST['nonce']))) {
23 - wp_send_json_error(array('message' => esc_html__('Invalid nonce.', 'mxchat')), 403);
24 - }
19 + check_ajax_referer('mxchat_chat_nonce', 'nonce');
25 20
26 21 if (!isset($_FILES['word_file']) || !isset($_POST['session_id'])) {
27 - wp_send_json_error(esc_html__('Missing required parameters.', 'mxchat'));
22 + wp_send_json_error('Missing required parameters.');
28 23 return;
29 24 }
30 -
31 - // SECURITY FIX: Check if Word uploads are enabled in settings
32 - $options = get_option('mxchat_options', array());
33 - $show_word_button = isset($options['show_word_upload_button']) ? $options['show_word_upload_button'] : 'on';
34 -
35 - if ($show_word_button !== 'on') {
36 - wp_send_json_error(esc_html__('Word document uploads are currently disabled.', 'mxchat'));
37 - return;
38 - }
39 -
25 +
40 26 $file = $_FILES['word_file'];
41 27 $session_id = sanitize_text_field($_POST['session_id']);
42 28 $original_filename = sanitize_text_field($file['name']);
43 -
44 - // Update session owner if it changed (e.g. IP changed due to network switch)
45 - $current_user_identifier = MxChat_User::mxchat_get_user_identifier();
46 - $session_owner = get_option("mxchat_session_owner_{$session_id}");
47 29
48 - if (!$session_owner || $session_owner !== $current_user_identifier) {
49 - update_option("mxchat_session_owner_{$session_id}", $current_user_identifier, 'no');
50 - }
51 -
52 30 // Check file type
53 31 $allowed_types = array(
54 32 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
55 33 );
@@ -55,44 +33,43 @@
55 33 );
56 34 $file_type = wp_check_filetype($file['name'], $allowed_types);
57 35
58 36 if (!$file_type['type']) {
59 - wp_send_json_error(esc_html__('Invalid file type. Only .docx files are allowed.', 'mxchat'));
37 + wp_send_json_error('Invalid file type. Only .docx files are allowed.');
60 38 return;
61 39 }
62 -
63 - // SECURITY FIX: Generate random filename without exposing session_id
64 - $random_string = wp_generate_password(20, false, false); // 20 char alphanumeric string
65 - $word_filename = 'mxchat_word_' . $random_string . '_' . time() . '.docx';
40 +
41 + // Generate unique filename
42 + $word_filename = 'mxchat_word_' . $session_id . '_' . time() . '.docx';
66 43 $word_path = $this->temp_dir . '/' . $word_filename;
67 -
44 +
68 45 if (!move_uploaded_file($file['tmp_name'], $word_path)) {
69 - wp_send_json_error(esc_html__('Failed to upload file.', 'mxchat'));
46 + wp_send_json_error('Failed to upload file.');
70 47 return;
71 48 }
72 -
49 +
73 50 $this->mxchat_clear_word_transients($session_id);
74 -
51 +
75 52 // Process the document
76 53 $embeddings = $this->mxchat_process_word_document($word_path);
77 -
54 +
78 55 if ($embeddings === false || empty($embeddings)) {
79 56 unlink($word_path);
80 57 $error_message = $this->options['word_intent_error_text'] ??
81 - esc_html__('The uploaded document appears to be empty or contains unsupported content.', 'mxchat');
58 + 'The uploaded document appears to be empty or contains unsupported content.';
82 59 wp_send_json_error($error_message);
83 60 return;
84 61 }
85 -
86 - // Store the mapping between session and the random filename
62 +
63 + // Store the embeddings and file information
87 64 set_transient('mxchat_word_url_' . $session_id, $word_path, HOUR_IN_SECONDS);
88 65 set_transient('mxchat_word_filename_' . $session_id, $original_filename, HOUR_IN_SECONDS);
89 66 set_transient('mxchat_word_embeddings_' . $session_id, $embeddings, HOUR_IN_SECONDS);
90 67 set_transient('mxchat_include_word_in_context_' . $session_id, true, HOUR_IN_SECONDS);
91 -
68 +
92 69 $success_message = $this->options['pdf_intent_success_text'] ??
93 - __("I've processed the document. What questions do you have about it?", 'mxchat');
94 -
70 + "I've processed the document. What questions do you have about it?";
71 +
95 72 wp_send_json_success([
96 73 'message' => $success_message,
97 74 'filename' => $original_filename
98 75 ]);
@@ -126,9 +103,9 @@
126 103 $paragraphs = explode("\n\n", $text);
127 104 $estimated_pages = ceil(count($paragraphs) / 3); // Assume ~3 paragraphs per page
128 105
129 106 if ($estimated_pages > $max_pages) {
130 - return esc_html__('too_many_pages', 'mxchat');
107 + return 'too_many_pages';
131 108 }
132 109
133 110 // Split into chunks and continue processing...
134 111 $chunks = $this->mxchat_split_word_into_chunks($text, 1000);
@@ -139,9 +116,9 @@
139 116 continue;
140 117 }
141 118
142 119 $embedding = $this->mxchat_generate_embedding_word(
143 - esc_html__('Chunk ', 'mxchat') . ($chunk_number + 1) . ': ' . $chunk,
120 + "Chunk " . ($chunk_number + 1) . ": " . $chunk,
144 121 $this->options['api_key']
145 122 );
146 123
147 124 if ($embedding) {
@@ -208,13 +185,13 @@
208 185
209 186 /**
210 187 * Remove Word document and clean up transients
211 188 */
212 -public function mxchat_handle_word_remove() {
189 + public function mxchat_handle_word_remove() {
213 190 check_ajax_referer('mxchat_chat_nonce', 'nonce');
214 191
215 192 if (empty($_POST['session_id'])) {
216 - wp_send_json_error(esc_html__('Session ID missing.', 'mxchat'));
193 + wp_send_json_error('Session ID missing.');
217 194 return;
218 195 }
219 196
220 197 $session_id = sanitize_text_field($_POST['session_id']);
@@ -226,9 +203,9 @@
226 203
227 204 $this->mxchat_clear_word_transients($session_id);
228 205
229 206 wp_send_json_success([
230 - 'message' => esc_html__('Document removed successfully.', 'mxchat')
207 + 'message' => 'Document removed successfully.'
231 208 ]);
232 209 }
233 210
234 211 /**
@@ -272,9 +249,9 @@
272 249
273 250 /**
274 251 * Handle Word document discussion similar to PDF discussion
275 252 */
276 -public function mxchat_handle_word_discussion($message, $user_id, $session_id) {
253 + public function mxchat_handle_word_discussion($message, $user_id, $session_id) {
277 254 // Get stored embeddings for the session
278 255 $embeddings = get_transient('mxchat_word_embeddings_' . $session_id);
279 256 $word_path = get_transient('mxchat_word_url_' . $session_id);
280 257
@@ -279,9 +256,9 @@
279 256 $word_path = get_transient('mxchat_word_url_' . $session_id);
280 257
281 258 if (!$embeddings || !$word_path) {
282 259 $trigger_text = $this->options['word_intent_trigger_text'] ??
283 - __("Please upload a Word document (.docx) that you'd like to discuss.", 'mxchat');
260 + "Please upload a Word document (.docx) that you'd like to discuss.";
284 261 set_transient('mxchat_waiting_for_word_' . $session_id, true, HOUR_IN_SECONDS);
285 262 $this->fallbackResponse['text'] = $trigger_text;
286 263 return;
287 264 }
@@ -349,34 +326,7 @@
349 326 }
350 327
351 328 return $dotProduct / ($normA * $normB);
352 329 }
353 -
354 - /**
355 - * Check the status of a Word document for the current session
356 - */
357 -public function mxchat_check_word_status() {
358 - check_ajax_referer('mxchat_chat_nonce', 'nonce');
359 -
360 - if (empty($_POST['session_id'])) {
361 - wp_send_json_error(esc_html__('Session ID missing.', 'mxchat'));
362 - return;
363 - }
364 -
365 - $session_id = sanitize_text_field($_POST['session_id']);
366 - $word_path = get_transient('mxchat_word_url_' . $session_id);
367 - $filename = get_transient('mxchat_word_filename_' . $session_id);
368 -
369 - if ($word_path && file_exists($word_path) && $filename) {
370 - wp_send_json_success([
371 - 'has_word' => true,
372 - 'filename' => $filename
373 - ]);
374 - } else {
375 - wp_send_json_success([
376 - 'has_word' => false
377 - ]);
378 - }
379 -}
380 330
381 331
382 332 }