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
51 * Used by all the framework components, specifically,
54 * @param string $urlVar the url variable being considered (i.e. crmPageID, crmSortID etc)
55 * @param boolean $includeReset - should we include or ignore the reset GET string (if present)
56 * @param boolean $includeForce - should we include or ignore the force GET string (if present)
57 * @param string $path - the path to use for the new url
58 * @param string $absolute - do we need a absolute or relative URL?
60 * @return string the url fragment
63 static function makeURL($urlVar, $includeReset = FALSE, $includeForce = TRUE, $path = NULL, $absolute = FALSE) {
65 $config = CRM_Core_Config
::singleton();
66 $path = CRM_Utils_Array
::value($config->userFrameworkURLVar
, $_GET);
75 CRM_Utils_System
::getLinksUrl($urlVar, $includeReset, $includeForce),
81 * get the query string and clean it up. Strip some variables that should not
82 * be propagated, specically variable like 'reset'. Also strip any side-affect
83 * actions (i.e. export)
85 * This function is copied mostly verbatim from Pager.php (_getLinksUrl)
87 * @param string $urlVar the url variable being considered (i.e. crmPageID, crmSortID etc)
88 * @param boolean $includeReset should we include the reset var (generally this variable should be skipped)
93 static function getLinksUrl($urlVar, $includeReset = FALSE, $includeForce = TRUE, $skipUFVar = TRUE) {
94 // Sort out query string to prevent messy urls
95 $querystring = array();
99 if (!empty($_SERVER['QUERY_STRING'])) {
100 $qs = explode('&', str_replace('&', '&', $_SERVER['QUERY_STRING']));
101 for ($i = 0, $cnt = count($qs); $i < $cnt; $i++
) {
102 // check first if exist a pair
103 if (strstr($qs[$i], '=') !== FALSE) {
104 list($name, $value) = explode('=', $qs[$i]);
105 if ($name != $urlVar) {
106 $name = rawurldecode($name);
107 //check for arrays in parameters: site.php?foo[]=1&foo[]=2&foo[]=3
108 if ((strpos($name, '[') !== FALSE) &&
109 (strpos($name, ']') !== FALSE)
129 unset($qs['snippet']);
130 unset($qs['section']);
133 $config = CRM_Core_Config
::singleton();
134 unset($qs[$config->userFrameworkURLVar
]);
137 foreach ($qs as $name => $value) {
138 if ($name != 'reset' ||
$includeReset) {
139 $querystring[] = $name . '=' . $value;
143 $querystring = array_merge($querystring, array_unique($arrays));
144 $querystring = array_map('htmlentities', $querystring);
146 $url = implode('&', $querystring);
148 $url .= (!empty($querystring) ?
'&' : '') . $urlVar . '=';
155 * if we are using a theming system, invoke theme, else just print the
158 * @param string $content the content that will be themed
159 * @param boolean $print are we displaying to the screen or bypassing theming?
160 * @param boolean $maintenance for maintenance mode
162 * @return void prints content on stdout
166 static function theme(
171 $config = &CRM_Core_Config
::singleton();
172 return $config->userSystem
->theme($content, $print, $maintenance);
176 * Generate a query string if input is an array
178 * @param mixed $query: array or string
183 static function makeQueryString($query) {
184 if (is_array($query)) {
186 foreach ($query as $key => $value) {
187 $buf .= ($buf ?
'&' : '') . urlencode($key) . '=' . urlencode($value);
195 * Generate an internal CiviCRM URL
197 * @param $path string The path being linked to, such as "civicrm/add"
198 * @param $query mixed A query string to append to the link, or an array of key-value pairs
199 * @param $absolute boolean Whether to force the output to be an absolute link (beginning with http:).
200 * Useful for links that will be displayed outside the site, such as in an
202 * @param $fragment string A fragment identifier (named anchor) to append to the link.
204 * @return string an HTML string containing a link to the given path.
215 $forceBackend = FALSE
217 $query = self
::makeQueryString($query);
219 // we have a valid query and it has not yet been transformed
220 if ($htmlize && !empty($query) && strpos($query, '&') === FALSE) {
221 $query = htmlentities($query);
224 $config = CRM_Core_Config
::singleton();
225 return $config->userSystem
->url($path, $query, $absolute, $fragment, $htmlize, $frontend, $forceBackend);
228 static function href($text, $path = NULL, $query = NULL, $absolute = TRUE,
229 $fragment = NULL, $htmlize = TRUE, $frontend = FALSE, $forceBackend = FALSE
231 $url = self
::url($path, $query, $absolute, $fragment, $htmlize, $frontend, $forceBackend);
232 return "<a href=\"$url\">$text</a>";
235 static function permissionDenied() {
236 $config = CRM_Core_Config
::singleton();
237 return $config->userSystem
->permissionDenied();
240 static function logout() {
241 $config = CRM_Core_Config
::singleton();
242 return $config->userSystem
->logout();
245 // this is a very drupal specific function for now
246 static function updateCategories() {
247 $config = CRM_Core_Config
::singleton();
248 if ($config->userSystem
->is_drupal
) {
249 $config->userSystem
->updateCategories();
254 * What menu path are we currently on. Called for the primary tpl
256 * @return string the current menu path
259 static function currentPath() {
260 $config = CRM_Core_Config
::singleton();
261 return trim(CRM_Utils_Array
::value($config->userFrameworkURLVar
, $_GET), '/');
265 * this function is called from a template to compose a url
267 * @param array $params list of parameters
273 static function crmURL($params) {
274 $p = CRM_Utils_Array
::value('p', $params);
276 $p = self
::currentPath();
281 CRM_Utils_Array
::value('q', $params),
282 CRM_Utils_Array
::value('a', $params, FALSE),
283 CRM_Utils_Array
::value('f', $params),
284 CRM_Utils_Array
::value('h', $params, TRUE),
285 CRM_Utils_Array
::value('fe', $params, FALSE),
286 CRM_Utils_Array
::value('fb', $params, FALSE)
291 * sets the title of the page
293 * @param string $title
294 * @param string $pageTitle
300 static function setTitle($title, $pageTitle = NULL) {
301 self
::$title = $title;
302 $config = CRM_Core_Config
::singleton();
303 return $config->userSystem
->setTitle($title, $pageTitle);
307 * figures and sets the userContext. Uses the referer if valid
308 * else uses the default
310 * @param array $names refererer should match any str in this array
311 * @param string $default the default userContext if no match found
316 static function setUserContext($names, $default = NULL) {
319 $session = CRM_Core_Session
::singleton();
320 $referer = CRM_Utils_Array
::value('HTTP_REFERER', $_SERVER);
322 if ($referer && !empty($names)) {
323 foreach ($names as $name) {
324 if (strstr($referer, $name)) {
332 $session->pushUserContext($url);
337 * gets a class name for an object
339 * @param object $object - object whose class name is needed
341 * @return string $className - class name
346 static function getClassName($object) {
347 return get_class($object);
351 * redirect to another url
353 * @param string $url the url to goto
359 static function redirect($url = NULL) {
361 $url = self
::url('civicrm/dashboard', 'reset=1');
364 // replace the & characters with &
365 // this is kinda hackish but not sure how to do it right
366 $url = str_replace('&', '&', $url);
367 header('Location: ' . $url);
372 * use a html based file with javascript embedded to redirect to another url
373 * This prevent the too many redirect errors emitted by various browsers
375 * @param string $url the url to goto
381 static function jsRedirect(
387 $url = self
::url('civicrm/dashboard', 'reset=1');
391 $title = ts('CiviCRM task in progress');
395 $message = ts('A long running CiviCRM task is currently in progress. This message will be refreshed till the task is completed');
398 // replace the & characters with &
399 // this is kinda hackish but not sure how to do it right
400 $url = str_replace('&', '&', $url);
402 $template = CRM_Core_Smarty
::singleton();
403 $template->assign('redirectURL', $url);
404 $template->assign('title', $title);
405 $template->assign('message', $message);
407 $html = $template->fetch('CRM/common/redirectJS.tpl');
415 * Append an additional breadcrumb tag to the existing breadcrumb
417 * @param string $title
424 static function appendBreadCrumb($breadCrumbs) {
425 $config = CRM_Core_Config
::singleton();
426 return $config->userSystem
->appendBreadCrumb($breadCrumbs);
430 * Reset an additional breadcrumb tag to the existing breadcrumb
436 static function resetBreadCrumb() {
437 $config = CRM_Core_Config
::singleton();
438 return $config->userSystem
->resetBreadCrumb();
442 * Append a string to the head of the html file
444 * @param string $head the new string to be appended
450 static function addHTMLHead($bc) {
451 $config = CRM_Core_Config
::singleton();
452 return $config->userSystem
->addHTMLHead($bc);
456 * figure out the post url for the form
458 * @param the default action if one is pre-specified
460 * @return string the url to post the form
464 static function postURL($action) {
465 $config = CRM_Core_Config
::singleton();
466 return $config->userSystem
->postURL($action);
470 * rewrite various system urls to https
476 static function mapConfigToSSL() {
477 $config = CRM_Core_Config
::singleton();
478 $config->userFrameworkResourceURL
= str_replace('http://', 'https://', $config->userFrameworkResourceURL
);
479 $config->resourceBase
= $config->userFrameworkResourceURL
;
481 if (! empty($config->extensionsURL
)) {
482 $config->extensionsURL
= str_replace('http://', 'https://', $config->extensionsURL
);
485 return $config->userSystem
->mapConfigToSSL();
489 * Get the base URL from the system
497 static function baseURL() {
498 $config = CRM_Core_Config
::singleton();
499 return $config->userFrameworkBaseURL
;
502 static function authenticateAbort($message, $abort) {
512 static function authenticateKey($abort = TRUE) {
513 // also make sure the key is sent and is valid
514 $key = trim(CRM_Utils_Array
::value('key', $_REQUEST));
516 $docAdd = "More info at:" . CRM_Utils_System
::docURL2("Managing Scheduled Jobs", TRUE, NULL, NULL, NULL, "wiki");
519 return self
::authenticateAbort(
520 "ERROR: You need to send a valid key to execute this file. " . $docAdd . "\n",
525 $siteKey = defined('CIVICRM_SITE_KEY') ? CIVICRM_SITE_KEY
: NULL;
527 if (!$siteKey ||
empty($siteKey)) {
528 return self
::authenticateAbort(
529 "ERROR: You need to set a valid site key in civicrm.settings.php. " . $docAdd . "\n",
534 if (strlen($siteKey) < 8) {
535 return self
::authenticateAbort(
536 "ERROR: Site key needs to be greater than 7 characters in civicrm.settings.php. " . $docAdd . "\n",
541 if ($key !== $siteKey) {
542 return self
::authenticateAbort(
543 "ERROR: Invalid key value sent. " . $docAdd . "\n",
551 static function authenticateScript($abort = TRUE, $name = NULL, $pass = NULL, $storeInSession = TRUE, $loadCMSBootstrap = TRUE, $requireKey = TRUE) {
552 // auth to make sure the user has a login/password to do a shell
554 // later on we'll link this to acl's
556 $name = trim(CRM_Utils_Array
::value('name', $_REQUEST));
557 $pass = trim(CRM_Utils_Array
::value('pass', $_REQUEST));
560 // its ok to have an empty password
562 return self
::authenticateAbort(
563 "ERROR: You need to send a valid user name and password to execute this file\n",
568 if ($requireKey && !self
::authenticateKey($abort)) {
572 $result = CRM_Utils_System
::authenticate($name, $pass, $loadCMSBootstrap);
574 return self
::authenticateAbort(
575 "ERROR: Invalid username and/or password\n",
579 elseif ($storeInSession) {
580 // lets store contact id and user id in session
581 list($userID, $ufID, $randomNumber) = $result;
582 if ($userID && $ufID) {
583 $config = CRM_Core_Config
::singleton();
584 $config->userSystem
->setUserSession( array($userID, $ufID) );
587 return self
::authenticateAbort(
588 "ERROR: Unexpected error, could not match userID and contactID",
598 * Authenticate the user against the uf db
600 * @param string $name the user name
601 * @param string $password the password for the above user name
603 * @return mixed false if no auth
605 contactID, ufID, unique string ) if success
609 static function authenticate($name, $password, $loadCMSBootstrap = FALSE, $realPath = NULL) {
610 $config = CRM_Core_Config
::singleton();
612 // before we do any loading, lets start the session and write to it
613 // we typically call authenticate only when we need to bootstrap the CMS directly via Civi
614 // and hence bypass the normal CMS auth and bootstrap process
615 // typically done in cli and cron scripts
617 $session = CRM_Core_Session
::singleton();
618 $session->set( 'civicrmInitSession', TRUE );
620 $dbDrupal = DB
::connect($config->userFrameworkDSN
);
621 return $config->userSystem
->authenticate($name, $password, $loadCMSBootstrap, $realPath);
625 * Set a message in the UF to display to a user
627 * @param string $name the message to set
632 static function setUFMessage($message) {
633 $config = CRM_Core_Config
::singleton();
634 return $config->userSystem
->setMessage($message);
639 static function isNull($value) {
640 // FIXME: remove $value = 'null' string test when we upgrade our DAO code to handle passing null in a better way.
641 if (!isset($value) ||
$value === NULL ||
$value === '' ||
$value === 'null') {
644 if (is_array($value)) {
645 foreach ($value as $key => $value) {
646 if (!self
::isNull($value)) {
655 static function mungeCreditCard($number, $keep = 4) {
656 $number = trim($number);
657 if (empty($number)) {
660 $replace = str_repeat('*', strlen($number) - $keep);
661 return substr_replace($number, $replace, 0, -$keep);
664 /** parse php modules from phpinfo */
665 public static function parsePHPModules() {
667 phpinfo(INFO_MODULES
);
668 $s = ob_get_contents();
671 $s = strip_tags($s, '<h2><th><td>');
672 $s = preg_replace('/<th[^>]*>([^<]+)<\/th>/', "<info>\\1</info>", $s);
673 $s = preg_replace('/<td[^>]*>([^<]+)<\/td>/', "<info>\\1</info>", $s);
674 $vTmp = preg_split('/(<h2>[^<]+<\/h2>)/', $s, -1, PREG_SPLIT_DELIM_CAPTURE
);
676 for ($i = 1; $i < count($vTmp); $i++
) {
677 if (preg_match('/<h2>([^<]+)<\/h2>/', $vTmp[$i], $vMat)) {
678 $vName = trim($vMat[1]);
679 $vTmp2 = explode("\n", $vTmp[$i +
1]);
680 foreach ($vTmp2 AS $vOne) {
681 $vPat = '<info>([^<]+)<\/info>';
682 $vPat3 = "/$vPat\s*$vPat\s*$vPat/";
683 $vPat2 = "/$vPat\s*$vPat/";
685 if (preg_match($vPat3, $vOne, $vMat)) {
686 $vModules[$vName][trim($vMat[1])] = array(trim($vMat[2]), trim($vMat[3]));
689 elseif (preg_match($vPat2, $vOne, $vMat)) {
690 $vModules[$vName][trim($vMat[1])] = trim($vMat[2]);
698 /** get a module setting */
699 public static function getModuleSetting($pModuleName, $pSetting) {
700 $vModules = self
::parsePHPModules();
701 return $vModules[$pModuleName][$pSetting];
704 static function memory($title = NULL) {
707 $pid = posix_getpid();
710 $memory = str_replace("\n", '', shell_exec("ps -p" . $pid . " -o rss="));
711 $memory .= ", " . time();
713 CRM_Core_Error
::debug_var($title, $memory);
718 static function download($name, $mimeType, &$buffer,
722 $now = gmdate('D, d M Y H:i:s') . ' GMT';
724 header('Content-Type: ' . $mimeType);
725 header('Expires: ' . $now);
727 // lem9 & loic1: IE need specific headers
728 $isIE = strstr($_SERVER['HTTP_USER_AGENT'], 'MSIE');
730 $fileString = "filename=\"{$name}.{$ext}\"";
733 $fileString = "filename=\"{$name}\"";
736 header("Content-Disposition: inline; $fileString");
737 header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
738 header('Pragma: public');
741 header("Content-Disposition: attachment; $fileString");
742 header('Pragma: no-cache');
751 static function xMemory($title = NULL, $log = FALSE) {
752 $mem = (float ) xdebug_memory_usage() / (float )(1024);
753 $mem = number_format($mem, 5) . ", " . time();
755 echo "<p>$title: $mem<p>";
757 CRM_Core_Error
::debug_var($title, $mem);
760 echo "<p>$title: $mem<p>";
765 static function fixURL($url) {
766 $components = parse_url($url);
772 // at some point we'll add code here to make sure the url is not
773 // something that will mess up up, so we need to clean it up here
778 * make sure the callback is valid in the current context
780 * @param string $callback the name of the function
785 static function validCallback($callback) {
786 if (self
::$_callbacks === NULL) {
787 self
::$_callbacks = array();
790 if (!array_key_exists($callback, self
::$_callbacks)) {
791 if (strpos($callback, '::') !== FALSE) {
792 list($className, $methodName) = explode('::', $callback);
793 $fileName = str_replace('_', DIRECTORY_SEPARATOR
, $className) . '.php';
794 // ignore errors if any
795 @include_once
($fileName);
796 if (!class_exists($className)) {
797 self
::$_callbacks[$callback] = FALSE;
800 // instantiate the class
801 $object = new $className();
802 if (!method_exists($object, $methodName)) {
803 self
::$_callbacks[$callback] = FALSE;
806 self
::$_callbacks[$callback] = TRUE;
811 self
::$_callbacks[$callback] = function_exists($callback);
814 return self
::$_callbacks[$callback];
818 * This serves as a wrapper to the php explode function
819 * we expect exactly $limit arguments in return, and if we dont
820 * get them, we pad it with null
822 static function explode($separator, $string, $limit) {
823 $result = explode($separator, $string, $limit);
824 for ($i = count($result); $i < $limit; $i++
) {
830 static function checkURL($url, $addCookie = FALSE) {
831 // make a GET request to $url
832 $ch = curl_init($url);
834 curl_setopt($ch, CURLOPT_COOKIE
, http_build_query($_COOKIE));
836 // it's quite alright to use a self-signed cert
837 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER
, 0);
839 // lets capture the return stuff rather than echo
840 curl_setopt($ch, CURLOPT_RETURNTRANSFER
, true );
842 return curl_exec($ch);
845 static function checkPHPVersion($ver = 5, $abort = TRUE) {
846 $phpVersion = substr(PHP_VERSION
, 0, 1);
847 if ($phpVersion >= $ver) {
852 CRM_Core_Error
::fatal(ts('This feature requires PHP Version %1 or greater',
859 static function formatWikiURL($string, $encode = FALSE) {
860 $items = explode(' ', trim($string), 2);
861 if (count($items) == 2) {
869 $url = $encode ? self
::urlEncode($items[0]) : $items[0];
870 return "<a href=\"$url\">$title</a>";
873 static function urlEncode($url) {
874 $items = parse_url($url);
875 if ($items === FALSE) {
879 if (!CRM_Utils_Array
::value('query', $items)) {
883 $items['query'] = urlencode($items['query']);
885 $url = $items['scheme'] . '://';
886 if (CRM_Utils_Array
::value('user', $items)) {
887 $url .= "{$items['user']}:{$items['pass']}@";
890 $url .= $items['host'];
891 if (CRM_Utils_Array
::value('port', $items)) {
892 $url .= ":{$items['port']}";
895 $url .= "{$items['path']}?{$items['query']}";
896 if (CRM_Utils_Array
::value('fragment', $items)) {
897 $url .= "#{$items['fragment']}";
904 * Function to return the latest civicrm version.
906 * @return string civicrm version
909 static function version() {
913 $verFile = implode(DIRECTORY_SEPARATOR
,
914 array(dirname(__FILE__
), '..', '..', 'civicrm-version.php')
916 if (file_exists($verFile)) {
917 require_once ($verFile);
918 if (function_exists('civicrmVersion')) {
919 $info = civicrmVersion();
920 $version = $info['version'];
924 // svn installs don't have version.txt by default. In that case version.xml should help -
925 $verFile = implode(DIRECTORY_SEPARATOR
,
926 array(dirname(__FILE__
), '..', '..', 'xml', 'version.xml')
928 if (file_exists($verFile)) {
929 $str = file_get_contents($verFile);
930 $xmlObj = simplexml_load_string($str);
931 $version = (string) $xmlObj->version_no
;
936 if (!CRM_Utils_System
::isVersionFormatValid($version)) {
937 CRM_Core_Error
::fatal('Unknown codebase version.');
944 static function isVersionFormatValid($version) {
945 return preg_match("/^(\d{1,2}\.){2,3}(\d{1,2}|(alpha|beta)\d{1,2})(\.upgrade)?$/", $version);
948 static function getAllHeaders() {
949 if (function_exists('getallheaders')) {
950 return getallheaders();
953 // emulate get all headers
954 // http://www.php.net/manual/en/function.getallheaders.php#66335
956 foreach ($_SERVER as $name => $value) {
957 if (substr($name, 0, 5) == 'HTTP_') {
958 $headers[str_replace(' ',
960 ucwords(strtolower(str_replace('_',
971 static function getRequestHeaders() {
972 if (function_exists('apache_request_headers')) {
973 return apache_request_headers();
981 * Check and determine is this is an SSL request
982 * Note that we inline this function in install/civicrm.php, so if
983 * you change this function, please go and change the code in the install script
985 static function isSSL( ) {
987 (isset($_SERVER['HTTPS']) &&
988 !empty($_SERVER['HTTPS']) &&
989 strtolower($_SERVER['HTTPS']) != 'off') ?
true : false;
992 static function redirectToSSL($abort = FALSE) {
993 $config = CRM_Core_Config
::singleton();
994 $req_headers = self
::getRequestHeaders();
995 if (CRM_Core_BAO_Setting
::getItem(CRM_Core_BAO_Setting
::SYSTEM_PREFERENCES_NAME
, 'enableSSL') &&
997 strtolower(CRM_Utils_Array
::value('X_FORWARDED_PROTO', $req_headers)) != 'https'
999 // ensure that SSL is enabled on a civicrm url (for cookie reasons etc)
1000 $url = "https://{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}";
1001 if (!self
::checkURL($url, TRUE)) {
1003 CRM_Core_Error
::fatal('HTTPS is not set up on this machine');
1006 CRM_Core_Session
::setStatus(ts('HTTPS is not set up on this machine'), ts('Warning'), 'alert');
1007 // admin should be the only one following this
1008 // since we dont want the user stuck in a bad place
1012 CRM_Utils_System
::redirect($url);
1017 * Get logged in user's IP address.
1019 * Get IP address from HTTP Header. If the CMS is Drupal then use the Drupal function
1020 * as this also handles reverse proxies (based on proper configuration in settings.php)
1022 * @return string ip address of logged in user
1024 static function ipAddress($strictIPV4 = TRUE) {
1025 $address = CRM_Utils_Array
::value('REMOTE_ADDR', $_SERVER);
1027 $config = CRM_Core_Config
::singleton();
1028 if ($config->userSystem
->is_drupal
) {
1029 //drupal function handles the server being behind a proxy securely
1030 $address = ip_address();
1034 if ($address == '::1') {
1035 $address = '127.0.0.1';
1038 // when we need to have strictly IPV4 ip address
1039 // convert ipV6 to ipV4
1041 // this converts 'IPV4 mapped IPV6 address' to IPV4
1042 if (filter_var($address, FILTER_VALIDATE_IP
, FILTER_FLAG_IPV6
) && strstr($address, '::ffff:')) {
1043 $address = ltrim($address, '::ffff:');
1051 * Returns you the referring / previous page url
1053 * @return string the previous page url
1056 static function refererPath() {
1057 return CRM_Utils_Array
::value('HTTP_REFERER', $_SERVER);
1061 * Returns default documentation URL base
1063 * @return string documentation url
1066 static function getDocBaseURL() {
1067 // FIXME: move this to configuration at some stage
1068 return 'http://book.civicrm.org/';
1072 * Returns wiki (alternate) documentation URL base
1074 * @return string documentation url
1077 static function getWikiBaseURL() {
1078 // FIXME: move this to configuration at some stage
1079 return 'http://wiki.civicrm.org/confluence/display/CRMDOC/';
1083 * Returns URL or link to documentation page, based on provided parameters.
1084 * For use in PHP code.
1085 * WARNING: Always returns URL, if ts function is not defined ($URLonly has no effect).
1087 * @param string $page Title of documentation wiki page
1088 * @param boolean $URLonly Whether function should return URL only or whole link (default)
1089 * @param string $text Text of HTML link (no effect if $URLonly = false)
1090 * @param string $title Tooltip text for HTML link (no effect if $URLonly = false)
1091 * @param string $style Style attribute value for HTML link (no effect if $URLonly = false)
1093 * @return string URL or link to documentation page, based on provided parameters
1096 static function docURL2($page, $URLonly = FALSE, $text = NULL, $title = NULL, $style = NULL, $resource = NULL) {
1097 // if ts function doesn't exist, it means that CiviCRM hasn't been fully initialised yet -
1098 // return just the URL, no matter what other parameters are defined
1099 if (!function_exists('ts')) {
1100 if ($resource == 'wiki') {
1101 $docBaseURL = self
::getWikiBaseURL();
1103 $docBaseURL = self
::getDocBaseURL();
1105 return $docBaseURL . str_replace(' ', '+', $page);
1110 'URLonly' => $URLonly,
1114 'resource' => $resource,
1116 return self
::docURL($params);
1121 * Returns URL or link to documentation page, based on provided parameters.
1122 * For use in templates code.
1124 * @param array $params An array of parameters (see CRM_Utils_System::docURL2 method for names)
1126 * @return string URL or link to documentation page, based on provided parameters
1129 static function docURL($params) {
1131 if (!isset($params['page'])) {
1135 if (CRM_Utils_Array
::value('resource', $params) == 'wiki') {
1136 $docBaseURL = self
::getWikiBaseURL();
1138 $docBaseURL = self
::getDocBaseURL();
1141 if (!isset($params['title']) or $params['title'] === NULL) {
1142 $params['title'] = ts('Opens documentation in a new window.');
1145 if (!isset($params['text']) or $params['text'] === NULL) {
1146 $params['text'] = ts('(learn more...)');
1149 if (!isset($params['style']) ||
$params['style'] === NULL) {
1153 $style = "style=\"{$params['style']}\"";
1156 $link = $docBaseURL . str_replace(' ', '+', $params['page']);
1158 if (isset($params['URLonly']) && $params['URLonly'] == TRUE) {
1162 return "<a href=\"{$link}\" $style target=\"_blank\" title=\"{$params['title']}\">{$params['text']}</a>";
1167 * Get the locale set in the hosting CMS
1169 * @return string the used locale or null for none
1171 static function getUFLocale() {
1172 $config = CRM_Core_Config
::singleton();
1173 return $config->userSystem
->getUFLocale();
1177 * Execute external or internal urls and return server response
1179 * @param string $url request url
1180 * @param boolean $addCookie should be true to access internal urls
1182 * @return string $response response from url
1185 static function getServerResponse($url, $addCookie = TRUE) {
1186 CRM_Core_Error
::ignoreException();
1187 require_once 'HTTP/Request.php';
1188 $request = new HTTP_Request($url);
1191 foreach ($_COOKIE as $name => $value) {
1192 $request->addCookie($name, $value);
1196 if (isset($_SERVER['AUTH_TYPE'])) {
1197 $request->setBasicAuth($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']);
1200 $config = CRM_Core_Config
::singleton();
1201 if ($config->userFramework
== 'WordPress') {
1202 session_write_close();
1205 $request->sendRequest();
1206 $response = $request->getResponseBody();
1208 CRM_Core_Error
::setCallback();
1212 static function isDBVersionValid(&$errorMessage) {
1213 $dbVersion = CRM_Core_BAO_Domain
::version();
1216 // if db.ver missing
1217 $errorMessage = ts('Version information found to be missing in database. You will need to determine the correct version corresponding to your current database state.');
1220 elseif (!CRM_Utils_System
::isVersionFormatValid($dbVersion)) {
1221 $errorMessage = ts('Database is marked with invalid version format. You may want to investigate this before you proceed further.');
1224 elseif (stripos($dbVersion, 'upgrade')) {
1225 // if db.ver indicates a partially upgraded db
1226 $upgradeUrl = CRM_Utils_System
::url("civicrm/upgrade", "reset=1");
1227 $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));
1231 $codeVersion = CRM_Utils_System
::version();
1233 // if db.ver < code.ver, time to upgrade
1234 if (version_compare($dbVersion, $codeVersion) < 0) {
1235 $upgradeUrl = CRM_Utils_System
::url("civicrm/upgrade", "reset=1");
1236 $errorMessage = ts('New codebase version detected. You might want to visit <a href=\'%1\'>upgrade screen</a> to upgrade the database.', array(1 => $upgradeUrl));
1240 // if db.ver > code.ver, sth really wrong
1241 if (version_compare($dbVersion, $codeVersion) > 0) {
1242 $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.',
1243 array(1 => $dbVersion, 2 => $codeVersion)
1245 $errorMessage .= "<p>" . ts('OR if this is a manual install from git, you might want to fix civicrm-version.php file.') . "</p>";
1249 // FIXME: there should be another check to make sure version is in valid format - X.Y.alpha_num
1254 static function civiExit($status = 0) {
1255 // move things to CiviCRM cache as needed
1256 CRM_Core_Session
::storeSessionObjects();
1262 * Reset the various system caches and some important
1265 static function flushCache( ) {
1266 // flush out all cache entries so we can reload new data
1267 // a bit aggressive, but livable for now
1268 $cache = CRM_Utils_Cache
::singleton();
1271 // also reset the various static memory caches
1273 // reset the memory or array cache
1274 CRM_Core_BAO_Cache
::deleteGroup('contact fields', NULL, FALSE);
1277 CRM_ACL_BAO_Cache
::resetCache();
1279 // reset various static arrays used here
1280 CRM_Contact_BAO_Contact
::$_importableFields =
1281 CRM_Contact_BAO_Contact
::$_exportableFields =
1282 CRM_Contribute_BAO_Contribution
::$_importableFields =
1283 CRM_Contribute_BAO_Contribution
::$_exportableFields =
1284 CRM_Pledge_BAO_Pledge
::$_exportableFields =
1285 CRM_Contribute_BAO_Query
::$_contributionFields =
1286 CRM_Core_BAO_CustomField
::$_importFields =
1287 CRM_Core_BAO_Cache
::$_cache =
1288 CRM_Core_DAO
::$_dbColumnValueCache = NULL;
1290 CRM_Core_OptionGroup
::flushAll();
1291 CRM_Utils_PseudoConstant
::flushAll();
1295 * load cms bootstrap
1297 * @param $params array with uid name and pass
1298 * @param $loadUser boolean load user or not
1300 static function loadBootStrap($params = array(
1301 ), $loadUser = TRUE, $throwError = TRUE, $realPath = NULL) {
1302 if (!is_array($params)) {
1305 $config = CRM_Core_Config
::singleton();
1306 return $config->userSystem
->loadBootStrap($params, $loadUser, $throwError, $realPath);
1310 * check is user logged in.
1314 public static function isUserLoggedIn() {
1315 $config = CRM_Core_Config
::singleton();
1316 return $config->userSystem
->isUserLoggedIn();
1320 * Get current logged in user id.
1322 * @return int ufId, currently logged in user uf id.
1324 public static function getLoggedInUfID() {
1325 $config = CRM_Core_Config
::singleton();
1326 return $config->userSystem
->getLoggedInUfID();
1329 static function baseCMSURL() {
1330 static $_baseURL = NULL;
1332 $config = CRM_Core_Config
::singleton();
1333 $_baseURL = $userFrameworkBaseURL = $config->userFrameworkBaseURL
;
1335 if ($config->userFramework
== 'Joomla') {
1337 // we need to remove the administrator/ from the end
1338 $_baseURL = str_replace("/administrator/", "/", $userFrameworkBaseURL);
1342 global $civicrm_root;
1343 if (strpos($civicrm_root,
1344 DIRECTORY_SEPARATOR
. 'sites' .
1345 DIRECTORY_SEPARATOR
. 'all' .
1346 DIRECTORY_SEPARATOR
. 'modules'
1348 $startPos = strpos($civicrm_root,
1349 DIRECTORY_SEPARATOR
. 'sites' . DIRECTORY_SEPARATOR
1351 $endPos = strpos($civicrm_root,
1352 DIRECTORY_SEPARATOR
. 'modules' . DIRECTORY_SEPARATOR
1354 if ($startPos && $endPos) {
1355 // if component is in sites/SITENAME/modules
1356 $siteName = substr($civicrm_root,
1358 $endPos - $startPos - 7
1361 $_baseURL = $userFrameworkBaseURL . "sites/$siteName/";
1369 static function relativeURL($url) {
1370 // check if url is relative, if so return immediately
1371 if (substr($url, 0, 4) != 'http') {
1375 // make everything relative from the baseFilePath
1376 $baseURL = self
::baseCMSURL();
1378 // check if baseURL is a substr of $url, if so
1379 // return rest of string
1380 if (substr($url, 0, strlen($baseURL)) == $baseURL) {
1381 return substr($url, strlen($baseURL));
1384 // return the original value
1388 static function absoluteURL($url, $removeLanguagePart = FALSE) {
1389 // check if url is already absolute, if so return immediately
1390 if (substr($url, 0, 4) == 'http') {
1394 // make everything absolute from the baseFileURL
1395 $baseURL = self
::baseCMSURL();
1397 //CRM-7622: drop the language from the URL if requested (and it’s there)
1398 $config = CRM_Core_Config
::singleton();
1399 if ($removeLanguagePart) {
1400 $baseURL = self
::languageNegotiationURL($baseURL, FALSE, TRUE);
1403 return $baseURL . $url;
1407 * Function to clean url, replaces first '&' with '?'
1409 * @param string $url
1411 * @return string $url, clean url
1414 static function cleanUrl($url) {
1419 if ($pos = strpos($url, '&')) {
1420 $url = substr_replace($url, '?', $pos, 1);
1427 * Format the url as per language Negotiation.
1429 * @param string $url
1431 * @return string $url, formatted url.
1434 static function languageNegotiationURL($url,
1435 $addLanguagePart = TRUE,
1436 $removeLanguagePart = FALSE
1438 $config = &CRM_Core_Config
::singleton();
1439 return $config->userSystem
->languageNegotiationURL($url, $addLanguagePart, $removeLanguagePart);
1443 * Append the contents of an 'extra' smarty template file if it is present in
1444 * the custom template directory. This does not work if there are
1445 * multiple custom template directories
1447 * @param string $fileName - the name of the tpl file that we are processing
1448 * @param string $content (by reference) - the current content string
1449 * @param string $overideFileName - an optional parameter which is sent by contribution/event reg/profile pages
1450 * which uses a id specific extra file name if present
1452 * @return void - the content string is modified if needed
1455 static function appendTPLFile($fileName,
1457 $overideFileName = NULL
1459 $template = CRM_Core_Smarty
::singleton();
1460 if ($overideFileName) {
1461 $additionalTPLFile = $overideFileName;
1464 $additionalTPLFile = str_replace('.tpl', '.extra.tpl', $fileName);
1467 if ($template->template_exists($additionalTPLFile)) {
1468 $content .= $template->fetch($additionalTPLFile);
1473 * Get a list of all files that are found within the directories
1474 * that are the result of appending the provided relative path to
1475 * each component of the PHP include path.
1477 * @author Ken Zalewski
1479 * @param string $relpath a relative path, typically pointing to
1480 * a directory with multiple class files
1482 * @return array An array of files that exist in one or more of the
1483 * directories that are referenced by the relative path
1484 * when appended to each element of the PHP include path
1487 static function listIncludeFiles($relpath) {
1488 $file_list = array();
1489 $inc_dirs = explode(PATH_SEPARATOR
, get_include_path());
1490 foreach ($inc_dirs as $inc_dir) {
1491 $target_dir = $inc_dir . DIRECTORY_SEPARATOR
. $relpath;
1492 if (is_dir($target_dir)) {
1493 $cur_list = scandir($target_dir);
1494 foreach ($cur_list as $fname) {
1495 if ($fname != '.' && $fname != '..') {
1496 $file_list[$fname] = $fname;
1503 // listIncludeFiles()
1506 * Get a list of all "plugins" (PHP classes that implement a piece of
1507 * functionality using a well-defined interface) that are found in a
1508 * particular CiviCRM directory (both custom and core are searched).
1510 * @author Ken Zalewski
1512 * @param string $relpath a relative path referencing a directory that
1513 * contains one or more plugins
1514 * @param string $fext only files with this extension will be considered
1516 * @param array $skipList list of files to skip
1518 * @return array List of plugins, where the plugin name is both the
1519 * key and the value of each element.
1522 static function getPluginList($relpath, $fext = '.php', $skipList = array(
1524 $fext_len = strlen($fext);
1526 $inc_files = CRM_Utils_System
::listIncludeFiles($relpath);
1527 foreach ($inc_files as $inc_file) {
1528 if (substr($inc_file, 0 - $fext_len) == $fext) {
1529 $plugin_name = substr($inc_file, 0, 0 - $fext_len);
1530 if (!in_array($plugin_name, $skipList)) {
1531 $plugins[$plugin_name] = $plugin_name;
1541 * @param string $fileName - the name of the tpl file that we are processing
1542 * @param string $content (by reference) - the current content string
1544 * @return void - the content string is modified if needed
1547 static function executeScheduledJobs() {
1548 $facility = new CRM_Core_JobManager();
1549 $facility->execute(FALSE);
1551 $redirectUrl = self
::url('civicrm/admin/job', 'reset=1');
1553 CRM_Core_Session
::setStatus(
1554 ts('Scheduled jobs have been executed according to individual timing settings. Please check log for messages.'),
1555 ts('Complete'), 'success');
1557 CRM_Utils_System
::redirect($redirectUrl);
1561 * Evaluate any tokens in a URL
1563 * @param string|FALSE $url
1564 * @return string|FALSE
1566 public static function evalUrl($url) {
1567 if ($url === FALSE) {
1571 $config = CRM_Core_Config
::singleton();
1573 '{ver}' => CRM_Utils_System
::version(),
1574 '{uf}' => $config->userFramework
,
1575 '{php}' => phpversion(),
1576 '{sid}' => md5('sid_' . (defined('CIVICRM_SITE_KEY') ? CIVICRM_SITE_KEY
: '') . '_' . $config->userFrameworkBaseURL
),
1577 '{baseUrl}' => $config->userFrameworkBaseURL
,
1578 '{lang}' => $config->lcMessages
,
1579 '{co}' => $config->defaultContactCountry
,
1581 foreach (array_keys($vars) as $k) {
1582 $vars[$k] = urlencode($vars[$k]);
1584 return strtr($url, $vars);
1590 * Determine whether this is a developmental system.
1594 static function isDevelopment() {
1595 static $cache = NULL;
1596 if ($cache === NULL) {
1597 global $civicrm_root;
1598 $cache = file_exists("{$civicrm_root}/.svn") ||
file_exists("{$civicrm_root}/.git");