daily pastebin goal
71%
SHARE
TWEET

Untitled

a guest Jan 22nd, 2018 52 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. <?php
  2. /*
  3. Copyright (c) 2011, Anil Cetin
  4. All rights reserved.
  5.  
  6. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
  7.  
  8.     * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  9.     * 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
  10. distribution.
  11.     * 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.
  12.  
  13. 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
  14. 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,
  15. 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
  16. 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.
  17. */
  18.  
  19. class rewriteConf {
  20.  
  21.     public function __construct($htContent){
  22.         $this->htContent = $htContent;
  23.     }
  24.  
  25.     private function parseLine($line){
  26.         list($cmd,$regex,$rew,$flags) = explode(" ",$line);
  27.         if(!empty($flags)){
  28.             $flagsArray = explode(",",trim(substr(substr(trim($flags),strpos($flags,'[')+1),0,strpos($flags,']')-1)));
  29.             $flagsArray = array_map("trim",$flagsArray);
  30.         }
  31.         return array(trim($regex),trim($rew),$flagsArray);
  32.     }
  33.  
  34.     private function readRules(){
  35.         $lines = explode("\n",$this->htContent);
  36.         $i = 0;
  37.         foreach($lines as $line){
  38.             if($line[0] != '#' && !empty($line[0])){
  39.                 if(strpos($line,"RewriteCond") !== false){
  40.                     if(!isset($k))$k = 0;
  41.                     if(!isset($p))$p = 0;
  42.                     $parsedLine = $this->parseLine($line);
  43.                     $conds[$p] = array(
  44.                         'match' => $parsedLine[0],
  45.                         'rule' => $parsedLine[1],
  46.                         'flags' => $parsedLine[2]
  47.                     );
  48.                     $p++;
  49.                 }
  50.                 if(strpos($line,"RewriteRule") !== false){
  51.                     if(!isset($k))$k = 0;
  52.                     $parsedLine = $this->parseLine($line);
  53.                     $condBit = 'AND';
  54.                     if(is_array($conds[0]["flags"]) && in_array('OR',$conds[0]["flags"]))$condBit = 'OR';
  55.                     $rules[$k] = array(
  56.                         'rule' => array(
  57.                             'regex' => $parsedLine[0],
  58.                             'rew' => $parsedLine[1],
  59.                             'flags' => $parsedLine[2]
  60.                         ),
  61.                         'condBit' => $condBit,
  62.                         'conditions' => $conds
  63.                     );                     
  64.                     unset($p,$conds,$parsedLine,$condBit);
  65.                     $k++;
  66.                 }                          
  67.             }
  68.         }
  69.         return $rules;
  70.     }
  71.  
  72.    
  73.     private function parseFlags($flagArray,$type,$r,$c){
  74.         //type: 0 -> rule 1-> condition
  75.         //this function returns an array;
  76.         /*
  77.             array(
  78.                 return => 0|return code
  79.                 break => 0|1
  80.                 appendEnd => last|permanent|redirect|break
  81.                 env => var=value
  82.                 matchOperator => ~*|~
  83.                 unknown => 0|1
  84.                 set => key:var
  85.             )
  86.         */
  87.         $returnArray = array('return' => '0','break' => '0','appendEnd' => '', 'env' => '', 'matchOperator' => '~');
  88.         foreach($flagArray as $flag){
  89.             switch($flag[0]){
  90.                 case 'N':
  91.                 case 'n':
  92.                     $returnArray["matchOperator"] = '~*';
  93.                     if(!isset($returnArray["unknown"]))$returnArray["unknown"] = '0';
  94.                 break;
  95.                 case 'F':
  96.                 case 'f':
  97.                     $returnArray["return"] = '403';
  98.                     $returnArray["break"] = '1';
  99.                     if(!isset($returnArray["unknown"]))$returnArray["unknown"] = '0';
  100.                 break;
  101.                 case 'G':
  102.                 case 'g':
  103.                     $returnArray["return"] = '410';
  104.                     $returnArray["break"] = '1';
  105.                     if(!isset($returnArray["unknown"]))$returnArray["unknown"] = '0';
  106.                 break;
  107.                 case 'R':
  108.                 case 'r':
  109.                     list($flaga,$rcode) = explode("=",$flag);
  110.                     if($rcode == '301' || $rcode == 'permanent'){
  111.                         $returnArray["appendEnd"] = 'permanent';
  112.                     } else {
  113.                         $returnArray["appendEnd"] = 'redirect';
  114.                     }
  115.                     $returnArray["break"] = '1';
  116.                     if(!isset($returnArray["unknown"]))$returnArray["unknown"] = '0';
  117.                 break;
  118.                 case 'L':
  119.                 case 'l':
  120.                     if(empty($returnArray["appendEnd"])){
  121.                         $returnArray["appendEnd"] = 'last';
  122.                     }
  123.                     if(!isset($returnArray["unknown"]))$returnArray["unknown"] = '0';
  124.                 break;
  125.                 case 'E':
  126.                 case 'e':
  127.                     list($cmd,$envvar) = explode("=",$flag);
  128.                     //list($ekey,$evar) = explode(":",$envvar);
  129.                     $returnArray["env"][] = $envvar;
  130.                 break;
  131.                 case 'O':
  132.                 case 'o':
  133.                     $returnArray["set"][] = '$rule_'.$r.' 1';
  134.                 break;
  135.                 case 'A':
  136.                     $returnArray["set"][] = '$rule_'.$r.' '.($c+1).'$rule_'.$r;
  137.                 break;
  138.             }
  139.         }
  140.         if(count($flagArray) > 1){
  141.             if(!isset($returnArray["unknown"]))$returnArray["unknown"] = '1';
  142.         } else {
  143.             $returnArray["unknown"] = '0';
  144.         }
  145.         return $returnArray;
  146.        
  147.     }
  148.  
  149.     private function parseCondMatch($condition,$r,$c,$condBit){
  150.         $matchOperator = '~';
  151.  
  152.         if($condition["rule"][0] == '!'){
  153.             $nomatch = '!';
  154.             $condition["rule"] = substr($condition["rule"],1);
  155.         }
  156.  
  157.         $condition["flags"][] = $condBit;
  158.         $condition["flags"] = array_unique($condition["flags"]);
  159.        
  160.  
  161.         $fromFlags = $this->parseFlags($condition["flags"],1,$r,$c);
  162.  
  163.  
  164.         if($fromFlags["matchOperator"]){
  165.             $matchOperator = $fromFlags["matchOperator"];
  166.         }
  167.  
  168.         switch($condition["rule"]){
  169.             case "-f":
  170.             case "-F":
  171.                 $left = $nomatch.'-f';
  172.                 $right = $condition["match"];
  173.                 $operand = '';
  174.             break;
  175.             case "-d":
  176.                 $left = $nomatch.'-d';
  177.                 $right = $condition["match"];
  178.                 $operand = '';
  179.             break; 
  180.             case "-s":
  181.                 $left = $nomatch.'-e';
  182.                 $right = $condition["match"];
  183.                 $operand = '';
  184.             break;
  185.             default:
  186.                 $left = $condition["match"];
  187.                 $right = $condition["rule"];
  188.                 $operand = $nomatch.$matchOperator;
  189.  
  190.             break;
  191.         }
  192.  
  193.         $returnArray = array(
  194.             'left' => $left,
  195.             'right' => $right,
  196.             'operand' => $operand,
  197.             'flags' => $fromFlags
  198.         );
  199.         return $returnArray;       
  200.     }
  201.  
  202.     private function parseRewirteCond($rule,$r){
  203.         $c = 0;
  204.         if(is_array($rule["conditions"])){
  205.             foreach($rule["conditions"] as $condition){
  206.                
  207.                     $condResult[$c] = $this->parseCondMatch($condition,$r,$c,$rule["condBit"]);            
  208.                 $c++;
  209.             }
  210.         }
  211.         return $condResult;
  212.     }
  213.  
  214.     private function mustSkipForCond($conditions){
  215.         if(count($conditions)==0){
  216.             return 0;
  217.         } elseif(count($conditions) == 1) {
  218.             if($conditions[0]["flags"]["unknown"] == 1){
  219.                 return "skipped because all flags in condition are unknown";
  220.             }
  221.             return 0;
  222.         } else {
  223.             $unknown = 0;
  224.             foreach($conditions as $cond){
  225.                 if($cond["flags"]["unknown"] == 1){
  226.                     $unknown++;
  227.                 }
  228.             }
  229.             if(count($conditions) == $unknown){
  230.                 return "skipped because all flags for all conditions are unknown";
  231.             }
  232.             return 0;
  233.         }
  234.     }
  235.  
  236.     private function setBackRef(&$rule,&$condsParsed){
  237.         if(preg_match_all('/\%([0-9])/',$rule["rule"]["regex"],$matchesRule)!=0){
  238.             $rule["rule"]["regex"] = preg_replace('/\%([0-9])/','$bref_$1',$rule["rule"]["regex"]);        
  239.         }
  240.        
  241.         if(preg_match_all('/\%([0-9])/',$rule["rule"]["rew"],$matchesRew)!=0){
  242.             $rule["rule"]["rew"] = preg_replace('/\%([0-9])/','$bref_$1',$rule["rule"]["rew"]);
  243.         }
  244.  
  245.         $totalMatches = array_merge($matchesRule[1],$matchesRew[1]);
  246.        
  247.  
  248.         if(is_array($rule["rule"]["flags"])){
  249.             $i=0;
  250.             foreach($rule["rule"]["flags"] as $flags){
  251.                 if(preg_match_all('/\%([0-9])/',$rule["rule"]["flags"][$i],$matchesFlag)!=0){
  252.                     $rule["rule"]["flags"][$i] = preg_replace('/\%([0-9])/','$bref_$1',$rule["rule"]["flags"][$i]);
  253.                     $totalMatches = array_merge($totalMatches,$matchesFlag[1]);
  254.                 }
  255.                 $i++;
  256.             }
  257.         }
  258.        
  259.         $totalMatches = array_unique($totalMatches);
  260.         if(is_array($totalMatches)){
  261.             foreach($totalMatches as $match){
  262.                 $i=0;
  263.                 if($rule["condBit"] == 'OR'){
  264.                     foreach($condsParsed as $cond){
  265.                         array_push($condsParsed[$i]["flags"]["set"], '$bref_'.$match.' $'.$match);
  266.                         $i++;
  267.                     }
  268.                 } else {                   
  269.                     array_push($condsParsed[count($condsParsed)-1]["flags"]["set"], '$bref_'.$match.' $'.$match);
  270.                 }
  271.             }
  272.         }
  273.        
  274.  
  275.     }
  276.  
  277.     private function parseRule(&$rule,$c){ 
  278.  
  279.         if($rule["rule"]["regex"][0] == '^'){
  280.             if($rule["rule"]["regex"][1]!='/'){
  281.                 $rule["rule"]["regex"] = '^/'.substr($rule["rule"]["regex"],1);
  282.             }
  283.         } else {
  284.             if($rule["rule"]["regex"][0]!='/'){
  285.                 $rule["rule"]["regex"] = '/'.$rule["rule"]["regex"];
  286.             }                      
  287.         }
  288.        
  289.         if($rule["rule"]["rew"][0] == '^' && substr($rule["rule"]["rew"],0,4) != 'http'){
  290.             if($rule["rule"]["rew"][1]!='/'){
  291.                 $rule["rule"]["rew"] = '^/'.substr($rule["rule"]["rew"],1);
  292.             }
  293.         } else {
  294.             if($rule["rule"]["rew"][0]!='/' && substr($rule["rule"]["rew"],0,4) != 'http'){
  295.                 $rule["rule"]["rew"] = '/'.$rule["rule"]["rew"];
  296.             }                      
  297.         }
  298.        
  299.         if($rule["rule"]["rew"] == '/-'){
  300.             unset($rule["rule"]["rew"],$rule["rule"]["regex"]);
  301.         }
  302.  
  303.        
  304.         if($c != 0){
  305.            
  306.             if($rule["condBit"] == 'OR'){
  307.                 $rule["rule"]["trueExp"] = '1';
  308.             } else {
  309.                 $i=0;
  310.                 while($i < $c){
  311.                     $backme = ($i+1).$backme;
  312.                     $i++;
  313.                 }
  314.                 $rule["rule"]["trueExp"] = $backme;
  315.             }
  316.         }
  317.     }
  318.    
  319.     private function replaceVariables(&$val,&$key){
  320.        
  321.         if(preg_match_all('/\%\{HTTP\:(.*)\}/',$val,$matches)){
  322.             foreach($matches[1] as $match){
  323.                 $val = str_replace('%{HTTP:'.$match.'}','$http_'.str_replace('-','_',strtolower($match)),$val);
  324.             }
  325.         }
  326.        
  327.        
  328.         $pat = array(
  329.             '%{HTTP_USER_AGENT}',
  330.             '%{HTTP_REFERER}',
  331.             '%{HTTP_COOKIE}',
  332.             '%{HTTP_FORWARDED}',
  333.             '%{HTTP_HOST}',
  334.             '%{HTTP_PROXY_CONNECTION}',
  335.             '%{HTTP_ACCEPT}',
  336.             '%{REMOTE_ADDR}',
  337.             '%{REMOTE_PORT}',
  338.             '%{REMOTE_USER}',
  339.             '%{REQUEST_METHOD}',
  340.             '%{SCRIPT_FILENAME}',
  341.             '%{PATH_INFO}',
  342.             '%{QUERY_STRING}',
  343.             '%{DOCUMENT_ROOT}',
  344.             '%{SERVER_NAME}',
  345.             '%{SERVER_ADDR}',
  346.             '%{SERVER_PORT}',
  347.             '%{SERVER_PROTOCOL}',
  348.             '%{REQUEST_URI}',
  349.             '%{REQUEST_FILENAME}'          
  350.         );
  351.        
  352.         $rep = array(
  353.             '$http_user_agent',
  354.             '$http_referer',
  355.             '$http_cookie',
  356.             '$http_forwarded',
  357.             '$http_host',
  358.             '$http_proxy_connection',
  359.             '$http_accept',
  360.             '$remote_addr',
  361.             '$remote_port',
  362.             '$remote_user',
  363.             '$request_method',
  364.             '$uri',
  365.             '$uri',
  366.             '$args',
  367.             '$document_root',
  368.             '$server_name',
  369.             '$server_addr',
  370.             '$server_port',
  371.             '$server_protocol',
  372.             '$uri',
  373.             '$request_filename'                                                                        
  374.         );
  375.         $oldVal = $val;
  376.         $val = str_replace($pat,$rep,$val);
  377.    
  378.         if($oldVal == $val && preg_match('/\%\{(.*)\}/i',$val)!=0){        
  379.             $val = "IGNORE";
  380.         }      
  381.     }
  382.  
  383.    
  384.     private function walkRecursiveFuckZend(&$input, $funcname, $userdata = ""){
  385.        
  386.         if (!is_array($input)){
  387.             return false;
  388.         }
  389.        
  390.         foreach ($input AS $key => $value){
  391.             if(is_array($input[$key])){
  392.                 $this->walkRecursiveFuckZend($input[$key], $funcname, $userdata);
  393.             } else {
  394.                 $saved_value = $value;
  395.                 if(!empty($userdata)){
  396.                     $this->$funcname($value, $key, $userdata);
  397.                 } else {
  398.                     $this->$funcname($value, $key);
  399.                 }
  400.  
  401.                 if($value != $saved_value){
  402.                     if($value == 'IGNORE'){
  403.                 unset($input[$key]);   
  404.             } else {
  405.                 $input[$key] = $value;
  406.             }
  407.                 }
  408.             }
  409.         }
  410.         return true;
  411.     }
  412.    
  413.     public function writeConfig(){     
  414.         $r = 0;
  415.         foreach($this->conf as $conf){
  416.             if(is_array($conf)){                   
  417.                 //array_walk_recursive($conf,'rewriteConf::replaceVariables');
  418.                 $this->walkRecursiveFuckZend($conf,'replaceVariables');
  419.                 //print_r($conf);
  420.                 //exit;
  421.                 $c = 0;
  422.                 $parsedRules = 0;
  423.                 if(is_array($conf["conds"])){          
  424.                     foreach($conf["conds"] as $cond){              
  425.                         if($cond["flags"]["unknown"]!=1 && isset($cond["left"]) && isset($cond["right"])){
  426.                             if($cond["operand"] == ''){
  427.                                 $ret.= 'if ('.$cond["left"].' '.$cond["right"].'){
  428. ';
  429.                             } else {
  430.                                 $ret.= 'if ('.$cond["left"].' '.$cond["operand"].' "'.$cond["right"].'"){
  431. ';
  432.                             }
  433.                             if(is_array($cond["flags"]["set"])){
  434.                                 foreach($cond["flags"]["set"] as $set){
  435.                                     $ret.= '    set '.$set.';
  436. ';
  437.                                 }
  438.                             }
  439.                            
  440.                             if(is_array($cond["flags"]["env"])){                       
  441.                                 foreach($cond["flags"]["env"] as $env){
  442.                                     $ret.= '    setenv '.$env.';
  443. ';
  444.                                 }
  445.                             }
  446.                             if($conf["condBit"] == 'OR'){                          
  447.                                 if($conf["rule"]["flags"]["return"] > 0){
  448.                                     $ret.= '    return '.$conf["rule"]["flags"]["return"].';
  449. ';
  450.                                     $isReturned = 1;
  451.                                 }
  452.                                 if($conf["rule"]["flags"]["break"] == 1){
  453.                                     $ret.= '    break;
  454. ';
  455.                                 }
  456.                             }
  457.                             $ret.='}
  458. ';
  459.                             $parsedRules++;
  460.                         } else {
  461.                             $conf["rule"]["trueExp"] = str_replace($c,'',$conf["rule"]["trueExp"]);
  462.                             $ret.= '#ignored: condition '.$c.'
  463. ';
  464.                         }
  465.                         $c++;                  
  466.                     }              
  467.                 }              
  468.                 if(!isset($isReturned)){
  469.                     if($conf["rule"]["flags"]["unknown"] != 1){
  470.                        
  471.                         if($parsedRules != 0){
  472.                             $ret.= 'if ($rule_'.$r.' = "'.$conf["rule"]["trueExp"].'"){
  473. ';
  474.                         }
  475.                         if($conf["rule"]["flags"]["return"] < 1){
  476.                            
  477.                             if(is_array($conf["rule"]["flags"]["set"])){
  478.                                 foreach($conf["rule"]["flags"]["set"] as $set){
  479.                                     $ret.= '    set '.$set.';
  480. ';
  481.                                 }
  482.                             }
  483.                            
  484.                             if(is_array($conf["rule"]["flags"]["env"])){
  485.                                 foreach($conf["rule"]["flags"]["env"] as $env){
  486.                                     $ret.= '    setenv '.$env.';
  487. ';
  488.                                 }
  489.                             }
  490.                             if(isset($conf["rule"]["regex"]) && isset($conf["rule"]["rew"])){
  491.                                 $addBreak = 0;
  492.                                 if(!empty($conf["rule"]["flags"]["appendEnd"])){
  493.                                     if($conf["rule"]["flags"]["appendEnd"] == 'permanent' || $conf["rule"]["flags"]["appendEnd"] == 'redirect'){
  494.                                         $addBreak = 1;
  495.                                     }
  496.                                     $conf["rule"]["flags"]["appendEnd"] = ' '.$conf["rule"]["flags"]["appendEnd"];
  497.                                 }
  498.                                 $ret.= '    rewrite '.$conf["rule"]["regex"].' '.$conf["rule"]["rew"].''.$conf["rule"]["flags"]["appendEnd"].';
  499. ';                              if($addBreak == 1){
  500.                                     $ret.= '    break;
  501. ';
  502.                                 }
  503.                             } else {
  504.                                 $ret.= '#ignored: "-" thing used or unknown variable in regex/rew
  505. ';
  506.                             }
  507.                         } else {
  508.                             $ret.= '    return '.$conf["rule"]["flags"]["return"].';
  509. ';
  510.                             if($conf["rule"]["flags"]["break"] == 1){
  511.                                 $ret.= '    break;
  512. ';
  513.                             }
  514.                         }
  515.                         if($parsedRules != 0){
  516.                             $ret.='}
  517. ';
  518.                         }
  519.                     } else {
  520.                         $ret.= '#ignored: unknown variable in rule flag
  521. ';
  522.                     }
  523.                 }
  524.                 unset($isReturned,$cond,$env,$set);
  525.             } else {
  526.                 $ret.= $conf.'
  527. ';
  528.             }
  529.             $r++;
  530.         }
  531.         $this->confOk = $ret;
  532.     }
  533.  
  534.     public function parseContent(){
  535.         $this->rules = $this->readRules();
  536.         $r = 0;
  537.         foreach($this->rules as $rule){
  538.             $condsParsed = $this->parseRewirteCond($rule,$r);
  539.             $beforeMscr = $mscr;
  540.             if(($mscr = $this->mustSkipForCond($condsParsed))!=0){
  541.                 $conf[$r]["conds"] = $mscr;
  542.                 $conf[$r]["rule"] = $mscr;
  543.             } else {
  544.                 if($beforeMscr != 0){
  545.                     //set last|break to before rule if any
  546.                 }
  547.                 $this->setBackRef($rule,$condsParsed);
  548.                 if(is_array($rule["rule"]["flags"])){
  549.                     $rule["rule"]["flags"] = $this->parseFlags($rule["rule"]["flags"],0,$r,0);
  550.                 } else {
  551.                     unset($rule["rule"]["flags"]);
  552.                 }
  553.                 $this->parseRule($rule,count($condsParsed));
  554.                 $conf[$r]["conds"] = $condsParsed;
  555.                 $conf[$r]["rule"] = $rule["rule"];             
  556.             }
  557.             $conf[$r]["condBit"] = $rule["condBit"];
  558.             $r++;
  559.         }
  560.         $this->conf = $conf;
  561.     }
  562.  
  563. }
  564. ?>
RAW Paste Data
Top