All pastes #16272 Raw Edit

Miscellany

public text v1 · immutable
#16272 ·published 2005-06-29 06:46 UTC
rendered paste body
<?php

/**
 * This is a library of functions to ensure file paths
 * aren't malicious.
 *
 * Proper use of this class is also required for proper security.
 * 
 * @version 1.0.0
 * @author Joshua St. Marie <webmaster@joshstmarie.com>
 * @copyright 2005 Joshua St. Marie
 */

class fpath
{
  private $doc_root; // the top location of the project, eg: /home/user/webroot/myproject
  private $path; // the path to add to the document root
  
  function fpath ($path='')
  {
    if($this->pathSanity($path))
      $this->setDocRoot($this->formatPath($path));
  }
  
  function getDocRoot ()
  {
    if(!empty($this->doc_root) && isset($this->doc_root))
      return $this->doc_root;
    else
      return false;
  }
  
  private function setDocRoot ($doc_root)
  {
    $this->doc_root = $doc_root;
    return true;
  }
  
  function setPath ($path)
  {
    if(substr($this->formatPath($path), 0, 1) == DIRECTORY_SEPARATOR)
    {
      $this->path = $path;
      if($this->pathSanity($this->formatPath($this->doc_root.$this->path)))
        return $this->formatPath($this->doc_root.$this->path);
      else
        return false;
    }
    else
    {
      $this->path = DIRECTORY_SEPARATOR.$path;
      if($this->pathSanity($this->formatPath($this->doc_root.$this->path)))
        return $this->formatPath($this->doc_root.$this->path);
      else
        return false;
    }
  }
  
  function getPath ()
  {
    if(!empty($this->path) && isset($this->path))
      return $this->formatPath($this->doc_root.$this->path);
    else
      return false;
  }
  
  function pathSanity ($path)
  {
    // run the path through some checks to make sure it's ok
    
    $regex = "/(\\\\\.\\.|\\\\\.|\.\.\\\|\.\\\|\.\.\/|\.\/|;|(?<![A-Z]):)/";
    if(preg_match_all($regex,$path,$matches,PREG_OFFSET_CAPTURE))
    {
      $errStr = preg_replace($regex,"<strong class=\"pathErr\">\\1</strong>",$path);

      echo "<P style=\"color:maroon;\">".$errStr."</p></br>\n";

      foreach($matches[0] as $k => $v)
      {
        if($v[0] == '../' || $v[0] == '..\\' || $v[0] == '\..')
          $type = 'UP';
        elseif($v[0] == './' || $v[0] == '.\\' || $v[0] == '\.')
          $type = 'CUR';
        elseif($v[0] == ';' || $v[0] == ':')
          $type = 'SEP';

        echo "[0x".str_pad($v[1],4,'0',STR_PAD_LEFT);
        echo " $type] Illegal path segment: ".$v[0]."</br>\n";
      }
      return false;
    }
    else // passed "../  ./  ..\  .\  \..  \.  :  ;" check
    {
      // make sure the location exists now
      if(file_exists($path))
      {
        return true;
      }
      else
      {
        echo "<P>Path doesnt exist: $path";
        return false;
      }
    }
  }
  
  function formatPath ($path)
  {
    $slash_replace = "~/+|\\\+~";
    $path = preg_replace($slash_replace, DIRECTORY_SEPARATOR, $path);
    
    if(DIRECTORY_SEPARATOR == '/') // Dealing with *nix separator
		{
		  if(stristr($path,'\\')) // Dealing with windows path on *nix.
			{
			  $path = explode('\\',$path);
				$path = implode('/',$path);
			}
		}
		elseif(DIRECTORY_SEPARATOR == '\\')
		{
		  if(stristr($path,'/')) // Dealing with *nix path on Windows.
			{
			  $path = explode('/',$path);
				$path = implode('\\',$path);
			}
		}
		
    // strip un-wanted slashes, format the path for windows or unix?
    $plen = strlen($path);
    if(substr($path, $plen-1, 1) == '/' || substr($path, $plen-1, 1) == '\\')
    {
      return substr($path, 0, $plen-1);
    }
    else
      return $path;
  }
}

$fm = new fpath(dirname(realpath($_SERVER['SCRIPT_FILENAME'])));
?>