1<?php 2/** 3 * EGroupware Setup - Install, update & remove single apps 4 * 5 * @link http://www.egroupware.org 6 * @package setup 7 * @author Miles Lott <milos@groupwhere.org> 8 * @author Ralf Becker <RalfBecker-AT-outdoor-training.de> 9 * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License 10 * @version $Id$ 11 */ 12 13use EGroupware\Api; 14use EGroupware\Api\Framework; 15 16$DEBUG = @$_POST['debug'] || @$_GET['debug']; 17/* 18 TODO: We allow a user to hose their setup here, need to make use 19 of dependencies so they are warned that they are pulling the rug 20 out from under other apps. e.g. if they select to uninstall the api 21 this will happen without further warning. 22*/ 23 24include ('./inc/functions.inc.php'); 25 26@set_time_limit(0); 27 28// Check header and authentication 29if (!$GLOBALS['egw_setup']->auth('Config')) 30{ 31 Header('Location: index.php'); 32 exit; 33} 34// Does not return unless user is authorized 35 36$tpl_root = $GLOBALS['egw_setup']->html->setup_tpl_dir('setup'); 37$setup_tpl = new Framework\Template($tpl_root); 38$setup_tpl->set_file(array( 39 'T_head' => 'head.tpl', 40 'T_footer' => 'footer.tpl', 41 'T_alert_msg' => 'msg_alert_msg.tpl', 42 'T_login_main' => 'login_main.tpl', 43 'T_login_stage_header' => 'login_stage_header.tpl', 44 'T_setup_main' => 'applications.tpl' 45)); 46$setup_tpl->set_var('hidden_vars', Api\Html::input_hidden('csrf_token', Api\Csrf::token(__FILE__))); 47 48// check CSRF token for POST requests with any content (setup uses empty POST to call it's modules!) 49if ($_SERVER['REQUEST_METHOD'] == 'POST' && $_POST) 50{ 51 Api\Csrf::validate($_POST['csrf_token'], __FILE__); 52} 53 54$setup_tpl->set_block('T_login_stage_header','B_multi_domain','V_multi_domain'); 55$setup_tpl->set_block('T_login_stage_header','B_single_domain','V_single_domain'); 56$setup_tpl->set_block('T_setup_main','header','header'); 57$setup_tpl->set_block('T_setup_main','app_header','app_header'); 58$setup_tpl->set_block('T_setup_main','apps','apps'); 59$setup_tpl->set_block('T_setup_main','detail','detail'); 60$setup_tpl->set_block('T_setup_main','table','table'); 61$setup_tpl->set_block('T_setup_main','hook','hook'); 62$setup_tpl->set_block('T_setup_main','dep','dep'); 63$setup_tpl->set_block('T_setup_main','app_footer','app_footer'); 64$setup_tpl->set_block('T_setup_main','submit','submit'); 65$setup_tpl->set_block('T_setup_main','footer','footer'); 66 67$bgcolor = array('#DDDDDD','#EEEEEE'); 68 69function parsedep($depends,$main=True) 70{ 71 $depstring = '('; 72 foreach($depends as $b) 73 { 74 foreach($b as $c => $d) 75 { 76 if (is_array($d)) 77 { 78 $depstring .= $c . ': ' .implode(',',$d) . '; '; 79 $depver[] = $d; 80 } 81 else 82 { 83 $depstring .= $c . ': ' . $d . '; '; 84 $depapp[] = $d; 85 } 86 } 87 } 88 $depstring .= ')'; 89 if ($main) 90 { 91 return $depstring; 92 } 93 else 94 { 95 return array($depapp,$depver); 96 } 97} 98 99$GLOBALS['egw_setup']->loaddb(); 100$GLOBALS['egw_info']['setup']['stage']['db'] = $GLOBALS['egw_setup']->detection->check_db(); 101 102$setup_info = $GLOBALS['egw_setup']->detection->check_depends( 103 $GLOBALS['egw_setup']->detection->compare_versions( 104 $GLOBALS['egw_setup']->detection->get_db_versions( 105 $GLOBALS['egw_setup']->detection->get_versions()))); 106 107@ksort($setup_info); 108 109if(@$_POST['cancel']) 110{ 111 Header("Location: index.php"); 112 exit; 113} 114 115if(@$_POST['submit']) 116{ 117 $GLOBALS['egw_setup']->html->show_header(lang('Application Management'),False,'config',$GLOBALS['egw_setup']->ConfigDomain . '(' . $GLOBALS['egw_domain'][$GLOBALS['egw_setup']->ConfigDomain]['db_type'] . ')'); 118 $setup_tpl->set_var('description',lang('App install/remove/upgrade') . ':'); 119 $setup_tpl->pparse('out','header'); 120 121 $appname = $_POST['appname']; 122 $remove = $_POST['remove']; 123 $install = $_POST['install']; 124 $upgrade = $_POST['upgrade']; 125 126 $register_hooks = false; 127 128 if(!empty($remove) && is_array($remove)) 129 { 130 $register_hooks = $GLOBALS['egw_setup']->process->remove(array_keys($remove), $setup_info, $DEBUG) > 0; 131 } 132 133 if(!empty($install) && is_array($install)) 134 { 135 foreach($install as $appname => $key) 136 { 137 $app_title = $setup_info[$appname]['title'] ? $setup_info[$appname]['title'] : $setup_info[$appname]['name']; 138 $terror = array(); 139 $terror[$appname] = $setup_info[$appname]; 140 141 if ($setup_info[$appname]['tables']) 142 { 143 $terror_c = $GLOBALS['egw_setup']->process->current($terror, $DEBUG); 144 $terror = $GLOBALS['egw_setup']->process->default_records($terror_c, $DEBUG); 145 echo '<br />' . $app_title . ' ' 146 . lang('tables installed, unless there are errors printed above') . '.'; 147 } 148 else 149 { 150 // check default_records for apps without tables, they might need some initial work too 151 $terror = $GLOBALS['egw_setup']->process->default_records($terror,$DEBUG); 152 if ($GLOBALS['egw_setup']->app_registered($setup_info[$appname]['name'])) 153 { 154 $GLOBALS['egw_setup']->update_app($setup_info[$appname]['name']); 155 } 156 else 157 { 158 $GLOBALS['egw_setup']->register_app($setup_info[$appname]['name']); 159 } 160 echo '<br />' . $app_title . ' ' . lang('registered') . '.'; 161 162 if ($setup_info[$appname]['hooks']) 163 { 164 $register_hooks = true; 165 } 166 } 167 } 168 } 169 170 if(!empty($upgrade) && is_array($upgrade)) 171 { 172 foreach($upgrade as $appname => $key) 173 { 174 $app_title = $setup_info[$appname]['title'] ? $setup_info[$appname]['title'] : $setup_info[$appname]['name']; 175 $terror = array(); 176 $terror[$appname] = $setup_info[$appname]; 177 178 $GLOBALS['egw_setup']->process->upgrade($terror,$DEBUG); 179 if ($setup_info[$appname]['tables']) 180 { 181 echo '<br />' . $app_title . ' ' . lang('tables upgraded') . '.'; 182 // The process_upgrade() function also handles registration 183 } 184 else 185 { 186 echo '<br />' . $app_title . ' ' . lang('upgraded') . '.'; 187 } 188 $register_hooks = true; 189 } 190 } 191 192 if ($register_hooks) 193 { 194 Api\Hooks::read(true); 195 echo '<br />' . $app_title . ' ' . lang('hooks registered') . '.'; 196 } 197 198 //$setup_tpl->set_var('goback', 199 echo '<br /><a href="applications.php?debug='.$DEBUG.'">' . lang('Go back') . '</a>'; 200 //$setup_tpl->pparse('out','submit'); 201 $setup_tpl->pparse('out','footer'); 202 exit; 203} 204else 205{ 206 $GLOBALS['egw_setup']->html->show_header(lang('Application Management'),False,'config',$GLOBALS['egw_setup']->ConfigDomain . '(' . $GLOBALS['egw_domain'][$GLOBALS['egw_setup']->ConfigDomain]['db_type'] . ')'); 207} 208 209if(@$_GET['hooks']) 210{ 211 Api\Cache::flush(Api\Cache::INSTANCE); 212 213 echo lang('Cached cleared') . '<br />'; 214} 215$detail = $_GET['detail']; 216$resolve = $_GET['resolve']; 217if(@$detail) 218{ 219 @ksort($setup_info[$detail]); 220 $setup_tpl->set_var('description',lang('App details') . ':'); 221 $setup_tpl->pparse('out','header'); 222 223 $setup_tpl->set_var('name','application'); 224 $setup_tpl->set_var('details', lang($setup_info[$detail]['title'])); 225 $setup_tpl->pparse('out','detail'); 226 227 foreach($setup_info[$detail] as $key => $val) 228 { 229 switch($key) 230 { 231 case 'title': 232 continue 2; 233 case 'tables': 234 $tblcnt = count($setup_info[$detail][$key]); 235 if(is_array($val)) 236 { 237 $key = '<a href="sqltoarray.php?appname=' . $detail . '&submit=True&apps=True">' . $key . '(' . $tblcnt . ')</a>' . "\n"; 238 $val = implode(',' . "\n",$val); 239 } 240 break; 241 case 'hooks': 242 foreach($val as &$hooks) 243 { 244 $hooks = (array)$hooks; 245 } 246 $val = str_replace('EGroupware\\', '', implode(', ', call_user_func_array('array_merge', $val))); 247 break; 248 case 'depends': 249 foreach($val as &$dep) 250 { 251 $dep = $dep['appname'].': '.implode(', ', $dep['versions']); 252 } 253 $val = implode('; ', $val); 254 break; 255 case 'check_install': 256 $val = array2string($val); 257 break; 258 default: 259 if (is_array($val)) $val = implode(', ', $val); 260 break; 261 } 262 $setup_tpl->set_var('bg_color', $bgcolor[++$i & 1]); 263 $setup_tpl->set_var('name',$key); 264 $setup_tpl->set_var('details',$val); 265 $setup_tpl->pparse('out','detail'); 266 } 267 268 echo '<br /><a href="applications.php?debug='.$DEBUG.'">' . lang('Go back') . '</a>'; 269 $setup_tpl->pparse('out','footer'); 270 exit; 271} 272elseif (@$resolve) 273{ 274 $version = $_GET['version']; 275 $notables = $_GET['notables']; 276 $setup_tpl->set_var('description',lang('Problem resolution'). ':'); 277 $setup_tpl->pparse('out','header'); 278 $app_title = $setup_info[$resolve]['title'] ? $setup_info[$resolve]['title'] : $setup_info[$resolve]['name']; 279 280 if($_GET['post']) 281 { 282 echo '"' . $app_title . '" ' . lang('may be broken') . ' '; 283 echo lang('because an application it depends upon was upgraded'); 284 echo '<br />'; 285 echo lang('to a version it does not know about') . '.'; 286 echo '<br />'; 287 echo lang('However, the application may still work') . '.'; 288 } 289 elseif($_GET['badinstall']) 290 { 291 echo '"' . $app_title . '" ' . lang('is broken') . ' '; 292 echo lang('because of a failed upgrade or install') . '.'; 293 echo '<br />'; 294 echo lang('Some or all of its tables are missing') . '.'; 295 echo '<br />'; 296 echo lang('You should either uninstall and then reinstall it, or attempt manual repairs') . '.'; 297 } 298 elseif($_GET['deleted']) 299 { 300 echo '"' . $app_title . '" ' . lang('is broken') . ' '; 301 echo lang('because its sources are missing') . '!'; 302 echo '<br />'; 303 echo lang('However the tables are still in the database') . '.'; 304 echo '<br />'; 305 echo lang('You should either install the sources or uninstall it, to get rid of the tables') . '.'; 306 } 307 elseif (!$version) 308 { 309 if($setup_info[$resolve]['enabled']) 310 { 311 echo '"' . $app_title . '" ' . lang('is broken') . ' '; 312 } 313 else 314 { 315 echo '"' . $app_title . '" ' . lang('is disabled') . ' '; 316 } 317 318 if (!$notables) 319 { 320 if($setup_info[$resolve]['status'] == 'D') 321 { 322 echo lang('because it depends upon') . ':<br />' . "\n"; 323 list($depapp,$depver) = parsedep($setup_info[$resolve]['depends'],False); 324 $depapp_count = count($depapp); 325 for ($i=0; $i<$depapp_count; $i++) 326 { 327 echo '<br />' . $depapp[$i] . ': '; 328 $list = ''; 329 foreach($depver[$i] as $x => $y) 330 { 331 $list .= $y . ', '; 332 } 333 echo substr($list,0,-2)."\n"; 334 } 335 echo '<br /><br />' . lang('The table definition was correct, and the tables were installed') . '.'; 336 } 337 else 338 { 339 echo lang('because it was manually disabled') . '.'; 340 } 341 } 342 elseif($setup_info[$resolve]['enable'] == 2) 343 { 344 echo lang('because it is not a user application, or access is controlled via acl') . '.'; 345 } 346 elseif($setup_info[$resolve]['enable'] == 0) 347 { 348 echo lang('because the enable flag for this app is set to 0, or is undefined') . '.'; 349 } 350 else 351 { 352 echo lang('because it requires manual table installation, <br />or the table definition was incorrect') . ".\n" 353 . lang("Please check for sql scripts within the application's directory") . '.'; 354 } 355 echo '<br />' . lang('However, the application is otherwise installed') . '.'; 356 } 357 else 358 { 359 echo $app_title . ' ' . lang('has a version mismatch') . ' '; 360 echo lang('because of a failed upgrade, or the database is newer than the installed version of this app') . '.'; 361 echo '<br />'; 362 echo lang('If the application has no defined tables, selecting upgrade should remedy the problem') . '.'; 363 echo '<br />' . lang('However, the application is otherwise installed') . '.'; 364 } 365 366 echo '<br /><a href="applications.php?debug='.$DEBUG.'">' . lang('Go back') . '</a>'; 367 $setup_tpl->pparse('out','footer'); 368 exit; 369} 370else 371{ 372 $setup_tpl->set_var('description',lang('Select the desired action(s) from the available choices')); 373 $setup_tpl->set_var('action_url','applications.php'); 374 $setup_tpl->pparse('out','header'); 375 376 $setup_tpl->set_var('appdata',lang('Application Data')); 377 $setup_tpl->set_var('actions',lang('Actions')); 378 $setup_tpl->set_var('app_info',lang('Application Name and Status Information')); 379 $setup_tpl->set_var('app_title',lang('Application Title')); 380 $setup_tpl->set_var('app_currentver',lang('Current Version')); 381 $setup_tpl->set_var('app_version',lang('Available Version')); 382 $setup_tpl->set_var('app_install',lang('Install')); 383 $setup_tpl->set_var('app_remove',lang('Remove')); 384 $setup_tpl->set_var('app_upgrade',lang('Upgrade')); 385 $setup_tpl->set_var('app_resolve',lang('Resolve')); 386 $setup_tpl->set_var('check','check.png'); 387 $setup_tpl->set_var('install_all',lang('Install All')); 388 $setup_tpl->set_var('upgrade_all',lang('Upgrade All')); 389 $setup_tpl->set_var('remove_all',lang('Remove All')); 390 $setup_tpl->set_var('lang_debug',lang('enable for extra debug-messages')); 391 $setup_tpl->set_var('debug','<input type="checkbox" name="debug" value="True"' .($DEBUG ? ' checked="checked"' : '') . ' />'); 392 $setup_tpl->set_var('bg_color',$bgcolor[0]); 393 394 $setup_tpl->pparse('out','app_header'); 395 396 $i = 0; 397 foreach($setup_info as $key => $value) 398 { 399 if(@$value['name']) 400 { 401 $i = ($i ? 0 : 1); 402 $setup_tpl->set_var('apptitle',$value['title']?$value['title']:lang($value['name'])); 403 $setup_tpl->set_var('currentver',@$value['currentver']); 404 $setup_tpl->set_var('version',$value['version']); 405 $setup_tpl->set_var('bg_color',$bgcolor[$i]); 406 407 switch($value['status']) 408 { 409 case 'C': 410 $setup_tpl->set_var('remove', $key == 'api' ? ' ' : '<input type="checkbox" name="remove[' . $value['name'] . ']" />'); 411 $setup_tpl->set_var('upgrade',' '); 412 if (!$GLOBALS['egw_setup']->detection->check_app_tables($value['name'])) 413 { 414 // App installed and enabled, but some tables are missing 415 $setup_tpl->set_var('instimg','table.png'); 416 $setup_tpl->set_var('bg_color','FFCCAA'); 417 $setup_tpl->set_var('instalt',lang('Not Completed')); 418 $setup_tpl->set_var('resolution','<a href="applications.php?resolve=' . $value['name'] . '&badinstall=True">' . lang('Potential Problem') . '</a>'); 419 $status = lang('Requires reinstall or manual repair') . ' - ' . $value['status']; 420 } 421 else 422 { 423 $setup_tpl->set_var('instimg','completed.png'); 424 $setup_tpl->set_var('instalt',lang('Completed')); 425 $setup_tpl->set_var('install',' '); 426 if($value['enabled']) 427 { 428 $setup_tpl->set_var('resolution',''); 429 $status = lang('OK') . ' - ' . $value['status']; 430 } 431 else 432 { 433 if ($value['tables'][0] != '') 434 { 435 $notables = '¬ables=True'; 436 } 437 $setup_tpl->set_var('bg_color','CCCCFF'); 438 $setup_tpl->set_var('resolution', 439 '<a href="applications.php?resolve=' . $value['name'] . $notables . '">' . lang('Possible Reasons') . '</a>' 440 ); 441 $status = lang('Disabled') . ' - ' . $value['status']; 442 } 443 } 444 break; 445 case 'U': 446 $setup_tpl->set_var('instimg','incomplete.png'); 447 $setup_tpl->set_var('instalt',lang('Not Completed')); 448 if (!@$value['currentver']) 449 { 450 if ($value['tables'] && $GLOBALS['egw_setup']->detection->check_app_tables($value['name'],True)) 451 { 452 // Some tables missing 453 $setup_tpl->set_var('remove',$key == 'api' ? ' ' : '<input type="checkbox" name="remove[' . $value['name'] . ']" />'); 454 $setup_tpl->set_var('resolution','<a href="applications.php?resolve=' . $value['name'] . '&badinstall=True">' . lang('Potential Problem') . '</a>'); 455 $status = lang('Requires reinstall or manual repair') . ' - ' . $value['status']; 456 } 457 else 458 { 459 $setup_tpl->set_var('remove',' '); 460 $setup_tpl->set_var('resolution',''); 461 $status = lang('Requires upgrade') . ' - ' . $value['status']; 462 } 463 // show not installed apps without icon 464 $setup_tpl->set_var('instimg','spacer.png'); 465 $setup_tpl->set_var('instalt',''); 466 $setup_tpl->set_var('bg_color','CCFFCC'); 467 $setup_tpl->set_var('install','<input type="checkbox" name="install[' . $value['name'] . ']" />'); 468 $setup_tpl->set_var('upgrade',' '); 469 $status = lang('Please install') . ' - ' . $value['status']; 470 } 471 else 472 { 473 $setup_tpl->set_var('bg_color','CCCCFF'); 474 $setup_tpl->set_var('install',' '); 475 // TODO display some info about breakage if you mess with this app 476 $setup_tpl->set_var('upgrade','<input type="checkbox" name="upgrade[' . $value['name'] . ']" />'); 477 $setup_tpl->set_var('remove',$key == 'api' ? ' ' : '<input type="checkbox" name="remove[' . $value['name'] . ']" />'); 478 $setup_tpl->set_var('resolution',''); 479 $status = lang('Requires upgrade') . ' - ' . $value['status']; 480 } 481 break; 482 case 'V': 483 $setup_tpl->set_var('instimg','incomplete.png'); 484 $setup_tpl->set_var('instalt',lang('Not Completed')); 485 $setup_tpl->set_var('install',' '); 486 $setup_tpl->set_var('remove',$key == 'api' ? ' ' : '<input type="checkbox" name="remove[' . $value['name'] . ']" />'); 487 if ($value['version'] == 'deleted') 488 { 489 $setup_tpl->set_var('bg_color','CCAAAA'); 490 $setup_tpl->set_var('upgrade',' '); 491 $setup_tpl->set_var('resolution','<a href="applications.php?resolve=' . $value['name'] . '&deleted=True">' . lang('Possible Solutions') . '</a>'); 492 $status = lang('Sources deleted/missing') . ' - ' . $value['status']; 493 } 494 else 495 { 496 $setup_tpl->set_var('upgrade','<input type="checkbox" name="upgrade[' . $value['name'] . ']" />'); 497 $setup_tpl->set_var('resolution','<a href="applications.php?resolve=' . $value['name'] . '&version=True">' . lang('Possible Solutions') . '</a>'); 498 $status = lang('Version Mismatch') . ' - ' . $value['status']; 499 } 500 break; 501 case 'D': 502 $setup_tpl->set_var('bg_color','FFCCCC'); 503 $depstring = parsedep($value['depends']); 504 $depstring .= ')'; 505 $setup_tpl->set_var('instimg','dep.png'); 506 $setup_tpl->set_var('instalt',lang('Dependency Failure')); 507 $setup_tpl->set_var('install',' '); 508 if ($values['currentver']) 509 { 510 $setup_tpl->set_var('remove',$key == 'api' ? ' ' : '<input type="checkbox" name="remove[' . $value['name'] . ']" />'); 511 $setup_tpl->set_var('resolution','<a href="applications.php?resolve=' . $value['name'] . '">' . lang('Possible Solutions') . '</a>'); 512 } 513 else 514 { 515 $setup_tpl->set_var('remove',' '); 516 $setup_tpl->set_var('resolution',' '); 517 } 518 $setup_tpl->set_var('upgrade',' '); 519 $status = lang('Dependency Failure') . ':' . $depstring . $value['status']; 520 break; 521 case 'P': 522 $setup_tpl->set_var('bg_color','FFCCFF'); 523 $depstring = parsedep($value['depends']); 524 $depstring .= ')'; 525 $setup_tpl->set_var('instimg','dep.png'); 526 $setup_tpl->set_var('instalt',lang('Post-install Dependency Failure')); 527 $setup_tpl->set_var('install',' '); 528 $setup_tpl->set_var('remove',' '); 529 $setup_tpl->set_var('upgrade',' '); 530 $setup_tpl->set_var('resolution','<a href="applications.php?resolve=' . $value['name'] . '&post=True">' . lang('Possible Solutions') . '</a>'); 531 $status = lang('Post-install Dependency Failure') . ':' . $depstring . $value['status']; 532 break; 533 default: 534 $setup_tpl->set_var('instimg','incomplete.png'); 535 $setup_tpl->set_var('instalt',lang('Not Completed')); 536 $setup_tpl->set_var('install',' '); 537 $setup_tpl->set_var('remove',' '); 538 $setup_tpl->set_var('upgrade',' '); 539 $setup_tpl->set_var('resolution',''); 540 $status = ''; 541 break; 542 } 543 //$setup_tpl->set_var('appname',$value['name'] . '-' . $status . ',' . $value['filename']); 544 $setup_tpl->set_var('appinfo',$value['name'] . '-' . $status); 545 $setup_tpl->set_var('appname',$value['name']); 546 547 $setup_tpl->pparse('out','apps',True); 548 } 549 } 550 551 $setup_tpl->set_var('submit',lang('Save')); 552 $setup_tpl->set_var('cancel',lang('Cancel')); 553 $setup_tpl->pparse('out','app_footer'); 554 $setup_tpl->pparse('out','footer'); 555 $GLOBALS['egw_setup']->html->show_footer(); 556} 557