2 /*********************************************************************************
3 * SugarCRM Community Edition is a customer relationship management program developed by
4 * SugarCRM, Inc. Copyright (C) 2004-2013 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;
85 global $requireAccounts;
86 global $RSS_CACHE_TIME;
90 global $sugar_version;
93 global $translation_string_prefix;
95 global $upload_badext;
97 global $upload_maxsize;
98 global $import_max_execution_time;
99 global $list_max_entries_per_subpanel;
100 global $passwordsetting;
102 // assumes the following variables must be set:
103 // $dbconfig, $dbconfigoption, $cache_dir, $session_dir, $site_URL, $upload_dir
105 $sugar_config = array (
106 'admin_export_only' => empty($admin_export_only) ? false : $admin_export_only,
107 'export_delimiter' => empty($export_delimiter) ? ',' : $export_delimiter,
108 'cache_dir' => empty($cache_dir) ? 'cache/' : $cache_dir,
109 'calculate_response_time' => empty($calculate_response_time) ? true : $calculate_response_time,
110 'create_default_user' => empty($create_default_user) ? false : $create_default_user,
111 'chartEngine' => 'Jit',
112 'date_formats' => empty($dateFormats) ? array(
113 'Y-m-d'=>'2010-12-23',
114 'd-m-Y' => '23-12-2010',
115 'm-d-Y'=>'12-23-2010',
116 'Y/m/d'=>'2010/12/23',
117 'd/m/Y' => '23/12/2010',
118 'm/d/Y'=>'12/23/2010',
119 'Y.m.d' => '2010.12.23',
120 'd.m.Y' => '23.12.2010',
121 'm.d.Y' => '12.23.2010'
123 'dbconfig' => $dbconfig, // this must be set!!
124 'dbconfigoption' => $dbconfigoption, // this must be set!!
125 'default_action' => empty($default_action) ? 'index' : $default_action,
126 'default_charset' => empty($default_charset) ? 'UTF-8' : $default_charset,
127 'default_currency_name' => empty($default_currency_name) ? 'US Dollar' : $default_currency_name,
128 'default_currency_symbol' => empty($default_currency_symbol) ? '$' : $default_currency_symbol,
129 'default_currency_iso4217' => empty($default_currency_iso4217) ? '$' : $default_currency_iso4217,
130 'default_date_format' => empty($defaultDateFormat) ? 'm/d/Y' : $defaultDateFormat,
131 'default_locale_name_format' => empty($defaultNameFormat) ? 's f l' : $defaultNameFormat,
132 'default_export_charset' => 'UTF-8',
133 'default_language' => empty($default_language) ? 'en_us' : $default_language,
134 'default_module' => empty($default_module) ? 'Home' : $default_module,
135 'default_password' => empty($default_password) ? '' : $default_password,
136 'default_permissions' => array (
142 'default_theme' => empty($default_theme) ? 'Sugar5' : $default_theme,
143 'default_time_format' => empty($defaultTimeFormat) ? 'h:ia' : $defaultTimeFormat,
144 'default_user_is_admin' => empty($default_user_is_admin) ? false : $default_user_is_admin,
145 'default_user_name' => empty($default_user_name) ? '' : $default_user_name,
146 'disable_export' => empty($disable_export) ? false : $disable_export,
147 'disable_persistent_connections' => empty($disable_persistent_connections) ? false : $disable_persistent_connections,
148 'display_email_template_variable_chooser' => empty($display_email_template_variable_chooser) ? false : $display_email_template_variable_chooser,
149 'display_inbound_email_buttons' => empty($display_inbound_email_buttons) ? false : $display_inbound_email_buttons,
150 'history_max_viewed' => empty($history_max_viewed) ? 50 : $history_max_viewed,
151 'host_name' => empty($host_name) ? 'localhost' : $host_name,
152 'import_dir' => $import_dir, // this must be set!!
153 'import_max_records_per_file' => 100,
154 'import_max_records_total_limit' => '',
155 'languages' => empty($languages) ? array('en_us' => 'English (US)') : $languages,
156 'list_max_entries_per_page' => empty($list_max_entries_per_page) ? 20 : $list_max_entries_per_page,
157 'list_max_entries_per_subpanel' => empty($list_max_entries_per_subpanel) ? 10 : $list_max_entries_per_subpanel,
158 'lock_default_user_name' => empty($lock_default_user_name) ? false : $lock_default_user_name,
159 'log_memory_usage' => empty($log_memory_usage) ? false : $log_memory_usage,
160 'name_formats' => empty($nameFormats) ? array(
161 's f l' => 's f l', 'f l' => 'f l', 's l' => 's l', 'l, s f' => 'l, s f',
162 'l, f' => 'l, f', 's l, f' => 's l, f', 'l s f' => 'l s f', 'l f s' => 'l f s'
164 'portal_view' => 'single_user',
165 'resource_management' => array (
166 'special_query_limit' => 50000,
167 'special_query_modules' => array('Reports', 'Export', 'Import', 'Administration', 'Sync'),
168 'default_limit' => 1000,
170 'require_accounts' => empty($requireAccounts) ? true : $requireAccounts,
171 'rss_cache_time' => empty($RSS_CACHE_TIME) ? '10800' : $RSS_CACHE_TIME,
172 'session_dir' => $session_dir, // this must be set!!
173 'site_url' => empty($site_URL) ? $site_url : $site_URL, // this must be set!!
174 'showDetailData' => true, // if true, read-only ACL fields will still appear on EditViews as non-editable
175 'showThemePicker' => true,
176 'sugar_version' => empty($sugar_version) ? 'unknown' : $sugar_version,
177 'time_formats' => empty($timeFormats) ? array (
178 'H:i'=>'23:00', 'h:ia'=>'11:00 pm', 'h:iA'=>'11:00PM',
179 'H.i'=>'23.00', 'h.ia'=>'11.00 pm', 'h.iA'=>'11.00PM' ) : $timeFormats,
180 'tmp_dir' => $tmp_dir, // this must be set!!
181 'translation_string_prefix' => empty($translation_string_prefix) ? false : $translation_string_prefix,
182 'unique_key' => empty($unique_key) ? md5(create_guid()) : $unique_key,
183 'upload_badext' => empty($upload_badext) ? array (
184 'php', 'php3', 'php4', 'php5', 'pl', 'cgi', 'py',
185 'asp', 'cfm', 'js', 'vbs', 'html', 'htm' ) : $upload_badext,
186 'upload_dir' => $upload_dir, // this must be set!!
187 'upload_maxsize' => empty($upload_maxsize) ? 30000000 : $upload_maxsize,
188 'import_max_execution_time' => empty($import_max_execution_time) ? 3600 : $import_max_execution_time,
189 'lock_homepage' => false,
190 'lock_subpanels' => false,
191 'max_dashlets_homepage' => 15,
192 'dashlet_display_row_options' => array('1','3','5','10'),
193 'default_max_tabs' => empty($max_tabs) ? '7' : $max_tabs,
194 'default_subpanel_tabs' => empty($subpanel_tabs) ? true : $subpanel_tabs,
195 'default_subpanel_links' => empty($subpanel_links) ? false : $subpanel_links,
196 'default_swap_last_viewed' => empty($swap_last_viewed) ? false : $swap_last_viewed,
197 'default_swap_shortcuts' => empty($swap_shortcuts) ? false : $swap_shortcuts,
198 'default_navigation_paradigm' => empty($navigation_paradigm) ? 'gm' : $navigation_paradigm,
199 'default_call_status' => 'Planned',
200 'js_lang_version' => 1,
201 'passwordsetting' => empty($passwordsetting) ? array (
202 'SystemGeneratedPasswordON' => '',
203 'generatepasswordtmpl' => '',
204 'lostpasswordtmpl' => '',
205 'forgotpasswordON' => true,
206 'linkexpiration' => '1',
207 'linkexpirationtime' => '30',
208 'linkexpirationtype' => '1',
209 'systexpiration' => '0',
210 'systexpirationtime' => '',
211 'systexpirationtype' => '0',
212 'systexpirationlogin' => '',
213 ) : $passwordsetting,
214 'use_sprites' => function_exists('imagecreatetruecolor'),
215 'search_wildcard_infront' => false,
216 'search_wildcard_char' => '%',
218 'min_retry_interval' => 60, // minimal job retry delay
219 'max_retries' => 5, // how many times to retry the job
220 'timeout' => 86400, // how long a job may spend as running before being force-failed
221 'soft_lifetime' => 7, // how many days until job record will be soft deleted after completion
222 'hard_lifetime' => 21, // how many days until job record will be purged from DB
225 'max_cron_jobs' => 10, // max jobs per cron schedule run
226 'max_cron_runtime' => 60, // max runtime for cron jobs
227 'min_cron_interval' => 30, // minimal interval between cron jobs
232 function get_sugar_config_defaults() {
235 * used for getting base values for array style config.php. used by the
236 * installer and to fill in new entries on upgrades. see also:
240 $sugar_config_defaults = array (
241 'admin_export_only' => false,
242 'export_delimiter' => ',',
243 'export_excel_compatible' => false,
244 'cache_dir' => 'cache/',
245 'calculate_response_time' => true,
246 'create_default_user' => false,
247 'chartEngine' => 'Jit',
248 'date_formats' => array (
249 'Y-m-d' => '2010-12-23', 'm-d-Y' => '12-23-2010', 'd-m-Y' => '23-12-2010',
250 'Y/m/d' => '2010/12/23', 'm/d/Y' => '12/23/2010', 'd/m/Y' => '23/12/2010',
251 'Y.m.d' => '2010.12.23', 'd.m.Y' => '23.12.2010', 'm.d.Y' => '12.23.2010',),
252 'name_formats' => array (
253 's f l' => 's f l', 'f l' => 'f l', 's l' => 's l', 'l, s f' => 'l, s f',
254 'l, f' => 'l, f', 's l, f' => 's l, f', 'l s f' => 'l s f', 'l f s' => 'l f s'
256 'dbconfigoption' => array (
257 'persistent' => true,
261 'default_action' => 'index',
262 'default_charset' => return_session_value_or_default('default_charset',
264 'default_currency_name' => return_session_value_or_default('default_currency_name', 'US Dollar'),
265 'default_currency_symbol' => return_session_value_or_default('default_currency_symbol', '$'),
266 'default_currency_iso4217' => return_session_value_or_default('default_currency_iso4217', 'USD'),
267 'default_currency_significant_digits' => return_session_value_or_default('default_currency_significant_digits', 2),
268 'default_number_grouping_seperator' => return_session_value_or_default('default_number_grouping_seperator', ','),
269 'default_decimal_seperator' => return_session_value_or_default('default_decimal_seperator', '.'),
270 'default_date_format' => 'm/d/Y',
271 'default_locale_name_format' => 's f l',
272 'default_export_charset' => 'UTF-8',
273 'default_language' => return_session_value_or_default('default_language',
275 'default_module' => 'Home',
276 'default_password' => '',
277 'default_permissions' => array (
283 'default_theme' => return_session_value_or_default('site_default_theme', 'Sugar5'),
284 'default_time_format' => 'h:ia',
285 'default_user_is_admin' => false,
286 'default_user_name' => '',
287 'disable_export' => false,
288 'disable_persistent_connections' =>
289 return_session_value_or_default('disable_persistent_connections',
291 'display_email_template_variable_chooser' => false,
292 'display_inbound_email_buttons' => false,
293 'dump_slow_queries' => false,
294 'email_address_separator' => ',', // use RFC2368 spec unless we have a noncompliant email client
295 'email_default_editor' => 'html',
296 'email_default_client' => 'sugar',
297 'email_default_delete_attachments' => true,
298 'history_max_viewed' => 50,
299 'installer_locked' => true,
300 'import_max_records_per_file' => 100,
301 'import_max_records_total_limit' => '',
302 'languages' => array('en_us' => 'English (US)'),
303 'large_scale_test' => false,
304 'list_max_entries_per_page' => 20,
305 'list_max_entries_per_subpanel' => 10,
306 'lock_default_user_name' => false,
307 'log_memory_usage' => false,
308 'portal_view' => 'single_user',
309 'resource_management' => array (
310 'special_query_limit' => 50000,
311 'special_query_modules' => array('Reports', 'Export', 'Import', 'Administration', 'Sync'),
312 'default_limit' => 1000,
314 'require_accounts' => true,
315 'rss_cache_time' => return_session_value_or_default('rss_cache_time',
317 'save_query' => 'all',
318 'showDetailData' => true, // if true, read-only ACL fields will still appear on EditViews as non-editable
319 'showThemePicker' => true,
320 'slow_query_time_msec' => '100',
322 'time_formats' => array (
323 'H:i'=>'23:00', 'h:ia'=>'11:00pm', 'h:iA'=>'11:00PM', 'h:i a'=>'11:00 pm', 'h:i A'=>'11:00 PM',
324 'H.i'=>'23.00', 'h.ia'=>'11.00pm', 'h.iA'=>'11.00PM', 'h.i a'=>'11.00 pm', 'h.i A'=>'11.00 PM' ),
325 'tracker_max_display_length' => 15,
326 'translation_string_prefix' =>
327 return_session_value_or_default('translation_string_prefix', false),
328 'upload_badext' => array (
329 'php', 'php3', 'php4', 'php5', 'pl', 'cgi', 'py',
330 'asp', 'cfm', 'js', 'vbs', 'html', 'htm' ),
331 'upload_maxsize' => 30000000,
332 'import_max_execution_time' => 3600,
333 // 'use_php_code_json' => returnPhpJsonStatus(),
334 'verify_client_ip' => true,
335 'js_custom_version' => '',
336 'js_lang_version' => 1,
337 'lead_conv_activity_opt' => 'donothing',
338 'default_number_grouping_seperator' => ',',
339 'default_decimal_seperator' => '.',
340 'lock_homepage' => false,
341 'lock_subpanels' => false,
342 'max_dashlets_homepage' => '15',
343 'default_max_tabs' => '7',
344 'dashlet_display_row_options' => array('1','3','5','10'),
345 'default_subpanel_tabs' => true,
346 'default_subpanel_links' => false,
347 'default_swap_last_viewed' => false,
348 'default_swap_shortcuts' => false,
349 'default_navigation_paradigm' => 'gm',
350 'admin_access_control' => false,
351 'use_common_ml_dir' => false,
352 'common_ml_dir' => '',
355 'default_view' => 'week',
356 'show_calls_by_default' => true,
357 'show_tasks_by_default' => true,
358 'show_completed_by_default' => true,
359 'editview_width' => 990,
360 'editview_height' => 485,
361 'day_timestep' => 15,
362 'week_timestep' => 30,
363 'items_draggable' => true,
364 'items_resizable' => true,
365 'enable_repeat' => true,
366 'max_repeat_count' => 1000,
368 'passwordsetting' => empty($passwordsetting) ? array (
369 'SystemGeneratedPasswordON' => '',
370 'generatepasswordtmpl' => '',
371 'lostpasswordtmpl' => '',
372 'forgotpasswordON' => false,
373 'linkexpiration' => '1',
374 'linkexpirationtime' => '30',
375 'linkexpirationtype' => '1',
376 'systexpiration' => '0',
377 'systexpirationtime' => '',
378 'systexpirationtype' => '0',
379 'systexpirationlogin' => '',
380 ) : $passwordsetting,
381 'use_real_names' => true,
383 'search_wildcard_infront' => false,
384 'search_wildcard_char' => '%',
386 'min_retry_interval' => 30, // 30 seconds minimal job retry
387 'max_retries' => 5, // how many times to retry the job
388 'timeout' => 86400, // how long a job may spend as running before being force-failed
391 'max_cron_jobs' => 10, // max jobs per cron schedule run
392 'max_cron_runtime' => 30, // max runtime for cron jobs
393 'min_cron_interval' => 30, // minimal interval between cron jobs
397 if(!is_object($locale)) {
398 $locale = new Localization();
401 $sugar_config_defaults['default_currencies'] = $locale->getDefaultCurrencies();
403 $sugar_config_defaults = sugarArrayMerge($locale->getLocaleConfigDefaults(), $sugar_config_defaults);
404 return( $sugar_config_defaults );
408 * @deprecated use SugarView::getMenu() instead
410 function load_menu($path){
413 if(file_exists($path . 'Menu.php'))
415 require($path . 'Menu.php');
417 if(file_exists('custom/' . $path . 'Ext/Menus/menu.ext.php'))
419 require('custom/' . $path . 'Ext/Menus/menu.ext.php');
421 if(file_exists('custom/application/Ext/Menus/menu.ext.php'))
423 require('custom/application/Ext/Menus/menu.ext.php');
429 * get_notify_template_file
430 * This function will return the location of the email notifications template to use
432 * @return string relative file path to email notifications template file
434 function get_notify_template_file($language){
436 * Order of operation:
437 * 1) custom version of specified language
438 * 2) stock version of specified language
439 * 3) custom version of en_us template
440 * 4) stock en_us template
443 // set $file to the base code template so it's set if none of the conditions pass
444 $file = "include/language/en_us.notify_template.html";
446 if(file_exists("custom/include/language/{$language}.notify_template.html")){
447 $file = "custom/include/language/{$language}.notify_template.html";
449 else if(file_exists("include/language/{$language}.notify_template.html")){
450 $file = "include/language/{$language}.notify_template.html";
452 else if(file_exists("custom/include/language/en_us.notify_template.html")){
453 $file = "custom/include/language/en_us.notify_template.html";
459 function sugar_config_union( $default, $override ){
460 // a little different then array_merge and array_merge_recursive. we want
461 // the second array to override the first array if the same value exists,
462 // otherwise merge the unique keys. it handles arrays of arrays recursively
463 // might be suitable for a generic array_union
464 if( !is_array( $override ) ){
467 foreach( $default as $key => $value ){
468 if( !array_key_exists($key, $override) ){
469 $override[$key] = $value;
471 else if( is_array( $key ) ){
472 $override[$key] = sugar_config_union( $value, $override[$key] );
478 function make_not_writable( $file ){
479 // Returns true if the given file/dir has been made not writable
481 if( is_file($file) || is_dir($file) ){
482 if( !is_writable($file) ){
486 $original_fileperms = fileperms($file);
488 // take away writable permissions
489 $new_fileperms = $original_fileperms & ~0x0092;
490 @sugar_chmod($file, $new_fileperms);
492 if( !is_writable($file) ){
501 /** This function returns the name of the person.
502 * It currently returns "first last". It should not put the space if either name is not available.
503 * It should not return errors if either name is not available.
504 * If no names are present, it will return ""
505 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
506 * All Rights Reserved.
507 * Contributor(s): ______________________________________..
509 function return_name($row, $first_column, $last_column)
515 if(isset($row[$first_column]))
517 $first_name = stripslashes($row[$first_column]);
520 if(isset($row[$last_column]))
522 $last_name = stripslashes($row[$last_column]);
525 $full_name = $first_name;
527 // If we have a first name and we have a last name
528 if($full_name != "" && $last_name != "")
530 // append a space, then the last name
531 $full_name .= " ".$last_name;
533 // If we have no first name, but we have a last name
534 else if($last_name != "")
536 // append the last name without the space.
537 $full_name .= $last_name;
544 function get_languages()
546 global $sugar_config;
547 $lang = $sugar_config['languages'];
548 if(!empty($sugar_config['disabled_languages'])){
549 foreach(explode(',', $sugar_config['disabled_languages']) as $disable) {
550 unset($lang[$disable]);
556 function get_all_languages()
558 global $sugar_config;
559 return $sugar_config['languages'];
563 function get_language_display($key)
565 global $sugar_config;
566 return $sugar_config['languages'][$key];
569 function get_assigned_user_name($assigned_user_id, $is_group = '') {
570 static $saved_user_list = null;
572 if(empty($saved_user_list)) {
573 $saved_user_list = get_user_array(false, '', '', false, null, $is_group);
576 if(isset($saved_user_list[$assigned_user_id])) {
577 return $saved_user_list[$assigned_user_id];
584 * retrieves the user_name column value (login)
585 * @param string id GUID of user
588 function get_user_name($id) {
592 $db = DBManagerFactory::getInstance();
594 $q = "SELECT user_name FROM users WHERE id='{$id}'";
596 $a = $db->fetchByAssoc($r);
598 return (empty($a)) ? '' : $a['user_name'];
602 //TODO Update to use global cache
606 * This is a helper function to return an Array of users depending on the parameters passed into the function.
607 * This function uses the get_register_value function by default to use a caching layer where supported.
609 * @param bool $add_blank Boolean value to add a blank entry to the array results, true by default
610 * @param string $status String value indicating the status to filter users by, "Active" by default
611 * @param string $user_id String value to specify a particular user id value (searches the id column of users table), blank by default
612 * @param bool $use_real_name Boolean value indicating whether or not results should include the full name or just user_name, false by default
613 * @param String $user_name_filter String value indicating the user_name filter (searches the user_name column of users table) to optionally search with, blank by default
614 * @param string $portal_filter String query filter for portal users (defaults to searching non-portal users), change to blank if you wish to search for all users including portal users
615 * @param bool $from_cache Boolean value indicating whether or not to use the get_register_value function for caching, true by default
616 * @return array Array of users matching the filter criteria that may be from cache (if similar search was previously run)
618 function get_user_array($add_blank=true, $status="Active", $user_id='', $use_real_name=false, $user_name_filter='', $portal_filter=' AND portal_only=0 ', $from_cache = true) {
620 global $sugar_config;
623 $locale = new Localization();
627 $key_name = $add_blank. $status . $user_id . $use_real_name . $user_name_filter . $portal_filter;
628 $user_array = get_register_value('user_array', $key_name);
631 if(empty($user_array)) {
632 $db = DBManagerFactory::getInstance();
633 $temp_result = Array();
634 // Including deleted users for now.
635 if (empty($status)) {
636 $query = "SELECT id, first_name, last_name, user_name from users WHERE 1=1".$portal_filter;
639 $query = "SELECT id, first_name, last_name, user_name from users WHERE status='$status'".$portal_filter;
642 if (!empty($user_name_filter)) {
643 $user_name_filter = $db->quote($user_name_filter);
644 $query .= " AND user_name LIKE '$user_name_filter%' ";
646 if (!empty($user_id)) {
647 $query .= " OR id='{$user_id}'";
649 $query = $query.' ORDER BY user_name ASC';
650 $GLOBALS['log']->debug("get_user_array query: $query");
651 $result = $db->query($query, true, "Error filling in user array: ");
653 if ($add_blank==true) {
654 // Add in a blank row
655 $temp_result[''] = '';
658 // Get the id and the name.
659 while($row = $db->fetchByAssoc($result)) {
660 if($use_real_name == true || showFullName()) {
661 if(isset($row['last_name'])) { // cn: we will ALWAYS have both first_name and last_name (empty value if blank in db)
662 $temp_result[$row['id']] = $locale->getLocaleFormattedName($row['first_name'],$row['last_name']);
664 $temp_result[$row['id']] = $row['user_name'];
667 $temp_result[$row['id']] = $row['user_name'];
671 $user_array = $temp_result;
674 set_register_value('user_array', $key_name, $temp_result);
684 * uses a different query to return a list of users than get_user_array()
685 * Used from QuickSearch.php
686 * @param args string where clause entry
687 * @return array Array of Users' details that match passed criteria
689 function getUserArrayFromFullName($args, $hide_portal_users = false) {
691 $db = DBManagerFactory::getInstance();
693 // jmorais@dri - Bug #51411
695 // Refactor the code responsible for parsing supplied $args, this way we
696 // ensure that if $args has at least one space (after trim), the $inClause
697 // will be composed by several clauses ($inClauses) inside parenthesis.
699 // Ensuring that operator precedence is respected, and avoiding
700 // inactive/deleted users to be retrieved.
703 if (strpos($args, ' ')) {
704 $inClauses = array();
706 $argArray = explode(' ', $args);
707 foreach ($argArray as $arg) {
708 $arg = $db->quote($arg);
709 $inClauses[] = "(first_name LIKE '{$arg}%' OR last_name LIKE '{$arg}%')";
712 $inClause = '(' . implode('OR ', $inClauses) . ')';
715 $args = $db->quote($args);
716 $inClause = "(first_name LIKE '{$args}%' OR last_name LIKE '{$args}%')";
720 $query = "SELECT id, first_name, last_name, user_name FROM users WHERE status='Active' AND deleted=0 AND ";
721 if ( $hide_portal_users ) {
722 $query .= " portal_only=0 AND ";
725 $query .= " ORDER BY last_name ASC";
727 $r = $db->query($query);
729 while($a = $db->fetchByAssoc($r)) {
730 $ret[$a['id']] = $locale->getLocaleFormattedName($a['first_name'], $a['last_name']);
738 * based on user pref then system pref
740 function showFullName() {
741 global $sugar_config;
742 global $current_user;
743 static $showFullName = null;
745 if (is_null($showFullName)) {
746 $sysPref = !empty($sugar_config['use_real_names']);
747 $userPref = (is_object($current_user)) ? $current_user->getPreference('use_real_names') : null;
749 if($userPref != null) {
750 $showFullName = ($userPref == 'on');
752 $showFullName = $sysPref;
756 return $showFullName;
759 function clean($string, $maxLength)
761 $string = substr($string, 0, $maxLength);
762 return escapeshellcmd($string);
766 * Copy the specified request variable to the member variable of the specified object.
767 * Do no copy if the member variable is already set.
768 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
769 * All Rights Reserved.
770 * Contributor(s): ______________________________________..
772 function safe_map($request_var, & $focus, $always_copy = false)
774 safe_map_named($request_var, $focus, $request_var, $always_copy);
778 * Copy the specified request variable to the member variable of the specified object.
779 * Do no copy if the member variable is already set.
780 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
781 * All Rights Reserved.
782 * Contributor(s): ______________________________________..
784 function safe_map_named($request_var, & $focus, $member_var, $always_copy)
786 if (isset($_REQUEST[$request_var]) && ($always_copy || is_null($focus->$member_var))) {
787 $GLOBALS['log']->debug("safe map named called assigning '{$_REQUEST[$request_var]}' to $member_var");
788 $focus->$member_var = $_REQUEST[$request_var];
793 * This function retrieves an application language file and returns the array of strings included in the $app_list_strings var.
795 * @param string $language specific language to load
796 * @return array lang strings
798 function return_app_list_strings_language($language)
800 global $app_list_strings;
801 global $sugar_config;
803 $cache_key = 'app_list_strings.'.$language;
805 // Check for cached value
806 $cache_entry = sugar_cache_retrieve($cache_key);
807 if(!empty($cache_entry))
812 $default_language = $sugar_config['default_language'];
813 $temp_app_list_strings = $app_list_strings;
816 if ($language != 'en_us') {
819 if ($default_language != 'en_us' && $language != $default_language) {
820 $langs[] = $default_language;
822 $langs[] = $language;
824 $app_list_strings_array = array();
826 foreach ( $langs as $lang ) {
827 $app_list_strings = array();
828 if(file_exists("include/language/$lang.lang.php")) {
829 include("include/language/$lang.lang.php");
830 $GLOBALS['log']->info("Found language file: $lang.lang.php");
832 if(file_exists("include/language/$lang.lang.override.php")) {
833 include("include/language/$lang.lang.override.php");
834 $GLOBALS['log']->info("Found override language file: $lang.lang.override.php");
836 if(file_exists("include/language/$lang.lang.php.override")) {
837 include("include/language/$lang.lang.php.override");
838 $GLOBALS['log']->info("Found override language file: $lang.lang.php.override");
841 $app_list_strings_array[] = $app_list_strings;
844 $app_list_strings = array();
845 foreach ( $app_list_strings_array as $app_list_strings_item ) {
846 $app_list_strings = sugarLangArrayMerge($app_list_strings, $app_list_strings_item);
849 foreach ( $langs as $lang ) {
850 if(file_exists("custom/application/Ext/Language/$lang.lang.ext.php")) {
851 $app_list_strings = _mergeCustomAppListStrings("custom/application/Ext/Language/$lang.lang.ext.php" , $app_list_strings);
852 $GLOBALS['log']->info("Found extended language file: $lang.lang.ext.php");
854 if(file_exists("custom/include/language/$lang.lang.php")) {
855 include("custom/include/language/$lang.lang.php");
856 $GLOBALS['log']->info("Found custom language file: $lang.lang.php");
860 if(!isset($app_list_strings)) {
861 $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");
865 $return_value = $app_list_strings;
866 $app_list_strings = $temp_app_list_strings;
868 sugar_cache_put($cache_key, $return_value);
870 return $return_value;
874 * The dropdown items in custom language files is $app_list_strings['$key']['$second_key'] = $value not
875 * $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.
876 * @param file string the language that you want include,
877 * @param app_list_strings array the golbal strings
881 function _mergeCustomAppListStrings($file , $app_list_strings){
882 $app_list_strings_original = $app_list_strings;
883 unset($app_list_strings);
884 // FG - bug 45525 - $exemptDropdown array is defined (once) here, not inside the foreach
885 // This way, language file can add items to save specific standard codelist from being overwritten
886 $exemptDropdowns = array();
888 if(!isset($app_list_strings) || !is_array($app_list_strings)){
889 return $app_list_strings_original;
891 //Bug 25347: We should not merge custom dropdown fields unless they relate to parent fields or the module list.
893 // FG - bug 45525 - Specific codelists must NOT be overwritten
894 $exemptDropdowns[] = "moduleList";
895 $exemptDropdowns[] = "moduleListSingular";
896 $exemptDropdowns = array_merge($exemptDropdowns, getTypeDisplayList());
898 foreach($app_list_strings as $key=>$value)
900 if (!in_array($key, $exemptDropdowns) && array_key_exists($key, $app_list_strings_original))
902 unset($app_list_strings_original["$key"]);
905 $app_list_strings = sugarArrayMergeRecursive($app_list_strings_original , $app_list_strings);
906 return $app_list_strings;
910 * This function retrieves an application language file and returns the array of strings included.
912 * @param string $language specific language to load
913 * @return array lang strings
915 function return_application_language($language)
917 global $app_strings, $sugar_config;
919 $cache_key = 'app_strings.'.$language;
921 // Check for cached value
922 $cache_entry = sugar_cache_retrieve($cache_key);
923 if(!empty($cache_entry))
928 $temp_app_strings = $app_strings;
929 $default_language = $sugar_config['default_language'];
932 if ($language != 'en_us') {
935 if ($default_language != 'en_us' && $language != $default_language) {
936 $langs[] = $default_language;
939 $langs[] = $language;
941 $app_strings_array = array();
943 foreach ( $langs as $lang ) {
944 $app_strings = array();
945 if(file_exists("include/language/$lang.lang.php")) {
946 include("include/language/$lang.lang.php");
947 $GLOBALS['log']->info("Found language file: $lang.lang.php");
949 if(file_exists("include/language/$lang.lang.override.php")) {
950 include("include/language/$lang.lang.override.php");
951 $GLOBALS['log']->info("Found override language file: $lang.lang.override.php");
953 if(file_exists("include/language/$lang.lang.php.override")) {
954 include("include/language/$lang.lang.php.override");
955 $GLOBALS['log']->info("Found override language file: $lang.lang.php.override");
957 if(file_exists("custom/application/Ext/Language/$lang.lang.ext.php")) {
958 include("custom/application/Ext/Language/$lang.lang.ext.php");
959 $GLOBALS['log']->info("Found extended language file: $lang.lang.ext.php");
961 if(file_exists("custom/include/language/$lang.lang.php")) {
962 include("custom/include/language/$lang.lang.php");
963 $GLOBALS['log']->info("Found custom language file: $lang.lang.php");
965 $app_strings_array[] = $app_strings;
968 $app_strings = array();
969 foreach ( $app_strings_array as $app_strings_item ) {
970 $app_strings = sugarLangArrayMerge($app_strings, $app_strings_item);
973 if(!isset($app_strings)) {
974 $GLOBALS['log']->fatal("Unable to load the application language strings");
978 // If we are in debug mode for translating, turn on the prefix now!
979 if(!empty($sugar_config['translation_string_prefix']))
981 foreach($app_strings as $entry_key=>$entry_value) {
982 $app_strings[$entry_key] = $language.' '.$entry_value;
985 if(isset($_SESSION['show_deleted'])) {
986 $app_strings['LBL_DELETE_BUTTON'] = $app_strings['LBL_UNDELETE_BUTTON'];
987 $app_strings['LBL_DELETE_BUTTON_LABEL'] = $app_strings['LBL_UNDELETE_BUTTON_LABEL'];
988 $app_strings['LBL_DELETE_BUTTON_TITLE'] = $app_strings['LBL_UNDELETE_BUTTON_TITLE'];
989 $app_strings['LBL_DELETE'] = $app_strings['LBL_UNDELETE'];
992 $app_strings['LBL_ALT_HOT_KEY'] = get_alt_hot_key();
994 $return_value = $app_strings;
995 $app_strings = $temp_app_strings;
997 sugar_cache_put($cache_key, $return_value);
999 return $return_value;
1003 * This function retrieves a module's language file and returns the array of strings included.
1005 * @param string $language specific language to load
1006 * @param string $module module name to load strings for
1007 * @param bool $refresh optional, true if you want to rebuild the language strings
1008 * @return array lang strings
1010 function return_module_language($language, $module, $refresh=false)
1012 global $mod_strings;
1013 global $sugar_config;
1014 global $currentModule;
1016 // Jenny - Bug 8119: Need to check if $module is not empty
1017 if (empty($module)) {
1018 $stack = debug_backtrace();
1019 $GLOBALS['log']->warn("Variable module is not in return_module_language ". var_export($stack, true));
1025 $cache_key = LanguageManager::getLanguageCacheKey($module, $language);
1026 // Check for cached value
1027 $cache_entry = sugar_cache_retrieve($cache_key);
1028 if(!empty($cache_entry) && is_array($cache_entry))
1030 return $cache_entry;
1033 // Store the current mod strings for later
1034 $temp_mod_strings = $mod_strings;
1035 $loaded_mod_strings = array();
1036 $language_used = $language;
1037 $default_language = $sugar_config['default_language'];
1039 if(empty($language)) {
1040 $language = $default_language;
1043 // Bug 21559 - So we can get all the strings defined in the template, refresh
1044 // the vardefs file if the cached language file doesn't exist.
1045 if(!file_exists(sugar_cached('modules/'). $module . '/language/'.$language.'.lang.php')
1046 && !empty($GLOBALS['beanList'][$module])){
1047 $object = BeanFactory::getObjectName($module);
1048 VardefManager::refreshVardefs($module,$object);
1051 $loaded_mod_strings = LanguageManager::loadModuleLanguage($module, $language,$refresh);
1053 // cn: bug 6048 - merge en_us with requested language
1054 if($language != $sugar_config['default_language'])
1055 $loaded_mod_strings = sugarLangArrayMerge(
1056 LanguageManager::loadModuleLanguage($module, $sugar_config['default_language'],$refresh),
1060 // Load in en_us strings by default
1061 if($language != 'en_us' && $sugar_config['default_language'] != 'en_us')
1062 $loaded_mod_strings = sugarLangArrayMerge(
1063 LanguageManager::loadModuleLanguage($module, 'en_us', $refresh),
1067 // If we are in debug mode for translating, turn on the prefix now!
1068 if($sugar_config['translation_string_prefix']) {
1069 foreach($loaded_mod_strings as $entry_key=>$entry_value) {
1070 $loaded_mod_strings[$entry_key] = $language_used.' '.$entry_value;
1074 $return_value = $loaded_mod_strings;
1075 if(!isset($mod_strings)){
1076 $mod_strings = $return_value;
1079 $mod_strings = $temp_mod_strings;
1081 $cache_key = LanguageManager::getLanguageCacheKey($module, $language);
1082 sugar_cache_put($cache_key, $return_value);
1083 return $return_value;
1087 /** This function retrieves an application language file and returns the array of strings included in the $mod_list_strings var.
1088 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1089 * All Rights Reserved.
1090 * Contributor(s): ______________________________________..
1091 * If you are using the current language, do not call this function unless you are loading it for the first time */
1092 function return_mod_list_strings_language($language,$module) {
1093 global $mod_list_strings;
1094 global $sugar_config;
1095 global $currentModule;
1097 $cache_key = "mod_list_str_lang.".$language.$module;
1099 // Check for cached value
1100 $cache_entry = sugar_cache_retrieve($cache_key);
1101 if(!empty($cache_entry))
1103 return $cache_entry;
1106 $language_used = $language;
1107 $temp_mod_list_strings = $mod_list_strings;
1108 $default_language = $sugar_config['default_language'];
1110 if($currentModule == $module && isset($mod_list_strings) && $mod_list_strings != null) {
1111 return $mod_list_strings;
1114 // cn: bug 6351 - include en_us if file langpack not available
1115 // cn: bug 6048 - merge en_us with requested language
1116 include("modules/$module/language/en_us.lang.php");
1117 $en_mod_list_strings = array();
1118 if($language_used != $default_language)
1119 $en_mod_list_strings = $mod_list_strings;
1121 if(file_exists("modules/$module/language/$language.lang.php")) {
1122 include("modules/$module/language/$language.lang.php");
1125 if(file_exists("modules/$module/language/$language.lang.override.php")){
1126 include("modules/$module/language/$language.lang.override.php");
1129 if(file_exists("modules/$module/language/$language.lang.php.override")){
1130 echo 'Please Change:<br>' . "modules/$module/language/$language.lang.php.override" . '<br>to<br>' . 'Please Change:<br>' . "modules/$module/language/$language.lang.override.php";
1131 include("modules/$module/language/$language.lang.php.override");
1134 // cn: bug 6048 - merge en_us with requested language
1135 $mod_list_strings = sugarLangArrayMerge($en_mod_list_strings, $mod_list_strings);
1137 // if we still don't have a language pack, then log an error
1138 if(!isset($mod_list_strings)) {
1139 $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})");
1143 $return_value = $mod_list_strings;
1144 $mod_list_strings = $temp_mod_list_strings;
1146 sugar_cache_put($cache_key, $return_value);
1147 return $return_value;
1151 /** This function retrieves a theme's language file and returns the array of strings included.
1152 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1153 * All Rights Reserved.
1154 * Contributor(s): ______________________________________..
1156 function return_theme_language($language, $theme)
1158 global $mod_strings, $sugar_config, $current_language;
1160 $language_used = $language;
1161 $default_language = $sugar_config['default_language'];
1163 include(SugarThemeRegistry::get($theme)->getFilePath()."/language/$current_language.lang.php");
1164 if(file_exists(SugarThemeRegistry::get($theme)->getFilePath()."/language/$current_language.lang.override.php")){
1165 include(SugarThemeRegistry::get($theme)->getFilePath()."/language/$current_language.lang.override.php");
1167 if(file_exists(SugarThemeRegistry::get($theme)->getFilePath()."/language/$current_language.lang.php.override")){
1168 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";
1169 include(SugarThemeRegistry::get($theme)->getFilePath()."/language/$current_language.lang.php.override");
1171 if(!isset($theme_strings))
1173 $GLOBALS['log']->warn("Unable to find the theme file for language: ".$language." and theme: ".$theme);
1174 require(SugarThemeRegistry::get($theme)->getFilePath()."/language/$default_language.lang.php");
1175 $language_used = $default_language;
1178 if(!isset($theme_strings))
1180 $GLOBALS['log']->fatal("Unable to load the theme($theme) language file for the selected language($language) or the default language($default_language)");
1184 // If we are in debug mode for translating, turn on the prefix now!
1185 if($sugar_config['translation_string_prefix'])
1187 foreach($theme_strings as $entry_key=>$entry_value)
1189 $theme_strings[$entry_key] = $language_used.' '.$entry_value;
1193 return $theme_strings;
1198 /** If the session variable is defined and is not equal to "" then return it. Otherwise, return the default value.
1199 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1200 * All Rights Reserved.
1201 * Contributor(s): ______________________________________..
1203 function return_session_value_or_default($varname, $default)
1205 if(isset($_SESSION[$varname]) && $_SESSION[$varname] != "")
1207 return $_SESSION[$varname];
1214 * Creates an array of where restrictions. These are used to construct a where SQL statement on the query
1215 * 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.
1216 * @param &$where_clauses - The array to append the clause to
1217 * @param $variable_name - The name of the variable to look for an add to the where clause if found
1218 * @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.
1219 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1220 * All Rights Reserved.
1221 * Contributor(s): ______________________________________..
1223 function append_where_clause(&$where_clauses, $variable_name, $SQL_name = null)
1225 if($SQL_name == null)
1227 $SQL_name = $variable_name;
1230 if(isset($_REQUEST[$variable_name]) && $_REQUEST[$variable_name] != "")
1232 array_push($where_clauses, "$SQL_name like '".$GLOBALS['db']->quote($_REQUEST[$variable_name])."%'");
1237 * Generate the appropriate SQL based on the where clauses.
1238 * @param $where_clauses - An Array of individual where clauses stored as strings
1239 * @returns string where_clause - The final SQL where clause to be executed.
1240 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1241 * All Rights Reserved.
1242 * Contributor(s): ______________________________________..
1244 function generate_where_statement($where_clauses)
1247 foreach($where_clauses as $clause)
1254 $GLOBALS['log']->info("Here is the where clause for the list view: $where");
1259 * determines if a passed string matches the criteria for a Sugar GUID
1260 * @param string $guid
1261 * @return bool False on failure
1263 function is_guid($guid) {
1264 if(strlen($guid) != 36) {
1268 if(preg_match("/\w{8}-\w{4}-\w{4}-\w{4}-\w{12}/i", $guid)) {
1277 * A temporary method of generating GUIDs of the correct format for our DB.
1278 * @return String contianing a GUID in the format: aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
1280 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1281 * All Rights Reserved.
1282 * Contributor(s): ______________________________________..
1284 function create_guid()
1286 $microTime = microtime();
1287 list($a_dec, $a_sec) = explode(" ", $microTime);
1289 $dec_hex = dechex($a_dec* 1000000);
1290 $sec_hex = dechex($a_sec);
1292 ensure_length($dec_hex, 5);
1293 ensure_length($sec_hex, 6);
1297 $guid .= create_guid_section(3);
1299 $guid .= create_guid_section(4);
1301 $guid .= create_guid_section(4);
1303 $guid .= create_guid_section(4);
1306 $guid .= create_guid_section(6);
1312 function create_guid_section($characters)
1315 for($i=0; $i<$characters; $i++)
1317 $return .= dechex(mt_rand(0,15));
1322 function ensure_length(&$string, $length)
1324 $strlen = strlen($string);
1325 if($strlen < $length)
1327 $string = str_pad($string,$length,"0");
1329 else if($strlen > $length)
1331 $string = substr($string, 0, $length);
1335 function microtime_diff($a, $b) {
1336 list($a_dec, $a_sec) = explode(" ", $a);
1337 list($b_dec, $b_sec) = explode(" ", $b);
1338 return $b_sec - $a_sec + $b_dec - $a_dec;
1341 // check if Studio is displayed.
1342 function displayStudioForCurrentUser()
1344 global $current_user;
1345 if ( $current_user->isAdmin() ) {
1355 function displayWorkflowForCurrentUser()
1357 $_SESSION['display_workflow_for_user'] = false;
1361 // return an array with all modules where the user is an admin.
1362 function get_admin_modules_for_user($user) {
1363 $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");
1370 return($user->getDeveloperModules());
1374 function get_workflow_admin_modules_for_user($user){
1375 if (isset($_SESSION['get_workflow_admin_modules_for_user'])) {
1376 return $_SESSION['get_workflow_admin_modules_for_user'];
1380 $workflow_mod_list = array();
1381 foreach($moduleList as $module){
1382 $workflow_mod_list[$module] = $module;
1385 // This list is taken from teh previous version of workflow_utils.php
1386 $workflow_mod_list['Tasks'] = "Tasks";
1387 $workflow_mod_list['Calls'] = "Calls";
1388 $workflow_mod_list['Meetings'] = "Meetings";
1389 $workflow_mod_list['Notes'] = "Notes";
1390 $workflow_mod_list['ProjectTask'] = "Project Tasks";
1391 $workflow_mod_list['Leads'] = "Leads";
1392 $workflow_mod_list['Opportunities'] = "Opportunities";
1395 $workflow_admin_modules = array();
1397 return $workflow_admin_modules;
1399 $actions = ACLAction::getUserActions($user->id);
1400 //check for ForecastSchedule because it doesn't exist in $workflow_mod_list
1401 if (isset($actions['ForecastSchedule']['module']['admin']['aclaccess']) && ($actions['ForecastSchedule']['module']['admin']['aclaccess']==ACL_ALLOW_DEV ||
1402 $actions['ForecastSchedule']['module']['admin']['aclaccess']==ACL_ALLOW_ADMIN_DEV)) {
1403 $workflow_admin_modules['Forecasts'] = 'Forecasts';
1405 foreach ($workflow_mod_list as $key=>$val) {
1406 if(!in_array($val, $workflow_admin_modules) && ($val!='iFrames' && $val!='Feeds' && $val!='Home' && $val!='Dashboard'
1407 && $val!='Calendar' && $val!='Activities' && $val!='Reports') &&
1408 ($user->isDeveloperForModule($key))) {
1409 $workflow_admin_modules[$key] = $val;
1412 $_SESSION['get_workflow_admin_modules_for_user'] = $workflow_admin_modules;
1413 return ($workflow_admin_modules);
1416 // Check if user is admin for at least one module.
1417 function is_admin_for_any_module($user) {
1421 if($user->isAdmin()) {
1428 // Check if user is admin for a specific module.
1429 function is_admin_for_module($user,$module) {
1430 if (!isset($user)) {
1433 if ($user->isAdmin()) {
1441 * Check if user id belongs to a system admin.
1442 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1443 * All Rights Reserved.
1444 * Contributor(s): ______________________________________..
1446 function is_admin($user) {
1451 return $user->isAdmin();
1455 * Return the display name for a theme if it exists.
1456 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1457 * All Rights Reserved.
1458 * Contributor(s): ______________________________________..
1460 * @deprecated use SugarThemeRegistry::get($theme)->name instead
1462 function get_theme_display($theme)
1464 return SugarThemeRegistry::get($theme)->name;
1468 * Return an array of directory names.
1469 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1470 * All Rights Reserved.
1471 * Contributor(s): ______________________________________..
1473 * @deprecated use SugarThemeRegistry::availableThemes() instead.
1475 function get_themes()
1477 return SugarThemeRegistry::availableThemes();
1481 * THIS FUNCTION IS DEPRECATED AND SHOULD NOT BE USED; USE get_select_options_with_id()
1482 * Create HTML to display select options in a dropdown list. To be used inside
1483 * of a select statement in a form.
1484 * param $option_list - the array of strings to that contains the option list
1485 * param $selected - the string which contains the default value
1486 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1487 * All Rights Reserved.
1488 * Contributor(s): ______________________________________..
1490 function get_select_options ($option_list, $selected) {
1491 return get_select_options_with_id($option_list, $selected);
1495 * Create HTML to display select options in a dropdown list. To be used inside
1496 * 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.
1497 * param $option_list - the array of strings to that contains the option list
1498 * param $selected - the string which contains the default value
1499 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1500 * All Rights Reserved.
1501 * Contributor(s): ______________________________________..
1503 function get_select_options_with_id ($option_list, $selected_key) {
1504 return get_select_options_with_id_separate_key($option_list, $option_list, $selected_key);
1509 * Create HTML to display select options in a dropdown list. To be used inside
1510 * 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.
1511 * param $label_list - the array of strings to that contains the option list
1512 * param $key_list - the array of strings to that contains the values list
1513 * param $selected - the string which contains the default value
1514 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1515 * All Rights Reserved.
1516 * Contributor(s): ______________________________________..
1518 function get_select_options_with_id_separate_key ($label_list, $key_list, $selected_key, $massupdate=false) {
1519 global $app_strings;
1520 $select_options = "";
1522 //for setting null selection values to human readable --None--
1523 $pattern = "/'0?'></";
1524 $replacement = "''>".$app_strings['LBL_NONE']."<";
1526 $replacement .= "/OPTION>\n<OPTION value='__SugarMassUpdateClearField__'><"; // Giving the user the option to unset a drop down list. I.e. none means that it won't get updated
1529 if (empty($key_list)) $key_list = array();
1530 //create the type dropdown domain and set the selected value if $opp value already exists
1531 foreach ($key_list as $option_key=>$option_value) {
1533 $selected_string = '';
1534 // the system is evaluating $selected_key == 0 || '' to true. Be very careful when changing this. Test all cases.
1535 // The bug was only happening with one of the users in the drop down. It was being replaced by none.
1537 ($option_key != '' && $selected_key == $option_key)
1540 && (($selected_key == '' && !$massupdate) || $selected_key == '__SugarMassUpdateClearField__')
1542 || (is_array($selected_key) && in_array($option_key, $selected_key))
1544 $selected_string = 'selected ';
1547 $html_value = $option_key;
1549 $select_options .= "\n<OPTION ".$selected_string."value='$html_value'>$label_list[$option_key]</OPTION>";
1551 $select_options = preg_replace($pattern, $replacement, $select_options);
1552 return $select_options;
1557 * Call this method instead of die().
1558 * We print the error message and then die with an appropriate
1561 function sugar_die($error_message, $exit_code = 1)
1565 echo $error_message;
1571 * Create javascript to clear values of all elements in a form.
1572 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1573 * All Rights Reserved.
1574 * Contributor(s): ______________________________________..
1576 function get_clear_form_js () {
1577 $the_script = <<<EOQ
1578 <script type="text/javascript" language="JavaScript">
1579 function clear_form(form) {
1580 var newLoc = 'index.php?action=' + form.action.value + '&module=' + form.module.value + '&query=true&clear_query=true';
1581 if(typeof(form.advanced) != 'undefined'){
1582 newLoc += '&advanced=' + form.advanced.value;
1584 document.location.href= newLoc;
1593 * Create javascript to set the cursor focus to specific field in a form
1594 * when the screen is rendered. The field name is currently hardcoded into the
1596 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1597 * All Rights Reserved.
1598 * Contributor(s): ______________________________________..
1600 function get_set_focus_js () {
1601 //TODO Clint 5/20 - Make this function more generic so that it can take in the target form and field names as variables
1602 $the_script = <<<EOQ
1603 <script type="text/javascript" language="JavaScript">
1605 function set_focus() {
1606 if (document.forms.length > 0) {
1607 for (i = 0; i < document.forms.length; i++) {
1608 for (j = 0; j < document.forms[i].elements.length; j++) {
1609 var field = document.forms[i].elements[j];
1610 if ((field.type == "text" || field.type == "textarea" || field.type == "password") &&
1611 !field.disabled && (field.name == "first_name" || field.name == "name" || field.name == "user_name" || field.name=="document_name")) {
1613 if (field.type == "text") {
1630 * Very cool algorithm for sorting multi-dimensional arrays. Found at http://us2.php.net/manual/en/function.array-multisort.php
1631 * Syntax: $new_array = array_csort($array [, 'col1' [, SORT_FLAG [, SORT_FLAG]]]...);
1632 * Explanation: $array is the array you want to sort, 'col1' is the name of the column
1633 * you want to sort, SORT_FLAGS are : SORT_ASC, SORT_DESC, SORT_REGULAR, SORT_NUMERIC, SORT_STRING
1634 * you can repeat the 'col',FLAG,FLAG, as often you want, the highest prioritiy is given to
1635 * the first - so the array is sorted by the last given column first, then the one before ...
1636 * Example: $array = array_csort($array,'town','age',SORT_DESC,'name');
1637 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1638 * All Rights Reserved.
1639 * Contributor(s): ______________________________________..
1641 function array_csort() {
1642 $args = func_get_args();
1643 $marray = array_shift($args);
1646 $msortline = "return(array_multisort(";
1647 foreach ($args as $arg) {
1649 if (is_string($arg)) {
1650 foreach ($marray as $row) {
1651 $sortarr[$i][] = $row[$arg];
1654 $sortarr[$i] = $arg;
1656 $msortline .= "\$sortarr[".$i."],";
1658 $msortline .= "\$marray));";
1665 * Converts localized date format string to jscalendar format
1666 * Example: $array = array_csort($array,'town','age',SORT_DESC,'name');
1667 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1668 * All Rights Reserved.
1669 * Contributor(s): ______________________________________..
1671 function parse_calendardate($local_format) {
1672 preg_match('/\(?([^-]{1})[^-]*-([^-]{1})[^-]*-([^-]{1})[^-]*\)/', $local_format, $matches);
1673 $calendar_format = "%" . $matches[1] . "-%" . $matches[2] . "-%" . $matches[3];
1674 return str_replace(array("y", "ᅣ1�7", "a", "j"), array("Y", "Y", "Y", "d"), $calendar_format);
1681 function translate($string, $mod='', $selectedValue=''){
1682 //$test_start = microtime();
1683 //static $mod_strings_results = array();
1685 global $current_language;
1687 if(isset($_REQUEST['login_language'])){
1688 $current_language = ($_REQUEST['login_language'] == $current_language)? $current_language : $_REQUEST['login_language'];
1690 $mod_strings = return_module_language($current_language, $mod);
1692 echo "Language is <pre>" . $mod_strings . "</pre>";
1695 global $mod_strings;
1699 global $app_strings, $app_list_strings;
1701 if (isset($mod_strings[$string]))
1702 $returnValue = $mod_strings[$string];
1703 else if (isset($app_strings[$string]))
1704 $returnValue = $app_strings[$string];
1705 else if (isset($app_list_strings[$string]))
1706 $returnValue = $app_list_strings[$string];
1707 else if (isset($app_list_strings['moduleList']) && isset($app_list_strings['moduleList'][$string]))
1708 $returnValue = $app_list_strings['moduleList'][$string];
1711 //$test_end = microtime();
1713 // $mod_strings_results[$mod] = microtime_diff($test_start,$test_end);
1715 // echo("translate results:");
1717 // $total_strings = 0;
1718 // foreach($mod_strings_results as $key=>$value)
1720 // echo("Module $key \t\t time $value \t\t<br>");
1721 // $total_time += $value;
1724 // echo("Total time: $total_time<br>");
1728 if(empty($returnValue)){
1732 // Bug 48996 - Custom enums with '0' value were not returning because of empty check
1733 // Added a numeric 0 checker to the conditional to allow 0 value indexed to pass
1734 if(is_array($returnValue) && (!empty($selectedValue) || (is_numeric($selectedValue) && $selectedValue == 0)) && isset($returnValue[$selectedValue]) ){
1735 return $returnValue[$selectedValue];
1738 return $returnValue;
1741 function unTranslateNum($num) {
1743 static $num_grp_sep;
1744 global $current_user, $sugar_config;
1746 if($dec_sep == null) {
1747 $user_dec_sep = $current_user->getPreference('dec_sep');
1748 $dec_sep = (empty($user_dec_sep) ? $sugar_config['default_decimal_seperator'] : $user_dec_sep);
1750 if($num_grp_sep == null) {
1751 $user_num_grp_sep = $current_user->getPreference('num_grp_sep');
1752 $num_grp_sep = (empty($user_num_grp_sep) ? $sugar_config['default_number_grouping_seperator'] : $user_num_grp_sep);
1755 $num = preg_replace("'" . preg_quote($num_grp_sep) . "'", '', $num);
1756 $num = preg_replace("'" . preg_quote($dec_sep) . "'", '.', $num);
1761 function add_http($url) {
1762 if(!preg_match("@://@i", $url)) {
1764 if(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') {
1768 return "{$scheme}://{$url}";
1775 * returns a default array of XSS tags to clean
1778 function getDefaultXssTags() {
1780 "applet" => "applet",
1785 "frameset" => "frameset",
1786 "iframe" => "iframe",
1787 "import" => "\?import",
1790 "object" => "object",
1791 "script" => "script",
1795 $ret = base64_encode(serialize($tmp));
1801 * Remove potential xss vectors from strings
1802 * @param string str String to search for XSS attack vectors
1806 function remove_xss($str)
1808 return SugarCleaner::cleanHtml($str, false);
1812 * Detects typical XSS attack patterns
1814 * @param string str String to search for XSS attack vectors
1815 * @param bool cleanImg Flag to allow <img> tags to survive - only used by InboundEmail for inline images.
1816 * @return array Array of matches, empty on clean string
1818 function clean_xss($str, $cleanImg=true) {
1819 global $sugar_config;
1821 if(empty($sugar_config['email_xss']))
1822 $sugar_config['email_xss'] = getDefaultXssTags();
1824 $xsstags = unserialize(base64_decode($sugar_config['email_xss']));
1826 // cn: bug 13079 - "on\w" matched too many non-events (cONTact, strONG, etc.)
1827 $jsEvents = "onblur|onfocus|oncontextmenu|onresize|onscroll|onunload|ondblclick|onclick|";
1828 $jsEvents .= "onmouseup|onmouseover|onmousedown|onmouseenter|onmouseleave|onmousemove|onload|onchange|";
1829 $jsEvents .= "onreset|onselect|onsubmit|onkeydown|onkeypress|onkeyup|onabort|onerror|ondragdrop";
1831 $attribute_regex = "#\b({$jsEvents})\s*=\s*(?|(?!['\"])\S+|['\"].+?['\"])#sim";
1832 $javascript_regex = '@<[^/>][^>]+(expression\(|j\W*a\W*v\W*a|v\W*b\W*s\W*c\W*r|&#|/\*|\*/)[^>]*>@sim';
1833 $imgsrc_regex = '#<[^>]+src[^=]*=([^>]*?http(s)?://[^>]*)>#sim';
1834 $css_url = '#url\(.*\.\w+\)#';
1836 $tagsrex = '#<\/?(\w+)((?:\s+(?:\w|\w[\w-]*\w)(?:\s*=\s*(?:\".*?\"|\'.*?\'|[^\'\">\s]+))?)+\s*|\s*)\/?>#im';
1838 $tagmatches = array();
1840 preg_match_all($tagsrex, $str, $tagmatches, PREG_PATTERN_ORDER);
1841 foreach($tagmatches[1] as $no => $tag) {
1842 if(in_array($tag, $xsstags)) {
1843 // dangerous tag - take out whole
1844 $matches[] = $tagmatches[0][$no];
1847 $attrmatch = array();
1848 preg_match_all($attribute_regex, $tagmatches[2][$no], $attrmatch, PREG_PATTERN_ORDER);
1849 if(!empty($attrmatch[0])) {
1850 $matches = array_merge($matches, $attrmatch[0]);
1854 $matches = array_merge($matches, xss_check_pattern($javascript_regex, $str));
1857 $matches = array_merge($matches,
1858 xss_check_pattern($imgsrc_regex, $str)
1862 // cn: bug 13498 - custom white-list of allowed domains that vet remote images
1863 preg_match_all($css_url, $str, $cssUrlMatches, PREG_PATTERN_ORDER);
1865 if(isset($sugar_config['security_trusted_domains']) && !empty($sugar_config['security_trusted_domains']) && is_array($sugar_config['security_trusted_domains'])) {
1866 if(is_array($cssUrlMatches) && count($cssUrlMatches) > 0) {
1867 // normalize whitelist
1868 foreach($sugar_config['security_trusted_domains'] as $k => $v) {
1869 $sugar_config['security_trusted_domains'][$k] = strtolower($v);
1872 foreach($cssUrlMatches[0] as $match) {
1873 $domain = strtolower(substr(strstr($match, "://"), 3));
1874 $baseUrl = substr($domain, 0, strpos($domain, "/"));
1876 if(!in_array($baseUrl, $sugar_config['security_trusted_domains'])) {
1877 $matches[] = $match;
1882 $matches = array_merge($matches, $cssUrlMatches[0]);
1889 * Helper function used by clean_xss() to parse for known-bad vectors
1890 * @param string pattern Regex pattern to use
1891 * @param string str String to parse for badness
1894 function xss_check_pattern($pattern, $str) {
1895 preg_match_all($pattern, $str, $matches, PREG_PATTERN_ORDER);
1900 * Designed to take a string passed in the URL as a parameter and clean all "bad" data from it
1902 * @param string $str
1903 * @param string $filter which corresponds to a regular expression to use; choices are:
1904 * "STANDARD" ( default )
1914 * @param boolean $dieOnBadData true (default) if you want to die if bad data if found, false if not
1916 function clean_string($str, $filter = "STANDARD", $dieOnBadData = true)
1918 global $sugar_config;
1921 "STANDARD" => '#[^A-Z0-9\-_\.\@]#i',
1922 "STANDARDSPACE" => '#[^A-Z0-9\-_\.\@\ ]#i',
1923 "FILE" => '#[^A-Z0-9\-_\.]#i',
1924 "NUMBER" => '#[^0-9\-]#i',
1925 "SQL_COLUMN_LIST" => '#[^A-Z0-9\(\),_\.]#i',
1926 "PATH_NO_URL" => '#://#i',
1927 "SAFED_GET" => '#[^A-Z0-9\@\=\&\?\.\/\-_~+]#i', /* range of allowed characters in a GET string */
1928 "UNIFIED_SEARCH" => "#[\\x00]#", /* cn: bug 3356 & 9236 - MBCS search strings */
1929 "AUTO_INCREMENT" => '#[^0-9\-,\ ]#i',
1930 "ALPHANUM" => '#[^A-Z0-9\-]#i',
1933 if (preg_match($filters[$filter], $str)) {
1934 if (isset($GLOBALS['log']) && is_object($GLOBALS['log'])) {
1935 $GLOBALS['log']->fatal("SECURITY[$filter]: bad data passed in; string: {$str}");
1937 if ( $dieOnBadData ) {
1938 die("Bad data passed in; <a href=\"{$sugar_config['site_url']}\">Return to Home</a>");
1947 function clean_special_arguments() {
1948 if(isset($_SERVER['PHP_SELF'])) {
1949 if (!empty($_SERVER['PHP_SELF'])) clean_string($_SERVER['PHP_SELF'], 'SAFED_GET');
1951 if (!empty($_REQUEST) && !empty($_REQUEST['login_theme'])) clean_string($_REQUEST['login_theme'], "STANDARD");
1952 if (!empty($_REQUEST) && !empty($_REQUEST['login_module'])) clean_string($_REQUEST['login_module'], "STANDARD");
1953 if (!empty($_REQUEST) && !empty($_REQUEST['login_action'])) clean_string($_REQUEST['login_action'], "STANDARD");
1954 if (!empty($_REQUEST) && !empty($_REQUEST['ck_login_theme_20'])) clean_string($_REQUEST['ck_login_theme_20'], "STANDARD");
1955 if (!empty($_SESSION) && !empty($_SESSION['authenticated_user_theme'])) clean_string($_SESSION['authenticated_user_theme'], "STANDARD");
1956 if (!empty($_REQUEST) && !empty($_REQUEST['module_name'])) clean_string($_REQUEST['module_name'], "STANDARD");
1957 if (!empty($_REQUEST) && !empty($_REQUEST['module'])) clean_string($_REQUEST['module'], "STANDARD");
1958 if (!empty($_POST) && !empty($_POST['parent_type'])) clean_string($_POST['parent_type'], "STANDARD");
1959 if (!empty($_REQUEST) && !empty($_REQUEST['mod_lang'])) clean_string($_REQUEST['mod_lang'], "STANDARD");
1960 if (!empty($_SESSION) && !empty($_SESSION['authenticated_user_language'])) clean_string($_SESSION['authenticated_user_language'], "STANDARD");
1961 if (!empty($_SESSION) && !empty($_SESSION['dyn_layout_file'])) clean_string($_SESSION['dyn_layout_file'], "PATH_NO_URL");
1962 if (!empty($_GET) && !empty($_GET['from'])) clean_string($_GET['from']);
1963 if (!empty($_GET) && !empty($_GET['gmto'])) clean_string($_GET['gmto'], "NUMBER");
1964 if (!empty($_GET) && !empty($_GET['case_number'])) clean_string($_GET['case_number'], "AUTO_INCREMENT");
1965 if (!empty($_GET) && !empty($_GET['bug_number'])) clean_string($_GET['bug_number'], "AUTO_INCREMENT");
1966 if (!empty($_GET) && !empty($_GET['quote_num'])) clean_string($_GET['quote_num'], "AUTO_INCREMENT");
1967 clean_superglobals('stamp', 'ALPHANUM'); // for vcr controls
1968 clean_superglobals('offset', 'ALPHANUM');
1969 clean_superglobals('return_action');
1970 clean_superglobals('return_module');
1975 * cleans the given key in superglobals $_GET, $_POST, $_REQUEST
1977 function clean_superglobals($key, $filter = 'STANDARD') {
1978 if(isset($_GET[$key])) clean_string($_GET[$key], $filter);
1979 if(isset($_POST[$key])) clean_string($_POST[$key], $filter);
1980 if(isset($_REQUEST[$key])) clean_string($_REQUEST[$key], $filter);
1983 function set_superglobals($key, $val){
1985 $_POST[$key] = $val;
1986 $_REQUEST[$key] = $val;
1989 // Works in conjunction with clean_string() to defeat SQL injection, file inclusion attacks, and XSS
1990 function clean_incoming_data() {
1991 global $sugar_config;
1992 global $RAW_REQUEST;
1994 if(get_magic_quotes_gpc()) {
1995 // magic quotes screw up data, we'd have to clean up
1996 $RAW_REQUEST = array_map("cleanup_slashes", $_REQUEST);
1998 $RAW_REQUEST = $_REQUEST;
2001 if (get_magic_quotes_gpc() == 1) {
2002 $req = array_map("preprocess_param", $_REQUEST);
2003 $post = array_map("preprocess_param", $_POST);
2004 $get = array_map("preprocess_param", $_GET);
2007 $req = array_map("securexss", $_REQUEST);
2008 $post = array_map("securexss", $_POST);
2009 $get = array_map("securexss", $_GET);
2012 // PHP cannot stomp out superglobals reliably
2013 foreach($post as $k => $v) { $_POST[$k] = $v; }
2014 foreach($get as $k => $v) { $_GET[$k] = $v; }
2015 foreach($req as $k => $v) {
2018 //ensure the keys are safe as well. If mbstring encoding translation is on, the post keys don't
2019 //get translated, so scrub the data but don't die
2020 if(ini_get('mbstring.encoding_translation')==='1'){
2021 securexsskey($k,false);
2023 securexsskey($k,true);
2027 // Any additional variables that need to be cleaned should be added here
2028 if (isset($_REQUEST['login_theme'])) clean_string($_REQUEST['login_theme']);
2029 if (isset($_REQUEST['login_module'])) clean_string($_REQUEST['login_module']);
2030 if (isset($_REQUEST['login_action'])) clean_string($_REQUEST['login_action']);
2031 if (isset($_REQUEST['login_language'])) clean_string($_REQUEST['login_language']);
2032 if (isset($_REQUEST['action'])) clean_string($_REQUEST['action']);
2033 if (isset($_REQUEST['module'])) clean_string($_REQUEST['module']);
2034 if (isset($_REQUEST['record'])) clean_string($_REQUEST['record'], 'STANDARDSPACE');
2035 if (isset($_SESSION['authenticated_user_theme'])) clean_string($_SESSION['authenticated_user_theme']);
2036 if (isset($_SESSION['authenticated_user_language'])) clean_string($_SESSION['authenticated_user_language']);
2037 if (isset($_REQUEST['language'])) clean_string($_REQUEST['language']);
2038 if (isset($sugar_config['default_theme'])) clean_string($sugar_config['default_theme']);
2039 if (isset($_REQUEST['offset'])) clean_string($_REQUEST['offset']);
2040 if (isset($_REQUEST['stamp'])) clean_string($_REQUEST['stamp']);
2042 if(isset($_REQUEST['lvso'])){
2043 set_superglobals('lvso', (strtolower($_REQUEST['lvso']) === 'desc')?'desc':'asc');
2045 // Clean "offset" and "order_by" parameters in URL
2046 foreach ($_REQUEST as $key => $val) {
2047 if (str_end($key, "_offset")) {
2048 clean_string($_REQUEST[$key], "ALPHANUM"); // keep this ALPHANUM for disable_count_query
2049 set_superglobals($key, $_REQUEST[$key]);
2051 elseif (str_end($key, "_ORDER_BY")) {
2052 clean_string($_REQUEST[$key], "SQL_COLUMN_LIST");
2053 set_superglobals($key, $_REQUEST[$key]);
2061 // Returns TRUE if $str begins with $begin
2062 function str_begin($str, $begin) {
2063 return (substr($str, 0, strlen($begin)) == $begin);
2066 // Returns TRUE if $str ends with $end
2067 function str_end($str, $end) {
2068 return (substr($str, strlen($str) - strlen($end)) == $end);
2071 function securexss($value) {
2072 if(is_array($value)){
2074 foreach($value as $key=>$val){
2075 $new[$key] = securexss($val);
2079 static $xss_cleanup= array(""" => "&", '"' =>'"', "'" => ''' , '<' =>'<' , '>'=>'>');
2080 $value = preg_replace(array('/javascript:/i', '/\0/'), array('java script:', ''), $value);
2081 $value = preg_replace('/javascript:/i', 'java script:', $value);
2082 return str_replace(array_keys($xss_cleanup), array_values($xss_cleanup), $value);
2085 function securexsskey($value, $die=true){
2086 global $sugar_config;
2088 preg_match('/[\'"<>]/', $value, $matches);
2089 if(!empty($matches)){
2091 die("Bad data passed in; <a href=\"{$sugar_config['site_url']}\">Return to Home</a>");
2093 unset($_REQUEST[$value]);
2094 unset($_POST[$value]);
2095 unset($_GET[$value]);
2100 function preprocess_param($value){
2101 if(is_string($value)){
2102 if(get_magic_quotes_gpc() == 1){
2103 $value = stripslashes($value);
2106 $value = securexss($value);
2108 else if (is_array($value)){
2109 foreach ($value as $key => $element) {
2110 $value[$key] = preprocess_param($element);
2117 function cleanup_slashes($value)
2119 if(is_string($value)) return stripslashes($value);
2124 function set_register_value($category, $name, $value){
2125 return sugar_cache_put("{$category}:{$name}", $value);
2128 function get_register_value($category,$name){
2129 return sugar_cache_retrieve("{$category}:{$name}");
2132 function clear_register_value($category,$name){
2133 return sugar_cache_clear("{$category}:{$name}");
2135 // this function cleans id's when being imported
2136 function convert_id($string)
2138 return preg_replace_callback( '|[^A-Za-z0-9\-]|',
2140 // single quotes are essential here,
2141 // or alternative escape all $ as \$
2143 'return ord($matches[0]);'
2148 * @deprecated use SugarTheme::getImage()
2150 function get_image($image,$other_attributes,$width="",$height="",$ext='.gif',$alt="")
2152 return SugarThemeRegistry::current()->getImage(basename($image), $other_attributes, empty($width) ? null : $width, empty($height) ? null : $height, $ext, $alt );
2155 * @deprecated use SugarTheme::getImageURL()
2157 function getImagePath($image_name)
2159 return SugarThemeRegistry::current()->getImageURL($image_name);
2162 function getWebPath($relative_path){
2163 //if it has a :// then it isn't a relative path
2164 if(substr_count($relative_path, '://') > 0) return $relative_path;
2165 if(defined('TEMPLATE_URL'))$relative_path = SugarTemplateUtilities::getWebPath($relative_path);
2166 return $relative_path;
2169 function getVersionedPath($path, $additional_attrs='')
2171 if(empty($GLOBALS['sugar_config']['js_custom_version'])) $GLOBALS['sugar_config']['js_custom_version'] = 1;
2172 $js_version_key = isset($GLOBALS['js_version_key'])?$GLOBALS['js_version_key']:'';
2173 if(inDeveloperMode()) {
2175 if(empty($rand)) $rand = mt_rand();
2180 if(is_array($additional_attrs)) {
2181 $additional_attrs = join("|",$additional_attrs);
2183 // cutting 2 last chars here because since md5 is 32 chars, it's always ==
2184 $str = substr(base64_encode(md5("$js_version_key|{$GLOBALS['sugar_config']['js_custom_version']}|$dev|$additional_attrs", true)), 0, -2);
2185 // remove / - it confuses some parsers
2186 $str = strtr($str, '/+', '-_');
2187 if(empty($path)) return $str;
2189 return $path . "?v=$str";
2192 function getVersionedScript($path, $additional_attrs='')
2194 return '<script type="text/javascript" src="'.getVersionedPath($path, $additional_attrs).'"></script>';
2197 function getJSPath($relative_path, $additional_attrs='')
2199 if(defined('TEMPLATE_URL'))$relative_path = SugarTemplateUtilities::getWebPath($relative_path);
2200 return getVersionedPath($relative_path).(!empty($additional_attrs)?"&$additional_attrs":"");
2203 function getSWFPath($relative_path, $additional_params=''){
2204 $path = $relative_path;
2205 if (!empty($additional_params)){
2206 $path .= '?' . $additional_params;
2208 if (defined('TEMPLATE_URL')){
2209 $path = TEMPLATE_URL . '/' . $path;
2218 function getSQLDate($date_str)
2220 if (preg_match('/^(\d{1,2})-(\d{1,2})-(\d{4})$/',$date_str,$match))
2222 if ( strlen($match[2]) == 1)
2224 $match[2] = "0".$match[2];
2226 if ( strlen($match[1]) == 1)
2228 $match[1] = "0".$match[1];
2230 return "{$match[3]}-{$match[1]}-{$match[2]}";
2232 else if (preg_match('/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/',$date_str,$match))
2234 if ( strlen($match[2]) == 1)
2236 $match[2] = "0".$match[2];
2238 if ( strlen($match[1]) == 1)
2240 $match[1] = "0".$match[1];
2242 return "{$match[3]}-{$match[1]}-{$match[2]}";
2250 function clone_history(&$db, $from_id,$to_id, $to_type)
2255 require_once('include/upload_file.php');
2256 $tables = array('calls'=>'Call', 'meetings'=>'Meeting', 'notes'=>'Note', 'tasks'=>'Task');
2258 $location=array('Email'=>"modules/Emails/Email.php",
2259 'Call'=>"modules/Calls/Call.php",
2260 'Meeting'=>"modules/Meetings/Meeting.php",
2261 'Note'=>"modules/Notes/Note.php",
2262 'Tasks'=>"modules/Tasks/Task.php",
2266 foreach($tables as $table=>$bean_class)
2269 if (!class_exists($bean_class))
2271 require_once($location[$bean_class]);
2274 $bProcessingNotes=false;
2275 if ($table=='notes')
2277 $bProcessingNotes=true;
2279 $query = "SELECT id FROM $table WHERE parent_id='$from_id'";
2280 $results = $db->query($query);
2281 while($row = $db->fetchByAssoc($results))
2283 //retrieve existing record.
2284 $bean= new $bean_class();
2285 $bean->retrieve($row['id']);
2286 //process for new instance.
2287 if ($bProcessingNotes)
2289 $old_note_id=$row['id'];
2290 $old_filename=$bean->filename;
2293 $bean->parent_id=$to_id;
2294 $bean->parent_type=$to_type;
2295 if ($to_type=='Contacts' and in_array('contact_id',$bean->column_fields))
2297 $bean->contact_id=$to_id;
2299 $bean->update_date_modified = false;
2300 $bean->update_modified_by = false;
2301 if(isset($bean->date_modified))
2302 $bean->date_modified = $timedate->to_db($bean->date_modified);
2303 if(isset($bean->date_entered))
2304 $bean->date_entered = $timedate->to_db($bean->date_entered);
2306 $new_id=$bean->save();
2308 //duplicate the file now. for notes.
2309 if ($bProcessingNotes && !empty($old_filename))
2311 UploadFile::duplicate_file($old_note_id,$new_id,$old_filename);
2313 //reset the values needed for attachment duplication.
2320 function values_to_keys($array)
2322 $new_array = array();
2323 if(!is_array($array))
2327 foreach($array as $arr){
2328 $new_array[$arr] = $arr;
2333 function clone_relationship(&$db, $tables = array(), $from_column, $from_id, $to_id)
2335 foreach($tables as $table)
2338 if ($table == 'emails_beans') {
2339 $query = "SELECT * FROM $table WHERE $from_column='$from_id' and bean_module='Leads'";
2341 $query = "SELECT * FROM $table WHERE $from_column='$from_id'";
2343 $results = $db->query($query);
2344 while($row = $db->fetchByAssoc($results))
2346 $query = "INSERT INTO $table ";
2349 $row[$from_column] = $to_id;
2350 $row['id'] = create_guid();
2351 if ($table=='emails_beans') {
2352 $row['bean_module'] =='Contacts';
2355 foreach($row as $name=>$value)
2361 $values .= "'$value'";
2364 $names .= ', '. $name;
2365 $values .= ", '$value'";
2368 $query .= "($names) VALUES ($values)";
2374 function get_unlinked_email_query($type, $bean) {
2375 global $current_user;
2377 $return_array['select']='SELECT emails.id ';
2378 $return_array['from']='FROM emails ';
2379 $return_array['where']="";
2380 $return_array['join'] = " JOIN (select DISTINCT email_id from emails_email_addr_rel eear
2382 join email_addr_bean_rel eabr on eabr.bean_id ='$bean->id' and eabr.bean_module = '$bean->module_dir' and
2383 eabr.email_address_id = eear.email_address_id and eabr.deleted=0
2384 where eear.deleted=0 and eear.email_id not in
2385 (select eb.email_id from emails_beans eb where eb.bean_module ='$bean->module_dir' and eb.bean_id = '$bean->id')
2386 ) derivedemails on derivedemails.email_id = emails.id";
2387 $return_array['join_tables'][0] = '';
2389 if (isset($type) and !empty($type['return_as_array'])) {
2390 return $return_array;
2393 return $return_array['select'] . $return_array['from'] . $return_array['where'] . $return_array['join'] ;
2396 function get_emails_by_assign_or_link($params)
2398 $relation = $params['link'];
2399 $bean = $GLOBALS['app']->controller->bean;
2400 if(empty($bean->$relation)) {
2401 $bean->load_relationship($relation);
2403 if(empty($bean->$relation)) {
2404 $GLOBALS['log']->error("Bad relation '$relation' for bean '{$bean->object_name}' id '{$bean->id}'");
2407 $rel_module = $bean->$relation->getRelatedModuleName();
2408 $rel_join = $bean->$relation->getJoin(array(
2409 'join_table_alias' => 'link_bean',
2410 'join_table_link_alias' => 'linkt',
2412 $rel_join = str_replace("{$bean->table_name}.id", "'{$bean->id}'", $rel_join);
2413 $return_array['select']='SELECT DISTINCT emails.id ';
2414 $return_array['from'] = "FROM emails ";
2416 $return_array['join'] = array();
2418 // directly assigned emails
2419 $return_array['join'][] = "
2426 eb.bean_module = '{$bean->module_dir}'
2427 AND eb.bean_id = '{$bean->id}'
2431 // Related by directly by email
2432 $return_array['join'][] = "
2437 emails_email_addr_rel eear
2439 email_addr_bean_rel eabr
2441 eabr.bean_id ='{$bean->id}'
2442 AND eabr.bean_module = '{$bean->module_dir}'
2443 AND eabr.email_address_id = eear.email_address_id
2449 $showEmailsOfRelatedContacts = empty($bean->field_defs[$relation]['hide_history_contacts_emails']);
2450 if (!empty($GLOBALS['sugar_config']['hide_history_contacts_emails']) && isset($GLOBALS['sugar_config']['hide_history_contacts_emails'][$bean->module_name])) {
2451 $showEmailsOfRelatedContacts = empty($GLOBALS['sugar_config']['hide_history_contacts_emails'][$bean->module_name]);
2453 if ($showEmailsOfRelatedContacts) {
2454 // Assigned to contacts
2455 $return_array['join'][] = "
2461 $rel_join AND link_bean.id = eb.bean_id
2463 eb.bean_module = '$rel_module'
2466 // Related by email to linked contact
2467 $return_array['join'][] = "
2470 'relate_contact' source
2472 emails_email_addr_rel eear
2474 email_addr_bean_rel eabr
2476 eabr.email_address_id=eear.email_address_id
2477 AND eabr.bean_module = '$rel_module'
2479 $rel_join AND link_bean.id = eabr.bean_id
2485 $return_array['join'] = " INNER JOIN (" . implode(" UNION ", $return_array['join']). ") email_ids ON emails.id=email_ids.email_id ";
2487 $return_array['where']=" WHERE emails.deleted=0 ";
2489 //$return_array['join'] = '';
2490 $return_array['join_tables'][0] = '';
2492 if($bean->object_name == "Case" && !empty($bean->case_number)) {
2493 $where = str_replace("%1", $bean->case_number, $bean->getEmailSubjectMacro());
2494 $return_array["where"] .= "\n AND (email_ids.source = 'direct' OR emails.name LIKE '%$where%')";
2497 return $return_array;
2501 * Check to see if the number is empty or non-zero
2505 function number_empty($value)
2507 return empty($value) && $value != '0';
2510 function get_bean_select_array($add_blank=true, $bean_name, $display_columns, $where='', $order_by='', $blank_is_none=false)
2513 require_once($beanFiles[$bean_name]);
2514 $focus = new $bean_name();
2515 $user_array = array();
2517 $key = ($bean_name == 'EmailTemplate') ? $bean_name : $bean_name . $display_columns. $where . $order_by;
2518 $user_array = get_register_value('select_array', $key );
2522 $db = DBManagerFactory::getInstance();
2524 $temp_result = Array();
2525 $query = "SELECT {$focus->table_name}.id, {$display_columns} as display from {$focus->table_name} ";
2529 $query .= $where." AND ";
2532 $query .= " {$focus->table_name}.deleted=0";
2534 if ( $order_by != '')
2536 $query .= " order by {$focus->table_name}.{$order_by}";
2539 $GLOBALS['log']->debug("get_user_array query: $query");
2540 $result = $db->query($query, true, "Error filling in user array: ");
2542 if ($add_blank==true){
2543 // Add in a blank row
2544 if($blank_is_none == true) { // set 'blank row' to "--None--"
2545 global $app_strings;
2546 $temp_result[''] = $app_strings['LBL_NONE'];
2548 $temp_result[''] = '';
2552 // Get the id and the name.
2553 while($row = $db->fetchByAssoc($result))
2555 $temp_result[$row['id']] = $row['display'];
2558 $user_array = $temp_result;
2559 set_register_value('select_array', $key ,$temp_result);
2568 * @param unknown_type $listArray
2570 // function parse_list_modules
2571 // searches a list for items in a user's allowed tabs and returns an array that removes unallowed tabs from list
2572 function parse_list_modules(&$listArray)
2574 global $modListHeader;
2575 $returnArray = array();
2577 foreach($listArray as $optionName => $optionVal)
2579 if(array_key_exists($optionName, $modListHeader))
2581 $returnArray[$optionName] = $optionVal;
2584 // special case for projects
2585 if(array_key_exists('Project', $modListHeader))
2587 $returnArray['ProjectTask'] = $listArray['ProjectTask'];
2590 $acldenied = ACLController::disabledModuleList($listArray,false);
2591 foreach($acldenied as $denied){
2592 unset($returnArray[$denied]);
2594 asort($returnArray);
2596 return $returnArray;
2599 function display_notice($msg = false){
2600 global $error_notice;
2601 //no error notice - lets just display the error to the user
2602 if(!isset($error_notice)){
2603 echo '<br>'.$msg . '<br>';
2605 $error_notice .= $msg . '<br>';
2609 /* checks if it is a number that at least has the plus at the beginning.
2611 function skype_formatted($number){
2612 //kbrill - BUG #15375
2613 if(isset($_REQUEST['action']) && $_REQUEST['action']=="Popup") {
2616 return substr($number, 0, 1) == '+' || substr($number, 0, 2) == '00' || substr($number, 0, 3) == '011';
2618 // return substr($number, 0, 1) == '+' || substr($number, 0, 2) == '00' || substr($number, 0, 2) == '011';
2621 function format_skype($number) {
2622 return preg_replace('/[^\+0-9]/','',$number);
2625 function insert_charset_header() {
2626 header('Content-Type: text/html; charset=UTF-8');
2629 function getCurrentURL()
2632 if(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on')
2637 $href.= "//".$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME'].'?'.$_SERVER['QUERY_STRING'];
2641 function javascript_escape($str) {
2644 for($i = 0; $i < strlen($str); $i++) {
2646 if(ord(substr($str, $i, 1))==10){
2648 }elseif(ord(substr($str, $i, 1))==13){
2652 $new_str .= $str{$i};
2656 $new_str = str_replace("'", "\\'", $new_str);
2661 function js_escape($str, $keep=true){
2662 $str = html_entity_decode(str_replace("\\", "", $str), ENT_QUOTES);
2665 $str = javascript_escape($str);
2668 $str = str_replace("'", " ", $str);
2669 $str = str_replace('"', " ", $str);
2674 //end function js_escape
2677 function br2nl($str) {
2678 $regex = "#<[^>]+br.+?>#i";
2679 preg_match_all($regex, $str, $matches);
2681 foreach($matches[0] as $match) {
2682 $str = str_replace($match, "<br>", $str);
2685 $brs = array('<br>','<br/>', '<br />');
2686 $str = str_replace("\r\n", "\n", $str); // make from windows-returns, *nix-returns
2687 $str = str_replace("\n\r", "\n", $str); // make from windows-returns, *nix-returns
2688 $str = str_replace("\r", "\n", $str); // make from windows-returns, *nix-returns
2689 $str = str_ireplace($brs, "\n", $str); // to retrieve it
2695 * Private helper function for displaying the contents of a given variable.
2696 * This function is only intended to be used for SugarCRM internal development.
2697 * The ppd stands for Pre Print Die.
2699 function _ppd($mixed)
2705 * Private helper function for displaying the contents of a given variable in
2706 * the Logger. This function is only intended to be used for SugarCRM internal
2707 * development. The pp stands for Pre Print.
2708 * @param $mixed var to print_r()
2709 * @param $die boolean end script flow
2710 * @param $displayStackTrace also show stack trace
2712 function _ppl($mixed, $die=false, $displayStackTrace=false, $loglevel="fatal") {
2713 if(!isset($GLOBALS['log']) || empty($GLOBALS['log'])) {
2715 $GLOBALS['log'] = LoggerManager :: getLogger('SugarCRM');
2719 $mix = print_r($mixed, true); // send print_r() output to $mix
2720 $stack = debug_backtrace();
2722 $GLOBALS['log']->$loglevel('------------------------------ _ppLogger() output start -----------------------------');
2723 $GLOBALS['log']->$loglevel($mix);
2724 if($displayStackTrace) {
2725 foreach($stack as $position) {
2726 $GLOBALS['log']->$loglevel($position['file']."({$position['line']})");
2730 $GLOBALS['log']->$loglevel('------------------------------ _ppLogger() output end -----------------------------');
2731 $GLOBALS['log']->$loglevel('------------------------------ _ppLogger() file: '.$stack[0]['file'].' line#: '.$stack[0]['line'].'-----------------------------');
2739 * private helper function to quickly show the major, direct, field attributes of a given bean.
2740 * The ppf stands for Pre[formatted] Print Focus [object]
2741 * @param object bean The focus bean
2743 function _ppf($bean, $die=false) {
2749 * Private helper function for displaying the contents of a given variable.
2750 * This function is only intended to be used for SugarCRM internal development.
2751 * The pp stands for Pre Print.
2753 function _pp($mixed)
2758 * Private helper function for displaying the contents of a given variable.
2759 * This function is only intended to be used for SugarCRM internal development.
2760 * The pp stands for Pre Print.
2762 function _pstack_trace($mixed=NULL)
2767 * Private helper function for displaying the contents of a given variable.
2768 * This function is only intended to be used for SugarCRM internal development.
2769 * The pp stands for Pre Print Trace.
2771 function _ppt($mixed, $textOnly=false)
2776 * Private helper function for displaying the contents of a given variable.
2777 * This function is only intended to be used for SugarCRM internal development.
2778 * The pp stands for Pre Print Trace Die.
2780 function _pptd($mixed)
2785 * Private helper function for decoding javascript UTF8
2786 * This function is only intended to be used for SugarCRM internal development.
2788 function decodeJavascriptUTF8($str) {
2792 * Will check if a given PHP version string is supported (tested on this ver),
2793 * unsupported (results unknown), or invalid (something will break on this
2794 * ver). Do not pass in any pararameter to default to a check against the
2795 * current environment's PHP version.
2797 * @return 1 implies supported, 0 implies unsupported, -1 implies invalid
2799 function check_php_version($sys_php_version = '') {
2800 $sys_php_version = empty($sys_php_version) ? constant('PHP_VERSION') : $sys_php_version;
2801 // versions below $min_considered_php_version considered invalid by default,
2802 // versions equal to or above this ver will be considered depending
2803 // on the rules that follow
2804 $min_considered_php_version = '5.2.2';
2806 // only the supported versions,
2807 // should be mutually exclusive with $invalid_php_versions
2808 $supported_php_versions = array (
2809 '5.2.2', '5.2.3', '5.2.4', '5.2.5', '5.2.6', '5.2.8', '5.3.0'
2812 // invalid versions above the $min_considered_php_version,
2813 // should be mutually exclusive with $supported_php_versions
2815 // SugarCRM prohibits install on PHP 5.2.7 on all platforms
2816 $invalid_php_versions = array('5.2.7');
2818 // default unsupported
2821 // versions below $min_considered_php_version are invalid
2822 if(1 == version_compare($sys_php_version, $min_considered_php_version, '<')) {
2826 // supported version check overrides default unsupported
2827 foreach($supported_php_versions as $ver) {
2828 if(1 == version_compare($sys_php_version, $ver, 'eq') || strpos($sys_php_version,$ver) !== false) {
2834 // invalid version check overrides default unsupported
2835 foreach($invalid_php_versions as $ver) {
2836 if(1 == version_compare($sys_php_version, $ver, 'eq') && strpos($sys_php_version,$ver) !== false) {
2842 //allow a redhat distro to install, regardless of version. We are assuming the redhat naming convention is followed
2843 //and the php version contains 'rh' characters
2844 if(strpos($sys_php_version, 'rh') !== false) {
2852 * Will check if a given IIS version string is supported (tested on this ver),
2853 * unsupported (results unknown), or invalid (something will break on this
2856 * @return 1 implies supported, 0 implies unsupported, -1 implies invalid
2858 function check_iis_version($sys_iis_version = '') {
2860 $server_software = $_SERVER["SERVER_SOFTWARE"];
2862 if(strpos($server_software,'Microsoft-IIS') !== false && preg_match_all("/^.*\/(\d+\.?\d*)$/", $server_software, $out))
2863 $iis_version = $out[1][0];
2865 $sys_iis_version = empty($sys_iis_version) ? $iis_version : $sys_iis_version;
2867 // versions below $min_considered_iis_version considered invalid by default,
2868 // versions equal to or above this ver will be considered depending
2869 // on the rules that follow
2870 $min_considered_iis_version = '6.0';
2872 // only the supported versions,
2873 // should be mutually exclusive with $invalid_iis_versions
2874 $supported_iis_versions = array ('6.0', '7.0',);
2875 $unsupported_iis_versions = array();
2876 $invalid_iis_versions = array('5.0',);
2878 // default unsupported
2881 // versions below $min_considered_iis_version are invalid
2882 if(1 == version_compare($sys_iis_version, $min_considered_iis_version, '<')) {
2886 // supported version check overrides default unsupported
2887 foreach($supported_iis_versions as $ver) {
2888 if(1 == version_compare($sys_iis_version, $ver, 'eq') || strpos($sys_iis_version,$ver) !== false) {
2894 // unsupported version check overrides default unsupported
2895 foreach($unsupported_iis_versions as $ver) {
2896 if(1 == version_compare($sys_iis_version, $ver, 'eq') && strpos($sys_iis_version,$ver) !== false) {
2902 // invalid version check overrides default unsupported
2903 foreach($invalid_iis_versions as $ver) {
2904 if(1 == version_compare($sys_iis_version, $ver, 'eq') && strpos($sys_iis_version,$ver) !== false) {
2913 function pre_login_check(){
2914 global $action, $login_error;
2915 if(!empty($action)&& $action == 'Login'){
2917 if(!empty($login_error)){
2918 $login_error = htmlentities($login_error);
2919 $login_error = str_replace(array("<pre>","</pre>","\r\n", "\n"), "<br>", $login_error);
2920 $_SESSION['login_error'] = $login_error;
2922 function set_focus() {}
2923 if(document.getElementById("post_error")) {
2924 document.getElementById("post_error").innerHTML="'. $login_error. '";
2925 document.getElementById("cant_login").value=1;
2926 document.getElementById("login_button").disabled = true;
2927 document.getElementById("user_name").disabled = true;
2928 //document.getElementById("user_password").disabled = true;
2937 function sugar_cleanup($exit = false) {
2938 static $called = false;
2941 set_include_path(realpath(dirname(__FILE__) . '/..') . PATH_SEPARATOR . get_include_path());
2942 chdir(realpath(dirname(__FILE__) . '/..'));
2943 global $sugar_config;
2944 require_once('include/utils/LogicHook.php');
2945 LogicHook::initialize();
2946 $GLOBALS['logic_hook']->call_custom_logic('', 'server_round_trip');
2948 //added this check to avoid errors during install.
2949 if (empty($sugar_config['dbconfig'])) {
2950 if ($exit) exit; else return;
2953 if (!class_exists('Tracker', true)) {
2954 require_once 'modules/Trackers/Tracker.php';
2957 // Now write the cached tracker_queries
2958 if(!empty($GLOBALS['savePreferencesToDB']) && $GLOBALS['savePreferencesToDB']) {
2959 if ( isset($GLOBALS['current_user']) && $GLOBALS['current_user'] instanceOf User )
2960 $GLOBALS['current_user']->savePreferencesToDB();
2963 //check to see if this is not an `ajax call AND the user preference error flag is set
2965 (isset($_SESSION['USER_PREFRENCE_ERRORS']) && $_SESSION['USER_PREFRENCE_ERRORS'])
2966 && ($_REQUEST['action']!='modulelistmenu' && $_REQUEST['action']!='DynamicAction')
2967 && ($_REQUEST['action']!='favorites' && $_REQUEST['action']!='DynamicAction')
2968 && (empty($_REQUEST['to_pdf']) || !$_REQUEST['to_pdf'] )
2969 && (empty($_REQUEST['sugar_body_only']) || !$_REQUEST['sugar_body_only'] )
2972 global $app_strings;
2973 //this is not an ajax call and the user preference error flag is set, so reset the flag and print js to flash message
2974 $err_mess = $app_strings['ERROR_USER_PREFS'];
2975 $_SESSION['USER_PREFRENCE_ERRORS'] = false;
2978 ajaxStatus.flashStatus('$err_mess',7000);
2984 if(class_exists('DBManagerFactory')) {
2985 $db = DBManagerFactory::getInstance();
2993 register_shutdown_function('sugar_cleanup');
2997 check_logic_hook - checks to see if your custom logic is in the logic file
2998 if not, it will add it. If the file isn't built yet, it will create the file
3001 function check_logic_hook_file($module_name, $event, $action_array){
3002 require_once('include/utils/logic_utils.php');
3005 if(file_exists("custom/modules/$module_name/logic_hooks.php")){
3007 $hook_array = get_hook_array($module_name);
3009 if(check_existing_element($hook_array, $event, $action_array)==true){
3010 //the hook at hand is present, so do nothing
3015 if(!empty($hook_array[$event]))
3017 $logic_count = count($hook_array[$event]);
3020 if($action_array[0]==""){
3021 $action_array[0] = $logic_count + 1;
3023 $hook_array[$event][] = $action_array;
3026 //end if the file exists already
3029 if($action_array[0]==""){
3030 $action_array[0] = 1;
3032 $hook_array = array();
3033 $hook_array[$event][] = $action_array;
3034 //end if else file exists already
3036 if($add_logic == true){
3038 //reorder array by element[0]
3039 //$hook_array = reorder_array($hook_array, $event);
3040 //!!!Finish this above TODO
3042 $new_contents = replace_or_add_logic_type($hook_array);
3043 write_logic_file($module_name, $new_contents);
3045 //end if add_element is true
3048 //end function check_logic_hook_file
3051 function remove_logic_hook($module_name, $event, $action_array) {
3052 require_once('include/utils/logic_utils.php');
3055 if(file_exists("custom/modules/".$module_name."/logic_hooks.php")){
3056 // The file exists, let's make sure the hook is there
3057 $hook_array = get_hook_array($module_name);
3059 if(check_existing_element($hook_array, $event, $action_array)==true){
3060 // The hook is there, time to take it out.
3062 foreach ( $hook_array[$event] as $i => $hook ) {
3063 // We don't do a full comparison below just in case the filename changes
3064 if ( $hook[0] == $action_array[0]
3065 && $hook[1] == $action_array[1]
3066 && $hook[3] == $action_array[3]
3067 && $hook[4] == $action_array[4] ) {
3068 unset($hook_array[$event][$i]);
3072 $new_contents = replace_or_add_logic_type($hook_array);
3073 write_logic_file($module_name, $new_contents);
3079 function display_stack_trace($textOnly=false){
3081 $stack = debug_backtrace();
3083 echo "\n\n display_stack_trace caller, file: " . $stack[0]['file']. ' line#: ' .$stack[0]['line'];
3091 foreach($stack as $item) {
3097 if(isset($item['file']))
3098 $file = $item['file'];
3099 if(isset($item['class']))
3100 $class = $item['class'];
3101 if(isset($item['line']))
3102 $line = $item['line'];
3103 if(isset($item['function']))
3104 $function = $item['function'];
3108 $out .= '<font color="black"><b>';
3114 $out .= '</b></font><font color="blue">';
3117 $out .= "[L:{$line}]";
3120 $out .= '</font><font color="red">';
3123 $out .= "({$class}:{$function})";
3126 $out .= '</font><br>';
3138 function StackTraceErrorHandler($errno, $errstr, $errfile,$errline, $errcontext) {
3139 $error_msg = " $errstr occurred in <b>$errfile</b> on line $errline [" . date("Y-m-d H:i:s") . ']';
3140 $halt_script = true;
3142 case 2048: return; //depricated we have lots of these ignore them
3145 if ( error_reporting() & E_NOTICE ) {
3146 $halt_script = false;
3152 case E_USER_WARNING:
3153 case E_COMPILE_WARNING:
3154 case E_CORE_WARNING:
3157 $halt_script = false;
3162 case E_COMPILE_ERROR:
3166 $type = "Fatal Error";
3171 $type = "Parse Error";
3175 //don't know what it is might not be so bad
3176 $halt_script = false;
3177 $type = "Unknown Error ($errno)";
3180 $error_msg = '<b>'.$type.'</b>:' . $error_msg;
3182 display_stack_trace();
3192 if(isset($sugar_config['stack_trace_errors']) && $sugar_config['stack_trace_errors']){
3194 set_error_handler('StackTraceErrorHandler');
3196 function get_sub_cookies($name){
3198 if(isset($_COOKIE[$name])){
3199 $subs = explode('#', $_COOKIE[$name]);
3200 foreach($subs as $cookie){
3201 if(!empty($cookie)){
3202 $cookie = explode('=', $cookie);
3204 $cookies[$cookie[0]] = $cookie[1];
3213 function mark_delete_components($sub_object_array, $run_second_level=false, $sub_sub_array=""){
3215 if(!empty($sub_object_array)){
3217 foreach($sub_object_array as $sub_object){
3219 //run_second level is set to true if you need to remove sub-sub components
3220 if($run_second_level==true){
3222 mark_delete_components($sub_object->get_linked_beans($sub_sub_array['rel_field'],$sub_sub_array['rel_module']));
3224 //end if run_second_level is true
3226 $sub_object->mark_deleted($sub_object->id);
3227 //end foreach sub component
3229 //end if this is not empty
3232 //end function mark_delete_components
3236 * For translating the php.ini memory values into bytes. e.g. input value of '8M' will return 8388608.
3238 function return_bytes($val)
3241 $last = strtolower($val{strlen($val)-1});
3245 // The 'G' modifier is available since PHP 5.1.0
3258 * Adds the href HTML tags around any URL in the $string
3260 function url2html($string) {
3262 $return_string = preg_replace('/(\w+:\/\/)(\S+)/', ' <a href="\\1\\2" target="_new" style="font-weight: normal;">\\1\\2</a>', $string);
3263 return $return_string;
3265 // End customization by Julian
3268 * tries to determine whether the Host machine is a Windows machine
3270 function is_windows() {
3271 static $is_windows = null;
3272 if (!isset($is_windows)) {
3273 $is_windows = strtoupper(substr(PHP_OS, 0, 3)) == 'WIN';
3279 * equivalent for windows filesystem for PHP's is_writable()
3280 * @param string file Full path to the file/dir
3281 * @return bool true if writable
3283 function is_writable_windows($file) {
3284 if($file{strlen($file)-1}=='/') {
3285 return is_writable_windows($file.uniqid(mt_rand()).'.tmp');
3288 // the assumption here is that Windows has an inherited permissions scheme
3289 // any file that is a descendant of an unwritable directory will inherit
3290 // that property and will trigger a failure below.
3295 $file = str_replace("/", '\\', $file);
3297 if(file_exists($file)) {
3298 if (!($f = @sugar_fopen($file, 'r+')))
3304 if(!($f = @sugar_fopen($file, 'w')))
3313 * best guesses Timezone based on webserver's TZ settings
3315 function lookupTimezone($userOffset = 0)
3317 return TimeDate::guessTimezone($userOffset);
3320 function convert_module_to_singular($module_array){
3323 foreach($module_array as $key => $value){
3324 if(!empty($beanList[$value])) $module_array[$key] = $beanList[$value];
3326 if($value=="Cases") {
3327 $module_array[$key] = "Case";
3329 if($key=="projecttask"){
3330 $module_array['ProjectTask'] = "Project Task";
3331 unset($module_array[$key]);
3335 return $module_array;
3337 //end function convert_module_to_singular
3341 * Given the bean_name which may be plural or singular return the singular
3342 * bean_name. This is important when you need to include files.
3344 function get_singular_bean_name($bean_name){
3345 global $beanFiles, $beanList;
3346 if(array_key_exists($bean_name, $beanList)){
3347 return $beanList[$bean_name];
3355 * Given the potential module name (singular name, renamed module name)
3356 * Return the real internal module name.
3358 function get_module_from_singular($singular) {
3360 // find the internal module name for a singular name
3361 if (isset($GLOBALS['app_list_strings']['moduleListSingular'])) {
3363 $singular_modules = $GLOBALS['app_list_strings']['moduleListSingular'];
3365 foreach ($singular_modules as $mod_name=>$sin_name) {
3366 if ($singular == $sin_name and $mod_name != $sin_name) {
3372 // find the internal module name for a renamed module
3373 if (isset($GLOBALS['app_list_strings']['moduleList'])) {
3375 $moduleList = $GLOBALS['app_list_strings']['moduleList'];
3377 foreach ($moduleList as $mod_name=>$name) {
3378 if ($singular == $name and $mod_name != $name) {
3384 // if it's not a singular name, nor a renamed name, return the original value
3388 function get_label($label_tag, $temp_module_strings){
3389 global $app_strings;
3390 if(!empty($temp_module_strings[$label_tag])){
3392 $label_name = $temp_module_strings[$label_tag];
3394 if(!empty($app_strings[$label_tag])){
3395 $label_name = $app_strings[$label_tag];
3397 $label_name = $label_tag;
3402 //end function get_label
3406 function search_filter_rel_info(& $focus, $tar_rel_module, $relationship_name){
3408 $rel_list = array();
3410 foreach($focus->relationship_fields as $rel_key => $rel_value){
3411 if($rel_value == $relationship_name){
3412 $temp_bean = get_module_info($tar_rel_module);
3413 // echo $focus->$rel_key;
3414 $temp_bean->retrieve($focus->$rel_key);
3415 if($temp_bean->id!=""){
3417 $rel_list[] = $temp_bean;
3423 foreach($focus->field_defs as $field_name => $field_def){
3424 //Check if the relationship_name matches a "relate" field
3425 if(!empty($field_def['type']) && $field_def['type'] == 'relate'
3426 && !empty($field_def['id_name']) && !empty($focus->field_defs[$field_def['id_name']])
3427 && !empty($focus->field_defs[$field_def['id_name']]['relationship'])
3428 && $focus->field_defs[$field_def['id_name']]['relationship'] == $relationship_name)
3430 $temp_bean = get_module_info($tar_rel_module);
3431 // echo $focus->$field_def['id_name'];
3432 $temp_bean->retrieve($focus->$field_def['id_name']);
3433 if($temp_bean->id!=""){
3435 $rel_list[] = $temp_bean;
3438 //Check if the relationship_name matches a "link" in a relate field
3439 } else if(!empty($rel_value['link']) && !empty($rel_value['id_name']) && $rel_value['link'] == $relationship_name){
3440 $temp_bean = get_module_info($tar_rel_module);
3441 // echo $focus->$rel_value['id_name'];
3442 $temp_bean->retrieve($focus->$rel_value['id_name']);
3443 if($temp_bean->id!=""){
3445 $rel_list[] = $temp_bean;
3451 // special case for unlisted parent-type relationships
3452 if( !empty($focus->parent_type) && $focus->parent_type == $tar_rel_module && !empty($focus->parent_id)) {
3453 $temp_bean = get_module_info($tar_rel_module);
3454 $temp_bean->retrieve($focus->parent_id);
3455 if($temp_bean->id!=""){
3456 $rel_list[] = $temp_bean;
3463 //end function search_filter_rel_info
3466 function get_module_info($module_name){
3470 //Get dictionary and focus data for module
3471 $vardef_name = $beanList[$module_name];
3473 if($vardef_name=="aCase"){
3474 $class_name = "Case";
3476 $class_name = $vardef_name;
3479 if(!file_exists('modules/'. $module_name . '/'.$class_name.'.php')){
3483 include_once('modules/'. $module_name . '/'.$class_name.'.php');
3485 $module_bean = new $vardef_name();
3486 return $module_bean;
3487 //end function get_module_table
3491 * In order to have one place to obtain the proper object name. aCase for example causes issues throughout the application.
3493 * @param string $moduleName
3495 function get_valid_bean_name($module_name){
3498 $vardef_name = $beanList[$module_name];
3499 if($vardef_name=="aCase"){
3500 $bean_name = "Case";
3502 $bean_name = $vardef_name;
3509 function checkAuthUserStatus(){
3516 * This function returns an array of phpinfo() results that can be parsed and
3517 * used to figure out what version we run, what modules are compiled in, etc.
3518 * @param $level int info level constant (1,2,4,8...64);
3519 * @return $returnInfo array array of info about the PHP environment
3520 * @author original by "code at adspeed dot com" Fron php.net
3521 * @author customized for Sugar by Chris N.
3523 function getPhpInfo($level=-1) {
3524 /** Name (constant) Value Description
3525 INFO_GENERAL 1 The configuration line, php.ini location, build date, Web Server, System and more.
3526 INFO_CREDITS 2 PHP Credits. See also phpcredits().
3527 INFO_CONFIGURATION 4 Current Local and Master values for PHP directives. See also ini_get().
3528 INFO_MODULES 8 Loaded modules and their respective settings. See also get_loaded_extensions().
3529 INFO_ENVIRONMENT 16 Environment Variable information that's also available in $_ENV.
3530 INFO_VARIABLES 32 Shows all predefined variables from EGPCS (Environment, GET, POST, Cookie, Server).
3531 INFO_LICENSE 64 PHP License information. See also the license FAQ.
3532 INFO_ALL -1 Shows all of the above. This is the default value.
3536 $phpinfo = ob_get_contents();
3539 $phpinfo = strip_tags($phpinfo,'<h1><h2><th><td>');
3540 $phpinfo = preg_replace('/<th[^>]*>([^<]+)<\/th>/',"<info>\\1</info>",$phpinfo);
3541 $phpinfo = preg_replace('/<td[^>]*>([^<]+)<\/td>/',"<info>\\1</info>",$phpinfo);
3542 $parsedInfo = preg_split('/(<h.?>[^<]+<\/h.>)/', $phpinfo, -1, PREG_SPLIT_DELIM_CAPTURE);
3545 $returnInfo = array();
3547 if(preg_match('/<h1 class\=\"p\">PHP Version ([^<]+)<\/h1>/', $phpinfo, $version)) {
3548 $returnInfo['PHP Version'] = $version[1];
3552 for ($i=1; $i<count($parsedInfo); $i++) {
3553 if (preg_match('/<h.>([^<]+)<\/h.>/', $parsedInfo[$i], $match)) {
3554 $vName = trim($match[1]);
3555 $parsedInfo2 = explode("\n",$parsedInfo[$i+1]);
3557 foreach ($parsedInfo2 AS $vOne) {
3558 $vPat = '<info>([^<]+)<\/info>';
3559 $vPat3 = "/$vPat\s*$vPat\s*$vPat/";
3560 $vPat2 = "/$vPat\s*$vPat/";
3562 if (preg_match($vPat3,$vOne,$match)) { // 3cols
3563 $returnInfo[$vName][trim($match[1])] = array(trim($match[2]),trim($match[3]));
3564 } elseif (preg_match($vPat2,$vOne,$match)) { // 2cols
3565 $returnInfo[$vName][trim($match[1])] = trim($match[2]);
3577 * This function will take a string that has tokens like {0}, {1} and will replace
3578 * those tokens with the args provided
3579 * @param $format string to format
3580 * @param $args args to replace
3581 * @return $result a formatted string
3583 function string_format($format, $args){
3587 * If args array has only one argument, and it's empty, so empty single quotes are used '' . That's because
3588 * IN () fails and IN ('') works.
3590 if (count($args) == 1)
3593 $singleArgument = current($args);
3594 if (empty($singleArgument))
3596 return str_replace("{0}", "''", $result);
3601 for($i = 0; $i < count($args); $i++){
3602 $result = str_replace('{'.$i.'}', $args[$i], $result);
3608 * Generate a string for displaying a unique identifier that is composed
3609 * of a system_id and number. This is use to allow us to generate quote
3610 * numbers using a DB auto-increment key from offline clients and still
3611 * have the number be unique (since it is modified by the system_id.
3613 * @param $num of bean
3614 * @param $system_id from system
3615 * @return $result a formatted string
3617 function format_number_display($num, $system_id){
3618 global $sugar_config;
3619 if(isset($num) && !empty($num)){
3620 $num=unformat_number($num);
3621 if(isset($system_id) && $system_id == 1){
3622 return sprintf("%d", $num);
3625 return sprintf("%d-%d", $num, $system_id);
3629 function checkLoginUserStatus(){
3633 * This function will take a number and system_id and format
3634 * @param $url URL containing host to append port
3635 * @param $port the port number - if '' is passed, no change to url
3636 * @return $resulturl the new URL with the port appended to the host
3638 function appendPortToHost($url, $port)
3642 // if no port, don't change the url
3645 $split = explode("/", $url);
3646 //check if it starts with http, in case they didn't include that in url
3647 if(str_begin($url, 'http'))
3649 //third index ($split[2]) will be the host
3650 $split[2] .= ":".$port;
3652 else // otherwise assumed to start with host name
3654 //first index ($split[0]) will be the host
3655 $split[0] .= ":".$port;
3658 $resulturl = implode("/", $split);
3665 * Singleton to return JSON object
3666 * @return JSON object
3668 function getJSONobj() {
3669 static $json = null;
3671 require_once('include/JSON.php');
3672 $json = new JSON(JSON_LOOSE_TYPE);
3677 require_once('include/utils/db_utils.php');
3680 * Set default php.ini settings for entry points
3682 function setPhpIniSettings() {
3684 // Bug 37579 - Comment out force enabling zlib.output_compression, since it can cause problems on certain hosts
3686 if(function_exists('gzclose') && headers_sent() == false) {
3687 ini_set('zlib.output_compression', 1);
3691 //nsingh: breaks zip/unzip functionality. Commenting out 4/23/08
3693 /*if(function_exists('mb_strlen')) {
3694 ini_set('mbstring.func_overload', 7);
3695 ini_set('mbstring.internal_encoding', 'UTF-8');
3699 // http://us3.php.net/manual/en/ref.pcre.php#ini.pcre.backtrack-limit
3700 // starting with 5.2.0, backtrack_limit breaks JSON decoding
3701 $backtrack_limit = ini_get('pcre.backtrack_limit');
3702 if(!empty($backtrack_limit)) {
3703 ini_set('pcre.backtrack_limit', '-1');
3708 * Identical to sugarArrayMerge but with some speed improvements and used specifically to merge
3709 * language files. Language file merges do not need to account for null values so we can get some
3710 * performance increases by using this specialized function. Note this merge function does not properly
3711 * handle null values.
3717 function sugarLangArrayMerge($gimp, $dom)
3719 if(is_array($gimp) && is_array($dom))
3721 foreach($dom as $domKey => $domVal)
3723 if(isset($gimp[$domKey]))
3725 if(is_array($domVal))
3728 foreach ( $domVal as $domArrKey => $domArrVal )
3729 $tempArr[$domArrKey] = $domArrVal;
3730 foreach ( $gimp[$domKey] as $gimpArrKey => $gimpArrVal )
3731 if ( !isset($tempArr[$gimpArrKey]) )
3732 $tempArr[$gimpArrKey] = $gimpArrVal;
3733 $gimp[$domKey] = $tempArr;
3737 $gimp[$domKey] = $domVal;
3742 $gimp[$domKey] = $domVal;
3746 // if the passed value for gimp isn't an array, then return the $dom
3747 elseif(is_array($dom))
3755 * like array_merge() but will handle array elements that are themselves arrays;
3756 * PHP's version just overwrites the element with the new one.
3758 * @internal Note that this function deviates from the internal array_merge()
3759 * functions in that it does does not treat numeric keys differently
3760 * than string keys. Additionally, it deviates from
3761 * array_merge_recursive() by not creating an array when like values
3764 * @param array gimp the array whose values will be overloaded
3765 * @param array dom the array whose values will pwn the gimp's
3766 * @return array beaten gimp
3768 function sugarArrayMerge($gimp, $dom) {
3769 if(is_array($gimp) && is_array($dom)) {
3770 foreach($dom as $domKey => $domVal) {
3771 if(array_key_exists($domKey, $gimp)) {
3772 if(is_array($domVal)) {
3774 foreach ( $domVal as $domArrKey => $domArrVal )
3775 $tempArr[$domArrKey] = $domArrVal;
3776 foreach ( $gimp[$domKey] as $gimpArrKey => $gimpArrVal )
3777 if ( !array_key_exists($gimpArrKey, $tempArr) )
3778 $tempArr[$gimpArrKey] = $gimpArrVal;
3779 $gimp[$domKey] = $tempArr;
3781 $gimp[$domKey] = $domVal;
3784 $gimp[$domKey] = $domVal;
3788 // if the passed value for gimp isn't an array, then return the $dom
3789 elseif(is_array($dom))
3796 * Similiar to sugarArrayMerge except arrays of N depth are merged.
3798 * @param array gimp the array whose values will be overloaded
3799 * @param array dom the array whose values will pwn the gimp's
3800 * @return array beaten gimp
3802 function sugarArrayMergeRecursive($gimp, $dom) {
3803 if(is_array($gimp) && is_array($dom)) {
3804 foreach($dom as $domKey => $domVal) {
3805 if(array_key_exists($domKey, $gimp)) {
3806 if(is_array($domVal) && is_array($gimp[$domKey])) {
3807 $gimp[$domKey] = sugarArrayMergeRecursive($gimp[$domKey], $domVal);
3809 $gimp[$domKey] = $domVal;
3812 $gimp[$domKey] = $domVal;
3816 // if the passed value for gimp isn't an array, then return the $dom
3817 elseif(is_array($dom))
3824 * finds the correctly working versions of PHP-JSON
3825 * @return bool True if NOT found or WRONG version
3827 function returnPhpJsonStatus() {
3828 if(function_exists('json_encode')) {
3829 $phpInfo = getPhpInfo(8);
3830 return version_compare($phpInfo['json']['json version'], '1.1.1', '<');
3832 return true; // not found
3837 * getTrackerSubstring
3839 * Returns a [number]-char or less string for the Tracker to display in the header
3840 * based on the tracker_max_display_length setting in config.php. If not set,
3841 * or invalid length, then defaults to 15 for COM editions, 30 for others.
3843 * @param string name field for a given Object
3844 * @return string [number]-char formatted string if length of string exceeds the max allowed
3846 function getTrackerSubstring($name) {
3847 static $max_tracker_item_length;
3850 $name = html_entity_decode($name, ENT_QUOTES, 'UTF-8');
3851 $strlen = function_exists('mb_strlen') ? mb_strlen($name) : strlen($name);
3853 global $sugar_config;
3855 if(!isset($max_tracker_item_length)) {
3856 if(isset($sugar_config['tracker_max_display_length'])) {
3857 $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;
3859 $max_tracker_item_length = 15;
3863 if($strlen > $max_tracker_item_length) {
3864 $chopped = function_exists('mb_substr') ? mb_substr($name, 0, $max_tracker_item_length-3, "UTF-8") : substr($name, 0, $max_tracker_item_length-3);
3872 function generate_search_where ($field_list=array(),$values=array(),&$bean,$add_custom_fields=false,$module='') {
3873 $where_clauses= array();
3875 $table_name=$bean->object_name;
3876 foreach ($field_list[$module] as $field=>$parms) {
3877 if(isset($values[$field]) && $values[$field] != "") {
3879 if (!empty($parms['operator'])) {
3880 $operator=$parms['operator'];
3882 if (is_array($values[$field])) {
3885 foreach ($values[$field] as $key => $val) {
3886 if ($val != ' ' and $val != '') {
3887 if (!empty($field_value)) {
3890 $field_value .= "'".$GLOBALS['db']->quote($val)."'";
3894 $field_value=$GLOBALS['db']->quote($values[$field]);
3896 //set db_fields array.
3897 if (!isset($parms['db_field']) ) {
3898 $parms['db_field'] = array($field);
3900 if (isset($parms['my_items']) and $parms['my_items'] == true) {
3901 global $current_user;
3902 $field_value = $GLOBALS['db']->quote($current_user->id);
3908 if ($field_value != '') {
3910 foreach ($parms['db_field'] as $db_field) {
3911 if (strstr($db_field,'.')===false) {
3912 $db_field=$bean->table_name.".".$db_field;
3914 if ($GLOBALS['db']->supports('case_sensitive') && isset($parms['query_type']) && $parms['query_type']=='case_insensitive') {
3915 $db_field='upper('.$db_field.")";
3916 $field_value=strtoupper($field_value);
3920 if (!empty($where)) {
3923 switch (strtolower($operator)) {
3925 $where .= $db_field . " like '".$field_value.$like_char."'";
3928 $where .= $db_field . " in (".$field_value.')';
3931 $where .= $db_field . " = '".$field_value ."'";
3936 if (!empty($where)) {
3938 array_push($where_clauses, '( '.$where.' )');
3940 array_push($where_clauses, $where);
3945 if ($add_custom_fields) {
3946 require_once('modules/DynamicFields/DynamicField.php');
3947 $bean->setupCustomFields($module);
3948 $bean->custom_fields->setWhereClauses($where_clauses);
3950 return $where_clauses;
3953 function add_quotes($str) {
3958 * This function will rebuild the config file
3959 * @param $sugar_config
3960 * @param $sugar_version
3961 * @return bool true if successful
3963 function rebuildConfigFile($sugar_config, $sugar_version) {
3964 // add defaults to missing values of in-memory sugar_config
3965 $sugar_config = sugarArrayMerge(get_sugar_config_defaults(), $sugar_config );
3966 // need to override version with default no matter what
3967 $sugar_config['sugar_version'] = $sugar_version;
3969 ksort( $sugar_config );
3971 if( write_array_to_file( "sugar_config", $sugar_config, "config.php" ) ){
3980 * Loads clean configuration, not overridden by config_override.php
3984 function loadCleanConfig()
3986 $sugar_config = array();
3987 require 'config.php';
3988 return $sugar_config;
3992 * getJavascriptSiteURL
3993 * This function returns a URL for the client javascript calls to access
3994 * the site. It uses $_SERVER['HTTP_REFERER'] in the event that Proxy servers
3995 * are used to access the site. Thus, the hostname in the URL returned may
3996 * not always match that of $sugar_config['site_url']. Basically, the
3997 * assumption is that however the user accessed the website is how they
3998 * will continue to with subsequent javascript requests. If the variable
3999 * $_SERVER['HTTP_REFERER'] is not found then we default to old algorithm.
4000 * @return $site_url The url used to refer to the website
4002 function getJavascriptSiteURL() {
4003 global $sugar_config;
4004 if(!empty($_SERVER['HTTP_REFERER'])) {
4005 $url = parse_url($_SERVER['HTTP_REFERER']);
4006 $replacement_url = $url['scheme']."://".$url['host'];
4007 if(!empty($url['port']))
4008 $replacement_url .= ':'.$url['port'];
4009 $site_url = preg_replace('/^http[s]?\:\/\/[^\/]+/',$replacement_url,$sugar_config['site_url']);
4011 $site_url = preg_replace('/^http(s)?\:\/\/[^\/]+/',"http$1://".$_SERVER['HTTP_HOST'],$sugar_config['site_url']);
4012 if(!empty($_SERVER['SERVER_PORT']) &&$_SERVER['SERVER_PORT'] == '443') {
4013 $site_url = preg_replace('/^http\:/','https:',$site_url);
4016 $GLOBALS['log']->debug("getJavascriptSiteURL(), site_url=". $site_url);
4020 // works nicely with array_map() -- can be used to wrap single quotes around each element in an array
4021 function add_squotes($str) {
4022 return "'" . $str . "'";
4026 // recursive function to count the number of levels within an array
4027 function array_depth($array, $depth_count=-1, $depth_array=array()){
4029 if (is_array($array)){
4030 foreach ($array as $key => $value){
4031 $depth_array[] = array_depth($value, $depth_count);
4035 return $depth_count;
4037 foreach ($depth_array as $value){
4038 $depth_count = $value > $depth_count ? $value : $depth_count;
4040 return $depth_count;
4044 * Creates a new Group User
4045 * @param string $name Name of Group User
4046 * @return string GUID of new Group User
4048 function createGroupUser($name) {
4051 $group = new User();
4052 $group->user_name = $name;
4053 $group->last_name = $name;
4054 $group->is_group = 1;
4055 $group->deleted = 0;
4056 $group->status = 'Active'; // cn: bug 6711
4057 $group->setPreference('timezone', TimeDate::userTimezone());
4064 * Helper function to locate an icon file given only a name
4065 * Searches through the various paths for the file
4066 * @param string iconFileName The filename of the icon
4067 * @return string Relative pathname of the located icon, or '' if not found
4070 function _getIcon($iconFileName)
4073 $iconName = "icon_{$iconFileName}.gif";
4074 $iconFound = SugarThemeRegistry::current()->getImageURL($iconName,false);
4076 //First try un-ucfirst-ing the icon name
4077 if ( empty($iconFound) )
4078 $iconName = "icon_" . strtolower(substr($iconFileName,0,1)).substr($iconFileName,1) . ".gif";
4079 $iconFound = SugarThemeRegistry::current()->getImageURL($iconName,false);
4081 //Next try removing the icon prefix
4082 if ( empty($iconFound) )
4083 $iconName = "{$iconFileName}.gif";
4084 $iconFound = SugarThemeRegistry::current()->getImageURL($iconName,false);
4086 if ( empty($iconFound) )
4092 * Function to grab the correct icon image for Studio
4093 * @param string $iconFileName Name of the icon file
4094 * @param string $altfilename Name of a fallback icon file (displayed if the imagefilename doesn't exist)
4095 * @param string $width Width of image
4096 * @param string $height Height of image
4097 * @param string $align Alignment of image
4098 * @param string $alt Alt tag of image
4099 * @return string $string <img> tag with corresponding image
4102 function getStudioIcon($iconFileName='', $altFileName='', $width='48', $height='48', $align='baseline', $alt='' )
4104 global $app_strings, $theme;
4106 $iconName = _getIcon($iconFileName);
4107 if(empty($iconName)){
4108 $iconName = _getIcon($altFileName);
4109 if (empty($iconName))
4111 return $app_strings['LBL_NO_IMAGE'];
4114 return SugarThemeRegistry::current()->getImage($iconName, "align=\"$align\" border=\"0\"", $width, $height);
4118 * Function to grab the correct icon image for Dashlets Dialog
4119 * @param string $filename Location of the icon file
4120 * @param string $module Name of the module to fall back onto if file does not exist
4121 * @param string $width Width of image
4122 * @param string $height Height of image
4123 * @param string $align Alignment of image
4124 * @param string $alt Alt tag of image
4125 * @return string $string <img> tag with corresponding image
4128 function get_dashlets_dialog_icon($module='', $width='32', $height='32', $align='absmiddle',$alt=''){
4129 global $app_strings, $theme;
4130 $iconName = _getIcon($module . "_32");
4131 if (empty($iconName))
4133 $iconName = _getIcon($module);
4135 if(empty($iconName)){
4136 return $app_strings['LBL_NO_IMAGE'];
4138 return SugarThemeRegistry::current()->getImage($iconName, "align=\"$align\" border=\"0\"", $width, $height);
4141 // works nicely to change UTF8 strings that are html entities - good for PDF conversions
4142 function html_entity_decode_utf8($string)
4145 // replace numeric entities
4146 //php will have issues with numbers with leading zeros, so do not include them in what we send to code2utf.
4147 $string = preg_replace('~�*([0-9a-f]+);~ei', 'code2utf(hexdec("\\1"))', $string);
4148 $string = preg_replace('~�*([0-9]+);~e', 'code2utf(\\1)', $string);
4149 // replace literal entities
4150 if (!isset($trans_tbl))
4152 $trans_tbl = array();
4153 foreach (get_html_translation_table(HTML_ENTITIES) as $val=>$key)
4154 $trans_tbl[$key] = utf8_encode($val);
4156 return strtr($string, $trans_tbl);
4159 // Returns the utf string corresponding to the unicode value
4160 function code2utf($num)
4162 if ($num < 128) return chr($num);
4163 if ($num < 2048) return chr(($num >> 6) + 192) . chr(($num & 63) + 128);
4164 if ($num < 65536) return chr(($num >> 12) + 224) . chr((($num >> 6) & 63) + 128) . chr(($num & 63) + 128);
4165 if ($num < 2097152) return chr(($num >> 18) + 240) . chr((($num >> 12) & 63) + 128) . chr((($num >> 6) & 63) + 128) . chr(($num & 63) + 128);
4169 function str_split_php4($string, $length = 1) {
4170 $string_length = strlen($string);
4173 if ($length > $string_length) {
4174 // use the string_length as the string is shorter than the length
4175 $length = $string_length;
4177 for ($cursor = 0; $cursor < $string_length; $cursor = $cursor + $length) {
4178 $return[] = substr($string, $cursor, $length);
4183 if (version_compare(phpversion(), '5.0.0', '<')) {
4184 function str_split($string, $length = 1) {
4185 return str_split_php4($string, $length);
4190 * @deprecated use DBManagerFactory::isFreeTDS
4192 function is_freetds()
4194 return DBManagerFactory::isFreeTDS();
4198 * Chart dashlet helper function that returns the correct CSS file, dependent on the current theme.
4200 * @todo this won't work completely right until we impliment css compression and combination
4201 * for now, we'll just include the last css file found.
4203 * @return chart.css file to use
4205 function chartStyle()
4207 return SugarThemeRegistry::current()->getCSSURL('chart.css');
4211 * Chart dashlet helper functions that returns the correct XML color file for charts,
4212 * dependent on the current theme.
4214 * @return sugarColors.xml to use
4216 function chartColors()
4218 if (SugarThemeRegistry::current()->getCSSURL('sugarColors.xml')=='')
4219 return SugarThemeRegistry::current()->getImageURL('sugarColors.xml');
4220 return SugarThemeRegistry::current()->getCSSURL('sugarColors.xml');
4222 /* End Chart Dashlet helper functions */
4225 * This function is designed to set up the php enviroment
4226 * for AJAX requests.
4229 function ajaxInit() {
4230 ini_set('display_errors', 'false');
4234 * Returns an absolute path from the given path, determining if it is relative or absolute
4236 * @param string $path
4239 function getAbsolutePath(
4241 $currentServer = false
4244 $path = trim($path);
4246 // try to match absolute paths like \\server\share, /directory or c:\
4247 if ( ( substr($path,0,2) == '\\\\' )
4248 || ( $path[0] == '/' )
4249 || preg_match('/^[A-z]:/i',$path)
4253 return getcwd().'/'.$path;
4257 * Returns the bean object of the given module
4259 * @deprecated use SugarModule::loadBean() instead
4260 * @param string $module
4267 return SugarModule::get($module)->loadBean();
4272 * Returns true if the application is being accessed on a touch screen interface ( like an iPad )
4274 function isTouchScreen()
4276 $ua = empty($_SERVER['HTTP_USER_AGENT']) ? "undefined" : strtolower($_SERVER['HTTP_USER_AGENT']);
4278 // first check if we have forced use of the touch enhanced interface
4279 if ( isset($_COOKIE['touchscreen']) && $_COOKIE['touchscreen'] == '1' ) {
4283 // next check if we should use the touch interface with our device
4284 if ( strpos($ua, 'ipad') !== false ) {
4292 * Returns the shortcut keys to access the shortcut links. Shortcut
4293 * keys vary depending on browser versions and operating systems.
4294 * @return String value of the shortcut keys
4296 function get_alt_hot_key() {
4298 if ( isset($_SERVER['HTTP_USER_AGENT']) )
4299 $ua = strtolower($_SERVER['HTTP_USER_AGENT']);
4300 $isMac = strpos($ua, 'mac') !== false;
4301 $isLinux = strpos($ua, 'linux') !== false;
4303 if(!$isMac && !$isLinux && strpos($ua, 'mozilla') !== false) {
4304 if(preg_match('/firefox\/(\d)?\./', $ua, $matches)) {
4305 return $matches[1] < 2 ? 'Alt+' : 'Alt+Shift+';
4308 return $isMac ? 'Ctrl+' : 'Alt+';
4311 function can_start_session(){
4312 if(!empty($_GET['PHPSESSID'])) {
4315 $session_id = session_id();
4316 return empty($session_id) ? true : false;
4319 function load_link_class($properties){
4321 if(!empty($properties['link_class']) && !empty($properties['link_file'])){
4322 require_once($properties['link_file']);
4323 $class = $properties['link_class'];
4329 function inDeveloperMode()
4331 return isset($GLOBALS['sugar_config']['developerMode']) && $GLOBALS['sugar_config']['developerMode'];
4335 * Filter the protocol list for inbound email accounts.
4337 * @param array $protocol
4339 function filterInboundEmailPopSelection($protocol)
4341 if ( !isset($GLOBALS['sugar_config']['allow_pop_inbound']) || ! $GLOBALS['sugar_config']['allow_pop_inbound'] )
4343 if( isset($protocol['pop3']) )
4344 unset($protocol['pop3']);
4347 $protocol['pop3'] = 'POP3';
4353 * The function is used because currently we are not supporting mbstring.func_overload
4354 * 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.
4355 * 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.
4356 * @returns the substred strings.
4358 function sugar_substr($string, $length, $charset='UTF-8')
4360 if(mb_strlen($string,$charset) > $length) {
4361 $string = trim(mb_substr(trim($string),0,$length,$charset));
4367 * The function is used because on FastCGI enviroment, the ucfirst(Chinese Characters) will produce bad charcters.
4368 * This will work even without setting the mbstring.*encoding
4370 function sugar_ucfirst($string, $charset='UTF-8') {
4371 return mb_strtoupper(mb_substr($string, 0, 1, $charset), $charset) . mb_substr($string, 1, mb_strlen($string), $charset);
4378 function unencodeMultienum($string) {
4379 if (is_array($string))
4383 if (substr($string, 0 ,1) == "^" && substr($string, -1) == "^") {
4384 $string = substr(substr($string, 1), 0, strlen($string) -2);
4387 return explode('^,^', $string);
4390 function encodeMultienumValue($arr) {
4391 if (!is_array($arr))
4397 $string = "^" . implode('^,^', $arr) . "^";
4403 * create_export_query is used for export and massupdate
4404 * We haven't handle the these fields: $field['type'] == 'relate' && isset($field['link']
4405 * This function will correct the where clause and output necessary join condition for them
4406 * @param $module: the module name
4407 * @param $searchFields: searchFields which is got after $searchForm->populateFromArray()
4408 * @param $where: where clauses
4409 * @return $ret_array['where']: corrected where clause
4410 * @return $ret_array['join']: extra join condition
4412 function create_export_query_relate_link_patch($module, $searchFields, $where){
4413 if(file_exists('modules/'.$module.'/SearchForm.html')){
4414 $ret_array['where'] = $where;
4417 $seed = loadBean($module);
4418 foreach($seed->field_defs as $name=>$field)
4421 if( $field['type'] == 'relate' && isset($field['link']) && !empty($searchFields[$name]['value']) ){
4422 $seed->load_relationship($field['link']);
4424 if(empty($join_type))
4426 $params['join_type'] = ' LEFT JOIN ';
4430 $params['join_type'] = $join_type;
4432 if(isset($data['join_name']))
4434 $params['join_table_alias'] = $field['join_name'];
4438 $params['join_table_alias'] = 'join_'.$field['name'];
4441 if(isset($data['join_link_name']))
4443 $params['join_table_link_alias'] = $field['join_link_name'];
4447 $params['join_table_link_alias'] = 'join_link_'.$field['name'];
4449 $join = $seed->$field['link']->getJoin($params, true);
4450 $join_table_alias = 'join_'.$field['name'];
4451 if(isset($field['db_concat_fields'])){
4452 $db_field = db_concat($join_table_alias, $field['db_concat_fields']);
4453 $where = preg_replace('/'.$field['name'].'/', $db_field, $where);
4455 $where = preg_replace('/(^|[\s(])' . $field['name'] . '/', '${1}' . $join_table_alias . '.'.$field['rname'], $where);
4459 $ret_array = array('where'=>$where, 'join'=> isset($join['join']) ? $join['join'] : '');
4464 * 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.
4465 * @Depends on QuickRepairAndRebuild.php
4466 * @Relate bug 30642 ,23177
4468 function clearAllJsAndJsLangFilesWithoutOutput(){
4469 global $current_language , $mod_strings;
4470 $MBmodStrings = $mod_strings;
4471 $mod_strings = return_module_language ( $current_language, 'Administration' ) ;
4472 include_once ('modules/Administration/QuickRepairAndRebuild.php') ;
4473 $repair = new RepairAndClear();
4474 $repair->module_list = array();
4475 $repair->show_output = false;
4476 $repair->clearJsLangFiles();
4477 $repair->clearJsFiles();
4478 $mod_strings = $MBmodStrings;
4482 * This function will allow you to get a variable value from query string
4484 function getVariableFromQueryString($variable, $string){
4486 $number = preg_match("/{$variable}=([a-zA-Z0-9_-]+)[&]?/", $string, $matches);
4496 * should_hide_iframes
4497 * This is a helper method to determine whether or not to show iframes (My Sites) related
4498 * information in the application.
4500 * @return boolean flag indicating whether or not iframes module should be hidden
4502 function should_hide_iframes() {
4503 //Remove the MySites module
4504 if(file_exists('modules/iFrames/iFrame.php')) {
4505 if(!class_exists("iFrame")) {
4506 require_once('modules/iFrames/iFrame.php');
4514 * Given a version such as 5.5.0RC1 return RC. If we have a version such as: 5.5 then return GA
4516 * @param string $version
4517 * @return string RC, BETA, GA
4519 function getVersionStatus($version){
4520 if(preg_match('/^[\d\.]+?([a-zA-Z]+?)[\d]*?$/si', $version, $matches)) {
4521 return strtoupper($matches[1]);
4528 * Return the numeric portion of a version. For example if passed 5.5.0RC1 then return 5.5. If given
4529 * 5.5.1RC1 then return 5.5.1
4531 * @param string $version
4534 function getMajorMinorVersion($version){
4535 if(preg_match('/^([\d\.]+).*$/si', $version, $matches2)){
4536 $version = $matches2[1];
4537 $arr = explode('.', $version);
4538 if(count($arr) > 2){
4540 $version = substr($version, 0, 3);
4548 * Return string composed of seconds & microseconds of current time, without dots
4551 function sugar_microtime()
4553 $now = explode(' ', microtime());
4554 $unique_id = $now[1].str_replace('.', '', $now[0]);
4559 * Extract urls from a piece of text
4561 * @return array of urls found in $string
4563 function getUrls($string)
4565 $lines = explode("<br>", trim($string));
4567 foreach($lines as $line){
4568 $regex = '/http?\:\/\/[^\" ]+/i';
4569 preg_match_all($regex, $line, $matches);
4570 foreach($matches[0] as $match){
4579 * Sanitize image file from hostile content
4580 * @param string $path Image file
4581 * @param bool $jpeg Accept only JPEGs?
4583 function verify_image_file($path, $jpeg = false)
4585 if(function_exists('imagepng') && function_exists('imagejpeg') && function_exists('imagecreatefromstring')) {
4586 $img = imagecreatefromstring(file_get_contents($path));
4590 $img_size = getimagesize($path);
4591 $filetype = $img_size['mime'];
4592 //if filetype is jpeg or if we are only allowing jpegs, create jpg image
4593 if($filetype == "image/jpeg" || $jpeg) {
4596 $image = ob_get_clean();
4597 // not writing directly because imagejpeg does not work with streams
4598 if(file_put_contents($path, $image)) {
4601 } elseif ($filetype == "image/png") {
4602 // else if the filetype is png, create png
4603 imagealphablending($img, true);
4604 imagesavealpha($img, true);
4607 $image = ob_get_clean();
4608 if(file_put_contents($path, $image)) {
4615 // check image manually
4616 $fp = fopen($path, "rb");
4617 if(!$fp) return false;
4619 // read the whole file in chunks
4621 $data .= fread($fp,8192);
4625 if(preg_match("/<(\?php|html|!doctype|script|body|head|plaintext|table|img |pre(>| )|frameset|iframe|object|link|base|style|font|applet|meta|center|form|isindex)/i",
4627 $GLOBALS['log']->fatal("Found {$m[0]} in $path, not allowing upload");
4636 * Verify uploaded image
4637 * Verifies that image has proper extension, MIME type and doesn't contain hostile content
4638 * @param string $path Image path
4639 * @param bool $jpeg_only Accept only JPEGs?
4641 function verify_uploaded_image($path, $jpeg_only = false)
4643 $supportedExtensions = array('jpg' => 'image/jpeg', 'jpeg' => 'image/jpeg');
4645 $supportedExtensions['png'] = 'image/png';
4648 if(!file_exists($path) || !is_file($path)) {
4652 $img_size = getimagesize($path);
4653 $filetype = $img_size['mime'];
4654 $ext = end(explode(".", $path));
4655 if(substr_count('..', $path) > 0 || ($ext !== $path && !isset($supportedExtensions[strtolower($ext)])) ||
4656 !in_array($filetype, array_values($supportedExtensions))) {
4659 return verify_image_file($path, $jpeg_only);
4662 function cmp_beans($a, $b)
4664 global $sugar_web_service_order_by;
4665 //If the order_by field is not valid, return 0;
4666 if (empty($sugar_web_service_order_by) || !isset($a->$sugar_web_service_order_by) || !isset($b->$sugar_web_service_order_by)){
4669 if (is_object($a->$sugar_web_service_order_by) || is_object($b->$sugar_web_service_order_by)
4670 || is_array($a->$sugar_web_service_order_by) || is_array($b->$sugar_web_service_order_by))
4674 if ($a->$sugar_web_service_order_by < $b->$sugar_web_service_order_by)
4682 function order_beans($beans, $field_name)
4684 //Since php 5.2 doesn't include closures, we must use a global to pass the order field to cmp_beans.
4685 global $sugar_web_service_order_by;
4686 $sugar_web_service_order_by = $field_name;
4687 usort($beans, "cmp_beans");
4692 * Return search like string
4693 * This function takes a user input string and returns a string that contains wild card(s) that can be used in db query.
4694 * @param string $str string to be searched
4695 * @param string $like_char Database like character, usually '%'
4696 * @return string Returns a string to be searched in db query
4698 function sql_like_string($str, $like_char, $wildcard = '%', $appendWildcard = true) {
4700 // override default wildcard character
4701 if (isset($GLOBALS['sugar_config']['search_wildcard_char']) &&
4702 strlen($GLOBALS['sugar_config']['search_wildcard_char']) == 1) {
4703 $wildcard = $GLOBALS['sugar_config']['search_wildcard_char'];
4706 // add wildcard at the beginning of the search string
4707 if (isset($GLOBALS['sugar_config']['search_wildcard_infront']) &&
4708 $GLOBALS['sugar_config']['search_wildcard_infront'] == true) {
4709 if (substr($str,0,1) <> $wildcard)
4710 $str = $wildcard.$str;
4713 // add wildcard at the end of search string (default)
4714 if ($appendWildcard) {
4715 if(substr($str,-1) <> $wildcard) {
4720 return str_replace($wildcard, $like_char, $str);
4723 //check to see if custom utils exists
4724 if(file_exists('custom/include/custom_utils.php')){
4725 include_once('custom/include/custom_utils.php');
4728 //check to see if custom utils exists in Extension framework
4729 if(file_exists('custom/application/Ext/Utils/custom_utils.ext.php')) {
4730 include_once('custom/application/Ext/Utils/custom_utils.ext.php');
4733 * @param $input - the input string to sanitize
4734 * @param int $quotes - use quotes
4735 * @param string $charset - the default charset
4736 * @param bool $remove - strip tags or not
4737 * @return string - the sanitized string
4739 function sanitize($input, $quotes = ENT_QUOTES, $charset = 'UTF-8', $remove = false)
4741 return htmlentities($input, $quotes, $charset);
4745 * @return string - the full text search engine name
4747 function getFTSEngineType()
4749 if (isset($GLOBALS['sugar_config']['full_text_engine']) && is_array($GLOBALS['sugar_config']['full_text_engine'])) {
4750 foreach ($GLOBALS['sugar_config']['full_text_engine'] as $name => $defs) {
4758 * @param string $optionName - name of the option to be retrieved from app_list_strings
4759 * @return array - the array to be used in option element
4761 function getFTSBoostOptions($optionName)
4763 if (isset($GLOBALS['app_list_strings'][$optionName])) {
4764 return $GLOBALS['app_list_strings'][$optionName];
4772 * utf8_recursive_encode
4774 * This function walks through an Array and recursively calls utf8_encode on the
4775 * values of each of the elements.
4777 * @param $data Array of data to encode
4778 * @return utf8 encoded Array data
4780 function utf8_recursive_encode($data)
4783 foreach($data as $key=>$val) {
4784 if(is_array($val)) {
4785 $result[$key] = utf8_recursive_encode($val);
4787 $result[$key] = utf8_encode($val);
4794 * get_language_header
4796 * This is a utility function for 508 Compliance. It returns the lang=[Current Language] text string used
4797 * inside the <html> tag. If no current language is specified, it defaults to lang='en'.
4799 * @return String The lang=[Current Language] markup to insert into the <html> tag
4801 function get_language_header()
4803 return isset($GLOBALS['current_language']) ? "lang='{$GLOBALS['current_language']}'" : "lang='en'";
4808 * get_custom_file_if_exists
4810 * This function handles the repetitive code we have where we first check if a file exists in the
4811 * custom directory to determine whether we should load it, require it, include it, etc. This function returns the
4812 * path of the custom file if it exists. It basically checks if custom/{$file} exists and returns this path if so;
4813 * otherwise it return $file
4815 * @param $file String of filename to check
4816 * @return $file String of filename including custom directory if found
4818 function get_custom_file_if_exists($file)
4820 return file_exists("custom/{$file}") ? "custom/{$file}" : $file;
4827 * This will return the URL used to redirect the user to the help documentation.
4828 * It can be overriden completely by setting the custom_help_url or partially by setting the custom_help_base_url
4829 * in config.php or config_override.php.
4831 * @param string $send_edition
4832 * @param string $send_version
4833 * @param string $send_lang
4834 * @param string $send_module
4835 * @param string $send_action
4836 * @param string $dev_status
4837 * @param string $send_key
4838 * @param string $send_anchor
4839 * @return string the completed help URL
4841 function get_help_url($send_edition = '', $send_version = '', $send_lang = '', $send_module = '', $send_action = '', $dev_status = '', $send_key = '', $send_anchor = '') {
4842 global $sugar_config;
4844 if (!empty($sugar_config['custom_help_url'])) {
4845 $sendUrl = $sugar_config['custom_help_url'];
4847 if (!empty($sugar_config['custom_help_base_url'])) {
4848 $baseUrl= $sugar_config['custom_help_base_url'];
4850 $baseUrl = "http://www.sugarcrm.com/crm/product_doc.php";
4852 $sendUrl = $baseUrl . "?edition={$send_edition}&version={$send_version}&lang={$send_lang}&module={$send_module}&help_action={$send_action}&status={$dev_status}&key={$send_key}";
4853 if(!empty($send_anchor)) {
4854 $sendUrl .= "&anchor=".$send_anchor;
4861 * generateETagHeader
4863 * This function generates the necessary cache headers for using ETags with dynamic content. You
4864 * simply have to generate the ETag, pass it in, and the function handles the rest.
4866 * @param string $etag ETag to use for this content.
4868 function generateETagHeader($etag){
4869 header("cache-control:");
4870 header('Expires: ');
4871 header("ETag: " . $etag);
4873 if(isset($_SERVER["HTTP_IF_NONE_MATCH"])){
4874 if($etag == $_SERVER["HTTP_IF_NONE_MATCH"]){
4876 header("Status: 304 Not Modified");
4877 header("HTTP/1.0 304 Not Modified");
4884 * getReportNameTranslation
4886 * Translates the report name if a translation exists,
4887 * otherwise just returns the name
4889 * @param string $reportName
4890 * @return string translated report name
4892 function getReportNameTranslation($reportName) {
4893 global $current_language;
4895 // Used for translating reports
4896 $mod_strings = return_module_language($current_language, 'Reports');
4898 // Search for the report name in the default language and get the key
4899 $key = array_search($reportName, return_module_language("", "Reports"));
4901 // If the key was found, use it to get a translation, otherwise just use report name
4903 $title = $mod_strings[$key];
4905 $title = $reportName;
4912 * Remove vars marked senstitive from array
4913 * @param array $defs
4914 * @param SugarBean|array $data
4915 * @return mixed $data without sensitive fields
4917 function clean_sensitive_data($defs, $data)
4919 foreach($defs as $field => $def) {
4920 if(!empty($def['sensitive'])) {
4921 if(is_array($data)) {
4924 if($data instanceof SugarBean) {
4933 * Return relations with labels for duplicates
4935 function getDuplicateRelationListWithTitle($def, $var_def, $module)
4937 global $current_language;
4938 $select_array = array_unique($def);
4939 if (count($select_array) < count($def))
4941 $temp_module_strings = return_module_language($current_language, $module);
4942 $temp_duplicate_array = array_diff_assoc($def, $select_array);
4943 $temp_duplicate_array = array_merge($temp_duplicate_array, array_intersect($select_array, $temp_duplicate_array));
4945 foreach ($temp_duplicate_array as $temp_key => $temp_value)
4947 // Don't add duplicate relationships
4948 if (!empty($var_def[$temp_key]['relationship']) && array_key_exists($var_def[$temp_key]['relationship'], $select_array))
4952 $select_array[$temp_key] = $temp_value;
4955 // Add the relationship name for easier recognition
4956 foreach ($select_array as $key => $value)
4958 $select_array[$key] .= ' (' . $key . ')';
4961 asort($select_array);
4962 return $select_array;
4966 * Gets the list of "*type_display*".
4970 function getTypeDisplayList()
4972 return array('record_type_display', 'parent_type_display', 'record_type_display_notes');
4976 * Breaks given string into substring according
4977 * to 'db_concat_fields' from field definition
4978 * and assigns values to corresponding properties
4981 * @param SugarBean $bean
4982 * @param array $fieldDef
4983 * @param string $value
4985 function assignConcatenatedValue(SugarBean $bean, $fieldDef, $value)
4987 $valueParts = explode(' ',$value);
4988 $valueParts = array_filter($valueParts);
4989 $fieldNum = count($fieldDef['db_concat_fields']);
4991 if (count($valueParts) == 1 && $fieldDef['db_concat_fields'] == array('first_name', 'last_name'))
4993 $bean->last_name = $value;
4995 // elseif ($fieldNum >= count($valueParts))
4998 for ($i = 0; $i < $fieldNum; $i++)
5000 $fieldValue = array_shift($valueParts);
5001 $fieldName = $fieldDef['db_concat_fields'][$i];
5002 $bean->$fieldName = $fieldValue !== false ? $fieldValue : '';
5005 if (!empty($valueParts))
5007 $bean->$fieldName .= ' ' . implode(' ', $valueParts);