Archiv

Artikel Tagged ‘PHP’

File Thingie – Syntax-Highlighting mit Ace-Editor

20. März 2017 Keine Kommentare

Als webbasierter Dateimanager kommt bei mir nach wie vor aufgrund seiner Einfachheit bevorzugt File Thingie zum Einsatz (Download Version 2.5.7). Diesen nutze ich auch gerne, um mal kurz was am Code bestimmter Dateien zu ändern, wenn ich grade keinen FTP-Zugang zum Server habe. Aber leider besteht der Standard-Editor nur aus einem Textfeld, und die im vorigen Beitrag angesprochenen Editor-Plugins wollte ich nicht nutzen, da ich WYSIWYG-Editoren nicht mag und für Code auch gar nicht gebrauchen kann.

Mit Ace gibt es aber auch einen reinen Code-Editor mit sehr gutem Funktionsumfang wie Syntax Highlighting für mehr als 110 Sprachen, verschiedene Themes sowie jede Menge weiterer Anpassungsmöglichkeiten. Dieser muss allerdings erst in File Thingie integriert werden. Nachfolgend möchte ich die dafür nötigen Änderungen aufzeigen.

Anforderungen
– Alle in File Thingie zur Bearbeitung freigegebenen Dateitypen sollen mit Ace dargestellt werden.
– Es soll je nach geöffneter Datei die korrekte Sprache für Syntax Highlighting geladen werden.
– Möglichst wenig Änderungen an der Funktionsweise von File Thingie selbst

Umsetzung
Zuerst müssen in der config.php die Dateitypen festgelegt werden, welche mit File Thingie bearbeitet werden sollen. Dafür sind an 2 Stellen Anpassungen erforderlich:

$ft["settings"]["FILETYPEBLACKLIST"] = ""; // File types that are not allowed for upload.

Nicht vom Kommentar irritieren lassen, diese Option gilt nicht nur für den Upload, sondern die hier eingegebenen Dateitypen werden generell nicht angezeigt.

$ft["plugins"]["edit"] = array(
  "settings" => array(
    "editlist" => "txt html htm css php js xml",
    "converttabs" => FALSE
  )
);

Danach geht es weiter mit der Datei edit.plugin.php im plugins-Verzeichnis. Der Editor in File Thingie ist eine einfache textarea. Diese kann von Ace aber nicht direkt verarbeitet werden. Ace ist für die Nutzung mit Containern wie div oder pre ausgelegt. Daher ist es erforderlich, ein neues div anzulegen.

In dieser Datei ist zusätzlich noch die Ermittlung des Dateityp erforderlich. Dazu wird ein zusätzliches verstecktes Eingabefeld angelegt, in welchem nur die Dateiendung der aktuell geladenen Datei gespeichert wird.

// Make form or show lock message.
$split_file = explode(".",$_REQUEST['file']);
$file_ext = $split_file[sizeof($split_file)-1];
$str .= '<form id="edit" action="'.ft_get_self().'" method="post">
  <div>
    <textarea cols="76" rows="20" name="filecontent" id="filecontent">'.$filecontent.'</textarea>
    <div name="ace_editor" id="ace_editor">'.$filecontent.'</div>
  </div>
  <div>
    <input type="hidden" name="file_ext" id="file_ext" value="'.strtolower($file_ext).'"</>
    <input type="hidden" name="file" id="file" value="'.$_REQUEST['file'].'" />
    <input type="hidden" name="dir" id="dir" value="'.$_REQUEST['dir'].'" />
    <input type="hidden" name="act" value="savefile" />
    <button type="button" id="save">'.t('Save').'</button>
    <input type="submit" value="'.t('Save &amp; exit').'" name="submit" />
    <input type="submit" value="'.t('Cancel').'" name="submit" />
    <input type="checkbox" name="convertspaces" id="convertspaces"'.($ft['plugins']['edit']['settings']['converttabs'] == TRUE ? ' checked="checked"' : '').' /> <label for="convertspaces">'.t('Convert spaces to tabs').'</label>
    <div id="savestatus"></div>
  </div>
</form>';				  

Zu guter Letzt muss in der Datei ft2.php der Ace-Editor eingebunden, aktiviert und der Inhalt des neuen Editor-div in die „alte“ textarea übertragen werden, damit die Änderungen auch gespeichert werden. Die textarea selbst wird ausgeblendet, damit nicht zwei Eingabebereiche ausgegeben werden. Zusätzlich wird geprüft, um welchen Dateityp es sich handelt, um die Syntax Highlighting Regeln für die entsprechende Sprache zu laden.

	<style type="text/css">
	  @import "css/ft.css";
    <?php echo implode("\r\n", ft_invoke_hook('add_css'));?>
	</style>
    <style type="text/css" media="screen">
      .ace_editor {
        position: relative !important;
        border: 1px solid lightgray;
        margin: auto;
        height: 600px;
        width: 800px;
      }
    </style>
    </head>
<body>

	<?php echo $str;?>
  <?php echo ft_make_scripts_footer();?>
  <?php echo implode("\r\n", ft_invoke_hook('destroy'));?>
<script src="./js/ace-builds/src/ace.js" type="text/javascript" charset="utf-8"></script>
<script>
  var editor = ace.edit("ace_editor");
  editor.setTheme("ace/theme/twilight");
  var file_ext = document.getElementById("file_ext").value;
  switch(file_ext) {
    case "php":
      editor.session.setMode("ace/mode/php");
      break;
    case "js":
      editor.session.setMode("ace/mode/javascript");
      break;
    case "htm":
    case "html":
      editor.session.setMode("ace/mode/html");
      break;
    case "css":
      editor.session.setMode("ace/mode/css");
      break;
    case "xml":
      editor.session.setMode("ace/mode/xml");
      break;
    default:
      editor.session.setMode("ace/mode/text");
  }
  var textarea = $('textarea[name="filecontent"]').hide();
  editor.getSession().setValue(textarea.val());
  editor.getSession().on('change', function(){
    textarea.val(editor.getSession().getValue());
  });
  editor.setPrintMarginColumn(false);
  </script>
</body>
</html>

Die erforderlichen Dateien für Ace kann man von der Webseite beziehen und beispielsweise im Unterverzeichnis js ablegen (wie im Code dargestellt). Möchte man weitere Dateitypen zur Bearbeitung freigeben, müssen die neuen Endungen wieder in der config.php freigegeben und in der ft2.php als neuer case ergänzt werden.

MoWeS Portable startet nicht unter Windows 10 Version 1607

15. Oktober 2016 Keine Kommentare

Habe zum Ende der kostenlosen Wechselphase noch schnell das Upgrade von Windows 7 auf Windows 10 durchgeführt. Kurz darauf folgte dann auch das Anniversary Update (Version 1607).

Nun wollte ich mal wieder MoWeS starten, da ich es trotz veralteter Apache und PHP Version dennoch gerne als schnell verfügbares Testsystem für einige Sachen nutze.

Nun musste ich leider feststellen, dass der Apache Dienst nicht mehr startet.

MoWeS-Status

Nach ein wenig Recherche war der Grund schnell gefunden: der WWW-Publishingdienst ist in Windows 10 standardmäßig aktiviert und blockiert den Port 80. Somit kann Apache in der Default-Konfiguration nicht starten.

Vorübergehend Abhilfe kann man sich über die Konsole verschaffen. CMD mit Admin-Rechten starten und folgendes eingeben:

net stop w3svc

Anschließend MoWeS bzw. die Server neu starten. Nun sollte alles wieder laufen.

Dies hilft aber nur temporär. Nach dem nächsten Neustart von Windows ist der WWW-Publishingdienst wieder aktiviert. Wer ihn dauerhaft abschalten möchte, muss den Dienst deaktivieren. Dazu gibt man in der Windows Suche bzw. Cortana das Wort Dienste ein und sollte eine passende Desktop-App finden. Diese öffnen und nach dem Eintrag WWW-Publishingdienst suchen. Mit der rechten Maustaste in die Eigenschaften wechseln und dort den Dienst von Starttyp Automatisch auf Deaktiviert ändern.

WWW-Dienst

Nach dem nächsten Neustart von Windows bleibt der Dienst abgeschaltet und man kann sofort mit MoWeS oder anderen WAMP-Installationen loslegen.

WordPress Fehlermeldungen nach Update auf Version 4.6

21. August 2016 Keine Kommentare

Grade das neue Update auf WordPress Version 4.6 installiert und feststellen müssen, dass anschließend Fehler-/Warnmeldungen auf der Seite und im Admin-Panel angezeigt werden. In der wp-config.ini nachgesehen, ob hier falsche Einstellungen vorliegen, aber daran lag es schonmal nicht:

@ini_set('display_errors', 0);
define('WP_DEBUG', false);

Nach etwas Suchen bin ich dann aber auf WordPress.org fündig geworden. Im Ticket #37680 wurde der Fehler erfasst und auch ein funktionierender Workaround veröffentlicht.

Nach den vorgeschlagenen Änderungen an der Datei load.php ist das Problem behoben. Mit dem nächsten Update auf 4.6.1 soll der Wordaround auch offiziell verteilt werden, aber bis dahin kann es noch ein paar Tage dauern.

Alternativ kann man auf seinem Server auch in der php.ini die Nutzung von ini_get_all() aktivieren, sofern man die Möglichkeit hat. Hier auf Pytal kann man die Einstellungen nicht eigenständig ändern, sondern ist auf den Serverbetreiber angewiesen.

MoWeS Portable II Installationspakete

4. März 2013 9 Kommentare

MoWes Portable II ist für mich schon lange eine unverzichtbare portable Softwareperle auf meinem USB-Stick. Der zuverlässige Webserver to go hat mich noch nie im Stich gelassen, ganz im Gegensatz zu seinem hoch gelobten Verwanten XAMPP, welcher zwar auch als Portable Edition zu haben ist, mir aber in der Vergangenheit mehr Ärger bereitete als Nutzen brachte.

Mit Bedauern musste ich vor einigen Monaten dann feststellen, dass die Firma hinter MoWeS ohne Vorankündigung ihre Geschäftstätigkeit eingestellt hat und im selben Zuge auch die Webseite offline genommen wurde. Somit war kein rankommen an die Installationspakete mehr möglich. Hätte man das vorher bekannt gegeben, ich hätte mir noch schnell eine Sicherung der aktuellsten Pakete gemacht.

Heute hatte ich mal ein wenig Zeit und Lust, mich auf die Suche nach einer dezentralen Sicherungskopie zu begeben und wurde schnell bei Softpedia fündig. Dort gibt es aber „nur“ die Serverkomponenten, die vorgefertigten Softwarepakete haben sie nicht im Angebot, was aber nicht weiter tragisch ist, die kann man schließlich selbst installieren.

Falls jemand nur einzelne Pakete benötigt, habe ich mal alles bei uploaded.to hochgeladen. Enthalten sind die folgenden Pakete:

  • MoWeS Portable II (Version 2.2.3)
  • Apache 2 (Version 2.2.11) + SE
  • MySQL 5 (Version 5.5.8) + SE
  • ImageMagick (Version 4.2.9)
  • PHP 4 (Version 4.4.9) + SE
  • PHP 5 (Version 5.3.5) + SE
  • PHP 5.2 (Version 5.2.17)

mowes_portable.zip ist ein Pflichtdownload und muss nur entpackt werden. Die anderen Pakete werden im Stammverzeichnis von MoWeS gespeichert und anschließend das Programm gestartet. Es beginnt mit der Einrichtung, installiert die einzelnen Pakete und startet anschließend den portablen Server. Fertig 🙂

Ich hoffe, der Download hilft dem einen oder anderen Fan von MoWeS.

 
Update 06.01.2015

Da Uploaded nun wirklich nicht die beste Wahl war, hier noch eine zusätzliche Download-Quelle: Google Drive. Zwar auch nicht optimal, aber zumindest schneller und keine Mengen- bzw Zeitbegrenzung.

Es sind auch ein paar Pakete dazu gekommen, für weitere Infos einfach mal dem Link folgen.

File Thingie – Ein web-basierter Dateimanager auf PHP-Basis

4. Januar 2013 2 Kommentare

Es kann sehr störend sein, wenn man nicht jederzeit via FTP auf seinen Webspace zugreifen kann. Tagsüber sitze ich hinter einem Proxy, der nur HTTP Verbindungen zulässt. Und ohne eigenen WebFTP-Server meide ich derartige Angebote auch lieber, wer kann schon mit Sicherheit sagen, was mit den Zugangsdaten passiert, die man auf solchen Seiten eingibt.

Um dieses Manko ein wenig zu entschärfen, habe ich mich daher nach einem Script umgesehen, welches es mir ermöglichen soll, alle relevanten Dateien (html, php, css, xml, etc.) auf dem Server direkt im Browser zu bearbeiten. Ein CMS kommt bisher nicht zum Einsatz (WordPress mal ausgenommen, aber darin verwalte ich nicht meine eigenen Scripte). Und ich muss sagen, ich bin überrascht, wie schwer es ist, ein passendes Helferlein zu finden.

Online Dateimanager gibt es zu Hauf, aber viele davon lassen sich nicht auf dem eigenen Server installieren, sondern wollen wieder wie schon WebFTP die Zugangsdaten von einem wissen. Und sehr viele der verbleibenden Lösungen lassen sich nicht auf das root-Verzeichnis des Servers anwenden, sondern bringen ihre eigene, geschlossene Verzeichnisstruktur mit. Ich will aber keine ausgeklügelte Multi-User Unterstützung, sondern einfach nur jederzeit Zugriff auf alle meine Daten.

Fündig geworden bin ich schließlich mit File Thingie. Dabei handelt es sich um einen kleinen, überschaubaren Dateimanager mit Editier-Funktionalität und der Möglichkeit, ZIP-Archive zu entpacken. Und er muss nicht mal im Root-Verzeichnis abgelegt werden, sondern kann in einem beliebigen Unterverzeichnis seine Dienste verrichten.

In der config.php müssen zuvor aber noch ein paar Änderungen vorgenommen werden: Benutzername und Passwort sollten vergeben werden, Anpassung des Standardverzeichnisses, Bearbeiten der Blacklists und letztlich unter den Plugin Settings die Ergänzung weiterer zugelassener Dateiendungen für den Editor.

Wer möchte, kann sich auch einen WYSIWYG-Editor hinzufügen. Im Installationspaket enthalten sind bereits Plugins für TinyMCE, CKEditor und FCKEditor, eigene Plugins können aber ebenfalls hinzugefügt werden.

Eine einfache, eingebaute Möglichkeit für Syntax Highlighting im normalen Texteditor gibt es hingegen leider nicht… oder ich hab sie bisher nur noch nicht gefunden, denn ein WYSIWYG-Editor hilft mir in den meisten Fällen nicht weiter.

Update:
Da das Projekt auf den offiziellen Seiten nicht mehr erreichbar ist, hier die letzte Version zum Download: File Thingie 2.5.7

WordPress Kontaktformular ohne Mail Versand

13. April 2012 Keine Kommentare

Möchte man für Besucher seiner Seite schnell und einfach erreichbar sein, bietet man ihnen einfach ein Kontaktformular an. Für diese Aufgabe gibt es auch unzählige Plugins. Dumm nur, wenn die Mail-Funktionen des Servers gesperrt sind. Pytal verbietet grundsätzlich erstmal den Versand, will man doch die eMail Funktion, so muss man betteln gehen. Einmal hab ich schon solch eine Anfrage gestellt, sogar nach den Vorgaben und Richtlinien im Forum, diese wurde aber trotzdem kommentarlos abgelehnt.

Daher musste nun erstmal ein Kontaktformular her, das in der Lage ist, die Formulardaten auf dem Server zu speichern, statt sie zu versenden. Recht zufrieden bin ich bisher mit MM Forms Community, da es dieer Aufgabe sehr gut nachkommt und wahlweise auch noch zusätzlich den Mailversand durchführen kann. Sobald die Funktion freigeschaltet sein sollte, kann ich also mit nur einem Klick in den Einstellungen wechseln, ohne mir ein neues Plugin suchen zu müssen.

Allerdings hat das Plugin auch einen kleinen Haken, zumindest temporär. Version 2.2.5 funktioniert im aktuellen WordPress nämlich nicht ganz fehlerfrei. Möchte man sich empfangene Nachrichten im Backend ansehen, erhält man lediglich eine Fehlermeldung. Die Anzeige der Nachrichten im Frontend hingegen funktioniert tadellos, nur geht deren Inhalt niemanden außer meiner einer etwas an 😉

Drum musste ein kleines Script her, welches in der Lage ist zu erkennen, ob grad jemand angemeldet ist und zudem noch über Admin-Rechte verfügt. Im WordPress Forum bin ich fündig geworden und hab die entsprechende Funktion gleich auf der Kontakt-Seite umgesetzt.

<?php global $current_user; get_currentuserinfo(); ?>
<?php if ($current_user->user_level == 10 ) { ?>
  [fοrmdata 1 "Kontaktformular"]
<?php } else {   ?>
  [fοrm 1 "Kontaktformular"]
<?php } ?>

Jetzt kann man mir unkompliziert Nachrichten senden und ich kann auf der selben Seite sehen, worum es denn überhaupt geht. Das einzige, was jetzt noch etwas skeptisch macht, ist das Captcha… das sieht mir etwas zu einfach aus, als das es wirklich effizient Spam-Bots abhalten könnte. Aber das wird sich erst noch zeigen müssen.

PHP Kalender Teil 6, Mondphasen

11. April 2012 5 Kommentare

Ähnlich wie auch schon bei der Berechung der Jahreszeiten ist auch die Berechnung der Mondphasen an eine deutlich umfangreichere Formel gebunden als die hiesigen Feiertage. Aber bevor es gleich ans Eingemachte geht, folgen erstmal ein paar Grundlagen.

Einen Umlauf des Mondes um die Erde (Neumond bis Neumond) nennt man Lunation oder auch synodische Periode. Da sich der Mond auf einer annähernd elliptischen Umlaufbahn um die Erde bewegt, kann die Dauer eines vollen Umlaufes jedoch stark variieren. Zur Vereinfachung wurde daher ein Mittelwert, der synodische Monat, gebildet. Dieser beträgt 29 Tage, 12 Stunden und 44 Minuten.

Für die Überprüfung der späteren Ergebnisse werden wieder Bezugsdaten benötigt. Erneut hilft hier die Wikipedia aus (Termine von 2005 – 2020), als zweite Quelle dienen die Daten vom Munich Astro Archive (Termine von 1700 – 2199).

 
Die „einfache“ Grundformel

Ausgehend vom synodischen Monat kann man schnell eine einfache Funktion für die Berechnung der Mondphasen erstellen. Man sucht sich aus den Bezugsdaten einfach einen vergangenen Neumond-Termin als Referenzpunkt und addiert den synodischen Monat. Halbierung, Viertelung oder sonstige Teilung des synodischen Monats bringen die restlichen Daten.

Für mich kam diese Lösung jedoch nicht in Frage, da der synodische Monat einen Fehler von bis zu 7 Stunden aufweist. Bei den Jahreszeiten waren mir schon 15 Minuten zu viel ^^

 
Die komplexere Formel

Eine Quelle, viele Umsetzungen. Auf der Suche nach einer genaueren Formel stolpert man recht schnell über das Buch Astronomische Algorithmen von Jean Meeus. Dessen Formel wurde auf der Seite Computus in JavaScript und im IP-Symcon Forum in PHP umgesetzt. Diese Berechnung hat einen Fehler von unter einer Minute.

Ich war so frei, mir die vorgefertigte PHP Variante zu nehmen und diese entsprechend meiner Vorstellungen zu modifizieren. Für den Kalender wollte ich nur die Termine für Neumond, Vollmond sowie rechtes und linkes Viertel. Alle anderen Funktionen flogen raus. Abschließend wurde das ganze noch zu einer Klasse umgebaut.

class mondphasen {
  function Var_o($k, $t){
    return 124.7746 - 1.5637558 * $k + .0020691 * $t * $t + .00000215 * $t * $t * $t;
  }

  function Var_f($k, $t){
    return 160.7108 + 390.67050274 * $k - .0016341 * $t * $t - .00000227 * $t * $t * $t + .000000011 * $t * $t * $t * $t;
  }

  function Var_m1($k, $t){
    return 201.5643 + 385.81693528 * $k + .1017438 * $t * $t + .00001239 * $t * $t * $t - .000000058 * $t * $t * $t * $t;
  }

  function Var_m($k, $t){
    return 2.5534 + 29.10535669 * $k - .0000218 * $t * $t - .00000011 * $t * $t * $t;
  }

  function Var_e($t){
    return 1 - .002516 * $t - .0000074 * $t * $t;
  }

  function Var_JDE($k, $t){
    return 2451550.09765 + 29.530588853 * $k + .0001337 * $t * $t - .00000015 * $t * $t * $t + .00000000073 * $t * $t * $t * $t;
  }

  function CS($x){
    return cos($x * .0174532925199433);
  }
  
  function SN($x){
    return sin($x * .0174532925199433);
  }

  function Neumond($k){
    $k = floor($k);
    $t = $k / 1236.85;
    $e = $this->Var_e($t);
    $m = $this->Var_m($k, $t);
    $m1 = $this->Var_m1($k, $t);
    $f = $this->Var_f($k, $t);
    $o = $this->Var_o($k, $t);
    //Neumondkorrekturen
    $JDE = $this->Var_JDE($k, $t);
    $JDE += (-1) * 0.4072 * $this->SN($m1) + 0.17241 * $e * $this->SN($m) + 0.01608 * $this->SN(2 * $m1) + 0.01039 * $this->SN(2 * $f) + 0.00739 * $e * $this->SN($m1 - $m) - 0.00514 * $e * $this->SN($m1 + $m) + 0.00208 * $e * $e * $this->SN(2 * $m) - 0.00111 * $this->SN($m1 - 2 * $f) - 0.00057 * $this->SN($m1 + 2 * $f);
    $JDE += 0.00056 * $e * $this->SN(2 * $m1 + $m) - 0.00042 * $this->SN(3 * $m1) + 0.00042 * $e * $this->SN($m + 2 * $f) + 0.00038 * $e * $this->SN($m - 2 * $f) - 0.00024 * $e * $this->SN(2 * $m1 - $m) - 0.00017 * $this->SN($o) - 0.00007 * $this->SN($m1 + 2 * $m) + 0.00004 * $this->SN(2 * $m1 - 2 * $f);
    $JDE += 0.00004 * $this->SN(3 * $m) + 0.00003 * $this->SN($m1 + $m - 2 * $f) + 0.00003 * $this->SN(2 * $m1 + 2 * $f) - 0.00003 * $this->SN($m1 + $m + 2 * $f) + 0.00003 * $this->SN($m1 - $m + 2 * $f) - 0.00002 * $this->SN($m1 - $m - 2 * $f) - 0.00002 * $this->SN(3 * $m1 + $m);
    $JDE += .00002 * $this->SN(4 * $m1);
    return $this->Korrektur($JDE, $t, $k);
  }

  function Viertel($k, $modus){
    // modus = .25 = Erstes Viertel, modus = .75 = Letztes Viertel
    $k = floor($k) + $modus;
    $t = $k / 1236.85;
    $e = $this->Var_e($t);
    $m = $this->Var_m($k, $t);
    $m1 = $this->Var_m1($k, $t);
    $f = $this->Var_f($k, $t);
    $o = $this->Var_o($k, $t);
    // Viertelmondkorrekturen
    $JDE = $this->Var_JDE($k, $t);
    $JDE += -.62801 * $this->SN($m1) + .17172 * $e * $this->SN($m) - .01183 * $e * $this->SN($m1 + $m) + .00862 * $this->SN(2 * $m1) + .00804 * $this->SN(2 * $f) + .00454 * $e * $this->SN($m1 - $m) + .00204 * $e * $e * $this->SN(2 * $m) - .0018 * $this->SN($m1 - 2 * $f) - .0007 * $this->SN($m1 + 2 * $f);
    $JDE += -.0004 * $this->SN(3 * $m1) - .00034 * $e * $this->SN(2 * $m1 - $m) + .00032 * $e * $this->SN($m + 2 * $f) + .00032 * $e * $this->SN($m - 2 * $f) - .00028 * $e * $e * $this->SN($m1 + 2 * $m) + .00027 * $e * $this->SN(2 * $m1 + $m) - .00017 * $this->SN($o);
    $JDE += -.00005 * $this->SN($m1 - $m - 2 * $f) + .00004 * $this->SN(2 * $m1 + 2 * $f) - .00004 * $this->SN($m1 + $m + 2 * $f) + .00004 * $this->SN($m1 - 2 * $m) + .00003 * $this->SN($m1 + $m - 2 * $f) + .00003 * $this->SN(3 * $m) + .00002 * $this->SN(2 * $m1 - 2 * $f);
    $JDE += .00002 * $this->SN($m1 - $m + 2 * $f) - .00002 * $this->SN(3 * $m1 + $m);
    $w = .00306 - .00038 * $e * $this->CS($m) + .00026 * $this->CS($m1) - .00002 * $this->CS($m1 - $m) + .00002 * $this->CS($m1 + $m) + .00002 * $this->CS(2 * $f);
    if ($modus == .25) {$JDE += $w;} else {$JDE += (-1)*$w;}
    return $this->Korrektur($JDE, $t, $k);
  }

  function Vollmond($k){
    $k = floor($k) + .5;
    $t = $k / 1236.85;
    $e = $this->Var_e($t);
    $m = $this->Var_m($k, $t);
    $m1 = $this->Var_m1($k, $t);
    $f = $this->Var_f($k, $t);
    $o = $this->Var_o($k, $t);
    //Vollmondkorrekturen
    $JDE = $this->Var_JDE($k, $t);
    $JDE += -.40614 * $this->SN($m1) + .17302 * $e * $this->SN($m) + .01614 * $this->SN(2 * $m1) + .01043 * $this->SN(2 * $f) + .00734 * $e * $this->SN($m1 - $m) - .00515 * $e * $this->SN($m1 + $m) + .00209 * $e * $e * $this->SN(2 * $m) - .00111 * $this->SN($m1 - 2 * $f) - .00057 * $this->SN($m1 + 2 * $f);
    $JDE += .00056 * $e * $this->SN(2 * $m1 + $m) - .00042 * $this->SN(3 * $m1) + .00042 * $e * $this->SN($m + 2 * $f) + .00038 * $e * $this->SN($m - 2 * $f) - .00024 * $e * $this->SN(2 * $m1 - $m) - .00017 * $this->SN($o) - .00007 * $this->SN($m1 + 2 * $m) + .00004 * $this->SN(2 * $m1 - 2 * $f);
    $JDE += .00004 * $this->SN(3 * $m) + .00003 * $this->SN($m1 + $m - 2 * $f) + .00003 * $this->SN(2 * $m1 + 2 * $f) - .00003 * $this->SN($m1 + $m + 2 * $f) + .00003 * $this->SN($m1 - $m + 2 * $f) - .00002 * $this->SN($m1 - $m - 2 * $f) - .00002 * $this->SN(3 * $m1 + $m);
    $JDE += .00002 * $this->SN(4 * $m1);
    return $this->Korrektur($JDE, $t, $k);
  }

  function Korrektur($JDE, $t, $k){
    //Zusätzlichen Korrekturen
    $JDE += .000325 * $this->SN(299.77 + .107408 * $k - .009173 * $t * $t) + .000165 * $this->SN(251.88 + .016321 * $k) + .000164 * $this->SN(251.83 + 26.651886 * $k) + .000126 * $this->SN(349.42 + 36.412478 * $k) + .00011 * $this->SN(84.66 + 18.206239 * $k);
    $JDE += .000062 * $this->SN(141.74 + 53.303771 * $k) + .00006 * $this->SN(207.14 + 2.453732 * $k) + .000056 * $this->SN(154.84 + 7.30686 * $k) + .000047 * $this->SN(34.52 + 27.261239 * $k) + .000042 * $this->SN(207.19 + .121824 * $k) + .00004 * $this->SN(291.34 + 1.844379 * $k);
    $JDE += .000037 * $this->SN(161.72 + 24.198154 * $k) + .000035 * $this->SN(239.56 + 25.513099 * $k) + .000023 * $this->SN(331.55 + 3.592518 * $k);
    return $JDE;
  }

  function Var_k($Jahr, $Aktdatum, $tz){
    return ($Jahr + ((date("m", time()) - 1) * 30.4 + date("d", time()) + $tz) / 365 - 2000) * 12.3685;
  }

  function NaechsterVM($Jahr, $Aktdatum, $zeit){
    $tz = 0;
    $k = "";
    while($this->Vollmond($k) < $zeit) {
      $k = $this->Var_k($Jahr, $Aktdatum, $tz);
      $tz += 1;
    }
    return $this->Vollmond($k) - $zeit;
  }

  function NaechstesLV($Jahr, $Aktdatum, $zeit){
    $tz = 0;
    $k = "";
    while($this->Viertel($k, .75) < $zeit) {
      $k = $this->Var_k($Jahr, $Aktdatum, $tz);
      $tz += 1;
    }
    return $this->Viertel($k, .75) - $zeit;
  }

  function NaechsterNM($Jahr, $Aktdatum, $zeit){
    $tz = 0;
    $k = "";
    while($this->Neumond($k) < $zeit) {
      $k = $this->Var_k($Jahr, $Aktdatum, $tz);
      $tz += 1;
    }
    return $this->Neumond($k) - $zeit;
  }

  function NaechstesEV($Jahr, $Aktdatum, $zeit){
    $tz = 0;
    $k = "";
    while($this->Viertel($k, .25) < $zeit) {
      $k = $this->Var_k($Jahr, $Aktdatum, $tz);
      $tz += 1;
    }
    return $this->Viertel($k, .25) - $zeit;
  }

  function nextMV($date = false){
    $temp = date_default_timezone_get();
    date_default_timezone_set("UTC");

    if($date != false)
      $aktuell = $date;
    else
      $aktuell = time();
    $zeit = $aktuell / 86400 + 2440587.5; // Umrechnen in Julianische Tage
    $Jahr = date("Y", $aktuell);

    $JDE_mondphase['vm'] = $this->NaechsterVM($Jahr, $aktuell, $zeit);
    $JDE_mondphase['lv'] = $this->NaechstesLV($Jahr, $aktuell, $zeit);
    $JDE_mondphase['nm'] = $this->NaechsterNM($Jahr, $aktuell, $zeit);
    $JDE_mondphase['ev'] = $this->NaechstesEV($Jahr, $aktuell, $zeit);

    asort($JDE_mondphase);

    $JDE_mondphase['vm'] = $aktuell + $JDE_mondphase['vm'] * 86400;
    $JDE_mondphase['lv'] = $aktuell + $JDE_mondphase['lv'] * 86400;
    $JDE_mondphase['nm'] = $aktuell + $JDE_mondphase['nm'] * 86400;
    $JDE_mondphase['ev'] = $aktuell + $JDE_mondphase['ev'] * 86400;

    date_default_timezone_set($temp);
    return $JDE_mondphase;
  }
}

Jetzt ruft man einfach die Funktion nextMV() auf, übergibt dieser ein bestimmtes Datum und erhält die direkt auf das angegebene Datum folgenden 4 Mondphasen. Mit einer kleinen Schleife lassen sich so auch alle Termine bis zu einem bestimmten Termin abrufen.

$mondphasen = new mondphasen();
$datum = time();
while($datum < mktime(0,0,0,12,31,2017)) {
  $mv = $mondphasen->nextMV($datum);
  foreach($mv as $phase => $termin) {
    echo date("d.m.Y H:i",$termin)." ".$phase."<br>\n";
    $datum = $termin + 86400;
  }
}

Mehr Sicherheit für WordPress

29. März 2012 Keine Kommentare

Nachdem ich mich in letzter Zeit ein wenig mit SEO beschäftigt habe, und die Seite dahingehend etwas optimiert habe, kam mir nun das Thema Sicherheit in den Sinn. Aber da dies mein erster Blog ist, kann ich diesbezüglich auf keinen allzu großen Wissenschatz zurückgreifen, sondern muss mich an den Hinweisen und Empfehlungen anderer orientieren. Als hilfreich habe ich dabei die foldenden Seiten empfunden:

Ich werde aber selbst auf die aus meiner Sicht wichtigsten Punkte nochmal genauer eingehen. Ich gehe dabei von einer vorhandenen Installation mit der Version 3.3.1 aus.

 
1. Admin-Account sinnvoll benennen

Der bei der Blog-Installation angelegte Admin-Account sollte nicht admin heißen! Ideal wäre ein Name, der nicht im direkten Zusammenhang mit der URL oder dem Thema des Seite steht. Der eigene Nickname sollte ebenfalls nicht genutzt werden. Hat man sich daran schon bei der Installation gehalten, kann man den folgenden Absatz überspringen, andernfalls weiterlesen.

Lege einen neuen Benutzer mit Admin-Rechten an, vergebe einen passenden Namen und nutze ein sicheres Passwort. Anschließend mit dem neuen Account einloggen und den alten Account löschen. Man wird gefragt, was mit den vorhandenen Inhalten des Benutzers passieren soll, hier wählt man die Übernahme auf den neuen Account.

Wähle im Profil auf jeden Fall aus, dass der angezeigte Name nicht der Benutzername ist.

Eine Sache fehlt aber noch: die ID des Accounts in der Datenbank hat nun noch immer die 1 oder, wenn es keine anderen Benutzer gibt, die 2. Das wissen auch potentielle Angreifer. Daher sollte man diese ID auf einen zufälligen Wert ändern. Dazu läd man sich entweder ein Plugin wie Search & Replace, öffnet phpMyAdmin oder greift sonst wie auf die Datenbank zu.

Es muss in 4 Tabellen je ein Wert geändert werden, und zwar in wp_users, wp_usermeta, wp_posts und wp_links. Im folgenden SQL-Statement nehme ich exemplarisch die ID 194, diese Zahl sollte aber jeder selbst festlegen. Die aktuelle ID muss selbstverständlich auch angepasst werden.

UPDATE wp_users    SET ID          = 194 WHERE ID          = 1;
UPDATE wp_usermeta SET user_id     = 194 WHERE user_id     = 1;
UPDATE wp_posts    SET post_author = 194 WHERE post_author = 1;
UPDATE wp_links    SET link_owner  = 194 WHERE link_owner  = 1;

 
2. Tabellen-Präfix != wp_

Was bei der Installation dem Benutzernamen das admin ist dem Tabellen-Präfix das wp_. Auch hier sollte man eine Änderung in Betracht ziehen. Je nachdem, wie viele Tabellen man noch in seiner Datenbank hat, kann es sinnvoll sein, das Präfix mit bestimmten Zeichen beginnen zu lassen, um die Position der WordPress-Tabellen bei der Sortierung zu beeinflussen.

In der Basisinstallation umfasst dies 11 Tabellen, die ich nachfolgend schon mal als fertiges SQL-Statement vorbereitet habe. Das Präfix wird für dieses Beispiel auf 19a7Z4_ gesetzt.

RENAME TABLE wp_commentmeta        TO 19a7Z4_commentmeta;
RENAME TABLE wp_comments           TO 19a7Z4_comments;
RENAME TABLE wp_links              TO 19a7Z4_links;
RENAME TABLE wp_options            TO 19a7Z4_options;
RENAME TABLE wp_postmeta           TO 19a7Z4_postmeta;
RENAME TABLE wp_posts              TO 19a7Z4_posts;
RENAME TABLE wp_terms              TO 19a7Z4_terms;
RENAME TABLE wp_term_relationships TO 19a7Z4_term_relationships;
RENAME TABLE wp_term_taxonomy      TO 19a7Z4_term_taxonomy;
RENAME TABLE wp_usermeta           TO 19a7Z4_usermeta;
RENAME TABLE wp_users              TO 19a7Z4_users;

Wenn man Plugins installiert hat, können es auch durchaus mehr Tabellen sein. Diese müssen dann ebenfalls umbenannt werden.

Damit allein ist es aber noch nicht getan, es sind noch weitere Schritte notwendig, damit WordPress weiterhin fehlerfrei seinen Dienst verrichtet. In der Tabelle 19a7Z4_options und evtl. auch in 19a7Z4_usermeta müssen noch Einträge abgeändert werden.

UPDATE 19a7Z4_options  SET option_name = REPLACE(option_name,'wp_','19a7Z4_');
UPDATE 19a7Z4_usermeta SET meta_key    = REPLACE(meta_key,   'wp_','19a7Z4_');

Zu guter letzt muss die Datei wp-config.php bearbeitet werden, damit WordPress das neue Tabellen-Präfix auch bekannt ist.

$table_prefix  = '19a7Z4_';

 
3. Verzeichnisschutz für wp-content und wp-includes

In diesen Verzeichnissen liegt nichts, worauf ein Besucher direkt zugreifen müsste, außer vielleicht den Uploads. Daher sollte man sie auch entsprechend absichern. In jedes Verzeichnis kommt eine .htaccess mit folgendem Inhalt:

Order Allow,Deny 
Deny from all 
<Files ~ ".(css|jpe?g|png|gif|js|svg)$"> 
  Allow from all 
</Files>

Grundsätzlich wird der Zugriff auf alle Dateien in diesen Verzeichnissen verboten, mit Ausnahme bestimmter Dateiendungen, die man individuell anpassen und ergänzen sollte.

 
4. Verzeichnisschutz für wp-admin oder nur wp-login.php ?

Diese Frage ist auf Playground sehr gut beantwortet und erläutert worden. In vielen Anleitungen wird dazu geraten, den kompletten Ordner wp-admin via .htaccess und .htpasswd zu schützen. Da WordPress aber auch außerhalb des Backends auf die Dateien in dem Verzeichnis zugreifen kann, wäre ein reibungsloser Betrieb für normale Besucher nicht gewährleistet. Daher wird nur die Datei wp-login.php zusätzlich geschützt.

# protect wp-login.php
<files wp-login.php>
  AuthType Basic
  AuthName "Admin-Bereich"
  AuthUserFile /absoluter-serverpfad/.htpasswd
  require valid-user
</files>

Ein doppelter Login also. Muss man aber nur machen, wenn man seinen für WordPress gewählten Benutzernamen und das Passwort für unzureichend hält… aber ob dann ein zusätzlicher Schutz mit ähnlich schwachen Daten die Situation großartig verbessert, darf angezweifelt werden.

Aus meiner Sicht nicht notwendig, für Sicherheitsfanatiker aber garantiert eine tolle Option 😉

 
5. Umgang mit fehlerhaften Login-Versuchen

Man kennt es von vielen Seiten, x-mal das Password falsch eingegeben, schon kann man sich erstmal Kaffee kochen gehen oder gleich den Support anrufen. WordPress bietet diesen Luxus von Haus aus nicht, aber er lässt sich leicht über Plugins nachrüsten. Limit Login Attempts oder Login LockDown sind zwei Vertreter dieser Plugin-Gattung, die Konfiguration sollte selbsterklärend sein.

 
6. Fehlerhinweise auf der Login-Seite ausblenden

Es ist immer wieder schön, wenn man die Zugangsdaten vergessen hat, und einem die Seite genau sagt, wo der Fehler liegt. So macht es auch WordPress und sagt einem genau, ob der Benutzername oder nur das Passwort falsch sind. Für einen selbst eine tolle Hilfe, aber leider auch für jeden anderen, der Zugang haben will.

Daher sollte man auch hier entweder mit Plugins wie WSD security arbeiten oder selbst die entsprechenden Änderungen im Quelltext vornehmen. Bei iNove zeigt das Plugin jedenfalls keine Wirkung, aber das kann durchaus am Theme liegen.

Man öffne also die Datei functions.php im iNove-Verzeichnis und kopiere folgende Zeile an den Anfang der Datei:

add_filter('login_errors',create_function('$a', "return null;"));

 
7. Versionsnummer nicht mehr ausgeben

WordPress gibt seine aktuelle Versionsnummer immer als meta-Tag aus. Eine wertvolle Information, weiß man so doch gleich, ob WordPress aktuell ist und welcher Exploit am ehesten Erfolg haben kann. Also weg mit der Information. Auch zu diesem Zweck gibt es wieder viele Plugins (erneut sei WSD security genannt) oder die Möglichkeit, händisch vorzugehen.

Man muss dafür im Theme-Verzeichnis entweder in der header.php oder der index.php die Zeile, in welcher der meta-Tag erzeugt wird, löschen.

<meta name="generator" content="WordPress <?php bloginfo('version'); ?>" />

Da die Version aber auch im RSS-Feed angegeben wird, und einige Funktionen und Plugins diese Information auch benötigen, kann man die Versionsnummer leider nicht ganz löschen. Das Ausblenden via Plugin scheint daher am flexibelsten.

Zudem sollte man noch den Zugriff auf zwei Dateien unterbinden, in denen die Versionsnummer ebenfalls nachzulesen ist: liesmich.html und readme.html. Einige Seiten empfehlen deren Löschung, was man dann aber nach jedem Update wiederholen darf. Als eine langfristige Lösung scheint mir hier der Einsatz von .htaccess hilfreich zu sein.

# protect liesmich.html
<files liesmich.html>
  Order deny,allow
  deny from all
</files>

# protect readme.html
<files readme.html>
  Order deny,allow
  deny from all
</files>

 
Fazit

Mit ein paar relativ einfachen Aktionen kann man die Sicherheit von WordPress ein gutes Stück erhöhen, auch wenn es zugleich etwa schade ist, dass man als normaler Nutzer überhaupt an sowas denken muss, denn einige Dinge könnten bereits voreingestellt ausgeliefert werden.

Aber so hat man zumindest immer mal wieder etwas neues, um sich zu beschäftigen ^^

PHP Kalender Teil 5

28. März 2012 Keine Kommentare

Ich komm gar nicht so oft zum schreiben, wie ich gerne würde. In letzter Zeit hat das Programmieren meine volle Aufmerksamkeit, und in der Überschrift sieht man auch gleich, worum es geht. Ich werkel endlich wieder am Kalender rum.

Mittlerweile ist das ganze auch funktionsbereit, es gab zwar anfangs einige Berechnungsprobleme dank der Zeitumstellungen, aber die haben sich lösen lassen und nun arbeitet das System wie gewünscht. Standardmäßig werden die Feiertage ausgegeben, in Schleswig Holstein arbeitsfreie Feiertage werden zudem farblich hinterlegt. Bei Bedarf können Urlaub, Geburtstage und Hochzeitstage hinzugefügt werden, allgemeine Termine stehen als nächstes auf der Todo-Liste, ebenso wie ein Login mit Session.

Zur Zeit habe ich den Kalender auf 3 Tage Rückblick und 15 Tage Vorschau eingestellt. Das bisherige Ergebnis kann im Testverzeichnis aufgerufen werden.

Mal schauen, ob ich da noch den Diskordianischen Kalender integriere. Ist zwar nur ne Spielerei, aber eine PHP-Portierung von ddate() habe ich bereits gefunden, also stände dem nichts im Wege.

SimpleXML statt mySQL

9. März 2012 Keine Kommentare

Dynamische Seiten sind in vielerlei Hinsicht praktischer als statische Seiten. Doch für so manche Anwendung ist der Einsatz einer Datenbank maßlos überdimensioniert, überhaupt nicht geeignet oder man hat noch nicht einmal einen Webspace mit Datenbankunterstützung.

Hier kommt XML ins Spiel. Man kann in einem XML-Dokument die ganze Struktur einer Datenbank nachbilden (natürlich nur mit aufgelösten Beziehungen), wobei ich insbesondere die m:n Beziehung in XML sogar als angenehmer empfinde, sowohl bei der Notation, als auch der Abfrage. Und dank fertiger Funktionen wie SimpleXML ist der Umgang mit XML-Dateien auch kaum komplizierter als eine DB-Abfrage.

Ich nehme als Beispiel mal eine kleine Linkliste.

 
Die Dokumentstruktur

Da man eine XML-Datei strukturieren kann, wie man möchte, sollte es nicht sonderlich schwer fallen, seine Ideen und Vorstellungen umzusetzen. Für eine einfache Linkliste wird ohnehin nicht viel benötigt: ein Linktitel, die URL und eine oder mehrere Kategorien, nach denen man Filtern kann. Vorteil gegenüber statischer Linklisten: keine redundanten Einträge.

<?xml version="1.0" encoding="UTF-8" ?>
<xfav>
  <entry>
    <title>SelfHTML</title>
    <url>http://de.selfhtml.org/</url>
    <category>HTML</category>
    <category>CSS</category>
    <category>JavaScript</category>
  </entry>
</xfav>

Als Datenbank wäre die Struktur schon etwas komplexer, da man die Kategorien als m:n Beziehung mit insgesamt 3 Tabellen umsetzen müsste.

 
Die Abfrage

Dank SimpleXML ist das Einlesen und Filtern der Einträge aus der XML-Datei keine große Herausforderung. Der Inhalt der Datei wird als mehrdimensionales Array zur Verfügung gestellt.

$xfav = array(
  "title"    => "SelfHTML";
  "url"      => "http://de.selfhtml.org/";
  "category" => array("HTML","CSS","JavaScript")
)

Die Ausgabe mit Filterfunktion könnte nun folgendermaßen aussehen:

<?php
$list = "HTML"; // all, none
$xfav = simplexml_load_file('xfav.xml');

if ($list == "none")
  echo "Bitte Kategorie auswählen!";
else {
  echo "Gewählte Kategorie: ".$list."<br>";
  foreach ($xfav->entry as $entry) {
    if ($list == "all")
      echo '<a href="'.$entry->url.'">'.$entry->title.'</a><br>';
    else {
      foreach ($entry->category as $category) {
        if ($category == $list)
          echo '<a href="'.$entry->url.'">'.$entry->title.'</a><br>';
      }
    }
  }
}
?>

Natürlich hat diese Variante gegenüber einer Datenbankabfrage nicht den gleichen Komfort. Möchte man in diesem Beispiel die Einträge zusätzlich zur Filterung auch noch alphabetisch sortiert haben, muss man sich die dafür nötige Sortierfunktion selbst erstellen.

Man sollte auch nicht außer Acht lassen, dass die Variante mit einer XML-Datei deutlich belastender für den Server ist. Es muss jedes Mal die komplette Datei eingelesen und in ein Array umgewandelt werden und beim Filtern muss auch jeder Eintrag einzeln geprüft werden. Es gibt weder Indexe noch Buffer oder Caches, die dem Server die Arbeit vereinfachen. Daher ist der Einsatz von XML als DB-Ersatz nur bei kleinen Datenmengen zu empfehlen.