3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.4 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2013 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
31 * @copyright CiviCRM LLC (c) 2004-2013
37 * System wide utilities.
40 class CRM_Utils_System
{
42 static $_callbacks = NULL;
45 * @var string Page title
50 * Compose a new url string from the current url string.
52 * Used by all the framework components, specifically,
55 * @param string $urlVar
56 * The url variable being considered (i.e. crmPageID, crmSortID etc).
57 * @param bool $includeReset
58 * (optional) Whether to include the reset GET string (if present).
59 * @param bool $includeForce
60 * (optional) Whether to include the force GET string (if present).
62 * (optional) The path to use for the new url.
63 * @param string $absolute
64 * (optional) Whether to return an absolute URL.
70 static function makeURL($urlVar, $includeReset = FALSE, $includeForce = TRUE, $path = NULL, $absolute = FALSE) {
72 $config = CRM_Core_Config
::singleton();
73 $path = CRM_Utils_Array
::value($config->userFrameworkURLVar
, $_GET);
82 CRM_Utils_System
::getLinksUrl($urlVar, $includeReset, $includeForce),
88 * Get the query string and clean it up.
90 * Strips some variables that should not be propagated, specically variables
91 * like 'reset'. Also strips any side-affect actions (e.g. export).
93 * This function is copied mostly verbatim from Pager.php (_getLinksUrl)
95 * @param string $urlVar
96 * The URL variable being considered (e.g. crmPageID, crmSortID etc).
97 * @param bool $includeReset
98 * (optional) Whether to include the reset var (generally this variable
100 * @param bool $includeForce
101 * @param bool $skipUFVar
106 static function getLinksUrl($urlVar, $includeReset = FALSE, $includeForce = TRUE, $skipUFVar = TRUE) {
107 // Sort out query string to prevent messy urls
108 $querystring = array();
112 if (!empty($_SERVER['QUERY_STRING'])) {
113 $qs = explode('&', str_replace('&', '&', $_SERVER['QUERY_STRING']));
114 for ($i = 0, $cnt = count($qs); $i < $cnt; $i++
) {
115 // check first if exist a pair
116 if (strstr($qs[$i], '=') !== FALSE) {
117 list($name, $value) = explode('=', $qs[$i]);
118 if ($name != $urlVar) {
119 $name = rawurldecode($name);
120 //check for arrays in parameters: site.php?foo[]=1&foo[]=2&foo[]=3
121 if ((strpos($name, '[') !== FALSE) &&
122 (strpos($name, ']') !== FALSE)
142 // Ok this is a big assumption but usually works
143 // If we are in snippet mode, retain the 'section' param, if not, get rid of it.
144 if (!empty($qs['snippet'])) {
145 unset($qs['snippet']);
148 unset($qs['section']);
152 $config = CRM_Core_Config
::singleton();
153 unset($qs[$config->userFrameworkURLVar
]);
156 foreach ($qs as $name => $value) {
157 if ($name != 'reset' ||
$includeReset) {
158 $querystring[] = $name . '=' . $value;
162 $querystring = array_merge($querystring, array_unique($arrays));
164 $url = implode('&', $querystring);
166 $url .= (!empty($querystring) ?
'&' : '') . $urlVar . '=';
173 * If we are using a theming system, invoke theme, else just print the
176 * @param string $content
177 * The content that will be themed.
179 * (optional) Are we displaying to the screen or bypassing theming?
180 * @param bool $maintenance
181 * (optional) For maintenance mode.
183 * @return void prints content on stdout
187 static function theme(
192 $config = &CRM_Core_Config
::singleton();
193 return $config->userSystem
->theme($content, $print, $maintenance);
197 * Generate a query string if input is an array.
199 * @param array|string $query
204 static function makeQueryString($query) {
205 if (is_array($query)) {
207 foreach ($query as $key => $value) {
208 $buf .= ($buf ?
'&' : '') . urlencode($key) . '=' . urlencode($value);
216 * Generate an internal CiviCRM URL.
218 * @param string $path
219 * The path being linked to, such as "civicrm/add".
220 * @param array|string $query
221 * A query string to append to the link, or an array of key-value pairs.
222 * @param bool $absolute
223 * Whether to force the output to be an absolute link (beginning with a
224 * URI-scheme such as http:). Useful for links that will be displayed
225 * outside the site, such as in an RSS feed.
226 * @param string $fragment
227 * A fragment identifier (named anchor) to append to the link.
229 * @param bool $htmlize
230 * @param bool $frontend
231 * @param bool $forceBackend
233 * An HTML string containing a link to the given path.
244 $forceBackend = FALSE
246 $query = self
::makeQueryString($query);
248 // we have a valid query and it has not yet been transformed
249 if ($htmlize && !empty($query) && strpos($query, '&') === FALSE) {
250 $query = htmlentities($query);
253 $config = CRM_Core_Config
::singleton();
254 return $config->userSystem
->url($path, $query, $absolute, $fragment, $htmlize, $frontend, $forceBackend);
257 static function href($text, $path = NULL, $query = NULL, $absolute = TRUE,
258 $fragment = NULL, $htmlize = TRUE, $frontend = FALSE, $forceBackend = FALSE
260 $url = self
::url($path, $query, $absolute, $fragment, $htmlize, $frontend, $forceBackend);
261 return "<a href=\"$url\">$text</a>";
264 static function permissionDenied() {
265 $config = CRM_Core_Config
::singleton();
266 return $config->userSystem
->permissionDenied();
269 static function logout() {
270 $config = CRM_Core_Config
::singleton();
271 return $config->userSystem
->logout();
274 // this is a very drupal specific function for now
275 static function updateCategories() {
276 $config = CRM_Core_Config
::singleton();
277 if ($config->userSystem
->is_drupal
) {
278 $config->userSystem
->updateCategories();
283 * What menu path are we currently on. Called for the primary tpl
285 * @return string the current menu path
288 static function currentPath() {
289 $config = CRM_Core_Config
::singleton();
290 return trim(CRM_Utils_Array
::value($config->userFrameworkURLVar
, $_GET), '/');
294 * This function is called from a template to compose a url.
296 * @param array $params
297 * List of parameters.
303 static function crmURL($params) {
304 $p = CRM_Utils_Array
::value('p', $params);
306 $p = self
::currentPath();
311 CRM_Utils_Array
::value('q', $params),
312 CRM_Utils_Array
::value('a', $params, FALSE),
313 CRM_Utils_Array
::value('f', $params),
314 CRM_Utils_Array
::value('h', $params, TRUE),
315 CRM_Utils_Array
::value('fe', $params, FALSE),
316 CRM_Utils_Array
::value('fb', $params, FALSE)
321 * Sets the title of the page.
323 * @param string $title
324 * @param string $pageTitle
330 static function setTitle($title, $pageTitle = NULL) {
331 self
::$title = $title;
332 $config = CRM_Core_Config
::singleton();
333 return $config->userSystem
->setTitle($title, $pageTitle);
337 * Figures and sets the userContext.
339 * Uses the referer if valid else uses the default.
341 * @param array $names
342 * Refererer should match any str in this array.
343 * @param string $default
344 * (optional) The default userContext if no match found.
348 static function setUserContext($names, $default = NULL) {
351 $session = CRM_Core_Session
::singleton();
352 $referer = CRM_Utils_Array
::value('HTTP_REFERER', $_SERVER);
354 if ($referer && !empty($names)) {
355 foreach ($names as $name) {
356 if (strstr($referer, $name)) {
364 $session->pushUserContext($url);
369 * Gets a class name for an object.
371 * @param object $object
372 * Object whose class name is needed.
375 * The class name of the object.
380 static function getClassName($object) {
381 return get_class($object);
385 * Redirect to another URL.
388 * The URL to provide to the browser via the Location header.
393 static function redirect($url = NULL) {
395 $url = self
::url('civicrm/dashboard', 'reset=1');
398 // replace the & characters with &
399 // this is kinda hackish but not sure how to do it right
400 $url = str_replace('&', '&', $url);
401 header('Location: ' . $url);
406 * Redirect to another URL using JavaScript.
408 * Use an html based file with javascript embedded to redirect to another url
409 * This prevent the too many redirect errors emitted by various browsers
412 * (optional) The destination URL.
413 * @param string $title
414 * (optional) The page title to use for the redirect page.
415 * @param string $message
416 * (optional) The message to provide in the body of the redirect page.
421 static function jsRedirect(
427 $url = self
::url('civicrm/dashboard', 'reset=1');
431 $title = ts('CiviCRM task in progress');
435 $message = ts('A long running CiviCRM task is currently in progress. This message will be refreshed till the task is completed');
438 // replace the & characters with &
439 // this is kinda hackish but not sure how to do it right
440 $url = str_replace('&', '&', $url);
442 $template = CRM_Core_Smarty
::singleton();
443 $template->assign('redirectURL', $url);
444 $template->assign('title', $title);
445 $template->assign('message', $message);
447 $html = $template->fetch('CRM/common/redirectJS.tpl');
455 * Append an additional breadcrumb tag to the existing breadcrumbs.
457 * @param $breadCrumbs
462 static function appendBreadCrumb($breadCrumbs) {
463 $config = CRM_Core_Config
::singleton();
464 return $config->userSystem
->appendBreadCrumb($breadCrumbs);
468 * Reset an additional breadcrumb tag to the existing breadcrumb.
473 static function resetBreadCrumb() {
474 $config = CRM_Core_Config
::singleton();
475 return $config->userSystem
->resetBreadCrumb();
479 * Append a string to the head of the HTML file.
486 static function addHTMLHead($bc) {
487 $config = CRM_Core_Config
::singleton();
488 return $config->userSystem
->addHTMLHead($bc);
492 * Determine the post URL for a form
495 * The default action if one is pre-specified.
498 * The URL to post the form.
502 static function postURL($action) {
503 $config = CRM_Core_Config
::singleton();
504 return $config->userSystem
->postURL($action);
508 * Rewrite various system URLs to https.
513 static function mapConfigToSSL() {
514 $config = CRM_Core_Config
::singleton();
515 $config->userFrameworkResourceURL
= str_replace('http://', 'https://', $config->userFrameworkResourceURL
);
516 $config->resourceBase
= $config->userFrameworkResourceURL
;
518 if (! empty($config->extensionsURL
)) {
519 $config->extensionsURL
= str_replace('http://', 'https://', $config->extensionsURL
);
522 return $config->userSystem
->mapConfigToSSL();
526 * Get the base URL of the system.
532 static function baseURL() {
533 $config = CRM_Core_Config
::singleton();
534 return $config->userFrameworkBaseURL
;
540 static function authenticateAbort($message, $abort) {
552 * (optional) Whether to exit; defaults to true.
555 static function authenticateKey($abort = TRUE) {
556 // also make sure the key is sent and is valid
557 $key = trim(CRM_Utils_Array
::value('key', $_REQUEST));
559 $docAdd = "More info at:" . CRM_Utils_System
::docURL2("Managing Scheduled Jobs", TRUE, NULL, NULL, NULL, "wiki");
562 return self
::authenticateAbort(
563 "ERROR: You need to send a valid key to execute this file. " . $docAdd . "\n",
568 $siteKey = defined('CIVICRM_SITE_KEY') ? CIVICRM_SITE_KEY
: NULL;
570 if (!$siteKey ||
empty($siteKey)) {
571 return self
::authenticateAbort(
572 "ERROR: You need to set a valid site key in civicrm.settings.php. " . $docAdd . "\n",
577 if (strlen($siteKey) < 8) {
578 return self
::authenticateAbort(
579 "ERROR: Site key needs to be greater than 7 characters in civicrm.settings.php. " . $docAdd . "\n",
584 if ($key !== $siteKey) {
585 return self
::authenticateAbort(
586 "ERROR: Invalid key value sent. " . $docAdd . "\n",
598 static function authenticateScript($abort = TRUE, $name = NULL, $pass = NULL, $storeInSession = TRUE, $loadCMSBootstrap = TRUE, $requireKey = TRUE) {
599 // auth to make sure the user has a login/password to do a shell operation
600 // later on we'll link this to acl's
602 $name = trim(CRM_Utils_Array
::value('name', $_REQUEST));
603 $pass = trim(CRM_Utils_Array
::value('pass', $_REQUEST));
606 // its ok to have an empty password
608 return self
::authenticateAbort(
609 "ERROR: You need to send a valid user name and password to execute this file\n",
614 if ($requireKey && !self
::authenticateKey($abort)) {
618 $result = CRM_Utils_System
::authenticate($name, $pass, $loadCMSBootstrap);
620 return self
::authenticateAbort(
621 "ERROR: Invalid username and/or password\n",
625 elseif ($storeInSession) {
626 // lets store contact id and user id in session
627 list($userID, $ufID, $randomNumber) = $result;
628 if ($userID && $ufID) {
629 $config = CRM_Core_Config
::singleton();
630 $config->userSystem
->setUserSession( array($userID, $ufID) );
633 return self
::authenticateAbort(
634 "ERROR: Unexpected error, could not match userID and contactID",
644 * Authenticate the user against the uf db.
646 * In case of succesful authentication, returns an array consisting of
647 * (contactID, ufID, unique string). Returns FALSE if authentication is
650 * @param string $name
652 * @param string $password
654 * @param bool $loadCMSBootstrap
657 * @return false|array
661 static function authenticate($name, $password, $loadCMSBootstrap = FALSE, $realPath = NULL) {
662 $config = CRM_Core_Config
::singleton();
664 /* Before we do any loading, let's start the session and write to it.
665 * We typically call authenticate only when we need to bootstrap the CMS
666 * directly via Civi and hence bypass the normal CMS auth and bootstrap
667 * process typically done in CLI and cron scripts. See: CRM-12648
669 $session = CRM_Core_Session
::singleton();
670 $session->set( 'civicrmInitSession', TRUE );
672 $dbDrupal = DB
::connect($config->userFrameworkDSN
);
673 return $config->userSystem
->authenticate($name, $password, $loadCMSBootstrap, $realPath);
677 * Set a message in the UF to display to a user.
679 * @param string $message
680 * The message to set.
685 static function setUFMessage($message) {
686 $config = CRM_Core_Config
::singleton();
687 return $config->userSystem
->setMessage($message);
692 * Determine whether a value is null-ish.
695 * The value to check for null.
699 static function isNull($value) {
700 // FIXME: remove $value = 'null' string test when we upgrade our DAO code to handle passing null in a better way.
701 if (!isset($value) ||
$value === NULL ||
$value === '' ||
$value === 'null') {
704 if (is_array($value)) {
705 foreach ($value as $key => $value) {
706 if (!self
::isNull($value)) {
716 * Obscure all but the last few digits of a credit card number.
718 * @param string $number
719 * The credit card number to obscure.
721 * (optional) The number of digits to preserve unmodified.
723 * The obscured credit card number.
726 static function mungeCreditCard($number, $keep = 4) {
727 $number = trim($number);
728 if (empty($number)) {
731 $replace = str_repeat('*', strlen($number) - $keep);
732 return substr_replace($number, $replace, 0, -$keep);
736 * Determine which PHP modules are loaded.
741 public static function parsePHPModules() {
743 phpinfo(INFO_MODULES
);
744 $s = ob_get_contents();
747 $s = strip_tags($s, '<h2><th><td>');
748 $s = preg_replace('/<th[^>]*>([^<]+)<\/th>/', "<info>\\1</info>", $s);
749 $s = preg_replace('/<td[^>]*>([^<]+)<\/td>/', "<info>\\1</info>", $s);
750 $vTmp = preg_split('/(<h2>[^<]+<\/h2>)/', $s, -1, PREG_SPLIT_DELIM_CAPTURE
);
752 for ($i = 1; $i < count($vTmp); $i++
) {
753 if (preg_match('/<h2>([^<]+)<\/h2>/', $vTmp[$i], $vMat)) {
754 $vName = trim($vMat[1]);
755 $vTmp2 = explode("\n", $vTmp[$i +
1]);
756 foreach ($vTmp2 AS $vOne) {
757 $vPat = '<info>([^<]+)<\/info>';
758 $vPat3 = "/$vPat\s*$vPat\s*$vPat/";
759 $vPat2 = "/$vPat\s*$vPat/";
761 if (preg_match($vPat3, $vOne, $vMat)) {
762 $vModules[$vName][trim($vMat[1])] = array(trim($vMat[2]), trim($vMat[3]));
765 elseif (preg_match($vPat2, $vOne, $vMat)) {
766 $vModules[$vName][trim($vMat[1])] = trim($vMat[2]);
775 * Get a setting from a loaded PHP module.
779 public static function getModuleSetting($pModuleName, $pSetting) {
780 $vModules = self
::parsePHPModules();
781 return $vModules[$pModuleName][$pSetting];
789 static function memory($title = NULL) {
792 $pid = posix_getpid();
795 $memory = str_replace("\n", '', shell_exec("ps -p" . $pid . " -o rss="));
796 $memory .= ", " . time();
798 CRM_Core_Error
::debug_var($title, $memory);
804 * @param string $name
805 * @param string $mimeType
808 * @param bool $output
811 static function download($name, $mimeType, &$buffer,
815 $now = gmdate('D, d M Y H:i:s') . ' GMT';
817 header('Content-Type: ' . $mimeType);
818 header('Expires: ' . $now);
820 // lem9 & loic1: IE need specific headers
821 $isIE = strstr($_SERVER['HTTP_USER_AGENT'], 'MSIE');
823 $fileString = "filename=\"{$name}.{$ext}\"";
826 $fileString = "filename=\"{$name}\"";
829 header("Content-Disposition: inline; $fileString");
830 header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
831 header('Pragma: public');
834 header("Content-Disposition: attachment; $fileString");
835 header('Pragma: no-cache');
847 static function xMemory($title = NULL, $log = FALSE) {
848 $mem = (float ) xdebug_memory_usage() / (float )(1024);
849 $mem = number_format($mem, 5) . ", " . time();
851 echo "<p>$title: $mem<p>";
853 CRM_Core_Error
::debug_var($title, $mem);
856 echo "<p>$title: $mem<p>";
863 * The URL to operate on.
866 static function fixURL($url) {
867 $components = parse_url($url);
873 // at some point we'll add code here to make sure the url is not
874 // something that will mess up up, so we need to clean it up here
879 * Make sure a callback is valid in the current context.
881 * @param string $callback
882 * Name of the function to check.
887 static function validCallback($callback) {
888 if (self
::$_callbacks === NULL) {
889 self
::$_callbacks = array();
892 if (!array_key_exists($callback, self
::$_callbacks)) {
893 if (strpos($callback, '::') !== FALSE) {
894 list($className, $methodName) = explode('::', $callback);
895 $fileName = str_replace('_', DIRECTORY_SEPARATOR
, $className) . '.php';
896 // ignore errors if any
897 @include_once
($fileName);
898 if (!class_exists($className)) {
899 self
::$_callbacks[$callback] = FALSE;
902 // instantiate the class
903 $object = new $className();
904 if (!method_exists($object, $methodName)) {
905 self
::$_callbacks[$callback] = FALSE;
908 self
::$_callbacks[$callback] = TRUE;
913 self
::$_callbacks[$callback] = function_exists($callback);
916 return self
::$_callbacks[$callback];
920 * Like PHP's built-in explode(), but always return an array of $limit items.
922 * This serves as a wrapper to the PHP explode() function. In the event that
923 * PHP's explode() returns an array with fewer than $limit elements, pad
924 * the end of the array with NULLs.
926 * @param string $separator
927 * @param string $string
932 static function explode($separator, $string, $limit) {
933 $result = explode($separator, $string, $limit);
934 for ($i = count($result); $i < $limit; $i++
) {
943 * @param bool $addCookie
947 static function checkURL($url, $addCookie = FALSE) {
948 // make a GET request to $url
949 $ch = curl_init($url);
951 curl_setopt($ch, CURLOPT_COOKIE
, http_build_query($_COOKIE));
953 // it's quite alright to use a self-signed cert
954 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER
, 0);
956 // lets capture the return stuff rather than echo
957 curl_setopt($ch, CURLOPT_RETURNTRANSFER
, true );
959 return curl_exec($ch);
963 * Assert that we are running on a particular PHP version.
966 * The major version of PHP that is required.
968 * (optional) Whether to fatally abort if the version requirement is not
969 * met. Defaults to TRUE.
971 * Returns TRUE if the requirement is met, FALSE if the requirement is not
972 * met and we're not aborting due to the failed requirement.
975 static function checkPHPVersion($ver = 5, $abort = TRUE) {
976 $phpVersion = substr(PHP_VERSION
, 0, 1);
977 if ($phpVersion >= $ver) {
982 CRM_Core_Error
::fatal(ts('This feature requires PHP Version %1 or greater',
993 static function formatWikiURL($string, $encode = FALSE) {
994 $items = explode(' ', trim($string), 2);
995 if (count($items) == 2) {
1003 $url = $encode ? self
::urlEncode($items[0]) : $items[0];
1004 return "<a href=\"$url\">$title</a>";
1008 * @param string $url
1011 static function urlEncode($url) {
1012 $items = parse_url($url);
1013 if ($items === FALSE) {
1017 if (empty($items['query'])) {
1021 $items['query'] = urlencode($items['query']);
1023 $url = $items['scheme'] . '://';
1024 if (!empty($items['user'])) {
1025 $url .= "{$items['user']}:{$items['pass']}@";
1028 $url .= $items['host'];
1029 if (!empty($items['port'])) {
1030 $url .= ":{$items['port']}";
1033 $url .= "{$items['path']}?{$items['query']}";
1034 if (!empty($items['fragment'])) {
1035 $url .= "#{$items['fragment']}";
1042 * Return the running civicrm version.
1048 static function version() {
1052 $verFile = implode(DIRECTORY_SEPARATOR
,
1053 array(dirname(__FILE__
), '..', '..', 'civicrm-version.php')
1055 if (file_exists($verFile)) {
1056 require_once ($verFile);
1057 if (function_exists('civicrmVersion')) {
1058 $info = civicrmVersion();
1059 $version = $info['version'];
1063 // svn installs don't have version.txt by default. In that case version.xml should help -
1064 $verFile = implode(DIRECTORY_SEPARATOR
,
1065 array(dirname(__FILE__
), '..', '..', 'xml', 'version.xml')
1067 if (file_exists($verFile)) {
1068 $str = file_get_contents($verFile);
1069 $xmlObj = simplexml_load_string($str);
1070 $version = (string) $xmlObj->version_no
;
1075 if (!CRM_Utils_System
::isVersionFormatValid($version)) {
1076 CRM_Core_Error
::fatal('Unknown codebase version.');
1084 * Determines whether a string is a valid CiviCRM version string.
1086 * @param string $version
1087 * Version string to be checked.
1091 static function isVersionFormatValid($version) {
1092 return preg_match("/^(\d{1,2}\.){2,3}(\d{1,2}|(alpha|beta)\d{1,2})(\.upgrade)?$/", $version);
1096 * Wraps or emulates PHP's getallheaders() function.
1099 static function getAllHeaders() {
1100 if (function_exists('getallheaders')) {
1101 return getallheaders();
1104 // emulate get all headers
1105 // http://www.php.net/manual/en/function.getallheaders.php#66335
1107 foreach ($_SERVER as $name => $value) {
1108 if (substr($name, 0, 5) == 'HTTP_') {
1109 $headers[str_replace(' ',
1111 ucwords(strtolower(str_replace('_',
1125 static function getRequestHeaders() {
1126 if (function_exists('apache_request_headers')) {
1127 return apache_request_headers();
1135 * Determine whether this is an SSL request.
1137 * Note that we inline this function in install/civicrm.php, so if you change
1138 * this function, please go and change the code in the install script as well.
1142 static function isSSL( ) {
1144 (isset($_SERVER['HTTPS']) &&
1145 !empty($_SERVER['HTTPS']) &&
1146 strtolower($_SERVER['HTTPS']) != 'off') ?
true : false;
1152 static function redirectToSSL($abort = FALSE) {
1153 $config = CRM_Core_Config
::singleton();
1154 $req_headers = self
::getRequestHeaders();
1155 if (CRM_Core_BAO_Setting
::getItem(CRM_Core_BAO_Setting
::SYSTEM_PREFERENCES_NAME
, 'enableSSL') &&
1157 strtolower(CRM_Utils_Array
::value('X_FORWARDED_PROTO', $req_headers)) != 'https'
1159 // ensure that SSL is enabled on a civicrm url (for cookie reasons etc)
1160 $url = "https://{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}";
1161 if (!self
::checkURL($url, TRUE)) {
1163 CRM_Core_Error
::fatal('HTTPS is not set up on this machine');
1166 CRM_Core_Session
::setStatus(ts('HTTPS is not set up on this machine'), ts('Warning'), 'alert');
1167 // admin should be the only one following this
1168 // since we dont want the user stuck in a bad place
1172 CRM_Utils_System
::redirect($url);
1177 * Get logged in user's IP address.
1179 * Get IP address from HTTP REMOTE_ADDR header. If the CMS is Drupal then use
1180 * the Drupal function as this also handles reverse proxies (based on proper
1181 * configuration in settings.php)
1183 * @param bool $strictIPV4
1184 * (optional) Whether to return only IPv4 addresses.
1187 * IP address of logged in user.
1189 static function ipAddress($strictIPV4 = TRUE) {
1190 $address = CRM_Utils_Array
::value('REMOTE_ADDR', $_SERVER);
1192 $config = CRM_Core_Config
::singleton();
1193 if ($config->userSystem
->is_drupal
) {
1194 //drupal function handles the server being behind a proxy securely
1195 $address = ip_address();
1199 if ($address == '::1') {
1200 $address = '127.0.0.1';
1203 // when we need to have strictly IPV4 ip address
1204 // convert ipV6 to ipV4
1206 // this converts 'IPV4 mapped IPV6 address' to IPV4
1207 if (filter_var($address, FILTER_VALIDATE_IP
, FILTER_FLAG_IPV6
) && strstr($address, '::ffff:')) {
1208 $address = ltrim($address, '::ffff:');
1216 * Get the referring / previous page URL.
1219 * The previous page URL
1223 static function refererPath() {
1224 return CRM_Utils_Array
::value('HTTP_REFERER', $_SERVER);
1228 * Get the documentation base URL.
1231 * Base URL of the CRM documentation.
1235 static function getDocBaseURL() {
1236 // FIXME: move this to configuration at some stage
1237 return 'http://book.civicrm.org/';
1241 * Returns wiki (alternate) documentation URL base.
1243 * @return string documentation url
1247 static function getWikiBaseURL() {
1248 // FIXME: move this to configuration at some stage
1249 return 'http://wiki.civicrm.org/confluence/display/CRMDOC/';
1253 * Returns URL or link to documentation page, based on provided parameters.
1255 * For use in PHP code.
1256 * WARNING: Always returns URL, if ts function is not defined ($URLonly has
1259 * @param string $page
1260 * Title of documentation wiki page.
1261 * @param boolean $URLonly
1262 * (optional) Whether to return URL only or full HTML link (default).
1263 * @param string $text
1264 * (optional) Text of HTML link (no effect if $URLonly = false).
1265 * @param string $title
1266 * (optional) Tooltip text for HTML link (no effect if $URLonly = false)
1267 * @param string $style
1268 * (optional) Style attribute value for HTML link (no effect if $URLonly = false)
1271 * URL or link to documentation page, based on provided parameters.
1275 static function docURL2($page, $URLonly = FALSE, $text = NULL, $title = NULL, $style = NULL, $resource = NULL) {
1276 // if ts function doesn't exist, it means that CiviCRM hasn't been fully initialised yet -
1277 // return just the URL, no matter what other parameters are defined
1278 if (!function_exists('ts')) {
1279 if ($resource == 'wiki') {
1280 $docBaseURL = self
::getWikiBaseURL();
1282 $docBaseURL = self
::getDocBaseURL();
1284 return $docBaseURL . str_replace(' ', '+', $page);
1289 'URLonly' => $URLonly,
1293 'resource' => $resource,
1295 return self
::docURL($params);
1300 * Returns URL or link to documentation page, based on provided parameters.
1302 * For use in templates code.
1304 * @param array $params
1305 * An array of parameters (see CRM_Utils_System::docURL2 method for names)
1308 * URL or link to documentation page, based on provided parameters.
1312 static function docURL($params) {
1314 if (!isset($params['page'])) {
1318 if (CRM_Utils_Array
::value('resource', $params) == 'wiki') {
1319 $docBaseURL = self
::getWikiBaseURL();
1321 $docBaseURL = self
::getDocBaseURL();
1324 if (!isset($params['title']) or $params['title'] === NULL) {
1325 $params['title'] = ts('Opens documentation in a new window.');
1328 if (!isset($params['text']) or $params['text'] === NULL) {
1329 $params['text'] = ts('(learn more...)');
1332 if (!isset($params['style']) ||
$params['style'] === NULL) {
1336 $style = "style=\"{$params['style']}\"";
1339 $link = $docBaseURL . str_replace(' ', '+', $params['page']);
1341 if (isset($params['URLonly']) && $params['URLonly'] == TRUE) {
1345 return "<a href=\"{$link}\" $style target=\"_blank\" title=\"{$params['title']}\">{$params['text']}</a>";
1350 * Get the locale set in the hosting CMS
1353 * The used locale or null for none.
1356 static function getUFLocale() {
1357 $config = CRM_Core_Config
::singleton();
1358 return $config->userSystem
->getUFLocale();
1362 * Execute external or internal URLs and return server response.
1364 * @param string $url
1366 * @param bool $addCookie
1367 * Whether to provide a cookie. Should be true to access internal URLs.
1370 * Response from URL.
1373 static function getServerResponse($url, $addCookie = TRUE) {
1374 CRM_Core_Error
::ignoreException();
1375 require_once 'HTTP/Request.php';
1376 $request = new HTTP_Request($url);
1379 foreach ($_COOKIE as $name => $value) {
1380 $request->addCookie($name, $value);
1384 if (isset($_SERVER['AUTH_TYPE'])) {
1385 $request->setBasicAuth($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']);
1388 $config = CRM_Core_Config
::singleton();
1389 if ($config->userFramework
== 'WordPress') {
1390 session_write_close();
1393 $request->sendRequest();
1394 $response = $request->getResponseBody();
1396 CRM_Core_Error
::setCallback();
1403 static function isDBVersionValid(&$errorMessage) {
1404 $dbVersion = CRM_Core_BAO_Domain
::version();
1407 // if db.ver missing
1408 $errorMessage = ts('Version information found to be missing in database. You will need to determine the correct version corresponding to your current database state.');
1411 elseif (!CRM_Utils_System
::isVersionFormatValid($dbVersion)) {
1412 $errorMessage = ts('Database is marked with invalid version format. You may want to investigate this before you proceed further.');
1415 elseif (stripos($dbVersion, 'upgrade')) {
1416 // if db.ver indicates a partially upgraded db
1417 $upgradeUrl = CRM_Utils_System
::url("civicrm/upgrade", "reset=1");
1418 $errorMessage = ts('Database check failed - the database looks to have been partially upgraded. You may want to reload the database with the backup and try the <a href=\'%1\'>upgrade process</a> again.', array(1 => $upgradeUrl));
1422 $codeVersion = CRM_Utils_System
::version();
1424 // if db.ver < code.ver, time to upgrade
1425 if (version_compare($dbVersion, $codeVersion) < 0) {
1426 $upgradeUrl = CRM_Utils_System
::url("civicrm/upgrade", "reset=1");
1427 $errorMessage = ts('New codebase version detected. You might want to visit <a href=\'%1\'>upgrade screen</a> to upgrade the database.', array(1 => $upgradeUrl));
1431 // if db.ver > code.ver, sth really wrong
1432 if (version_compare($dbVersion, $codeVersion) > 0) {
1433 $errorMessage = '<p>' . 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.',
1434 array(1 => $dbVersion, 2 => $codeVersion)
1436 $errorMessage .= "<p>" . ts('OR if this is a manual install from git, you might want to fix civicrm-version.php file.') . "</p>";
1440 // FIXME: there should be another check to make sure version is in valid format - X.Y.alpha_num
1446 * Exit with provided exit code.
1448 * @param int $status
1449 * (optional) Code with which to exit.
1452 static function civiExit($status = 0) {
1453 // move things to CiviCRM cache as needed
1454 CRM_Core_Session
::storeSessionObjects();
1460 * Reset the various system caches and some important static variables.
1462 static function flushCache( ) {
1463 // flush out all cache entries so we can reload new data
1464 // a bit aggressive, but livable for now
1465 $cache = CRM_Utils_Cache
::singleton();
1468 // also reset the various static memory caches
1470 // reset the memory or array cache
1471 CRM_Core_BAO_Cache
::deleteGroup('contact fields', NULL, FALSE);
1474 CRM_ACL_BAO_Cache
::resetCache();
1476 // reset various static arrays used here
1477 CRM_Contact_BAO_Contact
::$_importableFields =
1478 CRM_Contact_BAO_Contact
::$_exportableFields =
1479 CRM_Contribute_BAO_Contribution
::$_importableFields =
1480 CRM_Contribute_BAO_Contribution
::$_exportableFields =
1481 CRM_Pledge_BAO_Pledge
::$_exportableFields =
1482 CRM_Contribute_BAO_Query
::$_contributionFields =
1483 CRM_Core_BAO_CustomField
::$_importFields =
1484 CRM_Core_BAO_Cache
::$_cache =
1485 CRM_Core_DAO
::$_dbColumnValueCache = NULL;
1487 CRM_Core_OptionGroup
::flushAll();
1488 CRM_Utils_PseudoConstant
::flushAll();
1492 * Load CMS bootstrap.
1494 * @param array $params
1495 * Array with uid name and pass
1496 * @param bool $loadUser
1497 * Boolean load user or not.
1498 * @param bool $throwError
1502 static function loadBootStrap($params = array(
1503 ), $loadUser = TRUE, $throwError = TRUE, $realPath = NULL) {
1504 if (!is_array($params)) {
1507 $config = CRM_Core_Config
::singleton();
1508 return $config->userSystem
->loadBootStrap($params, $loadUser, $throwError, $realPath);
1512 * Check if user is logged in.
1517 public static function isUserLoggedIn() {
1518 $config = CRM_Core_Config
::singleton();
1519 return $config->userSystem
->isUserLoggedIn();
1523 * Get current logged in user id.
1526 * ufId, currently logged in user uf id.
1529 public static function getLoggedInUfID() {
1530 $config = CRM_Core_Config
::singleton();
1531 return $config->userSystem
->getLoggedInUfID();
1537 static function baseCMSURL() {
1538 static $_baseURL = NULL;
1540 $config = CRM_Core_Config
::singleton();
1541 $_baseURL = $userFrameworkBaseURL = $config->userFrameworkBaseURL
;
1543 if ($config->userFramework
== 'Joomla') {
1545 // we need to remove the administrator/ from the end
1546 $_baseURL = str_replace("/administrator/", "/", $userFrameworkBaseURL);
1550 global $civicrm_root;
1551 if (strpos($civicrm_root,
1552 DIRECTORY_SEPARATOR
. 'sites' .
1553 DIRECTORY_SEPARATOR
. 'all' .
1554 DIRECTORY_SEPARATOR
. 'modules'
1556 $startPos = strpos($civicrm_root,
1557 DIRECTORY_SEPARATOR
. 'sites' . DIRECTORY_SEPARATOR
1559 $endPos = strpos($civicrm_root,
1560 DIRECTORY_SEPARATOR
. 'modules' . DIRECTORY_SEPARATOR
1562 if ($startPos && $endPos) {
1563 // if component is in sites/SITENAME/modules
1564 $siteName = substr($civicrm_root,
1566 $endPos - $startPos - 7
1569 $_baseURL = $userFrameworkBaseURL . "sites/$siteName/";
1578 * Given a URL, return a relative URL if possible.
1580 * @param string $url
1584 static function relativeURL($url) {
1585 // check if url is relative, if so return immediately
1586 if (substr($url, 0, 4) != 'http') {
1590 // make everything relative from the baseFilePath
1591 $baseURL = self
::baseCMSURL();
1593 // check if baseURL is a substr of $url, if so
1594 // return rest of string
1595 if (substr($url, 0, strlen($baseURL)) == $baseURL) {
1596 return substr($url, strlen($baseURL));
1599 // return the original value
1604 * Produce an absolute URL from a possibly-relative URL.
1606 * @param string $url
1607 * @param bool $remoteLanguagePart
1611 static function absoluteURL($url, $removeLanguagePart = FALSE) {
1612 // check if url is already absolute, if so return immediately
1613 if (substr($url, 0, 4) == 'http') {
1617 // make everything absolute from the baseFileURL
1618 $baseURL = self
::baseCMSURL();
1620 //CRM-7622: drop the language from the URL if requested (and it’s there)
1621 $config = CRM_Core_Config
::singleton();
1622 if ($removeLanguagePart) {
1623 $baseURL = self
::languageNegotiationURL($baseURL, FALSE, TRUE);
1626 return $baseURL . $url;
1630 * Function to clean url, replaces first '&' with '?'
1632 * @param string $url
1634 * @return string $url, clean url
1637 static function cleanUrl($url) {
1642 if ($pos = strpos($url, '&')) {
1643 $url = substr_replace($url, '?', $pos, 1);
1650 * Format the url as per language Negotiation.
1652 * @param string $url
1654 * @return string $url, formatted url.
1657 static function languageNegotiationURL($url,
1658 $addLanguagePart = TRUE,
1659 $removeLanguagePart = FALSE
1661 $config = &CRM_Core_Config
::singleton();
1662 return $config->userSystem
->languageNegotiationURL($url, $addLanguagePart, $removeLanguagePart);
1666 * Append the contents of an 'extra' smarty template file if it is present in
1667 * the custom template directory. This does not work if there are
1668 * multiple custom template directories
1670 * @param string $fileName - the name of the tpl file that we are processing
1671 * @param string $content (by reference) - the current content string
1672 * @param string $overideFileName - an optional parameter which is sent by contribution/event reg/profile pages
1673 * which uses a id specific extra file name if present
1675 * @return void - the content string is modified if needed
1678 static function appendTPLFile($fileName,
1680 $overideFileName = NULL
1682 $template = CRM_Core_Smarty
::singleton();
1683 if ($overideFileName) {
1684 $additionalTPLFile = $overideFileName;
1687 $additionalTPLFile = str_replace('.tpl', '.extra.tpl', $fileName);
1690 if ($template->template_exists($additionalTPLFile)) {
1691 $content .= $template->fetch($additionalTPLFile);
1696 * Get a list of all files that are found within the directories
1697 * that are the result of appending the provided relative path to
1698 * each component of the PHP include path.
1700 * @author Ken Zalewski
1702 * @param string $relpath a relative path, typically pointing to
1703 * a directory with multiple class files
1705 * @return array An array of files that exist in one or more of the
1706 * directories that are referenced by the relative path
1707 * when appended to each element of the PHP include path
1710 static function listIncludeFiles($relpath) {
1711 $file_list = array();
1712 $inc_dirs = explode(PATH_SEPARATOR
, get_include_path());
1713 foreach ($inc_dirs as $inc_dir) {
1714 $target_dir = $inc_dir . DIRECTORY_SEPARATOR
. $relpath;
1715 if (is_dir($target_dir)) {
1716 $cur_list = scandir($target_dir);
1717 foreach ($cur_list as $fname) {
1718 if ($fname != '.' && $fname != '..') {
1719 $file_list[$fname] = $fname;
1726 // listIncludeFiles()
1729 * Get a list of all "plugins" (PHP classes that implement a piece of
1730 * functionality using a well-defined interface) that are found in a
1731 * particular CiviCRM directory (both custom and core are searched).
1733 * @author Ken Zalewski
1735 * @param string $relpath a relative path referencing a directory that
1736 * contains one or more plugins
1737 * @param string $fext only files with this extension will be considered
1739 * @param array $skipList list of files to skip
1741 * @return array List of plugins, where the plugin name is both the
1742 * key and the value of each element.
1745 static function getPluginList($relpath, $fext = '.php', $skipList = array(
1747 $fext_len = strlen($fext);
1749 $inc_files = CRM_Utils_System
::listIncludeFiles($relpath);
1750 foreach ($inc_files as $inc_file) {
1751 if (substr($inc_file, 0 - $fext_len) == $fext) {
1752 $plugin_name = substr($inc_file, 0, 0 - $fext_len);
1753 if (!in_array($plugin_name, $skipList)) {
1754 $plugins[$plugin_name] = $plugin_name;
1764 * @param string $fileName - the name of the tpl file that we are processing
1765 * @param string $content (by reference) - the current content string
1767 * @return void - the content string is modified if needed
1770 static function executeScheduledJobs() {
1771 $facility = new CRM_Core_JobManager();
1772 $facility->execute(FALSE);
1774 $redirectUrl = self
::url('civicrm/admin/job', 'reset=1');
1776 CRM_Core_Session
::setStatus(
1777 ts('Scheduled jobs have been executed according to individual timing settings. Please check log for messages.'),
1778 ts('Complete'), 'success');
1780 CRM_Utils_System
::redirect($redirectUrl);
1784 * Evaluate any tokens in a URL
1786 * @param string|FALSE $url
1787 * @return string|FALSE
1789 public static function evalUrl($url) {
1790 if ($url === FALSE) {
1794 $config = CRM_Core_Config
::singleton();
1796 '{ver}' => CRM_Utils_System
::version(),
1797 '{uf}' => $config->userFramework
,
1798 '{php}' => phpversion(),
1799 '{sid}' => md5('sid_' . (defined('CIVICRM_SITE_KEY') ? CIVICRM_SITE_KEY
: '') . '_' . $config->userFrameworkBaseURL
),
1800 '{baseUrl}' => $config->userFrameworkBaseURL
,
1801 '{lang}' => $config->lcMessages
,
1802 '{co}' => $config->defaultContactCountry
,
1804 foreach (array_keys($vars) as $k) {
1805 $vars[$k] = urlencode($vars[$k]);
1807 return strtr($url, $vars);
1813 * Determine whether this is a developmental system.
1817 static function isDevelopment() {
1818 static $cache = NULL;
1819 if ($cache === NULL) {
1820 global $civicrm_root;
1821 $cache = file_exists("{$civicrm_root}/.svn") ||
file_exists("{$civicrm_root}/.git");