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( 'ICO'  => 'icon',
00042                                      'CICO' => 'icon',
00043                                      'PICO' => 'icon',
00044                                      'MICO' => 'icon',
00045                                      'TH'   => '0',
00046                                      'TC'   => '0',
00047                                      'M1'   => 'master/1',
00048                                      'M2'   => 'master/2',
00049                                      'M3'   => 'master/3',
00050                                      'M4'   => 'master/4',
00051                                      'M5'   => 'master/5',
00052                                      'M6'   => 'master/6',
00053                                      'M7'   => 'master/7',
00054                                      'M8'   => 'master/8',
00055                                      'M9'   => 'master/9',
00056                                      'M10'  => 'master/10',
00057                                      'M11'  => 'master/11',
00058                                      'M12'  => 'master/12',
00059                                      'P1'   => '1',
00060                                      'P2'   => '2',
00061                                      'P3'   => '3',
00062                                      'P4'   => '4',
00063                                      'P5'   => '5',
00064                                      'P6'   => '6',
00065                                      'P7'   => '7',
00066                                      'P8'   => '8',
00067                                      'P9'   => '9',
00068                                      'P10'  => '10',
00069                                      'P11'  => '11',
00070                                      'P12'  => '12',
00071                                      'Z1'   => 'z1',
00072                                      'Z2'   => 'z2',
00073                                      'Z3'   => 'z3',
00074                                      'Z4'   => 'z4',
00075                                      'Z5'   => 'z5',
00076                                      'Z6'   => 'z6',
00077                                      'Z7'   => 'z7',
00078                                      'Z8'   => 'z8',
00079                                      'Z9'   => 'z9',
00080                                      'Z10'  => 'z10',
00081                                      'Z11'  => 'z11',
00082                                      'Z12'  => 'z12',
00083                                      'PROMO'=> self::PROMO_PICTURE_DIR,
00084                                    );
00085 
00091     protected $_aBadFiles = array( 'php', 'jsp', 'cgi', 'cmf', 'exe' );
00092 
00093 
00099     protected $_aAllowedFiles = array( 'gif', 'jpg', 'png', 'pdf' );
00105     public static function getInstance()
00106     {
00107         // disable caching for test modules
00108         if ( defined( 'OXID_PHP_UNIT' ) ) {
00109             self::$_instance = modInstances::getMod( __CLASS__ );
00110         }
00111 
00112         if ( !self::$_instance instanceof oxUtilsFile ) {
00113 
00114             self::$_instance = oxNew( 'oxUtilsFile' );
00115             if ( defined( 'OXID_PHP_UNIT' ) ) {
00116                 modInstances::addMod( __CLASS__, self::$_instance);
00117             }
00118         }
00119         return self::$_instance;
00120     }
00121 
00127     public function __construct()
00128     {
00129         $myConfig = $this->getConfig();
00130 
00131         if ( $iPicCount = $myConfig->getConfigParam( 'iPicCount' ) ) {
00132             $this->_iMaxPicImgCount = $iPicCount;
00133         }
00134 
00135         $this->_iMaxZoomImgCount = $this->_iMaxPicImgCount;
00136     }
00137 
00145     public function normalizeDir( $sDir )
00146     {
00147         if ( isset($sDir) && $sDir != "" && substr($sDir, -1) !== '/' ) {
00148             $sDir .= "/";
00149         }
00150 
00151         return $sDir;
00152     }
00153 
00162     public function copyDir( $sSourceDir, $sTargetDir )
00163     {
00164         $oStr = getStr();
00165         $handle = opendir( $sSourceDir );
00166         while ( false !== ( $file = readdir( $handle ) ) ) {
00167             if ( $file != '.' && $file != '..' ) {
00168                 if ( is_dir( $sSourceDir.'/'.$file ) ) {
00169 
00170                     // recursive
00171                     $sNewSourceDir = $sSourceDir.'/'.$file;
00172                     $sNewTargetDir = $sTargetDir.'/'.$file;
00173                     if ( strcasecmp( $file, 'CVS' ) &&  strcasecmp( $file, '.svn' )) {
00174                         @mkdir( $sNewTargetDir, 0777 );
00175                         $this->copyDir( $sNewSourceDir, $sNewTargetDir );
00176                     }
00177                 } else {
00178                     $sSourceFile = $sSourceDir.'/'.$file;
00179                     $sTargetFile = $sTargetDir.'/'.$file;
00180 
00181                     //do not copy files within dyn_images
00182                     if ( !$oStr->strstr( $sSourceDir, 'dyn_images' ) ||  $file == 'nopic.jpg' || $file == 'nopic_ico.jpg' ) {
00183                         @copy( $sSourceFile, $sTargetFile );
00184                     }
00185                 }
00186             }
00187         }
00188         closedir($handle);
00189     }
00190 
00198     public function deleteDir( $sSourceDir )
00199     {
00200         if ( is_dir( $sSourceDir ) ) {
00201             if ( $oDir = dir( $sSourceDir ) ) {
00202 
00203                 while ( false !== $sFile = $oDir->read() ) {
00204                     if ( $sFile == '.' || $sFile == '..' ) {
00205                         continue;
00206                     }
00207 
00208                     if ( !$this->deleteDir( $oDir->path . DIRECTORY_SEPARATOR . $sFile ) ) {
00209                         $oDir->close();
00210                         return false;
00211                     }
00212                 }
00213 
00214                 $oDir->close();
00215                 return rmdir( $sSourceDir );
00216             }
00217         } elseif ( file_exists( $sSourceDir ) ) {
00218             return unlink ( $sSourceDir );
00219         }
00220     }
00221 
00229     public function readRemoteFileAsString( $sPath )
00230     {
00231         $sRet  = '';
00232         $hFile = @fopen( $sPath, 'r' );
00233         if ( $hFile ) {
00234             socket_set_timeout( $hFile, 2 );
00235             while ( !feof( $hFile ) ) {
00236                 $sLine = fgets( $hFile, 4096 );
00237                 $sRet .= $sLine;
00238             }
00239             fclose( $hFile );
00240         }
00241 
00242         return $sRet;
00243     }
00244 
00256     protected function _prepareImageName( $sValue, $sType, $blDemo, $sImagePath, $blUnique = true )
00257     {
00258         if ( $sValue ) {
00259             // add type to name
00260             $aFilename = explode( ".", $sValue );
00261 
00262             $sFileType = trim( $aFilename[count( $aFilename )-1] );
00263 
00264             if ( isset( $sFileType ) ) {
00265 
00266                 $oStr = getStr();
00267 
00268                 // unallowed files ?
00269                 if ( in_array( $sFileType, $this->_aBadFiles ) || ( $blDemo && !in_array( $sFileType, $this->_aAllowedFiles ) ) ) {
00270                     oxUtils::getInstance()->showMessageAndExit( "We don't play this game, go away" );
00271                 }
00272 
00273                 // removing file type
00274                 if ( count( $aFilename ) > 0 ) {
00275                     unset( $aFilename[count( $aFilename )-1] );
00276                 }
00277 
00278                 $sFName = '';
00279                 if ( isset( $aFilename[0] ) ) {
00280                     $sFName = $oStr->preg_replace( '/[^a-zA-Z0-9()_\.-]/', '', implode( '.', $aFilename ) );
00281                 }
00282 
00283                 // removing sufix from main pictures, only zoom pictures, thumbnails
00284                 // and icons will have it.
00285                 $sSufix = ( $oStr->preg_match( "/(P|M)\d+/", $sType ) ) ? "" : "_".strtolower( $sType );
00286 
00287                 $sValue = $this->_getUniqueFileName( $sImagePath, "{$sFName}", $sFileType, $sSufix, $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 
00349     protected function _prepareImage( $sType, $sSource, $sTarget )
00350     {
00351         $oUtilsPic = oxUtilspic::getInstance();
00352         $oPictureHandler = oxPictureHandler::getInstance();
00353         $oStr = getStr();
00354 
00355         // picture type
00356         $sPicType = $oStr->preg_replace( "/\d*$/", "", $sType );
00357 
00358         // numper of processable picture
00359         $iPicNum  = (int) $oStr->preg_replace( "/^\D*/", "", $sType );
00360         $iPicNum = $iPicNum ? abs( $iPicNum ) : 1;
00361 
00362         $aSize = false;
00363         $blResize = false;
00364 
00365         // add file process here
00366         switch ( $sPicType ) {
00367             case 'TH':
00368                 $aSize = $this->_getImageSize( $sType, $iPicNum, 'sThumbnailsize' );
00369                 break;
00370             case 'TC':
00371                 $aSize = $this->_getImageSize( $sType, $iPicNum, 'sCatThumbnailsize' );
00372                 break;
00373             case 'MICO':
00374                 $sManufacturerIconsize = $this->getConfig()->getConfigParam( 'sManufacturerIconsize' );
00375                 if ( isset( $sManufacturerIconsize ) ) {
00376                     $aSize = $this->_getImageSize( $sType, $iPicNum, 'sManufacturerIconsize' );
00377                 } else {
00378                     $aSize = $this->_getImageSize( $sType, $iPicNum, 'sIconsize' );
00379                 }
00380                 break;
00381             case 'PICO':
00382                 $aSize = $this->_getImageSize( $sType, $iPicNum, 'sCatPromotionsize' );
00383                 break;
00384             case 'CICO':
00385                 $sCatIconsize = $this->getConfig()->getConfigParam( 'sCatIconsize' );
00386                 if ( isset( $sCatIconsize ) ) {
00387                     $aSize = $this->_getImageSize( $sType, $iPicNum, 'sCatIconsize' );
00388                 } else {
00389                     $aSize = $this->_getImageSize( $sType, $iPicNum, 'sIconsize' );
00390                 }
00391                 break;
00392             case 'ICO':
00393                 $aSize = $this->_getImageSize( $sType, $iPicNum, 'sIconsize' );
00394                 break;
00395             case 'P':
00396                 // pictures count is limited to 12
00397                 $iPicNum = ( $iPicNum > $this->_iMaxPicImgCount ) ? $this->_iMaxPicImgCount : $iPicNum;
00398 
00399                 //make an icon
00400                 if ( ( $aSize = $this->_getImageSize( $sType, 1, 'sIconsize' ) ) ) {
00401                     $sIconTarget = dirname($sTarget) . '/' . $oPictureHandler->getIconName( $sTarget );
00402                     $oUtilsPic->resizeImage( $sSource, $sIconTarget, $aSize[0], $aSize[1] );
00403                 }
00404 
00405                 $aSize = $this->_getImageSize( $sType, $iPicNum, 'aDetailImageSizes' );
00406                 break;
00407             case 'M':
00408             case 'WP':
00409             case 'FL':
00410             case 'PROMO':
00411                 // just copy file to target folder
00412                 $this->_copyFile($sSource, $sTarget);
00413                 break;
00414             case 'Z':
00415                 $aSize = $this->_getImageSize( $sType, $iPicNum, 'sZoomImageSize' );
00416                 break;
00417         }
00418 
00419         if ( $aSize ) {
00420             $blResize = $oUtilsPic->resizeImage( $sSource, $sTarget, $aSize[0], $aSize[1] );
00421         }
00422         return $blResize;
00423     }
00424 
00433     protected function _copyFile( $sSource, $sTarget )
00434     {
00435         $blDone = false;
00436 
00437         if ( $sSource === $sTarget ) {
00438             $blDone = true;
00439         } else {
00440             $blDone = copy( $sSource, $sTarget );
00441         }
00442 
00443         if ( $blDone ) {
00444             $blDone = @chmod( $sTarget, 0644 );
00445         }
00446 
00447         return $blDone;
00448     }
00449 
00458     protected function _moveImage( $sSource, $sTarget )
00459     {
00460 
00461 
00462         $blDone = false;
00463 
00464         if ( $sSource === $sTarget ) {
00465             $blDone = true;
00466         } else {
00467             $blDone = move_uploaded_file( $sSource, $sTarget );
00468         }
00469 
00470         if ( $blDone ) {
00471             $blDone = @chmod( $sTarget, 0644 );
00472         }
00473 
00474         return $blDone;
00475     }
00476 
00484     protected function _removeTempImage( $sImagePath )
00485     {
00486         return unlink( $sImagePath );
00487     }
00488 
00500     public function processFiles( $oObject = null, $aFiles = array(), $blUseMasterImage = false, $blUnique = true )
00501     {
00502         $aFiles = $aFiles ? $aFiles : $_FILES;
00503         if ( isset( $aFiles['myfile']['name'] ) ) {
00504 
00505             $oConfig = $this->getConfig();
00506             $oStr = getStr();
00507 
00508             // A. protection for demoshops - strictly defining allowed file extensions
00509             $blDemo = (bool) $oConfig->isDemoShop();
00510 
00511             // folder where images will be processed
00512             $sTmpFolder = $oConfig->getConfigParam( "sCompileDir" );
00513 
00514             // process all files
00515             while ( list( $sKey, $sValue ) = each( $aFiles['myfile']['name'] ) ) {
00516 
00517                 $aSource   = $aFiles['myfile']['tmp_name'];
00518                 $sSource   = $aSource[$sKey];
00519                 $aFiletype = explode( "@", $sKey );
00520                 $sKey      = $aFiletype[1];
00521                 $sType     = $aFiletype[0];
00522 
00523                 $sValue  = strtolower( $sValue );
00524                 $sImagePath = $this->_getImagePath( $sType );
00525 
00526                 // checking file type and building final file name
00527                 if ( $sSource && ( $sValue = $this->_prepareImageName( $sValue, $sType, $blDemo, $sImagePath, $blUnique ) ) ) {
00528                     // moving to tmp folder for processing as safe mode or spec. open_basedir setup
00529                     // usually does not allow file modification in php's temp folder
00530                     $sProcessPath = $sTmpFolder . basename( $sSource );
00531 
00532                     if ( $sProcessPath ) {
00533 
00534                         if ( $blUseMasterImage ) {
00535                             //using master image as source, so only copying it to
00536                             //temp dir for processing
00537                             $blMoved = $this->_copyFile( $sSource, $sProcessPath );
00538                         } else {
00539                             $blMoved = $this->_moveImage( $sSource, $sProcessPath );
00540                         }
00541 
00542                         if ( $blMoved ) {
00543                             // finding final image path
00544                             if ( ( $sTarget = $sImagePath . $sValue ) ) {
00545                                 // processing image and moving to final location
00546                                 $this->_prepareImage( $sType, $sProcessPath, $sTarget );
00547 
00548                                 // assign the name
00549                                 if ( $oObject ) {
00550                                     $oObject->{$sKey}->setValue( $sValue );
00551                                 }
00552                             }
00553                         }
00554 
00555                         // removing temporary file
00556                         $this->_removeTempImage( $sProcessPath );
00557                     }
00558                 }
00559             }
00560         }
00561 
00562         return $oObject;
00563     }
00564 
00573     function checkFile( $sFile )
00574     {
00575         $aCheckCache = oxSession::getVar("checkcache");
00576 
00577         if ( isset( $aCheckCache[$sFile] ) ) {
00578             return $aCheckCache[$sFile];
00579         }
00580 
00581         $blRet = false;
00582 
00583         if (is_readable( $sFile)) {
00584             $blRet = true;
00585         } else {
00586             // try again via socket
00587             $blRet = $this->urlValidate( $sFile );
00588         }
00589 
00590         $aCheckCache[$sFile] = $blRet;
00591         oxSession::setVar( "checkcache", $aCheckCache );
00592 
00593         return $blRet;
00594     }
00595 
00603     function urlValidate( $sLink )
00604     {
00605         $aUrlParts = @parse_url( $sLink );
00606         $sHost = ( isset( $aUrlParts["host"] ) && $aUrlParts["host"] ) ? $aUrlParts["host"] : null;
00607 
00608         $blValid = false;
00609         if ( $sHost ) {
00610             $sDocumentPath  = ( isset( $aUrlParts["path"] ) && $aUrlParts["path"] ) ? $aUrlParts["path"] : '/';
00611             $sDocumentPath .= ( isset( $aUrlParts["query"] ) && $aUrlParts["query"] ) ? '?' . $aUrlParts["query"] : '';
00612 
00613             $sPort = ( isset( $aUrlParts["port"] ) && $aUrlParts["port"] ) ? $aUrlParts["port"] : '80';
00614 
00615             // Now (HTTP-)GET $documentpath at $sHost";
00616             if ( ( $oConn = @fsockopen( $sHost, $sPort, $iErrNo, $sErrStr, 30 ) ) ) {
00617                 fwrite ( $oConn, "HEAD {$sDocumentPath} HTTP/1.0\r\nHost: {$sHost}\r\n\r\n" );
00618                 $sResponse = fgets( $oConn, 22 );
00619                 fclose( $oConn );
00620 
00621                 if ( preg_match( "/200 OK/", $sResponse ) ) {
00622                     $blValid = true;
00623                 }
00624             }
00625         }
00626 
00627         return $blValid;
00628     }
00629 
00640     public function handleUploadedFile($aFileInfo, $sUploadPath)
00641     {
00642         $sBasePath = $this->getConfig()->getConfigParam('sShopDir');
00643 
00644         //checking params
00645         if ( !isset( $aFileInfo['name'] ) || !isset( $aFileInfo['tmp_name'] ) ) {
00646             throw new oxException( 'EXCEPTION_NOFILE' );
00647         }
00648 
00649         //wrong chars in file name?
00650         if ( !getStr()->preg_match('/^[\-_a-z0-9\.]+$/i', $aFileInfo['name'] ) ) {
00651             throw new oxException( 'EXCEPTION_FILENAMEINVALIDCHARS' );
00652         }
00653 
00654         // error uploading file ?
00655         if ( isset( $aFileInfo['error'] ) && $aFileInfo['error'] ) {
00656             throw new oxException( 'EXCEPTION_FILEUPLOADERROR_'.( (int) $aFileInfo['error'] ) );
00657         }
00658 
00659         $aPathInfo = pathinfo($aFileInfo['name']);
00660 
00661         $sExt = $aPathInfo['extension'];
00662         $sFileName = $aPathInfo['filename'];
00663 
00664         $aAllowedUploadTypes = (array) $this->getConfig()->getConfigParam( 'aAllowedUploadTypes' );
00665         $aAllowedUploadTypes = array_map( "strtolower", $aAllowedUploadTypes );
00666         if ( !in_array( strtolower( $sExt ), $aAllowedUploadTypes ) ) {
00667             throw new oxException( 'EXCEPTION_NOTALLOWEDTYPE' );
00668         }
00669 
00670         $sFileName = $this->_getUniqueFileName( $sBasePath . $sUploadPath, $sFileName, $sExt );
00671         $this->_moveImage( $aFileInfo['tmp_name'], $sBasePath . $sUploadPath . "/" . $sFileName );
00672 
00673         $sUrl = $this->getConfig()->getShopUrl() . $sUploadPath . "/" . $sFileName;
00674 
00675         //removing dublicate slashes
00676         $sUrl = str_replace('//', '/', $sUrl);
00677         $sUrl = str_replace('http:/', 'http://', $sUrl);
00678 
00679         return $sUrl;
00680     }
00681 
00694     protected function _getUniqueFileName( $sFilePath, $sFileName, $sFileExt, $sSufix = "", $blUnique = true )
00695     {
00696         $sFilePath     = $this->normalizeDir( $sFilePath );
00697         $iFileCounter  = 0;
00698         $sTempFileName = $sFileName;
00699         $oStr = getStr();
00700 
00701         //file exists ?
00702         while ( $blUnique && file_exists( $sFilePath . "/" . $sFileName . $sSufix . "." . $sFileExt ) ) {
00703             $iFileCounter++;
00704 
00705             //removing "(any digit)" from file name end
00706             $sTempFileName = $oStr->preg_replace("/\(".$iFileCounter."\)/", "", $sTempFileName );
00707 
00708             $sFileName = $sTempFileName . "($iFileCounter)";
00709         }
00710 
00711         return $sFileName . $sSufix . "." . $sFileExt;
00712     }
00713 
00721     public function getImageDirByType( $sType )
00722     {
00723         $sFolder = array_key_exists( $sType, $this->_aTypeToPath ) ? $this->_aTypeToPath[ $sType ] : '0';
00724 
00725         return $this->normalizeDir( $sFolder );
00726     }
00727 }