2 /*********************************************************************************
3 * SugarCRM Community Edition is a customer relationship management program developed by
4 * SugarCRM, Inc. Copyright (C) 2004-2011 SugarCRM Inc.
6 * This program is free software; you can redistribute it and/or modify it under
7 * the terms of the GNU Affero General Public License version 3 as published by the
8 * Free Software Foundation with the addition of the following permission added
9 * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
10 * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
11 * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
18 * You should have received a copy of the GNU Affero General Public License along with
19 * this program; if not, see http://www.gnu.org/licenses or write to the Free
20 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
24 * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
26 * The interactive user interfaces in modified source and object code versions
27 * of this program must display Appropriate Legal Notices, as required under
28 * Section 5 of the GNU Affero General Public License version 3.
30 * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
31 * these Appropriate Legal Notices must retain the display of the "Powered by
32 * SugarCRM" logo. If the display of the logo is not reasonably feasible for
33 * technical reasons, the Appropriate Legal Notices must display the words
34 * "Powered by SugarCRM".
35 ********************************************************************************/
37 /*********************************************************************************
39 * Description: Includes generic helper functions used throughout the application.
40 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
41 * All Rights Reserved.
42 * Contributor(s): ______________________________________..
43 ********************************************************************************/
44 require_once('include/SugarObjects/SugarConfig.php');
45 require_once('include/utils/security_utils.php');
49 function make_sugar_config(&$sugar_config)
51 /* used to convert non-array config.php file to array format */
52 global $admin_export_only;
54 global $calculate_response_time;
55 global $create_default_user;
58 global $dbconfigoption;
59 global $default_action;
60 global $default_charset;
61 global $default_currency_name;
62 global $default_currency_symbol;
63 global $default_currency_iso4217;
64 global $defaultDateFormat;
65 global $default_language;
66 global $default_module;
67 global $default_password;
68 global $default_permission_mode;
69 global $default_theme;
70 global $defaultTimeFormat;
71 global $default_user_is_admin;
72 global $default_user_name;
73 global $disable_export;
74 global $disable_persistent_connections;
75 global $display_email_template_variable_chooser;
76 global $display_inbound_email_buttons;
77 global $history_max_viewed;
81 global $list_max_entries_per_page;
82 global $lock_default_user_name;
83 global $log_memory_usage;
84 global $requireAccounts;
85 global $RSS_CACHE_TIME;
89 global $sugar_version;
92 global $translation_string_prefix;
94 global $upload_badext;
96 global $upload_maxsize;
97 global $import_max_execution_time;
98 global $list_max_entries_per_subpanel;
99 global $passwordsetting;
101 // assumes the following variables must be set:
102 // $dbconfig, $dbconfigoption, $cache_dir, $import_dir, $session_dir, $site_URL, $tmp_dir, $upload_dir
104 $sugar_config = array (
105 'admin_export_only' => empty($admin_export_only) ? false : $admin_export_only,
106 'export_delimiter' => empty($export_delimiter) ? ',' : $export_delimiter,
107 'cache_dir' => empty($cache_dir) ? 'cache/' : $cache_dir,
108 'calculate_response_time' => empty($calculate_response_time) ? true : $calculate_response_time,
109 'create_default_user' => empty($create_default_user) ? false : $create_default_user,
110 'chartEngine' => 'Jit',
111 'date_formats' => empty($dateFormats) ? array(
112 'Y-m-d'=>'2010-12-23',
113 'd-m-Y' => '23-12-2010',
114 'm-d-Y'=>'12-23-2010',
115 'Y/m/d'=>'2010/12/23',
116 'd/m/Y' => '23/12/2010',
117 'm/d/Y'=>'12/23/2010',
118 'Y.m.d' => '2010.12.23',
119 'd.m.Y' => '23.12.2010',
120 'm.d.Y' => '12.23.2010'
122 'dbconfig' => $dbconfig, // this must be set!!
123 'dbconfigoption' => $dbconfigoption, // this must be set!!
124 'default_action' => empty($default_action) ? 'index' : $default_action,
125 'default_charset' => empty($default_charset) ? 'UTF-8' : $default_charset,
126 'default_currency_name' => empty($default_currency_name) ? 'US Dollar' : $default_currency_name,
127 'default_currency_symbol' => empty($default_currency_symbol) ? '$' : $default_currency_symbol,
128 'default_currency_iso4217' => empty($default_currency_iso4217) ? '$' : $default_currency_iso4217,
129 'default_date_format' => empty($defaultDateFormat) ? 'm/d/Y' : $defaultDateFormat,
130 'default_export_charset' => 'UTF-8',
131 'default_language' => empty($default_language) ? 'en_us' : $default_language,
132 'default_module' => empty($default_module) ? 'Home' : $default_module,
133 'default_password' => empty($default_password) ? '' : $default_password,
134 'default_permissions' => array (
140 'default_theme' => empty($default_theme) ? 'Sugar5' : $default_theme,
141 'default_time_format' => empty($defaultTimeFormat) ? 'h:ia' : $defaultTimeFormat,
142 'default_user_is_admin' => empty($default_user_is_admin) ? false : $default_user_is_admin,
143 'default_user_name' => empty($default_user_name) ? '' : $default_user_name,
144 'disable_export' => empty($disable_export) ? false : $disable_export,
145 'disable_persistent_connections' => empty($disable_persistent_connections) ? false : $disable_persistent_connections,
146 'display_email_template_variable_chooser' => empty($display_email_template_variable_chooser) ? false : $display_email_template_variable_chooser,
147 'display_inbound_email_buttons' => empty($display_inbound_email_buttons) ? false : $display_inbound_email_buttons,
148 'history_max_viewed' => empty($history_max_viewed) ? 50 : $history_max_viewed,
149 'host_name' => empty($host_name) ? 'localhost' : $host_name,
150 'import_dir' => $import_dir, // this must be set!!
151 'import_max_records_per_file' => 100,
152 'import_max_records_total_limit' => '',
153 'languages' => empty($languages) ? array('en_us' => 'English (US)') : $languages,
154 'list_max_entries_per_page' => empty($list_max_entries_per_page) ? 20 : $list_max_entries_per_page,
155 'list_max_entries_per_subpanel' => empty($list_max_entries_per_subpanel) ? 10 : $list_max_entries_per_subpanel,
156 'lock_default_user_name' => empty($lock_default_user_name) ? false : $lock_default_user_name,
157 'log_memory_usage' => empty($log_memory_usage) ? false : $log_memory_usage,
158 'portal_view' => 'single_user',
159 'resource_management' => array (
160 'special_query_limit' => 50000,
161 'special_query_modules' => array('Reports', 'Export', 'Import', 'Administration', 'Sync'),
162 'default_limit' => 1000,
164 'require_accounts' => empty($requireAccounts) ? true : $requireAccounts,
165 'rss_cache_time' => empty($RSS_CACHE_TIME) ? '10800' : $RSS_CACHE_TIME,
166 'session_dir' => $session_dir, // this must be set!!
167 'site_url' => empty($site_URL) ? $site_url : $site_URL, // this must be set!!
168 'showDetailData' => true, // if true, read-only ACL fields will still appear on EditViews as non-editable
169 'showThemePicker' => true,
170 'sugar_version' => empty($sugar_version) ? 'unknown' : $sugar_version,
171 'time_formats' => empty($timeFormats) ? array (
172 'H:i'=>'23:00', 'h:ia'=>'11:00 pm', 'h:iA'=>'11:00PM',
173 'H.i'=>'23.00', 'h.ia'=>'11.00 pm', 'h.iA'=>'11.00PM' ) : $timeFormats,
174 'tmp_dir' => $tmp_dir, // this must be set!!
175 'translation_string_prefix' => empty($translation_string_prefix) ? false : $translation_string_prefix,
176 'unique_key' => empty($unique_key) ? md5(create_guid()) : $unique_key,
177 'upload_badext' => empty($upload_badext) ? array (
178 'php', 'php3', 'php4', 'php5', 'pl', 'cgi', 'py',
179 'asp', 'cfm', 'js', 'vbs', 'html', 'htm' ) : $upload_badext,
180 'upload_dir' => $upload_dir, // this must be set!!
181 'upload_maxsize' => empty($upload_maxsize) ? 3000000 : $upload_maxsize,
182 'import_max_execution_time' => empty($import_max_execution_time) ? 3600 : $import_max_execution_time,
183 'lock_homepage' => false,
184 'lock_subpanels' => false,
185 'max_dashlets_homepage' => 15,
186 'dashlet_display_row_options' => array('1','3','5','10'),
187 'default_max_tabs' => empty($max_tabs) ? '7' : $max_tabs,
188 'default_subpanel_tabs' => empty($subpanel_tabs) ? true : $subpanel_tabs,
189 'default_subpanel_links' => empty($subpanel_links) ? false : $subpanel_links,
190 'default_swap_last_viewed' => empty($swap_last_viewed) ? false : $swap_last_viewed,
191 'default_swap_shortcuts' => empty($swap_shortcuts) ? false : $swap_shortcuts,
192 'default_navigation_paradigm' => empty($navigation_paradigm) ? 'gm' : $navigation_paradigm,
193 'default_call_status' => 'Planned',
194 'js_lang_version' => 1,
195 'passwordsetting' => empty($passwordsetting) ? array (
196 'SystemGeneratedPasswordON' => '',
197 'generatepasswordtmpl' => '',
198 'lostpasswordtmpl' => '',
199 'forgotpasswordON' => true,
200 'linkexpiration' => '1',
201 'linkexpirationtime' => '30',
202 'linkexpirationtype' => '1',
203 'systexpiration' => '0',
204 'systexpirationtime' => '',
205 'systexpirationtype' => '0',
206 'systexpirationlogin' => '',
207 ) : $passwordsetting,
211 function get_sugar_config_defaults() {
214 * used for getting base values for array style config.php. used by the
215 * installer and to fill in new entries on upgrades. see also:
219 $sugar_config_defaults = array (
220 'admin_export_only' => false,
221 'export_delimiter' => ',',
222 'cache_dir' => 'cache/',
223 'calculate_response_time' => true,
224 'create_default_user' => false,
225 'chartEngine' => 'Jit',
226 'date_formats' => array (
227 'Y-m-d' => '2010-12-23', 'm-d-Y' => '12-23-2010', 'd-m-Y' => '23-12-2010',
228 'Y/m/d' => '2010/12/23', 'm/d/Y' => '12/23/2010', 'd/m/Y' => '23/12/2010',
229 'Y.m.d' => '2010.12.23', 'd.m.Y' => '23.12.2010', 'm.d.Y' => '12.23.2010',),
230 'dbconfigoption' => array (
231 'persistent' => true,
234 'seqname_format' => '%s_seq',
237 'default_action' => 'index',
238 'default_charset' => return_session_value_or_default('default_charset',
240 'default_currency_name' => return_session_value_or_default('default_currency_name', 'US Dollar'),
241 'default_currency_symbol' => return_session_value_or_default('default_currency_symbol', '$'),
242 'default_currency_iso4217' => return_session_value_or_default('default_currency_iso4217', 'USD'),
243 'default_currency_significant_digits' => return_session_value_or_default('default_currency_significant_digits', 2),
244 'default_number_grouping_seperator' => return_session_value_or_default('default_number_grouping_seperator', ','),
245 'default_decimal_seperator' => return_session_value_or_default('default_decimal_seperator', '.'),
246 'default_date_format' => 'm/d/Y',
247 'default_export_charset' => 'UTF-8',
248 'default_language' => return_session_value_or_default('default_language',
250 'default_module' => 'Home',
251 'default_password' => '',
252 'default_permissions' => array (
258 'default_theme' => return_session_value_or_default('site_default_theme', 'Sugar5'),
259 'default_time_format' => 'h:ia',
260 'default_user_is_admin' => false,
261 'default_user_name' => '',
262 'disable_export' => false,
263 'disable_persistent_connections' =>
264 return_session_value_or_default('disable_persistent_connections',
266 'display_email_template_variable_chooser' => false,
267 'display_inbound_email_buttons' => false,
268 'dump_slow_queries' => false,
269 'email_default_editor' => 'html',
270 'email_default_client' => 'sugar',
271 'email_default_delete_attachments' => true,
272 'history_max_viewed' => 50,
273 'installer_locked' => true,
274 'import_max_records_per_file' => 100,
275 'import_max_records_total_limit' => '',
276 'languages' => array('en_us' => 'English (US)'),
277 'large_scale_test' => false,
278 'list_max_entries_per_page' => 20,
279 'list_max_entries_per_subpanel' => 10,
280 'lock_default_user_name' => false,
281 'log_memory_usage' => false,
282 'portal_view' => 'single_user',
283 'resource_management' => array (
284 'special_query_limit' => 50000,
285 'special_query_modules' => array('Reports', 'Export', 'Import', 'Administration', 'Sync'),
286 'default_limit' => 1000,
288 'require_accounts' => true,
289 'rss_cache_time' => return_session_value_or_default('rss_cache_time',
291 'save_query' => 'all',
292 'showDetailData' => true, // if true, read-only ACL fields will still appear on EditViews as non-editable
293 'showThemePicker' => true,
294 'slow_query_time_msec' => '100',
296 'time_formats' => array (
297 'H:i'=>'23:00', 'h:ia'=>'11:00pm', 'h:iA'=>'11:00PM', 'h:i a'=>'11:00 pm', 'h:i A'=>'11:00 PM',
298 'H.i'=>'23.00', 'h.ia'=>'11.00pm', 'h.iA'=>'11.00PM', 'h.i a'=>'11.00 pm', 'h.i A'=>'11.00 PM' ),
299 'tracker_max_display_length' => 15,
300 'translation_string_prefix' =>
301 return_session_value_or_default('translation_string_prefix', false),
302 'upload_badext' => array (
303 'php', 'php3', 'php4', 'php5', 'pl', 'cgi', 'py',
304 'asp', 'cfm', 'js', 'vbs', 'html', 'htm' ),
305 'upload_maxsize' => 3000000,
306 'import_max_execution_time' => 3600,
307 // 'use_php_code_json' => returnPhpJsonStatus(),
308 'verify_client_ip' => true,
309 'js_custom_version' => '',
310 'js_lang_version' => 1,
311 'lead_conv_activity_opt' => 'donothing',
312 'default_number_grouping_seperator' => ',',
313 'default_decimal_seperator' => '.',
314 'lock_homepage' => false,
315 'lock_subpanels' => false,
316 'max_dashlets_homepage' => '15',
317 'default_max_tabs' => '7',
318 'dashlet_display_row_options' => array('1','3','5','10'),
319 'default_subpanel_tabs' => true,
320 'default_subpanel_links' => false,
321 'default_swap_last_viewed' => false,
322 'default_swap_shortcuts' => false,
323 'default_navigation_paradigm' => 'gm',
324 'admin_access_control' => false,
325 'use_common_ml_dir' => false,
326 'common_ml_dir' => '',
328 'passwordsetting' => empty($passwordsetting) ? array (
329 'SystemGeneratedPasswordON' => '',
330 'generatepasswordtmpl' => '',
331 'lostpasswordtmpl' => '',
332 'forgotpasswordON' => false,
333 'linkexpiration' => '1',
334 'linkexpirationtime' => '30',
335 'linkexpirationtype' => '1',
336 'systexpiration' => '0',
337 'systexpirationtime' => '',
338 'systexpirationtype' => '0',
339 'systexpirationlogin' => '',
340 ) : $passwordsetting,
341 'use_real_names' => true,
344 if(!is_object($locale)) {
345 $locale = new Localization();
348 $sugar_config_defaults['default_currencies'] = $locale->getDefaultCurrencies();
350 $sugar_config_defaults = sugarArrayMerge($locale->getLocaleConfigDefaults(), $sugar_config_defaults);
351 return( $sugar_config_defaults );
355 * @deprecated use SugarView::getMenu() instead
357 function load_menu($path){
360 if(file_exists($path . 'Menu.php'))
362 require($path . 'Menu.php');
364 if(file_exists('custom/' . $path . 'Ext/Menus/menu.ext.php'))
366 require('custom/' . $path . 'Ext/Menus/menu.ext.php');
368 if(file_exists('custom/application/Ext/Menus/menu.ext.php'))
370 require('custom/application/Ext/Menus/menu.ext.php');
376 * get_notify_template_file
377 * This function will return the location of the email notifications template to use
379 * @return string relative file path to email notifications template file
381 function get_notify_template_file($language){
383 * Order of operation:
384 * 1) custom version of specified language
385 * 2) stock version of specified language
386 * 3) custom version of en_us template
387 * 4) stock en_us template
390 // set $file to the base code template so it's set if none of the conditions pass
391 $file = "include/language/en_us.notify_template.html";
393 if(file_exists("custom/include/language/{$language}.notify_template.html")){
394 $file = "custom/include/language/{$language}.notify_template.html";
396 else if(file_exists("include/language/{$language}.notify_template.html")){
397 $file = "include/language/{$language}.notify_template.html";
399 else if(file_exists("custom/include/language/en_us.notify_template.html")){
400 $file = "custom/include/language/en_us.notify_template.html";
406 function sugar_config_union( $default, $override ){
407 // a little different then array_merge and array_merge_recursive. we want
408 // the second array to override the first array if the same value exists,
409 // otherwise merge the unique keys. it handles arrays of arrays recursively
410 // might be suitable for a generic array_union
411 if( !is_array( $override ) ){
414 foreach( $default as $key => $value ){
415 if( !array_key_exists($key, $override) ){
416 $override[$key] = $value;
418 else if( is_array( $key ) ){
419 $override[$key] = sugar_config_union( $value, $override[$key] );
425 function make_not_writable( $file ){
426 // Returns true if the given file/dir has been made not writable
428 if( is_file($file) || is_dir($file) ){
429 if( !is_writable($file) ){
433 $original_fileperms = fileperms($file);
435 // take away writable permissions
436 $new_fileperms = $original_fileperms & ~0x0092;
437 @sugar_chmod($file, $new_fileperms);
439 if( !is_writable($file) ){
448 /** This function returns the name of the person.
449 * It currently returns "first last". It should not put the space if either name is not available.
450 * It should not return errors if either name is not available.
451 * If no names are present, it will return ""
452 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
453 * All Rights Reserved.
454 * Contributor(s): ______________________________________..
456 function return_name($row, $first_column, $last_column)
462 if(isset($row[$first_column]))
464 $first_name = stripslashes($row[$first_column]);
467 if(isset($row[$last_column]))
469 $last_name = stripslashes($row[$last_column]);
472 $full_name = $first_name;
474 // If we have a first name and we have a last name
475 if($full_name != "" && $last_name != "")
477 // append a space, then the last name
478 $full_name .= " ".$last_name;
480 // If we have no first name, but we have a last name
481 else if($last_name != "")
483 // append the last name without the space.
484 $full_name .= $last_name;
491 function get_languages()
493 global $sugar_config;
494 $lang = $sugar_config['languages'];
495 if(!empty($sugar_config['disabled_languages'])){
496 foreach(explode(',', $sugar_config['disabled_languages']) as $disable) {
497 unset($lang[$disable]);
503 function get_all_languages()
505 global $sugar_config;
506 return $sugar_config['languages'];
510 function get_language_display($key)
512 global $sugar_config;
513 return $sugar_config['languages'][$key];
516 function get_assigned_user_name($assigned_user_id, $is_group = '') {
517 static $saved_user_list = null;
519 if(empty($saved_user_list)) {
520 $saved_user_list = get_user_array(false, '', '', false, null, $is_group);
523 if(isset($saved_user_list[$assigned_user_id])) {
524 return $saved_user_list[$assigned_user_id];
531 * retrieves the user_name column value (login)
532 * @param string id GUID of user
535 function get_user_name($id) {
539 $db = DBManagerFactory::getInstance();
541 $q = "SELECT user_name FROM users WHERE id='{$id}'";
543 $a = $db->fetchByAssoc($r);
545 return (empty($a)) ? '' : $a['user_name'];
549 //TODO Update to use global cache
550 function get_user_array($add_blank=true, $status="Active", $assigned_user="", $use_real_name=false, $user_name_begins = null, $is_group=' AND portal_only=0 ', $from_cache = true) {
552 global $sugar_config;
556 $locale = new Localization();
559 $user_array = get_register_value('user_array', $add_blank. $status . $assigned_user);
561 if(empty($user_array)) {
562 $db = DBManagerFactory::getInstance();
563 $temp_result = Array();
564 // Including deleted users for now.
565 if (empty($status)) {
566 $query = "SELECT id, first_name, last_name, user_name from users WHERE 1=1".$is_group;
569 $query = "SELECT id, first_name, last_name, user_name from users WHERE status='$status'".$is_group;
572 if (!empty($user_name_begins)) {
573 $query .= " AND user_name LIKE '$user_name_begins%' ";
575 if (!empty($assigned_user)) {
576 $query .= " OR id='$assigned_user'";
578 $query = $query.' ORDER BY user_name ASC';
579 $GLOBALS['log']->debug("get_user_array query: $query");
580 $result = $db->query($query, true, "Error filling in user array: ");
582 if ($add_blank==true) {
583 // Add in a blank row
584 $temp_result[''] = '';
587 // Get the id and the name.
588 while($row = $db->fetchByAssoc($result)) {
589 if($use_real_name == true || showFullName()) {
590 if(isset($row['last_name'])) { // cn: we will ALWAYS have both first_name and last_name (empty value if blank in db)
591 $temp_result[$row['id']] = $locale->getLocaleFormattedName($row['first_name'],$row['last_name']);
593 $temp_result[$row['id']] = $row['user_name'];
596 $temp_result[$row['id']] = $row['user_name'];
600 $user_array = $temp_result;
602 set_register_value('user_array', $add_blank. $status . $assigned_user, $temp_result);
611 * uses a different query to return a list of users than get_user_array()
612 * @param args string where clause entry
613 * @return array Array of Users' details that match passed criteria
615 function getUserArrayFromFullName($args, $hide_portal_users = false) {
617 $db = DBManagerFactory::getInstance();
620 if(strpos($args, " ")) {
621 $argArray = explode(" ", $args);
627 foreach($argArray as $arg) {
628 if(!empty($inClause)) {
634 $inClause .= "(first_name LIKE '{$arg}%' OR last_name LIKE '{$arg}%')";
637 $query = "SELECT id, first_name, last_name, user_name FROM users WHERE status='Active' AND deleted=0 AND ";
638 if ( $hide_portal_users ) {
639 $query .= " portal_only=0 AND ";
642 $query .= " ORDER BY last_name ASC";
644 $r = $db->query($query);
646 while($a = $db->fetchByAssoc($r)) {
647 $ret[$a['id']] = $locale->getLocaleFormattedName($a['first_name'], $a['last_name']);
655 * based on user pref then system pref
657 function showFullName() {
658 global $sugar_config;
659 global $current_user;
660 static $showFullName = null;
662 if (is_null($showFullName)) {
663 $sysPref = !empty($sugar_config['use_real_names']);
664 $userPref = (is_object($current_user)) ? $current_user->getPreference('use_real_names') : null;
666 if($userPref != null) {
667 $showFullName = ($userPref == 'on');
669 $showFullName = $sysPref;
673 return $showFullName;
676 function clean($string, $maxLength)
678 $string = substr($string, 0, $maxLength);
679 return escapeshellcmd($string);
683 * Copy the specified request variable to the member variable of the specified object.
684 * Do no copy if the member variable is already set.
685 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
686 * All Rights Reserved.
687 * Contributor(s): ______________________________________..
689 function safe_map($request_var, & $focus, $always_copy = false)
691 safe_map_named($request_var, $focus, $request_var, $always_copy);
695 * Copy the specified request variable to the member variable of the specified object.
696 * Do no copy if the member variable is already set.
697 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
698 * All Rights Reserved.
699 * Contributor(s): ______________________________________..
701 function safe_map_named($request_var, & $focus, $member_var, $always_copy)
703 if (isset($_REQUEST[$request_var]) && ($always_copy || is_null($focus->$member_var))) {
704 $GLOBALS['log']->debug("safe map named called assigning '{$_REQUEST[$request_var]}' to $member_var");
705 $focus->$member_var = $_REQUEST[$request_var];
710 * This function retrieves an application language file and returns the array of strings included in the $app_list_strings var.
712 * @param string $language specific language to load
713 * @return array lang strings
715 function return_app_list_strings_language($language)
717 global $app_list_strings;
718 global $sugar_config;
720 $cache_key = 'app_list_strings.'.$language;
722 // Check for cached value
723 $cache_entry = sugar_cache_retrieve($cache_key);
724 if(!empty($cache_entry))
729 $default_language = $sugar_config['default_language'];
730 $temp_app_list_strings = $app_list_strings;
733 if ($language != 'en_us') {
736 if ($default_language != 'en_us' && $language != $default_language) {
737 $langs[] = $default_language;
739 $langs[] = $language;
741 $app_list_strings_array = array();
743 foreach ( $langs as $lang ) {
744 $app_list_strings = array();
745 if(file_exists("include/language/$lang.lang.php")) {
746 include("include/language/$lang.lang.php");
747 $GLOBALS['log']->info("Found language file: $lang.lang.php");
749 if(file_exists("include/language/$lang.lang.override.php")) {
750 include("include/language/$lang.lang.override.php");
751 $GLOBALS['log']->info("Found override language file: $lang.lang.override.php");
753 if(file_exists("include/language/$lang.lang.php.override")) {
754 include("include/language/$lang.lang.php.override");
755 $GLOBALS['log']->info("Found override language file: $lang.lang.php.override");
758 $app_list_strings_array[] = $app_list_strings;
761 $app_list_strings = array();
762 foreach ( $app_list_strings_array as $app_list_strings_item ) {
763 $app_list_strings = sugarArrayMerge($app_list_strings, $app_list_strings_item);
766 foreach ( $langs as $lang ) {
767 if(file_exists("custom/application/Ext/Language/$lang.lang.ext.php")) {
768 $app_list_strings = _mergeCustomAppListStrings("custom/application/Ext/Language/$lang.lang.ext.php" , $app_list_strings);
769 $GLOBALS['log']->info("Found extended language file: $lang.lang.ext.php");
771 if(file_exists("custom/include/language/$lang.lang.php")) {
772 include("custom/include/language/$lang.lang.php");
773 $GLOBALS['log']->info("Found custom language file: $lang.lang.php");
777 if(!isset($app_list_strings)) {
778 $GLOBALS['log']->fatal("Unable to load the application language file for the selected language ($language) or the default language ($default_language) or the en_us language");
782 $return_value = $app_list_strings;
783 $app_list_strings = $temp_app_list_strings;
785 sugar_cache_put($cache_key, $return_value);
787 return $return_value;
791 * The dropdown items in custom language files is $app_list_strings['$key']['$second_key'] = $value not
792 * $GLOBALS['app_list_strings']['$key'] = $value, so we have to delete the original ones in app_list_strings and relace it with the custom ones.
793 * @param file string the language that you want include,
794 * @param app_list_strings array the golbal strings
798 function _mergeCustomAppListStrings($file , $app_list_strings){
799 $app_list_strings_original = $app_list_strings;
800 unset($app_list_strings);
801 // FG - bug 45525 - $exemptDropdown array is defined (once) here, not inside the foreach
802 // This way, language file can add items to save specific standard codelist from being overwritten
803 $exemptDropdowns = array();
805 if(!isset($app_list_strings) || !is_array($app_list_strings)){
806 return $app_list_strings_original;
808 //Bug 25347: We should not merge custom dropdown fields unless they relate to parent fields or the module list.
810 // FG - bug 45525 - Specific codelists must NOT be overwritten
811 $exemptDropdowns[] = "moduleList";
812 $exemptDropdowns[] = "parent_type_display";
813 $exemptDropdowns[] = "record_type_display";
814 $exemptDropdowns[] = "record_type_display_notes";
816 foreach($app_list_strings as $key=>$value)
818 if (!in_array($key, $exemptDropdowns) && array_key_exists($key, $app_list_strings_original))
820 unset($app_list_strings_original["$key"]);
823 $app_list_strings = sugarArrayMergeRecursive($app_list_strings_original , $app_list_strings);
824 return $app_list_strings;
828 * This function retrieves an application language file and returns the array of strings included.
830 * @param string $language specific language to load
831 * @return array lang strings
833 function return_application_language($language)
835 global $app_strings, $sugar_config;
837 $cache_key = 'app_strings.'.$language;
839 // Check for cached value
840 $cache_entry = sugar_cache_retrieve($cache_key);
841 if(!empty($cache_entry))
846 $temp_app_strings = $app_strings;
847 $default_language = $sugar_config['default_language'];
850 if ($language != 'en_us') {
853 if ($default_language != 'en_us' && $language != $default_language) {
854 $langs[] = $default_language;
857 $langs[] = $language;
859 $app_strings_array = array();
861 foreach ( $langs as $lang ) {
862 $app_strings = array();
863 if(file_exists("include/language/$lang.lang.php")) {
864 include("include/language/$lang.lang.php");
865 $GLOBALS['log']->info("Found language file: $lang.lang.php");
867 if(file_exists("include/language/$lang.lang.override.php")) {
868 include("include/language/$lang.lang.override.php");
869 $GLOBALS['log']->info("Found override language file: $lang.lang.override.php");
871 if(file_exists("include/language/$lang.lang.php.override")) {
872 include("include/language/$lang.lang.php.override");
873 $GLOBALS['log']->info("Found override language file: $lang.lang.php.override");
875 if(file_exists("custom/application/Ext/Language/$lang.lang.ext.php")) {
876 include("custom/application/Ext/Language/$lang.lang.ext.php");
877 $GLOBALS['log']->info("Found extended language file: $lang.lang.ext.php");
879 if(file_exists("custom/include/language/$lang.lang.php")) {
880 include("custom/include/language/$lang.lang.php");
881 $GLOBALS['log']->info("Found custom language file: $lang.lang.php");
883 $app_strings_array[] = $app_strings;
886 $app_strings = array();
887 foreach ( $app_strings_array as $app_strings_item ) {
888 $app_strings = sugarArrayMerge($app_strings, $app_strings_item);
891 if(!isset($app_strings)) {
892 $GLOBALS['log']->fatal("Unable to load the application language strings");
896 // If we are in debug mode for translating, turn on the prefix now!
897 if($sugar_config['translation_string_prefix']) {
898 foreach($app_strings as $entry_key=>$entry_value) {
899 $app_strings[$entry_key] = $language.' '.$entry_value;
902 if(isset($_SESSION['show_deleted'])) {
903 $app_strings['LBL_DELETE_BUTTON'] = $app_strings['LBL_UNDELETE_BUTTON'];
904 $app_strings['LBL_DELETE_BUTTON_LABEL'] = $app_strings['LBL_UNDELETE_BUTTON_LABEL'];
905 $app_strings['LBL_DELETE_BUTTON_TITLE'] = $app_strings['LBL_UNDELETE_BUTTON_TITLE'];
906 $app_strings['LBL_DELETE'] = $app_strings['LBL_UNDELETE'];
909 $app_strings['LBL_ALT_HOT_KEY'] = get_alt_hot_key();
911 $return_value = $app_strings;
912 $app_strings = $temp_app_strings;
914 sugar_cache_put($cache_key, $return_value);
916 return $return_value;
920 * This function retrieves a module's language file and returns the array of strings included.
922 * @param string $language specific language to load
923 * @param string $module module name to load strings for
924 * @param bool $refresh optional, true if you want to rebuild the language strings
925 * @return array lang strings
927 function return_module_language($language, $module, $refresh=false)
930 global $sugar_config;
931 global $currentModule;
933 // Jenny - Bug 8119: Need to check if $module is not empty
934 if (empty($module)) {
935 $stack = debug_backtrace();
936 $GLOBALS['log']->warn("Variable module is not in return_module_language ". var_export($stack, true));
942 $cache_key = LanguageManager::getLanguageCacheKey($module, $language);
943 // Check for cached value
944 $cache_entry = sugar_cache_retrieve($cache_key);
945 if(!empty($cache_entry))
950 // Store the current mod strings for later
951 $temp_mod_strings = $mod_strings;
952 $loaded_mod_strings = array();
953 $language_used = $language;
954 $default_language = $sugar_config['default_language'];
956 if(empty($language)) {
957 $language = $default_language;
960 // Bug 21559 - So we can get all the strings defined in the template, refresh
961 // the vardefs file if the cached language file doesn't exist.
962 if(!file_exists($GLOBALS['sugar_config']['cache_dir'].'modules/'. $module . '/language/'.$language.'.lang.php')
963 && !empty($GLOBALS['beanList'][$module])){
964 $object = BeanFactory::getObjectName($module);
965 VardefManager::refreshVardefs($module,$object);
968 $loaded_mod_strings = LanguageManager::loadModuleLanguage($module, $language,$refresh);
970 // cn: bug 6048 - merge en_us with requested language
971 if($language != $sugar_config['default_language'])
972 $loaded_mod_strings = sugarArrayMerge(
973 LanguageManager::loadModuleLanguage($module, $sugar_config['default_language'],$refresh),
977 // Load in en_us strings by default
978 if($language != 'en_us' && $sugar_config['default_language'] != 'en_us')
979 $loaded_mod_strings = sugarArrayMerge(
980 LanguageManager::loadModuleLanguage($module, 'en_us', $refresh),
984 // If we are in debug mode for translating, turn on the prefix now!
985 if($sugar_config['translation_string_prefix']) {
986 foreach($loaded_mod_strings as $entry_key=>$entry_value) {
987 $loaded_mod_strings[$entry_key] = $language_used.' '.$entry_value;
991 $return_value = $loaded_mod_strings;
992 if(!isset($mod_strings)){
993 $mod_strings = $return_value;
996 $mod_strings = $temp_mod_strings;
998 $cache_key = LanguageManager::getLanguageCacheKey($module, $language);
999 sugar_cache_put($cache_key, $return_value);
1000 return $return_value;
1004 /** This function retrieves an application language file and returns the array of strings included in the $mod_list_strings var.
1005 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1006 * All Rights Reserved.
1007 * Contributor(s): ______________________________________..
1008 * If you are using the current language, do not call this function unless you are loading it for the first time */
1009 function return_mod_list_strings_language($language,$module) {
1010 global $mod_list_strings;
1011 global $sugar_config;
1012 global $currentModule;
1014 $cache_key = "mod_list_str_lang.".$language.$module;
1016 // Check for cached value
1017 $cache_entry = sugar_cache_retrieve($cache_key);
1018 if(!empty($cache_entry))
1020 return $cache_entry;
1023 $language_used = $language;
1024 $temp_mod_list_strings = $mod_list_strings;
1025 $default_language = $sugar_config['default_language'];
1027 if($currentModule == $module && isset($mod_list_strings) && $mod_list_strings != null) {
1028 return $mod_list_strings;
1031 // cn: bug 6351 - include en_us if file langpack not available
1032 // cn: bug 6048 - merge en_us with requested language
1033 include("modules/$module/language/en_us.lang.php");
1034 $en_mod_list_strings = array();
1035 if($language_used != $default_language)
1036 $en_mod_list_strings = $mod_list_strings;
1038 if(file_exists("modules/$module/language/$language.lang.php")) {
1039 include("modules/$module/language/$language.lang.php");
1042 if(file_exists("modules/$module/language/$language.lang.override.php")){
1043 include("modules/$module/language/$language.lang.override.php");
1046 if(file_exists("modules/$module/language/$language.lang.php.override")){
1047 echo 'Please Change:<br>' . "modules/$module/language/$language.lang.php.override" . '<br>to<br>' . 'Please Change:<br>' . "modules/$module/language/$language.lang.override.php";
1048 include("modules/$module/language/$language.lang.php.override");
1051 // cn: bug 6048 - merge en_us with requested language
1052 $mod_list_strings = sugarArrayMerge($en_mod_list_strings, $mod_list_strings);
1054 // if we still don't have a language pack, then log an error
1055 if(!isset($mod_list_strings)) {
1056 $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})");
1060 $return_value = $mod_list_strings;
1061 $mod_list_strings = $temp_mod_list_strings;
1063 sugar_cache_put($cache_key, $return_value);
1064 return $return_value;
1068 /** This function retrieves a theme's language file and returns the array of strings included.
1069 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1070 * All Rights Reserved.
1071 * Contributor(s): ______________________________________..
1073 function return_theme_language($language, $theme)
1075 global $mod_strings, $sugar_config, $currentModule;
1077 $language_used = $language;
1078 $default_language = $sugar_config['default_language'];
1080 include(SugarThemeRegistry::get($theme)->getFilePath()."/language/$current_language.lang.php");
1081 if(file_exists(SugarThemeRegistry::get($theme)->getFilePath()."/language/$current_language.lang.override.php")){
1082 include(SugarThemeRegistry::get($theme)->getFilePath()."/language/$current_language.lang.override.php");
1084 if(file_exists(SugarThemeRegistry::get($theme)->getFilePath()."/language/$current_language.lang.php.override")){
1085 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";
1086 include(SugarThemeRegistry::get($theme)->getFilePath()."/language/$current_language.lang.php.override");
1088 if(!isset($theme_strings))
1090 $GLOBALS['log']->warn("Unable to find the theme file for language: ".$language." and theme: ".$theme);
1091 require(SugarThemeRegistry::get($theme)->getFilePath()."/language/$default_language.lang.php");
1092 $language_used = $default_language;
1095 if(!isset($theme_strings))
1097 $GLOBALS['log']->fatal("Unable to load the theme($theme) language file for the selected language($language) or the default language($default_language)");
1101 // If we are in debug mode for translating, turn on the prefix now!
1102 if($sugar_config['translation_string_prefix'])
1104 foreach($theme_strings as $entry_key=>$entry_value)
1106 $theme_strings[$entry_key] = $language_used.' '.$entry_value;
1110 return $theme_strings;
1115 /** If the session variable is defined and is not equal to "" then return it. Otherwise, return the default value.
1116 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1117 * All Rights Reserved.
1118 * Contributor(s): ______________________________________..
1120 function return_session_value_or_default($varname, $default)
1122 if(isset($_SESSION[$varname]) && $_SESSION[$varname] != "")
1124 return $_SESSION[$varname];
1131 * Creates an array of where restrictions. These are used to construct a where SQL statement on the query
1132 * 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.
1133 * @param &$where_clauses - The array to append the clause to
1134 * @param $variable_name - The name of the variable to look for an add to the where clause if found
1135 * @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.
1136 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1137 * All Rights Reserved.
1138 * Contributor(s): ______________________________________..
1140 function append_where_clause(&$where_clauses, $variable_name, $SQL_name = null)
1142 if($SQL_name == null)
1144 $SQL_name = $variable_name;
1147 if(isset($_REQUEST[$variable_name]) && $_REQUEST[$variable_name] != "")
1149 array_push($where_clauses, "$SQL_name like '".$GLOBALS['db']->quote($_REQUEST[$variable_name])."%'");
1154 * Generate the appropriate SQL based on the where clauses.
1155 * @param $where_clauses - An Array of individual where clauses stored as strings
1156 * @returns string where_clause - The final SQL where clause to be executed.
1157 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1158 * All Rights Reserved.
1159 * Contributor(s): ______________________________________..
1161 function generate_where_statement($where_clauses)
1164 foreach($where_clauses as $clause)
1171 $GLOBALS['log']->info("Here is the where clause for the list view: $where");
1176 * determines if a passed string matches the criteria for a Sugar GUID
1177 * @param string $guid
1178 * @return bool False on failure
1180 function is_guid($guid) {
1181 if(strlen($guid) != 36) {
1185 if(preg_match("/\w{8}-\w{4}-\w{4}-\w{4}-\w{12}/i", $guid)) {
1194 * A temporary method of generating GUIDs of the correct format for our DB.
1195 * @return String contianing a GUID in the format: aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
1197 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1198 * All Rights Reserved.
1199 * Contributor(s): ______________________________________..
1201 function create_guid()
1203 $microTime = microtime();
1204 list($a_dec, $a_sec) = explode(" ", $microTime);
1206 $dec_hex = dechex($a_dec* 1000000);
1207 $sec_hex = dechex($a_sec);
1209 ensure_length($dec_hex, 5);
1210 ensure_length($sec_hex, 6);
1214 $guid .= create_guid_section(3);
1216 $guid .= create_guid_section(4);
1218 $guid .= create_guid_section(4);
1220 $guid .= create_guid_section(4);
1223 $guid .= create_guid_section(6);
1229 function create_guid_section($characters)
1232 for($i=0; $i<$characters; $i++)
1234 $return .= dechex(mt_rand(0,15));
1239 function ensure_length(&$string, $length)
1241 $strlen = strlen($string);
1242 if($strlen < $length)
1244 $string = str_pad($string,$length,"0");
1246 else if($strlen > $length)
1248 $string = substr($string, 0, $length);
1252 function microtime_diff($a, $b) {
1253 list($a_dec, $a_sec) = explode(" ", $a);
1254 list($b_dec, $b_sec) = explode(" ", $b);
1255 return $b_sec - $a_sec + $b_dec - $a_dec;
1258 // check if Studio is displayed.
1259 function displayStudioForCurrentUser()
1261 global $current_user;
1262 if ( $current_user->isAdmin() ) {
1272 function displayWorkflowForCurrentUser()
1274 $_SESSION['display_workflow_for_user'] = false;
1278 // return an array with all modules where the user is an admin.
1279 function get_admin_modules_for_user($user) {
1280 $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");
1287 return($user->getDeveloperModules());
1291 function get_workflow_admin_modules_for_user($user){
1292 if (isset($_SESSION['get_workflow_admin_modules_for_user'])) {
1293 return $_SESSION['get_workflow_admin_modules_for_user'];
1297 $workflow_mod_list = array();
1298 foreach($moduleList as $module){
1299 $workflow_mod_list[$module] = $module;
1302 // This list is taken from teh previous version of workflow_utils.php
1303 $workflow_mod_list['Tasks'] = "Tasks";
1304 $workflow_mod_list['Calls'] = "Calls";
1305 $workflow_mod_list['Meetings'] = "Meetings";
1306 $workflow_mod_list['Notes'] = "Notes";
1307 $workflow_mod_list['ProjectTask'] = "Project Tasks";
1308 $workflow_mod_list['Leads'] = "Leads";
1309 $workflow_mod_list['Opportunities'] = "Opportunities";
1312 $workflow_admin_modules = array();
1314 return $workflow_admin_modules;
1316 $actions = ACLAction::getUserActions($user->id);
1317 //check for ForecastSchedule because it doesn't exist in $workflow_mod_list
1318 if (isset($actions['ForecastSchedule']['module']['admin']['aclaccess']) && ($actions['ForecastSchedule']['module']['admin']['aclaccess']==ACL_ALLOW_DEV ||
1319 $actions['ForecastSchedule']['module']['admin']['aclaccess']==ACL_ALLOW_ADMIN_DEV)) {
1320 $workflow_admin_modules['Forecasts'] = 'Forecasts';
1322 foreach ($workflow_mod_list as $key=>$val) {
1323 if(!in_array($val, $workflow_admin_modules) && ($val!='iFrames' && $val!='Feeds' && $val!='Home' && $val!='Dashboard'
1324 && $val!='Calendar' && $val!='Activities' && $val!='Reports') &&
1325 ($user->isDeveloperForModule($key))) {
1326 $workflow_admin_modules[$key] = $val;
1329 $_SESSION['get_workflow_admin_modules_for_user'] = $workflow_admin_modules;
1330 return ($workflow_admin_modules);
1333 // Check if user is admin for at least one module.
1334 function is_admin_for_any_module($user) {
1338 if($user->isAdmin()) {
1345 // Check if user is admin for a specific module.
1346 function is_admin_for_module($user,$module) {
1347 if (!isset($user)) {
1350 if ($user->isAdmin()) {
1358 * Check if user id belongs to a system admin.
1359 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1360 * All Rights Reserved.
1361 * Contributor(s): ______________________________________..
1363 function is_admin($user) {
1368 return $user->isAdmin();
1372 * Return the display name for a theme if it exists.
1373 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1374 * All Rights Reserved.
1375 * Contributor(s): ______________________________________..
1377 * @deprecated use SugarThemeRegistry::get($theme)->name instead
1379 function get_theme_display($theme)
1381 return SugarThemeRegistry::get($theme)->name;
1385 * Return an array of directory names.
1386 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1387 * All Rights Reserved.
1388 * Contributor(s): ______________________________________..
1390 * @deprecated use SugarThemeRegistry::availableThemes() instead.
1392 function get_themes()
1394 return SugarThemeRegistry::availableThemes();
1398 * THIS FUNCTION IS DEPRECATED AND SHOULD NOT BE USED; USE get_select_options_with_id()
1399 * Create HTML to display select options in a dropdown list. To be used inside
1400 * of a select statement in a form.
1401 * param $option_list - the array of strings to that contains the option list
1402 * param $selected - the string which contains the default value
1403 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1404 * All Rights Reserved.
1405 * Contributor(s): ______________________________________..
1407 function get_select_options ($option_list, $selected) {
1408 return get_select_options_with_id($option_list, $selected);
1412 * Create HTML to display select options in a dropdown list. To be used inside
1413 * 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.
1414 * param $option_list - the array of strings to that contains the option list
1415 * param $selected - the string which contains the default value
1416 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1417 * All Rights Reserved.
1418 * Contributor(s): ______________________________________..
1420 function get_select_options_with_id ($option_list, $selected_key) {
1421 return get_select_options_with_id_separate_key($option_list, $option_list, $selected_key);
1426 * Create HTML to display select options in a dropdown list. To be used inside
1427 * 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.
1428 * param $label_list - the array of strings to that contains the option list
1429 * param $key_list - the array of strings to that contains the values list
1430 * param $selected - the string which contains the default value
1431 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1432 * All Rights Reserved.
1433 * Contributor(s): ______________________________________..
1435 function get_select_options_with_id_separate_key ($label_list, $key_list, $selected_key, $massupdate=false) {
1436 global $app_strings;
1437 $select_options = "";
1439 //for setting null selection values to human readable --None--
1440 $pattern = "/'0?'></";
1441 $replacement = "''>".$app_strings['LBL_NONE']."<";
1443 $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
1446 if (empty($key_list)) $key_list = array();
1447 //create the type dropdown domain and set the selected value if $opp value already exists
1448 foreach ($key_list as $option_key=>$option_value) {
1450 $selected_string = '';
1451 // the system is evaluating $selected_key == 0 || '' to true. Be very careful when changing this. Test all cases.
1452 // The bug was only happening with one of the users in the drop down. It was being replaced by none.
1453 if (($option_key != '' && $selected_key == $option_key) || ($selected_key == '' && $option_key == '' && !$massupdate) || (is_array($selected_key) && in_array($option_key, $selected_key)))
1455 $selected_string = 'selected ';
1458 $html_value = $option_key;
1460 $select_options .= "\n<OPTION ".$selected_string."value='$html_value'>$label_list[$option_key]</OPTION>";
1462 $select_options = preg_replace($pattern, $replacement, $select_options);
1463 return $select_options;
1468 * Call this method instead of die().
1469 * Then we call the die method with the error message that is passed in.
1471 function sugar_die($error_message)
1475 die($error_message);
1480 * Create javascript to clear values of all elements in a form.
1481 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1482 * All Rights Reserved.
1483 * Contributor(s): ______________________________________..
1485 function get_clear_form_js () {
1486 $the_script = <<<EOQ
1487 <script type="text/javascript" language="JavaScript">
1488 function clear_form(form) {
1489 var newLoc = 'index.php?action=' + form.action.value + '&module=' + form.module.value + '&query=true&clear_query=true';
1490 if(typeof(form.advanced) != 'undefined'){
1491 newLoc += '&advanced=' + form.advanced.value;
1493 document.location.href= newLoc;
1502 * Create javascript to set the cursor focus to specific field in a form
1503 * when the screen is rendered. The field name is currently hardcoded into the
1505 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1506 * All Rights Reserved.
1507 * Contributor(s): ______________________________________..
1509 function get_set_focus_js () {
1510 //TODO Clint 5/20 - Make this function more generic so that it can take in the target form and field names as variables
1511 $the_script = <<<EOQ
1512 <script type="text/javascript" language="JavaScript">
1514 function set_focus() {
1515 if (document.forms.length > 0) {
1516 for (i = 0; i < document.forms.length; i++) {
1517 for (j = 0; j < document.forms[i].elements.length; j++) {
1518 var field = document.forms[i].elements[j];
1519 if ((field.type == "text" || field.type == "textarea" || field.type == "password") &&
1520 !field.disabled && (field.name == "first_name" || field.name == "name" || field.name == "user_name" || field.name=="document_name")) {
1522 if (field.type == "text") {
1539 * Very cool algorithm for sorting multi-dimensional arrays. Found at http://us2.php.net/manual/en/function.array-multisort.php
1540 * Syntax: $new_array = array_csort($array [, 'col1' [, SORT_FLAG [, SORT_FLAG]]]...);
1541 * Explanation: $array is the array you want to sort, 'col1' is the name of the column
1542 * you want to sort, SORT_FLAGS are : SORT_ASC, SORT_DESC, SORT_REGULAR, SORT_NUMERIC, SORT_STRING
1543 * you can repeat the 'col',FLAG,FLAG, as often you want, the highest prioritiy is given to
1544 * the first - so the array is sorted by the last given column first, then the one before ...
1545 * Example: $array = array_csort($array,'town','age',SORT_DESC,'name');
1546 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1547 * All Rights Reserved.
1548 * Contributor(s): ______________________________________..
1550 function array_csort() {
1551 $args = func_get_args();
1552 $marray = array_shift($args);
1555 $msortline = "return(array_multisort(";
1556 foreach ($args as $arg) {
1558 if (is_string($arg)) {
1559 foreach ($marray as $row) {
1560 $sortarr[$i][] = $row[$arg];
1563 $sortarr[$i] = $arg;
1565 $msortline .= "\$sortarr[".$i."],";
1567 $msortline .= "\$marray));";
1574 * Converts localized date format string to jscalendar format
1575 * Example: $array = array_csort($array,'town','age',SORT_DESC,'name');
1576 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1577 * All Rights Reserved.
1578 * Contributor(s): ______________________________________..
1580 function parse_calendardate($local_format) {
1581 preg_match('/\(?([^-]{1})[^-]*-([^-]{1})[^-]*-([^-]{1})[^-]*\)/', $local_format, $matches);
1582 $calendar_format = "%" . $matches[1] . "-%" . $matches[2] . "-%" . $matches[3];
1583 return str_replace(array("y", "ᅣ1�7", "a", "j"), array("Y", "Y", "Y", "d"), $calendar_format);
1590 function translate($string, $mod='', $selectedValue=''){
1591 //$test_start = microtime();
1592 //static $mod_strings_results = array();
1594 global $current_language;
1596 if(isset($_REQUEST['login_language'])){
1597 $current_language = ($_REQUEST['login_language'] == $current_language)? $current_language : $_REQUEST['login_language'];
1599 $mod_strings = return_module_language($current_language, $mod);
1602 global $mod_strings;
1606 global $app_strings, $app_list_strings;
1608 if(isset($mod_strings[$string]))
1609 $returnValue = $mod_strings[$string];
1610 else if(isset($app_strings[$string]))
1611 $returnValue = $app_strings[$string];
1612 else if(isset($app_list_strings[$string]))
1613 $returnValue = $app_list_strings[$string];
1614 else if(isset($app_list_strings['moduleList']) && isset($app_list_strings['moduleList'][$string]))
1615 $returnValue = $app_list_strings['moduleList'][$string];
1618 //$test_end = microtime();
1620 // $mod_strings_results[$mod] = microtime_diff($test_start,$test_end);
1622 // echo("translate results:");
1624 // $total_strings = 0;
1625 // foreach($mod_strings_results as $key=>$value)
1627 // echo("Module $key \t\t time $value \t\t<br>");
1628 // $total_time += $value;
1631 // echo("Total time: $total_time<br>");
1635 if(empty($returnValue)){
1639 if(is_array($returnValue) && ! empty($selectedValue) && isset($returnValue[$selectedValue]) ){
1640 return $returnValue[$selectedValue];
1643 return $returnValue;
1646 function unTranslateNum($num) {
1648 static $num_grp_sep;
1649 global $current_user, $sugar_config;
1651 if($dec_sep == null) {
1652 $user_dec_sep = $current_user->getPreference('dec_sep');
1653 $dec_sep = (empty($user_dec_sep) ? $sugar_config['default_decimal_seperator'] : $user_dec_sep);
1655 if($num_grp_sep == null) {
1656 $user_num_grp_sep = $current_user->getPreference('num_grp_sep');
1657 $num_grp_sep = (empty($user_num_grp_sep) ? $sugar_config['default_number_grouping_seperator'] : $user_num_grp_sep);
1660 $num = preg_replace("'" . preg_quote($num_grp_sep) . "'", '', $num);
1661 $num = preg_replace("'" . preg_quote($dec_sep) . "'", '.', $num);
1666 function add_http($url) {
1667 if(!preg_match("@://@i", $url)) {
1669 if(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') {
1673 return "{$scheme}://{$url}";
1680 * returns a default array of XSS tags to clean
1683 function getDefaultXssTags() {
1685 "applet" => "applet",
1690 "frameset" => "frameset",
1691 "iframe" => "iframe",
1692 "import" => "\?import",
1695 "object" => "object",
1696 "script" => "script",
1700 $ret = base64_encode(serialize($tmp));
1706 * Remove potential xss vectors from strings
1707 * @param string str String to search for XSS attack vectors
1708 * @param bool cleanImg Flag to allow <img> tags to survive - only used by InboundEmail for inline images.
1711 function remove_xss($str, $cleanImg=true)
1713 $potentials = clean_xss($str, $cleanImg);
1714 if(is_array($potentials) && !empty($potentials)) {
1715 foreach($potentials as $bad) {
1716 $str = str_replace($bad, "", $str);
1723 * Detects typical XSS attack patterns
1724 * @param string str String to search for XSS attack vectors
1725 * @param bool cleanImg Flag to allow <img> tags to survive - only used by InboundEmail for inline images.
1726 * @return array Array of matches, empty on clean string
1728 function clean_xss($str, $cleanImg=true) {
1729 global $sugar_config;
1731 if(empty($sugar_config['email_xss']))
1732 $sugar_config['email_xss'] = getDefaultXssTags();
1734 $arr = unserialize(base64_decode($sugar_config['email_xss']));
1737 foreach($arr as $v) {
1738 if(!empty($regex)) {
1744 $tag_regex = "#<({$regex})[^>]*>?#sim";
1746 // cn: bug 13079 - "on\w" matched too many non-events (cONTact, strONG, etc.)
1747 $jsEvents = "onblur|onfocus|oncontextmenu|onresize|onscroll|onunload|ondblclick|onclick|";
1748 $jsEvents .= "onmouseup|onmouseover|onmousedown|onmouseenter|onmouseleave|onmousemove|onload|onchange|";
1749 $jsEvents .= "onreset|onselect|onsubmit|onkeydown|onkeypress|onkeyup|onabort|onerror|ondragdrop";
1751 $attribute_regex = "#<.+({$jsEvents})[^=>]*=[^>]*>#sim";
1752 $javascript_regex = '@<[^/>][^>]+(expression\(|j\W*a\W*v\W*a|v\W*b\W*s\W*c\W*r|&#|/\*|\*/)[^>]*>@sim';
1753 $imgsrc_regex = '#<[^>]+src[^=]*=([^>]*?http(s)?://[^>]*)>#sim';
1754 $css_url = '#url\(.*\.\w+\)#';
1757 $str = str_replace("\t", "", $str);
1759 $matches = array_merge(
1760 xss_check_pattern($tag_regex, $str),
1761 xss_check_pattern($javascript_regex, $str)
1765 $jsMatches = xss_check_pattern($attribute_regex, $str);
1766 if(!empty($jsMatches)){
1767 preg_match_all($attribute_regex, $str, $newMatches, PREG_PATTERN_ORDER);
1768 if(!empty($newMatches[0][0])){
1769 $matches2 = array_merge(xss_check_pattern("#({$jsEvents})#sim", $newMatches[0][0]));
1770 $matches = array_merge($matches, $matches2);
1775 $matches = array_merge($matches,
1776 xss_check_pattern($imgsrc_regex, $str)
1780 // cn: bug 13498 - custom white-list of allowed domains that vet remote images
1781 preg_match_all($css_url, $str, $cssUrlMatches, PREG_PATTERN_ORDER);
1783 if(isset($sugar_config['security_trusted_domains']) && !empty($sugar_config['security_trusted_domains']) && is_array($sugar_config['security_trusted_domains'])) {
1784 if(is_array($cssUrlMatches) && count($cssUrlMatches) > 0) {
1785 // normalize whitelist
1786 foreach($sugar_config['security_trusted_domains'] as $k => $v) {
1787 $sugar_config['security_trusted_domains'][$k] = strtolower($v);
1790 foreach($cssUrlMatches[0] as $match) {
1791 $domain = strtolower(substr(strstr($match, "://"), 3));
1792 $baseUrl = substr($domain, 0, strpos($domain, "/"));
1794 if(!in_array($baseUrl, $sugar_config['security_trusted_domains'])) {
1795 $matches[] = $match;
1800 $matches = array_merge($matches, $cssUrlMatches[0]);
1807 * Helper function used by clean_xss() to parse for known-bad vectors
1808 * @param string pattern Regex pattern to use
1809 * @param string str String to parse for badness
1812 function xss_check_pattern($pattern, $str) {
1813 preg_match_all($pattern, $str, $matches, PREG_PATTERN_ORDER);
1818 * Designed to take a string passed in the URL as a parameter and clean all "bad" data from it
1820 * @param string $str
1821 * @param string $filter which corresponds to a regular expression to use; choices are:
1822 * "STANDARD" ( default )
1832 * @param boolean $dieOnBadData true (default) if you want to die if bad data if found, false if not
1834 function clean_string($str, $filter = "STANDARD", $dieOnBadData = true)
1836 global $sugar_config;
1839 "STANDARD" => '#[^A-Z0-9\-_\.\@]#i',
1840 "STANDARDSPACE" => '#[^A-Z0-9\-_\.\@\ ]#i',
1841 "FILE" => '#[^A-Z0-9\-_\.]#i',
1842 "NUMBER" => '#[^0-9\-]#i',
1843 "SQL_COLUMN_LIST" => '#[^A-Z0-9\(\),_\.]#i',
1844 "PATH_NO_URL" => '#://#i',
1845 "SAFED_GET" => '#[^A-Z0-9\@\=\&\?\.\/\-_~]#i', /* range of allowed characters in a GET string */
1846 "UNIFIED_SEARCH" => "#[\\x00]#", /* cn: bug 3356 & 9236 - MBCS search strings */
1847 "AUTO_INCREMENT" => '#[^0-9\-,\ ]#i',
1848 "ALPHANUM" => '#[^A-Z0-9\-]#i',
1851 if (preg_match($filters[$filter], $str)) {
1852 if (isset($GLOBALS['log']) && is_object($GLOBALS['log'])) {
1853 $GLOBALS['log']->fatal("SECURITY: bad data passed in; string: {$str}");
1855 if ( $dieOnBadData ) {
1856 die("Bad data passed in; <a href=\"{$sugar_config['site_url']}\">Return to Home</a>");
1865 function clean_special_arguments() {
1866 if(isset($_SERVER['PHP_SELF'])) {
1867 if (!empty($_SERVER['PHP_SELF'])) clean_string($_SERVER['PHP_SELF'], 'SAFED_GET');
1869 if (!empty($_REQUEST) && !empty($_REQUEST['login_theme'])) clean_string($_REQUEST['login_theme'], "STANDARD");
1870 if (!empty($_REQUEST) && !empty($_REQUEST['login_module'])) clean_string($_REQUEST['login_module'], "STANDARD");
1871 if (!empty($_REQUEST) && !empty($_REQUEST['login_action'])) clean_string($_REQUEST['login_action'], "STANDARD");
1872 if (!empty($_REQUEST) && !empty($_REQUEST['ck_login_theme_20'])) clean_string($_REQUEST['ck_login_theme_20'], "STANDARD");
1873 if (!empty($_SESSION) && !empty($_SESSION['authenticated_user_theme'])) clean_string($_SESSION['authenticated_user_theme'], "STANDARD");
1874 if (!empty($_REQUEST) && !empty($_REQUEST['module_name'])) clean_string($_REQUEST['module_name'], "STANDARD");
1875 if (!empty($_REQUEST) && !empty($_REQUEST['module'])) clean_string($_REQUEST['module'], "STANDARD");
1876 if (!empty($_POST) && !empty($_POST['parent_type'])) clean_string($_POST['parent_type'], "STANDARD");
1877 if (!empty($_REQUEST) && !empty($_REQUEST['mod_lang'])) clean_string($_REQUEST['mod_lang'], "STANDARD");
1878 if (!empty($_SESSION) && !empty($_SESSION['authenticated_user_language'])) clean_string($_SESSION['authenticated_user_language'], "STANDARD");
1879 if (!empty($_SESSION) && !empty($_SESSION['dyn_layout_file'])) clean_string($_SESSION['dyn_layout_file'], "PATH_NO_URL");
1880 if (!empty($_GET) && !empty($_GET['from'])) clean_string($_GET['from']);
1881 if (!empty($_GET) && !empty($_GET['gmto'])) clean_string($_GET['gmto'], "NUMBER");
1882 if (!empty($_GET) && !empty($_GET['case_number'])) clean_string($_GET['case_number'], "AUTO_INCREMENT");
1883 if (!empty($_GET) && !empty($_GET['bug_number'])) clean_string($_GET['bug_number'], "AUTO_INCREMENT");
1884 if (!empty($_GET) && !empty($_GET['quote_num'])) clean_string($_GET['quote_num'], "AUTO_INCREMENT");
1885 clean_superglobals('stamp', 'ALPHANUM'); // for vcr controls
1886 clean_superglobals('offset', 'ALPHANUM');
1887 clean_superglobals('return_action');
1888 clean_superglobals('return_module');
1893 * cleans the given key in superglobals $_GET, $_POST, $_REQUEST
1895 function clean_superglobals($key, $filter = 'STANDARD') {
1896 if(isset($_GET[$key])) clean_string($_GET[$key], $filter);
1897 if(isset($_POST[$key])) clean_string($_POST[$key], $filter);
1898 if(isset($_REQUEST[$key])) clean_string($_REQUEST[$key], $filter);
1901 function set_superglobals($key, $val){
1903 $_POST[$key] = $val;
1904 $_REQUEST[$key] = $val;
1907 // Works in conjunction with clean_string() to defeat SQL injection, file inclusion attacks, and XSS
1908 function clean_incoming_data() {
1909 global $sugar_config;
1911 if (get_magic_quotes_gpc() == 1) {
1912 $req = array_map("preprocess_param", $_REQUEST);
1913 $post = array_map("preprocess_param", $_POST);
1914 $get = array_map("preprocess_param", $_GET);
1917 $req = array_map("securexss", $_REQUEST);
1918 $post = array_map("securexss", $_POST);
1919 $get = array_map("securexss", $_GET);
1922 // PHP cannot stomp out superglobals reliably
1923 foreach($post as $k => $v) { $_POST[$k] = $v; }
1924 foreach($get as $k => $v) { $_GET[$k] = $v; }
1925 foreach($req as $k => $v) {
1927 //ensure the keys are safe as well
1930 // Any additional variables that need to be cleaned should be added here
1931 if (isset($_REQUEST['login_theme'])) clean_string($_REQUEST['login_theme']);
1932 if (isset($_REQUEST['login_module'])) clean_string($_REQUEST['login_module']);
1933 if (isset($_REQUEST['login_action'])) clean_string($_REQUEST['login_action']);
1934 if (isset($_REQUEST['login_language'])) clean_string($_REQUEST['login_language']);
1935 if (isset($_REQUEST['action'])) clean_string($_REQUEST['action']);
1936 if (isset($_REQUEST['module'])) clean_string($_REQUEST['module']);
1937 if (isset($_REQUEST['record'])) clean_string($_REQUEST['record'], 'STANDARDSPACE');
1938 if (isset($_SESSION['authenticated_user_theme'])) clean_string($_SESSION['authenticated_user_theme']);
1939 if (isset($_SESSION['authenticated_user_language'])) clean_string($_SESSION['authenticated_user_language']);
1940 if (isset($_REQUEST['language'])) clean_string($_REQUEST['language']);
1941 if (isset($sugar_config['default_theme'])) clean_string($sugar_config['default_theme']);
1942 if (isset($_REQUEST['offset'])) clean_string($_REQUEST['offset']);
1943 if (isset($_REQUEST['stamp'])) clean_string($_REQUEST['stamp']);
1945 if(isset($_REQUEST['lvso'])){
1946 set_superglobals('lvso', (strtolower($_REQUEST['lvso']) === 'desc')?'desc':'asc');
1948 // Clean "offset" and "order_by" parameters in URL
1949 foreach ($_REQUEST as $key => $val) {
1950 if (str_end($key, "_offset")) {
1951 clean_string($_REQUEST[$key], "ALPHANUM"); // keep this ALPHANUM for disable_count_query
1952 set_superglobals($key, $_REQUEST[$key]);
1954 elseif (str_end($key, "_ORDER_BY")) {
1955 clean_string($_REQUEST[$key], "SQL_COLUMN_LIST");
1956 set_superglobals($key, $_REQUEST[$key]);
1964 // Returns TRUE if $str begins with $begin
1965 function str_begin($str, $begin) {
1966 return (substr($str, 0, strlen($begin)) == $begin);
1969 // Returns TRUE if $str ends with $end
1970 function str_end($str, $end) {
1971 return (substr($str, strlen($str) - strlen($end)) == $end);
1974 function securexss($value) {
1975 if(is_array($value)){
1977 foreach($value as $key=>$val){
1978 $new[$key] = securexss($val);
1982 static $xss_cleanup= array('"' =>'"', "'" => ''' , '<' =>'<' , '>'=>'>');
1983 $value = preg_replace(array('/javascript:/i', '/\0/'), array('java script:', ''), $value);
1984 $value = preg_replace('/javascript:/i', 'java script:', $value);
1985 return str_replace(array_keys($xss_cleanup), array_values($xss_cleanup), $value);
1988 function securexsskey($value, $die=true){
1989 global $sugar_config;
1991 preg_match("/[\'\"\<\>]/", $value, $matches);
1992 if(!empty($matches)){
1994 die("Bad data passed in; <a href=\"{$sugar_config['site_url']}\">Return to Home</a>");
1996 unset($_REQUEST[$value]);
1997 unset($_POST[$value]);
1998 unset($_GET[$value]);
2003 function preprocess_param($value){
2004 if(is_string($value)){
2005 if(get_magic_quotes_gpc() == 1){
2006 $value = stripslashes($value);
2009 $value = securexss($value);
2018 function set_register_value($category, $name, $value){
2019 return sugar_cache_put("{$category}:{$name}", $value);
2022 function get_register_value($category,$name){
2023 return sugar_cache_retrieve("{$category}:{$name}");
2026 function clear_register_value($category,$name){
2027 return sugar_cache_clear("{$category}:{$name}");
2029 // this function cleans id's when being imported
2030 function convert_id($string)
2032 return preg_replace_callback( '|[^A-Za-z0-9\-]|',
2034 // single quotes are essential here,
2035 // or alternative escape all $ as \$
2037 'return ord($matches[0]);'
2042 * @deprecated use SugarTheme::getImage()
2044 function get_image($image,$other_attributes,$width="",$height="")
2046 return SugarThemeRegistry::current()->getImage(basename($image),
2048 empty($width) ? null : $width,
2049 empty($height) ? null : $height
2053 * @deprecated use SugarTheme::getImageURL()
2055 function getImagePath($image_name)
2057 return SugarThemeRegistry::current()->getImageURL($image_name);
2060 function getWebPath($relative_path){
2061 //if it has a :// then it isn't a relative path
2062 if(substr_count($relative_path, '://') > 0) return $relative_path;
2063 if(defined('TEMPLATE_URL'))$relative_path = SugarTemplateUtilities::getWebPath($relative_path);
2064 return $relative_path;
2067 function getJSPath($relative_path, $additional_attrs=''){
2068 if(defined('TEMPLATE_URL'))$relative_path = SugarTemplateUtilities::getWebPath($relative_path);
2069 if(empty($GLOBALS['sugar_config']['js_custom_version']))$GLOBALS['sugar_config']['js_custom_version'] = 1;
2070 $js_version_key = isset($GLOBALS['js_version_key'])?$GLOBALS['js_version_key']:'';
2071 $path = $relative_path . '?s=' . $js_version_key . '&c=' . $GLOBALS['sugar_config']['js_custom_version'] ;
2072 if ( inDeveloperMode() ) $path .= '&developerMode='.mt_rand();
2073 if(!empty($additonal_attrs)) $path .= '&' . $additional_attrs;
2077 function getSWFPath($relative_path, $additional_params=''){
2078 $path = $relative_path;
2079 if (!empty($additional_params)){
2080 $path .= '?' . $additional_params;
2082 if (defined('TEMPLATE_URL')){
2083 $path = TEMPLATE_URL . '/' . $path;
2092 function getSQLDate($date_str)
2094 if (preg_match('/^(\d{1,2})-(\d{1,2})-(\d{4})$/',$date_str,$match))
2096 if ( strlen($match[2]) == 1)
2098 $match[2] = "0".$match[2];
2100 if ( strlen($match[1]) == 1)
2102 $match[1] = "0".$match[1];
2104 return "{$match[3]}-{$match[1]}-{$match[2]}";
2106 else if (preg_match('/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/',$date_str,$match))
2108 if ( strlen($match[2]) == 1)
2110 $match[2] = "0".$match[2];
2112 if ( strlen($match[1]) == 1)
2114 $match[1] = "0".$match[1];
2116 return "{$match[3]}-{$match[1]}-{$match[2]}";
2124 function clone_history(&$db, $from_id,$to_id, $to_type)
2129 require_once('include/upload_file.php');
2130 $tables = array('calls'=>'Call', 'meetings'=>'Meeting', 'notes'=>'Note', 'tasks'=>'Task');
2132 $location=array('Email'=>"modules/Emails/Email.php",
2133 'Call'=>"modules/Calls/Call.php",
2134 'Meeting'=>"modules/Meetings/Meeting.php",
2135 'Note'=>"modules/Notes/Note.php",
2136 'Tasks'=>"modules/Tasks/Task.php",
2140 foreach($tables as $table=>$bean_class)
2143 if (!class_exists($bean_class))
2145 require_once($location[$bean_class]);
2148 $bProcessingNotes=false;
2149 if ($table=='notes')
2151 $bProcessingNotes=true;
2153 $query = "SELECT id FROM $table WHERE parent_id='$from_id'";
2154 $results = $db->query($query);
2155 while($row = $db->fetchByAssoc($results))
2157 //retrieve existing record.
2158 $bean= new $bean_class();
2159 $bean->retrieve($row['id']);
2160 //process for new instance.
2161 if ($bProcessingNotes)
2163 $old_note_id=$row['id'];
2164 $old_filename=$bean->filename;
2167 $bean->parent_id=$to_id;
2168 $bean->parent_type=$to_type;
2169 if ($to_type=='Contacts' and in_array('contact_id',$bean->column_fields))
2171 $bean->contact_id=$to_id;
2173 $bean->update_date_modified = false;
2174 $bean->update_modified_by = false;
2175 if(isset($bean->date_modified))
2176 $bean->date_modified = $timedate->to_db($bean->date_modified);
2177 if(isset($bean->date_entered))
2178 $bean->date_entered = $timedate->to_db($bean->date_entered);
2180 $new_id=$bean->save();
2182 //duplicate the file now. for notes.
2183 if ($bProcessingNotes && !empty($old_filename))
2185 UploadFile::duplicate_file($old_note_id,$new_id,$old_filename);
2187 //reset the values needed for attachment duplication.
2194 function values_to_keys($array)
2196 $new_array = array();
2197 if(!is_array($array))
2201 foreach($array as $arr){
2202 $new_array[$arr] = $arr;
2207 function clone_relationship(&$db, $tables = array(), $from_column, $from_id, $to_id)
2209 foreach($tables as $table)
2212 if ($table == 'emails_beans') {
2213 $query = "SELECT * FROM $table WHERE $from_column='$from_id' and bean_module='Leads'";
2215 $query = "SELECT * FROM $table WHERE $from_column='$from_id'";
2217 $results = $db->query($query);
2218 while($row = $db->fetchByAssoc($results))
2220 $query = "INSERT INTO $table ";
2223 $row[$from_column] = $to_id;
2224 $row['id'] = create_guid();
2225 if ($table=='emails_beans') {
2226 $row['bean_module'] =='Contacts';
2229 foreach($row as $name=>$value)
2235 $values .= "'$value'";
2238 $names .= ', '. $name;
2239 $values .= ", '$value'";
2242 $query .= "($names) VALUES ($values)";
2248 function get_unlinked_email_query($type, $bean) {
2249 global $current_user;
2251 $return_array['select']='SELECT emails.id ';
2252 $return_array['from']='FROM emails ';
2253 $return_array['where']="";
2254 $return_array['join'] = " JOIN (select DISTINCT email_id from emails_email_addr_rel eear
2256 join email_addr_bean_rel eabr on eabr.bean_id ='$bean->id' and eabr.bean_module = '$bean->module_dir' and
2257 eabr.email_address_id = eear.email_address_id and eabr.deleted=0
2258 where eear.deleted=0 and eear.email_id not in
2259 (select eb.email_id from emails_beans eb where eb.bean_module ='$bean->module_dir' and eb.bean_id = '$bean->id')
2260 ) derivedemails on derivedemails.email_id = emails.id";
2261 $return_array['join_tables'][0] = '';
2263 if (isset($type) and !empty($type['return_as_array'])) {
2264 return $return_array;
2267 return $return_array['select'] . $return_array['from'] . $return_array['where'] . $return_array['join'] ;
2271 * Check to see if the number is empty or non-zero
2275 function number_empty($value)
2277 return empty($value) && $value != '0';
2280 function get_bean_select_array($add_blank=true, $bean_name, $display_columns, $where='', $order_by='', $blank_is_none=false)
2283 require_once($beanFiles[$bean_name]);
2284 $focus = new $bean_name();
2285 $user_array = array();
2287 $key = ($bean_name == 'EmailTemplate') ? $bean_name : $bean_name . $display_columns. $where . $order_by;
2288 $user_array = get_register_value('select_array', $key );
2292 $db = DBManagerFactory::getInstance();
2293 $temp_result = Array();
2294 $query = "SELECT {$focus->table_name}.id, {$display_columns} as display from {$focus->table_name} ";
2298 $query .= $where." AND ";
2301 $query .= " {$focus->table_name}.deleted=0";
2303 if ( $order_by != '')
2305 $query .= " order by {$focus->table_name}.{$order_by}";
2308 $GLOBALS['log']->debug("get_user_array query: $query");
2309 $result = $db->query($query, true, "Error filling in user array: ");
2311 if ($add_blank==true){
2312 // Add in a blank row
2313 if($blank_is_none == true) { // set 'blank row' to "--None--"
2314 global $app_strings;
2315 $temp_result[''] = $app_strings['LBL_NONE'];
2317 $temp_result[''] = '';
2321 // Get the id and the name.
2322 while($row = $db->fetchByAssoc($result))
2324 $temp_result[$row['id']] = $row['display'];
2327 $user_array = $temp_result;
2328 set_register_value('select_array', $key ,$temp_result);
2337 * @param unknown_type $listArray
2339 // function parse_list_modules
2340 // searches a list for items in a user's allowed tabs and returns an array that removes unallowed tabs from list
2341 function parse_list_modules(&$listArray)
2343 global $modListHeader;
2344 $returnArray = array();
2346 foreach($listArray as $optionName => $optionVal)
2348 if(array_key_exists($optionName, $modListHeader))
2350 $returnArray[$optionName] = $optionVal;
2353 // special case for projects
2354 if(array_key_exists('Project', $modListHeader))
2356 $returnArray['ProjectTask'] = $listArray['ProjectTask'];
2359 $acldenied = ACLController::disabledModuleList($listArray,false);
2360 foreach($acldenied as $denied){
2361 unset($returnArray[$denied]);
2363 asort($returnArray);
2365 return $returnArray;
2368 function display_notice($msg = false){
2369 global $error_notice;
2370 //no error notice - lets just display the error to the user
2371 if(!isset($error_notice)){
2372 echo '<br>'.$msg . '<br>';
2374 $error_notice .= $msg . '<br>';
2378 /* checks if it is a number that atleast has the plus at the beggining
2380 function skype_formatted($number){
2381 //kbrill - BUG #15375
2382 if(isset($_REQUEST['action']) && $_REQUEST['action']=="Popup") {
2385 return substr($number, 0, 1) == '+' || substr($number, 0, 2) == '00' || substr($number, 0, 3) == '011';
2387 // return substr($number, 0, 1) == '+' || substr($number, 0, 2) == '00' || substr($number, 0, 2) == '011';
2390 function format_skype($number) {
2391 return preg_replace('/[^\+0-9]/','',$number);
2394 function insert_charset_header() {
2395 header('Content-Type: text/html; charset=UTF-8');
2398 function getCurrentURL()
2401 if(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on')
2406 $href.= "//".$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME'].'?'.$_SERVER['QUERY_STRING'];
2410 function javascript_escape($str) {
2413 for($i = 0; $i < strlen($str); $i++) {
2415 if(ord(substr($str, $i, 1))==10){
2417 }elseif(ord(substr($str, $i, 1))==13){
2421 $new_str .= $str{$i};
2425 $new_str = str_replace("'", "\\'", $new_str);
2430 function js_escape($str, $keep=true){
2431 $str = html_entity_decode(str_replace("\\", "", $str), ENT_QUOTES);
2434 $str = javascript_escape($str);
2437 $str = str_replace("'", " ", $str);
2438 $str = str_replace('"', " ", $str);
2443 //end function js_escape
2446 function br2nl($str) {
2447 $regex = "#<[^>]+br.+?>#i";
2448 preg_match_all($regex, $str, $matches);
2450 foreach($matches[0] as $match) {
2451 $str = str_replace($match, "<br>", $str);
2454 $brs = array('<br>','<br/>', '<br />');
2455 $str = str_replace("\r\n", "\n", $str); // make from windows-returns, *nix-returns
2456 $str = str_replace("\n\r", "\n", $str); // make from windows-returns, *nix-returns
2457 $str = str_replace("\r", "\n", $str); // make from windows-returns, *nix-returns
2458 $str = str_ireplace($brs, "\n", $str); // to retrieve it
2464 * Private helper function for displaying the contents of a given variable.
2465 * This function is only intended to be used for SugarCRM internal development.
2466 * The ppd stands for Pre Print Die.
2468 function _ppd($mixed)
2474 * Private helper function for displaying the contents of a given variable in
2475 * the Logger. This function is only intended to be used for SugarCRM internal
2476 * development. The pp stands for Pre Print.
2477 * @param $mixed var to print_r()
2478 * @param $die boolean end script flow
2479 * @param $displayStackTrace also show stack trace
2481 function _ppl($mixed, $die=false, $displayStackTrace=false, $loglevel="fatal") {
2482 if(!isset($GLOBALS['log']) || empty($GLOBALS['log'])) {
2484 $GLOBALS['log'] = LoggerManager :: getLogger('SugarCRM');
2488 $mix = print_r($mixed, true); // send print_r() output to $mix
2489 $stack = debug_backtrace();
2491 $GLOBALS['log']->$loglevel('------------------------------ _ppLogger() output start -----------------------------');
2492 $GLOBALS['log']->$loglevel($mix);
2493 if($displayStackTrace) {
2494 foreach($stack as $position) {
2495 $GLOBALS['log']->$loglevel($position['file']."({$position['line']})");
2499 $GLOBALS['log']->$loglevel('------------------------------ _ppLogger() output end -----------------------------');
2500 $GLOBALS['log']->$loglevel('------------------------------ _ppLogger() file: '.$stack[0]['file'].' line#: '.$stack[0]['line'].'-----------------------------');
2508 * private helper function to quickly show the major, direct, field attributes of a given bean.
2509 * The ppf stands for Pre[formatted] Print Focus [object]
2510 * @param object bean The focus bean
2512 function _ppf($bean, $die=false) {
2518 * Private helper function for displaying the contents of a given variable.
2519 * This function is only intended to be used for SugarCRM internal development.
2520 * The pp stands for Pre Print.
2522 function _pp($mixed)
2527 * Private helper function for displaying the contents of a given variable.
2528 * This function is only intended to be used for SugarCRM internal development.
2529 * The pp stands for Pre Print.
2531 function _pstack_trace($mixed=NULL)
2536 * Private helper function for displaying the contents of a given variable.
2537 * This function is only intended to be used for SugarCRM internal development.
2538 * The pp stands for Pre Print Trace.
2540 function _ppt($mixed, $textOnly=false)
2545 * Private helper function for displaying the contents of a given variable.
2546 * This function is only intended to be used for SugarCRM internal development.
2547 * The pp stands for Pre Print Trace Die.
2549 function _pptd($mixed)
2554 * Private helper function for decoding javascript UTF8
2555 * This function is only intended to be used for SugarCRM internal development.
2557 function decodeJavascriptUTF8($str) {
2561 * Will check if a given PHP version string is supported (tested on this ver),
2562 * unsupported (results unknown), or invalid (something will break on this
2563 * ver). Do not pass in any pararameter to default to a check against the
2564 * current environment's PHP version.
2566 * @return 1 implies supported, 0 implies unsupported, -1 implies invalid
2568 function check_php_version($sys_php_version = '') {
2569 $sys_php_version = empty($sys_php_version) ? constant('PHP_VERSION') : $sys_php_version;
2570 // versions below $min_considered_php_version considered invalid by default,
2571 // versions equal to or above this ver will be considered depending
2572 // on the rules that follow
2573 $min_considered_php_version = '5.2.1';
2575 // only the supported versions,
2576 // should be mutually exclusive with $invalid_php_versions
2577 $supported_php_versions = array (
2578 '5.2.1', '5.2.2', '5.2.3', '5.2.4', '5.2.5', '5.2.6', '5.2.8', '5.3.0'
2580 //Find out what Database the system is using.
2581 global $sugar_config;
2583 if (isset($_REQUEST['setup_db_type'])) {
2584 $dbType = $_REQUEST['setup_db_type'];
2585 } else if (isset ($sugar_config['dbconfig']) && isset ($sugar_config['dbconfig']['db_type'])) {
2586 $dbType = $sugar_config['dbconfig']['db_type'];
2589 // invalid versions above the $min_considered_php_version,
2590 // should be mutually exclusive with $supported_php_versions
2592 // SugarCRM prohibits install on PHP 5.2.7 on all platforms
2593 $invalid_php_versions = array('5.2.7');
2595 // default unsupported
2598 // versions below $min_considered_php_version are invalid
2599 if(1 == version_compare($sys_php_version, $min_considered_php_version, '<')) {
2603 // supported version check overrides default unsupported
2604 foreach($supported_php_versions as $ver) {
2605 if(1 == version_compare($sys_php_version, $ver, 'eq') || strpos($sys_php_version,$ver) !== false) {
2611 // invalid version check overrides default unsupported
2612 foreach($invalid_php_versions as $ver) {
2613 if(1 == version_compare($sys_php_version, $ver, 'eq') && strpos($sys_php_version,$ver) !== false) {
2619 //allow a redhat distro to install, regardless of version. We are assuming the redhat naming convention is followed
2620 //and the php version contains 'rh' characters
2621 if(strpos($sys_php_version, 'rh') !== false) {
2629 * Will check if a given IIS version string is supported (tested on this ver),
2630 * unsupported (results unknown), or invalid (something will break on this
2633 * @return 1 implies supported, 0 implies unsupported, -1 implies invalid
2635 function check_iis_version($sys_iis_version = '') {
2637 $server_software = $_SERVER["SERVER_SOFTWARE"];
2639 if(strpos($server_software,'Microsoft-IIS') !== false && preg_match_all("/^.*\/(\d+\.?\d*)$/", $server_software, $out))
2640 $iis_version = $out[1][0];
2642 $sys_iis_version = empty($sys_iis_version) ? $iis_version : $sys_iis_version;
2644 // versions below $min_considered_iis_version considered invalid by default,
2645 // versions equal to or above this ver will be considered depending
2646 // on the rules that follow
2647 $min_considered_iis_version = '6.0';
2649 // only the supported versions,
2650 // should be mutually exclusive with $invalid_iis_versions
2651 $supported_iis_versions = array ('6.0', '7.0',);
2652 $unsupported_iis_versions = array();
2653 $invalid_iis_versions = array('5.0',);
2655 // default unsupported
2658 // versions below $min_considered_iis_version are invalid
2659 if(1 == version_compare($sys_iis_version, $min_considered_iis_version, '<')) {
2663 // supported version check overrides default unsupported
2664 foreach($supported_iis_versions as $ver) {
2665 if(1 == version_compare($sys_iis_version, $ver, 'eq') || strpos($sys_iis_version,$ver) !== false) {
2671 // unsupported version check overrides default unsupported
2672 foreach($unsupported_iis_versions as $ver) {
2673 if(1 == version_compare($sys_iis_version, $ver, 'eq') && strpos($sys_iis_version,$ver) !== false) {
2679 // invalid version check overrides default unsupported
2680 foreach($invalid_iis_versions as $ver) {
2681 if(1 == version_compare($sys_iis_version, $ver, 'eq') && strpos($sys_iis_version,$ver) !== false) {
2690 function pre_login_check(){
2691 global $action, $login_error;
2692 if(!empty($action)&& $action == 'Login'){
2694 if(!empty($login_error)){
2695 $login_error = htmlentities($login_error);
2696 $login_error = str_replace(array("<pre>","</pre>","\r\n", "\n"), "<br>", $login_error);
2697 $_SESSION['login_error'] = $login_error;
2699 function set_focus() {}
2700 if(document.getElementById("post_error")) {
2701 document.getElementById("post_error").innerHTML="'. $login_error. '";
2702 document.getElementById("cant_login").value=1;
2703 document.getElementById("login_button").disabled = true;
2704 document.getElementById("user_name").disabled = true;
2705 //document.getElementById("user_password").disabled = true;
2714 function sugar_cleanup($exit = false) {
2715 static $called = false;
2718 set_include_path(realpath(dirname(__FILE__) . '/..') . PATH_SEPARATOR . get_include_path());
2719 chdir(realpath(dirname(__FILE__) . '/..'));
2720 global $sugar_config;
2721 require_once('include/utils/LogicHook.php');
2722 LogicHook::initialize();
2723 $GLOBALS['logic_hook']->call_custom_logic('', 'server_round_trip');
2725 //added this check to avoid errors during install.
2726 if (empty($sugar_config['dbconfig'])) {
2727 if ($exit) exit; else return;
2730 if (!class_exists('Tracker', true)) {
2731 require_once 'modules/Trackers/Tracker.php';
2734 // Now write the cached tracker_queries
2735 if(!empty($GLOBALS['savePreferencesToDB']) && $GLOBALS['savePreferencesToDB']) {
2736 if ( isset($GLOBALS['current_user']) && $GLOBALS['current_user'] instanceOf User )
2737 $GLOBALS['current_user']->savePreferencesToDB();
2740 //check to see if this is not an `ajax call AND the user preference error flag is set
2742 (isset($_SESSION['USER_PREFRENCE_ERRORS']) && $_SESSION['USER_PREFRENCE_ERRORS'])
2743 && ($_REQUEST['action']!='modulelistmenu' && $_REQUEST['action']!='DynamicAction')
2744 && (empty($_REQUEST['to_pdf']) || !$_REQUEST['to_pdf'] )
2745 && (empty($_REQUEST['sugar_body_only']) || !$_REQUEST['sugar_body_only'] )
2748 global $app_strings;
2749 //this is not an ajax call and the user preference error flag is set, so reset the flag and print js to flash message
2750 $err_mess = $app_strings['ERROR_USER_PREFS'];
2751 $_SESSION['USER_PREFRENCE_ERRORS'] = false;
2754 ajaxStatus.flashStatus('$err_mess',7000);
2760 if(class_exists('DBManagerFactory')) {
2761 $db = DBManagerFactory::getInstance();
2769 register_shutdown_function('sugar_cleanup');
2773 check_logic_hook - checks to see if your custom logic is in the logic file
2774 if not, it will add it. If the file isn't built yet, it will create the file
2777 function check_logic_hook_file($module_name, $event, $action_array){
2778 require_once('include/utils/logic_utils.php');
2781 if(file_exists("custom/modules/$module_name/logic_hooks.php")){
2783 $hook_array = get_hook_array($module_name);
2785 if(check_existing_element($hook_array, $event, $action_array)==true){
2786 //the hook at hand is present, so do nothing
2791 if(!empty($hook_array[$event]))
2793 $logic_count = count($hook_array[$event]);
2796 if($action_array[0]==""){
2797 $action_array[0] = $logic_count + 1;
2799 $hook_array[$event][] = $action_array;
2802 //end if the file exists already
2805 if($action_array[0]==""){
2806 $action_array[0] = 1;
2808 $hook_array = array();
2809 $hook_array[$event][] = $action_array;
2810 //end if else file exists already
2812 if($add_logic == true){
2814 //reorder array by element[0]
2815 //$hook_array = reorder_array($hook_array, $event);
2816 //!!!Finish this above TODO
2818 $new_contents = replace_or_add_logic_type($hook_array);
2819 write_logic_file($module_name, $new_contents);
2821 //end if add_element is true
2824 //end function check_logic_hook_file
2827 function remove_logic_hook($module_name, $event, $action_array) {
2828 require_once('include/utils/logic_utils.php');
2831 if(file_exists("custom/modules/".$module_name."/logic_hooks.php")){
2832 // The file exists, let's make sure the hook is there
2833 $hook_array = get_hook_array($module_name);
2835 if(check_existing_element($hook_array, $event, $action_array)==true){
2836 // The hook is there, time to take it out.
2838 foreach ( $hook_array[$event] as $i => $hook ) {
2839 // We don't do a full comparison below just in case the filename changes
2840 if ( $hook[0] == $action_array[0]
2841 && $hook[1] == $action_array[1]
2842 && $hook[3] == $action_array[3]
2843 && $hook[4] == $action_array[4] ) {
2844 unset($hook_array[$event][$i]);
2848 $new_contents = replace_or_add_logic_type($hook_array);
2849 write_logic_file($module_name, $new_contents);
2855 function display_stack_trace($textOnly=false){
2857 $stack = debug_backtrace();
2859 echo "\n\n display_stack_trace caller, file: " . $stack[0]['file']. ' line#: ' .$stack[0]['line'];
2867 foreach($stack as $item) {
2873 if(isset($item['file']))
2874 $file = $item['file'];
2875 if(isset($item['class']))
2876 $class = $item['class'];
2877 if(isset($item['line']))
2878 $line = $item['line'];
2879 if(isset($item['function']))
2880 $function = $item['function'];
2884 $out .= '<font color="black"><b>';
2890 $out .= '</b></font><font color="blue">';
2893 $out .= "[L:{$line}]";
2896 $out .= '</font><font color="red">';
2899 $out .= "({$class}:{$function})";
2902 $out .= '</font><br>';
2914 function StackTraceErrorHandler($errno, $errstr, $errfile,$errline, $errcontext) {
2915 $error_msg = " $errstr occured in <b>$errfile</b> on line $errline [" . date("Y-m-d H:i:s") . ']';
2916 $halt_script = true;
2918 case 2048: return; //depricated we have lots of these ignore them
2921 if ( error_reporting() & E_NOTICE ) {
2922 $halt_script = false;
2928 case E_USER_WARNING:
2929 case E_COMPILE_WARNING:
2930 case E_CORE_WARNING:
2933 $halt_script = false;
2938 case E_COMPILE_ERROR:
2942 $type = "Fatal Error";
2947 $type = "Parse Error";
2951 //don't know what it is might not be so bad
2952 $halt_script = false;
2953 $type = "Unknown Error ($errno)";
2956 $error_msg = '<b>'.$type.'</b>:' . $error_msg;
2958 display_stack_trace();
2968 if(isset($sugar_config['stack_trace_errors']) && $sugar_config['stack_trace_errors']){
2970 set_error_handler('StackTraceErrorHandler');
2972 function get_sub_cookies($name){
2974 if(isset($_COOKIE[$name])){
2975 $subs = explode('#', $_COOKIE[$name]);
2976 foreach($subs as $cookie){
2977 if(!empty($cookie)){
2978 $cookie = explode('=', $cookie);
2980 $cookies[$cookie[0]] = $cookie[1];
2989 function mark_delete_components($sub_object_array, $run_second_level=false, $sub_sub_array=""){
2991 if(!empty($sub_object_array)){
2993 foreach($sub_object_array as $sub_object){
2995 //run_second level is set to true if you need to remove sub-sub components
2996 if($run_second_level==true){
2998 mark_delete_components($sub_object->get_linked_beans($sub_sub_array['rel_field'],$sub_sub_array['rel_module']));
3000 //end if run_second_level is true
3002 $sub_object->mark_deleted($sub_object->id);
3003 //end foreach sub component
3005 //end if this is not empty
3008 //end function mark_delete_components
3012 * For translating the php.ini memory values into bytes. e.g. input value of '8M' will return 8388608.
3014 function return_bytes($val)
3017 $last = strtolower($val{strlen($val)-1});
3021 // The 'G' modifier is available since PHP 5.1.0
3034 * Adds the href HTML tags around any URL in the $string
3036 function url2html($string) {
3038 $return_string = preg_replace('/(\w+:\/\/)(\S+)/', ' <a href="\\1\\2" target="_new" style="font-weight: normal;">\\1\\2</a>', $string);
3039 return $return_string;
3041 // End customization by Julian
3044 * tries to determine whether the Host machine is a Windows machine
3046 function is_windows() {
3047 static $is_windows = null;
3048 if (!isset($is_windows)) {
3049 $is_windows = strtoupper(substr(PHP_OS, 0, 3)) == 'WIN';
3055 * equivalent for windows filesystem for PHP's is_writable()
3056 * @param string file Full path to the file/dir
3057 * @return bool true if writable
3059 function is_writable_windows($file) {
3060 if($file{strlen($file)-1}=='/') {
3061 return is_writable_windows($file.uniqid(mt_rand()).'.tmp');
3064 // the assumption here is that Windows has an inherited permissions scheme
3065 // any file that is a descendant of an unwritable directory will inherit
3066 // that property and will trigger a failure below.
3071 $file = str_replace("/", '\\', $file);
3073 if(file_exists($file)) {
3074 if (!($f = @sugar_fopen($file, 'r+')))
3080 if(!($f = @sugar_fopen($file, 'w')))
3089 * best guesses Timezone based on webserver's TZ settings
3091 function lookupTimezone($userOffset = 0)
3093 return TimeDate::guessTimezone($userOffset);
3096 function convert_module_to_singular($module_array){
3099 foreach($module_array as $key => $value){
3100 if(!empty($beanList[$value])) $module_array[$key] = $beanList[$value];
3102 if($value=="Cases") {
3103 $module_array[$key] = "Case";
3105 if($key=="projecttask"){
3106 $module_array['ProjectTask'] = "Project Task";
3107 unset($module_array[$key]);
3111 return $module_array;
3113 //end function convert_module_to_singular
3117 * Given the bean_name which may be plural or singular return the singular
3118 * bean_name. This is important when you need to include files.
3120 function get_singular_bean_name($bean_name){
3121 global $beanFiles, $beanList;
3122 if(array_key_exists($bean_name, $beanList)){
3123 return $beanList[$bean_name];
3131 * Given the potential module name (singular name, renamed module name)
3132 * Return the real internal module name.
3134 function get_module_from_singular($singular) {
3136 // find the internal module name for a singular name
3137 if (isset($GLOBALS['app_list_strings']['moduleListSingular'])) {
3139 $singular_modules = $GLOBALS['app_list_strings']['moduleListSingular'];
3141 foreach ($singular_modules as $mod_name=>$sin_name) {
3142 if ($singular == $sin_name and $mod_name != $sin_name) {
3148 // find the internal module name for a renamed module
3149 if (isset($GLOBALS['app_list_strings']['moduleList'])) {
3151 $moduleList = $GLOBALS['app_list_strings']['moduleList'];
3153 foreach ($moduleList as $mod_name=>$name) {
3154 if ($singular == $name and $mod_name != $name) {
3160 // if it's not a singular name, nor a renamed name, return the original value
3164 function get_label($label_tag, $temp_module_strings){
3165 global $app_strings;
3166 if(!empty($temp_module_strings[$label_tag])){
3168 $label_name = $temp_module_strings[$label_tag];
3170 if(!empty($app_strings[$label_tag])){
3171 $label_name = $app_strings[$label_tag];
3173 $label_name = $label_tag;
3178 //end function get_label
3182 function search_filter_rel_info(& $focus, $tar_rel_module, $relationship_name){
3184 $rel_list = array();
3186 foreach($focus->relationship_fields as $rel_key => $rel_value){
3187 if($rel_value == $relationship_name){
3188 $temp_bean = get_module_info($tar_rel_module);
3189 // echo $focus->$rel_key;
3190 $temp_bean->retrieve($focus->$rel_key);
3191 if($temp_bean->id!=""){
3193 $rel_list[] = $temp_bean;
3199 foreach($focus->field_defs as $field_name => $field_def){
3200 //Check if the relationship_name matches a "relate" field
3201 if(!empty($field_def['type']) && $field_def['type'] == 'relate'
3202 && !empty($field_def['id_name']) && !empty($focus->field_defs[$field_def['id_name']])
3203 && !empty($focus->field_defs[$field_def['id_name']]['relationship'])
3204 && $focus->field_defs[$field_def['id_name']]['relationship'] == $relationship_name)
3206 $temp_bean = get_module_info($tar_rel_module);
3207 // echo $focus->$field_def['id_name'];
3208 $temp_bean->retrieve($focus->$field_def['id_name']);
3209 if($temp_bean->id!=""){
3211 $rel_list[] = $temp_bean;
3214 //Check if the relationship_name matches a "link" in a relate field
3215 } else if(!empty($rel_value['link']) && !empty($rel_value['id_name']) && $rel_value['link'] == $relationship_name){
3216 $temp_bean = get_module_info($tar_rel_module);
3217 // echo $focus->$rel_value['id_name'];
3218 $temp_bean->retrieve($focus->$rel_value['id_name']);
3219 if($temp_bean->id!=""){
3221 $rel_list[] = $temp_bean;
3227 // special case for unlisted parent-type relationships
3228 if( !empty($focus->parent_type) && $focus->parent_type == $tar_rel_module && !empty($focus->parent_id)) {
3229 $temp_bean = get_module_info($tar_rel_module);
3230 $temp_bean->retrieve($focus->parent_id);
3231 if($temp_bean->id!=""){
3232 $rel_list[] = $temp_bean;
3239 //end function search_filter_rel_info
3242 function get_module_info($module_name){
3246 //Get dictionary and focus data for module
3247 $vardef_name = $beanList[$module_name];
3249 if($vardef_name=="aCase"){
3250 $class_name = "Case";
3252 $class_name = $vardef_name;
3255 if(!file_exists('modules/'. $module_name . '/'.$class_name.'.php')){
3259 include_once('modules/'. $module_name . '/'.$class_name.'.php');
3261 $module_bean = new $vardef_name();
3262 return $module_bean;
3263 //end function get_module_table
3267 * In order to have one place to obtain the proper object name. aCase for example causes issues throughout the application.
3269 * @param string $moduleName
3271 function get_valid_bean_name($module_name){
3274 $vardef_name = $beanList[$module_name];
3275 if($vardef_name=="aCase"){
3276 $bean_name = "Case";
3278 $bean_name = $vardef_name;
3285 function checkAuthUserStatus(){
3292 * This function returns an array of phpinfo() results that can be parsed and
3293 * used to figure out what version we run, what modules are compiled in, etc.
3294 * @param $level int info level constant (1,2,4,8...64);
3295 * @return $returnInfo array array of info about the PHP environment
3296 * @author original by "code at adspeed dot com" Fron php.net
3297 * @author customized for Sugar by Chris N.
3299 function getPhpInfo($level=-1) {
3300 /** Name (constant) Value Description
3301 INFO_GENERAL 1 The configuration line, php.ini location, build date, Web Server, System and more.
3302 INFO_CREDITS 2 PHP Credits. See also phpcredits().
3303 INFO_CONFIGURATION 4 Current Local and Master values for PHP directives. See also ini_get().
3304 INFO_MODULES 8 Loaded modules and their respective settings. See also get_loaded_extensions().
3305 INFO_ENVIRONMENT 16 Environment Variable information that's also available in $_ENV.
3306 INFO_VARIABLES 32 Shows all predefined variables from EGPCS (Environment, GET, POST, Cookie, Server).
3307 INFO_LICENSE 64 PHP License information. See also the license FAQ.
3308 INFO_ALL -1 Shows all of the above. This is the default value.
3312 $phpinfo = ob_get_contents();
3315 $phpinfo = strip_tags($phpinfo,'<h1><h2><th><td>');
3316 $phpinfo = preg_replace('/<th[^>]*>([^<]+)<\/th>/',"<info>\\1</info>",$phpinfo);
3317 $phpinfo = preg_replace('/<td[^>]*>([^<]+)<\/td>/',"<info>\\1</info>",$phpinfo);
3318 $parsedInfo = preg_split('/(<h.?>[^<]+<\/h.>)/', $phpinfo, -1, PREG_SPLIT_DELIM_CAPTURE);
3321 $returnInfo = array();
3323 if(preg_match('/<h1 class\=\"p\">PHP Version ([^<]+)<\/h1>/', $phpinfo, $version)) {
3324 $returnInfo['PHP Version'] = $version[1];
3328 for ($i=1; $i<count($parsedInfo); $i++) {
3329 if (preg_match('/<h.>([^<]+)<\/h.>/', $parsedInfo[$i], $match)) {
3330 $vName = trim($match[1]);
3331 $parsedInfo2 = explode("\n",$parsedInfo[$i+1]);
3333 foreach ($parsedInfo2 AS $vOne) {
3334 $vPat = '<info>([^<]+)<\/info>';
3335 $vPat3 = "/$vPat\s*$vPat\s*$vPat/";
3336 $vPat2 = "/$vPat\s*$vPat/";
3338 if (preg_match($vPat3,$vOne,$match)) { // 3cols
3339 $returnInfo[$vName][trim($match[1])] = array(trim($match[2]),trim($match[3]));
3340 } elseif (preg_match($vPat2,$vOne,$match)) { // 2cols
3341 $returnInfo[$vName][trim($match[1])] = trim($match[2]);
3353 * This function will take a string that has tokens like {0}, {1} and will replace
3354 * those tokens with the args provided
3355 * @param $format string to format
3356 * @param $args args to replace
3357 * @return $result a formatted string
3359 function string_format($format, $args){
3363 * If args array has only one argument, and it's empty, so empty single quotes are used '' . That's because
3364 * IN () fails and IN ('') works.
3366 if (count($args) == 1)
3369 $singleArgument = current($args);
3370 if (empty($singleArgument))
3372 return str_replace("{0}", "''", $result);
3377 for($i = 0; $i < count($args); $i++){
3378 $result = str_replace('{'.$i.'}', $args[$i], $result);
3384 * Generate a string for displaying a unique identifier that is composed
3385 * of a system_id and number. This is use to allow us to generate quote
3386 * numbers using a DB auto-increment key from offline clients and still
3387 * have the number be unique (since it is modified by the system_id.
3389 * @param $num of bean
3390 * @param $system_id from system
3391 * @return $result a formatted string
3393 function format_number_display($num, $system_id){
3394 global $sugar_config;
3395 if(isset($num) && !empty($num)){
3396 $num=unformat_number($num);
3397 if(isset($system_id) && $system_id == 1){
3398 return sprintf("%d", $num);
3401 return sprintf("%d-%d", $num, $system_id);
3405 function checkLoginUserStatus(){
3409 * This function will take a number and system_id and format
3410 * @param $url URL containing host to append port
3411 * @param $port the port number - if '' is passed, no change to url
3412 * @return $resulturl the new URL with the port appended to the host
3414 function appendPortToHost($url, $port)
3418 // if no port, don't change the url
3421 $split = explode("/", $url);
3422 //check if it starts with http, in case they didn't include that in url
3423 if(str_begin($url, 'http'))
3425 //third index ($split[2]) will be the host
3426 $split[2] .= ":".$port;
3428 else // otherwise assumed to start with host name
3430 //first index ($split[0]) will be the host
3431 $split[0] .= ":".$port;
3434 $resulturl = implode("/", $split);
3441 * Singleton to return JSON object
3442 * @return JSON object
3444 function getJSONobj() {
3445 static $json = null;
3447 require_once('include/JSON.php');
3448 $json = new JSON(JSON_LOOSE_TYPE);
3453 require_once('include/utils/db_utils.php');
3456 * Set default php.ini settings for entry points
3458 function setPhpIniSettings() {
3460 // Bug 37579 - Comment out force enabling zlib.output_compression, since it can cause problems on certain hosts
3462 if(function_exists('gzclose') && headers_sent() == false) {
3463 ini_set('zlib.output_compression', 1);
3467 //nsingh: breaks zip/unzip functionality. Commenting out 4/23/08
3469 /*if(function_exists('mb_strlen')) {
3470 ini_set('mbstring.func_overload', 7);
3471 ini_set('mbstring.internal_encoding', 'UTF-8');
3475 // http://us3.php.net/manual/en/ref.pcre.php#ini.pcre.backtrack-limit
3476 // starting with 5.2.0, backtrack_limit breaks JSON decoding
3477 $backtrack_limit = ini_get('pcre.backtrack_limit');
3478 if(!empty($backtrack_limit)) {
3479 ini_set('pcre.backtrack_limit', '-1');
3483 if(ini_get("mssql.charset")) {
3484 ini_set('mssql.charset', "UTF-8");
3489 * like array_merge() but will handle array elements that are themselves arrays;
3490 * PHP's version just overwrites the element with the new one.
3492 * @internal Note that this function deviates from the internal array_merge()
3493 * functions in that it does does not treat numeric keys differently
3494 * than string keys. Additionally, it deviates from
3495 * array_merge_recursive() by not creating an array when like values
3498 * @param array gimp the array whose values will be overloaded
3499 * @param array dom the array whose values will pwn the gimp's
3500 * @return array beaten gimp
3502 function sugarArrayMerge($gimp, $dom) {
3503 if(is_array($gimp) && is_array($dom)) {
3504 foreach($dom as $domKey => $domVal) {
3505 if(array_key_exists($domKey, $gimp)) {
3506 if(is_array($domVal)) {
3508 foreach ( $domVal as $domArrKey => $domArrVal )
3509 $tempArr[$domArrKey] = $domArrVal;
3510 foreach ( $gimp[$domKey] as $gimpArrKey => $gimpArrVal )
3511 if ( !array_key_exists($gimpArrKey, $tempArr) )
3512 $tempArr[$gimpArrKey] = $gimpArrVal;
3513 $gimp[$domKey] = $tempArr;
3515 $gimp[$domKey] = $domVal;
3518 $gimp[$domKey] = $domVal;
3522 // if the passed value for gimp isn't an array, then return the $dom
3523 elseif(is_array($dom))
3530 * Similiar to sugarArrayMerge except arrays of N depth are merged.
3532 * @param array gimp the array whose values will be overloaded
3533 * @param array dom the array whose values will pwn the gimp's
3534 * @return array beaten gimp
3536 function sugarArrayMergeRecursive($gimp, $dom) {
3537 if(is_array($gimp) && is_array($dom)) {
3538 foreach($dom as $domKey => $domVal) {
3539 if(array_key_exists($domKey, $gimp)) {
3540 if(is_array($domVal) && is_array($gimp[$domKey])) {
3541 $gimp[$domKey] = sugarArrayMergeRecursive($gimp[$domKey], $domVal);
3543 $gimp[$domKey] = $domVal;
3546 $gimp[$domKey] = $domVal;
3550 // if the passed value for gimp isn't an array, then return the $dom
3551 elseif(is_array($dom))
3558 * finds the correctly working versions of PHP-JSON
3559 * @return bool True if NOT found or WRONG version
3561 function returnPhpJsonStatus() {
3562 if(function_exists('json_encode')) {
3563 $phpInfo = getPhpInfo(8);
3564 return version_compare($phpInfo['json']['json version'], '1.1.1', '<');
3566 return true; // not found
3571 * getTrackerSubstring
3573 * Returns a [number]-char or less string for the Tracker to display in the header
3574 * based on the tracker_max_display_length setting in config.php. If not set,
3575 * or invalid length, then defaults to 15 for COM editions, 30 for others.
3577 * @param string name field for a given Object
3578 * @return string [number]-char formatted string if length of string exceeds the max allowed
3580 function getTrackerSubstring($name) {
3581 static $max_tracker_item_length;
3584 $name = html_entity_decode($name, ENT_QUOTES, 'UTF-8');
3585 $strlen = function_exists('mb_strlen') ? mb_strlen($name) : strlen($name);
3587 global $sugar_config;
3589 if(!isset($max_tracker_item_length)) {
3590 if(isset($sugar_config['tracker_max_display_length'])) {
3591 $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;
3593 $max_tracker_item_length = 15;
3597 if($strlen > $max_tracker_item_length) {
3598 $chopped = function_exists('mb_substr') ? mb_substr($name, 0, $max_tracker_item_length, "UTF-8") : substr($name, 0, $max_tracker_item_length, "UTF-8");
3605 function generate_search_where ($field_list=array(),$values=array(),&$bean,$add_custom_fields=false,$module='') {
3606 $where_clauses= array();
3608 $table_name=$bean->object_name;
3609 foreach ($field_list[$module] as $field=>$parms) {
3610 if(isset($values[$field]) && $values[$field] != "") {
3612 if (!empty($parms['operator'])) {
3613 $operator=$parms['operator'];
3615 if (is_array($values[$field])) {
3618 foreach ($values[$field] as $key => $val) {
3619 if ($val != ' ' and $val != '') {
3620 if (!empty($field_value)) {
3623 $field_value .= "'".$GLOBALS['db']->quote($val)."'";
3627 $field_value=$GLOBALS['db']->quote($values[$field]);
3629 //set db_fields array.
3630 if (!isset($parms['db_field']) ) {
3631 $parms['db_field'] = array($field);
3633 if (isset($parms['my_items']) and $parms['my_items'] == true) {
3634 global $current_user;
3635 $field_value = $GLOBALS['db']->quote($current_user->id);
3641 if ($field_value != '') {
3643 foreach ($parms['db_field'] as $db_field) {
3644 if (strstr($db_field,'.')===false) {
3645 $db_field=$bean->table_name.".".$db_field;
3647 if ($GLOBALS['db']->dbType=='oci8' && isset($parms['query_type']) && $parms['query_type']=='case_insensitive') {
3648 $db_field='upper('.$db_field.")";
3649 $field_value=strtoupper($field_value);
3653 if (!empty($where)) {
3656 switch (strtolower($operator)) {
3658 $where .= $db_field . " like '".$field_value.$like_char."'";
3661 $where .= $db_field . " in (".$field_value.')';
3664 $where .= $db_field . " = '".$field_value ."'";
3669 if (!empty($where)) {
3671 array_push($where_clauses, '( '.$where.' )');
3673 array_push($where_clauses, $where);
3678 if ($add_custom_fields) {
3679 require_once('modules/DynamicFields/DynamicField.php');
3680 $bean->setupCustomFields($module);
3681 $bean->custom_fields->setWhereClauses($where_clauses);
3683 return $where_clauses;
3686 function add_quotes($str) {
3691 * This function will rebuild the config file
3692 * @param $sugar_config
3693 * @param $sugar_version
3694 * @return bool true if successful
3696 function rebuildConfigFile($sugar_config, $sugar_version) {
3697 // add defaults to missing values of in-memory sugar_config
3698 $sugar_config = sugarArrayMerge(get_sugar_config_defaults(), $sugar_config );
3699 // need to override version with default no matter what
3700 $sugar_config['sugar_version'] = $sugar_version;
3702 ksort( $sugar_config );
3704 if( write_array_to_file( "sugar_config", $sugar_config, "config.php" ) ){
3713 * getJavascriptSiteURL
3714 * This function returns a URL for the client javascript calls to access
3715 * the site. It uses $_SERVER['HTTP_REFERER'] in the event that Proxy servers
3716 * are used to access the site. Thus, the hostname in the URL returned may
3717 * not always match that of $sugar_config['site_url']. Basically, the
3718 * assumption is that however the user accessed the website is how they
3719 * will continue to with subsequent javascript requests. If the variable
3720 * $_SERVER['HTTP_REFERER'] is not found then we default to old algorithm.
3721 * @return $site_url The url used to refer to the website
3723 function getJavascriptSiteURL() {
3724 global $sugar_config;
3725 if(!empty($_SERVER['HTTP_REFERER'])) {
3726 $url = parse_url($_SERVER['HTTP_REFERER']);
3727 $replacement_url = $url['scheme']."://".$url['host'];
3728 if(!empty($url['port']))
3729 $replacement_url .= ':'.$url['port'];
3730 $site_url = preg_replace('/^http[s]?\:\/\/[^\/]+/',$replacement_url,$sugar_config['site_url']);
3732 $site_url = preg_replace('/^http(s)?\:\/\/[^\/]+/',"http$1://".$_SERVER['HTTP_HOST'],$sugar_config['site_url']);
3733 if(!empty($_SERVER['SERVER_PORT']) &&$_SERVER['SERVER_PORT'] == '443') {
3734 $site_url = preg_replace('/^http\:/','https:',$site_url);
3737 $GLOBALS['log']->debug("getJavascriptSiteURL(), site_url=". $site_url);
3741 // works nicely with array_map() -- can be used to wrap single quotes around each element in an array
3742 function add_squotes($str) {
3743 return "'" . $str . "'";
3747 // recursive function to count the number of levels within an array
3748 function array_depth($array, $depth_count=-1, $depth_array=array()){
3750 if (is_array($array)){
3751 foreach ($array as $key => $value){
3752 $depth_array[] = array_depth($value, $depth_count);
3756 return $depth_count;
3758 foreach ($depth_array as $value){
3759 $depth_count = $value > $depth_count ? $value : $depth_count;
3761 return $depth_count;
3765 * Creates a new Group User
3766 * @param string $name Name of Group User
3767 * @return string GUID of new Group User
3769 function createGroupUser($name) {
3772 $group = new User();
3773 $group->user_name = $name;
3774 $group->last_name = $name;
3775 $group->is_group = 1;
3776 $group->deleted = 0;
3777 $group->status = 'Active'; // cn: bug 6711
3778 $group->setPreference('timezone', TimeDate::userTimezone());
3785 * Helper function to locate an icon file given only a name
3786 * Searches through the various paths for the file
3787 * @param string iconFileName The filename of the icon
3788 * @return string Relative pathname of the located icon, or '' if not found
3791 function _getIcon($iconFileName)
3793 $iconPath = SugarThemeRegistry::current()->getImageURL("icon_{$iconFileName}.gif");
3794 //First try un-ucfirst-ing the icon name
3795 if ( empty($iconPath) )
3796 $iconPath = SugarThemeRegistry::current()->getImageURL(
3797 "icon_" . strtolower(substr($iconFileName,0,1)).substr($iconFileName,1) . ".gif");
3798 //Next try removing the icon prefix
3799 if ( empty($iconPath) )
3800 $iconPath = SugarThemeRegistry::current()->getImageURL("{$iconFileName}.gif");
3805 * Function to grab the correct icon image for Studio
3806 * @param string $iconFileName Name of the icon file
3807 * @param string $altfilename Name of a fallback icon file (displayed if the imagefilename doesn't exist)
3808 * @param string $width Width of image
3809 * @param string $height Height of image
3810 * @param string $align Alignment of image
3811 * @return string $string <img> tag with corresponding image
3814 function getStudioIcon($iconFileName='', $altFileName='', $width='48', $height='48', $align='baseline' )
3816 global $app_strings, $theme;
3818 $iconPath = _getIcon($iconFileName);
3819 if(empty($iconPath)){
3820 $iconPath = _getIcon($altFileName);
3821 if (empty($iconPath))
3823 return $app_strings['LBL_NO_IMAGE'];
3826 return '<img border="0" src="'.$iconPath.'" width="'.$width.'" height="'.$height.'" align="'.$align.'">';
3830 * Function to grab the correct icon image for Dashlets Dialog
3831 * @param string $filename Location of the icon file
3832 * @param string $module Name of the module to fall back onto if file does not exist
3833 * @param string $width Width of image
3834 * @param string $height Height of image
3835 * @param string $align Alignment of image
3836 * @return string $string <img> tag with corresponding image
3839 function get_dashlets_dialog_icon($module='', $width='32', $height='32', $align='absmiddle'){
3840 global $app_strings, $theme;
3841 $icon_path = _getIcon($module . "_32");
3842 if (empty($icon_path))
3844 $icon_path = _getIcon($module);
3846 if(empty($icon_path)){
3847 $icon = $app_strings['LBL_NO_IMAGE'];
3850 $icon = '<img border="0" src="'.$icon_path.'" width="'.$width.'" height="'.$height.'" align="'.$align.'">';
3855 // works nicely to change UTF8 strings that are html entities - good for PDF conversions
3856 function html_entity_decode_utf8($string)
3859 // replace numeric entities
3860 //php will have issues with numbers with leading zeros, so do not include them in what we send to code2utf.
3861 $string = preg_replace('~�*([0-9a-f]+);~ei', 'code2utf(hexdec("\\1"))', $string);
3862 $string = preg_replace('~�*([0-9]+);~e', 'code2utf(\\1)', $string);
3863 // replace literal entities
3864 if (!isset($trans_tbl))
3866 $trans_tbl = array();
3867 foreach (get_html_translation_table(HTML_ENTITIES) as $val=>$key)
3868 $trans_tbl[$key] = utf8_encode($val);
3870 return strtr($string, $trans_tbl);
3873 // Returns the utf string corresponding to the unicode value
3874 function code2utf($num)
3876 if ($num < 128) return chr($num);
3877 if ($num < 2048) return chr(($num >> 6) + 192) . chr(($num & 63) + 128);
3878 if ($num < 65536) return chr(($num >> 12) + 224) . chr((($num >> 6) & 63) + 128) . chr(($num & 63) + 128);
3879 if ($num < 2097152) return chr(($num >> 18) + 240) . chr((($num >> 12) & 63) + 128) . chr((($num >> 6) & 63) + 128) . chr(($num & 63) + 128);
3883 function str_split_php4($string, $length = 1) {
3884 $string_length = strlen($string);
3887 if ($length > $string_length) {
3888 // use the string_length as the string is shorter than the length
3889 $length = $string_length;
3891 for ($cursor = 0; $cursor < $string_length; $cursor = $cursor + $length) {
3892 $return[] = substr($string, $cursor, $length);
3897 if (version_compare(phpversion(), '5.0.0', '<')) {
3898 function str_split($string, $length = 1) {
3899 return str_split_php4($string, $length);
3904 * Invoked when connected to mssql. checks if we have freetds version of mssql library.
3905 * the response is put into a global variable.
3907 function is_freetds() {
3910 if (isset($GLOBALS['mssql_library_version'])) {
3911 if ($GLOBALS['mssql_library_version']=='freetds') {
3919 $info=ob_get_contents();
3922 if (strpos($info,'FreeTDS') !== false) {
3923 $GLOBALS['mssql_library_version']='freetds';
3926 $GLOBALS['mssql_library_version']='regular';
3934 * stripos - Find position of first occurrence of a case-insensitive string
3936 * The function is being defined for systems with PHP version < 5.
3939 if (!function_exists("stripos")){
3940 function stripos($haystack,$needle,$offset=0){
3941 return strpos(strtolower($haystack),strtolower($needle),$offset);
3946 * Chart dashlet helper function that returns the correct CSS file, dependent on the current theme.
3948 * @todo this won't work completely right until we impliment css compression and combination
3949 * for now, we'll just include the last css file found.
3951 * @return chart.css file to use
3953 function chartStyle()
3955 return SugarThemeRegistry::current()->getCSSURL('chart.css');
3959 * Chart dashlet helper functions that returns the correct XML color file for charts,
3960 * dependent on the current theme.
3962 * @return sugarColors.xml to use
3964 function chartColors()
3966 if (SugarThemeRegistry::current()->getCSSURL('sugarColors.xml')=='')
3967 return SugarThemeRegistry::current()->getImageURL('sugarColors.xml');
3968 return SugarThemeRegistry::current()->getCSSURL('sugarColors.xml');
3970 /* End Chart Dashlet helper functions */
3973 * This function is designed to set up the php enviroment
3974 * for AJAX requests.
3977 function ajaxInit() {
3978 ini_set('display_errors', 'false');
3982 * Returns an absolute path from the given path, determining if it is relative or absolute
3984 * @param string $path
3987 function getAbsolutePath(
3989 $currentServer = false
3992 $path = trim($path);
3994 // try to match absolute paths like \\server\share, /directory or c:\
3995 if ( ( substr($path,0,2) == '\\\\' )
3996 || ( $path[0] == '/' )
3997 || preg_match('/^[A-z]:/i',$path)
4001 return getcwd().'/'.$path;
4005 * Returns the bean object of the given module
4007 * @deprecated use SugarModule::loadBean() instead
4008 * @param string $module
4015 return SugarModule::get($module)->loadBean();
4020 * Returns true if the application is being accessed on a touch screen interface ( like an iPad )
4022 function isTouchScreen()
4024 $ua = empty($_SERVER['HTTP_USER_AGENT']) ? "undefined" : strtolower($_SERVER['HTTP_USER_AGENT']);
4026 // first check if we have forced use of the touch enhanced interface
4027 if ( isset($_COOKIE['touchscreen']) && $_COOKIE['touchscreen'] == '1' ) {
4031 // next check if we should use the touch interface with our device
4032 if ( strpos($ua, 'ipad') !== false ) {
4040 * Returns the shortcut keys to access the shortcut links. Shortcut
4041 * keys vary depending on browser versions and operating systems.
4042 * @return String value of the shortcut keys
4044 function get_alt_hot_key() {
4046 if ( isset($_SERVER['HTTP_USER_AGENT']) )
4047 $ua = strtolower($_SERVER['HTTP_USER_AGENT']);
4048 $isMac = strpos($ua, 'mac') !== false;
4049 $isLinux = strpos($ua, 'linux') !== false;
4051 if(!$isMac && !$isLinux && strpos($ua, 'mozilla') !== false) {
4052 if(preg_match('/firefox\/(\d)?\./', $ua, $matches)) {
4053 return $matches[1] < 2 ? 'Alt+' : 'Alt+Shift+';
4056 return $isMac ? 'Ctrl+' : 'Alt+';
4059 function can_start_session(){
4060 if(!empty($_GET['PHPSESSID'])) {
4063 $session_id = session_id();
4064 return empty($session_id) ? true : false;
4067 function load_link_class($properties){
4069 if(!empty($properties['link_class']) && !empty($properties['link_file'])){
4070 require_once($properties['link_file']);
4071 $class = $properties['link_class'];
4077 function inDeveloperMode()
4079 return isset($GLOBALS['sugar_config']['developerMode']) && $GLOBALS['sugar_config']['developerMode'];
4083 * Filter the protocol list for inbound email accounts.
4085 * @param array $protocol
4087 function filterInboundEmailPopSelection($protocol)
4089 if ( !isset($GLOBALS['sugar_config']['allow_pop_inbound']) || ! $GLOBALS['sugar_config']['allow_pop_inbound'] )
4091 if( isset($protocol['pop3']) )
4092 unset($protocol['pop3']);
4095 $protocol['pop3'] = 'POP3';
4101 * The function is used because currently we are not supporting mbstring.func_overload
4102 * 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.
4103 * 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.
4104 * @returns the substred strings.
4106 function sugar_substr($string, $length, $charset='UTF-8') {
4107 if($GLOBALS['db']->dbType == 'mssql' && empty($GLOBALS['db']->isFreeTDS)) {
4108 if(strlen($string) > $length) {
4109 $string = trim(substr(trim($string),0,$length));
4113 if(mb_strlen($string,$charset) > $length) {
4114 $string = trim(mb_substr(trim($string),0,$length,$charset));
4121 * The function is used because on FastCGI enviroment, the ucfirst(Chinese Characters) will produce bad charcters.
4122 * This will work even without setting the mbstring.*encoding
4124 function sugar_ucfirst($string, $charset='UTF-8') {
4125 return mb_strtoupper(mb_substr($string, 0, 1, $charset), $charset) . mb_substr($string, 1, mb_strlen($string), $charset);
4132 function unencodeMultienum($string) {
4133 if (is_array($string))
4137 if (substr($string, 0 ,1) == "^" && substr($string, -1) == "^") {
4138 $string = substr(substr($string, 1), 0, strlen($string) -2);
4141 return explode('^,^', $string);
4144 function encodeMultienumValue($arr) {
4145 if (!is_array($arr))
4151 $string = "^" . implode('^,^', $arr) . "^";
4157 * create_export_query is used for export and massupdate
4158 * We haven't handle the these fields: $field['type'] == 'relate' && isset($field['link']
4159 * This function will correct the where clause and output necessary join condition for them
4160 * @param $module: the module name
4161 * @param $searchFields: searchFields which is got after $searchForm->populateFromArray()
4162 * @param $where: where clauses
4163 * @return $ret_array['where']: corrected where clause
4164 * @return $ret_array['join']: extra join condition
4166 function create_export_query_relate_link_patch($module, $searchFields, $where){
4167 if(file_exists('modules/'.$module.'/SearchForm.html')){
4168 $ret_array['where'] = $where;
4171 $seed = loadBean($module);
4172 foreach($seed->field_defs as $name=>$field)
4175 if( $field['type'] == 'relate' && isset($field['link']) && !empty($searchFields[$name]['value']) ){
4176 $seed->load_relationship($field['link']);
4178 if(empty($join_type))
4180 $params['join_type'] = ' LEFT JOIN ';
4184 $params['join_type'] = $join_type;
4186 if(isset($data['join_name']))
4188 $params['join_table_alias'] = $field['join_name'];
4192 $params['join_table_alias'] = 'join_'.$field['name'];
4195 if(isset($data['join_link_name']))
4197 $params['join_table_link_alias'] = $field['join_link_name'];
4201 $params['join_table_link_alias'] = 'join_link_'.$field['name'];
4203 $join = $seed->$field['link']->getJoin($params, true);
4204 $join_table_alias = 'join_'.$field['name'];
4205 if(isset($field['db_concat_fields'])){
4206 $db_field = db_concat($join_table_alias, $field['db_concat_fields']);
4207 $where = preg_replace('/'.$field['name'].'/', $db_field, $where);
4209 $where = preg_replace('/(^|[\s(])' . $field['name'] . '/', '${1}' . $join_table_alias . '.'.$field['rname'], $where);
4213 $ret_array = array('where'=>$where, 'join'=>$join['join']);
4218 * 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.
4219 * @Depends on QuickRepairAndRebuild.php
4220 * @Relate bug 30642 ,23177
4222 function clearAllJsAndJsLangFilesWithoutOutput(){
4223 global $current_language , $mod_strings;
4224 $MBmodStrings = $mod_strings;
4225 $mod_strings = return_module_language ( $current_language, 'Administration' ) ;
4226 include_once ('modules/Administration/QuickRepairAndRebuild.php') ;
4227 $repair = new RepairAndClear();
4228 $repair->module_list = array();
4229 $repair->show_output = false;
4230 $repair->clearJsLangFiles();
4231 $repair->clearJsFiles();
4232 $mod_strings = $MBmodStrings;
4236 * This function will allow you to get a variable value from query string
4238 function getVariableFromQueryString($variable, $string){
4240 $number = preg_match("/{$variable}=([a-zA-Z0-9_-]+)[&]?/", $string, $matches);
4250 * should_hide_iframes
4251 * This is a helper method to determine whether or not to show iframes (My Sites) related
4252 * information in the application.
4254 * @return boolean flag indicating whether or not iframes module should be hidden
4256 function should_hide_iframes() {
4257 //Remove the MySites module
4258 if(file_exists('modules/iFrames/iFrame.php')) {
4259 if(!class_exists("iFrame")) {
4260 require_once('modules/iFrames/iFrame.php');
4268 * Given a version such as 5.5.0RC1 return RC. If we have a version such as: 5.5 then return GA
4270 * @param string $version
4271 * @return string RC, BETA, GA
4273 function getVersionStatus($version){
4274 if(preg_match('/^[\d\.]+?([a-zA-Z]+?)[\d]*?$/si', $version, $matches)) {
4275 return strtoupper($matches[1]);
4282 * Return the numeric portion of a version. For example if passed 5.5.0RC1 then return 5.5. If given
4283 * 5.5.1RC1 then return 5.5.1
4285 * @param string $version
4288 function getMajorMinorVersion($version){
4289 if(preg_match('/^([\d\.]+).*$/si', $version, $matches2)){
4290 $version = $matches2[1];
4291 $arr = explode('.', $version);
4292 if(count($arr) > 2){
4294 $version = substr($version, 0, 3);
4302 * Return string composed of seconds & microseconds of current time, without dots
4305 function sugar_microtime()
4307 $now = explode(' ', microtime());
4308 $unique_id = $now[1].str_replace('.', '', $now[0]);
4313 * Extract urls from a piece of text
4315 * @return array of urls found in $string
4317 function getUrls($string)
4319 $lines = explode("<br>", trim($string));
4321 foreach($lines as $line){
4322 $regex = '/http?\:\/\/[^\" ]+/i';
4323 preg_match_all($regex, $line, $matches);
4324 foreach($matches[0] as $match){
4333 * Sanitize image file from hostile content
4334 * @param string $path Image file
4335 * @param bool $jpeg Accept only JPEGs?
4337 function verify_image_file($path, $jpeg = false)
4339 if(function_exists('imagepng') && function_exists('imagejpeg') && function_exists('imagecreatefromstring')) {
4340 $img = imagecreatefromstring(file_get_contents($path));
4344 $img_size = getimagesize($path);
4345 $filetype = $img_size['mime'];
4346 //if filetype is jpeg or if we are only allowing jpegs, create jpg image
4347 if($filetype == "image/jpeg" || $jpeg) {
4348 if(imagejpeg($img, $path)) {
4351 } elseif ($filetype == "image/png") { // else if the filetype is png, create png
4352 imagealphablending($img, true);
4353 imagesavealpha($img, true);
4354 if(imagepng($img, $path)) {
4361 // check image manually
4362 $fp = fopen($path, "r");
4363 if(!$fp) return false;
4364 $data = fread($fp, 4096);
4366 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",
4368 $GLOBALS['log']->info("Found {$m[0]} in $path, not allowing upload");
4377 * Verify uploaded image
4378 * Verifies that image has proper extension, MIME type and doesn't contain hostile contant
4379 * @param string $path Image path
4380 * @param bool $jpeg_only Accept only JPEGs?
4382 function verify_uploaded_image($path, $jpeg_only = false)
4384 $supportedExtensions = array('jpg' => 'image/jpeg', 'jpeg' => 'image/jpeg');
4386 $supportedExtensions['png'] = 'image/png';
4389 if(!file_exists($path) || !is_file($path)) {
4393 $img_size = getimagesize($path);
4394 $filetype = $img_size['mime'];
4395 $ext = end(explode(".", $path));
4396 if(substr_count('..', $path) > 0 || $ext === $path || !in_array(strtolower($ext), array_keys($supportedExtensions)) ||
4397 !in_array($filetype, array_values($supportedExtensions))) {
4400 return verify_image_file($path, $jpeg_only);
4403 function cmp_beans($a, $b)
4405 global $sugar_web_service_order_by;
4406 //If the order_by field is not valid, return 0;
4407 if (empty($sugar_web_service_order_by) || !isset($a->$sugar_web_service_order_by) || !isset($b->$sugar_web_service_order_by)){
4410 if (is_object($a->$sugar_web_service_order_by) || is_object($b->$sugar_web_service_order_by)
4411 || is_array($a->$sugar_web_service_order_by) || is_array($b->$sugar_web_service_order_by))
4415 if ($a->$sugar_web_service_order_by < $b->$sugar_web_service_order_by)
4423 function order_beans($beans, $field_name)
4425 //Since php 5.2 doesn't include closures, we must use a global to pass the order field to cmp_beans.
4426 global $sugar_web_service_order_by;
4427 $sugar_web_service_order_by = $field_name;
4428 usort($beans, "cmp_beans");
4432 //check to see if custom utils exists
4433 if(file_exists('custom/include/custom_utils.php')){
4434 include_once('custom/include/custom_utils.php');
4437 //check to see if custom utils exists in Extension framework
4438 if(file_exists('custom/application/Ext/Utils/custom_utils.ext.php')) {
4439 include_once('custom/application/Ext/Utils/custom_utils.ext.php');
4442 * @param $input - the input string to sanitize
4443 * @param int $quotes - use quotes
4444 * @param string $charset - the default charset
4445 * @param bool $remove - strip tags or not
4446 * @return string - the sanitized string
4448 function sanitize($input, $quotes = ENT_QUOTES, $charset = 'UTF-8', $remove = false)
4450 return htmlentities($input, $quotes, $charset);