First commit
This commit is contained in:
commit
c6e2478c40
13918 changed files with 2303184 additions and 0 deletions
165
sites/all/modules/civicrm/CRM/Utils/Check/Component/Case.php
Normal file
165
sites/all/modules/civicrm/CRM/Utils/Check/Component/Case.php
Normal file
|
@ -0,0 +1,165 @@
|
|||
<?php
|
||||
/*
|
||||
+--------------------------------------------------------------------+
|
||||
| CiviCRM version 4.7 |
|
||||
+--------------------------------------------------------------------+
|
||||
| Copyright CiviCRM LLC (c) 2004-2017 |
|
||||
+--------------------------------------------------------------------+
|
||||
| This file is a part of CiviCRM. |
|
||||
| |
|
||||
| CiviCRM is free software; you can copy, modify, and distribute it |
|
||||
| under the terms of the GNU Affero General Public License |
|
||||
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
|
||||
| |
|
||||
| CiviCRM is distributed in the hope that it will be useful, but |
|
||||
| WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
|
||||
| See the GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| You should have received a copy of the GNU Affero General Public |
|
||||
| License and the CiviCRM Licensing Exception along |
|
||||
| with this program; if not, contact CiviCRM LLC |
|
||||
| at info[AT]civicrm[DOT]org. If you have questions about the |
|
||||
| GNU Affero General Public License or the licensing of CiviCRM, |
|
||||
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
|
||||
+--------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @package CRM
|
||||
* @copyright CiviCRM LLC (c) 2004-2017
|
||||
*/
|
||||
class CRM_Utils_Check_Component_Case extends CRM_Utils_Check_Component {
|
||||
|
||||
const DOCTOR_WHEN = 'https://github.com/civicrm/org.civicrm.doctorwhen';
|
||||
|
||||
/**
|
||||
* @var CRM_Case_XMLRepository
|
||||
*/
|
||||
protected $xmlRepo;
|
||||
|
||||
/**
|
||||
* @var array<string>
|
||||
*/
|
||||
protected $caseTypeNames;
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->caseTypeNames = CRM_Case_PseudoConstant::caseType('name');
|
||||
$this->xmlRepo = CRM_Case_XMLRepository::singleton();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function isEnabled() {
|
||||
return CRM_Case_BAO_Case::enabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the case-type names don't rely on double-munging.
|
||||
*
|
||||
* @return array<CRM_Utils_Check_Message>
|
||||
* An empty array, or a list of warnings
|
||||
*/
|
||||
public function checkCaseTypeNameConsistency() {
|
||||
$messages = array();
|
||||
|
||||
foreach ($this->caseTypeNames as $caseTypeName) {
|
||||
$normalFile = $this->xmlRepo->findXmlFile($caseTypeName);
|
||||
$mungedFile = $this->xmlRepo->findXmlFile(CRM_Case_XMLProcessor::mungeCaseType($caseTypeName));
|
||||
|
||||
if ($normalFile && $mungedFile && $normalFile == $mungedFile) {
|
||||
// ok
|
||||
}
|
||||
elseif ($normalFile && $mungedFile) {
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__ . $caseTypeName,
|
||||
ts('Case type "%1" has duplicate XML files ("%2" and "%3")', array(
|
||||
1 => $caseTypeName,
|
||||
2 => $normalFile,
|
||||
3 => $mungedFile,
|
||||
)) .
|
||||
'<br /><a href="' . CRM_Utils_System::getWikiBaseURL() . __FUNCTION__ . '">' .
|
||||
ts('Read more about this warning') .
|
||||
'</a>',
|
||||
ts('CiviCase'),
|
||||
\Psr\Log\LogLevel::WARNING,
|
||||
'fa-puzzle-piece'
|
||||
);
|
||||
}
|
||||
elseif ($normalFile && !$mungedFile) {
|
||||
// ok
|
||||
}
|
||||
elseif (!$normalFile && $mungedFile) {
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__ . $caseTypeName,
|
||||
ts('Case type "%1" corresponds to XML file ("%2") The XML file should be named "%3".', array(
|
||||
1 => $caseTypeName,
|
||||
2 => $mungedFile,
|
||||
3 => "{$caseTypeName}.xml",
|
||||
)) .
|
||||
'<br /><a href="' . CRM_Utils_System::getWikiBaseURL() . __FUNCTION__ . '">' .
|
||||
ts('Read more about this warning') .
|
||||
'</a>',
|
||||
ts('CiviCase'),
|
||||
\Psr\Log\LogLevel::WARNING,
|
||||
'fa-puzzle-piece'
|
||||
);
|
||||
}
|
||||
elseif (!$normalFile && !$mungedFile) {
|
||||
// ok -- probably a new or DB-based CaseType
|
||||
}
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the timestamp columns are populated. (CRM-20958)
|
||||
*
|
||||
* @return array<CRM_Utils_Check_Message>
|
||||
* An empty array, or a list of warnings
|
||||
*/
|
||||
public function checkNullTimestamps() {
|
||||
$messages = array();
|
||||
|
||||
$nullCount = 0;
|
||||
$nullCount += CRM_Utils_SQL_Select::from('civicrm_activity')
|
||||
->where('created_date IS NULL OR modified_date IS NULL')
|
||||
->select('COUNT(*)')
|
||||
->execute()
|
||||
->fetchValue();
|
||||
$nullCount += CRM_Utils_SQL_Select::from('civicrm_case')
|
||||
->where('created_date IS NULL OR modified_date IS NULL')
|
||||
->select('COUNT(*)')
|
||||
->execute()
|
||||
->fetchValue();
|
||||
|
||||
if ($nullCount > 0) {
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
'<p>' .
|
||||
ts('The tables "<em>civicrm_activity</em>" and "<em>civicrm_case</em>" were updated to support two new fields, "<em>created_date</em>" and "<em>modified_date</em>". For historical data, these fields may appear blank. (%1 records have NULL timestamps.)', array(
|
||||
1 => $nullCount,
|
||||
)) .
|
||||
'</p><p>' .
|
||||
ts('At time of writing, this is not a problem. However, future extensions and improvements could rely on these fields, so it may be useful to back-fill them.') .
|
||||
'</p><p>' .
|
||||
ts('For further discussion, please visit %1', array(
|
||||
1 => sprintf('<a href="%s" target="_blank">%s</a>', self::DOCTOR_WHEN, self::DOCTOR_WHEN),
|
||||
)) .
|
||||
'</p>',
|
||||
ts('Timestamps for Activities and Cases'),
|
||||
\Psr\Log\LogLevel::NOTICE,
|
||||
'fa-clock-o'
|
||||
);
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
}
|
918
sites/all/modules/civicrm/CRM/Utils/Check/Component/Env.php
Normal file
918
sites/all/modules/civicrm/CRM/Utils/Check/Component/Env.php
Normal file
|
@ -0,0 +1,918 @@
|
|||
<?php
|
||||
/*
|
||||
+--------------------------------------------------------------------+
|
||||
| CiviCRM version 4.7 |
|
||||
+--------------------------------------------------------------------+
|
||||
| Copyright CiviCRM LLC (c) 2004-2017 |
|
||||
+--------------------------------------------------------------------+
|
||||
| This file is a part of CiviCRM. |
|
||||
| |
|
||||
| CiviCRM is free software; you can copy, modify, and distribute it |
|
||||
| under the terms of the GNU Affero General Public License |
|
||||
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
|
||||
| |
|
||||
| CiviCRM is distributed in the hope that it will be useful, but |
|
||||
| WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
|
||||
| See the GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| You should have received a copy of the GNU Affero General Public |
|
||||
| License and the CiviCRM Licensing Exception along |
|
||||
| with this program; if not, contact CiviCRM LLC |
|
||||
| at info[AT]civicrm[DOT]org. If you have questions about the |
|
||||
| GNU Affero General Public License or the licensing of CiviCRM, |
|
||||
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
|
||||
+--------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @package CRM
|
||||
* @copyright CiviCRM LLC (c) 2004-2017
|
||||
*/
|
||||
class CRM_Utils_Check_Component_Env extends CRM_Utils_Check_Component {
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function checkPhpVersion() {
|
||||
$messages = array();
|
||||
$phpVersion = phpversion();
|
||||
|
||||
if (version_compare($phpVersion, CRM_Upgrade_Incremental_General::RECOMMENDED_PHP_VER) >= 0) {
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
ts('This system uses PHP version %1 which meets or exceeds the recommendation of %2.',
|
||||
array(
|
||||
1 => $phpVersion,
|
||||
2 => CRM_Upgrade_Incremental_General::RECOMMENDED_PHP_VER,
|
||||
)),
|
||||
ts('PHP Up-to-Date'),
|
||||
\Psr\Log\LogLevel::INFO,
|
||||
'fa-server'
|
||||
);
|
||||
}
|
||||
elseif (version_compare($phpVersion, CRM_Upgrade_Incremental_General::MIN_RECOMMENDED_PHP_VER) >= 0) {
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
ts('This system uses PHP version %1. This meets the minimum recommendations and you do not need to upgrade immediately, but the preferred version is %2.',
|
||||
array(
|
||||
1 => $phpVersion,
|
||||
2 => CRM_Upgrade_Incremental_General::RECOMMENDED_PHP_VER,
|
||||
)),
|
||||
ts('PHP Out-of-Date'),
|
||||
\Psr\Log\LogLevel::NOTICE,
|
||||
'fa-server'
|
||||
);
|
||||
}
|
||||
elseif (version_compare($phpVersion, CRM_Upgrade_Incremental_General::MIN_INSTALL_PHP_VER) >= 0) {
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
ts('This system uses PHP version %1. This meets the minimum requirements for CiviCRM to function but is not recommended. At least PHP version %2 is recommended; the preferrred version is %3.',
|
||||
array(
|
||||
1 => $phpVersion,
|
||||
2 => CRM_Upgrade_Incremental_General::MIN_RECOMMENDED_PHP_VER,
|
||||
3 => CRM_Upgrade_Incremental_General::RECOMMENDED_PHP_VER,
|
||||
)),
|
||||
ts('PHP Out-of-Date'),
|
||||
\Psr\Log\LogLevel::WARNING,
|
||||
'fa-server'
|
||||
);
|
||||
}
|
||||
else {
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
ts('This system uses PHP version %1. To ensure the continued operation of CiviCRM, upgrade your server now. At least PHP version %2 is recommended; the preferrred version is %3.',
|
||||
array(
|
||||
1 => $phpVersion,
|
||||
2 => CRM_Upgrade_Incremental_General::MIN_RECOMMENDED_PHP_VER,
|
||||
3 => CRM_Upgrade_Incremental_General::RECOMMENDED_PHP_VER,
|
||||
)),
|
||||
ts('PHP Out-of-Date'),
|
||||
\Psr\Log\LogLevel::ERROR,
|
||||
'fa-server'
|
||||
);
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function checkPhpMysqli() {
|
||||
$messages = array();
|
||||
|
||||
if (!extension_loaded('mysqli')) {
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
ts('Future versions of CiviCRM may require the PHP extension "%2". To ensure that your system will be compatible, please install it in advance. For more explanation, see <a href="%1">the announcement</a>.',
|
||||
array(
|
||||
1 => 'https://civicrm.org/blog/totten/psa-please-verify-php-extension-mysqli',
|
||||
2 => 'mysqli',
|
||||
)),
|
||||
ts('Forward Compatibility: Enable "mysqli"'),
|
||||
\Psr\Log\LogLevel::WARNING,
|
||||
'fa-server'
|
||||
);
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the MySQL time settings match the PHP time settings.
|
||||
*
|
||||
* @return array<CRM_Utils_Check_Message> an empty array, or a list of warnings
|
||||
*/
|
||||
public function checkMysqlTime() {
|
||||
//CRM-19115 - Always set MySQL time before checking it.
|
||||
CRM_Core_Config::singleton()->userSystem->setMySQLTimeZone();
|
||||
$messages = array();
|
||||
|
||||
$phpNow = date('Y-m-d H:i');
|
||||
$sqlNow = CRM_Core_DAO::singleValueQuery("SELECT date_format(now(), '%Y-%m-%d %H:%i')");
|
||||
if (!CRM_Utils_Time::isEqual($phpNow, $sqlNow, 2.5 * 60)) {
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
ts('Timestamps reported by MySQL (eg "%2") and PHP (eg "%3" ) are mismatched.<br /><a href="%1">Read more about this warning</a>', array(
|
||||
1 => CRM_Utils_System::getWikiBaseURL() . 'checkMysqlTime',
|
||||
2 => $sqlNow,
|
||||
3 => $phpNow,
|
||||
)),
|
||||
ts('Timestamp Mismatch'),
|
||||
\Psr\Log\LogLevel::ERROR,
|
||||
'fa-server'
|
||||
);
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function checkDebug() {
|
||||
$config = CRM_Core_Config::singleton();
|
||||
if ($config->debug) {
|
||||
$message = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
ts('Warning: Debug is enabled in <a href="%1">system settings</a>. This should not be enabled on production servers.',
|
||||
array(1 => CRM_Utils_System::url('civicrm/admin/setting/debug', 'reset=1'))),
|
||||
ts('Debug Mode Enabled'),
|
||||
\Psr\Log\LogLevel::WARNING,
|
||||
'fa-bug'
|
||||
);
|
||||
$message->addAction(
|
||||
ts('Disable Debug Mode'),
|
||||
ts('Disable debug mode now?'),
|
||||
'api3',
|
||||
array('Setting', 'create', array('debug_enabled' => 0))
|
||||
);
|
||||
return array($message);
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function checkOutboundMail() {
|
||||
$messages = array();
|
||||
|
||||
$mailingInfo = Civi::settings()->get('mailing_backend');
|
||||
if (($mailingInfo['outBound_option'] == CRM_Mailing_Config::OUTBOUND_OPTION_REDIRECT_TO_DB
|
||||
|| (defined('CIVICRM_MAIL_LOG') && CIVICRM_MAIL_LOG)
|
||||
|| $mailingInfo['outBound_option'] == CRM_Mailing_Config::OUTBOUND_OPTION_DISABLED
|
||||
|| $mailingInfo['outBound_option'] == CRM_Mailing_Config::OUTBOUND_OPTION_MOCK)
|
||||
) {
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
ts('Warning: Outbound email is disabled in <a href="%1">system settings</a>. Proper settings should be enabled on production servers.',
|
||||
array(1 => CRM_Utils_System::url('civicrm/admin/setting/smtp', 'reset=1'))),
|
||||
ts('Outbound Email Disabled'),
|
||||
\Psr\Log\LogLevel::WARNING,
|
||||
'fa-envelope'
|
||||
);
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that domain email and org name are set
|
||||
* @return array
|
||||
*/
|
||||
public function checkDomainNameEmail() {
|
||||
$messages = array();
|
||||
|
||||
list($domainEmailName, $domainEmailAddress) = CRM_Core_BAO_Domain::getNameAndEmail(TRUE);
|
||||
$domain = CRM_Core_BAO_Domain::getDomain();
|
||||
$domainName = $domain->name;
|
||||
$fixEmailUrl = CRM_Utils_System::url("civicrm/admin/domain", "action=update&reset=1");
|
||||
|
||||
if (!$domainEmailAddress || $domainEmailAddress == 'info@EXAMPLE.ORG') {
|
||||
if (!$domainName || $domainName == 'Default Domain Name') {
|
||||
$msg = ts("Please enter your organization's <a href=\"%1\">name, primary address, and default FROM Email Address</a> (for system-generated emails).",
|
||||
array(1 => $fixEmailUrl));
|
||||
}
|
||||
else {
|
||||
$msg = ts('Please enter a <a href="%1">default FROM Email Address</a> (for system-generated emails).',
|
||||
array(1 => $fixEmailUrl));
|
||||
}
|
||||
}
|
||||
elseif (!$domainName || $domainName == 'Default Domain Name') {
|
||||
$msg = ts("Please enter your organization's <a href=\"%1\">name and primary address</a>.",
|
||||
array(1 => $fixEmailUrl));
|
||||
}
|
||||
|
||||
if (!empty($msg)) {
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
$msg,
|
||||
ts('Complete Setup'),
|
||||
\Psr\Log\LogLevel::WARNING,
|
||||
'fa-check-square-o'
|
||||
);
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a default bounce handling mailbox is set up
|
||||
* @return array
|
||||
*/
|
||||
public function checkDefaultMailbox() {
|
||||
$messages = array();
|
||||
$config = CRM_Core_Config::singleton();
|
||||
|
||||
if (in_array('CiviMail', $config->enableComponents) &&
|
||||
CRM_Core_BAO_MailSettings::defaultDomain() == "EXAMPLE.ORG"
|
||||
) {
|
||||
$message = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
ts('Please configure a <a href="%1">default mailbox</a> for CiviMail.',
|
||||
array(1 => CRM_Utils_System::url('civicrm/admin/mailSettings', "reset=1"))),
|
||||
ts('Configure Default Mailbox'),
|
||||
\Psr\Log\LogLevel::WARNING,
|
||||
'fa-envelope'
|
||||
);
|
||||
$docUrl = 'target="_blank" href="' . CRM_Utils_System::docURL(array('page' => 'user/advanced-configuration/email-system-configuration/', 'URLonly' => TRUE)) . '""';
|
||||
$message->addHelp(
|
||||
ts('A default mailbox must be configured for email bounce processing.') . '<br />' .
|
||||
ts("Learn more in the <a %1>online documentation</a>.", array(1 => $docUrl))
|
||||
);
|
||||
$messages[] = $message;
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if cron has run in a reasonable amount of time
|
||||
* @return array
|
||||
*/
|
||||
public function checkLastCron() {
|
||||
$messages = array();
|
||||
|
||||
$statusPreference = new CRM_Core_DAO_StatusPreference();
|
||||
$statusPreference->domain_id = CRM_Core_Config::domainID();
|
||||
$statusPreference->name = 'checkLastCron';
|
||||
|
||||
if ($statusPreference->find(TRUE) && !empty($statusPreference->check_info)) {
|
||||
$lastCron = $statusPreference->check_info;
|
||||
$msg = ts('Last cron run at %1.', array(1 => CRM_Utils_Date::customFormat(date('c', $lastCron))));
|
||||
}
|
||||
else {
|
||||
$lastCron = 0;
|
||||
$msg = ts('No cron runs have been recorded.');
|
||||
}
|
||||
|
||||
if ($lastCron > gmdate('U') - 3600) {
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
$msg,
|
||||
ts('Cron Running OK'),
|
||||
\Psr\Log\LogLevel::INFO,
|
||||
'fa-clock-o'
|
||||
);
|
||||
}
|
||||
else {
|
||||
$message = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
$msg,
|
||||
ts('Cron Not Running'),
|
||||
($lastCron > gmdate('U') - 86400) ? \Psr\Log\LogLevel::WARNING : \Psr\Log\LogLevel::ERROR,
|
||||
'fa-clock-o'
|
||||
);
|
||||
$docUrl = 'target="_blank" href="' . CRM_Utils_System::docURL(array('resource' => 'wiki', 'page' => 'Managing Scheduled Jobs', 'URLonly' => TRUE)) . '""';
|
||||
$message->addHelp(
|
||||
ts('Configuring cron on your server is necessary for running scheduled jobs such as sending mail and scheduled reminders.') . '<br />' .
|
||||
ts("Learn more in the <a %1>online documentation</a>.", array(1 => $docUrl))
|
||||
);
|
||||
$messages[] = $message;
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recommend that sites use path-variables for their directories and URLs.
|
||||
* @return array
|
||||
*/
|
||||
public function checkUrlVariables() {
|
||||
$messages = array();
|
||||
$hasOldStyle = FALSE;
|
||||
$settingNames = array(
|
||||
'userFrameworkResourceURL',
|
||||
'imageUploadURL',
|
||||
'customCSSURL',
|
||||
'extensionsURL',
|
||||
);
|
||||
|
||||
foreach ($settingNames as $settingName) {
|
||||
$settingValue = Civi::settings()->get($settingName);
|
||||
if (!empty($settingValue) && $settingValue{0} != '[') {
|
||||
$hasOldStyle = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($hasOldStyle) {
|
||||
$message = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
ts('<a href="%1">Resource URLs</a> may use absolute paths, relative paths, or variables. Absolute paths are more difficult to maintain. To maximize portability, consider using a variable in each URL (eg "<tt>[cms.root]</tt>" or "<tt>[civicrm.files]</tt>").',
|
||||
array(1 => CRM_Utils_System::url('civicrm/admin/setting/url', "reset=1"))),
|
||||
ts('Resource URLs: Make them portable'),
|
||||
\Psr\Log\LogLevel::NOTICE,
|
||||
'fa-server'
|
||||
);
|
||||
$messages[] = $message;
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recommend that sites use path-variables for their directories and URLs.
|
||||
* @return array
|
||||
*/
|
||||
public function checkDirVariables() {
|
||||
$messages = array();
|
||||
$hasOldStyle = FALSE;
|
||||
$settingNames = array(
|
||||
'uploadDir',
|
||||
'imageUploadDir',
|
||||
'customFileUploadDir',
|
||||
'customTemplateDir',
|
||||
'customPHPPathDir',
|
||||
'extensionsDir',
|
||||
);
|
||||
|
||||
foreach ($settingNames as $settingName) {
|
||||
$settingValue = Civi::settings()->get($settingName);
|
||||
if (!empty($settingValue) && $settingValue{0} != '[') {
|
||||
$hasOldStyle = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($hasOldStyle) {
|
||||
$message = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
ts('<a href="%1">Directories</a> may use absolute paths, relative paths, or variables. Absolute paths are more difficult to maintain. To maximize portability, consider using a variable in each directory (eg "<tt>[cms.root]</tt>" or "<tt>[civicrm.files]</tt>").',
|
||||
array(1 => CRM_Utils_System::url('civicrm/admin/setting/path', "reset=1"))),
|
||||
ts('Directory Paths: Make them portable'),
|
||||
\Psr\Log\LogLevel::NOTICE,
|
||||
'fa-server'
|
||||
);
|
||||
$messages[] = $message;
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that important directories are writable.
|
||||
*
|
||||
* @return array
|
||||
* Any CRM_Utils_Check_Message instances that need to be generated.
|
||||
*/
|
||||
public function checkDirsWritable() {
|
||||
$notWritable = array();
|
||||
|
||||
$config = CRM_Core_Config::singleton();
|
||||
$directories = array(
|
||||
'uploadDir' => ts('Temporary Files Directory'),
|
||||
'imageUploadDir' => ts('Images Directory'),
|
||||
'customFileUploadDir' => ts('Custom Files Directory'),
|
||||
'extensionsDir' => ts('CiviCRM Extensions Directory'),
|
||||
);
|
||||
|
||||
foreach ($directories as $directory => $label) {
|
||||
$file = CRM_Utils_File::createFakeFile($config->$directory);
|
||||
|
||||
if ($file === FALSE) {
|
||||
$notWritable[] = "$label ({$config->$directory})";
|
||||
}
|
||||
else {
|
||||
$dirWithSlash = CRM_Utils_File::addTrailingSlash($config->$directory);
|
||||
unlink($dirWithSlash . $file);
|
||||
}
|
||||
}
|
||||
|
||||
$messages = array();
|
||||
|
||||
if (!empty($notWritable)) {
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
ts('The %1 is not writable. Please check your file permissions.', array(
|
||||
1 => implode(', ', $notWritable),
|
||||
'count' => count($notWritable),
|
||||
'plural' => 'The following directories are not writable: %1. Please check your file permissions.',
|
||||
)),
|
||||
ts('Directory not writable', array(
|
||||
'count' => count($notWritable),
|
||||
'plural' => 'Directories not writable',
|
||||
)),
|
||||
\Psr\Log\LogLevel::ERROR,
|
||||
'fa-ban'
|
||||
);
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if new versions are available
|
||||
* @return array
|
||||
*/
|
||||
public function checkVersion() {
|
||||
$messages = array();
|
||||
try {
|
||||
$vc = new CRM_Utils_VersionCheck();
|
||||
$vc->initialize();
|
||||
}
|
||||
catch (Exception $e) {
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
'checkVersionError',
|
||||
ts('Directory %1 is not writable. Please change your file permissions.',
|
||||
array(1 => dirname($vc->cacheFile))),
|
||||
ts('Directory not writable'),
|
||||
\Psr\Log\LogLevel::ERROR,
|
||||
'fa-times-circle-o'
|
||||
);
|
||||
return $messages;
|
||||
}
|
||||
|
||||
// Show a notice if the version_check job is disabled
|
||||
if (empty($vc->cronJob['is_active'])) {
|
||||
$args = empty($vc->cronJob['id']) ? array('reset' => 1) : array('reset' => 1, 'action' => 'update', 'id' => $vc->cronJob['id']);
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
'checkVersionDisabled',
|
||||
ts('The check for new versions of CiviCRM has been disabled. <a %1>Re-enable the scheduled job</a> to receive important security update notifications.', array(1 => 'href="' . CRM_Utils_System::url('civicrm/admin/job', $args) . '"')),
|
||||
ts('Update Check Disabled'),
|
||||
\Psr\Log\LogLevel::NOTICE,
|
||||
'fa-times-circle-o'
|
||||
);
|
||||
}
|
||||
|
||||
if ($vc->isInfoAvailable) {
|
||||
$newerVersion = $vc->isNewerVersionAvailable();
|
||||
if ($newerVersion['version']) {
|
||||
$vInfo = array(
|
||||
1 => $newerVersion['version'],
|
||||
2 => $vc->localVersion,
|
||||
);
|
||||
// LTS = long-term support version
|
||||
if ($newerVersion['status'] == 'lts') {
|
||||
$vInfo[1] .= ' ' . ts('(long-term support)');
|
||||
}
|
||||
|
||||
if ($newerVersion['upgrade'] == 'security') {
|
||||
// Security
|
||||
$severity = \Psr\Log\LogLevel::CRITICAL;
|
||||
$title = ts('CiviCRM Security Update Required');
|
||||
$message = ts('New security release %1 is available. The site is currently running %2.', $vInfo);
|
||||
}
|
||||
elseif ($newerVersion['status'] == 'eol') {
|
||||
// Warn about EOL
|
||||
$severity = \Psr\Log\LogLevel::WARNING;
|
||||
$title = ts('CiviCRM Update Needed');
|
||||
$message = ts('New version %1 is available. The site is currently running %2, which has reached its end of life.', $vInfo);
|
||||
}
|
||||
else {
|
||||
// For most new versions, just make them notice
|
||||
$severity = \Psr\Log\LogLevel::NOTICE;
|
||||
$title = ts('CiviCRM Update Available');
|
||||
$message = ts('New version %1 is available. The site is currently running %2.', $vInfo);
|
||||
}
|
||||
}
|
||||
elseif (!empty($vc->cronJob['is_active'])) {
|
||||
$vNum = $vc->localVersion;
|
||||
// LTS = long-term support version
|
||||
if ($newerVersion['status'] == 'lts') {
|
||||
$vNum .= ' ' . ts('(long-term support)');
|
||||
}
|
||||
|
||||
$severity = \Psr\Log\LogLevel::INFO;
|
||||
$title = ts('CiviCRM Up-to-Date');
|
||||
$message = ts('CiviCRM version %1 is up-to-date.', array(1 => $vNum));
|
||||
}
|
||||
|
||||
if (!empty($message)) {
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
$message,
|
||||
$title,
|
||||
$severity,
|
||||
'fa-cloud-upload'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if extensions are set up properly
|
||||
* @return array
|
||||
*/
|
||||
public function checkExtensions() {
|
||||
$messages = array();
|
||||
$extensionSystem = CRM_Extension_System::singleton();
|
||||
$mapper = $extensionSystem->getMapper();
|
||||
$manager = $extensionSystem->getManager();
|
||||
|
||||
if ($extensionSystem->getDefaultContainer()) {
|
||||
$basedir = $extensionSystem->getDefaultContainer()->baseDir;
|
||||
}
|
||||
|
||||
if (empty($basedir)) {
|
||||
// no extension directory
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
ts('Your extensions directory is not set. Click <a href="%1">here</a> to set the extensions directory.',
|
||||
array(1 => CRM_Utils_System::url('civicrm/admin/setting/path', 'reset=1'))),
|
||||
ts('Directory not writable'),
|
||||
\Psr\Log\LogLevel::NOTICE,
|
||||
'fa-plug'
|
||||
);
|
||||
return $messages;
|
||||
}
|
||||
|
||||
if (!is_dir($basedir)) {
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
ts('Your extensions directory path points to %1, which is not a directory. Please check your file system.',
|
||||
array(1 => $basedir)),
|
||||
ts('Extensions directory incorrect'),
|
||||
\Psr\Log\LogLevel::ERROR,
|
||||
'fa-plug'
|
||||
);
|
||||
return $messages;
|
||||
}
|
||||
elseif (!is_writable($basedir)) {
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
ts('Directory %1 is not writable. Please change your file permissions.',
|
||||
array(1 => $basedir)),
|
||||
ts('Directory not writable'),
|
||||
\Psr\Log\LogLevel::ERROR,
|
||||
'fa-plug'
|
||||
);
|
||||
return $messages;
|
||||
}
|
||||
|
||||
if (empty($extensionSystem->getDefaultContainer()->baseUrl)) {
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
ts('The extensions URL is not properly set. Please go to the <a href="%1">URL setting page</a> and correct it.',
|
||||
array(1 => CRM_Utils_System::url('civicrm/admin/setting/url', 'reset=1'))),
|
||||
ts('Extensions url missing'),
|
||||
\Psr\Log\LogLevel::ERROR,
|
||||
'fa-plug'
|
||||
);
|
||||
return $messages;
|
||||
}
|
||||
|
||||
if (!$extensionSystem->getBrowser()->isEnabled()) {
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
ts('Not checking remote URL for extensions since ext_repo_url is set to false.'),
|
||||
ts('Extensions check disabled'),
|
||||
\Psr\Log\LogLevel::NOTICE,
|
||||
'fa-plug'
|
||||
);
|
||||
return $messages;
|
||||
}
|
||||
|
||||
try {
|
||||
$remotes = $extensionSystem->getBrowser()->getExtensions();
|
||||
}
|
||||
catch (CRM_Extension_Exception $e) {
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
$e->getMessage(),
|
||||
ts('Extension download error'),
|
||||
\Psr\Log\LogLevel::ERROR,
|
||||
'fa-plug'
|
||||
);
|
||||
return $messages;
|
||||
}
|
||||
|
||||
if (!$remotes) {
|
||||
// CRM-13141 There may not be any compatible extensions available for the requested CiviCRM version + CMS. If so, $extdir is empty so just return a notice.
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
ts('There are currently no extensions on the CiviCRM public extension directory which are compatible with version %1. If you want to install an extension which is not marked as compatible, you may be able to <a %2>download and install extensions manually</a> (depending on access to your web server).', array(
|
||||
1 => CRM_Utils_System::majorVersion(),
|
||||
2 => 'href="http://wiki.civicrm.org/confluence/display/CRMDOC/Extensions"',
|
||||
)),
|
||||
ts('No Extensions Available for this Version'),
|
||||
\Psr\Log\LogLevel::NOTICE,
|
||||
'fa-plug'
|
||||
);
|
||||
return $messages;
|
||||
}
|
||||
|
||||
$keys = array_keys($manager->getStatuses());
|
||||
sort($keys);
|
||||
$updates = $errors = $okextensions = array();
|
||||
|
||||
foreach ($keys as $key) {
|
||||
try {
|
||||
$obj = $mapper->keyToInfo($key);
|
||||
}
|
||||
catch (CRM_Extension_Exception $ex) {
|
||||
$errors[] = ts('Failed to read extension (%1). Please refresh the extension list.', array(1 => $key));
|
||||
continue;
|
||||
}
|
||||
$row = CRM_Admin_Page_Extensions::createExtendedInfo($obj);
|
||||
switch ($row['status']) {
|
||||
case CRM_Extension_Manager::STATUS_INSTALLED_MISSING:
|
||||
$errors[] = ts('%1 extension (%2) is installed but missing files.', array(1 => CRM_Utils_Array::value('label', $row), 2 => $key));
|
||||
break;
|
||||
|
||||
case CRM_Extension_Manager::STATUS_INSTALLED:
|
||||
if (!empty($remotes[$key]) && version_compare($row['version'], $remotes[$key]->version, '<')) {
|
||||
$updates[] = ts('%1 (%2) version %3 is installed. <a %4>Upgrade to version %5</a>.', array(
|
||||
1 => CRM_Utils_Array::value('label', $row),
|
||||
2 => $key,
|
||||
3 => $row['version'],
|
||||
4 => 'href="' . CRM_Utils_System::url('civicrm/admin/extensions', "action=update&id=$key&key=$key") . '"',
|
||||
5 => $remotes[$key]->version,
|
||||
));
|
||||
}
|
||||
else {
|
||||
if (empty($row['label'])) {
|
||||
$okextensions[] = $key;
|
||||
}
|
||||
else {
|
||||
$okextensions[] = ts('%1 (%2) version %3', array(
|
||||
1 => $row['label'],
|
||||
2 => $key,
|
||||
3 => $row['version'],
|
||||
));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$okextensions && !$updates && !$errors) {
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
'extensionsOk',
|
||||
ts('No extensions installed. <a %1>Browse available extensions</a>.', array(
|
||||
1 => 'href="' . CRM_Utils_System::url('civicrm/admin/extensions', 'reset=1') . '"',
|
||||
)),
|
||||
ts('Extensions'),
|
||||
\Psr\Log\LogLevel::INFO,
|
||||
'fa-plug'
|
||||
);
|
||||
}
|
||||
|
||||
if ($errors) {
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
'<ul><li>' . implode('</li><li>', $errors) . '</li></ul>',
|
||||
ts('Extension Error'),
|
||||
\Psr\Log\LogLevel::ERROR,
|
||||
'fa-plug'
|
||||
);
|
||||
}
|
||||
|
||||
if ($updates) {
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
'extensionUpdates',
|
||||
'<ul><li>' . implode('</li><li>', $updates) . '</li></ul>',
|
||||
ts('Extension Update Available', array('plural' => '%count Extension Updates Available', 'count' => count($updates))),
|
||||
\Psr\Log\LogLevel::WARNING,
|
||||
'fa-plug'
|
||||
);
|
||||
}
|
||||
|
||||
if ($okextensions) {
|
||||
if ($updates || $errors) {
|
||||
$message = ts('1 extension is up-to-date:', array('plural' => '%count extensions are up-to-date:', 'count' => count($okextensions)));
|
||||
}
|
||||
else {
|
||||
$message = ts('All extensions are up-to-date:');
|
||||
}
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
'extensionsOk',
|
||||
$message . '<ul><li>' . implode('</li><li>', $okextensions) . '</li></ul>',
|
||||
ts('Extensions'),
|
||||
\Psr\Log\LogLevel::INFO,
|
||||
'fa-plug'
|
||||
);
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if there are pending extension upgrades.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function checkExtensionUpgrades() {
|
||||
if (CRM_Extension_Upgrades::hasPending()) {
|
||||
$message = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
ts('Extension upgrades should be run as soon as possible.'),
|
||||
ts('Extension Upgrades Pending'),
|
||||
\Psr\Log\LogLevel::ERROR,
|
||||
'fa-plug'
|
||||
);
|
||||
$message->addAction(
|
||||
ts('Run Upgrades'),
|
||||
ts('Run extension upgrades now?'),
|
||||
'href',
|
||||
array('path' => 'civicrm/admin/extensions/upgrade', 'query' => array('reset' => 1, 'destination' => CRM_Utils_System::url('civicrm/a/#/status')))
|
||||
);
|
||||
return array($message);
|
||||
}
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if CiviCRM database version is up-to-date
|
||||
* @return array
|
||||
*/
|
||||
public function checkDbVersion() {
|
||||
$messages = array();
|
||||
$dbVersion = CRM_Core_BAO_Domain::version();
|
||||
$upgradeUrl = CRM_Utils_System::url("civicrm/upgrade", "reset=1");
|
||||
|
||||
if (!$dbVersion) {
|
||||
// if db.ver missing
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
ts('Version information found to be missing in database. You will need to determine the correct version corresponding to your current database state.'),
|
||||
ts('Database Version Missing'),
|
||||
\Psr\Log\LogLevel::ERROR,
|
||||
'fa-database'
|
||||
);
|
||||
}
|
||||
elseif (!CRM_Utils_System::isVersionFormatValid($dbVersion)) {
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
ts('Database is marked with invalid version format. You may want to investigate this before you proceed further.'),
|
||||
ts('Database Version Invalid'),
|
||||
\Psr\Log\LogLevel::ERROR,
|
||||
'fa-database'
|
||||
);
|
||||
}
|
||||
elseif (stripos($dbVersion, 'upgrade')) {
|
||||
// if db.ver indicates a partially upgraded db
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
ts('Database check failed - the database looks to have been partially upgraded. You must reload the database with the backup and try the <a href=\'%1\'>upgrade process</a> again.', array(1 => $upgradeUrl)),
|
||||
ts('Database Partially Upgraded'),
|
||||
\Psr\Log\LogLevel::ALERT,
|
||||
'fa-database'
|
||||
);
|
||||
}
|
||||
else {
|
||||
$codeVersion = CRM_Utils_System::version();
|
||||
|
||||
// if db.ver < code.ver, time to upgrade
|
||||
if (version_compare($dbVersion, $codeVersion) < 0) {
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
ts('New codebase version detected. You must visit <a href=\'%1\'>upgrade screen</a> to upgrade the database.', array(1 => $upgradeUrl)),
|
||||
ts('Database Upgrade Required'),
|
||||
\Psr\Log\LogLevel::ALERT,
|
||||
'fa-database'
|
||||
);
|
||||
}
|
||||
|
||||
// if db.ver > code.ver, sth really wrong
|
||||
if (version_compare($dbVersion, $codeVersion) > 0) {
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
ts('Your database is marked with an unexpected version number: %1. The v%2 codebase may not be compatible with your database state.
|
||||
You will need to determine the correct version corresponding to your current database state. You may want to revert to the codebase
|
||||
you were using until you resolve this problem.<br/>OR if this is a manual install from git, you might want to fix civicrm-version.php file.',
|
||||
array(1 => $dbVersion, 2 => $codeVersion)
|
||||
),
|
||||
ts('Database In Unexpected Version'),
|
||||
\Psr\Log\LogLevel::ERROR,
|
||||
'fa-database'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* ensure that all CiviCRM tables are InnoDB
|
||||
* @return array
|
||||
*/
|
||||
public function checkDbEngine() {
|
||||
$messages = array();
|
||||
|
||||
if (CRM_Core_DAO::isDBMyISAM(150)) {
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
ts('Your database is configured to use the MyISAM database engine. CiviCRM requires InnoDB. You will need to convert any MyISAM tables in your database to InnoDB. Using MyISAM tables will result in data integrity issues.'),
|
||||
ts('MyISAM Database Engine'),
|
||||
\Psr\Log\LogLevel::ERROR,
|
||||
'fa-database'
|
||||
);
|
||||
}
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for required mbstring extension
|
||||
* @return array
|
||||
*/
|
||||
public function checkMbstring() {
|
||||
$messages = array();
|
||||
|
||||
if (!function_exists('mb_substr')) {
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
ts('The PHP Multibyte String extension is needed for CiviCRM to correctly handle user input among other functionality. Ask your system administrator to install it.'),
|
||||
ts('Missing mbstring Extension'),
|
||||
\Psr\Log\LogLevel::WARNING,
|
||||
'fa-server'
|
||||
);
|
||||
}
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if environment is Production.
|
||||
* @return array
|
||||
*/
|
||||
public function checkEnvironment() {
|
||||
$messages = array();
|
||||
|
||||
$environment = CRM_Core_Config::environment();
|
||||
if ($environment != 'Production') {
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
ts('The environment of this CiviCRM instance is set to \'%1\'. Certain functionality like scheduled jobs has been disabled.', array(1 => $environment)),
|
||||
ts('Non-Production Environment'),
|
||||
\Psr\Log\LogLevel::ALERT,
|
||||
'fa-bug'
|
||||
);
|
||||
}
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the resource URL points to the correct location.
|
||||
* @return array
|
||||
*/
|
||||
public function checkResourceUrl() {
|
||||
$messages = array();
|
||||
// Skip when run during unit tests, you can't check without a CMS.
|
||||
if (CRM_Core_Config::singleton()->userFramework == 'UnitTests') {
|
||||
return $messages;
|
||||
}
|
||||
// Does arrow.png exist where we expect it?
|
||||
$arrowUrl = CRM_Core_Config::singleton()->userFrameworkResourceURL . 'packages/jquery/css/images/arrow.png';
|
||||
$headers = get_headers($arrowUrl);
|
||||
$fileExists = stripos($headers[0], "200 OK") ? 1 : 0;
|
||||
if (!$fileExists) {
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
ts('The Resource URL is not set correctly. Please set the <a href="%1">CiviCRM Resource URL</a>.',
|
||||
array(1 => CRM_Utils_System::url('civicrm/admin/setting/url', 'reset=1'))),
|
||||
ts('Incorrect Resource URL'),
|
||||
\Psr\Log\LogLevel::ERROR,
|
||||
'fa-server'
|
||||
);
|
||||
}
|
||||
return $messages;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
/*
|
||||
+--------------------------------------------------------------------+
|
||||
| CiviCRM version 4.7 |
|
||||
+--------------------------------------------------------------------+
|
||||
| Copyright CiviCRM LLC (c) 2004-2017 |
|
||||
+--------------------------------------------------------------------+
|
||||
| This file is a part of CiviCRM. |
|
||||
| |
|
||||
| CiviCRM is free software; you can copy, modify, and distribute it |
|
||||
| under the terms of the GNU Affero General Public License |
|
||||
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
|
||||
| |
|
||||
| CiviCRM is distributed in the hope that it will be useful, but |
|
||||
| WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
|
||||
| See the GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| You should have received a copy of the GNU Affero General Public |
|
||||
| License and the CiviCRM Licensing Exception along |
|
||||
| with this program; if not, contact CiviCRM LLC |
|
||||
| at info[AT]civicrm[DOT]org. If you have questions about the |
|
||||
| GNU Affero General Public License or the licensing of CiviCRM, |
|
||||
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
|
||||
+--------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @package CRM
|
||||
* @copyright CiviCRM LLC (c) 2004-2017
|
||||
*/
|
||||
class CRM_Utils_Check_Component_FinancialTypeAcls extends CRM_Utils_Check_Component {
|
||||
|
||||
public static function checkFinancialAclReport() {
|
||||
$messages = array();
|
||||
$ftAclSetting = Civi::settings()->get('acl_financial_type');
|
||||
$financialAclExtension = civicrm_api3('extension', 'get', array('key' => 'biz.jmaconsulting.financialaclreport'));
|
||||
if ($ftAclSetting && (($financialAclExtension['count'] == 1 && $financialAclExtension['status'] != 'Installed') || $financialAclExtension['count'] !== 1)) {
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
ts('CiviCRM will in the future require the extension %1 for CiviCRM Reports to work correctly with the Financial Type ACLs. The extension can be downloaded <a href="%2">here</a>', array(
|
||||
1 => 'biz.jmaconsulting.financialaclreport',
|
||||
2 => 'https://github.com/JMAConsulting/biz.jmaconsulting.financialaclreport',
|
||||
)),
|
||||
ts('Extension Missing'),
|
||||
\Psr\Log\LogLevel::WARNING,
|
||||
'fa-server'
|
||||
);
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
/*
|
||||
+--------------------------------------------------------------------+
|
||||
| CiviCRM version 4.7 |
|
||||
+--------------------------------------------------------------------+
|
||||
| Copyright CiviCRM LLC (c) 2004-2017 |
|
||||
+--------------------------------------------------------------------+
|
||||
| This file is a part of CiviCRM. |
|
||||
| |
|
||||
| CiviCRM is free software; you can copy, modify, and distribute it |
|
||||
| under the terms of the GNU Affero General Public License |
|
||||
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
|
||||
| |
|
||||
| CiviCRM is distributed in the hope that it will be useful, but |
|
||||
| WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
|
||||
| See the GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| You should have received a copy of the GNU Affero General Public |
|
||||
| License and the CiviCRM Licensing Exception along |
|
||||
| with this program; if not, contact CiviCRM LLC |
|
||||
| at info[AT]civicrm[DOT]org. If you have questions about the |
|
||||
| GNU Affero General Public License or the licensing of CiviCRM, |
|
||||
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
|
||||
+--------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @package CRM
|
||||
* @copyright CiviCRM LLC (c) 2004-2017
|
||||
*/
|
||||
class CRM_Utils_Check_Component_OptionGroups extends CRM_Utils_Check_Component {
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function checkOptionGroupValues() {
|
||||
$messages = array();
|
||||
$problemValues = array();
|
||||
$optionGroups = civicrm_api3('OptionGroup', 'get', array(
|
||||
'sequential' => 1,
|
||||
'data_type' => array('IS NOT NULL' => 1),
|
||||
'options' => array('limit' => 0),
|
||||
));
|
||||
if ($optionGroups['count'] > 0) {
|
||||
foreach ($optionGroups['values'] as $optionGroup) {
|
||||
$values = CRM_Core_BAO_OptionValue::getOptionValuesArray($optionGroup['id']);
|
||||
if (count($values) > 0) {
|
||||
foreach ($values as $value) {
|
||||
$validate = CRM_Utils_Type::validate($value['value'], $optionGroup['data_type'], FALSE);
|
||||
if (!$validate) {
|
||||
$problemValues[] = array(
|
||||
'group_name' => $optionGroup['title'],
|
||||
'value_name' => $value['label'],
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!empty($problemValues)) {
|
||||
$strings = '';
|
||||
foreach ($problemValues as $problemValue) {
|
||||
$strings .= ts('<tr><td> "%1" </td><td> "%2" </td></tr>', array(
|
||||
1 => $problemValue['group_name'],
|
||||
2 => $problemValue['value_name'],
|
||||
));
|
||||
}
|
||||
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
ts('The Following Option Values contain value fields that do not match the Data Type of the Option Group</p>
|
||||
<p><table><tbody><th>Option Group</th><th>Option Value</th></tbody><tbody>') .
|
||||
$strings . ts('</tbody></table></p>'),
|
||||
ts('Option Values with problematic Values'),
|
||||
\Psr\Log\LogLevel::NOTICE,
|
||||
'fa-server'
|
||||
);
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
+--------------------------------------------------------------------+
|
||||
| CiviCRM version 4.7 |
|
||||
+--------------------------------------------------------------------+
|
||||
| Copyright CiviCRM LLC (c) 2004-2016 |
|
||||
+--------------------------------------------------------------------+
|
||||
| This file is a part of CiviCRM. |
|
||||
| |
|
||||
| CiviCRM is free software; you can copy, modify, and distribute it |
|
||||
| under the terms of the GNU Affero General Public License |
|
||||
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
|
||||
| |
|
||||
| CiviCRM is distributed in the hope that it will be useful, but |
|
||||
| WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
|
||||
| See the GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| You should have received a copy of the GNU Affero General Public |
|
||||
| License and the CiviCRM Licensing Exception along |
|
||||
| with this program; if not, contact CiviCRM LLC |
|
||||
| at info[AT]civicrm[DOT]org. If you have questions about the |
|
||||
| GNU Affero General Public License or the licensing of CiviCRM, |
|
||||
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
|
||||
+--------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @package CRM
|
||||
* @copyright CiviCRM LLC (c) 2004-2016
|
||||
*/
|
||||
class CRM_Utils_Check_Component_PriceFields extends CRM_Utils_Check_Component {
|
||||
|
||||
/**
|
||||
* Display warning about invalid priceFields
|
||||
*
|
||||
*/
|
||||
public function checkPriceFields() {
|
||||
$sql = "SELECT DISTINCT ps.title as ps_title, ps.id as ps_id, psf.label as psf_label
|
||||
FROM civicrm_price_set ps
|
||||
INNER JOIN civicrm_price_field psf ON psf.price_set_id = ps.id
|
||||
INNER JOIN civicrm_price_field_value pfv ON pfv.price_field_id = psf.id
|
||||
LEFT JOIN civicrm_financial_type cft ON cft.id = pfv.financial_type_id
|
||||
WHERE cft.id IS NULL OR cft.is_active = 0";
|
||||
$dao = CRM_Core_DAO::executeQuery($sql);
|
||||
$count = 0;
|
||||
$html = '';
|
||||
$messages = array();
|
||||
while ($dao->fetch()) {
|
||||
$count++;
|
||||
$url = CRM_Utils_System::url('civicrm/admin/price/field', array(
|
||||
'reset' => 1,
|
||||
'action' => 'browse',
|
||||
'sid' => $dao->ps_id));
|
||||
$html .= "<tr><td>$dao->ps_title</td><td>$dao->psf_label</td><td><a href='$url'>View Price Set Fields</a></td></tr>";
|
||||
}
|
||||
if ($count > 0) {
|
||||
$msg = "<p>the following Price Set Fields use disabled or invalid financial types and need to be fixed if they are to still be used.<p>
|
||||
<p><table><thead><tr><th>Price Set</th><th>Price Set Field</th><th>Action Link</th>
|
||||
</tr></thead><tbody>
|
||||
$html
|
||||
</tbody></table></p>";
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
ts($msg),
|
||||
ts('Invalid Price Fields'),
|
||||
\Psr\Log\LogLevel::WARNING,
|
||||
'fa-lock'
|
||||
);
|
||||
}
|
||||
return $messages;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
<?php
|
||||
/*
|
||||
+--------------------------------------------------------------------+
|
||||
| CiviCRM version 4.7 |
|
||||
+--------------------------------------------------------------------+
|
||||
| Copyright CiviCRM LLC (c) 2004-2016 |
|
||||
+--------------------------------------------------------------------+
|
||||
| This file is a part of CiviCRM. |
|
||||
| |
|
||||
| CiviCRM is free software; you can copy, modify, and distribute it |
|
||||
| under the terms of the GNU Affero General Public License |
|
||||
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
|
||||
| |
|
||||
| CiviCRM is distributed in the hope that it will be useful, but |
|
||||
| WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
|
||||
| See the GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| You should have received a copy of the GNU Affero General Public |
|
||||
| License and the CiviCRM Licensing Exception along |
|
||||
| with this program; if not, contact CiviCRM LLC |
|
||||
| at info[AT]civicrm[DOT]org. If you have questions about the |
|
||||
| GNU Affero General Public License or the licensing of CiviCRM, |
|
||||
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
|
||||
+--------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @package CRM
|
||||
* @copyright CiviCRM LLC (c) 2004-2016
|
||||
*/
|
||||
class CRM_Utils_Check_Component_Schema extends CRM_Utils_Check_Component {
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function checkIndices() {
|
||||
$messages = array();
|
||||
$missingIndices = CRM_Core_BAO_SchemaHandler::getMissingIndices();
|
||||
if ($missingIndices) {
|
||||
$html = '';
|
||||
foreach ($missingIndices as $tableName => $indices) {
|
||||
foreach ($indices as $index) {
|
||||
$fields = implode(', ', $index['field']);
|
||||
$html .= "<tr><td>{$tableName}</td><td>{$index['name']}</td><td>$fields</td>";
|
||||
}
|
||||
}
|
||||
$message = "<p>The following tables have missing indices. Click 'Update Indices' button to create them.<p>
|
||||
<p><table><thead><tr><th>Table Name</th><th>Key Name</th><th>Expected Indices</th>
|
||||
</tr></thead><tbody>
|
||||
$html
|
||||
</tbody></table></p>";
|
||||
$msg = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
ts($message),
|
||||
ts('Performance warning: Missing indices'),
|
||||
\Psr\Log\LogLevel::WARNING,
|
||||
'fa-server'
|
||||
);
|
||||
$msg->addAction(
|
||||
ts('Update Indices'),
|
||||
ts('Update all database indices now? This may take a few minutes and cause a noticeable performance lag for all users while running.'),
|
||||
'api3',
|
||||
array('System', 'updateindexes')
|
||||
);
|
||||
$messages[] = $msg;
|
||||
}
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function checkMissingLogTables() {
|
||||
$messages = array();
|
||||
$logging = new CRM_Logging_Schema();
|
||||
$missingLogTables = $logging->getMissingLogTables();
|
||||
|
||||
if ($missingLogTables) {
|
||||
$msg = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
ts("You don't have logging enabled on some tables. This may cause errors on performing insert/update operation on them."),
|
||||
ts('Missing Log Tables'),
|
||||
\Psr\Log\LogLevel::WARNING,
|
||||
'fa-server'
|
||||
);
|
||||
$msg->addAction(
|
||||
ts('Create Missing Log Tables'),
|
||||
ts('Create missing log tables now? This may take few minutes.'),
|
||||
'api3',
|
||||
array('System', 'createmissinglogtables')
|
||||
);
|
||||
$messages[] = $msg;
|
||||
}
|
||||
return $messages;
|
||||
}
|
||||
|
||||
}
|
407
sites/all/modules/civicrm/CRM/Utils/Check/Component/Security.php
Normal file
407
sites/all/modules/civicrm/CRM/Utils/Check/Component/Security.php
Normal file
|
@ -0,0 +1,407 @@
|
|||
<?php
|
||||
/*
|
||||
+--------------------------------------------------------------------+
|
||||
| CiviCRM version 4.7 |
|
||||
+--------------------------------------------------------------------+
|
||||
| Copyright CiviCRM LLC (c) 2004-2017 |
|
||||
+--------------------------------------------------------------------+
|
||||
| This file is a part of CiviCRM. |
|
||||
| |
|
||||
| CiviCRM is free software; you can copy, modify, and distribute it |
|
||||
| under the terms of the GNU Affero General Public License |
|
||||
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
|
||||
| |
|
||||
| CiviCRM is distributed in the hope that it will be useful, but |
|
||||
| WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
|
||||
| See the GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| You should have received a copy of the GNU Affero General Public |
|
||||
| License and the CiviCRM Licensing Exception along |
|
||||
| with this program; if not, contact CiviCRM LLC |
|
||||
| at info[AT]civicrm[DOT]org. If you have questions about the |
|
||||
| GNU Affero General Public License or the licensing of CiviCRM, |
|
||||
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
|
||||
+--------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @package CRM
|
||||
* @copyright CiviCRM LLC (c) 2004-2017
|
||||
*/
|
||||
class CRM_Utils_Check_Component_Security extends CRM_Utils_Check_Component {
|
||||
|
||||
/**
|
||||
* CMS have a different pattern to their default file path and URL.
|
||||
*
|
||||
* @todo Use Civi::paths instead?
|
||||
*/
|
||||
public function getFilePathMarker() {
|
||||
$config = CRM_Core_Config::singleton();
|
||||
switch ($config->userFramework) {
|
||||
case 'Joomla':
|
||||
return '/media/';
|
||||
|
||||
default:
|
||||
return '/files/';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if our logfile is directly accessible.
|
||||
*
|
||||
* Per CiviCRM default the logfile sits in a folder which is
|
||||
* web-accessible, and is protected by a default .htaccess
|
||||
* configuration. If server config causes the .htaccess not to
|
||||
* function as intended, there may be information disclosure.
|
||||
*
|
||||
* The debug log may be jam-packed with sensitive data, we don't
|
||||
* want that.
|
||||
*
|
||||
* Being able to be retrieved directly doesn't mean the logfile
|
||||
* is browseable or visible to search engines; it means it can be
|
||||
* requested directly.
|
||||
*
|
||||
* @return array
|
||||
* Array of messages
|
||||
* @see CRM-14091
|
||||
*/
|
||||
public function checkLogFileIsNotAccessible() {
|
||||
$messages = array();
|
||||
|
||||
$config = CRM_Core_Config::singleton();
|
||||
|
||||
$log = CRM_Core_Error::createDebugLogger();
|
||||
$log_filename = str_replace('\\', '/', $log->_filename);
|
||||
|
||||
$filePathMarker = $this->getFilePathMarker();
|
||||
|
||||
// Hazard a guess at the URL of the logfile, based on common
|
||||
// CiviCRM layouts.
|
||||
if ($upload_url = explode($filePathMarker, $config->imageUploadURL)) {
|
||||
$url[] = $upload_url[0];
|
||||
if ($log_path = explode($filePathMarker, $log_filename)) {
|
||||
// CRM-17149: check if debug log path includes $filePathMarker
|
||||
if (count($log_path) > 1) {
|
||||
$url[] = $log_path[1];
|
||||
$log_url = implode($filePathMarker, $url);
|
||||
$headers = @get_headers($log_url);
|
||||
if (stripos($headers[0], '200')) {
|
||||
$docs_url = $this->createDocUrl('checkLogFileIsNotAccessible');
|
||||
$msg = 'The <a href="%1">CiviCRM debug log</a> should not be downloadable.'
|
||||
. '<br />' .
|
||||
'<a href="%2">Read more about this warning</a>';
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
ts($msg, array(1 => $log_url, 2 => $docs_url)),
|
||||
ts('Security Warning'),
|
||||
\Psr\Log\LogLevel::WARNING,
|
||||
'fa-lock'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if our uploads directory has accessible files.
|
||||
*
|
||||
* We'll test a handful of files randomly. Hazard a guess at the URL
|
||||
* of the uploads dir, based on common CiviCRM layouts. Try and
|
||||
* request the files, and if any are successfully retrieved, warn.
|
||||
*
|
||||
* Being retrievable doesn't mean the files are browseable or visible
|
||||
* to search engines; it only means they can be requested directly.
|
||||
*
|
||||
* @return array
|
||||
* Array of messages
|
||||
* @see CRM-14091
|
||||
*
|
||||
* @todo Test with WordPress, Joomla.
|
||||
*/
|
||||
public function checkUploadsAreNotAccessible() {
|
||||
$messages = array();
|
||||
|
||||
$config = CRM_Core_Config::singleton();
|
||||
$privateDirs = array(
|
||||
$config->uploadDir,
|
||||
$config->customFileUploadDir,
|
||||
);
|
||||
|
||||
foreach ($privateDirs as $privateDir) {
|
||||
$heuristicUrl = $this->guessUrl($privateDir);
|
||||
if ($this->isDirAccessible($privateDir, $heuristicUrl)) {
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
ts('Files in the data directory (<a href="%3">%2</a>) should not be downloadable.'
|
||||
. '<br />'
|
||||
. '<a href="%1">Read more about this warning</a>',
|
||||
array(
|
||||
1 => $this->createDocUrl('checkUploadsAreNotAccessible'),
|
||||
2 => $privateDir,
|
||||
3 => $heuristicUrl,
|
||||
)),
|
||||
ts('Private Files Readable'),
|
||||
\Psr\Log\LogLevel::WARNING,
|
||||
'fa-lock'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if our uploads or ConfigAndLog directories have browseable
|
||||
* listings.
|
||||
*
|
||||
* Retrieve a listing of files from the local filesystem, and the
|
||||
* corresponding path via HTTP. Then check and see if the local
|
||||
* files are represented in the HTTP result; if so then warn. This
|
||||
* MAY trigger false positives (if you have files named 'a', 'e'
|
||||
* we'll probably match that).
|
||||
*
|
||||
* @return array
|
||||
* Array of messages
|
||||
* @see CRM-14091
|
||||
*
|
||||
* @todo Test with WordPress, Joomla.
|
||||
*/
|
||||
public function checkDirectoriesAreNotBrowseable() {
|
||||
$messages = array();
|
||||
$config = CRM_Core_Config::singleton();
|
||||
$publicDirs = array(
|
||||
$config->imageUploadDir => $config->imageUploadURL,
|
||||
);
|
||||
|
||||
// Setup index.html files to prevent browsing
|
||||
foreach ($publicDirs as $publicDir => $publicUrl) {
|
||||
CRM_Utils_File::restrictBrowsing($publicDir);
|
||||
}
|
||||
|
||||
// Test that $publicDir is not browsable
|
||||
foreach ($publicDirs as $publicDir => $publicUrl) {
|
||||
if ($this->isBrowsable($publicDir, $publicUrl)) {
|
||||
$msg = 'Directory <a href="%1">%2</a> should not be browseable via the web.'
|
||||
. '<br />' .
|
||||
'<a href="%3">Read more about this warning</a>';
|
||||
$docs_url = $this->createDocUrl('checkDirectoriesAreNotBrowseable');
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
ts($msg, array(1 => $publicDir, 2 => $publicDir, 3 => $docs_url)),
|
||||
ts('Browseable Directories'),
|
||||
\Psr\Log\LogLevel::ERROR,
|
||||
'fa-lock'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check that some files are not present.
|
||||
*
|
||||
* These files have generally been deleted but Civi source tree but could be
|
||||
* left online if one does a faulty upgrade.
|
||||
*
|
||||
* @return array of messages
|
||||
*/
|
||||
public function checkFilesAreNotPresent() {
|
||||
global $civicrm_root;
|
||||
|
||||
$messages = array();
|
||||
$files = array(
|
||||
array(
|
||||
// CRM-16005, upgraded from Civi <= 4.5.6
|
||||
"{$civicrm_root}/packages/dompdf/dompdf.php",
|
||||
\Psr\Log\LogLevel::CRITICAL,
|
||||
),
|
||||
array(
|
||||
// CRM-16005, Civi >= 4.5.7
|
||||
"{$civicrm_root}/packages/vendor/dompdf/dompdf/dompdf.php",
|
||||
\Psr\Log\LogLevel::CRITICAL,
|
||||
),
|
||||
array(
|
||||
// CRM-16005, Civi >= 4.6.0
|
||||
"{$civicrm_root}/vendor/dompdf/dompdf/dompdf.php",
|
||||
\Psr\Log\LogLevel::CRITICAL,
|
||||
),
|
||||
array(
|
||||
// CIVI-SA-2013-001
|
||||
"{$civicrm_root}/packages/OpenFlashChart/php-ofc-library/ofc_upload_image.php",
|
||||
\Psr\Log\LogLevel::CRITICAL,
|
||||
),
|
||||
array(
|
||||
"{$civicrm_root}/packages/html2text/class.html2text.inc",
|
||||
\Psr\Log\LogLevel::CRITICAL,
|
||||
),
|
||||
);
|
||||
foreach ($files as $file) {
|
||||
if (file_exists($file[0])) {
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
ts('File \'%1\' presents a security risk and should be deleted.', array(1 => $file[0])),
|
||||
ts('Unsafe Files'),
|
||||
$file[1],
|
||||
'fa-lock'
|
||||
);
|
||||
}
|
||||
}
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Discourage use of remote profile forms.
|
||||
*/
|
||||
public function checkRemoteProfile() {
|
||||
$messages = array();
|
||||
|
||||
if (Civi::settings()->get('remote_profile_submissions')) {
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
ts('Warning: External profile support (aka "HTML Snippet" support) is enabled in <a href="%1">system settings</a>. This setting may be prone to abuse. If you must retain it, consider HTTP throttling or other protections.',
|
||||
array(1 => CRM_Utils_System::url('civicrm/admin/setting/misc', 'reset=1'))
|
||||
),
|
||||
ts('Remote Profiles Enabled'),
|
||||
\Psr\Log\LogLevel::WARNING,
|
||||
'fa-lock'
|
||||
);
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check that the sysadmin has not modified the Cxn
|
||||
* security setup.
|
||||
*/
|
||||
public function checkCxnOverrides() {
|
||||
$list = array();
|
||||
if (defined('CIVICRM_CXN_CA') && CIVICRM_CXN_CA !== 'CiviRootCA') {
|
||||
$list[] = 'CIVICRM_CXN_CA';
|
||||
}
|
||||
if (defined('CIVICRM_CXN_APPS_URL') && CIVICRM_CXN_APPS_URL !== \Civi\Cxn\Rpc\Constants::OFFICIAL_APPMETAS_URL) {
|
||||
$list[] = 'CIVICRM_CXN_APPS_URL';
|
||||
}
|
||||
|
||||
$messages = array();
|
||||
|
||||
if (!empty($list)) {
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
ts('The system administrator has disabled security settings (%1). Connections to remote applications are insecure.', array(
|
||||
1 => implode(', ', $list),
|
||||
)),
|
||||
ts('Security Warning'),
|
||||
\Psr\Log\LogLevel::WARNING,
|
||||
'fa-lock'
|
||||
);
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether $url is a public, browsable listing for $dir
|
||||
*
|
||||
* @param string $dir
|
||||
* Local dir path.
|
||||
* @param string $url
|
||||
* Public URL.
|
||||
* @return bool
|
||||
*/
|
||||
public function isBrowsable($dir, $url) {
|
||||
if (empty($dir) || empty($url) || !is_dir($dir)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$result = FALSE;
|
||||
|
||||
// this could be a new system with no uploads (yet) -- so we'll make a file
|
||||
$file = CRM_Utils_File::createFakeFile($dir);
|
||||
|
||||
if ($file === FALSE) {
|
||||
// Couldn't write the file
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$content = @file_get_contents("$url");
|
||||
if (stristr($content, $file)) {
|
||||
$result = TRUE;
|
||||
}
|
||||
unlink("$dir/$file");
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether $url is a public version of $dir in which files
|
||||
* are remotely accessible.
|
||||
*
|
||||
* @param string $dir
|
||||
* Local dir path.
|
||||
* @param string $url
|
||||
* Public URL.
|
||||
* @return bool
|
||||
*/
|
||||
public function isDirAccessible($dir, $url) {
|
||||
$url = rtrim($url, '/');
|
||||
if (empty($dir) || empty($url) || !is_dir($dir)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$result = FALSE;
|
||||
$file = CRM_Utils_File::createFakeFile($dir, 'delete me');
|
||||
|
||||
if ($file === FALSE) {
|
||||
// Couldn't write the file
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$headers = @get_headers("$url/$file");
|
||||
if (stripos($headers[0], '200')) {
|
||||
$content = @file_get_contents("$url/$file");
|
||||
if (preg_match('/delete me/', $content)) {
|
||||
$result = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
unlink("$dir/$file");
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $topic
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function createDocUrl($topic) {
|
||||
return CRM_Utils_System::getWikiBaseURL() . $topic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a guess about the URL that corresponds to $targetDir.
|
||||
*
|
||||
* @param string $targetDir
|
||||
* Local path to a directory.
|
||||
* @return string
|
||||
* a guessed URL for $realDir
|
||||
*/
|
||||
public function guessUrl($targetDir) {
|
||||
$filePathMarker = $this->getFilePathMarker();
|
||||
$config = CRM_Core_Config::singleton();
|
||||
|
||||
list($heuristicBaseUrl) = explode($filePathMarker, $config->imageUploadURL);
|
||||
list(, $heuristicSuffix) = array_pad(explode($filePathMarker, str_replace('\\', '/', $targetDir)), 2, '');
|
||||
return $heuristicBaseUrl . $filePathMarker . $heuristicSuffix;
|
||||
}
|
||||
|
||||
}
|
122
sites/all/modules/civicrm/CRM/Utils/Check/Component/Source.php
Normal file
122
sites/all/modules/civicrm/CRM/Utils/Check/Component/Source.php
Normal file
|
@ -0,0 +1,122 @@
|
|||
<?php
|
||||
/*
|
||||
+--------------------------------------------------------------------+
|
||||
| CiviCRM version 4.7 |
|
||||
+--------------------------------------------------------------------+
|
||||
| Copyright CiviCRM LLC (c) 2004-2017 |
|
||||
+--------------------------------------------------------------------+
|
||||
| This file is a part of CiviCRM. |
|
||||
| |
|
||||
| CiviCRM is free software; you can copy, modify, and distribute it |
|
||||
| under the terms of the GNU Affero General Public License |
|
||||
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
|
||||
| |
|
||||
| CiviCRM is distributed in the hope that it will be useful, but |
|
||||
| WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
|
||||
| See the GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| You should have received a copy of the GNU Affero General Public |
|
||||
| License and the CiviCRM Licensing Exception along |
|
||||
| with this program; if not, contact CiviCRM LLC |
|
||||
| at info[AT]civicrm[DOT]org. If you have questions about the |
|
||||
| GNU Affero General Public License or the licensing of CiviCRM, |
|
||||
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
|
||||
+--------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @package CRM
|
||||
* @copyright CiviCRM LLC (c) 2004-2017
|
||||
*/
|
||||
class CRM_Utils_Check_Component_Source extends CRM_Utils_Check_Component {
|
||||
|
||||
public function getRemovedFiles() {
|
||||
$files[] = '[civicrm.packages]/Auth/SASL';
|
||||
$files[] = '[civicrm.packages]/Auth/SASL.php';
|
||||
$files[] = '[civicrm.packages]/Net/SMTP.php';
|
||||
$files[] = '[civicrm.packages]/Net/Socket.php';
|
||||
$files[] = '[civicrm.packages]/_ORIGINAL_/Net/SMTP.php';
|
||||
$files[] = '[civicrm.packages]/jquery/plugins/DataTables/Readme.md';
|
||||
$files[] = '[civicrm.packages]/jquery/plugins/DataTables/license.txt';
|
||||
$files[] = '[civicrm.packages]/jquery/plugins/DataTables/media/css/jquery.dataTables.css';
|
||||
$files[] = '[civicrm.packages]/jquery/plugins/DataTables/media/css/jquery.dataTables.min.css';
|
||||
$files[] = '[civicrm.packages]/jquery/plugins/DataTables/media/css/jquery.dataTables_themeroller.css';
|
||||
$files[] = '[civicrm.packages]/jquery/plugins/DataTables/media/js/jquery.dataTables.js';
|
||||
$files[] = '[civicrm.packages]/jquery/plugins/DataTables/media/js/jquery.dataTables.min.js';
|
||||
$files[] = '[civicrm.packages]/jquery/plugins/DataTables/media/js/jquery.js';
|
||||
$files[] = '[civicrm.vendor]/pear/net_smtp/examples';
|
||||
$files[] = '[civicrm.vendor]/pear/net_smtp/tests';
|
||||
$files[] = '[civicrm.vendor]/pear/net_smtp/phpdoc.sh';
|
||||
$files[] = '[civicrm.vendor]/phpoffice/phpword/samples';
|
||||
|
||||
return $files;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* Each item is an array with keys:
|
||||
* - name: string, an abstract name
|
||||
* - path: string, a full file path
|
||||
* Files are returned in deletable order (ie children before parents).
|
||||
*/
|
||||
public function findOrphanedFiles() {
|
||||
$orphans = array();
|
||||
|
||||
foreach ($this->getRemovedFiles() as $file) {
|
||||
$path = Civi::paths()->getPath($file);
|
||||
if (empty($path) || strpos('[civicrm', $path) !== FALSE) {
|
||||
Civi::log()->warning('Failed to resolve path of old file \"{file}\" ({path})', array(
|
||||
'file' => $file,
|
||||
'path' => $path,
|
||||
));
|
||||
}
|
||||
if (file_exists($path)) {
|
||||
$orphans[] = array(
|
||||
'name' => $file,
|
||||
'path' => $path,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
usort($orphans, function ($a, $b) {
|
||||
// Children first, then parents.
|
||||
$diff = strlen($b['name']) - strlen($a['name']);
|
||||
if ($diff !== 0) {
|
||||
return $diff;
|
||||
}
|
||||
if ($a['name'] === $b['name']) {
|
||||
return 0;
|
||||
}
|
||||
return $a['name'] < $b['name'] ? -1 : 1;
|
||||
});
|
||||
|
||||
return $orphans;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function checkOrphans() {
|
||||
$orphans = $this->findOrphanedFiles();
|
||||
if (empty($orphans)) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$messages = array();
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__,
|
||||
ts('The local system includes old files which should not exist: "%1"',
|
||||
array(
|
||||
1 => implode('", "', CRM_Utils_Array::collect('path', $orphans)),
|
||||
)),
|
||||
ts('Old files'),
|
||||
\Psr\Log\LogLevel::WARNING,
|
||||
'fa-server'
|
||||
);
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,138 @@
|
|||
<?php
|
||||
/*
|
||||
+--------------------------------------------------------------------+
|
||||
| CiviCRM version 4.7 |
|
||||
+--------------------------------------------------------------------+
|
||||
| Copyright CiviCRM LLC (c) 2004-2017 |
|
||||
+--------------------------------------------------------------------+
|
||||
| This file is a part of CiviCRM. |
|
||||
| |
|
||||
| CiviCRM is free software; you can copy, modify, and distribute it |
|
||||
| under the terms of the GNU Affero General Public License |
|
||||
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
|
||||
| |
|
||||
| CiviCRM is distributed in the hope that it will be useful, but |
|
||||
| WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
|
||||
| See the GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| You should have received a copy of the GNU Affero General Public |
|
||||
| License and the CiviCRM Licensing Exception along |
|
||||
| with this program; if not, contact CiviCRM LLC |
|
||||
| at info[AT]civicrm[DOT]org. If you have questions about the |
|
||||
| GNU Affero General Public License or the licensing of CiviCRM, |
|
||||
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
|
||||
+--------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @package CRM
|
||||
* @copyright CiviCRM LLC (c) 2004-2017
|
||||
*/
|
||||
class CRM_Utils_Check_Component_Timestamps extends CRM_Utils_Check_Component {
|
||||
|
||||
const DOCTOR_WHEN = 'https://github.com/civicrm/org.civicrm.doctorwhen';
|
||||
|
||||
/**
|
||||
* Check that various columns are TIMESTAMP and not DATETIME. (CRM-9683, etal)
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function checkSchema() {
|
||||
$problems = array();
|
||||
foreach (self::getConvertedTimestamps() as $target) {
|
||||
if (self::isFieldType($target['table'], $target['column'], 'datetime')) {
|
||||
$phrases = array();
|
||||
$phrases[] = sprintf('<em>%s.%s</em>', $target['table'], $target['column']);
|
||||
|
||||
if ($target['changed']) {
|
||||
$phrases[] = sprintf('(New sites default to TIMESTAMP in v%s+)', $target['changed']);
|
||||
}
|
||||
else {
|
||||
$phrases[] = '(Experimental suggestion)';
|
||||
}
|
||||
|
||||
if (isset($target['jira'])) {
|
||||
$phrases[] = sprintf(' [<a href="https://issues.civicrm.org/jira/browse/%s" target="_blank">%s</a>]', $target['jira'], $target['jira']);
|
||||
}
|
||||
|
||||
$problems[] = implode(' ', $phrases);
|
||||
}
|
||||
}
|
||||
|
||||
$messages = array();
|
||||
if ($problems) {
|
||||
$messages[] = new CRM_Utils_Check_Message(
|
||||
__FUNCTION__ . md5(implode(',', $problems)),
|
||||
'<p>' .
|
||||
ts('This MySQL database stores certain fields with data-type "DATETIME". To improve timezone support, you <em>may</em> want to change these from "DATETIME" to "TIMESTAMP".') .
|
||||
'</p>' .
|
||||
'<ul><li>' .
|
||||
implode('</li><li>', $problems) .
|
||||
'</li></ul>' .
|
||||
'<p>' .
|
||||
ts('Changing should improve data-quality for organizations working in multiple timezones. However, if you do change, then you may need to re-test any customizations or processes that reference these fields. Changing is <em>suggested</em> but not <em>required</em>.') .
|
||||
'</p>' .
|
||||
'<p>' .
|
||||
ts('For further discussion, please visit %1', array(
|
||||
1 => sprintf('<a href="%s" target="_blank">%s</a>', self::DOCTOR_WHEN, self::DOCTOR_WHEN),
|
||||
)) .
|
||||
'</p>',
|
||||
ts('Timestamps and Timezones'),
|
||||
\Psr\Log\LogLevel::NOTICE,
|
||||
'fa-clock-o'
|
||||
);
|
||||
}
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $table
|
||||
* Ex: 'civicrm_log'.
|
||||
* @param string $column
|
||||
* Ex: 'modified_date'.
|
||||
* @param string $expectType
|
||||
* Ex: 'datetime' or 'timestamp'.
|
||||
* @return bool
|
||||
*/
|
||||
public static function isFieldType($table, $column, $expectType) {
|
||||
$result = FALSE;
|
||||
$dao = CRM_Core_DAO::executeQuery('DESC ' . $table);
|
||||
while ($dao->fetch()) {
|
||||
if ($dao->Field === $column && strtolower($dao->Type) === $expectType) {
|
||||
$result = TRUE;
|
||||
}
|
||||
}
|
||||
$dao->free();
|
||||
return $result;
|
||||
}
|
||||
|
||||
public static function getConvertedTimestamps() {
|
||||
return array(
|
||||
array('table' => 'civicrm_cache', 'column' => 'created_date', 'changed' => '4.7.20', 'default' => 'CURRENT_TIMESTAMP', 'jira' => 'CRM-9683', 'comment' => 'When was the cache item created'),
|
||||
array('table' => 'civicrm_cache', 'column' => 'expired_date', 'changed' => '4.7.20', 'jira' => 'CRM-9683', 'comment' => 'When should the cache item expire'),
|
||||
array('table' => 'civicrm_job', 'column' => 'last_run', 'changed' => '4.7.20', 'jira' => 'CRM-9683', 'comment' => 'When was this cron entry last run'),
|
||||
array('table' => 'civicrm_mailing_event_bounce', 'column' => 'time_stamp', 'changed' => '4.7.20', 'default' => 'CURRENT_TIMESTAMP', 'jira' => 'CRM-9683', 'comment' => 'When this bounce event occurred.'),
|
||||
array('table' => 'civicrm_mailing_event_confirm', 'column' => 'time_stamp', 'changed' => '4.7.20', 'default' => 'CURRENT_TIMESTAMP', 'jira' => 'CRM-9683', 'comment' => 'When this confirmation event occurred.'),
|
||||
array('table' => 'civicrm_mailing_event_delivered', 'column' => 'time_stamp', 'changed' => '4.7.20', 'default' => 'CURRENT_TIMESTAMP', 'jira' => 'CRM-9683', 'comment' => 'When this delivery event occurred.'),
|
||||
array('table' => 'civicrm_mailing_event_forward', 'column' => 'time_stamp', 'changed' => '4.7.20', 'default' => 'CURRENT_TIMESTAMP', 'jira' => 'CRM-9683', 'comment' => 'When this forward event occurred.'),
|
||||
array('table' => 'civicrm_mailing_event_opened', 'column' => 'time_stamp', 'changed' => '4.7.20', 'default' => 'CURRENT_TIMESTAMP', 'jira' => 'CRM-9683', 'comment' => 'When this open event occurred.'),
|
||||
array('table' => 'civicrm_mailing_event_reply', 'column' => 'time_stamp', 'changed' => '4.7.20', 'default' => 'CURRENT_TIMESTAMP', 'jira' => 'CRM-9683', 'comment' => 'When this reply event occurred.'),
|
||||
array('table' => 'civicrm_mailing_event_subscribe', 'column' => 'time_stamp', 'changed' => '4.7.20', 'default' => 'CURRENT_TIMESTAMP', 'jira' => 'CRM-9683', 'comment' => 'When this subscription event occurred.'),
|
||||
array('table' => 'civicrm_mailing_event_trackable_url_open', 'column' => 'time_stamp', 'changed' => '4.7.20', 'default' => 'CURRENT_TIMESTAMP', 'jira' => 'CRM-9683', 'comment' => 'When this trackable URL open occurred.'),
|
||||
array('table' => 'civicrm_mailing_event_unsubscribe', 'column' => 'time_stamp', 'changed' => '4.7.20', 'default' => 'CURRENT_TIMESTAMP', 'jira' => 'CRM-9683', 'comment' => 'When this delivery event occurred.'),
|
||||
array('table' => 'civicrm_mailing', 'column' => 'created_date', 'changed' => '4.7.20', 'jira' => 'CRM-9683', 'comment' => 'Date and time this mailing was created.'),
|
||||
array('table' => 'civicrm_mailing', 'column' => 'scheduled_date', 'changed' => '4.7.20', 'jira' => 'CRM-9683', 'comment' => 'Date and time this mailing was scheduled.'),
|
||||
array('table' => 'civicrm_mailing', 'column' => 'approval_date', 'changed' => '4.7.20', 'jira' => 'CRM-9683', 'comment' => 'Date and time this mailing was approved.'),
|
||||
array('table' => 'civicrm_mailing_abtest', 'column' => 'created_date', 'changed' => '4.7.20', 'default' => 'CURRENT_TIMESTAMP', 'jira' => 'CRM-9683', 'comment' => 'When was this item created'),
|
||||
array('table' => 'civicrm_mailing_job', 'column' => 'scheduled_date', 'changed' => '4.7.20', 'jira' => 'CRM-9683', 'comment' => 'date on which this job was scheduled.'),
|
||||
array('table' => 'civicrm_mailing_job', 'column' => 'start_date', 'changed' => '4.7.20', 'jira' => 'CRM-9683', 'comment' => 'date on which this job was started.'),
|
||||
array('table' => 'civicrm_mailing_job', 'column' => 'end_date', 'changed' => '4.7.20', 'jira' => 'CRM-9683', 'comment' => 'date on which this job ended.'),
|
||||
array('table' => 'civicrm_mailing_spool', 'column' => 'added_at', 'changed' => '4.7.20', 'jira' => 'CRM-9683', 'comment' => 'date on which this job was added.'),
|
||||
array('table' => 'civicrm_mailing_spool', 'column' => 'removed_at', 'changed' => '4.7.20', 'jira' => 'CRM-9683', 'comment' => 'date on which this job was removed.'),
|
||||
array('table' => 'civicrm_subscription_history', 'column' => 'date', 'changed' => '4.7.27', 'default' => 'CURRENT_TIMESTAMP', 'jira' => 'CRM-21157', 'comment' => 'Date of the (un)subscription'),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue