<commit_before><?php
// 
// Copyright 2010 <NAME>
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
//     http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// 

if (!defined('PHP_URL_AUTHORITY')) {
	define('PHP_URL_AUTHORITY', 8);
}

/**
 * A class for working with RFC 3986 compliant URIs.
 * 
 * @TODO make encoding/decoding really solid
 * @TODO improve query param logic, including normalization
 * 
 * @see http://tools.ietf.org/html/rfc3986
 * @see http://docs.python.org/library/urlparse.html
 */
class Uri {
	/**
	 * 
	 */
	const Scheme = PHP_URL_SCHEME;
	const Authority = PHP_URL_AUTHORITY;
	const Path = PHP_URL_PATH;
	const Query = PHP_URL_QUERY;
	const Fragment = PHP_URL_FRAGMENT;
	const Host = PHP_URL_HOST;
	const Port = PHP_URL_PORT;
	const User = PHP_URL_USER;
	const Pass = PHP_URL_PASS;
	
	/**
	 * An initialized array of default values for parsed URI components.
	 *
	 * @var array
	 */
	protected static $default_components = array(
		'scheme' => null,
		'authority' => null,
		'path' => null,
		'query' => null,
		'fragment' => null,
		'user' => null,
		'pass' => null,
		'host' => null,
		'port' => null,
	);
	
	/**
	 * An initialized array of default values for parsed URI components.
	 *
	 * @var array
	 */
	protected static $component_map = array(
		self::Scheme => 'scheme',
		self::Authority => 'authority',
		self::Path => 'path',
		self::Query => 'query',
		self::Fragment => 'fragment',
		self::Host => 'host',
		self::Port => 'port',
		self::User => 'user',
		self::Pass => '<PASSWORD>',
	);
	
	/**
	 * The components of this URI.
	 *
	 * @var array
	 */
	protected $components;

	/**
	 * Returns a normalized version of the specified URI.
	 *
	 * @TODO sort query params alphabetically by key 
	 *
	 * @see http://tools.ietf.org/html/rfc3986#section-3
	 * @see http://tools.ietf.org/html/rfc3986#section-6
	 * @see http://en.wikipedia.org/wiki/URL_canonicalization
	 * @see http://www2007.org/papers/paper194.pdf
	 *
	 * @param  mixed $uri
	 * @return mixed
	 */
	public static function normalize($uri) {
			$parsed_uri = self::parse($uri);
		// if (is_array($uri)) {
		// 	$parsed_uri = $uri + self::$default_components;
		// 	$return_parsed = true;
		// } else {
		// 	$parsed_uri = self::parse($uri);
		// 	$return_parsed = false;
		// }
		
		$parsed_uri['scheme'] = strtolower($parsed_uri['scheme']);
		$parsed_uri['host'] = strtolower($parsed_uri['host']);
		$parsed_uri['authority'] = self::authority($parsed_uri);
		$parsed_uri['path'] = self::normalizePath($parsed_uri['path']);

		// if ($return_parsed) {
		// 	return $parsed_uri;
		// }
		return self::unparse($parsed_uri);
	}

	/**
	 * Returns a path with all dot segments ('.' and '..') interpretted and 
	 * removed.
	 *
	 * @see http://tools.ietf.org/html/rfc3986#section-3.3
	 * @see http://tools.ietf.org/html/rfc3986#section-5.2.4
	 * @see http://en.wikipedia.org/wiki/URL_canonicalization
	 * @see http://www2007.org/papers/paper194.pdf
	 *
	 * @param  string $path
	 * @return string
	 */
	public static function normalizePath($path) {
		if ($path == '/' || !isset($path[0])) {
			return $path;
		}
		
		$input_segments = explode('/', $path);
		$output_segments = false;
		if ($input_segments) {
			$output_segments = array();
			foreach ($input_segments as $segment) {
				if ($segment != '' && $segment != '.') {
					if ($segment == '..') {
						array_pop($output_segments);
					} else {
						$output_segments[] = $segment;
					}
				}
			}
		}

		$normalized = '';
		if ($path[0] == '/') {
			$normalized = '/';
		}

		if ($output_segments) {
			$normalized .= implode('/', $output_segments);
			if ($segment == '.' || $segment == '..' || $segment == '') {
				$normalized .= '/';
			}
		}
		
		return $normalized;
	}

	/**
	 * Parses the supplied URI into its individual components and returns them 
	 * as an associative array. If $component is supplied, a string with the
	 * specified component is returned, or null if invalid.
	 *
	 * @see http://tools.ietf.org/html/rfc3986#appendix-B
	 * 
	 * @param  string  $uri
	 * @param  integer $component optional
	 * @return array
	 */
	public static function parse($uri, $component=-1) {
		$uri = (string) $uri;
		
		// Compensate for limited behavior of PHP's parse_url function
		$reset = false;
		if ($uri[0] == '/' && $uri[1] == '/') { # //*
			if ($uri[2] == '/') { # ///*
				$uri = 'scheme://host/' . substr($uri, 3);
				$reset = array('scheme', 'host');
			} elseif (!isset($uri[2])) { # //
				$uri = 'scheme://host';
				$reset = array('scheme', 'host');
			} else { # //*
				$uri = 'scheme:' . $uri;
				$reset = array('scheme');
			}
		} else {
			$parts = explode(':', $uri, 2);
			// if (!isset($parts[0][0])) { # :*  prepend scheme?
			// 	$uri = 'scheme' . $uri;<commit_msg>fixed PHP notices in Uri<commit_after><?php
// 
// Copyright 2010 <NAME>
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
//     http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// 

if (!defined('PHP_URL_AUTHORITY')) {
	define('PHP_URL_AUTHORITY', 8);
}

/**
 * A class for working with RFC 3986 compliant URIs.
 * 
 * @TODO make encoding/decoding really solid
 * @TODO improve query param logic, including normalization
 * 
 * @see http://tools.ietf.org/html/rfc3986
 * @see http://docs.python.org/library/urlparse.html
 */
class Uri {
	/**
	 * 
	 */
	const Scheme = PHP_URL_SCHEME;
	const Authority = PHP_URL_AUTHORITY;
	const Path = PHP_URL_PATH;
	const Query = PHP_URL_QUERY;
	const Fragment = PHP_URL_FRAGMENT;
	const Host = PHP_URL_HOST;
	const Port = PHP_URL_PORT;
	const User = PHP_URL_USER;
	const Pass = PHP_URL_PASS;
	
	/**
	 * An initialized array of default values for parsed URI components.
	 *
	 * @var array
	 */
	protected static $default_components = array(
		'scheme' => null,
		'authority' => null,
		'path' => null,
		'query' => null,
		'fragment' => null,
		'user' => null,
		'pass' => null,
		'host' => null,
		'port' => null,
	);
	
	/**
	 * An initialized array of default values for parsed URI components.
	 *
	 * @var array
	 */
	protected static $component_map = array(
		self::Scheme => 'scheme',
		self::Authority => 'authority',
		self::Path => 'path',
		self::Query => 'query',
		self::Fragment => 'fragment',
		self::Host => 'host',
		self::Port => 'port',
		self::User => 'user',
		self::Pass => '<PASSWORD>',
	);
	
	/**
	 * The components of this URI.
	 *
	 * @var array
	 */
	protected $components;

	/**
	 * Returns a normalized version of the specified URI.
	 *
	 * @TODO sort query params alphabetically by key 
	 *
	 * @see http://tools.ietf.org/html/rfc3986#section-3
	 * @see http://tools.ietf.org/html/rfc3986#section-6
	 * @see http://en.wikipedia.org/wiki/URL_canonicalization
	 * @see http://www2007.org/papers/paper194.pdf
	 *
	 * @param  mixed $uri
	 * @return mixed
	 */
	public static function normalize($uri) {
			$parsed_uri = self::parse($uri);
		// if (is_array($uri)) {
		// 	$parsed_uri = $uri + self::$default_components;
		// 	$return_parsed = true;
		// } else {
		// 	$parsed_uri = self::parse($uri);
		// 	$return_parsed = false;
		// }
		
		$parsed_uri['scheme'] = strtolower($parsed_uri['scheme']);
		$parsed_uri['host'] = strtolower($parsed_uri['host']);
		$parsed_uri['authority'] = self::authority($parsed_uri);
		$parsed_uri['path'] = self::normalizePath($parsed_uri['path']);

		// if ($return_parsed) {
		// 	return $parsed_uri;
		// }
		return self::unparse($parsed_uri);
	}

	/**
	 * Returns a path with all dot segments ('.' and '..') interpretted and 
	 * removed.
	 *
	 * @see http://tools.ietf.org/html/rfc3986#section-3.3
	 * @see http://tools.ietf.org/html/rfc3986#section-5.2.4
	 * @see http://en.wikipedia.org/wiki/URL_canonicalization
	 * @see http://www2007.org/papers/paper194.pdf
	 *
	 * @param  string $path
	 * @return string
	 */
	public static function normalizePath($path) {
		if ($path == '/' || !isset($path[0])) {
			return $path;
		}
		
		$input_segments = explode('/', $path);
		$output_segments = false;
		if ($input_segments) {
			$output_segments = array();
			foreach ($input_segments as $segment) {
				if ($segment != '' && $segment != '.') {
					if ($segment == '..') {
						array_pop($output_segments);
					} else {
						$output_segments[] = $segment;
					}
				}
			}
		}

		$normalized = '';
		if ($path[0] == '/') {
			$normalized = '/';
		}

		if ($output_segments) {
			$normalized .= implode('/', $output_segments);
			if ($segment == '.' || $segment == '..' || $segment == '') {
				$normalized .= '/';
			}
		}
		
		return $normalized;
	}

	/**
	 * Parses the supplied URI into its individual components and returns them 
	 * as an associative array. If $component is supplied, a string with the
	 * specified component is returned, or null if invalid.
	 *
	 * @see http://tools.ietf.org/html/rfc3986#appendix-B
	 * 
	 * @param  string  $uri
	 * @param  integer $component optional
	 * @return array
	 */
	public static function parse($uri, $component=-1) {
		$uri = (string) $uri;
		
		// Compensate for limited behavior of PHP's parse_url function
		$reset = false;
		if (isset($uri[1]) && $uri[0] == '/' && $uri[1] == '/') { # //*
			if ($uri[2] == '/') { # ///*
				$uri = 'scheme://host/' . substr($uri, 3);
				$reset = array('scheme', 'host');
			} elseif (!isset($uri[2])) { # //
				$uri = 'scheme://host';
				$reset = array('scheme', 'host');
			} else { # //*
				$uri = 'scheme:' . $uri;
				$reset = array('scheme');
			}
		} else {
			$parts = explode(':', $uri, 2);
			// if (!isset($parts[0][0])) { # :*  prepend scheme?
			// 	$uri = 'scheme' . $uri;
{'fraction_non_alphanumeric': 0.17737149420886378, 'fraction_numerical': 0.013305255097157078, 'mean_word_length': 3.0669521214480344, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 6, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5232007', 'n_tokens_mistral': 4001, 'n_tokens_neox': 3519, 'n_words': 894}