openrat-cms

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

commit 4a3ae679a2e70a459eef8e5974d69e6ab211b97a
parent f2f11fd26d6902f7ab78b50fcb8a038df47d19e7
Author: dankert <devnull@localhost>
Date:   Sat,  6 Oct 2007 01:31:32 +0200

Bei Fehlersituationen kein Abbruch, sondern nur Status OK auf false setzen.

Diffstat:
serviceClasses/Ftp.class.php | 196++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
serviceClasses/Publish.class.php | 188++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------
2 files changed, 266 insertions(+), 118 deletions(-)

diff --git a/serviceClasses/Ftp.class.php b/serviceClasses/Ftp.class.php @@ -31,9 +31,11 @@ class Ftp { var $verb; var $url; - var $log = ''; + var $log = array(); var $mode=FTP_ASCII; - var $passive = false; + var $passive = false; + + var $ok = true; // Konstruktor @@ -48,62 +50,59 @@ class Ftp { $this->url = $url; - global $db, - $SESS, - $t_project; - + global $conf; + + $conf_ftp = $conf['publish']['ftp']; $ftp = parse_url( $this->url ); - // Wenn kein Port vorgegeben, dann Port 21 verwenden - if ( empty($ftp['port']) ) - $ftp['port'] = '21'; + // Die projektspezifischen Werte gewinnen bei Überschneidungen mit den Default-Werten + $ftp = array_merge($conf_ftp,$ftp); // Nur FTP und FTPS (seit PHP 4.3) erlaubt - if ( !ereg('^ftps?$',$ftp['scheme']) ) - die( 'unknown scheme in FTP Url: '.$ftp['scheme'] ); + if ( !ereg('^ftps?$',$ftp['scheme']) ) + { + $this->log[] = 'Unknown scheme in FTP Url: '.$ftp['scheme']; + $this->log[] = 'Only FTP (and FTPS, if compiled in) are supported'; + $this->ok = false; + return; + } - $this->verb = ftp_connect( $ftp['host'],$ftp['port'] ); + if ( function_exists('ftp_ssl_connect') && $ftp['scheme'] == 'ftps' ) + $this->verb = ftp_ssl_connect( $ftp['host'],$ftp['port'] ); + else + $this->verb = ftp_connect( $ftp['host'],$ftp['port'] ); if ( !$this->verb ) { - error('ERROR_FTP','ERROR_FTP_CANNOT_CONNECT_TO_SERVER','Cannot connect to '.$ftp['host'].':'.$ftp['port']); + $this->log[] = 'Cannot connect to '.$ftp['scheme'].'-server '.$ftp['host'].':'.$ftp['port']; + $this->ok = false; + + Logger::error('Cannot connect to '.$ftp['host'].':'.$ftp['port']); + return; } - $this->log .= 'connecting ...'."\n"; - $this->log .= 'host: '.$ftp['host']."\n"; - $this->log .= 'port: '.$ftp['port']."\n"; - - $erg = ftp_login( $this->verb,$ftp['user'],$ftp['pass'] ); - - if ( !$erg ) + $this->log[] = 'Connected to FTP server '.$ftp['host'].':'.$ftp['port']; + + if ( empty($ftp['user']) ) + $ftp['user'] = 'anonymous'; + + if ( ! ftp_login( $this->verb,$ftp['user'],$ftp['pass'] ) ) { - error('ERROR_FTP','ERROR_FTP_CANNOT_LOGIN','cannot login user: '.$ftp['user']); + $this->log[] = 'Unable to login as user '.$ftp['user']; + $this->ok = false; + return; } - - $this->log .= 'ok'."\n"; - $this->log .= 'login ...'."\n"; - $this->log .= 'user: '.$ftp['user']."\n"; - $this->log .= 'ok'."\n"; - - if ( !empty($ftp['fragment']) && $ftp['fragment'] == 'passive' ) - { - $this->log .= 'entering passive mode'."\n"; - $erg = ftp_pasv( $this->verb,true ); + + $this->log[] = 'Logged in as user '.$ftp['user']; - if ( !$erg ) - { - error('ERROR_FTP','ERROR_FTP_CANNOT_PASV_ON'); - } - } - else + $pasv = (!empty($ftp['fragment']) && $ftp['fragment'] == 'passive' ); + + $this->log[] = 'entering passive mode '.($pasv?'on':'off'); + if ( ! ftp_pasv($this->verb,true) ) { - $this->log .= 'no passive mode'."\n"; - $erg = ftp_pasv( $this->verb,false ); - - if ( !$erg ) - { - error('ERROR_FTP','ERROR_FTP_CANNOT_PASV_OFF'); - } + $this->log[] = 'cannot switch PASV mode'; + $this->ok = false; + return; } if ( !empty($ftp['query']) ) @@ -115,81 +114,114 @@ class Ftp $site_commands = explode( ',',$ftp_var['site'] ); foreach( $site_commands as $cmd ) { - $this->log .= 'exec SITE command: '.$cmd."\n"; - ftp_site( $this->verb,$cmd ); + $this->log .= 'executing SITE command: '.$cmd; + + if ( ! @ftp_site( $this->verb,$cmd ) ) + { + $this->log[] = 'unable to do SITE command: '.$cmd; + $this->ok = false; + return; + } } } } $this->path = ereg_replace( '\/$','',$ftp['path']); - $this->log .= 'Change directory to '.$this->path.'...'."\n"; - $erg = ftp_chdir( $this->verb,$this->path ); - - - if ( !$erg ) + $this->log[] = 'Changing directory to '.$this->path; + + if ( ! @ftp_chdir( $this->verb,$this->path ) ) { - error('ERROR_FTP','ERROR_FTP_UNABLE_TO_CHDIR','could not CHDIR to '.$this->path ); - } - $this->log .= 'ok'."\n"; - - - //echo "pwd ist".ftp_pwd( $this->verb ); + $this->log[] = 'unable CHDIR to directory: '.$this->path; + $this->ok = false; + return; + } } - + + /** + * Kopieren einer Datei vom lokalen System auf den FTP-Server. + * + * @param String Quelle + * @param String Ziel + * @param int FTP-Mode (BINARY oder ASCII) + */ function put( $source,$dest,$mode=FTP_BINARY ) - { + { + if ( ! $this->ok ) + return; + $ftp = parse_url( $this->url ); $dest = $this->path.'/'.$dest; $this->log .= "Copying file: $source -&gt; $dest ...\n"; + if ( !@ftp_put( $this->verb,$dest,$source,$this->mode ) ) { - $this->log .= "Copying FAILED, checking path: ".dirname($dest)."\n"; - - $erg = $this->mkdirs( dirname($dest) ); - - if ( !$erg ) - { - error('ERROR_FTP','ERROR_FTP_UNABLE_TO_MKDIR','cannot create directoriy '.$ftp['path'].'/'.dirname($dest) ); - } + if ( !$this->mkdirs( dirname($dest) ) ) + return; // Fehler. ftp_chdir( $this->verb,$this->path ); - $erg = ftp_put( $this->verb,$dest,$source,$mode ); - - if ( !$erg ) + if ( ! @ftp_put( $this->verb,$dest,$source,$mode ) ) { - error('ERROR_FTP','ERROR_FTP_UNABLE_TO_COPY','put failed from '.$source.' to '.$dest ); + $this->ok = false; + $this->log[] = 'FTP PUT failed...'; + $this->log[] = 'source : '.$source; + $this->log[] = 'destination: '.$dest; + return; } } } - - - // Rekursives Anlagen von Verzeichnisse + + + /** + * Private Methode zum rekursiven Anlegen von Verzeichnissen. + * + * @param String Pfad + * @return boolean true, wenn ok + */ function mkdirs( $strPath ) { - echo $strPath.'<br>'; if ( @ftp_chdir($this->verb,$strPath) ) - return true; - + return true; // Verzeichnis existiert schon :) + $pStrPath = dirname($strPath); + if ( !$this->mkdirs($pStrPath) ) return false; - $this->log .= "Creating directory: $strPath ...\n"; - //echo "lege an $strPath ...<br>"; - return ftp_mkdir($this->verb,$strPath); + if ( ! @ftp_mkdir($this->verb,$strPath) ) + { + $this->ok = false; + $this->log[] = "failed to create remote directory: $strPath"; + } + + return $this->ok; } - + + + /** + * Schließen der FTP-Verbindung.<br> + * Sollte unbedingt aufgerufen werden, damit keine unnötigen Sockets aufbleiben. + */ function close() { - ftp_quit( $this->verb ); + if ( !$this->ok ) // Noch alles ok? + return; + + if ( ! @ftp_quit( $this->verb ) ) + { + // Das Schließen der Verbindung hat nicht funktioniert. + // Eigentlich könnten wir das ignorieren, aber wir sind anständig und melden eine Fehler. + $this->log[] = 'failed to close connection'; + $this->ok = false; + return; + } } } diff --git a/serviceClasses/Publish.class.php b/serviceClasses/Publish.class.php @@ -34,29 +34,52 @@ class Publish var $content_negotiation = false; var $cut_index = false; var $cmd_after_publish = ''; - var $publishedObjects = array(); + var $publishedObjects = array(); + var $log = array(); + var $ok = true; // Konstruktor function Publish() - { + { + global $conf; + $conf_project = $conf['publish']['project']; + $project = Session::getProject(); - if ( !empty($project->ftp_url) ) + if ( !empty($project->ftp_url) || isset($conf['publish']['ftp']['host']) ) { + $this->with_ftp = true; $this->ftp = new Ftp( $project->ftp_url ); - $this->with_ftp = true; - + + if ( ! $this->ftp->ok ) + { + $this->ok = false; + $this->log = $this->ftp->log; + return; + } + $this->ftp->passive = ( $project->ftp_passive == '1' ); } - $this->local_destdir = ereg_replace( '\/$','',$project->target_dir); + $localDir = ereg_replace( '\/$','',$project->target_dir); + if ( empty( $localDir)) + $localDir = $project->name; + + if ( $conf_project['override_publish_dir'] && $localDir != basename($localDir) ) + $this->local_destdir = $localDir; + else + $this->local_destdir = $conf_project['publish_dir'].$localDir; + // Sofort pruefen, ob das Zielverzeichnis ueberhaupt beschreibbar ist. if ( $this->local_destdir != '' ) { if ( !is_writeable( $this->local_destdir ) ) - { - die( 'directory not writable: '.$this->local_destdir ); + { + $this->ok = false; + $this->log[] = 'directory not writable: '.$this->local_destdir; + $this->log[] = 'please correct the file permissions.'; + return; } $this->with_local = true; @@ -65,47 +88,89 @@ class Publish $this->content_negotiation = ( $project->content_negotiation == '1' ); $this->cut_index = ( $project->cut_index == '1' ); - $this->cmd_after_publish = $project->cmd_after_publish; + $this->cmd_after_publish = $project->cmd_after_publish; + // Variablen ersetzen + str_replace('{name}' ,$project->name ,$this->cmd_after_publish); + str_replace('{dir}' ,$this->local_destdir ,$this->cmd_after_publish); + str_replace('{dirbase}',basename($this->local_destdir),$this->cmd_after_publish); } - + + + + /** + * Kopieren einer Datei aus dem temporären Verzeichnis in das Zielverzeichnis.<br> + * Falls notwenig, wird ein Hochladen per FTP ausgeführt. + * + * @param String $tmp_filename + * @param String $dest_filename + */ function copy( $tmp_filename,$dest_filename ) - { + { + if ( !$this->ok) + return; + global $conf; $source = $tmp_filename; if ( $this->with_local ) { - $dest = $this->local_destdir.'/'.$dest_filename; - //echo "$source &gt; $dest<br>"; + $dest = $this->local_destdir.'/'.$dest_filename; + if (!@copy( $source,$dest )); { - $this->mkdirs( dirname($dest) ); + if ( ! $this->mkdirs( dirname($dest) ) ) + return; - if (!copy( $source,$dest )) - { - die('failed writing file: '.$dest); + if (!@copy( $source,$dest )) + { + $this->ok = false; + $this->log[] = 'failed copying local file:'; + $this->log[] = 'source : '.$source; + $this->log[] = 'destination: '.$dest; + return; } } - + // CHMOD auf der Datei ausgeführen. if (!empty($conf['security']['chmod'])) - chmod($dest,octdec($conf['security']['chmod'])); + { + if ( ! @chmod($dest,octdec($conf['security']['chmod'])) ) + { + $this->ok = false; + $this->log[] = 'Unable to CHMOD file '.$dest; + return; + } + } } - if ( $this->with_ftp ) + if ( $this->with_ftp ) // Falls FTP aktiviert { $dest = $dest_filename; - $this->ftp->put( $source,$dest,FTP_ASCII ); + $this->ftp->put( $source,$dest,FTP_ASCII ); + + if ( ! $this->ftp->ok ) + { + $this->ok = false; + $this->log[] = $this->ftp->log; + } } } + - - // Rekursives Anlagen von Verzeichnisse - // Nett gemacht. - // Quelle: http://de3.php.net/manual/de/function.mkdir.php - // Thx to acroyear at io dot com + + /** + * Rekursives Anlagen von Verzeichnisse + * Nett gemacht. + * Quelle: http://de3.php.net/manual/de/function.mkdir.php + * Thx to acroyear at io dot com + * + * @param String Verzeichnis + * @return boolean + */ function mkdirs( $strPath ) - { + { + global $conf; + if ( is_dir($strPath) ) return true; @@ -113,31 +178,82 @@ class Publish if ( !$this->mkdirs($pStrPath) ) return false; - //echo "lege an: $strPath<br>"; - return @mkdir($strPath,0755); + if ( ! @mkdir($strPath,0777) ) + { + $this->ok = false; + $this->log[] = 'Cannot create directory: '.$strPath; + return false; + } + + // CHMOD auf dem Verzeichnis ausgeführen. + if (!empty($conf['security']['chmod_dir'])) + { + if ( ! @chmod($strPath,octdec($conf['security']['chmod_dir'])) ) + { + $this->ok = false; + $this->log[] = 'Unable to CHMOD directory: '.$strPath; + return false; + } + } + + + return $this->ok; } - + + /** + * Beenden des Veröffentlichungs-Vorganges.<br> + * Eine vorhandene FTP-Verbindung wird geschlossen.<br> + * Falls entsprechend konfiguriert, wird ein Systemkommando ausgeführt. + */ function close() { if ( $this->with_ftp ) { $this->ftp->close(); } - - if ( !empty($this->cmd_after_publish) ) - exec( $this->cmd_after_publish ); + + // Ausführen des Systemkommandos. + if ( !empty($this->cmd_after_publish) && $this->ok ) + { + $ausgabe = array(); + $rc = false; + exec( $this->cmd_after_publish,$ausgabe,$rc ); + + if ( $rc != 0 ) + { + $this->log = $ausgabe; + $this->ok = false; + } + } } + + /** + * Aufräumen des Zielverzeichnisses.<br><br> + * Es wird der komplette Zielordner samt Unterverzeichnissen durchsucht. Jede + * Datei, die länger existiert als der aktuelle Request alt ist, wird gelöscht.<br> + * Natürlich darf diese Funktion nur nach einem Gesamt-Veröffentlichen ausgeführt werden. + */ function clean() - { + { + if ( $this->ok ) + return; + if ( !empty($this->local_destdir) ) $this->cleanFolder($this->local_destdir); } - - + + + + /** + * Aufräumen eines Verzeichnisses.<br><br> + * Dateien, die länger existieren als der aktuelle Request alt ist, werden gelöscht.<br> + * + * @param String Verzeichnis + */ function cleanFolder( $folderName ) { $dh = opendir( $folderName );