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