Location: PHPKode > scripts > Relink > relink/class.relink.php
<?php
	/**
	 * RELINK v.0.2.1
	 *	Copyright 2008 Benjamin Falk
	 *	Contact:	falk [at] citrosaft [dot] net

	 *	This program is free software: you can redistribute it and/or modify
	 *	it under the terms of the GNU General Public License as published by
	 *	the Free Software Foundation, either version 3 of the License, or
	 *	(at your option) any later version.

	 *	This program is distributed in the hope that it will be useful,
	 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
	 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	 *	GNU General Public License for more details.

	 *	You should have received a copy of the GNU General Public License
	 *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
	 */
	
	error_reporting(E_ALL);
	
	class RELINK
	{
		/*
			The following variables get
			automatically filled up
		*/
		var $auto			= false;			//Gets true, when .htaccess contains #set link auto on
		var $rules			= array();			//Contains all link-rules
		var $replacements	= array();			//Contains all replacements
		var $parts			= array();			//Contains all parts of a rule
		var $linkStart		= '';				//Contains the startvalue of every link

		/*
			CONSTRUCTOR
			Reads a given .htaccess-file and adds rules
			
			(string)	$file			Contains the path of .htaccess
			(boolean)	$ignoreFile		True, if you want to ignore for example index.php in index.php?foo=bar
		*/
		function __construct($file='./.htaccess', $ignoreFile=true)
		{
			$htaccess = file($file);
			foreach ($htaccess as $line)
			{
				//Check if the auto-detection is turned on
				if ($this->auto === false)
				{
					if (strtolower(trim($line)) == '#set link auto on')
						$this->auto = true;
				}
				else
				{
					$line = trim($line);
					if (strtolower(trim($line)) == '#set link auto off')
						$this->auto = false;
					elseif (strtolower(substr($line,0,($lslen = strlen('#set link start ')))) == '#set link start ')
						$this->linkStart = substr($line,$lslen);
					elseif (substr($line,0,strlen('RewriteRule ')) == 'RewriteRule ')
					{
						//Add rule...
						$regex = $replacement = '';
						list($null, $regex, $replacement) = preg_split('/[\s]+/', $line);
						$this->addRule($regex, $replacement, $ignoreFile);
					}
				}
			}
			
			if ($this->linkStart == '')
			{
				if (isset($_SERVER['PHP_SELF']))
					$this->linkStart .= dirname($_SERVER['PHP_SELF']).'/';
			}
			if (substr($this->linkStart,-1) != '/') $this->linkStart .= '/';
		}

		/*
			(boolean) addRule
			Adds a rule for rewriting the links easier
			
			(string)	$regex			Contains the part in what the link should replaced in
										For example (.+?)\.html for main.html
			(string)	$replacement	Contains the real page, so main.html should get into index.php?page=main
		*/
		function addRule($regex, $replacement, $ignoreFile=true)
		{
			if ($regex == '' || $replacement == '') return false;
			
			//Get parts of replacement
			if ($ignoreFile === true) {
				$replacement = preg_replace('/^([\w\d\.\/]*)\?/', '', $replacement);
			}
			else
				if (substr($replacement,0,1) == '?') $replacement = substr($replacement,1);
			parse_str($replacement, $replacementParts);
			
			$availParts = array();
			foreach ($replacementParts as $key => $value)
			{
				if (substr($value,0,1) == '$')
				{
					$availParts[intval(substr($value,1))] = $key;
				}
				elseif (substr($key,0,1) == '$')
				{
					$availParts[intval(substr($key,1))] = $value;
				}
			}
			
			if (substr($regex,0,1) == '^') $regex = substr($regex,1);
			if (substr($regex,-1) == '$') $regex = substr($regex,0,-1);
			
			array_unshift($this->parts, $availParts);
			array_unshift($this->rules, $regex);
			array_unshift($this->replacements, $replacement);
			
			return true;
		}
		
		/*
			(mixed) replaceLink
			Converts a normal link such as ?foo=bar into the known
			replacement set by an .htaccess-file.
			
			(string)	$link			Contains the baselink
			(boolean)	$ignoreFile		If true, the filename of the link gets ignored and only
										the variables after the questmark gets parsed.
		*/
		function replaceLink($link, $ignoreFile=true)
		{
			if (preg_match('/(^http\:\/\/)|(^mailto\:)/i', $link)) return $link; //Ignore absolute links
			if (substr($link,0,1) == '/') return $link; //Ignore root-links like /index.php
			
			$_link = $link;
			if ($ignoreFile === true)
			{
				$link = preg_replace('/^([\w\d\.\/]*)\?/', '', $link);
			}
			else
				if (substr($link,0,1) == '?') $link = substr($link,1);
			parse_str($link, $linkParts);
			$partsCount = count($linkParts);
			
			//Get the rule with the exact parts
			foreach ($this->parts as $index => $part)
			{
				$continue = false;
				if (count($part) == $partsCount)
				{	//If the given values have the same count as the current rule...
					foreach ($linkParts as $key => $val)
					{
						if ($key !== '' && $val === '') //Ignore if there are different parts like ?var1&var2=1
							continue;
						else
						{
							//Check if the exact parts are avail
							if (!in_array($key, $part))
							{
								$continue = true;
								break;
							}
						}
					}
					
					if ($continue == true)
					{	//If you want to replace a link such as ?val1&val2: This is the part, which does that
						foreach ($linkParts as $key => $val)
						{
							//Check if the exact parts are avail
							if (in_array($val, $part))
								$continue = false;
							else
							{
								$continue = true;
								break;
							}
						}
					}
					
					if ($continue) continue;
					
					//Got ya!
					$rule = $this->rules[$index];
					$ruleParts = preg_split('/(\(.+?\))|\{.*?\}|\[.*\]/s', $rule, -1, PREG_SPLIT_DELIM_CAPTURE);
					
					$rIndex	= 0;
					$nLink	= '';
					$failed	= false;
					foreach ($ruleParts as $rulePart)
					{
						if ($rulePart == '') continue;
						
						if (substr($rulePart,0,1) == '(' && substr($rulePart,-1) == ')')
						{
							//Current one is a variable
							$rIndex++;
							if ($this->parts[$index][$rIndex] === null)
							{
								$failed = true;
								break;
							}
							
							if ($this->parts[$index][$rIndex] === '')
							{	//If the given link is like ?foo&bar, this might be the part, which is checking everything
								reset($linkParts);
								if ($rIndex == 1)
									$nLink.= addslashes(key($linkParts));
								else
								{
									$_rIndex = 1;
									while ((current($linkParts)) !== false)
									{
										next($linkParts);
										$_rIndex++;
										if ($_rIndex == $rIndex)
											$nLink.= addslashes(key($linkParts));
									}
								}
							}
							else
							{
								$rVar = $this->parts[$index][$rIndex];
								$nLink.= addslashes($linkParts[$rVar]);
							}
						}
						else
							$nLink .= $rulePart;
					}
					
					$nLink = stripslashes($nLink);
					
					if ($failed == true)	return $this->linkStart.$_link;
					else					return $this->linkStart.$nLink;
					
					break;
				}
			}
			//Nothing found...
			return $this->linkStart.$_link;
		}
	}
?>
Return current item: Relink