<?php
defined( 'ABSPATH' ) || exit;

/**
 * Path safety helpers.
 *
 * Why: every converter writes to a destination path derived from a source path.
 * Both paths must be inside the WP uploads basedir, must not contain shell
 * metacharacters or null bytes, and must resolve under the basedir after
 * realpath() to defeat traversal. We refuse anything else.
 */

function bw_webp_uploads_basedir(): string {
	$dirs = wp_get_upload_dir();
	$base = isset( $dirs['basedir'] ) ? (string) $dirs['basedir'] : '';
	$base = rtrim( $base, "/\\" );
	return '' === $base ? '' : $base;
}

function bw_webp_is_safe_path( string $path ): bool {
	if ( '' === $path ) {
		return false;
	}
	if ( false !== strpos( $path, "\0" ) ) {
		return false;
	}
	$base = bw_webp_uploads_basedir();
	if ( '' === $base ) {
		return false;
	}

	// For source we expect the file to exist; for dest the parent must exist.
	$resolved = is_file( $path ) ? realpath( $path ) : realpath( dirname( $path ) );
	if ( false === $resolved ) {
		return false;
	}
	$base_real = realpath( $base );
	if ( false === $base_real ) {
		return false;
	}
	return 0 === strpos( $resolved, $base_real . DIRECTORY_SEPARATOR )
		|| $resolved === $base_real;
}

function bw_webp_assert_safe_paths( string $src, string $dest ): void {
	if ( ! bw_webp_is_safe_path( $src ) ) {
		throw new RuntimeException( 'BW WebP: refused unsafe source path' );
	}
	if ( ! bw_webp_is_safe_path( $dest ) ) {
		throw new RuntimeException( 'BW WebP: refused unsafe destination path' );
	}
}
