OXID eShop CE  4.8.12
 All Classes Files Functions Variables Pages
oxutilsfile.php
Go to the documentation of this file.
1 <?php
2 
6 class oxUtilsFile extends oxSuperCfg
7 {
13  const PROMO_PICTURE_DIR = 'promo';
14 
20  private static $_instance = null;
21 
27  protected $_iMaxPicImgCount = 12;
28 
34  protected $_iMaxZoomImgCount = 12;
35 
41  protected $_aTypeToPath = array( 'TC' => 'master/category/thumb',
42  'CICO' => 'master/category/icon',
43  'PICO' => 'master/category/promo_icon',
44  'MICO' => 'master/manufacturer/icon',
45  'VICO' => 'master/vendor/icon',
46  'PROMO'=> self::PROMO_PICTURE_DIR,
47  'ICO' => 'master/product/icon',
48  'TH' => 'master/product/thumb',
49  'M1' => 'master/product/1',
50  'M2' => 'master/product/2',
51  'M3' => 'master/product/3',
52  'M4' => 'master/product/4',
53  'M5' => 'master/product/5',
54  'M6' => 'master/product/6',
55  'M7' => 'master/product/7',
56  'M8' => 'master/product/8',
57  'M9' => 'master/product/9',
58  'M10' => 'master/product/10',
59  'M11' => 'master/product/11',
60  'M12' => 'master/product/12',
61  //
62  'P1' => '1',
63  'P2' => '2',
64  'P3' => '3',
65  'P4' => '4',
66  'P5' => '5',
67  'P6' => '6',
68  'P7' => '7',
69  'P8' => '8',
70  'P9' => '9',
71  'P10' => '10',
72  'P11' => '11',
73  'P12' => '12',
74  'Z1' => 'z1',
75  'Z2' => 'z2',
76  'Z3' => 'z3',
77  'Z4' => 'z4',
78  'Z5' => 'z5',
79  'Z6' => 'z6',
80  'Z7' => 'z7',
81  'Z8' => 'z8',
82  'Z9' => 'z9',
83  'Z10' => 'z10',
84  'Z11' => 'z11',
85  'Z12' => 'z12',
86  //
87  'WP' => 'master/wrapping',
88  'FL' => 'media',
89  );
90 
96  protected $_aBadFiles = array( 'php', 'php3', 'php4', 'php5', 'phps', 'php6', 'jsp', 'cgi', 'cmf', 'exe' );
97 
103  protected $_aAllowedFiles = array( 'gif', 'jpg', 'jpeg', 'png', 'pdf' );
104 
110  protected $_iNewFilesCounter = 0;
111 
119  public static function getInstance()
120  {
121  return oxRegistry::get("oxUtilsFile");
122  }
123 
129  public function __construct()
130  {
131  $myConfig = $this->getConfig();
132 
133  if ( $iPicCount = $myConfig->getConfigParam( 'iPicCount' ) ) {
134  $this->_iMaxPicImgCount = $iPicCount;
135  }
136 
137  $this->_iMaxZoomImgCount = $this->_iMaxPicImgCount;
138  }
139 
145  public function getNewFilesCounter()
146  {
148  }
149 
157  protected function _setNewFilesCounter( $iNewFilesCounter )
158  {
159  $this->_iNewFilesCounter = (int) $iNewFilesCounter;
160  }
161 
169  public function normalizeDir( $sDir )
170  {
171  if ( isset($sDir) && $sDir != "" && substr($sDir, -1) !== '/' ) {
172  $sDir .= "/";
173  }
174 
175  return $sDir;
176  }
177 
186  public function copyDir( $sSourceDir, $sTargetDir )
187  {
188  $oStr = getStr();
189  $handle = opendir( $sSourceDir );
190  while ( false !== ( $file = readdir( $handle ) ) ) {
191  if ( $file != '.' && $file != '..' ) {
192  if ( is_dir( $sSourceDir.'/'.$file ) ) {
193 
194  // recursive
195  $sNewSourceDir = $sSourceDir.'/'.$file;
196  $sNewTargetDir = $sTargetDir.'/'.$file;
197  if ( strcasecmp( $file, 'CVS' ) && strcasecmp( $file, '.svn' )) {
198  @mkdir( $sNewTargetDir, 0777 );
199  $this->copyDir( $sNewSourceDir, $sNewTargetDir );
200  }
201  } else {
202  $sSourceFile = $sSourceDir.'/'.$file;
203  $sTargetFile = $sTargetDir.'/'.$file;
204 
205  //do not copy files within dyn_images
206  if ( !$oStr->strstr( $sSourceDir, 'dyn_images' ) || $file == 'nopic.jpg' || $file == 'nopic_ico.jpg' ) {
207  @copy( $sSourceFile, $sTargetFile );
208  }
209  }
210  }
211  }
212  closedir($handle);
213  }
214 
222  public function deleteDir( $sSourceDir )
223  {
224  if ( is_dir( $sSourceDir ) ) {
225  if ( $oDir = dir( $sSourceDir ) ) {
226 
227  while ( false !== $sFile = $oDir->read() ) {
228  if ( $sFile == '.' || $sFile == '..' ) {
229  continue;
230  }
231 
232  if ( !$this->deleteDir( $oDir->path . DIRECTORY_SEPARATOR . $sFile ) ) {
233  $oDir->close();
234  return false;
235  }
236  }
237 
238  $oDir->close();
239  return rmdir( $sSourceDir );
240  }
241  } elseif ( file_exists( $sSourceDir ) ) {
242  return unlink ( $sSourceDir );
243  }
244  }
245 
253  public function readRemoteFileAsString( $sPath )
254  {
255  $sRet = '';
256  $hFile = @fopen( $sPath, 'r' );
257  if ( $hFile ) {
258  socket_set_timeout( $hFile, 2 );
259  while ( !feof( $hFile ) ) {
260  $sLine = fgets( $hFile, 4096 );
261  $sRet .= $sLine;
262  }
263  fclose( $hFile );
264  }
265 
266  return $sRet;
267  }
268 
280  protected function _prepareImageName( $sValue, $sType, $blDemo, $sImagePath, $blUnique = true )
281  {
282  if ( $sValue ) {
283  // add type to name
284  $aFilename = explode( ".", $sValue );
285 
286  $sFileType = trim( $aFilename[count( $aFilename )-1] );
287 
288  if ( isset( $sFileType ) ) {
289 
290  $oStr = getStr();
291 
292  // unallowed files ?
293  if ( in_array( $sFileType, $this->_aBadFiles ) || ( $blDemo && !in_array( $sFileType, $this->_aAllowedFiles ) ) ) {
294  oxRegistry::getUtils()->showMessageAndExit( "We don't play this game, go away" );
295  }
296 
297  // removing file type
298  if ( count( $aFilename ) > 0 ) {
299  unset( $aFilename[count( $aFilename )-1] );
300  }
301 
302  $sFName = '';
303  if ( isset( $aFilename[0] ) ) {
304  $sFName = $oStr->preg_replace( '/[^a-zA-Z0-9()_\.-]/', '', implode( '.', $aFilename ) );
305  }
306 
307  $sValue = $this->_getUniqueFileName( $sImagePath, "{$sFName}", $sFileType, "", $blUnique );
308  }
309  }
310  return $sValue;
311  }
312 
320  protected function _getImagePath( $sType )
321  {
322  $sFolder = array_key_exists( $sType, $this->_aTypeToPath ) ? $this->_aTypeToPath[ $sType ] : '0';
323  $sPath = $this->normalizeDir( $this->getConfig()->getPictureDir(false) ) . "{$sFolder}/";
324  return $sPath;
325  }
326 
337  protected function _getImageSize( $sImgType, $iImgNum, $sImgConf )
338  {
339  $myConfig = $this->getConfig();
340  $sSize = false;
341 
342  switch ( $sImgConf ) {
343  case 'aDetailImageSizes':
344  $aDetailImageSizes = $myConfig->getConfigParam( $sImgConf );
345  $sSize = $myConfig->getConfigParam( 'sDetailImageSize' );
346  if ( isset( $aDetailImageSizes['oxpic'.$iImgNum] ) ) {
347  $sSize = $aDetailImageSizes['oxpic'.$iImgNum];
348  }
349  break;
350  default:
351  $sSize = $myConfig->getConfigParam( $sImgConf );
352  break;
353  }
354  if ( $sSize ) {
355  return explode( '*', $sSize );
356  }
357  }
358 
367  protected function _copyFile( $sSource, $sTarget )
368  {
369  $blDone = false;
370 
371  if ( $sSource === $sTarget ) {
372  $blDone = true;
373  } else {
374  $blDone = copy( $sSource, $sTarget );
375  }
376 
377  if ( $blDone ) {
378  $blDone = @chmod( $sTarget, 0644 );
379  }
380 
381  return $blDone;
382  }
383 
392  protected function _moveImage( $sSource, $sTarget )
393  {
394  $blDone = false;
395  if ( !is_dir( dirname( $sTarget ) ) ) {
396  mkdir(dirname($sTarget), 0744, true);
397  }
398  if ( $sSource === $sTarget ) {
399  $blDone = true;
400  } else {
401  $blDone = move_uploaded_file( $sSource, $sTarget );
402  }
403 
404  if ( $blDone ) {
405  $blDone = @chmod( $sTarget, 0644 );
406  }
407 
408  return $blDone;
409  }
410 
422  public function processFiles( $oObject = null, $aFiles = array(), $blUseMasterImage = false, $blUnique = true )
423  {
424  $aFiles = $aFiles ? $aFiles : $_FILES;
425  if ( isset( $aFiles['myfile']['name'] ) ) {
426 
427  $oConfig = $this->getConfig();
428  $oStr = getStr();
429 
430  // A. protection for demoshops - strictly defining allowed file extensions
431  $blDemo = (bool) $oConfig->isDemoShop();
432 
433  // folder where images will be processed
434  $sTmpFolder = $oConfig->getConfigParam( "sCompileDir" );
435 
436  $iNewFilesCounter = 0;
437  $aSource = $aFiles['myfile']['tmp_name'];
438  $aError = $aFiles['myfile']['error'];
439  $sErrorsDescription = '';
440 
441  $oEx = oxNew( "oxExceptionToDisplay" );
442  // process all files
443  while ( list( $sKey, $sValue ) = each( $aFiles['myfile']['name'] ) ) {
444 
445  $sSource = $aSource[$sKey];
446  $iError = $aError[$sKey];
447  $aFiletype = explode( "@", $sKey );
448  $sKey = $aFiletype[1];
449  $sType = $aFiletype[0];
450 
451  $sValue = strtolower( $sValue );
452  $sImagePath = $this->_getImagePath( $sType );
453 
454  // Should translate error to user if file was uploaded
455  if ( UPLOAD_ERR_OK !== $iError && UPLOAD_ERR_NO_FILE !== $iError ) {
456  $sErrorsDescription = $this->translateError( $iError );
457  $oEx->setMessage( $sErrorsDescription );
458  oxRegistry::get("oxUtilsView")->addErrorToDisplay( $oEx, false );
459  }
460 
461  // checking file type and building final file name
462  if ( $sSource && ( $sValue = $this->_prepareImageName( $sValue, $sType, $blDemo, $sImagePath, $blUnique ) ) ) {
463  // moving to tmp folder for processing as safe mode or spec. open_basedir setup
464  // usually does not allow file modification in php's temp folder
465  $sProcessPath = $sTmpFolder . basename( $sSource );
466 
467  if ( $sProcessPath ) {
468 
469  if ( $blUseMasterImage ) {
470  //using master image as source, so only copying it to
471  $blMoved = $this->_copyFile( $sSource, $sImagePath . $sValue );
472  } else {
473  $blMoved = $this->_moveImage( $sSource, $sImagePath . $sValue );
474  }
475 
476  if ( $blMoved ) {
477  // New image successfully add.
478  $iNewFilesCounter++;
479  // assign the name
480  if ( $oObject && isset( $oObject->$sKey ) ) {
481  $oObject->{$sKey}->setValue( $sValue );
482  }
483  }
484  }
485  }
486  }
487 
488  $this->_setNewFilesCounter( $iNewFilesCounter );
489  }
490 
491  return $oObject;
492  }
493 
502  function checkFile( $sFile )
503  {
504  $aCheckCache = oxSession::getVar("checkcache");
505 
506  if ( isset( $aCheckCache[$sFile] ) ) {
507  return $aCheckCache[$sFile];
508  }
509 
510  $blRet = false;
511 
512  if (is_readable( $sFile)) {
513  $blRet = true;
514  } else {
515  // try again via socket
516  $blRet = $this->urlValidate( $sFile );
517  }
518 
519  $aCheckCache[$sFile] = $blRet;
520  oxSession::setVar( "checkcache", $aCheckCache );
521 
522  return $blRet;
523  }
524 
532  function urlValidate( $sLink )
533  {
534  $aUrlParts = @parse_url( $sLink );
535  $sHost = ( isset( $aUrlParts["host"] ) && $aUrlParts["host"] ) ? $aUrlParts["host"] : null;
536 
537  $blValid = false;
538  if ( $sHost ) {
539  $sDocumentPath = ( isset( $aUrlParts["path"] ) && $aUrlParts["path"] ) ? $aUrlParts["path"] : '/';
540  $sDocumentPath .= ( isset( $aUrlParts["query"] ) && $aUrlParts["query"] ) ? '?' . $aUrlParts["query"] : '';
541 
542  $sPort = ( isset( $aUrlParts["port"] ) && $aUrlParts["port"] ) ? $aUrlParts["port"] : '80';
543 
544  // Now (HTTP-)GET $documentpath at $sHost";
545  if ( ( $oConn = @fsockopen( $sHost, $sPort, $iErrNo, $sErrStr, 30 ) ) ) {
546  fwrite ( $oConn, "HEAD {$sDocumentPath} HTTP/1.0\r\nHost: {$sHost}\r\n\r\n" );
547  $sResponse = fgets( $oConn, 22 );
548  fclose( $oConn );
549 
550  if ( preg_match( "/200 OK/", $sResponse ) ) {
551  $blValid = true;
552  }
553  }
554  }
555 
556  return $blValid;
557  }
558 
569  public function processFile( $sFileName, $sUploadPath )
570  {
571  $aFileInfo = $_FILES[$sFileName];
572 
573  $sBasePath = $this->getConfig()->getConfigParam('sShopDir');
574 
575  //checking params
576  if ( !isset( $aFileInfo['name'] ) || !isset( $aFileInfo['tmp_name'] ) ) {
577  throw oxNew( "oxException", 'EXCEPTION_NOFILE' );
578  }
579 
580  //wrong chars in file name?
581  if ( !getStr()->preg_match('/^[\-_a-z0-9\.]+$/i', $aFileInfo['name'] ) ) {
582  throw oxNew( "oxException", 'EXCEPTION_FILENAMEINVALIDCHARS' );
583  }
584 
585  // error uploading file ?
586  if ( isset( $aFileInfo['error'] ) && $aFileInfo['error'] ) {
587  throw oxNew( "oxException", 'EXCEPTION_FILEUPLOADERROR_'.( (int) $aFileInfo['error'] ) );
588  }
589 
590  $aPathInfo = pathinfo($aFileInfo['name']);
591 
592  $sExt = $aPathInfo['extension'];
593  $sFileName = $aPathInfo['filename'];
594 
595  $aAllowedUploadTypes = (array) $this->getConfig()->getConfigParam( 'aAllowedUploadTypes' );
596  $aAllowedUploadTypes = array_map( "strtolower", $aAllowedUploadTypes );
597 
598  if ( !in_array( strtolower( $sExt ), $aAllowedUploadTypes ) ) {
599  throw oxNew( "oxException", 'EXCEPTION_NOTALLOWEDTYPE' );
600  }
601 
602  $sFileName = $this->_getUniqueFileName( $sBasePath . $sUploadPath, $sFileName, $sExt );
603 
604  if ( $this->_moveImage( $aFileInfo['tmp_name'], $sBasePath . $sUploadPath . "/" . $sFileName ) ) {
605  return $sFileName ;
606  } else {
607  return false;
608  }
609  }
610 
623  protected function _getUniqueFileName( $sFilePath, $sFileName, $sFileExt, $sSufix = "", $blUnique = true )
624  {
625  $sFilePath = $this->normalizeDir( $sFilePath );
626  $iFileCounter = 0;
627  $sTempFileName = $sFileName;
628  $oStr = getStr();
629 
630  //file exists ?
631  while ( $blUnique && file_exists( $sFilePath . "/" . $sFileName . $sSufix . "." . $sFileExt ) ) {
632  $iFileCounter++;
633 
634  //removing "(any digit)" from file name end
635  $sTempFileName = $oStr->preg_replace("/\(".$iFileCounter."\)/", "", $sTempFileName );
636 
637  $sFileName = $sTempFileName . "($iFileCounter)";
638  }
639 
640  return $sFileName . $sSufix . "." . $sFileExt;
641  }
642 
651  public function getImageDirByType( $sType, $blGenerated = false )
652  {
653  $sFolder = array_key_exists( $sType, $this->_aTypeToPath ) ? $this->_aTypeToPath[ $sType ] : '0';
654  $sDir = $this->normalizeDir( $sFolder );
655 
656  if ($blGenerated === true) {
657  $sDir = str_replace('master/', 'generated/', $sDir);
658  }
659 
660  return $sDir;
661  }
662 
670  function translateError( $iError )
671  {
672  $message = '';
673  // Translate only if translation exist
674  if ( $iError > 0 && $iError < 9 && 5 !== $iError ) {
675  $message = 'EXCEPTION_FILEUPLOADERROR_'.( (int) $iError );
676  }
677 
678  return $message;
679  }
680 
681 }