diff --git a/includes/Api/ProductsController.php b/includes/Api/ProductsController.php index 6c15f5d..3882452 100644 --- a/includes/Api/ProductsController.php +++ b/includes/Api/ProductsController.php @@ -20,6 +20,50 @@ use WC_Product_Variation; class ProductsController { + /** + * Sanitize text field + */ + private static function sanitize_text($value) { + if (!isset($value) || $value === '') { + return ''; + } + $sanitized = sanitize_text_field($value); + return trim($sanitized); + } + + /** + * Sanitize textarea (allows newlines) + */ + private static function sanitize_textarea($value) { + if (!isset($value) || $value === '') { + return ''; + } + $sanitized = sanitize_textarea_field($value); + return trim($sanitized); + } + + /** + * Sanitize numeric value + */ + private static function sanitize_number($value) { + if (!isset($value) || $value === '') { + return ''; + } + // Remove non-numeric except decimal point and minus + $sanitized = preg_replace('/[^0-9.-]/', '', $value); + return $sanitized !== '' ? $sanitized : ''; + } + + /** + * Sanitize slug + */ + private static function sanitize_slug($value) { + if (!isset($value) || $value === '') { + return ''; + } + return sanitize_title($value); + } + /** * Register REST API routes */ @@ -231,24 +275,24 @@ class ProductsController { $product = new WC_Product_Simple(); } - // Set basic data - $product->set_name($data['name']); + // Set basic data - sanitize all inputs + $product->set_name(self::sanitize_text($data['name'])); if (!empty($data['slug'])) { - $product->set_slug($data['slug']); + $product->set_slug(self::sanitize_slug($data['slug'])); } - $product->set_status($data['status'] ?? 'publish'); - $product->set_description($data['description'] ?? ''); - $product->set_short_description($data['short_description'] ?? ''); + $product->set_status(sanitize_key($data['status'] ?? 'publish')); + $product->set_description(self::sanitize_textarea($data['description'] ?? '')); + $product->set_short_description(self::sanitize_textarea($data['short_description'] ?? '')); if (!empty($data['sku'])) { - $product->set_sku($data['sku']); + $product->set_sku(self::sanitize_text($data['sku'])); } if (!empty($data['regular_price'])) { - $product->set_regular_price($data['regular_price']); + $product->set_regular_price(self::sanitize_number($data['regular_price'])); } if (!empty($data['sale_price'])) { - $product->set_sale_price($data['sale_price']); + $product->set_sale_price(self::sanitize_number($data['sale_price'])); } $product->set_manage_stock($data['manage_stock'] ?? false); @@ -258,18 +302,18 @@ class ProductsController { } $product->set_stock_status($data['stock_status'] ?? 'instock'); - // Optional fields + // Optional fields - sanitize dimensions if (!empty($data['weight'])) { - $product->set_weight($data['weight']); + $product->set_weight(self::sanitize_number($data['weight'])); } if (!empty($data['length'])) { - $product->set_length($data['length']); + $product->set_length(self::sanitize_number($data['length'])); } if (!empty($data['width'])) { - $product->set_width($data['width']); + $product->set_width(self::sanitize_number($data['width'])); } if (!empty($data['height'])) { - $product->set_height($data['height']); + $product->set_height(self::sanitize_number($data['height'])); } // Virtual and downloadable @@ -330,15 +374,15 @@ class ProductsController { return new WP_Error('product_not_found', __('Product not found', 'woonoow'), ['status' => 404]); } - // Update basic data - if (isset($data['name'])) $product->set_name($data['name']); - if (isset($data['slug'])) $product->set_slug($data['slug']); - if (isset($data['status'])) $product->set_status($data['status']); - if (isset($data['description'])) $product->set_description($data['description']); - if (isset($data['short_description'])) $product->set_short_description($data['short_description']); - if (isset($data['sku'])) $product->set_sku($data['sku']); - if (isset($data['regular_price'])) $product->set_regular_price($data['regular_price']); - if (isset($data['sale_price'])) $product->set_sale_price($data['sale_price']); + // Update basic data - sanitize all inputs + if (isset($data['name'])) $product->set_name(self::sanitize_text($data['name'])); + if (isset($data['slug'])) $product->set_slug(self::sanitize_slug($data['slug'])); + if (isset($data['status'])) $product->set_status(sanitize_key($data['status'])); + if (isset($data['description'])) $product->set_description(self::sanitize_textarea($data['description'])); + if (isset($data['short_description'])) $product->set_short_description(self::sanitize_textarea($data['short_description'])); + if (isset($data['sku'])) $product->set_sku(self::sanitize_text($data['sku'])); + if (isset($data['regular_price'])) $product->set_regular_price(self::sanitize_number($data['regular_price'])); + if (isset($data['sale_price'])) $product->set_sale_price(self::sanitize_number($data['sale_price'])); if (isset($data['manage_stock'])) { $product->set_manage_stock($data['manage_stock']); @@ -347,11 +391,11 @@ class ProductsController { } } - if (isset($data['stock_status'])) $product->set_stock_status($data['stock_status']); - if (isset($data['weight'])) $product->set_weight($data['weight']); - if (isset($data['length'])) $product->set_length($data['length']); - if (isset($data['width'])) $product->set_width($data['width']); - if (isset($data['height'])) $product->set_height($data['height']); + if (isset($data['stock_status'])) $product->set_stock_status(sanitize_key($data['stock_status'])); + if (isset($data['weight'])) $product->set_weight(self::sanitize_number($data['weight'])); + if (isset($data['length'])) $product->set_length(self::sanitize_number($data['length'])); + if (isset($data['width'])) $product->set_width(self::sanitize_number($data['width'])); + if (isset($data['height'])) $product->set_height(self::sanitize_number($data['height'])); // Categories if (isset($data['categories'])) {