]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - include/utils.php
Release 6.3.0
[Github/sugarcrm.git] / include / utils.php
1 <?php
2 /*********************************************************************************
3  * SugarCRM Community Edition is a customer relationship management program developed by
4  * SugarCRM, Inc. Copyright (C) 2004-2011 SugarCRM Inc.
5  * 
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.
12  * 
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
16  * details.
17  * 
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
21  * 02110-1301 USA.
22  * 
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.
25  * 
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.
29  * 
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  ********************************************************************************/
36
37 /*********************************************************************************
38
39  * Description:  Includes generic helper functions used throughout the application.
40  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
41  * All Rights Reserved.
42  * Contributor(s): ______________________________________..
43  ********************************************************************************/
44 require_once('include/SugarObjects/SugarConfig.php');
45 require_once('include/utils/security_utils.php');
46
47
48
49 function make_sugar_config(&$sugar_config)
50 {
51         /* used to convert non-array config.php file to array format */
52         global $admin_export_only;
53         global $cache_dir;
54         global $calculate_response_time;
55         global $create_default_user;
56         global $dateFormats;
57         global $dbconfig;
58         global $dbconfigoption;
59         global $default_action;
60         global $default_charset;
61         global $default_currency_name;
62         global $default_currency_symbol;
63         global $default_currency_iso4217;
64         global $defaultDateFormat;
65         global $default_language;
66         global $default_module;
67         global $default_password;
68         global $default_permission_mode;
69         global $default_theme;
70         global $defaultTimeFormat;
71         global $default_user_is_admin;
72         global $default_user_name;
73         global $disable_export;
74         global $disable_persistent_connections;
75         global $display_email_template_variable_chooser;
76         global $display_inbound_email_buttons;
77         global $history_max_viewed;
78         global $host_name;
79         global $import_dir;
80         global $languages;
81         global $list_max_entries_per_page;
82         global $lock_default_user_name;
83         global $log_memory_usage;
84         global $requireAccounts;
85         global $RSS_CACHE_TIME;
86         global $session_dir;
87         global $site_URL;
88         global $site_url;
89         global $sugar_version;
90         global $timeFormats;
91         global $tmp_dir;
92         global $translation_string_prefix;
93         global $unique_key;
94         global $upload_badext;
95         global $upload_dir;
96         global $upload_maxsize;
97         global $import_max_execution_time;
98         global $list_max_entries_per_subpanel;
99         global $passwordsetting;
100
101         // assumes the following variables must be set:
102         // $dbconfig, $dbconfigoption, $cache_dir, $import_dir, $session_dir, $site_URL, $tmp_dir, $upload_dir
103
104         $sugar_config = array (
105         'admin_export_only' => empty($admin_export_only) ? false : $admin_export_only,
106         'export_delimiter' => empty($export_delimiter) ? ',' : $export_delimiter,
107         'cache_dir' => empty($cache_dir) ? 'cache/' : $cache_dir,
108         'calculate_response_time' => empty($calculate_response_time) ? true : $calculate_response_time,
109         'create_default_user' => empty($create_default_user) ? false : $create_default_user,
110         'chartEngine' => 'Jit',
111         'date_formats' => empty($dateFormats) ? array(
112         'Y-m-d'=>'2010-12-23',
113         'd-m-Y' => '23-12-2010',
114         'm-d-Y'=>'12-23-2010',
115         'Y/m/d'=>'2010/12/23',
116         'd/m/Y' => '23/12/2010',
117         'm/d/Y'=>'12/23/2010',
118         'Y.m.d' => '2010.12.23',
119         'd.m.Y' => '23.12.2010',
120         'm.d.Y' => '12.23.2010'
121                 ) : $dateFormats,
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 (
135                 'dir_mode' => 02770,
136                 'file_mode' => 0660,
137                 'chown' => '',
138                 'chgrp' => '',
139         ),
140     'default_theme' => empty($default_theme) ? 'Sugar5' : $default_theme,
141     'default_time_format' => empty($defaultTimeFormat) ? 'h:ia' : $defaultTimeFormat,
142         'default_user_is_admin' => empty($default_user_is_admin) ? false : $default_user_is_admin,
143         'default_user_name' => empty($default_user_name) ? '' : $default_user_name,
144         'disable_export' => empty($disable_export) ? false : $disable_export,
145     'disable_persistent_connections' => empty($disable_persistent_connections) ? false : $disable_persistent_connections,
146     'display_email_template_variable_chooser' => empty($display_email_template_variable_chooser) ? false : $display_email_template_variable_chooser,
147         'display_inbound_email_buttons' => empty($display_inbound_email_buttons) ? false : $display_inbound_email_buttons,
148         'history_max_viewed' => empty($history_max_viewed) ? 50 : $history_max_viewed,
149         'host_name' => empty($host_name) ? 'localhost' : $host_name,
150         'import_dir' => $import_dir,  // this must be set!!
151         'import_max_records_per_file' => 100,
152     'import_max_records_total_limit' => '',
153         'languages' => empty($languages) ? array('en_us' => 'English (US)') : $languages,
154         'list_max_entries_per_page' => empty($list_max_entries_per_page) ? 20 : $list_max_entries_per_page,
155         'list_max_entries_per_subpanel' => empty($list_max_entries_per_subpanel) ? 10 : $list_max_entries_per_subpanel,
156         'lock_default_user_name' => empty($lock_default_user_name) ? false : $lock_default_user_name,
157         'log_memory_usage' => empty($log_memory_usage) ? false : $log_memory_usage,
158     'portal_view' => 'single_user',
159         'resource_management' => array (
160             'special_query_limit' => 50000,
161             'special_query_modules' => array('Reports', 'Export', 'Import', 'Administration', 'Sync'),
162             'default_limit' => 1000,
163     ),
164         'require_accounts' => empty($requireAccounts) ? true : $requireAccounts,
165         'rss_cache_time' => empty($RSS_CACHE_TIME) ? '10800' : $RSS_CACHE_TIME,
166         'session_dir' => $session_dir,  // this must be set!!
167         'site_url' => empty($site_URL) ? $site_url : $site_URL,  // this must be set!!
168         'showDetailData' => true, // if true, read-only ACL fields will still appear on EditViews as non-editable
169         'showThemePicker' => true,
170         'sugar_version' => empty($sugar_version) ? 'unknown' : $sugar_version,
171         'time_formats' => empty($timeFormats) ? array (
172         'H:i'=>'23:00', 'h:ia'=>'11:00 pm', 'h:iA'=>'11:00PM',
173         'H.i'=>'23.00', 'h.ia'=>'11.00 pm', 'h.iA'=>'11.00PM' ) : $timeFormats,
174         'tmp_dir' => $tmp_dir,  // this must be set!!
175         'translation_string_prefix' => empty($translation_string_prefix) ? false : $translation_string_prefix,
176         'unique_key' => empty($unique_key) ? md5(create_guid()) : $unique_key,
177         'upload_badext' => empty($upload_badext) ? array (
178         'php', 'php3', 'php4', 'php5', 'pl', 'cgi', 'py',
179         'asp', 'cfm', 'js', 'vbs', 'html', 'htm' ) : $upload_badext,
180         'upload_dir' => $upload_dir,  // this must be set!!
181         'upload_maxsize' => empty($upload_maxsize) ? 3000000 : $upload_maxsize,
182         'import_max_execution_time' => empty($import_max_execution_time) ? 3600 : $import_max_execution_time,
183         'lock_homepage' => false,
184         'lock_subpanels' => false,
185         'max_dashlets_homepage' => 15,
186         'dashlet_display_row_options' => array('1','3','5','10'),
187         'default_max_tabs' => empty($max_tabs) ? '7' : $max_tabs,
188         'default_subpanel_tabs' =>  empty($subpanel_tabs) ? true : $subpanel_tabs,
189         'default_subpanel_links' => empty($subpanel_links) ? false : $subpanel_links,
190         'default_swap_last_viewed' => empty($swap_last_viewed) ? false : $swap_last_viewed,
191         'default_swap_shortcuts' => empty($swap_shortcuts) ? false : $swap_shortcuts,
192         'default_navigation_paradigm' => empty($navigation_paradigm) ? 'gm' : $navigation_paradigm,
193     'default_call_status' => 'Planned',
194         'js_lang_version' => 1,
195         'passwordsetting' => empty($passwordsetting) ? array (
196             'SystemGeneratedPasswordON' => '',
197             'generatepasswordtmpl' => '',
198             'lostpasswordtmpl' => '',
199             'forgotpasswordON' => true,
200         'linkexpiration' => '1',
201         'linkexpirationtime' => '30',
202         'linkexpirationtype' => '1',
203             'systexpiration' => '0',
204             'systexpirationtime' => '',
205             'systexpirationtype' => '0',
206             'systexpirationlogin' => '',
207                 ) : $passwordsetting,
208         );
209 }
210
211 function get_sugar_config_defaults() {
212         global $locale;
213         /**
214          * used for getting base values for array style config.php.  used by the
215          * installer and to fill in new entries on upgrades.  see also:
216          * sugar_config_union
217          */
218
219         $sugar_config_defaults = array (
220         'admin_export_only' => false,
221         'export_delimiter' => ',',
222         'cache_dir' => 'cache/',
223         'calculate_response_time' => true,
224         'create_default_user' => false,
225         'chartEngine' => 'Jit',
226         'date_formats' => array (
227         'Y-m-d' => '2010-12-23', 'm-d-Y' => '12-23-2010', 'd-m-Y' => '23-12-2010',
228         'Y/m/d' => '2010/12/23', 'm/d/Y' => '12/23/2010', 'd/m/Y' => '23/12/2010',
229         'Y.m.d' => '2010.12.23', 'd.m.Y' => '23.12.2010', 'm.d.Y' => '12.23.2010',),
230         'dbconfigoption' => array (
231         'persistent' => true,
232         'autofree' => false,
233         'debug' => 0,
234         'seqname_format' => '%s_seq',
235         'portability' => 0,
236         'ssl' => false ),
237         'default_action' => 'index',
238         'default_charset' => return_session_value_or_default('default_charset',
239         'UTF-8'),
240         'default_currency_name' => return_session_value_or_default('default_currency_name', 'US Dollar'),
241         'default_currency_symbol' => return_session_value_or_default('default_currency_symbol', '$'),
242         'default_currency_iso4217' => return_session_value_or_default('default_currency_iso4217', 'USD'),
243         'default_currency_significant_digits' => return_session_value_or_default('default_currency_significant_digits', 2),
244         'default_number_grouping_seperator' => return_session_value_or_default('default_number_grouping_seperator', ','),
245         'default_decimal_seperator' => return_session_value_or_default('default_decimal_seperator', '.'),
246         'default_date_format' => 'm/d/Y',
247         'default_export_charset' => 'UTF-8',
248         'default_language' => return_session_value_or_default('default_language',
249         'en_us'),
250         'default_module' => 'Home',
251         'default_password' => '',
252         'default_permissions' => array (
253                 'dir_mode' => 02770,
254                 'file_mode' => 0660,
255                 'user' => '',
256                 'group' => '',
257         ),
258         'default_theme' => return_session_value_or_default('site_default_theme', 'Sugar5'),
259         'default_time_format' => 'h:ia',
260         'default_user_is_admin' => false,
261         'default_user_name' => '',
262         'disable_export' => false,
263         'disable_persistent_connections' =>
264         return_session_value_or_default('disable_persistent_connections',
265         'false'),
266     'display_email_template_variable_chooser' => false,
267         'display_inbound_email_buttons' => false,
268         'dump_slow_queries' => false,
269         'email_default_editor' => 'html',
270         'email_default_client' => 'sugar',
271         'email_default_delete_attachments' => true,
272         'history_max_viewed' => 50,
273         'installer_locked' => true,
274         'import_max_records_per_file' => 100,
275     'import_max_records_total_limit' => '',
276         'languages' => array('en_us' => 'English (US)'),
277         'large_scale_test' => false,
278         'list_max_entries_per_page' => 20,
279         'list_max_entries_per_subpanel' => 10,
280         'lock_default_user_name' => false,
281         'log_memory_usage' => false,
282         'portal_view' => 'single_user',
283     'resource_management' => array (
284             'special_query_limit' => 50000,
285             'special_query_modules' => array('Reports', 'Export', 'Import', 'Administration', 'Sync'),
286             'default_limit' => 1000,
287     ),
288         'require_accounts' => true,
289         'rss_cache_time' => return_session_value_or_default('rss_cache_time',
290         '10800'),
291         'save_query' => 'all',
292         'showDetailData' => true, // if true, read-only ACL fields will still appear on EditViews as non-editable
293         'showThemePicker' => true,
294         'slow_query_time_msec' => '100',
295     'sugarbeet' => true,
296     'time_formats' => array (
297         'H:i'=>'23:00', 'h:ia'=>'11:00pm', 'h:iA'=>'11:00PM', 'h:i a'=>'11:00 pm', 'h:i A'=>'11:00 PM',
298         'H.i'=>'23.00', 'h.ia'=>'11.00pm', 'h.iA'=>'11.00PM', 'h.i a'=>'11.00 pm', 'h.i A'=>'11.00 PM' ),
299     'tracker_max_display_length' => 15,
300         'translation_string_prefix' =>
301         return_session_value_or_default('translation_string_prefix', false),
302         'upload_badext' => array (
303         'php', 'php3', 'php4', 'php5', 'pl', 'cgi', 'py',
304         'asp', 'cfm', 'js', 'vbs', 'html', 'htm' ),
305         'upload_maxsize' => 3000000,
306         'import_max_execution_time' => 3600,
307 //      'use_php_code_json' => returnPhpJsonStatus(),
308         'verify_client_ip' => true,
309         'js_custom_version' => '',
310         'js_lang_version' => 1,
311         'lead_conv_activity_opt' => 'donothing',
312         'default_number_grouping_seperator' => ',',
313         'default_decimal_seperator' => '.',
314         'lock_homepage' => false,
315         'lock_subpanels' => false,
316         'max_dashlets_homepage' => '15',
317         'default_max_tabs' => '7',
318         'dashlet_display_row_options' => array('1','3','5','10'),
319         'default_subpanel_tabs' =>  true,
320         'default_subpanel_links' => false,
321         'default_swap_last_viewed' => false,
322         'default_swap_shortcuts' => false,
323         'default_navigation_paradigm' => 'gm',
324         'admin_access_control' => false,
325         'use_common_ml_dir'     => false,
326         'common_ml_dir' => '',
327         'vcal_time' => '2',
328         'passwordsetting' => empty($passwordsetting) ? array (
329             'SystemGeneratedPasswordON' => '',
330             'generatepasswordtmpl' => '',
331             'lostpasswordtmpl' => '',
332             'forgotpasswordON' => false,
333         'linkexpiration' => '1',
334         'linkexpirationtime' => '30',
335         'linkexpirationtype' => '1',
336             'systexpiration' => '0',
337             'systexpirationtime' => '',
338             'systexpirationtype' => '0',
339             'systexpirationlogin' => '',
340                 ) : $passwordsetting,
341         'use_real_names' => true,
342         );
343
344         if(!is_object($locale)) {
345                 $locale = new Localization();
346         }
347
348         $sugar_config_defaults['default_currencies'] = $locale->getDefaultCurrencies();
349
350         $sugar_config_defaults = sugarArrayMerge($locale->getLocaleConfigDefaults(), $sugar_config_defaults);
351         return( $sugar_config_defaults );
352 }
353
354 /**
355  * @deprecated use SugarView::getMenu() instead
356  */
357 function load_menu($path){
358         global $module_menu;
359
360         if(file_exists($path . 'Menu.php'))
361         {
362                 require($path . 'Menu.php');
363         }
364         if(file_exists('custom/' . $path . 'Ext/Menus/menu.ext.php'))
365         {
366                 require('custom/' . $path . 'Ext/Menus/menu.ext.php');
367         }
368         if(file_exists('custom/application/Ext/Menus/menu.ext.php'))
369         {
370                 require('custom/application/Ext/Menus/menu.ext.php');
371         }
372         return $module_menu;
373 }
374
375 /**
376  * get_notify_template_file
377  * This function will return the location of the email notifications template to use
378  *
379  * @return string relative file path to email notifications template file
380  */
381 function get_notify_template_file($language){
382         /*
383          * Order of operation:
384          * 1) custom version of specified language
385          * 2) stock version of specified language
386          * 3) custom version of en_us template
387          * 4) stock en_us template
388          */
389
390         // set $file to the base code template so it's set if none of the conditions pass
391         $file = "include/language/en_us.notify_template.html";
392
393         if(file_exists("custom/include/language/{$language}.notify_template.html")){
394                 $file = "custom/include/language/{$language}.notify_template.html";
395         }
396         else if(file_exists("include/language/{$language}.notify_template.html")){
397                 $file = "include/language/{$language}.notify_template.html";
398         }
399         else if(file_exists("custom/include/language/en_us.notify_template.html")){
400                 $file = "custom/include/language/en_us.notify_template.html";
401         }
402
403         return $file;
404 }
405
406 function sugar_config_union( $default, $override ){
407         // a little different then array_merge and array_merge_recursive.  we want
408         // the second array to override the first array if the same value exists,
409         // otherwise merge the unique keys.  it handles arrays of arrays recursively
410         // might be suitable for a generic array_union
411         if( !is_array( $override ) ){
412                 $override = array();
413         }
414         foreach( $default as $key => $value ){
415                 if( !array_key_exists($key, $override) ){
416                         $override[$key] = $value;
417                 }
418                 else if( is_array( $key ) ){
419                         $override[$key] = sugar_config_union( $value, $override[$key] );
420                 }
421         }
422         return( $override );
423 }
424
425 function make_not_writable( $file ){
426         // Returns true if the given file/dir has been made not writable
427         $ret_val = false;
428         if( is_file($file) || is_dir($file) ){
429                 if( !is_writable($file) ){
430                         $ret_val = true;
431                 }
432                 else {
433                         $original_fileperms = fileperms($file);
434
435                         // take away writable permissions
436                         $new_fileperms = $original_fileperms & ~0x0092;
437                         @sugar_chmod($file, $new_fileperms);
438
439                         if( !is_writable($file) ){
440                                 $ret_val = true;
441                         }
442                 }
443         }
444         return $ret_val;
445 }
446
447
448 /** This function returns the name of the person.
449  * It currently returns "first last".  It should not put the space if either name is not available.
450  * It should not return errors if either name is not available.
451  * If no names are present, it will return ""
452  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
453  * All Rights Reserved.
454  * Contributor(s): ______________________________________..
455  */
456 function return_name($row, $first_column, $last_column)
457 {
458         $first_name = "";
459         $last_name = "";
460         $full_name = "";
461
462         if(isset($row[$first_column]))
463         {
464                 $first_name = stripslashes($row[$first_column]);
465         }
466
467         if(isset($row[$last_column]))
468         {
469                 $last_name = stripslashes($row[$last_column]);
470         }
471
472         $full_name = $first_name;
473
474         // If we have a first name and we have a last name
475         if($full_name != "" && $last_name != "")
476         {
477                 // append a space, then the last name
478                 $full_name .= " ".$last_name;
479         }
480         // If we have no first name, but we have a last name
481         else if($last_name != "")
482         {
483                 // append the last name without the space.
484                 $full_name .= $last_name;
485         }
486
487         return $full_name;
488 }
489
490
491 function get_languages()
492 {
493         global $sugar_config;
494         $lang = $sugar_config['languages'];
495     if(!empty($sugar_config['disabled_languages'])){
496         foreach(explode(',', $sugar_config['disabled_languages']) as $disable) {
497             unset($lang[$disable]);
498         }
499     }
500         return $lang;
501 }
502
503 function get_all_languages()
504 {
505         global $sugar_config;
506         return $sugar_config['languages'];
507 }
508
509
510 function get_language_display($key)
511 {
512         global $sugar_config;
513         return $sugar_config['languages'][$key];
514 }
515
516 function get_assigned_user_name($assigned_user_id, $is_group = '') {
517         static $saved_user_list = null;
518
519         if(empty($saved_user_list)) {
520                 $saved_user_list = get_user_array(false, '', '', false, null, $is_group);
521         }
522
523         if(isset($saved_user_list[$assigned_user_id])) {
524                 return $saved_user_list[$assigned_user_id];
525         }
526
527         return '';
528 }
529
530 /**
531  * retrieves the user_name column value (login)
532  * @param string id GUID of user
533  * @return string
534  */
535 function get_user_name($id) {
536         global $db;
537
538         if(empty($db))
539         $db = DBManagerFactory::getInstance();
540
541         $q = "SELECT user_name FROM users WHERE id='{$id}'";
542         $r = $db->query($q);
543         $a = $db->fetchByAssoc($r);
544
545         return (empty($a)) ? '' : $a['user_name'];
546 }
547
548
549 //TODO Update to use global cache
550 function get_user_array($add_blank=true, $status="Active", $assigned_user="", $use_real_name=false, $user_name_begins = null, $is_group=' AND portal_only=0 ', $from_cache = true) {
551         global $locale;
552         global $sugar_config;
553
554         if(empty($locale)) {
555
556                 $locale = new Localization();
557         }
558         if($from_cache)
559                 $user_array = get_register_value('user_array', $add_blank. $status . $assigned_user);
560
561         if(empty($user_array)) {
562                 $db = DBManagerFactory::getInstance();
563                 $temp_result = Array();
564                 // Including deleted users for now.
565                 if (empty($status)) {
566                         $query = "SELECT id, first_name, last_name, user_name from users WHERE 1=1".$is_group;
567                 }
568                 else {
569                         $query = "SELECT id, first_name, last_name, user_name from users WHERE status='$status'".$is_group;
570                 }
571
572                 if (!empty($user_name_begins)) {
573                         $query .= " AND user_name LIKE '$user_name_begins%' ";
574                 }
575                 if (!empty($assigned_user)) {
576                         $query .= " OR id='$assigned_user'";
577                 }
578                 $query = $query.' ORDER BY user_name ASC';
579                 $GLOBALS['log']->debug("get_user_array query: $query");
580                 $result = $db->query($query, true, "Error filling in user array: ");
581
582                 if ($add_blank==true) {
583                         // Add in a blank row
584                         $temp_result[''] = '';
585                 }
586
587                 // Get the id and the name.
588                 while($row = $db->fetchByAssoc($result)) {
589                         if($use_real_name == true || showFullName()) {
590                                 if(isset($row['last_name'])) { // cn: we will ALWAYS have both first_name and last_name (empty value if blank in db)
591                                         $temp_result[$row['id']] = $locale->getLocaleFormattedName($row['first_name'],$row['last_name']);
592                                 } else {
593                                         $temp_result[$row['id']] = $row['user_name'];
594                                 }
595                         } else {
596                                 $temp_result[$row['id']] = $row['user_name'];
597                         }
598                 }
599
600                 $user_array = $temp_result;
601                 if($from_cache)
602                         set_register_value('user_array', $add_blank. $status . $assigned_user, $temp_result);
603         }
604
605
606         return $user_array;
607 }
608
609
610 /**
611  * uses a different query to return a list of users than get_user_array()
612  * @param args string where clause entry
613  * @return array Array of Users' details that match passed criteria
614  */
615 function getUserArrayFromFullName($args, $hide_portal_users = false) {
616         global $locale;
617         $db = DBManagerFactory::getInstance();
618
619         $argArray = array();
620         if(strpos($args, " ")) {
621                 $argArray = explode(" ", $args);
622         } else {
623                 $argArray[] = $args;
624         }
625
626         $inClause = '';
627         foreach($argArray as $arg) {
628                 if(!empty($inClause)) {
629                         $inClause .= ' OR ';
630                 }
631                 if(empty($arg))
632                 continue;
633
634                 $inClause .= "(first_name LIKE '{$arg}%' OR last_name LIKE '{$arg}%')";
635         }
636
637         $query  = "SELECT id, first_name, last_name, user_name FROM users WHERE status='Active' AND deleted=0 AND ";
638         if ( $hide_portal_users ) {
639             $query .= " portal_only=0 AND ";
640         }
641         $query .= $inClause;
642         $query .= " ORDER BY last_name ASC";
643
644         $r = $db->query($query);
645         $ret = array();
646         while($a = $db->fetchByAssoc($r)) {
647                 $ret[$a['id']] = $locale->getLocaleFormattedName($a['first_name'], $a['last_name']);
648         }
649
650         return $ret;
651 }
652
653 /**
654  *
655  * based on user pref then system pref
656  */
657 function showFullName() {
658         global $sugar_config;
659         global $current_user;
660         static $showFullName = null;
661
662         if (is_null($showFullName)) {
663                 $sysPref = !empty($sugar_config['use_real_names']);
664                 $userPref = (is_object($current_user)) ? $current_user->getPreference('use_real_names') : null;
665
666                 if($userPref != null) {
667                         $showFullName = ($userPref == 'on');
668                 } else {
669                         $showFullName = $sysPref;
670                 }
671         }
672
673         return $showFullName;
674 }
675
676 function clean($string, $maxLength)
677 {
678         $string = substr($string, 0, $maxLength);
679         return escapeshellcmd($string);
680 }
681
682 /**
683  * Copy the specified request variable to the member variable of the specified object.
684  * Do no copy if the member variable is already set.
685  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
686  * All Rights Reserved.
687  * Contributor(s): ______________________________________..
688  */
689 function safe_map($request_var, & $focus, $always_copy = false)
690 {
691         safe_map_named($request_var, $focus, $request_var, $always_copy);
692 }
693
694 /**
695  * Copy the specified request variable to the member variable of the specified object.
696  * Do no copy if the member variable is already set.
697  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
698  * All Rights Reserved.
699  * Contributor(s): ______________________________________..
700  */
701 function safe_map_named($request_var, & $focus, $member_var, $always_copy)
702 {
703         if (isset($_REQUEST[$request_var]) && ($always_copy || is_null($focus->$member_var))) {
704                 $GLOBALS['log']->debug("safe map named called assigning '{$_REQUEST[$request_var]}' to $member_var");
705                 $focus->$member_var = $_REQUEST[$request_var];
706         }
707 }
708
709 /**
710  * This function retrieves an application language file and returns the array of strings included in the $app_list_strings var.
711  *
712  * @param string $language specific language to load
713  * @return array lang strings
714  */
715 function return_app_list_strings_language($language)
716 {
717         global $app_list_strings;
718         global $sugar_config;
719
720         $cache_key = 'app_list_strings.'.$language;
721
722         // Check for cached value
723         $cache_entry = sugar_cache_retrieve($cache_key);
724         if(!empty($cache_entry))
725         {
726                 return $cache_entry;
727         }
728
729         $default_language = $sugar_config['default_language'];
730         $temp_app_list_strings = $app_list_strings;
731
732         $langs = array();
733         if ($language != 'en_us') {
734             $langs[] = 'en_us';
735         }
736         if ($default_language != 'en_us' && $language != $default_language) {
737             $langs[] = $default_language;
738         }
739         $langs[] = $language;
740
741         $app_list_strings_array = array();
742
743         foreach ( $langs as $lang ) {
744             $app_list_strings = array();
745             if(file_exists("include/language/$lang.lang.php")) {
746             include("include/language/$lang.lang.php");
747             $GLOBALS['log']->info("Found language file: $lang.lang.php");
748         }
749         if(file_exists("include/language/$lang.lang.override.php")) {
750             include("include/language/$lang.lang.override.php");
751             $GLOBALS['log']->info("Found override language file: $lang.lang.override.php");
752         }
753         if(file_exists("include/language/$lang.lang.php.override")) {
754             include("include/language/$lang.lang.php.override");
755             $GLOBALS['log']->info("Found override language file: $lang.lang.php.override");
756         }
757
758         $app_list_strings_array[] = $app_list_strings;
759     }
760
761     $app_list_strings = array();
762     foreach ( $app_list_strings_array as $app_list_strings_item ) {
763         $app_list_strings = sugarArrayMerge($app_list_strings, $app_list_strings_item);
764     }
765
766     foreach ( $langs as $lang ) {
767         if(file_exists("custom/application/Ext/Language/$lang.lang.ext.php")) {
768             $app_list_strings = _mergeCustomAppListStrings("custom/application/Ext/Language/$lang.lang.ext.php" , $app_list_strings);
769             $GLOBALS['log']->info("Found extended language file: $lang.lang.ext.php");
770         }
771         if(file_exists("custom/include/language/$lang.lang.php")) {
772             include("custom/include/language/$lang.lang.php");
773             $GLOBALS['log']->info("Found custom language file: $lang.lang.php");
774         }
775     }
776
777         if(!isset($app_list_strings)) {
778                 $GLOBALS['log']->fatal("Unable to load the application language file for the selected language ($language) or the default language ($default_language) or the en_us language");
779                 return null;
780         }
781
782         $return_value = $app_list_strings;
783         $app_list_strings = $temp_app_list_strings;
784
785         sugar_cache_put($cache_key, $return_value);
786
787         return $return_value;
788 }
789
790 /**
791 * The dropdown items in custom language files is $app_list_strings['$key']['$second_key'] = $value not
792 * $GLOBALS['app_list_strings']['$key'] = $value, so we have to delete the original ones in app_list_strings and relace it with the custom ones.
793  * @param file string the language that you want include,
794  * @param app_list_strings array the golbal strings
795  * @return array
796  */
797  //jchi 25347
798 function _mergeCustomAppListStrings($file , $app_list_strings){
799         $app_list_strings_original = $app_list_strings;
800         unset($app_list_strings);
801         // FG - bug 45525 - $exemptDropdown array is defined (once) here, not inside the foreach
802         //                  This way, language file can add items to save specific standard codelist from being overwritten
803         $exemptDropdowns = array();
804         include($file);
805         if(!isset($app_list_strings) || !is_array($app_list_strings)){
806                 return $app_list_strings_original;
807         }
808         //Bug 25347: We should not merge custom dropdown fields unless they relate to parent fields or the module list.
809
810         // FG - bug 45525 - Specific codelists must NOT be overwritten
811         $exemptDropdowns[] = "moduleList";
812         $exemptDropdowns[] = "parent_type_display";
813         $exemptDropdowns[] = "record_type_display";
814         $exemptDropdowns[] = "record_type_display_notes";
815    
816         foreach($app_list_strings as $key=>$value)
817         {
818                 if (!in_array($key, $exemptDropdowns) && array_key_exists($key, $app_list_strings_original))
819                 {
820                         unset($app_list_strings_original["$key"]);
821                 }
822    }
823    $app_list_strings = sugarArrayMergeRecursive($app_list_strings_original , $app_list_strings);
824    return $app_list_strings;
825 }
826
827 /**
828  * This function retrieves an application language file and returns the array of strings included.
829  *
830  * @param string $language specific language to load
831  * @return array lang strings
832  */
833 function return_application_language($language)
834 {
835         global $app_strings, $sugar_config;
836
837         $cache_key = 'app_strings.'.$language;
838
839         // Check for cached value
840         $cache_entry = sugar_cache_retrieve($cache_key);
841         if(!empty($cache_entry))
842         {
843                 return $cache_entry;
844         }
845
846         $temp_app_strings = $app_strings;
847         $default_language = $sugar_config['default_language'];
848
849         $langs = array();
850         if ($language != 'en_us') {
851             $langs[] = 'en_us';
852         }
853         if ($default_language != 'en_us' && $language != $default_language) {
854             $langs[] = $default_language;
855         }
856
857         $langs[] = $language;
858
859         $app_strings_array = array();
860
861         foreach ( $langs as $lang ) {
862             $app_strings = array();
863             if(file_exists("include/language/$lang.lang.php")) {
864             include("include/language/$lang.lang.php");
865             $GLOBALS['log']->info("Found language file: $lang.lang.php");
866         }
867         if(file_exists("include/language/$lang.lang.override.php")) {
868             include("include/language/$lang.lang.override.php");
869             $GLOBALS['log']->info("Found override language file: $lang.lang.override.php");
870         }
871         if(file_exists("include/language/$lang.lang.php.override")) {
872             include("include/language/$lang.lang.php.override");
873             $GLOBALS['log']->info("Found override language file: $lang.lang.php.override");
874         }
875         if(file_exists("custom/application/Ext/Language/$lang.lang.ext.php")) {
876             include("custom/application/Ext/Language/$lang.lang.ext.php");
877             $GLOBALS['log']->info("Found extended language file: $lang.lang.ext.php");
878         }
879         if(file_exists("custom/include/language/$lang.lang.php")) {
880             include("custom/include/language/$lang.lang.php");
881             $GLOBALS['log']->info("Found custom language file: $lang.lang.php");
882         }
883         $app_strings_array[] = $app_strings;
884         }
885
886         $app_strings = array();
887     foreach ( $app_strings_array as $app_strings_item ) {
888         $app_strings = sugarArrayMerge($app_strings, $app_strings_item);
889     }
890
891         if(!isset($app_strings)) {
892                 $GLOBALS['log']->fatal("Unable to load the application language strings");
893                 return null;
894         }
895
896         // If we are in debug mode for translating, turn on the prefix now!
897         if($sugar_config['translation_string_prefix']) {
898                 foreach($app_strings as $entry_key=>$entry_value) {
899                         $app_strings[$entry_key] = $language.' '.$entry_value;
900                 }
901         }
902         if(isset($_SESSION['show_deleted'])) {
903                 $app_strings['LBL_DELETE_BUTTON'] = $app_strings['LBL_UNDELETE_BUTTON'];
904                 $app_strings['LBL_DELETE_BUTTON_LABEL'] = $app_strings['LBL_UNDELETE_BUTTON_LABEL'];
905                 $app_strings['LBL_DELETE_BUTTON_TITLE'] = $app_strings['LBL_UNDELETE_BUTTON_TITLE'];
906                 $app_strings['LBL_DELETE'] = $app_strings['LBL_UNDELETE'];
907         }
908
909         $app_strings['LBL_ALT_HOT_KEY'] = get_alt_hot_key();
910
911         $return_value = $app_strings;
912         $app_strings = $temp_app_strings;
913
914         sugar_cache_put($cache_key, $return_value);
915
916         return $return_value;
917 }
918
919 /**
920  * This function retrieves a module's language file and returns the array of strings included.
921  *
922  * @param string $language specific language to load
923  * @param string $module module name to load strings for
924  * @param bool $refresh optional, true if you want to rebuild the language strings
925  * @return array lang strings
926  */
927 function return_module_language($language, $module, $refresh=false)
928 {
929         global $mod_strings;
930         global $sugar_config;
931         global $currentModule;
932
933         // Jenny - Bug 8119: Need to check if $module is not empty
934         if (empty($module)) {
935                 $stack  = debug_backtrace();
936                 $GLOBALS['log']->warn("Variable module is not in return_module_language ". var_export($stack, true));
937                 return array();
938         }
939
940     if( !$refresh )
941     {
942         $cache_key = LanguageManager::getLanguageCacheKey($module, $language);
943         // Check for cached value
944         $cache_entry = sugar_cache_retrieve($cache_key);
945         if(!empty($cache_entry))
946         {
947             return $cache_entry;
948         }
949     }
950         // Store the current mod strings for later
951         $temp_mod_strings = $mod_strings;
952         $loaded_mod_strings = array();
953         $language_used = $language;
954         $default_language = $sugar_config['default_language'];
955
956         if(empty($language)) {
957                 $language = $default_language;
958         }
959
960         // Bug 21559 - So we can get all the strings defined in the template, refresh
961         // the vardefs file if the cached language file doesn't exist.
962     if(!file_exists($GLOBALS['sugar_config']['cache_dir'].'modules/'. $module . '/language/'.$language.'.lang.php')
963                         && !empty($GLOBALS['beanList'][$module])){
964                 $object = BeanFactory::getObjectName($module);
965                 VardefManager::refreshVardefs($module,$object);
966         }
967
968         $loaded_mod_strings = LanguageManager::loadModuleLanguage($module, $language,$refresh);
969
970         // cn: bug 6048 - merge en_us with requested language
971         if($language != $sugar_config['default_language'])
972         $loaded_mod_strings = sugarArrayMerge(
973             LanguageManager::loadModuleLanguage($module, $sugar_config['default_language'],$refresh),
974                 $loaded_mod_strings
975             );
976
977     // Load in en_us strings by default
978     if($language != 'en_us' && $sugar_config['default_language'] != 'en_us')
979         $loaded_mod_strings = sugarArrayMerge(
980             LanguageManager::loadModuleLanguage($module, 'en_us', $refresh),
981                 $loaded_mod_strings
982             );
983
984         // If we are in debug mode for translating, turn on the prefix now!
985         if($sugar_config['translation_string_prefix']) {
986                 foreach($loaded_mod_strings as $entry_key=>$entry_value) {
987                         $loaded_mod_strings[$entry_key] = $language_used.' '.$entry_value;
988                 }
989         }
990
991         $return_value = $loaded_mod_strings;
992         if(!isset($mod_strings)){
993                 $mod_strings = $return_value;
994         }
995         else
996                 $mod_strings = $temp_mod_strings;
997
998     $cache_key = LanguageManager::getLanguageCacheKey($module, $language);
999     sugar_cache_put($cache_key, $return_value);
1000         return $return_value;
1001 }
1002
1003
1004 /** This function retrieves an application language file and returns the array of strings included in the $mod_list_strings var.
1005  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1006  * All Rights Reserved.
1007  * Contributor(s): ______________________________________..
1008  * If you are using the current language, do not call this function unless you are loading it for the first time */
1009 function return_mod_list_strings_language($language,$module) {
1010         global $mod_list_strings;
1011         global $sugar_config;
1012         global $currentModule;
1013
1014         $cache_key = "mod_list_str_lang.".$language.$module;
1015
1016         // Check for cached value
1017         $cache_entry = sugar_cache_retrieve($cache_key);
1018         if(!empty($cache_entry))
1019         {
1020                 return $cache_entry;
1021         }
1022
1023         $language_used = $language;
1024         $temp_mod_list_strings = $mod_list_strings;
1025         $default_language = $sugar_config['default_language'];
1026
1027         if($currentModule == $module && isset($mod_list_strings) && $mod_list_strings != null) {
1028                 return $mod_list_strings;
1029         }
1030
1031         // cn: bug 6351 - include en_us if file langpack not available
1032         // cn: bug 6048 - merge en_us with requested language
1033         include("modules/$module/language/en_us.lang.php");
1034         $en_mod_list_strings = array();
1035         if($language_used != $default_language)
1036         $en_mod_list_strings = $mod_list_strings;
1037
1038         if(file_exists("modules/$module/language/$language.lang.php")) {
1039                 include("modules/$module/language/$language.lang.php");
1040         }
1041
1042         if(file_exists("modules/$module/language/$language.lang.override.php")){
1043                 include("modules/$module/language/$language.lang.override.php");
1044         }
1045
1046         if(file_exists("modules/$module/language/$language.lang.php.override")){
1047                 echo 'Please Change:<br>' . "modules/$module/language/$language.lang.php.override" . '<br>to<br>' . 'Please Change:<br>' . "modules/$module/language/$language.lang.override.php";
1048                 include("modules/$module/language/$language.lang.php.override");
1049         }
1050
1051         // cn: bug 6048 - merge en_us with requested language
1052         $mod_list_strings = sugarArrayMerge($en_mod_list_strings, $mod_list_strings);
1053
1054         // if we still don't have a language pack, then log an error
1055         if(!isset($mod_list_strings)) {
1056                 $GLOBALS['log']->fatal("Unable to load the application list language file for the selected language($language) or the default language($default_language) for module({$module})");
1057                 return null;
1058         }
1059
1060         $return_value = $mod_list_strings;
1061         $mod_list_strings = $temp_mod_list_strings;
1062
1063         sugar_cache_put($cache_key, $return_value);
1064         return $return_value;
1065 }
1066
1067
1068 /** This function retrieves a theme's language file and returns the array of strings included.
1069  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1070  * All Rights Reserved.
1071  * Contributor(s): ______________________________________..
1072  */
1073 function return_theme_language($language, $theme)
1074 {
1075         global $mod_strings, $sugar_config, $currentModule;
1076
1077         $language_used = $language;
1078         $default_language = $sugar_config['default_language'];
1079
1080         include(SugarThemeRegistry::get($theme)->getFilePath()."/language/$current_language.lang.php");
1081         if(file_exists(SugarThemeRegistry::get($theme)->getFilePath()."/language/$current_language.lang.override.php")){
1082                 include(SugarThemeRegistry::get($theme)->getFilePath()."/language/$current_language.lang.override.php");
1083         }
1084         if(file_exists(SugarThemeRegistry::get($theme)->getFilePath()."/language/$current_language.lang.php.override")){
1085                 echo 'Please Change:<br>' . SugarThemeRegistry::get($theme)->getFilePath()."/language/$current_language.lang.php.override" . '<br>to<br>' . 'Please Change:<br>' . SugarThemeRegistry::get($theme)->getFilePath()."/language/$current_language.lang.override.php";
1086                 include(SugarThemeRegistry::get($theme)->getFilePath()."/language/$current_language.lang.php.override");
1087         }
1088         if(!isset($theme_strings))
1089         {
1090                 $GLOBALS['log']->warn("Unable to find the theme file for language: ".$language." and theme: ".$theme);
1091                 require(SugarThemeRegistry::get($theme)->getFilePath()."/language/$default_language.lang.php");
1092                 $language_used = $default_language;
1093         }
1094
1095         if(!isset($theme_strings))
1096         {
1097                 $GLOBALS['log']->fatal("Unable to load the theme($theme) language file for the selected language($language) or the default language($default_language)");
1098                 return null;
1099         }
1100
1101         // If we are in debug mode for translating, turn on the prefix now!
1102         if($sugar_config['translation_string_prefix'])
1103         {
1104                 foreach($theme_strings as $entry_key=>$entry_value)
1105                 {
1106                         $theme_strings[$entry_key] = $language_used.' '.$entry_value;
1107                 }
1108         }
1109
1110         return $theme_strings;
1111 }
1112
1113
1114
1115 /** If the session variable is defined and is not equal to "" then return it.  Otherwise, return the default value.
1116  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1117  * All Rights Reserved.
1118  * Contributor(s): ______________________________________..
1119  */
1120 function return_session_value_or_default($varname, $default)
1121 {
1122         if(isset($_SESSION[$varname]) && $_SESSION[$varname] != "")
1123         {
1124                 return $_SESSION[$varname];
1125         }
1126
1127         return $default;
1128 }
1129
1130 /**
1131  * Creates an array of where restrictions.  These are used to construct a where SQL statement on the query
1132  * It looks for the variable in the $_REQUEST array.  If it is set and is not "" it will create a where clause out of it.
1133  * @param &$where_clauses - The array to append the clause to
1134  * @param $variable_name - The name of the variable to look for an add to the where clause if found
1135  * @param $SQL_name - [Optional] If specified, this is the SQL column name that is used.  If not specified, the $variable_name is used as the SQL_name.
1136  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1137  * All Rights Reserved.
1138  * Contributor(s): ______________________________________..
1139  */
1140 function append_where_clause(&$where_clauses, $variable_name, $SQL_name = null)
1141 {
1142         if($SQL_name == null)
1143         {
1144                 $SQL_name = $variable_name;
1145         }
1146
1147         if(isset($_REQUEST[$variable_name]) && $_REQUEST[$variable_name] != "")
1148         {
1149                 array_push($where_clauses, "$SQL_name like '".$GLOBALS['db']->quote($_REQUEST[$variable_name])."%'");
1150         }
1151 }
1152
1153 /**
1154  * Generate the appropriate SQL based on the where clauses.
1155  * @param $where_clauses - An Array of individual where clauses stored as strings
1156  * @returns string where_clause - The final SQL where clause to be executed.
1157  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1158  * All Rights Reserved.
1159  * Contributor(s): ______________________________________..
1160  */
1161 function generate_where_statement($where_clauses)
1162 {
1163         $where = "";
1164         foreach($where_clauses as $clause)
1165         {
1166                 if($where != "")
1167                 $where .= " and ";
1168                 $where .= $clause;
1169         }
1170
1171         $GLOBALS['log']->info("Here is the where clause for the list view: $where");
1172         return $where;
1173 }
1174
1175 /**
1176  * determines if a passed string matches the criteria for a Sugar GUID
1177  * @param string $guid
1178  * @return bool False on failure
1179  */
1180 function is_guid($guid) {
1181         if(strlen($guid) != 36) {
1182                 return false;
1183         }
1184
1185         if(preg_match("/\w{8}-\w{4}-\w{4}-\w{4}-\w{12}/i", $guid)) {
1186                 return true;
1187         }
1188
1189         return true;;
1190 }
1191
1192
1193 /**
1194  * A temporary method of generating GUIDs of the correct format for our DB.
1195  * @return String contianing a GUID in the format: aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
1196  *
1197  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1198  * All Rights Reserved.
1199  * Contributor(s): ______________________________________..
1200  */
1201 function create_guid()
1202 {
1203         $microTime = microtime();
1204         list($a_dec, $a_sec) = explode(" ", $microTime);
1205
1206         $dec_hex = dechex($a_dec* 1000000);
1207         $sec_hex = dechex($a_sec);
1208
1209         ensure_length($dec_hex, 5);
1210         ensure_length($sec_hex, 6);
1211
1212         $guid = "";
1213         $guid .= $dec_hex;
1214         $guid .= create_guid_section(3);
1215         $guid .= '-';
1216         $guid .= create_guid_section(4);
1217         $guid .= '-';
1218         $guid .= create_guid_section(4);
1219         $guid .= '-';
1220         $guid .= create_guid_section(4);
1221         $guid .= '-';
1222         $guid .= $sec_hex;
1223         $guid .= create_guid_section(6);
1224
1225         return $guid;
1226
1227 }
1228
1229 function create_guid_section($characters)
1230 {
1231         $return = "";
1232         for($i=0; $i<$characters; $i++)
1233         {
1234                 $return .= dechex(mt_rand(0,15));
1235         }
1236         return $return;
1237 }
1238
1239 function ensure_length(&$string, $length)
1240 {
1241         $strlen = strlen($string);
1242         if($strlen < $length)
1243         {
1244                 $string = str_pad($string,$length,"0");
1245         }
1246         else if($strlen > $length)
1247         {
1248                 $string = substr($string, 0, $length);
1249         }
1250 }
1251
1252 function microtime_diff($a, $b) {
1253         list($a_dec, $a_sec) = explode(" ", $a);
1254         list($b_dec, $b_sec) = explode(" ", $b);
1255         return $b_sec - $a_sec + $b_dec - $a_dec;
1256 }
1257
1258 // check if Studio is displayed.
1259 function displayStudioForCurrentUser()
1260 {
1261     global $current_user;
1262     if ( $current_user->isAdmin() ) {
1263         return true;
1264     }
1265
1266
1267
1268         return true;
1269
1270 }
1271
1272 function displayWorkflowForCurrentUser()
1273 {
1274     $_SESSION['display_workflow_for_user'] = false;
1275     return false;
1276 }
1277
1278 // return an array with all modules where the user is an admin.
1279 function get_admin_modules_for_user($user) {
1280     $GLOBALS['log']->deprecated("get_admin_modules_for_user() is deprecated as of 6.2.2 and may disappear in the future, use Users->getDeveloperModules() instead");
1281
1282     if(!isset($user)){
1283         $modules = array();
1284         return $modules;
1285     }
1286
1287     return($user->getDeveloperModules());
1288
1289 }
1290
1291  function get_workflow_admin_modules_for_user($user){
1292     if (isset($_SESSION['get_workflow_admin_modules_for_user'])) {
1293         return $_SESSION['get_workflow_admin_modules_for_user'];
1294     }
1295
1296     global $moduleList;
1297     $workflow_mod_list = array();
1298     foreach($moduleList as $module){
1299                 $workflow_mod_list[$module] = $module;
1300         }
1301
1302         // This list is taken from teh previous version of workflow_utils.php
1303     $workflow_mod_list['Tasks'] = "Tasks";
1304     $workflow_mod_list['Calls'] = "Calls";
1305     $workflow_mod_list['Meetings'] = "Meetings";
1306     $workflow_mod_list['Notes'] = "Notes";
1307     $workflow_mod_list['ProjectTask'] = "Project Tasks";
1308         $workflow_mod_list['Leads'] = "Leads";
1309         $workflow_mod_list['Opportunities'] = "Opportunities";
1310         // End of list
1311
1312     $workflow_admin_modules = array();
1313     if(empty($user)) {
1314         return $workflow_admin_modules;
1315     }
1316     $actions = ACLAction::getUserActions($user->id);
1317     //check for ForecastSchedule because it doesn't exist in $workflow_mod_list
1318     if (isset($actions['ForecastSchedule']['module']['admin']['aclaccess']) && ($actions['ForecastSchedule']['module']['admin']['aclaccess']==ACL_ALLOW_DEV ||
1319         $actions['ForecastSchedule']['module']['admin']['aclaccess']==ACL_ALLOW_ADMIN_DEV)) {
1320         $workflow_admin_modules['Forecasts'] = 'Forecasts';
1321     }
1322     foreach ($workflow_mod_list as $key=>$val) {
1323         if(!in_array($val, $workflow_admin_modules) && ($val!='iFrames' && $val!='Feeds' && $val!='Home' && $val!='Dashboard'
1324             && $val!='Calendar' && $val!='Activities' && $val!='Reports') &&
1325            ($user->isDeveloperForModule($key))) {
1326                 $workflow_admin_modules[$key] = $val;
1327         }
1328     }
1329     $_SESSION['get_workflow_admin_modules_for_user'] = $workflow_admin_modules;
1330     return ($workflow_admin_modules);
1331 }
1332
1333 // Check if user is admin for at least one module.
1334 function is_admin_for_any_module($user) {
1335     if (!isset($user)){
1336         return false;
1337     }
1338     if($user->isAdmin()) {
1339         return true;
1340     }
1341     return false;
1342 }
1343
1344
1345 // Check if user is admin for a specific module.
1346 function is_admin_for_module($user,$module) {
1347     if (!isset($user)) {
1348         return false;
1349     }
1350     if ($user->isAdmin()) {
1351         return true;
1352     }
1353     return false;
1354 }
1355
1356
1357 /**
1358  * Check if user id belongs to a system admin.
1359  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1360  * All Rights Reserved.
1361  * Contributor(s): ______________________________________..
1362  */
1363 function is_admin($user) {
1364     if(empty($user)) {
1365         return false;
1366     }
1367
1368         return $user->isAdmin();
1369 }
1370
1371 /**
1372  * Return the display name for a theme if it exists.
1373  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1374  * All Rights Reserved.
1375  * Contributor(s): ______________________________________..
1376  *
1377  * @deprecated use SugarThemeRegistry::get($theme)->name instead
1378  */
1379 function get_theme_display($theme)
1380 {
1381         return SugarThemeRegistry::get($theme)->name;
1382 }
1383
1384 /**
1385  * Return an array of directory names.
1386  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1387  * All Rights Reserved.
1388  * Contributor(s): ______________________________________..
1389  *
1390  * @deprecated use SugarThemeRegistry::availableThemes() instead.
1391  */
1392 function get_themes()
1393 {
1394     return SugarThemeRegistry::availableThemes();
1395 }
1396
1397 /**
1398  * THIS FUNCTION IS DEPRECATED AND SHOULD NOT BE USED; USE get_select_options_with_id()
1399  * Create HTML to display select options in a dropdown list.  To be used inside
1400  * of a select statement in a form.
1401  * param $option_list - the array of strings to that contains the option list
1402  * param $selected - the string which contains the default value
1403  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1404  * All Rights Reserved.
1405  * Contributor(s): ______________________________________..
1406  */
1407 function get_select_options ($option_list, $selected) {
1408         return get_select_options_with_id($option_list, $selected);
1409 }
1410
1411 /**
1412  * Create HTML to display select options in a dropdown list.  To be used inside
1413  * of a select statement in a form.   This method expects the option list to have keys and values.  The keys are the ids.  The values are the display strings.
1414  * param $option_list - the array of strings to that contains the option list
1415  * param $selected - the string which contains the default value
1416  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1417  * All Rights Reserved.
1418  * Contributor(s): ______________________________________..
1419  */
1420 function get_select_options_with_id ($option_list, $selected_key) {
1421         return get_select_options_with_id_separate_key($option_list, $option_list, $selected_key);
1422 }
1423
1424
1425 /**
1426  * Create HTML to display select options in a dropdown list.  To be used inside
1427  * of a select statement in a form.   This method expects the option list to have keys and values.  The keys are the ids.  The values are the display strings.
1428  * param $label_list - the array of strings to that contains the option list
1429  * param $key_list - the array of strings to that contains the values list
1430  * param $selected - the string which contains the default value
1431  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1432  * All Rights Reserved.
1433  * Contributor(s): ______________________________________..
1434  */
1435 function get_select_options_with_id_separate_key ($label_list, $key_list, $selected_key, $massupdate=false) {
1436         global $app_strings;
1437         $select_options = "";
1438
1439         //for setting null selection values to human readable --None--
1440         $pattern = "/'0?'></";
1441         $replacement = "''>".$app_strings['LBL_NONE']."<";
1442     if($massupdate){
1443         $replacement .= "/OPTION>\n<OPTION value='__SugarMassUpdateClearField__'><"; // Giving the user the option to unset a drop down list. I.e. none means that it won't get updated
1444     }
1445
1446         if (empty($key_list)) $key_list = array();
1447         //create the type dropdown domain and set the selected value if $opp value already exists
1448         foreach ($key_list as $option_key=>$option_value) {
1449
1450                 $selected_string = '';
1451                 // the system is evaluating $selected_key == 0 || '' to true.  Be very careful when changing this.  Test all cases.
1452                 // The bug was only happening with one of the users in the drop down.  It was being replaced by none.
1453                 if (($option_key != '' && $selected_key == $option_key) || ($selected_key == '' && $option_key == '' && !$massupdate) || (is_array($selected_key) &&  in_array($option_key, $selected_key)))
1454                 {
1455                         $selected_string = 'selected ';
1456                 }
1457
1458                 $html_value = $option_key;
1459
1460                 $select_options .= "\n<OPTION ".$selected_string."value='$html_value'>$label_list[$option_key]</OPTION>";
1461         }
1462         $select_options = preg_replace($pattern, $replacement, $select_options);
1463         return $select_options;
1464 }
1465
1466
1467 /**
1468  * Call this method instead of die().
1469  * Then we call the die method with the error message that is passed in.
1470  */
1471 function sugar_die($error_message)
1472 {
1473         global $focus;
1474         sugar_cleanup();
1475         die($error_message);
1476 }
1477
1478
1479 /**
1480  * Create javascript to clear values of all elements in a form.
1481  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1482  * All Rights Reserved.
1483  * Contributor(s): ______________________________________..
1484  */
1485 function get_clear_form_js () {
1486         $the_script = <<<EOQ
1487 <script type="text/javascript" language="JavaScript">
1488 function clear_form(form) {
1489         var newLoc = 'index.php?action=' + form.action.value + '&module=' + form.module.value + '&query=true&clear_query=true';
1490         if(typeof(form.advanced) != 'undefined'){
1491                 newLoc += '&advanced=' + form.advanced.value;
1492         }
1493         document.location.href= newLoc;
1494 }
1495 </script>
1496 EOQ;
1497
1498         return $the_script;
1499 }
1500
1501 /**
1502  * Create javascript to set the cursor focus to specific field in a form
1503  * when the screen is rendered.  The field name is currently hardcoded into the
1504  * the function.
1505  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1506  * All Rights Reserved.
1507  * Contributor(s): ______________________________________..
1508  */
1509 function get_set_focus_js () {
1510         //TODO Clint 5/20 - Make this function more generic so that it can take in the target form and field names as variables
1511         $the_script = <<<EOQ
1512 <script type="text/javascript" language="JavaScript">
1513 <!-- Begin
1514 function set_focus() {
1515         if (document.forms.length > 0) {
1516                 for (i = 0; i < document.forms.length; i++) {
1517                         for (j = 0; j < document.forms[i].elements.length; j++) {
1518                                 var field = document.forms[i].elements[j];
1519                                 if ((field.type == "text" || field.type == "textarea" || field.type == "password") &&
1520                                                 !field.disabled && (field.name == "first_name" || field.name == "name" || field.name == "user_name" || field.name=="document_name")) {
1521                                         field.focus();
1522                     if (field.type == "text") {
1523                         field.select();
1524                     }
1525                                         break;
1526                         }
1527                         }
1528         }
1529         }
1530 }
1531 //  End -->
1532 </script>
1533 EOQ;
1534
1535         return $the_script;
1536 }
1537
1538 /**
1539  * Very cool algorithm for sorting multi-dimensional arrays.  Found at http://us2.php.net/manual/en/function.array-multisort.php
1540  * Syntax: $new_array = array_csort($array [, 'col1' [, SORT_FLAG [, SORT_FLAG]]]...);
1541  * Explanation: $array is the array you want to sort, 'col1' is the name of the column
1542  * you want to sort, SORT_FLAGS are : SORT_ASC, SORT_DESC, SORT_REGULAR, SORT_NUMERIC, SORT_STRING
1543  * you can repeat the 'col',FLAG,FLAG, as often you want, the highest prioritiy is given to
1544  * the first - so the array is sorted by the last given column first, then the one before ...
1545  * Example: $array = array_csort($array,'town','age',SORT_DESC,'name');
1546  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1547  * All Rights Reserved.
1548  * Contributor(s): ______________________________________..
1549  */
1550 function array_csort() {
1551         $args = func_get_args();
1552         $marray = array_shift($args);
1553         $i = 0;
1554
1555         $msortline = "return(array_multisort(";
1556         foreach ($args as $arg) {
1557                 $i++;
1558                 if (is_string($arg)) {
1559                         foreach ($marray as $row) {
1560                                 $sortarr[$i][] = $row[$arg];
1561                         }
1562                 } else {
1563                         $sortarr[$i] = $arg;
1564                 }
1565                 $msortline .= "\$sortarr[".$i."],";
1566         }
1567         $msortline .= "\$marray));";
1568
1569         eval($msortline);
1570         return $marray;
1571 }
1572
1573 /**
1574  * Converts localized date format string to jscalendar format
1575  * Example: $array = array_csort($array,'town','age',SORT_DESC,'name');
1576  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1577  * All Rights Reserved.
1578  * Contributor(s): ______________________________________..
1579  */
1580 function parse_calendardate($local_format) {
1581         preg_match('/\(?([^-]{1})[^-]*-([^-]{1})[^-]*-([^-]{1})[^-]*\)/', $local_format, $matches);
1582         $calendar_format = "%" . $matches[1] . "-%" . $matches[2] . "-%" . $matches[3];
1583         return str_replace(array("y", "ï¿„1�7", "a", "j"), array("Y", "Y", "Y", "d"), $calendar_format);
1584 }
1585
1586
1587
1588
1589
1590 function translate($string, $mod='', $selectedValue=''){
1591         //$test_start = microtime();
1592         //static $mod_strings_results = array();
1593         if(!empty($mod)){
1594                 global $current_language;
1595                 //Bug 31275
1596                 if(isset($_REQUEST['login_language'])){
1597                     $current_language = ($_REQUEST['login_language'] == $current_language)? $current_language : $_REQUEST['login_language'];
1598                 }
1599                 $mod_strings = return_module_language($current_language, $mod);
1600
1601         }else{
1602                 global $mod_strings;
1603         }
1604
1605         $returnValue = '';
1606         global $app_strings, $app_list_strings;
1607
1608         if(isset($mod_strings[$string]))
1609         $returnValue = $mod_strings[$string];
1610         else if(isset($app_strings[$string]))
1611         $returnValue = $app_strings[$string];
1612         else if(isset($app_list_strings[$string]))
1613         $returnValue = $app_list_strings[$string];
1614         else if(isset($app_list_strings['moduleList']) && isset($app_list_strings['moduleList'][$string]))
1615         $returnValue = $app_list_strings['moduleList'][$string];
1616
1617
1618         //$test_end = microtime();
1619         //
1620         //    $mod_strings_results[$mod] = microtime_diff($test_start,$test_end);
1621         //
1622         //    echo("translate results:");
1623         //    $total_time = 0;
1624         //    $total_strings = 0;
1625         //    foreach($mod_strings_results as $key=>$value)
1626         //    {
1627         //        echo("Module $key \t\t time $value \t\t<br>");
1628         //        $total_time += $value;
1629         //    }
1630         //
1631         //    echo("Total time: $total_time<br>");
1632
1633
1634
1635         if(empty($returnValue)){
1636                 return $string;
1637         }
1638
1639         if(is_array($returnValue) && ! empty($selectedValue) && isset($returnValue[$selectedValue]) ){
1640                 return $returnValue[$selectedValue];
1641         }
1642
1643         return $returnValue;
1644 }
1645
1646 function unTranslateNum($num) {
1647         static $dec_sep;
1648         static $num_grp_sep;
1649         global $current_user, $sugar_config;
1650
1651         if($dec_sep == null) {
1652             $user_dec_sep = $current_user->getPreference('dec_sep');
1653             $dec_sep = (empty($user_dec_sep) ? $sugar_config['default_decimal_seperator'] : $user_dec_sep);
1654         }
1655         if($num_grp_sep == null) {
1656             $user_num_grp_sep = $current_user->getPreference('num_grp_sep');
1657             $num_grp_sep = (empty($user_num_grp_sep) ? $sugar_config['default_number_grouping_seperator'] : $user_num_grp_sep);
1658         }
1659
1660         $num = preg_replace("'" . preg_quote($num_grp_sep) . "'", '', $num);
1661         $num = preg_replace("'" . preg_quote($dec_sep) . "'", '.', $num);
1662         return $num;
1663
1664 }
1665
1666 function add_http($url) {
1667         if(!preg_match("@://@i", $url)) {
1668                 $scheme = "http";
1669                 if(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') {
1670                         $scheme = 'https';
1671                 }
1672
1673                 return "{$scheme}://{$url}";
1674         }
1675
1676         return $url;
1677 }
1678
1679 /**
1680  * returns a default array of XSS tags to clean
1681  * @return array
1682  */
1683 function getDefaultXssTags() {
1684         $tmp = array(
1685         "applet" => "applet",
1686         "base" => "base",
1687         "embed" => "embed",
1688         "form" => "form",
1689         "frame" => "frame",
1690         "frameset" => "frameset",
1691         "iframe" => "iframe",
1692         "import" => "\?import",
1693         "layer" => "layer",
1694         "link" => "link",
1695         "object" => "object",
1696         "script" => "script",
1697         "xmp" => "xmp",
1698         );
1699
1700         $ret = base64_encode(serialize($tmp));
1701
1702         return $ret;
1703 }
1704
1705 /**
1706  * Remove potential xss vectors from strings
1707  * @param string str String to search for XSS attack vectors
1708  * @param bool cleanImg Flag to allow <img> tags to survive - only used by InboundEmail for inline images.
1709  * @return string
1710  */
1711 function remove_xss($str, $cleanImg=true)
1712 {
1713     $potentials = clean_xss($str, $cleanImg);
1714     if(is_array($potentials) && !empty($potentials)) {
1715         foreach($potentials as $bad) {
1716             $str = str_replace($bad, "", $str);
1717         }
1718     }
1719     return $str;
1720 }
1721
1722 /**
1723  * Detects typical XSS attack patterns
1724  * @param string str String to search for XSS attack vectors
1725  * @param bool cleanImg Flag to allow <img> tags to survive - only used by InboundEmail for inline images.
1726  * @return array Array of matches, empty on clean string
1727  */
1728 function clean_xss($str, $cleanImg=true) {
1729         global $sugar_config;
1730
1731         if(empty($sugar_config['email_xss']))
1732         $sugar_config['email_xss'] = getDefaultXssTags();
1733
1734         $arr = unserialize(base64_decode($sugar_config['email_xss']));
1735
1736         $regex = '';
1737         foreach($arr as $v) {
1738                 if(!empty($regex)) {
1739                         $regex .= "|";
1740                 }
1741                 $regex .= $v;
1742         }
1743
1744         $tag_regex        = "#<({$regex})[^>]*>?#sim";
1745
1746         // cn: bug 13079 - "on\w" matched too many non-events (cONTact, strONG, etc.)
1747         $jsEvents  = "onblur|onfocus|oncontextmenu|onresize|onscroll|onunload|ondblclick|onclick|";
1748         $jsEvents .= "onmouseup|onmouseover|onmousedown|onmouseenter|onmouseleave|onmousemove|onload|onchange|";
1749         $jsEvents .= "onreset|onselect|onsubmit|onkeydown|onkeypress|onkeyup|onabort|onerror|ondragdrop";
1750
1751         $attribute_regex        = "#<.+({$jsEvents})[^=>]*=[^>]*>#sim";
1752         $javascript_regex       = '@<[^/>][^>]+(expression\(|j\W*a\W*v\W*a|v\W*b\W*s\W*c\W*r|&#|/\*|\*/)[^>]*>@sim';
1753         $imgsrc_regex           = '#<[^>]+src[^=]*=([^>]*?http(s)?://[^>]*)>#sim';
1754         $css_url                        = '#url\(.*\.\w+\)#';
1755
1756
1757         $str = str_replace("\t", "", $str);
1758
1759         $matches = array_merge(
1760         xss_check_pattern($tag_regex, $str),
1761         xss_check_pattern($javascript_regex, $str)
1762         );
1763
1764
1765     $jsMatches = xss_check_pattern($attribute_regex, $str);
1766     if(!empty($jsMatches)){
1767         preg_match_all($attribute_regex, $str, $newMatches, PREG_PATTERN_ORDER);
1768         if(!empty($newMatches[0][0])){
1769             $matches2 = array_merge(xss_check_pattern("#({$jsEvents})#sim", $newMatches[0][0]));
1770             $matches = array_merge($matches, $matches2);
1771         }
1772     }
1773
1774         if($cleanImg) {
1775                 $matches = array_merge($matches,
1776                 xss_check_pattern($imgsrc_regex, $str)
1777                 );
1778         }
1779
1780         // cn: bug 13498 - custom white-list of allowed domains that vet remote images
1781         preg_match_all($css_url, $str, $cssUrlMatches, PREG_PATTERN_ORDER);
1782
1783         if(isset($sugar_config['security_trusted_domains']) && !empty($sugar_config['security_trusted_domains']) && is_array($sugar_config['security_trusted_domains'])) {
1784                 if(is_array($cssUrlMatches) && count($cssUrlMatches) > 0) {
1785                         // normalize whitelist
1786                         foreach($sugar_config['security_trusted_domains'] as $k => $v) {
1787                                 $sugar_config['security_trusted_domains'][$k] = strtolower($v);
1788                         }
1789
1790                         foreach($cssUrlMatches[0] as $match) {
1791                                 $domain = strtolower(substr(strstr($match, "://"), 3));
1792                                 $baseUrl = substr($domain, 0, strpos($domain, "/"));
1793
1794                                 if(!in_array($baseUrl, $sugar_config['security_trusted_domains'])) {
1795                                         $matches[] = $match;
1796                                 }
1797                         }
1798                 }
1799         } else {
1800                 $matches = array_merge($matches, $cssUrlMatches[0]);
1801         }
1802
1803         return $matches;
1804 }
1805
1806 /**
1807  * Helper function used by clean_xss() to parse for known-bad vectors
1808  * @param string pattern Regex pattern to use
1809  * @param string str String to parse for badness
1810  * @return array
1811  */
1812 function xss_check_pattern($pattern, $str) {
1813         preg_match_all($pattern, $str, $matches, PREG_PATTERN_ORDER);
1814         return $matches[1];
1815 }
1816
1817 /**
1818  * Designed to take a string passed in the URL as a parameter and clean all "bad" data from it
1819  *
1820  * @param string $str
1821  * @param string $filter which corresponds to a regular expression to use; choices are:
1822  *              "STANDARD" ( default )
1823  *              "STANDARDSPACE"
1824  *              "FILE"
1825  *              "NUMBER"
1826  *              "SQL_COLUMN_LIST"
1827  *              "PATH_NO_URL"
1828  *              "SAFED_GET"
1829  *              "UNIFIED_SEARCH"
1830  *              "AUTO_INCREMENT"
1831  *              "ALPHANUM"
1832  * @param boolean $dieOnBadData true (default) if you want to die if bad data if found, false if not
1833  */
1834 function clean_string($str, $filter = "STANDARD", $dieOnBadData = true) 
1835 {
1836         global  $sugar_config;
1837
1838         $filters = Array(
1839         "STANDARD"        => '#[^A-Z0-9\-_\.\@]#i',
1840         "STANDARDSPACE"   => '#[^A-Z0-9\-_\.\@\ ]#i',
1841         "FILE"            => '#[^A-Z0-9\-_\.]#i',
1842         "NUMBER"          => '#[^0-9\-]#i',
1843         "SQL_COLUMN_LIST" => '#[^A-Z0-9\(\),_\.]#i',
1844         "PATH_NO_URL"     => '#://#i',
1845         "SAFED_GET"               => '#[^A-Z0-9\@\=\&\?\.\/\-_~]#i', /* range of allowed characters in a GET string */
1846         "UNIFIED_SEARCH"        => "#[\\x00]#", /* cn: bug 3356 & 9236 - MBCS search strings */
1847         "AUTO_INCREMENT"        => '#[^0-9\-,\ ]#i',
1848         "ALPHANUM"        => '#[^A-Z0-9\-]#i',
1849         );
1850
1851         if (preg_match($filters[$filter], $str)) {
1852                 if (isset($GLOBALS['log']) && is_object($GLOBALS['log'])) {
1853                         $GLOBALS['log']->fatal("SECURITY: bad data passed in; string: {$str}");
1854                 }
1855                 if ( $dieOnBadData ) {
1856                         die("Bad data passed in; <a href=\"{$sugar_config['site_url']}\">Return to Home</a>");
1857                 }
1858                 return false;
1859         }
1860         else {
1861                 return $str;
1862         }
1863 }
1864
1865 function clean_special_arguments() {
1866         if(isset($_SERVER['PHP_SELF'])) {
1867                 if (!empty($_SERVER['PHP_SELF'])) clean_string($_SERVER['PHP_SELF'], 'SAFED_GET');
1868         }
1869         if (!empty($_REQUEST) && !empty($_REQUEST['login_theme'])) clean_string($_REQUEST['login_theme'], "STANDARD");
1870         if (!empty($_REQUEST) && !empty($_REQUEST['login_module'])) clean_string($_REQUEST['login_module'], "STANDARD");
1871         if (!empty($_REQUEST) && !empty($_REQUEST['login_action'])) clean_string($_REQUEST['login_action'], "STANDARD");
1872         if (!empty($_REQUEST) && !empty($_REQUEST['ck_login_theme_20'])) clean_string($_REQUEST['ck_login_theme_20'], "STANDARD");
1873         if (!empty($_SESSION) && !empty($_SESSION['authenticated_user_theme'])) clean_string($_SESSION['authenticated_user_theme'], "STANDARD");
1874         if (!empty($_REQUEST) && !empty($_REQUEST['module_name'])) clean_string($_REQUEST['module_name'], "STANDARD");
1875         if (!empty($_REQUEST) && !empty($_REQUEST['module'])) clean_string($_REQUEST['module'], "STANDARD");
1876         if (!empty($_POST) && !empty($_POST['parent_type'])) clean_string($_POST['parent_type'], "STANDARD");
1877         if (!empty($_REQUEST) && !empty($_REQUEST['mod_lang'])) clean_string($_REQUEST['mod_lang'], "STANDARD");
1878         if (!empty($_SESSION) && !empty($_SESSION['authenticated_user_language'])) clean_string($_SESSION['authenticated_user_language'], "STANDARD");
1879         if (!empty($_SESSION) && !empty($_SESSION['dyn_layout_file'])) clean_string($_SESSION['dyn_layout_file'], "PATH_NO_URL");
1880         if (!empty($_GET) && !empty($_GET['from'])) clean_string($_GET['from']);
1881         if (!empty($_GET) && !empty($_GET['gmto'])) clean_string($_GET['gmto'], "NUMBER");
1882         if (!empty($_GET) && !empty($_GET['case_number'])) clean_string($_GET['case_number'], "AUTO_INCREMENT");
1883         if (!empty($_GET) && !empty($_GET['bug_number'])) clean_string($_GET['bug_number'], "AUTO_INCREMENT");
1884         if (!empty($_GET) && !empty($_GET['quote_num'])) clean_string($_GET['quote_num'], "AUTO_INCREMENT");
1885         clean_superglobals('stamp', 'ALPHANUM'); // for vcr controls
1886         clean_superglobals('offset', 'ALPHANUM');
1887         clean_superglobals('return_action');
1888         clean_superglobals('return_module');
1889         return TRUE;
1890 }
1891
1892 /**
1893  * cleans the given key in superglobals $_GET, $_POST, $_REQUEST
1894  */
1895 function clean_superglobals($key, $filter = 'STANDARD') {
1896         if(isset($_GET[$key])) clean_string($_GET[$key], $filter);
1897         if(isset($_POST[$key])) clean_string($_POST[$key], $filter);
1898         if(isset($_REQUEST[$key])) clean_string($_REQUEST[$key], $filter);
1899 }
1900
1901 function set_superglobals($key, $val){
1902         $_GET[$key] = $val;
1903         $_POST[$key] = $val;
1904         $_REQUEST[$key] = $val;
1905 }
1906
1907 // Works in conjunction with clean_string() to defeat SQL injection, file inclusion attacks, and XSS
1908 function clean_incoming_data() {
1909         global $sugar_config;
1910
1911         if (get_magic_quotes_gpc() == 1) {
1912                 $req  = array_map("preprocess_param", $_REQUEST);
1913                 $post = array_map("preprocess_param", $_POST);
1914                 $get  = array_map("preprocess_param", $_GET);
1915         } else {
1916
1917                 $req  = array_map("securexss", $_REQUEST);
1918                 $post = array_map("securexss", $_POST);
1919                 $get  = array_map("securexss", $_GET);
1920         }
1921
1922         // PHP cannot stomp out superglobals reliably
1923         foreach($post as $k => $v) { $_POST[$k] = $v; }
1924         foreach($get  as $k => $v) { $_GET[$k] = $v; }
1925         foreach($req  as $k => $v) {
1926                  $_REQUEST[$k] = $v;
1927                  //ensure the keys are safe as well
1928                  securexsskey($k);
1929         }
1930         // Any additional variables that need to be cleaned should be added here
1931         if (isset($_REQUEST['login_theme'])) clean_string($_REQUEST['login_theme']);
1932         if (isset($_REQUEST['login_module'])) clean_string($_REQUEST['login_module']);
1933         if (isset($_REQUEST['login_action'])) clean_string($_REQUEST['login_action']);
1934         if (isset($_REQUEST['login_language'])) clean_string($_REQUEST['login_language']);
1935         if (isset($_REQUEST['action'])) clean_string($_REQUEST['action']);
1936         if (isset($_REQUEST['module'])) clean_string($_REQUEST['module']);
1937         if (isset($_REQUEST['record'])) clean_string($_REQUEST['record'], 'STANDARDSPACE');
1938         if (isset($_SESSION['authenticated_user_theme'])) clean_string($_SESSION['authenticated_user_theme']);
1939         if (isset($_SESSION['authenticated_user_language'])) clean_string($_SESSION['authenticated_user_language']);
1940         if (isset($_REQUEST['language'])) clean_string($_REQUEST['language']);
1941         if (isset($sugar_config['default_theme'])) clean_string($sugar_config['default_theme']);
1942         if (isset($_REQUEST['offset'])) clean_string($_REQUEST['offset']);
1943         if (isset($_REQUEST['stamp'])) clean_string($_REQUEST['stamp']);
1944
1945         if(isset($_REQUEST['lvso'])){
1946                         set_superglobals('lvso', (strtolower($_REQUEST['lvso']) === 'desc')?'desc':'asc');
1947         }
1948         // Clean "offset" and "order_by" parameters in URL
1949         foreach ($_REQUEST as $key => $val) {
1950                 if (str_end($key, "_offset")) {
1951                         clean_string($_REQUEST[$key], "ALPHANUM"); // keep this ALPHANUM for disable_count_query
1952                         set_superglobals($key, $_REQUEST[$key]);
1953                 }
1954                 elseif (str_end($key, "_ORDER_BY")) {
1955                         clean_string($_REQUEST[$key], "SQL_COLUMN_LIST");
1956                         set_superglobals($key, $_REQUEST[$key]);
1957                 }
1958         }
1959
1960
1961         return 0;
1962 }
1963
1964 // Returns TRUE if $str begins with $begin
1965 function str_begin($str, $begin) {
1966         return (substr($str, 0, strlen($begin)) == $begin);
1967 }
1968
1969 // Returns TRUE if $str ends with $end
1970 function str_end($str, $end) {
1971         return (substr($str, strlen($str) - strlen($end)) == $end);
1972 }
1973
1974 function securexss($value) {
1975         if(is_array($value)){
1976         $new = array();
1977         foreach($value as $key=>$val){
1978                 $new[$key] = securexss($val);
1979         }
1980         return $new;
1981     }
1982         static $xss_cleanup=  array('"' =>'&quot;', "'" =>  '&#039;' , '<' =>'&lt;' , '>'=>'&gt;');
1983         $value = preg_replace(array('/javascript:/i', '/\0/'), array('java script:', ''), $value);
1984         $value = preg_replace('/javascript:/i', 'java script:', $value);
1985         return str_replace(array_keys($xss_cleanup), array_values($xss_cleanup), $value);
1986 }
1987
1988 function securexsskey($value, $die=true){
1989         global $sugar_config;
1990         $matches = array();
1991         preg_match("/[\'\"\<\>]/", $value, $matches);
1992         if(!empty($matches)){
1993                 if($die){
1994                         die("Bad data passed in; <a href=\"{$sugar_config['site_url']}\">Return to Home</a>");
1995                 }else{
1996                         unset($_REQUEST[$value]);
1997                         unset($_POST[$value]);
1998                         unset($_GET[$value]);
1999                 }
2000         }
2001 }
2002
2003 function preprocess_param($value){
2004         if(is_string($value)){
2005                 if(get_magic_quotes_gpc() == 1){
2006                         $value = stripslashes($value);
2007                 }
2008
2009                 $value = securexss($value);
2010         }
2011
2012
2013         return $value;
2014
2015
2016 }
2017
2018 function set_register_value($category, $name, $value){
2019     return sugar_cache_put("{$category}:{$name}", $value);
2020 }
2021
2022 function get_register_value($category,$name){
2023     return sugar_cache_retrieve("{$category}:{$name}");
2024 }
2025
2026 function clear_register_value($category,$name){
2027     return sugar_cache_clear("{$category}:{$name}");
2028 }
2029 // this function cleans id's when being imported
2030 function convert_id($string)
2031 {
2032         return preg_replace_callback( '|[^A-Za-z0-9\-]|',
2033         create_function(
2034         // single quotes are essential here,
2035         // or alternative escape all $ as \$
2036         '$matches',
2037         'return ord($matches[0]);'
2038          ) ,$string);
2039 }
2040
2041 /**
2042  * @deprecated use SugarTheme::getImage()
2043  */
2044 function get_image($image,$other_attributes,$width="",$height="")
2045 {
2046     return SugarThemeRegistry::current()->getImage(basename($image),
2047         $other_attributes,
2048         empty($width) ? null : $width,
2049         empty($height) ? null : $height
2050         );
2051 }
2052 /**
2053  * @deprecated use SugarTheme::getImageURL()
2054  */
2055 function getImagePath($image_name)
2056 {
2057     return SugarThemeRegistry::current()->getImageURL($image_name);
2058 }
2059
2060 function getWebPath($relative_path){
2061         //if it has  a :// then it isn't a relative path
2062         if(substr_count($relative_path, '://') > 0) return $relative_path;
2063         if(defined('TEMPLATE_URL'))$relative_path = SugarTemplateUtilities::getWebPath($relative_path);
2064         return $relative_path;
2065 }
2066
2067 function getJSPath($relative_path, $additional_attrs=''){
2068         if(defined('TEMPLATE_URL'))$relative_path = SugarTemplateUtilities::getWebPath($relative_path);
2069         if(empty($GLOBALS['sugar_config']['js_custom_version']))$GLOBALS['sugar_config']['js_custom_version'] = 1;
2070         $js_version_key = isset($GLOBALS['js_version_key'])?$GLOBALS['js_version_key']:'';
2071         $path = $relative_path . '?s=' . $js_version_key . '&c=' . $GLOBALS['sugar_config']['js_custom_version'] ;
2072         if ( inDeveloperMode() ) $path .= '&developerMode='.mt_rand();
2073         if(!empty($additonal_attrs)) $path .= '&' . $additional_attrs;
2074         return $path;
2075 }
2076
2077 function getSWFPath($relative_path, $additional_params=''){
2078         $path = $relative_path;
2079         if (!empty($additional_params)){
2080                 $path .= '?' . $additional_params;
2081         }
2082         if (defined('TEMPLATE_URL')){
2083                 $path = TEMPLATE_URL . '/' . $path;
2084         }
2085         return $path;
2086 }
2087
2088
2089
2090
2091
2092 function getSQLDate($date_str)
2093 {
2094         if (preg_match('/^(\d{1,2})-(\d{1,2})-(\d{4})$/',$date_str,$match))
2095         {
2096                 if ( strlen($match[2]) == 1)
2097                 {
2098                         $match[2] = "0".$match[2];
2099                 }
2100                 if ( strlen($match[1]) == 1)
2101                 {
2102                         $match[1] = "0".$match[1];
2103                 }
2104                 return "{$match[3]}-{$match[1]}-{$match[2]}";
2105         }
2106         else if (preg_match('/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/',$date_str,$match))
2107         {
2108                 if ( strlen($match[2]) == 1)
2109                 {
2110                         $match[2] = "0".$match[2];
2111                 }
2112                 if ( strlen($match[1]) == 1)
2113                 {
2114                         $match[1] = "0".$match[1];
2115                 }
2116                 return "{$match[3]}-{$match[1]}-{$match[2]}";
2117         }
2118         else
2119         {
2120                 return "";
2121         }
2122 }
2123
2124 function clone_history(&$db, $from_id,$to_id, $to_type)
2125 {
2126         global $timedate;
2127         $old_note_id=null;
2128         $old_filename=null;
2129         require_once('include/upload_file.php');
2130         $tables = array('calls'=>'Call', 'meetings'=>'Meeting', 'notes'=>'Note', 'tasks'=>'Task');
2131
2132         $location=array('Email'=>"modules/Emails/Email.php",
2133         'Call'=>"modules/Calls/Call.php",
2134         'Meeting'=>"modules/Meetings/Meeting.php",
2135         'Note'=>"modules/Notes/Note.php",
2136         'Tasks'=>"modules/Tasks/Task.php",
2137         );
2138
2139
2140         foreach($tables as $table=>$bean_class)
2141         {
2142
2143                 if (!class_exists($bean_class))
2144                 {
2145                         require_once($location[$bean_class]);
2146                 }
2147
2148                 $bProcessingNotes=false;
2149                 if ($table=='notes')
2150                 {
2151                         $bProcessingNotes=true;
2152                 }
2153                 $query = "SELECT id FROM $table WHERE parent_id='$from_id'";
2154                 $results = $db->query($query);
2155                 while($row = $db->fetchByAssoc($results))
2156                 {
2157                         //retrieve existing record.
2158                         $bean= new $bean_class();
2159                         $bean->retrieve($row['id']);
2160                         //process for new instance.
2161                         if ($bProcessingNotes)
2162                         {
2163                                 $old_note_id=$row['id'];
2164                                 $old_filename=$bean->filename;
2165                         }
2166                         $bean->id=null;
2167                         $bean->parent_id=$to_id;
2168                         $bean->parent_type=$to_type;
2169                         if ($to_type=='Contacts' and in_array('contact_id',$bean->column_fields))
2170                         {
2171                                 $bean->contact_id=$to_id;
2172                         }
2173                         $bean->update_date_modified = false;
2174             $bean->update_modified_by = false;
2175             if(isset($bean->date_modified))
2176                 $bean->date_modified = $timedate->to_db($bean->date_modified);
2177             if(isset($bean->date_entered))
2178                 $bean->date_entered = $timedate->to_db($bean->date_entered);
2179                         //save
2180                         $new_id=$bean->save();
2181
2182                         //duplicate the file now. for notes.
2183                         if ($bProcessingNotes && !empty($old_filename))
2184                         {
2185                                 UploadFile::duplicate_file($old_note_id,$new_id,$old_filename);
2186                         }
2187                         //reset the values needed for attachment duplication.
2188                         $old_note_id=null;
2189                         $old_filename=null;
2190                 }
2191         }
2192 }
2193
2194 function values_to_keys($array)
2195 {
2196         $new_array = array();
2197         if(!is_array($array))
2198         {
2199                 return $new_array;
2200         }
2201         foreach($array as $arr){
2202                 $new_array[$arr] = $arr;
2203         }
2204         return $new_array;
2205 }
2206
2207 function clone_relationship(&$db, $tables = array(), $from_column, $from_id, $to_id)
2208 {
2209         foreach($tables as $table)
2210         {
2211
2212                 if ($table == 'emails_beans') {
2213                         $query = "SELECT * FROM $table WHERE $from_column='$from_id' and bean_module='Leads'";
2214                 } else {
2215                         $query = "SELECT * FROM $table WHERE $from_column='$from_id'";
2216                 }
2217                 $results = $db->query($query);
2218                 while($row = $db->fetchByAssoc($results))
2219                 {
2220                         $query = "INSERT INTO $table ";
2221                         $names = '';
2222                         $values = '';
2223                         $row[$from_column] = $to_id;
2224                         $row['id'] = create_guid();
2225                         if ($table=='emails_beans') {
2226                                 $row['bean_module'] =='Contacts';
2227                         }
2228
2229                         foreach($row as $name=>$value)
2230                         {
2231
2232                                 if(empty($names))
2233                                 {
2234                                         $names .= $name;
2235                                         $values .= "'$value'";
2236                                 } else
2237                                 {
2238                                         $names .= ', '. $name;
2239                                         $values .= ", '$value'";
2240                                 }
2241                         }
2242                         $query .= "($names)     VALUES ($values)";
2243                         $db->query($query);
2244                 }
2245         }
2246 }
2247
2248 function get_unlinked_email_query($type, $bean) {
2249     global $current_user;
2250
2251     $return_array['select']='SELECT emails.id ';
2252     $return_array['from']='FROM emails ';
2253     $return_array['where']="";
2254         $return_array['join'] = " JOIN (select DISTINCT email_id from emails_email_addr_rel eear
2255
2256         join email_addr_bean_rel eabr on eabr.bean_id ='$bean->id' and eabr.bean_module = '$bean->module_dir' and
2257         eabr.email_address_id = eear.email_address_id and eabr.deleted=0
2258         where eear.deleted=0 and eear.email_id not in
2259         (select eb.email_id from emails_beans eb where eb.bean_module ='$bean->module_dir' and eb.bean_id = '$bean->id')
2260         ) derivedemails on derivedemails.email_id = emails.id";
2261     $return_array['join_tables'][0] = '';
2262
2263         if (isset($type) and !empty($type['return_as_array'])) {
2264                 return $return_array;
2265         }
2266
2267         return $return_array['select'] . $return_array['from'] . $return_array['where'] . $return_array['join'] ;
2268 } // fn
2269
2270 /**
2271  * Check to see if the number is empty or non-zero
2272  * @param $value
2273  * @return boolean
2274  **/
2275 function number_empty($value)
2276 {
2277         return empty($value) && $value != '0';
2278 }
2279
2280 function get_bean_select_array($add_blank=true, $bean_name, $display_columns, $where='', $order_by='', $blank_is_none=false)
2281 {
2282         global $beanFiles;
2283         require_once($beanFiles[$bean_name]);
2284         $focus = new $bean_name();
2285         $user_array = array();
2286
2287     $key = ($bean_name == 'EmailTemplate') ?  $bean_name : $bean_name . $display_columns. $where . $order_by;
2288         $user_array = get_register_value('select_array', $key );
2289         if(!$user_array)
2290         {
2291
2292                 $db = DBManagerFactory::getInstance();
2293                 $temp_result = Array();
2294                 $query = "SELECT {$focus->table_name}.id, {$display_columns} as display from {$focus->table_name} ";
2295                 $query .= "where ";
2296                 if ( $where != '')
2297                 {
2298                         $query .= $where." AND ";
2299                 }
2300
2301                 $query .=  " {$focus->table_name}.deleted=0";
2302
2303                 if ( $order_by != '')
2304                 {
2305                         $query .= " order by {$focus->table_name}.{$order_by}";
2306                 }
2307
2308                 $GLOBALS['log']->debug("get_user_array query: $query");
2309                 $result = $db->query($query, true, "Error filling in user array: ");
2310
2311                 if ($add_blank==true){
2312                         // Add in a blank row
2313                         if($blank_is_none == true) { // set 'blank row' to "--None--"
2314                                 global $app_strings;
2315                                 $temp_result[''] = $app_strings['LBL_NONE'];
2316                         } else {
2317                                 $temp_result[''] = '';
2318                         }
2319                 }
2320
2321                 // Get the id and the name.
2322                 while($row = $db->fetchByAssoc($result))
2323                 {
2324                         $temp_result[$row['id']] = $row['display'];
2325                 }
2326
2327                 $user_array = $temp_result;
2328                 set_register_value('select_array', $key ,$temp_result);
2329         }
2330
2331         return $user_array;
2332
2333 }
2334 /**
2335  *
2336  *
2337  * @param unknown_type $listArray
2338  */
2339 // function parse_list_modules
2340 // searches a list for items in a user's allowed tabs and returns an array that removes unallowed tabs from list
2341 function parse_list_modules(&$listArray)
2342 {
2343         global $modListHeader;
2344         $returnArray = array();
2345
2346         foreach($listArray as $optionName => $optionVal)
2347         {
2348                 if(array_key_exists($optionName, $modListHeader))
2349                 {
2350                         $returnArray[$optionName] = $optionVal;
2351                 }
2352
2353                 // special case for projects
2354                 if(array_key_exists('Project', $modListHeader))
2355                 {
2356                         $returnArray['ProjectTask'] = $listArray['ProjectTask'];
2357                 }
2358         }
2359         $acldenied = ACLController::disabledModuleList($listArray,false);
2360         foreach($acldenied as $denied){
2361                 unset($returnArray[$denied]);
2362         }
2363         asort($returnArray);
2364
2365         return $returnArray;
2366 }
2367
2368 function display_notice($msg = false){
2369         global $error_notice;
2370         //no error notice - lets just display the error to the user
2371         if(!isset($error_notice)){
2372                 echo '<br>'.$msg . '<br>';
2373         }else{
2374                 $error_notice .= $msg . '<br>';
2375         }
2376 }
2377
2378 /* checks if it is a number that atleast has the plus at the beggining
2379  */
2380 function skype_formatted($number){
2381         //kbrill - BUG #15375
2382         if(isset($_REQUEST['action']) && $_REQUEST['action']=="Popup") {
2383                 return false;
2384         } else {
2385                 return substr($number, 0, 1) == '+' || substr($number, 0, 2) == '00' || substr($number, 0, 3) == '011';
2386         }
2387 //      return substr($number, 0, 1) == '+' || substr($number, 0, 2) == '00' || substr($number, 0, 2) == '011';
2388 }
2389
2390 function format_skype($number) {
2391     return preg_replace('/[^\+0-9]/','',$number);
2392 }
2393
2394 function insert_charset_header() {
2395         header('Content-Type: text/html; charset=UTF-8');
2396 }
2397
2398 function getCurrentURL()
2399 {
2400         $href = "http:";
2401         if(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on')
2402         {
2403                 $href = 'https:';
2404         }
2405
2406         $href.= "//".$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME'].'?'.$_SERVER['QUERY_STRING'];
2407         return $href;
2408 }
2409
2410 function javascript_escape($str) {
2411         $new_str = '';
2412
2413         for($i = 0; $i < strlen($str); $i++) {
2414
2415                 if(ord(substr($str, $i, 1))==10){
2416                         $new_str .= '\n';
2417                 }elseif(ord(substr($str, $i, 1))==13){
2418                         $new_str .= '\r';
2419                 }
2420                 else {
2421                         $new_str .= $str{$i};
2422                 }
2423         }
2424
2425         $new_str = str_replace("'", "\\'", $new_str);
2426
2427         return $new_str;
2428 }
2429
2430 function js_escape($str, $keep=true){
2431         $str = html_entity_decode(str_replace("\\", "", $str), ENT_QUOTES);
2432
2433         if($keep){
2434                 $str = javascript_escape($str);
2435         }
2436         else {
2437                 $str = str_replace("'", " ", $str);
2438                 $str = str_replace('"', " ", $str);
2439         }
2440
2441         return $str;
2442
2443         //end function js_escape
2444 }
2445
2446 function br2nl($str) {
2447         $regex = "#<[^>]+br.+?>#i";
2448         preg_match_all($regex, $str, $matches);
2449
2450         foreach($matches[0] as $match) {
2451                 $str = str_replace($match, "<br>", $str);
2452         }
2453
2454         $brs = array('<br>','<br/>', '<br />');
2455         $str = str_replace("\r\n", "\n", $str); // make from windows-returns, *nix-returns
2456         $str = str_replace("\n\r", "\n", $str); // make from windows-returns, *nix-returns
2457         $str = str_replace("\r", "\n", $str); // make from windows-returns, *nix-returns
2458         $str = str_ireplace($brs, "\n", $str); // to retrieve it
2459
2460         return $str;
2461 }
2462
2463 /**
2464  * Private helper function for displaying the contents of a given variable.
2465  * This function is only intended to be used for SugarCRM internal development.
2466  * The ppd stands for Pre Print Die.
2467  */
2468 function _ppd($mixed)
2469 {
2470 }
2471
2472
2473 /**
2474  * Private helper function for displaying the contents of a given variable in
2475  * the Logger. This function is only intended to be used for SugarCRM internal
2476  * development. The pp stands for Pre Print.
2477  * @param $mixed var to print_r()
2478  * @param $die boolean end script flow
2479  * @param $displayStackTrace also show stack trace
2480  */
2481 function _ppl($mixed, $die=false, $displayStackTrace=false, $loglevel="fatal") {
2482         if(!isset($GLOBALS['log']) || empty($GLOBALS['log'])) {
2483
2484                 $GLOBALS['log'] = LoggerManager :: getLogger('SugarCRM');
2485         }
2486
2487
2488         $mix    = print_r($mixed, true); // send print_r() output to $mix
2489         $stack  = debug_backtrace();
2490
2491         $GLOBALS['log']->$loglevel('------------------------------ _ppLogger() output start -----------------------------');
2492         $GLOBALS['log']->$loglevel($mix);
2493         if($displayStackTrace) {
2494                 foreach($stack as $position) {
2495                         $GLOBALS['log']->$loglevel($position['file']."({$position['line']})");
2496                 }
2497         }
2498
2499         $GLOBALS['log']->$loglevel('------------------------------ _ppLogger() output end -----------------------------');
2500         $GLOBALS['log']->$loglevel('------------------------------ _ppLogger() file: '.$stack[0]['file'].' line#: '.$stack[0]['line'].'-----------------------------');
2501
2502         if($die) {
2503                 die();
2504         }
2505 }
2506
2507 /**
2508  * private helper function to quickly show the major, direct, field attributes of a given bean.
2509  * The ppf stands for Pre[formatted] Print Focus [object]
2510  * @param object bean The focus bean
2511  */
2512 function _ppf($bean, $die=false) {
2513 }
2514
2515
2516
2517 /**
2518  * Private helper function for displaying the contents of a given variable.
2519  * This function is only intended to be used for SugarCRM internal development.
2520  * The pp stands for Pre Print.
2521  */
2522 function _pp($mixed)
2523 {
2524 }
2525
2526 /**
2527  * Private helper function for displaying the contents of a given variable.
2528  * This function is only intended to be used for SugarCRM internal development.
2529  * The pp stands for Pre Print.
2530  */
2531 function _pstack_trace($mixed=NULL)
2532 {
2533 }
2534
2535 /**
2536  * Private helper function for displaying the contents of a given variable.
2537  * This function is only intended to be used for SugarCRM internal development.
2538  * The pp stands for Pre Print Trace.
2539  */
2540 function _ppt($mixed, $textOnly=false)
2541 {
2542 }
2543
2544 /**
2545  * Private helper function for displaying the contents of a given variable.
2546  * This function is only intended to be used for SugarCRM internal development.
2547  * The pp stands for Pre Print Trace Die.
2548  */
2549 function _pptd($mixed)
2550 {
2551 }
2552
2553 /**
2554  * Private helper function for decoding javascript UTF8
2555  * This function is only intended to be used for SugarCRM internal development.
2556  */
2557 function decodeJavascriptUTF8($str) {
2558 }
2559
2560 /**
2561  * Will check if a given PHP version string is supported (tested on this ver),
2562  * unsupported (results unknown), or invalid (something will break on this
2563  * ver).  Do not pass in any pararameter to default to a check against the
2564  * current environment's PHP version.
2565  *
2566  * @return 1 implies supported, 0 implies unsupported, -1 implies invalid
2567  */
2568 function check_php_version($sys_php_version = '') {
2569         $sys_php_version = empty($sys_php_version) ? constant('PHP_VERSION') : $sys_php_version;
2570         // versions below $min_considered_php_version considered invalid by default,
2571         // versions equal to or above this ver will be considered depending
2572         // on the rules that follow
2573         $min_considered_php_version = '5.2.1';
2574
2575         // only the supported versions,
2576         // should be mutually exclusive with $invalid_php_versions
2577         $supported_php_versions = array (
2578         '5.2.1', '5.2.2', '5.2.3', '5.2.4', '5.2.5', '5.2.6', '5.2.8', '5.3.0'
2579         );
2580         //Find out what Database the system is using.
2581         global $sugar_config;
2582         $dbType = '';
2583         if (isset($_REQUEST['setup_db_type'])) {
2584                 $dbType = $_REQUEST['setup_db_type'];
2585         } else if (isset ($sugar_config['dbconfig']) && isset ($sugar_config['dbconfig']['db_type'])) {
2586                 $dbType = $sugar_config['dbconfig']['db_type'];
2587         }
2588
2589         // invalid versions above the $min_considered_php_version,
2590         // should be mutually exclusive with $supported_php_versions
2591
2592         // SugarCRM prohibits install on PHP 5.2.7 on all platforms
2593         $invalid_php_versions = array('5.2.7');
2594
2595         // default unsupported
2596         $retval = 0;
2597
2598         // versions below $min_considered_php_version are invalid
2599         if(1 == version_compare($sys_php_version, $min_considered_php_version, '<')) {
2600                 $retval = -1;
2601         }
2602
2603         // supported version check overrides default unsupported
2604         foreach($supported_php_versions as $ver) {
2605                 if(1 == version_compare($sys_php_version, $ver, 'eq') || strpos($sys_php_version,$ver) !== false) {
2606                         $retval = 1;
2607                         break;
2608                 }
2609         }
2610
2611         // invalid version check overrides default unsupported
2612         foreach($invalid_php_versions as $ver) {
2613                 if(1 == version_compare($sys_php_version, $ver, 'eq') && strpos($sys_php_version,$ver) !== false) {
2614                         $retval = -1;
2615                         break;
2616                 }
2617         }
2618
2619     //allow a redhat distro to install, regardless of version.  We are assuming the redhat naming convention is followed
2620     //and the php version contains 'rh' characters
2621     if(strpos($sys_php_version, 'rh') !== false) {
2622         $retval = 1;
2623     }
2624
2625         return $retval;
2626 }
2627
2628 /**
2629  * Will check if a given IIS version string is supported (tested on this ver),
2630  * unsupported (results unknown), or invalid (something will break on this
2631  * ver).
2632  *
2633  * @return 1 implies supported, 0 implies unsupported, -1 implies invalid
2634  */
2635 function check_iis_version($sys_iis_version = '') {
2636
2637         $server_software = $_SERVER["SERVER_SOFTWARE"];
2638         $iis_version = '';
2639         if(strpos($server_software,'Microsoft-IIS') !== false && preg_match_all("/^.*\/(\d+\.?\d*)$/",  $server_software, $out))
2640             $iis_version = $out[1][0];
2641
2642     $sys_iis_version = empty($sys_iis_version) ? $iis_version : $sys_iis_version;
2643
2644     // versions below $min_considered_iis_version considered invalid by default,
2645     // versions equal to or above this ver will be considered depending
2646     // on the rules that follow
2647     $min_considered_iis_version = '6.0';
2648
2649     // only the supported versions,
2650     // should be mutually exclusive with $invalid_iis_versions
2651     $supported_iis_versions = array ('6.0', '7.0',);
2652     $unsupported_iis_versions = array();
2653     $invalid_iis_versions = array('5.0',);
2654
2655     // default unsupported
2656     $retval = 0;
2657
2658     // versions below $min_considered_iis_version are invalid
2659     if(1 == version_compare($sys_iis_version, $min_considered_iis_version, '<')) {
2660         $retval = -1;
2661     }
2662
2663     // supported version check overrides default unsupported
2664     foreach($supported_iis_versions as $ver) {
2665         if(1 == version_compare($sys_iis_version, $ver, 'eq') || strpos($sys_iis_version,$ver) !== false) {
2666             $retval = 1;
2667             break;
2668         }
2669     }
2670
2671     // unsupported version check overrides default unsupported
2672     foreach($unsupported_iis_versions as $ver) {
2673         if(1 == version_compare($sys_iis_version, $ver, 'eq') && strpos($sys_iis_version,$ver) !== false) {
2674             $retval = 0;
2675             break;
2676         }
2677     }
2678
2679     // invalid version check overrides default unsupported
2680     foreach($invalid_iis_versions as $ver) {
2681         if(1 == version_compare($sys_iis_version, $ver, 'eq') && strpos($sys_iis_version,$ver) !== false) {
2682             $retval = -1;
2683             break;
2684         }
2685     }
2686
2687     return $retval;
2688 }
2689
2690 function pre_login_check(){
2691         global $action, $login_error;
2692         if(!empty($action)&& $action == 'Login'){
2693
2694                 if(!empty($login_error)){
2695                         $login_error = htmlentities($login_error);
2696                         $login_error = str_replace(array("&lt;pre&gt;","&lt;/pre&gt;","\r\n", "\n"), "<br>", $login_error);
2697                         $_SESSION['login_error'] = $login_error;
2698                         echo '<script>
2699                                                 function set_focus() {}
2700                                                 if(document.getElementById("post_error")) {
2701                                                         document.getElementById("post_error").innerHTML="'. $login_error. '";
2702                                                         document.getElementById("cant_login").value=1;
2703                                                         document.getElementById("login_button").disabled = true;
2704                                                         document.getElementById("user_name").disabled = true;
2705                                                         //document.getElementById("user_password").disabled = true;
2706                                                 }
2707                                                 </script>';
2708                 }
2709         }
2710 }
2711
2712
2713
2714 function sugar_cleanup($exit = false) {
2715         static $called = false;
2716         if($called)return;
2717         $called = true;
2718         set_include_path(realpath(dirname(__FILE__) . '/..') . PATH_SEPARATOR . get_include_path());
2719         chdir(realpath(dirname(__FILE__) . '/..'));
2720         global $sugar_config;
2721         require_once('include/utils/LogicHook.php');
2722         LogicHook::initialize();
2723         $GLOBALS['logic_hook']->call_custom_logic('', 'server_round_trip');
2724
2725         //added this check to avoid errors during install.
2726         if (empty($sugar_config['dbconfig'])) {
2727                 if ($exit) exit; else return;
2728         }
2729
2730     if (!class_exists('Tracker', true)) {
2731                 require_once 'modules/Trackers/Tracker.php';
2732         }
2733         Tracker::logPage();
2734         // Now write the cached tracker_queries
2735         if(!empty($GLOBALS['savePreferencesToDB']) && $GLOBALS['savePreferencesToDB']) {
2736             if ( isset($GLOBALS['current_user']) && $GLOBALS['current_user'] instanceOf User )
2737                 $GLOBALS['current_user']->savePreferencesToDB();
2738         }
2739
2740         //check to see if this is not an `ajax call AND the user preference error flag is set
2741         if(
2742                 (isset($_SESSION['USER_PREFRENCE_ERRORS']) && $_SESSION['USER_PREFRENCE_ERRORS'])
2743                 && ($_REQUEST['action']!='modulelistmenu' && $_REQUEST['action']!='DynamicAction')
2744                 && (empty($_REQUEST['to_pdf']) || !$_REQUEST['to_pdf'] )
2745                 && (empty($_REQUEST['sugar_body_only']) || !$_REQUEST['sugar_body_only'] )
2746
2747         ){
2748                 global $app_strings;
2749                 //this is not an ajax call and the user preference error flag is set, so reset the flag and print js to flash message
2750                 $err_mess = $app_strings['ERROR_USER_PREFS'];
2751                 $_SESSION['USER_PREFRENCE_ERRORS'] = false;
2752                 echo "
2753                 <script>
2754                         ajaxStatus.flashStatus('$err_mess',7000);
2755                 </script>";
2756
2757         }
2758
2759         pre_login_check();
2760         if(class_exists('DBManagerFactory')) {
2761                 $db = DBManagerFactory::getInstance();
2762                 $db->disconnect();
2763                 if($exit) {
2764                         exit;
2765                 }
2766         }
2767 }
2768
2769 register_shutdown_function('sugar_cleanup');
2770
2771
2772 /*
2773  check_logic_hook - checks to see if your custom logic is in the logic file
2774  if not, it will add it. If the file isn't built yet, it will create the file
2775
2776  */
2777 function check_logic_hook_file($module_name, $event, $action_array){
2778         require_once('include/utils/logic_utils.php');
2779         $add_logic = false;
2780
2781         if(file_exists("custom/modules/$module_name/logic_hooks.php")){
2782
2783                 $hook_array = get_hook_array($module_name);
2784
2785                 if(check_existing_element($hook_array, $event, $action_array)==true){
2786                         //the hook at hand is present, so do nothing
2787                 } else {
2788                         $add_logic = true;
2789
2790             $logic_count = 0;
2791             if(!empty($hook_array[$event]))
2792             {
2793                             $logic_count = count($hook_array[$event]);
2794             }
2795
2796                         if($action_array[0]==""){
2797                                 $action_array[0] = $logic_count  + 1;
2798                         }
2799                         $hook_array[$event][] = $action_array;
2800
2801                 }
2802                 //end if the file exists already
2803         } else {
2804                 $add_logic = true;
2805                 if($action_array[0]==""){
2806                         $action_array[0] = 1;
2807                 }
2808                 $hook_array = array();
2809                 $hook_array[$event][] = $action_array;
2810                 //end if else file exists already
2811         }
2812         if($add_logic == true){
2813
2814                 //reorder array by element[0]
2815                 //$hook_array = reorder_array($hook_array, $event);
2816                 //!!!Finish this above TODO
2817
2818                 $new_contents = replace_or_add_logic_type($hook_array);
2819                 write_logic_file($module_name, $new_contents);
2820
2821                 //end if add_element is true
2822         }
2823
2824         //end function check_logic_hook_file
2825 }
2826
2827 function remove_logic_hook($module_name, $event, $action_array) {
2828     require_once('include/utils/logic_utils.php');
2829         $add_logic = false;
2830
2831         if(file_exists("custom/modules/".$module_name."/logic_hooks.php")){
2832         // The file exists, let's make sure the hook is there
2833                 $hook_array = get_hook_array($module_name);
2834
2835                 if(check_existing_element($hook_array, $event, $action_array)==true){
2836             // The hook is there, time to take it out.
2837
2838             foreach ( $hook_array[$event] as $i => $hook ) {
2839                 // We don't do a full comparison below just in case the filename changes
2840                 if ( $hook[0] == $action_array[0]
2841                      && $hook[1] == $action_array[1]
2842                      && $hook[3] == $action_array[3]
2843                      && $hook[4] == $action_array[4] ) {
2844                     unset($hook_array[$event][$i]);
2845                 }
2846             }
2847
2848             $new_contents = replace_or_add_logic_type($hook_array);
2849             write_logic_file($module_name, $new_contents);
2850
2851         }
2852     }
2853 }
2854
2855 function display_stack_trace($textOnly=false){
2856
2857         $stack  = debug_backtrace();
2858
2859         echo "\n\n display_stack_trace caller, file: " . $stack[0]['file']. ' line#: ' .$stack[0]['line'];
2860
2861         if(!$textOnly)
2862         echo '<br>';
2863
2864         $first = true;
2865         $out = '';
2866
2867         foreach($stack as $item) {
2868                 $file  = '';
2869                 $class = '';
2870                 $line  = '';
2871                 $function  = '';
2872
2873                 if(isset($item['file']))
2874                 $file = $item['file'];
2875                 if(isset($item['class']))
2876                 $class = $item['class'];
2877                 if(isset($item['line']))
2878                 $line = $item['line'];
2879                 if(isset($item['function']))
2880                 $function = $item['function'];
2881
2882                 if(!$first) {
2883                         if(!$textOnly) {
2884                                 $out .= '<font color="black"><b>';
2885                         }
2886
2887                         $out .= $file;
2888
2889                         if(!$textOnly) {
2890                                 $out .= '</b></font><font color="blue">';
2891                         }
2892
2893                         $out .= "[L:{$line}]";
2894
2895                         if(!$textOnly) {
2896                                 $out .= '</font><font color="red">';
2897                         }
2898
2899                         $out .= "({$class}:{$function})";
2900
2901                         if(!$textOnly) {
2902                                 $out .= '</font><br>';
2903                         } else {
2904                                 $out .= "\n";
2905                         }
2906                 } else {
2907                         $first = false;
2908                 }
2909         }
2910
2911         echo $out;
2912 }
2913
2914 function StackTraceErrorHandler($errno, $errstr, $errfile,$errline, $errcontext) {
2915         $error_msg = " $errstr occured in <b>$errfile</b> on line $errline [" . date("Y-m-d H:i:s") . ']';
2916         $halt_script = true;
2917         switch($errno){
2918                 case 2048: return; //depricated we have lots of these ignore them
2919                 case E_USER_NOTICE:
2920                 case E_NOTICE:
2921                     if ( error_reporting() & E_NOTICE ) {
2922                         $halt_script = false;
2923                         $type = 'Notice';
2924                     }
2925                     else
2926                         return;
2927                         break;
2928                 case E_USER_WARNING:
2929                 case E_COMPILE_WARNING:
2930                 case E_CORE_WARNING:
2931                 case E_WARNING:
2932
2933                         $halt_script = false;
2934                         $type = "Warning";
2935                         break;
2936
2937                 case E_USER_ERROR:
2938                 case E_COMPILE_ERROR:
2939                 case E_CORE_ERROR:
2940                 case E_ERROR:
2941
2942                         $type = "Fatal Error";
2943                         break;
2944
2945                 case E_PARSE:
2946
2947                         $type = "Parse Error";
2948                         break;
2949
2950                 default:
2951                         //don't know what it is might not be so bad
2952                         $halt_script = false;
2953                         $type = "Unknown Error ($errno)";
2954                         break;
2955         }
2956         $error_msg = '<b>'.$type.'</b>:' . $error_msg;
2957         echo $error_msg;
2958         display_stack_trace();
2959         if($halt_script){
2960                 exit -1;
2961         }
2962
2963
2964
2965 }
2966
2967
2968 if(isset($sugar_config['stack_trace_errors']) && $sugar_config['stack_trace_errors']){
2969
2970         set_error_handler('StackTraceErrorHandler');
2971 }
2972 function get_sub_cookies($name){
2973         $cookies = array();
2974         if(isset($_COOKIE[$name])){
2975                 $subs = explode('#', $_COOKIE[$name]);
2976                 foreach($subs as $cookie){
2977                         if(!empty($cookie)){
2978                                 $cookie = explode('=', $cookie);
2979
2980                                 $cookies[$cookie[0]] = $cookie[1];
2981                         }
2982                 }
2983         }
2984         return $cookies;
2985
2986 }
2987
2988
2989 function mark_delete_components($sub_object_array, $run_second_level=false, $sub_sub_array=""){
2990
2991         if(!empty($sub_object_array)){
2992
2993                 foreach($sub_object_array as $sub_object){
2994
2995                         //run_second level is set to true if you need to remove sub-sub components
2996                         if($run_second_level==true){
2997
2998                                 mark_delete_components($sub_object->get_linked_beans($sub_sub_array['rel_field'],$sub_sub_array['rel_module']));
2999
3000                                 //end if run_second_level is true
3001                         }
3002                         $sub_object->mark_deleted($sub_object->id);
3003                         //end foreach sub component
3004                 }
3005                 //end if this is not empty
3006         }
3007
3008         //end function mark_delete_components
3009 }
3010
3011 /**
3012  * For translating the php.ini memory values into bytes.  e.g. input value of '8M' will return 8388608.
3013  */
3014 function return_bytes($val)
3015 {
3016         $val = trim($val);
3017         $last = strtolower($val{strlen($val)-1});
3018
3019         switch($last)
3020         {
3021                 // The 'G' modifier is available since PHP 5.1.0
3022                 case 'g':
3023                         $val *= 1024;
3024                 case 'm':
3025                         $val *= 1024;
3026                 case 'k':
3027                         $val *= 1024;
3028         }
3029
3030         return $val;
3031 }
3032
3033 /**
3034  * Adds the href HTML tags around any URL in the $string
3035  */
3036 function url2html($string) {
3037         //
3038         $return_string = preg_replace('/(\w+:\/\/)(\S+)/', ' <a href="\\1\\2" target="_new"  style="font-weight: normal;">\\1\\2</a>', $string);
3039         return $return_string;
3040 }
3041 // End customization by Julian
3042
3043 /**
3044  * tries to determine whether the Host machine is a Windows machine
3045  */
3046 function is_windows() {
3047     static $is_windows = null;
3048     if (!isset($is_windows)) {
3049         $is_windows = strtoupper(substr(PHP_OS, 0, 3)) == 'WIN';
3050     }
3051     return $is_windows;
3052 }
3053
3054 /**
3055  * equivalent for windows filesystem for PHP's is_writable()
3056  * @param string file Full path to the file/dir
3057  * @return bool true if writable
3058  */
3059 function is_writable_windows($file) {
3060         if($file{strlen($file)-1}=='/') {
3061                 return is_writable_windows($file.uniqid(mt_rand()).'.tmp');
3062         }
3063
3064         // the assumption here is that Windows has an inherited permissions scheme
3065         // any file that is a descendant of an unwritable directory will inherit
3066         // that property and will trigger a failure below.
3067         if(is_dir($file)) {
3068                 return true;
3069         }
3070
3071         $file = str_replace("/", '\\', $file);
3072
3073         if(file_exists($file)) {
3074                 if (!($f = @sugar_fopen($file, 'r+')))
3075                 return false;
3076                 fclose($f);
3077                 return true;
3078         }
3079
3080         if(!($f = @sugar_fopen($file, 'w')))
3081         return false;
3082         fclose($f);
3083         unlink($file);
3084         return true;
3085 }
3086
3087
3088 /**
3089  * best guesses Timezone based on webserver's TZ settings
3090  */
3091 function lookupTimezone($userOffset = 0)
3092 {
3093     return TimeDate::guessTimezone($userOffset);
3094 }
3095
3096 function convert_module_to_singular($module_array){
3097         global $beanList;
3098
3099         foreach($module_array as $key => $value){
3100                 if(!empty($beanList[$value])) $module_array[$key] = $beanList[$value];
3101
3102                 if($value=="Cases") {
3103                         $module_array[$key] = "Case";
3104                 }
3105                 if($key=="projecttask"){
3106                         $module_array['ProjectTask'] = "Project Task";
3107                         unset($module_array[$key]);
3108                 }
3109         }
3110
3111         return $module_array;
3112
3113         //end function convert_module_to_singular
3114 }
3115
3116 /*
3117  * Given the bean_name which may be plural or singular return the singular
3118  * bean_name. This is important when you need to include files.
3119  */
3120 function get_singular_bean_name($bean_name){
3121         global $beanFiles, $beanList;
3122         if(array_key_exists($bean_name, $beanList)){
3123                 return $beanList[$bean_name];
3124         }
3125         else{
3126                 return $bean_name;
3127         }
3128 }
3129
3130 /*
3131  * Given the potential module name (singular name, renamed module name)
3132  * Return the real internal module name.
3133  */
3134 function get_module_from_singular($singular) {
3135
3136     // find the internal module name for a singular name
3137     if (isset($GLOBALS['app_list_strings']['moduleListSingular'])) {
3138
3139         $singular_modules = $GLOBALS['app_list_strings']['moduleListSingular'];
3140
3141         foreach ($singular_modules as $mod_name=>$sin_name) {
3142             if ($singular == $sin_name and $mod_name != $sin_name) {
3143                 return $mod_name;
3144             }
3145         }
3146     }
3147
3148     // find the internal module name for a renamed module
3149     if (isset($GLOBALS['app_list_strings']['moduleList'])) {
3150
3151         $moduleList = $GLOBALS['app_list_strings']['moduleList'];
3152
3153         foreach ($moduleList as $mod_name=>$name) {
3154             if ($singular == $name and $mod_name != $name) {
3155                 return $mod_name;
3156             }
3157         }
3158     }
3159
3160     // if it's not a singular name, nor a renamed name, return the original value
3161     return $singular;
3162 }
3163
3164 function get_label($label_tag, $temp_module_strings){
3165         global $app_strings;
3166         if(!empty($temp_module_strings[$label_tag])){
3167
3168                 $label_name = $temp_module_strings[$label_tag];
3169         } else {
3170                 if(!empty($app_strings[$label_tag])){
3171                         $label_name = $app_strings[$label_tag];
3172                 } else {
3173                         $label_name = $label_tag;
3174                 }
3175         }
3176         return $label_name;
3177
3178         //end function get_label
3179 }
3180
3181
3182 function search_filter_rel_info(& $focus, $tar_rel_module, $relationship_name){
3183
3184         $rel_list = array();
3185
3186         foreach($focus->relationship_fields as $rel_key => $rel_value){
3187                 if($rel_value == $relationship_name){
3188                         $temp_bean = get_module_info($tar_rel_module);
3189         //              echo $focus->$rel_key;
3190                         $temp_bean->retrieve($focus->$rel_key);
3191                         if($temp_bean->id!=""){
3192
3193                                 $rel_list[] = $temp_bean;
3194                                 return $rel_list;
3195                         }
3196                 }
3197         }
3198
3199         foreach($focus->field_defs as $field_name => $field_def){
3200                 //Check if the relationship_name matches a "relate" field
3201                 if(!empty($field_def['type']) && $field_def['type'] == 'relate'
3202                 && !empty($field_def['id_name']) && !empty($focus->field_defs[$field_def['id_name']])
3203                 && !empty($focus->field_defs[$field_def['id_name']]['relationship'])
3204                 && $focus->field_defs[$field_def['id_name']]['relationship'] == $relationship_name)
3205                 {
3206                         $temp_bean = get_module_info($tar_rel_module);
3207                 //      echo $focus->$field_def['id_name'];
3208                         $temp_bean->retrieve($focus->$field_def['id_name']);
3209                         if($temp_bean->id!=""){
3210
3211                                 $rel_list[] = $temp_bean;
3212                                 return $rel_list;
3213                         }
3214                 //Check if the relationship_name matches a "link" in a relate field
3215                 } else if(!empty($rel_value['link']) && !empty($rel_value['id_name']) && $rel_value['link'] == $relationship_name){
3216                         $temp_bean = get_module_info($tar_rel_module);
3217                 //      echo $focus->$rel_value['id_name'];
3218                         $temp_bean->retrieve($focus->$rel_value['id_name']);
3219                         if($temp_bean->id!=""){
3220
3221                                 $rel_list[] = $temp_bean;
3222                                 return $rel_list;
3223                         }
3224                 }
3225         }
3226
3227         // special case for unlisted parent-type relationships
3228         if( !empty($focus->parent_type) && $focus->parent_type == $tar_rel_module && !empty($focus->parent_id)) {
3229                 $temp_bean = get_module_info($tar_rel_module);
3230                 $temp_bean->retrieve($focus->parent_id);
3231                 if($temp_bean->id!=""){
3232                         $rel_list[] = $temp_bean;
3233                         return $rel_list;
3234                 }
3235         }
3236
3237         return $rel_list;
3238
3239         //end function search_filter_rel_info
3240 }
3241
3242 function get_module_info($module_name){
3243         global $beanList;
3244         global $dictionary;
3245
3246         //Get dictionary and focus data for module
3247         $vardef_name = $beanList[$module_name];
3248
3249         if($vardef_name=="aCase"){
3250                 $class_name = "Case";
3251         } else {
3252                 $class_name = $vardef_name;
3253         }
3254
3255         if(!file_exists('modules/'. $module_name . '/'.$class_name.'.php')){
3256                 return;
3257         }
3258
3259         include_once('modules/'. $module_name . '/'.$class_name.'.php');
3260
3261         $module_bean = new $vardef_name();
3262         return $module_bean;
3263         //end function get_module_table
3264 }
3265
3266 /**
3267  * In order to have one place to obtain the proper object name. aCase for example causes issues throughout the application.
3268  *
3269  * @param string $moduleName
3270  */
3271 function get_valid_bean_name($module_name){
3272         global $beanList;
3273
3274         $vardef_name = $beanList[$module_name];
3275         if($vardef_name=="aCase"){
3276                 $bean_name = "Case";
3277         } else {
3278                 $bean_name = $vardef_name;
3279         }
3280         return $bean_name;
3281 }
3282
3283
3284
3285 function  checkAuthUserStatus(){
3286
3287         //authUserStatus();
3288 }
3289
3290
3291 /**
3292  * This function returns an array of phpinfo() results that can be parsed and
3293  * used to figure out what version we run, what modules are compiled in, etc.
3294  * @param       $level                  int             info level constant (1,2,4,8...64);
3295  * @return      $returnInfo             array   array of info about the PHP environment
3296  * @author      original by "code at adspeed dot com" Fron php.net
3297  * @author      customized for Sugar by Chris N.
3298  */
3299 function getPhpInfo($level=-1) {
3300         /**     Name (constant)         Value   Description
3301                 INFO_GENERAL            1               The configuration line, php.ini location, build date, Web Server, System and more.
3302                 INFO_CREDITS            2               PHP Credits. See also phpcredits().
3303                 INFO_CONFIGURATION      4               Current Local and Master values for PHP directives. See also ini_get().
3304                 INFO_MODULES            8               Loaded modules and their respective settings. See also get_loaded_extensions().
3305                 INFO_ENVIRONMENT        16              Environment Variable information that's also available in $_ENV.
3306                 INFO_VARIABLES          32              Shows all predefined variables from EGPCS (Environment, GET, POST, Cookie, Server).
3307                 INFO_LICENSE            64              PHP License information. See also the license FAQ.
3308                 INFO_ALL                        -1              Shows all of the above. This is the default value.
3309          */
3310         ob_start();
3311         phpinfo($level);
3312         $phpinfo = ob_get_contents();
3313         ob_end_clean();
3314
3315         $phpinfo        = strip_tags($phpinfo,'<h1><h2><th><td>');
3316         $phpinfo        = preg_replace('/<th[^>]*>([^<]+)<\/th>/',"<info>\\1</info>",$phpinfo);
3317         $phpinfo        = preg_replace('/<td[^>]*>([^<]+)<\/td>/',"<info>\\1</info>",$phpinfo);
3318         $parsedInfo     = preg_split('/(<h.?>[^<]+<\/h.>)/', $phpinfo, -1, PREG_SPLIT_DELIM_CAPTURE);
3319         $match          = '';
3320         $version        = '';
3321         $returnInfo     = array();
3322
3323         if(preg_match('/<h1 class\=\"p\">PHP Version ([^<]+)<\/h1>/', $phpinfo, $version)) {
3324                 $returnInfo['PHP Version'] = $version[1];
3325         }
3326
3327
3328         for ($i=1; $i<count($parsedInfo); $i++) {
3329                 if (preg_match('/<h.>([^<]+)<\/h.>/', $parsedInfo[$i], $match)) {
3330                         $vName = trim($match[1]);
3331                         $parsedInfo2 = explode("\n",$parsedInfo[$i+1]);
3332
3333                         foreach ($parsedInfo2 AS $vOne) {
3334                                 $vPat   = '<info>([^<]+)<\/info>';
3335                                 $vPat3  = "/$vPat\s*$vPat\s*$vPat/";
3336                                 $vPat2  = "/$vPat\s*$vPat/";
3337
3338                                 if (preg_match($vPat3,$vOne,$match)) { // 3cols
3339                                         $returnInfo[$vName][trim($match[1])] = array(trim($match[2]),trim($match[3]));
3340                                 } elseif (preg_match($vPat2,$vOne,$match)) { // 2cols
3341                                         $returnInfo[$vName][trim($match[1])] = trim($match[2]);
3342                                 }
3343                         }
3344                 } elseif(true) {
3345
3346                 }
3347         }
3348
3349         return $returnInfo;
3350 }
3351
3352 /**
3353  * This function will take a string that has tokens like {0}, {1} and will replace
3354  * those tokens with the args provided
3355  * @param       $format string to format
3356  * @param       $args args to replace
3357  * @return      $result a formatted string
3358  */
3359 function string_format($format, $args){
3360         $result = $format;
3361     
3362     /** Bug47277 fix.
3363      * If args array has only one argument, and it's empty, so empty single quotes are used '' . That's because
3364      * IN () fails and IN ('') works. 
3365      */
3366     if (count($args) == 1)
3367     {
3368         reset($args);
3369         $singleArgument = current($args);
3370         if (empty($singleArgument))
3371         {
3372             return str_replace("{0}", "''", $result);
3373         }
3374     }
3375     /* End of fix */
3376     
3377         for($i = 0; $i < count($args); $i++){
3378                 $result = str_replace('{'.$i.'}', $args[$i], $result);
3379         }
3380         return $result;
3381 }
3382
3383 /**
3384  * Generate a string for displaying a unique identifier that is composed
3385  * of a system_id and number.  This is use to allow us to generate quote
3386  * numbers using a DB auto-increment key from offline clients and still
3387  * have the number be unique (since it is modified by the system_id.
3388  *
3389  * @param       $num of bean
3390  * @param       $system_id from system
3391  * @return      $result a formatted string
3392  */
3393 function format_number_display($num, $system_id){
3394         global $sugar_config;
3395         if(isset($num) && !empty($num)){
3396                 $num=unformat_number($num);
3397                 if(isset($system_id) && $system_id == 1){
3398                         return sprintf("%d", $num);
3399                 }
3400                 else{
3401                         return sprintf("%d-%d", $num, $system_id);
3402                 }
3403         }
3404 }
3405 function checkLoginUserStatus(){
3406 }
3407
3408 /**
3409  * This function will take a number and system_id and format
3410  * @param       $url URL containing host to append port
3411  * @param       $port the port number - if '' is passed, no change to url
3412  * @return      $resulturl the new URL with the port appended to the host
3413  */
3414 function appendPortToHost($url, $port)
3415 {
3416         $resulturl = $url;
3417
3418         // if no port, don't change the url
3419         if($port != '')
3420         {
3421                 $split = explode("/", $url);
3422                 //check if it starts with http, in case they didn't include that in url
3423                 if(str_begin($url, 'http'))
3424                 {
3425                         //third index ($split[2]) will be the host
3426                         $split[2] .= ":".$port;
3427                 }
3428                 else // otherwise assumed to start with host name
3429                 {
3430                         //first index ($split[0]) will be the host
3431                         $split[0] .= ":".$port;
3432                 }
3433
3434                 $resulturl = implode("/", $split);
3435         }
3436
3437         return $resulturl;
3438 }
3439
3440 /**
3441  * Singleton to return JSON object
3442  * @return      JSON object
3443  */
3444 function getJSONobj() {
3445         static $json = null;
3446         if(!isset($json)) {
3447                 require_once('include/JSON.php');
3448                 $json = new JSON(JSON_LOOSE_TYPE);
3449         }
3450         return $json;
3451 }
3452
3453 require_once('include/utils/db_utils.php');
3454
3455 /**
3456  * Set default php.ini settings for entry points
3457  */
3458 function setPhpIniSettings() {
3459         // zlib module
3460         // Bug 37579 - Comment out force enabling zlib.output_compression, since it can cause problems on certain hosts
3461         /*
3462     if(function_exists('gzclose') && headers_sent() == false) {
3463                 ini_set('zlib.output_compression', 1);
3464         }
3465         */
3466         // mbstring module
3467         //nsingh: breaks zip/unzip functionality. Commenting out 4/23/08
3468
3469         /*if(function_exists('mb_strlen')) {
3470                 ini_set('mbstring.func_overload', 7);
3471                 ini_set('mbstring.internal_encoding', 'UTF-8');
3472         }*/
3473
3474
3475         // http://us3.php.net/manual/en/ref.pcre.php#ini.pcre.backtrack-limit
3476         // starting with 5.2.0, backtrack_limit breaks JSON decoding
3477         $backtrack_limit = ini_get('pcre.backtrack_limit');
3478         if(!empty($backtrack_limit)) {
3479                 ini_set('pcre.backtrack_limit', '-1');
3480         }
3481
3482         // mssql only
3483         if(ini_get("mssql.charset")) {
3484                 ini_set('mssql.charset', "UTF-8");
3485         }
3486 }
3487
3488 /**
3489  * like array_merge() but will handle array elements that are themselves arrays;
3490  * PHP's version just overwrites the element with the new one.
3491  *
3492  * @internal Note that this function deviates from the internal array_merge()
3493  *           functions in that it does does not treat numeric keys differently
3494  *           than string keys.  Additionally, it deviates from
3495  *           array_merge_recursive() by not creating an array when like values
3496  *           found.
3497  *
3498  * @param array gimp the array whose values will be overloaded
3499  * @param array dom the array whose values will pwn the gimp's
3500  * @return array beaten gimp
3501  */
3502 function sugarArrayMerge($gimp, $dom) {
3503         if(is_array($gimp) && is_array($dom)) {
3504                 foreach($dom as $domKey => $domVal) {
3505                         if(array_key_exists($domKey, $gimp)) {
3506                                 if(is_array($domVal)) {
3507                                         $tempArr = array();
3508                     foreach ( $domVal as $domArrKey => $domArrVal )
3509                         $tempArr[$domArrKey] = $domArrVal;
3510                     foreach ( $gimp[$domKey] as $gimpArrKey => $gimpArrVal )
3511                         if ( !array_key_exists($gimpArrKey, $tempArr) )
3512                             $tempArr[$gimpArrKey] = $gimpArrVal;
3513                     $gimp[$domKey] = $tempArr;
3514                                 } else {
3515                                         $gimp[$domKey] = $domVal;
3516                                 }
3517                         } else {
3518                                 $gimp[$domKey] = $domVal;
3519                         }
3520                 }
3521         }
3522     // if the passed value for gimp isn't an array, then return the $dom
3523     elseif(is_array($dom))
3524         return $dom;
3525
3526         return $gimp;
3527 }
3528
3529 /**
3530  * Similiar to sugarArrayMerge except arrays of N depth are merged.
3531  *
3532  * @param array gimp the array whose values will be overloaded
3533  * @param array dom the array whose values will pwn the gimp's
3534  * @return array beaten gimp
3535  */
3536 function sugarArrayMergeRecursive($gimp, $dom) {
3537         if(is_array($gimp) && is_array($dom)) {
3538                 foreach($dom as $domKey => $domVal) {
3539                         if(array_key_exists($domKey, $gimp)) {
3540                                 if(is_array($domVal) && is_array($gimp[$domKey])) {
3541                                         $gimp[$domKey] = sugarArrayMergeRecursive($gimp[$domKey], $domVal);
3542                                 } else {
3543                                         $gimp[$domKey] = $domVal;
3544                                 }
3545                         } else {
3546                                 $gimp[$domKey] = $domVal;
3547                         }
3548                 }
3549         }
3550     // if the passed value for gimp isn't an array, then return the $dom
3551     elseif(is_array($dom))
3552         return $dom;
3553
3554         return $gimp;
3555 }
3556
3557 /**
3558  * finds the correctly working versions of PHP-JSON
3559  * @return bool True if NOT found or WRONG version
3560  */
3561 function returnPhpJsonStatus() {
3562         if(function_exists('json_encode')) {
3563                 $phpInfo = getPhpInfo(8);
3564         return version_compare($phpInfo['json']['json version'], '1.1.1', '<');
3565         }
3566         return true; // not found
3567 }
3568
3569
3570 /**
3571  * getTrackerSubstring
3572  *
3573  * Returns a [number]-char or less string for the Tracker to display in the header
3574  * based on the tracker_max_display_length setting in config.php.  If not set,
3575  * or invalid length, then defaults to 15 for COM editions, 30 for others.
3576  *
3577  * @param string name field for a given Object
3578  * @return string [number]-char formatted string if length of string exceeds the max allowed
3579  */
3580 function getTrackerSubstring($name) {
3581         static $max_tracker_item_length;
3582
3583         //Trim the name
3584         $name = html_entity_decode($name, ENT_QUOTES, 'UTF-8');
3585         $strlen = function_exists('mb_strlen') ? mb_strlen($name) : strlen($name);
3586
3587         global $sugar_config;
3588
3589         if(!isset($max_tracker_item_length)) {
3590                 if(isset($sugar_config['tracker_max_display_length'])) {
3591               $max_tracker_item_length = (is_int($sugar_config['tracker_max_display_length']) && $sugar_config['tracker_max_display_length'] > 0 && $sugar_config['tracker_max_display_length'] < 50) ? $sugar_config['tracker_max_display_length'] : 15;
3592                 } else {
3593               $max_tracker_item_length = 15;
3594                 }
3595         }
3596
3597         if($strlen > $max_tracker_item_length) {
3598                 $chopped = function_exists('mb_substr') ? mb_substr($name, 0, $max_tracker_item_length, "UTF-8") : substr($name, 0, $max_tracker_item_length, "UTF-8");
3599         } else {
3600                 $chopped = $name;
3601         }
3602
3603         return $chopped;
3604 }
3605 function generate_search_where ($field_list=array(),$values=array(),&$bean,$add_custom_fields=false,$module='') {
3606         $where_clauses= array();
3607         $like_char='%';
3608         $table_name=$bean->object_name;
3609         foreach ($field_list[$module] as $field=>$parms) {
3610                 if(isset($values[$field]) && $values[$field] != "") {
3611                         $operator='like';
3612                         if (!empty($parms['operator'])) {
3613                                 $operator=$parms['operator'];
3614                         }
3615                         if (is_array($values[$field])) {
3616                                 $operator='in';
3617                                 $field_value='';
3618                                 foreach ($values[$field] as $key => $val) {
3619                                         if ($val != ' ' and $val != '') {
3620                                                 if (!empty($field_value)) {
3621                                                         $field_value.=',';
3622                                                 }
3623                                                 $field_value .= "'".$GLOBALS['db']->quote($val)."'";
3624                                         }
3625                                 }
3626                         } else {
3627                                 $field_value=$GLOBALS['db']->quote($values[$field]);
3628                         }
3629                         //set db_fields array.
3630                         if (!isset($parms['db_field']) )  {
3631                                 $parms['db_field'] = array($field);
3632                         }
3633                         if (isset($parms['my_items']) and $parms['my_items'] == true) {
3634                                 global $current_user;
3635                                 $field_value = $GLOBALS['db']->quote($current_user->id);
3636                                 $operator='=';
3637                         }
3638
3639                         $where='';
3640                         $itr=0;
3641                         if ($field_value != '') {
3642
3643                                 foreach ($parms['db_field'] as $db_field) {
3644                                         if (strstr($db_field,'.')===false) {
3645                                                 $db_field=$bean->table_name.".".$db_field;
3646                                         }
3647                                         if ($GLOBALS['db']->dbType=='oci8' &&  isset($parms['query_type']) && $parms['query_type']=='case_insensitive') {
3648                                                 $db_field='upper('.$db_field.")";
3649                                                 $field_value=strtoupper($field_value);
3650                                         }
3651
3652                                         $itr++;
3653                                         if (!empty($where)) {
3654                                                 $where .= " OR ";
3655                                         }
3656                                         switch (strtolower($operator)) {
3657                                                 case 'like' :
3658                                                         $where .=  $db_field . " like '".$field_value.$like_char."'";
3659                                                         break;
3660                                                 case 'in':
3661                                                         $where .=  $db_field . " in (".$field_value.')';
3662                                                         break;
3663                                                 case '=':
3664                                                         $where .=  $db_field . " = '".$field_value ."'";
3665                                                         break;
3666                                         }
3667                                 }
3668                         }
3669                         if (!empty($where)) {
3670                                 if ($itr>1) {
3671                                         array_push($where_clauses, '( '.$where.' )');
3672                                 } else {
3673                                         array_push($where_clauses, $where);
3674                                 }
3675                         }
3676                 }
3677         }
3678         if ($add_custom_fields) {
3679                 require_once('modules/DynamicFields/DynamicField.php');
3680                 $bean->setupCustomFields($module);
3681                 $bean->custom_fields->setWhereClauses($where_clauses);
3682         }
3683         return $where_clauses;
3684 }
3685
3686 function add_quotes($str) {
3687         return "'{$str}'";
3688 }
3689
3690 /**
3691  * This function will rebuild the config file
3692  * @param       $sugar_config
3693  * @param       $sugar_version
3694  * @return      bool true if successful
3695  */
3696 function rebuildConfigFile($sugar_config, $sugar_version) {
3697         // add defaults to missing values of in-memory sugar_config
3698         $sugar_config = sugarArrayMerge(get_sugar_config_defaults(), $sugar_config );
3699         // need to override version with default no matter what
3700         $sugar_config['sugar_version'] = $sugar_version;
3701
3702         ksort( $sugar_config );
3703
3704         if( write_array_to_file( "sugar_config", $sugar_config, "config.php" ) ){
3705                 return true;
3706         }
3707         else {
3708                 return false;
3709         }
3710 }
3711
3712 /**
3713  * getJavascriptSiteURL
3714  * This function returns a URL for the client javascript calls to access
3715  * the site.  It uses $_SERVER['HTTP_REFERER'] in the event that Proxy servers
3716  * are used to access the site.  Thus, the hostname in the URL returned may
3717  * not always match that of $sugar_config['site_url'].  Basically, the
3718  * assumption is that however the user accessed the website is how they
3719  * will continue to with subsequent javascript requests.  If the variable
3720  * $_SERVER['HTTP_REFERER'] is not found then we default to old algorithm.
3721  * @return $site_url The url used to refer to the website
3722  */
3723 function getJavascriptSiteURL() {
3724         global $sugar_config;
3725         if(!empty($_SERVER['HTTP_REFERER'])) {
3726                 $url = parse_url($_SERVER['HTTP_REFERER']);
3727                 $replacement_url = $url['scheme']."://".$url['host'];
3728                 if(!empty($url['port']))
3729                 $replacement_url .= ':'.$url['port'];
3730                 $site_url = preg_replace('/^http[s]?\:\/\/[^\/]+/',$replacement_url,$sugar_config['site_url']);
3731         } else {
3732                 $site_url = preg_replace('/^http(s)?\:\/\/[^\/]+/',"http$1://".$_SERVER['HTTP_HOST'],$sugar_config['site_url']);
3733                 if(!empty($_SERVER['SERVER_PORT']) &&$_SERVER['SERVER_PORT'] == '443') {
3734                         $site_url = preg_replace('/^http\:/','https:',$site_url);
3735                 }
3736         }
3737         $GLOBALS['log']->debug("getJavascriptSiteURL(), site_url=".  $site_url);
3738         return $site_url;
3739 }
3740
3741 // works nicely with array_map() -- can be used to wrap single quotes around each element in an array
3742 function add_squotes($str) {
3743         return "'" . $str . "'";
3744 }
3745
3746
3747 // recursive function to count the number of levels within an array
3748 function array_depth($array, $depth_count=-1, $depth_array=array()){
3749         $depth_count++;
3750         if (is_array($array)){
3751                 foreach ($array as $key => $value){
3752                         $depth_array[] = array_depth($value, $depth_count);
3753                 }
3754         }
3755         else{
3756                 return $depth_count;
3757         }
3758         foreach ($depth_array as $value){
3759                 $depth_count = $value > $depth_count ? $value : $depth_count;
3760         }
3761         return $depth_count;
3762 }
3763
3764 /**
3765  * Creates a new Group User
3766  * @param string $name Name of Group User
3767  * @return string GUID of new Group User
3768  */
3769 function createGroupUser($name) {
3770
3771
3772         $group = new User();
3773         $group->user_name       = $name;
3774         $group->last_name       = $name;
3775         $group->is_group        = 1;
3776         $group->deleted         = 0;
3777         $group->status          = 'Active'; // cn: bug 6711
3778         $group->setPreference('timezone', TimeDate::userTimezone());
3779         $group->save();
3780
3781         return $group->id;
3782 }
3783
3784 /*
3785  * Helper function to locate an icon file given only a name
3786  * Searches through the various paths for the file
3787  * @param string iconFileName   The filename of the icon
3788  * @return string Relative pathname of the located icon, or '' if not found
3789  */
3790
3791 function _getIcon($iconFileName)
3792 {
3793     $iconPath = SugarThemeRegistry::current()->getImageURL("icon_{$iconFileName}.gif");
3794     //First try un-ucfirst-ing the icon name
3795     if ( empty($iconPath) )
3796         $iconPath = SugarThemeRegistry::current()->getImageURL(
3797             "icon_" . strtolower(substr($iconFileName,0,1)).substr($iconFileName,1) . ".gif");
3798     //Next try removing the icon prefix
3799     if ( empty($iconPath) )
3800         $iconPath = SugarThemeRegistry::current()->getImageURL("{$iconFileName}.gif");
3801
3802         return $iconPath;
3803 }
3804 /**
3805  * Function to grab the correct icon image for Studio
3806  * @param string $iconFileName Name of the icon file
3807  * @param string $altfilename Name of a fallback icon file (displayed if the imagefilename doesn't exist)
3808  * @param string $width Width of image
3809  * @param string $height Height of image
3810  * @param string $align Alignment of image
3811  * @return string $string <img> tag with corresponding image
3812  */
3813
3814 function getStudioIcon($iconFileName='', $altFileName='', $width='48', $height='48', $align='baseline' )
3815 {
3816         global $app_strings, $theme;
3817
3818     $iconPath = _getIcon($iconFileName);
3819         if(empty($iconPath)){
3820             $iconPath = _getIcon($altFileName);
3821             if (empty($iconPath))
3822             {
3823             return $app_strings['LBL_NO_IMAGE'];
3824             }
3825         }
3826         return '<img border="0" src="'.$iconPath.'" width="'.$width.'" height="'.$height.'" align="'.$align.'">';
3827 }
3828
3829 /**
3830  * Function to grab the correct icon image for Dashlets Dialog
3831  * @param string $filename Location of the icon file
3832  * @param string $module Name of the module to fall back onto if file does not exist
3833  * @param string $width Width of image
3834  * @param string $height Height of image
3835  * @param string $align Alignment of image
3836  * @return string $string <img> tag with corresponding image
3837  */
3838
3839 function get_dashlets_dialog_icon($module='', $width='32', $height='32', $align='absmiddle'){
3840         global $app_strings, $theme;
3841         $icon_path = _getIcon($module . "_32");
3842         if (empty($icon_path))
3843         {
3844                 $icon_path = _getIcon($module);
3845         }
3846         if(empty($icon_path)){
3847                 $icon = $app_strings['LBL_NO_IMAGE'];
3848         }
3849         else{
3850                 $icon = '<img border="0" src="'.$icon_path.'" width="'.$width.'" height="'.$height.'" align="'.$align.'">';
3851         }
3852         return $icon;
3853 }
3854
3855 // works nicely to change UTF8 strings that are html entities - good for PDF conversions
3856 function html_entity_decode_utf8($string)
3857 {
3858     static $trans_tbl;
3859     // replace numeric entities
3860     //php will have issues with numbers with leading zeros, so do not include them in what we send to code2utf.
3861     $string = preg_replace('~&#x0*([0-9a-f]+);~ei', 'code2utf(hexdec("\\1"))', $string);
3862     $string = preg_replace('~&#0*([0-9]+);~e', 'code2utf(\\1)', $string);
3863     // replace literal entities
3864     if (!isset($trans_tbl))
3865     {
3866         $trans_tbl = array();
3867         foreach (get_html_translation_table(HTML_ENTITIES) as $val=>$key)
3868             $trans_tbl[$key] = utf8_encode($val);
3869     }
3870     return strtr($string, $trans_tbl);
3871 }
3872
3873 // Returns the utf string corresponding to the unicode value
3874 function code2utf($num)
3875 {
3876     if ($num < 128) return chr($num);
3877     if ($num < 2048) return chr(($num >> 6) + 192) . chr(($num & 63) + 128);
3878     if ($num < 65536) return chr(($num >> 12) + 224) . chr((($num >> 6) & 63) + 128) . chr(($num & 63) + 128);
3879     if ($num < 2097152) return chr(($num >> 18) + 240) . chr((($num >> 12) & 63) + 128) . chr((($num >> 6) & 63) + 128) . chr(($num & 63) + 128);
3880     return '';
3881 }
3882
3883 function str_split_php4($string, $length = 1) {
3884         $string_length = strlen($string);
3885         $return = array();
3886         $cursor = 0;
3887         if ($length > $string_length) {
3888                 // use the string_length as the string is shorter than the length
3889                 $length = $string_length;
3890         }
3891         for ($cursor = 0; $cursor < $string_length; $cursor = $cursor + $length) {
3892                 $return[] = substr($string, $cursor, $length);
3893         }
3894         return $return;
3895 }
3896
3897 if (version_compare(phpversion(), '5.0.0', '<')) {
3898         function str_split($string, $length = 1) {
3899                 return str_split_php4($string, $length);
3900         }
3901 }
3902
3903 /*
3904  * Invoked when connected to mssql. checks if we have freetds version of mssql library.
3905  * the response is put into a global variable.
3906  */
3907 function is_freetds() {
3908
3909         $ret=false;
3910         if (isset($GLOBALS['mssql_library_version'])) {
3911                 if ($GLOBALS['mssql_library_version']=='freetds') {
3912                         $ret=true;
3913                 } else {
3914                         $ret=false;
3915                 }
3916         } else {
3917                 ob_start();
3918                 phpinfo();
3919                 $info=ob_get_contents();
3920                 ob_end_clean();
3921
3922                 if (strpos($info,'FreeTDS') !== false) {
3923                         $GLOBALS['mssql_library_version']='freetds';
3924                         $ret=true;
3925                 } else {
3926                         $GLOBALS['mssql_library_version']='regular';
3927                         $ret=false;
3928                 }
3929         }
3930         return $ret;
3931 }
3932
3933 /*
3934  *  stripos - Find position of first occurrence of a case-insensitive string
3935  *
3936  *  The function is being defined for systems with PHP version < 5.
3937  *
3938  */
3939 if (!function_exists("stripos")){
3940         function stripos($haystack,$needle,$offset=0){
3941       return strpos(strtolower($haystack),strtolower($needle),$offset);
3942         }
3943 }
3944
3945 /**
3946  * Chart dashlet helper function that returns the correct CSS file, dependent on the current theme.
3947  *
3948  * @todo this won't work completely right until we impliment css compression and combination
3949  *       for now, we'll just include the last css file found.
3950  *
3951  * @return chart.css file to use
3952  */
3953 function chartStyle()
3954 {
3955     return SugarThemeRegistry::current()->getCSSURL('chart.css');
3956 }
3957
3958 /**
3959  * Chart dashlet helper functions that returns the correct XML color file for charts,
3960  * dependent on the current theme.
3961  *
3962  * @return sugarColors.xml to use
3963  */
3964 function chartColors()
3965 {
3966         if (SugarThemeRegistry::current()->getCSSURL('sugarColors.xml')=='')
3967         return SugarThemeRegistry::current()->getImageURL('sugarColors.xml');
3968     return SugarThemeRegistry::current()->getCSSURL('sugarColors.xml');
3969 }
3970 /* End Chart Dashlet helper functions */
3971
3972 /**
3973  * This function is designed to set up the php enviroment
3974  * for AJAX requests.
3975  */
3976
3977 function ajaxInit() {
3978         ini_set('display_errors', 'false');
3979 }
3980
3981 /**
3982  * Returns an absolute path from the given path, determining if it is relative or absolute
3983  *
3984  * @param  string $path
3985  * @return string
3986  */
3987 function getAbsolutePath(
3988     $path,
3989     $currentServer = false
3990     )
3991 {
3992     $path = trim($path);
3993
3994     // try to match absolute paths like \\server\share, /directory or c:\
3995     if ( ( substr($path,0,2) == '\\\\' )
3996             || ( $path[0] == '/' )
3997             || preg_match('/^[A-z]:/i',$path)
3998             || $currentServer )
3999         return $path;
4000
4001     return getcwd().'/'.$path;
4002 }
4003
4004 /**
4005  * Returns the bean object of the given module
4006  *
4007  * @deprecated use SugarModule::loadBean() instead
4008  * @param  string $module
4009  * @return object
4010  */
4011 function loadBean(
4012     $module
4013     )
4014 {
4015     return SugarModule::get($module)->loadBean();
4016 }
4017
4018
4019 /**
4020  * Returns true if the application is being accessed on a touch screen interface ( like an iPad )
4021  */
4022 function isTouchScreen()
4023 {
4024     $ua = empty($_SERVER['HTTP_USER_AGENT']) ? "undefined" : strtolower($_SERVER['HTTP_USER_AGENT']);
4025
4026     // first check if we have forced use of the touch enhanced interface
4027     if ( isset($_COOKIE['touchscreen']) && $_COOKIE['touchscreen'] == '1' ) {
4028         return true;
4029     }
4030
4031     // next check if we should use the touch interface with our device
4032     if ( strpos($ua, 'ipad') !== false ) {
4033         return true;
4034     }
4035
4036     return false;
4037 }
4038
4039 /**
4040  * Returns the shortcut keys to access the shortcut links.  Shortcut
4041  * keys vary depending on browser versions and operating systems.
4042  * @return String value of the shortcut keys
4043  */
4044 function get_alt_hot_key() {
4045         $ua = '';
4046     if ( isset($_SERVER['HTTP_USER_AGENT']) )
4047         $ua = strtolower($_SERVER['HTTP_USER_AGENT']);
4048         $isMac = strpos($ua, 'mac') !== false;
4049         $isLinux = strpos($ua, 'linux') !== false;
4050
4051         if(!$isMac && !$isLinux && strpos($ua, 'mozilla') !== false) {
4052            if(preg_match('/firefox\/(\d)?\./', $ua, $matches)) {
4053                   return $matches[1] < 2 ? 'Alt+' : 'Alt+Shift+';
4054            }
4055         }
4056         return $isMac ? 'Ctrl+' : 'Alt+';
4057 }
4058
4059 function can_start_session(){
4060         if(!empty($_GET['PHPSESSID'])) {
4061            return true;
4062         }
4063         $session_id = session_id();
4064         return empty($session_id) ? true : false;
4065 }
4066
4067 function load_link_class($properties){
4068         $class = 'Link2';
4069         if(!empty($properties['link_class']) && !empty($properties['link_file'])){
4070         require_once($properties['link_file']);
4071         $class = $properties['link_class'];
4072     }
4073     return $class;
4074 }
4075
4076
4077 function inDeveloperMode()
4078 {
4079     return isset($GLOBALS['sugar_config']['developerMode']) && $GLOBALS['sugar_config']['developerMode'];
4080 }
4081
4082 /**
4083  * Filter the protocol list for inbound email accounts.
4084  *
4085  * @param array $protocol
4086  */
4087 function filterInboundEmailPopSelection($protocol)
4088 {
4089     if ( !isset($GLOBALS['sugar_config']['allow_pop_inbound']) || ! $GLOBALS['sugar_config']['allow_pop_inbound'] )
4090     {
4091         if( isset($protocol['pop3']) )
4092                         unset($protocol['pop3']);
4093     }
4094     else
4095         $protocol['pop3'] = 'POP3';
4096
4097     return $protocol;
4098 }
4099
4100 /**
4101  * The function is used because currently we are not supporting mbstring.func_overload
4102  * For some user using mssql without FreeTDS, they may store multibyte charaters in varchar using latin_general collation. It cannot store so many mutilbyte characters, so we need to use strlen.
4103  * The varchar in MySQL, Orcale, and nvarchar in FreeTDS, we can store $length mutilbyte charaters in it. we need mb_substr to keep more info.
4104 * @returns the substred strings.
4105  */
4106 function sugar_substr($string, $length, $charset='UTF-8') {
4107     if($GLOBALS['db']->dbType == 'mssql' && empty($GLOBALS['db']->isFreeTDS)) {
4108         if(strlen($string) > $length) {
4109             $string = trim(substr(trim($string),0,$length));
4110         }
4111     }
4112     else {
4113         if(mb_strlen($string,$charset) > $length) {
4114             $string = trim(mb_substr(trim($string),0,$length,$charset));
4115         }
4116     }
4117     return $string;
4118 }
4119
4120 /**
4121  * The function is used because on FastCGI enviroment, the ucfirst(Chinese Characters) will produce bad charcters.
4122  * This will work even without setting the mbstring.*encoding
4123  */
4124 function sugar_ucfirst($string, $charset='UTF-8') {
4125     return mb_strtoupper(mb_substr($string, 0, 1, $charset), $charset) . mb_substr($string, 1, mb_strlen($string), $charset);
4126 }
4127
4128
4129 /**
4130  *
4131  */
4132 function unencodeMultienum($string) {
4133         if (is_array($string))
4134         {
4135            return $string;
4136         }
4137         if (substr($string, 0 ,1) == "^" && substr($string, -1) == "^") {
4138           $string = substr(substr($string, 1), 0, strlen($string) -2);
4139         }
4140
4141         return explode('^,^', $string);
4142 }
4143
4144 function encodeMultienumValue($arr) {
4145     if (!is_array($arr))
4146         return $arr;
4147
4148     if (empty($arr))
4149         return "";
4150
4151         $string = "^" . implode('^,^', $arr) . "^";
4152
4153     return $string;
4154 }
4155
4156 /**
4157  * create_export_query is used for export and massupdate
4158  * We haven't handle the these fields: $field['type'] == 'relate' && isset($field['link']
4159  * This function will correct the where clause and output necessary join condition for them
4160  * @param $module: the module name
4161  * @param $searchFields: searchFields which is got after $searchForm->populateFromArray()
4162  * @param $where: where clauses
4163  * @return $ret_array['where']: corrected where clause
4164  * @return $ret_array['join']: extra join condition
4165  */
4166 function create_export_query_relate_link_patch($module, $searchFields, $where){
4167         if(file_exists('modules/'.$module.'/SearchForm.html')){
4168                 $ret_array['where'] = $where;
4169                 return $ret_array;
4170         }
4171         $seed = loadBean($module);
4172     foreach($seed->field_defs as $name=>$field)
4173         {
4174
4175                 if( $field['type'] == 'relate' && isset($field['link']) && !empty($searchFields[$name]['value']) ){
4176                         $seed->load_relationship($field['link']);
4177                         $params = array();
4178                         if(empty($join_type))
4179                         {
4180                                 $params['join_type'] = ' LEFT JOIN ';
4181                         }
4182                         else
4183                         {
4184                                 $params['join_type'] = $join_type;
4185                         }
4186                         if(isset($data['join_name']))
4187                         {
4188                                 $params['join_table_alias'] = $field['join_name'];
4189                         }
4190                         else
4191                         {
4192                                 $params['join_table_alias']     = 'join_'.$field['name'];
4193
4194                         }
4195                         if(isset($data['join_link_name']))
4196                         {
4197                                 $params['join_table_link_alias'] = $field['join_link_name'];
4198                         }
4199                         else
4200                         {
4201                                 $params['join_table_link_alias'] = 'join_link_'.$field['name'];
4202                         }
4203                         $join = $seed->$field['link']->getJoin($params, true);
4204                         $join_table_alias = 'join_'.$field['name'];
4205                         if(isset($field['db_concat_fields'])){
4206                                 $db_field = db_concat($join_table_alias, $field['db_concat_fields']);
4207                                 $where = preg_replace('/'.$field['name'].'/', $db_field, $where);
4208                         }else{
4209                                 $where = preg_replace('/(^|[\s(])' . $field['name'] . '/', '${1}' . $join_table_alias . '.'.$field['rname'], $where);
4210                         }
4211                 }
4212         }
4213         $ret_array = array('where'=>$where, 'join'=>$join['join']);
4214         return $ret_array;
4215 }
4216
4217 /**
4218   * We need to clear all the js cache files, including the js language files  in serval places in MB. So I extract them into a util function here.
4219   * @Depends on QuickRepairAndRebuild.php
4220   * @Relate bug 30642  ,23177
4221   */
4222 function clearAllJsAndJsLangFilesWithoutOutput(){
4223                 global $current_language , $mod_strings;
4224                 $MBmodStrings = $mod_strings;
4225         $mod_strings = return_module_language ( $current_language, 'Administration' ) ;
4226         include_once ('modules/Administration/QuickRepairAndRebuild.php') ;
4227         $repair = new RepairAndClear();
4228         $repair->module_list = array();
4229                 $repair->show_output = false;
4230                 $repair->clearJsLangFiles();
4231                 $repair->clearJsFiles();
4232                 $mod_strings = $MBmodStrings;
4233 }
4234
4235 /**
4236  * This function will allow you to get a variable value from query string
4237  */
4238 function getVariableFromQueryString($variable, $string){
4239         $matches = array();
4240         $number = preg_match("/{$variable}=([a-zA-Z0-9_-]+)[&]?/", $string, $matches);
4241         if($number){
4242                 return $matches[1];
4243         }
4244         else{
4245                 return false;
4246         }
4247 }
4248
4249 /**
4250  * should_hide_iframes
4251  * This is a helper method to determine whether or not to show iframes (My Sites) related
4252  * information in the application.
4253  *
4254  * @return boolean flag indicating whether or not iframes module should be hidden
4255  */
4256 function should_hide_iframes() {
4257    //Remove the MySites module
4258    if(file_exists('modules/iFrames/iFrame.php')) {
4259         if(!class_exists("iFrame")) {
4260                 require_once('modules/iFrames/iFrame.php');
4261         }
4262         return false;
4263    }
4264    return true;
4265 }
4266
4267 /**
4268  * Given a version such as 5.5.0RC1 return RC. If we have a version such as: 5.5 then return GA
4269  *
4270  * @param string $version
4271  * @return string RC, BETA, GA
4272  */
4273 function getVersionStatus($version){
4274         if(preg_match('/^[\d\.]+?([a-zA-Z]+?)[\d]*?$/si', $version, $matches)) {
4275                 return strtoupper($matches[1]);
4276         }else{
4277                 return 'GA';
4278         }
4279 }
4280
4281 /**
4282  * Return the numeric portion of a version. For example if passed 5.5.0RC1 then return 5.5. If given
4283  * 5.5.1RC1 then return 5.5.1
4284  *
4285  * @param string $version
4286  * @return version
4287  */
4288 function getMajorMinorVersion($version){
4289         if(preg_match('/^([\d\.]+).*$/si', $version, $matches2)){
4290                 $version = $matches2[1];
4291                 $arr = explode('.', $version);
4292                 if(count($arr) > 2){
4293                         if($arr[2] == '0'){
4294                                 $version = substr($version, 0, 3);
4295                         }
4296                 }
4297         }
4298         return $version;
4299 }
4300
4301 /**
4302  * Return string composed of seconds & microseconds of current time, without dots
4303  * @return string
4304  */
4305 function sugar_microtime()
4306 {
4307         $now = explode(' ', microtime());
4308         $unique_id = $now[1].str_replace('.', '', $now[0]);
4309         return $unique_id;
4310 }
4311
4312 /**
4313  * Extract urls from a piece of text
4314  * @param  $string
4315  * @return array of urls found in $string
4316  */
4317 function getUrls($string)
4318 {
4319         $lines = explode("<br>", trim($string));
4320         $urls = array();
4321         foreach($lines as $line){
4322         $regex = '/http?\:\/\/[^\" ]+/i';
4323         preg_match_all($regex, $line, $matches);
4324         foreach($matches[0] as $match){
4325                 $urls[] = $match;
4326         }
4327         }
4328     return $urls;
4329 }
4330
4331
4332 /**
4333  * Sanitize image file from hostile content
4334  * @param string $path Image file
4335  * @param bool $jpeg  Accept only JPEGs?
4336  */
4337 function verify_image_file($path, $jpeg = false)
4338 {
4339         if(function_exists('imagepng') && function_exists('imagejpeg') && function_exists('imagecreatefromstring')) {
4340         $img = imagecreatefromstring(file_get_contents($path));
4341         if(!$img) {
4342             return false;
4343         }
4344         $img_size = getimagesize($path);
4345                 $filetype = $img_size['mime'];
4346                 //if filetype is jpeg or if we are only allowing jpegs, create jpg image
4347         if($filetype == "image/jpeg" || $jpeg) {
4348             if(imagejpeg($img, $path)) {
4349                 return true;
4350             }
4351         } elseif ($filetype == "image/png") { // else if the filetype is png, create png
4352                 imagealphablending($img, true);
4353                 imagesavealpha($img, true);
4354             if(imagepng($img, $path)) {
4355                 return true;
4356             }
4357         } else {
4358                 return false;
4359         }
4360         } else {
4361             // check image manually
4362             $fp = fopen($path, "r");
4363             if(!$fp) return false;
4364             $data = fread($fp, 4096);
4365             fclose($fp);
4366             if(preg_match("/<(html|!doctype|script|body|head|plaintext|table|img |pre(>| )|frameset|iframe|object|link|base|style|font|applet|meta|center|form|isindex)/i",
4367                  $data, $m)) {
4368                 $GLOBALS['log']->info("Found {$m[0]} in $path, not allowing upload");
4369                 return false;
4370             }
4371             return true;
4372         }
4373         return false;
4374 }
4375
4376 /**
4377  * Verify uploaded image
4378  * Verifies that image has proper extension, MIME type and doesn't contain hostile contant
4379  * @param string $path  Image path
4380  * @param bool $jpeg_only  Accept only JPEGs?
4381  */
4382 function verify_uploaded_image($path, $jpeg_only = false)
4383 {
4384     $supportedExtensions = array('jpg' => 'image/jpeg', 'jpeg' => 'image/jpeg');
4385     if(!$jpeg_only) {
4386         $supportedExtensions['png'] = 'image/png';
4387     }
4388
4389     if(!file_exists($path) || !is_file($path)) {
4390             return false;
4391         }
4392
4393         $img_size = getimagesize($path);
4394         $filetype = $img_size['mime'];
4395         $ext = end(explode(".", $path));
4396         if(substr_count('..', $path) > 0 || $ext === $path || !in_array(strtolower($ext), array_keys($supportedExtensions)) ||
4397             !in_array($filetype, array_values($supportedExtensions))) {
4398                 return false;
4399         }
4400     return verify_image_file($path, $jpeg_only);
4401 }
4402
4403 function cmp_beans($a, $b)
4404 {
4405     global $sugar_web_service_order_by;
4406     //If the order_by field is not valid, return 0;
4407     if (empty($sugar_web_service_order_by) || !isset($a->$sugar_web_service_order_by) || !isset($b->$sugar_web_service_order_by)){
4408         return 0;
4409     }
4410     if (is_object($a->$sugar_web_service_order_by) || is_object($b->$sugar_web_service_order_by)
4411         || is_array($a->$sugar_web_service_order_by) || is_array($b->$sugar_web_service_order_by))
4412     {
4413         return 0;
4414     }
4415     if ($a->$sugar_web_service_order_by < $b->$sugar_web_service_order_by)
4416     {
4417         return -1;
4418     } else {
4419         return 1;
4420     }
4421 }
4422
4423 function order_beans($beans, $field_name)
4424 {
4425     //Since php 5.2 doesn't include closures, we must use a global to pass the order field to cmp_beans.
4426     global $sugar_web_service_order_by;
4427     $sugar_web_service_order_by = $field_name;
4428     usort($beans, "cmp_beans");
4429     return $beans;
4430 }
4431
4432 //check to see if custom utils exists
4433 if(file_exists('custom/include/custom_utils.php')){
4434         include_once('custom/include/custom_utils.php');
4435 }
4436
4437 //check to see if custom utils exists in Extension framework
4438 if(file_exists('custom/application/Ext/Utils/custom_utils.ext.php')) {
4439     include_once('custom/application/Ext/Utils/custom_utils.ext.php');
4440 }
4441 /**
4442  * @param $input - the input string to sanitize
4443  * @param int $quotes - use quotes
4444  * @param string $charset - the default charset
4445  * @param bool $remove - strip tags or not
4446  * @return string - the sanitized string
4447  */
4448 function sanitize($input, $quotes = ENT_QUOTES, $charset = 'UTF-8', $remove = false)
4449 {
4450     return htmlentities($input, $quotes, $charset);
4451 }