Location: PHPKode > projects > RCS Man on the Web > RCSManager-0.2/classes/rcs.php
<?php
/**
 * $Id$
 * $Log$
 */

Class RCS {
/*
    La classe RCS sert d'interface avec les programmes (bas niveau) rcs

    Attribut:
      $_path      String   virtual path in RCSManager (pwd)
      $_realpath  String   real path in the file system
      $_valid     Boolean  true if RCS archive can be found, i.e. 
                           RCS subdirectory exist and is readable

    Method:
      RCS($path)                   Builder of this class
      Table   getFilesTable()      give the table of RCS archives
      RCSFile getFile($name)       give an RCS object about the file name
      Table   checkin($argument)   do a check in
      Table   checkout($argument)  do a cheak out
  
 */

  /* Serveur path */
  var $_path;

  /* Real system path */
  var $_realpath;

  /* Is RealPath/RCS is valid */
  var $_valid = false;

  /**
   * Constructeur de la classe
   * @param $path
   */
  function RCS($path)
  {
    $this->_path = $path;
    $this->_realpath = BASE_dir . "$this->_path";
    
    if(is_dir("$this->_realpath/RCS"))
      if(is_readable("$this->_realpath/RCS"))
	$this->_valid = true;
  }/* RCS() */
  
  /**
   * Réalise un CheckIn du fichier spécifié dans ce système RCS
   * @param $argument table des argument du check in
   */
  function checkin($argument)
  {
    if(!is_uploaded_file($argument[fichier]))
      return(array(code => false, cmd => "erreur", msg => "no file uploaded!"));

    if(!checkTmpDIR())
      return(array(code => false, cmd => "erreur", msg => "can't use temporary folder."));

    $options = "";
    $pattern = array('/\\\/',  '/\\$/', '/`/', '/\"/');
    $replace = array('\\\\\\', '\\\$',  '\`',  '\"'  );


    // Real name of the file
    if($argument[rcsname] != "")
      $name = "$argument[rcsname]";
    else
      $name = "$argument[fichier_name]";
    $archivename =  "$this->_realpath/RCS/$name,v";

    if(file_exists("$archivename") && ($argument[type] == "initial"))
      return(array(code => false, cmd => "erreur",
		   msg => "You ask for initial revision but archive name exist."));

    if($argument[revision])
      $options = "$options -r$argument[revision]";
    if($argument[log])
      $options = "$options -m\""  . preg_replace($pattern, $replace, $argument[log]) . "\"";
    if($argument[description])
      $options = "$options -t-\"" . preg_replace($pattern, $replace, $argument[description]) . "\"";

    // location of the uploaded file
    $fichier = TmpDIR  . "/$name";

    // making the command line
    putenv("PHP_REMOTE_USER_LOGIN=" . REMOTE_LOGIN);
    $command = "mv $argument[fichier] \"$fichier\" && chmod 666 \"$fichier\"";
    if(!is_dir("$this->_realpath/RCS"))
      $command = "$command && " . WRAPPER . " mkdir --mode 0775 \"$this->_realpath/RCS\"";
    $command = "$command && " . WRAPPER . " ci $options \"$fichier\" \"$archivename\"";
    if($argument[type] == "initial")
      $command = "$command && " . WRAPPER . " rcs -a" . BASE_acl . " \"$archivename\"";
    exec("( $command ) 2>&1" , $flow, $code);

    // prepare results message
    $result[code] = $code == 0;
    $result[cmd] = preg_replace("/\&\&/", "&&\n", $command);
    $result[msg] = "";
    while(list($k,$v) = each($flow)) $result[msg] .= "$v\n";
    return($result);
  }/* checkin()*/

  /**
   * Réalise un CheckOut du fichier spécifié dans ce système RCS
   */
  function checkout($argument)
  {
    $result = array();
    $flow = array();
    $options = "";
    $name = $argument[file];
		
    if($argument[revision])	  $options = "$options -r$argument[revision]";
    if($argument[verou] == "yes") $options = "$options -l";
    
    switch($argument[destination])
    {
      case "download" :
	$dir = TmpDIR;
	//$tmpfile = "/tmp/phpRCSmanager/" + microtime();
	if(!checkTmpDIR())
	  return(array(msg => "can't use tmp folder: $dir"));

	if(is_file("$dir/$name"))
	  if(!unlink("$dir/$name"))
	    return(array(msg => "can't delete $dir/$name"));
	break;

      case "url" :
	$dir = $this->_realpath;
	if(is_file("$dir/$name"))
	  $command = WRAPPER . " rm \"$dir/$name\" && ";
	break;
    }

    // making the command line
    putenv("PHP_REMOTE_USER_LOGIN=" . REMOTE_LOGIN);
    $command = $command . WRAPPER . " co $options \"$dir/$name\" \"$this->_realpath/RCS/$name,v\"";
    exec("( $command ) 2>&1" , $flow, $code);
    if(code == 0)
      $result[id] = $name;
    
    $result[code] = $code == 0;
    $result[cmd] = preg_replace("/\&\&/", "&&\n", $command);
    $result[msg] = "";
    while(list($k,$v) = each($flow)) $result[msg] .= "$v\n";

    return($result);
  }/* checkout()*/

  /**
   * Construit la tables des fichiers RCS du répertoire
   * @return Table liste d'objet: "RCSFile".
   */
  function getFilesTable()
  {
    // teste de base
    if(!$this->_valid) return (array());
		
    exec("cd \"$this->_realpath\"; rlog -t RCS/*", $flow, $code);
    if($code != 0) return(array());
    $table = $this->parseFilesListing($flow);

    $result = array();
    reset($table);
    while(list($k,$v) = each($table))
      $result[$v["Workingfile"]] = new RCSFile($v["Workingfile"], $this->_path ,$v);
		
    return($result);
  }/* getFilesTable() */

  /**
   * Crée un object "RCSFile" avec toutes les infos données par rlog
   * @param $name nom du fichier
   * @return Object:RCSFile
   */
  function getFile($name)
  {
    // teste de base
    if(!$this->_valid) return (array());
    
    exec("cd \"$this->_realpath\"; rlog \"$name\"", $flow, $code);
    if($code != 0) return(array());

    //$file->addAttribut("logs", $this->parserLogs($flow));
    $table = $this->parseFilesListing($flow);
    return(new RCSFile($table[0]["Workingfile"], $this->_path ,$table[0]));
  }/* logFile() */


  /**
   * Parse le détail des révisions
   * @param $input le flux d'entrée des logs d'un fichier
   * @return Table chaque entrée correspondant a une révision, la clé étant son numéro.
   */
  function parseLogs($input)
  {
    $final = array();
    do{
      // matche une ligne remplie de "-"
      if(preg_match("/^\-{23,}$/",$v))
      {
	list($k,$v) = each($input);
	// récupère les infos de la première lignes.
	$mask = "/^(revision )([0-9]+(?:\.[0-9]+)+)(?:\t(locked by: )(.*)|)$/";
	preg_match($mask, $v, $matches);
	$number = $matches[2]; // numéro de révision
	$locker = $matches[4]; // Utilisateur vérouillant
	$result = "";
	while(!preg_match("/(^\={23,}$)|(^\-{23,}$)/", $v))
	{
	  $result = "$result$v\n";
	  list($k,$v) = each($input);
	}
	prev($input);
	$final[$number] = $result;
			}
    }while((list($k,$v) = each($input)) && !preg_match("/^\={23,}$/",$v));
    return($final);	
  }/*parseLogs()*/

  /**
   * Parser du listing généré par "rlog"
   * @param $Input le flux d'entrée
   * @return Table chaque entrée correspondant à un fichier.
   */
  function parseFilesListing($input)
  {
    reset($input);
    $finalResult = array();
    $result = array();

    //Parcours du tableau
    while(list($k,$v) = each($input))
    {
      // coupe la chaine de caracteres en plusieurs sous chaine
      $valeur=explode(":", $v);
      $valeur[0]=ereg_replace(" ", "", $valeur[0]);
      $tmp = array();
      switch($valeur[0])
      {
	// traitement des champs multiples
      case "locks" :
      case "accesslist" :
      case "symbolicnames":
	$champs = trim($valeur[0]);
	$tmp["attrib"]=trim($valeur[1]);
	list($k,$v) = each($input);
	while(preg_match("/^\t/",$v))
	  {
	    //$valeur = explode(":",$v);
	    //$tmp[trim($valeur[0])] = trim($valeur[1]);
	    $tmp[] = trim($v);
	    list($k,$v) = each($input);
	  }
	prev($input);
	$result[$champs] = $tmp;
	break;
	
	// traitement du champs description
      case "description" :
	list($k,$v) = each($input);
	$description = "";
	while(!preg_match("/(^\={23,}$)|(^\-{23,}$)/", $v))
	  {
	    $description = "$description\n$v";
	    list($k,$v) = each($input);
	  }
	$result["description"] = $description;
	// Y a t'il les logs des révisions ?
	if(preg_match("/^\-{23,}$/", $v)) 
	  {
	    prev($input);
	    $result["logs"] = $this->parseLogs($input);
	  }else
	    $result["logs"] = array();
	each($input);
	// Termine le fichier courrant
	$resultFinal[] = $result;
	$result = array();
	break;
	
      case "":
	break;
	
	// Affectation des valeurs a chaque champs du tableau
      default:
	$result[trim($valeur[0])]=trim($valeur[1]);
      }/*switch()*/
    }/*while()*/
    return($resultFinal);
  }/*parseFilesListing()*/
  
}/*class RCS*/

?>
Return current item: RCS Man on the Web