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 'import_max_records_total_limit' => '',
153 'languages' => empty($languages) ? array('en_us' => 'English (US)') : $languages,
154 'list_max_entries_per_page' => empty($list_max_entries_per_page) ? 20 : $list_max_entries_per_page,
155 'list_max_entries_per_subpanel' => empty($list_max_entries_per_subpanel) ? 10 : $list_max_entries_per_subpanel,
156 'lock_default_user_name' => empty($lock_default_user_name) ? false : $lock_default_user_name,
157 'log_memory_usage' => empty($log_memory_usage) ? false : $log_memory_usage,
158 'portal_view' => 'single_user',
159 'resource_management' => array (
160 'special_query_limit' => 50000,
161 'special_query_modules' => array('Reports', 'Export', 'Import', 'Administration', 'Sync'),
162 'default_limit' => 1000,
164 'require_accounts' => empty($requireAccounts) ? true : $requireAccounts,
165 'rss_cache_time' => empty($RSS_CACHE_TIME) ? '10800' : $RSS_CACHE_TIME,
166 'session_dir' => $session_dir, // this must be set!!
167 'site_url' => empty($site_URL) ? $site_url : $site_URL, // this must be set!!
168 'showDetailData' => true, // if true, read-only ACL fields will still appear on EditViews as non-editable
169 'showThemePicker' => true,
170 'sugar_version' => empty($sugar_version) ? 'unknown' : $sugar_version,
171 'time_formats' => empty($timeFormats) ? array (
172 'H:i'=>'23:00', 'h:ia'=>'11:00 pm', 'h:iA'=>'11:00PM',
173 'H.i'=>'23.00', 'h.ia'=>'11.00 pm', 'h.iA'=>'11.00PM' ) : $timeFormats,
174 'tmp_dir' => $tmp_dir, // this must be set!!
175 'translation_string_prefix' => empty($translation_string_prefix) ? false : $translation_string_prefix,
176 'unique_key' => empty($unique_key) ? md5(create_guid()) : $unique_key,
177 'upload_badext' => empty($upload_badext) ? array (
178 'php', 'php3', 'php4', 'php5', 'pl', 'cgi', 'py',
179 'asp', 'cfm', 'js', 'vbs', 'html', 'htm' ) : $upload_badext,
180 'upload_dir' => $upload_dir, // this must be set!!
181 'upload_maxsize' => empty($upload_maxsize) ? 3000000 : $upload_maxsize,
182 'import_max_execution_time' => empty($import_max_execution_time) ? 3600 : $import_max_execution_time,
183 'lock_homepage' => false,
184 'lock_subpanels' => false,
185 'max_dashlets_homepage' => 15,
186 'dashlet_display_row_options' => array('1','3','5','10'),
187 'default_max_tabs' => empty($max_tabs) ? '7' : $max_tabs,
188 'default_subpanel_tabs' => empty($subpanel_tabs) ? true : $subpanel_tabs,
189 'default_subpanel_links' => empty($subpanel_links) ? false : $subpanel_links,
190 'default_swap_last_viewed' => empty($swap_last_viewed) ? false : $swap_last_viewed,
191 'default_swap_shortcuts' => empty($swap_shortcuts) ? false : $swap_shortcuts,
192 'default_navigation_paradigm' => empty($navigation_paradigm) ? 'gm' : $navigation_paradigm,
193 'default_call_status' => 'Planned',
194 'js_lang_version' => 1,
195 'passwordsetting' => empty($passwordsetting) ? array (
196 'SystemGeneratedPasswordON' => '',
197 'generatepasswordtmpl' => '',
198 'lostpasswordtmpl' => '',
199 'forgotpasswordON' => true,
200 'linkexpiration' => '1',
201 'linkexpirationtime' => '30',
202 'linkexpirationtype' => '1',
203 'systexpiration' => '0',
204 'systexpirationtime' => '',
205 'systexpirationtype' => '0',
206 'systexpirationlogin' => '',
207 ) : $passwordsetting,
211 function get_sugar_config_defaults() {
214 * used for getting base values for array style config.php. used by the
215 * installer and to fill in new entries on upgrades. see also:
219 $sugar_config_defaults = array (
220 'admin_export_only' => false,
221 'export_delimiter' => ',',
222 'cache_dir' => 'cache/',
223 'calculate_response_time' => true,
224 'create_default_user' => false,
225 'chartEngine' => 'Jit',
226 'date_formats' => array (
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', 'm/d/Y' => '12/23/2010', 'd/m/Y' => '23/12/2010',
229 'Y.m.d' => '2010.12.23', 'd.m.Y' => '23.12.2010', 'm.d.Y' => '12.23.2010',),
230 'dbconfigoption' => array (
231 'persistent' => true,
234 'seqname_format' => '%s_seq',
237 'default_action' => 'index',
238 'default_charset' => return_session_value_or_default('default_charset',
240 'default_currency_name' => return_session_value_or_default('default_currency_name', 'US Dollar'),
241 'default_currency_symbol' => return_session_value_or_default('default_currency_symbol', '$'),
242 'default_currency_iso4217' => return_session_value_or_default('default_currency_iso4217', 'USD'),
243 'default_currency_significant_digits' => return_session_value_or_default('default_currency_significant_digits', 2),
244 'default_number_grouping_seperator' => return_session_value_or_default('default_number_grouping_seperator', ','),
245 'default_decimal_seperator' => return_session_value_or_default('default_decimal_seperator', '.'),
246 'default_date_format' => 'm/d/Y',
247 'default_export_charset' => 'UTF-8',
248 'default_language' => return_session_value_or_default('default_language',
250 'default_module' => 'Home',
251 'default_password' => '',
252 'default_permissions' => array (
258 'default_theme' => return_session_value_or_default('site_default_theme', 'Sugar5'),
259 'default_time_format' => 'h:ia',
260 'default_user_is_admin' => false,
261 'default_user_name' => '',
262 'disable_export' => false,
263 'disable_persistent_connections' =>
264 return_session_value_or_default('disable_persistent_connections',
266 'display_email_template_variable_chooser' => false,
267 'display_inbound_email_buttons' => false,
268 'dump_slow_queries' => false,
269 'email_default_editor' => 'html',
270 'email_default_client' => 'sugar',
271 'email_default_delete_attachments' => true,
272 'history_max_viewed' => 50,
273 'installer_locked' => true,
274 'import_max_records_per_file' => 100,
275 'import_max_records_total_limit' => '',
276 'languages' => array('en_us' => 'English (US)'),
277 'large_scale_test' => false,
278 'list_max_entries_per_page' => 20,
279 'list_max_entries_per_subpanel' => 10,
280 'lock_default_user_name' => false,
281 'log_memory_usage' => false,
282 'portal_view' => 'single_user',
283 'resource_management' => array (
284 'special_query_limit' => 50000,
285 'special_query_modules' => array('Reports', 'Export', 'Import', 'Administration', 'Sync'),
286 'default_limit' => 1000,
288 'require_accounts' => true,
289 'rss_cache_time' => return_session_value_or_default('rss_cache_time',
291 'save_query' => 'all',
292 'showDetailData' => true, // if true, read-only ACL fields will still appear on EditViews as non-editable
293 'showThemePicker' => true,
294 'slow_query_time_msec' => '100',
296 'time_formats' => array (
297 'H:i'=>'23:00', 'h:ia'=>'11:00pm', 'h:iA'=>'11:00PM', 'h:i a'=>'11:00 pm', 'h:i A'=>'11:00 PM',
298 'H.i'=>'23.00', 'h.ia'=>'11.00pm', 'h.iA'=>'11.00PM', 'h.i a'=>'11.00 pm', 'h.i A'=>'11.00 PM' ),
299 'tracker_max_display_length' => 15,
300 'translation_string_prefix' =>
301 return_session_value_or_default('translation_string_prefix', false),
302 'upload_badext' => array (
303 'php', 'php3', 'php4', 'php5', 'pl', 'cgi', 'py',
304 'asp', 'cfm', 'js', 'vbs', 'html', 'htm' ),
305 'upload_maxsize' => 3000000,
306 'import_max_execution_time' => 3600,
307 // 'use_php_code_json' => returnPhpJsonStatus(),
308 'verify_client_ip' => true,
309 'js_custom_version' => '',
310 'js_lang_version' => 1,
311 'lead_conv_activity_opt' => 'move',
312 'default_number_grouping_seperator' => ',',
313 'default_decimal_seperator' => '.',
314 'lock_homepage' => false,
315 'lock_subpanels' => false,
316 'max_dashlets_homepage' => '15',
317 'default_max_tabs' => '7',
318 'dashlet_display_row_options' => array('1','3','5','10'),
319 'default_subpanel_tabs' => true,
320 'default_subpanel_links' => false,
321 'default_swap_last_viewed' => false,
322 'default_swap_shortcuts' => false,
323 'default_navigation_paradigm' => 'gm',
324 'admin_access_control' => false,
325 'use_common_ml_dir' => false,
326 'common_ml_dir' => '',
328 'passwordsetting' => empty($passwordsetting) ? array (
329 'SystemGeneratedPasswordON' => '',
330 'generatepasswordtmpl' => '',
331 'lostpasswordtmpl' => '',
332 'forgotpasswordON' => false,
333 'linkexpiration' => '1',
334 'linkexpirationtime' => '30',
335 'linkexpirationtype' => '1',
336 'systexpiration' => '0',
337 'systexpirationtime' => '',
338 'systexpirationtype' => '0',
339 'systexpirationlogin' => '',
340 ) : $passwordsetting,
341 'use_real_names' => true,
344 if(!is_object($locale)) {
345 $locale = new Localization();
348 $sugar_config_defaults['default_currencies'] = $locale->getDefaultCurrencies();
350 $sugar_config_defaults = sugarArrayMerge($locale->getLocaleConfigDefaults(), $sugar_config_defaults);
351 return( $sugar_config_defaults );
355 * @deprecated use SugarView::getMenu() instead
357 function load_menu($path){
360 if(file_exists($path . 'Menu.php'))
362 require($path . 'Menu.php');
364 if(file_exists('custom/' . $path . 'Ext/Menus/menu.ext.php'))
366 require('custom/' . $path . 'Ext/Menus/menu.ext.php');
368 if(file_exists('custom/application/Ext/Menus/menu.ext.php'))
370 require('custom/application/Ext/Menus/menu.ext.php');
376 * get_notify_template_file
377 * This function will return the location of the email notifications template to use
379 * @return string relative file path to email notifications template file
381 function get_notify_template_file($language){
383 * Order of operation:
384 * 1) custom version of specified language
385 * 2) stock version of specified language
386 * 3) custom version of en_us template
387 * 4) stock en_us template
390 // set $file to the base code template so it's set if none of the conditions pass
391 $file = "include/language/en_us.notify_template.html";
393 if(file_exists("custom/include/language/{$language}.notify_template.html")){
394 $file = "custom/include/language/{$language}.notify_template.html";
396 else if(file_exists("include/language/{$language}.notify_template.html")){
397 $file = "include/language/{$language}.notify_template.html";
399 else if(file_exists("custom/include/language/en_us.notify_template.html")){
400 $file = "custom/include/language/en_us.notify_template.html";
406 function sugar_config_union( $default, $override ){
407 // a little different then array_merge and array_merge_recursive. we want
408 // the second array to override the first array if the same value exists,
409 // otherwise merge the unique keys. it handles arrays of arrays recursively
410 // might be suitable for a generic array_union
411 if( !is_array( $override ) ){
414 foreach( $default as $key => $value ){
415 if( !array_key_exists($key, $override) ){
416 $override[$key] = $value;
418 else if( is_array( $key ) ){
419 $override[$key] = sugar_config_union( $value, $override[$key] );
425 function make_not_writable( $file ){
426 // Returns true if the given file/dir has been made not writable
428 if( is_file($file) || is_dir($file) ){
429 if( !is_writable($file) ){
433 $original_fileperms = fileperms($file);
435 // take away writable permissions
436 $new_fileperms = $original_fileperms & ~0x0092;
437 @sugar_chmod($file, $new_fileperms);
439 if( !is_writable($file) ){
448 /** This function returns the name of the person.
449 * It currently returns "first last". It should not put the space if either name is not available.
450 * It should not return errors if either name is not available.
451 * If no names are present, it will return ""
452 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
453 * All Rights Reserved.
454 * Contributor(s): ______________________________________..
456 function return_name($row, $first_column, $last_column)
462 if(isset($row[$first_column]))
464 $first_name = stripslashes($row[$first_column]);
467 if(isset($row[$last_column]))
469 $last_name = stripslashes($row[$last_column]);
472 $full_name = $first_name;
474 // If we have a first name and we have a last name
475 if($full_name != "" && $last_name != "")
477 // append a space, then the last name
478 $full_name .= " ".$last_name;
480 // If we have no first name, but we have a last name
481 else if($last_name != "")
483 // append the last name without the space.
484 $full_name .= $last_name;
491 function get_languages()
493 global $sugar_config;
494 $lang = $sugar_config['languages'];
495 if(!empty($sugar_config['disabled_languages'])){
496 foreach(explode(',', $sugar_config['disabled_languages']) as $disable) {
497 unset($lang[$disable]);
503 function get_all_languages()
505 global $sugar_config;
506 return $sugar_config['languages'];
510 function get_language_display($key)
512 global $sugar_config;
513 return $sugar_config['languages'][$key];
516 function get_assigned_user_name($assigned_user_id, $is_group = '') {
517 static $saved_user_list = null;
519 if(empty($saved_user_list)) {
520 $saved_user_list = get_user_array(false, '', '', false, null, $is_group);
523 if(isset($saved_user_list[$assigned_user_id])) {
524 return $saved_user_list[$assigned_user_id];
531 * retrieves the user_name column value (login)
532 * @param string id GUID of user
535 function get_user_name($id) {
539 $db = DBManagerFactory::getInstance();
541 $q = "SELECT user_name FROM users WHERE id='{$id}'";
543 $a = $db->fetchByAssoc($r);
545 return (empty($a)) ? '' : $a['user_name'];
549 //TODO Update to use global cache
550 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) {
552 global $sugar_config;
556 $locale = new Localization();
559 $user_array = get_register_value('user_array', $add_blank. $status . $assigned_user);
561 if(!isset($user_array)) {
562 $db = DBManagerFactory::getInstance();
563 $temp_result = Array();
564 // Including deleted users for now.
565 if (empty($status)) {
566 $query = "SELECT id, first_name, last_name, user_name from users WHERE 1=1".$is_group;
569 $query = "SELECT id, first_name, last_name, user_name from users WHERE status='$status'".$is_group;
572 if (!empty($user_name_begins)) {
573 $query .= " AND user_name LIKE '$user_name_begins%' ";
575 if (!empty($assigned_user)) {
576 $query .= " OR id='$assigned_user'";
578 $query = $query.' ORDER BY user_name ASC';
579 $GLOBALS['log']->debug("get_user_array query: $query");
580 $result = $db->query($query, true, "Error filling in user array: ");
582 if ($add_blank==true) {
583 // Add in a blank row
584 $temp_result[''] = '';
587 // Get the id and the name.
588 while($row = $db->fetchByAssoc($result)) {
589 if($use_real_name == true || showFullName()) {
590 if(isset($row['last_name'])) { // cn: we will ALWAYS have both first_name and last_name (empty value if blank in db)
591 $temp_result[$row['id']] = $locale->getLocaleFormattedName($row['first_name'],$row['last_name']);
593 $temp_result[$row['id']] = $row['user_name'];
596 $temp_result[$row['id']] = $row['user_name'];
600 $user_array = $temp_result;
602 set_register_value('user_array', $add_blank. $status . $assigned_user, $temp_result);
611 * uses a different query to return a list of users than get_user_array()
612 * @param args string where clause entry
613 * @return array Array of Users' details that match passed criteria
615 function getUserArrayFromFullName($args, $hide_portal_users = false) {
617 $db = DBManagerFactory::getInstance();
620 if(strpos($args, " ")) {
621 $argArray = explode(" ", $args);
627 foreach($argArray as $arg) {
628 if(!empty($inClause)) {
634 $inClause .= "(first_name LIKE '{$arg}%' OR last_name LIKE '{$arg}%')";
637 $query = "SELECT id, first_name, last_name, user_name FROM users WHERE status='Active' AND deleted=0 AND ";
638 if ( $hide_portal_users ) {
639 $query .= " portal_only=0 AND ";
642 $query .= " ORDER BY last_name ASC";
644 $r = $db->query($query);
646 while($a = $db->fetchByAssoc($r)) {
647 $ret[$a['id']] = $locale->getLocaleFormattedName($a['first_name'], $a['last_name']);
655 * based on user pref then system pref
657 function showFullName() {
658 global $sugar_config;
659 global $current_user;
660 static $showFullName = null;
662 if (is_null($showFullName)) {
663 $sysPref = !empty($sugar_config['use_real_names']);
664 $userPref = (is_object($current_user)) ? $current_user->getPreference('use_real_names') : null;
666 if($userPref != null) {
667 $showFullName = ($userPref == 'on');
669 $showFullName = $sysPref;
673 return $showFullName;
676 function clean($string, $maxLength)
678 $string = substr($string, 0, $maxLength);
679 return escapeshellcmd($string);
683 * Copy the specified request variable to the member variable of the specified object.
684 * Do no copy if the member variable is already set.
685 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
686 * All Rights Reserved.
687 * Contributor(s): ______________________________________..
689 function safe_map($request_var, & $focus, $always_copy = false)
691 safe_map_named($request_var, $focus, $request_var, $always_copy);
695 * Copy the specified request variable to the member variable of the specified object.
696 * Do no copy if the member variable is already set.
697 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
698 * All Rights Reserved.
699 * Contributor(s): ______________________________________..
701 function safe_map_named($request_var, & $focus, $member_var, $always_copy)
703 if (isset($_REQUEST[$request_var]) && ($always_copy || is_null($focus->$member_var))) {
704 $GLOBALS['log']->debug("safe map named called assigning '{$_REQUEST[$request_var]}' to $member_var");
705 $focus->$member_var = $_REQUEST[$request_var];
710 * This function retrieves an application language file and returns the array of strings included in the $app_list_strings var.
712 * @param string $language specific language to load
713 * @return array lang strings
715 function return_app_list_strings_language($language)
717 global $app_list_strings;
718 global $sugar_config;
720 $cache_key = 'app_list_strings.'.$language;
722 // Check for cached value
723 $cache_entry = sugar_cache_retrieve($cache_key);
724 if(!empty($cache_entry))
729 $default_language = $sugar_config['default_language'];
730 $temp_app_list_strings = $app_list_strings;
733 if ($language != 'en_us') {
736 if ($default_language != 'en_us' && $language != $default_language) {
737 $langs[] = $default_language;
739 $langs[] = $language;
741 $app_list_strings_array = array();
743 foreach ( $langs as $lang ) {
744 $app_list_strings = array();
745 if(file_exists("include/language/$lang.lang.php")) {
746 include("include/language/$lang.lang.php");
747 $GLOBALS['log']->info("Found language file: $lang.lang.php");
749 if(file_exists("include/language/$lang.lang.override.php")) {
750 include("include/language/$lang.lang.override.php");
751 $GLOBALS['log']->info("Found override language file: $lang.lang.override.php");
753 if(file_exists("include/language/$lang.lang.php.override")) {
754 include("include/language/$lang.lang.php.override");
755 $GLOBALS['log']->info("Found override language file: $lang.lang.php.override");
758 $app_list_strings_array[] = $app_list_strings;
761 $app_list_strings = array();
762 foreach ( $app_list_strings_array as $app_list_strings_item ) {
763 $app_list_strings = sugarArrayMerge($app_list_strings, $app_list_strings_item);
766 foreach ( $langs as $lang ) {
767 if(file_exists("custom/application/Ext/Language/$lang.lang.ext.php")) {
768 $app_list_strings = _mergeCustomAppListStrings("custom/application/Ext/Language/$lang.lang.ext.php" , $app_list_strings);
769 $GLOBALS['log']->info("Found extended language file: $lang.lang.ext.php");
771 if(file_exists("custom/include/language/$lang.lang.php")) {
772 include("custom/include/language/$lang.lang.php");
773 $GLOBALS['log']->info("Found custom language file: $lang.lang.php");
777 if(!isset($app_list_strings)) {
778 $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");
782 $return_value = $app_list_strings;
783 $app_list_strings = $temp_app_list_strings;
785 sugar_cache_put($cache_key, $return_value);
787 return $return_value;
791 * The dropdown items in custom language files is $app_list_strings['$key']['$second_key'] = $value not
792 * $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.
793 * @param file string the language that you want include,
794 * @param app_list_strings array the golbal strings
798 function _mergeCustomAppListStrings($file , $app_list_strings){
799 $app_list_strings_original = $app_list_strings;
800 unset($app_list_strings);
802 if(!isset($app_list_strings) || !is_array($app_list_strings)){
803 return $app_list_strings_original;
805 //Bug 25347: We should not merge custom dropdown fields unless they relate to parent fields or the module list.
806 foreach($app_list_strings as $key=>$value)
808 $exemptDropdowns = array("moduleList", "parent_type_display", "record_type_display", "record_type_display_notes");
809 if (!in_array($key, $exemptDropdowns) && array_key_exists($key, $app_list_strings_original))
811 unset($app_list_strings_original["$key"]);
814 $app_list_strings = sugarArrayMergeRecursive($app_list_strings_original , $app_list_strings);
815 return $app_list_strings;
819 * This function retrieves an application language file and returns the array of strings included.
821 * @param string $language specific language to load
822 * @return array lang strings
824 function return_application_language($language)
826 global $app_strings, $sugar_config;
828 $cache_key = 'app_strings.'.$language;
830 // Check for cached value
831 $cache_entry = sugar_cache_retrieve($cache_key);
832 if(!empty($cache_entry))
837 $temp_app_strings = $app_strings;
838 $default_language = $sugar_config['default_language'];
841 if ($language != 'en_us') {
844 if ($default_language != 'en_us' && $language != $default_language) {
845 $langs[] = $default_language;
848 $langs[] = $language;
850 $app_strings_array = array();
852 foreach ( $langs as $lang ) {
853 $app_strings = array();
854 if(file_exists("include/language/$lang.lang.php")) {
855 include("include/language/$lang.lang.php");
856 $GLOBALS['log']->info("Found language file: $lang.lang.php");
858 if(file_exists("include/language/$lang.lang.override.php")) {
859 include("include/language/$lang.lang.override.php");
860 $GLOBALS['log']->info("Found override language file: $lang.lang.override.php");
862 if(file_exists("include/language/$lang.lang.php.override")) {
863 include("include/language/$lang.lang.php.override");
864 $GLOBALS['log']->info("Found override language file: $lang.lang.php.override");
866 if(file_exists("custom/application/Ext/Language/$lang.lang.ext.php")) {
867 include("custom/application/Ext/Language/$lang.lang.ext.php");
868 $GLOBALS['log']->info("Found extended language file: $lang.lang.ext.php");
870 if(file_exists("custom/include/language/$lang.lang.php")) {
871 include("custom/include/language/$lang.lang.php");
872 $GLOBALS['log']->info("Found custom language file: $lang.lang.php");
874 $app_strings_array[] = $app_strings;
877 $app_strings = array();
878 foreach ( $app_strings_array as $app_strings_item ) {
879 $app_strings = sugarArrayMerge($app_strings, $app_strings_item);
882 if(!isset($app_strings)) {
883 $GLOBALS['log']->fatal("Unable to load the application language strings");
887 // If we are in debug mode for translating, turn on the prefix now!
888 if($sugar_config['translation_string_prefix']) {
889 foreach($app_strings as $entry_key=>$entry_value) {
890 $app_strings[$entry_key] = $language.' '.$entry_value;
893 if(isset($_SESSION['show_deleted'])) {
894 $app_strings['LBL_DELETE_BUTTON'] = $app_strings['LBL_UNDELETE_BUTTON'];
895 $app_strings['LBL_DELETE_BUTTON_LABEL'] = $app_strings['LBL_UNDELETE_BUTTON_LABEL'];
896 $app_strings['LBL_DELETE_BUTTON_TITLE'] = $app_strings['LBL_UNDELETE_BUTTON_TITLE'];
897 $app_strings['LBL_DELETE'] = $app_strings['LBL_UNDELETE'];
900 $app_strings['LBL_ALT_HOT_KEY'] = get_alt_hot_key();
902 $return_value = $app_strings;
903 $app_strings = $temp_app_strings;
905 sugar_cache_put($cache_key, $return_value);
907 return $return_value;
911 * This function retrieves a module's language file and returns the array of strings included.
913 * @param string $language specific language to load
914 * @param string $module module name to load strings for
915 * @param bool $refresh optional, true if you want to rebuild the language strings
916 * @return array lang strings
918 function return_module_language($language, $module, $refresh=false)
921 global $sugar_config;
922 global $currentModule;
924 // Jenny - Bug 8119: Need to check if $module is not empty
925 if (empty($module)) {
926 $stack = debug_backtrace();
927 $GLOBALS['log']->warn("Variable module is not in return_module_language ". var_export($stack, true));
933 $cache_key = LanguageManager::getLanguageCacheKey($module, $language);
934 // Check for cached value
935 $cache_entry = sugar_cache_retrieve($cache_key);
936 if(!empty($cache_entry))
941 // Store the current mod strings for later
942 $temp_mod_strings = $mod_strings;
943 $loaded_mod_strings = array();
944 $language_used = $language;
945 $default_language = $sugar_config['default_language'];
947 if(empty($language)) {
948 $language = $default_language;
951 // Bug 21559 - So we can get all the strings defined in the template, refresh
952 // the vardefs file if the cached language file doesn't exist.
953 if(!file_exists($GLOBALS['sugar_config']['cache_dir'].'modules/'. $module . '/language/'.$language.'.lang.php')
954 && !empty($GLOBALS['beanList'][$module])){
955 $object = $GLOBALS['beanList'][$module];
956 if ($object == 'aCase') {
959 VardefManager::refreshVardefs($module,$object);
962 $loaded_mod_strings = LanguageManager::loadModuleLanguage($module, $language,$refresh);
964 // cn: bug 6048 - merge en_us with requested language
965 if($language != $sugar_config['default_language'])
966 $loaded_mod_strings = sugarArrayMerge(
967 LanguageManager::loadModuleLanguage($module, $sugar_config['default_language'],$refresh),
971 // Load in en_us strings by default
972 if($language != 'en_us' && $sugar_config['default_language'] != 'en_us')
973 $loaded_mod_strings = sugarArrayMerge(
974 LanguageManager::loadModuleLanguage($module, 'en_us', $refresh),
978 // If we are in debug mode for translating, turn on the prefix now!
979 if($sugar_config['translation_string_prefix']) {
980 foreach($loaded_mod_strings as $entry_key=>$entry_value) {
981 $loaded_mod_strings[$entry_key] = $language_used.' '.$entry_value;
985 $return_value = $loaded_mod_strings;
986 if(!isset($mod_strings)){
987 $mod_strings = $return_value;
990 $mod_strings = $temp_mod_strings;
992 $cache_key = LanguageManager::getLanguageCacheKey($module, $language);
993 sugar_cache_put($cache_key, $return_value);
994 return $return_value;
998 /** This function retrieves an application language file and returns the array of strings included in the $mod_list_strings var.
999 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1000 * All Rights Reserved.
1001 * Contributor(s): ______________________________________..
1002 * If you are using the current language, do not call this function unless you are loading it for the first time */
1003 function return_mod_list_strings_language($language,$module) {
1004 global $mod_list_strings;
1005 global $sugar_config;
1006 global $currentModule;
1008 $cache_key = "mod_list_str_lang.".$language.$module;
1010 // Check for cached value
1011 $cache_entry = sugar_cache_retrieve($cache_key);
1012 if(!empty($cache_entry))
1014 return $cache_entry;
1017 $language_used = $language;
1018 $temp_mod_list_strings = $mod_list_strings;
1019 $default_language = $sugar_config['default_language'];
1021 if($currentModule == $module && isset($mod_list_strings) && $mod_list_strings != null) {
1022 return $mod_list_strings;
1025 // cn: bug 6351 - include en_us if file langpack not available
1026 // cn: bug 6048 - merge en_us with requested language
1027 include("modules/$module/language/en_us.lang.php");
1028 $en_mod_list_strings = array();
1029 if($language_used != $default_language)
1030 $en_mod_list_strings = $mod_list_strings;
1032 if(file_exists("modules/$module/language/$language.lang.php")) {
1033 include("modules/$module/language/$language.lang.php");
1036 if(file_exists("modules/$module/language/$language.lang.override.php")){
1037 include("modules/$module/language/$language.lang.override.php");
1040 if(file_exists("modules/$module/language/$language.lang.php.override")){
1041 echo 'Please Change:<br>' . "modules/$module/language/$language.lang.php.override" . '<br>to<br>' . 'Please Change:<br>' . "modules/$module/language/$language.lang.override.php";
1042 include("modules/$module/language/$language.lang.php.override");
1045 // cn: bug 6048 - merge en_us with requested language
1046 $mod_list_strings = sugarArrayMerge($en_mod_list_strings, $mod_list_strings);
1048 // if we still don't have a language pack, then log an error
1049 if(!isset($mod_list_strings)) {
1050 $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})");
1054 $return_value = $mod_list_strings;
1055 $mod_list_strings = $temp_mod_list_strings;
1057 sugar_cache_put($cache_key, $return_value);
1058 return $return_value;
1062 /** This function retrieves a theme's language file and returns the array of strings included.
1063 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1064 * All Rights Reserved.
1065 * Contributor(s): ______________________________________..
1067 function return_theme_language($language, $theme)
1069 global $mod_strings, $sugar_config, $currentModule;
1071 $language_used = $language;
1072 $default_language = $sugar_config['default_language'];
1074 include(SugarThemeRegistry::get($theme)->getFilePath()."/language/$current_language.lang.php");
1075 if(file_exists(SugarThemeRegistry::get($theme)->getFilePath()."/language/$current_language.lang.override.php")){
1076 include(SugarThemeRegistry::get($theme)->getFilePath()."/language/$current_language.lang.override.php");
1078 if(file_exists(SugarThemeRegistry::get($theme)->getFilePath()."/language/$current_language.lang.php.override")){
1079 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";
1080 include(SugarThemeRegistry::get($theme)->getFilePath()."/language/$current_language.lang.php.override");
1082 if(!isset($theme_strings))
1084 $GLOBALS['log']->warn("Unable to find the theme file for language: ".$language." and theme: ".$theme);
1085 require(SugarThemeRegistry::get($theme)->getFilePath()."/language/$default_language.lang.php");
1086 $language_used = $default_language;
1089 if(!isset($theme_strings))
1091 $GLOBALS['log']->fatal("Unable to load the theme($theme) language file for the selected language($language) or the default language($default_language)");
1095 // If we are in debug mode for translating, turn on the prefix now!
1096 if($sugar_config['translation_string_prefix'])
1098 foreach($theme_strings as $entry_key=>$entry_value)
1100 $theme_strings[$entry_key] = $language_used.' '.$entry_value;
1104 return $theme_strings;
1109 /** If the session variable is defined and is not equal to "" then return it. Otherwise, return the default value.
1110 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1111 * All Rights Reserved.
1112 * Contributor(s): ______________________________________..
1114 function return_session_value_or_default($varname, $default)
1116 if(isset($_SESSION[$varname]) && $_SESSION[$varname] != "")
1118 return $_SESSION[$varname];
1125 * Creates an array of where restrictions. These are used to construct a where SQL statement on the query
1126 * 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.
1127 * @param &$where_clauses - The array to append the clause to
1128 * @param $variable_name - The name of the variable to look for an add to the where clause if found
1129 * @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.
1130 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1131 * All Rights Reserved.
1132 * Contributor(s): ______________________________________..
1134 function append_where_clause(&$where_clauses, $variable_name, $SQL_name = null)
1136 if($SQL_name == null)
1138 $SQL_name = $variable_name;
1141 if(isset($_REQUEST[$variable_name]) && $_REQUEST[$variable_name] != "")
1143 array_push($where_clauses, "$SQL_name like '".$GLOBALS['db']->quote($_REQUEST[$variable_name])."%'");
1148 * Generate the appropriate SQL based on the where clauses.
1149 * @param $where_clauses - An Array of individual where clauses stored as strings
1150 * @returns string where_clause - The final SQL where clause to be executed.
1151 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1152 * All Rights Reserved.
1153 * Contributor(s): ______________________________________..
1155 function generate_where_statement($where_clauses)
1158 foreach($where_clauses as $clause)
1165 $GLOBALS['log']->info("Here is the where clause for the list view: $where");
1170 * determines if a passed string matches the criteria for a Sugar GUID
1171 * @param string $guid
1172 * @return bool False on failure
1174 function is_guid($guid) {
1175 if(strlen($guid) != 36) {
1179 if(preg_match("/\w{8}-\w{4}-\w{4}-\w{4}-\w{12}/i", $guid)) {
1188 * A temporary method of generating GUIDs of the correct format for our DB.
1189 * @return String contianing a GUID in the format: aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
1191 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1192 * All Rights Reserved.
1193 * Contributor(s): ______________________________________..
1195 function create_guid()
1197 $microTime = microtime();
1198 list($a_dec, $a_sec) = explode(" ", $microTime);
1200 $dec_hex = dechex($a_dec* 1000000);
1201 $sec_hex = dechex($a_sec);
1203 ensure_length($dec_hex, 5);
1204 ensure_length($sec_hex, 6);
1208 $guid .= create_guid_section(3);
1210 $guid .= create_guid_section(4);
1212 $guid .= create_guid_section(4);
1214 $guid .= create_guid_section(4);
1217 $guid .= create_guid_section(6);
1223 function create_guid_section($characters)
1226 for($i=0; $i<$characters; $i++)
1228 $return .= dechex(mt_rand(0,15));
1233 function ensure_length(&$string, $length)
1235 $strlen = strlen($string);
1236 if($strlen < $length)
1238 $string = str_pad($string,$length,"0");
1240 else if($strlen > $length)
1242 $string = substr($string, 0, $length);
1246 function microtime_diff($a, $b) {
1247 list($a_dec, $a_sec) = explode(" ", $a);
1248 list($b_dec, $b_sec) = explode(" ", $b);
1249 return $b_sec - $a_sec + $b_dec - $a_dec;
1252 // check if Studio is displayed.
1253 function displayStudioForCurrentUser()
1255 global $current_user;
1256 if ( $current_user->isAdmin() ) {
1266 function displayWorkflowForCurrentUser()
1268 $_SESSION['display_workflow_for_user'] = false;
1272 // return an array with all modules where the user is an admin.
1273 function get_admin_modules_for_user($user) {
1274 $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");
1281 return($user->getDeveloperModules());
1285 function get_workflow_admin_modules_for_user($user){
1286 if (isset($_SESSION['get_workflow_admin_modules_for_user'])) {
1287 return $_SESSION['get_workflow_admin_modules_for_user'];
1291 $workflow_mod_list = array();
1292 foreach($moduleList as $module){
1293 $workflow_mod_list[$module] = $module;
1296 // This list is taken from teh previous version of workflow_utils.php
1297 $workflow_mod_list['Tasks'] = "Tasks";
1298 $workflow_mod_list['Calls'] = "Calls";
1299 $workflow_mod_list['Meetings'] = "Meetings";
1300 $workflow_mod_list['Notes'] = "Notes";
1301 $workflow_mod_list['ProjectTask'] = "Project Tasks";
1302 $workflow_mod_list['Leads'] = "Leads";
1303 $workflow_mod_list['Opportunities'] = "Opportunities";
1306 $workflow_admin_modules = array();
1308 return $workflow_admin_modules;
1310 $actions = ACLAction::getUserActions($user->id);
1311 //check for ForecastSchedule because it doesn't exist in $workflow_mod_list
1312 if (isset($actions['ForecastSchedule']['module']['admin']['aclaccess']) && ($actions['ForecastSchedule']['module']['admin']['aclaccess']==ACL_ALLOW_DEV ||
1313 $actions['ForecastSchedule']['module']['admin']['aclaccess']==ACL_ALLOW_ADMIN_DEV)) {
1314 $workflow_admin_modules['Forecasts'] = 'Forecasts';
1316 foreach ($workflow_mod_list as $key=>$val) {
1317 if(!in_array($val, $workflow_admin_modules) && ($val!='iFrames' && $val!='Feeds' && $val!='Home' && $val!='Dashboard'
1318 && $val!='Calendar' && $val!='Activities' && $val!='Reports') &&
1319 ($user->isDeveloperForModule($key))) {
1320 $workflow_admin_modules[$key] = $val;
1323 $_SESSION['get_workflow_admin_modules_for_user'] = $workflow_admin_modules;
1324 return ($workflow_admin_modules);
1327 // Check if user is admin for at least one module.
1328 function is_admin_for_any_module($user) {
1332 if($user->isAdmin()) {
1339 // Check if user is admin for a specific module.
1340 function is_admin_for_module($user,$module) {
1341 if (!isset($user)) {
1344 if ($user->isAdmin()) {
1352 * Check if user id belongs to a system admin.
1353 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1354 * All Rights Reserved.
1355 * Contributor(s): ______________________________________..
1357 function is_admin($user) {
1362 return $user->isAdmin();
1366 * Return the display name for a theme if it exists.
1367 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1368 * All Rights Reserved.
1369 * Contributor(s): ______________________________________..
1371 * @deprecated use SugarThemeRegistry::get($theme)->name instead
1373 function get_theme_display($theme)
1375 return SugarThemeRegistry::get($theme)->name;
1379 * Return an array of directory names.
1380 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1381 * All Rights Reserved.
1382 * Contributor(s): ______________________________________..
1384 * @deprecated use SugarThemeRegistry::availableThemes() instead.
1386 function get_themes()
1388 return SugarThemeRegistry::availableThemes();
1392 * THIS FUNCTION IS DEPRECATED AND SHOULD NOT BE USED; USE get_select_options_with_id()
1393 * Create HTML to display select options in a dropdown list. To be used inside
1394 * of a select statement in a form.
1395 * param $option_list - the array of strings to that contains the option list
1396 * param $selected - the string which contains the default value
1397 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1398 * All Rights Reserved.
1399 * Contributor(s): ______________________________________..
1401 function get_select_options ($option_list, $selected) {
1402 return get_select_options_with_id($option_list, $selected);
1406 * Create HTML to display select options in a dropdown list. To be used inside
1407 * 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.
1408 * param $option_list - the array of strings to that contains the option list
1409 * param $selected - the string which contains the default value
1410 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1411 * All Rights Reserved.
1412 * Contributor(s): ______________________________________..
1414 function get_select_options_with_id ($option_list, $selected_key) {
1415 return get_select_options_with_id_separate_key($option_list, $option_list, $selected_key);
1420 * Create HTML to display select options in a dropdown list. To be used inside
1421 * 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.
1422 * param $label_list - the array of strings to that contains the option list
1423 * param $key_list - the array of strings to that contains the values list
1424 * param $selected - the string which contains the default value
1425 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1426 * All Rights Reserved.
1427 * Contributor(s): ______________________________________..
1429 function get_select_options_with_id_separate_key ($label_list, $key_list, $selected_key, $massupdate=false) {
1430 global $app_strings;
1431 $select_options = "";
1433 //for setting null selection values to human readable --None--
1434 $pattern = "/'0?'></";
1435 $replacement = "''>".$app_strings['LBL_NONE']."<";
1437 if (empty($key_list)) $key_list = array();
1438 //create the type dropdown domain and set the selected value if $opp value already exists
1439 foreach ($key_list as $option_key=>$option_value) {
1441 $selected_string = '';
1442 // the system is evaluating $selected_key == 0 || '' to true. Be very careful when changing this. Test all cases.
1443 // The bug was only happening with one of the users in the drop down. It was being replaced by none.
1444 if (($option_key != '' && $selected_key == $option_key) || ($selected_key == '' && $option_key == '' && !$massupdate) || (is_array($selected_key) && in_array($option_key, $selected_key)))
1446 $selected_string = 'selected ';
1449 $html_value = $option_key;
1451 $select_options .= "\n<OPTION ".$selected_string."value='$html_value'>$label_list[$option_key]</OPTION>";
1453 $select_options = preg_replace($pattern, $replacement, $select_options);
1454 return $select_options;
1459 * Call this method instead of die().
1460 * Then we call the die method with the error message that is passed in.
1462 function sugar_die($error_message)
1466 die($error_message);
1471 * Create javascript to clear values of all elements in a form.
1472 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1473 * All Rights Reserved.
1474 * Contributor(s): ______________________________________..
1476 function get_clear_form_js () {
1477 $the_script = <<<EOQ
1478 <script type="text/javascript" language="JavaScript">
1479 function clear_form(form) {
1480 var newLoc = 'index.php?action=' + form.action.value + '&module=' + form.module.value + '&query=true&clear_query=true';
1481 if(typeof(form.advanced) != 'undefined'){
1482 newLoc += '&advanced=' + form.advanced.value;
1484 document.location.href= newLoc;
1493 * Create javascript to set the cursor focus to specific field in a form
1494 * when the screen is rendered. The field name is currently hardcoded into the
1496 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1497 * All Rights Reserved.
1498 * Contributor(s): ______________________________________..
1500 function get_set_focus_js () {
1501 //TODO Clint 5/20 - Make this function more generic so that it can take in the target form and field names as variables
1502 $the_script = <<<EOQ
1503 <script type="text/javascript" language="JavaScript">
1505 function set_focus() {
1506 if (document.forms.length > 0) {
1507 for (i = 0; i < document.forms.length; i++) {
1508 for (j = 0; j < document.forms[i].elements.length; j++) {
1509 var field = document.forms[i].elements[j];
1510 if ((field.type == "text" || field.type == "textarea" || field.type == "password") &&
1511 !field.disabled && (field.name == "first_name" || field.name == "name" || field.name == "user_name" || field.name=="document_name")) {
1513 if (field.type == "text") {
1530 * Very cool algorithm for sorting multi-dimensional arrays. Found at http://us2.php.net/manual/en/function.array-multisort.php
1531 * Syntax: $new_array = array_csort($array [, 'col1' [, SORT_FLAG [, SORT_FLAG]]]...);
1532 * Explanation: $array is the array you want to sort, 'col1' is the name of the column
1533 * you want to sort, SORT_FLAGS are : SORT_ASC, SORT_DESC, SORT_REGULAR, SORT_NUMERIC, SORT_STRING
1534 * you can repeat the 'col',FLAG,FLAG, as often you want, the highest prioritiy is given to
1535 * the first - so the array is sorted by the last given column first, then the one before ...
1536 * Example: $array = array_csort($array,'town','age',SORT_DESC,'name');
1537 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1538 * All Rights Reserved.
1539 * Contributor(s): ______________________________________..
1541 function array_csort() {
1542 $args = func_get_args();
1543 $marray = array_shift($args);
1546 $msortline = "return(array_multisort(";
1547 foreach ($args as $arg) {
1549 if (is_string($arg)) {
1550 foreach ($marray as $row) {
1551 $sortarr[$i][] = $row[$arg];
1554 $sortarr[$i] = $arg;
1556 $msortline .= "\$sortarr[".$i."],";
1558 $msortline .= "\$marray));";
1565 * Converts localized date format string to jscalendar format
1566 * Example: $array = array_csort($array,'town','age',SORT_DESC,'name');
1567 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1568 * All Rights Reserved.
1569 * Contributor(s): ______________________________________..
1571 function parse_calendardate($local_format) {
1572 preg_match('/\(?([^-]{1})[^-]*-([^-]{1})[^-]*-([^-]{1})[^-]*\)/', $local_format, $matches);
1573 $calendar_format = "%" . $matches[1] . "-%" . $matches[2] . "-%" . $matches[3];
1574 return str_replace(array("y", "ᅣ1�7", "a", "j"), array("Y", "Y", "Y", "d"), $calendar_format);
1581 function translate($string, $mod='', $selectedValue=''){
1582 //$test_start = microtime();
1583 //static $mod_strings_results = array();
1585 global $current_language;
1587 if(isset($_REQUEST['login_language'])){
1588 $current_language = ($_REQUEST['login_language'] == $current_language)? $current_language : $_REQUEST['login_language'];
1590 $mod_strings = return_module_language($current_language, $mod);
1593 global $mod_strings;
1597 global $app_strings, $app_list_strings;
1599 if(isset($mod_strings[$string]))
1600 $returnValue = $mod_strings[$string];
1601 else if(isset($app_strings[$string]))
1602 $returnValue = $app_strings[$string];
1603 else if(isset($app_list_strings[$string]))
1604 $returnValue = $app_list_strings[$string];
1605 else if(isset($app_list_strings['moduleList']) && isset($app_list_strings['moduleList'][$string]))
1606 $returnValue = $app_list_strings['moduleList'][$string];
1609 //$test_end = microtime();
1611 // $mod_strings_results[$mod] = microtime_diff($test_start,$test_end);
1613 // echo("translate results:");
1615 // $total_strings = 0;
1616 // foreach($mod_strings_results as $key=>$value)
1618 // echo("Module $key \t\t time $value \t\t<br>");
1619 // $total_time += $value;
1622 // echo("Total time: $total_time<br>");
1626 if(empty($returnValue)){
1630 if(is_array($returnValue) && ! empty($selectedValue) && isset($returnValue[$selectedValue]) ){
1631 return $returnValue[$selectedValue];
1634 return $returnValue;
1637 function unTranslateNum($num) {
1639 static $num_grp_sep;
1640 global $current_user, $sugar_config;
1642 if($dec_sep == null) {
1643 $user_dec_sep = $current_user->getPreference('dec_sep');
1644 $dec_sep = (empty($user_dec_sep) ? $sugar_config['default_decimal_seperator'] : $user_dec_sep);
1646 if($num_grp_sep == null) {
1647 $user_num_grp_sep = $current_user->getPreference('num_grp_sep');
1648 $num_grp_sep = (empty($user_num_grp_sep) ? $sugar_config['default_number_grouping_seperator'] : $user_num_grp_sep);
1651 $num = preg_replace("'" . preg_quote($num_grp_sep) . "'", '', $num);
1652 $num = preg_replace("'" . preg_quote($dec_sep) . "'", '.', $num);
1657 function add_http($url) {
1658 if(!preg_match("@://@i", $url)) {
1660 if(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') {
1664 return "{$scheme}://{$url}";
1671 * returns a default array of XSS tags to clean
1674 function getDefaultXssTags() {
1676 "applet" => "applet",
1681 "frameset" => "frameset",
1682 "iframe" => "iframe",
1683 "import" => "\?import",
1686 "object" => "object",
1687 "script" => "script",
1691 $ret = base64_encode(serialize($tmp));
1697 * Remove potential xss vectors from strings
1698 * @param string str String to search for XSS attack vectors
1699 * @param bool cleanImg Flag to allow <img> tags to survive - only used by InboundEmail for inline images.
1702 function remove_xss($str, $cleanImg=true)
1704 $potentials = clean_xss($str, $cleanImg);
1705 if(is_array($potentials) && !empty($potentials)) {
1706 foreach($potentials as $bad) {
1707 $str = str_replace($bad, "", $str);
1714 * Detects typical XSS attack patterns
1715 * @param string str String to search for XSS attack vectors
1716 * @param bool cleanImg Flag to allow <img> tags to survive - only used by InboundEmail for inline images.
1717 * @return array Array of matches, empty on clean string
1719 function clean_xss($str, $cleanImg=true) {
1720 global $sugar_config;
1722 if(empty($sugar_config['email_xss']))
1723 $sugar_config['email_xss'] = getDefaultXssTags();
1725 $arr = unserialize(base64_decode($sugar_config['email_xss']));
1728 foreach($arr as $v) {
1729 if(!empty($regex)) {
1735 $tag_regex = "#<({$regex})[^>]*>?#sim";
1737 // cn: bug 13079 - "on\w" matched too many non-events (cONTact, strONG, etc.)
1738 $jsEvents = "onblur|onfocus|oncontextmenu|onresize|onscroll|onunload|ondblclick|onclick|";
1739 $jsEvents .= "onmouseup|onmouseover|onmousedown|onmouseenter|onmouseleave|onmousemove|onload|onchange|";
1740 $jsEvents .= "onreset|onselect|onsubmit|onkeydown|onkeypress|onkeyup|onabort|onerror|ondragdrop";
1742 $attribute_regex = "#<.+({$jsEvents})[^=>]*=[^>]*>#sim";
1743 $javascript_regex = '@<[^/>][^>]+(expression\(|j\W*a\W*v\W*a|v\W*b\W*s\W*c\W*r|&#|/\*|\*/)[^>]*>@sim';
1744 $imgsrc_regex = '#<[^>]+src[^=]*=([^>]*?http://[^>]*)>#sim';
1745 $css_url = '#url\(.*\.\w+\)#';
1748 $str = str_replace("\t", "", $str);
1750 $matches = array_merge(
1751 xss_check_pattern($tag_regex, $str),
1752 xss_check_pattern($javascript_regex, $str),
1753 xss_check_pattern($attribute_regex, $str)
1757 $matches = array_merge($matches,
1758 xss_check_pattern($imgsrc_regex, $str)
1762 // cn: bug 13498 - custom white-list of allowed domains that vet remote images
1763 preg_match_all($css_url, $str, $cssUrlMatches, PREG_PATTERN_ORDER);
1765 if(isset($sugar_config['security_trusted_domains']) && !empty($sugar_config['security_trusted_domains']) && is_array($sugar_config['security_trusted_domains'])) {
1766 if(is_array($cssUrlMatches) && count($cssUrlMatches) > 0) {
1767 // normalize whitelist
1768 foreach($sugar_config['security_trusted_domains'] as $k => $v) {
1769 $sugar_config['security_trusted_domains'][$k] = strtolower($v);
1772 foreach($cssUrlMatches[0] as $match) {
1773 $domain = strtolower(substr(strstr($match, "://"), 3));
1774 $baseUrl = substr($domain, 0, strpos($domain, "/"));
1776 if(!in_array($baseUrl, $sugar_config['security_trusted_domains'])) {
1777 $matches[] = $match;
1782 $matches = array_merge($matches, $cssUrlMatches[0]);
1789 * Helper function used by clean_xss() to parse for known-bad vectors
1790 * @param string pattern Regex pattern to use
1791 * @param string str String to parse for badness
1794 function xss_check_pattern($pattern, $str) {
1795 preg_match_all($pattern, $str, $matches, PREG_PATTERN_ORDER);
1799 // Designed to take a string passed in the URL as a parameter and clean all "bad" data from it
1800 // The second argument is a string, "filter," which corresponds to a regular expression
1801 function clean_string($str, $filter = "STANDARD") {
1802 global $sugar_config;
1805 "STANDARD" => '#[^A-Z0-9\-_\.\@]#i',
1806 "STANDARDSPACE" => '#[^A-Z0-9\-_\.\@\ ]#i',
1807 "FILE" => '#[^A-Z0-9\-_\.]#i',
1808 "NUMBER" => '#[^0-9\-]#i',
1809 "SQL_COLUMN_LIST" => '#[^A-Z0-9,_\.]#i',
1810 "PATH_NO_URL" => '#://#i',
1811 "SAFED_GET" => '#[^A-Z0-9\@\=\&\?\.\/\-_~]#i', /* range of allowed characters in a GET string */
1812 "UNIFIED_SEARCH" => "#[\\x00]#", /* cn: bug 3356 & 9236 - MBCS search strings */
1813 "AUTO_INCREMENT" => '#[^0-9\-,\ ]#i',
1814 "ALPHANUM" => '#[^A-Z0-9\-]#i',
1817 if (preg_match($filters[$filter], $str)) {
1818 if (isset($GLOBALS['log']) && is_object($GLOBALS['log'])) {
1819 $GLOBALS['log']->fatal("SECURITY: bad data passed in; string: {$str}");
1821 die("Bad data passed in; <a href=\"{$sugar_config['site_url']}\">Return to Home</a>");
1828 function clean_special_arguments() {
1829 if(isset($_SERVER['PHP_SELF'])) {
1830 if (!empty($_SERVER['PHP_SELF'])) clean_string($_SERVER['PHP_SELF'], 'SAFED_GET');
1832 if (!empty($_REQUEST) && !empty($_REQUEST['login_theme'])) clean_string($_REQUEST['login_theme'], "STANDARD");
1833 if (!empty($_REQUEST) && !empty($_REQUEST['login_module'])) clean_string($_REQUEST['login_module'], "STANDARD");
1834 if (!empty($_REQUEST) && !empty($_REQUEST['login_action'])) clean_string($_REQUEST['login_action'], "STANDARD");
1835 if (!empty($_REQUEST) && !empty($_REQUEST['ck_login_theme_20'])) clean_string($_REQUEST['ck_login_theme_20'], "STANDARD");
1836 if (!empty($_SESSION) && !empty($_SESSION['authenticated_user_theme'])) clean_string($_SESSION['authenticated_user_theme'], "STANDARD");
1837 if (!empty($_REQUEST) && !empty($_REQUEST['module_name'])) clean_string($_REQUEST['module_name'], "STANDARD");
1838 if (!empty($_REQUEST) && !empty($_REQUEST['module'])) clean_string($_REQUEST['module'], "STANDARD");
1839 if (!empty($_POST) && !empty($_POST['parent_type'])) clean_string($_POST['parent_type'], "STANDARD");
1840 if (!empty($_REQUEST) && !empty($_REQUEST['mod_lang'])) clean_string($_REQUEST['mod_lang'], "STANDARD");
1841 if (!empty($_SESSION) && !empty($_SESSION['authenticated_user_language'])) clean_string($_SESSION['authenticated_user_language'], "STANDARD");
1842 if (!empty($_SESSION) && !empty($_SESSION['dyn_layout_file'])) clean_string($_SESSION['dyn_layout_file'], "PATH_NO_URL");
1843 if (!empty($_GET) && !empty($_GET['from'])) clean_string($_GET['from']);
1844 if (!empty($_GET) && !empty($_GET['gmto'])) clean_string($_GET['gmto'], "NUMBER");
1845 if (!empty($_GET) && !empty($_GET['case_number'])) clean_string($_GET['case_number'], "AUTO_INCREMENT");
1846 if (!empty($_GET) && !empty($_GET['bug_number'])) clean_string($_GET['bug_number'], "AUTO_INCREMENT");
1847 if (!empty($_GET) && !empty($_GET['quote_num'])) clean_string($_GET['quote_num'], "AUTO_INCREMENT");
1848 clean_superglobals('stamp', 'ALPHANUM'); // for vcr controls
1849 clean_superglobals('offset', 'ALPHANUM');
1850 clean_superglobals('return_action');
1851 clean_superglobals('return_module');
1856 * cleans the given key in superglobals $_GET, $_POST, $_REQUEST
1858 function clean_superglobals($key, $filter = 'STANDARD') {
1859 if(isset($_GET[$key])) clean_string($_GET[$key], $filter);
1860 if(isset($_POST[$key])) clean_string($_POST[$key], $filter);
1861 if(isset($_REQUEST[$key])) clean_string($_REQUEST[$key], $filter);
1864 function set_superglobals($key, $val){
1866 $_POST[$key] = $val;
1867 $_REQUEST[$key] = $val;
1870 // Works in conjunction with clean_string() to defeat SQL injection, file inclusion attacks, and XSS
1871 function clean_incoming_data() {
1872 global $sugar_config;
1874 if (get_magic_quotes_gpc() == 1) {
1875 $req = array_map("preprocess_param", $_REQUEST);
1876 $post = array_map("preprocess_param", $_POST);
1877 $get = array_map("preprocess_param", $_GET);
1880 $req = array_map("securexss", $_REQUEST);
1881 $post = array_map("securexss", $_POST);
1882 $get = array_map("securexss", $_GET);
1885 // PHP cannot stomp out superglobals reliably
1886 foreach($post as $k => $v) { $_POST[$k] = $v; }
1887 foreach($get as $k => $v) { $_GET[$k] = $v; }
1888 foreach($req as $k => $v) {
1890 //ensure the keys are safe as well
1893 // Any additional variables that need to be cleaned should be added here
1894 if (isset($_REQUEST['login_theme'])) clean_string($_REQUEST['login_theme']);
1895 if (isset($_REQUEST['login_module'])) clean_string($_REQUEST['login_module']);
1896 if (isset($_REQUEST['login_action'])) clean_string($_REQUEST['login_action']);
1897 if (isset($_REQUEST['login_language'])) clean_string($_REQUEST['login_language']);
1898 if (isset($_REQUEST['action'])) clean_string($_REQUEST['action']);
1899 if (isset($_REQUEST['module'])) clean_string($_REQUEST['module']);
1900 if (isset($_REQUEST['record'])) clean_string($_REQUEST['record'], 'STANDARDSPACE');
1901 if (isset($_SESSION['authenticated_user_theme'])) clean_string($_SESSION['authenticated_user_theme']);
1902 if (isset($_SESSION['authenticated_user_language'])) clean_string($_SESSION['authenticated_user_language']);
1903 if (isset($_REQUEST['language'])) clean_string($_REQUEST['language']);
1904 if (isset($sugar_config['default_theme'])) clean_string($sugar_config['default_theme']);
1905 if (isset($_REQUEST['offset'])) clean_string($_REQUEST['offset']);
1906 if (isset($_REQUEST['stamp'])) clean_string($_REQUEST['stamp']);
1908 if(isset($_REQUEST['lvso'])){
1909 set_superglobals('lvso', (strtolower($_REQUEST['lvso']) === 'desc')?'desc':'asc');
1911 // Clean "offset" and "order_by" parameters in URL
1912 foreach ($_REQUEST as $key => $val) {
1913 if (str_end($key, "_offset")) {
1914 clean_string($_REQUEST[$key], "ALPHANUM"); // keep this ALPHANUM for disable_count_query
1915 set_superglobals($key, $_REQUEST[$key]);
1917 elseif (str_end($key, "_ORDER_BY")) {
1918 clean_string($_REQUEST[$key], "SQL_COLUMN_LIST");
1919 set_superglobals($key, $_REQUEST[$key]);
1927 // Returns TRUE if $str begins with $begin
1928 function str_begin($str, $begin) {
1929 return (substr($str, 0, strlen($begin)) == $begin);
1932 // Returns TRUE if $str ends with $end
1933 function str_end($str, $end) {
1934 return (substr($str, strlen($str) - strlen($end)) == $end);
1937 function securexss($value) {
1938 if(is_array($value)){
1940 foreach($value as $key=>$val){
1941 $new[$key] = securexss($val);
1945 static $xss_cleanup= array('"' =>'"', "'" => ''' , '<' =>'<' , '>'=>'>');
1946 $value = preg_replace(array('/javascript:/i', '/\0/'), array('java script:', ''), $value);
1947 $value = preg_replace('/javascript:/i', 'java script:', $value);
1948 return str_replace(array_keys($xss_cleanup), array_values($xss_cleanup), $value);
1951 function securexsskey($value, $die=true){
1952 global $sugar_config;
1954 preg_match("/[\'\"\<\>]/", $value, $matches);
1955 if(!empty($matches)){
1957 die("Bad data passed in; <a href=\"{$sugar_config['site_url']}\">Return to Home</a>");
1959 unset($_REQUEST[$value]);
1960 unset($_POST[$value]);
1961 unset($_GET[$value]);
1966 function preprocess_param($value){
1967 if(is_string($value)){
1968 if(get_magic_quotes_gpc() == 1){
1969 $value = stripslashes($value);
1972 $value = securexss($value);
1981 function set_register_value($category, $name, $value){
1982 return sugar_cache_put("{$category}:{$name}", $value);
1985 function get_register_value($category,$name){
1986 return sugar_cache_retrieve("{$category}:{$name}");
1989 // this function cleans id's when being imported
1990 function convert_id($string)
1992 return preg_replace_callback( '|[^A-Za-z0-9\-]|',
1994 // single quotes are essential here,
1995 // or alternative escape all $ as \$
1997 'return ord($matches[0]);'
2002 * @deprecated use SugarTheme::getImage()
2004 function get_image($image,$other_attributes,$width="",$height="")
2006 return SugarThemeRegistry::current()->getImage(basename($image),
2008 empty($width) ? null : $width,
2009 empty($height) ? null : $height
2013 * @deprecated use SugarTheme::getImageURL()
2015 function getImagePath($image_name)
2017 return SugarThemeRegistry::current()->getImageURL($image_name);
2020 function getWebPath($relative_path){
2021 //if it has a :// then it isn't a relative path
2022 if(substr_count($relative_path, '://') > 0) return $relative_path;
2023 if(defined('TEMPLATE_URL'))$relative_path = SugarTemplateUtilities::getWebPath($relative_path);
2024 return $relative_path;
2027 function getJSPath($relative_path, $additional_attrs=''){
2028 if(defined('TEMPLATE_URL'))$relative_path = SugarTemplateUtilities::getWebPath($relative_path);
2029 if(empty($GLOBALS['sugar_config']['js_custom_version']))$GLOBALS['sugar_config']['js_custom_version'] = 1;
2030 $js_version_key = isset($GLOBALS['js_version_key'])?$GLOBALS['js_version_key']:'';
2031 $path = $relative_path . '?s=' . $js_version_key . '&c=' . $GLOBALS['sugar_config']['js_custom_version'] ;
2032 if ( inDeveloperMode() ) $path .= '&developerMode='.mt_rand();
2033 if(!empty($additonal_attrs)) $path .= '&' . $additional_attrs;
2037 function getSWFPath($relative_path, $additional_params=''){
2038 $path = $relative_path;
2039 if (!empty($additional_params)){
2040 $path .= '?' . $additional_params;
2042 if (defined('TEMPLATE_URL')){
2043 $path = TEMPLATE_URL . '/' . $path;
2052 function getSQLDate($date_str)
2054 if (preg_match('/^(\d{1,2})-(\d{1,2})-(\d{4})$/',$date_str,$match))
2056 if ( strlen($match[2]) == 1)
2058 $match[2] = "0".$match[2];
2060 if ( strlen($match[1]) == 1)
2062 $match[1] = "0".$match[1];
2064 return "{$match[3]}-{$match[1]}-{$match[2]}";
2066 else if (preg_match('/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/',$date_str,$match))
2068 if ( strlen($match[2]) == 1)
2070 $match[2] = "0".$match[2];
2072 if ( strlen($match[1]) == 1)
2074 $match[1] = "0".$match[1];
2076 return "{$match[3]}-{$match[1]}-{$match[2]}";
2084 function clone_history(&$db, $from_id,$to_id, $to_type)
2089 require_once('include/upload_file.php');
2090 $tables = array('calls'=>'Call', 'meetings'=>'Meeting', 'notes'=>'Note', 'tasks'=>'Task');
2092 $location=array('Email'=>"modules/Emails/Email.php",
2093 'Call'=>"modules/Calls/Call.php",
2094 'Meeting'=>"modules/Meetings/Meeting.php",
2095 'Note'=>"modules/Notes/Note.php",
2096 'Tasks'=>"modules/Tasks/Task.php",
2100 foreach($tables as $table=>$bean_class)
2103 if (!class_exists($bean_class))
2105 require_once($location[$bean_class]);
2108 $bProcessingNotes=false;
2109 if ($table=='notes')
2111 $bProcessingNotes=true;
2113 $query = "SELECT id FROM $table WHERE parent_id='$from_id'";
2114 $results = $db->query($query);
2115 while($row = $db->fetchByAssoc($results))
2117 //retrieve existing record.
2118 $bean= new $bean_class();
2119 $bean->retrieve($row['id']);
2120 //process for new instance.
2121 if ($bProcessingNotes)
2123 $old_note_id=$row['id'];
2124 $old_filename=$bean->filename;
2127 $bean->parent_id=$to_id;
2128 $bean->parent_type=$to_type;
2129 if ($to_type=='Contacts' and in_array('contact_id',$bean->column_fields))
2131 $bean->contact_id=$to_id;
2133 $bean->update_date_modified = false;
2134 $bean->update_modified_by = false;
2135 if(isset($bean->date_modified))
2136 $bean->date_modified = $timedate->to_db($bean->date_modified);
2137 if(isset($bean->date_entered))
2138 $bean->date_entered = $timedate->to_db($bean->date_entered);
2140 $new_id=$bean->save();
2142 //duplicate the file now. for notes.
2143 if ($bProcessingNotes && !empty($old_filename))
2145 UploadFile::duplicate_file($old_note_id,$new_id,$old_filename);
2147 //reset the values needed for attachment duplication.
2154 function values_to_keys($array)
2156 $new_array = array();
2157 if(!is_array($array))
2161 foreach($array as $arr){
2162 $new_array[$arr] = $arr;
2167 function clone_relationship(&$db, $tables = array(), $from_column, $from_id, $to_id)
2169 foreach($tables as $table)
2172 if ($table == 'emails_beans') {
2173 $query = "SELECT * FROM $table WHERE $from_column='$from_id' and bean_module='Leads'";
2175 $query = "SELECT * FROM $table WHERE $from_column='$from_id'";
2177 $results = $db->query($query);
2178 while($row = $db->fetchByAssoc($results))
2180 $query = "INSERT INTO $table ";
2183 $row[$from_column] = $to_id;
2184 $row['id'] = create_guid();
2185 if ($table=='emails_beans') {
2186 $row['bean_module'] =='Contacts';
2189 foreach($row as $name=>$value)
2195 $values .= "'$value'";
2198 $names .= ', '. $name;
2199 $values .= ", '$value'";
2202 $query .= "($names) VALUES ($values)";
2208 function get_unlinked_email_query($type, $bean) {
2209 global $current_user;
2211 $return_array['select']='SELECT emails.id ';
2212 $return_array['from']='FROM emails ';
2213 $return_array['where']="";
2214 $return_array['join'] = " JOIN (select distinct email_id from emails_email_addr_rel eear
2216 join email_addr_bean_rel eabr on eabr.bean_id ='$bean->id' and eabr.bean_module = '$bean->module_dir' and
2217 eabr.email_address_id = eear.email_address_id and eabr.deleted=0
2218 where eear.deleted=0 and eear.email_id not in
2219 (select eb.email_id from emails_beans eb where eb.bean_module ='$bean->module_dir' and eb.bean_id = '$bean->id')
2220 ) derivedemails on derivedemails.email_id = emails.id";
2221 $return_array['join_tables'][0] = '';
2223 if (isset($type) and isset($type['return_as_array']) and $type['return_as_array']==true) {
2224 return $return_array;
2227 return $return_array['select'] . $return_array['from'] . $return_array['where'];
2231 * Check to see if the number is empty or non-zero
2235 function number_empty($value)
2237 return empty($value) && $value != '0';
2240 function get_bean_select_array($add_blank=true, $bean_name, $display_columns, $where='', $order_by='', $blank_is_none=false)
2243 require_once($beanFiles[$bean_name]);
2244 $focus = new $bean_name();
2245 $user_array = array();
2246 $user_array = get_register_value('select_array',$bean_name. $display_columns. $where . $order_by);
2250 $db = DBManagerFactory::getInstance();
2251 $temp_result = Array();
2252 $query = "SELECT {$focus->table_name}.id, {$display_columns} as display from {$focus->table_name} ";
2256 $query .= $where." AND ";
2259 $query .= " {$focus->table_name}.deleted=0";
2261 if ( $order_by != '')
2263 $query .= " order by {$focus->table_name}.{$order_by}";
2266 $GLOBALS['log']->debug("get_user_array query: $query");
2267 $result = $db->query($query, true, "Error filling in user array: ");
2269 if ($add_blank==true){
2270 // Add in a blank row
2271 if($blank_is_none == true) { // set 'blank row' to "--None--"
2272 global $app_strings;
2273 $temp_result[''] = $app_strings['LBL_NONE'];
2275 $temp_result[''] = '';
2279 // Get the id and the name.
2280 while($row = $db->fetchByAssoc($result))
2282 $temp_result[$row['id']] = $row['display'];
2285 $user_array = $temp_result;
2286 set_register_value('select_array',$bean_name. $display_columns. $where . $order_by,$temp_result);
2295 * @param unknown_type $listArray
2297 // function parse_list_modules
2298 // searches a list for items in a user's allowed tabs and returns an array that removes unallowed tabs from list
2299 function parse_list_modules(&$listArray)
2301 global $modListHeader;
2302 $returnArray = array();
2304 foreach($listArray as $optionName => $optionVal)
2306 if(array_key_exists($optionName, $modListHeader))
2308 $returnArray[$optionName] = $optionVal;
2311 // special case for projects
2312 if(array_key_exists('Project', $modListHeader))
2314 $returnArray['ProjectTask'] = $listArray['ProjectTask'];
2317 $acldenied = ACLController::disabledModuleList($listArray,false);
2318 foreach($acldenied as $denied){
2319 unset($returnArray[$denied]);
2321 asort($returnArray);
2323 return $returnArray;
2326 function display_notice($msg = false){
2327 global $error_notice;
2328 //no error notice - lets just display the error to the user
2329 if(!isset($error_notice)){
2330 echo '<br>'.$msg . '<br>';
2332 $error_notice .= $msg . '<br>';
2336 /* checks if it is a number that atleast has the plus at the beggining
2338 function skype_formatted($number){
2339 //kbrill - BUG #15375
2340 if(isset($_REQUEST['action']) && $_REQUEST['action']=="Popup") {
2343 return substr($number, 0, 1) == '+' || substr($number, 0, 2) == '00' || substr($number, 0, 3) == '011';
2345 // return substr($number, 0, 1) == '+' || substr($number, 0, 2) == '00' || substr($number, 0, 2) == '011';
2348 function format_skype($number) {
2349 return preg_replace('/[^\+0-9]/','',$number);
2352 function insert_charset_header() {
2353 header('Content-Type: text/html; charset=UTF-8');
2356 function getCurrentURL()
2359 if(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on')
2364 $href.= "//".$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME'].'?'.$_SERVER['QUERY_STRING'];
2368 function javascript_escape($str) {
2371 for($i = 0; $i < strlen($str); $i++) {
2373 if(ord(substr($str, $i, 1))==10){
2375 }elseif(ord(substr($str, $i, 1))==13){
2379 $new_str .= $str{$i};
2383 $new_str = str_replace("'", "\\'", $new_str);
2388 function js_escape($str, $keep=true){
2389 $str = html_entity_decode(str_replace("\\", "", $str), ENT_QUOTES);
2392 $str = javascript_escape($str);
2395 $str = str_replace("'", " ", $str);
2396 $str = str_replace('"', " ", $str);
2401 //end function js_escape
2404 function br2nl($str) {
2405 $regex = "#<[^>]+br.+?>#i";
2406 preg_match_all($regex, $str, $matches);
2408 foreach($matches[0] as $match) {
2409 $str = str_replace($match, "<br>", $str);
2412 $brs = array('<br>','<br/>', '<br />');
2413 $str = str_replace("\r\n", "\n", $str); // make from windows-returns, *nix-returns
2414 $str = str_replace("\n\r", "\n", $str); // make from windows-returns, *nix-returns
2415 $str = str_replace("\r", "\n", $str); // make from windows-returns, *nix-returns
2416 $str = str_ireplace($brs, "\n", $str); // to retrieve it
2422 * Private helper function for displaying the contents of a given variable.
2423 * This function is only intended to be used for SugarCRM internal development.
2424 * The ppd stands for Pre Print Die.
2426 function _ppd($mixed)
2432 * Private helper function for displaying the contents of a given variable in
2433 * the Logger. This function is only intended to be used for SugarCRM internal
2434 * development. The pp stands for Pre Print.
2435 * @param $mixed var to print_r()
2436 * @param $die boolean end script flow
2437 * @param $displayStackTrace also show stack trace
2439 function _ppl($mixed, $die=false, $displayStackTrace=false, $loglevel="fatal") {
2443 * private helper function to quickly show the major, direct, field attributes of a given bean.
2444 * The ppf stands for Pre[formatted] Print Focus [object]
2445 * @param object bean The focus bean
2447 function _ppf($bean, $die=false) {
2453 * Private helper function for displaying the contents of a given variable.
2454 * This function is only intended to be used for SugarCRM internal development.
2455 * The pp stands for Pre Print.
2457 function _pp($mixed)
2463 $stack = debug_backtrace();
2464 if (!empty($stack) && isset($stack[0]['file']) && $stack[0]['line']) {
2465 echo "\n\n _pp caller, file: " . $stack[0]['file']. ' line#: ' .$stack[0]['line'];
2471 * Private helper function for displaying the contents of a given variable.
2472 * This function is only intended to be used for SugarCRM internal development.
2473 * The pp stands for Pre Print.
2475 function _pstack_trace($mixed=NULL)
2480 * Private helper function for displaying the contents of a given variable.
2481 * This function is only intended to be used for SugarCRM internal development.
2482 * The pp stands for Pre Print Trace.
2484 function _ppt($mixed, $textOnly=false)
2489 * Private helper function for displaying the contents of a given variable.
2490 * This function is only intended to be used for SugarCRM internal development.
2491 * The pp stands for Pre Print Trace Die.
2493 function _pptd($mixed)
2498 * Private helper function for decoding javascript UTF8
2499 * This function is only intended to be used for SugarCRM internal development.
2501 function decodeJavascriptUTF8($str) {
2505 * Will check if a given PHP version string is supported (tested on this ver),
2506 * unsupported (results unknown), or invalid (something will break on this
2507 * ver). Do not pass in any pararameter to default to a check against the
2508 * current environment's PHP version.
2510 * @return 1 implies supported, 0 implies unsupported, -1 implies invalid
2512 function check_php_version($sys_php_version = '') {
2513 $sys_php_version = empty($sys_php_version) ? constant('PHP_VERSION') : $sys_php_version;
2514 // versions below $min_considered_php_version considered invalid by default,
2515 // versions equal to or above this ver will be considered depending
2516 // on the rules that follow
2517 $min_considered_php_version = '5.2.1';
2519 // only the supported versions,
2520 // should be mutually exclusive with $invalid_php_versions
2521 $supported_php_versions = array (
2522 '5.2.1', '5.2.2', '5.2.3', '5.2.4', '5.2.5', '5.2.6', '5.2.8', '5.3.0'
2524 //Find out what Database the system is using.
2525 global $sugar_config;
2527 if (isset($_REQUEST['setup_db_type'])) {
2528 $dbType = $_REQUEST['setup_db_type'];
2529 } else if (isset ($sugar_config['dbconfig']) && isset ($sugar_config['dbconfig']['db_type'])) {
2530 $dbType = $sugar_config['dbconfig']['db_type'];
2533 // invalid versions above the $min_considered_php_version,
2534 // should be mutually exclusive with $supported_php_versions
2536 // SugarCRM prohibits install on PHP 5.2.7 on all platforms
2537 $invalid_php_versions = array('5.2.7');
2539 // default unsupported
2542 // versions below $min_considered_php_version are invalid
2543 if(1 == version_compare($sys_php_version, $min_considered_php_version, '<')) {
2547 // supported version check overrides default unsupported
2548 foreach($supported_php_versions as $ver) {
2549 if(1 == version_compare($sys_php_version, $ver, 'eq') || strpos($sys_php_version,$ver) !== false) {
2555 // invalid version check overrides default unsupported
2556 foreach($invalid_php_versions as $ver) {
2557 if(1 == version_compare($sys_php_version, $ver, 'eq') && strpos($sys_php_version,$ver) !== false) {
2563 //allow a redhat distro to install, regardless of version. We are assuming the redhat naming convention is followed
2564 //and the php version contains 'rh' characters
2565 if(strpos($sys_php_version, 'rh') !== false) {
2573 * Will check if a given IIS version string is supported (tested on this ver),
2574 * unsupported (results unknown), or invalid (something will break on this
2577 * @return 1 implies supported, 0 implies unsupported, -1 implies invalid
2579 function check_iis_version($sys_iis_version = '') {
2581 $server_software = $_SERVER["SERVER_SOFTWARE"];
2583 if(strpos($server_software,'Microsoft-IIS') !== false && preg_match_all("/^.*\/(\d+\.?\d*)$/", $server_software, $out))
2584 $iis_version = $out[1][0];
2586 $sys_iis_version = empty($sys_iis_version) ? $iis_version : $sys_iis_version;
2588 // versions below $min_considered_iis_version considered invalid by default,
2589 // versions equal to or above this ver will be considered depending
2590 // on the rules that follow
2591 $min_considered_iis_version = '6.0';
2593 // only the supported versions,
2594 // should be mutually exclusive with $invalid_iis_versions
2595 $supported_iis_versions = array ('6.0', '7.0',);
2596 $unsupported_iis_versions = array();
2597 $invalid_iis_versions = array('5.0',);
2599 // default unsupported
2602 // versions below $min_considered_iis_version are invalid
2603 if(1 == version_compare($sys_iis_version, $min_considered_iis_version, '<')) {
2607 // supported version check overrides default unsupported
2608 foreach($supported_iis_versions as $ver) {
2609 if(1 == version_compare($sys_iis_version, $ver, 'eq') || strpos($sys_iis_version,$ver) !== false) {
2615 // unsupported version check overrides default unsupported
2616 foreach($unsupported_iis_versions as $ver) {
2617 if(1 == version_compare($sys_iis_version, $ver, 'eq') && strpos($sys_iis_version,$ver) !== false) {
2623 // invalid version check overrides default unsupported
2624 foreach($invalid_iis_versions as $ver) {
2625 if(1 == version_compare($sys_iis_version, $ver, 'eq') && strpos($sys_iis_version,$ver) !== false) {
2634 function pre_login_check(){
2635 global $action, $login_error;
2636 if(!empty($action)&& $action == 'Login'){
2638 if(!empty($login_error)){
2639 $login_error = htmlentities($login_error);
2640 $login_error = str_replace(array("<pre>","</pre>","\r\n", "\n"), "<br>", $login_error);
2641 $_SESSION['login_error'] = $login_error;
2643 function set_focus() {}
2644 if(document.getElementById("post_error")) {
2645 document.getElementById("post_error").innerHTML="'. $login_error. '";
2646 document.getElementById("cant_login").value=1;
2647 document.getElementById("login_button").disabled = true;
2648 document.getElementById("user_name").disabled = true;
2649 //document.getElementById("user_password").disabled = true;
2658 function sugar_cleanup($exit = false) {
2659 static $called = false;
2662 set_include_path(realpath(dirname(__FILE__) . '/..') . PATH_SEPARATOR . get_include_path());
2663 chdir(realpath(dirname(__FILE__) . '/..'));
2664 global $sugar_config;
2665 require_once('include/utils/LogicHook.php');
2666 LogicHook::initialize();
2667 $GLOBALS['logic_hook']->call_custom_logic('', 'server_round_trip');
2669 //added this check to avoid errors during install.
2670 if (empty($sugar_config['dbconfig'])) {
2671 if ($exit) exit; else return;
2674 if (!class_exists('Tracker', true)) {
2675 require_once 'modules/Trackers/Tracker.php';
2678 // Now write the cached tracker_queries
2679 if(!empty($GLOBALS['savePreferencesToDB']) && $GLOBALS['savePreferencesToDB']) {
2680 if ( isset($GLOBALS['current_user']) && $GLOBALS['current_user'] instanceOf User )
2681 $GLOBALS['current_user']->savePreferencesToDB();
2684 //check to see if this is not an ajax call AND the user preference error flag is set
2686 (isset($_SESSION['USER_PREFRENCE_ERRORS']) && $_SESSION['USER_PREFRENCE_ERRORS'])
2687 && ($_REQUEST['action']!='modulelistmenu' && $_REQUEST['action']!='DynamicAction')
2688 && (empty($_REQUEST['to_pdf']) || !$_REQUEST['to_pdf'] )
2689 && (empty($_REQUEST['sugar_body_only']) || !$_REQUEST['sugar_body_only'] )
2692 global $app_strings;
2693 //this is not an ajax call and the user preference error flag is set, so reset the flag and print js to flash message
2694 $err_mess = $app_strings['ERROR_USER_PREFS'];
2695 $_SESSION['USER_PREFRENCE_ERRORS'] = false;
2698 ajaxStatus.flashStatus('$err_mess',7000);
2704 if(class_exists('DBManagerFactory')) {
2705 $db = DBManagerFactory::getInstance();
2713 register_shutdown_function('sugar_cleanup');
2717 check_logic_hook - checks to see if your custom logic is in the logic file
2718 if not, it will add it. If the file isn't built yet, it will create the file
2721 function check_logic_hook_file($module_name, $event, $action_array){
2722 require_once('include/utils/logic_utils.php');
2725 if(file_exists("custom/modules/$module_name/logic_hooks.php")){
2727 $hook_array = get_hook_array($module_name);
2729 if(check_existing_element($hook_array, $event, $action_array)==true){
2730 //the hook at hand is present, so do nothing
2735 if(!empty($hook_array[$event]))
2737 $logic_count = count($hook_array[$event]);
2740 if($action_array[0]==""){
2741 $action_array[0] = $logic_count + 1;
2743 $hook_array[$event][] = $action_array;
2746 //end if the file exists already
2749 if($action_array[0]==""){
2750 $action_array[0] = 1;
2752 $hook_array = array();
2753 $hook_array[$event][] = $action_array;
2754 //end if else file exists already
2756 if($add_logic == true){
2758 //reorder array by element[0]
2759 //$hook_array = reorder_array($hook_array, $event);
2760 //!!!Finish this above TODO
2762 $new_contents = replace_or_add_logic_type($hook_array);
2763 write_logic_file($module_name, $new_contents);
2765 //end if add_element is true
2768 //end function check_logic_hook_file
2771 function remove_logic_hook($module_name, $event, $action_array) {
2772 require_once('include/utils/logic_utils.php');
2775 if(file_exists("custom/modules/".$module_name."/logic_hooks.php")){
2776 // The file exists, let's make sure the hook is there
2777 $hook_array = get_hook_array($module_name);
2779 if(check_existing_element($hook_array, $event, $action_array)==true){
2780 // The hook is there, time to take it out.
2782 foreach ( $hook_array[$event] as $i => $hook ) {
2783 // We don't do a full comparison below just in case the filename changes
2784 if ( $hook[0] == $action_array[0]
2785 && $hook[1] == $action_array[1]
2786 && $hook[3] == $action_array[3]
2787 && $hook[4] == $action_array[4] ) {
2788 unset($hook_array[$event][$i]);
2792 $new_contents = replace_or_add_logic_type($hook_array);
2793 write_logic_file($module_name, $new_contents);
2799 function display_stack_trace($textOnly=false){
2801 $stack = debug_backtrace();
2803 echo "\n\n display_stack_trace caller, file: " . $stack[0]['file']. ' line#: ' .$stack[0]['line'];
2811 foreach($stack as $item) {
2817 if(isset($item['file']))
2818 $file = $item['file'];
2819 if(isset($item['class']))
2820 $class = $item['class'];
2821 if(isset($item['line']))
2822 $line = $item['line'];
2823 if(isset($item['function']))
2824 $function = $item['function'];
2828 $out .= '<font color="black"><b>';
2834 $out .= '</b></font><font color="blue">';
2837 $out .= "[L:{$line}]";
2840 $out .= '</font><font color="red">';
2843 $out .= "({$class}:{$function})";
2846 $out .= '</font><br>';
2858 function StackTraceErrorHandler($errno, $errstr, $errfile,$errline, $errcontext) {
2859 $error_msg = " $errstr occured in <b>$errfile</b> on line $errline [" . date("Y-m-d H:i:s") . ']';
2860 $halt_script = true;
2862 case 2048: return; //depricated we have lots of these ignore them
2865 if ( error_reporting() & E_NOTICE ) {
2866 $halt_script = false;
2872 case E_USER_WARNING:
2873 case E_COMPILE_WARNING:
2874 case E_CORE_WARNING:
2877 $halt_script = false;
2882 case E_COMPILE_ERROR:
2886 $type = "Fatal Error";
2891 $type = "Parse Error";
2895 //don't know what it is might not be so bad
2896 $halt_script = false;
2897 $type = "Unknown Error ($errno)";
2900 $error_msg = '<b>'.$type.'</b>:' . $error_msg;
2902 display_stack_trace();
2912 if(isset($sugar_config['stack_trace_errors']) && $sugar_config['stack_trace_errors']){
2914 set_error_handler('StackTraceErrorHandler');
2916 function get_sub_cookies($name){
2918 if(isset($_COOKIE[$name])){
2919 $subs = explode('#', $_COOKIE[$name]);
2920 foreach($subs as $cookie){
2921 if(!empty($cookie)){
2922 $cookie = explode('=', $cookie);
2924 $cookies[$cookie[0]] = $cookie[1];
2933 function mark_delete_components($sub_object_array, $run_second_level=false, $sub_sub_array=""){
2935 if(!empty($sub_object_array)){
2937 foreach($sub_object_array as $sub_object){
2939 //run_second level is set to true if you need to remove sub-sub components
2940 if($run_second_level==true){
2942 mark_delete_components($sub_object->get_linked_beans($sub_sub_array['rel_field'],$sub_sub_array['rel_module']));
2944 //end if run_second_level is true
2946 $sub_object->mark_deleted($sub_object->id);
2947 //end foreach sub component
2949 //end if this is not empty
2952 //end function mark_delete_components
2956 * For translating the php.ini memory values into bytes. e.g. input value of '8M' will return 8388608.
2958 function return_bytes($val)
2961 $last = strtolower($val{strlen($val)-1});
2965 // The 'G' modifier is available since PHP 5.1.0
2978 * Adds the href HTML tags around any URL in the $string
2980 function url2html($string) {
2982 $return_string = preg_replace('/(\w+:\/\/)(\S+)/', ' <a href="\\1\\2" target="_new" style="font-weight: normal;">\\1\\2</a>', $string);
2983 return $return_string;
2985 // End customization by Julian
2988 * tries to determine whether the Host machine is a Windows machine
2990 function is_windows() {
2991 static $is_windows = null;
2992 if (!isset($is_windows)) {
2993 $is_windows = strtoupper(substr(PHP_OS, 0, 3)) == 'WIN';
2999 * equivalent for windows filesystem for PHP's is_writable()
3000 * @param string file Full path to the file/dir
3001 * @return bool true if writable
3003 function is_writable_windows($file) {
3004 if($file{strlen($file)-1}=='/') {
3005 return is_writable_windows($file.uniqid(mt_rand()).'.tmp');
3008 // the assumption here is that Windows has an inherited permissions scheme
3009 // any file that is a descendant of an unwritable directory will inherit
3010 // that property and will trigger a failure below.
3015 $file = str_replace("/", '\\', $file);
3017 if(file_exists($file)) {
3018 if (!($f = @sugar_fopen($file, 'r+')))
3024 if(!($f = @sugar_fopen($file, 'w')))
3033 * best guesses Timezone based on webserver's TZ settings
3035 function lookupTimezone($userOffset = 0)
3037 return TimeDate::guessTimezone($userOffset);
3040 function convert_module_to_singular($module_array){
3043 foreach($module_array as $key => $value){
3044 if(!empty($beanList[$value])) $module_array[$key] = $beanList[$value];
3046 if($value=="Cases") {
3047 $module_array[$key] = "Case";
3049 if($key=="projecttask"){
3050 $module_array['ProjectTask'] = "Project Task";
3051 unset($module_array[$key]);
3055 return $module_array;
3057 //end function convert_module_to_singular
3061 * Given the bean_name which may be plural or singular return the singular
3062 * bean_name. This is important when you need to include files.
3064 function get_singular_bean_name($bean_name){
3065 global $beanFiles, $beanList;
3066 if(array_key_exists($bean_name, $beanList)){
3067 return $beanList[$bean_name];
3075 * Given the potential module name (singular name, renamed module name)
3076 * Return the real internal module name.
3078 function get_module_from_singular($singular) {
3080 // find the internal module name for a singular name
3081 if (isset($GLOBALS['app_list_strings']['moduleListSingular'])) {
3083 $singular_modules = $GLOBALS['app_list_strings']['moduleListSingular'];
3085 foreach ($singular_modules as $mod_name=>$sin_name) {
3086 if ($singular == $sin_name and $mod_name != $sin_name) {
3092 // find the internal module name for a renamed module
3093 if (isset($GLOBALS['app_list_strings']['moduleList'])) {
3095 $moduleList = $GLOBALS['app_list_strings']['moduleList'];
3097 foreach ($moduleList as $mod_name=>$name) {
3098 if ($singular == $name and $mod_name != $name) {
3104 // if it's not a singular name, nor a renamed name, return the original value
3108 function get_label($label_tag, $temp_module_strings){
3109 global $app_strings;
3110 if(!empty($temp_module_strings[$label_tag])){
3112 $label_name = $temp_module_strings[$label_tag];
3114 if(!empty($app_strings[$label_tag])){
3115 $label_name = $app_strings[$label_tag];
3117 $label_name = $label_tag;
3122 //end function get_label
3126 function search_filter_rel_info(& $focus, $tar_rel_module, $relationship_name){
3128 $rel_list = array();
3130 foreach($focus->relationship_fields as $rel_key => $rel_value){
3131 if($rel_value == $relationship_name){
3132 $temp_bean = get_module_info($tar_rel_module);
3133 // echo $focus->$rel_key;
3134 $temp_bean->retrieve($focus->$rel_key);
3135 if($temp_bean->id!=""){
3137 $rel_list[] = $temp_bean;
3143 foreach($focus->field_defs as $field_name => $field_def){
3144 //Check if the relationship_name matches a "relate" field
3145 if(!empty($field_def['type']) && $field_def['type'] == 'relate'
3146 && !empty($field_def['id_name']) && !empty($focus->field_defs[$field_def['id_name']])
3147 && !empty($focus->field_defs[$field_def['id_name']]['relationship'])
3148 && $focus->field_defs[$field_def['id_name']]['relationship'] == $relationship_name)
3150 $temp_bean = get_module_info($tar_rel_module);
3151 // echo $focus->$field_def['id_name'];
3152 $temp_bean->retrieve($focus->$field_def['id_name']);
3153 if($temp_bean->id!=""){
3155 $rel_list[] = $temp_bean;
3158 //Check if the relationship_name matches a "link" in a relate field
3159 } else if(!empty($rel_value['link']) && !empty($rel_value['id_name']) && $rel_value['link'] == $relationship_name){
3160 $temp_bean = get_module_info($tar_rel_module);
3161 // echo $focus->$rel_value['id_name'];
3162 $temp_bean->retrieve($focus->$rel_value['id_name']);
3163 if($temp_bean->id!=""){
3165 $rel_list[] = $temp_bean;
3171 // special case for unlisted parent-type relationships
3172 if($focus->parent_type == $tar_rel_module && !empty($focus->parent_id)) {
3173 $temp_bean = get_module_info($tar_rel_module);
3174 $temp_bean->retrieve($focus->parent_id);
3175 if($temp_bean->id!=""){
3176 $rel_list[] = $temp_bean;
3183 //end function search_filter_rel_info
3186 function get_module_info($module_name){
3190 //Get dictionary and focus data for module
3191 $vardef_name = $beanList[$module_name];
3193 if($vardef_name=="aCase"){
3194 $class_name = "Case";
3196 $class_name = $vardef_name;
3199 if(!file_exists('modules/'. $module_name . '/'.$class_name.'.php')){
3203 include_once('modules/'. $module_name . '/'.$class_name.'.php');
3205 $module_bean = new $vardef_name();
3206 return $module_bean;
3207 //end function get_module_table
3211 * In order to have one place to obtain the proper object name. aCase for example causes issues throughout the application.
3213 * @param string $moduleName
3215 function get_valid_bean_name($module_name){
3218 $vardef_name = $beanList[$module_name];
3219 if($vardef_name=="aCase"){
3220 $bean_name = "Case";
3222 $bean_name = $vardef_name;
3229 function checkAuthUserStatus(){
3236 * This function returns an array of phpinfo() results that can be parsed and
3237 * used to figure out what version we run, what modules are compiled in, etc.
3238 * @param $level int info level constant (1,2,4,8...64);
3239 * @return $returnInfo array array of info about the PHP environment
3240 * @author original by "code at adspeed dot com" Fron php.net
3241 * @author customized for Sugar by Chris N.
3243 function getPhpInfo($level=-1) {
3244 /** Name (constant) Value Description
3245 INFO_GENERAL 1 The configuration line, php.ini location, build date, Web Server, System and more.
3246 INFO_CREDITS 2 PHP Credits. See also phpcredits().
3247 INFO_CONFIGURATION 4 Current Local and Master values for PHP directives. See also ini_get().
3248 INFO_MODULES 8 Loaded modules and their respective settings. See also get_loaded_extensions().
3249 INFO_ENVIRONMENT 16 Environment Variable information that's also available in $_ENV.
3250 INFO_VARIABLES 32 Shows all predefined variables from EGPCS (Environment, GET, POST, Cookie, Server).
3251 INFO_LICENSE 64 PHP License information. See also the license FAQ.
3252 INFO_ALL -1 Shows all of the above. This is the default value.
3256 $phpinfo = ob_get_contents();
3259 $phpinfo = strip_tags($phpinfo,'<h1><h2><th><td>');
3260 $phpinfo = preg_replace('/<th[^>]*>([^<]+)<\/th>/',"<info>\\1</info>",$phpinfo);
3261 $phpinfo = preg_replace('/<td[^>]*>([^<]+)<\/td>/',"<info>\\1</info>",$phpinfo);
3262 $parsedInfo = preg_split('/(<h.?>[^<]+<\/h.>)/', $phpinfo, -1, PREG_SPLIT_DELIM_CAPTURE);
3265 $returnInfo = array();
3267 if(preg_match('/<h1 class\=\"p\">PHP Version ([^<]+)<\/h1>/', $phpinfo, $version)) {
3268 $returnInfo['PHP Version'] = $version[1];
3272 for ($i=1; $i<count($parsedInfo); $i++) {
3273 if (preg_match('/<h.>([^<]+)<\/h.>/', $parsedInfo[$i], $match)) {
3274 $vName = trim($match[1]);
3275 $parsedInfo2 = explode("\n",$parsedInfo[$i+1]);
3277 foreach ($parsedInfo2 AS $vOne) {
3278 $vPat = '<info>([^<]+)<\/info>';
3279 $vPat3 = "/$vPat\s*$vPat\s*$vPat/";
3280 $vPat2 = "/$vPat\s*$vPat/";
3282 if (preg_match($vPat3,$vOne,$match)) { // 3cols
3283 $returnInfo[$vName][trim($match[1])] = array(trim($match[2]),trim($match[3]));
3284 } elseif (preg_match($vPat2,$vOne,$match)) { // 2cols
3285 $returnInfo[$vName][trim($match[1])] = trim($match[2]);
3297 * This function will take a string that has tokens like {0}, {1} and will replace
3298 * those tokens with the args provided
3299 * @param $format string to format
3300 * @param $args args to replace
3301 * @return $result a formatted string
3303 function string_format($format, $args){
3305 for($i = 0; $i < count($args); $i++){
3306 $result = str_replace('{'.$i.'}', $args[$i], $result);
3312 * Generate a string for displaying a unique identifier that is composed
3313 * of a system_id and number. This is use to allow us to generate quote
3314 * numbers using a DB auto-increment key from offline clients and still
3315 * have the number be unique (since it is modified by the system_id.
3317 * @param $num of bean
3318 * @param $system_id from system
3319 * @return $result a formatted string
3321 function format_number_display($num, $system_id){
3322 global $sugar_config;
3323 if(isset($num) && !empty($num)){
3324 $num=unformat_number($num);
3325 if(isset($system_id) && $system_id == 1){
3326 return sprintf("%d", $num);
3329 return sprintf("%d-%d", $num, $system_id);
3333 function checkLoginUserStatus(){
3337 * This function will take a number and system_id and format
3338 * @param $url URL containing host to append port
3339 * @param $port the port number - if '' is passed, no change to url
3340 * @return $resulturl the new URL with the port appended to the host
3342 function appendPortToHost($url, $port)
3346 // if no port, don't change the url
3349 $split = explode("/", $url);
3350 //check if it starts with http, in case they didn't include that in url
3351 if(str_begin($url, 'http'))
3353 //third index ($split[2]) will be the host
3354 $split[2] .= ":".$port;
3356 else // otherwise assumed to start with host name
3358 //first index ($split[0]) will be the host
3359 $split[0] .= ":".$port;
3362 $resulturl = implode("/", $split);
3369 * Singleton to return JSON object
3370 * @return JSON object
3372 function getJSONobj() {
3373 static $json = null;
3375 require_once('include/JSON.php');
3376 $json = new JSON(JSON_LOOSE_TYPE);
3381 require_once('include/utils/db_utils.php');
3384 * Set default php.ini settings for entry points
3386 function setPhpIniSettings() {
3388 // Bug 37579 - Comment out force enabling zlib.output_compression, since it can cause problems on certain hosts
3390 if(function_exists('gzclose') && headers_sent() == false) {
3391 ini_set('zlib.output_compression', 1);
3395 //nsingh: breaks zip/unzip functionality. Commenting out 4/23/08
3397 /*if(function_exists('mb_strlen')) {
3398 ini_set('mbstring.func_overload', 7);
3399 ini_set('mbstring.internal_encoding', 'UTF-8');
3403 // http://us3.php.net/manual/en/ref.pcre.php#ini.pcre.backtrack-limit
3404 // starting with 5.2.0, backtrack_limit breaks JSON decoding
3405 $backtrack_limit = ini_get('pcre.backtrack_limit');
3406 if(!empty($backtrack_limit)) {
3407 ini_set('pcre.backtrack_limit', '-1');
3411 if(ini_get("mssql.charset")) {
3412 ini_set('mssql.charset', "UTF-8");
3417 * like array_merge() but will handle array elements that are themselves arrays;
3418 * PHP's version just overwrites the element with the new one.
3420 * @internal Note that this function deviates from the internal array_merge()
3421 * functions in that it does does not treat numeric keys differently
3422 * than string keys. Additionally, it deviates from
3423 * array_merge_recursive() by not creating an array when like values
3426 * @param array gimp the array whose values will be overloaded
3427 * @param array dom the array whose values will pwn the gimp's
3428 * @return array beaten gimp
3430 function sugarArrayMerge($gimp, $dom) {
3431 if(is_array($gimp) && is_array($dom)) {
3432 foreach($dom as $domKey => $domVal) {
3433 if(array_key_exists($domKey, $gimp)) {
3434 if(is_array($domVal)) {
3436 foreach ( $domVal as $domArrKey => $domArrVal )
3437 $tempArr[$domArrKey] = $domArrVal;
3438 foreach ( $gimp[$domKey] as $gimpArrKey => $gimpArrVal )
3439 if ( !array_key_exists($gimpArrKey, $tempArr) )
3440 $tempArr[$gimpArrKey] = $gimpArrVal;
3441 $gimp[$domKey] = $tempArr;
3443 $gimp[$domKey] = $domVal;
3446 $gimp[$domKey] = $domVal;
3450 // if the passed value for gimp isn't an array, then return the $dom
3451 elseif(is_array($dom))
3458 * Similiar to sugarArrayMerge except arrays of N depth are merged.
3460 * @param array gimp the array whose values will be overloaded
3461 * @param array dom the array whose values will pwn the gimp's
3462 * @return array beaten gimp
3464 function sugarArrayMergeRecursive($gimp, $dom) {
3465 if(is_array($gimp) && is_array($dom)) {
3466 foreach($dom as $domKey => $domVal) {
3467 if(array_key_exists($domKey, $gimp)) {
3468 if(is_array($domVal) && is_array($gimp[$domKey])) {
3469 $gimp[$domKey] = sugarArrayMergeRecursive($gimp[$domKey], $domVal);
3471 $gimp[$domKey] = $domVal;
3474 $gimp[$domKey] = $domVal;
3478 // if the passed value for gimp isn't an array, then return the $dom
3479 elseif(is_array($dom))
3486 * finds the correctly working versions of PHP-JSON
3487 * @return bool True if NOT found or WRONG version
3489 function returnPhpJsonStatus() {
3490 if(function_exists('json_encode')) {
3491 $phpInfo = getPhpInfo(8);
3492 return version_compare($phpInfo['json']['json version'], '1.1.1', '<');
3494 return true; // not found
3499 * getTrackerSubstring
3501 * Returns a [number]-char or less string for the Tracker to display in the header
3502 * based on the tracker_max_display_length setting in config.php. If not set,
3503 * or invalid length, then defaults to 15 for COM editions, 30 for others.
3505 * @param string name field for a given Object
3506 * @return string [number]-char formatted string if length of string exceeds the max allowed
3508 function getTrackerSubstring($name) {
3509 static $max_tracker_item_length;
3512 $name = html_entity_decode($name, ENT_QUOTES, 'UTF-8');
3513 $strlen = function_exists('mb_strlen') ? mb_strlen($name) : strlen($name);
3515 global $sugar_config;
3517 if(!isset($max_tracker_item_length)) {
3518 if(isset($sugar_config['tracker_max_display_length'])) {
3519 $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;
3521 $max_tracker_item_length = 15;
3525 if($strlen > $max_tracker_item_length) {
3526 $chopped = function_exists('mb_substr') ? mb_substr($name, 0, $max_tracker_item_length, "UTF-8") : substr($name, 0, $max_tracker_item_length, "UTF-8");
3533 function generate_search_where ($field_list=array(),$values=array(),&$bean,$add_custom_fields=false,$module='') {
3534 $where_clauses= array();
3536 $table_name=$bean->object_name;
3537 foreach ($field_list[$module] as $field=>$parms) {
3538 if(isset($values[$field]) && $values[$field] != "") {
3540 if (!empty($parms['operator'])) {
3541 $operator=$parms['operator'];
3543 if (is_array($values[$field])) {
3546 foreach ($values[$field] as $key => $val) {
3547 if ($val != ' ' and $val != '') {
3548 if (!empty($field_value)) {
3551 $field_value .= "'".$GLOBALS['db']->quote($val)."'";
3555 $field_value=$GLOBALS['db']->quote($values[$field]);
3557 //set db_fields array.
3558 if (!isset($parms['db_field']) ) {
3559 $parms['db_field'] = array($field);
3561 if (isset($parms['my_items']) and $parms['my_items'] == true) {
3562 global $current_user;
3563 $field_value = $GLOBALS['db']->quote($current_user->id);
3569 if ($field_value != '') {
3571 foreach ($parms['db_field'] as $db_field) {
3572 if (strstr($db_field,'.')===false) {
3573 $db_field=$bean->table_name.".".$db_field;
3575 if ($GLOBALS['db']->dbType=='oci8' && isset($parms['query_type']) && $parms['query_type']=='case_insensitive') {
3576 $db_field='upper('.$db_field.")";
3577 $field_value=strtoupper($field_value);
3581 if (!empty($where)) {
3584 switch (strtolower($operator)) {
3586 $where .= $db_field . " like '".$field_value.$like_char."'";
3589 $where .= $db_field . " in (".$field_value.')';
3592 $where .= $db_field . " = '".$field_value ."'";
3597 if (!empty($where)) {
3599 array_push($where_clauses, '( '.$where.' )');
3601 array_push($where_clauses, $where);
3606 if ($add_custom_fields) {
3607 require_once('modules/DynamicFields/DynamicField.php');
3608 $bean->setupCustomFields($module);
3609 $bean->custom_fields->setWhereClauses($where_clauses);
3611 return $where_clauses;
3614 function add_quotes($str) {
3619 * This function will rebuild the config file
3620 * @param $sugar_config
3621 * @param $sugar_version
3622 * @return bool true if successful
3624 function rebuildConfigFile($sugar_config, $sugar_version) {
3625 // add defaults to missing values of in-memory sugar_config
3626 $sugar_config = sugarArrayMerge(get_sugar_config_defaults(), $sugar_config );
3627 // need to override version with default no matter what
3628 $sugar_config['sugar_version'] = $sugar_version;
3630 ksort( $sugar_config );
3632 if( write_array_to_file( "sugar_config", $sugar_config, "config.php" ) ){
3641 * getJavascriptSiteURL
3642 * This function returns a URL for the client javascript calls to access
3643 * the site. It uses $_SERVER['HTTP_REFERER'] in the event that Proxy servers
3644 * are used to access the site. Thus, the hostname in the URL returned may
3645 * not always match that of $sugar_config['site_url']. Basically, the
3646 * assumption is that however the user accessed the website is how they
3647 * will continue to with subsequent javascript requests. If the variable
3648 * $_SERVER['HTTP_REFERER'] is not found then we default to old algorithm.
3649 * @return $site_url The url used to refer to the website
3651 function getJavascriptSiteURL() {
3652 global $sugar_config;
3653 if(!empty($_SERVER['HTTP_REFERER'])) {
3654 $url = parse_url($_SERVER['HTTP_REFERER']);
3655 $replacement_url = $url['scheme']."://".$url['host'];
3656 if(!empty($url['port']))
3657 $replacement_url .= ':'.$url['port'];
3658 $site_url = preg_replace('/^http[s]?\:\/\/[^\/]+/',$replacement_url,$sugar_config['site_url']);
3660 $site_url = preg_replace('/^http(s)?\:\/\/[^\/]+/',"http$1://".$_SERVER['HTTP_HOST'],$sugar_config['site_url']);
3661 if(!empty($_SERVER['SERVER_PORT']) &&$_SERVER['SERVER_PORT'] == '443') {
3662 $site_url = preg_replace('/^http\:/','https:',$site_url);
3665 $GLOBALS['log']->debug("getJavascriptSiteURL(), site_url=". $site_url);
3669 // works nicely with array_map() -- can be used to wrap single quotes around each element in an array
3670 function add_squotes($str) {
3671 return "'" . $str . "'";
3675 // recursive function to count the number of levels within an array
3676 function array_depth($array, $depth_count=-1, $depth_array=array()){
3678 if (is_array($array)){
3679 foreach ($array as $key => $value){
3680 $depth_array[] = array_depth($value, $depth_count);
3684 return $depth_count;
3686 foreach ($depth_array as $value){
3687 $depth_count = $value > $depth_count ? $value : $depth_count;
3689 return $depth_count;
3693 * Creates a new Group User
3694 * @param string $name Name of Group User
3695 * @return string GUID of new Group User
3697 function createGroupUser($name) {
3700 $group = new User();
3701 $group->user_name = $name;
3702 $group->last_name = $name;
3703 $group->is_group = 1;
3704 $group->deleted = 0;
3705 $group->status = 'Active'; // cn: bug 6711
3706 $group->setPreference('timezone', TimeDate::userTimezone());
3713 * Helper function to locate an icon file given only a name
3714 * Searches through the various paths for the file
3715 * @param string iconFileName The filename of the icon
3716 * @return string Relative pathname of the located icon, or '' if not found
3719 function _getIcon($iconFileName)
3721 $iconPath = SugarThemeRegistry::current()->getImageURL("icon_{$iconFileName}.gif");
3722 //First try un-ucfirst-ing the icon name
3723 if ( empty($iconPath) )
3724 $iconPath = SugarThemeRegistry::current()->getImageURL(
3725 "icon_" . strtolower(substr($iconFileName,0,1)).substr($iconFileName,1) . ".gif");
3726 //Next try removing the icon prefix
3727 if ( empty($iconPath) )
3728 $iconPath = SugarThemeRegistry::current()->getImageURL("{$iconFileName}.gif");
3733 * Function to grab the correct icon image for Studio
3734 * @param string $iconFileName Name of the icon file
3735 * @param string $altfilename Name of a fallback icon file (displayed if the imagefilename doesn't exist)
3736 * @param string $width Width of image
3737 * @param string $height Height of image
3738 * @param string $align Alignment of image
3739 * @return string $string <img> tag with corresponding image
3742 function getStudioIcon($iconFileName='', $altFileName='', $width='48', $height='48', $align='baseline' )
3744 global $app_strings, $theme;
3746 $iconPath = _getIcon($iconFileName);
3747 if(empty($iconPath)){
3748 $iconPath = _getIcon($altFileName);
3749 if (empty($iconPath))
3751 return $app_strings['LBL_NO_IMAGE'];
3754 return '<img border="0" src="'.$iconPath.'" width="'.$width.'" height="'.$height.'" align="'.$align.'">';
3758 * Function to grab the correct icon image for Dashlets Dialog
3759 * @param string $filename Location of the icon file
3760 * @param string $module Name of the module to fall back onto if file does not exist
3761 * @param string $width Width of image
3762 * @param string $height Height of image
3763 * @param string $align Alignment of image
3764 * @return string $string <img> tag with corresponding image
3767 function get_dashlets_dialog_icon($module='', $width='32', $height='32', $align='absmiddle'){
3768 global $app_strings, $theme;
3769 $icon_path = _getIcon($module . "_32");
3770 if (empty($icon_path))
3772 $icon_path = _getIcon($module);
3774 if(empty($icon_path)){
3775 $icon = $app_strings['LBL_NO_IMAGE'];
3778 $icon = '<img border="0" src="'.$icon_path.'" width="'.$width.'" height="'.$height.'" align="'.$align.'">';
3783 // works nicely to change UTF8 strings that are html entities - good for PDF conversions
3784 function html_entity_decode_utf8($string)
3787 // replace numeric entities
3788 //php will have issues with numbers with leading zeros, so do not include them in what we send to code2utf.
3789 $string = preg_replace('~�*([0-9a-f]+);~ei', 'code2utf(hexdec("\\1"))', $string);
3790 $string = preg_replace('~�*([0-9]+);~e', 'code2utf(\\1)', $string);
3791 // replace literal entities
3792 if (!isset($trans_tbl))
3794 $trans_tbl = array();
3795 foreach (get_html_translation_table(HTML_ENTITIES) as $val=>$key)
3796 $trans_tbl[$key] = utf8_encode($val);
3798 return strtr($string, $trans_tbl);
3801 // Returns the utf string corresponding to the unicode value
3802 function code2utf($num)
3804 if ($num < 128) return chr($num);
3805 if ($num < 2048) return chr(($num >> 6) + 192) . chr(($num & 63) + 128);
3806 if ($num < 65536) return chr(($num >> 12) + 224) . chr((($num >> 6) & 63) + 128) . chr(($num & 63) + 128);
3807 if ($num < 2097152) return chr(($num >> 18) + 240) . chr((($num >> 12) & 63) + 128) . chr((($num >> 6) & 63) + 128) . chr(($num & 63) + 128);
3811 function str_split_php4($string, $length = 1) {
3812 $string_length = strlen($string);
3815 if ($length > $string_length) {
3816 // use the string_length as the string is shorter than the length
3817 $length = $string_length;
3819 for ($cursor = 0; $cursor < $string_length; $cursor = $cursor + $length) {
3820 $return[] = substr($string, $cursor, $length);
3825 if (version_compare(phpversion(), '5.0.0', '<')) {
3826 function str_split($string, $length = 1) {
3827 return str_split_php4($string, $length);
3832 * Invoked when connected to mssql. checks if we have freetds version of mssql library.
3833 * the response is put into a global variable.
3835 function is_freetds() {
3838 if (isset($GLOBALS['mssql_library_version'])) {
3839 if ($GLOBALS['mssql_library_version']=='freetds') {
3847 $info=ob_get_contents();
3850 if (strpos($info,'FreeTDS') !== false) {
3851 $GLOBALS['mssql_library_version']='freetds';
3854 $GLOBALS['mssql_library_version']='regular';
3862 * stripos - Find position of first occurrence of a case-insensitive string
3864 * The function is being defined for systems with PHP version < 5.
3867 if (!function_exists("stripos")){
3868 function stripos($haystack,$needle,$offset=0){
3869 return strpos(strtolower($haystack),strtolower($needle),$offset);
3874 * Chart dashlet helper function that returns the correct CSS file, dependent on the current theme.
3876 * @todo this won't work completely right until we impliment css compression and combination
3877 * for now, we'll just include the last css file found.
3879 * @return chart.css file to use
3881 function chartStyle()
3883 return SugarThemeRegistry::current()->getCSSURL('chart.css');
3887 * Chart dashlet helper functions that returns the correct XML color file for charts,
3888 * dependent on the current theme.
3890 * @return sugarColors.xml to use
3892 function chartColors()
3894 if (SugarThemeRegistry::current()->getCSSURL('sugarColors.xml')=='')
3895 return SugarThemeRegistry::current()->getImageURL('sugarColors.xml');
3896 return SugarThemeRegistry::current()->getCSSURL('sugarColors.xml');
3898 /* End Chart Dashlet helper functions */
3901 * This function is designed to set up the php enviroment
3902 * for AJAX requests.
3905 function ajaxInit() {
3906 ini_set('display_errors', 'false');
3910 * Returns an absolute path from the given path, determining if it is relative or absolute
3912 * @param string $path
3915 function getAbsolutePath(
3917 $currentServer = false
3920 $path = trim($path);
3922 // try to match absolute paths like \\server\share, /directory or c:\
3923 if ( ( substr($path,0,2) == '\\\\' )
3924 || ( $path[0] == '/' )
3925 || preg_match('/^[A-z]:/i',$path)
3929 return getcwd().'/'.$path;
3933 * Returns the bean object of the given module
3935 * @deprecated use SugarModule::loadBean() instead
3936 * @param string $module
3943 return SugarModule::get($module)->loadBean();
3948 * Returns true if the application is being accessed on a touch screen interface ( like an iPad )
3950 function isTouchScreen()
3952 $ua = empty($_SERVER['HTTP_USER_AGENT']) ? "undefined" : strtolower($_SERVER['HTTP_USER_AGENT']);
3954 // first check if we have forced use of the touch enhanced interface
3955 if ( isset($_COOKIE['touchscreen']) && $_COOKIE['touchscreen'] == '1' ) {
3959 // next check if we should use the touch interface with our device
3960 if ( strpos($ua, 'ipad') !== false ) {
3968 * Returns the shortcut keys to access the shortcut links. Shortcut
3969 * keys vary depending on browser versions and operating systems.
3970 * @return String value of the shortcut keys
3972 function get_alt_hot_key() {
3974 if ( isset($_SERVER['HTTP_USER_AGENT']) )
3975 $ua = strtolower($_SERVER['HTTP_USER_AGENT']);
3976 $isMac = strpos($ua, 'mac') !== false;
3977 $isLinux = strpos($ua, 'linux') !== false;
3979 if(!$isMac && !$isLinux && strpos($ua, 'mozilla') !== false) {
3980 if(preg_match('/firefox\/(\d)?\./', $ua, $matches)) {
3981 return $matches[1] < 2 ? 'Alt+' : 'Alt+Shift+';
3984 return $isMac ? 'Ctrl+' : 'Alt+';
3987 function can_start_session(){
3988 if(!empty($_GET['PHPSESSID'])) {
3991 $session_id = session_id();
3992 return empty($session_id) ? true : false;
3995 function load_link_class($properties){
3997 if(!empty($properties['link_class']) && !empty($properties['link_file'])){
3998 require_once($properties['link_file']);
3999 $class = $properties['link_class'];
4005 function inDeveloperMode()
4007 return isset($GLOBALS['sugar_config']['developerMode']) && $GLOBALS['sugar_config']['developerMode'];
4011 * Filter the protocol list for inbound email accounts.
4013 * @param array $protocol
4015 function filterInboundEmailPopSelection($protocol)
4017 if ( !isset($GLOBALS['sugar_config']['allow_pop_inbound']) || ! $GLOBALS['sugar_config']['allow_pop_inbound'] )
4019 if( isset($protocol['pop3']) )
4020 unset($protocol['pop3']);
4023 $protocol['pop3'] = 'POP3';
4029 * The function is used because currently we are not supporting mbstring.func_overload
4030 * 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.
4031 * 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.
4032 * @returns the substred strings.
4034 function sugar_substr($string, $length, $charset='UTF-8') {
4035 if($GLOBALS['db']->dbType == 'mssql' && empty($GLOBALS['db']->isFreeTDS)) {
4036 if(strlen($string) > $length) {
4037 $string = trim(substr(trim($string),0,$length));
4041 if(mb_strlen($string,$charset) > $length) {
4042 $string = trim(mb_substr(trim($string),0,$length,$charset));
4049 * The function is used because on FastCGI enviroment, the ucfirst(Chinese Characters) will produce bad charcters.
4050 * This will work even without setting the mbstring.*encoding
4052 function sugar_ucfirst($string, $charset='UTF-8') {
4053 return mb_strtoupper(mb_substr($string, 0, 1, $charset), $charset) . mb_substr($string, 1, mb_strlen($string), $charset);
4060 function unencodeMultienum($string) {
4061 if (is_array($string))
4065 if (substr($string, 0 ,1) == "^" && substr($string, -1) == "^") {
4066 $string = substr(substr($string, 1), 0, strlen($string) -2);
4069 return explode('^,^', $string);
4072 function encodeMultienumValue($arr) {
4073 if (!is_array($arr))
4079 $string = "^" . implode('^,^', $arr) . "^";
4085 * create_export_query is used for export and massupdate
4086 * We haven't handle the these fields: $field['type'] == 'relate' && isset($field['link']
4087 * This function will correct the where clause and output necessary join condition for them
4088 * @param $module: the module name
4089 * @param $searchFields: searchFields which is got after $searchForm->populateFromArray()
4090 * @param $where: where clauses
4091 * @return $ret_array['where']: corrected where clause
4092 * @return $ret_array['join']: extra join condition
4094 function create_export_query_relate_link_patch($module, $searchFields, $where){
4095 if(file_exists('modules/'.$module.'/SearchForm.html')){
4096 $ret_array['where'] = $where;
4099 $seed = loadBean($module);
4100 foreach($seed->field_defs as $name=>$field)
4103 if( $field['type'] == 'relate' && isset($field['link']) && !empty($searchFields[$name]['value']) ){
4104 $seed->load_relationship($field['link']);
4106 if(empty($join_type))
4108 $params['join_type'] = ' LEFT JOIN ';
4112 $params['join_type'] = $join_type;
4114 if(isset($data['join_name']))
4116 $params['join_table_alias'] = $field['join_name'];
4120 $params['join_table_alias'] = 'join_'.$field['name'];
4123 if(isset($data['join_link_name']))
4125 $params['join_table_link_alias'] = $field['join_link_name'];
4129 $params['join_table_link_alias'] = 'join_link_'.$field['name'];
4131 $join = $seed->$field['link']->getJoin($params, true);
4132 $join_table_alias = 'join_'.$field['name'];
4133 if(isset($field['db_concat_fields'])){
4134 $db_field = db_concat($join_table_alias, $field['db_concat_fields']);
4135 $where = preg_replace('/'.$field['name'].'/', $db_field, $where);
4137 $where = preg_replace('/(^|[\s(])' . $field['name'] . '/', '${1}' . $join_table_alias . '.'.$field['rname'], $where);
4141 $ret_array = array('where'=>$where, 'join'=>$join['join']);
4146 * 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.
4147 * @Depends on QuickRepairAndRebuild.php
4148 * @Relate bug 30642 ,23177
4150 function clearAllJsAndJsLangFilesWithoutOutput(){
4151 global $current_language , $mod_strings;
4152 $MBmodStrings = $mod_strings;
4153 $mod_strings = return_module_language ( $current_language, 'Administration' ) ;
4154 include_once ('modules/Administration/QuickRepairAndRebuild.php') ;
4155 $repair = new RepairAndClear();
4156 $repair->module_list = array();
4157 $repair->show_output = false;
4158 $repair->clearJsLangFiles();
4159 $repair->clearJsFiles();
4160 $mod_strings = $MBmodStrings;
4164 * This function will allow you to get a variable value from query string
4166 function getVariableFromQueryString($variable, $string){
4168 $number = preg_match("/{$variable}=([a-zA-Z0-9_-]+)[&]?/", $string, $matches);
4178 * should_hide_iframes
4179 * This is a helper method to determine whether or not to show iframes (My Sites) related
4180 * information in the application.
4182 * @return boolean flag indicating whether or not iframes module should be hidden
4184 function should_hide_iframes() {
4185 //Remove the MySites module
4186 if(file_exists('modules/iFrames/iFrame.php')) {
4187 if(!class_exists("iFrame")) {
4188 require_once('modules/iFrames/iFrame.php');
4196 * Given a version such as 5.5.0RC1 return RC. If we have a version such as: 5.5 then return GA
4198 * @param string $version
4199 * @return string RC, BETA, GA
4201 function getVersionStatus($version){
4202 if(preg_match('/^[\d\.]+?([a-zA-Z]+?)[\d]*?$/si', $version, $matches)) {
4203 return strtoupper($matches[1]);
4210 * Return the numeric portion of a version. For example if passed 5.5.0RC1 then return 5.5. If given
4211 * 5.5.1RC1 then return 5.5.1
4213 * @param string $version
4216 function getMajorMinorVersion($version){
4217 if(preg_match('/^([\d\.]+).*$/si', $version, $matches2)){
4218 $version = $matches2[1];
4219 $arr = explode('.', $version);
4220 if(count($arr) > 2){
4222 $version = substr($version, 0, 3);
4230 * Return string composed of seconds & microseconds of current time, without dots
4233 function sugar_microtime()
4235 $now = explode(' ', microtime());
4236 $unique_id = $now[1].str_replace('.', '', $now[0]);
4241 * Extract urls from a piece of text
4243 * @return array of urls found in $string
4245 function getUrls($string)
4247 $lines = explode("<br>", trim($string));
4249 foreach($lines as $line){
4250 $regex = '/http?\:\/\/[^\" ]+/i';
4251 preg_match_all($regex, $line, $matches);
4252 foreach($matches[0] as $match){
4261 * Sanitize image file from hostile content
4262 * @param string $path Image file
4263 * @param bool $jpeg Accept only JPEGs?
4265 function verify_image_file($path, $jpeg = false)
4267 if(function_exists('imagepng') && function_exists('imagejpeg') && function_exists('imagecreatefromstring')) {
4268 $img = imagecreatefromstring(file_get_contents($path));
4272 $img_size = getimagesize($path);
4273 $filetype = $img_size['mime'];
4274 //if filetype is jpeg or if we are only allowing jpegs, create jpg image
4275 if($filetype == "image/jpeg" || $jpeg) {
4276 if(imagejpeg($img, $path)) {
4279 } elseif ($filetype == "image/png") { // else if the filetype is png, create png
4280 imagealphablending($img, true);
4281 imagesavealpha($img, true);
4282 if(imagepng($img, $path)) {
4289 // check image manually
4290 $fp = fopen($path, "r");
4291 if(!$fp) return false;
4292 $data = fread($fp, 4096);
4294 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",
4296 $GLOBALS['log']->info("Found {$m[0]} in $path, not allowing upload");
4305 * Verify uploaded image
4306 * Verifies that image has proper extension, MIME type and doesn't contain hostile contant
4307 * @param string $path Image path
4308 * @param bool $jpeg_only Accept only JPEGs?
4310 function verify_uploaded_image($path, $jpeg_only = false)
4312 $supportedExtensions = array('jpg' => 'image/jpeg', 'jpeg' => 'image/jpeg');
4314 $supportedExtensions['png'] = 'image/png';
4317 if(!file_exists($path) || !is_file($path)) {
4321 $img_size = getimagesize($path);
4322 $filetype = $img_size['mime'];
4323 $ext = end(explode(".", $path));
4324 if(substr_count('..', $path) > 0 || $ext === $path || !in_array(strtolower($ext), array_keys($supportedExtensions)) ||
4325 !in_array($filetype, array_values($supportedExtensions))) {
4328 return verify_image_file($path, $jpeg_only);
4331 function cmp_beans($a, $b)
4333 global $sugar_web_service_order_by;
4334 //If the order_by field is not valid, return 0;
4335 if (empty($sugar_web_service_order_by) || !isset($a->$sugar_web_service_order_by) || !isset($b->$sugar_web_service_order_by)){
4338 if (is_object($a->$sugar_web_service_order_by) || is_object($b->$sugar_web_service_order_by)
4339 || is_array($a->$sugar_web_service_order_by) || is_array($b->$sugar_web_service_order_by))
4343 if ($a->$sugar_web_service_order_by < $b->$sugar_web_service_order_by)
4351 function order_beans($beans, $field_name)
4353 //Since php 5.2 doesn't include closures, we must use a global to pass the order field to cmp_beans.
4354 global $sugar_web_service_order_by;
4355 $sugar_web_service_order_by = $field_name;
4356 usort($beans, "cmp_beans");
4360 //check to see if custom utils exists
4361 if(file_exists('custom/include/custom_utils.php')){
4362 include_once('custom/include/custom_utils.php');
4365 //check to see if custom utils exists in Extension framework
4366 if(file_exists('custom/application/Ext/Utils/custom_utils.ext.php')) {
4367 include_once('custom/application/Ext/Utils/custom_utils.ext.php');