oxutilsfile.php

Go to the documentation of this file.
00001 <?php
00002 
00006 class oxUtilsFile extends oxSuperCfg
00007 {
00013     const PROMO_PICTURE_DIR = 'promo';
00014 
00020     private static $_instance = null;
00021 
00027     protected $_iMaxPicImgCount  = 12;
00028 
00034     protected $_iMaxZoomImgCount = 12;
00035 
00041     protected $_aTypeToPath = array( 'TC'   => 'master/category/thumb',
00042                                      'CICO' => 'master/category/icon',
00043                                      'PICO' => 'master/category/promo_icon',
00044                                      'MICO' => 'master/manufacturer/icon',
00045                                      'VICO' => 'master/vendor/icon',
00046                                      'PROMO'=> self::PROMO_PICTURE_DIR,
00047                                      'ICO'  => 'master/product/icon',
00048                                      'TH'   => 'master/product/thumb',
00049                                      'M1'   => 'master/product/1',
00050                                      'M2'   => 'master/product/2',
00051                                      'M3'   => 'master/product/3',
00052                                      'M4'   => 'master/product/4',
00053                                      'M5'   => 'master/product/5',
00054                                      'M6'   => 'master/product/6',
00055                                      'M7'   => 'master/product/7',
00056                                      'M8'   => 'master/product/8',
00057                                      'M9'   => 'master/product/9',
00058                                      'M10'  => 'master/product/10',
00059                                      'M11'  => 'master/product/11',
00060                                      'M12'  => 'master/product/12',
00061                                      //
00062                                      'P1'   => '1',
00063                                      'P2'   => '2',
00064                                      'P3'   => '3',
00065                                      'P4'   => '4',
00066                                      'P5'   => '5',
00067                                      'P6'   => '6',
00068                                      'P7'   => '7',
00069                                      'P8'   => '8',
00070                                      'P9'   => '9',
00071                                      'P10'  => '10',
00072                                      'P11'  => '11',
00073                                      'P12'  => '12',
00074                                      'Z1'   => 'z1',
00075                                      'Z2'   => 'z2',
00076                                      'Z3'   => 'z3',
00077                                      'Z4'   => 'z4',
00078                                      'Z5'   => 'z5',
00079                                      'Z6'   => 'z6',
00080                                      'Z7'   => 'z7',
00081                                      'Z8'   => 'z8',
00082                                      'Z9'   => 'z9',
00083                                      'Z10'  => 'z10',
00084                                      'Z11'  => 'z11',
00085                                      'Z12'  => 'z12',
00086                                      //
00087                                      'WP'   => 'master/wrapping',
00088                                      'FL'   => 'media',
00089     );
00090 
00096     protected $_aBadFiles = array( 'php', 'php3', 'php4', 'php5', 'phps', 'php6', 'jsp', 'cgi', 'cmf', 'exe' );
00097 
00103     protected $_aAllowedFiles = array( 'gif', 'jpg', 'jpeg', 'png', 'pdf' );
00109     public static function getInstance()
00110     {
00111         // disable caching for test modules
00112         if ( defined( 'OXID_PHP_UNIT' ) ) {
00113             self::$_instance = modInstances::getMod( __CLASS__ );
00114         }
00115 
00116         if ( !self::$_instance instanceof oxUtilsFile ) {
00117 
00118             self::$_instance = oxNew( 'oxUtilsFile' );
00119             if ( defined( 'OXID_PHP_UNIT' ) ) {
00120                 modInstances::addMod( __CLASS__, self::$_instance);
00121             }
00122         }
00123         return self::$_instance;
00124     }
00125 
00131     public function __construct()
00132     {
00133         $myConfig = $this->getConfig();
00134 
00135         if ( $iPicCount = $myConfig->getConfigParam( 'iPicCount' ) ) {
00136             $this->_iMaxPicImgCount = $iPicCount;
00137         }
00138 
00139         $this->_iMaxZoomImgCount = $this->_iMaxPicImgCount;
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 
00166     public function copyDir( $sSourceDir, $sTargetDir )
00167     {
00168         $oStr = getStr();
00169         $handle = opendir( $sSourceDir );
00170         while ( false !== ( $file = readdir( $handle ) ) ) {
00171             if ( $file != '.' && $file != '..' ) {
00172                 if ( is_dir( $sSourceDir.'/'.$file ) ) {
00173 
00174                     // recursive
00175                     $sNewSourceDir = $sSourceDir.'/'.$file;
00176                     $sNewTargetDir = $sTargetDir.'/'.$file;
00177                     if ( strcasecmp( $file, 'CVS' ) &&  strcasecmp( $file, '.svn' )) {
00178                         @mkdir( $sNewTargetDir, 0777 );
00179                         $this->copyDir( $sNewSourceDir, $sNewTargetDir );
00180                     }
00181                 } else {
00182                     $sSourceFile = $sSourceDir.'/'.$file;
00183                     $sTargetFile = $sTargetDir.'/'.$file;
00184 
00185                     //do not copy files within dyn_images
00186                     if ( !$oStr->strstr( $sSourceDir, 'dyn_images' ) ||  $file == 'nopic.jpg' || $file == 'nopic_ico.jpg' ) {
00187                         @copy( $sSourceFile, $sTargetFile );
00188                     }
00189                 }
00190             }
00191         }
00192         closedir($handle);
00193     }
00194 
00202     public function deleteDir( $sSourceDir )
00203     {
00204         if ( is_dir( $sSourceDir ) ) {
00205             if ( $oDir = dir( $sSourceDir ) ) {
00206 
00207                 while ( false !== $sFile = $oDir->read() ) {
00208                     if ( $sFile == '.' || $sFile == '..' ) {
00209                         continue;
00210                     }
00211 
00212                     if ( !$this->deleteDir( $oDir->path . DIRECTORY_SEPARATOR . $sFile ) ) {
00213                         $oDir->close();
00214                         return false;
00215                     }
00216                 }
00217 
00218                 $oDir->close();
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                     oxUtils::getInstance()->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         return $sValue;
00291     }
00292 
00300     protected function _getImagePath( $sType )
00301     {
00302         $sFolder = array_key_exists( $sType, $this->_aTypeToPath ) ? $this->_aTypeToPath[ $sType ] : '0';
00303         $sPath = $this->normalizeDir( $this->getConfig()->getPictureDir(false) ) . "{$sFolder}/";
00304         return $sPath;
00305     }
00306 
00317     protected function _getImageSize( $sImgType, $iImgNum, $sImgConf )
00318     {
00319         $myConfig = $this->getConfig();
00320         $sSize = false;
00321 
00322         switch ( $sImgConf ) {
00323             case 'aDetailImageSizes':
00324                 $aDetailImageSizes = $myConfig->getConfigParam( $sImgConf );
00325                 $sSize = $myConfig->getConfigParam( 'sDetailImageSize' );
00326                 if ( isset( $aDetailImageSizes['oxpic'.$iImgNum] ) ) {
00327                     $sSize = $aDetailImageSizes['oxpic'.$iImgNum];
00328                 }
00329                 break;
00330             default:
00331                 $sSize = $myConfig->getConfigParam( $sImgConf );
00332                 break;
00333         }
00334         if ( $sSize ) {
00335             return explode( '*', $sSize );
00336         }
00337     }
00338 
00347     protected function _copyFile( $sSource, $sTarget )
00348     {
00349         $blDone = false;
00350 
00351         if ( $sSource === $sTarget ) {
00352             $blDone = true;
00353         } else {
00354             $blDone = copy( $sSource, $sTarget );
00355         }
00356 
00357         if ( $blDone ) {
00358             $blDone = @chmod( $sTarget, 0644 );
00359         }
00360 
00361         return $blDone;
00362     }
00363 
00372     protected function _moveImage( $sSource, $sTarget )
00373     {
00374         $blDone = false;
00375 
00376         if ( $sSource === $sTarget ) {
00377             $blDone = true;
00378         } else {
00379             $blDone = move_uploaded_file( $sSource, $sTarget );
00380         }
00381 
00382         if ( $blDone ) {
00383             $blDone = @chmod( $sTarget, 0644 );
00384         }
00385 
00386         return $blDone;
00387     }
00388 
00400     public function processFiles( $oObject = null, $aFiles = array(), $blUseMasterImage = false, $blUnique = true )
00401     {
00402         $aFiles = $aFiles ? $aFiles : $_FILES;
00403         if ( isset( $aFiles['myfile']['name'] ) ) {
00404 
00405             $oConfig = $this->getConfig();
00406             $oStr = getStr();
00407 
00408             // A. protection for demoshops - strictly defining allowed file extensions
00409             $blDemo = (bool) $oConfig->isDemoShop();
00410 
00411             // folder where images will be processed
00412             $sTmpFolder = $oConfig->getConfigParam( "sCompileDir" );
00413 
00414             // process all files
00415             while ( list( $sKey, $sValue ) = each( $aFiles['myfile']['name'] ) ) {
00416 
00417                 $aSource   = $aFiles['myfile']['tmp_name'];
00418                 $sSource   = $aSource[$sKey];
00419                 $aFiletype = explode( "@", $sKey );
00420                 $sKey      = $aFiletype[1];
00421                 $sType     = $aFiletype[0];
00422 
00423                 $sValue  = strtolower( $sValue );
00424                 $sImagePath = $this->_getImagePath( $sType );
00425 
00426                 // checking file type and building final file name
00427                 if ( $sSource && ( $sValue = $this->_prepareImageName( $sValue, $sType, $blDemo, $sImagePath, $blUnique ) ) ) {
00428                     // moving to tmp folder for processing as safe mode or spec. open_basedir setup
00429                     // usually does not allow file modification in php's temp folder
00430                     $sProcessPath = $sTmpFolder . basename( $sSource );
00431 
00432                     if ( $sProcessPath ) {
00433 
00434                         if ( $blUseMasterImage ) {
00435                             //using master image as source, so only copying it to
00436                             $blMoved = $this->_copyFile( $sSource, $sImagePath . $sValue );
00437                         } else {
00438                             $blMoved = $this->_moveImage( $sSource, $sImagePath . $sValue );
00439                         }
00440 
00441                         if ( $blMoved ) {
00442                             // assign the name
00443                             if ( $oObject && isset( $oObject->$sKey ) ) {
00444                                 $oObject->{$sKey}->setValue( $sValue );
00445                             }
00446                         }
00447                     }
00448                 }
00449             }
00450         }
00451 
00452         return $oObject;
00453     }
00454 
00463     function checkFile( $sFile )
00464     {
00465         $aCheckCache = oxSession::getVar("checkcache");
00466 
00467         if ( isset( $aCheckCache[$sFile] ) ) {
00468             return $aCheckCache[$sFile];
00469         }
00470 
00471         $blRet = false;
00472 
00473         if (is_readable( $sFile)) {
00474             $blRet = true;
00475         } else {
00476             // try again via socket
00477             $blRet = $this->urlValidate( $sFile );
00478         }
00479 
00480         $aCheckCache[$sFile] = $blRet;
00481         oxSession::setVar( "checkcache", $aCheckCache );
00482 
00483         return $blRet;
00484     }
00485 
00493     function urlValidate( $sLink )
00494     {
00495         $aUrlParts = @parse_url( $sLink );
00496         $sHost = ( isset( $aUrlParts["host"] ) && $aUrlParts["host"] ) ? $aUrlParts["host"] : null;
00497 
00498         $blValid = false;
00499         if ( $sHost ) {
00500             $sDocumentPath  = ( isset( $aUrlParts["path"] ) && $aUrlParts["path"] ) ? $aUrlParts["path"] : '/';
00501             $sDocumentPath .= ( isset( $aUrlParts["query"] ) && $aUrlParts["query"] ) ? '?' . $aUrlParts["query"] : '';
00502 
00503             $sPort = ( isset( $aUrlParts["port"] ) && $aUrlParts["port"] ) ? $aUrlParts["port"] : '80';
00504 
00505             // Now (HTTP-)GET $documentpath at $sHost";
00506             if ( ( $oConn = @fsockopen( $sHost, $sPort, $iErrNo, $sErrStr, 30 ) ) ) {
00507                 fwrite ( $oConn, "HEAD {$sDocumentPath} HTTP/1.0\r\nHost: {$sHost}\r\n\r\n" );
00508                 $sResponse = fgets( $oConn, 22 );
00509                 fclose( $oConn );
00510 
00511                 if ( preg_match( "/200 OK/", $sResponse ) ) {
00512                     $blValid = true;
00513                 }
00514             }
00515         }
00516 
00517         return $blValid;
00518     }
00519 
00532     public function handleUploadedFile($aFileInfo, $sUploadPath)
00533     {
00534         $sBasePath = $this->getConfig()->getConfigParam('sShopDir');
00535 
00536         //checking params
00537         if ( !isset( $aFileInfo['name'] ) || !isset( $aFileInfo['tmp_name'] ) ) {
00538             throw oxNew( "oxException", 'EXCEPTION_NOFILE' );
00539         }
00540 
00541         //wrong chars in file name?
00542         if ( !getStr()->preg_match('/^[\-_a-z0-9\.]+$/i', $aFileInfo['name'] ) ) {
00543             throw oxNew( "oxException", 'EXCEPTION_FILENAMEINVALIDCHARS' );
00544         }
00545 
00546         // error uploading file ?
00547         if ( isset( $aFileInfo['error'] ) && $aFileInfo['error'] ) {
00548             throw oxNew( "oxException", 'EXCEPTION_FILEUPLOADERROR_'.( (int) $aFileInfo['error'] ) );
00549         }
00550 
00551         $aPathInfo = pathinfo($aFileInfo['name']);
00552 
00553         $sExt = $aPathInfo['extension'];
00554         $sFileName = $aPathInfo['filename'];
00555 
00556         $aAllowedUploadTypes = (array) $this->getConfig()->getConfigParam( 'aAllowedUploadTypes' );
00557         $aAllowedUploadTypes = array_map( "strtolower", $aAllowedUploadTypes );
00558         if ( !in_array( strtolower( $sExt ), $aAllowedUploadTypes ) ) {
00559             throw oxNew( "oxException", 'EXCEPTION_NOTALLOWEDTYPE' );
00560         }
00561 
00562         $sFileName = $this->_getUniqueFileName( $sBasePath . $sUploadPath, $sFileName, $sExt );
00563         $this->_moveImage( $aFileInfo['tmp_name'], $sBasePath . $sUploadPath . "/" . $sFileName );
00564 
00565         $sUrl = $this->getConfig()->getShopUrl() . $sUploadPath . "/" . $sFileName;
00566 
00567         //removing dublicate slashes
00568         $sUrl = str_replace('//', '/', $sUrl);
00569         $sUrl = str_replace(array('http:/', 'https:/'), array('http://', 'https://'), $sUrl);
00570 
00571         return $sUrl;
00572     }
00573 
00584     public function processFile( $sFileName, $sUploadPath )
00585     {
00586         $aFileInfo = $_FILES[$sFileName];
00587 
00588         $sBasePath = $this->getConfig()->getConfigParam('sShopDir');
00589 
00590         //checking params
00591         if ( !isset( $aFileInfo['name'] ) || !isset( $aFileInfo['tmp_name'] ) ) {
00592             throw oxNew( "oxException", 'EXCEPTION_NOFILE' );
00593         }
00594 
00595         //wrong chars in file name?
00596         if ( !getStr()->preg_match('/^[\-_a-z0-9\.]+$/i', $aFileInfo['name'] ) ) {
00597             throw oxNew( "oxException", 'EXCEPTION_FILENAMEINVALIDCHARS' );
00598         }
00599 
00600         // error uploading file ?
00601         if ( isset( $aFileInfo['error'] ) && $aFileInfo['error'] ) {
00602             throw oxNew( "oxException", 'EXCEPTION_FILEUPLOADERROR_'.( (int) $aFileInfo['error'] ) );
00603         }
00604 
00605         $aPathInfo = pathinfo($aFileInfo['name']);
00606 
00607         $sExt = $aPathInfo['extension'];
00608         $sFileName = $aPathInfo['filename'];
00609 
00610         $aAllowedUploadTypes = (array) $this->getConfig()->getConfigParam( 'aAllowedUploadTypes' );
00611         $aAllowedUploadTypes = array_map( "strtolower", $aAllowedUploadTypes );
00612 
00613         if ( !in_array( strtolower( $sExt ), $aAllowedUploadTypes ) ) {
00614             throw oxNew( "oxException", 'EXCEPTION_NOTALLOWEDTYPE' );
00615         }
00616 
00617         $sFileName = $this->_getUniqueFileName( $sBasePath . $sUploadPath, $sFileName, $sExt );
00618 
00619         if ( $this->_moveImage( $aFileInfo['tmp_name'], $sBasePath . $sUploadPath . "/" . $sFileName ) ) {
00620             return $sFileName ;
00621         } else {
00622             return false;
00623         }
00624     }
00625 
00638     protected function _getUniqueFileName( $sFilePath, $sFileName, $sFileExt, $sSufix = "", $blUnique = true )
00639     {
00640         $sFilePath     = $this->normalizeDir( $sFilePath );
00641         $iFileCounter  = 0;
00642         $sTempFileName = $sFileName;
00643         $oStr = getStr();
00644 
00645         //file exists ?
00646         while ( $blUnique && file_exists( $sFilePath . "/" . $sFileName . $sSufix . "." . $sFileExt ) ) {
00647             $iFileCounter++;
00648 
00649             //removing "(any digit)" from file name end
00650             $sTempFileName = $oStr->preg_replace("/\(".$iFileCounter."\)/", "", $sTempFileName );
00651 
00652             $sFileName = $sTempFileName . "($iFileCounter)";
00653         }
00654 
00655         return $sFileName . $sSufix . "." . $sFileExt;
00656     }
00657 
00665     public function getImageDirByType( $sType )
00666     {
00667         $sFolder = array_key_exists( $sType, $this->_aTypeToPath ) ? $this->_aTypeToPath[ $sType ] : '0';
00668         return $this->normalizeDir( $sFolder );
00669     }
00670 }