2 /*********************************************************************************
3 * SugarCRM Community Edition is a customer relationship management program developed by
4 * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
6 * This program is free software; you can redistribute it and/or modify it under
7 * the terms of the GNU Affero General Public License version 3 as published by the
8 * Free Software Foundation with the addition of the following permission added
9 * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
10 * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
11 * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
18 * You should have received a copy of the GNU Affero General Public License along with
19 * this program; if not, see http://www.gnu.org/licenses or write to the Free
20 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
24 * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
26 * The interactive user interfaces in modified source and object code versions
27 * of this program must display Appropriate Legal Notices, as required under
28 * Section 5 of the GNU Affero General Public License version 3.
30 * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
31 * these Appropriate Legal Notices must retain the display of the "Powered by
32 * SugarCRM" logo. If the display of the logo is not reasonably feasible for
33 * technical reasons, the Appropriate Legal Notices must display the words
34 * "Powered by SugarCRM".
35 ********************************************************************************/
37 /*********************************************************************************
39 * Description: Includes generic helper functions used throughout the application.
40 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
41 * All Rights Reserved.
42 * Contributor(s): ______________________________________..
43 ********************************************************************************/
44 require_once('include/SugarObjects/SugarConfig.php');
45 require_once('include/utils/security_utils.php');
49 function make_sugar_config(&$sugar_config)
51 /* used to convert non-array config.php file to array format */
52 global $admin_export_only;
54 global $calculate_response_time;
55 global $create_default_user;
58 global $dbconfigoption;
59 global $default_action;
60 global $default_charset;
61 global $default_currency_name;
62 global $default_currency_symbol;
63 global $default_currency_iso4217;
64 global $defaultDateFormat;
65 global $default_language;
66 global $default_module;
67 global $default_password;
68 global $default_permission_mode;
69 global $default_theme;
70 global $defaultTimeFormat;
71 global $default_user_is_admin;
72 global $default_user_name;
73 global $disable_export;
74 global $disable_persistent_connections;
75 global $display_email_template_variable_chooser;
76 global $display_inbound_email_buttons;
77 global $history_max_viewed;
81 global $list_max_entries_per_page;
82 global $lock_default_user_name;
83 global $log_memory_usage;
85 global $requireAccounts;
86 global $RSS_CACHE_TIME;
90 global $sugar_version;
93 global $translation_string_prefix;
95 global $upload_badext;
97 global $upload_maxsize;
98 global $import_max_execution_time;
99 global $list_max_entries_per_subpanel;
100 global $passwordsetting;
102 // assumes the following variables must be set:
103 // $dbconfig, $dbconfigoption, $cache_dir, $session_dir, $site_URL, $upload_dir
105 $sugar_config = array (
106 'admin_export_only' => empty($admin_export_only) ? false : $admin_export_only,
107 'export_delimiter' => empty($export_delimiter) ? ',' : $export_delimiter,
108 'cache_dir' => empty($cache_dir) ? 'cache/' : $cache_dir,
109 'calculate_response_time' => empty($calculate_response_time) ? true : $calculate_response_time,
110 'create_default_user' => empty($create_default_user) ? false : $create_default_user,
111 'chartEngine' => 'Jit',
112 'date_formats' => empty($dateFormats) ? array(
113 'Y-m-d'=>'2010-12-23',
114 'd-m-Y' => '23-12-2010',
115 'm-d-Y'=>'12-23-2010',
116 'Y/m/d'=>'2010/12/23',
117 'd/m/Y' => '23/12/2010',
118 'm/d/Y'=>'12/23/2010',
119 'Y.m.d' => '2010.12.23',
120 'd.m.Y' => '23.12.2010',
121 'm.d.Y' => '12.23.2010'
123 'dbconfig' => $dbconfig, // this must be set!!
124 'dbconfigoption' => $dbconfigoption, // this must be set!!
125 'default_action' => empty($default_action) ? 'index' : $default_action,
126 'default_charset' => empty($default_charset) ? 'UTF-8' : $default_charset,
127 'default_currency_name' => empty($default_currency_name) ? 'US Dollar' : $default_currency_name,
128 'default_currency_symbol' => empty($default_currency_symbol) ? '$' : $default_currency_symbol,
129 'default_currency_iso4217' => empty($default_currency_iso4217) ? '$' : $default_currency_iso4217,
130 'default_date_format' => empty($defaultDateFormat) ? 'm/d/Y' : $defaultDateFormat,
131 'default_locale_name_format' => empty($defaultNameFormat) ? 's f l' : $defaultNameFormat,
132 'default_export_charset' => 'UTF-8',
133 'default_language' => empty($default_language) ? 'en_us' : $default_language,
134 'default_module' => empty($default_module) ? 'Home' : $default_module,
135 'default_password' => empty($default_password) ? '' : $default_password,
136 'default_permissions' => array (
142 'default_theme' => empty($default_theme) ? 'Sugar5' : $default_theme,
143 'default_time_format' => empty($defaultTimeFormat) ? 'h:ia' : $defaultTimeFormat,
144 'default_user_is_admin' => empty($default_user_is_admin) ? false : $default_user_is_admin,
145 'default_user_name' => empty($default_user_name) ? '' : $default_user_name,
146 'disable_export' => empty($disable_export) ? false : $disable_export,
147 'disable_persistent_connections' => empty($disable_persistent_connections) ? false : $disable_persistent_connections,
148 'display_email_template_variable_chooser' => empty($display_email_template_variable_chooser) ? false : $display_email_template_variable_chooser,
149 'display_inbound_email_buttons' => empty($display_inbound_email_buttons) ? false : $display_inbound_email_buttons,
150 'history_max_viewed' => empty($history_max_viewed) ? 50 : $history_max_viewed,
151 'host_name' => empty($host_name) ? 'localhost' : $host_name,
152 'import_dir' => $import_dir, // this must be set!!
153 'import_max_records_per_file' => 100,
154 'import_max_records_total_limit' => '',
155 'languages' => empty($languages) ? array('en_us' => 'English (US)') : $languages,
156 'list_max_entries_per_page' => empty($list_max_entries_per_page) ? 20 : $list_max_entries_per_page,
157 'list_max_entries_per_subpanel' => empty($list_max_entries_per_subpanel) ? 10 : $list_max_entries_per_subpanel,
158 'lock_default_user_name' => empty($lock_default_user_name) ? false : $lock_default_user_name,
159 'log_memory_usage' => empty($log_memory_usage) ? false : $log_memory_usage,
160 'name_formats' => empty($nameFormats) ? array(
161 's f l' => 's f l', 'f l' => 'f l', 's l' => 's l', 'l, s f' => 'l, s f',
162 'l, f' => 'l, f', 's l, f' => 's l, f', 'l s f' => 'l s f', 'l f s' => 'l f s'
164 'portal_view' => 'single_user',
165 'resource_management' => array (
166 'special_query_limit' => 50000,
167 'special_query_modules' => array('Reports', 'Export', 'Import', 'Administration', 'Sync'),
168 'default_limit' => 1000,
170 'require_accounts' => empty($requireAccounts) ? true : $requireAccounts,
171 'rss_cache_time' => empty($RSS_CACHE_TIME) ? '10800' : $RSS_CACHE_TIME,
172 'session_dir' => $session_dir, // this must be set!!
173 'site_url' => empty($site_URL) ? $site_url : $site_URL, // this must be set!!
174 'showDetailData' => true, // if true, read-only ACL fields will still appear on EditViews as non-editable
175 'showThemePicker' => true,
176 'sugar_version' => empty($sugar_version) ? 'unknown' : $sugar_version,
177 'time_formats' => empty($timeFormats) ? array (
178 'H:i'=>'23:00', 'h:ia'=>'11:00 pm', 'h:iA'=>'11:00PM',
179 'H.i'=>'23.00', 'h.ia'=>'11.00 pm', 'h.iA'=>'11.00PM' ) : $timeFormats,
180 'tmp_dir' => $tmp_dir, // this must be set!!
181 'translation_string_prefix' => empty($translation_string_prefix) ? false : $translation_string_prefix,
182 'unique_key' => empty($unique_key) ? md5(create_guid()) : $unique_key,
183 'upload_badext' => empty($upload_badext) ? array (
184 'php', 'php3', 'php4', 'php5', 'pl', 'cgi', 'py',
185 'asp', 'cfm', 'js', 'vbs', 'html', 'htm' ) : $upload_badext,
186 'upload_dir' => $upload_dir, // this must be set!!
187 'upload_maxsize' => empty($upload_maxsize) ? 30000000 : $upload_maxsize,
188 'import_max_execution_time' => empty($import_max_execution_time) ? 3600 : $import_max_execution_time,
189 'lock_homepage' => false,
190 'lock_subpanels' => false,
191 'max_dashlets_homepage' => 15,
192 'dashlet_display_row_options' => array('1','3','5','10'),
193 'default_max_tabs' => empty($max_tabs) ? '7' : $max_tabs,
194 'default_subpanel_tabs' => empty($subpanel_tabs) ? true : $subpanel_tabs,
195 'default_subpanel_links' => empty($subpanel_links) ? false : $subpanel_links,
196 'default_swap_last_viewed' => empty($swap_last_viewed) ? false : $swap_last_viewed,
197 'default_swap_shortcuts' => empty($swap_shortcuts) ? false : $swap_shortcuts,
198 'default_navigation_paradigm' => empty($navigation_paradigm) ? 'gm' : $navigation_paradigm,
199 'default_call_status' => 'Planned',
200 'js_lang_version' => 1,
201 'passwordsetting' => empty($passwordsetting) ? array (
202 'SystemGeneratedPasswordON' => '',
203 'generatepasswordtmpl' => '',
204 'lostpasswordtmpl' => '',
205 'forgotpasswordON' => true,
206 'linkexpiration' => '1',
207 'linkexpirationtime' => '30',
208 'linkexpirationtype' => '1',
209 'systexpiration' => '0',
210 'systexpirationtime' => '',
211 'systexpirationtype' => '0',
212 'systexpirationlogin' => '',
213 ) : $passwordsetting,
214 'use_sprites' => function_exists('imagecreatetruecolor'),
215 'search_wildcard_infront' => false,
216 'search_wildcard_char' => '%',
218 'min_retry_interval' => 60, // minimal job retry delay
219 'max_retries' => 5, // how many times to retry the job
220 'timeout' => 86400, // how long a job may spend as running before being force-failed
221 'soft_lifetime' => 7, // how many days until job record will be soft deleted after completion
222 'hard_lifetime' => 21, // how many days until job record will be purged from DB
225 'max_cron_jobs' => 10, // max jobs per cron schedule run
226 'max_cron_runtime' => 60, // max runtime for cron jobs
227 'min_cron_interval' => 30, // minimal interval between cron jobs
232 function get_sugar_config_defaults() {
235 * used for getting base values for array style config.php. used by the
236 * installer and to fill in new entries on upgrades. see also:
240 $sugar_config_defaults = array (
241 'admin_export_only' => false,
242 'export_delimiter' => ',',
243 'export_excel_compatible' => false,
244 'cache_dir' => 'cache/',
245 'calculate_response_time' => true,
246 'create_default_user' => false,
247 'chartEngine' => 'Jit',
248 'date_formats' => array (
249 'Y-m-d' => '2010-12-23', 'm-d-Y' => '12-23-2010', 'd-m-Y' => '23-12-2010',
250 'Y/m/d' => '2010/12/23', 'm/d/Y' => '12/23/2010', 'd/m/Y' => '23/12/2010',
251 'Y.m.d' => '2010.12.23', 'd.m.Y' => '23.12.2010', 'm.d.Y' => '12.23.2010',),
252 'name_formats' => array (
253 's f l' => 's f l', 'f l' => 'f l', 's l' => 's l', 'l, s f' => 'l, s f',
254 'l, f' => 'l, f', 's l, f' => 's l, f', 'l s f' => 'l s f', 'l f s' => 'l f s'
256 'dbconfigoption' => array (
257 'persistent' => true,
261 'default_action' => 'index',
262 'default_charset' => return_session_value_or_default('default_charset',
264 'default_currency_name' => return_session_value_or_default('default_currency_name', 'US Dollar'),
265 'default_currency_symbol' => return_session_value_or_default('default_currency_symbol', '$'),
266 'default_currency_iso4217' => return_session_value_or_default('default_currency_iso4217', 'USD'),
267 'default_currency_significant_digits' => return_session_value_or_default('default_currency_significant_digits', 2),
268 'default_number_grouping_seperator' => return_session_value_or_default('default_number_grouping_seperator', ','),
269 'default_decimal_seperator' => return_session_value_or_default('default_decimal_seperator', '.'),
270 'default_date_format' => 'm/d/Y',
271 'default_locale_name_format' => 's f l',
272 'default_export_charset' => 'UTF-8',
273 'default_language' => return_session_value_or_default('default_language',
275 'default_module' => 'Home',
276 'default_password' => '',
277 'default_permissions' => array (
283 'default_theme' => return_session_value_or_default('site_default_theme', 'Sugar5'),
284 'default_time_format' => 'h:ia',
285 'default_user_is_admin' => false,
286 'default_user_name' => '',
287 'disable_export' => false,
288 'disable_persistent_connections' =>
289 return_session_value_or_default('disable_persistent_connections',
291 'display_email_template_variable_chooser' => false,
292 'display_inbound_email_buttons' => false,
293 'dump_slow_queries' => false,
294 'email_address_separator' => ',', // use RFC2368 spec unless we have a noncompliant email client
295 'email_default_editor' => 'html',
296 'email_default_client' => 'sugar',
297 'email_default_delete_attachments' => true,
298 'history_max_viewed' => 50,
299 'installer_locked' => true,
300 'import_max_records_per_file' => 100,
301 'import_max_records_total_limit' => '',
302 'languages' => array('en_us' => 'English (US)'),
303 'large_scale_test' => false,
304 'list_max_entries_per_page' => 20,
305 'list_max_entries_per_subpanel' => 10,
306 'lock_default_user_name' => false,
307 'log_memory_usage' => false,
308 'portal_view' => 'single_user',
309 'resource_management' => array (
310 'special_query_limit' => 50000,
311 'special_query_modules' => array('Reports', 'Export', 'Import', 'Administration', 'Sync'),
312 'default_limit' => 1000,
314 'require_accounts' => true,
315 'rss_cache_time' => return_session_value_or_default('rss_cache_time',
317 'save_query' => 'all',
318 'showDetailData' => true, // if true, read-only ACL fields will still appear on EditViews as non-editable
319 'showThemePicker' => true,
320 'slow_query_time_msec' => '100',
322 'time_formats' => array (
323 'H:i'=>'23:00', 'h:ia'=>'11:00pm', 'h:iA'=>'11:00PM', 'h:i a'=>'11:00 pm', 'h:i A'=>'11:00 PM',
324 'H.i'=>'23.00', 'h.ia'=>'11.00pm', 'h.iA'=>'11.00PM', 'h.i a'=>'11.00 pm', 'h.i A'=>'11.00 PM' ),
325 'tracker_max_display_length' => 15,
326 'translation_string_prefix' =>
327 return_session_value_or_default('translation_string_prefix', false),
328 'upload_badext' => array (
329 'php', 'php3', 'php4', 'php5', 'pl', 'cgi', 'py',
330 'asp', 'cfm', 'js', 'vbs', 'html', 'htm' ),
331 'upload_maxsize' => 30000000,
332 'import_max_execution_time' => 3600,
333 // 'use_php_code_json' => returnPhpJsonStatus(),
334 'verify_client_ip' => true,
335 'js_custom_version' => '',
336 'js_lang_version' => 1,
337 'lead_conv_activity_opt' => 'donothing',
338 'default_number_grouping_seperator' => ',',
339 'default_decimal_seperator' => '.',
340 'lock_homepage' => false,
341 'lock_subpanels' => false,
342 'max_dashlets_homepage' => '15',
343 'default_max_tabs' => '7',
344 'dashlet_display_row_options' => array('1','3','5','10'),
345 'default_subpanel_tabs' => true,
346 'default_subpanel_links' => false,
347 'default_swap_last_viewed' => false,
348 'default_swap_shortcuts' => false,
349 'default_navigation_paradigm' => 'gm',
350 'admin_access_control' => false,
351 'use_common_ml_dir' => false,
352 'common_ml_dir' => '',
355 'default_view' => 'week',
356 'show_calls_by_default' => true,
357 'show_tasks_by_default' => true,
358 'show_completed_by_default' => true,
359 'editview_width' => 990,
360 'editview_height' => 485,
361 'day_timestep' => 15,
362 'week_timestep' => 30,
363 'items_draggable' => true,
364 'items_resizable' => true,
365 'enable_repeat' => true,
366 'max_repeat_count' => 1000,
368 'passwordsetting' => empty($passwordsetting) ? array (
369 'SystemGeneratedPasswordON' => '',
370 'generatepasswordtmpl' => '',
371 'lostpasswordtmpl' => '',
372 'forgotpasswordON' => false,
373 'linkexpiration' => '1',
374 'linkexpirationtime' => '30',
375 'linkexpirationtype' => '1',
376 'systexpiration' => '0',
377 'systexpirationtime' => '',
378 'systexpirationtype' => '0',
379 'systexpirationlogin' => '',
380 ) : $passwordsetting,
381 'use_real_names' => true,
383 'search_wildcard_infront' => false,
384 'search_wildcard_char' => '%',
386 'min_retry_interval' => 30, // 30 seconds minimal job retry
387 'max_retries' => 5, // how many times to retry the job
388 'timeout' => 86400, // how long a job may spend as running before being force-failed
391 'max_cron_jobs' => 10, // max jobs per cron schedule run
392 'max_cron_runtime' => 30, // max runtime for cron jobs
393 'min_cron_interval' => 30, // minimal interval between cron jobs
397 if(!is_object($locale)) {
398 $locale = new Localization();
401 $sugar_config_defaults['default_currencies'] = $locale->getDefaultCurrencies();
403 $sugar_config_defaults = sugarArrayMerge($locale->getLocaleConfigDefaults(), $sugar_config_defaults);
404 return( $sugar_config_defaults );
408 * @deprecated use SugarView::getMenu() instead
410 function load_menu($path){
413 if(file_exists($path . 'Menu.php'))
415 require($path . 'Menu.php');
417 if(file_exists('custom/' . $path . 'Ext/Menus/menu.ext.php'))
419 require('custom/' . $path . 'Ext/Menus/menu.ext.php');
421 if(file_exists('custom/application/Ext/Menus/menu.ext.php'))
423 require('custom/application/Ext/Menus/menu.ext.php');
429 * get_notify_template_file
430 * This function will return the location of the email notifications template to use
432 * @return string relative file path to email notifications template file
434 function get_notify_template_file($language){
436 * Order of operation:
437 * 1) custom version of specified language
438 * 2) stock version of specified language
439 * 3) custom version of en_us template
440 * 4) stock en_us template
443 // set $file to the base code template so it's set if none of the conditions pass
444 $file = "include/language/en_us.notify_template.html";
446 if(file_exists("custom/include/language/{$language}.notify_template.html")){
447 $file = "custom/include/language/{$language}.notify_template.html";
449 else if(file_exists("include/language/{$language}.notify_template.html")){
450 $file = "include/language/{$language}.notify_template.html";
452 else if(file_exists("custom/include/language/en_us.notify_template.html")){
453 $file = "custom/include/language/en_us.notify_template.html";
459 function sugar_config_union( $default, $override ){
460 // a little different then array_merge and array_merge_recursive. we want
461 // the second array to override the first array if the same value exists,
462 // otherwise merge the unique keys. it handles arrays of arrays recursively
463 // might be suitable for a generic array_union
464 if( !is_array( $override ) ){
467 foreach( $default as $key => $value ){
468 if( !array_key_exists($key, $override) ){
469 $override[$key] = $value;
471 else if( is_array( $key ) ){
472 $override[$key] = sugar_config_union( $value, $override[$key] );
478 function make_not_writable( $file ){
479 // Returns true if the given file/dir has been made not writable
481 if( is_file($file) || is_dir($file) ){
482 if( !is_writable($file) ){
486 $original_fileperms = fileperms($file);
488 // take away writable permissions
489 $new_fileperms = $original_fileperms & ~0x0092;
490 @sugar_chmod($file, $new_fileperms);
492 if( !is_writable($file) ){
501 /** This function returns the name of the person.
502 * It currently returns "first last". It should not put the space if either name is not available.
503 * It should not return errors if either name is not available.
504 * If no names are present, it will return ""
505 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
506 * All Rights Reserved.
507 * Contributor(s): ______________________________________..
509 function return_name($row, $first_column, $last_column)
515 if(isset($row[$first_column]))
517 $first_name = stripslashes($row[$first_column]);
520 if(isset($row[$last_column]))
522 $last_name = stripslashes($row[$last_column]);
525 $full_name = $first_name;
527 // If we have a first name and we have a last name
528 if($full_name != "" && $last_name != "")
530 // append a space, then the last name
531 $full_name .= " ".$last_name;
533 // If we have no first name, but we have a last name
534 else if($last_name != "")
536 // append the last name without the space.
537 $full_name .= $last_name;
544 function get_languages()
546 global $sugar_config;
547 $lang = $sugar_config['languages'];
548 if(!empty($sugar_config['disabled_languages'])){
549 foreach(explode(',', $sugar_config['disabled_languages']) as $disable) {
550 unset($lang[$disable]);
556 function get_all_languages()
558 global $sugar_config;
559 return $sugar_config['languages'];
563 function get_language_display($key)
565 global $sugar_config;
566 return $sugar_config['languages'][$key];
569 function get_assigned_user_name($assigned_user_id, $is_group = '') {
570 static $saved_user_list = null;
572 if(empty($saved_user_list)) {
573 $saved_user_list = get_user_array(false, '', '', false, null, $is_group);
576 if(isset($saved_user_list[$assigned_user_id])) {
577 return $saved_user_list[$assigned_user_id];
584 * retrieves the user_name column value (login)
585 * @param string id GUID of user
588 function get_user_name($id) {
592 $db = DBManagerFactory::getInstance();
594 $q = "SELECT user_name FROM users WHERE id='{$id}'";
596 $a = $db->fetchByAssoc($r);
598 return (empty($a)) ? '' : $a['user_name'];
602 //TODO Update to use global cache
606 * This is a helper function to return an Array of users depending on the parameters passed into the function.
607 * This function uses the get_register_value function by default to use a caching layer where supported.
608 * This function has been updated return the array sorted by user preference of name display (bug 62712)
610 * @param bool $add_blank Boolean value to add a blank entry to the array results, true by default
611 * @param string $status String value indicating the status to filter users by, "Active" by default
612 * @param string $user_id String value to specify a particular user id value (searches the id column of users table), blank by default
613 * @param bool $use_real_name Boolean value indicating whether or not results should include the full name or just user_name, false by default
614 * @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
615 * @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
616 * @param bool $from_cache Boolean value indicating whether or not to use the get_register_value function for caching, true by default
617 * @return array Array of users matching the filter criteria that may be from cache (if similar search was previously run)
619 function get_user_array($add_blank=true, $status="Active", $user_id='', $use_real_name=false, $user_name_filter='', $portal_filter=' AND portal_only=0 ', $from_cache = true) {
620 global $locale, $sugar_config, $current_user;
623 $locale = new Localization();
627 $key_name = $add_blank. $status . $user_id . $use_real_name . $user_name_filter . $portal_filter;
628 $user_array = get_register_value('user_array', $key_name);
631 if(empty($user_array)) {
632 $db = DBManagerFactory::getInstance();
633 $temp_result = Array();
634 // Including deleted users for now.
635 if (empty($status)) {
636 $query = "SELECT id, first_name, last_name, user_name from users WHERE 1=1".$portal_filter;
639 $query = "SELECT id, first_name, last_name, user_name from users WHERE status='$status'".$portal_filter;
642 if (!empty($user_name_filter)) {
643 $user_name_filter = $db->quote($user_name_filter);
644 $query .= " AND user_name LIKE '$user_name_filter%' ";
646 if (!empty($user_id)) {
647 $query .= " OR id='{$user_id}'";
650 //get the user preference for name formatting, to be used in order by
651 $order_by_string =' user_name ASC ';
652 if(!empty($current_user) && !empty($current_user->id))
654 $formatString = $current_user->getPreference('default_locale_name_format');
656 //create the order by string based on position of first and last name in format string
657 $order_by_string =' user_name ASC ';
658 $firstNamePos = strpos( $formatString, 'f');
659 $lastNamePos = strpos( $formatString, 'l');
660 if($firstNamePos !== false || $lastNamePos !== false){
661 //its possible for first name to be skipped, check for this
662 if($firstNamePos===false){
663 $order_by_string = 'last_name ASC';
665 $order_by_string = ($lastNamePos < $firstNamePos) ? "last_name, first_name ASC" : "first_name, last_name ASC";
670 $query = $query.' ORDER BY '.$order_by_string;
671 $GLOBALS['log']->debug("get_user_array query: $query");
672 $result = $db->query($query, true, "Error filling in user array: ");
674 if ($add_blank==true) {
675 // Add in a blank row
676 $temp_result[''] = '';
679 // Get the id and the name.
680 while($row = $db->fetchByAssoc($result)) {
681 if($use_real_name == true || showFullName()) {
682 if(isset($row['last_name'])) { // cn: we will ALWAYS have both first_name and last_name (empty value if blank in db)
683 $temp_result[$row['id']] = $locale->getLocaleFormattedName($row['first_name'],$row['last_name']);
685 $temp_result[$row['id']] = $row['user_name'];
688 $temp_result[$row['id']] = $row['user_name'];
692 $user_array = $temp_result;
695 set_register_value('user_array', $key_name, $temp_result);
705 * uses a different query to return a list of users than get_user_array()
706 * Used from QuickSearch.php
707 * @param args string where clause entry
708 * @return array Array of Users' details that match passed criteria
710 function getUserArrayFromFullName($args, $hide_portal_users = false) {
712 $db = DBManagerFactory::getInstance();
714 // jmorais@dri - Bug #51411
716 // Refactor the code responsible for parsing supplied $args, this way we
717 // ensure that if $args has at least one space (after trim), the $inClause
718 // will be composed by several clauses ($inClauses) inside parenthesis.
720 // Ensuring that operator precedence is respected, and avoiding
721 // inactive/deleted users to be retrieved.
724 if (strpos($args, ' ')) {
725 $inClauses = array();
727 $argArray = explode(' ', $args);
728 foreach ($argArray as $arg) {
729 $arg = $db->quote($arg);
730 $inClauses[] = "(first_name LIKE '{$arg}%' OR last_name LIKE '{$arg}%')";
733 $inClause = '(' . implode('OR ', $inClauses) . ')';
736 $args = $db->quote($args);
737 $inClause = "(first_name LIKE '{$args}%' OR last_name LIKE '{$args}%')";
741 $query = "SELECT id, first_name, last_name, user_name FROM users WHERE status='Active' AND deleted=0 AND ";
742 if ( $hide_portal_users ) {
743 $query .= " portal_only=0 AND ";
746 $query .= " ORDER BY last_name ASC";
748 $r = $db->query($query);
750 while($a = $db->fetchByAssoc($r)) {
751 $ret[$a['id']] = $locale->getLocaleFormattedName($a['first_name'], $a['last_name']);
759 * based on user pref then system pref
761 function showFullName() {
762 global $sugar_config;
763 global $current_user;
764 static $showFullName = null;
766 if (is_null($showFullName)) {
767 $sysPref = !empty($sugar_config['use_real_names']);
768 $userPref = (is_object($current_user)) ? $current_user->getPreference('use_real_names') : null;
770 if($userPref != null) {
771 $showFullName = ($userPref == 'on');
773 $showFullName = $sysPref;
777 return $showFullName;
780 function clean($string, $maxLength)
782 $string = substr($string, 0, $maxLength);
783 return escapeshellcmd($string);
787 * Copy the specified request variable to the member variable of the specified object.
788 * Do no copy if the member variable is already set.
789 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
790 * All Rights Reserved.
791 * Contributor(s): ______________________________________..
793 function safe_map($request_var, & $focus, $always_copy = false)
795 safe_map_named($request_var, $focus, $request_var, $always_copy);
799 * Copy the specified request variable to the member variable of the specified object.
800 * Do no copy if the member variable is already set.
801 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
802 * All Rights Reserved.
803 * Contributor(s): ______________________________________..
805 function safe_map_named($request_var, & $focus, $member_var, $always_copy)
807 if (isset($_REQUEST[$request_var]) && ($always_copy || is_null($focus->$member_var))) {
808 $GLOBALS['log']->debug("safe map named called assigning '{$_REQUEST[$request_var]}' to $member_var");
809 $focus->$member_var = $_REQUEST[$request_var];
814 * This function retrieves an application language file and returns the array of strings included in the $app_list_strings var.
816 * @param string $language specific language to load
817 * @return array lang strings
819 function return_app_list_strings_language($language)
821 global $app_list_strings;
822 global $sugar_config;
824 $cache_key = 'app_list_strings.'.$language;
826 // Check for cached value
827 $cache_entry = sugar_cache_retrieve($cache_key);
828 if(!empty($cache_entry))
833 $default_language = $sugar_config['default_language'];
834 $temp_app_list_strings = $app_list_strings;
837 if ($language != 'en_us') {
840 if ($default_language != 'en_us' && $language != $default_language) {
841 $langs[] = $default_language;
843 $langs[] = $language;
845 $app_list_strings_array = array();
847 foreach ( $langs as $lang ) {
848 $app_list_strings = array();
849 if(file_exists("include/language/$lang.lang.php")) {
850 include("include/language/$lang.lang.php");
851 $GLOBALS['log']->info("Found language file: $lang.lang.php");
853 if(file_exists("include/language/$lang.lang.override.php")) {
854 include("include/language/$lang.lang.override.php");
855 $GLOBALS['log']->info("Found override language file: $lang.lang.override.php");
857 if(file_exists("include/language/$lang.lang.php.override")) {
858 include("include/language/$lang.lang.php.override");
859 $GLOBALS['log']->info("Found override language file: $lang.lang.php.override");
862 $app_list_strings_array[] = $app_list_strings;
865 $app_list_strings = array();
866 foreach ( $app_list_strings_array as $app_list_strings_item ) {
867 $app_list_strings = sugarLangArrayMerge($app_list_strings, $app_list_strings_item);
870 foreach ( $langs as $lang ) {
871 if(file_exists("custom/application/Ext/Language/$lang.lang.ext.php")) {
872 $app_list_strings = _mergeCustomAppListStrings("custom/application/Ext/Language/$lang.lang.ext.php" , $app_list_strings);
873 $GLOBALS['log']->info("Found extended language file: $lang.lang.ext.php");
875 if(file_exists("custom/include/language/$lang.lang.php")) {
876 include("custom/include/language/$lang.lang.php");
877 $GLOBALS['log']->info("Found custom language file: $lang.lang.php");
881 if(!isset($app_list_strings)) {
882 $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");
886 $return_value = $app_list_strings;
887 $app_list_strings = $temp_app_list_strings;
889 sugar_cache_put($cache_key, $return_value);
891 return $return_value;
895 * The dropdown items in custom language files is $app_list_strings['$key']['$second_key'] = $value not
896 * $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.
897 * @param file string the language that you want include,
898 * @param app_list_strings array the golbal strings
902 function _mergeCustomAppListStrings($file , $app_list_strings){
903 $app_list_strings_original = $app_list_strings;
904 unset($app_list_strings);
905 // FG - bug 45525 - $exemptDropdown array is defined (once) here, not inside the foreach
906 // This way, language file can add items to save specific standard codelist from being overwritten
907 $exemptDropdowns = array();
909 if(!isset($app_list_strings) || !is_array($app_list_strings)){
910 return $app_list_strings_original;
912 //Bug 25347: We should not merge custom dropdown fields unless they relate to parent fields or the module list.
914 // FG - bug 45525 - Specific codelists must NOT be overwritten
915 $exemptDropdowns[] = "moduleList";
916 $exemptDropdowns[] = "moduleListSingular";
917 $exemptDropdowns = array_merge($exemptDropdowns, getTypeDisplayList());
919 foreach($app_list_strings as $key=>$value)
921 if (!in_array($key, $exemptDropdowns) && array_key_exists($key, $app_list_strings_original))
923 unset($app_list_strings_original["$key"]);
926 $app_list_strings = sugarArrayMergeRecursive($app_list_strings_original , $app_list_strings);
927 return $app_list_strings;
931 * This function retrieves an application language file and returns the array of strings included.
933 * @param string $language specific language to load
934 * @return array lang strings
936 function return_application_language($language)
938 global $app_strings, $sugar_config;
940 $cache_key = 'app_strings.'.$language;
942 // Check for cached value
943 $cache_entry = sugar_cache_retrieve($cache_key);
944 if(!empty($cache_entry))
949 $temp_app_strings = $app_strings;
950 $default_language = $sugar_config['default_language'];
953 if ($language != 'en_us') {
956 if ($default_language != 'en_us' && $language != $default_language) {
957 $langs[] = $default_language;
960 $langs[] = $language;
962 $app_strings_array = array();
964 foreach ( $langs as $lang ) {
965 $app_strings = array();
966 if(file_exists("include/language/$lang.lang.php")) {
967 include("include/language/$lang.lang.php");
968 $GLOBALS['log']->info("Found language file: $lang.lang.php");
970 if(file_exists("include/language/$lang.lang.override.php")) {
971 include("include/language/$lang.lang.override.php");
972 $GLOBALS['log']->info("Found override language file: $lang.lang.override.php");
974 if(file_exists("include/language/$lang.lang.php.override")) {
975 include("include/language/$lang.lang.php.override");
976 $GLOBALS['log']->info("Found override language file: $lang.lang.php.override");
978 if(file_exists("custom/application/Ext/Language/$lang.lang.ext.php")) {
979 include("custom/application/Ext/Language/$lang.lang.ext.php");
980 $GLOBALS['log']->info("Found extended language file: $lang.lang.ext.php");
982 if(file_exists("custom/include/language/$lang.lang.php")) {
983 include("custom/include/language/$lang.lang.php");
984 $GLOBALS['log']->info("Found custom language file: $lang.lang.php");
986 $app_strings_array[] = $app_strings;
989 $app_strings = array();
990 foreach ( $app_strings_array as $app_strings_item ) {
991 $app_strings = sugarLangArrayMerge($app_strings, $app_strings_item);
994 if(!isset($app_strings)) {
995 $GLOBALS['log']->fatal("Unable to load the application language strings");
999 // If we are in debug mode for translating, turn on the prefix now!
1000 if(!empty($sugar_config['translation_string_prefix']))
1002 foreach($app_strings as $entry_key=>$entry_value) {
1003 $app_strings[$entry_key] = $language.' '.$entry_value;
1006 if(isset($_SESSION['show_deleted'])) {
1007 $app_strings['LBL_DELETE_BUTTON'] = $app_strings['LBL_UNDELETE_BUTTON'];
1008 $app_strings['LBL_DELETE_BUTTON_LABEL'] = $app_strings['LBL_UNDELETE_BUTTON_LABEL'];
1009 $app_strings['LBL_DELETE_BUTTON_TITLE'] = $app_strings['LBL_UNDELETE_BUTTON_TITLE'];
1010 $app_strings['LBL_DELETE'] = $app_strings['LBL_UNDELETE'];
1013 $app_strings['LBL_ALT_HOT_KEY'] = get_alt_hot_key();
1015 $return_value = $app_strings;
1016 $app_strings = $temp_app_strings;
1018 sugar_cache_put($cache_key, $return_value);
1020 return $return_value;
1024 * This function retrieves a module's language file and returns the array of strings included.
1026 * @param string $language specific language to load
1027 * @param string $module module name to load strings for
1028 * @param bool $refresh optional, true if you want to rebuild the language strings
1029 * @return array lang strings
1031 function return_module_language($language, $module, $refresh=false)
1033 global $mod_strings;
1034 global $sugar_config;
1035 global $currentModule;
1037 // Jenny - Bug 8119: Need to check if $module is not empty
1038 if (empty($module)) {
1039 $stack = debug_backtrace();
1040 $GLOBALS['log']->warn("Variable module is not in return_module_language ". var_export($stack, true));
1046 $cache_key = LanguageManager::getLanguageCacheKey($module, $language);
1047 // Check for cached value
1048 $cache_entry = sugar_cache_retrieve($cache_key);
1049 if(!empty($cache_entry) && is_array($cache_entry))
1051 return $cache_entry;
1054 // Store the current mod strings for later
1055 $temp_mod_strings = $mod_strings;
1056 $loaded_mod_strings = array();
1057 $language_used = $language;
1058 $default_language = $sugar_config['default_language'];
1060 if(empty($language)) {
1061 $language = $default_language;
1064 // Bug 21559 - So we can get all the strings defined in the template, refresh
1065 // the vardefs file if the cached language file doesn't exist.
1066 if(!file_exists(sugar_cached('modules/'). $module . '/language/'.$language.'.lang.php')
1067 && !empty($GLOBALS['beanList'][$module])){
1068 $object = BeanFactory::getObjectName($module);
1069 VardefManager::refreshVardefs($module,$object);
1072 $loaded_mod_strings = LanguageManager::loadModuleLanguage($module, $language,$refresh);
1074 // cn: bug 6048 - merge en_us with requested language
1075 if($language != $sugar_config['default_language'])
1076 $loaded_mod_strings = sugarLangArrayMerge(
1077 LanguageManager::loadModuleLanguage($module, $sugar_config['default_language'],$refresh),
1081 // Load in en_us strings by default
1082 if($language != 'en_us' && $sugar_config['default_language'] != 'en_us')
1083 $loaded_mod_strings = sugarLangArrayMerge(
1084 LanguageManager::loadModuleLanguage($module, 'en_us', $refresh),
1088 // If we are in debug mode for translating, turn on the prefix now!
1089 if($sugar_config['translation_string_prefix']) {
1090 foreach($loaded_mod_strings as $entry_key=>$entry_value) {
1091 $loaded_mod_strings[$entry_key] = $language_used.' '.$entry_value;
1095 $return_value = $loaded_mod_strings;
1096 if(!isset($mod_strings)){
1097 $mod_strings = $return_value;
1100 $mod_strings = $temp_mod_strings;
1102 $cache_key = LanguageManager::getLanguageCacheKey($module, $language);
1103 sugar_cache_put($cache_key, $return_value);
1104 return $return_value;
1108 /** This function retrieves an application language file and returns the array of strings included in the $mod_list_strings var.
1109 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1110 * All Rights Reserved.
1111 * Contributor(s): ______________________________________..
1112 * If you are using the current language, do not call this function unless you are loading it for the first time */
1113 function return_mod_list_strings_language($language,$module) {
1114 global $mod_list_strings;
1115 global $sugar_config;
1116 global $currentModule;
1118 $cache_key = "mod_list_str_lang.".$language.$module;
1120 // Check for cached value
1121 $cache_entry = sugar_cache_retrieve($cache_key);
1122 if(!empty($cache_entry))
1124 return $cache_entry;
1127 $language_used = $language;
1128 $temp_mod_list_strings = $mod_list_strings;
1129 $default_language = $sugar_config['default_language'];
1131 if($currentModule == $module && isset($mod_list_strings) && $mod_list_strings != null) {
1132 return $mod_list_strings;
1135 // cn: bug 6351 - include en_us if file langpack not available
1136 // cn: bug 6048 - merge en_us with requested language
1137 include("modules/$module/language/en_us.lang.php");
1138 $en_mod_list_strings = array();
1139 if($language_used != $default_language)
1140 $en_mod_list_strings = $mod_list_strings;
1142 if(file_exists("modules/$module/language/$language.lang.php")) {
1143 include("modules/$module/language/$language.lang.php");
1146 if(file_exists("modules/$module/language/$language.lang.override.php")){
1147 include("modules/$module/language/$language.lang.override.php");
1150 if(file_exists("modules/$module/language/$language.lang.php.override")){
1151 echo 'Please Change:<br>' . "modules/$module/language/$language.lang.php.override" . '<br>to<br>' . 'Please Change:<br>' . "modules/$module/language/$language.lang.override.php";
1152 include("modules/$module/language/$language.lang.php.override");
1155 // cn: bug 6048 - merge en_us with requested language
1156 $mod_list_strings = sugarLangArrayMerge($en_mod_list_strings, $mod_list_strings);
1158 // if we still don't have a language pack, then log an error
1159 if(!isset($mod_list_strings)) {
1160 $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})");
1164 $return_value = $mod_list_strings;
1165 $mod_list_strings = $temp_mod_list_strings;
1167 sugar_cache_put($cache_key, $return_value);
1168 return $return_value;
1172 /** This function retrieves a theme's language file and returns the array of strings included.
1173 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1174 * All Rights Reserved.
1175 * Contributor(s): ______________________________________..
1177 function return_theme_language($language, $theme)
1179 global $mod_strings, $sugar_config, $current_language;
1181 $language_used = $language;
1182 $default_language = $sugar_config['default_language'];
1184 include(SugarThemeRegistry::get($theme)->getFilePath()."/language/$current_language.lang.php");
1185 if(file_exists(SugarThemeRegistry::get($theme)->getFilePath()."/language/$current_language.lang.override.php")){
1186 include(SugarThemeRegistry::get($theme)->getFilePath()."/language/$current_language.lang.override.php");
1188 if(file_exists(SugarThemeRegistry::get($theme)->getFilePath()."/language/$current_language.lang.php.override")){
1189 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";
1190 include(SugarThemeRegistry::get($theme)->getFilePath()."/language/$current_language.lang.php.override");
1192 if(!isset($theme_strings))
1194 $GLOBALS['log']->warn("Unable to find the theme file for language: ".$language." and theme: ".$theme);
1195 require(SugarThemeRegistry::get($theme)->getFilePath()."/language/$default_language.lang.php");
1196 $language_used = $default_language;
1199 if(!isset($theme_strings))
1201 $GLOBALS['log']->fatal("Unable to load the theme($theme) language file for the selected language($language) or the default language($default_language)");
1205 // If we are in debug mode for translating, turn on the prefix now!
1206 if($sugar_config['translation_string_prefix'])
1208 foreach($theme_strings as $entry_key=>$entry_value)
1210 $theme_strings[$entry_key] = $language_used.' '.$entry_value;
1214 return $theme_strings;
1219 /** If the session variable is defined and is not equal to "" then return it. Otherwise, return the default value.
1220 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1221 * All Rights Reserved.
1222 * Contributor(s): ______________________________________..
1224 function return_session_value_or_default($varname, $default)
1226 if(isset($_SESSION[$varname]) && $_SESSION[$varname] != "")
1228 return $_SESSION[$varname];
1235 * Creates an array of where restrictions. These are used to construct a where SQL statement on the query
1236 * 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.
1237 * @param &$where_clauses - The array to append the clause to
1238 * @param $variable_name - The name of the variable to look for an add to the where clause if found
1239 * @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.
1240 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1241 * All Rights Reserved.
1242 * Contributor(s): ______________________________________..
1244 function append_where_clause(&$where_clauses, $variable_name, $SQL_name = null)
1246 if($SQL_name == null)
1248 $SQL_name = $variable_name;
1251 if(isset($_REQUEST[$variable_name]) && $_REQUEST[$variable_name] != "")
1253 array_push($where_clauses, "$SQL_name like '".$GLOBALS['db']->quote($_REQUEST[$variable_name])."%'");
1258 * Generate the appropriate SQL based on the where clauses.
1259 * @param $where_clauses - An Array of individual where clauses stored as strings
1260 * @returns string where_clause - The final SQL where clause to be executed.
1261 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1262 * All Rights Reserved.
1263 * Contributor(s): ______________________________________..
1265 function generate_where_statement($where_clauses)
1268 foreach($where_clauses as $clause)
1275 $GLOBALS['log']->info("Here is the where clause for the list view: $where");
1280 * determines if a passed string matches the criteria for a Sugar GUID
1281 * @param string $guid
1282 * @return bool False on failure
1284 function is_guid($guid) {
1285 if(strlen($guid) != 36) {
1289 if(preg_match("/\w{8}-\w{4}-\w{4}-\w{4}-\w{12}/i", $guid)) {
1298 * A temporary method of generating GUIDs of the correct format for our DB.
1299 * @return String contianing a GUID in the format: aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
1301 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1302 * All Rights Reserved.
1303 * Contributor(s): ______________________________________..
1305 function create_guid()
1307 $microTime = microtime();
1308 list($a_dec, $a_sec) = explode(" ", $microTime);
1310 $dec_hex = dechex($a_dec* 1000000);
1311 $sec_hex = dechex($a_sec);
1313 ensure_length($dec_hex, 5);
1314 ensure_length($sec_hex, 6);
1318 $guid .= create_guid_section(3);
1320 $guid .= create_guid_section(4);
1322 $guid .= create_guid_section(4);
1324 $guid .= create_guid_section(4);
1327 $guid .= create_guid_section(6);
1333 function create_guid_section($characters)
1336 for($i=0; $i<$characters; $i++)
1338 $return .= dechex(mt_rand(0,15));
1343 function ensure_length(&$string, $length)
1345 $strlen = strlen($string);
1346 if($strlen < $length)
1348 $string = str_pad($string,$length,"0");
1350 else if($strlen > $length)
1352 $string = substr($string, 0, $length);
1356 function microtime_diff($a, $b) {
1357 list($a_dec, $a_sec) = explode(" ", $a);
1358 list($b_dec, $b_sec) = explode(" ", $b);
1359 return $b_sec - $a_sec + $b_dec - $a_dec;
1362 // check if Studio is displayed.
1363 function displayStudioForCurrentUser()
1365 global $current_user;
1366 if ( $current_user->isAdmin() ) {
1376 function displayWorkflowForCurrentUser()
1378 $_SESSION['display_workflow_for_user'] = false;
1382 // return an array with all modules where the user is an admin.
1383 function get_admin_modules_for_user($user) {
1384 $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");
1391 return($user->getDeveloperModules());
1395 function get_workflow_admin_modules_for_user($user){
1396 if (isset($_SESSION['get_workflow_admin_modules_for_user'])) {
1397 return $_SESSION['get_workflow_admin_modules_for_user'];
1401 $workflow_mod_list = array();
1402 foreach($moduleList as $module){
1403 $workflow_mod_list[$module] = $module;
1406 // This list is taken from teh previous version of workflow_utils.php
1407 $workflow_mod_list['Tasks'] = "Tasks";
1408 $workflow_mod_list['Calls'] = "Calls";
1409 $workflow_mod_list['Meetings'] = "Meetings";
1410 $workflow_mod_list['Notes'] = "Notes";
1411 $workflow_mod_list['ProjectTask'] = "Project Tasks";
1412 $workflow_mod_list['Leads'] = "Leads";
1413 $workflow_mod_list['Opportunities'] = "Opportunities";
1416 $workflow_admin_modules = array();
1418 return $workflow_admin_modules;
1420 $actions = ACLAction::getUserActions($user->id);
1421 //check for ForecastSchedule because it doesn't exist in $workflow_mod_list
1422 if (isset($actions['ForecastSchedule']['module']['admin']['aclaccess']) && ($actions['ForecastSchedule']['module']['admin']['aclaccess']==ACL_ALLOW_DEV ||
1423 $actions['ForecastSchedule']['module']['admin']['aclaccess']==ACL_ALLOW_ADMIN_DEV)) {
1424 $workflow_admin_modules['Forecasts'] = 'Forecasts';
1426 foreach ($workflow_mod_list as $key=>$val) {
1427 if(!in_array($val, $workflow_admin_modules) && ($val!='iFrames' && $val!='Feeds' && $val!='Home' && $val!='Dashboard'
1428 && $val!='Calendar' && $val!='Activities' && $val!='Reports') &&
1429 ($user->isDeveloperForModule($key))) {
1430 $workflow_admin_modules[$key] = $val;
1433 $_SESSION['get_workflow_admin_modules_for_user'] = $workflow_admin_modules;
1434 return ($workflow_admin_modules);
1437 // Check if user is admin for at least one module.
1438 function is_admin_for_any_module($user) {
1442 if($user->isAdmin()) {
1449 // Check if user is admin for a specific module.
1450 function is_admin_for_module($user,$module) {
1451 if (!isset($user)) {
1454 if ($user->isAdmin()) {
1462 * Check if user id belongs to a system admin.
1463 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1464 * All Rights Reserved.
1465 * Contributor(s): ______________________________________..
1467 function is_admin($user) {
1472 return $user->isAdmin();
1476 * Return the display name for a theme if it exists.
1477 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1478 * All Rights Reserved.
1479 * Contributor(s): ______________________________________..
1481 * @deprecated use SugarThemeRegistry::get($theme)->name instead
1483 function get_theme_display($theme)
1485 return SugarThemeRegistry::get($theme)->name;
1489 * Return an array of directory names.
1490 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1491 * All Rights Reserved.
1492 * Contributor(s): ______________________________________..
1494 * @deprecated use SugarThemeRegistry::availableThemes() instead.
1496 function get_themes()
1498 return SugarThemeRegistry::availableThemes();
1502 * THIS FUNCTION IS DEPRECATED AND SHOULD NOT BE USED; USE get_select_options_with_id()
1503 * Create HTML to display select options in a dropdown list. To be used inside
1504 * of a select statement in a form.
1505 * param $option_list - the array of strings to that contains the option list
1506 * param $selected - the string which contains the default value
1507 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1508 * All Rights Reserved.
1509 * Contributor(s): ______________________________________..
1511 function get_select_options ($option_list, $selected) {
1512 return get_select_options_with_id($option_list, $selected);
1516 * Create HTML to display select options in a dropdown list. To be used inside
1517 * 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.
1518 * param $option_list - the array of strings to that contains the option list
1519 * param $selected - the string which contains the default value
1520 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1521 * All Rights Reserved.
1522 * Contributor(s): ______________________________________..
1524 function get_select_options_with_id ($option_list, $selected_key) {
1525 return get_select_options_with_id_separate_key($option_list, $option_list, $selected_key);
1530 * Create HTML to display select options in a dropdown list. To be used inside
1531 * 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.
1532 * param $label_list - the array of strings to that contains the option list
1533 * param $key_list - the array of strings to that contains the values list
1534 * param $selected - the string which contains the default value
1535 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1536 * All Rights Reserved.
1537 * Contributor(s): ______________________________________..
1539 function get_select_options_with_id_separate_key ($label_list, $key_list, $selected_key, $massupdate=false) {
1540 global $app_strings;
1541 $select_options = "";
1543 //for setting null selection values to human readable --None--
1544 $pattern = "/'0?'></";
1545 $replacement = "''>".$app_strings['LBL_NONE']."<";
1547 $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
1550 if (empty($key_list)) $key_list = array();
1551 //create the type dropdown domain and set the selected value if $opp value already exists
1552 foreach ($key_list as $option_key=>$option_value) {
1554 $selected_string = '';
1555 // the system is evaluating $selected_key == 0 || '' to true. Be very careful when changing this. Test all cases.
1556 // The bug was only happening with one of the users in the drop down. It was being replaced by none.
1558 ($option_key != '' && $selected_key == $option_key)
1561 && (($selected_key == '' && !$massupdate) || $selected_key == '__SugarMassUpdateClearField__')
1563 || (is_array($selected_key) && in_array($option_key, $selected_key))
1565 $selected_string = 'selected ';
1568 $html_value = $option_key;
1570 $select_options .= "\n<OPTION ".$selected_string."value='$html_value'>$label_list[$option_key]</OPTION>";
1572 $select_options = preg_replace($pattern, $replacement, $select_options);
1573 return $select_options;
1578 * Call this method instead of die().
1579 * We print the error message and then die with an appropriate
1582 function sugar_die($error_message, $exit_code = 1)
1586 echo $error_message;
1592 * Create javascript to clear values of all elements in a form.
1593 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1594 * All Rights Reserved.
1595 * Contributor(s): ______________________________________..
1597 function get_clear_form_js () {
1598 $the_script = <<<EOQ
1599 <script type="text/javascript" language="JavaScript">
1600 function clear_form(form) {
1601 var newLoc = 'index.php?action=' + form.action.value + '&module=' + form.module.value + '&query=true&clear_query=true';
1602 if(typeof(form.advanced) != 'undefined'){
1603 newLoc += '&advanced=' + form.advanced.value;
1605 document.location.href= newLoc;
1614 * Create javascript to set the cursor focus to specific field in a form
1615 * when the screen is rendered. The field name is currently hardcoded into the
1617 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1618 * All Rights Reserved.
1619 * Contributor(s): ______________________________________..
1621 function get_set_focus_js () {
1622 //TODO Clint 5/20 - Make this function more generic so that it can take in the target form and field names as variables
1623 $the_script = <<<EOQ
1624 <script type="text/javascript" language="JavaScript">
1626 function set_focus() {
1627 if (document.forms.length > 0) {
1628 for (i = 0; i < document.forms.length; i++) {
1629 for (j = 0; j < document.forms[i].elements.length; j++) {
1630 var field = document.forms[i].elements[j];
1631 if ((field.type == "text" || field.type == "textarea" || field.type == "password") &&
1632 !field.disabled && (field.name == "first_name" || field.name == "name" || field.name == "user_name" || field.name=="document_name")) {
1634 if (field.type == "text") {
1651 * Very cool algorithm for sorting multi-dimensional arrays. Found at http://us2.php.net/manual/en/function.array-multisort.php
1652 * Syntax: $new_array = array_csort($array [, 'col1' [, SORT_FLAG [, SORT_FLAG]]]...);
1653 * Explanation: $array is the array you want to sort, 'col1' is the name of the column
1654 * you want to sort, SORT_FLAGS are : SORT_ASC, SORT_DESC, SORT_REGULAR, SORT_NUMERIC, SORT_STRING
1655 * you can repeat the 'col',FLAG,FLAG, as often you want, the highest prioritiy is given to
1656 * the first - so the array is sorted by the last given column first, then the one before ...
1657 * Example: $array = array_csort($array,'town','age',SORT_DESC,'name');
1658 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1659 * All Rights Reserved.
1660 * Contributor(s): ______________________________________..
1662 function array_csort() {
1663 $args = func_get_args();
1664 $marray = array_shift($args);
1667 $msortline = "return(array_multisort(";
1668 foreach ($args as $arg) {
1670 if (is_string($arg)) {
1671 foreach ($marray as $row) {
1672 $sortarr[$i][] = $row[$arg];
1675 $sortarr[$i] = $arg;
1677 $msortline .= "\$sortarr[".$i."],";
1679 $msortline .= "\$marray));";
1686 * Converts localized date format string to jscalendar format
1687 * Example: $array = array_csort($array,'town','age',SORT_DESC,'name');
1688 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1689 * All Rights Reserved.
1690 * Contributor(s): ______________________________________..
1692 function parse_calendardate($local_format) {
1693 preg_match('/\(?([^-]{1})[^-]*-([^-]{1})[^-]*-([^-]{1})[^-]*\)/', $local_format, $matches);
1694 $calendar_format = "%" . $matches[1] . "-%" . $matches[2] . "-%" . $matches[3];
1695 return str_replace(array("y", "ᅣ1�7", "a", "j"), array("Y", "Y", "Y", "d"), $calendar_format);
1702 function translate($string, $mod='', $selectedValue=''){
1703 //$test_start = microtime();
1704 //static $mod_strings_results = array();
1706 global $current_language;
1708 if(isset($_REQUEST['login_language'])){
1709 $current_language = ($_REQUEST['login_language'] == $current_language)? $current_language : $_REQUEST['login_language'];
1711 $mod_strings = return_module_language($current_language, $mod);
1713 echo "Language is <pre>" . $mod_strings . "</pre>";
1716 global $mod_strings;
1720 global $app_strings, $app_list_strings;
1722 if (isset($mod_strings[$string]))
1723 $returnValue = $mod_strings[$string];
1724 else if (isset($app_strings[$string]))
1725 $returnValue = $app_strings[$string];
1726 else if (isset($app_list_strings[$string]))
1727 $returnValue = $app_list_strings[$string];
1728 else if (isset($app_list_strings['moduleList']) && isset($app_list_strings['moduleList'][$string]))
1729 $returnValue = $app_list_strings['moduleList'][$string];
1732 //$test_end = microtime();
1734 // $mod_strings_results[$mod] = microtime_diff($test_start,$test_end);
1736 // echo("translate results:");
1738 // $total_strings = 0;
1739 // foreach($mod_strings_results as $key=>$value)
1741 // echo("Module $key \t\t time $value \t\t<br>");
1742 // $total_time += $value;
1745 // echo("Total time: $total_time<br>");
1749 if(empty($returnValue)){
1753 // Bug 48996 - Custom enums with '0' value were not returning because of empty check
1754 // Added a numeric 0 checker to the conditional to allow 0 value indexed to pass
1755 if(is_array($returnValue) && (!empty($selectedValue) || (is_numeric($selectedValue) && $selectedValue == 0)) && isset($returnValue[$selectedValue]) ){
1756 return $returnValue[$selectedValue];
1759 return $returnValue;
1762 function unTranslateNum($num) {
1764 static $num_grp_sep;
1765 global $current_user, $sugar_config;
1767 if($dec_sep == null) {
1768 $user_dec_sep = $current_user->getPreference('dec_sep');
1769 $dec_sep = (empty($user_dec_sep) ? $sugar_config['default_decimal_seperator'] : $user_dec_sep);
1771 if($num_grp_sep == null) {
1772 $user_num_grp_sep = $current_user->getPreference('num_grp_sep');
1773 $num_grp_sep = (empty($user_num_grp_sep) ? $sugar_config['default_number_grouping_seperator'] : $user_num_grp_sep);
1776 $num = preg_replace("'" . preg_quote($num_grp_sep) . "'", '', $num);
1777 $num = preg_replace("'" . preg_quote($dec_sep) . "'", '.', $num);
1782 function add_http($url) {
1783 if(!preg_match("@://@i", $url)) {
1785 if(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') {
1789 return "{$scheme}://{$url}";
1796 * returns a default array of XSS tags to clean
1799 function getDefaultXssTags() {
1801 "applet" => "applet",
1806 "frameset" => "frameset",
1807 "iframe" => "iframe",
1808 "import" => "\?import",
1811 "object" => "object",
1812 "script" => "script",
1816 $ret = base64_encode(serialize($tmp));
1822 * Remove potential xss vectors from strings
1823 * @param string str String to search for XSS attack vectors
1827 function remove_xss($str)
1829 return SugarCleaner::cleanHtml($str, false);
1833 * Detects typical XSS attack patterns
1835 * @param string str String to search for XSS attack vectors
1836 * @param bool cleanImg Flag to allow <img> tags to survive - only used by InboundEmail for inline images.
1837 * @return array Array of matches, empty on clean string
1839 function clean_xss($str, $cleanImg=true) {
1840 global $sugar_config;
1842 if(empty($sugar_config['email_xss']))
1843 $sugar_config['email_xss'] = getDefaultXssTags();
1845 $xsstags = unserialize(base64_decode($sugar_config['email_xss']));
1847 // cn: bug 13079 - "on\w" matched too many non-events (cONTact, strONG, etc.)
1848 $jsEvents = "onblur|onfocus|oncontextmenu|onresize|onscroll|onunload|ondblclick|onclick|";
1849 $jsEvents .= "onmouseup|onmouseover|onmousedown|onmouseenter|onmouseleave|onmousemove|onload|onchange|";
1850 $jsEvents .= "onreset|onselect|onsubmit|onkeydown|onkeypress|onkeyup|onabort|onerror|ondragdrop";
1852 $attribute_regex = "#\b({$jsEvents})\s*=\s*(?|(?!['\"])\S+|['\"].+?['\"])#sim";
1853 $javascript_regex = '@<[^/>][^>]+(expression\(|j\W*a\W*v\W*a|v\W*b\W*s\W*c\W*r|&#|/\*|\*/)[^>]*>@sim';
1854 $imgsrc_regex = '#<[^>]+src[^=]*=([^>]*?http(s)?://[^>]*)>#sim';
1855 $css_url = '#url\(.*\.\w+\)#';
1857 $tagsrex = '#<\/?(\w+)((?:\s+(?:\w|\w[\w-]*\w)(?:\s*=\s*(?:\".*?\"|\'.*?\'|[^\'\">\s]+))?)+\s*|\s*)\/?>#im';
1859 $tagmatches = array();
1861 preg_match_all($tagsrex, $str, $tagmatches, PREG_PATTERN_ORDER);
1862 foreach($tagmatches[1] as $no => $tag) {
1863 if(in_array($tag, $xsstags)) {
1864 // dangerous tag - take out whole
1865 $matches[] = $tagmatches[0][$no];
1868 $attrmatch = array();
1869 preg_match_all($attribute_regex, $tagmatches[2][$no], $attrmatch, PREG_PATTERN_ORDER);
1870 if(!empty($attrmatch[0])) {
1871 $matches = array_merge($matches, $attrmatch[0]);
1875 $matches = array_merge($matches, xss_check_pattern($javascript_regex, $str));
1878 $matches = array_merge($matches,
1879 xss_check_pattern($imgsrc_regex, $str)
1883 // cn: bug 13498 - custom white-list of allowed domains that vet remote images
1884 preg_match_all($css_url, $str, $cssUrlMatches, PREG_PATTERN_ORDER);
1886 if(isset($sugar_config['security_trusted_domains']) && !empty($sugar_config['security_trusted_domains']) && is_array($sugar_config['security_trusted_domains'])) {
1887 if(is_array($cssUrlMatches) && count($cssUrlMatches) > 0) {
1888 // normalize whitelist
1889 foreach($sugar_config['security_trusted_domains'] as $k => $v) {
1890 $sugar_config['security_trusted_domains'][$k] = strtolower($v);
1893 foreach($cssUrlMatches[0] as $match) {
1894 $domain = strtolower(substr(strstr($match, "://"), 3));
1895 $baseUrl = substr($domain, 0, strpos($domain, "/"));
1897 if(!in_array($baseUrl, $sugar_config['security_trusted_domains'])) {
1898 $matches[] = $match;
1903 $matches = array_merge($matches, $cssUrlMatches[0]);
1910 * Helper function used by clean_xss() to parse for known-bad vectors
1911 * @param string pattern Regex pattern to use
1912 * @param string str String to parse for badness
1915 function xss_check_pattern($pattern, $str) {
1916 preg_match_all($pattern, $str, $matches, PREG_PATTERN_ORDER);
1921 * Designed to take a string passed in the URL as a parameter and clean all "bad" data from it
1923 * @param string $str
1924 * @param string $filter which corresponds to a regular expression to use; choices are:
1925 * "STANDARD" ( default )
1935 * @param boolean $dieOnBadData true (default) if you want to die if bad data if found, false if not
1937 function clean_string($str, $filter = "STANDARD", $dieOnBadData = true)
1939 global $sugar_config;
1942 "STANDARD" => '#[^A-Z0-9\-_\.\@]#i',
1943 "STANDARDSPACE" => '#[^A-Z0-9\-_\.\@\ ]#i',
1944 "FILE" => '#[^A-Z0-9\-_\.]#i',
1945 "NUMBER" => '#[^0-9\-]#i',
1946 "SQL_COLUMN_LIST" => '#[^A-Z0-9\(\),_\.]#i',
1947 "PATH_NO_URL" => '#://#i',
1948 "SAFED_GET" => '#[^A-Z0-9\@\=\&\?\.\/\-_~+]#i', /* range of allowed characters in a GET string */
1949 "UNIFIED_SEARCH" => "#[\\x00]#", /* cn: bug 3356 & 9236 - MBCS search strings */
1950 "AUTO_INCREMENT" => '#[^0-9\-,\ ]#i',
1951 "ALPHANUM" => '#[^A-Z0-9\-]#i',
1954 if (preg_match($filters[$filter], $str)) {
1955 if (isset($GLOBALS['log']) && is_object($GLOBALS['log'])) {
1956 $GLOBALS['log']->fatal("SECURITY[$filter]: bad data passed in; string: {$str}");
1958 if ( $dieOnBadData ) {
1959 die("Bad data passed in; <a href=\"{$sugar_config['site_url']}\">Return to Home</a>");
1968 function clean_special_arguments() {
1969 if(isset($_SERVER['PHP_SELF'])) {
1970 if (!empty($_SERVER['PHP_SELF'])) clean_string($_SERVER['PHP_SELF'], 'SAFED_GET');
1972 if (!empty($_REQUEST) && !empty($_REQUEST['login_theme'])) clean_string($_REQUEST['login_theme'], "STANDARD");
1973 if (!empty($_REQUEST) && !empty($_REQUEST['login_module'])) clean_string($_REQUEST['login_module'], "STANDARD");
1974 if (!empty($_REQUEST) && !empty($_REQUEST['login_action'])) clean_string($_REQUEST['login_action'], "STANDARD");
1975 if (!empty($_REQUEST) && !empty($_REQUEST['ck_login_theme_20'])) clean_string($_REQUEST['ck_login_theme_20'], "STANDARD");
1976 if (!empty($_SESSION) && !empty($_SESSION['authenticated_user_theme'])) clean_string($_SESSION['authenticated_user_theme'], "STANDARD");
1977 if (!empty($_REQUEST) && !empty($_REQUEST['module_name'])) clean_string($_REQUEST['module_name'], "STANDARD");
1978 if (!empty($_REQUEST) && !empty($_REQUEST['module'])) clean_string($_REQUEST['module'], "STANDARD");
1979 if (!empty($_POST) && !empty($_POST['parent_type'])) clean_string($_POST['parent_type'], "STANDARD");
1980 if (!empty($_REQUEST) && !empty($_REQUEST['mod_lang'])) clean_string($_REQUEST['mod_lang'], "STANDARD");
1981 if (!empty($_SESSION) && !empty($_SESSION['authenticated_user_language'])) clean_string($_SESSION['authenticated_user_language'], "STANDARD");
1982 if (!empty($_SESSION) && !empty($_SESSION['dyn_layout_file'])) clean_string($_SESSION['dyn_layout_file'], "PATH_NO_URL");
1983 if (!empty($_GET) && !empty($_GET['from'])) clean_string($_GET['from']);
1984 if (!empty($_GET) && !empty($_GET['gmto'])) clean_string($_GET['gmto'], "NUMBER");
1985 if (!empty($_GET) && !empty($_GET['case_number'])) clean_string($_GET['case_number'], "AUTO_INCREMENT");
1986 if (!empty($_GET) && !empty($_GET['bug_number'])) clean_string($_GET['bug_number'], "AUTO_INCREMENT");
1987 if (!empty($_GET) && !empty($_GET['quote_num'])) clean_string($_GET['quote_num'], "AUTO_INCREMENT");
1988 clean_superglobals('stamp', 'ALPHANUM'); // for vcr controls
1989 clean_superglobals('offset', 'ALPHANUM');
1990 clean_superglobals('return_action');
1991 clean_superglobals('return_module');
1996 * cleans the given key in superglobals $_GET, $_POST, $_REQUEST
1998 function clean_superglobals($key, $filter = 'STANDARD') {
1999 if(isset($_GET[$key])) clean_string($_GET[$key], $filter);
2000 if(isset($_POST[$key])) clean_string($_POST[$key], $filter);
2001 if(isset($_REQUEST[$key])) clean_string($_REQUEST[$key], $filter);
2004 function set_superglobals($key, $val){
2006 $_POST[$key] = $val;
2007 $_REQUEST[$key] = $val;
2010 // Works in conjunction with clean_string() to defeat SQL injection, file inclusion attacks, and XSS
2011 function clean_incoming_data() {
2012 global $sugar_config;
2013 global $RAW_REQUEST;
2015 if(get_magic_quotes_gpc()) {
2016 // magic quotes screw up data, we'd have to clean up
2017 $RAW_REQUEST = array_map("cleanup_slashes", $_REQUEST);
2019 $RAW_REQUEST = $_REQUEST;
2022 if (get_magic_quotes_gpc() == 1) {
2023 $req = array_map("preprocess_param", $_REQUEST);
2024 $post = array_map("preprocess_param", $_POST);
2025 $get = array_map("preprocess_param", $_GET);
2028 $req = array_map("securexss", $_REQUEST);
2029 $post = array_map("securexss", $_POST);
2030 $get = array_map("securexss", $_GET);
2033 // PHP cannot stomp out superglobals reliably
2034 foreach($post as $k => $v) { $_POST[$k] = $v; }
2035 foreach($get as $k => $v) { $_GET[$k] = $v; }
2036 foreach($req as $k => $v) {
2039 //ensure the keys are safe as well. If mbstring encoding translation is on, the post keys don't
2040 //get translated, so scrub the data but don't die
2041 if(ini_get('mbstring.encoding_translation')==='1'){
2042 securexsskey($k,false);
2044 securexsskey($k,true);
2048 // Any additional variables that need to be cleaned should be added here
2049 if (isset($_REQUEST['login_theme'])) clean_string($_REQUEST['login_theme']);
2050 if (isset($_REQUEST['login_module'])) clean_string($_REQUEST['login_module']);
2051 if (isset($_REQUEST['login_action'])) clean_string($_REQUEST['login_action']);
2052 if (isset($_REQUEST['login_language'])) clean_string($_REQUEST['login_language']);
2053 if (isset($_REQUEST['action'])) clean_string($_REQUEST['action']);
2054 if (isset($_REQUEST['module'])) clean_string($_REQUEST['module']);
2055 if (isset($_REQUEST['record'])) clean_string($_REQUEST['record'], 'STANDARDSPACE');
2056 if (isset($_SESSION['authenticated_user_theme'])) clean_string($_SESSION['authenticated_user_theme']);
2057 if (isset($_SESSION['authenticated_user_language'])) clean_string($_SESSION['authenticated_user_language']);
2058 if (isset($_REQUEST['language'])) clean_string($_REQUEST['language']);
2059 if (isset($sugar_config['default_theme'])) clean_string($sugar_config['default_theme']);
2060 if (isset($_REQUEST['offset'])) clean_string($_REQUEST['offset']);
2061 if (isset($_REQUEST['stamp'])) clean_string($_REQUEST['stamp']);
2063 if(isset($_REQUEST['lvso'])){
2064 set_superglobals('lvso', (strtolower($_REQUEST['lvso']) === 'desc')?'desc':'asc');
2066 // Clean "offset" and "order_by" parameters in URL
2067 foreach ($_REQUEST as $key => $val) {
2068 if (str_end($key, "_offset")) {
2069 clean_string($_REQUEST[$key], "ALPHANUM"); // keep this ALPHANUM for disable_count_query
2070 set_superglobals($key, $_REQUEST[$key]);
2072 elseif (str_end($key, "_ORDER_BY")) {
2073 clean_string($_REQUEST[$key], "SQL_COLUMN_LIST");
2074 set_superglobals($key, $_REQUEST[$key]);
2082 // Returns TRUE if $str begins with $begin
2083 function str_begin($str, $begin) {
2084 return (substr($str, 0, strlen($begin)) == $begin);
2087 // Returns TRUE if $str ends with $end
2088 function str_end($str, $end) {
2089 return (substr($str, strlen($str) - strlen($end)) == $end);
2092 function securexss($value) {
2093 if(is_array($value)){
2095 foreach($value as $key=>$val){
2096 $new[$key] = securexss($val);
2100 static $xss_cleanup= array(""" => "&", '"' =>'"', "'" => ''' , '<' =>'<' , '>'=>'>');
2101 $value = preg_replace(array('/javascript:/i', '/\0/'), array('java script:', ''), $value);
2102 $value = preg_replace('/javascript:/i', 'java script:', $value);
2103 return str_replace(array_keys($xss_cleanup), array_values($xss_cleanup), $value);
2106 function securexsskey($value, $die=true){
2107 global $sugar_config;
2109 preg_match('/[\'"<>]/', $value, $matches);
2110 if(!empty($matches)){
2112 die("Bad data passed in; <a href=\"{$sugar_config['site_url']}\">Return to Home</a>");
2114 unset($_REQUEST[$value]);
2115 unset($_POST[$value]);
2116 unset($_GET[$value]);
2121 function preprocess_param($value){
2122 if(is_string($value)){
2123 if(get_magic_quotes_gpc() == 1){
2124 $value = stripslashes($value);
2127 $value = securexss($value);
2129 else if (is_array($value)){
2130 foreach ($value as $key => $element) {
2131 $value[$key] = preprocess_param($element);
2138 function cleanup_slashes($value)
2140 if(is_string($value)) return stripslashes($value);
2145 function set_register_value($category, $name, $value){
2146 return sugar_cache_put("{$category}:{$name}", $value);
2149 function get_register_value($category,$name){
2150 return sugar_cache_retrieve("{$category}:{$name}");
2153 function clear_register_value($category,$name){
2154 return sugar_cache_clear("{$category}:{$name}");
2156 // this function cleans id's when being imported
2157 function convert_id($string)
2159 return preg_replace_callback( '|[^A-Za-z0-9\-]|',
2161 // single quotes are essential here,
2162 // or alternative escape all $ as \$
2164 'return ord($matches[0]);'
2169 * @deprecated use SugarTheme::getImage()
2171 function get_image($image,$other_attributes,$width="",$height="",$ext='.gif',$alt="")
2173 return SugarThemeRegistry::current()->getImage(basename($image), $other_attributes, empty($width) ? null : $width, empty($height) ? null : $height, $ext, $alt );
2176 * @deprecated use SugarTheme::getImageURL()
2178 function getImagePath($image_name)
2180 return SugarThemeRegistry::current()->getImageURL($image_name);
2183 function getWebPath($relative_path){
2184 //if it has a :// then it isn't a relative path
2185 if(substr_count($relative_path, '://') > 0) return $relative_path;
2186 if(defined('TEMPLATE_URL'))$relative_path = SugarTemplateUtilities::getWebPath($relative_path);
2187 return $relative_path;
2190 function getVersionedPath($path, $additional_attrs='')
2192 if(empty($GLOBALS['sugar_config']['js_custom_version'])) $GLOBALS['sugar_config']['js_custom_version'] = 1;
2193 $js_version_key = isset($GLOBALS['js_version_key'])?$GLOBALS['js_version_key']:'';
2194 if(inDeveloperMode()) {
2196 if(empty($rand)) $rand = mt_rand();
2201 if(is_array($additional_attrs)) {
2202 $additional_attrs = join("|",$additional_attrs);
2204 // cutting 2 last chars here because since md5 is 32 chars, it's always ==
2205 $str = substr(base64_encode(md5("$js_version_key|{$GLOBALS['sugar_config']['js_custom_version']}|$dev|$additional_attrs", true)), 0, -2);
2206 // remove / - it confuses some parsers
2207 $str = strtr($str, '/+', '-_');
2208 if(empty($path)) return $str;
2210 return $path . "?v=$str";
2213 function getVersionedScript($path, $additional_attrs='')
2215 return '<script type="text/javascript" src="'.getVersionedPath($path, $additional_attrs).'"></script>';
2218 function getJSPath($relative_path, $additional_attrs='')
2220 if(defined('TEMPLATE_URL'))$relative_path = SugarTemplateUtilities::getWebPath($relative_path);
2221 return getVersionedPath($relative_path).(!empty($additional_attrs)?"&$additional_attrs":"");
2224 function getSWFPath($relative_path, $additional_params=''){
2225 $path = $relative_path;
2226 if (!empty($additional_params)){
2227 $path .= '?' . $additional_params;
2229 if (defined('TEMPLATE_URL')){
2230 $path = TEMPLATE_URL . '/' . $path;
2239 function getSQLDate($date_str)
2241 if (preg_match('/^(\d{1,2})-(\d{1,2})-(\d{4})$/',$date_str,$match))
2243 if ( strlen($match[2]) == 1)
2245 $match[2] = "0".$match[2];
2247 if ( strlen($match[1]) == 1)
2249 $match[1] = "0".$match[1];
2251 return "{$match[3]}-{$match[1]}-{$match[2]}";
2253 else if (preg_match('/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/',$date_str,$match))
2255 if ( strlen($match[2]) == 1)
2257 $match[2] = "0".$match[2];
2259 if ( strlen($match[1]) == 1)
2261 $match[1] = "0".$match[1];
2263 return "{$match[3]}-{$match[1]}-{$match[2]}";
2271 function clone_history(&$db, $from_id,$to_id, $to_type)
2276 require_once('include/upload_file.php');
2277 $tables = array('calls'=>'Call', 'meetings'=>'Meeting', 'notes'=>'Note', 'tasks'=>'Task');
2279 $location=array('Email'=>"modules/Emails/Email.php",
2280 'Call'=>"modules/Calls/Call.php",
2281 'Meeting'=>"modules/Meetings/Meeting.php",
2282 'Note'=>"modules/Notes/Note.php",
2283 'Tasks'=>"modules/Tasks/Task.php",
2287 foreach($tables as $table=>$bean_class)
2290 if (!class_exists($bean_class))
2292 require_once($location[$bean_class]);
2295 $bProcessingNotes=false;
2296 if ($table=='notes')
2298 $bProcessingNotes=true;
2300 $query = "SELECT id FROM $table WHERE parent_id='$from_id'";
2301 $results = $db->query($query);
2302 while($row = $db->fetchByAssoc($results))
2304 //retrieve existing record.
2305 $bean= new $bean_class();
2306 $bean->retrieve($row['id']);
2307 //process for new instance.
2308 if ($bProcessingNotes)
2310 $old_note_id=$row['id'];
2311 $old_filename=$bean->filename;
2314 $bean->parent_id=$to_id;
2315 $bean->parent_type=$to_type;
2316 if ($to_type=='Contacts' and in_array('contact_id',$bean->column_fields))
2318 $bean->contact_id=$to_id;
2320 $bean->update_date_modified = false;
2321 $bean->update_modified_by = false;
2322 if(isset($bean->date_modified))
2323 $bean->date_modified = $timedate->to_db($bean->date_modified);
2324 if(isset($bean->date_entered))
2325 $bean->date_entered = $timedate->to_db($bean->date_entered);
2327 $new_id=$bean->save();
2329 //duplicate the file now. for notes.
2330 if ($bProcessingNotes && !empty($old_filename))
2332 UploadFile::duplicate_file($old_note_id,$new_id,$old_filename);
2334 //reset the values needed for attachment duplication.
2341 function values_to_keys($array)
2343 $new_array = array();
2344 if(!is_array($array))
2348 foreach($array as $arr){
2349 $new_array[$arr] = $arr;
2354 function clone_relationship(&$db, $tables = array(), $from_column, $from_id, $to_id)
2356 foreach($tables as $table)
2359 if ($table == 'emails_beans') {
2360 $query = "SELECT * FROM $table WHERE $from_column='$from_id' and bean_module='Leads'";
2362 $query = "SELECT * FROM $table WHERE $from_column='$from_id'";
2364 $results = $db->query($query);
2365 while($row = $db->fetchByAssoc($results))
2367 $query = "INSERT INTO $table ";
2370 $row[$from_column] = $to_id;
2371 $row['id'] = create_guid();
2372 if ($table=='emails_beans') {
2373 $row['bean_module'] =='Contacts';
2376 foreach($row as $name=>$value)
2382 $values .= "'$value'";
2385 $names .= ', '. $name;
2386 $values .= ", '$value'";
2389 $query .= "($names) VALUES ($values)";
2395 function get_unlinked_email_query($type, $bean) {
2396 global $current_user;
2398 $return_array['select']='SELECT emails.id ';
2399 $return_array['from']='FROM emails ';
2400 $return_array['where']="";
2401 $return_array['join'] = " JOIN (select DISTINCT email_id from emails_email_addr_rel eear
2403 join email_addr_bean_rel eabr on eabr.bean_id ='$bean->id' and eabr.bean_module = '$bean->module_dir' and
2404 eabr.email_address_id = eear.email_address_id and eabr.deleted=0
2405 where eear.deleted=0 and eear.email_id not in
2406 (select eb.email_id from emails_beans eb where eb.bean_module ='$bean->module_dir' and eb.bean_id = '$bean->id')
2407 ) derivedemails on derivedemails.email_id = emails.id";
2408 $return_array['join_tables'][0] = '';
2410 if (isset($type) and !empty($type['return_as_array'])) {
2411 return $return_array;
2414 return $return_array['select'] . $return_array['from'] . $return_array['where'] . $return_array['join'] ;
2417 function get_emails_by_assign_or_link($params)
2419 $relation = $params['link'];
2420 $bean = $GLOBALS['app']->controller->bean;
2421 if(empty($bean->$relation)) {
2422 $bean->load_relationship($relation);
2424 if(empty($bean->$relation)) {
2425 $GLOBALS['log']->error("Bad relation '$relation' for bean '{$bean->object_name}' id '{$bean->id}'");
2428 $rel_module = $bean->$relation->getRelatedModuleName();
2429 $rel_join = $bean->$relation->getJoin(array(
2430 'join_table_alias' => 'link_bean',
2431 'join_table_link_alias' => 'linkt',
2433 $rel_join = str_replace("{$bean->table_name}.id", "'{$bean->id}'", $rel_join);
2434 $return_array['select']='SELECT DISTINCT emails.id ';
2435 $return_array['from'] = "FROM emails ";
2437 $return_array['join'] = array();
2439 // directly assigned emails
2440 $return_array['join'][] = "
2447 eb.bean_module = '{$bean->module_dir}'
2448 AND eb.bean_id = '{$bean->id}'
2452 // Related by directly by email
2453 $return_array['join'][] = "
2458 emails_email_addr_rel eear
2460 email_addr_bean_rel eabr
2462 eabr.bean_id ='{$bean->id}'
2463 AND eabr.bean_module = '{$bean->module_dir}'
2464 AND eabr.email_address_id = eear.email_address_id
2470 $showEmailsOfRelatedContacts = empty($bean->field_defs[$relation]['hide_history_contacts_emails']);
2471 if (!empty($GLOBALS['sugar_config']['hide_history_contacts_emails']) && isset($GLOBALS['sugar_config']['hide_history_contacts_emails'][$bean->module_name])) {
2472 $showEmailsOfRelatedContacts = empty($GLOBALS['sugar_config']['hide_history_contacts_emails'][$bean->module_name]);
2474 if ($showEmailsOfRelatedContacts) {
2475 // Assigned to contacts
2476 $return_array['join'][] = "
2482 $rel_join AND link_bean.id = eb.bean_id
2484 eb.bean_module = '$rel_module'
2487 // Related by email to linked contact
2488 $return_array['join'][] = "
2491 'relate_contact' source
2493 emails_email_addr_rel eear
2495 email_addr_bean_rel eabr
2497 eabr.email_address_id=eear.email_address_id
2498 AND eabr.bean_module = '$rel_module'
2500 $rel_join AND link_bean.id = eabr.bean_id
2506 $return_array['join'] = " INNER JOIN (" . implode(" UNION ", $return_array['join']). ") email_ids ON emails.id=email_ids.email_id ";
2508 $return_array['where']=" WHERE emails.deleted=0 ";
2510 //$return_array['join'] = '';
2511 $return_array['join_tables'][0] = '';
2513 if($bean->object_name == "Case" && !empty($bean->case_number)) {
2514 $where = str_replace("%1", $bean->case_number, $bean->getEmailSubjectMacro());
2515 $return_array["where"] .= "\n AND (email_ids.source = 'direct' OR emails.name LIKE '%$where%')";
2518 return $return_array;
2522 * Check to see if the number is empty or non-zero
2526 function number_empty($value)
2528 return empty($value) && $value != '0';
2531 function get_bean_select_array($add_blank=true, $bean_name, $display_columns, $where='', $order_by='', $blank_is_none=false)
2534 require_once($beanFiles[$bean_name]);
2535 $focus = new $bean_name();
2536 $user_array = array();
2538 $key = ($bean_name == 'EmailTemplate') ? $bean_name : $bean_name . $display_columns. $where . $order_by;
2539 $user_array = get_register_value('select_array', $key );
2543 $db = DBManagerFactory::getInstance();
2545 $temp_result = Array();
2546 $query = "SELECT {$focus->table_name}.id, {$display_columns} as display from {$focus->table_name} ";
2550 $query .= $where." AND ";
2553 $query .= " {$focus->table_name}.deleted=0";
2555 if ( $order_by != '')
2557 $query .= " order by {$focus->table_name}.{$order_by}";
2560 $GLOBALS['log']->debug("get_user_array query: $query");
2561 $result = $db->query($query, true, "Error filling in user array: ");
2563 if ($add_blank==true){
2564 // Add in a blank row
2565 if($blank_is_none == true) { // set 'blank row' to "--None--"
2566 global $app_strings;
2567 $temp_result[''] = $app_strings['LBL_NONE'];
2569 $temp_result[''] = '';
2573 // Get the id and the name.
2574 while($row = $db->fetchByAssoc($result))
2576 $temp_result[$row['id']] = $row['display'];
2579 $user_array = $temp_result;
2580 set_register_value('select_array', $key ,$temp_result);
2589 * @param unknown_type $listArray
2591 // function parse_list_modules
2592 // searches a list for items in a user's allowed tabs and returns an array that removes unallowed tabs from list
2593 function parse_list_modules(&$listArray)
2595 global $modListHeader;
2596 $returnArray = array();
2598 foreach($listArray as $optionName => $optionVal)
2600 if(array_key_exists($optionName, $modListHeader))
2602 $returnArray[$optionName] = $optionVal;
2605 // special case for projects
2606 if(array_key_exists('Project', $modListHeader))
2608 $returnArray['ProjectTask'] = $listArray['ProjectTask'];
2611 $acldenied = ACLController::disabledModuleList($listArray,false);
2612 foreach($acldenied as $denied){
2613 unset($returnArray[$denied]);
2615 asort($returnArray);
2617 return $returnArray;
2620 function display_notice($msg = false){
2621 global $error_notice;
2622 //no error notice - lets just display the error to the user
2623 if(!isset($error_notice)){
2624 echo '<br>'.$msg . '<br>';
2626 $error_notice .= $msg . '<br>';
2630 /* checks if it is a number that at least has the plus at the beginning.
2632 function skype_formatted($number){
2633 //kbrill - BUG #15375
2634 if(isset($_REQUEST['action']) && $_REQUEST['action']=="Popup") {
2637 return substr($number, 0, 1) == '+' || substr($number, 0, 2) == '00' || substr($number, 0, 3) == '011';
2639 // return substr($number, 0, 1) == '+' || substr($number, 0, 2) == '00' || substr($number, 0, 2) == '011';
2642 function format_skype($number) {
2643 return preg_replace('/[^\+0-9]/','',$number);
2646 function insert_charset_header() {
2647 header('Content-Type: text/html; charset=UTF-8');
2650 function getCurrentURL()
2653 if(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on')
2658 $href.= "//".$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME'].'?'.$_SERVER['QUERY_STRING'];
2662 function javascript_escape($str) {
2665 for($i = 0; $i < strlen($str); $i++) {
2667 if(ord(substr($str, $i, 1))==10){
2669 }elseif(ord(substr($str, $i, 1))==13){
2673 $new_str .= $str{$i};
2677 $new_str = str_replace("'", "\\'", $new_str);
2682 function js_escape($str, $keep=true){
2683 $str = html_entity_decode(str_replace("\\", "", $str), ENT_QUOTES);
2686 $str = javascript_escape($str);
2689 $str = str_replace("'", " ", $str);
2690 $str = str_replace('"', " ", $str);
2695 //end function js_escape
2698 function br2nl($str) {
2699 $regex = "#<[^>]+br.+?>#i";
2700 preg_match_all($regex, $str, $matches);
2702 foreach($matches[0] as $match) {
2703 $str = str_replace($match, "<br>", $str);
2706 $brs = array('<br>','<br/>', '<br />');
2707 $str = str_replace("\r\n", "\n", $str); // make from windows-returns, *nix-returns
2708 $str = str_replace("\n\r", "\n", $str); // make from windows-returns, *nix-returns
2709 $str = str_replace("\r", "\n", $str); // make from windows-returns, *nix-returns
2710 $str = str_ireplace($brs, "\n", $str); // to retrieve it
2716 * Private helper function for displaying the contents of a given variable.
2717 * This function is only intended to be used for SugarCRM internal development.
2718 * The ppd stands for Pre Print Die.
2720 function _ppd($mixed)
2726 * Private helper function for displaying the contents of a given variable in
2727 * the Logger. This function is only intended to be used for SugarCRM internal
2728 * development. The pp stands for Pre Print.
2729 * @param $mixed var to print_r()
2730 * @param $die boolean end script flow
2731 * @param $displayStackTrace also show stack trace
2733 function _ppl($mixed, $die=false, $displayStackTrace=false, $loglevel="fatal") {
2734 if(!isset($GLOBALS['log']) || empty($GLOBALS['log'])) {
2736 $GLOBALS['log'] = LoggerManager :: getLogger('SugarCRM');
2740 $mix = print_r($mixed, true); // send print_r() output to $mix
2741 $stack = debug_backtrace();
2743 $GLOBALS['log']->$loglevel('------------------------------ _ppLogger() output start -----------------------------');
2744 $GLOBALS['log']->$loglevel($mix);
2745 if($displayStackTrace) {
2746 foreach($stack as $position) {
2747 $GLOBALS['log']->$loglevel($position['file']."({$position['line']})");
2751 $GLOBALS['log']->$loglevel('------------------------------ _ppLogger() output end -----------------------------');
2752 $GLOBALS['log']->$loglevel('------------------------------ _ppLogger() file: '.$stack[0]['file'].' line#: '.$stack[0]['line'].'-----------------------------');
2760 * private helper function to quickly show the major, direct, field attributes of a given bean.
2761 * The ppf stands for Pre[formatted] Print Focus [object]
2762 * @param object bean The focus bean
2764 function _ppf($bean, $die=false) {
2770 * Private helper function for displaying the contents of a given variable.
2771 * This function is only intended to be used for SugarCRM internal development.
2772 * The pp stands for Pre Print.
2774 function _pp($mixed)
2779 * Private helper function for displaying the contents of a given variable.
2780 * This function is only intended to be used for SugarCRM internal development.
2781 * The pp stands for Pre Print.
2783 function _pstack_trace($mixed=NULL)
2788 * Private helper function for displaying the contents of a given variable.
2789 * This function is only intended to be used for SugarCRM internal development.
2790 * The pp stands for Pre Print Trace.
2792 function _ppt($mixed, $textOnly=false)
2797 * Private helper function for displaying the contents of a given variable.
2798 * This function is only intended to be used for SugarCRM internal development.
2799 * The pp stands for Pre Print Trace Die.
2801 function _pptd($mixed)
2806 * Private helper function for decoding javascript UTF8
2807 * This function is only intended to be used for SugarCRM internal development.
2809 function decodeJavascriptUTF8($str) {
2813 * Will check if a given PHP version string is supported (tested on this ver),
2814 * unsupported (results unknown), or invalid (something will break on this
2815 * ver). Do not pass in any pararameter to default to a check against the
2816 * current environment's PHP version.
2818 * @return 1 implies supported, 0 implies unsupported, -1 implies invalid
2820 function check_php_version($sys_php_version = '') {
2821 $sys_php_version = empty($sys_php_version) ? constant('PHP_VERSION') : $sys_php_version;
2822 // versions below $min_considered_php_version considered invalid by default,
2823 // versions equal to or above this ver will be considered depending
2824 // on the rules that follow
2825 $min_considered_php_version = '5.2.2';
2827 // only the supported versions,
2828 // should be mutually exclusive with $invalid_php_versions
2829 $supported_php_versions = array (
2830 '5.2.2', '5.2.3', '5.2.4', '5.2.5', '5.2.6', '5.2.8', '5.3.0'
2833 // invalid versions above the $min_considered_php_version,
2834 // should be mutually exclusive with $supported_php_versions
2836 // SugarCRM prohibits install on PHP 5.2.7 on all platforms
2837 $invalid_php_versions = array('5.2.7');
2839 // default unsupported
2842 // versions below $min_considered_php_version are invalid
2843 if(1 == version_compare($sys_php_version, $min_considered_php_version, '<')) {
2847 // supported version check overrides default unsupported
2848 foreach($supported_php_versions as $ver) {
2849 if(1 == version_compare($sys_php_version, $ver, 'eq') || strpos($sys_php_version,$ver) !== false) {
2855 // invalid version check overrides default unsupported
2856 foreach($invalid_php_versions as $ver) {
2857 if(1 == version_compare($sys_php_version, $ver, 'eq') && strpos($sys_php_version,$ver) !== false) {
2863 //allow a redhat distro to install, regardless of version. We are assuming the redhat naming convention is followed
2864 //and the php version contains 'rh' characters
2865 if(strpos($sys_php_version, 'rh') !== false) {
2873 * Will check if a given IIS version string is supported (tested on this ver),
2874 * unsupported (results unknown), or invalid (something will break on this
2877 * @return 1 implies supported, 0 implies unsupported, -1 implies invalid
2879 function check_iis_version($sys_iis_version = '') {
2881 $server_software = $_SERVER["SERVER_SOFTWARE"];
2883 if(strpos($server_software,'Microsoft-IIS') !== false && preg_match_all("/^.*\/(\d+\.?\d*)$/", $server_software, $out))
2884 $iis_version = $out[1][0];
2886 $sys_iis_version = empty($sys_iis_version) ? $iis_version : $sys_iis_version;
2888 // versions below $min_considered_iis_version considered invalid by default,
2889 // versions equal to or above this ver will be considered depending
2890 // on the rules that follow
2891 $min_considered_iis_version = '6.0';
2893 // only the supported versions,
2894 // should be mutually exclusive with $invalid_iis_versions
2895 $supported_iis_versions = array ('6.0', '7.0',);
2896 $unsupported_iis_versions = array();
2897 $invalid_iis_versions = array('5.0',);
2899 // default unsupported
2902 // versions below $min_considered_iis_version are invalid
2903 if(1 == version_compare($sys_iis_version, $min_considered_iis_version, '<')) {
2907 // supported version check overrides default unsupported
2908 foreach($supported_iis_versions as $ver) {
2909 if(1 == version_compare($sys_iis_version, $ver, 'eq') || strpos($sys_iis_version,$ver) !== false) {
2915 // unsupported version check overrides default unsupported
2916 foreach($unsupported_iis_versions as $ver) {
2917 if(1 == version_compare($sys_iis_version, $ver, 'eq') && strpos($sys_iis_version,$ver) !== false) {
2923 // invalid version check overrides default unsupported
2924 foreach($invalid_iis_versions as $ver) {
2925 if(1 == version_compare($sys_iis_version, $ver, 'eq') && strpos($sys_iis_version,$ver) !== false) {
2934 function pre_login_check(){
2935 global $action, $login_error;
2936 if(!empty($action)&& $action == 'Login'){
2938 if(!empty($login_error)){
2939 $login_error = htmlentities($login_error);
2940 $login_error = str_replace(array("<pre>","</pre>","\r\n", "\n"), "<br>", $login_error);
2941 $_SESSION['login_error'] = $login_error;
2943 function set_focus() {}
2944 if(document.getElementById("post_error")) {
2945 document.getElementById("post_error").innerHTML="'. $login_error. '";
2946 document.getElementById("cant_login").value=1;
2947 document.getElementById("login_button").disabled = true;
2948 document.getElementById("user_name").disabled = true;
2949 //document.getElementById("user_password").disabled = true;
2958 function sugar_cleanup($exit = false) {
2959 static $called = false;
2962 set_include_path(realpath(dirname(__FILE__) . '/..') . PATH_SEPARATOR . get_include_path());
2963 chdir(realpath(dirname(__FILE__) . '/..'));
2964 global $sugar_config;
2965 require_once('include/utils/LogicHook.php');
2966 LogicHook::initialize();
2967 $GLOBALS['logic_hook']->call_custom_logic('', 'server_round_trip');
2969 //added this check to avoid errors during install.
2970 if (empty($sugar_config['dbconfig'])) {
2971 if ($exit) exit; else return;
2974 if (!class_exists('Tracker', true)) {
2975 require_once 'modules/Trackers/Tracker.php';
2978 // Now write the cached tracker_queries
2979 if(!empty($GLOBALS['savePreferencesToDB']) && $GLOBALS['savePreferencesToDB']) {
2980 if ( isset($GLOBALS['current_user']) && $GLOBALS['current_user'] instanceOf User )
2981 $GLOBALS['current_user']->savePreferencesToDB();
2984 //check to see if this is not an `ajax call AND the user preference error flag is set
2986 (isset($_SESSION['USER_PREFRENCE_ERRORS']) && $_SESSION['USER_PREFRENCE_ERRORS'])
2987 && ($_REQUEST['action']!='modulelistmenu' && $_REQUEST['action']!='DynamicAction')
2988 && ($_REQUEST['action']!='favorites' && $_REQUEST['action']!='DynamicAction')
2989 && (empty($_REQUEST['to_pdf']) || !$_REQUEST['to_pdf'] )
2990 && (empty($_REQUEST['sugar_body_only']) || !$_REQUEST['sugar_body_only'] )
2993 global $app_strings;
2994 //this is not an ajax call and the user preference error flag is set, so reset the flag and print js to flash message
2995 $err_mess = $app_strings['ERROR_USER_PREFS'];
2996 $_SESSION['USER_PREFRENCE_ERRORS'] = false;
2999 ajaxStatus.flashStatus('$err_mess',7000);
3005 if(class_exists('DBManagerFactory')) {
3006 $db = DBManagerFactory::getInstance();
3014 register_shutdown_function('sugar_cleanup');
3018 check_logic_hook - checks to see if your custom logic is in the logic file
3019 if not, it will add it. If the file isn't built yet, it will create the file
3022 function check_logic_hook_file($module_name, $event, $action_array){
3023 require_once('include/utils/logic_utils.php');
3026 if(file_exists("custom/modules/$module_name/logic_hooks.php")){
3028 $hook_array = get_hook_array($module_name);
3030 if(check_existing_element($hook_array, $event, $action_array)==true){
3031 //the hook at hand is present, so do nothing
3036 if(!empty($hook_array[$event]))
3038 $logic_count = count($hook_array[$event]);
3041 if($action_array[0]==""){
3042 $action_array[0] = $logic_count + 1;
3044 $hook_array[$event][] = $action_array;
3047 //end if the file exists already
3050 if($action_array[0]==""){
3051 $action_array[0] = 1;
3053 $hook_array = array();
3054 $hook_array[$event][] = $action_array;
3055 //end if else file exists already
3057 if($add_logic == true){
3059 //reorder array by element[0]
3060 //$hook_array = reorder_array($hook_array, $event);
3061 //!!!Finish this above TODO
3063 $new_contents = replace_or_add_logic_type($hook_array);
3064 write_logic_file($module_name, $new_contents);
3066 //end if add_element is true
3069 //end function check_logic_hook_file
3072 function remove_logic_hook($module_name, $event, $action_array) {
3073 require_once('include/utils/logic_utils.php');
3076 if(file_exists("custom/modules/".$module_name."/logic_hooks.php")){
3077 // The file exists, let's make sure the hook is there
3078 $hook_array = get_hook_array($module_name);
3080 if(check_existing_element($hook_array, $event, $action_array)==true){
3081 // The hook is there, time to take it out.
3083 foreach ( $hook_array[$event] as $i => $hook ) {
3084 // We don't do a full comparison below just in case the filename changes
3085 if ( $hook[0] == $action_array[0]
3086 && $hook[1] == $action_array[1]
3087 && $hook[3] == $action_array[3]
3088 && $hook[4] == $action_array[4] ) {
3089 unset($hook_array[$event][$i]);
3093 $new_contents = replace_or_add_logic_type($hook_array);
3094 write_logic_file($module_name, $new_contents);
3100 function display_stack_trace($textOnly=false){
3102 $stack = debug_backtrace();
3104 echo "\n\n display_stack_trace caller, file: " . $stack[0]['file']. ' line#: ' .$stack[0]['line'];
3112 foreach($stack as $item) {
3118 if(isset($item['file']))
3119 $file = $item['file'];
3120 if(isset($item['class']))
3121 $class = $item['class'];
3122 if(isset($item['line']))
3123 $line = $item['line'];
3124 if(isset($item['function']))
3125 $function = $item['function'];
3129 $out .= '<font color="black"><b>';
3135 $out .= '</b></font><font color="blue">';
3138 $out .= "[L:{$line}]";
3141 $out .= '</font><font color="red">';
3144 $out .= "({$class}:{$function})";
3147 $out .= '</font><br>';
3159 function StackTraceErrorHandler($errno, $errstr, $errfile,$errline, $errcontext) {
3160 $error_msg = " $errstr occurred in <b>$errfile</b> on line $errline [" . date("Y-m-d H:i:s") . ']';
3161 $halt_script = true;
3163 case 2048: return; //depricated we have lots of these ignore them
3166 if ( error_reporting() & E_NOTICE ) {
3167 $halt_script = false;
3173 case E_USER_WARNING:
3174 case E_COMPILE_WARNING:
3175 case E_CORE_WARNING:
3178 $halt_script = false;
3183 case E_COMPILE_ERROR:
3187 $type = "Fatal Error";
3192 $type = "Parse Error";
3196 //don't know what it is might not be so bad
3197 $halt_script = false;
3198 $type = "Unknown Error ($errno)";
3201 $error_msg = '<b>'.$type.'</b>:' . $error_msg;
3203 display_stack_trace();
3213 if(isset($sugar_config['stack_trace_errors']) && $sugar_config['stack_trace_errors']){
3215 set_error_handler('StackTraceErrorHandler');
3217 function get_sub_cookies($name){
3219 if(isset($_COOKIE[$name])){
3220 $subs = explode('#', $_COOKIE[$name]);
3221 foreach($subs as $cookie){
3222 if(!empty($cookie)){
3223 $cookie = explode('=', $cookie);
3225 $cookies[$cookie[0]] = $cookie[1];
3234 function mark_delete_components($sub_object_array, $run_second_level=false, $sub_sub_array=""){
3236 if(!empty($sub_object_array)){
3238 foreach($sub_object_array as $sub_object){
3240 //run_second level is set to true if you need to remove sub-sub components
3241 if($run_second_level==true){
3243 mark_delete_components($sub_object->get_linked_beans($sub_sub_array['rel_field'],$sub_sub_array['rel_module']));
3245 //end if run_second_level is true
3247 $sub_object->mark_deleted($sub_object->id);
3248 //end foreach sub component
3250 //end if this is not empty
3253 //end function mark_delete_components
3257 * For translating the php.ini memory values into bytes. e.g. input value of '8M' will return 8388608.
3259 function return_bytes($val)
3262 $last = strtolower($val{strlen($val)-1});
3266 // The 'G' modifier is available since PHP 5.1.0
3279 * Adds the href HTML tags around any URL in the $string
3281 function url2html($string) {
3283 $return_string = preg_replace('/(\w+:\/\/)(\S+)/', ' <a href="\\1\\2" target="_new" style="font-weight: normal;">\\1\\2</a>', $string);
3284 return $return_string;
3286 // End customization by Julian
3289 * tries to determine whether the Host machine is a Windows machine
3291 function is_windows() {
3292 static $is_windows = null;
3293 if (!isset($is_windows)) {
3294 $is_windows = strtoupper(substr(PHP_OS, 0, 3)) == 'WIN';
3300 * equivalent for windows filesystem for PHP's is_writable()
3301 * @param string file Full path to the file/dir
3302 * @return bool true if writable
3304 function is_writable_windows($file) {
3305 if($file{strlen($file)-1}=='/') {
3306 return is_writable_windows($file.uniqid(mt_rand()).'.tmp');
3309 // the assumption here is that Windows has an inherited permissions scheme
3310 // any file that is a descendant of an unwritable directory will inherit
3311 // that property and will trigger a failure below.
3316 $file = str_replace("/", '\\', $file);
3318 if(file_exists($file)) {
3319 if (!($f = @sugar_fopen($file, 'r+')))
3325 if(!($f = @sugar_fopen($file, 'w')))
3334 * best guesses Timezone based on webserver's TZ settings
3336 function lookupTimezone($userOffset = 0)
3338 return TimeDate::guessTimezone($userOffset);
3341 function convert_module_to_singular($module_array){
3344 foreach($module_array as $key => $value){
3345 if(!empty($beanList[$value])) $module_array[$key] = $beanList[$value];
3347 if($value=="Cases") {
3348 $module_array[$key] = "Case";
3350 if($key=="projecttask"){
3351 $module_array['ProjectTask'] = "Project Task";
3352 unset($module_array[$key]);
3356 return $module_array;
3358 //end function convert_module_to_singular
3362 * Given the bean_name which may be plural or singular return the singular
3363 * bean_name. This is important when you need to include files.
3365 function get_singular_bean_name($bean_name){
3366 global $beanFiles, $beanList;
3367 if(array_key_exists($bean_name, $beanList)){
3368 return $beanList[$bean_name];
3376 * Given the potential module name (singular name, renamed module name)
3377 * Return the real internal module name.
3379 function get_module_from_singular($singular) {
3381 // find the internal module name for a singular name
3382 if (isset($GLOBALS['app_list_strings']['moduleListSingular'])) {
3384 $singular_modules = $GLOBALS['app_list_strings']['moduleListSingular'];
3386 foreach ($singular_modules as $mod_name=>$sin_name) {
3387 if ($singular == $sin_name and $mod_name != $sin_name) {
3393 // find the internal module name for a renamed module
3394 if (isset($GLOBALS['app_list_strings']['moduleList'])) {
3396 $moduleList = $GLOBALS['app_list_strings']['moduleList'];
3398 foreach ($moduleList as $mod_name=>$name) {
3399 if ($singular == $name and $mod_name != $name) {
3405 // if it's not a singular name, nor a renamed name, return the original value
3409 function get_label($label_tag, $temp_module_strings){
3410 global $app_strings;
3411 if(!empty($temp_module_strings[$label_tag])){
3413 $label_name = $temp_module_strings[$label_tag];
3415 if(!empty($app_strings[$label_tag])){
3416 $label_name = $app_strings[$label_tag];
3418 $label_name = $label_tag;
3423 //end function get_label
3427 function search_filter_rel_info(& $focus, $tar_rel_module, $relationship_name){
3429 $rel_list = array();
3431 foreach($focus->relationship_fields as $rel_key => $rel_value){
3432 if($rel_value == $relationship_name){
3433 $temp_bean = get_module_info($tar_rel_module);
3434 // echo $focus->$rel_key;
3435 $temp_bean->retrieve($focus->$rel_key);
3436 if($temp_bean->id!=""){
3438 $rel_list[] = $temp_bean;
3444 foreach($focus->field_defs as $field_name => $field_def){
3445 //Check if the relationship_name matches a "relate" field
3446 if(!empty($field_def['type']) && $field_def['type'] == 'relate'
3447 && !empty($field_def['id_name']) && !empty($focus->field_defs[$field_def['id_name']])
3448 && !empty($focus->field_defs[$field_def['id_name']]['relationship'])
3449 && $focus->field_defs[$field_def['id_name']]['relationship'] == $relationship_name)
3451 $temp_bean = get_module_info($tar_rel_module);
3452 // echo $focus->$field_def['id_name'];
3453 $temp_bean->retrieve($focus->$field_def['id_name']);
3454 if($temp_bean->id!=""){
3456 $rel_list[] = $temp_bean;
3459 //Check if the relationship_name matches a "link" in a relate field
3460 } else if(!empty($rel_value['link']) && !empty($rel_value['id_name']) && $rel_value['link'] == $relationship_name){
3461 $temp_bean = get_module_info($tar_rel_module);
3462 // echo $focus->$rel_value['id_name'];
3463 $temp_bean->retrieve($focus->$rel_value['id_name']);
3464 if($temp_bean->id!=""){
3466 $rel_list[] = $temp_bean;
3472 // special case for unlisted parent-type relationships
3473 if( !empty($focus->parent_type) && $focus->parent_type == $tar_rel_module && !empty($focus->parent_id)) {
3474 $temp_bean = get_module_info($tar_rel_module);
3475 $temp_bean->retrieve($focus->parent_id);
3476 if($temp_bean->id!=""){
3477 $rel_list[] = $temp_bean;
3484 //end function search_filter_rel_info
3487 function get_module_info($module_name){
3491 //Get dictionary and focus data for module
3492 $vardef_name = $beanList[$module_name];
3494 if($vardef_name=="aCase"){
3495 $class_name = "Case";
3497 $class_name = $vardef_name;
3500 if(!file_exists('modules/'. $module_name . '/'.$class_name.'.php')){
3504 include_once('modules/'. $module_name . '/'.$class_name.'.php');
3506 $module_bean = new $vardef_name();
3507 return $module_bean;
3508 //end function get_module_table
3512 * In order to have one place to obtain the proper object name. aCase for example causes issues throughout the application.
3514 * @param string $moduleName
3516 function get_valid_bean_name($module_name){
3519 $vardef_name = $beanList[$module_name];
3520 if($vardef_name=="aCase"){
3521 $bean_name = "Case";
3523 $bean_name = $vardef_name;
3530 function checkAuthUserStatus(){
3537 * This function returns an array of phpinfo() results that can be parsed and
3538 * used to figure out what version we run, what modules are compiled in, etc.
3539 * @param $level int info level constant (1,2,4,8...64);
3540 * @return $returnInfo array array of info about the PHP environment
3541 * @author original by "code at adspeed dot com" Fron php.net
3542 * @author customized for Sugar by Chris N.
3544 function getPhpInfo($level=-1) {
3545 /** Name (constant) Value Description
3546 INFO_GENERAL 1 The configuration line, php.ini location, build date, Web Server, System and more.
3547 INFO_CREDITS 2 PHP Credits. See also phpcredits().
3548 INFO_CONFIGURATION 4 Current Local and Master values for PHP directives. See also ini_get().
3549 INFO_MODULES 8 Loaded modules and their respective settings. See also get_loaded_extensions().
3550 INFO_ENVIRONMENT 16 Environment Variable information that's also available in $_ENV.
3551 INFO_VARIABLES 32 Shows all predefined variables from EGPCS (Environment, GET, POST, Cookie, Server).
3552 INFO_LICENSE 64 PHP License information. See also the license FAQ.
3553 INFO_ALL -1 Shows all of the above. This is the default value.
3557 $phpinfo = ob_get_contents();
3560 $phpinfo = strip_tags($phpinfo,'<h1><h2><th><td>');
3561 $phpinfo = preg_replace('/<th[^>]*>([^<]+)<\/th>/',"<info>\\1</info>",$phpinfo);
3562 $phpinfo = preg_replace('/<td[^>]*>([^<]+)<\/td>/',"<info>\\1</info>",$phpinfo);
3563 $parsedInfo = preg_split('/(<h.?>[^<]+<\/h.>)/', $phpinfo, -1, PREG_SPLIT_DELIM_CAPTURE);
3566 $returnInfo = array();
3568 if(preg_match('/<h1 class\=\"p\">PHP Version ([^<]+)<\/h1>/', $phpinfo, $version)) {
3569 $returnInfo['PHP Version'] = $version[1];
3573 for ($i=1; $i<count($parsedInfo); $i++) {
3574 if (preg_match('/<h.>([^<]+)<\/h.>/', $parsedInfo[$i], $match)) {
3575 $vName = trim($match[1]);
3576 $parsedInfo2 = explode("\n",$parsedInfo[$i+1]);
3578 foreach ($parsedInfo2 AS $vOne) {
3579 $vPat = '<info>([^<]+)<\/info>';
3580 $vPat3 = "/$vPat\s*$vPat\s*$vPat/";
3581 $vPat2 = "/$vPat\s*$vPat/";
3583 if (preg_match($vPat3,$vOne,$match)) { // 3cols
3584 $returnInfo[$vName][trim($match[1])] = array(trim($match[2]),trim($match[3]));
3585 } elseif (preg_match($vPat2,$vOne,$match)) { // 2cols
3586 $returnInfo[$vName][trim($match[1])] = trim($match[2]);
3598 * This function will take a string that has tokens like {0}, {1} and will replace
3599 * those tokens with the args provided
3600 * @param $format string to format
3601 * @param $args args to replace
3602 * @return $result a formatted string
3604 function string_format($format, $args){
3608 * If args array has only one argument, and it's empty, so empty single quotes are used '' . That's because
3609 * IN () fails and IN ('') works.
3611 if (count($args) == 1)
3614 $singleArgument = current($args);
3615 if (empty($singleArgument))
3617 return str_replace("{0}", "''", $result);
3622 for($i = 0; $i < count($args); $i++){
3623 $result = str_replace('{'.$i.'}', $args[$i], $result);
3629 * Generate a string for displaying a unique identifier that is composed
3630 * of a system_id and number. This is use to allow us to generate quote
3631 * numbers using a DB auto-increment key from offline clients and still
3632 * have the number be unique (since it is modified by the system_id.
3634 * @param $num of bean
3635 * @param $system_id from system
3636 * @return $result a formatted string
3638 function format_number_display($num, $system_id){
3639 global $sugar_config;
3640 if(isset($num) && !empty($num)){
3641 $num=unformat_number($num);
3642 if(isset($system_id) && $system_id == 1){
3643 return sprintf("%d", $num);
3646 return sprintf("%d-%d", $num, $system_id);
3650 function checkLoginUserStatus(){
3654 * This function will take a number and system_id and format
3655 * @param $url URL containing host to append port
3656 * @param $port the port number - if '' is passed, no change to url
3657 * @return $resulturl the new URL with the port appended to the host
3659 function appendPortToHost($url, $port)
3663 // if no port, don't change the url
3666 $split = explode("/", $url);
3667 //check if it starts with http, in case they didn't include that in url
3668 if(str_begin($url, 'http'))
3670 //third index ($split[2]) will be the host
3671 $split[2] .= ":".$port;
3673 else // otherwise assumed to start with host name
3675 //first index ($split[0]) will be the host
3676 $split[0] .= ":".$port;
3679 $resulturl = implode("/", $split);
3686 * Singleton to return JSON object
3687 * @return JSON object
3689 function getJSONobj() {
3690 static $json = null;
3692 require_once('include/JSON.php');
3693 $json = new JSON(JSON_LOOSE_TYPE);
3698 require_once('include/utils/db_utils.php');
3701 * Set default php.ini settings for entry points
3703 function setPhpIniSettings() {
3705 // Bug 37579 - Comment out force enabling zlib.output_compression, since it can cause problems on certain hosts
3707 if(function_exists('gzclose') && headers_sent() == false) {
3708 ini_set('zlib.output_compression', 1);
3712 //nsingh: breaks zip/unzip functionality. Commenting out 4/23/08
3714 /*if(function_exists('mb_strlen')) {
3715 ini_set('mbstring.func_overload', 7);
3716 ini_set('mbstring.internal_encoding', 'UTF-8');
3720 // http://us3.php.net/manual/en/ref.pcre.php#ini.pcre.backtrack-limit
3721 // starting with 5.2.0, backtrack_limit breaks JSON decoding
3722 $backtrack_limit = ini_get('pcre.backtrack_limit');
3723 if(!empty($backtrack_limit)) {
3724 ini_set('pcre.backtrack_limit', '-1');
3729 * Identical to sugarArrayMerge but with some speed improvements and used specifically to merge
3730 * language files. Language file merges do not need to account for null values so we can get some
3731 * performance increases by using this specialized function. Note this merge function does not properly
3732 * handle null values.
3738 function sugarLangArrayMerge($gimp, $dom)
3740 if(is_array($gimp) && is_array($dom))
3742 foreach($dom as $domKey => $domVal)
3744 if(isset($gimp[$domKey]))
3746 if(is_array($domVal))
3749 foreach ( $domVal as $domArrKey => $domArrVal )
3750 $tempArr[$domArrKey] = $domArrVal;
3751 foreach ( $gimp[$domKey] as $gimpArrKey => $gimpArrVal )
3752 if ( !isset($tempArr[$gimpArrKey]) )
3753 $tempArr[$gimpArrKey] = $gimpArrVal;
3754 $gimp[$domKey] = $tempArr;
3758 $gimp[$domKey] = $domVal;
3763 $gimp[$domKey] = $domVal;
3767 // if the passed value for gimp isn't an array, then return the $dom
3768 elseif(is_array($dom))
3776 * like array_merge() but will handle array elements that are themselves arrays;
3777 * PHP's version just overwrites the element with the new one.
3779 * @internal Note that this function deviates from the internal array_merge()
3780 * functions in that it does does not treat numeric keys differently
3781 * than string keys. Additionally, it deviates from
3782 * array_merge_recursive() by not creating an array when like values
3785 * @param array gimp the array whose values will be overloaded
3786 * @param array dom the array whose values will pwn the gimp's
3787 * @return array beaten gimp
3789 function sugarArrayMerge($gimp, $dom) {
3790 if(is_array($gimp) && is_array($dom)) {
3791 foreach($dom as $domKey => $domVal) {
3792 if(array_key_exists($domKey, $gimp)) {
3793 if(is_array($domVal)) {
3795 foreach ( $domVal as $domArrKey => $domArrVal )
3796 $tempArr[$domArrKey] = $domArrVal;
3797 foreach ( $gimp[$domKey] as $gimpArrKey => $gimpArrVal )
3798 if ( !array_key_exists($gimpArrKey, $tempArr) )
3799 $tempArr[$gimpArrKey] = $gimpArrVal;
3800 $gimp[$domKey] = $tempArr;
3802 $gimp[$domKey] = $domVal;
3805 $gimp[$domKey] = $domVal;
3809 // if the passed value for gimp isn't an array, then return the $dom
3810 elseif(is_array($dom))
3817 * Similiar to sugarArrayMerge except arrays of N depth are merged.
3819 * @param array gimp the array whose values will be overloaded
3820 * @param array dom the array whose values will pwn the gimp's
3821 * @return array beaten gimp
3823 function sugarArrayMergeRecursive($gimp, $dom) {
3824 if(is_array($gimp) && is_array($dom)) {
3825 foreach($dom as $domKey => $domVal) {
3826 if(array_key_exists($domKey, $gimp)) {
3827 if(is_array($domVal) && is_array($gimp[$domKey])) {
3828 $gimp[$domKey] = sugarArrayMergeRecursive($gimp[$domKey], $domVal);
3830 $gimp[$domKey] = $domVal;
3833 $gimp[$domKey] = $domVal;
3837 // if the passed value for gimp isn't an array, then return the $dom
3838 elseif(is_array($dom))
3845 * finds the correctly working versions of PHP-JSON
3846 * @return bool True if NOT found or WRONG version
3848 function returnPhpJsonStatus() {
3849 if(function_exists('json_encode')) {
3850 $phpInfo = getPhpInfo(8);
3851 return version_compare($phpInfo['json']['json version'], '1.1.1', '<');
3853 return true; // not found
3858 * getTrackerSubstring
3860 * Returns a [number]-char or less string for the Tracker to display in the header
3861 * based on the tracker_max_display_length setting in config.php. If not set,
3862 * or invalid length, then defaults to 15 for COM editions, 30 for others.
3864 * @param string name field for a given Object
3865 * @return string [number]-char formatted string if length of string exceeds the max allowed
3867 function getTrackerSubstring($name) {
3868 static $max_tracker_item_length;
3871 $name = html_entity_decode($name, ENT_QUOTES, 'UTF-8');
3872 $strlen = function_exists('mb_strlen') ? mb_strlen($name) : strlen($name);
3874 global $sugar_config;
3876 if(!isset($max_tracker_item_length)) {
3877 if(isset($sugar_config['tracker_max_display_length'])) {
3878 $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;
3880 $max_tracker_item_length = 15;
3884 if($strlen > $max_tracker_item_length) {
3885 $chopped = function_exists('mb_substr') ? mb_substr($name, 0, $max_tracker_item_length-3, "UTF-8") : substr($name, 0, $max_tracker_item_length-3);
3893 function generate_search_where ($field_list=array(),$values=array(),&$bean,$add_custom_fields=false,$module='') {
3894 $where_clauses= array();
3896 $table_name=$bean->object_name;
3897 foreach ($field_list[$module] as $field=>$parms) {
3898 if(isset($values[$field]) && $values[$field] != "") {
3900 if (!empty($parms['operator'])) {
3901 $operator=$parms['operator'];
3903 if (is_array($values[$field])) {
3906 foreach ($values[$field] as $key => $val) {
3907 if ($val != ' ' and $val != '') {
3908 if (!empty($field_value)) {
3911 $field_value .= "'".$GLOBALS['db']->quote($val)."'";
3915 $field_value=$GLOBALS['db']->quote($values[$field]);
3917 //set db_fields array.
3918 if (!isset($parms['db_field']) ) {
3919 $parms['db_field'] = array($field);
3921 if (isset($parms['my_items']) and $parms['my_items'] == true) {
3922 global $current_user;
3923 $field_value = $GLOBALS['db']->quote($current_user->id);
3929 if ($field_value != '') {
3931 foreach ($parms['db_field'] as $db_field) {
3932 if (strstr($db_field,'.')===false) {
3933 $db_field=$bean->table_name.".".$db_field;
3935 if ($GLOBALS['db']->supports('case_sensitive') && isset($parms['query_type']) && $parms['query_type']=='case_insensitive') {
3936 $db_field='upper('.$db_field.")";
3937 $field_value=strtoupper($field_value);
3941 if (!empty($where)) {
3944 switch (strtolower($operator)) {
3946 $where .= $db_field . " like '".$field_value.$like_char."'";
3949 $where .= $db_field . " in (".$field_value.')';
3952 $where .= $db_field . " = '".$field_value ."'";
3957 if (!empty($where)) {
3959 array_push($where_clauses, '( '.$where.' )');
3961 array_push($where_clauses, $where);
3966 if ($add_custom_fields) {
3967 require_once('modules/DynamicFields/DynamicField.php');
3968 $bean->setupCustomFields($module);
3969 $bean->custom_fields->setWhereClauses($where_clauses);
3971 return $where_clauses;
3974 function add_quotes($str) {
3979 * This function will rebuild the config file
3980 * @param $sugar_config
3981 * @param $sugar_version
3982 * @return bool true if successful
3984 function rebuildConfigFile($sugar_config, $sugar_version) {
3985 // add defaults to missing values of in-memory sugar_config
3986 $sugar_config = sugarArrayMerge(get_sugar_config_defaults(), $sugar_config );
3987 // need to override version with default no matter what
3988 $sugar_config['sugar_version'] = $sugar_version;
3990 ksort( $sugar_config );
3992 if( write_array_to_file( "sugar_config", $sugar_config, "config.php" ) ){
4001 * Loads clean configuration, not overridden by config_override.php
4005 function loadCleanConfig()
4007 $sugar_config = array();
4008 require 'config.php';
4009 return $sugar_config;
4013 * getJavascriptSiteURL
4014 * This function returns a URL for the client javascript calls to access
4015 * the site. It uses $_SERVER['HTTP_REFERER'] in the event that Proxy servers
4016 * are used to access the site. Thus, the hostname in the URL returned may
4017 * not always match that of $sugar_config['site_url']. Basically, the
4018 * assumption is that however the user accessed the website is how they
4019 * will continue to with subsequent javascript requests. If the variable
4020 * $_SERVER['HTTP_REFERER'] is not found then we default to old algorithm.
4021 * @return $site_url The url used to refer to the website
4023 function getJavascriptSiteURL() {
4024 global $sugar_config;
4025 if(!empty($_SERVER['HTTP_REFERER'])) {
4026 $url = parse_url($_SERVER['HTTP_REFERER']);
4027 $replacement_url = $url['scheme']."://".$url['host'];
4028 if(!empty($url['port']))
4029 $replacement_url .= ':'.$url['port'];
4030 $site_url = preg_replace('/^http[s]?\:\/\/[^\/]+/',$replacement_url,$sugar_config['site_url']);
4032 $site_url = preg_replace('/^http(s)?\:\/\/[^\/]+/',"http$1://".$_SERVER['HTTP_HOST'],$sugar_config['site_url']);
4033 if(!empty($_SERVER['SERVER_PORT']) &&$_SERVER['SERVER_PORT'] == '443') {
4034 $site_url = preg_replace('/^http\:/','https:',$site_url);
4037 $GLOBALS['log']->debug("getJavascriptSiteURL(), site_url=". $site_url);
4041 // works nicely with array_map() -- can be used to wrap single quotes around each element in an array
4042 function add_squotes($str) {
4043 return "'" . $str . "'";
4047 // recursive function to count the number of levels within an array
4048 function array_depth($array, $depth_count=-1, $depth_array=array()){
4050 if (is_array($array)){
4051 foreach ($array as $key => $value){
4052 $depth_array[] = array_depth($value, $depth_count);
4056 return $depth_count;
4058 foreach ($depth_array as $value){
4059 $depth_count = $value > $depth_count ? $value : $depth_count;
4061 return $depth_count;
4065 * Creates a new Group User
4066 * @param string $name Name of Group User
4067 * @return string GUID of new Group User
4069 function createGroupUser($name) {
4072 $group = new User();
4073 $group->user_name = $name;
4074 $group->last_name = $name;
4075 $group->is_group = 1;
4076 $group->deleted = 0;
4077 $group->status = 'Active'; // cn: bug 6711
4078 $group->setPreference('timezone', TimeDate::userTimezone());
4085 * Helper function to locate an icon file given only a name
4086 * Searches through the various paths for the file
4087 * @param string iconFileName The filename of the icon
4088 * @return string Relative pathname of the located icon, or '' if not found
4091 function _getIcon($iconFileName)
4094 $iconName = "icon_{$iconFileName}.gif";
4095 $iconFound = SugarThemeRegistry::current()->getImageURL($iconName,false);
4097 //First try un-ucfirst-ing the icon name
4098 if ( empty($iconFound) )
4099 $iconName = "icon_" . strtolower(substr($iconFileName,0,1)).substr($iconFileName,1) . ".gif";
4100 $iconFound = SugarThemeRegistry::current()->getImageURL($iconName,false);
4102 //Next try removing the icon prefix
4103 if ( empty($iconFound) )
4104 $iconName = "{$iconFileName}.gif";
4105 $iconFound = SugarThemeRegistry::current()->getImageURL($iconName,false);
4107 if ( empty($iconFound) )
4113 * Function to grab the correct icon image for Studio
4114 * @param string $iconFileName Name of the icon file
4115 * @param string $altfilename Name of a fallback icon file (displayed if the imagefilename doesn't exist)
4116 * @param string $width Width of image
4117 * @param string $height Height of image
4118 * @param string $align Alignment of image
4119 * @param string $alt Alt tag of image
4120 * @return string $string <img> tag with corresponding image
4123 function getStudioIcon($iconFileName='', $altFileName='', $width='48', $height='48', $align='baseline', $alt='' )
4125 global $app_strings, $theme;
4127 $iconName = _getIcon($iconFileName);
4128 if(empty($iconName)){
4129 $iconName = _getIcon($altFileName);
4130 if (empty($iconName))
4132 return $app_strings['LBL_NO_IMAGE'];
4135 return SugarThemeRegistry::current()->getImage($iconName, "align=\"$align\" border=\"0\"", $width, $height);
4139 * Function to grab the correct icon image for Dashlets Dialog
4140 * @param string $filename Location of the icon file
4141 * @param string $module Name of the module to fall back onto if file does not exist
4142 * @param string $width Width of image
4143 * @param string $height Height of image
4144 * @param string $align Alignment of image
4145 * @param string $alt Alt tag of image
4146 * @return string $string <img> tag with corresponding image
4149 function get_dashlets_dialog_icon($module='', $width='32', $height='32', $align='absmiddle',$alt=''){
4150 global $app_strings, $theme;
4151 $iconName = _getIcon($module . "_32");
4152 if (empty($iconName))
4154 $iconName = _getIcon($module);
4156 if(empty($iconName)){
4157 return $app_strings['LBL_NO_IMAGE'];
4159 return SugarThemeRegistry::current()->getImage($iconName, "align=\"$align\" border=\"0\"", $width, $height);
4162 // works nicely to change UTF8 strings that are html entities - good for PDF conversions
4163 function html_entity_decode_utf8($string)
4166 // replace numeric entities
4167 //php will have issues with numbers with leading zeros, so do not include them in what we send to code2utf.
4168 $string = preg_replace('~�*([0-9a-f]+);~ei', 'code2utf(hexdec("\\1"))', $string);
4169 $string = preg_replace('~�*([0-9]+);~e', 'code2utf(\\1)', $string);
4170 // replace literal entities
4171 if (!isset($trans_tbl))
4173 $trans_tbl = array();
4174 foreach (get_html_translation_table(HTML_ENTITIES) as $val=>$key)
4175 $trans_tbl[$key] = utf8_encode($val);
4177 return strtr($string, $trans_tbl);
4180 // Returns the utf string corresponding to the unicode value
4181 function code2utf($num)
4183 if ($num < 128) return chr($num);
4184 if ($num < 2048) return chr(($num >> 6) + 192) . chr(($num & 63) + 128);
4185 if ($num < 65536) return chr(($num >> 12) + 224) . chr((($num >> 6) & 63) + 128) . chr(($num & 63) + 128);
4186 if ($num < 2097152) return chr(($num >> 18) + 240) . chr((($num >> 12) & 63) + 128) . chr((($num >> 6) & 63) + 128) . chr(($num & 63) + 128);
4190 function str_split_php4($string, $length = 1) {
4191 $string_length = strlen($string);
4194 if ($length > $string_length) {
4195 // use the string_length as the string is shorter than the length
4196 $length = $string_length;
4198 for ($cursor = 0; $cursor < $string_length; $cursor = $cursor + $length) {
4199 $return[] = substr($string, $cursor, $length);
4204 if (version_compare(phpversion(), '5.0.0', '<')) {
4205 function str_split($string, $length = 1) {
4206 return str_split_php4($string, $length);
4211 * @deprecated use DBManagerFactory::isFreeTDS
4213 function is_freetds()
4215 return DBManagerFactory::isFreeTDS();
4219 * Chart dashlet helper function that returns the correct CSS file, dependent on the current theme.
4221 * @todo this won't work completely right until we impliment css compression and combination
4222 * for now, we'll just include the last css file found.
4224 * @return chart.css file to use
4226 function chartStyle()
4228 return SugarThemeRegistry::current()->getCSSURL('chart.css');
4232 * Chart dashlet helper functions that returns the correct XML color file for charts,
4233 * dependent on the current theme.
4235 * @return sugarColors.xml to use
4237 function chartColors()
4239 if (SugarThemeRegistry::current()->getCSSURL('sugarColors.xml')=='')
4240 return SugarThemeRegistry::current()->getImageURL('sugarColors.xml');
4241 return SugarThemeRegistry::current()->getCSSURL('sugarColors.xml');
4243 /* End Chart Dashlet helper functions */
4246 * This function is designed to set up the php enviroment
4247 * for AJAX requests.
4250 function ajaxInit() {
4251 ini_set('display_errors', 'false');
4255 * Returns an absolute path from the given path, determining if it is relative or absolute
4257 * @param string $path
4260 function getAbsolutePath(
4262 $currentServer = false
4265 $path = trim($path);
4267 // try to match absolute paths like \\server\share, /directory or c:\
4268 if ( ( substr($path,0,2) == '\\\\' )
4269 || ( $path[0] == '/' )
4270 || preg_match('/^[A-z]:/i',$path)
4274 return getcwd().'/'.$path;
4278 * Returns the bean object of the given module
4280 * @deprecated use SugarModule::loadBean() instead
4281 * @param string $module
4288 return SugarModule::get($module)->loadBean();
4293 * Returns true if the application is being accessed on a touch screen interface ( like an iPad )
4295 function isTouchScreen()
4297 $ua = empty($_SERVER['HTTP_USER_AGENT']) ? "undefined" : strtolower($_SERVER['HTTP_USER_AGENT']);
4299 // first check if we have forced use of the touch enhanced interface
4300 if ( isset($_COOKIE['touchscreen']) && $_COOKIE['touchscreen'] == '1' ) {
4304 // next check if we should use the touch interface with our device
4305 if ( strpos($ua, 'ipad') !== false ) {
4313 * Returns the shortcut keys to access the shortcut links. Shortcut
4314 * keys vary depending on browser versions and operating systems.
4315 * @return String value of the shortcut keys
4317 function get_alt_hot_key() {
4319 if ( isset($_SERVER['HTTP_USER_AGENT']) )
4320 $ua = strtolower($_SERVER['HTTP_USER_AGENT']);
4321 $isMac = strpos($ua, 'mac') !== false;
4322 $isLinux = strpos($ua, 'linux') !== false;
4324 if(!$isMac && !$isLinux && strpos($ua, 'mozilla') !== false) {
4325 if(preg_match('/firefox\/(\d)?\./', $ua, $matches)) {
4326 return $matches[1] < 2 ? 'Alt+' : 'Alt+Shift+';
4329 return $isMac ? 'Ctrl+' : 'Alt+';
4332 function can_start_session(){
4333 if(!empty($_GET['PHPSESSID'])) {
4336 $session_id = session_id();
4337 return empty($session_id) ? true : false;
4340 function load_link_class($properties){
4342 if(!empty($properties['link_class']) && !empty($properties['link_file'])){
4343 require_once($properties['link_file']);
4344 $class = $properties['link_class'];
4350 function inDeveloperMode()
4352 return isset($GLOBALS['sugar_config']['developerMode']) && $GLOBALS['sugar_config']['developerMode'];
4356 * Filter the protocol list for inbound email accounts.
4358 * @param array $protocol
4360 function filterInboundEmailPopSelection($protocol)
4362 if ( !isset($GLOBALS['sugar_config']['allow_pop_inbound']) || ! $GLOBALS['sugar_config']['allow_pop_inbound'] )
4364 if( isset($protocol['pop3']) )
4365 unset($protocol['pop3']);
4368 $protocol['pop3'] = 'POP3';
4374 * The function is used because currently we are not supporting mbstring.func_overload
4375 * 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.
4376 * 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.
4377 * @returns the substred strings.
4379 function sugar_substr($string, $length, $charset='UTF-8')
4381 if(mb_strlen($string,$charset) > $length) {
4382 $string = trim(mb_substr(trim($string),0,$length,$charset));
4388 * The function is used because on FastCGI enviroment, the ucfirst(Chinese Characters) will produce bad charcters.
4389 * This will work even without setting the mbstring.*encoding
4391 function sugar_ucfirst($string, $charset='UTF-8') {
4392 return mb_strtoupper(mb_substr($string, 0, 1, $charset), $charset) . mb_substr($string, 1, mb_strlen($string), $charset);
4399 function unencodeMultienum($string) {
4400 if (is_array($string))
4404 if (substr($string, 0 ,1) == "^" && substr($string, -1) == "^") {
4405 $string = substr(substr($string, 1), 0, strlen($string) -2);
4408 return explode('^,^', $string);
4411 function encodeMultienumValue($arr) {
4412 if (!is_array($arr))
4418 $string = "^" . implode('^,^', $arr) . "^";
4424 * create_export_query is used for export and massupdate
4425 * We haven't handle the these fields: $field['type'] == 'relate' && isset($field['link']
4426 * This function will correct the where clause and output necessary join condition for them
4427 * @param $module: the module name
4428 * @param $searchFields: searchFields which is got after $searchForm->populateFromArray()
4429 * @param $where: where clauses
4430 * @return $ret_array['where']: corrected where clause
4431 * @return $ret_array['join']: extra join condition
4433 function create_export_query_relate_link_patch($module, $searchFields, $where){
4434 if(file_exists('modules/'.$module.'/SearchForm.html')){
4435 $ret_array['where'] = $where;
4438 $seed = loadBean($module);
4439 foreach($seed->field_defs as $name=>$field)
4442 if( $field['type'] == 'relate' && isset($field['link']) && !empty($searchFields[$name]['value']) ){
4443 $seed->load_relationship($field['link']);
4445 if(empty($join_type))
4447 $params['join_type'] = ' LEFT JOIN ';
4451 $params['join_type'] = $join_type;
4453 if(isset($data['join_name']))
4455 $params['join_table_alias'] = $field['join_name'];
4459 $params['join_table_alias'] = 'join_'.$field['name'];
4462 if(isset($data['join_link_name']))
4464 $params['join_table_link_alias'] = $field['join_link_name'];
4468 $params['join_table_link_alias'] = 'join_link_'.$field['name'];
4470 $join = $seed->$field['link']->getJoin($params, true);
4471 $join_table_alias = 'join_'.$field['name'];
4472 if(isset($field['db_concat_fields'])){
4473 $db_field = db_concat($join_table_alias, $field['db_concat_fields']);
4474 $where = preg_replace('/'.$field['name'].'/', $db_field, $where);
4476 $where = preg_replace('/(^|[\s(])' . $field['name'] . '/', '${1}' . $join_table_alias . '.'.$field['rname'], $where);
4480 $ret_array = array('where'=>$where, 'join'=> isset($join['join']) ? $join['join'] : '');
4485 * 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.
4486 * @Depends on QuickRepairAndRebuild.php
4487 * @Relate bug 30642 ,23177
4489 function clearAllJsAndJsLangFilesWithoutOutput(){
4490 global $current_language , $mod_strings;
4491 $MBmodStrings = $mod_strings;
4492 $mod_strings = return_module_language ( $current_language, 'Administration' ) ;
4493 include_once ('modules/Administration/QuickRepairAndRebuild.php') ;
4494 $repair = new RepairAndClear();
4495 $repair->module_list = array();
4496 $repair->show_output = false;
4497 $repair->clearJsLangFiles();
4498 $repair->clearJsFiles();
4499 $mod_strings = $MBmodStrings;
4503 * This function will allow you to get a variable value from query string
4505 function getVariableFromQueryString($variable, $string){
4507 $number = preg_match("/{$variable}=([a-zA-Z0-9_-]+)[&]?/", $string, $matches);
4517 * should_hide_iframes
4518 * This is a helper method to determine whether or not to show iframes (My Sites) related
4519 * information in the application.
4521 * @return boolean flag indicating whether or not iframes module should be hidden
4523 function should_hide_iframes() {
4524 //Remove the MySites module
4525 if(file_exists('modules/iFrames/iFrame.php')) {
4526 if(!class_exists("iFrame")) {
4527 require_once('modules/iFrames/iFrame.php');
4535 * Given a version such as 5.5.0RC1 return RC. If we have a version such as: 5.5 then return GA
4537 * @param string $version
4538 * @return string RC, BETA, GA
4540 function getVersionStatus($version){
4541 if(preg_match('/^[\d\.]+?([a-zA-Z]+?)[\d]*?$/si', $version, $matches)) {
4542 return strtoupper($matches[1]);
4549 * Return the numeric portion of a version. For example if passed 5.5.0RC1 then return 5.5. If given
4550 * 5.5.1RC1 then return 5.5.1
4552 * @param string $version
4555 function getMajorMinorVersion($version){
4556 if(preg_match('/^([\d\.]+).*$/si', $version, $matches2)){
4557 $version = $matches2[1];
4558 $arr = explode('.', $version);
4559 if(count($arr) > 2){
4561 $version = substr($version, 0, 3);
4569 * Return string composed of seconds & microseconds of current time, without dots
4572 function sugar_microtime()
4574 $now = explode(' ', microtime());
4575 $unique_id = $now[1].str_replace('.', '', $now[0]);
4580 * Extract urls from a piece of text
4582 * @return array of urls found in $string
4584 function getUrls($string)
4586 $lines = explode("<br>", trim($string));
4588 foreach($lines as $line){
4589 $regex = '/http?\:\/\/[^\" ]+/i';
4590 preg_match_all($regex, $line, $matches);
4591 foreach($matches[0] as $match){
4600 * Sanitize image file from hostile content
4601 * @param string $path Image file
4602 * @param bool $jpeg Accept only JPEGs?
4604 function verify_image_file($path, $jpeg = false)
4606 if(function_exists('imagepng') && function_exists('imagejpeg') && function_exists('imagecreatefromstring')) {
4607 $img = imagecreatefromstring(file_get_contents($path));
4611 $img_size = getimagesize($path);
4612 $filetype = $img_size['mime'];
4613 //if filetype is jpeg or if we are only allowing jpegs, create jpg image
4614 if($filetype == "image/jpeg" || $jpeg) {
4617 $image = ob_get_clean();
4618 // not writing directly because imagejpeg does not work with streams
4619 if(file_put_contents($path, $image)) {
4622 } elseif ($filetype == "image/png") {
4623 // else if the filetype is png, create png
4624 imagealphablending($img, true);
4625 imagesavealpha($img, true);
4628 $image = ob_get_clean();
4629 if(file_put_contents($path, $image)) {
4636 // check image manually
4637 $fp = fopen($path, "rb");
4638 if(!$fp) return false;
4640 // read the whole file in chunks
4642 $data .= fread($fp,8192);
4646 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",
4648 $GLOBALS['log']->fatal("Found {$m[0]} in $path, not allowing upload");
4657 * Verify uploaded image
4658 * Verifies that image has proper extension, MIME type and doesn't contain hostile content
4659 * @param string $path Image path
4660 * @param bool $jpeg_only Accept only JPEGs?
4662 function verify_uploaded_image($path, $jpeg_only = false)
4664 $supportedExtensions = array('jpg' => 'image/jpeg', 'jpeg' => 'image/jpeg');
4666 $supportedExtensions['png'] = 'image/png';
4669 if(!file_exists($path) || !is_file($path)) {
4673 $img_size = getimagesize($path);
4674 $filetype = $img_size['mime'];
4675 $ext = end(explode(".", $path));
4676 if(substr_count('..', $path) > 0 || ($ext !== $path && !isset($supportedExtensions[strtolower($ext)])) ||
4677 !in_array($filetype, array_values($supportedExtensions))) {
4680 return verify_image_file($path, $jpeg_only);
4683 function cmp_beans($a, $b)
4685 global $sugar_web_service_order_by;
4686 //If the order_by field is not valid, return 0;
4687 if (empty($sugar_web_service_order_by) || !isset($a->$sugar_web_service_order_by) || !isset($b->$sugar_web_service_order_by)){
4690 if (is_object($a->$sugar_web_service_order_by) || is_object($b->$sugar_web_service_order_by)
4691 || is_array($a->$sugar_web_service_order_by) || is_array($b->$sugar_web_service_order_by))
4695 if ($a->$sugar_web_service_order_by < $b->$sugar_web_service_order_by)
4703 function order_beans($beans, $field_name)
4705 //Since php 5.2 doesn't include closures, we must use a global to pass the order field to cmp_beans.
4706 global $sugar_web_service_order_by;
4707 $sugar_web_service_order_by = $field_name;
4708 usort($beans, "cmp_beans");
4713 * Return search like string
4714 * This function takes a user input string and returns a string that contains wild card(s) that can be used in db query.
4715 * @param string $str string to be searched
4716 * @param string $like_char Database like character, usually '%'
4717 * @return string Returns a string to be searched in db query
4719 function sql_like_string($str, $like_char, $wildcard = '%', $appendWildcard = true) {
4721 // override default wildcard character
4722 if (isset($GLOBALS['sugar_config']['search_wildcard_char']) &&
4723 strlen($GLOBALS['sugar_config']['search_wildcard_char']) == 1) {
4724 $wildcard = $GLOBALS['sugar_config']['search_wildcard_char'];
4727 // add wildcard at the beginning of the search string
4728 if (isset($GLOBALS['sugar_config']['search_wildcard_infront']) &&
4729 $GLOBALS['sugar_config']['search_wildcard_infront'] == true) {
4730 if (substr($str,0,1) <> $wildcard)
4731 $str = $wildcard.$str;
4734 // add wildcard at the end of search string (default)
4735 if ($appendWildcard) {
4736 if(substr($str,-1) <> $wildcard) {
4741 return str_replace($wildcard, $like_char, $str);
4744 //check to see if custom utils exists
4745 if(file_exists('custom/include/custom_utils.php')){
4746 include_once('custom/include/custom_utils.php');
4749 //check to see if custom utils exists in Extension framework
4750 if(file_exists('custom/application/Ext/Utils/custom_utils.ext.php')) {
4751 include_once('custom/application/Ext/Utils/custom_utils.ext.php');
4754 * @param $input - the input string to sanitize
4755 * @param int $quotes - use quotes
4756 * @param string $charset - the default charset
4757 * @param bool $remove - strip tags or not
4758 * @return string - the sanitized string
4760 function sanitize($input, $quotes = ENT_QUOTES, $charset = 'UTF-8', $remove = false)
4762 return htmlentities($input, $quotes, $charset);
4766 * @return string - the full text search engine name
4768 function getFTSEngineType()
4770 if (isset($GLOBALS['sugar_config']['full_text_engine']) && is_array($GLOBALS['sugar_config']['full_text_engine'])) {
4771 foreach ($GLOBALS['sugar_config']['full_text_engine'] as $name => $defs) {
4779 * @param string $optionName - name of the option to be retrieved from app_list_strings
4780 * @return array - the array to be used in option element
4782 function getFTSBoostOptions($optionName)
4784 if (isset($GLOBALS['app_list_strings'][$optionName])) {
4785 return $GLOBALS['app_list_strings'][$optionName];
4793 * utf8_recursive_encode
4795 * This function walks through an Array and recursively calls utf8_encode on the
4796 * values of each of the elements.
4798 * @param $data Array of data to encode
4799 * @return utf8 encoded Array data
4801 function utf8_recursive_encode($data)
4804 foreach($data as $key=>$val) {
4805 if(is_array($val)) {
4806 $result[$key] = utf8_recursive_encode($val);
4808 $result[$key] = utf8_encode($val);
4815 * get_language_header
4817 * This is a utility function for 508 Compliance. It returns the lang=[Current Language] text string used
4818 * inside the <html> tag. If no current language is specified, it defaults to lang='en'.
4820 * @return String The lang=[Current Language] markup to insert into the <html> tag
4822 function get_language_header()
4824 return isset($GLOBALS['current_language']) ? "lang='{$GLOBALS['current_language']}'" : "lang='en'";
4829 * get_custom_file_if_exists
4831 * This function handles the repetitive code we have where we first check if a file exists in the
4832 * custom directory to determine whether we should load it, require it, include it, etc. This function returns the
4833 * path of the custom file if it exists. It basically checks if custom/{$file} exists and returns this path if so;
4834 * otherwise it return $file
4836 * @param $file String of filename to check
4837 * @return $file String of filename including custom directory if found
4839 function get_custom_file_if_exists($file)
4841 return file_exists("custom/{$file}") ? "custom/{$file}" : $file;
4848 * This will return the URL used to redirect the user to the help documentation.
4849 * It can be overriden completely by setting the custom_help_url or partially by setting the custom_help_base_url
4850 * in config.php or config_override.php.
4852 * @param string $send_edition
4853 * @param string $send_version
4854 * @param string $send_lang
4855 * @param string $send_module
4856 * @param string $send_action
4857 * @param string $dev_status
4858 * @param string $send_key
4859 * @param string $send_anchor
4860 * @return string the completed help URL
4862 function get_help_url($send_edition = '', $send_version = '', $send_lang = '', $send_module = '', $send_action = '', $dev_status = '', $send_key = '', $send_anchor = '') {
4863 global $sugar_config;
4865 if (!empty($sugar_config['custom_help_url'])) {
4866 $sendUrl = $sugar_config['custom_help_url'];
4868 if (!empty($sugar_config['custom_help_base_url'])) {
4869 $baseUrl= $sugar_config['custom_help_base_url'];
4871 $baseUrl = "http://www.sugarcrm.com/crm/product_doc.php";
4873 $sendUrl = $baseUrl . "?edition={$send_edition}&version={$send_version}&lang={$send_lang}&module={$send_module}&help_action={$send_action}&status={$dev_status}&key={$send_key}";
4874 if(!empty($send_anchor)) {
4875 $sendUrl .= "&anchor=".$send_anchor;
4882 * generateETagHeader
4884 * This function generates the necessary cache headers for using ETags with dynamic content. You
4885 * simply have to generate the ETag, pass it in, and the function handles the rest.
4887 * @param string $etag ETag to use for this content.
4889 function generateETagHeader($etag){
4890 header("cache-control:");
4891 header('Expires: ');
4892 header("ETag: " . $etag);
4894 if(isset($_SERVER["HTTP_IF_NONE_MATCH"])){
4895 if($etag == $_SERVER["HTTP_IF_NONE_MATCH"]){
4897 header("Status: 304 Not Modified");
4898 header("HTTP/1.0 304 Not Modified");
4905 * getReportNameTranslation
4907 * Translates the report name if a translation exists,
4908 * otherwise just returns the name
4910 * @param string $reportName
4911 * @return string translated report name
4913 function getReportNameTranslation($reportName) {
4914 global $current_language;
4916 // Used for translating reports
4917 $mod_strings = return_module_language($current_language, 'Reports');
4919 // Search for the report name in the default language and get the key
4920 $key = array_search($reportName, return_module_language("", "Reports"));
4922 // If the key was found, use it to get a translation, otherwise just use report name
4924 $title = $mod_strings[$key];
4926 $title = $reportName;
4933 * Remove vars marked senstitive from array
4934 * @param array $defs
4935 * @param SugarBean|array $data
4936 * @return mixed $data without sensitive fields
4938 function clean_sensitive_data($defs, $data)
4940 foreach($defs as $field => $def) {
4941 if(!empty($def['sensitive'])) {
4942 if(is_array($data)) {
4945 if($data instanceof SugarBean) {
4954 * Return relations with labels for duplicates
4956 function getDuplicateRelationListWithTitle($def, $var_def, $module)
4958 global $current_language;
4959 $select_array = array_unique($def);
4960 if (count($select_array) < count($def))
4962 $temp_module_strings = return_module_language($current_language, $module);
4963 $temp_duplicate_array = array_diff_assoc($def, $select_array);
4964 $temp_duplicate_array = array_merge($temp_duplicate_array, array_intersect($select_array, $temp_duplicate_array));
4966 foreach ($temp_duplicate_array as $temp_key => $temp_value)
4968 // Don't add duplicate relationships
4969 if (!empty($var_def[$temp_key]['relationship']) && array_key_exists($var_def[$temp_key]['relationship'], $select_array))
4973 $select_array[$temp_key] = $temp_value;
4976 // Add the relationship name for easier recognition
4977 foreach ($select_array as $key => $value)
4979 $select_array[$key] .= ' (' . $key . ')';
4982 asort($select_array);
4983 return $select_array;
4987 * Gets the list of "*type_display*".
4991 function getTypeDisplayList()
4993 return array('record_type_display', 'parent_type_display', 'record_type_display_notes');
4997 * Breaks given string into substring according
4998 * to 'db_concat_fields' from field definition
4999 * and assigns values to corresponding properties
5002 * @param SugarBean $bean
5003 * @param array $fieldDef
5004 * @param string $value
5006 function assignConcatenatedValue(SugarBean $bean, $fieldDef, $value)
5008 $valueParts = explode(' ',$value);
5009 $valueParts = array_filter($valueParts);
5010 $fieldNum = count($fieldDef['db_concat_fields']);
5012 if (count($valueParts) == 1 && $fieldDef['db_concat_fields'] == array('first_name', 'last_name'))
5014 $bean->last_name = $value;
5016 // elseif ($fieldNum >= count($valueParts))
5019 for ($i = 0; $i < $fieldNum; $i++)
5021 $fieldValue = array_shift($valueParts);
5022 $fieldName = $fieldDef['db_concat_fields'][$i];
5023 $bean->$fieldName = $fieldValue !== false ? $fieldValue : '';
5026 if (!empty($valueParts))
5028 $bean->$fieldName .= ' ' . implode(' ', $valueParts);