register_scripts(); wp_enqueue_style( 'wooccm-checkout-css' ); wp_enqueue_style( 'dashicons' ); wp_enqueue_script( 'wooccm-frontend-js' ); } } public function admin_scripts() { $screen = get_current_screen(); if ( is_admin() && $screen ) { if ( in_array( $screen->id, array( /* 'product', 'edit-product', */'shop_order', 'edit-shop_order', 'woocommerce_page_wc-orders' ) ) ) { Plugin::instance()->register_scripts(); wp_enqueue_script( 'wooccm-frontend-js' ); } } } public function ajax_order_attachment_upload() { // Security Fix: CVE-2025-13965 - Added order key validation for guest orders // Step 1: Verify nonce for CSRF protection if ( ! check_admin_referer( 'wooccm_upload', 'nonce' ) ) { wp_send_json_error( array( 'message' => esc_html__( 'Security check failed.', 'woocommerce-checkout-manager' ) ) ); } if ( empty( $_REQUEST ) ) { wp_send_json_error( array( 'message' => esc_html__( 'Invalid request.', 'woocommerce-checkout-manager' ) ) ); } // Step 2: Validate order ID $order_id = ( isset( $_REQUEST['order_id'] ) ? absint( $_REQUEST['order_id'] ) : false ); if ( empty( $order_id ) ) { wp_send_json_error( array( 'message' => esc_html__( 'Empty order id.', 'woocommerce-checkout-manager' ) ) ); } $order = wc_get_order( $order_id ); if ( ! $order ) { wp_send_json_error( array( 'message' => esc_html__( 'Invalid order.', 'woocommerce-checkout-manager' ) ) ); } // Step 3: Authorization check - distinguish between logged-in users and guests $current_user = wp_get_current_user(); $is_user_logged = 0 !== $current_user->ID; if ( ! $is_user_logged ) { // GUEST ORDER VALIDATION // CRITICAL: Add order key validation for guests (CVE-2025-13965 fix) // The order key is the secret token in URLs like /view-order/123/?key=wc_order_ABC123xyz // This prevents attackers from uploading files to arbitrary guest orders $order_key = isset( $_REQUEST['order_key'] ) ? wc_clean( wp_unslash( $_REQUEST['order_key'] ) ) : ''; if ( empty( $order_key ) ) { wp_send_json_error( array( 'message' => esc_html__( 'Order key is required for guest orders.', 'woocommerce-checkout-manager' ) ) ); } // Validate order key matches using timing-safe comparison if ( ! hash_equals( $order->get_order_key(), $order_key ) ) { wp_send_json_error( array( 'message' => esc_html__( 'Invalid order key.', 'woocommerce-checkout-manager' ) ) ); } // Defense in depth: Also verify session email matches (additional security layer) $session_handler = WC()->session; if ( $session_handler && ! empty( $session_handler->get( 'customer' )['email'] ) ) { $order_email = $order->get_billing_email(); $session_customer_email = $session_handler->get( 'customer' )['email']; if ( $order_email !== $session_customer_email ) { wp_send_json_error( array( 'message' => esc_html__( 'Email verification failed.', 'woocommerce-checkout-manager' ) ) ); } } } else { // LOGGED-IN USER VALIDATION $order_user_id = $order->get_user_id(); // Check if user has admin/shop manager capabilities $user_has_capabilities = current_user_can( 'administrator' ) || current_user_can( 'edit_others_shop_orders' ) || current_user_can( 'delete_others_shop_orders' ); // Check if the logged-in user owns this order $is_current_user_order_equal_user_id = $current_user->ID === $order_user_id; if ( ! $user_has_capabilities && ! $is_current_user_order_equal_user_id ) { wp_send_json_error( array( 'message' => esc_html__( 'This is not your order.', 'woocommerce-checkout-manager' ) ) ); } } // Step 4: Validate files are present // It cannot be wp_unslash becouse it has images paths. // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash $files = isset( $_FILES['wooccm_order_attachment_upload'] ) ? wc_clean( $_FILES['wooccm_order_attachment_upload'] ) : false; if ( empty( $files ) ) { wp_send_json_error( array( 'message' => esc_html__( 'No uploads were recognized. Files were not uploaded.', 'woocommerce-checkout-manager' ) ) ); } $post = get_post( $order_id ); if ( ! $post ) { wp_send_json_error( array( 'message' => esc_html__( 'Invalid order id.', 'woocommerce-checkout-manager' ) ) ); } // Step 5: Process file uploads $attachment_ids = $this->process_uploads( $files, 'wooccm_order_attachment_upload', $order_id ); if ( count( $attachment_ids ) ) { ob_start(); if ( ! empty( $_REQUEST['metabox'] ) ) { $this->add_metabox_content( $post ); } else { $this->add_upload_files( $post->ID ); } wp_send_json_success( ob_get_clean() ); } wp_send_json_error( array( 'message' => esc_html__( 'Unknown error.', 'woocommerce-checkout-manager' ) ) ); } public function add_upload_files( $order_id ) { if ( get_option( 'wooccm_order_upload_files', 'no' ) === 'yes' ) { $order = wc_get_order( $order_id ); if ( $order ) { if ( in_array( "wc-{$order->get_status()}", array_values( get_option( 'wooccm_order_upload_files_order_status', array() ) ) ) ) { $attachments = get_posts( array( 'fields' => 'ids', 'post_type' => 'attachment', 'numberposts' => -1, 'post_status' => null, 'post_parent' => $order->get_id(), ) ); wc_get_template( 'templates/order/order-upload-files.php', array( 'order' => $order, 'attachments' => $attachments, ), '', WOOCCM_PLUGIN_DIR ); } } } } public function add_custom_fields( $order_id ) { if ( get_option( 'wooccm_order_custom_fields', 'yes' ) === 'yes' ) { $order = wc_get_order( $order_id ); if ( $order ) { if ( in_array( "wc-{$order->get_status()}", array_values( get_option( 'wooccm_order_custom_fields_status', array_keys( wc_get_order_statuses() ) ) ) ) ) { wc_get_template( 'templates/order/order-custom-fields.php', array( 'order' => $order ), '', WOOCCM_PLUGIN_DIR ); } } } } public function add_metabox_content( $post ) { $order = null; if ( method_exists( $post, 'get_id' ) ) { $order = wc_get_order( $post->get_id() ); } else { $order = wc_get_order( $post->ID ); } if ( $order ) { $attachments = get_posts( array( 'fields' => 'ids', 'post_type' => 'attachment', 'numberposts' => -1, 'post_status' => null, 'post_parent' => $order->get_id(), ) ); include WOOCCM_PLUGIN_DIR . 'lib/view/backend/meta-boxes/html-order-uploads.php'; } } // Admin // ------------------------------------------------------------------------- public function add_metabox() { add_meta_box( 'wooccm-order-files', esc_html__( 'Order Files', 'woocommerce-checkout-manager' ), array( $this, 'add_metabox_content' ), 'shop_order', 'normal', 'default' ); } public function add_metabox_woocommerce_page_wc_orders() { add_meta_box( 'wooccm-order-files', esc_html__( 'Order Files', 'woocommerce-checkout-manager' ), array( $this, 'add_metabox_content' ), 'woocommerce_page_wc-orders', 'normal', 'default' ); } // Panel // --------------------------------------------------------------------------- public function get_settings() { return array( array( 'type' => 'title', 'id' => 'section_title', ), array( 'name' => esc_html__( 'Add upload files', 'woocommerce-checkout-manager' ), 'desc_tip' => esc_html__( 'Allow customers to upload files in the order.', 'woocommerce-checkout-manager' ), 'id' => 'wooccm_order_upload_files', 'type' => 'select', 'class' => 'chosen_select', 'options' => array( 'yes' => esc_html__( 'Yes', 'woocommerce-checkout-manager' ), 'no' => esc_html__( 'No', 'woocommerce-checkout-manager' ), ), 'default' => 'no', ), array( 'name' => esc_html__( 'Add for this order status', 'woocommerce-checkout-manager' ), 'desc_tip' => esc_html__( 'Allow customers to upload files in the order.', 'woocommerce-checkout-manager' ), 'id' => 'wooccm_order_upload_files_order_status', 'type' => 'multiselect', 'class' => 'chosen_select', 'options' => wc_get_order_statuses(), 'default' => array_keys( wc_get_order_statuses() ), ), array( 'name' => esc_html__( 'Add upload files title', 'woocommerce-checkout-manager' ), 'desc_tip' => esc_html__( 'Add custom title for the uploads files table.', 'woocommerce-checkout-manager' ), 'id' => 'wooccm_order_upload_files_title', 'type' => 'text', 'placeholder' => esc_html__( 'Uploaded files', 'woocommerce-checkout-manager' ), ), array( 'name' => esc_html__( 'Add custom fields', 'woocommerce-checkout-manager' ), 'desc_tip' => esc_html__( 'Show the selected fields in the order.', 'woocommerce-checkout-manager' ), 'id' => 'wooccm_order_custom_fields', 'type' => 'select', 'class' => 'chosen_select', 'options' => array( 'yes' => esc_html__( 'Yes', 'woocommerce-checkout-manager' ), 'no' => esc_html__( 'No', 'woocommerce-checkout-manager' ), ), 'default' => 'yes', ), array( 'name' => esc_html__( 'Add for this order status', 'woocommerce-checkout-manager' ), 'desc_tip' => esc_html__( 'Allow customers to upload files in the order.', 'woocommerce-checkout-manager' ), 'id' => 'wooccm_order_custom_fields_status', 'type' => 'multiselect', 'class' => 'chosen_select', 'options' => wc_get_order_statuses(), 'default' => array_keys( wc_get_order_statuses() ), ), array( 'name' => esc_html__( 'Add custom fields title', 'woocommerce-checkout-manager' ), 'desc_tip' => esc_html__( 'Add custom title for the uploads files table.', 'woocommerce-checkout-manager' ), 'id' => 'wooccm_order_custom_fields_title', 'type' => 'text', 'placeholder' => esc_html__( 'Order extra', 'woocommerce-checkout-manager' ), ), array( 'type' => 'sectionend', 'id' => 'section_end', ), ); } public function add_header() { global $current_section; ?>