2 /*********************************************************************************
3 * SugarCRM Community Edition is a customer relationship management program developed by
4 * SugarCRM, Inc. Copyright (C) 2004-2012 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 'cache_dir' => 'cache/',
244 'calculate_response_time' => true,
245 'create_default_user' => false,
246 'chartEngine' => 'Jit',
247 'date_formats' => array (
248 'Y-m-d' => '2010-12-23', 'm-d-Y' => '12-23-2010', 'd-m-Y' => '23-12-2010',
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', 'd.m.Y' => '23.12.2010', 'm.d.Y' => '12.23.2010',),
251 'name_formats' => array (
252 's f l' => 's f l', 'f l' => 'f l', 's l' => 's l', 'l, s f' => 'l, s f',
253 'l, f' => 'l, f', 's l, f' => 's l, f', 'l s f' => 'l s f', 'l f s' => 'l f s'
255 'dbconfigoption' => array (
256 'persistent' => true,
260 'default_action' => 'index',
261 'default_charset' => return_session_value_or_default('default_charset',
263 'default_currency_name' => return_session_value_or_default('default_currency_name', 'US Dollar'),
264 'default_currency_symbol' => return_session_value_or_default('default_currency_symbol', '$'),
265 'default_currency_iso4217' => return_session_value_or_default('default_currency_iso4217', 'USD'),
266 'default_currency_significant_digits' => return_session_value_or_default('default_currency_significant_digits', 2),
267 'default_number_grouping_seperator' => return_session_value_or_default('default_number_grouping_seperator', ','),
268 'default_decimal_seperator' => return_session_value_or_default('default_decimal_seperator', '.'),
269 'default_date_format' => 'm/d/Y',
270 'default_locale_name_format' => 's f l',
271 'default_export_charset' => 'UTF-8',
272 'default_language' => return_session_value_or_default('default_language',
274 'default_module' => 'Home',
275 'default_password' => '',
276 'default_permissions' => array (
282 'default_theme' => return_session_value_or_default('site_default_theme', 'Sugar5'),
283 'default_time_format' => 'h:ia',
284 'default_user_is_admin' => false,
285 'default_user_name' => '',
286 'disable_export' => false,
287 'disable_persistent_connections' =>
288 return_session_value_or_default('disable_persistent_connections',
290 'display_email_template_variable_chooser' => false,
291 'display_inbound_email_buttons' => false,
292 'dump_slow_queries' => false,
293 'email_address_separator' => ',', // use RFC2368 spec unless we have a noncompliant email client
294 'email_default_editor' => 'html',
295 'email_default_client' => 'sugar',
296 'email_default_delete_attachments' => true,
297 'history_max_viewed' => 50,
298 'installer_locked' => true,
299 'import_max_records_per_file' => 100,
300 'import_max_records_total_limit' => '',
301 'languages' => array('en_us' => 'English (US)'),
302 'large_scale_test' => false,
303 'list_max_entries_per_page' => 20,
304 'list_max_entries_per_subpanel' => 10,
305 'lock_default_user_name' => false,
306 'log_memory_usage' => false,
307 'portal_view' => 'single_user',
308 'resource_management' => array (
309 'special_query_limit' => 50000,
310 'special_query_modules' => array('Reports', 'Export', 'Import', 'Administration', 'Sync'),
311 'default_limit' => 1000,
313 'require_accounts' => true,
314 'rss_cache_time' => return_session_value_or_default('rss_cache_time',
316 'save_query' => 'all',
317 'showDetailData' => true, // if true, read-only ACL fields will still appear on EditViews as non-editable
318 'showThemePicker' => true,
319 'slow_query_time_msec' => '100',
321 'time_formats' => array (
322 'H:i'=>'23:00', 'h:ia'=>'11:00pm', 'h:iA'=>'11:00PM', 'h:i a'=>'11:00 pm', 'h:i A'=>'11:00 PM',
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 'tracker_max_display_length' => 15,
325 'translation_string_prefix' =>
326 return_session_value_or_default('translation_string_prefix', false),
327 'upload_badext' => array (
328 'php', 'php3', 'php4', 'php5', 'pl', 'cgi', 'py',
329 'asp', 'cfm', 'js', 'vbs', 'html', 'htm' ),
330 'upload_maxsize' => 30000000,
331 'import_max_execution_time' => 3600,
332 // 'use_php_code_json' => returnPhpJsonStatus(),
333 'verify_client_ip' => true,
334 'js_custom_version' => '',
335 'js_lang_version' => 1,
336 'lead_conv_activity_opt' => 'donothing',
337 'default_number_grouping_seperator' => ',',
338 'default_decimal_seperator' => '.',
339 'lock_homepage' => false,
340 'lock_subpanels' => false,
341 'max_dashlets_homepage' => '15',
342 'default_max_tabs' => '7',
343 'dashlet_display_row_options' => array('1','3','5','10'),
344 'default_subpanel_tabs' => true,
345 'default_subpanel_links' => false,
346 'default_swap_last_viewed' => false,
347 'default_swap_shortcuts' => false,
348 'default_navigation_paradigm' => 'gm',
349 'admin_access_control' => false,
350 'use_common_ml_dir' => false,
351 'common_ml_dir' => '',
354 'default_view' => 'week',
355 'show_calls_by_default' => true,
356 'show_tasks_by_default' => true,
357 'editview_width' => 990,
358 'editview_height' => 485,
359 'day_timestep' => 15,
360 'week_timestep' => 30,
361 'items_draggable' => true,
362 'items_resizable' => true,
363 'enable_repeat' => true,
364 'max_repeat_count' => 1000,
366 'passwordsetting' => empty($passwordsetting) ? array (
367 'SystemGeneratedPasswordON' => '',
368 'generatepasswordtmpl' => '',
369 'lostpasswordtmpl' => '',
370 'forgotpasswordON' => false,
371 'linkexpiration' => '1',
372 'linkexpirationtime' => '30',
373 'linkexpirationtype' => '1',
374 'systexpiration' => '0',
375 'systexpirationtime' => '',
376 'systexpirationtype' => '0',
377 'systexpirationlogin' => '',
378 ) : $passwordsetting,
379 'use_real_names' => true,
381 'search_wildcard_infront' => false,
382 'search_wildcard_char' => '%',
384 'min_retry_interval' => 30, // 30 seconds minimal job retry
385 'max_retries' => 5, // how many times to retry the job
386 'timeout' => 86400, // how long a job may spend as running before being force-failed
389 'max_cron_jobs' => 10, // max jobs per cron schedule run
390 'max_cron_runtime' => 30, // max runtime for cron jobs
391 'min_cron_interval' => 30, // minimal interval between cron jobs
395 if(!is_object($locale)) {
396 $locale = new Localization();
399 $sugar_config_defaults['default_currencies'] = $locale->getDefaultCurrencies();
401 $sugar_config_defaults = sugarArrayMerge($locale->getLocaleConfigDefaults(), $sugar_config_defaults);
402 return( $sugar_config_defaults );
406 * @deprecated use SugarView::getMenu() instead
408 function load_menu($path){
411 if(file_exists($path . 'Menu.php'))
413 require($path . 'Menu.php');
415 if(file_exists('custom/' . $path . 'Ext/Menus/menu.ext.php'))
417 require('custom/' . $path . 'Ext/Menus/menu.ext.php');
419 if(file_exists('custom/application/Ext/Menus/menu.ext.php'))
421 require('custom/application/Ext/Menus/menu.ext.php');
427 * get_notify_template_file
428 * This function will return the location of the email notifications template to use
430 * @return string relative file path to email notifications template file
432 function get_notify_template_file($language){
434 * Order of operation:
435 * 1) custom version of specified language
436 * 2) stock version of specified language
437 * 3) custom version of en_us template
438 * 4) stock en_us template
441 // set $file to the base code template so it's set if none of the conditions pass
442 $file = "include/language/en_us.notify_template.html";
444 if(file_exists("custom/include/language/{$language}.notify_template.html")){
445 $file = "custom/include/language/{$language}.notify_template.html";
447 else if(file_exists("include/language/{$language}.notify_template.html")){
448 $file = "include/language/{$language}.notify_template.html";
450 else if(file_exists("custom/include/language/en_us.notify_template.html")){
451 $file = "custom/include/language/en_us.notify_template.html";
457 function sugar_config_union( $default, $override ){
458 // a little different then array_merge and array_merge_recursive. we want
459 // the second array to override the first array if the same value exists,
460 // otherwise merge the unique keys. it handles arrays of arrays recursively
461 // might be suitable for a generic array_union
462 if( !is_array( $override ) ){
465 foreach( $default as $key => $value ){
466 if( !array_key_exists($key, $override) ){
467 $override[$key] = $value;
469 else if( is_array( $key ) ){
470 $override[$key] = sugar_config_union( $value, $override[$key] );
476 function make_not_writable( $file ){
477 // Returns true if the given file/dir has been made not writable
479 if( is_file($file) || is_dir($file) ){
480 if( !is_writable($file) ){
484 $original_fileperms = fileperms($file);
486 // take away writable permissions
487 $new_fileperms = $original_fileperms & ~0x0092;
488 @sugar_chmod($file, $new_fileperms);
490 if( !is_writable($file) ){
499 /** This function returns the name of the person.
500 * It currently returns "first last". It should not put the space if either name is not available.
501 * It should not return errors if either name is not available.
502 * If no names are present, it will return ""
503 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
504 * All Rights Reserved.
505 * Contributor(s): ______________________________________..
507 function return_name($row, $first_column, $last_column)
513 if(isset($row[$first_column]))
515 $first_name = stripslashes($row[$first_column]);
518 if(isset($row[$last_column]))
520 $last_name = stripslashes($row[$last_column]);
523 $full_name = $first_name;
525 // If we have a first name and we have a last name
526 if($full_name != "" && $last_name != "")
528 // append a space, then the last name
529 $full_name .= " ".$last_name;
531 // If we have no first name, but we have a last name
532 else if($last_name != "")
534 // append the last name without the space.
535 $full_name .= $last_name;
542 function get_languages()
544 global $sugar_config;
545 $lang = $sugar_config['languages'];
546 if(!empty($sugar_config['disabled_languages'])){
547 foreach(explode(',', $sugar_config['disabled_languages']) as $disable) {
548 unset($lang[$disable]);
554 function get_all_languages()
556 global $sugar_config;
557 return $sugar_config['languages'];
561 function get_language_display($key)
563 global $sugar_config;
564 return $sugar_config['languages'][$key];
567 function get_assigned_user_name($assigned_user_id, $is_group = '') {
568 static $saved_user_list = null;
570 if(empty($saved_user_list)) {
571 $saved_user_list = get_user_array(false, '', '', false, null, $is_group);
574 if(isset($saved_user_list[$assigned_user_id])) {
575 return $saved_user_list[$assigned_user_id];
582 * retrieves the user_name column value (login)
583 * @param string id GUID of user
586 function get_user_name($id) {
590 $db = DBManagerFactory::getInstance();
592 $q = "SELECT user_name FROM users WHERE id='{$id}'";
594 $a = $db->fetchByAssoc($r);
596 return (empty($a)) ? '' : $a['user_name'];
600 //TODO Update to use global cache
604 * This is a helper function to return an Array of users depending on the parameters passed into the function.
605 * This function uses the get_register_value function by default to use a caching layer where supported.
607 * @param bool $add_blank Boolean value to add a blank entry to the array results, true by default
608 * @param string $status String value indicating the status to filter users by, "Active" by default
609 * @param string $user_id String value to specify a particular user id value (searches the id column of users table), blank by default
610 * @param bool $use_real_name Boolean value indicating whether or not results should include the full name or just user_name, false by default
611 * @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
612 * @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
613 * @param bool $from_cache Boolean value indicating whether or not to use the get_register_value function for caching, true by default
614 * @return array Array of users matching the filter criteria that may be from cache (if similar search was previously run)
616 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) {
618 global $sugar_config;
621 $locale = new Localization();
625 $key_name = $add_blank. $status . $user_id . $use_real_name . $user_name_filter . $portal_filter;
626 $user_array = get_register_value('user_array', $key_name);
629 if(empty($user_array)) {
630 $db = DBManagerFactory::getInstance();
631 $temp_result = Array();
632 // Including deleted users for now.
633 if (empty($status)) {
634 $query = "SELECT id, first_name, last_name, user_name from users WHERE 1=1".$portal_filter;
637 $query = "SELECT id, first_name, last_name, user_name from users WHERE status='$status'".$portal_filter;
640 if (!empty($user_name_filter)) {
641 $user_name_filter = $db->quote($user_name_filter);
642 $query .= " AND user_name LIKE '$user_name_filter%' ";
644 if (!empty($user_id)) {
645 $query .= " OR id='{$user_id}'";
647 $query = $query.' ORDER BY user_name ASC';
648 $GLOBALS['log']->debug("get_user_array query: $query");
649 $result = $db->query($query, true, "Error filling in user array: ");
651 if ($add_blank==true) {
652 // Add in a blank row
653 $temp_result[''] = '';
656 // Get the id and the name.
657 while($row = $db->fetchByAssoc($result)) {
658 if($use_real_name == true || showFullName()) {
659 if(isset($row['last_name'])) { // cn: we will ALWAYS have both first_name and last_name (empty value if blank in db)
660 $temp_result[$row['id']] = $locale->getLocaleFormattedName($row['first_name'],$row['last_name']);
662 $temp_result[$row['id']] = $row['user_name'];
665 $temp_result[$row['id']] = $row['user_name'];
669 $user_array = $temp_result;
672 set_register_value('user_array', $key_name, $temp_result);
682 * uses a different query to return a list of users than get_user_array()
683 * Used from QuickSearch.php
684 * @param args string where clause entry
685 * @return array Array of Users' details that match passed criteria
687 function getUserArrayFromFullName($args, $hide_portal_users = false) {
689 $db = DBManagerFactory::getInstance();
691 // jmorais@dri - Bug #51411
693 // Refactor the code responsible for parsing supplied $args, this way we
694 // ensure that if $args has at least one space (after trim), the $inClause
695 // will be composed by several clauses ($inClauses) inside parenthesis.
697 // Ensuring that operator precedence is respected, and avoiding
698 // inactive/deleted users to be retrieved.
701 if (strpos($args, ' ')) {
702 $inClauses = array();
704 $argArray = explode(' ', $args);
705 foreach ($argArray as $arg) {
706 $arg = $db->quote($arg);
707 $inClauses[] = "(first_name LIKE '{$arg}%' OR last_name LIKE '{$arg}%')";
710 $inClause = '(' . implode('OR ', $inClauses) . ')';
713 $args = $db->quote($args);
714 $inClause = "(first_name LIKE '{$args}%' OR last_name LIKE '{$args}%')";
718 $query = "SELECT id, first_name, last_name, user_name FROM users WHERE status='Active' AND deleted=0 AND ";
719 if ( $hide_portal_users ) {
720 $query .= " portal_only=0 AND ";
723 $query .= " ORDER BY last_name ASC";
725 $r = $db->query($query);
727 while($a = $db->fetchByAssoc($r)) {
728 $ret[$a['id']] = $locale->getLocaleFormattedName($a['first_name'], $a['last_name']);
736 * based on user pref then system pref
738 function showFullName() {
739 global $sugar_config;
740 global $current_user;
741 static $showFullName = null;
743 if (is_null($showFullName)) {
744 $sysPref = !empty($sugar_config['use_real_names']);
745 $userPref = (is_object($current_user)) ? $current_user->getPreference('use_real_names') : null;
747 if($userPref != null) {
748 $showFullName = ($userPref == 'on');
750 $showFullName = $sysPref;
754 return $showFullName;
757 function clean($string, $maxLength)
759 $string = substr($string, 0, $maxLength);
760 return escapeshellcmd($string);
764 * Copy the specified request variable to the member variable of the specified object.
765 * Do no copy if the member variable is already set.
766 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
767 * All Rights Reserved.
768 * Contributor(s): ______________________________________..
770 function safe_map($request_var, & $focus, $always_copy = false)
772 safe_map_named($request_var, $focus, $request_var, $always_copy);
776 * Copy the specified request variable to the member variable of the specified object.
777 * Do no copy if the member variable is already set.
778 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
779 * All Rights Reserved.
780 * Contributor(s): ______________________________________..
782 function safe_map_named($request_var, & $focus, $member_var, $always_copy)
784 if (isset($_REQUEST[$request_var]) && ($always_copy || is_null($focus->$member_var))) {
785 $GLOBALS['log']->debug("safe map named called assigning '{$_REQUEST[$request_var]}' to $member_var");
786 $focus->$member_var = $_REQUEST[$request_var];
791 * This function retrieves an application language file and returns the array of strings included in the $app_list_strings var.
793 * @param string $language specific language to load
794 * @return array lang strings
796 function return_app_list_strings_language($language)
798 global $app_list_strings;
799 global $sugar_config;
801 $cache_key = 'app_list_strings.'.$language;
803 // Check for cached value
804 $cache_entry = sugar_cache_retrieve($cache_key);
805 if(!empty($cache_entry))
810 $default_language = $sugar_config['default_language'];
811 $temp_app_list_strings = $app_list_strings;
814 if ($language != 'en_us') {
817 if ($default_language != 'en_us' && $language != $default_language) {
818 $langs[] = $default_language;
820 $langs[] = $language;
822 $app_list_strings_array = array();
824 foreach ( $langs as $lang ) {
825 $app_list_strings = array();
826 if(file_exists("include/language/$lang.lang.php")) {
827 include("include/language/$lang.lang.php");
828 $GLOBALS['log']->info("Found language file: $lang.lang.php");
830 if(file_exists("include/language/$lang.lang.override.php")) {
831 include("include/language/$lang.lang.override.php");
832 $GLOBALS['log']->info("Found override language file: $lang.lang.override.php");
834 if(file_exists("include/language/$lang.lang.php.override")) {
835 include("include/language/$lang.lang.php.override");
836 $GLOBALS['log']->info("Found override language file: $lang.lang.php.override");
839 $app_list_strings_array[] = $app_list_strings;
842 $app_list_strings = array();
843 foreach ( $app_list_strings_array as $app_list_strings_item ) {
844 $app_list_strings = sugarLangArrayMerge($app_list_strings, $app_list_strings_item);
847 foreach ( $langs as $lang ) {
848 if(file_exists("custom/application/Ext/Language/$lang.lang.ext.php")) {
849 $app_list_strings = _mergeCustomAppListStrings("custom/application/Ext/Language/$lang.lang.ext.php" , $app_list_strings);
850 $GLOBALS['log']->info("Found extended language file: $lang.lang.ext.php");
852 if(file_exists("custom/include/language/$lang.lang.php")) {
853 include("custom/include/language/$lang.lang.php");
854 $GLOBALS['log']->info("Found custom language file: $lang.lang.php");
858 if(!isset($app_list_strings)) {
859 $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");
863 $return_value = $app_list_strings;
864 $app_list_strings = $temp_app_list_strings;
866 sugar_cache_put($cache_key, $return_value);
868 return $return_value;
872 * The dropdown items in custom language files is $app_list_strings['$key']['$second_key'] = $value not
873 * $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.
874 * @param file string the language that you want include,
875 * @param app_list_strings array the golbal strings
879 function _mergeCustomAppListStrings($file , $app_list_strings){
880 $app_list_strings_original = $app_list_strings;
881 unset($app_list_strings);
882 // FG - bug 45525 - $exemptDropdown array is defined (once) here, not inside the foreach
883 // This way, language file can add items to save specific standard codelist from being overwritten
884 $exemptDropdowns = array();
886 if(!isset($app_list_strings) || !is_array($app_list_strings)){
887 return $app_list_strings_original;
889 //Bug 25347: We should not merge custom dropdown fields unless they relate to parent fields or the module list.
891 // FG - bug 45525 - Specific codelists must NOT be overwritten
892 $exemptDropdowns[] = "moduleList";
893 $exemptDropdowns[] = "moduleListSingular";
894 $exemptDropdowns[] = "parent_type_display";
895 $exemptDropdowns[] = "record_type_display";
896 $exemptDropdowns[] = "record_type_display_notes";
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.
1536 if (($option_key != '' && $selected_key == $option_key) || ($selected_key == '' && $option_key == '' && !$massupdate) || (is_array($selected_key) && in_array($option_key, $selected_key)))
1538 $selected_string = 'selected ';
1541 $html_value = $option_key;
1543 $select_options .= "\n<OPTION ".$selected_string."value='$html_value'>$label_list[$option_key]</OPTION>";
1545 $select_options = preg_replace($pattern, $replacement, $select_options);
1546 return $select_options;
1551 * Call this method instead of die().
1552 * We print the error message and then die with an appropriate
1555 function sugar_die($error_message, $exit_code = 1)
1559 echo $error_message;
1565 * Create javascript to clear values of all elements in a form.
1566 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1567 * All Rights Reserved.
1568 * Contributor(s): ______________________________________..
1570 function get_clear_form_js () {
1571 $the_script = <<<EOQ
1572 <script type="text/javascript" language="JavaScript">
1573 function clear_form(form) {
1574 var newLoc = 'index.php?action=' + form.action.value + '&module=' + form.module.value + '&query=true&clear_query=true';
1575 if(typeof(form.advanced) != 'undefined'){
1576 newLoc += '&advanced=' + form.advanced.value;
1578 document.location.href= newLoc;
1587 * Create javascript to set the cursor focus to specific field in a form
1588 * when the screen is rendered. The field name is currently hardcoded into the
1590 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1591 * All Rights Reserved.
1592 * Contributor(s): ______________________________________..
1594 function get_set_focus_js () {
1595 //TODO Clint 5/20 - Make this function more generic so that it can take in the target form and field names as variables
1596 $the_script = <<<EOQ
1597 <script type="text/javascript" language="JavaScript">
1599 function set_focus() {
1600 if (document.forms.length > 0) {
1601 for (i = 0; i < document.forms.length; i++) {
1602 for (j = 0; j < document.forms[i].elements.length; j++) {
1603 var field = document.forms[i].elements[j];
1604 if ((field.type == "text" || field.type == "textarea" || field.type == "password") &&
1605 !field.disabled && (field.name == "first_name" || field.name == "name" || field.name == "user_name" || field.name=="document_name")) {
1607 if (field.type == "text") {
1624 * Very cool algorithm for sorting multi-dimensional arrays. Found at http://us2.php.net/manual/en/function.array-multisort.php
1625 * Syntax: $new_array = array_csort($array [, 'col1' [, SORT_FLAG [, SORT_FLAG]]]...);
1626 * Explanation: $array is the array you want to sort, 'col1' is the name of the column
1627 * you want to sort, SORT_FLAGS are : SORT_ASC, SORT_DESC, SORT_REGULAR, SORT_NUMERIC, SORT_STRING
1628 * you can repeat the 'col',FLAG,FLAG, as often you want, the highest prioritiy is given to
1629 * the first - so the array is sorted by the last given column first, then the one before ...
1630 * Example: $array = array_csort($array,'town','age',SORT_DESC,'name');
1631 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1632 * All Rights Reserved.
1633 * Contributor(s): ______________________________________..
1635 function array_csort() {
1636 $args = func_get_args();
1637 $marray = array_shift($args);
1640 $msortline = "return(array_multisort(";
1641 foreach ($args as $arg) {
1643 if (is_string($arg)) {
1644 foreach ($marray as $row) {
1645 $sortarr[$i][] = $row[$arg];
1648 $sortarr[$i] = $arg;
1650 $msortline .= "\$sortarr[".$i."],";
1652 $msortline .= "\$marray));";
1659 * Converts localized date format string to jscalendar format
1660 * Example: $array = array_csort($array,'town','age',SORT_DESC,'name');
1661 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1662 * All Rights Reserved.
1663 * Contributor(s): ______________________________________..
1665 function parse_calendardate($local_format) {
1666 preg_match('/\(?([^-]{1})[^-]*-([^-]{1})[^-]*-([^-]{1})[^-]*\)/', $local_format, $matches);
1667 $calendar_format = "%" . $matches[1] . "-%" . $matches[2] . "-%" . $matches[3];
1668 return str_replace(array("y", "ᅣ1�7", "a", "j"), array("Y", "Y", "Y", "d"), $calendar_format);
1675 function translate($string, $mod='', $selectedValue=''){
1676 //$test_start = microtime();
1677 //static $mod_strings_results = array();
1679 global $current_language;
1681 if(isset($_REQUEST['login_language'])){
1682 $current_language = ($_REQUEST['login_language'] == $current_language)? $current_language : $_REQUEST['login_language'];
1684 $mod_strings = return_module_language($current_language, $mod);
1686 echo "Language is <pre>" . $mod_strings . "</pre>";
1689 global $mod_strings;
1693 global $app_strings, $app_list_strings;
1695 if (isset($mod_strings[$string]))
1696 $returnValue = $mod_strings[$string];
1697 else if (isset($app_strings[$string]))
1698 $returnValue = $app_strings[$string];
1699 else if (isset($app_list_strings[$string]))
1700 $returnValue = $app_list_strings[$string];
1701 else if (isset($app_list_strings['moduleList']) && isset($app_list_strings['moduleList'][$string]))
1702 $returnValue = $app_list_strings['moduleList'][$string];
1705 //$test_end = microtime();
1707 // $mod_strings_results[$mod] = microtime_diff($test_start,$test_end);
1709 // echo("translate results:");
1711 // $total_strings = 0;
1712 // foreach($mod_strings_results as $key=>$value)
1714 // echo("Module $key \t\t time $value \t\t<br>");
1715 // $total_time += $value;
1718 // echo("Total time: $total_time<br>");
1722 if(empty($returnValue)){
1726 // Bug 48996 - Custom enums with '0' value were not returning because of empty check
1727 // Added a numeric 0 checker to the conditional to allow 0 value indexed to pass
1728 if(is_array($returnValue) && (!empty($selectedValue) || (is_numeric($selectedValue) && $selectedValue == 0)) && isset($returnValue[$selectedValue]) ){
1729 return $returnValue[$selectedValue];
1732 return $returnValue;
1735 function unTranslateNum($num) {
1737 static $num_grp_sep;
1738 global $current_user, $sugar_config;
1740 if($dec_sep == null) {
1741 $user_dec_sep = $current_user->getPreference('dec_sep');
1742 $dec_sep = (empty($user_dec_sep) ? $sugar_config['default_decimal_seperator'] : $user_dec_sep);
1744 if($num_grp_sep == null) {
1745 $user_num_grp_sep = $current_user->getPreference('num_grp_sep');
1746 $num_grp_sep = (empty($user_num_grp_sep) ? $sugar_config['default_number_grouping_seperator'] : $user_num_grp_sep);
1749 $num = preg_replace("'" . preg_quote($num_grp_sep) . "'", '', $num);
1750 $num = preg_replace("'" . preg_quote($dec_sep) . "'", '.', $num);
1755 function add_http($url) {
1756 if(!preg_match("@://@i", $url)) {
1758 if(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') {
1762 return "{$scheme}://{$url}";
1769 * returns a default array of XSS tags to clean
1772 function getDefaultXssTags() {
1774 "applet" => "applet",
1779 "frameset" => "frameset",
1780 "iframe" => "iframe",
1781 "import" => "\?import",
1784 "object" => "object",
1785 "script" => "script",
1789 $ret = base64_encode(serialize($tmp));
1795 * Remove potential xss vectors from strings
1796 * @param string str String to search for XSS attack vectors
1800 function remove_xss($str)
1802 return SugarCleaner::cleanHtml($str, false);
1806 * Detects typical XSS attack patterns
1808 * @param string str String to search for XSS attack vectors
1809 * @param bool cleanImg Flag to allow <img> tags to survive - only used by InboundEmail for inline images.
1810 * @return array Array of matches, empty on clean string
1812 function clean_xss($str, $cleanImg=true) {
1813 global $sugar_config;
1815 if(empty($sugar_config['email_xss']))
1816 $sugar_config['email_xss'] = getDefaultXssTags();
1818 $xsstags = unserialize(base64_decode($sugar_config['email_xss']));
1820 // cn: bug 13079 - "on\w" matched too many non-events (cONTact, strONG, etc.)
1821 $jsEvents = "onblur|onfocus|oncontextmenu|onresize|onscroll|onunload|ondblclick|onclick|";
1822 $jsEvents .= "onmouseup|onmouseover|onmousedown|onmouseenter|onmouseleave|onmousemove|onload|onchange|";
1823 $jsEvents .= "onreset|onselect|onsubmit|onkeydown|onkeypress|onkeyup|onabort|onerror|ondragdrop";
1825 $attribute_regex = "#\b({$jsEvents})\s*=\s*(?|(?!['\"])\S+|['\"].+?['\"])#sim";
1826 $javascript_regex = '@<[^/>][^>]+(expression\(|j\W*a\W*v\W*a|v\W*b\W*s\W*c\W*r|&#|/\*|\*/)[^>]*>@sim';
1827 $imgsrc_regex = '#<[^>]+src[^=]*=([^>]*?http(s)?://[^>]*)>#sim';
1828 $css_url = '#url\(.*\.\w+\)#';
1830 $tagsrex = '#<\/?(\w+)((?:\s+(?:\w|\w[\w-]*\w)(?:\s*=\s*(?:\".*?\"|\'.*?\'|[^\'\">\s]+))?)+\s*|\s*)\/?>#im';
1832 $tagmatches = array();
1834 preg_match_all($tagsrex, $str, $tagmatches, PREG_PATTERN_ORDER);
1835 foreach($tagmatches[1] as $no => $tag) {
1836 if(in_array($tag, $xsstags)) {
1837 // dangerous tag - take out whole
1838 $matches[] = $tagmatches[0][$no];
1841 $attrmatch = array();
1842 preg_match_all($attribute_regex, $tagmatches[2][$no], $attrmatch, PREG_PATTERN_ORDER);
1843 if(!empty($attrmatch[0])) {
1844 $matches = array_merge($matches, $attrmatch[0]);
1848 $matches = array_merge($matches, xss_check_pattern($javascript_regex, $str));
1851 $matches = array_merge($matches,
1852 xss_check_pattern($imgsrc_regex, $str)
1856 // cn: bug 13498 - custom white-list of allowed domains that vet remote images
1857 preg_match_all($css_url, $str, $cssUrlMatches, PREG_PATTERN_ORDER);
1859 if(isset($sugar_config['security_trusted_domains']) && !empty($sugar_config['security_trusted_domains']) && is_array($sugar_config['security_trusted_domains'])) {
1860 if(is_array($cssUrlMatches) && count($cssUrlMatches) > 0) {
1861 // normalize whitelist
1862 foreach($sugar_config['security_trusted_domains'] as $k => $v) {
1863 $sugar_config['security_trusted_domains'][$k] = strtolower($v);
1866 foreach($cssUrlMatches[0] as $match) {
1867 $domain = strtolower(substr(strstr($match, "://"), 3));
1868 $baseUrl = substr($domain, 0, strpos($domain, "/"));
1870 if(!in_array($baseUrl, $sugar_config['security_trusted_domains'])) {
1871 $matches[] = $match;
1876 $matches = array_merge($matches, $cssUrlMatches[0]);
1883 * Helper function used by clean_xss() to parse for known-bad vectors
1884 * @param string pattern Regex pattern to use
1885 * @param string str String to parse for badness
1888 function xss_check_pattern($pattern, $str) {
1889 preg_match_all($pattern, $str, $matches, PREG_PATTERN_ORDER);
1894 * Designed to take a string passed in the URL as a parameter and clean all "bad" data from it
1896 * @param string $str
1897 * @param string $filter which corresponds to a regular expression to use; choices are:
1898 * "STANDARD" ( default )
1908 * @param boolean $dieOnBadData true (default) if you want to die if bad data if found, false if not
1910 function clean_string($str, $filter = "STANDARD", $dieOnBadData = true)
1912 global $sugar_config;
1915 "STANDARD" => '#[^A-Z0-9\-_\.\@]#i',
1916 "STANDARDSPACE" => '#[^A-Z0-9\-_\.\@\ ]#i',
1917 "FILE" => '#[^A-Z0-9\-_\.]#i',
1918 "NUMBER" => '#[^0-9\-]#i',
1919 "SQL_COLUMN_LIST" => '#[^A-Z0-9\(\),_\.]#i',
1920 "PATH_NO_URL" => '#://#i',
1921 "SAFED_GET" => '#[^A-Z0-9\@\=\&\?\.\/\-_~+]#i', /* range of allowed characters in a GET string */
1922 "UNIFIED_SEARCH" => "#[\\x00]#", /* cn: bug 3356 & 9236 - MBCS search strings */
1923 "AUTO_INCREMENT" => '#[^0-9\-,\ ]#i',
1924 "ALPHANUM" => '#[^A-Z0-9\-]#i',
1927 if (preg_match($filters[$filter], $str)) {
1928 if (isset($GLOBALS['log']) && is_object($GLOBALS['log'])) {
1929 $GLOBALS['log']->fatal("SECURITY[$filter]: bad data passed in; string: {$str}");
1931 if ( $dieOnBadData ) {
1932 die("Bad data passed in; <a href=\"{$sugar_config['site_url']}\">Return to Home</a>");
1941 function clean_special_arguments() {
1942 if(isset($_SERVER['PHP_SELF'])) {
1943 if (!empty($_SERVER['PHP_SELF'])) clean_string($_SERVER['PHP_SELF'], 'SAFED_GET');
1945 if (!empty($_REQUEST) && !empty($_REQUEST['login_theme'])) clean_string($_REQUEST['login_theme'], "STANDARD");
1946 if (!empty($_REQUEST) && !empty($_REQUEST['login_module'])) clean_string($_REQUEST['login_module'], "STANDARD");
1947 if (!empty($_REQUEST) && !empty($_REQUEST['login_action'])) clean_string($_REQUEST['login_action'], "STANDARD");
1948 if (!empty($_REQUEST) && !empty($_REQUEST['ck_login_theme_20'])) clean_string($_REQUEST['ck_login_theme_20'], "STANDARD");
1949 if (!empty($_SESSION) && !empty($_SESSION['authenticated_user_theme'])) clean_string($_SESSION['authenticated_user_theme'], "STANDARD");
1950 if (!empty($_REQUEST) && !empty($_REQUEST['module_name'])) clean_string($_REQUEST['module_name'], "STANDARD");
1951 if (!empty($_REQUEST) && !empty($_REQUEST['module'])) clean_string($_REQUEST['module'], "STANDARD");
1952 if (!empty($_POST) && !empty($_POST['parent_type'])) clean_string($_POST['parent_type'], "STANDARD");
1953 if (!empty($_REQUEST) && !empty($_REQUEST['mod_lang'])) clean_string($_REQUEST['mod_lang'], "STANDARD");
1954 if (!empty($_SESSION) && !empty($_SESSION['authenticated_user_language'])) clean_string($_SESSION['authenticated_user_language'], "STANDARD");
1955 if (!empty($_SESSION) && !empty($_SESSION['dyn_layout_file'])) clean_string($_SESSION['dyn_layout_file'], "PATH_NO_URL");
1956 if (!empty($_GET) && !empty($_GET['from'])) clean_string($_GET['from']);
1957 if (!empty($_GET) && !empty($_GET['gmto'])) clean_string($_GET['gmto'], "NUMBER");
1958 if (!empty($_GET) && !empty($_GET['case_number'])) clean_string($_GET['case_number'], "AUTO_INCREMENT");
1959 if (!empty($_GET) && !empty($_GET['bug_number'])) clean_string($_GET['bug_number'], "AUTO_INCREMENT");
1960 if (!empty($_GET) && !empty($_GET['quote_num'])) clean_string($_GET['quote_num'], "AUTO_INCREMENT");
1961 clean_superglobals('stamp', 'ALPHANUM'); // for vcr controls
1962 clean_superglobals('offset', 'ALPHANUM');
1963 clean_superglobals('return_action');
1964 clean_superglobals('return_module');
1969 * cleans the given key in superglobals $_GET, $_POST, $_REQUEST
1971 function clean_superglobals($key, $filter = 'STANDARD') {
1972 if(isset($_GET[$key])) clean_string($_GET[$key], $filter);
1973 if(isset($_POST[$key])) clean_string($_POST[$key], $filter);
1974 if(isset($_REQUEST[$key])) clean_string($_REQUEST[$key], $filter);
1977 function set_superglobals($key, $val){
1979 $_POST[$key] = $val;
1980 $_REQUEST[$key] = $val;
1983 // Works in conjunction with clean_string() to defeat SQL injection, file inclusion attacks, and XSS
1984 function clean_incoming_data() {
1985 global $sugar_config;
1986 global $RAW_REQUEST;
1988 if(get_magic_quotes_gpc()) {
1989 // magic quotes screw up data, we'd have to clean up
1990 $RAW_REQUEST = array_map("cleanup_slashes", $_REQUEST);
1992 $RAW_REQUEST = $_REQUEST;
1995 if (get_magic_quotes_gpc() == 1) {
1996 $req = array_map("preprocess_param", $_REQUEST);
1997 $post = array_map("preprocess_param", $_POST);
1998 $get = array_map("preprocess_param", $_GET);
2001 $req = array_map("securexss", $_REQUEST);
2002 $post = array_map("securexss", $_POST);
2003 $get = array_map("securexss", $_GET);
2006 // PHP cannot stomp out superglobals reliably
2007 foreach($post as $k => $v) { $_POST[$k] = $v; }
2008 foreach($get as $k => $v) { $_GET[$k] = $v; }
2009 foreach($req as $k => $v) {
2012 //ensure the keys are safe as well. If mbstring encoding translation is on, the post keys don't
2013 //get translated, so scrub the data but don't die
2014 if(ini_get('mbstring.encoding_translation')==='1'){
2015 securexsskey($k,false);
2017 securexsskey($k,true);
2021 // Any additional variables that need to be cleaned should be added here
2022 if (isset($_REQUEST['login_theme'])) clean_string($_REQUEST['login_theme']);
2023 if (isset($_REQUEST['login_module'])) clean_string($_REQUEST['login_module']);
2024 if (isset($_REQUEST['login_action'])) clean_string($_REQUEST['login_action']);
2025 if (isset($_REQUEST['login_language'])) clean_string($_REQUEST['login_language']);
2026 if (isset($_REQUEST['action'])) clean_string($_REQUEST['action']);
2027 if (isset($_REQUEST['module'])) clean_string($_REQUEST['module']);
2028 if (isset($_REQUEST['record'])) clean_string($_REQUEST['record'], 'STANDARDSPACE');
2029 if (isset($_SESSION['authenticated_user_theme'])) clean_string($_SESSION['authenticated_user_theme']);
2030 if (isset($_SESSION['authenticated_user_language'])) clean_string($_SESSION['authenticated_user_language']);
2031 if (isset($_REQUEST['language'])) clean_string($_REQUEST['language']);
2032 if (isset($sugar_config['default_theme'])) clean_string($sugar_config['default_theme']);
2033 if (isset($_REQUEST['offset'])) clean_string($_REQUEST['offset']);
2034 if (isset($_REQUEST['stamp'])) clean_string($_REQUEST['stamp']);
2036 if(isset($_REQUEST['lvso'])){
2037 set_superglobals('lvso', (strtolower($_REQUEST['lvso']) === 'desc')?'desc':'asc');
2039 // Clean "offset" and "order_by" parameters in URL
2040 foreach ($_REQUEST as $key => $val) {
2041 if (str_end($key, "_offset")) {
2042 clean_string($_REQUEST[$key], "ALPHANUM"); // keep this ALPHANUM for disable_count_query
2043 set_superglobals($key, $_REQUEST[$key]);
2045 elseif (str_end($key, "_ORDER_BY")) {
2046 clean_string($_REQUEST[$key], "SQL_COLUMN_LIST");
2047 set_superglobals($key, $_REQUEST[$key]);
2055 // Returns TRUE if $str begins with $begin
2056 function str_begin($str, $begin) {
2057 return (substr($str, 0, strlen($begin)) == $begin);
2060 // Returns TRUE if $str ends with $end
2061 function str_end($str, $end) {
2062 return (substr($str, strlen($str) - strlen($end)) == $end);
2065 function securexss($value) {
2066 if(is_array($value)){
2068 foreach($value as $key=>$val){
2069 $new[$key] = securexss($val);
2073 static $xss_cleanup= array(""" => "&", '"' =>'"', "'" => ''' , '<' =>'<' , '>'=>'>');
2074 $value = preg_replace(array('/javascript:/i', '/\0/'), array('java script:', ''), $value);
2075 $value = preg_replace('/javascript:/i', 'java script:', $value);
2076 return str_replace(array_keys($xss_cleanup), array_values($xss_cleanup), $value);
2079 function securexsskey($value, $die=true){
2080 global $sugar_config;
2082 preg_match('/[\'"<>]/', $value, $matches);
2083 if(!empty($matches)){
2085 die("Bad data passed in; <a href=\"{$sugar_config['site_url']}\">Return to Home</a>");
2087 unset($_REQUEST[$value]);
2088 unset($_POST[$value]);
2089 unset($_GET[$value]);
2094 function preprocess_param($value){
2095 if(is_string($value)){
2096 if(get_magic_quotes_gpc() == 1){
2097 $value = stripslashes($value);
2100 $value = securexss($value);
2106 function cleanup_slashes($value)
2108 if(is_string($value)) return stripslashes($value);
2113 function set_register_value($category, $name, $value){
2114 return sugar_cache_put("{$category}:{$name}", $value);
2117 function get_register_value($category,$name){
2118 return sugar_cache_retrieve("{$category}:{$name}");
2121 function clear_register_value($category,$name){
2122 return sugar_cache_clear("{$category}:{$name}");
2124 // this function cleans id's when being imported
2125 function convert_id($string)
2127 return preg_replace_callback( '|[^A-Za-z0-9\-]|',
2129 // single quotes are essential here,
2130 // or alternative escape all $ as \$
2132 'return ord($matches[0]);'
2137 * @deprecated use SugarTheme::getImage()
2139 function get_image($image,$other_attributes,$width="",$height="",$ext='.gif',$alt="")
2141 return SugarThemeRegistry::current()->getImage(basename($image), $other_attributes, empty($width) ? null : $width, empty($height) ? null : $height, $ext, $alt );
2144 * @deprecated use SugarTheme::getImageURL()
2146 function getImagePath($image_name)
2148 return SugarThemeRegistry::current()->getImageURL($image_name);
2151 function getWebPath($relative_path){
2152 //if it has a :// then it isn't a relative path
2153 if(substr_count($relative_path, '://') > 0) return $relative_path;
2154 if(defined('TEMPLATE_URL'))$relative_path = SugarTemplateUtilities::getWebPath($relative_path);
2155 return $relative_path;
2158 function getVersionedPath($path, $additional_attrs='')
2160 if(empty($GLOBALS['sugar_config']['js_custom_version'])) $GLOBALS['sugar_config']['js_custom_version'] = 1;
2161 $js_version_key = isset($GLOBALS['js_version_key'])?$GLOBALS['js_version_key']:'';
2162 if(inDeveloperMode()) {
2164 if(empty($rand)) $rand = mt_rand();
2169 if(is_array($additional_attrs)) {
2170 $additional_attrs = join("|",$additional_attrs);
2172 // cutting 2 last chars here because since md5 is 32 chars, it's always ==
2173 $str = substr(base64_encode(md5("$js_version_key|{$GLOBALS['sugar_config']['js_custom_version']}|$dev|$additional_attrs", true)), 0, -2);
2174 // remove / - it confuses some parsers
2175 $str = strtr($str, '/+', '-_');
2176 if(empty($path)) return $str;
2178 return $path . "?v=$str";
2181 function getVersionedScript($path, $additional_attrs='')
2183 return '<script type="text/javascript" src="'.getVersionedPath($path, $additional_attrs).'"></script>';
2186 function getJSPath($relative_path, $additional_attrs='')
2188 if(defined('TEMPLATE_URL'))$relative_path = SugarTemplateUtilities::getWebPath($relative_path);
2189 return getVersionedPath($relative_path).(!empty($additional_attrs)?"&$additional_attrs":"");
2192 function getSWFPath($relative_path, $additional_params=''){
2193 $path = $relative_path;
2194 if (!empty($additional_params)){
2195 $path .= '?' . $additional_params;
2197 if (defined('TEMPLATE_URL')){
2198 $path = TEMPLATE_URL . '/' . $path;
2207 function getSQLDate($date_str)
2209 if (preg_match('/^(\d{1,2})-(\d{1,2})-(\d{4})$/',$date_str,$match))
2211 if ( strlen($match[2]) == 1)
2213 $match[2] = "0".$match[2];
2215 if ( strlen($match[1]) == 1)
2217 $match[1] = "0".$match[1];
2219 return "{$match[3]}-{$match[1]}-{$match[2]}";
2221 else if (preg_match('/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/',$date_str,$match))
2223 if ( strlen($match[2]) == 1)
2225 $match[2] = "0".$match[2];
2227 if ( strlen($match[1]) == 1)
2229 $match[1] = "0".$match[1];
2231 return "{$match[3]}-{$match[1]}-{$match[2]}";
2239 function clone_history(&$db, $from_id,$to_id, $to_type)
2244 require_once('include/upload_file.php');
2245 $tables = array('calls'=>'Call', 'meetings'=>'Meeting', 'notes'=>'Note', 'tasks'=>'Task');
2247 $location=array('Email'=>"modules/Emails/Email.php",
2248 'Call'=>"modules/Calls/Call.php",
2249 'Meeting'=>"modules/Meetings/Meeting.php",
2250 'Note'=>"modules/Notes/Note.php",
2251 'Tasks'=>"modules/Tasks/Task.php",
2255 foreach($tables as $table=>$bean_class)
2258 if (!class_exists($bean_class))
2260 require_once($location[$bean_class]);
2263 $bProcessingNotes=false;
2264 if ($table=='notes')
2266 $bProcessingNotes=true;
2268 $query = "SELECT id FROM $table WHERE parent_id='$from_id'";
2269 $results = $db->query($query);
2270 while($row = $db->fetchByAssoc($results))
2272 //retrieve existing record.
2273 $bean= new $bean_class();
2274 $bean->retrieve($row['id']);
2275 //process for new instance.
2276 if ($bProcessingNotes)
2278 $old_note_id=$row['id'];
2279 $old_filename=$bean->filename;
2282 $bean->parent_id=$to_id;
2283 $bean->parent_type=$to_type;
2284 if ($to_type=='Contacts' and in_array('contact_id',$bean->column_fields))
2286 $bean->contact_id=$to_id;
2288 $bean->update_date_modified = false;
2289 $bean->update_modified_by = false;
2290 if(isset($bean->date_modified))
2291 $bean->date_modified = $timedate->to_db($bean->date_modified);
2292 if(isset($bean->date_entered))
2293 $bean->date_entered = $timedate->to_db($bean->date_entered);
2295 $new_id=$bean->save();
2297 //duplicate the file now. for notes.
2298 if ($bProcessingNotes && !empty($old_filename))
2300 UploadFile::duplicate_file($old_note_id,$new_id,$old_filename);
2302 //reset the values needed for attachment duplication.
2309 function values_to_keys($array)
2311 $new_array = array();
2312 if(!is_array($array))
2316 foreach($array as $arr){
2317 $new_array[$arr] = $arr;
2322 function clone_relationship(&$db, $tables = array(), $from_column, $from_id, $to_id)
2324 foreach($tables as $table)
2327 if ($table == 'emails_beans') {
2328 $query = "SELECT * FROM $table WHERE $from_column='$from_id' and bean_module='Leads'";
2330 $query = "SELECT * FROM $table WHERE $from_column='$from_id'";
2332 $results = $db->query($query);
2333 while($row = $db->fetchByAssoc($results))
2335 $query = "INSERT INTO $table ";
2338 $row[$from_column] = $to_id;
2339 $row['id'] = create_guid();
2340 if ($table=='emails_beans') {
2341 $row['bean_module'] =='Contacts';
2344 foreach($row as $name=>$value)
2350 $values .= "'$value'";
2353 $names .= ', '. $name;
2354 $values .= ", '$value'";
2357 $query .= "($names) VALUES ($values)";
2363 function get_unlinked_email_query($type, $bean) {
2364 global $current_user;
2366 $return_array['select']='SELECT emails.id ';
2367 $return_array['from']='FROM emails ';
2368 $return_array['where']="";
2369 $return_array['join'] = " JOIN (select DISTINCT email_id from emails_email_addr_rel eear
2371 join email_addr_bean_rel eabr on eabr.bean_id ='$bean->id' and eabr.bean_module = '$bean->module_dir' and
2372 eabr.email_address_id = eear.email_address_id and eabr.deleted=0
2373 where eear.deleted=0 and eear.email_id not in
2374 (select eb.email_id from emails_beans eb where eb.bean_module ='$bean->module_dir' and eb.bean_id = '$bean->id')
2375 ) derivedemails on derivedemails.email_id = emails.id";
2376 $return_array['join_tables'][0] = '';
2378 if (isset($type) and !empty($type['return_as_array'])) {
2379 return $return_array;
2382 return $return_array['select'] . $return_array['from'] . $return_array['where'] . $return_array['join'] ;
2385 function get_emails_by_assign_or_link($params)
2387 $relation = $params['link'];
2388 $bean = $GLOBALS['app']->controller->bean;
2389 if(empty($bean->$relation)) {
2390 $bean->load_relationship($relation);
2392 if(empty($bean->$relation)) {
2393 $GLOBALS['log']->error("Bad relation '$relation' for bean '{$bean->object_name}' id '{$bean->id}'");
2396 $rel_module = $bean->$relation->getRelatedModuleName();
2397 $rel_join = $bean->$relation->getJoin(array(
2398 'join_table_alias' => 'link_bean',
2399 'join_table_link_alias' => 'linkt',
2401 $rel_join = str_replace("{$bean->table_name}.id", "'{$bean->id}'", $rel_join);
2402 $return_array['select']='SELECT DISTINCT emails.id ';
2403 $return_array['from'] = "FROM emails ";
2404 $return_array['join'] = " INNER JOIN (".
2405 // directly assigned emails
2406 "select eb.email_id, 'direct' source FROM emails_beans eb where eb.bean_module = '{$bean->module_dir}' AND eb.bean_id = '{$bean->id}' AND eb.deleted=0 ".
2408 // Assigned to contacts
2409 "select DISTINCT eb.email_id, 'contact' source FROM emails_beans eb
2410 $rel_join AND link_bean.id = eb.bean_id
2411 where eb.bean_module = '$rel_module' AND eb.deleted=0".
2413 // Related by directly by email
2414 "select DISTINCT eear.email_id, 'relate' source from emails_email_addr_rel eear INNER JOIN email_addr_bean_rel eabr
2415 ON eabr.bean_id ='{$bean->id}' AND eabr.bean_module = '{$bean->module_dir}' AND
2416 eabr.email_address_id = eear.email_address_id and eabr.deleted=0 where eear.deleted=0".
2418 // Related by email to linked contact
2419 "select DISTINCT eear.email_id, 'relate_contact' source FROM emails_email_addr_rel eear INNER JOIN email_addr_bean_rel eabr
2420 ON eabr.email_address_id=eear.email_address_id AND eabr.bean_module = '$rel_module' AND eabr.deleted=0
2421 $rel_join AND link_bean.id = eabr.bean_id
2422 where eear.deleted=0".
2423 ") email_ids ON emails.id=email_ids.email_id ";
2424 $return_array['where']=" WHERE emails.deleted=0 ";
2426 //$return_array['join'] = '';
2427 $return_array['join_tables'][0] = '';
2429 if($bean->object_name == "Case" && !empty($bean->case_number)) {
2430 $where = str_replace("%1", $bean->case_number, $bean->getEmailSubjectMacro());
2431 $return_array["where"] .= "\n AND (email_ids.source = 'direct' OR emails.name LIKE '%$where%')";
2434 return $return_array;
2438 * Check to see if the number is empty or non-zero
2442 function number_empty($value)
2444 return empty($value) && $value != '0';
2447 function get_bean_select_array($add_blank=true, $bean_name, $display_columns, $where='', $order_by='', $blank_is_none=false)
2450 require_once($beanFiles[$bean_name]);
2451 $focus = new $bean_name();
2452 $user_array = array();
2454 $key = ($bean_name == 'EmailTemplate') ? $bean_name : $bean_name . $display_columns. $where . $order_by;
2455 $user_array = get_register_value('select_array', $key );
2459 $db = DBManagerFactory::getInstance();
2461 $temp_result = Array();
2462 $query = "SELECT {$focus->table_name}.id, {$display_columns} as display from {$focus->table_name} ";
2466 $query .= $where." AND ";
2469 $query .= " {$focus->table_name}.deleted=0";
2471 if ( $order_by != '')
2473 $query .= " order by {$focus->table_name}.{$order_by}";
2476 $GLOBALS['log']->debug("get_user_array query: $query");
2477 $result = $db->query($query, true, "Error filling in user array: ");
2479 if ($add_blank==true){
2480 // Add in a blank row
2481 if($blank_is_none == true) { // set 'blank row' to "--None--"
2482 global $app_strings;
2483 $temp_result[''] = $app_strings['LBL_NONE'];
2485 $temp_result[''] = '';
2489 // Get the id and the name.
2490 while($row = $db->fetchByAssoc($result))
2492 $temp_result[$row['id']] = $row['display'];
2495 $user_array = $temp_result;
2496 set_register_value('select_array', $key ,$temp_result);
2505 * @param unknown_type $listArray
2507 // function parse_list_modules
2508 // searches a list for items in a user's allowed tabs and returns an array that removes unallowed tabs from list
2509 function parse_list_modules(&$listArray)
2511 global $modListHeader;
2512 $returnArray = array();
2514 foreach($listArray as $optionName => $optionVal)
2516 if(array_key_exists($optionName, $modListHeader))
2518 $returnArray[$optionName] = $optionVal;
2521 // special case for projects
2522 if(array_key_exists('Project', $modListHeader))
2524 $returnArray['ProjectTask'] = $listArray['ProjectTask'];
2527 $acldenied = ACLController::disabledModuleList($listArray,false);
2528 foreach($acldenied as $denied){
2529 unset($returnArray[$denied]);
2531 asort($returnArray);
2533 return $returnArray;
2536 function display_notice($msg = false){
2537 global $error_notice;
2538 //no error notice - lets just display the error to the user
2539 if(!isset($error_notice)){
2540 echo '<br>'.$msg . '<br>';
2542 $error_notice .= $msg . '<br>';
2546 /* checks if it is a number that at least has the plus at the beginning.
2548 function skype_formatted($number){
2549 //kbrill - BUG #15375
2550 if(isset($_REQUEST['action']) && $_REQUEST['action']=="Popup") {
2553 return substr($number, 0, 1) == '+' || substr($number, 0, 2) == '00' || substr($number, 0, 3) == '011';
2555 // return substr($number, 0, 1) == '+' || substr($number, 0, 2) == '00' || substr($number, 0, 2) == '011';
2558 function format_skype($number) {
2559 return preg_replace('/[^\+0-9]/','',$number);
2562 function insert_charset_header() {
2563 header('Content-Type: text/html; charset=UTF-8');
2566 function getCurrentURL()
2569 if(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on')
2574 $href.= "//".$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME'].'?'.$_SERVER['QUERY_STRING'];
2578 function javascript_escape($str) {
2581 for($i = 0; $i < strlen($str); $i++) {
2583 if(ord(substr($str, $i, 1))==10){
2585 }elseif(ord(substr($str, $i, 1))==13){
2589 $new_str .= $str{$i};
2593 $new_str = str_replace("'", "\\'", $new_str);
2598 function js_escape($str, $keep=true){
2599 $str = html_entity_decode(str_replace("\\", "", $str), ENT_QUOTES);
2602 $str = javascript_escape($str);
2605 $str = str_replace("'", " ", $str);
2606 $str = str_replace('"', " ", $str);
2611 //end function js_escape
2614 function br2nl($str) {
2615 $regex = "#<[^>]+br.+?>#i";
2616 preg_match_all($regex, $str, $matches);
2618 foreach($matches[0] as $match) {
2619 $str = str_replace($match, "<br>", $str);
2622 $brs = array('<br>','<br/>', '<br />');
2623 $str = str_replace("\r\n", "\n", $str); // make from windows-returns, *nix-returns
2624 $str = str_replace("\n\r", "\n", $str); // make from windows-returns, *nix-returns
2625 $str = str_replace("\r", "\n", $str); // make from windows-returns, *nix-returns
2626 $str = str_ireplace($brs, "\n", $str); // to retrieve it
2632 * Private helper function for displaying the contents of a given variable.
2633 * This function is only intended to be used for SugarCRM internal development.
2634 * The ppd stands for Pre Print Die.
2636 function _ppd($mixed)
2642 * Private helper function for displaying the contents of a given variable in
2643 * the Logger. This function is only intended to be used for SugarCRM internal
2644 * development. The pp stands for Pre Print.
2645 * @param $mixed var to print_r()
2646 * @param $die boolean end script flow
2647 * @param $displayStackTrace also show stack trace
2649 function _ppl($mixed, $die=false, $displayStackTrace=false, $loglevel="fatal") {
2650 if(!isset($GLOBALS['log']) || empty($GLOBALS['log'])) {
2652 $GLOBALS['log'] = LoggerManager :: getLogger('SugarCRM');
2656 $mix = print_r($mixed, true); // send print_r() output to $mix
2657 $stack = debug_backtrace();
2659 $GLOBALS['log']->$loglevel('------------------------------ _ppLogger() output start -----------------------------');
2660 $GLOBALS['log']->$loglevel($mix);
2661 if($displayStackTrace) {
2662 foreach($stack as $position) {
2663 $GLOBALS['log']->$loglevel($position['file']."({$position['line']})");
2667 $GLOBALS['log']->$loglevel('------------------------------ _ppLogger() output end -----------------------------');
2668 $GLOBALS['log']->$loglevel('------------------------------ _ppLogger() file: '.$stack[0]['file'].' line#: '.$stack[0]['line'].'-----------------------------');
2676 * private helper function to quickly show the major, direct, field attributes of a given bean.
2677 * The ppf stands for Pre[formatted] Print Focus [object]
2678 * @param object bean The focus bean
2680 function _ppf($bean, $die=false) {
2686 * Private helper function for displaying the contents of a given variable.
2687 * This function is only intended to be used for SugarCRM internal development.
2688 * The pp stands for Pre Print.
2690 function _pp($mixed)
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 pp stands for Pre Print.
2699 function _pstack_trace($mixed=NULL)
2704 * Private helper function for displaying the contents of a given variable.
2705 * This function is only intended to be used for SugarCRM internal development.
2706 * The pp stands for Pre Print Trace.
2708 function _ppt($mixed, $textOnly=false)
2713 * Private helper function for displaying the contents of a given variable.
2714 * This function is only intended to be used for SugarCRM internal development.
2715 * The pp stands for Pre Print Trace Die.
2717 function _pptd($mixed)
2722 * Private helper function for decoding javascript UTF8
2723 * This function is only intended to be used for SugarCRM internal development.
2725 function decodeJavascriptUTF8($str) {
2729 * Will check if a given PHP version string is supported (tested on this ver),
2730 * unsupported (results unknown), or invalid (something will break on this
2731 * ver). Do not pass in any pararameter to default to a check against the
2732 * current environment's PHP version.
2734 * @return 1 implies supported, 0 implies unsupported, -1 implies invalid
2736 function check_php_version($sys_php_version = '') {
2737 $sys_php_version = empty($sys_php_version) ? constant('PHP_VERSION') : $sys_php_version;
2738 // versions below $min_considered_php_version considered invalid by default,
2739 // versions equal to or above this ver will be considered depending
2740 // on the rules that follow
2741 $min_considered_php_version = '5.2.1';
2743 // only the supported versions,
2744 // should be mutually exclusive with $invalid_php_versions
2745 $supported_php_versions = array (
2746 '5.2.1', '5.2.2', '5.2.3', '5.2.4', '5.2.5', '5.2.6', '5.2.8', '5.3.0'
2749 // invalid versions above the $min_considered_php_version,
2750 // should be mutually exclusive with $supported_php_versions
2752 // SugarCRM prohibits install on PHP 5.2.7 on all platforms
2753 $invalid_php_versions = array('5.2.7');
2755 // default unsupported
2758 // versions below $min_considered_php_version are invalid
2759 if(1 == version_compare($sys_php_version, $min_considered_php_version, '<')) {
2763 // supported version check overrides default unsupported
2764 foreach($supported_php_versions as $ver) {
2765 if(1 == version_compare($sys_php_version, $ver, 'eq') || strpos($sys_php_version,$ver) !== false) {
2771 // invalid version check overrides default unsupported
2772 foreach($invalid_php_versions as $ver) {
2773 if(1 == version_compare($sys_php_version, $ver, 'eq') && strpos($sys_php_version,$ver) !== false) {
2779 //allow a redhat distro to install, regardless of version. We are assuming the redhat naming convention is followed
2780 //and the php version contains 'rh' characters
2781 if(strpos($sys_php_version, 'rh') !== false) {
2789 * Will check if a given IIS version string is supported (tested on this ver),
2790 * unsupported (results unknown), or invalid (something will break on this
2793 * @return 1 implies supported, 0 implies unsupported, -1 implies invalid
2795 function check_iis_version($sys_iis_version = '') {
2797 $server_software = $_SERVER["SERVER_SOFTWARE"];
2799 if(strpos($server_software,'Microsoft-IIS') !== false && preg_match_all("/^.*\/(\d+\.?\d*)$/", $server_software, $out))
2800 $iis_version = $out[1][0];
2802 $sys_iis_version = empty($sys_iis_version) ? $iis_version : $sys_iis_version;
2804 // versions below $min_considered_iis_version considered invalid by default,
2805 // versions equal to or above this ver will be considered depending
2806 // on the rules that follow
2807 $min_considered_iis_version = '6.0';
2809 // only the supported versions,
2810 // should be mutually exclusive with $invalid_iis_versions
2811 $supported_iis_versions = array ('6.0', '7.0',);
2812 $unsupported_iis_versions = array();
2813 $invalid_iis_versions = array('5.0',);
2815 // default unsupported
2818 // versions below $min_considered_iis_version are invalid
2819 if(1 == version_compare($sys_iis_version, $min_considered_iis_version, '<')) {
2823 // supported version check overrides default unsupported
2824 foreach($supported_iis_versions as $ver) {
2825 if(1 == version_compare($sys_iis_version, $ver, 'eq') || strpos($sys_iis_version,$ver) !== false) {
2831 // unsupported version check overrides default unsupported
2832 foreach($unsupported_iis_versions as $ver) {
2833 if(1 == version_compare($sys_iis_version, $ver, 'eq') && strpos($sys_iis_version,$ver) !== false) {
2839 // invalid version check overrides default unsupported
2840 foreach($invalid_iis_versions as $ver) {
2841 if(1 == version_compare($sys_iis_version, $ver, 'eq') && strpos($sys_iis_version,$ver) !== false) {
2850 function pre_login_check(){
2851 global $action, $login_error;
2852 if(!empty($action)&& $action == 'Login'){
2854 if(!empty($login_error)){
2855 $login_error = htmlentities($login_error);
2856 $login_error = str_replace(array("<pre>","</pre>","\r\n", "\n"), "<br>", $login_error);
2857 $_SESSION['login_error'] = $login_error;
2859 function set_focus() {}
2860 if(document.getElementById("post_error")) {
2861 document.getElementById("post_error").innerHTML="'. $login_error. '";
2862 document.getElementById("cant_login").value=1;
2863 document.getElementById("login_button").disabled = true;
2864 document.getElementById("user_name").disabled = true;
2865 //document.getElementById("user_password").disabled = true;
2874 function sugar_cleanup($exit = false) {
2875 static $called = false;
2878 set_include_path(realpath(dirname(__FILE__) . '/..') . PATH_SEPARATOR . get_include_path());
2879 chdir(realpath(dirname(__FILE__) . '/..'));
2880 global $sugar_config;
2881 require_once('include/utils/LogicHook.php');
2882 LogicHook::initialize();
2883 $GLOBALS['logic_hook']->call_custom_logic('', 'server_round_trip');
2885 //added this check to avoid errors during install.
2886 if (empty($sugar_config['dbconfig'])) {
2887 if ($exit) exit; else return;
2890 if (!class_exists('Tracker', true)) {
2891 require_once 'modules/Trackers/Tracker.php';
2894 // Now write the cached tracker_queries
2895 if(!empty($GLOBALS['savePreferencesToDB']) && $GLOBALS['savePreferencesToDB']) {
2896 if ( isset($GLOBALS['current_user']) && $GLOBALS['current_user'] instanceOf User )
2897 $GLOBALS['current_user']->savePreferencesToDB();
2900 //check to see if this is not an `ajax call AND the user preference error flag is set
2902 (isset($_SESSION['USER_PREFRENCE_ERRORS']) && $_SESSION['USER_PREFRENCE_ERRORS'])
2903 && ($_REQUEST['action']!='modulelistmenu' && $_REQUEST['action']!='DynamicAction')
2904 && ($_REQUEST['action']!='favorites' && $_REQUEST['action']!='DynamicAction')
2905 && (empty($_REQUEST['to_pdf']) || !$_REQUEST['to_pdf'] )
2906 && (empty($_REQUEST['sugar_body_only']) || !$_REQUEST['sugar_body_only'] )
2909 global $app_strings;
2910 //this is not an ajax call and the user preference error flag is set, so reset the flag and print js to flash message
2911 $err_mess = $app_strings['ERROR_USER_PREFS'];
2912 $_SESSION['USER_PREFRENCE_ERRORS'] = false;
2915 ajaxStatus.flashStatus('$err_mess',7000);
2921 if(class_exists('DBManagerFactory')) {
2922 $db = DBManagerFactory::getInstance();
2930 register_shutdown_function('sugar_cleanup');
2934 check_logic_hook - checks to see if your custom logic is in the logic file
2935 if not, it will add it. If the file isn't built yet, it will create the file
2938 function check_logic_hook_file($module_name, $event, $action_array){
2939 require_once('include/utils/logic_utils.php');
2942 if(file_exists("custom/modules/$module_name/logic_hooks.php")){
2944 $hook_array = get_hook_array($module_name);
2946 if(check_existing_element($hook_array, $event, $action_array)==true){
2947 //the hook at hand is present, so do nothing
2952 if(!empty($hook_array[$event]))
2954 $logic_count = count($hook_array[$event]);
2957 if($action_array[0]==""){
2958 $action_array[0] = $logic_count + 1;
2960 $hook_array[$event][] = $action_array;
2963 //end if the file exists already
2966 if($action_array[0]==""){
2967 $action_array[0] = 1;
2969 $hook_array = array();
2970 $hook_array[$event][] = $action_array;
2971 //end if else file exists already
2973 if($add_logic == true){
2975 //reorder array by element[0]
2976 //$hook_array = reorder_array($hook_array, $event);
2977 //!!!Finish this above TODO
2979 $new_contents = replace_or_add_logic_type($hook_array);
2980 write_logic_file($module_name, $new_contents);
2982 //end if add_element is true
2985 //end function check_logic_hook_file
2988 function remove_logic_hook($module_name, $event, $action_array) {
2989 require_once('include/utils/logic_utils.php');
2992 if(file_exists("custom/modules/".$module_name."/logic_hooks.php")){
2993 // The file exists, let's make sure the hook is there
2994 $hook_array = get_hook_array($module_name);
2996 if(check_existing_element($hook_array, $event, $action_array)==true){
2997 // The hook is there, time to take it out.
2999 foreach ( $hook_array[$event] as $i => $hook ) {
3000 // We don't do a full comparison below just in case the filename changes
3001 if ( $hook[0] == $action_array[0]
3002 && $hook[1] == $action_array[1]
3003 && $hook[3] == $action_array[3]
3004 && $hook[4] == $action_array[4] ) {
3005 unset($hook_array[$event][$i]);
3009 $new_contents = replace_or_add_logic_type($hook_array);
3010 write_logic_file($module_name, $new_contents);
3016 function display_stack_trace($textOnly=false){
3018 $stack = debug_backtrace();
3020 echo "\n\n display_stack_trace caller, file: " . $stack[0]['file']. ' line#: ' .$stack[0]['line'];
3028 foreach($stack as $item) {
3034 if(isset($item['file']))
3035 $file = $item['file'];
3036 if(isset($item['class']))
3037 $class = $item['class'];
3038 if(isset($item['line']))
3039 $line = $item['line'];
3040 if(isset($item['function']))
3041 $function = $item['function'];
3045 $out .= '<font color="black"><b>';
3051 $out .= '</b></font><font color="blue">';
3054 $out .= "[L:{$line}]";
3057 $out .= '</font><font color="red">';
3060 $out .= "({$class}:{$function})";
3063 $out .= '</font><br>';
3075 function StackTraceErrorHandler($errno, $errstr, $errfile,$errline, $errcontext) {
3076 $error_msg = " $errstr occurred in <b>$errfile</b> on line $errline [" . date("Y-m-d H:i:s") . ']';
3077 $halt_script = true;
3079 case 2048: return; //depricated we have lots of these ignore them
3082 if ( error_reporting() & E_NOTICE ) {
3083 $halt_script = false;
3089 case E_USER_WARNING:
3090 case E_COMPILE_WARNING:
3091 case E_CORE_WARNING:
3094 $halt_script = false;
3099 case E_COMPILE_ERROR:
3103 $type = "Fatal Error";
3108 $type = "Parse Error";
3112 //don't know what it is might not be so bad
3113 $halt_script = false;
3114 $type = "Unknown Error ($errno)";
3117 $error_msg = '<b>'.$type.'</b>:' . $error_msg;
3119 display_stack_trace();
3129 if(isset($sugar_config['stack_trace_errors']) && $sugar_config['stack_trace_errors']){
3131 set_error_handler('StackTraceErrorHandler');
3133 function get_sub_cookies($name){
3135 if(isset($_COOKIE[$name])){
3136 $subs = explode('#', $_COOKIE[$name]);
3137 foreach($subs as $cookie){
3138 if(!empty($cookie)){
3139 $cookie = explode('=', $cookie);
3141 $cookies[$cookie[0]] = $cookie[1];
3150 function mark_delete_components($sub_object_array, $run_second_level=false, $sub_sub_array=""){
3152 if(!empty($sub_object_array)){
3154 foreach($sub_object_array as $sub_object){
3156 //run_second level is set to true if you need to remove sub-sub components
3157 if($run_second_level==true){
3159 mark_delete_components($sub_object->get_linked_beans($sub_sub_array['rel_field'],$sub_sub_array['rel_module']));
3161 //end if run_second_level is true
3163 $sub_object->mark_deleted($sub_object->id);
3164 //end foreach sub component
3166 //end if this is not empty
3169 //end function mark_delete_components
3173 * For translating the php.ini memory values into bytes. e.g. input value of '8M' will return 8388608.
3175 function return_bytes($val)
3178 $last = strtolower($val{strlen($val)-1});
3182 // The 'G' modifier is available since PHP 5.1.0
3195 * Adds the href HTML tags around any URL in the $string
3197 function url2html($string) {
3199 $return_string = preg_replace('/(\w+:\/\/)(\S+)/', ' <a href="\\1\\2" target="_new" style="font-weight: normal;">\\1\\2</a>', $string);
3200 return $return_string;
3202 // End customization by Julian
3205 * tries to determine whether the Host machine is a Windows machine
3207 function is_windows() {
3208 static $is_windows = null;
3209 if (!isset($is_windows)) {
3210 $is_windows = strtoupper(substr(PHP_OS, 0, 3)) == 'WIN';
3216 * equivalent for windows filesystem for PHP's is_writable()
3217 * @param string file Full path to the file/dir
3218 * @return bool true if writable
3220 function is_writable_windows($file) {
3221 if($file{strlen($file)-1}=='/') {
3222 return is_writable_windows($file.uniqid(mt_rand()).'.tmp');
3225 // the assumption here is that Windows has an inherited permissions scheme
3226 // any file that is a descendant of an unwritable directory will inherit
3227 // that property and will trigger a failure below.
3232 $file = str_replace("/", '\\', $file);
3234 if(file_exists($file)) {
3235 if (!($f = @sugar_fopen($file, 'r+')))
3241 if(!($f = @sugar_fopen($file, 'w')))
3250 * best guesses Timezone based on webserver's TZ settings
3252 function lookupTimezone($userOffset = 0)
3254 return TimeDate::guessTimezone($userOffset);
3257 function convert_module_to_singular($module_array){
3260 foreach($module_array as $key => $value){
3261 if(!empty($beanList[$value])) $module_array[$key] = $beanList[$value];
3263 if($value=="Cases") {
3264 $module_array[$key] = "Case";
3266 if($key=="projecttask"){
3267 $module_array['ProjectTask'] = "Project Task";
3268 unset($module_array[$key]);
3272 return $module_array;
3274 //end function convert_module_to_singular
3278 * Given the bean_name which may be plural or singular return the singular
3279 * bean_name. This is important when you need to include files.
3281 function get_singular_bean_name($bean_name){
3282 global $beanFiles, $beanList;
3283 if(array_key_exists($bean_name, $beanList)){
3284 return $beanList[$bean_name];
3292 * Given the potential module name (singular name, renamed module name)
3293 * Return the real internal module name.
3295 function get_module_from_singular($singular) {
3297 // find the internal module name for a singular name
3298 if (isset($GLOBALS['app_list_strings']['moduleListSingular'])) {
3300 $singular_modules = $GLOBALS['app_list_strings']['moduleListSingular'];
3302 foreach ($singular_modules as $mod_name=>$sin_name) {
3303 if ($singular == $sin_name and $mod_name != $sin_name) {
3309 // find the internal module name for a renamed module
3310 if (isset($GLOBALS['app_list_strings']['moduleList'])) {
3312 $moduleList = $GLOBALS['app_list_strings']['moduleList'];
3314 foreach ($moduleList as $mod_name=>$name) {
3315 if ($singular == $name and $mod_name != $name) {
3321 // if it's not a singular name, nor a renamed name, return the original value
3325 function get_label($label_tag, $temp_module_strings){
3326 global $app_strings;
3327 if(!empty($temp_module_strings[$label_tag])){
3329 $label_name = $temp_module_strings[$label_tag];
3331 if(!empty($app_strings[$label_tag])){
3332 $label_name = $app_strings[$label_tag];
3334 $label_name = $label_tag;
3339 //end function get_label
3343 function search_filter_rel_info(& $focus, $tar_rel_module, $relationship_name){
3345 $rel_list = array();
3347 foreach($focus->relationship_fields as $rel_key => $rel_value){
3348 if($rel_value == $relationship_name){
3349 $temp_bean = get_module_info($tar_rel_module);
3350 // echo $focus->$rel_key;
3351 $temp_bean->retrieve($focus->$rel_key);
3352 if($temp_bean->id!=""){
3354 $rel_list[] = $temp_bean;
3360 foreach($focus->field_defs as $field_name => $field_def){
3361 //Check if the relationship_name matches a "relate" field
3362 if(!empty($field_def['type']) && $field_def['type'] == 'relate'
3363 && !empty($field_def['id_name']) && !empty($focus->field_defs[$field_def['id_name']])
3364 && !empty($focus->field_defs[$field_def['id_name']]['relationship'])
3365 && $focus->field_defs[$field_def['id_name']]['relationship'] == $relationship_name)
3367 $temp_bean = get_module_info($tar_rel_module);
3368 // echo $focus->$field_def['id_name'];
3369 $temp_bean->retrieve($focus->$field_def['id_name']);
3370 if($temp_bean->id!=""){
3372 $rel_list[] = $temp_bean;
3375 //Check if the relationship_name matches a "link" in a relate field
3376 } else if(!empty($rel_value['link']) && !empty($rel_value['id_name']) && $rel_value['link'] == $relationship_name){
3377 $temp_bean = get_module_info($tar_rel_module);
3378 // echo $focus->$rel_value['id_name'];
3379 $temp_bean->retrieve($focus->$rel_value['id_name']);
3380 if($temp_bean->id!=""){
3382 $rel_list[] = $temp_bean;
3388 // special case for unlisted parent-type relationships
3389 if( !empty($focus->parent_type) && $focus->parent_type == $tar_rel_module && !empty($focus->parent_id)) {
3390 $temp_bean = get_module_info($tar_rel_module);
3391 $temp_bean->retrieve($focus->parent_id);
3392 if($temp_bean->id!=""){
3393 $rel_list[] = $temp_bean;
3400 //end function search_filter_rel_info
3403 function get_module_info($module_name){
3407 //Get dictionary and focus data for module
3408 $vardef_name = $beanList[$module_name];
3410 if($vardef_name=="aCase"){
3411 $class_name = "Case";
3413 $class_name = $vardef_name;
3416 if(!file_exists('modules/'. $module_name . '/'.$class_name.'.php')){
3420 include_once('modules/'. $module_name . '/'.$class_name.'.php');
3422 $module_bean = new $vardef_name();
3423 return $module_bean;
3424 //end function get_module_table
3428 * In order to have one place to obtain the proper object name. aCase for example causes issues throughout the application.
3430 * @param string $moduleName
3432 function get_valid_bean_name($module_name){
3435 $vardef_name = $beanList[$module_name];
3436 if($vardef_name=="aCase"){
3437 $bean_name = "Case";
3439 $bean_name = $vardef_name;
3446 function checkAuthUserStatus(){
3453 * This function returns an array of phpinfo() results that can be parsed and
3454 * used to figure out what version we run, what modules are compiled in, etc.
3455 * @param $level int info level constant (1,2,4,8...64);
3456 * @return $returnInfo array array of info about the PHP environment
3457 * @author original by "code at adspeed dot com" Fron php.net
3458 * @author customized for Sugar by Chris N.
3460 function getPhpInfo($level=-1) {
3461 /** Name (constant) Value Description
3462 INFO_GENERAL 1 The configuration line, php.ini location, build date, Web Server, System and more.
3463 INFO_CREDITS 2 PHP Credits. See also phpcredits().
3464 INFO_CONFIGURATION 4 Current Local and Master values for PHP directives. See also ini_get().
3465 INFO_MODULES 8 Loaded modules and their respective settings. See also get_loaded_extensions().
3466 INFO_ENVIRONMENT 16 Environment Variable information that's also available in $_ENV.
3467 INFO_VARIABLES 32 Shows all predefined variables from EGPCS (Environment, GET, POST, Cookie, Server).
3468 INFO_LICENSE 64 PHP License information. See also the license FAQ.
3469 INFO_ALL -1 Shows all of the above. This is the default value.
3473 $phpinfo = ob_get_contents();
3476 $phpinfo = strip_tags($phpinfo,'<h1><h2><th><td>');
3477 $phpinfo = preg_replace('/<th[^>]*>([^<]+)<\/th>/',"<info>\\1</info>",$phpinfo);
3478 $phpinfo = preg_replace('/<td[^>]*>([^<]+)<\/td>/',"<info>\\1</info>",$phpinfo);
3479 $parsedInfo = preg_split('/(<h.?>[^<]+<\/h.>)/', $phpinfo, -1, PREG_SPLIT_DELIM_CAPTURE);
3482 $returnInfo = array();
3484 if(preg_match('/<h1 class\=\"p\">PHP Version ([^<]+)<\/h1>/', $phpinfo, $version)) {
3485 $returnInfo['PHP Version'] = $version[1];
3489 for ($i=1; $i<count($parsedInfo); $i++) {
3490 if (preg_match('/<h.>([^<]+)<\/h.>/', $parsedInfo[$i], $match)) {
3491 $vName = trim($match[1]);
3492 $parsedInfo2 = explode("\n",$parsedInfo[$i+1]);
3494 foreach ($parsedInfo2 AS $vOne) {
3495 $vPat = '<info>([^<]+)<\/info>';
3496 $vPat3 = "/$vPat\s*$vPat\s*$vPat/";
3497 $vPat2 = "/$vPat\s*$vPat/";
3499 if (preg_match($vPat3,$vOne,$match)) { // 3cols
3500 $returnInfo[$vName][trim($match[1])] = array(trim($match[2]),trim($match[3]));
3501 } elseif (preg_match($vPat2,$vOne,$match)) { // 2cols
3502 $returnInfo[$vName][trim($match[1])] = trim($match[2]);
3514 * This function will take a string that has tokens like {0}, {1} and will replace
3515 * those tokens with the args provided
3516 * @param $format string to format
3517 * @param $args args to replace
3518 * @return $result a formatted string
3520 function string_format($format, $args){
3524 * If args array has only one argument, and it's empty, so empty single quotes are used '' . That's because
3525 * IN () fails and IN ('') works.
3527 if (count($args) == 1)
3530 $singleArgument = current($args);
3531 if (empty($singleArgument))
3533 return str_replace("{0}", "''", $result);
3538 for($i = 0; $i < count($args); $i++){
3539 $result = str_replace('{'.$i.'}', $args[$i], $result);
3545 * Generate a string for displaying a unique identifier that is composed
3546 * of a system_id and number. This is use to allow us to generate quote
3547 * numbers using a DB auto-increment key from offline clients and still
3548 * have the number be unique (since it is modified by the system_id.
3550 * @param $num of bean
3551 * @param $system_id from system
3552 * @return $result a formatted string
3554 function format_number_display($num, $system_id){
3555 global $sugar_config;
3556 if(isset($num) && !empty($num)){
3557 $num=unformat_number($num);
3558 if(isset($system_id) && $system_id == 1){
3559 return sprintf("%d", $num);
3562 return sprintf("%d-%d", $num, $system_id);
3566 function checkLoginUserStatus(){
3570 * This function will take a number and system_id and format
3571 * @param $url URL containing host to append port
3572 * @param $port the port number - if '' is passed, no change to url
3573 * @return $resulturl the new URL with the port appended to the host
3575 function appendPortToHost($url, $port)
3579 // if no port, don't change the url
3582 $split = explode("/", $url);
3583 //check if it starts with http, in case they didn't include that in url
3584 if(str_begin($url, 'http'))
3586 //third index ($split[2]) will be the host
3587 $split[2] .= ":".$port;
3589 else // otherwise assumed to start with host name
3591 //first index ($split[0]) will be the host
3592 $split[0] .= ":".$port;
3595 $resulturl = implode("/", $split);
3602 * Singleton to return JSON object
3603 * @return JSON object
3605 function getJSONobj() {
3606 static $json = null;
3608 require_once('include/JSON.php');
3609 $json = new JSON(JSON_LOOSE_TYPE);
3614 require_once('include/utils/db_utils.php');
3617 * Set default php.ini settings for entry points
3619 function setPhpIniSettings() {
3621 // Bug 37579 - Comment out force enabling zlib.output_compression, since it can cause problems on certain hosts
3623 if(function_exists('gzclose') && headers_sent() == false) {
3624 ini_set('zlib.output_compression', 1);
3628 //nsingh: breaks zip/unzip functionality. Commenting out 4/23/08
3630 /*if(function_exists('mb_strlen')) {
3631 ini_set('mbstring.func_overload', 7);
3632 ini_set('mbstring.internal_encoding', 'UTF-8');
3636 // http://us3.php.net/manual/en/ref.pcre.php#ini.pcre.backtrack-limit
3637 // starting with 5.2.0, backtrack_limit breaks JSON decoding
3638 $backtrack_limit = ini_get('pcre.backtrack_limit');
3639 if(!empty($backtrack_limit)) {
3640 ini_set('pcre.backtrack_limit', '-1');
3645 * Identical to sugarArrayMerge but with some speed improvements and used specifically to merge
3646 * language files. Language file merges do not need to account for null values so we can get some
3647 * performance increases by using this specialized function. Note this merge function does not properly
3648 * handle null values.
3654 function sugarLangArrayMerge($gimp, $dom)
3656 if(is_array($gimp) && is_array($dom))
3658 foreach($dom as $domKey => $domVal)
3660 if(isset($gimp[$domKey]))
3662 if(is_array($domVal))
3665 foreach ( $domVal as $domArrKey => $domArrVal )
3666 $tempArr[$domArrKey] = $domArrVal;
3667 foreach ( $gimp[$domKey] as $gimpArrKey => $gimpArrVal )
3668 if ( !isset($tempArr[$gimpArrKey]) )
3669 $tempArr[$gimpArrKey] = $gimpArrVal;
3670 $gimp[$domKey] = $tempArr;
3674 $gimp[$domKey] = $domVal;
3679 $gimp[$domKey] = $domVal;
3683 // if the passed value for gimp isn't an array, then return the $dom
3684 elseif(is_array($dom))
3692 * like array_merge() but will handle array elements that are themselves arrays;
3693 * PHP's version just overwrites the element with the new one.
3695 * @internal Note that this function deviates from the internal array_merge()
3696 * functions in that it does does not treat numeric keys differently
3697 * than string keys. Additionally, it deviates from
3698 * array_merge_recursive() by not creating an array when like values
3701 * @param array gimp the array whose values will be overloaded
3702 * @param array dom the array whose values will pwn the gimp's
3703 * @return array beaten gimp
3705 function sugarArrayMerge($gimp, $dom) {
3706 if(is_array($gimp) && is_array($dom)) {
3707 foreach($dom as $domKey => $domVal) {
3708 if(array_key_exists($domKey, $gimp)) {
3709 if(is_array($domVal)) {
3711 foreach ( $domVal as $domArrKey => $domArrVal )
3712 $tempArr[$domArrKey] = $domArrVal;
3713 foreach ( $gimp[$domKey] as $gimpArrKey => $gimpArrVal )
3714 if ( !array_key_exists($gimpArrKey, $tempArr) )
3715 $tempArr[$gimpArrKey] = $gimpArrVal;
3716 $gimp[$domKey] = $tempArr;
3718 $gimp[$domKey] = $domVal;
3721 $gimp[$domKey] = $domVal;
3725 // if the passed value for gimp isn't an array, then return the $dom
3726 elseif(is_array($dom))
3733 * Similiar to sugarArrayMerge except arrays of N depth are merged.
3735 * @param array gimp the array whose values will be overloaded
3736 * @param array dom the array whose values will pwn the gimp's
3737 * @return array beaten gimp
3739 function sugarArrayMergeRecursive($gimp, $dom) {
3740 if(is_array($gimp) && is_array($dom)) {
3741 foreach($dom as $domKey => $domVal) {
3742 if(array_key_exists($domKey, $gimp)) {
3743 if(is_array($domVal) && is_array($gimp[$domKey])) {
3744 $gimp[$domKey] = sugarArrayMergeRecursive($gimp[$domKey], $domVal);
3746 $gimp[$domKey] = $domVal;
3749 $gimp[$domKey] = $domVal;
3753 // if the passed value for gimp isn't an array, then return the $dom
3754 elseif(is_array($dom))
3761 * finds the correctly working versions of PHP-JSON
3762 * @return bool True if NOT found or WRONG version
3764 function returnPhpJsonStatus() {
3765 if(function_exists('json_encode')) {
3766 $phpInfo = getPhpInfo(8);
3767 return version_compare($phpInfo['json']['json version'], '1.1.1', '<');
3769 return true; // not found
3774 * getTrackerSubstring
3776 * Returns a [number]-char or less string for the Tracker to display in the header
3777 * based on the tracker_max_display_length setting in config.php. If not set,
3778 * or invalid length, then defaults to 15 for COM editions, 30 for others.
3780 * @param string name field for a given Object
3781 * @return string [number]-char formatted string if length of string exceeds the max allowed
3783 function getTrackerSubstring($name) {
3784 static $max_tracker_item_length;
3787 $name = html_entity_decode($name, ENT_QUOTES, 'UTF-8');
3788 $strlen = function_exists('mb_strlen') ? mb_strlen($name) : strlen($name);
3790 global $sugar_config;
3792 if(!isset($max_tracker_item_length)) {
3793 if(isset($sugar_config['tracker_max_display_length'])) {
3794 $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;
3796 $max_tracker_item_length = 15;
3800 if($strlen > $max_tracker_item_length) {
3801 $chopped = function_exists('mb_substr') ? mb_substr($name, 0, $max_tracker_item_length-3, "UTF-8") : substr($name, 0, $max_tracker_item_length-3);
3809 function generate_search_where ($field_list=array(),$values=array(),&$bean,$add_custom_fields=false,$module='') {
3810 $where_clauses= array();
3812 $table_name=$bean->object_name;
3813 foreach ($field_list[$module] as $field=>$parms) {
3814 if(isset($values[$field]) && $values[$field] != "") {
3816 if (!empty($parms['operator'])) {
3817 $operator=$parms['operator'];
3819 if (is_array($values[$field])) {
3822 foreach ($values[$field] as $key => $val) {
3823 if ($val != ' ' and $val != '') {
3824 if (!empty($field_value)) {
3827 $field_value .= "'".$GLOBALS['db']->quote($val)."'";
3831 $field_value=$GLOBALS['db']->quote($values[$field]);
3833 //set db_fields array.
3834 if (!isset($parms['db_field']) ) {
3835 $parms['db_field'] = array($field);
3837 if (isset($parms['my_items']) and $parms['my_items'] == true) {
3838 global $current_user;
3839 $field_value = $GLOBALS['db']->quote($current_user->id);
3845 if ($field_value != '') {
3847 foreach ($parms['db_field'] as $db_field) {
3848 if (strstr($db_field,'.')===false) {
3849 $db_field=$bean->table_name.".".$db_field;
3851 if ($GLOBALS['db']->supports('case_sensitive') && isset($parms['query_type']) && $parms['query_type']=='case_insensitive') {
3852 $db_field='upper('.$db_field.")";
3853 $field_value=strtoupper($field_value);
3857 if (!empty($where)) {
3860 switch (strtolower($operator)) {
3862 $where .= $db_field . " like '".$field_value.$like_char."'";
3865 $where .= $db_field . " in (".$field_value.')';
3868 $where .= $db_field . " = '".$field_value ."'";
3873 if (!empty($where)) {
3875 array_push($where_clauses, '( '.$where.' )');
3877 array_push($where_clauses, $where);
3882 if ($add_custom_fields) {
3883 require_once('modules/DynamicFields/DynamicField.php');
3884 $bean->setupCustomFields($module);
3885 $bean->custom_fields->setWhereClauses($where_clauses);
3887 return $where_clauses;
3890 function add_quotes($str) {
3895 * This function will rebuild the config file
3896 * @param $sugar_config
3897 * @param $sugar_version
3898 * @return bool true if successful
3900 function rebuildConfigFile($sugar_config, $sugar_version) {
3901 // add defaults to missing values of in-memory sugar_config
3902 $sugar_config = sugarArrayMerge(get_sugar_config_defaults(), $sugar_config );
3903 // need to override version with default no matter what
3904 $sugar_config['sugar_version'] = $sugar_version;
3906 ksort( $sugar_config );
3908 if( write_array_to_file( "sugar_config", $sugar_config, "config.php" ) ){
3917 * Loads clean configuration, not overridden by config_override.php
3921 function loadCleanConfig()
3923 $sugar_config = array();
3924 require 'config.php';
3925 return $sugar_config;
3929 * getJavascriptSiteURL
3930 * This function returns a URL for the client javascript calls to access
3931 * the site. It uses $_SERVER['HTTP_REFERER'] in the event that Proxy servers
3932 * are used to access the site. Thus, the hostname in the URL returned may
3933 * not always match that of $sugar_config['site_url']. Basically, the
3934 * assumption is that however the user accessed the website is how they
3935 * will continue to with subsequent javascript requests. If the variable
3936 * $_SERVER['HTTP_REFERER'] is not found then we default to old algorithm.
3937 * @return $site_url The url used to refer to the website
3939 function getJavascriptSiteURL() {
3940 global $sugar_config;
3941 if(!empty($_SERVER['HTTP_REFERER'])) {
3942 $url = parse_url($_SERVER['HTTP_REFERER']);
3943 $replacement_url = $url['scheme']."://".$url['host'];
3944 if(!empty($url['port']))
3945 $replacement_url .= ':'.$url['port'];
3946 $site_url = preg_replace('/^http[s]?\:\/\/[^\/]+/',$replacement_url,$sugar_config['site_url']);
3948 $site_url = preg_replace('/^http(s)?\:\/\/[^\/]+/',"http$1://".$_SERVER['HTTP_HOST'],$sugar_config['site_url']);
3949 if(!empty($_SERVER['SERVER_PORT']) &&$_SERVER['SERVER_PORT'] == '443') {
3950 $site_url = preg_replace('/^http\:/','https:',$site_url);
3953 $GLOBALS['log']->debug("getJavascriptSiteURL(), site_url=". $site_url);
3957 // works nicely with array_map() -- can be used to wrap single quotes around each element in an array
3958 function add_squotes($str) {
3959 return "'" . $str . "'";
3963 // recursive function to count the number of levels within an array
3964 function array_depth($array, $depth_count=-1, $depth_array=array()){
3966 if (is_array($array)){
3967 foreach ($array as $key => $value){
3968 $depth_array[] = array_depth($value, $depth_count);
3972 return $depth_count;
3974 foreach ($depth_array as $value){
3975 $depth_count = $value > $depth_count ? $value : $depth_count;
3977 return $depth_count;
3981 * Creates a new Group User
3982 * @param string $name Name of Group User
3983 * @return string GUID of new Group User
3985 function createGroupUser($name) {
3988 $group = new User();
3989 $group->user_name = $name;
3990 $group->last_name = $name;
3991 $group->is_group = 1;
3992 $group->deleted = 0;
3993 $group->status = 'Active'; // cn: bug 6711
3994 $group->setPreference('timezone', TimeDate::userTimezone());
4001 * Helper function to locate an icon file given only a name
4002 * Searches through the various paths for the file
4003 * @param string iconFileName The filename of the icon
4004 * @return string Relative pathname of the located icon, or '' if not found
4007 function _getIcon($iconFileName)
4010 $iconName = "icon_{$iconFileName}.gif";
4011 $iconFound = SugarThemeRegistry::current()->getImageURL($iconName,false);
4013 //First try un-ucfirst-ing the icon name
4014 if ( empty($iconFound) )
4015 $iconName = "icon_" . strtolower(substr($iconFileName,0,1)).substr($iconFileName,1) . ".gif";
4016 $iconFound = SugarThemeRegistry::current()->getImageURL($iconName,false);
4018 //Next try removing the icon prefix
4019 if ( empty($iconFound) )
4020 $iconName = "{$iconFileName}.gif";
4021 $iconFound = SugarThemeRegistry::current()->getImageURL($iconName,false);
4023 if ( empty($iconFound) )
4029 * Function to grab the correct icon image for Studio
4030 * @param string $iconFileName Name of the icon file
4031 * @param string $altfilename Name of a fallback icon file (displayed if the imagefilename doesn't exist)
4032 * @param string $width Width of image
4033 * @param string $height Height of image
4034 * @param string $align Alignment of image
4035 * @param string $alt Alt tag of image
4036 * @return string $string <img> tag with corresponding image
4039 function getStudioIcon($iconFileName='', $altFileName='', $width='48', $height='48', $align='baseline', $alt='' )
4041 global $app_strings, $theme;
4043 $iconName = _getIcon($iconFileName);
4044 if(empty($iconName)){
4045 $iconName = _getIcon($altFileName);
4046 if (empty($iconName))
4048 return $app_strings['LBL_NO_IMAGE'];
4051 return SugarThemeRegistry::current()->getImage($iconName, "align=\"$align\" border=\"0\"", $width, $height);
4055 * Function to grab the correct icon image for Dashlets Dialog
4056 * @param string $filename Location of the icon file
4057 * @param string $module Name of the module to fall back onto if file does not exist
4058 * @param string $width Width of image
4059 * @param string $height Height of image
4060 * @param string $align Alignment of image
4061 * @param string $alt Alt tag of image
4062 * @return string $string <img> tag with corresponding image
4065 function get_dashlets_dialog_icon($module='', $width='32', $height='32', $align='absmiddle',$alt=''){
4066 global $app_strings, $theme;
4067 $iconName = _getIcon($module . "_32");
4068 if (empty($iconName))
4070 $iconName = _getIcon($module);
4072 if(empty($iconName)){
4073 return $app_strings['LBL_NO_IMAGE'];
4075 return SugarThemeRegistry::current()->getImage($iconName, "align=\"$align\" border=\"0\"", $width, $height);
4078 // works nicely to change UTF8 strings that are html entities - good for PDF conversions
4079 function html_entity_decode_utf8($string)
4082 // replace numeric entities
4083 //php will have issues with numbers with leading zeros, so do not include them in what we send to code2utf.
4084 $string = preg_replace('~�*([0-9a-f]+);~ei', 'code2utf(hexdec("\\1"))', $string);
4085 $string = preg_replace('~�*([0-9]+);~e', 'code2utf(\\1)', $string);
4086 // replace literal entities
4087 if (!isset($trans_tbl))
4089 $trans_tbl = array();
4090 foreach (get_html_translation_table(HTML_ENTITIES) as $val=>$key)
4091 $trans_tbl[$key] = utf8_encode($val);
4093 return strtr($string, $trans_tbl);
4096 // Returns the utf string corresponding to the unicode value
4097 function code2utf($num)
4099 if ($num < 128) return chr($num);
4100 if ($num < 2048) return chr(($num >> 6) + 192) . chr(($num & 63) + 128);
4101 if ($num < 65536) return chr(($num >> 12) + 224) . chr((($num >> 6) & 63) + 128) . chr(($num & 63) + 128);
4102 if ($num < 2097152) return chr(($num >> 18) + 240) . chr((($num >> 12) & 63) + 128) . chr((($num >> 6) & 63) + 128) . chr(($num & 63) + 128);
4106 function str_split_php4($string, $length = 1) {
4107 $string_length = strlen($string);
4110 if ($length > $string_length) {
4111 // use the string_length as the string is shorter than the length
4112 $length = $string_length;
4114 for ($cursor = 0; $cursor < $string_length; $cursor = $cursor + $length) {
4115 $return[] = substr($string, $cursor, $length);
4120 if (version_compare(phpversion(), '5.0.0', '<')) {
4121 function str_split($string, $length = 1) {
4122 return str_split_php4($string, $length);
4127 * @deprecated use DBManagerFactory::isFreeTDS
4129 function is_freetds()
4131 return DBManagerFactory::isFreeTDS();
4135 * Chart dashlet helper function that returns the correct CSS file, dependent on the current theme.
4137 * @todo this won't work completely right until we impliment css compression and combination
4138 * for now, we'll just include the last css file found.
4140 * @return chart.css file to use
4142 function chartStyle()
4144 return SugarThemeRegistry::current()->getCSSURL('chart.css');
4148 * Chart dashlet helper functions that returns the correct XML color file for charts,
4149 * dependent on the current theme.
4151 * @return sugarColors.xml to use
4153 function chartColors()
4155 if (SugarThemeRegistry::current()->getCSSURL('sugarColors.xml')=='')
4156 return SugarThemeRegistry::current()->getImageURL('sugarColors.xml');
4157 return SugarThemeRegistry::current()->getCSSURL('sugarColors.xml');
4159 /* End Chart Dashlet helper functions */
4162 * This function is designed to set up the php enviroment
4163 * for AJAX requests.
4166 function ajaxInit() {
4167 ini_set('display_errors', 'false');
4171 * Returns an absolute path from the given path, determining if it is relative or absolute
4173 * @param string $path
4176 function getAbsolutePath(
4178 $currentServer = false
4181 $path = trim($path);
4183 // try to match absolute paths like \\server\share, /directory or c:\
4184 if ( ( substr($path,0,2) == '\\\\' )
4185 || ( $path[0] == '/' )
4186 || preg_match('/^[A-z]:/i',$path)
4190 return getcwd().'/'.$path;
4194 * Returns the bean object of the given module
4196 * @deprecated use SugarModule::loadBean() instead
4197 * @param string $module
4204 return SugarModule::get($module)->loadBean();
4209 * Returns true if the application is being accessed on a touch screen interface ( like an iPad )
4211 function isTouchScreen()
4213 $ua = empty($_SERVER['HTTP_USER_AGENT']) ? "undefined" : strtolower($_SERVER['HTTP_USER_AGENT']);
4215 // first check if we have forced use of the touch enhanced interface
4216 if ( isset($_COOKIE['touchscreen']) && $_COOKIE['touchscreen'] == '1' ) {
4220 // next check if we should use the touch interface with our device
4221 if ( strpos($ua, 'ipad') !== false ) {
4229 * Returns the shortcut keys to access the shortcut links. Shortcut
4230 * keys vary depending on browser versions and operating systems.
4231 * @return String value of the shortcut keys
4233 function get_alt_hot_key() {
4235 if ( isset($_SERVER['HTTP_USER_AGENT']) )
4236 $ua = strtolower($_SERVER['HTTP_USER_AGENT']);
4237 $isMac = strpos($ua, 'mac') !== false;
4238 $isLinux = strpos($ua, 'linux') !== false;
4240 if(!$isMac && !$isLinux && strpos($ua, 'mozilla') !== false) {
4241 if(preg_match('/firefox\/(\d)?\./', $ua, $matches)) {
4242 return $matches[1] < 2 ? 'Alt+' : 'Alt+Shift+';
4245 return $isMac ? 'Ctrl+' : 'Alt+';
4248 function can_start_session(){
4249 if(!empty($_GET['PHPSESSID'])) {
4252 $session_id = session_id();
4253 return empty($session_id) ? true : false;
4256 function load_link_class($properties){
4258 if(!empty($properties['link_class']) && !empty($properties['link_file'])){
4259 require_once($properties['link_file']);
4260 $class = $properties['link_class'];
4266 function inDeveloperMode()
4268 return isset($GLOBALS['sugar_config']['developerMode']) && $GLOBALS['sugar_config']['developerMode'];
4272 * Filter the protocol list for inbound email accounts.
4274 * @param array $protocol
4276 function filterInboundEmailPopSelection($protocol)
4278 if ( !isset($GLOBALS['sugar_config']['allow_pop_inbound']) || ! $GLOBALS['sugar_config']['allow_pop_inbound'] )
4280 if( isset($protocol['pop3']) )
4281 unset($protocol['pop3']);
4284 $protocol['pop3'] = 'POP3';
4290 * The function is used because currently we are not supporting mbstring.func_overload
4291 * 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.
4292 * 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.
4293 * @returns the substred strings.
4295 function sugar_substr($string, $length, $charset='UTF-8')
4297 if(mb_strlen($string,$charset) > $length) {
4298 $string = trim(mb_substr(trim($string),0,$length,$charset));
4304 * The function is used because on FastCGI enviroment, the ucfirst(Chinese Characters) will produce bad charcters.
4305 * This will work even without setting the mbstring.*encoding
4307 function sugar_ucfirst($string, $charset='UTF-8') {
4308 return mb_strtoupper(mb_substr($string, 0, 1, $charset), $charset) . mb_substr($string, 1, mb_strlen($string), $charset);
4315 function unencodeMultienum($string) {
4316 if (is_array($string))
4320 if (substr($string, 0 ,1) == "^" && substr($string, -1) == "^") {
4321 $string = substr(substr($string, 1), 0, strlen($string) -2);
4324 return explode('^,^', $string);
4327 function encodeMultienumValue($arr) {
4328 if (!is_array($arr))
4334 $string = "^" . implode('^,^', $arr) . "^";
4340 * create_export_query is used for export and massupdate
4341 * We haven't handle the these fields: $field['type'] == 'relate' && isset($field['link']
4342 * This function will correct the where clause and output necessary join condition for them
4343 * @param $module: the module name
4344 * @param $searchFields: searchFields which is got after $searchForm->populateFromArray()
4345 * @param $where: where clauses
4346 * @return $ret_array['where']: corrected where clause
4347 * @return $ret_array['join']: extra join condition
4349 function create_export_query_relate_link_patch($module, $searchFields, $where){
4350 if(file_exists('modules/'.$module.'/SearchForm.html')){
4351 $ret_array['where'] = $where;
4354 $seed = loadBean($module);
4355 foreach($seed->field_defs as $name=>$field)
4358 if( $field['type'] == 'relate' && isset($field['link']) && !empty($searchFields[$name]['value']) ){
4359 $seed->load_relationship($field['link']);
4361 if(empty($join_type))
4363 $params['join_type'] = ' LEFT JOIN ';
4367 $params['join_type'] = $join_type;
4369 if(isset($data['join_name']))
4371 $params['join_table_alias'] = $field['join_name'];
4375 $params['join_table_alias'] = 'join_'.$field['name'];
4378 if(isset($data['join_link_name']))
4380 $params['join_table_link_alias'] = $field['join_link_name'];
4384 $params['join_table_link_alias'] = 'join_link_'.$field['name'];
4386 $join = $seed->$field['link']->getJoin($params, true);
4387 $join_table_alias = 'join_'.$field['name'];
4388 if(isset($field['db_concat_fields'])){
4389 $db_field = db_concat($join_table_alias, $field['db_concat_fields']);
4390 $where = preg_replace('/'.$field['name'].'/', $db_field, $where);
4392 $where = preg_replace('/(^|[\s(])' . $field['name'] . '/', '${1}' . $join_table_alias . '.'.$field['rname'], $where);
4396 $ret_array = array('where'=>$where, 'join'=>$join['join']);
4401 * 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.
4402 * @Depends on QuickRepairAndRebuild.php
4403 * @Relate bug 30642 ,23177
4405 function clearAllJsAndJsLangFilesWithoutOutput(){
4406 global $current_language , $mod_strings;
4407 $MBmodStrings = $mod_strings;
4408 $mod_strings = return_module_language ( $current_language, 'Administration' ) ;
4409 include_once ('modules/Administration/QuickRepairAndRebuild.php') ;
4410 $repair = new RepairAndClear();
4411 $repair->module_list = array();
4412 $repair->show_output = false;
4413 $repair->clearJsLangFiles();
4414 $repair->clearJsFiles();
4415 $mod_strings = $MBmodStrings;
4419 * This function will allow you to get a variable value from query string
4421 function getVariableFromQueryString($variable, $string){
4423 $number = preg_match("/{$variable}=([a-zA-Z0-9_-]+)[&]?/", $string, $matches);
4433 * should_hide_iframes
4434 * This is a helper method to determine whether or not to show iframes (My Sites) related
4435 * information in the application.
4437 * @return boolean flag indicating whether or not iframes module should be hidden
4439 function should_hide_iframes() {
4440 //Remove the MySites module
4441 if(file_exists('modules/iFrames/iFrame.php')) {
4442 if(!class_exists("iFrame")) {
4443 require_once('modules/iFrames/iFrame.php');
4451 * Given a version such as 5.5.0RC1 return RC. If we have a version such as: 5.5 then return GA
4453 * @param string $version
4454 * @return string RC, BETA, GA
4456 function getVersionStatus($version){
4457 if(preg_match('/^[\d\.]+?([a-zA-Z]+?)[\d]*?$/si', $version, $matches)) {
4458 return strtoupper($matches[1]);
4465 * Return the numeric portion of a version. For example if passed 5.5.0RC1 then return 5.5. If given
4466 * 5.5.1RC1 then return 5.5.1
4468 * @param string $version
4471 function getMajorMinorVersion($version){
4472 if(preg_match('/^([\d\.]+).*$/si', $version, $matches2)){
4473 $version = $matches2[1];
4474 $arr = explode('.', $version);
4475 if(count($arr) > 2){
4477 $version = substr($version, 0, 3);
4485 * Return string composed of seconds & microseconds of current time, without dots
4488 function sugar_microtime()
4490 $now = explode(' ', microtime());
4491 $unique_id = $now[1].str_replace('.', '', $now[0]);
4496 * Extract urls from a piece of text
4498 * @return array of urls found in $string
4500 function getUrls($string)
4502 $lines = explode("<br>", trim($string));
4504 foreach($lines as $line){
4505 $regex = '/http?\:\/\/[^\" ]+/i';
4506 preg_match_all($regex, $line, $matches);
4507 foreach($matches[0] as $match){
4516 * Sanitize image file from hostile content
4517 * @param string $path Image file
4518 * @param bool $jpeg Accept only JPEGs?
4520 function verify_image_file($path, $jpeg = false)
4522 if(function_exists('imagepng') && function_exists('imagejpeg') && function_exists('imagecreatefromstring')) {
4523 $img = imagecreatefromstring(file_get_contents($path));
4527 $img_size = getimagesize($path);
4528 $filetype = $img_size['mime'];
4529 //if filetype is jpeg or if we are only allowing jpegs, create jpg image
4530 if($filetype == "image/jpeg" || $jpeg) {
4533 $image = ob_get_clean();
4534 // not writing directly because imagejpeg does not work with streams
4535 if(file_put_contents($path, $image)) {
4538 } elseif ($filetype == "image/png") {
4539 // else if the filetype is png, create png
4540 imagealphablending($img, true);
4541 imagesavealpha($img, true);
4544 $image = ob_get_clean();
4545 if(file_put_contents($path, $image)) {
4552 // check image manually
4553 $fp = fopen($path, "rb");
4554 if(!$fp) return false;
4556 // read the whole file in chunks
4558 $data .= fread($fp,8192);
4562 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",
4564 $GLOBALS['log']->fatal("Found {$m[0]} in $path, not allowing upload");
4573 * Verify uploaded image
4574 * Verifies that image has proper extension, MIME type and doesn't contain hostile content
4575 * @param string $path Image path
4576 * @param bool $jpeg_only Accept only JPEGs?
4578 function verify_uploaded_image($path, $jpeg_only = false)
4580 $supportedExtensions = array('jpg' => 'image/jpeg', 'jpeg' => 'image/jpeg');
4582 $supportedExtensions['png'] = 'image/png';
4585 if(!file_exists($path) || !is_file($path)) {
4589 $img_size = getimagesize($path);
4590 $filetype = $img_size['mime'];
4591 $ext = end(explode(".", $path));
4592 if(substr_count('..', $path) > 0 || ($ext !== $path && !isset($supportedExtensions[strtolower($ext)])) ||
4593 !in_array($filetype, array_values($supportedExtensions))) {
4596 return verify_image_file($path, $jpeg_only);
4599 function cmp_beans($a, $b)
4601 global $sugar_web_service_order_by;
4602 //If the order_by field is not valid, return 0;
4603 if (empty($sugar_web_service_order_by) || !isset($a->$sugar_web_service_order_by) || !isset($b->$sugar_web_service_order_by)){
4606 if (is_object($a->$sugar_web_service_order_by) || is_object($b->$sugar_web_service_order_by)
4607 || is_array($a->$sugar_web_service_order_by) || is_array($b->$sugar_web_service_order_by))
4611 if ($a->$sugar_web_service_order_by < $b->$sugar_web_service_order_by)
4619 function order_beans($beans, $field_name)
4621 //Since php 5.2 doesn't include closures, we must use a global to pass the order field to cmp_beans.
4622 global $sugar_web_service_order_by;
4623 $sugar_web_service_order_by = $field_name;
4624 usort($beans, "cmp_beans");
4629 * Return search like string
4630 * This function takes a user input string and returns a string that contains wild card(s) that can be used in db query.
4631 * @param string $str string to be searched
4632 * @param string $like_char Database like character, usually '%'
4633 * @return string Returns a string to be searched in db query
4635 function sql_like_string($str, $like_char, $wildcard = '%', $appendWildcard = true) {
4637 // override default wildcard character
4638 if (isset($GLOBALS['sugar_config']['search_wildcard_char']) &&
4639 strlen($GLOBALS['sugar_config']['search_wildcard_char']) == 1) {
4640 $wildcard = $GLOBALS['sugar_config']['search_wildcard_char'];
4643 // add wildcard at the beginning of the search string
4644 if (isset($GLOBALS['sugar_config']['search_wildcard_infront']) &&
4645 $GLOBALS['sugar_config']['search_wildcard_infront'] == true) {
4646 if (substr($str,0,1) <> $wildcard)
4647 $str = $wildcard.$str;
4650 // add wildcard at the end of search string (default)
4651 if ($appendWildcard) {
4652 if(substr($str,-1) <> $wildcard) {
4657 return str_replace($wildcard, $like_char, $str);
4660 //check to see if custom utils exists
4661 if(file_exists('custom/include/custom_utils.php')){
4662 include_once('custom/include/custom_utils.php');
4665 //check to see if custom utils exists in Extension framework
4666 if(file_exists('custom/application/Ext/Utils/custom_utils.ext.php')) {
4667 include_once('custom/application/Ext/Utils/custom_utils.ext.php');
4670 * @param $input - the input string to sanitize
4671 * @param int $quotes - use quotes
4672 * @param string $charset - the default charset
4673 * @param bool $remove - strip tags or not
4674 * @return string - the sanitized string
4676 function sanitize($input, $quotes = ENT_QUOTES, $charset = 'UTF-8', $remove = false)
4678 return htmlentities($input, $quotes, $charset);
4682 * @return string - the full text search engine name
4684 function getFTSEngineType()
4686 if (isset($GLOBALS['sugar_config']['full_text_engine']) && is_array($GLOBALS['sugar_config']['full_text_engine'])) {
4687 foreach ($GLOBALS['sugar_config']['full_text_engine'] as $name => $defs) {
4695 * @param string $optionName - name of the option to be retrieved from app_list_strings
4696 * @return array - the array to be used in option element
4698 function getFTSBoostOptions($optionName)
4700 if (isset($GLOBALS['app_list_strings'][$optionName])) {
4701 return $GLOBALS['app_list_strings'][$optionName];
4709 * utf8_recursive_encode
4711 * This function walks through an Array and recursively calls utf8_encode on the
4712 * values of each of the elements.
4714 * @param $data Array of data to encode
4715 * @return utf8 encoded Array data
4717 function utf8_recursive_encode($data)
4720 foreach($data as $key=>$val) {
4721 if(is_array($val)) {
4722 $result[$key] = utf8_recursive_encode($val);
4724 $result[$key] = utf8_encode($val);
4731 * get_language_header
4733 * This is a utility function for 508 Compliance. It returns the lang=[Current Language] text string used
4734 * inside the <html> tag. If no current language is specified, it defaults to lang='en'.
4736 * @return String The lang=[Current Language] markup to insert into the <html> tag
4738 function get_language_header()
4740 return isset($GLOBALS['current_language']) ? "lang='{$GLOBALS['current_language']}'" : "lang='en'";
4745 * get_custom_file_if_exists
4747 * This function handles the repetitive code we have where we first check if a file exists in the
4748 * custom directory to determine whether we should load it, require it, include it, etc. This function returns the
4749 * path of the custom file if it exists. It basically checks if custom/{$file} exists and returns this path if so;
4750 * otherwise it return $file
4752 * @param $file String of filename to check
4753 * @return $file String of filename including custom directory if found
4755 function get_custom_file_if_exists($file)
4757 return file_exists("custom/{$file}") ? "custom/{$file}" : $file;
4764 * This will return the URL used to redirect the user to the help documentation.
4765 * It can be overriden completely by setting the custom_help_url or partially by setting the custom_help_base_url
4766 * in config.php or config_override.php.
4768 * @param string $send_edition
4769 * @param string $send_version
4770 * @param string $send_lang
4771 * @param string $send_module
4772 * @param string $send_action
4773 * @param string $dev_status
4774 * @param string $send_key
4775 * @param string $send_anchor
4776 * @return string the completed help URL
4778 function get_help_url($send_edition = '', $send_version = '', $send_lang = '', $send_module = '', $send_action = '', $dev_status = '', $send_key = '', $send_anchor = '') {
4779 global $sugar_config;
4781 if (!empty($sugar_config['custom_help_url'])) {
4782 $sendUrl = $sugar_config['custom_help_url'];
4784 if (!empty($sugar_config['custom_help_base_url'])) {
4785 $baseUrl= $sugar_config['custom_help_base_url'];
4787 $baseUrl = "http://www.sugarcrm.com/crm/product_doc.php";
4789 $sendUrl = $baseUrl . "?edition={$send_edition}&version={$send_version}&lang={$send_lang}&module={$send_module}&help_action={$send_action}&status={$dev_status}&key={$send_key}";
4790 if(!empty($send_anchor)) {
4791 $sendUrl .= "&anchor=".$send_anchor;
4798 * generateETagHeader
4800 * This function generates the necessary cache headers for using ETags with dynamic content. You
4801 * simply have to generate the ETag, pass it in, and the function handles the rest.
4803 * @param string $etag ETag to use for this content.
4805 function generateETagHeader($etag){
4806 header("cache-control:");
4807 header('Expires: ');
4808 header("ETag: " . $etag);
4810 if(isset($_SERVER["HTTP_IF_NONE_MATCH"])){
4811 if($etag == $_SERVER["HTTP_IF_NONE_MATCH"]){
4813 header("Status: 304 Not Modified");
4814 header("HTTP/1.0 304 Not Modified");
4821 * getReportNameTranslation
4823 * Translates the report name if a translation exists,
4824 * otherwise just returns the name
4826 * @param string $reportName
4827 * @return string translated report name
4829 function getReportNameTranslation($reportName) {
4830 global $current_language;
4832 // Used for translating reports
4833 $mod_strings = return_module_language($current_language, 'Reports');
4835 // Search for the report name in the default language and get the key
4836 $key = array_search($reportName, return_module_language("", "Reports"));
4838 // If the key was found, use it to get a translation, otherwise just use report name
4840 $title = $mod_strings[$key];
4842 $title = $reportName;
4849 * Remove vars marked senstitive from array
4850 * @param array $defs
4851 * @param SugarBean|array $data
4852 * @return mixed $data without sensitive fields
4854 function clean_sensitive_data($defs, $data)
4856 foreach($defs as $field => $def) {
4857 if(!empty($def['sensitive'])) {
4858 if(is_array($data)) {
4861 if($data instanceof SugarBean) {
4870 * Return relations with labels for duplicates
4872 function getDuplicateRelationListWithTitle($def, $var_def, $module)
4874 global $current_language;
4875 $select_array = array_unique($def);
4876 if (count($select_array) < count($def))
4878 $temp_module_strings = return_module_language($current_language, $module);
4879 $temp_duplicate_array = array_diff_assoc($def, $select_array);
4880 $temp_duplicate_array = array_merge($temp_duplicate_array, array_intersect($select_array, $temp_duplicate_array));
4882 foreach ($temp_duplicate_array as $temp_key => $temp_value)
4884 // Don't add duplicate relationships
4885 if (!empty($var_def[$temp_key]['relationship']) && array_key_exists($var_def[$temp_key]['relationship'], $select_array))
4889 $select_array[$temp_key] = $temp_value;
4892 // Add the relationship name for easier recognition
4893 foreach ($select_array as $key => $value)
4895 $select_array[$key] .= ' (' . $key . ')';
4898 asort($select_array);
4899 return $select_array;