$formel_str
+ * @var mixed $spieler_adminbereich_hilfsadmin_fuer_spalten
+ * @var mixed $spieler_adminbereich_hilfsadmin_zulassen
+ * @var mixed $spieler_adminbereich_standard_sortierung
+ * @var mixed $spieler_anzeige_pro_seite
+ * @var mixed $spieler_extra_sortierspalte
+ * @var mixed $spieler_nullwerte_anzeigen
+ * @var mixed $spieler_standard_richtung
+ * @var mixed $spieler_standard_sortierung
+ * @var mixed $spieler_vereinsweise_anzeigen
+ * @var mixed $wert
+ */
+
if (isset($_REQUEST['sort_direction'])) {
$stats_sort_direction = $_REQUEST['sort_direction'];
} else {
@@ -283,7 +309,7 @@
}
break;
case 'delcolumn':
- if ($wert > 0) {
+ if ($wert > 0 && isset($spalten[$wert])) {
$filepointer = @fopen($filename, 'w+b');
stream_set_write_buffer($filepointer, 0);
if ($formel[$wert]) $formel_ges--;
@@ -564,8 +590,8 @@ function mark(el) {
- >
+ for ($j = 0; $j <= $ligaDaten->anzteams; $j++) {?>
+ teams[$j]) == $data[$j1][$j2]) echo ' selected';?>>teams[$j]);?>
@@ -711,7 +737,7 @@ function cmpstrlength ($a, $b) {
}
function formel_berechnen ($formel, $formel_str,$spalten) {
- global $data;
+ global $data, $text;
uasort($spalten, 'cmpstrlength');
for ($i = 0; $i < count($spalten); $i++) {
if ($formel[$i]) {
@@ -724,7 +750,6 @@ function formel_berechnen ($formel, $formel_str,$spalten) {
}
}
$help_str = strtr($help_str, '+-*/0123456789.(),', ' ');
- echo (chop($help_str));
if (strlen(trim($help_str)) == 0 || trim($help_str) == 'MAX' || trim($help_str) == 'MIN') {
$formel_str[$i] = '$help2 = round(' . $formel_str[$i] . ', 2);';
} else {
@@ -740,6 +765,9 @@ function formel_berechnen ($formel, $formel_str,$spalten) {
@eval($formel_str[$i]);
} catch (\DivisionByZeroError $e) {
$help2 = 0.0;
+ } catch (\Throwable $e) {
+ // unvollstaendige Formel (z.B. "Tore/"): Fehlertext statt Abbruch der Seite
+ $help2 = $text['spieler'][55];
}
$data[$j][$i] = $help2;
}
diff --git a/lmo/addon/spieler/lmo-statloadconfig.php b/lmo/addon/spieler/lmo-statloadconfig.php
index 3def391e..4cca8b5c 100644
--- a/lmo/addon/spieler/lmo-statloadconfig.php
+++ b/lmo/addon/spieler/lmo-statloadconfig.php
@@ -21,6 +21,9 @@
*
*
*/
+if (!defined('PATH_TO_LMO')) {
+ exit; // kein Direktaufruf: diese Datei wird nur ueber LMO eingebunden
+}
//Datei auslesen
$filename = basename($file);
diff --git a/lmo/addon/spieler/lmo-statprint.php b/lmo/addon/spieler/lmo-statprint.php
index 06cf97b2..f0ad3e24 100644
--- a/lmo/addon/spieler/lmo-statprint.php
+++ b/lmo/addon/spieler/lmo-statprint.php
@@ -25,18 +25,19 @@
//Konfiguration laden
require(PATH_TO_ADDONDIR . '/spieler/lmo-statloadconfig.php');
-$sort = isset($_GET['sort']) ? $_GET['sort'] : $spieler_standard_sortierung;
+// Zahlen aus der Anfrage als Zahlen behandeln: mit ihnen wird gerechnet
+$sort = (int)(isset($_GET['sort']) ? $_GET['sort'] : $spieler_standard_sortierung);
if (isset($_GET['begin'])) {
- $begin = $_GET['begin'];
+ $begin = max(0, (int)$_GET['begin']);
$all = false;
} else {
$begin = 0;
$all = true;
}
-$direction = isset($_GET['direction']) ? $_GET['direction'] : $spieler_standard_richtung;
+$direction = (int)(isset($_GET['direction']) ? $_GET['direction'] : $spieler_standard_richtung);
$team = isset($_GET['team']) ? urldecode($_GET['team']) : '';
-if ($filepointer = fopen($filename, 'r+b')) {
+if (is_readable($filename) && $filepointer = fopen($filename, 'r+b')) {
$spalten = array(); // Spaltenbezeichnung
$data = array(); // Daten
$typ = array(); // Spaltentyp (true=String)
@@ -52,6 +53,10 @@
}
}
if ($formel) fgetcsv($filepointer, separator: '#', escape: ''); // Zeile mit Formeln
+ // Sortierspalte aus der Anfrage oder Konfiguration muss es in der Statistik geben
+ if (!isset($spalten[$sort])) {
+ $sort = 0;
+ }
$linkspalte = array_search($text['spieler'][32], $spalten); // Linkunterstützung aktiviert?
@@ -117,7 +122,7 @@
diff --git a/lmo/addon/spieler/lmo-statshow.php b/lmo/addon/spieler/lmo-statshow.php
index 82e7f98e..23cd38ae 100644
--- a/lmo/addon/spieler/lmo-statshow.php
+++ b/lmo/addon/spieler/lmo-statshow.php
@@ -20,13 +20,32 @@
require_once(__DIR__ . '/../../init.php');
+/**
+ * Diese Datei wird direkt aufgerufen; init.php stellt bereit:
+ *
+ * @var \Lmo\Liga\LigaDaten $ligaDaten Daten der geladenen Liga (lmo-ligadaten.php)
+ * @var array $text Sprachtexte
+ * @var string $file Ligadatei relativ zum Ligenordner, leer wenn keine geladen ist
+ * @var string $action gewaehlte Seite (Aufrufparameter)
+ *
+ * Einstellungen:
+ * @var int|string $spieler_anzeige_pro_seite Einstellung aus spieler/cfg.txt
+ * @var int|string $spieler_extra_sortierspalte Einstellung aus spieler/cfg.txt
+ * @var int|string $spieler_nullwerte_anzeigen Einstellung aus spieler/cfg.txt
+ * @var int|string $spieler_standard_richtung Einstellung aus spieler/cfg.txt
+ * @var int|string $spieler_standard_sortierung Einstellung aus spieler/cfg.txt
+ * @var int|string $spieler_vereinsweise_anzeigen Einstellung aus spieler/cfg.txt
+ */
+
//Konfiguration laden
require(PATH_TO_ADDONDIR . '/spieler/lmo-statloadconfig.php');
-$sort = isset($_GET['sort']) ? $_GET['sort'] : $spieler_standard_sortierung;
-$begin = isset($_GET['begin']) ? $_GET['begin'] : 0;
-$direction = isset($_GET['direction']) ? $_GET['direction'] : $spieler_standard_richtung;
+// Zahlen aus der Anfrage als Zahlen behandeln: sie werden zum Rechnen und in Links verwendet
+$sort = (int)(isset($_GET['sort']) ? $_GET['sort'] : $spieler_standard_sortierung);
+$begin = max(0, (int)(isset($_GET['begin']) ? $_GET['begin'] : 0));
+$direction = (int)(isset($_GET['direction']) ? $_GET['direction'] : $spieler_standard_richtung);
$team = !empty($_GET['team']) ? urldecode($_GET['team'] ): '';
+$team_link = htmlspecialchars(urlencode($team));
if (!isset($filename)) {
$filename = $_GET['file'];
@@ -48,6 +67,10 @@
}
}
if ($formel) fgetcsv($filepointer, separator: '#', escape: ""); // Zeile mit Formeln
+ // Sortierspalte aus der Anfrage oder Konfiguration muss es in der Statistik geben
+ if (!isset($spalten[$sort])) {
+ $sort = 0;
+ }
$linkspalte = array_search($text['spieler'][32], $spalten); // Linkunterstützung aktiviert?
@@ -109,18 +132,18 @@
+ for ($i = 0; $i < count($ligaDaten->teams) - 1; $i++) {
+ $ligaDaten->teams[$i] = stripslashes($ligaDaten->teams[$i]);?>
- ">teams[$i] != $team) { ?>
+ teams[$i];?>"> teamk[$i];
+ if ($ligaDaten->teams[$i] != $team) { ?>
-
+ teams[$i], ' alt=""'); ?>
@@ -139,7 +162,7 @@
" title=""> " title=""> ';
@@ -150,7 +173,7 @@
} //Ende der Suche nach Bildern für die Spaltenüberschriften
if ($spieler_extra_sortierspalte == 0) {
?>" title=""> " title="">
" align="center">= 0) {
- ?>"><< "><< "><< "><< | "> | | "> | "> >> "> >>
@@ -211,10 +234,10 @@
if ($spalten[$j2] == $text['spieler'][25]) {
echo '
';
- $pos = array_search($data[$j1][$j2], $teamu);
+ $pos = array_search($data[$j1][$j2], $ligaDaten->teamu);
echo HTML_icon($data[$j1][$j2], 'teams', 'small') . str_replace(' ', ' ', $data[$j1][$j2]) . ' ';
- if (!empty($pos) && $teamu[$pos] != '' && $urlt == 1) {
- echo ' ';
+ if (!empty($pos) && $ligaDaten->teamu[$pos] != '' && $ligaDaten->urlt == 1) {
+ echo ' ';
}
//Spielerlinks
@@ -252,10 +275,10 @@
- ">
+ ">
- ">
+ ">
@@ -270,11 +293,11 @@
- ">
+ ">
- ">
+ ">
diff --git a/lmo/addon/ticker/ticker.php b/lmo/addon/ticker/ticker.php
index 7f28cae4..6955a765 100644
--- a/lmo/addon/ticker/ticker.php
+++ b/lmo/addon/ticker/ticker.php
@@ -20,19 +20,37 @@
require_once(__DIR__ . '/../../init.php');
+/**
+ * Diese Datei wird direkt aufgerufen; init.php stellt bereit:
+ *
+ * @var \Lmo\Liga\LigaDaten $ligaDaten Daten der geladenen Liga (lmo-ligadaten.php)
+ * @var array $text Sprachtexte
+ * @var string $dirliga Ligenordner relativ zum LMO (Konfiguration)
+ *
+ * Einstellungen:
+ * @var int|string $ticker_standard_ligen Einstellung aus ticker/cfg.txt
+ *
+ * Werden auch in dieser Datei gesetzt, aber nicht auf jedem Weg (koennen von aussen kommen):
+ * @var mixed $ticker_breite
+ * @var mixed $ticker_geschwindigkeit
+ * @var mixed $ticker_notizanzeigen
+ * @var mixed $ticker_tickerart
+ * @var mixed $ticker_tickertitel
+ */
+
// Durch gesetzte $tickerart bestimmter Parameter (für include/require)
$ticker_tickerart = isset($tickerart) ? $tickerart : $ticker_tickerart;
$ticker_ligen = isset($tickerligen) ? $tickerligen : $ticker_standard_ligen;
$ticker_tickertitel = isset($tickertitel) ? $tickertitel : $ticker_tickertitel;
$ticker_notizanzeigen = isset($tickernotizen) ? $tickernotizen : $ticker_notizanzeigen;
-$ticker_breite = isset($tickerbreite) ? $breite : $ticker_breite;
-$ticker_geschwindigkeit = isset($tickergeschwindigkeit) ? $geschwindigkeit : $ticker_geschwindigkeit;
+$ticker_breite = isset($tickerbreite) ? $tickerbreite : $ticker_breite;
+$ticker_geschwindigkeit = isset($tickergeschwindigkeit) ? $tickergeschwindigkeit : $ticker_geschwindigkeit;
$trenner = ' +++ ';
$array = array();
-$msieg = 0;
+$ligaDaten->msieg = 0;
$hilf = $hilf1 = '';
-$ticker_text = $mnote = $dummy1 = $dummy2 = $dummy3 = $dummy4 = '';
+$ticker_text = $ligaDaten->mnote = $dummy1 = $dummy2 = $dummy3 = $dummy4 = '';
?>
@@ -52,85 +70,89 @@
$ticker_array = explode(",", $ticker_ligen);
foreach($ticker_array as $file) {
+ // je Liga neu beginnen: sonst stehen die Spiele der vorigen Ligen noch einmal bei der naechsten
+ $hilf = $hilf1 = '';
require(PATH_TO_LMO . '/lmo-openfile.php');
- if (isset($lmtype)) {
+ // lmo-openfile.php laesst bei einer fehlenden Liga die Daten der vorigen stehen
+ if (isset($ligaDaten->lmtype) && $file != '' && file_exists(PATH_TO_LMO . '/' . $dirliga . $file)) {
if($ticker_tickerart == 2) {
- if (isset($nlines)) {
- for($i = 0; $i < count($nlines); $i++) {
- if(strlen($nlines[$i]) > 0)
- $hilf .= $trenner . $nlines[$i];
+ if (isset($ligaDaten->nlines)) {
+ for($i = 0; $i < count($ligaDaten->nlines); $i++) {
+ if(strlen($ligaDaten->nlines[$i]) > 0)
+ $hilf .= $trenner . $ligaDaten->nlines[$i];
}
}
$ticker_text .= $hilf;
}
else {
- if ($lmtype == 0) {
- for ($i = 0; $i < $anzsp; $i++) {
- if (($teama[$stx-1][$i] > 0) && ($teamb[$stx-1][$i] > 0) ) {
- if ($mspez[$stx-1][$i] == ' ') {
+ if ($ligaDaten->lmtype == 0) {
+ for ($i = 0; $i < $ligaDaten->anzsp; $i++) {
+ if (($ligaDaten->teama[$ligaDaten->stx-1][$i] > 0) && ($ligaDaten->teamb[$ligaDaten->stx-1][$i] > 0) ) {
+ if ($ligaDaten->mspez[$ligaDaten->stx-1][$i] == ' ') {
$mspezhilf = '';
}
else {
- $mspezhilf = ' ' . $mspez[$stx-1][$i];
+ $mspezhilf = ' ' . $ligaDaten->mspez[$ligaDaten->stx-1][$i];
}
- if ($favteam == $teama[$stx-1][$i] || $favteam == $teamb[$stx-1][$i] || $ticker_tickerart == 1) {
- if ($msieg[$stx-1][$i] == 1) {
- $dummy1 = $text['ticker'][2] . ':' . addslashes($teams[$teama[$stx-1][$i]] . ' ' . $text[211]);
+ if ($ligaDaten->favteam == $ligaDaten->teama[$ligaDaten->stx-1][$i] || $ligaDaten->favteam == $ligaDaten->teamb[$ligaDaten->stx-1][$i] || $ticker_tickerart == 1) {
+ if ($ligaDaten->msieg[$ligaDaten->stx-1][$i] == 1) {
+ $dummy1 = $text['ticker'][2] . ':' . addslashes($ligaDaten->teams[$ligaDaten->teama[$ligaDaten->stx-1][$i]] . ' ' . $text[211]);
}
else {
$dummy1 = '';
}
- if ($msieg[$stx-1][$i] == 2) {
- $dummy2 = $text['ticker'][2] . ':' . addslashes($teams[$teamb[$stx-1][$i]] . ' ' . $text[211]);
+ if ($ligaDaten->msieg[$ligaDaten->stx-1][$i] == 2) {
+ $dummy2 = $text['ticker'][2] . ':' . addslashes($ligaDaten->teams[$ligaDaten->teamb[$ligaDaten->stx-1][$i]] . ' ' . $text[211]);
}
else {
- $dumm2y = '';
+ $dummy2 = '';
}
- if ($msieg[$stx-1][$i] == 3) {
+ if ($ligaDaten->msieg[$ligaDaten->stx-1][$i] == 3) {
$dummy3 = $text['ticker'][2] . ':' . addslashes($text['ticker'][3]);
}
else {
$dummy3 = '';
}
- if ($mnote[$stx-1][$i] != '' && $ticker_notizanzeigen == 1) {
- $dummy4 = ' Notiz' . ': ' . $mnote[$stx-1][$i];
+ if ($ligaDaten->mnote[$ligaDaten->stx-1][$i] != '' && $ticker_notizanzeigen == 1) {
+ $dummy4 = ' Notiz' . ': ' . $ligaDaten->mnote[$ligaDaten->stx-1][$i];
}
else {
$dummy4 = '';
}
- $hilf = $hilf . $teams[$teama[$stx-1][$i]] . " - " . $teams[$teamb[$stx-1][$i]] . " " . applyFactor($goala[$stx-1][$i], $goalfaktor) . ":" . applyFactor($goalb[$stx-1][$i], $goalfaktor) . $mspezhilf . $dummy1 . $dummy2 . $dummy3 . $dummy4 . $trenner;
+ $hilf = $hilf . $ligaDaten->teams[$ligaDaten->teama[$ligaDaten->stx-1][$i]] . " - " . $ligaDaten->teams[$ligaDaten->teamb[$ligaDaten->stx-1][$i]] . " " . applyFactor($ligaDaten->goala[$ligaDaten->stx-1][$i], $ligaDaten->goalfaktor) . ":" . applyFactor($ligaDaten->goalb[$ligaDaten->stx-1][$i], $ligaDaten->goalfaktor) . $mspezhilf . $dummy1 . $dummy2 . $dummy3 . $dummy4 . $trenner;
}
}
} // for ($i = 0; $i < $anzsp; $i++)
}
else {
- for ($i = 0; $i < $anzsp; $i++) {
- for ($n = 0; $n < $modus[$stx-1]; $n++) {
- if (($teama[$stx-1][$i] > 0) && ($teamb[$stx-1][$i] > 0) ) {
- if ($mspez[$stx-1][$i][$n] == ' ') {
+ for ($i = 0; $i < $ligaDaten->anzsp; $i++) {
+ for ($n = 0; $n < $ligaDaten->modus[$ligaDaten->stx-1]; $n++) {
+ if (($ligaDaten->teama[$ligaDaten->stx-1][$i] > 0) && ($ligaDaten->teamb[$ligaDaten->stx-1][$i] > 0) ) {
+ if ($ligaDaten->mspez[$ligaDaten->stx-1][$i][$n] == ' ') {
$mspezhilf = '';
}
else {
- $mspezhilf = ' ' . $mspez[$stx-1][$i][$n];
+ $mspezhilf = ' ' . $ligaDaten->mspez[$ligaDaten->stx-1][$i][$n];
}
- if ($favteam == $teama[$stx-1][$i] || $favteam == $teamb[$stx-1][$i] || $ticker_tickerart == 1) {
- if ($mnote[$stx-1][$i][$n] != '' && $notizanzeigen == 1) {
- $dummy4 = ' ' . $text[22] . ': ' . $mnote[$stx-1][$i][$n];
+ if ($ligaDaten->favteam == $ligaDaten->teama[$ligaDaten->stx-1][$i] || $ligaDaten->favteam == $ligaDaten->teamb[$ligaDaten->stx-1][$i] || $ticker_tickerart == 1) {
+ if ($ligaDaten->mnote[$ligaDaten->stx-1][$i][$n] != '' && $ticker_notizanzeigen == 1) {
+ $dummy4 = ' ' . $text[22] . ': ' . $ligaDaten->mnote[$ligaDaten->stx-1][$i][$n];
}
else {
$dummy4 = '';
}
- $hilf1 = $hilf1 . $teams[$teama[$stx-1][$i]] . " - " . $teams[$teamb[$stx-1][$i]] . " " . applyFactor($goala[$stx-1][$i][$n], $goalfaktor) . ":".applyFactor($goalb[$stx-1][$i][$n], $goalfaktor) . $mspezhilf . $dummy4 . $trenner;
+ $hilf1 = $hilf1 . $ligaDaten->teams[$ligaDaten->teama[$ligaDaten->stx-1][$i]] . " - " . $ligaDaten->teams[$ligaDaten->teamb[$ligaDaten->stx-1][$i]] . " " . applyFactor($ligaDaten->goala[$ligaDaten->stx-1][$i][$n], $ligaDaten->goalfaktor) . ":".applyFactor($ligaDaten->goalb[$ligaDaten->stx-1][$i][$n], $ligaDaten->goalfaktor) . $mspezhilf . $dummy4 . $trenner;
}
}
}
}
}
}
- $ticker_text .= " $trenner $titel ($stx{$text['ticker'][1]}): $hilf $hilf1";
+ $ticker_text .= " $trenner {$ligaDaten->titel} ({$ligaDaten->stx}{$text['ticker'][1]}): $hilf $hilf1";
}
else {
- $ticker_text = $text[224] . $trenner;
+ // anhaengen statt ersetzen: eine fehlende Liga loescht nicht den Text der anderen
+ $ticker_text .= $text[224] . $trenner;
}
} //foreach
$ticker_formnumber = 't' . substr(md5(microtime()), 3, 4);
diff --git a/lmo/addon/tipp/lmo-admintipp.php b/lmo/addon/tipp/lmo-admintipp.php
index 52fccf24..887789b3 100644
--- a/lmo/addon/tipp/lmo-admintipp.php
+++ b/lmo/addon/tipp/lmo-admintipp.php
@@ -16,6 +16,9 @@
* REMOVING OR CHANGING THE COPYRIGHT NOTICES IS NOT ALLOWED!
*
*/
+if (!defined('PATH_TO_LMO')) {
+ exit; // kein Direktaufruf: diese Datei wird nur ueber LMO eingebunden
+}
$save = isset($_REQUEST['save']) ? $_REQUEST['save'] : 0;
$liga = isset($_REQUEST['liga']) ? $_REQUEST['liga'] : '';
diff --git a/lmo/addon/tipp/lmo-admintippbenachrichtigung.php b/lmo/addon/tipp/lmo-admintippbenachrichtigung.php
index ae2fb1d8..09fa410a 100644
--- a/lmo/addon/tipp/lmo-admintippbenachrichtigung.php
+++ b/lmo/addon/tipp/lmo-admintippbenachrichtigung.php
@@ -16,17 +16,15 @@
* REMOVING OR CHANGING THE COPYRIGHT NOTICES IS NOT ALLOWED!
*
*/
+if (!defined('PATH_TO_LMO')) {
+ exit; // kein Direktaufruf: diese Datei wird nur ueber LMO eingebunden
+}
require_once (PATH_TO_ADDONDIR . '/tipp/lmo-tipptest.php');
-require_once (PATH_TO_LMO . '/includes/PHPMailer.php');
-$mail = new PHPMailer(true);
+$mail = lmo_mailer($aadr, $text['tipp'][92]);
$tipp_mailtext = str_replace(array('\n', '[nick]'), array("\n", $xtippernick), $text['tipp'][303]);
-$mail->isMail();
-$mail->CharSet = 'UTF-8';
-$mail->Encoding = 'base64';
$mail->Subject = $text['tipp'][13] . ' (' . $_SERVER['HTTP_HOST'] . ')';
-$mail->setFrom($aadr, $text['tipp'][92]);
$mail->Body = $tipp_mailtext;
$mail->addAddress($aadr, $text['tipp'][92]);
diff --git a/lmo/addon/tipp/lmo-admintippemail.php b/lmo/addon/tipp/lmo-admintippemail.php
index cd775c39..f883e062 100644
--- a/lmo/addon/tipp/lmo-admintippemail.php
+++ b/lmo/addon/tipp/lmo-admintippemail.php
@@ -16,6 +16,9 @@
* REMOVING OR CHANGING THE COPYRIGHT NOTICES IS NOT ALLOWED!
*
*/
+if (!defined('PATH_TO_LMO')) {
+ exit; // kein Direktaufruf: diese Datei wird nur ueber LMO eingebunden
+}
require_once(PATH_TO_LMO."/lmo-admintest.php");
diff --git a/lmo/addon/tipp/lmo-admintippfreischaltung.php b/lmo/addon/tipp/lmo-admintippfreischaltung.php
index 6994e065..52621069 100644
--- a/lmo/addon/tipp/lmo-admintippfreischaltung.php
+++ b/lmo/addon/tipp/lmo-admintippfreischaltung.php
@@ -1,4 +1,7 @@
isMail();
-$mail->CharSet = 'UTF-8';
-$mail->Encoding = 'base64';
$mail->Subject = $text['tipp'][77] . ' (' . $_SERVER['HTTP_HOST'] . ')';
-$mail->setFrom($aadr, $text['tipp'][92]);
$mail->Body = $tipp_mailtext;
$mail->addAddress($xtipperemail, $xtippernick);
diff --git a/lmo/addon/tipp/lmo-admintippgetoptions.php b/lmo/addon/tipp/lmo-admintippgetoptions.php
index fc259a6c..f662659d 100644
--- a/lmo/addon/tipp/lmo-admintippgetoptions.php
+++ b/lmo/addon/tipp/lmo-admintippgetoptions.php
@@ -1,4 +1,7 @@
+
loadFile(PATH_TO_LMO . '/' . $dirliga . $ligen_datei) == true) { // Ligenfile vorhanden?
- $file_ligen_datei = file(chop(PATH_TO_LMO . '/ligen/' . $ligen_datei));
if ($ligen_datei != $doppelt_check) {
$doppelt_check = $ligen_datei;
$zz++;
diff --git a/lmo/addon/viewer/viewer.php b/lmo/addon/viewer/viewer.php
index 47d8e3c1..ca39fbfe 100644
--- a/lmo/addon/viewer/viewer.php
+++ b/lmo/addon/viewer/viewer.php
@@ -65,7 +65,9 @@
//check if one of the leagues is newer than the cache file
$i = 1;
while (isset($multi_cfgarray['liga' . $i])) {
- if (filemtime(PATH_TO_LMO . '/' . $diroutput . 'viewer_' . $multi . '.txt') < filemtime(PATH_TO_LMO . '/' . $dirliga . $multi_cfgarray['liga' . $i])) {
+ // beim ersten Aufruf gibt es die Cache-Datei noch nicht (filemtime() warnte dann)
+ $viewer_cache_filename = PATH_TO_LMO . '/' . $diroutput . 'viewer_' . $multi . '.txt';
+ if (!file_exists($viewer_cache_filename) || filemtime($viewer_cache_filename) < filemtime(PATH_TO_LMO . '/' . $dirliga . $multi_cfgarray['liga' . $i])) {
$viewer_cache_counter = 0;
}
$i++;
@@ -99,7 +101,7 @@
$anzahl_ligen = --$i;
$template_file = $multi_cfgarray['template'];
- $template = new HTML_Template_IT(PATH_TO_TEMPLATEDIR . '/viewer'); // Template Object
+ $template = new LMO_Template(PATH_TO_TEMPLATEDIR . '/viewer'); // Template Object
$template->loadTemplatefile($template_file . '.tpl.php');
// Template laden
if (isset($multi_cfgarray['titelzeile'])) {
diff --git a/lmo/addon/viewer/viewer_datum.php b/lmo/addon/viewer/viewer_datum.php
index f0e8b42c..a235d184 100644
--- a/lmo/addon/viewer/viewer_datum.php
+++ b/lmo/addon/viewer/viewer_datum.php
@@ -17,6 +17,9 @@
*
*
*/
+if (!defined('PATH_TO_LMO')) {
+ exit; // kein Direktaufruf: diese Datei wird nur ueber LMO eingebunden
+}
$startzeit = zeitberechnung('1', - $multi_cfgarray['anzahl_tage_minus']);
$endzeit = zeitberechnung('2', $multi_cfgarray['anzahl_tage_plus']);
diff --git a/lmo/addon/viewer/viewer_functions.php b/lmo/addon/viewer/viewer_functions.php
index c5f8164c..924a92b6 100644
--- a/lmo/addon/viewer/viewer_functions.php
+++ b/lmo/addon/viewer/viewer_functions.php
@@ -17,6 +17,9 @@
*
*
*/
+if (!defined('PATH_TO_LMO')) {
+ exit; // kein Direktaufruf: diese Datei wird nur ueber LMO eingebunden
+}
function zeitberechnung($modus, $wert) {
// Gibt verschiedene Werte je nach $Modus zurück:
diff --git a/lmo/addon/viewer/viewer_spiel.inc.php b/lmo/addon/viewer/viewer_spiel.inc.php
index b359c44c..9f60430b 100644
--- a/lmo/addon/viewer/viewer_spiel.inc.php
+++ b/lmo/addon/viewer/viewer_spiel.inc.php
@@ -17,6 +17,29 @@
*
*
*/
+if (!defined('PATH_TO_LMO')) {
+ exit; // kein Direktaufruf: diese Datei wird nur ueber LMO eingebunden
+}
+
+/**
+ * Diese Datei wird eingebunden und erwartet:
+ *
+ * @var \Lmo\Liga\LigaDaten $ligaDaten Daten der geladenen Liga (lmo-ligadaten.php)
+ * @var array $text Sprachtexte
+ *
+ * Weitere Variablen des einbindenden Codes:
+ * @var array $fav_liga
+ * @var array $fav_team
+ * @var mixed $i
+ * @var mixed $liga
+ * @var array|null $multi_cfgarray
+ * @var mixed $mySpieltag
+ * @var mixed $partie
+ * @var mixed $template
+ *
+ * Werden auch in dieser Datei gesetzt, aber nicht auf jedem Weg (koennen von aussen kommen):
+ * @var mixed $spieltag
+ */
foreach ($fav_team[$i] as $akt_team) {
if (isset($multi_cfgarray['modus']) && $multi_cfgarray['modus'] == 1) {
@@ -26,13 +49,13 @@
if (($akt_team == $partie->heim->nr) || ($akt_team == $partie->gast->nr)) {
//Anfang Relevante Daten
- $goalfaktor = $liga->options->keyValues['goalfaktor'];
+ $ligaDaten->goalfaktor = $liga->options->keyValues['goalfaktor'];
$template->setVariable('Liganame', $liga->name);
$template->setVariable('Ligadatum', $liga->ligaDatumAsString());
$template->setVariable('Spieltag', $multi_cfgarray['spieltagtext'] . ' ' . $spieltag);
$template->setVariable('Datum', $partie->datumString('-', $multi_cfgarray['datumsformat']));
$template->setVariable('Uhrzeit', $partie->zeitString('-', $multi_cfgarray['uhrzeitformat']));
- $template->setVariable('Tore', $partie->hToreString($multi_cfgarray['tordummy'], $goalfaktor) . ' : ' . $partie->gToreString($multi_cfgarray['tordummy'], $goalfaktor) . ' ' . $partie->spielEndeString($text));
+ $template->setVariable('Tore', $partie->hToreString($multi_cfgarray['tordummy'], $ligaDaten->goalfaktor) . ' : ' . $partie->gToreString($multi_cfgarray['tordummy'], $ligaDaten->goalfaktor) . ' ' . $partie->spielEndeString($text));
//Heim & Gasttore einzeln
$template->setVariable('ToreHeim', $partie->hToreString($multi_cfgarray['tordummy']));
$template->setVariable('ToreGast', $partie->gToreString($multi_cfgarray['tordummy']));
diff --git a/lmo/addon/viewer/viewer_spieltag.php b/lmo/addon/viewer/viewer_spieltag.php
index f5b9d24f..ee34f502 100644
--- a/lmo/addon/viewer/viewer_spieltag.php
+++ b/lmo/addon/viewer/viewer_spieltag.php
@@ -17,6 +17,9 @@
*
*
*/
+if (!defined('PATH_TO_LMO')) {
+ exit; // kein Direktaufruf: diese Datei wird nur ueber LMO eingebunden
+}
$template->setVariable('Spieltageminus', $multi_cfgarray['anzahl_spieltage_zurueck']);
$template->setVariable('Spieltageplus', $multi_cfgarray['anzahl_spieltage_vor']);
diff --git a/lmo/composer.json b/lmo/composer.json
deleted file mode 100644
index 2d46cef9..00000000
--- a/lmo/composer.json
+++ /dev/null
@@ -1,33 +0,0 @@
-{
- "name": "henshingly\/lmo_php8",
- "type": "PHP-Script",
- "description": "The Liga Manager Online (LMO for short) is free software for managing sports leagues with tables on the Internet.",
- "homepage": "https:\/\/github.com\/henshingly\/lmo_php8",
- "version": "4.1.4",
- "time": "2024-10-20",
- "keywords": [
- "LMO",
- "Liga Manager Online",
- "Sportligen verwalten"
- ],
- "license": "GPL-2.0-only",
- "authors": [
- {
- "name": "Rene Marth (joker)",
- "homepage": "https:\/\/www.liga-manager-online.de",
- "role": "Extension developer"
- },
- {
- "name": "Henshingly",
- "homepage": "https:\/\/www.vest-sport.de",
- "role": "Developer"
- }
- ],
- "require": {
- "php": ">=7.4.0"
- },
- "extra": {
- "display-name": "Liga Manager Online",
- "check": "https:\/\/www.vest-sport.de\/check_version.json"
- }
-}
diff --git a/lmo/install/config/cfg.txt b/lmo/config-default/cfg.txt
similarity index 100%
rename from lmo/install/config/cfg.txt
rename to lmo/config-default/cfg.txt
diff --git a/lmo/install/config/classlib/cfg.txt b/lmo/config-default/classlib/cfg.txt
similarity index 100%
rename from lmo/install/config/classlib/cfg.txt
rename to lmo/config-default/classlib/cfg.txt
diff --git a/lmo/install/config/mini/cfg.txt b/lmo/config-default/mini/cfg.txt
similarity index 100%
rename from lmo/install/config/mini/cfg.txt
rename to lmo/config-default/mini/cfg.txt
diff --git a/lmo/install/config/spieler/cfg.txt b/lmo/config-default/spieler/cfg.txt
similarity index 100%
rename from lmo/install/config/spieler/cfg.txt
rename to lmo/config-default/spieler/cfg.txt
diff --git a/lmo/install/config/ticker/cfg.txt b/lmo/config-default/ticker/cfg.txt
similarity index 100%
rename from lmo/install/config/ticker/cfg.txt
rename to lmo/config-default/ticker/cfg.txt
diff --git a/lmo/install/config/tipp/cfg.txt b/lmo/config-default/tipp/cfg.txt
similarity index 100%
rename from lmo/install/config/tipp/cfg.txt
rename to lmo/config-default/tipp/cfg.txt
diff --git a/lmo/help/Deutsch/addons/pdf_addon.txt b/lmo/help/Deutsch/addons/pdf_addon.txt
deleted file mode 100644
index aa396b2c..00000000
--- a/lmo/help/Deutsch/addons/pdf_addon.txt
+++ /dev/null
@@ -1,310 +0,0 @@
-# this is the text which will end up within readme.pdf, when processed
-# by readme.php.
-#
-# the syntax being used is fairly obvious:
-#
-# a line starting with '#' is a comment or a directive
-# 1 is a first level heading (text is 'title')
-# 2 is a second level heading (text is 'heading')
-#
-# the table of contents is automatically generated from the titles and headings.
-#
-# "#NP" starts a new page
-# "#C" starts a code section (put this on a line by itself
-# "#c" end the code section
-# "#X" and "#x" surround a block which will be executed as php code.
-#
-# can be used within the text with gleeful abandon
-#
-# a link can be added within the text using label
-1
-
-Dieses PDF Addon Paket enthält den offiziellen GIT-Klon der R&OS PHP PDF-Klasse und 3 PDF Addons verschiedener Autoren
-
- 1. ROS PHP Pdf creation class
- enthält die Source Dateien der PDF-Klasse
-
- 2. PDF Spielplan von timme
- enthält unter anderem die PDF Ausgabedateien pdf-spielplan.php und pdf-tabelle.php
-
- 3. PDF Teamplan von plastic
- enthält unter anderem die PDF Ausgabedatei pdf-teamplan.php
-
- 4. PDF Teamvergleich von plastic
- enthält unter anderem die PDF Ausgabedatei stats_viewp.php
-
-Dieses Paket wurde von mir neu geschnürt um diverse festgestellte Bugs zu entfernen und die Möglichkeit der Sprachauswahl aller Dateien zu gewährleisten. Außerdem wurde noch die Verwendbarkeit der Addons unter PHP 8 getestet. Bei mir lief es auch unter PHP Version 8.2.4.
-Ich muss außerdem zugeben das ich nicht den originalen LMO 4.0.2a, von der Webseite www.liga-manager-online.de, genommenhabe. Sondern den LMO mit PHP 8 Unterstützung von meiner Webseite. Also alle hier beschriebenen Einstellungen und Codeänderungen beziehen sich auf die LMO_PHP 8 Version.
-#NP
-
-1
-
-
-3<3.0.5>
- 17.03.2019
- - Dateiupdate der R&OS Klasse von 0.12.41 -> 0.12.49
-
-3<3.0.3>
- 03.08.2017
- - Dateiupdate der R&OS Klasse von 0.12.40 -> 0.12.41
- - sortierte Ausgabe der Partien eines Spieltages in pdf-tabelle.php und
- pdf-spielplan.php (wenn in den Grundeistellungen des Ligenfiles dieses
- eingestellt wurde "->Datumssortierung<-". Ansonsten Ausgabe wie in der Adminansicht)
-
-3<3.0.2>
- 19.07.2017
- - Dateiupdate der R&OS Klasse von 0.12.39 -> 0.12.40
- - Ausgabe der Mannschaftsicon in den Tabellen und Spielplänen mittels
- "'name,'teams').' 11>'"
- "'gast->name,'teams').' 9>'" und
- "'heim->name,'teams').' 9>'"
- und dem einfügen einer geänderten HTML_icon Funktion als function HTML_iconPDF()
- und einer function findImage() als function findImagePDF() in die ini.php.
-
-
-3<3.0.1>
- 08.07.2017
- - Dateiupdate der R&OS Klasse von 0.12.38 -> 0.12.39
-
-
-3<3.0rc>
- 28.04.2017
- - Einbindung aller einzelnen Addons in einer Addonoberfläche im Adminmenü
- - Anpassungen an PHP 7
- - Dateiupdate der R&OS PDF-Klasse von 0.11.6 -> 0.12.38
-
-
-3<2.3>
- 10.01.2013
- - Update der alten PDF-Klasse aus dem CSV-Download des LMO's. Von 0.0.9 -> 0.11.6
-
-
-3<2.2>
- 16.12.2012
- - Anpassungen der Originalen PDF Addons aus dem Forum des LMO.
-#NP
-
-1
-
-Die R&OS Pdf-Klasse wird verwendet um PDF-Dokumente mit PHP zu erzeugen. Dabei werden keine zusätzlichen Module oder Erweiterungen installiert. Die R&OS PDF-Klasse kommt mit einer Basisklasse namens "Cpdf.php". Zusätzlich noch mit einer Hilfs-Klasse "Cezpdf.php", um Tabellen zu generieren, Hintergründe hinzuzufügen und Paging zu bieten.
-Ich habe die aktuellste stabile Version in diesen Download integriert. Die im CSV_LMO enthaltene PDF-Klasse ist schon ein sehr alter Vorläufer, mit der Versionnummer: 0.0.9.
-Die neue Version unterstüzt nun auch UTF-8. Bzw. es werden nicht UTF-8 kodierte Strings bei Bedarf automatisch in UTF-8 umgewandelt. Die neuen Dateien der Klasse überschreiben einige alte aus dem Download der CSV-Version des LMO's.
-
-
-2
-Zur Installation des kompletten Pakets dieses zuerst einmal entpacken. Den entpackten Ordner "lmo_root" öffnen nun sollten dort einige Ordner zu sehen sein. Diese heißen -
- - addons
- - config
- - help
- - img
- - lang
-alle Ordner kopieren und in das Hauptverzeichnis deines LMO's einfügen. Es werden nur einige Schriftarten der alten PDF-Klasse von Wayne Munro, R&OS Ltd überschrieben.
-Das PDF-ADDON ist nun integriert. Weiter geht es mit dem Einbinden der Designoberfläche, des PDF-ADDON, in das Adminmenü.
-#NP
-1
-
-2
-
-1. Zuerst einmal wurden alle Dateien schon in Dein LMO Hauptverzeichnis kopiert? Wenn Du diese Frage mit "JA" beantworten kannst dann geht es weiter.
-
-2. Du öffnest mit einem Texteditor die Datei
- - lmo-adminmain.php
- Diese befindet sich im Hauptverzeichnis Deine's LMO's.
-
-1. Änderung
- Die Zeilen 206 - 210 sehen folgendermaßen aus.
-#C
- /*Viewer-Addon*/
- elseif ($todo=="vieweroptions"){
- require(PATH_TO_ADDONDIR."/viewer/lmo-adminvieweroptions.php");
- }
- /*Viewer-Addon*/
-#c
-
- unter die letzte Zeile "/*Viewer-Addon*/" fügst Du folgenden Code ein.
-
-#C
- /*PDF-Addon*/
- elseif ($todo=="pdfoptions"){
- require(PATH_TO_ADDONDIR."/pdf/lmo-adminpdfoptions.inc.php");
- }
- /*PDF-Addon*/
-#c
-
- danach sollte es so aussehen.
-
-#C
- /*Viewer-Addon*/
- elseif ($todo=="vieweroptions"){
- require(PATH_TO_ADDONDIR."/viewer/lmo-adminvieweroptions.php");
- }
- /*Viewer-Addon*/
- /*PDF-Addon*/
- elseif ($todo=="pdfoptions"){
- require(PATH_TO_ADDONDIR."/pdf/lmo-adminpdfoptions.inc.php");
- }
- /*PDF-Addon*/
-#c
-
-
-2. Änderung
- Nun zum nächsten Codeeinfügen. Es sind die Zeilen 150 - 152. Die sollten so aussehen.
-#C
- /*Viewer-Addon*/
- $viewer_addr_optionen = $_SERVER['PHP_SELF']."?action=admin&todo=vieweroptions";
- /*Viewer-Addon*/
-#c
-
- Darunter (nach "/*PDF-Addon*/") folgenden Code einfügen .
-
-#C
- /*PDF-Addon*/
- $pdf_addr_optionen = $_SERVER['PHP_SELF']."?action=admin&todo=pdfoptions";
- /*PDF-Addon*/
-#c
-
- der Codebereich sollte nun so aussehen.
-
-#C
- /*Viewer-Addon*/
- $viewer_addr_optionen = $_SERVER['PHP_SELF']."?action=admin&todo=vieweroptions";
- /*Viewer-Addon*/
- /*PDF-Addon*/
- $pdf_addr_optionen = $_SERVER['PHP_SELF']."?action=admin&todo=pdfoptions";
- /*PDF-Addon*/
-#c
-
-3. Änderung
- kommen wir nun zum letzten einfügen von PHP Code in der lmo-admimain.php.
- Die Zeilen 104 - 106 sehen so aus.
-#C
- echo $text['viewer'][20];
- }
- /*Viewer-Addon*/
-#c
-
- darunter nun den letzten Code einfügen. (wieder nach dem "/*Viewer-Addon*/")
-
-#C
- /*PDF-Addon*/
- echo " ";
- if (($todo!="pdfoptions")){
- echo "{$text['pdf'][200]} ";
- } else {
- echo $text['pdf'][200];
- }
- /*PDF-Addon*/
-#c
-
- der gesamte Codebereich sollte nun so aussehen.
-
-#C
- echo $text['viewer'][20];
- }
- /*Viewer-Addon*/
- /*PDF-Addon*/
- echo " ";
- if (($todo!="pdfoptions")){
- echo "{$text['pdf'][200]} ";
- } else {
- echo $text['pdf'][200];
- }
- /*PDF-Addon*/
-#c
-
-Das war es auch schon für diesen Teil mit den Änderungen im Code. Die oberen 3 Codeänderungen haben nun die Ansicht des Adminbereiches um einen neuen Menüpunkt erweitert.
-#NP
-1
-
-Ermöglicht das Erstellen von Spielplänen im PDF-Format.
-Nach der erfolreichen Einbindung erscheint unterhalb der Links 'Aktuellen Spieltag drucken' ein weiterer Link namens 'Spieltag als PDF-Dokument'. Dieser zeigt den aktuellen Spieltag, die aktuelle Tabelle und den folgenden Spieltag in einer PDF Datei an.
-Unter dem Link 'Ligaspielplan drucken' erscheint der Link 'Ligaspielplan als PDF-Dokument'. Beim betätigen dieses Links erscheint eine Ausgabe aller Spieltage der Liga als PDF Datei.
-
-
-2
-
-1. Zuerst einmal, du hast die Dateien aus der Installation der R&OS PHP PDF Class schon in Deinen LMO kopierst.
-
-2. Nun öffnest Du die Datei
- - lmo-showmain2.php
- Diese befindet sich im Hauptverzeichnis Deines LMO's.
- Die Zeilen 239, 240 und 241 sehen folgendermaßen aus.
-
-#C
- $output_savehtml.=ob_get_contents();ob_end_clean();
- }
-}
-#c
-
- nach der ersten schließenden Klammer "}" (Zeile 240) fügst Du folgenden Code ein.
-
-#C
- // PDF ADDON BEGIN
- if (file_exists(PATH_TO_ADDONDIR.'/pdf/lmo-showmain2.inc.php'))
- include(PATH_TO_ADDONDIR.'/pdf/lmo-showmain2.inc.php');
- // PDF ADDON END
-#c
-
- danach sollte es so aussehen.
-
-#C
- $output_savehtml.=ob_get_contents();ob_end_clean();
- }
- // PDF ADDON BEGIN
- if (file_exists(PATH_TO_ADDONDIR.'/pdf/lmo-showmain2.inc.php'))
- include(PATH_TO_ADDONDIR.'/pdf/lmo-showmain2.inc.php');
- // PDF ADDON END
-}
-#c
-
-Das war es schon mit der Einbindung des PDF-Addon Spielplan
-#NP
-1
-
-Ermöglicht die Ausgabe im Link Spielpläne des LMO in einer PDF Ausgabe. Hier werden die gezeigten Partien (der ganzen Session) einer ausgewählten Mannschaft als PDF-Dokument dargestellt.
-Nach der Installation erscheint unterhalb des Auswahlfensters 'Spielpläne' ein neuer Link 'Spielplan als PDF-Dokument'.
-
-2
-
- 1. Zuerst einmal, du hast die Dateien aus der Installation der R&OS PHP PDF Class schon in Deinen LMO kopierst.
-
- 2. Nun öffnest Du folgende Datei aus dem Hauptverzeichnis Deines LMO's
- - lmo-showprogram.php
- nach die letzte Zeile (Zeile 161)
-
-#C
-}?>
-#c
-
- folgendes einfügen
-
-#C
-
-#c
-
- danach sollte es so aussehen.
-
-#C
-}?>
-
-#c
-Das war es schon mit der Einbindung des PDF-Addon Teamplan
-#NP
-1
-
-Beschreibung folgt noch
-
-
-2
-
-Beschreibung folgt noch
\ No newline at end of file
diff --git a/lmo/help/Deutsch/addons/readme.php b/lmo/help/Deutsch/addons/readme.php
deleted file mode 100644
index bac247f6..00000000
--- a/lmo/help/Deutsch/addons/readme.php
+++ /dev/null
@@ -1,319 +0,0 @@
-.
- *
- * REMOVING OR CHANGING THE COPYRIGHT NOTICES IS NOT ALLOWED!
- *
- * Diese Datei ist Teil des PDF Addon für LMO 4.
- *
- * Pdf Addon für LMO 4 ist Freie Software: Sie können es unter den Bedingungen
- * der GNU General Public License, wie von der Free Software Foundation,
- * Version 3 der Lizenz oder (nach Ihrer Wahl) jeder späteren
- * veröffentlichten Version, weiterverbreiten und/oder modifizieren.
- *
- * Pdf Addon für LMO 4 wird in der Hoffnung, dass es nützlich sein wird, aber
- * OHNE JEDE GEWÄHRLEISTUNG, bereitgestellt; sogar ohne die implizite
- * Gewährleistung der MARKTFÄHIGKEIT oder EIGNUNG FÜR EINEN BESTIMMTEN ZWECK.
- * Siehe die GNU General Public License für weitere Details.
- *
- * Sie sollten eine Kopie der GNU General Public License zusammen mit diesem
- * Pdf Addon für LMO 4 erhalten haben. Wenn nicht, siehe .
- *
- * DAS ENTFERNEN ODER DIE ÄNDERUNG DER COPYRIGHT-HINWEISE IST NICHT ERLAUBT!
-**/
-
-error_reporting(E_ALL);
-date_default_timezone_set('Europe/Berlin');
-
-require_once(__DIR__.'/../../../init.php');
-require_once(PATH_TO_ADDONDIR."/pdf/ini.php");
-
-
-// define a class extension to allow the use of a callback to get the table of contents, and to put the dots in the toc
-class Creport extends Cezpdf {
- public $reportContents = [];
- public function __construct($p, $o, $t, $op) {
- parent::__construct($p, $o, $t, $op);
- }
-
- public function rf($info) {
- // this callback records all of the table of contents entries, it also places a destination marker there
- // so that it can be linked too
- $tmp = $info['p'];
- $lvl = $tmp[0];
- $lbl = rawurldecode(substr($tmp, 1));
- $num = $this->ezWhatPageNumber($this->ezGetCurrentPageNumber());
- $this->reportContents[] = [$lbl, $num, $lvl];
- $this->addDestination('toc' . (count($this->reportContents) - 1), 'XYZ', 0, $info['y'] + $info['height'], 0);
- }
-
- public function dots($info) {
- // draw a dotted line over to the right and put on a page number
- $tmp = $info['p'];
- $lvl = $tmp[0];
- $lbl = substr($tmp, 1);
- $xpos = 520;
-
- switch ($lvl) {
- case '1':
- $size = 16;
- $thick = 1;
- break;
- case '2':
- $size = 12;
- $thick = 0.5;
- break;
- }
-
- $this->saveState();
- $this->setLineStyle($thick, 'round', '', [0, 2]);
- $this->line($xpos, $info['y'], $info['x'] + 5, $info['y']);
- $this->restoreState();
- $this->addText($xpos + 5, $info['y'], $size, $lbl);
- }
-}
-// this code has been modified to use ezpdf.
-
-$project_url = "https://github.com/henshingly/";
-$project_version = "Version 3.2.0";
-
-$pdf = new Creport('a4', 'portrait', 'none', null);
-
-$start = microtime(true);
-
-// IMPORTANT: To allow custom callbacks being executed
-$pdf->allowedTags .= '|uline|rf:?.*?|dots:[0-9]+';
-
-$pdf->ezSetMargins(50, 70, 50, 50);
-
-// put a line top and bottom on all the pages
-$all = $pdf->openObject();
-$pdf->saveState();
-$pdf->setStrokeColor(0, 0, 0, 1);
-$pdf->line(20, 40, 578, 40);
-$pdf->line(20, 822, 578, 822);
-$pdf->addText(20, 30, 8, $project_url);
-
-$w = $pdf->getTextWidth(8, $project_version);
-$pdf->addText(578 - intval($w), 30, 8, $project_version);
-
-$pdf->restoreState();
-$pdf->closeObject();
-// note that object can be told to appear on just odd or even pages by changing 'all' to 'odd'
-// or 'even'.
-$pdf->addObject($all, 'all');
-
-$pdf->ezSetDy(-150);
-
-$mainFont = 'Helvetica';
-$codeFont = PATH_TO_ADDONDIR."/classes/pdf/fonts/Courier.afm";
-// select a font
-$pdf->selectFont($mainFont);
-
-$pdf->ezText("LMO PDF Addon\n", 30, ['justification' => 'centre']);
-$pdf->ezText($text['pdf'][16]."\n".$text['pdf'][17]."\nwww.liga-manager-online.de\n", 20, ['justification' => 'centre']);
-$pdf->ezText($text['pdf'][19]."\n\n".$text['pdf'][20]."\n", 14, ['justification' => 'centre']);
-$pdf->ezText($project_version, 12, ['justification' => 'centre']);
-$pdf->ezText('php ' . phpversion(), 12, ['justification' => 'centre']);
-$pdf->ezSetDy(-150);
-// modified to use the local file if it can
-$pdf->ezText("FORK AUF GITHUB.COM", 12, ['justification' => 'right']);
-
-$pdf->openHere('Fit');
-
-function ros_logo(&$pdf, $x, $y, $height, $wl = 0, $wr = 0) {
- global $project_url;
- $pdf->saveState();
- $h = 100;
- $factor = $height / $h;
- $pdf->selectFont('Helvetica-Bold');
- $text = 'PDF-Addon';
- $ts = 100 * $factor;
- $th = $pdf->getFontHeight($ts);
- $td = $pdf->getFontDescender($ts);
- $tw = $pdf->getTextWidth($ts, $text);
- $pdf->setColor(0, 0.2, 0.8);
- $z = 0.86;
- $pdf->filledRectangle($x - $wl, $y - $z * $h * $factor, $tw * 1.2 + $wr + $wl, $h * $factor * $z);
- $pdf->setColor(0, 0.9, 1);
- $pdf->addText($x, $y - $th - $td, $ts, $text,0, 'left',-10);
- $pdf->setColor(0.2, 0.9, 1);
- $pdf->addText($x, $y - $th - $td, $ts, $text,0, 'left',-8);
- $pdf->setColor(0.4, 0.9, 1);
- $pdf->addText($x, $y - $th - $td, $ts, $text,0, 'left',-6);
- $pdf->setColor(0.6, 0.9, 1);
- $pdf->addText($x, $y - $th - $td, $ts, $text,0, 'left',-4);
- $pdf->setColor(0.8, 0.9, 1);
- $pdf->addText($x, $y - $th - $td, $ts, $text,0, 'left',-2);
- $pdf->setColor(1, 1, 1);
- $pdf->addText($x, $y - $th - $td, $ts, $text,0, 'left',0);
- $pdf->setColor(0.6, 0, 0);
- $pdf->addText($x, $y - $th - $td, $ts * 0.1, $project_url);
- $pdf->restoreState();
- return $height;
-}
-ros_logo($pdf, 100, $pdf->y - 80, 80, 180, 300);
-$pdf->selectFont($mainFont);
-
-if (file_exists(PATH_TO_IMGDIR."/pdf/addon-pdf.png")) {
- $pdf->addPngFromFile(PATH_TO_IMGDIR."/pdf/addon-pdf.png", 199, 650, 200, 0);
-}
-if (file_exists(PATH_TO_IMGDIR."/pdf/github.jpg")) {
- $pdf->ezSetDy(-30);
- $pdf->addJpegFromFile(PATH_TO_IMGDIR."/pdf/github.jpg", 330, $pdf->y);
- $pdf->addLink($project_url . 'lmo-pdf-addon', 330, $pdf->y, 394, $pdf->y + 64);
-}
-
-//-----------------------------------------------------------
-// load up the document content
-if (file_exists(PATH_TO_LMO."/help/{$lmouserlang}/addons/pdf_addon.txt")) {
- $data = file(PATH_TO_LMO."/help/{$lmouserlang}/addons/pdf_addon.txt");
-} else $data = file(PATH_TO_LMO."/help/Deutsch/addons/pdf_addon.txt");
-
-$pdf->ezNewPage();
-
-$pdf->ezStartPageNumbers(intval($pdf->ez['pageWidth'] / 2), 28, 10, 'center');
-
-$size = 12;
-$height = $pdf->getFontHeight($size);
-$textOptions = ['justification' => 'full'];
-$collecting = 0;
-$code = '';
-
-foreach ($data as $line) {
- // go through each line, showing it as required, if it is surrounded by '<>' then
- // assume that it is a title
- $line = chop($line);
- if (strlen($line) && $line[0] == '#') {
- // comment, or new page request
- switch ($line) {
- case '#NP':
- $pdf->ezNewPage();
- break;
- case '#C':
- $pdf->selectFont($codeFont);
- $textOptions = ['justification' => 'left', 'left' => 20, 'right' => 20];
- $size = 10;
- break;
- case '#c':
- $pdf->selectFont($mainFont);
- $textOptions = ['justification' => 'full'];
- $size = 12;
- break;
- case '#X':
- $collecting = 1;
- break;
- case '#x':
- $pdf->saveState();
- eval($code);
- $pdf->restoreState();
- $pdf->selectFont($mainFont);
- $code = '';
- $collecting = 0;
- break;
- }
- } elseif ($collecting) {
- $code .= $line;
- } elseif (((strlen($line) > 1 && $line[1] == '<'))) {
- // then this is a title
- $tmp = substr($line, 2, strpos($line, '>') - 2);
- $tmp2 = $tmp . '';
- $tmp3 = substr($line, strpos($line, '>') + 1);
- switch ($line[0]) {
- case '1':
- $pdf->saveState();
- $pdf->setColor(0.5, 0.5, 0.5);
- $pdf->ezText("# " . $tmp2 . " #", 26, ['justification' => 'centre']);
- $pdf->restoreState();
- break;
- case '2':
- // add a grey bar, highlighting the change
- $pdf->transaction('start');
- $ok = 0;
- while (!$ok) {
- $thisPageNum = $pdf->ezPageCount;
- $pdf->saveState();
- $pdf->setColor(0.5, 0.5, 0.5);
- //$pdf->filledRectangle($pdf->ez['leftMargin'],$pdf->y-$pdf->getFontHeight(18)+$pdf->getFontDescender(18),$pdf->ez['pageWidth']-$pdf->ez['leftMargin']-$pdf->ez['rightMargin'],$pdf->getFontHeight(18));
- $pdf->ezText("# " . $tmp2, 18);
- $w = $pdf->getTextWidth(18, "# " . $tmp2);
- $pdf->y = $pdf->y + 15;
- $pdf->ezText($tmp3, 12, ['left' => $w]);
- $pdf->restoreState();
- if ($pdf->ezPageCount == $thisPageNum) {
- $pdf->transaction('commit');
- $ok = 1;
- } else {
- // then we have moved onto a new page, bad bad, as the background colour will be on the old one
- $pdf->transaction('rewind');
- $pdf->ezNewPage();
- }
- }
- break;
- case '3':
- $pdf->saveState();
- $pdf->setColor(0.5, 0.5, 0.5);
- $pdf->ezText("" . $tmp2, 12, ['justification' => 'left']);
- $pdf->restoreState();
- break;
- }
- } else {
- // then this is just text
- // the ezpdf function will take care of all of the wrapping etc.
- $pdf->ezText($line, $size, $textOptions);
- }
-}
-
-$pdf->ezStopPageNumbers(1, 1);
-
-// now add the table of contents, including internal links
-$pdf->ezInsertMode(1, 1, 'after');
-$pdf->ezNewPage();
-
-$pdf->saveState();
-$pdf->setColor(0.5, 0.5, 0.5);
-$pdf->ezText($text['pdf'][14] . "\n", 26, ['justification' => 'centre']);
-$xpos = 520;
-$contents = $pdf->reportContents;
-foreach ($contents as $k => $v) {
- switch ($v[2]) {
- case '1':
- $y = $pdf->ezText('' . $v[0] . '', 16, ['aright' => $xpos]);
- break;
- case '2':
- $pdf->ezText('' . $v[0] . '', 12, ['left' => 50, 'aright' => $xpos]);
- break;
- }
-}
-$pdf->restoreState();
-
-if (isset($_GET['d']) && $_GET['d']) {
- echo "";
- echo $pdf->ezOutput(true);
- echo " ";
-} else {
- $pdf->ezStream(['Content-Disposition' => 'readme.pdf']);
-}
-
-$end = microtime(true) - $start;
-error_log($end);
diff --git a/lmo/help/Deutsch/addons/ros.jpg b/lmo/help/Deutsch/addons/ros.jpg
deleted file mode 100644
index 2b7ed4fe..00000000
Binary files a/lmo/help/Deutsch/addons/ros.jpg and /dev/null differ
diff --git a/lmo/help/Deutsch/einstiegsinformationen.html b/lmo/help/Deutsch/einstiegsinformationen.html
index 6b3e1192..fae52d42 100644
--- a/lmo/help/Deutsch/einstiegsinformationen.html
+++ b/lmo/help/Deutsch/einstiegsinformationen.html
@@ -62,70 +62,52 @@
anpasst, steht im Abschnitt Anpassung des LMO . Zu jedem Link erhalten Ihre Besucher
einen Tooltip, so daß Sie keine weiteren Erklärungen zur Benutzung des Skripts geben müssen.
- Der Adminbereich ist, über lmoadmin.php erreichbar. Beim ersten Start melden Sie sich mit
- dem Namen admin und dem Passwort lmo (Mit L wie Ludwig!) an. Unter Optionen
- können und sollten Sie das dann sofort ändern, damit kein Unbefugter mehr Zugriff hat.
[nach oben]
+ Der Adminbereich ist über lmoadmin.php erreichbar. Beim ersten Aufruf legen Sie dort Ihren
+ Benutzernamen und Ihr Passwort fest (siehe Installation ). Rufen Sie lmoadmin.php deshalb
+ direkt nach dem Hochladen auf, damit Ihnen niemand zuvorkommt.[nach oben]
Unix- oder Windows-Webserver (empfohlen: Apache)
- PHP 4.1 (oder höher)
+ PHP 8.0 bis PHP 8.4
+ empfohlen: PHP-Erweiterung GD (für Grafiken wie die Fieberkurve)
empfohlen: JavaScript- und CSS-fähiger Browser
[nach oben]
-
- Update des LMO: Beim Update des LMO 4.0 von älteren LMO4-Versionen (beta/RC1) werden keine Konfigurationsdateien überschrieben,
- Sie können die Dateien über Ihre vorhandenen Datein kopieren. Führen Sie danach unbedingt die Installation neu aus, indem Sie
- den LMO aufrufen. Es empfiehlt sich bei Live-Systemen den LMO für den Zeitpunkt der Installation kurz zu sperren. (z.B. über htaccess).
- Eventuell installierte zusätzliche Addons werden nicht erkannt, diese sind also nach dem Update erneut zu installieren
- Das ZIP-Archiv wurde bereits von Ihnen entpackt. Achten Sie darauf, dass die Verzeichnisstruktur beim
- Entpacken beibehalten wird.
- Rufen Sie nun den LMO auf, indem Sie die Adresse zum LMO in Ihren Browser eingeben. Die Installation startet automatisch
- und sorgt für alle Vorraussetzungen, die der Betrieb des LMO erfordert.
- Im Normalfall ist der LMO nun korrekt installiert. Sollte jedoch ein Fehler aufgetreten sein oder Sie können aus anderen
- Gründen die Installation nicht abschließen, müssen Sie die folgenden Schritte manuell nachvollziehen:
- Manuelle Installation
-
- Achtung: Diese Schritte sind nur notwendig, wenn die normale Installation nicht funktioniert!
- Löschen Sie die Datei install/install.php und kopieren Sie danach den Inhalt
- des Ordners install über Ihr LMO-Verzeichnis
- Ändern Sie die Datei config/init-parameters.php mit einem normalen Texteditor und tragen Sie dort die
- benötigten Pfade ein. Falls die Datei noch nicht existiert, legen Sie diese mit einem normalen Texteditor an.
- Die Datei sollte so aussehen: <?php
+ Entpacken Sie das ZIP-Archiv und laden Sie den Ordner lmo auf Ihren Webspace hoch.
+ Achten Sie darauf, dass die Verzeichnisstruktur erhalten bleibt. Einen Installer gibt es nicht mehr.
+ Rufen Sie lmo.php im Browser auf. Der LMO richtet sich dabei selbst ein: Er ermittelt Dateipfad und
+ Webadresse, legt die Konfiguration im Verzeichnis config an (aus den Vorlagen in
+ config-default ) und erzeugt die benötigten Verzeichnisse.
+ Rufen Sie sofort danach lmoadmin.php auf. Beim ersten Aufruf legen Sie
+ dort Benutzernamen und Passwort des Hauptadministrators fest (mindestens 8 Zeichen). Ein voreingestelltes Konto gibt es nicht;
+ wer lmoadmin.php als Erster aufruft, legt das Passwort fest.
+ Erscheint die Meldung „Der Ordner config/ ist nicht beschreibbar“ , setzen Sie mit Ihrem FTP-Programm die
+ Zugriffsrechte (chmod) und rufen den LMO erneut auf:
+
+ 775 oder 777 - die Verzeichnisse config , ligen , output ,
+ addon/spieler/stats und addon/tipp/tipps jeweils mit allen Unterverzeichnissen
+ 664 oder 666 - die Ligen im Verzeichnis ligen
+
+ Welche Werte nötig sind, hängt vom Server ab; bei den meisten Anbietern ist das heute nicht mehr erforderlich.
+ Nur falls Dateipfad oder Webadresse falsch erkannt werden (z. B. hinter einer besonderen
+ Weiterleitung), können Sie beide fest vorgeben. Legen Sie dazu mit einem Texteditor die Datei
+ config/init-parameters.php an:<?php
$lmo_dateipfad='/absoluter/pfad/zum/lmo '; //Dateipfad zum LMO
- $lmo_url='http://www.adresse.ihres/lmo '; //abolute URL zum LMO
-?>
- Ersetzen Sie die beiden markierten Werte mit dem Dateipfad zum LMO-Verzeichnis
- und mit der Webadresse zum LMO . Falls Sie
- diese Angaben nicht wissen, fragen Sie bitte Ihren Provider.
- Nun ändern Sie bei folgenden Datei die Zugriffsrechte (chmod):
-
- Verzeichnisse:
- 777 - das Verzeichnis ligen und alle Unterverzeichnisse
- 777 - das Verzeichnis output
- 777 - das Verzeichnis config und dessen Unterverzeichnis config/viewer
- 777 - das Verzeichnis addon/spieler/stats
- 777 - das Verzeichnis addon/tipp/tipps und alle Unterverzeichnisse
- Dateien:
- 666 - config/lmo-auth.php
- 666 - addon/tipp/lmo-tippauth.txt
- 666 - Alle Dateien cfg.txt im Verzeichnis config und dessen Unterverzeichnissen
- 666 - alle Ligen im ligen -Verzeichnis und in dessen Unterverzeichnissen
- 666 - alle Dateien in den Verzeichnissen output , addon/spieler/stats und
- tipp/tipps (sofern vorhanden)
-
-
- Damit ist der Liga Manager Online installiert!
-
-
+ $lmo_url='https://www.adresse.ihres/lmo '; //absolute URL zum LMO
+?>
+
+ Update des LMO: Laden Sie die neuen Dateien über die vorhandenen. Ihre Konfiguration, Ligen und Konten
+ bleiben erhalten. Neue Einstellungen einer neueren Version ergänzt der LMO beim nächsten Aufruf automatisch in Ihren
+ vorhandenen cfg.txt -Dateien, ohne Ihre Werte zu verändern. Einen Ordner install aus einer
+ älteren Version können Sie löschen.
[nach oben]
- Wenn Sie den Adminbereich betreten, sehen Sie zuerst eine Eingabemaske, mit der Sie sich beim System anmelden müssen. Nach
- der Installation ist der voreingestellte der Nutzername admin und das Passwort lmo (kleines L, kleines M,
- kleines O) eingestellt. Das sollten Sie aber schnellstmöglich ändern, um Unbefugten den Zutritt zu Ihrem Adminbereich zu
- verwehren.
+ Wenn Sie den Adminbereich betreten, sehen Sie zuerst eine Eingabemaske, mit der Sie sich beim System anmelden müssen. Beim
+ allerersten Aufruf erscheint stattdessen die Ersteinrichtung , in der Sie Benutzernamen und Passwort des
+ Hauptadministrators festlegen; danach sind Sie direkt angemeldet. Weitere Benutzer und Passwortänderungen verwalten Sie unter
+ Optionen .
Wenn Sie eingeloggt sind, haben Sie rechts oben im Menü immer auch einen Befehl Logout , mit dem Sie sich aus
dem Adminbereich ausloggen können. Das sollten Sie der Sicherheit wegen auch immer am Ende einer Sitzung tun.
- * @author Jorrit Schippers
- * @copyright 1997-2008 The PHP Group
- * @license BSD http://www.opensource.org/licenses/bsd-license.php
- *
- * @link http://pear.php.net/package/Net_FTP
- * @since File available since Release 0.0.1
- */
-/**
- * Include PEAR.php to obtain the PEAR base class
- */
-require_once __DIR__.'/PEAR.php';
-/**
- * Option to let the ls() method return only files.
- *
- * @since 1.3
- * @name NET_FTP_FILES_ONLY
- * @see Net_FTP::ls()
- */
-define('NET_FTP_FILES_ONLY', 0);
-/**
- * Option to let the ls() method return only directories.
- *
- * @since 1.3
- * @name NET_FTP_DIRS_ONLY
- * @see Net_FTP::ls()
- */
-define('NET_FTP_DIRS_ONLY', 1);
-/**
- * Option to let the ls() method return directories and files (default).
- *
- * @since 1.3
- * @name NET_FTP_DIRS_FILES
- * @see Net_FTP::ls()
- */
-define('NET_FTP_DIRS_FILES', 2);
-/**
- * Option to let the ls() method return the raw directory listing from ftp_rawlist()
- *
- * @since 1.3
- * @name NET_FTP_RAWLIST
- * @see Net_FTP::ls()
- */
-define('NET_FTP_RAWLIST', 3);
-/**
- * Option to indicate that non-blocking features should not be used in
- * put(). This will also disable the listener functionality as a side effect.
- *
- * @since 1.4a1
- * @name NET_FTP_BLOCKING
- * @see Net_FTP::put()
- */
-define('NET_FTP_BLOCKING', 1);
-/**
- * Option to indicate that non-blocking features should be used if available in
- * put(). This will also enable the listener functionality.
- *
- * This is the default behaviour.
- *
- * @since 1.4a1
- * @name NET_FTP_NONBLOCKING
- * @see Net_FTP::put()
- */
-define('NET_FTP_NONBLOCKING', 2);
-/**
- * Error code to indicate a failed connection
- * This error code indicates, that the connection you tryed to set up
- * could not be established. Check your connection settings (host & port)!
- *
- * @since 1.3
- * @name NET_FTP_ERR_CONNECT_FAILED
- * @see Net_FTP::connect()
- */
-define('NET_FTP_ERR_CONNECT_FAILED', -1);
-/**
- * Error code to indicate a failed login
- * This error code indicates, that the login to the FTP server failed. Check
- * your user data (username & password).
- *
- * @since 1.3
- * @name NET_FTP_ERR_LOGIN_FAILED
- * @see Net_FTP::login()
- */
-define('NET_FTP_ERR_LOGIN_FAILED', -2);
-/**
- * Error code to indicate a failed directory change
- * The cd() method failed. Ensure that the directory you wanted to access exists.
- *
- * @since 1.3
- * @name NET_FTP_ERR_DIRCHANGE_FAILED
- * @see Net_FTP::cd()
- */
-define('NET_FTP_ERR_DIRCHANGE_FAILED', 2); // Compatibillity reasons!
-/**
- * Error code to indicate that Net_FTP could not determine the current path
- * The pwd() method failed and could not determine the path you currently reside
- * in on the FTP server.
- *
- * @since 1.3
- * @name NET_FTP_ERR_DETERMINEPATH_FAILED
- * @see Net_FTP::pwd()
- */
-define('NET_FTP_ERR_DETERMINEPATH_FAILED', 4); // Compatibillity reasons!
-/**
- * Error code to indicate that the creation of a directory failed
- * The directory you tryed to create could not be created. Check the
- * access rights on the parent directory!
- *
- * @since 1.3
- * @name NET_FTP_ERR_CREATEDIR_FAILED
- * @see Net_FTP::mkdir()
- */
-define('NET_FTP_ERR_CREATEDIR_FAILED', -4);
-/**
- * Error code to indicate that the EXEC execution failed.
- * The execution of a command using EXEC failed. Ensure, that your
- * FTP server supports the EXEC command.
- *
- * @since 1.3
- * @name NET_FTP_ERR_EXEC_FAILED
- * @see Net_FTP::execute()
- */
-define('NET_FTP_ERR_EXEC_FAILED', -5);
-/**
- * Error code to indicate that the SITE command failed.
- * The execution of a command using SITE failed. Ensure, that your
- * FTP server supports the SITE command.
- *
- * @since 1.3
- * @name NET_FTP_ERR_SITE_FAILED
- * @see Net_FTP::site()
- */
-define('NET_FTP_ERR_SITE_FAILED', -6);
-/**
- * Error code to indicate that the CHMOD command failed.
- * The execution of CHMOD failed. Ensure, that your
- * FTP server supports the CHMOD command and that you have the appropriate
- * access rights to use CHMOD.
- *
- * @since 1.3
- * @name NET_FTP_ERR_CHMOD_FAILED
- * @see Net_FTP::chmod()
- */
-define('NET_FTP_ERR_CHMOD_FAILED', -7);
-/**
- * Error code to indicate that a file rename failed
- * The renaming of a file on the server failed. Ensure that you have the
- * appropriate access rights to rename the file.
- *
- * @since 1.3
- * @name NET_FTP_ERR_RENAME_FAILED
- * @see Net_FTP::rename()
- */
-define('NET_FTP_ERR_RENAME_FAILED', -8);
-/**
- * Error code to indicate that the MDTM command failed
- * The MDTM command is not supported for directories. Ensure that you gave
- * a file path to the mdtm() method, not a directory path.
- *
- * @since 1.3
- * @name NET_FTP_ERR_MDTMDIR_UNSUPPORTED
- * @see Net_FTP::mdtm()
- */
-define('NET_FTP_ERR_MDTMDIR_UNSUPPORTED', -9);
-/**
- * Error code to indicate that the MDTM command failed
- * The MDTM command failed. Ensure that your server supports the MDTM command.
- *
- * @since 1.3
- * @name NET_FTP_ERR_MDTM_FAILED
- * @see Net_FTP::mdtm()
- */
-define('NET_FTP_ERR_MDTM_FAILED', -10);
-/**
- * Error code to indicate that a date returned by the server was misformated
- * A date string returned by your server seems to be missformated and could not be
- * parsed. Check that the server is configured correctly. If you're sure, please
- * send an email to the auhtor with a dumped output of
- * $ftp->ls('./', NET_FTP_RAWLIST); to get the date format supported.
- *
- * @since 1.3
- * @name NET_FTP_ERR_DATEFORMAT_FAILED
- * @see Net_FTP::mdtm(), Net_FTP::ls()
- */
-define('NET_FTP_ERR_DATEFORMAT_FAILED', -11);
-/**
- * Error code to indicate that the SIZE command failed
- * The determination of the filesize of a file failed. Ensure that your server
- * supports the SIZE command.
- *
- * @since 1.3
- * @name NET_FTP_ERR_SIZE_FAILED
- * @see Net_FTP::size()
- */
-define('NET_FTP_ERR_SIZE_FAILED', -12);
-/**
- * Error code to indicate that a local file could not be overwritten
- * You specified not to overwrite files. Therefore the local file has not been
- * overwriten. If you want to get the file overwriten, please set the option to
- * do so.
- *
- * @since 1.3
- * @name NET_FTP_ERR_OVERWRITELOCALFILE_FORBIDDEN
- * @see Net_FTP::get(), Net_FTP::getRecursive()
- */
-define('NET_FTP_ERR_OVERWRITELOCALFILE_FORBIDDEN', -13);
-/**
- * Error code to indicate that a local file could not be overwritten
- * Also you specified to overwrite the local file you want to download to,
- * it has not been possible to do so. Check that you have the appropriate access
- * rights on the local file to overwrite it.
- *
- * @since 1.3
- * @name NET_FTP_ERR_OVERWRITELOCALFILE_FAILED
- * @see Net_FTP::get(), Net_FTP::getRecursive()
- */
-define('NET_FTP_ERR_OVERWRITELOCALFILE_FAILED', -14);
-/**
- * Error code to indicate that the file you wanted to upload does not exist
- * The file you tried to upload does not exist. Ensure that it exists.
- *
- * @since 1.3
- * @name NET_FTP_ERR_LOCALFILENOTEXIST
- * @see Net_FTP::put(), Net_FTP::putRecursive()
- */
-define('NET_FTP_ERR_LOCALFILENOTEXIST', -15);
-/**
- * Error code to indicate that a remote file could not be overwritten
- * You specified not to overwrite files. Therefore the remote file has not been
- * overwriten. If you want to get the file overwriten, please set the option to
- * do so.
- *
- * @since 1.3
- * @name NET_FTP_ERR_OVERWRITEREMOTEFILE_FORBIDDEN
- * @see Net_FTP::put(), Net_FTP::putRecursive()
- */
-define('NET_FTP_ERR_OVERWRITEREMOTEFILE_FORBIDDEN', -16);
-/**
- * Error code to indicate that the upload of a file failed
- * The upload you tried failed. Ensure that you have appropriate access rights
- * to upload the desired file.
- *
- * @since 1.3
- * @name NET_FTP_ERR_UPLOADFILE_FAILED
- * @see Net_FTP::put(), Net_FTP::putRecursive()
- */
-define('NET_FTP_ERR_UPLOADFILE_FAILED', -17);
-/**
- * Error code to indicate that you specified an incorrect directory path
- * The remote path you specified seems not to be a directory. Ensure that
- * the path you specify is a directory and that the path string ends with
- * a /.
- *
- * @since 1.3
- * @name NET_FTP_ERR_REMOTEPATHNODIR
- * @see Net_FTP::putRecursive(), Net_FTP::getRecursive()
- */
-define('NET_FTP_ERR_REMOTEPATHNODIR', -18);
-/**
- * Error code to indicate that you specified an incorrect directory path
- * The local path you specified seems not to be a directory. Ensure that
- * the path you specify is a directory and that the path string ends with
- * a /.
- *
- * @since 1.3
- * @name NET_FTP_ERR_LOCALPATHNODIR
- * @see Net_FTP::putRecursive(), Net_FTP::getRecursive()
- */
-define('NET_FTP_ERR_LOCALPATHNODIR', -19);
-/**
- * Error code to indicate that a local directory failed to be created
- * You tried to create a local directory through getRecursive() method,
- * which has failed. Ensure that you have the appropriate access rights
- * to create it.
- *
- * @since 1.3
- * @name NET_FTP_ERR_CREATELOCALDIR_FAILED
- * @see Net_FTP::getRecursive()
- */
-define('NET_FTP_ERR_CREATELOCALDIR_FAILED', -20);
-/**
- * Error code to indicate that the provided hostname was incorrect
- * The hostname you provided was invalid. Ensure to provide either a
- * full qualified domain name or an IP address.
- *
- * @since 1.3
- * @name NET_FTP_ERR_HOSTNAMENOSTRING
- * @see Net_FTP::setHostname()
- */
-define('NET_FTP_ERR_HOSTNAMENOSTRING', -21);
-/**
- * Error code to indicate that the provided port was incorrect
- * The port number you provided was invalid. Ensure to provide either a
- * a numeric port number greater zero.
- *
- * @since 1.3
- * @name NET_FTP_ERR_PORTLESSZERO
- * @see Net_FTP::setPort()
- */
-define('NET_FTP_ERR_PORTLESSZERO', -22);
-/**
- * Error code to indicate that you provided an invalid mode constant
- * The mode constant you provided was invalid. You may only provide
- * FTP_ASCII or FTP_BINARY.
- *
- * @since 1.3
- * @name NET_FTP_ERR_NOMODECONST
- * @see Net_FTP::setMode()
- */
-define('NET_FTP_ERR_NOMODECONST', -23);
-/**
- * Error code to indicate that you provided an invalid timeout
- * The timeout you provided was invalid. You have to provide a timeout greater
- * or equal to zero.
- *
- * @since 1.3
- * @name NET_FTP_ERR_TIMEOUTLESSZERO
- * @see Net_FTP::Net_FTP(), Net_FTP::setTimeout()
- */
-define('NET_FTP_ERR_TIMEOUTLESSZERO', -24);
-/**
- * Error code to indicate that you provided an invalid timeout
- * An error occured while setting the timeout. Ensure that you provide a
- * valid integer for the timeount and that your PHP installation works
- * correctly.
- *
- * @since 1.3
- * @name NET_FTP_ERR_SETTIMEOUT_FAILED
- * @see Net_FTP::Net_FTP(), Net_FTP::setTimeout()
- */
-define('NET_FTP_ERR_SETTIMEOUT_FAILED', -25);
-/**
- * Error code to indicate that the provided extension file doesn't exist
- * The provided extension file does not exist. Ensure to provided an
- * existant extension file.
- *
- * @since 1.3
- * @name NET_FTP_ERR_EXTFILENOTEXIST
- * @see Net_FTP::getExtensionsFile()
- */
-define('NET_FTP_ERR_EXTFILENOTEXIST', -26);
-/**
- * Error code to indicate that the provided extension file is not readable
- * The provided extension file is not readable. Ensure to have sufficient
- * access rights for it.
- *
- * @since 1.3
- * @name NET_FTP_ERR_EXTFILEREAD_FAILED
- * @see Net_FTP::getExtensionsFile()
- */
-define('NET_FTP_ERR_EXTFILEREAD_FAILED', -27);
-/**
- * Error code to indicate that the deletion of a file failed
- * The specified file could not be deleted. Ensure to have sufficient
- * access rights to delete the file.
- *
- * @since 1.3
- * @name NET_FTP_ERR_EXTFILEREAD_FAILED
- * @see Net_FTP::rm()
- */
-define('NET_FTP_ERR_DELETEFILE_FAILED', -28);
-/**
- * Error code to indicate that the deletion of a directory faild
- * The specified file could not be deleted. Ensure to have sufficient
- * access rights to delete the file.
- *
- * @since 1.3
- * @name NET_FTP_ERR_EXTFILEREAD_FAILED
- * @see Net_FTP::rm()
- */
-define('NET_FTP_ERR_DELETEDIR_FAILED', -29);
-/**
- * Error code to indicate that the directory listing failed
- * PHP could not list the directory contents on the server. Ensure
- * that your server is configured appropriate.
- *
- * @since 1.3
- * @name NET_FTP_ERR_RAWDIRLIST_FAILED
- * @see Net_FTP::ls()
- */
-define('NET_FTP_ERR_RAWDIRLIST_FAILED', -30);
-/**
- * Error code to indicate that the directory listing failed
- * The directory listing format your server uses seems not to
- * be supported by Net_FTP. Please send the output of the
- * call ls('./', NET_FTP_RAWLIST); to the author of this
- * class to get it supported.
- *
- * @since 1.3
- * @name NET_FTP_ERR_DIRLIST_UNSUPPORTED
- * @see Net_FTP::ls()
- */
-define('NET_FTP_ERR_DIRLIST_UNSUPPORTED', -31);
-/**
- * Error code to indicate failed disconnecting
- * This error code indicates, that disconnection was not possible.
- *
- * @since 1.3
- * @name NET_FTP_ERR_DISCONNECT_FAILED
- * @see Net_FTP::disconnect()
- */
-define('NET_FTP_ERR_DISCONNECT_FAILED', -32);
-/**
- * Error code to indicate that the username you provided was invalid.
- * Check that you provided a non-empty string as the username.
- *
- * @since 1.3
- * @name NET_FTP_ERR_USERNAMENOSTRING
- * @see Net_FTP::setUsername()
- */
-define('NET_FTP_ERR_USERNAMENOSTRING', -33);
-/**
- * Error code to indicate that the username you provided was invalid.
- * Check that you provided a non-empty string as the username.
- *
- * @since 1.3
- * @name NET_FTP_ERR_PASSWORDNOSTRING
- * @see Net_FTP::setPassword()
- */
-define('NET_FTP_ERR_PASSWORDNOSTRING', -34);
-/**
- * Error code to indicate that the provided extension file is not loadable
- * The provided extension file is not loadable. Ensure to have a correct file
- * syntax.
- *
- * @since 1.3.3
- * @name NET_FTP_ERR_EXTFILELOAD_FAILED
- * @see Net_FTP::getExtensionsFile()
- */
-define('NET_FTP_ERR_EXTFILELOAD_FAILED', -35);
-/**
- * Error code to indicate that the directory listing pattern provided is not a
- * string.
- *
- * @since 1.4.0a1
- * @name NET_FTP_ERR_ILLEGALPATTERN
- * @see Net_FTP::setDirMatcher()
- */
-define('NET_FTP_ERR_ILLEGALPATTERN', -36);
-/**
- * Error code to indicate that the directory listing matcher map provided is not an
- * array.
- *
- * @since 1.4.0a1
- * @name NET_FTP_ERR_ILLEGALMAP
- * @see Net_FTP::setDirMatcher()
- */
-define('NET_FTP_ERR_ILLEGALMAP', -37);
-/**
- * Error code to indicate that the directory listing matcher map provided contains
- * wrong values (ie: it contains non-numerical values)
- *
- * @since 1.4.0a1
- * @name NET_FTP_ERR_ILLEGALMAPVALUE
- * @see Net_FTP::setDirMatcher()
- */
-define('NET_FTP_ERR_ILLEGALMAPVALUE', -38);
-/**
- * Error code indicating that bad options were supplied to the
- * put() method.
- *
- * @since 1.4a1
- * @name NET_FTP_ERR_BADOPTIONS
- * @see Net_FTP::put()
- */
-define('NET_FTP_ERR_BADOPTIONS', -39);
-/**
- * Error code indicating that SSL connection is not supported as either the
- * ftp module or OpenSSL support is not statically built into php.
- *
- * @since 1.4a2
- * @name NET_FTP_ERR_NOSSL
- * @see Net_FTP::setSsl()
- */
-define('NET_FTP_ERR_NOSSL', -40);
-/**
- * Class for comfortable FTP-communication
- *
- * This class provides comfortable communication with FTP-servers. You may do
- * everything enabled by the PHP-FTP-extension and further functionalities, like
- * recursive-deletion, -up- and -download. Another feature is to create directories
- * recursively.
- *
- * @category Networking
- * @package FTP
- * @author Tobias Schlitt
- * @author Jorrit Schippers
- * @copyright 1997-2008 The PHP Group
- * @license http://www.php.net/license/3_0.txt PHP License 3.0
- * @version Release: @package_version@
- * @link http://pear.php.net/package/Net_FTP
- * @since 0.0.1
- * @access public
- */
-class Net_FTP extends PEAR
-{
- /**
- * The host to connect to
- *
- * @access private
- * @var string
- */
- var $_hostname;
- /**
- * The port for ftp-connection (standard is 21)
- *
- * @access private
- * @var int
- */
- var $_port = 21;
- /**
- * The username for login
- *
- * @access private
- * @var string
- */
- var $_username;
- /**
- * The password for login
- *
- * @access private
- * @var string
- */
- var $_password;
- /**
- * Determine whether to connect through secure SSL connection or not
- *
- * Is null when it hasn't been explicitly set
- *
- * @access private
- * @var bool
- */
- var $_ssl;
- /**
- * Determine whether to use passive-mode (true) or active-mode (false)
- *
- * Is null when it hasn't been explicitly set
- *
- * @access private
- * @var bool
- */
- var $_passv = null;
- /**
- * The standard mode for ftp-transfer
- *
- * @access private
- * @var int
- */
- var $_mode = FTP_BINARY;
- /**
- * This holds the handle for the ftp-connection
- *
- * If null, the connection hasn't been setup yet. If false, the connection
- * attempt has failed. Else, it contains an ftp resource.
- *
- * @access private
- * @var resource
- */
- var $_handle = null;
- /**
- * Contains the timeout for FTP operations
- *
- * @access private
- * @var int
- * @since 1.3
- */
- var $_timeout = 90;
-
- /**
- * Saves file-extensions for ascii- and binary-mode
- *
- * The array is built like this: 'php' => FTP_ASCII, 'png' => FTP_BINARY
- *
- * @access private
- * @var array
- */
- var $_file_extensions = array();
- /**
- * ls match
- * Matches the ls entries against a regex and maps the resulting array to
- * speaking names
- *
- * The values are set in the constructor because of line length constaints.
- *
- * Typical lines for the Windows format:
- * 07-05-07 08:40AM 4701 SomeFile.ext
- * 04-29-07 10:28PM SomeDir
- *
- * @access private
- * @var array
- * @since 1.3
- */
- var $_ls_match = null;
-
- /**
- * matcher
- * Stores the matcher for the current connection
- *
- * @access private
- * @var array
- * @since 1.3
- */
- var $_matcher = null;
-
- /**
- * Holds all Net_FTP_Observer objects
- * that wish to be notified of new messages.
- *
- * @var array
- * @access private
- * @since 1.3
- */
- var $_listeners = array();
- /**
- * Is true when a login has been performed
- * and was successful
- *
- * @access private
- * @var boolean
- * @since 1.4
- */
- var $_loggedin = false;
- /**
- * This generates a new FTP-Object. The FTP-connection will not be established,
- * yet.
- * You can leave $host and $port blank, if you want. The $host will not be set
- * and the $port will be left at 21. You have to set the $host manualy before
- * trying to connect or with the connect() method.
- *
- * @param string $host (optional) The hostname
- * @param int $port (optional) The port
- * @param int $timeout (optional) Sets the standard timeout
- *
- * @access public
- * @return void
- * @see Net_FTP::setHostname(), Net_FTP::setPort(), Net_FTP::connect()
- */
- function __construct($host = null, $port = null, $timeout = 90)
- {
- $this->PEAR();
- if (isset($host)) {
- $this->setHostname($host);
- }
- if (isset($port)) {
- $this->setPort($port);
- }
- $this->_timeout = $timeout;
-
- $this->_ls_match = array(
- 'unix' => array(
- 'pattern' => '/(?:(d)|.)([rwxts\-]{9})\s+(\w+)\s+([\w\d\-()?.]+)\s+'.
- '([\w\d\-()?.]+)\s+(\w+)\s+(\S+\s+\S+\s+\S+)\s+(.+)/',
- 'map' => array(
- 'is_dir' => 1,
- 'rights' => 2,
- 'files_inside' => 3,
- 'user' => 4,
- 'group' => 5,
- 'size' => 6,
- 'date' => 7,
- 'name' => 8,
- )
- ),
- 'windows' => array(
- 'pattern' => '/([0-9\-]+\s+[0-9:APM]+)\s+(()|\d+)\s+(.+)/',
- 'map' => array(
- 'date' => 1,
- 'size' => 2,
- 'is_dir' => 3,
- 'name' => 4,
- )
- )
- );
- }
- /**
- * This function generates the FTP-connection. You can optionally define a
- * hostname and/or a port. If you do so, this data is stored inside the object.
- *
- * @param string $host (optional) The Hostname
- * @param int $port (optional) The Port
- * @param bool $ssl (optional) Whether to connect through secure SSL connection
- *
- * @access public
- * @return mixed true on success, otherwise PEAR::Error
- * @see NET_FTP_ERR_CONNECT_FAILED
- */
- function connect($host = null, $port = null, $ssl = null)
- {
- $this->_matcher = null;
- if (isset($host)) {
- $this->setHostname($host);
- }
- if (isset($port)) {
- $this->setPort($port);
- }
- if (isset($ssl) && is_bool($ssl) && $ssl) {
- $this->setSsl();
- }
- if ($this->getSsl()) {
- $handle = @ftp_ssl_connect($this->getHostname(), $this->getPort(),
- $this->_timeout);
- } else {
- $handle = @ftp_connect($this->getHostname(), $this->getPort(),
- $this->_timeout);
- }
- if (!$handle) {
- $this->_handle = false;
- return $this->raiseError("Connection to host failed",
- NET_FTP_ERR_CONNECT_FAILED);
- } else {
- $this->_handle =& $handle;
- return true;
- }
- }
- /**
- * This function close the FTP-connection
- *
- * @access public
- * @return bool|PEAR_Error Returns true on success, PEAR_Error on failure
- */
- function disconnect()
- {
- $res = @ftp_close($this->_handle);
- if (!$res) {
- return PEAR::raiseError('Disconnect failed.',
- NET_FTP_ERR_DISCONNECT_FAILED);
- }
- $this->_handle = null;
- return true;
- }
- /**
- * This logs you into the ftp-server. You are free to specify username and
- * password in this method. If you specify it, the values will be taken into
- * the corresponding attributes, if do not specify, the attributes are taken.
- *
- * If connect() has not been called yet, a connection will be setup
- *
- * @param string $username (optional) The username to use
- * @param string $password (optional) The password to use
- *
- * @access public
- * @return mixed true on success, otherwise PEAR::Error
- * @see NET_FTP_ERR_LOGIN_FAILED
- */
- function login($username = null, $password = null)
- {
- if ($this->_handle === null) {
- $res = $this->connect();
- if (PEAR::isError($res)) {
- return $res;
- }
- }
-
- if (!isset($username)) {
- $username = $this->getUsername();
- } else {
- $this->setUsername($username);
- }
- if (!isset($password)) {
- $password = $this->getPassword();
- } else {
- $this->setPassword($password);
- }
- $res = @ftp_login($this->_handle, $username, $password);
- if (!$res) {
- return $this->raiseError("Unable to login", NET_FTP_ERR_LOGIN_FAILED);
- } else {
- $this->_loggedin = true;
- // distinguish between null and false, null means this setting wasn't
- // explicitly changed, so we only change it when setPassive or
- // setActive was called by the user
- if ($this->_passv === true) {
- $this->setPassive();
- } elseif ($this->_passv === false) {
- $this->setActive();
- }
- return true;
- }
- }
- /**
- * This changes the currently used directory. You can use either an absolute
- * directory-path (e.g. "/home/blah") or a relative one (e.g. "../test").
- *
- * @param string $dir The directory to go to.
- *
- * @access public
- * @return mixed true on success, otherwise PEAR::Error
- * @see NET_FTP_ERR_DIRCHANGE_FAILED
- */
- function cd($dir)
- {
- $erg = @ftp_chdir($this->_handle, $dir);
- if (!$erg) {
- return $this->raiseError("Directory change failed",
- NET_FTP_ERR_DIRCHANGE_FAILED);
- } else {
- return true;
- }
- }
- /**
- * Show's you the actual path on the server
- * This function questions the ftp-handle for the actual selected path and
- * returns it.
- *
- * @access public
- * @return mixed The actual path or PEAR::Error
- * @see NET_FTP_ERR_DETERMINEPATH_FAILED
- */
- function pwd()
- {
- $res = @ftp_pwd($this->_handle);
- if (!$res) {
- return $this->raiseError("Could not determine the actual path.",
- NET_FTP_ERR_DETERMINEPATH_FAILED);
- } else {
- return $res;
- }
- }
- /**
- * This works similar to the mkdir-command on your local machine. You can either
- * give it an absolute or relative path. The relative path will be completed
- * with the actual selected server-path. (see: pwd())
- *
- * @param string $dir Absolute or relative dir-path
- * @param bool $recursive (optional) Create all needed directories
- *
- * @access public
- * @return mixed true on success, otherwise PEAR::Error
- * @see NET_FTP_ERR_CREATEDIR_FAILED
- */
- function mkdir($dir, $recursive = false)
- {
- $dir = $this->_constructPath($dir);
- $savedir = $this->pwd();
- $this->pushErrorHandling(PEAR_ERROR_RETURN);
- $e = $this->cd($dir);
- $this->popErrorHandling();
- if ($e === true) {
- $this->cd($savedir);
- return true;
- }
- $this->cd($savedir);
- if ($recursive === false) {
- $res = @ftp_mkdir($this->_handle, $dir);
- if (!$res) {
- return $this->raiseError("Creation of '$dir' failed",
- NET_FTP_ERR_CREATEDIR_FAILED);
- } else {
- return true;
- }
- } else {
- // do not look at the first character, as $dir is absolute,
- // it will always be a /
- if (strpos(substr($dir, 1), '/') === false) {
- return $this->mkdir($dir, false);
- }
- if (substr($dir, -1) == '/') {
- $dir = substr($dir, 0, -1);
- }
- $parent = substr($dir, 0, strrpos($dir, '/'));
- $res = $this->mkdir($parent, true);
- if ($res === true) {
- $res = $this->mkdir($dir, false);
- }
- if ($res !== true) {
- return $res;
- }
- return true;
- }
- }
- /**
- * This method tries executing a command on the ftp, using SITE EXEC.
- *
- * @param string $command The command to execute
- *
- * @access public
- * @return mixed The result of the command (if successfull), otherwise
- * PEAR::Error
- * @see NET_FTP_ERR_EXEC_FAILED
- */
- function execute($command)
- {
- $res = @ftp_exec($this->_handle, $command);
- if (!$res) {
- return $this->raiseError("Execution of command '$command' failed.",
- NET_FTP_ERR_EXEC_FAILED);
- } else {
- return $res;
- }
- }
- /**
- * Execute a SITE command on the server
- * This method tries to execute a SITE command on the ftp server.
- *
- * @param string $command The command with parameters to execute
- *
- * @access public
- * @return mixed true if successful, otherwise PEAR::Error
- * @see NET_FTP_ERR_SITE_FAILED
- */
- function site($command)
- {
- $res = @ftp_site($this->_handle, $command);
- if (!$res) {
- return $this->raiseError("Execution of SITE command '$command' failed.",
- NET_FTP_ERR_SITE_FAILED);
- } else {
- return $res;
- }
- }
- /**
- * This method will try to chmod the file specified on the server
- * Currently, you must give a number as the the permission argument (777 or
- * similar). The file can be either a relative or absolute path.
- * NOTE: Some servers do not support this feature. In that case, you will
- * get a PEAR error object returned. If successful, the method returns true
- *
- * @param mixed $target The file or array of files to set permissions for
- * @param integer $permissions The mode to set the file permissions to
- *
- * @access public
- * @return mixed true if successful, otherwise PEAR::Error
- * @see NET_FTP_ERR_CHMOD_FAILED
- */
- function chmod($target, $permissions)
- {
- // If $target is an array: Loop through it.
- if (is_array($target)) {
- for ($i = 0; $i < count($target); $i++) {
- $res = $this->chmod($target[$i], $permissions);
- if (PEAR::isError($res)) {
- return $res;
- } // end if isError
- } // end for i < count($target)
-
- return true;
- } else {
- $res = $this->site("CHMOD " . $permissions . " " . $target);
- if (!$res) {
- return PEAR::raiseError("CHMOD " . $permissions . " " . $target .
- " failed", NET_FTP_ERR_CHMOD_FAILED);
- } else {
- return $res;
- }
- } // end if is_array
- } // end method chmod
- /**
- * This method will try to chmod a folder and all of its contents
- * on the server. The target argument must be a folder or an array of folders
- * and the permissions argument have to be an integer (i.e. 777).
- * The file can be either a relative or absolute path.
- * NOTE: Some servers do not support this feature. In that case, you
- * will get a PEAR error object returned. If successful, the method
- * returns true
- *
- * @param mixed $target The folder or array of folders to
- * set permissions for
- * @param integer $permissions The mode to set the folder
- * and file permissions to
- *
- * @access public
- * @return mixed true if successful, otherwise PEAR::Error
- * @see NET_FTP_ERR_CHMOD_FAILED, NET_FTP_ERR_DETERMINEPATH_FAILED,
- * NET_FTP_ERR_RAWDIRLIST_FAILED, NET_FTP_ERR_DIRLIST_UNSUPPORTED
- */
- function chmodRecursive($target, $permissions)
- {
- static $dir_permissions;
- if (!isset($dir_permissions)) { // Making directory specific permissions
- $dir_permissions = $this->_makeDirPermissions($permissions);
- }
- // If $target is an array: Loop through it
- if (is_array($target)) {
- for ($i = 0; $i < count($target); $i++) {
- $res = $this->chmodRecursive($target[$i], $permissions);
- if (PEAR::isError($res)) {
- return $res;
- } // end if isError
- } // end for i < count($target)
- } else {
- $remote_path = $this->_constructPath($target);
- // Chmod the directory itself
- $result = $this->chmod($remote_path, $dir_permissions);
- if (PEAR::isError($result)) {
- return $result;
- }
- // If $remote_path last character is not a slash, add one
- if (substr($remote_path, strlen($remote_path)-1) != "/") {
- $remote_path .= "/";
- }
- $dir_list = array();
- $mode = NET_FTP_DIRS_ONLY;
- $dir_list = $this->ls($remote_path, $mode);
- if (PEAR::isError($dir_list)) {
- return $dir_list;
- }
- foreach ($dir_list as $dir_entry) {
- if ($dir_entry['name'] == '.' || $dir_entry['name'] == '..') {
- continue;
- }
-
- $remote_path_new = $remote_path.$dir_entry["name"]."/";
- // Chmod the directory we're about to enter
- $result = $this->chmod($remote_path_new, $dir_permissions);
- if (PEAR::isError($result)) {
- return $result;
- }
- $result = $this->chmodRecursive($remote_path_new, $permissions);
- if (PEAR::isError($result)) {
- return $result;
- }
- } // end foreach dir_list as dir_entry
- $file_list = array();
- $mode = NET_FTP_FILES_ONLY;
- $file_list = $this->ls($remote_path, $mode);
-
- if (PEAR::isError($file_list)) {
- return $file_list;
- }
- foreach ($file_list as $file_entry) {
- $remote_file = $remote_path.$file_entry["name"];
- $result = $this->chmod($remote_file, $permissions);
- if (PEAR::isError($result)) {
- return $result;
- }
- } // end foreach $file_list
- } // end if is_array
- return true; // No errors
- } // end method chmodRecursive
- /**
- * Rename or move a file or a directory from the ftp-server
- *
- * @param string $remote_from The remote file or directory original to rename or
- * move
- * @param string $remote_to The remote file or directory final to rename or
- * move
- *
- * @access public
- * @return bool $res true on success, otherwise PEAR::Error
- * @see NET_FTP_ERR_RENAME_FAILED
- */
- function rename ($remote_from, $remote_to)
- {
- $res = @ftp_rename($this->_handle, $remote_from, $remote_to);
- if (!$res) {
- return $this->raiseError("Could not rename ".$remote_from." to ".
- $remote_to." !", NET_FTP_ERR_RENAME_FAILED);
- }
- return true;
- }
- /**
- * This will return logical permissions mask for directory.
- * if directory has to be readable it have also be executable
- *
- * @param string $permissions File permissions in digits for file (i.e. 666)
- *
- * @access private
- * @return string File permissions in digits for directory (i.e. 777)
- */
- function _makeDirPermissions($permissions)
- {
- $permissions = (string)$permissions;
-
- // going through (user, group, world)
- for ($i = 0; $i < strlen($permissions); $i++) {
- // Read permission is set but execute not yet
- if ((int)$permissions[$i] & 4 and !((int)$permissions[$i] & 1)) {
- // Adding execute flag
- $permissions[$i] = (int)$permissions[$i] + 1;
- }
- }
- return (string)$permissions;
- }
- /**
- * This will return the last modification-time of a file. You can either give
- * this function a relative or an absolute path to the file to check.
- * NOTE: Some servers will not support this feature and the function works
- * only on files, not directories! When successful,
- * it will return the last modification-time as a unix-timestamp or, when
- * $format is specified, a preformated timestring.
- *
- * @param string $file The file to check
- * @param string $format (optional) The format to give the date back
- * if not set, it will return a Unix timestamp
- *
- * @access public
- * @return mixed Unix timestamp, a preformated date-string or PEAR::Error
- * @see NET_FTP_ERR_MDTMDIR_UNSUPPORTED, NET_FTP_ERR_MDTM_FAILED,
- * NET_FTP_ERR_DATEFORMAT_FAILED
- */
- function mdtm($file, $format = null)
- {
- $file = $this->_constructPath($file);
- if ($this->_checkRemoteDir($file) !== false) {
- return $this->raiseError("Filename '$file' seems to be a directory.",
- NET_FTP_ERR_MDTMDIR_UNSUPPORTED);
- }
- $res = @ftp_mdtm($this->_handle, $file);
- if ($res == -1) {
- return $this->raiseError("Could not get last-modification-date of '".
- $file."'.", NET_FTP_ERR_MDTM_FAILED);
- }
- if (isset($format)) {
- $res = date($format, $res);
- if (!$res) {
- return $this->raiseError("Date-format failed on timestamp '".$res.
- "'.", NET_FTP_ERR_DATEFORMAT_FAILED);
- }
- }
- return $res;
- }
- /**
- * This will return the size of a given file in bytes. You can either give this
- * function a relative or an absolute file-path. NOTE: Some servers do not
- * support this feature!
- *
- * @param string $file The file to check
- *
- * @access public
- * @return mixed Size in bytes or PEAR::Error
- * @see NET_FTP_ERR_SIZE_FAILED
- */
- function size($file)
- {
- $file = $this->_constructPath($file);
- $res = @ftp_size($this->_handle, $file);
- if ($res == -1) {
- return $this->raiseError("Could not determine filesize of '$file'.",
- NET_FTP_ERR_SIZE_FAILED);
- } else {
- return $res;
- }
- }
- /**
- * This method returns a directory-list of the current directory or given one.
- * To display the current selected directory, simply set the first parameter to
- * null
- * or leave it blank, if you do not want to use any other parameters.
- *
- * There are 4 different modes of listing directories. Either to list only
- * the files (using NET_FTP_FILES_ONLY), to list only directories (using
- * NET_FTP_DIRS_ONLY) or to show both (using NET_FTP_DIRS_FILES, which is
- * default).
- *
- * The 4th one is the NET_FTP_RAWLIST, which returns just the array created by
- * the ftp_rawlist()-function build into PHP.
- *
- * The other function-modes will return an array containing the requested data.
- * The files and dirs are listed in human-sorted order, but if you select
- * NET_FTP_DIRS_FILES the directories will be added above the files,
- * but although both sorted.
- *
- * All elements in the arrays are associative arrays themselves. They have the
- * following structure:
- *
- * Dirs:
- * ["name"] => string The name of the directory
- * ["rights"] => string The rights of the directory (in style
- * "rwxr-xr-x")
- * ["user"] => string The owner of the directory
- * ["group"] => string The group-owner of the directory
- * ["files_inside"]=> string The number of files/dirs inside the
- * directory excluding "." and ".."
- * ["date"] => int The creation-date as Unix timestamp
- * ["is_dir"] => bool true, cause this is a dir
- *
- * Files:
- * ["name"] => string The name of the file
- * ["size"] => int Size in bytes
- * ["rights"] => string The rights of the file (in style
- * "rwxr-xr-x")
- * ["user"] => string The owner of the file
- * ["group"] => string The group-owner of the file
- * ["date"] => int The creation-date as Unix timestamp
- * ["is_dir"] => bool false, cause this is a file
- *
- * @param string $dir (optional) The directory to list or null, when listing
- * the current directory.
- * @param int $mode (optional) The mode which types to list (files,
- * directories or both).
- *
- * @access public
- * @return mixed The directory list as described above or PEAR::Error on failure
- * @see NET_FTP_DIRS_FILES, NET_FTP_DIRS_ONLY, NET_FTP_FILES_ONLY,
- * NET_FTP_RAWLIST, NET_FTP_ERR_DETERMINEPATH_FAILED,
- * NET_FTP_ERR_RAWDIRLIST_FAILED, NET_FTP_ERR_DIRLIST_UNSUPPORTED
- */
- function ls($dir = null, $mode = NET_FTP_DIRS_FILES)
- {
- if (!isset($dir)) {
- $dir = @ftp_pwd($this->_handle);
- if (!$dir) {
- return $this->raiseError("Could not retrieve current directory",
- NET_FTP_ERR_DETERMINEPATH_FAILED);
- }
- }
- if (($mode != NET_FTP_FILES_ONLY) && ($mode != NET_FTP_DIRS_ONLY) &&
- ($mode != NET_FTP_RAWLIST)) {
- $mode = NET_FTP_DIRS_FILES;
- }
- switch ($mode) {
- case NET_FTP_DIRS_FILES:
- $res = $this->_lsBoth($dir);
- break;
- case NET_FTP_DIRS_ONLY:
- $res = $this->_lsDirs($dir);
- break;
- case NET_FTP_FILES_ONLY:
- $res = $this->_lsFiles($dir);
- break;
- case NET_FTP_RAWLIST:
- $res = @ftp_rawlist($this->_handle, $dir);
- break;
- }
- return $res;
- }
- /**
- * This method will delete the given file or directory ($path) from the server
- * (maybe recursive).
- *
- * Whether the given string is a file or directory is only determined by the
- * last sign inside the string ("/" or not).
- *
- * If you specify a directory, you can optionally specify $recursive as true,
- * to let the directory be deleted recursive (with all sub-directories and files
- * inherited).
- *
- * You can either give a absolute or relative path for the file / dir. If you
- * choose to use the relative path, it will be automatically completed with the
- * actual selected directory.
- *
- * @param string $path The absolute or relative path to the file/directory.
- * @param bool $recursive Recursively delete everything in $path
- * @param bool $filesonly When deleting recursively, only delete files so the
- * directory structure is preserved
- *
- * @access public
- * @return mixed true on success, otherwise PEAR::Error
- * @see NET_FTP_ERR_DELETEFILE_FAILED, NET_FTP_ERR_DELETEDIR_FAILED,
- * NET_FTP_ERR_REMOTEPATHNODIR
- */
- function rm($path, $recursive = false, $filesonly = false)
- {
- $path = $this->_constructPath($path);
- if ($this->_checkRemoteDir($path) === true) {
- if ($recursive) {
- return $this->_rmDirRecursive($path, $filesonly);
- } else {
- return $this->_rmDir($path);
- }
- } else {
- return $this->_rmFile($path);
- }
- }
- /**
- * This function will download a file from the ftp-server. You can either
- * specify an absolute path to the file (beginning with "/") or a relative one,
- * which will be completed with the actual directory you selected on the server.
- * You can specify the path to which the file will be downloaded on the local
- * machine, if the file should be overwritten if it exists (optionally, default
- * is no overwriting) and in which mode (FTP_ASCII or FTP_BINARY) the file
- * should be downloaded (if you do not specify this, the method tries to
- * determine it automatically from the mode-directory or uses the default-mode,
- * set by you).
- * If you give a relative path to the local-file, the script-path is used as
- * basepath.
- *
- * @param string $remote_file The absolute or relative path to the file to
- * download
- * @param string $local_file The local file to put the downloaded in
- * @param bool $overwrite (optional) Whether to overwrite existing file
- * @param int $mode (optional) Either FTP_ASCII or FTP_BINARY
- *
- * @access public
- * @return mixed true on success, otherwise PEAR::Error
- * @see NET_FTP_ERR_OVERWRITELOCALFILE_FORBIDDEN,
- * NET_FTP_ERR_OVERWRITELOCALFILE_FAILED,
- * NET_FTP_ERR_OVERWRITELOCALFILE_FAILED
- */
- function get($remote_file, $local_file, $overwrite = false, $mode = null)
- {
- if (!isset($mode)) {
- $mode = $this->checkFileExtension($remote_file);
- }
- $remote_file = $this->_constructPath($remote_file);
- if (@file_exists($local_file) && !$overwrite) {
- return $this->raiseError("Local file '".$local_file.
- "' exists and may not be overwriten.",
- NET_FTP_ERR_OVERWRITELOCALFILE_FORBIDDEN);
- }
- if (@file_exists($local_file) &&
- !@is_writeable($local_file) && $overwrite) {
- return $this->raiseError("Local file '".$local_file.
- "' is not writeable. Can not overwrite.",
- NET_FTP_ERR_OVERWRITELOCALFILE_FAILED);
- }
- if (@function_exists('ftp_nb_get')) {
- $res = @ftp_nb_get($this->_handle, $local_file, $remote_file, $mode);
- while ($res == FTP_MOREDATA) {
- $this->_announce('nb_get');
- $res = @ftp_nb_continue($this->_handle);
- }
- } else {
- $res = @ftp_get($this->_handle, $local_file, $remote_file, $mode);
- }
- if (!$res) {
- return $this->raiseError("File '".$remote_file.
- "' could not be downloaded to '$local_file'.",
- NET_FTP_ERR_OVERWRITELOCALFILE_FAILED);
- } else {
- return true;
- }
- }
- /**
- * This function will upload a file to the ftp-server. You can either specify a
- * absolute path to the remote-file (beginning with "/") or a relative one,
- * which will be completed with the actual directory you selected on the server.
- * You can specify the path from which the file will be uploaded on the local
- * maschine, if the file should be overwritten if it exists (optionally, default
- * is no overwriting) and in which mode (FTP_ASCII or FTP_BINARY) the file
- * should be downloaded (if you do not specify this, the method tries to
- * determine it automatically from the mode-directory or uses the default-mode,
- * set by you).
- * If you give a relative path to the local-file, the script-path is used as
- * basepath.
- *
- * @param string $local_file The local file to upload
- * @param string $remote_file The absolute or relative path to the file to
- * upload to
- * @param bool $overwrite (optional) Whether to overwrite existing file
- * @param int $mode (optional) Either FTP_ASCII or FTP_BINARY
- * @param int $options (optional) Flags describing the behaviour of this
- * function. Currently NET_FTP_BLOCKING and
- * NET_FTP_NONBLOCKING are supported, of which
- * NET_FTP_NONBLOCKING is the default.
- *
- * @access public
- * @return mixed true on success, otherwise PEAR::Error
- * @see NET_FTP_ERR_LOCALFILENOTEXIST,
- * NET_FTP_ERR_OVERWRITEREMOTEFILE_FORBIDDEN,
- * NET_FTP_ERR_UPLOADFILE_FAILED, NET_FTP_NONBLOCKING, NET_FTP_BLOCKING
- */
- function put($local_file, $remote_file, $overwrite = false, $mode = null,
- $options = 0)
- {
- if ($options & (NET_FTP_BLOCKING | NET_FTP_NONBLOCKING) ===
- (NET_FTP_BLOCKING | NET_FTP_NONBLOCKING)) {
- return $this->raiseError('Bad options given: NET_FTP_NONBLOCKING and '.
- 'NET_FTP_BLOCKING can\'t both be set',
- NET_FTP_ERR_BADOPTIONS);
- }
-
- $usenb = ! ($options & (NET_FTP_BLOCKING == NET_FTP_BLOCKING));
-
- if (!isset($mode)) {
- $mode = $this->checkFileExtension($local_file);
- }
- $remote_file = $this->_constructPath($remote_file);
- if (!@file_exists($local_file)) {
- return $this->raiseError("Local file '$local_file' does not exist.",
- NET_FTP_ERR_LOCALFILENOTEXIST);
- }
- if ((@ftp_size($this->_handle, $remote_file) != -1) && !$overwrite) {
- return $this->raiseError("Remote file '".$remote_file.
- "' exists and may not be overwriten.",
- NET_FTP_ERR_OVERWRITEREMOTEFILE_FORBIDDEN);
- }
- if (function_exists('ftp_alloc')) {
- ftp_alloc($this->_handle, filesize($local_file));
- }
- if ($usenb && function_exists('ftp_nb_put')) {
- $res = @ftp_nb_put($this->_handle, $remote_file, $local_file, $mode);
- while ($res == FTP_MOREDATA) {
- $this->_announce('nb_put');
- $res = @ftp_nb_continue($this->_handle);
- }
- } else {
- $res = @ftp_put($this->_handle, $remote_file, $local_file, $mode);
- }
- if (!$res) {
- return $this->raiseError("File '$local_file' could not be uploaded to '"
- .$remote_file."'.",
- NET_FTP_ERR_UPLOADFILE_FAILED);
- } else {
- return true;
- }
- }
- /**
- * This functionality allows you to transfer a whole directory-structure from
- * the remote-ftp to your local host. You have to give a remote-directory
- * (ending with '/') and the local directory (ending with '/') where to put the
- * files you download.
- * The remote path is automatically completed with the current-remote-dir, if
- * you give a relative path to this function. You can give a relative path for
- * the $local_path, too. Then the script-basedir will be used for comletion of
- * the path.
- * The parameter $overwrite will determine, whether to overwrite existing files
- * or not. Standard for this is false. Fourth you can explicitly set a mode for
- * all transfer actions done. If you do not set this, the method tries to
- * determine the transfer mode by checking your mode-directory for the file
- * extension. If the extension is not inside the mode-directory, it will get
- * your default mode.
- *
- * Since 1.4 no error will be returned when a file exists while $overwrite is
- * set to false.
- *
- * @param string $remote_path The path to download
- * @param string $local_path The path to download to
- * @param bool $overwrite (optional) Whether to overwrite existing files
- * (true) or not (false, standard).
- * @param int $mode (optional) The transfermode (either FTP_ASCII or
- * FTP_BINARY).
- * @param array $excluded_paths (optional) List of remote files or directories to
- * exclude from the transfer. All files and
- * directories must be stated as absolute paths.
- * Note: You must include a trailing slash on directory names.
- *
- * @access public
- * @return mixed true on succes, otherwise PEAR::Error
- * @see NET_FTP_ERR_OVERWRITELOCALFILE_FORBIDDEN,
- * NET_FTP_ERR_OVERWRITELOCALFILE_FAILED, NET_FTP_ERR_OVERWRITELOCALFILE_FAILED,
- * NET_FTP_ERR_REMOTEPATHNODIR, NET_FTP_ERR_LOCALPATHNODIR,
- * NET_FTP_ERR_CREATELOCALDIR_FAILED
- */
- function getRecursive($remote_path, $local_path, $overwrite = false,
- $mode = null, $excluded_paths = array())
- {
- $remote_path = $this->_constructPath($remote_path);
- if ($this->_checkRemoteDir($remote_path) !== true) {
- return $this->raiseError("Given remote-path '".$remote_path.
- "' seems not to be a directory.",
- NET_FTP_ERR_REMOTEPATHNODIR);
- }
- if (!@file_exists($local_path)) {
- $res = @mkdir($local_path);
- if (!$res) {
- return $this->raiseError("Could not create dir '$local_path'",
- NET_FTP_ERR_CREATELOCALDIR_FAILED);
- }
- } elseif (!@is_dir($local_path)) {
- return $this->raiseError("Given local-path '".$local_path.
- "' seems not to be a directory.",
- NET_FTP_ERR_LOCALPATHNODIR);
- }
-
- $dir_list = array();
- $dir_list = $this->ls($remote_path, NET_FTP_DIRS_ONLY);
- if (PEAR::isError($dir_list)) {
- return $dir_list;
- }
- foreach ($dir_list as $dir_entry) {
- if ($dir_entry['name'] != '.' && $dir_entry['name'] != '..') {
- $remote_path_new = $remote_path.$dir_entry["name"]."/";
- $local_path_new = $local_path.$dir_entry["name"]."/";
- // Check whether the directory should be excluded
- if (!in_array($remote_path_new, $excluded_paths)) {
- $result = $this->getRecursive($remote_path_new,
- $local_path_new, $overwrite, $mode);
- if ($this->isError($result)) {
- return $result;
- }
- }
- }
- }
- $file_list = array();
- $file_list = $this->ls($remote_path, NET_FTP_FILES_ONLY);
- if (PEAR::isError($file_list)) {
- return $file_list;
- }
- foreach ($file_list as $file_entry) {
- $remote_file = $remote_path.$file_entry["name"];
- $local_file = $local_path.$file_entry["name"];
- // Check whether the file should be excluded
- if (!in_array($remote_file, $excluded_paths)) {
- $result = $this->get($remote_file, $local_file, $overwrite, $mode);
- if ($this->isError($result) &&
- $result->getCode() != NET_FTP_ERR_OVERWRITELOCALFILE_FORBIDDEN) {
- return $result;
- }
- }
- }
- return true;
- }
- /**
- * This functionality allows you to transfer a whole directory-structure from
- * your local host to the remote-ftp. You have to give a remote-directory
- * (ending with '/') and the local directory (ending with '/') where to put the
- * files you download. The remote path is automatically completed with the
- * current-remote-dir, if you give a relative path to this function. You can
- * give a relative path for the $local_path, too. Then the script-basedir will
- * be used for comletion of the path.
- * The parameter $overwrite will determine, whether to overwrite existing files
- * or not.
- * Standard for this is false. Fourth you can explicitly set a mode for all
- * transfer actions done. If you do not set this, the method tries to determine
- * the transfer mode by checking your mode-directory for the file-extension. If
- * the extension is not inside the mode-directory, it will get your default
- * mode.
- *
- * @param string $local_path The path to download to
- * @param string $remote_path The path to download
- * @param bool $overwrite (optional) Whether to overwrite existing files
- * (true) or not (false, standard).
- * @param int $mode (optional) The transfermode (either FTP_ASCII or
- * FTP_BINARY).
- * @param array $excluded_paths (optional) List of local files or directories to
- * exclude from the transfer. All files and
- * directories must be stated as absolute paths.
- * Note: You must include a trailing slash on
- * directory names.
- *
- * @access public
- * @return mixed true on succes, otherwise PEAR::Error
- * @see NET_FTP_ERR_LOCALFILENOTEXIST,
- * NET_FTP_ERR_OVERWRITEREMOTEFILE_FORBIDDEN,
- * NET_FTP_ERR_UPLOADFILE_FAILED, NET_FTP_ERR_LOCALPATHNODIR,
- * NET_FTP_ERR_REMOTEPATHNODIR
- */
- function putRecursive($local_path, $remote_path, $overwrite = false,
- $mode = null, $excluded_paths = array())
- {
- $remote_path = $this->_constructPath($remote_path);
- if (!file_exists($local_path) || !is_dir($local_path)) {
- return $this->raiseError("Given local-path '".$local_path.
- "' seems not to be a directory.",
- NET_FTP_ERR_LOCALPATHNODIR);
- }
- // try to create directory if it doesn't exist
- $old_path = $this->pwd();
- if ($this->isError($this->cd($remote_path))) {
- $res = $this->mkdir($remote_path);
- if ($this->isError($res)) {
- return $res;
- }
- }
- $this->cd($old_path);
- if ($this->_checkRemoteDir($remote_path) !== true) {
- return $this->raiseError("Given remote-path '".$remote_path.
- "' seems not to be a directory.",
- NET_FTP_ERR_REMOTEPATHNODIR);
- }
- $dir_list = $this->_lsLocal($local_path);
- foreach ($dir_list["dirs"] as $dir_entry) {
- // local directories do not have arrays as entry
- $remote_path_new = $remote_path.$dir_entry."/";
- $local_path_new = $local_path.$dir_entry."/";
- // Check whether the directory should be excluded
- if (!in_array($local_path_new, $excluded_paths)) {
- $result = $this->putRecursive($local_path_new,
- $remote_path_new, $overwrite, $mode,
- $excluded_paths);
- if ($this->isError($result)) {
- return $result;
- }
- }
- }
- foreach ($dir_list["files"] as $file_entry) {
- $remote_file = $remote_path.$file_entry;
- $local_file = $local_path.$file_entry;
- // Check whether the file should be excluded
- if (!in_array($local_file, $excluded_paths)) {
- $result = $this->put($local_file, $remote_file, $overwrite, $mode);
- if ($this->isError($result)) {
- return $result;
- }
- }
- }
- return true;
- }
- /**
- * This checks, whether a file should be transfered in ascii- or binary-mode
- * by it's file-extension. If the file-extension is not set or
- * the extension is not inside one of the extension-dirs, the actual set
- * transfer-mode is returned.
- *
- * @param string $filename The filename to be checked
- *
- * @access public
- * @return int Either FTP_ASCII or FTP_BINARY
- */
- function checkFileExtension($filename)
- {
- if (($pos = strrpos($filename, '.')) === false) {
- return $this->_mode;
- } else {
- $ext = substr($filename, $pos + 1);
- }
-
- if (isset($this->_file_extensions[$ext])) {
- return $this->_file_extensions[$ext];
- }
-
- return $this->_mode;
- }
- /**
- * Set the hostname
- *
- * @param string $host The hostname to set
- *
- * @access public
- * @return bool true on success, otherwise PEAR::Error
- * @see NET_FTP_ERR_HOSTNAMENOSTRING
- */
- function setHostname($host)
- {
- if (!is_string($host)) {
- return PEAR::raiseError("Hostname must be a string.",
- NET_FTP_ERR_HOSTNAMENOSTRING);
- }
- $this->_hostname = $host;
- return true;
- }
- /**
- * Set the Port
- *
- * @param int $port The port to set
- *
- * @access public
- * @return bool true on success, otherwise PEAR::Error
- * @see NET_FTP_ERR_PORTLESSZERO
- */
- function setPort($port)
- {
- if (!is_int($port) || ($port < 0)) {
- PEAR::raiseError("Invalid port. Has to be integer >= 0",
- NET_FTP_ERR_PORTLESSZERO);
- }
- $this->_port = $port;
- return true;
- }
- /**
- * Set to connect through secure SSL connection
- *
- * @access public
- * @return bool true on success, otherwise PEAR::Error
- */
- function setSsl()
- {
- if (!function_exists('ftp_ssl_connect')) {
- return PEAR::raiseError('SSL connection not supported. Function ftp_ssl_connect does not exist.',
- NET_FTP_ERR_NOSSL);
- }
- $this->_ssl = true;
- return true;
- }
- /**
- * Set the Username
- *
- * @param string $user The username to set
- *
- * @access public
- * @return mixed true on success, otherwise PEAR::Error
- * @see NET_FTP_ERR_USERNAMENOSTRING
- */
- function setUsername($user)
- {
- if (empty($user) || !is_string($user)) {
- return PEAR::raiseError('Username $user invalid.',
- NET_FTP_ERR_USERNAMENOSTRING);
- }
- $this->_username = $user;
- return true;
- }
- /**
- * Set the password
- *
- * @param string $password The password to set
- *
- * @access private
- * @return mixed true on success, otherwise PEAR::Error
- * @see NET_FTP_ERR_PASSWORDNOSTRING
- */
- function setPassword($password)
- {
- if (empty($password) || !is_string($password)) {
- return PEAR::raiseError('Password xxx invalid.',
- NET_FTP_ERR_PASSWORDNOSTRING);
- }
- $this->_password = $password;
- return true;
- }
- /**
- * Set the transfer-mode. You can use the predefined constants
- * FTP_ASCII or FTP_BINARY. The mode will be stored for any further transfers.
- *
- * @param int $mode The mode to set
- *
- * @access public
- * @return mixed true on success, otherwise PEAR::Error
- * @see NET_FTP_ERR_NOMODECONST
- */
- function setMode($mode)
- {
- if (($mode == FTP_ASCII) || ($mode == FTP_BINARY)) {
- $this->_mode = $mode;
- return true;
- } else {
- return $this->raiseError('FTP-Mode has either to be FTP_ASCII or'.
- 'FTP_BINARY', NET_FTP_ERR_NOMODECONST);
- }
- }
- /**
- * Set the transfer-method to passive mode
- *
- * @access public
- * @return void
- */
- function setPassive()
- {
- $this->_passv = true;
- if ($this->_handle != null && $this->_loggedin) {
- @ftp_pasv($this->_handle, true);
- }
- }
- /**
- * Set the transfer-method to active mode
- *
- * @access public
- * @return void
- */
- function setActive()
- {
- $this->_passv = false;
- if ($this->_handle != null && $this->_loggedin) {
- @ftp_pasv($this->_handle, false);
- }
- }
- /**
- * Set the timeout for FTP operations
- *
- * Use this method to set a timeout for FTP operation. Timeout has to be an
- * integer.
- *
- * @param int $timeout the timeout to use
- *
- * @access public
- * @return bool true on success, otherwise PEAR::Error
- * @see NET_FTP_ERR_TIMEOUTLESSZERO, NET_FTP_ERR_SETTIMEOUT_FAILED
- */
- function setTimeout ( $timeout = 0 )
- {
- if (!is_int($timeout) || ($timeout < 0)) {
- return PEAR::raiseError('Timeout '.$timeout.
- ' is invalid, has to be an integer >= 0',
- NET_FTP_ERR_TIMEOUTLESSZERO);
- }
- $this->_timeout = $timeout;
- if (isset($this->_handle) && is_resource($this->_handle)) {
- $res = @ftp_set_option($this->_handle, FTP_TIMEOUT_SEC, $timeout);
- } else {
- $res = true;
- }
- if (!$res) {
- return PEAR::raiseError("Set timeout failed.",
- NET_FTP_ERR_SETTIMEOUT_FAILED);
- }
- return true;
- }
- /**
- * Adds an extension to a mode-directory
- *
- * The mode-directory saves file-extensions coresponding to filetypes
- * (ascii e.g.: 'php', 'txt', 'htm',...; binary e.g.: 'jpg', 'gif', 'exe',...).
- * The extensions have to be saved without the '.'. And
- * can be predefined in an external file (see: getExtensionsFile()).
- *
- * The array is build like this: 'php' => FTP_ASCII, 'png' => FTP_BINARY
- *
- * To change the mode of an extension, just add it again with the new mode!
- *
- * @param int $mode Either FTP_ASCII or FTP_BINARY
- * @param string $ext Extension
- *
- * @access public
- * @return void
- */
- function addExtension($mode, $ext)
- {
- $this->_file_extensions[$ext] = $mode;
- }
- /**
- * This function removes an extension from the mode-directories
- * (described above).
- *
- * @param string $ext The extension to remove
- *
- * @access public
- * @return void
- */
- function removeExtension($ext)
- {
- if (isset($this->_file_extensions[$ext])) {
- unset($this->_file_extensions[$ext]);
- }
- }
- /**
- * This get's both (ascii- and binary-mode-directories) from the given file.
- * Beware, if you read a file into the mode-directory, all former set values
- * will be unset!
- *
- * Example file contents:
- * [ASCII]
- * asc = 0
- * txt = 0
- * [BINARY]
- * bin = 1
- * jpg = 1
- *
- * @param string $filename The file to get from
- *
- * @access public
- * @return mixed true on success, otherwise PEAR::Error
- * @see NET_FTP_ERR_EXTFILENOTEXIST, NET_FTP_ERR_EXTFILEREAD_FAILED
- */
- function getExtensionsFile($filename)
- {
- if (!file_exists($filename)) {
- return $this->raiseError("Extensions-file '$filename' does not exist",
- NET_FTP_ERR_EXTFILENOTEXIST);
- }
-
- if (!is_readable($filename)) {
- return $this->raiseError("Extensions-file '$filename' is not readable",
- NET_FTP_ERR_EXTFILEREAD_FAILED);
- }
-
- $exts = @parse_ini_file($filename, true);
- if (!is_array($exts)) {
- return $this->raiseError("Extensions-file '$filename' could not be".
- "loaded", NET_FTP_ERR_EXTFILELOAD_FAILED);
- }
-
- $this->_file_extensions = array();
-
- if (isset($exts['ASCII'])) {
- foreach (array_keys($exts['ASCII']) as $ext) {
- $this->_file_extensions[$ext] = FTP_ASCII;
- }
- }
-
- if (isset($exts['BINARY'])) {
- foreach (array_keys($exts['BINARY']) as $ext) {
- $this->_file_extensions[$ext] = FTP_BINARY;
- }
- }
-
- return true;
- }
- /**
- * Returns the hostname
- *
- * @access public
- * @return string The hostname
- */
- function getHostname()
- {
- return $this->_hostname;
- }
- /**
- * Returns the port
- *
- * @access public
- * @return int The port
- */
- function getPort()
- {
- return $this->_port;
- }
- /**
- * Returns whether to connect through secure SSL connection
- *
- * @access public
- * @return bool true if with SSL, false if without SSL
- */
- function getSsl()
- {
- return $this->_ssl;
- }
- /**
- * Returns the username
- *
- * @access public
- * @return string The username
- */
- function getUsername()
- {
- return $this->_username;
- }
- /**
- * Returns the password
- *
- * @access public
- * @return string The password
- */
- function getPassword()
- {
- return $this->_password;
- }
- /**
- * Returns the transfermode
- *
- * @access public
- * @return int The transfermode, either FTP_ASCII or FTP_BINARY.
- */
- function getMode()
- {
- return $this->_mode;
- }
- /**
- * Returns, whether the connection is set to passive mode or not
- *
- * @access public
- * @return bool true if passive-, false if active-mode
- */
- function isPassive()
- {
- return $this->_passv;
- }
- /**
- * Returns the mode set for a file-extension
- *
- * @param string $ext The extension you wanna ask for
- *
- * @return int Either FTP_ASCII, FTP_BINARY or NULL (if not set a mode for it)
- * @access public
- */
- function getExtensionMode($ext)
- {
- return @$this->_file_extensions[$ext];
- }
- /**
- * Get the currently set timeout.
- * Returns the actual timeout set.
- *
- * @access public
- * @return int The actual timeout
- */
- function getTimeout()
- {
- return ftp_get_option($this->_handle, FTP_TIMEOUT_SEC);
- }
- /**
- * Adds a Net_FTP_Observer instance to the list of observers
- * that are listening for messages emitted by this Net_FTP instance.
- *
- * @param object &$observer The Net_FTP_Observer instance to attach
- * as a listener.
- *
- * @return boolean true if the observer is successfully attached.
- * @access public
- * @since 1.3
- */
- function attach(&$observer)
- {
- if (!is_a($observer, 'Net_FTP_Observer')) {
- return false;
- }
- $this->_listeners[$observer->getId()] = &$observer;
- return true;
- }
- /**
- * Removes a Net_FTP_Observer instance from the list of observers.
- *
- * @param object $observer The Net_FTP_Observer instance to detach
- * from the list of listeners.
- *
- * @return boolean true if the observer is successfully detached.
- * @access public
- * @since 1.3
- */
- function detach($observer)
- {
- if (!is_a($observer, 'Net_FTP_Observer') ||
- !isset($this->_listeners[$observer->getId()])) {
- return false;
- }
- unset($this->_listeners[$observer->getId()]);
- return true;
- }
- /**
- * Sets the directory listing matcher
- *
- * Use this method to set the directory listing matcher to a specific pattern.
- * Indicate the pattern as a perl regular expression and give an array
- * containing as keys the fields selected in the regular expression and as
- * values the offset of the subpattern in the pattern.
- *
- * Example:
- * $pattern = '/(?:(d)|.)([rwxt-]+)\s+(\w+)\s+([\w\d-]+)\s+([\w\d-]+)\s+(\w+)
- * \s+(\S+\s+\S+\s+\S+)\s+(.+)/',
- * $matchmap = array(
- * 'is_dir' => 1,
- * 'rights' => 2,
- * 'files_inside' => 3,
- * 'user' => 4,
- * 'group' => 5,
- * 'size' => 6,
- * 'date' => 7,
- * 'name' => 8,
- * )
- *
- * Make sure at least the is_dir and name keys are set. The is_dir key should
- * point to a subpattern that is empty for non-directories and non-empty
- * for directories.
- *
- * @param string $pattern The new matcher pattern to use
- * @param array $matchmap An mapping from key to subpattern offset
- *
- * @since 1.4.0a1
- * @access public
- * @return bool|PEAR_Error true if matcher set successfully, PEAR_Error
- * otherwise
- * @see NET_FTP_ERR_ILLEGALPATTERN,
- * NET_FTP_ERR_ILLEGALMAP
- * NET_FTP_ERR_ILLEGALMAPVALUE
- */
- function setDirMatcher($pattern, $matchmap)
- {
- if (!is_string($pattern)) {
- return $this->raiseError('The supplied pattern is not a string',
- NET_FTP_ERR_ILLEGALPATTERN);
- }
- if (!is_array($matchmap)) {
- return $this->raiseError('The supplied pattern is not an array',
- NET_FTP_ERR_ILLEGALMAP);
- } else {
- foreach ($matchmap AS $val) {
- if (!is_numeric($val)) {
- return $this->raiseError('The supplied pattern contains'.
- 'invalid value '.$val,
- NET_FTP_ERR_ILLEGALMAPVALUE);
- }
- }
- }
-
- $this->_matcher = array('pattern' => $pattern, 'map' => $matchmap);
-
- return true;
- }
- /**
- * Informs each registered observer instance that a new message has been
- * sent.
- *
- * @param mixed $event A hash describing the net event.
- *
- * @access private
- * @since 1.3
- * @return void
- */
- function _announce($event)
- {
- foreach ($this->_listeners as $listener) {
- $listener->notify($event);
- }
- }
- /**
- * Rebuild the path, if given relative
- *
- * This method will make a relative path absolute by prepending the current
- * remote directory in front of it.
- *
- * @param string $path The path to check and construct
- *
- * @access private
- * @return string The build path
- */
- function _constructPath($path)
- {
- if ((substr($path, 0, 1) != '/') && (substr($path, 0, 2) != './')) {
- $actual_dir = @ftp_pwd($this->_handle);
- if (substr($actual_dir, -1) != '/') {
- $actual_dir .= '/';
- }
- $path = $actual_dir.$path;
- }
- return $path;
- }
- /**
- * Checks whether the given path is a remote directory by trying to
- * chdir() into it (and back out)
- *
- * @param string $path Path to check
- *
- * @access private
- * @return mixed true if $path is a directory, otherwise false, PEAR_Error
- * when an error occurs in determining path type
- */
- function _checkRemoteDir($path)
- {
- $pwd = $this->pwd();
- if ($this->isError($pwd)) {
- return $pwd;
- }
- $res = $this->cd($path);
- $this->cd($pwd);
-
- return $this->isError($res, NET_FTP_ERR_DIRCHANGE_FAILED) === false;
- }
- /**
- * This will remove a file
- *
- * @param string $file The file to delete
- *
- * @access private
- * @return mixed true on success, otherwise PEAR::Error
- * @see NET_FTP_ERR_DELETEFILE_FAILED
- */
- function _rmFile($file)
- {
- if (substr($file, 0, 1) != "/") {
- $actual_dir = @ftp_pwd($this->_handle);
- if (substr($actual_dir, (strlen($actual_dir) - 2), 1) != "/") {
- $actual_dir .= "/";
- }
- $file = $actual_dir.$file;
- }
- $res = @ftp_delete($this->_handle, $file);
-
- if (!$res) {
- return $this->raiseError("Could not delete file '$file'.",
- NET_FTP_ERR_DELETEFILE_FAILED);
- } else {
- return true;
- }
- }
- /**
- * This will remove a dir
- *
- * @param string $dir The dir to delete
- *
- * @access private
- * @return mixed true on success, otherwise PEAR::Error
- * @see NET_FTP_ERR_REMOTEPATHNODIR, NET_FTP_ERR_DELETEDIR_FAILED
- */
- function _rmDir($dir)
- {
- if (substr($dir, (strlen($dir) - 1), 1) != "/") {
- return $this->raiseError("Directory name '".$dir.
- "' is invalid, has to end with '/'",
- NET_FTP_ERR_REMOTEPATHNODIR);
- }
- $res = @ftp_rmdir($this->_handle, $dir);
- if (!$res) {
- return $this->raiseError("Could not delete directory '$dir'.",
- NET_FTP_ERR_DELETEDIR_FAILED);
- } else {
- return true;
- }
- }
- /**
- * This will remove a dir and all subdirs and -files
- *
- * @param string $dir The dir to delete recursively
- * @param bool $filesonly Only delete files so the directory structure is
- * preserved
- *
- * @access private
- * @return mixed true on success, otherwise PEAR::Error
- * @see NET_FTP_ERR_REMOTEPATHNODIR, NET_FTP_ERR_DELETEDIR_FAILED
- */
- function _rmDirRecursive($dir, $filesonly = false)
- {
- if (substr($dir, (strlen($dir) - 1), 1) != "/") {
- return $this->raiseError("Directory name '".$dir.
- "' is invalid, has to end with '/'",
- NET_FTP_ERR_REMOTEPATHNODIR);
- }
- $file_list = $this->_lsFiles($dir);
- if (PEAR::isError($file_list)) {
- return $file_list;
- }
-
- foreach ($file_list as $file) {
- $file = $dir.$file["name"];
- $res = $this->rm($file);
- if ($this->isError($res)) {
- return $res;
- }
- }
-
- $dir_list = $this->_lsDirs($dir);
- if (PEAR::isError($dir_list)) {
- return $dir_list;
- }
-
- foreach ($dir_list as $new_dir) {
- if ($new_dir["name"] == '.' || $new_dir["name"] == '..') {
- continue;
- }
- $new_dir = $dir.$new_dir["name"]."/";
- $res = $this->_rmDirRecursive($new_dir, $filesonly);
- if ($this->isError($res)) {
- return $res;
- }
- }
- if (!$filesonly) {
- $res = $this->_rmDir($dir);
- }
- if (PEAR::isError($res)) {
- return $res;
- } else {
- return true;
- }
- }
- /**
- * Lists up files and directories
- *
- * @param string $dir The directory to list up
- *
- * @access private
- * @return array An array of dirs and files
- */
- function _lsBoth($dir)
- {
- $list_splitted = $this->_listAndParse($dir);
- if (PEAR::isError($list_splitted)) {
- return $list_splitted;
- }
- if (!is_array($list_splitted["files"])) {
- $list_splitted["files"] = array();
- }
- if (!is_array($list_splitted["dirs"])) {
- $list_splitted["dirs"] = array();
- }
- $res = array();
- @array_splice($res, 0, 0, $list_splitted["files"]);
- @array_splice($res, 0, 0, $list_splitted["dirs"]);
- return $res;
- }
- /**
- * Lists up directories
- *
- * @param string $dir The directory to list up
- *
- * @access private
- * @return array An array of dirs
- */
- function _lsDirs($dir)
- {
- $list = $this->_listAndParse($dir);
- if (PEAR::isError($list)) {
- return $list;
- }
- return $list["dirs"];
- }
- /**
- * Lists up files
- *
- * @param string $dir The directory to list up
- *
- * @access private
- * @return array An array of files
- */
- function _lsFiles($dir)
- {
- $list = $this->_listAndParse($dir);
- if (PEAR::isError($list)) {
- return $list;
- }
- return $list["files"];
- }
- /**
- * This lists up the directory-content and parses the items into well-formated
- * arrays.
- * The results of this array are sorted (dirs on top, sorted by name;
- * files below, sorted by name).
- *
- * @param string $dir The directory to parse
- *
- * @access private
- * @return array Lists of dirs and files
- * @see NET_FTP_ERR_RAWDIRLIST_FAILED
- */
- function _listAndParse($dir)
- {
- $dirs_list = array();
- $files_list = array();
- $dir_list = @ftp_rawlist($this->_handle, $dir);
- if (!is_array($dir_list)) {
- return PEAR::raiseError('Could not get raw directory listing.',
- NET_FTP_ERR_RAWDIRLIST_FAILED);
- }
-
- foreach ($dir_list AS $k=>$v) {
- if (strncmp($v, 'total: ', 7) == 0 && preg_match('/total: \d+/', $v)) {
- unset($dir_list[$k]);
- break; // usually there is just one line like this
- }
- }
-
- // Handle empty directories
- if (count($dir_list) == 0) {
- return array('dirs' => $dirs_list, 'files' => $files_list);
- }
- // Exception for some FTP servers seem to return this wiered result instead
- // of an empty list
- if (count($dirs_list) == 1 && $dirs_list[0] == 'total 0') {
- return array('dirs' => array(), 'files' => $files_list);
- }
-
- if (!isset($this->_matcher) || PEAR::isError($this->_matcher)) {
- $this->_matcher = $this->_determineOSMatch($dir_list);
- if (PEAR::isError($this->_matcher)) {
- return $this->_matcher;
- }
- }
- foreach ($dir_list as $entry) {
- $m = array();
- if (!preg_match($this->_matcher['pattern'], $entry, $m)) {
- continue;
- }
- $entry = array();
- foreach ($this->_matcher['map'] as $key=>$val) {
- $entry[$key] = $m[$val];
- }
- $entry['stamp'] = $this->_parseDate($entry['date']);
- if ($entry['is_dir']) {
- $dirs_list[] = $entry;
- } else {
- $files_list[] = $entry;
- }
- }
- @usort($dirs_list, array("Net_FTP", "_natSort"));
- @usort($files_list, array("Net_FTP", "_natSort"));
- $res["dirs"] = (is_array($dirs_list)) ? $dirs_list : array();
- $res["files"] = (is_array($files_list)) ? $files_list : array();
- return $res;
- }
- /**
- * Determine server OS
- * This determines the server OS and returns a valid regex to parse
- * ls() output.
- *
- * @param array &$dir_list The raw dir list to parse
- *
- * @access private
- * @return mixed An array of 'pattern' and 'map' on success, otherwise
- * PEAR::Error
- * @see NET_FTP_ERR_DIRLIST_UNSUPPORTED
- */
- function _determineOSMatch(&$dir_list)
- {
- foreach ($dir_list as $entry) {
- foreach ($this->_ls_match as $match) {
- if (preg_match($match['pattern'], $entry)) {
- return $match;
- }
- }
- }
- $error = 'The list style of your server seems not to be supported. Please'.
- 'email a "$ftp->ls(NET_FTP_RAWLIST);" output plus info on the'.
- 'server to the maintainer of this package to get it supported!'.
- 'Thanks for your help!';
- return PEAR::raiseError($error, NET_FTP_ERR_DIRLIST_UNSUPPORTED);
- }
- /**
- * Lists a local directory
- *
- * @param string $dir_path The dir to list
- *
- * @access private
- * @return array The list of dirs and files
- */
- function _lsLocal($dir_path)
- {
- $dir = dir($dir_path);
- $dir_list = array();
- $file_list = array();
- while (false !== ($entry = $dir->read())) {
- if (($entry != '.') && ($entry != '..')) {
- if (is_dir($dir_path.$entry)) {
- $dir_list[] = $entry;
- } else {
- $file_list[] = $entry;
- }
- }
- }
- $dir->close();
- $res['dirs'] = $dir_list;
- $res['files'] = $file_list;
- return $res;
- }
- /**
- * Function for use with usort().
- * Compares the list-array-elements by name.
- *
- * @param string $item_1 first item to be compared
- * @param string $item_2 second item to be compared
- *
- * @access private
- * @return int < 0 if $item_1 is less than $item_2, 0 if equal and > 0 otherwise
- */
- function _natSort($item_1, $item_2)
- {
- return strnatcmp($item_1['name'], $item_2['name']);
- }
- /**
- * Parse dates to timestamps
- *
- * @param string $date Date
- *
- * @access private
- * @return int Timestamp
- * @see NET_FTP_ERR_DATEFORMAT_FAILED
- */
- function _parseDate($date)
- {
- // Sep 10 22:06 => Sep 10, 22:06
- $res = array();
- if (preg_match('/([A-Za-z]+)[ ]+([0-9]+)[ ]+([0-9]+):([0-9]+)/', $date,
- $res)) {
- $year = date('Y');
- $month = $res[1];
- $day = $res[2];
- $hour = $res[3];
- $minute = $res[4];
- $date = "$month $day, $year $hour:$minute";
- $tmpDate = strtotime($date);
- if ($tmpDate > time()) {
- $year--;
- $date = "$month $day, $year $hour:$minute";
- }
- } elseif (preg_match('/^\d\d-\d\d-\d\d/', $date)) {
- // 09-10-04 => 09/10/04
- $date = str_replace('-', '/', $date);
- }
- $res = strtotime($date);
- if (!$res) {
- return $this->raiseError('Dateconversion failed.',
- NET_FTP_ERR_DATEFORMAT_FAILED);
- }
- return $res;
- }
-}
-?>
\ No newline at end of file
diff --git a/lmo/includes/IT.php b/lmo/includes/IT.php
deleted file mode 100644
index 2d301b43..00000000
--- a/lmo/includes/IT.php
+++ /dev/null
@@ -1,1041 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-// $Id: IT.php 432 2009-03-08 13:26:56Z jokerlmo $
-//
-
-//jokerlmo: Changed include path
-require_once(PATH_TO_LMO.'/includes/PEAR.php');
-
-define("IT_OK", 1);
-define("IT_ERROR", -1);
-define("IT_TPL_NOT_FOUND", -2);
-define("IT_BLOCK_NOT_FOUND", -3);
-define("IT_BLOCK_DUPLICATE", -4);
-define('IT_UNKNOWN_OPTION', -6);
-/**
- * Integrated Template - IT
- *
- * Well there's not much to say about it. I needed a template class that
- * supports a single template file with multiple (nested) blocks inside and
- * a simple block API.
- *
- * The Isotemplate API is somewhat tricky for a beginner although it is the best
- * one you can build. template::parse() [phplib template = Isotemplate] requests
- * you to name a source and a target where the current block gets parsed into.
- * Source and target can be block names or even handler names. This API gives you
- * a maximum of fexibility but you always have to know what you do which is
- * quite unusual for php skripter like me.
- *
- * I noticed that I do not any control on which block gets parsed into which one.
- * If all blocks are within one file, the script knows how they are nested and in
- * which way you have to parse them. IT knows that inner1 is a child of block2, there's
- * no need to tell him about this.
- *
- *
- *
- *
- * __global__
- *
- * (hidden and automatically added)
- *
- *
- *
- * block1
- *
- *
- *
- * block2
- *
- *
- * inner1
- * inner2
- *
- *
- *
- *
- *
- *
- * To add content to block1 you simply type:
- * $tpl->setCurrentBlock("block1");
- * and repeat this as often as needed:
- *
- * $tpl->setVariable(...);
- * $tpl->parseCurrentBlock();
- *
- *
- * To add content to block2 you would type something like:
- *
- * $tpl->setCurrentBlock("inner1");
- * $tpl->setVariable(...);
- * $tpl->parseCurrentBlock();
- *
- * $tpl->setVariable(...);
- * $tpl->parseCurrentBlock();
- *
- * $tpl->parse("block1");
- *
- *
- * This will result in one repition of block1 which contains two repitions
- * of inner1. inner2 will be removed if $removeEmptyBlock is set to true which is the default.
- *
- * Usage:
- *
- * $tpl = new HTML_Template_IT( [string filerootdir] );
- *
- * // load a template or set it with setTemplate()
- * $tpl->loadTemplatefile( string filename [, boolean removeUnknownVariables, boolean removeEmptyBlocks] )
- *
- * // set "global" Variables meaning variables not beeing within a (inner) block
- * $tpl->setVariable( string variablename, mixed value );
- *
- * // like with the Isotemplates there's a second way to use setVariable()
- * $tpl->setVariable( array ( string varname => mixed value ) );
- *
- * // Let's use any block, even a deeply nested one
- * $tpl->setCurrentBlock( string blockname );
- *
- * // repeat this as often as you need it.
- * $tpl->setVariable( array ( string varname => mixed value ) );
- * $tpl->parseCurrentBlock();
- *
- * // get the parsed template or print it: $tpl->show()
- * $tpl->get();
- *
- *
- * @author Ulf Wendel
- * @version $Id: IT.php 432 2009-03-08 13:26:56Z jokerlmo $
- * @access public
- * @package HTML_Template_IT
- */
-
-#[\AllowDynamicProperties]
-
-class HTML_Template_IT {
-
- /**
- * Contains the error objects
- * @var array
- * @access public
- * @see halt(), $printError, $haltOnError
- */
- var $err = array();
-
- /**
- * Clear cache on get()?
- * @var boolean
- */
- var $clearCache = false;
-
- /**
- * First character of a variable placeholder ( _{_VARIABLE} ).
- * @var string
- * @access public
- * @see $closingDelimiter, $blocknameRegExp, $variablenameRegExp
- */
- var $openingDelimiter = "";
-
- /**
- * RegExp matching a block in the template.
- * Per default "sm" is used as the regexp modifier, "i" is missing.
- * That means a case sensitive search is done.
- * @var string
- * @access public
- * @see $variablenameRegExp, $openingDelimiter, $closingDelimiter
- */
- var $blocknameRegExp = "[0-9A-Za-z_-]+";
-
- /**
- * RegExp matching a variable placeholder in the template.
- * Per default "sm" is used as the regexp modifier, "i" is missing.
- * That means a case sensitive search is done.
- * @var string
- * @access public
- * @see $blocknameRegExp, $openingDelimiter, $closingDelimiter
- */
- var $variablenameRegExp = "[0-9A-Za-z_-]+";
-
- /**
- * RegExp used to find variable placeholder, filled by the constructor.
- * @var string Looks somewhat like @(delimiter varname delimiter)@
- * @access public
- * @see IntegratedTemplate()
- */
- var $variablesRegExp = "";
-
- /**
- * RegExp used to strip unused variable placeholder.
- * @brother $variablesRegExp
- */
- var $removeVariablesRegExp = "";
-
- /**
- * Controls the handling of unknown variables, default is remove.
- * @var boolean
- * @access public
- */
- var $removeUnknownVariables = false;
-
- /**
- * Controls the handling of empty blocks, default is remove.
- * @var boolean
- * @access public
- */
- var $removeEmptyBlocks = true;
-
- /**
- * RegExp used to find blocks an their content, filled by the constructor.
- * @var string
- * @see IntegratedTemplate()
- */
- var $blockRegExp = "";
-
- /**
- * Name of the current block.
- * @var string
- */
- var $currentBlock = "__global__";
-
- /**
- * Content of the template.
- * @var string
- */
- var $template = "";
-
- /**
- * Array of all blocks and their content.
- *
- * @var array
- * @see findBlocks()
- */
- var $blocklist = array();
-
- /**
- * Array with the parsed content of a block.
- *
- * @var array
- */
- var $blockdata = array();
-
- /**
- * Array of variables in a block.
- * @var array
- */
- var $blockvariables = array();
-
- /**
- * Array of inner blocks of a block.
- * @var array
- */
- var $blockinner = array();
-
- /**
- * List of blocks to preverse even if they are "empty".
- *
- * This is something special. Sometimes you have blocks that
- * should be preserved although they are empty (no placeholder replaced).
- * Think of a shopping basket. If it's empty you have to drop a message to
- * the user. If it's filled you have to show the contents of
- * the shopping baseket. Now where do you place the message that the basket
- * is empty? It's no good idea to place it in you applications as customers
- * tend to like unecessary minor text changes. Having another template file
- * for an empty basket means that it's very likely that one fine day
- * the filled and empty basket templates have different layout. I decided
- * to introduce blocks that to not contain any placeholder but only
- * text such as the message "Your shopping basked is empty".
- *
- * Now if there is no replacement done in such a block the block will
- * be recognized as "empty" and by default ($removeEmptyBlocks = true) be
- * stripped off. To avoid thisyou can now call touchBlock() to avoid this.
- *
- * The array $touchedBlocks stores a list of touched block which must not
- * be removed even if they are empty.
- *
- * @var array $touchedBlocks
- * @see touchBlock(), $removeEmptyBlocks
- */
- var $touchedBlocks = array();
-
- /**
- * List of blocks which should not be shown even if not "empty"
- * @var array $_hiddenBlocks
- * @see hideBlock(), $removeEmptyBlocks
- */
- var $_hiddenBlocks = array();
-
- /**
- * Variable cache.
- *
- * Variables get cached before any replacement is done.
- * Advantage: empty blocks can be removed automatically.
- * Disadvantage: might take some more memory
- *
- * @var array
- * @see setVariable(), $clearCacheOnParse
- */
- var $variableCache = array();
-
- /**
- * Clear the variable cache on parse?
- *
- * If you're not an expert just leave the default false.
- * true reduces memory consumption somewhat if you tend to
- * add lots of values for unknown placeholder.
- *
- * @var boolean
- */
- var $clearCacheOnParse = false;
-
- /**
- * Root directory for all file operations.
- * The string gets prefixed to all filenames given.
- * @var string
- * @see HTML_Template_IT(), setRoot()
- */
- var $fileRoot = "";
-
- /**
- * Internal flag indicating that a blockname was used multiple times.
- * @var boolean
- */
- var $flagBlocktrouble = false;
-
- /**
- * Flag indicating that the global block was parsed.
- * @var boolean
- */
- var $flagGlobalParsed = false;
-
- /**
- * EXPERIMENTAL! FIXME!
- * Flag indication that a template gets cached.
- *
- * Complex templates require some times to be preparsed
- * before the replacement can take place. Often I use
- * one template file over and over again but I don't know
- * before that I will use the same template file again.
- * Now IT could notice this and skip the preparse.
- *
- * @var boolean
- */
- var $flagCacheTemplatefile = true;
-
- /**
- * EXPERIMENTAL! FIXME!
- */
- var $lastTemplatefile = "";
-
- /**
- * $_options['preserve_data'] Whether to substitute variables and remove
- * empty placeholders in data passed through setVariable
- * (see also bugs #20199, #21951).
- * $_options['use_preg'] Whether to use preg_replace instead of
- * str_replace in parse()
- * (this is a backwards compatibility feature, see also bugs #21951, #20392)
- */
- var $_options = array(
- 'preserve_data' => false,
- 'use_preg' => true
- );
-
-
- /**
- * Builds some complex regular expressions and optinally sets the
- * file root directory.
- *
- * Make sure that you call this constructor if you derive your template
- * class from this one.
- *
- * @param string File root directory, prefix for all filenames
- * given to the object.
- * @see setRoot()
- */
- function __construct($root = "", $options=null) {
- if (!is_null($options)){
- $this->setOptions($options);
- }
- $this->variablesRegExp = "@" . $this->openingDelimiter .
- "(" . $this->variablenameRegExp . ")" .
- $this->closingDelimiter . "@sm";
- $this->removeVariablesRegExp = "@" . $this->openingDelimiter .
- "\s*(" . $this->variablenameRegExp .
- ")\s*" . $this->closingDelimiter ."@sm";
-
- $this->blockRegExp = '@(.*)@sm';
-
- $this->setRoot($root);
- } // end constructor
-
-
- /**
- * Sets the option for the template class
- *
- * @access public
- * @param string option name
- * @param mixed option value
- * @return mixed IT_OK on success, error object on failure
- */
- function setOption($option, $value)
- {
- if (isset($this->_options[$option])) {
- $this->_options[$option] = $value;
- return IT_OK;
- }
- return PEAR::raiseError(
- $this->errorMessage(IT_UNKNOWN_OPTION) . ": '{$option}'",
- IT_UNKNOWN_OPTION
- );
- }
-
- /**
- * Sets the options for the template class
- *
- * @access public
- * @param string options array of options
- * default value:
- * 'preserve_data' => false,
- * 'use_preg' => true
- * @param mixed option value
- * @return mixed IT_OK on success, error object on failure
- * @see $options
- */
- function setOptions($options)
- {
- foreach($options as $option=>$value){
- if ( PEAR::isError($error=$this->setOption($option, $value)) ){
- return $error;
- }
- }
- return IT_OK;
- }
-
- /**
- * Print a certain block with all replacements done.
- * @brother get()
- */
- function show($block = "__global__") {
- print $this->get($block);
- } // end func show
-
- /**
- * Returns a block with all replacements done.
- *
- * @param string name of the block
- * @return string
- * @throws PEAR_Error
- * @access public
- * @see show()
- */
- function get($block = "__global__") {
-
- if ("__global__" == $block && !$this->flagGlobalParsed)
- $this->parse("__global__");
-
- if (!isset($this->blocklist[$block])) {
- $this->err[] = PEAR::raiseError(
- $this->errorMessage( IT_BLOCK_NOT_FOUND ) .
- '"' . $block . "'",
- IT_BLOCK_NOT_FOUND
- );
- return "";
- }
-
- if (!isset($this->blockdata[$block])) {
- return '';
-
- } else {
- $ret = $this->blockdata[$block];
- if ($this->clearCache) {
- unset($this->blockdata[$block]);
- }
- if ($this->_options['preserve_data']) {
- $ret = str_replace(
- $this->openingDelimiter .
- '%preserved%' . $this->closingDelimiter,
- $this->openingDelimiter,
- $ret
- );
- }
- return $ret;
- }
- } // end func get()
-
- /**
- * Parses the given block.
- *
- * @param string name of the block to be parsed
- * @access public
- * @see parseCurrentBlock()
- * @throws PEAR_Error
- */
- function parse($block = "__global__", $flag_recursion = false)
- {
- static $regs, $values;
-
- if (!isset($this->blocklist[$block])) {
- return PEAR::raiseError(
- $this->errorMessage( IT_BLOCK_NOT_FOUND ) . '"' . $block . "'",
- IT_BLOCK_NOT_FOUND
- );
- }
-
- if ("__global__" == $block) {
- $this->flagGlobalParsed = true;
- }
-
- if (!$flag_recursion) {
- $regs = array();
- $values = array();
- }
- $outer = $this->blocklist[$block];
- $empty = true;
-
- if ($this->clearCacheOnParse) {
-
- foreach ($this->variableCache as $name => $value) {
- $regs[] = $this->openingDelimiter .
- $name . $this->closingDelimiter;
- $values[] = $value;
- $empty = false;
- }
- $this->variableCache = array();
-
- } else {
-
- foreach ($this->blockvariables[$block] as $allowedvar => $v) {
-
- if (isset($this->variableCache[$allowedvar])) {
- $regs[] = $this->openingDelimiter .
- $allowedvar . $this->closingDelimiter;
- $values[] = $this->variableCache[$allowedvar];
- unset($this->variableCache[$allowedvar]);
- $empty = false;
- }
-
- }
-
- }
-
- if (isset($this->blockinner[$block])) {
-
- foreach ($this->blockinner[$block] as $k => $innerblock) {
-
- $this->parse($innerblock, true);
- if ("" != $this->blockdata[$innerblock]) {
- $empty = false;
- }
-
- $placeholder = $this->openingDelimiter . "__" .
- $innerblock . "__" . $this->closingDelimiter;
- $outer = str_replace(
- $placeholder,
- $this->blockdata[$innerblock], $outer
- );
- $this->blockdata[$innerblock] = "";
- }
-
- }
-
- if (!$flag_recursion && 0 != count($values)) {
- if ($this->_options['use_preg']) {
- $regs = array_map(array(
- &$this, '_addPregDelimiters'),
- $regs
- );
- $funcReplace = 'preg_replace';
- } else {
- $funcReplace = 'str_replace';
- }
- if ($this->_options['preserve_data']) {
- $values = array_map(
- array(&$this, '_preserveOpeningDelimiter'), $values
- );
- }
-
- $outer = $funcReplace($regs, $values, $outer);
-
- if ($this->removeUnknownVariables) {
- $outer = preg_replace($this->removeVariablesRegExp, "", $outer);
- }
- }
- if ($empty) {
-
- if (!$this->removeEmptyBlocks) {
-
- $this->blockdata[$block ].= $outer;
-
- } else {
-
- if (isset($this->touchedBlocks[$block])) {
- $this->blockdata[$block] .= $outer;
- unset($this->touchedBlocks[$block]);
- }
-
- }
-
- } else {
-
- $this->blockdata[$block] .= $outer;
-
- }
-
- return $empty;
- } // end func parse
-
- /**
- * Parses the current block
- * @see parse(), setCurrentBlock(), $currentBlock
- * @access public
- */
- function parseCurrentBlock() {
- return $this->parse($this->currentBlock);
- } // end func parseCurrentBlock
-
- /**
- * Sets a variable value.
- *
- * The function can be used eighter like setVariable( "varname", "value")
- * or with one array $variables["varname"] = "value"
- * given setVariable($variables) quite like phplib templates set_var().
- *
- * @param mixed string with the variable name or an array
- * %variables["varname"] = "value"
- * @param string value of the variable or empty if $variable
- * is an array.
- * @param string prefix for variable names
- * @access public
- */
- function setVariable($variable, $value = "") {
-
- if (is_array($variable)) {
-
- $this->variableCache = array_merge(
- $this->variableCache, $variable
- );
-
- } else {
-
- $this->variableCache[$variable] = $value;
-
- }
-
- } // end func setVariable
-
- /**
- * Sets the name of the current block that is the block where variables
- * are added.
- *
- * @param string name of the block
- * @return boolean false on failure, otherwise true
- * @throws PEAR_Error
- * @access public
- */
- function setCurrentBlock($block = "__global__") {
-
- if (!isset($this->blocklist[$block])) {
- return PEAR::raiseError(
- $this->errorMessage( IT_BLOCK_NOT_FOUND ) .
- '"' . $block . "'", IT_BLOCK_NOT_FOUND
- );
- }
-
- $this->currentBlock = $block;
-
- return true;
- } // end func setCurrentBlock
-
- /**
- * Preserves an empty block even if removeEmptyBlocks is true.
- *
- * @param string name of the block
- * @return boolean false on false, otherwise true
- * @throws PEAR_Error
- * @access public
- * @see $removeEmptyBlocks
- */
- function touchBlock($block) {
-
- if (!isset($this->blocklist[$block])) {
- return PEAR::raiseError(
- $this->errorMessage( IT_BLOCK_NOT_FOUND ) .
- '"' . $block . "'", IT_BLOCK_NOT_FOUND );
- }
-
- $this->touchedBlocks[$block] = true;
-
- return true;
- } // end func touchBlock
-
- /**
- * Clears all datafields of the object and rebuild the internal blocklist
- *
- * LoadTemplatefile() and setTemplate() automatically call this function
- * when a new template is given. Don't use this function
- * unless you know what you're doing.
- *
- * @access public
- * @see free()
- */
- function init() {
-
- $this->free();
- $this->findBlocks($this->template);
- // we don't need it any more
- $this->template = '';
- $this->buildBlockvariablelist();
-
- } // end func init
-
- /**
- * Clears all datafields of the object.
- *
- * Don't use this function unless you know what you're doing.
- *
- * @access public
- * @see init()
- */
- function free() {
-
- $this->err = array();
-
- $this->currentBlock = "__global__";
-
- $this->variableCache = array();
- $this->blocklookup = array();
- $this->touchedBlocks = array();
-
- $this->flagBlocktrouble = false;
- $this->flagGlobalParsed = false;
-
- } // end func free
-
- /**
- * Sets the template.
- *
- * You can eighter load a template file from disk with
- * LoadTemplatefile() or set the template manually using this function.
- *
- * @param string template content
- * @param boolean remove unknown/unused variables?
- * @param boolean remove empty blocks?
- * @see LoadTemplatefile(), $template
- * @access public
- */
- function setTemplate( $template, $removeUnknownVariables = true,
- $removeEmptyBlocks = true
- ) {
-
- $this->removeUnknownVariables = $removeUnknownVariables;
- $this->removeEmptyBlocks = $removeEmptyBlocks;
-
- if ("" == $template && $this->flagCacheTemplatefile) {
-
- $this->variableCache = array();
- $this->blockdata = array();
- $this->touchedBlocks = array();
- $this->currentBlock = "__global__";
-
- } else {
-
- $this->template = '' . $template .
- '';
- $this->init();
-
- }
-
- if ($this->flagBlocktrouble)
- return false;
-
- return true;
- } // end func setTemplate
-
- /**
- * Reads a template file from the disk.
- *
- * @param string name of the template file
- * @param bool how to handle unknown variables.
- * @param bool how to handle empty blocks.
- * @access public
- * @return boolean false on failure, otherwise true
- * @see $template, setTemplate(), $removeUnknownVariables,
- * $removeEmptyBlocks
- */
- function loadTemplatefile( $filename,
- $removeUnknownVariables = false,
- $removeEmptyBlocks = true ) {
-
- $template = "";
- if (!$this->flagCacheTemplatefile ||
- $this->lastTemplatefile != $filename
- ){
- $template = $this->getFile($filename);
- }
- $this->lastTemplatefile = $filename;
-
- return $template!=""?
- $this->setTemplate(
- $template,$removeUnknownVariables, $removeEmptyBlocks
- ):false;
- } // end func LoadTemplatefile
-
- /**
- * Sets the file root. The file root gets prefixed to all filenames passed
- * to the object.
- *
- * Make sure that you override this function when using the class
- * on windows.
- *
- * @param string
- * @see IntegratedTemplate()
- * @access public
- */
- function setRoot($root) {
-
- if ("" != $root && "/" != substr($root, -1))
- $root .= "/";
-
- $this->fileRoot = $root;
-
- } // end func setRoot
-
- /**
- * Build a list of all variables within of a block
- */
- function buildBlockvariablelist() {
-
- foreach ($this->blocklist as $name => $content) {
- preg_match_all( $this->variablesRegExp, $content, $regs );
-
- if (0 != count($regs[1])) {
-
- foreach ($regs[1] as $k => $var)
- $this->blockvariables[$name][$var] = true;
-
- } else {
-
- $this->blockvariables[$name] = array();
-
- }
-
- }
-
- } // end func buildBlockvariablelist
-
- /**
- * Returns a list of all global variables
- */
- function getGlobalvariables() {
-
- $regs = array();
- $values = array();
-
- foreach ($this->blockvariables["__global__"] as $allowedvar => $v) {
-
- if (isset($this->variableCache[$allowedvar])) {
- $regs[] = "@" . $this->openingDelimiter .
- $allowedvar . $this->closingDelimiter."@";
- $values[] = $this->variableCache[$allowedvar];
- unset($this->variableCache[$allowedvar]);
- }
-
- }
-
- return array($regs, $values);
- } // end func getGlobalvariables
-
- /**
- * Recusively builds a list of all blocks within the template.
- *
- * @param string string that gets scanned
- * @see $blocklist
- */
- function findBlocks($string) {
-
- $blocklist = array();
-
- if (
- preg_match_all($this->blockRegExp, $string, $regs, PREG_SET_ORDER)
- ) {
-
- foreach ($regs as $k => $match) {
-
- $blockname = $match[1];
- $blockcontent = $match[2];
-
- if (isset($this->blocklist[$blockname])) {
- $this->err[] = PEAR::raiseError(
- $this->errorMessage(
- IT_BLOCK_DUPLICATE ) . '"' .
- $blockname . "'",
- IT_BLOCK_DUPLICATE
- );
- $this->flagBlocktrouble = true;
- }
-
- $this->blocklist[$blockname] = $blockcontent;
- $this->blockdata[$blockname] = "";
-
- $blocklist[] = $blockname;
-
- $inner = $this->findBlocks($blockcontent);
- foreach ($inner as $k => $name) {
-
- $pattern = sprintf(
- '@(.*)@sm',
- $name,
- $name
- );
-
- $this->blocklist[$blockname] = preg_replace(
- $pattern,
- $this->openingDelimiter .
- "__" . $name . "__" .
- $this->closingDelimiter,
- $this->blocklist[$blockname]
- );
- $this->blockinner[$blockname][] = $name;
- $this->blockparents[$name] = $blockname;
-
- }
-
- }
-
- }
-
- return $blocklist;
- } // end func findBlocks
-
- /**
- * Reads a file from disk and returns its content.
- * @param string Filename
- * @return string Filecontent
- */
- function getFile($filename) {
-
- if ("/" == $filename[0] && "/" == substr($this->fileRoot, -1))
- $filename = substr($filename, 1);
-
- $filename = $this->fileRoot . $filename;
-
- if (!($fh = @fopen($filename, "r"))) {
- $this->err[] = PEAR::raiseError(
- $this->errorMessage(IT_TPL_NOT_FOUND) .
- ': "' .$filename .'"',
- IT_TPL_NOT_FOUND
- );
- return "";
- }
-
- $content = fread($fh, filesize($filename));
- fclose($fh);
-
- return preg_replace(
- "##im", "\$this->getFile('\\1')", $content
- );
- } // end func getFile
-
-
- /**
- * Adds delimiters to a string, so it can be used as a pattern
- * in preg_* functions
- *
- * @param string
- * @return string
- */
- function _addPregDelimiters($str)
- {
- return '@' . $str . '@';
- }
-
-
- /**
- * Replaces an opening delimiter by a special string
- *
- * @param string
- * @return string
- */
- function _preserveOpeningDelimiter($str)
- {
- return (false === strpos($str, $this->openingDelimiter))?
- $str:
- str_replace(
- $this->openingDelimiter,
- $this->openingDelimiter .
- '%preserved%' . $this->closingDelimiter,
- $str
- );
- }
-
- /**
- * Return a textual error message for a IT error code
- *
- * @param integer $value error code
- *
- * @return string error message, or false if the error code was
- * not recognized
- */
- function errorMessage($value)
- {
- global $blockname;
- static $errorMessages;
- if (!isset($errorMessages)) {
- $errorMessages = array(
- IT_OK => '',
- IT_ERROR => 'unknown error',
- IT_TPL_NOT_FOUND => 'Cannot read the template file',
- IT_BLOCK_NOT_FOUND => 'Cannot find this block',
- IT_BLOCK_DUPLICATE => 'The name of a block must be'.
- ' uniquewithin a template.'.
- ' Found "' . $blockname . '" twice.'.
- 'Unpredictable results '.
- 'may appear.',
- IT_UNKNOWN_OPTION => 'Unknown option'
- );
- }
-
- if (PEAR::isError($value)) {
- $value = $value->getCode();
- }
-
- return isset($errorMessages[$value]) ?
- $errorMessages[$value] : $errorMessages[IT_ERROR];
- }
-
- /**
- * Gets the Template as string
- *
- *
- *
- * @access public
- */
- function toString() {
-
- return $this->getFile($this->lastTemplatefile);
-
- } // end func setVariable
-} // end class IntegratedTemplate
-?>
diff --git a/lmo/includes/ITX.php b/lmo/includes/ITX.php
deleted file mode 100644
index 2cf16e60..00000000
--- a/lmo/includes/ITX.php
+++ /dev/null
@@ -1,825 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-//
-//
-
-//jokerlmo: Changed include path
-require_once(PATH_TO_LMO.'/includes/IT.php');
-require_once(PATH_TO_LMO.'/includes/IT_Error.php');
-
-/**
-* Integrated Template Extension - ITX
-*
-* With this class you get the full power of the phplib template class.
-* You may have one file with blocks in it but you have as well one main file
-* and multiple files one for each block. This is quite usefull when you have
-* user configurable websites. Using blocks not in the main template allows
-* you to modify some parts of your layout easily.
-*
-* Note that you can replace an existing block and add new blocks at runtime.
-* Adding new blocks means changing a variable placeholder to a block.
-*
-* @author Ulf Wendel
-* @access public
-*
-* @package IT[X]
-*/
-class HTML_Template_ITX extends HTML_Template_IT {
-
- /**
- * Array with all warnings.
- * @var array
- * @access public
- * @see $printWarning, $haltOnWarning, warning()
- */
- var $warn = array();
-
- /**
- * Print warnings?
- * @var array
- * @access public
- * @see $haltOnWarning, $warn, warning()
- */
- var $printWarning = false;
-
- /**
- * Call die() on warning?
- * @var boolean
- * @access public
- * @see $warn, $printWarning, warning()
- */
- var $haltOnWarning = false;
-
- /**
- * RegExp used to test for a valid blockname.
- * @var string
- */
- var $checkblocknameRegExp = '';
-
- /**
- * Functionnameprefix used when searching function calls in the template.
- * @var string
- */
- var $functionPrefix = 'func_';
-
- /**
- * Functionname RegExp.
- * @var string
- */
- var $functionnameRegExp = '[_a-zA-Z]+[A-Za-z_0-9]*';
-
- /**
- * RegExp used to grep function calls in the template.
- *
- * The variable gets set by the constructor.
- *
- * @var string
- * @see HTML_Template_IT()
- */
- var $functionRegExp = '';
-
- /**
- * List of functions found in the template.
- *
- * @var array
- */
- var $functions = array();
-
- /**
- * List of callback functions specified by the user.
- *
- * @var array
- */
- var $callback = array();
-
- /**
- * Builds some complex regexps and calls the constructor
- * of the parent class.
- *
- * Make sure that you call this constructor if you derive your own
- * template class from this one.
- *
- * @see HTML_Template_IT()
- */
- function HTML_Template_ITX($root = '')
- {
-
- $this->checkblocknameRegExp = '@' . $this->blocknameRegExp . '@';
- $this->functionRegExp = '@' . $this->functionPrefix . '(' .
- $this->functionnameRegExp . ')\s*\(@sm';
-
- $this->HTML_Template_IT($root);
- } // end func constructor
-
- function init()
- {
- $this->free();
- $this->buildFunctionlist();
- $this->findBlocks($this->template);
- // we don't need it any more
- $this->template = '';
- $this->buildBlockvariablelist();
-
- } // end func init
-
- /**
- * Replaces an existing block with new content.
- *
- * This function will replace a block of the template and all blocks
- * contained in the replaced block and add a new block insted, means
- * you can dynamically change your template.
- *
- * Note that changing the template structure violates one of the IT[X]
- * development goals. I've tried to write a simple to use template engine
- * supporting blocks. In contrast to other systems IT[X] analyses the way
- * you've nested blocks and knows which block belongs into another block.
- * The nesting information helps to make the API short and simple. Replacing
- * blocks does not only mean that IT[X] has to update the nesting
- * information (relatively time consumpting task) but you have to make sure
- * that you do not get confused due to the template change itself.
- *
- * @param string Blockname
- * @param string Blockcontent
- * @param boolean true if the new block inherits the content
- * of the old block
- * @return boolean
- * @throws IT_Error
- * @see replaceBlockfile(), addBlock(), addBlockfile()
- * @access public
- */
- function replaceBlock($block, $template, $keep_content = false)
- {
- if (!isset($this->blocklist[$block])) {
- return new IT_Error(
- "The block "."'$block'".
- " does not exist in the template and thus it can't be replaced.",
- __FILE__, __LINE__
- );
- }
- if ('' == $template) {
- return new IT_Error('No block content given.', __FILE__, __LINE__);
- }
- if ($keep_content) {
- $blockdata = $this->blockdata[$block];
- }
-
- // remove all kinds of links to the block / data of the block
- $this->removeBlockData($block);
-
- $template = "" . $template . "";
- $parents = $this->blockparents[$block];
- $this->findBlocks($template);
- $this->blockparents[$block] = $parents;
-
- // KLUDGE: rebuild the list for all block - could be done faster
- $this->buildBlockvariablelist();
-
- if ($keep_content) {
- $this->blockdata[$block] = $blockdata;
- }
-
- // old TODO - I'm not sure if we need this
- // update caches
-
- return true;
- } // end func replaceBlock
-
- /**
- * Replaces an existing block with new content from a file.
- *
- * @brother replaceBlock()
- * @param string Blockname
- * @param string Name of the file that contains the blockcontent
- * @param boolean true if the new block inherits the content of the old block
- */
- function replaceBlockfile($block, $filename, $keep_content = false)
- {
- return $this->replaceBlock($block, $this->getFile($filename), $keep_content);
- } // end func replaceBlockfile
-
- /**
- * Adds a block to the template changing a variable placeholder
- * to a block placeholder.
- *
- * Add means "replace a variable placeholder by a new block".
- * This is different to PHPLibs templates. The function loads a
- * block, creates a handle for it and assigns it to a certain
- * variable placeholder. To to the same with PHPLibs templates you would
- * call set_file() to create the handle and parse() to assign the
- * parsed block to a variable. By this PHPLibs templates assume
- * that you tend to assign a block to more than one one placeholder.
- * To assign a parsed block to more than only the placeholder you specify
- * in this function you have to use a combination of getBlock()
- * and setVariable().
- *
- * As no updates to cached data is necessary addBlock() and addBlockfile()
- * are rather "cheap" meaning quick operations.
- *
- * The block content must not start with
- * and end with this would cause overhead and
- * produce an error.
- *
- * @param string Name of the variable placeholder, the name must be unique
- * within the template.
- * @param string Name of the block to be added
- * @param string Content of the block
- * @return boolean
- * @throws IT_Error
- * @see addBlockfile()
- * @access public
- */
- function addBlock($placeholder, $blockname, $template)
- {
-
- // Don't trust any user even if it's a programmer or yourself...
- if ('' == $placeholder) {
-
- return new IT_Error('No variable placeholder given.',
- __FILE__, __LINE__
- );
-
- } elseif ( '' == $blockname ||
- !preg_match($this->checkblocknameRegExp, $blockname)
- ) {
-
- return new IT_Error("No or invalid blockname '$blockname' given.",
- __FILE__, __LINE__
- );
-
- } elseif ('' == $template) {
-
- return new IT_Error('No block content given.', __FILE__, __LINE__);
-
- } elseif (isset($this->blocklist[$blockname])) {
-
- return new IT_Error('The block already exists.',
- __FILE__, __LINE__
- );
-
- }
-
- // find out where to insert the new block
- $parents = $this->findPlaceholderBlocks($placeholder);
- if (0 == count($parents)) {
-
- return new IT_Error(
- "The variable placeholder".
- " '$placeholder' was not found in the template.",
- __FILE__, __LINE__
- );
-
- } elseif ( count($parents) > 1 ) {
-
- foreach ($parents as $k => $parent) {
- $msg .= "$parent, ";
- }
- $msg = substr($parent, -2);
-
- return new IT_Error("The variable placeholder "."'$placeholder'".
- " must be unique, found in multiple blocks '$msg'.",
- __FILE__, __LINE__
- );
- }
-
- $template = "" . $template . "";
- $this->findBlocks($template);
- if ($this->flagBlocktrouble) {
- return false; // findBlocks() already throws an exception
- }
- $this->blockinner[$parents[0]][] = $blockname;
- $this->blocklist[$parents[0]] = preg_replace(
- '@' . $this->openingDelimiter . $placeholder .
- $this->closingDelimiter . '@',
-
- $this->openingDelimiter . '__' . $blockname . '__' .
- $this->closingDelimiter,
-
- $this->blocklist[$parents[0]]
- );
-
- $this->deleteFromBlockvariablelist($parents[0], $placeholder);
- $this->updateBlockvariablelist($blockname);
- /*
- // check if any inner blocks were found
- if (is_array($this->blockinner[$blockname]) and count($this->blockinner[$blockname]) > 0) {
- // loop through inner blocks, registering the variable placeholders in each
- foreach($this->blockinner[$blockname] as $childBlock) {
- $this->updateBlockvariablelist($childBlock);
- }
- }
- */
- return true;
- } // end func addBlock
-
- /**
- * Adds a block taken from a file to the template changing a variable
- * placeholder to a block placeholder.
- *
- * @param string Name of the variable placeholder to be converted
- * @param string Name of the block to be added
- * @param string File that contains the block
- * @brother addBlock()
- */
- function addBlockfile($placeholder, $blockname, $filename)
- {
- return $this->addBlock($placeholder, $blockname, $this->getFile($filename));
- } // end func addBlockfile
-
- /**
- * Returns the name of the (first) block that contains
- * the specified placeholder.
- *
- * @param string Name of the placeholder you're searching
- * @param string Name of the block to scan. If left out (default)
- * all blocks are scanned.
- * @return string Name of the (first) block that contains
- * the specified placeholder.
- * If the placeholder was not found or an error occured
- * an empty string is returned.
- * @throws IT_Error
- * @access public
- */
- function placeholderExists($placeholder, $block = '')
- {
- if ('' == $placeholder) {
- new IT_Error('No placeholder name given.', __FILE__, __LINE__);
- return '';
- }
-
- if ('' != $block && !isset($this->blocklist[$block])) {
- new IT_Error("Unknown block '$block'.", __FILE__, __LINE__);
- return '';
- }
-
- // name of the block where the given placeholder was found
- $found = '';
-
- if ('' != $block) {
-
- if (is_array($variables = $this->blockvariables[$block])) {
-
- // search the value in the list of blockvariables
- foreach ($variables as $k => $variable) {
- if ($k == $placeholder) {
- $found = $block;
- break;
- }
- }
- }
-
- } else {
-
- // search all blocks and return the name of the first block that
- // contains the placeholder
- foreach ($this->blockvariables as $blockname => $variables) {
-
- if (is_array($variables) && isset($variables[$placeholder])) {
- $found = $blockname;
- break;
- }
- }
-
- }
-
- return $found;
- } // end func placeholderExists
-
- /**
- * Checks the list of function calls in the template and
- * calls their callback function.
- *
- * @access public
- */
- function performCallback()
- {
-
- foreach ($this->functions as $func_id => $function) {
-
- if (isset($this->callback[$function['name']])) {
-
- if ('' != $this->callback[$function['name']]['object']) {
- $this->variableCache['__function' . $func_id . '__'] =
- call_user_func(
- array(
- &$GLOBALS[$this->callback[$function['name']]['object']],
- $this->callback[$function['name']]['function']),
- $function['args']
- );
- } else {
- $this->variableCache['__function' . $func_id . '__'] =
- call_user_func(
- $this->callback[$function['name']]['function'],
- $function['args']
- );
- }
-
- }
-
- }
-
- } // end func performCallback
-
- /**
- * Returns a list of all function calls in the current template.
- *
- * @return array
- * @access public
- */
- function getFunctioncalls()
- {
- return $this->functions;
- } // end func getFunctioncalls
-
- /**
- * Replaces a function call with the given replacement.
- *
- * @param int Function ID
- * @param string Replacement
- * @deprec
- */
- function setFunctioncontent($functionID, $replacement)
- {
- $this->variableCache['__function' . $functionID . '__'] = $replacement;
- } // end func setFunctioncontent
-
- /**
- * Sets a callback function.
- *
- * IT[X] templates (note the X) can contain simple function calls.
- * "function call" means that the editor of the template can add
- * special placeholder to the template like 'func_h1("embedded in h1")'.
- * IT[X] will grab this function calls and allow you to define a callback
- * function for them.
- *
- * This is an absolutely evil feature. If your application makes heavy
- * use of such callbacks and you're even implementing if-then etc. on
- * the level of a template engine you're reiventing the wheel... - that's
- * actually how PHP came into life. Anyway, sometimes it's handy.
- *
- * Consider also using XML/XSLT or native PHP. And please do not push
- * IT[X] any further into this direction of adding logics to the template
- * engine.
- *
- * For those of you ready for the X in IT[X]:
- *
- * %s', $args[0]);
- * }
- *
- * ...
- * $itx = new HTML_Template_ITX( ... );
- * ...
- * $itx->setCallbackFunction('h1', 'h_one');
- * $itx->performCallback();
- * ?>
- *
- * template:
- * func_h1('H1 Headline');
- *
- * @param string Function name in the template
- * @param string Name of the callback function
- * @param string Name of the callback object
- * @return boolean false on failure.
- * @throws IT_Error
- * @access public
- */
- function
- setCallbackFunction($tplfunction, $callbackfunction, $callbackobject = '')
- {
-
- if ('' == $tplfunction || '' == $callbackfunction) {
- return new IT_Error(
- "No template function "."('$tplfunction')".
- " and/or no callback function ('$callback') given.",
- __FILE__, __LINE__
- );
- }
- $this->callback[$tplfunction] = array(
- "function" => $callbackfunction,
- "object" => $callbackobject
- );
-
- return true;
- } // end func setCallbackFunction
-
- /**
- * Sets the Callback function lookup table
- *
- * @param array function table
- * array[templatefunction] =
- * array(
- * "function" => userfunction,
- * "object" => userobject
- * )
- * @access public
- */
- function setCallbackFuntiontable($functions)
- {
- $this->callback = $functions;
- } // end func setCallbackFunctiontable
-
- /**
- * Recursively removes all data assiciated with a block, including all inner blocks
- *
- * @param string block to be removed
- */
- function removeBlockData($block)
- {
- if (isset($this->blockinner[$block])) {
- foreach ($this->blockinner[$block] as $k => $inner) {
- $this->removeBlockData($inner);
- }
-
- unset($this->blockinner[$block]);
- }
-
- unset($this->blocklist[$block]);
- unset($this->blockdata[$block]);
- unset($this->blockvariables[$block]);
- unset($this->touchedBlocks[$block]);
-
- } // end func removeBlockinner
-
- /**
- * Returns a list of blocknames in the template.
- *
- * @return array [blockname => blockname]
- * @access public
- * @see blockExists()
- */
- function getBlocklist()
- {
- $blocklist = array();
- foreach ($this->blocklist as $block => $content) {
- $blocklist[$block] = $block;
- }
-
- return $blocklist;
- } // end func getBlocklist
-
- /**
- * Checks wheter a block exists.
- *
- * @param string
- * @return boolean
- * @access public
- * @see getBlocklist()
- */
- function blockExists($blockname)
- {
- return isset($this->blocklist[$blockname]);
- } // end func blockExists
-
- /**
- * Returns a list of variables of a block.
- *
- * @param string Blockname
- * @return array [varname => varname]
- * @access public
- * @see BlockvariableExists()
- */
- function getBlockvariables($block)
- {
- if (!isset($this->blockvariables[$block])) {
- return array();
- }
-
- $variables = array();
- foreach ($this->blockvariables[$block] as $variable => $v) {
- $variables[$variable] = $variable;
- }
-
- return $variables;
- } // end func getBlockvariables
-
- /**
- * Checks wheter a block variable exists.
- *
- * @param string Blockname
- * @param string Variablename
- * @return boolean
- * @access public
- * @see getBlockvariables()
- */
- function BlockvariableExists($block, $variable)
- {
- return isset($this->blockvariables[$block][$variable]);
- } // end func BlockvariableExists
-
- /**
- * Builds a functionlist from the template.
- */
- function buildFunctionlist()
- {
- $this->functions = array();
-
- $template = $this->template;
- $num = 0;
-
- while (preg_match($this->functionRegExp, $template, $regs)) {
-
- $pos = strpos($template, $regs[0]);
- $template = substr($template, $pos + strlen($regs[0]));
-
- $head = $this->getValue($template, ')');
- $args = array();
-
- $this->template = str_replace($regs[0] . $head . ')',
- '{__function' . $num . '__}', $this->template
- );
- $template = str_replace($regs[0] . $head . ')',
- '{__function' . $num . '__}', $template
- );
-
- while ('' != $head && $args2 = $this->getValue($head, ',')) {
- $arg2 = trim($args2);
- $args[] = ('"' == $arg2[0] || "'" == $arg2[0]) ?
- substr($arg2, 1, -1) : $arg2;
- if ($arg2 == $head) {
- break;
- }
- $head = substr($head, strlen($arg2) + 1);
- }
-
- $this->functions[$num++] = array(
- 'name' => $regs[1],
- 'args' => $args
- );
- }
-
- } // end func buildFunctionlist
-
-
- function getValue($code, $delimiter) {
- if ('' == $code) {
- return '';
- }
-
- if (!is_array($delimiter)) {
- $delimiter = array( $delimiter => true );
- }
-
- $len = strlen($code);
- $enclosed = false;
- $enclosed_by = '';
-
- if (isset($delimiter[$code[0]])) {
-
- $i = 1;
-
- } else {
-
- for ($i = 0; $i < $len; ++$i) {
-
- $char = $code[$i];
-
- if (
- ('"' == $char || "'" == $char) &&
- ($char == $enclosed_by || '' == $enclosed_by) &&
- (0 == $i || ($i > 0 && '\\' != $code[$i - 1]))
- ){
-
- if (!$enclosed) {
- $enclosed_by = $char;
- } else {
- $enclosed_by = "";
- }
- $enclosed = !$enclosed;
-
- }
- if (!$enclosed && isset($delimiter[$char])) {
- break;
- }
- }
-
- }
-
- return substr($code, 0, $i);
- } // end func getValue
-
-
- /**
- * Deletes one or many variables from the block variable list.
- *
- * @param string Blockname
- * @param mixed Name of one variable or array of variables
- * ( array ( name => true ) ) to be stripped.
- */
- function deleteFromBlockvariablelist($block, $variables)
- {
- if (!is_array($variables)) {
- $variables = array($variables => true);
- }
-
- foreach ($this->blockvariables[$block] as $varname => $val) {
- if (isset($variables[$varname])) {
- unset($this->blockvariables[$block][$varname]);
- }
- }
- } // end deleteFromBlockvariablelist
-
- /**
- * Updates the variable list of a block.
- *
- * @param string Blockname
- */
- function updateBlockvariablelist($block)
- {
- preg_match_all( $this->variablesRegExp,
- $this->blocklist[$block], $regs
- );
-
- if (0 != count($regs[1])) {
- foreach ($regs[1] as $k => $var) {
- $this->blockvariables[$block][$var] = true;
- }
- } else {
- $this->blockvariables[$block] = array();
- }
-
- // check if any inner blocks were found
- if (isset($this->blockinner[$block]) &&
- is_array($this->blockinner[$block]) &&
- count($this->blockinner[$block]) > 0
- ) {
- /*
- * loop through inner blocks, registering the variable
- * placeholders in each
- */
- foreach($this->blockinner[$block] as $childBlock) {
- $this->updateBlockvariablelist($childBlock);
- }
- }
-
- } // end func updateBlockvariablelist
-
- /**
- * Returns an array of blocknames where the given variable
- * placeholder is used.
- *
- * @param string Variable placeholder
- * @return array $parents parents[0..n] = blockname
- */
- function findPlaceholderBlocks($variable)
- {
- $parents = array();
- foreach ($this->blocklist as $blockname => $content) {
- foreach ($this->blockvariables[$blockname] as $varname => $val) {
- if ($variable == $varname) {
- $parents[] = $blockname;
- }
- }
- }
-
- return $parents;
- } // end func findPlaceholderBlocks
-
- /**
- * Handles warnings, saves them to $warn and prints them or
- * calls die() depending on the flags
- *
- * @param string Warning
- * @param string File where the warning occured
- * @param int Linenumber where the warning occured
- * @see $warn, $printWarning, $haltOnWarning
- */
- function warning($message, $file = '', $line = 0)
- {
- $message = sprintf(
- 'HTML_Template_ITX Warning: %s [File: %s, Line: %d]',
- $message,
- $file,
- $line
- );
-
- $this->warn[] = $message;
-
- if ($this->printWarning) {
- print $message;
- }
-
- if ($this->haltOnWarning) {
- die($message);
- }
- } // end func warning
-
-} // end class HTML_Template_ITX
-?>
diff --git a/lmo/includes/IT_Error.php b/lmo/includes/IT_Error.php
deleted file mode 100644
index c19eaeab..00000000
--- a/lmo/includes/IT_Error.php
+++ /dev/null
@@ -1,53 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-//
-
-//jokerlmo: Changed include path
-require_once(PATH_TO_LMO.'/includes/PEAR.php');
-
-
-/**
-* IT[X] Error class
-*
-* @package IT[X]
-*/
-class IT_Error extends PEAR_Error {
-
-
- /**
- * Prefix of all error messages.
- *
- * @var string
- */
- var $error_message_prefix = "IntegratedTemplate Error: ";
-
- /**
- * Creates an cache error object.
- *
- * @param string error message
- * @param string file where the error occured
- * @param string linenumber where the error occured
- */
- function IT_Error($msg, $file = __FILE__, $line = __LINE__) {
-
- $this->PEAR_Error(sprintf("%s [%s on line %d].", $msg, $file, $line));
-
- } // end func IT_Error
-
-} // end class IT_Error
-?>
diff --git a/lmo/includes/Lite.php b/lmo/includes/Lite.php
deleted file mode 100644
index 6031a719..00000000
--- a/lmo/includes/Lite.php
+++ /dev/null
@@ -1,733 +0,0 @@
-
-*
-* @package Cache_Lite
-* @category Caching
-*
-* @author Fabien MARTY
-*/
-
-define('CACHE_LITE_ERROR_RETURN', 1);
-define('CACHE_LITE_ERROR_DIE', 8);
-
-class Cache_Lite
-{
-
- // --- Private properties ---
-
- /**
- * Directory where to put the cache files
- * (make sure to add a trailing slash)
- *
- * @var string $_cacheDir
- */
- var $_cacheDir = '/tmp/';
-
- /**
- * Enable / disable caching
- *
- * (can be very usefull for the debug of cached scripts)
- *
- * @var boolean $_caching
- */
- var $_caching = true;
-
- /**
- * Cache lifetime (in seconds)
- *
- * @var int $_lifeTime
- */
- var $_lifeTime = 3600;
-
- /**
- * Enable / disable fileLocking
- *
- * (can avoid cache corruption under bad circumstances)
- *
- * @var boolean $_fileLocking
- */
- var $_fileLocking = true;
-
- /**
- * Timestamp of the last valid cache
- *
- * @var int $_refreshTime
- */
- var $_refreshTime;
-
- /**
- * File name (with path)
- *
- * @var string $_file
- */
- var $_file;
-
- /**
- * File name (without path)
- *
- * @var string $_fileName
- */
- var $_fileName;
-
- /**
- * Enable / disable write control (the cache is read just after writing to detect corrupt entries)
- *
- * Enable write control will lightly slow the cache writing but not the cache reading
- * Write control can detect some corrupt cache files but maybe it's not a perfect control
- *
- * @var boolean $_writeControl
- */
- var $_writeControl = true;
-
- /**
- * Enable / disable read control
- *
- * If enabled, a control key is embeded in cache file and this key is compared with the one
- * calculated after the reading.
- *
- * @var boolean $_writeControl
- */
- var $_readControl = true;
-
- /**
- * Type of read control (only if read control is enabled)
- *
- * Available values are :
- * 'md5' for a md5 hash control (best but slowest)
- * 'crc32' for a crc32 hash control (lightly less safe but faster, better choice)
- * 'strlen' for a length only test (fastest)
- *
- * @var boolean $_readControlType
- */
- var $_readControlType = 'crc32';
-
- /**
- * Pear error mode (when raiseError is called)
- *
- * (see PEAR doc)
- *
- * @see setToDebug()
- * @var int $_pearErrorMode
- */
- var $_pearErrorMode = CACHE_LITE_ERROR_RETURN;
-
- /**
- * Current cache id
- *
- * @var string $_id
- */
- var $_id;
-
- /**
- * Current cache group
- *
- * @var string $_group
- */
- var $_group;
-
- /**
- * Enable / Disable "Memory Caching"
- *
- * NB : There is no lifetime for memory caching !
- *
- * @var boolean $_memoryCaching
- */
- var $_memoryCaching = false;
-
- /**
- * Enable / Disable "Only Memory Caching"
- * (be carefull, memory caching is "beta quality")
- *
- * @var boolean $_onlyMemoryCaching
- */
- var $_onlyMemoryCaching = false;
-
- /**
- * Memory caching array
- *
- * @var array $_memoryCachingArray
- */
- var $_memoryCachingArray = array();
-
- /**
- * Memory caching counter
- *
- * @var int $memoryCachingCounter
- */
- var $_memoryCachingCounter = 0;
-
- /**
- * Memory caching limit
- *
- * @var int $memoryCachingLimit
- */
- var $_memoryCachingLimit = 1000;
-
- /**
- * File Name protection
- *
- * if set to true, you can use any cache id or group name
- * if set to false, it can be faster but cache ids and group names
- * will be used directly in cache file names so be carefull with
- * special characters...
- *
- * @var boolean $fileNameProtection
- */
- var $_fileNameProtection = true;
-
- /**
- * Enable / disable automatic serialization
- *
- * it can be used to save directly datas which aren't strings
- * (but it's slower)
- *
- * @var boolean $_serialize
- */
- var $_automaticSerialization = false;
-
- /**
- * Disable / Tune the automatic cleaning process
- *
- * The automatic cleaning process destroy too old (for the given life time)
- * cache files when a new cache file is written.
- * 0 => no automatic cache cleaning
- * 1 => systematic cache cleaning
- * x (integer) > 1 => automatic cleaning randomly 1 times on x cache write
- *
- * @var int $_automaticCleaning
- */
- var $_automaticCleaningFactor = 0;
-
- /**
- * Nested directory level
- *
- *
- * @var int $_hashedDirectoryLevel
- */
- var $_hashedDirectoryLevel = 0;
-
- // --- Public methods ---
-
- /**
- * Constructor
- *
- * $options is an assoc. Available options are :
- * $options = array(
- * 'cacheDir' => directory where to put the cache files (string),
- * 'caching' => enable / disable caching (boolean),
- * 'lifeTime' => cache lifetime in seconds (int),
- * 'fileLocking' => enable / disable fileLocking (boolean),
- * 'writeControl' => enable / disable write control (boolean),
- * 'readControl' => enable / disable read control (boolean),
- * 'readControlType' => type of read control 'crc32', 'md5', 'strlen' (string),
- * 'pearErrorMode' => pear error mode (when raiseError is called) (cf PEAR doc) (int),
- * 'memoryCaching' => enable / disable memory caching (boolean),
- * 'onlyMemoryCaching' => enable / disable only memory caching (boolean),
- * 'memoryCachingLimit' => max nbr of records to store into memory caching (int),
- * 'fileNameProtection' => enable / disable automatic file name protection (boolean),
- * 'automaticSerialization' => enable / disable automatic serialization (boolean)
- * 'automaticCleaningFactor' => distable / tune automatic cleaning process (int)
- * 'hashedDirectoryLevel' => level of the hashed directory system (int)
- * );
- *
- * @param array $options options
- * @access public
- */
- function Cache_Lite($options = array(NULL))
- {
- $availableOptions = array('hashedDirectoryLevel', 'automaticCleaningFactor', 'automaticSerialization', 'fileNameProtection', 'memoryCaching', 'onlyMemoryCaching', 'memoryCachingLimit', 'cacheDir', 'caching', 'lifeTime', 'fileLocking', 'writeControl', 'readControl', 'readControlType', 'pearErrorMode');
- foreach($options as $key => $value) {
- if (in_array($key, $availableOptions)) {
- $property = '_'.$key;
- $this->$property = $value;
- }
- }
- $this->_refreshTime = time() - $this->_lifeTime;
- }
-
- /**
- * Test if a cache is available and (if yes) return it
- *
- * @param string $id cache id
- * @param string $group name of the cache group
- * @param boolean $doNotTestCacheValidity if set to true, the cache validity won't be tested
- * @return string data of the cache (or false if no cache available)
- * @access public
- */
- function get($id, $group = 'default', $doNotTestCacheValidity = false)
- {
- $this->_id = $id;
- $this->_group = $group;
- $data = false;
- if ($this->_caching) {
- $this->_setFileName($id, $group);
- if ($this->_memoryCaching) {
- if (isset($this->_memoryCachingArray[$this->_file])) {
- if ($this->_automaticSerialization) {
- return unserialize($this->_memoryCachingArray[$this->_file]);
- } else {
- return $this->_memoryCachingArray[$this->_file];
- }
- } else {
- if ($this->_onlyMemoryCaching) {
- return false;
- }
- }
- }
- if ($doNotTestCacheValidity) {
- if (file_exists($this->_file)) {
- $data = $this->_read();
- }
- } else {
- if ((file_exists($this->_file)) && (@filemtime($this->_file) > $this->_refreshTime)) {
- $data = $this->_read();
- }
- }
- if (($data) and ($this->_memoryCaching)) {
- $this->_memoryCacheAdd($this->_file, $data);
- }
- if (($this->_automaticSerialization) and (is_string($data))) {
- $data = unserialize($data);
- }
- return $data;
- }
- return false;
- }
-
- /**
- * Save some data in a cache file
- *
- * @param string $data data to put in cache (can be another type than strings if automaticSerialization is on)
- * @param string $id cache id
- * @param string $group name of the cache group
- * @return boolean true if no problem
- * @access public
- */
- function save($data, $id = NULL, $group = 'default')
- {
- if ($this->_caching) {
- if ($this->_automaticSerialization) {
- $data = serialize($data);
- }
- if (isset($id)) {
- $this->_setFileName($id, $group);
- }
- if ($this->_memoryCaching) {
- $this->_memoryCacheAdd($this->_file, $data);
- if ($this->_onlyMemoryCaching) {
- return true;
- }
- }
- if ($this->_automaticCleaningFactor>0) {
- $rand = rand(1, $this->_automaticCleaningFactor);
- if ($rand==1) {
- $this->clean(false, 'old');
- }
- }
- if ($this->_writeControl) {
- if (!$this->_writeAndControl($data)) {
- @touch($this->_file, time() - 2*abs($this->_lifeTime));
- return false;
- } else {
- return true;
- }
- } else {
- return $this->_write($data);
- }
- }
- return false;
- }
-
- /**
- * Remove a cache file
- *
- * @param string $id cache id
- * @param string $group name of the cache group
- * @return boolean true if no problem
- * @access public
- */
- function remove($id, $group = 'default')
- {
- $this->_setFileName($id, $group);
- if ($this->_memoryCaching) {
- if (isset($this->_memoryCachingArray[$this->_file])) {
- unset($this->_memoryCachingArray[$this->_file]);
- $this->_memoryCachingCounter = $this->_memoryCachingCounter - 1;
- }
- if ($this->_onlyMemoryCaching) {
- return true;
- }
- }
- return $this->_unlink($this->_file);
- }
-
- /**
- * Clean the cache
- *
- * if no group is specified all cache files will be destroyed
- * else only cache files of the specified group will be destroyed
- *
- * @param string $group name of the cache group
- * @param string $mode flush cache mode : 'old', 'ingroup', 'notingroup'
- * @return boolean true if no problem
- * @access public
- */
- function clean($group = false, $mode = 'ingroup')
- {
- return $this->_cleanDir($this->_cacheDir, $group, $mode);
- }
-
- /**
- * Set to debug mode
- *
- * When an error is found, the script will stop and the message will be displayed
- * (in debug mode only).
- *
- * @access public
- */
- function setToDebug()
- {
- $this->_pearErrorMode = CACHE_LITE_ERROR_DIE;
- }
-
- /**
- * Set a new life time
- *
- * @param int $newLifeTime new life time (in seconds)
- * @access public
- */
- function setLifeTime($newLifeTime)
- {
- $this->_lifeTime = $newLifeTime;
- $this->_refreshTime = time() - $newLifeTime;
- }
-
- /**
- * Save the state of the caching memory array into a cache file cache
- *
- * @param string $id cache id
- * @param string $group name of the cache group
- * @access public
- */
- function saveMemoryCachingState($id, $group = 'default')
- {
- if ($this->_caching) {
- $array = array(
- 'counter' => $this->_memoryCachingCounter,
- 'array' => $this->_memoryCachingState
- );
- $data = serialize($array);
- $this->save($data, $id, $group);
- }
- }
-
- /**
- * Load the state of the caching memory array from a given cache file cache
- *
- * @param string $id cache id
- * @param string $group name of the cache group
- * @param boolean $doNotTestCacheValidity if set to true, the cache validity won't be tested
- * @access public
- */
- function getMemoryCachingState($id, $group = 'default', $doNotTestCacheValidity = false)
- {
- if ($this->_caching) {
- if ($data = $this->get($id, $group, $doNotTestCacheValidity)) {
- $array = unserialize($data);
- $this->_memoryCachingCounter = $array['counter'];
- $this->_memoryCachingArray = $array['array'];
- }
- }
- }
-
- /**
- * Return the cache last modification time
- *
- * BE CAREFUL : THIS METHOD IS FOR HACKING ONLY !
- *
- * @return int last modification time
- */
- function lastModified() {
- return filemtime($this->_file);
- }
-
- /**
- * Trigger a PEAR error
- *
- * To improve performances, the PEAR.php file is included dynamically.
- * The file is so included only when an error is triggered. So, in most
- * cases, the file isn't included and perfs are much better.
- *
- * @param string $msg error message
- * @param int $code error code
- * @access public
- */
- function raiseError($msg, $code)
- {
- require_once(PATH_TO_LMO.'/includes/PEAR.php');
- PEAR::raiseError($msg, $code, $this->_pearErrorMode);
- }
-
- // --- Private methods ---
-
- /**
- * Remove a file
- *
- * @param string $file complete file path and name
- * @return boolean true if no problem
- * @access private
- */
- function _unlink($file)
- {
- if (!@unlink($file)) {
- $this->raiseError('Cache_Lite : Unable to remove cache !', -3);
- return false;
- } else {
- return true;
- }
- }
-
- /**
- * Recursive function for cleaning cache file in the given directory
- *
- * @param string $dir directory complete path (with a trailing slash)
- * @param string $group name of the cache group
- * @param string $mode flush cache mode : 'old', 'ingroup', 'notingroup'
- * @return boolean true if no problem
- * @access private
- */
- function _cleanDir($dir, $group = false, $mode = 'ingroup')
- {
- if ($this->_fileNameProtection) {
- $motif = ($group) ? 'cache_'.md5($group).'_' : 'cache_';
- } else {
- $motif = ($group) ? 'cache_'.$group.'_' : 'cache_';
- }
- if ($this->_memoryCaching) {
- foreach ($this->_memoryCachingArray as $key => $value) {
- if (strpos($key, $motif, 0)) {
- unset($this->_memoryCachingArray[$key]);
- $this->_memoryCachingCounter = $this->_memoryCachingCounter - 1;
- }
- }
- if ($this->_onlyMemoryCaching) {
- return true;
- }
- }
- if (!($dh = opendir($dir))) {
- $this->raiseError('Cache_Lite : Unable to open cache directory !', -4);
- return false;
- }
- $result = true;
- while ($file = readdir($dh)) {
- if (($file != '.') && ($file != '..')) {
- if (substr($file, 0, 6)=='cache_') {
- $file2 = $dir . $file;
- if (is_file($file2)) {
- switch ($mode) {
- case 'old':
- // files older than lifeTime get deleted from cache
- if ((mktime() - filemtime($file2)) > $this->_lifeTime) {
- $result = ($result and ($this->_unlink($file2)));
- }
- break;
- case 'notingroup':
- if (!strpos($file2, $motif, 0)) {
- $result = ($result and ($this->_unlink($file2)));
- }
- break;
- case 'ingroup':
- default:
- if (strpos($file2, $motif, 0)) {
- $result = ($result and ($this->_unlink($file2)));
- }
- break;
- }
- }
- if ((is_dir($file2)) and ($this->_hashedDirectoryLevel>0)) {
- $result = ($result and ($this->_cleanDir($file2 . '/', $group, $mode)));
- }
- }
- }
- }
- return $result;
- }
-
- /**
- * Add some date in the memory caching array
- *
- * @param string $id cache id
- * @param string $data data to cache
- * @access private
- */
- function _memoryCacheAdd($id, $data)
- {
- $this->_memoryCachingArray[$this->_file] = $data;
- if ($this->_memoryCachingCounter >= $this->_memoryCachingLimit) {
- $key = array_key_first($this->_memoryCachingArray);
- unset($this->_memoryCachingArray[$key]);
- } else {
- $this->_memoryCachingCounter = $this->_memoryCachingCounter + 1;
- }
- }
-
- /**
- * Make a file name (with path)
- *
- * @param string $id cache id
- * @param string $group name of the group
- * @access private
- */
- function _setFileName($id, $group)
- {
-
- if ($this->_fileNameProtection) {
- $suffix = 'cache_'.md5($group).'_'.md5($id);
- } else {
- $suffix = 'cache_'.$group.'_'.$id;
- }
- $root = $this->_cacheDir;
- if ($this->_hashedDirectoryLevel>0) {
- $hash = md5($suffix);
- for ($i=0 ; $i<$this->_hashedDirectoryLevel ; $i++) {
- $root = $root . 'cache_' . substr($hash, 0, $i + 1) . '/';
- }
- }
- $this->_fileName = $suffix;
- $this->_file = $root.$suffix;
- }
-
- /**
- * Read the cache file and return the content
- *
- * @return string content of the cache file
- * @access private
- */
- function _read()
- {
- $fp = @fopen($this->_file, "rb");
- if ($this->_fileLocking) @flock($fp, LOCK_SH);
- if ($fp) {
- clearstatcache(); // because the filesize can be cached by PHP itself...
- $length = @filesize($this->_file);
- $mqr = get_magic_quotes_runtime();
- set_magic_quotes_runtime(0);
- if ($this->_readControl) {
- $hashControl = @fread($fp, 32);
- $length = $length - 32;
- }
- $data = @fread($fp, $length);
- set_magic_quotes_runtime($mqr);
- if ($this->_fileLocking) @flock($fp, LOCK_UN);
- @fclose($fp);
- if ($this->_readControl) {
- $hashData = $this->_hash($data, $this->_readControlType);
- if ($hashData != $hashControl) {
- @touch($this->_file, time() - 2*abs($this->_lifeTime));
- return false;
- }
- }
- return $data;
- }
- $this->raiseError('Cache_Lite : Unable to read cache !', -2);
- return false;
- }
-
- /**
- * Write the given data in the cache file
- *
- * @param string $data data to put in cache
- * @return boolean true if ok
- * @access private
- */
- function _write($data)
- {
- $try = 1;
- while ($try<=2) {
- $fp = @fopen($this->_file, "wb");
- if ($fp) {
- if ($this->_fileLocking) @flock($fp, LOCK_EX);
- if ($this->_readControl) {
- @fwrite($fp, $this->_hash($data, $this->_readControlType), 32);
- }
- $len = strlen($data);
- @fwrite($fp, $data, $len);
- if ($this->_fileLocking) @flock($fp, LOCK_UN);
- @fclose($fp);
- return true;
- } else {
- if (($try==1) and ($this->_hashedDirectoryLevel>0)) {
- $hash = md5($this->_fileName);
- $root = $this->_cacheDir;
- for ($i=0 ; $i<$this->_hashedDirectoryLevel ; $i++) {
- $root = $root . 'cache_' . substr($hash, 0, $i + 1) . '/';
- @mkdir($root, 0700);
- }
- $try = 2;
- } else {
- $try = 999;
- }
- }
- }
- $this->raiseError('Cache_Lite : Unable to write cache file : '.$this->_file, -1);
- return false;
- }
-
- /**
- * Write the given data in the cache file and control it just after to avoir corrupted cache entries
- *
- * @param string $data data to put in cache
- * @return boolean true if the test is ok
- * @access private
- */
- function _writeAndControl($data)
- {
- $this->_write($data);
- $dataRead = $this->_read($data);
- return ($dataRead==$data);
- }
-
- /**
- * Make a control key with the string containing datas
- *
- * @param string $data data
- * @param string $controlType type of control 'md5', 'crc32' or 'strlen'
- * @return string control key
- * @access private
- */
- function _hash($data, $controlType)
- {
- switch ($controlType) {
- case 'md5':
- return md5($data);
- case 'crc32':
- return sprintf('% 32d', crc32($data));
- case 'strlen':
- return sprintf('% 32d', strlen($data));
- default:
- $this->raiseError('Unknown controlType ! (available values are only \'md5\', \'crc32\', \'strlen\')', -5);
- }
- }
-
-}
-
-?>
diff --git a/lmo/includes/LiteOutput.php b/lmo/includes/LiteOutput.php
deleted file mode 100644
index 24100105..00000000
--- a/lmo/includes/LiteOutput.php
+++ /dev/null
@@ -1,72 +0,0 @@
-
-*/
-
-require_once(PATH_TO_LMO.'/includes/Lite.php');
-
-class Cache_Lite_Output extends Cache_Lite
-{
-
- // --- Public methods ---
-
- /**
- * Constructor
- *
- * $options is an assoc. To have a look at availables options,
- * see the constructor of the Cache_Lite class in 'Cache_Lite.php'
- *
- * @param array $options options
- * @access public
- */
- function Cache_Lite_Output($options)
- {
- $this->Cache_Lite($options);
- }
-
- /**
- * Start the cache
- *
- * @param string $id cache id
- * @param string $group name of the cache group
- * @return boolean true if the cache is hit (false else)
- * @access public
- */
- function start($id, $group = 'default')
- {
- $data = $this->get($id, $group);
- if ($data !== false) {
- echo($data);
- return true;
- } else {
- ob_start();
- ob_implicit_flush(false);
- return false;
- }
- }
-
- /**
- * Stop the cache
- *
- * @access public
- */
- function end()
- {
- $data = ob_get_contents();
- ob_end_clean();
- $this->save($data, $this->_id, $this->_group);
- echo($data);
- }
-
-}
-
-
-?>
diff --git a/lmo/includes/LmoTemplate.php b/lmo/includes/LmoTemplate.php
new file mode 100644
index 00000000..17f51c88
--- /dev/null
+++ b/lmo/includes/LmoTemplate.php
@@ -0,0 +1,36 @@
+ statt {Name}
+ * - unbekannte Platzhalter bleiben stehen (sonst verschwinden auch normale HTML-Kommentare)
+ * - Variablen werden auch ohne passenden Platzhalter angenommen
+ * - toString() liefert die geladene Templatedatei unveraendert
+ */
+class LMO_Template extends HTML_Template_IT
+{
+ var $openingDelimiter = '';
+ var $blocknameRegExp = '[0-9A-Za-z_-]+';
+ var $variablenameRegExp = '[0-9A-Za-z_-]+';
+ var $removeUnknownVariables = false;
+
+ function __construct($root = '', $options = null)
+ {
+ $this->_options['preserve_input'] = false;
+ $this->_options['check_placeholder_exists'] = false;
+ parent::__construct($root, $options);
+ }
+
+ function loadTemplatefile($filename, $removeUnknownVariables = false, $removeEmptyBlocks = true)
+ {
+ return parent::loadTemplatefile($filename, $removeUnknownVariables, $removeEmptyBlocks);
+ }
+
+ function toString()
+ {
+ return $this->getFile($this->lastTemplatefile);
+ }
+}
diff --git a/lmo/includes/PEAR.php b/lmo/includes/PEAR.php
deleted file mode 100644
index 3ad97c0b..00000000
--- a/lmo/includes/PEAR.php
+++ /dev/null
@@ -1,1114 +0,0 @@
-
- * @author Stig Bakken
- * @author Tomas V.V.Cox
- * @author Greg Beaver
- * @copyright 1997-2010 The Authors
- * @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @link http://pear.php.net/package/PEAR
- * @since File available since Release 0.1
- */
-
-/**#@+
- * ERROR constants
- */
-define('PEAR_ERROR_RETURN', 1);
-define('PEAR_ERROR_PRINT', 2);
-define('PEAR_ERROR_TRIGGER', 4);
-define('PEAR_ERROR_DIE', 8);
-define('PEAR_ERROR_CALLBACK', 16);
-/**
- * WARNING: obsolete
- * @deprecated
- */
-define('PEAR_ERROR_EXCEPTION', 32);
-/**#@-*/
-
-if (substr(PHP_OS, 0, 3) == 'WIN') {
- define('OS_WINDOWS', true);
- define('OS_UNIX', false);
- define('PEAR_OS', 'Windows');
-} else {
- define('OS_WINDOWS', false);
- define('OS_UNIX', true);
- define('PEAR_OS', 'Unix'); // blatant assumption
-}
-
-$GLOBALS['_PEAR_default_error_mode'] = PEAR_ERROR_RETURN;
-$GLOBALS['_PEAR_default_error_options'] = E_USER_NOTICE;
-$GLOBALS['_PEAR_destructor_object_list'] = array();
-$GLOBALS['_PEAR_shutdown_funcs'] = array();
-$GLOBALS['_PEAR_error_handler_stack'] = array();
-
-@ini_set('track_errors', true);
-
-/**
- * Base class for other PEAR classes. Provides rudimentary
- * emulation of destructors.
- *
- * If you want a destructor in your class, inherit PEAR and make a
- * destructor method called _yourclassname (same name as the
- * constructor, but with a "_" prefix). Also, in your constructor you
- * have to call the PEAR constructor: $this->PEAR();.
- * The destructor method will be called without parameters. Note that
- * at in some SAPI implementations (such as Apache), any output during
- * the request shutdown (in which destructors are called) seems to be
- * discarded. If you need to get any debug information from your
- * destructor, use error_log(), syslog() or something similar.
- *
- * IMPORTANT! To use the emulated destructors you need to create the
- * objects by reference: $obj =& new PEAR_child;
- *
- * @category pear
- * @package PEAR
- * @author Stig Bakken
- * @author Tomas V.V. Cox
- * @author Greg Beaver
- * @copyright 1997-2006 The PHP Group
- * @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: @package_version@
- * @link http://pear.php.net/package/PEAR
- * @see PEAR_Error
- * @since Class available since PHP 4.0.2
- * @link http://pear.php.net/manual/en/core.pear.php#core.pear.pear
- */
-class PEAR
-{
- /**
- * Whether to enable internal debug messages.
- *
- * @var bool
- * @access private
- */
- var $_debug = false;
-
- /**
- * Default error mode for this object.
- *
- * @var int
- * @access private
- */
- var $_default_error_mode = null;
-
- /**
- * Default error options used for this object when error mode
- * is PEAR_ERROR_TRIGGER.
- *
- * @var int
- * @access private
- */
- var $_default_error_options = null;
-
- /**
- * Default error handler (callback) for this object, if error mode is
- * PEAR_ERROR_CALLBACK.
- *
- * @var string
- * @access private
- */
- var $_default_error_handler = '';
-
- /**
- * Which class to use for error objects.
- *
- * @var string
- * @access private
- */
- var $_error_class = 'PEAR_Error';
-
- /**
- * An array of expected errors.
- *
- * @var array
- * @access private
- */
- var $_expected_errors = array();
-
- /**
- * List of methods that can be called both statically and non-statically.
- * @var array
- */
- protected static $bivalentMethods = array(
- 'setErrorHandling' => true,
- 'raiseError' => true,
- 'throwError' => true,
- 'pushErrorHandling' => true,
- 'popErrorHandling' => true,
- );
-
- /**
- * Constructor. Registers this object in
- * $_PEAR_destructor_object_list for destructor emulation if a
- * destructor object exists.
- *
- * @param string $error_class (optional) which class to use for
- * error objects, defaults to PEAR_Error.
- * @access public
- * @return void
- */
- function __construct($error_class = null)
- {
- $classname = strtolower(get_class($this));
- if ($this->_debug) {
- print "PEAR constructor called, class=$classname\n";
- }
-
- if ($error_class !== null) {
- $this->_error_class = $error_class;
- }
-
- while ($classname && strcasecmp($classname, "pear")) {
- $destructor = "_$classname";
- if (method_exists($this, $destructor)) {
- global $_PEAR_destructor_object_list;
- $_PEAR_destructor_object_list[] = $this;
- if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) {
- register_shutdown_function("_PEAR_call_destructors");
- $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true;
- }
- break;
- } else {
- $classname = get_parent_class($classname);
- }
- }
- }
-
- /**
- * Only here for backwards compatibility.
- * E.g. Archive_Tar calls $this->PEAR() in its constructor.
- *
- * @param string $error_class Which class to use for error objects,
- * defaults to PEAR_Error.
- */
- public function PEAR($error_class = null)
- {
- self::__construct($error_class);
- }
-
- /**
- * Destructor (the emulated type of...). Does nothing right now,
- * but is included for forward compatibility, so subclass
- * destructors should always call it.
- *
- * See the note in the class desciption about output from
- * destructors.
- *
- * @access public
- * @return void
- */
- function _PEAR() {
- if ($this->_debug) {
- printf("PEAR destructor called, class=%s\n", strtolower(get_class($this)));
- }
- }
-
- public function __call($method, $arguments)
- {
- if (!isset(self::$bivalentMethods[$method])) {
- trigger_error(
- 'Call to undefined method PEAR::' . $method . '()', E_USER_ERROR
- );
- }
- return call_user_func_array(
- array(get_class(), '_' . $method),
- array_merge(array($this), $arguments)
- );
- }
-
- public static function __callStatic($method, $arguments)
- {
- if (!isset(self::$bivalentMethods[$method])) {
- trigger_error(
- 'Call to undefined method PEAR::' . $method . '()', E_USER_ERROR
- );
- }
- return call_user_func_array(
- array(get_class(), '_' . $method),
- array_merge(array(null), $arguments)
- );
- }
-
- /**
- * If you have a class that's mostly/entirely static, and you need static
- * properties, you can use this method to simulate them. Eg. in your method(s)
- * do this: $myVar = &PEAR::getStaticProperty('myclass', 'myVar');
- * You MUST use a reference, or they will not persist!
- *
- * @param string $class The calling classname, to prevent clashes
- * @param string $var The variable to retrieve.
- * @return mixed A reference to the variable. If not set it will be
- * auto initialised to NULL.
- */
- public static function &getStaticProperty($class, $var)
- {
- static $properties;
- if (!isset($properties[$class])) {
- $properties[$class] = array();
- }
-
- if (!array_key_exists($var, $properties[$class])) {
- $properties[$class][$var] = null;
- }
-
- return $properties[$class][$var];
- }
-
- /**
- * Use this function to register a shutdown method for static
- * classes.
- *
- * @param mixed $func The function name (or array of class/method) to call
- * @param mixed $args The arguments to pass to the function
- *
- * @return void
- */
- public static function registerShutdownFunc($func, $args = array())
- {
- // if we are called statically, there is a potential
- // that no shutdown func is registered. Bug #6445
- if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) {
- register_shutdown_function("_PEAR_call_destructors");
- $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true;
- }
- $GLOBALS['_PEAR_shutdown_funcs'][] = array($func, $args);
- }
-
- /**
- * Tell whether a value is a PEAR error.
- *
- * @param mixed $data the value to test
- * @param int $code if $data is an error object, return true
- * only if $code is a string and
- * $obj->getMessage() == $code or
- * $code is an integer and $obj->getCode() == $code
- *
- * @return bool true if parameter is an error
- */
- public static function isError($data, $code = null)
- {
- if (!is_a($data, 'PEAR_Error')) {
- return false;
- }
-
- if (is_null($code)) {
- return true;
- } elseif (is_string($code)) {
- return $data->getMessage() == $code;
- }
-
- return $data->getCode() == $code;
- }
-
- /**
- * Sets how errors generated by this object should be handled.
- * Can be invoked both in objects and statically. If called
- * statically, setErrorHandling sets the default behaviour for all
- * PEAR objects. If called in an object, setErrorHandling sets
- * the default behaviour for that object.
- *
- * @param object $object
- * Object the method was called on (non-static mode)
- *
- * @param int $mode
- * One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
- * PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
- * PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION.
- *
- * @param mixed $options
- * When $mode is PEAR_ERROR_TRIGGER, this is the error level (one
- * of E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
- *
- * When $mode is PEAR_ERROR_CALLBACK, this parameter is expected
- * to be the callback function or method. A callback
- * function is a string with the name of the function, a
- * callback method is an array of two elements: the element
- * at index 0 is the object, and the element at index 1 is
- * the name of the method to call in the object.
- *
- * When $mode is PEAR_ERROR_PRINT or PEAR_ERROR_DIE, this is
- * a printf format string used when printing the error
- * message.
- *
- * @access public
- * @return void
- * @see PEAR_ERROR_RETURN
- * @see PEAR_ERROR_PRINT
- * @see PEAR_ERROR_TRIGGER
- * @see PEAR_ERROR_DIE
- * @see PEAR_ERROR_CALLBACK
- * @see PEAR_ERROR_EXCEPTION
- *
- * @since PHP 4.0.5
- */
- protected static function _setErrorHandling(
- $object, $mode = null, $options = null
- ) {
- if ($object !== null) {
- $setmode = &$object->_default_error_mode;
- $setoptions = &$object->_default_error_options;
- } else {
- $setmode = &$GLOBALS['_PEAR_default_error_mode'];
- $setoptions = &$GLOBALS['_PEAR_default_error_options'];
- }
-
- switch ($mode) {
- case PEAR_ERROR_EXCEPTION:
- case PEAR_ERROR_RETURN:
- case PEAR_ERROR_PRINT:
- case PEAR_ERROR_TRIGGER:
- case PEAR_ERROR_DIE:
- case null:
- $setmode = $mode;
- $setoptions = $options;
- break;
-
- case PEAR_ERROR_CALLBACK:
- $setmode = $mode;
- // class/object method callback
- if (is_callable($options)) {
- $setoptions = $options;
- } else {
- trigger_error("invalid error callback", E_USER_WARNING);
- }
- break;
-
- default:
- trigger_error("invalid error mode", E_USER_WARNING);
- break;
- }
- }
-
- /**
- * This method is used to tell which errors you expect to get.
- * Expected errors are always returned with error mode
- * PEAR_ERROR_RETURN. Expected error codes are stored in a stack,
- * and this method pushes a new element onto it. The list of
- * expected errors are in effect until they are popped off the
- * stack with the popExpect() method.
- *
- * Note that this method can not be called statically
- *
- * @param mixed $code a single error code or an array of error codes to expect
- *
- * @return int the new depth of the "expected errors" stack
- * @access public
- */
- function expectError($code = '*')
- {
- if (is_array($code)) {
- array_push($this->_expected_errors, $code);
- } else {
- array_push($this->_expected_errors, array($code));
- }
- return count($this->_expected_errors);
- }
-
- /**
- * This method pops one element off the expected error codes
- * stack.
- *
- * @return array the list of error codes that were popped
- */
- function popExpect()
- {
- return array_pop($this->_expected_errors);
- }
-
- /**
- * This method checks unsets an error code if available
- *
- * @param mixed error code
- * @return bool true if the error code was unset, false otherwise
- * @access private
- * @since PHP 4.3.0
- */
- function _checkDelExpect($error_code)
- {
- $deleted = false;
- foreach ($this->_expected_errors as $key => $error_array) {
- if (in_array($error_code, $error_array)) {
- unset($this->_expected_errors[$key][array_search($error_code, $error_array)]);
- $deleted = true;
- }
-
- // clean up empty arrays
- if (0 == count($this->_expected_errors[$key])) {
- unset($this->_expected_errors[$key]);
- }
- }
-
- return $deleted;
- }
-
- /**
- * This method deletes all occurrences of the specified element from
- * the expected error codes stack.
- *
- * @param mixed $error_code error code that should be deleted
- * @return mixed list of error codes that were deleted or error
- * @access public
- * @since PHP 4.3.0
- */
- function delExpect($error_code)
- {
- $deleted = false;
- if ((is_array($error_code) && (0 != count($error_code)))) {
- // $error_code is a non-empty array here; we walk through it trying
- // to unset all values
- foreach ($error_code as $key => $error) {
- $deleted = $this->_checkDelExpect($error) ? true : false;
- }
-
- return $deleted ? true : PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
- } elseif (!empty($error_code)) {
- // $error_code comes alone, trying to unset it
- if ($this->_checkDelExpect($error_code)) {
- return true;
- }
-
- return PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
- }
-
- // $error_code is empty
- return PEAR::raiseError("The expected error you submitted is empty"); // IMPROVE ME
- }
-
- /**
- * This method is a wrapper that returns an instance of the
- * configured error class with this object's default error
- * handling applied. If the $mode and $options parameters are not
- * specified, the object's defaults are used.
- *
- * @param mixed $message a text error message or a PEAR error object
- *
- * @param int $code a numeric error code (it is up to your class
- * to define these if you want to use codes)
- *
- * @param int $mode One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
- * PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
- * PEAR_ERROR_CALLBACK, PEAR_ERROR_EXCEPTION.
- *
- * @param mixed $options If $mode is PEAR_ERROR_TRIGGER, this parameter
- * specifies the PHP-internal error level (one of
- * E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
- * If $mode is PEAR_ERROR_CALLBACK, this
- * parameter specifies the callback function or
- * method. In other error modes this parameter
- * is ignored.
- *
- * @param string $userinfo If you need to pass along for example debug
- * information, this parameter is meant for that.
- *
- * @param string $error_class The returned error object will be
- * instantiated from this class, if specified.
- *
- * @param bool $skipmsg If true, raiseError will only pass error codes,
- * the error message parameter will be dropped.
- *
- * @return object a PEAR error object
- * @see PEAR::setErrorHandling
- * @since PHP 4.0.5
- */
- protected static function _raiseError($object,
- $message = null,
- $code = null,
- $mode = null,
- $options = null,
- $userinfo = null,
- $error_class = null,
- $skipmsg = false)
- {
- // The error is yet a PEAR error object
- if (is_object($message)) {
- $code = $message->getCode();
- $userinfo = $message->getUserInfo();
- $error_class = $message->getType();
- $message->error_message_prefix = '';
- $message = $message->getMessage();
- }
-
- if (
- $object !== null &&
- isset($object->_expected_errors) &&
- count($object->_expected_errors) > 0 &&
- count($exp = end($object->_expected_errors))
- ) {
- if ($exp[0] == "*" ||
- (is_int(reset($exp)) && in_array($code, $exp)) ||
- (is_string(reset($exp)) && in_array($message, $exp))
- ) {
- $mode = PEAR_ERROR_RETURN;
- }
- }
-
- // No mode given, try global ones
- if ($mode === null) {
- // Class error handler
- if ($object !== null && isset($object->_default_error_mode)) {
- $mode = $object->_default_error_mode;
- $options = $object->_default_error_options;
- // Global error handler
- } elseif (isset($GLOBALS['_PEAR_default_error_mode'])) {
- $mode = $GLOBALS['_PEAR_default_error_mode'];
- $options = $GLOBALS['_PEAR_default_error_options'];
- }
- }
-
- if ($error_class !== null) {
- $ec = $error_class;
- } elseif ($object !== null && isset($object->_error_class)) {
- $ec = $object->_error_class;
- } else {
- $ec = 'PEAR_Error';
- }
-
- if ($skipmsg) {
- $a = new $ec($code, $mode, $options, $userinfo);
- } else {
- $a = new $ec($message, $code, $mode, $options, $userinfo);
- }
-
- return $a;
- }
-
- /**
- * Simpler form of raiseError with fewer options. In most cases
- * message, code and userinfo are enough.
- *
- * @param mixed $message a text error message or a PEAR error object
- *
- * @param int $code a numeric error code (it is up to your class
- * to define these if you want to use codes)
- *
- * @param string $userinfo If you need to pass along for example debug
- * information, this parameter is meant for that.
- *
- * @return object a PEAR error object
- * @see PEAR::raiseError
- */
- protected static function _throwError($object, $message = null, $code = null, $userinfo = null)
- {
- if ($object !== null) {
- $a = $object->raiseError($message, $code, null, null, $userinfo);
- return $a;
- }
-
- $a = PEAR::raiseError($message, $code, null, null, $userinfo);
- return $a;
- }
-
- public static function staticPushErrorHandling($mode, $options = null)
- {
- $stack = &$GLOBALS['_PEAR_error_handler_stack'];
- $def_mode = &$GLOBALS['_PEAR_default_error_mode'];
- $def_options = &$GLOBALS['_PEAR_default_error_options'];
- $stack[] = array($def_mode, $def_options);
- switch ($mode) {
- case PEAR_ERROR_EXCEPTION:
- case PEAR_ERROR_RETURN:
- case PEAR_ERROR_PRINT:
- case PEAR_ERROR_TRIGGER:
- case PEAR_ERROR_DIE:
- case null:
- $def_mode = $mode;
- $def_options = $options;
- break;
-
- case PEAR_ERROR_CALLBACK:
- $def_mode = $mode;
- // class/object method callback
- if (is_callable($options)) {
- $def_options = $options;
- } else {
- trigger_error("invalid error callback", E_USER_WARNING);
- }
- break;
-
- default:
- trigger_error("invalid error mode", E_USER_WARNING);
- break;
- }
- $stack[] = array($mode, $options);
- return true;
- }
-
- public static function staticPopErrorHandling()
- {
- $stack = &$GLOBALS['_PEAR_error_handler_stack'];
- $setmode = &$GLOBALS['_PEAR_default_error_mode'];
- $setoptions = &$GLOBALS['_PEAR_default_error_options'];
- array_pop($stack);
- list($mode, $options) = $stack[sizeof($stack) - 1];
- array_pop($stack);
- switch ($mode) {
- case PEAR_ERROR_EXCEPTION:
- case PEAR_ERROR_RETURN:
- case PEAR_ERROR_PRINT:
- case PEAR_ERROR_TRIGGER:
- case PEAR_ERROR_DIE:
- case null:
- $setmode = $mode;
- $setoptions = $options;
- break;
-
- case PEAR_ERROR_CALLBACK:
- $setmode = $mode;
- // class/object method callback
- if (is_callable($options)) {
- $setoptions = $options;
- } else {
- trigger_error("invalid error callback", E_USER_WARNING);
- }
- break;
-
- default:
- trigger_error("invalid error mode", E_USER_WARNING);
- break;
- }
- return true;
- }
-
- /**
- * Push a new error handler on top of the error handler options stack. With this
- * you can easily override the actual error handler for some code and restore
- * it later with popErrorHandling.
- *
- * @param mixed $mode (same as setErrorHandling)
- * @param mixed $options (same as setErrorHandling)
- *
- * @return bool Always true
- *
- * @see PEAR::setErrorHandling
- */
- protected static function _pushErrorHandling($object, $mode, $options = null)
- {
- $stack = &$GLOBALS['_PEAR_error_handler_stack'];
- if ($object !== null) {
- $def_mode = &$object->_default_error_mode;
- $def_options = &$object->_default_error_options;
- } else {
- $def_mode = &$GLOBALS['_PEAR_default_error_mode'];
- $def_options = &$GLOBALS['_PEAR_default_error_options'];
- }
- $stack[] = array($def_mode, $def_options);
-
- if ($object !== null) {
- $object->setErrorHandling($mode, $options);
- } else {
- PEAR::setErrorHandling($mode, $options);
- }
- $stack[] = array($mode, $options);
- return true;
- }
-
- /**
- * Pop the last error handler used
- *
- * @return bool Always true
- *
- * @see PEAR::pushErrorHandling
- */
- protected static function _popErrorHandling($object)
- {
- $stack = &$GLOBALS['_PEAR_error_handler_stack'];
- array_pop($stack);
- list($mode, $options) = $stack[sizeof($stack) - 1];
- array_pop($stack);
- if ($object !== null) {
- $object->setErrorHandling($mode, $options);
- } else {
- PEAR::setErrorHandling($mode, $options);
- }
- return true;
- }
-
- /**
- * OS independent PHP extension load. Remember to take care
- * on the correct extension name for case sensitive OSes.
- *
- * @param string $ext The extension name
- * @return bool Success or not on the dl() call
- */
- public static function loadExtension($ext)
- {
- if (extension_loaded($ext)) {
- return true;
- }
-
- // if either returns true dl() will produce a FATAL error, stop that
- if (
- function_exists('dl') === false ||
- ini_get('enable_dl') != 1
- ) {
- return false;
- }
-
- if (OS_WINDOWS) {
- $suffix = '.dll';
- } elseif (PHP_OS == 'HP-UX') {
- $suffix = '.sl';
- } elseif (PHP_OS == 'AIX') {
- $suffix = '.a';
- } elseif (PHP_OS == 'OSX') {
- $suffix = '.bundle';
- } else {
- $suffix = '.so';
- }
-
- return @dl('php_'.$ext.$suffix) || @dl($ext.$suffix);
- }
-}
-
-function _PEAR_call_destructors()
-{
- global $_PEAR_destructor_object_list;
- if (is_array($_PEAR_destructor_object_list) &&
- sizeof($_PEAR_destructor_object_list))
- {
- reset($_PEAR_destructor_object_list);
-
- $destructLifoExists = PEAR::getStaticProperty('PEAR', 'destructlifo');
-
- if ($destructLifoExists) {
- $_PEAR_destructor_object_list = array_reverse($_PEAR_destructor_object_list);
- }
-
- foreach ($_PEAR_destructor_object_list as $k => $objref) {
- $classname = get_class($objref);
- while ($classname) {
- $destructor = "_$classname";
- if (method_exists($objref, $destructor)) {
- $objref->$destructor();
- break;
- } else {
- $classname = get_parent_class($classname);
- }
- }
- }
- // Empty the object list to ensure that destructors are
- // not called more than once.
- $_PEAR_destructor_object_list = array();
- }
-
- // Now call the shutdown functions
- if (
- isset($GLOBALS['_PEAR_shutdown_funcs']) &&
- is_array($GLOBALS['_PEAR_shutdown_funcs']) &&
- !empty($GLOBALS['_PEAR_shutdown_funcs'])
- ) {
- foreach ($GLOBALS['_PEAR_shutdown_funcs'] as $value) {
- call_user_func_array($value[0], $value[1]);
- }
- }
-}
-
-/**
- * Standard PEAR error class for PHP 4
- *
- * This class is supserseded by {@link PEAR_Exception} in PHP 5
- *
- * @category pear
- * @package PEAR
- * @author Stig Bakken
- * @author Tomas V.V. Cox
- * @author Gregory Beaver
- * @copyright 1997-2006 The PHP Group
- * @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: @package_version@
- * @link http://pear.php.net/manual/en/core.pear.pear-error.php
- * @see PEAR::raiseError(), PEAR::throwError()
- * @since Class available since PHP 4.0.2
- */
-class PEAR_Error
-{
- var $error_message_prefix = '';
- var $mode = PEAR_ERROR_RETURN;
- var $level = E_USER_NOTICE;
- var $code = -1;
- var $message = '';
- var $userinfo = '';
- var $backtrace = null;
- var $callback = null;
-
- /**
- * PEAR_Error constructor
- *
- * @param string $message message
- *
- * @param int $code (optional) error code
- *
- * @param int $mode (optional) error mode, one of: PEAR_ERROR_RETURN,
- * PEAR_ERROR_PRINT, PEAR_ERROR_DIE, PEAR_ERROR_TRIGGER,
- * PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION
- *
- * @param mixed $options (optional) error level, _OR_ in the case of
- * PEAR_ERROR_CALLBACK, the callback function or object/method
- * tuple.
- *
- * @param string $userinfo (optional) additional user/debug info
- *
- * @access public
- *
- */
- function __construct($message = 'unknown error', $code = null,
- $mode = null, $options = null, $userinfo = null)
- {
- if ($mode === null) {
- $mode = PEAR_ERROR_RETURN;
- }
- $this->message = $message;
- $this->code = $code;
- $this->mode = $mode;
- $this->userinfo = $userinfo;
-
- $skiptrace = PEAR::getStaticProperty('PEAR_Error', 'skiptrace');
-
- if (!$skiptrace) {
- $this->backtrace = debug_backtrace();
- if (isset($this->backtrace[0]) && isset($this->backtrace[0]['object'])) {
- unset($this->backtrace[0]['object']);
- }
- }
-
- if ($mode & PEAR_ERROR_CALLBACK) {
- $this->level = E_USER_NOTICE;
- $this->callback = $options;
- } else {
- if ($options === null) {
- $options = E_USER_NOTICE;
- }
-
- $this->level = $options;
- $this->callback = null;
- }
-
- if ($this->mode & PEAR_ERROR_PRINT) {
- if (is_null($options) || is_int($options)) {
- $format = "%s";
- } else {
- $format = $options;
- }
-
- printf($format, $this->getMessage());
- }
-
- if ($this->mode & PEAR_ERROR_TRIGGER) {
- trigger_error($this->getMessage(), $this->level);
- }
-
- if ($this->mode & PEAR_ERROR_DIE) {
- $msg = $this->getMessage();
- if (is_null($options) || is_int($options)) {
- $format = "%s";
- if (substr($msg, -1) != "\n") {
- $msg .= "\n";
- }
- } else {
- $format = $options;
- }
- printf($format, $msg);
- exit($code);
- }
-
- if ($this->mode & PEAR_ERROR_CALLBACK && is_callable($this->callback)) {
- call_user_func($this->callback, $this);
- }
-
- if ($this->mode & PEAR_ERROR_EXCEPTION) {
- trigger_error("PEAR_ERROR_EXCEPTION is obsolete, use class PEAR_Exception for exceptions", E_USER_WARNING);
- eval('$e = new Exception($this->message, $this->code);throw($e);');
- }
- }
-
- /**
- * Only here for backwards compatibility.
- *
- * Class "Cache_Error" still uses it, among others.
- *
- * @param string $message Message
- * @param int $code Error code
- * @param int $mode Error mode
- * @param mixed $options See __construct()
- * @param string $userinfo Additional user/debug info
- */
- public function PEAR_Error(
- $message = 'unknown error', $code = null, $mode = null,
- $options = null, $userinfo = null
- ) {
- self::__construct($message, $code, $mode, $options, $userinfo);
- }
-
- /**
- * Get the error mode from an error object.
- *
- * @return int error mode
- * @access public
- */
- function getMode()
- {
- return $this->mode;
- }
-
- /**
- * Get the callback function/method from an error object.
- *
- * @return mixed callback function or object/method array
- * @access public
- */
- function getCallback()
- {
- return $this->callback;
- }
-
- /**
- * Get the error message from an error object.
- *
- * @return string full error message
- * @access public
- */
- function getMessage()
- {
- return ($this->error_message_prefix . $this->message);
- }
-
- /**
- * Get error code from an error object
- *
- * @return int error code
- * @access public
- */
- function getCode()
- {
- return $this->code;
- }
-
- /**
- * Get the name of this error/exception.
- *
- * @return string error/exception name (type)
- * @access public
- */
- function getType()
- {
- return get_class($this);
- }
-
- /**
- * Get additional user-supplied information.
- *
- * @return string user-supplied information
- * @access public
- */
- function getUserInfo()
- {
- return $this->userinfo;
- }
-
- /**
- * Get additional debug information supplied by the application.
- *
- * @return string debug information
- * @access public
- */
- function getDebugInfo()
- {
- return $this->getUserInfo();
- }
-
- /**
- * Get the call backtrace from where the error was generated.
- * Supported with PHP 4.3.0 or newer.
- *
- * @param int $frame (optional) what frame to fetch
- * @return array Backtrace, or NULL if not available.
- * @access public
- */
- function getBacktrace($frame = null)
- {
- if (defined('PEAR_IGNORE_BACKTRACE')) {
- return null;
- }
- if ($frame === null) {
- return $this->backtrace;
- }
- return $this->backtrace[$frame];
- }
-
- function addUserInfo($info)
- {
- if (empty($this->userinfo)) {
- $this->userinfo = $info;
- } else {
- $this->userinfo .= " ** $info";
- }
- }
-
- function __toString()
- {
- return $this->getMessage();
- }
-
- /**
- * Make a string representation of this object.
- *
- * @return string a string with an object summary
- * @access public
- */
- function toString()
- {
- $modes = array();
- $levels = array(E_USER_NOTICE => 'notice',
- E_USER_WARNING => 'warning',
- E_USER_ERROR => 'error');
- if ($this->mode & PEAR_ERROR_CALLBACK) {
- if (is_array($this->callback)) {
- $callback = (is_object($this->callback[0]) ?
- strtolower(get_class($this->callback[0])) :
- $this->callback[0]) . '::' .
- $this->callback[1];
- } else {
- $callback = $this->callback;
- }
- return sprintf('[%s: message="%s" code=%d mode=callback '.
- 'callback=%s prefix="%s" info="%s"]',
- strtolower(get_class($this)), $this->message, $this->code,
- $callback, $this->error_message_prefix,
- $this->userinfo);
- }
- if ($this->mode & PEAR_ERROR_PRINT) {
- $modes[] = 'print';
- }
- if ($this->mode & PEAR_ERROR_TRIGGER) {
- $modes[] = 'trigger';
- }
- if ($this->mode & PEAR_ERROR_DIE) {
- $modes[] = 'die';
- }
- if ($this->mode & PEAR_ERROR_RETURN) {
- $modes[] = 'return';
- }
- return sprintf('[%s: message="%s" code=%d mode=%s level=%s '.
- 'prefix="%s" info="%s"]',
- strtolower(get_class($this)), $this->message, $this->code,
- implode("|", $modes), $levels[$this->level],
- $this->error_message_prefix,
- $this->userinfo);
- }
-}
-
-/*
- * Local Variables:
- * mode: php
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- */
diff --git a/lmo/includes/PEAR5.php b/lmo/includes/PEAR5.php
deleted file mode 100644
index 42860678..00000000
--- a/lmo/includes/PEAR5.php
+++ /dev/null
@@ -1,33 +0,0 @@
-
- * @author Jim Jagielski (jimjag)
- * @author Andy Prevost (codeworxtech)
- * @author Brent R. Matzelle (original founder)
- * @copyright 2012 - 2020 Marcus Bointon
- * @copyright 2010 - 2012 Jim Jagielski
- * @copyright 2004 - 2009 Andy Prevost
- * @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License
- * @note This program is distributed in the hope that it will be useful - WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#[\AllowDynamicProperties]
-
-/**
- * PHPMailer - PHP email creation and transport class.
- *
- * @author Marcus Bointon (Synchro/coolbru)
- * @author Jim Jagielski (jimjag)
- * @author Andy Prevost (codeworxtech)
- * @author Brent R. Matzelle (original founder)
- */
-class PHPMailer
-{
- const CHARSET_ASCII = 'us-ascii';
- const CHARSET_ISO88591 = 'iso-8859-1';
- const CHARSET_UTF8 = 'utf-8';
-
- const CONTENT_TYPE_PLAINTEXT = 'text/plain';
- const CONTENT_TYPE_TEXT_CALENDAR = 'text/calendar';
- const CONTENT_TYPE_TEXT_HTML = 'text/html';
- const CONTENT_TYPE_MULTIPART_ALTERNATIVE = 'multipart/alternative';
- const CONTENT_TYPE_MULTIPART_MIXED = 'multipart/mixed';
- const CONTENT_TYPE_MULTIPART_RELATED = 'multipart/related';
-
- const ENCODING_7BIT = '7bit';
- const ENCODING_8BIT = '8bit';
- const ENCODING_BASE64 = 'base64';
- const ENCODING_BINARY = 'binary';
- const ENCODING_QUOTED_PRINTABLE = 'quoted-printable';
-
- const ENCRYPTION_STARTTLS = 'tls';
- const ENCRYPTION_SMTPS = 'ssl';
-
- const ICAL_METHOD_REQUEST = 'REQUEST';
- const ICAL_METHOD_PUBLISH = 'PUBLISH';
- const ICAL_METHOD_REPLY = 'REPLY';
- const ICAL_METHOD_ADD = 'ADD';
- const ICAL_METHOD_CANCEL = 'CANCEL';
- const ICAL_METHOD_REFRESH = 'REFRESH';
- const ICAL_METHOD_COUNTER = 'COUNTER';
- const ICAL_METHOD_DECLINECOUNTER = 'DECLINECOUNTER';
-
- /**
- * Email priority.
- * Options: null (default), 1 = High, 3 = Normal, 5 = low.
- * When null, the header is not set at all.
- *
- * @var int|null
- */
- public $Priority;
-
- /**
- * The character set of the message.
- *
- * @var string
- */
- public $CharSet = self::CHARSET_ISO88591;
-
- /**
- * The MIME Content-type of the message.
- *
- * @var string
- */
- public $ContentType = self::CONTENT_TYPE_PLAINTEXT;
-
- /**
- * The message encoding.
- * Options: "8bit", "7bit", "binary", "base64", and "quoted-printable".
- *
- * @var string
- */
- public $Encoding = self::ENCODING_8BIT;
-
- /**
- * Holds the most recent mailer error message.
- *
- * @var string
- */
- public $ErrorInfo = '';
-
- /**
- * The From email address for the message.
- *
- * @var string
- */
- public $From = '';
-
- /**
- * The From name of the message.
- *
- * @var string
- */
- public $FromName = '';
-
- /**
- * The envelope sender of the message.
- * This will usually be turned into a Return-Path header by the receiver,
- * and is the address that bounces will be sent to.
- * If not empty, will be passed via `-f` to sendmail or as the 'MAIL FROM' value over SMTP.
- *
- * @var string
- */
- public $Sender = '';
-
- /**
- * The Subject of the message.
- *
- * @var string
- */
- public $Subject = '';
-
- /**
- * An HTML or plain text message body.
- * If HTML then call isHTML(true).
- *
- * @var string
- */
- public $Body = '';
-
- /**
- * The plain-text message body.
- * This body can be read by mail clients that do not have HTML email
- * capability such as mutt & Eudora.
- * Clients that can read HTML will view the normal Body.
- *
- * @var string
- */
- public $AltBody = '';
-
- /**
- * An iCal message part body.
- * Only supported in simple alt or alt_inline message types
- * To generate iCal event structures, use classes like EasyPeasyICS or iCalcreator.
- *
- * @see https://kigkonsult.se/iCalcreator/
- *
- * @var string
- */
- public $Ical = '';
-
- /**
- * Value-array of "method" in Contenttype header "text/calendar"
- *
- * @var string[]
- */
- protected static $IcalMethods = [
- self::ICAL_METHOD_REQUEST,
- self::ICAL_METHOD_PUBLISH,
- self::ICAL_METHOD_REPLY,
- self::ICAL_METHOD_ADD,
- self::ICAL_METHOD_CANCEL,
- self::ICAL_METHOD_REFRESH,
- self::ICAL_METHOD_COUNTER,
- self::ICAL_METHOD_DECLINECOUNTER,
- ];
-
- /**
- * The complete compiled MIME message body.
- *
- * @var string
- */
- protected $MIMEBody = '';
-
- /**
- * The complete compiled MIME message headers.
- *
- * @var string
- */
- protected $MIMEHeader = '';
-
- /**
- * Extra headers that createHeader() doesn't fold in.
- *
- * @var string
- */
- protected $mailHeader = '';
-
- /**
- * Word-wrap the message body to this number of chars.
- * Set to 0 to not wrap. A useful value here is 78, for RFC2822 section 2.1.1 compliance.
- *
- * @see static::STD_LINE_LENGTH
- *
- * @var int
- */
- public $WordWrap = 0;
-
- /**
- * Which method to use to send mail.
- * Options: "mail", "sendmail", or "smtp".
- *
- * @var string
- */
- public $Mailer = 'mail';
-
- /**
- * The path to the sendmail program.
- *
- * @var string
- */
- public $Sendmail = '/usr/sbin/sendmail';
-
- /**
- * Whether mail() uses a fully sendmail-compatible MTA.
- * One which supports sendmail's "-oi -f" options.
- *
- * @var bool
- */
- public $UseSendmailOptions = true;
-
- /**
- * The email address that a reading confirmation should be sent to, also known as read receipt.
- *
- * @var string
- */
- public $ConfirmReadingTo = '';
-
- /**
- * The hostname to use in the Message-ID header and as default HELO string.
- * If empty, PHPMailer attempts to find one with, in order,
- * $_SERVER['SERVER_NAME'], gethostname(), php_uname('n'), or the value
- * 'localhost.localdomain'.
- *
- * @see PHPMailer::$Helo
- *
- * @var string
- */
- public $Hostname = '';
-
- /**
- * An ID to be used in the Message-ID header.
- * If empty, a unique id will be generated.
- * You can set your own, but it must be in the format "",
- * as defined in RFC5322 section 3.6.4 or it will be ignored.
- *
- * @see https://tools.ietf.org/html/rfc5322#section-3.6.4
- *
- * @var string
- */
- public $MessageID = '';
-
- /**
- * The message Date to be used in the Date header.
- * If empty, the current date will be added.
- *
- * @var string
- */
- public $MessageDate = '';
-
- /**
- * SMTP hosts.
- * Either a single hostname or multiple semicolon-delimited hostnames.
- * You can also specify a different port
- * for each host by using this format: [hostname:port]
- * (e.g. "smtp1.example.com:25;smtp2.example.com").
- * You can also specify encryption type, for example:
- * (e.g. "tls://smtp1.example.com:587;ssl://smtp2.example.com:465").
- * Hosts will be tried in order.
- *
- * @var string
- */
- public $Host = 'localhost';
-
- /**
- * The default SMTP server port.
- *
- * @var int
- */
- public $Port = 25;
-
- /**
- * The SMTP HELO/EHLO name used for the SMTP connection.
- * Default is $Hostname. If $Hostname is empty, PHPMailer attempts to find
- * one with the same method described above for $Hostname.
- *
- * @see PHPMailer::$Hostname
- *
- * @var string
- */
- public $Helo = '';
-
- /**
- * What kind of encryption to use on the SMTP connection.
- * Options: '', static::ENCRYPTION_STARTTLS, or static::ENCRYPTION_SMTPS.
- *
- * @var string
- */
- public $SMTPSecure = '';
-
- /**
- * Whether to enable TLS encryption automatically if a server supports it,
- * even if `SMTPSecure` is not set to 'tls'.
- * Be aware that in PHP >= 5.6 this requires that the server's certificates are valid.
- *
- * @var bool
- */
- public $SMTPAutoTLS = true;
-
- /**
- * Whether to use SMTP authentication.
- * Uses the Username and Password properties.
- *
- * @see PHPMailer::$Username
- * @see PHPMailer::$Password
- *
- * @var bool
- */
- public $SMTPAuth = false;
-
- /**
- * Options array passed to stream_context_create when connecting via SMTP.
- *
- * @var array
- */
- public $SMTPOptions = [];
-
- /**
- * SMTP username.
- *
- * @var string
- */
- public $Username = '';
-
- /**
- * SMTP password.
- *
- * @var string
- */
- public $Password = '';
-
- /**
- * SMTP authentication type. Options are CRAM-MD5, LOGIN, PLAIN, XOAUTH2.
- * If not specified, the first one from that list that the server supports will be selected.
- *
- * @var string
- */
- public $AuthType = '';
-
- /**
- * SMTP SMTPXClient command attributes
- *
- * @var array
- */
- protected $SMTPXClient = [];
-
- /**
- * An implementation of the PHPMailer OAuthTokenProvider interface.
- *
- * @var OAuthTokenProvider
- */
- protected $oauth;
-
- /**
- * The SMTP server timeout in seconds.
- * Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2.
- *
- * @var int
- */
- public $Timeout = 300;
-
- /**
- * Comma separated list of DSN notifications
- * 'NEVER' under no circumstances a DSN must be returned to the sender.
- * If you use NEVER all other notifications will be ignored.
- * 'SUCCESS' will notify you when your mail has arrived at its destination.
- * 'FAILURE' will arrive if an error occurred during delivery.
- * 'DELAY' will notify you if there is an unusual delay in delivery, but the actual
- * delivery's outcome (success or failure) is not yet decided.
- *
- * @see https://tools.ietf.org/html/rfc3461 See section 4.1 for more information about NOTIFY
- */
- public $dsn = '';
-
- /**
- * SMTP class debug output mode.
- * Debug output level.
- * Options:
- * @see SMTP::DEBUG_OFF: No output
- * @see SMTP::DEBUG_CLIENT: Client messages
- * @see SMTP::DEBUG_SERVER: Client and server messages
- * @see SMTP::DEBUG_CONNECTION: As SERVER plus connection status
- * @see SMTP::DEBUG_LOWLEVEL: Noisy, low-level data output, rarely needed
- *
- * @see SMTP::$do_debug
- *
- * @var int
- */
- public $SMTPDebug = 0;
-
- /**
- * How to handle debug output.
- * Options:
- * * `echo` Output plain-text as-is, appropriate for CLI
- * * `html` Output escaped, line breaks converted to ` `, appropriate for browser output
- * * `error_log` Output to error log as configured in php.ini
- * By default PHPMailer will use `echo` if run from a `cli` or `cli-server` SAPI, `html` otherwise.
- * Alternatively, you can provide a callable expecting two params: a message string and the debug level:
- *
- * ```php
- * $mail->Debugoutput = function($str, $level) {echo "debug level $level; message: $str";};
- * ```
- *
- * Alternatively, you can pass in an instance of a PSR-3 compatible logger, though only `debug`
- * level output is used:
- *
- * ```php
- * $mail->Debugoutput = new myPsr3Logger;
- * ```
- *
- * @see SMTP::$Debugoutput
- *
- * @var string|callable|\Psr\Log\LoggerInterface
- */
- public $Debugoutput = 'echo';
-
- /**
- * Whether to keep the SMTP connection open after each message.
- * If this is set to true then the connection will remain open after a send,
- * and closing the connection will require an explicit call to smtpClose().
- * It's a good idea to use this if you are sending multiple messages as it reduces overhead.
- * See the mailing list example for how to use it.
- *
- * @var bool
- */
- public $SMTPKeepAlive = false;
-
- /**
- * Whether to split multiple to addresses into multiple messages
- * or send them all in one message.
- * Only supported in `mail` and `sendmail` transports, not in SMTP.
- *
- * @var bool
- *
- * @deprecated 6.0.0 PHPMailer isn't a mailing list manager!
- */
- public $SingleTo = false;
-
- /**
- * Storage for addresses when SingleTo is enabled.
- *
- * @var array
- */
- protected $SingleToArray = [];
-
- /**
- * Whether to generate VERP addresses on send.
- * Only applicable when sending via SMTP.
- *
- * @see https://en.wikipedia.org/wiki/Variable_envelope_return_path
- * @see https://www.postfix.org/VERP_README.html Postfix VERP info
- *
- * @var bool
- */
- public $do_verp = false;
-
- /**
- * Whether to allow sending messages with an empty body.
- *
- * @var bool
- */
- public $AllowEmpty = false;
-
- /**
- * DKIM selector.
- *
- * @var string
- */
- public $DKIM_selector = '';
-
- /**
- * DKIM Identity.
- * Usually the email address used as the source of the email.
- *
- * @var string
- */
- public $DKIM_identity = '';
-
- /**
- * DKIM passphrase.
- * Used if your key is encrypted.
- *
- * @var string
- */
- public $DKIM_passphrase = '';
-
- /**
- * DKIM signing domain name.
- *
- * @example 'example.com'
- *
- * @var string
- */
- public $DKIM_domain = '';
-
- /**
- * DKIM Copy header field values for diagnostic use.
- *
- * @var bool
- */
- public $DKIM_copyHeaderFields = true;
-
- /**
- * DKIM Extra signing headers.
- *
- * @example ['List-Unsubscribe', 'List-Help']
- *
- * @var array
- */
- public $DKIM_extraHeaders = [];
-
- /**
- * DKIM private key file path.
- *
- * @var string
- */
- public $DKIM_private = '';
-
- /**
- * DKIM private key string.
- *
- * If set, takes precedence over `$DKIM_private`.
- *
- * @var string
- */
- public $DKIM_private_string = '';
-
- /**
- * Callback Action function name.
- *
- * The function that handles the result of the send email action.
- * It is called out by send() for each email sent.
- *
- * Value can be any php callable: https://www.php.net/is_callable
- *
- * Parameters:
- * bool $result result of the send action
- * array $to email addresses of the recipients
- * array $cc cc email addresses
- * array $bcc bcc email addresses
- * string $subject the subject
- * string $body the email body
- * string $from email address of sender
- * string $extra extra information of possible use
- * "smtp_transaction_id' => last smtp transaction id
- *
- * @var string
- */
- public $action_function = '';
-
- /**
- * What to put in the X-Mailer header.
- * Options: An empty string for PHPMailer default, whitespace/null for none, or a string to use.
- *
- * @var string|null
- */
- public $XMailer = '';
-
- /**
- * Which validator to use by default when validating email addresses.
- * May be a callable to inject your own validator, but there are several built-in validators.
- * The default validator uses PHP's FILTER_VALIDATE_EMAIL filter_var option.
- *
- * @see PHPMailer::validateAddress()
- *
- * @var string|callable
- */
- public static $validator = 'php';
-
- /**
- * An instance of the SMTP sender class.
- *
- * @var SMTP
- */
- protected $smtp;
-
- /**
- * The array of 'to' names and addresses.
- *
- * @var array
- */
- protected $to = [];
-
- /**
- * The array of 'cc' names and addresses.
- *
- * @var array
- */
- protected $cc = [];
-
- /**
- * The array of 'bcc' names and addresses.
- *
- * @var array
- */
- protected $bcc = [];
-
- /**
- * The array of reply-to names and addresses.
- *
- * @var array
- */
- protected $ReplyTo = [];
-
- /**
- * An array of all kinds of addresses.
- * Includes all of $to, $cc, $bcc.
- *
- * @see PHPMailer::$to
- * @see PHPMailer::$cc
- * @see PHPMailer::$bcc
- *
- * @var array
- */
- protected $all_recipients = [];
-
- /**
- * An array of names and addresses queued for validation.
- * In send(), valid and non duplicate entries are moved to $all_recipients
- * and one of $to, $cc, or $bcc.
- * This array is used only for addresses with IDN.
- *
- * @see PHPMailer::$to
- * @see PHPMailer::$cc
- * @see PHPMailer::$bcc
- * @see PHPMailer::$all_recipients
- *
- * @var array
- */
- protected $RecipientsQueue = [];
-
- /**
- * An array of reply-to names and addresses queued for validation.
- * In send(), valid and non duplicate entries are moved to $ReplyTo.
- * This array is used only for addresses with IDN.
- *
- * @see PHPMailer::$ReplyTo
- *
- * @var array
- */
- protected $ReplyToQueue = [];
-
- /**
- * The array of attachments.
- *
- * @var array
- */
- protected $attachment = [];
-
- /**
- * The array of custom headers.
- *
- * @var array
- */
- protected $CustomHeader = [];
-
- /**
- * The most recent Message-ID (including angular brackets).
- *
- * @var string
- */
- protected $lastMessageID = '';
-
- /**
- * The message's MIME type.
- *
- * @var string
- */
- protected $message_type = '';
-
- /**
- * The array of MIME boundary strings.
- *
- * @var array
- */
- protected $boundary = [];
-
- /**
- * The array of available text strings for the current language.
- *
- * @var array
- */
- protected $language = [];
-
- /**
- * The number of errors encountered.
- *
- * @var int
- */
- protected $error_count = 0;
-
- /**
- * The S/MIME certificate file path.
- *
- * @var string
- */
- protected $sign_cert_file = '';
-
- /**
- * The S/MIME key file path.
- *
- * @var string
- */
- protected $sign_key_file = '';
-
- /**
- * The optional S/MIME extra certificates ("CA Chain") file path.
- *
- * @var string
- */
- protected $sign_extracerts_file = '';
-
- /**
- * The S/MIME password for the key.
- * Used only if the key is encrypted.
- *
- * @var string
- */
- protected $sign_key_pass = '';
-
- /**
- * Whether to throw exceptions for errors.
- *
- * @var bool
- */
- protected $exceptions = false;
-
- /**
- * Unique ID used for message ID and boundaries.
- *
- * @var string
- */
- protected $uniqueid = '';
-
- /**
- * The PHPMailer Version number.
- *
- * @var string
- */
- const VERSION = '6.9.2';
-
- /**
- * Error severity: message only, continue processing.
- *
- * @var int
- */
- const STOP_MESSAGE = 0;
-
- /**
- * Error severity: message, likely ok to continue processing.
- *
- * @var int
- */
- const STOP_CONTINUE = 1;
-
- /**
- * Error severity: message, plus full stop, critical error reached.
- *
- * @var int
- */
- const STOP_CRITICAL = 2;
-
- /**
- * The SMTP standard CRLF line break.
- * If you want to change line break format, change static::$LE, not this.
- */
- const CRLF = "\r\n";
-
- /**
- * "Folding White Space" a white space string used for line folding.
- */
- const FWS = ' ';
-
- /**
- * SMTP RFC standard line ending; Carriage Return, Line Feed.
- *
- * @var string
- */
- protected static $LE = self::CRLF;
-
- /**
- * The maximum line length supported by mail().
- *
- * Background: mail() will sometimes corrupt messages
- * with headers longer than 65 chars, see #818.
- *
- * @var int
- */
- const MAIL_MAX_LINE_LENGTH = 63;
-
- /**
- * The maximum line length allowed by RFC 2822 section 2.1.1.
- *
- * @var int
- */
- const MAX_LINE_LENGTH = 998;
-
- /**
- * The lower maximum line length allowed by RFC 2822 section 2.1.1.
- * This length does NOT include the line break
- * 76 means that lines will be 77 or 78 chars depending on whether
- * the line break format is LF or CRLF; both are valid.
- *
- * @var int
- */
- const STD_LINE_LENGTH = 76;
-
- /**
- * Constructor.
- *
- * @param bool $exceptions Should we throw external exceptions?
- */
- public function __construct($exceptions = null)
- {
- if (null !== $exceptions) {
- $this->exceptions = (bool) $exceptions;
- }
- //Pick an appropriate debug output format automatically
- $this->Debugoutput = (strpos(PHP_SAPI, 'cli') !== false ? 'echo' : 'html');
- }
-
- /**
- * Destructor.
- */
- public function __destruct()
- {
- //Close any open SMTP connection nicely
- $this->smtpClose();
- }
-
- /**
- * Call mail() in a safe_mode-aware fashion.
- * Also, unless sendmail_path points to sendmail (or something that
- * claims to be sendmail), don't pass params (not a perfect fix,
- * but it will do).
- *
- * @param string $to To
- * @param string $subject Subject
- * @param string $body Message Body
- * @param string $header Additional Header(s)
- * @param string|null $params Params
- *
- * @return bool
- */
- private function mailPassthru($to, $subject, $body, $header, $params)
- {
- //Check overloading of mail function to avoid double-encoding
- if ((int)ini_get('mbstring.func_overload') & 1) {
- $subject = $this->secureHeader($subject);
- } else {
- $subject = $this->encodeHeader($this->secureHeader($subject));
- }
- //Calling mail() with null params breaks
- $this->edebug('Sending with mail()');
- $this->edebug('Sendmail path: ' . ini_get('sendmail_path'));
- $this->edebug("Envelope sender: {$this->Sender}");
- $this->edebug("To: {$to}");
- $this->edebug("Subject: {$subject}");
- $this->edebug("Headers: {$header}");
- if (!$this->UseSendmailOptions || null === $params) {
- $result = @mail($to, $subject, $body, $header);
- } else {
- $this->edebug("Additional params: {$params}");
- $result = @mail($to, $subject, $body, $header, $params);
- }
- $this->edebug('Result: ' . ($result ? 'true' : 'false'));
- return $result;
- }
-
- /**
- * Output debugging info via a user-defined method.
- * Only generates output if debug output is enabled.
- *
- * @see PHPMailer::$Debugoutput
- * @see PHPMailer::$SMTPDebug
- *
- * @param string $str
- */
- protected function edebug($str)
- {
- if ($this->SMTPDebug <= 0) {
- return;
- }
- //Is this a PSR-3 logger?
- if ($this->Debugoutput instanceof \Psr\Log\LoggerInterface) {
- $this->Debugoutput->debug(rtrim($str, "\r\n"));
-
- return;
- }
- //Avoid clash with built-in function names
- if (is_callable($this->Debugoutput) && !in_array($this->Debugoutput, ['error_log', 'html', 'echo'])) {
- call_user_func($this->Debugoutput, $str, $this->SMTPDebug);
-
- return;
- }
- switch ($this->Debugoutput) {
- case 'error_log':
- //Don't output, just log
- /** @noinspection ForgottenDebugOutputInspection */
- error_log($str);
- break;
- case 'html':
- //Cleans up output a bit for a better looking, HTML-safe output
- echo htmlentities(
- preg_replace('/[\r\n]+/', '', $str),
- ENT_QUOTES,
- 'UTF-8'
- ), " \n";
- break;
- case 'echo':
- default:
- //Normalize line breaks
- $str = preg_replace('/\r\n|\r/m', "\n", $str);
- echo gmdate('Y-m-d H:i:s'),
- "\t",
- //Trim trailing space
- trim(
- //Indent for readability, except for trailing break
- str_replace(
- "\n",
- "\n \t ",
- trim($str)
- )
- ),
- "\n";
- }
- }
-
- /**
- * Sets message type to HTML or plain.
- *
- * @param bool $isHtml True for HTML mode
- */
- public function isHTML($isHtml = true)
- {
- if ($isHtml) {
- $this->ContentType = static::CONTENT_TYPE_TEXT_HTML;
- } else {
- $this->ContentType = static::CONTENT_TYPE_PLAINTEXT;
- }
- }
-
- /**
- * Send messages using SMTP.
- */
- public function isSMTP()
- {
- $this->Mailer = 'smtp';
- }
-
- /**
- * Send messages using PHP's mail() function.
- */
- public function isMail()
- {
- $this->Mailer = 'mail';
- }
-
- /**
- * Send messages using $Sendmail.
- */
- public function isSendmail()
- {
- $ini_sendmail_path = ini_get('sendmail_path');
-
- if (false === stripos($ini_sendmail_path, 'sendmail')) {
- $this->Sendmail = '/usr/sbin/sendmail';
- } else {
- $this->Sendmail = $ini_sendmail_path;
- }
- $this->Mailer = 'sendmail';
- }
-
- /**
- * Send messages using qmail.
- */
- public function isQmail()
- {
- $ini_sendmail_path = ini_get('sendmail_path');
-
- if (false === stripos($ini_sendmail_path, 'qmail')) {
- $this->Sendmail = '/var/qmail/bin/qmail-inject';
- } else {
- $this->Sendmail = $ini_sendmail_path;
- }
- $this->Mailer = 'qmail';
- }
-
- /**
- * Add a "To" address.
- *
- * @param string $address The email address to send to
- * @param string $name
- *
- * @throws Exception
- *
- * @return bool true on success, false if address already used or invalid in some way
- */
- public function addAddress($address, $name = '')
- {
- return $this->addOrEnqueueAnAddress('to', $address, $name);
- }
-
- /**
- * Add a "CC" address.
- *
- * @param string $address The email address to send to
- * @param string $name
- *
- * @throws Exception
- *
- * @return bool true on success, false if address already used or invalid in some way
- */
- public function addCC($address, $name = '')
- {
- return $this->addOrEnqueueAnAddress('cc', $address, $name);
- }
-
- /**
- * Add a "BCC" address.
- *
- * @param string $address The email address to send to
- * @param string $name
- *
- * @throws Exception
- *
- * @return bool true on success, false if address already used or invalid in some way
- */
- public function addBCC($address, $name = '')
- {
- return $this->addOrEnqueueAnAddress('bcc', $address, $name);
- }
-
- /**
- * Add a "Reply-To" address.
- *
- * @param string $address The email address to reply to
- * @param string $name
- *
- * @throws Exception
- *
- * @return bool true on success, false if address already used or invalid in some way
- */
- public function addReplyTo($address, $name = '')
- {
- return $this->addOrEnqueueAnAddress('Reply-To', $address, $name);
- }
-
- /**
- * Add an address to one of the recipient arrays or to the ReplyTo array. Because PHPMailer
- * can't validate addresses with an IDN without knowing the PHPMailer::$CharSet (that can still
- * be modified after calling this function), addition of such addresses is delayed until send().
- * Addresses that have been added already return false, but do not throw exceptions.
- *
- * @param string $kind One of 'to', 'cc', 'bcc', or 'Reply-To'
- * @param string $address The email address
- * @param string $name An optional username associated with the address
- *
- * @throws Exception
- *
- * @return bool true on success, false if address already used or invalid in some way
- */
- protected function addOrEnqueueAnAddress($kind, $address, $name)
- {
- $pos = false;
- if ($address !== null) {
- $address = trim($address);
- $pos = strrpos($address, '@');
- }
- if (false === $pos) {
- //At-sign is missing.
- $error_message = sprintf(
- '%s (%s): %s',
- $this->lang('invalid_address'),
- $kind,
- $address
- );
- $this->setError($error_message);
- $this->edebug($error_message);
- if ($this->exceptions) {
- throw new Exception($error_message);
- }
-
- return false;
- }
- if ($name !== null && is_string($name)) {
- $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
- } else {
- $name = '';
- }
- $params = [$kind, $address, $name];
- //Enqueue addresses with IDN until we know the PHPMailer::$CharSet.
- //Domain is assumed to be whatever is after the last @ symbol in the address
- if (static::idnSupported() && $this->has8bitChars(substr($address, ++$pos))) {
- if ('Reply-To' !== $kind) {
- if (!array_key_exists($address, $this->RecipientsQueue)) {
- $this->RecipientsQueue[$address] = $params;
-
- return true;
- }
- } elseif (!array_key_exists($address, $this->ReplyToQueue)) {
- $this->ReplyToQueue[$address] = $params;
-
- return true;
- }
-
- return false;
- }
-
- //Immediately add standard addresses without IDN.
- return call_user_func_array([$this, 'addAnAddress'], $params);
- }
-
- /**
- * Set the boundaries to use for delimiting MIME parts.
- * If you override this, ensure you set all 3 boundaries to unique values.
- * The default boundaries include a "=_" sequence which cannot occur in quoted-printable bodies,
- * as suggested by https://www.rfc-editor.org/rfc/rfc2045#section-6.7
- *
- * @return void
- */
- public function setBoundaries()
- {
- $this->uniqueid = $this->generateId();
- $this->boundary[1] = 'b1=_' . $this->uniqueid;
- $this->boundary[2] = 'b2=_' . $this->uniqueid;
- $this->boundary[3] = 'b3=_' . $this->uniqueid;
- }
-
- /**
- * Add an address to one of the recipient arrays or to the ReplyTo array.
- * Addresses that have been added already return false, but do not throw exceptions.
- *
- * @param string $kind One of 'to', 'cc', 'bcc', or 'ReplyTo'
- * @param string $address The email address to send, resp. to reply to
- * @param string $name
- *
- * @throws Exception
- *
- * @return bool true on success, false if address already used or invalid in some way
- */
- protected function addAnAddress($kind, $address, $name = '')
- {
- if (!in_array($kind, ['to', 'cc', 'bcc', 'Reply-To'])) {
- $error_message = sprintf(
- '%s: %s',
- $this->lang('Invalid recipient kind'),
- $kind
- );
- $this->setError($error_message);
- $this->edebug($error_message);
- if ($this->exceptions) {
- throw new Exception($error_message);
- }
-
- return false;
- }
- if (!static::validateAddress($address)) {
- $error_message = sprintf(
- '%s (%s): %s',
- $this->lang('invalid_address'),
- $kind,
- $address
- );
- $this->setError($error_message);
- $this->edebug($error_message);
- if ($this->exceptions) {
- throw new Exception($error_message);
- }
-
- return false;
- }
- if ('Reply-To' !== $kind) {
- if (!array_key_exists(strtolower($address), $this->all_recipients)) {
- $this->{$kind}[] = [$address, $name];
- $this->all_recipients[strtolower($address)] = true;
-
- return true;
- }
- } elseif (!array_key_exists(strtolower($address), $this->ReplyTo)) {
- $this->ReplyTo[strtolower($address)] = [$address, $name];
-
- return true;
- }
-
- return false;
- }
-
- /**
- * Parse and validate a string containing one or more RFC822-style comma-separated email addresses
- * of the form "display name " into an array of name/address pairs.
- * Uses the imap_rfc822_parse_adrlist function if the IMAP extension is available.
- * Note that quotes in the name part are removed.
- *
- * @see https://www.andrew.cmu.edu/user/agreen1/testing/mrbs/web/Mail/RFC822.php A more careful implementation
- *
- * @param string $addrstr The address list string
- * @param bool $useimap Whether to use the IMAP extension to parse the list
- * @param string $charset The charset to use when decoding the address list string.
- *
- * @return array
- */
- public static function parseAddresses($addrstr, $useimap = true, $charset = self::CHARSET_ISO88591)
- {
- $addresses = [];
- if ($useimap && function_exists('imap_rfc822_parse_adrlist')) {
- //Use this built-in parser if it's available
- $list = imap_rfc822_parse_adrlist($addrstr, '');
- // Clear any potential IMAP errors to get rid of notices being thrown at end of script.
- imap_errors();
- foreach ($list as $address) {
- if (
- '.SYNTAX-ERROR.' !== $address->host &&
- static::validateAddress($address->mailbox . '@' . $address->host)
- ) {
- //Decode the name part if it's present and encoded
- if (
- property_exists($address, 'personal') &&
- //Check for a Mbstring constant rather than using extension_loaded, which is sometimes disabled
- defined('MB_CASE_UPPER') &&
- preg_match('/^=\?.*\?=$/s', $address->personal)
- ) {
- $origCharset = mb_internal_encoding();
- mb_internal_encoding($charset);
- //Undo any RFC2047-encoded spaces-as-underscores
- $address->personal = str_replace('_', '=20', $address->personal);
- //Decode the name
- $address->personal = mb_decode_mimeheader($address->personal);
- mb_internal_encoding($origCharset);
- }
-
- $addresses[] = [
- 'name' => (property_exists($address, 'personal') ? $address->personal : ''),
- 'address' => $address->mailbox . '@' . $address->host,
- ];
- }
- }
- } else {
- //Use this simpler parser
- $list = explode(',', $addrstr);
- foreach ($list as $address) {
- $address = trim($address);
- //Is there a separate name part?
- if (strpos($address, '<') === false) {
- //No separate name, just use the whole thing
- if (static::validateAddress($address)) {
- $addresses[] = [
- 'name' => '',
- 'address' => $address,
- ];
- }
- } else {
- list($name, $email) = explode('<', $address);
- $email = trim(str_replace('>', '', $email));
- $name = trim($name);
- if (static::validateAddress($email)) {
- //Check for a Mbstring constant rather than using extension_loaded, which is sometimes disabled
- //If this name is encoded, decode it
- if (defined('MB_CASE_UPPER') && preg_match('/^=\?.*\?=$/s', $name)) {
- $origCharset = mb_internal_encoding();
- mb_internal_encoding($charset);
- //Undo any RFC2047-encoded spaces-as-underscores
- $name = str_replace('_', '=20', $name);
- //Decode the name
- $name = mb_decode_mimeheader($name);
- mb_internal_encoding($origCharset);
- }
- $addresses[] = [
- //Remove any surrounding quotes and spaces from the name
- 'name' => trim($name, '\'" '),
- 'address' => $email,
- ];
- }
- }
- }
- }
-
- return $addresses;
- }
-
- /**
- * Set the From and FromName properties.
- *
- * @param string $address
- * @param string $name
- * @param bool $auto Whether to also set the Sender address, defaults to true
- *
- * @throws Exception
- *
- * @return bool
- */
- public function setFrom($address, $name = '', $auto = true)
- {
- $address = trim((string)$address);
- $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
- //Don't validate now addresses with IDN. Will be done in send().
- $pos = strrpos($address, '@');
- if (
- (false === $pos)
- || ((!$this->has8bitChars(substr($address, ++$pos)) || !static::idnSupported())
- && !static::validateAddress($address))
- ) {
- $error_message = sprintf(
- '%s (From): %s',
- $this->lang('invalid_address'),
- $address
- );
- $this->setError($error_message);
- $this->edebug($error_message);
- if ($this->exceptions) {
- throw new Exception($error_message);
- }
-
- return false;
- }
- $this->From = $address;
- $this->FromName = $name;
- if ($auto && empty($this->Sender)) {
- $this->Sender = $address;
- }
-
- return true;
- }
-
- /**
- * Return the Message-ID header of the last email.
- * Technically this is the value from the last time the headers were created,
- * but it's also the message ID of the last sent message except in
- * pathological cases.
- *
- * @return string
- */
- public function getLastMessageID()
- {
- return $this->lastMessageID;
- }
-
- /**
- * Check that a string looks like an email address.
- * Validation patterns supported:
- * * `auto` Pick best pattern automatically;
- * * `pcre8` Use the squiloople.com pattern, requires PCRE > 8.0;
- * * `pcre` Use old PCRE implementation;
- * * `php` Use PHP built-in FILTER_VALIDATE_EMAIL;
- * * `html5` Use the pattern given by the HTML5 spec for 'email' type form input elements.
- * * `noregex` Don't use a regex: super fast, really dumb.
- * Alternatively you may pass in a callable to inject your own validator, for example:
- *
- * ```php
- * PHPMailer::validateAddress('user@example.com', function($address) {
- * return (strpos($address, '@') !== false);
- * });
- * ```
- *
- * You can also set the PHPMailer::$validator static to a callable, allowing built-in methods to use your validator.
- *
- * @param string $address The email address to check
- * @param string|callable $patternselect Which pattern to use
- *
- * @return bool
- */
- public static function validateAddress($address, $patternselect = null)
- {
- if (null === $patternselect) {
- $patternselect = static::$validator;
- }
- //Don't allow strings as callables, see SECURITY.md and CVE-2021-3603
- if (is_callable($patternselect) && !is_string($patternselect)) {
- return call_user_func($patternselect, $address);
- }
- //Reject line breaks in addresses; it's valid RFC5322, but not RFC5321
- if (strpos($address, "\n") !== false || strpos($address, "\r") !== false) {
- return false;
- }
- switch ($patternselect) {
- case 'pcre': //Kept for BC
- case 'pcre8':
- /*
- * A more complex and more permissive version of the RFC5322 regex on which FILTER_VALIDATE_EMAIL
- * is based.
- * In addition to the addresses allowed by filter_var, also permits:
- * * dotless domains: `a@b`
- * * comments: `1234 @ local(blah) .machine .example`
- * * quoted elements: `'"test blah"@example.org'`
- * * numeric TLDs: `a@b.123`
- * * unbracketed IPv4 literals: `a@192.168.0.1`
- * * IPv6 literals: 'first.last@[IPv6:a1::]'
- * Not all of these will necessarily work for sending!
- *
- * @copyright 2009-2010 Michael Rushton
- * Feel free to use and redistribute this code. But please keep this copyright notice.
- */
- return (bool) preg_match(
- '/^(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){255,})(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){65,}@)' .
- '((?>(?>(?>((?>(?>(?>\x0D\x0A)?[\t ])+|(?>[\t ]*\x0D\x0A)?[\t ]+)?)(\((?>(?2)' .
- '(?>[\x01-\x08\x0B\x0C\x0E-\'*-\[\]-\x7F]|\\\[\x00-\x7F]|(?3)))*(?2)\)))+(?2))|(?2))?)' .
- '([!#-\'*+\/-9=?^-~-]+|"(?>(?2)(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\x7F]))*' .
- '(?2)")(?>(?1)\.(?1)(?4))*(?1)@(?!(?1)[a-z0-9-]{64,})(?1)(?>([a-z0-9](?>[a-z0-9-]*[a-z0-9])?)' .
- '(?>(?1)\.(?!(?1)[a-z0-9-]{64,})(?1)(?5)){0,126}|\[(?:(?>IPv6:(?>([a-f0-9]{1,4})(?>:(?6)){7}' .
- '|(?!(?:.*[a-f0-9][:\]]){8,})((?6)(?>:(?6)){0,6})?::(?7)?))|(?>(?>IPv6:(?>(?6)(?>:(?6)){5}:' .
- '|(?!(?:.*[a-f0-9]:){6,})(?8)?::(?>((?6)(?>:(?6)){0,4}):)?))?(25[0-5]|2[0-4][0-9]|1[0-9]{2}' .
- '|[1-9]?[0-9])(?>\.(?9)){3}))\])(?1)$/isD',
- $address
- );
- case 'html5':
- /*
- * This is the pattern used in the HTML5 spec for validation of 'email' type form input elements.
- *
- * @see https://html.spec.whatwg.org/#e-mail-state-(type=email)
- */
- return (bool) preg_match(
- '/^[a-zA-Z0-9.!#$%&\'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}' .
- '[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/sD',
- $address
- );
- case 'php':
- default:
- return filter_var($address, FILTER_VALIDATE_EMAIL) !== false;
- }
- }
-
- /**
- * Tells whether IDNs (Internationalized Domain Names) are supported or not. This requires the
- * `intl` and `mbstring` PHP extensions.
- *
- * @return bool `true` if required functions for IDN support are present
- */
- public static function idnSupported()
- {
- return function_exists('idn_to_ascii') && function_exists('mb_convert_encoding');
- }
-
- /**
- * Converts IDN in given email address to its ASCII form, also known as punycode, if possible.
- * Important: Address must be passed in same encoding as currently set in PHPMailer::$CharSet.
- * This function silently returns unmodified address if:
- * - No conversion is necessary (i.e. domain name is not an IDN, or is already in ASCII form)
- * - Conversion to punycode is impossible (e.g. required PHP functions are not available)
- * or fails for any reason (e.g. domain contains characters not allowed in an IDN).
- *
- * @see PHPMailer::$CharSet
- *
- * @param string $address The email address to convert
- *
- * @return string The encoded address in ASCII form
- */
- public function punyencodeAddress($address)
- {
- //Verify we have required functions, CharSet, and at-sign.
- $pos = strrpos($address, '@');
- if (
- !empty($this->CharSet) &&
- false !== $pos &&
- static::idnSupported()
- ) {
- $domain = substr($address, ++$pos);
- //Verify CharSet string is a valid one, and domain properly encoded in this CharSet.
- if ($this->has8bitChars($domain) && @mb_check_encoding($domain, $this->CharSet)) {
- //Convert the domain from whatever charset it's in to UTF-8
- $domain = mb_convert_encoding($domain, self::CHARSET_UTF8, $this->CharSet);
- //Ignore IDE complaints about this line - method signature changed in PHP 5.4
- $errorcode = 0;
- if (defined('INTL_IDNA_VARIANT_UTS46')) {
- //Use the current punycode standard (appeared in PHP 7.2)
- $punycode = idn_to_ascii(
- $domain,
- \IDNA_DEFAULT | \IDNA_USE_STD3_RULES | \IDNA_CHECK_BIDI |
- \IDNA_CHECK_CONTEXTJ | \IDNA_NONTRANSITIONAL_TO_ASCII,
- \INTL_IDNA_VARIANT_UTS46
- );
- } elseif (defined('INTL_IDNA_VARIANT_2003')) {
- //Fall back to this old, deprecated/removed encoding
- $punycode = idn_to_ascii($domain, $errorcode, \INTL_IDNA_VARIANT_2003);
- } else {
- //Fall back to a default we don't know about
- $punycode = idn_to_ascii($domain, $errorcode);
- }
- if (false !== $punycode) {
- return substr($address, 0, $pos) . $punycode;
- }
- }
- }
-
- return $address;
- }
-
- /**
- * Create a message and send it.
- * Uses the sending method specified by $Mailer.
- *
- * @throws Exception
- *
- * @return bool false on error - See the ErrorInfo property for details of the error
- */
- public function send()
- {
- try {
- if (!$this->preSend()) {
- return false;
- }
-
- return $this->postSend();
- } catch (Exception $exc) {
- $this->mailHeader = '';
- $this->setError($exc->getMessage());
- if ($this->exceptions) {
- throw $exc;
- }
-
- return false;
- }
- }
-
- /**
- * Prepare a message for sending.
- *
- * @throws Exception
- *
- * @return bool
- */
- public function preSend()
- {
- if (
- 'smtp' === $this->Mailer
- || ('mail' === $this->Mailer && (\PHP_VERSION_ID >= 80000 || stripos(PHP_OS, 'WIN') === 0))
- ) {
- //SMTP mandates RFC-compliant line endings
- //and it's also used with mail() on Windows
- static::setLE(self::CRLF);
- } else {
- //Maintain backward compatibility with legacy Linux command line mailers
- static::setLE(PHP_EOL);
- }
- //Check for buggy PHP versions that add a header with an incorrect line break
- if (
- 'mail' === $this->Mailer
- && ((\PHP_VERSION_ID >= 70000 && \PHP_VERSION_ID < 70017)
- || (\PHP_VERSION_ID >= 70100 && \PHP_VERSION_ID < 70103))
- && ini_get('mail.add_x_header') === '1'
- && stripos(PHP_OS, 'WIN') === 0
- ) {
- trigger_error($this->lang('buggy_php'), E_USER_WARNING);
- }
-
- try {
- $this->error_count = 0; //Reset errors
- $this->mailHeader = '';
-
- //Dequeue recipient and Reply-To addresses with IDN
- foreach (array_merge($this->RecipientsQueue, $this->ReplyToQueue) as $params) {
- $params[1] = $this->punyencodeAddress($params[1]);
- call_user_func_array([$this, 'addAnAddress'], $params);
- }
- if (count($this->to) + count($this->cc) + count($this->bcc) < 1) {
- throw new Exception($this->lang('provide_address'), self::STOP_CRITICAL);
- }
-
- //Validate From, Sender, and ConfirmReadingTo addresses
- foreach (['From', 'Sender', 'ConfirmReadingTo'] as $address_kind) {
- if ($this->{$address_kind} === null) {
- $this->{$address_kind} = '';
- continue;
- }
- $this->{$address_kind} = trim($this->{$address_kind});
- if (empty($this->{$address_kind})) {
- continue;
- }
- $this->{$address_kind} = $this->punyencodeAddress($this->{$address_kind});
- if (!static::validateAddress($this->{$address_kind})) {
- $error_message = sprintf(
- '%s (%s): %s',
- $this->lang('invalid_address'),
- $address_kind,
- $this->{$address_kind}
- );
- $this->setError($error_message);
- $this->edebug($error_message);
- if ($this->exceptions) {
- throw new Exception($error_message);
- }
-
- return false;
- }
- }
-
- //Set whether the message is multipart/alternative
- if ($this->alternativeExists()) {
- $this->ContentType = static::CONTENT_TYPE_MULTIPART_ALTERNATIVE;
- }
-
- $this->setMessageType();
- //Refuse to send an empty message unless we are specifically allowing it
- if (!$this->AllowEmpty && empty($this->Body)) {
- throw new Exception($this->lang('empty_message'), self::STOP_CRITICAL);
- }
-
- //Trim subject consistently
- $this->Subject = trim($this->Subject);
- //Create body before headers in case body makes changes to headers (e.g. altering transfer encoding)
- $this->MIMEHeader = '';
- $this->MIMEBody = $this->createBody();
- //createBody may have added some headers, so retain them
- $tempheaders = $this->MIMEHeader;
- $this->MIMEHeader = $this->createHeader();
- $this->MIMEHeader .= $tempheaders;
-
- //To capture the complete message when using mail(), create
- //an extra header list which createHeader() doesn't fold in
- if ('mail' === $this->Mailer) {
- if (count($this->to) > 0) {
- $this->mailHeader .= $this->addrAppend('To', $this->to);
- } else {
- $this->mailHeader .= $this->headerLine('To', 'undisclosed-recipients:;');
- }
- $this->mailHeader .= $this->headerLine(
- 'Subject',
- $this->encodeHeader($this->secureHeader($this->Subject))
- );
- }
-
- //Sign with DKIM if enabled
- if (
- !empty($this->DKIM_domain)
- && !empty($this->DKIM_selector)
- && (!empty($this->DKIM_private_string)
- || (!empty($this->DKIM_private)
- && static::isPermittedPath($this->DKIM_private)
- && file_exists($this->DKIM_private)
- )
- )
- ) {
- $header_dkim = $this->DKIM_Add(
- $this->MIMEHeader . $this->mailHeader,
- $this->encodeHeader($this->secureHeader($this->Subject)),
- $this->MIMEBody
- );
- $this->MIMEHeader = static::stripTrailingWSP($this->MIMEHeader) . static::$LE .
- static::normalizeBreaks($header_dkim) . static::$LE;
- }
-
- return true;
- } catch (Exception $exc) {
- $this->setError($exc->getMessage());
- if ($this->exceptions) {
- throw $exc;
- }
-
- return false;
- }
- }
-
- /**
- * Actually send a message via the selected mechanism.
- *
- * @throws Exception
- *
- * @return bool
- */
- public function postSend()
- {
- try {
- //Choose the mailer and send through it
- switch ($this->Mailer) {
- case 'sendmail':
- case 'qmail':
- return $this->sendmailSend($this->MIMEHeader, $this->MIMEBody);
- case 'smtp':
- return $this->smtpSend($this->MIMEHeader, $this->MIMEBody);
- case 'mail':
- return $this->mailSend($this->MIMEHeader, $this->MIMEBody);
- default:
- $sendMethod = $this->Mailer . 'Send';
- if (method_exists($this, $sendMethod)) {
- return $this->{$sendMethod}($this->MIMEHeader, $this->MIMEBody);
- }
-
- return $this->mailSend($this->MIMEHeader, $this->MIMEBody);
- }
- } catch (Exception $exc) {
- $this->setError($exc->getMessage());
- $this->edebug($exc->getMessage());
- if ($this->Mailer === 'smtp' && $this->SMTPKeepAlive == true && $this->smtp->connected()) {
- $this->smtp->reset();
- }
- if ($this->exceptions) {
- throw $exc;
- }
- }
-
- return false;
- }
-
- /**
- * Send mail using the $Sendmail program.
- *
- * @see PHPMailer::$Sendmail
- *
- * @param string $header The message headers
- * @param string $body The message body
- *
- * @throws Exception
- *
- * @return bool
- */
- protected function sendmailSend($header, $body)
- {
- if ($this->Mailer === 'qmail') {
- $this->edebug('Sending with qmail');
- } else {
- $this->edebug('Sending with sendmail');
- }
- $header = static::stripTrailingWSP($header) . static::$LE . static::$LE;
- //This sets the SMTP envelope sender which gets turned into a return-path header by the receiver
- //A space after `-f` is optional, but there is a long history of its presence
- //causing problems, so we don't use one
- //Exim docs: https://www.exim.org/exim-html-current/doc/html/spec_html/ch-the_exim_command_line.html
- //Sendmail docs: https://www.sendmail.org/~ca/email/man/sendmail.html
- //Example problem: https://www.drupal.org/node/1057954
-
- //PHP 5.6 workaround
- $sendmail_from_value = ini_get('sendmail_from');
- if (empty($this->Sender) && !empty($sendmail_from_value)) {
- //PHP config has a sender address we can use
- $this->Sender = ini_get('sendmail_from');
- }
- //CVE-2016-10033, CVE-2016-10045: Don't pass -f if characters will be escaped.
- if (!empty($this->Sender) && static::validateAddress($this->Sender) && self::isShellSafe($this->Sender)) {
- if ($this->Mailer === 'qmail') {
- $sendmailFmt = '%s -f%s';
- } else {
- $sendmailFmt = '%s -oi -f%s -t';
- }
- } else {
- //allow sendmail to choose a default envelope sender. It may
- //seem preferable to force it to use the From header as with
- //SMTP, but that introduces new problems (see
- //), and
- //it has historically worked this way.
- $sendmailFmt = '%s -oi -t';
- }
-
- $sendmail = sprintf($sendmailFmt, escapeshellcmd($this->Sendmail), $this->Sender);
- $this->edebug('Sendmail path: ' . $this->Sendmail);
- $this->edebug('Sendmail command: ' . $sendmail);
- $this->edebug('Envelope sender: ' . $this->Sender);
- $this->edebug("Headers: {$header}");
-
- if ($this->SingleTo) {
- foreach ($this->SingleToArray as $toAddr) {
- $mail = @popen($sendmail, 'w');
- if (!$mail) {
- throw new Exception($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
- }
- $this->edebug("To: {$toAddr}");
- fwrite($mail, 'To: ' . $toAddr . "\n");
- fwrite($mail, $header);
- fwrite($mail, $body);
- $result = pclose($mail);
- $addrinfo = static::parseAddresses($toAddr, true, $this->CharSet);
- $this->doCallback(
- ($result === 0),
- [[$addrinfo['address'], $addrinfo['name']]],
- $this->cc,
- $this->bcc,
- $this->Subject,
- $body,
- $this->From,
- []
- );
- $this->edebug("Result: " . ($result === 0 ? 'true' : 'false'));
- if (0 !== $result) {
- throw new Exception($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
- }
- }
- } else {
- $mail = @popen($sendmail, 'w');
- if (!$mail) {
- throw new Exception($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
- }
- fwrite($mail, $header);
- fwrite($mail, $body);
- $result = pclose($mail);
- $this->doCallback(
- ($result === 0),
- $this->to,
- $this->cc,
- $this->bcc,
- $this->Subject,
- $body,
- $this->From,
- []
- );
- $this->edebug("Result: " . ($result === 0 ? 'true' : 'false'));
- if (0 !== $result) {
- throw new Exception($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
- }
- }
-
- return true;
- }
-
- /**
- * Fix CVE-2016-10033 and CVE-2016-10045 by disallowing potentially unsafe shell characters.
- * Note that escapeshellarg and escapeshellcmd are inadequate for our purposes, especially on Windows.
- *
- * @see https://github.com/PHPMailer/PHPMailer/issues/924 CVE-2016-10045 bug report
- *
- * @param string $string The string to be validated
- *
- * @return bool
- */
- protected static function isShellSafe($string)
- {
- //It's not possible to use shell commands safely (which includes the mail() function) without escapeshellarg,
- //but some hosting providers disable it, creating a security problem that we don't want to have to deal with,
- //so we don't.
- if (!function_exists('escapeshellarg') || !function_exists('escapeshellcmd')) {
- return false;
- }
-
- if (
- escapeshellcmd($string) !== $string
- || !in_array(escapeshellarg($string), ["'$string'", "\"$string\""])
- ) {
- return false;
- }
-
- $length = strlen($string);
-
- for ($i = 0; $i < $length; ++$i) {
- $c = $string[$i];
-
- //All other characters have a special meaning in at least one common shell, including = and +.
- //Full stop (.) has a special meaning in cmd.exe, but its impact should be negligible here.
- //Note that this does permit non-Latin alphanumeric characters based on the current locale.
- if (!ctype_alnum($c) && strpos('@_-.', $c) === false) {
- return false;
- }
- }
-
- return true;
- }
-
- /**
- * Check whether a file path is of a permitted type.
- * Used to reject URLs and phar files from functions that access local file paths,
- * such as addAttachment.
- *
- * @param string $path A relative or absolute path to a file
- *
- * @return bool
- */
- protected static function isPermittedPath($path)
- {
- //Matches scheme definition from https://tools.ietf.org/html/rfc3986#section-3.1
- return !preg_match('#^[a-z][a-z\d+.-]*://#i', $path);
- }
-
- /**
- * Check whether a file path is safe, accessible, and readable.
- *
- * @param string $path A relative or absolute path to a file
- *
- * @return bool
- */
- protected static function fileIsAccessible($path)
- {
- if (!static::isPermittedPath($path)) {
- return false;
- }
- $readable = is_file($path);
- //If not a UNC path (expected to start with \\), check read permission, see #2069
- if (strpos($path, '\\\\') !== 0) {
- $readable = $readable && is_readable($path);
- }
- return $readable;
- }
-
- /**
- * Send mail using the PHP mail() function.
- *
- * @see https://www.php.net/manual/en/book.mail.php
- *
- * @param string $header The message headers
- * @param string $body The message body
- *
- * @throws Exception
- *
- * @return bool
- */
- protected function mailSend($header, $body)
- {
- $header = static::stripTrailingWSP($header) . static::$LE . static::$LE;
-
- $toArr = [];
- foreach ($this->to as $toaddr) {
- $toArr[] = $this->addrFormat($toaddr);
- }
- $to = trim(implode(', ', $toArr));
-
- //If there are no To-addresses (e.g. when sending only to BCC-addresses)
- //the following should be added to get a correct DKIM-signature.
- //Compare with $this->preSend()
- if ($to === '') {
- $to = 'undisclosed-recipients:;';
- }
-
- $params = null;
- //This sets the SMTP envelope sender which gets turned into a return-path header by the receiver
- //A space after `-f` is optional, but there is a long history of its presence
- //causing problems, so we don't use one
- //Exim docs: https://www.exim.org/exim-html-current/doc/html/spec_html/ch-the_exim_command_line.html
- //Sendmail docs: https://www.sendmail.org/~ca/email/man/sendmail.html
- //Example problem: https://www.drupal.org/node/1057954
- //CVE-2016-10033, CVE-2016-10045: Don't pass -f if characters will be escaped.
-
- //PHP 5.6 workaround
- $sendmail_from_value = ini_get('sendmail_from');
- if (empty($this->Sender) && !empty($sendmail_from_value)) {
- //PHP config has a sender address we can use
- $this->Sender = ini_get('sendmail_from');
- }
- if (!empty($this->Sender) && static::validateAddress($this->Sender)) {
- if (self::isShellSafe($this->Sender)) {
- $params = sprintf('-f%s', $this->Sender);
- }
- $old_from = ini_get('sendmail_from');
- ini_set('sendmail_from', $this->Sender);
- }
- $result = false;
- if ($this->SingleTo && count($toArr) > 1) {
- foreach ($toArr as $toAddr) {
- $result = $this->mailPassthru($toAddr, $this->Subject, $body, $header, $params);
- $addrinfo = static::parseAddresses($toAddr, true, $this->CharSet);
- $this->doCallback(
- $result,
- [[$addrinfo['address'], $addrinfo['name']]],
- $this->cc,
- $this->bcc,
- $this->Subject,
- $body,
- $this->From,
- []
- );
- }
- } else {
- $result = $this->mailPassthru($to, $this->Subject, $body, $header, $params);
- $this->doCallback($result, $this->to, $this->cc, $this->bcc, $this->Subject, $body, $this->From, []);
- }
- if (isset($old_from)) {
- ini_set('sendmail_from', $old_from);
- }
- if (!$result) {
- throw new Exception($this->lang('instantiate'), self::STOP_CRITICAL);
- }
-
- return true;
- }
-
- /**
- * Get an instance to use for SMTP operations.
- * Override this function to load your own SMTP implementation,
- * or set one with setSMTPInstance.
- *
- * @return SMTP
- */
- public function getSMTPInstance()
- {
- if (!is_object($this->smtp)) {
- $this->smtp = new SMTP();
- }
-
- return $this->smtp;
- }
-
- /**
- * Provide an instance to use for SMTP operations.
- *
- * @return SMTP
- */
- public function setSMTPInstance(SMTP $smtp)
- {
- $this->smtp = $smtp;
-
- return $this->smtp;
- }
-
- /**
- * Provide SMTP XCLIENT attributes
- *
- * @param string $name Attribute name
- * @param ?string $value Attribute value
- *
- * @return bool
- */
- public function setSMTPXclientAttribute($name, $value)
- {
- if (!in_array($name, SMTP::$xclient_allowed_attributes)) {
- return false;
- }
- if (isset($this->SMTPXClient[$name]) && $value === null) {
- unset($this->SMTPXClient[$name]);
- } elseif ($value !== null) {
- $this->SMTPXClient[$name] = $value;
- }
-
- return true;
- }
-
- /**
- * Get SMTP XCLIENT attributes
- *
- * @return array
- */
- public function getSMTPXclientAttributes()
- {
- return $this->SMTPXClient;
- }
-
- /**
- * Send mail via SMTP.
- * Returns false if there is a bad MAIL FROM, RCPT, or DATA input.
- *
- * @see PHPMailer::setSMTPInstance() to use a different class.
- *
- * @uses \PHPMailer\PHPMailer\SMTP
- *
- * @param string $header The message headers
- * @param string $body The message body
- *
- * @throws Exception
- *
- * @return bool
- */
- protected function smtpSend($header, $body)
- {
- $header = static::stripTrailingWSP($header) . static::$LE . static::$LE;
- $bad_rcpt = [];
- if (!$this->smtpConnect($this->SMTPOptions)) {
- throw new Exception($this->lang('smtp_connect_failed'), self::STOP_CRITICAL);
- }
- //Sender already validated in preSend()
- if ('' === $this->Sender) {
- $smtp_from = $this->From;
- } else {
- $smtp_from = $this->Sender;
- }
- if (count($this->SMTPXClient)) {
- $this->smtp->xclient($this->SMTPXClient);
- }
- if (!$this->smtp->mail($smtp_from)) {
- $this->setError($this->lang('from_failed') . $smtp_from . ' : ' . implode(',', $this->smtp->getError()));
- throw new Exception($this->ErrorInfo, self::STOP_CRITICAL);
- }
-
- $callbacks = [];
- //Attempt to send to all recipients
- foreach ([$this->to, $this->cc, $this->bcc] as $togroup) {
- foreach ($togroup as $to) {
- if (!$this->smtp->recipient($to[0], $this->dsn)) {
- $error = $this->smtp->getError();
- $bad_rcpt[] = ['to' => $to[0], 'error' => $error['detail']];
- $isSent = false;
- } else {
- $isSent = true;
- }
-
- $callbacks[] = ['issent' => $isSent, 'to' => $to[0], 'name' => $to[1]];
- }
- }
-
- //Only send the DATA command if we have viable recipients
- if ((count($this->all_recipients) > count($bad_rcpt)) && !$this->smtp->data($header . $body)) {
- throw new Exception($this->lang('data_not_accepted'), self::STOP_CRITICAL);
- }
-
- $smtp_transaction_id = $this->smtp->getLastTransactionID();
-
- if ($this->SMTPKeepAlive) {
- $this->smtp->reset();
- } else {
- $this->smtp->quit();
- $this->smtp->close();
- }
-
- foreach ($callbacks as $cb) {
- $this->doCallback(
- $cb['issent'],
- [[$cb['to'], $cb['name']]],
- [],
- [],
- $this->Subject,
- $body,
- $this->From,
- ['smtp_transaction_id' => $smtp_transaction_id]
- );
- }
-
- //Create error message for any bad addresses
- if (count($bad_rcpt) > 0) {
- $errstr = '';
- foreach ($bad_rcpt as $bad) {
- $errstr .= $bad['to'] . ': ' . $bad['error'];
- }
- throw new Exception($this->lang('recipients_failed') . $errstr, self::STOP_CONTINUE);
- }
-
- return true;
- }
-
- /**
- * Initiate a connection to an SMTP server.
- * Returns false if the operation failed.
- *
- * @param array $options An array of options compatible with stream_context_create()
- *
- * @throws Exception
- *
- * @uses \PHPMailer\PHPMailer\SMTP
- *
- * @return bool
- */
- public function smtpConnect($options = null)
- {
- if (null === $this->smtp) {
- $this->smtp = $this->getSMTPInstance();
- }
-
- //If no options are provided, use whatever is set in the instance
- if (null === $options) {
- $options = $this->SMTPOptions;
- }
-
- //Already connected?
- if ($this->smtp->connected()) {
- return true;
- }
-
- $this->smtp->setTimeout($this->Timeout);
- $this->smtp->setDebugLevel($this->SMTPDebug);
- $this->smtp->setDebugOutput($this->Debugoutput);
- $this->smtp->setVerp($this->do_verp);
- if ($this->Host === null) {
- $this->Host = 'localhost';
- }
- $hosts = explode(';', $this->Host);
- $lastexception = null;
-
- foreach ($hosts as $hostentry) {
- $hostinfo = [];
- if (
- !preg_match(
- '/^(?:(ssl|tls):\/\/)?(.+?)(?::(\d+))?$/',
- trim($hostentry),
- $hostinfo
- )
- ) {
- $this->edebug($this->lang('invalid_hostentry') . ' ' . trim($hostentry));
- //Not a valid host entry
- continue;
- }
- //$hostinfo[1]: optional ssl or tls prefix
- //$hostinfo[2]: the hostname
- //$hostinfo[3]: optional port number
- //The host string prefix can temporarily override the current setting for SMTPSecure
- //If it's not specified, the default value is used
-
- //Check the host name is a valid name or IP address before trying to use it
- if (!static::isValidHost($hostinfo[2])) {
- $this->edebug($this->lang('invalid_host') . ' ' . $hostinfo[2]);
- continue;
- }
- $prefix = '';
- $secure = $this->SMTPSecure;
- $tls = (static::ENCRYPTION_STARTTLS === $this->SMTPSecure);
- if ('ssl' === $hostinfo[1] || ('' === $hostinfo[1] && static::ENCRYPTION_SMTPS === $this->SMTPSecure)) {
- $prefix = 'ssl://';
- $tls = false; //Can't have SSL and TLS at the same time
- $secure = static::ENCRYPTION_SMTPS;
- } elseif ('tls' === $hostinfo[1]) {
- $tls = true;
- //TLS doesn't use a prefix
- $secure = static::ENCRYPTION_STARTTLS;
- }
- //Do we need the OpenSSL extension?
- $sslext = defined('OPENSSL_ALGO_SHA256');
- if (static::ENCRYPTION_STARTTLS === $secure || static::ENCRYPTION_SMTPS === $secure) {
- //Check for an OpenSSL constant rather than using extension_loaded, which is sometimes disabled
- if (!$sslext) {
- throw new Exception($this->lang('extension_missing') . 'openssl', self::STOP_CRITICAL);
- }
- }
- $host = $hostinfo[2];
- $port = $this->Port;
- if (
- array_key_exists(3, $hostinfo) &&
- is_numeric($hostinfo[3]) &&
- $hostinfo[3] > 0 &&
- $hostinfo[3] < 65536
- ) {
- $port = (int) $hostinfo[3];
- }
- if ($this->smtp->connect($prefix . $host, $port, $this->Timeout, $options)) {
- try {
- if ($this->Helo) {
- $hello = $this->Helo;
- } else {
- $hello = $this->serverHostname();
- }
- $this->smtp->hello($hello);
- //Automatically enable TLS encryption if:
- //* it's not disabled
- //* we are not connecting to localhost
- //* we have openssl extension
- //* we are not already using SSL
- //* the server offers STARTTLS
- if (
- $this->SMTPAutoTLS &&
- $this->Host !== 'localhost' &&
- $sslext &&
- $secure !== 'ssl' &&
- $this->smtp->getServerExt('STARTTLS')
- ) {
- $tls = true;
- }
- if ($tls) {
- if (!$this->smtp->startTLS()) {
- $message = $this->getSmtpErrorMessage('connect_host');
- throw new Exception($message);
- }
- //We must resend EHLO after TLS negotiation
- $this->smtp->hello($hello);
- }
- if (
- $this->SMTPAuth && !$this->smtp->authenticate(
- $this->Username,
- $this->Password,
- $this->AuthType,
- $this->oauth
- )
- ) {
- throw new Exception($this->lang('authenticate'));
- }
-
- return true;
- } catch (Exception $exc) {
- $lastexception = $exc;
- $this->edebug($exc->getMessage());
- //We must have connected, but then failed TLS or Auth, so close connection nicely
- $this->smtp->quit();
- }
- }
- }
- //If we get here, all connection attempts have failed, so close connection hard
- $this->smtp->close();
- //As we've caught all exceptions, just report whatever the last one was
- if ($this->exceptions && null !== $lastexception) {
- throw $lastexception;
- }
- if ($this->exceptions) {
- // no exception was thrown, likely $this->smtp->connect() failed
- $message = $this->getSmtpErrorMessage('connect_host');
- throw new Exception($message);
- }
-
- return false;
- }
-
- /**
- * Close the active SMTP session if one exists.
- */
- public function smtpClose()
- {
- if ((null !== $this->smtp) && $this->smtp->connected()) {
- $this->smtp->quit();
- $this->smtp->close();
- }
- }
-
- /**
- * Set the language for error messages.
- * The default language is English.
- *
- * @param string $langcode ISO 639-1 2-character language code (e.g. French is "fr")
- * Optionally, the language code can be enhanced with a 4-character
- * script annotation and/or a 2-character country annotation.
- * @param string $lang_path Path to the language file directory, with trailing separator (slash)
- * Do not set this from user input!
- *
- * @return bool Returns true if the requested language was loaded, false otherwise.
- */
- public function setLanguage($langcode = 'en', $lang_path = '')
- {
- //Backwards compatibility for renamed language codes
- $renamed_langcodes = [
- 'br' => 'pt_br',
- 'cz' => 'cs',
- 'dk' => 'da',
- 'no' => 'nb',
- 'se' => 'sv',
- 'rs' => 'sr',
- 'tg' => 'tl',
- 'am' => 'hy',
- ];
-
- if (array_key_exists($langcode, $renamed_langcodes)) {
- $langcode = $renamed_langcodes[$langcode];
- }
-
- //Define full set of translatable strings in English
- $PHPMAILER_LANG = [
- 'authenticate' => 'SMTP Error: Could not authenticate.',
- 'buggy_php' => 'Your version of PHP is affected by a bug that may result in corrupted messages.' .
- ' To fix it, switch to sending using SMTP, disable the mail.add_x_header option in' .
- ' your php.ini, switch to MacOS or Linux, or upgrade your PHP to version 7.0.17+ or 7.1.3+.',
- 'connect_host' => 'SMTP Error: Could not connect to SMTP host.',
- 'data_not_accepted' => 'SMTP Error: data not accepted.',
- 'empty_message' => 'Message body empty',
- 'encoding' => 'Unknown encoding: ',
- 'execute' => 'Could not execute: ',
- 'extension_missing' => 'Extension missing: ',
- 'file_access' => 'Could not access file: ',
- 'file_open' => 'File Error: Could not open file: ',
- 'from_failed' => 'The following From address failed: ',
- 'instantiate' => 'Could not instantiate mail function.',
- 'invalid_address' => 'Invalid address: ',
- 'invalid_header' => 'Invalid header name or value',
- 'invalid_hostentry' => 'Invalid hostentry: ',
- 'invalid_host' => 'Invalid host: ',
- 'mailer_not_supported' => ' mailer is not supported.',
- 'provide_address' => 'You must provide at least one recipient email address.',
- 'recipients_failed' => 'SMTP Error: The following recipients failed: ',
- 'signing' => 'Signing Error: ',
- 'smtp_code' => 'SMTP code: ',
- 'smtp_code_ex' => 'Additional SMTP info: ',
- 'smtp_connect_failed' => 'SMTP connect() failed.',
- 'smtp_detail' => 'Detail: ',
- 'smtp_error' => 'SMTP server error: ',
- 'variable_set' => 'Cannot set or reset variable: ',
- ];
- if (empty($lang_path)) {
- //Calculate an absolute path so it can work if CWD is not here
- $lang_path = dirname(__DIR__) . DIRECTORY_SEPARATOR . 'language' . DIRECTORY_SEPARATOR;
- }
-
- //Validate $langcode
- $foundlang = true;
- $langcode = strtolower($langcode);
- if (
- !preg_match('/^(?P[a-z]{2})(?P
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-