ich habe selbst einige Jahre an einem eigenen CMS-System entwickelt. Nun bin ich aus synergie-effekten auf contenido umgestiegen.
Schade finde ich, dass sich Contenido och icht ohne Safe_mode betreiben lässt, wobei das doch eingentlich eines der geringsten Probleme ist, eine Software so zu schreiben, das Sie auch ohne Safemode funktioniert.
(Klar, große Sprüche kann jeder klopfen ... komme aber gleich zu einem Lösungsansatz)
Ich weiß nicht, wie genau Contenido technsich aufgebaut ist, da ich noch bei einer intensiven Einarbeitung und Handbucherstellung für die Verwaltung von Contenido stecke. Jedoch habe ich bei meinem alten CMS-System das Problem so gelößt:
Mein altes System hatte alle SQL-Befehlt in einer Datenbank-Schnittstellen-Klasse (AppDbManager.class) gekapselt. Über diese Klasse wurden alle Datenbankverbindungen aufgebaut und verwaltet. So ist es unter anderem möglich, mit der Änderung dieser einene Klasse auch andere Datenbanken zu unterstützen (interportabilität)
Nun zum Safe_Mode:
Ich habe eine Schnittstellen-Klasse (FtpManager.class) geschreiben, die von der Datenbank-Schnittstelle erbt. In dieser FTP-Klasse handle ich dann Verbindungen zum eigenen Server, die eine Dummy-Datei dort positionieren.
Die Dummy-Datei ist wichtig, da man im Safe_Mode Dateien umbenennen und bearbeiten kann. So öffne ich im zweiten Schritt die Dummy-Datei und fülle Sie mit den Inhalten, wie es beliebt.
Programmiertechnisch ist das nicht viel mehr Aufwand als das normale erzeugen oder kopieren einer Datei, da dies dann anstatt über einen php-Befehl (mkdir) über eine eigene Funktion erzeugt wird, die auf FtpManager.class zugreift (z mkFtpDir() ).
Anbei ein Codebeispiel für die FtpManager-Klasse:
und hier noch ein Beispiel für eine Funktion, die auf diese Klasse zugreift... mein ehemaliger Template-Parser (es wurde analog zur Verzeichnisstruktur auf wunsch auch eine physikalische Struktur erzeugt)FtpManager.class
<?php
/*______________________________________________________________________________
* @(#)FtpManager.class.php
* Datum : 03.06.2004
* Letzte Änderung :
* geändert von : Samuel Suther
* Art der Änderung :
* Version : 0.5_beta
*______________________________________________________________________________
*/
include_once(dirname(__FILE__)."/ConnectionManager.class.php");
class FtpManager extends AppDbManager
{
//------------------------------------------------------------------------------
// KONSTANTEN
//------------------------------------------------------------------------------
/* Die Folgenden Werte werden als Kostanten abgelegt,
* damit sie waehrend der Laufzeit nicht mehr veraendert werden koennen.
*/
var $FTP_USER =""; // Benutzername fuer den FTP-Zugang
var $FTP_PASSWD =""; // Passwort fuer den FTP-Zugang
var $FTP_SERVER =""; // URL des FTP-Servers (Standart-URL: 127.0.0.1)
var $FTP_PORT ="21"; // PORT des FTP-Zugang (Standartport: 21)
//------------------------------------------------------------------------------
// PROPERTIES
//------------------------------------------------------------------------------
var $ftpStatus = false; // Kontrollflag ob Verbindung besteht
var $errorM = null; // Fehler Meldung (Text)
var $statusM = null; // Meldung des aktuellen Verarbeitungsstatus
var $theConnection = null; // FTP-Verbindung
var $persObj = null; // PeristenzObjekt
var $resultNum = null; // Anzahl der gefundenen Datensätze
var $result = null; // Datensaetze der Abfrage
var $debug = 1; // Debugausgabe fuer Entwicklung (Fehlerausgabe inkl. exit) (1|0)
//------------------------------------------------------------------------------
/**
* FtpManager Konstruktor
* @param PersObj - PersistenzObjekt (alle Objekte, die
* das Interface "PersistenzIF" implementieren)
**/
function FtpManager($inPersObj)
{
$this->persObj = $inPersObj;
if($ftpStatus == FALSE)
{
if(!$this->theConnection = ConnectionManager::getFtpConnection($this->FTP_SERVER,$this->FTP_PORT,$this->FTP_USER,$this->FTP_PASSWD))
{
$this->setErrorMsg("Die Verbindung zum FTP-Server konnte nicht hergestellt werden");
}
else $this->ftpStatus = TRUE;
$this->setStatusMsg("Aktuelles Verzeichnis:".ftp_pwd($this->theConnection)."<br>");
}
}
/**
* getFtpVerz Methode
* gibt das aktuelle Verzeichnis aus
**/
function getFtpVerz()
{
return ftp_pwd($this->theConnection);
}
/**
* changeFtpVerz Methode
* wechselt von dem aktuellen in das angegebene Verzeichnis
* @ $ftpVerz = Pfad zum Verzeichnis (ohne beginnenden "/")
**/
function changeFtpVerz($ftpVerz)
{
if(!@ftp_chdir($this->theConnection,$ftpVerz))
$this->setErrorMsg("Kann nicht in das Zielverzeichnis $ftpVerz wechseln.");
}
/**
* mkFtpVerz Methode
* erstellt ein neues Verzeichnis
* @ $newFtpVerz = vollständiger Verzeichnisname (wird kein Pfad angegeben, wird das Verzeichnis direkt im FTP-Root erzeugt)
**/
function mkFtpVerz($newFtpVerz)
{
if(!@ftp_mkdir($this->theConnection,$newFtpVerz))
$this->setErrorMsg("Das Verzeichnis $newFtpVerz konnte nicht angelegt werden.");
}
/**
* mkFtpVerz Methode
* löscht ein bestehendes Verzeichnis
* @ $newFtpVerz = vollständiger Verzeichnisname (wird kein Pfad angegeben, wird das Verzeichnis direkt im FTP-Root erzeugt)
**/
function rmFtpVerz($delFtpVerz)
{
if(!@ftp_rmdir($this->theConnection,$delFtpVerz))
$this->setErrorMsg("Das Verzeichnis $delFtpVerz konnte nicht gelöscht werden.");
}
/**
* getFtpFileList Methode
* gibt eine Liste der Dateien in dem entsprechenden Verzeichnis zurück
* @ $listFtpVerz = vollständiger Dateiname
**/
# später in Array zurückgeben Verzeichnis,Dateiname, größe, letzte Änderung usw.
function getFtpFileList($listFtpVerz)
{
$name = @ftp_nlist($this->theConnection, $listFtpVerz);
if(isset($name) and is_array($name))
{
reset($name);
while(list($k,$v)=each($name))
{
printf("%s - %s<br>\n", $k, $v);
}
}
}
/**
* getFtpFileSize Methode
* gibt die Dateigröße der im Parameter angegebenen Datei zurück.
* @ $ftpFile = vollständiger Dateiname
**/
function getFtpFileSize($ftpFile)
{
if(!$size=@ftp_size($this->theConnection, $ftpFile))
$this->setErrorMsg("Die angegebene Datei konnte nicht gefunden werden.");
return $size;
}
/**
* getFtpFile Methode
* lädt eine Datei vom FTP-Server.
* @ $localFileName = bestimmt den Dateinamen im aktuellen Verzeichnis
* @ $remoteFileName = hochzuladende Datei (ggf. inkl. Pfadangaben)
* @ $mode = Übertragungsart 2 Konstanten möglich (FTP_ASCII | FTP_BINARY)
* ACHTUNG, nicht als String übergeben, nur Konstante angeben (ohne Präfix $)
**/
function getFtpFile($localFileName,$remoteFileName,$mode)
{
$result = ftp_get($this->theConnection, $localFileName, $remoteFileName, $mode);
if (!$result)
$this->setErrorMsg("Download der Datei $remoteFileName fehlgeschlagen.");
else
$this->setStatusMsg("Download der Datei $remoteFileName erfolgreich.");
}
/**
* putFtpFile Methode
* überträgt eine Datei auf den FTP-Server.
* @ $localFileName = bestimmt den Dateinamen im aktuellen Verzeichnis
* @ $remoteFileName = hochzuladende Datei (ggf. inkl. Pfadangaben)
* @ $mode = Übertragungsart 2 Konstanten möglich (FTP_ASCII | FTP_BINARY)
* ACHTUNG, nicht als String übergeben, nur Konstante angeben (ohne Präfix $)
**/
function putFtpFile($remoteFileName,$localFileName,$mode)
{
ftp_pasv($this->theConnection,$cfgSystem["ftp_passiv"]);
$result=ftp_put($this->theConnection, $remoteFileName, $localFileName, $mode);
if(!$result)
{
$this->setErrorMsg("Upload der Datei $remoteFileName fehlgeschlagen.");
return true;
}
else
{
$this->setStatusMsg("Upload der Datei $remoteFileName erfolgreich.");
return true;
}
}
/**
* chmodFtpFile Methode
* überträgt eine Datei auf den FTP-Server.
* @ $ftpFile = Dateinamen, dessen Zugriffsrechte geändert werden sollen
* @ $parm = Änderungsstring (linux z.B. 775)
**/
function chmodFtpFile($ftpFile,$parm)
{
if (!@ftp_site($this->theConnection, "chmod $parm $ftpFile"))
{
$this->setErrorMsg("Dateirechte für $remoteFileName konnten nicht verändert werden.");
return true;
}
else
{
$this->setStatusMsg("Dateirechte für $remoteFileName wurden verändert.");
return false;
}
}
/**
* closeFtpSession Methode
* beendet die aktuelle FTP-Sitzung
**/
function closeFtpSession()
{
ConnectionManager::setFtpConnectionFree();
}
//------------------------------------------------------------------------------
/**
* getlastError Methode
* gibt die als letztes aufgetretene Fehlermeldung aus.
* @return Fehlermeldung (Text)
**/
function getLastError()
{
return $this->errorM;
}
//------------------------------------------------------------------------------
/**
* getlastStatus Methode
* gibt eine Stausmeldung des als letztes aufgetretenen Ereignisses aus.
* @return Statusmeldung (Text)
**/
function getStatus()
{
return $this->statusM;
}
//------------------------------------------------------------------------------
// Properties
//------------------------------------------------------------------------------
/**
* setErrorMsg Property
* @ $inErrM - FTP-Felermeldung
**/
function setErrorMsg($inErrM)
{
$this->ftpStatus = FALSE;
$this->errorM = trim($inErrM);
}
/**
* setErrorMsg Property
* @ $inErrM - FTP-Felermeldung
**/
//------------------------------------------------------------------------------
function setStatusMsg($inMsg)
{
$this->statusM = trim($inMsg);
}
//------------------------------------------------------------------------------
} // END_CLASS FtpManager
//------------------------------------------------------------------------------
Auf diese Art hat mein System - das ja durch die Erstellung aller in der Datebbank abgelegten Strukturen als physikalischen Verzeichnisbaum, sehr viel mit Dateierstellung zu tun hatte- immer tadellos funktioniert.//------------------------------------------------------------------------------
/**
* writeTemplate Methode
* Oeffnet eine Datei mit dem Template-Dateinamen mit der Endung ".tmp"
* (falls nicht vorhanden wird diese angelegt!) und schreibt in ihr
* den Inhalt dieses Templates
**/
function writeTemplate($fileDir, $fileName, $fileType, $output)
{
extract($_SESSION,EXTR_REFS);
$cached_file = $cfgSystem["site_path"].$sep.$fileName.$fileType;
$cached_dir = $cfgSystem["site_path"].$sep.$fileDir;
$safe_mode = $cfgSystem["safe_mode"];
$dirHandle = @opendir($cached_dir);
// Konfiguration auslesen, ob safe_mode on|off, wenn on, dann FTP-aktivieren
// um Dateischreibrechte zu umgehen
if($safe_mode==1)
{
include_once(dirname(__FILE__)."/FtpManager.class.php");
$ftpManager = new FtpManager($this); // FTP-Session starten und User Anmelden
}
//Prüfen ob Verzeichnis besteht, sonst anlegen
if(!$dirHandle)
{
$verzErrMsg = "Verzeichnis ".$cached_dir."konnte nicht erstellt werden!";
//Verzeichnis erstellen
if($safe_mode==1)
{
if($cfgSystem["baseDir"]==1)
{
$cached_dir_FTP=str_replace($cfgSystem["slice_ftproot"],".",$cached_dir);
$ftpManager->mkFtpVerz($cached_dir_FTP);
$ftpManager->chmodFtpFile($cached_dir_FTP,"777");
}else
{
$ftpManager->mkFtpVerz($cached_dir);
$ftpManager->chmodFtpFile($cached_dir,"777");
}
}
if($safe_mode==0)
{
if(!mkdir($cached_dir,0700)) echo $verzErrMsg;
}
}else @closedir($dirHandle);
if($safe_mode==1)
{
/* Bei FTP-Upload: Dummydatei auf den Server laden,
* um Inhalt mit fopen einfügen zu können und Zugriffsberechtigung zu haben
* Wenn Basedir gesetzt wurde, schneide das vom Pfad weg, was vor dem baseDir liegt
* Beipsiel:
* Vorher: /srv/www/htdocs/<domain>/html
* Nachher:/html
*/
//
if($cfgSystem["baseDir"]==1)
{
$cached_file_FTP=str_replace($cfgSystem["slice_ftproot"],".",$cached_file);
$ftpManager->putFtpFile($cached_file_FTP,$cfgSystem["ftp_dummy"],FTP_ASCII);
$ftpManager->chmodFtpFile($cached_file_FTP,"777");
}
else
{
$ftpManager->putFtpFile($cached_file,$cfgSystem["ftp_dummy"],FTP_ASCII);
$ftpManager->chmodFtpFile($cached_file,"777");
}
}
$fp = fopen($cached_file, "w") or die("Kann Datei ".$cached_file." nicht finden / öffnen");
if($safe_mode==0)
{
// Zugriffsrechte für UNIX/Linux setzten
@chmod ($cached_file, 0777) or die ($cached_file.": konnte Zugriffsberechtigungen rwx-rwx-rwx nicht setzen.<br> Bitte Servereinstellung des Safe_mode prüfen. Ggf. in Konfinguration anpassen!");
}
// Template-String in die Datei schreiben:
// Schreibe in die ersten Zeilen alle nötigen include.
$inc = "<?php\n";
$inc.= "include_once(dirname(__FILE__).\"/".$this->relPfad."admin/classes/classes.inc.php\");\n";
$inc.= "include_once(dirname(__FILE__).\"/".$this->relPfad."admin/functions/site_functions.inc.php\");\n";
$inc.= "if(!site_get_onlineStatus() )
{
\$template_id = site_cfg_get_value_from_key(\"SITE_OFFLINE_PAGE_ID\");
\$siteFactory = new SiteFactory(\$template_id,0);
\$siteFactory->createSite(true);
exit;
}else{\n";
$inc.= "@session_start(); // Session-Starten\n";
$inc.= "\$PAGE_ID='".$this->node_id.".php';\n";
$inc.= "@session_start();\n";
$inc.= "\$_SESSION['PAGE_ID']=\$PAGE_ID;";
$inc.= "?>\n";
$inc.= $output;
$inc.="<?}?>";
fputs($fp, $inc);
// Datei schliessen und Lock aufgeben
fclose($fp);
//Zugriffsberechtigung zurücksetzen
if($safe_mode==0)
{ // Zugriffsrechte für UNIX/Linux setzten
@chmod ($cached_file, 0755) or die ($cached_file.": konnte Zugriffsb. rwx-rwx-rwx nicht setzen.<br> Bitte Servereinstellung des Safe_mode prüfen. Ggf. in Konfinguration anpassen!");
}else
{
if($cfgSystem["baseDir"]==1)
{
$ftpManager->chmodFtpFile($cached_file_FTP,"755");
}
else
{
$ftpManager->chmodFtpFile($cached_file,"755");
}
}
}
Wäre toll, wenn Ihr das ins Contendio übernehmen könntet, denn bis ich ans entwickeln bzw. weiterentwickeln von Contenido komme, dauert es noch ein paar wochen...
Sollte es bis dahin noch nicht eingepflegt sein, erstelle ich diese Funktion gerne selbst...
Bei Fragen, oder dem wunsch nach näheren Informationien einfach hier posten.