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['disable_convert_lead'] = false;
784 $sugar_config['log_dir'] = $setup_site_log_dir;
785 $sugar_config['log_file'] = $setup_site_log_file;
788 if(!empty($_SESSION['fts_type']))
789 $sugar_config['full_text_engine'] = array($_SESSION['fts_type'] => array('host'=> $_SESSION['fts_host'], 'port' => $_SESSION['fts_port']));
791 /*nsingh(bug 22402): Consolidate logger settings under $config['logger'] as liked by the new logger! If log4pphp exists,
792 these settings will be overwritten by those in log4php.properties when the user access admin->system settings.*/
793 $sugar_config['logger'] =
794 array ('level'=>$setup_site_log_level,
797 'name' => 'sugarcrm',
798 'dateFormat' => '%c',
801 'suffix' => ''), // bug51583, change default suffix to blank for backwards comptability
804 $sugar_config['session_dir'] = $setup_site_session_path;
805 $sugar_config['site_url'] = $setup_site_url;
806 $sugar_config['sugar_version'] = $setup_sugar_version;
807 $sugar_config['tmp_dir'] = $cache_dir.'xml/';
808 $sugar_config['upload_dir'] = 'upload/';
809 // $sugar_config['use_php_code_json'] = returnPhpJsonStatus(); // true on error
810 if( isset($_SESSION['setup_site_sugarbeet_anonymous_stats']) ){
811 $sugar_config['sugarbeet'] = $_SESSION['setup_site_sugarbeet_anonymous_stats'];
813 $sugar_config['demoData'] = $_SESSION['demoData'];
814 if( isset( $setup_site_guid ) ){
815 $sugar_config['unique_key'] = $setup_site_guid;
817 if(empty($sugar_config['unique_key'])){
818 $sugar_config['unique_key'] = md5( create_guid() );
820 // add installed langs to config
821 // entry in upgrade_history comes AFTER table creation
822 if(isset($_SESSION['INSTALLED_LANG_PACKS']) && is_array($_SESSION['INSTALLED_LANG_PACKS']) && !empty($_SESSION['INSTALLED_LANG_PACKS'])) {
823 foreach($_SESSION['INSTALLED_LANG_PACKS'] as $langZip) {
824 $lang = getSugarConfigLanguageArray($langZip);
826 $exLang = explode('::', $lang);
827 if(is_array($exLang) && count($exLang) == 3) {
828 $sugar_config['languages'][$exLang[0]] = $exLang[1];
833 if(file_exists('install/lang.config.php')){
834 include('install/lang.config.php');
835 if(!empty($config['languages'])){
836 foreach($config['languages'] as $lang=>$label){
837 $sugar_config['languages'][$lang] = $label;
842 ksort($sugar_config);
843 $sugar_config_string = "<?php\n" .
844 '// created: ' . date('Y-m-d H:i:s') . "\n" .
846 var_export($sugar_config, true) .
848 if($is_writable && write_array_to_file( "sugar_config", $sugar_config, "config.php")) {
852 echo "<p>{$mod_strings['ERR_PERFORM_CONFIG_PHP_1']}</p>\n";
853 echo "<p>{$mod_strings['ERR_PERFORM_CONFIG_PHP_2']}</p>\n";
854 echo "<TEXTAREA rows=\"15\" cols=\"80\">".$sugar_config_string."</TEXTAREA>";
855 echo "<p>{$mod_strings['ERR_PERFORM_CONFIG_PHP_3']}</p>";
857 $bottle[] = $mod_strings['ERR_PERFORM_CONFIG_PHP_4'];
861 //Now merge the config_si.php settings into config.php
862 if(file_exists('config.php') && file_exists('config_si.php'))
864 require_once('modules/UpgradeWizard/uw_utils.php');
865 merge_config_si_settings(false, 'config.php', 'config_si.php');
869 //// END $sugar_config
870 ///////////////////////////////////////////////////////////////////////////////
874 * (re)write the .htaccess file to prevent browser access to the log file
876 function handleHtaccess(){
878 $ignoreCase = (substr_count(strtolower($_SERVER['SERVER_SOFTWARE']), 'apache/2') > 0)?'(?i)':'';
879 $htaccess_file = ".htaccess";
881 $restrict_str = <<<EOQ
883 # BEGIN SUGARCRM RESTRICTIONS
884 RedirectMatch 403 {$ignoreCase}.*\.log$
885 RedirectMatch 403 {$ignoreCase}/+not_imported_.*\.txt
886 RedirectMatch 403 {$ignoreCase}/+(soap|cache|xtemplate|data|examples|include|log4php|metadata|modules)/+.*\.(php|tpl)
887 RedirectMatch 403 {$ignoreCase}/+emailmandelivery\.php
888 RedirectMatch 403 {$ignoreCase}/+upload
889 RedirectMatch 403 {$ignoreCase}/+custom/+blowfish
890 RedirectMatch 403 {$ignoreCase}/+cache/+diagnostic
891 RedirectMatch 403 {$ignoreCase}/+files\.md5$
892 # END SUGARCRM RESTRICTIONS
895 $cache_headers = <<<EOQ
897 <FilesMatch "\.(jpg|png|gif|js|css|ico)$">
898 <IfModule mod_headers.c>
900 Header set Cache-Control "max-age=2592000"
901 Header set Expires "01 Jan 2112 00:00:00 GMT"
904 <IfModule mod_expires.c>
905 ExpiresByType text/css "access plus 1 month"
906 ExpiresByType text/javascript "access plus 1 month"
907 ExpiresByType application/x-javascript "access plus 1 month"
908 ExpiresByType image/gif "access plus 1 month"
909 ExpiresByType image/jpg "access plus 1 month"
910 ExpiresByType image/png "access plus 1 month"
913 if(file_exists($htaccess_file)){
914 $fp = fopen($htaccess_file, 'r');
916 while($line = fgets($fp)){
918 if(preg_match("/\s*#\s*BEGIN\s*SUGARCRM\s*RESTRICTIONS/i", $line))$skip = true;
919 if(!$skip)$contents .= $line;
920 if(preg_match("/\s*#\s*END\s*SUGARCRM\s*RESTRICTIONS/i", $line))$skip = false;
923 $status = file_put_contents($htaccess_file, $contents . $restrict_str . $cache_headers);
925 echo "<p>{$mod_strings['ERR_PERFORM_HTACCESS_1']}<span class=stop>{$htaccess_file}</span> {$mod_strings['ERR_PERFORM_HTACCESS_2']}</p>\n";
926 echo "<p>{$mod_strings['ERR_PERFORM_HTACCESS_3']}</p>\n";
933 * (re)write the web.config file to prevent browser access to the log file
935 function handleWebConfig()
937 if ( !isset($_SERVER['IIS_UrlRewriteModule']) ) {
941 global $setup_site_log_dir;
942 global $setup_site_log_file;
943 global $sugar_config;
945 // Bug 36968 - Fallback to using $sugar_config values when we are not calling this from the installer
946 if (empty($setup_site_log_file)) {
947 $setup_site_log_file = $sugar_config['log_file'];
948 if ( empty($sugar_config['log_file']) ) {
949 $setup_site_log_file = 'sugarcrm.log';
952 if (empty($setup_site_log_dir)) {
953 $setup_site_log_dir = $sugar_config['log_dir'];
954 if ( empty($sugar_config['log_dir']) ) {
955 $setup_site_log_dir = '.';
959 $prefix = $setup_site_log_dir.empty($setup_site_log_dir)?'':'/';
962 $config_array = array(
963 array('1'=> $prefix.str_replace('.','\\.',$setup_site_log_file).'\\.*' ,'2'=>'log_file_restricted.html'),
964 array('1'=> $prefix.'install.log' ,'2'=>'log_file_restricted.html'),
965 array('1'=> $prefix.'upgradeWizard.log' ,'2'=>'log_file_restricted.html'),
966 array('1'=> $prefix.'emailman.log' ,'2'=>'log_file_restricted.html'),
967 array('1'=>'not_imported_.*.txt' ,'2'=>'log_file_restricted.html'),
968 array('1'=>'XTemplate/(.*)/(.*).php' ,'2'=>'index.php'),
969 array('1'=>'data/(.*).php' ,'2'=>'index.php'),
970 array('1'=>'examples/(.*).php' ,'2'=>'index.php'),
971 array('1'=>'include/(.*).php' ,'2'=>'index.php'),
972 array('1'=>'include/(.*)/(.*).php' ,'2'=>'index.php'),
973 array('1'=>'log4php/(.*).php' ,'2'=>'index.php'),
974 array('1'=>'log4php/(.*)/(.*)' ,'2'=>'index.php'),
975 array('1'=>'metadata/(.*)/(.*).php' ,'2'=>'index.php'),
976 array('1'=>'modules/(.*)/(.*).php' ,'2'=>'index.php'),
977 array('1'=>'soap/(.*).php' ,'2'=>'index.php'),
978 array('1'=>'emailmandelivery.php' ,'2'=>'index.php'),
979 array('1'=>'cron.php' ,'2'=>'index.php'),
980 array('1'=> $sugar_config['upload_dir'].'.*' ,'2'=>'index.php'),
984 $xmldoc = new XMLWriter();
985 $xmldoc->openURI('web.config');
986 $xmldoc->setIndent(true);
987 $xmldoc->setIndentString(' ');
988 $xmldoc->startDocument('1.0','UTF-8');
989 $xmldoc->startElement('configuration');
990 $xmldoc->startElement('system.webServer');
991 $xmldoc->startElement('rewrite');
992 $xmldoc->startElement('rules');
993 for ($i = 0; $i < count($config_array); $i++) {
994 $xmldoc->startElement('rule');
995 $xmldoc->writeAttribute('name', "redirect$i");
996 $xmldoc->writeAttribute('stopProcessing', 'true');
997 $xmldoc->startElement('match');
998 $xmldoc->writeAttribute('url', $config_array[$i]['1']);
999 $xmldoc->endElement();
1000 $xmldoc->startElement('action');
1001 $xmldoc->writeAttribute('type', 'Redirect');
1002 $xmldoc->writeAttribute('url', $config_array[$i]['2']);
1003 $xmldoc->writeAttribute('redirectType', 'Found');
1004 $xmldoc->endElement();
1005 $xmldoc->endElement();
1007 $xmldoc->endElement();
1008 $xmldoc->startElement('outboundRules');
1009 $xmldoc->startElement('rule');
1010 $xmldoc->writeAttribute('name', 'Remove ETag');
1011 $xmldoc->startElement('match');
1012 $xmldoc->writeAttribute('serverVariable', 'RESPONSE_ETag');
1013 $xmldoc->writeAttribute('pattern', '.+');
1014 $xmldoc->endElement();
1015 $xmldoc->startElement('action');
1016 $xmldoc->writeAttribute('type', 'Rewrite');
1017 $xmldoc->writeAttribute('value', '');
1018 $xmldoc->endElement();
1019 $xmldoc->endElement();
1020 $xmldoc->endElement();
1021 $xmldoc->endElement();
1022 $xmldoc->startElement('caching');
1023 $xmldoc->startElement('profiles');
1024 $xmldoc->startElement('remove');
1025 $xmldoc->writeAttribute('extension', ".php");
1026 $xmldoc->endElement();
1027 $xmldoc->endElement();
1028 $xmldoc->endElement();
1029 $xmldoc->startElement('staticContent');
1030 $xmldoc->startElement("clientCache");
1031 $xmldoc->writeAttribute('cacheControlMode', 'UseMaxAge');
1032 $xmldoc->writeAttribute('cacheControlMaxAge', '30.00:00:00');
1033 $xmldoc->endElement();
1034 $xmldoc->endElement();
1035 $xmldoc->endElement();
1036 $xmldoc->endElement();
1037 $xmldoc->endDocument();
1042 * Drop old tables if table exists and told to drop it
1044 function drop_table_install( &$focus ){
1048 $result = $db->tableExists($focus->table_name);
1051 $focus->drop_tables();
1052 $GLOBALS['log']->info("Dropped old ".$focus->table_name." table.");
1056 $GLOBALS['log']->info("Did not need to drop old ".$focus->table_name." table. It doesn't exist.");
1061 // Creating new tables if they don't exist.
1062 function create_table_if_not_exist( &$focus ){
1064 $table_created = false;
1066 // normal code follows
1067 $result = $db->tableExists($focus->table_name);
1069 $GLOBALS['log']->info("Table ".$focus->table_name." already exists.");
1071 $focus->create_tables();
1072 $GLOBALS['log']->info("Created ".$focus->table_name." table.");
1073 $table_created = true;
1075 return $table_created;
1080 function create_default_users(){
1082 global $setup_site_admin_password;
1083 global $setup_site_admin_user_name;
1084 global $create_default_user;
1085 global $sugar_config;
1087 require_once('install/UserDemoData.php');
1089 //Create default admin user
1092 $user->new_with_id = true;
1093 $user->last_name = 'Administrator';
1094 $user->user_name = $setup_site_admin_user_name;
1095 $user->title = "Administrator";
1096 $user->status = 'Active';
1097 $user->is_admin = true;
1098 $user->employee_status = 'Active';
1099 $user->user_hash = User::getPasswordHash($setup_site_admin_password);
1101 $user->picture = UserDemoData::_copy_user_image($user->id);
1105 if( $create_default_user ){
1106 $default_user = new User();
1107 $default_user->last_name = $sugar_config['default_user_name'];
1108 $default_user->user_name = $sugar_config['default_user_name'];
1109 $default_user->status = 'Active';
1110 if( isset($sugar_config['default_user_is_admin']) && $sugar_config['default_user_is_admin'] ){
1111 $default_user->is_admin = true;
1113 $default_user->user_hash = User::getPasswordHash($sugar_config['default_password']);
1114 $default_user->save();
1118 function set_admin_password( $password ) {
1121 $user_hash = User::getPasswordHash($password);
1123 $query = "update users set user_hash='$user_hash' where id='1'";
1128 function insert_default_settings(){
1130 global $setup_sugar_version;
1131 global $sugar_db_version;
1134 $db->query("INSERT INTO config (category, name, value) VALUES ('notify', 'fromaddress', 'do_not_reply@example.com')");
1135 $db->query("INSERT INTO config (category, name, value) VALUES ('notify', 'fromname', 'SugarCRM')");
1136 $db->query("INSERT INTO config (category, name, value) VALUES ('notify', 'send_by_default', '1')");
1137 $db->query("INSERT INTO config (category, name, value) VALUES ('notify', 'on', '1')");
1138 $db->query("INSERT INTO config (category, name, value) VALUES ('notify', 'send_from_assigning_user', '0')");
1139 /* cn: moved to OutboundEmail class
1140 $db->query("INSERT INTO config (category, name, value) VALUES ('mail', 'smtpserver', 'localhost')");
1141 $db->query("INSERT INTO config (category, name, value) VALUES ('mail', 'smtpport', '25')");
1142 $db->query("INSERT INTO config (category, name, value) VALUES ('mail', 'sendtype', 'smtp')");
1143 $db->query("INSERT INTO config (category, name, value) VALUES ('mail', 'smtpuser', '')");
1144 $db->query("INSERT INTO config (category, name, value) VALUES ('mail', 'smtppass', '')");
1145 $db->query("INSERT INTO config (category, name, value) VALUES ('mail', 'smtpauth_req', '0')");
1147 $db->query("INSERT INTO config (category, name, value) VALUES ('info', 'sugar_version', '" . $sugar_db_version . "')");
1148 $db->query("INSERT INTO config (category, name, value) VALUES ('MySettings', 'tab', '')");
1149 $db->query("INSERT INTO config (category, name, value) VALUES ('portal', 'on', '0')");
1153 //insert default tracker settings
1154 $db->query("INSERT INTO config (category, name, value) VALUES ('tracker', 'Tracker', '1')");
1158 $db->query( "INSERT INTO config (category, name, value) VALUES ( 'system', 'skypeout_on', '1')" );
1169 // Returns true if the given file/dir has been made writable (or is already
1171 function make_writable($file)
1175 if(is_file($file) || is_dir($file))
1177 if(is_writable($file))
1183 $original_fileperms = fileperms($file);
1185 // add user writable permission
1186 $new_fileperms = $original_fileperms | 0x0080;
1187 @sugar_chmod($file, $new_fileperms);
1189 if(is_writable($file))
1195 // add group writable permission
1196 $new_fileperms = $original_fileperms | 0x0010;
1197 @chmod($file, $new_fileperms);
1199 if(is_writable($file))
1205 // add world writable permission
1206 $new_fileperms = $original_fileperms | 0x0002;
1207 @chmod($file, $new_fileperms);
1209 if(is_writable($file))
1221 function recursive_make_writable($start_file)
1223 $ret_val = make_writable($start_file);
1225 if($ret_val && is_dir($start_file))
1227 // PHP 4 alternative to scandir()
1229 $dh = opendir($start_file);
1230 $filename = readdir($dh);
1231 while(!empty($filename))
1233 if($filename != '.' && $filename != '..' && $filename != '.svn')
1235 $files[] = $filename;
1238 $filename = readdir($dh);
1241 foreach($files as $file)
1243 $ret_val = recursive_make_writable($start_file . '/' . $file);
1247 $_SESSION['unwriteable_module_files'][dirname($file)] = dirname($file);
1248 $fnl_ret_val = false;
1255 $unwriteable_directory = is_dir($start_file) ? $start_file : dirname($start_file);
1256 if($unwriteable_directory[0] == '.'){$unwriteable_directory = substr($unwriteable_directory,1);}
1257 $_SESSION['unwriteable_module_files'][$unwriteable_directory] = $unwriteable_directory;
1258 $_SESSION['unwriteable_module_files']['failed'] = true;
1264 function recursive_is_writable($start_file)
1266 $ret_val = is_writable($start_file);
1268 if($ret_val && is_dir($start_file))
1270 // PHP 4 alternative to scandir()
1272 $dh = opendir($start_file);
1273 $filename = readdir($dh);
1274 while(!empty($filename))
1276 if($filename != '.' && $filename != '..' && $filename != '.svn')
1278 $files[] = $filename;
1281 $filename = readdir($dh);
1284 foreach($files as $file)
1286 $ret_val = recursive_is_writable($start_file . '/' . $file);
1298 // one place for form validation/conversion to boolean
1299 function get_boolean_from_request( $field ){
1300 if( !isset($_REQUEST[$field]) ){
1304 if( ($_REQUEST[$field] == 'on') || ($_REQUEST[$field] == 'yes') ){
1312 function stripslashes_checkstrings($value){
1313 if(is_string($value)){
1314 return stripslashes($value);
1320 function print_debug_array( $name, $debug_array ){
1321 ksort( $debug_array );
1323 print( "$name vars:\n" );
1326 foreach( $debug_array as $key => $value ){
1327 if( stristr( $key, "password" ) ){
1330 print( " [$key] => $value\n" );
1336 function print_debug_comment(){
1337 if( !empty($_REQUEST['debug']) ){
1338 $_SESSION['debug'] = $_REQUEST['debug'];
1341 if( !empty($_SESSION['debug']) && ($_SESSION['debug'] == 'true') ){
1342 print( "<!-- debug is on (to turn off, hit any page with 'debug=false' as a URL parameter.\n" );
1344 print_debug_array( "Session", $_SESSION );
1345 print_debug_array( "Request", $_REQUEST );
1346 print_debug_array( "Post", $_POST );
1347 print_debug_array( "Get", $_GET );
1353 function validate_systemOptions() {
1354 global $mod_strings;
1356 if(!empty($_SESSION['setup_db_type']) && trim($_SESSION['setup_db_type']) != '') {
1357 $db = DBManagerFactory::getTypeInstance($_SESSION['setup_db_type']);
1359 $_SESSION['setup_db_manager'] = get_class($db);
1363 $errors[] = "<span class='error'>".$mod_strings['ERR_DB_INVALID']."</span>";
1368 function validate_dbConfig() {
1369 global $mod_strings;
1370 require_once('install/checkDBSettings.php');
1371 return checkDBSettings(true);
1375 function validate_siteConfig($type){
1376 global $mod_strings;
1380 if(empty($_SESSION['setup_system_name'])){
1381 $errors[] = "<span class='error'>".$mod_strings['LBL_REQUIRED_SYSTEM_NAME']."</span>";
1383 if($_SESSION['setup_site_url'] == ''){
1384 $errors[] = "<span class='error'>".$mod_strings['ERR_URL_BLANK']."</span>";
1387 if($_SESSION['setup_site_admin_user_name'] == '') {
1388 $errors[] = "<span class='error'>".$mod_strings['ERR_ADMIN_USER_NAME_BLANK']."</span>";
1391 if($_SESSION['setup_site_admin_password'] == ''){
1392 $errors[] = "<span class='error'>".$mod_strings['ERR_ADMIN_PASS_BLANK']."</span>";
1395 if($_SESSION['setup_site_admin_password'] != $_SESSION['setup_site_admin_password_retype']){
1396 $errors[] = "<span class='error'>".$mod_strings['ERR_PASSWORD_MISMATCH']."</span>";
1399 if(!empty($_SESSION['setup_site_custom_session_path']) && $_SESSION['setup_site_session_path'] == ''){
1400 $errors[] = "<span class='error'>".$mod_strings['ERR_SESSION_PATH']."</span>";
1403 if(!empty($_SESSION['setup_site_custom_session_path']) && $_SESSION['setup_site_session_path'] != ''){
1404 if(is_dir($_SESSION['setup_site_session_path'])){
1405 if(!is_writable($_SESSION['setup_site_session_path'])){
1406 $errors[] = "<span class='error'>".$mod_strings['ERR_SESSION_DIRECTORY']."</span>";
1410 $errors[] = "<span class='error'>".$mod_strings['ERR_SESSION_DIRECTORY_NOT_EXISTS']."</span>";
1414 if(!empty($_SESSION['setup_site_custom_log_dir']) && $_SESSION['setup_site_log_dir'] == ''){
1415 $errors[] = "<span class='error'>".$mod_strings['ERR_LOG_DIRECTORY_NOT_EXISTS']."</span>";
1418 if(!empty($_SESSION['setup_site_custom_log_dir']) && $_SESSION['setup_site_log_dir'] != ''){
1419 if(is_dir($_SESSION['setup_site_log_dir'])){
1420 if(!is_writable($_SESSION['setup_site_log_dir'])) {
1421 $errors[] = "<span class='error'>".$mod_strings['ERR_LOG_DIRECTORY_NOT_WRITABLE']."</span>";
1425 $errors[] = "<span class='error'>".$mod_strings['ERR_LOG_DIRECTORY_NOT_EXISTS']."</span>";
1429 if(!empty($_SESSION['setup_site_specify_guid']) && $_SESSION['setup_site_guid'] == ''){
1430 $errors[] = "<span class='error'>".$mod_strings['ERR_SITE_GUID']."</span>";
1438 function pullSilentInstallVarsIntoSession() {
1439 global $mod_strings;
1440 global $sugar_config;
1443 if( file_exists('config_si.php') ){
1444 require_once('config_si.php');
1446 else if( empty($sugar_config_si) ){
1447 die( $mod_strings['ERR_SI_NO_CONFIG'] );
1450 $config_subset = array (
1451 'setup_site_url' => isset($sugar_config['site_url']) ? $sugar_config['site_url'] : '',
1452 'setup_db_host_name' => isset($sugar_config['dbconfig']['db_host_name']) ? $sugar_config['dbconfig']['db_host_name'] : '',
1453 'setup_db_host_instance' => isset($sugar_config['dbconfig']['db_host_instance']) ? $sugar_config['dbconfig']['db_host_instance'] : '',
1454 'setup_db_sugarsales_user' => isset($sugar_config['dbconfig']['db_user_name']) ? $sugar_config['dbconfig']['db_user_name'] : '',
1455 'setup_db_sugarsales_password' => isset($sugar_config['dbconfig']['db_password']) ? $sugar_config['dbconfig']['db_password'] : '',
1456 'setup_db_database_name' => isset($sugar_config['dbconfig']['db_name']) ? $sugar_config['dbconfig']['db_name'] : '',
1457 'setup_db_type' => isset($sugar_config['dbconfig']['db_type']) ? $sugar_config['dbconfig']['db_type'] : '',
1458 'setup_db_port_num' => isset($sugar_config['dbconfig']['db_port']) ? $sugar_config['dbconfig']['db_port'] : '',
1459 'setup_db_options' => !empty($sugar_config['dbconfigoptions']) ? $sugar_config['dbconfigoptions'] : array(),
1461 // third array of values derived from above values
1463 'setup_site_admin_password_retype' => $sugar_config_si['setup_site_admin_password'],
1464 'setup_db_sugarsales_password_retype' => $config_subset['setup_db_sugarsales_password'],
1467 $needles = array('setup_db_create_database','setup_db_create_sugarsales_user','setup_license_key_users',
1468 'setup_license_key_expire_date','setup_license_key', 'setup_num_lic_oc',
1469 'default_currency_iso4217', 'default_currency_name', 'default_currency_significant_digits',
1470 'default_currency_symbol', 'default_date_format', 'default_time_format', 'default_decimal_seperator',
1471 'default_export_charset', 'default_language', 'default_locale_name_format', 'default_number_grouping_seperator',
1472 'export_delimiter', 'cache_dir', 'setup_db_options');
1473 copyFromArray($sugar_config_si, $needles, $derived);
1474 $all_config_vars = array_merge( $config_subset, $sugar_config_si, $derived );
1476 // bug 16860 tyoung - trim leading and trailing whitespace from license_key
1477 if (isset($all_config_vars['setup_license_key'])) {
1478 $all_config_vars['setup_license_key'] = trim($all_config_vars['setup_license_key']);
1481 foreach( $all_config_vars as $key => $value ){
1482 $_SESSION[$key] = $value;
1487 * given an array it will check to determine if the key exists in the array, if so
1488 * it will addd to the return array
1490 * @param intput_array haystack to check
1491 * @param needles list of needles to search for
1492 * @param output_array the array to add the keys to
1494 function copyFromArray($input_array, $needles, $output_array){
1495 foreach($needles as $needle){
1496 if(isset($input_array[$needle])){
1497 $output_array[$needle] = $input_array[$needle];
1505 * handles language pack uploads - code based off of upload_file->final_move()
1506 * puts it into the cache/upload dir to be handed off to langPackUnpack();
1508 * @param object file UploadFile object
1509 * @return bool true if successful
1511 function langPackFinalMove($file) {
1512 global $sugar_config;
1513 //."upgrades/langpack/"
1514 $destination = $sugar_config['upload_dir'].$file->stored_file_name;
1515 if(!move_uploaded_file($_FILES[$file->field_name]['tmp_name'], $destination)) {
1516 die ("ERROR: can't move_uploaded_file to $destination. You should try making the directory writable by the webserver");
1521 function getLicenseDisplay($type, $manifest, $zipFile, $next_step, $license_file, $clean_file) {
1522 return PackageManagerDisplay::getLicenseDisplay($license_file, 'install.php', $next_step, $zipFile, $type, $manifest, $clean_file);
1527 * creates the remove/delete form for langpack page
1528 * @param string type commit/remove
1529 * @param string manifest path to manifest file
1530 * @param string zipFile path to uploaded zip file
1531 * @param int nextstep current step
1532 * @return string ret <form> for this package
1534 function getPackButton($type, $manifest, $zipFile, $next_step, $uninstallable='Yes', $showButtons=true) {
1535 global $mod_strings;
1537 $button = $mod_strings['LBL_LANG_BUTTON_COMMIT'];
1538 if($type == 'remove') {
1539 $button = $mod_strings['LBL_LANG_BUTTON_REMOVE'];
1540 } elseif($type == 'uninstall') {
1541 $button = $mod_strings['LBL_LANG_BUTTON_UNINSTALL'];
1544 $disabled = ($uninstallable == 'Yes') ? false : true;
1546 $ret = "<form name='delete{$zipFile}' action='install.php' method='POST'>
1547 <input type='hidden' name='current_step' value='{$next_step}'>
1548 <input type='hidden' name='goto' value='{$mod_strings['LBL_CHECKSYS_RECHECK']}'>
1549 <input type='hidden' name='languagePackAction' value='{$type}'>
1550 <input type='hidden' name='manifest' value='".urlencode($manifest)."'>
1551 <input type='hidden' name='zipFile' value='".urlencode($zipFile)."'>
1552 <input type='hidden' name='install_type' value='custom'>";
1553 if(!$disabled && $showButtons) {
1554 $ret .= "<input type='submit' value='{$button}' class='button'>";
1561 * finds all installed languages and returns an array with the names
1562 * @return array langs array of installed languages
1564 function getInstalledLanguages() {
1565 $langDir = 'include/language/';
1566 $dh = opendir($langDir);
1569 while($file = readdir($dh)) {
1570 if(substr($file, -3) == 'php') {
1579 * searches upgrade dir for lang pack files.
1581 * @return string HTML of available lang packs
1583 function getLangPacks($display_commit = true, $types = array('langpack'), $notice_text = '') {
1584 global $mod_strings;
1586 global $base_upgrade_dir;
1588 if(empty($notice_text)){
1589 $notice_text = $mod_strings['LBL_LANG_PACK_READY'];
1591 $ret = "<tr><td colspan=7 align=left>{$notice_text}</td></tr>";
1592 //$ret .="<table width='100%' cellpadding='0' cellspacing='0' border='0'>";
1594 <td width='20%' ><b>{$mod_strings['LBL_ML_NAME']}</b></td>
1595 <td width='15%' ><b>{$mod_strings['LBL_ML_VERSION']}</b></td>
1596 <td width='15%' ><b>{$mod_strings['LBL_ML_PUBLISHED']}</b></td>
1597 <td width='15%' ><b>{$mod_strings['LBL_ML_UNINSTALLABLE']}</b></td>
1598 <td width='20%' ><b>{$mod_strings['LBL_ML_DESCRIPTION']}</b></td>
1599 <td width='7%' ></td>
1600 <td width='1%' ></td>
1601 <td width='7%' ></td>
1605 // duh, new installs won't have the upgrade folders
1606 if(!is_dir($base_upgrade_dir)) {
1607 mkdir_recursive( $base_upgrade_dir);
1609 $subdirs = array('full', 'langpack', 'module', 'patch', 'theme', 'temp');
1610 foreach( $subdirs as $subdir ){
1611 mkdir_recursive( "$base_upgrade_dir/$subdir" );
1614 $files = findAllFiles($base_upgrade_dir, $files);
1616 unset($_SESSION['hidden_input']);
1618 foreach($files as $file) {
1619 if(!preg_match("#.*\.zip\$#", $file)) {
1623 // skip installed lang packs
1624 if(isset($_SESSION['INSTALLED_LANG_PACKS']) && in_array($file, $_SESSION['INSTALLED_LANG_PACKS'])) {
1628 // handle manifest.php
1629 $target_manifest = remove_file_extension( $file ) . '-manifest.php';
1630 $license_file = remove_file_extension( $file ) . '-license.txt';
1631 include($target_manifest);
1634 if(!in_array(strtolower($manifest['type']), $types))
1638 $md5_matches = array();
1639 if($manifest['type'] == 'module'){
1640 $uh = new UpgradeHistory();
1641 $upgrade_content = clean_path($file);
1642 $the_base = basename($upgrade_content);
1643 $the_md5 = md5_file($upgrade_content);
1644 $md5_matches = $uh->findByMd5($the_md5);
1647 if($manifest['type']!= 'module' || 0 == sizeof($md5_matches)){
1648 $name = empty($manifest['name']) ? $file : $manifest['name'];
1649 $version = empty($manifest['version']) ? '' : $manifest['version'];
1650 $published_date = empty($manifest['published_date']) ? '' : $manifest['published_date'];
1652 $description = empty($manifest['description']) ? 'None' : $manifest['description'];
1653 $uninstallable = empty($manifest['is_uninstallable']) ? 'No' : 'Yes';
1654 $manifest_type = $manifest['type'];
1655 $commitPackage = getPackButton('commit', $target_manifest, $file, $next_step);
1656 $deletePackage = getPackButton('remove', $target_manifest, $file, $next_step);
1657 //$ret .="<table width='100%' cellpadding='0' cellspacing='0' border='0'>";
1659 $ret .= "<td width='20%' >".$name."</td>";
1660 $ret .= "<td width='15%' >".$version."</td>";
1661 $ret .= "<td width='15%' >".$published_date."</td>";
1662 $ret .= "<td width='15%' >".$uninstallable."</td>";
1663 $ret .= "<td width='20%' >".$description."</td>";
1666 $ret .= "<td width='7%'>{$commitPackage}</td>";
1667 $ret .= "<td width='1%'></td>";
1668 $ret .= "<td width='7%'>{$deletePackage}</td>";
1669 $ret .= "</td></tr>";
1671 $clean_field_name = "accept_lic_".str_replace('.', '_', urlencode(basename($file)));
1673 if(is_file($license_file)){
1675 $ret .= "<tr><td colspan=6>";
1676 $ret .= getLicenseDisplay('commit', $target_manifest, $file, $next_step, $license_file, $clean_field_name);
1677 $ret .= "</td></tr>";
1678 $hidden_input .= "<input type='hidden' name='$clean_field_name' id='$clean_field_name' value='no'>";
1680 $hidden_input .= "<input type='hidden' name='$clean_field_name' id='$clean_field_name' value='yes'>";
1684 $_SESSION['hidden_input'] = $hidden_input;
1686 if(count($files) > 0 ) {
1687 $ret .= "</tr><td colspan=7>";
1688 $ret .= "<form name='commit' action='install.php' method='POST'>
1689 <input type='hidden' name='current_step' value='{$next_step}'>
1690 <input type='hidden' name='goto' value='Re-check'>
1691 <input type='hidden' name='languagePackAction' value='commit'>
1692 <input type='hidden' name='install_type' value='custom'>
1695 $ret .= "</td></tr>";
1697 $ret .= "</tr><td colspan=7><i>{$mod_strings['LBL_LANG_NO_PACKS']}</i></td></tr>";
1702 if ( !function_exists('extractFile') ) {
1703 function extractFile( $zip_file, $file_in_zip, $base_tmp_upgrade_dir){
1704 $my_zip_dir = mk_temp_dir( $base_tmp_upgrade_dir );
1705 unzip_file( $zip_file, $file_in_zip, $my_zip_dir );
1706 return( "$my_zip_dir/$file_in_zip" );
1710 if ( !function_exists('extractManifest') ) {
1711 function extractManifest( $zip_file,$base_tmp_upgrade_dir ) {
1712 return( extractFile( $zip_file, "manifest.php",$base_tmp_upgrade_dir ) );
1716 if ( !function_exists('unlinkTempFiles') ) {
1717 function unlinkTempFiles($manifest='', $zipFile='') {
1718 global $sugar_config;
1720 @unlink($_FILES['language_pack']['tmp_name']);
1721 if(!empty($manifest))
1723 if(!empty($zipFile)) {
1724 //@unlink($zipFile);
1725 $tmpZipFile = substr($zipFile, strpos($zipFile, 'langpack/') + 9, strlen($zipFile));
1726 @unlink($sugar_config['upload_dir'].$tmpZipFile);
1729 rmdir_recursive($sugar_config['upload_dir']."upgrades/temp");
1730 sugar_mkdir($sugar_config['upload_dir']."upgrades/temp");
1734 function langPackUnpack($unpack_type, $full_file)
1736 global $sugar_config;
1737 global $base_upgrade_dir;
1738 global $base_tmp_upgrade_dir;
1740 $manifest = array();
1741 if(!empty($full_file)){
1742 $base_filename = pathinfo(urldecode($full_file), PATHINFO_FILENAME );
1744 return "Empty filename supplied";
1746 $manifest_file = extractManifest($full_file, $base_tmp_upgrade_dir);
1747 if($unpack_type == 'module')
1748 $license_file = extractFile($full_file, 'LICENSE.txt', $base_tmp_upgrade_dir);
1750 if(is_file($manifest_file)) {
1752 if($unpack_type == 'module' && is_file($license_file)){
1753 copy($license_file, $base_upgrade_dir.'/'.$unpack_type.'/'.$base_filename."-license.txt");
1755 copy($manifest_file, $base_upgrade_dir.'/'.$unpack_type.'/'.$base_filename."-manifest.php");
1757 require_once( $manifest_file );
1758 validate_manifest( $manifest );
1759 $upgrade_zip_type = $manifest['type'];
1761 mkdir_recursive( "$base_upgrade_dir/$upgrade_zip_type" );
1762 $target_path = "$base_upgrade_dir/$upgrade_zip_type/$base_filename";
1763 $target_manifest = $target_path . "-manifest.php";
1765 if( isset($manifest['icon']) && $manifest['icon'] != "" ) {
1766 $icon_location = extractFile( $full_file, $manifest['icon'], $base_tmp_upgrade_dir );
1767 $path_parts = pathinfo( $icon_location );
1768 copy( $icon_location, $target_path . "-icon." . $path_parts['extension'] );
1771 // move file from uploads to cache
1772 // FIXME: where should it be?
1773 if( copy( $full_file , $target_path.".zip" ) ){
1774 copy( $manifest_file, $target_manifest );
1775 unlink($full_file); // remove tempFile
1776 return "The file $base_filename has been uploaded.<br>\n";
1778 unlinkTempFiles($manifest_file, $full_file);
1779 return "There was an error uploading the file, please try again!<br>\n";
1782 die("The zip file is missing a manifest.php file. Cannot proceed.");
1784 unlinkTempFiles($manifest_file, '');
1787 if ( !function_exists('validate_manifest') ) {
1788 function validate_manifest( $manifest ){
1789 // takes a manifest.php manifest array and validates contents
1791 global $sugar_version;
1792 global $sugar_flavor;
1793 global $mod_strings;
1795 if( !isset($manifest['type']) ){
1796 die($mod_strings['ERROR_MANIFEST_TYPE']);
1798 $type = $manifest['type'];
1799 if( getInstallType( "/$type/" ) == "" ){
1800 die($mod_strings['ERROR_PACKAGE_TYPE']. ": '" . $type . "'." );
1803 return true; // making this a bit more relaxed since we updated the language extraction and merge capabilities
1806 if( isset($manifest['acceptable_sugar_versions']) ){
1807 $version_ok = false;
1808 $matches_empty = true;
1809 if( isset($manifest['acceptable_sugar_versions']['exact_matches']) ){
1810 $matches_empty = false;
1811 foreach( $manifest['acceptable_sugar_versions']['exact_matches'] as $match ){
1812 if( $match == $sugar_version ){
1817 if( !$version_ok && isset($manifest['acceptable_sugar_versions']['regex_matches']) ){
1818 $matches_empty = false;
1819 foreach( $manifest['acceptable_sugar_versions']['regex_matches'] as $match ){
1820 if( preg_match( "/$match/", $sugar_version ) ){
1826 if( !$matches_empty && !$version_ok ){
1827 die( $mod_strings['ERROR_VERSION_INCOMPATIBLE'] . $sugar_version );
1831 if( isset($manifest['acceptable_sugar_flavors']) && sizeof($manifest['acceptable_sugar_flavors']) > 0 ){
1833 foreach( $manifest['acceptable_sugar_flavors'] as $match ){
1834 if( $match == $sugar_flavor ){
1839 //die( $mod_strings['ERROR_FLAVOR_INCOMPATIBLE'] . $sugar_flavor );
1845 if ( !function_exists('getInstallType') ) {
1846 function getInstallType( $type_string ){
1848 $subdirs = array('full', 'langpack', 'module', 'patch', 'theme', 'temp');
1849 foreach( $subdirs as $subdir ){
1850 if( preg_match( "#/$subdir/#", $type_string ) ){
1854 // return empty if no match
1861 //mysqli connector has a separate parameter for port.. We need to separate it out from the host name
1862 function getHostPortFromString($hostname=''){
1864 $pos=strpos($hostname,':');
1866 //no need to process as string is empty or does not contain ':' delimiter
1870 $hostArr = explode(':', $hostname);
1876 function getLicenseContents($filename)
1879 if(file_exists($filename) && filesize($filename) >0){
1880 $license_file = trim(file_get_contents($filename));
1882 return $license_file;
1892 ///////////////////////////////////////////////////////////////////////////////
1893 //// FROM POPULATE SEED DATA
1895 'qa', 'dev', 'beans',
1896 'info', 'sales', 'support',
1897 'kid', 'the', 'section',
1898 'sugar', 'hr', 'im',
1899 'kid', 'vegan', 'phone',
1902 ".com", ".org", ".net", ".tv", ".cn", ".co.jp", ".us",
1903 ".edu", ".tw", ".de", ".it", ".co.uk", ".info", ".biz",
1908 * creates a random, DNS-clean webaddress
1910 function createWebAddress() {
1914 $one = $seed[rand(0, count($seed)-1)];
1915 $two = $seed[rand(0, count($seed)-1)];
1916 $tld = $tlds[rand(0, count($tlds)-1)];
1918 return "www.{$one}{$two}{$tld}";
1922 * creates a random email address
1925 function createEmailAddress() {
1929 $part[0] = $seed[rand(0, count($seed)-1)];
1930 $part[1] = $seed[rand(0, count($seed)-1)];
1931 $part[2] = $seed[rand(0, count($seed)-1)];
1933 $tld = $tlds[rand(0, count($tlds)-1)];
1938 for($i=0; $i<$len; $i++) {
1939 $ret .= (empty($ret)) ? '' : '.';
1944 $ret .= rand(10, 99);
1947 return "{$ret}@example{$tld}";
1951 function add_digits($quantity, &$string, $min = 0, $max = 9) {
1952 for($i=0; $i < $quantity; $i++) {
1953 $string .= mt_rand($min,$max);
1957 function create_phone_number() {
1959 add_digits(3, $phone);
1961 add_digits(3, $phone);
1963 add_digits(4, $phone);
1968 function create_date($year=null,$mnth=null,$day=null)
1971 $now = $timedate->getNow();
1972 if ($day==null) $day=$now->day+mt_rand(0,365);
1973 return $timedate->asDbDate($now->get_day_begin($day, $mnth, $year));
1976 function create_current_date_time()
1979 return $timedate->nowDb();
1982 function create_time($hr=null,$min=null,$sec=null)
1985 $date = TimeDate::fromTimestamp(0);
1986 if ($hr==null) $hr=mt_rand(6,19);
1987 if ($min==null) $min=(mt_rand(0,3)*15);
1988 if ($sec==null) $sec=0;
1989 return $timedate->asDbTime($date->setDate(2007, 10, 7)->setTime($hr, $min, $sec));
1992 function create_past_date()
1995 $now = $timedate->getNow(true);
1996 $day=$now->day-mt_rand(1, 365);
1997 return $timedate->asDbDate($now->get_day_begin($day));
2001 * This method will look for a file modules_post_install.php in the root directory and based on the
2002 * contents of this file, it will silently install any modules as specified in this array.
2004 function post_install_modules(){
2005 if(is_file('modules_post_install.php')){
2006 global $current_user, $mod_strings;
2007 $current_user = new User();
2008 $current_user->is_admin = '1';
2009 require_once('ModuleInstall/PackageManager/PackageManager.php');
2010 require_once('modules_post_install.php');
2011 //we now have the $modules_to_install array in memory
2012 $pm = new PackageManager();
2013 $old_mod_strings = $mod_strings;
2014 foreach($modules_to_install as $module_to_install){
2015 if(is_file($module_to_install)){
2016 $pm->performSetup($module_to_install, 'module', false);
2017 $file_to_install = sugar_cached('upload/upgrades/module/').basename($module_to_install);
2018 $_REQUEST['install_file'] = $file_to_install;
2019 $pm->performInstall($file_to_install);
2022 $mod_strings = $old_mod_strings;
2026 function get_help_button_url(){
2027 $help_url = 'http://www.sugarcrm.com/docs/Administration_Guides/CommunityEdition_Admin_Guide_5.0/toc.html';
2032 function create_db_user_creds($numChars=10){
2033 $numChars = 7; // number of chars in the password
2034 //chars to select from
2035 $charBKT = "abcdefghijklmnpqrstuvwxyz123456789ABCDEFGHIJKLMNPQRSTUVWXYZ";
2036 // seed the random number generator
2037 srand((double)microtime()*1000000);
2039 for ($i=0;$i<$numChars;$i++) // loop and create password
2040 $password = $password . substr ($charBKT, rand() % strlen($charBKT), 1);
2046 function addDefaultRoles($defaultRoles = array()) {
2050 foreach($defaultRoles as $roleName=>$role){
2051 $ACLField = new ACLField();
2052 $role1= new ACLRole();
2053 $role1->name = $roleName;
2054 $role1->description = $roleName." Role";
2055 $role1_id=$role1->save();
2056 foreach($role as $category=>$actions){
2057 foreach($actions as $name=>$access_override){
2058 if($name=='fields'){
2059 foreach($access_override as $field_id=>$access){
2060 $ACLField->setAccessControl($category, $role1_id, $field_id, $access);
2063 $queryACL="SELECT id FROM acl_actions where category='$category' and name='$name'";
2064 $result = $db->query($queryACL);
2065 $actionId=$db->fetchByAssoc($result);
2066 if (isset($actionId['id']) && !empty($actionId['id'])){
2067 $role1->setAction($role1_id, $actionId['id'], $access_override);
2076 * Fully enable SugarFeeds, enabling the user feed and all available modules that have SugarFeed data.
2078 function enableSugarFeeds()
2080 $admin = new Administration();
2081 $admin->saveSetting('sugarfeed','enabled','1');
2083 foreach ( SugarFeed::getAllFeedModules() as $module )
2084 SugarFeed::activateModuleFeed($module);
2086 check_logic_hook_file('Users','after_login', array(1, 'SugarFeed old feed entry remover', 'modules/SugarFeed/SugarFeedFlush.php', 'SugarFeedFlush', 'flushStaleEntries'));
2089 function create_writable_dir($dirname)
2091 if ((is_dir($dirname)) || @sugar_mkdir($dirname,0755)) {
2092 $ok = make_writable($dirname);
2095 installLog("ERROR: Cannot create writable dir $dirname");
2100 * Enable the InsideView connector for the four default modules.
2102 function enableInsideViewConnector()
2104 // Load up the existing mapping and hand it to the InsideView connector to have it setup the correct logic hooks
2105 $mapFile = 'modules/Connectors/connectors/sources/ext/rest/insideview/mapping.php';
2106 if ( file_exists('custom/'.$mapFile) ) {
2107 require('custom/'.$mapFile);
2112 require_once('modules/Connectors/connectors/sources/ext/rest/insideview/insideview.php');
2113 $source = new ext_rest_insideview();
2115 // $mapping is brought in from the mapping.php file above
2116 $source->saveMappingHook($mapping);