]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - install/install_utils.php
Release 6.4.0
[Github/sugarcrm.git] / install / install_utils.php
1 <?php
2 if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
3 /*********************************************************************************
4  * SugarCRM Community Edition is a customer relationship management program developed by
5  * SugarCRM, Inc. Copyright (C) 2004-2011 SugarCRM Inc.
6  * 
7  * This program is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU Affero General Public License version 3 as published by the
9  * Free Software Foundation with the addition of the following permission added
10  * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
11  * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
12  * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
13  * 
14  * This program is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
17  * details.
18  * 
19  * You should have received a copy of the GNU Affero General Public License along with
20  * this program; if not, see http://www.gnu.org/licenses or write to the Free
21  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22  * 02110-1301 USA.
23  * 
24  * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
25  * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
26  * 
27  * The interactive user interfaces in modified source and object code versions
28  * of this program must display Appropriate Legal Notices, as required under
29  * Section 5 of the GNU Affero General Public License version 3.
30  * 
31  * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
32  * these Appropriate Legal Notices must retain the display of the "Powered by
33  * SugarCRM" logo. If the display of the logo is not reasonably feasible for
34  * technical reasons, the Appropriate Legal Notices must display the words
35  * "Powered by SugarCRM".
36  ********************************************************************************/
37
38 /*********************************************************************************
39
40  * $Description: TODO: To be written. Portions created by SugarCRM are Copyright
41  * (C) SugarCRM, Inc. All Rights Reserved. Contributor(s):
42  * ______________________________________..
43  * *******************************************************************************/
44
45 require_once('include/utils/zip_utils.php');
46
47 require_once('include/upload_file.php');
48
49
50
51 ///////////////////////////////////////////////////////////////////////////////
52 ////    FROM welcome.php
53 /**
54  * returns lowercase lang encoding
55  * @return string   encoding or blank on false
56  */
57 function parseAcceptLanguage() {
58     $lang = $_SERVER['HTTP_ACCEPT_LANGUAGE'];
59     if(strpos($lang, ';')) {
60         $exLang = explode(';', $lang);
61         return strtolower(str_replace('-','_',$exLang[0]));
62     } else {
63         $match = array();
64         if(preg_match("#\w{2}\-?\_?\w{2}#", $lang, $match)) {
65             return strtolower(str_replace('-','_',$match[0]));
66         }
67     }
68     return '';
69 }
70
71
72 ///////////////////////////////////////////////////////////////////////////////
73 ////    FROM localization.php
74 /**
75  * copies the temporary unzip'd files to their final destination
76  * removes unzip'd files from system if $uninstall=true
77  * @param bool uninstall true if uninstalling a language pack
78  * @return array sugar_config
79  */
80 function commitLanguagePack($uninstall=false) {
81     global $sugar_config;
82     global $mod_strings;
83     global $base_upgrade_dir;
84     global $base_tmp_upgrade_dir;
85
86     $errors         = array();
87     $manifest       = urldecode($_REQUEST['manifest']);
88     $zipFile        = urldecode($_REQUEST['zipFile']);
89     $version        = "";
90     $show_files     = true;
91     $unzip_dir      = mk_temp_dir( $base_tmp_upgrade_dir );
92     $zip_from_dir   = ".";
93     $zip_to_dir     = ".";
94     $zip_force_copy = array();
95
96     if($uninstall == false && isset($_SESSION['INSTALLED_LANG_PACKS']) && in_array($zipFile, $_SESSION['INSTALLED_LANG_PACKS'])) {
97         return;
98     }
99
100     // unzip lang pack to temp dir
101     if(isset($zipFile) && !empty($zipFile)) {
102         if(is_file($zipFile)) {
103             unzip( $zipFile, $unzip_dir );
104         } else {
105             echo $mod_strings['ERR_LANG_MISSING_FILE'].$zipFile;
106             die(); // no point going any further
107         }
108     }
109
110     // filter for special to/from dir conditions (langpacks generally don't have them)
111     if(isset($manifest) && !empty($manifest)) {
112         if(is_file($manifest)) {
113             include($manifest);
114             if( isset( $manifest['copy_files']['from_dir'] ) && $manifest['copy_files']['from_dir'] != "" ){
115                 $zip_from_dir   = $manifest['copy_files']['from_dir'];
116             }
117             if( isset( $manifest['copy_files']['to_dir'] ) && $manifest['copy_files']['to_dir'] != "" ){
118                 $zip_to_dir     = $manifest['copy_files']['to_dir'];
119             }
120             if( isset( $manifest['copy_files']['force_copy'] ) && $manifest['copy_files']['force_copy'] != "" ){
121                 $zip_force_copy     = $manifest['copy_files']['force_copy'];
122             }
123             if( isset( $manifest['version'] ) ){
124                 $version    = $manifest['version'];
125             }
126         } else {
127             $errors[] = $mod_strings['ERR_LANG_MISSING_FILE'].$manifest;
128         }
129     }
130
131
132     // find name of language pack: find single file in include/language/xx_xx.lang.php
133     $d = dir( "$unzip_dir/$zip_from_dir/include/language" );
134     while( $f = $d->read() ){
135         if( $f == "." || $f == ".." ){
136             continue;
137         }
138         else if( preg_match("/(.*)\.lang\.php\$/", $f, $match) ){
139             $new_lang_name = $match[1];
140         }
141     }
142     if( $new_lang_name == "" ){
143         die( $mod_strings['ERR_LANG_NO_LANG_FILE'].$zipFile );
144     }
145     $new_lang_desc = getLanguagePackName( "$unzip_dir/$zip_from_dir/include/language/$new_lang_name.lang.php" );
146     if( $new_lang_desc == "" ){
147         die( "No language pack description found at include/language/$new_lang_name.lang.php inside $install_file." );
148     }
149     // add language to available languages
150     $sugar_config['languages'][$new_lang_name] = ($new_lang_desc);
151
152     // get an array of all files to be moved
153     $filesFrom = array();
154     $filesFrom = findAllFiles($unzip_dir, $filesFrom);
155
156
157
158     ///////////////////////////////////////////////////////////////////////////
159     ////    FINALIZE
160     if($uninstall) {
161         // unlink all pack files
162         foreach($filesFrom as $fileFrom) {
163             //echo "deleting: ".getcwd().substr($fileFrom, strlen($unzip_dir), strlen($fileFrom))."<br>";
164             @unlink(getcwd().substr($fileFrom, strlen($unzip_dir), strlen($fileFrom)));
165         }
166
167         // remove session entry
168         if(isset($_SESSION['INSTALLED_LANG_PACKS']) && is_array($_SESSION['INSTALLED_LANG_PACKS'])) {
169             foreach($_SESSION['INSTALLED_LANG_PACKS'] as $k => $langPack) {
170                 if($langPack == $zipFile) {
171                     unset($_SESSION['INSTALLED_LANG_PACKS'][$k]);
172                     unset($_SESSION['INSTALLED_LANG_PACKS_VERSION'][$k]);
173                     unset($_SESSION['INSTALLED_LANG_PACKS_MANIFEST'][$k]);
174                     $removedLang = $k;
175                 }
176             }
177
178             // remove language from config
179             $new_langs = array();
180             $old_langs = $sugar_config['languages'];
181             foreach( $old_langs as $key => $value ){
182                 if( $key != $removedLang ){
183                     $new_langs += array( $key => $value );
184                 }
185             }
186             $sugar_config['languages'] = $new_langs;
187         }
188     } else {
189         // copy filesFrom to filesTo
190         foreach($filesFrom as $fileFrom) {
191             @copy($fileFrom, getcwd().substr($fileFrom, strlen($unzip_dir), strlen($fileFrom)));
192         }
193
194         $_SESSION['INSTALLED_LANG_PACKS'][$new_lang_name] = $zipFile;
195         $_SESSION['INSTALLED_LANG_PACKS_VERSION'][$new_lang_name] = $version;
196         $serial_manifest = array();
197         $serial_manifest['manifest'] = (isset($manifest) ? $manifest : '');
198         $serial_manifest['installdefs'] = (isset($installdefs) ? $installdefs : '');
199         $serial_manifest['upgrade_manifest'] = (isset($upgrade_manifest) ? $upgrade_manifest : '');
200         $_SESSION['INSTALLED_LANG_PACKS_MANIFEST'][$new_lang_name] = base64_encode(serialize($serial_manifest));
201     }
202
203     writeSugarConfig($sugar_config);
204
205     return $sugar_config;
206 }
207
208 function commitPatch($unlink = false, $type = 'patch'){
209     require_once('ModuleInstall/ModuleInstaller.php');
210     require_once('include/entryPoint.php');
211
212
213     global $mod_strings;
214     global $base_upgrade_dir;
215     global $base_tmp_upgrade_dir;
216     global $db;
217     $GLOBALS['db'] = $db;
218     $errors = array();
219     $files = array();
220      global $current_user;
221     $current_user = new User();
222     $current_user->is_admin = '1';
223     $old_mod_strings = $mod_strings;
224     if(is_dir($base_upgrade_dir)) {
225             $files = findAllFiles("$base_upgrade_dir/$type", $files);
226             $mi = new ModuleInstaller();
227             $mi->silent = true;
228             $mod_strings = return_module_language('en', "Administration");
229
230             foreach($files as $file) {
231                 if(!preg_match('#.*\.zip\$#', $file)) {
232                     continue;
233                 }
234                 // handle manifest.php
235                 $target_manifest = remove_file_extension( $file ) . '-manifest.php';
236
237                 include($target_manifest);
238
239                 $unzip_dir = mk_temp_dir( $base_tmp_upgrade_dir );
240                 unzip($file, $unzip_dir );
241                 if(file_exists("$unzip_dir/scripts/pre_install.php")){
242                     require_once("$unzip_dir/scripts/pre_install.php");
243                     pre_install();
244                 }
245                 if( isset( $manifest['copy_files']['from_dir'] ) && $manifest['copy_files']['from_dir'] != "" ){
246                     $zip_from_dir   = $manifest['copy_files']['from_dir'];
247                 }
248                 $source = "$unzip_dir/$zip_from_dir";
249                 $dest = getcwd();
250                 copy_recursive($source, $dest);
251
252                 if(file_exists("$unzip_dir/scripts/post_install.php")){
253                     require_once("$unzip_dir/scripts/post_install.php");
254                     post_install();
255                 }
256                 $new_upgrade = new UpgradeHistory();
257                 $new_upgrade->filename      = $file;
258                 $new_upgrade->md5sum        = md5_file($file);
259                 $new_upgrade->type          = $manifest['type'];
260                 $new_upgrade->version       = $manifest['version'];
261                 $new_upgrade->status        = "installed";
262                 //$new_upgrade->author        = $manifest['author'];
263                 $new_upgrade->name          = $manifest['name'];
264                 $new_upgrade->description   = $manifest['description'];
265                 $serial_manifest = array();
266                 $serial_manifest['manifest'] = (isset($manifest) ? $manifest : '');
267                 $serial_manifest['installdefs'] = (isset($installdefs) ? $installdefs : '');
268                 $serial_manifest['upgrade_manifest'] = (isset($upgrade_manifest) ? $upgrade_manifest : '');
269                 $new_upgrade->manifest   = base64_encode(serialize($serial_manifest));
270                 $new_upgrade->save();
271                 unlink($file);
272             }//rof
273     }//fi
274     $mod_strings = $old_mod_strings;
275 }
276
277 function commitModules($unlink = false, $type = 'module'){
278     require_once('ModuleInstall/ModuleInstaller.php');
279     require_once('include/entryPoint.php');
280
281
282     global $mod_strings;
283     global $base_upgrade_dir;
284     global $base_tmp_upgrade_dir;
285     global $db;
286     $GLOBALS['db'] = $db;
287     $errors = array();
288     $files = array();
289      global $current_user;
290     $current_user = new User();
291     $current_user->is_admin = '1';
292     $old_mod_strings = $mod_strings;
293     if(is_dir(sugar_cached("upload/upgrades"))) {
294             $files = findAllFiles(sugar_cached("upload/upgrades/$type"), $files);
295             $mi = new ModuleInstaller();
296             $mi->silent = true;
297             $mod_strings = return_module_language('en', "Administration");
298
299             foreach($files as $file) {
300                 if(!preg_match('#.*\.zip\$', $file)) {
301                     continue;
302                 }
303                 $lic_name = 'accept_lic_'.str_replace('.', '_', urlencode(basename($file)));
304
305                 $can_install = true;
306                 if(isset($_REQUEST[$lic_name])){
307                     if($_REQUEST[$lic_name] == 'yes'){
308                         $can_install = true;
309                     }else{
310                         $can_install = false;
311                     }
312                 }
313                 if($can_install){
314                     // handle manifest.php
315                     $target_manifest = remove_file_extension( $file ) . '-manifest.php';
316                     if($type == 'langpack'){
317                         $_REQUEST['manifest'] = $target_manifest;
318                         $_REQUEST['zipFile'] = $file;
319                         commitLanguagePack();
320                         continue;
321                     }
322                     include($target_manifest);
323
324                     $unzip_dir = mk_temp_dir( $base_tmp_upgrade_dir );
325                     unzip($file, $unzip_dir );
326                     $_REQUEST['install_file'] = $file;
327                     $mi->install($unzip_dir);
328                     $new_upgrade = new UpgradeHistory();
329                     $new_upgrade->filename      = $file;
330                     $new_upgrade->md5sum        = md5_file($file);
331                     $new_upgrade->type          = $manifest['type'];
332                     $new_upgrade->version       = $manifest['version'];
333                     $new_upgrade->status        = "installed";
334                    // $new_upgrade->author        = $manifest['author'];
335                     $new_upgrade->name          = $manifest['name'];
336                     $new_upgrade->description   = $manifest['description'];
337                     $new_upgrade->id_name       = (isset($installdefs['id_name'])) ? $installdefs['id_name'] : '';
338                     $serial_manifest = array();
339                     $serial_manifest['manifest'] = (isset($manifest) ? $manifest : '');
340                     $serial_manifest['installdefs'] = (isset($installdefs) ? $installdefs : '');
341                     $serial_manifest['upgrade_manifest'] = (isset($upgrade_manifest) ? $upgrade_manifest : '');
342                     $new_upgrade->manifest   = base64_encode(serialize($serial_manifest));
343                     $new_upgrade->save();
344                     //unlink($file);
345                 }//fi
346             }//rof
347     }//fi
348     $mod_strings = $old_mod_strings;
349 }
350
351 /**
352  * creates UpgradeHistory entries
353  * @param mode string Install or Uninstall
354  */
355 function updateUpgradeHistory() {
356     if(isset($_SESSION['INSTALLED_LANG_PACKS']) && count($_SESSION['INSTALLED_LANG_PACKS']) > 0) {
357         foreach($_SESSION['INSTALLED_LANG_PACKS'] as $k => $zipFile) {
358             $new_upgrade = new UpgradeHistory();
359             $new_upgrade->filename      = $zipFile;
360             $new_upgrade->md5sum        = md5_file($zipFile);
361             $new_upgrade->type          = 'langpack';
362             $new_upgrade->version       = $_SESSION['INSTALLED_LANG_PACKS_VERSION'][$k];
363             $new_upgrade->status        = "installed";
364             $new_upgrade->manifest      = $_SESSION['INSTALLED_LANG_PACKS_MANIFEST'][$k];
365             $new_upgrade->save();
366         }
367     }
368 }
369
370
371 /**
372  * removes the installed language pack, but the zip is still in the cache dir
373  */
374 function removeLanguagePack() {
375     global $mod_strings;
376     global $sugar_config;
377
378     $errors = array();
379     $manifest = urldecode($_REQUEST['manifest']);
380     $zipFile = urldecode($_REQUEST['zipFile']);
381
382     if(isset($manifest) && !empty($manifest)) {
383         if(is_file($manifest)) {
384             if(!unlink($manifest)) {
385                 $errors[] = $mod_strings['ERR_LANG_CANNOT_DELETE_FILE'].$manifest;
386             }
387         } else {
388             $errors[] = $mod_strings['ERR_LANG_MISSING_FILE'].$manifest;
389         }
390         unset($_SESSION['packages_to_install'][$manifest]);
391     }
392     if(isset($zipFile) && !empty($zipFile)) {
393         if(is_file($zipFile)) {
394             if(!unlink($zipFile)) {
395                 $errors[] = $mod_strings['ERR_LANG_CANNOT_DELETE_FILE'].$zipFile;
396             }
397         } else {
398             $errors[] = $mod_strings['ERR_LANG_MISSING_FILE'].$zipFile;
399         }
400     }
401     if(count($errors > 0)) {
402         echo "<p class='error'>";
403         foreach($errors as $error) {
404             echo "{$error}<br>";
405         }
406         echo "</p>";
407     }
408
409     unlinkTempFiles($manifest, $zipFile);
410 }
411
412
413
414 /**
415  * takes the current value of $sugar_config and writes it out to config.php (sorta the same as the final step)
416  * @param array sugar_config
417  */
418 function writeSugarConfig($sugar_config) {
419     ksort($sugar_config);
420     $sugar_config_string = "<?php\n" .
421         '// created: ' . date('Y-m-d H:i:s') . "\n" .
422         '$sugar_config = ' .
423         var_export($sugar_config, true) .
424         ";\n?>\n";
425     if(is_writable('config.php') && write_array_to_file( "sugar_config", $sugar_config, "config.php")) {
426     }
427 }
428
429
430 /**
431  * uninstalls the Language pack
432  */
433 function uninstallLangPack() {
434     global $sugar_config;
435
436     // remove language from config
437     $new_langs = array();
438     $old_langs = $sugar_config['languages'];
439     foreach( $old_langs as $key => $value ){
440         if( $key != $_REQUEST['new_lang_name'] ){
441             $new_langs += array( $key => $value );
442         }
443     }
444     $sugar_config['languages'] = $new_langs;
445
446     writeSugarConfig($sugar_config);
447 }
448
449 /**
450  * retrieves the name of the language
451  */
452 if ( !function_exists('getLanguagePackName') ) {
453 function getLanguagePackName($the_file) {
454     require_once( "$the_file" );
455     if( isset( $app_list_strings["language_pack_name"] ) ){
456         return( $app_list_strings["language_pack_name"] );
457     }
458     return( "" );
459 }
460 }
461
462 function getInstalledLangPacks($showButtons=true) {
463     global $mod_strings;
464     global $next_step;
465
466     $ret  = "<tr><td colspan=7 align=left>{$mod_strings['LBL_LANG_PACK_INSTALLED']}</td></tr>";
467     //$ret .="<table width='100%' cellpadding='0' cellspacing='0' border='0'>";
468     $ret .= "<tr>
469                 <td width='15%' ><b>{$mod_strings['LBL_ML_NAME']}</b></td>
470                 <td width='15%' ><b>{$mod_strings['LBL_ML_VERSION']}</b></td>
471                 <td width='15%' ><b>{$mod_strings['LBL_ML_PUBLISHED']}</b></td>
472                 <td width='15%' ><b>{$mod_strings['LBL_ML_UNINSTALLABLE']}</b></td>
473                 <td width='15%' ><b>{$mod_strings['LBL_ML_DESCRIPTION']}</b></td>
474                 <td width='15%' ></td>
475                 <td width='15%' ></td>
476             </tr>\n";
477     $files = array();
478     $files = findAllFiles(sugar_cached("upload/upgrades"), $files);
479
480     if(isset($_SESSION['INSTALLED_LANG_PACKS']) && !empty($_SESSION['INSTALLED_LANG_PACKS'])){
481         if(count($_SESSION['INSTALLED_LANG_PACKS'] > 0)) {
482             foreach($_SESSION['INSTALLED_LANG_PACKS'] as $file) {
483                 // handle manifest.php
484                 $target_manifest = remove_file_extension( $file ) . '-manifest.php';
485                 include($target_manifest);
486
487                 $name = empty($manifest['name']) ? $file : $manifest['name'];
488                 $version = empty($manifest['version']) ? '' : $manifest['version'];
489                 $published_date = empty($manifest['published_date']) ? '' : $manifest['published_date'];
490                 $icon = '';
491                 $description = empty($manifest['description']) ? 'None' : $manifest['description'];
492                 $uninstallable = empty($manifest['is_uninstallable']) ? 'No' : 'Yes';
493                 $manifest_type = $manifest['type'];
494
495                 $deletePackage = getPackButton('uninstall', $target_manifest, $file, $next_step, $uninstallable, $showButtons);
496                 //$ret .="<table width='100%' cellpadding='0' cellspacing='0' border='0'>";
497                 $ret .= "<tr>";
498                 $ret .= "<td width='15%' >".$name."</td>";
499                 $ret .= "<td width='15%' >".$version."</td>";
500                 $ret .= "<td width='15%' >".$published_date."</td>";
501                 $ret .= "<td width='15%' >".$uninstallable."</td>";
502                 $ret .= "<td width='15%' >".$description."</td>";
503                 $ret .= "<td width='15%' ></td>";
504                 $ret .= "<td width='15%' >{$deletePackage}</td>";
505                 $ret .= "</tr>";
506             }
507         } else {
508             $ret .= "</tr><td colspan=7><i>{$mod_strings['LBL_LANG_NO_PACKS']}</i></td></tr>";
509         }
510     } else {
511         $ret .= "</tr><td colspan=7><i>{$mod_strings['LBL_LANG_NO_PACKS']}</i></td></tr>";
512     }
513     return $ret;
514 }
515
516
517 function uninstallLanguagePack() {
518     return commitLanguagePack(true);
519 }
520
521
522 function getSugarConfigLanguageArray($langZip) {
523     global $sugar_config;
524
525     include(remove_file_extension($langZip)."-manifest.php");
526     $ret = '';
527     if(isset($installdefs['id']) && isset($manifest['name'])) {
528         $ret = $installdefs['id']."::".$manifest['name']."::".$manifest['version'];
529     }
530
531     return $ret;
532 }
533
534
535
536 ///////////////////////////////////////////////////////////////////////////////
537 ////    FROM performSetup.php
538
539 function getInstallDbInstance()
540 {
541     return DBManagerFactory::getTypeInstance($_SESSION['setup_db_type'], array("db_manager" => $_SESSION['setup_db_manager']));
542 }
543
544 function getDbConnection()
545 {
546     $dbconfig = array(
547                 "db_host_name" => $_SESSION['setup_db_host_name'],
548                 "db_user_name" => $_SESSION['setup_db_admin_user_name'],
549                 "db_password" => $_SESSION['setup_db_admin_password'],
550                 "db_host_instance" => $_SESSION['setup_db_host_instance'],
551                 "db_port" => $_SESSION['setup_db_port_num'],
552     );
553     if(empty($_SESSION['setup_db_create_database'])) {
554             $dbconfig["db_name"] = $_SESSION['setup_db_database_name'];
555     }
556
557     $db = getInstallDbInstance();
558     if(!empty($_SESSION['setup_db_options'])) {
559         $db->setOptions($_SESSION['setup_db_options']);
560     }
561     $db->connect($dbconfig, true);
562     return $db;
563 }
564
565 /**
566  * creates the Sugar DB user (if not admin)
567  */
568 function handleDbCreateSugarUser() {
569     global $mod_strings;
570     global $setup_db_database_name;
571     global $setup_db_host_name;
572     global $setup_db_host_instance;
573     global $setup_db_port_num;
574     global $setup_db_admin_user_name;
575     global $setup_db_admin_password;
576     global $sugar_config;
577     global $setup_db_sugarsales_user;
578     global $setup_site_host_name;
579     global $setup_db_sugarsales_password;
580
581     echo $mod_strings['LBL_PERFORM_CREATE_DB_USER'];
582
583     $db = getDbConnection();
584     $db->createDbUser($setup_db_database_name, $setup_site_host_name, $setup_db_sugarsales_user, $setup_db_sugarsales_password);
585     $err = $db->lastError();
586     if($err == '')  {
587         echo $mod_strings['LBL_PERFORM_DONE'];
588     } else {
589           echo "<div style='color:red;'>";
590           echo "An error occured when creating user:<br>";
591           echo "$err<br>";
592           echo "</div>";
593           installLog("An error occured when creating user: $err");
594     }
595 }
596
597 /**
598  * ensures that the charset and collation for a given database is set
599  * MYSQL ONLY
600  */
601 function handleDbCharsetCollation() {
602     global $mod_strings;
603     global $setup_db_database_name;
604     global $setup_db_host_name;
605     global $setup_db_admin_user_name;
606     global $setup_db_admin_password;
607     global $sugar_config;
608
609     if($_SESSION['setup_db_type'] == 'mysql') {
610          $db = getDbConnection();
611          $db->query("ALTER DATABASE `{$setup_db_database_name}` DEFAULT CHARACTER SET utf8", true);
612          $db->query("ALTER DATABASE `{$setup_db_database_name}` DEFAULT COLLATE utf8_general_ci", true);
613     }
614 }
615
616
617 /**
618  * creates the new database
619  */
620 function handleDbCreateDatabase() {
621     global $mod_strings;
622     global $setup_db_database_name;
623     global $setup_db_host_name;
624     global $setup_db_host_instance;
625     global $setup_db_port_num;
626     global $setup_db_admin_user_name;
627     global $setup_db_admin_password;
628     global $sugar_config;
629
630     echo "{$mod_strings['LBL_PERFORM_CREATE_DB_1']} {$setup_db_database_name} {$mod_strings['LBL_PERFORM_CREATE_DB_2']} {$setup_db_host_name}...";
631     $db = getDbConnection();
632     if($db->dbExists($setup_db_database_name)) {
633         $db->dropDatabase($setup_db_database_name);
634     }
635     $db->createDatabase($setup_db_database_name);
636
637     echo $mod_strings['LBL_PERFORM_DONE'];
638 }
639
640
641 /**
642  * handles creation of Log4PHP properties file
643  * This function has been deprecated.  Use SugarLogger.
644  */
645 function handleLog4Php() {
646     return;
647 }
648
649 function installLog($entry) {
650     global $mod_strings;
651     $nl = '
652 '.gmdate("Y-m-d H:i:s").'...';
653     $log = clean_path(getcwd().'/install.log');
654
655     // create if not exists
656     if(!file_exists($log)) {
657         $fp = @sugar_fopen($log, 'w+'); // attempts to create file
658         if(!is_resource($fp)) {
659             $GLOBALS['log']->fatal('could not create the install.log file');
660         }
661     } else {
662         $fp = @sugar_fopen($log, 'a+'); // write pointer at end of file
663         if(!is_resource($fp)) {
664             $GLOBALS['log']->fatal('could not open/lock install.log file');
665         }
666     }
667
668
669
670     if(@fwrite($fp, $nl.$entry) === false) {
671         $GLOBALS['log']->fatal('could not write to install.log: '.$entry);
672     }
673
674     if(is_resource($fp)) {
675         fclose($fp);
676     }
677 }
678
679
680
681 /**
682  * takes session vars and creates config.php
683  * @return array bottle collection of error messages
684  */
685 function handleSugarConfig() {
686     global $bottle;
687     global $cache_dir;
688     global $mod_strings;
689     global $setup_db_host_name;
690     global $setup_db_host_instance;
691     global $setup_db_port_num;
692     global $setup_db_sugarsales_user;
693     global $setup_db_sugarsales_password;
694     global $setup_db_database_name;
695     global $setup_site_host_name;
696     global $setup_site_log_dir;
697     global $setup_site_log_file;
698     global $setup_site_session_path;
699     global $setup_site_guid;
700     global $setup_site_url;
701     global $setup_sugar_version;
702     global $sugar_config;
703     global $setup_site_log_level;
704
705     echo "<b>{$mod_strings['LBL_PERFORM_CONFIG_PHP']} (config.php)</b><br>";
706     ///////////////////////////////////////////////////////////////////////////////
707     ////    $sugar_config SETTINGS
708     if( is_file('config.php') ){
709         $is_writable = is_writable('config.php');
710         // require is needed here (config.php is sometimes require'd from install.php)
711         require('config.php');
712     } else {
713         $is_writable = is_writable('.');
714     }
715
716     // build default sugar_config and merge with new values
717     $sugar_config = sugarArrayMerge(get_sugar_config_defaults(), $sugar_config);
718     // always lock the installer
719     $sugar_config['installer_locked'] = true;
720     // we're setting these since the user was given a fair chance to change them
721     $sugar_config['dbconfig']['db_host_name']       = $setup_db_host_name;
722     if(!empty($setup_db_host_instance)) {
723         $sugar_config['dbconfig']['db_host_instance']   = $setup_db_host_instance;
724     } else {
725         $sugar_config['dbconfig']['db_host_instance'] = '';
726     }
727     if(!isset($_SESSION['setup_db_manager'])) {
728         $_SESSION['setup_db_manager'] = DBManagerFactory::getManagerByType($_SESSION['setup_db_type']);
729     }
730     $sugar_config['dbconfig']['db_user_name']       = $setup_db_sugarsales_user;
731     $sugar_config['dbconfig']['db_password']        = $setup_db_sugarsales_password;
732     $sugar_config['dbconfig']['db_name']            = $setup_db_database_name;
733     $sugar_config['dbconfig']['db_type']            = $_SESSION['setup_db_type'];
734     $sugar_config['dbconfig']['db_port']            = $setup_db_port_num;
735     $sugar_config['dbconfig']['db_manager']         = $_SESSION['setup_db_manager'];
736     if(!empty($_SESSION['setup_db_options'])) {
737         $sugar_config['dbconfigoption']                 = array_merge($sugar_config['dbconfigoption'], $_SESSION['setup_db_options']);
738     }
739
740     $sugar_config['cache_dir']                      = $cache_dir;
741     $sugar_config['default_charset']                = $mod_strings['DEFAULT_CHARSET'];
742     $sugar_config['default_email_client']           = 'sugar';
743     $sugar_config['default_email_editor']           = 'html';
744     $sugar_config['host_name']                      = $setup_site_host_name;
745     $sugar_config['js_custom_version']              = '';
746     $sugar_config['use_real_names']                 = true;
747     $sugar_config['log_dir']                        = $setup_site_log_dir;
748     $sugar_config['log_file']                       = $setup_site_log_file;
749
750         /*nsingh(bug 22402): Consolidate logger settings under $config['logger'] as liked by the new logger! If log4pphp exists,
751                 these settings will be overwritten by those in log4php.properties when the user access admin->system settings.*/
752     $sugar_config['logger']     =
753         array ('level'=>$setup_site_log_level,
754          'file' => array(
755                         'ext' => '.log',
756                         'name' => 'sugarcrm',
757                         'dateFormat' => '%c',
758                         'maxSize' => '10MB',
759                         'maxLogs' => 10,
760                         'suffix' => '%m_%Y'),
761         );
762     $sugar_config['session_dir']                    = $setup_site_session_path;
763     $sugar_config['site_url']                       = $setup_site_url;
764     $sugar_config['sugar_version']                  = $setup_sugar_version;
765     $sugar_config['tmp_dir']                        = $cache_dir.'xml/';
766     $sugar_config['upload_dir']                 = 'upload/';
767 //    $sugar_config['use_php_code_json']              = returnPhpJsonStatus(); // true on error
768     if( isset($_SESSION['setup_site_sugarbeet_anonymous_stats']) ){
769         $sugar_config['sugarbeet']      = $_SESSION['setup_site_sugarbeet_anonymous_stats'];
770     }
771     $sugar_config['demoData'] = $_SESSION['demoData'];
772     if( isset( $setup_site_guid ) ){
773         $sugar_config['unique_key'] = $setup_site_guid;
774     }
775     if(empty($sugar_config['unique_key'])){
776         $sugar_config['unique_key'] = md5( create_guid() );
777     }
778     // add installed langs to config
779     // entry in upgrade_history comes AFTER table creation
780     if(isset($_SESSION['INSTALLED_LANG_PACKS']) && is_array($_SESSION['INSTALLED_LANG_PACKS']) && !empty($_SESSION['INSTALLED_LANG_PACKS'])) {
781         foreach($_SESSION['INSTALLED_LANG_PACKS'] as $langZip) {
782             $lang = getSugarConfigLanguageArray($langZip);
783             if(!empty($lang)) {
784                 $exLang = explode('::', $lang);
785                 if(is_array($exLang) && count($exLang) == 3) {
786                     $sugar_config['languages'][$exLang[0]] = $exLang[1];
787                 }
788             }
789         }
790     }
791     if(file_exists('install/lang.config.php')){
792         include('install/lang.config.php');
793         if(!empty($config['languages'])){
794                 foreach($config['languages'] as $lang=>$label){
795                         $sugar_config['languages'][$lang] = $label;
796                 }
797         }
798     }
799
800     ksort($sugar_config);
801     $sugar_config_string = "<?php\n" .
802         '// created: ' . date('Y-m-d H:i:s') . "\n" .
803         '$sugar_config = ' .
804         var_export($sugar_config, true) .
805         ";\n?>\n";
806     if($is_writable && write_array_to_file( "sugar_config", $sugar_config, "config.php")) {
807         // was 'Done'
808     } else {
809         echo 'failed<br>';
810         echo "<p>{$mod_strings['ERR_PERFORM_CONFIG_PHP_1']}</p>\n";
811         echo "<p>{$mod_strings['ERR_PERFORM_CONFIG_PHP_2']}</p>\n";
812         echo "<TEXTAREA  rows=\"15\" cols=\"80\">".$sugar_config_string."</TEXTAREA>";
813         echo "<p>{$mod_strings['ERR_PERFORM_CONFIG_PHP_3']}</p>";
814
815         $bottle[] = $mod_strings['ERR_PERFORM_CONFIG_PHP_4'];
816     }
817
818
819     //Now merge the config_si.php settings into config.php
820     if(file_exists('config.php') && file_exists('config_si.php'))
821     {
822        require_once('modules/UpgradeWizard/uw_utils.php');
823        merge_config_si_settings(false, 'config.php', 'config_si.php');
824     }
825
826
827     ////    END $sugar_config
828     ///////////////////////////////////////////////////////////////////////////////
829     return $bottle;
830 }
831 /**
832  * (re)write the .htaccess file to prevent browser access to the log file
833  */
834 function handleHtaccess(){
835 global $mod_strings;
836 $ignoreCase = (substr_count(strtolower($_SERVER['SERVER_SOFTWARE']), 'apache/2') > 0)?'(?i)':'';
837 $htaccess_file   = ".htaccess";
838 $contents = '';
839 $restrict_str = <<<EOQ
840
841 # BEGIN SUGARCRM RESTRICTIONS
842 RedirectMatch 403 {$ignoreCase}.*\.log$
843 RedirectMatch 403 {$ignoreCase}/+not_imported_.*\.txt
844 RedirectMatch 403 {$ignoreCase}/+(soap|cache|xtemplate|data|examples|include|log4php|metadata|modules)/+.*\.(php|tpl)
845 RedirectMatch 403 {$ignoreCase}/+emailmandelivery\.php
846 RedirectMatch 403 {$ignoreCase}/+upload
847 RedirectMatch 403 {$ignoreCase}/+custom/+blowfish
848 RedirectMatch 403 {$ignoreCase}/+cache/+diagnostic
849 RedirectMatch 403 {$ignoreCase}/+files\.md5$
850 # END SUGARCRM RESTRICTIONS
851 EOQ;
852         if(file_exists($htaccess_file)){
853                 $fp = fopen($htaccess_file, 'r');
854                 $skip = false;
855                 while($line = fgets($fp)){
856
857                         if(preg_match("/\s*#\s*BEGIN\s*SUGARCRM\s*RESTRICTIONS/i", $line))$skip = true;
858                         if(!$skip)$contents .= $line;
859                         if(preg_match("/\s*#\s*END\s*SUGARCRM\s*RESTRICTIONS/i", $line))$skip = false;
860                 }
861         }
862         $status =  file_put_contents($htaccess_file, $contents . $restrict_str);
863     if( !$status ) {
864         echo "<p>{$mod_strings['ERR_PERFORM_HTACCESS_1']}<span class=stop>{$htaccess_file}</span> {$mod_strings['ERR_PERFORM_HTACCESS_2']}</p>\n";
865         echo "<p>{$mod_strings['ERR_PERFORM_HTACCESS_3']}</p>\n";
866         echo $restrict_str;
867     }
868     return $status;
869 }
870
871 /**
872  * (re)write the web.config file to prevent browser access to the log file
873  */
874 function handleWebConfig()
875 {
876     if ( !isset($_SERVER['IIS_UrlRewriteModule']) ) {
877         return;
878     }
879
880         global $setup_site_log_dir;
881     global $setup_site_log_file;
882     global $sugar_config;
883
884     // Bug 36968 - Fallback to using $sugar_config values when we are not calling this from the installer
885     if (empty($setup_site_log_file)) {
886         $setup_site_log_file = $sugar_config['log_file'];
887         if ( empty($sugar_config['log_file']) ) {
888             $setup_site_log_file = 'sugarcrm.log';
889         }
890     }
891     if (empty($setup_site_log_dir)) {
892         $setup_site_log_dir = $sugar_config['log_dir'];
893         if ( empty($sugar_config['log_dir']) ) {
894             $setup_site_log_dir = '.';
895         }
896     }
897
898     $prefix = $setup_site_log_dir.empty($setup_site_log_dir)?'':'/';
899
900
901     $config_array = array(
902     array('1'=> $prefix.str_replace('.','\\.',$setup_site_log_file).'\\.*' ,'2'=>'log_file_restricted.html'),
903     array('1'=> $prefix.'install.log' ,'2'=>'log_file_restricted.html'),
904     array('1'=> $prefix.'upgradeWizard.log' ,'2'=>'log_file_restricted.html'),
905     array('1'=> $prefix.'emailman.log' ,'2'=>'log_file_restricted.html'),
906     array('1'=>'not_imported_.*.txt' ,'2'=>'log_file_restricted.html'),
907     array('1'=>'XTemplate/(.*)/(.*).php' ,'2'=>'index.php'),
908     array('1'=>'data/(.*).php' ,'2'=>'index.php'),
909     array('1'=>'examples/(.*).php' ,'2'=>'index.php'),
910     array('1'=>'include/(.*).php' ,'2'=>'index.php'),
911     array('1'=>'include/(.*)/(.*).php' ,'2'=>'index.php'),
912     array('1'=>'log4php/(.*).php' ,'2'=>'index.php'),
913     array('1'=>'log4php/(.*)/(.*)' ,'2'=>'index.php'),
914     array('1'=>'metadata/(.*)/(.*).php' ,'2'=>'index.php'),
915     array('1'=>'modules/(.*)/(.*).php' ,'2'=>'index.php'),
916     array('1'=>'soap/(.*).php' ,'2'=>'index.php'),
917     array('1'=>'emailmandelivery.php' ,'2'=>'index.php'),
918     array('1'=>'cron.php' ,'2'=>'index.php'),
919     array('1'=> $sugar_config['upload_dir'].'.*' ,'2'=>'index.php'),
920     );
921
922
923     $xmldoc = new XMLWriter();
924     $xmldoc->openURI('web.config');
925     $xmldoc->setIndent(true);
926     $xmldoc->setIndentString(' ');
927     $xmldoc->startDocument('1.0','UTF-8');
928     $xmldoc->startElement('configuration');
929     $xmldoc->startElement('system.webServer');
930     $xmldoc->startElement('rewrite');
931     $xmldoc->startElement('rules');
932     for ($i = 0; $i < count($config_array); $i++) {
933         $xmldoc->startElement('rule');
934         $xmldoc->writeAttribute('name', "redirect$i");
935         $xmldoc->writeAttribute('stopProcessing', 'true');
936         $xmldoc->startElement('match');
937         $xmldoc->writeAttribute('url', $config_array[$i]['1']);
938         $xmldoc->endElement();
939         $xmldoc->startElement('action');
940         $xmldoc->writeAttribute('type', 'Redirect');
941         $xmldoc->writeAttribute('url', $config_array[$i]['2']);
942         $xmldoc->writeAttribute('redirectType', 'Found');
943         $xmldoc->endElement();
944         $xmldoc->endElement();
945     }
946     $xmldoc->endElement();
947     $xmldoc->endElement();
948     $xmldoc->endElement();
949     $xmldoc->endElement();
950     $xmldoc->endDocument();
951     $xmldoc->flush();
952 }
953
954 /**
955  * Drop old tables if table exists and told to drop it
956  */
957 function drop_table_install( &$focus ){
958     global $db;
959     global $dictionary;
960
961     $result = $db->tableExists($focus->table_name);
962
963     if( $result ){
964         $focus->drop_tables();
965         $GLOBALS['log']->info("Dropped old ".$focus->table_name." table.");
966         return 1;
967     }
968     else {
969         $GLOBALS['log']->info("Did not need to drop old ".$focus->table_name." table.  It doesn't exist.");
970         return 0;
971     }
972 }
973
974 // Creating new tables if they don't exist.
975 function create_table_if_not_exist( &$focus ){
976     global  $db;
977     $table_created = false;
978
979     // normal code follows
980     $result = $db->tableExists($focus->table_name);
981     if($result){
982         $GLOBALS['log']->info("Table ".$focus->table_name." already exists.");
983     } else {
984         $focus->create_tables();
985         $GLOBALS['log']->info("Created ".$focus->table_name." table.");
986         $table_created = true;
987     }
988     return $table_created;
989 }
990
991
992
993 function create_default_users(){
994     global $db;
995     global $setup_site_admin_password;
996     global $setup_site_admin_user_name;
997     global $create_default_user;
998     global $sugar_config;
999     global $current_user;
1000         require_once('install/UserDemoData.php');
1001
1002     //Create default admin user
1003     $current_user = new User();
1004     $current_user->id = 1;
1005     $current_user->new_with_id = true;
1006     $current_user->last_name = 'Administrator';
1007     //$user->user_name = 'admin';
1008     $current_user->user_name = $setup_site_admin_user_name;
1009     $current_user->title = "Administrator";
1010     $current_user->status = 'Active';
1011     $current_user->is_admin = true;
1012         $current_user->employee_status = 'Active';
1013     //$user->user_password = $user->encrypt_password($setup_site_admin_password);
1014     $current_user->user_hash = strtolower(md5($setup_site_admin_password));
1015     $current_user->email = '';
1016     $current_user->picture = UserDemoData::_copy_user_image($current_user->id);
1017     $current_user->save();
1018
1019     // echo 'Creating RSS Feeds';
1020     //$feed = new Feed();
1021     //$feed->createRSSHomePage($user->id);
1022
1023
1024     // We need to change the admin user to a fixed id of 1.
1025     // $query = "update users set id='1' where user_name='$user->user_name'";
1026     // $result = $db->query($query, true, "Error updating admin user ID: ");
1027
1028     $GLOBALS['log']->info("Created ".$current_user->table_name." table. for user $current_user->id");
1029
1030     if( $create_default_user ){
1031         $default_user = new User();
1032         $default_user->last_name = $sugar_config['default_user_name'];
1033         $default_user->user_name = $sugar_config['default_user_name'];
1034         $default_user->status = 'Active';
1035         if( isset($sugar_config['default_user_is_admin']) && $sugar_config['default_user_is_admin'] ){
1036             $default_user->is_admin = true;
1037         }
1038         //$default_user->user_password = $default_user->encrypt_password($sugar_config['default_password']);
1039         $default_user->user_hash = strtolower(md5($sugar_config['default_password']));
1040         $default_user->save();
1041         //$feed->createRSSHomePage($user->id);
1042     }
1043 }
1044
1045 function set_admin_password( $password ) {
1046     global $db;
1047
1048     $user = new User();
1049     $encrypted_password = $user->encrypt_password($password);
1050     $user_hash = strtolower(md5($password));
1051
1052     //$query = "update users set user_password='$encrypted_password', user_hash='$user_hash' where id='1'";
1053     $query = "update users set user_hash='$user_hash' where id='1'";
1054
1055     $db->query($query);
1056 }
1057
1058 function insert_default_settings(){
1059     global $db;
1060     global $setup_sugar_version;
1061     global $sugar_db_version;
1062
1063
1064     $db->query("INSERT INTO config (category, name, value) VALUES ('notify', 'fromaddress', 'do_not_reply@example.com')");
1065     $db->query("INSERT INTO config (category, name, value) VALUES ('notify', 'fromname', 'SugarCRM')");
1066     $db->query("INSERT INTO config (category, name, value) VALUES ('notify', 'send_by_default', '1')");
1067     $db->query("INSERT INTO config (category, name, value) VALUES ('notify', 'on', '1')");
1068     $db->query("INSERT INTO config (category, name, value) VALUES ('notify', 'send_from_assigning_user', '0')");
1069     /* cn: moved to OutboundEmail class
1070     $db->query("INSERT INTO config (category, name, value) VALUES ('mail', 'smtpserver', 'localhost')");
1071     $db->query("INSERT INTO config (category, name, value) VALUES ('mail', 'smtpport', '25')");
1072     $db->query("INSERT INTO config (category, name, value) VALUES ('mail', 'sendtype', 'smtp')");
1073     $db->query("INSERT INTO config (category, name, value) VALUES ('mail', 'smtpuser', '')");
1074     $db->query("INSERT INTO config (category, name, value) VALUES ('mail', 'smtppass', '')");
1075     $db->query("INSERT INTO config (category, name, value) VALUES ('mail', 'smtpauth_req', '0')");
1076     */
1077     $db->query("INSERT INTO config (category, name, value) VALUES ('info', 'sugar_version', '" . $sugar_db_version . "')");
1078     $db->query("INSERT INTO config (category, name, value) VALUES ('MySettings', 'tab', '')");
1079     $db->query("INSERT INTO config (category, name, value) VALUES ('portal', 'on', '0')");
1080
1081
1082
1083     //insert default tracker settings
1084     $db->query("INSERT INTO config (category, name, value) VALUES ('tracker', 'Tracker', '1')");
1085
1086
1087
1088     $db->query( "INSERT INTO config (category, name, value) VALUES ( 'system', 'skypeout_on', '1')" );
1089
1090 }
1091
1092
1093
1094
1095
1096
1097
1098
1099 // Returns true if the given file/dir has been made writable (or is already
1100 // writable).
1101 function make_writable($file)
1102 {
1103
1104     $ret_val = false;
1105     if(is_file($file) || is_dir($file))
1106     {
1107         if(is_writable($file))
1108         {
1109             $ret_val = true;
1110         }
1111         else
1112         {
1113             $original_fileperms = fileperms($file);
1114
1115             // add user writable permission
1116             $new_fileperms = $original_fileperms | 0x0080;
1117             @sugar_chmod($file, $new_fileperms);
1118             clearstatcache();
1119             if(is_writable($file))
1120             {
1121                 $ret_val = true;
1122             }
1123             else
1124             {
1125                 // add group writable permission
1126                 $new_fileperms = $original_fileperms | 0x0010;
1127                 @chmod($file, $new_fileperms);
1128                 clearstatcache();
1129                 if(is_writable($file))
1130                 {
1131                     $ret_val = true;
1132                 }
1133                 else
1134                 {
1135                     // add world writable permission
1136                     $new_fileperms = $original_fileperms | 0x0002;
1137                     @chmod($file, $new_fileperms);
1138                     clearstatcache();
1139                     if(is_writable($file))
1140                     {
1141                         $ret_val = true;
1142                     }
1143                 }
1144             }
1145         }
1146     }
1147
1148     return $ret_val;
1149 }
1150
1151 function recursive_make_writable($start_file)
1152     {
1153     $ret_val = make_writable($start_file);
1154
1155     if($ret_val && is_dir($start_file))
1156     {
1157         // PHP 4 alternative to scandir()
1158         $files = array();
1159         $dh = opendir($start_file);
1160         $filename = readdir($dh);
1161         while(!empty($filename))
1162         {
1163             if($filename != '.' && $filename != '..' && $filename != '.svn')
1164             {
1165                 $files[] = $filename;
1166             }
1167
1168             $filename = readdir($dh);
1169         }
1170
1171         foreach($files as $file)
1172         {
1173             $ret_val = recursive_make_writable($start_file . '/' . $file);
1174
1175             if(!$ret_val)
1176             {
1177                 $_SESSION['unwriteable_module_files'][dirname($file)] = dirname($file);
1178                 $fnl_ret_val = false;
1179                 //break;
1180             }
1181         }
1182     }
1183             if(!$ret_val)
1184             {
1185                 $unwriteable_directory = is_dir($start_file) ? $start_file : dirname($start_file);
1186                 if($unwriteable_directory[0] == '.'){$unwriteable_directory = substr($unwriteable_directory,1);}
1187                 $_SESSION['unwriteable_module_files'][$unwriteable_directory] = $unwriteable_directory;
1188                 $_SESSION['unwriteable_module_files']['failed'] = true;
1189             }
1190
1191     return $ret_val;
1192 }
1193
1194 function recursive_is_writable($start_file)
1195 {
1196     $ret_val = is_writable($start_file);
1197
1198     if($ret_val && is_dir($start_file))
1199     {
1200         // PHP 4 alternative to scandir()
1201         $files = array();
1202         $dh = opendir($start_file);
1203         $filename = readdir($dh);
1204         while(!empty($filename))
1205         {
1206             if($filename != '.' && $filename != '..' && $filename != '.svn')
1207             {
1208                 $files[] = $filename;
1209             }
1210
1211             $filename = readdir($dh);
1212         }
1213
1214         foreach($files as $file)
1215         {
1216             $ret_val = recursive_is_writable($start_file . '/' . $file);
1217
1218             if(!$ret_val)
1219             {
1220                 break;
1221             }
1222         }
1223     }
1224
1225     return $ret_val;
1226 }
1227
1228 // one place for form validation/conversion to boolean
1229 function get_boolean_from_request( $field ){
1230     if( !isset($_REQUEST[$field]) ){
1231         return( false );
1232     }
1233
1234     if( ($_REQUEST[$field] == 'on') || ($_REQUEST[$field] == 'yes') ){
1235         return(true);
1236     }
1237     else {
1238         return(false);
1239     }
1240 }
1241
1242 function stripslashes_checkstrings($value){
1243    if(is_string($value)){
1244       return stripslashes($value);
1245    }
1246    return $value;
1247 }
1248
1249
1250 function print_debug_array( $name, $debug_array ){
1251     ksort( $debug_array );
1252
1253     print( "$name vars:\n" );
1254     print( "(\n" );
1255
1256     foreach( $debug_array as $key => $value ){
1257         if( stristr( $key, "password" ) ){
1258             $value = "WAS SET";
1259         }
1260         print( "    [$key] => $value\n" );
1261     }
1262
1263     print( ")\n" );
1264 }
1265
1266 function print_debug_comment(){
1267     if( !empty($_REQUEST['debug']) ){
1268         $_SESSION['debug'] = $_REQUEST['debug'];
1269     }
1270
1271     if( !empty($_SESSION['debug']) && ($_SESSION['debug'] == 'true') ){
1272         print( "<!-- debug is on (to turn off, hit any page with 'debug=false' as a URL parameter.\n" );
1273
1274         print_debug_array( "Session",   $_SESSION );
1275         print_debug_array( "Request",   $_REQUEST );
1276         print_debug_array( "Post",      $_POST );
1277         print_debug_array( "Get",       $_GET );
1278
1279         print_r( "-->\n" );
1280     }
1281 }
1282
1283 function validate_systemOptions() {
1284     global $mod_strings;
1285     $errors = array();
1286     $db = DBManagerFactory::getTypeInstance($_SESSION['setup_db_type']);
1287     if(empty($db)) {
1288        $errors[] = "<span class='error'>".$mod_strings['ERR_DB_INVALID']."</span>";
1289     } else {
1290         $_SESSION['setup_db_manager'] = get_class($db);
1291     }
1292     return $errors;
1293 }
1294
1295
1296 function validate_dbConfig() {
1297     global $mod_strings;
1298     require_once('install/checkDBSettings.php');
1299     return checkDBSettings(true);
1300
1301 }
1302
1303 function validate_siteConfig($type){
1304     global $mod_strings;
1305    $errors = array();
1306
1307    if($type=='a'){
1308        if(empty($_SESSION['setup_system_name'])){
1309             $errors[] = "<span class='error'>".$mod_strings['LBL_REQUIRED_SYSTEM_NAME']."</span>";
1310        }
1311        if($_SESSION['setup_site_url'] == ''){
1312           $errors[] = "<span class='error'>".$mod_strings['ERR_URL_BLANK']."</span>";
1313        }
1314
1315        if($_SESSION['setup_site_admin_user_name'] == '') {
1316           $errors[] = "<span class='error'>".$mod_strings['ERR_ADMIN_USER_NAME_BLANK']."</span>";
1317        }
1318
1319        if($_SESSION['setup_site_admin_password'] == ''){
1320           $errors[] = "<span class='error'>".$mod_strings['ERR_ADMIN_PASS_BLANK']."</span>";
1321        }
1322
1323        if($_SESSION['setup_site_admin_password'] != $_SESSION['setup_site_admin_password_retype']){
1324           $errors[] = "<span class='error'>".$mod_strings['ERR_PASSWORD_MISMATCH']."</span>";
1325        }
1326    }else{
1327        if(!empty($_SESSION['setup_site_custom_session_path']) && $_SESSION['setup_site_session_path'] == ''){
1328           $errors[] = "<span class='error'>".$mod_strings['ERR_SESSION_PATH']."</span>";
1329        }
1330
1331        if(!empty($_SESSION['setup_site_custom_session_path']) && $_SESSION['setup_site_session_path'] != ''){
1332           if(is_dir($_SESSION['setup_site_session_path'])){
1333              if(!is_writable($_SESSION['setup_site_session_path'])){
1334                 $errors[] = "<span class='error'>".$mod_strings['ERR_SESSION_DIRECTORY']."</span>";
1335              }
1336           }
1337           else {
1338              $errors[] = "<span class='error'>".$mod_strings['ERR_SESSION_DIRECTORY_NOT_EXISTS']."</span>";
1339           }
1340        }
1341
1342        if(!empty($_SESSION['setup_site_custom_log_dir']) && $_SESSION['setup_site_log_dir'] == ''){
1343           $errors[] = "<span class='error'>".$mod_strings['ERR_LOG_DIRECTORY_NOT_EXISTS']."</span>";
1344        }
1345
1346        if(!empty($_SESSION['setup_site_custom_log_dir']) && $_SESSION['setup_site_log_dir'] != ''){
1347           if(is_dir($_SESSION['setup_site_log_dir'])){
1348              if(!is_writable($_SESSION['setup_site_log_dir'])) {
1349                 $errors[] = "<span class='error'>".$mod_strings['ERR_LOG_DIRECTORY_NOT_WRITABLE']."</span>";
1350              }
1351           }
1352           else {
1353              $errors[] = "<span class='error'>".$mod_strings['ERR_LOG_DIRECTORY_NOT_EXISTS']."</span>";
1354           }
1355        }
1356
1357        if(!empty($_SESSION['setup_site_specify_guid']) && $_SESSION['setup_site_guid'] == ''){
1358           $errors[] = "<span class='error'>".$mod_strings['ERR_SITE_GUID']."</span>";
1359        }
1360    }
1361
1362    return $errors;
1363 }
1364
1365
1366 function pullSilentInstallVarsIntoSession() {
1367     global $mod_strings;
1368     global $sugar_config;
1369
1370
1371     if( file_exists('config_si.php') ){
1372         require_once('config_si.php');
1373     }
1374     else if( empty($sugar_config_si) ){
1375         die( $mod_strings['ERR_SI_NO_CONFIG'] );
1376     }
1377
1378     $config_subset = array (
1379         'setup_site_url'                => isset($sugar_config['site_url']) ? $sugar_config['site_url'] : '',
1380         'setup_db_host_name'            => isset($sugar_config['dbconfig']['db_host_name']) ? $sugar_config['dbconfig']['db_host_name'] : '',
1381         'setup_db_host_instance'        => isset($sugar_config['dbconfig']['db_host_instance']) ? $sugar_config['dbconfig']['db_host_instance'] : '',
1382         'setup_db_sugarsales_user'      => isset($sugar_config['dbconfig']['db_user_name']) ? $sugar_config['dbconfig']['db_user_name'] : '',
1383         'setup_db_sugarsales_password'  => isset($sugar_config['dbconfig']['db_password']) ? $sugar_config['dbconfig']['db_password'] : '',
1384         'setup_db_database_name'        => isset($sugar_config['dbconfig']['db_name']) ? $sugar_config['dbconfig']['db_name'] : '',
1385         'setup_db_type'                 => isset($sugar_config['dbconfig']['db_type']) ? $sugar_config['dbconfig']['db_type'] : '',
1386         'setup_db_port_num'             => isset($sugar_config['dbconfig']['db_port']) ? $sugar_config['dbconfig']['db_port'] : '',
1387         'setup_db_options'                          => !empty($sugar_config['dbconfigoptions']) ? $sugar_config['dbconfigoptions'] : array(),
1388     );
1389     // third array of values derived from above values
1390     $derived = array (
1391         'setup_site_admin_password_retype'      => $sugar_config_si['setup_site_admin_password'],
1392         'setup_db_sugarsales_password_retype'   => $config_subset['setup_db_sugarsales_password'],
1393     );
1394
1395     $needles = array('setup_db_create_database','setup_db_create_sugarsales_user','setup_license_key_users',
1396                                  'setup_license_key_expire_date','setup_license_key', 'setup_num_lic_oc',
1397                      'default_currency_iso4217', 'default_currency_name', 'default_currency_significant_digits',
1398                      'default_currency_symbol',  'default_date_format', 'default_time_format', 'default_decimal_seperator',
1399                      'default_export_charset', 'default_language', 'default_locale_name_format', 'default_number_grouping_seperator',
1400                      'export_delimiter', 'cache_dir', 'setup_db_options');
1401     copyFromArray($sugar_config_si, $needles, $derived);
1402     $all_config_vars = array_merge( $config_subset, $sugar_config_si, $derived );
1403
1404     // bug 16860 tyoung -  trim leading and trailing whitespace from license_key
1405     if (isset($all_config_vars['setup_license_key'])) {
1406         $all_config_vars['setup_license_key'] = trim($all_config_vars['setup_license_key']);
1407     }
1408
1409     foreach( $all_config_vars as $key => $value ){
1410         $_SESSION[$key] = $value;
1411     }
1412 }
1413
1414 /**
1415  * given an array it will check to determine if the key exists in the array, if so
1416  * it will addd to the return array
1417  *
1418  * @param intput_array haystack to check
1419  * @param needles list of needles to search for
1420  * @param output_array the array to add the keys to
1421  */
1422 function copyFromArray($input_array, $needles, $output_array){
1423     foreach($needles as $needle){
1424          if(isset($input_array[$needle])){
1425             $output_array[$needle]  = $input_array[$needle];
1426          }
1427     }
1428 }
1429
1430
1431
1432 /**
1433  * handles language pack uploads - code based off of upload_file->final_move()
1434  * puts it into the cache/upload dir to be handed off to langPackUnpack();
1435  *
1436  * @param object file UploadFile object
1437  * @return bool true if successful
1438  */
1439 function langPackFinalMove($file) {
1440     global $sugar_config;
1441     //."upgrades/langpack/"
1442     $destination = $sugar_config['upload_dir'].$file->stored_file_name;
1443     if(!move_uploaded_file($_FILES[$file->field_name]['tmp_name'], $destination)) {
1444         die ("ERROR: can't move_uploaded_file to $destination. You should try making the directory writable by the webserver");
1445     }
1446     return true;
1447 }
1448
1449 function getLicenseDisplay($type, $manifest, $zipFile, $next_step, $license_file, $clean_file) {
1450     return PackageManagerDisplay::getLicenseDisplay($license_file, 'install.php', $next_step, $zipFile, $type, $manifest, $clean_file);
1451 }
1452
1453
1454 /**
1455  * creates the remove/delete form for langpack page
1456  * @param string type commit/remove
1457  * @param string manifest path to manifest file
1458  * @param string zipFile path to uploaded zip file
1459  * @param int nextstep current step
1460  * @return string ret <form> for this package
1461  */
1462 function getPackButton($type, $manifest, $zipFile, $next_step, $uninstallable='Yes', $showButtons=true) {
1463     global $mod_strings;
1464
1465     $button = $mod_strings['LBL_LANG_BUTTON_COMMIT'];
1466     if($type == 'remove') {
1467         $button = $mod_strings['LBL_LANG_BUTTON_REMOVE'];
1468     } elseif($type == 'uninstall') {
1469         $button = $mod_strings['LBL_LANG_BUTTON_UNINSTALL'];
1470     }
1471
1472     $disabled = ($uninstallable == 'Yes') ? false : true;
1473
1474     $ret = "<form name='delete{$zipFile}' action='install.php' method='POST'>
1475                 <input type='hidden' name='current_step' value='{$next_step}'>
1476                 <input type='hidden' name='goto' value='{$mod_strings['LBL_CHECKSYS_RECHECK']}'>
1477                 <input type='hidden' name='languagePackAction' value='{$type}'>
1478                 <input type='hidden' name='manifest' value='".urlencode($manifest)."'>
1479                 <input type='hidden' name='zipFile' value='".urlencode($zipFile)."'>
1480                 <input type='hidden' name='install_type' value='custom'>";
1481     if(!$disabled && $showButtons) {
1482         $ret .= "<input type='submit' value='{$button}' class='button'>";
1483     }
1484     $ret .= "</form>";
1485     return $ret;
1486 }
1487
1488 /**
1489  * finds all installed languages and returns an array with the names
1490  * @return array langs array of installed languages
1491  */
1492 function getInstalledLanguages() {
1493     $langDir = 'include/language/';
1494     $dh = opendir($langDir);
1495
1496     $langs = array();
1497     while($file = readdir($dh)) {
1498         if(substr($file, -3) == 'php') {
1499
1500         }
1501     }
1502 }
1503
1504
1505
1506 /**
1507  * searches upgrade dir for lang pack files.
1508  *
1509  * @return string HTML of available lang packs
1510  */
1511 function getLangPacks($display_commit = true, $types = array('langpack'), $notice_text = '') {
1512     global $mod_strings;
1513     global $next_step;
1514     global $base_upgrade_dir;
1515
1516     if(empty($notice_text)){
1517         $notice_text =  $mod_strings['LBL_LANG_PACK_READY'];
1518     }
1519         $ret = "<tr><td colspan=7 align=left>{$notice_text}</td></tr>";
1520     //$ret .="<table width='100%' cellpadding='0' cellspacing='0' border='0'>";
1521     $ret .= "<tr>
1522                 <td width='20%' ><b>{$mod_strings['LBL_ML_NAME']}</b></td>
1523                 <td width='15%' ><b>{$mod_strings['LBL_ML_VERSION']}</b></td>
1524                 <td width='15%' ><b>{$mod_strings['LBL_ML_PUBLISHED']}</b></td>
1525                 <td width='15%' ><b>{$mod_strings['LBL_ML_UNINSTALLABLE']}</b></td>
1526                 <td width='20%' ><b>{$mod_strings['LBL_ML_DESCRIPTION']}</b></td>
1527                 <td width='7%' ></td>
1528                 <td width='1%' ></td>
1529                 <td width='7%' ></td>
1530             </tr>\n";
1531     $files = array();
1532
1533     // duh, new installs won't have the upgrade folders
1534    if(!is_dir($base_upgrade_dir)) {
1535             mkdir_recursive( $base_upgrade_dir);
1536         }
1537         $subdirs = array('full', 'langpack', 'module', 'patch', 'theme', 'temp');
1538         foreach( $subdirs as $subdir ){
1539                 mkdir_recursive( "$base_upgrade_dir/$subdir" );
1540         }
1541
1542     $files = findAllFiles($base_upgrade_dir, $files);
1543     $hidden_input = '';
1544     unset($_SESSION['hidden_input']);
1545
1546     foreach($files as $file) {
1547         if(!preg_match("#.*\.zip\$#", $file)) {
1548             continue;
1549         }
1550
1551         // skip installed lang packs
1552         if(isset($_SESSION['INSTALLED_LANG_PACKS']) && in_array($file, $_SESSION['INSTALLED_LANG_PACKS'])) {
1553             continue;
1554         }
1555
1556         // handle manifest.php
1557         $target_manifest = remove_file_extension( $file ) . '-manifest.php';
1558         $license_file = remove_file_extension( $file ) . '-license.txt';
1559         include($target_manifest);
1560
1561         if(!empty($types)){
1562             if(!in_array(strtolower($manifest['type']), $types))
1563                 continue;
1564         }
1565
1566         $md5_matches = array();
1567         if($manifest['type'] == 'module'){
1568             $uh = new UpgradeHistory();
1569             $upgrade_content = clean_path($file);
1570             $the_base = basename($upgrade_content);
1571             $the_md5 = md5_file($upgrade_content);
1572             $md5_matches = $uh->findByMd5($the_md5);
1573         }
1574
1575         if($manifest['type']!= 'module' || 0 == sizeof($md5_matches)){
1576             $name = empty($manifest['name']) ? $file : $manifest['name'];
1577             $version = empty($manifest['version']) ? '' : $manifest['version'];
1578             $published_date = empty($manifest['published_date']) ? '' : $manifest['published_date'];
1579             $icon = '';
1580             $description = empty($manifest['description']) ? 'None' : $manifest['description'];
1581             $uninstallable = empty($manifest['is_uninstallable']) ? 'No' : 'Yes';
1582             $manifest_type = $manifest['type'];
1583             $commitPackage = getPackButton('commit', $target_manifest, $file, $next_step);
1584             $deletePackage = getPackButton('remove', $target_manifest, $file, $next_step);
1585             //$ret .="<table width='100%' cellpadding='0' cellspacing='0' border='0'>";
1586             $ret .= "<tr>";
1587             $ret .= "<td width='20%' >".$name."</td>";
1588             $ret .= "<td width='15%' >".$version."</td>";
1589             $ret .= "<td width='15%' >".$published_date."</td>";
1590             $ret .= "<td width='15%' >".$uninstallable."</td>";
1591             $ret .= "<td width='20%' >".$description."</td>";
1592
1593             if($display_commit)
1594                 $ret .= "<td width='7%'>{$commitPackage}</td>";
1595             $ret .= "<td width='1%'></td>";
1596             $ret .= "<td width='7%'>{$deletePackage}</td>";
1597             $ret .= "</td></tr>";
1598
1599             $clean_field_name = "accept_lic_".str_replace('.', '_', urlencode(basename($file)));
1600
1601             if(is_file($license_file)){
1602                 //rrs
1603                 $ret .= "<tr><td colspan=6>";
1604                 $ret .= getLicenseDisplay('commit', $target_manifest, $file, $next_step, $license_file, $clean_field_name);
1605                 $ret .= "</td></tr>";
1606                 $hidden_input .= "<input type='hidden' name='$clean_field_name' id='$clean_field_name' value='no'>";
1607             }else{
1608                 $hidden_input .= "<input type='hidden' name='$clean_field_name' id='$clean_field_name' value='yes'>";
1609             }
1610         }//fi
1611     }//rof
1612     $_SESSION['hidden_input'] = $hidden_input;
1613
1614     if(count($files) > 0 ) {
1615         $ret .= "</tr><td colspan=7>";
1616         $ret .= "<form name='commit' action='install.php' method='POST'>
1617                     <input type='hidden' name='current_step' value='{$next_step}'>
1618                     <input type='hidden' name='goto' value='Re-check'>
1619                     <input type='hidden' name='languagePackAction' value='commit'>
1620                     <input type='hidden' name='install_type' value='custom'>
1621                  </form>
1622                 ";
1623         $ret .= "</td></tr>";
1624     } else {
1625         $ret .= "</tr><td colspan=7><i>{$mod_strings['LBL_LANG_NO_PACKS']}</i></td></tr>";
1626     }
1627     return $ret;
1628 }
1629
1630 if ( !function_exists('extractFile') ) {
1631 function extractFile( $zip_file, $file_in_zip, $base_tmp_upgrade_dir){
1632     $my_zip_dir = mk_temp_dir( $base_tmp_upgrade_dir );
1633     unzip_file( $zip_file, $file_in_zip, $my_zip_dir );
1634     return( "$my_zip_dir/$file_in_zip" );
1635 }
1636 }
1637
1638 if ( !function_exists('extractManifest') ) {
1639 function extractManifest( $zip_file,$base_tmp_upgrade_dir ) {
1640     return( extractFile( $zip_file, "manifest.php",$base_tmp_upgrade_dir ) );
1641 }
1642 }
1643
1644 if ( !function_exists('unlinkTempFiles') ) {
1645 function unlinkTempFiles($manifest='', $zipFile='') {
1646     global $sugar_config;
1647
1648     @unlink($_FILES['language_pack']['tmp_name']);
1649     if(!empty($manifest))
1650         @unlink($manifest);
1651     if(!empty($zipFile)) {
1652         //@unlink($zipFile);
1653         $tmpZipFile = substr($zipFile, strpos($zipFile, 'langpack/') + 9, strlen($zipFile));
1654         @unlink($sugar_config['upload_dir'].$tmpZipFile);
1655     }
1656
1657     rmdir_recursive($sugar_config['upload_dir']."upgrades/temp");
1658     sugar_mkdir($sugar_config['upload_dir']."upgrades/temp");
1659 }
1660 }
1661
1662 function langPackUnpack($unpack_type, $full_file)
1663 {
1664     global $sugar_config;
1665     global $base_upgrade_dir;
1666     global $base_tmp_upgrade_dir;
1667
1668     $manifest = array();
1669     if(!empty($full_file)){
1670         $base_filename = pathinfo(urldecode($full_file), PATHINFO_FILENAME );
1671     } else {
1672         return "Empty filename supplied";
1673     }
1674     $manifest_file = extractManifest($full_file, $base_tmp_upgrade_dir);
1675     if($unpack_type == 'module')
1676         $license_file = extractFile($full_file, 'LICENSE.txt', $base_tmp_upgrade_dir);
1677
1678     if(is_file($manifest_file)) {
1679
1680         if($unpack_type == 'module' && is_file($license_file)){
1681             copy($license_file, $base_upgrade_dir.'/'.$unpack_type.'/'.$base_filename."-license.txt");
1682         }
1683         copy($manifest_file, $base_upgrade_dir.'/'.$unpack_type.'/'.$base_filename."-manifest.php");
1684
1685         require_once( $manifest_file );
1686         validate_manifest( $manifest );
1687         $upgrade_zip_type = $manifest['type'];
1688
1689         mkdir_recursive( "$base_upgrade_dir/$upgrade_zip_type" );
1690         $target_path = "$base_upgrade_dir/$upgrade_zip_type/$base_filename";
1691         $target_manifest = $target_path . "-manifest.php";
1692
1693         if( isset($manifest['icon']) && $manifest['icon'] != "" ) {
1694             $icon_location = extractFile( $full_file, $manifest['icon'], $base_tmp_upgrade_dir );
1695             $path_parts = pathinfo( $icon_location );
1696             copy( $icon_location, $target_path . "-icon." . $path_parts['extension'] );
1697         }
1698
1699         // move file from uploads to cache
1700         // FIXME: where should it be?
1701         if( copy( $full_file , $target_path.".zip" ) ){
1702             copy( $manifest_file, $target_manifest );
1703             unlink($full_file); // remove tempFile
1704             return "The file $base_filename has been uploaded.<br>\n";
1705         } else {
1706             unlinkTempFiles($manifest_file, $full_file);
1707             return "There was an error uploading the file, please try again!<br>\n";
1708         }
1709     } else {
1710         die("The zip file is missing a manifest.php file.  Cannot proceed.");
1711     }
1712     unlinkTempFiles($manifest_file, '');
1713 }
1714
1715 if ( !function_exists('validate_manifest') ) {
1716 function validate_manifest( $manifest ){
1717     // takes a manifest.php manifest array and validates contents
1718     global $subdirs;
1719     global $sugar_version;
1720     global $sugar_flavor;
1721     global $mod_strings;
1722
1723     if( !isset($manifest['type']) ){
1724         die($mod_strings['ERROR_MANIFEST_TYPE']);
1725     }
1726     $type = $manifest['type'];
1727     if( getInstallType( "/$type/" ) == "" ){
1728         die($mod_strings['ERROR_PACKAGE_TYPE']. ": '" . $type . "'." );
1729     }
1730
1731     return true; // making this a bit more relaxed since we updated the language extraction and merge capabilities
1732
1733     /*
1734     if( isset($manifest['acceptable_sugar_versions']) ){
1735         $version_ok = false;
1736         $matches_empty = true;
1737         if( isset($manifest['acceptable_sugar_versions']['exact_matches']) ){
1738             $matches_empty = false;
1739             foreach( $manifest['acceptable_sugar_versions']['exact_matches'] as $match ){
1740                 if( $match == $sugar_version ){
1741                     $version_ok = true;
1742                 }
1743             }
1744         }
1745         if( !$version_ok && isset($manifest['acceptable_sugar_versions']['regex_matches']) ){
1746             $matches_empty = false;
1747             foreach( $manifest['acceptable_sugar_versions']['regex_matches'] as $match ){
1748                 if( preg_match( "/$match/", $sugar_version ) ){
1749                     $version_ok = true;
1750                 }
1751             }
1752         }
1753
1754         if( !$matches_empty && !$version_ok ){
1755             die( $mod_strings['ERROR_VERSION_INCOMPATIBLE'] . $sugar_version );
1756         }
1757     }
1758
1759     if( isset($manifest['acceptable_sugar_flavors']) && sizeof($manifest['acceptable_sugar_flavors']) > 0 ){
1760         $flavor_ok = false;
1761         foreach( $manifest['acceptable_sugar_flavors'] as $match ){
1762             if( $match == $sugar_flavor ){
1763                 $flavor_ok = true;
1764             }
1765         }
1766         if( !$flavor_ok ){
1767             //die( $mod_strings['ERROR_FLAVOR_INCOMPATIBLE'] . $sugar_flavor );
1768         }
1769     }*/
1770 }
1771 }
1772
1773 if ( !function_exists('getInstallType') ) {
1774 function getInstallType( $type_string ){
1775     // detect file type
1776     $subdirs = array('full', 'langpack', 'module', 'patch', 'theme', 'temp');
1777     foreach( $subdirs as $subdir ){
1778         if( preg_match( "#/$subdir/#", $type_string ) ){
1779             return( $subdir );
1780         }
1781     }
1782     // return empty if no match
1783     return( "" );
1784 }
1785 }
1786
1787
1788
1789 //mysqli connector has a separate parameter for port.. We need to separate it out from the host name
1790 function getHostPortFromString($hostname=''){
1791
1792     $pos=strpos($hostname,':');
1793     if($pos === false){
1794         //no need to process as string is empty or does not contain ':' delimiter
1795         return '';
1796     }
1797
1798     $hostArr = explode(':', $hostname);
1799
1800     return $hostArr;
1801
1802 }
1803
1804 function getLicenseContents($filename)
1805 {
1806         $license_file = '';
1807     if(file_exists($filename) && filesize($filename) >0){
1808             $license_file = trim(file_get_contents($filename));
1809     }
1810     return $license_file;
1811 }
1812
1813
1814
1815
1816
1817
1818
1819
1820 ///////////////////////////////////////////////////////////////////////////////
1821 ////    FROM POPULATE SEED DATA
1822 $seed = array(
1823     'qa',       'dev',          'beans',
1824     'info',     'sales',        'support',
1825     'kid',      'the',          'section',
1826     'sugar',    'hr',           'im',
1827     'kid',      'vegan',        'phone',
1828 );
1829 $tlds = array(
1830     ".com", ".org", ".net", ".tv", ".cn", ".co.jp", ".us",
1831     ".edu", ".tw", ".de", ".it", ".co.uk", ".info", ".biz",
1832     ".name",
1833 );
1834
1835 /**
1836  * creates a random, DNS-clean webaddress
1837  */
1838 function createWebAddress() {
1839     global $seed;
1840     global $tlds;
1841
1842     $one = $seed[rand(0, count($seed)-1)];
1843     $two = $seed[rand(0, count($seed)-1)];
1844     $tld = $tlds[rand(0, count($tlds)-1)];
1845
1846     return "www.{$one}{$two}{$tld}";
1847 }
1848
1849 /**
1850  * creates a random email address
1851  * @return string
1852  */
1853 function createEmailAddress() {
1854     global $seed;
1855     global $tlds;
1856
1857     $part[0] = $seed[rand(0, count($seed)-1)];
1858     $part[1] = $seed[rand(0, count($seed)-1)];
1859     $part[2] = $seed[rand(0, count($seed)-1)];
1860
1861     $tld = $tlds[rand(0, count($tlds)-1)];
1862
1863     $len = rand(1,3);
1864
1865     $ret = '';
1866     for($i=0; $i<$len; $i++) {
1867         $ret .= (empty($ret)) ? '' : '.';
1868         $ret .= $part[$i];
1869     }
1870
1871     if($len == 1) {
1872         $ret .= rand(10, 99);
1873     }
1874
1875     return "{$ret}@example{$tld}";
1876 }
1877
1878
1879 function add_digits($quantity, &$string, $min = 0, $max = 9) {
1880     for($i=0; $i < $quantity; $i++) {
1881         $string .= mt_rand($min,$max);
1882     }
1883 }
1884
1885 function create_phone_number() {
1886     $phone = "(";
1887     add_digits(3, $phone);
1888     $phone .= ") ";
1889     add_digits(3, $phone);
1890     $phone .= "-";
1891     add_digits(4, $phone);
1892
1893     return $phone;
1894 }
1895
1896 function create_date($year=null,$mnth=null,$day=null)
1897 {
1898     global $timedate;
1899     $now = $timedate->getNow();
1900     if ($day==null) $day=$now->day+mt_rand(0,365);
1901     return $timedate->asDbDate($now->get_day_begin($day, $mnth, $year));
1902 }
1903
1904 function create_current_date_time()
1905 {
1906     global $timedate;
1907     return $timedate->nowDb();
1908 }
1909
1910 function create_time($hr=null,$min=null,$sec=null)
1911 {
1912     global $timedate;
1913     $date = TimeDate::fromTimestamp(0);
1914     if ($hr==null) $hr=mt_rand(6,19);
1915     if ($min==null) $min=(mt_rand(0,3)*15);
1916     if ($sec==null) $sec=0;
1917     return $timedate->asDbTime($date->setDate(2007, 10, 7)->setTime($hr, $min, $sec));
1918 }
1919
1920 function create_past_date()
1921 {
1922     global $timedate;
1923     $now = $timedate->getNow(true);
1924     $day=$now->day-mt_rand(1, 365);
1925     return $timedate->asUserDate($now->get_day_begin($day));
1926 }
1927
1928 /**
1929 *   This method will look for a file modules_post_install.php in the root directory and based on the
1930 *   contents of this file, it will silently install any modules as specified in this array.
1931 */
1932 function post_install_modules(){
1933     if(is_file('modules_post_install.php')){
1934         global $current_user, $mod_strings;
1935         $current_user = new User();
1936         $current_user->is_admin = '1';
1937         require_once('ModuleInstall/PackageManager/PackageManager.php');
1938         require_once('modules_post_install.php');
1939         //we now have the $modules_to_install array in memory
1940         $pm = new PackageManager();
1941         $old_mod_strings = $mod_strings;
1942         foreach($modules_to_install as $module_to_install){
1943             if(is_file($module_to_install)){
1944                 $pm->performSetup($module_to_install, 'module', false);
1945                 $file_to_install = sugar_cached('upload/upgrades/module/').basename($module_to_install);
1946                 $_REQUEST['install_file'] = $file_to_install;
1947                 $pm->performInstall($file_to_install);
1948             }
1949         }
1950         $mod_strings = $old_mod_strings;
1951     }
1952 }
1953
1954 function get_help_button_url(){
1955     $help_url = 'http://www.sugarcrm.com/docs/Administration_Guides/CommunityEdition_Admin_Guide_5.0/toc.html';
1956
1957     return $help_url;
1958 }
1959
1960 function create_db_user_creds($numChars=10){
1961 $numChars = 7; // number of chars in the password
1962 //chars to select from
1963 $charBKT = "abcdefghijklmnpqrstuvwxyz123456789ABCDEFGHIJKLMNPQRSTUVWXYZ";
1964 // seed the random number generator
1965 srand((double)microtime()*1000000);
1966 $password="";
1967 for ($i=0;$i<$numChars;$i++)  // loop and create password
1968             $password = $password . substr ($charBKT, rand() % strlen($charBKT), 1);
1969
1970 return $password;
1971
1972 }
1973
1974 function addDefaultRoles($defaultRoles = array()) {
1975         global $db;
1976
1977
1978         foreach($defaultRoles as $roleName=>$role){
1979             $ACLField = new ACLField();
1980         $role1= new ACLRole();
1981         $role1->name = $roleName;
1982         $role1->description = $roleName." Role";
1983         $role1_id=$role1->save();
1984         foreach($role as $category=>$actions){
1985             foreach($actions as $name=>$access_override){
1986                 if($name=='fields'){
1987                     foreach($access_override as $field_id=>$access){
1988                         $ACLField->setAccessControl($category, $role1_id, $field_id, $access);
1989                     }
1990                 }else{
1991                     $queryACL="SELECT id FROM acl_actions where category='$category' and name='$name'";
1992                     $result = $db->query($queryACL);
1993                     $actionId=$db->fetchByAssoc($result);
1994                     if (isset($actionId['id']) && !empty($actionId['id'])){
1995                         $role1->setAction($role1_id, $actionId['id'], $access_override);
1996                     }
1997                 }
1998             }
1999         }
2000         }
2001 }
2002
2003 /**
2004  * Fully enable SugarFeeds, enabling the user feed and all available modules that have SugarFeed data.
2005  */
2006 function enableSugarFeeds()
2007 {
2008     $admin = new Administration();
2009     $admin->saveSetting('sugarfeed','enabled','1');
2010
2011     foreach ( SugarFeed::getAllFeedModules() as $module )
2012         SugarFeed::activateModuleFeed($module);
2013
2014     check_logic_hook_file('Users','after_login', array(1, 'SugarFeed old feed entry remover', 'modules/SugarFeed/SugarFeedFlush.php', 'SugarFeedFlush', 'flushStaleEntries'));
2015 }
2016
2017 function create_writable_dir($dirname)
2018 {
2019     if ((is_dir($dirname)) || @sugar_mkdir($dirname,0555)) {
2020         $ok = make_writable($dirname);
2021     }
2022     if(empty($ok)) {
2023         installLog("ERROR: Cannot create writable dir $dirname");
2024     }
2025 }
2026
2027 /**
2028  * Enable the InsideView connector for the four default modules.
2029  */
2030 function enableInsideViewConnector()
2031 {
2032     // Load up the existing mapping and hand it to the InsideView connector to have it setup the correct logic hooks
2033     $mapFile = 'modules/Connectors/connectors/sources/ext/rest/insideview/mapping.php';
2034     if ( file_exists('custom/'.$mapFile) ) {
2035         require('custom/'.$mapFile);
2036     } else {
2037         require($mapFile);
2038     }
2039
2040     require_once('modules/Connectors/connectors/sources/ext/rest/insideview/insideview.php');
2041     $source = new ext_rest_insideview();
2042
2043     // $mapping is brought in from the mapping.php file above
2044     $source->saveMappingHook($mapping);
2045 }