1
0
mirror of https://github.com/dg/dibi.git synced 2025-08-01 11:50:15 +02:00

update to 0.5alpha

This commit is contained in:
David Grudl
2006-06-04 23:06:33 +00:00
commit 0d18c4c366
21 changed files with 3384 additions and 0 deletions

21
copyright.txt Normal file
View File

@@ -0,0 +1,21 @@
Copyright notice
----------------
dibi (C) David Grudl, 2005-2006 <dave@dgx.cz>
For more information, visit the homepage http://texy.info/dibi
or author's weblog: http://www.dgx.cz/trine/
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

View File

@@ -0,0 +1,33 @@
<?php
/**
* dibi - Database Abstraction Layer according to dgx
* --------------------------------------------------
*
* This source file is subject to the GNU GPL license.
*
* @author David Grudl aka -dgx- <dave@dgx.cz>
* @link http://texy.info/dibi/
* @copyright Copyright (c) 2005-2006 David Grudl
* @license GNU GENERAL PUBLIC LICENSE
* @package dibi
* @category Database
* @version 0.5alpha (2006-05-26) for PHP5
*/define('dibi','Database Abstraction Layer (c) David Grudl, http://texy.info/dibi/');if(version_compare(PHP_VERSION,'5.0.3','<'))die('dibi needs PHP 5.0.3 or newer');
abstract class DibiDriver{protected$config;public$formats=array('NULL'=>"NULL",'TRUE'=>"1",'FALSE'=>"0",'date'=>"'Y-m-d'",'datetime'=>"'Y-m-d H:i:s'",);abstract static public function connect($config);protected function __construct($config){$this->config=$config;}public function getConfig(){return$this->config;}abstract public function query($sql);abstract public function affectedRows();abstract public function insertId();abstract public function begin();abstract public function commit();abstract public function rollback();abstract public function escape($value,$appendQuotes=FALSE);abstract public function quoteName($value);abstract public function getMetaData();}
if(!interface_exists('Countable',false)){interface Countable{function count();}}abstract class DibiResult implements IteratorAggregate,Countable{const FIELD_TEXT='s',FIELD_BINARY='b',FIELD_BOOL='l',FIELD_INTEGER='i',FIELD_FLOAT='f',FIELD_DATE='d',FIELD_DATETIME='t',FIELD_UNKNOWN='?',FIELD_COUNTER='c';protected$convert;abstract public function seek($row);abstract public function rowCount();abstract public function getFields();abstract public function getMetaData($field);abstract protected function detectTypes();abstract protected function free();abstract protected function doFetch();final public function fetch(){$rec=$this->doFetch();if(!is_array($rec))return FALSE;if($t=$this->convert){foreach($rec as$key=>$value){if(isset($t[$key]))$rec[$key]=$this->convert($value,$t[$key]);}}return$rec;}final function fetchSingle(){$rec=$this->doFetch();if(!is_array($rec))return FALSE;if($t=$this->convert){$value=reset($rec);$key=key($rec);return isset($t[$key])?$this->convert($value,$t[$key]):$value;}return reset($rec);}final function fetchAll(){@$this->seek(0);$rec=$this->fetch();if(!$rec)return array();$assocBy=func_get_args();$arr=array();if(!$assocBy){$value=count($rec)==1?key($rec):NULL;do{$arr[]=$value===NULL?$rec:$rec[$value];}while($rec=$this->fetch());return$arr;}do{foreach($assocBy as$n=>$assoc){$val[$n]=$rec[$assoc];unset($rec[$assoc]);}foreach($assocBy as$n=>$assoc){if($n==0)$tmp=&$arr[$val[$n]];else$tmp=&$tmp[$assoc][$val[$n]];if($tmp===NULL)$tmp=$rec;}}while($rec=$this->fetch());return$arr;}final function fetchPairs($key,$value){@$this->seek(0);$rec=$this->fetch();if(!$rec)return array();$arr=array();do{$arr[$rec[$key]]=$rec[$value];}while($rec=$this->fetch());return$arr;}public function __destruct(){@$this->free();}public function setType($field,$type=NULL){if($field===TRUE)$this->detectTypes();elseif(is_array($field))$this->convert=$field;else$this->convert[$field]=$type;}public function getType($field){return isset($this->convert[$field])?$this->convert[$field]:NULL;}public function convert($value,$type){if($value===NULL||$value===FALSE)return$value;static$conv=array(self::FIELD_TEXT=>'string',self::FIELD_BINARY=>'string',self::FIELD_BOOL=>'bool',self::FIELD_INTEGER=>'int',self::FIELD_FLOAT=>'float',self::FIELD_COUNTER=>'int',);if(isset($conv[$type])){settype($value,$conv[$type]);return$value;}if($type==self::FIELD_DATE)return new TDate($value);if($type==self::FIELD_DATETIME)return new TDateTime($value);return$value;}public function getIterator($offset=NULL,$count=NULL){return new DibiResultIterator($this,$offset,$count);}public function count(){return$this->rowCount();}}class DibiResultIterator implements Iterator{private$result,$offset,$count,$record,$row;public function __construct(DibiResult$result,$offset=NULL,$count=NULL){$this->result=$result;$this->offset=(int)$offset;$this->count=$count===NULL?PHP_INT_MAX:(int)$count;}public function rewind(){$this->row=0;@$this->result->seek($this->offset);$this->record=$this->result->fetch();}public function key(){return$this->row;}public function current(){return$this->record;}public function next(){$this->record=$this->result->fetch();$this->row++;}public function valid(){return is_array($this->record)&&($this->row<$this->count);}}
class DibiParser{private$modifier,$hasError,$driver;public function parse($driver,$args){$sql='';$this->driver=$driver;$this->modifier=0;$this->hasError=false;$command=null;$lastString=null;foreach($args as$index=>$arg){$sql.=' ';if(is_array($arg)){if($this->modifier){$type=$this->modifier;$this->modifier=false;}else{if(is_int(key($arg)))$type='L';else{if(!$command)$command=strtoupper(substr(ltrim($args[0]),0,6));$type=$command=='UPDATE'?'S':'V';}}$vx=$kx=array();switch($type){case'S':foreach($arg as$k=>$v)$vx[]=$this->driver->quoteName($k).'='.$this->formatValue($v);$sql.=implode(', ',$vx);break;case'V':foreach($arg as$k=>$v){$kx[]=$this->driver->quoteName($k);$vx[]=$this->formatValue($v);}$sql.='('.implode(', ',$kx).') VALUES ('.implode(', ',$vx).')';break;case'L':foreach($arg as$k=>$v)$vx[]=$this->formatValue($v);$sql.=implode(', ',$vx);break;case'N':foreach($arg as$v)$vx[]=$this->driver->quoteName($v);$sql.=implode(', ',$vx);break;default:$this->hasError=true;$sql.="**Unknown modifier %$type**";}continue;}if($this->modifier){if($arg instanceof IDibiVariable){$sql.=$arg->toSql($this->driver,$this->modifier);$this->modifier=false;continue;}if(!is_scalar($arg)&&!is_null($arg)){$this->hasError=true;$this->modifier=false;$sql.='**Unexpected '.gettype($arg).'**';continue;}switch($this->modifier){case"s":$sql.=$this->driver->escape($arg,TRUE);break;case'T':$sql.=date($this->driver->formats['date'],is_string($arg)?strtotime($arg):$arg);break;case't':$sql.=date($this->driver->formats['datetime'],is_string($arg)?strtotime($arg):$arg);break;case'b':$sql.=$arg?$this->driver->formats['TRUE']:$this->driver->formats['FALSE'];break;case'i':case'u':case'd':$sql.=(string)(int)$arg;break;case'f':$sql.=(string)(float)$arg;break;case'n':$sql.=$this->driver->quoteName($arg);break;default:$this->hasError=true;$sql.="**Unknown modifier %$this->modifier**";}$this->modifier=false;continue;}if(is_string($arg)){$lastString=$index;$toSkip=strcspn($arg,'`[\'"%');if($toSkip==strlen($arg)){$sql.=$arg;}else{$sql.=substr($arg,0,$toSkip).preg_replace_callback('/
(?=`|\[|\'|"|%) ## speed-up
(?:
`(.+?)`| ## 1) `identifier`
\[(.+?)\]| ## 2) [identifier]
(\')((?:\'\'|[^\'])*)\'| ## 3,4) string
(")((?:""|[^"])*)"| ## 5,6) "string"
%([a-zA-Z])$| ## 7) right modifier
(\'|") ## 8) lone-quote
)/xs',array($this,'callback'),substr($arg,$toSkip));}continue;}$sql.=$this->formatValue($arg);}if($this->hasError)return new DibiException('Errors during generating SQL',array('sql'=>$sql));return trim($sql);}private function formatValue($value){if(is_string($value))return$this->driver->escape($value,TRUE);if(is_int($value)||is_float($value))return(string)$value;if(is_bool($value))return$value?$this->driver->formats['TRUE']:$this->driver->formats['FALSE'];if(is_null($value))return$this->driver->formats['NULL'];if($value instanceof IDibiVariable)return$value->toSql($this->driver);$this->hasError=true;return'**Unsupported type '.gettype($value).'**';}private function callback($matches){if($matches[1])return$this->driver->quoteName($matches[1]);if($matches[2])return$this->driver->quoteName($matches[2]);if($matches[3])return$this->driver->escape(strtr($matches[4],array("''"=>"'")),true);if($matches[5])return$this->driver->escape(strtr($matches[6],array('""'=>'"')),true);if($matches[7]){$this->modifier=$matches[7];return'';}if($matches[8]){return'**Alone quote**';$this->hasError=true;}die('this should be never executed');}}
class DibiException extends Exception{private$info;public function __construct($message,$info=NULL){$this->info=$info;if(isset($info['message']))$message="$message: $info[message]";parent::__construct($message);}public function getSql(){return@$this->info['sql'];}}function is_error($var){return($var===FALSE)||($var instanceof Exception);}
if(function_exists('date_default_timezone_set'))date_default_timezone_set('Europe/Prague');class TDate implements IDibiVariable{protected$time;public function __construct($time=NULL){if($time===NULL)$this->time=time();elseif(is_string($time))$this->time=strtotime($time);else$this->time=(int)$time;}public function toSQL($driver,$modifier=NULL){return date($driver->formats['date'],$this->time);}public function getTimeStamp(){return$this->time;}}class TDateTime extends TDate{public function toSQL($driver,$modifier=NULL){return date($driver->formats['datetime'],$this->time);}} interface IDibiVariable{public function toSQL($driver,$modifier=NULL);}class dibi{static private$registry=array();static private$conn;static private$parser;static public$sql;static public$error;static public$logfile;static public$debug=false;static private$query=array();static public function connect($config,$name='def'){if(!self::$parser)self::$parser=new DibiParser();if(isset(self::$registry[$name]))return new DibiException("Connection named '$name' already exists.");if(empty($config['driver']))return new DibiException('Driver is not specified.');$className="Dibi$config[driver]Driver"; if(!class_exists($className))return new DibiException("Unable to create instance of dibi driver class '$className'.");$conn=call_user_func(array($className,'connect'),$config);if(self::$logfile!=NULL){if(is_error($conn))$msg="Can't connect to DB '$config[driver]': ".$conn->getMessage();else$msg="Successfully connected to DB '$config[driver]'";$f=fopen(self::$logfile,'a');fwrite($f,"$msg\r\n\r\n");fclose($f);}if(is_error($conn)){if(self::$debug)echo'[dibi error] '.$conn->getMessage();return$conn;}self::$conn=self::$registry[$name]=$conn;return TRUE;}static public function isConnected(){return(bool)self::$conn;}static public function getConnection($name=NULL){return$name===NULL?self::$conn:@self::$registry[$name];}static public function activate($name){if(!isset(self::$registry[$name]))return FALSE;self::$conn=self::$registry[$name];return TRUE;}static public function query(){if(!self::$conn)return new DibiException('Dibi is not connected to DB');$args=func_num_args()?func_get_args():self::$query;self::$query=array();self::$sql=self::$parser->parse(self::$conn,$args);if(is_error(self::$sql))return self::$sql;$timer=-microtime(true);$res=self::$conn->query(self::$sql);$timer+=microtime(true);if(is_error($res)){if(self::$debug){echo'[dibi error] '.$res->getMessage();self::dump(self::$sql);}self::$error=$res;}else{self::$error=FALSE;}if(self::$logfile!=NULL){if(is_error($res))$msg=$res->getMessage();elseif($res instanceof DibiResult)$msg='object('.get_class($res).') rows: '.$res->rowCount();else$msg='OK';$f=fopen(self::$logfile,'a');fwrite($f,self::$sql.";\r\n-- Result: $msg"."\r\n-- Takes: ".sprintf('%0.3f',$timer*1000).' ms'."\r\n\r\n");fclose($f);}return$res;}static public function queryStart(){self::$query=func_get_args();}static public function queryAdd(){$args=func_get_args();self::$query=array_merge(self::$query,$args);}static public function test(){if(!self::$conn)return FALSE;$args=func_num_args()?func_get_args():self::$query;self::$query=array();$sql=self::$parser->parse(self::$conn,$args);if(is_error($sql)){self::dump($sql->getSql());return$sql->getSql();}else{self::dump($sql);return$sql;}}static public function insertId(){if(!self::$conn)return FALSE;return self::$conn->insertId();}static public function affectedRows(){if(!self::$conn)return FALSE;return self::$conn->affectedRows();}static public function dump($sql){static$highlight=array('ALL','DISTINCT','AS','ON','INTO','AND','OR','AS',);static$newline=array('SELECT','UPDATE','INSERT','DELETE','FROM','WHERE','HAVING','GROUP BY','ORDER BY','LIMIT','SET','VALUES','LEFT JOIN','INNER JOIN',);foreach($newline as$word)$sql=preg_replace('#\b'.$word.'\b#',"\n\$0",$sql);$sql=trim($sql);$sql=wordwrap($sql,100);$sql=htmlSpecialChars($sql);$sql=strtr($sql,array("\n"=>'<br />'));foreach($newline as$word)$sql=preg_replace('#\b'.$word.'\b#','<strong style="color:blue">$0</strong>',$sql);foreach($highlight as$word)$sql=preg_replace('#\b'.$word.'\b#','<strong style="color:green">$0</strong>',$sql);$sql=preg_replace('#\*\*.+?\*\*#','<strong style="color:red">$0</strong>',$sql);echo'<pre>',$sql,'</pre>';}static public function dumpResult(DibiResult$res){echo'<table class="dump"><tr>';echo'<th>Row</th>';$fieldCount=$res->fieldCount();for($i=0;$i<$fieldCount;$i++){$info=$res->fieldMeta($i);echo'<th>'.htmlSpecialChars($info['name']).'</th>';}echo'</tr>';foreach($res as$row=>$fields){echo'<tr><th>',$row,'</th>';foreach($fields as$field){if(is_object($field))$field=$field->__toString();echo'<td>',htmlSpecialChars($field),'</td>';}echo'</tr>';}echo'</table>';}}
class DibiMySqlDriver extends DibiDriver{private$conn;public$formats=array('NULL'=>"NULL",'TRUE'=>"1",'FALSE'=>"0",'date'=>"'Y-m-d'",'datetime'=>"'Y-m-d H:i:s'",);public static function connect($config){if(!extension_loaded('mysql'))return new DibiException("PHP extension 'mysql' is not loaded");if(empty($config['host']))$config['host']='localhost';if(@$config['protocol']==='unix')$host=':'.$config['host'];else$host=$config['host'].(empty($config['port'])?'':$config['port']);if(function_exists('ini_set'))$save=ini_set('track_errors',TRUE);$php_errormsg='';if(empty($config['persistent']))$conn=@mysql_connect($host,@$config['username'],@$config['password']);else$conn=@mysql_pconnect($host,@$config['username'],@$config['password']);if(function_exists('ini_set'))ini_set('track_errors',$save);if(!is_resource($conn))return new DibiException("Connecting error",array('message'=>mysql_error()?mysql_error():$php_errormsg,'code'=>mysql_errno(),));if(!empty($config['charset'])){$succ=@mysql_query('SET CHARACTER SET '.$config['charset'],$conn);}if(!empty($config['database'])){if(!@mysql_select_db($config['database'],$conn))return new DibiException("Connecting error",array('message'=>mysql_error($conn),'code'=>mysql_errno($conn),));}$obj=new self($config);$obj->conn=$conn;return$obj;}public function query($sql){$res=@mysql_query($sql,$this->conn);if(is_resource($res))return new DibiMySqlResult($res);if($res===FALSE)return new DibiException("Query error",array('message'=>mysql_error($this->conn),'code'=>mysql_errno($this->conn),'sql'=>$sql,));return TRUE;}public function affectedRows(){$rows=mysql_affected_rows($this->conn);return$rows<0?FALSE:$rows;}public function insertId(){$id=mysql_insert_id($this->conn);return$id<0?FALSE:$id;}public function begin(){return mysql_query('BEGIN',$this->conn);}public function commit(){return mysql_query('COMMIT',$this->conn);}public function rollback(){return mysql_query('ROLLBACK',$this->conn);}public function escape($value,$appendQuotes=FALSE){return$appendQuotes?"'".mysql_real_escape_string($value,$this->conn)."'":mysql_real_escape_string($value,$this->conn);}public function quoteName($value){return'`'.strtr($value,array('.'=>'`.`')).'`';}public function getMetaData(){trigger_error('Meta is not implemented yet.',E_USER_WARNING);}}class DibiMySqlResult extends DibiResult{private$resource,$meta;public function __construct($resource){$this->resource=$resource;}public function rowCount(){return mysql_num_rows($this->resource);}protected function doFetch(){return mysql_fetch_assoc($this->resource);}public function seek($row){return mysql_data_seek($this->resource,$row);}protected function free(){mysql_free_result($this->resource);}public function getFields(){if($this->meta===NULL)$this->createMeta();return array_keys($this->meta);}protected function detectTypes(){if($this->meta===NULL)$this->createMeta();}public function getMetaData($field){if($this->meta===NULL)$this->createMeta();return isset($this->meta[$field])?$this->meta[$field]:FALSE;}private function createMeta(){static$types=array('ENUM'=>self::FIELD_TEXT,'SET'=>self::FIELD_TEXT,'CHAR'=>self::FIELD_TEXT,'VARCHAR'=>self::FIELD_TEXT,'STRING'=>self::FIELD_TEXT,'TINYTEXT'=>self::FIELD_TEXT,'TEXT'=>self::FIELD_TEXT,'MEDIUMTEXT'=>self::FIELD_TEXT,'LONGTEXT'=>self::FIELD_TEXT,'BINARY'=>self::FIELD_BINARY,'VARBINARY'=>self::FIELD_BINARY,'TINYBLOB'=>self::FIELD_BINARY,'BLOB'=>self::FIELD_BINARY,'MEDIUMBLOB'=>self::FIELD_BINARY,'LONGBLOB'=>self::FIELD_BINARY,'DATE'=>self::FIELD_DATE,'DATETIME'=>self::FIELD_DATETIME,'TIMESTAMP'=>self::FIELD_DATETIME,'TIME'=>self::FIELD_DATETIME,'BIT'=>self::FIELD_BOOL,'YEAR'=>self::FIELD_INTEGER,'TINYINT'=>self::FIELD_INTEGER,'SMALLINT'=>self::FIELD_INTEGER,'MEDIUMINT'=>self::FIELD_INTEGER,'INT'=>self::FIELD_INTEGER,'INTEGER'=>self::FIELD_INTEGER,'BIGINT'=>self::FIELD_INTEGER,'FLOAT'=>self::FIELD_FLOAT,'DOUBLE'=>self::FIELD_FLOAT,'REAL'=>self::FIELD_FLOAT,'DECIMAL'=>self::FIELD_FLOAT,'NUMERIC'=>self::FIELD_FLOAT,);$count=mysql_num_fields($this->resource);$this->meta=$this->convert=array();for($index=0;$index<$count;$index++){$info['native']=$native=strtoupper(mysql_field_type($this->resource,$index));$info['flags']=explode(' ',mysql_field_flags($this->resource,$index));$info['length']=mysql_field_len($this->resource,$index);$info['table']=mysql_field_table($this->resource,$index);if(in_array('auto_increment',$info['flags']))$info['type']=self::FIELD_COUNTER;else{$info['type']=isset($types[$native])?$types[$native]:self::FIELD_UNKNOWN;}$name=mysql_field_name($this->resource,$index);$this->meta[$name]=$info;$this->convert[$name]=$info['type'];}}}
class DibiMySqliDriver extends DibiDriver{private$conn;public$formats=array('NULL'=>"NULL",'TRUE'=>"1",'FALSE'=>"0",'date'=>"'Y-m-d'",'datetime'=>"'Y-m-d H:i:s'",);public static function connect($config){if(!extension_loaded('mysqli'))return new DibiException("PHP extension 'mysqli' is not loaded");if(empty($config['host']))$config['host']='localhost';$conn=@mysqli_connect($config['host'],@$config['username'],@$config['password'],@$config['database'],@$config['port']);if(!$conn)return new DibiException("Connecting error",array('message'=>mysqli_connect_error(),'code'=>mysqli_connect_errno(),));if(!empty($config['charset']))mysqli_query($conn,'SET CHARACTER SET '.$config['charset']);$obj=new self($config);$obj->conn=$conn;return$obj;}public function query($sql){$res=@mysqli_query($this->conn,$sql);if(is_object($res))return new DibiMySqliResult($res);if($res===FALSE)return new DibiException("Query error",$this->errorInfo($sql));return TRUE;}public function affectedRows(){$rows=mysqli_affected_rows($this->conn);return$rows<0?FALSE:$rows;}public function insertId(){$id=mysqli_insert_id($this->conn);return$id<1?FALSE:$id;}public function begin(){return mysqli_autocommit($this->conn,FALSE);}public function commit(){$ok=mysqli_commit($this->conn);mysqli_autocommit($this->conn,TRUE);return$ok;}public function rollback(){$ok=mysqli_rollback($this->conn);mysqli_autocommit($this->conn,TRUE);return$ok;}private function errorInfo($sql=NULL){return array('message'=>mysqli_error($this->conn),'code'=>mysqli_errno($this->conn),'sql'=>$sql,);}public function escape($value,$appendQuotes=FALSE){return$appendQuotes?"'".mysqli_real_escape_string($this->conn,$value)."'":mysqli_real_escape_string($this->conn,$value);}public function quoteName($value){return'`'.strtr($value,array('.'=>'`.`')).'`';}public function getMetaData(){trigger_error('Meta is not implemented yet.',E_USER_WARNING);}}class DibiMySqliResult extends DibiResult{private$resource,$meta;public function __construct($resource){$this->resource=$resource;}public function rowCount(){return mysqli_num_rows($this->resource);}protected function doFetch(){return mysqli_fetch_assoc($this->resource);}public function seek($row){return mysqli_data_seek($this->resource,$row);}protected function free(){mysqli_free_result($this->resource);}public function getFields(){if($this->meta===NULL)$this->createMeta();return array_keys($this->meta);}protected function detectTypes(){if($this->meta===NULL)$this->createMeta();}public function getMetaData($field){if($this->meta===NULL)$this->createMeta();return isset($this->meta[$field])?$this->meta[$field]:FALSE;}private function createMeta(){static$types=array(MYSQLI_TYPE_FLOAT=>self::FIELD_FLOAT,MYSQLI_TYPE_DOUBLE=>self::FIELD_FLOAT,MYSQLI_TYPE_DECIMAL=>self::FIELD_FLOAT,MYSQLI_TYPE_TINY=>self::FIELD_INTEGER,MYSQLI_TYPE_SHORT=>self::FIELD_INTEGER,MYSQLI_TYPE_LONG=>self::FIELD_INTEGER,MYSQLI_TYPE_LONGLONG=>self::FIELD_INTEGER,MYSQLI_TYPE_INT24=>self::FIELD_INTEGER,MYSQLI_TYPE_YEAR=>self::FIELD_INTEGER,MYSQLI_TYPE_GEOMETRY=>self::FIELD_INTEGER,MYSQLI_TYPE_DATE=>self::FIELD_DATE,MYSQLI_TYPE_NEWDATE=>self::FIELD_DATE,MYSQLI_TYPE_TIMESTAMP=>self::FIELD_DATETIME,MYSQLI_TYPE_TIME=>self::FIELD_DATETIME,MYSQLI_TYPE_DATETIME=>self::FIELD_DATETIME,MYSQLI_TYPE_ENUM=>self::FIELD_TEXT,MYSQLI_TYPE_SET=>self::FIELD_TEXT,MYSQLI_TYPE_STRING=>self::FIELD_TEXT,MYSQLI_TYPE_VAR_STRING=>self::FIELD_TEXT,MYSQLI_TYPE_TINY_BLOB=>self::FIELD_BINARY,MYSQLI_TYPE_MEDIUM_BLOB=>self::FIELD_BINARY,MYSQLI_TYPE_LONG_BLOB=>self::FIELD_BINARY,MYSQLI_TYPE_BLOB=>self::FIELD_BINARY,);$count=mysqli_num_fields($this->resource);$this->meta=$this->convert=array();for($index=0;$index<$count;$index++){$info=(array)mysqli_fetch_field_direct($this->resource,$index);$native=$info['native']=$info['type'];if($info['flags']&MYSQLI_AUTO_INCREMENT_FLAG)$info['type']=self::FIELD_COUNTER;else{$info['type']=isset($types[$native])?$types[$native]:self::FIELD_UNKNOWN;}$this->meta[$info['name']]=$info;$this->convert[$info['name']]=$info['type'];}}}
class DibiOdbcDriver extends DibiDriver{private$conn;public$formats=array('NULL'=>"NULL",'TRUE'=>"-1",'FALSE'=>"0",'date'=>"#m/d/Y#",'datetime'=>"#m/d/Y H:i:s#",);public static function connect($config){if(!extension_loaded('odbc'))return new DibiException("PHP extension 'odbc' is not loaded");if(@$config['persistent'])$conn=@odbc_pconnect($config['database'],$config['username'],$config['password']);else$conn=@odbc_connect($config['database'],$config['username'],$config['password']);if(!is_resource($conn))return new DibiException("Connecting error",array('message'=>odbc_errormsg(),'code'=>odbc_error(),));$obj=new self($config);$obj->conn=$conn;return$obj;}public function query($sql){$res=@odbc_exec($this->conn,$sql);if(is_resource($res))return new DibiOdbcResult($res);if($res===FALSE)return new DibiException("Query error",$this->errorInfo($sql));return TRUE;}public function affectedRows(){$rows=odbc_num_rows($this->conn);return$rows<0?FALSE:$rows;}public function insertId(){return FALSE;}public function begin(){return odbc_autocommit($this->conn,FALSE);}public function commit(){$ok=odbc_commit($this->conn);odbc_autocommit($this->conn,TRUE);return$ok;}public function rollback(){$ok=odbc_rollback($this->conn);odbc_autocommit($this->conn,TRUE);return$ok;}private function errorInfo($sql=NULL){return array('message'=>odbc_errormsg($this->conn),'code'=>odbc_error($this->conn),'sql'=>$sql,);}public function escape($value,$appendQuotes=FALSE){$value=str_replace("'","''",$value);return$appendQuotes?"'".$value."'":$value;}public function quoteName($value){return'['.strtr($value,array('.'=>'].[')).']';}public function getMetaData(){trigger_error('Meta is not implemented yet.',E_USER_WARNING);}}class DibiOdbcResult extends DibiResult{private$resource,$meta,$row=0;public function __construct($resource){$this->resource=$resource;}public function rowCount(){return odbc_num_rows($this->resource);}protected function doFetch(){return odbc_fetch_array($this->resource,$this->row++);}public function seek($row){$this->row=$row;}protected function free(){odbc_free_result($this->resource);}public function getFields(){if($this->meta===NULL)$this->createMeta();return array_keys($this->meta);}protected function detectTypes(){if($this->meta===NULL)$this->createMeta();}public function getMetaData($field){if($this->meta===NULL)$this->createMeta();return isset($this->meta[$field])?$this->meta[$field]:FALSE;}private function createMeta(){if($this->meta!==NULL)return$this->meta;static$types=array('CHAR'=>self::FIELD_TEXT,'COUNTER'=>self::FIELD_COUNTER,'VARCHAR'=>self::FIELD_TEXT,'LONGCHAR'=>self::FIELD_TEXT,'INTEGER'=>self::FIELD_INTEGER,'DATETIME'=>self::FIELD_DATETIME,'CURRENCY'=>self::FIELD_FLOAT,'BIT'=>self::FIELD_BOOL,'LONGBINARY'=>self::FIELD_BINARY,'SMALLINT'=>self::FIELD_INTEGER,'BYTE'=>self::FIELD_INTEGER,'BIGINT'=>self::FIELD_INTEGER,'INT'=>self::FIELD_INTEGER,'TINYINT'=>self::FIELD_INTEGER,'REAL'=>self::FIELD_FLOAT,'DOUBLE'=>self::FIELD_FLOAT,'DECIMAL'=>self::FIELD_FLOAT,'NUMERIC'=>self::FIELD_FLOAT,'MONEY'=>self::FIELD_FLOAT,'SMALLMONEY'=>self::FIELD_FLOAT,'FLOAT'=>self::FIELD_FLOAT,'YESNO'=>self::FIELD_BOOL,);$count=odbc_num_fields($this->resource);$this->meta=$this->convert=array();for($index=1;$index<=$count;$index++){$native=strtoupper(odbc_field_type($this->resource,$index));$name=odbc_field_name($this->resource,$index);$this->meta[$name]=array('type'=>isset($types[$native])?$types[$native]:self::FIELD_UNKNOWN,'native'=>$native,'length'=>odbc_field_len($this->resource,$index),'scale'=>odbc_field_scale($this->resource,$index),'precision'=>odbc_field_precision($this->resource,$index),);$this->convert[$name]=$this->meta[$name]['type'];}}}
class DibiSqliteDriver extends DibiDriver{private$conn;public$formats=array('NULL'=>"NULL",'TRUE'=>"1",'FALSE'=>"0",'date'=>"'Y-m-d'",'datetime'=>"'Y-m-d H:i:s'",);public static function connect($config){if(!extension_loaded('sqlite'))return new DibiException("PHP extension 'sqlite' is not loaded");if(empty($config['database']))return new DibiException("Database must be specified");$errorMsg='';if(empty($config['persistent']))$conn=@sqlite_open($config['database'],@$config['mode'],$errorMsg);else$conn=@sqlite_popen($config['database'],@$config['mode'],$errorMsg);if(!$conn)return new DibiException("Connecting error",array('message'=>$errorMsg,));$obj=new self($config);$obj->conn=$conn;return$obj;}public function query($sql){$errorMsg='';$res=@sqlite_query($this->conn,$sql,SQLITE_ASSOC,$errorMsg);if($res===FALSE)return new DibiException("Query error",array('message'=>$errorMsg,'sql'=>$sql,));if(is_resource($res))return new DibiSqliteResult($res);return TRUE;}public function affectedRows(){$rows=sqlite_changes($this->conn);return$rows<0?FALSE:$rows;}public function insertId(){$id=sqlite_last_insert_rowid($this->conn);return$id<1?FALSE:$id;}public function begin(){return sqlite_query($this->conn,'BEGIN');}public function commit(){return sqlite_query($this->conn,'COMMIT');}public function rollback(){return sqlite_query($this->conn,'ROLLBACK');}public function escape($value,$appendQuotes=FALSE){return$appendQuotes?"'".sqlite_escape_string($value)."'":sqlite_escape_string($value);}public function quoteName($value){return$value;}public function getMetaData(){trigger_error('Meta is not implemented yet.',E_USER_WARNING);}}class DibiSqliteResult extends DibiResult{private$resource,$meta;public function __construct($resource){$this->resource=$resource;}public function rowCount(){return sqlite_num_rows($this->resource);}protected function doFetch(){return sqlite_fetch_array($this->resource,SQLITE_ASSOC);}public function seek($row){return sqlite_seek($this->resource,$row);}protected function free(){}public function getFields(){if($this->meta===NULL)$this->createMeta();return array_keys($this->meta);}protected function detectTypes(){if($this->meta===NULL)$this->createMeta();}public function getMetaData($field){if($this->meta===NULL)$this->createMeta();return isset($this->meta[$field])?$this->meta[$field]:FALSE;}private function createMeta(){$count=sqlite_num_fields($this->resource);$this->meta=$this->convert=array();for($index=0;$index<$count;$index++){$name=sqlite_field_name($this->resource,$index);$this->meta[$name]=array('type'=>self::FIELD_UNKNOWN);$this->convert[$name]=self::FIELD_UNKNOWN;}}}?>

416
dibi/dibi.php Normal file
View File

@@ -0,0 +1,416 @@
<?php
/**
* dibi - Database Abstraction Layer according to dgx
* --------------------------------------------------
*
* This source file is subject to the GNU GPL license.
*
* @author David Grudl aka -dgx- <dave@dgx.cz>
* @link http://texy.info/dibi/
* @copyright Copyright (c) 2005-2006 David Grudl
* @license GNU GENERAL PUBLIC LICENSE
* @package dibi
* @category Database
* @version 0.5alpha (2006-05-26) for PHP5
*/
define('dibi', 'Database Abstraction Layer (c) David Grudl, http://texy.info/dibi/');
if (version_compare(PHP_VERSION , '5.0.3', '<'))
die('dibi needs PHP 5.0.3 or newer');
// libraries
require_once dirname(__FILE__).'/libs/driver.php';
require_once dirname(__FILE__).'/libs/resultset.php';
require_once dirname(__FILE__).'/libs/parser.php';
require_once dirname(__FILE__).'/libs/exception.php';
// support
require_once dirname(__FILE__).'/libs/date.type.demo.php';
/**
* Interface for user variable, used for generating SQL
*/
interface IDibiVariable
{
/**
* Format for SQL
*
* @param object destination DibiDriver
* @param string optional modifier
* @return string SQL code
*/
public function toSQL($driver, $modifier = NULL);
}
/**
* Interface for database drivers
*
* This class is static container class for creating DB objects and
* store debug & connections info.
*
*/
class dibi
{
/**
* Connection registry storage for DibiDriver objects
* @var array
*/
static private $registry = array();
/**
* Current connection
* @var object DibiDriver
*/
static private $conn;
/**
* Arguments -> SQL parser
* @var object DibiParser
*/
static private $parser;
/**
* Last SQL command @see dibi::query()
* @var string
*/
static public $sql;
static public $error;
/**
* File for logging SQL queryies - strongly recommended to use with NSafeStream
* @var string|NULL
*/
static public $logfile;
/**
* Enable/disable debug mode
* @var bool
*/
static public $debug = false;
/**
* Progressive created query
* @var array
*/
static private $query = array();
/**
* Creates a new DibiDriver object and connects it to specified database
*
* @param array connection parameters
* @param string connection name
* @return bool|object TRUE on success, FALSE or Exception on failure
*/
static public function connect($config, $name = 'def')
{
// init parser
if (!self::$parser) self::$parser = new DibiParser();
// $name must be unique
if (isset(self::$registry[$name]))
return new DibiException("Connection named '$name' already exists.");
// config['driver'] is required
if (empty($config['driver']))
return new DibiException('Driver is not specified.');
// include dibi driver
$className = "Dibi$config[driver]Driver";
require_once dirname(__FILE__) . "/drivers/$config[driver].php";
if (!class_exists($className))
return new DibiException("Unable to create instance of dibi driver class '$className'.");
// create connection object
/** like $conn = $className::connect($config); */
$conn = call_user_func(array($className, 'connect'), $config);
// optionally log to file
// todo: log other exceptions!
if (self::$logfile != NULL) {
if (is_error($conn))
$msg = "Can't connect to DB '$config[driver]': ".$conn->getMessage();
else
$msg = "Successfully connected to DB '$config[driver]'";
$f = fopen(self::$logfile, 'a');
fwrite($f, "$msg\r\n\r\n");
fclose($f);
}
if (is_error($conn)) {
// optionally debug on display
if (self::$debug) echo '[dibi error] ' . $conn->getMessage();
return $conn; // reraise the exception
}
// store connection in list
self::$conn = self::$registry[$name] = $conn;
return TRUE;
}
/**
* Returns TRUE when connection was established
*
* @return bool
*/
static public function isConnected()
{
return (bool) self::$conn;
}
/**
* Retrieve active connection
*
* @param string connection registy name or NULL for active connection
* @return object DibiDriver object.
*/
static public function getConnection($name = NULL)
{
return $name === NULL
? self::$conn
: @self::$registry[$name];
}
/**
* Change active connection
*
* @param string connection registy name
* @return void
*/
static public function activate($name)
{
if (!isset(self::$registry[$name]))
return FALSE;
// change active connection
self::$conn = self::$registry[$name];
return TRUE;
}
/**
* Generates and executes SQL query
*
* @param mixed one or more arguments
* @return int|DibiResult|Exception
*/
static public function query()
{
if (!self::$conn) return new DibiException('Dibi is not connected to DB'); // is connected?
// receive arguments
$args = func_num_args() ? func_get_args() : self::$query;
self::$query = array();
// and generate SQL
self::$sql = self::$parser->parse(self::$conn, $args);
if (is_error(self::$sql)) return self::$sql; // reraise the exception
// execute SQL
$timer = -microtime(true);
$res = self::$conn->query(self::$sql);
$timer += microtime(true);
if (is_error($res)) {
// optionally debug on display
if (self::$debug) {
echo '[dibi error] ' . $res->getMessage();
self::dump(self::$sql);
}
// todo: log all errors!
self::$error = $res;
} else {
self::$error = FALSE;
}
// optionally log to file
if (self::$logfile != NULL)
{
if (is_error($res))
$msg = $res->getMessage();
elseif ($res instanceof DibiResult)
$msg = 'object('.get_class($res).') rows: '.$res->rowCount();
else
$msg = 'OK';
$f = fopen(self::$logfile, 'a');
fwrite($f,
self::$sql
. ";\r\n-- Result: $msg"
. "\r\n-- Takes: " . sprintf('%0.3f', $timer * 1000) . ' ms'
. "\r\n\r\n"
);
fclose($f);
}
return $res;
}
static public function queryStart()
{
self::$query = func_get_args();
}
static public function queryAdd()
{
$args = func_get_args();
self::$query = array_merge(self::$query, $args);
}
/**
* Generates and returns SQL query
*
* @param mixed one or more arguments
* @return string
*/
static public function test()
{
if (!self::$conn) return FALSE; // is connected?
// receive arguments
$args = func_num_args() ? func_get_args() : self::$query;
self::$query = array();
// and generate SQL
$sql = self::$parser->parse(self::$conn, $args);
if (is_error($sql)) {
self::dump($sql->getSql());
return $sql->getSql();
} else {
self::dump($sql);
return $sql;
}
}
/**
* Monostate for DibiDriver::insertId()
*
* @return int
*/
static public function insertId()
{
if (!self::$conn) return FALSE; // is connected?
return self::$conn->insertId();
}
/**
* Monostate for DibiDriver::affectedRows()
*
* @return int
*/
static public function affectedRows()
{
if (!self::$conn) return FALSE; // is connected?
return self::$conn->affectedRows();
}
/**
* Prints out a syntax highlighted version of the SQL command
*
* @param string SQL command
* @return void
*/
static public function dump($sql) {
static $highlight = array ('ALL', 'DISTINCT', 'AS', 'ON', 'INTO', 'AND', 'OR', 'AS', );
static $newline = array ('SELECT', 'UPDATE', 'INSERT', 'DELETE', 'FROM', 'WHERE', 'HAVING', 'GROUP BY', 'ORDER BY', 'LIMIT', 'SET', 'VALUES', 'LEFT JOIN', 'INNER JOIN',);
// insert new lines
foreach ($newline as $word)
$sql = preg_replace('#\b'.$word.'\b#', "\n\$0", $sql);
$sql = trim($sql);
// reduce spaces
// $sql = preg_replace('# +#', ' ', $sql);
$sql = wordwrap($sql, 100);
$sql = htmlSpecialChars($sql);
$sql = strtr($sql, array("\n" => '<br />'));
foreach ($newline as $word)
$sql = preg_replace('#\b'.$word.'\b#', '<strong style="color:blue">$0</strong>', $sql);
foreach ($highlight as $word)
$sql = preg_replace('#\b'.$word.'\b#', '<strong style="color:green">$0</strong>', $sql);
$sql = preg_replace('#\*\*.+?\*\*#', '<strong style="color:red">$0</strong>', $sql);
echo '<pre>', $sql, '</pre>';
}
/**
* Displays complete result-set as HTML table
*
* @param object DibiResult
* @return void
*/
static public function dumpResult(DibiResult $res)
{
echo '<table class="dump"><tr>';
echo '<th>Row</th>';
$fieldCount = $res->fieldCount();
for ($i = 0; $i < $fieldCount; $i++) {
$info = $res->fieldMeta($i);
echo '<th>'.htmlSpecialChars($info['name']).'</th>';
}
echo '</tr>';
foreach ($res as $row => $fields) {
echo '<tr><th>', $row, '</th>';
foreach ($fields as $field) {
if (is_object($field)) $field = $field->__toString();
echo '<td>', htmlSpecialChars($field), '</td>';
}
echo '</tr>';
}
echo '</table>';
}
} // class dibi
?>

334
dibi/drivers/mysql.php Normal file
View File

@@ -0,0 +1,334 @@
<?php
/**
* dibi - Database Abstraction Layer according to dgx
* --------------------------------------------------
*
* This source file is subject to the GNU GPL license.
*
* @author David Grudl aka -dgx- <dave@dgx.cz>
* @link http://texy.info/dibi/
* @copyright Copyright (c) 2005-2006 David Grudl
* @license GNU GENERAL PUBLIC LICENSE
* @package dibi
* @category Database
* @version 0.5alpha (2006-05-26) for PHP5
*/
// security - include dibi.php, not this file
if (!defined('dibi')) die();
/**
* The dibi driver for MySQL database
*
*/
class DibiMySqlDriver extends DibiDriver {
private
$conn;
public
$formats = array(
'NULL' => "NULL",
'TRUE' => "1",
'FALSE' => "0",
'date' => "'Y-m-d'",
'datetime' => "'Y-m-d H:i:s'",
);
/**
* Driver factory
*/
public static function connect($config)
{
if (!extension_loaded('mysql'))
return new DibiException("PHP extension 'mysql' is not loaded");
if (empty($config['host'])) $config['host'] = 'localhost';
if (@$config['protocol'] === 'unix') // host can be socket
$host = ':' . $config['host'];
else
$host = $config['host'] . (empty($config['port']) ? '' : $config['port']);
// some errors aren't handled. Must use $php_errormsg
if (function_exists('ini_set'))
$save = ini_set('track_errors', TRUE);
$php_errormsg = '';
if (empty($config['persistent']))
$conn = @mysql_connect($host, @$config['username'], @$config['password']);
else
$conn = @mysql_pconnect($host, @$config['username'], @$config['password']);
if (function_exists('ini_set'))
ini_set('track_errors', $save);
if (!is_resource($conn))
return new DibiException("Connecting error", array(
'message' => mysql_error() ? mysql_error() : $php_errormsg,
'code' => mysql_errno(),
));
if (!empty($config['charset'])) {
$succ = @mysql_query('SET CHARACTER SET '.$config['charset'], $conn);
// don't handle this error...
}
if (!empty($config['database'])) {
if (!@mysql_select_db($config['database'], $conn))
return new DibiException("Connecting error", array(
'message' => mysql_error($conn),
'code' => mysql_errno($conn),
));
}
$obj = new self($config);
$obj->conn = $conn;
return $obj;
}
public function query($sql)
{
$res = @mysql_query($sql, $this->conn);
if (is_resource($res))
return new DibiMySqlResult($res);
if ($res === FALSE)
return new DibiException("Query error", array(
'message' => mysql_error($this->conn),
'code' => mysql_errno($this->conn),
'sql' => $sql,
));
return TRUE;
}
public function affectedRows()
{
$rows = mysql_affected_rows($this->conn);
return $rows < 0 ? FALSE : $rows;
}
public function insertId()
{
$id = mysql_insert_id($this->conn);
return $id < 0 ? FALSE : $id;
}
public function begin()
{
return mysql_query('BEGIN', $this->conn);
}
public function commit()
{
return mysql_query('COMMIT', $this->conn);
}
public function rollback()
{
return mysql_query('ROLLBACK', $this->conn);
}
public function escape($value, $appendQuotes = FALSE)
{
return $appendQuotes
? "'" . mysql_real_escape_string($value, $this->conn) . "'"
: mysql_real_escape_string($value, $this->conn);
}
public function quoteName($value)
{
return '`' . strtr($value, array('.' => '`.`')) . '`';
}
public function getMetaData()
{
trigger_error('Meta is not implemented yet.', E_USER_WARNING);
}
/*
// is this really needed?
public function getResource()
{
return $this->conn;
}
// experimental
public function applyLimit(&$sql, $offset, $limit)
{
if ($limit > 0) {
$sql .= " LIMIT " . (int) $limit . ($offset > 0 ? " OFFSET " . (int) $offset : "");
} elseif ($offset > 0) {
$sql .= " LIMIT " . $offset . ", 18446744073709551615";
}
}
*/
} // DibiMySqlDriver
class DibiMySqlResult extends DibiResult
{
private
$resource,
$meta;
public function __construct($resource)
{
$this->resource = $resource;
}
public function rowCount()
{
return mysql_num_rows($this->resource);
}
protected function doFetch()
{
return mysql_fetch_assoc($this->resource);
}
public function seek($row)
{
return mysql_data_seek($this->resource, $row);
}
protected function free()
{
mysql_free_result($this->resource);
}
public function getFields()
{
// cache
if ($this->meta === NULL)
$this->createMeta();
return array_keys($this->meta);
}
protected function detectTypes()
{
if ($this->meta === NULL)
$this->createMeta();
}
/** this is experimental */
public function getMetaData($field)
{
// cache
if ($this->meta === NULL)
$this->createMeta();
return isset($this->meta[$field]) ? $this->meta[$field] : FALSE;
}
/** this is experimental */
private function createMeta()
{
static $types = array(
'ENUM' => self::FIELD_TEXT, // eventually self::FIELD_INTEGER
'SET' => self::FIELD_TEXT, // eventually self::FIELD_INTEGER
'CHAR' => self::FIELD_TEXT,
'VARCHAR' => self::FIELD_TEXT,
'STRING' => self::FIELD_TEXT,
'TINYTEXT' => self::FIELD_TEXT,
'TEXT' => self::FIELD_TEXT,
'MEDIUMTEXT'=> self::FIELD_TEXT,
'LONGTEXT' => self::FIELD_TEXT,
'BINARY' => self::FIELD_BINARY,
'VARBINARY' => self::FIELD_BINARY,
'TINYBLOB' => self::FIELD_BINARY,
'BLOB' => self::FIELD_BINARY,
'MEDIUMBLOB'=> self::FIELD_BINARY,
'LONGBLOB' => self::FIELD_BINARY,
'DATE' => self::FIELD_DATE,
'DATETIME' => self::FIELD_DATETIME,
'TIMESTAMP' => self::FIELD_DATETIME,
'TIME' => self::FIELD_DATETIME,
'BIT' => self::FIELD_BOOL,
'YEAR' => self::FIELD_INTEGER,
'TINYINT' => self::FIELD_INTEGER,
'SMALLINT' => self::FIELD_INTEGER,
'MEDIUMINT' => self::FIELD_INTEGER,
'INT' => self::FIELD_INTEGER,
'INTEGER' => self::FIELD_INTEGER,
'BIGINT' => self::FIELD_INTEGER,
'FLOAT' => self::FIELD_FLOAT,
'DOUBLE' => self::FIELD_FLOAT,
'REAL' => self::FIELD_FLOAT,
'DECIMAL' => self::FIELD_FLOAT,
'NUMERIC' => self::FIELD_FLOAT,
);
$count = mysql_num_fields($this->resource);
$this->meta = $this->convert = array();
for ($index = 0; $index < $count; $index++) {
$info['native'] = $native = strtoupper(mysql_field_type($this->resource, $index));
$info['flags'] = explode(' ', mysql_field_flags($this->resource, $index));
$info['length'] = mysql_field_len($this->resource, $index);
$info['table'] = mysql_field_table($this->resource, $index);
if (in_array('auto_increment', $info['flags'])) // or 'primary_key' ?
$info['type'] = self::FIELD_COUNTER;
else {
$info['type'] = isset($types[$native]) ? $types[$native] : self::FIELD_UNKNOWN;
// if ($info['type'] == self::FIELD_TEXT && $info['length'] > 255)
// $info['type'] = self::FIELD_LONG_TEXT;
}
$name = mysql_field_name($this->resource, $index);
$this->meta[$name] = $info;
$this->convert[$name] = $info['type'];
}
}
} // class DibiMySqlResult
?>

282
dibi/drivers/mysqli.php Normal file
View File

@@ -0,0 +1,282 @@
<?php
/**
* dibi - Database Abstraction Layer according to dgx
* --------------------------------------------------
*
* This source file is subject to the GNU GPL license.
*
* @author David Grudl aka -dgx- <dave@dgx.cz>
* @link http://texy.info/dibi/
* @copyright Copyright (c) 2005-2006 David Grudl
* @license GNU GENERAL PUBLIC LICENSE
* @package dibi
* @category Database
* @version 0.5alpha (2006-05-26) for PHP5
*/
// security - include dibi.php, not this file
if (!defined('dibi')) die();
/**
* The dibi driver for MySQLi database
*
*/
class DibiMySqliDriver extends DibiDriver {
private
$conn;
public
$formats = array(
'NULL' => "NULL",
'TRUE' => "1",
'FALSE' => "0",
'date' => "'Y-m-d'",
'datetime' => "'Y-m-d H:i:s'",
);
public static function connect($config)
{
if (!extension_loaded('mysqli'))
return new DibiException("PHP extension 'mysqli' is not loaded");
if (empty($config['host'])) $config['host'] = 'localhost';
$conn = @mysqli_connect($config['host'], @$config['username'], @$config['password'], @$config['database'], @$config['port']);
if (!$conn)
return new DibiException("Connecting error", array(
'message' => mysqli_connect_error(),
'code' => mysqli_connect_errno(),
));
if (!empty($config['charset']))
mysqli_query($conn, 'SET CHARACTER SET '.$config['charset']);
$obj = new self($config);
$obj->conn = $conn;
return $obj;
}
public function query($sql)
{
$res = @mysqli_query($this->conn, $sql);
if (is_object($res))
return new DibiMySqliResult($res);
if ($res === FALSE)
return new DibiException("Query error", $this->errorInfo($sql));
return TRUE;
}
public function affectedRows()
{
$rows = mysqli_affected_rows($this->conn);
return $rows < 0 ? FALSE : $rows;
}
public function insertId()
{
$id = mysqli_insert_id($this->conn);
return $id < 1 ? FALSE : $id;
}
public function begin()
{
return mysqli_autocommit($this->conn, FALSE);
}
public function commit()
{
$ok = mysqli_commit($this->conn);
mysqli_autocommit($this->conn, TRUE);
return $ok;
}
public function rollback()
{
$ok = mysqli_rollback($this->conn);
mysqli_autocommit($this->conn, TRUE);
return $ok;
}
private function errorInfo($sql = NULL)
{
return array(
'message' => mysqli_error($this->conn),
'code' => mysqli_errno($this->conn),
'sql' => $sql,
);
}
public function escape($value, $appendQuotes = FALSE)
{
return $appendQuotes
? "'" . mysqli_real_escape_string($this->conn, $value) . "'"
: mysqli_real_escape_string($this->conn, $value);
}
public function quoteName($value)
{
return '`' . strtr($value, array('.' => '`.`')) . '`';
}
public function getMetaData()
{
trigger_error('Meta is not implemented yet.', E_USER_WARNING);
}
} // class DibiMySqliDriver
class DibiMySqliResult extends DibiResult
{
private
$resource,
$meta;
public function __construct($resource)
{
$this->resource = $resource;
}
public function rowCount()
{
return mysqli_num_rows($this->resource);
}
protected function doFetch()
{
return mysqli_fetch_assoc($this->resource);
}
public function seek($row)
{
return mysqli_data_seek($this->resource, $row);
}
protected function free()
{
mysqli_free_result($this->resource);
}
public function getFields()
{
// cache
if ($this->meta === NULL)
$this->createMeta();
return array_keys($this->meta);
}
protected function detectTypes()
{
if ($this->meta === NULL)
$this->createMeta();
}
/** this is experimental */
public function getMetaData($field)
{
// cache
if ($this->meta === NULL)
$this->createMeta();
return isset($this->meta[$field]) ? $this->meta[$field] : FALSE;
}
/** this is experimental */
private function createMeta()
{
static $types = array(
MYSQLI_TYPE_FLOAT => self::FIELD_FLOAT,
MYSQLI_TYPE_DOUBLE => self::FIELD_FLOAT,
MYSQLI_TYPE_DECIMAL => self::FIELD_FLOAT,
// MYSQLI_TYPE_NEWDECIMAL=> self::FIELD_FLOAT,
// MYSQLI_TYPE_BIT => self::FIELD_INTEGER,
MYSQLI_TYPE_TINY => self::FIELD_INTEGER,
MYSQLI_TYPE_SHORT => self::FIELD_INTEGER,
MYSQLI_TYPE_LONG => self::FIELD_INTEGER,
MYSQLI_TYPE_LONGLONG => self::FIELD_INTEGER,
MYSQLI_TYPE_INT24 => self::FIELD_INTEGER,
MYSQLI_TYPE_YEAR => self::FIELD_INTEGER,
MYSQLI_TYPE_GEOMETRY => self::FIELD_INTEGER,
MYSQLI_TYPE_DATE => self::FIELD_DATE,
MYSQLI_TYPE_NEWDATE => self::FIELD_DATE,
MYSQLI_TYPE_TIMESTAMP => self::FIELD_DATETIME,
MYSQLI_TYPE_TIME => self::FIELD_DATETIME,
MYSQLI_TYPE_DATETIME => self::FIELD_DATETIME,
MYSQLI_TYPE_ENUM => self::FIELD_TEXT, // eventually self::FIELD_INTEGER
MYSQLI_TYPE_SET => self::FIELD_TEXT, // eventually self::FIELD_INTEGER
MYSQLI_TYPE_STRING => self::FIELD_TEXT,
MYSQLI_TYPE_VAR_STRING=> self::FIELD_TEXT,
MYSQLI_TYPE_TINY_BLOB => self::FIELD_BINARY,
MYSQLI_TYPE_MEDIUM_BLOB=> self::FIELD_BINARY,
MYSQLI_TYPE_LONG_BLOB => self::FIELD_BINARY,
MYSQLI_TYPE_BLOB => self::FIELD_BINARY,
);
$count = mysqli_num_fields($this->resource);
$this->meta = $this->convert = array();
for ($index = 0; $index < $count; $index++) {
$info = (array) mysqli_fetch_field_direct($this->resource, $index);
$native = $info['native'] = $info['type'];
if ($info['flags'] & MYSQLI_AUTO_INCREMENT_FLAG) // or 'primary_key' ?
$info['type'] = self::FIELD_COUNTER;
else {
$info['type'] = isset($types[$native]) ? $types[$native] : self::FIELD_UNKNOWN;
// if ($info['type'] == self::FIELD_TEXT && $info['length'] > 255)
// $info['type'] = self::FIELD_LONG_TEXT;
}
$this->meta[$info['name']] = $info;
$this->convert[$info['name']] = $info['type'];
}
}
} // class DibiMySqliResult
?>

273
dibi/drivers/odbc.php Normal file
View File

@@ -0,0 +1,273 @@
<?php
/**
* dibi - Database Abstraction Layer according to dgx
* --------------------------------------------------
*
* This source file is subject to the GNU GPL license.
*
* @author David Grudl aka -dgx- <dave@dgx.cz>
* @link http://texy.info/dibi/
* @copyright Copyright (c) 2005-2006 David Grudl
* @license GNU GENERAL PUBLIC LICENSE
* @package dibi
* @category Database
* @version 0.5alpha (2006-05-26) for PHP5
*/
// security - include dibi.php, not this file
if (!defined('dibi')) die();
/**
* The dibi driver interacting with databases via ODBC connections
*
*/
class DibiOdbcDriver extends DibiDriver {
private
$conn;
public
$formats = array(
'NULL' => "NULL",
'TRUE' => "-1",
'FALSE' => "0",
'date' => "#m/d/Y#",
'datetime' => "#m/d/Y H:i:s#",
);
public static function connect($config)
{
if (!extension_loaded('odbc'))
return new DibiException("PHP extension 'odbc' is not loaded");
if (@$config['persistent'])
$conn = @odbc_pconnect($config['database'], $config['username'], $config['password']);
else
$conn = @odbc_connect($config['database'], $config['username'], $config['password']);
if (!is_resource($conn))
return new DibiException("Connecting error", array(
'message' => odbc_errormsg(),
'code' => odbc_error(),
));
$obj = new self($config);
$obj->conn = $conn;
return $obj;
}
public function query($sql)
{
$res = @odbc_exec($this->conn, $sql);
if (is_resource($res))
return new DibiOdbcResult($res);
if ($res === FALSE)
return new DibiException("Query error", $this->errorInfo($sql));
return TRUE;
}
public function affectedRows()
{
$rows = odbc_num_rows($this->conn);
return $rows < 0 ? FALSE : $rows;
}
public function insertId()
{
return FALSE;
}
public function begin()
{
return odbc_autocommit($this->conn, FALSE);
}
public function commit()
{
$ok = odbc_commit($this->conn);
odbc_autocommit($this->conn, TRUE);
return $ok;
}
public function rollback()
{
$ok = odbc_rollback($this->conn);
odbc_autocommit($this->conn, TRUE);
return $ok;
}
private function errorInfo($sql = NULL)
{
return array(
'message' => odbc_errormsg($this->conn),
'code' => odbc_error($this->conn),
'sql' => $sql,
);
}
public function escape($value, $appendQuotes = FALSE)
{
$value = str_replace("'", "''", $value);
return $appendQuotes
? "'" . $value . "'"
: $value;
}
public function quoteName($value)
{
return '[' . strtr($value, array('.' => '].[')) . ']';
}
public function getMetaData()
{
trigger_error('Meta is not implemented yet.', E_USER_WARNING);
}
} // class DibiOdbcDriver
class DibiOdbcResult extends DibiResult
{
private
$resource,
$meta,
$row = 0;
public function __construct($resource)
{
$this->resource = $resource;
}
public function rowCount()
{
// will return -1 with many drivers :-(
return odbc_num_rows($this->resource);
}
protected function doFetch()
{
return odbc_fetch_array($this->resource, $this->row++);
}
public function seek($row)
{
$this->row = $row;
}
protected function free()
{
odbc_free_result($this->resource);
}
public function getFields()
{
// cache
if ($this->meta === NULL)
$this->createMeta();
return array_keys($this->meta);
}
protected function detectTypes()
{
if ($this->meta === NULL)
$this->createMeta();
}
/** this is experimental */
public function getMetaData($field)
{
// cache
if ($this->meta === NULL)
$this->createMeta();
return isset($this->meta[$field]) ? $this->meta[$field] : FALSE;
}
/** this is experimental */
private function createMeta()
{
// cache
if ($this->meta !== NULL)
return $this->meta;
static $types = array(
'CHAR' => self::FIELD_TEXT,
'COUNTER' => self::FIELD_COUNTER,
'VARCHAR' => self::FIELD_TEXT,
'LONGCHAR' => self::FIELD_TEXT,
'INTEGER' => self::FIELD_INTEGER,
'DATETIME' => self::FIELD_DATETIME,
'CURRENCY' => self::FIELD_FLOAT,
'BIT' => self::FIELD_BOOL,
'LONGBINARY'=> self::FIELD_BINARY,
'SMALLINT' => self::FIELD_INTEGER,
'BYTE' => self::FIELD_INTEGER,
'BIGINT' => self::FIELD_INTEGER,
'INT' => self::FIELD_INTEGER,
'TINYINT' => self::FIELD_INTEGER,
'REAL' => self::FIELD_FLOAT,
'DOUBLE' => self::FIELD_FLOAT,
'DECIMAL' => self::FIELD_FLOAT,
'NUMERIC' => self::FIELD_FLOAT,
'MONEY' => self::FIELD_FLOAT,
'SMALLMONEY'=> self::FIELD_FLOAT,
'FLOAT' => self::FIELD_FLOAT,
'YESNO' => self::FIELD_BOOL,
// and many others?
);
$count = odbc_num_fields($this->resource);
$this->meta = $this->convert = array();
for ($index = 1; $index <= $count; $index++) {
$native = strtoupper(odbc_field_type($this->resource, $index));
$name = odbc_field_name($this->resource, $index);
$this->meta[$name] = array(
'type' => isset($types[$native]) ? $types[$native] : self::FIELD_UNKNOWN,
'native' => $native,
'length' => odbc_field_len($this->resource, $index),
'scale' => odbc_field_scale($this->resource, $index),
'precision' => odbc_field_precision($this->resource, $index),
);
$this->convert[$name] = $this->meta[$name]['type'];
}
}
} // class DibiOdbcResult
?>

View File

233
dibi/drivers/sqlite.php Normal file
View File

@@ -0,0 +1,233 @@
<?php
/**
* dibi - Database Abstraction Layer according to dgx
* --------------------------------------------------
*
* This source file is subject to the GNU GPL license.
*
* @author David Grudl aka -dgx- <dave@dgx.cz>
* @link http://texy.info/dibi/
* @copyright Copyright (c) 2005-2006 David Grudl
* @license GNU GENERAL PUBLIC LICENSE
* @package dibi
* @category Database
* @version 0.5alpha (2006-05-26) for PHP5
*/
// security - include dibi.php, not this file
if (!defined('dibi')) die();
/**
* The dibi driver for SQlite database
*
*/
class DibiSqliteDriver extends DibiDriver {
private
$conn;
public
$formats = array(
'NULL' => "NULL",
'TRUE' => "1",
'FALSE' => "0",
'date' => "'Y-m-d'",
'datetime' => "'Y-m-d H:i:s'",
);
public static function connect($config)
{
if (!extension_loaded('sqlite'))
return new DibiException("PHP extension 'sqlite' is not loaded");
if (empty($config['database']))
return new DibiException("Database must be specified");
$errorMsg = '';
if (empty($config['persistent']))
$conn = @sqlite_open($config['database'], @$config['mode'], $errorMsg);
else
$conn = @sqlite_popen($config['database'], @$config['mode'], $errorMsg);
if (!$conn)
return new DibiException("Connecting error", array(
'message' => $errorMsg,
));
$obj = new self($config);
$obj->conn = $conn;
return $obj;
}
public function query($sql)
{
$errorMsg = '';
$res = @sqlite_query($this->conn, $sql, SQLITE_ASSOC, $errorMsg);
if ($res === FALSE)
return new DibiException("Query error", array(
'message' => $errorMsg,
'sql' => $sql,
));
if (is_resource($res))
return new DibiSqliteResult($res);
return TRUE;
}
public function affectedRows()
{
$rows = sqlite_changes($this->conn);
return $rows < 0 ? FALSE : $rows;
}
public function insertId()
{
$id = sqlite_last_insert_rowid($this->conn);
return $id < 1 ? FALSE : $id;
}
public function begin()
{
return sqlite_query($this->conn, 'BEGIN');
}
public function commit()
{
return sqlite_query($this->conn, 'COMMIT');
}
public function rollback()
{
return sqlite_query($this->conn, 'ROLLBACK');
}
public function escape($value, $appendQuotes = FALSE)
{
return $appendQuotes
? "'" . sqlite_escape_string($value) . "'"
: sqlite_escape_string($value);
}
public function quoteName($value)
{
return $value;
}
public function getMetaData()
{
trigger_error('Meta is not implemented yet.', E_USER_WARNING);
}
} // class DibiSqliteDriver
class DibiSqliteResult extends DibiResult
{
private
$resource,
$meta;
public function __construct($resource)
{
$this->resource = $resource;
}
public function rowCount()
{
return sqlite_num_rows($this->resource);
}
protected function doFetch()
{
return sqlite_fetch_array($this->resource, SQLITE_ASSOC);
}
public function seek($row)
{
return sqlite_seek($this->resource, $row);
}
protected function free()
{
}
public function getFields()
{
// cache
if ($this->meta === NULL)
$this->createMeta();
return array_keys($this->meta);
}
protected function detectTypes()
{
if ($this->meta === NULL)
$this->createMeta();
}
/** this is experimental */
public function getMetaData($field)
{
// cache
if ($this->meta === NULL)
$this->createMeta();
return isset($this->meta[$field]) ? $this->meta[$field] : FALSE;
}
/** this is experimental */
private function createMeta()
{
$count = sqlite_num_fields($this->resource);
$this->meta = $this->convert = array();
for ($index = 0; $index < $count; $index++) {
$name = sqlite_field_name($this->resource, $index);
$this->meta[$name] = array('type' => self::FIELD_UNKNOWN);
$this->convert[$name] = self::FIELD_UNKNOWN;
}
}
} // class DibiSqliteResult
?>

View File

@@ -0,0 +1,101 @@
<?php
/**
* dibi - Database Abstraction Layer according to dgx
* --------------------------------------------------
*
* This source file is subject to the GNU GPL license.
*
* @author David Grudl aka -dgx- <dave@dgx.cz>
* @link http://texy.info/dibi/
* @copyright Copyright (c) 2005-2006 David Grudl
* @license GNU GENERAL PUBLIC LICENSE
* @package dibi
* @category Database
* @version 0.5alpha (2006-05-26) for PHP5
*/
// security - include dibi.php, not this file
if (!defined('dibi')) die();
// required since PHP 5.1.0
// todo:
if (function_exists('date_default_timezone_set'))
date_default_timezone_set('Europe/Prague'); // or 'GMT'
/**
* Pseudotype for UNIX timestamp representation
*/
class TDate implements IDibiVariable
{
/**
* Unix timestamp
* @var int
*/
protected $time;
public function __construct($time = NULL)
{
if ($time === NULL)
$this->time = time(); // current time
elseif (is_string($time))
$this->time = strtotime($time); // try convert to timestamp
else
$this->time = (int) $time;
}
/**
* Format for SQL
*
* @param object destination DibiDriver
* @param string optional modifier
* @return string
*/
public function toSQL($driver, $modifier = NULL)
{
return date(
$driver->formats['date'], // format according to driver's spec.
$this->time
);
}
public function getTimeStamp()
{
return $this->time;
}
}
/**
* Pseudotype for datetime representation
*/
class TDateTime extends TDate
{
public function toSQL($driver, $modifier = NULL)
{
return date(
$driver->formats['datetime'], // format according to driver's spec.
$this->time
);
}
}
?>

164
dibi/libs/driver.php Normal file
View File

@@ -0,0 +1,164 @@
<?php
/**
* dibi - Database Abstraction Layer according to dgx
* --------------------------------------------------
*
* This source file is subject to the GNU GPL license.
*
* @author David Grudl aka -dgx- <dave@dgx.cz>
* @link http://texy.info/dibi/
* @copyright Copyright (c) 2005-2006 David Grudl
* @license GNU GENERAL PUBLIC LICENSE
* @package dibi
* @category Database
* @version 0.5alpha (2006-05-26) for PHP5
*/
// security - include dibi.php, not this file
if (!defined('dibi')) die();
/**
* dibi Common Driver
*
*/
abstract class DibiDriver
{
/**
* Current connection configuration
* @var array
*/
protected
$config;
/**
* Describes how convert some datatypes to SQL command
* @var array
*/
public $formats = array(
'NULL' => "NULL", // NULL
'TRUE' => "1", // boolean true
'FALSE' => "0", // boolean false
'date' => "'Y-m-d'", // format used by date()
'datetime' => "'Y-m-d H:i:s'", // format used by date()
);
/**
* DibiDriver factory: creates object and connects to a database
*
* @param array connect configuration
* @return bool|object DibiDriver object on success, FALSE or Exception on failure
*/
abstract static public function connect($config);
/**
* Driver initialization
*
* @param array connect configuration
*/
protected function __construct($config)
{
$this->config = $config;
}
/**
* Get the configuration descriptor used by connect() to connect to database.
* @see connect()
* @return array
*/
public function getConfig()
{
return $this->config;
}
/**
* Executes the SQL query
*
* @param string SQL statement.
* @return object|bool Result set object or TRUE on success, Exception on failure
*/
abstract public function query($sql);
/**
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query
*
* @return int number of rows or FALSE on error
*/
abstract public function affectedRows();
/**
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query
* @return int|bool int on success or FALSE on failure
*/
abstract public function insertId();
/**
* Begins a transaction (if supported).
*/
abstract public function begin();
/**
* Commits statements in a transaction.
*/
abstract public function commit();
/**
* Rollback changes in a transaction.
*/
abstract public function rollback();
/**
* Escapes the string
* @param string unescaped string
* @param bool quote string?
* @return string escaped and optionally quoted string
*/
abstract public function escape($value, $appendQuotes = FALSE);
/**
* Quotes SQL identifier (table's or column's name, etc.)
* @param string identifier
* @return string quoted identifier
*/
abstract public function quoteName($value);
/**
* Gets a information of the current database.
*
* @return DibiMetaData
*/
abstract public function getMetaData();
} // class DibiDriver
?>

67
dibi/libs/exception.php Normal file
View File

@@ -0,0 +1,67 @@
<?php
/**
* dibi - Database Abstraction Layer according to dgx
* --------------------------------------------------
*
* This source file is subject to the GNU GPL license.
*
* @author David Grudl aka -dgx- <dave@dgx.cz>
* @link http://texy.info/dibi/
* @copyright Copyright (c) 2005-2006 David Grudl
* @license GNU GENERAL PUBLIC LICENSE
* @package dibi
* @category Database
* @version 0.5alpha (2006-05-26) for PHP5
*/
// security - include dibi.php, not this file
if (!defined('dibi')) die();
/**
* dibi exception class
*
*/
class DibiException extends Exception
{
private
$info;
public function __construct($message, $info=NULL) {
$this->info = $info;
if (isset($info['message']))
$message = "$message: $info[message]";
/*
if (isset($info['sql']))
$message .= "\n[SQL] $info[sql]";
*/
parent::__construct($message);
}
public function getSql()
{
return @$this->info['sql'];
}
} // class DibiException
function is_error($var)
{
return ($var === FALSE) || ($var instanceof Exception);
}
?>

295
dibi/libs/parser.php Normal file
View File

@@ -0,0 +1,295 @@
<?php
/**
* dibi - Database Abstraction Layer according to dgx
* --------------------------------------------------
*
* This source file is subject to the GNU GPL license.
*
* @author David Grudl aka -dgx- <dave@dgx.cz>
* @link http://texy.info/dibi/
* @copyright Copyright (c) 2005-2006 David Grudl
* @license GNU GENERAL PUBLIC LICENSE
* @package dibi
* @category Database
* @version 0.5alpha (2006-05-26) for PHP5
*/
// security - include dibi.php, not this file
if (!defined('dibi')) die();
/**
* dibi parser
*
*/
class DibiParser
{
private
$modifier,
$hasError,
$driver;
/**
* Generates SQL
*
* @param array
* @return string
*/
public function parse($driver, $args)
{
$sql = '';
$this->driver = $driver;
$this->modifier = 0;
$this->hasError = false;
$command = null;
$lastString = null;
foreach ($args as $index => $arg) {
$sql .= ' '; // always add simple space
// array processing (with or without modifier)
if (is_array($arg)) {
// determine type: set | values | list
if ($this->modifier) {
$type = $this->modifier;
$this->modifier = false;
} else {
// autodetect
if (is_int(key($arg)))
$type = 'L'; // LIST
else {
if (!$command)
$command = strtoupper(substr(ltrim($args[0]), 0, 6));
$type = $command == 'UPDATE' ? 'S' : 'V'; // SET | VALUES
}
}
// build array
$vx = $kx = array();
switch ($type) {
case 'S': // SET
foreach ($arg as $k => $v)
$vx[] = $this->driver->quoteName($k) . '=' . $this->formatValue($v);
$sql .= implode(', ', $vx);
break;
case 'V': // VALUES
foreach ($arg as $k => $v) {
$kx[] = $this->driver->quoteName($k);
$vx[] = $this->formatValue($v);
}
$sql .= '(' . implode(', ', $kx) . ') VALUES (' . implode(', ', $vx) . ')';
break;
case 'L': // LIST
foreach ($arg as $k => $v)
$vx[] = $this->formatValue($v);
$sql .= implode(', ', $vx);
break;
case 'N': // NAMES
foreach ($arg as $v)
$vx[] = $this->driver->quoteName($v);
$sql .= implode(', ', $vx);
break;
default:
$this->hasError = true;
$sql .= "**Unknown modifier %$type**";
}
continue;
}
// after-modifier procession
if ($this->modifier) {
if ($arg instanceof IDibiVariable) {
$sql .= $arg->toSql($this->driver, $this->modifier);
$this->modifier = false;
continue;
}
if (!is_scalar($arg) && !is_null($arg)) { // array is already processed
$this->hasError = true;
$this->modifier = false;
$sql .= '**Unexpected '.gettype($arg).'**';
continue;
}
switch ($this->modifier) {
case "s": // string
$sql .= $this->driver->escape($arg, TRUE);
break;
case 'T': // date
$sql .= date($this->driver->formats['date'], is_string($arg) ? strtotime($arg) : $arg);
break;
case 't': // datetime
$sql .= date($this->driver->formats['datetime'], is_string($arg) ? strtotime($arg) : $arg);
break;
case 'b': // boolean
$sql .= $arg ? $this->driver->formats['TRUE'] : $this->driver->formats['FALSE'];
break;
case 'i':
case 'u': // unsigned int
case 'd': // signed int
$sql .= (string) (int) $arg;
break;
case 'f': // float
$sql .= (string) (float) $arg; // something like -9E-005 is accepted by SQL
break;
case 'n': // identifier name
$sql .= $this->driver->quoteName($arg);
break;
default:
$this->hasError = true;
$sql .= "**Unknown modifier %$this->modifier**";
}
$this->modifier = false;
continue;
}
// simple string means SQL
if (is_string($arg)) {
// double string warning
// (problematic with dibi::queryStart & dibi::queryAdd
// if ($lastString === $index-1)
// trigger_error("Is seems there is error in SQL near '$arg'.", E_USER_WARNING);
$lastString = $index;
// speed-up - is regexp required?
$toSkip = strcspn($arg, '`[\'"%');
if ($toSkip == strlen($arg)) {
$sql .= $arg;
} else {
$sql .= substr($arg, 0, $toSkip)
. preg_replace_callback('/
(?=`|\[|\'|"|%) ## speed-up
(?:
`(.+?)`| ## 1) `identifier`
\[(.+?)\]| ## 2) [identifier]
(\')((?:\'\'|[^\'])*)\'| ## 3,4) string
(")((?:""|[^"])*)"| ## 5,6) "string"
%([a-zA-Z])$| ## 7) right modifier
(\'|") ## 8) lone-quote
)/xs',
array($this, 'callback'),
substr($arg, $toSkip)
);
}
continue;
}
// default processing
$sql .= $this->formatValue($arg);
} // for
if ($this->hasError)
return new DibiException('Errors during generating SQL', array('sql' => $sql));
return trim($sql);
}
private function formatValue($value)
{
if (is_string($value))
return $this->driver->escape($value, TRUE);
if (is_int($value) || is_float($value))
return (string) $value; // something like -9E-005 is accepted by SQL
if (is_bool($value))
return $value ? $this->driver->formats['TRUE'] : $this->driver->formats['FALSE'];
if (is_null($value))
return $this->driver->formats['NULL'];
if ($value instanceof IDibiVariable)
return $value->toSql($this->driver);
$this->hasError = true;
return '**Unsupported type '.gettype($value).'**';
}
/**
* PREG callback for @see self::translate()
* @param array
* @return string
*/
private function callback($matches)
{
// [1] => `ident`
// [2] => [ident]
// [3] => '
// [4] => string
// [5] => "
// [6] => string
// [7] => right modifier
// [8] => lone-quote
if ($matches[1]) // SQL identifiers: `ident`
return $this->driver->quoteName($matches[1]);
if ($matches[2]) // SQL identifiers: [ident]
return $this->driver->quoteName($matches[2]);
if ($matches[3]) // SQL strings: '....'
return $this->driver->escape( strtr($matches[4], array("''" => "'")), true);
if ($matches[5]) // SQL strings: "..."
return $this->driver->escape( strtr($matches[6], array('""' => '"')), true);
if ($matches[7]) { // modifier
$this->modifier = $matches[7];
return '';
}
if ($matches[8]) { // string quote
return '**Alone quote**';
$this->hasError = true;
}
die('this should be never executed');
}
} // class DibiParser
?>

396
dibi/libs/resultset.php Normal file
View File

@@ -0,0 +1,396 @@
<?php
/**
* dibi - Database Abstraction Layer according to dgx
* --------------------------------------------------
*
* This source file is subject to the GNU GPL license.
*
* @author David Grudl aka -dgx- <dave@dgx.cz>
* @link http://texy.info/dibi/
* @copyright Copyright (c) 2005-2006 David Grudl
* @license GNU GENERAL PUBLIC LICENSE
* @package dibi
* @category Database
* @version 0.5alpha (2006-05-26) for PHP5
*/
// security - include dibi.php, not this file
if (!defined('dibi')) die();
// PHP < 5.1 compatibility
if (!interface_exists('Countable', false)) {
interface Countable
{
function count();
}
}
/**
* dibi result-set abstract class
*
* <code>
* $result = dibi::query('SELECT * FROM [table]');
* $value = $result->fetchSingle();
* $all = $result->fetchAll();
* $assoc = $result->fetchAll('id');
* $assoc = $result->fetchAll('active', 'id');
* unset($result);
* </code>
*/
abstract class DibiResult implements IteratorAggregate, Countable
{
/**
* Column type in relation to PHP native type
*/
const
FIELD_TEXT = 's', // as 'string'
FIELD_BINARY = 'b',
FIELD_BOOL = 'l', // as 'logical'
FIELD_INTEGER = 'i',
FIELD_FLOAT = 'f',
FIELD_DATE = 'd',
FIELD_DATETIME = 't',
FIELD_UNKNOWN = '?',
// special
FIELD_COUNTER = 'c'; // counter or autoincrement, is integer
/**
* Describes columns types
* @var array
*/
protected $convert;
/**
* Moves cursor position without fetching row
* @param int the 0-based cursor pos to seek to
* @return boolean TRUE on success, FALSE if unable to seek to specified record
*/
abstract public function seek($row);
/**
* Returns the number of rows in a result set
* @return int
*/
abstract public function rowCount();
/**
* Gets an array of field names
* @return array
*/
abstract public function getFields();
/**
* Gets an array of meta informations about column
* @param string column name
* @return array
*/
abstract public function getMetaData($field);
/**
* Acquires ....
* @return void
*/
abstract protected function detectTypes();
/**
* Frees the resources allocated for this result set
* @return void
*/
abstract protected function free();
/**
* Fetches the row at current position and moves the internal cursor to the next position
* internal usage only
* @return array|FALSE array() on success, FALSE if no next record
*/
abstract protected function doFetch();
/**
* Fetches the row at current position, process optional type conversion
* and moves the internal cursor to the next position
* @return array|FALSE array() on success, FALSE if no next record
*/
final public function fetch()
{
$rec = $this->doFetch();
if (!is_array($rec))
return FALSE;
// types-converting?
if ($t = $this->convert) { // little speed-up
foreach ($rec as $key => $value) {
if (isset($t[$key]))
$rec[$key] = $this->convert($value, $t[$key]);
}
}
return $rec;
}
/**
* Like fetch(), but returns only first field
* @return mixed value on success, FALSE if no next record
*/
final function fetchSingle()
{
$rec = $this->doFetch();
if (!is_array($rec))
return FALSE;
// types-converting?
if ($t = $this->convert) { // little speed-up
$value = reset($rec);
$key = key($rec);
return isset($t[$key])
? $this->convert($value, $t[$key])
: $value;
}
return reset($rec);
}
/**
* Fetches all records from table. Records , but returns only first field
* @param string associative colum [, param, ... ]
* @return array
*/
final function fetchAll()
{
@$this->seek(0);
$rec = $this->fetch();
if (!$rec)
return array(); // empty resultset
$assocBy = func_get_args();
$arr = array();
if (!$assocBy) { // no associative array
$value = count($rec) == 1 ? key($rec) : NULL;
do {
$arr[] = $value === NULL ? $rec : $rec[$value];
} while ($rec = $this->fetch());
return $arr;
}
do { // make associative arrays
foreach ($assocBy as $n => $assoc) {
$val[$n] = $rec[$assoc];
unset($rec[$assoc]);
}
foreach ($assocBy as $n => $assoc) {
if ($n == 0)
$tmp = &$arr[ $val[$n] ];
else
$tmp = &$tmp[$assoc][ $val[$n] ];
if ($tmp === NULL)
$tmp = $rec;
}
} while ($rec = $this->fetch());
return $arr;
}
/**
* Fetches all records from table like $key => $value pairs
* @return array
*/
final function fetchPairs($key, $value)
{
@$this->seek(0);
$rec = $this->fetch();
if (!$rec)
return array(); // empty resultset
$arr = array();
do {
$arr[ $rec[$key] ] = $rec[$value];
} while ($rec = $this->fetch());
return $arr;
}
/**
* Automatically frees the resources allocated for this result set
* @return void
*/
public function __destruct()
{
@$this->free();
}
public function setType($field, $type = NULL)
{
if ($field === TRUE)
$this->detectTypes();
elseif (is_array($field))
$this->convert = $field;
else
$this->convert[$field] = $type;
}
/** is this needed? */
public function getType($field)
{
return isset($this->convert[$field]) ? $this->convert[$field] : NULL;
}
public function convert($value, $type)
{
if ($value === NULL || $value === FALSE)
return $value;
static $conv = array(
self::FIELD_TEXT => 'string',
self::FIELD_BINARY => 'string',
self::FIELD_BOOL => 'bool',
self::FIELD_INTEGER => 'int',
self::FIELD_FLOAT => 'float',
self::FIELD_COUNTER => 'int',
);
if (isset($conv[$type])) {
settype($value, $conv[$type]);
return $value;
}
if ($type == self::FIELD_DATE)
return new TDate($value); // !!! experimental
if ($type == self::FIELD_DATETIME)
return new TDateTime($value); // !!! experimental
return $value;
}
/** these are the required IteratorAggregate functions */
public function getIterator($offset = NULL, $count = NULL)
{
return new DibiResultIterator($this, $offset, $count);
}
/** end required IteratorAggregate functions */
/** these are the required Countable functions */
public function count()
{
return $this->rowCount();
}
/** end required Countable functions */
} // class DibiResult
/**
* Basic Result set iterator.
*
* This can be returned by DibiResult::getIterator() method or directly using foreach:
* <code>
* $result = dibi::query('SELECT * FROM table');
* foreach ($result as $fields) {
* print_r($fields);
* }
* unset($result);
* </code>
*
* Optionally you can specify offset and limit:
* <code>
* foreach ($result->getIterator(2, 3) as $fields) {
* print_r($fields);
* }
* </code>
*/
class DibiResultIterator implements Iterator
{
private
$result,
$offset,
$count,
$record,
$row;
public function __construct(DibiResult $result, $offset = NULL, $count = NULL)
{
$this->result = $result;
$this->offset = (int) $offset;
$this->count = $count === NULL ? PHP_INT_MAX : (int) $count;
}
/** these are the required Iterator functions */
public function rewind()
{
$this->row = 0;
@$this->result->seek($this->offset);
$this->record = $this->result->fetch();
}
public function key()
{
return $this->row;
}
public function current()
{
return $this->record;
}
public function next()
{
$this->record = $this->result->fetch();
$this->row++;
}
public function valid()
{
return is_array($this->record) && ($this->row < $this->count);
}
/** end required Iterator functions */
} // class DibiResultIterator
?>

40
examples/connect.php Normal file
View File

@@ -0,0 +1,40 @@
<?php
require_once '../dibi/dibi.php';
// use two connections:
// first connection to mysql
$state = dibi::connect(array(
'driver' => 'mysql',
'host' => 'localhost',
'username' => 'root',
'password' => '***',
'database' => 'test',
'charset' => 'utf8',
), 1);
if ($state instanceof Exception) {
echo $state;
}
if (!dibi::isConnected()) {
die();
}
// second connection to odbc
dibi::connect(array(
'driver' => 'odbc',
'username' => 'root',
'password' => '***',
'database' => 'Driver={Microsoft Access Driver (*.mdb)};Dbq=C:\\Database.mdb',
), 3);
echo dibi::isConnected();
?>

52
examples/fetch.php Normal file
View File

@@ -0,0 +1,52 @@
<pre>
<?php
require_once '../dibi/dibi.php';
dibi::$debug = true;
// mysql
dibi::connect(array(
'driver' => 'mysqli',
'host' => 'localhost',
'username' => 'root',
'password' => '***',
'database' => 'test',
'charset' => 'utf8',
));
if (!dibi::isConnected())
die('Not connected');
$res = dibi::query('SELECT * FROM table');
// fetch a single value
$value = $res->fetchSingle();
// fetch complete result set
$all = $res->fetchAll();
// fetch complete result set like association array
$assoc = $res->fetchAll('id');
$assoc = $res->fetchAll('id', 'id2');
// fetch complete result set like pairs key => value
$pairs = $res->fetchPairs('id', 'name');
// fetch row by row
foreach ($res as $row => $fields) {
print_r($fields);
}
// fetch row by row with defined offset and limit
foreach ($res->getIterator(2, 3) as $row => $fields) {
print_r($fields);
}
?>

14
examples/log.sql Normal file
View File

@@ -0,0 +1,14 @@
Successfully connected to DB 'mysql'
SELECT * FROM `nucleus_item` WHERE `inumber` = 38;
-- Result: object(DibiMySqlResult) rows: 1
-- Takes: 4.994 ms
SELECT * FROM `nucleus_item` WHERE `inumber` < 38;
-- Result: object(DibiMySqlResult) rows: 29
-- Takes: 135.842 ms
SELECT * FROM `*nucleus_item` WHERE `inumber` < 38;
-- Result: Query error: Can't find file: '.\dgx\*nucleus_item.frm' (errno: 22)
-- Takes: 121.454 ms

31
examples/logging.php Normal file
View File

@@ -0,0 +1,31 @@
<pre>
<?php
require_once '../dibi/dibi.php';
dibi::$logfile = 'log.sql';
// mysql
dibi::connect(array(
'driver' => 'mysql',
'host' => 'localhost',
'username' => 'root',
'password' => '***',
'database' => 'test',
'charset' => 'utf8',
));
$res = dibi::query('SELECT * FROM [nucleus_item] WHERE [inumber] = %i', 38);
$res = dibi::query('SELECT * FROM [nucleus_item] WHERE [inumber] < %i', 38);
$res = dibi::query('SELECT * FROM [*nucleus_item] WHERE [inumber] < %i', 38);
?>

34
examples/metatypes.php Normal file
View File

@@ -0,0 +1,34 @@
<pre>
<?php
require_once '../dibi/dibi.php';
// mysql
dibi::connect(array(
'driver' => 'mysql',
'host' => 'localhost',
'username' => 'root',
'password' => '***',
'database' => 'test',
'charset' => 'utf8',
));
$res = dibi::query('SELECT * FROM [nucleus_item] WHERE [inumber] <> %i', 38);
$res = dibi::query('SELECT * FROM [nucleus_item] WHERE [inumber] <> %i', 38);
// auto-convert this field to integer
$res->setType('inumber', DibiResult::FIELD_INTEGER);
$record = $res->fetch();
var_dump($record);
// auto-detect all types
$res->setType(TRUE);
$record = $res->fetch();
var_dump($record);
?>

48
examples/sql-builder.php Normal file
View File

@@ -0,0 +1,48 @@
<pre>
<?php
require_once '../dibi/dibi.php';
// mysql
dibi::connect(array(
'driver' => 'mysqli',
'host' => 'localhost',
'username' => 'root',
'password' => '***',
'database' => 'test',
'charset' => 'utf8',
));
$arr1 = array(1, 2, 3);
$arr2 = array('one', 'two', 'three');
$arr3 = array(
'a' => 'one',
'b' => 'two',
'c' => 'three',
);
$arr4 = array(
'A' => 12,
'B' => NULL,
'C' => new TDateTime(31542),
'D' => 'string',
);
dibi::test(
"
SELECT *
FROM [test]
WHERE ([test.a] LIKE %T", '1995-03-01', "
OR [b1] IN (", $arr1, ")
OR [b2] IN (", $arr2, ")
OR [b3] IN (%N", $arr3, ")
OR [b4] IN %V", $arr4, "
AND [c] = 'embedded '' string'
OR [d]=%d", 10.3, "
OR [true]=", true, "
OR [false]=", false, "
OR [null]=", NULL, "
LIMIT 10");
?>

271
license/license.gpl.cz.txt Normal file
View File

@@ -0,0 +1,271 @@
----------------------------------------------------------------------------------
Tento text je neofici<63>ln<6C>m p<>ekladem GNU General Public License (GNU GPL). Nebyl
vyd<EFBFBD>n nadac<61> Free Software Foundation a nevyjad<61>uje pr<70>vn<76> podstatu podm<64>nek pro
<EFBFBD><EFBFBD><EFBFBD>en<EFBFBD> softwaru pou<6F><75>vaj<61>c<EFBFBD>ho GNU GPL - tomuto <20><>elu slou<6F><75> v<>hradn<64> p<>vodn<64>
anglick<EFBFBD> verze GNU GPL. P<>esto douf<75>me, <20>e tento p<>eklad pom<6F><6D>e <20>esk<73>m <20>ten<65><6E><EFBFBD>m
l<EFBFBD>pe porozum<75>t licenci GNU GPL.
----------------------------------------------------------------------------------
GNU GENERAL PUBLIC LICENSE
<20>esk<73> p<>eklad verze 2, <20>erven 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
Kop<6F>rov<6F>n<EFBFBD> a distribuce doslovn<76>ch kopi<70> tohoto licen<65>n<EFBFBD>ho dokumentu jsou
dovoleny komukoliv, jeho zm<7A>ny jsou v<>ak zak<61>z<EFBFBD>ny.
Preambule
Softwarov<6F> licence jsou v<>t<EFBFBD>inou navr<76>eny tak, <20>e v<>m odeb<65>raj<61> pr<70>vo svobodn<64>ho
sd<EFBFBD>len<EFBFBD> a <20>prav program<61>. Smyslem GNU General Public License je naproti tomu
zaru<EFBFBD>it svobodu ke sd<73>len<65> a <20>prav<61>m svobodn<64>ho softwaru - pro zaji<6A>t<EFBFBD>n<EFBFBD>
svobodn<EFBFBD>ho p<><70>stupu k tomuto softwaru pro v<>echny jeho u<>ivatele. Tato General
Public License se vztahuje na v<>t<EFBFBD>inu softwaru nadace Free Software Foundation a
na jak<61>koli jin<69> program, jeho<68> autor se p<>iklon<6F> k jej<65>mu pou<6F><75>v<EFBFBD>n<EFBFBD>. (N<>kter<65>
dal<EFBFBD><EFBFBD> software od Free Software Foundation je nam<61>sto toho pokryt GNU Lesser
General Public License.) M<><4D>ete ji rovn<76><6E> pou<6F><75>t pro sv<73> programy.
Pokud mluv<75>me o svobodn<64>m softwaru, m<>me na mysli svobodu, nikoliv cenu. Na<4E>e
General Public License je navr<76>ena pro zaji<6A>t<EFBFBD>n<EFBFBD> toho, <20>e m<><6D>ete svobodn<64> <20><><EFBFBD>it
kopie svobodn<64>ho softwaru (a <20><>tovat si poplatek za tuto slu<6C>bu, pokud chcete),
<EFBFBD>e obdr<64><72>te zdrojov<6F> k<>d anebo jej m<><6D>ete z<>skat, pokud ho chcete, <20>e m<><6D>ete
tento software modifikovat nebo jeho <20><>sti pou<6F><75>t v nov<6F>ch svobodn<64>ch programech;
a <20>e v<>te, <20>e tyto v<>ci sm<73>te d<>lat.
Abychom mohli va<76>e pr<70>va chr<68>nit, mus<75>me vytvo<76>it omezen<65>, kter<65> zak<61><6B><EFBFBD> komukoli
v<EFBFBD>m tato pr<70>va odep<65>rat nebo v<>s <20><>dat, abyste se t<>chto pr<70>v vzdal. Tato
omezen<EFBFBD> se prom<6F>taj<61> do jist<73>ch povinnost<73>, kter<65>m mus<75>te dost<73>t, pokud <20><><EFBFBD><EFBFBD>te
kopie doty<74>n<EFBFBD>ho softwaru anebo ho modifikujete.
Nap<61><70>klad, <20><><EFBFBD><EFBFBD>te-li kopie takov<6F>ho programu, a<> ji<6A> zdarma nebo za poplatek,
mus<EFBFBD>te poskytnout p<><70>jemc<6D>m v<>echna pr<70>va, kter<65> m<>te s<>m. Mus<75>te zaru<72>it, <20>e
p<EFBFBD><EFBFBD>jemci rovn<76><6E> dostanou anebo mohou z<>skat zdrojov<6F> k<>d. A mus<75>te jim uk<75>zat
tyto podm<64>nky, aby znali sv<73> pr<70>va.
Va<56>e pr<70>va chr<68>n<EFBFBD>me ve dvou kroc<6F>ch: (1) autorizac<61> softwaru a (2) nab<61>dkou t<>to
licence, kter<65> v<>m d<>v<EFBFBD> pr<70>voplatn<74> svolen<65> ke kop<6F>rov<6F>n<EFBFBD>, <20><><EFBFBD>en<65> a modifikaci
softwaru.
Kv<4B>li ochran<61> ka<6B>d<EFBFBD>ho autora i n<>s samotn<74>ch chceme zajistit, aby ka<6B>d<EFBFBD> ch<63>pal
skute<EFBFBD>nost, <20>e pro svobodn<64> software neplat<61> <20><>dn<64> z<>ruky. Je-li software n<>k<EFBFBD>m
jin<EFBFBD>m modifikov<6F>n a posl<73>n d<>le, chceme, aby p<><70>jemci v<>d<EFBFBD>li, <20>e to, co maj<61>,
nen<EFBFBD> origin<69>l, tak<61>e jak<61>koliv probl<62>my vnesen<65> jin<69>mi se neodraz<61> na reputaci
p<EFBFBD>vodn<EFBFBD>ch autor<6F>.
Kone<6E>n<EFBFBD>, ka<6B>d<EFBFBD> svobodn<64> program je neust<73>le ohro<72>en softwarov<6F>mi patenty.
P<EFBFBD>ejeme si zamezit nebezpe<70><65>, <20>e redistributo<74>i svobodn<64>ho programu obdr<64><72>
samostatn<EFBFBD> patentov<6F> osv<73>d<EFBFBD>en<65> a t<>m u<>in<69> program v<>zan<61>m. Abychom tomu
zamezili, deklarovali jsme, <20>e ka<6B>d<EFBFBD> patent mus<75> b<>t bu<62> vyd<79>n s t<>m, <20>e
umo<EFBFBD><EFBFBD>uje ka<6B>d<EFBFBD>mu svobodn<64> u<>it<69>, anebo nesm<73> b<>t vyd<79>n v<>bec.
P<>esn<73> ustanoven<65> a podm<64>nky pro kop<6F>rov<6F>n<EFBFBD>, <20><><EFBFBD>en<65> a modifikaci jsou uvedeny
d<EFBFBD>le.
USTANOVEN<45> A PODM<44>NKY PRO KOP<4F>ROV<4F>N<EFBFBD>, DISTRIBUCI A MODIFIKACI
0. Tato licence se vztahuje na kter<65>koliv program <20>i jin<69> d<>lo, kter<65> obsahuje
zm<EFBFBD>nku, um<75>st<73>nou v n<>m dr<64>itelem autorsk<73>ch pr<70>v, o tom, <20>e d<>lo m<><6D>e b<>t
<EFBFBD><EFBFBD><EFBFBD>eno podle ustanoven<65> GNU General Public License. V dal<61><6C>m textu znamen<65> "program"
ka<EFBFBD>d<EFBFBD> takov<6F> program nebo d<>lo a "d<>lo zalo<6C>en<65> na programu" znamen<65> bu<62> program
samotn<EFBFBD> anebo ka<6B>d<EFBFBD> jin<69> d<>lo z n<>j odvozen<65>, kter<65> podl<64>h<EFBFBD> autorsk<73>mu z<>konu:
t<EFBFBD>m se m<>n<EFBFBD> d<>lo obsahuj<75>c<EFBFBD> program nebo jeho <20><>st, bu<62> doslovn<76> anebo s
modifikacemi, pop<6F><70>pad<61> v p<>ekladu do jin<69>ho jazyka. (Nad<61>le je p<>eklad
zahrnov<EFBFBD>n bez omezen<65> pod pojem "modifikace".) Ka<4B>d<EFBFBD> u<>ivatel licence je
ozna<EFBFBD>ov<EFBFBD>n jako "vy".
Jin<EFBFBD> <20>innosti ne<6E> kop<6F>rov<6F>n<EFBFBD>, <20><><EFBFBD>en<65> a modifikace nejsou pokryty touto licenc<6E>;
sahaj<EFBFBD> mimo jej<65> r<>mec. Akt spu<70>t<EFBFBD>n<EFBFBD> programu nen<65> omezen a v<>stup z programu je
pokryt pouze tehdy, jestli<6C>e obsah v<>stupu tvo<76><6F> d<>lo zalo<6C>en<65> na programu (nez<65>visle
na tom, zda bylo vytvo<76>eno <20>innost<73> programu). Posouzen<65> platnosti p<>edchoz<6F>
v<EFBFBD>ty z<>vis<69> na tom, co program d<>l<EFBFBD>.
1. Sm<53>te kop<6F>rovat a <20><><EFBFBD>it doslovn<76> kopie zdrojov<6F>ho k<>du programu tak, jak jste
jej obdr<64>el a na libovoln<6C>m m<>diu, za p<>edpokladu, <20>e na ka<6B>d<EFBFBD> kopii viditeln<6C> a
n<EFBFBD>le<EFBFBD>it<EFBFBD> zve<76>ejn<6A>te zm<7A>nku o autorsk<73>ch pr<70>vech a absenci z<>ruky; ponech<63>te
nedot<EFBFBD>en<EFBFBD> v<>echny zm<7A>nky vztahuj<75>c<EFBFBD> se k t<>to licenci a k absenci z<>ruky; a d<>te
ka<EFBFBD>d<EFBFBD>mu p<><70>jemci spolu s programem kopii t<>to licence.
Za fyzick<63> akt p<>enesen<65> kopie m<><6D>ete <20><>dat poplatek a podle vlastn<74>ho uv<75><76>en<65>
m<EFBFBD><EFBFBD>ete nab<61>dnout za poplatek z<>ru<72>n<EFBFBD> ochranu.
2. M<><4D>ete modifikovat va<76>i kopii <20>i kopie programu anebo kter<65>koliv jeho <20><>sti,
a tak vytvo<76>it d<>lo zalo<6C>en<65> na programu a kop<6F>rovat a roz<6F>i<EFBFBD>ovat takov<6F>
modifikace <20>i d<>lo podle podm<64>nek paragrafu 1 v<><76>e, za p<>edpokladu, <20>e spln<6C>te
v<EFBFBD>echny tyto podm<64>nky:
a) Modifikovan<61> soubory mus<75>te opat<61>it z<>etelnou zm<7A>nkou uv<75>d<EFBFBD>j<EFBFBD>c<EFBFBD>, <20>e jste
soubory zm<7A>nil a datum ka<6B>d<EFBFBD> zm<7A>ny.
b) Mus<75>te umo<6D>nit, aby jak<61>koliv v<>mi publikovan<61> <20>i roz<6F>i<EFBFBD>ovan<61> d<>lo, kter<65>
obsahuje zcela nebo z<><7A>sti program nebo jakoukoli jeho <20><>st, pop<6F><70>pad<61> je z
programu nebo jeho <20><>sti odvozeno, mohlo b<>t jako celek bezplatn<74> poskytnuto
ka<6B>d<EFBFBD> t<>et<65> osob<6F> v souladu s ustanoven<65>mi t<>to licence.
c) Pokud modifikovan<61> program pracuje norm<72>ln<6C> tak, <20>e <20>te interaktivn<76> povely,
mus<75>te zajistit, <20>e p<>i nejb<6A><62>n<EFBFBD>j<EFBFBD><6A>m zp<7A>sobu jeho spu<70>t<EFBFBD>n<EFBFBD> vytiskne nebo zobraz<61>
hl<68><6C>en<65> zahrnuj<75>c<EFBFBD> p<><70>slu<6C>nou zm<7A>nku o autorsk<73>m pr<70>vu a uvede, <20>e neexistuje
<20><>dn<64> z<>ruka (nebo p<><70>padn<64>, <20>e z<>ruku poskytujete vy), a <20>e u<>ivatel<65> mohou za
t<>chto podm<64>nek program redistribuovat, a mus<75> u<>ivateli sd<73>lit, jak<61>m zp<7A>sobem
m<><6D>e nahl<68>dnout do kopie t<>to licence. (V<>jimka: v p<><70>pad<61>, <20>e s<>m program je
interaktivn<76>, av<61>ak <20><>dn<64> takov<6F> hl<68><6C>en<65> nevypisuje, nepo<70>aduje se, aby va<76>e
d<>lo zalo<6C>en<65> na programu takov<6F> hl<68><6C>en<65> vypisovalo.)
Tyto po<70>adavky se vztahuj<75> k modifikovan<61>mu d<>lu jako celku. Pokud lze
identifikovat <20><>sti takov<6F>ho d<>la, kter<65> z<>ejm<6A> nejsou odvozeny z programu a
mohou b<>t samy o sob<6F> rozumn<6D> pova<76>ov<6F>ny za nez<65>visl<73> a samostatn<74> d<>la, pak se
tato licence a jej<65> ustanoven<65> nevztahuj<75> na tyto <20><>sti, jsou-li <20><><EFBFBD>eny jako
nez<EFBFBD>visl<EFBFBD> d<>la. Av<41>ak jakmile tyt<79><74> <20><>sti roz<6F>i<EFBFBD>ujete jako <20><>st celku, j<>m<EFBFBD> je
d<EFBFBD>lo zalo<6C>en<65> na programu, mus<75> b<>t roz<6F>i<EFBFBD>ov<6F>n<EFBFBD> tohoto celku pod<6F><64>zeno
ustanoven<EFBFBD>m t<>to licence tak, <20>e povolen<65> poskytnut<75> dal<61><6C>m u<>ivatel<65>m se
roz<EFBFBD><EFBFBD><EFBFBD><EFBFBD> na cel<65> d<>lo, tedy na v<>echny jeho <20><>sti bez ohledu na to, kdo kterou
<EFBFBD><EFBFBD>st napsal.
Smyslem tohoto paragrafu tedy nen<65> z<>sk<73>n<EFBFBD> pr<70>v na d<>lo zcela napsan<61> v<>mi ani
pop<EFBFBD>r<EFBFBD>n<EFBFBD> va<76>ich pr<70>v v<><76>i n<>mu; skute<74>n<EFBFBD>m smyslem je v<>kon pr<70>va na <20><>zen<65>
distribuce odvozen<65>ch nebo kolektivn<76>ch d<>l zalo<6C>en<65>ch na programu.
Pouh<EFBFBD> spojen<65> jin<69>ho d<>la, je<6A> nen<65> na programu zalo<6C>eno, s programem (anebo
d<EFBFBD>lem zalo<6C>en<65>m na programu) na pam<61><6D>ov<6F>m nebo distribu<62>n<EFBFBD>m m<>diu neuvazuje toto
jin<EFBFBD> d<>lo do p<>sobnosti t<>to licence.
3. M<><4D>ete kop<6F>rovat a roz<6F>i<EFBFBD>ovat program (nebo d<>lo na n<>m zalo<6C>en<65>, viz
paragraf 2) v objektov<6F> anebo spustiteln<6C> podob<6F> podle ustanoven<65> paragraf<61> 1 a
2 v<><76>e, pokud spln<6C>te n<>kterou z n<>sleduj<75>c<EFBFBD>ch n<>le<6C>itost<73>:
a) Doprovod<6F>te jej zdrojov<6F>m k<>dem ve strojov<6F> <20>iteln<6C> form<72>. Zdrojov<6F> k<>d mus<75>
b<>t roz<6F>i<EFBFBD>ov<6F>n podle ustanoven<65> paragraf<61> 1 a 2 v<><76>e, a to na m<>diu b<><62>n<EFBFBD>
pou<6F><75>van<61>m pro v<>m<EFBFBD>nu softwaru; nebo
b) Doprovod<6F>te jej p<>semnou nab<61>dkou s platnost<73> nejm<6A>n<EFBFBD> t<>i roky, podle n<><6E>
poskytnete jak<61>koli t<>et<65> stran<61>, za poplatek nep<65>evy<76>uj<75>c<EFBFBD> va<76>e v<>daje
vynalo<6C>en<65> na fyzickou v<>robou zdrojov<6F> distribuce, kompletn<74> strojov<6F> <20>itelnou
kopii odpov<6F>daj<61>c<EFBFBD>ho zdrojov<6F>ho k<>du, jen<65> mus<75> b<>t <20><><EFBFBD>en podle ustanoven<65>
paragraf<61> 1 a 2 v<><76>e na m<>diu b<><62>n<EFBFBD> pou<6F><75>van<61>m pro v<>m<EFBFBD>nu softwaru; nebo
c) Doprovod<6F>te jej informacemi, kter<65> jste dostal ohledn<64> nab<61>dky na poskytnut<75>
zdrojov<6F>ho k<>du. (Tato alternativa je povolena jen pro nekomer<65>n<EFBFBD> <20><><EFBFBD>en<65> a jenom
tehdy, pokud jste obdr<64>el program v objektov<6F>m nebo spustiteln<6C>m tvaru spolu s
takovou nab<61>dkou, v souladu s polo<6C>kou b v<><76>e.)
Zdrojov<EFBFBD> k<>d k d<>lu je nejvhodn<64>j<EFBFBD><6A> formou d<>la z hlediska jeho p<><70>padn<64>ch
modifikac<EFBFBD>. Pro d<>lo ve spustiteln<6C>m tvaru znamen<65> <20>pln<6C> zdrojov<6F> k<>d ve<76>ker<65>
zdrojov<EFBFBD> k<>d pro v<>echny moduly, kter<65> obsahuje, plus jak<61>koli dal<61><6C> soubory pro
definici rozhran<61>, plus d<>vkov<6F> soubory pot<6F>ebn<62> pro kompilaci a instalaci
spustiteln<EFBFBD>ho programu. Zvl<76><6C>tn<74> v<>jimkou jsou v<>ak ty softwarov<6F> komponenty,
kter<EFBFBD> jsou norm<72>ln<6C> <20><><EFBFBD>eny (bu<62> ve zdrojov<6F> nebo bin<69>rn<72> form<72>) s hlavn<76>mi
sou<EFBFBD><EFBFBD>stmi opera<72>n<EFBFBD>ho syst<73>mu, na n<>m<EFBFBD> spustiteln<6C> program b<><62><EFBFBD> (tj. s
p<EFBFBD>eklada<EFBFBD>em, j<>drem apod.). Tyto komponenty nemus<75> b<>t <20><><EFBFBD>eny se zdrojov<6F>m k<>dem,
pokud ov<6F>em komponenta sama nedoprov<6F>z<EFBFBD> spustitelnou podobu d<>la.
Je-li <20><><EFBFBD>en<65> objektov<6F>ho nebo spustiteln<6C>ho k<>du <20>in<69>no nab<61>dkou p<><70>stupu ke
kop<EFBFBD>rov<EFBFBD>n<EFBFBD> z ur<75>it<69>ho m<>sta, potom se za distribuci zdrojov<6F>ho k<>du po<70><6F>t<EFBFBD> i
nab<EFBFBD>dnut<EFBFBD> ekvivalentn<74>ho p<><70>stupu ke kop<6F>rov<6F>n<EFBFBD> zdrojov<6F>ho k<>du ze stejn<6A>ho
m<EFBFBD>sta, by<62> p<>itom nejsou t<>et<65> strany nuceny ke zkop<6F>rov<6F>n<EFBFBD> zdrojov<6F>ho k<>du
spolu s objektov<6F>m.
4. Nesm<73>te kop<6F>rovat, modifikovat, poskytovat sublicence anebo <20><><EFBFBD>it program
jin<EFBFBD>m zp<7A>sobem ne<6E> v<>slovn<76> uveden<65>m v t<>to licenci. Jak<61>koli jin<69> pokus o
kop<EFBFBD>rov<EFBFBD>n<EFBFBD>, modifikov<6F>n<EFBFBD>, poskytnut<75> sublicence anebo <20><><EFBFBD>en<65> programu je
neplatn<EFBFBD> a automaticky ukon<6F><6E> va<76>e pr<70>va dan<61> touto licenc<6E>. Strany, kter<65> od
v<EFBFBD>s obdr<64>ely kopie anebo pr<70>va v souladu s touto licenc<6E>, v<>ak nemaj<61> sv<73>
licence ukon<6F>eny, dokud se jim pln<6C> pod<6F>izuj<75>.
5. Nen<65> va<76><61> povinost<73> tuto licenci p<>ijmout, proto<74>e jste ji nepodepsal. Nic
jin<EFBFBD>ho v<>m v<>ak ned<65>v<EFBFBD> mo<6D>nost kop<6F>rovat nebo <20><><EFBFBD>it program nebo odvozen<65> d<>la.
V p<><70>pad<61>, <20>e tuto licenci nep<65>ijmete, jsou tyto <20>innosti z<>konem zak<61>z<EFBFBD>ny. T<>m
p<EFBFBD>dem modifikac<61> anebo <20><><EFBFBD>en<65>m programu (anebo ka<6B>d<EFBFBD>ho d<>la zalo<6C>en<65>ho na
programu) vyjad<61>ujete sv<73> pod<6F><64>zen<65> se licenci a v<>em jej<65>m ustanoven<65>m a
podm<EFBFBD>nk<EFBFBD>m pro kop<6F>rovan<61>, modifikov<6F>n<EFBFBD> a <20><><EFBFBD>en<65> programu a d<>l na n<>m zalo<6C>en<65>ch.
6. Poka<6B>d<EFBFBD>, kdy<64> redistribuujete program (nebo d<>lo zalo<6C>en<65> na programu),
z<EFBFBD>sk<EFBFBD>v<EFBFBD> p<><70>jemce od p<>vodn<64>ho dr<64>itele licence pr<70>vo kop<6F>rovat, modifikovat a
<EFBFBD><EFBFBD><EFBFBD>it program v souladu s t<>mito ustanoven<65>mi a podm<64>nkami. Nesm<73>te kl<6B>st <20><>dn<64>
dal<EFBFBD><EFBFBD> p<>ek<65><6B>ky v<>konu zde zaru<72>en<65>ch p<><70>jemcov<6F>ch pr<70>v. Nejste odpov<6F>dn<64> za
vym<EFBFBD>h<EFBFBD>n<EFBFBD> dodr<64>ov<6F>n<EFBFBD> t<>to licence t<>et<65>mi stranami.
7. Jsou-li v<>m z rozhodnut<75> soudu, obvin<69>n<EFBFBD>m z poru<72>en<65> patentu nebo z
jak<EFBFBD>hokoli jin<69>ho d<>vodu (nejen v souvislosti s patenty) ulo<6C>eny takov<6F> podm<64>nky
(a<> ji<6A> p<><70>kazem soudu, smlouvou nebo jinak), kter<65> se vylu<6C>uj<75> s podm<64>nkami
t<EFBFBD>to licence, nejste t<>m osvobozen od podm<64>nek t<>to licence. Pokud nem<65><6D>ete
<EFBFBD><EFBFBD><EFBFBD>it program tak, abyste vyhov<6F>l z<>rove<76> sv<73>m z<>vazk<7A>m vypl<70>vaj<61>c<EFBFBD>m z t<>to
licence a jin<69>m platn<74>m z<>vazk<7A>m, nesm<73>te jej v d<>sledku toho <20><><EFBFBD>it v<>bec. Pokud
by nap<61><70>klad patentov<6F> osv<73>d<EFBFBD>en<65> nepovolovalo bezplatnou redistribuci programu
v<EFBFBD>emi, kdo va<76><61>m p<>i<EFBFBD>in<69>n<EFBFBD>m z<>skaj<61> p<><70>mo nebo nep<65><70>mo jeho kopie, pak by jedin<69>
mo<EFBFBD>n<EFBFBD> zp<7A>sob jak vyhov<6F>t z<>rove<76> patentov<6F>mu osv<73>d<EFBFBD>en<65> i t<>to licenci spo<70><6F>val v
ukon<EFBFBD>en<EFBFBD> distribuce programu.
Pokud by se za n<>jak<61>ch specifick<63>ch okolnost<73> jevila n<>kter<65> <20><>st tohoto
paragrafu jako neplatn<74> nebo nevynutiteln<6C>, pova<76>uje se za sm<73>rodatnou rovnov<6F>ha
vyj<EFBFBD>d<EFBFBD>en<EFBFBD> t<>mto paragrafem a paragraf jako celek se pova<76>uje za sm<73>rodatn<74> za
jin<EFBFBD>ch okolnost<73>.
Smyslem tohoto paragrafu nen<65> nav<61>d<EFBFBD>t v<>s k poru<72>ov<6F>n<EFBFBD> patent<6E> <20>i jin<69>ch
ustanoven<EFBFBD> vlastnick<63>ho pr<70>va, anebo tato ustanoven<65> zpochyb<79>ovat; jedin<69>m jeho
smyslem je ochrana integrity syst<73>mu <20><><EFBFBD>en<65> svobodn<64>ho softwaru, kter<65> je
podlo<EFBFBD>en ve<76>ejn<6A>mi licen<65>n<EFBFBD>mi p<>edpisy. Mnoz<6F> lid<69> poskytli sv<73> p<><70>sp<73>vky do
<EFBFBD>irok<EFBFBD>ho okruhu softwaru <20><><EFBFBD>en<65>ho t<>mto syst<73>mem, spolehnuv<75>e se na jeho
d<EFBFBD>sledn<EFBFBD> uplat<61>ov<6F>n<EFBFBD>; z<>le<6C><65> na autorovi/d<>rci, aby rozhodl, zda si p<>eje <20><><EFBFBD>it
software pomoc<6F> n<>jak<61>ho jin<69>ho syst<73>mu a <20><>dn<64> u<>ivatel licence nem<65><6D>e takov<6F>
rozhodnut<EFBFBD> zpochyb<79>ovat.
Smyslem tohoto paragrafu je zevrubn<62> osv<73>tlit to, co je pova<76>ov<6F>no za d<>sledek
plynouc<EFBFBD> ze zbytku t<>to licence.
8. Pokud je <20><><EFBFBD>en<65> <20>i pou<6F>it<69> programu v n<>kter<65>ch zem<65>ch omezeno bu<62> patenty
anebo autorsky chr<68>n<EFBFBD>n<EFBFBD>mi rozhran<61>mi, m<><6D>e dr<64>itel p<>vodn<64>ch autorsk<73>ch pr<70>v,
kter<EFBFBD> sv<73><76>uje program do p<>sobnosti t<>to licence, p<>idat v<>slovn<76> omezen<65> pro
geografick<EFBFBD> <20><><EFBFBD>en<65>, vylu<6C>uj<75>c<EFBFBD> takov<6F> zem<65>, tak<61>e <20><><EFBFBD>en<65> je povoleno jen v t<>ch
zem<EFBFBD>ch nebo mezi t<>mi zem<65>mi, kter<65> nejsou t<>mto zp<7A>sobem vylou<6F>eny. Tato
licence zahrnuje v tomto p<><70>pad<61> takov<6F> omezen<65> p<>esn<73> tak, jako by bylo zaps<70>no
v textu t<>to licence.
9. Free Software Foundation m<><6D>e <20>as od <20>asu vyd<79>vat upraven<65> nebo nov<6F> verze
General Public License. Takov<6F> nov<6F> verze se budou sv<73>m duchem podobat sou<6F>asn<73>
verzi, v jednotlivostech se v<>ak mohou li<6C>it s ohledem na nov<6F> probl<62>my <20>i z<>jmy.
Ka<EFBFBD>d<EFBFBD> verzi je p<>id<69>leno rozli<6C>uj<75>c<EFBFBD> <20><>slo verze. Pokud program specifikuje
<EFBFBD><EFBFBD>slo verze, kter<65> se na n<>j vztahuje, a "v<>echny n<>sleduj<75>c<EFBFBD> verze", m<><6D>ete se
podle uv<75><76>en<65> <20><>dit ustanoven<65>mi a podm<64>nkami bu<62>to on<6F> konkr<6B>tn<74> verze anebo
kter<EFBFBD>koliv n<>sleduj<75>c<EFBFBD> verze, kterou vydala Free Software Foundation. Jestli<6C>e
program nespecifikuje <20><>slo verze t<>to licence, m<><6D>ete si vybrat libovolnou
verzi, kterou kdy Free Software Foundation vydala.
10. Pokud si p<>ejete zahrnout <20><>sti programu do jin<69>ch svobodn<64>ch program<61>,
jejich<EFBFBD> distribu<62>n<EFBFBD> podm<64>nky jsou odli<6C>n<EFBFBD>, za<7A>lete autorovi <20><>dost o povolen<65>. V
p<EFBFBD><EFBFBD>pad<EFBFBD> softwaru, k n<>mu<6D> vlastn<74> autorsk<73> pr<70>va Free Software Foundation,
napi<EFBFBD>te Free Software Foundation; n<>kdy <20>in<69>me v<>jimky ze zde uveden<65>ch
ustanoven<EFBFBD>. Na<4E>e rozhodnut<75> bude vedeno dv<64>ma c<>li: zachov<6F>n<EFBFBD>m svobodn<64> povahy
v<EFBFBD>ech odvozenin na<6E>eho svobodn<64>ho softwaru a podporou sd<73>len<65> a op<6F>tovn<76>ho
vyu<EFBFBD>it<EFBFBD> softwaru obecn<63>.
Z<>RUKA SE NEPOSKYTUJE
11. VZHLEDEM K BEZPLATN<54>MU POSKYTNUT<55> LICENCE K PROGRAMU SE NA PROGRAM
NEVZTAHUJE <20><>DN<44> Z<>RUKA, A TO V M<><4D>E POVOLEN<45> PLATN<54>M Z<>KONEM. POKUD NEN<45>
P<EFBFBD>SEMN<EFBFBD> STANOVENO JINAK, POSKYTUJ<55> DR<44>ITEL<45> AUTORSK<53>CH PR<50>V POP<4F><50>PAD<41> JIN<49>
STRANY PROGRAM "TAK, JAK JE", BEZ Z<>RUKY JAK<41>HOKOLI DRUHU, A<> V<>SLOVN<56> NEBO
VYPL<EFBFBD>VAJ<EFBFBD>C<EFBFBD>, V<>ETN<54>, ALE NIKOLI JEN, Z<>RUK PRODEJNOSTI A VHODNOSTI PRO UR<55>IT<49>
<EFBFBD><EFBFBD>EL. POKUD JDE O KVALITU A V<>KONNOST PROGRAMU, LE<4C><45> VE<56>KER<45> RIZIKO NA V<>S.
POKUD BY SE U PROGRAMU PROJEVILY Z<>VADY, PADAJ<41> N<>KLADY ZA V<>ECHNU POT<4F>EBNOU
<EFBFBD>DR<EFBFBD>BU, OPRAVU <20>I N<>PRAVU NA V<><56> VRUB.
12. V <20><>DN<44>M P<><50>PAD<41>, S V<>JIMKOU TOHO, KDY<44> TO VY<56>ADUJE PLATN<54> Z<>KON, ANEBO KDY<44>
TO BYLO P<>SEMN<4D> ODSOUHLASENO, V<>M NEBUDE <20><>DN<44> Z DR<44>ITEL<45> AUTORSK<53>CH PR<50>V ANI
<EFBFBD><EFBFBD>DN<EFBFBD> JIN<49> STRANA, KTER<45> SM<53> MODIFIKOVAT <20>I <20><><EFBFBD>IT PROGRAM V SOULADU S
P<EFBFBD>EDCHOZ<EFBFBD>MI USTANOVEN<45>MI, ODPOV<4F>DNI ZA <20>KODY, V<>ETN<54> V<>ECH OBECN<43>CH, SPECI<43>LN<4C>CH,
NAHODIL<EFBFBD>CH NEBO N<>SLEDN<44>CH <20>KOD VYPL<50>VAJ<41>C<EFBFBD>CH Z U<><55>V<EFBFBD>N<EFBFBD> ANEBO NESCHOPNOSTI
U<EFBFBD><EFBFBD>VAT PROGRAMU (V<>ETN<54>, ALE NIKOLI JEN, ZTR<54>TY NEBO ZKRESLEN<45> DAT, NEBO
TRVAL<EFBFBD>CH <20>KOD ZP<5A>SOBEN<45>CH V<>M NEBO T<>ET<45>M STRAN<41>M, NEBO SELH<4C>N<EFBFBD> FUNKCE PROGRAMU
V SOU<4F>INNOSTI S JIN<49>MI PROGRAMY), A TO I V P<><50>PAD<41>, <20>E TAKOV<4F> DR<44>ITEL AUTORSK<53>CH
PR<EFBFBD>V NEBO JIN<49> STRANA BYLI UPOZORN<52>NI NA MO<4D>NOST TAKOV<4F>CH <20>KOD.
KONEC USTANOVEN<45> A PODM<44>NEK
----------------------------------------------------------------------------------
(c) 2004, Str<74>nky o svobodn<64>m software (info@gnu.cz)
Tento p<>eklad je z velk<6C> <20><>sti zalo<6C>en na p<>ekladu od Ladislava Lhotky.
V p<><70>pad<61> dopl<70>uj<75>c<EFBFBD>ch informac<61> nebo oprav kontaktujte maintainera: kysela@gnu.cz
Posledn<EFBFBD> <20>prava: 22. 12. 2004
----------------------------------------------------------------------------------

279
license/license.gpl.txt Normal file
View File

@@ -0,0 +1,279 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS