2 /*********************************************************************************
3 * SugarCRM Community Edition is a customer relationship management program developed by
4 * SugarCRM, Inc. Copyright (C) 2004-2012 SugarCRM Inc.
6 * This program is free software; you can redistribute it and/or modify it under
7 * the terms of the GNU Affero General Public License version 3 as published by the
8 * Free Software Foundation with the addition of the following permission added
9 * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
10 * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
11 * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
18 * You should have received a copy of the GNU Affero General Public License along with
19 * this program; if not, see http://www.gnu.org/licenses or write to the Free
20 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
24 * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
26 * The interactive user interfaces in modified source and object code versions
27 * of this program must display Appropriate Legal Notices, as required under
28 * Section 5 of the GNU Affero General Public License version 3.
30 * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
31 * these Appropriate Legal Notices must retain the display of the "Powered by
32 * SugarCRM" logo. If the display of the logo is not reasonably feasible for
33 * technical reasons, the Appropriate Legal Notices must display the words
34 * "Powered by SugarCRM".
35 ********************************************************************************/
37 /*********************************************************************************
39 * Description: Includes generic helper functions used throughout the application.
40 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
41 * All Rights Reserved.
42 * Contributor(s): ______________________________________..
43 ********************************************************************************/
44 require_once('include/SugarObjects/SugarConfig.php');
45 require_once('include/utils/security_utils.php');
49 function make_sugar_config(&$sugar_config)
51 /* used to convert non-array config.php file to array format */
52 global $admin_export_only;
54 global $calculate_response_time;
55 global $create_default_user;
58 global $dbconfigoption;
59 global $default_action;
60 global $default_charset;
61 global $default_currency_name;
62 global $default_currency_symbol;
63 global $default_currency_iso4217;
64 global $defaultDateFormat;
65 global $default_language;
66 global $default_module;
67 global $default_password;
68 global $default_permission_mode;
69 global $default_theme;
70 global $defaultTimeFormat;
71 global $default_user_is_admin;
72 global $default_user_name;
73 global $disable_export;
74 global $disable_persistent_connections;
75 global $display_email_template_variable_chooser;
76 global $display_inbound_email_buttons;
77 global $history_max_viewed;
81 global $list_max_entries_per_page;
82 global $lock_default_user_name;
83 global $log_memory_usage;
85 global $requireAccounts;
86 global $RSS_CACHE_TIME;
90 global $sugar_version;
93 global $translation_string_prefix;
95 global $upload_badext;
97 global $upload_maxsize;
98 global $import_max_execution_time;
99 global $list_max_entries_per_subpanel;
100 global $passwordsetting;
102 // assumes the following variables must be set:
103 // $dbconfig, $dbconfigoption, $cache_dir, $session_dir, $site_URL, $upload_dir
105 $sugar_config = array (
106 'admin_export_only' => empty($admin_export_only) ? false : $admin_export_only,
107 'export_delimiter' => empty($export_delimiter) ? ',' : $export_delimiter,
108 'cache_dir' => empty($cache_dir) ? 'cache/' : $cache_dir,
109 'calculate_response_time' => empty($calculate_response_time) ? true : $calculate_response_time,
110 'create_default_user' => empty($create_default_user) ? false : $create_default_user,
111 'chartEngine' => 'Jit',
112 'date_formats' => empty($dateFormats) ? array(
113 'Y-m-d'=>'2010-12-23',
114 'd-m-Y' => '23-12-2010',
115 'm-d-Y'=>'12-23-2010',
116 'Y/m/d'=>'2010/12/23',
117 'd/m/Y' => '23/12/2010',
118 'm/d/Y'=>'12/23/2010',
119 'Y.m.d' => '2010.12.23',
120 'd.m.Y' => '23.12.2010',
121 'm.d.Y' => '12.23.2010'
123 'dbconfig' => $dbconfig, // this must be set!!
124 'dbconfigoption' => $dbconfigoption, // this must be set!!
125 'default_action' => empty($default_action) ? 'index' : $default_action,
126 'default_charset' => empty($default_charset) ? 'UTF-8' : $default_charset,
127 'default_currency_name' => empty($default_currency_name) ? 'US Dollar' : $default_currency_name,
128 'default_currency_symbol' => empty($default_currency_symbol) ? '$' : $default_currency_symbol,
129 'default_currency_iso4217' => empty($default_currency_iso4217) ? '$' : $default_currency_iso4217,
130 'default_date_format' => empty($defaultDateFormat) ? 'm/d/Y' : $defaultDateFormat,
131 'default_locale_name_format' => empty($defaultNameFormat) ? 's f l' : $defaultNameFormat,
132 'default_export_charset' => 'UTF-8',
133 'default_language' => empty($default_language) ? 'en_us' : $default_language,
134 'default_module' => empty($default_module) ? 'Home' : $default_module,
135 'default_password' => empty($default_password) ? '' : $default_password,
136 'default_permissions' => array (
142 'default_theme' => empty($default_theme) ? 'Sugar5' : $default_theme,
143 'default_time_format' => empty($defaultTimeFormat) ? 'h:ia' : $defaultTimeFormat,
144 'default_user_is_admin' => empty($default_user_is_admin) ? false : $default_user_is_admin,
145 'default_user_name' => empty($default_user_name) ? '' : $default_user_name,
146 'disable_export' => empty($disable_export) ? false : $disable_export,
147 'disable_persistent_connections' => empty($disable_persistent_connections) ? false : $disable_persistent_connections,
148 'display_email_template_variable_chooser' => empty($display_email_template_variable_chooser) ? false : $display_email_template_variable_chooser,
149 'display_inbound_email_buttons' => empty($display_inbound_email_buttons) ? false : $display_inbound_email_buttons,
150 'history_max_viewed' => empty($history_max_viewed) ? 50 : $history_max_viewed,
151 'host_name' => empty($host_name) ? 'localhost' : $host_name,
152 'import_dir' => $import_dir, // this must be set!!
153 'import_max_records_per_file' => 100,
154 'import_max_records_total_limit' => '',
155 'languages' => empty($languages) ? array('en_us' => 'English (US)') : $languages,
156 'list_max_entries_per_page' => empty($list_max_entries_per_page) ? 20 : $list_max_entries_per_page,
157 'list_max_entries_per_subpanel' => empty($list_max_entries_per_subpanel) ? 10 : $list_max_entries_per_subpanel,
158 'lock_default_user_name' => empty($lock_default_user_name) ? false : $lock_default_user_name,
159 'log_memory_usage' => empty($log_memory_usage) ? false : $log_memory_usage,
160 'name_formats' => empty($nameFormats) ? array(
161 's f l' => 's f l', 'f l' => 'f l', 's l' => 's l', 'l, s f' => 'l, s f',
162 'l, f' => 'l, f', 's l, f' => 's l, f', 'l s f' => 'l s f', 'l f s' => 'l f s'
164 'portal_view' => 'single_user',
165 'resource_management' => array (
166 'special_query_limit' => 50000,
167 'special_query_modules' => array('Reports', 'Export', 'Import', 'Administration', 'Sync'),
168 'default_limit' => 1000,
170 'require_accounts' => empty($requireAccounts) ? true : $requireAccounts,
171 'rss_cache_time' => empty($RSS_CACHE_TIME) ? '10800' : $RSS_CACHE_TIME,
172 'session_dir' => $session_dir, // this must be set!!
173 'site_url' => empty($site_URL) ? $site_url : $site_URL, // this must be set!!
174 'showDetailData' => true, // if true, read-only ACL fields will still appear on EditViews as non-editable
175 'showThemePicker' => true,
176 'sugar_version' => empty($sugar_version) ? 'unknown' : $sugar_version,
177 'time_formats' => empty($timeFormats) ? array (
178 'H:i'=>'23:00', 'h:ia'=>'11:00 pm', 'h:iA'=>'11:00PM',
179 'H.i'=>'23.00', 'h.ia'=>'11.00 pm', 'h.iA'=>'11.00PM' ) : $timeFormats,
180 'tmp_dir' => $tmp_dir, // this must be set!!
181 'translation_string_prefix' => empty($translation_string_prefix) ? false : $translation_string_prefix,
182 'unique_key' => empty($unique_key) ? md5(create_guid()) : $unique_key,
183 'upload_badext' => empty($upload_badext) ? array (
184 'php', 'php3', 'php4', 'php5', 'pl', 'cgi', 'py',
185 'asp', 'cfm', 'js', 'vbs', 'html', 'htm' ) : $upload_badext,
186 'upload_dir' => $upload_dir, // this must be set!!
187 'upload_maxsize' => empty($upload_maxsize) ? 30000000 : $upload_maxsize,
188 'import_max_execution_time' => empty($import_max_execution_time) ? 3600 : $import_max_execution_time,
189 'lock_homepage' => false,
190 'lock_subpanels' => false,
191 'max_dashlets_homepage' => 15,
192 'dashlet_display_row_options' => array('1','3','5','10'),
193 'default_max_tabs' => empty($max_tabs) ? '7' : $max_tabs,
194 'default_subpanel_tabs' => empty($subpanel_tabs) ? true : $subpanel_tabs,
195 'default_subpanel_links' => empty($subpanel_links) ? false : $subpanel_links,
196 'default_swap_last_viewed' => empty($swap_last_viewed) ? false : $swap_last_viewed,
197 'default_swap_shortcuts' => empty($swap_shortcuts) ? false : $swap_shortcuts,
198 'default_navigation_paradigm' => empty($navigation_paradigm) ? 'gm' : $navigation_paradigm,
199 'default_call_status' => 'Planned',
200 'js_lang_version' => 1,
201 'passwordsetting' => empty($passwordsetting) ? array (
202 'SystemGeneratedPasswordON' => '',
203 'generatepasswordtmpl' => '',
204 'lostpasswordtmpl' => '',
205 'forgotpasswordON' => true,
206 'linkexpiration' => '1',
207 'linkexpirationtime' => '30',
208 'linkexpirationtype' => '1',
209 'systexpiration' => '0',
210 'systexpirationtime' => '',
211 'systexpirationtype' => '0',
212 'systexpirationlogin' => '',
213 ) : $passwordsetting,
214 'use_sprites' => function_exists('imagecreatetruecolor'),
218 function get_sugar_config_defaults() {
221 * used for getting base values for array style config.php. used by the
222 * installer and to fill in new entries on upgrades. see also:
226 $sugar_config_defaults = array (
227 'admin_export_only' => false,
228 'export_delimiter' => ',',
229 'cache_dir' => 'cache/',
230 'calculate_response_time' => true,
231 'create_default_user' => false,
232 'chartEngine' => 'Jit',
233 'date_formats' => array (
234 'Y-m-d' => '2010-12-23', 'm-d-Y' => '12-23-2010', 'd-m-Y' => '23-12-2010',
235 'Y/m/d' => '2010/12/23', 'm/d/Y' => '12/23/2010', 'd/m/Y' => '23/12/2010',
236 'Y.m.d' => '2010.12.23', 'd.m.Y' => '23.12.2010', 'm.d.Y' => '12.23.2010',),
237 'name_formats' => array (
238 's f l' => 's f l', 'f l' => 'f l', 's l' => 's l', 'l, s f' => 'l, s f',
239 'l, f' => 'l, f', 's l, f' => 's l, f', 'l s f' => 'l s f', 'l f s' => 'l f s'
241 'dbconfigoption' => array (
242 'persistent' => true,
246 'default_action' => 'index',
247 'default_charset' => return_session_value_or_default('default_charset',
249 'default_currency_name' => return_session_value_or_default('default_currency_name', 'US Dollar'),
250 'default_currency_symbol' => return_session_value_or_default('default_currency_symbol', '$'),
251 'default_currency_iso4217' => return_session_value_or_default('default_currency_iso4217', 'USD'),
252 'default_currency_significant_digits' => return_session_value_or_default('default_currency_significant_digits', 2),
253 'default_number_grouping_seperator' => return_session_value_or_default('default_number_grouping_seperator', ','),
254 'default_decimal_seperator' => return_session_value_or_default('default_decimal_seperator', '.'),
255 'default_date_format' => 'm/d/Y',
256 'default_locale_name_format' => 's f l',
257 'default_export_charset' => 'UTF-8',
258 'default_language' => return_session_value_or_default('default_language',
260 'default_module' => 'Home',
261 'default_password' => '',
262 'default_permissions' => array (
268 'default_theme' => return_session_value_or_default('site_default_theme', 'Sugar5'),
269 'default_time_format' => 'h:ia',
270 'default_user_is_admin' => false,
271 'default_user_name' => '',
272 'disable_export' => false,
273 'disable_persistent_connections' =>
274 return_session_value_or_default('disable_persistent_connections',
276 'display_email_template_variable_chooser' => false,
277 'display_inbound_email_buttons' => false,
278 'dump_slow_queries' => false,
279 'email_default_editor' => 'html',
280 'email_default_client' => 'sugar',
281 'email_default_delete_attachments' => true,
282 'history_max_viewed' => 50,
283 'installer_locked' => true,
284 'import_max_records_per_file' => 100,
285 'import_max_records_total_limit' => '',
286 'languages' => array('en_us' => 'English (US)'),
287 'large_scale_test' => false,
288 'list_max_entries_per_page' => 20,
289 'list_max_entries_per_subpanel' => 10,
290 'lock_default_user_name' => false,
291 'log_memory_usage' => false,
292 'portal_view' => 'single_user',
293 'resource_management' => array (
294 'special_query_limit' => 50000,
295 'special_query_modules' => array('Reports', 'Export', 'Import', 'Administration', 'Sync'),
296 'default_limit' => 1000,
298 'require_accounts' => true,
299 'rss_cache_time' => return_session_value_or_default('rss_cache_time',
301 'save_query' => 'all',
302 'showDetailData' => true, // if true, read-only ACL fields will still appear on EditViews as non-editable
303 'showThemePicker' => true,
304 'slow_query_time_msec' => '100',
306 'time_formats' => array (
307 'H:i'=>'23:00', 'h:ia'=>'11:00pm', 'h:iA'=>'11:00PM', 'h:i a'=>'11:00 pm', 'h:i A'=>'11:00 PM',
308 'H.i'=>'23.00', 'h.ia'=>'11.00pm', 'h.iA'=>'11.00PM', 'h.i a'=>'11.00 pm', 'h.i A'=>'11.00 PM' ),
309 'tracker_max_display_length' => 15,
310 'translation_string_prefix' =>
311 return_session_value_or_default('translation_string_prefix', false),
312 'upload_badext' => array (
313 'php', 'php3', 'php4', 'php5', 'pl', 'cgi', 'py',
314 'asp', 'cfm', 'js', 'vbs', 'html', 'htm' ),
315 'upload_maxsize' => 30000000,
316 'import_max_execution_time' => 3600,
317 // 'use_php_code_json' => returnPhpJsonStatus(),
318 'verify_client_ip' => true,
319 'js_custom_version' => '',
320 'js_lang_version' => 1,
321 'lead_conv_activity_opt' => 'donothing',
322 'default_number_grouping_seperator' => ',',
323 'default_decimal_seperator' => '.',
324 'lock_homepage' => false,
325 'lock_subpanels' => false,
326 'max_dashlets_homepage' => '15',
327 'default_max_tabs' => '7',
328 'dashlet_display_row_options' => array('1','3','5','10'),
329 'default_subpanel_tabs' => true,
330 'default_subpanel_links' => false,
331 'default_swap_last_viewed' => false,
332 'default_swap_shortcuts' => false,
333 'default_navigation_paradigm' => 'gm',
334 'admin_access_control' => false,
335 'use_common_ml_dir' => false,
336 'common_ml_dir' => '',
339 'default_view' => 'week',
340 'show_calls_by_default' => true,
341 'show_tasks_by_default' => true,
342 'editview_width' => 990,
343 'editview_height' => 480,
344 'day_timestep' => 15,
345 'week_timestep' => 30,
346 'month_timestep' => 60,
347 'items_draggable' => true,
348 'mouseover_expand' => true,
350 'passwordsetting' => empty($passwordsetting) ? array (
351 'SystemGeneratedPasswordON' => '',
352 'generatepasswordtmpl' => '',
353 'lostpasswordtmpl' => '',
354 'forgotpasswordON' => false,
355 'linkexpiration' => '1',
356 'linkexpirationtime' => '30',
357 'linkexpirationtype' => '1',
358 'systexpiration' => '0',
359 'systexpirationtime' => '',
360 'systexpirationtype' => '0',
361 'systexpirationlogin' => '',
362 ) : $passwordsetting,
363 'use_real_names' => true,
366 if(!is_object($locale)) {
367 $locale = new Localization();
370 $sugar_config_defaults['default_currencies'] = $locale->getDefaultCurrencies();
372 $sugar_config_defaults = sugarArrayMerge($locale->getLocaleConfigDefaults(), $sugar_config_defaults);
373 return( $sugar_config_defaults );
377 * @deprecated use SugarView::getMenu() instead
379 function load_menu($path){
382 if(file_exists($path . 'Menu.php'))
384 require($path . 'Menu.php');
386 if(file_exists('custom/' . $path . 'Ext/Menus/menu.ext.php'))
388 require('custom/' . $path . 'Ext/Menus/menu.ext.php');
390 if(file_exists('custom/application/Ext/Menus/menu.ext.php'))
392 require('custom/application/Ext/Menus/menu.ext.php');
398 * get_notify_template_file
399 * This function will return the location of the email notifications template to use
401 * @return string relative file path to email notifications template file
403 function get_notify_template_file($language){
405 * Order of operation:
406 * 1) custom version of specified language
407 * 2) stock version of specified language
408 * 3) custom version of en_us template
409 * 4) stock en_us template
412 // set $file to the base code template so it's set if none of the conditions pass
413 $file = "include/language/en_us.notify_template.html";
415 if(file_exists("custom/include/language/{$language}.notify_template.html")){
416 $file = "custom/include/language/{$language}.notify_template.html";
418 else if(file_exists("include/language/{$language}.notify_template.html")){
419 $file = "include/language/{$language}.notify_template.html";
421 else if(file_exists("custom/include/language/en_us.notify_template.html")){
422 $file = "custom/include/language/en_us.notify_template.html";
428 function sugar_config_union( $default, $override ){
429 // a little different then array_merge and array_merge_recursive. we want
430 // the second array to override the first array if the same value exists,
431 // otherwise merge the unique keys. it handles arrays of arrays recursively
432 // might be suitable for a generic array_union
433 if( !is_array( $override ) ){
436 foreach( $default as $key => $value ){
437 if( !array_key_exists($key, $override) ){
438 $override[$key] = $value;
440 else if( is_array( $key ) ){
441 $override[$key] = sugar_config_union( $value, $override[$key] );
447 function make_not_writable( $file ){
448 // Returns true if the given file/dir has been made not writable
450 if( is_file($file) || is_dir($file) ){
451 if( !is_writable($file) ){
455 $original_fileperms = fileperms($file);
457 // take away writable permissions
458 $new_fileperms = $original_fileperms & ~0x0092;
459 @sugar_chmod($file, $new_fileperms);
461 if( !is_writable($file) ){
470 /** This function returns the name of the person.
471 * It currently returns "first last". It should not put the space if either name is not available.
472 * It should not return errors if either name is not available.
473 * If no names are present, it will return ""
474 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
475 * All Rights Reserved.
476 * Contributor(s): ______________________________________..
478 function return_name($row, $first_column, $last_column)
484 if(isset($row[$first_column]))
486 $first_name = stripslashes($row[$first_column]);
489 if(isset($row[$last_column]))
491 $last_name = stripslashes($row[$last_column]);
494 $full_name = $first_name;
496 // If we have a first name and we have a last name
497 if($full_name != "" && $last_name != "")
499 // append a space, then the last name
500 $full_name .= " ".$last_name;
502 // If we have no first name, but we have a last name
503 else if($last_name != "")
505 // append the last name without the space.
506 $full_name .= $last_name;
513 function get_languages()
515 global $sugar_config;
516 $lang = $sugar_config['languages'];
517 if(!empty($sugar_config['disabled_languages'])){
518 foreach(explode(',', $sugar_config['disabled_languages']) as $disable) {
519 unset($lang[$disable]);
525 function get_all_languages()
527 global $sugar_config;
528 return $sugar_config['languages'];
532 function get_language_display($key)
534 global $sugar_config;
535 return $sugar_config['languages'][$key];
538 function get_assigned_user_name($assigned_user_id, $is_group = '') {
539 static $saved_user_list = null;
541 if(empty($saved_user_list)) {
542 $saved_user_list = get_user_array(false, '', '', false, null, $is_group);
545 if(isset($saved_user_list[$assigned_user_id])) {
546 return $saved_user_list[$assigned_user_id];
553 * retrieves the user_name column value (login)
554 * @param string id GUID of user
557 function get_user_name($id) {
561 $db = DBManagerFactory::getInstance();
563 $q = "SELECT user_name FROM users WHERE id='{$id}'";
565 $a = $db->fetchByAssoc($r);
567 return (empty($a)) ? '' : $a['user_name'];
571 //TODO Update to use global cache
575 * This is a helper function to return an Array of users depending on the parameters passed into the function.
576 * This function uses the get_register_value function by default to use a caching layer where supported.
578 * @param bool $add_blank Boolean value to add a blank entry to the array results, true by default
579 * @param string $status String value indicating the status to filter users by, "Active" by default
580 * @param string $user_id String value to specify a particular user id value (searches the id column of users table), blank by default
581 * @param bool $use_real_name Boolean value indicating whether or not results should include the full name or just user_name, false by default
582 * @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
583 * @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
584 * @param bool $from_cache Boolean value indicating whether or not to use the get_register_value function for caching, true by default
585 * @return array Array of users matching the filter criteria that may be from cache (if similar search was previously run)
587 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) {
589 global $sugar_config;
592 $locale = new Localization();
596 $key_name = $add_blank. $status . $user_id . $use_real_name . $user_name_filter . $portal_filter;
597 $user_array = get_register_value('user_array', $key_name);
600 if(empty($user_array)) {
601 $db = DBManagerFactory::getInstance();
602 $temp_result = Array();
603 // Including deleted users for now.
604 if (empty($status)) {
605 $query = "SELECT id, first_name, last_name, user_name from users WHERE 1=1".$portal_filter;
608 $query = "SELECT id, first_name, last_name, user_name from users WHERE status='$status'".$portal_filter;
611 if (!empty($user_name_filter)) {
612 $query .= " AND user_name LIKE '$user_name_filter%' ";
614 if (!empty($user_id)) {
615 $query .= " OR id='{$user_id}'";
617 $query = $query.' ORDER BY user_name ASC';
618 $GLOBALS['log']->debug("get_user_array query: $query");
619 $result = $db->query($query, true, "Error filling in user array: ");
621 if ($add_blank==true) {
622 // Add in a blank row
623 $temp_result[''] = '';
626 // Get the id and the name.
627 while($row = $db->fetchByAssoc($result)) {
628 if($use_real_name == true || showFullName()) {
629 if(isset($row['last_name'])) { // cn: we will ALWAYS have both first_name and last_name (empty value if blank in db)
630 $temp_result[$row['id']] = $locale->getLocaleFormattedName($row['first_name'],$row['last_name']);
632 $temp_result[$row['id']] = $row['user_name'];
635 $temp_result[$row['id']] = $row['user_name'];
639 $user_array = $temp_result;
642 set_register_value('user_array', $key_name, $temp_result);
652 * uses a different query to return a list of users than get_user_array()
653 * @param args string where clause entry
654 * @return array Array of Users' details that match passed criteria
656 function getUserArrayFromFullName($args, $hide_portal_users = false) {
658 $db = DBManagerFactory::getInstance();
661 if(strpos($args, " ")) {
662 $argArray = explode(" ", $args);
668 foreach($argArray as $arg) {
669 if(!empty($inClause)) {
675 $inClause .= "(first_name LIKE '{$arg}%' OR last_name LIKE '{$arg}%')";
678 $query = "SELECT id, first_name, last_name, user_name FROM users WHERE status='Active' AND deleted=0 AND ";
679 if ( $hide_portal_users ) {
680 $query .= " portal_only=0 AND ";
683 $query .= " ORDER BY last_name ASC";
685 $r = $db->query($query);
687 while($a = $db->fetchByAssoc($r)) {
688 $ret[$a['id']] = $locale->getLocaleFormattedName($a['first_name'], $a['last_name']);
696 * based on user pref then system pref
698 function showFullName() {
699 global $sugar_config;
700 global $current_user;
701 static $showFullName = null;
703 if (is_null($showFullName)) {
704 $sysPref = !empty($sugar_config['use_real_names']);
705 $userPref = (is_object($current_user)) ? $current_user->getPreference('use_real_names') : null;
707 if($userPref != null) {
708 $showFullName = ($userPref == 'on');
710 $showFullName = $sysPref;
714 return $showFullName;
717 function clean($string, $maxLength)
719 $string = substr($string, 0, $maxLength);
720 return escapeshellcmd($string);
724 * Copy the specified request variable to the member variable of the specified object.
725 * Do no copy if the member variable is already set.
726 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
727 * All Rights Reserved.
728 * Contributor(s): ______________________________________..
730 function safe_map($request_var, & $focus, $always_copy = false)
732 safe_map_named($request_var, $focus, $request_var, $always_copy);
736 * Copy the specified request variable to the member variable of the specified object.
737 * Do no copy if the member variable is already set.
738 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
739 * All Rights Reserved.
740 * Contributor(s): ______________________________________..
742 function safe_map_named($request_var, & $focus, $member_var, $always_copy)
744 if (isset($_REQUEST[$request_var]) && ($always_copy || is_null($focus->$member_var))) {
745 $GLOBALS['log']->debug("safe map named called assigning '{$_REQUEST[$request_var]}' to $member_var");
746 $focus->$member_var = $_REQUEST[$request_var];
751 * This function retrieves an application language file and returns the array of strings included in the $app_list_strings var.
753 * @param string $language specific language to load
754 * @return array lang strings
756 function return_app_list_strings_language($language)
758 global $app_list_strings;
759 global $sugar_config;
761 $cache_key = 'app_list_strings.'.$language;
763 // Check for cached value
764 $cache_entry = sugar_cache_retrieve($cache_key);
765 if(!empty($cache_entry))
770 $default_language = $sugar_config['default_language'];
771 $temp_app_list_strings = $app_list_strings;
774 if ($language != 'en_us') {
777 if ($default_language != 'en_us' && $language != $default_language) {
778 $langs[] = $default_language;
780 $langs[] = $language;
782 $app_list_strings_array = array();
784 foreach ( $langs as $lang ) {
785 $app_list_strings = array();
786 if(file_exists("include/language/$lang.lang.php")) {
787 include("include/language/$lang.lang.php");
788 $GLOBALS['log']->info("Found language file: $lang.lang.php");
790 if(file_exists("include/language/$lang.lang.override.php")) {
791 include("include/language/$lang.lang.override.php");
792 $GLOBALS['log']->info("Found override language file: $lang.lang.override.php");
794 if(file_exists("include/language/$lang.lang.php.override")) {
795 include("include/language/$lang.lang.php.override");
796 $GLOBALS['log']->info("Found override language file: $lang.lang.php.override");
799 $app_list_strings_array[] = $app_list_strings;
802 $app_list_strings = array();
803 foreach ( $app_list_strings_array as $app_list_strings_item ) {
804 $app_list_strings = sugarArrayMerge($app_list_strings, $app_list_strings_item);
807 foreach ( $langs as $lang ) {
808 if(file_exists("custom/application/Ext/Language/$lang.lang.ext.php")) {
809 $app_list_strings = _mergeCustomAppListStrings("custom/application/Ext/Language/$lang.lang.ext.php" , $app_list_strings);
810 $GLOBALS['log']->info("Found extended language file: $lang.lang.ext.php");
812 if(file_exists("custom/include/language/$lang.lang.php")) {
813 include("custom/include/language/$lang.lang.php");
814 $GLOBALS['log']->info("Found custom language file: $lang.lang.php");
818 if(!isset($app_list_strings)) {
819 $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");
823 $return_value = $app_list_strings;
824 $app_list_strings = $temp_app_list_strings;
826 sugar_cache_put($cache_key, $return_value);
828 return $return_value;
832 * The dropdown items in custom language files is $app_list_strings['$key']['$second_key'] = $value not
833 * $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.
834 * @param file string the language that you want include,
835 * @param app_list_strings array the golbal strings
839 function _mergeCustomAppListStrings($file , $app_list_strings){
840 $app_list_strings_original = $app_list_strings;
841 unset($app_list_strings);
842 // FG - bug 45525 - $exemptDropdown array is defined (once) here, not inside the foreach
843 // This way, language file can add items to save specific standard codelist from being overwritten
844 $exemptDropdowns = array();
846 if(!isset($app_list_strings) || !is_array($app_list_strings)){
847 return $app_list_strings_original;
849 //Bug 25347: We should not merge custom dropdown fields unless they relate to parent fields or the module list.
851 // FG - bug 45525 - Specific codelists must NOT be overwritten
852 $exemptDropdowns[] = "moduleList";
853 $exemptDropdowns[] = "parent_type_display";
854 $exemptDropdowns[] = "record_type_display";
855 $exemptDropdowns[] = "record_type_display_notes";
857 foreach($app_list_strings as $key=>$value)
859 if (!in_array($key, $exemptDropdowns) && array_key_exists($key, $app_list_strings_original))
861 unset($app_list_strings_original["$key"]);
864 $app_list_strings = sugarArrayMergeRecursive($app_list_strings_original , $app_list_strings);
865 return $app_list_strings;
869 * This function retrieves an application language file and returns the array of strings included.
871 * @param string $language specific language to load
872 * @return array lang strings
874 function return_application_language($language)
876 global $app_strings, $sugar_config;
878 $cache_key = 'app_strings.'.$language;
880 // Check for cached value
881 $cache_entry = sugar_cache_retrieve($cache_key);
882 if(!empty($cache_entry))
887 $temp_app_strings = $app_strings;
888 $default_language = $sugar_config['default_language'];
891 if ($language != 'en_us') {
894 if ($default_language != 'en_us' && $language != $default_language) {
895 $langs[] = $default_language;
898 $langs[] = $language;
900 $app_strings_array = array();
902 foreach ( $langs as $lang ) {
903 $app_strings = array();
904 if(file_exists("include/language/$lang.lang.php")) {
905 include("include/language/$lang.lang.php");
906 $GLOBALS['log']->info("Found language file: $lang.lang.php");
908 if(file_exists("include/language/$lang.lang.override.php")) {
909 include("include/language/$lang.lang.override.php");
910 $GLOBALS['log']->info("Found override language file: $lang.lang.override.php");
912 if(file_exists("include/language/$lang.lang.php.override")) {
913 include("include/language/$lang.lang.php.override");
914 $GLOBALS['log']->info("Found override language file: $lang.lang.php.override");
916 if(file_exists("custom/application/Ext/Language/$lang.lang.ext.php")) {
917 include("custom/application/Ext/Language/$lang.lang.ext.php");
918 $GLOBALS['log']->info("Found extended language file: $lang.lang.ext.php");
920 if(file_exists("custom/include/language/$lang.lang.php")) {
921 include("custom/include/language/$lang.lang.php");
922 $GLOBALS['log']->info("Found custom language file: $lang.lang.php");
924 $app_strings_array[] = $app_strings;
927 $app_strings = array();
928 foreach ( $app_strings_array as $app_strings_item ) {
929 $app_strings = sugarArrayMerge($app_strings, $app_strings_item);
932 if(!isset($app_strings)) {
933 $GLOBALS['log']->fatal("Unable to load the application language strings");
937 // If we are in debug mode for translating, turn on the prefix now!
938 if($sugar_config['translation_string_prefix']) {
939 foreach($app_strings as $entry_key=>$entry_value) {
940 $app_strings[$entry_key] = $language.' '.$entry_value;
943 if(isset($_SESSION['show_deleted'])) {
944 $app_strings['LBL_DELETE_BUTTON'] = $app_strings['LBL_UNDELETE_BUTTON'];
945 $app_strings['LBL_DELETE_BUTTON_LABEL'] = $app_strings['LBL_UNDELETE_BUTTON_LABEL'];
946 $app_strings['LBL_DELETE_BUTTON_TITLE'] = $app_strings['LBL_UNDELETE_BUTTON_TITLE'];
947 $app_strings['LBL_DELETE'] = $app_strings['LBL_UNDELETE'];
950 $app_strings['LBL_ALT_HOT_KEY'] = get_alt_hot_key();
952 $return_value = $app_strings;
953 $app_strings = $temp_app_strings;
955 sugar_cache_put($cache_key, $return_value);
957 return $return_value;
961 * This function retrieves a module's language file and returns the array of strings included.
963 * @param string $language specific language to load
964 * @param string $module module name to load strings for
965 * @param bool $refresh optional, true if you want to rebuild the language strings
966 * @return array lang strings
968 function return_module_language($language, $module, $refresh=false)
971 global $sugar_config;
972 global $currentModule;
974 // Jenny - Bug 8119: Need to check if $module is not empty
975 if (empty($module)) {
976 $stack = debug_backtrace();
977 $GLOBALS['log']->warn("Variable module is not in return_module_language ". var_export($stack, true));
983 $cache_key = LanguageManager::getLanguageCacheKey($module, $language);
984 // Check for cached value
985 $cache_entry = sugar_cache_retrieve($cache_key);
986 if(!empty($cache_entry))
991 // Store the current mod strings for later
992 $temp_mod_strings = $mod_strings;
993 $loaded_mod_strings = array();
994 $language_used = $language;
995 $default_language = $sugar_config['default_language'];
997 if(empty($language)) {
998 $language = $default_language;
1001 // Bug 21559 - So we can get all the strings defined in the template, refresh
1002 // the vardefs file if the cached language file doesn't exist.
1003 if(!file_exists(sugar_cached('modules/'). $module . '/language/'.$language.'.lang.php')
1004 && !empty($GLOBALS['beanList'][$module])){
1005 $object = BeanFactory::getObjectName($module);
1006 VardefManager::refreshVardefs($module,$object);
1009 $loaded_mod_strings = LanguageManager::loadModuleLanguage($module, $language,$refresh);
1011 // cn: bug 6048 - merge en_us with requested language
1012 if($language != $sugar_config['default_language'])
1013 $loaded_mod_strings = sugarArrayMerge(
1014 LanguageManager::loadModuleLanguage($module, $sugar_config['default_language'],$refresh),
1018 // Load in en_us strings by default
1019 if($language != 'en_us' && $sugar_config['default_language'] != 'en_us')
1020 $loaded_mod_strings = sugarArrayMerge(
1021 LanguageManager::loadModuleLanguage($module, 'en_us', $refresh),
1025 // If we are in debug mode for translating, turn on the prefix now!
1026 if($sugar_config['translation_string_prefix']) {
1027 foreach($loaded_mod_strings as $entry_key=>$entry_value) {
1028 $loaded_mod_strings[$entry_key] = $language_used.' '.$entry_value;
1032 $return_value = $loaded_mod_strings;
1033 if(!isset($mod_strings)){
1034 $mod_strings = $return_value;
1037 $mod_strings = $temp_mod_strings;
1039 $cache_key = LanguageManager::getLanguageCacheKey($module, $language);
1040 sugar_cache_put($cache_key, $return_value);
1041 return $return_value;
1045 /** This function retrieves an application language file and returns the array of strings included in the $mod_list_strings var.
1046 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1047 * All Rights Reserved.
1048 * Contributor(s): ______________________________________..
1049 * If you are using the current language, do not call this function unless you are loading it for the first time */
1050 function return_mod_list_strings_language($language,$module) {
1051 global $mod_list_strings;
1052 global $sugar_config;
1053 global $currentModule;
1055 $cache_key = "mod_list_str_lang.".$language.$module;
1057 // Check for cached value
1058 $cache_entry = sugar_cache_retrieve($cache_key);
1059 if(!empty($cache_entry))
1061 return $cache_entry;
1064 $language_used = $language;
1065 $temp_mod_list_strings = $mod_list_strings;
1066 $default_language = $sugar_config['default_language'];
1068 if($currentModule == $module && isset($mod_list_strings) && $mod_list_strings != null) {
1069 return $mod_list_strings;
1072 // cn: bug 6351 - include en_us if file langpack not available
1073 // cn: bug 6048 - merge en_us with requested language
1074 include("modules/$module/language/en_us.lang.php");
1075 $en_mod_list_strings = array();
1076 if($language_used != $default_language)
1077 $en_mod_list_strings = $mod_list_strings;
1079 if(file_exists("modules/$module/language/$language.lang.php")) {
1080 include("modules/$module/language/$language.lang.php");
1083 if(file_exists("modules/$module/language/$language.lang.override.php")){
1084 include("modules/$module/language/$language.lang.override.php");
1087 if(file_exists("modules/$module/language/$language.lang.php.override")){
1088 echo 'Please Change:<br>' . "modules/$module/language/$language.lang.php.override" . '<br>to<br>' . 'Please Change:<br>' . "modules/$module/language/$language.lang.override.php";
1089 include("modules/$module/language/$language.lang.php.override");
1092 // cn: bug 6048 - merge en_us with requested language
1093 $mod_list_strings = sugarArrayMerge($en_mod_list_strings, $mod_list_strings);
1095 // if we still don't have a language pack, then log an error
1096 if(!isset($mod_list_strings)) {
1097 $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})");
1101 $return_value = $mod_list_strings;
1102 $mod_list_strings = $temp_mod_list_strings;
1104 sugar_cache_put($cache_key, $return_value);
1105 return $return_value;
1109 /** This function retrieves a theme's language file and returns the array of strings included.
1110 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1111 * All Rights Reserved.
1112 * Contributor(s): ______________________________________..
1114 function return_theme_language($language, $theme)
1116 global $mod_strings, $sugar_config, $current_language;
1118 $language_used = $language;
1119 $default_language = $sugar_config['default_language'];
1121 include(SugarThemeRegistry::get($theme)->getFilePath()."/language/$current_language.lang.php");
1122 if(file_exists(SugarThemeRegistry::get($theme)->getFilePath()."/language/$current_language.lang.override.php")){
1123 include(SugarThemeRegistry::get($theme)->getFilePath()."/language/$current_language.lang.override.php");
1125 if(file_exists(SugarThemeRegistry::get($theme)->getFilePath()."/language/$current_language.lang.php.override")){
1126 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";
1127 include(SugarThemeRegistry::get($theme)->getFilePath()."/language/$current_language.lang.php.override");
1129 if(!isset($theme_strings))
1131 $GLOBALS['log']->warn("Unable to find the theme file for language: ".$language." and theme: ".$theme);
1132 require(SugarThemeRegistry::get($theme)->getFilePath()."/language/$default_language.lang.php");
1133 $language_used = $default_language;
1136 if(!isset($theme_strings))
1138 $GLOBALS['log']->fatal("Unable to load the theme($theme) language file for the selected language($language) or the default language($default_language)");
1142 // If we are in debug mode for translating, turn on the prefix now!
1143 if($sugar_config['translation_string_prefix'])
1145 foreach($theme_strings as $entry_key=>$entry_value)
1147 $theme_strings[$entry_key] = $language_used.' '.$entry_value;
1151 return $theme_strings;
1156 /** If the session variable is defined and is not equal to "" then return it. Otherwise, return the default value.
1157 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1158 * All Rights Reserved.
1159 * Contributor(s): ______________________________________..
1161 function return_session_value_or_default($varname, $default)
1163 if(isset($_SESSION[$varname]) && $_SESSION[$varname] != "")
1165 return $_SESSION[$varname];
1172 * Creates an array of where restrictions. These are used to construct a where SQL statement on the query
1173 * 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.
1174 * @param &$where_clauses - The array to append the clause to
1175 * @param $variable_name - The name of the variable to look for an add to the where clause if found
1176 * @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.
1177 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1178 * All Rights Reserved.
1179 * Contributor(s): ______________________________________..
1181 function append_where_clause(&$where_clauses, $variable_name, $SQL_name = null)
1183 if($SQL_name == null)
1185 $SQL_name = $variable_name;
1188 if(isset($_REQUEST[$variable_name]) && $_REQUEST[$variable_name] != "")
1190 array_push($where_clauses, "$SQL_name like '".$GLOBALS['db']->quote($_REQUEST[$variable_name])."%'");
1195 * Generate the appropriate SQL based on the where clauses.
1196 * @param $where_clauses - An Array of individual where clauses stored as strings
1197 * @returns string where_clause - The final SQL where clause to be executed.
1198 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1199 * All Rights Reserved.
1200 * Contributor(s): ______________________________________..
1202 function generate_where_statement($where_clauses)
1205 foreach($where_clauses as $clause)
1212 $GLOBALS['log']->info("Here is the where clause for the list view: $where");
1217 * determines if a passed string matches the criteria for a Sugar GUID
1218 * @param string $guid
1219 * @return bool False on failure
1221 function is_guid($guid) {
1222 if(strlen($guid) != 36) {
1226 if(preg_match("/\w{8}-\w{4}-\w{4}-\w{4}-\w{12}/i", $guid)) {
1235 * A temporary method of generating GUIDs of the correct format for our DB.
1236 * @return String contianing a GUID in the format: aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
1238 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1239 * All Rights Reserved.
1240 * Contributor(s): ______________________________________..
1242 function create_guid()
1244 $microTime = microtime();
1245 list($a_dec, $a_sec) = explode(" ", $microTime);
1247 $dec_hex = dechex($a_dec* 1000000);
1248 $sec_hex = dechex($a_sec);
1250 ensure_length($dec_hex, 5);
1251 ensure_length($sec_hex, 6);
1255 $guid .= create_guid_section(3);
1257 $guid .= create_guid_section(4);
1259 $guid .= create_guid_section(4);
1261 $guid .= create_guid_section(4);
1264 $guid .= create_guid_section(6);
1270 function create_guid_section($characters)
1273 for($i=0; $i<$characters; $i++)
1275 $return .= dechex(mt_rand(0,15));
1280 function ensure_length(&$string, $length)
1282 $strlen = strlen($string);
1283 if($strlen < $length)
1285 $string = str_pad($string,$length,"0");
1287 else if($strlen > $length)
1289 $string = substr($string, 0, $length);
1293 function microtime_diff($a, $b) {
1294 list($a_dec, $a_sec) = explode(" ", $a);
1295 list($b_dec, $b_sec) = explode(" ", $b);
1296 return $b_sec - $a_sec + $b_dec - $a_dec;
1299 // check if Studio is displayed.
1300 function displayStudioForCurrentUser()
1302 global $current_user;
1303 if ( $current_user->isAdmin() ) {
1313 function displayWorkflowForCurrentUser()
1315 $_SESSION['display_workflow_for_user'] = false;
1319 // return an array with all modules where the user is an admin.
1320 function get_admin_modules_for_user($user) {
1321 $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");
1328 return($user->getDeveloperModules());
1332 function get_workflow_admin_modules_for_user($user){
1333 if (isset($_SESSION['get_workflow_admin_modules_for_user'])) {
1334 return $_SESSION['get_workflow_admin_modules_for_user'];
1338 $workflow_mod_list = array();
1339 foreach($moduleList as $module){
1340 $workflow_mod_list[$module] = $module;
1343 // This list is taken from teh previous version of workflow_utils.php
1344 $workflow_mod_list['Tasks'] = "Tasks";
1345 $workflow_mod_list['Calls'] = "Calls";
1346 $workflow_mod_list['Meetings'] = "Meetings";
1347 $workflow_mod_list['Notes'] = "Notes";
1348 $workflow_mod_list['ProjectTask'] = "Project Tasks";
1349 $workflow_mod_list['Leads'] = "Leads";
1350 $workflow_mod_list['Opportunities'] = "Opportunities";
1353 $workflow_admin_modules = array();
1355 return $workflow_admin_modules;
1357 $actions = ACLAction::getUserActions($user->id);
1358 //check for ForecastSchedule because it doesn't exist in $workflow_mod_list
1359 if (isset($actions['ForecastSchedule']['module']['admin']['aclaccess']) && ($actions['ForecastSchedule']['module']['admin']['aclaccess']==ACL_ALLOW_DEV ||
1360 $actions['ForecastSchedule']['module']['admin']['aclaccess']==ACL_ALLOW_ADMIN_DEV)) {
1361 $workflow_admin_modules['Forecasts'] = 'Forecasts';
1363 foreach ($workflow_mod_list as $key=>$val) {
1364 if(!in_array($val, $workflow_admin_modules) && ($val!='iFrames' && $val!='Feeds' && $val!='Home' && $val!='Dashboard'
1365 && $val!='Calendar' && $val!='Activities' && $val!='Reports') &&
1366 ($user->isDeveloperForModule($key))) {
1367 $workflow_admin_modules[$key] = $val;
1370 $_SESSION['get_workflow_admin_modules_for_user'] = $workflow_admin_modules;
1371 return ($workflow_admin_modules);
1374 // Check if user is admin for at least one module.
1375 function is_admin_for_any_module($user) {
1379 if($user->isAdmin()) {
1386 // Check if user is admin for a specific module.
1387 function is_admin_for_module($user,$module) {
1388 if (!isset($user)) {
1391 if ($user->isAdmin()) {
1399 * Check if user id belongs to a system admin.
1400 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1401 * All Rights Reserved.
1402 * Contributor(s): ______________________________________..
1404 function is_admin($user) {
1409 return $user->isAdmin();
1413 * Return the display name for a theme if it exists.
1414 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1415 * All Rights Reserved.
1416 * Contributor(s): ______________________________________..
1418 * @deprecated use SugarThemeRegistry::get($theme)->name instead
1420 function get_theme_display($theme)
1422 return SugarThemeRegistry::get($theme)->name;
1426 * Return an array of directory names.
1427 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1428 * All Rights Reserved.
1429 * Contributor(s): ______________________________________..
1431 * @deprecated use SugarThemeRegistry::availableThemes() instead.
1433 function get_themes()
1435 return SugarThemeRegistry::availableThemes();
1439 * THIS FUNCTION IS DEPRECATED AND SHOULD NOT BE USED; USE get_select_options_with_id()
1440 * Create HTML to display select options in a dropdown list. To be used inside
1441 * of a select statement in a form.
1442 * param $option_list - the array of strings to that contains the option list
1443 * param $selected - the string which contains the default value
1444 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1445 * All Rights Reserved.
1446 * Contributor(s): ______________________________________..
1448 function get_select_options ($option_list, $selected) {
1449 return get_select_options_with_id($option_list, $selected);
1453 * Create HTML to display select options in a dropdown list. To be used inside
1454 * 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.
1455 * param $option_list - the array of strings to that contains the option list
1456 * param $selected - the string which contains the default value
1457 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1458 * All Rights Reserved.
1459 * Contributor(s): ______________________________________..
1461 function get_select_options_with_id ($option_list, $selected_key) {
1462 return get_select_options_with_id_separate_key($option_list, $option_list, $selected_key);
1467 * Create HTML to display select options in a dropdown list. To be used inside
1468 * 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.
1469 * param $label_list - the array of strings to that contains the option list
1470 * param $key_list - the array of strings to that contains the values list
1471 * param $selected - the string which contains the default value
1472 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1473 * All Rights Reserved.
1474 * Contributor(s): ______________________________________..
1476 function get_select_options_with_id_separate_key ($label_list, $key_list, $selected_key, $massupdate=false) {
1477 global $app_strings;
1478 $select_options = "";
1480 //for setting null selection values to human readable --None--
1481 $pattern = "/'0?'></";
1482 $replacement = "''>".$app_strings['LBL_NONE']."<";
1484 $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
1487 if (empty($key_list)) $key_list = array();
1488 //create the type dropdown domain and set the selected value if $opp value already exists
1489 foreach ($key_list as $option_key=>$option_value) {
1491 $selected_string = '';
1492 // the system is evaluating $selected_key == 0 || '' to true. Be very careful when changing this. Test all cases.
1493 // The bug was only happening with one of the users in the drop down. It was being replaced by none.
1494 if (($option_key != '' && $selected_key == $option_key) || ($selected_key == '' && $option_key == '' && !$massupdate) || (is_array($selected_key) && in_array($option_key, $selected_key)))
1496 $selected_string = 'selected ';
1499 $html_value = $option_key;
1501 $select_options .= "\n<OPTION ".$selected_string."value='$html_value'>$label_list[$option_key]</OPTION>";
1503 $select_options = preg_replace($pattern, $replacement, $select_options);
1504 return $select_options;
1509 * Call this method instead of die().
1510 * Then we call the die method with the error message that is passed in.
1512 function sugar_die($error_message)
1516 die($error_message);
1521 * Create javascript to clear values of all elements in a form.
1522 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1523 * All Rights Reserved.
1524 * Contributor(s): ______________________________________..
1526 function get_clear_form_js () {
1527 $the_script = <<<EOQ
1528 <script type="text/javascript" language="JavaScript">
1529 function clear_form(form) {
1530 var newLoc = 'index.php?action=' + form.action.value + '&module=' + form.module.value + '&query=true&clear_query=true';
1531 if(typeof(form.advanced) != 'undefined'){
1532 newLoc += '&advanced=' + form.advanced.value;
1534 document.location.href= newLoc;
1543 * Create javascript to set the cursor focus to specific field in a form
1544 * when the screen is rendered. The field name is currently hardcoded into the
1546 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1547 * All Rights Reserved.
1548 * Contributor(s): ______________________________________..
1550 function get_set_focus_js () {
1551 //TODO Clint 5/20 - Make this function more generic so that it can take in the target form and field names as variables
1552 $the_script = <<<EOQ
1553 <script type="text/javascript" language="JavaScript">
1555 function set_focus() {
1556 if (document.forms.length > 0) {
1557 for (i = 0; i < document.forms.length; i++) {
1558 for (j = 0; j < document.forms[i].elements.length; j++) {
1559 var field = document.forms[i].elements[j];
1560 if ((field.type == "text" || field.type == "textarea" || field.type == "password") &&
1561 !field.disabled && (field.name == "first_name" || field.name == "name" || field.name == "user_name" || field.name=="document_name")) {
1563 if (field.type == "text") {
1580 * Very cool algorithm for sorting multi-dimensional arrays. Found at http://us2.php.net/manual/en/function.array-multisort.php
1581 * Syntax: $new_array = array_csort($array [, 'col1' [, SORT_FLAG [, SORT_FLAG]]]...);
1582 * Explanation: $array is the array you want to sort, 'col1' is the name of the column
1583 * you want to sort, SORT_FLAGS are : SORT_ASC, SORT_DESC, SORT_REGULAR, SORT_NUMERIC, SORT_STRING
1584 * you can repeat the 'col',FLAG,FLAG, as often you want, the highest prioritiy is given to
1585 * the first - so the array is sorted by the last given column first, then the one before ...
1586 * Example: $array = array_csort($array,'town','age',SORT_DESC,'name');
1587 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1588 * All Rights Reserved.
1589 * Contributor(s): ______________________________________..
1591 function array_csort() {
1592 $args = func_get_args();
1593 $marray = array_shift($args);
1596 $msortline = "return(array_multisort(";
1597 foreach ($args as $arg) {
1599 if (is_string($arg)) {
1600 foreach ($marray as $row) {
1601 $sortarr[$i][] = $row[$arg];
1604 $sortarr[$i] = $arg;
1606 $msortline .= "\$sortarr[".$i."],";
1608 $msortline .= "\$marray));";
1615 * Converts localized date format string to jscalendar format
1616 * Example: $array = array_csort($array,'town','age',SORT_DESC,'name');
1617 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1618 * All Rights Reserved.
1619 * Contributor(s): ______________________________________..
1621 function parse_calendardate($local_format) {
1622 preg_match('/\(?([^-]{1})[^-]*-([^-]{1})[^-]*-([^-]{1})[^-]*\)/', $local_format, $matches);
1623 $calendar_format = "%" . $matches[1] . "-%" . $matches[2] . "-%" . $matches[3];
1624 return str_replace(array("y", "ᅣ1�7", "a", "j"), array("Y", "Y", "Y", "d"), $calendar_format);
1631 function translate($string, $mod='', $selectedValue=''){
1632 //$test_start = microtime();
1633 //static $mod_strings_results = array();
1635 global $current_language;
1637 if(isset($_REQUEST['login_language'])){
1638 $current_language = ($_REQUEST['login_language'] == $current_language)? $current_language : $_REQUEST['login_language'];
1640 $mod_strings = return_module_language($current_language, $mod);
1643 global $mod_strings;
1647 global $app_strings, $app_list_strings;
1649 if(isset($mod_strings[$string]))
1650 $returnValue = $mod_strings[$string];
1651 else if(isset($app_strings[$string]))
1652 $returnValue = $app_strings[$string];
1653 else if(isset($app_list_strings[$string]))
1654 $returnValue = $app_list_strings[$string];
1655 else if(isset($app_list_strings['moduleList']) && isset($app_list_strings['moduleList'][$string]))
1656 $returnValue = $app_list_strings['moduleList'][$string];
1659 //$test_end = microtime();
1661 // $mod_strings_results[$mod] = microtime_diff($test_start,$test_end);
1663 // echo("translate results:");
1665 // $total_strings = 0;
1666 // foreach($mod_strings_results as $key=>$value)
1668 // echo("Module $key \t\t time $value \t\t<br>");
1669 // $total_time += $value;
1672 // echo("Total time: $total_time<br>");
1676 if(empty($returnValue)){
1680 if(is_array($returnValue) && ! empty($selectedValue) && isset($returnValue[$selectedValue]) ){
1681 return $returnValue[$selectedValue];
1684 return $returnValue;
1687 function unTranslateNum($num) {
1689 static $num_grp_sep;
1690 global $current_user, $sugar_config;
1692 if($dec_sep == null) {
1693 $user_dec_sep = $current_user->getPreference('dec_sep');
1694 $dec_sep = (empty($user_dec_sep) ? $sugar_config['default_decimal_seperator'] : $user_dec_sep);
1696 if($num_grp_sep == null) {
1697 $user_num_grp_sep = $current_user->getPreference('num_grp_sep');
1698 $num_grp_sep = (empty($user_num_grp_sep) ? $sugar_config['default_number_grouping_seperator'] : $user_num_grp_sep);
1701 $num = preg_replace("'" . preg_quote($num_grp_sep) . "'", '', $num);
1702 $num = preg_replace("'" . preg_quote($dec_sep) . "'", '.', $num);
1707 function add_http($url) {
1708 if(!preg_match("@://@i", $url)) {
1710 if(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') {
1714 return "{$scheme}://{$url}";
1721 * returns a default array of XSS tags to clean
1724 function getDefaultXssTags() {
1726 "applet" => "applet",
1731 "frameset" => "frameset",
1732 "iframe" => "iframe",
1733 "import" => "\?import",
1736 "object" => "object",
1737 "script" => "script",
1741 $ret = base64_encode(serialize($tmp));
1747 * Remove potential xss vectors from strings
1748 * @param string str String to search for XSS attack vectors
1749 * @param bool cleanImg Flag to allow <img> tags to survive - only used by InboundEmail for inline images.
1752 function remove_xss($str, $cleanImg=true)
1754 $potentials = clean_xss($str, $cleanImg);
1755 if(is_array($potentials) && !empty($potentials)) {
1756 foreach($potentials as $bad) {
1757 $str = str_replace($bad, "", $str);
1764 * Detects typical XSS attack patterns
1765 * @param string str String to search for XSS attack vectors
1766 * @param bool cleanImg Flag to allow <img> tags to survive - only used by InboundEmail for inline images.
1767 * @return array Array of matches, empty on clean string
1769 function clean_xss($str, $cleanImg=true) {
1770 global $sugar_config;
1772 if(empty($sugar_config['email_xss']))
1773 $sugar_config['email_xss'] = getDefaultXssTags();
1775 $xsstags = unserialize(base64_decode($sugar_config['email_xss']));
1777 // cn: bug 13079 - "on\w" matched too many non-events (cONTact, strONG, etc.)
1778 $jsEvents = "onblur|onfocus|oncontextmenu|onresize|onscroll|onunload|ondblclick|onclick|";
1779 $jsEvents .= "onmouseup|onmouseover|onmousedown|onmouseenter|onmouseleave|onmousemove|onload|onchange|";
1780 $jsEvents .= "onreset|onselect|onsubmit|onkeydown|onkeypress|onkeyup|onabort|onerror|ondragdrop";
1782 $attribute_regex = "#\b({$jsEvents})\s*=\s*(?|(?!['\"])\S+|['\"].+?['\"])#sim";
1783 $javascript_regex = '@<[^/>][^>]+(expression\(|j\W*a\W*v\W*a|v\W*b\W*s\W*c\W*r|&#|/\*|\*/)[^>]*>@sim';
1784 $imgsrc_regex = '#<[^>]+src[^=]*=([^>]*?http(s)?://[^>]*)>#sim';
1785 $css_url = '#url\(.*\.\w+\)#';
1787 $tagsrex = '#<\/?(\w+)((?:\s+(?:\w|\w[\w-]*\w)(?:\s*=\s*(?:\".*?\"|\'.*?\'|[^\'\">\s]+))?)+\s*|\s*)\/?>#im';
1789 $tagmatches = array();
1791 preg_match_all($tagsrex, $str, $tagmatches, PREG_PATTERN_ORDER);
1792 foreach($tagmatches[1] as $no => $tag) {
1793 if(in_array($tag, $xsstags)) {
1794 // dangerous tag - take out whole
1795 $matches[] = $tagmatches[0][$no];
1798 $attrmatch = array();
1799 preg_match_all($attribute_regex, $tagmatches[2][$no], $attrmatch, PREG_PATTERN_ORDER);
1800 if(!empty($attrmatch[0])) {
1801 $matches = array_merge($matches, $attrmatch[0]);
1805 $matches = array_merge($matches, xss_check_pattern($javascript_regex, $str));
1808 $matches = array_merge($matches,
1809 xss_check_pattern($imgsrc_regex, $str)
1813 // cn: bug 13498 - custom white-list of allowed domains that vet remote images
1814 preg_match_all($css_url, $str, $cssUrlMatches, PREG_PATTERN_ORDER);
1816 if(isset($sugar_config['security_trusted_domains']) && !empty($sugar_config['security_trusted_domains']) && is_array($sugar_config['security_trusted_domains'])) {
1817 if(is_array($cssUrlMatches) && count($cssUrlMatches) > 0) {
1818 // normalize whitelist
1819 foreach($sugar_config['security_trusted_domains'] as $k => $v) {
1820 $sugar_config['security_trusted_domains'][$k] = strtolower($v);
1823 foreach($cssUrlMatches[0] as $match) {
1824 $domain = strtolower(substr(strstr($match, "://"), 3));
1825 $baseUrl = substr($domain, 0, strpos($domain, "/"));
1827 if(!in_array($baseUrl, $sugar_config['security_trusted_domains'])) {
1828 $matches[] = $match;
1833 $matches = array_merge($matches, $cssUrlMatches[0]);
1840 * Helper function used by clean_xss() to parse for known-bad vectors
1841 * @param string pattern Regex pattern to use
1842 * @param string str String to parse for badness
1845 function xss_check_pattern($pattern, $str) {
1846 preg_match_all($pattern, $str, $matches, PREG_PATTERN_ORDER);
1851 * Designed to take a string passed in the URL as a parameter and clean all "bad" data from it
1853 * @param string $str
1854 * @param string $filter which corresponds to a regular expression to use; choices are:
1855 * "STANDARD" ( default )
1865 * @param boolean $dieOnBadData true (default) if you want to die if bad data if found, false if not
1867 function clean_string($str, $filter = "STANDARD", $dieOnBadData = true)
1869 global $sugar_config;
1872 "STANDARD" => '#[^A-Z0-9\-_\.\@]#i',
1873 "STANDARDSPACE" => '#[^A-Z0-9\-_\.\@\ ]#i',
1874 "FILE" => '#[^A-Z0-9\-_\.]#i',
1875 "NUMBER" => '#[^0-9\-]#i',
1876 "SQL_COLUMN_LIST" => '#[^A-Z0-9\(\),_\.]#i',
1877 "PATH_NO_URL" => '#://#i',
1878 "SAFED_GET" => '#[^A-Z0-9\@\=\&\?\.\/\-_~+]#i', /* range of allowed characters in a GET string */
1879 "UNIFIED_SEARCH" => "#[\\x00]#", /* cn: bug 3356 & 9236 - MBCS search strings */
1880 "AUTO_INCREMENT" => '#[^0-9\-,\ ]#i',
1881 "ALPHANUM" => '#[^A-Z0-9\-]#i',
1884 if (preg_match($filters[$filter], $str)) {
1885 if (isset($GLOBALS['log']) && is_object($GLOBALS['log'])) {
1886 $GLOBALS['log']->fatal("SECURITY[$filter]: bad data passed in; string: {$str}");
1888 if ( $dieOnBadData ) {
1889 die("Bad data passed in; <a href=\"{$sugar_config['site_url']}\">Return to Home</a>");
1898 function clean_special_arguments() {
1899 if(isset($_SERVER['PHP_SELF'])) {
1900 if (!empty($_SERVER['PHP_SELF'])) clean_string($_SERVER['PHP_SELF'], 'SAFED_GET');
1902 if (!empty($_REQUEST) && !empty($_REQUEST['login_theme'])) clean_string($_REQUEST['login_theme'], "STANDARD");
1903 if (!empty($_REQUEST) && !empty($_REQUEST['login_module'])) clean_string($_REQUEST['login_module'], "STANDARD");
1904 if (!empty($_REQUEST) && !empty($_REQUEST['login_action'])) clean_string($_REQUEST['login_action'], "STANDARD");
1905 if (!empty($_REQUEST) && !empty($_REQUEST['ck_login_theme_20'])) clean_string($_REQUEST['ck_login_theme_20'], "STANDARD");
1906 if (!empty($_SESSION) && !empty($_SESSION['authenticated_user_theme'])) clean_string($_SESSION['authenticated_user_theme'], "STANDARD");
1907 if (!empty($_REQUEST) && !empty($_REQUEST['module_name'])) clean_string($_REQUEST['module_name'], "STANDARD");
1908 if (!empty($_REQUEST) && !empty($_REQUEST['module'])) clean_string($_REQUEST['module'], "STANDARD");
1909 if (!empty($_POST) && !empty($_POST['parent_type'])) clean_string($_POST['parent_type'], "STANDARD");
1910 if (!empty($_REQUEST) && !empty($_REQUEST['mod_lang'])) clean_string($_REQUEST['mod_lang'], "STANDARD");
1911 if (!empty($_SESSION) && !empty($_SESSION['authenticated_user_language'])) clean_string($_SESSION['authenticated_user_language'], "STANDARD");
1912 if (!empty($_SESSION) && !empty($_SESSION['dyn_layout_file'])) clean_string($_SESSION['dyn_layout_file'], "PATH_NO_URL");
1913 if (!empty($_GET) && !empty($_GET['from'])) clean_string($_GET['from']);
1914 if (!empty($_GET) && !empty($_GET['gmto'])) clean_string($_GET['gmto'], "NUMBER");
1915 if (!empty($_GET) && !empty($_GET['case_number'])) clean_string($_GET['case_number'], "AUTO_INCREMENT");
1916 if (!empty($_GET) && !empty($_GET['bug_number'])) clean_string($_GET['bug_number'], "AUTO_INCREMENT");
1917 if (!empty($_GET) && !empty($_GET['quote_num'])) clean_string($_GET['quote_num'], "AUTO_INCREMENT");
1918 clean_superglobals('stamp', 'ALPHANUM'); // for vcr controls
1919 clean_superglobals('offset', 'ALPHANUM');
1920 clean_superglobals('return_action');
1921 clean_superglobals('return_module');
1926 * cleans the given key in superglobals $_GET, $_POST, $_REQUEST
1928 function clean_superglobals($key, $filter = 'STANDARD') {
1929 if(isset($_GET[$key])) clean_string($_GET[$key], $filter);
1930 if(isset($_POST[$key])) clean_string($_POST[$key], $filter);
1931 if(isset($_REQUEST[$key])) clean_string($_REQUEST[$key], $filter);
1934 function set_superglobals($key, $val){
1936 $_POST[$key] = $val;
1937 $_REQUEST[$key] = $val;
1940 // Works in conjunction with clean_string() to defeat SQL injection, file inclusion attacks, and XSS
1941 function clean_incoming_data() {
1942 global $sugar_config;
1943 global $RAW_REQUEST;
1945 if(get_magic_quotes_gpc()) {
1946 // magic quotes screw up data, we'd have to clean up
1947 $RAW_REQUEST = array_map("cleanup_slashes", $_REQUEST);
1949 $RAW_REQUEST = $_REQUEST;
1952 if (get_magic_quotes_gpc() == 1) {
1953 $req = array_map("preprocess_param", $_REQUEST);
1954 $post = array_map("preprocess_param", $_POST);
1955 $get = array_map("preprocess_param", $_GET);
1958 $req = array_map("securexss", $_REQUEST);
1959 $post = array_map("securexss", $_POST);
1960 $get = array_map("securexss", $_GET);
1963 // PHP cannot stomp out superglobals reliably
1964 foreach($post as $k => $v) { $_POST[$k] = $v; }
1965 foreach($get as $k => $v) { $_GET[$k] = $v; }
1966 foreach($req as $k => $v) {
1968 //ensure the keys are safe as well
1971 // Any additional variables that need to be cleaned should be added here
1972 if (isset($_REQUEST['login_theme'])) clean_string($_REQUEST['login_theme']);
1973 if (isset($_REQUEST['login_module'])) clean_string($_REQUEST['login_module']);
1974 if (isset($_REQUEST['login_action'])) clean_string($_REQUEST['login_action']);
1975 if (isset($_REQUEST['login_language'])) clean_string($_REQUEST['login_language']);
1976 if (isset($_REQUEST['action'])) clean_string($_REQUEST['action']);
1977 if (isset($_REQUEST['module'])) clean_string($_REQUEST['module']);
1978 if (isset($_REQUEST['record'])) clean_string($_REQUEST['record'], 'STANDARDSPACE');
1979 if (isset($_SESSION['authenticated_user_theme'])) clean_string($_SESSION['authenticated_user_theme']);
1980 if (isset($_SESSION['authenticated_user_language'])) clean_string($_SESSION['authenticated_user_language']);
1981 if (isset($_REQUEST['language'])) clean_string($_REQUEST['language']);
1982 if (isset($sugar_config['default_theme'])) clean_string($sugar_config['default_theme']);
1983 if (isset($_REQUEST['offset'])) clean_string($_REQUEST['offset']);
1984 if (isset($_REQUEST['stamp'])) clean_string($_REQUEST['stamp']);
1986 if(isset($_REQUEST['lvso'])){
1987 set_superglobals('lvso', (strtolower($_REQUEST['lvso']) === 'desc')?'desc':'asc');
1989 // Clean "offset" and "order_by" parameters in URL
1990 foreach ($_REQUEST as $key => $val) {
1991 if (str_end($key, "_offset")) {
1992 clean_string($_REQUEST[$key], "ALPHANUM"); // keep this ALPHANUM for disable_count_query
1993 set_superglobals($key, $_REQUEST[$key]);
1995 elseif (str_end($key, "_ORDER_BY")) {
1996 clean_string($_REQUEST[$key], "SQL_COLUMN_LIST");
1997 set_superglobals($key, $_REQUEST[$key]);
2005 // Returns TRUE if $str begins with $begin
2006 function str_begin($str, $begin) {
2007 return (substr($str, 0, strlen($begin)) == $begin);
2010 // Returns TRUE if $str ends with $end
2011 function str_end($str, $end) {
2012 return (substr($str, strlen($str) - strlen($end)) == $end);
2015 function securexss($value) {
2016 if(is_array($value)){
2018 foreach($value as $key=>$val){
2019 $new[$key] = securexss($val);
2023 static $xss_cleanup= array(""" => "&", '"' =>'"', "'" => ''' , '<' =>'<' , '>'=>'>');
2024 $value = preg_replace(array('/javascript:/i', '/\0/'), array('java script:', ''), $value);
2025 $value = preg_replace('/javascript:/i', 'java script:', $value);
2026 return str_replace(array_keys($xss_cleanup), array_values($xss_cleanup), $value);
2029 function securexsskey($value, $die=true){
2030 global $sugar_config;
2032 preg_match('/[\'"<>]/', $value, $matches);
2033 if(!empty($matches)){
2035 die("Bad data passed in; <a href=\"{$sugar_config['site_url']}\">Return to Home</a>");
2037 unset($_REQUEST[$value]);
2038 unset($_POST[$value]);
2039 unset($_GET[$value]);
2044 function preprocess_param($value){
2045 if(is_string($value)){
2046 if(get_magic_quotes_gpc() == 1){
2047 $value = stripslashes($value);
2050 $value = securexss($value);
2056 function cleanup_slashes($value)
2058 if(is_string($value)) return stripslashes($value);
2063 function set_register_value($category, $name, $value){
2064 return sugar_cache_put("{$category}:{$name}", $value);
2067 function get_register_value($category,$name){
2068 return sugar_cache_retrieve("{$category}:{$name}");
2071 function clear_register_value($category,$name){
2072 return sugar_cache_clear("{$category}:{$name}");
2074 // this function cleans id's when being imported
2075 function convert_id($string)
2077 return preg_replace_callback( '|[^A-Za-z0-9\-]|',
2079 // single quotes are essential here,
2080 // or alternative escape all $ as \$
2082 'return ord($matches[0]);'
2087 * @deprecated use SugarTheme::getImage()
2089 function get_image($image,$other_attributes,$width="",$height="",$ext='.gif',$alt)
2091 return SugarThemeRegistry::current()->getImage(basename($image), $other_attributes, empty($width) ? null : $width, empty($height) ? null : $height, $ext, $alt );
2094 * @deprecated use SugarTheme::getImageURL()
2096 function getImagePath($image_name)
2098 return SugarThemeRegistry::current()->getImageURL($image_name);
2101 function getWebPath($relative_path){
2102 //if it has a :// then it isn't a relative path
2103 if(substr_count($relative_path, '://') > 0) return $relative_path;
2104 if(defined('TEMPLATE_URL'))$relative_path = SugarTemplateUtilities::getWebPath($relative_path);
2105 return $relative_path;
2108 function getVersionedPath($path, $additional_attrs='')
2110 if(empty($GLOBALS['sugar_config']['js_custom_version'])) $GLOBALS['sugar_config']['js_custom_version'] = 1;
2111 $js_version_key = isset($GLOBALS['js_version_key'])?$GLOBALS['js_version_key']:'';
2112 if(inDeveloperMode()) {
2114 if(empty($rand)) $rand = mt_rand();
2119 if(is_array($additional_attrs)) {
2120 $additional_attrs = join("|",$additional_attrs);
2122 // cutting 2 last chars here because since md5 is 32 chars, it's always ==
2123 $str = substr(base64_encode(md5("$js_version_key|{$GLOBALS['sugar_config']['js_custom_version']}|$dev|$additional_attrs", true)), 0, -2);
2124 // remove / - it confuses some parsers
2125 $str = strtr($str, '/+', '-_');
2126 if(empty($path)) return $str;
2128 return $path . "?v=$str";
2131 function getVersionedScript($path, $additional_attrs='')
2133 return '<script type="text/javascript" src="'.getVersionedPath($path, $additional_attrs).'"></script>';
2136 function getJSPath($relative_path, $additional_attrs='')
2138 if(defined('TEMPLATE_URL'))$relative_path = SugarTemplateUtilities::getWebPath($relative_path);
2139 return getVersionedPath($relative_path).(!empty($additional_attrs)?"&$additional_attrs":"");
2142 function getSWFPath($relative_path, $additional_params=''){
2143 $path = $relative_path;
2144 if (!empty($additional_params)){
2145 $path .= '?' . $additional_params;
2147 if (defined('TEMPLATE_URL')){
2148 $path = TEMPLATE_URL . '/' . $path;
2157 function getSQLDate($date_str)
2159 if (preg_match('/^(\d{1,2})-(\d{1,2})-(\d{4})$/',$date_str,$match))
2161 if ( strlen($match[2]) == 1)
2163 $match[2] = "0".$match[2];
2165 if ( strlen($match[1]) == 1)
2167 $match[1] = "0".$match[1];
2169 return "{$match[3]}-{$match[1]}-{$match[2]}";
2171 else if (preg_match('/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/',$date_str,$match))
2173 if ( strlen($match[2]) == 1)
2175 $match[2] = "0".$match[2];
2177 if ( strlen($match[1]) == 1)
2179 $match[1] = "0".$match[1];
2181 return "{$match[3]}-{$match[1]}-{$match[2]}";
2189 function clone_history(&$db, $from_id,$to_id, $to_type)
2194 require_once('include/upload_file.php');
2195 $tables = array('calls'=>'Call', 'meetings'=>'Meeting', 'notes'=>'Note', 'tasks'=>'Task');
2197 $location=array('Email'=>"modules/Emails/Email.php",
2198 'Call'=>"modules/Calls/Call.php",
2199 'Meeting'=>"modules/Meetings/Meeting.php",
2200 'Note'=>"modules/Notes/Note.php",
2201 'Tasks'=>"modules/Tasks/Task.php",
2205 foreach($tables as $table=>$bean_class)
2208 if (!class_exists($bean_class))
2210 require_once($location[$bean_class]);
2213 $bProcessingNotes=false;
2214 if ($table=='notes')
2216 $bProcessingNotes=true;
2218 $query = "SELECT id FROM $table WHERE parent_id='$from_id'";
2219 $results = $db->query($query);
2220 while($row = $db->fetchByAssoc($results))
2222 //retrieve existing record.
2223 $bean= new $bean_class();
2224 $bean->retrieve($row['id']);
2225 //process for new instance.
2226 if ($bProcessingNotes)
2228 $old_note_id=$row['id'];
2229 $old_filename=$bean->filename;
2232 $bean->parent_id=$to_id;
2233 $bean->parent_type=$to_type;
2234 if ($to_type=='Contacts' and in_array('contact_id',$bean->column_fields))
2236 $bean->contact_id=$to_id;
2238 $bean->update_date_modified = false;
2239 $bean->update_modified_by = false;
2240 if(isset($bean->date_modified))
2241 $bean->date_modified = $timedate->to_db($bean->date_modified);
2242 if(isset($bean->date_entered))
2243 $bean->date_entered = $timedate->to_db($bean->date_entered);
2245 $new_id=$bean->save();
2247 //duplicate the file now. for notes.
2248 if ($bProcessingNotes && !empty($old_filename))
2250 UploadFile::duplicate_file($old_note_id,$new_id,$old_filename);
2252 //reset the values needed for attachment duplication.
2259 function values_to_keys($array)
2261 $new_array = array();
2262 if(!is_array($array))
2266 foreach($array as $arr){
2267 $new_array[$arr] = $arr;
2272 function clone_relationship(&$db, $tables = array(), $from_column, $from_id, $to_id)
2274 foreach($tables as $table)
2277 if ($table == 'emails_beans') {
2278 $query = "SELECT * FROM $table WHERE $from_column='$from_id' and bean_module='Leads'";
2280 $query = "SELECT * FROM $table WHERE $from_column='$from_id'";
2282 $results = $db->query($query);
2283 while($row = $db->fetchByAssoc($results))
2285 $query = "INSERT INTO $table ";
2288 $row[$from_column] = $to_id;
2289 $row['id'] = create_guid();
2290 if ($table=='emails_beans') {
2291 $row['bean_module'] =='Contacts';
2294 foreach($row as $name=>$value)
2300 $values .= "'$value'";
2303 $names .= ', '. $name;
2304 $values .= ", '$value'";
2307 $query .= "($names) VALUES ($values)";
2313 function get_unlinked_email_query($type, $bean) {
2314 global $current_user;
2316 $return_array['select']='SELECT emails.id ';
2317 $return_array['from']='FROM emails ';
2318 $return_array['where']="";
2319 $return_array['join'] = " JOIN (select DISTINCT email_id from emails_email_addr_rel eear
2321 join email_addr_bean_rel eabr on eabr.bean_id ='$bean->id' and eabr.bean_module = '$bean->module_dir' and
2322 eabr.email_address_id = eear.email_address_id and eabr.deleted=0
2323 where eear.deleted=0 and eear.email_id not in
2324 (select eb.email_id from emails_beans eb where eb.bean_module ='$bean->module_dir' and eb.bean_id = '$bean->id')
2325 ) derivedemails on derivedemails.email_id = emails.id";
2326 $return_array['join_tables'][0] = '';
2328 if (isset($type) and !empty($type['return_as_array'])) {
2329 return $return_array;
2332 return $return_array['select'] . $return_array['from'] . $return_array['where'] . $return_array['join'] ;
2336 * Check to see if the number is empty or non-zero
2340 function number_empty($value)
2342 return empty($value) && $value != '0';
2345 function get_bean_select_array($add_blank=true, $bean_name, $display_columns, $where='', $order_by='', $blank_is_none=false)
2348 require_once($beanFiles[$bean_name]);
2349 $focus = new $bean_name();
2350 $user_array = array();
2352 $key = ($bean_name == 'EmailTemplate') ? $bean_name : $bean_name . $display_columns. $where . $order_by;
2353 $user_array = get_register_value('select_array', $key );
2357 $db = DBManagerFactory::getInstance();
2359 $temp_result = Array();
2360 $query = "SELECT {$focus->table_name}.id, {$display_columns} as display from {$focus->table_name} ";
2364 $query .= $where." AND ";
2367 $query .= " {$focus->table_name}.deleted=0";
2369 if ( $order_by != '')
2371 $query .= " order by {$focus->table_name}.{$order_by}";
2374 $GLOBALS['log']->debug("get_user_array query: $query");
2375 $result = $db->query($query, true, "Error filling in user array: ");
2377 if ($add_blank==true){
2378 // Add in a blank row
2379 if($blank_is_none == true) { // set 'blank row' to "--None--"
2380 global $app_strings;
2381 $temp_result[''] = $app_strings['LBL_NONE'];
2383 $temp_result[''] = '';
2387 // Get the id and the name.
2388 while($row = $db->fetchByAssoc($result))
2390 $temp_result[$row['id']] = $row['display'];
2393 $user_array = $temp_result;
2394 set_register_value('select_array', $key ,$temp_result);
2403 * @param unknown_type $listArray
2405 // function parse_list_modules
2406 // searches a list for items in a user's allowed tabs and returns an array that removes unallowed tabs from list
2407 function parse_list_modules(&$listArray)
2409 global $modListHeader;
2410 $returnArray = array();
2412 foreach($listArray as $optionName => $optionVal)
2414 if(array_key_exists($optionName, $modListHeader))
2416 $returnArray[$optionName] = $optionVal;
2419 // special case for projects
2420 if(array_key_exists('Project', $modListHeader))
2422 $returnArray['ProjectTask'] = $listArray['ProjectTask'];
2425 $acldenied = ACLController::disabledModuleList($listArray,false);
2426 foreach($acldenied as $denied){
2427 unset($returnArray[$denied]);
2429 asort($returnArray);
2431 return $returnArray;
2434 function display_notice($msg = false){
2435 global $error_notice;
2436 //no error notice - lets just display the error to the user
2437 if(!isset($error_notice)){
2438 echo '<br>'.$msg . '<br>';
2440 $error_notice .= $msg . '<br>';
2444 /* checks if it is a number that atleast has the plus at the beggining
2446 function skype_formatted($number){
2447 //kbrill - BUG #15375
2448 if(isset($_REQUEST['action']) && $_REQUEST['action']=="Popup") {
2451 return substr($number, 0, 1) == '+' || substr($number, 0, 2) == '00' || substr($number, 0, 3) == '011';
2453 // return substr($number, 0, 1) == '+' || substr($number, 0, 2) == '00' || substr($number, 0, 2) == '011';
2456 function format_skype($number) {
2457 return preg_replace('/[^\+0-9]/','',$number);
2460 function insert_charset_header() {
2461 header('Content-Type: text/html; charset=UTF-8');
2464 function getCurrentURL()
2467 if(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on')
2472 $href.= "//".$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME'].'?'.$_SERVER['QUERY_STRING'];
2476 function javascript_escape($str) {
2479 for($i = 0; $i < strlen($str); $i++) {
2481 if(ord(substr($str, $i, 1))==10){
2483 }elseif(ord(substr($str, $i, 1))==13){
2487 $new_str .= $str{$i};
2491 $new_str = str_replace("'", "\\'", $new_str);
2496 function js_escape($str, $keep=true){
2497 $str = html_entity_decode(str_replace("\\", "", $str), ENT_QUOTES);
2500 $str = javascript_escape($str);
2503 $str = str_replace("'", " ", $str);
2504 $str = str_replace('"', " ", $str);
2509 //end function js_escape
2512 function br2nl($str) {
2513 $regex = "#<[^>]+br.+?>#i";
2514 preg_match_all($regex, $str, $matches);
2516 foreach($matches[0] as $match) {
2517 $str = str_replace($match, "<br>", $str);
2520 $brs = array('<br>','<br/>', '<br />');
2521 $str = str_replace("\r\n", "\n", $str); // make from windows-returns, *nix-returns
2522 $str = str_replace("\n\r", "\n", $str); // make from windows-returns, *nix-returns
2523 $str = str_replace("\r", "\n", $str); // make from windows-returns, *nix-returns
2524 $str = str_ireplace($brs, "\n", $str); // to retrieve it
2530 * Private helper function for displaying the contents of a given variable.
2531 * This function is only intended to be used for SugarCRM internal development.
2532 * The ppd stands for Pre Print Die.
2534 function _ppd($mixed)
2540 * Private helper function for displaying the contents of a given variable in
2541 * the Logger. This function is only intended to be used for SugarCRM internal
2542 * development. The pp stands for Pre Print.
2543 * @param $mixed var to print_r()
2544 * @param $die boolean end script flow
2545 * @param $displayStackTrace also show stack trace
2547 function _ppl($mixed, $die=false, $displayStackTrace=false, $loglevel="fatal") {
2548 if(!isset($GLOBALS['log']) || empty($GLOBALS['log'])) {
2550 $GLOBALS['log'] = LoggerManager :: getLogger('SugarCRM');
2554 $mix = print_r($mixed, true); // send print_r() output to $mix
2555 $stack = debug_backtrace();
2557 $GLOBALS['log']->$loglevel('------------------------------ _ppLogger() output start -----------------------------');
2558 $GLOBALS['log']->$loglevel($mix);
2559 if($displayStackTrace) {
2560 foreach($stack as $position) {
2561 $GLOBALS['log']->$loglevel($position['file']."({$position['line']})");
2565 $GLOBALS['log']->$loglevel('------------------------------ _ppLogger() output end -----------------------------');
2566 $GLOBALS['log']->$loglevel('------------------------------ _ppLogger() file: '.$stack[0]['file'].' line#: '.$stack[0]['line'].'-----------------------------');
2574 * private helper function to quickly show the major, direct, field attributes of a given bean.
2575 * The ppf stands for Pre[formatted] Print Focus [object]
2576 * @param object bean The focus bean
2578 function _ppf($bean, $die=false) {
2584 * Private helper function for displaying the contents of a given variable.
2585 * This function is only intended to be used for SugarCRM internal development.
2586 * The pp stands for Pre Print.
2588 function _pp($mixed)
2593 * Private helper function for displaying the contents of a given variable.
2594 * This function is only intended to be used for SugarCRM internal development.
2595 * The pp stands for Pre Print.
2597 function _pstack_trace($mixed=NULL)
2602 * Private helper function for displaying the contents of a given variable.
2603 * This function is only intended to be used for SugarCRM internal development.
2604 * The pp stands for Pre Print Trace.
2606 function _ppt($mixed, $textOnly=false)
2611 * Private helper function for displaying the contents of a given variable.
2612 * This function is only intended to be used for SugarCRM internal development.
2613 * The pp stands for Pre Print Trace Die.
2615 function _pptd($mixed)
2620 * Private helper function for decoding javascript UTF8
2621 * This function is only intended to be used for SugarCRM internal development.
2623 function decodeJavascriptUTF8($str) {
2627 * Will check if a given PHP version string is supported (tested on this ver),
2628 * unsupported (results unknown), or invalid (something will break on this
2629 * ver). Do not pass in any pararameter to default to a check against the
2630 * current environment's PHP version.
2632 * @return 1 implies supported, 0 implies unsupported, -1 implies invalid
2634 function check_php_version($sys_php_version = '') {
2635 $sys_php_version = empty($sys_php_version) ? constant('PHP_VERSION') : $sys_php_version;
2636 // versions below $min_considered_php_version considered invalid by default,
2637 // versions equal to or above this ver will be considered depending
2638 // on the rules that follow
2639 $min_considered_php_version = '5.2.1';
2641 // only the supported versions,
2642 // should be mutually exclusive with $invalid_php_versions
2643 $supported_php_versions = array (
2644 '5.2.1', '5.2.2', '5.2.3', '5.2.4', '5.2.5', '5.2.6', '5.2.8', '5.3.0'
2647 // invalid versions above the $min_considered_php_version,
2648 // should be mutually exclusive with $supported_php_versions
2650 // SugarCRM prohibits install on PHP 5.2.7 on all platforms
2651 $invalid_php_versions = array('5.2.7');
2653 // default unsupported
2656 // versions below $min_considered_php_version are invalid
2657 if(1 == version_compare($sys_php_version, $min_considered_php_version, '<')) {
2661 // supported version check overrides default unsupported
2662 foreach($supported_php_versions as $ver) {
2663 if(1 == version_compare($sys_php_version, $ver, 'eq') || strpos($sys_php_version,$ver) !== false) {
2669 // invalid version check overrides default unsupported
2670 foreach($invalid_php_versions as $ver) {
2671 if(1 == version_compare($sys_php_version, $ver, 'eq') && strpos($sys_php_version,$ver) !== false) {
2677 //allow a redhat distro to install, regardless of version. We are assuming the redhat naming convention is followed
2678 //and the php version contains 'rh' characters
2679 if(strpos($sys_php_version, 'rh') !== false) {
2687 * Will check if a given IIS version string is supported (tested on this ver),
2688 * unsupported (results unknown), or invalid (something will break on this
2691 * @return 1 implies supported, 0 implies unsupported, -1 implies invalid
2693 function check_iis_version($sys_iis_version = '') {
2695 $server_software = $_SERVER["SERVER_SOFTWARE"];
2697 if(strpos($server_software,'Microsoft-IIS') !== false && preg_match_all("/^.*\/(\d+\.?\d*)$/", $server_software, $out))
2698 $iis_version = $out[1][0];
2700 $sys_iis_version = empty($sys_iis_version) ? $iis_version : $sys_iis_version;
2702 // versions below $min_considered_iis_version considered invalid by default,
2703 // versions equal to or above this ver will be considered depending
2704 // on the rules that follow
2705 $min_considered_iis_version = '6.0';
2707 // only the supported versions,
2708 // should be mutually exclusive with $invalid_iis_versions
2709 $supported_iis_versions = array ('6.0', '7.0',);
2710 $unsupported_iis_versions = array();
2711 $invalid_iis_versions = array('5.0',);
2713 // default unsupported
2716 // versions below $min_considered_iis_version are invalid
2717 if(1 == version_compare($sys_iis_version, $min_considered_iis_version, '<')) {
2721 // supported version check overrides default unsupported
2722 foreach($supported_iis_versions as $ver) {
2723 if(1 == version_compare($sys_iis_version, $ver, 'eq') || strpos($sys_iis_version,$ver) !== false) {
2729 // unsupported version check overrides default unsupported
2730 foreach($unsupported_iis_versions as $ver) {
2731 if(1 == version_compare($sys_iis_version, $ver, 'eq') && strpos($sys_iis_version,$ver) !== false) {
2737 // invalid version check overrides default unsupported
2738 foreach($invalid_iis_versions as $ver) {
2739 if(1 == version_compare($sys_iis_version, $ver, 'eq') && strpos($sys_iis_version,$ver) !== false) {
2748 function pre_login_check(){
2749 global $action, $login_error;
2750 if(!empty($action)&& $action == 'Login'){
2752 if(!empty($login_error)){
2753 $login_error = htmlentities($login_error);
2754 $login_error = str_replace(array("<pre>","</pre>","\r\n", "\n"), "<br>", $login_error);
2755 $_SESSION['login_error'] = $login_error;
2757 function set_focus() {}
2758 if(document.getElementById("post_error")) {
2759 document.getElementById("post_error").innerHTML="'. $login_error. '";
2760 document.getElementById("cant_login").value=1;
2761 document.getElementById("login_button").disabled = true;
2762 document.getElementById("user_name").disabled = true;
2763 //document.getElementById("user_password").disabled = true;
2772 function sugar_cleanup($exit = false) {
2773 static $called = false;
2776 set_include_path(realpath(dirname(__FILE__) . '/..') . PATH_SEPARATOR . get_include_path());
2777 chdir(realpath(dirname(__FILE__) . '/..'));
2778 global $sugar_config;
2779 require_once('include/utils/LogicHook.php');
2780 LogicHook::initialize();
2781 $GLOBALS['logic_hook']->call_custom_logic('', 'server_round_trip');
2783 //added this check to avoid errors during install.
2784 if (empty($sugar_config['dbconfig'])) {
2785 if ($exit) exit; else return;
2788 if (!class_exists('Tracker', true)) {
2789 require_once 'modules/Trackers/Tracker.php';
2792 // Now write the cached tracker_queries
2793 if(!empty($GLOBALS['savePreferencesToDB']) && $GLOBALS['savePreferencesToDB']) {
2794 if ( isset($GLOBALS['current_user']) && $GLOBALS['current_user'] instanceOf User )
2795 $GLOBALS['current_user']->savePreferencesToDB();
2798 //check to see if this is not an `ajax call AND the user preference error flag is set
2800 (isset($_SESSION['USER_PREFRENCE_ERRORS']) && $_SESSION['USER_PREFRENCE_ERRORS'])
2801 && ($_REQUEST['action']!='modulelistmenu' && $_REQUEST['action']!='DynamicAction')
2802 && (empty($_REQUEST['to_pdf']) || !$_REQUEST['to_pdf'] )
2803 && (empty($_REQUEST['sugar_body_only']) || !$_REQUEST['sugar_body_only'] )
2806 global $app_strings;
2807 //this is not an ajax call and the user preference error flag is set, so reset the flag and print js to flash message
2808 $err_mess = $app_strings['ERROR_USER_PREFS'];
2809 $_SESSION['USER_PREFRENCE_ERRORS'] = false;
2812 ajaxStatus.flashStatus('$err_mess',7000);
2818 if(class_exists('DBManagerFactory')) {
2819 $db = DBManagerFactory::getInstance();
2827 register_shutdown_function('sugar_cleanup');
2831 check_logic_hook - checks to see if your custom logic is in the logic file
2832 if not, it will add it. If the file isn't built yet, it will create the file
2835 function check_logic_hook_file($module_name, $event, $action_array){
2836 require_once('include/utils/logic_utils.php');
2839 if(file_exists("custom/modules/$module_name/logic_hooks.php")){
2841 $hook_array = get_hook_array($module_name);
2843 if(check_existing_element($hook_array, $event, $action_array)==true){
2844 //the hook at hand is present, so do nothing
2849 if(!empty($hook_array[$event]))
2851 $logic_count = count($hook_array[$event]);
2854 if($action_array[0]==""){
2855 $action_array[0] = $logic_count + 1;
2857 $hook_array[$event][] = $action_array;
2860 //end if the file exists already
2863 if($action_array[0]==""){
2864 $action_array[0] = 1;
2866 $hook_array = array();
2867 $hook_array[$event][] = $action_array;
2868 //end if else file exists already
2870 if($add_logic == true){
2872 //reorder array by element[0]
2873 //$hook_array = reorder_array($hook_array, $event);
2874 //!!!Finish this above TODO
2876 $new_contents = replace_or_add_logic_type($hook_array);
2877 write_logic_file($module_name, $new_contents);
2879 //end if add_element is true
2882 //end function check_logic_hook_file
2885 function remove_logic_hook($module_name, $event, $action_array) {
2886 require_once('include/utils/logic_utils.php');
2889 if(file_exists("custom/modules/".$module_name."/logic_hooks.php")){
2890 // The file exists, let's make sure the hook is there
2891 $hook_array = get_hook_array($module_name);
2893 if(check_existing_element($hook_array, $event, $action_array)==true){
2894 // The hook is there, time to take it out.
2896 foreach ( $hook_array[$event] as $i => $hook ) {
2897 // We don't do a full comparison below just in case the filename changes
2898 if ( $hook[0] == $action_array[0]
2899 && $hook[1] == $action_array[1]
2900 && $hook[3] == $action_array[3]
2901 && $hook[4] == $action_array[4] ) {
2902 unset($hook_array[$event][$i]);
2906 $new_contents = replace_or_add_logic_type($hook_array);
2907 write_logic_file($module_name, $new_contents);
2913 function display_stack_trace($textOnly=false){
2915 $stack = debug_backtrace();
2917 echo "\n\n display_stack_trace caller, file: " . $stack[0]['file']. ' line#: ' .$stack[0]['line'];
2925 foreach($stack as $item) {
2931 if(isset($item['file']))
2932 $file = $item['file'];
2933 if(isset($item['class']))
2934 $class = $item['class'];
2935 if(isset($item['line']))
2936 $line = $item['line'];
2937 if(isset($item['function']))
2938 $function = $item['function'];
2942 $out .= '<font color="black"><b>';
2948 $out .= '</b></font><font color="blue">';
2951 $out .= "[L:{$line}]";
2954 $out .= '</font><font color="red">';
2957 $out .= "({$class}:{$function})";
2960 $out .= '</font><br>';
2972 function StackTraceErrorHandler($errno, $errstr, $errfile,$errline, $errcontext) {
2973 $error_msg = " $errstr occured in <b>$errfile</b> on line $errline [" . date("Y-m-d H:i:s") . ']';
2974 $halt_script = true;
2976 case 2048: return; //depricated we have lots of these ignore them
2979 if ( error_reporting() & E_NOTICE ) {
2980 $halt_script = false;
2986 case E_USER_WARNING:
2987 case E_COMPILE_WARNING:
2988 case E_CORE_WARNING:
2991 $halt_script = false;
2996 case E_COMPILE_ERROR:
3000 $type = "Fatal Error";
3005 $type = "Parse Error";
3009 //don't know what it is might not be so bad
3010 $halt_script = false;
3011 $type = "Unknown Error ($errno)";
3014 $error_msg = '<b>'.$type.'</b>:' . $error_msg;
3016 display_stack_trace();
3026 if(isset($sugar_config['stack_trace_errors']) && $sugar_config['stack_trace_errors']){
3028 set_error_handler('StackTraceErrorHandler');
3030 function get_sub_cookies($name){
3032 if(isset($_COOKIE[$name])){
3033 $subs = explode('#', $_COOKIE[$name]);
3034 foreach($subs as $cookie){
3035 if(!empty($cookie)){
3036 $cookie = explode('=', $cookie);
3038 $cookies[$cookie[0]] = $cookie[1];
3047 function mark_delete_components($sub_object_array, $run_second_level=false, $sub_sub_array=""){
3049 if(!empty($sub_object_array)){
3051 foreach($sub_object_array as $sub_object){
3053 //run_second level is set to true if you need to remove sub-sub components
3054 if($run_second_level==true){
3056 mark_delete_components($sub_object->get_linked_beans($sub_sub_array['rel_field'],$sub_sub_array['rel_module']));
3058 //end if run_second_level is true
3060 $sub_object->mark_deleted($sub_object->id);
3061 //end foreach sub component
3063 //end if this is not empty
3066 //end function mark_delete_components
3070 * For translating the php.ini memory values into bytes. e.g. input value of '8M' will return 8388608.
3072 function return_bytes($val)
3075 $last = strtolower($val{strlen($val)-1});
3079 // The 'G' modifier is available since PHP 5.1.0
3092 * Adds the href HTML tags around any URL in the $string
3094 function url2html($string) {
3096 $return_string = preg_replace('/(\w+:\/\/)(\S+)/', ' <a href="\\1\\2" target="_new" style="font-weight: normal;">\\1\\2</a>', $string);
3097 return $return_string;
3099 // End customization by Julian
3102 * tries to determine whether the Host machine is a Windows machine
3104 function is_windows() {
3105 static $is_windows = null;
3106 if (!isset($is_windows)) {
3107 $is_windows = strtoupper(substr(PHP_OS, 0, 3)) == 'WIN';
3113 * equivalent for windows filesystem for PHP's is_writable()
3114 * @param string file Full path to the file/dir
3115 * @return bool true if writable
3117 function is_writable_windows($file) {
3118 if($file{strlen($file)-1}=='/') {
3119 return is_writable_windows($file.uniqid(mt_rand()).'.tmp');
3122 // the assumption here is that Windows has an inherited permissions scheme
3123 // any file that is a descendant of an unwritable directory will inherit
3124 // that property and will trigger a failure below.
3129 $file = str_replace("/", '\\', $file);
3131 if(file_exists($file)) {
3132 if (!($f = @sugar_fopen($file, 'r+')))
3138 if(!($f = @sugar_fopen($file, 'w')))
3147 * best guesses Timezone based on webserver's TZ settings
3149 function lookupTimezone($userOffset = 0)
3151 return TimeDate::guessTimezone($userOffset);
3154 function convert_module_to_singular($module_array){
3157 foreach($module_array as $key => $value){
3158 if(!empty($beanList[$value])) $module_array[$key] = $beanList[$value];
3160 if($value=="Cases") {
3161 $module_array[$key] = "Case";
3163 if($key=="projecttask"){
3164 $module_array['ProjectTask'] = "Project Task";
3165 unset($module_array[$key]);
3169 return $module_array;
3171 //end function convert_module_to_singular
3175 * Given the bean_name which may be plural or singular return the singular
3176 * bean_name. This is important when you need to include files.
3178 function get_singular_bean_name($bean_name){
3179 global $beanFiles, $beanList;
3180 if(array_key_exists($bean_name, $beanList)){
3181 return $beanList[$bean_name];
3189 * Given the potential module name (singular name, renamed module name)
3190 * Return the real internal module name.
3192 function get_module_from_singular($singular) {
3194 // find the internal module name for a singular name
3195 if (isset($GLOBALS['app_list_strings']['moduleListSingular'])) {
3197 $singular_modules = $GLOBALS['app_list_strings']['moduleListSingular'];
3199 foreach ($singular_modules as $mod_name=>$sin_name) {
3200 if ($singular == $sin_name and $mod_name != $sin_name) {
3206 // find the internal module name for a renamed module
3207 if (isset($GLOBALS['app_list_strings']['moduleList'])) {
3209 $moduleList = $GLOBALS['app_list_strings']['moduleList'];
3211 foreach ($moduleList as $mod_name=>$name) {
3212 if ($singular == $name and $mod_name != $name) {
3218 // if it's not a singular name, nor a renamed name, return the original value
3222 function get_label($label_tag, $temp_module_strings){
3223 global $app_strings;
3224 if(!empty($temp_module_strings[$label_tag])){
3226 $label_name = $temp_module_strings[$label_tag];
3228 if(!empty($app_strings[$label_tag])){
3229 $label_name = $app_strings[$label_tag];
3231 $label_name = $label_tag;
3236 //end function get_label
3240 function search_filter_rel_info(& $focus, $tar_rel_module, $relationship_name){
3242 $rel_list = array();
3244 foreach($focus->relationship_fields as $rel_key => $rel_value){
3245 if($rel_value == $relationship_name){
3246 $temp_bean = get_module_info($tar_rel_module);
3247 // echo $focus->$rel_key;
3248 $temp_bean->retrieve($focus->$rel_key);
3249 if($temp_bean->id!=""){
3251 $rel_list[] = $temp_bean;
3257 foreach($focus->field_defs as $field_name => $field_def){
3258 //Check if the relationship_name matches a "relate" field
3259 if(!empty($field_def['type']) && $field_def['type'] == 'relate'
3260 && !empty($field_def['id_name']) && !empty($focus->field_defs[$field_def['id_name']])
3261 && !empty($focus->field_defs[$field_def['id_name']]['relationship'])
3262 && $focus->field_defs[$field_def['id_name']]['relationship'] == $relationship_name)
3264 $temp_bean = get_module_info($tar_rel_module);
3265 // echo $focus->$field_def['id_name'];
3266 $temp_bean->retrieve($focus->$field_def['id_name']);
3267 if($temp_bean->id!=""){
3269 $rel_list[] = $temp_bean;
3272 //Check if the relationship_name matches a "link" in a relate field
3273 } else if(!empty($rel_value['link']) && !empty($rel_value['id_name']) && $rel_value['link'] == $relationship_name){
3274 $temp_bean = get_module_info($tar_rel_module);
3275 // echo $focus->$rel_value['id_name'];
3276 $temp_bean->retrieve($focus->$rel_value['id_name']);
3277 if($temp_bean->id!=""){
3279 $rel_list[] = $temp_bean;
3285 // special case for unlisted parent-type relationships
3286 if( !empty($focus->parent_type) && $focus->parent_type == $tar_rel_module && !empty($focus->parent_id)) {
3287 $temp_bean = get_module_info($tar_rel_module);
3288 $temp_bean->retrieve($focus->parent_id);
3289 if($temp_bean->id!=""){
3290 $rel_list[] = $temp_bean;
3297 //end function search_filter_rel_info
3300 function get_module_info($module_name){
3304 //Get dictionary and focus data for module
3305 $vardef_name = $beanList[$module_name];
3307 if($vardef_name=="aCase"){
3308 $class_name = "Case";
3310 $class_name = $vardef_name;
3313 if(!file_exists('modules/'. $module_name . '/'.$class_name.'.php')){
3317 include_once('modules/'. $module_name . '/'.$class_name.'.php');
3319 $module_bean = new $vardef_name();
3320 return $module_bean;
3321 //end function get_module_table
3325 * In order to have one place to obtain the proper object name. aCase for example causes issues throughout the application.
3327 * @param string $moduleName
3329 function get_valid_bean_name($module_name){
3332 $vardef_name = $beanList[$module_name];
3333 if($vardef_name=="aCase"){
3334 $bean_name = "Case";
3336 $bean_name = $vardef_name;
3343 function checkAuthUserStatus(){
3350 * This function returns an array of phpinfo() results that can be parsed and
3351 * used to figure out what version we run, what modules are compiled in, etc.
3352 * @param $level int info level constant (1,2,4,8...64);
3353 * @return $returnInfo array array of info about the PHP environment
3354 * @author original by "code at adspeed dot com" Fron php.net
3355 * @author customized for Sugar by Chris N.
3357 function getPhpInfo($level=-1) {
3358 /** Name (constant) Value Description
3359 INFO_GENERAL 1 The configuration line, php.ini location, build date, Web Server, System and more.
3360 INFO_CREDITS 2 PHP Credits. See also phpcredits().
3361 INFO_CONFIGURATION 4 Current Local and Master values for PHP directives. See also ini_get().
3362 INFO_MODULES 8 Loaded modules and their respective settings. See also get_loaded_extensions().
3363 INFO_ENVIRONMENT 16 Environment Variable information that's also available in $_ENV.
3364 INFO_VARIABLES 32 Shows all predefined variables from EGPCS (Environment, GET, POST, Cookie, Server).
3365 INFO_LICENSE 64 PHP License information. See also the license FAQ.
3366 INFO_ALL -1 Shows all of the above. This is the default value.
3370 $phpinfo = ob_get_contents();
3373 $phpinfo = strip_tags($phpinfo,'<h1><h2><th><td>');
3374 $phpinfo = preg_replace('/<th[^>]*>([^<]+)<\/th>/',"<info>\\1</info>",$phpinfo);
3375 $phpinfo = preg_replace('/<td[^>]*>([^<]+)<\/td>/',"<info>\\1</info>",$phpinfo);
3376 $parsedInfo = preg_split('/(<h.?>[^<]+<\/h.>)/', $phpinfo, -1, PREG_SPLIT_DELIM_CAPTURE);
3379 $returnInfo = array();
3381 if(preg_match('/<h1 class\=\"p\">PHP Version ([^<]+)<\/h1>/', $phpinfo, $version)) {
3382 $returnInfo['PHP Version'] = $version[1];
3386 for ($i=1; $i<count($parsedInfo); $i++) {
3387 if (preg_match('/<h.>([^<]+)<\/h.>/', $parsedInfo[$i], $match)) {
3388 $vName = trim($match[1]);
3389 $parsedInfo2 = explode("\n",$parsedInfo[$i+1]);
3391 foreach ($parsedInfo2 AS $vOne) {
3392 $vPat = '<info>([^<]+)<\/info>';
3393 $vPat3 = "/$vPat\s*$vPat\s*$vPat/";
3394 $vPat2 = "/$vPat\s*$vPat/";
3396 if (preg_match($vPat3,$vOne,$match)) { // 3cols
3397 $returnInfo[$vName][trim($match[1])] = array(trim($match[2]),trim($match[3]));
3398 } elseif (preg_match($vPat2,$vOne,$match)) { // 2cols
3399 $returnInfo[$vName][trim($match[1])] = trim($match[2]);
3411 * This function will take a string that has tokens like {0}, {1} and will replace
3412 * those tokens with the args provided
3413 * @param $format string to format
3414 * @param $args args to replace
3415 * @return $result a formatted string
3417 function string_format($format, $args){
3421 * If args array has only one argument, and it's empty, so empty single quotes are used '' . That's because
3422 * IN () fails and IN ('') works.
3424 if (count($args) == 1)
3427 $singleArgument = current($args);
3428 if (empty($singleArgument))
3430 return str_replace("{0}", "''", $result);
3435 for($i = 0; $i < count($args); $i++){
3436 $result = str_replace('{'.$i.'}', $args[$i], $result);
3442 * Generate a string for displaying a unique identifier that is composed
3443 * of a system_id and number. This is use to allow us to generate quote
3444 * numbers using a DB auto-increment key from offline clients and still
3445 * have the number be unique (since it is modified by the system_id.
3447 * @param $num of bean
3448 * @param $system_id from system
3449 * @return $result a formatted string
3451 function format_number_display($num, $system_id){
3452 global $sugar_config;
3453 if(isset($num) && !empty($num)){
3454 $num=unformat_number($num);
3455 if(isset($system_id) && $system_id == 1){
3456 return sprintf("%d", $num);
3459 return sprintf("%d-%d", $num, $system_id);
3463 function checkLoginUserStatus(){
3467 * This function will take a number and system_id and format
3468 * @param $url URL containing host to append port
3469 * @param $port the port number - if '' is passed, no change to url
3470 * @return $resulturl the new URL with the port appended to the host
3472 function appendPortToHost($url, $port)
3476 // if no port, don't change the url
3479 $split = explode("/", $url);
3480 //check if it starts with http, in case they didn't include that in url
3481 if(str_begin($url, 'http'))
3483 //third index ($split[2]) will be the host
3484 $split[2] .= ":".$port;
3486 else // otherwise assumed to start with host name
3488 //first index ($split[0]) will be the host
3489 $split[0] .= ":".$port;
3492 $resulturl = implode("/", $split);
3499 * Singleton to return JSON object
3500 * @return JSON object
3502 function getJSONobj() {
3503 static $json = null;
3505 require_once('include/JSON.php');
3506 $json = new JSON(JSON_LOOSE_TYPE);
3511 require_once('include/utils/db_utils.php');
3514 * Set default php.ini settings for entry points
3516 function setPhpIniSettings() {
3518 // Bug 37579 - Comment out force enabling zlib.output_compression, since it can cause problems on certain hosts
3520 if(function_exists('gzclose') && headers_sent() == false) {
3521 ini_set('zlib.output_compression', 1);
3525 //nsingh: breaks zip/unzip functionality. Commenting out 4/23/08
3527 /*if(function_exists('mb_strlen')) {
3528 ini_set('mbstring.func_overload', 7);
3529 ini_set('mbstring.internal_encoding', 'UTF-8');
3533 // http://us3.php.net/manual/en/ref.pcre.php#ini.pcre.backtrack-limit
3534 // starting with 5.2.0, backtrack_limit breaks JSON decoding
3535 $backtrack_limit = ini_get('pcre.backtrack_limit');
3536 if(!empty($backtrack_limit)) {
3537 ini_set('pcre.backtrack_limit', '-1');
3542 * like array_merge() but will handle array elements that are themselves arrays;
3543 * PHP's version just overwrites the element with the new one.
3545 * @internal Note that this function deviates from the internal array_merge()
3546 * functions in that it does does not treat numeric keys differently
3547 * than string keys. Additionally, it deviates from
3548 * array_merge_recursive() by not creating an array when like values
3551 * @param array gimp the array whose values will be overloaded
3552 * @param array dom the array whose values will pwn the gimp's
3553 * @return array beaten gimp
3555 function sugarArrayMerge($gimp, $dom) {
3556 if(is_array($gimp) && is_array($dom)) {
3557 foreach($dom as $domKey => $domVal) {
3558 if(array_key_exists($domKey, $gimp)) {
3559 if(is_array($domVal)) {
3561 foreach ( $domVal as $domArrKey => $domArrVal )
3562 $tempArr[$domArrKey] = $domArrVal;
3563 foreach ( $gimp[$domKey] as $gimpArrKey => $gimpArrVal )
3564 if ( !array_key_exists($gimpArrKey, $tempArr) )
3565 $tempArr[$gimpArrKey] = $gimpArrVal;
3566 $gimp[$domKey] = $tempArr;
3568 $gimp[$domKey] = $domVal;
3571 $gimp[$domKey] = $domVal;
3575 // if the passed value for gimp isn't an array, then return the $dom
3576 elseif(is_array($dom))
3583 * Similiar to sugarArrayMerge except arrays of N depth are merged.
3585 * @param array gimp the array whose values will be overloaded
3586 * @param array dom the array whose values will pwn the gimp's
3587 * @return array beaten gimp
3589 function sugarArrayMergeRecursive($gimp, $dom) {
3590 if(is_array($gimp) && is_array($dom)) {
3591 foreach($dom as $domKey => $domVal) {
3592 if(array_key_exists($domKey, $gimp)) {
3593 if(is_array($domVal) && is_array($gimp[$domKey])) {
3594 $gimp[$domKey] = sugarArrayMergeRecursive($gimp[$domKey], $domVal);
3596 $gimp[$domKey] = $domVal;
3599 $gimp[$domKey] = $domVal;
3603 // if the passed value for gimp isn't an array, then return the $dom
3604 elseif(is_array($dom))
3611 * finds the correctly working versions of PHP-JSON
3612 * @return bool True if NOT found or WRONG version
3614 function returnPhpJsonStatus() {
3615 if(function_exists('json_encode')) {
3616 $phpInfo = getPhpInfo(8);
3617 return version_compare($phpInfo['json']['json version'], '1.1.1', '<');
3619 return true; // not found
3624 * getTrackerSubstring
3626 * Returns a [number]-char or less string for the Tracker to display in the header
3627 * based on the tracker_max_display_length setting in config.php. If not set,
3628 * or invalid length, then defaults to 15 for COM editions, 30 for others.
3630 * @param string name field for a given Object
3631 * @return string [number]-char formatted string if length of string exceeds the max allowed
3633 function getTrackerSubstring($name) {
3634 static $max_tracker_item_length;
3637 $name = html_entity_decode($name, ENT_QUOTES, 'UTF-8');
3638 $strlen = function_exists('mb_strlen') ? mb_strlen($name) : strlen($name);
3640 global $sugar_config;
3642 if(!isset($max_tracker_item_length)) {
3643 if(isset($sugar_config['tracker_max_display_length'])) {
3644 $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;
3646 $max_tracker_item_length = 15;
3650 if($strlen > $max_tracker_item_length) {
3651 $chopped = function_exists('mb_substr') ? mb_substr($name, 0, $max_tracker_item_length, "UTF-8") : substr($name, 0, $max_tracker_item_length, "UTF-8");
3658 function generate_search_where ($field_list=array(),$values=array(),&$bean,$add_custom_fields=false,$module='') {
3659 $where_clauses= array();
3661 $table_name=$bean->object_name;
3662 foreach ($field_list[$module] as $field=>$parms) {
3663 if(isset($values[$field]) && $values[$field] != "") {
3665 if (!empty($parms['operator'])) {
3666 $operator=$parms['operator'];
3668 if (is_array($values[$field])) {
3671 foreach ($values[$field] as $key => $val) {
3672 if ($val != ' ' and $val != '') {
3673 if (!empty($field_value)) {
3676 $field_value .= "'".$GLOBALS['db']->quote($val)."'";
3680 $field_value=$GLOBALS['db']->quote($values[$field]);
3682 //set db_fields array.
3683 if (!isset($parms['db_field']) ) {
3684 $parms['db_field'] = array($field);
3686 if (isset($parms['my_items']) and $parms['my_items'] == true) {
3687 global $current_user;
3688 $field_value = $GLOBALS['db']->quote($current_user->id);
3694 if ($field_value != '') {
3696 foreach ($parms['db_field'] as $db_field) {
3697 if (strstr($db_field,'.')===false) {
3698 $db_field=$bean->table_name.".".$db_field;
3700 if ($GLOBALS['db']->supports('case_sensitive') && isset($parms['query_type']) && $parms['query_type']=='case_insensitive') {
3701 $db_field='upper('.$db_field.")";
3702 $field_value=strtoupper($field_value);
3706 if (!empty($where)) {
3709 switch (strtolower($operator)) {
3711 $where .= $db_field . " like '".$field_value.$like_char."'";
3714 $where .= $db_field . " in (".$field_value.')';
3717 $where .= $db_field . " = '".$field_value ."'";
3722 if (!empty($where)) {
3724 array_push($where_clauses, '( '.$where.' )');
3726 array_push($where_clauses, $where);
3731 if ($add_custom_fields) {
3732 require_once('modules/DynamicFields/DynamicField.php');
3733 $bean->setupCustomFields($module);
3734 $bean->custom_fields->setWhereClauses($where_clauses);
3736 return $where_clauses;
3739 function add_quotes($str) {
3744 * This function will rebuild the config file
3745 * @param $sugar_config
3746 * @param $sugar_version
3747 * @return bool true if successful
3749 function rebuildConfigFile($sugar_config, $sugar_version) {
3750 // add defaults to missing values of in-memory sugar_config
3751 $sugar_config = sugarArrayMerge(get_sugar_config_defaults(), $sugar_config );
3752 // need to override version with default no matter what
3753 $sugar_config['sugar_version'] = $sugar_version;
3755 ksort( $sugar_config );
3757 if( write_array_to_file( "sugar_config", $sugar_config, "config.php" ) ){
3766 * getJavascriptSiteURL
3767 * This function returns a URL for the client javascript calls to access
3768 * the site. It uses $_SERVER['HTTP_REFERER'] in the event that Proxy servers
3769 * are used to access the site. Thus, the hostname in the URL returned may
3770 * not always match that of $sugar_config['site_url']. Basically, the
3771 * assumption is that however the user accessed the website is how they
3772 * will continue to with subsequent javascript requests. If the variable
3773 * $_SERVER['HTTP_REFERER'] is not found then we default to old algorithm.
3774 * @return $site_url The url used to refer to the website
3776 function getJavascriptSiteURL() {
3777 global $sugar_config;
3778 if(!empty($_SERVER['HTTP_REFERER'])) {
3779 $url = parse_url($_SERVER['HTTP_REFERER']);
3780 $replacement_url = $url['scheme']."://".$url['host'];
3781 if(!empty($url['port']))
3782 $replacement_url .= ':'.$url['port'];
3783 $site_url = preg_replace('/^http[s]?\:\/\/[^\/]+/',$replacement_url,$sugar_config['site_url']);
3785 $site_url = preg_replace('/^http(s)?\:\/\/[^\/]+/',"http$1://".$_SERVER['HTTP_HOST'],$sugar_config['site_url']);
3786 if(!empty($_SERVER['SERVER_PORT']) &&$_SERVER['SERVER_PORT'] == '443') {
3787 $site_url = preg_replace('/^http\:/','https:',$site_url);
3790 $GLOBALS['log']->debug("getJavascriptSiteURL(), site_url=". $site_url);
3794 // works nicely with array_map() -- can be used to wrap single quotes around each element in an array
3795 function add_squotes($str) {
3796 return "'" . $str . "'";
3800 // recursive function to count the number of levels within an array
3801 function array_depth($array, $depth_count=-1, $depth_array=array()){
3803 if (is_array($array)){
3804 foreach ($array as $key => $value){
3805 $depth_array[] = array_depth($value, $depth_count);
3809 return $depth_count;
3811 foreach ($depth_array as $value){
3812 $depth_count = $value > $depth_count ? $value : $depth_count;
3814 return $depth_count;
3818 * Creates a new Group User
3819 * @param string $name Name of Group User
3820 * @return string GUID of new Group User
3822 function createGroupUser($name) {
3825 $group = new User();
3826 $group->user_name = $name;
3827 $group->last_name = $name;
3828 $group->is_group = 1;
3829 $group->deleted = 0;
3830 $group->status = 'Active'; // cn: bug 6711
3831 $group->setPreference('timezone', TimeDate::userTimezone());
3838 * Helper function to locate an icon file given only a name
3839 * Searches through the various paths for the file
3840 * @param string iconFileName The filename of the icon
3841 * @return string Relative pathname of the located icon, or '' if not found
3844 function _getIcon($iconFileName)
3847 $iconName = "icon_{$iconFileName}.gif";
3848 $iconFound = SugarThemeRegistry::current()->getImageURL($iconName,false);
3850 //First try un-ucfirst-ing the icon name
3851 if ( empty($iconFound) )
3852 $iconName = "icon_" . strtolower(substr($iconFileName,0,1)).substr($iconFileName,1) . ".gif";
3853 $iconFound = SugarThemeRegistry::current()->getImageURL($iconName,false);
3855 //Next try removing the icon prefix
3856 if ( empty($iconFound) )
3857 $iconName = "{$iconFileName}.gif";
3858 $iconFound = SugarThemeRegistry::current()->getImageURL($iconName,false);
3860 if ( empty($iconFound) )
3866 * Function to grab the correct icon image for Studio
3867 * @param string $iconFileName Name of the icon file
3868 * @param string $altfilename Name of a fallback icon file (displayed if the imagefilename doesn't exist)
3869 * @param string $width Width of image
3870 * @param string $height Height of image
3871 * @param string $align Alignment of image
3872 * @param string $alt Alt tag of image
3873 * @return string $string <img> tag with corresponding image
3876 function getStudioIcon($iconFileName='', $altFileName='', $width='48', $height='48', $align='baseline', $alt='' )
3878 global $app_strings, $theme;
3880 $iconName = _getIcon($iconFileName);
3881 if(empty($iconName)){
3882 $iconName = _getIcon($altFileName);
3883 if (empty($iconName))
3885 return $app_strings['LBL_NO_IMAGE'];
3888 return SugarThemeRegistry::current()->getImage($iconName, "align=\"$align\" border=\"0\"", $width, $height);
3892 * Function to grab the correct icon image for Dashlets Dialog
3893 * @param string $filename Location of the icon file
3894 * @param string $module Name of the module to fall back onto if file does not exist
3895 * @param string $width Width of image
3896 * @param string $height Height of image
3897 * @param string $align Alignment of image
3898 * @param string $alt Alt tag of image
3899 * @return string $string <img> tag with corresponding image
3902 function get_dashlets_dialog_icon($module='', $width='32', $height='32', $align='absmiddle',$alt=''){
3903 global $app_strings, $theme;
3904 $iconName = _getIcon($module . "_32");
3905 if (empty($iconName))
3907 $iconName = _getIcon($module);
3909 if(empty($iconName)){
3910 return $app_strings['LBL_NO_IMAGE'];
3912 return SugarThemeRegistry::current()->getImage($iconName, "align=\"$align\" border=\"0\"", $width, $height);
3915 // works nicely to change UTF8 strings that are html entities - good for PDF conversions
3916 function html_entity_decode_utf8($string)
3919 // replace numeric entities
3920 //php will have issues with numbers with leading zeros, so do not include them in what we send to code2utf.
3921 $string = preg_replace('~�*([0-9a-f]+);~ei', 'code2utf(hexdec("\\1"))', $string);
3922 $string = preg_replace('~�*([0-9]+);~e', 'code2utf(\\1)', $string);
3923 // replace literal entities
3924 if (!isset($trans_tbl))
3926 $trans_tbl = array();
3927 foreach (get_html_translation_table(HTML_ENTITIES) as $val=>$key)
3928 $trans_tbl[$key] = utf8_encode($val);
3930 return strtr($string, $trans_tbl);
3933 // Returns the utf string corresponding to the unicode value
3934 function code2utf($num)
3936 if ($num < 128) return chr($num);
3937 if ($num < 2048) return chr(($num >> 6) + 192) . chr(($num & 63) + 128);
3938 if ($num < 65536) return chr(($num >> 12) + 224) . chr((($num >> 6) & 63) + 128) . chr(($num & 63) + 128);
3939 if ($num < 2097152) return chr(($num >> 18) + 240) . chr((($num >> 12) & 63) + 128) . chr((($num >> 6) & 63) + 128) . chr(($num & 63) + 128);
3943 function str_split_php4($string, $length = 1) {
3944 $string_length = strlen($string);
3947 if ($length > $string_length) {
3948 // use the string_length as the string is shorter than the length
3949 $length = $string_length;
3951 for ($cursor = 0; $cursor < $string_length; $cursor = $cursor + $length) {
3952 $return[] = substr($string, $cursor, $length);
3957 if (version_compare(phpversion(), '5.0.0', '<')) {
3958 function str_split($string, $length = 1) {
3959 return str_split_php4($string, $length);
3964 * @deprecated use DBManagerFactory::isFreeTDS
3966 function is_freetds()
3968 return DBManagerFactory::isFreeTDS();
3972 * Chart dashlet helper function that returns the correct CSS file, dependent on the current theme.
3974 * @todo this won't work completely right until we impliment css compression and combination
3975 * for now, we'll just include the last css file found.
3977 * @return chart.css file to use
3979 function chartStyle()
3981 return SugarThemeRegistry::current()->getCSSURL('chart.css');
3985 * Chart dashlet helper functions that returns the correct XML color file for charts,
3986 * dependent on the current theme.
3988 * @return sugarColors.xml to use
3990 function chartColors()
3992 if (SugarThemeRegistry::current()->getCSSURL('sugarColors.xml')=='')
3993 return SugarThemeRegistry::current()->getImageURL('sugarColors.xml');
3994 return SugarThemeRegistry::current()->getCSSURL('sugarColors.xml');
3996 /* End Chart Dashlet helper functions */
3999 * This function is designed to set up the php enviroment
4000 * for AJAX requests.
4003 function ajaxInit() {
4004 ini_set('display_errors', 'false');
4008 * Returns an absolute path from the given path, determining if it is relative or absolute
4010 * @param string $path
4013 function getAbsolutePath(
4015 $currentServer = false
4018 $path = trim($path);
4020 // try to match absolute paths like \\server\share, /directory or c:\
4021 if ( ( substr($path,0,2) == '\\\\' )
4022 || ( $path[0] == '/' )
4023 || preg_match('/^[A-z]:/i',$path)
4027 return getcwd().'/'.$path;
4031 * Returns the bean object of the given module
4033 * @deprecated use SugarModule::loadBean() instead
4034 * @param string $module
4041 return SugarModule::get($module)->loadBean();
4046 * Returns true if the application is being accessed on a touch screen interface ( like an iPad )
4048 function isTouchScreen()
4050 $ua = empty($_SERVER['HTTP_USER_AGENT']) ? "undefined" : strtolower($_SERVER['HTTP_USER_AGENT']);
4052 // first check if we have forced use of the touch enhanced interface
4053 if ( isset($_COOKIE['touchscreen']) && $_COOKIE['touchscreen'] == '1' ) {
4057 // next check if we should use the touch interface with our device
4058 if ( strpos($ua, 'ipad') !== false ) {
4066 * Returns the shortcut keys to access the shortcut links. Shortcut
4067 * keys vary depending on browser versions and operating systems.
4068 * @return String value of the shortcut keys
4070 function get_alt_hot_key() {
4072 if ( isset($_SERVER['HTTP_USER_AGENT']) )
4073 $ua = strtolower($_SERVER['HTTP_USER_AGENT']);
4074 $isMac = strpos($ua, 'mac') !== false;
4075 $isLinux = strpos($ua, 'linux') !== false;
4077 if(!$isMac && !$isLinux && strpos($ua, 'mozilla') !== false) {
4078 if(preg_match('/firefox\/(\d)?\./', $ua, $matches)) {
4079 return $matches[1] < 2 ? 'Alt+' : 'Alt+Shift+';
4082 return $isMac ? 'Ctrl+' : 'Alt+';
4085 function can_start_session(){
4086 if(!empty($_GET['PHPSESSID'])) {
4089 $session_id = session_id();
4090 return empty($session_id) ? true : false;
4093 function load_link_class($properties){
4095 if(!empty($properties['link_class']) && !empty($properties['link_file'])){
4096 require_once($properties['link_file']);
4097 $class = $properties['link_class'];
4103 function inDeveloperMode()
4105 return isset($GLOBALS['sugar_config']['developerMode']) && $GLOBALS['sugar_config']['developerMode'];
4109 * Filter the protocol list for inbound email accounts.
4111 * @param array $protocol
4113 function filterInboundEmailPopSelection($protocol)
4115 if ( !isset($GLOBALS['sugar_config']['allow_pop_inbound']) || ! $GLOBALS['sugar_config']['allow_pop_inbound'] )
4117 if( isset($protocol['pop3']) )
4118 unset($protocol['pop3']);
4121 $protocol['pop3'] = 'POP3';
4127 * The function is used because currently we are not supporting mbstring.func_overload
4128 * 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.
4129 * 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.
4130 * @returns the substred strings.
4132 function sugar_substr($string, $length, $charset='UTF-8')
4134 if(mb_strlen($string,$charset) > $length) {
4135 $string = trim(mb_substr(trim($string),0,$length,$charset));
4141 * The function is used because on FastCGI enviroment, the ucfirst(Chinese Characters) will produce bad charcters.
4142 * This will work even without setting the mbstring.*encoding
4144 function sugar_ucfirst($string, $charset='UTF-8') {
4145 return mb_strtoupper(mb_substr($string, 0, 1, $charset), $charset) . mb_substr($string, 1, mb_strlen($string), $charset);
4152 function unencodeMultienum($string) {
4153 if (is_array($string))
4157 if (substr($string, 0 ,1) == "^" && substr($string, -1) == "^") {
4158 $string = substr(substr($string, 1), 0, strlen($string) -2);
4161 return explode('^,^', $string);
4164 function encodeMultienumValue($arr) {
4165 if (!is_array($arr))
4171 $string = "^" . implode('^,^', $arr) . "^";
4177 * create_export_query is used for export and massupdate
4178 * We haven't handle the these fields: $field['type'] == 'relate' && isset($field['link']
4179 * This function will correct the where clause and output necessary join condition for them
4180 * @param $module: the module name
4181 * @param $searchFields: searchFields which is got after $searchForm->populateFromArray()
4182 * @param $where: where clauses
4183 * @return $ret_array['where']: corrected where clause
4184 * @return $ret_array['join']: extra join condition
4186 function create_export_query_relate_link_patch($module, $searchFields, $where){
4187 if(file_exists('modules/'.$module.'/SearchForm.html')){
4188 $ret_array['where'] = $where;
4191 $seed = loadBean($module);
4192 foreach($seed->field_defs as $name=>$field)
4195 if( $field['type'] == 'relate' && isset($field['link']) && !empty($searchFields[$name]['value']) ){
4196 $seed->load_relationship($field['link']);
4198 if(empty($join_type))
4200 $params['join_type'] = ' LEFT JOIN ';
4204 $params['join_type'] = $join_type;
4206 if(isset($data['join_name']))
4208 $params['join_table_alias'] = $field['join_name'];
4212 $params['join_table_alias'] = 'join_'.$field['name'];
4215 if(isset($data['join_link_name']))
4217 $params['join_table_link_alias'] = $field['join_link_name'];
4221 $params['join_table_link_alias'] = 'join_link_'.$field['name'];
4223 $join = $seed->$field['link']->getJoin($params, true);
4224 $join_table_alias = 'join_'.$field['name'];
4225 if(isset($field['db_concat_fields'])){
4226 $db_field = db_concat($join_table_alias, $field['db_concat_fields']);
4227 $where = preg_replace('/'.$field['name'].'/', $db_field, $where);
4229 $where = preg_replace('/(^|[\s(])' . $field['name'] . '/', '${1}' . $join_table_alias . '.'.$field['rname'], $where);
4233 $ret_array = array('where'=>$where, 'join'=>$join['join']);
4238 * 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.
4239 * @Depends on QuickRepairAndRebuild.php
4240 * @Relate bug 30642 ,23177
4242 function clearAllJsAndJsLangFilesWithoutOutput(){
4243 global $current_language , $mod_strings;
4244 $MBmodStrings = $mod_strings;
4245 $mod_strings = return_module_language ( $current_language, 'Administration' ) ;
4246 include_once ('modules/Administration/QuickRepairAndRebuild.php') ;
4247 $repair = new RepairAndClear();
4248 $repair->module_list = array();
4249 $repair->show_output = false;
4250 $repair->clearJsLangFiles();
4251 $repair->clearJsFiles();
4252 $mod_strings = $MBmodStrings;
4256 * This function will allow you to get a variable value from query string
4258 function getVariableFromQueryString($variable, $string){
4260 $number = preg_match("/{$variable}=([a-zA-Z0-9_-]+)[&]?/", $string, $matches);
4270 * should_hide_iframes
4271 * This is a helper method to determine whether or not to show iframes (My Sites) related
4272 * information in the application.
4274 * @return boolean flag indicating whether or not iframes module should be hidden
4276 function should_hide_iframes() {
4277 //Remove the MySites module
4278 if(file_exists('modules/iFrames/iFrame.php')) {
4279 if(!class_exists("iFrame")) {
4280 require_once('modules/iFrames/iFrame.php');
4288 * Given a version such as 5.5.0RC1 return RC. If we have a version such as: 5.5 then return GA
4290 * @param string $version
4291 * @return string RC, BETA, GA
4293 function getVersionStatus($version){
4294 if(preg_match('/^[\d\.]+?([a-zA-Z]+?)[\d]*?$/si', $version, $matches)) {
4295 return strtoupper($matches[1]);
4302 * Return the numeric portion of a version. For example if passed 5.5.0RC1 then return 5.5. If given
4303 * 5.5.1RC1 then return 5.5.1
4305 * @param string $version
4308 function getMajorMinorVersion($version){
4309 if(preg_match('/^([\d\.]+).*$/si', $version, $matches2)){
4310 $version = $matches2[1];
4311 $arr = explode('.', $version);
4312 if(count($arr) > 2){
4314 $version = substr($version, 0, 3);
4322 * Return string composed of seconds & microseconds of current time, without dots
4325 function sugar_microtime()
4327 $now = explode(' ', microtime());
4328 $unique_id = $now[1].str_replace('.', '', $now[0]);
4333 * Extract urls from a piece of text
4335 * @return array of urls found in $string
4337 function getUrls($string)
4339 $lines = explode("<br>", trim($string));
4341 foreach($lines as $line){
4342 $regex = '/http?\:\/\/[^\" ]+/i';
4343 preg_match_all($regex, $line, $matches);
4344 foreach($matches[0] as $match){
4353 * Sanitize image file from hostile content
4354 * @param string $path Image file
4355 * @param bool $jpeg Accept only JPEGs?
4357 function verify_image_file($path, $jpeg = false)
4359 if(function_exists('imagepng') && function_exists('imagejpeg') && function_exists('imagecreatefromstring')) {
4360 $img = imagecreatefromstring(file_get_contents($path));
4364 $img_size = getimagesize($path);
4365 $filetype = $img_size['mime'];
4366 //if filetype is jpeg or if we are only allowing jpegs, create jpg image
4367 if($filetype == "image/jpeg" || $jpeg) {
4370 $image = ob_get_clean();
4371 // not writing directly because imagejpeg does not work with streams
4372 if(file_put_contents($path, $image)) {
4375 } elseif ($filetype == "image/png") { // else if the filetype is png, create png
4376 imagealphablending($img, true);
4377 imagesavealpha($img, true);
4380 $image = ob_get_clean();
4381 if(file_put_contents($path, $image)) {
4388 // check image manually
4389 $fp = fopen($path, "r");
4390 if(!$fp) return false;
4391 $data = fread($fp, 4096);
4393 if(preg_match("/<(html|!doctype|script|body|head|plaintext|table|img |pre(>| )|frameset|iframe|object|link|base|style|font|applet|meta|center|form|isindex)/i",
4395 $GLOBALS['log']->info("Found {$m[0]} in $path, not allowing upload");
4404 * Verify uploaded image
4405 * Verifies that image has proper extension, MIME type and doesn't contain hostile contant
4406 * @param string $path Image path
4407 * @param bool $jpeg_only Accept only JPEGs?
4409 function verify_uploaded_image($path, $jpeg_only = false)
4411 $supportedExtensions = array('jpg' => 'image/jpeg', 'jpeg' => 'image/jpeg');
4413 $supportedExtensions['png'] = 'image/png';
4416 if(!file_exists($path) || !is_file($path)) {
4420 $img_size = getimagesize($path);
4421 $filetype = $img_size['mime'];
4422 $ext = end(explode(".", $path));
4423 if(substr_count('..', $path) > 0 || ($ext !== $path && !in_array(strtolower($ext), array_keys($supportedExtensions))) ||
4424 !in_array($filetype, array_values($supportedExtensions))) {
4427 return verify_image_file($path, $jpeg_only);
4430 function cmp_beans($a, $b)
4432 global $sugar_web_service_order_by;
4433 //If the order_by field is not valid, return 0;
4434 if (empty($sugar_web_service_order_by) || !isset($a->$sugar_web_service_order_by) || !isset($b->$sugar_web_service_order_by)){
4437 if (is_object($a->$sugar_web_service_order_by) || is_object($b->$sugar_web_service_order_by)
4438 || is_array($a->$sugar_web_service_order_by) || is_array($b->$sugar_web_service_order_by))
4442 if ($a->$sugar_web_service_order_by < $b->$sugar_web_service_order_by)
4450 function order_beans($beans, $field_name)
4452 //Since php 5.2 doesn't include closures, we must use a global to pass the order field to cmp_beans.
4453 global $sugar_web_service_order_by;
4454 $sugar_web_service_order_by = $field_name;
4455 usort($beans, "cmp_beans");
4459 //check to see if custom utils exists
4460 if(file_exists('custom/include/custom_utils.php')){
4461 include_once('custom/include/custom_utils.php');
4464 //check to see if custom utils exists in Extension framework
4465 if(file_exists('custom/application/Ext/Utils/custom_utils.ext.php')) {
4466 include_once('custom/application/Ext/Utils/custom_utils.ext.php');
4469 * @param $input - the input string to sanitize
4470 * @param int $quotes - use quotes
4471 * @param string $charset - the default charset
4472 * @param bool $remove - strip tags or not
4473 * @return string - the sanitized string
4475 function sanitize($input, $quotes = ENT_QUOTES, $charset = 'UTF-8', $remove = false)
4477 return htmlentities($input, $quotes, $charset);
4482 * utf8_recursive_encode
4484 * This function walks through an Array and recursively calls utf8_encode on the
4485 * values of each of the elements.
4487 * @param $data Array of data to encode
4488 * @return utf8 encoded Array data
4490 function utf8_recursive_encode($data)
4493 foreach($data as $key=>$val) {
4494 if(is_array($val)) {
4495 $result[$key] = utf8_recursive_encode($val);
4497 $result[$key] = utf8_encode($val);
4504 * get_language_header
4506 * This is a utility function for 508 Compliance. It returns the lang=[Current Language] text string used
4507 * inside the <html> tag. If no current language is specified, it defaults to lang='en'.
4509 * @return String The lang=[Current Language] markup to insert into the <html> tag
4511 function get_language_header()
4513 return isset($GLOBALS['current_language']) ? "lang='{$GLOBALS['current_language']}'" : "lang='en'";
4518 * get_custom_file_if_exists
4520 * This function handles the repetitive code we have where we first check if a file exists in the
4521 * custom directory to determine whether we should load it, require it, include it, etc. This function returns the
4522 * path of the custom file if it exists. It basically checks if custom/{$file} exists and returns this path if so;
4523 * otherwise it return $file
4525 * @param $file String of filename to check
4526 * @return $file String of filename including custom directory if found
4528 function get_custom_file_if_exists($file)
4530 return file_exists("custom/{$file}") ? "custom/{$file}" : $file;