diff --git a/.gitignore b/.gitignore index d57bdee03..a243728f3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,11 @@ # Exclude all hidden files .* -# But not .gitignore, .vagrant-puppet, .htaccess and .gitkeep +# But not .gitignore, .gitattributes, .vagrant-puppet, .htaccess and .gitkeep !.gitignore +!.gitattributes !.vagrant-puppet !public/.htaccess +!packages/rhel/usr/share/icingaweb/public/.htaccess !public/.htaccess.in !.gitkeep diff --git a/.vagrant-puppet/.gitattributes b/.vagrant-puppet/.gitattributes new file mode 100644 index 000000000..af67531d8 --- /dev/null +++ b/.vagrant-puppet/.gitattributes @@ -0,0 +1 @@ +* -crlf diff --git a/.vagrant-puppet/files/etc/icinga2/conf.d/commands.conf b/.vagrant-puppet/files/etc/icinga2/conf.d/commands.conf new file mode 100644 index 000000000..9000ac090 --- /dev/null +++ b/.vagrant-puppet/files/etc/icinga2/conf.d/commands.conf @@ -0,0 +1,48 @@ +/* Command objects */ + +object CheckCommand "kernel" { + import "plugin-check-command" + + command = [ "sudo", SysconfDir + "/icinga2/scripts/check_kernel" ] +} + +object NotificationCommand "mail-host-notification" { + import "plugin-notification-command" + + command = [ "/bin/true" ] + + env = { + "NOTIFICATIONTYPE" = "$notification.type$" + "HOSTALIAS" = "$host.display_name$", + "HOSTADDRESS" = "$address$", + "HOSTSTATE" = "$host.state$", + "LONGDATETIME" = "$icinga.long_date_time$", + "HOSTOUTPUT" = "$host.output$", + "NOTIFICATIONAUTHORNAME" = "$notification.author$", + "NOTIFICATIONCOMMENT" = "$notification.comment$", + "HOSTDISPLAYNAME" = "$host.display_name$", + "USEREMAIL" = "$user.email$" + } +} + +object NotificationCommand "mail-service-notification" { + import "plugin-notification-command" + + command = [ "/bin/true" ] + + env = { + "NOTIFICATIONTYPE" = "$notification.type$" + "SERVICEDESC" = "$service.name$" + "HOSTALIAS" = "$host.display_name$", + "HOSTADDRESS" = "$address$", + "SERVICESTATE" = "$service.state$", + "LONGDATETIME" = "$icinga.long_date_time$", + "SERVICEOUTPUT" = "$service.output$", + "NOTIFICATIONAUTHORNAME" = "$notification.author$", + "NOTIFICATIONCOMMENT" = "$notification.comment$", + "HOSTDISPLAYNAME" = "$host.display_name$", + "SERVICEDISPLAYNAME" = "$service.display_name$", + "USEREMAIL" = "$user.email$" + } +} + diff --git a/.vagrant-puppet/files/etc/icinga2/conf.d/test-config.conf b/.vagrant-puppet/files/etc/icinga2/conf.d/test-config.conf new file mode 100644 index 000000000..412307328 --- /dev/null +++ b/.vagrant-puppet/files/etc/icinga2/conf.d/test-config.conf @@ -0,0 +1,113 @@ +object CheckCommand "dummy-host" { + import "plugin-check-command" + command = [ PluginDir + "/libexec/test_hostcheck.pl" ] + arguments = { + "--type" = "$check_type$" + "--failchance" = "$check_failchance$" + "--previous-state" = "$check_previous_state$" + "--state-duration" = "$check_state_duration$" + "--hostname" = "$check_hostname$" + } + + vars.check_type = "UP" + vars.check_failchance = "2%" + vars.check_previous_state = "$state$" + vars.check_state_duration = "$duration_sec$" + vars.check_hostname = "$name$" +} + +object CheckCommand "dummy-service" { + import "plugin-check-command" + command = [ PluginDir + "/libexec/test_servicecheck.pl" ] + arguments = { + "--total-critical-on-host" = "$check_critical_on_host$" + "--total-warning-on-host" = "$check_warning_on_host$" + "--type" = "$check_type$" + "--failchance" = "$check_failchance$" + "--previous-state" = "$check_previous_state$" + "--state-duration" = "$check_state_duration$" + "--hostname" = "$check_hostname$" + "--servicedesc" = "$check_servicedesc$" + } + vars.check_critical_on_host = "$host.total_services_critical$" + vars.check_warning_on_host = "$host.total_services_warning$" + vars.check_type = "random" + vars.check_failchange = "5%" + vars.check_previous_state = "$service.state$" + vars.check_duration = "$service.duration_sec$" + vars.check_hostname = "$host.name$" + vars.check_servicedesc = "$service.name$" +} + +// Hostgroups +object HostGroup "all-hosts" { + display_name = "All hosts on the system" + assign where true +} + +host_types = ["ok", "random", "down", "up", "unreachable", "pending"] + +__for (host_type in host_types) { + object HostGroup "all-" + host_type { + display_name = "All " + host_type + " hosts" + assign where regex("^test-" + host_type, host.name) + } +} + +service_types = ["ok", "warning", "critical", "unknown", "flapping", "pending"] + +// Servicegroups +__for (service_type in service_types) { + object ServiceGroup "service-" + service_type { + display_name = "All " + service_type + " services" + assign where regex("^service-" + service_type, service.name) + } +} + +// --------------------------------------------------------------------------------------------------------------------- +// Services +// --------------------------------------------------------------------------------------------------------------------- + +__function createService(service_type, num) { + apply Service "service-" + service_type + "-" + string(num + 1) { + import "generic-service" + + check_command = "dummy-service" + enable_active_checks = (service_type != "pending") + vars.check_type = service_type + + assign where match("*" + service_type + "*", host.vars.check_config) + } +} + +__for (num in range(4)) { + __for (service_type in service_types) { + createService(service_type, num) + } +} + +// --------------------------------------------------------------------------------------------------------------------- +// Hosts +// --------------------------------------------------------------------------------------------------------------------- + +__function createHost(checkType, checkConfig, num, checkEnabled) { + object Host "test-" + checkType + "-" + string(num + 1) { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + enable_active_checks = checkEnabled + vars.check_type = checkType + vars.check_config = checkConfig + } +} + +__for (num in range(10)) { + createHost("ok", "ok", num, true) + createHost("random", "random,flapping", num, true) + createHost("down", "warning,critical", num, true) + createHost("unreachable", "unknown", num, true) + createHost("pending", "pending", num, false) + createHost("flap", "flapping", num, true) +} + +// EOF diff --git a/.vagrant-puppet/files/etc/icinga2/features-available/ido-mysql.conf b/.vagrant-puppet/files/etc/icinga2/features-available/ido-mysql.conf new file mode 100644 index 000000000..3e278fe2d --- /dev/null +++ b/.vagrant-puppet/files/etc/icinga2/features-available/ido-mysql.conf @@ -0,0 +1,13 @@ +/** + * The db_ido_mysql library implements IDO functionality + * for MySQL. + */ + +library "db_ido_mysql" + +object IdoMysqlConnection "ido-mysql" { + user = "icinga2", + password = "icinga2", + host = "localhost", + database = "icinga2" +} diff --git a/.vagrant-puppet/files/etc/icinga2/features-available/ido-pgsql.conf b/.vagrant-puppet/files/etc/icinga2/features-available/ido-pgsql.conf new file mode 100644 index 000000000..e16cc6c3d --- /dev/null +++ b/.vagrant-puppet/files/etc/icinga2/features-available/ido-pgsql.conf @@ -0,0 +1,13 @@ +/** + * The db_ido_pgsql library implements IDO functionality + * for PostgreSQL. + */ + +library "db_ido_pgsql" + +object IdoPgsqlConnection "ido-pgsql" { + user = "icinga2", + password = "icinga2", + host = "localhost", + database = "icinga2" +} diff --git a/.vagrant-puppet/files/etc/icingaweb/modules/monitoring/instances.ini b/.vagrant-puppet/files/etc/icingaweb/modules/monitoring/instances.ini index 2f54e11e3..037baa8b9 100644 --- a/.vagrant-puppet/files/etc/icingaweb/modules/monitoring/instances.ini +++ b/.vagrant-puppet/files/etc/icingaweb/modules/monitoring/instances.ini @@ -1,2 +1,2 @@ [icinga] -path = "/usr/local/icinga-mysql/var/rw/icinga.cmd" +path = "/var/run/icinga2/cmd/icinga2.cmd" diff --git a/.vagrant-puppet/files/etc/icingaweb/resources.ini b/.vagrant-puppet/files/etc/icingaweb/resources.ini index 2ef51e921..3935906eb 100644 --- a/.vagrant-puppet/files/etc/icingaweb/resources.ini +++ b/.vagrant-puppet/files/etc/icingaweb/resources.ini @@ -12,9 +12,9 @@ type = db db = mysql host = localhost port = 3306 -password = icinga -username = icinga -dbname = icinga +password = icinga2 +username = icinga2 +dbname = icinga2 [statusdat] type = statusdat diff --git a/.vagrant-puppet/manifests/default.pp b/.vagrant-puppet/manifests/default.pp index 9c5666a89..db17e8576 100644 --- a/.vagrant-puppet/manifests/default.pp +++ b/.vagrant-puppet/manifests/default.pp @@ -5,21 +5,29 @@ include openldap Exec { path => '/bin:/usr/bin:/sbin' } -$icingaVersion = '1.9.4' -$icinga2Version = '0.0.6' +$icingaVersion = '1.11.2' +$icinga2Version = '0.0.11' exec { 'create-mysql-icinga-db': unless => 'mysql -uicinga -picinga icinga', command => 'mysql -uroot -e "CREATE DATABASE icinga; \ - GRANT ALL ON icinga.* TO icinga@localhost \ + GRANT SELECT,INSERT,UPDATE,DELETE ON icinga.* TO icinga@localhost \ IDENTIFIED BY \'icinga\';"', require => Service['mysqld'] } +exec { 'create-mysql-icinga2-db': + unless => 'mysql -uicinga2 -picinga2 icinga2', + command => 'mysql -uroot -e "CREATE DATABASE icinga2; \ + GRANT SELECT,INSERT,UPDATE,DELETE ON icinga2.* to icinga2@localhost \ + IDENTIFIED BY \'icinga2\';"', + require => Service['mysqld'] +} + exec{ 'create-pgsql-icinga-db': unless => 'sudo -u postgres psql -tAc "SELECT 1 FROM pg_roles WHERE rolname=\'icinga\'" | grep -q 1', command => 'sudo -u postgres psql -c "CREATE ROLE icinga WITH LOGIN PASSWORD \'icingaweb\';" && \ - sudo -u postgres createdb -O icinga -E UTF8 icinga && \ + sudo -u postgres createdb -O icinga -E UTF8 -T template0 icinga && \ sudo -u postgres createlang plpgsql icinga', require => Service['postgresql'] } @@ -40,6 +48,11 @@ group { 'icinga-cmd': ensure => present } +group { 'icingacmd': + ensure => present, + require => Exec['install icinga2'] +} + user { 'icinga': ensure => present, groups => 'icinga-cmd', @@ -47,8 +60,8 @@ user { 'icinga': } user { 'apache': - groups => ['icinga-cmd', 'vagrant'], - require => [ Class['apache'], Group['icinga-cmd'] ] + groups => ['icinga-cmd', 'vagrant', 'icingacmd'], + require => [ Class['apache'], Group['icinga-cmd'], Group['icingacmd'] ] } cmmi { 'icinga-mysql': @@ -104,7 +117,7 @@ file { '/etc/init.d/ido2db-pgsql': exec { 'populate-icinga-mysql-db': unless => 'mysql -uicinga -picinga icinga -e "SELECT * FROM icinga_dbversion;" &> /dev/null', - command => "mysql -uicinga -picinga icinga < /usr/local/src/icinga-mysql/icinga-${icingaVersion}/module/idoutils/db/mysql/mysql.sql", + command => "mysql -uroot icinga < /usr/local/src/icinga-mysql/icinga-${icingaVersion}/module/idoutils/db/mysql/mysql.sql", require => [ Cmmi['icinga-mysql'], Exec['create-mysql-icinga-db'] ] } @@ -330,7 +343,91 @@ package { ['cmake', 'boost-devel', 'bison', 'flex']: ensure => installed } -#cmmi { 'icinga2': +yumrepo { 'icinga2-repo': + baseurl => "http://packages.icinga.org/epel/6/snapshot/", + enabled => '0', + gpgcheck => '1', + gpgkey => 'http://packages.icinga.org/icinga.key', + descr => "Icinga Repository - ${::architecture}" +} + +exec { 'install icinga2': + command => 'yum -d 0 -e 0 -y --enablerepo=icinga2-repo install icinga2', + unless => 'rpm -qa | grep icinga2', + require => Yumrepo['icinga2-repo'] +} + +exec { 'install icinga2-classicui-config': + command => 'yum -d 0 -e 0 -y --enablerepo=icinga2-repo install icinga2-classicui-config', + unless => 'rpm -qa | grep icinga2-classicui-config', + require => [ Yumrepo['icinga2-repo'], Exec['install icinga2'], Exec['install icinga2-ido-mysql'] ] +} + +exec { 'install icinga2-ido-mysql': + command => 'yum -d 0 -e 0 -y --enablerepo=icinga2-repo install icinga2-ido-mysql', + unless => 'rpm -qa | grep icinga2-ido-mysql', + require => [ Yumrepo['icinga2-repo'], Exec['install icinga2'] ], +} + +exec { 'install nagios-plugins-all': + command => 'yum -d 0 -e 0 -y --enablerepo=epel install nagios-plugins-all', + unless => 'rpm -qa | grep nagios-plugins-all', + require => [ Class['epel'], Exec['install icinga2'] ], +} + +file { '/etc/icinga2/features-enabled/': + ensure => directory, + owner => icinga, + group => icinga, + require => Exec['install icinga2-ido-mysql'] +} + +file { '/etc/icinga2/features-available/ido-mysql.conf': + source => 'puppet:////vagrant/.vagrant-puppet/files/etc/icinga2/features-available/ido-mysql.conf', + owner => 'icinga', + group => 'icinga', + require => Exec['install icinga2-ido-mysql'] +} + +file { '/etc/icinga2/features-enabled/ido-mysql.conf': + ensure => 'link', + target => '/etc/icinga2/features-available/ido-mysql.conf', + owner => 'root', + group => 'root', + require => Exec['install icinga2-ido-mysql'] +} + +file { '/etc/icinga2/conf.d/test-config.conf': + source => 'puppet:////vagrant/.vagrant-puppet/files/etc/icinga2/conf.d/test-config.conf', + owner => 'icinga', + group => 'icinga', + require => [ Exec['install icinga2'], Exec['create_monitoring_test_config'] ] +} + +file { '/etc/icinga2/conf.d/commands.conf': + source => 'puppet:////vagrant/.vagrant-puppet/files/etc/icinga2/conf.d/commands.conf', + owner => 'icinga', + group => 'icinga', + require => Exec['install icinga2'] +} + +service { 'icinga2': + ensure => running, + require => [ + Exec['install icinga2'], + File['/etc/icinga2/features-enabled/ido-mysql.conf'], + File['/etc/icinga2/conf.d/test-config.conf'], + File['/etc/icinga2/conf.d/commands.conf'] + ] +} + +exec { 'populate-icinga2-mysql-db': + unless => 'mysql -uicinga2 -picinga2 icinga2 -e "SELECT * FROM icinga_dbversion;" &> /dev/null', + command => "mysql -uroot icinga2 < /usr/share/doc/icinga2-ido-mysql-$icinga2Version/schema/mysql.sql", + require => [ Exec['create-mysql-icinga2-db'], Exec['install icinga2-ido-mysql'] ] +} + +# cmmi { 'icinga2': # url => "https://github.com/Icinga/icinga2/releases/download/v${icinga2Version}/icinga2-${icinga2Version}.tar.gz", # output => "icinga2-${icinga2Version}.tar.gz", # configure_command => 'mkdir build &> /dev/null || true && cd build && sudo cmake ..', @@ -338,7 +435,7 @@ package { ['cmake', 'boost-devel', 'bison', 'flex']: # make => 'true && cd build/ && make && make install', # require => Package[ ['cmake', 'boost-devel', 'bison', 'flex'] ], # make_timeout => 900 -#} +# } #configure { 'icingaweb': # path => '/vagrant', @@ -388,7 +485,7 @@ exec { 'create-mysql-icinga_unittest-db': exec{ 'create-pgsql-icinga_unittest-db': unless => 'sudo -u postgres psql -tAc "SELECT 1 FROM pg_roles WHERE rolname=\'icinga_unittest\'" | grep -q 1', command => 'sudo -u postgres psql -c "CREATE ROLE icinga_unittest WITH LOGIN PASSWORD \'icinga_unittest\';" && \ - sudo -u postgres createdb -O icinga_unittest -E UTF8 icinga_unittest && \ + sudo -u postgres createdb -O icinga_unittest -E UTF8 -T template0 icinga_unittest && \ sudo -u postgres createlang plpgsql icinga_unittest', require => Service['postgresql'] } @@ -483,7 +580,7 @@ exec { 'create-mysql-icingaweb-db': exec { 'create-pgsql-icingaweb-db': unless => 'sudo -u postgres psql -tAc "SELECT 1 FROM pg_roles WHERE rolname=\'icingaweb\'" | grep -q 1', command => 'sudo -u postgres psql -c "CREATE ROLE icingaweb WITH LOGIN PASSWORD \'icinga\';" && \ - sudo -u postgres createdb -O icingaweb -E UTF8 icingaweb && \ + sudo -u postgres createdb -O icingaweb -E UTF8 -T template0 icingaweb && \ sudo -u postgres createlang plpgsql icingaweb', require => Service['postgresql'] } @@ -699,6 +796,6 @@ file { '/etc/icingaweb/dashboard/dashboard.ini': group => 'apache', } -pear::package { 'deepend/Mockery': - channel => 'pear.survivethedeepend.com' -} +# pear::package { 'deepend/Mockery': +# channel => 'pear.survivethedeepend.com' +# } diff --git a/application/controllers/ErrorController.php b/application/controllers/ErrorController.php index 343a40b7f..74e2e8b52 100644 --- a/application/controllers/ErrorController.php +++ b/application/controllers/ErrorController.php @@ -66,8 +66,9 @@ class ErrorController extends ActionController break; default: + $title = preg_replace('/\r?\n.*$/s', '', $exception->getMessage()); $this->getResponse()->setHttpResponseCode(500); - $this->view->title = 'Server error: ' . $exception->getMessage(); + $this->view->title = 'Server error: ' . $title; $this->view->message = $exception->getMessage(); if ($this->getInvokeArg('displayExceptions') == true) { $this->view->stackTrace = $exception->getTraceAsString(); diff --git a/application/controllers/InstallController.php b/application/controllers/InstallController.php new file mode 100644 index 000000000..da320a6b1 --- /dev/null +++ b/application/controllers/InstallController.php @@ -0,0 +1,111 @@ +createWizard(); + + if ($wizard->isSubmittedAndValid()) { + $wizard->navigate(); + if ($wizard->isFinished()) { + // TODO: Run the installer (Who creates an installer? How do we handle module installers?) + $this->dropConfiguration(); // TODO: Should only be done if the installation has been successfully completed + $this->view->installer = ''; + } else { + $this->storeConfiguration($wizard->getConfig()); + } + } + + $this->view->wizard = $wizard; + } + + /** + * Create the wizard and register all pages + * + * @return Wizard + */ + protected function createWizard() + { + $wizard = new Wizard(); + $wizard->setTitle('Web'); + $wizard->setRequest($this->getRequest()); + $wizard->setConfiguration($this->loadConfiguration()); + $wizard->addPages( + array( +// t('Welcome') => 'Icinga\Form\Install\WelcomePage', +// t('Requirements') => 'Icinga\Form\Install\RequirementsPage', +// t('Authentication') => 'Icinga\Form\Install\AuthenticationPage', +// t('Administration') => 'Icinga\Form\Install\AdministrationPage', +// t('Preferences') => 'Icinga\Form\Install\PreferencesPage', + t('Logging') => 'Icinga\Form\Install\LoggingPage', +// t('Database Setup') => 'Icinga\Form\Install\DatabasePage', +// t('Summary') => 'Icinga\Form\Install\SummaryPage' + ) + ); + + return $wizard; + } + + /** + * Store the given configuration values + * + * @param Zend_Config $config The configuration + */ + protected function storeConfiguration(Zend_Config $config) + { + $session = Session::getSession(); + $session->getNamespace('WebWizard')->setAll($config->toArray(), true); + $session->write(); + } + + /** + * Load all configuration values + * + * @return Zend_Config + */ + protected function loadConfiguration() + { + return new Zend_Config(Session::getSession()->getNamespace('WebWizard')->getAll(), true); + } + + /** + * Clear all stored configuration values + */ + protected function dropConfiguration() + { + $session = Session::getSession(); + $session->removeNamespace('WebWizard'); + $session->write(); + } +} + +// @codeCoverageIgnoreEnd diff --git a/application/forms/Config/LoggingForm.php b/application/forms/Config/LoggingForm.php index eff629e09..81540a683 100644 --- a/application/forms/Config/LoggingForm.php +++ b/application/forms/Config/LoggingForm.php @@ -30,7 +30,7 @@ namespace Icinga\Form\Config; -use Zend_Config; +use \Zend_Config; use Icinga\Web\Form; use Icinga\Application\Icinga; use Icinga\Web\Form\Validator\WritablePathValidator; @@ -116,7 +116,19 @@ class LoggingForm extends Form 'required' => true, 'label' => t('Application Prefix'), 'helptext' => t('The name of the application by which to prefix syslog messages.'), - 'value' => $loggingConfig->get('application', 'icingaweb') + 'value' => $loggingConfig->get('application', 'icingaweb'), + 'validators' => array( + array( + 'Regex', + false, + array( + 'pattern' => '/^[^\W]+$/', + 'messages' => array( + 'regexNotMatch' => 'The application prefix cannot contain any whitespaces.' + ) + ) + ) + ) ) ); $this->addElement( @@ -151,6 +163,16 @@ class LoggingForm extends Form $this->setSubmitLabel('{{SAVE_ICON}} Save Changes'); } + public function isValid($data) { + foreach ($this->getElements() as $key => $element) { + // Initialize all empty elements with their default values. + if (!isset($data[$key])) { + $data[$key] = $element->getValue(); + } + } + return parent::isValid($data); + } + /** * Return a Zend_Config object containing the state defined in this form * diff --git a/application/forms/Install/LoggingPage.php b/application/forms/Install/LoggingPage.php new file mode 100644 index 000000000..6bb4a21ce --- /dev/null +++ b/application/forms/Install/LoggingPage.php @@ -0,0 +1,67 @@ +setName('logging'); + } + + /** + * Create and return the logging form + * + * @return LoggingForm + */ + protected function createForm() + { + if ($this->loggingForm === null) { + $this->loggingForm = new LoggingForm(); + $this->loggingForm->hideButtons(); + $this->loggingForm->setTokenDisabled(); + $this->loggingForm->setRequest($this->getRequest()); + $this->loggingForm->setConfiguration($this->getConfiguration()); + } + + return $this->loggingForm; + } + + /** + * Create this wizard page + */ + protected function create() + { + $loggingForm = $this->createForm(); + $loggingForm->buildForm(); // Needs to get called manually as it's nothing that Zend knows about + $this->addSubForm($loggingForm, $loggingForm->getName()); + } + + /** + * Return a config containing all values provided by the user + * + * @return Zend_Config + */ + public function getConfig() + { + return $this->createForm()->getConfig(); + } +} +// @codeCoverageIgnoreEnd diff --git a/application/layouts/scripts/layout.phtml b/application/layouts/scripts/layout.phtml index ad54ad9fa..c527edbd5 100644 --- a/application/layouts/scripts/layout.phtml +++ b/application/layouts/scripts/layout.phtml @@ -24,6 +24,7 @@ $isIframe = isset($_GET['_render']) && $_GET['_render'] === 'iframe'; + <?= $this->title ? $this->escape($this->title) : 'Icinga Web' ?> diff --git a/application/layouts/scripts/pdf.phtml b/application/layouts/scripts/pdf.phtml index 500aec268..c4a1b25f7 100644 --- a/application/layouts/scripts/pdf.phtml +++ b/application/layouts/scripts/pdf.phtml @@ -2,6 +2,15 @@ use Icinga\Web\StyleSheet; + +$moduleName = $this->layout()->moduleName; +if ($moduleName) { + $moduleClass = ' icinga-module module-' . $moduleName; +} else { + $moduleClass = ''; +} + + ?> @@ -32,7 +41,7 @@ if ( isset($pdf) ) -->

escape($this->title) ?>

-
+
render('inline.phtml') ?>
diff --git a/application/views/scripts/install/index.phtml b/application/views/scripts/install/index.phtml new file mode 100644 index 000000000..baf0608f0 --- /dev/null +++ b/application/views/scripts/install/index.phtml @@ -0,0 +1,40 @@ +
+
+ +

getTitle(); ?>

+
+ +
+isFinished()): ?> + partial('install/index/installog.phtml', array('installer' => $installer)); ?> + + + +
+
diff --git a/application/views/scripts/install/index/installog.phtml b/application/views/scripts/install/index/installog.phtml new file mode 100644 index 000000000..d4b9f7375 --- /dev/null +++ b/application/views/scripts/install/index/installog.phtml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/doc/installation.md b/doc/installation.md index c8ee79cb6..9de3f7d5c 100644 --- a/doc/installation.md +++ b/doc/installation.md @@ -75,6 +75,7 @@ create all database tables. You will find the installation guides for the differ > RPM packages install the schema into /usr/share/doc/icingaweb-<version>/schema bash$ mysql -u root -p icingaweb < etc/schema/accounts.mysql.sql + bash$ mysql -u root -p icingaweb < etc/schema/preferences.mysql.sql #### PostgreSQL @@ -108,6 +109,7 @@ And restart your database ('service postgresql restart' or '/etc/init.d/postgres > RPM packages install the schema into /usr/share/doc/icingaweb-<version>/schema bash$ psql -U icingaweb -a -f etc/schema/accounts.pgsql.sql + bash$ psql -U icingaweb -a -f etc/schema/preferences.pgsql.sql diff --git a/files b/files deleted file mode 100644 index 8c743933a..000000000 --- a/files +++ /dev/null @@ -1,384 +0,0 @@ -./modules/doc/application/controllers/IndexController.php -./modules/doc/application/controllers/ModuleController.php -./modules/doc/library/Doc/DocParser.php -./modules/doc/library/Doc/Controller.php -./modules/doc/library/Doc/DocException.php -./modules/doc/library/Doc/MarkdownFileIterator.php -./modules/translation/application/clicommands/CompileCommand.php -./modules/translation/application/clicommands/RefreshCommand.php -./modules/translation/library/Translation/Cli/TranslationCommand.php -./modules/translation/library/Translation/Util/GettextTranslationHelper.php -./modules/monitoring/application/forms/Config/Backend/EditBackendForm.php -./modules/monitoring/application/forms/Config/Backend/CreateBackendForm.php -./modules/monitoring/application/forms/Config/ConfirmRemovalForm.php -./modules/monitoring/application/forms/Config/Instance/CreateInstanceForm.php -./modules/monitoring/application/forms/Config/Instance/EditInstanceForm.php -./modules/monitoring/application/forms/Command/DelayNotificationForm.php -./modules/monitoring/application/forms/Command/SubmitPassiveCheckResultForm.php -./modules/monitoring/application/forms/Command/CommandForm.php -./modules/monitoring/application/forms/Command/WithChildrenCommandForm.php -./modules/monitoring/application/forms/Command/CustomNotificationForm.php -./modules/monitoring/application/forms/Command/AcknowledgeForm.php -./modules/monitoring/application/forms/Command/CommentForm.php -./modules/monitoring/application/forms/Command/MultiCommandFlagForm.php -./modules/monitoring/application/forms/Command/RescheduleNextCheckForm.php -./modules/monitoring/application/forms/Command/ScheduleDowntimeForm.php -./modules/monitoring/application/forms/Command/SingleArgumentCommandForm.php -./modules/monitoring/application/forms/Command/DisableNotificationWithExpireForm.php -./modules/monitoring/application/views/helpers/MonitoringFlags.php -./modules/monitoring/application/views/helpers/MonitoringProperties.php -./modules/monitoring/application/views/helpers/CommandForm.php -./modules/monitoring/application/views/helpers/RuntimeVariables.php -./modules/monitoring/application/views/helpers/CheckPerformance.php -./modules/monitoring/application/views/helpers/PluginOutput.php -./modules/monitoring/application/views/helpers/Perfdata.php -./modules/monitoring/application/views/helpers/_RenderServicePerfdata.php -./modules/monitoring/application/views/helpers/SelectionToolbar.php -./modules/monitoring/application/views/helpers/ContactFlags.php -./modules/monitoring/application/views/helpers/ResolveMacros.php -./modules/monitoring/application/views/helpers/MonitoringState.php -./modules/monitoring/application/views/helpers/ResolveComments.php -./modules/monitoring/application/clicommands/NrpeCommand.php -./modules/monitoring/application/clicommands/ConferenceCommand.php -./modules/monitoring/application/clicommands/ListCommand.php -./modules/monitoring/application/controllers/ShowController.php -./modules/monitoring/application/controllers/ConfigController.php -./modules/monitoring/application/controllers/MultiController.php -./modules/monitoring/application/controllers/ListController.php -./modules/monitoring/application/controllers/CommandController.php -./modules/monitoring/application/controllers/MonitoringCommands.php -./modules/monitoring/application/controllers/ChartController.php -./modules/monitoring/application/controllers/TimelineController.php -./modules/monitoring/application/controllers/TacticalController.php -./modules/monitoring/application/controllers/ProcessController.php -./modules/monitoring/library/Monitoring/DataView/Contactgroup.php -./modules/monitoring/library/Monitoring/DataView/Notification.php -./modules/monitoring/library/Monitoring/DataView/Comment.php -./modules/monitoring/library/Monitoring/DataView/Customvar.php -./modules/monitoring/library/Monitoring/DataView/EventHistory.php -./modules/monitoring/library/Monitoring/DataView/StatusSummary.php -./modules/monitoring/library/Monitoring/DataView/DataView.php -./modules/monitoring/library/Monitoring/DataView/Runtimesummary.php -./modules/monitoring/library/Monitoring/DataView/Servicegroup.php -./modules/monitoring/library/Monitoring/DataView/Runtimevariables.php -./modules/monitoring/library/Monitoring/DataView/Contact.php -./modules/monitoring/library/Monitoring/DataView/Programstatus.php -./modules/monitoring/library/Monitoring/DataView/StateHistorySummary.php -./modules/monitoring/library/Monitoring/DataView/Downtime.php -./modules/monitoring/library/Monitoring/DataView/Groupsummary.php -./modules/monitoring/library/Monitoring/DataView/Hostgroup.php -./modules/monitoring/library/Monitoring/DataView/HostStatus.php -./modules/monitoring/library/Monitoring/DataView/ServiceStatus.php -./modules/monitoring/library/Monitoring/Backend/Statusdat/Query/StatusdatQuery.php -./modules/monitoring/library/Monitoring/Backend/Statusdat/Query/ContactgroupQuery.php -./modules/monitoring/library/Monitoring/Backend/Statusdat/Query/ServicegroupsummaryQuery.php -./modules/monitoring/library/Monitoring/Backend/Statusdat/Query/HostgroupQuery.php -./modules/monitoring/library/Monitoring/Backend/Statusdat/Query/CommentQuery.php -./modules/monitoring/library/Monitoring/Backend/Statusdat/Query/DowntimeQuery.php -./modules/monitoring/library/Monitoring/Backend/Statusdat/Query/StatusSummaryQuery.php -./modules/monitoring/library/Monitoring/Backend/Statusdat/Query/GroupsummaryQuery.php -./modules/monitoring/library/Monitoring/Backend/Statusdat/Query/ContactQuery.php -./modules/monitoring/library/Monitoring/Backend/Statusdat/Query/ServicegroupQuery.php -./modules/monitoring/library/Monitoring/Backend/Statusdat/Query/HostlistQuery.php -./modules/monitoring/library/Monitoring/Backend/Statusdat/Query/StatusQuery.php -./modules/monitoring/library/Monitoring/Backend/Statusdat/Query/ServicelistQuery.php -./modules/monitoring/library/Monitoring/Backend/Livestatus/Query/StatusQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/ContactgroupQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/NotificationhistoryQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/CustomvarQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/DowntimeendhistoryQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/HostgroupQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/CommentQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/DowntimeQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/StatehistoryQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/ProgramstatusQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/EventHistoryQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/StatusSummaryQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/GroupsummaryQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/HoststatusQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/RuntimevariablesQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/CommenthistoryQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/ContactQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/StateHistorySummaryQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicegroupQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/AllcontactsQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/DowntimestarthistoryQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/RuntimesummaryQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/StatusQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/NotificationQuery.php -./modules/monitoring/library/Monitoring/Environment.php -./modules/monitoring/library/Monitoring/Controller.php -./modules/monitoring/library/Monitoring/Timeline/TimeEntry.php -./modules/monitoring/library/Monitoring/Timeline/TimeRange.php -./modules/monitoring/library/Monitoring/Timeline/TimeLine.php -./modules/monitoring/library/Monitoring/Object/Service.php -./modules/monitoring/library/Monitoring/Object/Host.php -./modules/monitoring/library/Monitoring/Object/AbstractObject.php -./modules/monitoring/library/Monitoring/Filter/Type/StatusFilter.php -./modules/monitoring/library/Monitoring/Filter/Registry.php -./modules/monitoring/library/Monitoring/Filter/UrlViewFilter.php -./modules/monitoring/library/Monitoring/Exception/UnsupportedBackendException.php -./modules/monitoring/library/Monitoring/Web/Widget/TimelineIntervalBox.php -./modules/monitoring/library/Monitoring/Web/Hook/TimelineProvider.php -./modules/monitoring/library/Monitoring/Web/Hook/TopBar.php -./modules/monitoring/library/Monitoring/Command/SubmitPassiveCheckresultCommand.php -./modules/monitoring/library/Monitoring/Command/AcknowledgeCommand.php -./modules/monitoring/library/Monitoring/Command/ScheduleDowntimeCommand.php -./modules/monitoring/library/Monitoring/Command/ScheduleCheckCommand.php -./modules/monitoring/library/Monitoring/Command/DisableNotificationWithExpireCommand.php -./modules/monitoring/library/Monitoring/Command/SingleArgumentCommand.php -./modules/monitoring/library/Monitoring/Command/AddCommentCommand.php -./modules/monitoring/library/Monitoring/Command/CustomNotificationCommand.php -./modules/monitoring/library/Monitoring/Command/DelayNotificationCommand.php -./modules/monitoring/library/Monitoring/Plugin.php -./modules/monitoring/library/Monitoring/Cli/CliUtils.php -./modules/monitoring/library/Monitoring/Backend.php -./modules/monitoring/library/Monitoring/Plugin/Perfdata.php -./modules/monitoring/library/Monitoring/Plugin/PerfdataSet.php -./modules/monitoring/run.php -./modules/monitoring/configuration.php -./modules/monitoring/bin/action/list.inc.php -./etc/module_skeleton/application/controllers/IndexController.php -./application/forms/Authentication/LoginForm.php -./application/forms/Config/GeneralForm.php -./application/forms/Config/Authentication/LdapBackendForm.php -./application/forms/Config/Authentication/ReorderForm.php -./application/forms/Config/Authentication/BaseBackendForm.php -./application/forms/Config/Authentication/DbBackendForm.php -./application/forms/Config/LoggingForm.php -./application/forms/Config/ConfirmRemovalForm.php -./application/forms/Config/Resource/CreateResourceForm.php -./application/forms/Config/Resource/EditResourceForm.php -./application/forms/TestForm.php -./application/forms/Dashboard/AddUrlForm.php -./application/forms/Preference/GeneralForm.php -./application/views/helpers/FormNumber.php -./application/views/helpers/DateFormat.php -./application/views/helpers/FormDateTime.php -./application/views/helpers/FormTriStateCheckbox.php -./application/views/helpers/Util.php -./application/clicommands/HelpCommand.php -./application/clicommands/ModuleCommand.php -./application/clicommands/AutocompleteCommand.php -./application/clicommands/WebCommand.php -./application/controllers/ConfigController.php -./application/controllers/ListController.php -./application/controllers/IndexController.php -./application/controllers/LayoutController.php -./application/controllers/PreferenceController.php -./application/controllers/DashboardController.php -./application/controllers/FilterController.php -./application/controllers/StaticController.php -./application/controllers/SearchController.php -./application/controllers/ErrorController.php -./application/controllers/AuthenticationController.php -./library/Icinga/Logger/Logger.php -./library/Icinga/Logger/Writer/StreamWriter.php -./library/Icinga/Logger/Writer/SyslogWriter.php -./library/Icinga/Logger/LogWriter.php -./library/Icinga/User/Preferences.php -./library/Icinga/User/Message.php -./library/Icinga/User/Preferences/Store/IniStore.php -./library/Icinga/User/Preferences/Store/DbStore.php -./library/Icinga/User/Preferences/PreferencesStore.php -./library/Icinga/Authentication/UserBackend.php -./library/Icinga/Authentication/Backend/DbUserBackend.php -./library/Icinga/Authentication/Backend/LdapUserBackend.php -./library/Icinga/Authentication/Membership.php -./library/Icinga/Authentication/Manager.php -./library/Icinga/Authentication/AdmissionLoader.php -./library/Icinga/Authentication/AuthChain.php -./library/Icinga/Data/Db/Query.php -./library/Icinga/Data/Db/TreeToSqlParser.php -./library/Icinga/Data/Db/Connection.php -./library/Icinga/Data/PivotTable.php -./library/Icinga/Data/DatasourceInterface.php -./library/Icinga/Data/DataArray/Query.php -./library/Icinga/Data/DataArray/Datasource.php -./library/Icinga/Data/ResourceFactory.php -./library/Icinga/Data/BaseQuery.php -./library/Icinga/File/Pdf.php -./library/Icinga/File/Csv.php -./library/Icinga/File/Csv/Query.php -./library/Icinga/Test/DbTest.php -./library/Icinga/Test/BaseTestCase.php -./library/Icinga/Test/FormTest.php -./library/Icinga/Protocol/Ldap/Root.php -./library/Icinga/Protocol/Ldap/Query.php -./library/Icinga/Protocol/Ldap/Exception.php -./library/Icinga/Protocol/Ldap/LdapUtils.php -./library/Icinga/Protocol/Ldap/Node.php -./library/Icinga/Protocol/Ldap/Connection.php -./library/Icinga/Protocol/File/Query.php -./library/Icinga/Protocol/File/Reader.php -./library/Icinga/Protocol/Statusdat/Parser.php -./library/Icinga/Protocol/Statusdat/Query.php -./library/Icinga/Protocol/Statusdat/Query/IQueryPart.php -./library/Icinga/Protocol/Statusdat/Query/Group.php -./library/Icinga/Protocol/Statusdat/Query/Expression.php -./library/Icinga/Protocol/Statusdat/View/AccessorStrategy.php -./library/Icinga/Protocol/Statusdat/View/MonitoringObjectList.php -./library/Icinga/Protocol/Statusdat/ObjectContainer.php -./library/Icinga/Protocol/Statusdat/Exception/ParsingException.php -./library/Icinga/Protocol/Statusdat/Reader.php -./library/Icinga/Protocol/Statusdat/IReader.php -./library/Icinga/Protocol/Statusdat/PrintableObject.php -./library/Icinga/Protocol/Statusdat/TreeToStatusdatQueryParser.php -./library/Icinga/Protocol/Statusdat/RuntimeStateContainer.php -./library/Icinga/Protocol/Nrpe/Packet.php -./library/Icinga/Protocol/Nrpe/Connection.php -./library/Icinga/Protocol/Livestatus/Query.php -./library/Icinga/Protocol/Livestatus/Connection.php -./library/Icinga/Protocol/Commandpipe/Transport/Transport.php -./library/Icinga/Protocol/Commandpipe/Transport/LocalPipe.php -./library/Icinga/Protocol/Commandpipe/Transport/SecureShell.php -./library/Icinga/Protocol/Commandpipe/Comment.php -./library/Icinga/Protocol/Commandpipe/Exception/InvalidCommandException.php -./library/Icinga/Protocol/Commandpipe/PropertyModifier.php -./library/Icinga/Protocol/Commandpipe/Command.php -./library/Icinga/Protocol/Commandpipe/CommandPipe.php -./library/Icinga/Application/Platform.php -./library/Icinga/Application/Benchmark.php -./library/Icinga/Application/functions.php -./library/Icinga/Application/LegacyWeb.php -./library/Icinga/Application/Config.php -./library/Icinga/Application/EmbeddedWeb.php -./library/Icinga/Application/ApplicationBootstrap.php -./library/Icinga/Application/Cli.php -./library/Icinga/Application/webrouter.php -./library/Icinga/Application/Modules/Module.php -./library/Icinga/Application/Modules/Manager.php -./library/Icinga/Application/Loader.php -./library/Icinga/Application/Icinga.php -./library/Icinga/Application/Web.php -./library/Icinga/Chart/Primitive/Animation.php -./library/Icinga/Chart/Primitive/Text.php -./library/Icinga/Chart/Primitive/Animatable.php -./library/Icinga/Chart/Primitive/Drawable.php -./library/Icinga/Chart/Primitive/Circle.php -./library/Icinga/Chart/Primitive/Styleable.php -./library/Icinga/Chart/Primitive/RawElement.php -./library/Icinga/Chart/Primitive/Rect.php -./library/Icinga/Chart/Primitive/Line.php -./library/Icinga/Chart/Primitive/Canvas.php -./library/Icinga/Chart/Primitive/PieSlice.php -./library/Icinga/Chart/Primitive/Path.php -./library/Icinga/Chart/Graph/LineGraph.php -./library/Icinga/Chart/Graph/StackedGraph.php -./library/Icinga/Chart/Graph/BarGraph.php -./library/Icinga/Chart/Axis.php -./library/Icinga/Chart/Palette.php -./library/Icinga/Chart/Unit/AxisUnit.php -./library/Icinga/Chart/Unit/LinearUnit.php -./library/Icinga/Chart/Unit/StaticAxis.php -./library/Icinga/Chart/Unit/CalendarUnit.php -./library/Icinga/Chart/PieChart.php -./library/Icinga/Chart/GridChart.php -./library/Icinga/Chart/SVGRenderer.php -./library/Icinga/Chart/Legend.php -./library/Icinga/Chart/Inline/PieChart.php -./library/Icinga/Chart/Inline/Inline.php -./library/Icinga/Chart/Chart.php -./library/Icinga/Chart/Render/RenderContext.php -./library/Icinga/Chart/Render/LayoutBox.php -./library/Icinga/Config/IniEditor.php -./library/Icinga/Config/PreservingIniWriter.php -./library/Icinga/User.php -./library/Icinga/Filter/Query/Tree.php -./library/Icinga/Filter/Query/Node.php -./library/Icinga/Filter/FilterAttribute.php -./library/Icinga/Filter/Type/FilterType.php -./library/Icinga/Filter/Type/BooleanFilter.php -./library/Icinga/Filter/Type/TextFilter.php -./library/Icinga/Filter/Type/TimeRangeSpecifier.php -./library/Icinga/Filter/QueryProposer.php -./library/Icinga/Filter/Registry.php -./library/Icinga/Filter/Filter.php -./library/Icinga/Filter/Filterable.php -./library/Icinga/Filter/Domain.php -./library/Icinga/Exception/NotWritableError.php -./library/Icinga/Exception/MissingParameterException.php -./library/Icinga/Exception/NotImplementedError.php -./library/Icinga/Exception/ConfigurationError.php -./library/Icinga/Exception/NotReadableError.php -./library/Icinga/Exception/SystemPermissionException.php -./library/Icinga/Exception/ProgrammingError.php -./library/Icinga/Web/JavaScript.php -./library/Icinga/Web/Notification.php -./library/Icinga/Web/MenuItem.php -./library/Icinga/Web/Widget/Dashboard.php -./library/Icinga/Web/Widget/FilterBox.php -./library/Icinga/Web/Widget/AlertMessageBox.php -./library/Icinga/Web/Widget/Tabextension/DashboardAction.php -./library/Icinga/Web/Widget/Tabextension/BasketAction.php -./library/Icinga/Web/Widget/Tabextension/Tabextension.php -./library/Icinga/Web/Widget/Tabextension/OutputFormat.php -./library/Icinga/Web/Widget/Chart/InlinePie.php -./library/Icinga/Web/Widget/Chart/HistoryColorGrid.php -./library/Icinga/Web/Widget/AbstractWidget.php -./library/Icinga/Web/Widget/FilterBadgeRenderer.php -./library/Icinga/Web/Widget/Dashboard/Component.php -./library/Icinga/Web/Widget/Dashboard/Pane.php -./library/Icinga/Web/Widget/Tabs.php -./library/Icinga/Web/Widget/Tab.php -./library/Icinga/Web/Widget/Widget.php -./library/Icinga/Web/Widget/SortBox.php -./library/Icinga/Web/Hook.php -./library/Icinga/Web/View/helpers/generic.php -./library/Icinga/Web/View/helpers/url.php -./library/Icinga/Web/View/helpers/format.php -./library/Icinga/Web/Menu.php -./library/Icinga/Web/Session.php -./library/Icinga/Web/Paginator/ScrollingStyle/SlidingWithBorder.php -./library/Icinga/Web/Paginator/Adapter/QueryAdapter.php -./library/Icinga/Web/ViewStream.php -./library/Icinga/Web/Url.php -./library/Icinga/Web/Session/SessionNamespace.php -./library/Icinga/Web/Session/Session.php -./library/Icinga/Web/Session/PhpSession.php -./library/Icinga/Web/StyleSheet.php -./library/Icinga/Web/Hook/Ticket.php -./library/Icinga/Web/Hook/Configuration/ConfigurationTabInterface.php -./library/Icinga/Web/Hook/Configuration/ConfigurationTab.php -./library/Icinga/Web/Hook/Configuration/ConfigurationTabBuilder.php -./library/Icinga/Web/Hook/TopBar.php -./library/Icinga/Web/Hook/Grapher.php -./library/Icinga/Web/Request.php -./library/Icinga/Web/View.php -./library/Icinga/Web/Widget.php -./library/Icinga/Web/Controller/ActionController.php -./library/Icinga/Web/Controller/BaseConfigController.php -./library/Icinga/Web/Controller/BasePreferenceController.php -./library/Icinga/Web/Controller/ControllerTabCollector.php -./library/Icinga/Web/LessCompiler.php -./library/Icinga/Web/Form.php -./library/Icinga/Web/Form/Element/Number.php -./library/Icinga/Web/Form/Element/DateTimePicker.php -./library/Icinga/Web/Form/Element/TriStateCheckbox.php -./library/Icinga/Web/Form/Element/Note.php -./library/Icinga/Web/Form/Decorator/ConditionalHidden.php -./library/Icinga/Web/Form/Decorator/BootstrapForm.php -./library/Icinga/Web/Form/Decorator/HelpText.php -./library/Icinga/Web/Form/Validator/DateFormatValidator.php -./library/Icinga/Web/Form/Validator/TriStateValidator.php -./library/Icinga/Web/Form/Validator/DateTimeValidator.php -./library/Icinga/Web/Form/Validator/TimeFormatValidator.php -./library/Icinga/Web/Form/Validator/WritablePathValidator.php -./library/Icinga/Web/Form/InvalidCSRFTokenException.php -./library/Icinga/Cli/Documentation/CommentParser.php -./library/Icinga/Cli/Params.php -./library/Icinga/Cli/Documentation.php -./library/Icinga/Cli/Screen/AnsiScreen.php -./library/Icinga/Cli/Loader.php -./library/Icinga/Cli/Command.php -./library/Icinga/Cli/Screen.php -./library/Icinga/Util/File.php -./library/Icinga/Util/Dimension.php -./library/Icinga/Util/DateTimeFactory.php -./library/Icinga/Util/Color.php -./library/Icinga/Util/String.php -./library/Icinga/Util/Format.php -./library/Icinga/Util/ConfigAwareFactory.php -./library/Icinga/Util/Translator.php - diff --git a/icingaweb2.spec b/icingaweb2.spec index 35a50d8f4..e66046a9f 100644 --- a/icingaweb2.spec +++ b/icingaweb2.spec @@ -1,14 +1,15 @@ # $Id$ -# Authority: The icinga devel team -# Upstream: The icinga devel team +# Authority: The icinga devel team +# Upstream: The icinga devel team # ExcludeDist: el4 el3 %define revision 0 %define configdir %{_sysconfdir}/icingaweb -%define logdir %{_localstatedir}/log/icingaweb %define sharedir %{_datadir}/icingaweb %define prefixdir %{_datadir}/icingaweb +%define logdir %{sharedir}/log +#%define logdir %{_localstatedir}/log/icingaweb %if "%{_vendor}" == "suse" %define phpname php5 @@ -41,7 +42,7 @@ Summary: Open Source host, service and network monitoring Web UI Name: icingaweb2 -Version: 1.0.0 +Version: 0.0.1 Release: %{revision}%{?dist} License: GPLv2 Group: Applications/System @@ -52,7 +53,7 @@ BuildArch: noarch AutoReqProv: Off %endif -Source0: https://downloads.sourceforge.net/project/icinga/%{name}/%{version}/%{name}-%{version}.tar.gz +Source0: icingaweb2-%{version}.tar.gz BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root @@ -92,108 +93,44 @@ Requires: %{phpname}-json Requires: apache2-mod_php5 %endif -Requires: %{name}-doc +Requires: %{phpzendname}-Db-Adapter-Pdo +Requires: %{phpzendname}-Db-Adapter-Pdo-Mysql + +Requires: php-Icinga %description IcingaWeb for Icinga 2 or Icinga 1.x using status data, IDOUtils or Livestatus as backend provider. -%package config-internal-mysql -Summary: config for internal mysql database +%package -n icingacli +Summary: Icinga CLI Group: Applications/System Requires: %{name} = %{version}-%{release} -Requires: %{phpzendname}-Db-Adapter-Pdo -Requires: %{phpzendname}-Db-Adapter-Pdo-Mysql +Requires: php-Icinga -%description config-internal-mysql -Configuration for internal mysql database. +%description -n icingacli +Icinga CLI using php-Icinga Icinga Web 2 backend. -%package config-internal-pgsql -Summary: config for internal pgsql database +%package -n php-Icinga +Summary: Icinga Web 2 PHP Libraries Group: Applications/System Requires: %{name} = %{version}-%{release} -Requires: %{phpzendname}-Db-Adapter-Pdo -Requires: %{phpzendname}-Db-Adapter-Pdo-Pgsql +Requires: %{phpname} >= 5.3.0 +Requires: %{phpzendname} -%description config-internal-pgsql -Configuration for internal pgsql database. -%package config-backend-statusdata-1x -Summary: Backend config for status data -Group: Applications/System -Requires: %{name} = %{version}-%{release} -Provides: %{name}-config-statusdata +%description -n php-Icinga +Icinga Web 2 PHP Libraries shared with icingacli. -%description config-backend-statusdata-1x -Backend config for status data provided by Icinga 1.x Core. -%package config-backend-ido-mysql-1x -Summary: Backend config for icinga 1.x ido mysql database -Group: Applications/System -Requires: %{name} = %{version}-%{release} -Requires: %{phpname}-mysql -Provides: %{name}-config-ido-mysql -%description config-backend-ido-mysql-1x -Backend config for ido mysql database provided by -Icinga 1.x IDOUtils with MySQL. - -%package config-backend-ido-pgsql-1x -Summary: Backend config for icinga 1.x ido pgsql database -Group: Applications/System -Requires: %{name} = %{version}-%{release} -Requires: %{phpname}-pgsql -Provides: %{name}-config-ido-pgsql - -%description config-backend-ido-pgsql-1x -Backend config for ido mysql database provided by -Icinga 1.x IDOUtils with PostgreSQL. - -%package config-backend-livestatus-1x -Summary: Backend config for icinga 1.x livestatus -Group: Applications/System -Requires: %{name} = %{version}-%{release} -Provides: %{name}-config-livestatus - -%description config-backend-livestatus-1x -Backend config for livestatus provided by Icinga 1.x -with mk_livestatus NEB module. - -%package config-backend-commands-1x -Summary: Backend config for icinga 1.x commands -Group: Applications/System -Requires: %{name} = %{version}-%{release} -Provides: %{name}-config-commands - -%description config-backend-commands-1x -Backend config for external command pipe provided by -Icinga 1.x %prep -%setup -q -n %{name}-%{version} +#%setup -q -n %{name}-%{version} +%setup -q -n %{name} %build -%configure \ - --prefix="%{prefixdir}" \ - --datadir="%{sharedir}" \ - --datarootdir="%{sharedir}" \ - --sysconfdir="%{configdir}" \ - --with-icingaweb-config-path='%{configdir}' \ - --with-icingaweb-log-path='%{logdir}' \ - --with-web-path='/icingaweb' \ - --with-httpd-config-path=%{apacheconfdir} \ - --with-web-user='%{apacheuser}' \ - --with-web-group='%{apachegroup}' \ - --with-internal-db-type='mysql' \ - --with-internal-db-name='icingaweb' \ - --with-internal-db-host='localhost' \ - --with-internal-db-port='3306' \ - --with-internal-db-pass='icingaweb' \ - --with-internal-db-user='icingaweb' \ - --with-internal-authentication=yes \ - --with-icinga-commandpipe='%{extcmdfile1x}' \ - --with-livestatus-socket='%{livestatussocket1x}' cat > README.RHEL.SUSE <<"EOF" IcingaWeb for RHEL and SUSE @@ -205,17 +142,40 @@ EOF %install [ "%{buildroot}" != "/" ] && [ -d "%{buildroot}" ] && rm -rf %{buildroot} -%{__mkdir} -p %{buildroot}/%{apacheconfdir} -%{__make} install \ - install-apache-config \ - DESTDIR="%{buildroot}" \ - INSTALL_OPTS="" \ - COMMAND_OPTS="" \ - INSTALL_OPTS_WEB="" \ - INIT_OPTS="" # prepare configuration for sub packages +# install rhel apache config +install -D -m0644 packages/rhel/etc/httpd/conf.d/icingaweb.conf %{buildroot}/%{apacheconfdir}/icingaweb.conf + +# install public, library, modules +%{__mkdir} -p %{buildroot}/%{sharedir} +%{__mkdir} -p %{buildroot}/%{logdir} +%{__mkdir} -p %{buildroot}/%{_sysconfdir}/icingaweb/enabledModules + +%{__cp} -r application library modules public %{buildroot}/%{sharedir}/ + +# install index.php, .htaccess +install -m0644 packages/rhel/usr/share/icingaweb/public/index.php %{buildroot}/%{sharedir}/public/index.php +install -m0644 packages/rhel/usr/share/icingaweb/public/.htaccess %{buildroot}/%{sharedir}/public/.htaccess + +# use the vagrant config for configuration for now - TODO +%{__cp} -r .vagrant-puppet/files/etc/icingaweb %{buildroot}/%{_sysconfdir}/ + +# we use the default 'icinga' database +sed -i 's/icinga2/icinga/g' %{buildroot}/%{_sysconfdir}/icingaweb/resources.ini + +# enable the monitoring module by default +ln -s %{sharedir}/modules/monitoring %{buildroot}/%{_sysconfdir}/icingaweb/enabledModules/monitoring + +# install icingacli +install -D -m0755 bin/icingacli %{buildroot}/usr/bin/icingacli + +# install sql schema files as example + +# delete all *.in files +rm -f %{buildroot}/%{_datadir}/%{name}/public/index.php.in +rm -f %{buildroot}/%{_datadir}/%{name}/public/.htaccess.in %pre # Add apacheuser in the icingacmd group @@ -243,11 +203,9 @@ fi %files # main dirs %defattr(-,root,root) -%doc etc/schema doc README.RHEL.SUSE -%{sharedir}/application -%{sharedir}/library -%{sharedir}/public -%{sharedir}/modules +%doc etc/schema doc packages/rhel/README +%attr(755,%{apacheuser},%{apachegroup}) %{sharedir}/public +%attr(755,%{apacheuser},%{apachegroup}) %{sharedir}/modules # configs %defattr(-,root,root) %config(noreplace) %attr(-,root,root) %{apacheconfdir}/icingaweb.conf @@ -256,7 +214,14 @@ fi # logs %attr(2775,%{apacheuser},%{apachegroup}) %dir %{logdir} +%files -n php-Icinga +%attr(755,%{apacheuser},%{apachegroup}) %{sharedir}/application +%attr(755,%{apacheuser},%{apachegroup}) %{sharedir}/library + +%files -n icingacli +%attr(0755,root,root) /usr/bin/icingacli + %changelog -* Sun Oct 20 2013 Michael Friedrich - 1.0.0-1 +* Tue May 11 2014 Michael Friedrich - 0.0.1-1 - initial creation diff --git a/library/Icinga/Application/Modules/Manager.php b/library/Icinga/Application/Modules/Manager.php index 050c6c275..6fefd3930 100644 --- a/library/Icinga/Application/Modules/Manager.php +++ b/library/Icinga/Application/Modules/Manager.php @@ -532,7 +532,7 @@ class Manager if (! array_key_exists($file, $this->installedBaseDirs)) { $this->installedBaseDirs[$file] = $canonical . '/' . $file; } else { - Logger::warning( + Logger::debug( 'Module "%s" already exists in installation path "%s" and is ignored.', $canonical . '/' . $file, $this->installedBaseDirs[$file] diff --git a/library/Icinga/Application/webrouter.php b/library/Icinga/Application/webrouter.php index 2cf7a3155..bee27ee1d 100644 --- a/library/Icinga/Application/webrouter.php +++ b/library/Icinga/Application/webrouter.php @@ -87,6 +87,17 @@ if (in_array($path, $special)) { $pie->initFromRequest(); echo $pie->render(); +} elseif ($path === 'png/chart.php') { + if (!array_key_exists('data', $_GET)) { + return false; + } + include __DIR__ . '/EmbeddedWeb.php'; + EmbeddedWeb::start(); + header('Content-Type: image/png'); + $pie = new PieChart(); + $pie->initFromRequest(); + $pie->toPng(); + } elseif (file_exists($baseDir . '/' . $path) && is_file($baseDir . '/' . $path)) { return false; } else { diff --git a/library/Icinga/Chart/Inline/PieChart.php b/library/Icinga/Chart/Inline/PieChart.php index 687e28f08..369ae6b9b 100644 --- a/library/Icinga/Chart/Inline/PieChart.php +++ b/library/Icinga/Chart/Inline/PieChart.php @@ -31,12 +31,14 @@ namespace Icinga\Chart\Inline; use Icinga\Chart\PieChart as PieChartRenderer; +use Imagick; +use Exception; /** * Draw an inline pie-chart directly from the available request parameters. */ class PieChart extends Inline { - public function render() + public function render($output = true) { $pie = new PieChartRenderer(); $pie->disableLegend(); @@ -44,6 +46,23 @@ class PieChart extends Inline { 'data' => $this->data, 'colors' => $this->colors, 'labels' => $this->labels )); $pie->setWidth($this->width)->setHeight($this->height); - echo $pie->render(); + if ($output) { + echo $pie->render(); + } else { + return $pie->render(); + } + } + + public function toPng() + { + if (! class_exists('Imagick')) { + // TODO: This is quick & dirty. 404? + throw new Exception('Cannot render PNGs without Imagick'); + } + $image = new Imagick(); + $image->readImageBlob($this->render(false)); + $image->setImageFormat('png24'); + $image->resizeImage($this->width, $this->height, imagick::FILTER_LANCZOS, 1); + echo $image; } } \ No newline at end of file diff --git a/library/Icinga/Data/Db/TreeToSqlParser.php b/library/Icinga/Data/Db/TreeToSqlParser.php index 9d41b88e6..ebdb867b2 100644 --- a/library/Icinga/Data/Db/TreeToSqlParser.php +++ b/library/Icinga/Data/Db/TreeToSqlParser.php @@ -75,7 +75,12 @@ class TreeToSqlParser if (count($right) > 1) { return 'IN'; } else { - return 'LIKE'; + foreach ($right as $r) { + if (strpos($r, '*') !== false) { + return 'LIKE'; + } + } + return '='; } case Node::OPERATOR_EQUALS_NOT: if (count($right) > 1) { @@ -171,7 +176,11 @@ class TreeToSqlParser if ($node->context === Node::CONTEXT_TIMESTRING && !is_numeric($value)) { $value = strtotime($value); } - $values[] = $this->query->getDatasource()->getConnection()->quote($value); + if (preg_match('/^\d+$/', $value)) { + $values[] = $value; + } else { + $values[] = $this->query->getDatasource()->getConnection()->quote($value); + } } $valueString = join(',', $values); diff --git a/library/Icinga/File/Pdf.php b/library/Icinga/File/Pdf.php index 4f3f24c90..77f5bf001 100644 --- a/library/Icinga/File/Pdf.php +++ b/library/Icinga/File/Pdf.php @@ -1,5 +1,4 @@ render(); $layout->content = $controller->getResponse(); $html = $layout->render(); - $imgDir = Url::fromPath('img'); $html = preg_replace('~src="' . $imgDir . '/~', 'src="' . Icinga::app()->getBootstrapDirecory() . '/img/', $html); - //echo $html; exit; + $html = preg_replace('~src="/svg/chart.php(.*)"~', 'class="icon" src="http://master1.com/png/chart.php$1"', $html); $this->load_html($html); - - /* - // TODO: We need to find a solution for page footers - $font = Font_Metrics::get_font("helvetica", "bold"); - $canvas = $this->get_canvas(); - $canvas->page_text(555, 750, "{PAGE_NUM}/{PAGE_COUNT}", $font, 10, array(0,0,0)); - $dompdf->page_script(' - // $pdf is the variable containing a reference to the canvas object provided by dompdf - $pdf->line(10,730,800,730,array(0,0,0),1); - '); - */ $this->render(); $this->stream( sprintf( @@ -93,127 +60,4 @@ class Pdf extends DOMPDF ) ); } - - /** - * @param $body - * @param $css - */ -/* public function renderPage($body, $css) - { - $html = - '' - . '' - . '' - . $body - . '' - . ''; - if ($this->paginateTable === true) { - $doc = new DOMDocument(); - @$doc->loadHTML($html); - $this->paginateHtmlTables($doc); - $html = $doc->saveHtml(); - } - $this->load_html($html); - $this->render(); - }*/ - - /** - * Split up tables into multiple elements that each contain $rowsPerPage of all original rows - * - * NOTE: This is a workaround to fix the buggy page-break on table-rows in dompdf. - * - * @param DOMDocument $doc The html document containing the tables. - * - * @return array All paginated tables from the document. - */ -/* private function paginateHtmlTables(DOMDocument $doc) - { - $xpath = new DOMXPath($doc); - $tables = $xpath->query('.//table'); - $paginated = array(); - $j = 0; - - foreach ($tables as $table) { - $containerType = null; - $rows = $xpath->query('.//tr', $table); - $rowCnt = $rows->length; - $tableCnt = (Integer)ceil($rowCnt / $this->rowsPerPage); - $paginated[$j] = array(); - if ($rowCnt <= $this->rowsPerPage) { - continue; - } - // remove all rows from the original parent - foreach ($rows as $row) { - if (!isset($containerType)) { - $containerType = $row->parentNode->nodeName; - } - $row->parentNode->removeChild($row); - } - - // clone table for each additional page and fetch the row containers - $containers = array(); - $pages = array(); - - if ($this->tableInitialPageBreak) { - $this->pageBreak($doc, $table); - } - for ($i = 0; $i < $tableCnt; $i++) { - // clone table - $currentPage = $table->cloneNode(true); - $pages[$i] = $currentPage; - $table->parentNode->insertBefore($currentPage, $table); - - // put it in current paginated table - $paginated[$j] = $currentPage; - - // insert page-break - if ($i < $tableCnt - 1) { - $this->pageBreak($doc, $table); - } - - // fetch row container - $container = $xpath->query('.//' . $containerType, $currentPage)->item(0); - $containers[$i] = $container; - } - - $i = 0; - foreach ($rows as $row) { - $p = (Integer)floor($i / $this->rowsPerPage); - $containers[$p]->appendChild($row); - $i++; - } - - // remove original table - $table->parentNode->removeChild($table); - $j++; - } - return $paginated; - } - - private function pageBreak($doc, $before) - { - $div = $doc->createElement('div'); - $div->setAttribute('style', 'page-break-before: always;'); - $before->parentNode->insertBefore($div, $before); - } -*/ - /** - * Prepare the given css for rendering with DOMPDF, by removing or hiding all incompatible - * styles - * - * @param $css The css-string - * - * @return string A css-string that is ready to use for DOMPDF - */ - -// public static function prepareCss($css) -// { -// $css = preg_replace('/\*:\s*before\s*,\s*/', '', $css); -// $css = preg_replace('/\*\s*:\s*after\s*\{[^\}]*\}/', '', $css); -// return $css; -// } - -} -// @codeCoverageIgnoreEnd +} \ No newline at end of file diff --git a/library/Icinga/Web/Controller/ActionController.php b/library/Icinga/Web/Controller/ActionController.php index 5b42f8730..5893a3c3f 100644 --- a/library/Icinga/Web/Controller/ActionController.php +++ b/library/Icinga/Web/Controller/ActionController.php @@ -46,6 +46,7 @@ use Icinga\File\Pdf; use Icinga\Exception\ProgrammingError; use Icinga\Web\Session; use Icinga\Session\SessionNamespace; +use Icinga\Exception\NotReadableError; /** * Base class for all core action controllers @@ -61,6 +62,13 @@ class ActionController extends Zend_Controller_Action */ protected $requiresAuthentication = true; + /** + * Whether the controller requires configuration + * + * @var bool + */ + protected $requiresConfiguration = true; + private $config; private $configs = array(); @@ -114,26 +122,24 @@ class ActionController extends Zend_Controller_Action $this->_helper = new Zend_Controller_Action_HelperBroker($this); $this->_helper->addPath('../application/controllers/helpers'); - // when noInit is set (e.g. for testing), authentication and init is skipped - if (isset($invokeArgs['noInit'])) { - // TODO: Find out whether this still makes sense? - return; - } - if ($this->_request->isXmlHttpRequest()) { $this->windowId = $this->_request->getHeader('X-Icinga-WindowId', null); } - if ($this->requiresLogin() === false) { - $this->view->tabs = new Tabs(); - $this->init(); - } else { - $url = $this->getRequestUrl(); - if ($url === 'default/index/index') { - // TODO: We need our own router :p - $url = 'dashboard'; + if ($this->requiresConfig() === false) { + if ($this->requiresLogin() === false) { + $this->view->tabs = new Tabs(); + $this->init(); + } else { + $url = $this->getRequestUrl(); + if ($url === 'default/index/index') { + // TODO: We need our own router :p + $url = 'dashboard'; + } + $this->redirectToLogin($url); } - $this->redirectToLogin($url); + } else { + $this->redirectNow(Url::fromPath('install')); } } @@ -224,11 +230,39 @@ class ActionController extends Zend_Controller_Action } } + /** + * Check whether the controller requires configuration. That is when no configuration + * is available and when it is possible to setup the configuration + * + * @return bool + * + * @see requiresConfiguration + */ + protected function requiresConfig() + { + if (!$this->requiresConfiguration) { + return false; + } + + if (file_exists(Config::$configDir . '/setup.token')) { + try { + $config = Config::app()->toArray(); + } catch (NotReadableError $e) { + return true; + } + + return empty($config); + } else { + return false; + } + } + /** * Check whether the controller requires a login. That is when the controller requires authentication and the * user is currently not authenticated * * @return bool + * * @see requiresAuthentication */ protected function requiresLogin() diff --git a/library/Icinga/Web/Form.php b/library/Icinga/Web/Form.php index 7cd3ad746..02c9787f4 100644 --- a/library/Icinga/Web/Form.php +++ b/library/Icinga/Web/Form.php @@ -127,6 +127,15 @@ class Form extends Zend_Form */ protected $last_note_id = 0; + /** + * Whether buttons are shown or not + * + * This is just a q&d solution and MUST NOT survive any refactoring! + * + * @var bool + */ + protected $buttonsHidden = false; + /** * Getter for the session ID * @@ -279,11 +288,11 @@ class Form extends Zend_Form $this->initCsrfToken(); $this->create(); - if ($this->submitLabel) { + if (!$this->buttonsHidden && $this->submitLabel) { $this->addSubmitButton(); } - if ($this->cancelLabel) { + if (!$this->buttonsHidden && $this->cancelLabel) { $this->addCancelButton(); } @@ -596,4 +605,18 @@ class Form extends Zend_Form return $this; } + + public function hideButtons() + { + $this->buttonsHidden = true; + } + + /** + * q&d solution to be able to recreate a form + */ + public function reset() + { + $this->created = false; + $this->clearElements(); + } } diff --git a/library/Icinga/Web/StyleSheet.php b/library/Icinga/Web/StyleSheet.php index b247f32e9..e62a861ca 100644 --- a/library/Icinga/Web/StyleSheet.php +++ b/library/Icinga/Web/StyleSheet.php @@ -22,6 +22,7 @@ class StyleSheet 'css/icinga/monitoring-colors.less', 'css/icinga/selection-toolbar.less', 'css/icinga/login.less', + 'css/icinga/install.less', ); public static function compileForPdf() diff --git a/library/Icinga/Web/Url.php b/library/Icinga/Web/Url.php index 8476e40ce..e00fad03c 100644 --- a/library/Icinga/Web/Url.php +++ b/library/Icinga/Web/Url.php @@ -463,6 +463,25 @@ class Url return $this; } + /** + * Shift a query parameter from this URL if it exists, otherwise $default + * + * @param string $param Parameter name + * @param mixed $default Default value in case $param does not exist + * + * @return mixed + */ + public function shift($param, $default = null) + { + if (isset($this->params[$param])) { + $ret = $this->params[$param]; + unset($this->params[$param]); + } else { + $ret = $default; + } + return $ret; + } + /** * Return a copy of this url without the parameter given * diff --git a/library/Icinga/Web/Wizard/Page.php b/library/Icinga/Web/Wizard/Page.php new file mode 100644 index 000000000..82e064745 --- /dev/null +++ b/library/Icinga/Web/Wizard/Page.php @@ -0,0 +1,93 @@ +wizard = $wizard; + } + + /** + * Overwrite this to initialize this wizard page + */ + public function init() + { + + } + + /** + * Return whether this page needs to be shown to the user + * + * Overwrite this to add page specific handling + * + * @return bool + */ + public function isRequired() + { + return true; + } + + /** + * Set the title for this wizard page + * + * @param string $title The title to set + */ + public function setTitle($title) + { + $this->title = $title; + } + + /** + * Return the title of this wizard page + * + * @return string + */ + public function getTitle() + { + return $this->title; + } + + /** + * Return a config containing all values provided by the user + * + * @return Zend_Config + */ + public function getConfig() + { + return $this->getConfiguration(); + } +} diff --git a/library/Icinga/Web/Wizard/Wizard.php b/library/Icinga/Web/Wizard/Wizard.php new file mode 100644 index 000000000..3fc5fa49d --- /dev/null +++ b/library/Icinga/Web/Wizard/Wizard.php @@ -0,0 +1,385 @@ +pages, function ($page) { return $page->isRequired(); }); + } + + /** + * Return a page by its name or null if it's not found + * + * @param string $pageName The name of the page + * + * @return Page|null + */ + public function getPage($pageName) + { + $candidates = array_filter( + $this->pages, // Cannot use getPages() here because I might get called as part of Page::isRequired() + function ($page) use ($pageName) { return $page->getName() === $pageName; } + ); + + if (!empty($candidates)) { + return array_shift($candidates); + } elseif ($this->wizard !== null) { + return $this->wizard->getPage($pageName); + } + } + + /** + * Add a new page to this wizard + * + * @param Page $page The page to add + */ + public function addPage(Page $page) + { + if (!($pageName = $page->getName())) { + throw new ProgrammingError('Wizard page "' . get_class($page) . '" has no unique name'); + } + + $wizardConfig = $this->getConfig(); + if ($wizardConfig->get($pageName) === null) { + $wizardConfig->{$pageName} = new Zend_Config(array(), true); + } + + $page->setConfiguration($wizardConfig->{$pageName}); + $page->setRequest($this->getRequest()); + $page->setTokenDisabled(); // Usually default for pages, but not for wizards + $this->pages[] = $page; + } + + /** + * Add multiple pages to this wizard + * + * The given array's keys are titles and its values are class names to add + * as wizard pages. An array as value causes a sub-wizard being added. + * + * @param array $pages The pages to add to the wizard + */ + public function addPages(array $pages) + { + foreach ($pages as $title => $pageClassOrArray) { + if (is_array($pageClassOrArray)) { + $wizard = new static($this); + $wizard->setTitle($title); + $this->addPage($wizard); + $wizard->addPages($pageClassOrArray); + } else { + $page = new $pageClassOrArray($this); + $page->setTitle($title); + $this->addPage($page); + } + } + } + + /** + * Return this wizard's progress + * + * @param int $default The step to return in case this wizard has no progress information yet + * + * @return int The current step + */ + public function getProgress($default = 0) + { + return $this->getConfig()->get('progress', $default); + } + + /** + * Set this wizard's progress + * + * @param int $step The current step + */ + public function setProgress($step) + { + $config = $this->getConfig(); + $config->progress = $step; + } + + /** + * Return the current page + * + * @return Page + * + * @throws ProgrammingError In case there are not any pages registered + */ + public function getCurrentPage() + { + $pages = $this->getPages(); + + if (empty($pages)) { + throw new ProgrammingError('This wizard has no pages'); + } + + return $pages[$this->getProgress()]; + } + + /** + * Return whether the given page is the current page + * + * @param Page $page The page to check + * + * @return bool + */ + public function isCurrentPage(Page $page) + { + return $this->getCurrentPage() === $page; + } + + /** + * Return whether the given page is the first page in the wizard + * + * @param Page $page The page to check + * + * @return bool + * + * @throws ProgrammingError In case there are not any pages registered + */ + public function isFirstPage(Page $page) + { + $pages = $this->getPages(); + + if (empty($pages)) { + throw new ProgrammingError('This wizard has no pages'); + } + + return $pages[0] === $page; + } + + /** + * Return whether the given page has been completed + * + * @param Page $page The page to check + * + * @return bool + * + * @throws ProgrammingError In case there are not any pages registered + */ + public function isCompletedPage(Page $page) + { + $pages = $this->getPages(); + + if (empty($pages)) { + throw new ProgrammingError('This wizard has no pages'); + } + + return $this->isFinished() || array_search($page, $pages, true) < $this->getProgress(); + } + + /** + * Return whether the given page is the last page in the wizard + * + * @param Page $page The page to check + * + * @return bool + * + * @throws ProgrammingError In case there are not any pages registered + */ + public function isLastPage(Page $page) + { + $pages = $this->getPages(); + + if (empty($pages)) { + throw new ProgrammingError('This wizard has no pages'); + } + + return $pages[count($pages) - 1] === $page; + } + + /** + * Return whether this wizard has been completed + * + * @return bool + */ + public function isFinished() + { + return $this->finished && $this->isLastPage($this->getCurrentPage()); + } + + /** + * Return whether the given page is a wizard + * + * @param Page $page The page to check + * + * @return bool + */ + public function isWizard(Page $page) + { + return $page instanceof self; + } + + /** + * Return whether either the back- or next-button was clicked + * + * @see Form::isSubmitted() + */ + public function isSubmitted() + { + $checkData = $this->getRequest()->getParams(); + return isset($checkData['btn_return']) || isset($checkData['btn_advance']); + } + + /** + * Update the wizard's progress + * + * @param bool $lastStepIsLast Whether the last step of this wizard is actually the very last one + */ + public function navigate($lastStepIsLast = true) + { + $currentPage = $this->getCurrentPage(); + if (($pageName = $this->getRequest()->getParam('btn_advance'))) { + if (!$this->isWizard($currentPage) || $currentPage->navigate(false) || $currentPage->isFinished()) { + if ($this->isLastPage($currentPage) && (!$lastStepIsLast || $pageName === 'install')) { + $this->finished = true; + } else { + $pages = $this->getPages(); + $newStep = $this->getProgress() + 1; + if (isset($pages[$newStep]) && $pages[$newStep]->getName() === $pageName) { + $this->setProgress($newStep); + $this->reset(); + } + } + } + } elseif (($pageName = $this->getRequest()->getParam('btn_return'))) { + if ($this->isWizard($currentPage) && $currentPage->getProgress() > 0) { + $currentPage->navigate(false); + } elseif (!$this->isFirstPage($currentPage)) { + $pages = $this->getPages(); + $newStep = $this->getProgress() - 1; + if ($pages[$newStep]->getName() === $pageName) { + $this->setProgress($newStep); + $this->reset(); + } + } + } + + $config = $this->getConfig(); + $config->{$currentPage->getName()} = $currentPage->getConfig(); + } + + /** + * Setup the current wizard page + */ + protected function create() + { + $currentPage = $this->getCurrentPage(); + if ($this->isWizard($currentPage)) { + $this->createWizard($currentPage); + } else { + $this->createPage($currentPage); + } + } + + /** + * Display the given page as this wizard's current page + * + * @param Page $page The page + */ + protected function createPage(Page $page) + { + $pages = $this->getPages(); + $currentStep = $this->getProgress(); + + $page->buildForm(); // Needs to get called manually as it's nothing that Zend knows about + $this->addSubForm($page, $page->getName()); + + if (!$this->isFirstPage($page)) { + $this->addElement( + 'button', + 'btn_return', + array( + 'type' => 'submit', + 'label' => t('Previous'), + 'value' => $pages[$currentStep - 1]->getName() + ) + ); + } + + $this->addElement( + 'button', + 'btn_advance', + array( + 'type' => 'submit', + 'label' => $this->isLastPage($page) ? t('Install') : t('Next'), + 'value' => $this->isLastPage($page) ? 'install' : $pages[$currentStep + 1]->getName() + ) + ); + } + + /** + * Display the current page of the given wizard as this wizard's current page + * + * @param Wizard $wizard The wizard + */ + protected function createWizard(Wizard $wizard) + { + $isFirstPage = $this->isFirstPage($wizard); + $isLastPage = $this->isLastPage($wizard); + $currentSubPage = $wizard->getCurrentPage(); + $isFirstSubPage = $wizard->isFirstPage($currentSubPage); + $isLastSubPage = $wizard->isLastPage($currentSubPage); + + $currentSubPage->buildForm(); // Needs to get called manually as it's nothing that Zend knows about + $this->addSubForm($currentSubPage, $currentSubPage->getName()); + + if (!$isFirstPage || !$isFirstSubPage) { + $pages = $isFirstSubPage ? $this->getPages() : $wizard->getPages(); + $currentStep = $isFirstSubPage ? $this->getProgress() : $wizard->getProgress(); + $this->addElement( + 'button', + 'btn_return', + array( + 'type' => 'submit', + 'label' => t('Previous'), + 'value' => $pages[$currentStep - 1]->getName() + ) + ); + } + + $pages = $isLastSubPage ? $this->getPages() : $wizard->getPages(); + $currentStep = $isLastSubPage ? $this->getProgress() : $wizard->getProgress(); + $this->addElement( + 'button', + 'btn_advance', + array( + 'type' => 'submit', + 'label' => $isLastPage && $isLastSubPage ? t('Install') : t('Next'), + 'value' => $isLastPage && $isLastSubPage ? 'install' : $pages[$currentStep + 1]->getName() + ) + ); + } +} diff --git a/library/vendor/Parsedown/Parsedown.php b/library/vendor/Parsedown/Parsedown.php index 20db13475..92f3dd897 100644 --- a/library/vendor/Parsedown/Parsedown.php +++ b/library/vendor/Parsedown/Parsedown.php @@ -29,6 +29,9 @@ class Parsedown function text($text) { + # make sure no definitions are set + $this->Definitions = array(); + # standardize line breaks $text = str_replace("\r\n", "\n", $text); $text = str_replace("\r", "\n", $text); @@ -48,9 +51,6 @@ class Parsedown # trim line breaks $markup = trim($markup, "\n"); - # clean up - $this->definitions = array(); - return $markup; } @@ -58,6 +58,8 @@ class Parsedown # Setters # + private $breaksEnabled; + function setBreaksEnabled($breaksEnabled) { $this->breaksEnabled = $breaksEnabled; @@ -65,13 +67,11 @@ class Parsedown return $this; } - private $breaksEnabled; - # - # Blocks + # Lines # - protected $blockMarkers = array( + protected $BlockTypes = array( '#' => array('Atx'), '*' => array('Rule', 'List'), '+' => array('List'), @@ -87,24 +87,31 @@ class Parsedown '8' => array('List'), '9' => array('List'), ':' => array('Table'), - '<' => array('Markup'), + '<' => array('Comment', 'Markup'), '=' => array('Setext'), '>' => array('Quote'), - '[' => array('Reference'), '_' => array('Rule'), '`' => array('FencedCode'), '|' => array('Table'), '~' => array('FencedCode'), ); - protected $definitionMarkers = array( + # ~ + + protected $DefinitionTypes = array( '[' => array('Reference'), ); + # ~ + protected $unmarkedBlockTypes = array( 'CodeBlock', ); + # + # Blocks + # + private function lines(array $lines) { $CurrentBlock = null; @@ -134,7 +141,7 @@ class Parsedown $Line = array('body' => $line, 'indent' => $indent, 'text' => $text); - # Multiline block types define "addTo" methods. + # ~ if (isset($CurrentBlock['incomplete'])) { @@ -161,17 +168,15 @@ class Parsedown $marker = $text[0]; - # Definitions - - if (isset($this->definitionMarkers[$marker])) + if (isset($this->DefinitionTypes[$marker])) { - foreach ($this->definitionMarkers[$marker] as $definitionType) + foreach ($this->DefinitionTypes[$marker] as $definitionType) { $Definition = $this->{'identify'.$definitionType}($Line, $CurrentBlock); if (isset($Definition)) { - $this->definitions[$definitionType][$Definition['id']] = $Definition['data']; + $this->Definitions[$definitionType][$Definition['id']] = $Definition['data']; continue 2; } @@ -182,9 +187,9 @@ class Parsedown $blockTypes = $this->unmarkedBlockTypes; - if (isset($this->blockMarkers[$marker])) + if (isset($this->BlockTypes[$marker])) { - foreach ($this->blockMarkers[$marker] as $blockType) + foreach ($this->BlockTypes[$marker] as $blockType) { $blockTypes []= $blockType; } @@ -195,23 +200,19 @@ class Parsedown foreach ($blockTypes as $blockType) { - # Block types define "identify" methods. - $Block = $this->{'identify'.$blockType}($Line, $CurrentBlock); if (isset($Block)) { $Block['type'] = $blockType; - if ( ! isset($Block['identified'])) # ยป + if ( ! isset($Block['identified'])) { $Elements []= $CurrentBlock['element']; $Block['identified'] = true; } - # Multiline block types define "addTo" methods. - if (method_exists($this, 'addTo'.$blockType)) { $Block['incomplete'] = true; @@ -225,7 +226,7 @@ class Parsedown # ~ - if ($CurrentBlock['type'] === 'Paragraph' and ! isset($CurrentBlock['interrupted'])) + if (isset($CurrentBlock) and ! isset($CurrentBlock['type']) and ! isset($CurrentBlock['interrupted'])) { $CurrentBlock['element']['text'] .= "\n".$text; } @@ -233,15 +234,9 @@ class Parsedown { $Elements []= $CurrentBlock['element']; - $CurrentBlock = array( - 'type' => 'Paragraph', - 'identified' => true, - 'element' => array( - 'name' => 'p', - 'text' => $text, - 'handler' => 'line', - ), - ); + $CurrentBlock = $this->buildParagraph($Line); + + $CurrentBlock['identified'] = true; } } @@ -296,15 +291,22 @@ class Parsedown } # - # Rule + # Code - protected function identifyRule($Line) + protected function identifyCodeBlock($Line) { - if (preg_match('/^(['.$Line['text'][0].'])([ ]{0,2}\1){2,}[ ]*$/', $Line['text'])) + if ($Line['indent'] >= 4) { + $text = substr($Line['body'], 4); + $Block = array( 'element' => array( - 'name' => 'hr' + 'name' => 'pre', + 'handler' => 'element', + 'text' => array( + 'name' => 'code', + 'text' => $text, + ), ), ); @@ -312,104 +314,72 @@ class Parsedown } } - # - # Reference - - protected function identifyReference($Line) + protected function addToCodeBlock($Line, $Block) { - if (preg_match('/^\[(.+?)\]:[ ]*?(?:[ ]+["\'(](.+)["\')])?[ ]*$/', $Line['text'], $matches)) + if ($Line['indent'] >= 4) { - $Definition = array( - 'id' => strtolower($matches[1]), - 'data' => array( - 'url' => $matches[2], - ), - ); - - if (isset($matches[3])) + if (isset($Block['interrupted'])) { - $Definition['data']['title'] = $matches[3]; + $Block['element']['text']['text'] .= "\n"; + + unset($Block['interrupted']); } - return $Definition; - } - } + $Block['element']['text']['text'] .= "\n"; - # - # Setext + $text = substr($Line['body'], 4); - protected function identifySetext($Line, array $Block = null) - { - if ( ! isset($Block) or $Block['type'] !== 'Paragraph' or isset($Block['interrupted'])) - { - return; - } - - if (chop($Line['text'], $Line['text'][0]) === '') - { - $Block['element']['name'] = $Line['text'][0] === '=' ? 'h1' : 'h2'; + $Block['element']['text']['text'] .= $text; return $Block; } } - # - # Markup - - protected function identifyMarkup($Line) + protected function completeCodeBlock($Block) { - if (preg_match('/^<(\w[\w\d]*)(?:[ ][^>\/]*)?(\/?)[ ]*>/', $Line['text'], $matches)) - { - if (in_array($matches[1], $this->textLevelElements)) - { - return; - } + $text = $Block['element']['text']['text']; + $text = htmlspecialchars($text, ENT_NOQUOTES, 'UTF-8'); + + $Block['element']['text']['text'] = $text; + + return $Block; + } + + # + # Comment + + protected function identifyComment($Line) + { + if (isset($Line['text'][3]) and $Line['text'][3] === '-' and $Line['text'][2] === '-' and $Line['text'][1] === '!') + { $Block = array( 'element' => $Line['body'], ); - if ($matches[2] or $matches[1] === 'hr' or preg_match('/<\/'.$matches[1].'>[ ]*$/', $Line['text'])) + if (preg_match('/-->$/', $Line['text'])) { $Block['closed'] = true; } - else - { - $Block['depth'] = 0; - $Block['start'] = '<'.$matches[1].'>'; - $Block['end'] = ''; - } return $Block; } } - protected function addToMarkup($Line, array $Block) + protected function addToComment($Line, array $Block) { if (isset($Block['closed'])) { return; } - if (stripos($Line['text'], $Block['start']) !== false) # opening tag - { - $Block['depth'] ++; - } + $Block['element'] .= "\n" . $Line['body']; - if (stripos($Line['text'], $Block['end']) !== false) # closing tag + if (preg_match('/-->$/', $Line['text'])) { - if ($Block['depth'] > 0) - { - $Block['depth'] --; - } - else - { - $Block['closed'] = true; - } + $Block['closed'] = true; } - $Block['element'] .= "\n".$Line['body']; - return $Block; } @@ -610,12 +580,106 @@ class Parsedown } } + # + # Rule + + protected function identifyRule($Line) + { + if (preg_match('/^(['.$Line['text'][0].'])([ ]{0,2}\1){2,}[ ]*$/', $Line['text'])) + { + $Block = array( + 'element' => array( + 'name' => 'hr' + ), + ); + + return $Block; + } + } + + # + # Setext + + protected function identifySetext($Line, array $Block = null) + { + if ( ! isset($Block) or isset($Block['type']) or isset($Block['interrupted'])) + { + return; + } + + if (chop($Line['text'], $Line['text'][0]) === '') + { + $Block['element']['name'] = $Line['text'][0] === '=' ? 'h1' : 'h2'; + + return $Block; + } + } + + # + # Markup + + protected function identifyMarkup($Line) + { + if (preg_match('/^<(\w[\w\d]*)(?:[ ][^>\/]*)?(\/?)[ ]*>/', $Line['text'], $matches)) + { + if (in_array($matches[1], $this->textLevelElements)) + { + return; + } + + $Block = array( + 'element' => $Line['body'], + ); + + if ($matches[2] or $matches[1] === 'hr' or preg_match('/<\/'.$matches[1].'>[ ]*$/', $Line['text'])) + { + $Block['closed'] = true; + } + else + { + $Block['depth'] = 0; + $Block['name'] = $matches[1]; + } + + return $Block; + } + } + + protected function addToMarkup($Line, array $Block) + { + if (isset($Block['closed'])) + { + return; + } + + if (preg_match('/<'.$Block['name'].'([ ][^\/]+)?>/', $Line['text'])) # opening tag + { + $Block['depth'] ++; + } + + if (stripos($Line['text'], '') !== false) # closing tag + { + if ($Block['depth'] > 0) + { + $Block['depth'] --; + } + else + { + $Block['closed'] = true; + } + } + + $Block['element'] .= "\n".$Line['body']; + + return $Block; + } + # # Table protected function identifyTable($Line, array $Block = null) { - if ( ! isset($Block) or $Block['type'] !== 'Paragraph' or isset($Block['interrupted'])) + if ( ! isset($Block) or isset($Block['type']) or isset($Block['interrupted'])) { return; } @@ -766,57 +830,42 @@ class Parsedown } # - # Code + # Definitions + # - protected function identifyCodeBlock($Line) + protected function identifyReference($Line) { - if ($Line['indent'] >= 4) + if (preg_match('/^\[(.+?)\]:[ ]*?(?:[ ]+["\'(](.+)["\')])?[ ]*$/', $Line['text'], $matches)) { - $text = substr($Line['body'], 4); - - $Block = array( - 'element' => array( - 'name' => 'pre', - 'handler' => 'element', - 'text' => array( - 'name' => 'code', - 'text' => $text, - ), + $Definition = array( + 'id' => strtolower($matches[1]), + 'data' => array( + 'url' => $matches[2], ), ); - return $Block; - } - } - - protected function addToCodeBlock($Line, $Block) - { - if ($Line['indent'] >= 4) - { - if (isset($Block['interrupted'])) + if (isset($matches[3])) { - $Block['element']['text']['text'] .= "\n"; - - unset($Block['interrupted']); + $Definition['data']['title'] = $matches[3]; } - $Block['element']['text']['text'] .= "\n"; - - $text = substr($Line['body'], 4); - - $Block['element']['text']['text'] .= $text; - - return $Block; + return $Definition; } } - protected function completeCodeBlock($Block) + # + # ~ + # + + protected function buildParagraph($Line) { - $text = $Block['element']['text']['text']; - - $text = htmlspecialchars($text, ENT_NOQUOTES, 'UTF-8'); - - $Block['element']['text']['text'] = $text; + $Block = array( + 'element' => array( + 'name' => 'p', + 'text' => $Line['text'], + 'handler' => 'line', + ), + ); return $Block; } @@ -825,7 +874,7 @@ class Parsedown # ~ # - private function element(array $Element) + protected function element(array $Element) { $markup = '<'.$Element['name']; @@ -860,7 +909,7 @@ class Parsedown return $markup; } - private function elements(array $Elements) + protected function elements(array $Elements) { $markup = ''; @@ -873,7 +922,7 @@ class Parsedown $markup .= "\n"; - if (is_string($Element)) # because of markup + if (is_string($Element)) # because of Markup { $markup .= $Element; @@ -892,7 +941,7 @@ class Parsedown # Spans # - protected $spanMarkers = array( + protected $SpanTypes = array( '!' => array('Link'), # ? '&' => array('Ampersand'), '*' => array('Emphasis'), @@ -905,8 +954,14 @@ class Parsedown '\\' => array('EscapeSequence'), ); + # ~ + protected $spanMarkerList = '*_!&[spanMarkerList)) + while ($excerpt = strpbrk($remainder, $this->spanMarkerList)) { - $marker = $markedExcerpt[0]; + $marker = $excerpt[0]; $markerPosition += strpos($remainder, $marker); - foreach ($this->spanMarkers[$marker] as $spanType) + $Excerpt = array('text' => $excerpt, 'context' => $text); + + foreach ($this->SpanTypes[$marker] as $spanType) { $handler = 'identify'.$spanType; - $Span = $this->$handler($markedExcerpt, $text); + $Span = $this->$handler($Excerpt); if ( ! isset($Span)) { @@ -950,7 +1007,7 @@ class Parsedown $markup .= $this->readPlainText($plainText); - $markup .= isset($Span['element']) ? $this->element($Span['element']) : $Span['markup']; + $markup .= isset($Span['markup']) ? $Span['markup'] : $this->element($Span['element']); $text = substr($text, $Span['position'] + $Span['extent']); @@ -961,7 +1018,7 @@ class Parsedown continue 2; } - $remainder = substr($markedExcerpt, 1); + $remainder = substr($excerpt, 1); $markerPosition ++; } @@ -975,14 +1032,14 @@ class Parsedown # ~ # - protected function identifyUrl($excerpt, $text) + protected function identifyUrl($Excerpt) { - if ( ! isset($excerpt[1]) or $excerpt[1] !== '/') + if ( ! isset($Excerpt['text'][1]) or $Excerpt['text'][1] !== '/') { return; } - if (preg_match('/\bhttps?:[\/]{2}[^\s]+\b\/*/ui', $text, $matches, PREG_OFFSET_CAPTURE)) + if (preg_match('/\bhttps?:[\/]{2}[^\s<]+\b\/*/ui', $Excerpt['context'], $matches, PREG_OFFSET_CAPTURE)) { $url = str_replace(array('&', '<'), array('&', '<'), $matches[0][0]); @@ -1000,9 +1057,9 @@ class Parsedown } } - protected function identifyAmpersand($excerpt) + protected function identifyAmpersand($Excerpt) { - if ( ! preg_match('/^&#?\w+;/', $excerpt)) + if ( ! preg_match('/^&#?\w+;/', $Excerpt['text'])) { return array( 'markup' => '&', @@ -1011,14 +1068,14 @@ class Parsedown } } - protected function identifyStrikethrough($excerpt) + protected function identifyStrikethrough($Excerpt) { - if ( ! isset($excerpt[1])) + if ( ! isset($Excerpt['text'][1])) { return; } - if ($excerpt[1] === $excerpt[0] and preg_match('/^~~(?=\S)(.+?)(?<=\S)~~/', $excerpt, $matches)) + if ($Excerpt['text'][1] === '~' and preg_match('/^~~(?=\S)(.+?)(?<=\S)~~/', $Excerpt['text'], $matches)) { return array( 'extent' => strlen($matches[0]), @@ -1031,12 +1088,12 @@ class Parsedown } } - protected function identifyEscapeSequence($excerpt) + protected function identifyEscapeSequence($Excerpt) { - if (in_array($excerpt[1], $this->specialCharacters)) + if (isset($Excerpt['text'][1]) and in_array($Excerpt['text'][1], $this->specialCharacters)) { return array( - 'markup' => $excerpt[1], + 'markup' => $Excerpt['text'][1], 'extent' => 2, ); } @@ -1050,9 +1107,9 @@ class Parsedown ); } - protected function identifyUrlTag($excerpt) + protected function identifyUrlTag($Excerpt) { - if (strpos($excerpt, '>') !== false and preg_match('/^<(https?:[\/]{2}[^\s]+?)>/i', $excerpt, $matches)) + if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<(https?:[\/]{2}[^\s]+?)>/i', $Excerpt['text'], $matches)) { $url = str_replace(array('&', '<'), array('&', '<'), $matches[1]); @@ -1069,9 +1126,9 @@ class Parsedown } } - protected function identifyEmailTag($excerpt) + protected function identifyEmailTag($Excerpt) { - if (strpos($excerpt, '>') !== false and preg_match('/^<(\S+?@\S+?)>/', $excerpt, $matches)) + if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<(\S+?@\S+?)>/', $Excerpt['text'], $matches)) { return array( 'extent' => strlen($matches[0]), @@ -1086,9 +1143,9 @@ class Parsedown } } - protected function identifyTag($excerpt) + protected function identifyTag($Excerpt) { - if (strpos($excerpt, '>') !== false and preg_match('/^<\/?\w.*?>/', $excerpt, $matches)) + if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<\/?\w.*?>/', $Excerpt['text'], $matches)) { return array( 'markup' => $matches[0], @@ -1097,11 +1154,11 @@ class Parsedown } } - protected function identifyInlineCode($excerpt) + protected function identifyInlineCode($Excerpt) { - $marker = $excerpt[0]; + $marker = $Excerpt['text'][0]; - if (preg_match('/^('.$marker.'+)[ ]*(.+?)[ ]*(? $matches[1], 'label' => strtolower($matches[1])); $extent += strlen($matches[0]); - $substring = substr($excerpt, $extent); + $substring = substr($Excerpt['text'], $extent); - if (preg_match('/^\s*\[(.+?)\]/', $substring, $matches)) + if (preg_match('/^\s*\[([^][]+)\]/', $substring, $matches)) { $Link['label'] = strtolower($matches[1]); - if (isset($this->definitions['Reference'][$Link['label']])) + if (isset($this->Definitions['Reference'][$Link['label']])) { - $Link += $this->definitions['Reference'][$Link['label']]; + $Link += $this->Definitions['Reference'][$Link['label']]; $extent += strlen($matches[0]); } @@ -1143,9 +1200,9 @@ class Parsedown return; } } - elseif (isset($this->definitions['Reference'][$Link['label']])) + elseif (isset($this->Definitions['Reference'][$Link['label']])) { - $Link += $this->definitions['Reference'][$Link['label']]; + $Link += $this->Definitions['Reference'][$Link['label']]; if (preg_match('/^[ ]*\[\]/', $substring, $matches)) { @@ -1175,7 +1232,7 @@ class Parsedown $url = str_replace(array('&', '<'), array('&', '<'), $Link['url']); - if ($excerpt[0] === '!') + if ($Excerpt['text'][0] === '!') { $Element = array( 'name' => 'img', @@ -1208,20 +1265,20 @@ class Parsedown ); } - protected function identifyEmphasis($excerpt) + protected function identifyEmphasis($Excerpt) { - if ( ! isset($excerpt[1])) + if ( ! isset($Excerpt['text'][1])) { return; } - $marker = $excerpt[0]; + $marker = $Excerpt['text'][0]; - if ($excerpt[1] === $marker and preg_match($this->strongRegex[$marker], $excerpt, $matches)) + if ($Excerpt['text'][1] === $marker and preg_match($this->StrongRegex[$marker], $Excerpt['text'], $matches)) { $emphasis = 'strong'; } - elseif (preg_match($this->emRegex[$marker], $excerpt, $matches)) + elseif (preg_match($this->EmRegex[$marker], $Excerpt['text'], $matches)) { $emphasis = 'em'; } @@ -1313,7 +1370,7 @@ class Parsedown # Fields # - protected $definitions; + protected $Definitions; # # Read-only @@ -1322,12 +1379,12 @@ class Parsedown '\\', '`', '*', '_', '{', '}', '[', ']', '(', ')', '>', '#', '+', '-', '.', '!', ); - protected $strongRegex = array( + protected $StrongRegex = array( '*' => '/^[*]{2}((?:[^*]|[*][^*]*[*])+?)[*]{2}(?![*])/s', '_' => '/^__((?:[^_]|_[^_]*_)+?)__(?!_)/us', ); - protected $emRegex = array( + protected $EmRegex = array( '*' => '/^[*]((?:[^*]|[*][*][^*]+?[*][*])+?)[*](?![*])/s', '_' => '/^_((?:[^_]|__[^_]*__)+?)_(?!_)\b/us', ); diff --git a/library/vendor/Parsedown/SOURCE b/library/vendor/Parsedown/SOURCE index 59f79409d..c5a2c7c28 100644 --- a/library/vendor/Parsedown/SOURCE +++ b/library/vendor/Parsedown/SOURCE @@ -1,4 +1,4 @@ -RELEASE=1.0.0-rc.4 +RELEASE=1.0.0 FILENAME=parsedown-$RELEASE DESTINATION=. wget -O ${FILENAME}.tar.gz https://github.com/erusev/parsedown/archive/${RELEASE}.tar.gz diff --git a/library/vendor/dompdf/dompdf_config.inc.php b/library/vendor/dompdf/dompdf_config.inc.php index 723b5c0dc..742b312b7 100644 --- a/library/vendor/dompdf/dompdf_config.inc.php +++ b/library/vendor/dompdf/dompdf_config.inc.php @@ -266,7 +266,7 @@ def("DOMPDF_ENABLE_PHP", false); * * @var bool */ -def("DOMPDF_ENABLE_JAVASCRIPT", true); +def("DOMPDF_ENABLE_JAVASCRIPT", false; /** * Enable remote file access @@ -285,7 +285,7 @@ def("DOMPDF_ENABLE_JAVASCRIPT", true); * * @var bool */ -def("DOMPDF_ENABLE_REMOTE", false); +def("DOMPDF_ENABLE_REMOTE", true); /** * The debug output log diff --git a/modules/monitoring/application/controllers/ShowController.php b/modules/monitoring/application/controllers/ShowController.php index b695389a4..e8f3dd1b4 100644 --- a/modules/monitoring/application/controllers/ShowController.php +++ b/modules/monitoring/application/controllers/ShowController.php @@ -58,8 +58,7 @@ class Monitoring_ShowController extends Controller { if ($this->getRequest()->getActionName() === 'host') { $this->view->object = new Host($this->getRequest()); - } elseif ($this->getRequest()->getActionName() === 'service' - || $this->getRequest()->getActionName() === 'services' ) { + } elseif ($this->getRequest()->getActionName() === 'service') { $this->view->object = new Service($this->getRequest()); } else { // TODO: Well... this could be done better diff --git a/modules/monitoring/application/views/scripts/list/eventhistory.phtml b/modules/monitoring/application/views/scripts/list/eventhistory.phtml index 5fe526739..fb8e1b212 100644 --- a/modules/monitoring/application/views/scripts/list/eventhistory.phtml +++ b/modules/monitoring/application/views/scripts/list/eventhistory.phtml @@ -1,9 +1,7 @@
tabs->render($this); ?>
- Sort by sortControl->render($this); ?> -
paginationControl($history, null, null, array('preserve' => $this->preserve)); ?>
diff --git a/modules/monitoring/application/views/scripts/list/servicematrix.phtml b/modules/monitoring/application/views/scripts/list/servicematrix.phtml index 0aa0c324c..224dd46c5 100644 --- a/modules/monitoring/application/views/scripts/list/servicematrix.phtml +++ b/modules/monitoring/application/views/scripts/list/servicematrix.phtml @@ -2,7 +2,7 @@
tabs; ?>
- Sort by sortControl->render($this); ?> + Sort by sortControl ?>
partial( 'pivottablePagination.phtml', @@ -15,7 +15,7 @@
- +
pivot->toArray(); @@ -23,57 +23,57 @@ $hostFilter = implode(',', array_keys($pivotData)); ?> $serviceStates): ?> - - - - + + + - - - + + + + + - - + + - - - + - + - -
  -
+
  + -
- - - -
+ + - + + + - · + ·
+ +
diff --git a/modules/monitoring/application/views/scripts/list/services.phtml b/modules/monitoring/application/views/scripts/list/services.phtml index 35ae7a473..346555a07 100644 --- a/modules/monitoring/application/views/scripts/list/services.phtml +++ b/modules/monitoring/application/views/scripts/list/services.phtml @@ -9,20 +9,16 @@ if (!$this->compact): ?> Sort by sortControl ?>
-paginationControl($services, null, null, array('preserve' => $this->preserve));?> - - -selectionToolbar('multi', $this->href('monitoring/multi/service', $query)); ?> +paginationControl($services, null, null, array('preserve' => $this->preserve)) ?> +selectionToolbar('multi', $this->href('monitoring/multi/service', $query)) ?>
-" - data-icinga-multiselect-data="service,host" -> + data-icinga-multiselect-data="service,host"> - service_icon_image): ?> + service_icon_image && ! preg_match('/[\'"]/', $service->service_icon_image)): ?> icon($this->resolveMacros($service->service_icon_image, $service)) ?> service_display_name ?>showHost): ?> on host_name; ?> diff --git a/modules/monitoring/application/views/scripts/show/components/checksource.phtml b/modules/monitoring/application/views/scripts/show/components/checksource.phtml new file mode 100644 index 000000000..60bb944f3 --- /dev/null +++ b/modules/monitoring/application/views/scripts/show/components/checksource.phtml @@ -0,0 +1,7 @@ +check_source) return ?> + + + + diff --git a/modules/monitoring/application/views/scripts/show/components/flapping.phtml b/modules/monitoring/application/views/scripts/show/components/flapping.phtml index b6dbe0cee..0cf9d6408 100644 --- a/modules/monitoring/application/views/scripts/show/components/flapping.phtml +++ b/modules/monitoring/application/views/scripts/show/components/flapping.phtml @@ -6,7 +6,7 @@ if ($object->is_flapping) { 'Flapping', $this->icon('flapping.png', 'Flapping'), sprintf( - 'Currently flapping witgh a %.2f%% state change rate', + 'Currently flapping with a %.2f%% state change rate', $object->percent_state_change ) ); diff --git a/modules/monitoring/application/views/scripts/show/host.phtml b/modules/monitoring/application/views/scripts/show/host.phtml index d21fed261..189729192 100644 --- a/modules/monitoring/application/views/scripts/show/host.phtml +++ b/modules/monitoring/application/views/scripts/show/host.phtml @@ -13,6 +13,7 @@ render('show/components/downtime.phtml') ?> render('show/components/flapping.phtml') ?> render('show/components/perfdata.phtml') ?> +render('show/components/checksource.phtml') ?> render('show/components/actions.phtml') ?> render('show/components/command.phtml') ?> render('show/components/hostgroups.phtml') ?> diff --git a/modules/monitoring/application/views/scripts/show/service.phtml b/modules/monitoring/application/views/scripts/show/service.phtml index 18ef09cd6..1c8f42c9f 100644 --- a/modules/monitoring/application/views/scripts/show/service.phtml +++ b/modules/monitoring/application/views/scripts/show/service.phtml @@ -13,6 +13,7 @@ render('show/components/downtime.phtml') ?> render('show/components/flapping.phtml') ?> render('show/components/perfdata.phtml') ?> +render('show/components/checksource.phtml') ?> render('show/components/actions.phtml') ?> render('show/components/command.phtml') ?> render('show/components/servicegroups.phtml') ?> diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ContactgroupQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ContactgroupQuery.php index dde165c0e..a335bfec0 100644 --- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ContactgroupQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ContactgroupQuery.php @@ -113,9 +113,9 @@ class ContactgroupQuery extends IdoQuery +-------------------------+-------------+------------+------------------------+ */ - $this->select->join( - // array('scg' => $this->prefix . 'service_contactgroups'), - array('scg' => $scgSub), + $this->baseQuery->distinct()->join( + array('scg' => $this->prefix . 'service_contactgroups'), + // array('scg' => $scgSub), 'scg.contactgroup_object_id = cg.contactgroup_object_id', array() )->join( diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/CustomvarQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/CustomvarQuery.php index 99c5bf0cd..981fb5712 100644 --- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/CustomvarQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/CustomvarQuery.php @@ -14,11 +14,23 @@ class CustomvarQuery extends IdoQuery 'service_host_name' => 'cvo.name1 COLLATE latin1_general_ci', 'service_description' => 'cvo.name2 COLLATE latin1_general_ci', 'contact_name' => 'cvo.name1 COLLATE latin1_general_ci', - 'object_type' => "CASE cvo.objecttype_id WHEN 1 THEN 'host' WHEN 2 THEN 'service' WHEN 10 THEN 'contact' ELSE 'invalid' END" + 'object_type' => "CASE cvo.objecttype_id WHEN 1 THEN 'host' WHEN 2 THEN 'service' WHEN 10 THEN 'contact' ELSE 'invalid' END", + 'object_type_id' => 'cvo.objecttype_id' // 'object_type' => "CASE cvo.objecttype_id WHEN 1 THEN 'host' WHEN 2 THEN 'service' WHEN 3 THEN 'hostgroup' WHEN 4 THEN 'servicegroup' WHEN 5 THEN 'hostescalation' WHEN 6 THEN 'serviceescalation' WHEN 7 THEN 'hostdependency' WHEN 8 THEN 'servicedependency' WHEN 9 THEN 'timeperiod' WHEN 10 THEN 'contact' WHEN 11 THEN 'contactgroup' WHEN 12 THEN 'command' ELSE 'other' END" ), ); + public function where($expression, $parameters = null) + { + $types = array('host' => 1, 'service' => 2, 'contact' => 10); + if ($expression === 'object_type') { + parent::where('object_type_id', $types[$parameters]); + } else { + parent::where($expression, $parameters); + } + return $this; + } + protected function joinBaseTables() { $this->select->from( diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php index da593778e..67988ec48 100644 --- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php @@ -32,6 +32,8 @@ namespace Icinga\Module\Monitoring\Backend\Ido\Query; use Icinga\Logger\Logger; use Icinga\Data\Db\Query; use Icinga\Exception\ProgrammingError; +use Icinga\Application\Icinga; +use Icinga\Web\Session; /** * Base class for Ido Queries @@ -181,6 +183,18 @@ abstract class IdoQuery extends Query */ protected $allowCustomVars = false; + /** + * Current IDO version. This is bullshit and needs to be moved somewhere + * else. As someone decided that we need no Backend-specific connection + * class unfortunately there is no better place right now. And as of the + * 'check_source' patch we need a quick fix immediately. So here you go. + * + * TODO: Fix this. + * + * @var string + */ + protected static $idoVersion; + /** * Return true when the column is an aggregate column * @@ -578,4 +592,29 @@ abstract class IdoQuery extends Query $this->columns = $this->resolveColumns($columns); return $this; } + + // TODO: Move this away, see note related to $idoVersion var + protected function getIdoVersion() + { + if (self::$idoVersion === null) { + $session = null; + if (Icinga::app()->isWeb()) { + // TODO: Once we have version per connection we should choose a + // namespace based on resource name + $session = Session::getSession()->getNamespace('monitoring/ido'); + if (isset($session->version)) { + self::$idoVersion = $session->version; + return self::$idoVersion; + } + } + self::$idoVersion = $this->db->fetchOne( + $this->db->select()->from($this->prefix . 'dbversion', 'version') + ); + if ($session !== null) { + $session->version = self::$idoVersion; + $session->write(); // <- WHY? I don't want to care about this! + } + } + return self::$idoVersion; + } } diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatusQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatusQuery.php index 8d60b3307..6d7fc5588 100644 --- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatusQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatusQuery.php @@ -52,6 +52,7 @@ class StatusQuery extends IdoQuery 'host_output' => 'hs.output', 'host_long_output' => 'hs.long_output', 'host_perfdata' => 'hs.perfdata', + 'host_check_source' => 'hs.check_source', 'host_acknowledged' => 'hs.problem_has_been_acknowledged', 'host_in_downtime' => 'CASE WHEN (hs.scheduled_downtime_depth = 0) THEN 0 ELSE 1 END', 'host_handled' => 'CASE WHEN (hs.problem_has_been_acknowledged + hs.scheduled_downtime_depth) > 0 THEN 1 ELSE 0 END', @@ -181,6 +182,7 @@ class StatusQuery extends IdoQuery 'service_output' => 'ss.output', 'service_long_output' => 'ss.long_output', 'service_perfdata' => 'ss.perfdata', + 'service_check_source' => 'ss.check_source', 'service_acknowledged' => 'ss.problem_has_been_acknowledged', 'service_in_downtime' => 'CASE WHEN (ss.scheduled_downtime_depth = 0 OR ss.scheduled_downtime_depth IS NULL) THEN 0 ELSE 1 END', 'service_handled' => 'CASE WHEN (ss.problem_has_been_acknowledged + ss.scheduled_downtime_depth + COALESCE(hs.current_state, 0)) > 0 THEN 1 ELSE 0 END', @@ -303,6 +305,10 @@ class StatusQuery extends IdoQuery protected function joinBaseTables() { + if (version_compare($this->getIdoVersion(), '1.10.0', '<')) { + $this->columnMap['hoststatus']['host_check_source'] = '(NULL)'; + $this->columnMap['servicestatus']['service_check_source'] = '(NULL)'; + } $this->select->from(array('ho' => $this->prefix . 'objects'), array()) ->join( array('hs' => $this->prefix . 'hoststatus'), diff --git a/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/StatusQuery.php b/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/StatusQuery.php index 1fa082254..d17468bd3 100644 --- a/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/StatusQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/StatusQuery.php @@ -30,6 +30,7 @@ class StatusQuery extends StatusdatQuery 'host_output' => 'host.status.plugin_output', 'host_long_output' => 'host.status.long_plugin_output', 'host_perfdata' => 'host.status.performance_data', + 'host_check_source' => 'host.status.check_source', 'host_acknowledged' => 'host.status.problem_has_been_acknowledged', 'host_last_state_change' => 'host.status.last_state_change', 'host_last_hard_state' => 'host.status.last_hard_state', @@ -82,6 +83,7 @@ class StatusQuery extends StatusdatQuery 'service_output' => 'service.status.output', 'service_long_output' => 'service.status.long_output', 'service_perfdata' => 'service.status.perfdata', + 'service_check_source' => 'service.status.check_source', 'service_acknowledged' => 'service.status.problem_has_been_acknowledged', 'service_last_state_change' => 'service.status.last_state_change', 'service_check_command' => 'service.status.check_command', diff --git a/modules/monitoring/library/Monitoring/Controller.php b/modules/monitoring/library/Monitoring/Controller.php index 49be32eca..a5d17b89e 100644 --- a/modules/monitoring/library/Monitoring/Controller.php +++ b/modules/monitoring/library/Monitoring/Controller.php @@ -29,8 +29,8 @@ namespace Icinga\Module\Monitoring; -use Icinga\File\Csv; use Icinga\Web\Controller\ActionController; +use Icinga\File\Csv; /** * Base class for all monitoring action controller diff --git a/modules/monitoring/library/Monitoring/DataView/HostStatus.php b/modules/monitoring/library/Monitoring/DataView/HostStatus.php index 36ffe9354..db67cdf78 100644 --- a/modules/monitoring/library/Monitoring/DataView/HostStatus.php +++ b/modules/monitoring/library/Monitoring/DataView/HostStatus.php @@ -62,6 +62,7 @@ class HostStatus extends DataView 'host_long_output', 'host_check_command', 'host_perfdata', + 'host_check_source', 'host_passive_checks_enabled', 'host_passive_checks_enabled_changed', 'host_obsessing', diff --git a/modules/monitoring/library/Monitoring/DataView/ServiceStatus.php b/modules/monitoring/library/Monitoring/DataView/ServiceStatus.php index 31d8960ac..563d7aaef 100644 --- a/modules/monitoring/library/Monitoring/DataView/ServiceStatus.php +++ b/modules/monitoring/library/Monitoring/DataView/ServiceStatus.php @@ -90,6 +90,7 @@ class ServiceStatus extends DataView 'host_ipv4', 'host_severity', 'host_perfdata', + 'host_check_source', 'host_active_checks_enabled', 'host_passive_checks_enabled', 'host_last_hard_state', @@ -102,6 +103,7 @@ class ServiceStatus extends DataView 'service_hard_state', 'service_problem', 'service_perfdata', + 'service_check_source', 'service_active_checks_enabled', 'service_active_checks_enabled_changed', 'service_passive_checks_enabled', diff --git a/modules/monitoring/library/Monitoring/Object/AbstractObject.php b/modules/monitoring/library/Monitoring/Object/AbstractObject.php index 23417f034..de01845a4 100644 --- a/modules/monitoring/library/Monitoring/Object/AbstractObject.php +++ b/modules/monitoring/library/Monitoring/Object/AbstractObject.php @@ -33,6 +33,7 @@ abstract class AbstractObject public $customvars = array(); public $events = array(); + protected $view; private $properties = array(); private $request = null; @@ -251,11 +252,6 @@ abstract class AbstractObject return $this->$expandedName; } - public function getRequest() - { - return $this->request; - } - public static function fromRequest(Request $request) { if ($request->has('service') && $request->has('host')) { diff --git a/modules/monitoring/library/Monitoring/Object/Host.php b/modules/monitoring/library/Monitoring/Object/Host.php index 41a6dbb01..7c89bc838 100644 --- a/modules/monitoring/library/Monitoring/Object/Host.php +++ b/modules/monitoring/library/Monitoring/Object/Host.php @@ -9,7 +9,6 @@ class Host extends AbstractObject { public $type = 'host'; public $prefix = 'host_'; - private $view = null; protected function applyObjectFilter(Query $query) { @@ -28,7 +27,48 @@ class Host extends AbstractObject protected function getProperties() { - $this->view = HostStatus::fromRequest($this->getRequest()); + $this->view = HostStatus::fromRequest($this->request, array( + 'host_name', + 'host_alias', + 'host_address', + 'host_state', + 'host_state_type', + 'host_handled', + 'host_in_downtime', + 'host_acknowledged', + 'host_last_state_change', + 'host_last_notification', + 'host_last_check', + 'host_next_check', + 'host_check_execution_time', + 'host_check_latency', + 'host_check_source', + 'host_output', + 'host_long_output', + 'host_check_command', + 'host_perfdata', + 'host_passive_checks_enabled', + 'host_passive_checks_enabled_changed', + 'host_obsessing', + 'host_obsessing_changed', + 'host_notifications_enabled', + 'host_notifications_enabled_changed', + 'host_event_handler_enabled', + 'host_event_handler_enabled_changed', + 'host_flap_detection_enabled', + 'host_flap_detection_enabled_changed', + 'host_active_checks_enabled', + 'host_active_checks_enabled_changed', + 'host_current_check_attempt', + 'host_max_check_attempts', + 'host_current_notification_number', + 'host_percent_state_change', + 'host_is_flapping', + 'host_action_url', + 'host_notes_url', + 'host_modified_host_attributes', + 'host_problem' + )); return $this->view->getQuery()->fetchRow(); } } diff --git a/modules/monitoring/library/Monitoring/Object/Service.php b/modules/monitoring/library/Monitoring/Object/Service.php index 2a661f7b7..ab7209a85 100644 --- a/modules/monitoring/library/Monitoring/Object/Service.php +++ b/modules/monitoring/library/Monitoring/Object/Service.php @@ -9,7 +9,6 @@ class Service extends AbstractObject { public $type = 'service'; public $prefix = 'service_'; - private $view = null; protected function applyObjectFilter(Query $query) { @@ -29,7 +28,90 @@ class Service extends AbstractObject protected function getProperties() { - $this->view = ServiceStatus::fromRequest($this->getRequest()); + $this->view = ServiceStatus::fromRequest($this->request, array( + 'host_name', + 'host_state', + 'host_state_type', + 'host_last_state_change', + 'host_address', + 'host_problem', + 'host_handled', + 'service_description', + 'service_display_name', + 'service_state', + 'service_in_downtime', + 'service_acknowledged', + 'service_handled', + 'service_unhandled', + 'service_output', + 'service_last_state_change', + 'service_icon_image', + 'service_long_output', + 'service_is_flapping', + 'service_state_type', + 'service_severity', + 'service_last_check', + 'service_notifications_enabled', + 'service_notifications_enabled_changed', + 'service_action_url', + 'service_notes_url', + 'service_last_check', + 'service_next_check', + 'service_attempt', + 'service_last_notification', + 'service_check_command', + 'service_check_source', + 'service_current_notification_number', + 'host_icon_image', + 'host_acknowledged', + 'host_output', + 'host_long_output', + 'host_in_downtime', + 'host_is_flapping', + 'host_last_check', + 'host_notifications_enabled', + 'host_unhandled_service_count', + 'host_action_url', + 'host_notes_url', + 'host_last_comment', + 'host_display_name', + 'host_alias', + 'host_ipv4', + 'host_severity', + 'host_perfdata', + 'host_active_checks_enabled', + 'host_passive_checks_enabled', + 'host_last_hard_state', + 'host_last_hard_state_change', + 'host_last_time_up', + 'host_last_time_down', + 'host_last_time_unreachable', + 'host_modified_host_attributes', + 'host', + 'service', + 'service_hard_state', + 'service_problem', + 'service_perfdata', + 'service_active_checks_enabled', + 'service_active_checks_enabled_changed', + 'service_passive_checks_enabled', + 'service_passive_checks_enabled_changed', + 'service_last_hard_state', + 'service_last_hard_state_change', + 'service_last_time_ok', + 'service_last_time_warning', + 'service_last_time_critical', + 'service_last_time_unknown', + 'service_current_check_attempt', + 'service_max_check_attempts', + 'service_obsessing', + 'service_obsessing_changed', + 'service_event_handler_enabled', + 'service_event_handler_enabled_changed', + 'service_flap_detection_enabled', + 'service_flap_detection_enabled_changed', + 'service_modified_service_attributes', + )); return $this->view->getQuery()->fetchRow(); } } diff --git a/packages/rhel/README b/packages/rhel/README new file mode 100644 index 000000000..4e04875bb --- /dev/null +++ b/packages/rhel/README @@ -0,0 +1,57 @@ +Requirements +============ + +Disabled SELinux for sending commands via external command pipe +provided by Icinga (2) Core. + +# setenforce 0 + + +Webinterface Login +================== + +The default credentials using the internal MySQL database are + +icingaadmin:icinga + + +Internal MySQL DB Setup +======================= + +# mysql -u root -p + CREATE USER `icingaweb`@`localhost` IDENTIFIED BY 'icingaweb'; + CREATE DATABASE `icingaweb`; + GRANT ALL PRIVILEGES ON `icingaweb`.* TO `icingaweb`@`localhost`; + FLUSH PRIVILEGES; + quit + +# mysql icingaweb < /usr/share/doc/icingaweb2-*/schema/accounts.mysql.sql +# mysql icingaweb < /usr/share/doc/icingaweb2-*/schema/preferences.mysql.sql + + +Modules +======= + +The monitoring module is enabled by default. + + +Backend configuration +===================== + +/etc/icingaweb/resources.ini + +contains the database backend information. By default +the Icinga IDO DB is used by the monitoring module in + +/etc/icingaweb/modules/monitoring/backends.ini + +The external command pipe is required for sending commands +and configured for Icinga 2 in + +/etc/icingaweb/modules/monitoring/instances.ini + + +Support +======= + +Please use one of the listed support channels at https://support.icinga.org diff --git a/packages/rhel/etc/httpd/conf.d/icingaweb.conf b/packages/rhel/etc/httpd/conf.d/icingaweb.conf new file mode 100644 index 000000000..47d408a67 --- /dev/null +++ b/packages/rhel/etc/httpd/conf.d/icingaweb.conf @@ -0,0 +1,12 @@ +Alias /icingaweb /usr/share/icingaweb/public + + Options -Indexes + + AllowOverride All + + Order allow,deny + Allow from all + + EnableSendfile Off + + diff --git a/packages/rhel/usr/share/icingaweb/public/.htaccess b/packages/rhel/usr/share/icingaweb/public/.htaccess new file mode 100644 index 000000000..8588fbbe1 --- /dev/null +++ b/packages/rhel/usr/share/icingaweb/public/.htaccess @@ -0,0 +1,7 @@ +RewriteEngine on +RewriteBase /icingaweb +RewriteCond %{REQUEST_FILENAME} -s [OR] +RewriteCond %{REQUEST_FILENAME} -l [OR] +RewriteCond %{REQUEST_FILENAME} -d +RewriteRule ^.*$ - [NC,L] +RewriteRule ^.*$ index.php [NC,L] diff --git a/packages/rhel/usr/share/icingaweb/public/index.php b/packages/rhel/usr/share/icingaweb/public/index.php new file mode 100644 index 000000000..45ac69392 --- /dev/null +++ b/packages/rhel/usr/share/icingaweb/public/index.php @@ -0,0 +1,5 @@ + ul { + margin: 0; + padding: 0; + list-style: none; + + & > li { + color: #f5f5f5; + font-size: 1.1em; + padding: 0.5em; + margin-left: 0.5em; + text-shadow: #555 -1px 1px 0px; + border-bottom: 1px solid #888; + + &.active { + color: black; + margin-left: 0; + padding-left: 1em; + text-shadow: none; + background-color: white; + } + + &.complete { + color: green; + } + + &.pending { + color: red; + } + + &.install { + border-bottom: 0; + } + + ul { + margin: 0; + padding: 0; + list-style: none; + + li.child { + font-size: 0.9em; + padding: 0.4em 0.8em 0; + + &.active { + font-weight: bold; + } + } + } + } + } + } + + div.panel { + padding: 1em; + position: fixed; + top: 3.6em; + left: 13em; + right: 0; + bottom: 0; + } +} diff --git a/public/css/icinga/layout-colors.less b/public/css/icinga/layout-colors.less index 36225c66b..0c54e4a12 100644 --- a/public/css/icinga/layout-colors.less +++ b/public/css/icinga/layout-colors.less @@ -26,14 +26,18 @@ background-color: white; } -.container { - background-color: white; -} - #col1.impact, #col2.impact, #col3.impact { background-color: #ddd; + transition: background-color 2s 1s linear; + -moz-transition: background-color 2s 1s linear; + -o-transition: background-color 2s 1s linear; + -webkit-transition: background-color 2s 1s linear; .controls { background-color: #ddd; + transition: background-color 2s 1s linear; + -moz-transition: background-color 2s 1s linear; + -o-transition: background-color 2s 1s linear; + -webkit-transition: background-color 2s 1s linear; } } diff --git a/public/css/icinga/tabs.less b/public/css/icinga/tabs.less index 7150b7ec5..2999a1928 100644 --- a/public/css/icinga/tabs.less +++ b/public/css/icinga/tabs.less @@ -46,13 +46,21 @@ ul.tabs > li.active > a:focus { color: #555; } -ul.tabs li.active a, ul.tabs li.dropdown:hover, ul.tabs li.dropdown.hover { +ul.tabs li.dropdown > a{ + padding: 0 0.4em; +} + +ul.tabs li.active a, ul.tabs li.dropdown:hover a, ul.tabs li.dropdown.hover a { background-color: white; color: #333; } -.impact ul.tabs li.active a, .impact ul.tabs li.dropdown:hover { - background: white; +.impact ul.tabs li.active a, .impact ul.tabs li.dropdown:hover, .impact ul.tabs li.dropdown.hover a { + background-color: #ddd; + transition: background-color 2s 1s linear; + -moz-transition: background-color 2s 1s linear; + -o-transition: background-color 2s 1s linear; + -webkit-transition: background-color 2s 1s linear; } ul.tabs li a:hover { @@ -74,13 +82,16 @@ ul.dropdown-menu { /* Dropdown tabs after the fourth title should be right-aligned */ ul.tabs li:nth-child(n+5) ul.dropdown-menu { width: 13em; - margin-left: -9em; + margin-left: -11em; } ul.dropdown-menu { + box-shadow: 0.2em 0.2em 0.3em -0.2em #555; -moz-box-shadow: 0.2em 0.2em 0.3em -0.2em #555; -webkit-box-shadow: 0.2em 0.2em 0.3em -0.2em #555; - box-shadow: 0.2em 0.2em 0.3em -0.2em #555; + border-radius: 0 0 3px 3px; + -moz-border-radius: 0 0 3px 3px; + -webkit-border-radius: 0 0 3px 3px; } ul.dropdown-menu li { diff --git a/public/js/icinga/events.js b/public/js/icinga/events.js index 39cd3cd00..cfaea02e1 100644 --- a/public/js/icinga/events.js +++ b/public/js/icinga/events.js @@ -9,6 +9,8 @@ Icinga.Events = function (icinga) { this.icinga = icinga; + + this.searchValue = ''; }; Icinga.Events.prototype = { @@ -74,6 +76,12 @@ // replace all sparklines $('span.sparkline', el).sparkline('html', { enableTagOptions: true }); + + var searchField = $('#menu input.search', el); + // Remember initial search field value if any + if (searchField.length && searchField.val().length) { + this.searchValue = searchField.val(); + } }, /** @@ -108,7 +116,7 @@ // We support an 'autosubmit' class on dropdown form elements $(document).on('change', 'form select.autosubmit', { self: this }, this.autoSubmitForm); - $(document).on('keyup', '#menu input.search', {self: this}, this.autoSubmitForm); + $(document).on('keyup', '#menu input.search', {self: this}, this.autoSubmitSearch); $(document).on('mouseenter', '.historycolorgrid td', this.historycolorgridHover); $(document).on('mouseleave', '.historycolorgrid td', this.historycolorgidUnhover); @@ -190,7 +198,8 @@ dropdownLeave: function () { var $li = $(this); setTimeout(function () { - if (! $li.is('li:hover') && ! $li.find(':focus')) { + // TODO: make this behave well together with keyboard navigation + if (! $li.is('li:hover') /*&& ! $li.find('a:focus')*/) { $li.removeClass('hover'); } }, 300); @@ -232,6 +241,15 @@ $(this).removeClass('hover'); }, + autoSubmitSearch: function(event) { + var self = event.data.self; + if ($('#menu input.search').val() === self.searchValue) { + return; + } + self.searchValue = $('#menu input.search').val(); + return self.autoSubmitForm(event); + }, + autoSubmitForm: function (event) { return event.data.self.submitForm(event, true); }, diff --git a/public/js/icinga/loader.js b/public/js/icinga/loader.js index 2f9454223..32a7875d5 100644 --- a/public/js/icinga/loader.js +++ b/public/js/icinga/loader.js @@ -118,6 +118,9 @@ if (id) { this.requests[id] = req; } + if (! autorefresh) { + req.$target.addClass('impact'); + } this.icinga.ui.refreshDebug(); return req; }, diff --git a/public/js/icinga/ui.js b/public/js/icinga/ui.js index bdb9dc714..e6e57db7c 100644 --- a/public/js/icinga/ui.js +++ b/public/js/icinga/ui.js @@ -664,8 +664,8 @@ '' ); },
translate('Check Source') ?> + escape($object->check_source) ?> +