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 ********************************************************************************/
42 require_once('modules/Administration/UpgradeWizardCommon.php');
45 unset($_SESSION['rebuild_relationships']);
46 unset($_SESSION['rebuild_extensions']);
48 if(empty($_REQUEST['install_file'])){
49 die( "File to install not specified." );
51 if( !isset($_REQUEST['mode']) || ($_REQUEST['mode'] == "") ){
52 die( "No mode specified." );
55 if(!file_exists($base_tmp_upgrade_dir)) {
56 mkdir($base_tmp_upgrade_dir, 0755, true);
59 $unzip_dir = mk_temp_dir( $base_tmp_upgrade_dir );
60 $install_file = hashToFile($_REQUEST['install_file']);
65 $mode = $_REQUEST['mode'];
66 $hidden_fields .= "<input type=hidden name=\"mode\" value=\"$mode\"/>";
69 $install_type = getInstallType( $install_file );
72 $previous_version = "";
77 $zip_force_copy = array();
78 $license_file = $unzip_dir.'/LICENSE.txt';
79 $readme_file = $unzip_dir.'/README.txt';
80 $require_license = false;
81 $found_readme = false;
85 $is_uninstallable = true;
87 $dependencies = array();
88 $remove_tables = 'true';
90 unzip( $install_file, $unzip_dir );
91 if($install_type == 'module' && $mode != 'Uninstall'){
92 if(file_exists($license_file)){
93 $require_license = true;
97 //Scan the unzip dir for unsafe files
98 if (((defined('MODULE_INSTALLER_PACKAGE_SCAN') && MODULE_INSTALLER_PACKAGE_SCAN)
99 || !empty($GLOBALS['sugar_config']['moduleInstaller']['packageScan'])) && $install_type != 'patch') {
100 require_once('ModuleInstall/ModuleScanner.php');
101 $ms = new ModuleScanner();
102 $ms->scanPackage($unzip_dir);
103 if($ms->hasIssues()){
104 rmdir_recursive($unzip_dir);
105 $ms->displayIssues();
110 // assumption -- already validated manifest.php at time of upload
111 require( "$unzip_dir/manifest.php" );
115 if( isset( $manifest['copy_files']['from_dir'] ) && $manifest['copy_files']['from_dir'] != "" ){
116 $zip_from_dir = $manifest['copy_files']['from_dir'];
118 if( isset( $manifest['copy_files']['to_dir'] ) && $manifest['copy_files']['to_dir'] != "" ){
119 $zip_to_dir = $manifest['copy_files']['to_dir'];
121 if( isset( $manifest['copy_files']['force_copy'] ) && $manifest['copy_files']['force_copy'] != "" ){
122 $zip_force_copy = $manifest['copy_files']['force_copy'];
124 if( isset( $manifest['version'] ) ){
125 $version = $manifest['version'];
127 if( isset( $manifest['author'] ) ){
128 $author = $manifest['author'];
130 if( isset( $manifest['name'] ) ){
131 $name = $manifest['name'];
133 if( isset( $manifest['description'] ) ){
134 $description = $manifest['description'];
136 if( isset( $manifest['is_uninstallable'] ) ){
137 $is_uninstallable = $manifest['is_uninstallable'];
139 if(isset($installdefs) && isset( $installdefs['id'] ) ){
140 $id_name = $installdefs['id'];
142 if( isset( $manifest['dependencies']) ){
143 $dependencies = $manifest['dependencies'];
145 if( isset( $manifest['remove_tables']) ){
146 $remove_tables = $manifest['remove_tables'];
149 if($remove_tables != 'prompt'){
150 $hidden_fields .= "<input type=hidden name=\"remove_tables\" value='".$remove_tables."'>";
152 if(file_exists($readme_file) || !empty($manifest['readme'])){
153 $found_readme = true;
155 $uh = new UpgradeHistory();
156 //check dependencies first
157 if(!empty($dependencies)){
158 $not_found = $uh->checkDependencies($dependencies);
159 if(!empty($not_found) && count($not_found) > 0){
160 die( $mod_strings['ERR_UW_NO_DEPENDENCY']."[".implode(',', $not_found)."]");
163 switch( $install_type ){
166 if( !is_writable( "config.php" ) ){
167 die( $mod_strings['ERR_UW_CONFIG'] );
173 // find name of language pack: find single file in include/language/xx_xx.lang.php
174 $d = dir( "$unzip_dir/$zip_from_dir/include/language" );
175 while( $f = $d->read() ){
176 if( $f == "." || $f == ".." ){
179 else if( preg_match("/(.*)\.lang\.php\$/", $f, $match) ){
180 $new_lang_name = $match[1];
183 if( $new_lang_name == "" ){
184 die( $mod_strings['ERR_UW_NO_LANGPACK'].$install_file );
186 $hidden_fields .= "<input type=hidden name=\"new_lang_name\" value=\"$new_lang_name\"/>";
188 $new_lang_desc = getLanguagePackName( "$unzip_dir/$zip_from_dir/include/language/$new_lang_name.lang.php" );
189 if( $new_lang_desc == "" ){
190 die( $mod_strings['ERR_UW_NO_LANG_DESC_1']."include/language/$new_lang_name.lang.php".$mod_strings['ERR_UW_NO_LANG_DESC_2']."$install_file." );
192 $hidden_fields .= "<input type=hidden name=\"new_lang_desc\" value=\"$new_lang_desc\"/>";
194 if( !is_writable( "config.php" ) ){
195 die( $mod_strings['ERR_UW_CONFIG'] );
199 $previous_install = array();
200 if(!empty($id_name) & !empty($version))
201 $previous_install = $uh->determineIfUpgrade($id_name, $version);
202 $previous_version = (empty($previous_install['version'])) ? '' : $previous_install['version'];
203 $previous_id = (empty($previous_install['id'])) ? '' : $previous_install['id'];
205 //rrs pull out unique_key
206 $hidden_fields .= "<input type=hidden name=\"author\" value=\"$author\"/>";
207 $hidden_fields .= "<input type=hidden name=\"name\" value=\"$name\"/>";
208 $hidden_fields .= "<input type=hidden name=\"description\" value=\"$description\"/>";
209 $hidden_fields .= "<input type=hidden name=\"is_uninstallable\" value=\"$is_uninstallable\"/>";
210 $hidden_fields .= "<input type=hidden name=\"id_name\" value=\"$id_name\"/>";
211 $hidden_fields .= "<input type=hidden name=\"previous_version\" value=\"$previous_version\"/>";
212 $hidden_fields .= "<input type=hidden name=\"previous_id\" value=\"$previous_id\"/>";
215 die( $mod_strings['ERR_UW_WRONG_TYPE'].$install_type );
219 $new_files = findAllFilesRelative( "$unzip_dir/$zip_from_dir", array() );
220 $hidden_fields .= "<input type=hidden name=\"version\" value=\"$version\"/>";
221 $serial_manifest = array();
222 $serial_manifest['manifest'] = (isset($manifest) ? $manifest : '');
223 $serial_manifest['installdefs'] = (isset($installdefs) ? $installdefs : '');
224 $serial_manifest['upgrade_manifest'] = (isset($upgrade_manifest) ? $upgrade_manifest : '');
225 $hidden_fields .= "<input type=hidden name=\"s_manifest\" value='".base64_encode(serialize($serial_manifest))."'>";
226 // present list to user
228 <form action="<?php print( $form_action . "_commit" ); ?>" name="files" method="post" onSubmit="return validateForm(<?php print($require_license); ?>);">
230 if(empty($new_studio_mod_files)) {
231 if(!empty($mode) && $mode == 'Uninstall')
232 echo $mod_strings['LBL_UW_UNINSTALL_READY'];
233 else if($mode == 'Disable')
234 echo $mod_strings['LBL_UW_DISABLE_READY'];
235 else if($mode == 'Enable')
236 echo $mod_strings['LBL_UW_ENABLE_READY'];
238 echo $mod_strings['LBL_UW_PATCH_READY'];
240 echo $mod_strings['LBL_UW_PATCH_READY2'];
241 echo '<input type="checkbox" onclick="toggle_these(0, ' . count($new_studio_mod_files) . ', this)"> '.$mod_strings['LBL_UW_CHECK_ALL'];
242 foreach($new_studio_mod_files as $the_file) {
243 $new_file = clean_path( "$zip_to_dir/$the_file" );
244 print( "<li><input id=\"copy_$count\" name=\"copy_$count\" type=\"checkbox\" value=\"" . $the_file . "\"> " . $new_file . "</li>");
249 if($require_license){
250 $contents = sugar_file_get_contents($license_file);
251 $readme_contents = '';
253 if(file_exists($readme_file) && filesize($readme_file) > 0){
254 $readme_contents = file_get_contents($readme_file);
255 }elseif(!empty($manifest['readme'])){
256 $readme_contents = $manifest['readme'];
259 $license_final =<<<eoq2
262 <td colspan="3"><ul class="tablist">
263 <li id="license_li" class="active"><a id="license_link" class="current" href="javascript:selectTabCSS('license');">{$mod_strings['LBL_LICENSE']}</a></li>
264 <li class="active" id="readme_li"><a id="readme_link" href="javascript:selectTabCSS('readme');">{$mod_strings['LBL_README']}</a></li>
268 <div id='license_div'>
271 <td colspan="3"> </td>
274 <td align="left" valign="top" colspan=2>
275 <b>{$mod_strings['LBL_MODULE_LICENSE']}</b>
279 <td align="left" valign="top" colspan=2>
280 <textarea cols="100" rows="8" readonly>{$contents}</textarea>
285 <td align="left" valign="top" colspan=2>
286 <input type='radio' id='radio_license_agreement_accept' name='radio_license_agreement' value='accept'>{$mod_strings['LBL_ACCEPT']}
287 <input type='radio' id='radio_license_agreement_reject' name='radio_license_agreement' value='reject' checked>{$mod_strings['LBL_DENY']}
292 <div id='readme_div' style='display: none;'>
295 <td colspan="3"> </td>
298 <td align="left" valign="top" colspan=2>
299 <b>{$mod_strings['LBL_README']}</b>
303 <td align="left" valign="top" colspan=2>
304 <textarea cols="100" rows="8" readonly>{$readme_contents}</textarea>
318 if( $install_type == "langpack") {
319 print( $mod_strings['LBL_UW_LANGPACK_READY'] );
324 if( $install_type == "langpack" ){
325 print( $mod_strings['LBL_UW_LANGPACK_READY_UNISTALL'] );
328 else if($install_type != "module"){
329 print( $mod_strings['LBL_UW_FILES_REMOVED'] );
333 if( $install_type == "langpack" ){
334 print( $mod_strings['LBL_UW_LANGPACK_READY_DISABLE'] );
339 if( $install_type == "langpack" ){
340 print( $mod_strings['LBL_UW_LANGPACK_READY_ENABLE'] );
348 <input type=submit value="<?php echo $mod_strings['LBL_ML_COMMIT'];?>" class="button" id="submit_button" />
349 <input type=button value="<?php echo $mod_strings['LBL_ML_CANCEL'];?>" class="button" onClick="location.href='index.php?module=Administration&action=UpgradeWizard&view=module';"/>
353 if($remove_tables == 'prompt' && $mode == 'Uninstall'){
354 print ("<br/><br/>");
355 print ("<input type='radio' id='remove_tables_true' name='remove_tables' value='true' checked>".$mod_strings['ML_LBL_REMOVE_TABLES']." ");
356 print ("<input type='radio' id='remove_tables_false' name='remove_tables' value='false'>".$mod_strings['ML_LBL_DO_NOT_REMOVE_TABLES']."<br>");
360 if( $show_files == true ){
363 $new_studio_mod_files = array();
364 $new_sugar_mod_files = array();
366 $cache_html_files = findAllFilesRelative( sugar_cached("layout"), array());
368 foreach($new_files as $the_file) {
369 if(substr(strtolower($the_file), -5, 5) == '.html' && in_array($the_file, $cache_html_files))
370 array_push($new_studio_mod_files, $the_file);
372 array_push($new_sugar_mod_files, $the_file);
376 function toggle_these(start, end, ca) {
378 elem = eval("document.forms.files.copy_" + start);
379 if(!ca.checked) elem.checked = false;
380 else elem.checked = true;
392 echo '<div style="text-align: left; cursor: hand; cursor: pointer; text-decoration: underline;'.(($mode == 'Enable' || $mode == 'Disable')?'display:none;':'').'" onclick=\'this.style.display="none"; toggleDisplay("more");\'id="all_text">
393 '.SugarThemeRegistry::current()->getImage('advanced_search', '', null, null, ".gif", $mod_strings['LBL_ADVANCED_SEARCH']).$mod_strings['LBL_UW_SHOW_DETAILS'].'</div><div id=\'more\' style=\'display: none\'>
394 <div style="text-align: left; cursor: hand; cursor: pointer; text-decoration: underline;" onclick=\'document.getElementById("all_text").style.display=""; toggleDisplay("more");\'>'
395 .SugarThemeRegistry::current()->getImage('basic_search', '', null, null, ".gif", $mod_strings['LBL_BASIC_SEARCH']).$mod_strings['LBL_UW_HIDE_DETAILS'].'</div><br>';
396 echo '<input type="checkbox" checked onclick="toggle_these(' . count($new_studio_mod_files) . ',' . count($new_files) . ', this)"> '.$mod_strings['LBL_UW_CHECK_ALL'];
398 foreach( $new_sugar_mod_files as $the_file ){
399 $highlight_start = "";
403 $unzip_file = "$unzip_dir/$zip_from_dir/$the_file";
404 $new_file = clean_path( "$zip_to_dir/$the_file" );
405 $forced_copy = false;
407 if( $mode == "Install" ){
408 $checked = "checked";
409 foreach( $zip_force_copy as $pattern ){
410 if( preg_match("#" . $pattern . "#", $unzip_file) ){
411 $disabled = "disabled=\"true\"";
415 if( !$forced_copy && is_file( $new_file ) && (md5_file( $unzip_file ) == md5_file( $new_file )) ){
416 $disabled = "disabled=\"true\"";
419 if( $checked != "" && $disabled != "" ){ // need to put a hidden field
420 print( "<input name=\"copy_$count\" type=\"hidden\" value=\"" . $the_file . "\">\n" );
422 print( "<li><input id=\"copy_$count\" name=\"copy_$count\" type=\"checkbox\" value=\"" . $the_file . "\" $checked $disabled > " . $highlight_start . $new_file . $highlight_end );
423 if( $checked == "" && $disabled != "" ){ // need to explain this file hasn't changed
424 print( " (no changes)" );
428 else if( $mode == "Uninstall" && file_exists( $new_file ) ){
429 if( md5_file( $unzip_file ) == md5_file( $new_file ) ){
430 $checked = "checked=\"true\"";
433 $highlight_start = "<font color=red>";
434 $highlight_end = "</font>";
436 print( "<li><input name=\"copy_$count\" type=\"checkbox\" value=\"" . $the_file . "\" $checked $disabled > " . $highlight_start . $new_file . $highlight_end . "<br>\n" );
443 if($mode == "Disable" || $mode == "Enable"){
444 //check to see if any files have been modified
445 $modified_files = getDiffFiles($unzip_dir, $install_file, ($mode == 'Enable'), $previous_version);
446 if(count($modified_files) > 0){
447 //we need to tell the user that some files have been modified since they last did an install
449 'function handleFileChange(){';
450 if(count($modified_files) > 0){
451 echo 'if(document.getElementById("radio_overwrite_files") != null && document.getElementById("radio_do_not_overwrite_files") != null){
452 var overwrite = false;
453 if(document.getElementById("radio_overwrite_files").checked){
462 print('<b>'.$mod_strings['ML_LBL_OVERWRITE_FILES'].'</b>');
463 print('<table><td align="left" valign="top" colspan=2>');
464 print("<input type='radio' id='radio_overwrite_files' name='radio_overwrite' value='overwrite'>{$mod_strings['LBL_OVERWRITE_FILES']} ");
465 print("<input type='radio' id='radio_do_not_overwrite_files' name='radio_overwrite' value='do_not_overwrite' checked>{$mod_strings['LBL_DO_OVERWRITE_FILES']}");
466 print("</td></tr></table>");
468 foreach($modified_files as $modified_file){
469 print('<li>'.$modified_file.'</li>');
474 'function handleFileChange(){';
480 'function handleFileChange(){';
485 'function validateForm(process){'.
486 'return (handleCommit(process) && handleFileChange());'.
488 'function handleCommit(process){
490 if(document.getElementById("radio_license_agreement_reject") != null && document.getElementById("radio_license_agreement_accept") != null){
492 if(document.getElementById("radio_license_agreement_accept").checked){
496 //do not allow the form to submit
497 alert("'.$mod_strings['ERR_UW_ACCEPT_LICENSE'].'");
502 document.getElementById("submit_button").disabled = true;
505 var keys = [ "license","readme"];
506 function selectTabCSS(key){
507 for( var i=0; i<keys.length;i++)
514 var liclass = "active";
515 var linkclass = "current";
516 document.getElementById(keys[i]+"_div").style.display = "block";
518 document.getElementById(keys[i]+"_div").style.display = "none";
520 document.getElementById(keys[i]+"_li").className = liclass;
521 document.getElementById(keys[i]+"_link").className = linkclass;
523 tabPreviousKey = key;
527 $fileHash = fileToHash($install_file );
529 <?php print( $hidden_fields ); ?>
530 <input type="hidden" name="copy_count" value="<?php print( $count );?>"/>
531 <input type="hidden" name="run" value="commit" />
532 <input type="hidden" name="install_file" value="<?php echo $fileHash; ?>" />
533 <input type="hidden" name="unzip_dir" value="<?php echo basename($unzip_dir); ?>" />
534 <input type="hidden" name="zip_from_dir" value="<?php echo $zip_from_dir; ?>" />
535 <input type="hidden" name="zip_to_dir" value="<?php echo $zip_to_dir; ?>" />
539 $GLOBALS['log']->info( "Upgrade Wizard patches" );