openrat-cms

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

commit 0e77573dbba97babb0b02be802700fdafc525345
parent 08b2d2ade50dae6994c9099dc856d41f3556a68b
Author: dankert <devnull@localhost>
Date:   Tue, 28 Nov 2006 00:58:06 +0100

Interne Ablage der Parameterpositionen zur Vermeidung von SQL-Injection.

Diffstat:
serviceClasses/Sql.class.php | 261++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 227 insertions(+), 34 deletions(-)

diff --git a/serviceClasses/Sql.class.php b/serviceClasses/Sql.class.php @@ -1,54 +1,144 @@ <?php -# -# DaCMS Content Management System -# Copyright (C) 2002 Jan Dankert, jandankert@jandankert.de -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# - +// --------------------------------------------------------------------------- +// $Id$ +// --------------------------------------------------------------------------- +// OpenRat Content Management System +// Copyright (C) 2002-2006 Jan Dankert, jandankert@jandankert.de +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// --------------------------------------------------------------------------- /** + * SQL-Anweisung.<br> + * <br> * Darstellen eines SQL-Statements incl. Methoden zum Fuellen von - * Platzhaltern im SQL-Befehl. - * - * @author $Author$ + * Platzhaltern im SQL-Befehl.<br> + * <br> + * Beispiel<br> + * <pre> + * // Neues Objekt erzeugen mit SQL-Anweisung + * $sql = new Sql('SELECT * FROM xy WHERE id={uid} AND name={name}'); + * + * // Parameter füllen + * $sql->setInt ('uid' ,1 ); + * $sql->setString('name','peter'); + * + * // Fertige SQL-Anweisung verwenden + * $xy->execute( $sql->query ); + * </pre> + * <br> + * Ziele dieser Klasse sind:<br> + * - Schreiben einfacher SQL-Anweisungen ohne Stringverarbeitung<br> + * - Verhindern von SQL-Injection.<br> + * <br> + * + * @author Jan Dankert, $Author$ * @version $Revision$ * @package openrat.services */ class Sql { - var $query = ''; - var $data = Array(); + /** + * Ursprüngliche SQL-Anweisung. + */ + var $src = ''; + + /** + * Auszuführende Abfrage. + */ + var $query = ''; + + + /** + * Zwischenspeicher für Parameterwerte. + */ + var $data = Array(); + + /** + * Ein 2-dimensionales Array mit den Positionen der Parameter.<br> + * <br> + * Beispiel:<br> + * <pre> + * + * Array + * ( + * [lid] => Array + * ( + * [0] => 65 + * [1] => 81 + * ) + * [oid] => Array + * ( + * [0] => 123 + * ) + * ) + * </pre> + * In der ersten Dimension sind die Parameter vorhanden, jeder Parameter hat eine Liste von Positionen, an denen er steht.<br> + * Ein Parameter kann nämlich mehrfach vorkommen! + */ + var $param = array(); - // Konstruktor, normalerweise setzen der SQL-Abfrage + + + /** + * Erzeugt ein SQL-Objekt und analysiert die SQL-Anfrage. + */ function Sql( $query = '' ) { - $this->query = $query; - $this->data = array(); + $this->src = $query; // Wir merken uns die Ur-Abfrage, evtl. für Fehlermeldungen interessant. + + while( true ) // Schleife wird solange durchlaufen, solange Parameter gefunden werden. + { + $posKlLinks = strpos($query,'{'); + $posKlRechts = strpos($query,'}'); + + if ( $posKlLinks === false ) + break; // Schleife abbrechen, wenn kein Parameter mehr gefunden wird. + + $nameParam = substr($query,$posKlLinks+1,$posKlRechts-$posKlLinks-1); // Name Parameter + + if ( !isset($this->param[$nameParam ])) + $this->param [$nameParam ] = array(); + + $this->param[$nameParam ][] = $posKlLinks; + + $query = substr($query,0,$posKlLinks).substr($query,$posKlRechts+1); + } + $this->data = array(); + $this->query = $query; + + // Tabellennamen in die Platzhalter setzen. + // Dies ist noch OpenRat-spezifisch und sollte bei einer sauberen Abstraktion woanders gemacht werden. Aber wo? foreach( table_names() as $t=>$name ) { - $this->query = str_replace( '{'.$t.'}',$name,$this->query ); + $this->setParam($t,$name,false ); } + +// Html::debug($this->param); } - // Neues Setzen der SQL-Abfrage + + /** + * Setzt eine neue SQL-Abfrage.<br> + * Bereits vorhandene Parameter werden automatisch wieder gesetzt. + */ function setQuery( $query = '' ) { $this->query = $query; @@ -67,6 +157,62 @@ class Sql } + + /** + * Setzt einen Parameter.<br> + * Diese Methode sollte nur intern aufgerufen werden!<br> + * + * @param name Name des Parameters + * @param value Inhalt + * @param dieIfUnknown wenn <code>true</code> und Parameter unbekannt, dann Abbruch. + * @access private + */ + function setParam( $name,$value,$dieIfUnknown=true) + { +// Html::debug($this->src); +// Html::debug($this->param,'vor setParam() ('.$name.'='.$value.')'); + +// Nett gemeint, führt aber aktuell zu Fehlern, weil an vielen Stellen zu viele Parameter gefüllt werden. +// Daher erstmal deaktiviert. +// if ( !isset($this->param[$name]) ) +// { +// if ( $dieIfUnknown ) +// die("parameter '$name' unknown. SQL=".$this->src); +// else +// return; +// } + + foreach( $this->param[$name] as $idx=>$xyz ) + { + $pos = $this->param[$name][$idx]; + + $this->query = substr( $this->query,0,$pos ).$value.substr( $this->query,$pos ); + + foreach( $this->param as $pn=>$par) + { + foreach( $par as $i=>$p ) + { + if ( $p > $pos ) + $this->param[$pn][$i]=$p+strlen($value); + } + } + + } + + unset( $this->param[$name] ); + +// Html::debug($this->param,'nach setParam()'); + } + + + + /** + * Setzt einen Parameter.<br> + * Der Typ des Parameters wird automatisch ermittelt.<br> + * + * @param name Name des Parameters + * @param value Inhalt + */ function setVar( $name,$value ) { if ( is_string($value) ) @@ -80,25 +226,52 @@ class Sql } + + /** + * Setzt eine Ganzzahl als Parameter.<br> + * + * @param name Name des Parameters + * @param value Inhalt + */ function setInt( $name,$value ) { $this->data[ $name ] = array( 'type'=>'int','value'=>$value ); - $this->query = str_replace( '{'.$name.'}',intval($value),$this->query ); + + $this->setParam($name,intval($value)); +// $this->query = str_replace( '{'.$name.'}',intval($value),$this->query ); } + + /** + * Setzt eine Zeichenkette als Parameter.<br> + * + * @param name Name des Parameters + * @param value Inhalt + */ function setString( $name,$value ) { $this->data[ $name ] = array( 'type'=>'string','value'=>$value ); //if ( defined('CONF_ADDSLASHES') && CONF_ADDSLASHES ) - $value = addslashes( $value ); + + $value = addslashes( $value ); $value = "'".$value."'"; - $this->query = str_replace( '{'.$name.'}',$value,$this->query ); + + $this->setParam($name,$value); +// $this->query = str_replace( '{'.$name.'}',$value,$this->query ); } + + /** + * Setzt einen bool'schen Wert als Parameter.<br> + * Ist der Parameterwert wahr, dann wird eine 1 gesetzt. Sonst 0.<br> + * + * @param name Name des Parameters + * @param value Inhalt + */ function setBoolean( $name,$value ) { if ( $value ) @@ -107,21 +280,41 @@ class Sql } + + /** + * Setzt einen Parameter auf den Wert <code>null</code>.<br> + * + * @param name Name des Parameters + */ function setNull( $name ) { $this->data[ $name ] = array( 'type'=>'null' ); - $this->query = str_replace( '{'.$name.'}','NULL',$this->query ); + $this->setParam($name,'NULL'); } - function query() + + /** + * Ermittelt die fertige SQL-Anfrage.<br> + * Alias zu #getQuery() + */ + function &query() { return $this->getQuery(); } + + /** + * Ermittelt die fertige SQL-Anfrage. + */ function &getQuery() { +// Abbruch, wenn es noch nicht gefüllte Parameter gibt. +// Da diese Methode eh kaum verwendet wird, erstmal deaktiviert. +// if ( count($this->param) > 0 ) +// die('parameters not bound: '+implode(',',$this->param) ); + return $this->query; } }