Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- /*
- Copyright (c) 2011, Anil Cetin
- All rights reserved.
- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
- * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the
- distribution.
- * Neither the name of the Anil Cetin nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- class rewriteConf {
- public function __construct($htContent){
- $this->htContent = $htContent;
- }
- private function parseLine($line){
- list($cmd,$regex,$rew,$flags) = explode(" ",$line);
- if(!empty($flags)){
- $flagsArray = explode(",",trim(substr(substr(trim($flags),strpos($flags,'[')+1),0,strpos($flags,']')-1)));
- $flagsArray = array_map("trim",$flagsArray);
- }
- return array(trim($regex),trim($rew),$flagsArray);
- }
- private function readRules(){
- $lines = explode("\n",$this->htContent);
- $i = 0;
- foreach($lines as $line){
- if($line[0] != '#' && !empty($line[0])){
- if(strpos($line,"RewriteCond") !== false){
- if(!isset($k))$k = 0;
- if(!isset($p))$p = 0;
- $parsedLine = $this->parseLine($line);
- $conds[$p] = array(
- 'match' => $parsedLine[0],
- 'rule' => $parsedLine[1],
- 'flags' => $parsedLine[2]
- );
- $p++;
- }
- if(strpos($line,"RewriteRule") !== false){
- if(!isset($k))$k = 0;
- $parsedLine = $this->parseLine($line);
- $condBit = 'AND';
- if(is_array($conds[0]["flags"]) && in_array('OR',$conds[0]["flags"]))$condBit = 'OR';
- $rules[$k] = array(
- 'rule' => array(
- 'regex' => $parsedLine[0],
- 'rew' => $parsedLine[1],
- 'flags' => $parsedLine[2]
- ),
- 'condBit' => $condBit,
- 'conditions' => $conds
- );
- unset($p,$conds,$parsedLine,$condBit);
- $k++;
- }
- }
- }
- return $rules;
- }
- private function parseFlags($flagArray,$type,$r,$c){
- //type: 0 -> rule 1-> condition
- //this function returns an array;
- /*
- array(
- return => 0|return code
- break => 0|1
- appendEnd => last|permanent|redirect|break
- env => var=value
- matchOperator => ~*|~
- unknown => 0|1
- set => key:var
- )
- */
- $returnArray = array('return' => '0','break' => '0','appendEnd' => '', 'env' => '', 'matchOperator' => '~');
- foreach($flagArray as $flag){
- switch($flag[0]){
- case 'N':
- case 'n':
- $returnArray["matchOperator"] = '~*';
- if(!isset($returnArray["unknown"]))$returnArray["unknown"] = '0';
- break;
- case 'F':
- case 'f':
- $returnArray["return"] = '403';
- $returnArray["break"] = '1';
- if(!isset($returnArray["unknown"]))$returnArray["unknown"] = '0';
- break;
- case 'G':
- case 'g':
- $returnArray["return"] = '410';
- $returnArray["break"] = '1';
- if(!isset($returnArray["unknown"]))$returnArray["unknown"] = '0';
- break;
- case 'R':
- case 'r':
- list($flaga,$rcode) = explode("=",$flag);
- if($rcode == '301' || $rcode == 'permanent'){
- $returnArray["appendEnd"] = 'permanent';
- } else {
- $returnArray["appendEnd"] = 'redirect';
- }
- $returnArray["break"] = '1';
- if(!isset($returnArray["unknown"]))$returnArray["unknown"] = '0';
- break;
- case 'L':
- case 'l':
- if(empty($returnArray["appendEnd"])){
- $returnArray["appendEnd"] = 'last';
- }
- if(!isset($returnArray["unknown"]))$returnArray["unknown"] = '0';
- break;
- case 'E':
- case 'e':
- list($cmd,$envvar) = explode("=",$flag);
- //list($ekey,$evar) = explode(":",$envvar);
- $returnArray["env"][] = $envvar;
- break;
- case 'O':
- case 'o':
- $returnArray["set"][] = '$rule_'.$r.' 1';
- break;
- case 'A':
- $returnArray["set"][] = '$rule_'.$r.' '.($c+1).'$rule_'.$r;
- break;
- }
- }
- if(count($flagArray) > 1){
- if(!isset($returnArray["unknown"]))$returnArray["unknown"] = '1';
- } else {
- $returnArray["unknown"] = '0';
- }
- return $returnArray;
- }
- private function parseCondMatch($condition,$r,$c,$condBit){
- $matchOperator = '~';
- if($condition["rule"][0] == '!'){
- $nomatch = '!';
- $condition["rule"] = substr($condition["rule"],1);
- }
- $condition["flags"][] = $condBit;
- $condition["flags"] = array_unique($condition["flags"]);
- $fromFlags = $this->parseFlags($condition["flags"],1,$r,$c);
- if($fromFlags["matchOperator"]){
- $matchOperator = $fromFlags["matchOperator"];
- }
- switch($condition["rule"]){
- case "-f":
- case "-F":
- $left = $nomatch.'-f';
- $right = $condition["match"];
- $operand = '';
- break;
- case "-d":
- $left = $nomatch.'-d';
- $right = $condition["match"];
- $operand = '';
- break;
- case "-s":
- $left = $nomatch.'-e';
- $right = $condition["match"];
- $operand = '';
- break;
- default:
- $left = $condition["match"];
- $right = $condition["rule"];
- $operand = $nomatch.$matchOperator;
- break;
- }
- $returnArray = array(
- 'left' => $left,
- 'right' => $right,
- 'operand' => $operand,
- 'flags' => $fromFlags
- );
- return $returnArray;
- }
- private function parseRewirteCond($rule,$r){
- $c = 0;
- if(is_array($rule["conditions"])){
- foreach($rule["conditions"] as $condition){
- $condResult[$c] = $this->parseCondMatch($condition,$r,$c,$rule["condBit"]);
- $c++;
- }
- }
- return $condResult;
- }
- private function mustSkipForCond($conditions){
- if(count($conditions)==0){
- return 0;
- } elseif(count($conditions) == 1) {
- if($conditions[0]["flags"]["unknown"] == 1){
- return "skipped because all flags in condition are unknown";
- }
- return 0;
- } else {
- $unknown = 0;
- foreach($conditions as $cond){
- if($cond["flags"]["unknown"] == 1){
- $unknown++;
- }
- }
- if(count($conditions) == $unknown){
- return "skipped because all flags for all conditions are unknown";
- }
- return 0;
- }
- }
- private function setBackRef(&$rule,&$condsParsed){
- if(preg_match_all('/\%([0-9])/',$rule["rule"]["regex"],$matchesRule)!=0){
- $rule["rule"]["regex"] = preg_replace('/\%([0-9])/','$bref_$1',$rule["rule"]["regex"]);
- }
- if(preg_match_all('/\%([0-9])/',$rule["rule"]["rew"],$matchesRew)!=0){
- $rule["rule"]["rew"] = preg_replace('/\%([0-9])/','$bref_$1',$rule["rule"]["rew"]);
- }
- $totalMatches = array_merge($matchesRule[1],$matchesRew[1]);
- if(is_array($rule["rule"]["flags"])){
- $i=0;
- foreach($rule["rule"]["flags"] as $flags){
- if(preg_match_all('/\%([0-9])/',$rule["rule"]["flags"][$i],$matchesFlag)!=0){
- $rule["rule"]["flags"][$i] = preg_replace('/\%([0-9])/','$bref_$1',$rule["rule"]["flags"][$i]);
- $totalMatches = array_merge($totalMatches,$matchesFlag[1]);
- }
- $i++;
- }
- }
- $totalMatches = array_unique($totalMatches);
- if(is_array($totalMatches)){
- foreach($totalMatches as $match){
- $i=0;
- if($rule["condBit"] == 'OR'){
- foreach($condsParsed as $cond){
- array_push($condsParsed[$i]["flags"]["set"], '$bref_'.$match.' $'.$match);
- $i++;
- }
- } else {
- array_push($condsParsed[count($condsParsed)-1]["flags"]["set"], '$bref_'.$match.' $'.$match);
- }
- }
- }
- }
- private function parseRule(&$rule,$c){
- if($rule["rule"]["regex"][0] == '^'){
- if($rule["rule"]["regex"][1]!='/'){
- $rule["rule"]["regex"] = '^/'.substr($rule["rule"]["regex"],1);
- }
- } else {
- if($rule["rule"]["regex"][0]!='/'){
- $rule["rule"]["regex"] = '/'.$rule["rule"]["regex"];
- }
- }
- if($rule["rule"]["rew"][0] == '^' && substr($rule["rule"]["rew"],0,4) != 'http'){
- if($rule["rule"]["rew"][1]!='/'){
- $rule["rule"]["rew"] = '^/'.substr($rule["rule"]["rew"],1);
- }
- } else {
- if($rule["rule"]["rew"][0]!='/' && substr($rule["rule"]["rew"],0,4) != 'http'){
- $rule["rule"]["rew"] = '/'.$rule["rule"]["rew"];
- }
- }
- if($rule["rule"]["rew"] == '/-'){
- unset($rule["rule"]["rew"],$rule["rule"]["regex"]);
- }
- if($c != 0){
- if($rule["condBit"] == 'OR'){
- $rule["rule"]["trueExp"] = '1';
- } else {
- $i=0;
- while($i < $c){
- $backme = ($i+1).$backme;
- $i++;
- }
- $rule["rule"]["trueExp"] = $backme;
- }
- }
- }
- private function replaceVariables(&$val,&$key){
- if(preg_match_all('/\%\{HTTP\:(.*)\}/',$val,$matches)){
- foreach($matches[1] as $match){
- $val = str_replace('%{HTTP:'.$match.'}','$http_'.str_replace('-','_',strtolower($match)),$val);
- }
- }
- $pat = array(
- '%{HTTP_USER_AGENT}',
- '%{HTTP_REFERER}',
- '%{HTTP_COOKIE}',
- '%{HTTP_FORWARDED}',
- '%{HTTP_HOST}',
- '%{HTTP_PROXY_CONNECTION}',
- '%{HTTP_ACCEPT}',
- '%{REMOTE_ADDR}',
- '%{REMOTE_PORT}',
- '%{REMOTE_USER}',
- '%{REQUEST_METHOD}',
- '%{SCRIPT_FILENAME}',
- '%{PATH_INFO}',
- '%{QUERY_STRING}',
- '%{DOCUMENT_ROOT}',
- '%{SERVER_NAME}',
- '%{SERVER_ADDR}',
- '%{SERVER_PORT}',
- '%{SERVER_PROTOCOL}',
- '%{REQUEST_URI}',
- '%{REQUEST_FILENAME}'
- );
- $rep = array(
- '$http_user_agent',
- '$http_referer',
- '$http_cookie',
- '$http_forwarded',
- '$http_host',
- '$http_proxy_connection',
- '$http_accept',
- '$remote_addr',
- '$remote_port',
- '$remote_user',
- '$request_method',
- '$uri',
- '$uri',
- '$args',
- '$document_root',
- '$server_name',
- '$server_addr',
- '$server_port',
- '$server_protocol',
- '$uri',
- '$request_filename'
- );
- $oldVal = $val;
- $val = str_replace($pat,$rep,$val);
- if($oldVal == $val && preg_match('/\%\{(.*)\}/i',$val)!=0){
- $val = "IGNORE";
- }
- }
- private function walkRecursiveFuckZend(&$input, $funcname, $userdata = ""){
- if (!is_array($input)){
- return false;
- }
- foreach ($input AS $key => $value){
- if(is_array($input[$key])){
- $this->walkRecursiveFuckZend($input[$key], $funcname, $userdata);
- } else {
- $saved_value = $value;
- if(!empty($userdata)){
- $this->$funcname($value, $key, $userdata);
- } else {
- $this->$funcname($value, $key);
- }
- if($value != $saved_value){
- if($value == 'IGNORE'){
- unset($input[$key]);
- } else {
- $input[$key] = $value;
- }
- }
- }
- }
- return true;
- }
- public function writeConfig(){
- $r = 0;
- foreach($this->conf as $conf){
- if(is_array($conf)){
- //array_walk_recursive($conf,'rewriteConf::replaceVariables');
- $this->walkRecursiveFuckZend($conf,'replaceVariables');
- //print_r($conf);
- //exit;
- $c = 0;
- $parsedRules = 0;
- if(is_array($conf["conds"])){
- foreach($conf["conds"] as $cond){
- if($cond["flags"]["unknown"]!=1 && isset($cond["left"]) && isset($cond["right"])){
- if($cond["operand"] == ''){
- $ret.= 'if ('.$cond["left"].' '.$cond["right"].'){
- ';
- } else {
- $ret.= 'if ('.$cond["left"].' '.$cond["operand"].' "'.$cond["right"].'"){
- ';
- }
- if(is_array($cond["flags"]["set"])){
- foreach($cond["flags"]["set"] as $set){
- $ret.= ' set '.$set.';
- ';
- }
- }
- if(is_array($cond["flags"]["env"])){
- foreach($cond["flags"]["env"] as $env){
- $ret.= ' setenv '.$env.';
- ';
- }
- }
- if($conf["condBit"] == 'OR'){
- if($conf["rule"]["flags"]["return"] > 0){
- $ret.= ' return '.$conf["rule"]["flags"]["return"].';
- ';
- $isReturned = 1;
- }
- if($conf["rule"]["flags"]["break"] == 1){
- $ret.= ' break;
- ';
- }
- }
- $ret.='}
- ';
- $parsedRules++;
- } else {
- $conf["rule"]["trueExp"] = str_replace($c,'',$conf["rule"]["trueExp"]);
- $ret.= '#ignored: condition '.$c.'
- ';
- }
- $c++;
- }
- }
- if(!isset($isReturned)){
- if($conf["rule"]["flags"]["unknown"] != 1){
- if($parsedRules != 0){
- $ret.= 'if ($rule_'.$r.' = "'.$conf["rule"]["trueExp"].'"){
- ';
- }
- if($conf["rule"]["flags"]["return"] < 1){
- if(is_array($conf["rule"]["flags"]["set"])){
- foreach($conf["rule"]["flags"]["set"] as $set){
- $ret.= ' set '.$set.';
- ';
- }
- }
- if(is_array($conf["rule"]["flags"]["env"])){
- foreach($conf["rule"]["flags"]["env"] as $env){
- $ret.= ' setenv '.$env.';
- ';
- }
- }
- if(isset($conf["rule"]["regex"]) && isset($conf["rule"]["rew"])){
- $addBreak = 0;
- if(!empty($conf["rule"]["flags"]["appendEnd"])){
- if($conf["rule"]["flags"]["appendEnd"] == 'permanent' || $conf["rule"]["flags"]["appendEnd"] == 'redirect'){
- $addBreak = 1;
- }
- $conf["rule"]["flags"]["appendEnd"] = ' '.$conf["rule"]["flags"]["appendEnd"];
- }
- $ret.= ' rewrite '.$conf["rule"]["regex"].' '.$conf["rule"]["rew"].''.$conf["rule"]["flags"]["appendEnd"].';
- '; if($addBreak == 1){
- $ret.= ' break;
- ';
- }
- } else {
- $ret.= '#ignored: "-" thing used or unknown variable in regex/rew
- ';
- }
- } else {
- $ret.= ' return '.$conf["rule"]["flags"]["return"].';
- ';
- if($conf["rule"]["flags"]["break"] == 1){
- $ret.= ' break;
- ';
- }
- }
- if($parsedRules != 0){
- $ret.='}
- ';
- }
- } else {
- $ret.= '#ignored: unknown variable in rule flag
- ';
- }
- }
- unset($isReturned,$cond,$env,$set);
- } else {
- $ret.= $conf.'
- ';
- }
- $r++;
- }
- $this->confOk = $ret;
- }
- public function parseContent(){
- $this->rules = $this->readRules();
- $r = 0;
- foreach($this->rules as $rule){
- $condsParsed = $this->parseRewirteCond($rule,$r);
- $beforeMscr = $mscr;
- if(($mscr = $this->mustSkipForCond($condsParsed))!=0){
- $conf[$r]["conds"] = $mscr;
- $conf[$r]["rule"] = $mscr;
- } else {
- if($beforeMscr != 0){
- //set last|break to before rule if any
- }
- $this->setBackRef($rule,$condsParsed);
- if(is_array($rule["rule"]["flags"])){
- $rule["rule"]["flags"] = $this->parseFlags($rule["rule"]["flags"],0,$r,0);
- } else {
- unset($rule["rule"]["flags"]);
- }
- $this->parseRule($rule,count($condsParsed));
- $conf[$r]["conds"] = $condsParsed;
- $conf[$r]["rule"] = $rule["rule"];
- }
- $conf[$r]["condBit"] = $rule["condBit"];
- $r++;
- }
- $this->conf = $conf;
- }
- }
- ?>
Add Comment
Please, Sign In to add comment