Snippets

tleilax

be forever curious
ID: 27936
L
20 April 2006
1.845
184
Moinsen,

in Absprache mit theHacker mache ich mal diesen Thread auf, der dazu gedacht ist, interessante oder nützliche Snippets (also kleine Codefetzen oder Funktionen) zu posten.

Ich werde hier an dieser Stelle eine Übersicht pflegen, welche Snippets vorhanden sind.

Regeln:
  • In diesem Thread sind bitte keine Diskussionen zu halten. Es sollen lediglich die Snippets zu finden sein. Für Diskussionen gibt einen parallelen Thread, der dafür genutzt werden sollte.
  • Bei dem Snippet sollte eine kleine Beschreibung dabei sein.
  • Bitte gebt bei den Snippetposts auch einen Titel an, den ich hier in der Übersicht dann übernehmen kann.
  • Der Übersichtlichkeit halber würde ich es begrüssen, wenn bei den Posts hier im Thread auf die Signatur verzichtet wird.
  • To be completed...

PHP
MySQL
Javascript
Ruby (on Rails)
Delphi
 
Zuletzt bearbeitet:
[PHP] Umrechnung von dezimalen Längen-/Breitengraden in sexagesimale und umgekehrt

Diese Funktionen dienen der Umrechnung von dezimalen Werten in ihre analoge sexagesimale Darstellung und ungekehrt.

Das Sexagesimalsystem ist das bei Koordinaten üblicherweise verwendete Zahlensystem auf Basis von 60. Die Angaben sind dann in Stunden, Minuten und Sekunden.

Beispiel:

50.12944444 - Dezimal
50° 07' 46" - Sexagesimal​

PHP:
  /** Rechnet einen dezimalen Wert in den entsprechen sexagesimalen Wert um
   * Eingabe: $decimal - Der dezimale Wert
   * Ausgabe: Der sexagesimale Wert
   **************************************************************************/
  function dec2sex($decimal) {
    if (!is_numeric($decimal))
      return false;

    $h = floor($decimal);
    $decimal = ($decimal-$h)*60;
    $m = floor($decimal);
    $decimal = ($decimal-$m)*60;
    $s = round($decimal);
    return sprintf('%02d° %02d\' %02d"', $h, $m, $s);
  }

  /** Rechnet einen sexagesimalen Wert in den entsprechen dezimalen Wert um
   * Eingabe: $decimal - Der sexagesimale Wert
   * Ausgabe: Der dezimale Wert
   **************************************************************************/
  function sex2dec($sexagesimal) {
    if (!preg_match('/^(\d+)\D+(\d{1,2})\D+(\d{1,2})\D+$/', $sexagesimal, $matches))
      return false;

    return $matches[1]+($matches[2]+$matches[3]/60)/60;
  }
 
Zuletzt bearbeitet:
[PHP] file()-Alternative bei allow_url_fopen = off

Da ein file() auf externe URLs auf vielen Servern aufgrund der Einstellung allow_url_fopen = off nicht mehr funktioniert, habe ich diesen Workaround geschrieben.

Die Funktionsweise ist exakt analog zu file().

PHP:
<?php
  /** file()-Alternative bei allow_url_fopen = off
    * Eingabe: $url - Die auszulesende URL.
    * Rückgabe: Array, das alle Zeilen der auszulesenden URL enthält.
    *********************************************/
  function socketfile($url) {
    // URL zerlegen
    $parsedurl = @parse_url($url);
    // Host ermitteln, ungültigen Aufruf abfangen
    if (empty($parsedurl['host']))
      return null;
    $host = $parsedurl['host'];
    // Pfadangabe ermitteln
    if (empty($parsedurl['path']))
      $documentpath = '/';
    else
      $documentpath = $parsedurl['path'];
    // Parameter ermitteln
    if (!empty($parsedurl['query']))
      $documentpath .= '?'.$parsedurl['query'];
    // Port ermitteln
    $port = empty($parsedurl['port'])?80:$parsedurl['port'];
    // Socket öffnen
    $fp = fsockopen ($host, $port, $errno, $errstr, 30);
    if (!$fp)
      return null;
    // Request senden
    fputs ($fp, "GET {$documentpath} HTTP/1.0\r\nHost: {$host}\r\n\r\n");
    // Header auslesen und verwerfen
    do {
      $line = chop(fgets($fp));
    } while (!empty($line) and !feof($fp));
    // Daten auslesen
    $result = Array();
    while (!feof($fp)) {
      $result[] = fgets($fp);
    }
    // Socket schliessen
    fclose($fp);
    // Ergebnis-Array zurückgeben
    return $result;
  }
 
Zuletzt bearbeitet:
Da man leider noch bei sehr vielen Scripten die Möglichkeit findet, andere Scripts über den "Variablen Include" einzuschleusen, poste ich hier mal eine kleine Funktion / einen Lösungsvorschlag, wie man dieses Problem lösen kann.

Nun wird bei unten stehendem Beispiel z.B. 'https://boeserhacker.example.org' nicht als gültig angesehen.

PHP:
/* Testet eine Seite $page auf ihre Gueltigkeit  */
/* Ist $page nicht gueltig, wird $default zurückgeliefert */
function test_page($page,$default) {
   // Gueltige Seiten
   $pages = array('start','aboutme');

   // Wenn $page gueltig, dann $page zurueckgeben
   if(in_array($page,$pages)) return $page;
   // Ansonsten $default zurueckgeben
   return $default;
}
oder:

PHP:
$pages = array (
'start' => './index.inc.php',
'about' => './about.inc.php'
); # eine Zuordnung von Aliasen zu ihren Dateien
#und dann 
if(isset($pages[$_GET['query']])) include($pages[$_GET['query']]);
else include('default.inc.php');
 
Zuletzt bearbeitet:
[MySQL] Automatisches "Rang ermitteln" / Aufsummieren

Es gibt ja Situationen, an denen man bspw die Position einer Zeile innerhalb des Resultsets bestimmen möchte ohne dies in der verwendeten Programmiersprache zu tun.

In diesem Fall sind die User-Defined Variables ungemein praktisch, da sie genau dies ermöglichen.

Eine Rangfolge wäre beispielsweise über dieses Statement realisierbar:
Code:
[COLOR="Purple"]SET [/COLOR][COLOR="DarkRed"]@rank [/COLOR][COLOR="Magenta"]=[/COLOR] [COLOR="Teal"]0[/COLOR][COLOR="Magenta"];[/COLOR]
[COLOR="Purple"]SELECT [/COLOR][COLOR="DarkRed"]@rank[/COLOR] [COLOR="Magenta"]:= [/COLOR][COLOR="DarkRed"]@rank[/COLOR] [COLOR="Magenta"]+[/COLOR] [COLOR="Teal"]1[/COLOR] [COLOR="Purple"]AS [/COLOR]rank[COLOR="Magenta"], [/COLOR]column
[COLOR="Purple"]FROM [/COLOR]table
[COLOR="Purple"]ORDER BY [/COLOR]foobar [COLOR="Purple"]DESC[/COLOR]
In Situationen, wo man kein mehrbefehliges Query absenden kann/will, wäre folgende (zum obigen äquivalente) Query angebracht:
Code:
[COLOR="Purple"]SELECT IF[/COLOR] [COLOR="Magenta"]([/COLOR][COLOR="DarkRed"]@rank[/COLOR][COLOR="Magenta"], [/COLOR][COLOR="DarkRed"]@rank[/COLOR][COLOR="Magenta"] :=[/COLOR] [COLOR="DarkRed"]@rank[/COLOR] [COLOR="Magenta"]+ [/COLOR][COLOR="Teal"]1[/COLOR][COLOR="Magenta"], [/COLOR][COLOR="DarkRed"]@rank[/COLOR][COLOR="Magenta"]:=[/COLOR][COLOR="Teal"]1[/COLOR][COLOR="Magenta"])[/COLOR] [COLOR="Purple"]AS [/COLOR]rank[COLOR="Magenta"],[/COLOR] column
[COLOR="Purple"]FROM [/COLOR]table
[COLOR="Purple"]ORDER BY [/COLOR]foobar [COLOR="Purple"]DESC[/COLOR]
Aber auch in Situationen, wo man etwa die bisherigen Summe einer Spalte bis zur aktuellen Spalte braucht, ist mit den User-Defined Variables umsetzbar:
Code:
[COLOR="DarkRed"]@sum[/COLOR][COLOR="Magenta"] =[/COLOR] [COLOR="Teal"]0[/COLOR][COLOR="Magenta"];[/COLOR]
[COLOR="Purple"]SELECT [/COLOR][COLOR="DarkRed"]@sum[/COLOR] [COLOR="Magenta"]:=[/COLOR] [COLOR="DarkRed"]@sum[/COLOR] [COLOR="Magenta"]+[/COLOR] column [COLOR="Purple"]AS [/COLOR]currentsum, anothercolumn
[COLOR="Purple"]FROM [/COLOR]table
 
PHP
Manchmal kann es für ein umfangreiches und komplexes Programm sehr nützlich sein, sogenannte "Hookpoints" zu ermöglichen. Damit werden an vorher im Programmcode festgelegten Stellen variable Code-Stücke ausgeführt, was besonders für Updates und Erweiterungen sehr nützlich sein kann.

Dazu eine Klasse, die ich - leicht abgeändert - auch selbst einsetze:
PHP:
// class "Hook" by raven, 2006

/**
 * hook handler class
 *
 */
class Hook {
    /**
     * hook array
     *
     * @var array
     */
    var $hooks = array();
    
    /**
     * constructor
     *
     * @return Hook
     */
    function Hook(){
        $query = mysql_query("SELECT var_name, var_value FROM hooksconfig");
        while($config = mysql_fetch_assoc($query)) $config_vars[$config['var_name']] = $config['var_value'];
        $this->hooks = (is_array(unserialize($config_vars['hook_cache'])) ? unserialize($config_vars['hook_cache']) : array());
        return true;
    }
    
    /**
     * fetches hook data from cache and executes it
     *
     * @param string $hook hook ident
     * @return bool
     */
    function HookPoint($hook){
        if(!preg_match("/^[0-9a-z]{3,20}$/i", $hook)) return false;
        if(!isset($this->hooks["$hook"])) return false;
        $hookcode = $this->hooks["$hook"];
        
        return ($hookcode) ? eval($hookcode) : false;
    }
    
    /**
     * fetches hook data into cache
     *
     * @return bool
     */
    function HookCache(){
        $hooks_cache = array();
        $query = mysql_query("SELECT hookpoint, hookcode FROM hooks WHERE hookstatus=1");
        while($result_hooks = mysql_fetch_assoc($query)){
            $hookpoint = $result_hooks['hookpoint'];
            $hookcode = $result_hooks['hookcode'];
            
            if(!isset($hooks_cache["$hookpoint"])) $hooks_cache["$hookpoint"] = "";
            $hooks_cache["$hookpoint"] .= $hookcode . "\n";
        }
        
        $this->hooks = $hooks_cache;
        $hooks_cache = serialize($hooks_cache);
        
        return (mysql_query("UPDATE hooksconfig SET var_value='".addslashes($hooks_cache)."' WHERE var_name='hook_cache'") ? true : false);
    }
}
Einzige Voraussetzung ist, wenn ich grad nicht irgendwas überseh, eine bestehende DB-Verbindung (mysql)

Datenbankstruktur:
PHP:
CREATE TABLE `hooks` (
  `hookid` int(11) unsigned NOT NULL auto_increment,
  `hooktitle` varchar(50) NOT NULL,
  `hookdesc` varchar(255) NOT NULL,
  `hookcode` text NOT NULL,
  `hookpoint` varchar(20) NOT NULL,
  `hookstatus` tinyint(1) NOT NULL default '0',
  PRIMARY KEY  (`hookid`)
) ENGINE=MyISAM;

CREATE TABLE `hooksconfig` (
  `varid` int(11) unsigned NOT NULL auto_increment,
  `var_name` varchar(20) NOT NULL,
  `var_value` text NOT NULL,
  PRIMARY KEY  (`varid`)
) ENGINE=MyISAM;

INSERT INTO `hooksconfig` (`var_name`) VALUES('hook_cache');
Einbauen kann man das dann so:
PHP:
/* Datenbank-Verbindung: MySQL */
require("hook.inc.php");
$Hook = new Hook();

print("blub");
$Hook->HookPoint("post_blub");
print("bla");
Hoffe, dass das für irgendwen nützlich ist ... habe die Klasse jetzt ein wenig anpassen müssen, weil sie in ein Skript von mir eingebaut war, wenn es irgendwelche Fehler geben sollte, einfach schreien :)

P.S.: Nach jedem einfügen eines Codestücks in die Tabelle "hooks" muss Hook::HookCache einmal ausgeführt werden - erst dann werden die Änderungen übernommen.
 
Zuletzt bearbeitet:
[PHP/MySql] sichere Querys

jeder kennt es und jeder hört davon: SQL-Injection
Jede Variable zu sichern bläht den Code sehr auf, deshalb nutze ich folgende Funktion:
PHP:
  function db_query($query){
    $args=func_get_args();
    $vargs=array();
    for($i=1;$i<func_num_args();$i++) {
      if(get_magic_quotes_gpc()) {
        $args[$i]=stripslashes($args[$i]);
      }
      $vargs[]=mysql_real_escape_string($args[$i]);
    }
    $query=vsprintf($query,$vargs);
    $res=mysql_query($query);
    return($res);
  }
  db_query('SELECT * FROM %s WHERE `%s`=%d','user','klammid',93995);
MySql-Querys werden nach dem Muster db_query(MySql-String, Variablen) ausgeführt, dabei gibt es keine Begrenzung von Variablen. Die Daten werden per vsprintf() eingetragen und dementsprechend müssen die Strings auch formatiert werden.
Ebenfalls wird es zu keinen Komplikationen kommen, sollte Magic Quotes aktiviert sein.
Solltet ihr Querys machen wollen in denen ein % benötigt wird (zb. für like) muss dieses per % escaped werden, also muss %% geschrieben werden.
Macht eure Anwendungen sicherer uns nutzt SQL-Injection sichere Querys ;)
 
[PHP] Ein Counter für echte Besucher auf MySQL-Basis

Ein Counter in PHP auf MySQL-Basis:

Dieses Stück Code kann man mit oder ohne Ausgabe in ziemlich jede Seite einbauen um die Anzahl der Besucher festzustellen. Bei mehreren Seiten sollte man mehrere Tabellen anlegen, es sei denn man will die Summe der Besucher haben.

PHP:
$_VAR=array(); # braucht man nicht unbedingt und wenn dann am Anfang des Scripts

#Konfigurationsteil
$_VAR['countertabelle'] = 'count'; # Name der Countertabelle
$_VAR['counteroffset'] = 14587; # Zahl die zum Counter hinzugezählt wird ;)
$_VAR['counterdelay'] = 30*60; # Zeit nach der ein Besucher erneut als
Besucher gezählt wird (in Sekunden)
$_VAR['isbot'] = FALSE;

PHP:
# Optional: Erkennung von Suchmaschinen aufgrund des übermittelten User-Agent:
# Man erwischt damit die meisten/wichtigsten Bots aber nicht alle.
$_Bots_UA = array(
'Google', # Google
'Lycos', #Lycos
'Scooter', # Altavista + Yahoo
'slurp', # Yahoo
'Crawler', #Yahoo
'Yahoo', # Yahoo
'Infoseek', # Infoseek
'archiver',
'spider',
'browser',
'bot',
'MarkWatch',
'flunky',
'Teoma'
);
# Wenn kein User-Agent angegeben wird ist es möglicherweise ein Bot, ein üblicher Browser ist es jedenfalls nicht ...
if($_SERVER['HTTP_USER_AGENT'] != '')
{
    foreach($_Bots_UA as $val)
    {
        if(!$_VAR['isbot'] && preg_match('/'.$val.'/i', $_SERVER['HTTP_USER_AGENT']) && !preg_match('/^Mozilla/', $_SERVER['HTTP_USER_AGENT'])) $_VAR['isbot'] = TRUE;
    }
}
else
{
    $_VAR['isbot'] = TRUE;
}
Man könnte schauen ob bestimmte Suchmaschinen, die man sicherlich nicht unbedingt mitzählen will, auf der Seite rumspidern. Sicherer aber aufwändiger wäre es die Bots anhand ihrer IP-Adressen zu erkennen.
Der Yahoo-Bot (?) schickt bspw. auch mal den User-Agent 'Mozilla/4.0 (compatible; MSIE 5.0; Windows NT)', was aber auch ein gültiger User-Agent für den IE ist oder es surft ein Yahoo Mitarbeiter am Spider-Server. ;)

PHP:
# Aufruf der Funktion, bzw. Ausgabe des Counters an einer beliebigen Stelle
echo doctraxs_besucher_counter($_VAR);

# So gibts keine Ausgabe
doctraxs_besucher_counter($_VAR);
Eine Ausgabe wäre etwa auf der Hauptseite sinnvoll auf Unterseiten jedoch wäre eine Ausgabe wohl eher deplatziert, und so kann man trotz dem die Besucher der Unterseiten in die Zählung mit ein beziehen.

PHP:
function doctraxs_besucher_counter($_VAR)
{
    # Erstmal die Tabelle anlegen, sofern sie nicht existiert
    # Diese Anweisung sollte man wegen der Performance kommentieren wenn die Tabelle angelegt ist
    mysql_query('CREATE TABLE IF NOT EXISTS DocTraxs_counter_'.$_VAR['countertabelle'].' (
    `id` int(12) NOT NULL auto_increment,
    `ip` varchar(15) NOT NULL,
    `timestamp` int(15) NOT NULL,
    UNIQUE KEY `id` (`id`)
    );');

    # Prüfung ob die IP-Adresse überhaupt zu zählen ist
    if(preg_match('/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/', $_SERVER['REMOTE_ADDR'], $tmp) &&
    $tmp[1]>=1 && $tmp[1]<=255 &&
    $tmp[2]>=0 && $tmp[2]<=255 &&
    $tmp[3]>=0 && $tmp[3]<=255 &&
    $tmp[4]>=1 && $tmp[4]<255 &&
    !$_VAR['isbot'])
    {
        # Wenn die IP-Adresse nicht in der Tabelle ist
        # und nicht länger als $_VAR['counterdelay'] nicht aktiv auf der Seite war
        # wird eine neue Zeile (Heisst ein echter Besucher ist auf der Seite) angelegt,
        # ansonsten wird nur der timestamp aktualisiert.
        # => Hier wird also gezählt.
        if(!mysql_fetch_row(mysql_query('SELECT id from DocTraxs_counter_'.$_VAR['countertabelle'].' WHERE ip="'.$_SERVER['REMOTE_ADDR'].'" AND timestamp > '.(time()-$_VAR['counterdelay']))))
        {
            mysql_query('INSERT INTO DocTraxs_counter_'.$_VAR['countertabelle'].' SET ip="'.$_SERVER['REMOTE_ADDR'].'",timestamp='.time());
        }
        else
        {
            mysql_query('UPDATE DocTraxs_counter_'.$_VAR['countertabelle'].' SET timestamp='.time().' WHERE ip="'.$_SERVER['REMOTE_ADDR'].'"');
        }
        # nun wird der Maximalwert von id ausgelesen
        # und gleichzeitig alte Einträge gelöscht um die Tabelle schön klein zu halten
        # => Hier wird also die Besucherzahl aus der Tabelle ausgelesen.
        if($countrow = mysql_fetch_row(mysql_query('SELECT max(id) FROM DocTraxs_counter_'.$_VAR['countertabelle'])))
        {
            mysql_query('DELETE FROM DocTraxs_counter_'.$_VAR['countertabelle'].' WHERE id<'.$countrow[0].' AND timestamp<='.(time()-$_VAR['counterdelay']));
            return '<table align="center" border="1" cellpadding="2" cellspacing="2"><tr><td>'.
                    ($countrow[0]+$_VAR['counteroffset']).
                    '</td></tr></table>'; 
        }
    }
}
Changes:
Als Funktion sieht das ganze übersichtlicher aus.
Ich habe noch ein statisches Prefix für die Tabelle hinzugefügt um die Counter-Tabellen von den übrigen abzugrenzen.
Man kann die Funktion aufrufen ohne vorher extra eine Tabelle anzulegen.
Mehr unnütze Klammerungen => noch übersichtlicher. :mrgreen:
 
Zuletzt bearbeitet:
[php] Altercheck mit Deutschem Personalausweis

Alter mit Hilfe des Personalausweises überprüfen
Mit dieser Funktion könnt ihr die Personalausweis-Nummer (Personalausweise von Deutschland) nutzen,
um eine Alterkontrolle einzurichten. Der Code überprüft dabei nicht nur das Alter sondern auch die
eigentliche Richtigkeit der Nummer anhand von 4 Prüfziffern.

Funktion:
PHP:
function check_age_by_perso($perso,$age=18){
    if(!function_exists("pruefziffer")){
        function pruefziffer($zahl,$suf=TRUE){
            $multi = array(7,3,1);
            $h = 0;
            for($i=0; $i<strlen($zahl); $i++){
                $g = $multi[($i%3)];
                $h = $h + $zahl[$i]*$g;
            }
            settype($h, "string");
            if($suf){
                $pruefziffer = $zahl.$h[strlen($h)-1];
            }else{
                $pruefziffer = $h[strlen($h)-1];
            }
        return $pruefziffer;
        }
    }
    if (preg_match('/^([0-9]{10})([A-Z]{1}) ([0-9]{7}) ([0-9]{7}) ([0-9]{1})$/si',$perso)){
        $parts = explode(" ", $perso);
        $p1 = pruefziffer(substr($parts[0], 0, strlen($parts[0])-2));
        $p2 = pruefziffer(substr($parts[1], 0, strlen($parts[1])-1));
        $p3 = pruefziffer(substr($parts[2], 0, strlen($parts[2])-1));
        $st = $parts[0][strlen($parts[0])-1];
        $p4 = pruefziffer($p1.$p2.$p3, FALSE);
        $new_perso = $p1.$st." ".$p2." ".$p3." ".$p4;
        if($new_perso == $perso){
            $geb = substr($parts[1], 0, 6);
            $y = "19".$geb[0].$geb[1];
            $m = $geb[2].$geb[3];
            $d = $geb[4].$geb[5];
            $seconds = mktime(0,0,0,$m,$d,$y);
            $r_age = date("Y", time() - $seconds)  - 1970;
            if($r_age >= $age) {
                return TRUE;
            }
        }
    }
return FALSE;
}
Aufruf der Funktion:
Wir geben hier mit Absicht keine gültige Perso-Nummer für eine volljährige Person an
PHP:
if(check_age_by_perso('8739781102D 8603153 0701019 2')){
    echo 'Über 18<br />';
}else{
    echo 'nicht über 18 oder ungültige Perso-Nummer<br />';
}

Hinweis zur verwendung:
Ich möchte darauf hinweisen das die Alterskontrolle durch die Prüfung der Ausweisnummer laut dem Deutschen Jugendschutzgesetzt im Internet nicht mehr ausreichend ist.
Mehr dazu hier: heise.de
 
Zuletzt bearbeitet:
[PHP] Deutsches Datum mit date()-Formatparametern

Das Problem mit der date()-Funktion von PHP ist es, dass Monats- und Wochentagsnamen englisch ausgegeben werden. Die Alternative mit setlocale() und strftime() hat den Nachteil, dass einige Parameter nicht unterstützt werden bzw. es keine Parameter für eine gewünschte Ausgabe (z.B. Stunde oder Tag ohne führende Null) gibt.

Die nachfolgende Funktion wird analog zu date() verwendet, gibt aber deutsche Monats- und Wochentagsnamen aus.
PHP:
function mydate($format,$time=null)
{
  $mydate=date($format,($time!==null) ? $time : time());
  
  $replace=array('January' => 'Januar',
                 'February' => 'Februar',
                 'March' => 'März',
              /* 'April' => 'April', */
                 'May' => 'Mai',
                 'June' => 'Juni',
                 'July' => 'Juli',
              /* 'August' => 'August',
                 'September' => 'September', */
                 'October' => 'Oktober',
              /* 'November' => 'November', */
                 'December' => 'Dezember',

                 'Monday' => 'Montag',
                 'Tuesday' => 'Dienstag',
                 'Wednesday' => 'Mittwoch',
                 'Thursday' => 'Donnerstag',
                 'Friday' => 'Freitag',
                 'Saturday' => 'Samstag',
                 'Sunday' => 'Sonntag',

              /* 'Jan' => 'Jan',
                 'Feb' => 'Feb', */
                 'Mar' => 'Mär',
              /* 'Apr' => 'Apr', */
                 'May' => 'Mai',
              /* 'Jun' => 'Jun',
                 'Jul' => 'Jul',
                 'Aug' => 'Aug',
                 'Sep' => 'Sep', */
                 'Oct' => 'Okt',
              /* 'Nov' => 'Nov', */
                 'Dec' => 'Dez',

                 'Mon' => 'Mo',
                 'Tue' => 'Di',
                 'Wed' => 'Mi',
                 'Thu' => 'Do',
                 'Fri' => 'Fr',
                 'Sat' => 'Sa',
                 'Sun' => 'So');
  
  return strtr($mydate,$replace);
}
Beispielaufruf:
PHP:
echo mydate('l, j. F Y G:i:s \U\h\r',1157774235);
// Ausgabe:
// Samstag, 9. September 2006 5:57:15 Uhr
 
Zuletzt bearbeitet:
Manchmal kann es äußerst nützlich sein, eine E-Mail Adresse auf ihre formale Gültigkeit zu überprüfen. In PHP funktioniert das mit einem vergleichsweise relativ einfachen perl regexp.

PHP:
/**
 * checks if an email is valid
 *
 * @param string $mail
 * @return bool
 */
function valid_mail($mail){
    return preg_match("/^[a-z0-9]+([_\\.-][a-z0-9]+)*@([a-z0-9]+([\.-][a-z0-9]+)*)+\\.[a-z]{2,}$/i", $mail);
}
 
[PHP] Simple XML-Erstellungsklasse

Mancherorts wird es ja immer beliebter, beim Export statt CSV XML zu benutzen. Ich habe vor kurzem für so einen Zweck die folgende Klasse geschrieben, die aus übergebenen, 1-dimensionalen Arrays (oder auch Arrays aus 1-dimensionalen Arrays *g*) ein XML-File erzeugt.
PHP:
<?php
 /**
  * XMLExport - Erzeugt XML-Dokumente aus Arrays
  *
  * @author	Jan-Hendrik Willms <[email protected]>
  * @version	22.09.2006
  */

  class XMLExport {
    // Der Name des Wurzelknotens
    var $rootName = null;
    // Der Name der einzelnen Zeilenknoten
    var $rowName = null;
    // Das benutzte Filehandle
    var $file_handle = null;
    // Entities kodieren?
    var $encode_entities;
    // Array, um doppelte Einträge zu verhindern
    var $writtenRows = null;

    /**
     * Konstruktor
     *
     * @param String $filename Name der Ausgabedatei
     * @param String Name des Wurzelknotens (default: root)
     * @param String Name der Zeilenknoten (default: row)
     * @param boolean Entities kodieren
     */
    function XMLExport($filename, $rootName='root', $rowName='row', $encode_entities=true) {
      $this->rootName = $rootName;
      $this->rowName = $rowName;
      $this->encode_entities = $encode_entities;

      $this->writtenRows = Array();

      $this->file_handle = fopen($filename, 'w+');
      fputs($this->file_handle, '<?xml version="1.0" encoding="iso-8859-1"?>'."\n");
      fputs($this->file_handle, '<'.$this->rootName.'>'."\n");
    }

    /**
     * Speichert eine als Array übergebene Zeile in dem XML-File
     *
     * @param Array $rowData Die Daten der Zeile
     */
    function saveRow($rowData) {
      $data = '';
      foreach ($rowData as $key=>$value) {
        $data.=$key.$value;
      }
      $hash = md5($data);
      if (!empty($this->writtenRows[$hash]))
        return;
      $this->writtenRows[$hash] = true;
      fputs($this->file_handle, '  <'.$this->rowName.'>'."\n");
      foreach ($rowData as $key=>$value) {
        if ($this->encode_entities) {
          $value = $this->xmlentities($value);
        }
        fputs($this->file_handle, '    <'.$key.'>'.$value.'</'.$key.'>'."\n");
      }
      fputs($this->file_handle, '  </'.$this->rowName.'>'."\n");
      fflush($this->file_handle);
    }

    /**
     * Speichert mehrere als Array übergebene Zeilen in dem XML-File
     *
     * @param Array $rowsData Die Zeilen als Array
     * @see saveRow
     */
    function saveRows($rowsData) {
      foreach ($rowsData as $row) {
        $this->saveRow($row);
      }
    }

    /**
     * Ersetzt bestimmte Zeichen durch ihre XML-Entitäten
     *
     * @param String $string Die Zeichenkette, in der die Entitäten ersetzt werden sollen
     * @return String Der bearbeitete String
     */
    function xmlentities($string) {
      return str_replace (array('&', '"', "'", '<', '>'), array('&', '"', '&apos;', '<', '>'), $string);
    }

    /**
     * Schliesst das XML-File
     */
    function close() {
      fputs($this->file_handle, '</'.$this->rootName.'>'."\n");
      fclose($this->file_handle);
    }
  }
?>
Beispiel zur Benutzung (zugegebenermassen leicht unsinnig, aber es verdeutlich die Benutzung):
PHP:
require('XMLExport.class.php');
$xmlfile = new XMLExport('export.xml');

$row = Array('foo'=>'bar', 'bar'=>'foo');
$xmlfile->saveRow( $row );

$rows = Array();
$rows[] = Array('whatever'=>'may be');
$rows[] = Array('answer'=>42, 'me'=>'kinda tired', 'reason'=>'who knows?');
$xmlfile->saveRows($rows);

$xmlfile->close();
Ausgabe:
Code:
<?xml version="1.0" encoding="iso-8859-1"?>
<root>
  <row>
    <foo>bar</foo>
    <bar>foo</bar>
  </row>
  <row>
    <whatever>may be</whatever>
  </row>
  <row>
    <answer>42</answer>
    <me>kinda tired</me>
    <reason>who knows&apos;</reason>
  </row>
</root>
 
[mysql]

eintrag vorhanden oder nicht? umständlich ist es häufig festzustellen, ob ein eintrag in einer tabelle mit einem entsprechenden schlüssel schon existiert. zuerst ein SELECT und dann eine entscheidung, ob ein INSERT oder ein UPDATE verwendet werden soll (zu sehen z.b. bei doctraxs_besucher_counter von DocTrax weiter oben).

PHP:
erst ein select:
SELECT id from DocTraxs_counter_'.$_VAR['countertabelle'].' WHERE ip="'.$_SERVER['REMOTE_ADDR'].'" AND timestamp > '.(time()-$_VAR['counterdelay'])

dann insert: 
INSERT INTO DocTraxs_counter_'.$_VAR['countertabelle'].' SET ip="'.$_SERVER['REMOTE_ADDR'].'",timestamp='.time());

oder update:
UPDATE DocTraxs_counter_'.$_VAR['countertabelle'].' SET timestamp='.time().' WHERE ip="'.$_SERVER['REMOTE_ADDR'].'"'
dabei gibt es doch eine mysql-anweisung, die das alles in nur einem schritt ausführt:

PHP:
INSERT INTO DocTraxs_counter_{$_VAR['countertabelle']} (ip,time) VALUES ('{$_SERVER['REMOTE_ADDR']}', NOW()) ON DUPLICATE KEY UPDATE time=NOW()
 
Zuletzt bearbeitet:
[MYSQL] und IP-Adressen in Tabellen

viele tabellen sehen für eine IP ein 15-stelliges varchar-feld vor. warum??

um eine ip-adresse in einer tabelle zu speichern benötigt man lediglich eine unsigned int(10)-spalte. diese füllt man man mit dem binären äquivalent der adresse. die funktion dafür heisst INET_ATON():

PHP:
INSERT INTO table (ip) VALUES ( INET_ATON('123.456.789.123')
was bringt uns das, ausser dass es komisch aussieht? ganze einfach: die ip wird als eine zahl gespeichert, die man zum beispiel ganz simpel z.b. für abfragen nach einer ip-range benutzen kann:

PHP:
SELECT * FROM table WHERE ip>INET_ATON('111.222.333.0') AND ip<INET_ATON('111.222.333.100')
um die ip-adresse wieder in eine "lesbare" anzeige zurück zu verwandeln benutzt man die umkehrfunktion: INET_NTOA();

PHP:
SELECT INET_NTOA(ip) FROM table WHERE 1
 
Zuletzt bearbeitet:
[MYSQL] - ein paar regeln

* INSERT *
ein insert-befehl enthält KEINEN "SET"-befehl

falsch:
INSERT INTO table SET field1=val1,field2=val2,field3=val3

richtig:
INSERT INTO table (field1,field2,field3) VALUES (val1,val2,val3)

die set-syntax funktioniert zwar, ist aber FALSCH und wurde nur aus kompatibilitätsgründen (historisch bedingt) zu update eingeführt.

* LIMIT 1 *
an jeden sicheren query gehört ein LIMIT. ganz egal, ob man etwas limitieren möchten, oder auch nicht. das hat nicht nur logische gründe, die sich auf den aufbau eines query beziehen, sondern auch rein praktische.

beispiel: irgendein hacker hat es vielleicht geschafft eure sql-anweisung aus einer seite zu injecten und schafft es damit, folgenden query zu erzeugen (hackerinjection ist fett):

DELETE * FROM user WHERE userID=123456 or userID>0

in diesem fall wurde einfach die variable userID, die ursprünglich "123456" enthielt umgeschrieben und enthält jetzt "123456 or userID>0" ... das bringt fatale folgen mit sich. wenn ihr webbetreier seid und kein backup parat habt, dann ist in einem solchen fall die seite zum tode verurteilt.

mit einer LIMIT-anweisung wäre so etwas nicht passiert:

DELETE * FROM user WHERE userID=123456 or userID>0 LIMIT 1

damit wäre der schlimmste der fälle nicht auf die gesamte tabelle angewendet worden, sondern nur auf einen einzigen datensatz beschränkt.

* SELECT * FROM table *
"benutze niemals einen stern-query" ... diesen satz sollte sich jeder, der mit mysql arbeitet sofort hinter die löffel schreiben. schön, wenn du im kopf hast, welche felder die tabelle hat, aber was ist, wenn du die seite verkaufst und dein nachfolger etwas ändern möchte? ein griff und das suchen beginn.
 
[PHP] automatische fakebanner-generierung

das ist grad als kleine funktion bei der arbeit abgefallen, vielleicht interessierts?

man nehme ein buntes bildchen

und benutze dann folgende funktion:

PHP:
function createFakeBanner( $file, $source, $w=468, $h=60 ) {
  $src  = ImageCreateFromGIF( $source );
  $px   = rand( 0, ImagesX($src)-$w );
  $py   = rand( 0, ImagesY($src)-$h );
  $img  = ImageCreate($w, $h);
  ImageCopy ( $img, $src, 0, 0, $px, $py, $w, $h );
  imageRectangle ( $img, 0, 0, $w-1, $h-1, ImageColorAllocate( $img, 0, 0, 0 ) );
  ImageGIF( $img, $file );
}
$file (banner) und $source (vorlage) sind absolute pfadangaben. das script macht eigentlich nix weiter, als ein $w breites und $h hohes stück aus der vorlage auszuschneiden und als .gif abzuspeichern.
 
[PHP] random signature fürs forum

dieses script prüft den empfangenen banner auf korrekte "forumsgrösse" - 88x31px bei max.15kb - bei fehler wird der nächste banner geholt - bei erfolg wird der banner angezeigt -einzubinden ins forum wie gehabt:

PHP:
[url=https://www.webmasterlose.de/lose/randsigclick.php?id=XXXXX&aid=YYYYY][img]https://www.ZZZZZ.de/randsigview.php?id=XXXXX&aid=YYYYY[/img][/url]
XXXXX, YYYYY, ZZZZZ müssen natürlich ersetzt werden. das ganze funktioniert (mit angepasster url) natürlich für alle sig-banner, die auf diese art ausgegeben werden...

PHP:
<? /********************************************************
  file:         randomsig.php
  description:  check randsig-banners for correct size
  copyright:    ActionScripter | https://www.actionscripter.de
***********************************************************/

  $url    = "https://www.webmasterlose.de/lose/randsigview.php?id=%d&aid=%d";
  $retry = 3;
  while( $retry-->0 ) {
    $data = file_get_contents( sprintf($url,$_GET['id'],$_GET['aid']) );
    // bild darf nicht grösser als 15k sein 
    // zur sicherheit nehmen wir 14kb
    if( strLen($data)>14*1024 ) continue;
    // wml mal wieder zu lahm
    if( strLen($data)<=0 ) continue;
    $img  = ImageCreateFromString( $data );
    // bild darf nicht grösser als 88x31 sein
    if( ImagesX($img)>88 || ImagesY($img)>31 ) continue;
    header( "Content-type: image/gif" );
    echo $data;
    exit;
  }
?>
[EDIT]
Da in diesem Forum kein php-script als image eingebunden werden kann. muss man das script auf eine html-datei umbiegen.

wer die signatur verwenden will, der kann sich folgende url als IMG angeben:
https://remote.lokis-losebude.de/randsig/randsigview_XXXXX_YYYYY.html

beim ersten aufruf wird die datei freigeschaltet, ab dem zweiten gibt es bilder :)
[/EDIT]

[EDIT2]es sind natürlich nur 15k erlaubt ... weiss gar nicht, wie ich auf 35 kam[/EDIT2]
 
Zuletzt bearbeitet von einem Moderator:
[JS] Cookie setzen wie mit PHP

So ich saß an den beiden Funktionen nun gute 8 Stunden und hoffe mal es ist ersichtlich das ich kein JavaScript Profi bin, aber die Funktionen funktionieren soweit und wurden gerade getestet. Kann Sein das noch einige Sicherheitsfunktionen reinmüssen, aber die kann ich ja ergänzen wenn ich was vergessen haben sollte. Bin mal auf eure Meinungen gespannt und hoffe mal mein erstes Snippet kommt gut an und wird auch gebraucht :mrgreen: .
PHP:
/* imitate the setCookie Funktion from PHP use */
function setCookie( name, value, ex, path, domain, secure )
{
   if(typeof(ex) == 'undefined')
      var expires = null;
   else
   {
      var expires = new Date();
      var expires_tmp = expires.getTime() + ( parseInt(ex) * 60 * 60 * 1000);
      expires.setTime(expires_tmp);
   }

   if(typeof(path) == 'undefined')
      var path = null;
   if(typeof(domain) == 'undefined')
      var domain = null;
   if(typeof(secure) == 'undefined')
      var secure = null;

   var cookieString = name + '=' + escape(value);
   if(expires != null)
      cookieString += '; expires=' + expires.toGMTString();
   if(path != null)
      cookieString += '; path=' + path;
   if(domain != null)
      cookieString += '; domain=' + domain;
   if(secure != null)
      cookieString += '; secure';

   document.cookie = cookieString;
}

/* imitate the $_COOKIE vars from PHP use */
function readCookie( name )
{
   if(!document.cookie || document.cookie.indexOf( name + '=' ) == -1)
      return false;

   var cookies = document.cookie.split('; ');
   if(cookies.length > 1)
   {
      for( var i = 0; i < cookies.length; i++)
      {
         var copy = cookies[i].split('=');
         if(copy[0] == name)
            return unescape( copy[1] );
      }
   }
}

Zu benutzen mit:
PHP:
setCookie('TestsetCookie', "1#7'\/", 24);
alert(readCookie('TestsetCookie'));

Hoffe es ist ersichtlich, wer was net versteht einfach frage.
 
Zuletzt bearbeitet:
[PHP] HTTP Authentifizierung

Man kann diese HTTP Authentifizierung auch mit der .htaccess machen:
Code:
<FILES beispiel.php>
order deny,allow
allow from all
AuthType Basic
AuthUserFile /var/www/.htpasswd
AuthName "..."
require valid-user
</FILES>

Man kann das selbe aber auch mit PHP machen:
PHP:
<?php
# $_PAIRS ist ein Array in der Form "Benutzername" => "verschlüsseltes Passwort"
#Man kann den Array $_PAIRS z.B. aus einer Datenbank holen oder gleich im Skript definieren.

if(!isset($_PAIRS))
{
	header('HTTP/1.1 404 Not Found');
	echo '404 Not Found';
	exit;
}
$pair = get_user_and_password();

if( ( !isset($_PAIRS[$pair['user']]) ||  (crypt($pair['password'], $_PAIRS[$pair['user']]) != $_PAIRS[$pair['user']]) ))
{
	header("WWW-Authenticate: Basic realm=\"Password required\"");
	header('HTTP/1.1 401 Unauthorized');
	echo '401 Unauthorized';
	exit;
}

function allgemein_getenv($env)
{
	if(isset($_SERVER[$env])) return $_SERVER[$env];
	elseif(isset($_ENV[$env])) return $_ENV[$env];
	elseif(getenv($env)) return getenv($env);
	elseif(function_exists('apache_getenv') && apache_getenv($env, true)) return apache_getenv($var_name, true);
	else return FALSE;
}
function get_user_and_password()
{
	$_env_userkeys = array('PHP_AUTH_USER','REMOTE_USER','AUTH_USER','HTTP_AUTHORIZATION','Authorization');
	$_env_passkeys = array('PHP_AUTH_PW','REMOTE_PASSWORD','AUTH_PASSWORD');
	
	$i=0;
	while(isset($_env_userkeys[$i]) && !$user = allgemein_getenv($_env_userkeys[$i])) { $i++; }
	while(isset($_env_passkeys[$i]) && !$pass = allgemein_getenv($_env_passkeys[$i])) { $i++; }
	return array('user' => $user, 'password' => $pass);
}
?>
MIt PHP hat gegenüber der Apache Variante den Vorteil, dass man auch noch weitere Sicherungsmaßnahmen einbauen kann, wie z.B. eine maximale Anzahl von Login-Versuchen je User und/oder ein Delay nach einem fehlgeschlagenen Versuch bis zum nächsten Versuch.
Außerdem lassen sich die User leichter verwalten als bei der Apache-Variante mit der .htpasswd Datei.

Der Auth geht natürlich nur bei PHP-files bei denen er auch eingebaut ist und beeinflusst keine anderen Dateien im selben Verzeichniss. Ob das nun ein Vorteil oder ein Nachteil ist ist von Fall zu Fall unterschiedlich.
Wenn man Bilder damit schützen wollte, müsste man sie aus einem gesperrten Verzeichniss mit PHP auslesen und anzeigen.

Im übrigen ist es besser wenn möglich (meist eh nicht) die Funktion hash() statt der Funktion crypt() zu benutzen.
 
Zuletzt bearbeitet:
Wenn man mal wieder nen Server trifft, auf dem register_globals auf on gestellt ist, kann man das Sicherheitsrisiko, dass dieses darstellt mit dem Folgenden Snippet umgehen:
PHP:
<?php

/*
Script: unregister_golbals
Original-Filename: server.inc.php
Author: Astrodan
*/


// Optionen, welche Variablen gelsöcht werden sollen
define('DEL_SERVER', true); // $_SERVER
define('DEL_COOKIE', true); // $_COOKIE
define('DEL_GET', true); // $_GET
define('DEL_POST', true); // $_POST
define('DEL_ENV', true); // $_ENV
define('DEL_SESSION', true); // $_SESSION

if(ini_get('register_globals') != false) {
	$variables_order = ini_get('variables_order'); // Nur das löschen, das auch gesetzt wurde
	if(DEL_ENV and (strpos($variables_order, 'E') !==  false)) {  
		foreach($_ENV as $key => $value) {
			unset(${$key});
		}
	}
	if(DEL_GET and (strpos($variables_order, 'G') !==  false)) {
		foreach($_GET as $key => $value) {
			unset(${$key});
		}
	}
	if(DEL_POST and (strpos($variables_order, 'P') !==  false)) {
		foreach($_POST as $key => $value){
			unset(${$key});
		}
	}
	if(DEL_COOKIE and (strpos($variables_order, 'C') !==  false)) {
		foreach($_COOKIE as $key => $value) {
			unset(${$key});
		}
	}
	if(DEL_SERVER and (strpos($variables_order, 'S') !==  false)) {
		foreach($_SERVER as $key => $value) {
			unset(${$key});
		}
	}
	if(DEL_SESSION) {  // Löscht die Session Variablen. Steht uwar nirgends im PHP-Manual, dass die übernommen werden, aber ist anscheinend so
		foreach($_SERVER as $key => $value) {
			unset(${$key});
		}
	}		
} // Brauch ja nit aufgeräumt werden, wenn die Dinger noch gar nit registriert sind

?>

Sollte allerdings nur eingesetzt werden, wenn man keine Möglichkeit hat (oder keine Ahnung ;)) die Einstellungen in der php.ini zu ändern, oder in einer .htaccess-Datei den entsprechenden PHP-Flag zu setzen.

Dauer der Ausführung habe ich nicht getestet, hängt aber schließlich auch von der Anzahl der gesetzten Variablen ab.

Edit: Korrektur, war als Funktion nicht Funktionstüchtig, da die Variablen innerhalb der Funktion ja nicht die selben sind wie außerhalb. Sollte aber so, wie es aktuell ist, gehen, am besten in eine Datei rein und dann am Anfang des Scripts per include() starten. (Dank an chrissel)

Edit 2: Signatur entfernt (Auf Hinweis von Samy)

Edit 3: Falsche Reihenfolge der Variablen bei foreach. *grml* irgendwann reichts. (Dank an chrissel)
 
Zuletzt bearbeitet: