Location: PHPKode > projects > iF.SVNAdmin > svnadmin/ifphplib/IF_SVNClientC.class.php
<?php
class IF_SVNList
{
	var $path = "";
  var $entries = array();
  var $curEntry = null;
}

class IF_SVNListEntry
{
  var $rev = 1;
  var $author = "";
  var $date = "";
  var $size = 0;
  var $name = "";
  var $isdir = false;
}

class IF_SVNClientC
{
	var $is_windows_server = false;
  var $svnExe = null;
  var $curList = null;
  var $curTag = "";
  var $error_string = "";
  
  // Command line options which should be used
  // for the next command.
  var $trust_server_cert = true;
  var $non_interactive = true;
  var $username = "";
  var $password = "";
  
  function __construct()
  {
  	// Server operating system.
  	$soft = $_SERVER["SERVER_SOFTWARE"];
  	$soft = strtoupper($soft);
  	if (strpos($soft, "WIN") !== FALSE)
  	{
  		$this->is_windows_server = true;
  	}
  }
  
  function init($svn_exe)
  {
  	$this->svnExe = $svn_exe;
  	if (!file_exists($svn_exe))
  	{
  		$this->error_string = "Path to the svn-executable doesn't exist.";
  		return false;
  	}
  	
  	if (!is_executable($svn_exe))
  	{
  		$this->error_string = "The svn-executable is not executable. Missing permissions?";
  		return false;
  	}
    return true;
  }
  
  function encode_path($uri)
  {
  	$uri = str_replace(DIRECTORY_SEPARATOR, "/", $uri);
  	
  	// Convert to UTF-8 string.
  	if (function_exists("mb_detect_encoding") && function_exists("mb_convert_encoding"))
  		$path = mb_convert_encoding($uri, "UTF-8", mb_detect_encoding($uri));
  	
  	// Skip encoding of 'svn+ssh://' part.
  	$parts = explode("/", $uri);
  	$partsCount = count($parts);
  	for ($i=0; $i<$partsCount; $i++)
  	{
  		if ($i != 0 || $parts[$i] != 'svn+ssh:')
  		{
  			$parts[$i] = rawurlencode($parts[$i]);
  		}
  	}
  	$uri = implode("/", $parts);
  	
  	// Subversion bug?
  	$uri = str_replace("%3A", ":", $uri);
  	
  	// Quick fix for Windows share names.
  	if ($this->is_windows_server)
  	{
  		if (substr($uri, 0, 2) == "//")
  		{
  			$uri = '\\'.substr($uri, 2);
  		}
  		
  		if (substr($uri, 0, 10) == "file://///")
  		{
  			$uri = "file:///\\\\".substr($uri, 10);
  		}
  	}
  	
  	return $uri;
  }
  
  function encode_string($s, $dest_enc = "UTF-8")
  {
    if (function_exists("mb_detect_encoding") && function_exists("mb_convert_encoding"))
    {
      $s = mb_convert_encoding($s, "UTF-8", mb_detect_encoding($str));
    }
    return $s;
  }
  
  function create_svn_command($command, $repo_path, $args=null, $asXml=true)
  {
  	$cmd = "\"".$this->svnExe."\" ".$command;
  	
  	if ($asXml === true)
  	  $cmd.= " --xml";
  	 
  	if ($this->non_interactive)
  	  $cmd.= " --non-interactive";
  	  
  	if ($this->trust_server_cert)
  	  $cmd.= " --trust-server-cert";
  	  
  	if (!empty($this->username))
  	  $cmd.= " --username ".$this->username;
  	  
  	if (!empty($this->password))
  	  $cmd.= " --password ".$this->password;
  	  
  	// Handle custom args.
  	if (!empty($args))
  	{
  		foreach ($args as $key => &$val)
  		{
  			$cmd.= " ".$key;
  			if (!empty($val))
  			  $cmd.= " ".escapeshellarg($val);
  		}
  	}

  	// Automatic prepend the "file://" prefix, if nothing
  	// else is given.
  	if (preg_match('/^[a-z0-9+]+:\/\//i', $repo_path))
  	   ;
  	else
  	{
  		if (strpos($repo_path, "/") === 0)
  	    $repo_path = "file://".$repo_path;
  		else
  		  $repo_path = "file:///".$repo_path;
  	}
  	
    $cmd.= " ".$repo_path;
  	return ''.$cmd.'';
  }
  
  function svn_mkdir($path, $parents=true, $commitMessage=null)
  {
  	if (empty($path))
  	 return false;
  	 
  	 $args = array();
  	 if ($parents)
  	   $args["--parents"] = "";
  	 if (!empty($commitMessage))
  	   $args["--message"] = $commitMessage;
  	 
  	 $command = self::create_svn_command("mkdir", self::encode_path($path), $args, false);
  	 $command = substr($command, 1, -1); // Remove leading and ending slash for "exec" function.
  	 
  	 $output = null;
  	 $return_var = 0;
  	 exec($command, $output, $return_var);
  	 
  	 if ($return_var != 0)
  	   return false;
  	   
  	 return true;
  }
  
  function svn_list($path)
  {
  	if (empty($path))
  	{
  		$this->error_string = "Empty path for svn_list() command.";
  		return false;
  	}
  	
  	$command = self::create_svn_command("ls", self::encode_path($path), null, true);
    
    $proc_descr = array(
      0 => array("pipe", "r"), // STDIN
      1 => array("pipe", "w"), // STDOUT
      2 => array("pipe", "w")  // STDERR
    );
    
    $resource = proc_open($command, $proc_descr, $pipes);
    if (!is_resource($resource))
      return false;
    
    // Create XML-Parser.
    $xml_parser = xml_parser_create("UTF-8");
    xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, true);
    xml_set_element_handler($xml_parser, array($this, "xml_svn_list_start_element"), array($this, "xml_svn_list_end_element"));
    xml_set_character_data_handler($xml_parser, array($this, "xml_svn_list_character_data"));
    
    // Read the XML stream now.
    $data_handle = $pipes[1];
    while (!feof($data_handle))
    {
    	$line = fgets($data_handle);
    	if (!xml_parse($xml_parser, $line, feof($data_handle)))
    	{
    		// Error.
    		$this->error_string = "XML parse error: (code=".xml_get_error_code($xml_parser).") ".xml_error_string(xml_get_error_code($xml_parser));
    	}
    }
    
    $error_handle = $pipes[2];
    $error_message = "";
    while (!feof($error_handle))
    {
    	$error_message.= fgets($error_handle);
    }
    if (!empty($error_message))
      $this->error_string.= "(".$this->svnExe." error=".$error_message.")";
    
    // Free resources.
    xml_parser_free($xml_parser);
    fclose($pipes[0]);
    fclose($pipes[1]);
    fclose($pipes[2]);
    proc_close($resource);
    return $this->curList;
  }
  
  /////
  //
  // XML Handler Functions
  //
  /////
  
  function xml_svn_list_start_element($xml_parser, $tagname, $attrs)
  {
  	//echo "xml_svn_list_start_element($xml_parser, $tagname, $attrs)\n";
    switch($tagname)
    {
      case "LIST":
      	$this->curList = new IF_SVNList();
        if (count($attrs))
          foreach ($attrs as $aName => $aVal)
            switch($aName)
            {
              case "PATH":
                $this->curList->path = self::encode_string($aVal);
                break;
            }
        break;

      case "ENTRY":
        $this->curList->curEntry = new IF_SVNListEntry;
        if (count($attrs))
        {
          foreach ($attrs as $aName => $aVal)
          {
            switch($aName)
            {
              case "KIND":
                if ($aVal == "dir")
                  $this->curList->curEntry->isdir = true;
                else
                  $this->curList->curEntry->isdir = false;
                break;
            }
          }
        }
        break;
        
      case "COMMIT":
      	if (count($attrs))
      	{
      		foreach ($attrs as $aName => $aVal)
      		{
      			switch ($aName)
      			{
      				case "REVISION":
      					$this->curList->curEntry->rev = $aVal;
      					break;
      			}
      		}
      	}
      	break;
    }
    $this->curTag = $tagname;
  }
  
  function xml_svn_list_character_data($xml_parser, $tagdata)
  {
  	switch ($this->curTag)
  	{
  		case "NAME";
  		  if ($tagdata === false || $tagdata === "")
  		    return;
  		  $this->curList->curEntry->name.= self::encode_string(trim($tagdata));
  		  break;
  			
  		case "AUTHOR":
  			if ($tagdata === false || $tagdata === "")
          return;
  			$this->curList->curEntry->author.= trim($tagdata);
  			break;
  			
  		case "DATE":
  			if ($tagdata === false || $tagdata === "")
          return;
  			$this->curList->curEntry->date.= trim($tagdata);
  			break;
  	}
  }
  
  function xml_svn_list_end_element($xml_parser, $tagname)
  {
    switch ($tagname)
    {
      // Add the created entry to the list as child.
      case "ENTRY":
        $this->curList->entries[] = $this->curList->curEntry;
        break;
        
      case "LISTS":
      	unset($this->curList->curEntry);
      	break;
    }
  }
}
?>
Return current item: iF.SVNAdmin