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-2013 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 occurred when creating user:<br>";
629 installLog("An error occurred 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
896 if (ini_get('suhosin.perdir') !== false && strpos(ini_get('suhosin.perdir'), 'e') !== false)
898 $restrict_str .= "php_value suhosin.executor.include.whitelist upload\n";
900 $restrict_str .= <<<EOQ
901 RedirectMatch 403 {$ignoreCase}.*\.log$
902 RedirectMatch 403 {$ignoreCase}/+not_imported_.*\.txt
903 RedirectMatch 403 {$ignoreCase}/+(soap|cache|xtemplate|data|examples|include|log4php|metadata|modules)/+.*\.(php|tpl)
904 RedirectMatch 403 {$ignoreCase}/+emailmandelivery\.php
905 RedirectMatch 403 {$ignoreCase}/+upload
906 RedirectMatch 403 {$ignoreCase}/+custom/+blowfish
907 RedirectMatch 403 {$ignoreCase}/+cache/+diagnostic
908 RedirectMatch 403 {$ignoreCase}/+files\.md5$
909 # END SUGARCRM RESTRICTIONS
912 $cache_headers = <<<EOQ
914 <FilesMatch "\.(jpg|png|gif|js|css|ico)$">
915 <IfModule mod_headers.c>
917 Header set Cache-Control "max-age=2592000"
918 Header set Expires "01 Jan 2112 00:00:00 GMT"
921 <IfModule mod_expires.c>
922 ExpiresByType text/css "access plus 1 month"
923 ExpiresByType text/javascript "access plus 1 month"
924 ExpiresByType application/x-javascript "access plus 1 month"
925 ExpiresByType image/gif "access plus 1 month"
926 ExpiresByType image/jpg "access plus 1 month"
927 ExpiresByType image/png "access plus 1 month"
930 if(file_exists($htaccess_file)){
931 $fp = fopen($htaccess_file, 'r');
933 while($line = fgets($fp)){
935 if(preg_match("/\s*#\s*BEGIN\s*SUGARCRM\s*RESTRICTIONS/i", $line))$skip = true;
936 if(!$skip)$contents .= $line;
937 if(preg_match("/\s*#\s*END\s*SUGARCRM\s*RESTRICTIONS/i", $line))$skip = false;
940 $status = file_put_contents($htaccess_file, $contents . $restrict_str . $cache_headers);
942 echo "<p>{$mod_strings['ERR_PERFORM_HTACCESS_1']}<span class=stop>{$htaccess_file}</span> {$mod_strings['ERR_PERFORM_HTACCESS_2']}</p>\n";
943 echo "<p>{$mod_strings['ERR_PERFORM_HTACCESS_3']}</p>\n";
950 * (re)write the web.config file to prevent browser access to the log file
952 function handleWebConfig()
954 if ( !isset($_SERVER['IIS_UrlRewriteModule']) ) {
958 global $setup_site_log_dir;
959 global $setup_site_log_file;
960 global $sugar_config;
962 // Bug 36968 - Fallback to using $sugar_config values when we are not calling this from the installer
963 if (empty($setup_site_log_file)) {
964 $setup_site_log_file = $sugar_config['log_file'];
965 if ( empty($sugar_config['log_file']) ) {
966 $setup_site_log_file = 'sugarcrm.log';
969 if (empty($setup_site_log_dir)) {
970 $setup_site_log_dir = $sugar_config['log_dir'];
971 if ( empty($sugar_config['log_dir']) ) {
972 $setup_site_log_dir = '.';
976 $prefix = $setup_site_log_dir.empty($setup_site_log_dir)?'':'/';
979 $config_array = array(
980 array('1'=> $prefix.str_replace('.','\\.',$setup_site_log_file).'\\.*' ,'2'=>'log_file_restricted.html'),
981 array('1'=> $prefix.'install.log' ,'2'=>'log_file_restricted.html'),
982 array('1'=> $prefix.'upgradeWizard.log' ,'2'=>'log_file_restricted.html'),
983 array('1'=> $prefix.'emailman.log' ,'2'=>'log_file_restricted.html'),
984 array('1'=>'not_imported_.*.txt' ,'2'=>'log_file_restricted.html'),
985 array('1'=>'XTemplate/(.*)/(.*).php' ,'2'=>'index.php'),
986 array('1'=>'data/(.*).php' ,'2'=>'index.php'),
987 array('1'=>'examples/(.*).php' ,'2'=>'index.php'),
988 array('1'=>'include/(.*).php' ,'2'=>'index.php'),
989 array('1'=>'include/(.*)/(.*).php' ,'2'=>'index.php'),
990 array('1'=>'log4php/(.*).php' ,'2'=>'index.php'),
991 array('1'=>'log4php/(.*)/(.*)' ,'2'=>'index.php'),
992 array('1'=>'metadata/(.*)/(.*).php' ,'2'=>'index.php'),
993 array('1'=>'modules/(.*)/(.*).php' ,'2'=>'index.php'),
994 array('1'=>'soap/(.*).php' ,'2'=>'index.php'),
995 array('1'=>'emailmandelivery.php' ,'2'=>'index.php'),
996 array('1'=>'cron.php' ,'2'=>'index.php'),
997 array('1'=> $sugar_config['upload_dir'].'.*' ,'2'=>'index.php'),
1001 $xmldoc = new XMLWriter();
1002 $xmldoc->openURI('web.config');
1003 $xmldoc->setIndent(true);
1004 $xmldoc->setIndentString(' ');
1005 $xmldoc->startDocument('1.0','UTF-8');
1006 $xmldoc->startElement('configuration');
1007 $xmldoc->startElement('system.webServer');
1008 $xmldoc->startElement('rewrite');
1009 $xmldoc->startElement('rules');
1010 for ($i = 0; $i < count($config_array); $i++) {
1011 $xmldoc->startElement('rule');
1012 $xmldoc->writeAttribute('name', "redirect$i");
1013 $xmldoc->writeAttribute('stopProcessing', 'true');
1014 $xmldoc->startElement('match');
1015 $xmldoc->writeAttribute('url', $config_array[$i]['1']);
1016 $xmldoc->endElement();
1017 $xmldoc->startElement('action');
1018 $xmldoc->writeAttribute('type', 'Redirect');
1019 $xmldoc->writeAttribute('url', $config_array[$i]['2']);
1020 $xmldoc->writeAttribute('redirectType', 'Found');
1021 $xmldoc->endElement();
1022 $xmldoc->endElement();
1024 $xmldoc->endElement();
1025 $xmldoc->endElement();
1026 $xmldoc->startElement('caching');
1027 $xmldoc->startElement('profiles');
1028 $xmldoc->startElement('remove');
1029 $xmldoc->writeAttribute('extension', ".php");
1030 $xmldoc->endElement();
1031 $xmldoc->endElement();
1032 $xmldoc->endElement();
1033 $xmldoc->startElement('staticContent');
1034 $xmldoc->startElement("clientCache");
1035 $xmldoc->writeAttribute('cacheControlMode', 'UseMaxAge');
1036 $xmldoc->writeAttribute('cacheControlMaxAge', '30.00:00:00');
1037 $xmldoc->endElement();
1038 $xmldoc->endElement();
1039 $xmldoc->endElement();
1040 $xmldoc->endElement();
1041 $xmldoc->endDocument();
1046 * Drop old tables if table exists and told to drop it
1048 function drop_table_install( &$focus ){
1052 $result = $db->tableExists($focus->table_name);
1055 $focus->drop_tables();
1056 $GLOBALS['log']->info("Dropped old ".$focus->table_name." table.");
1060 $GLOBALS['log']->info("Did not need to drop old ".$focus->table_name." table. It doesn't exist.");
1065 // Creating new tables if they don't exist.
1066 function create_table_if_not_exist( &$focus ){
1068 $table_created = false;
1070 // normal code follows
1071 $result = $db->tableExists($focus->table_name);
1073 $GLOBALS['log']->info("Table ".$focus->table_name." already exists.");
1075 $focus->create_tables();
1076 $GLOBALS['log']->info("Created ".$focus->table_name." table.");
1077 $table_created = true;
1079 return $table_created;
1084 function create_default_users(){
1086 global $setup_site_admin_password;
1087 global $setup_site_admin_user_name;
1088 global $create_default_user;
1089 global $sugar_config;
1091 require_once('install/UserDemoData.php');
1093 //Create default admin user
1096 $user->new_with_id = true;
1097 $user->last_name = 'Administrator';
1098 $user->user_name = $setup_site_admin_user_name;
1099 $user->title = "Administrator";
1100 $user->status = 'Active';
1101 $user->is_admin = true;
1102 $user->employee_status = 'Active';
1103 $user->user_hash = User::getPasswordHash($setup_site_admin_password);
1105 $user->picture = UserDemoData::_copy_user_image($user->id);
1107 //Bug#53793: Keep default current user in the global variable in order to store 'created_by' info as default user
1108 // while installation is proceed.
1109 $GLOBALS['current_user'] = $user;
1112 if( $create_default_user ){
1113 $default_user = new User();
1114 $default_user->last_name = $sugar_config['default_user_name'];
1115 $default_user->user_name = $sugar_config['default_user_name'];
1116 $default_user->status = 'Active';
1117 if( isset($sugar_config['default_user_is_admin']) && $sugar_config['default_user_is_admin'] ){
1118 $default_user->is_admin = true;
1120 $default_user->user_hash = User::getPasswordHash($sugar_config['default_password']);
1121 $default_user->save();
1125 function set_admin_password( $password ) {
1128 $user_hash = User::getPasswordHash($password);
1130 $query = "update users set user_hash='$user_hash' where id='1'";
1135 function insert_default_settings(){
1137 global $setup_sugar_version;
1138 global $sugar_db_version;
1141 $db->query("INSERT INTO config (category, name, value) VALUES ('notify', 'fromaddress', 'do_not_reply@example.com')");
1142 $db->query("INSERT INTO config (category, name, value) VALUES ('notify', 'fromname', 'SugarCRM')");
1143 $db->query("INSERT INTO config (category, name, value) VALUES ('notify', 'send_by_default', '1')");
1144 $db->query("INSERT INTO config (category, name, value) VALUES ('notify', 'on', '1')");
1145 $db->query("INSERT INTO config (category, name, value) VALUES ('notify', 'send_from_assigning_user', '0')");
1146 /* cn: moved to OutboundEmail class
1147 $db->query("INSERT INTO config (category, name, value) VALUES ('mail', 'smtpserver', 'localhost')");
1148 $db->query("INSERT INTO config (category, name, value) VALUES ('mail', 'smtpport', '25')");
1149 $db->query("INSERT INTO config (category, name, value) VALUES ('mail', 'sendtype', 'smtp')");
1150 $db->query("INSERT INTO config (category, name, value) VALUES ('mail', 'smtpuser', '')");
1151 $db->query("INSERT INTO config (category, name, value) VALUES ('mail', 'smtppass', '')");
1152 $db->query("INSERT INTO config (category, name, value) VALUES ('mail', 'smtpauth_req', '0')");
1154 $db->query("INSERT INTO config (category, name, value) VALUES ('info', 'sugar_version', '" . $sugar_db_version . "')");
1155 $db->query("INSERT INTO config (category, name, value) VALUES ('MySettings', 'tab', '')");
1156 $db->query("INSERT INTO config (category, name, value) VALUES ('portal', 'on', '0')");
1160 //insert default tracker settings
1161 $db->query("INSERT INTO config (category, name, value) VALUES ('tracker', 'Tracker', '1')");
1165 $db->query( "INSERT INTO config (category, name, value) VALUES ( 'system', 'skypeout_on', '1')" );
1176 // Returns true if the given file/dir has been made writable (or is already
1178 function make_writable($file)
1182 if(is_file($file) || is_dir($file))
1184 if(is_writable($file))
1190 $original_fileperms = fileperms($file);
1192 // add user writable permission
1193 $new_fileperms = $original_fileperms | 0x0080;
1194 @sugar_chmod($file, $new_fileperms);
1196 if(is_writable($file))
1202 // add group writable permission
1203 $new_fileperms = $original_fileperms | 0x0010;
1204 @chmod($file, $new_fileperms);
1206 if(is_writable($file))
1212 // add world writable permission
1213 $new_fileperms = $original_fileperms | 0x0002;
1214 @chmod($file, $new_fileperms);
1216 if(is_writable($file))
1228 function recursive_make_writable($start_file)
1230 $ret_val = make_writable($start_file);
1232 if($ret_val && is_dir($start_file))
1234 // PHP 4 alternative to scandir()
1236 $dh = opendir($start_file);
1237 $filename = readdir($dh);
1238 while(!empty($filename))
1240 if($filename != '.' && $filename != '..' && $filename != '.svn')
1242 $files[] = $filename;
1245 $filename = readdir($dh);
1248 foreach($files as $file)
1250 $ret_val = recursive_make_writable($start_file . '/' . $file);
1254 $_SESSION['unwriteable_module_files'][dirname($file)] = dirname($file);
1255 $fnl_ret_val = false;
1262 $unwriteable_directory = is_dir($start_file) ? $start_file : dirname($start_file);
1263 if($unwriteable_directory[0] == '.'){$unwriteable_directory = substr($unwriteable_directory,1);}
1264 $_SESSION['unwriteable_module_files'][$unwriteable_directory] = $unwriteable_directory;
1265 $_SESSION['unwriteable_module_files']['failed'] = true;
1271 function recursive_is_writable($start_file)
1273 $ret_val = is_writable($start_file);
1275 if($ret_val && is_dir($start_file))
1277 // PHP 4 alternative to scandir()
1279 $dh = opendir($start_file);
1280 $filename = readdir($dh);
1281 while(!empty($filename))
1283 if($filename != '.' && $filename != '..' && $filename != '.svn')
1285 $files[] = $filename;
1288 $filename = readdir($dh);
1291 foreach($files as $file)
1293 $ret_val = recursive_is_writable($start_file . '/' . $file);
1305 // one place for form validation/conversion to boolean
1306 function get_boolean_from_request( $field ){
1307 if( !isset($_REQUEST[$field]) ){
1311 if( ($_REQUEST[$field] == 'on') || ($_REQUEST[$field] == 'yes') ){
1319 function stripslashes_checkstrings($value){
1320 if(is_string($value)){
1321 return stripslashes($value);
1327 function print_debug_array( $name, $debug_array ){
1328 ksort( $debug_array );
1330 print( "$name vars:\n" );
1333 foreach( $debug_array as $key => $value ){
1334 if( stristr( $key, "password" ) ){
1337 print( " [$key] => $value\n" );
1343 function print_debug_comment(){
1344 if( !empty($_REQUEST['debug']) ){
1345 $_SESSION['debug'] = $_REQUEST['debug'];
1348 if( !empty($_SESSION['debug']) && ($_SESSION['debug'] == 'true') ){
1349 print( "<!-- debug is on (to turn off, hit any page with 'debug=false' as a URL parameter.\n" );
1351 print_debug_array( "Session", $_SESSION );
1352 print_debug_array( "Request", $_REQUEST );
1353 print_debug_array( "Post", $_POST );
1354 print_debug_array( "Get", $_GET );
1360 function validate_systemOptions() {
1361 global $mod_strings;
1363 if(!empty($_SESSION['setup_db_type']) && trim($_SESSION['setup_db_type']) != '') {
1364 $db = DBManagerFactory::getTypeInstance($_SESSION['setup_db_type']);
1366 $_SESSION['setup_db_manager'] = get_class($db);
1370 $errors[] = "<span class='error'>".$mod_strings['ERR_DB_INVALID']."</span>";
1375 function validate_dbConfig() {
1376 global $mod_strings;
1377 require_once('install/checkDBSettings.php');
1378 return checkDBSettings(true);
1382 function validate_siteConfig($type){
1383 global $mod_strings;
1387 if(empty($_SESSION['setup_system_name'])){
1388 $errors[] = "<span class='error'>".$mod_strings['LBL_REQUIRED_SYSTEM_NAME']."</span>";
1390 if($_SESSION['setup_site_url'] == ''){
1391 $errors[] = "<span class='error'>".$mod_strings['ERR_URL_BLANK']."</span>";
1394 if($_SESSION['setup_site_admin_user_name'] == '') {
1395 $errors[] = "<span class='error'>".$mod_strings['ERR_ADMIN_USER_NAME_BLANK']."</span>";
1398 if($_SESSION['setup_site_admin_password'] == ''){
1399 $errors[] = "<span class='error'>".$mod_strings['ERR_ADMIN_PASS_BLANK']."</span>";
1402 if($_SESSION['setup_site_admin_password'] != $_SESSION['setup_site_admin_password_retype']){
1403 $errors[] = "<span class='error'>".$mod_strings['ERR_PASSWORD_MISMATCH']."</span>";
1406 if(!empty($_SESSION['setup_site_custom_session_path']) && $_SESSION['setup_site_session_path'] == ''){
1407 $errors[] = "<span class='error'>".$mod_strings['ERR_SESSION_PATH']."</span>";
1410 if(!empty($_SESSION['setup_site_custom_session_path']) && $_SESSION['setup_site_session_path'] != ''){
1411 if(is_dir($_SESSION['setup_site_session_path'])){
1412 if(!is_writable($_SESSION['setup_site_session_path'])){
1413 $errors[] = "<span class='error'>".$mod_strings['ERR_SESSION_DIRECTORY']."</span>";
1417 $errors[] = "<span class='error'>".$mod_strings['ERR_SESSION_DIRECTORY_NOT_EXISTS']."</span>";
1421 if(!empty($_SESSION['setup_site_custom_log_dir']) && $_SESSION['setup_site_log_dir'] == ''){
1422 $errors[] = "<span class='error'>".$mod_strings['ERR_LOG_DIRECTORY_NOT_EXISTS']."</span>";
1425 if(!empty($_SESSION['setup_site_custom_log_dir']) && $_SESSION['setup_site_log_dir'] != ''){
1426 if(is_dir($_SESSION['setup_site_log_dir'])){
1427 if(!is_writable($_SESSION['setup_site_log_dir'])) {
1428 $errors[] = "<span class='error'>".$mod_strings['ERR_LOG_DIRECTORY_NOT_WRITABLE']."</span>";
1432 $errors[] = "<span class='error'>".$mod_strings['ERR_LOG_DIRECTORY_NOT_EXISTS']."</span>";
1436 if(!empty($_SESSION['setup_site_specify_guid']) && $_SESSION['setup_site_guid'] == ''){
1437 $errors[] = "<span class='error'>".$mod_strings['ERR_SITE_GUID']."</span>";
1445 function pullSilentInstallVarsIntoSession() {
1446 global $mod_strings;
1447 global $sugar_config;
1450 if( file_exists('config_si.php') ){
1451 require_once('config_si.php');
1453 else if( empty($sugar_config_si) ){
1454 die( $mod_strings['ERR_SI_NO_CONFIG'] );
1457 $config_subset = array (
1458 'setup_site_url' => isset($sugar_config['site_url']) ? $sugar_config['site_url'] : '',
1459 'setup_db_host_name' => isset($sugar_config['dbconfig']['db_host_name']) ? $sugar_config['dbconfig']['db_host_name'] : '',
1460 'setup_db_host_instance' => isset($sugar_config['dbconfig']['db_host_instance']) ? $sugar_config['dbconfig']['db_host_instance'] : '',
1461 'setup_db_sugarsales_user' => isset($sugar_config['dbconfig']['db_user_name']) ? $sugar_config['dbconfig']['db_user_name'] : '',
1462 'setup_db_sugarsales_password' => isset($sugar_config['dbconfig']['db_password']) ? $sugar_config['dbconfig']['db_password'] : '',
1463 'setup_db_database_name' => isset($sugar_config['dbconfig']['db_name']) ? $sugar_config['dbconfig']['db_name'] : '',
1464 'setup_db_type' => isset($sugar_config['dbconfig']['db_type']) ? $sugar_config['dbconfig']['db_type'] : '',
1465 'setup_db_port_num' => isset($sugar_config['dbconfig']['db_port']) ? $sugar_config['dbconfig']['db_port'] : '',
1466 'setup_db_options' => !empty($sugar_config['dbconfigoptions']) ? $sugar_config['dbconfigoptions'] : array(),
1468 // third array of values derived from above values
1470 'setup_site_admin_password_retype' => $sugar_config_si['setup_site_admin_password'],
1471 'setup_db_sugarsales_password_retype' => $config_subset['setup_db_sugarsales_password'],
1474 $needles = array('setup_db_create_database','setup_db_create_sugarsales_user','setup_license_key_users',
1475 'setup_license_key_expire_date','setup_license_key', 'setup_num_lic_oc',
1476 'default_currency_iso4217', 'default_currency_name', 'default_currency_significant_digits',
1477 'default_currency_symbol', 'default_date_format', 'default_time_format', 'default_decimal_seperator',
1478 'default_export_charset', 'default_language', 'default_locale_name_format', 'default_number_grouping_seperator',
1479 'export_delimiter', 'cache_dir', 'setup_db_options');
1480 copyFromArray($sugar_config_si, $needles, $derived);
1481 $all_config_vars = array_merge( $config_subset, $sugar_config_si, $derived );
1483 // bug 16860 tyoung - trim leading and trailing whitespace from license_key
1484 if (isset($all_config_vars['setup_license_key'])) {
1485 $all_config_vars['setup_license_key'] = trim($all_config_vars['setup_license_key']);
1488 foreach( $all_config_vars as $key => $value ){
1489 $_SESSION[$key] = $value;
1494 * given an array it will check to determine if the key exists in the array, if so
1495 * it will addd to the return array
1497 * @param intput_array haystack to check
1498 * @param needles list of needles to search for
1499 * @param output_array the array to add the keys to
1501 function copyFromArray($input_array, $needles, $output_array){
1502 foreach($needles as $needle){
1503 if(isset($input_array[$needle])){
1504 $output_array[$needle] = $input_array[$needle];
1512 * handles language pack uploads - code based off of upload_file->final_move()
1513 * puts it into the cache/upload dir to be handed off to langPackUnpack();
1515 * @param object file UploadFile object
1516 * @return bool true if successful
1518 function langPackFinalMove($file) {
1519 global $sugar_config;
1520 //."upgrades/langpack/"
1521 $destination = $sugar_config['upload_dir'].$file->stored_file_name;
1522 if(!move_uploaded_file($_FILES[$file->field_name]['tmp_name'], $destination)) {
1523 die ("ERROR: can't move_uploaded_file to $destination. You should try making the directory writable by the webserver");
1528 function getLicenseDisplay($type, $manifest, $zipFile, $next_step, $license_file, $clean_file) {
1529 return PackageManagerDisplay::getLicenseDisplay($license_file, 'install.php', $next_step, $zipFile, $type, $manifest, $clean_file);
1534 * creates the remove/delete form for langpack page
1535 * @param string type commit/remove
1536 * @param string manifest path to manifest file
1537 * @param string zipFile path to uploaded zip file
1538 * @param int nextstep current step
1539 * @return string ret <form> for this package
1541 function getPackButton($type, $manifest, $zipFile, $next_step, $uninstallable='Yes', $showButtons=true) {
1542 global $mod_strings;
1544 $button = $mod_strings['LBL_LANG_BUTTON_COMMIT'];
1545 if($type == 'remove') {
1546 $button = $mod_strings['LBL_LANG_BUTTON_REMOVE'];
1547 } elseif($type == 'uninstall') {
1548 $button = $mod_strings['LBL_LANG_BUTTON_UNINSTALL'];
1551 $disabled = ($uninstallable == 'Yes') ? false : true;
1553 $ret = "<form name='delete{$zipFile}' action='install.php' method='POST'>
1554 <input type='hidden' name='current_step' value='{$next_step}'>
1555 <input type='hidden' name='goto' value='{$mod_strings['LBL_CHECKSYS_RECHECK']}'>
1556 <input type='hidden' name='languagePackAction' value='{$type}'>
1557 <input type='hidden' name='manifest' value='".urlencode($manifest)."'>
1558 <input type='hidden' name='zipFile' value='".urlencode($zipFile)."'>
1559 <input type='hidden' name='install_type' value='custom'>";
1560 if(!$disabled && $showButtons) {
1561 $ret .= "<input type='submit' value='{$button}' class='button'>";
1568 * finds all installed languages and returns an array with the names
1569 * @return array langs array of installed languages
1571 function getInstalledLanguages() {
1572 $langDir = 'include/language/';
1573 $dh = opendir($langDir);
1576 while($file = readdir($dh)) {
1577 if(substr($file, -3) == 'php') {
1586 * searches upgrade dir for lang pack files.
1588 * @return string HTML of available lang packs
1590 function getLangPacks($display_commit = true, $types = array('langpack'), $notice_text = '') {
1591 global $mod_strings;
1593 global $base_upgrade_dir;
1595 if(empty($notice_text)){
1596 $notice_text = $mod_strings['LBL_LANG_PACK_READY'];
1598 $ret = "<tr><td colspan=7 align=left>{$notice_text}</td></tr>";
1599 //$ret .="<table width='100%' cellpadding='0' cellspacing='0' border='0'>";
1601 <td width='20%' ><b>{$mod_strings['LBL_ML_NAME']}</b></td>
1602 <td width='15%' ><b>{$mod_strings['LBL_ML_VERSION']}</b></td>
1603 <td width='15%' ><b>{$mod_strings['LBL_ML_PUBLISHED']}</b></td>
1604 <td width='15%' ><b>{$mod_strings['LBL_ML_UNINSTALLABLE']}</b></td>
1605 <td width='20%' ><b>{$mod_strings['LBL_ML_DESCRIPTION']}</b></td>
1606 <td width='7%' ></td>
1607 <td width='1%' ></td>
1608 <td width='7%' ></td>
1612 // duh, new installs won't have the upgrade folders
1613 if(!is_dir($base_upgrade_dir)) {
1614 mkdir_recursive( $base_upgrade_dir);
1616 $subdirs = array('full', 'langpack', 'module', 'patch', 'theme', 'temp');
1617 foreach( $subdirs as $subdir ){
1618 mkdir_recursive( "$base_upgrade_dir/$subdir" );
1621 $files = findAllFiles($base_upgrade_dir, $files);
1623 unset($_SESSION['hidden_input']);
1625 foreach($files as $file) {
1626 if(!preg_match("#.*\.zip\$#", $file)) {
1630 // skip installed lang packs
1631 if(isset($_SESSION['INSTALLED_LANG_PACKS']) && in_array($file, $_SESSION['INSTALLED_LANG_PACKS'])) {
1635 // handle manifest.php
1636 $target_manifest = remove_file_extension( $file ) . '-manifest.php';
1637 $license_file = remove_file_extension( $file ) . '-license.txt';
1638 include($target_manifest);
1641 if(!in_array(strtolower($manifest['type']), $types))
1645 $md5_matches = array();
1646 if($manifest['type'] == 'module'){
1647 $uh = new UpgradeHistory();
1648 $upgrade_content = clean_path($file);
1649 $the_base = basename($upgrade_content);
1650 $the_md5 = md5_file($upgrade_content);
1651 $md5_matches = $uh->findByMd5($the_md5);
1654 if($manifest['type']!= 'module' || 0 == sizeof($md5_matches)){
1655 $name = empty($manifest['name']) ? $file : $manifest['name'];
1656 $version = empty($manifest['version']) ? '' : $manifest['version'];
1657 $published_date = empty($manifest['published_date']) ? '' : $manifest['published_date'];
1659 $description = empty($manifest['description']) ? 'None' : $manifest['description'];
1660 $uninstallable = empty($manifest['is_uninstallable']) ? 'No' : 'Yes';
1661 $manifest_type = $manifest['type'];
1662 $commitPackage = getPackButton('commit', $target_manifest, $file, $next_step);
1663 $deletePackage = getPackButton('remove', $target_manifest, $file, $next_step);
1664 //$ret .="<table width='100%' cellpadding='0' cellspacing='0' border='0'>";
1666 $ret .= "<td width='20%' >".$name."</td>";
1667 $ret .= "<td width='15%' >".$version."</td>";
1668 $ret .= "<td width='15%' >".$published_date."</td>";
1669 $ret .= "<td width='15%' >".$uninstallable."</td>";
1670 $ret .= "<td width='20%' >".$description."</td>";
1673 $ret .= "<td width='7%'>{$commitPackage}</td>";
1674 $ret .= "<td width='1%'></td>";
1675 $ret .= "<td width='7%'>{$deletePackage}</td>";
1676 $ret .= "</td></tr>";
1678 $clean_field_name = "accept_lic_".str_replace('.', '_', urlencode(basename($file)));
1680 if(is_file($license_file)){
1682 $ret .= "<tr><td colspan=6>";
1683 $ret .= getLicenseDisplay('commit', $target_manifest, $file, $next_step, $license_file, $clean_field_name);
1684 $ret .= "</td></tr>";
1685 $hidden_input .= "<input type='hidden' name='$clean_field_name' id='$clean_field_name' value='no'>";
1687 $hidden_input .= "<input type='hidden' name='$clean_field_name' id='$clean_field_name' value='yes'>";
1691 $_SESSION['hidden_input'] = $hidden_input;
1693 if(count($files) > 0 ) {
1694 $ret .= "</tr><td colspan=7>";
1695 $ret .= "<form name='commit' action='install.php' method='POST'>
1696 <input type='hidden' name='current_step' value='{$next_step}'>
1697 <input type='hidden' name='goto' value='Re-check'>
1698 <input type='hidden' name='languagePackAction' value='commit'>
1699 <input type='hidden' name='install_type' value='custom'>
1702 $ret .= "</td></tr>";
1704 $ret .= "</tr><td colspan=7><i>{$mod_strings['LBL_LANG_NO_PACKS']}</i></td></tr>";
1709 if ( !function_exists('extractFile') ) {
1710 function extractFile( $zip_file, $file_in_zip, $base_tmp_upgrade_dir){
1711 $my_zip_dir = mk_temp_dir( $base_tmp_upgrade_dir );
1712 unzip_file( $zip_file, $file_in_zip, $my_zip_dir );
1713 return( "$my_zip_dir/$file_in_zip" );
1717 if ( !function_exists('extractManifest') ) {
1718 function extractManifest( $zip_file,$base_tmp_upgrade_dir ) {
1719 return( extractFile( $zip_file, "manifest.php",$base_tmp_upgrade_dir ) );
1723 if ( !function_exists('unlinkTempFiles') ) {
1724 function unlinkTempFiles($manifest='', $zipFile='') {
1725 global $sugar_config;
1727 @unlink($_FILES['language_pack']['tmp_name']);
1728 if(!empty($manifest))
1730 if(!empty($zipFile)) {
1731 //@unlink($zipFile);
1732 $tmpZipFile = substr($zipFile, strpos($zipFile, 'langpack/') + 9, strlen($zipFile));
1733 @unlink($sugar_config['upload_dir'].$tmpZipFile);
1736 rmdir_recursive($sugar_config['upload_dir']."upgrades/temp");
1737 sugar_mkdir($sugar_config['upload_dir']."upgrades/temp");
1741 function langPackUnpack($unpack_type, $full_file)
1743 global $sugar_config;
1744 global $base_upgrade_dir;
1745 global $base_tmp_upgrade_dir;
1747 $manifest = array();
1748 if(!empty($full_file)){
1749 $base_filename = pathinfo(urldecode($full_file), PATHINFO_FILENAME );
1751 return "Empty filename supplied";
1753 $manifest_file = extractManifest($full_file, $base_tmp_upgrade_dir);
1754 if($unpack_type == 'module')
1755 $license_file = extractFile($full_file, 'LICENSE.txt', $base_tmp_upgrade_dir);
1757 if(is_file($manifest_file)) {
1759 if($unpack_type == 'module' && is_file($license_file)){
1760 copy($license_file, $base_upgrade_dir.'/'.$unpack_type.'/'.$base_filename."-license.txt");
1762 copy($manifest_file, $base_upgrade_dir.'/'.$unpack_type.'/'.$base_filename."-manifest.php");
1764 require_once( $manifest_file );
1765 validate_manifest( $manifest );
1766 $upgrade_zip_type = $manifest['type'];
1768 mkdir_recursive( "$base_upgrade_dir/$upgrade_zip_type" );
1769 $target_path = "$base_upgrade_dir/$upgrade_zip_type/$base_filename";
1770 $target_manifest = $target_path . "-manifest.php";
1772 if( isset($manifest['icon']) && $manifest['icon'] != "" ) {
1773 $icon_location = extractFile( $full_file, $manifest['icon'], $base_tmp_upgrade_dir );
1774 $path_parts = pathinfo( $icon_location );
1775 copy( $icon_location, $target_path . "-icon." . $path_parts['extension'] );
1778 // move file from uploads to cache
1779 // FIXME: where should it be?
1780 if( copy( $full_file , $target_path.".zip" ) ){
1781 copy( $manifest_file, $target_manifest );
1782 unlink($full_file); // remove tempFile
1783 return "The file $base_filename has been uploaded.<br>\n";
1785 unlinkTempFiles($manifest_file, $full_file);
1786 return "There was an error uploading the file, please try again!<br>\n";
1789 die("The zip file is missing a manifest.php file. Cannot proceed.");
1791 unlinkTempFiles($manifest_file, '');
1794 if ( !function_exists('validate_manifest') ) {
1795 function validate_manifest( $manifest ){
1796 // takes a manifest.php manifest array and validates contents
1798 global $sugar_version;
1799 global $sugar_flavor;
1800 global $mod_strings;
1802 if( !isset($manifest['type']) ){
1803 die($mod_strings['ERROR_MANIFEST_TYPE']);
1805 $type = $manifest['type'];
1806 if( getInstallType( "/$type/" ) == "" ){
1807 die($mod_strings['ERROR_PACKAGE_TYPE']. ": '" . $type . "'." );
1810 return true; // making this a bit more relaxed since we updated the language extraction and merge capabilities
1813 if( isset($manifest['acceptable_sugar_versions']) ){
1814 $version_ok = false;
1815 $matches_empty = true;
1816 if( isset($manifest['acceptable_sugar_versions']['exact_matches']) ){
1817 $matches_empty = false;
1818 foreach( $manifest['acceptable_sugar_versions']['exact_matches'] as $match ){
1819 if( $match == $sugar_version ){
1824 if( !$version_ok && isset($manifest['acceptable_sugar_versions']['regex_matches']) ){
1825 $matches_empty = false;
1826 foreach( $manifest['acceptable_sugar_versions']['regex_matches'] as $match ){
1827 if( preg_match( "/$match/", $sugar_version ) ){
1833 if( !$matches_empty && !$version_ok ){
1834 die( $mod_strings['ERROR_VERSION_INCOMPATIBLE'] . $sugar_version );
1838 if( isset($manifest['acceptable_sugar_flavors']) && sizeof($manifest['acceptable_sugar_flavors']) > 0 ){
1840 foreach( $manifest['acceptable_sugar_flavors'] as $match ){
1841 if( $match == $sugar_flavor ){
1846 //die( $mod_strings['ERROR_FLAVOR_INCOMPATIBLE'] . $sugar_flavor );
1852 if ( !function_exists('getInstallType') ) {
1853 function getInstallType( $type_string ){
1855 $subdirs = array('full', 'langpack', 'module', 'patch', 'theme', 'temp');
1856 foreach( $subdirs as $subdir ){
1857 if( preg_match( "#/$subdir/#", $type_string ) ){
1861 // return empty if no match
1868 //mysqli connector has a separate parameter for port.. We need to separate it out from the host name
1869 function getHostPortFromString($hostname=''){
1871 $pos=strpos($hostname,':');
1873 //no need to process as string is empty or does not contain ':' delimiter
1877 $hostArr = explode(':', $hostname);
1883 function getLicenseContents($filename)
1886 if(file_exists($filename) && filesize($filename) >0){
1887 $license_file = trim(file_get_contents($filename));
1889 return $license_file;
1899 ///////////////////////////////////////////////////////////////////////////////
1900 //// FROM POPULATE SEED DATA
1902 'qa', 'dev', 'beans',
1903 'info', 'sales', 'support',
1904 'kid', 'the', 'section',
1905 'sugar', 'hr', 'im',
1906 'kid', 'vegan', 'phone',
1909 ".com", ".org", ".net", ".tv", ".cn", ".co.jp", ".us",
1910 ".edu", ".tw", ".de", ".it", ".co.uk", ".info", ".biz",
1915 * creates a random, DNS-clean webaddress
1917 function createWebAddress() {
1921 $one = $seed[rand(0, count($seed)-1)];
1922 $two = $seed[rand(0, count($seed)-1)];
1923 $tld = $tlds[rand(0, count($tlds)-1)];
1925 return "www.{$one}{$two}{$tld}";
1929 * creates a random email address
1932 function createEmailAddress() {
1936 $part[0] = $seed[rand(0, count($seed)-1)];
1937 $part[1] = $seed[rand(0, count($seed)-1)];
1938 $part[2] = $seed[rand(0, count($seed)-1)];
1940 $tld = $tlds[rand(0, count($tlds)-1)];
1945 for($i=0; $i<$len; $i++) {
1946 $ret .= (empty($ret)) ? '' : '.';
1951 $ret .= rand(10, 99);
1954 return "{$ret}@example{$tld}";
1958 function add_digits($quantity, &$string, $min = 0, $max = 9) {
1959 for($i=0; $i < $quantity; $i++) {
1960 $string .= mt_rand($min,$max);
1964 function create_phone_number() {
1966 add_digits(3, $phone);
1968 add_digits(3, $phone);
1970 add_digits(4, $phone);
1975 function create_date($year=null,$mnth=null,$day=null)
1978 $now = $timedate->getNow();
1979 if ($day==null) $day=$now->day+mt_rand(0,365);
1980 return $timedate->asDbDate($now->get_day_begin($day, $mnth, $year));
1983 function create_current_date_time()
1986 return $timedate->nowDb();
1989 function create_time($hr=null,$min=null,$sec=null)
1992 $date = TimeDate::fromTimestamp(0);
1993 if ($hr==null) $hr=mt_rand(6,19);
1994 if ($min==null) $min=(mt_rand(0,3)*15);
1995 if ($sec==null) $sec=0;
1996 return $timedate->asDbTime($date->setDate(2007, 10, 7)->setTime($hr, $min, $sec));
1999 function create_past_date()
2002 $now = $timedate->getNow(true);
2003 $day=$now->day-mt_rand(1, 365);
2004 return $timedate->asDbDate($now->get_day_begin($day));
2008 * This method will look for a file modules_post_install.php in the root directory and based on the
2009 * contents of this file, it will silently install any modules as specified in this array.
2011 function post_install_modules(){
2012 if(is_file('modules_post_install.php')){
2013 global $current_user, $mod_strings;
2014 $current_user = new User();
2015 $current_user->is_admin = '1';
2016 require_once('ModuleInstall/PackageManager/PackageManager.php');
2017 require_once('modules_post_install.php');
2018 //we now have the $modules_to_install array in memory
2019 $pm = new PackageManager();
2020 $old_mod_strings = $mod_strings;
2021 foreach($modules_to_install as $module_to_install){
2022 if(is_file($module_to_install)){
2023 $pm->performSetup($module_to_install, 'module', false);
2024 $file_to_install = sugar_cached('upload/upgrades/module/').basename($module_to_install);
2025 $_REQUEST['install_file'] = $file_to_install;
2026 $pm->performInstall($file_to_install);
2029 $mod_strings = $old_mod_strings;
2033 function get_help_button_url(){
2034 $help_url = 'http://www.sugarcrm.com/docs/Administration_Guides/CommunityEdition_Admin_Guide_5.0/toc.html';
2039 function create_db_user_creds($numChars=10){
2040 $numChars = 7; // number of chars in the password
2041 //chars to select from
2042 $charBKT = "abcdefghijklmnpqrstuvwxyz123456789ABCDEFGHIJKLMNPQRSTUVWXYZ";
2043 // seed the random number generator
2044 srand((double)microtime()*1000000);
2046 for ($i=0;$i<$numChars;$i++) // loop and create password
2047 $password = $password . substr ($charBKT, rand() % strlen($charBKT), 1);
2053 function addDefaultRoles($defaultRoles = array()) {
2057 foreach($defaultRoles as $roleName=>$role){
2058 $ACLField = new ACLField();
2059 $role1= new ACLRole();
2060 $role1->name = $roleName;
2061 $role1->description = $roleName." Role";
2062 $role1_id=$role1->save();
2063 foreach($role as $category=>$actions){
2064 foreach($actions as $name=>$access_override){
2065 if($name=='fields'){
2066 foreach($access_override as $field_id=>$access){
2067 $ACLField->setAccessControl($category, $role1_id, $field_id, $access);
2070 $queryACL="SELECT id FROM acl_actions where category='$category' and name='$name'";
2071 $result = $db->query($queryACL);
2072 $actionId=$db->fetchByAssoc($result);
2073 if (isset($actionId['id']) && !empty($actionId['id'])){
2074 $role1->setAction($role1_id, $actionId['id'], $access_override);
2083 * Fully enable SugarFeeds, enabling the user feed and all available modules that have SugarFeed data.
2085 function enableSugarFeeds()
2087 $admin = new Administration();
2088 $admin->saveSetting('sugarfeed','enabled','1');
2090 foreach ( SugarFeed::getAllFeedModules() as $module )
2091 SugarFeed::activateModuleFeed($module);
2093 check_logic_hook_file('Users','after_login', array(1, 'SugarFeed old feed entry remover', 'modules/SugarFeed/SugarFeedFlush.php', 'SugarFeedFlush', 'flushStaleEntries'));
2096 function create_writable_dir($dirname)
2098 if ((is_dir($dirname)) || @sugar_mkdir($dirname,0755)) {
2099 $ok = make_writable($dirname);
2102 installLog("ERROR: Cannot create writable dir $dirname");
2107 * Enable the InsideView connector for the four default modules.
2109 function enableInsideViewConnector()
2111 // Load up the existing mapping and hand it to the InsideView connector to have it setup the correct logic hooks
2112 $mapFile = 'modules/Connectors/connectors/sources/ext/rest/insideview/mapping.php';
2113 if ( file_exists('custom/'.$mapFile) ) {
2114 require('custom/'.$mapFile);
2119 require_once('modules/Connectors/connectors/sources/ext/rest/insideview/insideview.php');
2120 $source = new ext_rest_insideview();
2122 // $mapping is brought in from the mapping.php file above
2123 $source->saveMappingHook($mapping);