<?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;
}
}
?>
|