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-2012 SugarCRM Inc.
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.
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
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
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.
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.
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 ********************************************************************************/
38 /*********************************************************************************
40 * $Description: TODO: To be written. Portions created by SugarCRM are Copyright
41 * (C) SugarCRM, Inc. All Rights Reserved. Contributor(s):
42 * ______________________________________..
43 * *******************************************************************************/
45 require_once('include/utils/zip_utils.php');
47 require_once('include/upload_file.php');
53 * Calls a custom function (if it exists) based on the first parameter,
54 * and returns result of function call, or 'undefined' if the function doesn't exist
55 * @param string function name to call in custom install hooks
56 * @return mixed function call result, or 'undefined'
58 function installerHook($function_name, $options = array()){
59 if(!isset($GLOBALS['customInstallHooksExist'])){
60 if(file_exists('custom/install/install_hooks.php')){
61 installLog("installerHook: Found custom/install/install_hooks.php");
62 require_once('custom/install/install_hooks.php');
63 $GLOBALS['customInstallHooksExist'] = true;
66 installLog("installerHook: Could not find custom/install/install_hooks.php");
67 $GLOBALS['customInstallHooksExist'] = false;
71 if($GLOBALS['customInstallHooksExist'] === false){
75 if(function_exists($function_name)){
76 installLog("installerHook: function {$function_name} found, calling and returning the return value");
77 return $function_name($options);
80 installLog("installerHook: function {$function_name} not found in custom install hooks file");
86 ///////////////////////////////////////////////////////////////////////////////
89 * returns lowercase lang encoding
90 * @return string encoding or blank on false
92 function parseAcceptLanguage() {
93 $lang = $_SERVER['HTTP_ACCEPT_LANGUAGE'];
94 if(strpos($lang, ';')) {
95 $exLang = explode(';', $lang);
96 return strtolower(str_replace('-','_',$exLang[0]));
99 if(preg_match("#\w{2}\-?\_?\w{2}#", $lang, $match)) {
100 return strtolower(str_replace('-','_',$match[0]));
107 ///////////////////////////////////////////////////////////////////////////////
108 //// FROM localization.php
110 * copies the temporary unzip'd files to their final destination
111 * removes unzip'd files from system if $uninstall=true
112 * @param bool uninstall true if uninstalling a language pack
113 * @return array sugar_config
115 function commitLanguagePack($uninstall=false) {
116 global $sugar_config;
118 global $base_upgrade_dir;
119 global $base_tmp_upgrade_dir;
122 $manifest = urldecode($_REQUEST['manifest']);
123 $zipFile = urldecode($_REQUEST['zipFile']);
126 $unzip_dir = mk_temp_dir( $base_tmp_upgrade_dir );
129 $zip_force_copy = array();
131 if($uninstall == false && isset($_SESSION['INSTALLED_LANG_PACKS']) && in_array($zipFile, $_SESSION['INSTALLED_LANG_PACKS'])) {
135 // unzip lang pack to temp dir
136 if(isset($zipFile) && !empty($zipFile)) {
137 if(is_file($zipFile)) {
138 unzip( $zipFile, $unzip_dir );
140 echo $mod_strings['ERR_LANG_MISSING_FILE'].$zipFile;
141 die(); // no point going any further
145 // filter for special to/from dir conditions (langpacks generally don't have them)
146 if(isset($manifest) && !empty($manifest)) {
147 if(is_file($manifest)) {
149 if( isset( $manifest['copy_files']['from_dir'] ) && $manifest['copy_files']['from_dir'] != "" ){
150 $zip_from_dir = $manifest['copy_files']['from_dir'];
152 if( isset( $manifest['copy_files']['to_dir'] ) && $manifest['copy_files']['to_dir'] != "" ){
153 $zip_to_dir = $manifest['copy_files']['to_dir'];
155 if( isset( $manifest['copy_files']['force_copy'] ) && $manifest['copy_files']['force_copy'] != "" ){
156 $zip_force_copy = $manifest['copy_files']['force_copy'];
158 if( isset( $manifest['version'] ) ){
159 $version = $manifest['version'];
162 $errors[] = $mod_strings['ERR_LANG_MISSING_FILE'].$manifest;
167 // find name of language pack: find single file in include/language/xx_xx.lang.php
168 $d = dir( "$unzip_dir/$zip_from_dir/include/language" );
169 while( $f = $d->read() ){
170 if( $f == "." || $f == ".." ){
173 else if( preg_match("/(.*)\.lang\.php\$/", $f, $match) ){
174 $new_lang_name = $match[1];
177 if( $new_lang_name == "" ){
178 die( $mod_strings['ERR_LANG_NO_LANG_FILE'].$zipFile );
180 $new_lang_desc = getLanguagePackName( "$unzip_dir/$zip_from_dir/include/language/$new_lang_name.lang.php" );
181 if( $new_lang_desc == "" ){
182 die( "No language pack description found at include/language/$new_lang_name.lang.php inside $install_file." );
184 // add language to available languages
185 $sugar_config['languages'][$new_lang_name] = ($new_lang_desc);
187 // get an array of all files to be moved
188 $filesFrom = array();
189 $filesFrom = findAllFiles($unzip_dir, $filesFrom);
193 ///////////////////////////////////////////////////////////////////////////
196 // unlink all pack files
197 foreach($filesFrom as $fileFrom) {
198 //echo "deleting: ".getcwd().substr($fileFrom, strlen($unzip_dir), strlen($fileFrom))."<br>";
199 @unlink(getcwd().substr($fileFrom, strlen($unzip_dir), strlen($fileFrom)));
202 // remove session entry
203 if(isset($_SESSION['INSTALLED_LANG_PACKS']) && is_array($_SESSION['INSTALLED_LANG_PACKS'])) {
204 foreach($_SESSION['INSTALLED_LANG_PACKS'] as $k => $langPack) {
205 if($langPack == $zipFile) {
206 unset($_SESSION['INSTALLED_LANG_PACKS'][$k]);
207 unset($_SESSION['INSTALLED_LANG_PACKS_VERSION'][$k]);
208 unset($_SESSION['INSTALLED_LANG_PACKS_MANIFEST'][$k]);
213 // remove language from config
214 $new_langs = array();
215 $old_langs = $sugar_config['languages'];
216 foreach( $old_langs as $key => $value ){
217 if( $key != $removedLang ){
218 $new_langs += array( $key => $value );
221 $sugar_config['languages'] = $new_langs;
224 // copy filesFrom to filesTo
225 foreach($filesFrom as $fileFrom) {
226 @copy($fileFrom, getcwd().substr($fileFrom, strlen($unzip_dir), strlen($fileFrom)));
229 $_SESSION['INSTALLED_LANG_PACKS'][$new_lang_name] = $zipFile;
230 $_SESSION['INSTALLED_LANG_PACKS_VERSION'][$new_lang_name] = $version;
231 $serial_manifest = array();
232 $serial_manifest['manifest'] = (isset($manifest) ? $manifest : '');
233 $serial_manifest['installdefs'] = (isset($installdefs) ? $installdefs : '');
234 $serial_manifest['upgrade_manifest'] = (isset($upgrade_manifest) ? $upgrade_manifest : '');
235 $_SESSION['INSTALLED_LANG_PACKS_MANIFEST'][$new_lang_name] = base64_encode(serialize($serial_manifest));
238 writeSugarConfig($sugar_config);
240 return $sugar_config;
243 function commitPatch($unlink = false, $type = 'patch'){
244 require_once('ModuleInstall/ModuleInstaller.php');
245 require_once('include/entryPoint.php');
249 global $base_upgrade_dir;
250 global $base_tmp_upgrade_dir;
252 $GLOBALS['db'] = $db;
255 global $current_user;
256 $current_user = new User();
257 $current_user->is_admin = '1';
258 $old_mod_strings = $mod_strings;
259 if(is_dir($base_upgrade_dir)) {
260 $files = findAllFiles("$base_upgrade_dir/$type", $files);
261 $mi = new ModuleInstaller();
263 $mod_strings = return_module_language('en', "Administration");
265 foreach($files as $file) {
266 if(!preg_match('#.*\.zip\$#', $file)) {
269 // handle manifest.php
270 $target_manifest = remove_file_extension( $file ) . '-manifest.php';
272 include($target_manifest);
274 $unzip_dir = mk_temp_dir( $base_tmp_upgrade_dir );
275 unzip($file, $unzip_dir );
276 if(file_exists("$unzip_dir/scripts/pre_install.php")){
277 require_once("$unzip_dir/scripts/pre_install.php");
280 if( isset( $manifest['copy_files']['from_dir'] ) && $manifest['copy_files']['from_dir'] != "" ){
281 $zip_from_dir = $manifest['copy_files']['from_dir'];
283 $source = "$unzip_dir/$zip_from_dir";
285 copy_recursive($source, $dest);
287 if(file_exists("$unzip_dir/scripts/post_install.php")){
288 require_once("$unzip_dir/scripts/post_install.php");
291 $new_upgrade = new UpgradeHistory();
292 $new_upgrade->filename = $file;
293 $new_upgrade->md5sum = md5_file($file);
294 $new_upgrade->type = $manifest['type'];
295 $new_upgrade->version = $manifest['version'];
296 $new_upgrade->status = "installed";
297 //$new_upgrade->author = $manifest['author'];
298 $new_upgrade->name = $manifest['name'];
299 $new_upgrade->description = $manifest['description'];
300 $serial_manifest = array();
301 $serial_manifest['manifest'] = (isset($manifest) ? $manifest : '');
302 $serial_manifest['installdefs'] = (isset($installdefs) ? $installdefs : '');
303 $serial_manifest['upgrade_manifest'] = (isset($upgrade_manifest) ? $upgrade_manifest : '');
304 $new_upgrade->manifest = base64_encode(serialize($serial_manifest));
305 $new_upgrade->save();
309 $mod_strings = $old_mod_strings;
312 function commitModules($unlink = false, $type = 'module'){
313 require_once('ModuleInstall/ModuleInstaller.php');
314 require_once('include/entryPoint.php');
318 global $base_upgrade_dir;
319 global $base_tmp_upgrade_dir;
321 $GLOBALS['db'] = $db;
324 global $current_user;
325 $current_user = new User();
326 $current_user->is_admin = '1';
327 $old_mod_strings = $mod_strings;
328 if(is_dir(sugar_cached("upload/upgrades"))) {
329 $files = findAllFiles(sugar_cached("upload/upgrades/$type"), $files);
330 $mi = new ModuleInstaller();
332 $mod_strings = return_module_language('en', "Administration");
334 foreach($files as $file) {
335 if(!preg_match('#.*\.zip\$', $file)) {
338 $lic_name = 'accept_lic_'.str_replace('.', '_', urlencode(basename($file)));
341 if(isset($_REQUEST[$lic_name])){
342 if($_REQUEST[$lic_name] == 'yes'){
345 $can_install = false;
349 // handle manifest.php
350 $target_manifest = remove_file_extension( $file ) . '-manifest.php';
351 if($type == 'langpack'){
352 $_REQUEST['manifest'] = $target_manifest;
353 $_REQUEST['zipFile'] = $file;
354 commitLanguagePack();
357 include($target_manifest);
359 $unzip_dir = mk_temp_dir( $base_tmp_upgrade_dir );
360 unzip($file, $unzip_dir );
361 $_REQUEST['install_file'] = $file;
362 $mi->install($unzip_dir);
363 $new_upgrade = new UpgradeHistory();
364 $new_upgrade->filename = $file;
365 $new_upgrade->md5sum = md5_file($file);
366 $new_upgrade->type = $manifest['type'];
367 $new_upgrade->version = $manifest['version'];
368 $new_upgrade->status = "installed";
369 // $new_upgrade->author = $manifest['author'];
370 $new_upgrade->name = $manifest['name'];
371 $new_upgrade->description = $manifest['description'];
372 $new_upgrade->id_name = (isset($installdefs['id_name'])) ? $installdefs['id_name'] : '';
373 $serial_manifest = array();
374 $serial_manifest['manifest'] = (isset($manifest) ? $manifest : '');
375 $serial_manifest['installdefs'] = (isset($installdefs) ? $installdefs : '');
376 $serial_manifest['upgrade_manifest'] = (isset($upgrade_manifest) ? $upgrade_manifest : '');
377 $new_upgrade->manifest = base64_encode(serialize($serial_manifest));
378 $new_upgrade->save();
383 $mod_strings = $old_mod_strings;
387 * creates UpgradeHistory entries
388 * @param mode string Install or Uninstall
390 function updateUpgradeHistory() {
391 if(isset($_SESSION['INSTALLED_LANG_PACKS']) && count($_SESSION['INSTALLED_LANG_PACKS']) > 0) {
392 foreach($_SESSION['INSTALLED_LANG_PACKS'] as $k => $zipFile) {
393 $new_upgrade = new UpgradeHistory();
394 $new_upgrade->filename = $zipFile;
395 $new_upgrade->md5sum = md5_file($zipFile);
396 $new_upgrade->type = 'langpack';
397 $new_upgrade->version = $_SESSION['INSTALLED_LANG_PACKS_VERSION'][$k];
398 $new_upgrade->status = "installed";
399 $new_upgrade->manifest = $_SESSION['INSTALLED_LANG_PACKS_MANIFEST'][$k];
400 $new_upgrade->save();
407 * removes the installed language pack, but the zip is still in the cache dir
409 function removeLanguagePack() {
411 global $sugar_config;
414 $manifest = urldecode($_REQUEST['manifest']);
415 $zipFile = urldecode($_REQUEST['zipFile']);
417 if(isset($manifest) && !empty($manifest)) {
418 if(is_file($manifest)) {
419 if(!unlink($manifest)) {
420 $errors[] = $mod_strings['ERR_LANG_CANNOT_DELETE_FILE'].$manifest;
423 $errors[] = $mod_strings['ERR_LANG_MISSING_FILE'].$manifest;
425 unset($_SESSION['packages_to_install'][$manifest]);
427 if(isset($zipFile) && !empty($zipFile)) {
428 if(is_file($zipFile)) {
429 if(!unlink($zipFile)) {
430 $errors[] = $mod_strings['ERR_LANG_CANNOT_DELETE_FILE'].$zipFile;
433 $errors[] = $mod_strings['ERR_LANG_MISSING_FILE'].$zipFile;
436 if(count($errors > 0)) {
437 echo "<p class='error'>";
438 foreach($errors as $error) {
444 unlinkTempFiles($manifest, $zipFile);
450 * takes the current value of $sugar_config and writes it out to config.php (sorta the same as the final step)
451 * @param array sugar_config
453 function writeSugarConfig($sugar_config) {
454 ksort($sugar_config);
455 $sugar_config_string = "<?php\n" .
456 '// created: ' . date('Y-m-d H:i:s') . "\n" .
458 var_export($sugar_config, true) .
460 if(is_writable('config.php')) {
461 write_array_to_file( "sugar_config", $sugar_config, "config.php");
467 * uninstalls the Language pack
469 function uninstallLangPack() {
470 global $sugar_config;
472 // remove language from config
473 $new_langs = array();
474 $old_langs = $sugar_config['languages'];
475 foreach( $old_langs as $key => $value ){
476 if( $key != $_REQUEST['new_lang_name'] ){
477 $new_langs += array( $key => $value );
480 $sugar_config['languages'] = $new_langs;
482 writeSugarConfig($sugar_config);
486 * retrieves the name of the language
488 if ( !function_exists('getLanguagePackName') ) {
489 function getLanguagePackName($the_file) {
490 require_once( "$the_file" );
491 if( isset( $app_list_strings["language_pack_name"] ) ){
492 return( $app_list_strings["language_pack_name"] );
498 function getInstalledLangPacks($showButtons=true) {
502 $ret = "<tr><td colspan=7 align=left>{$mod_strings['LBL_LANG_PACK_INSTALLED']}</td></tr>";
503 //$ret .="<table width='100%' cellpadding='0' cellspacing='0' border='0'>";
505 <td width='15%' ><b>{$mod_strings['LBL_ML_NAME']}</b></td>
506 <td width='15%' ><b>{$mod_strings['LBL_ML_VERSION']}</b></td>
507 <td width='15%' ><b>{$mod_strings['LBL_ML_PUBLISHED']}</b></td>
508 <td width='15%' ><b>{$mod_strings['LBL_ML_UNINSTALLABLE']}</b></td>
509 <td width='15%' ><b>{$mod_strings['LBL_ML_DESCRIPTION']}</b></td>
510 <td width='15%' ></td>
511 <td width='15%' ></td>
514 $files = findAllFiles(sugar_cached("upload/upgrades"), $files);
516 if(isset($_SESSION['INSTALLED_LANG_PACKS']) && !empty($_SESSION['INSTALLED_LANG_PACKS'])){
517 if(count($_SESSION['INSTALLED_LANG_PACKS'] > 0)) {
518 foreach($_SESSION['INSTALLED_LANG_PACKS'] as $file) {
519 // handle manifest.php
520 $target_manifest = remove_file_extension( $file ) . '-manifest.php';
521 include($target_manifest);
523 $name = empty($manifest['name']) ? $file : $manifest['name'];
524 $version = empty($manifest['version']) ? '' : $manifest['version'];
525 $published_date = empty($manifest['published_date']) ? '' : $manifest['published_date'];
527 $description = empty($manifest['description']) ? 'None' : $manifest['description'];
528 $uninstallable = empty($manifest['is_uninstallable']) ? 'No' : 'Yes';
529 $manifest_type = $manifest['type'];
531 $deletePackage = getPackButton('uninstall', $target_manifest, $file, $next_step, $uninstallable, $showButtons);
532 //$ret .="<table width='100%' cellpadding='0' cellspacing='0' border='0'>";
534 $ret .= "<td width='15%' >".$name."</td>";
535 $ret .= "<td width='15%' >".$version."</td>";
536 $ret .= "<td width='15%' >".$published_date."</td>";
537 $ret .= "<td width='15%' >".$uninstallable."</td>";
538 $ret .= "<td width='15%' >".$description."</td>";
539 $ret .= "<td width='15%' ></td>";
540 $ret .= "<td width='15%' >{$deletePackage}</td>";
544 $ret .= "</tr><td colspan=7><i>{$mod_strings['LBL_LANG_NO_PACKS']}</i></td></tr>";
547 $ret .= "</tr><td colspan=7><i>{$mod_strings['LBL_LANG_NO_PACKS']}</i></td></tr>";
553 function uninstallLanguagePack() {
554 return commitLanguagePack(true);
558 function getSugarConfigLanguageArray($langZip) {
559 global $sugar_config;
561 include(remove_file_extension($langZip)."-manifest.php");
563 if(isset($installdefs['id']) && isset($manifest['name'])) {
564 $ret = $installdefs['id']."::".$manifest['name']."::".$manifest['version'];
572 ///////////////////////////////////////////////////////////////////////////////
573 //// FROM performSetup.php
575 function getInstallDbInstance()
577 return DBManagerFactory::getTypeInstance($_SESSION['setup_db_type'], array("db_manager" => $_SESSION['setup_db_manager']));
580 function getDbConnection()
583 "db_host_name" => $_SESSION['setup_db_host_name'],
584 "db_user_name" => $_SESSION['setup_db_admin_user_name'],
585 "db_password" => $_SESSION['setup_db_admin_password'],
586 "db_host_instance" => $_SESSION['setup_db_host_instance'],
587 "db_port" => $_SESSION['setup_db_port_num'],
589 if(empty($_SESSION['setup_db_create_database'])) {
590 $dbconfig["db_name"] = $_SESSION['setup_db_database_name'];
593 $db = getInstallDbInstance();
594 if(!empty($_SESSION['setup_db_options'])) {
595 $db->setOptions($_SESSION['setup_db_options']);
597 $db->connect($dbconfig, true);
602 * creates the Sugar DB user (if not admin)
604 function handleDbCreateSugarUser() {
606 global $setup_db_database_name;
607 global $setup_db_host_name;
608 global $setup_db_host_instance;
609 global $setup_db_port_num;
610 global $setup_db_admin_user_name;
611 global $setup_db_admin_password;
612 global $sugar_config;
613 global $setup_db_sugarsales_user;
614 global $setup_site_host_name;
615 global $setup_db_sugarsales_password;
617 echo $mod_strings['LBL_PERFORM_CREATE_DB_USER'];
619 $db = getDbConnection();
620 $db->createDbUser($setup_db_database_name, $setup_site_host_name, $setup_db_sugarsales_user, $setup_db_sugarsales_password);
621 $err = $db->lastError();
623 echo $mod_strings['LBL_PERFORM_DONE'];
625 echo "<div style='color:red;'>";
626 echo "An error occured when creating user:<br>";
629 installLog("An error occured when creating user: $err");
634 * ensures that the charset and collation for a given database is set
637 function handleDbCharsetCollation() {
639 global $setup_db_database_name;
640 global $setup_db_host_name;
641 global $setup_db_admin_user_name;
642 global $setup_db_admin_password;
643 global $sugar_config;
645 if($_SESSION['setup_db_type'] == 'mysql') {
646 $db = getDbConnection();
647 $db->query("ALTER DATABASE `{$setup_db_database_name}` DEFAULT CHARACTER SET utf8", true);
648 $db->query("ALTER DATABASE `{$setup_db_database_name}` DEFAULT COLLATE utf8_general_ci", true);
654 * creates the new database
656 function handleDbCreateDatabase() {
658 global $setup_db_database_name;
659 global $setup_db_host_name;
660 global $setup_db_host_instance;
661 global $setup_db_port_num;
662 global $setup_db_admin_user_name;
663 global $setup_db_admin_password;
664 global $sugar_config;
666 echo "{$mod_strings['LBL_PERFORM_CREATE_DB_1']} {$setup_db_database_name} {$mod_strings['LBL_PERFORM_CREATE_DB_2']} {$setup_db_host_name}...";
667 $db = getDbConnection();
668 if($db->dbExists($setup_db_database_name)) {
669 $db->dropDatabase($setup_db_database_name);
671 $db->createDatabase($setup_db_database_name);
673 echo $mod_strings['LBL_PERFORM_DONE'];
678 * handles creation of Log4PHP properties file
679 * This function has been deprecated. Use SugarLogger.
681 function handleLog4Php() {
685 function installLog($entry) {
688 '.gmdate("Y-m-d H:i:s").'...';
689 $log = clean_path(getcwd().'/install.log');
691 // create if not exists
692 if(!file_exists($log)) {
693 $fp = @sugar_fopen($log, 'w+'); // attempts to create file
694 if(!is_resource($fp)) {
695 $GLOBALS['log']->fatal('could not create the install.log file');
698 $fp = @sugar_fopen($log, 'a+'); // write pointer at end of file
699 if(!is_resource($fp)) {
700 $GLOBALS['log']->fatal('could not open/lock install.log file');
706 if(@fwrite($fp, $nl.$entry) === false) {
707 $GLOBALS['log']->fatal('could not write to install.log: '.$entry);
710 if(is_resource($fp)) {
718 * takes session vars and creates config.php
719 * @return array bottle collection of error messages
721 function handleSugarConfig() {
725 global $setup_db_host_name;
726 global $setup_db_host_instance;
727 global $setup_db_port_num;
728 global $setup_db_sugarsales_user;
729 global $setup_db_sugarsales_password;
730 global $setup_db_database_name;
731 global $setup_site_host_name;
732 global $setup_site_log_dir;
733 global $setup_site_log_file;
734 global $setup_site_session_path;
735 global $setup_site_guid;
736 global $setup_site_url;
737 global $setup_sugar_version;
738 global $sugar_config;
739 global $setup_site_log_level;
741 echo "<b>{$mod_strings['LBL_PERFORM_CONFIG_PHP']} (config.php)</b><br>";
742 ///////////////////////////////////////////////////////////////////////////////
743 //// $sugar_config SETTINGS
744 if( is_file('config.php') ){
745 $is_writable = is_writable('config.php');
746 // require is needed here (config.php is sometimes require'd from install.php)
747 require('config.php');
749 $is_writable = is_writable('.');
752 // build default sugar_config and merge with new values
753 $sugar_config = sugarArrayMerge(get_sugar_config_defaults(), $sugar_config);
754 // always lock the installer
755 $sugar_config['installer_locked'] = true;
756 // we're setting these since the user was given a fair chance to change them
757 $sugar_config['dbconfig']['db_host_name'] = $setup_db_host_name;
758 if(!empty($setup_db_host_instance)) {
759 $sugar_config['dbconfig']['db_host_instance'] = $setup_db_host_instance;
761 $sugar_config['dbconfig']['db_host_instance'] = '';
763 if(!isset($_SESSION['setup_db_manager'])) {
764 $_SESSION['setup_db_manager'] = DBManagerFactory::getManagerByType($_SESSION['setup_db_type']);
766 $sugar_config['dbconfig']['db_user_name'] = $setup_db_sugarsales_user;
767 $sugar_config['dbconfig']['db_password'] = $setup_db_sugarsales_password;
768 $sugar_config['dbconfig']['db_name'] = $setup_db_database_name;
769 $sugar_config['dbconfig']['db_type'] = $_SESSION['setup_db_type'];
770 $sugar_config['dbconfig']['db_port'] = $setup_db_port_num;
771 $sugar_config['dbconfig']['db_manager'] = $_SESSION['setup_db_manager'];
772 if(!empty($_SESSION['setup_db_options'])) {
773 $sugar_config['dbconfigoption'] = array_merge($sugar_config['dbconfigoption'], $_SESSION['setup_db_options']);
776 $sugar_config['cache_dir'] = $cache_dir;
777 $sugar_config['default_charset'] = $mod_strings['DEFAULT_CHARSET'];
778 $sugar_config['default_email_client'] = 'sugar';
779 $sugar_config['default_email_editor'] = 'html';
780 $sugar_config['host_name'] = $setup_site_host_name;
781 $sugar_config['js_custom_version'] = '';
782 $sugar_config['use_real_names'] = true;
783 $sugar_config['log_dir'] = $setup_site_log_dir;
784 $sugar_config['log_file'] = $setup_site_log_file;
786 /*nsingh(bug 22402): Consolidate logger settings under $config['logger'] as liked by the new logger! If log4pphp exists,
787 these settings will be overwritten by those in log4php.properties when the user access admin->system settings.*/
788 $sugar_config['logger'] =
789 array ('level'=>$setup_site_log_level,
792 'name' => 'sugarcrm',
793 'dateFormat' => '%c',
796 'suffix' => ''), // bug51583, change default suffix to blank for backwards comptability
798 $sugar_config['session_dir'] = $setup_site_session_path;
799 $sugar_config['site_url'] = $setup_site_url;
800 $sugar_config['sugar_version'] = $setup_sugar_version;
801 $sugar_config['tmp_dir'] = $cache_dir.'xml/';
802 $sugar_config['upload_dir'] = 'upload/';
803 // $sugar_config['use_php_code_json'] = returnPhpJsonStatus(); // true on error
804 if( isset($_SESSION['setup_site_sugarbeet_anonymous_stats']) ){
805 $sugar_config['sugarbeet'] = $_SESSION['setup_site_sugarbeet_anonymous_stats'];
807 $sugar_config['demoData'] = $_SESSION['demoData'];
808 if( isset( $setup_site_guid ) ){
809 $sugar_config['unique_key'] = $setup_site_guid;
811 if(empty($sugar_config['unique_key'])){
812 $sugar_config['unique_key'] = md5( create_guid() );
814 // add installed langs to config
815 // entry in upgrade_history comes AFTER table creation
816 if(isset($_SESSION['INSTALLED_LANG_PACKS']) && is_array($_SESSION['INSTALLED_LANG_PACKS']) && !empty($_SESSION['INSTALLED_LANG_PACKS'])) {
817 foreach($_SESSION['INSTALLED_LANG_PACKS'] as $langZip) {
818 $lang = getSugarConfigLanguageArray($langZip);
820 $exLang = explode('::', $lang);
821 if(is_array($exLang) && count($exLang) == 3) {
822 $sugar_config['languages'][$exLang[0]] = $exLang[1];
827 if(file_exists('install/lang.config.php')){
828 include('install/lang.config.php');
829 if(!empty($config['languages'])){
830 foreach($config['languages'] as $lang=>$label){
831 $sugar_config['languages'][$lang] = $label;
836 ksort($sugar_config);
837 $sugar_config_string = "<?php\n" .
838 '// created: ' . date('Y-m-d H:i:s') . "\n" .
840 var_export($sugar_config, true) .
842 if($is_writable && write_array_to_file( "sugar_config", $sugar_config, "config.php")) {
846 echo "<p>{$mod_strings['ERR_PERFORM_CONFIG_PHP_1']}</p>\n";
847 echo "<p>{$mod_strings['ERR_PERFORM_CONFIG_PHP_2']}</p>\n";
848 echo "<TEXTAREA rows=\"15\" cols=\"80\">".$sugar_config_string."</TEXTAREA>";
849 echo "<p>{$mod_strings['ERR_PERFORM_CONFIG_PHP_3']}</p>";
851 $bottle[] = $mod_strings['ERR_PERFORM_CONFIG_PHP_4'];
855 //Now merge the config_si.php settings into config.php
856 if(file_exists('config.php') && file_exists('config_si.php'))
858 require_once('modules/UpgradeWizard/uw_utils.php');
859 merge_config_si_settings(false, 'config.php', 'config_si.php');
863 //// END $sugar_config
864 ///////////////////////////////////////////////////////////////////////////////
868 * (re)write the .htaccess file to prevent browser access to the log file
870 function handleHtaccess(){
872 $ignoreCase = (substr_count(strtolower($_SERVER['SERVER_SOFTWARE']), 'apache/2') > 0)?'(?i)':'';
873 $htaccess_file = ".htaccess";
875 $restrict_str = <<<EOQ
877 # BEGIN SUGARCRM RESTRICTIONS
878 RedirectMatch 403 {$ignoreCase}.*\.log$
879 RedirectMatch 403 {$ignoreCase}/+not_imported_.*\.txt
880 RedirectMatch 403 {$ignoreCase}/+(soap|cache|xtemplate|data|examples|include|log4php|metadata|modules)/+.*\.(php|tpl)
881 RedirectMatch 403 {$ignoreCase}/+emailmandelivery\.php
882 RedirectMatch 403 {$ignoreCase}/+upload
883 RedirectMatch 403 {$ignoreCase}/+custom/+blowfish
884 RedirectMatch 403 {$ignoreCase}/+cache/+diagnostic
885 RedirectMatch 403 {$ignoreCase}/+files\.md5$
886 # END SUGARCRM RESTRICTIONS
888 if(file_exists($htaccess_file)){
889 $fp = fopen($htaccess_file, 'r');
891 while($line = fgets($fp)){
893 if(preg_match("/\s*#\s*BEGIN\s*SUGARCRM\s*RESTRICTIONS/i", $line))$skip = true;
894 if(!$skip)$contents .= $line;
895 if(preg_match("/\s*#\s*END\s*SUGARCRM\s*RESTRICTIONS/i", $line))$skip = false;
898 $status = file_put_contents($htaccess_file, $contents . $restrict_str);
900 echo "<p>{$mod_strings['ERR_PERFORM_HTACCESS_1']}<span class=stop>{$htaccess_file}</span> {$mod_strings['ERR_PERFORM_HTACCESS_2']}</p>\n";
901 echo "<p>{$mod_strings['ERR_PERFORM_HTACCESS_3']}</p>\n";
908 * (re)write the web.config file to prevent browser access to the log file
910 function handleWebConfig()
912 if ( !isset($_SERVER['IIS_UrlRewriteModule']) ) {
916 global $setup_site_log_dir;
917 global $setup_site_log_file;
918 global $sugar_config;
920 // Bug 36968 - Fallback to using $sugar_config values when we are not calling this from the installer
921 if (empty($setup_site_log_file)) {
922 $setup_site_log_file = $sugar_config['log_file'];
923 if ( empty($sugar_config['log_file']) ) {
924 $setup_site_log_file = 'sugarcrm.log';
927 if (empty($setup_site_log_dir)) {
928 $setup_site_log_dir = $sugar_config['log_dir'];
929 if ( empty($sugar_config['log_dir']) ) {
930 $setup_site_log_dir = '.';
934 $prefix = $setup_site_log_dir.empty($setup_site_log_dir)?'':'/';
937 $config_array = array(
938 array('1'=> $prefix.str_replace('.','\\.',$setup_site_log_file).'\\.*' ,'2'=>'log_file_restricted.html'),
939 array('1'=> $prefix.'install.log' ,'2'=>'log_file_restricted.html'),
940 array('1'=> $prefix.'upgradeWizard.log' ,'2'=>'log_file_restricted.html'),
941 array('1'=> $prefix.'emailman.log' ,'2'=>'log_file_restricted.html'),
942 array('1'=>'not_imported_.*.txt' ,'2'=>'log_file_restricted.html'),
943 array('1'=>'XTemplate/(.*)/(.*).php' ,'2'=>'index.php'),
944 array('1'=>'data/(.*).php' ,'2'=>'index.php'),
945 array('1'=>'examples/(.*).php' ,'2'=>'index.php'),
946 array('1'=>'include/(.*).php' ,'2'=>'index.php'),
947 array('1'=>'include/(.*)/(.*).php' ,'2'=>'index.php'),
948 array('1'=>'log4php/(.*).php' ,'2'=>'index.php'),
949 array('1'=>'log4php/(.*)/(.*)' ,'2'=>'index.php'),
950 array('1'=>'metadata/(.*)/(.*).php' ,'2'=>'index.php'),
951 array('1'=>'modules/(.*)/(.*).php' ,'2'=>'index.php'),
952 array('1'=>'soap/(.*).php' ,'2'=>'index.php'),
953 array('1'=>'emailmandelivery.php' ,'2'=>'index.php'),
954 array('1'=>'cron.php' ,'2'=>'index.php'),
955 array('1'=> $sugar_config['upload_dir'].'.*' ,'2'=>'index.php'),
959 $xmldoc = new XMLWriter();
960 $xmldoc->openURI('web.config');
961 $xmldoc->setIndent(true);
962 $xmldoc->setIndentString(' ');
963 $xmldoc->startDocument('1.0','UTF-8');
964 $xmldoc->startElement('configuration');
965 $xmldoc->startElement('system.webServer');
966 $xmldoc->startElement('rewrite');
967 $xmldoc->startElement('rules');
968 for ($i = 0; $i < count($config_array); $i++) {
969 $xmldoc->startElement('rule');
970 $xmldoc->writeAttribute('name', "redirect$i");
971 $xmldoc->writeAttribute('stopProcessing', 'true');
972 $xmldoc->startElement('match');
973 $xmldoc->writeAttribute('url', $config_array[$i]['1']);
974 $xmldoc->endElement();
975 $xmldoc->startElement('action');
976 $xmldoc->writeAttribute('type', 'Redirect');
977 $xmldoc->writeAttribute('url', $config_array[$i]['2']);
978 $xmldoc->writeAttribute('redirectType', 'Found');
979 $xmldoc->endElement();
980 $xmldoc->endElement();
982 $xmldoc->endElement();
983 $xmldoc->endElement();
984 $xmldoc->endElement();
985 $xmldoc->endElement();
986 $xmldoc->endDocument();
991 * Drop old tables if table exists and told to drop it
993 function drop_table_install( &$focus ){
997 $result = $db->tableExists($focus->table_name);
1000 $focus->drop_tables();
1001 $GLOBALS['log']->info("Dropped old ".$focus->table_name." table.");
1005 $GLOBALS['log']->info("Did not need to drop old ".$focus->table_name." table. It doesn't exist.");
1010 // Creating new tables if they don't exist.
1011 function create_table_if_not_exist( &$focus ){
1013 $table_created = false;
1015 // normal code follows
1016 $result = $db->tableExists($focus->table_name);
1018 $GLOBALS['log']->info("Table ".$focus->table_name." already exists.");
1020 $focus->create_tables();
1021 $GLOBALS['log']->info("Created ".$focus->table_name." table.");
1022 $table_created = true;
1024 return $table_created;
1029 function create_default_users(){
1031 global $setup_site_admin_password;
1032 global $setup_site_admin_user_name;
1033 global $create_default_user;
1034 global $sugar_config;
1035 global $current_user;
1036 require_once('install/UserDemoData.php');
1038 //Create default admin user
1039 $current_user = new User();
1040 $current_user->id = 1;
1041 $current_user->new_with_id = true;
1042 $current_user->last_name = 'Administrator';
1043 //$user->user_name = 'admin';
1044 $current_user->user_name = $setup_site_admin_user_name;
1045 $current_user->title = "Administrator";
1046 $current_user->status = 'Active';
1047 $current_user->is_admin = true;
1048 $current_user->employee_status = 'Active';
1049 //$user->user_password = $user->encrypt_password($setup_site_admin_password);
1050 $current_user->user_hash = strtolower(md5($setup_site_admin_password));
1051 $current_user->email = '';
1052 $current_user->picture = UserDemoData::_copy_user_image($current_user->id);
1053 $current_user->save();
1055 // echo 'Creating RSS Feeds';
1056 //$feed = new Feed();
1057 //$feed->createRSSHomePage($user->id);
1060 // We need to change the admin user to a fixed id of 1.
1061 // $query = "update users set id='1' where user_name='$user->user_name'";
1062 // $result = $db->query($query, true, "Error updating admin user ID: ");
1064 $GLOBALS['log']->info("Created ".$current_user->table_name." table. for user $current_user->id");
1066 if( $create_default_user ){
1067 $default_user = new User();
1068 $default_user->last_name = $sugar_config['default_user_name'];
1069 $default_user->user_name = $sugar_config['default_user_name'];
1070 $default_user->status = 'Active';
1071 if( isset($sugar_config['default_user_is_admin']) && $sugar_config['default_user_is_admin'] ){
1072 $default_user->is_admin = true;
1074 //$default_user->user_password = $default_user->encrypt_password($sugar_config['default_password']);
1075 $default_user->user_hash = strtolower(md5($sugar_config['default_password']));
1076 $default_user->save();
1077 //$feed->createRSSHomePage($user->id);
1081 function set_admin_password( $password ) {
1085 $encrypted_password = $user->encrypt_password($password);
1086 $user_hash = strtolower(md5($password));
1088 //$query = "update users set user_password='$encrypted_password', user_hash='$user_hash' where id='1'";
1089 $query = "update users set user_hash='$user_hash' where id='1'";
1094 function insert_default_settings(){
1096 global $setup_sugar_version;
1097 global $sugar_db_version;
1100 $db->query("INSERT INTO config (category, name, value) VALUES ('notify', 'fromaddress', 'do_not_reply@example.com')");
1101 $db->query("INSERT INTO config (category, name, value) VALUES ('notify', 'fromname', 'SugarCRM')");
1102 $db->query("INSERT INTO config (category, name, value) VALUES ('notify', 'send_by_default', '1')");
1103 $db->query("INSERT INTO config (category, name, value) VALUES ('notify', 'on', '1')");
1104 $db->query("INSERT INTO config (category, name, value) VALUES ('notify', 'send_from_assigning_user', '0')");
1105 /* cn: moved to OutboundEmail class
1106 $db->query("INSERT INTO config (category, name, value) VALUES ('mail', 'smtpserver', 'localhost')");
1107 $db->query("INSERT INTO config (category, name, value) VALUES ('mail', 'smtpport', '25')");
1108 $db->query("INSERT INTO config (category, name, value) VALUES ('mail', 'sendtype', 'smtp')");
1109 $db->query("INSERT INTO config (category, name, value) VALUES ('mail', 'smtpuser', '')");
1110 $db->query("INSERT INTO config (category, name, value) VALUES ('mail', 'smtppass', '')");
1111 $db->query("INSERT INTO config (category, name, value) VALUES ('mail', 'smtpauth_req', '0')");
1113 $db->query("INSERT INTO config (category, name, value) VALUES ('info', 'sugar_version', '" . $sugar_db_version . "')");
1114 $db->query("INSERT INTO config (category, name, value) VALUES ('MySettings', 'tab', '')");
1115 $db->query("INSERT INTO config (category, name, value) VALUES ('portal', 'on', '0')");
1119 //insert default tracker settings
1120 $db->query("INSERT INTO config (category, name, value) VALUES ('tracker', 'Tracker', '1')");
1124 $db->query( "INSERT INTO config (category, name, value) VALUES ( 'system', 'skypeout_on', '1')" );
1135 // Returns true if the given file/dir has been made writable (or is already
1137 function make_writable($file)
1141 if(is_file($file) || is_dir($file))
1143 if(is_writable($file))
1149 $original_fileperms = fileperms($file);
1151 // add user writable permission
1152 $new_fileperms = $original_fileperms | 0x0080;
1153 @sugar_chmod($file, $new_fileperms);
1155 if(is_writable($file))
1161 // add group writable permission
1162 $new_fileperms = $original_fileperms | 0x0010;
1163 @chmod($file, $new_fileperms);
1165 if(is_writable($file))
1171 // add world writable permission
1172 $new_fileperms = $original_fileperms | 0x0002;
1173 @chmod($file, $new_fileperms);
1175 if(is_writable($file))
1187 function recursive_make_writable($start_file)
1189 $ret_val = make_writable($start_file);
1191 if($ret_val && is_dir($start_file))
1193 // PHP 4 alternative to scandir()
1195 $dh = opendir($start_file);
1196 $filename = readdir($dh);
1197 while(!empty($filename))
1199 if($filename != '.' && $filename != '..' && $filename != '.svn')
1201 $files[] = $filename;
1204 $filename = readdir($dh);
1207 foreach($files as $file)
1209 $ret_val = recursive_make_writable($start_file . '/' . $file);
1213 $_SESSION['unwriteable_module_files'][dirname($file)] = dirname($file);
1214 $fnl_ret_val = false;
1221 $unwriteable_directory = is_dir($start_file) ? $start_file : dirname($start_file);
1222 if($unwriteable_directory[0] == '.'){$unwriteable_directory = substr($unwriteable_directory,1);}
1223 $_SESSION['unwriteable_module_files'][$unwriteable_directory] = $unwriteable_directory;
1224 $_SESSION['unwriteable_module_files']['failed'] = true;
1230 function recursive_is_writable($start_file)
1232 $ret_val = is_writable($start_file);
1234 if($ret_val && is_dir($start_file))
1236 // PHP 4 alternative to scandir()
1238 $dh = opendir($start_file);
1239 $filename = readdir($dh);
1240 while(!empty($filename))
1242 if($filename != '.' && $filename != '..' && $filename != '.svn')
1244 $files[] = $filename;
1247 $filename = readdir($dh);
1250 foreach($files as $file)
1252 $ret_val = recursive_is_writable($start_file . '/' . $file);
1264 // one place for form validation/conversion to boolean
1265 function get_boolean_from_request( $field ){
1266 if( !isset($_REQUEST[$field]) ){
1270 if( ($_REQUEST[$field] == 'on') || ($_REQUEST[$field] == 'yes') ){
1278 function stripslashes_checkstrings($value){
1279 if(is_string($value)){
1280 return stripslashes($value);
1286 function print_debug_array( $name, $debug_array ){
1287 ksort( $debug_array );
1289 print( "$name vars:\n" );
1292 foreach( $debug_array as $key => $value ){
1293 if( stristr( $key, "password" ) ){
1296 print( " [$key] => $value\n" );
1302 function print_debug_comment(){
1303 if( !empty($_REQUEST['debug']) ){
1304 $_SESSION['debug'] = $_REQUEST['debug'];
1307 if( !empty($_SESSION['debug']) && ($_SESSION['debug'] == 'true') ){
1308 print( "<!-- debug is on (to turn off, hit any page with 'debug=false' as a URL parameter.\n" );
1310 print_debug_array( "Session", $_SESSION );
1311 print_debug_array( "Request", $_REQUEST );
1312 print_debug_array( "Post", $_POST );
1313 print_debug_array( "Get", $_GET );
1319 function validate_systemOptions() {
1320 global $mod_strings;
1322 $db = DBManagerFactory::getTypeInstance($_SESSION['setup_db_type']);
1324 $errors[] = "<span class='error'>".$mod_strings['ERR_DB_INVALID']."</span>";
1326 $_SESSION['setup_db_manager'] = get_class($db);
1332 function validate_dbConfig() {
1333 global $mod_strings;
1334 require_once('install/checkDBSettings.php');
1335 return checkDBSettings(true);
1339 function validate_siteConfig($type){
1340 global $mod_strings;
1344 if(empty($_SESSION['setup_system_name'])){
1345 $errors[] = "<span class='error'>".$mod_strings['LBL_REQUIRED_SYSTEM_NAME']."</span>";
1347 if($_SESSION['setup_site_url'] == ''){
1348 $errors[] = "<span class='error'>".$mod_strings['ERR_URL_BLANK']."</span>";
1351 if($_SESSION['setup_site_admin_user_name'] == '') {
1352 $errors[] = "<span class='error'>".$mod_strings['ERR_ADMIN_USER_NAME_BLANK']."</span>";
1355 if($_SESSION['setup_site_admin_password'] == ''){
1356 $errors[] = "<span class='error'>".$mod_strings['ERR_ADMIN_PASS_BLANK']."</span>";
1359 if($_SESSION['setup_site_admin_password'] != $_SESSION['setup_site_admin_password_retype']){
1360 $errors[] = "<span class='error'>".$mod_strings['ERR_PASSWORD_MISMATCH']."</span>";
1363 if(!empty($_SESSION['setup_site_custom_session_path']) && $_SESSION['setup_site_session_path'] == ''){
1364 $errors[] = "<span class='error'>".$mod_strings['ERR_SESSION_PATH']."</span>";
1367 if(!empty($_SESSION['setup_site_custom_session_path']) && $_SESSION['setup_site_session_path'] != ''){
1368 if(is_dir($_SESSION['setup_site_session_path'])){
1369 if(!is_writable($_SESSION['setup_site_session_path'])){
1370 $errors[] = "<span class='error'>".$mod_strings['ERR_SESSION_DIRECTORY']."</span>";
1374 $errors[] = "<span class='error'>".$mod_strings['ERR_SESSION_DIRECTORY_NOT_EXISTS']."</span>";
1378 if(!empty($_SESSION['setup_site_custom_log_dir']) && $_SESSION['setup_site_log_dir'] == ''){
1379 $errors[] = "<span class='error'>".$mod_strings['ERR_LOG_DIRECTORY_NOT_EXISTS']."</span>";
1382 if(!empty($_SESSION['setup_site_custom_log_dir']) && $_SESSION['setup_site_log_dir'] != ''){
1383 if(is_dir($_SESSION['setup_site_log_dir'])){
1384 if(!is_writable($_SESSION['setup_site_log_dir'])) {
1385 $errors[] = "<span class='error'>".$mod_strings['ERR_LOG_DIRECTORY_NOT_WRITABLE']."</span>";
1389 $errors[] = "<span class='error'>".$mod_strings['ERR_LOG_DIRECTORY_NOT_EXISTS']."</span>";
1393 if(!empty($_SESSION['setup_site_specify_guid']) && $_SESSION['setup_site_guid'] == ''){
1394 $errors[] = "<span class='error'>".$mod_strings['ERR_SITE_GUID']."</span>";
1402 function pullSilentInstallVarsIntoSession() {
1403 global $mod_strings;
1404 global $sugar_config;
1407 if( file_exists('config_si.php') ){
1408 require_once('config_si.php');
1410 else if( empty($sugar_config_si) ){
1411 die( $mod_strings['ERR_SI_NO_CONFIG'] );
1414 $config_subset = array (
1415 'setup_site_url' => isset($sugar_config['site_url']) ? $sugar_config['site_url'] : '',
1416 'setup_db_host_name' => isset($sugar_config['dbconfig']['db_host_name']) ? $sugar_config['dbconfig']['db_host_name'] : '',
1417 'setup_db_host_instance' => isset($sugar_config['dbconfig']['db_host_instance']) ? $sugar_config['dbconfig']['db_host_instance'] : '',
1418 'setup_db_sugarsales_user' => isset($sugar_config['dbconfig']['db_user_name']) ? $sugar_config['dbconfig']['db_user_name'] : '',
1419 'setup_db_sugarsales_password' => isset($sugar_config['dbconfig']['db_password']) ? $sugar_config['dbconfig']['db_password'] : '',
1420 'setup_db_database_name' => isset($sugar_config['dbconfig']['db_name']) ? $sugar_config['dbconfig']['db_name'] : '',
1421 'setup_db_type' => isset($sugar_config['dbconfig']['db_type']) ? $sugar_config['dbconfig']['db_type'] : '',
1422 'setup_db_port_num' => isset($sugar_config['dbconfig']['db_port']) ? $sugar_config['dbconfig']['db_port'] : '',
1423 'setup_db_options' => !empty($sugar_config['dbconfigoptions']) ? $sugar_config['dbconfigoptions'] : array(),
1425 // third array of values derived from above values
1427 'setup_site_admin_password_retype' => $sugar_config_si['setup_site_admin_password'],
1428 'setup_db_sugarsales_password_retype' => $config_subset['setup_db_sugarsales_password'],
1431 $needles = array('setup_db_create_database','setup_db_create_sugarsales_user','setup_license_key_users',
1432 'setup_license_key_expire_date','setup_license_key', 'setup_num_lic_oc',
1433 'default_currency_iso4217', 'default_currency_name', 'default_currency_significant_digits',
1434 'default_currency_symbol', 'default_date_format', 'default_time_format', 'default_decimal_seperator',
1435 'default_export_charset', 'default_language', 'default_locale_name_format', 'default_number_grouping_seperator',
1436 'export_delimiter', 'cache_dir', 'setup_db_options');
1437 copyFromArray($sugar_config_si, $needles, $derived);
1438 $all_config_vars = array_merge( $config_subset, $sugar_config_si, $derived );
1440 // bug 16860 tyoung - trim leading and trailing whitespace from license_key
1441 if (isset($all_config_vars['setup_license_key'])) {
1442 $all_config_vars['setup_license_key'] = trim($all_config_vars['setup_license_key']);
1445 foreach( $all_config_vars as $key => $value ){
1446 $_SESSION[$key] = $value;
1451 * given an array it will check to determine if the key exists in the array, if so
1452 * it will addd to the return array
1454 * @param intput_array haystack to check
1455 * @param needles list of needles to search for
1456 * @param output_array the array to add the keys to
1458 function copyFromArray($input_array, $needles, $output_array){
1459 foreach($needles as $needle){
1460 if(isset($input_array[$needle])){
1461 $output_array[$needle] = $input_array[$needle];
1469 * handles language pack uploads - code based off of upload_file->final_move()
1470 * puts it into the cache/upload dir to be handed off to langPackUnpack();
1472 * @param object file UploadFile object
1473 * @return bool true if successful
1475 function langPackFinalMove($file) {
1476 global $sugar_config;
1477 //."upgrades/langpack/"
1478 $destination = $sugar_config['upload_dir'].$file->stored_file_name;
1479 if(!move_uploaded_file($_FILES[$file->field_name]['tmp_name'], $destination)) {
1480 die ("ERROR: can't move_uploaded_file to $destination. You should try making the directory writable by the webserver");
1485 function getLicenseDisplay($type, $manifest, $zipFile, $next_step, $license_file, $clean_file) {
1486 return PackageManagerDisplay::getLicenseDisplay($license_file, 'install.php', $next_step, $zipFile, $type, $manifest, $clean_file);
1491 * creates the remove/delete form for langpack page
1492 * @param string type commit/remove
1493 * @param string manifest path to manifest file
1494 * @param string zipFile path to uploaded zip file
1495 * @param int nextstep current step
1496 * @return string ret <form> for this package
1498 function getPackButton($type, $manifest, $zipFile, $next_step, $uninstallable='Yes', $showButtons=true) {
1499 global $mod_strings;
1501 $button = $mod_strings['LBL_LANG_BUTTON_COMMIT'];
1502 if($type == 'remove') {
1503 $button = $mod_strings['LBL_LANG_BUTTON_REMOVE'];
1504 } elseif($type == 'uninstall') {
1505 $button = $mod_strings['LBL_LANG_BUTTON_UNINSTALL'];
1508 $disabled = ($uninstallable == 'Yes') ? false : true;
1510 $ret = "<form name='delete{$zipFile}' action='install.php' method='POST'>
1511 <input type='hidden' name='current_step' value='{$next_step}'>
1512 <input type='hidden' name='goto' value='{$mod_strings['LBL_CHECKSYS_RECHECK']}'>
1513 <input type='hidden' name='languagePackAction' value='{$type}'>
1514 <input type='hidden' name='manifest' value='".urlencode($manifest)."'>
1515 <input type='hidden' name='zipFile' value='".urlencode($zipFile)."'>
1516 <input type='hidden' name='install_type' value='custom'>";
1517 if(!$disabled && $showButtons) {
1518 $ret .= "<input type='submit' value='{$button}' class='button'>";
1525 * finds all installed languages and returns an array with the names
1526 * @return array langs array of installed languages
1528 function getInstalledLanguages() {
1529 $langDir = 'include/language/';
1530 $dh = opendir($langDir);
1533 while($file = readdir($dh)) {
1534 if(substr($file, -3) == 'php') {
1543 * searches upgrade dir for lang pack files.
1545 * @return string HTML of available lang packs
1547 function getLangPacks($display_commit = true, $types = array('langpack'), $notice_text = '') {
1548 global $mod_strings;
1550 global $base_upgrade_dir;
1552 if(empty($notice_text)){
1553 $notice_text = $mod_strings['LBL_LANG_PACK_READY'];
1555 $ret = "<tr><td colspan=7 align=left>{$notice_text}</td></tr>";
1556 //$ret .="<table width='100%' cellpadding='0' cellspacing='0' border='0'>";
1558 <td width='20%' ><b>{$mod_strings['LBL_ML_NAME']}</b></td>
1559 <td width='15%' ><b>{$mod_strings['LBL_ML_VERSION']}</b></td>
1560 <td width='15%' ><b>{$mod_strings['LBL_ML_PUBLISHED']}</b></td>
1561 <td width='15%' ><b>{$mod_strings['LBL_ML_UNINSTALLABLE']}</b></td>
1562 <td width='20%' ><b>{$mod_strings['LBL_ML_DESCRIPTION']}</b></td>
1563 <td width='7%' ></td>
1564 <td width='1%' ></td>
1565 <td width='7%' ></td>
1569 // duh, new installs won't have the upgrade folders
1570 if(!is_dir($base_upgrade_dir)) {
1571 mkdir_recursive( $base_upgrade_dir);
1573 $subdirs = array('full', 'langpack', 'module', 'patch', 'theme', 'temp');
1574 foreach( $subdirs as $subdir ){
1575 mkdir_recursive( "$base_upgrade_dir/$subdir" );
1578 $files = findAllFiles($base_upgrade_dir, $files);
1580 unset($_SESSION['hidden_input']);
1582 foreach($files as $file) {
1583 if(!preg_match("#.*\.zip\$#", $file)) {
1587 // skip installed lang packs
1588 if(isset($_SESSION['INSTALLED_LANG_PACKS']) && in_array($file, $_SESSION['INSTALLED_LANG_PACKS'])) {
1592 // handle manifest.php
1593 $target_manifest = remove_file_extension( $file ) . '-manifest.php';
1594 $license_file = remove_file_extension( $file ) . '-license.txt';
1595 include($target_manifest);
1598 if(!in_array(strtolower($manifest['type']), $types))
1602 $md5_matches = array();
1603 if($manifest['type'] == 'module'){
1604 $uh = new UpgradeHistory();
1605 $upgrade_content = clean_path($file);
1606 $the_base = basename($upgrade_content);
1607 $the_md5 = md5_file($upgrade_content);
1608 $md5_matches = $uh->findByMd5($the_md5);
1611 if($manifest['type']!= 'module' || 0 == sizeof($md5_matches)){
1612 $name = empty($manifest['name']) ? $file : $manifest['name'];
1613 $version = empty($manifest['version']) ? '' : $manifest['version'];
1614 $published_date = empty($manifest['published_date']) ? '' : $manifest['published_date'];
1616 $description = empty($manifest['description']) ? 'None' : $manifest['description'];
1617 $uninstallable = empty($manifest['is_uninstallable']) ? 'No' : 'Yes';
1618 $manifest_type = $manifest['type'];
1619 $commitPackage = getPackButton('commit', $target_manifest, $file, $next_step);
1620 $deletePackage = getPackButton('remove', $target_manifest, $file, $next_step);
1621 //$ret .="<table width='100%' cellpadding='0' cellspacing='0' border='0'>";
1623 $ret .= "<td width='20%' >".$name."</td>";
1624 $ret .= "<td width='15%' >".$version."</td>";
1625 $ret .= "<td width='15%' >".$published_date."</td>";
1626 $ret .= "<td width='15%' >".$uninstallable."</td>";
1627 $ret .= "<td width='20%' >".$description."</td>";
1630 $ret .= "<td width='7%'>{$commitPackage}</td>";
1631 $ret .= "<td width='1%'></td>";
1632 $ret .= "<td width='7%'>{$deletePackage}</td>";
1633 $ret .= "</td></tr>";
1635 $clean_field_name = "accept_lic_".str_replace('.', '_', urlencode(basename($file)));
1637 if(is_file($license_file)){
1639 $ret .= "<tr><td colspan=6>";
1640 $ret .= getLicenseDisplay('commit', $target_manifest, $file, $next_step, $license_file, $clean_field_name);
1641 $ret .= "</td></tr>";
1642 $hidden_input .= "<input type='hidden' name='$clean_field_name' id='$clean_field_name' value='no'>";
1644 $hidden_input .= "<input type='hidden' name='$clean_field_name' id='$clean_field_name' value='yes'>";
1648 $_SESSION['hidden_input'] = $hidden_input;
1650 if(count($files) > 0 ) {
1651 $ret .= "</tr><td colspan=7>";
1652 $ret .= "<form name='commit' action='install.php' method='POST'>
1653 <input type='hidden' name='current_step' value='{$next_step}'>
1654 <input type='hidden' name='goto' value='Re-check'>
1655 <input type='hidden' name='languagePackAction' value='commit'>
1656 <input type='hidden' name='install_type' value='custom'>
1659 $ret .= "</td></tr>";
1661 $ret .= "</tr><td colspan=7><i>{$mod_strings['LBL_LANG_NO_PACKS']}</i></td></tr>";
1666 if ( !function_exists('extractFile') ) {
1667 function extractFile( $zip_file, $file_in_zip, $base_tmp_upgrade_dir){
1668 $my_zip_dir = mk_temp_dir( $base_tmp_upgrade_dir );
1669 unzip_file( $zip_file, $file_in_zip, $my_zip_dir );
1670 return( "$my_zip_dir/$file_in_zip" );
1674 if ( !function_exists('extractManifest') ) {
1675 function extractManifest( $zip_file,$base_tmp_upgrade_dir ) {
1676 return( extractFile( $zip_file, "manifest.php",$base_tmp_upgrade_dir ) );
1680 if ( !function_exists('unlinkTempFiles') ) {
1681 function unlinkTempFiles($manifest='', $zipFile='') {
1682 global $sugar_config;
1684 @unlink($_FILES['language_pack']['tmp_name']);
1685 if(!empty($manifest))
1687 if(!empty($zipFile)) {
1688 //@unlink($zipFile);
1689 $tmpZipFile = substr($zipFile, strpos($zipFile, 'langpack/') + 9, strlen($zipFile));
1690 @unlink($sugar_config['upload_dir'].$tmpZipFile);
1693 rmdir_recursive($sugar_config['upload_dir']."upgrades/temp");
1694 sugar_mkdir($sugar_config['upload_dir']."upgrades/temp");
1698 function langPackUnpack($unpack_type, $full_file)
1700 global $sugar_config;
1701 global $base_upgrade_dir;
1702 global $base_tmp_upgrade_dir;
1704 $manifest = array();
1705 if(!empty($full_file)){
1706 $base_filename = pathinfo(urldecode($full_file), PATHINFO_FILENAME );
1708 return "Empty filename supplied";
1710 $manifest_file = extractManifest($full_file, $base_tmp_upgrade_dir);
1711 if($unpack_type == 'module')
1712 $license_file = extractFile($full_file, 'LICENSE.txt', $base_tmp_upgrade_dir);
1714 if(is_file($manifest_file)) {
1716 if($unpack_type == 'module' && is_file($license_file)){
1717 copy($license_file, $base_upgrade_dir.'/'.$unpack_type.'/'.$base_filename."-license.txt");
1719 copy($manifest_file, $base_upgrade_dir.'/'.$unpack_type.'/'.$base_filename."-manifest.php");
1721 require_once( $manifest_file );
1722 validate_manifest( $manifest );
1723 $upgrade_zip_type = $manifest['type'];
1725 mkdir_recursive( "$base_upgrade_dir/$upgrade_zip_type" );
1726 $target_path = "$base_upgrade_dir/$upgrade_zip_type/$base_filename";
1727 $target_manifest = $target_path . "-manifest.php";
1729 if( isset($manifest['icon']) && $manifest['icon'] != "" ) {
1730 $icon_location = extractFile( $full_file, $manifest['icon'], $base_tmp_upgrade_dir );
1731 $path_parts = pathinfo( $icon_location );
1732 copy( $icon_location, $target_path . "-icon." . $path_parts['extension'] );
1735 // move file from uploads to cache
1736 // FIXME: where should it be?
1737 if( copy( $full_file , $target_path.".zip" ) ){
1738 copy( $manifest_file, $target_manifest );
1739 unlink($full_file); // remove tempFile
1740 return "The file $base_filename has been uploaded.<br>\n";
1742 unlinkTempFiles($manifest_file, $full_file);
1743 return "There was an error uploading the file, please try again!<br>\n";
1746 die("The zip file is missing a manifest.php file. Cannot proceed.");
1748 unlinkTempFiles($manifest_file, '');
1751 if ( !function_exists('validate_manifest') ) {
1752 function validate_manifest( $manifest ){
1753 // takes a manifest.php manifest array and validates contents
1755 global $sugar_version;
1756 global $sugar_flavor;
1757 global $mod_strings;
1759 if( !isset($manifest['type']) ){
1760 die($mod_strings['ERROR_MANIFEST_TYPE']);
1762 $type = $manifest['type'];
1763 if( getInstallType( "/$type/" ) == "" ){
1764 die($mod_strings['ERROR_PACKAGE_TYPE']. ": '" . $type . "'." );
1767 return true; // making this a bit more relaxed since we updated the language extraction and merge capabilities
1770 if( isset($manifest['acceptable_sugar_versions']) ){
1771 $version_ok = false;
1772 $matches_empty = true;
1773 if( isset($manifest['acceptable_sugar_versions']['exact_matches']) ){
1774 $matches_empty = false;
1775 foreach( $manifest['acceptable_sugar_versions']['exact_matches'] as $match ){
1776 if( $match == $sugar_version ){
1781 if( !$version_ok && isset($manifest['acceptable_sugar_versions']['regex_matches']) ){
1782 $matches_empty = false;
1783 foreach( $manifest['acceptable_sugar_versions']['regex_matches'] as $match ){
1784 if( preg_match( "/$match/", $sugar_version ) ){
1790 if( !$matches_empty && !$version_ok ){
1791 die( $mod_strings['ERROR_VERSION_INCOMPATIBLE'] . $sugar_version );
1795 if( isset($manifest['acceptable_sugar_flavors']) && sizeof($manifest['acceptable_sugar_flavors']) > 0 ){
1797 foreach( $manifest['acceptable_sugar_flavors'] as $match ){
1798 if( $match == $sugar_flavor ){
1803 //die( $mod_strings['ERROR_FLAVOR_INCOMPATIBLE'] . $sugar_flavor );
1809 if ( !function_exists('getInstallType') ) {
1810 function getInstallType( $type_string ){
1812 $subdirs = array('full', 'langpack', 'module', 'patch', 'theme', 'temp');
1813 foreach( $subdirs as $subdir ){
1814 if( preg_match( "#/$subdir/#", $type_string ) ){
1818 // return empty if no match
1825 //mysqli connector has a separate parameter for port.. We need to separate it out from the host name
1826 function getHostPortFromString($hostname=''){
1828 $pos=strpos($hostname,':');
1830 //no need to process as string is empty or does not contain ':' delimiter
1834 $hostArr = explode(':', $hostname);
1840 function getLicenseContents($filename)
1843 if(file_exists($filename) && filesize($filename) >0){
1844 $license_file = trim(file_get_contents($filename));
1846 return $license_file;
1856 ///////////////////////////////////////////////////////////////////////////////
1857 //// FROM POPULATE SEED DATA
1859 'qa', 'dev', 'beans',
1860 'info', 'sales', 'support',
1861 'kid', 'the', 'section',
1862 'sugar', 'hr', 'im',
1863 'kid', 'vegan', 'phone',
1866 ".com", ".org", ".net", ".tv", ".cn", ".co.jp", ".us",
1867 ".edu", ".tw", ".de", ".it", ".co.uk", ".info", ".biz",
1872 * creates a random, DNS-clean webaddress
1874 function createWebAddress() {
1878 $one = $seed[rand(0, count($seed)-1)];
1879 $two = $seed[rand(0, count($seed)-1)];
1880 $tld = $tlds[rand(0, count($tlds)-1)];
1882 return "www.{$one}{$two}{$tld}";
1886 * creates a random email address
1889 function createEmailAddress() {
1893 $part[0] = $seed[rand(0, count($seed)-1)];
1894 $part[1] = $seed[rand(0, count($seed)-1)];
1895 $part[2] = $seed[rand(0, count($seed)-1)];
1897 $tld = $tlds[rand(0, count($tlds)-1)];
1902 for($i=0; $i<$len; $i++) {
1903 $ret .= (empty($ret)) ? '' : '.';
1908 $ret .= rand(10, 99);
1911 return "{$ret}@example{$tld}";
1915 function add_digits($quantity, &$string, $min = 0, $max = 9) {
1916 for($i=0; $i < $quantity; $i++) {
1917 $string .= mt_rand($min,$max);
1921 function create_phone_number() {
1923 add_digits(3, $phone);
1925 add_digits(3, $phone);
1927 add_digits(4, $phone);
1932 function create_date($year=null,$mnth=null,$day=null)
1935 $now = $timedate->getNow();
1936 if ($day==null) $day=$now->day+mt_rand(0,365);
1937 return $timedate->asDbDate($now->get_day_begin($day, $mnth, $year));
1940 function create_current_date_time()
1943 return $timedate->nowDb();
1946 function create_time($hr=null,$min=null,$sec=null)
1949 $date = TimeDate::fromTimestamp(0);
1950 if ($hr==null) $hr=mt_rand(6,19);
1951 if ($min==null) $min=(mt_rand(0,3)*15);
1952 if ($sec==null) $sec=0;
1953 return $timedate->asDbTime($date->setDate(2007, 10, 7)->setTime($hr, $min, $sec));
1956 function create_past_date()
1959 $now = $timedate->getNow(true);
1960 $day=$now->day-mt_rand(1, 365);
1961 return $timedate->asUserDate($now->get_day_begin($day));
1965 * This method will look for a file modules_post_install.php in the root directory and based on the
1966 * contents of this file, it will silently install any modules as specified in this array.
1968 function post_install_modules(){
1969 if(is_file('modules_post_install.php')){
1970 global $current_user, $mod_strings;
1971 $current_user = new User();
1972 $current_user->is_admin = '1';
1973 require_once('ModuleInstall/PackageManager/PackageManager.php');
1974 require_once('modules_post_install.php');
1975 //we now have the $modules_to_install array in memory
1976 $pm = new PackageManager();
1977 $old_mod_strings = $mod_strings;
1978 foreach($modules_to_install as $module_to_install){
1979 if(is_file($module_to_install)){
1980 $pm->performSetup($module_to_install, 'module', false);
1981 $file_to_install = sugar_cached('upload/upgrades/module/').basename($module_to_install);
1982 $_REQUEST['install_file'] = $file_to_install;
1983 $pm->performInstall($file_to_install);
1986 $mod_strings = $old_mod_strings;
1990 function get_help_button_url(){
1991 $help_url = 'http://www.sugarcrm.com/docs/Administration_Guides/CommunityEdition_Admin_Guide_5.0/toc.html';
1996 function create_db_user_creds($numChars=10){
1997 $numChars = 7; // number of chars in the password
1998 //chars to select from
1999 $charBKT = "abcdefghijklmnpqrstuvwxyz123456789ABCDEFGHIJKLMNPQRSTUVWXYZ";
2000 // seed the random number generator
2001 srand((double)microtime()*1000000);
2003 for ($i=0;$i<$numChars;$i++) // loop and create password
2004 $password = $password . substr ($charBKT, rand() % strlen($charBKT), 1);
2010 function addDefaultRoles($defaultRoles = array()) {
2014 foreach($defaultRoles as $roleName=>$role){
2015 $ACLField = new ACLField();
2016 $role1= new ACLRole();
2017 $role1->name = $roleName;
2018 $role1->description = $roleName." Role";
2019 $role1_id=$role1->save();
2020 foreach($role as $category=>$actions){
2021 foreach($actions as $name=>$access_override){
2022 if($name=='fields'){
2023 foreach($access_override as $field_id=>$access){
2024 $ACLField->setAccessControl($category, $role1_id, $field_id, $access);
2027 $queryACL="SELECT id FROM acl_actions where category='$category' and name='$name'";
2028 $result = $db->query($queryACL);
2029 $actionId=$db->fetchByAssoc($result);
2030 if (isset($actionId['id']) && !empty($actionId['id'])){
2031 $role1->setAction($role1_id, $actionId['id'], $access_override);
2040 * Fully enable SugarFeeds, enabling the user feed and all available modules that have SugarFeed data.
2042 function enableSugarFeeds()
2044 $admin = new Administration();
2045 $admin->saveSetting('sugarfeed','enabled','1');
2047 foreach ( SugarFeed::getAllFeedModules() as $module )
2048 SugarFeed::activateModuleFeed($module);
2050 check_logic_hook_file('Users','after_login', array(1, 'SugarFeed old feed entry remover', 'modules/SugarFeed/SugarFeedFlush.php', 'SugarFeedFlush', 'flushStaleEntries'));
2053 function create_writable_dir($dirname)
2055 if ((is_dir($dirname)) || @sugar_mkdir($dirname,0555)) {
2056 $ok = make_writable($dirname);
2059 installLog("ERROR: Cannot create writable dir $dirname");
2064 * Enable the InsideView connector for the four default modules.
2066 function enableInsideViewConnector()
2068 // Load up the existing mapping and hand it to the InsideView connector to have it setup the correct logic hooks
2069 $mapFile = 'modules/Connectors/connectors/sources/ext/rest/insideview/mapping.php';
2070 if ( file_exists('custom/'.$mapFile) ) {
2071 require('custom/'.$mapFile);
2076 require_once('modules/Connectors/connectors/sources/ext/rest/insideview/insideview.php');
2077 $source = new ext_rest_insideview();
2079 // $mapping is brought in from the mapping.php file above
2080 $source->saveMappingHook($mapping);