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