2 /*********************************************************************************
3 * SugarCRM Community Edition is a customer relationship management program developed by
4 * SugarCRM, Inc. Copyright (C) 2004-2011 SugarCRM Inc.
6 * This program is free software; you can redistribute it and/or modify it under
7 * the terms of the GNU Affero General Public License version 3 as published by the
8 * Free Software Foundation with the addition of the following permission added
9 * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
10 * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
11 * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
18 * You should have received a copy of the GNU Affero General Public License along with
19 * this program; if not, see http://www.gnu.org/licenses or write to the Free
20 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
24 * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
26 * The interactive user interfaces in modified source and object code versions
27 * of this program must display Appropriate Legal Notices, as required under
28 * Section 5 of the GNU Affero General Public License version 3.
30 * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
31 * these Appropriate Legal Notices must retain the display of the "Powered by
32 * SugarCRM" logo. If the display of the logo is not reasonably feasible for
33 * technical reasons, the Appropriate Legal Notices must display the words
34 * "Powered by SugarCRM".
35 ********************************************************************************/
37 /*********************************************************************************
39 * Description: Includes generic helper functions used throughout the application.
40 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
41 * All Rights Reserved.
42 * Contributor(s): ______________________________________..
43 ********************************************************************************/
44 require_once('include/SugarObjects/SugarConfig.php');
45 require_once('include/utils/security_utils.php');
49 function make_sugar_config(&$sugar_config)
51 /* used to convert non-array config.php file to array format */
52 global $admin_export_only;
54 global $calculate_response_time;
55 global $create_default_user;
58 global $dbconfigoption;
59 global $default_action;
60 global $default_charset;
61 global $default_currency_name;
62 global $default_currency_symbol;
63 global $default_currency_iso4217;
64 global $defaultDateFormat;
65 global $default_language;
66 global $default_module;
67 global $default_password;
68 global $default_permission_mode;
69 global $default_theme;
70 global $defaultTimeFormat;
71 global $default_user_is_admin;
72 global $default_user_name;
73 global $disable_export;
74 global $disable_persistent_connections;
75 global $display_email_template_variable_chooser;
76 global $display_inbound_email_buttons;
77 global $history_max_viewed;
81 global $list_max_entries_per_page;
82 global $lock_default_user_name;
83 global $log_memory_usage;
84 global $requireAccounts;
85 global $RSS_CACHE_TIME;
89 global $sugar_version;
92 global $translation_string_prefix;
94 global $upload_badext;
96 global $upload_maxsize;
97 global $import_max_execution_time;
98 global $list_max_entries_per_subpanel;
99 global $passwordsetting;
101 // assumes the following variables must be set:
102 // $dbconfig, $dbconfigoption, $cache_dir, $import_dir, $session_dir, $site_URL, $tmp_dir, $upload_dir
104 $sugar_config = array (
105 'admin_export_only' => empty($admin_export_only) ? false : $admin_export_only,
106 'export_delimiter' => empty($export_delimiter) ? ',' : $export_delimiter,
107 'cache_dir' => empty($cache_dir) ? 'cache/' : $cache_dir,
108 'calculate_response_time' => empty($calculate_response_time) ? true : $calculate_response_time,
109 'create_default_user' => empty($create_default_user) ? false : $create_default_user,
110 'chartEngine' => 'Jit',
111 'date_formats' => empty($dateFormats) ? array(
112 'Y-m-d'=>'2010-12-23',
113 'd-m-Y' => '23-12-2010',
114 'm-d-Y'=>'12-23-2010',
115 'Y/m/d'=>'2010/12/23',
116 'd/m/Y' => '23/12/2010',
117 'm/d/Y'=>'12/23/2010',
118 'Y.m.d' => '2010.12.23',
119 'd.m.Y' => '23.12.2010',
120 'm.d.Y' => '12.23.2010'
122 'dbconfig' => $dbconfig, // this must be set!!
123 'dbconfigoption' => $dbconfigoption, // this must be set!!
124 'default_action' => empty($default_action) ? 'index' : $default_action,
125 'default_charset' => empty($default_charset) ? 'UTF-8' : $default_charset,
126 'default_currency_name' => empty($default_currency_name) ? 'US Dollar' : $default_currency_name,
127 'default_currency_symbol' => empty($default_currency_symbol) ? '$' : $default_currency_symbol,
128 'default_currency_iso4217' => empty($default_currency_iso4217) ? '$' : $default_currency_iso4217,
129 'default_date_format' => empty($defaultDateFormat) ? 'm/d/Y' : $defaultDateFormat,
130 'default_export_charset' => 'UTF-8',
131 'default_language' => empty($default_language) ? 'en_us' : $default_language,
132 'default_module' => empty($default_module) ? 'Home' : $default_module,
133 'default_password' => empty($default_password) ? '' : $default_password,
134 'default_permissions' => array (
140 'default_theme' => empty($default_theme) ? 'Sugar5' : $default_theme,
141 'default_time_format' => empty($defaultTimeFormat) ? 'h:ia' : $defaultTimeFormat,
142 'default_user_is_admin' => empty($default_user_is_admin) ? false : $default_user_is_admin,
143 'default_user_name' => empty($default_user_name) ? '' : $default_user_name,
144 'disable_export' => empty($disable_export) ? false : $disable_export,
145 'disable_persistent_connections' => empty($disable_persistent_connections) ? false : $disable_persistent_connections,
146 'display_email_template_variable_chooser' => empty($display_email_template_variable_chooser) ? false : $display_email_template_variable_chooser,
147 'display_inbound_email_buttons' => empty($display_inbound_email_buttons) ? false : $display_inbound_email_buttons,
148 'history_max_viewed' => empty($history_max_viewed) ? 50 : $history_max_viewed,
149 'host_name' => empty($host_name) ? 'localhost' : $host_name,
150 'import_dir' => $import_dir, // this must be set!!
151 'import_max_records_per_file' => 100,
152 'languages' => empty($languages) ? array('en_us' => 'English (US)') : $languages,
153 'list_max_entries_per_page' => empty($list_max_entries_per_page) ? 20 : $list_max_entries_per_page,
154 'list_max_entries_per_subpanel' => empty($list_max_entries_per_subpanel) ? 10 : $list_max_entries_per_subpanel,
155 'lock_default_user_name' => empty($lock_default_user_name) ? false : $lock_default_user_name,
156 'log_memory_usage' => empty($log_memory_usage) ? false : $log_memory_usage,
157 'portal_view' => 'single_user',
158 'resource_management' => array (
159 'special_query_limit' => 50000,
160 'special_query_modules' => array('Reports', 'Export', 'Import', 'Administration', 'Sync'),
161 'default_limit' => 1000,
163 'require_accounts' => empty($requireAccounts) ? true : $requireAccounts,
164 'rss_cache_time' => empty($RSS_CACHE_TIME) ? '10800' : $RSS_CACHE_TIME,
165 'session_dir' => $session_dir, // this must be set!!
166 'site_url' => empty($site_URL) ? $site_url : $site_URL, // this must be set!!
167 'showDetailData' => true, // if true, read-only ACL fields will still appear on EditViews as non-editable
168 'showThemePicker' => true,
169 'sugar_version' => empty($sugar_version) ? 'unknown' : $sugar_version,
170 'time_formats' => empty($timeFormats) ? array (
171 'H:i'=>'23:00', 'h:ia'=>'11:00 pm', 'h:iA'=>'11:00PM',
172 'H.i'=>'23.00', 'h.ia'=>'11.00 pm', 'h.iA'=>'11.00PM' ) : $timeFormats,
173 'tmp_dir' => $tmp_dir, // this must be set!!
174 'translation_string_prefix' => empty($translation_string_prefix) ? false : $translation_string_prefix,
175 'unique_key' => empty($unique_key) ? md5(create_guid()) : $unique_key,
176 'upload_badext' => empty($upload_badext) ? array (
177 'php', 'php3', 'php4', 'php5', 'pl', 'cgi', 'py',
178 'asp', 'cfm', 'js', 'vbs', 'html', 'htm' ) : $upload_badext,
179 'upload_dir' => $upload_dir, // this must be set!!
180 'upload_maxsize' => empty($upload_maxsize) ? 3000000 : $upload_maxsize,
181 'import_max_execution_time' => empty($import_max_execution_time) ? 3600 : $import_max_execution_time,
182 'lock_homepage' => false,
183 'lock_subpanels' => false,
184 'max_dashlets_homepage' => 15,
185 'dashlet_display_row_options' => array('1','3','5','10'),
186 'default_max_tabs' => empty($max_tabs) ? '7' : $max_tabs,
187 'default_subpanel_tabs' => empty($subpanel_tabs) ? true : $subpanel_tabs,
188 'default_subpanel_links' => empty($subpanel_links) ? false : $subpanel_links,
189 'default_swap_last_viewed' => empty($swap_last_viewed) ? false : $swap_last_viewed,
190 'default_swap_shortcuts' => empty($swap_shortcuts) ? false : $swap_shortcuts,
191 'default_navigation_paradigm' => empty($navigation_paradigm) ? 'gm' : $navigation_paradigm,
192 'default_call_status' => 'Planned',
193 'js_lang_version' => 1,
194 'passwordsetting' => empty($passwordsetting) ? array (
195 'SystemGeneratedPasswordON' => '',
196 'generatepasswordtmpl' => '',
197 'lostpasswordtmpl' => '',
198 'forgotpasswordON' => true,
199 'linkexpiration' => '1',
200 'linkexpirationtime' => '30',
201 'linkexpirationtype' => '1',
202 'systexpiration' => '0',
203 'systexpirationtime' => '',
204 'systexpirationtype' => '0',
205 'systexpirationlogin' => '',
206 ) : $passwordsetting,
210 function get_sugar_config_defaults() {
213 * used for getting base values for array style config.php. used by the
214 * installer and to fill in new entries on upgrades. see also:
218 $sugar_config_defaults = array (
219 'admin_export_only' => false,
220 'export_delimiter' => ',',
221 'cache_dir' => 'cache/',
222 'calculate_response_time' => true,
223 'create_default_user' => false,
224 'chartEngine' => 'Jit',
225 'date_formats' => array (
226 'Y-m-d' => '2010-12-23', 'm-d-Y' => '12-23-2010', 'd-m-Y' => '23-12-2010',
227 'Y/m/d' => '2010/12/23', 'm/d/Y' => '12/23/2010', 'd/m/Y' => '23/12/2010',
228 'Y.m.d' => '2010.12.23', 'd.m.Y' => '23.12.2010', 'm.d.Y' => '12.23.2010',),
229 'dbconfigoption' => array (
230 'persistent' => true,
233 'seqname_format' => '%s_seq',
236 'default_action' => 'index',
237 'default_charset' => return_session_value_or_default('default_charset',
239 'default_currency_name' => return_session_value_or_default('default_currency_name', 'US Dollar'),
240 'default_currency_symbol' => return_session_value_or_default('default_currency_symbol', '$'),
241 'default_currency_iso4217' => return_session_value_or_default('default_currency_iso4217', 'USD'),
242 'default_currency_significant_digits' => return_session_value_or_default('default_currency_significant_digits', 2),
243 'default_number_grouping_seperator' => return_session_value_or_default('default_number_grouping_seperator', ','),
244 'default_decimal_seperator' => return_session_value_or_default('default_decimal_seperator', '.'),
245 'default_date_format' => 'm/d/Y',
246 'default_export_charset' => 'UTF-8',
247 'default_language' => return_session_value_or_default('default_language',
249 'default_module' => 'Home',
250 'default_password' => '',
251 'default_permissions' => array (
257 'default_theme' => return_session_value_or_default('site_default_theme', 'Sugar5'),
258 'default_time_format' => 'h:ia',
259 'default_user_is_admin' => false,
260 'default_user_name' => '',
261 'disable_export' => false,
262 'disable_persistent_connections' =>
263 return_session_value_or_default('disable_persistent_connections',
265 'display_email_template_variable_chooser' => false,
266 'display_inbound_email_buttons' => false,
267 'dump_slow_queries' => false,
268 'email_default_editor' => 'html',
269 'email_default_client' => 'sugar',
270 'email_default_delete_attachments' => true,
271 'history_max_viewed' => 50,
272 'installer_locked' => true,
273 'import_max_records_per_file' => 100,
274 'languages' => array('en_us' => 'English (US)'),
275 'large_scale_test' => false,
276 'list_max_entries_per_page' => 20,
277 'list_max_entries_per_subpanel' => 10,
278 'lock_default_user_name' => false,
279 'log_memory_usage' => false,
280 'portal_view' => 'single_user',
281 'resource_management' => array (
282 'special_query_limit' => 50000,
283 'special_query_modules' => array('Reports', 'Export', 'Import', 'Administration', 'Sync'),
284 'default_limit' => 1000,
286 'require_accounts' => true,
287 'rss_cache_time' => return_session_value_or_default('rss_cache_time',
289 'save_query' => 'all',
290 'showDetailData' => true, // if true, read-only ACL fields will still appear on EditViews as non-editable
291 'showThemePicker' => true,
292 'slow_query_time_msec' => '100',
294 'time_formats' => array (
295 'H:i'=>'23:00', 'h:ia'=>'11:00pm', 'h:iA'=>'11:00PM',
296 'H.i'=>'23.00', 'h.ia'=>'11.00pm', 'h.iA'=>'11.00PM' ),
297 'tracker_max_display_length' => 15,
298 'translation_string_prefix' =>
299 return_session_value_or_default('translation_string_prefix', false),
300 'upload_badext' => array (
301 'php', 'php3', 'php4', 'php5', 'pl', 'cgi', 'py',
302 'asp', 'cfm', 'js', 'vbs', 'html', 'htm' ),
303 'upload_maxsize' => 3000000,
304 'import_max_execution_time' => 3600,
305 // 'use_php_code_json' => returnPhpJsonStatus(),
306 'verify_client_ip' => true,
307 'js_custom_version' => '',
308 'js_lang_version' => 1,
309 'default_number_grouping_seperator' => ',',
310 'default_decimal_seperator' => '.',
311 'lock_homepage' => false,
312 'lock_subpanels' => false,
313 'max_dashlets_homepage' => '15',
314 'default_max_tabs' => '7',
315 'dashlet_display_row_options' => array('1','3','5','10'),
316 'default_subpanel_tabs' => true,
317 'default_subpanel_links' => false,
318 'default_swap_last_viewed' => false,
319 'default_swap_shortcuts' => false,
320 'default_navigation_paradigm' => 'gm',
321 'admin_access_control' => false,
322 'use_common_ml_dir' => false,
323 'common_ml_dir' => '',
325 'passwordsetting' => empty($passwordsetting) ? array (
326 'SystemGeneratedPasswordON' => '',
327 'generatepasswordtmpl' => '',
328 'lostpasswordtmpl' => '',
329 'forgotpasswordON' => false,
330 'linkexpiration' => '1',
331 'linkexpirationtime' => '30',
332 'linkexpirationtype' => '1',
333 'systexpiration' => '0',
334 'systexpirationtime' => '',
335 'systexpirationtype' => '0',
336 'systexpirationlogin' => '',
337 ) : $passwordsetting,
338 'use_real_names' => true,
341 if(!is_object($locale)) {
342 $locale = new Localization();
345 $sugar_config_defaults['default_currencies'] = $locale->getDefaultCurrencies();
347 $sugar_config_defaults = sugarArrayMerge($locale->getLocaleConfigDefaults(), $sugar_config_defaults);
348 return( $sugar_config_defaults );
352 * @deprecated use SugarView::getMenu() instead
354 function load_menu($path){
357 if(file_exists($path . 'Menu.php'))
359 require($path . 'Menu.php');
361 if(file_exists('custom/' . $path . 'Ext/Menus/menu.ext.php'))
363 require('custom/' . $path . 'Ext/Menus/menu.ext.php');
365 if(file_exists('custom/application/Ext/Menus/menu.ext.php'))
367 require('custom/application/Ext/Menus/menu.ext.php');
373 * get_notify_template_file
374 * This function will return the location of the email notifications template to use
376 * @return string relative file path to email notifications template file
378 function get_notify_template_file($language){
380 * Order of operation:
381 * 1) custom version of specified language
382 * 2) stock version of specified language
383 * 3) custom version of en_us template
384 * 4) stock en_us template
387 // set $file to the base code template so it's set if none of the conditions pass
388 $file = "include/language/en_us.notify_template.html";
390 if(file_exists("custom/include/language/{$language}.notify_template.html")){
391 $file = "custom/include/language/{$language}.notify_template.html";
393 else if(file_exists("include/language/{$language}.notify_template.html")){
394 $file = "include/language/{$language}.notify_template.html";
396 else if(file_exists("custom/include/language/en_us.notify_template.html")){
397 $file = "custom/include/language/en_us.notify_template.html";
403 function sugar_config_union( $default, $override ){
404 // a little different then array_merge and array_merge_recursive. we want
405 // the second array to override the first array if the same value exists,
406 // otherwise merge the unique keys. it handles arrays of arrays recursively
407 // might be suitable for a generic array_union
408 if( !is_array( $override ) ){
411 foreach( $default as $key => $value ){
412 if( !array_key_exists($key, $override) ){
413 $override[$key] = $value;
415 else if( is_array( $key ) ){
416 $override[$key] = sugar_config_union( $value, $override[$key] );
422 function make_not_writable( $file ){
423 // Returns true if the given file/dir has been made not writable
425 if( is_file($file) || is_dir($file) ){
426 if( !is_writable($file) ){
430 $original_fileperms = fileperms($file);
432 // take away writable permissions
433 $new_fileperms = $original_fileperms & ~0x0092;
434 @sugar_chmod($file, $new_fileperms);
436 if( !is_writable($file) ){
445 /** This function returns the name of the person.
446 * It currently returns "first last". It should not put the space if either name is not available.
447 * It should not return errors if either name is not available.
448 * If no names are present, it will return ""
449 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
450 * All Rights Reserved.
451 * Contributor(s): ______________________________________..
453 function return_name($row, $first_column, $last_column)
459 if(isset($row[$first_column]))
461 $first_name = stripslashes($row[$first_column]);
464 if(isset($row[$last_column]))
466 $last_name = stripslashes($row[$last_column]);
469 $full_name = $first_name;
471 // If we have a first name and we have a last name
472 if($full_name != "" && $last_name != "")
474 // append a space, then the last name
475 $full_name .= " ".$last_name;
477 // If we have no first name, but we have a last name
478 else if($last_name != "")
480 // append the last name without the space.
481 $full_name .= $last_name;
488 function get_languages()
490 global $sugar_config;
491 $lang = $sugar_config['languages'];
492 if(!empty($sugar_config['disabled_languages'])){
493 foreach(explode(',', $sugar_config['disabled_languages']) as $disable) {
494 unset($lang[$disable]);
500 function get_all_languages()
502 global $sugar_config;
503 return $sugar_config['languages'];
507 function get_language_display($key)
509 global $sugar_config;
510 return $sugar_config['languages'][$key];
513 function get_assigned_user_name($assigned_user_id, $is_group = '') {
514 static $saved_user_list = null;
516 if(empty($saved_user_list)) {
517 $saved_user_list = get_user_array(false, '', '', false, null, $is_group);
520 if(isset($saved_user_list[$assigned_user_id])) {
521 return $saved_user_list[$assigned_user_id];
528 * retrieves the user_name column value (login)
529 * @param string id GUID of user
532 function get_user_name($id) {
536 $db = DBManagerFactory::getInstance();
538 $q = "SELECT user_name FROM users WHERE id='{$id}'";
540 $a = $db->fetchByAssoc($r);
542 return (empty($a)) ? '' : $a['user_name'];
546 //TODO Update to use global cache
547 function get_user_array($add_blank=true, $status="Active", $assigned_user="", $use_real_name=false, $user_name_begins = null, $is_group=' AND portal_only=0 ', $from_cache = true) {
549 global $sugar_config;
553 $locale = new Localization();
556 $user_array = get_register_value('user_array', $add_blank. $status . $assigned_user);
558 if(!isset($user_array)) {
559 $db = DBManagerFactory::getInstance();
560 $temp_result = Array();
561 // Including deleted users for now.
562 if (empty($status)) {
563 $query = "SELECT id, first_name, last_name, user_name from users WHERE 1=1".$is_group;
566 $query = "SELECT id, first_name, last_name, user_name from users WHERE status='$status'".$is_group;
569 if (!empty($user_name_begins)) {
570 $query .= " AND user_name LIKE '$user_name_begins%' ";
572 if (!empty($assigned_user)) {
573 $query .= " OR id='$assigned_user'";
575 $query = $query.' ORDER BY user_name ASC';
576 $GLOBALS['log']->debug("get_user_array query: $query");
577 $result = $db->query($query, true, "Error filling in user array: ");
579 if ($add_blank==true) {
580 // Add in a blank row
581 $temp_result[''] = '';
584 // Get the id and the name.
585 while($row = $db->fetchByAssoc($result)) {
586 if($use_real_name == true || showFullName()) {
587 if(isset($row['last_name'])) { // cn: we will ALWAYS have both first_name and last_name (empty value if blank in db)
588 $temp_result[$row['id']] = $locale->getLocaleFormattedName($row['first_name'],$row['last_name']);
590 $temp_result[$row['id']] = $row['user_name'];
593 $temp_result[$row['id']] = $row['user_name'];
597 $user_array = $temp_result;
599 set_register_value('user_array', $add_blank. $status . $assigned_user, $temp_result);
608 * uses a different query to return a list of users than get_user_array()
609 * @param args string where clause entry
610 * @return array Array of Users' details that match passed criteria
612 function getUserArrayFromFullName($args, $hide_portal_users = false) {
614 $db = DBManagerFactory::getInstance();
617 if(strpos($args, " ")) {
618 $argArray = explode(" ", $args);
624 foreach($argArray as $arg) {
625 if(!empty($inClause)) {
631 $inClause .= "(first_name LIKE '{$arg}%' OR last_name LIKE '{$arg}%')";
634 $query = "SELECT id, first_name, last_name, user_name FROM users WHERE status='Active' AND deleted=0 AND ";
635 if ( $hide_portal_users ) {
636 $query .= " portal_only=0 AND ";
639 $query .= " ORDER BY last_name ASC";
641 $r = $db->query($query);
643 while($a = $db->fetchByAssoc($r)) {
644 $ret[$a['id']] = $locale->getLocaleFormattedName($a['first_name'], $a['last_name']);
652 * based on user pref then system pref
654 function showFullName() {
655 global $sugar_config;
656 global $current_user;
657 static $showFullName = null;
659 if (is_null($showFullName)) {
660 $sysPref = !empty($sugar_config['use_real_names']);
661 $userPref = (is_object($current_user)) ? $current_user->getPreference('use_real_names') : null;
663 if($userPref != null) {
664 $showFullName = ($userPref == 'on');
666 $showFullName = $sysPref;
670 return $showFullName;
673 function clean($string, $maxLength)
675 $string = substr($string, 0, $maxLength);
676 return escapeshellcmd($string);
680 * Copy the specified request variable to the member variable of the specified object.
681 * Do no copy if the member variable is already set.
682 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
683 * All Rights Reserved.
684 * Contributor(s): ______________________________________..
686 function safe_map($request_var, & $focus, $always_copy = false)
688 safe_map_named($request_var, $focus, $request_var, $always_copy);
692 * Copy the specified request variable to the member variable of the specified object.
693 * Do no copy if the member variable is already set.
694 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
695 * All Rights Reserved.
696 * Contributor(s): ______________________________________..
698 function safe_map_named($request_var, & $focus, $member_var, $always_copy)
700 if (isset($_REQUEST[$request_var]) && ($always_copy || is_null($focus->$member_var))) {
701 $GLOBALS['log']->debug("safe map named called assigning '{$_REQUEST[$request_var]}' to $member_var");
702 $focus->$member_var = $_REQUEST[$request_var];
707 * This function retrieves an application language file and returns the array of strings included in the $app_list_strings var.
709 * @param string $language specific language to load
710 * @return array lang strings
712 function return_app_list_strings_language($language)
714 global $app_list_strings;
715 global $sugar_config;
717 $cache_key = 'app_list_strings.'.$language;
719 // Check for cached value
720 $cache_entry = sugar_cache_retrieve($cache_key);
721 if(!empty($cache_entry))
726 $default_language = $sugar_config['default_language'];
727 $temp_app_list_strings = $app_list_strings;
730 if ($language != 'en_us') {
733 if ($default_language != 'en_us' && $language != $default_language) {
734 $langs[] = $default_language;
736 $langs[] = $language;
738 $app_list_strings_array = array();
740 foreach ( $langs as $lang ) {
741 $app_list_strings = array();
742 if(file_exists("include/language/$lang.lang.php")) {
743 include("include/language/$lang.lang.php");
744 $GLOBALS['log']->info("Found language file: $lang.lang.php");
746 if(file_exists("include/language/$lang.lang.override.php")) {
747 include("include/language/$lang.lang.override.php");
748 $GLOBALS['log']->info("Found override language file: $lang.lang.override.php");
750 if(file_exists("include/language/$lang.lang.php.override")) {
751 include("include/language/$lang.lang.php.override");
752 $GLOBALS['log']->info("Found override language file: $lang.lang.php.override");
755 $app_list_strings_array[] = $app_list_strings;
758 $app_list_strings = array();
759 foreach ( $app_list_strings_array as $app_list_strings_item ) {
760 $app_list_strings = sugarArrayMerge($app_list_strings, $app_list_strings_item);
763 foreach ( $langs as $lang ) {
764 if(file_exists("custom/application/Ext/Language/$lang.lang.ext.php")) {
765 $app_list_strings = _mergeCustomAppListStrings("custom/application/Ext/Language/$lang.lang.ext.php" , $app_list_strings);
766 $GLOBALS['log']->info("Found extended language file: $lang.lang.ext.php");
768 if(file_exists("custom/include/language/$lang.lang.php")) {
769 include("custom/include/language/$lang.lang.php");
770 $GLOBALS['log']->info("Found custom language file: $lang.lang.php");
774 if(!isset($app_list_strings)) {
775 $GLOBALS['log']->fatal("Unable to load the application language file for the selected language ($language) or the default language ($default_language) or the en_us language");
779 $return_value = $app_list_strings;
780 $app_list_strings = $temp_app_list_strings;
782 sugar_cache_put($cache_key, $return_value);
784 return $return_value;
788 * The dropdown items in custom language files is $app_list_strings['$key']['$second_key'] = $value not
789 * $GLOBALS['app_list_strings']['$key'] = $value, so we have to delete the original ones in app_list_strings and relace it with the custom ones.
790 * @param file string the language that you want include,
791 * @param app_list_strings array the golbal strings
795 function _mergeCustomAppListStrings($file , $app_list_strings){
796 $app_list_strings_original = $app_list_strings;
797 unset($app_list_strings);
799 if(!isset($app_list_strings) || !is_array($app_list_strings)){
800 return $app_list_strings_original;
802 //Bug 25347: We should not merge custom dropdown fields unless they relate to parent fields or the module list.
803 foreach($app_list_strings as $key=>$value)
805 $exemptDropdowns = array("moduleList", "parent_type_display", "record_type_display", "record_type_display_notes");
806 if (!in_array($key, $exemptDropdowns) && array_key_exists($key, $app_list_strings_original))
808 unset($app_list_strings_original["$key"]);
811 $app_list_strings = sugarArrayMergeRecursive($app_list_strings_original , $app_list_strings);
812 return $app_list_strings;
816 * This function retrieves an application language file and returns the array of strings included.
818 * @param string $language specific language to load
819 * @return array lang strings
821 function return_application_language($language)
823 global $app_strings, $sugar_config;
825 $cache_key = 'app_strings.'.$language;
827 // Check for cached value
828 $cache_entry = sugar_cache_retrieve($cache_key);
829 if(!empty($cache_entry))
834 $temp_app_strings = $app_strings;
835 $default_language = $sugar_config['default_language'];
838 if ($language != 'en_us') {
841 if ($default_language != 'en_us' && $language != $default_language) {
842 $langs[] = $default_language;
845 $langs[] = $language;
847 $app_strings_array = array();
849 foreach ( $langs as $lang ) {
850 $app_strings = array();
851 if(file_exists("include/language/$lang.lang.php")) {
852 include("include/language/$lang.lang.php");
853 $GLOBALS['log']->info("Found language file: $lang.lang.php");
855 if(file_exists("include/language/$lang.lang.override.php")) {
856 include("include/language/$lang.lang.override.php");
857 $GLOBALS['log']->info("Found override language file: $lang.lang.override.php");
859 if(file_exists("include/language/$lang.lang.php.override")) {
860 include("include/language/$lang.lang.php.override");
861 $GLOBALS['log']->info("Found override language file: $lang.lang.php.override");
863 if(file_exists("custom/application/Ext/Language/$lang.lang.ext.php")) {
864 include("custom/application/Ext/Language/$lang.lang.ext.php");
865 $GLOBALS['log']->info("Found extended language file: $lang.lang.ext.php");
867 if(file_exists("custom/include/language/$lang.lang.php")) {
868 include("custom/include/language/$lang.lang.php");
869 $GLOBALS['log']->info("Found custom language file: $lang.lang.php");
871 $app_strings_array[] = $app_strings;
874 $app_strings = array();
875 foreach ( $app_strings_array as $app_strings_item ) {
876 $app_strings = sugarArrayMerge($app_strings, $app_strings_item);
879 if(!isset($app_strings)) {
880 $GLOBALS['log']->fatal("Unable to load the application language strings");
884 // If we are in debug mode for translating, turn on the prefix now!
885 if($sugar_config['translation_string_prefix']) {
886 foreach($app_strings as $entry_key=>$entry_value) {
887 $app_strings[$entry_key] = $language.' '.$entry_value;
890 if(isset($_SESSION['show_deleted'])) {
891 $app_strings['LBL_DELETE_BUTTON'] = $app_strings['LBL_UNDELETE_BUTTON'];
892 $app_strings['LBL_DELETE_BUTTON_LABEL'] = $app_strings['LBL_UNDELETE_BUTTON_LABEL'];
893 $app_strings['LBL_DELETE_BUTTON_TITLE'] = $app_strings['LBL_UNDELETE_BUTTON_TITLE'];
894 $app_strings['LBL_DELETE'] = $app_strings['LBL_UNDELETE'];
897 $app_strings['LBL_ALT_HOT_KEY'] = get_alt_hot_key();
899 $return_value = $app_strings;
900 $app_strings = $temp_app_strings;
902 sugar_cache_put($cache_key, $return_value);
904 return $return_value;
908 * This function retrieves a module's language file and returns the array of strings included.
910 * @param string $language specific language to load
911 * @param string $module module name to load strings for
912 * @param bool $refresh optional, true if you want to rebuild the language strings
913 * @return array lang strings
915 function return_module_language($language, $module, $refresh=false)
918 global $sugar_config;
919 global $currentModule;
921 // Jenny - Bug 8119: Need to check if $module is not empty
922 if (empty($module)) {
923 $stack = debug_backtrace();
924 $GLOBALS['log']->warn("Variable module is not in return_module_language ". var_export($stack, true));
928 $cache_key = LanguageManager::getLanguageCacheKey($module, $language);
929 // Check for cached value
930 $cache_entry = sugar_cache_retrieve($cache_key);
931 if(!empty($cache_entry))
936 // Store the current mod strings for later
937 $temp_mod_strings = $mod_strings;
938 $loaded_mod_strings = array();
939 $language_used = $language;
940 $default_language = $sugar_config['default_language'];
942 if(empty($language)) {
943 $language = $default_language;
946 // Bug 21559 - So we can get all the strings defined in the template, refresh
947 // the vardefs file if the cached language file doesn't exist.
948 if(!file_exists($GLOBALS['sugar_config']['cache_dir'].'modules/'. $module . '/language/'.$language.'.lang.php')
949 && !empty($GLOBALS['beanList'][$module])){
950 $object = $GLOBALS['beanList'][$module];
951 if ($object == 'aCase') {
954 VardefManager::refreshVardefs($module,$object);
957 $loaded_mod_strings = LanguageManager::loadModuleLanguage($module, $language,$refresh);
959 // cn: bug 6048 - merge en_us with requested language
960 if($language != $sugar_config['default_language'])
961 $loaded_mod_strings = sugarArrayMerge(
962 LanguageManager::loadModuleLanguage($module, $sugar_config['default_language'],$refresh),
966 // Load in en_us strings by default
967 if($language != 'en_us' && $sugar_config['default_language'] != 'en_us')
968 $loaded_mod_strings = sugarArrayMerge(
969 LanguageManager::loadModuleLanguage($module, 'en_us', $refresh),
973 // If we are in debug mode for translating, turn on the prefix now!
974 if($sugar_config['translation_string_prefix']) {
975 foreach($loaded_mod_strings as $entry_key=>$entry_value) {
976 $loaded_mod_strings[$entry_key] = $language_used.' '.$entry_value;
980 $return_value = $loaded_mod_strings;
981 if(!isset($mod_strings)){
982 $mod_strings = $return_value;
985 $mod_strings = $temp_mod_strings;
987 sugar_cache_put($cache_key, $return_value);
988 return $return_value;
992 /** This function retrieves an application language file and returns the array of strings included in the $mod_list_strings var.
993 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
994 * All Rights Reserved.
995 * Contributor(s): ______________________________________..
996 * If you are using the current language, do not call this function unless you are loading it for the first time */
997 function return_mod_list_strings_language($language,$module) {
998 global $mod_list_strings;
999 global $sugar_config;
1000 global $currentModule;
1002 $cache_key = "mod_list_str_lang.".$language.$module;
1004 // Check for cached value
1005 $cache_entry = sugar_cache_retrieve($cache_key);
1006 if(!empty($cache_entry))
1008 return $cache_entry;
1011 $language_used = $language;
1012 $temp_mod_list_strings = $mod_list_strings;
1013 $default_language = $sugar_config['default_language'];
1015 if($currentModule == $module && isset($mod_list_strings) && $mod_list_strings != null) {
1016 return $mod_list_strings;
1019 // cn: bug 6351 - include en_us if file langpack not available
1020 // cn: bug 6048 - merge en_us with requested language
1021 include("modules/$module/language/en_us.lang.php");
1022 $en_mod_list_strings = array();
1023 if($language_used != $default_language)
1024 $en_mod_list_strings = $mod_list_strings;
1026 if(file_exists("modules/$module/language/$language.lang.php")) {
1027 include("modules/$module/language/$language.lang.php");
1030 if(file_exists("modules/$module/language/$language.lang.override.php")){
1031 include("modules/$module/language/$language.lang.override.php");
1034 if(file_exists("modules/$module/language/$language.lang.php.override")){
1035 echo 'Please Change:<br>' . "modules/$module/language/$language.lang.php.override" . '<br>to<br>' . 'Please Change:<br>' . "modules/$module/language/$language.lang.override.php";
1036 include("modules/$module/language/$language.lang.php.override");
1039 // cn: bug 6048 - merge en_us with requested language
1040 $mod_list_strings = sugarArrayMerge($en_mod_list_strings, $mod_list_strings);
1042 // if we still don't have a language pack, then log an error
1043 if(!isset($mod_list_strings)) {
1044 $GLOBALS['log']->fatal("Unable to load the application list language file for the selected language($language) or the default language($default_language) for module({$module})");
1048 $return_value = $mod_list_strings;
1049 $mod_list_strings = $temp_mod_list_strings;
1051 sugar_cache_put($cache_key, $return_value);
1052 return $return_value;
1056 /** This function retrieves a theme's language file and returns the array of strings included.
1057 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1058 * All Rights Reserved.
1059 * Contributor(s): ______________________________________..
1061 function return_theme_language($language, $theme)
1063 global $mod_strings, $sugar_config, $currentModule;
1065 $language_used = $language;
1066 $default_language = $sugar_config['default_language'];
1068 include(SugarThemeRegistry::get($theme)->getFilePath()."/language/$current_language.lang.php");
1069 if(file_exists(SugarThemeRegistry::get($theme)->getFilePath()."/language/$current_language.lang.override.php")){
1070 include(SugarThemeRegistry::get($theme)->getFilePath()."/language/$current_language.lang.override.php");
1072 if(file_exists(SugarThemeRegistry::get($theme)->getFilePath()."/language/$current_language.lang.php.override")){
1073 echo 'Please Change:<br>' . SugarThemeRegistry::get($theme)->getFilePath()."/language/$current_language.lang.php.override" . '<br>to<br>' . 'Please Change:<br>' . SugarThemeRegistry::get($theme)->getFilePath()."/language/$current_language.lang.override.php";
1074 include(SugarThemeRegistry::get($theme)->getFilePath()."/language/$current_language.lang.php.override");
1076 if(!isset($theme_strings))
1078 $GLOBALS['log']->warn("Unable to find the theme file for language: ".$language." and theme: ".$theme);
1079 require(SugarThemeRegistry::get($theme)->getFilePath()."/language/$default_language.lang.php");
1080 $language_used = $default_language;
1083 if(!isset($theme_strings))
1085 $GLOBALS['log']->fatal("Unable to load the theme($theme) language file for the selected language($language) or the default language($default_language)");
1089 // If we are in debug mode for translating, turn on the prefix now!
1090 if($sugar_config['translation_string_prefix'])
1092 foreach($theme_strings as $entry_key=>$entry_value)
1094 $theme_strings[$entry_key] = $language_used.' '.$entry_value;
1098 return $theme_strings;
1103 /** If the session variable is defined and is not equal to "" then return it. Otherwise, return the default value.
1104 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1105 * All Rights Reserved.
1106 * Contributor(s): ______________________________________..
1108 function return_session_value_or_default($varname, $default)
1110 if(isset($_SESSION[$varname]) && $_SESSION[$varname] != "")
1112 return $_SESSION[$varname];
1119 * Creates an array of where restrictions. These are used to construct a where SQL statement on the query
1120 * It looks for the variable in the $_REQUEST array. If it is set and is not "" it will create a where clause out of it.
1121 * @param &$where_clauses - The array to append the clause to
1122 * @param $variable_name - The name of the variable to look for an add to the where clause if found
1123 * @param $SQL_name - [Optional] If specified, this is the SQL column name that is used. If not specified, the $variable_name is used as the SQL_name.
1124 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1125 * All Rights Reserved.
1126 * Contributor(s): ______________________________________..
1128 function append_where_clause(&$where_clauses, $variable_name, $SQL_name = null)
1130 if($SQL_name == null)
1132 $SQL_name = $variable_name;
1135 if(isset($_REQUEST[$variable_name]) && $_REQUEST[$variable_name] != "")
1137 array_push($where_clauses, "$SQL_name like '".$GLOBALS['db']->quote($_REQUEST[$variable_name])."%'");
1142 * Generate the appropriate SQL based on the where clauses.
1143 * @param $where_clauses - An Array of individual where clauses stored as strings
1144 * @returns string where_clause - The final SQL where clause to be executed.
1145 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1146 * All Rights Reserved.
1147 * Contributor(s): ______________________________________..
1149 function generate_where_statement($where_clauses)
1152 foreach($where_clauses as $clause)
1159 $GLOBALS['log']->info("Here is the where clause for the list view: $where");
1164 * determines if a passed string matches the criteria for a Sugar GUID
1165 * @param string $guid
1166 * @return bool False on failure
1168 function is_guid($guid) {
1169 if(strlen($guid) != 36) {
1173 if(preg_match("/\w{8}-\w{4}-\w{4}-\w{4}-\w{12}/i", $guid)) {
1182 * A temporary method of generating GUIDs of the correct format for our DB.
1183 * @return String contianing a GUID in the format: aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
1185 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1186 * All Rights Reserved.
1187 * Contributor(s): ______________________________________..
1189 function create_guid()
1191 $microTime = microtime();
1192 list($a_dec, $a_sec) = explode(" ", $microTime);
1194 $dec_hex = dechex($a_dec* 1000000);
1195 $sec_hex = dechex($a_sec);
1197 ensure_length($dec_hex, 5);
1198 ensure_length($sec_hex, 6);
1202 $guid .= create_guid_section(3);
1204 $guid .= create_guid_section(4);
1206 $guid .= create_guid_section(4);
1208 $guid .= create_guid_section(4);
1211 $guid .= create_guid_section(6);
1217 function create_guid_section($characters)
1220 for($i=0; $i<$characters; $i++)
1222 $return .= dechex(mt_rand(0,15));
1227 function ensure_length(&$string, $length)
1229 $strlen = strlen($string);
1230 if($strlen < $length)
1232 $string = str_pad($string,$length,"0");
1234 else if($strlen > $length)
1236 $string = substr($string, 0, $length);
1240 function microtime_diff($a, $b) {
1241 list($a_dec, $a_sec) = explode(" ", $a);
1242 list($b_dec, $b_sec) = explode(" ", $b);
1243 return $b_sec - $a_sec + $b_dec - $a_dec;
1246 // check if Studio is displayed.
1247 function displayStudioForCurrentUser()
1249 global $current_user;
1250 if ( $current_user->isAdmin() ) {
1260 function displayWorkflowForCurrentUser()
1262 $_SESSION['display_workflow_for_user'] = false;
1266 // return an array with all modules where the user is an admin.
1267 function get_admin_modules_for_user($user) {
1268 $GLOBALS['log']->deprecated("get_admin_modules_for_user() is deprecated as of 6.2.2 and may disappear in the future, use Users->getDeveloperModules() instead");
1275 return($user->getDeveloperModules());
1279 function get_workflow_admin_modules_for_user($user){
1280 if (isset($_SESSION['get_workflow_admin_modules_for_user'])) {
1281 return $_SESSION['get_workflow_admin_modules_for_user'];
1285 $workflow_mod_list = array();
1286 foreach($moduleList as $module){
1287 $workflow_mod_list[$module] = $module;
1290 // This list is taken from teh previous version of workflow_utils.php
1291 $workflow_mod_list['Tasks'] = "Tasks";
1292 $workflow_mod_list['Calls'] = "Calls";
1293 $workflow_mod_list['Meetings'] = "Meetings";
1294 $workflow_mod_list['Notes'] = "Notes";
1295 $workflow_mod_list['ProjectTask'] = "Project Tasks";
1296 $workflow_mod_list['Leads'] = "Leads";
1297 $workflow_mod_list['Opportunities'] = "Opportunities";
1300 $workflow_admin_modules = array();
1302 return $workflow_admin_modules;
1304 $actions = ACLAction::getUserActions($user->id);
1305 //check for ForecastSchedule because it doesn't exist in $workflow_mod_list
1306 if (isset($actions['ForecastSchedule']['module']['admin']['aclaccess']) && ($actions['ForecastSchedule']['module']['admin']['aclaccess']==ACL_ALLOW_DEV ||
1307 $actions['ForecastSchedule']['module']['admin']['aclaccess']==ACL_ALLOW_ADMIN_DEV)) {
1308 $workflow_admin_modules['Forecasts'] = 'Forecasts';
1310 foreach ($workflow_mod_list as $key=>$val) {
1311 if(!in_array($val, $workflow_admin_modules) && ($val!='iFrames' && $val!='Feeds' && $val!='Home' && $val!='Dashboard'
1312 && $val!='Calendar' && $val!='Activities' && $val!='Reports') &&
1313 ($user->isDeveloperForModule($key))) {
1314 $workflow_admin_modules[$key] = $val;
1317 $_SESSION['get_workflow_admin_modules_for_user'] = $workflow_admin_modules;
1318 return ($workflow_admin_modules);
1321 // Check if user is admin for at least one module.
1322 function is_admin_for_any_module($user) {
1326 if($user->isAdmin()) {
1333 // Check if user is admin for a specific module.
1334 function is_admin_for_module($user,$module) {
1335 if (!isset($user)) {
1338 if ($user->isAdmin()) {
1346 * Check if user id belongs to a system admin.
1347 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1348 * All Rights Reserved.
1349 * Contributor(s): ______________________________________..
1351 function is_admin($user) {
1356 return $user->isAdmin();
1360 * Return the display name for a theme if it exists.
1361 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1362 * All Rights Reserved.
1363 * Contributor(s): ______________________________________..
1365 * @deprecated use SugarThemeRegistry::get($theme)->name instead
1367 function get_theme_display($theme)
1369 return SugarThemeRegistry::get($theme)->name;
1373 * Return an array of directory names.
1374 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1375 * All Rights Reserved.
1376 * Contributor(s): ______________________________________..
1378 * @deprecated use SugarThemeRegistry::availableThemes() instead.
1380 function get_themes()
1382 return SugarThemeRegistry::availableThemes();
1386 * THIS FUNCTION IS DEPRECATED AND SHOULD NOT BE USED; USE get_select_options_with_id()
1387 * Create HTML to display select options in a dropdown list. To be used inside
1388 * of a select statement in a form.
1389 * param $option_list - the array of strings to that contains the option list
1390 * param $selected - the string which contains the default value
1391 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1392 * All Rights Reserved.
1393 * Contributor(s): ______________________________________..
1395 function get_select_options ($option_list, $selected) {
1396 return get_select_options_with_id($option_list, $selected);
1400 * Create HTML to display select options in a dropdown list. To be used inside
1401 * of a select statement in a form. This method expects the option list to have keys and values. The keys are the ids. The values are the display strings.
1402 * param $option_list - the array of strings to that contains the option list
1403 * param $selected - the string which contains the default value
1404 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1405 * All Rights Reserved.
1406 * Contributor(s): ______________________________________..
1408 function get_select_options_with_id ($option_list, $selected_key) {
1409 return get_select_options_with_id_separate_key($option_list, $option_list, $selected_key);
1414 * Create HTML to display select options in a dropdown list. To be used inside
1415 * of a select statement in a form. This method expects the option list to have keys and values. The keys are the ids. The values are the display strings.
1416 * param $label_list - the array of strings to that contains the option list
1417 * param $key_list - the array of strings to that contains the values list
1418 * param $selected - the string which contains the default value
1419 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1420 * All Rights Reserved.
1421 * Contributor(s): ______________________________________..
1423 function get_select_options_with_id_separate_key ($label_list, $key_list, $selected_key, $massupdate=false) {
1424 global $app_strings;
1425 $select_options = "";
1427 //for setting null selection values to human readable --None--
1428 $pattern = "/'0?'></";
1429 $replacement = "''>".$app_strings['LBL_NONE']."<";
1431 if (empty($key_list)) $key_list = array();
1432 //create the type dropdown domain and set the selected value if $opp value already exists
1433 foreach ($key_list as $option_key=>$option_value) {
1435 $selected_string = '';
1436 // the system is evaluating $selected_key == 0 || '' to true. Be very careful when changing this. Test all cases.
1437 // The bug was only happening with one of the users in the drop down. It was being replaced by none.
1438 if (($option_key != '' && $selected_key == $option_key) || ($selected_key == '' && $option_key == '' && !$massupdate) || (is_array($selected_key) && in_array($option_key, $selected_key)))
1440 $selected_string = 'selected ';
1443 $html_value = $option_key;
1445 $select_options .= "\n<OPTION ".$selected_string."value='$html_value'>$label_list[$option_key]</OPTION>";
1447 $select_options = preg_replace($pattern, $replacement, $select_options);
1448 return $select_options;
1453 * Call this method instead of die().
1454 * Then we call the die method with the error message that is passed in.
1456 function sugar_die($error_message)
1460 die($error_message);
1465 * Create javascript to clear values of all elements in a form.
1466 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1467 * All Rights Reserved.
1468 * Contributor(s): ______________________________________..
1470 function get_clear_form_js () {
1471 $the_script = <<<EOQ
1472 <script type="text/javascript" language="JavaScript">
1473 function clear_form(form) {
1474 var newLoc = 'index.php?action=' + form.action.value + '&module=' + form.module.value + '&query=true&clear_query=true';
1475 if(typeof(form.advanced) != 'undefined'){
1476 newLoc += '&advanced=' + form.advanced.value;
1478 document.location.href= newLoc;
1487 * Create javascript to set the cursor focus to specific field in a form
1488 * when the screen is rendered. The field name is currently hardcoded into the
1490 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1491 * All Rights Reserved.
1492 * Contributor(s): ______________________________________..
1494 function get_set_focus_js () {
1495 //TODO Clint 5/20 - Make this function more generic so that it can take in the target form and field names as variables
1496 $the_script = <<<EOQ
1497 <script type="text/javascript" language="JavaScript">
1499 function set_focus() {
1500 if (document.forms.length > 0) {
1501 for (i = 0; i < document.forms.length; i++) {
1502 for (j = 0; j < document.forms[i].elements.length; j++) {
1503 var field = document.forms[i].elements[j];
1504 if ((field.type == "text" || field.type == "textarea" || field.type == "password") &&
1505 !field.disabled && (field.name == "first_name" || field.name == "name" || field.name == "user_name" || field.name=="document_name")) {
1507 if (field.type == "text") {
1524 * Very cool algorithm for sorting multi-dimensional arrays. Found at http://us2.php.net/manual/en/function.array-multisort.php
1525 * Syntax: $new_array = array_csort($array [, 'col1' [, SORT_FLAG [, SORT_FLAG]]]...);
1526 * Explanation: $array is the array you want to sort, 'col1' is the name of the column
1527 * you want to sort, SORT_FLAGS are : SORT_ASC, SORT_DESC, SORT_REGULAR, SORT_NUMERIC, SORT_STRING
1528 * you can repeat the 'col',FLAG,FLAG, as often you want, the highest prioritiy is given to
1529 * the first - so the array is sorted by the last given column first, then the one before ...
1530 * Example: $array = array_csort($array,'town','age',SORT_DESC,'name');
1531 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1532 * All Rights Reserved.
1533 * Contributor(s): ______________________________________..
1535 function array_csort() {
1536 $args = func_get_args();
1537 $marray = array_shift($args);
1540 $msortline = "return(array_multisort(";
1541 foreach ($args as $arg) {
1543 if (is_string($arg)) {
1544 foreach ($marray as $row) {
1545 $sortarr[$i][] = $row[$arg];
1548 $sortarr[$i] = $arg;
1550 $msortline .= "\$sortarr[".$i."],";
1552 $msortline .= "\$marray));";
1559 * Converts localized date format string to jscalendar format
1560 * Example: $array = array_csort($array,'town','age',SORT_DESC,'name');
1561 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1562 * All Rights Reserved.
1563 * Contributor(s): ______________________________________..
1565 function parse_calendardate($local_format) {
1566 preg_match('/\(?([^-]{1})[^-]*-([^-]{1})[^-]*-([^-]{1})[^-]*\)/', $local_format, $matches);
1567 $calendar_format = "%" . $matches[1] . "-%" . $matches[2] . "-%" . $matches[3];
1568 return str_replace(array("y", "ᅣ1�7", "a", "j"), array("Y", "Y", "Y", "d"), $calendar_format);
1575 function translate($string, $mod='', $selectedValue=''){
1576 //$test_start = microtime();
1577 //static $mod_strings_results = array();
1579 global $current_language;
1581 if(isset($_REQUEST['login_language'])){
1582 $current_language = ($_REQUEST['login_language'] == $current_language)? $current_language : $_REQUEST['login_language'];
1584 $mod_strings = return_module_language($current_language, $mod);
1587 global $mod_strings;
1591 global $app_strings, $app_list_strings;
1593 if(isset($mod_strings[$string]))
1594 $returnValue = $mod_strings[$string];
1595 else if(isset($app_strings[$string]))
1596 $returnValue = $app_strings[$string];
1597 else if(isset($app_list_strings[$string]))
1598 $returnValue = $app_list_strings[$string];
1599 else if(isset($app_list_strings['moduleList']) && isset($app_list_strings['moduleList'][$string]))
1600 $returnValue = $app_list_strings['moduleList'][$string];
1603 //$test_end = microtime();
1605 // $mod_strings_results[$mod] = microtime_diff($test_start,$test_end);
1607 // echo("translate results:");
1609 // $total_strings = 0;
1610 // foreach($mod_strings_results as $key=>$value)
1612 // echo("Module $key \t\t time $value \t\t<br>");
1613 // $total_time += $value;
1616 // echo("Total time: $total_time<br>");
1620 if(empty($returnValue)){
1624 if(is_array($returnValue) && ! empty($selectedValue) && isset($returnValue[$selectedValue]) ){
1625 return $returnValue[$selectedValue];
1628 return $returnValue;
1631 function unTranslateNum($num) {
1633 static $num_grp_sep;
1634 global $current_user, $sugar_config;
1636 if($dec_sep == null) {
1637 $user_dec_sep = $current_user->getPreference('dec_sep');
1638 $dec_sep = (empty($user_dec_sep) ? $sugar_config['default_decimal_seperator'] : $user_dec_sep);
1640 if($num_grp_sep == null) {
1641 $user_num_grp_sep = $current_user->getPreference('num_grp_sep');
1642 $num_grp_sep = (empty($user_num_grp_sep) ? $sugar_config['default_number_grouping_seperator'] : $user_num_grp_sep);
1645 $num = preg_replace("'" . preg_quote($num_grp_sep) . "'", '', $num);
1646 $num = preg_replace("'" . preg_quote($dec_sep) . "'", '.', $num);
1651 function add_http($url) {
1652 if(!preg_match("@://@i", $url)) {
1654 if(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') {
1658 return "{$scheme}://{$url}";
1665 * returns a default array of XSS tags to clean
1668 function getDefaultXssTags() {
1670 "applet" => "applet",
1675 "frameset" => "frameset",
1676 "iframe" => "iframe",
1677 "import" => "\?import",
1680 "object" => "object",
1681 "script" => "script",
1685 $ret = base64_encode(serialize($tmp));
1691 * Remove potential xss vectors from strings
1692 * @param string str String to search for XSS attack vectors
1693 * @param bool cleanImg Flag to allow <img> tags to survive - only used by InboundEmail for inline images.
1696 function remove_xss($str, $cleanImg=true)
1698 $potentials = clean_xss($str, $cleanImg);
1699 if(is_array($potentials) && !empty($potentials)) {
1700 foreach($potentials as $bad) {
1701 $str = str_replace($bad, "", $str);
1708 * Detects typical XSS attack patterns
1709 * @param string str String to search for XSS attack vectors
1710 * @param bool cleanImg Flag to allow <img> tags to survive - only used by InboundEmail for inline images.
1711 * @return array Array of matches, empty on clean string
1713 function clean_xss($str, $cleanImg=true) {
1714 global $sugar_config;
1716 if(empty($sugar_config['email_xss']))
1717 $sugar_config['email_xss'] = getDefaultXssTags();
1719 $arr = unserialize(base64_decode($sugar_config['email_xss']));
1722 foreach($arr as $v) {
1723 if(!empty($regex)) {
1729 $tag_regex = "#<({$regex})[^>]*>?#sim";
1731 // cn: bug 13079 - "on\w" matched too many non-events (cONTact, strONG, etc.)
1732 $jsEvents = "onblur|onfocus|oncontextmenu|onresize|onscroll|onunload|ondblclick|onclick|";
1733 $jsEvents .= "onmouseup|onmouseover|onmousedown|onmouseenter|onmouseleave|onmousemove|onload|onchange|";
1734 $jsEvents .= "onreset|onselect|onsubmit|onkeydown|onkeypress|onkeyup|onabort|onerror|ondragdrop";
1736 $attribute_regex = "#<.+({$jsEvents})[^=>]*=[^>]*>#sim";
1737 $javascript_regex = '@<[^/>][^>]+(expression\(|j\W*a\W*v\W*a|v\W*b\W*s\W*c\W*r|&#|/\*|\*/)[^>]*>@sim';
1738 $imgsrc_regex = '#<[^>]+src[^=]*=([^>]*?http(s)?://[^>]*)>#sim';
1739 $css_url = '#url\(.*\.\w+\)#';
1742 $str = str_replace("\t", "", $str);
1744 $matches = array_merge(
1745 xss_check_pattern($tag_regex, $str),
1746 xss_check_pattern($javascript_regex, $str)
1750 $jsMatches = xss_check_pattern($attribute_regex, $str);
1751 if(!empty($jsMatches)){
1752 preg_match_all($attribute_regex, $str, $newMatches, PREG_PATTERN_ORDER);
1753 if(!empty($newMatches[0][0])){
1754 $matches2 = array_merge(xss_check_pattern("#({$jsEvents})#sim", $newMatches[0][0]));
1755 $matches = array_merge($matches, $matches2);
1760 $matches = array_merge($matches,
1761 xss_check_pattern($imgsrc_regex, $str)
1765 // cn: bug 13498 - custom white-list of allowed domains that vet remote images
1766 preg_match_all($css_url, $str, $cssUrlMatches, PREG_PATTERN_ORDER);
1768 if(isset($sugar_config['security_trusted_domains']) && !empty($sugar_config['security_trusted_domains']) && is_array($sugar_config['security_trusted_domains'])) {
1769 if(is_array($cssUrlMatches) && count($cssUrlMatches) > 0) {
1770 // normalize whitelist
1771 foreach($sugar_config['security_trusted_domains'] as $k => $v) {
1772 $sugar_config['security_trusted_domains'][$k] = strtolower($v);
1775 foreach($cssUrlMatches[0] as $match) {
1776 $domain = strtolower(substr(strstr($match, "://"), 3));
1777 $baseUrl = substr($domain, 0, strpos($domain, "/"));
1779 if(!in_array($baseUrl, $sugar_config['security_trusted_domains'])) {
1780 $matches[] = $match;
1785 $matches = array_merge($matches, $cssUrlMatches[0]);
1792 * Helper function used by clean_xss() to parse for known-bad vectors
1793 * @param string pattern Regex pattern to use
1794 * @param string str String to parse for badness
1797 function xss_check_pattern($pattern, $str) {
1798 preg_match_all($pattern, $str, $matches, PREG_PATTERN_ORDER);
1803 * Designed to take a string passed in the URL as a parameter and clean all "bad" data from it
1805 * @param string $str
1806 * @param string $filter which corresponds to a regular expression to use; choices are:
1807 * "STANDARD" ( default )
1817 * @param boolean $dieOnBadData true (default) if you want to die if bad data if found, false if not
1819 function clean_string($str, $filter = "STANDARD", $dieOnBadData = true)
1821 global $sugar_config;
1824 "STANDARD" => '#[^A-Z0-9\-_\.\@]#i',
1825 "STANDARDSPACE" => '#[^A-Z0-9\-_\.\@\ ]#i',
1826 "FILE" => '#[^A-Z0-9\-_\.]#i',
1827 "NUMBER" => '#[^0-9\-]#i',
1828 "SQL_COLUMN_LIST" => '#[^A-Z0-9\(\),_\.]#i',
1829 "PATH_NO_URL" => '#://#i',
1830 "SAFED_GET" => '#[^A-Z0-9\@\=\&\?\.\/\-_~]#i', /* range of allowed characters in a GET string */
1831 "UNIFIED_SEARCH" => "#[\\x00]#", /* cn: bug 3356 & 9236 - MBCS search strings */
1832 "AUTO_INCREMENT" => '#[^0-9\-,\ ]#i',
1833 "ALPHANUM" => '#[^A-Z0-9\-]#i',
1836 if (preg_match($filters[$filter], $str)) {
1837 if (isset($GLOBALS['log']) && is_object($GLOBALS['log'])) {
1838 $GLOBALS['log']->fatal("SECURITY: bad data passed in; string: {$str}");
1840 if ( $dieOnBadData ) {
1841 die("Bad data passed in; <a href=\"{$sugar_config['site_url']}\">Return to Home</a>");
1850 function clean_special_arguments() {
1851 if(isset($_SERVER['PHP_SELF'])) {
1852 if (!empty($_SERVER['PHP_SELF'])) clean_string($_SERVER['PHP_SELF'], 'SAFED_GET');
1854 if (!empty($_REQUEST) && !empty($_REQUEST['login_theme'])) clean_string($_REQUEST['login_theme'], "STANDARD");
1855 if (!empty($_REQUEST) && !empty($_REQUEST['login_module'])) clean_string($_REQUEST['login_module'], "STANDARD");
1856 if (!empty($_REQUEST) && !empty($_REQUEST['login_action'])) clean_string($_REQUEST['login_action'], "STANDARD");
1857 if (!empty($_REQUEST) && !empty($_REQUEST['ck_login_theme_20'])) clean_string($_REQUEST['ck_login_theme_20'], "STANDARD");
1858 if (!empty($_SESSION) && !empty($_SESSION['authenticated_user_theme'])) clean_string($_SESSION['authenticated_user_theme'], "STANDARD");
1859 if (!empty($_REQUEST) && !empty($_REQUEST['module_name'])) clean_string($_REQUEST['module_name'], "STANDARD");
1860 if (!empty($_REQUEST) && !empty($_REQUEST['module'])) clean_string($_REQUEST['module'], "STANDARD");
1861 if (!empty($_POST) && !empty($_POST['parent_type'])) clean_string($_POST['parent_type'], "STANDARD");
1862 if (!empty($_REQUEST) && !empty($_REQUEST['mod_lang'])) clean_string($_REQUEST['mod_lang'], "STANDARD");
1863 if (!empty($_SESSION) && !empty($_SESSION['authenticated_user_language'])) clean_string($_SESSION['authenticated_user_language'], "STANDARD");
1864 if (!empty($_SESSION) && !empty($_SESSION['dyn_layout_file'])) clean_string($_SESSION['dyn_layout_file'], "PATH_NO_URL");
1865 if (!empty($_GET) && !empty($_GET['from'])) clean_string($_GET['from']);
1866 if (!empty($_GET) && !empty($_GET['gmto'])) clean_string($_GET['gmto'], "NUMBER");
1867 if (!empty($_GET) && !empty($_GET['case_number'])) clean_string($_GET['case_number'], "AUTO_INCREMENT");
1868 if (!empty($_GET) && !empty($_GET['bug_number'])) clean_string($_GET['bug_number'], "AUTO_INCREMENT");
1869 if (!empty($_GET) && !empty($_GET['quote_num'])) clean_string($_GET['quote_num'], "AUTO_INCREMENT");
1870 clean_superglobals('stamp', 'ALPHANUM'); // for vcr controls
1871 clean_superglobals('offset', 'ALPHANUM');
1872 clean_superglobals('return_action');
1873 clean_superglobals('return_module');
1878 * cleans the given key in superglobals $_GET, $_POST, $_REQUEST
1880 function clean_superglobals($key, $filter = 'STANDARD') {
1881 if(isset($_GET[$key])) clean_string($_GET[$key], $filter);
1882 if(isset($_POST[$key])) clean_string($_POST[$key], $filter);
1883 if(isset($_REQUEST[$key])) clean_string($_REQUEST[$key], $filter);
1886 function set_superglobals($key, $val){
1888 $_POST[$key] = $val;
1889 $_REQUEST[$key] = $val;
1892 // Works in conjunction with clean_string() to defeat SQL injection, file inclusion attacks, and XSS
1893 function clean_incoming_data() {
1894 global $sugar_config;
1896 if (get_magic_quotes_gpc() == 1) {
1897 $req = array_map("preprocess_param", $_REQUEST);
1898 $post = array_map("preprocess_param", $_POST);
1899 $get = array_map("preprocess_param", $_GET);
1902 $req = array_map("securexss", $_REQUEST);
1903 $post = array_map("securexss", $_POST);
1904 $get = array_map("securexss", $_GET);
1907 // PHP cannot stomp out superglobals reliably
1908 foreach($post as $k => $v) { $_POST[$k] = $v; }
1909 foreach($get as $k => $v) { $_GET[$k] = $v; }
1910 foreach($req as $k => $v) {
1912 //ensure the keys are safe as well
1915 // Any additional variables that need to be cleaned should be added here
1916 if (isset($_REQUEST['login_theme'])) clean_string($_REQUEST['login_theme']);
1917 if (isset($_REQUEST['login_module'])) clean_string($_REQUEST['login_module']);
1918 if (isset($_REQUEST['login_action'])) clean_string($_REQUEST['login_action']);
1919 if (isset($_REQUEST['login_language'])) clean_string($_REQUEST['login_language']);
1920 if (isset($_REQUEST['action'])) clean_string($_REQUEST['action']);
1921 if (isset($_REQUEST['module'])) clean_string($_REQUEST['module']);
1922 if (isset($_REQUEST['record'])) clean_string($_REQUEST['record'], 'STANDARDSPACE');
1923 if (isset($_SESSION['authenticated_user_theme'])) clean_string($_SESSION['authenticated_user_theme']);
1924 if (isset($_SESSION['authenticated_user_language'])) clean_string($_SESSION['authenticated_user_language']);
1925 if (isset($_REQUEST['language'])) clean_string($_REQUEST['language']);
1926 if (isset($sugar_config['default_theme'])) clean_string($sugar_config['default_theme']);
1927 if (isset($_REQUEST['offset'])) clean_string($_REQUEST['offset']);
1928 if (isset($_REQUEST['stamp'])) clean_string($_REQUEST['stamp']);
1930 if(isset($_REQUEST['lvso'])){
1931 set_superglobals('lvso', (strtolower($_REQUEST['lvso']) === 'desc')?'desc':'asc');
1933 // Clean "offset" and "order_by" parameters in URL
1934 foreach ($_REQUEST as $key => $val) {
1935 if (str_end($key, "_offset")) {
1936 clean_string($_REQUEST[$key], "ALPHANUM"); // keep this ALPHANUM for disable_count_query
1937 set_superglobals($key, $_REQUEST[$key]);
1939 elseif (str_end($key, "_ORDER_BY")) {
1940 clean_string($_REQUEST[$key], "SQL_COLUMN_LIST");
1941 set_superglobals($key, $_REQUEST[$key]);
1949 // Returns TRUE if $str begins with $begin
1950 function str_begin($str, $begin) {
1951 return (substr($str, 0, strlen($begin)) == $begin);
1954 // Returns TRUE if $str ends with $end
1955 function str_end($str, $end) {
1956 return (substr($str, strlen($str) - strlen($end)) == $end);
1959 function securexss($value) {
1960 if(is_array($value)){
1962 foreach($value as $key=>$val){
1963 $new[$key] = securexss($val);
1967 static $xss_cleanup= array('"' =>'"', "'" => ''' , '<' =>'<' , '>'=>'>');
1968 $value = preg_replace(array('/javascript:/i', '/\0/'), array('java script:', ''), $value);
1969 $value = preg_replace('/javascript:/i', 'java script:', $value);
1970 return str_replace(array_keys($xss_cleanup), array_values($xss_cleanup), $value);
1973 function securexsskey($value, $die=true){
1974 global $sugar_config;
1976 preg_match("/[\'\"\<\>]/", $value, $matches);
1977 if(!empty($matches)){
1979 die("Bad data passed in; <a href=\"{$sugar_config['site_url']}\">Return to Home</a>");
1981 unset($_REQUEST[$value]);
1982 unset($_POST[$value]);
1983 unset($_GET[$value]);
1988 function preprocess_param($value){
1989 if(is_string($value)){
1990 if(get_magic_quotes_gpc() == 1){
1991 $value = stripslashes($value);
1994 $value = securexss($value);
2003 function set_register_value($category, $name, $value){
2004 return sugar_cache_put("{$category}:{$name}", $value);
2007 function get_register_value($category,$name){
2008 return sugar_cache_retrieve("{$category}:{$name}");
2011 // this function cleans id's when being imported
2012 function convert_id($string)
2014 return preg_replace_callback( '|[^A-Za-z0-9\-]|',
2016 // single quotes are essential here,
2017 // or alternative escape all $ as \$
2019 'return ord($matches[0]);'
2024 * @deprecated use SugarTheme::getImage()
2026 function get_image($image,$other_attributes,$width="",$height="")
2028 return SugarThemeRegistry::current()->getImage(basename($image),
2030 empty($width) ? null : $width,
2031 empty($height) ? null : $height
2035 * @deprecated use SugarTheme::getImageURL()
2037 function getImagePath($image_name)
2039 return SugarThemeRegistry::current()->getImageURL($image_name);
2042 function getWebPath($relative_path){
2043 //if it has a :// then it isn't a relative path
2044 if(substr_count($relative_path, '://') > 0) return $relative_path;
2045 if(defined('TEMPLATE_URL'))$relative_path = SugarTemplateUtilities::getWebPath($relative_path);
2046 return $relative_path;
2049 function getJSPath($relative_path, $additional_attrs=''){
2050 if(defined('TEMPLATE_URL'))$relative_path = SugarTemplateUtilities::getWebPath($relative_path);
2051 if(empty($GLOBALS['sugar_config']['js_custom_version']))$GLOBALS['sugar_config']['js_custom_version'] = 1;
2052 $js_version_key = isset($GLOBALS['js_version_key'])?$GLOBALS['js_version_key']:'';
2053 $path = $relative_path . '?s=' . $js_version_key . '&c=' . $GLOBALS['sugar_config']['js_custom_version'] ;
2054 if ( inDeveloperMode() ) $path .= '&developerMode='.mt_rand();
2055 if(!empty($additonal_attrs)) $path .= '&' . $additional_attrs;
2059 function getSWFPath($relative_path, $additional_params=''){
2060 $path = $relative_path;
2061 if (!empty($additional_params)){
2062 $path .= '?' . $additional_params;
2064 if (defined('TEMPLATE_URL')){
2065 $path = TEMPLATE_URL . '/' . $path;
2074 function getSQLDate($date_str)
2076 if (preg_match('/^(\d{1,2})-(\d{1,2})-(\d{4})$/',$date_str,$match))
2078 if ( strlen($match[2]) == 1)
2080 $match[2] = "0".$match[2];
2082 if ( strlen($match[1]) == 1)
2084 $match[1] = "0".$match[1];
2086 return "{$match[3]}-{$match[1]}-{$match[2]}";
2088 else if (preg_match('/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/',$date_str,$match))
2090 if ( strlen($match[2]) == 1)
2092 $match[2] = "0".$match[2];
2094 if ( strlen($match[1]) == 1)
2096 $match[1] = "0".$match[1];
2098 return "{$match[3]}-{$match[1]}-{$match[2]}";
2106 function clone_history(&$db, $from_id,$to_id, $to_type)
2111 require_once('include/upload_file.php');
2112 $tables = array('calls'=>'Call', 'meetings'=>'Meeting', 'notes'=>'Note', 'tasks'=>'Task');
2114 $location=array('Email'=>"modules/Emails/Email.php",
2115 'Call'=>"modules/Calls/Call.php",
2116 'Meeting'=>"modules/Meetings/Meeting.php",
2117 'Note'=>"modules/Notes/Note.php",
2118 'Tasks'=>"modules/Tasks/Task.php",
2122 foreach($tables as $table=>$bean_class)
2125 if (!class_exists($bean_class))
2127 require_once($location[$bean_class]);
2130 $bProcessingNotes=false;
2131 if ($table=='notes')
2133 $bProcessingNotes=true;
2135 $query = "SELECT id FROM $table WHERE parent_id='$from_id'";
2136 $results = $db->query($query);
2137 while($row = $db->fetchByAssoc($results))
2139 //retrieve existing record.
2140 $bean= new $bean_class();
2141 $bean->retrieve($row['id']);
2142 //process for new instance.
2143 if ($bProcessingNotes)
2145 $old_note_id=$row['id'];
2146 $old_filename=$bean->filename;
2149 $bean->parent_id=$to_id;
2150 $bean->parent_type=$to_type;
2151 if ($to_type=='Contacts' and in_array('contact_id',$bean->column_fields))
2153 $bean->contact_id=$to_id;
2155 $bean->update_date_modified = false;
2156 $bean->update_modified_by = false;
2157 if(isset($bean->date_modified))
2158 $bean->date_modified = $timedate->to_db($bean->date_modified);
2159 if(isset($bean->date_entered))
2160 $bean->date_entered = $timedate->to_db($bean->date_entered);
2162 $new_id=$bean->save();
2164 //duplicate the file now. for notes.
2165 if ($bProcessingNotes && !empty($old_filename))
2167 UploadFile::duplicate_file($old_note_id,$new_id,$old_filename);
2169 //reset the values needed for attachment duplication.
2176 function values_to_keys($array)
2178 $new_array = array();
2179 if(!is_array($array))
2183 foreach($array as $arr){
2184 $new_array[$arr] = $arr;
2189 function clone_relationship(&$db, $tables = array(), $from_column, $from_id, $to_id)
2191 foreach($tables as $table)
2194 if ($table == 'emails_beans') {
2195 $query = "SELECT * FROM $table WHERE $from_column='$from_id' and bean_module='Leads'";
2197 $query = "SELECT * FROM $table WHERE $from_column='$from_id'";
2199 $results = $db->query($query);
2200 while($row = $db->fetchByAssoc($results))
2202 $query = "INSERT INTO $table ";
2205 $row[$from_column] = $to_id;
2206 $row['id'] = create_guid();
2207 if ($table=='emails_beans') {
2208 $row['bean_module'] =='Contacts';
2211 foreach($row as $name=>$value)
2217 $values .= "'$value'";
2220 $names .= ', '. $name;
2221 $values .= ", '$value'";
2224 $query .= "($names) VALUES ($values)";
2230 function get_unlinked_email_query($type, $bean) {
2231 global $current_user;
2233 $return_array['select']='SELECT emails.id ';
2234 $return_array['from']='FROM emails ';
2235 $return_array['where']="";
2236 $return_array['join'] = " JOIN (select distinct email_id from emails_email_addr_rel eear
2238 join email_addr_bean_rel eabr on eabr.bean_id ='$bean->id' and eabr.bean_module = '$bean->module_dir' and
2239 eabr.email_address_id = eear.email_address_id and eabr.deleted=0
2240 where eear.deleted=0 and eear.email_id not in
2241 (select eb.email_id from emails_beans eb where eb.bean_module ='$bean->module_dir' and eb.bean_id = '$bean->id')
2242 ) derivedemails on derivedemails.email_id = emails.id";
2243 $return_array['join_tables'][0] = '';
2245 if (isset($type) and isset($type['return_as_array']) and $type['return_as_array']==true) {
2246 return $return_array;
2249 return $return_array['select'] . $return_array['from'] . $return_array['where'];
2253 * Check to see if the number is empty or non-zero
2257 function number_empty($value)
2259 return empty($value) && $value != '0';
2262 function get_bean_select_array($add_blank=true, $bean_name, $display_columns, $where='', $order_by='', $blank_is_none=false)
2265 require_once($beanFiles[$bean_name]);
2266 $focus = new $bean_name();
2267 $user_array = array();
2268 $user_array = get_register_value('select_array',$bean_name. $display_columns. $where . $order_by);
2272 $db = DBManagerFactory::getInstance();
2273 $temp_result = Array();
2274 $query = "SELECT {$focus->table_name}.id, {$display_columns} as display from {$focus->table_name} ";
2278 $query .= $where." AND ";
2281 $query .= " {$focus->table_name}.deleted=0";
2283 if ( $order_by != '')
2285 $query .= " order by {$focus->table_name}.{$order_by}";
2288 $GLOBALS['log']->debug("get_user_array query: $query");
2289 $result = $db->query($query, true, "Error filling in user array: ");
2291 if ($add_blank==true){
2292 // Add in a blank row
2293 if($blank_is_none == true) { // set 'blank row' to "--None--"
2294 global $app_strings;
2295 $temp_result[''] = $app_strings['LBL_NONE'];
2297 $temp_result[''] = '';
2301 // Get the id and the name.
2302 while($row = $db->fetchByAssoc($result))
2304 $temp_result[$row['id']] = $row['display'];
2307 $user_array = $temp_result;
2308 set_register_value('select_array',$bean_name. $display_columns. $where . $order_by,$temp_result);
2317 * @param unknown_type $listArray
2319 // function parse_list_modules
2320 // searches a list for items in a user's allowed tabs and returns an array that removes unallowed tabs from list
2321 function parse_list_modules(&$listArray)
2323 global $modListHeader;
2324 $returnArray = array();
2326 foreach($listArray as $optionName => $optionVal)
2328 if(array_key_exists($optionName, $modListHeader))
2330 $returnArray[$optionName] = $optionVal;
2333 // special case for projects
2334 if(array_key_exists('Project', $modListHeader))
2336 $returnArray['ProjectTask'] = $listArray['ProjectTask'];
2339 $acldenied = ACLController::disabledModuleList($listArray,false);
2340 foreach($acldenied as $denied){
2341 unset($returnArray[$denied]);
2343 asort($returnArray);
2345 return $returnArray;
2348 function display_notice($msg = false){
2349 global $error_notice;
2350 //no error notice - lets just display the error to the user
2351 if(!isset($error_notice)){
2352 echo '<br>'.$msg . '<br>';
2354 $error_notice .= $msg . '<br>';
2358 /* checks if it is a number that atleast has the plus at the beggining
2360 function skype_formatted($number){
2361 //kbrill - BUG #15375
2362 if(isset($_REQUEST['action']) && $_REQUEST['action']=="Popup") {
2365 return substr($number, 0, 1) == '+' || substr($number, 0, 2) == '00' || substr($number, 0, 3) == '011';
2367 // return substr($number, 0, 1) == '+' || substr($number, 0, 2) == '00' || substr($number, 0, 2) == '011';
2370 function format_skype($number) {
2371 return preg_replace('/[^\+0-9]/','',$number);
2374 function insert_charset_header() {
2375 header('Content-Type: text/html; charset=UTF-8');
2378 function getCurrentURL()
2381 if(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on')
2386 $href.= "//".$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME'].'?'.$_SERVER['QUERY_STRING'];
2390 function javascript_escape($str) {
2393 for($i = 0; $i < strlen($str); $i++) {
2395 if(ord(substr($str, $i, 1))==10){
2397 }elseif(ord(substr($str, $i, 1))==13){
2401 $new_str .= $str{$i};
2405 $new_str = str_replace("'", "\\'", $new_str);
2410 function js_escape($str, $keep=true){
2411 $str = html_entity_decode(str_replace("\\", "", $str), ENT_QUOTES);
2414 $str = javascript_escape($str);
2417 $str = str_replace("'", " ", $str);
2418 $str = str_replace('"', " ", $str);
2423 //end function js_escape
2426 function br2nl($str) {
2427 $regex = "#<[^>]+br.+?>#i";
2428 preg_match_all($regex, $str, $matches);
2430 foreach($matches[0] as $match) {
2431 $str = str_replace($match, "<br>", $str);
2434 $brs = array('<br>','<br/>', '<br />');
2435 $str = str_replace("\r\n", "\n", $str); // make from windows-returns, *nix-returns
2436 $str = str_replace("\n\r", "\n", $str); // make from windows-returns, *nix-returns
2437 $str = str_replace("\r", "\n", $str); // make from windows-returns, *nix-returns
2438 $str = str_ireplace($brs, "\n", $str); // to retrieve it
2444 * Private helper function for displaying the contents of a given variable.
2445 * This function is only intended to be used for SugarCRM internal development.
2446 * The ppd stands for Pre Print Die.
2448 function _ppd($mixed)
2454 * Private helper function for displaying the contents of a given variable in
2455 * the Logger. This function is only intended to be used for SugarCRM internal
2456 * development. The pp stands for Pre Print.
2457 * @param $mixed var to print_r()
2458 * @param $die boolean end script flow
2459 * @param $displayStackTrace also show stack trace
2461 function _ppl($mixed, $die=false, $displayStackTrace=false, $loglevel="fatal") {
2465 * private helper function to quickly show the major, direct, field attributes of a given bean.
2466 * The ppf stands for Pre[formatted] Print Focus [object]
2467 * @param object bean The focus bean
2469 function _ppf($bean, $die=false) {
2475 * Private helper function for displaying the contents of a given variable.
2476 * This function is only intended to be used for SugarCRM internal development.
2477 * The pp stands for Pre Print.
2479 function _pp($mixed)
2484 * Private helper function for displaying the contents of a given variable.
2485 * This function is only intended to be used for SugarCRM internal development.
2486 * The pp stands for Pre Print.
2488 function _pstack_trace($mixed=NULL)
2493 * Private helper function for displaying the contents of a given variable.
2494 * This function is only intended to be used for SugarCRM internal development.
2495 * The pp stands for Pre Print Trace.
2497 function _ppt($mixed, $textOnly=false)
2502 * Private helper function for displaying the contents of a given variable.
2503 * This function is only intended to be used for SugarCRM internal development.
2504 * The pp stands for Pre Print Trace Die.
2506 function _pptd($mixed)
2511 * Private helper function for decoding javascript UTF8
2512 * This function is only intended to be used for SugarCRM internal development.
2514 function decodeJavascriptUTF8($str) {
2518 * Will check if a given PHP version string is supported (tested on this ver),
2519 * unsupported (results unknown), or invalid (something will break on this
2520 * ver). Do not pass in any pararameter to default to a check against the
2521 * current environment's PHP version.
2523 * @return 1 implies supported, 0 implies unsupported, -1 implies invalid
2525 function check_php_version($sys_php_version = '') {
2526 $sys_php_version = empty($sys_php_version) ? constant('PHP_VERSION') : $sys_php_version;
2527 // versions below $min_considered_php_version considered invalid by default,
2528 // versions equal to or above this ver will be considered depending
2529 // on the rules that follow
2530 $min_considered_php_version = '5.2.1';
2532 // only the supported versions,
2533 // should be mutually exclusive with $invalid_php_versions
2534 $supported_php_versions = array (
2535 '5.2.1', '5.2.2', '5.2.3', '5.2.4', '5.2.5', '5.2.6', '5.2.8', '5.3.0'
2537 //Find out what Database the system is using.
2538 global $sugar_config;
2540 if (isset($_REQUEST['setup_db_type'])) {
2541 $dbType = $_REQUEST['setup_db_type'];
2542 } else if (isset ($sugar_config['dbconfig']) && isset ($sugar_config['dbconfig']['db_type'])) {
2543 $dbType = $sugar_config['dbconfig']['db_type'];
2546 // invalid versions above the $min_considered_php_version,
2547 // should be mutually exclusive with $supported_php_versions
2549 // SugarCRM prohibits install on PHP 5.2.7 on all platforms
2550 $invalid_php_versions = array('5.2.7');
2552 // default unsupported
2555 // versions below $min_considered_php_version are invalid
2556 if(1 == version_compare($sys_php_version, $min_considered_php_version, '<')) {
2560 // supported version check overrides default unsupported
2561 foreach($supported_php_versions as $ver) {
2562 if(1 == version_compare($sys_php_version, $ver, 'eq') || strpos($sys_php_version,$ver) !== false) {
2568 // invalid version check overrides default unsupported
2569 foreach($invalid_php_versions as $ver) {
2570 if(1 == version_compare($sys_php_version, $ver, 'eq') && strpos($sys_php_version,$ver) !== false) {
2576 //allow a redhat distro to install, regardless of version. We are assuming the redhat naming convention is followed
2577 //and the php version contains 'rh' characters
2578 if(strpos($sys_php_version, 'rh') !== false) {
2586 * Will check if a given IIS version string is supported (tested on this ver),
2587 * unsupported (results unknown), or invalid (something will break on this
2590 * @return 1 implies supported, 0 implies unsupported, -1 implies invalid
2592 function check_iis_version($sys_iis_version = '') {
2594 $server_software = $_SERVER["SERVER_SOFTWARE"];
2596 if(strpos($server_software,'Microsoft-IIS') !== false && preg_match_all("/^.*\/(\d+\.?\d*)$/", $server_software, $out))
2597 $iis_version = $out[1][0];
2599 $sys_iis_version = empty($sys_iis_version) ? $iis_version : $sys_iis_version;
2601 // versions below $min_considered_iis_version considered invalid by default,
2602 // versions equal to or above this ver will be considered depending
2603 // on the rules that follow
2604 $min_considered_iis_version = '6.0';
2606 // only the supported versions,
2607 // should be mutually exclusive with $invalid_iis_versions
2608 $supported_iis_versions = array ('6.0', '7.0',);
2609 $unsupported_iis_versions = array();
2610 $invalid_iis_versions = array('5.0',);
2612 // default unsupported
2615 // versions below $min_considered_iis_version are invalid
2616 if(1 == version_compare($sys_iis_version, $min_considered_iis_version, '<')) {
2620 // supported version check overrides default unsupported
2621 foreach($supported_iis_versions as $ver) {
2622 if(1 == version_compare($sys_iis_version, $ver, 'eq') || strpos($sys_iis_version,$ver) !== false) {
2628 // unsupported version check overrides default unsupported
2629 foreach($unsupported_iis_versions as $ver) {
2630 if(1 == version_compare($sys_iis_version, $ver, 'eq') && strpos($sys_iis_version,$ver) !== false) {
2636 // invalid version check overrides default unsupported
2637 foreach($invalid_iis_versions as $ver) {
2638 if(1 == version_compare($sys_iis_version, $ver, 'eq') && strpos($sys_iis_version,$ver) !== false) {
2647 function pre_login_check(){
2648 global $action, $login_error;
2649 if(!empty($action)&& $action == 'Login'){
2651 if(!empty($login_error)){
2652 $login_error = htmlentities($login_error);
2653 $login_error = str_replace(array("<pre>","</pre>","\r\n", "\n"), "<br>", $login_error);
2654 $_SESSION['login_error'] = $login_error;
2656 function set_focus() {}
2657 if(document.getElementById("post_error")) {
2658 document.getElementById("post_error").innerHTML="'. $login_error. '";
2659 document.getElementById("cant_login").value=1;
2660 document.getElementById("login_button").disabled = true;
2661 document.getElementById("user_name").disabled = true;
2662 //document.getElementById("user_password").disabled = true;
2671 function sugar_cleanup($exit = false) {
2672 static $called = false;
2675 set_include_path(realpath(dirname(__FILE__) . '/..') . PATH_SEPARATOR . get_include_path());
2676 chdir(realpath(dirname(__FILE__) . '/..'));
2677 global $sugar_config;
2678 require_once('include/utils/LogicHook.php');
2679 LogicHook::initialize();
2680 $GLOBALS['logic_hook']->call_custom_logic('', 'server_round_trip');
2682 //added this check to avoid errors during install.
2683 if (empty($sugar_config['dbconfig'])) {
2684 if ($exit) exit; else return;
2687 if (!class_exists('Tracker', true)) {
2688 require_once 'modules/Trackers/Tracker.php';
2691 // Now write the cached tracker_queries
2692 if(!empty($GLOBALS['savePreferencesToDB']) && $GLOBALS['savePreferencesToDB']) {
2693 if ( isset($GLOBALS['current_user']) && $GLOBALS['current_user'] instanceOf User )
2694 $GLOBALS['current_user']->savePreferencesToDB();
2697 //check to see if this is not an ajax call AND the user preference error flag is set
2699 (isset($_SESSION['USER_PREFRENCE_ERRORS']) && $_SESSION['USER_PREFRENCE_ERRORS'])
2700 && ($_REQUEST['action']!='modulelistmenu' && $_REQUEST['action']!='DynamicAction')
2701 && (empty($_REQUEST['to_pdf']) || !$_REQUEST['to_pdf'] )
2702 && (empty($_REQUEST['sugar_body_only']) || !$_REQUEST['sugar_body_only'] )
2705 global $app_strings;
2706 //this is not an ajax call and the user preference error flag is set, so reset the flag and print js to flash message
2707 $err_mess = $app_strings['ERROR_USER_PREFS'];
2708 $_SESSION['USER_PREFRENCE_ERRORS'] = false;
2711 ajaxStatus.flashStatus('$err_mess',7000);
2717 if(class_exists('DBManagerFactory')) {
2718 $db = DBManagerFactory::getInstance();
2726 register_shutdown_function('sugar_cleanup');
2730 check_logic_hook - checks to see if your custom logic is in the logic file
2731 if not, it will add it. If the file isn't built yet, it will create the file
2734 function check_logic_hook_file($module_name, $event, $action_array){
2735 require_once('include/utils/logic_utils.php');
2738 if(file_exists("custom/modules/$module_name/logic_hooks.php")){
2740 $hook_array = get_hook_array($module_name);
2742 if(check_existing_element($hook_array, $event, $action_array)==true){
2743 //the hook at hand is present, so do nothing
2748 if(!empty($hook_array[$event]))
2750 $logic_count = count($hook_array[$event]);
2753 if($action_array[0]==""){
2754 $action_array[0] = $logic_count + 1;
2756 $hook_array[$event][] = $action_array;
2759 //end if the file exists already
2762 if($action_array[0]==""){
2763 $action_array[0] = 1;
2765 $hook_array = array();
2766 $hook_array[$event][] = $action_array;
2767 //end if else file exists already
2769 if($add_logic == true){
2771 //reorder array by element[0]
2772 //$hook_array = reorder_array($hook_array, $event);
2773 //!!!Finish this above TODO
2775 $new_contents = replace_or_add_logic_type($hook_array);
2776 write_logic_file($module_name, $new_contents);
2778 //end if add_element is true
2781 //end function check_logic_hook_file
2784 function remove_logic_hook($module_name, $event, $action_array) {
2785 require_once('include/utils/logic_utils.php');
2788 if(file_exists("custom/modules/".$module_name."/logic_hooks.php")){
2789 // The file exists, let's make sure the hook is there
2790 $hook_array = get_hook_array($module_name);
2792 if(check_existing_element($hook_array, $event, $action_array)==true){
2793 // The hook is there, time to take it out.
2795 foreach ( $hook_array[$event] as $i => $hook ) {
2796 // We don't do a full comparison below just in case the filename changes
2797 if ( $hook[0] == $action_array[0]
2798 && $hook[1] == $action_array[1]
2799 && $hook[3] == $action_array[3]
2800 && $hook[4] == $action_array[4] ) {
2801 unset($hook_array[$event][$i]);
2805 $new_contents = replace_or_add_logic_type($hook_array);
2806 write_logic_file($module_name, $new_contents);
2812 function display_stack_trace($textOnly=false){
2814 $stack = debug_backtrace();
2816 echo "\n\n display_stack_trace caller, file: " . $stack[0]['file']. ' line#: ' .$stack[0]['line'];
2824 foreach($stack as $item) {
2830 if(isset($item['file']))
2831 $file = $item['file'];
2832 if(isset($item['class']))
2833 $class = $item['class'];
2834 if(isset($item['line']))
2835 $line = $item['line'];
2836 if(isset($item['function']))
2837 $function = $item['function'];
2841 $out .= '<font color="black"><b>';
2847 $out .= '</b></font><font color="blue">';
2850 $out .= "[L:{$line}]";
2853 $out .= '</font><font color="red">';
2856 $out .= "({$class}:{$function})";
2859 $out .= '</font><br>';
2871 function StackTraceErrorHandler($errno, $errstr, $errfile,$errline, $errcontext) {
2872 $error_msg = " $errstr occured in <b>$errfile</b> on line $errline [" . date("Y-m-d H:i:s") . ']';
2873 $halt_script = true;
2875 case 2048: return; //depricated we have lots of these ignore them
2878 if ( error_reporting() & E_NOTICE ) {
2879 $halt_script = false;
2885 case E_USER_WARNING:
2886 case E_COMPILE_WARNING:
2887 case E_CORE_WARNING:
2890 $halt_script = false;
2895 case E_COMPILE_ERROR:
2899 $type = "Fatal Error";
2904 $type = "Parse Error";
2908 //don't know what it is might not be so bad
2909 $halt_script = false;
2910 $type = "Unknown Error ($errno)";
2913 $error_msg = '<b>'.$type.'</b>:' . $error_msg;
2915 display_stack_trace();
2925 if(isset($sugar_config['stack_trace_errors']) && $sugar_config['stack_trace_errors']){
2927 set_error_handler('StackTraceErrorHandler');
2929 function get_sub_cookies($name){
2931 if(isset($_COOKIE[$name])){
2932 $subs = explode('#', $_COOKIE[$name]);
2933 foreach($subs as $cookie){
2934 if(!empty($cookie)){
2935 $cookie = explode('=', $cookie);
2937 $cookies[$cookie[0]] = $cookie[1];
2946 function mark_delete_components($sub_object_array, $run_second_level=false, $sub_sub_array=""){
2948 if(!empty($sub_object_array)){
2950 foreach($sub_object_array as $sub_object){
2952 //run_second level is set to true if you need to remove sub-sub components
2953 if($run_second_level==true){
2955 mark_delete_components($sub_object->get_linked_beans($sub_sub_array['rel_field'],$sub_sub_array['rel_module']));
2957 //end if run_second_level is true
2959 $sub_object->mark_deleted($sub_object->id);
2960 //end foreach sub component
2962 //end if this is not empty
2965 //end function mark_delete_components
2969 * For translating the php.ini memory values into bytes. e.g. input value of '8M' will return 8388608.
2971 function return_bytes($val)
2974 $last = strtolower($val{strlen($val)-1});
2978 // The 'G' modifier is available since PHP 5.1.0
2991 * Adds the href HTML tags around any URL in the $string
2993 function url2html($string) {
2995 $return_string = preg_replace('/(\w+:\/\/)(\S+)/', ' <a href="\\1\\2" target="_new" style="font-weight: normal;">\\1\\2</a>', $string);
2996 return $return_string;
2998 // End customization by Julian
3001 * tries to determine whether the Host machine is a Windows machine
3003 function is_windows() {
3004 static $is_windows = null;
3005 if (!isset($is_windows)) {
3006 $is_windows = strtoupper(substr(PHP_OS, 0, 3)) == 'WIN';
3012 * equivalent for windows filesystem for PHP's is_writable()
3013 * @param string file Full path to the file/dir
3014 * @return bool true if writable
3016 function is_writable_windows($file) {
3017 if($file{strlen($file)-1}=='/') {
3018 return is_writable_windows($file.uniqid(mt_rand()).'.tmp');
3021 // the assumption here is that Windows has an inherited permissions scheme
3022 // any file that is a descendant of an unwritable directory will inherit
3023 // that property and will trigger a failure below.
3028 $file = str_replace("/", '\\', $file);
3030 if(file_exists($file)) {
3031 if (!($f = @sugar_fopen($file, 'r+')))
3037 if(!($f = @sugar_fopen($file, 'w')))
3046 * best guesses Timezone based on webserver's TZ settings
3048 function lookupTimezone($userOffset = 0)
3050 return TimeDate::guessTimezone($userOffset);
3053 function convert_module_to_singular($module_array){
3056 foreach($module_array as $key => $value){
3057 if(!empty($beanList[$value])) $module_array[$key] = $beanList[$value];
3059 if($value=="Cases") {
3060 $module_array[$key] = "Case";
3062 if($key=="projecttask"){
3063 $module_array['ProjectTask'] = "Project Task";
3064 unset($module_array[$key]);
3068 return $module_array;
3070 //end function convert_module_to_singular
3074 * Given the bean_name which may be plural or singular return the singular
3075 * bean_name. This is important when you need to include files.
3077 function get_singular_bean_name($bean_name){
3078 global $beanFiles, $beanList;
3079 if(array_key_exists($bean_name, $beanList)){
3080 return $beanList[$bean_name];
3087 function get_label($label_tag, $temp_module_strings){
3088 global $app_strings;
3089 if(!empty($temp_module_strings[$label_tag])){
3091 $label_name = $temp_module_strings[$label_tag];
3093 if(!empty($app_strings[$label_tag])){
3094 $label_name = $app_strings[$label_tag];
3096 $label_name = $label_tag;
3101 //end function get_label
3105 function search_filter_rel_info(& $focus, $tar_rel_module, $relationship_name){
3107 $rel_list = array();
3109 foreach($focus->relationship_fields as $rel_key => $rel_value){
3110 if($rel_value == $relationship_name){
3111 $temp_bean = get_module_info($tar_rel_module);
3112 // echo $focus->$rel_key;
3113 $temp_bean->retrieve($focus->$rel_key);
3114 if($temp_bean->id!=""){
3116 $rel_list[] = $temp_bean;
3122 foreach($focus->field_defs as $field_name => $field_def){
3123 //Check if the relationship_name matches a "relate" field
3124 if(!empty($field_def['type']) && $field_def['type'] == 'relate'
3125 && !empty($field_def['id_name']) && !empty($focus->field_defs[$field_def['id_name']])
3126 && !empty($focus->field_defs[$field_def['id_name']]['relationship'])
3127 && $focus->field_defs[$field_def['id_name']]['relationship'] == $relationship_name)
3129 $temp_bean = get_module_info($tar_rel_module);
3130 // echo $focus->$field_def['id_name'];
3131 $temp_bean->retrieve($focus->$field_def['id_name']);
3132 if($temp_bean->id!=""){
3134 $rel_list[] = $temp_bean;
3137 //Check if the relationship_name matches a "link" in a relate field
3138 } else if(!empty($rel_value['link']) && !empty($rel_value['id_name']) && $rel_value['link'] == $relationship_name){
3139 $temp_bean = get_module_info($tar_rel_module);
3140 // echo $focus->$rel_value['id_name'];
3141 $temp_bean->retrieve($focus->$rel_value['id_name']);
3142 if($temp_bean->id!=""){
3144 $rel_list[] = $temp_bean;
3150 // special case for unlisted parent-type relationships
3151 if($focus->parent_type == $tar_rel_module && !empty($focus->parent_id)) {
3152 $temp_bean = get_module_info($tar_rel_module);
3153 $temp_bean->retrieve($focus->parent_id);
3154 if($temp_bean->id!=""){
3155 $rel_list[] = $temp_bean;
3162 //end function search_filter_rel_info
3165 function get_module_info($module_name){
3169 //Get dictionary and focus data for module
3170 $vardef_name = $beanList[$module_name];
3172 if($vardef_name=="aCase"){
3173 $class_name = "Case";
3175 $class_name = $vardef_name;
3178 if(!file_exists('modules/'. $module_name . '/'.$class_name.'.php')){
3182 include_once('modules/'. $module_name . '/'.$class_name.'.php');
3184 $module_bean = new $vardef_name();
3185 return $module_bean;
3186 //end function get_module_table
3190 * In order to have one place to obtain the proper object name. aCase for example causes issues throughout the application.
3192 * @param string $moduleName
3194 function get_valid_bean_name($module_name){
3197 $vardef_name = $beanList[$module_name];
3198 if($vardef_name=="aCase"){
3199 $bean_name = "Case";
3201 $bean_name = $vardef_name;
3208 function checkAuthUserStatus(){
3215 * This function returns an array of phpinfo() results that can be parsed and
3216 * used to figure out what version we run, what modules are compiled in, etc.
3217 * @param $level int info level constant (1,2,4,8...64);
3218 * @return $returnInfo array array of info about the PHP environment
3219 * @author original by "code at adspeed dot com" Fron php.net
3220 * @author customized for Sugar by Chris N.
3222 function getPhpInfo($level=-1) {
3223 /** Name (constant) Value Description
3224 INFO_GENERAL 1 The configuration line, php.ini location, build date, Web Server, System and more.
3225 INFO_CREDITS 2 PHP Credits. See also phpcredits().
3226 INFO_CONFIGURATION 4 Current Local and Master values for PHP directives. See also ini_get().
3227 INFO_MODULES 8 Loaded modules and their respective settings. See also get_loaded_extensions().
3228 INFO_ENVIRONMENT 16 Environment Variable information that's also available in $_ENV.
3229 INFO_VARIABLES 32 Shows all predefined variables from EGPCS (Environment, GET, POST, Cookie, Server).
3230 INFO_LICENSE 64 PHP License information. See also the license FAQ.
3231 INFO_ALL -1 Shows all of the above. This is the default value.
3235 $phpinfo = ob_get_contents();
3238 $phpinfo = strip_tags($phpinfo,'<h1><h2><th><td>');
3239 $phpinfo = preg_replace('/<th[^>]*>([^<]+)<\/th>/',"<info>\\1</info>",$phpinfo);
3240 $phpinfo = preg_replace('/<td[^>]*>([^<]+)<\/td>/',"<info>\\1</info>",$phpinfo);
3241 $parsedInfo = preg_split('/(<h.?>[^<]+<\/h.>)/', $phpinfo, -1, PREG_SPLIT_DELIM_CAPTURE);
3244 $returnInfo = array();
3246 if(preg_match('/<h1 class\=\"p\">PHP Version ([^<]+)<\/h1>/', $phpinfo, $version)) {
3247 $returnInfo['PHP Version'] = $version[1];
3251 for ($i=1; $i<count($parsedInfo); $i++) {
3252 if (preg_match('/<h.>([^<]+)<\/h.>/', $parsedInfo[$i], $match)) {
3253 $vName = trim($match[1]);
3254 $parsedInfo2 = explode("\n",$parsedInfo[$i+1]);
3256 foreach ($parsedInfo2 AS $vOne) {
3257 $vPat = '<info>([^<]+)<\/info>';
3258 $vPat3 = "/$vPat\s*$vPat\s*$vPat/";
3259 $vPat2 = "/$vPat\s*$vPat/";
3261 if (preg_match($vPat3,$vOne,$match)) { // 3cols
3262 $returnInfo[$vName][trim($match[1])] = array(trim($match[2]),trim($match[3]));
3263 } elseif (preg_match($vPat2,$vOne,$match)) { // 2cols
3264 $returnInfo[$vName][trim($match[1])] = trim($match[2]);
3276 * This function will take a string that has tokens like {0}, {1} and will replace
3277 * those tokens with the args provided
3278 * @param $format string to format
3279 * @param $args args to replace
3280 * @return $result a formatted string
3282 function string_format($format, $args){
3284 for($i = 0; $i < count($args); $i++){
3285 $result = str_replace('{'.$i.'}', $args[$i], $result);
3291 * Generate a string for displaying a unique identifier that is composed
3292 * of a system_id and number. This is use to allow us to generate quote
3293 * numbers using a DB auto-increment key from offline clients and still
3294 * have the number be unique (since it is modified by the system_id.
3296 * @param $num of bean
3297 * @param $system_id from system
3298 * @return $result a formatted string
3300 function format_number_display($num, $system_id){
3301 global $sugar_config;
3302 if(isset($num) && !empty($num)){
3303 $num=unformat_number($num);
3304 if(isset($system_id) && $system_id == 1){
3305 return sprintf("%d", $num);
3308 return sprintf("%d-%d", $num, $system_id);
3312 function checkLoginUserStatus(){
3316 * This function will take a number and system_id and format
3317 * @param $url URL containing host to append port
3318 * @param $port the port number - if '' is passed, no change to url
3319 * @return $resulturl the new URL with the port appended to the host
3321 function appendPortToHost($url, $port)
3325 // if no port, don't change the url
3328 $split = explode("/", $url);
3329 //check if it starts with http, in case they didn't include that in url
3330 if(str_begin($url, 'http'))
3332 //third index ($split[2]) will be the host
3333 $split[2] .= ":".$port;
3335 else // otherwise assumed to start with host name
3337 //first index ($split[0]) will be the host
3338 $split[0] .= ":".$port;
3341 $resulturl = implode("/", $split);
3348 * Singleton to return JSON object
3349 * @return JSON object
3351 function getJSONobj() {
3352 static $json = null;
3354 require_once('include/JSON.php');
3355 $json = new JSON(JSON_LOOSE_TYPE);
3360 require_once('include/utils/db_utils.php');
3361 //check to see if custom utils exists
3362 if(file_exists('custom/include/custom_utils.php')){
3363 include_once('custom/include/custom_utils.php');
3368 * Set default php.ini settings for entry points
3370 function setPhpIniSettings() {
3372 // Bug 37579 - Comment out force enabling zlib.output_compression, since it can cause problems on certain hosts
3374 if(function_exists('gzclose') && headers_sent() == false) {
3375 ini_set('zlib.output_compression', 1);
3379 //nsingh: breaks zip/unzip functionality. Commenting out 4/23/08
3381 /*if(function_exists('mb_strlen')) {
3382 ini_set('mbstring.func_overload', 7);
3383 ini_set('mbstring.internal_encoding', 'UTF-8');
3387 // http://us3.php.net/manual/en/ref.pcre.php#ini.pcre.backtrack-limit
3388 // starting with 5.2.0, backtrack_limit breaks JSON decoding
3389 $backtrack_limit = ini_get('pcre.backtrack_limit');
3390 if(!empty($backtrack_limit)) {
3391 ini_set('pcre.backtrack_limit', '-1');
3395 if(ini_get("mssql.charset")) {
3396 ini_set('mssql.charset', "UTF-8");
3401 * like array_merge() but will handle array elements that are themselves arrays;
3402 * PHP's version just overwrites the element with the new one.
3404 * @internal Note that this function deviates from the internal array_merge()
3405 * functions in that it does does not treat numeric keys differently
3406 * than string keys. Additionally, it deviates from
3407 * array_merge_recursive() by not creating an array when like values
3410 * @param array gimp the array whose values will be overloaded
3411 * @param array dom the array whose values will pwn the gimp's
3412 * @return array beaten gimp
3414 function sugarArrayMerge($gimp, $dom) {
3415 if(is_array($gimp) && is_array($dom)) {
3416 foreach($dom as $domKey => $domVal) {
3417 if(array_key_exists($domKey, $gimp)) {
3418 if(is_array($domVal)) {
3420 foreach ( $domVal as $domArrKey => $domArrVal )
3421 $tempArr[$domArrKey] = $domArrVal;
3422 foreach ( $gimp[$domKey] as $gimpArrKey => $gimpArrVal )
3423 if ( !array_key_exists($gimpArrKey, $tempArr) )
3424 $tempArr[$gimpArrKey] = $gimpArrVal;
3425 $gimp[$domKey] = $tempArr;
3427 $gimp[$domKey] = $domVal;
3430 $gimp[$domKey] = $domVal;
3434 // if the passed value for gimp isn't an array, then return the $dom
3435 elseif(is_array($dom))
3442 * Similiar to sugarArrayMerge except arrays of N depth are merged.
3444 * @param array gimp the array whose values will be overloaded
3445 * @param array dom the array whose values will pwn the gimp's
3446 * @return array beaten gimp
3448 function sugarArrayMergeRecursive($gimp, $dom) {
3449 if(is_array($gimp) && is_array($dom)) {
3450 foreach($dom as $domKey => $domVal) {
3451 if(array_key_exists($domKey, $gimp)) {
3452 if(is_array($domVal) && is_array($gimp[$domKey])) {
3453 $gimp[$domKey] = sugarArrayMergeRecursive($gimp[$domKey], $domVal);
3455 $gimp[$domKey] = $domVal;
3458 $gimp[$domKey] = $domVal;
3462 // if the passed value for gimp isn't an array, then return the $dom
3463 elseif(is_array($dom))
3470 * finds the correctly working versions of PHP-JSON
3471 * @return bool True if NOT found or WRONG version
3473 function returnPhpJsonStatus() {
3474 if(function_exists('json_encode')) {
3475 $phpInfo = getPhpInfo(8);
3476 return version_compare($phpInfo['json']['json version'], '1.1.1', '<');
3478 return true; // not found
3483 * getTrackerSubstring
3485 * Returns a [number]-char or less string for the Tracker to display in the header
3486 * based on the tracker_max_display_length setting in config.php. If not set,
3487 * or invalid length, then defaults to 15 for COM editions, 30 for others.
3489 * @param string name field for a given Object
3490 * @return string [number]-char formatted string if length of string exceeds the max allowed
3492 function getTrackerSubstring($name) {
3493 static $max_tracker_item_length;
3496 $name = html_entity_decode($name, ENT_QUOTES, 'UTF-8');
3497 $strlen = function_exists('mb_strlen') ? mb_strlen($name) : strlen($name);
3499 global $sugar_config;
3501 if(!isset($max_tracker_item_length)) {
3502 if(isset($sugar_config['tracker_max_display_length'])) {
3503 $max_tracker_item_length = (is_int($sugar_config['tracker_max_display_length']) && $sugar_config['tracker_max_display_length'] > 0 && $sugar_config['tracker_max_display_length'] < 50) ? $sugar_config['tracker_max_display_length'] : 15;
3505 $max_tracker_item_length = 15;
3509 if($strlen > $max_tracker_item_length) {
3510 $chopped = function_exists('mb_substr') ? mb_substr($name, 0, $max_tracker_item_length, "UTF-8") : substr($name, 0, $max_tracker_item_length, "UTF-8");
3517 function generate_search_where ($field_list=array(),$values=array(),&$bean,$add_custom_fields=false,$module='') {
3518 $where_clauses= array();
3520 $table_name=$bean->object_name;
3521 foreach ($field_list[$module] as $field=>$parms) {
3522 if(isset($values[$field]) && $values[$field] != "") {
3524 if (!empty($parms['operator'])) {
3525 $operator=$parms['operator'];
3527 if (is_array($values[$field])) {
3530 foreach ($values[$field] as $key => $val) {
3531 if ($val != ' ' and $val != '') {
3532 if (!empty($field_value)) {
3535 $field_value .= "'".$GLOBALS['db']->quote($val)."'";
3539 $field_value=$GLOBALS['db']->quote($values[$field]);
3541 //set db_fields array.
3542 if (!isset($parms['db_field']) ) {
3543 $parms['db_field'] = array($field);
3545 if (isset($parms['my_items']) and $parms['my_items'] == true) {
3546 global $current_user;
3547 $field_value = $GLOBALS['db']->quote($current_user->id);
3553 if ($field_value != '') {
3555 foreach ($parms['db_field'] as $db_field) {
3556 if (strstr($db_field,'.')===false) {
3557 $db_field=$bean->table_name.".".$db_field;
3559 if ($GLOBALS['db']->dbType=='oci8' && isset($parms['query_type']) && $parms['query_type']=='case_insensitive') {
3560 $db_field='upper('.$db_field.")";
3561 $field_value=strtoupper($field_value);
3565 if (!empty($where)) {
3568 switch (strtolower($operator)) {
3570 $where .= $db_field . " like '".$field_value.$like_char."'";
3573 $where .= $db_field . " in (".$field_value.')';
3576 $where .= $db_field . " = '".$field_value ."'";
3581 if (!empty($where)) {
3583 array_push($where_clauses, '( '.$where.' )');
3585 array_push($where_clauses, $where);
3590 if ($add_custom_fields) {
3591 require_once('modules/DynamicFields/DynamicField.php');
3592 $bean->setupCustomFields($module);
3593 $bean->custom_fields->setWhereClauses($where_clauses);
3595 return $where_clauses;
3598 function add_quotes($str) {
3603 * This function will rebuild the config file
3604 * @param $sugar_config
3605 * @param $sugar_version
3606 * @return bool true if successful
3608 function rebuildConfigFile($sugar_config, $sugar_version) {
3609 // add defaults to missing values of in-memory sugar_config
3610 $sugar_config = sugarArrayMerge(get_sugar_config_defaults(), $sugar_config );
3611 // need to override version with default no matter what
3612 $sugar_config['sugar_version'] = $sugar_version;
3614 ksort( $sugar_config );
3616 if( write_array_to_file( "sugar_config", $sugar_config, "config.php" ) ){
3625 * getJavascriptSiteURL
3626 * This function returns a URL for the client javascript calls to access
3627 * the site. It uses $_SERVER['HTTP_REFERER'] in the event that Proxy servers
3628 * are used to access the site. Thus, the hostname in the URL returned may
3629 * not always match that of $sugar_config['site_url']. Basically, the
3630 * assumption is that however the user accessed the website is how they
3631 * will continue to with subsequent javascript requests. If the variable
3632 * $_SERVER['HTTP_REFERER'] is not found then we default to old algorithm.
3633 * @return $site_url The url used to refer to the website
3635 function getJavascriptSiteURL() {
3636 global $sugar_config;
3637 if(!empty($_SERVER['HTTP_REFERER'])) {
3638 $url = parse_url($_SERVER['HTTP_REFERER']);
3639 $replacement_url = $url['scheme']."://".$url['host'];
3640 if(!empty($url['port']))
3641 $replacement_url .= ':'.$url['port'];
3642 $site_url = preg_replace('/^http[s]?\:\/\/[^\/]+/',$replacement_url,$sugar_config['site_url']);
3644 $site_url = preg_replace('/^http(s)?\:\/\/[^\/]+/',"http$1://".$_SERVER['HTTP_HOST'],$sugar_config['site_url']);
3645 if(!empty($_SERVER['SERVER_PORT']) &&$_SERVER['SERVER_PORT'] == '443') {
3646 $site_url = preg_replace('/^http\:/','https:',$site_url);
3649 $GLOBALS['log']->debug("getJavascriptSiteURL(), site_url=". $site_url);
3653 // works nicely with array_map() -- can be used to wrap single quotes around each element in an array
3654 function add_squotes($str) {
3655 return "'" . $str . "'";
3659 // recursive function to count the number of levels within an array
3660 function array_depth($array, $depth_count=-1, $depth_array=array()){
3662 if (is_array($array)){
3663 foreach ($array as $key => $value){
3664 $depth_array[] = array_depth($value, $depth_count);
3668 return $depth_count;
3670 foreach ($depth_array as $value){
3671 $depth_count = $value > $depth_count ? $value : $depth_count;
3673 return $depth_count;
3677 * Creates a new Group User
3678 * @param string $name Name of Group User
3679 * @return string GUID of new Group User
3681 function createGroupUser($name) {
3684 $group = new User();
3685 $group->user_name = $name;
3686 $group->last_name = $name;
3687 $group->is_group = 1;
3688 $group->deleted = 0;
3689 $group->status = 'Active'; // cn: bug 6711
3690 $group->setPreference('timezone', TimeDate::userTimezone());
3697 * Helper function to locate an icon file given only a name
3698 * Searches through the various paths for the file
3699 * @param string iconFileName The filename of the icon
3700 * @return string Relative pathname of the located icon, or '' if not found
3703 function _getIcon($iconFileName)
3705 $iconPath = SugarThemeRegistry::current()->getImageURL("icon_{$iconFileName}.gif");
3706 //First try un-ucfirst-ing the icon name
3707 if ( empty($iconPath) )
3708 $iconPath = SugarThemeRegistry::current()->getImageURL(
3709 "icon_" . strtolower(substr($iconFileName,0,1)).substr($iconFileName,1) . ".gif");
3710 //Next try removing the icon prefix
3711 if ( empty($iconPath) )
3712 $iconPath = SugarThemeRegistry::current()->getImageURL("{$iconFileName}.gif");
3717 * Function to grab the correct icon image for Studio
3718 * @param string $iconFileName Name of the icon file
3719 * @param string $altfilename Name of a fallback icon file (displayed if the imagefilename doesn't exist)
3720 * @param string $width Width of image
3721 * @param string $height Height of image
3722 * @param string $align Alignment of image
3723 * @return string $string <img> tag with corresponding image
3726 function getStudioIcon($iconFileName='', $altFileName='', $width='48', $height='48', $align='baseline' )
3728 global $app_strings, $theme;
3730 $iconPath = _getIcon($iconFileName);
3731 if(empty($iconPath)){
3732 $iconPath = _getIcon($altFileName);
3733 if (empty($iconPath))
3735 return $app_strings['LBL_NO_IMAGE'];
3738 return '<img border="0" src="'.$iconPath.'" width="'.$width.'" height="'.$height.'" align="'.$align.'">';
3742 * Function to grab the correct icon image for Dashlets Dialog
3743 * @param string $filename Location of the icon file
3744 * @param string $module Name of the module to fall back onto if file does not exist
3745 * @param string $width Width of image
3746 * @param string $height Height of image
3747 * @param string $align Alignment of image
3748 * @return string $string <img> tag with corresponding image
3751 function get_dashlets_dialog_icon($module='', $width='32', $height='32', $align='absmiddle'){
3752 global $app_strings, $theme;
3753 $icon_path = _getIcon($module . "_32");
3754 if (empty($icon_path))
3756 $icon_path = _getIcon($module);
3758 if(empty($icon_path)){
3759 $icon = $app_strings['LBL_NO_IMAGE'];
3762 $icon = '<img border="0" src="'.$icon_path.'" width="'.$width.'" height="'.$height.'" align="'.$align.'">';
3767 // works nicely to change UTF8 strings that are html entities - good for PDF conversions
3768 function html_entity_decode_utf8($string)
3771 // replace numeric entities
3772 //php will have issues with numbers with leading zeros, so do not include them in what we send to code2utf.
3773 $string = preg_replace('~�*([0-9a-f]+);~ei', 'code2utf(hexdec("\\1"))', $string);
3774 $string = preg_replace('~�*([0-9]+);~e', 'code2utf(\\1)', $string);
3775 // replace literal entities
3776 if (!isset($trans_tbl))
3778 $trans_tbl = array();
3779 foreach (get_html_translation_table(HTML_ENTITIES) as $val=>$key)
3780 $trans_tbl[$key] = utf8_encode($val);
3782 return strtr($string, $trans_tbl);
3785 // Returns the utf string corresponding to the unicode value
3786 function code2utf($num)
3788 if ($num < 128) return chr($num);
3789 if ($num < 2048) return chr(($num >> 6) + 192) . chr(($num & 63) + 128);
3790 if ($num < 65536) return chr(($num >> 12) + 224) . chr((($num >> 6) & 63) + 128) . chr(($num & 63) + 128);
3791 if ($num < 2097152) return chr(($num >> 18) + 240) . chr((($num >> 12) & 63) + 128) . chr((($num >> 6) & 63) + 128) . chr(($num & 63) + 128);
3795 function str_split_php4($string, $length = 1) {
3796 $string_length = strlen($string);
3799 if ($length > $string_length) {
3800 // use the string_length as the string is shorter than the length
3801 $length = $string_length;
3803 for ($cursor = 0; $cursor < $string_length; $cursor = $cursor + $length) {
3804 $return[] = substr($string, $cursor, $length);
3809 if (version_compare(phpversion(), '5.0.0', '<')) {
3810 function str_split($string, $length = 1) {
3811 return str_split_php4($string, $length);
3816 * Invoked when connected to mssql. checks if we have freetds version of mssql library.
3817 * the response is put into a global variable.
3819 function is_freetds() {
3822 if (isset($GLOBALS['mssql_library_version'])) {
3823 if ($GLOBALS['mssql_library_version']=='freetds') {
3831 $info=ob_get_contents();
3834 if (strpos($info,'FreeTDS') !== false) {
3835 $GLOBALS['mssql_library_version']='freetds';
3838 $GLOBALS['mssql_library_version']='regular';
3846 * stripos - Find position of first occurrence of a case-insensitive string
3848 * The function is being defined for systems with PHP version < 5.
3851 if (!function_exists("stripos")){
3852 function stripos($haystack,$needle,$offset=0){
3853 return strpos(strtolower($haystack),strtolower($needle),$offset);
3858 * Chart dashlet helper function that returns the correct CSS file, dependent on the current theme.
3860 * @todo this won't work completely right until we impliment css compression and combination
3861 * for now, we'll just include the last css file found.
3863 * @return chart.css file to use
3865 function chartStyle()
3867 return SugarThemeRegistry::current()->getCSSURL('chart.css');
3871 * Chart dashlet helper functions that returns the correct XML color file for charts,
3872 * dependent on the current theme.
3874 * @return sugarColors.xml to use
3876 function chartColors()
3878 if (SugarThemeRegistry::current()->getCSSURL('sugarColors.xml')=='')
3879 return SugarThemeRegistry::current()->getImageURL('sugarColors.xml');
3880 return SugarThemeRegistry::current()->getCSSURL('sugarColors.xml');
3882 /* End Chart Dashlet helper functions */
3885 * This function is designed to set up the php enviroment
3886 * for AJAX requests.
3889 function ajaxInit() {
3890 ini_set('display_errors', 'false');
3894 * Returns an absolute path from the given path, determining if it is relative or absolute
3896 * @param string $path
3899 function getAbsolutePath(
3901 $currentServer = false
3904 $path = trim($path);
3906 // try to match absolute paths like \\server\share, /directory or c:\
3907 if ( ( substr($path,0,2) == '\\\\' )
3908 || ( $path[0] == '/' )
3909 || preg_match('/^[A-z]:/i',$path)
3913 return getcwd().'/'.$path;
3917 * Returns the bean object of the given module
3919 * @deprecated use SugarModule::loadBean() instead
3920 * @param string $module
3927 return SugarModule::get($module)->loadBean();
3932 * Returns true if the application is being accessed on a touch screen interface ( like an iPad )
3934 function isTouchScreen()
3936 $ua = empty($_SERVER['HTTP_USER_AGENT']) ? "undefined" : strtolower($_SERVER['HTTP_USER_AGENT']);
3938 // first check if we have forced use of the touch enhanced interface
3939 if ( isset($_COOKIE['touchscreen']) && $_COOKIE['touchscreen'] == '1' ) {
3943 // next check if we should use the touch interface with our device
3944 if ( strpos($ua, 'ipad') !== false ) {
3952 * Returns the shortcut keys to access the shortcut links. Shortcut
3953 * keys vary depending on browser versions and operating systems.
3954 * @return String value of the shortcut keys
3956 function get_alt_hot_key() {
3958 if ( isset($_SERVER['HTTP_USER_AGENT']) )
3959 $ua = strtolower($_SERVER['HTTP_USER_AGENT']);
3960 $isMac = strpos($ua, 'mac') !== false;
3961 $isLinux = strpos($ua, 'linux') !== false;
3963 if(!$isMac && !$isLinux && strpos($ua, 'mozilla') !== false) {
3964 if(preg_match('/firefox\/(\d)?\./', $ua, $matches)) {
3965 return $matches[1] < 2 ? 'Alt+' : 'Alt+Shift+';
3968 return $isMac ? 'Ctrl+' : 'Alt+';
3971 function can_start_session(){
3972 if(!empty($_GET['PHPSESSID'])) {
3975 $session_id = session_id();
3976 return empty($session_id) ? true : false;
3979 function load_link_class($properties){
3981 if(!empty($properties['link_class']) && !empty($properties['link_file'])){
3982 require_once($properties['link_file']);
3983 $class = $properties['link_class'];
3989 function inDeveloperMode()
3991 return isset($GLOBALS['sugar_config']['developerMode']) && $GLOBALS['sugar_config']['developerMode'];
3995 * Filter the protocol list for inbound email accounts.
3997 * @param array $protocol
3999 function filterInboundEmailPopSelection($protocol)
4001 if ( !isset($GLOBALS['sugar_config']['allow_pop_inbound']) || ! $GLOBALS['sugar_config']['allow_pop_inbound'] )
4003 if( isset($protocol['pop3']) )
4004 unset($protocol['pop3']);
4007 $protocol['pop3'] = 'POP3';
4013 * The function is used because currently we are not supporting mbstring.func_overload
4014 * For some user using mssql without FreeTDS, they may store multibyte charaters in varchar using latin_general collation. It cannot store so many mutilbyte characters, so we need to use strlen.
4015 * The varchar in MySQL, Orcale, and nvarchar in FreeTDS, we can store $length mutilbyte charaters in it. we need mb_substr to keep more info.
4016 * @returns the substred strings.
4018 function sugar_substr($string, $length, $charset='UTF-8') {
4019 if($GLOBALS['db']->dbType == 'mssql' && empty($GLOBALS['db']->isFreeTDS)) {
4020 if(strlen($string) > $length) {
4021 $string = trim(substr(trim($string),0,$length));
4025 if(mb_strlen($string,$charset) > $length) {
4026 $string = trim(mb_substr(trim($string),0,$length,$charset));
4033 * The function is used because on FastCGI enviroment, the ucfirst(Chinese Characters) will produce bad charcters.
4034 * This will work even without setting the mbstring.*encoding
4036 function sugar_ucfirst($string, $charset='UTF-8') {
4037 return mb_strtoupper(mb_substr($string, 0, 1, $charset), $charset) . mb_substr($string, 1, mb_strlen($string), $charset);
4044 function unencodeMultienum($string) {
4045 if (is_array($string))
4049 if (substr($string, 0 ,1) == "^" && substr($string, -1) == "^") {
4050 $string = substr(substr($string, 1), 0, strlen($string) -2);
4053 return explode('^,^', $string);
4056 function encodeMultienumValue($arr) {
4057 if (!is_array($arr))
4063 $string = "^" . implode('^,^', $arr) . "^";
4069 * create_export_query is used for export and massupdate
4070 * We haven't handle the these fields: $field['type'] == 'relate' && isset($field['link']
4071 * This function will correct the where clause and output necessary join condition for them
4072 * @param $module: the module name
4073 * @param $searchFields: searchFields which is got after $searchForm->populateFromArray()
4074 * @param $where: where clauses
4075 * @return $ret_array['where']: corrected where clause
4076 * @return $ret_array['join']: extra join condition
4078 function create_export_query_relate_link_patch($module, $searchFields, $where){
4079 if(file_exists('modules/'.$module.'/SearchForm.html')){
4080 $ret_array['where'] = $where;
4083 $seed = loadBean($module);
4084 foreach($seed->field_defs as $name=>$field)
4087 if( $field['type'] == 'relate' && isset($field['link']) && !empty($searchFields[$name]['value']) ){
4088 $seed->load_relationship($field['link']);
4090 if(empty($join_type))
4092 $params['join_type'] = ' LEFT JOIN ';
4096 $params['join_type'] = $join_type;
4098 if(isset($data['join_name']))
4100 $params['join_table_alias'] = $field['join_name'];
4104 $params['join_table_alias'] = 'join_'.$field['name'];
4107 if(isset($data['join_link_name']))
4109 $params['join_table_link_alias'] = $field['join_link_name'];
4113 $params['join_table_link_alias'] = 'join_link_'.$field['name'];
4115 $join = $seed->$field['link']->getJoin($params, true);
4116 $join_table_alias = 'join_'.$field['name'];
4117 if(isset($field['db_concat_fields'])){
4118 $db_field = db_concat($join_table_alias, $field['db_concat_fields']);
4119 $where = preg_replace('/'.$field['name'].'/', $db_field, $where);
4121 $where = preg_replace('/(^|[\s(])' . $field['name'] . '/', '${1}' . $join_table_alias . '.'.$field['rname'], $where);
4125 $ret_array = array('where'=>$where, 'join'=>$join['join']);
4130 * We need to clear all the js cache files, including the js language files in serval places in MB. So I extract them into a util function here.
4131 * @Depends on QuickRepairAndRebuild.php
4132 * @Relate bug 30642 ,23177
4134 function clearAllJsAndJsLangFilesWithoutOutput(){
4135 global $current_language , $mod_strings;
4136 $MBmodStrings = $mod_strings;
4137 $mod_strings = return_module_language ( $current_language, 'Administration' ) ;
4138 include_once ('modules/Administration/QuickRepairAndRebuild.php') ;
4139 $repair = new RepairAndClear();
4140 $repair->module_list = array();
4141 $repair->show_output = false;
4142 $repair->clearJsLangFiles();
4143 $repair->clearJsFiles();
4144 $mod_strings = $MBmodStrings;
4148 * This function will allow you to get a variable value from query string
4150 function getVariableFromQueryString($variable, $string){
4152 $number = preg_match("/{$variable}=([a-zA-Z0-9_-]+)[&]?/", $string, $matches);
4162 * should_hide_iframes
4163 * This is a helper method to determine whether or not to show iframes (My Sites) related
4164 * information in the application.
4166 * @return boolean flag indicating whether or not iframes module should be hidden
4168 function should_hide_iframes() {
4169 //Remove the MySites module
4170 if(file_exists('modules/iFrames/iFrame.php')) {
4171 if(!class_exists("iFrame")) {
4172 require_once('modules/iFrames/iFrame.php');
4180 * Given a version such as 5.5.0RC1 return RC. If we have a version such as: 5.5 then return GA
4182 * @param string $version
4183 * @return string RC, BETA, GA
4185 function getVersionStatus($version){
4186 if(preg_match('/^[\d\.]+?([a-zA-Z]+?)[\d]*?$/si', $version, $matches)) {
4187 return strtoupper($matches[1]);
4194 * Return the numeric portion of a version. For example if passed 5.5.0RC1 then return 5.5. If given
4195 * 5.5.1RC1 then return 5.5.1
4197 * @param string $version
4200 function getMajorMinorVersion($version){
4201 if(preg_match('/^([\d\.]+).*$/si', $version, $matches2)){
4202 $version = $matches2[1];
4203 $arr = explode('.', $version);
4204 if(count($arr) > 2){
4206 $version = substr($version, 0, 3);
4214 * Return string composed of seconds & microseconds of current time, without dots
4217 function sugar_microtime()
4219 $now = explode(' ', microtime());
4220 $unique_id = $now[1].str_replace('.', '', $now[0]);
4225 * Extract urls from a piece of text
4227 * @return array of urls found in $string
4229 function getUrls($string)
4231 $lines = explode("<br>", trim($string));
4233 foreach($lines as $line){
4234 $regex = '/http?\:\/\/[^\" ]+/i';
4235 preg_match_all($regex, $line, $matches);
4236 foreach($matches[0] as $match){
4245 * Sanitize image file from hostile content
4246 * @param string $path Image file
4247 * @param bool $jpeg Accept only JPEGs?
4249 function verify_image_file($path, $jpeg = false)
4251 if(function_exists('imagepng') && function_exists('imagejpeg') && function_exists('imagecreatefromstring')) {
4252 $img = imagecreatefromstring(file_get_contents($path));
4256 $img_size = getimagesize($path);
4257 $filetype = $img_size['mime'];
4258 //if filetype is jpeg or if we are only allowing jpegs, create jpg image
4259 if($filetype == "image/jpeg" || $jpeg) {
4260 if(imagejpeg($img, $path)) {
4263 } elseif ($filetype == "image/png") { // else if the filetype is png, create png
4264 imagealphablending($img, true);
4265 imagesavealpha($img, true);
4266 if(imagepng($img, $path)) {
4273 // check image manually
4274 $fp = fopen($path, "r");
4275 if(!$fp) return false;
4276 $data = fread($fp, 4096);
4278 if(preg_match("/<(html|!doctype|script|body|head|plaintext|table|img |pre(>| )|frameset|iframe|object|link|base|style|font|applet|meta|center|form|isindex)/i",
4280 $GLOBALS['log']->info("Found {$m[0]} in $path, not allowing upload");
4289 * Verify uploaded image
4290 * Verifies that image has proper extension, MIME type and doesn't contain hostile contant
4291 * @param string $path Image path
4292 * @param bool $jpeg_only Accept only JPEGs?
4294 function verify_uploaded_image($path, $jpeg_only = false)
4296 $supportedExtensions = array('jpg' => 'image/jpeg', 'jpeg' => 'image/jpeg');
4298 $supportedExtensions['png'] = 'image/png';
4301 if(!file_exists($path) || !is_file($path)) {
4305 $img_size = getimagesize($path);
4306 $filetype = $img_size['mime'];
4307 $ext = end(explode(".", $path));
4308 if(substr_count('..', $path) > 0 || $ext === $path || !in_array(strtolower($ext), array_keys($supportedExtensions)) ||
4309 !in_array($filetype, array_values($supportedExtensions))) {
4312 return verify_image_file($path, $jpeg_only);
4316 * @param $input - the input string to sanitize
4317 * @param int $quotes - use quotes
4318 * @param string $charset - the default charset
4319 * @param bool $remove - strip tags or not
4320 * @return string - the sanitized string
4322 function sanitize($input, $quotes = ENT_QUOTES, $charset = 'UTF-8', $remove = false)
4324 return htmlentities($input, $quotes, $charset);