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                                      "open_ssl"           => "OpenSSL",
00098                                      "soap"               => "SOAP",
00099                                      "j_son"              => "JSON",
00100                                      "i_conv"             => "ICONV",
00101                                      "tokenizer"          => "Tokenizer",
00102                                      "mysql_connect"      => "MySQL_module_for_MySQL_5",
00103                                      "gd_info"            => "GDlib_v2_.5Bv1.5D_incl._JPEG_support",
00104                                      "mb_string"          => "mbstring",
00105                                      "bc_math"            => "BCMath",
00106                                      "allow_url_fopen"    => "allow_url_fopen_or_fsockopen_to_port_80",
00107                                      "php4_compat"        => "Zend_compatibility_mode_must_be_off",
00108                                      "request_uri"        => "REQUEST_URI_set",
00109                                      "ini_set"            => "ini_set_allowed",
00110                                      "register_globals"   => "register_globals_must_be_off",
00111                                      "memory_limit"       => "PHP_Memory_limit_.28min._14MB.2C_30MB_recommended.29",
00112                                      "unicode_support"    => "UTF-8_support",
00113                                      "mod_rewrite"        => "apache_mod_rewrite_module",
00114                                      "server_permissions" => "Files_.26_Folder_Permission_Setup",
00115                                      "zend_optimizer"     => "Zend_Optimizer"
00116                                      // "zend_platform_or_server"
00117                                       );
00118 
00124     public function __construct()
00125     {
00126     }
00127 
00133     public function getRequiredModules()
00134     {
00135         if ( $this->_aRequiredModules == null ) {
00136             $aRequiredPHPExtensions = array(
00137                                           'php_version',
00138                                           'lib_xml2',
00139                                           'php_xml',
00140                                           'j_son',
00141                                           'i_conv',
00142                                           'tokenizer',
00143                                           'mysql_connect',
00144                                           'gd_info',
00145                                           'mb_string',
00146                                           'curl',
00147                                           'bc_math',
00148                                           'open_ssl',
00149                                           'soap',
00150                                       );
00151 
00152             $aRequiredPHPConfigs = array(
00153                                        'allow_url_fopen',
00154                                        'php4_compat',
00155                                        'request_uri',
00156                                        'ini_set',
00157                                        'register_globals',
00158                                        'memory_limit',
00159                                        'unicode_support'
00160                                    );
00161 
00162             $aRequiredServerConfigs = array(
00163                                           'mod_rewrite',
00164                                           'server_permissions'
00165                                       );
00166 
00167 
00168             if ( isAdmin() ) {
00169                 $aRequiredServerConfigs[] = 'mysql_version';
00170             }
00171             $this->_aRequiredModules = array_fill_keys( $aRequiredPHPExtensions, 'php_extennsions' ) +
00172                                        array_fill_keys( $aRequiredPHPConfigs, 'php_config' ) +
00173                                        array_fill_keys( $aRequiredServerConfigs, 'server_config' );
00174         }
00175         return $this->_aRequiredModules;
00176     }
00177 
00183     public function checkCurl()
00184     {
00185         return extension_loaded( 'curl' ) ? 2 : 1;
00186     }
00187 
00193     public function checkMbString()
00194     {
00195         return extension_loaded( 'mbstring' ) ? 2 : 1;
00196     }
00197 
00206     public function checkServerPermissions( $sPath = null, $iMinPerm = 777 )
00207     {
00208         $sVerPrefix = '';
00209 
00210         clearstatcache();
00211         $sPath = $sPath ? $sPath : getShopBasePath();
00212 
00213         // special config file check
00214         $sFullPath = $sPath . "config.inc.php";
00215         if ( !is_readable( $sFullPath ) ||
00216              ( isAdmin() && is_writable( $sFullPath ) ) ||
00217              ( !isAdmin() && !is_writable( $sFullPath ) )
00218            ) {
00219             return 0;
00220         }
00221 
00222         $sTheme = 'basic';
00223         $sTmp = "$sPath/tmp$sVerPrefix/";
00224         if (class_exists('oxConfig')) {
00225             $sTheme  = oxConfig::getInstance()->getConfigParam('sTheme');
00226             $sCfgTmp = oxConfig::getInstance()->getConfigParam('sCompileDir');
00227             if (strpos($sCfgTmp, '<sCompileDir_') === false) {
00228                 $sTmp = $sCfgTmp;
00229             }
00230         }
00231 
00232         $aPathsToCheck = array(
00233                             $sPath."out/pictures{$sVerPrefix}/",
00234                             $sPath."out/media/",
00235                             $sPath."out/$sTheme/src/",
00236                             $sPath."log/",
00237                             $sTmp
00238                             );
00239         $iModStat = 2;
00240         $sPathToCheck = reset( $aPathsToCheck );
00241         while ( $sPathToCheck ) {
00242             // missing file/folder?
00243             if ( !file_exists( $sPathToCheck ) ) {
00244                 $iModStat = 0;
00245                 break;
00246             }
00247 
00248             if ( is_dir( $sPathToCheck ) ) {
00249                 // adding subfolders
00250                 $aSubF = glob( $sPathToCheck."*", GLOB_ONLYDIR );
00251                 if (is_array($aSubF)) {
00252                     foreach ( $aSubF as $sNewFolder ) {
00253                         $aPathsToCheck[] = $sNewFolder . "/";
00254                     }
00255                 }
00256             }
00257 
00258             // testing if file permissions >= $iMinPerm
00259             //if ( ( (int) substr( decoct( fileperms( $sFullPath ) ), 2 ) ) < $iMinPerm ) {
00260             if ( !is_readable( $sPathToCheck ) || !is_writable( $sPathToCheck ) ) {
00261                 $iModStat = 0;
00262                 break;
00263             }
00264 
00265             $sPathToCheck = next( $aPathsToCheck );
00266         }
00267 
00268         return $iModStat;
00269     }
00270 
00277     protected function _getShopHostInfoFromConfig()
00278     {
00279         $sShopURL = oxConfig::getInstance()->getConfigParam( 'sShopURL' );
00280         if (preg_match('#^(https?://)?([^/:]+)(:([0-9]+))?(/.*)?$#i', $sShopURL, $m)) {
00281             $sHost = $m[2];
00282             $iPort = (int)$m[4];
00283             $blSsl = (strtolower($m[1])=='https://');
00284             if (!$iPort) {
00285                 $iPort = $blSsl?443:80;
00286             }
00287             $sScript = rtrim($m[5], '/').'/';
00288             return array(
00289                     'host'=>$sHost,
00290                     'port'=>$iPort,
00291                     'dir'=>$sScript,
00292                     'ssl'=>$blSsl,
00293             );
00294         } else {
00295             return false;
00296         }
00297     }
00298 
00305     protected function _getShopHostInfoFromServerVars()
00306     {
00307         // got here from setup dir
00308         $sScript = $_SERVER['SCRIPT_NAME'];
00309         $iPort = (int) $_SERVER['SERVER_PORT'];
00310         $blSsl = (isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] == 'on'));
00311         if (!$iPort) {
00312             $iPort = $blSsl?443:80;
00313         }
00314         $sScript = rtrim(dirname(dirname( $sScript )), '/').'/';
00315         return array(
00316                     'host'=>$_SERVER['HTTP_HOST'],
00317                     'port'=>$iPort,
00318                     'dir'=>$sScript,
00319                     'ssl'=>$blSsl,
00320         );
00321     }
00322 
00328     protected function _getShopHostInfo()
00329     {
00330         if ( isAdmin() ) {
00331             return $this->_getShopHostInfoFromConfig();
00332         } else {
00333             return $this->_getShopHostInfoFromServerVars();
00334         }
00335     }
00336 
00342     public function checkModRewrite()
00343     {
00344         $iModStat = null;
00345         if ( ($aHostInfo = $this->_getShopHostInfo()) && $rFp = @fsockopen( ($aHostInfo['ssl']?'ssl://':'').$aHostInfo['host'], $aHostInfo['port'], $iErrNo, $sErrStr, 10 ) ) {
00346             $sReq  = "POST {$aHostInfo['dir']}oxseo.php?mod_rewrite_module_is=off HTTP/1.1\r\n";
00347             $sReq .= "Host: {$aHostInfo['host']}\r\n";
00348             $sReq .= "User-Agent: OXID eShop setup\r\n";
00349             $sReq .= "Content-Type: application/x-www-form-urlencoded\r\n";
00350             $sReq .= "Content-Length: 0\r\n"; // empty post
00351             $sReq .= "Connection: close\r\n\r\n";
00352 
00353             $sOut = '';
00354             fwrite( $rFp, $sReq );
00355             while ( !feof( $rFp ) ) {
00356                 $sOut .= fgets( $rFp, 100 );
00357             }
00358             fclose( $rFp );
00359 
00360             $iModStat = ( strpos( $sOut, 'mod_rewrite_on' ) !== false ) ? 2 : 0;
00361         } else {
00362             if ( function_exists( 'apache_get_modules' ) ) {
00363                 // it does not assure that mod_rewrite is enabled on current host, so setting 1
00364                 $iModStat = in_array( 'mod_rewrite', apache_get_modules() ) ? 1 : 0;
00365             } else {
00366                 $iModStat = -1;
00367             }
00368         }
00369         return $iModStat;
00370     }
00371 
00377     public function checkAllowUrlFopen()
00378     {
00379         $iModStat = @ini_get('allow_url_fopen');
00380         $iModStat = ( $iModStat && strcasecmp( '1', $iModStat ) ) ? 2 : 1;
00381         if ( $iModStat == 1 ) {
00382             $iErrNo  = 0;
00383             $sErrStr = '';
00384             if ( $oRes = @fsockopen( 'www.example.com', 80, $iErrNo, $sErrStr, 10 ) ) {
00385                 $iModStat = 2;
00386                 fclose( $oRes );
00387             }
00388         }
00389         $iModStat = ( !$iModStat ) ? 1 : $iModStat;
00390         return $iModStat;
00391     }
00392 
00399     public function checkPhp4Compat()
00400     {
00401         $sZendStatus = ( strtolower( (string) @ini_get( 'zend.ze1_compatibility_mode' ) ) );
00402         return in_array( $sZendStatus, array( 'on', '1' ) ) ? 0 : 2;
00403     }
00404 
00411     public function checkPhpVersion()
00412     {
00413         $iModStat = ( version_compare( PHP_VERSION, '5.1', '>' ) ) ? 1 : 0;
00414         $iModStat = ( $iModStat == 0 ) ? $iModStat : ( version_compare( PHP_VERSION, '5.2', '>=' ) ? 2 : 1 );
00415         return $iModStat;
00416     }
00417 
00423     public function checkRequestUri()
00424     {
00425         return ( isset( $_SERVER['REQUEST_URI'] ) || isset( $_SERVER['SCRIPT_URI'] ) ) ? 2 : 0;
00426     }
00427 
00433     public function checkLibXml2()
00434     {
00435         return class_exists( 'DOMDocument' ) ? 2 : 0;
00436     }
00437 
00443     public function checkPhpXml()
00444     {
00445         return class_exists( 'DOMDocument' ) ? 2 : 0;
00446     }
00447 
00453     public function checkJSon()
00454     {
00455         return extension_loaded( 'json' ) ? 2 : 0;
00456     }
00457 
00463     public function checkIConv()
00464     {
00465         return extension_loaded( 'iconv' ) ? 2 : 0;
00466     }
00467 
00473     public function checkTokenizer()
00474     {
00475         return extension_loaded( 'tokenizer' ) ? 2 : 0;
00476     }
00477 
00483     public function checkBcMath()
00484     {
00485         return extension_loaded( 'bcmath' ) ? 2 : 1;
00486     }
00487 
00493     public function checkOpenSsl()
00494     {
00495         return extension_loaded( 'openssl' ) ? 2 : 1;
00496     }
00497 
00503     public function checkSoap()
00504     {
00505         return extension_loaded( 'soap' ) ? 2 : 1;
00506     }
00507 
00513     public function checkMysqlConnect()
00514     {
00515         // MySQL module for MySQL5
00516         $iModStat = ( extension_loaded( 'mysql' ) || extension_loaded( 'mysqli' ) || extension_loaded( 'pdo_mysql' ) ) ? 2 : 0;
00517         // client version must be >=5
00518         if ( $iModStat ) {
00519             $sClientVersion = mysql_get_client_info();
00520             if (version_compare( $sClientVersion, '5', '<' )) {
00521                 $iModStat = 1;
00522                 if (version_compare( $sClientVersion, '4', '<' )) {
00523                     $iModStat = 0;
00524                 }
00525             } elseif (version_compare($sClientVersion, '5.0.36', '>=') && version_compare($sClientVersion, '5.0.38', '<')) {
00526                 // mantis#0001003: Problems with MySQL version 5.0.37
00527                 $iModStat = 0;
00528             } elseif (version_compare($sClientVersion, '5.0.40', '>') && version_compare($sClientVersion, '5.0.42', '<')) {
00529                 // mantis#0001877: Exclude MySQL 5.0.41 from system requirements as not fitting
00530                 $iModStat = 0;
00531             }
00532             if (strpos($sClientVersion, 'mysqlnd') !== false) {
00533                 // PHP 5.3 includes new mysqlnd extension
00534                 $iModStat = 2;
00535             }
00536         }
00537         return $iModStat;
00538     }
00539 
00547     public function checkMysqlVersion( $sVersion = null )
00548     {
00549         if ( $sVersion === null ) {
00550             $aRez = oxDb::getDb()->getAll( "SHOW VARIABLES LIKE 'version'" );
00551             foreach ( $aRez as $aRecord ) {
00552                 $sVersion = $aRecord[1];
00553                 break;
00554             }
00555         }
00556 
00557         $iModStat = 0;
00558         if ( version_compare( $sVersion, '5', '>=' ) && version_compare( $sVersion, '5.0.37', '<>' ) ) {
00559             $iModStat = 2;
00560         }
00561 
00562         return $iModStat;
00563     }
00564 
00570     public function checkGdInfo()
00571     {
00572         $iModStat = extension_loaded( 'gd' ) ? 1 : 0;
00573         $iModStat = function_exists( 'imagecreatetruecolor' ) ? 2 : $iModStat;
00574         $iModStat = function_exists( 'imagecreatefromjpeg' ) ? $iModStat : 0;
00575         return $iModStat;
00576     }
00577 
00583     public function checkIniSet()
00584     {
00585         return ( @ini_set('session.name', 'sid' ) !== false ) ? 2 : 0;
00586     }
00587 
00593     public function checkRegisterGlobals()
00594     {
00595         $sGlobStatus = ( strtolower( (string) @ini_get( 'register_globals' ) ) );
00596         return in_array( $sGlobStatus, array( 'on', '1' ) ) ? 0 : 2;
00597     }
00598 
00604     public function checkMemoryLimit()
00605     {
00606         if ( $sMemLimit = @ini_get('memory_limit') ) {
00607                 // CE - PE at least to 14 MB. We recomend a memory_limit of 30MB.
00608                 $sDefLimit = '14M';
00609                 $sRecLimit = '30M';
00610 
00611 
00612             $iMemLimit = $this->_getBytes( $sMemLimit );
00613             $iModStat = ( $iMemLimit >= $this->_getBytes( $sDefLimit ) ) ? 1 : 0;
00614             $iModStat = $iModStat ? ( ( $iMemLimit >= $this->_getBytes( $sRecLimit ) ) ? 2 : $iModStat ) : $iModStat;
00615 
00616         } else {
00617             $iModStat = -1;
00618         }
00619         return $iModStat;
00620     }
00621 
00627     public function checkZendOptimizer()
00628     {
00633         return 2;
00634     }
00635 
00641     public function checkZendPlatformOrServer()
00642     {
00643         if (function_exists( 'output_cache_get' )) {
00644             return 2;
00645         }
00646         if (function_exists( 'zend_disk_cache_fetch' )) {
00647             return 2;
00648         }
00649         if (function_exists( 'zend_shm_cache_fetch' )) {
00650             return 2;
00651         }
00652         return 1;
00653     }
00654 
00660     protected function _getAdditionalCheck()
00661     {
00662         $sSelect = '';
00663         foreach ( $this->_aException as $sTable => $sColumn ) {
00664             $sSelect .= 'and ( t.TABLE_NAME != "'.$sTable.'" and c.COLUMN_NAME != "'.$sColumn.'" ) ';
00665         }
00666         return $sSelect;
00667     }
00668 
00674     public function checkCollation()
00675     {
00676         $myConfig = oxConfig::getInstance();
00677 
00678         $aCollations = array();
00679         $sCollation = '';
00680 
00681         $sSelect = 'select t.TABLE_NAME, c.COLUMN_NAME, c.COLLATION_NAME from INFORMATION_SCHEMA.tables t ' .
00682                    'LEFT JOIN INFORMATION_SCHEMA.columns c ON t.TABLE_NAME = c.TABLE_NAME  ' .
00683                    'where t.TABLE_SCHEMA = "'.$myConfig->getConfigParam( 'dbName' ).'" ' .
00684                    'and c.TABLE_SCHEMA = "'.$myConfig->getConfigParam( 'dbName' ).'" ' .
00685                    'and c.COLUMN_NAME in ("'.implode('", "', $this->_aColumns).'") ' . $this->_getAdditionalCheck() .
00686                    ' ORDER BY (t.TABLE_NAME = "oxarticles") DESC';
00687         $aRez = oxDb::getDb()->getAll($sSelect);
00688         foreach ( $aRez as $aRetTable ) {
00689             if ( !$sCollation ) {
00690                 $sCollation = $aRetTable[2];
00691             } else {
00692                 if ( $aRetTable[2] && $sCollation != $aRetTable[2]) {
00693                     $aCollations[$aRetTable[0]][$aRetTable[1]] = $aRetTable[2];
00694                 }
00695             }
00696         }
00697 
00698         if ( $this->_blSysReqStatus === null ) {
00699             $this->_blSysReqStatus = true;
00700         }
00701         if ( count($aCollations) > 0 ) {
00702             $this->_blSysReqStatus = false;
00703         }
00704         return $aCollations;
00705     }
00706 
00712     public function checkDatabaseCluster()
00713     {
00714         return 2;
00715     }
00716 
00722     public function checkUnicodeSupport()
00723     {
00724         return (@preg_match('/\pL/u', 'a') == 1) ? 2 : 1;
00725     }
00726 
00732     public function getSysReqStatus()
00733     {
00734         if ( $this->_blSysReqStatus == null ) {
00735             $this->_blSysReqStatus = true;
00736             $this->getSystemInfo();
00737             $this->checkCollation();
00738         }
00739         return $this->_blSysReqStatus;
00740     }
00741 
00756     public function getSystemInfo()
00757     {
00758         $aSysInfo = array();
00759         $aRequiredModules = $this->getRequiredModules();
00760         $this->_blSysReqStatus = true;
00761         foreach ( $aRequiredModules as $sModule => $sGroup ) {
00762             if ( isset($aSysInfo[$sGroup]) && !$aSysInfo[$sGroup] ) {
00763                 $aSysInfo[$sGroup] = array();
00764             }
00765             $iModuleState = $this->getModuleInfo( $sModule );
00766             $aSysInfo[$sGroup][$sModule] = $iModuleState;
00767             $this->_blSysReqStatus = $this->_blSysReqStatus && ( bool ) abs( $iModuleState );
00768         }
00769         return $aSysInfo;
00770     }
00771 
00779     public function getModuleInfo( $sModule = null )
00780     {
00781         if ( $sModule ) {
00782             $iModStat = null;
00783             $sCheckFunction = "check".str_replace(" ", "", ucwords(str_replace("_", " ", $sModule)));
00784             $iModStat = $this->$sCheckFunction();
00785 
00786             return $iModStat;
00787         }
00788     }
00789 
00797     public function getReqInfoUrl( $sIdent)
00798     {
00799         $sUrl = $this->_sReqInfoUrl;
00800         $aInfoMap = $this->_aInfoMap;
00801 
00802         // only known will be anchored
00803         if ( isset( $aInfoMap[$sIdent] ) ) {
00804             $sUrl .= "#".$aInfoMap[$sIdent];
00805         }
00806 
00807         return $sUrl;
00808     }
00809 
00817     protected function _getBytes( $sBytes )
00818     {
00819         $sBytes = trim( $sBytes );
00820         $sLast = strtolower($sBytes[strlen($sBytes)-1]);
00821         switch( $sLast ) {
00822             // The 'G' modifier is available since PHP 5.1.0
00823             case 'g':
00824                 $sBytes *= 1024;
00825             case 'm':
00826                 $sBytes *= 1024;
00827             case 'k':
00828                 $sBytes *= 1024;
00829                 break;
00830         }
00831 
00832         return $sBytes;
00833     }
00834 }