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