mirror of
https://github.com/Icinga/icingaweb2.git
synced 2025-07-26 23:34:08 +02:00
Merge branch 'master' into feature/display-documentation-4820
This commit is contained in:
commit
25a73ea3a1
@ -63,8 +63,6 @@ class AuthenticationController extends ActionController
|
|||||||
$this->view->form = new LoginForm();
|
$this->view->form = new LoginForm();
|
||||||
$this->view->form->setRequest($this->_request);
|
$this->view->form->setRequest($this->_request);
|
||||||
$this->view->title = $this->translate('Icingaweb Login');
|
$this->view->title = $this->translate('Icingaweb Login');
|
||||||
$user = new User('');
|
|
||||||
$password = '';
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$redirectUrl = Url::fromPath($this->_request->getParam('redirect', 'dashboard'));
|
$redirectUrl = Url::fromPath($this->_request->getParam('redirect', 'dashboard'));
|
||||||
@ -95,9 +93,10 @@ class AuthenticationController extends ActionController
|
|||||||
|
|
||||||
|
|
||||||
if ($this->getRequest()->isGet()) {
|
if ($this->getRequest()->isGet()) {
|
||||||
|
$user = new User('');
|
||||||
foreach ($chain as $backend) {
|
foreach ($chain as $backend) {
|
||||||
if ($backend instanceof AutoLoginBackend) {
|
if ($backend instanceof AutoLoginBackend) {
|
||||||
$authenticated = $backend->authenticate($user, $password);
|
$authenticated = $backend->authenticate($user);
|
||||||
if ($authenticated === true) {
|
if ($authenticated === true) {
|
||||||
$auth->setAuthenticated($user);
|
$auth->setAuthenticated($user);
|
||||||
$this->redirectNow($redirectUrl);
|
$this->redirectNow($redirectUrl);
|
||||||
|
@ -179,9 +179,12 @@ class LdapBackendForm extends BaseBackendForm
|
|||||||
$backendConfig->user_class,
|
$backendConfig->user_class,
|
||||||
$backendConfig->user_name_attribute
|
$backendConfig->user_name_attribute
|
||||||
);
|
);
|
||||||
|
$testConn->assertAuthenticationPossible();
|
||||||
|
/*
|
||||||
if ($testConn->count() === 0) {
|
if ($testConn->count() === 0) {
|
||||||
throw new Exception('No Users Found On Directory Server');
|
throw new Exception('No Users Found On Directory Server');
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
} catch (Exception $exc) {
|
} catch (Exception $exc) {
|
||||||
$this->addErrorMessage(
|
$this->addErrorMessage(
|
||||||
t('Connection Validation Failed: ' . $exc->getMessage())
|
t('Connection Validation Failed: ' . $exc->getMessage())
|
||||||
|
@ -10,17 +10,16 @@ if (array_key_exists('_dev', $_GET)) {
|
|||||||
$cssfile = 'css/icinga.min.css';
|
$cssfile = 'css/icinga.min.css';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$ie8jsfile = 'js/icinga.ie8.js';
|
||||||
|
|
||||||
$isIframe = isset($_GET['_render']) && $_GET['_render'] === 'iframe';
|
$isIframe = isset($_GET['_render']) && $_GET['_render'] === 'iframe';
|
||||||
|
$iframeClass = $isIframe ? ' iframe' : '';
|
||||||
|
|
||||||
?><!DOCTYPE html>
|
?><!DOCTYPE html>
|
||||||
<!--[if lt IE 7]>
|
|
||||||
<html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
|
|
||||||
<!--[if IE 7]>
|
|
||||||
<html class="no-js lt-ie9 lt-ie8"> <![endif]-->
|
|
||||||
<!--[if IE 8]>
|
<!--[if IE 8]>
|
||||||
<html class="no-js lt-ie9"> <![endif]-->
|
<html class="no-js ie8<?= $iframeClass ?>"> <![endif]-->
|
||||||
<!--[if gt IE 8]><!-->
|
<!--[if gt IE 8]><!-->
|
||||||
<html class="no-js<?= $isIframe ? ' iframe' : '' ?>"> <!--<![endif]-->
|
<html class="no-js<?= $iframeClass ?>"> <!--<![endif]-->
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta content="width=320; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"/>
|
<meta content="width=320; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"/>
|
||||||
@ -50,7 +49,12 @@ $isIframe = isset($_GET['_render']) && $_GET['_render'] === 'iframe';
|
|||||||
<div id="layout" class="default-layout">
|
<div id="layout" class="default-layout">
|
||||||
<?= $this->render('body.phtml') ?>
|
<?= $this->render('body.phtml') ?>
|
||||||
</div>
|
</div>
|
||||||
|
<!--[if IE 8]>
|
||||||
|
<script type="text/javascript" src="<?= $this->href($ie8jsfile) ?>"></script>
|
||||||
|
<![endif]-->
|
||||||
|
<!--[if gt IE 8]><!-->
|
||||||
<script type="text/javascript" src="<?= $this->href($jsfile) ?>"></script>
|
<script type="text/javascript" src="<?= $this->href($jsfile) ?>"></script>
|
||||||
|
<!--<![endif]-->
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var icinga = new Icinga({
|
var icinga = new Icinga({
|
||||||
baseUrl: '<?= $this->href('/') ?>'
|
baseUrl: '<?= $this->href('/') ?>'
|
||||||
|
@ -14,7 +14,7 @@ timeFormat = "g:i A"
|
|||||||
[logging]
|
[logging]
|
||||||
enable = true
|
enable = true
|
||||||
; Writing to a Stream
|
; Writing to a Stream
|
||||||
type = "stream"
|
type = "file"
|
||||||
; Write data to the following file
|
; Write data to the following file
|
||||||
target = "@icingaweb_log_path@/icingaweb.log"
|
target = "@icingaweb_log_path@/icingaweb.log"
|
||||||
; Write data to a PHP stream
|
; Write data to a PHP stream
|
||||||
@ -22,8 +22,8 @@ target = "@icingaweb_log_path@/icingaweb.log"
|
|||||||
|
|
||||||
; Writing to the System Log
|
; Writing to the System Log
|
||||||
;type = "syslog"
|
;type = "syslog"
|
||||||
; Prefix all syslog messages generated with the string "Icinga Web"
|
; Prefix all syslog messages generated with the string "icingaweb"
|
||||||
;application = "Icinga Web"
|
;application = "icingaweb"
|
||||||
;facility = "LOG_USER"
|
;facility = "LOG_USER"
|
||||||
|
|
||||||
level = 1
|
level = 1
|
||||||
|
@ -30,7 +30,6 @@
|
|||||||
|
|
||||||
namespace Icinga\Application;
|
namespace Icinga\Application;
|
||||||
|
|
||||||
use DateTimeZone;
|
|
||||||
use Exception;
|
use Exception;
|
||||||
use Zend_Config;
|
use Zend_Config;
|
||||||
use Icinga\Application\Modules\Manager as ModuleManager;
|
use Icinga\Application\Modules\Manager as ModuleManager;
|
||||||
@ -484,7 +483,7 @@ abstract class ApplicationBootstrap
|
|||||||
|
|
||||||
$localeDir = $this->getApplicationDir('locale');
|
$localeDir = $this->getApplicationDir('locale');
|
||||||
if (file_exists($localeDir) && is_dir($localeDir)) {
|
if (file_exists($localeDir) && is_dir($localeDir)) {
|
||||||
Translator::registerDomain('icinga', $localeDir);
|
Translator::registerDomain(Translator::DEFAULT_DOMAIN, $localeDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
|
@ -32,7 +32,7 @@ use \Icinga\Util\Translator;
|
|||||||
if (extension_loaded('gettext')) {
|
if (extension_loaded('gettext')) {
|
||||||
function t($messageId)
|
function t($messageId)
|
||||||
{
|
{
|
||||||
return Translator::translate($messageId, 'icinga');
|
return Translator::translate($messageId, Translator::DEFAULT_DOMAIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
function mt($domain, $messageId)
|
function mt($domain, $messageId)
|
||||||
|
@ -47,6 +47,7 @@ $special = array(
|
|||||||
'css/icinga.css',
|
'css/icinga.css',
|
||||||
'css/icinga.min.css',
|
'css/icinga.min.css',
|
||||||
'js/icinga.dev.js',
|
'js/icinga.dev.js',
|
||||||
|
'js/icinga.ie8.js',
|
||||||
'js/icinga.min.js'
|
'js/icinga.min.js'
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -72,6 +73,10 @@ if (in_array($path, $special)) {
|
|||||||
JavaScript::sendMinified();
|
JavaScript::sendMinified();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'js/icinga.ie8.js':
|
||||||
|
JavaScript::sendForIe8();
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,9 @@
|
|||||||
|
|
||||||
namespace Icinga\Authentication\Backend;
|
namespace Icinga\Authentication\Backend;
|
||||||
|
|
||||||
|
use Zend_Config;
|
||||||
use Icinga\Authentication\UserBackend;
|
use Icinga\Authentication\UserBackend;
|
||||||
use Icinga\User;
|
use Icinga\User;
|
||||||
use \Zend_Config;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test login with external authentication mechanism, e.g. Apache
|
* Test login with external authentication mechanism, e.g. Apache
|
||||||
@ -31,13 +31,11 @@ class AutoLoginBackend extends UserBackend
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* (PHP 5 >= 5.1.0)<br/>
|
* Count the available users
|
||||||
* Count elements of an object
|
*
|
||||||
* @link http://php.net/manual/en/countable.count.php
|
* Autologin backends will always return 1
|
||||||
* @return int The custom count as an integer.
|
*
|
||||||
* </p>
|
* @return int
|
||||||
* <p>
|
|
||||||
* The return value is cast to an integer.
|
|
||||||
*/
|
*/
|
||||||
public function count()
|
public function count()
|
||||||
{
|
{
|
||||||
@ -53,22 +51,18 @@ class AutoLoginBackend extends UserBackend
|
|||||||
*/
|
*/
|
||||||
public function hasUser(User $user)
|
public function hasUser(User $user)
|
||||||
{
|
{
|
||||||
if (isset($_SERVER['PHP_AUTH_USER'])
|
if (isset($_SERVER['REMOTE_USER'])) {
|
||||||
&& isset($_SERVER['AUTH_TYPE'])
|
$username = $_SERVER['REMOTE_USER'];
|
||||||
&& in_array($_SERVER['AUTH_TYPE'], array('Basic', 'Digest')) === true
|
if ($this->stripUsernameRegexp !== null) {
|
||||||
) {
|
$stripped = preg_replace($this->stripUsernameRegexp, '', $username);
|
||||||
$username = filter_var(
|
if ($stripped !== false) {
|
||||||
$_SERVER['PHP_AUTH_USER'],
|
// TODO(el): PHP issues a warning when PHP cannot compile the regular expression. Should we log an
|
||||||
FILTER_SANITIZE_STRING,
|
// additional message in that case?
|
||||||
FILTER_FLAG_ENCODE_HIGH|FILTER_FLAG_ENCODE_LOW
|
$username = $stripped;
|
||||||
);
|
|
||||||
|
|
||||||
if ($username !== false) {
|
|
||||||
if ($this->stripUsernameRegexp !== null) {
|
|
||||||
$username = preg_replace($this->stripUsernameRegexp, '', $username);
|
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
$user->setUsername($username);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -77,12 +71,12 @@ class AutoLoginBackend extends UserBackend
|
|||||||
/**
|
/**
|
||||||
* Authenticate
|
* Authenticate
|
||||||
*
|
*
|
||||||
* @param User $user
|
* @param User $user
|
||||||
* @param string $password
|
* @param string $password
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function authenticate(User $user, $password)
|
public function authenticate(User $user, $password = null)
|
||||||
{
|
{
|
||||||
return $this->hasUser($user);
|
return $this->hasUser($user);
|
||||||
}
|
}
|
||||||
|
@ -75,12 +75,46 @@ class LdapUserBackend extends UserBackend
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Probe the backend to test if authentication is possible
|
||||||
|
*
|
||||||
|
* Try to bind to the backend and query all available users to check if:
|
||||||
|
* <ul>
|
||||||
|
* <li>User connection credentials are correct and the bind is possible</li>
|
||||||
|
* <li>At least one user exists</li>
|
||||||
|
* <li>The specified userClass has the property specified by userNameAttribute</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @throws AuthenticationException When authentication is not possible
|
||||||
|
*/
|
||||||
|
public function assertAuthenticationPossible()
|
||||||
|
{
|
||||||
|
$q = $this->conn->select()->from($this->userClass);
|
||||||
|
$result = $q->fetchRow();
|
||||||
|
if (!isset($result)) {
|
||||||
|
throw new AuthenticationException(
|
||||||
|
sprintf('No objects with objectClass="%s" in DN="%s" found.',
|
||||||
|
$this->userClass,
|
||||||
|
$this->conn->getDN()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($result->{$this->userNameAttribute})) {
|
||||||
|
throw new AuthenticationException(
|
||||||
|
sprintf('UserNameAttribute "%s" not existing in objectClass="%s"',
|
||||||
|
$this->userNameAttribute,
|
||||||
|
$this->userClass
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether the given user exists
|
* Test whether the given user exists
|
||||||
*
|
*
|
||||||
* @param User $user
|
* @param User $user
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
|
* @throws AuthenticationException
|
||||||
*/
|
*/
|
||||||
public function hasUser(User $user)
|
public function hasUser(User $user)
|
||||||
{
|
{
|
||||||
@ -93,18 +127,38 @@ class LdapUserBackend extends UserBackend
|
|||||||
*
|
*
|
||||||
* @param User $user
|
* @param User $user
|
||||||
* @param string $password
|
* @param string $password
|
||||||
|
* @param boolean $healthCheck Perform additional health checks to generate more useful
|
||||||
|
* exceptions in case of a configuration or backend error
|
||||||
*
|
*
|
||||||
* @return bool|null
|
* @return bool True when the authentication was successful, false when the username or password was invalid
|
||||||
* @throws AuthenticationException
|
* @throws AuthenticationException When an error occurred during authentication and authentication is not possible
|
||||||
*/
|
*/
|
||||||
public function authenticate(User $user, $password)
|
public function authenticate(User $user, $password, $healthCheck = true)
|
||||||
{
|
{
|
||||||
|
if ($healthCheck) {
|
||||||
|
try {
|
||||||
|
$this->assertAuthenticationPossible();
|
||||||
|
} catch (AuthenticationException $e) {
|
||||||
|
// Authentication not possible
|
||||||
|
throw new AuthenticationException(
|
||||||
|
sprintf(
|
||||||
|
'Authentication against backend "%s" not possible: ',
|
||||||
|
$this->getName()
|
||||||
|
),
|
||||||
|
0,
|
||||||
|
$e
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
return $this->conn->testCredentials(
|
$userDn = $this->conn->fetchDN($this->createQuery($user->getUsername()));
|
||||||
$this->conn->fetchDN($this->createQuery($user->getUsername())),
|
if (!$userDn) {
|
||||||
$password
|
// User does not exist
|
||||||
);
|
return false;
|
||||||
|
}
|
||||||
|
return $this->conn->testCredentials($userDn, $password);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
|
// Error during authentication of this specific user
|
||||||
throw new AuthenticationException(
|
throw new AuthenticationException(
|
||||||
sprintf(
|
sprintf(
|
||||||
'Failed to authenticate user "%s" against backend "%s". An exception was thrown:',
|
'Failed to authenticate user "%s" against backend "%s". An exception was thrown:',
|
||||||
@ -124,6 +178,7 @@ class LdapUserBackend extends UserBackend
|
|||||||
*/
|
*/
|
||||||
public function count()
|
public function count()
|
||||||
{
|
{
|
||||||
|
|
||||||
return $this->conn->count(
|
return $this->conn->count(
|
||||||
$this->conn->select()->from(
|
$this->conn->select()->from(
|
||||||
$this->userClass,
|
$this->userClass,
|
||||||
|
@ -85,7 +85,14 @@ abstract class UserBackend implements Countable
|
|||||||
}
|
}
|
||||||
return new $backendConfig->class($backendConfig);
|
return new $backendConfig->class($backendConfig);
|
||||||
}
|
}
|
||||||
if ($name === 'autologin') {
|
if (($backendType = $backendConfig->backend) === null) {
|
||||||
|
throw new ConfigurationError(
|
||||||
|
'Authentication configuration for backend "' . $name
|
||||||
|
. '" is missing the backend directive'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$backendType = strtolower($backendType);
|
||||||
|
if ($backendType === 'autologin') {
|
||||||
$backend = new AutoLoginBackend($backendConfig);
|
$backend = new AutoLoginBackend($backendConfig);
|
||||||
$backend->setName($name);
|
$backend->setName($name);
|
||||||
return $backend;
|
return $backend;
|
||||||
@ -96,12 +103,6 @@ abstract class UserBackend implements Countable
|
|||||||
. '" is missing the resource directive'
|
. '" is missing the resource directive'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (($backendType = $backendConfig->backend) === null) {
|
|
||||||
throw new ConfigurationError(
|
|
||||||
'Authentication configuration for backend "' . $name
|
|
||||||
. '" is missing the backend directive'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
$resourceConfig = ResourceFactory::getResourceConfig($backendConfig->resource);
|
$resourceConfig = ResourceFactory::getResourceConfig($backendConfig->resource);
|
||||||
} catch (ProgrammingError $e) {
|
} catch (ProgrammingError $e) {
|
||||||
@ -110,7 +111,7 @@ abstract class UserBackend implements Countable
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
$resource = ResourceFactory::createResource($resourceConfig);
|
$resource = ResourceFactory::createResource($resourceConfig);
|
||||||
switch (strtolower($backendType)) {
|
switch ($backendType) {
|
||||||
case 'db':
|
case 'db':
|
||||||
$backend = new DbUserBackend($resource);
|
$backend = new DbUserBackend($resource);
|
||||||
break;
|
break;
|
||||||
|
@ -1,21 +1,58 @@
|
|||||||
<?php
|
<?php
|
||||||
|
// {{{ICINGA_LICENSE_HEADER}}}
|
||||||
|
// {{{ICINGA_LICENSE_HEADER}}}
|
||||||
|
|
||||||
namespace Icinga\Cli;
|
namespace Icinga\Cli;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Params
|
||||||
|
*
|
||||||
|
* A class to ease commandline-option and -argument handling.
|
||||||
|
*/
|
||||||
class Params
|
class Params
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* The name and path of the executable
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
protected $program;
|
protected $program;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The arguments
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
protected $standalone = array();
|
protected $standalone = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The options
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
protected $params = array();
|
protected $params = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the given commandline and create a new Params object
|
||||||
|
*
|
||||||
|
* @param array $argv The commandline
|
||||||
|
*/
|
||||||
public function __construct($argv)
|
public function __construct($argv)
|
||||||
{
|
{
|
||||||
|
$noOptionFlag = false;
|
||||||
$this->program = array_shift($argv);
|
$this->program = array_shift($argv);
|
||||||
for ($i = 0; $i < count($argv); $i++) {
|
for ($i = 0; $i < count($argv); $i++) {
|
||||||
if (substr($argv[$i], 0, 2) === '--') {
|
if ($argv[$i] === '--') {
|
||||||
|
$noOptionFlag = true;
|
||||||
|
} elseif (!$noOptionFlag && substr($argv[$i], 0, 2) === '--') {
|
||||||
$key = substr($argv[$i], 2);
|
$key = substr($argv[$i], 2);
|
||||||
if (! isset($argv[$i + 1]) || substr($argv[$i + 1], 0, 2) === '--') {
|
if (! isset($argv[$i + 1]) || substr($argv[$i + 1], 0, 2) === '--') {
|
||||||
$this->params[$key] = true;
|
$this->params[$key] = true;
|
||||||
|
} elseif (array_key_exists($key, $this->params)) {
|
||||||
|
if (!is_array($this->params[$key])) {
|
||||||
|
$this->params[$key] = array($this->params[$key]);
|
||||||
|
}
|
||||||
|
$this->params[$key][] = $argv[++$i];
|
||||||
} else {
|
} else {
|
||||||
$this->params[$key] = $argv[++$i];
|
$this->params[$key] = $argv[++$i];
|
||||||
}
|
}
|
||||||
@ -25,6 +62,14 @@ class Params
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the value for an argument by position
|
||||||
|
*
|
||||||
|
* @param int $pos The position of the argument
|
||||||
|
* @param mixed $default The default value to return
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
public function getStandalone($pos = 0, $default = null)
|
public function getStandalone($pos = 0, $default = null)
|
||||||
{
|
{
|
||||||
if (isset($this->standalone[$pos])) {
|
if (isset($this->standalone[$pos])) {
|
||||||
@ -33,26 +78,64 @@ class Params
|
|||||||
return $default;
|
return $default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count and return the number of arguments and options
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
public function count()
|
public function count()
|
||||||
{
|
{
|
||||||
return count($this->standalone) + count($this->params);
|
return count($this->standalone) + count($this->params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the options
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public function getParams()
|
public function getParams()
|
||||||
{
|
{
|
||||||
return $this->params;
|
return $this->params;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the arguments
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getAllStandalone()
|
||||||
|
{
|
||||||
|
return $this->standalone;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see Params::get()
|
||||||
|
*/
|
||||||
public function __get($key)
|
public function __get($key)
|
||||||
{
|
{
|
||||||
return $this->get($key);
|
return $this->get($key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return whether the given option exists
|
||||||
|
*
|
||||||
|
* @param string $key The option name to check
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function has($key)
|
public function has($key)
|
||||||
{
|
{
|
||||||
return array_key_exists($key, $this->params);
|
return array_key_exists($key, $this->params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the value of the given option
|
||||||
|
*
|
||||||
|
* @param string $key The option name
|
||||||
|
* @param mixed $default The default value to return
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
public function get($key, $default = null)
|
public function get($key, $default = null)
|
||||||
{
|
{
|
||||||
if ($this->has($key)) {
|
if ($this->has($key)) {
|
||||||
@ -61,12 +144,27 @@ class Params
|
|||||||
return $default;
|
return $default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a value for the given option
|
||||||
|
*
|
||||||
|
* @param string $key The option name
|
||||||
|
* @param mixed $value The value to set
|
||||||
|
*
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
public function set($key, $value)
|
public function set($key, $value)
|
||||||
{
|
{
|
||||||
$this->params[$key] = $value;
|
$this->params[$key] = $value;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a single option or multiple options
|
||||||
|
*
|
||||||
|
* @param string|array $keys The option or options to remove
|
||||||
|
*
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
public function remove($keys = array())
|
public function remove($keys = array())
|
||||||
{
|
{
|
||||||
if (! is_array($keys)) {
|
if (! is_array($keys)) {
|
||||||
@ -80,12 +178,30 @@ class Params
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a copy of this object with the given options being removed
|
||||||
|
*
|
||||||
|
* @param string|array $keys The option or options to remove
|
||||||
|
*
|
||||||
|
* @return Params
|
||||||
|
*/
|
||||||
public function without($keys = array())
|
public function without($keys = array())
|
||||||
{
|
{
|
||||||
$params = clone($this);
|
$params = clone($this);
|
||||||
return $params->remove($keys);
|
return $params->remove($keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove and return the value of the given option
|
||||||
|
*
|
||||||
|
* Called multiple times for an option with multiple values returns
|
||||||
|
* them one by one in case the default is not an array.
|
||||||
|
*
|
||||||
|
* @param string $key The option name
|
||||||
|
* @param mixed $default The default value to return
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
public function shift($key = null, $default = null)
|
public function shift($key = null, $default = null)
|
||||||
{
|
{
|
||||||
if ($key === null) {
|
if ($key === null) {
|
||||||
@ -95,16 +211,37 @@ class Params
|
|||||||
return $default;
|
return $default;
|
||||||
}
|
}
|
||||||
$result = $this->get($key, $default);
|
$result = $this->get($key, $default);
|
||||||
$this->remove($key);
|
if (is_array($result) && !is_array($default)) {
|
||||||
|
$result = array_shift($result) || $default;
|
||||||
|
if ($result === $default) {
|
||||||
|
$this->remove($key);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->remove($key);
|
||||||
|
}
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Put the given value onto the argument stack
|
||||||
|
*
|
||||||
|
* @param mixed $key The argument
|
||||||
|
*
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
public function unshift($key)
|
public function unshift($key)
|
||||||
{
|
{
|
||||||
array_unshift($this->standalone, $key);
|
array_unshift($this->standalone, $key);
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the given commandline
|
||||||
|
*
|
||||||
|
* @param array $argv The commandline to parse
|
||||||
|
*
|
||||||
|
* @return Params
|
||||||
|
*/
|
||||||
public static function parse($argv = null)
|
public static function parse($argv = null)
|
||||||
{
|
{
|
||||||
if ($argv === null) {
|
if ($argv === null) {
|
||||||
|
114
library/Icinga/Protocol/Dns.php
Normal file
114
library/Icinga/Protocol/Dns.php
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
<?php
|
||||||
|
// {{{ICINGA_LICENSE_HEADER}}}
|
||||||
|
/**
|
||||||
|
* This file is part of Icinga Web 2.
|
||||||
|
*
|
||||||
|
* Icinga Web 2 - Head for multiple monitoring backends.
|
||||||
|
* Copyright (C) 2013 Icinga Development Team
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* @copyright 2013 Icinga Development Team <info@icinga.org>
|
||||||
|
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
|
||||||
|
* @author Icinga Development Team <info@icinga.org>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
// {{{ICINGA_LICENSE_HEADER}}}
|
||||||
|
|
||||||
|
namespace Icinga\Protocol;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Discover dns records using regular or reverse lookup
|
||||||
|
*/
|
||||||
|
class Dns {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all ldap records for the given domain
|
||||||
|
*
|
||||||
|
* @param String $query The domain to query
|
||||||
|
*
|
||||||
|
* @return array An array of entries
|
||||||
|
*/
|
||||||
|
public static function ldapRecords($query)
|
||||||
|
{
|
||||||
|
$ldaps_records = dns_get_record('_ldaps._tcp.' . $query);
|
||||||
|
$ldap_records = dns_get_record('_ldap._tcp.' . $query);
|
||||||
|
return array_merge($ldaps_records, $ldap_records);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all ldap records for the given domain
|
||||||
|
*
|
||||||
|
* @param String $query The domain to query
|
||||||
|
* @param int $type The type of DNS-entry to fetch, see http://www.php.net/manual/de/function.dns-get-record.php
|
||||||
|
* for available types
|
||||||
|
*
|
||||||
|
* @return array|Boolean An array of entries
|
||||||
|
*/
|
||||||
|
public static function records($query, $type = DNS_ANY)
|
||||||
|
{
|
||||||
|
return dns_get_record($query, $type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse lookup all hostname on the given ip address
|
||||||
|
*
|
||||||
|
* @param $ipAddress
|
||||||
|
* @param int $type
|
||||||
|
*
|
||||||
|
* @return array|Boolean
|
||||||
|
*/
|
||||||
|
public static function ptr($ipAddress, $type = DNS_ANY)
|
||||||
|
{
|
||||||
|
$host = gethostbyaddr($ipAddress);
|
||||||
|
if ($host === false || $host === $ipAddress) {
|
||||||
|
// malformed input or no host found
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return self::records($host, $type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the IPv4 address of the given hostname.
|
||||||
|
*
|
||||||
|
* @param $hostname The hostname to resolve
|
||||||
|
*
|
||||||
|
* @return String|Boolean The IPv4 address of the given hostname, or false when no entry exists.
|
||||||
|
*/
|
||||||
|
public static function ipv4($hostname)
|
||||||
|
{
|
||||||
|
$records = dns_get_record($hostname, DNS_A);
|
||||||
|
if ($records !== false && sizeof($records) > 0) {
|
||||||
|
return $records[0]['ip'];
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the IPv6 address of the given hostname.
|
||||||
|
*
|
||||||
|
* @param $hostname The hostname to resolve
|
||||||
|
*
|
||||||
|
* @return String|Boolean The IPv6 address of the given hostname, or false when no entry exists.
|
||||||
|
*/
|
||||||
|
public static function ipv6($hostname)
|
||||||
|
{
|
||||||
|
$records = dns_get_record($hostname, DNS_AAAA);
|
||||||
|
if ($records !== false && sizeof($records) > 0) {
|
||||||
|
return $records[0]['ip'];
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -63,6 +63,7 @@ class Connection
|
|||||||
protected $bind_pw;
|
protected $bind_pw;
|
||||||
protected $root_dn;
|
protected $root_dn;
|
||||||
protected $count;
|
protected $count;
|
||||||
|
|
||||||
protected $ldap_extension = array(
|
protected $ldap_extension = array(
|
||||||
'1.3.6.1.4.1.1466.20037' => 'STARTTLS',
|
'1.3.6.1.4.1.1466.20037' => 'STARTTLS',
|
||||||
// '1.3.6.1.4.1.4203.1.11.1' => '11.1', // PASSWORD_MODIFY
|
// '1.3.6.1.4.1.4203.1.11.1' => '11.1', // PASSWORD_MODIFY
|
||||||
@ -109,6 +110,8 @@ class Connection
|
|||||||
protected $supports_v3 = false;
|
protected $supports_v3 = false;
|
||||||
protected $supports_tls = false;
|
protected $supports_tls = false;
|
||||||
|
|
||||||
|
protected $capabilities;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
@ -204,16 +207,19 @@ class Connection
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch the distinguished name of the first result of the given query
|
||||||
|
*
|
||||||
|
* @param $query
|
||||||
|
* @param array $fields
|
||||||
|
*
|
||||||
|
* @return bool|String Returns the distinguished name, or false when the given query yields no results
|
||||||
|
*/
|
||||||
public function fetchDN($query, $fields = array())
|
public function fetchDN($query, $fields = array())
|
||||||
{
|
{
|
||||||
$rows = $this->fetchAll($query, $fields);
|
$rows = $this->fetchAll($query, $fields);
|
||||||
if (count($rows) !== 1) {
|
if (count($rows) !== 1) {
|
||||||
throw new \Exception(
|
return false;
|
||||||
sprintf(
|
|
||||||
'Cannot fetch single DN for %s',
|
|
||||||
$query
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return key($rows);
|
return key($rows);
|
||||||
}
|
}
|
||||||
@ -353,12 +359,6 @@ class Connection
|
|||||||
return $dir;
|
return $dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function discoverServerlistForDomain($domain)
|
|
||||||
{
|
|
||||||
$ldaps_records = dns_get_record('_ldaps._tcp.' . $domain, DNS_SRV);
|
|
||||||
$ldap_records = dns_get_record('_ldap._tcp.' . $domain, DNS_SRV);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function prepareNewConnection()
|
protected function prepareNewConnection()
|
||||||
{
|
{
|
||||||
$use_tls = false;
|
$use_tls = false;
|
||||||
@ -371,6 +371,7 @@ class Connection
|
|||||||
|
|
||||||
$ds = ldap_connect($this->hostname, $this->port);
|
$ds = ldap_connect($this->hostname, $this->port);
|
||||||
$cap = $this->discoverCapabilities($ds);
|
$cap = $this->discoverCapabilities($ds);
|
||||||
|
$this->capabilities = $cap;
|
||||||
|
|
||||||
if ($use_tls) {
|
if ($use_tls) {
|
||||||
if ($cap->starttls) {
|
if ($cap->starttls) {
|
||||||
@ -405,7 +406,6 @@ class Connection
|
|||||||
|
|
||||||
// TODO: remove this -> FORCING v3 for now
|
// TODO: remove this -> FORCING v3 for now
|
||||||
ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
|
ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
|
||||||
|
|
||||||
Logger::warning('No LDAPv3 support detected');
|
Logger::warning('No LDAPv3 support detected');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -435,6 +435,116 @@ class Connection
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function hasCapabilityStarTSL($cap)
|
||||||
|
{
|
||||||
|
$cap = $this->getExtensionCapabilities($cap);
|
||||||
|
return isset($cap['1.3.6.1.4.1.1466.20037']);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function hasCapabilityLdapV3($cap)
|
||||||
|
{
|
||||||
|
if ((is_string($cap->supportedLDAPVersion)
|
||||||
|
&& (int) $cap->supportedLDAPVersion === 3)
|
||||||
|
|| (is_array($cap->supportedLDAPVersion)
|
||||||
|
&& in_array(3, $cap->supportedLDAPVersion)
|
||||||
|
)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getExtensionCapabilities($cap)
|
||||||
|
{
|
||||||
|
$extensions = array();
|
||||||
|
if (isset($cap->supportedExtension)) {
|
||||||
|
foreach ($cap->supportedExtension as $oid) {
|
||||||
|
if (array_key_exists($oid, $this->ldap_extension)) {
|
||||||
|
if ($this->ldap_extension[$oid] === 'STARTTLS') {
|
||||||
|
$extensions['1.3.6.1.4.1.1466.20037'] = $this->ldap_extension['1.3.6.1.4.1.1466.20037'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $extensions;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getMsCapabilities($cap)
|
||||||
|
{
|
||||||
|
$ms = array();
|
||||||
|
foreach ($this->ms_capability as $name) {
|
||||||
|
$ms[$this->convName($name)] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($cap->supportedCapabilities)) {
|
||||||
|
foreach ($cap->supportedCapabilities as $oid) {
|
||||||
|
if (array_key_exists($oid, $this->ms_capability)) {
|
||||||
|
$ms[$this->convName($this->ms_capability[$oid])] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (object)$ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function convName($name)
|
||||||
|
{
|
||||||
|
$parts = explode('_', $name);
|
||||||
|
foreach ($parts as $i => $part) {
|
||||||
|
$parts[$i] = ucfirst(strtolower($part));
|
||||||
|
}
|
||||||
|
return implode('', $parts);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the capabilities of this ldap server
|
||||||
|
*
|
||||||
|
* @return stdClass An object, providing the flags 'ldapv3' and 'starttls' to indicate LdapV3 and StartTLS
|
||||||
|
* support and an additional property 'msCapabilities', containing all supported active directory capabilities.
|
||||||
|
*/
|
||||||
|
public function getCapabilities()
|
||||||
|
{
|
||||||
|
return $this->capabilities;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the default naming context of this ldap connection
|
||||||
|
*
|
||||||
|
* @return String|null the default naming context, or null when no contexts are available
|
||||||
|
*/
|
||||||
|
public function getDefaultNamingContext()
|
||||||
|
{
|
||||||
|
$cap = $this->capabilities;
|
||||||
|
if (isset($cap->defaultNamingContext)) {
|
||||||
|
return $cap->defaultNamingContext;
|
||||||
|
}
|
||||||
|
$namingContexts = $this->namingContexts($cap);
|
||||||
|
return empty($namingContexts) ? null : $namingContexts[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch the namingContexts for this Ldap-Connection
|
||||||
|
*
|
||||||
|
* @return array the available naming contexts
|
||||||
|
*/
|
||||||
|
public function namingContexts()
|
||||||
|
{
|
||||||
|
$cap = $this->capabilities;
|
||||||
|
if (!isset($cap->namingContexts)) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
if (!is_array($cap->namingContexts)) {
|
||||||
|
return array($cap->namingContexts);
|
||||||
|
}
|
||||||
|
return $cap->namingContexts;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Discover the capabilities of the given ldap-server
|
||||||
|
*
|
||||||
|
* @param $ds The link identifier of the current ldap connection
|
||||||
|
*
|
||||||
|
* @return bool|object The capabilities or false if the server has none
|
||||||
|
* @throws Exception When the capability query fails
|
||||||
|
*/
|
||||||
protected function discoverCapabilities($ds)
|
protected function discoverCapabilities($ds)
|
||||||
{
|
{
|
||||||
$query = $this->select()->from(
|
$query = $this->select()->from(
|
||||||
@ -477,69 +587,49 @@ class Connection
|
|||||||
$cap = (object) array(
|
$cap = (object) array(
|
||||||
'ldapv3' => false,
|
'ldapv3' => false,
|
||||||
'starttls' => false,
|
'starttls' => false,
|
||||||
|
'msCapabilities' => array()
|
||||||
);
|
);
|
||||||
|
|
||||||
if ($entry === false) {
|
if ($entry === false) {
|
||||||
// TODO: Is it OK to have no capabilities?
|
// TODO: Is it OK to have no capabilities?
|
||||||
return $cap;
|
return false;
|
||||||
}
|
}
|
||||||
$ldapAttributes = ldap_get_attributes($ds, $entry);
|
$ldapAttributes = ldap_get_attributes($ds, $entry);
|
||||||
$result = $this->cleanupAttributes(
|
$result = $this->cleanupAttributes($ldapAttributes);
|
||||||
$ldapAttributes
|
$cap->ldapv3 = $this->hasCapabilityLdapV3($result);
|
||||||
);
|
$cap->starttls = $this->hasCapabilityStarTSL($result);
|
||||||
|
$cap->msCapabilities = $this->getMsCapabilities($result);
|
||||||
|
$cap->namingContexts = $result->namingContexts;
|
||||||
/*
|
/*
|
||||||
if (isset($result->dnsHostName)) {
|
if (isset($result->dnsHostName)) {
|
||||||
ldap_set_option($ds, LDAP_OPT_HOST_NAME, $result->dnsHostName);
|
ldap_set_option($ds, LDAP_OPT_HOST_NAME, $result->dnsHostName);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if ((is_string($result->supportedLDAPVersion)
|
|
||||||
&& (int) $result->supportedLDAPVersion === 3)
|
|
||||||
|| (is_array($result->supportedLDAPVersion)
|
|
||||||
&& in_array(3, $result->supportedLDAPVersion)
|
|
||||||
)) {
|
|
||||||
$cap->ldapv3 = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($result->supportedCapabilities)) {
|
|
||||||
foreach ($result->supportedCapabilities as $oid) {
|
|
||||||
if (array_key_exists($oid, $this->ms_capability)) {
|
|
||||||
// echo $this->ms_capability[$oid] . "\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (isset($result->supportedExtension)) {
|
|
||||||
foreach ($result->supportedExtension as $oid) {
|
|
||||||
if (array_key_exists($oid, $this->ldap_extension)) {
|
|
||||||
if ($this->ldap_extension[$oid] === 'STARTTLS') {
|
|
||||||
$cap->starttls = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $cap;
|
return $cap;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function connect()
|
public function connect($anonymous = false)
|
||||||
{
|
{
|
||||||
if ($this->ds !== null) {
|
if ($this->ds !== null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$this->ds = $this->prepareNewConnection();
|
$this->ds = $this->prepareNewConnection();
|
||||||
|
|
||||||
$r = @ldap_bind($this->ds, $this->bind_dn, $this->bind_pw);
|
if (!$anonymous) {
|
||||||
|
$r = @ldap_bind($this->ds, $this->bind_dn, $this->bind_pw);
|
||||||
if (! $r) {
|
if (! $r) {
|
||||||
throw new \Exception(
|
throw new \Exception(
|
||||||
sprintf(
|
sprintf(
|
||||||
'LDAP connection to %s:%s (%s / %s) failed: %s',
|
'LDAP connection to %s:%s (%s / %s) failed: %s',
|
||||||
$this->hostname,
|
$this->hostname,
|
||||||
$this->port,
|
$this->port,
|
||||||
$this->bind_dn,
|
$this->bind_dn,
|
||||||
'***' /* $this->bind_pw */,
|
'***' /* $this->bind_pw */,
|
||||||
ldap_error($this->ds)
|
ldap_error($this->ds)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,15 +62,9 @@ class Translator
|
|||||||
* @param string $domain The primary domain to use
|
* @param string $domain The primary domain to use
|
||||||
*
|
*
|
||||||
* @return string The translated string
|
* @return string The translated string
|
||||||
*
|
|
||||||
* @throws Exception In case the given domain is unknown
|
|
||||||
*/
|
*/
|
||||||
public static function translate($text, $domain)
|
public static function translate($text, $domain)
|
||||||
{
|
{
|
||||||
if ($domain !== self::DEFAULT_DOMAIN && !array_key_exists($domain, self::$knownDomains)) {
|
|
||||||
throw new Exception("Cannot translate string '$text' with unknown domain '$domain'");
|
|
||||||
}
|
|
||||||
|
|
||||||
$res = dgettext($domain, $text);
|
$res = dgettext($domain, $text);
|
||||||
if ($res === $text && $domain !== self::DEFAULT_DOMAIN) {
|
if ($res === $text && $domain !== self::DEFAULT_DOMAIN) {
|
||||||
return dgettext(self::DEFAULT_DOMAIN, $text);
|
return dgettext(self::DEFAULT_DOMAIN, $text);
|
||||||
|
@ -301,7 +301,7 @@ class ActionController extends Zend_Controller_Action
|
|||||||
public function translate($text)
|
public function translate($text)
|
||||||
{
|
{
|
||||||
$module = $this->getRequest()->getModuleName();
|
$module = $this->getRequest()->getModuleName();
|
||||||
$domain = $module === 'default' ? 'icinga' : $module;
|
$domain = $module === 'default' ? Translator::DEFAULT_DOMAIN : $module;
|
||||||
return Translator::translate($text, $domain);
|
return Translator::translate($text, $domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,11 +22,15 @@ class JavaScript
|
|||||||
);
|
);
|
||||||
|
|
||||||
protected static $vendorFiles = array(
|
protected static $vendorFiles = array(
|
||||||
// 'js/vendor/jquery-1.11.0',
|
|
||||||
'js/vendor/jquery-2.1.0',
|
'js/vendor/jquery-2.1.0',
|
||||||
'js/vendor/jquery.sparkline'
|
'js/vendor/jquery.sparkline'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
protected static $ie8VendorFiles = array(
|
||||||
|
'js/vendor/jquery-1.11.0',
|
||||||
|
'js/vendor/jquery.sparkline'
|
||||||
|
);
|
||||||
|
|
||||||
public static function listModuleFiles()
|
public static function listModuleFiles()
|
||||||
{
|
{
|
||||||
$list = array();
|
$list = array();
|
||||||
@ -43,6 +47,12 @@ class JavaScript
|
|||||||
return self::send(true);
|
return self::send(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function sendForIe8()
|
||||||
|
{
|
||||||
|
self::$vendorFiles = self::$ie8VendorFiles;
|
||||||
|
return self::send();
|
||||||
|
}
|
||||||
|
|
||||||
public static function send($minified = false)
|
public static function send($minified = false)
|
||||||
{
|
{
|
||||||
header('Content-Type: application/javascript');
|
header('Content-Type: application/javascript');
|
||||||
|
@ -50,10 +50,14 @@ class InlinePie extends AbstractWidget
|
|||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
private $template =<<<'EOD'
|
private $template =<<<'EOD'
|
||||||
|
<span class="sparkline" sparkTitle="{title}" sparkWidth="{width}" sparkHeight="{height}" style="{style}"
|
||||||
|
sparkSliceColors="[{colors}]" values="{data}" sparkType="pie"></span>
|
||||||
|
<noscript>
|
||||||
<img class="inlinepie"
|
<img class="inlinepie"
|
||||||
title="{title}" src="{url}" style="width: {width}px; height: {height}px; {style}"
|
title="{title}" src="{url}" style="width: {width}px; height: {height}px; {style}"
|
||||||
data-icinga-colors="{colors}" data-icinga-values="{data}"
|
data-icinga-colors="{colors}" data-icinga-values="{data}"
|
||||||
/>
|
/>
|
||||||
|
</noscript>
|
||||||
EOD;
|
EOD;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
160
modules/test/application/clicommands/PhpCommand.php
Normal file
160
modules/test/application/clicommands/PhpCommand.php
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
<?php
|
||||||
|
// {{{ICINGA_LICENSE_HEADER}}}
|
||||||
|
// {{{ICINGA_LICENSE_HEADER}}}
|
||||||
|
|
||||||
|
namespace Icinga\Module\Test\Clicommands;
|
||||||
|
|
||||||
|
use Icinga\Cli\Command;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHP unit- & style-tests
|
||||||
|
*/
|
||||||
|
class PhpCommand extends Command
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Default arguments and options for PHP_CodeSniffer
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $phpcsDefaultParams = array(
|
||||||
|
'-p',
|
||||||
|
'--standard=PSR2',
|
||||||
|
'--extensions=php',
|
||||||
|
'--encoding=utf-8'
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run all unit-test suites
|
||||||
|
*
|
||||||
|
* This command runs the unit- and regression-tests of icingaweb and installed modules.
|
||||||
|
*
|
||||||
|
* USAGE
|
||||||
|
*
|
||||||
|
* icingacli test php unit [options]
|
||||||
|
*
|
||||||
|
* OPTIONS
|
||||||
|
*
|
||||||
|
* --verbose Be more verbose.
|
||||||
|
* --build Enable reporting.
|
||||||
|
* --include Pattern to use for including files/test cases.
|
||||||
|
*
|
||||||
|
* EXAMPLES
|
||||||
|
*
|
||||||
|
* icingacli test php unit --verbose
|
||||||
|
* icingacli test php unit --build
|
||||||
|
* icingacli test php unit --include *SpecialTest
|
||||||
|
*/
|
||||||
|
public function unitAction()
|
||||||
|
{
|
||||||
|
$build = $this->params->shift('build');
|
||||||
|
$include = $this->params->shift('include');
|
||||||
|
|
||||||
|
$phpUnit = exec('which phpunit');
|
||||||
|
if (!file_exists($phpUnit)) {
|
||||||
|
$this->fail('PHPUnit not found. Please install PHPUnit to be able to run the unit-test suites.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$options = array();
|
||||||
|
if ($this->isVerbose) {
|
||||||
|
$options[] = '--verbose';
|
||||||
|
}
|
||||||
|
if ($build) {
|
||||||
|
$reportPath = $this->setupAndReturnReportDirectory();
|
||||||
|
echo $reportPath;
|
||||||
|
$options[] = '--log-junit';
|
||||||
|
$options[] = $reportPath . '/phpunit_results.xml';
|
||||||
|
$options[] = '--coverage-html';
|
||||||
|
$options[] = $reportPath . '/php_html_coverage';
|
||||||
|
}
|
||||||
|
if ($include !== null) {
|
||||||
|
$options[] = '--filter';
|
||||||
|
$options[] = $include;
|
||||||
|
}
|
||||||
|
|
||||||
|
chdir(realpath(__DIR__ . '/../..'));
|
||||||
|
passthru($phpUnit . ' ' . join(' ', array_merge($options, $this->params->getAllStandalone())));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run code-style checks
|
||||||
|
*
|
||||||
|
* This command checks whether icingaweb and installed modules match the PSR-2 coding standard.
|
||||||
|
*
|
||||||
|
* USAGE
|
||||||
|
*
|
||||||
|
* icingacli test php style [options]
|
||||||
|
*
|
||||||
|
* OPTIONS
|
||||||
|
*
|
||||||
|
* --verbose Be more verbose.
|
||||||
|
* --build Enable reporting.
|
||||||
|
* --include Include only specific files. (Can be supplied multiple times.)
|
||||||
|
* --exclude Pattern to use for excluding files. (Can be supplied multiple times.)
|
||||||
|
*
|
||||||
|
* EXAMPLES
|
||||||
|
*
|
||||||
|
* icingacli test php style --verbose
|
||||||
|
* icingacli test php style --build
|
||||||
|
* icingacli test php style --include path/to/your/file
|
||||||
|
* icingacli test php style --exclude *someFile* --exclude someOtherFile*
|
||||||
|
*/
|
||||||
|
public function styleAction()
|
||||||
|
{
|
||||||
|
$build = $this->params->shift('build');
|
||||||
|
$include = (array) $this->params->shift('include', array());
|
||||||
|
$exclude = (array) $this->params->shift('exclude', array());
|
||||||
|
|
||||||
|
$phpcs = exec('which phpcs');
|
||||||
|
if (!file_exists($phpcs)) {
|
||||||
|
$this->fail(
|
||||||
|
'PHP_CodeSniffer not found. Please install PHP_CodeSniffer to be able to run code style tests.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$options = array();
|
||||||
|
if ($this->isVerbose) {
|
||||||
|
$options[] = '-v';
|
||||||
|
}
|
||||||
|
if ($build) {
|
||||||
|
$options[] = '--report-checkstyle=' . $this->setupAndReturnReportDirectory();
|
||||||
|
}
|
||||||
|
if (!empty($exclude)) {
|
||||||
|
$options[] = '--ignore=' . join(',', $exclude);
|
||||||
|
}
|
||||||
|
$arguments = array_filter(array_map(function ($p) { return realpath($p); }, $include));
|
||||||
|
if (empty($arguments)) {
|
||||||
|
$arguments = array(
|
||||||
|
realpath(__DIR__ . '/../../../../application'),
|
||||||
|
realpath(__DIR__ . '/../../../../library/Icinga')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
chdir(realpath(__DIR__ . '/../..'));
|
||||||
|
passthru(
|
||||||
|
$phpcs . ' ' . join(
|
||||||
|
' ',
|
||||||
|
array_merge(
|
||||||
|
$options,
|
||||||
|
$this->phpcsDefaultParams,
|
||||||
|
$arguments,
|
||||||
|
$this->params->getAllStandalone()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup the directory where to put report files and return its path
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function setupAndReturnReportDirectory()
|
||||||
|
{
|
||||||
|
$path = realpath(__DIR__ . '/../../../..') . '/build/log';
|
||||||
|
if (!file_exists($path) && !@mkdir($path, 0755, true)) {
|
||||||
|
$this->fail("Could not create directory: $path");
|
||||||
|
}
|
||||||
|
|
||||||
|
return $path;
|
||||||
|
}
|
||||||
|
}
|
@ -1,25 +1,24 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<phpunit bootstrap="bootstrap.php">
|
<phpunit bootstrap="../../test/php/bootstrap.php">
|
||||||
<testsuites>
|
<testsuites>
|
||||||
<!--
|
<!--
|
||||||
Unit testing
|
Unit testing
|
||||||
-->
|
-->
|
||||||
<testsuite name="unit">
|
<testsuite name="unit">
|
||||||
<directory>application/</directory>
|
<directory>../../test/php/application/</directory>
|
||||||
<directory>bin/</directory>
|
<directory>../../test/php/library/</directory>
|
||||||
<directory>library/</directory>
|
|
||||||
|
|
||||||
<!-- Module tests are independent from core tests -->
|
<!-- Module tests are independent from core tests -->
|
||||||
<directory>../../modules/*/test/php</directory>
|
<directory>../*/test/php</directory>
|
||||||
<exclude>../../modules/*/test/php/regression</exclude>
|
<exclude>../*/test/php/regression</exclude>
|
||||||
</testsuite>
|
</testsuite>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Regression testing
|
Regression testing
|
||||||
-->
|
-->
|
||||||
<testsuite name="regression">
|
<testsuite name="regression">
|
||||||
<directory>regression/</directory>
|
<directory>../../test/php/regression/</directory>
|
||||||
<directory>../../modules/*/test/regression</directory>
|
<directory>../*/test/php/regression</directory>
|
||||||
</testsuite>
|
</testsuite>
|
||||||
</testsuites>
|
</testsuites>
|
||||||
<filter>
|
<filter>
|
@ -127,15 +127,12 @@ tr.state.handled td.state, tr.state.ok td.state, tr.state.up td.state, tr.state.
|
|||||||
color: black;
|
color: black;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
tr[href].active {
|
tr[href].active {
|
||||||
background-color: #ddd;
|
background-color: #ddd;
|
||||||
color: black;
|
color: black;
|
||||||
}
|
}
|
||||||
|
|
||||||
tr.state[href]:hover, tr.state[href].active td.state {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
tr.state.ok td.state, tr.state.up td.state {
|
tr.state.ok td.state, tr.state.up td.state {
|
||||||
border-left-color: @colorOk;
|
border-left-color: @colorOk;
|
||||||
}
|
}
|
||||||
@ -195,12 +192,12 @@ tr.state.handled td.state {
|
|||||||
|
|
||||||
/* HOVER colors */
|
/* HOVER colors */
|
||||||
|
|
||||||
|
tr[href]:hover, tr.state[href]:hover td.state {
|
||||||
tr.state[href]:hover, tr.state[href]:hover td.state {
|
|
||||||
color: white;
|
color: white;
|
||||||
|
background-color: #555;
|
||||||
}
|
}
|
||||||
|
|
||||||
tr.state.ok:hover {
|
tr.state.ok[href]:hover, tr.state.up[href]:hover {
|
||||||
background-color: @colorOk;
|
background-color: @colorOk;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -248,6 +245,11 @@ tr.state.unreachable[href]:hover {
|
|||||||
tr.state.unreachable.handled[href]:hover {
|
tr.state.unreachable.handled[href]:hover {
|
||||||
background-color: @colorUnreachableHandled;
|
background-color: @colorUnreachableHandled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tr.state[href]:hover td.state {
|
||||||
|
background-color: inherit !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* END of HOVER colors */
|
/* END of HOVER colors */
|
||||||
|
|
||||||
/* END of special tables and states */
|
/* END of special tables and states */
|
||||||
|
@ -2,6 +2,12 @@ ul.pagination {
|
|||||||
font-size: 0.68em;
|
font-size: 0.68em;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
display: inline;
|
display: inline;
|
||||||
|
|
||||||
|
-webkit-touch-callout: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#layout.twocols u.pagination {
|
#layout.twocols u.pagination {
|
||||||
|
@ -69,10 +69,6 @@
|
|||||||
|
|
||||||
$('input.autofocus', el).focus();
|
$('input.autofocus', el).focus();
|
||||||
|
|
||||||
$('img.inlinepie', el).each(function() {
|
|
||||||
icinga.ui.initializeSparklines($(this));
|
|
||||||
});
|
|
||||||
|
|
||||||
// replace all sparklines
|
// replace all sparklines
|
||||||
$('span.sparkline', el).sparkline('html', { enableTagOptions: true });
|
$('span.sparkline', el).sparkline('html', { enableTagOptions: true });
|
||||||
|
|
||||||
|
@ -269,7 +269,7 @@
|
|||||||
if (this.processRedirectHeader(req)) return;
|
if (this.processRedirectHeader(req)) return;
|
||||||
|
|
||||||
// div helps getting an XML tree
|
// div helps getting an XML tree
|
||||||
var $resp = $('<div>' + icinga.ui.removeImageSourceFromSparklines(req.responseText) + '</div>');
|
var $resp = $('<div>' + req.responseText + '</div>');
|
||||||
var active = false;
|
var active = false;
|
||||||
var rendered = false;
|
var rendered = false;
|
||||||
var classes;
|
var classes;
|
||||||
@ -409,11 +409,6 @@
|
|||||||
|
|
||||||
this.icinga.ui.initializeTriStates($resp);
|
this.icinga.ui.initializeTriStates($resp);
|
||||||
|
|
||||||
// Replace images with sparklines.
|
|
||||||
$resp.find('img.inlinepie').each(function(){
|
|
||||||
self.icinga.ui.initializeSparklines($(this));
|
|
||||||
});
|
|
||||||
|
|
||||||
/* Should we try to fiddle with responses containing full HTML? */
|
/* Should we try to fiddle with responses containing full HTML? */
|
||||||
/*
|
/*
|
||||||
if ($('body', $resp).length) {
|
if ($('body', $resp).length) {
|
||||||
@ -617,7 +612,7 @@
|
|||||||
$container.scrollTop(scrollPos);
|
$container.scrollTop(scrollPos);
|
||||||
}
|
}
|
||||||
if (origFocus) {
|
if (origFocus) {
|
||||||
origFocus.focus();
|
$(origFocus).focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: this.icinga.events.refreshContainer(container);
|
// TODO: this.icinga.events.refreshContainer(container);
|
||||||
|
@ -631,48 +631,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* Search and replace all inlinepies with html for sparklines.
|
|
||||||
*
|
|
||||||
* @param parent
|
|
||||||
*/
|
|
||||||
initializeSparklines: function($container) {
|
|
||||||
|
|
||||||
// replace all remaining images with sparklines
|
|
||||||
var title = $container.attr('title'),
|
|
||||||
values = $container.data('icinga-values'),
|
|
||||||
colors = $container.data('icinga-colors'),
|
|
||||||
width = $container.css('width'),
|
|
||||||
height = $container.css('height');
|
|
||||||
if (!values) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$container.replaceWith(
|
|
||||||
'<span sparkTitle="' + title +
|
|
||||||
'" sparkWidth="' + width +
|
|
||||||
'" sparkHeight="' + height +
|
|
||||||
'" sparkType="pie" sparkSliceColors="[' +
|
|
||||||
colors + ']" values="' +
|
|
||||||
values + '" class="sparkline"></span>'
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find all svg charts and removes src attributes for sparklines
|
|
||||||
*
|
|
||||||
* @param {string} text
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
removeImageSourceFromSparklines: function(text) {
|
|
||||||
var match, sourceMatch;
|
|
||||||
var re = new RegExp(/(src=".+chart.php[^"]+")/g);
|
|
||||||
var reSource = new RegExp(/src="([^"]+)"/);
|
|
||||||
while ((match = re.exec(text))) {
|
|
||||||
text = text.replace(match[0], '');
|
|
||||||
}
|
|
||||||
return text;
|
|
||||||
},
|
|
||||||
|
|
||||||
initializeControls: function (parent) {
|
initializeControls: function (parent) {
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
@ -1,127 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import subprocess
|
|
||||||
from pipes import quote
|
|
||||||
from optparse import OptionParser, BadOptionError, AmbiguousOptionError
|
|
||||||
|
|
||||||
|
|
||||||
APPLICATION = 'phpcs'
|
|
||||||
DEFAULT_ARGS = ['-p', '--standard=PSR2', '--extensions=php',
|
|
||||||
'--encoding=utf-8']
|
|
||||||
|
|
||||||
VAGRANT_SCRIPT = '/vagrant/test/php/checkswag'
|
|
||||||
REPORT_DIRECTORY = '../../build/log'
|
|
||||||
|
|
||||||
|
|
||||||
class PassThroughOptionParser(OptionParser):
|
|
||||||
"""
|
|
||||||
An unknown option pass-through implementation of OptionParser.
|
|
||||||
|
|
||||||
When unknown arguments are encountered, bundle with largs and try again,
|
|
||||||
until rargs is depleted.
|
|
||||||
|
|
||||||
sys.exit(status) will still be called if a known argument is passed
|
|
||||||
incorrectly (e.g. missing arguments or bad argument types, etc.)
|
|
||||||
|
|
||||||
Borrowed from: http://stackoverflow.com/a/9307174
|
|
||||||
"""
|
|
||||||
def _process_args(self, largs, rargs, values):
|
|
||||||
while rargs:
|
|
||||||
try:
|
|
||||||
OptionParser._process_args(self, largs, rargs, values)
|
|
||||||
except (BadOptionError, AmbiguousOptionError), error:
|
|
||||||
largs.append(error.opt_str)
|
|
||||||
|
|
||||||
|
|
||||||
def execute_command(command, return_output=False, shell=False):
|
|
||||||
prog = subprocess.Popen(command, shell=shell,
|
|
||||||
stdout=subprocess.PIPE
|
|
||||||
if return_output
|
|
||||||
else None)
|
|
||||||
return prog.wait() if not return_output else \
|
|
||||||
prog.communicate()[0]
|
|
||||||
|
|
||||||
|
|
||||||
def get_report_directory():
|
|
||||||
path = os.path.abspath(REPORT_DIRECTORY)
|
|
||||||
|
|
||||||
try:
|
|
||||||
os.makedirs(REPORT_DIRECTORY)
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
return path
|
|
||||||
|
|
||||||
|
|
||||||
def get_script_directory():
|
|
||||||
return os.path.dirname(os.path.abspath(sys.argv[0]))
|
|
||||||
|
|
||||||
|
|
||||||
def parse_commandline():
|
|
||||||
parser = PassThroughOptionParser(usage='%prog [options] [additional arguments'
|
|
||||||
' for {0}]'.format(APPLICATION))
|
|
||||||
parser.add_option('-b', '--build', action='store_true',
|
|
||||||
help='Enable reporting.')
|
|
||||||
parser.add_option('-v', '--verbose', action='store_true',
|
|
||||||
help='Be more verbose.')
|
|
||||||
parser.add_option('-i', '--include', metavar='PATTERN', action='append',
|
|
||||||
help='Include only specific files/test cases.'
|
|
||||||
' (Can be supplied multiple times.)')
|
|
||||||
parser.add_option('-e', '--exclude', metavar='PATTERN', action='append',
|
|
||||||
help='Exclude specific files/test cases. '
|
|
||||||
'(Can be supplied multiple times.)')
|
|
||||||
parser.add_option('-V', '--vagrant', action='store_true',
|
|
||||||
help='Run in vagrant VM')
|
|
||||||
return parser.parse_args()
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
options, arguments = parse_commandline()
|
|
||||||
|
|
||||||
if options.vagrant and os.environ['USER'] != 'vagrant':
|
|
||||||
# Check if vagrant is installed
|
|
||||||
vagrant_path = execute_command('which vagrant', True, True).strip()
|
|
||||||
if not vagrant_path:
|
|
||||||
print 'ERROR: vagrant not found!'
|
|
||||||
return 2
|
|
||||||
|
|
||||||
# Call the script in the Vagrant VM with the same parameters
|
|
||||||
commandline = ' '.join(quote(p) for p in sys.argv[1:])
|
|
||||||
return execute_command('vagrant ssh -c "{0} {1}"'
|
|
||||||
''.format(VAGRANT_SCRIPT, commandline),
|
|
||||||
shell=True)
|
|
||||||
else:
|
|
||||||
# Environment preparation and verification
|
|
||||||
os.chdir(get_script_directory())
|
|
||||||
application_path = execute_command('which {0}'.format(APPLICATION),
|
|
||||||
True, True).strip()
|
|
||||||
if not application_path:
|
|
||||||
print 'ERROR: {0} not found!'.format(APPLICATION)
|
|
||||||
return 2
|
|
||||||
|
|
||||||
# Commandline preparation
|
|
||||||
command_options = []
|
|
||||||
if options.verbose:
|
|
||||||
command_options.append('-v')
|
|
||||||
if options.build:
|
|
||||||
result_path = os.path.join(get_report_directory(),
|
|
||||||
'phpcs_results.xml')
|
|
||||||
command_options.append('--report-checkstyle=' + result_path)
|
|
||||||
if options.exclude:
|
|
||||||
command_options.append('--ignore=' + ','.join(options.exclude))
|
|
||||||
if options.include:
|
|
||||||
arguments.extend(options.include)
|
|
||||||
else:
|
|
||||||
arguments.extend(['../../application', '../../bin',
|
|
||||||
'../../library/Icinga'])
|
|
||||||
|
|
||||||
# Application invocation..
|
|
||||||
execute_command([application_path] + DEFAULT_ARGS +
|
|
||||||
command_options + arguments)
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
sys.exit(main())
|
|
23
test/php/regression/Bug6432Test.php
Normal file
23
test/php/regression/Bug6432Test.php
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
// {{{ICINGA_LICENSE_HEADER}}}
|
||||||
|
// {{{ICINGA_LICENSE_HEADER}}}
|
||||||
|
|
||||||
|
namespace Tests\Icinga\Regression;
|
||||||
|
|
||||||
|
use Icinga\Test\BaseTestCase;
|
||||||
|
use Icinga\Util\Translator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Regression-Test for bug #6432
|
||||||
|
*
|
||||||
|
* Translating strings must not throw an exception even if the given domain is not valid.
|
||||||
|
*
|
||||||
|
* @see https://dev.icinga.org/issues/6432
|
||||||
|
*/
|
||||||
|
class Bug6432Test extends BaseTestCase
|
||||||
|
{
|
||||||
|
public function testWhetherTranslateReturnsTheInputStringInCaseTheGivenDomainIsNotValid()
|
||||||
|
{
|
||||||
|
$this->assertEquals('test', Translator::translate('test', 'invalid_domain'));
|
||||||
|
}
|
||||||
|
}
|
@ -1,124 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import subprocess
|
|
||||||
from pipes import quote
|
|
||||||
from fnmatch import fnmatch
|
|
||||||
from optparse import OptionParser, BadOptionError, AmbiguousOptionError
|
|
||||||
|
|
||||||
|
|
||||||
APPLICATION = 'phpunit'
|
|
||||||
DEFAULT_ARGS = []
|
|
||||||
|
|
||||||
VAGRANT_SCRIPT = '/vagrant/test/php/runtests'
|
|
||||||
REPORT_DIRECTORY = '../../build/log'
|
|
||||||
|
|
||||||
|
|
||||||
class PassThroughOptionParser(OptionParser):
|
|
||||||
"""
|
|
||||||
An unknown option pass-through implementation of OptionParser.
|
|
||||||
|
|
||||||
When unknown arguments are encountered, bundle with largs and try again,
|
|
||||||
until rargs is depleted.
|
|
||||||
|
|
||||||
sys.exit(status) will still be called if a known argument is passed
|
|
||||||
incorrectly (e.g. missing arguments or bad argument types, etc.)
|
|
||||||
|
|
||||||
Borrowed from: http://stackoverflow.com/a/9307174
|
|
||||||
"""
|
|
||||||
def _process_args(self, largs, rargs, values):
|
|
||||||
while rargs:
|
|
||||||
try:
|
|
||||||
OptionParser._process_args(self, largs, rargs, values)
|
|
||||||
except (BadOptionError, AmbiguousOptionError), error:
|
|
||||||
largs.append(error.opt_str)
|
|
||||||
|
|
||||||
|
|
||||||
def execute_command(command, return_output=False, shell=False):
|
|
||||||
prog = subprocess.Popen(command, shell=shell,
|
|
||||||
stdout=subprocess.PIPE
|
|
||||||
if return_output
|
|
||||||
else None)
|
|
||||||
return prog.wait() if not return_output else \
|
|
||||||
prog.communicate()[0]
|
|
||||||
|
|
||||||
|
|
||||||
def get_report_directory():
|
|
||||||
path = os.path.abspath(REPORT_DIRECTORY)
|
|
||||||
|
|
||||||
try:
|
|
||||||
os.makedirs(REPORT_DIRECTORY)
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
return path
|
|
||||||
|
|
||||||
|
|
||||||
def get_script_directory():
|
|
||||||
return os.path.dirname(os.path.abspath(sys.argv[0]))
|
|
||||||
|
|
||||||
|
|
||||||
def parse_commandline():
|
|
||||||
parser = PassThroughOptionParser(usage='%prog [options] [additional arguments'
|
|
||||||
' for {0}]'.format(APPLICATION))
|
|
||||||
parser.add_option('-b', '--build', action='store_true',
|
|
||||||
help='Enable reporting.')
|
|
||||||
parser.add_option('-v', '--verbose', action='store_true',
|
|
||||||
help='Be more verbose.')
|
|
||||||
parser.add_option('-i', '--include', metavar='PATTERN',
|
|
||||||
help='Include only specific files/test cases.')
|
|
||||||
parser.add_option('-V', '--vagrant', action='store_true',
|
|
||||||
help='Run in vagrant VM')
|
|
||||||
return parser.parse_args()
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
options, arguments = parse_commandline()
|
|
||||||
|
|
||||||
if options.vagrant and os.environ['USER'] != 'vagrant':
|
|
||||||
# Check if vagrant is installed
|
|
||||||
vagrant_path = execute_command('which vagrant', True, True).strip()
|
|
||||||
if not vagrant_path:
|
|
||||||
print 'ERROR: vagrant not found!'
|
|
||||||
return 2
|
|
||||||
|
|
||||||
# Call the script in the Vagrant VM with the same parameters
|
|
||||||
commandline = ' '.join(quote(p) for p in sys.argv[1:])
|
|
||||||
return execute_command('vagrant ssh -c "{0} {1}"'
|
|
||||||
''.format(VAGRANT_SCRIPT, commandline),
|
|
||||||
shell=True)
|
|
||||||
else:
|
|
||||||
# Environment preparation and verification
|
|
||||||
os.chdir(get_script_directory())
|
|
||||||
application_path = execute_command('which {0}'.format(APPLICATION),
|
|
||||||
True, True).strip()
|
|
||||||
if not application_path:
|
|
||||||
print 'ERROR: {0} not found!'.format(APPLICATION)
|
|
||||||
return 2
|
|
||||||
if not os.path.isfile('./bin/extcmd_test'):
|
|
||||||
execute_command('make', shell=True)
|
|
||||||
|
|
||||||
# Commandline preparation
|
|
||||||
command_options = []
|
|
||||||
if options.verbose:
|
|
||||||
command_options.append('--verbose')
|
|
||||||
if options.build:
|
|
||||||
report_directory = get_report_directory()
|
|
||||||
command_options.append('--log-junit')
|
|
||||||
command_options.append(os.path.join(report_directory,
|
|
||||||
'phpunit_results.xml'))
|
|
||||||
command_options.append('--coverage-html')
|
|
||||||
command_options.append(os.path.join(report_directory,
|
|
||||||
'php_html_coverage'))
|
|
||||||
if options.include:
|
|
||||||
command_options.append('--filter')
|
|
||||||
command_options.append(options.include)
|
|
||||||
|
|
||||||
# Application invocation..
|
|
||||||
execute_command([application_path] + DEFAULT_ARGS +
|
|
||||||
command_options + arguments)
|
|
||||||
return 0
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
sys.exit(main())
|
|
Loading…
x
Reference in New Issue
Block a user