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
00088 return $iVersion;
00089 }
00090 }
00091
00092
00093 if (!function_exists("includeImageUtils")) {
00097 function includeImageUtils()
00098 {
00099 include_once getShopBasePath() . "core/utils/oxpicgenerator.php";
00100 }
00101 }
00102
00106 class oxDynImgGenerator
00107 {
00108
00114 protected static $_oInstance = null;
00115
00121 protected $_aHeaders = array();
00122
00128 protected $_aAllowedImgTypes = array("jpg", "jpeg", "png", "gif");
00129
00136 protected $_sImageInfoSep = "_";
00137
00143 protected $_hLockHandle = null;
00144
00150 protected $_sImageUri = null;
00151
00157 protected $_aConfParamToPath = array(
00158 "sIconsize" => '/.*\/generated\/product\/(icon|\d+)\/\d+\_\d+\_\d+$/',
00159 "sThumbnailsize" => '/.*\/generated\/product\/(thumb|\d+)\/\d+\_\d+\_\d+$/',
00160 "sZoomImageSize" => '/.*\/generated\/product\/\d+\/\d+\_\d+\_\d+$/',
00161 "aDetailImageSizes" => '/.*\/generated\/product\/\d+\/\d+\_\d+\_\d+$/',
00162
00163
00164 "sManufacturerIconsize" => '/.*\/generated\/(manufacturer|vendor)\/icon\/\d+\_\d+\_\d+$/',
00165
00166
00167 "sCatThumbnailsize" => '/.*\/generated\/category\/thumb\/\d+\_\d+\_\d+$/',
00168 "sCatIconsize" => '/.*\/generated\/category\/icon\/\d+\_\d+\_\d+$/',
00169 "sCatPromotionsize" => '/.*\/generated\/category\/promo_icon\/\d+\_\d+\_\d+$/'
00170 );
00171
00177 public static function getInstance()
00178 {
00179 if (self::$_oInstance === null) {
00180 $sInstanceName = getGeneratorInstanceName();
00181 self::$_oInstance = new $sInstanceName();
00182 }
00183
00184 return self::$_oInstance;
00185 }
00186
00198 public function __call($sMethod, $aArgs)
00199 {
00200 if (defined('OXID_PHP_UNIT')) {
00201 if (substr($sMethod, 0, 4) == "UNIT") {
00202 $sMethod = str_replace("UNIT", "_", $sMethod);
00203 }
00204 if (method_exists($this, $sMethod)) {
00205 return call_user_func_array(array(& $this, $sMethod), $aArgs);
00206 }
00207 }
00208
00209 throw new oxSystemComponentException("Function '$sMethod' does not exist or is not accessible! (" . get_class($this) . ")" . PHP_EOL);
00210 }
00211
00217 protected function _getShopBasePath()
00218 {
00219 return getConfig()->getConfigParam("sShopDir");
00220 }
00221
00227 protected function _getImageUri()
00228 {
00229 if ($this->_sImageUri === null) {
00230
00231 $this->_sImageUri = "";
00232 $sReqPath = "out/pictures/generated";
00233
00234
00235 $sReqImg = isset($_SERVER["REQUEST_URI"]) ? urldecode($_SERVER["REQUEST_URI"]) : "";
00236 if (($iPos = strpos($sReqImg, $sReqPath)) !== false) {
00237 $this->_sImageUri = substr($sReqImg, $iPos);
00238 }
00239
00240 $this->_sImageUri = trim($this->_sImageUri, "/");
00241 }
00242
00243 return $this->_sImageUri;
00244 }
00245
00251 protected function _getImageName()
00252 {
00253 return basename($this->_getImageUri());
00254 }
00255
00261 protected function _getImageMasterPath()
00262 {
00263 $sUri = $this->_getImageUri();
00264 $sPath = false;
00265
00266 if ($sUri && ($sPath = dirname(dirname($sUri)))) {
00267 $sPath = preg_replace("/\/([^\/]*)\/([^\/]*)\/([^\/]*)$/", "/master/\\2/\\3/", $sPath);
00268 }
00269
00270 return $sPath;
00271 }
00272
00278 protected function _getImageInfo()
00279 {
00280 $aInfo = array();
00281 if (($sUri = $this->_getImageUri())) {
00282 $aInfo = explode($this->_sImageInfoSep, basename(dirname($sUri)));
00283 }
00284
00285 return $aInfo;
00286 }
00287
00293 protected function _getImageTarget()
00294 {
00295 return $this->_getShopBasePath() . $this->_getImageUri();
00296 }
00297
00303 protected function _getNopicImageTarget()
00304 {
00305 $sPath = $this->_getShopBasePath() . $this->_getImageUri();
00306
00307 return str_replace($this->_getImageName(), "nopic.jpg", $sPath);
00308 }
00309
00315 protected function _getImageType()
00316 {
00317 $sType = preg_replace("/.*\.(png|jp(e)?g|gif)$/", "\\1", $this->_getImageName());
00318 $sType = (strcmp($sType, "jpg") == 0) ? "jpeg" : $sType;
00319
00320 return in_array($sType, $this->_aAllowedImgTypes) ? $sType : false;
00321 }
00322
00333 protected function _generatePng($sSource, $sTarget, $iWidth, $iHeight)
00334 {
00335 return resizePng($sSource, $sTarget, $iWidth, $iHeight, @getimagesize($sSource), getGdVersion(), null);
00336 }
00337
00349 protected function _generateJpg($sSource, $sTarget, $iWidth, $iHeight, $iQuality)
00350 {
00351 return resizeJpeg($sSource, $sTarget, $iWidth, $iHeight, @getimagesize($sSource), getGdVersion(), null, $iQuality);
00352 }
00353
00364 protected function _generateGif($sSource, $sTarget, $iWidth, $iHeight)
00365 {
00366 $aImageInfo = @getimagesize($sSource);
00367
00368 return resizeGif($sSource, $sTarget, $iWidth, $iHeight, $aImageInfo[0], $aImageInfo[1], getGdVersion());
00369 }
00370
00379 protected function _isTargetPathValid($sPath)
00380 {
00381 $blValid = true;
00382 $sDir = dirname(trim($sPath));
00383
00384
00385 if (!is_dir($sDir) && ($blValid = $this->_isValidPath($sDir))) {
00386
00387 $blValid = $this->_createFolders($sDir);
00388 }
00389
00390 return $blValid;
00391 }
00392
00400 protected function _createFolders($sDir)
00401 {
00402 $oConfig = getConfig();
00403 $sPicFolderPath = dirname($oConfig->getMasterPictureDir());
00404
00405 $blDone = false;
00406 if ($sPicFolderPath && is_dir($sPicFolderPath)) {
00407
00408
00409 if (strcmp($sPicFolderPath, substr($sDir, 0, strlen($sPicFolderPath))) == 0) {
00410
00411 if (!($blDone = file_exists($sDir))) {
00412 clearstatcache();
00413
00414 $iMode = 0755;
00415 if (defined('OXID_PHP_UNIT')) {
00416 $iMode = 0777;
00417 }
00418 $blDone = mkdir($sDir, $iMode, true) || file_exists($sDir);
00419 }
00420 }
00421 }
00422
00423 return $blDone;
00424 }
00425
00433 protected function _isValidPath($sPath)
00434 {
00435 $blValid = false;
00436
00437 list($iWidth, $iHeight, $sQuality) = $this->_getImageInfo();
00438 if ($iWidth && $iHeight && $sQuality) {
00439
00440 $oConfig = getConfig();
00441 $oDb = oxDb::getDb(oxDb::FETCH_MODE_ASSOC);
00442
00443
00444 $sNames = '';
00445 foreach ($this->_aConfParamToPath as $sParamName => $sPathReg) {
00446 if (preg_match($sPathReg, $sPath)) {
00447 if ($sNames) {
00448 $sNames .= ", ";
00449 }
00450 $sNames .= $oDb->quote($sParamName);
00451
00452 if ($sParamName == "sManufacturerIconsize" || $sParamName == "sCatIconsize") {
00453 $sNames .= ", " . $oDb->quote("sIconsize");
00454 }
00455 }
00456 }
00457
00458
00459 if ($sNames) {
00460
00461 $sDecodeField = $oConfig->getDecodeValueQuery();
00462
00463
00464 $sQ = "select oxshopid from oxconfig where oxvarname = 'sDefaultImageQuality' and
00465 {$sDecodeField} = " . $oDb->quote($sQuality);
00466
00467 $aShopIds = $oDb->getAll($sQ);
00468
00469
00470
00471 $sShopIds = '';
00472 foreach ($aShopIds as $aShopId) {
00473
00474
00475
00476
00477 if ($sShopIds) {
00478 $sShopIds .= ", ";
00479 }
00480 $sShopIds .= $oDb->quote($aShopId["oxshopid"]);
00481 }
00482
00483
00484 if ($sShopIds) {
00485
00486
00487 $sCheckSize = "$iWidth*$iHeight";
00488
00489
00490 $sQ = "select oxvartype, {$sDecodeField} as oxvarvalue from oxconfig
00491 where oxvarname in ( {$sNames} ) and oxshopid in ( {$sShopIds} ) order by oxshopid";
00492
00493 $aValues = $oDb->getAll($sQ);
00494 foreach ($aValues as $aValue) {
00495 $aConfValues = (array) $oConfig->decodeValue($aValue["oxvartype"], $aValue["oxvarvalue"]);
00496 foreach ($aConfValues as $sValue) {
00497 if (strcmp($sCheckSize, $sValue) == 0) {
00498 $blValid = true;
00499 break;
00500 }
00501 }
00502 }
00503 }
00504 }
00505 }
00506
00507 return $blValid;
00508 }
00509
00518 protected function _generateImage($sImageSource, $sImageTarget)
00519 {
00520 $sPath = false;
00521
00522 if (getGdVersion() !== false && $this->_isTargetPathValid($sImageTarget) && ($sImageType = $this->_getImageType())) {
00523
00524
00525 includeImageUtils();
00526
00527
00528 if ($this->_lock($sImageTarget)) {
00529
00530
00531 list($iWidth, $iHeight, $iQuality) = $this->_getImageInfo();
00532 switch ($sImageType) {
00533 case "png":
00534 $sPath = $this->_generatePng($sImageSource, $sImageTarget, $iWidth, $iHeight);
00535 break;
00536 case "jpeg":
00537 $sPath = $this->_generateJpg($sImageSource, $sImageTarget, $iWidth, $iHeight, $iQuality);
00538 break;
00539 case "gif":
00540 $sPath = $this->_generateGif($sImageSource, $sImageTarget, $iWidth, $iHeight);
00541 break;
00542 }
00543
00544
00545 if ($sPath) {
00546 $this->_unlock($sImageTarget);
00547 }
00548 } else {
00549
00550 $sPath = file_exists($sImageTarget) ? $sImageTarget : false;
00551 }
00552 }
00553
00554 return $sPath;
00555 }
00556
00564 protected function _getLockName($sName)
00565 {
00566 return "$sName.lck";
00567 }
00568
00576 protected function _lock($sSource)
00577 {
00578 $blLocked = false;
00579 $sLockName = $this->_getLockName($sSource);
00580
00581
00582 $this->_hLockHandle = @fopen($this->_getLockName($sSource), "w");
00583 if ($this->_hLockHandle) {
00584 if (!($blLocked = flock($this->_hLockHandle, LOCK_EX))) {
00585
00586 fclose($rHandle);
00587 }
00588 }
00589
00590
00591 if (!$blLocked) {
00592
00593 if (!(file_exists($this->_getLockName($sSource)) && abs(time() - filectime($this->_getLockName($sSource)) < 40))) {
00594 if ($this->_hLockHandle = @fopen($this->_getLockName($sSource), "w")) {
00595 $blLocked = true;
00596 }
00597 }
00598 }
00599
00600 return $blLocked;
00601 }
00602
00608 protected function _unlock($sSource)
00609 {
00610 if ($this->_hLockHandle) {
00611 flock($this->_hLockHandle, LOCK_UN);
00612 fclose($this->_hLockHandle);
00613 unlink($this->_getLockName($sSource));
00614 }
00615 }
00616
00625 public function getImagePath($sAbsPath = false)
00626 {
00627 if ($sAbsPath) {
00628 $this->_sImageUri = str_replace($this->_getShopBasePath(), "", $sAbsPath);
00629 }
00630
00631 $sImagePath = false;
00632 $sMasterPath = $this->_getImageMasterPath();
00633
00634
00635 $sMasterImagePath = $this->_getShopBasePath() . $sMasterPath . $this->_getImageName();
00636
00637 if (file_exists($sMasterImagePath)) {
00638 $sGenImagePath = $this->_getImageTarget();
00639 } else {
00640
00641 $sMasterImagePath = $this->_getShopBasePath() . dirname(dirname($sMasterPath)) . "/nopic.jpg";
00642 $sGenImagePath = $this->_getNopicImageTarget();
00643
00644
00645 $this->_setHeader("HTTP/1.0 404 Not Found");
00646 }
00647
00648
00649 if (file_exists($sGenImagePath)) {
00650 $sImagePath = $sGenImagePath;
00651 } elseif (file_exists($sMasterImagePath)) {
00652
00653 $sImagePath = $this->_generateImage($sMasterImagePath, $sGenImagePath);
00654 }
00655
00656 if ($sImagePath) {
00657
00658 $this->_setHeader("Content-Type: image/" . $this->_getImageType());
00659 } else {
00660
00661 $this->_setHeader("HTTP/1.0 404 Not Found");
00662 }
00663
00664 return $sImagePath;
00665 }
00666
00672 public function outputImage()
00673 {
00674 $blBuffer = true;
00675 if (defined('OXID_PHP_UNIT')) {
00676 $blBuffer = false;
00677 }
00678
00679
00680 if ($blBuffer) {
00681 ob_start();
00682 }
00683
00684
00685 $sImgPath = $this->getImagePath();
00686
00687
00688 if ($blBuffer) {
00689 ob_clean();
00690 }
00691
00692
00693 $aHeaders = $this->_getHeaders();
00694 foreach ($aHeaders as $sHeader) {
00695 header($sHeader);
00696 }
00697
00698
00699 if ($blBuffer) {
00700 ob_end_flush();
00701 }
00702
00703
00704 if ($sImgPath) {
00705
00706 @readfile($sImgPath);
00707 }
00708 }
00709
00715 protected function _setHeader($sHeader)
00716 {
00717 $this->_aHeaders[] = $sHeader;
00718 }
00719
00725 protected function _getHeaders()
00726 {
00727 return $this->_aHeaders;
00728 }
00729 }