1<?php 2function DisplayStatus(WebPage $oPage) 3{ 4 $oPage->set_title(Dict::S('iTopHub:Landing:Status')); 5 6 $oPage->add('<table class="module-selection-banner"><tr>'); 7 $sBannerUrl = utils::GetAbsoluteUrlModulesRoot().'/itop-hub-connector/images/landing-extension.png'; 8 $oPage->add('<td><img style="max-height:72px; margin-right: 10px;" src="'.$sBannerUrl.'"/><td>'); 9 $oPage->add('<td><h2>'.Dict::S('iTopHub:LandingWelcome').'</h2><td>'); 10 $oPage->add('</tr></table>'); 11 12 $oPage->add('<div class="module-selection-body">'); 13 // Now scan the extensions and display a report of the extensions brought by the hub 14 $sPath = APPROOT.'data/downloaded-extensions/'; 15 $aExtraDirs = array(); 16 if (is_dir($sPath)) 17 { 18 $aExtraDirs[] = $sPath; // Also read the extra downloaded-modules directory 19 } 20 $oExtensionsMap = new iTopExtensionsMap('production', true, $aExtraDirs); 21 $oExtensionsMap->LoadChoicesFromDatabase(MetaModel::GetConfig()); 22 23 foreach($oExtensionsMap->GetAllExtensions() as $oExtension) 24 { 25 if ($oExtension->sSource == iTopExtension::SOURCE_REMOTE) 26 { 27 $aCSSClasses = array('landing-extension'); 28 if ($oExtension->sInstalledVersion === '') 29 { 30 $aCSSClasses[] = 'landing-installation'; 31 $sInstallation = Dict::Format('iTopHub:InstallationStatus:Version_NotInstalled', $oExtension->sVersion); 32 33 } 34 else 35 { 36 $aCSSClasses[] = 'landing-no-change'; 37 $sBadge = '<span style="display:inline-block;font-size:8pt;padding:3px;border-radius:4px;color:#fff;background-color:#1c94c4;margin-left:0.5em;margin-right:0.5em">'.Dict::S('iTopHub:InstallationStatus:Installed').'</span>'; 38 $sInstallation = Dict::Format('iTopHub:InstallationStatus:Installed_Version', $sBadge, $oExtension->sInstalledVersion); 39 } 40 41 $oPage->add('<div class="choice">'); 42 $sCode = $oExtension->sCode; 43 $sDir = basename($oExtension->sSourceDir); 44 $oPage->add('<input type="checkbox" data-extension-code="'.$sCode.'" data-extension-dir="'.$sDir.'" checked disabled> '); 45 $oPage->add('<label><b>'.htmlentities($oExtension->sLabel, ENT_QUOTES, 'UTF-8').'</b> '.$sInstallation.'</label>'); 46 $oPage->add('<div class="description">'); 47 $oPage->add('<p>'); 48 if ($oExtension->sDescription != '') 49 { 50 $oPage->add(htmlentities($oExtension->sDescription, ENT_QUOTES, 'UTF-8').'</br>'); 51 } 52 $oPage->add('</p>'); 53 $oPage->add('</div>'); 54 $oPage->add('</div>'); 55 } 56 } 57 $oPage->add('</div>'); 58 $oPage->add('<div style="text-align:center"><button onclick="window.location.href=\'./UI.php\';">'.Dict::S('iTopHub:GoBackToITopBtn').'</button></div>'); 59} 60 61function DoLanding(WebPage $oPage) 62{ 63 $oPage->add_linked_stylesheet(utils::GetAbsoluteUrlModulesRoot().'itop-hub-connector/css/hub.css'); 64 $oPage->add('<table class="module-selection-banner"><tr>'); 65 $sBannerUrl = utils::GetAbsoluteUrlModulesRoot().'/itop-hub-connector/images/landing-extension.png'; 66 $oPage->add('<td><img style="max-height:72px; margin-right: 10px;" src="'.$sBannerUrl.'"/><td>'); 67 $oPage->add('<td><h2>'.Dict::S('iTopHub:InstallationWelcome').'</h2><td>'); 68 $oPage->add('</tr></table>'); 69 70 $oPage->set_title(Dict::S('iTopHub:Landing:Status')); 71 72 $oPage->add('<div class="module-selection-body" style="text-align: center; line-height: 14em;"><h2>'.Dict::S('iTopHub:Uncompressing').'</h2></div>'); 73 74 75 $sProduct = utils::ReadParam('applicationName', '', false, 'raw_data'); 76 $sVersion = utils::ReadParam('applicationVersion', '', false, 'raw_data'); 77 $sInstanceUUID = utils::ReadParam('uuidFile', '', false, 'raw_data'); 78 $sDatabaseUUID = utils::ReadParam('uuidBdd', '', false, 'raw_data'); 79 $aExtensions = utils::ReadParam('extensions', array(), false, 'raw_data'); 80 81 // Basic consistency validation 82 if ($sProduct != ITOP_APPLICATION) 83 { 84 throw new Exception("Inconsistent product '$sProduct', expecting '".ITOP_APPLICATION."'"); 85 } 86 87 if ($sVersion != ITOP_VERSION) 88 { 89 throw new Exception("Inconsistent version '$sVersion', expecting ".ITOP_VERSION."'"); 90 } 91 92 $sFileUUID = (string) trim(@file_get_contents(APPROOT."data/instance.txt"), "{} \n"); 93 if ($sInstanceUUID != $sFileUUID) 94 { 95 throw new Exception("Inconsistent file UUID '$sInstanceUUID', expecting ".$sFileUUID."'"); 96 } 97 98 $sDBUUID = (string) trim(DBProperty::GetProperty('database_uuid', ''), '{}'); 99 if ($sDatabaseUUID != $sDBUUID) 100 { 101 throw new Exception("Inconsistent database UUID '$sDatabaseUUID', expecting ".$sDBUUID."'"); 102 } 103 104 // Uncompression of extensions in data/downloaded-extensions 105 // only newly downloaded extensions reside in this folder 106 $i = 0; 107 $sPath = APPROOT.'data/downloaded-extensions/'; 108 if (!is_dir($sPath)) 109 { 110 if (!mkdir($sPath)) throw new Exception("ERROR: Unable to create the directory '$sPath'. Cannot download any extension. Check the access rights on '".dirname('data/downloaded-extensions/')."'"); 111 } 112 else 113 { 114 // Make sure that the directory is empty 115 SetupUtils::tidydir($sPath); 116 } 117 118 foreach($aExtensions as $sBase64Archive) 119 { 120 $sArchive = base64_decode($sBase64Archive); 121 122 $sZipArchiveFile = $sPath."/extension-{$i}.zip"; 123 file_put_contents($sZipArchiveFile, $sArchive); 124 // Expand the content of extension-x.zip into APPROOT.'data/downloaded-extensions/' 125 // where the installation will load the extension automatically 126 $oZip = new ZipArchive(); 127 if (!$oZip->open($sZipArchiveFile)) 128 { 129 throw new Exception('Unable to open "'.$sZipArchiveFile.'" for extraction. Make sure that the directory "'.'data/downloaded-extensions/'.'" is writable for the web server.'); 130 } 131 for($idx = 0; $idx < $oZip->numFiles; $idx++) 132 { 133 $sCompressedFile = $oZip->getNameIndex($idx); 134 $oZip->extractTo($sPath, $sCompressedFile); 135 } 136 @$oZip->close(); 137 @unlink($sZipArchiveFile); // Get rid of the temporary file 138 $i++; 139 } 140 141 // Now scan the extensions and display a report of the extensions brought by the hub 142 $sNextPage = utils::GetAbsoluteUrlModulePage('itop-hub-connector', 'land.php', array('operation' => 'install')); 143 $oPage->add_ready_script("window.location.href='$sNextPage'"); 144 145} 146 147function DoInstall(WebPage $oPage) 148{ 149 $sUID = hash('sha256', rand()); 150 file_put_contents(APPROOT.'data/hub/compile_authent', $sUID); 151 152 $oPage->add_linked_stylesheet(utils::GetAbsoluteUrlModulesRoot().'itop-hub-connector/css/hub.css'); 153 $oPage->add('<table class="module-selection-banner"><tr>'); 154 $sBannerUrl = utils::GetAbsoluteUrlModulesRoot().'/itop-hub-connector/images/landing-extension.png'; 155 $oPage->add('<td><img style="max-height:72px; margin-right: 10px;" src="'.$sBannerUrl.'"/><td>'); 156 $oPage->add('<td><h2>'.Dict::S('iTopHub:InstallationWelcome').'</h2><td>'); 157 $oPage->add('</tr></table>'); 158 159 $oPage->set_title(Dict::S('iTopHub:Landing:Install')); 160 $oPage->add('<div id="installation-summary" class="module-selection-body" style="position: relative">'); 161 162 163 // Now scan the extensions and display a report of the extensions brought by the hub 164 // Now scan the extensions and display a report of the extensions brought by the hub 165 $sPath = APPROOT.'data/downloaded-extensions/'; 166 $aExtraDirs = array(); 167 if (is_dir($sPath)) 168 { 169 $aExtraDirs[] = $sPath; // Also read the extra downloaded-modules directory 170 } 171 $oExtensionsMap = new iTopExtensionsMap('production', true, $aExtraDirs); 172 $oExtensionsMap->LoadChoicesFromDatabase(MetaModel::GetConfig()); 173 174 foreach($oExtensionsMap->GetAllExtensions() as $oExtension) 175 { 176 if ($oExtension->sSource == iTopExtension::SOURCE_REMOTE) 177 { 178 if (count($oExtension->aMissingDependencies) > 0) 179 { 180 $oPage->add('<div class="choice">'); 181 $oPage->add('<input type="checkbox" disabled> '); 182 $sTitle = Dict::Format('iTopHub:InstallationEffect:MissingDependencies_Details', implode(', ', $oExtension->aMissingDependencies)); 183 $oPage->add('<label><b>'.htmlentities($oExtension->sLabel, ENT_QUOTES, 'UTF-8').'</b> <span style="color:red" title="'.$sTitle.'">'.Dict::S('iTopHub:InstallationEffect:MissingDependencies').'<span></label>'); 184 $oPage->add('<div class="description">'); 185 $oPage->add('<p>'); 186 if ($oExtension->sDescription != '') 187 { 188 $oPage->add(htmlentities($oExtension->sDescription, ENT_QUOTES, 'UTF-8').'</br>'); 189 } 190 $oPage->add('</p>'); 191 $oPage->add('</div>'); 192 $oPage->add('</div>'); 193 } 194 else 195 { 196 $aCSSClasses = array('landing-extension'); 197 if ($oExtension->sInstalledVersion === '') 198 { 199 $aCSSClasses[] = 'landing-installation'; 200 $sInstallation = Dict::Format('iTopHub:InstallationEffect:Install', $oExtension->sVersion); 201 } 202 else if ($oExtension->sInstalledVersion == $oExtension->sVersion) 203 { 204 $aCSSClasses[] = 'landing-no-change'; 205 $sInstallation = Dict::Format('iTopHub:InstallationEffect:NoChange', $oExtension->sVersion); 206 } 207 else if (version_compare($oExtension->sInstalledVersion, $oExtension->sVersion, '<')) 208 { 209 $aCSSClasses[] = 'landing-upgrade'; 210 $sInstallation = Dict::Format('iTopHub:InstallationEffect:Upgrade', $oExtension->sInstalledVersion, $oExtension->sVersion); 211 } 212 else 213 { 214 $aCSSClasses[] = 'landing-downgrade'; 215 $sInstallation = Dict::Format('iTopHub:InstallationEffect:Downgrade', $oExtension->sInstalledVersion, $oExtension->sVersion); 216 } 217 $oPage->add('<div class="choice">'); 218 $sCode = $oExtension->sCode; 219 $sDir = basename($oExtension->sSourceDir); 220 $oPage->add('<input type="checkbox" checked disabled data-extension-code="'.$sCode.'" data-extension-dir="'.$sDir.'"> '); 221 $oPage->add('<label><b>'.htmlentities($oExtension->sLabel, ENT_QUOTES, 'UTF-8').'</b> '.$sInstallation.'</label>'); 222 $oPage->add('<div class="description">'); 223 $oPage->add('<p>'); 224 if ($oExtension->sDescription != '') 225 { 226 $oPage->add(htmlentities($oExtension->sDescription, ENT_QUOTES, 'UTF-8').'</br>'); 227 } 228 $oPage->add('</p>'); 229 $oPage->add('</div>'); 230 $oPage->add('</div>'); 231 } 232 } 233 } 234 235 $oPage->add('<div id="hub-installation-feedback">'); 236 $oPage->add('<div id="hub-installation-progress-text">'.Dict::S('iTopHub:DatabaseBackupProgress').'</div>'); 237 $oPage->add('<div id="hub-installation-progress"></div>'); 238 $oPage->add('</div>'); 239 240 $oPage->add('</div>'); // module-selection-body 241 242 243 $oPage->add_linked_stylesheet('../css/font-awesome/css/font-awesome.min.css'); 244 $oPage->add('<div id="hub_installation_widget"></div>'); 245 $oPage->add('<fieldset id="database-backup-fieldset"><legend>'.Dict::S('iTopHub:DBBackupLabel').'</legend>'); 246 $oPage->add('<div id="backup_form"><input id="backup_checkbox" type="checkbox" checked><label for="backup_checkbox"> '.Dict::S('iTopHub:DBBackupSentence').'</label></div>'); 247 $oPage->add('<div id="backup_status"></div>'); 248 $oPage->add('</fieldset>'); 249 $oPage->add('<p style="text-align: center"><input type="button" id="hub_start_installation" type="button" disabled value="'.Dict::S('iTopHub:DeployBtn').'"/></p>'); 250 251 $sIframeUrl = utils::GetAbsoluteUrlModulePage('itop-hub-connector', 'launch.php', array('target' => 'inform_after_setup')); 252 $sStatusPageUrl = utils::GetAbsoluteUrlModulePage('itop-hub-connector', 'land.php', array('operation' => 'done')); 253 254 $aWidgetParams = array( 255 'self_url' => utils::GetAbsoluteUrlModulePage('itop-hub-connector', 'ajax.php'), 256 'iframe_url' => $sIframeUrl, 257 'redirect_after_completion_url' => $sStatusPageUrl, 258 'mysql_bindir' => MetaModel::GetConfig()->GetModuleSetting('itop-backup', 'mysql_bindir', ''), 259 'labels' => array( 260 'database_backup' => Dict::S('iTopHub:InstallationProgress:DatabaseBackup'), 261 'extensions_installation' => Dict::S('iTopHub:InstallationProgress:ExtensionsInstallation'), 262 'installation_successful' => Dict::S('iTopHub:InstallationProgress:InstallationSuccessful'), 263 'rollback' => Dict::S('iTopHub:ConfigurationSafelyReverted'), 264 ), 265 'authent' => $sUID, 266 ); 267 268 $sWidgetParams = json_encode($aWidgetParams); 269 270 $oPage->add_ready_script("$('#hub_installation_widget').hub_installation($sWidgetParams);"); 271 $oPage->add_ready_script("$('#hub_start_installation').click(function() { $('#hub_installation_widget').hub_installation('start_installation');} );"); 272 $oPage->add_ready_script("$('#hub_installation_widget').hub_installation('check_before_backup');"); 273 $oPage->add('<div id="debug"></div>'); 274} 275 276 277try 278{ 279 require_once(APPROOT.'/application/application.inc.php'); 280 require_once(APPROOT.'/setup/setuppage.class.inc.php'); 281 require_once(APPROOT.'/setup/extensionsmap.class.inc.php'); 282 require_once(APPROOT.'/application/startup.inc.php'); 283 require_once(APPROOT.'/application/loginwebpage.class.inc.php'); 284 285 LoginWebPage::DoLoginEx(null, true /* $bMustBeAdmin */); // Check user rights and prompt if needed 286 if (MetaModel::GetConfig()->Get('demo_mode')) throw new Exception('Sorry the installation of extensions is not allowed in demo mode'); 287 288 $oPage = new SetupPage(''); // Title will be set later, depending on $sOperation 289 $oPage->add_linked_script(utils::GetAbsoluteUrlModulesRoot().'itop-hub-connector/js/hub.js'); 290 $oPage->add_linked_stylesheet('../css/font-combodo/font-combodo.css'); 291 292 $oPage->add_style("div.choice { margin: 0.5em;}"); 293 $oPage->add_style("div.choice a { text-decoration:none; font-weight: bold; color: #1C94C4 }"); 294 $oPage->add_style("div.description { margin-left: 2em; }"); 295 $oPage->add_style("div.description p { margin-top: 0.25em; margin-bottom: 0.5em; }"); 296 $oPage->add_style(".choice-disabled { color: #999; }"); 297 298 299 $sOperation = utils::ReadParam('operation', 'land'); 300 301 switch($sOperation) 302 { 303 case 'done': 304 DisplayStatus($oPage); 305 break; 306 307 case 'install': 308 if (!file_exists(APPROOT.'data/hub')) 309 { 310 mkdir(APPROOT.'data/hub'); 311 } 312 DoInstall($oPage); 313 break; 314 315 case 'land': 316 default: 317 DoLanding($oPage); 318 } 319 320 $oPage->output(); 321 322} 323catch(Exception $e) 324{ 325 require_once(APPROOT.'/setup/setuppage.class.inc.php'); 326 $oP = new SetupPage(Dict::S('UI:PageTitle:FatalError')); 327 $oP->add("<h1>".Dict::S('UI:FatalErrorMessage')."</h1>\n"); 328 $oP->error(Dict::Format('UI:Error_Details', $e->getMessage())); 329 $oP->output(); 330 331 if (MetaModel::IsLogEnabledIssue()) 332 { 333 if (MetaModel::IsValidClass('EventIssue')) 334 { 335 $oLog = new EventIssue(); 336 337 $oLog->Set('message', $e->getMessage()); 338 $oLog->Set('userinfo', ''); 339 $oLog->Set('issue', 'PHP Exception'); 340 $oLog->Set('impact', 'Page could not be displayed'); 341 $oLog->Set('callstack', $e->getTrace()); 342 $oLog->Set('data', array()); 343 $oLog->DBInsertNoReload(); 344 } 345 346 IssueLog::Error($e->getMessage()); 347 } 348} 349