| @@ -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 | } |