oxutilsfile.php

Go to the documentation of this file.
00001 <?php
00002 
00006 class oxUtilsFile extends oxSuperCfg
00007 {
00008 
00014     const PROMO_PICTURE_DIR = 'promo';
00015 
00021     protected $_iMaxPicImgCount = 12;
00022 
00028     protected $_iMaxZoomImgCount = 12;
00029 
00035     protected $_aTypeToPath = array('TC'    => 'master/category/thumb',
00036                                     'CICO'  => 'master/category/icon',
00037                                     'PICO'  => 'master/category/promo_icon',
00038                                     'MICO'  => 'master/manufacturer/icon',
00039                                     'VICO'  => 'master/vendor/icon',
00040                                     'PROMO' => self::PROMO_PICTURE_DIR,
00041                                     'ICO'   => 'master/product/icon',
00042                                     'TH'    => 'master/product/thumb',
00043                                     'M1'    => 'master/product/1',
00044                                     'M2'    => 'master/product/2',
00045                                     'M3'    => 'master/product/3',
00046                                     'M4'    => 'master/product/4',
00047                                     'M5'    => 'master/product/5',
00048                                     'M6'    => 'master/product/6',
00049                                     'M7'    => 'master/product/7',
00050                                     'M8'    => 'master/product/8',
00051                                     'M9'    => 'master/product/9',
00052                                     'M10'   => 'master/product/10',
00053                                     'M11'   => 'master/product/11',
00054                                     'M12'   => 'master/product/12',
00055         //
00056                                     'P1'    => '1',
00057                                     'P2'    => '2',
00058                                     'P3'    => '3',
00059                                     'P4'    => '4',
00060                                     'P5'    => '5',
00061                                     'P6'    => '6',
00062                                     'P7'    => '7',
00063                                     'P8'    => '8',
00064                                     'P9'    => '9',
00065                                     'P10'   => '10',
00066                                     'P11'   => '11',
00067                                     'P12'   => '12',
00068                                     'Z1'    => 'z1',
00069                                     'Z2'    => 'z2',
00070                                     'Z3'    => 'z3',
00071                                     'Z4'    => 'z4',
00072                                     'Z5'    => 'z5',
00073                                     'Z6'    => 'z6',
00074                                     'Z7'    => 'z7',
00075                                     'Z8'    => 'z8',
00076                                     'Z9'    => 'z9',
00077                                     'Z10'   => 'z10',
00078                                     'Z11'   => 'z11',
00079                                     'Z12'   => 'z12',
00080         //
00081                                     'WP'    => 'master/wrapping',
00082                                     'FL'    => 'media',
00083     );
00084 
00090     protected $_aBadFiles = array('php', 'php3', 'php4', 'php5', 'phps', 'php6', 'jsp', 'cgi', 'cmf', 'exe');
00091 
00097     protected $_aAllowedFiles = array('gif', 'jpg', 'jpeg', 'png', 'pdf');
00098 
00104     protected $_iNewFilesCounter = 0;
00105 
00111     public function __construct()
00112     {
00113         $myConfig = $this->getConfig();
00114 
00115         if ($iPicCount = $myConfig->getConfigParam('iPicCount')) {
00116             $this->_iMaxPicImgCount = $iPicCount;
00117         }
00118 
00119         $this->_iMaxZoomImgCount = $this->_iMaxPicImgCount;
00120     }
00121 
00127     public function getNewFilesCounter()
00128     {
00129         return $this->_iNewFilesCounter;
00130     }
00131 
00137     protected function _setNewFilesCounter($iNewFilesCounter)
00138     {
00139         $this->_iNewFilesCounter = (int) $iNewFilesCounter;
00140     }
00141 
00149     public function normalizeDir($sDir)
00150     {
00151         if (isset($sDir) && $sDir != "" && substr($sDir, -1) !== '/') {
00152             $sDir .= "/";
00153         }
00154 
00155         return $sDir;
00156     }
00157 
00164     public function copyDir($sSourceDir, $sTargetDir)
00165     {
00166         $oStr = getStr();
00167         $handle = opendir($sSourceDir);
00168         while (false !== ($file = readdir($handle))) {
00169             if ($file != '.' && $file != '..') {
00170                 if (is_dir($sSourceDir . '/' . $file)) {
00171 
00172                     // recursive
00173                     $sNewSourceDir = $sSourceDir . '/' . $file;
00174                     $sNewTargetDir = $sTargetDir . '/' . $file;
00175                     if (strcasecmp($file, 'CVS') && strcasecmp($file, '.svn')) {
00176                         @mkdir($sNewTargetDir, 0777);
00177                         $this->copyDir($sNewSourceDir, $sNewTargetDir);
00178                     }
00179                 } else {
00180                     $sSourceFile = $sSourceDir . '/' . $file;
00181                     $sTargetFile = $sTargetDir . '/' . $file;
00182 
00183                     //do not copy files within dyn_images
00184                     if (!$oStr->strstr($sSourceDir, 'dyn_images') || $file == 'nopic.jpg' || $file == 'nopic_ico.jpg') {
00185                         @copy($sSourceFile, $sTargetFile);
00186                     }
00187                 }
00188             }
00189         }
00190         closedir($handle);
00191     }
00192 
00200     public function deleteDir($sSourceDir)
00201     {
00202         if (is_dir($sSourceDir)) {
00203             if ($oDir = dir($sSourceDir)) {
00204 
00205                 while (false !== $sFile = $oDir->read()) {
00206                     if ($sFile == '.' || $sFile == '..') {
00207                         continue;
00208                     }
00209 
00210                     if (!$this->deleteDir($oDir->path . DIRECTORY_SEPARATOR . $sFile)) {
00211                         $oDir->close();
00212 
00213                         return false;
00214                     }
00215                 }
00216 
00217                 $oDir->close();
00218 
00219                 return rmdir($sSourceDir);
00220             }
00221         } elseif (file_exists($sSourceDir)) {
00222             return unlink($sSourceDir);
00223         }
00224     }
00225 
00233     public function readRemoteFileAsString($sPath)
00234     {
00235         $sRet = '';
00236         $hFile = @fopen($sPath, 'r');
00237         if ($hFile) {
00238             socket_set_timeout($hFile, 2);
00239             while (!feof($hFile)) {
00240                 $sLine = fgets($hFile, 4096);
00241                 $sRet .= $sLine;
00242             }
00243             fclose($hFile);
00244         }
00245 
00246         return $sRet;
00247     }
00248 
00260     protected function _prepareImageName($sValue, $sType, $blDemo, $sImagePath, $blUnique = true)
00261     {
00262         if ($sValue) {
00263             // add type to name
00264             $aFilename = explode(".", $sValue);
00265 
00266             $sFileType = trim($aFilename[count($aFilename) - 1]);
00267 
00268             if (isset($sFileType)) {
00269 
00270                 $oStr = getStr();
00271 
00272                 // unallowed files ?
00273                 if (in_array($sFileType, $this->_aBadFiles) || ($blDemo && !in_array($sFileType, $this->_aAllowedFiles))) {
00274                     oxRegistry::getUtils()->showMessageAndExit("We don't play this game, go away");
00275                 }
00276 
00277                 // removing file type
00278                 if (count($aFilename) > 0) {
00279                     unset($aFilename[count($aFilename) - 1]);
00280                 }
00281 
00282                 $sFName = '';
00283                 if (isset($aFilename[0])) {
00284                     $sFName = $oStr->preg_replace('/[^a-zA-Z0-9()_\.-]/', '', implode('.', $aFilename));
00285                 }
00286 
00287                 $sValue = $this->_getUniqueFileName($sImagePath, "{$sFName}", $sFileType, "", $blUnique);
00288             }
00289         }
00290 
00291         return $sValue;
00292     }
00293 
00301     protected function _getImagePath($sType)
00302     {
00303         $sFolder = array_key_exists($sType, $this->_aTypeToPath) ? $this->_aTypeToPath[$sType] : '0';
00304         $sPath = $this->normalizeDir($this->getConfig()->getPictureDir(false)) . "{$sFolder}/";
00305 
00306         return $sPath;
00307     }
00308 
00319     protected function _getImageSize($sImgType, $iImgNum, $sImgConf)
00320     {
00321         $myConfig = $this->getConfig();
00322         $sSize = false;
00323 
00324         switch ($sImgConf) {
00325             case 'aDetailImageSizes':
00326                 $aDetailImageSizes = $myConfig->getConfigParam($sImgConf);
00327                 $sSize = $myConfig->getConfigParam('sDetailImageSize');
00328                 if (isset($aDetailImageSizes['oxpic' . $iImgNum])) {
00329                     $sSize = $aDetailImageSizes['oxpic' . $iImgNum];
00330                 }
00331                 break;
00332             default:
00333                 $sSize = $myConfig->getConfigParam($sImgConf);
00334                 break;
00335         }
00336         if ($sSize) {
00337             return explode('*', $sSize);
00338         }
00339     }
00340 
00349     protected function _copyFile($sSource, $sTarget)
00350     {
00351         $blDone = false;
00352 
00353         if ($sSource === $sTarget) {
00354             $blDone = true;
00355         } else {
00356             $blDone = copy($sSource, $sTarget);
00357         }
00358 
00359         if ($blDone) {
00360             $blDone = @chmod($sTarget, 0644);
00361         }
00362 
00363         return $blDone;
00364     }
00365 
00374     protected function _moveImage($sSource, $sTarget)
00375     {
00376         $blDone = false;
00377         if (!is_dir(dirname($sTarget))) {
00378             mkdir(dirname($sTarget), 0744, true);
00379         }
00380         if ($sSource === $sTarget) {
00381             $blDone = true;
00382         } else {
00383             $blDone = move_uploaded_file($sSource, $sTarget);
00384         }
00385 
00386         if ($blDone) {
00387             $blDone = @chmod($sTarget, 0644);
00388         }
00389 
00390         return $blDone;
00391     }
00392 
00404     public function processFiles($oObject = null, $aFiles = array(), $blUseMasterImage = false, $blUnique = true)
00405     {
00406         $aFiles = $aFiles ? $aFiles : $_FILES;
00407         if (isset($aFiles['myfile']['name'])) {
00408 
00409             $oConfig = $this->getConfig();
00410             $oStr = getStr();
00411 
00412             // A. protection for demoshops - strictly defining allowed file extensions
00413             $blDemo = (bool) $oConfig->isDemoShop();
00414 
00415             // folder where images will be processed
00416             $sTmpFolder = $oConfig->getConfigParam("sCompileDir");
00417 
00418             $iNewFilesCounter = 0;
00419             $aSource = $aFiles['myfile']['tmp_name'];
00420             $aError = $aFiles['myfile']['error'];
00421             $sErrorsDescription = '';
00422 
00423             $oEx = oxNew("oxExceptionToDisplay");
00424             // process all files
00425             while (list($sKey, $sValue) = each($aFiles['myfile']['name'])) {
00426 
00427                 $sSource = $aSource[$sKey];
00428                 $iError = $aError[$sKey];
00429                 $aFiletype = explode("@", $sKey);
00430                 $sKey = $aFiletype[1];
00431                 $sType = $aFiletype[0];
00432 
00433                 $sValue = strtolower($sValue);
00434                 $sImagePath = $this->_getImagePath($sType);
00435 
00436                 // Should translate error to user if file was uploaded
00437                 if (UPLOAD_ERR_OK !== $iError && UPLOAD_ERR_NO_FILE !== $iError) {
00438                     $sErrorsDescription = $this->translateError($iError);
00439                     $oEx->setMessage($sErrorsDescription);
00440                     oxRegistry::get("oxUtilsView")->addErrorToDisplay($oEx, false);
00441                 }
00442 
00443                 // checking file type and building final file name
00444                 if ($sSource && ($sValue = $this->_prepareImageName($sValue, $sType, $blDemo, $sImagePath, $blUnique))) {
00445                     // moving to tmp folder for processing as safe mode or spec. open_basedir setup
00446                     // usually does not allow file modification in php's temp folder
00447                     $sProcessPath = $sTmpFolder . basename($sSource);
00448 
00449                     if ($sProcessPath) {
00450 
00451                         if ($blUseMasterImage) {
00452                             //using master image as source, so only copying it to
00453                             $blMoved = $this->_copyFile($sSource, $sImagePath . $sValue);
00454                         } else {
00455                             $blMoved = $this->_moveImage($sSource, $sImagePath . $sValue);
00456                         }
00457 
00458                         if ($blMoved) {
00459                             // New image successfully add.
00460                             $iNewFilesCounter++;
00461                             // assign the name
00462                             if ($oObject && isset($oObject->$sKey)) {
00463                                 $oObject->{$sKey}->setValue($sValue);
00464                             }
00465                         }
00466                     }
00467                 }
00468             }
00469 
00470             $this->_setNewFilesCounter($iNewFilesCounter);
00471         }
00472 
00473         return $oObject;
00474     }
00475 
00484     public function checkFile($sFile)
00485     {
00486         $aCheckCache = oxRegistry::getSession()->getVariable("checkcache");
00487 
00488         if (isset($aCheckCache[$sFile])) {
00489             return $aCheckCache[$sFile];
00490         }
00491 
00492         $blRet = false;
00493 
00494         if (is_readable($sFile)) {
00495             $blRet = true;
00496         } else {
00497             // try again via socket
00498             $blRet = $this->urlValidate($sFile);
00499         }
00500 
00501         $aCheckCache[$sFile] = $blRet;
00502         oxRegistry::getSession()->setVariable("checkcache", $aCheckCache);
00503 
00504         return $blRet;
00505     }
00506 
00514     public function urlValidate($sLink)
00515     {
00516         $aUrlParts = @parse_url($sLink);
00517         $sHost = (isset($aUrlParts["host"]) && $aUrlParts["host"]) ? $aUrlParts["host"] : null;
00518 
00519         $blValid = false;
00520         if ($sHost) {
00521             $sDocumentPath = (isset($aUrlParts["path"]) && $aUrlParts["path"]) ? $aUrlParts["path"] : '/';
00522             $sDocumentPath .= (isset($aUrlParts["query"]) && $aUrlParts["query"]) ? '?' . $aUrlParts["query"] : '';
00523 
00524             $sPort = (isset($aUrlParts["port"]) && $aUrlParts["port"]) ? $aUrlParts["port"] : '80';
00525 
00526             // Now (HTTP-)GET $documentpath at $sHost";
00527             if (($oConn = @fsockopen($sHost, $sPort, $iErrNo, $sErrStr, 30))) {
00528                 fwrite($oConn, "HEAD {$sDocumentPath} HTTP/1.0\r\nHost: {$sHost}\r\n\r\n");
00529                 $sResponse = fgets($oConn, 22);
00530                 fclose($oConn);
00531 
00532                 if (preg_match("/200 OK/", $sResponse)) {
00533                     $blValid = true;
00534                 }
00535             }
00536         }
00537 
00538         return $blValid;
00539     }
00540 
00551     public function processFile($sFileName, $sUploadPath)
00552     {
00553         $aFileInfo = $_FILES[$sFileName];
00554 
00555         $sBasePath = $this->getConfig()->getConfigParam('sShopDir');
00556 
00557         //checking params
00558         if (!isset($aFileInfo['name']) || !isset($aFileInfo['tmp_name'])) {
00559             throw oxNew("oxException", 'EXCEPTION_NOFILE');
00560         }
00561 
00562         //wrong chars in file name?
00563         if (!getStr()->preg_match('/^[\-_a-z0-9\.]+$/i', $aFileInfo['name'])) {
00564             throw oxNew("oxException", 'EXCEPTION_FILENAMEINVALIDCHARS');
00565         }
00566 
00567         // error uploading file ?
00568         if (isset($aFileInfo['error']) && $aFileInfo['error']) {
00569             throw oxNew("oxException", 'EXCEPTION_FILEUPLOADERROR_' . ((int) $aFileInfo['error']));
00570         }
00571 
00572         $aPathInfo = pathinfo($aFileInfo['name']);
00573 
00574         $sExt = $aPathInfo['extension'];
00575         $sFileName = $aPathInfo['filename'];
00576 
00577         $aAllowedUploadTypes = (array) $this->getConfig()->getConfigParam('aAllowedUploadTypes');
00578         $aAllowedUploadTypes = array_map("strtolower", $aAllowedUploadTypes);
00579 
00580         if (!in_array(strtolower($sExt), $aAllowedUploadTypes)) {
00581             throw oxNew("oxException", 'EXCEPTION_NOTALLOWEDTYPE');
00582         }
00583 
00584         $sFileName = $this->_getUniqueFileName($sBasePath . $sUploadPath, $sFileName, $sExt);
00585 
00586         if ($this->_moveImage($aFileInfo['tmp_name'], $sBasePath . $sUploadPath . "/" . $sFileName)) {
00587             return $sFileName;
00588         } else {
00589             return false;
00590         }
00591     }
00592 
00605     protected function _getUniqueFileName($sFilePath, $sFileName, $sFileExt, $sSufix = "", $blUnique = true)
00606     {
00607         $sFilePath = $this->normalizeDir($sFilePath);
00608         $iFileCounter = 0;
00609         $sTempFileName = $sFileName;
00610         $oStr = getStr();
00611 
00612         //file exists ?
00613         while ($blUnique && file_exists($sFilePath . "/" . $sFileName . $sSufix . "." . $sFileExt)) {
00614             $iFileCounter++;
00615 
00616             //removing "(any digit)" from file name end
00617             $sTempFileName = $oStr->preg_replace("/\(" . $iFileCounter . "\)/", "", $sTempFileName);
00618 
00619             $sFileName = $sTempFileName . "($iFileCounter)";
00620         }
00621 
00622         return $sFileName . $sSufix . "." . $sFileExt;
00623     }
00624 
00633     public function getImageDirByType($sType, $blGenerated = false)
00634     {
00635         $sFolder = array_key_exists($sType, $this->_aTypeToPath) ? $this->_aTypeToPath[$sType] : '0';
00636         $sDir = $this->normalizeDir($sFolder);
00637 
00638         if ($blGenerated === true) {
00639             $sDir = str_replace('master/', 'generated/', $sDir);
00640         }
00641 
00642         return $sDir;
00643     }
00644 
00652     public function translateError($iError)
00653     {
00654         $message = '';
00655         // Translate only if translation exist
00656         if ($iError > 0 && $iError < 9 && 5 !== $iError) {
00657             $message = 'EXCEPTION_FILEUPLOADERROR_' . ((int) $iError);
00658         }
00659 
00660         return $message;
00661     }
00662 }