Automattic\WooCommerce\Internal\Utilities

URL::process_path()privateWC 1.0

Simplifies the path if possible, by resolving directory traversals to the extent possible without touching the filesystem.

{} It's a method of the class: URL{}

No Hooks.

Return

null. Nothing.

Usage

// private - for code of main (parent) class only
$result = $this->process_path();

Code of URL::process_path() WC 7.1.0

private function process_path() {
	$segments                    = explode( '/', $this->components['path'] );
	$this->is_absolute           = substr( $this->components['path'], 0, 1 ) === '/' || ! empty( $this->components['host'] );
	$this->is_non_root_directory = substr( $this->components['path'], -1, 1 ) === '/' && strlen( $this->components['path'] ) > 1;
	$resolve_traversals          = 'file' !== $this->components['scheme'] || $this->is_absolute;
	$retain_traversals           = false;

	// Clean the path.
	foreach ( $segments as $part ) {
		// Drop empty segments.
		if ( strlen( $part ) === 0 || '.' === $part ) {
			continue;
		}

		// Directory traversals created with percent-encoding syntax should also be detected.
		$is_traversal = str_ireplace( '%2e', '.', $part ) === '..';

		// Resolve directory traversals (if allowed: see further comment relating to this).
		if ( $resolve_traversals && $is_traversal ) {
			if ( count( $this->path_parts ) > 0 && ! $retain_traversals ) {
				$this->path_parts = array_slice( $this->path_parts, 0, count( $this->path_parts ) - 1 );
				continue;
			} elseif ( $this->is_absolute ) {
				continue;
			}
		}

		/*
		 * Consider allowing directory traversals to be resolved (ie, the process that converts 'foo/bar/../baz' to
		 * 'foo/baz').
		 *
		 * 1. For this decision point, we are only concerned with relative filepaths (in all other cases,
		 *    $resolve_traversals will already be true).
		 * 2. This is a 'one time' and unidirectional operation. We only wish to flip from false to true, and we
		 *    never wish to do this more than once.
		 * 3. We only flip the switch after we have examined all leading '..' traversal segments.
		 */
		if ( false === $resolve_traversals && '..' !== $part && 'file' === $this->components['scheme'] && ! $this->is_absolute ) {
			$resolve_traversals = true;
		}

		/*
		 * Set a flag indicating that traversals should be retained. This is done to ensure we don't prematurely
		 * discard traversals at the start of the path.
		 */
		$retain_traversals = $resolve_traversals && '..' === $part;

		// Retain this part of the path.
		$this->path_parts[] = $part;
	}

	// Protect against empty relative paths.
	if ( count( $this->path_parts ) === 0 && ! $this->is_absolute ) {
		$this->path_parts = array( '.' );
		$this->is_non_root_directory = true;
	}

	// Reform the path from the processed segments, appending a leading slash if it is absolute and restoring
	// the Windows drive letter if we have one.
	$this->components['path'] = ( $this->is_absolute ? '/' : '' ) . implode( '/', $this->path_parts ) . ( $this->is_non_root_directory ? '/' : '' );
}