Overview

Packages

  • CONTENIDO
  • Core
    • Authentication
    • Backend
    • Cache
    • CEC
    • Chain
    • ContentType
    • Database
    • Debug
    • Exception
    • Frontend
      • Search
      • URI
      • Util
    • GenericDB
      • Model
    • GUI
      • HTML
    • I18N
    • LayoutHandler
    • Log
    • Security
    • Session
    • Util
    • Validation
    • Versioning
    • XML
  • Module
    • ContentRssCreator
    • ContentSitemapHtml
    • ContentSitemapXml
    • ContentUserForum
    • NavigationTop
    • ScriptCookieDirective
  • mpAutoloaderClassMap
  • None
  • Plugin
    • ContentAllocation
    • CronjobOverview
    • FormAssistant
    • FrontendLogic
    • FrontendUsers
    • Linkchecker
    • ModRewrite
    • Newsletter
    • Repository
      • FrontendNavigation
      • KeywordDensity
    • SearchSolr
    • SmartyWrapper
    • UrlShortener
    • UserForum
    • Workflow
  • PluginManager
  • Setup
    • Form
    • GUI
    • Helper
      • Environment
      • Filesystem
      • MySQL
      • PHP
    • UpgradeJob
  • Smarty
    • Cacher
    • Compiler
    • Config
    • Debug
    • PluginsBlock
    • PluginsFilter
    • PluginsFunction
    • PluginsInternal
    • PluginsModifier
    • PluginsModifierCompiler
    • PluginsShared
    • Security
    • Template
    • TemplateResources
  • Swift
    • ByteStream
    • CharacterStream
    • Encoder
    • Events
    • KeyCache
    • Mailer
    • Mime
    • Plugins
    • Transport

Classes

  • Swift_FailoverTransport
  • Swift_LoadBalancedTransport
  • Swift_MailTransport
  • Swift_Plugins_Loggers_ArrayLogger
  • Swift_Plugins_Loggers_EchoLogger
  • Swift_SendmailTransport
  • Swift_SmtpTransport
  • Swift_Transport_AbstractSmtpTransport
  • Swift_Transport_Esmtp_Auth_CramMd5Authenticator
  • Swift_Transport_Esmtp_Auth_LoginAuthenticator
  • Swift_Transport_Esmtp_Auth_PlainAuthenticator
  • Swift_Transport_Esmtp_AuthHandler
  • Swift_Transport_EsmtpTransport
  • Swift_Transport_FailoverTransport
  • Swift_Transport_LoadBalancedTransport
  • Swift_Transport_MailTransport
  • Swift_Transport_SendmailTransport
  • Swift_Transport_SimpleMailInvoker
  • Swift_Transport_StreamBuffer

Interfaces

  • Swift_Plugins_Logger
  • Swift_Plugins_Pop_Pop3Exception
  • Swift_Transport
  • Swift_Transport_Esmtp_Authenticator
  • Swift_Transport_EsmtpHandler
  • Swift_Transport_IoBuffer
  • Swift_Transport_MailInvoker
  • Swift_Transport_SmtpAgent
  • Swift_TransportException
  • Overview
  • Package
  • Function
  • Todo
  • Download
   1: <?php
   2: /**
   3:  * This file contains the the system test class.
   4:  *
   5:  * @package Core
   6:  * @subpackage Backend
   7:  * @version SVN Revision $Rev:$
   8:  *
   9:  * @author Mischa Holz
  10:  * @copyright four for business AG <www.4fb.de>
  11:  * @license http://www.contenido.org/license/LIZENZ.txt
  12:  * @link http://www.4fb.de
  13:  * @link http://www.contenido.org
  14:  */
  15: 
  16: defined('CON_FRAMEWORK') || die('Illegal call: Missing framework initialization - request aborted.');
  17: 
  18: /**
  19:  * Provides functions to test the system integrity
  20:  *
  21:  * @package Core
  22:  * @subpackage Backend
  23:  */
  24: class cSystemtest {
  25: 
  26:     /**
  27:      * The minimal PHP version
  28:      *
  29:      * @var string
  30:      */
  31:     const CON_SETUP_MIN_PHP_VERSION = '5.3';
  32: 
  33:     /**
  34:      * Messages have no influence on the result of the system integrity
  35:      *
  36:      * @var int
  37:      */
  38:     const C_SEVERITY_NONE = 1;
  39: 
  40:     /**
  41:      * Messages are only to inform the user about something.
  42:      *
  43:      * @var int
  44:      */
  45:     const C_SEVERITY_INFO = 2;
  46: 
  47:     /**
  48:      * Messages about settings which aren't correct, but CONTENIDO might work
  49:      * anyway
  50:      *
  51:      * @var int
  52:      */
  53:     const C_SEVERITY_WARNING = 3;
  54: 
  55:     /**
  56:      * Messages about settings which aren't correct.
  57:      * CONTENIDO won't work
  58:      *
  59:      * @var int
  60:      */
  61:     const C_SEVERITY_ERROR = 4;
  62: 
  63:     /**
  64:      * Possible result of cSystemtest::predictCorrectFilePermissions()
  65:      * The filepermissions are okay
  66:      *
  67:      * @var int
  68:      */
  69:     const CON_PREDICT_SUFFICIENT = 1;
  70: 
  71:     /**
  72:      * Possible result of cSystemtest::predictCorrectFilePermissions()
  73:      * The filepermissions are not predictable (we can't figure the server UID)
  74:      *
  75:      * @var int
  76:      */
  77:     const CON_PREDICT_NOTPREDICTABLE = 2;
  78: 
  79:     /**
  80:      * Possible result of cSystemtest::predictCorrectFilePermissions()
  81:      * The filepermissions for the owner have to be changed
  82:      *
  83:      * @var int
  84:      */
  85:     const CON_PREDICT_CHANGEPERM_SAMEOWNER = 3;
  86: 
  87:     /**
  88:      * Possible result of cSystemtest::predictCorrectFilePermissions()
  89:      * The filepermissions for the group have to be changed
  90:      *
  91:      * @var int
  92:      */
  93:     const CON_PREDICT_CHANGEPERM_SAMEGROUP = 4;
  94: 
  95:     /**
  96:      * Possible result of cSystemtest::predictCorrectFilePermissions()
  97:      * The filepermissions for others should be changed
  98:      *
  99:      * @var int
 100:      */
 101:     const CON_PREDICT_CHANGEPERM_OTHERS = 5;
 102: 
 103:     /**
 104:      * Possible result of cSystemtest::predictCorrectFilePermissions()
 105:      * The owner of the file should be changed
 106:      *
 107:      * @var int
 108:      */
 109:     const CON_PREDICT_CHANGEUSER = 6;
 110: 
 111:     /**
 112:      * Possible result of cSystemtest::predictCorrectFilePermissions()
 113:      * The group of the file should be changed
 114:      *
 115:      * @var int
 116:      */
 117:     const CON_PREDICT_CHANGEGROUP = 7;
 118: 
 119:     /**
 120:      * Possible result of cSystemtest::predictCorrectFilePermissions()
 121:      * The filepermissions are unpredictable because Windows
 122:      *
 123:      * @var int
 124:      */
 125:     const CON_PREDICT_WINDOWS = 8;
 126: 
 127:     /**
 128:      * Possible result of cSystemtest::checkOpenBaseDir().
 129:      * No restrictions
 130:      *
 131:      * @var int
 132:      */
 133:     const CON_BASEDIR_NORESTRICTION = 1;
 134: 
 135:     /**
 136:      * Possible result of cSystemtest::checkOpenBaseDir().
 137:      * The Basedir is set to ".". CONTENIDO won't work
 138:      *
 139:      * @var int
 140:      */
 141:     const CON_BASEDIR_DOTRESTRICTION = 2;
 142: 
 143:     /**
 144:      * Possible result of cSystemtest::checkOpenBaseDir().
 145:      * Open basedir is in effect but CONTENIDO works anyway
 146:      *
 147:      * @var int
 148:      */
 149:     const CON_BASEDIR_RESTRICTIONSUFFICIENT = 3;
 150: 
 151:     /**
 152:      * Possible result of cSystemtest::checkOpenBaseDir().
 153:      * Open basedir is in effect and CONTENIDO doesn't work with it
 154:      *
 155:      * @var int
 156:      */
 157:     const CON_BASEDIR_INCOMPATIBLE = 4;
 158: 
 159:     /**
 160:      * Possible result of cSystemtest::isPHPExtensionLoaded()
 161:      * The extension is loaded
 162:      *
 163:      * @var int
 164:      */
 165:     const CON_EXTENSION_AVAILABLE = 1;
 166: 
 167:     /**
 168:      * Possible result of cSystemtest::isPHPExtensionLoaded()
 169:      * The extension is not loaded
 170:      *
 171:      * @var int
 172:      */
 173:     const CON_EXTENSION_UNAVAILABLE = 2;
 174: 
 175:     /**
 176:      * Possible result of cSystemtest::isPHPExtensionLoaded()
 177:      * It was unable to check wether the extension is loaded or not
 178:      *
 179:      * @var int
 180:      */
 181:     const CON_EXTENSION_CANTCHECK = 3;
 182: 
 183:     /**
 184:      * Possible result of cSystemtest::checkImageResizer()
 185:      * GD is available for image resizing
 186:      *
 187:      * @var int
 188:      */
 189:     const CON_IMAGERESIZE_GD = 1;
 190: 
 191:     /**
 192:      * Possible result of cSystemtest::checkImageResizer()
 193:      * ImageMagick is available for image resizing
 194:      *
 195:      * @var int
 196:      */
 197:     const CON_IMAGERESIZE_IMAGEMAGICK = 2;
 198: 
 199:     /**
 200:      * Possible result of cSystemtest::checkImageResizer()
 201:      * It was unable to check which extension is available for image resizing
 202:      *
 203:      * @var int
 204:      */
 205:     const CON_IMAGERESIZE_CANTCHECK = 3;
 206: 
 207:     /**
 208:      * Possible result of cSystemtest::checkImageResizer()
 209:      * No fitting extension is available
 210:      *
 211:      * @var int
 212:      */
 213:     const CON_IMAGERESIZE_NOTHINGAVAILABLE = 4;
 214: 
 215:     /**
 216:      * Possible result of cSystemtest::testMySQL()
 217:      * Everything works fine with the given settings
 218:      *
 219:      * @var int
 220:      */
 221:     const CON_MYSQL_OK = 1;
 222: 
 223:     /**
 224:      * Possible result of cSystemtest::testMySQL()
 225:      * Strict mode is activated.
 226:      * CONTENIDO won't work
 227:      *
 228:      * @var int
 229:      */
 230:     const CON_MYSQL_STRICT_MODE = 2;
 231: 
 232:     /**
 233:      * Possible result of cSystemtest::testMySQL()
 234:      * Strict mode is activated.
 235:      * CONTENIDO won't work
 236:      *
 237:      * @var int
 238:      */
 239:     const CON_MYSQL_CANT_CONNECT = 3;
 240: 
 241:     /**
 242:      * The test results which are stored for display.
 243:      * Every array element is an assoicative array like this:
 244:      * $_messages[$i] = array(
 245:      * "result" => $result, //true or false, success or no success
 246:      * "severity" => $severity, //one of the C_SEVERITY constants
 247:      * "headline" => $headline, //the headline of the message
 248:      * "message" => $message //the message
 249:      * );
 250:      *
 251:      * @var array
 252:      */
 253:     protected $_messages;
 254: 
 255:     /**
 256:      * The stored config array
 257:      *
 258:      * @var array
 259:      */
 260:     protected $_config;
 261: 
 262:     /**
 263:      * Caches the given config array for later use.
 264:      *
 265:      * @param array $config A config array which should be similar to
 266:      *        CONTENIDO's $cfg
 267:      */
 268:     public function __construct($config) {
 269:         $this->_config = $config;
 270:     }
 271: 
 272:     /**
 273:      * Runs all available tests and stores the resuls in the messages array
 274:      *
 275:      * @param bool $testFileSystem If this is true the file system checks will
 276:      *        be performed too with standard settings.
 277:      */
 278:     public function runTests($testFileSystem = true) {
 279:         $this->storeResult($this->testPHPVersion(), self::C_SEVERITY_ERROR, sprintf(i18n("PHP Version lower than %s"), self::CON_SETUP_MIN_PHP_VERSION), sprintf(i18n("CONTENIDO requires PHP %s or higher as it uses functionality first introduced with this version. Please update your PHP version."), self::CON_SETUP_MIN_PHP_VERSION), i18n("The PHP version is higher than ") . self::CON_SETUP_MIN_PHP_VERSION);
 280:         $this->storeResult($this->testFileUploadSetting(), self::C_SEVERITY_WARNING, i18n("File uploads disabled"), sprintf(i18n("Your PHP version is not configured for file uploads. You can't upload files using CONTENIDO's file manager unless you configure PHP for file uploads. See %s for more information"), '<a target="_blank" href="http://www.php.net/manual/en/ini.core.php#ini.file-uploads">http://www.php.net/manual/en/ini.core.php#ini.file-uploads</a>'), i18n("PHP file upload is enabled"));
 281:         $this->storeResult($this->testMagicQuotesRuntimeSetting(), self::C_SEVERITY_ERROR, i18n("PHP setting 'magic_quotes_runtime' is turned on"), i18n("The PHP setting 'magic_quotes_runtime' is turned on. CONTENIDO has been developed to comply with magic_quotes_runtime=Off as this is the PHP default setting. You have to change this directive to make CONTENIDO work."), i18n("'magic_quotes_runtime' is turned off"));
 282:         $this->storeResult($this->testMagicQuotesSybaseSetting(), self::C_SEVERITY_ERROR, i18n("PHP Setting 'magic_quotes_sybase' is turned on"), i18n("The PHP Setting 'magic_quotes_sybase' is turned on. CONTENIDO has been developed to comply with magic_quotes_sybase=Off as this is the PHP default setting. You have to change this directive to make CONTENIDO work."), i18n("'magic_quotes_sybase' is turned off"));
 283:         $this->storeResult($this->testMaxExecutionTime(), self::C_SEVERITY_WARNING, i18n("PHP maximum execution time is less than 30 seconds"), i18n("PHP is configured for a maximum execution time of less than 30 seconds. This could cause problems with slow web servers and/or long operations in the backend. Our recommended execution time is 120 seconds on slow web servers, 60 seconds for medium ones and 30 seconds for fast web servers."), i18n("PHP allows execution times longer than 30 seconds"));
 284:         $this->storeResult($this->testZIPArchive(), self::C_SEVERITY_WARNING, i18n("The class ZipArchive could not be found"), i18n("This could cause some problems, but CONTENIDO is able to run without it. You should check your PHP installation."), i18n("The ZipArchive class is enabled"));
 285: 
 286:         $test = $this->checkOpenBasedirCompatibility();
 287:         switch ($test) {
 288:             case self::CON_BASEDIR_NORESTRICTION:
 289:                 $this->storeResult(true, self::C_SEVERITY_ERROR, "", "", i18n("open_basedir directive doesn't enforce any restrictions"));
 290:                 break;
 291:             case self::CON_BASEDIR_DOTRESTRICTION:
 292:                 $this->storeResult(false, self::C_SEVERITY_ERROR, i18n("open_basedir directive set to '.'"), i18n("The directive open_basedir is set to '.' (e.g. current directory). This means that CONTENIDO is unable to access files in a logical upper level in the filesystem. This will cause problems managing the CONTENIDO frontends. Either add the full path of this CONTENIDO installation to the open_basedir directive, or turn it off completely."));
 293:                 break;
 294:             case self::CON_BASEDIR_RESTRICTIONSUFFICIENT:
 295:                 $this->storeResult(false, self::C_SEVERITY_INFO, i18n("open_basedir setting might be insufficient"), i18n("Setup believes that the PHP directive open_basedir is configured sufficient, however, if you encounter errors like 'open_basedir restriction in effect. File <filename> is not within the allowed path(s): <path>', you have to adjust the open_basedir directive"));
 296:                 break;
 297:             case self::CON_BASEDIR_INCOMPATIBLE:
 298:                 $this->storeResult(false, self::C_SEVERITY_ERROR, i18n("open_basedir directive incompatible"), i18n("Setup has checked your PHP open_basedir directive and reckons that it is not sufficient. Please change the directive to include the CONTENIDO installation or turn it off completely."));
 299:                 break;
 300:         }
 301: 
 302:         $this->storeResult($this->testMemoryLimit(), self::C_SEVERITY_WARNING, i18n("PHP memory_limit directive too small"), i18n("The memory_limit directive is set to 32 MB or lower. This might be not enough for CONTENIDO to operate correctly. We recommend to disable this setting completely, as this can cause problems with large CONTENIDO projects."), i18n("Memory limit is either high enough or deactivated"));
 303:         $this->storeResult($this->testPHPSQLSafeMode(), self::C_SEVERITY_ERROR, i18n("PHP sql.safe_mode turned on"), i18n("The PHP directive sql.safe_mode is turned on. This causes problems with the SQL queries issued by CONTENIDO. Please turn that directive off."), i18n("sql.safe_mode is deactivated"));
 304:         $this->storeResult($this->isPHPExtensionLoaded("gd") == self::CON_EXTENSION_AVAILABLE, self::C_SEVERITY_WARNING, i18n("PHP GD-Extension is not loaded"), i18n("The PHP GD-Extension is not loaded. Some third-party modules rely on the GD functionality. If you don't enable the GD extension, you will encounter problems with modules like galleries."), i18n("GD extension loaded"));
 305:         if ($this->isPHPExtensionLoaded("gd") == self::CON_EXTENSION_AVAILABLE) {
 306:             $this->storeResult($this->testGDGIFRead(), self::C_SEVERITY_INFO, i18n("GD-Library GIF read support missing"), i18n("Your GD version doesn't support reading GIF files. This might cause problems with some modules."), i18n("GD is able to read GIFs"));
 307:             $this->storeResult($this->testGDGIFWrite(), self::C_SEVERITY_INFO, i18n("GD-Library GIF write support missing"), i18n("Your GD version doesn't support writing GIF files. This might cause problems with some modules."), i18n("GD is able to write GIFs"));
 308:             $this->storeResult($this->testGDJPEGRead(), self::C_SEVERITY_INFO, i18n("GD-Library JPEG read support missing"), i18n("Your GD version doesn't support reading JPEG files. This might cause problems with some modules."), i18n("GD is able to read JPEGs"));
 309:             $this->storeResult($this->testGDJPEGWrite(), self::C_SEVERITY_INFO, i18n("GD-Library JPEG write support missing"), i18n("Your GD version doesn't support writing JPEG files. This might cause problems with some modules."), i18n("GD is able to write JPEGs"));
 310:             $this->storeResult($this->testGDPNGRead(), self::C_SEVERITY_INFO, i18n("GD-Library PNG read support missing"), i18n("Your GD version doesn't support reading PNG files. This might cause problems with some modules."), i18n("GD is able to read PNGs"));
 311:             $this->storeResult($this->testGDPNGWrite(), self::C_SEVERITY_INFO, i18n("GD-Library PNG write support missing"), i18n("Your GD version doesn't support writing PNG files. This might cause problems with some modules."), i18n("GD is able to write PNGs"));
 312:         }
 313:         $this->storeResult($this->isPHPExtensionLoaded("pcre") == self::CON_EXTENSION_AVAILABLE, self::C_SEVERITY_ERROR, i18n("PHP PCRE Extension is not loaded"), i18n("The PHP PCRE Extension is not loaded. CONTENIDO uses PCRE-functions like preg_repace and preg_match and won't work without the PCRE Extension."), i18n("PCRE extension loaded"));
 314:         $this->storeResult($this->isPHPExtensionLoaded("xml") == self::CON_EXTENSION_AVAILABLE, self::C_SEVERITY_ERROR, i18n("PHP XML Extension is not loaded"), i18n("The PHP XML Extension is not loaded. CONTENIDO won't work without the XML Extension."), i18n("XML extension loaded"));
 315:         $this->storeResult($this->testDOMDocument(), self::C_SEVERITY_ERROR, i18n("Class 'DOMDocument' is not available"), i18n("The class DOMDocument could not be found. Please check your PHP installation and enable the XML extension if necessary. CONTENIDO won't work without it."), i18n("DOMDocument is available"));
 316:         $this->storeResult($this->testXMLParserCreate(), self::C_SEVERITY_ERROR, i18n("Function 'xml_parser_create' is not available"), i18n("The function xml_parser_create could not be found. Please check your PHP installation and enable the XML extension if necessary. CONTENIDO won't work without it."), i18n("xml_parser_create is available"));
 317:         $this->storeResult(class_exists("SimpleXMLElement") && function_exists("dom_import_simplexml"), self::C_SEVERITY_ERROR, i18n("The class SimpleXML is missing"), i18n("The SimpleXML class is missing. Make sure that the extension is installed and activated"), i18n("SimpleXML is available"));
 318:         $this->storeResult($this->isPHPExtensionLoaded("mbstring") == self::CON_EXTENSION_AVAILABLE, self::C_SEVERITY_ERROR, i18n("PHP mbstring extension is not loaded"), i18n("Since version 4.9.4 CONTENIDO requires the mbstring extension to be loaded and activated! Without it CONTENIDO won't work!"), i18n("mbstring extension is loaded"));
 319: 
 320:         $result = $this->checkImageResizer();
 321:         switch ($result) {
 322:             case self::CON_IMAGERESIZE_CANTCHECK:
 323:                 $this->storeResult(false, self::C_SEVERITY_WARNING, i18n("Unable to check for a suitable image resizer"), i18n("Setup has tried to check for a suitable image resizer (which is, for exampl, required for thumbnail creation), but was not able to clearly identify one. If thumbnails won't work, make sure you've got either the GD-extension or ImageMagick available."));
 324:                 break;
 325:             case self::CON_IMAGERESIZE_NOTHINGAVAILABLE:
 326:                 $this->storeResult(false, self::C_SEVERITY_ERROR, i18n("No suitable image resizer available"), i18n("Setup checked your image resizing support, however, it was unable to find a suitable image resizer. Thumbnails won't work correctly or won't be looking good. Install the GD-Extension or ImageMagick"));
 327:                 break;
 328:             case self::CON_IMAGERESIZE_GD:
 329:                 $this->storeResult(true, self::C_SEVERITY_WARNING, "", "", i18n("GD extension is available and usable to handle images"));
 330:                 break;
 331:             case self::CON_IMAGERESIZE_IMAGEMAGICK:
 332:                 $this->storeResult(true, self::C_SEVERITY_WARNING, "", "", i18n("ImageMagick extension is available and usable to handle images"));
 333:                 break;
 334:         }
 335: 
 336:         $this->storeResult($this->testIconv(), self::C_SEVERITY_ERROR, i18n("PHP iconv functions are not available."), i18n("PHP has been compiled with the --without-iconv directive. CONTENIDO won't work without the iconv functions."), i18n("iconv is available"));
 337: 
 338:         $result = $this->testMySQL($this->_config['db']['connection']['host'], $this->_config['db']['connection']['user'], $this->_config['db']['connection']['password']);
 339:         switch ($result) {
 340:             case self::CON_MYSQL_OK:
 341:                 $this->storeResult(true, self::C_SEVERITY_ERROR, "", "", i18n("Database connection works"));
 342:                 break;
 343:             case self::CON_MYSQL_STRICT_MODE:
 344:                 $this->storeResult(false, self::C_SEVERITY_ERROR, i18n('MySQL is running in strict mode'), i18n('MySQL is running in strict mode, CONTENIDO will not work with this mode. Please change your sql_mode!'));
 345:                 break;
 346:             default:
 347:                 $this->storeResult(false, self::C_SEVERITY_ERROR, i18n("MySQL database connect failed"), sprintf(i18n("Setup was unable to connect to the MySQL Server (Server %s, Username %s). Please correct the MySQL data and try again.<br><br>The error message given was: %s"), $this->_config['db']['connection']['host'], $this->_config['db']['connection']['user'], $result));
 348:         }
 349: 
 350:         if ($testFileSystem) {
 351:             $this->storeResult($this->testFilesystem(), self::C_SEVERITY_WARNING, i18n("Permission error"), i18n("CONTENIDO doesn't have the necessary permissions to write all the files it needs. Please check your filesystem permissions."), i18n("Filesystem checks"), i18n("CONTENIDO has all the necessary permissions to read and write files"));
 352:         }
 353:     }
 354: 
 355:     /**
 356:      * Stores a result in the messages array for later display
 357:      *
 358:      * @param bool $result true for success, false otherwise
 359:      * @param int $severity One one of the C_SEVERITY constants
 360:      * @param string $errorHeadline The headline which will be stored in the
 361:      *        case that $result is false
 362:      * @param string $errorMessage The message which will be stored in the case
 363:      *        that $result is false
 364:      * @param string $successHeadline The headline which will be stored in the
 365:      *        case that $result is true
 366:      * @param string $successMessage The message which will be stored in the
 367:      *        case that $result is true
 368:      */
 369:     public function storeResult($result, $severity, $errorHeadline = "", $errorMessage = "", $successHeadline = "", $successMessage = "") {
 370:         if ($result) {
 371:             $this->_messages[] = array(
 372:                 "result" => $result,
 373:                 "severity" => $severity,
 374:                 "headline" => $successHeadline,
 375:                 "message" => $successMessage
 376:             );
 377:         } else {
 378:             $this->_messages[] = array(
 379:                 "result" => $result,
 380:                 "severity" => $severity,
 381:                 "headline" => $errorHeadline,
 382:                 "message" => $errorMessage
 383:             );
 384:         }
 385:     }
 386: 
 387:     /**
 388:      * Returns the message array
 389:      *
 390:      * @see cSystemtest::$_messages
 391:      * @return array
 392:      */
 393:     public function getResults() {
 394:         return $this->_messages;
 395:     }
 396: 
 397:     /**
 398:      * Returns an array with information about the file, especially the file
 399:      * owner
 400:      *
 401:      * The return array looks like this:
 402:      * array(
 403:      * "info" => $info, //'s' for a socket, 'l' for a symbolic link, '-' for a
 404:      * regular file, 'b' "block special", 'd' for a directory, 'c' "character
 405:      * special", 'p' FIFO pipe, 'u' for unkown
 406:      * "type" => $type, //A more descriptive version of $info
 407:      * "owner" => array(
 408:      * "id" => $id, //the owner id
 409:      * "read" => $read, //true if the owner is allowed to read the file
 410:      * "write" => $write //true if the owner is allowed to write the file
 411:      * )
 412:      * "group" => array(
 413:      * "id" => $id, //the owner group
 414:      * "read" => $read, //true if the owner group is allowed to read the file
 415:      * "write" => $write //true if the owner group is allowed to write the file
 416:      * )
 417:      * "others" => array(
 418:      * "read" => $read, //true if others are allowed to read the file
 419:      * "write" => $write //true if others are allowed to write the file
 420:      * )
 421:      * )
 422:      *
 423:      * @param string $sFilename The path to the file
 424:      * @return boolean array if the file can't be accessed
 425:      */
 426:     protected function getFileInfo($sFilename) {
 427:         if (!cFileHandler::exists($sFilename)) {
 428:             return false;
 429:         }
 430: 
 431:         $oiFilePermissions = fileperms($sFilename);
 432:         if ($oiFilePermissions === false) {
 433:             return false;
 434:         }
 435: 
 436:         switch (true) {
 437:             case (($oiFilePermissions & 0xC000) == 0xC000):
 438:                 $info = 's';
 439:                 $type = "socket";
 440:                 break;
 441:             case (($oiFilePermissions & 0xA000) == 0xA000):
 442:                 $info = 'l';
 443:                 $type = "symbolic link";
 444:                 break;
 445:             case (($oiFilePermissions & 0x8000) == 0x8000):
 446:                 $info = '-';
 447:                 $type = "regular file";
 448:                 break;
 449:             case (($oiFilePermissions & 0x6000) == 0x6000):
 450:                 $info = 'b';
 451:                 $type = "block special";
 452:                 break;
 453:             case (($oiFilePermissions & 0x4000) == 0x4000):
 454:                 $info = 'd';
 455:                 $type = "directory";
 456:                 break;
 457:             case (($oiFilePermissions & 0x2000) == 0x2000):
 458:                 $info = 'c';
 459:                 $type = "character special";
 460:                 break;
 461:             case (($oiFilePermissions & 0x1000) == 0x1000):
 462:                 $info = 'p';
 463:                 $type = "FIFO pipe";
 464:                 break;
 465:             default:
 466:                 $info = "u";
 467:                 $type = "Unknown";
 468:                 break;
 469:         }
 470: 
 471:         $aFileinfo = array();
 472:         $aFileinfo["info"] = $info;
 473:         $aFileinfo["type"] = $type;
 474:         $aFileinfo["owner"]["read"] = ($oiFilePermissions & 0x0100) ? true : false;
 475:         $aFileinfo["owner"]["write"] = ($oiFilePermissions & 0x0080) ? true : false;
 476:         $aFileinfo["group"]["read"] = ($oiFilePermissions & 0x0020) ? true : false;
 477:         $aFileinfo["group"]["write"] = ($oiFilePermissions & 0x0010) ? true : false;
 478:         $aFileinfo["others"]["read"] = ($oiFilePermissions & 0x0004) ? true : false;
 479:         $aFileinfo["others"]["write"] = ($oiFilePermissions & 0x0002) ? true : false;
 480:         $aFileinfo["owner"]["id"] = fileowner($sFilename);
 481:         $aFileinfo["group"]["id"] = filegroup($sFilename);
 482:         return ($aFileinfo);
 483:     }
 484: 
 485:     /**
 486:      * Returns true if the file is writeable
 487:      *
 488:      * @param string $filename The path to the file
 489:      * @return boolean
 490:      */
 491:     protected function canWriteFile($filename) {
 492:         clearstatcache();
 493:         if (is_file($filename)) {
 494:             return is_writable($filename);
 495:         } else {
 496:             return is_writable(dirname($filename));
 497:         }
 498:     }
 499: 
 500:     /**
 501:      * Returns true if the given file is a directory and if it is writeable
 502:      *
 503:      * @param string $dirname The path to the directory
 504:      * @return boolean
 505:      */
 506:     protected function canWriteDir($dirname) {
 507:         clearstatcache();
 508:         return is_dir($dirname) && is_writable($dirname);
 509:     }
 510: 
 511:     /**
 512:      * Returns the current user which runs the PHP interpreter
 513:      *
 514:      * @return number boolean ID or false if unable to determine the user
 515:      */
 516:     protected function getServerUID() {
 517:         if (function_exists("posix_getuid")) {
 518:             return posix_getuid();
 519:         }
 520: 
 521:         $sFilename = md5(mt_rand()) . ".txt";
 522: 
 523:         if (is_writeable(".")) {
 524:             cFileHandler::create($sFilename, "test");
 525:             $iUserId = fileowner($sFilename);
 526:             cFileHandler::remove($sFilename);
 527: 
 528:             return ($iUserId);
 529:         } else {
 530:             if (is_writeable("/tmp/")) {
 531:                 cFileHandler::create("/tmp/" . $sFilename, "w");
 532:                 $iUserId = fileowner("/tmp/" . $sFilename);
 533:                 cFileHandler::remove("/tmp/" . $sFilename);
 534: 
 535:                 return ($iUserId);
 536:             }
 537:             return false;
 538:         }
 539:     }
 540: 
 541:     /**
 542:      * Returns the current group which runs the PHP interpreter
 543:      *
 544:      * @return number boolean ID or false if unable to determine the group
 545:      */
 546:     protected function getServerGID() {
 547:         if (function_exists("posix_getgid")) {
 548:             return posix_getgid();
 549:         }
 550: 
 551:         $sFilename = md5(mt_rand()) . ".txt";
 552: 
 553:         if (is_writeable(".")) {
 554:             cFileHandler::create($sFilename, "test");
 555:             $iUserId = filegroup($sFilename);
 556:             cFileHandler::remove($sFilename);
 557: 
 558:             return ($iUserId);
 559:         } else {
 560:             return false;
 561:         }
 562:     }
 563: 
 564:     /**
 565:      * Returns one of the CON_PREDICT suggestions depending on the permissions
 566:      * of the given file
 567:      *
 568:      * @param string $file The path to the file
 569:      * @return int CON_PREDICT_*
 570:      */
 571:     protected function predictCorrectFilepermissions($file) {
 572:         // Check if the system is a windows system. If yes, we can't predict
 573:         // anything.
 574:         if ($this->isWindows()) {
 575:             return self::CON_PREDICT_WINDOWS;
 576:         }
 577: 
 578:         // Check if the file is read- and writeable. If yes, we don't need to do
 579:         // any
 580:         // further checks.
 581:         if (is_writable($file) && is_readable($file)) {
 582:             return self::CON_PREDICT_SUFFICIENT;
 583:         }
 584: 
 585:         // If we can't find out the web server UID, we cannot predict the
 586:         // correct
 587:         // mask.
 588:         $iServerUID = $this->getServerUID();
 589:         if ($iServerUID === false) {
 590:             return self::CON_PREDICT_NOTPREDICTABLE;
 591:         }
 592: 
 593:         // If we can't find out the web server GID, we cannot predict the
 594:         // correct
 595:         // mask.
 596:         $iServerGID = $this->getServerGID();
 597:         if ($iServerGID === false) {
 598:             return self::CON_PREDICT_NOTPREDICTABLE;
 599:         }
 600: 
 601:         $aFilePermissions = $this->getFileInfo($file);
 602: 
 603:         if ($this->getSafeModeStatus()) {
 604:             // SAFE-Mode related checks
 605:             if ($iServerUID == $aFilePermissions["owner"]["id"]) {
 606:                 return self::CON_PREDICT_CHANGEPERM_SAMEOWNER;
 607:             }
 608: 
 609:             if ($this->getSafeModeGidStatus()) {
 610:                 // SAFE-Mode GID related checks
 611:                 if ($iServerGID == $aFilePermissions["group"]["id"]) {
 612:                     return self::CON_PREDICT_CHANGEPERM_SAMEGROUP;
 613:                 }
 614: 
 615:                 return self::CON_PREDICT_CHANGEGROUP;
 616:             }
 617:         } else {
 618:             // Regular checks
 619:             if ($iServerUID == $aFilePermissions["owner"]["id"]) {
 620:                 return self::CON_PREDICT_CHANGEPERM_SAMEOWNER;
 621:             }
 622: 
 623:             if ($iServerGID == $aFilePermissions["group"]["id"]) {
 624:                 return self::CON_PREDICT_CHANGEPERM_SAMEGROUP;
 625:             }
 626: 
 627:             return self::CON_PREDICT_CHANGEPERM_OTHERS;
 628:         }
 629:     }
 630: 
 631:     /**
 632:      * Gets a PHP setting with ini_get
 633:      *
 634:      * @param string $setting A PHP setting
 635:      * @return mixed The value of the PHP setting or NULL if ini_get is disabled
 636:      */
 637:     protected function getPHPIniSetting($setting) {
 638:         // Avoid errors if ini_get is in the disable_functions directive
 639:         $value = @ini_get($setting);
 640: 
 641:         return $value;
 642:     }
 643: 
 644:     /**
 645:      * Converts a string like "12M" to the correct number of bytes
 646:      *
 647:      * @param string $val A string in the form of "12K", "12M" or "12G"
 648:      * @return number
 649:      */
 650:     protected function getAsBytes($val) {
 651:         if (strlen($val) == 0) {
 652:             return 0;
 653:         }
 654:         $val = trim($val);
 655:         $last = $val{strlen($val) - 1};
 656:         switch ($last) {
 657:             case 'k':
 658:             case 'K':
 659:                 return (int) $val * 1024;
 660:                 break;
 661:             case 'm':
 662:             case 'M':
 663:                 return (int) $val * 1048576;
 664:                 break;
 665:             case 'g':
 666:             case 'G':
 667:                 return (int) $val * 1048576 * 1024;
 668:                 break;
 669:             default:
 670:                 return $val;
 671:         }
 672:     }
 673: 
 674:     /**
 675:      * Connects to the database with the given settings
 676:      *
 677:      * @param string $host The database host
 678:      * @param string $username The database user
 679:      * @param string $password The database user password
 680:      * @return boolean cDb an array with the cDB object on the first place and a
 681:      *         boolean on the second
 682:      */
 683:     protected function doMySQLConnect($host, $username, $password) {
 684:         $aOptions = array(
 685:             'connection' => array(
 686:                 'host' => $host,
 687:                 'user' => $username,
 688:                 'password' => $password
 689:             )
 690:         );
 691:         try {
 692:             $db = new cDb($aOptions);
 693:         } catch (cDbException $e) {
 694:             return array(
 695:                 $db,
 696:                 false
 697:             );
 698:         }
 699: 
 700:         if ($db->connect() == 0) {
 701:             return array(
 702:                 $db,
 703:                 false
 704:             );
 705:         } else {
 706:             return array(
 707:                 $db,
 708:                 true
 709:             );
 710:         }
 711:     }
 712: 
 713:     /**
 714:      * Checks if a given extension is loaded.
 715:      *
 716:      * @param string $extension A PHP extension
 717:      * @return int Returns one of the CON_EXTENSION constants
 718:      */
 719:     public function isPHPExtensionLoaded($extension) {
 720:         $value = extension_loaded($extension);
 721: 
 722:         if ($value === NULL) {
 723:             return self::CON_EXTENSION_CANTCHECK;
 724:         }
 725: 
 726:         if ($value === true) {
 727:             return self::CON_EXTENSION_AVAILABLE;
 728:         }
 729: 
 730:         if ($value === false) {
 731:             return self::CON_EXTENSION_UNAVAILABLE;
 732:         }
 733:     }
 734: 
 735:     /**
 736:      * Returns true if the interpreter is run on Windows
 737:      *
 738:      * @return boolean
 739:      */
 740:     public function isWindows() {
 741:         if (strtolower(substr(PHP_OS, 0, 3)) == "win") {
 742:             return true;
 743:         } else {
 744:             return false;
 745:         }
 746:     }
 747: 
 748:     /**
 749:      * Test PHP function
 750:      *
 751:      * @return boolean true if the test passed and false if not
 752:      */
 753:     public function testPHPVersion() {
 754:         if (version_compare(phpversion(), CON_SETUP_MIN_PHP_VERSION, '>=') == true) {
 755:             return true;
 756:         } else {
 757:             return false;
 758:         }
 759:     }
 760: 
 761:     /**
 762:      *
 763:      * @return boolean true if the test passed and false if not
 764:      */
 765:     public function getSafeModeStatus() {
 766:         if ($this->getPHPIniSetting("safe_mode") == "1") {
 767:             return true;
 768:         } else {
 769:             return false;
 770:         }
 771:     }
 772: 
 773:     /**
 774:      *
 775:      * @return boolean true if the test passed and false if not
 776:      */
 777:     public function getSafeModeGidStatus() {
 778:         if ($this->getPHPIniSetting("safe_mode_gid") == "1") {
 779:             return true;
 780:         } else {
 781:             return false;
 782:         }
 783:     }
 784: 
 785:     /**
 786:      *
 787:      * @return boolean true if the test passed and false if not
 788:      */
 789:     public function testXMLParserCreate() {
 790:         return function_exists("xml_parser_create");
 791:     }
 792: 
 793:     /**
 794:      *
 795:      * @return boolean true if the test passed and false if not
 796:      */
 797:     public function testFileUploadSetting() {
 798:         return $this->getPHPIniSetting('file_uploads');
 799:     }
 800: 
 801:     /**
 802:      *
 803:      * @return boolean true if the test passed and false if not
 804:      */
 805:     public function testMagicQuotesRuntimeSetting() {
 806:         return !$this->getPHPIniSetting('magic_quotes_runtime');
 807:     }
 808: 
 809:     /**
 810:      *
 811:      * @return boolean true if the test passed and false if not
 812:      */
 813:     public function testMagicQuotesSybaseSetting() {
 814:         return !$this->getPHPIniSetting('magic_quotes_sybase');
 815:     }
 816: 
 817:     /**
 818:      *
 819:      * @return boolean true if the test passed and false if not
 820:      */
 821:     public function testMaxExecutionTime() {
 822:         return intval($this->getPHPIniSetting('max_execution_time')) >= 30;
 823:     }
 824: 
 825:     /**
 826:      *
 827:      * @return boolean true if the test passed and false if not
 828:      */
 829:     public function testZIPArchive() {
 830:         return class_exists("ZipArchive");
 831:     }
 832: 
 833:     /**
 834:      *
 835:      * @return boolean true if the test passed and false if not
 836:      */
 837:     public function testMemoryLimit() {
 838:         $memoryLimit = $this->getAsBytes($this->getPHPIniSetting("memory_limit"));
 839:         return ($memoryLimit > 1024 * 1024 * 32) || ($memoryLimit == 0);
 840:     }
 841: 
 842:     /**
 843:      *
 844:      * @return boolean true if the test passed and false if not
 845:      */
 846:     public function testPHPSQLSafeMode() {
 847:         return !$this->getPHPIniSetting('sql.safe_mode');
 848:     }
 849: 
 850:     /**
 851:      *
 852:      * @return boolean true if the test passed and false if not
 853:      */
 854:     public function testDOMDocument() {
 855:         return class_exists("DOMDocument");
 856:     }
 857: 
 858:     /**
 859:      *
 860:      * @param string $ext
 861:      * @return bool true if the test passed and false if not
 862:      */
 863:     public function testPHPExtension($ext) {
 864:         return $this->isPHPExtensionLoaded($ext) == CON_EXTENSION_AVAILABLE;
 865:     }
 866: 
 867:     /**
 868:      *
 869:      * @return boolean true if the test passed and false if not
 870:      */
 871:     public function testIconv() {
 872:         return function_exists("iconv");
 873:     }
 874: 
 875:     /**
 876:      *
 877:      * @return boolean true if the test passed and false if not
 878:      */
 879:     public function testGDGIFRead() {
 880:         if (($this->isPHPExtensionLoaded('gd') != self::CON_EXTENSION_AVAILABLE) && ($this->isPHPExtensionLoaded('gd') != self::CON_EXTENSION_CANTCHECK)) {
 881:             return false;
 882:         }
 883:         return function_exists("imagecreatefromgif");
 884:     }
 885: 
 886:     /**
 887:      *
 888:      * @return boolean true if the test passed and false if not
 889:      */
 890:     public function testGDGIFWrite() {
 891:         if (($this->isPHPExtensionLoaded('gd') != self::CON_EXTENSION_AVAILABLE) && ($this->isPHPExtensionLoaded('gd') != self::CON_EXTENSION_CANTCHECK)) {
 892:             return false;
 893:         }
 894:         return function_exists("imagegif");
 895:     }
 896: 
 897:     /**
 898:      *
 899:      * @return boolean true if the test passed and false if not
 900:      */
 901:     public function testGDJPEGRead() {
 902:         if (($this->isPHPExtensionLoaded('gd') != self::CON_EXTENSION_AVAILABLE) && ($this->isPHPExtensionLoaded('gd') != self::CON_EXTENSION_CANTCHECK)) {
 903:             return false;
 904:         }
 905:         return function_exists("imagecreatefromjpeg");
 906:     }
 907: 
 908:     /**
 909:      *
 910:      * @return boolean true if the test passed and false if not
 911:      */
 912:     public function testGDJPEGWrite() {
 913:         if (($this->isPHPExtensionLoaded('gd') != self::CON_EXTENSION_AVAILABLE) && ($this->isPHPExtensionLoaded('gd') != self::CON_EXTENSION_CANTCHECK)) {
 914:             return false;
 915:         }
 916:         return function_exists("imagejpeg");
 917:     }
 918: 
 919:     /**
 920:      *
 921:      * @return boolean true if the test passed and false if not
 922:      */
 923:     public function testGDPNGRead() {
 924:         if (($this->isPHPExtensionLoaded('gd') != self::CON_EXTENSION_AVAILABLE) && ($this->isPHPExtensionLoaded('gd') != self::CON_EXTENSION_CANTCHECK)) {
 925:             return false;
 926:         }
 927:         return function_exists("imagecreatefrompng");
 928:     }
 929: 
 930:     /**
 931:      *
 932:      * @return boolean true if the test passed and false if not
 933:      */
 934:     public function testGDPNGWrite() {
 935:         if (($this->isPHPExtensionLoaded('gd') != self::CON_EXTENSION_AVAILABLE) && ($this->isPHPExtensionLoaded('gd') != self::CON_EXTENSION_CANTCHECK)) {
 936:             return false;
 937:         }
 938:         return function_exists("imagepng");
 939:     }
 940: 
 941:     /**
 942:      *
 943:      * @return boolean true if the test passed and false if not
 944:      */
 945:     public function testMySQLExtension() {
 946:         if ($this->isPHPExtensionLoaded("mysql") == self::CON_EXTENSION_AVAILABLE) {
 947:             return true;
 948:         } else {
 949:             return false;
 950:         }
 951:     }
 952: 
 953:     /**
 954:      *
 955:      * @return boolean true if the test passed and false if not
 956:      */
 957:     public function testMySQLiExtension() {
 958:         if ($this->isPHPExtensionLoaded("mysqli") == self::CON_EXTENSION_AVAILABLE) {
 959:             return true;
 960:         } else {
 961:             return false;
 962:         }
 963:     }
 964: 
 965:     /**
 966:      *
 967:      * @param string $host
 968:      * @param string $username
 969:      * @param string $password
 970:      * @return boolean true if the test passed and false if not
 971:      */
 972:     public function testMySQLModeStrict($host, $username, $password) {
 973:         // host, user and password
 974:         $dbCfg = array(
 975:             'connection' => array(
 976:                 'host' => $host,
 977:                 'user' => $username,
 978:                 'password' => $password
 979:             )
 980:         );
 981: 
 982:         $db = new cDb($dbCfg);
 983:         $db->query('SELECT LOWER(@@GLOBAL.sql_mode) AS sql_mode');
 984:         if ($db->nextRecord()) {
 985:             if (strpos($db->f('sql_mode'), 'strict_trans_tables') !== false || strpos($db->f('sql_mode'), 'strict_all_tables') !== false) {
 986:                 return false;
 987:             }
 988:         }
 989:         return true;
 990:     }
 991: 
 992:     /**
 993:      *
 994:      * @param string $host
 995:      * @param string $username
 996:      * @param string $password
 997:      * @return int 1 if the test passed and > 1 if not
 998:      */
 999:     public function testMySQL($host, $username, $password) {
1000:         list($handle, $status) = $this->doMySQLConnect($host, $username, $password);
1001: 
1002:         $errorMessage = "";
1003:         if ($this->testMySQLiExtension() && !$this->testMySQLExtension()) {
1004:             $errorMessage = mysqli_error($handle->getLinkId());
1005:         } else {
1006:             $errorMessage = mysql_error();
1007:         }
1008:         if ($errorMessage != "") {
1009:             return $errorMessage;
1010:         }
1011: 
1012:         if (false === isset($handle) || $handle->getLinkId()->errno == 1045) {
1013:             return self::CON_MYSQL_CANT_CONNECT;
1014:         }
1015: 
1016:         if (!$this->testMySQLModeStrict($host, $username, $password)) {
1017:             return self::CON_MYSQL_STRICT_MODE;
1018:         }
1019: 
1020:         return self::CON_MYSQL_OK;
1021:     }
1022: 
1023:     /**
1024:      *
1025:      * @param bool $testConfig
1026:      * @param bool $testFrontend
1027:      * @return bool true if the test passed and false if not
1028:      */
1029:     public function testFilesystem($testConfig = true, $testFrontend = true) {
1030:         global $cfgClient;
1031: 
1032:         $status = true;
1033: 
1034:         $files = array(
1035:             // check files
1036:             array(
1037:                 'filename' => $this->_config['path']['contenido_logs'] . "errorlog.txt",
1038:                 'severity' => self::C_SEVERITY_WARNING
1039:             ),
1040:             array(
1041:                 'filename' => $this->_config['path']['contenido_logs'] . "setuplog.txt",
1042:                 'severity' => self::C_SEVERITY_WARNING
1043:             ),
1044:             array(
1045:                 'filename' => $this->_config['path']['contenido_cronlog'] . "pseudo-cron.log",
1046:                 'severity' => self::C_SEVERITY_WARNING
1047:             ),
1048:             array(
1049:                 'filename' => $this->_config['path']['contenido_cronlog'] . "session_cleanup.php.job",
1050:                 'severity' => self::C_SEVERITY_WARNING
1051:             ),
1052:             array(
1053:                 'filename' => $this->_config['path']['contenido_cronlog'] . "send_reminder.php.job",
1054:                 'severity' => self::C_SEVERITY_WARNING
1055:             ),
1056:             array(
1057:                 'filename' => $this->_config['path']['contenido_cronlog'] . "optimize_database.php.job",
1058:                 'severity' => self::C_SEVERITY_WARNING
1059:             ),
1060:             array(
1061:                 'filename' => $this->_config['path']['contenido_cronlog'] . "move_old_stats.php.job",
1062:                 'severity' => self::C_SEVERITY_WARNING
1063:             ),
1064:             array(
1065:                 'filename' => $this->_config['path']['contenido_cronlog'] . "move_articles.php.job",
1066:                 'severity' => self::C_SEVERITY_WARNING
1067:             ),
1068:             array(
1069:                 'filename' => $this->_config['path']['contenido_cronlog'] . "linkchecker.php.job",
1070:                 'severity' => self::C_SEVERITY_WARNING
1071:             ),
1072:             array(
1073:                 'filename' => $this->_config['path']['contenido_cronlog'] . "run_newsletter_job.php.job",
1074:                 'severity' => self::C_SEVERITY_WARNING
1075:             ),
1076:             array(
1077:                 'filename' => $this->_config['path']['contenido_cronlog'] . "setfrontenduserstate.php.job",
1078:                 'severity' => self::C_SEVERITY_WARNING
1079:             ),
1080:             array(
1081:                 'filename' => $this->_config['path']['contenido_cronlog'] . "advance_workflow.php.job",
1082:                 'severity' => self::C_SEVERITY_WARNING
1083:             ),
1084:             array(
1085:                 'filename' => $this->_config['path']['contenido_cache'],
1086:                 'severity' => self::C_SEVERITY_WARNING,
1087:                 'dir' => true
1088:             ),
1089:             array(
1090:                 'filename' => $this->_config['path']['contenido_temp'],
1091:                 'severity' => self::C_SEVERITY_WARNING,
1092:                 'dir' => true
1093:             ),
1094:             array(
1095:                 'filename' => $this->_config['path']['contenido_config'] . "config.php",
1096:                 'severity' => self::C_SEVERITY_ERROR,
1097:                 'config' => $testConfig
1098:             )
1099:         );
1100: 
1101:         $frontendFiles = array(
1102:             "cache",
1103:             "cache/code",
1104:             "css",
1105:             "data",
1106:             "data/layouts",
1107:             "data/logs",
1108:             "data/modules",
1109:             "data/version",
1110:             "data/version/css",
1111:             "data/version/js",
1112:             "data/version/layout",
1113:             "data/version/module",
1114:             "data/version/templates",
1115:             "js",
1116:             "templates",
1117:             "upload"
1118:         );
1119: 
1120:         $ret = true;
1121:         foreach ($files as $key => $file) {
1122: 
1123:             $name = $file['filename'];
1124:             $severity = $file['severity'];
1125:             $dir = $file['dir'];
1126:             $frontend = $file['frontend'];
1127:             $config = $file['config'];
1128: 
1129:             if (array_key_exists('frontend', $file) && $frontend != false) {
1130:                 $ret = $this->testSingleFile($name, $severity, $frontend);
1131:             } else if (array_key_exists('config', $file) && $config != false) {
1132:                 $ret = $this->testSingleFile($name, $severity);
1133:             } else if (!array_key_exists('frontend', $file) && !array_key_exists('config', $file)) {
1134:                 $ret = $this->testSingleFile($name, $severity, $config);
1135:             }
1136:             if ($ret == false) {
1137:                 $status = false;
1138:             }
1139:         }
1140: 
1141:         if ($testFrontend) {
1142:             foreach ($cfgClient as $oneClient) {
1143:                 if (!is_array($oneClient)) {
1144:                     continue;
1145:                 }
1146:                 foreach ($frontendFiles as $file) {
1147: 
1148:                     // If data/layouts or data/modules not exist, do not display an error message
1149:                     // Cause: At CONTENIDO 4.8 both folders do not exist
1150:                     if (($file == "data/layouts" || $file == "data/modules") && !is_dir($oneClient["path"]["frontend"] . $file)) {
1151:                         continue;
1152:                     } else {
1153:                         $ret = $this->testSingleFile($oneClient["path"]["frontend"] . $file, self::C_SEVERITY_WARNING, true);
1154:                     }
1155: 
1156:                     if ($ret == false) {
1157:                         $status = false;
1158:                     }
1159:                 }
1160:             }
1161:         }
1162: 
1163:         return $status;
1164:     }
1165: 
1166:     /**
1167:      * Checks a single file or directory wether it is writeable or not
1168:      *
1169:      * @param string $filename The file
1170:      * @param int $severity The resulting C_SEVERITY constant should the test
1171:      *        fail
1172:      * @param bool $dir True if the $filename is a directory
1173:      * @throws Exception Throws a generic Exception in the event that the
1174:      *         permissions are wrong
1175:      * @return boolean Returns true if everything is fine
1176:      */
1177:     protected function testSingleFile($filename, $severity, $dir = false) {
1178:         if (strpos($filename, $this->_config["path"]["frontend"]) === 0) {
1179:             $length = strlen($this->_config["path"]["frontend"]) + 1;
1180:             $shortFilename = substr($filename, $length);
1181:         } else { // for dirs
1182:             $shortFilename = $filename;
1183:         }
1184: 
1185:         if (!$dir) {
1186:             $status = $this->canWriteFile($filename);
1187:         } else {
1188:             $status = $this->canWriteDir($filename);
1189:         }
1190: 
1191:         $title = sprintf(i18n("Can't write %s"), $shortFilename);
1192:         $message = sprintf(i18n("Setup or CONTENIDO can't write to the file %s. Please change the file permissions to correct this problem."), $shortFilename);
1193: 
1194:         if ($status == false) {
1195:             if (cFileHandler::exists($filename)) {
1196:                 $perm = $this->predictCorrectFilepermissions($filename);
1197: 
1198:                 switch ($perm) {
1199:                     case self::CON_PREDICT_WINDOWS:
1200:                         $predictMessage = i18n("Your Server runs Windows. Due to that, Setup can't recommend any file permissions.");
1201:                         break;
1202:                     case self::CON_PREDICT_NOTPREDICTABLE:
1203:                         $predictMessage = sprintf(i18n("Due to a very restrictive environment, an advise is not possible. Ask your system administrator to enable write access to the file %s, especially in environments where ACL (Access Control Lists) are used."), $shortFilename);
1204:                         break;
1205:                     case self::CON_PREDICT_CHANGEPERM_SAMEOWNER:
1206:                         $mfileperms = substr(sprintf("%o", fileperms($filename)), -3);
1207:                         $mfileperms{0} = intval($mfileperms{0}) | 0x6;
1208:                         $predictMessage = sprintf(i18n("Your web server and the owner of your files are identical. You need to enable write access for the owner, e.g. using chmod u+rw %s, setting the file mask to %s or set the owner to allow writing the file."), $shortFilename, $mfileperms);
1209:                         break;
1210:                     case self::CON_PREDICT_CHANGEPERM_SAMEGROUP:
1211:                         $mfileperms = substr(sprintf("%o", fileperms($filename)), -3);
1212:                         $mfileperms{1} = intval($mfileperms{1}) | 0x6;
1213:                         $predictMessage = sprintf(i18n("Your web server's group and the group of your files are identical. You need to enable write access for the group, e.g. using chmod g+rw %s, setting the file mask to %s or set the group to allow writing the file."), $shortFilename, $mfileperms);
1214:                         break;
1215:                     case self::CON_PREDICT_CHANGEPERM_OTHERS:
1216:                         $mfileperms = substr(sprintf("%o", fileperms($filename)), -3);
1217:                         $mfileperms{2} = intval($mfileperms{2}) | 0x6;
1218:                         $predictMessage = sprintf(i18n("Your web server is not equal to the file owner, and is not in the webserver's group. It would be highly insecure to allow world write acess to the files. If you want to install anyways, enable write access for all others, e.g. using chmod o+rw %s, setting the file mask to %s or set the others to allow writing the file."), $shortFilename, $mfileperms);
1219:                         break;
1220:                 }
1221:             } else {
1222:                 $target = dirname($filename);
1223: 
1224:                 $perm = $this->predictCorrectFilepermissions($target);
1225: 
1226:                 switch ($perm) {
1227:                     case self::CON_PREDICT_WINDOWS:
1228:                         $predictMessage = i18n("Your Server runs Windows. Due to that, Setup can't recommend any directory permissions.");
1229:                         break;
1230:                     case self::CON_PREDICT_NOTPREDICTABLE:
1231:                         $predictMessage = sprintf(i18n("Due to a very restrictive environment, an advise is not possible. Ask your system administrator to enable write access to the file or directory %s, especially in environments where ACL (Access Control Lists) are used."), dirname($shortFilename));
1232:                         break;
1233:                     case self::CON_PREDICT_CHANGEPERM_SAMEOWNER:
1234:                         $mfileperms = substr(sprintf("%o", @fileperms($target)), -3);
1235:                         $mfileperms{0} = intval($mfileperms{0}) | 0x6;
1236:                         $predictMessage = sprintf(i18n("Your web server and the owner of your directory are identical. You need to enable write access for the owner, e.g. using chmod u+rw %s, setting the directory mask to %s or set the owner to allow writing the directory."), dirname($shortFilename), $mfileperms);
1237:                         break;
1238:                     case self::CON_PREDICT_CHANGEPERM_SAMEGROUP:
1239:                         $mfileperms = substr(sprintf("%o", @fileperms($target)), -3);
1240:                         $mfileperms{1} = intval($mfileperms{1}) | 0x6;
1241:                         $predictMessage = sprintf(i18n("Your web server's group and the group of your directory are identical. You need to enable write access for the group, e.g. using chmod g+rw %s, setting the directory mask to %s or set the group to allow writing the directory."), dirname($shortFilename), $mfileperms);
1242:                         break;
1243:                     case self::CON_PREDICT_CHANGEPERM_OTHERS:
1244:                         $mfileperms = substr(sprintf("%o", @fileperms($target)), -3);
1245:                         $mfileperms{2} = intval($mfileperms{2}) | 0x6;
1246:                         $predictMessage = sprintf(i18n("Your web server is not equal to the directory owner, and is not in the webserver's group. It would be highly insecure to allow world write acess to the directory. If you want to install anyways, enable write access for all others, e.g. using chmod o+rw %s, setting the directory mask to %s or set the others to allow writing the directory."), dirname($shortFilename), $mfileperms);
1247:                         break;
1248:                 }
1249:             }
1250: 
1251:             $this->storeResult(false, $severity, $title, $message . "<br><br>" . $predictMessage);
1252:             if ($title && $message) {
1253:                 $status = false;
1254:             }
1255:         }
1256: 
1257:         return $status;
1258:     }
1259: 
1260:     /**
1261:      *
1262:      * @return boolean true if the test passed and false if not
1263:      */
1264:     public function testFrontendFolderCreation() {
1265:         $directories = array(
1266:             "cms/cache",
1267:             "cms/cache/code",
1268:             "cms/css",
1269:             "cms/data",
1270:             "cms/data/layouts",
1271:             "cms/data/modules",
1272:             "cms/data/version",
1273:             "cms/data/version/css",
1274:             "cms/data/version/js",
1275:             "cms/data/version/layout",
1276:             "cms/data/version/module",
1277:             "cms/data/version/templates",
1278:             "cms/js",
1279:             "cms/templates",
1280:             "cms/upload"
1281:         );
1282: 
1283:         $ret = true;
1284: 
1285:         foreach ($directories as $dir) {
1286:             if (!cFileHandler::exists("../" . $dir)) {
1287:                 if (!mkdir("../" . $dir)) {
1288:                     $ret = false;
1289:                     $this->storeResult(false, self::C_SEVERITY_WARNING, sprintf(i18n("Could not find or create directory %s"), $dir), i18n("The frontend expects certain directories to exist and it needs to be able to write to these directories."));
1290:                 } else {
1291:                     if (!cFileHandler::chmod("../" . $dir, "777")) {
1292:                         $ret = false;
1293:                         $this->storeResult(false, self::C_SEVERITY_WARNING, sprintf(i18n("Could not find or create directory %s"), $dir), i18n("The frontend expects certain directories to exist and it needs to be able to write to these directories."));
1294:                     }
1295:                 }
1296:             }
1297:         }
1298: 
1299:         return $ret;
1300:     }
1301: 
1302:     /**
1303:      * Checks for the open_basedir directive and returns one of the CON_BASEDIR
1304:      * constants
1305:      *
1306:      * @return int
1307:      */
1308:     public function checkOpenBasedirCompatibility() {
1309:         $value = $this->getPHPIniSetting("open_basedir");
1310: 
1311:         if ($this->isWindows()) {
1312:             $aBasedirEntries = explode(";", $value);
1313:         } else {
1314:             $aBasedirEntries = explode(":", $value);
1315:         }
1316: 
1317:         if (count($aBasedirEntries) == 1 && $aBasedirEntries[0] == $value) {
1318:             return self::CON_BASEDIR_NORESTRICTION;
1319:         }
1320: 
1321:         if (in_array(".", $aBasedirEntries) && count($aBasedirEntries) == 1) {
1322:             return self::CON_BASEDIR_DOTRESTRICTION;
1323:         }
1324: 
1325:         $sCurrentDirectory = getcwd();
1326: 
1327:         foreach ($aBasedirEntries as $entry) {
1328:             if (stristr($sCurrentDirectory, $entry)) {
1329:                 return self::CON_BASEDIR_RESTRICTIONSUFFICIENT;
1330:             }
1331:         }
1332: 
1333:         return self::CON_BASEDIR_INCOMPATIBLE;
1334:     }
1335: 
1336:     /**
1337:      * Checks the available image resizer classes and functions
1338:      *
1339:      * @return int Returns one of the CON_IMAGERESIZE constants
1340:      */
1341:     public function checkImageResizer() {
1342:         $iGDStatus = $this->isPHPExtensionLoaded('gd');
1343: 
1344:         if ($iGDStatus == self::CON_EXTENSION_AVAILABLE) {
1345:             return self::CON_IMAGERESIZE_GD;
1346:         }
1347: 
1348:         if (function_exists('imagecreate')) {
1349:             return self::CON_IMAGERESIZE_GD;
1350:         }
1351: 
1352:         if(function_exists("checkAndInclude")) {
1353:             checkAndInclude($this->_config['path']['contenido'] . 'includes/functions.api.images.php');
1354:         } else {
1355:             cInclude('includes', 'functions.api.images.php');
1356:         }
1357:         if (capiIsImageMagickAvailable()) {
1358:             return self::CON_IMAGERESIZE_IMAGEMAGICK;
1359:         }
1360: 
1361:         if ($iGDStatus === self::CON_EXTENSION_CANTCHECK) {
1362:             return self::CON_IMAGERESIZE_CANTCHECK;
1363:         } else {
1364:             return self::CON_IMAGERESIZE_NOTHINGAVAILABLE;
1365:         }
1366:     }
1367: 
1368:     /**
1369:      *
1370:      * @param string $setupType
1371:      * @param string $databaseName
1372:      * @param string $databasePrefix
1373:      */
1374:     public function checkSetupMysql($setupType, $databaseName, $databasePrefix, $charset = '', $collation = '') {
1375:         switch ($setupType) {
1376:             case "setup":
1377: 
1378:                 $db = getSetupMySQLDBConnection(false);
1379: 
1380:                 // Check if the database exists
1381:                 $status = checkMySQLDatabaseExists($db, $databaseName);
1382: 
1383:                 if ($status) {
1384:                     // Yes, database exists
1385:                     $db = getSetupMySQLDBConnection();
1386:                     $db->connect();
1387: 
1388:                     // Check if data already exists
1389:                     $db->query('SHOW TABLES LIKE "%s_actions"', $databasePrefix);
1390: 
1391:                     if ($db->nextRecord()) {
1392:                         $this->storeResult(false, cSystemtest::C_SEVERITY_ERROR, i18n("MySQL database already exists and seems to be filled", "setup"), sprintf(i18n("Setup checked the database %s and found the table %s. It seems that you already have a CONTENIDO installation in this database. If you want to install anyways, change the database prefix. If you want to upgrade from a previous version, choose 'upgrade' as setup type.", "setup"), $databaseName, sprintf("%s_actions", $databasePrefix)));
1393:                         return;
1394:                     }
1395: 
1396:                     // Check if data already exists
1397:                     $db->query('SHOW TABLES LIKE "%s_test"', $databasePrefix);
1398:                     if ($db->nextRecord()) {
1399:                         $this->storeResult(false, cSystemtest::C_SEVERITY_ERROR, i18n("MySQL test table already exists in the database", "setup"), sprintf(i18n("Setup checked the database %s and found the test table %s. Please remove it before continuing.", "setup"), $databaseName, sprintf("%s_test", $databasePrefix)));
1400:                         return;
1401:                     }
1402: 
1403:                     // Good, table doesn't exist. Check for database permisions
1404:                     $status = checkMySQLTableCreation($db, $databaseName, sprintf("%s_test", $databasePrefix));
1405:                     if (!$status) {
1406:                         $this->storeResult(false, cSystemtest::C_SEVERITY_ERROR, i18n("Unable to create tables in the selected MySQL database", "setup"), sprintf(i18n("Setup tried to create a test table in the database %s and failed. Please assign table creation permissions to the database user you entered, or ask an administrator to do so.", "setup"), $databaseName));
1407:                         return;
1408:                     }
1409: 
1410:                     // Good, we could create a table. Now remove it again
1411:                     $status = checkMySQLDropTable($db, $databaseName, sprintf("%s_test", $databasePrefix));
1412:                     if (!$status) {
1413:                         $this->storeResult(false, cSystemtest::C_SEVERITY_WARNING, i18n("Unable to remove the test table", "setup"), sprintf(i18n("Setup tried to remove the test table %s in the database %s and failed due to insufficient permissions. Please remove the table %s manually.", "setup"), sprintf("%s_test", $databasePrefix), $databaseName, sprintf("%s_test", $databasePrefix)));
1414:                     }
1415:                 } else {
1416:                     $db->connect();
1417:                     // Check if database can be created
1418:                     $status = checkMySQLDatabaseCreation($db, $databaseName, $charset, $collation);
1419:                     if (!$status) {
1420:                         $this->storeResult(false, cSystemtest::C_SEVERITY_ERROR, i18n("Unable to create the database in the MySQL server", "setup"), sprintf(i18n("Setup tried to create a test database and failed. Please assign database creation permissions to the database user you entered, ask an administrator to do so, or create the database manually.", "setup")));
1421:                         return;
1422:                     }
1423: 
1424:                     // Check for database permisions
1425:                     $status = checkMySQLTableCreation($db, $databaseName, sprintf("%s_test", $databasePrefix));
1426:                     if (!$status) {
1427:                         $this->storeResult(false, cSystemtest::C_SEVERITY_ERROR, i18n("Unable to create tables in the selected MySQL database", "setup"), sprintf(i18n("Setup tried to create a test table in the database %s and failed. Please assign table creation permissions to the database user you entered, or ask an administrator to do so.", "setup"), $databaseName));
1428:                         return;
1429:                     }
1430: 
1431:                     // Good, we could create a table. Now remove it again
1432:                     $status = checkMySQLDropTable($db, $databaseName, sprintf("%s_test", $databasePrefix));
1433:                     if (!$status) {
1434:                         $this->storeResult(false, cSystemtest::C_SEVERITY_WARNING, i18n("Unable to remove the test table", "setup"), sprintf(i18n("Setup tried to remove the test table %s in the database %s and failed due to insufficient permissions. Please remove the table %s manually.", "setup"), sprintf("%s_test", $databasePrefix), $databaseName, sprintf("%s_test", $databasePrefix)));
1435:                     }
1436:                 }
1437:                 break;
1438:             case "upgrade":
1439:                 $db = getSetupMySQLDBConnection(false);
1440: 
1441:                 // Check if the database exists
1442:                 $status = checkMySQLDatabaseExists($db, $databaseName);
1443:                 if (!$status) {
1444:                     $this->storeResult(false, cSystemtest::C_SEVERITY_ERROR, i18n("No data found for the upgrade", "setup"), sprintf(i18n("Setup tried to locate the data for the upgrade, however, the database %s doesn't exist. You need to copy your database first before running setup.", "setup"), $databaseName));
1445:                     return;
1446:                 }
1447: 
1448:                 $db = getSetupMySQLDBConnection();
1449: 
1450:                 // Check if data already exists
1451:                 $sql = 'SHOW TABLES LIKE "%s_actions"';
1452:                 $db->query(sprintf($sql, $databasePrefix));
1453:                 if (!$db->nextRecord()) {
1454:                     $this->storeResult(false, cSystemtest::C_SEVERITY_ERROR, i18n("No data found for the upgrade", "setup"), sprintf(i18n("Setup tried to locate the data for the upgrade, however, the database %s contains no tables. You need to copy your database first before running setup.", "setup"), $databaseName));
1455:                     return;
1456:                 }
1457: 
1458:                 break;
1459:         }
1460:     }
1461: 
1462: }
1463: 
CMS CONTENIDO 4.9.7 API documentation generated by ApiGen