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' );
00104 
00110     protected $_iNewFilesCounter = 0;
00111 
00119     public static function getInstance()
00120     {
00121         return oxRegistry::get("oxUtilsFile");
00122     }
00123 
00129     public function __construct()
00130     {
00131         $myConfig = $this->getConfig();
00132 
00133         if ( $iPicCount = $myConfig->getConfigParam( 'iPicCount' ) ) {
00134             $this->_iMaxPicImgCount = $iPicCount;
00135         }
00136 
00137         $this->_iMaxZoomImgCount = $this->_iMaxPicImgCount;
00138     }
00139 
00145     public function getNewFilesCounter()
00146     {
00147         return $this->_iNewFilesCounter;
00148     }
00149 
00157     protected function _setNewFilesCounter( $iNewFilesCounter )
00158     {
00159         $this->_iNewFilesCounter = (int) $iNewFilesCounter;
00160     }
00161 
00169     public function normalizeDir( $sDir )
00170     {
00171         if ( isset($sDir) && $sDir != "" && substr($sDir, -1) !== '/' ) {
00172             $sDir .= "/";
00173         }
00174 
00175         return $sDir;
00176     }
00177 
00186     public function copyDir( $sSourceDir, $sTargetDir )
00187     {
00188         $oStr = getStr();
00189         $handle = opendir( $sSourceDir );
00190         while ( false !== ( $file = readdir( $handle ) ) ) {
00191             if ( $file != '.' && $file != '..' ) {
00192                 if ( is_dir( $sSourceDir.'/'.$file ) ) {
00193 
00194                     // recursive
00195                     $sNewSourceDir = $sSourceDir.'/'.$file;
00196                     $sNewTargetDir = $sTargetDir.'/'.$file;
00197                     if ( strcasecmp( $file, 'CVS' ) &&  strcasecmp( $file, '.svn' )) {
00198                         @mkdir( $sNewTargetDir, 0777 );
00199                         $this->copyDir( $sNewSourceDir, $sNewTargetDir );
00200                     }
00201                 } else {
00202                     $sSourceFile = $sSourceDir.'/'.$file;
00203                     $sTargetFile = $sTargetDir.'/'.$file;
00204 
00205                     //do not copy files within dyn_images
00206                     if ( !$oStr->strstr( $sSourceDir, 'dyn_images' ) ||  $file == 'nopic.jpg' || $file == 'nopic_ico.jpg' ) {
00207                         @copy( $sSourceFile, $sTargetFile );
00208                     }
00209                 }
00210             }
00211         }
00212         closedir($handle);
00213     }
00214 
00222     public function deleteDir( $sSourceDir )
00223     {
00224         if ( is_dir( $sSourceDir ) ) {
00225             if ( $oDir = dir( $sSourceDir ) ) {
00226 
00227                 while ( false !== $sFile = $oDir->read() ) {
00228                     if ( $sFile == '.' || $sFile == '..' ) {
00229                         continue;
00230                     }
00231 
00232                     if ( !$this->deleteDir( $oDir->path . DIRECTORY_SEPARATOR . $sFile ) ) {
00233                         $oDir->close();
00234                         return false;
00235                     }
00236                 }
00237 
00238                 $oDir->close();
00239                 return rmdir( $sSourceDir );
00240             }
00241         } elseif ( file_exists( $sSourceDir ) ) {
00242             return unlink ( $sSourceDir );
00243         }
00244     }
00245 
00253     public function readRemoteFileAsString( $sPath )
00254     {
00255         $sRet  = '';
00256         $hFile = @fopen( $sPath, 'r' );
00257         if ( $hFile ) {
00258             socket_set_timeout( $hFile, 2 );
00259             while ( !feof( $hFile ) ) {
00260                 $sLine = fgets( $hFile, 4096 );
00261                 $sRet .= $sLine;
00262             }
00263             fclose( $hFile );
00264         }
00265 
00266         return $sRet;
00267     }
00268 
00280     protected function _prepareImageName( $sValue, $sType, $blDemo, $sImagePath, $blUnique = true )
00281     {
00282         if ( $sValue ) {
00283             // add type to name
00284             $aFilename = explode( ".", $sValue );
00285 
00286             $sFileType = trim( $aFilename[count( $aFilename )-1] );
00287 
00288             if ( isset( $sFileType ) ) {
00289 
00290                 $oStr = getStr();
00291 
00292                 // unallowed files ?
00293                 if ( in_array( $sFileType, $this->_aBadFiles ) || ( $blDemo && !in_array( $sFileType, $this->_aAllowedFiles ) ) ) {
00294                     oxRegistry::getUtils()->showMessageAndExit( "We don't play this game, go away" );
00295                 }
00296 
00297                 // removing file type
00298                 if ( count( $aFilename ) > 0 ) {
00299                     unset( $aFilename[count( $aFilename )-1] );
00300                 }
00301 
00302                 $sFName = '';
00303                 if ( isset( $aFilename[0] ) ) {
00304                     $sFName = $oStr->preg_replace( '/[^a-zA-Z0-9()_\.-]/', '', implode( '.', $aFilename ) );
00305                 }
00306 
00307                 $sValue = $this->_getUniqueFileName( $sImagePath, "{$sFName}", $sFileType, "", $blUnique );
00308             }
00309         }
00310         return $sValue;
00311     }
00312 
00320     protected function _getImagePath( $sType )
00321     {
00322         $sFolder = array_key_exists( $sType, $this->_aTypeToPath ) ? $this->_aTypeToPath[ $sType ] : '0';
00323         $sPath = $this->normalizeDir( $this->getConfig()->getPictureDir(false) ) . "{$sFolder}/";
00324         return $sPath;
00325     }
00326 
00337     protected function _getImageSize( $sImgType, $iImgNum, $sImgConf )
00338     {
00339         $myConfig = $this->getConfig();
00340         $sSize = false;
00341 
00342         switch ( $sImgConf ) {
00343             case 'aDetailImageSizes':
00344                 $aDetailImageSizes = $myConfig->getConfigParam( $sImgConf );
00345                 $sSize = $myConfig->getConfigParam( 'sDetailImageSize' );
00346                 if ( isset( $aDetailImageSizes['oxpic'.$iImgNum] ) ) {
00347                     $sSize = $aDetailImageSizes['oxpic'.$iImgNum];
00348                 }
00349                 break;
00350             default:
00351                 $sSize = $myConfig->getConfigParam( $sImgConf );
00352                 break;
00353         }
00354         if ( $sSize ) {
00355             return explode( '*', $sSize );
00356         }
00357     }
00358 
00367     protected function _copyFile( $sSource, $sTarget )
00368     {
00369         $blDone = false;
00370 
00371         if ( $sSource === $sTarget ) {
00372             $blDone = true;
00373         } else {
00374             $blDone = copy( $sSource, $sTarget );
00375         }
00376 
00377         if ( $blDone ) {
00378             $blDone = @chmod( $sTarget, 0644 );
00379         }
00380 
00381         return $blDone;
00382     }
00383 
00392     protected function _moveImage( $sSource, $sTarget )
00393     {
00394         $blDone = false;
00395         if ( !is_dir( dirname( $sTarget ) ) ) {
00396             mkdir(dirname($sTarget), 0744, true);
00397         }
00398         if ( $sSource === $sTarget ) {
00399             $blDone = true;
00400         } else {
00401             $blDone = move_uploaded_file( $sSource, $sTarget );
00402         }
00403 
00404         if ( $blDone ) {
00405             $blDone = @chmod( $sTarget, 0644 );
00406         }
00407 
00408         return $blDone;
00409     }
00410 
00422     public function processFiles( $oObject = null, $aFiles = array(), $blUseMasterImage = false, $blUnique = true )
00423     {
00424         $aFiles = $aFiles ? $aFiles : $_FILES;
00425         if ( isset( $aFiles['myfile']['name'] ) ) {
00426 
00427             $oConfig = $this->getConfig();
00428             $oStr = getStr();
00429 
00430             // A. protection for demoshops - strictly defining allowed file extensions
00431             $blDemo = (bool) $oConfig->isDemoShop();
00432 
00433             // folder where images will be processed
00434             $sTmpFolder = $oConfig->getConfigParam( "sCompileDir" );
00435 
00436             $iNewFilesCounter = 0;
00437             $aSource   = $aFiles['myfile']['tmp_name'];
00438             $aError    = $aFiles['myfile']['error'];
00439             $sErrorsDescription = '';
00440 
00441             $oEx = oxNew( "oxExceptionToDisplay" );
00442             // process all files
00443             while ( list( $sKey, $sValue ) = each( $aFiles['myfile']['name'] ) ) {
00444 
00445                 $sSource   = $aSource[$sKey];
00446                 $iError    = $aError[$sKey];
00447                 $aFiletype = explode( "@", $sKey );
00448                 $sKey      = $aFiletype[1];
00449                 $sType     = $aFiletype[0];
00450 
00451                 $sValue  = strtolower( $sValue );
00452                 $sImagePath = $this->_getImagePath( $sType );
00453 
00454                 // Should translate error to user if file was uploaded
00455                 if ( UPLOAD_ERR_OK !== $iError && UPLOAD_ERR_NO_FILE !== $iError ) {
00456                     $sErrorsDescription = $this->translateError( $iError );
00457                     $oEx->setMessage( $sErrorsDescription );
00458                     oxRegistry::get("oxUtilsView")->addErrorToDisplay( $oEx, false );
00459                 }
00460 
00461                 // checking file type and building final file name
00462                 if ( $sSource && ( $sValue = $this->_prepareImageName( $sValue, $sType, $blDemo, $sImagePath, $blUnique ) ) ) {
00463                     // moving to tmp folder for processing as safe mode or spec. open_basedir setup
00464                     // usually does not allow file modification in php's temp folder
00465                     $sProcessPath = $sTmpFolder . basename( $sSource );
00466 
00467                     if ( $sProcessPath ) {
00468 
00469                         if ( $blUseMasterImage ) {
00470                             //using master image as source, so only copying it to
00471                             $blMoved = $this->_copyFile( $sSource, $sImagePath . $sValue );
00472                         } else {
00473                             $blMoved = $this->_moveImage( $sSource, $sImagePath . $sValue );
00474                         }
00475 
00476                         if ( $blMoved ) {
00477                             // New image successfully add.
00478                             $iNewFilesCounter++;
00479                             // assign the name
00480                             if ( $oObject && isset( $oObject->$sKey ) ) {
00481                                 $oObject->{$sKey}->setValue( $sValue );
00482                             }
00483                         }
00484                     }
00485                 }
00486             }
00487 
00488             $this->_setNewFilesCounter( $iNewFilesCounter );
00489         }
00490 
00491         return $oObject;
00492     }
00493 
00502     function checkFile( $sFile )
00503     {
00504         $aCheckCache = oxSession::getVar("checkcache");
00505 
00506         if ( isset( $aCheckCache[$sFile] ) ) {
00507             return $aCheckCache[$sFile];
00508         }
00509 
00510         $blRet = false;
00511 
00512         if (is_readable( $sFile)) {
00513             $blRet = true;
00514         } else {
00515             // try again via socket
00516             $blRet = $this->urlValidate( $sFile );
00517         }
00518 
00519         $aCheckCache[$sFile] = $blRet;
00520         oxSession::setVar( "checkcache", $aCheckCache );
00521 
00522         return $blRet;
00523     }
00524 
00532     function urlValidate( $sLink )
00533     {
00534         $aUrlParts = @parse_url( $sLink );
00535         $sHost = ( isset( $aUrlParts["host"] ) && $aUrlParts["host"] ) ? $aUrlParts["host"] : null;
00536 
00537         $blValid = false;
00538         if ( $sHost ) {
00539             $sDocumentPath  = ( isset( $aUrlParts["path"] ) && $aUrlParts["path"] ) ? $aUrlParts["path"] : '/';
00540             $sDocumentPath .= ( isset( $aUrlParts["query"] ) && $aUrlParts["query"] ) ? '?' . $aUrlParts["query"] : '';
00541 
00542             $sPort = ( isset( $aUrlParts["port"] ) && $aUrlParts["port"] ) ? $aUrlParts["port"] : '80';
00543 
00544             // Now (HTTP-)GET $documentpath at $sHost";
00545             if ( ( $oConn = @fsockopen( $sHost, $sPort, $iErrNo, $sErrStr, 30 ) ) ) {
00546                 fwrite ( $oConn, "HEAD {$sDocumentPath} HTTP/1.0\r\nHost: {$sHost}\r\n\r\n" );
00547                 $sResponse = fgets( $oConn, 22 );
00548                 fclose( $oConn );
00549 
00550                 if ( preg_match( "/200 OK/", $sResponse ) ) {
00551                     $blValid = true;
00552                 }
00553             }
00554         }
00555 
00556         return $blValid;
00557     }
00558 
00569     public function processFile( $sFileName, $sUploadPath )
00570     {
00571         $aFileInfo = $_FILES[$sFileName];
00572 
00573         $sBasePath = $this->getConfig()->getConfigParam('sShopDir');
00574 
00575         //checking params
00576         if ( !isset( $aFileInfo['name'] ) || !isset( $aFileInfo['tmp_name'] ) ) {
00577             throw oxNew( "oxException", 'EXCEPTION_NOFILE' );
00578         }
00579 
00580         //wrong chars in file name?
00581         if ( !getStr()->preg_match('/^[\-_a-z0-9\.]+$/i', $aFileInfo['name'] ) ) {
00582             throw oxNew( "oxException", 'EXCEPTION_FILENAMEINVALIDCHARS' );
00583         }
00584 
00585         // error uploading file ?
00586         if ( isset( $aFileInfo['error'] ) && $aFileInfo['error'] ) {
00587             throw oxNew( "oxException", 'EXCEPTION_FILEUPLOADERROR_'.( (int) $aFileInfo['error'] ) );
00588         }
00589 
00590         $aPathInfo = pathinfo($aFileInfo['name']);
00591 
00592         $sExt = $aPathInfo['extension'];
00593         $sFileName = $aPathInfo['filename'];
00594 
00595         $aAllowedUploadTypes = (array) $this->getConfig()->getConfigParam( 'aAllowedUploadTypes' );
00596         $aAllowedUploadTypes = array_map( "strtolower", $aAllowedUploadTypes );
00597 
00598         if ( !in_array( strtolower( $sExt ), $aAllowedUploadTypes ) ) {
00599             throw oxNew( "oxException", 'EXCEPTION_NOTALLOWEDTYPE' );
00600         }
00601 
00602         $sFileName = $this->_getUniqueFileName( $sBasePath . $sUploadPath, $sFileName, $sExt );
00603 
00604         if ( $this->_moveImage( $aFileInfo['tmp_name'], $sBasePath . $sUploadPath . "/" . $sFileName ) ) {
00605             return $sFileName ;
00606         } else {
00607             return false;
00608         }
00609     }
00610 
00623     protected function _getUniqueFileName( $sFilePath, $sFileName, $sFileExt, $sSufix = "", $blUnique = true )
00624     {
00625         $sFilePath     = $this->normalizeDir( $sFilePath );
00626         $iFileCounter  = 0;
00627         $sTempFileName = $sFileName;
00628         $oStr = getStr();
00629 
00630         //file exists ?
00631         while ( $blUnique && file_exists( $sFilePath . "/" . $sFileName . $sSufix . "." . $sFileExt ) ) {
00632             $iFileCounter++;
00633 
00634             //removing "(any digit)" from file name end
00635             $sTempFileName = $oStr->preg_replace("/\(".$iFileCounter."\)/", "", $sTempFileName );
00636 
00637             $sFileName = $sTempFileName . "($iFileCounter)";
00638         }
00639 
00640         return $sFileName . $sSufix . "." . $sFileExt;
00641     }
00642 
00651     public function getImageDirByType( $sType, $blGenerated = false )
00652     {
00653         $sFolder = array_key_exists( $sType, $this->_aTypeToPath ) ? $this->_aTypeToPath[ $sType ] : '0';
00654         $sDir = $this->normalizeDir( $sFolder );
00655 
00656         if ($blGenerated === true) {
00657             $sDir = str_replace('master/', 'generated/', $sDir);
00658         }
00659 
00660         return $sDir;
00661     }
00662 
00670     function translateError( $iError )
00671     {
00672         $message = '';
00673         // Translate only if translation exist
00674         if ( $iError > 0 && $iError < 9 && 5 !== $iError ) {
00675             $message = 'EXCEPTION_FILEUPLOADERROR_'.( (int) $iError );
00676         }
00677 
00678         return $message;
00679     }
00680 
00681 }