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 }