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 // for silent install
792 if(!empty($_SESSION['setup_fts_type']))
794 $sugar_config['full_text_engine'] = array($_SESSION['setup_fts_type'] => array('host'=> $_SESSION['setup_fts_host'], 'port' => $_SESSION['setup_fts_port']));
795 if (isset($_SESSION['setup_fts_hide_config']))
797 $sugar_config['hide_full_text_engine_config'] = $_SESSION['setup_fts_hide_config'];
801 /*nsingh(bug 22402): Consolidate logger settings under $config['logger'] as liked by the new logger! If log4pphp exists,
802 these settings will be overwritten by those in log4php.properties when the user access admin->system settings.*/
803 $sugar_config['logger'] =
804 array ('level'=>$setup_site_log_level,
807 'name' => 'sugarcrm',
808 'dateFormat' => '%c',
811 'suffix' => ''), // bug51583, change default suffix to blank for backwards comptability
814 $sugar_config['session_dir'] = $setup_site_session_path;
815 $sugar_config['site_url'] = $setup_site_url;
816 $sugar_config['sugar_version'] = $setup_sugar_version;
817 $sugar_config['tmp_dir'] = $cache_dir.'xml/';
818 $sugar_config['upload_dir'] = 'upload/';
819 // $sugar_config['use_php_code_json'] = returnPhpJsonStatus(); // true on error
820 if( isset($_SESSION['setup_site_sugarbeet_anonymous_stats']) ){
821 $sugar_config['sugarbeet'] = $_SESSION['setup_site_sugarbeet_anonymous_stats'];
823 $sugar_config['demoData'] = $_SESSION['demoData'];
824 if( isset( $setup_site_guid ) ){
825 $sugar_config['unique_key'] = $setup_site_guid;
827 if(empty($sugar_config['unique_key'])){
828 $sugar_config['unique_key'] = md5( create_guid() );
830 // add installed langs to config
831 // entry in upgrade_history comes AFTER table creation
832 if(isset($_SESSION['INSTALLED_LANG_PACKS']) && is_array($_SESSION['INSTALLED_LANG_PACKS']) && !empty($_SESSION['INSTALLED_LANG_PACKS'])) {
833 foreach($_SESSION['INSTALLED_LANG_PACKS'] as $langZip) {
834 $lang = getSugarConfigLanguageArray($langZip);
836 $exLang = explode('::', $lang);
837 if(is_array($exLang) && count($exLang) == 3) {
838 $sugar_config['languages'][$exLang[0]] = $exLang[1];
843 if(file_exists('install/lang.config.php')){
844 include('install/lang.config.php');
845 if(!empty($config['languages'])){
846 foreach($config['languages'] as $lang=>$label){
847 $sugar_config['languages'][$lang] = $label;
852 ksort($sugar_config);
853 $sugar_config_string = "<?php\n" .
854 '// created: ' . date('Y-m-d H:i:s') . "\n" .
856 var_export($sugar_config, true) .
858 if($is_writable && write_array_to_file( "sugar_config", $sugar_config, "config.php")) {
862 echo "<p>{$mod_strings['ERR_PERFORM_CONFIG_PHP_1']}</p>\n";
863 echo "<p>{$mod_strings['ERR_PERFORM_CONFIG_PHP_2']}</p>\n";
864 echo "<TEXTAREA rows=\"15\" cols=\"80\">".$sugar_config_string."</TEXTAREA>";
865 echo "<p>{$mod_strings['ERR_PERFORM_CONFIG_PHP_3']}</p>";
867 $bottle[] = $mod_strings['ERR_PERFORM_CONFIG_PHP_4'];
871 //Now merge the config_si.php settings into config.php
872 if(file_exists('config.php') && file_exists('config_si.php'))
874 require_once('modules/UpgradeWizard/uw_utils.php');
875 merge_config_si_settings(false, 'config.php', 'config_si.php');
879 //// END $sugar_config
880 ///////////////////////////////////////////////////////////////////////////////
884 * (re)write the .htaccess file to prevent browser access to the log file
886 function handleHtaccess(){
888 $ignoreCase = (substr_count(strtolower($_SERVER['SERVER_SOFTWARE']), 'apache/2') > 0)?'(?i)':'';
889 $htaccess_file = ".htaccess";
891 $restrict_str = <<<EOQ
893 # BEGIN SUGARCRM RESTRICTIONS
894 RedirectMatch 403 {$ignoreCase}.*\.log$
895 RedirectMatch 403 {$ignoreCase}/+not_imported_.*\.txt
896 RedirectMatch 403 {$ignoreCase}/+(soap|cache|xtemplate|data|examples|include|log4php|metadata|modules)/+.*\.(php|tpl)
897 RedirectMatch 403 {$ignoreCase}/+emailmandelivery\.php
898 RedirectMatch 403 {$ignoreCase}/+upload
899 RedirectMatch 403 {$ignoreCase}/+custom/+blowfish
900 RedirectMatch 403 {$ignoreCase}/+cache/+diagnostic
901 RedirectMatch 403 {$ignoreCase}/+files\.md5$
902 # END SUGARCRM RESTRICTIONS
905 $cache_headers = <<<EOQ
907 <FilesMatch "\.(jpg|png|gif|js|css|ico)$">
908 <IfModule mod_headers.c>
910 Header set Cache-Control "max-age=2592000"
911 Header set Expires "01 Jan 2112 00:00:00 GMT"
914 <IfModule mod_expires.c>
915 ExpiresByType text/css "access plus 1 month"
916 ExpiresByType text/javascript "access plus 1 month"
917 ExpiresByType application/x-javascript "access plus 1 month"
918 ExpiresByType image/gif "access plus 1 month"
919 ExpiresByType image/jpg "access plus 1 month"
920 ExpiresByType image/png "access plus 1 month"
923 if(file_exists($htaccess_file)){
924 $fp = fopen($htaccess_file, 'r');
926 while($line = fgets($fp)){
928 if(preg_match("/\s*#\s*BEGIN\s*SUGARCRM\s*RESTRICTIONS/i", $line))$skip = true;
929 if(!$skip)$contents .= $line;
930 if(preg_match("/\s*#\s*END\s*SUGARCRM\s*RESTRICTIONS/i", $line))$skip = false;
933 $status = file_put_contents($htaccess_file, $contents . $restrict_str . $cache_headers);
935 echo "<p>{$mod_strings['ERR_PERFORM_HTACCESS_1']}<span class=stop>{$htaccess_file}</span> {$mod_strings['ERR_PERFORM_HTACCESS_2']}</p>\n";
936 echo "<p>{$mod_strings['ERR_PERFORM_HTACCESS_3']}</p>\n";
943 * (re)write the web.config file to prevent browser access to the log file
945 function handleWebConfig()
947 if ( !isset($_SERVER['IIS_UrlRewriteModule']) ) {
951 global $setup_site_log_dir;
952 global $setup_site_log_file;
953 global $sugar_config;
955 // Bug 36968 - Fallback to using $sugar_config values when we are not calling this from the installer
956 if (empty($setup_site_log_file)) {
957 $setup_site_log_file = $sugar_config['log_file'];
958 if ( empty($sugar_config['log_file']) ) {
959 $setup_site_log_file = 'sugarcrm.log';
962 if (empty($setup_site_log_dir)) {
963 $setup_site_log_dir = $sugar_config['log_dir'];
964 if ( empty($sugar_config['log_dir']) ) {
965 $setup_site_log_dir = '.';
969 $prefix = $setup_site_log_dir.empty($setup_site_log_dir)?'':'/';
972 $config_array = array(
973 array('1'=> $prefix.str_replace('.','\\.',$setup_site_log_file).'\\.*' ,'2'=>'log_file_restricted.html'),
974 array('1'=> $prefix.'install.log' ,'2'=>'log_file_restricted.html'),
975 array('1'=> $prefix.'upgradeWizard.log' ,'2'=>'log_file_restricted.html'),
976 array('1'=> $prefix.'emailman.log' ,'2'=>'log_file_restricted.html'),
977 array('1'=>'not_imported_.*.txt' ,'2'=>'log_file_restricted.html'),
978 array('1'=>'XTemplate/(.*)/(.*).php' ,'2'=>'index.php'),
979 array('1'=>'data/(.*).php' ,'2'=>'index.php'),
980 array('1'=>'examples/(.*).php' ,'2'=>'index.php'),
981 array('1'=>'include/(.*).php' ,'2'=>'index.php'),
982 array('1'=>'include/(.*)/(.*).php' ,'2'=>'index.php'),
983 array('1'=>'log4php/(.*).php' ,'2'=>'index.php'),
984 array('1'=>'log4php/(.*)/(.*)' ,'2'=>'index.php'),
985 array('1'=>'metadata/(.*)/(.*).php' ,'2'=>'index.php'),
986 array('1'=>'modules/(.*)/(.*).php' ,'2'=>'index.php'),
987 array('1'=>'soap/(.*).php' ,'2'=>'index.php'),
988 array('1'=>'emailmandelivery.php' ,'2'=>'index.php'),
989 array('1'=>'cron.php' ,'2'=>'index.php'),
990 array('1'=> $sugar_config['upload_dir'].'.*' ,'2'=>'index.php'),
994 $xmldoc = new XMLWriter();
995 $xmldoc->openURI('web.config');
996 $xmldoc->setIndent(true);
997 $xmldoc->setIndentString(' ');
998 $xmldoc->startDocument('1.0','UTF-8');
999 $xmldoc->startElement('configuration');
1000 $xmldoc->startElement('system.webServer');
1001 $xmldoc->startElement('rewrite');
1002 $xmldoc->startElement('rules');
1003 for ($i = 0; $i < count($config_array); $i++) {
1004 $xmldoc->startElement('rule');
1005 $xmldoc->writeAttribute('name', "redirect$i");
1006 $xmldoc->writeAttribute('stopProcessing', 'true');
1007 $xmldoc->startElement('match');
1008 $xmldoc->writeAttribute('url', $config_array[$i]['1']);
1009 $xmldoc->endElement();
1010 $xmldoc->startElement('action');
1011 $xmldoc->writeAttribute('type', 'Redirect');
1012 $xmldoc->writeAttribute('url', $config_array[$i]['2']);
1013 $xmldoc->writeAttribute('redirectType', 'Found');
1014 $xmldoc->endElement();
1015 $xmldoc->endElement();
1017 $xmldoc->endElement();
1018 $xmldoc->endElement();
1019 $xmldoc->startElement('caching');
1020 $xmldoc->startElement('profiles');
1021 $xmldoc->startElement('remove');
1022 $xmldoc->writeAttribute('extension', ".php");
1023 $xmldoc->endElement();
1024 $xmldoc->endElement();
1025 $xmldoc->endElement();
1026 $xmldoc->startElement('staticContent');
1027 $xmldoc->startElement("clientCache");
1028 $xmldoc->writeAttribute('cacheControlMode', 'UseMaxAge');
1029 $xmldoc->writeAttribute('cacheControlMaxAge', '30.00:00:00');
1030 $xmldoc->endElement();
1031 $xmldoc->endElement();
1032 $xmldoc->endElement();
1033 $xmldoc->endElement();
1034 $xmldoc->endDocument();
1039 * Drop old tables if table exists and told to drop it
1041 function drop_table_install( &$focus ){
1045 $result = $db->tableExists($focus->table_name);
1048 $focus->drop_tables();
1049 $GLOBALS['log']->info("Dropped old ".$focus->table_name." table.");
1053 $GLOBALS['log']->info("Did not need to drop old ".$focus->table_name." table. It doesn't exist.");
1058 // Creating new tables if they don't exist.
1059 function create_table_if_not_exist( &$focus ){
1061 $table_created = false;
1063 // normal code follows
1064 $result = $db->tableExists($focus->table_name);
1066 $GLOBALS['log']->info("Table ".$focus->table_name." already exists.");
1068 $focus->create_tables();
1069 $GLOBALS['log']->info("Created ".$focus->table_name." table.");
1070 $table_created = true;
1072 return $table_created;
1077 function create_default_users(){
1079 global $setup_site_admin_password;
1080 global $setup_site_admin_user_name;
1081 global $create_default_user;
1082 global $sugar_config;
1084 require_once('install/UserDemoData.php');
1086 //Create default admin user
1089 $user->new_with_id = true;
1090 $user->last_name = 'Administrator';
1091 $user->user_name = $setup_site_admin_user_name;
1092 $user->title = "Administrator";
1093 $user->status = 'Active';
1094 $user->is_admin = true;
1095 $user->employee_status = 'Active';
1096 $user->user_hash = User::getPasswordHash($setup_site_admin_password);
1098 $user->picture = UserDemoData::_copy_user_image($user->id);
1102 if( $create_default_user ){
1103 $default_user = new User();
1104 $default_user->last_name = $sugar_config['default_user_name'];
1105 $default_user->user_name = $sugar_config['default_user_name'];
1106 $default_user->status = 'Active';
1107 if( isset($sugar_config['default_user_is_admin']) && $sugar_config['default_user_is_admin'] ){
1108 $default_user->is_admin = true;
1110 $default_user->user_hash = User::getPasswordHash($sugar_config['default_password']);
1111 $default_user->save();
1115 function set_admin_password( $password ) {
1118 $user_hash = User::getPasswordHash($password);
1120 $query = "update users set user_hash='$user_hash' where id='1'";
1125 function insert_default_settings(){
1127 global $setup_sugar_version;
1128 global $sugar_db_version;
1131 $db->query("INSERT INTO config (category, name, value) VALUES ('notify', 'fromaddress', 'do_not_reply@example.com')");
1132 $db->query("INSERT INTO config (category, name, value) VALUES ('notify', 'fromname', 'SugarCRM')");
1133 $db->query("INSERT INTO config (category, name, value) VALUES ('notify', 'send_by_default', '1')");
1134 $db->query("INSERT INTO config (category, name, value) VALUES ('notify', 'on', '1')");
1135 $db->query("INSERT INTO config (category, name, value) VALUES ('notify', 'send_from_assigning_user', '0')");
1136 /* cn: moved to OutboundEmail class
1137 $db->query("INSERT INTO config (category, name, value) VALUES ('mail', 'smtpserver', 'localhost')");
1138 $db->query("INSERT INTO config (category, name, value) VALUES ('mail', 'smtpport', '25')");
1139 $db->query("INSERT INTO config (category, name, value) VALUES ('mail', 'sendtype', 'smtp')");
1140 $db->query("INSERT INTO config (category, name, value) VALUES ('mail', 'smtpuser', '')");
1141 $db->query("INSERT INTO config (category, name, value) VALUES ('mail', 'smtppass', '')");
1142 $db->query("INSERT INTO config (category, name, value) VALUES ('mail', 'smtpauth_req', '0')");
1144 $db->query("INSERT INTO config (category, name, value) VALUES ('info', 'sugar_version', '" . $sugar_db_version . "')");
1145 $db->query("INSERT INTO config (category, name, value) VALUES ('MySettings', 'tab', '')");
1146 $db->query("INSERT INTO config (category, name, value) VALUES ('portal', 'on', '0')");
1150 //insert default tracker settings
1151 $db->query("INSERT INTO config (category, name, value) VALUES ('tracker', 'Tracker', '1')");
1155 $db->query( "INSERT INTO config (category, name, value) VALUES ( 'system', 'skypeout_on', '1')" );
1166 // Returns true if the given file/dir has been made writable (or is already
1168 function make_writable($file)
1172 if(is_file($file) || is_dir($file))
1174 if(is_writable($file))
1180 $original_fileperms = fileperms($file);
1182 // add user writable permission
1183 $new_fileperms = $original_fileperms | 0x0080;
1184 @sugar_chmod($file, $new_fileperms);
1186 if(is_writable($file))
1192 // add group writable permission
1193 $new_fileperms = $original_fileperms | 0x0010;
1194 @chmod($file, $new_fileperms);
1196 if(is_writable($file))
1202 // add world writable permission
1203 $new_fileperms = $original_fileperms | 0x0002;
1204 @chmod($file, $new_fileperms);
1206 if(is_writable($file))
1218 function recursive_make_writable($start_file)
1220 $ret_val = make_writable($start_file);
1222 if($ret_val && is_dir($start_file))
1224 // PHP 4 alternative to scandir()
1226 $dh = opendir($start_file);
1227 $filename = readdir($dh);
1228 while(!empty($filename))
1230 if($filename != '.' && $filename != '..' && $filename != '.svn')
1232 $files[] = $filename;
1235 $filename = readdir($dh);
1238 foreach($files as $file)
1240 $ret_val = recursive_make_writable($start_file . '/' . $file);
1244 $_SESSION['unwriteable_module_files'][dirname($file)] = dirname($file);
1245 $fnl_ret_val = false;
1252 $unwriteable_directory = is_dir($start_file) ? $start_file : dirname($start_file);
1253 if($unwriteable_directory[0] == '.'){$unwriteable_directory = substr($unwriteable_directory,1);}
1254 $_SESSION['unwriteable_module_files'][$unwriteable_directory] = $unwriteable_directory;
1255 $_SESSION['unwriteable_module_files']['failed'] = true;
1261 function recursive_is_writable($start_file)
1263 $ret_val = is_writable($start_file);
1265 if($ret_val && is_dir($start_file))
1267 // PHP 4 alternative to scandir()
1269 $dh = opendir($start_file);
1270 $filename = readdir($dh);
1271 while(!empty($filename))
1273 if($filename != '.' && $filename != '..' && $filename != '.svn')
1275 $files[] = $filename;
1278 $filename = readdir($dh);
1281 foreach($files as $file)
1283 $ret_val = recursive_is_writable($start_file . '/' . $file);
1295 // one place for form validation/conversion to boolean
1296 function get_boolean_from_request( $field ){
1297 if( !isset($_REQUEST[$field]) ){
1301 if( ($_REQUEST[$field] == 'on') || ($_REQUEST[$field] == 'yes') ){
1309 function stripslashes_checkstrings($value){
1310 if(is_string($value)){
1311 return stripslashes($value);
1317 function print_debug_array( $name, $debug_array ){
1318 ksort( $debug_array );
1320 print( "$name vars:\n" );
1323 foreach( $debug_array as $key => $value ){
1324 if( stristr( $key, "password" ) ){
1327 print( " [$key] => $value\n" );
1333 function print_debug_comment(){
1334 if( !empty($_REQUEST['debug']) ){
1335 $_SESSION['debug'] = $_REQUEST['debug'];
1338 if( !empty($_SESSION['debug']) && ($_SESSION['debug'] == 'true') ){
1339 print( "<!-- debug is on (to turn off, hit any page with 'debug=false' as a URL parameter.\n" );
1341 print_debug_array( "Session", $_SESSION );
1342 print_debug_array( "Request", $_REQUEST );
1343 print_debug_array( "Post", $_POST );
1344 print_debug_array( "Get", $_GET );
1350 function validate_systemOptions() {
1351 global $mod_strings;
1353 if(!empty($_SESSION['setup_db_type']) && trim($_SESSION['setup_db_type']) != '') {
1354 $db = DBManagerFactory::getTypeInstance($_SESSION['setup_db_type']);
1356 $_SESSION['setup_db_manager'] = get_class($db);
1360 $errors[] = "<span class='error'>".$mod_strings['ERR_DB_INVALID']."</span>";
1365 function validate_dbConfig() {
1366 global $mod_strings;
1367 require_once('install/checkDBSettings.php');
1368 return checkDBSettings(true);
1372 function validate_siteConfig($type){
1373 global $mod_strings;
1377 if(empty($_SESSION['setup_system_name'])){
1378 $errors[] = "<span class='error'>".$mod_strings['LBL_REQUIRED_SYSTEM_NAME']."</span>";
1380 if($_SESSION['setup_site_url'] == ''){
1381 $errors[] = "<span class='error'>".$mod_strings['ERR_URL_BLANK']."</span>";
1384 if($_SESSION['setup_site_admin_user_name'] == '') {
1385 $errors[] = "<span class='error'>".$mod_strings['ERR_ADMIN_USER_NAME_BLANK']."</span>";
1388 if($_SESSION['setup_site_admin_password'] == ''){
1389 $errors[] = "<span class='error'>".$mod_strings['ERR_ADMIN_PASS_BLANK']."</span>";
1392 if($_SESSION['setup_site_admin_password'] != $_SESSION['setup_site_admin_password_retype']){
1393 $errors[] = "<span class='error'>".$mod_strings['ERR_PASSWORD_MISMATCH']."</span>";
1396 if(!empty($_SESSION['setup_site_custom_session_path']) && $_SESSION['setup_site_session_path'] == ''){
1397 $errors[] = "<span class='error'>".$mod_strings['ERR_SESSION_PATH']."</span>";
1400 if(!empty($_SESSION['setup_site_custom_session_path']) && $_SESSION['setup_site_session_path'] != ''){
1401 if(is_dir($_SESSION['setup_site_session_path'])){
1402 if(!is_writable($_SESSION['setup_site_session_path'])){
1403 $errors[] = "<span class='error'>".$mod_strings['ERR_SESSION_DIRECTORY']."</span>";
1407 $errors[] = "<span class='error'>".$mod_strings['ERR_SESSION_DIRECTORY_NOT_EXISTS']."</span>";
1411 if(!empty($_SESSION['setup_site_custom_log_dir']) && $_SESSION['setup_site_log_dir'] == ''){
1412 $errors[] = "<span class='error'>".$mod_strings['ERR_LOG_DIRECTORY_NOT_EXISTS']."</span>";
1415 if(!empty($_SESSION['setup_site_custom_log_dir']) && $_SESSION['setup_site_log_dir'] != ''){
1416 if(is_dir($_SESSION['setup_site_log_dir'])){
1417 if(!is_writable($_SESSION['setup_site_log_dir'])) {
1418 $errors[] = "<span class='error'>".$mod_strings['ERR_LOG_DIRECTORY_NOT_WRITABLE']."</span>";
1422 $errors[] = "<span class='error'>".$mod_strings['ERR_LOG_DIRECTORY_NOT_EXISTS']."</span>";
1426 if(!empty($_SESSION['setup_site_specify_guid']) && $_SESSION['setup_site_guid'] == ''){
1427 $errors[] = "<span class='error'>".$mod_strings['ERR_SITE_GUID']."</span>";
1435 function pullSilentInstallVarsIntoSession() {
1436 global $mod_strings;
1437 global $sugar_config;
1440 if( file_exists('config_si.php') ){
1441 require_once('config_si.php');
1443 else if( empty($sugar_config_si) ){
1444 die( $mod_strings['ERR_SI_NO_CONFIG'] );
1447 $config_subset = array (
1448 'setup_site_url' => isset($sugar_config['site_url']) ? $sugar_config['site_url'] : '',
1449 'setup_db_host_name' => isset($sugar_config['dbconfig']['db_host_name']) ? $sugar_config['dbconfig']['db_host_name'] : '',
1450 'setup_db_host_instance' => isset($sugar_config['dbconfig']['db_host_instance']) ? $sugar_config['dbconfig']['db_host_instance'] : '',
1451 'setup_db_sugarsales_user' => isset($sugar_config['dbconfig']['db_user_name']) ? $sugar_config['dbconfig']['db_user_name'] : '',
1452 'setup_db_sugarsales_password' => isset($sugar_config['dbconfig']['db_password']) ? $sugar_config['dbconfig']['db_password'] : '',
1453 'setup_db_database_name' => isset($sugar_config['dbconfig']['db_name']) ? $sugar_config['dbconfig']['db_name'] : '',
1454 'setup_db_type' => isset($sugar_config['dbconfig']['db_type']) ? $sugar_config['dbconfig']['db_type'] : '',
1455 'setup_db_port_num' => isset($sugar_config['dbconfig']['db_port']) ? $sugar_config['dbconfig']['db_port'] : '',
1456 'setup_db_options' => !empty($sugar_config['dbconfigoptions']) ? $sugar_config['dbconfigoptions'] : array(),
1458 // third array of values derived from above values
1460 'setup_site_admin_password_retype' => $sugar_config_si['setup_site_admin_password'],
1461 'setup_db_sugarsales_password_retype' => $config_subset['setup_db_sugarsales_password'],
1464 $needles = array('setup_db_create_database','setup_db_create_sugarsales_user','setup_license_key_users',
1465 'setup_license_key_expire_date','setup_license_key', 'setup_num_lic_oc',
1466 'default_currency_iso4217', 'default_currency_name', 'default_currency_significant_digits',
1467 'default_currency_symbol', 'default_date_format', 'default_time_format', 'default_decimal_seperator',
1468 'default_export_charset', 'default_language', 'default_locale_name_format', 'default_number_grouping_seperator',
1469 'export_delimiter', 'cache_dir', 'setup_db_options');
1470 copyFromArray($sugar_config_si, $needles, $derived);
1471 $all_config_vars = array_merge( $config_subset, $sugar_config_si, $derived );
1473 // bug 16860 tyoung - trim leading and trailing whitespace from license_key
1474 if (isset($all_config_vars['setup_license_key'])) {
1475 $all_config_vars['setup_license_key'] = trim($all_config_vars['setup_license_key']);
1478 foreach( $all_config_vars as $key => $value ){
1479 $_SESSION[$key] = $value;
1484 * given an array it will check to determine if the key exists in the array, if so
1485 * it will addd to the return array
1487 * @param intput_array haystack to check
1488 * @param needles list of needles to search for
1489 * @param output_array the array to add the keys to
1491 function copyFromArray($input_array, $needles, $output_array){
1492 foreach($needles as $needle){
1493 if(isset($input_array[$needle])){
1494 $output_array[$needle] = $input_array[$needle];
1502 * handles language pack uploads - code based off of upload_file->final_move()
1503 * puts it into the cache/upload dir to be handed off to langPackUnpack();
1505 * @param object file UploadFile object
1506 * @return bool true if successful
1508 function langPackFinalMove($file) {
1509 global $sugar_config;
1510 //."upgrades/langpack/"
1511 $destination = $sugar_config['upload_dir'].$file->stored_file_name;
1512 if(!move_uploaded_file($_FILES[$file->field_name]['tmp_name'], $destination)) {
1513 die ("ERROR: can't move_uploaded_file to $destination. You should try making the directory writable by the webserver");
1518 function getLicenseDisplay($type, $manifest, $zipFile, $next_step, $license_file, $clean_file) {
1519 return PackageManagerDisplay::getLicenseDisplay($license_file, 'install.php', $next_step, $zipFile, $type, $manifest, $clean_file);
1524 * creates the remove/delete form for langpack page
1525 * @param string type commit/remove
1526 * @param string manifest path to manifest file
1527 * @param string zipFile path to uploaded zip file
1528 * @param int nextstep current step
1529 * @return string ret <form> for this package
1531 function getPackButton($type, $manifest, $zipFile, $next_step, $uninstallable='Yes', $showButtons=true) {
1532 global $mod_strings;
1534 $button = $mod_strings['LBL_LANG_BUTTON_COMMIT'];
1535 if($type == 'remove') {
1536 $button = $mod_strings['LBL_LANG_BUTTON_REMOVE'];
1537 } elseif($type == 'uninstall') {
1538 $button = $mod_strings['LBL_LANG_BUTTON_UNINSTALL'];
1541 $disabled = ($uninstallable == 'Yes') ? false : true;
1543 $ret = "<form name='delete{$zipFile}' action='install.php' method='POST'>
1544 <input type='hidden' name='current_step' value='{$next_step}'>
1545 <input type='hidden' name='goto' value='{$mod_strings['LBL_CHECKSYS_RECHECK']}'>
1546 <input type='hidden' name='languagePackAction' value='{$type}'>
1547 <input type='hidden' name='manifest' value='".urlencode($manifest)."'>
1548 <input type='hidden' name='zipFile' value='".urlencode($zipFile)."'>
1549 <input type='hidden' name='install_type' value='custom'>";
1550 if(!$disabled && $showButtons) {
1551 $ret .= "<input type='submit' value='{$button}' class='button'>";
1558 * finds all installed languages and returns an array with the names
1559 * @return array langs array of installed languages
1561 function getInstalledLanguages() {
1562 $langDir = 'include/language/';
1563 $dh = opendir($langDir);
1566 while($file = readdir($dh)) {
1567 if(substr($file, -3) == 'php') {
1576 * searches upgrade dir for lang pack files.
1578 * @return string HTML of available lang packs
1580 function getLangPacks($display_commit = true, $types = array('langpack'), $notice_text = '') {
1581 global $mod_strings;
1583 global $base_upgrade_dir;
1585 if(empty($notice_text)){
1586 $notice_text = $mod_strings['LBL_LANG_PACK_READY'];
1588 $ret = "<tr><td colspan=7 align=left>{$notice_text}</td></tr>";
1589 //$ret .="<table width='100%' cellpadding='0' cellspacing='0' border='0'>";
1591 <td width='20%' ><b>{$mod_strings['LBL_ML_NAME']}</b></td>
1592 <td width='15%' ><b>{$mod_strings['LBL_ML_VERSION']}</b></td>
1593 <td width='15%' ><b>{$mod_strings['LBL_ML_PUBLISHED']}</b></td>
1594 <td width='15%' ><b>{$mod_strings['LBL_ML_UNINSTALLABLE']}</b></td>
1595 <td width='20%' ><b>{$mod_strings['LBL_ML_DESCRIPTION']}</b></td>
1596 <td width='7%' ></td>
1597 <td width='1%' ></td>
1598 <td width='7%' ></td>
1602 // duh, new installs won't have the upgrade folders
1603 if(!is_dir($base_upgrade_dir)) {
1604 mkdir_recursive( $base_upgrade_dir);
1606 $subdirs = array('full', 'langpack', 'module', 'patch', 'theme', 'temp');
1607 foreach( $subdirs as $subdir ){
1608 mkdir_recursive( "$base_upgrade_dir/$subdir" );
1611 $files = findAllFiles($base_upgrade_dir, $files);
1613 unset($_SESSION['hidden_input']);
1615 foreach($files as $file) {
1616 if(!preg_match("#.*\.zip\$#", $file)) {
1620 // skip installed lang packs
1621 if(isset($_SESSION['INSTALLED_LANG_PACKS']) && in_array($file, $_SESSION['INSTALLED_LANG_PACKS'])) {
1625 // handle manifest.php
1626 $target_manifest = remove_file_extension( $file ) . '-manifest.php';
1627 $license_file = remove_file_extension( $file ) . '-license.txt';
1628 include($target_manifest);
1631 if(!in_array(strtolower($manifest['type']), $types))
1635 $md5_matches = array();
1636 if($manifest['type'] == 'module'){
1637 $uh = new UpgradeHistory();
1638 $upgrade_content = clean_path($file);
1639 $the_base = basename($upgrade_content);
1640 $the_md5 = md5_file($upgrade_content);
1641 $md5_matches = $uh->findByMd5($the_md5);
1644 if($manifest['type']!= 'module' || 0 == sizeof($md5_matches)){
1645 $name = empty($manifest['name']) ? $file : $manifest['name'];
1646 $version = empty($manifest['version']) ? '' : $manifest['version'];
1647 $published_date = empty($manifest['published_date']) ? '' : $manifest['published_date'];
1649 $description = empty($manifest['description']) ? 'None' : $manifest['description'];
1650 $uninstallable = empty($manifest['is_uninstallable']) ? 'No' : 'Yes';
1651 $manifest_type = $manifest['type'];
1652 $commitPackage = getPackButton('commit', $target_manifest, $file, $next_step);
1653 $deletePackage = getPackButton('remove', $target_manifest, $file, $next_step);
1654 //$ret .="<table width='100%' cellpadding='0' cellspacing='0' border='0'>";
1656 $ret .= "<td width='20%' >".$name."</td>";
1657 $ret .= "<td width='15%' >".$version."</td>";
1658 $ret .= "<td width='15%' >".$published_date."</td>";
1659 $ret .= "<td width='15%' >".$uninstallable."</td>";
1660 $ret .= "<td width='20%' >".$description."</td>";
1663 $ret .= "<td width='7%'>{$commitPackage}</td>";
1664 $ret .= "<td width='1%'></td>";
1665 $ret .= "<td width='7%'>{$deletePackage}</td>";
1666 $ret .= "</td></tr>";
1668 $clean_field_name = "accept_lic_".str_replace('.', '_', urlencode(basename($file)));
1670 if(is_file($license_file)){
1672 $ret .= "<tr><td colspan=6>";
1673 $ret .= getLicenseDisplay('commit', $target_manifest, $file, $next_step, $license_file, $clean_field_name);
1674 $ret .= "</td></tr>";
1675 $hidden_input .= "<input type='hidden' name='$clean_field_name' id='$clean_field_name' value='no'>";
1677 $hidden_input .= "<input type='hidden' name='$clean_field_name' id='$clean_field_name' value='yes'>";
1681 $_SESSION['hidden_input'] = $hidden_input;
1683 if(count($files) > 0 ) {
1684 $ret .= "</tr><td colspan=7>";
1685 $ret .= "<form name='commit' action='install.php' method='POST'>
1686 <input type='hidden' name='current_step' value='{$next_step}'>
1687 <input type='hidden' name='goto' value='Re-check'>
1688 <input type='hidden' name='languagePackAction' value='commit'>
1689 <input type='hidden' name='install_type' value='custom'>
1692 $ret .= "</td></tr>";
1694 $ret .= "</tr><td colspan=7><i>{$mod_strings['LBL_LANG_NO_PACKS']}</i></td></tr>";
1699 if ( !function_exists('extractFile') ) {
1700 function extractFile( $zip_file, $file_in_zip, $base_tmp_upgrade_dir){
1701 $my_zip_dir = mk_temp_dir( $base_tmp_upgrade_dir );
1702 unzip_file( $zip_file, $file_in_zip, $my_zip_dir );
1703 return( "$my_zip_dir/$file_in_zip" );
1707 if ( !function_exists('extractManifest') ) {
1708 function extractManifest( $zip_file,$base_tmp_upgrade_dir ) {
1709 return( extractFile( $zip_file, "manifest.php",$base_tmp_upgrade_dir ) );
1713 if ( !function_exists('unlinkTempFiles') ) {
1714 function unlinkTempFiles($manifest='', $zipFile='') {
1715 global $sugar_config;
1717 @unlink($_FILES['language_pack']['tmp_name']);
1718 if(!empty($manifest))
1720 if(!empty($zipFile)) {
1721 //@unlink($zipFile);
1722 $tmpZipFile = substr($zipFile, strpos($zipFile, 'langpack/') + 9, strlen($zipFile));
1723 @unlink($sugar_config['upload_dir'].$tmpZipFile);
1726 rmdir_recursive($sugar_config['upload_dir']."upgrades/temp");
1727 sugar_mkdir($sugar_config['upload_dir']."upgrades/temp");
1731 function langPackUnpack($unpack_type, $full_file)
1733 global $sugar_config;
1734 global $base_upgrade_dir;
1735 global $base_tmp_upgrade_dir;
1737 $manifest = array();
1738 if(!empty($full_file)){
1739 $base_filename = pathinfo(urldecode($full_file), PATHINFO_FILENAME );
1741 return "Empty filename supplied";
1743 $manifest_file = extractManifest($full_file, $base_tmp_upgrade_dir);
1744 if($unpack_type == 'module')
1745 $license_file = extractFile($full_file, 'LICENSE.txt', $base_tmp_upgrade_dir);
1747 if(is_file($manifest_file)) {
1749 if($unpack_type == 'module' && is_file($license_file)){
1750 copy($license_file, $base_upgrade_dir.'/'.$unpack_type.'/'.$base_filename."-license.txt");
1752 copy($manifest_file, $base_upgrade_dir.'/'.$unpack_type.'/'.$base_filename."-manifest.php");
1754 require_once( $manifest_file );
1755 validate_manifest( $manifest );
1756 $upgrade_zip_type = $manifest['type'];
1758 mkdir_recursive( "$base_upgrade_dir/$upgrade_zip_type" );
1759 $target_path = "$base_upgrade_dir/$upgrade_zip_type/$base_filename";
1760 $target_manifest = $target_path . "-manifest.php";
1762 if( isset($manifest['icon']) && $manifest['icon'] != "" ) {
1763 $icon_location = extractFile( $full_file, $manifest['icon'], $base_tmp_upgrade_dir );
1764 $path_parts = pathinfo( $icon_location );
1765 copy( $icon_location, $target_path . "-icon." . $path_parts['extension'] );
1768 // move file from uploads to cache
1769 // FIXME: where should it be?
1770 if( copy( $full_file , $target_path.".zip" ) ){
1771 copy( $manifest_file, $target_manifest );
1772 unlink($full_file); // remove tempFile
1773 return "The file $base_filename has been uploaded.<br>\n";
1775 unlinkTempFiles($manifest_file, $full_file);
1776 return "There was an error uploading the file, please try again!<br>\n";
1779 die("The zip file is missing a manifest.php file. Cannot proceed.");
1781 unlinkTempFiles($manifest_file, '');
1784 if ( !function_exists('validate_manifest') ) {
1785 function validate_manifest( $manifest ){
1786 // takes a manifest.php manifest array and validates contents
1788 global $sugar_version;
1789 global $sugar_flavor;
1790 global $mod_strings;
1792 if( !isset($manifest['type']) ){
1793 die($mod_strings['ERROR_MANIFEST_TYPE']);
1795 $type = $manifest['type'];
1796 if( getInstallType( "/$type/" ) == "" ){
1797 die($mod_strings['ERROR_PACKAGE_TYPE']. ": '" . $type . "'." );
1800 return true; // making this a bit more relaxed since we updated the language extraction and merge capabilities
1803 if( isset($manifest['acceptable_sugar_versions']) ){
1804 $version_ok = false;
1805 $matches_empty = true;
1806 if( isset($manifest['acceptable_sugar_versions']['exact_matches']) ){
1807 $matches_empty = false;
1808 foreach( $manifest['acceptable_sugar_versions']['exact_matches'] as $match ){
1809 if( $match == $sugar_version ){
1814 if( !$version_ok && isset($manifest['acceptable_sugar_versions']['regex_matches']) ){
1815 $matches_empty = false;
1816 foreach( $manifest['acceptable_sugar_versions']['regex_matches'] as $match ){
1817 if( preg_match( "/$match/", $sugar_version ) ){
1823 if( !$matches_empty && !$version_ok ){
1824 die( $mod_strings['ERROR_VERSION_INCOMPATIBLE'] . $sugar_version );
1828 if( isset($manifest['acceptable_sugar_flavors']) && sizeof($manifest['acceptable_sugar_flavors']) > 0 ){
1830 foreach( $manifest['acceptable_sugar_flavors'] as $match ){
1831 if( $match == $sugar_flavor ){
1836 //die( $mod_strings['ERROR_FLAVOR_INCOMPATIBLE'] . $sugar_flavor );
1842 if ( !function_exists('getInstallType') ) {
1843 function getInstallType( $type_string ){
1845 $subdirs = array('full', 'langpack', 'module', 'patch', 'theme', 'temp');
1846 foreach( $subdirs as $subdir ){
1847 if( preg_match( "#/$subdir/#", $type_string ) ){
1851 // return empty if no match
1858 //mysqli connector has a separate parameter for port.. We need to separate it out from the host name
1859 function getHostPortFromString($hostname=''){
1861 $pos=strpos($hostname,':');
1863 //no need to process as string is empty or does not contain ':' delimiter
1867 $hostArr = explode(':', $hostname);
1873 function getLicenseContents($filename)
1876 if(file_exists($filename) && filesize($filename) >0){
1877 $license_file = trim(file_get_contents($filename));
1879 return $license_file;
1889 ///////////////////////////////////////////////////////////////////////////////
1890 //// FROM POPULATE SEED DATA
1892 'qa', 'dev', 'beans',
1893 'info', 'sales', 'support',
1894 'kid', 'the', 'section',
1895 'sugar', 'hr', 'im',
1896 'kid', 'vegan', 'phone',
1899 ".com", ".org", ".net", ".tv", ".cn", ".co.jp", ".us",
1900 ".edu", ".tw", ".de", ".it", ".co.uk", ".info", ".biz",
1905 * creates a random, DNS-clean webaddress
1907 function createWebAddress() {
1911 $one = $seed[rand(0, count($seed)-1)];
1912 $two = $seed[rand(0, count($seed)-1)];
1913 $tld = $tlds[rand(0, count($tlds)-1)];
1915 return "www.{$one}{$two}{$tld}";
1919 * creates a random email address
1922 function createEmailAddress() {
1926 $part[0] = $seed[rand(0, count($seed)-1)];
1927 $part[1] = $seed[rand(0, count($seed)-1)];
1928 $part[2] = $seed[rand(0, count($seed)-1)];
1930 $tld = $tlds[rand(0, count($tlds)-1)];
1935 for($i=0; $i<$len; $i++) {
1936 $ret .= (empty($ret)) ? '' : '.';
1941 $ret .= rand(10, 99);
1944 return "{$ret}@example{$tld}";
1948 function add_digits($quantity, &$string, $min = 0, $max = 9) {
1949 for($i=0; $i < $quantity; $i++) {
1950 $string .= mt_rand($min,$max);
1954 function create_phone_number() {
1956 add_digits(3, $phone);
1958 add_digits(3, $phone);
1960 add_digits(4, $phone);
1965 function create_date($year=null,$mnth=null,$day=null)
1968 $now = $timedate->getNow();
1969 if ($day==null) $day=$now->day+mt_rand(0,365);
1970 return $timedate->asDbDate($now->get_day_begin($day, $mnth, $year));
1973 function create_current_date_time()
1976 return $timedate->nowDb();
1979 function create_time($hr=null,$min=null,$sec=null)
1982 $date = TimeDate::fromTimestamp(0);
1983 if ($hr==null) $hr=mt_rand(6,19);
1984 if ($min==null) $min=(mt_rand(0,3)*15);
1985 if ($sec==null) $sec=0;
1986 return $timedate->asDbTime($date->setDate(2007, 10, 7)->setTime($hr, $min, $sec));
1989 function create_past_date()
1992 $now = $timedate->getNow(true);
1993 $day=$now->day-mt_rand(1, 365);
1994 return $timedate->asDbDate($now->get_day_begin($day));
1998 * This method will look for a file modules_post_install.php in the root directory and based on the
1999 * contents of this file, it will silently install any modules as specified in this array.
2001 function post_install_modules(){
2002 if(is_file('modules_post_install.php')){
2003 global $current_user, $mod_strings;
2004 $current_user = new User();
2005 $current_user->is_admin = '1';
2006 require_once('ModuleInstall/PackageManager/PackageManager.php');
2007 require_once('modules_post_install.php');
2008 //we now have the $modules_to_install array in memory
2009 $pm = new PackageManager();
2010 $old_mod_strings = $mod_strings;
2011 foreach($modules_to_install as $module_to_install){
2012 if(is_file($module_to_install)){
2013 $pm->performSetup($module_to_install, 'module', false);
2014 $file_to_install = sugar_cached('upload/upgrades/module/').basename($module_to_install);
2015 $_REQUEST['install_file'] = $file_to_install;
2016 $pm->performInstall($file_to_install);
2019 $mod_strings = $old_mod_strings;
2023 function get_help_button_url(){
2024 $help_url = 'http://www.sugarcrm.com/docs/Administration_Guides/CommunityEdition_Admin_Guide_5.0/toc.html';
2029 function create_db_user_creds($numChars=10){
2030 $numChars = 7; // number of chars in the password
2031 //chars to select from
2032 $charBKT = "abcdefghijklmnpqrstuvwxyz123456789ABCDEFGHIJKLMNPQRSTUVWXYZ";
2033 // seed the random number generator
2034 srand((double)microtime()*1000000);
2036 for ($i=0;$i<$numChars;$i++) // loop and create password
2037 $password = $password . substr ($charBKT, rand() % strlen($charBKT), 1);
2043 function addDefaultRoles($defaultRoles = array()) {
2047 foreach($defaultRoles as $roleName=>$role){
2048 $ACLField = new ACLField();
2049 $role1= new ACLRole();
2050 $role1->name = $roleName;
2051 $role1->description = $roleName." Role";
2052 $role1_id=$role1->save();
2053 foreach($role as $category=>$actions){
2054 foreach($actions as $name=>$access_override){
2055 if($name=='fields'){
2056 foreach($access_override as $field_id=>$access){
2057 $ACLField->setAccessControl($category, $role1_id, $field_id, $access);
2060 $queryACL="SELECT id FROM acl_actions where category='$category' and name='$name'";
2061 $result = $db->query($queryACL);
2062 $actionId=$db->fetchByAssoc($result);
2063 if (isset($actionId['id']) && !empty($actionId['id'])){
2064 $role1->setAction($role1_id, $actionId['id'], $access_override);
2073 * Fully enable SugarFeeds, enabling the user feed and all available modules that have SugarFeed data.
2075 function enableSugarFeeds()
2077 $admin = new Administration();
2078 $admin->saveSetting('sugarfeed','enabled','1');
2080 foreach ( SugarFeed::getAllFeedModules() as $module )
2081 SugarFeed::activateModuleFeed($module);
2083 check_logic_hook_file('Users','after_login', array(1, 'SugarFeed old feed entry remover', 'modules/SugarFeed/SugarFeedFlush.php', 'SugarFeedFlush', 'flushStaleEntries'));
2086 function create_writable_dir($dirname)
2088 if ((is_dir($dirname)) || @sugar_mkdir($dirname,0755)) {
2089 $ok = make_writable($dirname);
2092 installLog("ERROR: Cannot create writable dir $dirname");
2097 * Enable the InsideView connector for the four default modules.
2099 function enableInsideViewConnector()
2101 // Load up the existing mapping and hand it to the InsideView connector to have it setup the correct logic hooks
2102 $mapFile = 'modules/Connectors/connectors/sources/ext/rest/insideview/mapping.php';
2103 if ( file_exists('custom/'.$mapFile) ) {
2104 require('custom/'.$mapFile);
2109 require_once('modules/Connectors/connectors/sources/ext/rest/insideview/insideview.php');
2110 $source = new ext_rest_insideview();
2112 // $mapping is brought in from the mapping.php file above
2113 $source->saveMappingHook($mapping);