<?php
// OpenRat Content Management System
// Copyright (C) 2002-2009 Jan Dankert, hide@address.com
//
// 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.
// Standard Mime-Type
define('OR_FILE_DEFAULT_MIMETYPE','application/octet-stream');
/**
* Datei.
*
* @author Jan Dankert
* @package openrat.objects
*/
class File extends Object
{
var $fileid;
var $size = 0;
var $value = '';
var $extension = '';
var $log_filenames = array();
var $fullFilename = '';
var $publish = null;
var $mime_type = '';
/**
* Breite eines Bildes. Ist nur verfuegbar, wenn vorher
* #getImageSize() aufgerufen wurde.
*/
var $width = null;
/**
* Hoehe eines Bildes. Ist nur verfuegbar, wenn vorher
* #getImageSize() aufgerufen wurde.
*/
var $height = null;
var $tmpfile;
var $content_negotiation = false;
/**
* Um Probleme mit BLOB-Feldern und Datenbank-Besonderheiten zu vermeiden,
* kann der Binaerinhalt BASE64-kodiert gespeichert werden.
* @type Boolean
*/
var $storeValueAsBase64 = false;
/**
* Konstruktor
*
* @param Objekt-Id
*/
function File( $objectid='' )
{
global $conf,$SESS;
$db = Session::getDatabase();
$this->storeValueAsBase64 = $db->conf['base64'];
$this->Object( $objectid );
$this->isFile = true;
}
/**
* Ermitteln des Dateinamens dieser Datei
*
* @return String Kompletter Dateiname, z.B. '/pfad/datei.jpeg'
*/
function full_filename()
{
if ( !empty($this->fullFilename) )
return $this->fullFilename;
$filename = parent::full_filename();
if ( $this->content_negotiation && config('publish','negotiation','file_negotiate_type' ) )
{
// Link auf Datei: Extension bleibt aufgrund Content-Negotiation leer
}
else
{
if ( !empty($this->extension) )
$filename .= '.'.$this->extension;
}
$this->fullFilename = $filename;
return $filename;
}
/**
* Ermitteln des Dateinamens dieser Datei (ohne Pfadangabe)
*
* @return String Kompletter Dateiname, z.B. '/pfad/datei.jpeg'
*/
function filenameWithExtension()
{
if ( $this->extension != '' )
return $this->filename.'.'.$this->extension;
else return $this->filename;
}
/**
* Ermitteln aller Eigenschaften
*
* @return Array
*/
function getProperties()
{
return array_merge( parent::getProperties(),
array('full_filename'=>$this->fullFilename,
'extension' =>$this->extension,
'size' =>$this->size,
'mimetype' =>$this->mimetype() ) );
}
/**
* @deprecated
*/
function getFileObjectIdsByExtension( $extension )
{
global $SESS;
$db = db_connection();
$sqlquery = 'SELECT * FROM {t_object} ';
if ( $extension != '' )
{
$sqlquery .= " WHERE extension='";
$ext = explode(',',$extension);
$sqlquery .= implode( "' OR extension='",$ext );
$sqlquery .= "' AND is_file=1 AND projectid={projectid}";
}
else
{
$sqlquery .= " WHERE is_file=1 AND projectid={projectid}";
}
$sql = new Sql( $sqlquery );
$sql->setInt( 'projectid',$SESS['projectid'] );
return $db->getCol( $sql );
}
/**
* Es werden Objekte zu einer Dateierweiterung ermittelt
*
* @param String Dateierweiterung ohne fuehrenden Punkt (z.B. 'jpeg')
* @return Array Liste der gefundenen Objekt-IDs
*/
function getObjectIdsByExtension( $extension )
{
$db = db_connection();
$sql = new Sql( 'SELECT {t_file}.objectid FROM {t_file} '.
' LEFT JOIN {t_object} '.
' ON {t_object}.id={t_file}.objectid'.
' WHERE {t_file}.extension={extension}'.
' AND {t_object}.projectid={projectid}' );
$sql->setInt ( 'projectid',$this->projectid );
$sql->setString( 'extension',$extension );
return $db->getCol( $sql );
}
/**
* Ermittelt den Mime-Type zu dieser Datei
*
* @return String Mime-Type
*/
function mimeType()
{
if ( !empty( $this->mime_type ) )
return $this->mime_type;
global $conf;
$mime_types = $conf['mime-types'];
$ext = strtolower( $this->getRealExtension() );
if ( !empty($mime_types[$ext]) )
$this->mime_type = $mime_types[$ext];
else
// Wenn kein Mime-Type gefunden, dann Standartwert setzen
$this->mime_type = OR_FILE_DEFAULT_MIMETYPE;
return( $this->mime_type );
}
/**
* Ermittelt Breite und H�he des Bildes.<br>
* Die Werte lassen sich anschlie�end �ber die Eigenschaften "width" und "height" ermitteln.
*/
function getImageSize()
{
if ( is_null($this->width) )
{
$this->write(); // Datei schreiben
// Bildinformationen ermitteln
$size = getimagesize( $this->tmpfile() );
// Breite und Hoehe des aktuellen Bildes
$this->width = $size[0];
$this->height = $size[1];
}
}
/**
* Veraendert die Bildgroesse eines Bildes
*
* Diese Methode sollte natuerlich nur bei Bildern ausgefuehrt werden.
*
* @param Neue Breite
* @param Neue Hoehe
* @param Bildgr��enfaktor
* @param Altes Format als Integer-Konstante IMG_xxx
* @param Neues Format als Integer-Konstante IMG_xxx
* @param Jpeg-Qualitaet (sofern neues Format = Jpeg)
*/
function imageResize( $newWidth,$newHeight,$factor,$oldformat,$newformat,$jpegquality )
{
global $conf;
$this->write(); // Datei schreiben
// Bildinformationen ermitteln
$size = getimagesize( $this->tmpfile() );
// Breite und Hoehe des aktuellen Bildes
$oldWidth = $size[0];
$oldHeight = $size[1];
$aspectRatio = $oldHeight / $oldWidth; // Seitenverhaeltnis
// Wenn Breite und Hoehe fehlen, dann Bildgroesse beibehalten
if ( $newWidth == 0 && $newHeight == 0)
{
if ( $factor != 0 && $factor != 1 )
{
$newWidth = $oldWidth * $factor;
$newHeight = $oldHeight * $factor;
$resizing = true;
}
else
{
$newWidth = $oldWidth;
$newHeight = $oldHeight;
$resizing = false;
}
}
else
{
$resizing = true;
}
// Wenn nur Breite oder Hoehe angegeben ist, dann
// das Seitenverhaeltnis beibehalten
if ( $newWidth == 0 )
$newWidth = $newHeight / $aspectRatio;
if ( $newHeight == 0 )
$newHeight = $newWidth * $aspectRatio;
switch( $oldformat )
{
case IMG_GIF: // GIF
$oldImage = ImageCreateFromGIF( $this->tmpfile );
break;
case IMG_JPG: // JPEG
$oldImage = ImageCreateFromJPEG($this->tmpfile);
break;
case IMG_PNG: // PNG
$oldImage = imagecreatefrompng($this->tmpfile);
break;
default:
die('unsupported image format "'.$this->extension.'", cannot load image. resize failed');
}
// Ab Version 2 der GD-Bibliothek sind TrueColor-Umwandlungen moeglich.
global $conf;
$hasTrueColor = $conf['image']['truecolor'];
switch( $newformat )
{
case IMG_GIF: // GIF
if ( $resizing )
{
$newImage = ImageCreate($newWidth,$newHeight);
ImageCopyResized($newImage,$oldImage,0,0,0,0,$newWidth,
$newHeight,$oldWidth,$oldHeight);
}
else
{
$newImage = &$oldImage;
}
ImageGIF($newImage, $this->tmpfile() );
$this->extension = 'gif';
break;
case IMG_JPG: // JPEG
if ( !$resizing )
{
$newImage = &$oldImage;
}
elseif ( $hasTrueColor )
{
// Verwende TrueColor (GD2)
$newImage = imageCreateTrueColor( $newWidth,$newHeight );
ImageCopyResampled($newImage,$oldImage,0,0,0,0,$newWidth,
$newHeight,$oldWidth,$oldHeight);
}
else
{
// GD Version 1.x unterstuetzt kein TrueColor
$newImage = ImageCreate($newWidth,$newHeight);
ImageCopyResized($newImage,$oldImage,0,0,0,0,$newWidth,
$newHeight,$oldWidth,$oldHeight);
}
ImageJPEG($newImage, $this->tmpfile,$jpegquality );
$this->extension = 'jpeg';
break;
case IMG_PNG: // PNG
if ( !$resizing )
{
$newImage = &$oldImage;
}
elseif ( $hasTrueColor )
{
// Verwende TrueColor (GD2)
$newImage = imageCreateTrueColor( $newWidth,$newHeight );
ImageCopyResampled($newImage,$oldImage,0,0,0,0,$newWidth,
$newHeight,$oldWidth,$oldHeight);
}
else
{
// GD Version 1.x unterstuetzt kein TrueColor
$newImage = ImageCreate($newWidth,$newHeight);
ImageCopyResized($newImage,$oldImage,0,0,0,0,$newWidth,
$newHeight,$oldWidth,$oldHeight);
}
imagepng( $newImage,$this->tmpfile() );
$this->extension = 'png';
break;
default:
die('unsupported image format "'.$newformat.'", cannot resize');
}
$f = fopen( $this->tmpfile(), "r" );
$this->value = fread( $f,filesize($this->tmpfile()) );
fclose( $f );
imagedestroy( $oldImage );
//imagedestroy( $newImage );
}
/**
* Lesen der Datei aus der Datenbank.
*
* Es werden nur die Meta-Daten (Erweiterung, Gr��e) gelesen. Zum Lesen des
* Datei-Inhaltes muss #loadValue() aufgerufen werden.
*/
function load()
{
$db = db_connection();
$sql = new Sql( 'SELECT id,extension,size'.
' FROM {t_file}'.
' WHERE objectid={objectid}' );
$sql->setInt( 'objectid',$this->objectid );
$row = $db->getRow( $sql );
if ( count($row)!=0 )
{
$this->fileid = $row['id' ];
$this->extension = $row['extension'];
$this->size = $row['size' ];
}
$this->objectLoad();
}
/**
* Unwiderrufliches L�schen der Datei aus der Datenbank.
*/
function delete()
{
$db = db_connection();
// Datei l?schen
$sql = new Sql( 'DELETE FROM {t_file} '.
' WHERE objectid={objectid}' );
$sql->setInt( 'objectid',$this->objectid );
$db->query( $sql );
$this->objectDelete();
}
/**
* Stellt anhand der Dateiendung fest, ob es sich bei dieser Datei um ein Bild handelt
*/
function isImage()
{
return substr($this->mimeType(),0,6)=='image/';
}
/**
* Ermittelt die Datei-Endung.
*
* @return String Datei-Endung
*/
function extension()
{
if ($this->extension != '')
return $this->extension;
$this->load();
return $this->extension;
}
/**
* Einen Dateinamen in Dateiname und Extension aufteilen.
* @param filename Dateiname
*/
function parse_filename($filename)
{
$filename = basename($filename);
$p = strrpos($filename, '.');
if ($p !== false)
{
$this->extension = substr($filename, $p +1);
$this->filename = substr($filename, 0, $p);
}
else
{
$this->extension = '';
$this->filename = $filename;
}
}
/**
* Speichert die Datei-Informationen in der Datenbank.
*/
function save()
{
global $SESS;
$db = db_connection();
$sql = new Sql( <<<EOF
UPDATE {t_file} SET
size = {size},
extension = {extension}
WHERE objectid={objectid}
EOF
);
$sql->setString('size' ,$this->size );
$sql->setString('extension',$this->extension );
$sql->setString('objectid' ,$this->objectid );
$db->query( $sql );
$this->objectSave();
}
/**
* Kopieren des Inhaltes von einer anderen Datei
* @param ID der Datei, von der der Inhalt kopiert werden soll
*/
function copyValueFromFile( $otherfileid )
{
$of = new File( $otherfileid );
$this->value = $of->loadValue();
$this->saveValue();
}
/**
* Lesen des Inhaltes der Datei aus der Datenbank.
*
* @return String Inhalt der Datei
*/
function loadValue()
{
if ( is_file($this->tmpfile()))
return implode('',file($this->tmpfile())); // From cache
$db = db_connection();
$sql = new Sql( 'SELECT size,value'.
' FROM {t_file}'.
' WHERE objectid={objectid}' );
$sql->setInt( 'objectid',$this->objectid );
$row = $db->getRow( $sql );
if ( count($row) != 0 )
{
$this->value = $row['value'];
$this->size = $row['size' ];
}
if ( $this->storeValueAsBase64 )
$this->value = base64_decode( $this->value );
// Store in cache.
$f = fopen( $this->tmpfile(),'w' );
fwrite( $f,$this->value );
fclose( $f );
return $this->value;
}
/**
* Speichert den Inhalt in der Datenbank.
*/
function saveValue( $value = '' )
{
if ( is_file($this->tmpfile()) )
@unlink( $this->tmpfile() );
$db = db_connection();
$sql = new Sql( 'UPDATE {t_file}'.
' SET value={value}, '.
' size={size} '.
' WHERE objectid={objectid}' );
$sql->setString( 'objectid' ,$this->objectid );
$sql->setInt ( 'size' ,strlen($this->value) );
if ( $this->storeValueAsBase64 )
$sql->setString( 'value',base64_encode($this->value) );
else
$sql->setString( 'value',$this->value );
$db->query( $sql );
}
/**
* Lesen der Datei aus der Datenbank und schreiben in temporaere Datei
*/
function write()
{
if ( !is_file($this->tmpfile()) )
$this->loadValue();
}
/**
* F�gt die Datei der Datenbank hinzu.
*/
function add()
{
$db = db_connection();
$this->objectAdd();
$sql = new Sql('SELECT MAX(id) FROM {t_file}');
$this->fileid = intval($db->getOne($sql))+1;
$sql = new Sql('INSERT INTO {t_file}'.
' (id,objectid,extension,size,value)'.
" VALUES( {fileid},{objectid},{extension},0,'' )" );
$sql->setInt ('fileid' ,$this->fileid );
$sql->setInt ('objectid' ,$this->objectid );
$sql->setString('extension',$this->extension );
$db->query( $sql );
$this->saveValue();
}
function publish()
{
if ( ! is_object($this->publish) )
$this->publish = new Publish();
$this->write();
$this->publish->copy( $this->tmpfile(),$this->full_filename(),$this->lastchangeDate );
$this->publish->publishedObjects[] = $this->getProperties();
}
/**
* Ermittelt einen tempor�ren Dateinamen f�r diese Datei.
*/
function tmpfile()
{
if ( $this->tmpfile == '' )
{
$db = db_connection();
$this->tmpfile = $this->getTempDir().'/openrat_db'.$db->id.'_'.$this->objectid.'.tmp';
}
return $this->tmpfile;
}
/**
* Setzt den Zeitstempel der Datei auf die aktuelle Zeit.
*
* @see objectClasses/Object#setTimestamp()
*/
function setTimestamp()
{
@unlink( $this->tmpfile() );
parent::setTimestamp();
}
/**
* Ermittelt die wirksame Datei-Endung. Diese kann sich
* in der Extra-Dateiendung, aber auch direkt im Dateiname
* befinden.
*
* @return Dateiendung
*/
function getRealExtension()
{
if ( !empty($this->extension))
{
return $this->extension;
}
else
{
$pos = strrpos($this->filename,'.');
if ( $pos === false )
return '';
else
return substr($this->filename,$pos+1);
}
}
}
?>