00001 <?php
00002
00003
00004 if ( !function_exists( "getShopBasePath" ) ) {
00010 function getShopBasePath()
00011 {
00012 return realpath( dirname( __FILE__ ) . '/..' ) . '/';
00013 }
00014 }
00015
00016
00017
00018 if ( !function_exists( 'isAdmin' )) {
00024 function isAdmin()
00025 {
00026 return false;
00027 }
00028 }
00029
00030
00031 if ( !function_exists( "getConfig" ) ) {
00037 function getConfig()
00038 {
00039
00040 include_once getShopBasePath() . 'modules/functions.php';
00041
00042
00043 include_once getShopBasePath() . 'core/oxfunctions.php';
00044
00045
00046 return oxConfig::getInstance();
00047 }
00048 }
00049
00050
00051 if ( !function_exists( "getGeneratorInstanceName" ) ) {
00057 function getGeneratorInstanceName()
00058 {
00059 return "oxdynimggenerator";
00060 }
00061 }
00062
00063
00064 if ( !function_exists( "getGdVersion" ) ) {
00070 function getGdVersion()
00071 {
00072 static $iVersion = null;
00073
00074 if ( $iVersion === null ) {
00075 $iVersion = false;
00076 if ( function_exists( "gd_info" ) ) {
00077
00078 $aInfo = gd_info();
00079 if ( isset( $aInfo["GD Version"] ) ) {
00080 $iVersion = version_compare( preg_replace( "/[^0-9\.]/", "", $aInfo["GD Version"] ), 1, '>' ) ? 2 : 1;
00081 }
00082 }
00083
00084 }
00085 return $iVersion;
00086 }
00087 }
00088
00089
00090 if ( !function_exists( "includeImageUtils" ) ) {
00096 function includeImageUtils()
00097 {
00098 include_once getShopBasePath() . "core/utils/oxpicgenerator.php";
00099 }
00100 }
00101
00105 class oxDynImgGenerator
00106 {
00111 protected static $_oInstance = null;
00112
00117 protected $_aHeaders = array();
00118
00123 protected $_aAllowedImgTypes = array( "jpg", "jpeg", "png", "gif" );
00124
00130 protected $_sImageInfoSep = "_";
00131
00136 protected $_hLockHandle = null;
00137
00142 protected $_sImageUri = null;
00143
00148 protected $_aConfParamToPath = array(
00149 "sIconsize" => '/.*\/generated\/product\/(icon|\d+)\/\d+\_\d+\_\d+$/',
00150 "sThumbnailsize" => '/.*\/generated\/product\/(thumb|\d+)\/\d+\_\d+\_\d+$/',
00151 "sZoomImageSize" => '/.*\/generated\/product\/\d+\/\d+\_\d+\_\d+$/',
00152 "aDetailImageSizes" => '/.*\/generated\/product\/\d+\/\d+\_\d+\_\d+$/',
00153
00154
00155 "sManufacturerIconsize" => '/.*\/generated\/(manufacturer|vendor)\/icon\/\d+\_\d+\_\d+$/',
00156
00157
00158 "sCatThumbnailsize" => '/.*\/generated\/category\/thumb\/\d+\_\d+\_\d+$/',
00159 "sCatIconsize" => '/.*\/generated\/category\/icon\/\d+\_\d+\_\d+$/',
00160 "sCatPromotionsize" => '/.*\/generated\/category\/promo_icon\/\d+\_\d+\_\d+$/'
00161 );
00162
00168 public static function getInstance()
00169 {
00170 if ( self::$_oInstance === null ) {
00171 $sInstanceName = getGeneratorInstanceName();
00172 self::$_oInstance = new $sInstanceName();
00173 }
00174 return self::$_oInstance;
00175 }
00176
00188 public function __call( $sMethod, $aArgs )
00189 {
00190 if ( defined( 'OXID_PHP_UNIT' ) ) {
00191 if ( substr( $sMethod, 0, 4) == "UNIT" ) {
00192 $sMethod = str_replace( "UNIT", "_", $sMethod );
00193 }
00194 if ( method_exists( $this, $sMethod)) {
00195 return call_user_func_array( array( & $this, $sMethod ), $aArgs );
00196 }
00197 }
00198
00199 throw new oxSystemComponentException( "Function '$sMethod' does not exist or is not accessible! (" . get_class($this) . ")".PHP_EOL);
00200 }
00201
00207 protected function _getShopBasePath()
00208 {
00209 return getConfig()->getConfigParam( "sShopDir" );
00210 }
00211
00217 protected function _getImageUri()
00218 {
00219 if ( $this->_sImageUri === null ) {
00220
00221 $this->_sImageUri = "";
00222 $sReqPath = "out/pictures/generated";
00223
00224
00225 $sReqImg = isset( $_SERVER["REQUEST_URI"] ) ? $_SERVER["REQUEST_URI"] : "";
00226 if ( ( $iPos = strpos( $sReqImg, $sReqPath ) ) !== false ) {
00227 $this->_sImageUri = substr( $sReqImg, $iPos );
00228 }
00229
00230 $this->_sImageUri = trim( $this->_sImageUri, "/" );
00231 }
00232
00233 return $this->_sImageUri;
00234 }
00235
00241 protected function _getImageName()
00242 {
00243 return basename( $this->_getImageUri() );
00244 }
00245
00251 protected function _getImageMasterPath()
00252 {
00253 $sUri = $this->_getImageUri();
00254 $sPath = false;
00255
00256 if ( $sUri && ( $sPath = dirname( dirname( $sUri ) ) ) ) {
00257 $sPath = preg_replace( "/\/([^\/]*)\/([^\/]*)\/([^\/]*)$/", "/master/\\2/\\3/", $sPath );
00258 }
00259
00260 return $sPath;
00261 }
00262
00268 protected function _getImageInfo()
00269 {
00270 $aInfo = array();
00271 if ( ( $sUri = $this->_getImageUri() ) ) {
00272 $aInfo = explode( $this->_sImageInfoSep, basename( dirname( $sUri ) ) );
00273 }
00274
00275 return $aInfo;
00276 }
00277
00283 protected function _getImageTarget()
00284 {
00285 return $this->_getShopBasePath() . $this->_getImageUri();
00286 }
00287
00293 protected function _getNopicImageTarget()
00294 {
00295 $sPath = $this->_getShopBasePath() . $this->_getImageUri();
00296 return str_replace( $this->_getImageName(), "nopic.jpg", $sPath );
00297 }
00298
00304 protected function _getImageType()
00305 {
00306 $sType = preg_replace( "/.*\.(png|jp(e)?g|gif)$/", "\\1", $this->_getImageName() );
00307 $sType = ( strcmp( $sType, "jpg") == 0 ) ? "jpeg" : $sType;
00308 return in_array( $sType, $this->_aAllowedImgTypes ) ? $sType : false;
00309 }
00310
00321 protected function _generatePng( $sSource, $sTarget, $iWidth, $iHeight )
00322 {
00323 return resizePng( $sSource, $sTarget, $iWidth, $iHeight, @getimagesize( $sSource ), getGdVersion(), null );
00324 }
00325
00337 protected function _generateJpg( $sSource, $sTarget, $iWidth, $iHeight, $iQuality )
00338 {
00339 return resizeJpeg( $sSource, $sTarget, $iWidth, $iHeight, @getimagesize( $sSource ), getGdVersion(), null, $iQuality );
00340 }
00341
00352 protected function _generateGif( $sSource, $sTarget, $iWidth, $iHeight )
00353 {
00354 $aImageInfo = @getimagesize( $sSource );
00355 return resizeGif( $sSource, $sTarget, $iWidth, $iHeight, $aImageInfo[0], $aImageInfo[1], getGdVersion() );
00356 }
00357
00366 protected function _isTargetPathValid( $sPath )
00367 {
00368 $blValid = true;
00369 $sDir = dirname( trim( $sPath ) );
00370
00371
00372 if ( ! is_dir( $sDir ) && ( $blValid = $this->_isValidPath( $sDir ) ) ) {
00373
00374 $blValid = $this->_createFolders( $sDir );
00375 }
00376
00377 return $blValid;
00378 }
00379
00387 protected function _createFolders( $sDir )
00388 {
00389 $oConfig = getConfig();
00390 $sPicFolderPath = dirname( $oConfig->getMasterPictureDir() );
00391
00392 $blDone = false;
00393 if ( $sPicFolderPath && is_dir( $sPicFolderPath ) ) {
00394
00395
00396 if ( strcmp( $sPicFolderPath, substr( $sDir, 0, strlen( $sPicFolderPath ) ) ) == 0 ) {
00397
00398 if ( ! ( $blDone = file_exists( $sDir ) ) ) {
00399 clearstatcache();
00400
00401 $iMode = 0755;
00402 if ( defined( 'OXID_PHP_UNIT' ) ) {
00403 $iMode = 0777;
00404 }
00405 $blDone = mkdir( $sDir, $iMode, true ) || file_exists( $sDir );
00406 }
00407 }
00408 }
00409
00410 return $blDone;
00411 }
00412
00420 protected function _isValidPath( $sPath )
00421 {
00422 $blValid = false;
00423
00424 list( $iWidth, $iHeight, $sQuality ) = $this->_getImageInfo();
00425 if ( $iWidth && $iHeight && $sQuality ) {
00426
00427 $oConfig = getConfig();
00428 $oDb = oxDb::getDb(true);
00429
00430
00431 $sNames = '';
00432 foreach ( $this->_aConfParamToPath as $sParamName => $sPathReg ) {
00433 if ( preg_match( $sPathReg, $sPath ) ) {
00434 if ( $sNames ) {
00435 $sNames .= ", ";
00436 }
00437 $sNames .= $oDb->quote( $sParamName );
00438
00439 if ( $sParamName == "sManufacturerIconsize" || $sParamName == "sCatIconsize" ) {
00440 $sNames .= ", " . $oDb->quote( "sIconsize" );
00441 }
00442 }
00443 }
00444
00445
00446 if ( $sNames ) {
00447
00448 $sDecodeField = $oConfig->getDecodeValueQuery();
00449
00450
00451 $sQ = "select oxshopid from oxconfig where oxvarname = 'sDefaultImageQuality' and
00452 {$sDecodeField} = " . $oDb->quote( $sQuality );
00453
00454 $aShopIds = $oDb->getAll( $sQ );
00455
00456
00457
00458 $sShopIds = '';
00459 foreach ( $aShopIds as $aShopId ) {
00460
00461
00462
00463
00464 if ( $sShopIds ) {
00465 $sShopIds .= ", ";
00466 }
00467 $sShopIds .= $oDb->quote( $aShopId["oxshopid"] );
00468 }
00469
00470
00471 if ( $sShopIds ) {
00472
00473
00474 $sCheckSize = "$iWidth*$iHeight";
00475
00476
00477 $sQ = "select oxvartype, {$sDecodeField} as oxvarvalue from oxconfig
00478 where oxvarname in ( {$sNames} ) and oxshopid in ( {$sShopIds} ) order by oxshopid";
00479
00480 $aValues = $oDb->getAll( $sQ );
00481 foreach ( $aValues as $aValue ) {
00482 $aConfValues = (array) $oConfig->decodeValue( $aValue["oxvartype"], $aValue["oxvarvalue"] );
00483 foreach ( $aConfValues as $sValue ) {
00484 if ( strcmp( $sCheckSize, $sValue ) == 0 ) {
00485 $blValid = true;
00486 break;
00487 }
00488 }
00489 }
00490 }
00491 }
00492 }
00493 return $blValid;
00494 }
00495
00504 protected function _generateImage( $sImageSource, $sImageTarget )
00505 {
00506 $sPath = false;
00507
00508 if ( getGdVersion() !== false && $this->_isTargetPathValid( $sImageTarget ) && ( $sImageType = $this->_getImageType() ) ) {
00509
00510
00511 includeImageUtils();
00512
00513
00514 if ( $this->_lock( $sImageTarget ) ) {
00515
00516
00517 list( $iWidth, $iHeight, $iQuality ) = $this->_getImageInfo();
00518 switch ( $sImageType ) {
00519 case "png":
00520 $sPath = $this->_generatePng( $sImageSource, $sImageTarget, $iWidth, $iHeight );
00521 break;
00522 case "jpeg":
00523 $sPath = $this->_generateJpg( $sImageSource, $sImageTarget, $iWidth, $iHeight, $iQuality );
00524 break;
00525 case "gif":
00526 $sPath = $this->_generateGif( $sImageSource, $sImageTarget, $iWidth, $iHeight );
00527 break;
00528 }
00529
00530
00531 if ( $sPath ) {
00532 $this->_unlock( $sImageTarget );
00533 }
00534 } else {
00535
00536 $sPath = file_exists( $sImageTarget ) ? $sImageTarget : false;
00537 }
00538 }
00539
00540 return $sPath;
00541 }
00542
00550 protected function _getLockName( $sName )
00551 {
00552 return "$sName.lck";
00553 }
00554
00562 protected function _lock( $sSource )
00563 {
00564 $blLocked = false;
00565 $sLockName = $this->_getLockName( $sSource );
00566
00567
00568 $this->_hLockHandle = @fopen( $this->_getLockName( $sSource ), "w" );
00569 if ( $this->_hLockHandle ) {
00570 if ( !( $blLocked = flock( $this->_hLockHandle, LOCK_EX ) ) ) {
00571
00572 fclose( $rHandle );
00573 }
00574 }
00575
00576
00577 if ( !$blLocked ) {
00578
00579 if (!( file_exists( $this->_getLockName( $sSource ) ) && abs( time() - filectime( $this->_getLockName( $sSource ) ) < 40 ) ) ) {
00580 if ( $this->_hLockHandle = @fopen( $this->_getLockName( $sSource ), "w" ) ) {
00581 $blLocked = true;
00582 }
00583 }
00584 }
00585
00586 return $blLocked;
00587 }
00588
00596 protected function _unlock( $sSource )
00597 {
00598 if ( $this->_hLockHandle ) {
00599 flock( $this->_hLockHandle, LOCK_UN );
00600 fclose( $this->_hLockHandle );
00601 unlink( $this->_getLockName( $sSource ) );
00602 }
00603 }
00604
00613 public function getImagePath( $sAbsPath = false )
00614 {
00615 if ( $sAbsPath ) {
00616 $this->_sImageUri = str_replace( $this->_getShopBasePath(), "", $sAbsPath );
00617 }
00618
00619 $sImagePath = false;
00620 $sMasterPath = $this->_getImageMasterPath();
00621
00622
00623 $sMasterImagePath = $this->_getShopBasePath() . $sMasterPath . $this->_getImageName();
00624
00625 if ( file_exists( $sMasterImagePath ) ) {
00626 $sGenImagePath = $this->_getImageTarget();
00627 } else {
00628
00629 $sMasterImagePath = $this->_getShopBasePath() . dirname( dirname( $sMasterPath ) ) . "/nopic.jpg";
00630 $sGenImagePath = $this->_getNopicImageTarget();
00631
00632
00633 $this->_setHeader( "HTTP/1.0 404 Not Found" );
00634 }
00635
00636
00637 if ( file_exists( $sGenImagePath ) ) {
00638 $sImagePath = $sGenImagePath;
00639 } elseif ( file_exists( $sMasterImagePath ) ) {
00640
00641 $sImagePath = $this->_generateImage( $sMasterImagePath, $sGenImagePath );
00642 }
00643
00644 if ( $sImagePath ) {
00645
00646 $this->_setHeader( "Content-Type: image/" . $this->_getImageType() );
00647 } else {
00648
00649 $this->_setHeader( "HTTP/1.0 404 Not Found" );
00650 }
00651
00652 return $sImagePath;
00653 }
00654
00662 public function outputImage()
00663 {
00664 $blBuffer = true;
00665 if ( defined( 'OXID_PHP_UNIT' ) ) {
00666 $blBuffer = false;
00667 }
00668
00669
00670 if ( $blBuffer ) {
00671 ob_start();
00672 }
00673
00674
00675 $sImgPath = $this->getImagePath();
00676
00677
00678 if ( $blBuffer ) {
00679 ob_clean();
00680 }
00681
00682
00683 $aHeaders = $this->_getHeaders();
00684 foreach ( $aHeaders as $sHeader ) {
00685 header( $sHeader );
00686 }
00687
00688
00689 if ( $blBuffer ) {
00690 ob_end_flush();
00691 }
00692
00693
00694 if ( $sImgPath ) {
00695
00696 @readfile( $sImgPath );
00697 }
00698 }
00699
00707 protected function _setHeader( $sHeader )
00708 {
00709 $this->_aHeaders[] = $sHeader;
00710 }
00711
00717 protected function _getHeaders()
00718 {
00719 return $this->_aHeaders;
00720 }
00721 }