<?php

class update
{
   /*
   *	Fehlercodes:
   *
   *	0: OK
   *	1: File not found
   *	2: Error backup/rollback
   *	3: Cannot chmod
   *	100: Failed to execute command
   *	200: Parse Error: nothing to parse
   */

   var $errno = 0;

   /*
   *
   *	Script
   *
   */

   var $script_pattern = ' :: ';
   var $script_checksum = 'md5';
   var $script_name = '';
   var $script_path = '';
   var $script_critical = true;
   var $script = '';

   function __construct ();
   {
   }

   /* Interpreter */

   function load_script ( $file = '' )
   {
      clear_errno();
      if ( check_file_exists( $file ) ) return $this -> errno;
      $this -> script = file ($file);
      if ( strlen ($this -> script)>0 )
      {
         $this -> script_path = dirname ($file);
         $this -> script_name = basename ($file);
      }
      return;
   }

   function parse_script ()
   {
      clear_errno();
      $this -> script_critical = true;
      if ( strlen ($this -> script) == 0 )
      {
         $this -> set_errno(2);
         return 2;
      }
      /* Splittet die Zeile in Command / Option / Checksumme (md5, sha1 etc.) */
      $lines = array();
      $n = 0;
      foreach $this -> script as $row
      {
         $line = explode($this -> script_pattern,$row);
         $lines[$n]['command'] = $line[0];
         $lines[$n]['option'] = $line[1];
         $n++;
      }
      while ( list( $command,$option )=each( $lines ) && $this -> errno == 0)
      {
         /* Befehle mit Rollback */
         if ( $command == 'copy' && $this -> f_copy ($lines[$n]['option']) >0 ) $this -> file_rollback($lines[$n]['option']);
         if ( $command == 'delete' && $this -> f_delete ($lines[$n]['option']) >0 ) $this -> file_rollback($lines[$n]['option']);

         /* Befehle ohne Rollback, da ein Fehlschlag keine Änderung mit sich bringt */
         if ( $command == 'chmod' ) $this -> f_chmod ($lines[$n]['option']);
         if ( $command == 'mkdir' ) $this -> f_mkdir ($lines[$n]['option']);
         if ( $command == 'rmdir' ) $this -> f_rmdir ($lines[$n]['option']);
         if ( $command == 'sql' ) $this -> f_sql ($lines[$n]['option']);
         if ( $command == 'unpack' ) $this -> f_unpack ($lines[$n]['option']);
         if ( $command == 'sync' ) $this -> f_sync ($lines[$n]['option']);

         /* Log */
         if ( $command == 'log' ) $this -> f_log ($lines[$n]['option']);

         /* Setzt oder Löscht die Fehlerbehandlung */
         if ( $command == 'critical' && ( $option == 'true' ||  $option == '1' ) ) $this -> f_critical ();
         if ( $command == 'critical' && ( $option == 'false' ||  $option == '0' ) ) $this -> f_uncritical ();
         if ( ! $this -> script_critical && $this -> errno > 0 ) $this -> clear_errno();
      }

      if ( $this -> errno == 0 ) $this -> cleanup();

      return $this -> errno;
   }

   /* Primäre Funktionen */

   function f_copy ( $options = '' )
   {

      /*
      *	ToDo: Code für Checksumme
      */

      clear_errno();

      // Erster Test, ob String $file nicht leer ist.
      if ( $options == '' ) return $this -> set_errno(1);

      // Prüft auf Leerzeichen, da dort eine Checksumme hinterlegt sein könnte.
      $line = explode(' ',$options);
      $file = (( count( $line )>0 )?$line[0]:$options;
      if ( $line[1] ) $checksum = $line[1]; // Hiernach sollte der Teil mit der Überprüfung stehen

      // Quelle
      $source = BASE.'/'.$this -> script_path.'/files/'.$file;
      // Ziel
      $target = BASE.'/'.$file;

      // Test auf Quelle
      if ( check_file_exists( $source ) ) return $this -> errno;
      // Backup des Targets ohne Auswertung der Rückgabe, da auch noch nicht existerende Ziele behandelt werden müssen.
      $this -> file_backup( $target );
      // Kopiert Quelle nach Ziel. Bei Fehler wird Fehlercode 100 ("Failed to execute command") zurückgegeben.
      return (( ! copy ($source, $target) )?$this -> set_errno(100):0);
   }

   function f_delete ( $file='' )
   {
      /*
      *	Alias für file_backup(). Das Löschen erfolgt erst durch die Funktion cleanup().
      */
      return $this -> file_backup ($file);
   }

   function f_mkdir ( $directory = '')
   {
      clear_errno();
      if ( check_dir_exists( $directory ) ) return $this -> errno;
      mkdir ($directory);
      return;
   }

   function f_rmdir ( $directory = '')
   {
      clear_errno();
      if ( check_dir_exists( $directory ) ) return $this -> errno;
      rmdir ($directory);
      return;
   }

   function f_chmod ( $options = '')
   {
      clear_errno();

      // Prüft auf Leerzeichen, da File/Rechte-Kombination
      $line = explode(' ',$options);
      $name = (( count( $line )>0 )?$line[0]:$options;

      if ( ! $line[1] || $line[1] == 0 )
      {
         $this -> set_errno(3);
         return 3;
      }

      if ( check_dir_exists( $name ) || check_file_exists( $name ) ) return $this -> errno;

      chmod ( $name, $mod );
      return;
   }

   function f_sql ( $sqlscript = '' )
   {
      /*
      *	ToDo: Liest das SQL-Script aus und gibt es an die Datenbank weiter.
      */
   }

   function f_log ( $text = '' )
   {
      /*
      *	ToDo: Schreibt ein Text in ein Logfile oder in die entsprechende Tabelle. Sollte auch von den anderen f_*()-Funktionen genutzt werden!
      */
   }

   function f_unpack ( $file = '' )
   {
      /*
      *	ToDo: Extrahiert ein Archiv
      */
   }

   function f_sync ( $options = '' )
   {
      /*
      *	ToDo: Synchronisiert die angegebene Tabelle.Spalte mit dem Verzeichnis rekursiv mit (true=fullpath, rekursiv) oder ohne Pfadangabe (false=filename, flat)
      */
   }

   function f_critical ()
   {
      /*
      *	Setzt das Flag für systemkritische Befehle. Wenn das Flag gesetzt ist, bricht das Update sofort ab.
      */
      $this -> script_critical = true;
   }

   function f_uncritical ()
   {
      /*
      *	Lösct das Flag für systemkritische Befehle. Wenn das Flag gelöscht ist, wird der nächste Befehl ausgeführt.
      */
      $this -> script_critical = false;
   }

   /* Private Funktionen */

   private function clear_errno ()
   {
         $this -> errno = 0;
	 return 0;
   }

   private function set_errno ( $errno = 0 )
   {
         $this -> errno = $errno;
	 return $errno;
   }

   private function file_backup ( $file= '' )
   {
      $this -> errno = 0;
      if ( check_file_exists( $file ) ) return $this -> errno;
      if ( rename $file $file.".bak" )
      {
         $this -> set_errno(2);
         return 2;
      }
   }

   private function file_rollback ( $file= '' )
   {
      if ( check_file_exists( $file ) ) return $this -> errno;
      if ( rename $file.".bak" $file )
      {
         $this -> set_errno(2);
         return 2;
      }
   }

   private function check_dir_exists ( $directory = '' )
   {
      $this -> errno = (($directory == '' || ! is_dir($directory))?1:0);
      return $this -> errno;
   }

   private function check_file_exists ( $file = '' )
   {
      $this -> errno = (($file == '' || ! is_file($file))?1:0);
      return $this -> errno;
   }

   private function cleanup ()
   {
      /*
      *	ToDo: Lösche alle Backups
      */
   }
}
?>