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         $iPort = isset( $_SERVER['SERVER_PORT'] ) ? $_SERVER['SERVER_PORT'] : 80;
00278         if ( $sScript && $rFp = @fsockopen( $sHost, $iPort, $iErrNo, $sErrStr, 10 ) ) {
00279             if ( isAdmin() ) {
00280                 $sScript = oxConfig::getInstance()->getConfigParam( 'sShopURL' ).'oxseo.php?mod_rewrite_module_is=off';
00281             } else {
00282                 $sScript = str_replace( basename( $sScript ), '../oxseo.php?mod_rewrite_module_is=off', $sScript );
00283             }
00284 
00285             $sReq  = "POST $sScript HTTP/1.1\r\n";
00286             $sReq .= "Host: $sHost\r\n";
00287             $sReq .= "User-Agent: oxid setup\r\n";
00288             $sReq .= "Content-Type: application/x-www-form-urlencoded\r\n";
00289             $sReq .= "Content-Length: 0\r\n"; // empty post
00290             $sReq .= "Connection: close\r\n\r\n";
00291 
00292             $sOut = '';
00293             fwrite( $rFp, $sReq );
00294             while ( !feof( $rFp ) ) {
00295                 $sOut .= fgets( $rFp, 100 );
00296             }
00297             fclose( $rFp );
00298 
00299             $iModStat = ( strpos( $sOut, 'mod_rewrite_on' ) !== false ) ? 2 : 0;
00300         } else {
00301             if ( function_exists( 'apache_get_modules' ) ) {
00302                 // it does not assure that mod_rewrite is enabled on current host, so setting 1
00303                 $iModStat = in_array( 'mod_rewrite', apache_get_modules() ) ? 1 : 0;
00304             } else {
00305                 $iModStat = -1;
00306             }
00307         }
00308         return $iModStat;
00309     }
00310 
00316     public function checkAllowUrlFopen()
00317     {
00318         $iModStat = @ini_get('allow_url_fopen');
00319         $iModStat = ( $iModStat && strcasecmp( '1', $iModStat ) ) ? 2 : 1;
00320         if ( $iModStat == 1 ) {
00321             $iErrNo  = 0;
00322             $sErrStr = '';
00323             if ( $oRes = @fsockopen( 'www.example.com', 80, $iErrNo, $sErrStr, 10 ) ) {
00324                 $iModStat = 2;
00325                 fclose( $oRes );
00326             }
00327         }
00328         $iModStat = ( !$iModStat ) ? 1 : $iModStat;
00329         return $iModStat;
00330     }
00331 
00338     public function checkPhp4Compat()
00339     {
00340         $sZendStatus = ( strtolower( (string) @ini_get( 'zend.ze1_compatibility_mode' ) ) );
00341         return in_array( $sZendStatus, array( 'on', '1' ) ) ? 0 : 2;
00342     }
00343 
00350     public function checkPhpVersion()
00351     {
00352         $iModStat = ( version_compare( PHP_VERSION, '5.1', '>' ) ) ? 1 : 0;
00353         $iModStat = ( $iModStat == 0 ) ? $iModStat : ( version_compare( PHP_VERSION, '5.2', '>=' ) ? 2 : 1 );
00354         return $iModStat;
00355     }
00356 
00362     public function checkRequestUri()
00363     {
00364         return ( isset( $_SERVER['REQUEST_URI'] ) || isset( $_SERVER['SCRIPT_URI'] ) ) ? 2 : 0;
00365     }
00366 
00372     public function checkLibXml2()
00373     {
00374         return class_exists( 'DOMDocument' ) ? 2 : 0;
00375     }
00376 
00382     public function checkPhpXml()
00383     {
00384         return class_exists( 'DOMDocument' ) ? 2 : 0;
00385     }
00386 
00392     public function checkJSon()
00393     {
00394         return extension_loaded( 'json' ) ? 2 : 0;
00395     }
00396 
00402     public function checkIConv()
00403     {
00404         return extension_loaded( 'iconv' ) ? 2 : 0;
00405     }
00406 
00412     public function checkTokenizer()
00413     {
00414         return extension_loaded( 'tokenizer' ) ? 2 : 0;
00415     }
00416 
00422     public function checkBcMath()
00423     {
00424         return extension_loaded( 'bcmath' ) ? 2 : 1;
00425     }
00426 
00432     public function checkMysqlConnect()
00433     {
00434         // MySQL module for MySQL5
00435         $iModStat = ( extension_loaded( 'mysql' ) || extension_loaded( 'mysqli' ) || extension_loaded( 'pdo_mysql' ) ) ? 2 : 0;
00436         // client version must be >=5
00437         if ( $iModStat ) {
00438             $sClientVersion = mysql_get_client_info();
00439             if (version_compare( $sClientVersion, '5', '<' )) {
00440                 $iModStat = 1;
00441                 if (version_compare( $sClientVersion, '4', '<' )) {
00442                     $iModStat = 0;
00443                 }
00444             } elseif (version_compare($sClientVersion, '5.0.36', '>=') && version_compare($sClientVersion, '5.0.38', '<')) {
00445                 // mantis#0001003: Problems with MySQL version 5.0.37
00446                 $iModStat = 0;
00447             } elseif (version_compare($sClientVersion, '5.0.40', '>') && version_compare($sClientVersion, '5.0.42', '<')) {
00448                 // mantis#0001877: Exclude MySQL 5.0.41 from system requirements as not fitting
00449                 $iModStat = 0;
00450             }
00451             if (strpos($sClientVersion, 'mysqlnd') !== false) {
00452                 // PHP 5.3 includes new mysqlnd extension
00453                 $iModStat = 2;
00454             }
00455         }
00456         return $iModStat;
00457     }
00458 
00466     public function checkMysqlVersion( $sVersion = null )
00467     {
00468         if ( $sVersion === null ) {
00469             $aRez = oxDb::getDb()->getAll( "SHOW VARIABLES LIKE 'version'" );
00470             foreach ( $aRez as $aRecord ) {
00471                 $sVersion = $aRecord[1];
00472                 break;
00473             }
00474         }
00475 
00476         $iModStat = 0;
00477         if ( version_compare( $sVersion, '5', '>=' ) && version_compare( $sVersion, '5.0.37', '<>' ) ) {
00478             $iModStat = 2;
00479         }
00480 
00481         return $iModStat;
00482     }
00483 
00489     public function checkGdInfo()
00490     {
00491         $iModStat = extension_loaded( 'gd' ) ? 1 : 0;
00492         $iModStat = function_exists( 'imagecreatetruecolor' ) ? 2 : $iModStat;
00493         $iModStat = function_exists( 'imagecreatefromjpeg' ) ? $iModStat : 0;
00494         return $iModStat;
00495     }
00496 
00502     public function checkIniSet()
00503     {
00504         return ( @ini_set('session.name', 'sid' ) !== false ) ? 2 : 0;
00505     }
00506 
00512     public function checkRegisterGlobals()
00513     {
00514         $sGlobStatus = ( strtolower( (string) @ini_get( 'register_globals' ) ) );
00515         return in_array( $sGlobStatus, array( 'on', '1' ) ) ? 0 : 2;
00516     }
00517 
00523     public function checkMemoryLimit()
00524     {
00525         if ( $sMemLimit = @ini_get('memory_limit') ) {
00526                 // CE - PE at least to 14 MB. We recomend a memory_limit of 30MB.
00527                 $sDefLimit = '14M';
00528                 $sRecLimit = '30M';
00529 
00530 
00531             $iMemLimit = $this->_getBytes( $sMemLimit );
00532             $iModStat = ( $iMemLimit >= $this->_getBytes( $sDefLimit ) ) ? 1 : 0;
00533             $iModStat = $iModStat ? ( ( $iMemLimit >= $this->_getBytes( $sRecLimit ) ) ? 2 : $iModStat ) : $iModStat;
00534 
00535         } else {
00536             $iModStat = -1;
00537         }
00538         return $iModStat;
00539     }
00540 
00546     public function checkZendOptimizer()
00547     {
00552         return 2;
00553     }
00554 
00560     public function checkZendPlatformOrServer()
00561     {
00562         if (function_exists( 'output_cache_get' )) {
00563             return 2;
00564         }
00565         if (function_exists( 'zend_disk_cache_fetch' )) {
00566             return 2;
00567         }
00568         if (function_exists( 'zend_shm_cache_fetch' )) {
00569             return 2;
00570         }
00571         return 1;
00572     }
00573 
00579     protected function _getAdditionalCheck()
00580     {
00581         $sSelect = '';
00582         foreach ( $this->_aException as $sTable => $sColumn ) {
00583             $sSelect .= 'and ( t.TABLE_NAME != "'.$sTable.'" and c.COLUMN_NAME != "'.$sColumn.'" ) ';
00584         }
00585         return $sSelect;
00586     }
00587 
00593     public function checkCollation()
00594     {
00595         $myConfig = oxConfig::getInstance();
00596 
00597         $aCollations = array();
00598         $sCollation = '';
00599 
00600         $sSelect = 'select t.TABLE_NAME, c.COLUMN_NAME, c.COLLATION_NAME from INFORMATION_SCHEMA.tables t ' .
00601                    'LEFT JOIN INFORMATION_SCHEMA.columns c ON t.TABLE_NAME = c.TABLE_NAME  ' .
00602                    'where t.TABLE_SCHEMA = "'.$myConfig->getConfigParam( 'dbName' ).'" ' .
00603                    'and c.TABLE_SCHEMA = "'.$myConfig->getConfigParam( 'dbName' ).'" ' .
00604                    'and c.COLUMN_NAME in ("'.implode('", "', $this->_aColumns).'") ' . $this->_getAdditionalCheck() .
00605                    ' ORDER BY (t.TABLE_NAME = "oxarticles") DESC';
00606         $aRez = oxDb::getDb()->getAll($sSelect);
00607         foreach ( $aRez as $aRetTable ) {
00608             if ( !$sCollation ) {
00609                 $sCollation = $aRetTable[2];
00610             } else {
00611                 if ( $aRetTable[2] && $sCollation != $aRetTable[2]) {
00612                     $aCollations[$aRetTable[0]][$aRetTable[1]] = $aRetTable[2];
00613                 }
00614             }
00615         }
00616 
00617         if ( $this->_blSysReqStatus === null ) {
00618             $this->_blSysReqStatus = true;
00619         }
00620         if ( count($aCollations) > 0 ) {
00621             $this->_blSysReqStatus = false;
00622         }
00623         return $aCollations;
00624     }
00625 
00631     public function checkDatabaseCluster()
00632     {
00633         return 2;
00634     }
00635 
00641     public function checkUnicodeSupport()
00642     {
00643         return (@preg_match('/\pL/u', 'a') == 1) ? 2 : 1;
00644     }
00645 
00651     public function getSysReqStatus()
00652     {
00653         if ( $this->_blSysReqStatus == null ) {
00654             $this->_blSysReqStatus = true;
00655             $this->getSystemInfo();
00656             $this->checkCollation();
00657         }
00658         return $this->_blSysReqStatus;
00659     }
00660 
00675     public function getSystemInfo()
00676     {
00677         $aSysInfo = array();
00678         $aRequiredModules = $this->getRequiredModules();
00679         $this->_blSysReqStatus = true;
00680         foreach ( $aRequiredModules as $sModule => $sGroup ) {
00681             if ( isset($aSysInfo[$sGroup]) && !$aSysInfo[$sGroup] ) {
00682                 $aSysInfo[$sGroup] = array();
00683             }
00684             $iModuleState = $this->getModuleInfo( $sModule );
00685             $aSysInfo[$sGroup][$sModule] = $iModuleState;
00686             $this->_blSysReqStatus = $this->_blSysReqStatus && ( bool ) abs( $iModuleState );
00687         }
00688         return $aSysInfo;
00689     }
00690 
00698     public function getModuleInfo( $sModule = null )
00699     {
00700         if ( $sModule ) {
00701             $iModStat = null;
00702             $sCheckFunction = "check".str_replace(" ", "", ucwords(str_replace("_", " ", $sModule)));
00703             $iModStat = $this->$sCheckFunction();
00704 
00705             return $iModStat;
00706         }
00707     }
00708 
00716     public function getReqInfoUrl( $sIdent)
00717     {
00718         $sUrl = $this->_sReqInfoUrl;
00719         $aInfoMap = $this->_aInfoMap;
00720 
00721         // only known will be anchored
00722         if ( isset( $aInfoMap[$sIdent] ) ) {
00723             $sUrl .= "#".$aInfoMap[$sIdent];
00724         }
00725 
00726         return $sUrl;
00727     }
00728 
00736     protected function _getBytes( $sBytes )
00737     {
00738         $sBytes = trim( $sBytes );
00739         $sLast = strtolower($sBytes[strlen($sBytes)-1]);
00740         switch( $sLast ) {
00741             // The 'G' modifier is available since PHP 5.1.0
00742             case 'g':
00743                 $sBytes *= 1024;
00744             case 'm':
00745                 $sBytes *= 1024;
00746             case 'k':
00747                 $sBytes *= 1024;
00748                 break;
00749         }
00750 
00751         return $sBytes;
00752     }
00753 }