2 /*********************************************************************************
3 * SugarCRM 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/external_cache.php');
46 require_once('include/utils/security_utils.php');
50 function make_sugar_config(&$sugar_config)
52 /* used to convert non-array config.php file to array format */
53 global $admin_export_only;
55 global $calculate_response_time;
56 global $create_default_user;
59 global $dbconfigoption;
60 global $default_action;
61 global $default_charset;
62 global $default_currency_name;
63 global $default_currency_symbol;
64 global $default_currency_iso4217;
65 global $defaultDateFormat;
66 global $default_language;
67 global $default_module;
68 global $default_password;
69 global $default_permission_mode;
70 global $default_theme;
71 global $defaultTimeFormat;
72 global $default_user_is_admin;
73 global $default_user_name;
74 global $disable_export;
75 global $disable_persistent_connections;
76 global $display_email_template_variable_chooser;
77 global $display_inbound_email_buttons;
78 global $history_max_viewed;
82 global $list_max_entries_per_page;
83 global $lock_default_user_name;
84 global $log_memory_usage;
85 global $requireAccounts;
86 global $RSS_CACHE_TIME;
90 global $sugar_version;
93 global $translation_string_prefix;
95 global $upload_badext;
97 global $upload_maxsize;
98 global $import_max_execution_time;
99 global $list_max_entries_per_subpanel;
100 global $passwordsetting;
102 // assumes the following variables must be set:
103 // $dbconfig, $dbconfigoption, $cache_dir, $import_dir, $session_dir, $site_URL, $tmp_dir, $upload_dir
105 $sugar_config = array (
106 'admin_export_only' => empty($admin_export_only) ? false : $admin_export_only,
107 'export_delimiter' => empty($export_delimiter) ? ',' : $export_delimiter,
108 'cache_dir' => empty($cache_dir) ? 'cache/' : $cache_dir,
109 'calculate_response_time' => empty($calculate_response_time) ? true : $calculate_response_time,
110 'create_default_user' => empty($create_default_user) ? false : $create_default_user,
111 '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 'languages' => empty($languages) ? array('en_us' => 'English (US)') : $languages,
153 'list_max_entries_per_page' => empty($list_max_entries_per_page) ? 20 : $list_max_entries_per_page,
154 'list_max_entries_per_subpanel' => empty($list_max_entries_per_subpanel) ? 10 : $list_max_entries_per_subpanel,
155 'lock_default_user_name' => empty($lock_default_user_name) ? false : $lock_default_user_name,
156 'log_memory_usage' => empty($log_memory_usage) ? false : $log_memory_usage,
157 'portal_view' => 'single_user',
158 'resource_management' => array (
159 'special_query_limit' => 50000,
160 'special_query_modules' => array('Reports', 'Export', 'Import', 'Administration', 'Sync'),
161 'default_limit' => 1000,
163 'require_accounts' => empty($requireAccounts) ? true : $requireAccounts,
164 'rss_cache_time' => empty($RSS_CACHE_TIME) ? '10800' : $RSS_CACHE_TIME,
165 'session_dir' => $session_dir, // this must be set!!
166 'site_url' => empty($site_URL) ? $site_url : $site_URL, // this must be set!!
167 'showDetailData' => true, // if true, read-only ACL fields will still appear on EditViews as non-editable
168 'showThemePicker' => true,
169 'sugar_version' => empty($sugar_version) ? 'unknown' : $sugar_version,
170 'time_formats' => empty($timeFormats) ? array (
171 'H:i'=>'23:00', 'h:ia'=>'11:00 pm', 'h:iA'=>'11:00PM',
172 'H.i'=>'23.00', 'h.ia'=>'11.00 pm', 'h.iA'=>'11.00PM' ) : $timeFormats,
173 'tmp_dir' => $tmp_dir, // this must be set!!
174 'translation_string_prefix' => empty($translation_string_prefix) ? false : $translation_string_prefix,
175 'unique_key' => empty($unique_key) ? md5(create_guid()) : $unique_key,
176 'upload_badext' => empty($upload_badext) ? array (
177 'php', 'php3', 'php4', 'php5', 'pl', 'cgi', 'py',
178 'asp', 'cfm', 'js', 'vbs', 'html', 'htm' ) : $upload_badext,
179 'upload_dir' => $upload_dir, // this must be set!!
180 'upload_maxsize' => empty($upload_maxsize) ? 3000000 : $upload_maxsize,
181 'import_max_execution_time' => empty($import_max_execution_time) ? 3600 : $import_max_execution_time,
182 'lock_homepage' => false,
183 'lock_subpanels' => false,
184 'max_dashlets_homepage' => 15,
185 'dashlet_display_row_options' => array('1','3','5','10'),
186 'default_max_tabs' => empty($max_tabs) ? '7' : $max_tabs,
187 'default_subpanel_tabs' => empty($subpanel_tabs) ? true : $subpanel_tabs,
188 'default_subpanel_links' => empty($subpanel_links) ? false : $subpanel_links,
189 'default_swap_last_viewed' => empty($swap_last_viewed) ? false : $swap_last_viewed,
190 'default_swap_shortcuts' => empty($swap_shortcuts) ? false : $swap_shortcuts,
191 'default_navigation_paradigm' => empty($navigation_paradigm) ? 'gm' : $navigation_paradigm,
192 'js_lang_version' => 1,
193 'passwordsetting' => empty($passwordsetting) ? array (
194 'SystemGeneratedPasswordON' => '',
195 'generatepasswordtmpl' => '',
196 'lostpasswordtmpl' => '',
197 'forgotpasswordON' => true,
198 'linkexpiration' => '1',
199 'linkexpirationtime' => '30',
200 'linkexpirationtype' => '1',
201 'systexpiration' => '0',
202 'systexpirationtime' => '',
203 'systexpirationtype' => '0',
204 'systexpirationlogin' => '',
205 ) : $passwordsetting,
210 function get_sugar_config_defaults() {
213 * used for getting base values for array style config.php. used by the
214 * installer and to fill in new entries on upgrades. see also:
218 $sugar_config_defaults = array (
219 'admin_export_only' => false,
220 'export_delimiter' => ',',
221 'cache_dir' => 'cache/',
222 'calculate_response_time' => true,
223 'create_default_user' => false,
224 'date_formats' => array (
225 'Y-m-d' => '2010-12-23', 'm-d-Y' => '12-23-2010', 'd-m-Y' => '23-12-2010',
226 'Y/m/d' => '2010/12/23', 'm/d/Y' => '12/23/2010', 'd/m/Y' => '23/12/2010',
227 'Y.m.d' => '2010.12.23', 'd.m.Y' => '23.12.2010', 'm.d.Y' => '12.23.2010',),
228 'dbconfigoption' => array (
229 'persistent' => true,
232 'seqname_format' => '%s_seq',
235 'default_action' => 'index',
236 'default_charset' => return_session_value_or_default('default_charset',
238 'default_currency_name' => return_session_value_or_default('default_currency_name', 'US Dollar'),
239 'default_currency_symbol' => return_session_value_or_default('default_currency_symbol', '$'),
240 'default_currency_iso4217' => return_session_value_or_default('default_currency_iso4217', 'USD'),
241 'default_currency_significant_digits' => return_session_value_or_default('default_currency_significant_digits', 2),
242 'default_number_grouping_seperator' => return_session_value_or_default('default_number_grouping_seperator', ','),
243 'default_decimal_seperator' => return_session_value_or_default('default_decimal_seperator', '.'),
244 'default_date_format' => 'm/d/Y',
245 'default_export_charset' => 'UTF-8',
246 'default_language' => return_session_value_or_default('default_language',
248 'default_module' => 'Home',
249 'default_password' => '',
250 'default_permissions' => array (
256 'default_theme' => return_session_value_or_default('site_default_theme', 'Sugar5'),
257 'default_time_format' => 'h:ia',
258 'default_user_is_admin' => false,
259 'default_user_name' => '',
260 'disable_export' => false,
261 'disable_persistent_connections' =>
262 return_session_value_or_default('disable_persistent_connections',
264 'display_email_template_variable_chooser' => false,
265 'display_inbound_email_buttons' => false,
266 'dump_slow_queries' => false,
267 'email_default_editor' => 'html',
268 'email_default_client' => 'sugar',
269 'email_default_delete_attachments' => true,
270 'history_max_viewed' => 50,
271 'installer_locked' => true,
272 'import_max_records_per_file' => 100,
273 'languages' => array('en_us' => 'English (US)'),
274 'large_scale_test' => false,
275 'list_max_entries_per_page' => 20,
276 'list_max_entries_per_subpanel' => 10,
277 'lock_default_user_name' => false,
278 'log_memory_usage' => false,
279 'portal_view' => 'single_user',
280 'resource_management' => array (
281 'special_query_limit' => 50000,
282 'special_query_modules' => array('Reports', 'Export', 'Import', 'Administration', 'Sync'),
283 'default_limit' => 1000,
285 'require_accounts' => true,
286 'rss_cache_time' => return_session_value_or_default('rss_cache_time',
288 'save_query' => 'all',
289 'showDetailData' => true, // if true, read-only ACL fields will still appear on EditViews as non-editable
290 'showThemePicker' => true,
291 'slow_query_time_msec' => '100',
293 'time_formats' => array (
294 'H:i'=>'23:00', 'h:ia'=>'11:00pm', 'h:iA'=>'11:00PM',
295 'H.i'=>'23.00', 'h.ia'=>'11.00pm', 'h.iA'=>'11.00PM' ),
296 'tracker_max_display_length' => 15,
297 'translation_string_prefix' =>
298 return_session_value_or_default('translation_string_prefix', false),
299 'upload_badext' => array (
300 'php', 'php3', 'php4', 'php5', 'pl', 'cgi', 'py',
301 'asp', 'cfm', 'js', 'vbs', 'html', 'htm' ),
302 'upload_maxsize' => 3000000,
303 'import_max_execution_time' => 3600,
304 'use_php_code_json' => returnPhpJsonStatus(),
305 'verify_client_ip' => true,
306 'js_custom_version' => '',
307 'js_lang_version' => 1,
308 'default_number_grouping_seperator' => ',',
309 'default_decimal_seperator' => '.',
310 'lock_homepage' => false,
311 'lock_subpanels' => false,
312 'max_dashlets_homepage' => '15',
313 'default_max_tabs' => '7',
314 'dashlet_display_row_options' => array('1','3','5','10'),
315 'default_subpanel_tabs' => true,
316 'default_subpanel_links' => false,
317 'default_swap_last_viewed' => false,
318 'default_swap_shortcuts' => false,
319 'default_navigation_paradigm' => 'gm',
320 'admin_access_control' => false,
321 'use_common_ml_dir' => false,
322 'common_ml_dir' => '',
324 'passwordsetting' => empty($passwordsetting) ? array (
325 'SystemGeneratedPasswordON' => '',
326 'generatepasswordtmpl' => '',
327 'lostpasswordtmpl' => '',
328 'forgotpasswordON' => false,
329 'linkexpiration' => '1',
330 'linkexpirationtime' => '30',
331 'linkexpirationtype' => '1',
332 'systexpiration' => '0',
333 'systexpirationtime' => '',
334 'systexpirationtype' => '0',
335 'systexpirationlogin' => '',
336 ) : $passwordsetting,
337 'use_real_names' => true,
340 if(!is_object($locale)) {
341 $locale = new Localization();
344 $sugar_config_defaults['default_currencies'] = $locale->getDefaultCurrencies();
346 $sugar_config_defaults = sugarArrayMerge($locale->getLocaleConfigDefaults(), $sugar_config_defaults);
347 return( $sugar_config_defaults );
351 * @deprecated use SugarView::getMenu() instead
353 function load_menu($path){
356 if(file_exists($path . 'Menu.php'))
358 require($path . 'Menu.php');
360 if(file_exists('custom/' . $path . 'Ext/Menus/menu.ext.php'))
362 require('custom/' . $path . 'Ext/Menus/menu.ext.php');
364 if(file_exists('custom/application/Ext/Menus/menu.ext.php'))
366 require('custom/application/Ext/Menus/menu.ext.php');
372 * get_notify_template_file
373 * This function will return the location of the email notifications template to use
375 * @return string relative file path to email notifications template file
377 function get_notify_template_file($language){
379 * Order of operation:
380 * 1) custom version of specified language
381 * 2) stock version of specified language
382 * 3) custom version of en_us template
383 * 4) stock en_us template
386 // set $file to the base code template so it's set if none of the conditions pass
387 $file = "include/language/en_us.notify_template.html";
389 if(file_exists("custom/include/language/{$language}.notify_template.html")){
390 $file = "custom/include/language/{$language}.notify_template.html";
392 else if(file_exists("include/language/{$language}.notify_template.html")){
393 $file = "include/language/{$language}.notify_template.html";
395 else if(file_exists("custom/include/language/en_us.notify_template.html")){
396 $file = "custom/include/language/en_us.notify_template.html";
402 function sugar_config_union( $default, $override ){
403 // a little different then array_merge and array_merge_recursive. we want
404 // the second array to override the first array if the same value exists,
405 // otherwise merge the unique keys. it handles arrays of arrays recursively
406 // might be suitable for a generic array_union
407 if( !is_array( $override ) ){
410 foreach( $default as $key => $value ){
411 if( !array_key_exists($key, $override) ){
412 $override[$key] = $value;
414 else if( is_array( $key ) ){
415 $override[$key] = sugar_config_union( $value, $override[$key] );
421 function make_not_writable( $file ){
422 // Returns true if the given file/dir has been made not writable
424 if( is_file($file) || is_dir($file) ){
425 if( !is_writable($file) ){
429 $original_fileperms = fileperms($file);
431 // take away writable permissions
432 $new_fileperms = $original_fileperms & ~0x0092;
433 @sugar_chmod($file, $new_fileperms);
435 if( !is_writable($file) ){
444 /** This function returns the name of the person.
445 * It currently returns "first last". It should not put the space if either name is not available.
446 * It should not return errors if either name is not available.
447 * If no names are present, it will return ""
448 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
449 * All Rights Reserved.
450 * Contributor(s): ______________________________________..
452 function return_name($row, $first_column, $last_column)
458 if(isset($row[$first_column]))
460 $first_name = stripslashes($row[$first_column]);
463 if(isset($row[$last_column]))
465 $last_name = stripslashes($row[$last_column]);
468 $full_name = $first_name;
470 // If we have a first name and we have a last name
471 if($full_name != "" && $last_name != "")
473 // append a space, then the last name
474 $full_name .= " ".$last_name;
476 // If we have no first name, but we have a last name
477 else if($last_name != "")
479 // append the last name without the space.
480 $full_name .= $last_name;
487 function get_languages()
489 global $sugar_config;
490 return $sugar_config['languages'];
493 function get_language_display($key)
495 global $sugar_config;
496 return $sugar_config['languages'][$key];
499 function get_assigned_user_name($assigned_user_id, $is_group = '') {
500 static $saved_user_list = null;
502 if(empty($saved_user_list)) {
503 $saved_user_list = get_user_array(false, '', '', false, null, $is_group);
506 if(isset($saved_user_list[$assigned_user_id])) {
507 return $saved_user_list[$assigned_user_id];
514 * retrieves the user_name column value (login)
515 * @param string id GUID of user
518 function get_user_name($id) {
522 $db = DBManagerFactory::getInstance();
524 $q = "SELECT user_name FROM users WHERE id='{$id}'";
526 $a = $db->fetchByAssoc($r);
528 return (empty($a)) ? '' : $a['user_name'];
532 //TODO Update to use global cache
533 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) {
535 global $sugar_config;
539 $locale = new Localization();
542 $user_array = get_register_value('user_array', $add_blank. $status . $assigned_user);
544 if(!isset($user_array)) {
545 $db = DBManagerFactory::getInstance();
546 $temp_result = Array();
547 // Including deleted users for now.
548 if (empty($status)) {
549 $query = "SELECT id, first_name, last_name, user_name from users WHERE 1=1".$is_group;
552 $query = "SELECT id, first_name, last_name, user_name from users WHERE status='$status'".$is_group;
555 if (!empty($user_name_begins)) {
556 $query .= " AND user_name LIKE '$user_name_begins%' ";
558 if (!empty($assigned_user)) {
559 $query .= " OR id='$assigned_user'";
561 $query = $query.' ORDER BY user_name ASC';
562 $GLOBALS['log']->debug("get_user_array query: $query");
563 $result = $db->query($query, true, "Error filling in user array: ");
565 if ($add_blank==true) {
566 // Add in a blank row
567 $temp_result[''] = '';
570 // Get the id and the name.
571 while($row = $db->fetchByAssoc($result)) {
572 if($use_real_name == true || showFullName()) {
573 if(isset($row['last_name'])) { // cn: we will ALWAYS have both first_name and last_name (empty value if blank in db)
574 $temp_result[$row['id']] = $locale->getLocaleFormattedName($row['first_name'],$row['last_name']);
576 $temp_result[$row['id']] = $row['user_name'];
579 $temp_result[$row['id']] = $row['user_name'];
583 $user_array = $temp_result;
585 set_register_value('user_array', $add_blank. $status . $assigned_user, $temp_result);
594 * uses a different query to return a list of users than get_user_array()
595 * @param args string where clause entry
596 * @return array Array of Users' details that match passed criteria
598 function getUserArrayFromFullName($args) {
600 $db = DBManagerFactory::getInstance();
603 if(strpos($args, " ")) {
604 $argArray = explode(" ", $args);
610 foreach($argArray as $arg) {
611 if(!empty($inClause)) {
617 $inClause .= "(first_name LIKE '{$arg}%' OR last_name LIKE '{$arg}%')";
620 $query = "SELECT id, first_name, last_name, user_name FROM users WHERE status='Active' AND deleted=0 AND ";
622 $query .= " ORDER BY last_name ASC";
624 $r = $db->query($query);
626 while($a = $db->fetchByAssoc($r)) {
627 $ret[$a['id']] = $locale->getLocaleFormattedName($a['first_name'], $a['last_name']);
635 * based on user pref then system pref
637 function showFullName() {
638 global $sugar_config;
639 global $current_user;
640 static $showFullName = null;
642 if (is_null($showFullName)) {
643 $sysPref = (isset($sugar_config['use_real_names']) && $sugar_config['use_real_names'] == true) ? true : false;
644 $userPref = (is_object($current_user)) ? $current_user->getPreference('use_real_names') : null;
646 if($userPref != null) {
647 $bool = ($userPref == 'on') ? true : false;
648 $showFullName = $bool;
650 $showFullName = $sysPref;
654 return $showFullName;
657 function clean($string, $maxLength)
659 $string = substr($string, 0, $maxLength);
660 return escapeshellcmd($string);
664 * Copy the specified request variable to the member variable of the specified object.
665 * Do no copy if the member variable is already set.
666 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
667 * All Rights Reserved.
668 * Contributor(s): ______________________________________..
670 function safe_map($request_var, & $focus, $always_copy = false)
672 safe_map_named($request_var, $focus, $request_var, $always_copy);
676 * Copy the specified request variable to the member variable of the specified object.
677 * Do no copy if the member variable is already set.
678 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
679 * All Rights Reserved.
680 * Contributor(s): ______________________________________..
682 function safe_map_named($request_var, & $focus, $member_var, $always_copy)
684 if (isset($_REQUEST[$request_var]) && ($always_copy || is_null($focus->$member_var))) {
685 $GLOBALS['log']->debug("safe map named called assigning '{$_REQUEST[$request_var]}' to $member_var");
686 $focus->$member_var = $_REQUEST[$request_var];
691 * This function retrieves an application language file and returns the array of strings included in the $app_list_strings var.
693 * @param string $language specific language to load
694 * @return array lang strings
696 function return_app_list_strings_language($language)
698 global $app_list_strings;
699 global $sugar_config;
701 $cache_key = 'app_list_strings.'.$language;
703 // Check for cached value
704 $cache_entry = sugar_cache_retrieve($cache_key);
705 if(!empty($cache_entry))
710 $default_language = $sugar_config['default_language'];
711 $temp_app_list_strings = $app_list_strings;
714 if ($language != 'en_us') {
717 if ($default_language != 'en_us' && $language != $default_language) {
718 $langs[] = $default_language;
720 $langs[] = $language;
722 $app_list_strings_array = array();
724 foreach ( $langs as $lang ) {
725 $app_list_strings = array();
726 if(file_exists("include/language/$lang.lang.php")) {
727 include("include/language/$lang.lang.php");
728 $GLOBALS['log']->info("Found language file: $lang.lang.php");
730 if(file_exists("include/language/$lang.lang.override.php")) {
731 include("include/language/$lang.lang.override.php");
732 $GLOBALS['log']->info("Found override language file: $lang.lang.override.php");
734 if(file_exists("include/language/$lang.lang.php.override")) {
735 include("include/language/$lang.lang.php.override");
736 $GLOBALS['log']->info("Found override language file: $lang.lang.php.override");
739 $app_list_strings_array[] = $app_list_strings;
742 $app_list_strings = array();
743 foreach ( $app_list_strings_array as $app_list_strings_item ) {
744 $app_list_strings = sugarArrayMerge($app_list_strings, $app_list_strings_item);
747 foreach ( $langs as $lang ) {
748 if(file_exists("custom/application/Ext/Language/$lang.lang.ext.php")) {
749 $app_list_strings = _mergeCustomAppListStrings("custom/application/Ext/Language/$lang.lang.ext.php" , $app_list_strings);
750 $GLOBALS['log']->info("Found extended language file: $lang.lang.ext.php");
752 if(file_exists("custom/include/language/$lang.lang.php")) {
753 include("custom/include/language/$lang.lang.php");
754 $GLOBALS['log']->info("Found custom language file: $lang.lang.php");
758 if(!isset($app_list_strings)) {
759 $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");
763 $return_value = $app_list_strings;
764 $app_list_strings = $temp_app_list_strings;
766 sugar_cache_put($cache_key, $return_value);
768 return $return_value;
772 * The dropdown items in custom language files is $app_list_strings['$key']['$second_key'] = $value not
773 * $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.
774 * @param file string the language that you want include,
775 * @param app_list_strings array the golbal strings
779 function _mergeCustomAppListStrings($file , $app_list_strings){
780 $app_list_strings_original = $app_list_strings;
781 unset($app_list_strings);
783 if(!isset($app_list_strings) || !is_array($app_list_strings)){
784 return $app_list_strings_original;
786 //Bug 25347: We should not merge custom dropdown fields unless they relate to parent fields or the module list.
787 foreach($app_list_strings as $key=>$value)
789 $exemptDropdowns = array("moduleList", "parent_type_display", "record_type_display", "record_type_display_notes");
790 if (!in_array($key, $exemptDropdowns) && array_key_exists($key, $app_list_strings_original))
792 unset($app_list_strings_original["$key"]);
795 $app_list_strings = sugarArrayMergeRecursive($app_list_strings_original , $app_list_strings);
796 return $app_list_strings;
800 * This function retrieves an application language file and returns the array of strings included.
802 * @param string $language specific language to load
803 * @return array lang strings
805 function return_application_language($language)
807 global $app_strings, $sugar_config;
809 $cache_key = 'app_strings.'.$language;
811 // Check for cached value
812 $cache_entry = sugar_cache_retrieve($cache_key);
813 if(!empty($cache_entry))
818 $temp_app_strings = $app_strings;
819 $default_language = $sugar_config['default_language'];
822 if ($language != 'en_us') {
825 if ($default_language != 'en_us' && $language != $default_language) {
826 $langs[] = $default_language;
828 $langs[] = $language;
830 $app_strings_array = array();
832 foreach ( $langs as $lang ) {
833 $app_strings = array();
834 if(file_exists("include/language/$lang.lang.php")) {
835 include("include/language/$lang.lang.php");
836 $GLOBALS['log']->info("Found language file: $lang.lang.php");
838 if(file_exists("include/language/$lang.lang.override.php")) {
839 include("include/language/$lang.lang.override.php");
840 $GLOBALS['log']->info("Found override language file: $lang.lang.override.php");
842 if(file_exists("include/language/$lang.lang.php.override")) {
843 include("include/language/$lang.lang.php.override");
844 $GLOBALS['log']->info("Found override language file: $lang.lang.php.override");
846 if(file_exists("custom/application/Ext/Language/$lang.lang.ext.php")) {
847 include("custom/application/Ext/Language/$lang.lang.ext.php");
848 $GLOBALS['log']->info("Found extended language file: $lang.lang.ext.php");
850 if(file_exists("custom/include/language/$lang.lang.php")) {
851 include("custom/include/language/$lang.lang.php");
852 $GLOBALS['log']->info("Found custom language file: $lang.lang.php");
854 $app_strings_array[] = $app_strings;
857 $app_strings = array();
858 foreach ( $app_strings_array as $app_strings_item ) {
859 $app_strings = sugarArrayMerge($app_strings, $app_strings_item);
862 if(!isset($app_strings)) {
863 $GLOBALS['log']->fatal("Unable to load the application language strings");
867 // If we are in debug mode for translating, turn on the prefix now!
868 if($sugar_config['translation_string_prefix']) {
869 foreach($app_strings as $entry_key=>$entry_value) {
870 $app_strings[$entry_key] = $language.' '.$entry_value;
873 if(isset($_SESSION['show_deleted'])) {
874 $app_strings['LBL_DELETE_BUTTON'] = $app_strings['LBL_UNDELETE_BUTTON'];
875 $app_strings['LBL_DELETE_BUTTON_LABEL'] = $app_strings['LBL_UNDELETE_BUTTON_LABEL'];
876 $app_strings['LBL_DELETE_BUTTON_TITLE'] = $app_strings['LBL_UNDELETE_BUTTON_TITLE'];
877 $app_strings['LBL_DELETE'] = $app_strings['LBL_UNDELETE'];
880 $app_strings['LBL_ALT_HOT_KEY'] = get_alt_hot_key();
882 $return_value = $app_strings;
883 $app_strings = $temp_app_strings;
885 sugar_cache_put($cache_key, $return_value);
887 return $return_value;
891 * This function retrieves a module's language file and returns the array of strings included.
893 * @param string $language specific language to load
894 * @param string $module module name to load strings for
895 * @param bool $refresh optional, true if you want to rebuild the language strings
896 * @return array lang strings
898 function return_module_language($language, $module, $refresh=false)
901 global $sugar_config;
902 global $currentModule;
904 // Jenny - Bug 8119: Need to check if $module is not empty
905 if (empty($module)) {
906 $stack = debug_backtrace();
907 $GLOBALS['log']->warn("Variable module is not in return_module_language ". var_export($stack, true));
911 // Store the current mod strings for later
912 $temp_mod_strings = $mod_strings;
913 $loaded_mod_strings = array();
914 $language_used = $language;
915 $default_language = $sugar_config['default_language'];
917 if(empty($language)) {
918 $language = $default_language;
921 // Bug 21559 - So we can get all the strings defined in the template, refresh
922 // the vardefs file if the cached language file doesn't exist.
923 if(!file_exists($GLOBALS['sugar_config']['cache_dir'].'modules/'. $module . '/language/'.$language.'.lang.php')
924 && !empty($GLOBALS['beanList'][$module])){
925 $object = $GLOBALS['beanList'][$module];
926 if ($object == 'aCase') {
929 VardefManager::refreshVardefs($module,$object);
932 $loaded_mod_strings = LanguageManager::loadModuleLanguage($module, $language,$refresh);
934 // cn: bug 6048 - merge en_us with requested language
935 if($language != $sugar_config['default_language'])
936 $loaded_mod_strings = sugarArrayMerge(
937 LanguageManager::loadModuleLanguage($module, $sugar_config['default_language'],$refresh),
941 // Load in en_us strings by default
942 if($language != 'en_us' && $sugar_config['default_language'] != 'en_us')
943 $loaded_mod_strings = sugarArrayMerge(
944 LanguageManager::loadModuleLanguage($module, 'en_us', $refresh),
948 // If we are in debug mode for translating, turn on the prefix now!
949 if($sugar_config['translation_string_prefix']) {
950 foreach($loaded_mod_strings as $entry_key=>$entry_value) {
951 $loaded_mod_strings[$entry_key] = $language_used.' '.$entry_value;
955 $return_value = $loaded_mod_strings;
956 if(!isset($mod_strings)){
957 $mod_strings = $return_value;
960 $mod_strings = $temp_mod_strings;
962 return $return_value;
966 /** This function retrieves an application language file and returns the array of strings included in the $mod_list_strings var.
967 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
968 * All Rights Reserved.
969 * Contributor(s): ______________________________________..
970 * If you are using the current language, do not call this function unless you are loading it for the first time */
971 function return_mod_list_strings_language($language,$module) {
972 global $mod_list_strings;
973 global $sugar_config;
974 global $currentModule;
976 $cache_key = "mod_list_str_lang.".$language.$module;
978 // Check for cached value
979 $cache_entry = sugar_cache_retrieve($cache_key);
980 if(!empty($cache_entry))
985 $language_used = $language;
986 $temp_mod_list_strings = $mod_list_strings;
987 $default_language = $sugar_config['default_language'];
989 if($currentModule == $module && isset($mod_list_strings) && $mod_list_strings != null) {
990 return $mod_list_strings;
993 // cn: bug 6351 - include en_us if file langpack not available
994 // cn: bug 6048 - merge en_us with requested language
995 include("modules/$module/language/en_us.lang.php");
996 $en_mod_list_strings = array();
997 if($language_used != $default_language)
998 $en_mod_list_strings = $mod_list_strings;
1000 if(file_exists("modules/$module/language/$language.lang.php")) {
1001 include("modules/$module/language/$language.lang.php");
1004 if(file_exists("modules/$module/language/$language.lang.override.php")){
1005 include("modules/$module/language/$language.lang.override.php");
1008 if(file_exists("modules/$module/language/$language.lang.php.override")){
1009 echo 'Please Change:<br>' . "modules/$module/language/$language.lang.php.override" . '<br>to<br>' . 'Please Change:<br>' . "modules/$module/language/$language.lang.override.php";
1010 include("modules/$module/language/$language.lang.php.override");
1013 // cn: bug 6048 - merge en_us with requested language
1014 $mod_list_strings = sugarArrayMerge($en_mod_list_strings, $mod_list_strings);
1016 // if we still don't have a language pack, then log an error
1017 if(!isset($mod_list_strings)) {
1018 $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})");
1022 $return_value = $mod_list_strings;
1023 $mod_list_strings = $temp_mod_list_strings;
1025 sugar_cache_put($cache_key, $return_value);
1026 return $return_value;
1030 /** This function retrieves a theme's language file and returns the array of strings included.
1031 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1032 * All Rights Reserved.
1033 * Contributor(s): ______________________________________..
1035 function return_theme_language($language, $theme)
1037 global $mod_strings, $sugar_config, $currentModule;
1039 $language_used = $language;
1040 $default_language = $sugar_config['default_language'];
1042 include(SugarThemeRegistry::get($theme)->getFilePath()."/language/$current_language.lang.php");
1043 if(file_exists(SugarThemeRegistry::get($theme)->getFilePath()."/language/$current_language.lang.override.php")){
1044 include(SugarThemeRegistry::get($theme)->getFilePath()."/language/$current_language.lang.override.php");
1046 if(file_exists(SugarThemeRegistry::get($theme)->getFilePath()."/language/$current_language.lang.php.override")){
1047 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";
1048 include(SugarThemeRegistry::get($theme)->getFilePath()."/language/$current_language.lang.php.override");
1050 if(!isset($theme_strings))
1052 $GLOBALS['log']->warn("Unable to find the theme file for language: ".$language." and theme: ".$theme);
1053 require(SugarThemeRegistry::get($theme)->getFilePath()."/language/$default_language.lang.php");
1054 $language_used = $default_language;
1057 if(!isset($theme_strings))
1059 $GLOBALS['log']->fatal("Unable to load the theme($theme) language file for the selected language($language) or the default language($default_language)");
1063 // If we are in debug mode for translating, turn on the prefix now!
1064 if($sugar_config['translation_string_prefix'])
1066 foreach($theme_strings as $entry_key=>$entry_value)
1068 $theme_strings[$entry_key] = $language_used.' '.$entry_value;
1072 return $theme_strings;
1077 /** If the session variable is defined and is not equal to "" then return it. Otherwise, return the default value.
1078 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1079 * All Rights Reserved.
1080 * Contributor(s): ______________________________________..
1082 function return_session_value_or_default($varname, $default)
1084 if(isset($_SESSION[$varname]) && $_SESSION[$varname] != "")
1086 return $_SESSION[$varname];
1093 * Creates an array of where restrictions. These are used to construct a where SQL statement on the query
1094 * 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.
1095 * @param &$where_clauses - The array to append the clause to
1096 * @param $variable_name - The name of the variable to look for an add to the where clause if found
1097 * @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.
1098 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1099 * All Rights Reserved.
1100 * Contributor(s): ______________________________________..
1102 function append_where_clause(&$where_clauses, $variable_name, $SQL_name = null)
1104 if($SQL_name == null)
1106 $SQL_name = $variable_name;
1109 if(isset($_REQUEST[$variable_name]) && $_REQUEST[$variable_name] != "")
1111 array_push($where_clauses, "$SQL_name like '".$GLOBALS['db']->quote($_REQUEST[$variable_name])."%'");
1116 * Generate the appropriate SQL based on the where clauses.
1117 * @param $where_clauses - An Array of individual where clauses stored as strings
1118 * @returns string where_clause - The final SQL where clause to be executed.
1119 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1120 * All Rights Reserved.
1121 * Contributor(s): ______________________________________..
1123 function generate_where_statement($where_clauses)
1126 foreach($where_clauses as $clause)
1133 $GLOBALS['log']->info("Here is the where clause for the list view: $where");
1138 * determines if a passed string matches the criteria for a Sugar GUID
1139 * @param string $guid
1140 * @return bool False on failure
1142 function is_guid($guid) {
1143 if(strlen($guid) != 36) {
1147 if(preg_match("/\w{8}-\w{4}-\w{4}-\w{4}-\w{12}/i", $guid)) {
1156 * A temporary method of generating GUIDs of the correct format for our DB.
1157 * @return String contianing a GUID in the format: aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
1159 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1160 * All Rights Reserved.
1161 * Contributor(s): ______________________________________..
1163 function create_guid()
1165 $microTime = microtime();
1166 list($a_dec, $a_sec) = explode(" ", $microTime);
1168 $dec_hex = dechex($a_dec* 1000000);
1169 $sec_hex = dechex($a_sec);
1171 ensure_length($dec_hex, 5);
1172 ensure_length($sec_hex, 6);
1176 $guid .= create_guid_section(3);
1178 $guid .= create_guid_section(4);
1180 $guid .= create_guid_section(4);
1182 $guid .= create_guid_section(4);
1185 $guid .= create_guid_section(6);
1191 function create_guid_section($characters)
1194 for($i=0; $i<$characters; $i++)
1196 $return .= dechex(mt_rand(0,15));
1201 function ensure_length(&$string, $length)
1203 $strlen = strlen($string);
1204 if($strlen < $length)
1206 $string = str_pad($string,$length,"0");
1208 else if($strlen > $length)
1210 $string = substr($string, 0, $length);
1214 function microtime_diff($a, $b) {
1215 list($a_dec, $a_sec) = explode(" ", $a);
1216 list($b_dec, $b_sec) = explode(" ", $b);
1217 return $b_sec - $a_sec + $b_dec - $a_dec;
1220 // check if Studio is displayed.
1221 function displayStudioForCurrentUser()
1223 if ( is_admin($GLOBALS['current_user']) ) {
1233 function displayWorkflowForCurrentUser()
1235 $_SESSION['display_workflow_for_user'] = false;
1239 // return an array with all modules where the user is an admin.
1240 function get_admin_modules_for_user($user) {
1242 $admin_modules = array();
1244 return ($admin_modules);
1247 function get_workflow_admin_modules_for_user($user){
1248 if (isset($_SESSION['get_workflow_admin_modules_for_user'])) {
1249 return $_SESSION['get_workflow_admin_modules_for_user'];
1253 $workflow_mod_list = array();
1254 foreach($moduleList as $module){
1255 $workflow_mod_list[$module] = $module;
1258 // This list is taken from teh previous version of workflow_utils.php
1259 $workflow_mod_list['Tasks'] = "Tasks";
1260 $workflow_mod_list['Calls'] = "Calls";
1261 $workflow_mod_list['Meetings'] = "Meetings";
1262 $workflow_mod_list['Notes'] = "Notes";
1263 $workflow_mod_list['ProjectTask'] = "Project Tasks";
1264 $workflow_mod_list['Leads'] = "Leads";
1265 $workflow_mod_list['Opportunities'] = "Opportunities";
1268 $workflow_admin_modules = array();
1270 return $workflow_admin_modules;
1272 $actions = ACLAction::getUserActions($user->id);
1273 //check for ForecastSchedule because it doesn't exist in $workflow_mod_list
1274 if (isset($actions['ForecastSchedule']['module']['admin']['aclaccess']) && ($actions['ForecastSchedule']['module']['admin']['aclaccess']==ACL_ALLOW_DEV ||
1275 $actions['ForecastSchedule']['module']['admin']['aclaccess']==ACL_ALLOW_ADMIN_DEV)) {
1276 $workflow_admin_modules['Forecasts'] = 'Forecasts';
1278 foreach ($workflow_mod_list as $key=>$val) {
1279 if(!in_array($val, $workflow_admin_modules) && ($val!='iFrames' && $val!='Feeds' && $val!='Home' && $val!='Dashboard'
1280 && $val!='Calendar' && $val!='Activities' && $val!='Reports') &&
1281 (is_admin_for_module($user,$key))) {
1282 $workflow_admin_modules[$key] = $val;
1285 $_SESSION['get_workflow_admin_modules_for_user'] = $workflow_admin_modules;
1286 return ($workflow_admin_modules);
1289 // Check if user is admin for at least one module.
1290 function is_admin_for_any_module($user) {
1295 // Check if user is admin for a specific module.
1296 function is_admin_for_module($user,$module) {
1302 * Check if user id belongs to a system admin.
1303 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1304 * All Rights Reserved.
1305 * Contributor(s): ______________________________________..
1307 function is_admin($user) {
1308 if(!empty($user) && ($user->is_admin == '1' || $user->is_admin === 'on')){
1316 * Return the display name for a theme if it exists.
1317 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1318 * All Rights Reserved.
1319 * Contributor(s): ______________________________________..
1321 * @deprecated use SugarThemeRegistry::get($theme)->name instead
1323 function get_theme_display($theme)
1325 return SugarThemeRegistry::get($theme)->name;
1329 * Return an array of directory names.
1330 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1331 * All Rights Reserved.
1332 * Contributor(s): ______________________________________..
1334 * @deprecated use SugarThemeRegistry::availableThemes() instead.
1336 function get_themes()
1338 return SugarThemeRegistry::availableThemes();
1342 * THIS FUNCTION IS DEPRECATED AND SHOULD NOT BE USED; USE get_select_options_with_id()
1343 * Create HTML to display select options in a dropdown list. To be used inside
1344 * of a select statement in a form.
1345 * param $option_list - the array of strings to that contains the option list
1346 * param $selected - the string which contains the default value
1347 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1348 * All Rights Reserved.
1349 * Contributor(s): ______________________________________..
1351 function get_select_options ($option_list, $selected) {
1352 return get_select_options_with_id($option_list, $selected);
1356 * Create HTML to display select options in a dropdown list. To be used inside
1357 * 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.
1358 * param $option_list - the array of strings to that contains the option list
1359 * param $selected - the string which contains the default value
1360 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1361 * All Rights Reserved.
1362 * Contributor(s): ______________________________________..
1364 function get_select_options_with_id ($option_list, $selected_key) {
1365 return get_select_options_with_id_separate_key($option_list, $option_list, $selected_key);
1370 * Create HTML to display select options in a dropdown list. To be used inside
1371 * 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.
1372 * param $label_list - the array of strings to that contains the option list
1373 * param $key_list - the array of strings to that contains the values list
1374 * param $selected - the string which contains the default value
1375 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1376 * All Rights Reserved.
1377 * Contributor(s): ______________________________________..
1379 function get_select_options_with_id_separate_key ($label_list, $key_list, $selected_key, $massupdate=false) {
1380 global $app_strings;
1381 $select_options = "";
1383 //for setting null selection values to human readable --None--
1384 $pattern = "/'0?'></";
1385 $replacement = "''>".$app_strings['LBL_NONE']."<";
1387 if (empty($key_list)) $key_list = array();
1388 //create the type dropdown domain and set the selected value if $opp value already exists
1389 foreach ($key_list as $option_key=>$option_value) {
1391 $selected_string = '';
1392 // the system is evaluating $selected_key == 0 || '' to true. Be very careful when changing this. Test all cases.
1393 // The bug was only happening with one of the users in the drop down. It was being replaced by none.
1394 if (($option_key != '' && $selected_key == $option_key) || ($selected_key == '' && $option_key == '' && !$massupdate) || (is_array($selected_key) && in_array($option_key, $selected_key)))
1396 $selected_string = 'selected ';
1399 $html_value = $option_key;
1401 $select_options .= "\n<OPTION ".$selected_string."value='$html_value'>$label_list[$option_key]</OPTION>";
1403 $select_options = preg_replace($pattern, $replacement, $select_options);
1404 return $select_options;
1409 * Call this method instead of die().
1410 * Then we call the die method with the error message that is passed in.
1412 function sugar_die($error_message)
1416 die($error_message);
1421 * Create javascript to clear values of all elements in a form.
1422 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1423 * All Rights Reserved.
1424 * Contributor(s): ______________________________________..
1426 function get_clear_form_js () {
1427 $the_script = <<<EOQ
1428 <script type="text/javascript" language="JavaScript">
1429 function clear_form(form) {
1430 var newLoc = 'index.php?action=' + form.action.value + '&module=' + form.module.value + '&query=true&clear_query=true';
1431 if(typeof(form.advanced) != 'undefined'){
1432 newLoc += '&advanced=' + form.advanced.value;
1434 document.location.href= newLoc;
1443 * Create javascript to set the cursor focus to specific field in a form
1444 * when the screen is rendered. The field name is currently hardcoded into the
1446 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1447 * All Rights Reserved.
1448 * Contributor(s): ______________________________________..
1450 function get_set_focus_js () {
1451 //TODO Clint 5/20 - Make this function more generic so that it can take in the target form and field names as variables
1452 $the_script = <<<EOQ
1453 <script type="text/javascript" language="JavaScript">
1455 function set_focus() {
1456 if (document.forms.length > 0) {
1457 for (i = 0; i < document.forms.length; i++) {
1458 for (j = 0; j < document.forms[i].elements.length; j++) {
1459 var field = document.forms[i].elements[j];
1460 if ((field.type == "text" || field.type == "textarea" || field.type == "password") &&
1461 !field.disabled && (field.name == "first_name" || field.name == "name" || field.name == "user_name" || field.name=="document_name")) {
1463 if (field.type == "text") {
1480 * Very cool algorithm for sorting multi-dimensional arrays. Found at http://us2.php.net/manual/en/function.array-multisort.php
1481 * Syntax: $new_array = array_csort($array [, 'col1' [, SORT_FLAG [, SORT_FLAG]]]...);
1482 * Explanation: $array is the array you want to sort, 'col1' is the name of the column
1483 * you want to sort, SORT_FLAGS are : SORT_ASC, SORT_DESC, SORT_REGULAR, SORT_NUMERIC, SORT_STRING
1484 * you can repeat the 'col',FLAG,FLAG, as often you want, the highest prioritiy is given to
1485 * the first - so the array is sorted by the last given column first, then the one before ...
1486 * Example: $array = array_csort($array,'town','age',SORT_DESC,'name');
1487 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1488 * All Rights Reserved.
1489 * Contributor(s): ______________________________________..
1491 function array_csort() {
1492 $args = func_get_args();
1493 $marray = array_shift($args);
1496 $msortline = "return(array_multisort(";
1497 foreach ($args as $arg) {
1499 if (is_string($arg)) {
1500 foreach ($marray as $row) {
1501 $sortarr[$i][] = $row[$arg];
1504 $sortarr[$i] = $arg;
1506 $msortline .= "\$sortarr[".$i."],";
1508 $msortline .= "\$marray));";
1515 * Converts localized date format string to jscalendar format
1516 * Example: $array = array_csort($array,'town','age',SORT_DESC,'name');
1517 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1518 * All Rights Reserved.
1519 * Contributor(s): ______________________________________..
1521 function parse_calendardate($local_format) {
1522 preg_match("/\(?([^-]{1})[^-]*-([^-]{1})[^-]*-([^-]{1})[^-]*\)/", $local_format, $matches);
1523 $calendar_format = "%" . $matches[1] . "-%" . $matches[2] . "-%" . $matches[3];
1524 return str_replace(array("y", "ᅣ1�7", "a", "j"), array("Y", "Y", "Y", "d"), $calendar_format);
1531 function translate($string, $mod='', $selectedValue=''){
1532 //$test_start = microtime();
1533 //static $mod_strings_results = array();
1535 global $current_language;
1537 if(isset($_REQUEST['login_language'])){
1538 $current_language = ($_REQUEST['login_language'] == $current_language)? $current_language : $_REQUEST['login_language'];
1540 $mod_strings = return_module_language($current_language, $mod);
1543 global $mod_strings;
1547 global $app_strings, $app_list_strings;
1549 if(isset($mod_strings[$string]))
1550 $returnValue = $mod_strings[$string];
1551 else if(isset($app_strings[$string]))
1552 $returnValue = $app_strings[$string];
1553 else if(isset($app_list_strings[$string]))
1554 $returnValue = $app_list_strings[$string];
1555 else if(isset($app_list_strings['moduleList']) && isset($app_list_strings['moduleList'][$string]))
1556 $returnValue = $app_list_strings['moduleList'][$string];
1559 //$test_end = microtime();
1561 // $mod_strings_results[$mod] = microtime_diff($test_start,$test_end);
1563 // echo("translate results:");
1565 // $total_strings = 0;
1566 // foreach($mod_strings_results as $key=>$value)
1568 // echo("Module $key \t\t time $value \t\t<br>");
1569 // $total_time += $value;
1572 // echo("Total time: $total_time<br>");
1576 if(empty($returnValue)){
1580 if(is_array($returnValue) && ! empty($selectedValue) && isset($returnValue[$selectedValue]) ){
1581 return $returnValue[$selectedValue];
1584 return $returnValue;
1587 function unTranslateNum($num) {
1589 static $num_grp_sep;
1590 global $current_user, $sugar_config;
1592 if($dec_sep == null) {
1593 $user_dec_sep = $current_user->getPreference('dec_sep');
1594 $dec_sep = (empty($user_dec_sep) ? $sugar_config['default_decimal_seperator'] : $user_dec_sep);
1596 if($num_grp_sep == null) {
1597 $user_num_grp_sep = $current_user->getPreference('num_grp_sep');
1598 $num_grp_sep = (empty($user_num_grp_sep) ? $sugar_config['default_number_grouping_seperator'] : $user_num_grp_sep);
1601 $num = preg_replace("'" . preg_quote($num_grp_sep) . "'", '', $num);
1602 $num = preg_replace("'" . preg_quote($dec_sep) . "'", '.', $num);
1607 function add_http($url) {
1608 if(!preg_match("@://@i", $url)) {
1610 if(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') {
1614 return "{$scheme}://{$url}";
1621 * returns a default array of XSS tags to clean
1624 function getDefaultXssTags() {
1626 "applet" => "applet",
1631 "frameset" => "frameset",
1632 "iframe" => "iframe",
1633 "import" => "\?import",
1636 "object" => "object",
1637 "script" => "script",
1641 $ret = base64_encode(serialize($tmp));
1647 * Detects typical XSS attack patterns
1648 * @param string str String to search for XSS attack vectors
1649 * @param bool cleanImg Flag to allow <img> tags to survive - only used by InboundEmail for inline images.
1650 * @return array Array of matches, empty on clean string
1652 function clean_xss($str, $cleanImg=true) {
1653 global $sugar_config;
1655 if(empty($sugar_config['email_xss']))
1656 $sugar_config['email_xss'] = getDefaultXssTags();
1658 $arr = unserialize(base64_decode($sugar_config['email_xss']));
1661 foreach($arr as $v) {
1662 if(!empty($regex)) {
1668 $tag_regex = "#<({$regex})[^>]*>?#sim";
1670 // cn: bug 13079 - "on\w" matched too many non-events (cONTact, strONG, etc.)
1671 $jsEvents = "onblur|onfocus|oncontextmenu|onresize|onscroll|onunload|ondblclick|onclick|";
1672 $jsEvents .= "onmouseup|onmouseover|onmousedown|onmouseenter|onmouseleave|onmousemove|onload|onchange|";
1673 $jsEvents .= "onreset|onselect|onsubmit|onkeydown|onkeypress|onkeyup|onabort|onerror";
1675 $attribute_regex = "#<[^/>][^>]+({$jsEvents}\w+)[^=>]*=[^>]*>#sim";
1676 $javascript_regex = '@<[^/>][^>]+(expression\(|j\W*a\W*v\W*a|v\W*b\W*s\W*c\W*r|&#|/\*|\*/)[^>]*>@sim';
1677 $imgsrc_regex = '#<[^>]+src[^=]*=([^>]*?http://[^>]*)>#sim';
1678 $css_url = "#url\(.*\.\w+\)#";
1681 $str = str_replace("\t", "", $str);
1683 $matches = array_merge(
1684 xss_check_pattern($tag_regex, $str),
1685 xss_check_pattern($javascript_regex, $str),
1686 xss_check_pattern($attribute_regex, $str)
1690 $matches = array_merge($matches,
1691 xss_check_pattern($imgsrc_regex, $str)
1695 // cn: bug 13498 - custom white-list of allowed domains that vet remote images
1696 preg_match_all($css_url, $str, $cssUrlMatches, PREG_PATTERN_ORDER);
1698 if(isset($sugar_config['security_trusted_domains']) && !empty($sugar_config['security_trusted_domains']) && is_array($sugar_config['security_trusted_domains'])) {
1699 if(is_array($cssUrlMatches) && count($cssUrlMatches) > 0) {
1700 // normalize whitelist
1701 foreach($sugar_config['security_trusted_domains'] as $k => $v) {
1702 $sugar_config['security_trusted_domains'][$k] = strtolower($v);
1705 foreach($cssUrlMatches[0] as $match) {
1706 $domain = strtolower(substr(strstr($match, "://"), 3));
1707 $baseUrl = substr($domain, 0, strpos($domain, "/"));
1709 if(!in_array($baseUrl, $sugar_config['security_trusted_domains'])) {
1710 $matches[] = $match;
1715 $matches = array_merge($matches, $cssUrlMatches[0]);
1722 * Helper function used by clean_xss() to parse for known-bad vectors
1723 * @param string pattern Regex pattern to use
1724 * @param string str String to parse for badness
1727 function xss_check_pattern($pattern, $str) {
1728 preg_match_all($pattern, $str, $matches, PREG_PATTERN_ORDER);
1732 // Designed to take a string passed in the URL as a parameter and clean all "bad" data from it
1733 // The second argument is a string, "filter," which corresponds to a regular expression
1734 function clean_string($str, $filter = "STANDARD") {
1735 global $sugar_config;
1738 "STANDARD" => "#[^A-Z0-9\-_\.\@]#i",
1739 "STANDARDSPACE" => "#[^A-Z0-9\-_\.\@\ ]#i",
1740 "FILE" => "#[^A-Z0-9\-_\.]#i",
1741 "NUMBER" => "#[^0-9\-]#i",
1742 "SQL_COLUMN_LIST" => "#[^A-Z0-9,_\.]#i",
1743 "PATH_NO_URL" => "#://#i",
1744 "SAFED_GET" => "#[^A-Z0-9\@\=\&\?\.\/\-_~]#i", /* range of allowed characters in a GET string */
1745 "UNIFIED_SEARCH" => "#[\\x00]#", /* cn: bug 3356 & 9236 - MBCS search strings */
1746 "AUTO_INCREMENT" => "#[^0-9\-,\ ]#i",
1747 "ALPHANUM" => "#[^A-Z0-9\-]#i",
1750 if (preg_match($filters[$filter], $str)) {
1751 if (isset($GLOBALS['log']) && is_object($GLOBALS['log'])) {
1752 $GLOBALS['log']->fatal("SECURITY: bad data passed in; string: {$str}");
1754 die("Bad data passed in; <a href=\"{$sugar_config['site_url']}\">Return to Home</a>");
1761 function clean_special_arguments() {
1762 if(isset($_SERVER['PHP_SELF'])) {
1763 if (!empty($_SERVER['PHP_SELF'])) clean_string($_SERVER['PHP_SELF'], 'SAFED_GET');
1765 if (!empty($_REQUEST) && !empty($_REQUEST['login_theme'])) clean_string($_REQUEST['login_theme'], "STANDARD");
1766 if (!empty($_REQUEST) && !empty($_REQUEST['login_module'])) clean_string($_REQUEST['login_module'], "STANDARD");
1767 if (!empty($_REQUEST) && !empty($_REQUEST['login_action'])) clean_string($_REQUEST['login_action'], "STANDARD");
1768 if (!empty($_REQUEST) && !empty($_REQUEST['ck_login_theme_20'])) clean_string($_REQUEST['ck_login_theme_20'], "STANDARD");
1769 if (!empty($_SESSION) && !empty($_SESSION['authenticated_user_theme'])) clean_string($_SESSION['authenticated_user_theme'], "STANDARD");
1770 if (!empty($_REQUEST) && !empty($_REQUEST['module_name'])) clean_string($_REQUEST['module_name'], "STANDARD");
1771 if (!empty($_REQUEST) && !empty($_REQUEST['module'])) clean_string($_REQUEST['module'], "STANDARD");
1772 if (!empty($_POST) && !empty($_POST['parent_type'])) clean_string($_POST['parent_type'], "STANDARD");
1773 if (!empty($_REQUEST) && !empty($_REQUEST['mod_lang'])) clean_string($_REQUEST['mod_lang'], "STANDARD");
1774 if (!empty($_SESSION) && !empty($_SESSION['authenticated_user_language'])) clean_string($_SESSION['authenticated_user_language'], "STANDARD");
1775 if (!empty($_SESSION) && !empty($_SESSION['dyn_layout_file'])) clean_string($_SESSION['dyn_layout_file'], "PATH_NO_URL");
1776 if (!empty($_GET) && !empty($_GET['from'])) clean_string($_GET['from']);
1777 if (!empty($_GET) && !empty($_GET['gmto'])) clean_string($_GET['gmto'], "NUMBER");
1778 if (!empty($_GET) && !empty($_GET['case_number'])) clean_string($_GET['case_number'], "AUTO_INCREMENT");
1779 if (!empty($_GET) && !empty($_GET['bug_number'])) clean_string($_GET['bug_number'], "AUTO_INCREMENT");
1780 if (!empty($_GET) && !empty($_GET['quote_num'])) clean_string($_GET['quote_num'], "AUTO_INCREMENT");
1781 clean_superglobals('stamp', 'ALPHANUM'); // for vcr controls
1782 clean_superglobals('offset', 'ALPHANUM');
1783 clean_superglobals('return_action');
1784 clean_superglobals('return_module');
1789 * cleans the given key in superglobals $_GET, $_POST, $_REQUEST
1791 function clean_superglobals($key, $filter = 'STANDARD') {
1792 if(isset($_GET[$key])) clean_string($_GET[$key], $filter);
1793 if(isset($_POST[$key])) clean_string($_POST[$key], $filter);
1794 if(isset($_REQUEST[$key])) clean_string($_REQUEST[$key], $filter);
1797 function set_superglobals($key, $val){
1799 $_POST[$key] = $val;
1800 $_REQUEST[$key] = $val;
1803 // Works in conjunction with clean_string() to defeat SQL injection, file inclusion attacks, and XSS
1804 function clean_incoming_data() {
1805 global $sugar_config;
1807 if (get_magic_quotes_gpc() == 1) {
1808 $req = array_map("preprocess_param", $_REQUEST);
1809 $post = array_map("preprocess_param", $_POST);
1810 $get = array_map("preprocess_param", $_GET);
1813 $req = array_map("securexss", $_REQUEST);
1814 $post = array_map("securexss", $_POST);
1815 $get = array_map("securexss", $_GET);
1818 // PHP cannot stomp out superglobals reliably
1819 foreach($post as $k => $v) { $_POST[$k] = $v; }
1820 foreach($get as $k => $v) { $_GET[$k] = $v; }
1821 foreach($req as $k => $v) {
1823 //ensure the keys are safe as well
1826 // Any additional variables that need to be cleaned should be added here
1827 if (isset($_REQUEST['login_theme'])) clean_string($_REQUEST['login_theme']);
1828 if (isset($_REQUEST['login_module'])) clean_string($_REQUEST['login_module']);
1829 if (isset($_REQUEST['login_action'])) clean_string($_REQUEST['login_action']);
1830 if (isset($_REQUEST['login_language'])) clean_string($_REQUEST['login_language']);
1831 if (isset($_REQUEST['action'])) clean_string($_REQUEST['action']);
1832 if (isset($_REQUEST['module'])) clean_string($_REQUEST['module']);
1833 if (isset($_REQUEST['record'])) clean_string($_REQUEST['record'], 'STANDARDSPACE');
1834 if (isset($_SESSION['authenticated_user_theme'])) clean_string($_SESSION['authenticated_user_theme']);
1835 if (isset($_SESSION['authenticated_user_language'])) clean_string($_SESSION['authenticated_user_language']);
1836 if (isset($_REQUEST['language'])) clean_string($_REQUEST['language']);
1837 if (isset($sugar_config['default_theme'])) clean_string($sugar_config['default_theme']);
1838 if (isset($_REQUEST['offset'])) clean_string($_REQUEST['offset']);
1839 if (isset($_REQUEST['stamp'])) clean_string($_REQUEST['stamp']);
1841 if(isset($_REQUEST['lvso'])){
1842 set_superglobals('lvso', (strtolower($_REQUEST['lvso']) === 'desc')?'desc':'asc');
1844 // Clean "offset" and "order_by" parameters in URL
1845 foreach ($_REQUEST as $key => $val) {
1846 if (str_end($key, "_offset")) {
1847 clean_string($_REQUEST[$key], "ALPHANUM"); // keep this ALPHANUM for disable_count_query
1848 set_superglobals($key, $_REQUEST[$key]);
1850 elseif (str_end($key, "_ORDER_BY")) {
1851 clean_string($_REQUEST[$key], "SQL_COLUMN_LIST");
1852 set_superglobals($key, $_REQUEST[$key]);
1860 // Returns TRUE if $str begins with $begin
1861 function str_begin($str, $begin) {
1862 return (substr($str, 0, strlen($begin)) == $begin);
1865 // Returns TRUE if $str ends with $end
1866 function str_end($str, $end) {
1867 return (substr($str, strlen($str) - strlen($end)) == $end);
1870 function securexss($value) {
1871 if(is_array($value)){
1873 foreach($value as $key=>$val){
1874 $new[$key] = securexss($val);
1878 static $xss_cleanup= array('"' =>'"', "'" => ''' , '<' =>'<' , '>'=>'>');
1879 $value = preg_replace(array('/javascript:/i', '/\0/'), array('java script:', ''), $value);
1880 $value = preg_replace('/javascript:/i', 'java script:', $value);
1881 return str_replace(array_keys($xss_cleanup), array_values($xss_cleanup), $value);
1884 function securexsskey($value, $die=true){
1885 global $sugar_config;
1887 preg_match("/[\'\"\<\>]/", $value, $matches);
1888 if(!empty($matches)){
1890 die("Bad data passed in; <a href=\"{$sugar_config['site_url']}\">Return to Home</a>");
1892 unset($_REQUEST[$value]);
1893 unset($_POST[$value]);
1894 unset($_GET[$value]);
1899 function preprocess_param($value){
1900 if(is_string($value)){
1901 if(get_magic_quotes_gpc() == 1){
1902 $value = stripslashes($value);
1905 $value = securexss($value);
1914 function set_register_value($category, $name, $value){
1915 return sugar_cache_put("{$category}:{$name}", $value);
1918 function get_register_value($category,$name){
1919 return sugar_cache_retrieve("{$category}:{$name}");
1922 // this function cleans id's when being imported
1923 function convert_id($string)
1925 return preg_replace_callback( '|[^A-Za-z0-9\-]|',
1927 // single quotes are essential here,
1928 // or alternative escape all $ as \$
1930 'return ord($matches[0]);'
1935 * @deprecated use SugarTheme::getImage()
1937 function get_image($image,$other_attributes,$width="",$height="")
1939 return SugarThemeRegistry::current()->getImage(basename($image),
1941 empty($width) ? null : $width,
1942 empty($height) ? null : $height
1946 * @deprecated use SugarTheme::getImageURL()
1948 function getImagePath($image_name)
1950 return SugarThemeRegistry::current()->getImageURL($image_name);
1953 function getWebPath($relative_path){
1954 //if it has a :// then it isn't a relative path
1955 if(substr_count($relative_path, '://') > 0) return $relative_path;
1956 if(defined('TEMPLATE_URL'))$relative_path = SugarTemplateUtilities::getWebPath($relative_path);
1957 return $relative_path;
1960 function getJSPath($relative_path, $additional_attrs=''){
1961 if(defined('TEMPLATE_URL'))$relative_path = SugarTemplateUtilities::getWebPath($relative_path);
1962 if(empty($GLOBALS['sugar_config']['js_custom_version']))$GLOBALS['sugar_config']['js_custom_version'] = 1;
1963 $js_version_key = isset($GLOBALS['js_version_key'])?$GLOBALS['js_version_key']:'';
1964 $path = $relative_path . '?s=' . $js_version_key . '&c=' . $GLOBALS['sugar_config']['js_custom_version'] ;
1965 if ( inDeveloperMode() ) $path .= '&developerMode='.mt_rand();
1966 if(!empty($additonal_attrs)) $path .= '&' . $additional_attrs;
1970 function getSWFPath($relative_path, $additional_params=''){
1971 $path = $relative_path;
1972 if (!empty($additional_params)){
1973 $path .= '?' . $additional_params;
1975 if (defined('TEMPLATE_URL')){
1976 $path = TEMPLATE_URL . '/' . $path;
1985 function getSQLDate($date_str)
1987 if (preg_match('/^(\d{1,2})-(\d{1,2})-(\d{4})$/',$date_str,$match))
1989 if ( strlen($match[2]) == 1)
1991 $match[2] = "0".$match[2];
1993 if ( strlen($match[1]) == 1)
1995 $match[1] = "0".$match[1];
1997 return "{$match[3]}-{$match[1]}-{$match[2]}";
1999 else if (preg_match('/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/',$date_str,$match))
2001 if ( strlen($match[2]) == 1)
2003 $match[2] = "0".$match[2];
2005 if ( strlen($match[1]) == 1)
2007 $match[1] = "0".$match[1];
2009 return "{$match[3]}-{$match[1]}-{$match[2]}";
2017 function clone_history(&$db, $from_id,$to_id, $to_type)
2022 require_once('include/upload_file.php');
2023 $tables = array('calls'=>'Call', 'meetings'=>'Meeting', 'notes'=>'Note', 'tasks'=>'Task');
2025 $location=array('Email'=>"modules/Emails/Email.php",
2026 'Call'=>"modules/Calls/Call.php",
2027 'Meeting'=>"modules/Meetings/Meeting.php",
2028 'Note'=>"modules/Notes/Note.php",
2029 'Tasks'=>"modules/Tasks/Task.php",
2033 foreach($tables as $table=>$bean_class)
2036 if (!class_exists($bean_class))
2038 require_once($location[$bean_class]);
2041 $bProcessingNotes=false;
2042 if ($table=='notes')
2044 $bProcessingNotes=true;
2046 $query = "SELECT id FROM $table WHERE parent_id='$from_id'";
2047 $results = $db->query($query);
2048 while($row = $db->fetchByAssoc($results))
2050 //retrieve existing record.
2051 $bean= new $bean_class();
2052 $bean->retrieve($row['id']);
2053 //process for new instance.
2054 if ($bProcessingNotes)
2056 $old_note_id=$row['id'];
2057 $old_filename=$bean->filename;
2060 $bean->parent_id=$to_id;
2061 $bean->parent_type=$to_type;
2062 if ($to_type=='Contacts' and in_array('contact_id',$bean->column_fields))
2064 $bean->contact_id=$to_id;
2066 $bean->update_date_modified = false;
2067 $bean->update_modified_by = false;
2068 if(isset($bean->date_modified))
2069 $bean->date_modified = $timedate->to_db($bean->date_modified);
2070 if(isset($bean->date_entered))
2071 $bean->date_entered = $timedate->to_db($bean->date_entered);
2073 $new_id=$bean->save();
2075 //duplicate the file now. for notes.
2076 if ($bProcessingNotes && !empty($old_filename))
2078 UploadFile::duplicate_file($old_note_id,$new_id,$old_filename);
2080 //reset the values needed for attachment duplication.
2087 function values_to_keys($array)
2089 $new_array = array();
2090 if(!is_array($array))
2094 foreach($array as $arr){
2095 $new_array[$arr] = $arr;
2100 function clone_relationship(&$db, $tables = array(), $from_column, $from_id, $to_id)
2102 foreach($tables as $table)
2105 if ($table == 'emails_beans') {
2106 $query = "SELECT * FROM $table WHERE $from_column='$from_id' and bean_module='Leads'";
2108 $query = "SELECT * FROM $table WHERE $from_column='$from_id'";
2110 $results = $db->query($query);
2111 while($row = $db->fetchByAssoc($results))
2113 $query = "INSERT INTO $table ";
2116 $row[$from_column] = $to_id;
2117 $row['id'] = create_guid();
2118 if ($table=='emails_beans') {
2119 $row['bean_module'] =='Contacts';
2122 foreach($row as $name=>$value)
2128 $values .= "'$value'";
2131 $names .= ', '. $name;
2132 $values .= ", '$value'";
2135 $query .= "($names) VALUES ($values)";
2141 function get_unlinked_email_query($type, $bean) {
2142 global $current_user;
2144 $return_array['select']='SELECT emails.id ';
2145 $return_array['from']='FROM emails ';
2146 $return_array['where']="";
2147 $return_array['join'] = " JOIN (select distinct email_id from emails_email_addr_rel eear
2149 join email_addr_bean_rel eabr on eabr.bean_id ='$bean->id' and eabr.bean_module = '$bean->module_dir' and
2150 eabr.email_address_id = eear.email_address_id and eabr.deleted=0
2151 where eear.deleted=0 and eear.email_id not in
2152 (select eb.email_id from emails_beans eb where eb.bean_module ='$bean->module_dir' and eb.bean_id = '$bean->id')
2153 ) derivedemails on derivedemails.email_id = emails.id";
2154 $return_array['join_tables'][0] = '';
2156 if (isset($type) and isset($type['return_as_array']) and $type['return_as_array']==true) {
2157 return $return_array;
2160 return $return_array['select'] . $return_array['from'] . $return_array['where'];
2164 * Check to see if the number is empty or non-zero
2168 function number_empty($value)
2170 return empty($value) && $value != '0';
2173 function get_bean_select_array($add_blank=true, $bean_name, $display_columns, $where='', $order_by='', $blank_is_none=false)
2176 require_once($beanFiles[$bean_name]);
2177 $focus = new $bean_name();
2178 $user_array = array();
2179 $user_array = get_register_value('select_array',$bean_name. $display_columns. $where . $order_by);
2183 $db = DBManagerFactory::getInstance();
2184 $temp_result = Array();
2185 $query = "SELECT id, {$display_columns} as display from {$focus->table_name} where ";
2188 $query .= $where." AND ";
2191 $query .= " deleted=0";
2193 if ( $order_by != '')
2195 $query .= ' order by '.$order_by;
2198 $GLOBALS['log']->debug("get_user_array query: $query");
2199 $result = $db->query($query, true, "Error filling in user array: ");
2201 if ($add_blank==true){
2202 // Add in a blank row
2203 if($blank_is_none == true) { // set 'blank row' to "--None--"
2204 global $app_strings;
2205 $temp_result[''] = $app_strings['LBL_NONE'];
2207 $temp_result[''] = '';
2211 // Get the id and the name.
2212 while($row = $db->fetchByAssoc($result))
2214 $temp_result[$row['id']] = $row['display'];
2217 $user_array = $temp_result;
2218 set_register_value('select_array',$bean_name. $display_columns. $where . $order_by,$temp_result);
2227 * @param unknown_type $listArray
2229 // function parse_list_modules
2230 // searches a list for items in a user's allowed tabs and returns an array that removes unallowed tabs from list
2231 function parse_list_modules(&$listArray)
2233 global $modListHeader;
2234 $returnArray = array();
2236 foreach($listArray as $optionName => $optionVal)
2238 if(array_key_exists($optionName, $modListHeader))
2240 $returnArray[$optionName] = $optionVal;
2243 // special case for projects
2244 if(array_key_exists('Project', $modListHeader))
2246 $returnArray['ProjectTask'] = $listArray['ProjectTask'];
2249 $acldenied = ACLController::disabledModuleList($listArray,false);
2250 foreach($acldenied as $denied){
2251 unset($returnArray[$denied]);
2253 asort($returnArray);
2255 return $returnArray;
2258 function display_notice($msg = false){
2259 global $error_notice;
2260 //no error notice - lets just display the error to the user
2261 if(!isset($error_notice)){
2262 echo '<br>'.$msg . '<br>';
2264 $error_notice .= $msg . '<br>';
2268 /* checks if it is a number that atleast has the plus at the beggining
2270 function skype_formatted($number){
2271 //kbrill - BUG #15375
2272 if(isset($_REQUEST['action']) && $_REQUEST['action']=="Popup") {
2275 return substr($number, 0, 1) == '+' || substr($number, 0, 2) == '00' || substr($number, 0, 3) == '011';
2277 // return substr($number, 0, 1) == '+' || substr($number, 0, 2) == '00' || substr($number, 0, 2) == '011';
2280 function format_skype($number) {
2281 return preg_replace('/[^\+0-9]/','',$number);
2284 function insert_charset_header() {
2285 header('Content-Type: text/html; charset=UTF-8');
2288 function getCurrentURL()
2291 if(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on')
2296 $href.= "//".$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME'].'?'.$_SERVER['QUERY_STRING'];
2300 function javascript_escape($str) {
2303 for($i = 0; $i < strlen($str); $i++) {
2305 if(ord(substr($str, $i, 1))==10){
2307 }elseif(ord(substr($str, $i, 1))==13){
2311 $new_str .= $str{$i};
2315 $new_str = str_replace("'", "\\'", $new_str);
2320 function js_escape($str, $keep=true){
2321 $str = html_entity_decode(str_replace("\\", "", $str), ENT_QUOTES);
2324 $str = javascript_escape($str);
2327 $str = str_replace("'", " ", $str);
2328 $str = str_replace('"', " ", $str);
2333 //end function js_escape
2336 function br2nl($str) {
2337 $regex = "#<[^>]+br.+?>#";
2338 preg_match_all($regex, $str, $matches);
2340 foreach($matches[0] as $match) {
2341 $str = str_replace($match, "<br>", $str);
2344 $brs = array('<br>','<br/>', '<br />');
2345 $str = str_replace("\r\n", "\n", $str); // make from windows-returns, *nix-returns
2346 $str = str_replace("\n\r", "\n", $str); // make from windows-returns, *nix-returns
2347 $str = str_replace("\r", "\n", $str); // make from windows-returns, *nix-returns
2348 $str = str_replace($brs, "\n", $str); // to retrieve it
2354 * Private helper function for displaying the contents of a given variable.
2355 * This function is only intended to be used for SugarCRM internal development.
2356 * The ppd stands for Pre Print Die.
2358 function _ppd($mixed)
2364 * Private helper function for displaying the contents of a given variable in
2365 * the Logger. This function is only intended to be used for SugarCRM internal
2366 * development. The pp stands for Pre Print.
2367 * @param $mixed var to print_r()
2368 * @param $die boolean end script flow
2369 * @param $displayStackTrace also show stack trace
2371 function _ppl($mixed, $die=false, $displayStackTrace=false, $loglevel="fatal") {
2375 * private helper function to quickly show the major, direct, field attributes of a given bean.
2376 * The ppf stands for Pre[formatted] Print Focus [object]
2377 * @param object bean The focus bean
2379 function _ppf($bean, $die=false) {
2385 * Private helper function for displaying the contents of a given variable.
2386 * This function is only intended to be used for SugarCRM internal development.
2387 * The pp stands for Pre Print.
2389 function _pp($mixed)
2394 * Private helper function for displaying the contents of a given variable.
2395 * This function is only intended to be used for SugarCRM internal development.
2396 * The pp stands for Pre Print.
2398 function _pstack_trace($mixed=NULL)
2403 * Private helper function for displaying the contents of a given variable.
2404 * This function is only intended to be used for SugarCRM internal development.
2405 * The pp stands for Pre Print Trace.
2407 function _ppt($mixed, $textOnly=false)
2412 * Private helper function for displaying the contents of a given variable.
2413 * This function is only intended to be used for SugarCRM internal development.
2414 * The pp stands for Pre Print Trace Die.
2416 function _pptd($mixed)
2421 * Private helper function for decoding javascript UTF8
2422 * This function is only intended to be used for SugarCRM internal development.
2424 function decodeJavascriptUTF8($str) {
2428 * Will check if a given PHP version string is supported (tested on this ver),
2429 * unsupported (results unknown), or invalid (something will break on this
2430 * ver). Do not pass in any pararameter to default to a check against the
2431 * current environment's PHP version.
2433 * @return 1 implies supported, 0 implies unsupported, -1 implies invalid
2435 function check_php_version($sys_php_version = '') {
2436 $sys_php_version = empty($sys_php_version) ? constant('PHP_VERSION') : $sys_php_version;
2437 // versions below $min_considered_php_version considered invalid by default,
2438 // versions equal to or above this ver will be considered depending
2439 // on the rules that follow
2440 $min_considered_php_version = '5.2.1';
2442 // only the supported versions,
2443 // should be mutually exclusive with $invalid_php_versions
2444 $supported_php_versions = array (
2445 '5.2.1', '5.2.2', '5.2.3', '5.2.4', '5.2.5', '5.2.6', '5.2.8', '5.3.0'
2447 //Find out what Database the system is using.
2448 global $sugar_config;
2450 if (isset($_REQUEST['setup_db_type'])) {
2451 $dbType = $_REQUEST['setup_db_type'];
2452 } else if (isset ($sugar_config['dbconfig']) && isset ($sugar_config['dbconfig']['db_type'])) {
2453 $dbType = $sugar_config['dbconfig']['db_type'];
2456 // invalid versions above the $min_considered_php_version,
2457 // should be mutually exclusive with $supported_php_versions
2459 // SugarCRM prohibits install on PHP 5.2.7 on all platforms
2460 $invalid_php_versions = array('5.2.7');
2462 // default unsupported
2465 // versions below $min_considered_php_version are invalid
2466 if(1 == version_compare($sys_php_version, $min_considered_php_version, '<')) {
2470 // supported version check overrides default unsupported
2471 foreach($supported_php_versions as $ver) {
2472 if(1 == version_compare($sys_php_version, $ver, 'eq') || strpos($sys_php_version,$ver) !== false) {
2478 // invalid version check overrides default unsupported
2479 foreach($invalid_php_versions as $ver) {
2480 if(1 == version_compare($sys_php_version, $ver, 'eq') && strpos($sys_php_version,$ver) !== false) {
2486 //allow a redhat distro to install, regardless of version. We are assuming the redhat naming convention is followed
2487 //and the php version contains 'rh' characters
2488 if(strpos($sys_php_version, 'rh') !== false) {
2496 * Will check if a given IIS version string is supported (tested on this ver),
2497 * unsupported (results unknown), or invalid (something will break on this
2500 * @return 1 implies supported, 0 implies unsupported, -1 implies invalid
2502 function check_iis_version($sys_iis_version = '') {
2504 $server_software = $_SERVER["SERVER_SOFTWARE"];
2506 if(strpos($server_software,'Microsoft-IIS') !== false && preg_match_all("/^.*\/(\d+\.?\d*)$/", $server_software, $out))
2507 $iis_version = $out[1][0];
2509 $sys_iis_version = empty($sys_iis_version) ? $iis_version : $sys_iis_version;
2511 // versions below $min_considered_iis_version considered invalid by default,
2512 // versions equal to or above this ver will be considered depending
2513 // on the rules that follow
2514 $min_considered_iis_version = '6.0';
2516 // only the supported versions,
2517 // should be mutually exclusive with $invalid_iis_versions
2518 $supported_iis_versions = array ('6.0', '7.0',);
2519 $unsupported_iis_versions = array();
2520 $invalid_iis_versions = array('5.0',);
2522 // default unsupported
2525 // versions below $min_considered_iis_version are invalid
2526 if(1 == version_compare($sys_iis_version, $min_considered_iis_version, '<')) {
2530 // supported version check overrides default unsupported
2531 foreach($supported_iis_versions as $ver) {
2532 if(1 == version_compare($sys_iis_version, $ver, 'eq') || strpos($sys_iis_version,$ver) !== false) {
2538 // unsupported version check overrides default unsupported
2539 foreach($unsupported_iis_versions as $ver) {
2540 if(1 == version_compare($sys_iis_version, $ver, 'eq') && strpos($sys_iis_version,$ver) !== false) {
2546 // invalid version check overrides default unsupported
2547 foreach($invalid_iis_versions as $ver) {
2548 if(1 == version_compare($sys_iis_version, $ver, 'eq') && strpos($sys_iis_version,$ver) !== false) {
2557 function pre_login_check(){
2558 global $action, $login_error;
2559 if(!empty($action)&& $action == 'Login'){
2561 if(!empty($login_error)){
2562 $login_error = htmlentities($login_error);
2563 $login_error = str_replace(array("<pre>","</pre>","\r\n", "\n"), "<br>", $login_error);
2564 $_SESSION['login_error'] = $login_error;
2566 function set_focus() {}
2567 if(document.getElementById("post_error")) {
2568 document.getElementById("post_error").innerHTML="'. $login_error. '";
2569 document.getElementById("cant_login").value=1;
2570 document.getElementById("login_button").disabled = true;
2571 document.getElementById("user_name").disabled = true;
2572 //document.getElementById("user_password").disabled = true;
2581 function sugar_cleanup($exit = false) {
2582 static $called = false;
2585 set_include_path(realpath(dirname(__FILE__) . '/..') . PATH_SEPARATOR . get_include_path());
2586 chdir(realpath(dirname(__FILE__) . '/..'));
2587 global $sugar_config;
2588 LogicHook::initialize();
2589 $GLOBALS['logic_hook']->call_custom_logic('', 'server_round_trip');
2591 //added this check to avoid errors during install.
2592 if (empty($sugar_config['dbconfig'])) {
2593 if ($exit) exit; else return;
2596 if (!class_exists('Tracker', true)) {
2597 require_once 'modules/Trackers/Tracker.php';
2600 // Now write the cached tracker_queries
2601 if(!empty($GLOBALS['savePreferencesToDB']) && $GLOBALS['savePreferencesToDB']) {
2602 if ( isset($GLOBALS['current_user']) && $GLOBALS['current_user'] instanceOf User )
2603 $GLOBALS['current_user']->savePreferencesToDB();
2606 //check to see if this is not an ajax call AND the user preference error flag is set
2608 (isset($_SESSION['USER_PREFRENCE_ERRORS']) && $_SESSION['USER_PREFRENCE_ERRORS'])
2609 && ($_REQUEST['action']!='modulelistmenu' && $_REQUEST['action']!='DynamicAction')
2610 && (empty($_REQUEST['to_pdf']) || !$_REQUEST['to_pdf'] )
2611 && (empty($_REQUEST['sugar_body_only']) || !$_REQUEST['sugar_body_only'] )
2614 global $app_strings;
2615 //this is not an ajax call and the user preference error flag is set, so reset the flag and print js to flash message
2616 $err_mess = $app_strings['ERROR_USER_PREFS'];
2617 $_SESSION['USER_PREFRENCE_ERRORS'] = false;
2620 ajaxStatus.flashStatus('$err_mess',7000);
2626 if(class_exists('DBManagerFactory')) {
2627 $db = DBManagerFactory::getInstance();
2635 register_shutdown_function('sugar_cleanup');
2639 check_logic_hook - checks to see if your custom logic is in the logic file
2640 if not, it will add it. If the file isn't built yet, it will create the file
2643 function check_logic_hook_file($module_name, $event, $action_array){
2644 require_once('include/utils/logic_utils.php');
2647 if(file_exists("custom/modules/$module_name/logic_hooks.php")){
2649 $hook_array = get_hook_array($module_name);
2651 if(check_existing_element($hook_array, $event, $action_array)==true){
2652 //the hook at hand is present, so do nothing
2656 $logic_count = count($hook_array[$event]);
2657 if($action_array[0]==""){
2658 $action_array[0] = $logic_count + 1;
2660 $hook_array[$event][] = $action_array;
2663 //end if the file exists already
2666 if($action_array[0]==""){
2667 $action_array[0] = 1;
2669 $hook_array = array();
2670 $hook_array[$event][] = $action_array;
2671 //end if else file exists already
2673 if($add_logic == true){
2675 //reorder array by element[0]
2676 //$hook_array = reorder_array($hook_array, $event);
2677 //!!!Finish this above TODO
2679 $new_contents = replace_or_add_logic_type($hook_array);
2680 write_logic_file($module_name, $new_contents);
2682 //end if add_element is true
2685 //end function check_logic_hook_file
2688 function remove_logic_hook($module_name, $event, $action_array) {
2689 require_once('include/utils/logic_utils.php');
2692 if(file_exists("custom/modules/".$module_name."/logic_hooks.php")){
2693 // The file exists, let's make sure the hook is there
2694 $hook_array = get_hook_array($module_name);
2696 if(check_existing_element($hook_array, $event, $action_array)==true){
2697 // The hook is there, time to take it out.
2699 foreach ( $hook_array[$event] as $i => $hook ) {
2700 // We don't do a full comparison below just in case the filename changes
2701 if ( $hook[0] == $action_array[0]
2702 && $hook[1] == $action_array[1]
2703 && $hook[3] == $action_array[3]
2704 && $hook[4] == $action_array[4] ) {
2705 unset($hook_array[$event][$i]);
2709 $new_contents = replace_or_add_logic_type($hook_array);
2710 write_logic_file($module_name, $new_contents);
2716 function display_stack_trace($textOnly=false){
2718 $stack = debug_backtrace();
2720 echo "\n\n display_stack_trace caller, file: " . $stack[0]['file']. ' line#: ' .$stack[0]['line'];
2728 foreach($stack as $item) {
2734 if(isset($item['file']))
2735 $file = $item['file'];
2736 if(isset($item['class']))
2737 $class = $item['class'];
2738 if(isset($item['line']))
2739 $line = $item['line'];
2740 if(isset($item['function']))
2741 $function = $item['function'];
2745 $out .= '<font color="black"><b>';
2751 $out .= '</b></font><font color="blue">';
2754 $out .= "[L:{$line}]";
2757 $out .= '</font><font color="red">';
2760 $out .= "({$class}:{$function})";
2763 $out .= '</font><br>';
2775 function StackTraceErrorHandler($errno, $errstr, $errfile,$errline, $errcontext) {
2776 $error_msg = " $errstr occured in <b>$errfile</b> on line $errline [" . date("Y-m-d H:i:s") . ']';
2777 $halt_script = true;
2779 case 2048: return; //depricated we have lots of these ignore them
2782 if ( error_reporting() & E_NOTICE ) {
2783 $halt_script = false;
2789 case E_USER_WARNING:
2790 case E_COMPILE_WARNING:
2791 case E_CORE_WARNING:
2794 $halt_script = false;
2799 case E_COMPILE_ERROR:
2803 $type = "Fatal Error";
2808 $type = "Parse Error";
2812 //don't know what it is might not be so bad
2813 $halt_script = false;
2814 $type = "Unknown Error ($errno)";
2817 $error_msg = '<b>'.$type.'</b>:' . $error_msg;
2819 display_stack_trace();
2829 if(isset($sugar_config['stack_trace_errors']) && $sugar_config['stack_trace_errors']){
2831 set_error_handler('StackTraceErrorHandler');
2833 function get_sub_cookies($name){
2835 if(isset($_COOKIE[$name])){
2836 $subs = explode('#', $_COOKIE[$name]);
2837 foreach($subs as $cookie){
2838 if(!empty($cookie)){
2839 $cookie = explode('=', $cookie);
2841 $cookies[$cookie[0]] = $cookie[1];
2850 function mark_delete_components($sub_object_array, $run_second_level=false, $sub_sub_array=""){
2852 if(!empty($sub_object_array)){
2854 foreach($sub_object_array as $sub_object){
2856 //run_second level is set to true if you need to remove sub-sub components
2857 if($run_second_level==true){
2859 mark_delete_components($sub_object->get_linked_beans($sub_sub_array['rel_field'],$sub_sub_array['rel_module']));
2861 //end if run_second_level is true
2863 $sub_object->mark_deleted($sub_object->id);
2864 //end foreach sub component
2866 //end if this is not empty
2869 //end function mark_delete_components
2873 * For translating the php.ini memory values into bytes. e.g. input value of '8M' will return 8388608.
2875 function return_bytes($val)
2878 $last = strtolower($val{strlen($val)-1});
2882 // The 'G' modifier is available since PHP 5.1.0
2895 * Adds the href HTML tags around any URL in the $string
2897 function url2html($string) {
2899 $return_string = preg_replace('/(\w+:\/\/)(\S+)/', ' <a href="\\1\\2" target="_new" style="font-weight: normal;">\\1\\2</a>', $string);
2900 return $return_string;
2902 // End customization by Julian
2905 * tries to determine whether the Host machine is a Windows machine
2907 function is_windows() {
2908 static $is_windows = null;
2909 if (!isset($is_windows)) {
2910 $is_windows = strtoupper(substr(PHP_OS, 0, 3)) == 'WIN';
2916 * equivalent for windows filesystem for PHP's is_writable()
2917 * @param string file Full path to the file/dir
2918 * @return bool true if writable
2920 function is_writable_windows($file) {
2921 if($file{strlen($file)-1}=='/') {
2922 return is_writable_windows($file.uniqid(mt_rand()).'.tmp');
2925 // the assumption here is that Windows has an inherited permissions scheme
2926 // any file that is a descendant of an unwritable directory will inherit
2927 // that property and will trigger a failure below.
2932 $file = str_replace("/", '\\', $file);
2934 if(file_exists($file)) {
2935 if (!($f = @sugar_fopen($file, 'r+')))
2941 if(!($f = @sugar_fopen($file, 'w')))
2950 * best guesses Timezone based on webserver's TZ settings
2952 function lookupTimezone($userOffset = 0){
2953 require_once('include/timezone/timezones.php');
2955 $defaultZones= array('America/New_York'=>1, 'America/Los_Angeles'=>1,'America/Chicago'=>1, 'America/Denver'=>1,'America/Anchorage'=>1, 'America/Phoenix'=>1, 'Europe/Amsterdam'=>1,'Europe/Athens'=>1,'Europe/London'=>1, 'Australia/Sydney'=>1, 'Australia/Perth'=>1);
2957 $serverOffset = date('Z');
2959 $serverOffset -= 3600;
2961 if(!is_int($userOffset)) {
2964 $gmtOffset = $serverOffset/60 + $userOffset * 60;
2965 $selectedZone = ' ';
2966 foreach($timezones as $zoneName=>$zone) {
2968 if($zone['gmtOffset'] == $gmtOffset) {
2969 $selectedZone = $zoneName;
2971 if(!empty($defaultZones[$selectedZone]) ) {
2972 return $selectedZone;
2975 return $selectedZone;
2978 function convert_module_to_singular($module_array){
2981 foreach($module_array as $key => $value){
2982 if(!empty($beanList[$value])) $module_array[$key] = $beanList[$value];
2984 if($value=="Cases") {
2985 $module_array[$key] = "Case";
2987 if($key=="projecttask"){
2988 $module_array['ProjectTask'] = "Project Task";
2989 unset($module_array[$key]);
2993 return $module_array;
2995 //end function convert_module_to_singular
2999 * Given the bean_name which may be plural or singular return the singular
3000 * bean_name. This is important when you need to include files.
3002 function get_singular_bean_name($bean_name){
3003 global $beanFiles, $beanList;
3004 if(array_key_exists($bean_name, $beanList)){
3005 return $beanList[$bean_name];
3012 function get_label($label_tag, $temp_module_strings){
3013 global $app_strings;
3014 if(!empty($temp_module_strings[$label_tag])){
3016 $label_name = $temp_module_strings[$label_tag];
3018 if(!empty($app_strings[$label_tag])){
3019 $label_name = $app_strings[$label_tag];
3021 $label_name = $label_tag;
3026 //end function get_label
3030 function search_filter_rel_info(& $focus, $tar_rel_module, $relationship_name){
3032 $rel_list = array();
3034 foreach($focus->relationship_fields as $rel_key => $rel_value){
3035 if($rel_value == $relationship_name){
3036 $temp_bean = get_module_info($tar_rel_module);
3037 // echo $focus->$rel_key;
3038 $temp_bean->retrieve($focus->$rel_key);
3039 if($temp_bean->id!=""){
3041 $rel_list[] = $temp_bean;
3047 foreach($focus->field_defs as $field_name => $field_def){
3048 //Check if the relationship_name matches a "relate" field
3049 if(!empty($field_def['type']) && $field_def['type'] == 'relate'
3050 && !empty($field_def['id_name']) && !empty($focus->field_defs[$field_def['id_name']])
3051 && !empty($focus->field_defs[$field_def['id_name']]['relationship'])
3052 && $focus->field_defs[$field_def['id_name']]['relationship'] == $relationship_name)
3054 $temp_bean = get_module_info($tar_rel_module);
3055 // echo $focus->$field_def['id_name'];
3056 $temp_bean->retrieve($focus->$field_def['id_name']);
3057 if($temp_bean->id!=""){
3059 $rel_list[] = $temp_bean;
3062 //Check if the relationship_name matches a "link" in a relate field
3063 } else if(!empty($rel_value['link']) && !empty($rel_value['id_name']) && $rel_value['link'] == $relationship_name){
3064 $temp_bean = get_module_info($tar_rel_module);
3065 // echo $focus->$rel_value['id_name'];
3066 $temp_bean->retrieve($focus->$rel_value['id_name']);
3067 if($temp_bean->id!=""){
3069 $rel_list[] = $temp_bean;
3075 // special case for unlisted parent-type relationships
3076 if($focus->parent_type == $tar_rel_module && !empty($focus->parent_id)) {
3077 $temp_bean = get_module_info($tar_rel_module);
3078 $temp_bean->retrieve($focus->parent_id);
3079 if($temp_bean->id!=""){
3080 $rel_list[] = $temp_bean;
3087 //end function search_filter_rel_info
3090 function get_module_info($module_name){
3094 //Get dictionary and focus data for module
3095 $vardef_name = $beanList[$module_name];
3097 if($vardef_name=="aCase"){
3098 $class_name = "Case";
3100 $class_name = $vardef_name;
3103 if(!file_exists('modules/'. $module_name . '/'.$class_name.'.php')){
3107 include_once('modules/'. $module_name . '/'.$class_name.'.php');
3109 $module_bean = new $vardef_name();
3110 return $module_bean;
3111 //end function get_module_table
3115 * In order to have one place to obtain the proper object name. aCase for example causes issues throughout the application.
3117 * @param string $moduleName
3119 function get_valid_bean_name($module_name){
3122 $vardef_name = $beanList[$module_name];
3123 if($vardef_name=="aCase"){
3124 $bean_name = "Case";
3126 $bean_name = $vardef_name;
3133 function checkAuthUserStatus(){
3140 * This function returns an array of phpinfo() results that can be parsed and
3141 * used to figure out what version we run, what modules are compiled in, etc.
3142 * @param $level int info level constant (1,2,4,8...64);
3143 * @return $returnInfo array array of info about the PHP environment
3144 * @author original by "code at adspeed dot com" Fron php.net
3145 * @author customized for Sugar by Chris N.
3147 function getPhpInfo($level=-1) {
3148 /** Name (constant) Value Description
3149 INFO_GENERAL 1 The configuration line, php.ini location, build date, Web Server, System and more.
3150 INFO_CREDITS 2 PHP Credits. See also phpcredits().
3151 INFO_CONFIGURATION 4 Current Local and Master values for PHP directives. See also ini_get().
3152 INFO_MODULES 8 Loaded modules and their respective settings. See also get_loaded_extensions().
3153 INFO_ENVIRONMENT 16 Environment Variable information that's also available in $_ENV.
3154 INFO_VARIABLES 32 Shows all predefined variables from EGPCS (Environment, GET, POST, Cookie, Server).
3155 INFO_LICENSE 64 PHP License information. See also the license FAQ.
3156 INFO_ALL -1 Shows all of the above. This is the default value.
3160 $phpinfo = ob_get_contents();
3163 $phpinfo = strip_tags($phpinfo,'<h1><h2><th><td>');
3164 $phpinfo = preg_replace('/<th[^>]*>([^<]+)<\/th>/',"<info>\\1</info>",$phpinfo);
3165 $phpinfo = preg_replace('/<td[^>]*>([^<]+)<\/td>/',"<info>\\1</info>",$phpinfo);
3166 $parsedInfo = preg_split('/(<h.?>[^<]+<\/h.>)/', $phpinfo, -1, PREG_SPLIT_DELIM_CAPTURE);
3169 $returnInfo = array();
3171 if(preg_match('/<h1 class\=\"p\">PHP Version ([^<]+)<\/h1>/', $phpinfo, $version)) {
3172 $returnInfo['PHP Version'] = $version[1];
3176 for ($i=1; $i<count($parsedInfo); $i++) {
3177 if (preg_match('/<h.>([^<]+)<\/h.>/', $parsedInfo[$i], $match)) {
3178 $vName = trim($match[1]);
3179 $parsedInfo2 = explode("\n",$parsedInfo[$i+1]);
3181 foreach ($parsedInfo2 AS $vOne) {
3182 $vPat = '<info>([^<]+)<\/info>';
3183 $vPat3 = "/$vPat\s*$vPat\s*$vPat/";
3184 $vPat2 = "/$vPat\s*$vPat/";
3186 if (preg_match($vPat3,$vOne,$match)) { // 3cols
3187 $returnInfo[$vName][trim($match[1])] = array(trim($match[2]),trim($match[3]));
3188 } elseif (preg_match($vPat2,$vOne,$match)) { // 2cols
3189 $returnInfo[$vName][trim($match[1])] = trim($match[2]);
3201 * This function will take a string that has tokens like {0}, {1} and will replace
3202 * those tokens with the args provided
3203 * @param $format string to format
3204 * @param $args args to replace
3205 * @return $result a formatted string
3207 function string_format($format, $args){
3209 for($i = 0; $i < count($args); $i++){
3210 $result = str_replace('{'.$i.'}', $args[$i], $result);
3216 * Generate a string for displaying a unique identifier that is composed
3217 * of a system_id and number. This is use to allow us to generate quote
3218 * numbers using a DB auto-increment key from offline clients and still
3219 * have the number be unique (since it is modified by the system_id.
3221 * @param $num of bean
3222 * @param $system_id from system
3223 * @return $result a formatted string
3225 function format_number_display($num, $system_id){
3226 global $sugar_config;
3227 if(isset($num) && !empty($num)){
3228 $num=unformat_number($num);
3229 if(isset($system_id) && $system_id == 1){
3230 return sprintf("%d", $num);
3233 return sprintf("%d-%d", $num, $system_id);
3237 function checkLoginUserStatus(){
3241 * This function will take a number and system_id and format
3242 * @param $url URL containing host to append port
3243 * @param $port the port number - if '' is passed, no change to url
3244 * @return $resulturl the new URL with the port appended to the host
3246 function appendPortToHost($url, $port)
3250 // if no port, don't change the url
3253 $split = explode("/", $url);
3254 //check if it starts with http, in case they didn't include that in url
3255 if(str_begin($url, 'http'))
3257 //third index ($split[2]) will be the host
3258 $split[2] .= ":".$port;
3260 else // otherwise assumed to start with host name
3262 //first index ($split[0]) will be the host
3263 $split[0] .= ":".$port;
3266 $resulturl = implode("/", $split);
3273 * Singleton to return JSON object
3274 * @return JSON object
3276 function getJSONobj() {
3277 static $json = null;
3279 require_once('include/JSON.php');
3280 $json = new JSON(JSON_LOOSE_TYPE);
3285 require_once('include/utils/db_utils.php');
3286 //check to see if custom utils exists
3287 if(file_exists('custom/include/custom_utils.php')){
3288 include_once('custom/include/custom_utils.php');
3293 * Set default php.ini settings for entry points
3295 function setPhpIniSettings() {
3297 // Bug 37579 - Comment out force enabling zlib.output_compression, since it can cause problems on certain hosts
3299 if(function_exists('gzclose') && headers_sent() == false) {
3300 ini_set('zlib.output_compression', 1);
3304 //nsingh: breaks zip/unzip functionality. Commenting out 4/23/08
3306 /*if(function_exists('mb_strlen')) {
3307 ini_set('mbstring.func_overload', 7);
3308 ini_set('mbstring.internal_encoding', 'UTF-8');
3312 // http://us3.php.net/manual/en/ref.pcre.php#ini.pcre.backtrack-limit
3313 // starting with 5.2.0, backtrack_limit breaks JSON decoding
3314 $backtrack_limit = ini_get('pcre.backtrack_limit');
3315 if(!empty($backtrack_limit)) {
3316 ini_set('pcre.backtrack_limit', '-1');
3320 if(ini_get("mssql.charset")) {
3321 ini_set('mssql.charset', "UTF-8");
3326 * like array_merge() but will handle array elements that are themselves arrays;
3327 * PHP's version just overwrites the element with the new one.
3329 * @internal Note that this function deviates from the internal array_merge()
3330 * functions in that it does does not treat numeric keys differently
3331 * than string keys. Additionally, it deviates from
3332 * array_merge_recursive() by not creating an array when like values
3335 * @param array gimp the array whose values will be overloaded
3336 * @param array dom the array whose values will pwn the gimp's
3337 * @return array beaten gimp
3339 function sugarArrayMerge($gimp, $dom) {
3340 if(is_array($gimp) && is_array($dom)) {
3341 foreach($dom as $domKey => $domVal) {
3342 if(array_key_exists($domKey, $gimp)) {
3343 if(is_array($domVal)) {
3345 foreach ( $domVal as $domArrKey => $domArrVal )
3346 $tempArr[$domArrKey] = $domArrVal;
3347 foreach ( $gimp[$domKey] as $gimpArrKey => $gimpArrVal )
3348 if ( !array_key_exists($gimpArrKey, $tempArr) )
3349 $tempArr[$gimpArrKey] = $gimpArrVal;
3350 $gimp[$domKey] = $tempArr;
3352 $gimp[$domKey] = $domVal;
3355 $gimp[$domKey] = $domVal;
3359 // if the passed value for gimp isn't an array, then return the $dom
3360 elseif(is_array($dom))
3367 * Similiar to sugarArrayMerge except arrays of N depth are merged.
3369 * @param array gimp the array whose values will be overloaded
3370 * @param array dom the array whose values will pwn the gimp's
3371 * @return array beaten gimp
3373 function sugarArrayMergeRecursive($gimp, $dom) {
3374 if(is_array($gimp) && is_array($dom)) {
3375 foreach($dom as $domKey => $domVal) {
3376 if(array_key_exists($domKey, $gimp)) {
3377 if(is_array($domVal) && is_array($gimp[$domKey])) {
3378 $gimp[$domKey] = sugarArrayMergeRecursive($gimp[$domKey], $domVal);
3380 $gimp[$domKey] = $domVal;
3383 $gimp[$domKey] = $domVal;
3387 // if the passed value for gimp isn't an array, then return the $dom
3388 elseif(is_array($dom))
3395 * finds the correctly working versions of PHP-JSON
3396 * @return bool True if NOT found or WRONG version
3398 function returnPhpJsonStatus() {
3399 $goodVersions = array('1.1.1',);
3401 if(function_exists('json_encode')) {
3402 $phpInfo = getPhpInfo(8);
3404 if(!in_array($phpInfo['json']['json version'], $goodVersions)) {
3405 return true; // bad version found
3407 return false; // all requirements met
3410 return true; // not found
3415 * getTrackerSubstring
3417 * Returns a [number]-char or less string for the Tracker to display in the header
3418 * based on the tracker_max_display_length setting in config.php. If not set,
3419 * or invalid length, then defaults to 15 for COM editions, 30 for others.
3421 * @param string name field for a given Object
3422 * @return string [number]-char formatted string if length of string exceeds the max allowed
3424 function getTrackerSubstring($name) {
3425 static $max_tracker_item_length;
3428 $strlen = function_exists('mb_strlen') ? mb_strlen($name) : strlen($name);
3430 global $sugar_config;
3432 if(!isset($max_tracker_item_length)) {
3433 if(isset($sugar_config['tracker_max_display_length'])) {
3434 $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;
3436 $max_tracker_item_length = 15;
3440 if($strlen > $max_tracker_item_length) {
3441 $chopped = function_exists('mb_substr') ? mb_substr($name, 0, $max_tracker_item_length, "UTF-8") : substr($name, 0, $max_tracker_item_length, "UTF-8");
3448 function generate_search_where ($field_list=array(),$values=array(),&$bean,$add_custom_fields=false,$module='') {
3449 $where_clauses= array();
3451 $table_name=$bean->object_name;
3452 foreach ($field_list[$module] as $field=>$parms) {
3453 if(isset($values[$field]) && $values[$field] != "") {
3455 if (!empty($parms['operator'])) {
3456 $operator=$parms['operator'];
3458 if (is_array($values[$field])) {
3461 foreach ($values[$field] as $key => $val) {
3462 if ($val != ' ' and $val != '') {
3463 if (!empty($field_value)) {
3466 $field_value .= "'".$GLOBALS['db']->quote($val)."'";
3470 $field_value=$GLOBALS['db']->quote($values[$field]);
3472 //set db_fields array.
3473 if (!isset($parms['db_field']) ) {
3474 $parms['db_field'] = array($field);
3476 if (isset($parms['my_items']) and $parms['my_items'] == true) {
3477 global $current_user;
3478 $field_value = $GLOBALS['db']->quote($current_user->id);
3484 if ($field_value != '') {
3486 foreach ($parms['db_field'] as $db_field) {
3487 if (strstr($db_field,'.')===false) {
3488 $db_field=$bean->table_name.".".$db_field;
3490 if ($GLOBALS['db']->dbType=='oci8' && isset($parms['query_type']) && $parms['query_type']=='case_insensitive') {
3491 $db_field='upper('.$db_field.")";
3492 $field_value=strtoupper($field_value);
3496 if (!empty($where)) {
3499 switch (strtolower($operator)) {
3501 $where .= $db_field . " like '".$field_value.$like_char."'";
3504 $where .= $db_field . " in (".$field_value.')';
3507 $where .= $db_field . " = '".$field_value ."'";
3512 if (!empty($where)) {
3514 array_push($where_clauses, '( '.$where.' )');
3516 array_push($where_clauses, $where);
3521 if ($add_custom_fields) {
3522 require_once('modules/DynamicFields/DynamicField.php');
3523 $bean->setupCustomFields($module);
3524 $bean->custom_fields->setWhereClauses($where_clauses);
3526 return $where_clauses;
3529 function add_quotes($str) {
3534 * This function will rebuild the config file
3535 * @param $sugar_config
3536 * @param $sugar_version
3537 * @return bool true if successful
3539 function rebuildConfigFile($sugar_config, $sugar_version) {
3540 // add defaults to missing values of in-memory sugar_config
3541 $sugar_config = sugarArrayMerge(get_sugar_config_defaults(), $sugar_config );
3542 // need to override version with default no matter what
3543 $sugar_config['sugar_version'] = $sugar_version;
3545 ksort( $sugar_config );
3547 if( write_array_to_file( "sugar_config", $sugar_config, "config.php" ) ){
3556 * getJavascriptSiteURL
3557 * This function returns a URL for the client javascript calls to access
3558 * the site. It uses $_SERVER['HTTP_REFERER'] in the event that Proxy servers
3559 * are used to access the site. Thus, the hostname in the URL returned may
3560 * not always match that of $sugar_config['site_url']. Basically, the
3561 * assumption is that however the user accessed the website is how they
3562 * will continue to with subsequent javascript requests. If the variable
3563 * $_SERVER['HTTP_REFERER'] is not found then we default to old algorithm.
3564 * @return $site_url The url used to refer to the website
3566 function getJavascriptSiteURL() {
3567 global $sugar_config;
3568 if(!empty($_SERVER['HTTP_REFERER'])) {
3569 $url = parse_url($_SERVER['HTTP_REFERER']);
3570 $replacement_url = $url['scheme']."://".$url['host'];
3571 if(!empty($url['port']))
3572 $replacement_url .= ':'.$url['port'];
3573 $site_url = preg_replace('/^http[s]?\:\/\/[^\/]+/',$replacement_url,$sugar_config['site_url']);
3575 $site_url = preg_replace('/^http(s)?\:\/\/[^\/]+/',"http$1://".$_SERVER['HTTP_HOST'],$sugar_config['site_url']);
3576 if(!empty($_SERVER['SERVER_PORT']) &&$_SERVER['SERVER_PORT'] == '443') {
3577 $site_url = preg_replace('/^http\:/','https:',$site_url);
3580 $GLOBALS['log']->debug("getJavascriptSiteURL(), site_url=". $site_url);
3584 // works nicely with array_map() -- can be used to wrap single quotes around each element in an array
3585 function add_squotes($str) {
3586 return "'" . $str . "'";
3590 // recursive function to count the number of levels within an array
3591 function array_depth($array, $depth_count=-1, $depth_array=array()){
3593 if (is_array($array)){
3594 foreach ($array as $key => $value){
3595 $depth_array[] = array_depth($value, $depth_count);
3599 return $depth_count;
3601 foreach ($depth_array as $value){
3602 $depth_count = $value > $depth_count ? $value : $depth_count;
3604 return $depth_count;
3608 * Creates a new Group User
3609 * @param string $name Name of Group User
3610 * @return string GUID of new Group User
3612 function createGroupUser($name) {
3615 $group = new User();
3616 $group->user_name = $name;
3617 $group->last_name = $name;
3618 $group->is_group = 1;
3619 $group->deleted = 0;
3620 $group->status = 'Active'; // cn: bug 6711
3621 $timezone = lookupTimezone();
3622 $group->setPreference('timezone', $timezone);
3629 * Helper function to locate an icon file given only a name
3630 * Searches through the various paths for the file
3631 * @param string iconFileName The filename of the icon
3632 * @return string Relative pathname of the located icon, or '' if not found
3635 function _getIcon($iconFileName)
3637 $iconPath = SugarThemeRegistry::current()->getImageURL("icon_{$iconFileName}.gif");
3638 //First try un-ucfirst-ing the icon name
3639 if ( empty($iconPath) )
3640 $iconPath = SugarThemeRegistry::current()->getImageURL(
3641 "icon_" . strtolower(substr($iconFileName,0,1)).substr($iconFileName,1) . ".gif");
3642 //Next try removing the icon prefix
3643 if ( empty($iconPath) )
3644 $iconPath = SugarThemeRegistry::current()->getImageURL("{$iconFileName}.gif");
3649 * Function to grab the correct icon image for Studio
3650 * @param string $iconFileName Name of the icon file
3651 * @param string $altfilename Name of a fallback icon file (displayed if the imagefilename doesn't exist)
3652 * @param string $width Width of image
3653 * @param string $height Height of image
3654 * @param string $align Alignment of image
3655 * @return string $string <img> tag with corresponding image
3658 function getStudioIcon($iconFileName='', $altFileName='', $width='48', $height='48', $align='baseline' )
3660 global $app_strings, $theme;
3662 $iconPath = _getIcon($iconFileName);
3663 if(empty($iconPath)){
3664 $iconPath = _getIcon($altFileName);
3665 if (empty($iconPath))
3667 return $app_strings['LBL_NO_IMAGE'];
3670 return '<img border="0" src="'.$iconPath.'" width="'.$width.'" height="'.$height.'" align="'.$align.'">';
3674 * Function to grab the correct icon image for Dashlets Dialog
3675 * @param string $filename Location of the icon file
3676 * @param string $module Name of the module to fall back onto if file does not exist
3677 * @param string $width Width of image
3678 * @param string $height Height of image
3679 * @param string $align Alignment of image
3680 * @return string $string <img> tag with corresponding image
3683 function get_dashlets_dialog_icon($module='', $width='32', $height='32', $align='absmiddle'){
3684 global $app_strings, $theme;
3685 $icon_path = _getIcon($module . "_32");
3686 if (empty($icon_path))
3688 $icon_path = _getIcon($module);
3690 if(empty($icon_path)){
3691 $icon = $app_strings['LBL_NO_IMAGE'];
3694 $icon = '<img border="0" src="'.$icon_path.'" width="'.$width.'" height="'.$height.'" align="'.$align.'">';
3699 // works nicely to change UTF8 strings that are html entities - good for PDF conversions
3700 function html_entity_decode_utf8($string)
3703 // replace numeric entities
3704 //php will have issues with numbers with leading zeros, so do not include them in what we send to code2utf.
3705 $string = preg_replace('~�*([0-9a-f]+);~ei', 'code2utf(hexdec("\\1"))', $string);
3706 $string = preg_replace('~�*([0-9]+);~e', 'code2utf(\\1)', $string);
3707 // replace literal entities
3708 if (!isset($trans_tbl))
3710 $trans_tbl = array();
3711 foreach (get_html_translation_table(HTML_ENTITIES) as $val=>$key)
3712 $trans_tbl[$key] = utf8_encode($val);
3714 return strtr($string, $trans_tbl);
3717 // Returns the utf string corresponding to the unicode value
3718 function code2utf($num)
3720 if ($num < 128) return chr($num);
3721 if ($num < 2048) return chr(($num >> 6) + 192) . chr(($num & 63) + 128);
3722 if ($num < 65536) return chr(($num >> 12) + 224) . chr((($num >> 6) & 63) + 128) . chr(($num & 63) + 128);
3723 if ($num < 2097152) return chr(($num >> 18) + 240) . chr((($num >> 12) & 63) + 128) . chr((($num >> 6) & 63) + 128) . chr(($num & 63) + 128);
3727 function str_split_php4($string, $length = 1) {
3728 $string_length = strlen($string);
3731 if ($length > $string_length) {
3732 // use the string_length as the string is shorter than the length
3733 $length = $string_length;
3735 for ($cursor = 0; $cursor < $string_length; $cursor = $cursor + $length) {
3736 $return[] = substr($string, $cursor, $length);
3741 if (version_compare(phpversion(), '5.0.0', '<')) {
3742 function str_split($string, $length = 1) {
3743 return str_split_php4($string, $length);
3748 * Invoked when connected to mssql. checks if we have freetds version of mssql library.
3749 * the response is put into a global variable.
3751 function is_freetds() {
3754 if (isset($GLOBALS['mssql_library_version'])) {
3755 if ($GLOBALS['mssql_library_version']=='freetds') {
3763 $info=ob_get_contents();
3766 if (strpos($info,'FreeTDS') !== false) {
3767 $GLOBALS['mssql_library_version']='freetds';
3770 $GLOBALS['mssql_library_version']='regular';
3778 * stripos - Find position of first occurrence of a case-insensitive string
3780 * The function is being defined for systems with PHP version < 5.
3783 if (!function_exists("stripos")){
3784 function stripos($haystack,$needle,$offset=0){
3785 return strpos(strtolower($haystack),strtolower($needle),$offset);
3790 * Chart dashlet helper function that returns the correct CSS file, dependent on the current theme.
3792 * @todo this won't work completely right until we impliment css compression and combination
3793 * for now, we'll just include the last css file found.
3795 * @return chart.css file to use
3797 function chartStyle()
3799 return SugarThemeRegistry::current()->getCSSURL('chart.css');
3803 * Chart dashlet helper functions that returns the correct XML color file for charts,
3804 * dependent on the current theme.
3806 * @return sugarColors.xml to use
3808 function chartColors()
3810 if (SugarThemeRegistry::current()->getCSSURL('sugarColors.xml')=='')
3811 return SugarThemeRegistry::current()->getImageURL('sugarColors.xml');
3812 return SugarThemeRegistry::current()->getCSSURL('sugarColors.xml');
3814 /* End Chart Dashlet helper functions */
3817 * This function is designed to set up the php enviroment
3818 * for AJAX requests.
3821 function ajaxInit() {
3822 ini_set('display_errors', 'false');
3826 * Returns an absolute path from the given path, determining if it is relative or absolute
3828 * @param string $path
3831 function getAbsolutePath(
3833 $currentServer = false
3836 $path = trim($path);
3838 // try to match absolute paths like \\server\share, /directory or c:\
3839 if ( ( substr($path,0,2) == '\\\\' )
3840 || ( $path[0] == '/' )
3841 || preg_match('/^[A-z]:/i',$path)
3845 return getcwd().'/'.$path;
3849 * Returns the bean object of the given module
3851 * @deprecated use SugarModule::loadBean() instead
3852 * @param string $module
3859 return SugarModule::get($module)->loadBean();
3864 * Returns true if the application is being accessed on a touch screen interface ( like an iPad )
3866 function isTouchScreen()
3868 $ua = empty($_SERVER['HTTP_USER_AGENT']) ? "undefined" : strtolower($_SERVER['HTTP_USER_AGENT']);
3870 // first check if we have forced use of the touch enhanced interface
3871 if ( isset($_COOKIE['touchscreen']) && $_COOKIE['touchscreen'] == '1' ) {
3875 // next check if we should use the touch interface with our device
3876 if ( strpos($ua, 'ipad') !== false ) {
3884 * Returns the shortcut keys to access the shortcut links. Shortcut
3885 * keys vary depending on browser versions and operating systems.
3886 * @return String value of the shortcut keys
3888 function get_alt_hot_key() {
3890 if ( isset($_SERVER['HTTP_USER_AGENT']) )
3891 $ua = strtolower($_SERVER['HTTP_USER_AGENT']);
3892 $isMac = strpos($ua, 'mac') !== false;
3893 $isLinux = strpos($ua, 'linux') !== false;
3895 if(!$isMac && !$isLinux && strpos($ua, 'mozilla') !== false) {
3896 if(preg_match('/firefox\/(\d)?\./', $ua, $matches)) {
3897 return $matches[1] < 2 ? 'Alt+' : 'Alt+Shift+';
3900 return $isMac ? 'Ctrl+' : 'Alt+';
3903 function can_start_session(){
3904 if(!empty($_GET['PHPSESSID'])) {
3907 $session_id = session_id();
3908 return empty($session_id) ? true : false;
3911 function load_link_class($properties){
3913 if(!empty($properties['link_class']) && !empty($properties['link_file'])){
3914 require_once($properties['link_file']);
3915 $class = $properties['link_class'];
3921 function inDeveloperMode()
3923 return isset($GLOBALS['sugar_config']['developerMode']) && $GLOBALS['sugar_config']['developerMode'];
3927 * Filter the protocol list for inbound email accounts.
3929 * @param array $protocol
3931 function filterInboundEmailPopSelection($protocol)
3933 if ( !isset($GLOBALS['sugar_config']['allow_pop_inbound']) || ! $GLOBALS['sugar_config']['allow_pop_inbound'] )
3935 if( isset($protocol['pop3']) )
3936 unset($protocol['pop3']);
3939 $protocol['pop3'] = 'POP3';
3945 * The function is used because currently we are not supporting mbstring.func_overload
3946 * 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.
3947 * 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.
3948 * @returns the substred strings.
3950 function sugar_substr($string, $length, $charset='UTF-8') {
3951 if($GLOBALS['db']->dbType == 'mssql' && empty($GLOBALS['db']->isFreeTDS)) {
3952 if(strlen($string) > $length) {
3953 $string = trim(substr(trim($string),0,$length));
3957 if(mb_strlen($string,$charset) > $length) {
3958 $string = trim(mb_substr(trim($string),0,$length,$charset));
3965 * The function is used because on FastCGI enviroment, the ucfirst(Chinese Characters) will produce bad charcters.
3966 * This will work even without setting the mbstring.*encoding
3968 function sugar_ucfirst($string, $charset='UTF-8') {
3969 return mb_strtoupper(mb_substr($string, 0, 1, $charset), $charset) . mb_substr($string, 1, mb_strlen($string), $charset);
3976 function unencodeMultienum($string) {
3977 if (is_array($string))
3981 if (substr($string, 0 ,1) == "^" && substr($string, -1) == "^") {
3982 $string = substr(substr($string, 1), 0, strlen($string) -2);
3985 return explode('^,^', $string);
3988 function encodeMultienumValue($arr) {
3989 if (!is_array($arr))
3995 $string = "^" . implode('^,^', $arr) . "^";
4001 * create_export_query is used for export and massupdate
4002 * We haven't handle the these fields: $field['type'] == 'relate' && isset($field['link']
4003 * This function will correct the where clause and output necessary join condition for them
4004 * @param $module: the module name
4005 * @param $searchFields: searchFields which is got after $searchForm->populateFromArray()
4006 * @param $where: where clauses
4007 * @return $ret_array['where']: corrected where clause
4008 * @return $ret_array['join']: extra join condition
4010 function create_export_query_relate_link_patch($module, $searchFields, $where){
4011 if(file_exists('modules/'.$module.'/SearchForm.html')){
4012 $ret_array['where'] = $where;
4015 $seed = loadBean($module);
4016 foreach($seed->field_defs as $name=>$field)
4019 if( $field['type'] == 'relate' && isset($field['link']) && !empty($searchFields[$name]['value']) ){
4020 $seed->load_relationship($field['link']);
4022 if(empty($join_type))
4024 $params['join_type'] = ' LEFT JOIN ';
4028 $params['join_type'] = $join_type;
4030 if(isset($data['join_name']))
4032 $params['join_table_alias'] = $field['join_name'];
4036 $params['join_table_alias'] = 'join_'.$field['name'];
4039 if(isset($data['join_link_name']))
4041 $params['join_table_link_alias'] = $field['join_link_name'];
4045 $params['join_table_link_alias'] = 'join_link_'.$field['name'];
4047 $join = $seed->$field['link']->getJoin($params, true);
4048 $join_table_alias = 'join_'.$field['name'];
4049 if(isset($field['db_concat_fields'])){
4050 $db_field = db_concat($join_table_alias, $field['db_concat_fields']);
4051 $where = preg_replace('/'.$field['name'].'/', $db_field, $where);
4053 $where = preg_replace('/(^|[\s(])' . $field['name'] . '/', '${1}' . $join_table_alias . '.'.$field['rname'], $where);
4057 $ret_array = array('where'=>$where, 'join'=>$join['join']);
4062 * 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.
4063 * @Depends on QuickRepairAndRebuild.php
4064 * @Relate bug 30642 ,23177
4066 function clearAllJsAndJsLangFilesWithoutOutput(){
4067 global $current_language , $mod_strings;
4068 $MBmodStrings = $mod_strings;
4069 $mod_strings = return_module_language ( $current_language, 'Administration' ) ;
4070 include_once ('modules/Administration/QuickRepairAndRebuild.php') ;
4071 $repair = new RepairAndClear();
4072 $repair->module_list = array();
4073 $repair->show_output = false;
4074 $repair->clearJsLangFiles();
4075 $repair->clearJsFiles();
4076 $mod_strings = $MBmodStrings;
4080 * This function will allow you to get a variable value from query string
4082 function getVariableFromQueryString($variable, $string){
4084 $number = preg_match("/{$variable}=([a-zA-Z0-9_-]+)[&]?/", $string, $matches);
4094 * should_hide_iframes
4095 * This is a helper method to determine whether or not to show iframes (My Sites) related
4096 * information in the application.
4098 * @return boolean flag indicating whether or not iframes module should be hidden
4100 function should_hide_iframes() {
4101 //Remove the MySites module
4102 if(file_exists('modules/iFrames/iFrame.php')) {
4103 if(!class_exists("iFrame")) {
4104 require_once('modules/iFrames/iFrame.php');
4112 * Given a version such as 5.5.0RC1 return RC. If we have a version such as: 5.5 then return GA
4114 * @param string $version
4115 * @return string RC, BETA, GA
4117 function getVersionStatus($version){
4118 if(preg_match('/^[\d\.]+?([a-zA-Z]+?)[\d]*?$/si', $version, $matches)) {
4119 return strtoupper($matches[1]);
4126 * Return the numeric portion of a version. For example if passed 5.5.0RC1 then return 5.5. If given
4127 * 5.5.1RC1 then return 5.5.1
4129 * @param string $version
4132 function getMajorMinorVersion($version){
4133 if(preg_match('/^([\d\.]+).*$/si', $version, $matches2)){
4134 $version = $matches2[1];
4135 $arr = explode('.', $version);
4136 if(count($arr) > 2){
4138 $version = substr($version, 0, 3);
4146 * Return string composed of seconds & microseconds of current time, without dots
4149 function sugar_microtime()
4151 $now = explode(' ', microtime());
4152 $unique_id = $now[1].str_replace('.', '', $now[0]);