Skip to content
Sep 9 10

htaccess: Alle bis auf eine IP umleiten

by dennis

z.B. für Wartungsarbeiten:

folgendes Beispiel leitet alle Anfragen (außer die von IP 111.111.111.111) um auf http://wartungsarbeiten.quirks-modus.de

RewriteCond %{REMOTE_ADDR} !^111\.111\.111\.111$
RewriteRule ^(.*)$ http://wartungsarbeiten.quirks-modus.de [R=307,L]
Jul 28 10

PHP Template System

by dennis

Hier mal ein Anfang für ein eigenes Template-System für PHP:

Ein Beispiel für die index.tpl:

[head.tpl]
        <div id="content">
                <p>your content here</p>
        </div>
[footer.tpl]

Die Dateien head.tpl und footer.tpl können weitere Template-Dateien enthalten. Es wird rekursiv geparst.

Der Aufruf:

echo new Template('index.tpl');

Die Klasse:

class Template {
        private $template;
 
        public function __construct($templateFile) {
                if (is_file($templateFile)) {
                        $this->template = file_get_contents($templateFile);
                } else {
                        die('Template File "'.$templateFile.'" not found.');
                } 
        }
 
        private function getModules($s) {
                preg_match_all( "/\[(.+?)\]/is", $s, $matches);
                return $matches[1];
        }
 
        private function parse($tpl) {
                $modules = $this->getModules($tpl);
                if (count($modules)) {
                        foreach ($modules as $mod) {
                                if (is_file($mod)) {
                                        $tpl = str_replace('['.$mod.']',file_get_contents($mod), $tpl);
                                        $tpl = $this->parse($tpl);
                                } 
                        }
                }
                return $tpl;
        }
 
        public function __toString() {
                return $this->parse($this->template);
        }
 
 
}
Jul 23 10

symfony/doctrine:
MySql Datenbankverbindung bei 1&1

by dennis

Nach langem Suchen hier die korrekte Schreibweise für die Datei /config/database.yml :

all:
  doctrine:
    class: sfDoctrineDatabase
    param:
      dsn: 'mysql:dbname=hierDerDbName;host=localhost;unix_socket=/tmp/mysql5.sock;'
      username: hierDerBenutzername
      password: hierDasPasswort

Die Kurzschreibweise “localhost:/tmp/mysql5.sock” wie bei 1&1 angegeben funktioniert an dieser Stelle nicht! Diese Schreibweise wird von den PHP Data Objects (PDO) nicht akzeptiert und erzeugt folgende Fehlermeldung:

PDO Connection Error: SQLSTATE[HY000] [2005] Unknown MySQL server host 'localhost:/tmp/mysql5.sock'
Jun 1 10

jScrollPane print-Stylesheet

by dennis

JScrollPane ist ein jQuery Plugin von Kevin Luck:
http://www.kelvinluck.com/assets/jquery/jScrollPane/jScrollPane.html.

Folgenden Codeschnipsel für eine korrekte Druck-Ausgabe habe ich hier gefunden:
http://stackoverflow.com/questions/2570906/how-to-print-a-full-content-of-jscrollpane

div.jScrollPaneContainer {
   position: static !important;
   height: auto !important;
   overflow: visible !important;
}
 
div.jScrollPaneContainer > * {
   display: none !important;
}
 
div.scroll-pane {
   position: static !important;
   display: block !important;
   float: none !important;
}
Feb 11 10

OpenDocument Dateien mit PHP ändern

by dennis

Das erste was man wissen muss, wenn man OpenDocument Dateien bearbeiten will, ist dass es sich dabei um ein offenes Format handelt, welches aus einem ZIP Archiv mit vielen einzelnen Dateien besteht. Wie dieses Archiv aufgebaut ist, kann man hier nachlesen: http://de.wikipedia.org/wiki/OpenDocument

Nachdem man das Archiv also mit einem Programm seiner Wahl entpackt hat (z.B. mit 7-Zip: http://www.7-zip.org/), kann man die einzelnen Dateien ganz einfach mit PHP bearbeiten. Zur Unterstützung habe ich dafür eine kleine PHP-Klasse geschrieben (siehe weiter unten). Als Beispiel bearbeite ich hier mal eine odt-Datei aus OpenOffice Writer.

Der Platzhalter ###BEISPIEL###, den ich vorher mit OpenOffice an die entsprechende Stelle gesetzt habe soll hier durch den String “Hat geklappt” ersetzt werden:

<?
include 'opendocument.class.php'; // klasse einbinden
 
// Als erstes erstelle ich ein neues Odf - Objekt. Im Ordner 'beispiel' befinden sie die 
// unkomprimierten Dateien meiner OpenDocument-Text Datei 
 
$Odf = new opendocument('/www/beispiel/');
 
// Inhalt von content.xml einlesen: 
// (Hier steht der eigentliche Inhalt des Dokuments drin --> siehe wikipedia)
$content = $Odf -> get_file('content.xml');
 
// Platzhalter ###beispiel### durch String 'Hat geklappt' ersetzen:
$content = str_replace('###BEISPIEL###','Hat geklappt',$content);
 
// Neuen Content "setzen":
$Odf -> set_file($content,'content.xml');
 
// Header senden ($Odf->get_mime gibt den mime-Typ zurück):
header("Content-type: ".$Odf->get_mime); 
header("Content-Disposition: attachment; filename=beispiel.odt");
 
// Manipuliertes Dokument ausgeben:
echo $Odf -> output();
?>

und hier die dazu benötigte Klasse:

<?
class opendocument {
        /*
         * opendocument class
         * written by D.Lehmann (www.quirks-modus.de)                  
         * 
         * zip file support based on 'zip.lib.php' of the phpMyAdmin project
         * official zip file format: http://www.pkware.com/documents/casestudies/APPNOTE.TXT
         *                            
        */
        private $source;  // dir of the unzipped opendocument file
        private $files   = array(); // array to store changed files
        private $datasec = array(); // array to store compressed data
        private $ctrl_dir = array(); // central directory (zip-file)
        private $eof_ctrl_dir = "\x50\x4b\x05\x06\x00\x00\x00\x00"; // end of central directory record (zip file)
        private $old_offset = 0; //last offset position (zip-file)
 
        private function unix2DosTime($unixtime = 0) {
        // converts an unix timestamp to a four byte DOS date and time format (date
        // in high two bytes, time in low two bytes allowing magnitude comparison).
                $timearray = ($unixtime == 0) ? getdate() : getdate($unixtime);
                if ($timearray['year'] < 1980) {
                        $timearray['year']    = 1980;
                        $timearray['mon']     = 1;
                        $timearray['mday']    = 1;
                        $timearray['hours']   = 0;
                        $timearray['minutes'] = 0;
                        $timearray['seconds'] = 0;
                }
                return (($timearray['year'] - 1980) << 25) | ($timearray['mon'] << 21) | ($timearray['mday'] << 16) |
                        ($timearray['hours'] << 11) | ($timearray['minutes'] << 5) | ($timearray['seconds'] >> 1);
        }
 
        private function zipAddFile($data, $name, $time = 0) {
        // adds "file" to archive
                $name     = str_replace('\\', '/', $name);
 
                $dtime    = dechex($this->unix2DosTime($time));
                $hexdtime = '\x' . $dtime[6] . $dtime[7]
                          . '\x' . $dtime[4] . $dtime[5]
                          . '\x' . $dtime[2] . $dtime[3]
                          . '\x' . $dtime[0] . $dtime[1];
                eval('$hexdtime = "' . $hexdtime . '";');
 
                $fr   = "\x50\x4b\x03\x04";
                $fr   .= "\x14\x00";            // ver needed to extract
                $fr   .= "\x00\x00";            // gen purpose bit flag
                $fr   .= "\x08\x00";            // compression method
                $fr   .= $hexdtime;             // last mod time and date
 
                // "local file header" segment
                $unc_len = strlen($data);
                $crc     = crc32($data);
                $zdata   = gzcompress($data);
                $zdata   = substr(substr($zdata, 0, strlen($zdata) - 4), 2); // fix crc bug
                $c_len   = strlen($zdata);
                $fr      .= pack('V', $crc);             // crc32
                $fr      .= pack('V', $c_len);           // compressed filesize
                $fr      .= pack('V', $unc_len);         // uncompressed filesize
                $fr      .= pack('v', strlen($name));    // length of filename
                $fr      .= pack('v', 0);                // extra field length
                $fr      .= $name;
 
                // "file data" segment
                $fr .= $zdata;
 
                // add this entry to array
                $this -> datasec[] = $fr;
 
                // now add to central directory record
                $cdrec = "\x50\x4b\x01\x02";
                $cdrec .= "\x00\x00";                // version made by
                $cdrec .= "\x14\x00";                // version needed to extract
                $cdrec .= "\x00\x00";                // gen purpose bit flag
                $cdrec .= "\x08\x00";                // compression method
                $cdrec .= $hexdtime;                 // last mod time & date
                $cdrec .= pack('V', $crc);           // crc32
                $cdrec .= pack('V', $c_len);         // compressed filesize
                $cdrec .= pack('V', $unc_len);       // uncompressed filesize
                $cdrec .= pack('v', strlen($name)); // length of filename
                $cdrec .= pack('v', 0);             // extra field length
                $cdrec .= pack('v', 0);             // file comment length
                $cdrec .= pack('v', 0);             // disk number start
                $cdrec .= pack('v', 0);             // internal file attributes
                $cdrec .= pack('V', 32);            // external file attributes - 'archive' bit set
 
                $cdrec .= pack('V', $this -> old_offset); // relative offset of local header
                $this -> old_offset += strlen($fr);
 
                $cdrec .= $name;
 
                // optional extra field, file comment goes here
                // save to central directory
                $this -> ctrl_dir[] = $cdrec;
        }
 
        private function zipDumpFile() {
        // dumps out zipfile
                $data    = implode('', $this -> datasec);
                $ctrldir = implode('', $this -> ctrl_dir);
 
                return
                    $data .
                    $ctrldir .
                    $this -> eof_ctrl_dir .
                    pack('v', sizeof($this -> ctrl_dir)) .  // total # of entries "on this disk"
                    pack('v', sizeof($this -> ctrl_dir)) .  // total # of entries overall
                    pack('V', strlen($ctrldir)) .           // size of central dir
                    pack('V', strlen($data)) .              // offset to start of central dir
                    "\x00\x00";                             // .zip file comment length
        } 
 
        private function zipAddDir($verzeichnis, $excludedFiles) {
        // adds a directory to zip file
                $handle =  opendir($verzeichnis); 
                while ($datei = readdir($handle)) { 
                        if ($datei != "." && $datei != ".." && !in_array($datei, $excludedFiles)) { 
                                if (is_dir($verzeichnis.$datei)) { 
                                        // ... if you want you can create empty directories here ...
                                        $this->zipAddDir($verzeichnis.$datei.'/', $excludedFiles); 
                                } else { 
                                        // is file:
                                        $this->zipAddFile(file_get_contents($verzeichnis.$datei), substr($verzeichnis.$datei,strlen($this->source)));
                                } 
                        }
                } 
                closedir($handle);
        }
 
        public function opendocument($source) {
                if ($source=='') throw new Exception('no source defined');
                if (!is_dir($source)) throw new Exception('source must be a directory with uncompressed opendocument files');
                if (!is_file($source.'mimetype')) throw new Exception('no mimetype file found in '.$source);
                $this   -> source = $source;
                $this->files['mimetype'] = file_get_contents($this->source.'mimetype');
        }
 
        public function get_file($filename, $overwrite = false) {
                $file = $this->source.$filename;
                if (is_file($file)) {
                        if (!array_key_exists($filename,$this->files) || $overwrite) {
                                $this->files[$filename] = file_get_contents($file);
                                return $this->files[$filename];
                        } 
                } else {
                        if (!array_key_exists($filename,$this->files)) {
                                throw new Exception('File "'.$file.'" not found');
                        } else {
                                return $this->files[$filename];
                        }
                }
        }
 
        public function set_file($content, $file) {
                $this->files[$file] = $content;
        }
 
        public function get_mime() {
                return $this->files['mimetype'];        
        }
 
        public function output() {
                $this->zipAddFile($this->files['mimetype'], 'mimetype'); // set mimetyp first
                $keys = array_keys($this->files);
                for ($i=0; $i<count($this->files); $i++) {
                        if ($keys[$i] != 'mimetype') {
                                $this -> zipAddFile($this->files[$keys[$i]],$keys[$i]);
                        }
                }
                $this->zipAddDir($this->source, $keys);
                return $this->zipDumpFile();
        }
}
?>
Feb 2 10

Gepunkteter Rahmen um Links

by dennis

… tauchen u.a. im Firefox auf wenn ein Link aktiv ist bzw. angeklickt wurde. So kann man den Rahmen entfernen:

a:active, a:focus { outline: none; }

dabei gilt zu beachten, dass dies als optischer Hinweis gedacht ist, wenn ein User per TAB-Taste o.ä. durch die Seite navigiert. Dieser Hinweis entfällt in diesem Fall.

Jan 21 10

Petition: Datenschutz – Aufhebung des elektronischen Entgeltnachweises (ELENA) vom 20.12.2009

by dennis

Zum 1. Januar 2010 wurde der Elektronische Entgeltnachweis (ELENA) eingeführt. Der Chaos Computer Club (CCC) fordert ein Ende der Datenanhäufung auf Vorrat und ruft zur Unterzeichnung einer Petition an den Deutschen Bundestag auf.

zur Petition

Jan 6 10

Typografie im Internet

by dennis

Hier mal eine kleine Übersicht über wichtige Sonderzeichen, Normen etc…

Wichtige Zeichen:

Zeichen DEC HTML Bemerkung
0132 &bdquo;  
0147 &ldquo;  
» 0187 &raquo;  
« 0171 &laquo;  
0133 &hellip;  
7 &bull;  
0150 &ndash; Halbgeviertstrich (Gedankenstrich)
× 0215 &times; Typografisches Malzeichen
8722 &minus; Typografisches Minuszeichen
÷ 0247 &divide; Divisionszeichen nach Johann Rahn
© 0169 &copy;  
® 0174 &reg;  
< 060 &lt;  
> 062 &gt;  
& 038 &amp;  
0128 &euro;  
0146 &rsquo; Typografischer Apostroph

Auszeichnungen

Korrekte Auszeichnung: (&bdquo; / 0132)„text“(&ldquo; / 0147)
alternativ: (&raquo; / 0187)»text«(&laquo; / 0171)

Apostroph

Typografisch korrekt: ’ (&rsquo; / 0146)
Ersatzzeichen: ' (&#39; / 039)
Anwendung: Der Apostroph ersetzt den Buchstaben „e“ und in seltenen Fällen den Buchstaben „i“.

Geldbeträge

Mit Halbgeviertstrich: 15,–(&ndash; / 0150) €

Telefonnummern

Beispiel nach DIN 5008: 0123 456789

Dez 30 09

Online-Unterschriftensammlung gegen Oracles Kauf von MySQL

by dennis

MySQL-Gründer Michael Widenius hat eine Kampagne gegen die Übernahme von MySQL durch Oracle gestartet. Die Übergabe der Unterschriften soll am 4. Januar 2010 erfolgen. Weitere Informationen und Unterschriftensammlung hier:

http://www.helpmysql.org/de/

Dez 28 09

PHP: Array rekursiv durchlaufen

by dennis

Um zum Beispiel die Funktion htmlentities auf ein Array rekursiv anzuwenden kann man wie folgt vorgehen:

1. Eine neue (rekursive) Funktion arr_htmlentities erstellen:

        function arr_htmlentities($arr) {
                foreach ($arr as $key=>$value) {
                        if (!is_array($arr[$key])) {
                                $arr[$key] = htmlentities($arr[$key]);
                        } else {
                                $arr[$key] = arr_htmlentities($arr[$key]);
                        }
                }
                return $arr;
        }

2. Die neue Funktion für das array $_POST (z.B. Eingaben aus einem Kontaktformular) aufrufen:

$userInput = arr_htmlentities($_POST);
 
// ausgabe:
print_r($userInput);