File.class.php (18423B)
1 <?php 2 namespace cms\model; 3 // OpenRat Content Management System 4 // Copyright (C) 2002-2012 Jan Dankert, cms@jandankert.de 5 // 6 // This program is free software; you can redistribute it and/or 7 // modify it under the terms of the GNU General Public License 8 // as published by the Free Software Foundation; either version 2 9 // of the License, or (at your option) any later version. 10 // 11 // This program is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 // 16 // You should have received a copy of the GNU General Public License 17 // along with this program; if not, write to the Free Software 18 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 20 21 // Standard Mime-Type 22 use cms\base\Configuration; 23 use cms\base\DB as Db; 24 use util\cache\FileCache; 25 26 27 /** 28 * File. 29 * 30 * @author Jan Dankert 31 */ 32 class File extends BaseObject 33 { 34 const DEFAULT_MIMETYPE = 'application/octet-stream'; 35 36 public $fileid; 37 38 public $contentid = null; 39 40 public $size = 0; 41 public $value = ''; 42 public $extension = ''; 43 public $log_filenames = array(); 44 public $fullFilename = ''; 45 46 public $mime_type = ''; 47 48 public $tmpfile; 49 50 51 public static $MIME_TYPES = [ 52 'ez' => 'application/andrew-inset', 53 'csm' => 'application/cu-seeme', 54 'cu' => 'application/cu-seeme', 55 'tsp' => 'application/dsptype', 56 'spl' => 'application/x-futuresplash ', 57 'cpt' => 'image/x-corelphotopaint', 58 'hqx' => 'application/mac-binhex40', 59 'nb' => 'application/mathematica', 60 'mdb' => 'application/msaccess', 61 'doc' => 'application/msword', 62 'dot' => 'application/msword', 63 'bin' => 'application/octet-stream', 64 'oda' => 'application/oda', 65 'pdf' => 'application/pdf', 66 'pgp' => 'application/pgp-signature', 67 'ps' => 'application/postscript', 68 'ai' => 'application/postscript', 69 'eps' => 'application/postscript', 70 'rtf' => 'text/rtf', 71 'smi' => 'application/smil', 72 'smil' => 'application/smil', 73 'xls' => 'application/vnd.ms-excel', 74 'xlb' => 'application/vnd.ms-excel', 75 'ppt' => 'application/vnd.ms-powerpoint', 76 'pps' => 'application/vnd.ms-powerpoint', 77 'pot' => 'application/vnd.ms-powerpoint', 78 'sdw' => 'application/vnd.stardivision.writer', 79 'sgl' => 'application/vnd.stardivision.writer-global', 80 'vor' => 'application/vnd.stardivision.writer', 81 'sdc' => 'application/vnd.stardivision.calc', 82 'sda' => 'application/vnd.stardivision.draw', 83 'sdd' => 'application/vnd.stardivision.impress', 84 'sdp' => 'application/vnd.stardivision.impress-packed', 85 'smf' => 'application/vnd.stardivision.math', 86 'sds' => 'application/vnd.stardivision.chart', 87 'smd' => 'application/vnd.stardivision.mail', 88 'wbxml' => 'application/vnd.wap.wbxml ', 89 'wmlc' => 'application/vnd.wap.wmlc', 90 'wmlsc' => 'application/vnd.wap.wmlscriptc', 91 'wp5' => 'application/wordperfect5.1', 92 'zip' => 'application/zip', 93 'wk' => 'application/x-123', 94 'bcpio' => 'application/x-bcpio', 95 'vcd' => 'application/x-cdlink ', 96 'pgn' => 'application/x-chess-pgn', 97 'cpio' => 'application/x-cpio', 98 'csh' => 'text/x-csh', 99 'deb' => 'application/x-debian-package', 100 'dcr' => 'application/x-director', 101 'dir' => 'application/x-director', 102 'dxr' => 'application/x-director', 103 'wad' => 'application/x-doom', 104 'dms' => 'application/x-dms', 105 'dvi' => 'application/x-dvi', 106 'pfa' => 'application/x-font', 107 'pfb' => 'application/x-font', 108 'gsf' => 'application/x-font', 109 'pcf' => 'application/x-font', 110 'gnumeric' => 'application/x-gnumeric', 111 'gtar' => 'application/x-gtar', 112 'tgz' => 'application/x-gtar', 113 'taz' => 'application/x-gtar', 114 'hdf' => 'application/x-hdf', 115 'phtml' => 'text/html', 116 'pht' => 'text/html', 117 'php' => 'text/html', 118 'phps' => 'text/html', 119 'php3' => 'text/html', 120 'php3p' => 'text/html ', 121 'php4' => 'text/html', 122 'docbook' => 'application/docbook+xml', 123 'ica' => 'application/x-ica', 124 'jar' => 'application/x-java-archive', 125 'jnlp' => 'application/x-java-jnlp-file', 126 'ser' => 'application/x-java-serialized-object', 127 'class' => 'application/x-java-vm', 128 'js' => 'application/x-javascript', 129 'chrt' => 'application/x-kchart', 130 'kil' => 'application/x-killustrator', 131 'kpr' => 'application/x-kpresenter', 132 'kpt' => 'application/x-kpresenter', 133 'skp' => 'application/x-koan ', 134 'skd' => 'application/x-koan ', 135 'skt' => 'application/x-koan ', 136 'skm' => 'application/x-koan ', 137 'ksp' => 'application/x-kspread', 138 'kwd' => 'application/x-kword', 139 ' kwt' => 'application/x-kword', 140 'latex' => 'application/x-latex', 141 'lha' => 'application/x-lha', 142 'lzh' => 'application/x-lzh', 143 'lzx' => 'application/x-lzx', 144 'frm' => 'fbdocapplication/x-maker', 145 'maker' => 'fbdocapplication/x-maker', 146 'frame' => 'fbdocapplication/x-maker', 147 'fm' => 'fbdocapplication/x-maker', 148 'fb' => 'fbdocapplication/x-maker', 149 'book' => 'fbdocapplication/x-maker', 150 'mif' => 'application/x-mif', 151 'com' => 'application/x-msdos-program', 152 'exe' => 'application/x-msdos-program', 153 'bat' => 'application/x-msdos-program', 154 'dll' => 'application/x-msdos-program', 155 'msi' => 'application/x-msi', 156 'nc' => 'application/x-netcdf', 157 'cdf' => 'application/x-netcdf', 158 'pac' => 'application/x-ns-proxy-autoconfig', 159 'o' => 'application/x-object', 160 'ogg' => 'application/x-ogg', 161 'oza' => 'application/x-oz-application', 162 'pl' => 'application/x-perl', 163 'pm' => 'application/x-perl', 164 'crl' => 'application/x-pkcs7-crl', 165 'rpm' => 'audio/x-pn-realaudio-plugin ', 166 'shar' => 'application/x-shar', 167 'swf' => 'application/x-shockwave-flash', 168 'swfl' => 'application/x-shockwave-flash', 169 'sh' => 'text/x-sh', 170 'sit' => 'application/x-stuffit', 171 'sv4cpio' => 'application/x-sv4cpio', 172 'sv4crc' => 'application/x-sv4crc', 173 'tar' => 'application/x-tar', 174 'tcl' => 'text/x-tcl', 175 'tex' => 'text/x-tex', 176 'gf' => 'application/x-tex-gf', 177 'pk' => 'application/x-tex-pk', 178 'texinfo' => 'application/x-texinfo', 179 'texi' => 'application/x-texinfo', 180 '; "~"' => 'application/x-trash', 181 ';"%"' => 'application/x-trash', 182 'bak' => 'application/x-trash', 183 'old' => 'application/x-trash', 184 'sik' => 'application/x-trash', 185 't' => 'application/x-troff', 186 'tr' => 'application/x-troff', 187 'roff' => 'application/x-troff', 188 'man' => 'application/x-troff-man', 189 'me' => 'application/x-troff-me', 190 'ms' => 'application/x-troff-ms', 191 'ustar' => 'application/x-ustar', 192 'src' => 'application/x-wais-source', 193 'wz' => 'application/x-wingz', 194 'crt' => 'application/x-x509-ca-cert', 195 'fig' => 'application/x-xfig', 196 'au' => 'audio/basic', 197 'snd' => 'audio/basic', 198 'mid' => 'audio/midi', 199 'midi' => 'audio/midi', 200 'kar' => 'audio/midi', 201 'mpga' => 'audio/mpeg', 202 'mpega' => 'audio/mpeg', 203 'mp2' => 'audio/mpeg', 204 'mp3' => 'audio/mpeg', 205 'm3u' => 'audio/x-mpegurl', 206 'sid' => 'audio/prs.sid', 207 'aif' => 'audio/x-aiff', 208 'aiff' => 'audio/x-aiff', 209 'aifc' => 'audio/x-aiff', 210 'gsm' => 'audio/x-gsm', 211 'ra' => 'audio/x-realaudio ', 212 'rm' => 'audio/x-pn-realaudio', 213 'ram' => 'audio/x-pn-realaudio', 214 'pls' => 'audio/x-scpls', 215 'wav' => 'audio/x-wav', 216 'pdb' => 'chemical/x-pdb', 217 'xyz' => 'chemical/x-xyz ', 218 'bmp' => 'image/x-ms-bmp', 219 'gif' => 'image/gif', 220 'ief' => 'image/ief', 221 'jpeg' => 'image/jpeg', 222 'jpg' => 'image/jpeg', 223 'jpe' => 'image/jpeg', 224 'pcx' => 'image/pcx', 225 'png' => 'image/png', 226 'svg' => 'image/svg+xml', 227 'svgz' => 'image/svg+xml', 228 'tiff' => 'image/tiff', 229 'tif' => 'image/tiff', 230 'wbmp' => 'image/vnd.wap.wbmp', 231 'ras' => 'image/x-cmu-raster', 232 'cdr' => 'image/x-coreldraw', 233 'pat' => 'image/x-coreldrawpattern', 234 'cdt' => 'image/x-coreldrawtemplate', 235 'djvu' => 'image/x-djvu', 236 'djv' => 'image/x-djvu', 237 'jng' => 'image/x-jng', 238 'pnm' => 'image/x-portable-anymap', 239 'pbm' => 'image/x-portable-bitmap', 240 'pgm' => 'image/x-portable-graymap', 241 'ppm' => 'image/x-portable-pixmap', 242 'rgb' => 'image/x-rgb', 243 'xbm' => 'image/x-xbitmap', 244 'xpm' => 'image/x-xpixmap', 245 'xwd' => 'image/x-xwindowdump', 246 'igs' => 'model/iges', 247 'iges' => 'model/iges', 248 'msh' => 'model/mesh', 249 'mesh' => 'model/mesh', 250 'silo' => 'model/mesh', 251 'wrl' => 'x-world/x-vrml', 252 'vrml' => 'x-world/x-vrml', 253 'csv' => 'text/comma-separated-values', 254 'css' => 'text/css', 255 'htm' => 'text/html', 256 'html' => 'text/html', 257 'xhtml' => 'text/html', 258 'mml' => 'text/mathml', 259 'asc' => 'text/plain', 260 'txt' => 'text/plain', 261 'text' => 'text/plain', 262 'diff' => 'text/plain', 263 'rtx' => 'text/richtext', 264 'tsv' => 'text/tab-separated-values', 265 'wml' => 'text/vnd.wap.wml', 266 'wmls' => 'text/vnd.wap.wmlscript', 267 'xml' => 'text/xml', 268 'xsl' => 'text/xml', 269 'hpp' => 'text/x-c++hdr', 270 'hxx' => 'text/x-c++hdr', 271 'hh' => 'text/x-c++hdr', 272 'cpp' => 'text/x-c++src', 273 'cxx' => 'text/x-c++src', 274 'cc' => 'text/x-c++src', 275 'h' => 'text/x-chdr', 276 'c' => 'text/x-csrc', 277 'java' => 'text/x-java', 278 'moc' => 'text/x-moc', 279 'p' => 'text/x-pascal', 280 'pas' => 'text/x-pascal', 281 'etx' => 'text/x-setext', 282 'tk' => 'text/x-tcl', 283 'ltx' => 'text/x-tex', 284 'sty' => 'text/x-tex', 285 'cls' => 'text/x-tex', 286 'vcs' => 'text/x-vcalendar', 287 'vcf' => 'text/x-vcard', 288 'dl' => 'video/dl', 289 'fli' => 'video/fli', 290 'gl' => 'video/gl', 291 'mpeg' => 'video/mpeg', 292 'mpg' => 'video/mpeg', 293 'mpe' => 'video/mpeg', 294 'qt' => 'video/quicktime', 295 'mov' => 'video/quicktime', 296 'mxu' => 'video/vnd.mpegurl', 297 'mng' => 'video/x-mng', 298 'asf' => 'video/x-ms-asf', 299 'asx' => 'video/x-ms-asf', 300 'avi' => 'video/x-msvideo', 301 'movie' => 'video/x-sgi-movie', 302 'ice' => 'x-conference/x-cooltalk', 303 'vrm' => 'x-world/x-vrml', 304 ]; 305 306 /** 307 * Um Probleme mit BLOB-Feldern und Datenbank-Besonderheiten zu vermeiden, 308 * kann der Binaerinhalt BASE64-kodiert gespeichert werden. 309 * @type Boolean 310 */ 311 var $storeValueAsBase64 = false; 312 313 public $filterid; 314 public $public; 315 316 /** 317 * Konstruktor 318 * 319 * @param Objekt-Id 320 */ 321 function __construct( $objectid='' ) 322 { 323 parent::__construct( $objectid ); 324 $this->isFile = true; 325 $this->typeid = BaseObject::TYPEID_FILE; 326 } 327 328 329 /** 330 * @return FileCache 331 */ 332 public function getCache() { 333 $cacheKey = array('db'=>DB::get()->id,'file'=>$this->objectid,'publish'=> \util\ClassUtils::getSimpleClassName($this->publisher)); 334 335 return new FileCache( $cacheKey,function() { 336 return $this->loadValueFromDatabase(); 337 }, $this->lastchangeDate ); 338 } 339 340 341 342 /** 343 * Ermitteln aller Eigenschaften. 344 * 345 * @return array 346 */ 347 function getProperties() 348 { 349 return array_merge( parent::getProperties(), 350 array('full_filename'=>$this->fullFilename, 351 'extension' =>$this->extension, 352 'size' =>$this->size, 353 'filterid' =>$this->filterid ) ); 354 } 355 356 357 358 /** 359 * Es werden Objekte zu einer Dateierweiterung ermittelt 360 * 361 * @param String Dateierweiterung ohne fuehrenden Punkt (z.B. 'jpeg') 362 * @return array Liste der gefundenen Objekt-IDs 363 */ 364 public static function getObjectIdsByExtension( $extension ) 365 { 366 $db = \cms\base\DB::get(); 367 368 $sql = $db->sql( 'SELECT {{file}}.objectid FROM {{file}} '. 369 ' LEFT JOIN {{object}} '. 370 ' ON {{object}}.id={{file}}.objectid'. 371 ' WHERE {{file}}.extension={extension}' ); 372 $sql->setString( 'extension',$extension ); 373 374 return $sql->getCol(); 375 } 376 377 378 379 /** 380 * Ermittelt den Mime-Type zu dieser Datei 381 * 382 * @return String Mime-Type 383 * @deprecated use FileGenerator for this. 384 */ 385 public function mimeType() 386 { 387 if ( $this->mime_type ) 388 return $this->mime_type; 389 390 $ext = strtolower( $this->getRealExtension() ); 391 392 $this->mime_type = self::getMimeType( $ext ); 393 394 return( $this->mime_type ); 395 } 396 397 398 399 public static function getMimeType( $extension ) { 400 401 $mime_types = Configuration::subset('mime_types')->getConfig() + self::$MIME_TYPES; 402 403 $mimeType = @$mime_types[$extension]; 404 405 if ( $mimeType ) 406 return $mimeType; 407 else 408 // Fallback to default mime type 409 return self::DEFAULT_MIMETYPE; 410 } 411 412 413 /** 414 * Lesen der Datei aus der Datenbank. 415 * 416 * Es werden nur die Meta-Daten (Erweiterung, Gr��e) gelesen. Zum Lesen des 417 * Datei-Inhaltes muss #loadValue() aufgerufen werden. 418 */ 419 public function load() 420 { 421 $db = \cms\base\DB::get(); 422 423 $sql = $db->sql( 'SELECT id,contentid,extension,size,filterid'. 424 ' FROM {{file}}'. 425 ' WHERE objectid={objectid}' ); 426 $sql->setInt( 'objectid',$this->objectid ); 427 $row = $sql->getRow(); 428 429 if ( count($row)!=0 ) 430 { 431 $this->fileid = $row['id' ]; 432 $this->extension = $row['extension']; 433 $this->size = $row['size' ]; 434 $this->filterid = $row['filterid' ]; 435 $this->contentid = $row['contentid']; 436 } 437 438 $this->objectLoad(); 439 440 return $this; 441 } 442 443 444 445 /** 446 * Unwiderrufliches L�schen der Datei aus der Datenbank. 447 */ 448 function delete() 449 { 450 // Delete file 451 $sql = DB::sql( <<<SQL 452 DELETE FROM {{file}} 453 WHERE objectid={objectid} 454 SQL 455 ); 456 $sql->setInt( 'objectid',$this->objectid ); 457 $sql->execute(); 458 459 // Content must be deleted after the file (because the file is referencing the content) 460 $content = new Content( $this->contentid ); 461 $content->delete(); 462 463 parent::delete(); 464 } 465 466 467 468 /** 469 * Ermittelt die Datei-Endung. 470 * 471 * @return String Datei-Endung 472 */ 473 function extension() 474 { 475 if ($this->extension != '') 476 return $this->extension; 477 478 $this->load(); 479 return $this->extension; 480 } 481 482 483 /** 484 * Einen Dateinamen in Dateiname und Extension aufteilen. 485 * @param string filename Dateiname 486 */ 487 function parse_filename($filename) 488 { 489 $filename = basename($filename); 490 491 $p = strrpos($filename, '.'); 492 if ($p !== false) 493 { 494 $this->extension = substr($filename, $p +1); 495 $this->filename = substr($filename, 0, $p); 496 } 497 else 498 { 499 $this->extension = ''; 500 $this->filename = $filename; 501 } 502 } 503 504 505 /** 506 * Speichert die Datei-Informationen in der Datenbank. 507 */ 508 public function save() 509 { 510 $db = \cms\base\DB::get(); 511 512 $sql = $db->sql( <<<EOF 513 UPDATE {{file}} SET 514 size = {size}, 515 filterid = {filterid}, 516 extension = {extension} 517 WHERE objectid={objectid} 518 EOF 519 ); 520 $sql->setString('size' ,$this->size ); 521 $sql->setString('extension',$this->extension ); 522 $sql->setString('objectid' ,$this->objectid ); 523 $sql->setInt ('filterid' ,$this->filterid ); 524 $sql->execute(); 525 526 parent::save(); 527 } 528 529 530 /** 531 * Kopieren des Inhaltes von einer anderen Datei 532 * @param int ID der Datei, von der der Inhalt kopiert werden soll 533 */ 534 function copyValueFromFile( $otherfileid ) 535 { 536 $of = new File( $otherfileid ); 537 $this->value = $of->loadValue(); 538 $this->saveValue(); 539 } 540 541 542 public function loadValue() 543 { 544 return $this->loadValueFromDatabase(); 545 } 546 547 548 /** 549 * Lesen des Inhaltes der Datei aus der Datenbank. 550 * 551 * @return String Inhalt der Datei 552 */ 553 private function loadValueFromDatabase() 554 { 555 $sql = Db::sql( <<<SQL 556 SELECT {{file}}.size,{{value}}.file 557 FROM {{file}} 558 LEFT JOIN {{content}} 559 ON {{file}}.contentid = {{content}}.id 560 LEFT JOIN {{value}} 561 ON {{value}}.contentid = {{content}}.id AND {{value}}.active = 1 562 WHERE objectid={objectid} 563 SQL 564 ); 565 $sql->setInt( 'objectid', $this->objectid); 566 $row = $sql->getRow(); 567 568 if ( count($row) != 0 ) 569 { 570 $this->value = $row['file']; 571 $this->size = $row['size']; 572 } 573 574 // Because we are reading directly from the value table we must do base64-encoding here. 575 $storeValueAsBase64 = DB::get()->conf['base64']; 576 577 if ( $storeValueAsBase64 ) 578 $this->value = base64_decode( $this->value ); 579 580 return $this->value; 581 } 582 583 584 /** 585 * Speichert den Inhalt in der Datenbank. 586 */ 587 function saveValue() 588 { 589 $this->getCache()->invalidate(); 590 591 $db = \cms\base\DB::get(); 592 593 $sql = $db->sql( 'UPDATE {{file}}'. 594 ' SET size={size} '. 595 ' WHERE objectid={objectid}' ); 596 $sql->setInt( 'objectid' ,$this->objectid ); 597 $sql->setInt( 'size' ,strlen($this->value) ); 598 599 $sql->execute(); 600 601 $value = new Value(); 602 $value->contentid = $this->contentid; 603 604 // Base64-encoding is done in the Value. 605 $value->file = $this->value; 606 607 $value->publish = $this->public; 608 609 $value->persist(); 610 } 611 612 613 /** 614 * Lesen der Datei aus der Datenbank und schreiben in temporaere Datei 615 */ 616 function write() 617 { 618 $this->getCache()->load(); 619 } 620 621 622 /** 623 * F�gt die Datei der Datenbank hinzu. 624 */ 625 function add() 626 { 627 parent::add(); 628 629 // Getting the content id 630 $content = new Content(); 631 $content->persist(); 632 $this->contentid = $content->getId(); 633 634 $sql = Db::sql('SELECT MAX(id) FROM {{file}}'); 635 $this->fileid = intval($sql->getOne())+1; 636 637 $sql = Db::sql('INSERT INTO {{file}}'. 638 ' (id,contentid,objectid,extension,size)'. 639 " VALUES( {fileid},{contentid},{objectid},{extension},0 )" ); 640 $sql->setInt ('fileid' ,$this->fileid ); 641 $sql->setInt ('contentid',$this->contentid ); 642 $sql->setInt ('objectid' ,$this->objectid ); 643 $sql->setString('extension',$this->extension ); 644 645 $sql->execute(); 646 647 $this->saveValue(); 648 } 649 650 651 /** 652 * Setzt den Zeitstempel der Datei auf die aktuelle Zeit. 653 * 654 * @see objectClasses/Object#setTimestamp() 655 */ 656 657 function setTimestamp() 658 { 659 $this->getCache()->invalidate(); 660 661 parent::setTimestamp(); 662 } 663 664 665 666 667 /** 668 * Change type. 669 * 670 * This is only allowed for files, because it is only allowed to switch between the following types: file,image,text. 671 */ 672 public function updateType() 673 { 674 675 $stmt = Db::sql(<<<SQL 676 UPDATE {{object}} SET 677 typeid = {typeid} 678 WHERE id={objectid} 679 SQL 680 ); 681 682 $stmt->setInt('typeid' , $this->typeid ); 683 $stmt->setInt('objectid', $this->objectid); 684 $stmt->execute(); 685 } 686 687 688 689 690 /** 691 * Ermittelt die wirksame Datei-Endung. Diese kann sich 692 * in der Extra-Dateiendung, aber auch direkt im Dateiname 693 * befinden. 694 * 695 * @return Dateiendung 696 */ 697 function getRealExtension() 698 { 699 if ( $this->extension ) 700 { 701 return $this->extension; 702 } 703 else 704 { 705 $pos = strrpos($this->filename,'.'); 706 if ( $pos === false ) 707 return ''; 708 else 709 return substr($this->filename,$pos+1); 710 } 711 } 712 713 714 715 716 public function getSize() 717 { 718 return $this->size; 719 } 720 721 } 722