oxsysrequirements.php

Go to the documentation of this file.
00001 <?php
00002 
00006 class oxSysRequirements
00007 {
00013     protected $_aRequiredModules = null;
00014 
00020     protected $_blSysReqStatus = null;
00021 
00027     protected $_aException = array( 'OXDELIVERY'   => 'OXDELTYPE',
00028                                     'OXSELECTLIST' => 'OXIDENT');
00029 
00035     protected $_aColumns = array( 'OXID',
00036                                   'OXOBJECTID',
00037                                   'OXARTICLENID',
00038                                   'OXACTIONID',
00039                                   'OXARTID',
00040                                   'OXUSERID',
00041                                   'OXADDRESSUSERID',
00042                                   'OXCOUNTRYID',
00043                                   'OXSESSID',
00044                                   'OXITMID',
00045                                   'OXPARENTID',
00046                                   'OXAMITEMID',
00047                                   'OXAMTASKID',
00048                                   'OXVENDORID',
00049                                   'OXMANUFACTURERID',
00050                                   'OXROOTID',
00051                                   'OXATTRID',
00052                                   'OXCATID',
00053                                   'OXDELID',
00054                                   'OXDELSETID',
00055                                   'OXITMARTID',
00056                                   'OXFIELDID',
00057                                   'OXROLEID',
00058                                   'OXCNID',
00059                                   'OXANID',
00060                                   'OXARTICLENID',
00061                                   'OXCATNID',
00062                                   'OXDELIVERYID',
00063                                   'OXDISCOUNTID',
00064                                   'OXGROUPSID',
00065                                   'OXLISTID',
00066                                   'OXPAYMENTID',
00067                                   'OXDELTYPE',
00068                                   'OXROLEID',
00069                                   'OXSELNID',
00070                                   'OXBILLCOUNTRYID',
00071                                   'OXDELCOUNTRYID',
00072                                   'OXPAYMENTID',
00073                                   'OXCARDID',
00074                                   'OXPAYID',
00075                                   'OXIDENT',
00076                                   'OXDEFCAT',
00077                                   'OXBASKETID',
00078                                   'OXPAYMENTSID',
00079                                   'OXORDERID',
00080                                   'OXVOUCHERSERIEID');
00081 
00087     protected $_sReqInfoUrl = "http://www.oxidforge.org/wiki/Installation";
00088 
00094     protected $_aInfoMap    = array( "php_version"        => "PHP_version_at_least_5.2.0",
00095                                      "lib_xml2"           => "LIB_XML2",
00096                                      "php_xml"            => "DOM",
00097                                      "j_son"              => "JSON",
00098                                      "i_conv"             => "ICONV",
00099                                      "tokenizer"          => "Tokenizer",
00100                                      "mysql_connect"      => "MySQL_module_for_MySQL_5",
00101                                      "gd_info"            => "GDlib_v2_.5Bv1.5D_incl._JPEG_support",
00102                                      "mb_string"          => "mbstring",
00103                                      "bc_math"            => "BCMath",
00104                                      "allow_url_fopen"    => "allow_url_fopen_or_fsockopen_to_port_80",
00105                                      "php4_compat"        => "Zend_compatibility_mode_must_be_off",
00106                                      "request_uri"        => "REQUEST_URI_set",
00107                                      "ini_set"            => "ini_set_allowed",
00108                                      "register_globals"   => "register_globals_must_be_off",
00109                                      "memory_limit"       => "PHP_Memory_limit_.28min._14MB.2C_30MB_recommended.29",
00110                                      "unicode_support"    => "UTF-8_support",
00111                                      "mod_rewrite"        => "apache_mod_rewrite_module",
00112                                      "server_permissions" => "Files_.26_Folder_Permission_Setup",
00113                                      "zend_optimizer"     => "Zend_Optimizer"
00114                                      // "zend_platform_or_server"
00115                                       );
00116 
00122     public function __construct()
00123     {
00124     }
00125 
00131     public function getRequiredModules()
00132     {
00133         if ( $this->_aRequiredModules == null ) {
00134             $aRequiredPHPExtensions = array(
00135                                           'php_version',
00136                                           'lib_xml2',
00137                                           'php_xml',
00138                                           'j_son',
00139                                           'i_conv',
00140                                           'tokenizer',
00141                                           'mysql_connect',
00142                                           'gd_info',
00143                                           'mb_string',
00144                                           'curl',
00145                                           'bc_math',
00146                                       );
00147 
00148             $aRequiredPHPConfigs = array(
00149                                        'allow_url_fopen',
00150                                        'php4_compat',
00151                                        'request_uri',
00152                                        'ini_set',
00153                                        'register_globals',
00154                                        'memory_limit',
00155                                        'unicode_support'
00156                                    );
00157 
00158             $aRequiredServerConfigs = array(
00159                                           'mod_rewrite',
00160                                           'server_permissions'
00161                                       );
00162 
00163 
00164             if ( isAdmin() ) {
00165                 $aRequiredServerConfigs[] = 'mysql_version';
00166             }
00167             $this->_aRequiredModules = array_fill_keys( $aRequiredPHPExtensions, 'php_extennsions' ) +
00168                                        array_fill_keys( $aRequiredPHPConfigs, 'php_config' ) +
00169                                        array_fill_keys( $aRequiredServerConfigs, 'server_config' );
00170         }
00171         return $this->_aRequiredModules;
00172     }
00173 
00179     public function checkCurl()
00180     {
00181         return extension_loaded( 'curl' ) ? 2 : 1;
00182     }
00183 
00189     public function checkMbString()
00190     {
00191         return extension_loaded( 'mbstring' ) ? 2 : 1;
00192     }
00193 
00202     public function checkServerPermissions( $sPath = null, $iMinPerm = 777 )
00203     {
00204         $sVerPrefix = '';
00205 
00206         clearstatcache();
00207         $sPath = $sPath ? $sPath : getShopBasePath();
00208 
00209         // special config file check
00210         $sFullPath = $sPath . "config.inc.php";
00211         if ( !is_readable( $sFullPath ) ||
00212              ( isAdmin() && is_writable( $sFullPath ) ) ||
00213              ( !isAdmin() && !is_writable( $sFullPath ) )
00214            ) {
00215             return 0;
00216         }
00217 
00218         $sTheme = 'basic';
00219         $sTmp = "$sPath/tmp$sVerPrefix/";
00220         if (class_exists('oxConfig')) {
00221             $sTheme  = oxConfig::getInstance()->getConfigParam('sTheme');
00222             $sCfgTmp = oxConfig::getInstance()->getConfigParam('sCompileDir');
00223             if (strpos($sCfgTmp, '<sCompileDir_') === false) {
00224                 $sTmp = $sCfgTmp;
00225             }
00226         }
00227 
00228         $aPathsToCheck = array(
00229                             $sPath."out/pictures{$sVerPrefix}/",
00230                             $sPath."out/media/",
00231                             $sPath."out/$sTheme/src/",
00232                             $sPath."log/",
00233                             $sTmp
00234                             );
00235         $iModStat = 2;
00236         $sPathToCheck = reset( $aPathsToCheck );
00237         while ( $sPathToCheck ) {
00238             // missing file/folder?
00239             if ( !file_exists( $sPathToCheck ) ) {
00240                 $iModStat = 0;
00241                 break;
00242             }
00243 
00244             if ( is_dir( $sPathToCheck ) ) {
00245                 // adding subfolders
00246                 $aSubF = glob( $sPathToCheck."*", GLOB_ONLYDIR );
00247                 if (is_array($aSubF)) {
00248                     foreach ( $aSubF as $sNewFolder ) {
00249                         $aPathsToCheck[] = $sNewFolder . "/";
00250                     }
00251                 }
00252             }
00253 
00254             // testing if file permissions >= $iMinPerm
00255             //if ( ( (int) substr( decoct( fileperms( $sFullPath ) ), 2 ) ) < $iMinPerm ) {
00256             if ( !is_readable( $sPathToCheck ) || !is_writable( $sPathToCheck ) ) {
00257                 $iModStat = 0;
00258                 break;
00259             }
00260 
00261             $sPathToCheck = next( $aPathsToCheck );
00262         }
00263 
00264         return $iModStat;
00265     }
00266 
00272     public function checkModRewrite()
00273     {
00274         $iModStat = null;
00275         $sHost   = $_SERVER['HTTP_HOST'];
00276         $sScript = $_SERVER['SCRIPT_NAME'];
00277         if ( $sScript && $rFp = @fsockopen( $sHost, 80, $iErrNo, $sErrStr, 10 ) ) {
00278             if ( isAdmin() ) {
00279                 $sScript = oxConfig::getInstance()->getConfigParam( 'sShopURL' ).'oxseo.php?mod_rewrite_module_is=off';
00280             } else {
00281                 $sScript = str_replace( basename( $sScript ), '../oxseo.php?mod_rewrite_module_is=off', $sScript );
00282             }
00283 
00284             $sReq  = "POST $sScript HTTP/1.1\r\n";
00285             $sReq .= "Host: $sHost\r\n";
00286             $sReq .= "User-Agent: oxid setup\r\n";
00287             $sReq .= "Content-Type: application/x-www-form-urlencoded\r\n";
00288             $sReq .= "Content-Length: 0\r\n"; // empty post
00289             $sReq .= "Connection: close\r\n\r\n";
00290 
00291             $sOut = '';
00292             fwrite( $rFp, $sReq );
00293             while ( !feof( $rFp ) ) {
00294                 $sOut .= fgets( $rFp, 100 );
00295             }
00296             fclose( $rFp );
00297 
00298             $iModStat = ( strpos( $sOut, 'mod_rewrite_on' ) !== false ) ? 2 : 0;
00299         } else {
00300             if ( function_exists( 'apache_get_modules' ) ) {
00301                 // it does not assure that mod_rewrite is enabled on current host, so setting 1
00302                 $iModStat = in_array( 'mod_rewrite', apache_get_modules() ) ? 1 : 0;
00303             } else {
00304                 $iModStat = -1;
00305             }
00306         }
00307         return $iModStat;
00308     }
00309 
00315     public function checkAllowUrlFopen()
00316     {
00317         $iModStat = @ini_get('allow_url_fopen');
00318         $iModStat = ( $iModStat && strcasecmp( '1', $iModStat ) ) ? 2 : 1;
00319         if ( $iModStat == 1 ) {
00320             $iErrNo  = 0;
00321             $sErrStr = '';
00322             if ( $oRes = @fsockopen( 'www.example.com', 80, $iErrNo, $sErrStr, 10 ) ) {
00323                 $iModStat = 2;
00324                 fclose( $oRes );
00325             }
00326         }
00327         $iModStat = ( !$iModStat ) ? 1 : $iModStat;
00328         return $iModStat;
00329     }
00330 
00337     public function checkPhp4Compat()
00338     {
00339         $sZendStatus = ( strtolower( (string) @ini_get( 'zend.ze1_compatibility_mode' ) ) );
00340         return in_array( $sZendStatus, array( 'on', '1' ) ) ? 0 : 2;
00341     }
00342 
00349     public function checkPhpVersion()
00350     {
00351         $iModStat = ( version_compare( PHP_VERSION, '5.1', '>' ) ) ? 1 : 0;
00352         $iModStat = ( $iModStat == 0 ) ? $iModStat : ( version_compare( PHP_VERSION, '5.2', '>=' ) ? 2 : 1 );
00353         return $iModStat;
00354     }
00355 
00361     public function checkRequestUri()
00362     {
00363         return ( isset( $_SERVER['REQUEST_URI'] ) || isset( $_SERVER['SCRIPT_URI'] ) ) ? 2 : 0;
00364     }
00365 
00371     public function checkLibXml2()
00372     {
00373         return class_exists( 'DOMDocument' ) ? 2 : 0;
00374     }
00375 
00381     public function checkPhpXml()
00382     {
00383         return class_exists( 'DOMDocument' ) ? 2 : 0;
00384     }
00385 
00391     public function checkJSon()
00392     {
00393         return extension_loaded( 'json' ) ? 2 : 0;
00394     }
00395 
00401     public function checkIConv()
00402     {
00403         return extension_loaded( 'iconv' ) ? 2 : 0;
00404     }
00405 
00411     public function checkTokenizer()
00412     {
00413         return extension_loaded( 'tokenizer' ) ? 2 : 0;
00414     }
00415 
00421     public function checkBcMath()
00422     {
00423         return extension_loaded( 'bcmath' ) ? 2 : 1;
00424     }
00425 
00431     public function checkMysqlConnect()
00432     {
00433         // MySQL module for MySQL5
00434         $iModStat = ( extension_loaded( 'mysql' ) || extension_loaded( 'mysqli' ) || extension_loaded( 'pdo_mysql' ) ) ? 2 : 0;
00435         // client version must be >=5
00436         if ( $iModStat ) {
00437             $sClientVersion = mysql_get_client_info();
00438             if (version_compare( $sClientVersion, '5', '<' )) {
00439                 $iModStat = 1;
00440                 if (version_compare( $sClientVersion, '4', '<' )) {
00441                     $iModStat = 0;
00442                 }
00443             } elseif (version_compare($sClientVersion, '5.0.36', '>=') && version_compare($sClientVersion, '5.0.38', '<')) {
00444                 // mantis#0001003: Problems with MySQL version 5.0.37
00445                 $iModStat = 0;
00446             } elseif (version_compare($sClientVersion, '5.0.40', '>') && version_compare($sClientVersion, '5.0.42', '<')) {
00447                 // mantis#0001877: Exclude MySQL 5.0.41 from system requirements as not fitting
00448                 $iModStat = 0;
00449             }
00450             if (strpos($sClientVersion, 'mysqlnd') !== false) {
00451                 // PHP 5.3 includes new mysqlnd extension
00452                 $iModStat = 2;
00453             }
00454         }
00455         return $iModStat;
00456     }
00457 
00465     public function checkMysqlVersion( $sVersion = null )
00466     {
00467         if ( $sVersion === null ) {
00468             $aRez = oxDb::getDb()->getAll( "SHOW VARIABLES LIKE 'version'" );
00469             foreach ( $aRez as $aRecord ) {
00470                 $sVersion = $aRecord[1];
00471                 break;
00472             }
00473         }
00474 
00475         $iModStat = 0;
00476         if ( version_compare( $sVersion, '5', '>=' ) && version_compare( $sVersion, '5.0.37', '<>' ) ) {
00477             $iModStat = 2;
00478         }
00479 
00480         return $iModStat;
00481     }
00482 
00488     public function checkGdInfo()
00489     {
00490         $iModStat = extension_loaded( 'gd' ) ? 1 : 0;
00491         $iModStat = function_exists( 'imagecreatetruecolor' ) ? 2 : $iModStat;
00492         $iModStat = function_exists( 'imagecreatefromjpeg' ) ? $iModStat : 0;
00493         return $iModStat;
00494     }
00495 
00501     public function checkIniSet()
00502     {
00503         return ( @ini_set('session.name', 'sid' ) !== false ) ? 2 : 0;
00504     }
00505 
00511     public function checkRegisterGlobals()
00512     {
00513         $sGlobStatus = ( strtolower( (string) @ini_get( 'register_globals' ) ) );
00514         return in_array( $sGlobStatus, array( 'on', '1' ) ) ? 0 : 2;
00515     }
00516 
00522     public function checkMemoryLimit()
00523     {
00524         if ( $sMemLimit = @ini_get('memory_limit') ) {
00525                 // CE - PE at least to 14 MB. We recomend a memory_limit of 30MB.
00526                 $sDefLimit = '14M';
00527                 $sRecLimit = '30M';
00528 
00529 
00530             $iMemLimit = $this->_getBytes( $sMemLimit );
00531             $iModStat = ( $iMemLimit >= $this->_getBytes( $sDefLimit ) ) ? 1 : 0;
00532             $iModStat = $iModStat ? ( ( $iMemLimit >= $this->_getBytes( $sRecLimit ) ) ? 2 : $iModStat ) : $iModStat;
00533 
00534         } else {
00535             $iModStat = -1;
00536         }
00537         return $iModStat;
00538     }
00539 
00545     public function checkZendOptimizer()
00546     {
00547         $iMinStat = 0;
00548         $iModStat = (extension_loaded( 'Zend Optimizer' ) || (function_exists('zend_loader_enabled') && zend_loader_enabled())) ? 2 : $iMinStat;
00549         $sHost   = $_SERVER['HTTP_HOST'];
00550         $sScript = $_SERVER['SCRIPT_NAME'];
00551         if ( $iModStat > $iMinStat && $sScript && $rFp = @fsockopen( $sHost, 80, $iErrNo, $sErrStr, 10 ) ) {
00552             $sScript = str_replace( basename($sScript), '../admin/index.php', $sScript );
00553 
00554             $sReq  = "POST $sScript HTTP/1.1\r\n";
00555             $sReq .= "Host: $sHost\r\n";
00556             $sReq .= "User-Agent: oxid setup\r\n";
00557             $sReq .= "Content-Type: application/x-www-form-urlencoded\r\n";
00558             $sReq .= "Content-Length: 0\r\n"; // empty post
00559             $sReq .= "Connection: close\r\n\r\n";
00560 
00561             $sOut = '';
00562             fwrite( $rFp, $sReq );
00563             while ( !feof( $rFp ) ) {
00564                 $sOut .= fgets( $rFp, 100 );
00565             }
00566 
00567             $iModStat = ( strpos( $sOut, 'Zend Optimizer not installed' ) !== false ) ? $iMinStat : 2;
00568             fclose( $rFp );
00569         }
00570         if ( $iModStat > $iMinStat && $sScript && $rFp = @fsockopen( $sHost, 80, $iErrNo, $sErrStr, 10 ) ) {
00571             $sScript = str_replace( basename($sScript), '../index.php', $sScript );
00572 
00573             $sReq  = "POST $sScript HTTP/1.1\r\n";
00574             $sReq .= "Host: $sHost\r\n";
00575             $sReq .= "User-Agent: oxid setup\r\n";
00576             $sReq .= "Content-Type: application/x-www-form-urlencoded\r\n";
00577             $sReq .= "Content-Length: 0\r\n"; // empty post
00578             $sReq .= "Connection: close\r\n\r\n";
00579 
00580             $sOut = '';
00581             fwrite( $rFp, $sReq );
00582             while ( !feof( $rFp ) ) {
00583                 $sOut .= fgets( $rFp, 100 );
00584             }
00585             $iModStat = ( strpos( $sOut, 'Zend Optimizer not installed' ) !== false ) ? $iMinStat : 2;
00586             fclose( $rFp );
00587         }
00588         return $iModStat;
00589     }
00590 
00596     public function checkZendPlatformOrServer()
00597     {
00598         if (function_exists( 'output_cache_get' )) {
00599             return 2;
00600         }
00601         if (function_exists( 'zend_disk_cache_fetch' )) {
00602             return 2;
00603         }
00604         if (function_exists( 'zend_shm_cache_fetch' )) {
00605             return 2;
00606         }
00607         return 1;
00608     }
00609 
00615     protected function _getAdditionalCheck()
00616     {
00617         $sSelect = '';
00618         foreach ( $this->_aException as $sTable => $sColumn ) {
00619             $sSelect .= 'and ( t.TABLE_NAME != "'.$sTable.'" and c.COLUMN_NAME != "'.$sColumn.'" ) ';
00620         }
00621         return $sSelect;
00622     }
00623 
00629     public function checkCollation()
00630     {
00631         $myConfig = oxConfig::getInstance();
00632 
00633         $aCollations = array();
00634         $sCollation = '';
00635 
00636         $sSelect = 'select t.TABLE_NAME, c.COLUMN_NAME, c.COLLATION_NAME from INFORMATION_SCHEMA.tables t ' .
00637                    'LEFT JOIN INFORMATION_SCHEMA.columns c ON t.TABLE_NAME = c.TABLE_NAME  ' .
00638                    'where t.TABLE_SCHEMA = "'.$myConfig->getConfigParam( 'dbName' ).'" ' .
00639                    'and c.TABLE_SCHEMA = "'.$myConfig->getConfigParam( 'dbName' ).'" ' .
00640                    'and c.COLUMN_NAME in ("'.implode('", "', $this->_aColumns).'") ' . $this->_getAdditionalCheck() .
00641                    ' ORDER BY (t.TABLE_NAME = "oxarticles") DESC';
00642         $aRez = oxDb::getDb()->getAll($sSelect);
00643         foreach ( $aRez as $aRetTable ) {
00644             if ( !$sCollation ) {
00645                 $sCollation = $aRetTable[2];
00646             } else {
00647                 if ( $aRetTable[2] && $sCollation != $aRetTable[2]) {
00648                     $aCollations[$aRetTable[0]][$aRetTable[1]] = $aRetTable[2];
00649                 }
00650             }
00651         }
00652 
00653         if ( $this->_blSysReqStatus === null ) {
00654             $this->_blSysReqStatus = true;
00655         }
00656         if ( count($aCollations) > 0 ) {
00657             $this->_blSysReqStatus = false;
00658         }
00659         return $aCollations;
00660     }
00661 
00667     public function checkDatabaseCluster()
00668     {
00669         return 2;
00670     }
00671 
00677     public function checkUnicodeSupport()
00678     {
00679         return (@preg_match('/\pL/u', 'a') == 1) ? 2 : 1;
00680     }
00681 
00687     public function getSysReqStatus()
00688     {
00689         if ( $this->_blSysReqStatus == null ) {
00690             $this->_blSysReqStatus = true;
00691             $this->getSystemInfo();
00692             $this->checkCollation();
00693         }
00694         return $this->_blSysReqStatus;
00695     }
00696 
00711     public function getSystemInfo()
00712     {
00713         $aSysInfo = array();
00714         $aRequiredModules = $this->getRequiredModules();
00715         $this->_blSysReqStatus = true;
00716         foreach ( $aRequiredModules as $sModule => $sGroup ) {
00717             if ( isset($aSysInfo[$sGroup]) && !$aSysInfo[$sGroup] ) {
00718                 $aSysInfo[$sGroup] = array();
00719             }
00720             $iModuleState = $this->getModuleInfo( $sModule );
00721             $aSysInfo[$sGroup][$sModule] = $iModuleState;
00722             $this->_blSysReqStatus = $this->_blSysReqStatus && ( bool ) abs( $iModuleState );
00723         }
00724         return $aSysInfo;
00725     }
00726 
00734     public function getModuleInfo( $sModule = null )
00735     {
00736         if ( $sModule ) {
00737             $iModStat = null;
00738             $sCheckFunction = "check".str_replace(" ", "", ucwords(str_replace("_", " ", $sModule)));
00739             $iModStat = $this->$sCheckFunction();
00740 
00741             return $iModStat;
00742         }
00743     }
00744 
00752     public function getReqInfoUrl( $sIdent)
00753     {
00754         $sUrl = $this->_sReqInfoUrl;
00755         $aInfoMap = $this->_aInfoMap;
00756 
00757         // only known will be anchored
00758         if ( isset( $aInfoMap[$sIdent] ) ) {
00759             $sUrl .= "#".$aInfoMap[$sIdent];
00760         }
00761 
00762         return $sUrl;
00763     }
00764 
00772     protected function _getBytes( $sBytes )
00773     {
00774         $sBytes = trim( $sBytes );
00775         $sLast = strtolower($sBytes[strlen($sBytes)-1]);
00776         switch( $sLast ) {
00777             // The 'G' modifier is available since PHP 5.1.0
00778             case 'g':
00779                 $sBytes *= 1024;
00780             case 'm':
00781                 $sBytes *= 1024;
00782             case 'k':
00783                 $sBytes *= 1024;
00784                 break;
00785         }
00786 
00787         return $sBytes;
00788     }
00789 }