Merge branch 'master' into feature/doc-search-6630

This commit is contained in:
Eric Lippmann 2015-02-11 13:28:06 +01:00
commit 54292eed20
12 changed files with 270 additions and 194 deletions

View File

@ -0,0 +1,36 @@
<!doctype html>
<html class="no-js" lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Accessibility: Text cue for required form control labels</title>
<meta name="description" content="Text cue for required form control labels">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style type="text/css">
label.required span.required-indicator:after {
content: " *";
}
.sr-only {
border: 0;
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
</style>
</head>
<body>
<form>
<label class="required">
Enter some text
<span class="required-indicator" aria-hidden="true"></span>
<span class="sr-only"> (required)</span>
</label>
<input type="text" name="some_text" value="" aria-required="true" required>
<input type="submit" name="btn_submit" value="Submit">
</form>
</body>
</html>

View File

@ -55,6 +55,14 @@ nginx:
./bin/icingacli setup config webserver nginx --document-root /usr/share/icingaweb2/public ./bin/icingacli setup config webserver nginx --document-root /usr/share/icingaweb2/public
```` ````
Save the output as new file in your webserver's configuration directory.
Example for Apache on RHEL/CentOS:
````
./bin/icingacli setup config webserver apache --document-root /usr/share/icingaweb2/public > /etc/httpd/conf.d/icingaweb2.conf
````
**Step 4: Preparing Web Setup** **Step 4: Preparing Web Setup**
Because both web and CLI must have access to configuration and logs, permissions will be managed using a special Because both web and CLI must have access to configuration and logs, permissions will be managed using a special

View File

@ -189,7 +189,7 @@ rm -rf %{buildroot}
mkdir -p %{buildroot}/{%{basedir}/{modules,library,public},%{bindir},%{configdir}/modules/setup,%{logdir},%{phpdir},%{wwwconfigdir},%{_sysconfdir}/bash_completion.d,%{docsdir}} mkdir -p %{buildroot}/{%{basedir}/{modules,library,public},%{bindir},%{configdir}/modules/setup,%{logdir},%{phpdir},%{wwwconfigdir},%{_sysconfdir}/bash_completion.d,%{docsdir}}
cp -prv application doc %{buildroot}/%{basedir} cp -prv application doc %{buildroot}/%{basedir}
cp -pv etc/bash_completion.d/icingacli %{buildroot}/%{_sysconfdir}/bash_completion.d/icingacli cp -pv etc/bash_completion.d/icingacli %{buildroot}/%{_sysconfdir}/bash_completion.d/icingacli
cp -prv modules/{monitoring,setup} %{buildroot}/%{basedir}/modules cp -prv modules/{monitoring,setup,doc,translation} %{buildroot}/%{basedir}/modules
cp -prv library/Icinga %{buildroot}/%{phpdir} cp -prv library/Icinga %{buildroot}/%{phpdir}
cp -prv library/vendor %{buildroot}/%{basedir}/library cp -prv library/vendor %{buildroot}/%{basedir}/library
cp -prv public/{css,img,js,error_norewrite.html} %{buildroot}/%{basedir}/public cp -prv public/{css,img,js,error_norewrite.html} %{buildroot}/%{basedir}/public

View File

@ -5,6 +5,7 @@ namespace Icinga\Authentication\Backend;
use Icinga\User; use Icinga\User;
use Icinga\Authentication\UserBackend; use Icinga\Authentication\UserBackend;
use Icinga\Protocol\Ldap\Query;
use Icinga\Protocol\Ldap\Connection; use Icinga\Protocol\Ldap\Connection;
use Icinga\Exception\AuthenticationException; use Icinga\Exception\AuthenticationException;
use Icinga\Protocol\Ldap\Exception as LdapException; use Icinga\Protocol\Ldap\Exception as LdapException;
@ -15,7 +16,7 @@ class LdapUserBackend extends UserBackend
* Connection to the LDAP server * Connection to the LDAP server
* *
* @var Connection * @var Connection
**/ */
protected $conn; protected $conn;
protected $baseDn; protected $baseDn;
@ -36,7 +37,9 @@ class LdapUserBackend extends UserBackend
} }
/** /**
* @return \Icinga\Protocol\Ldap\Query * Create a query to select all usernames
*
* @return Query
*/ */
protected function selectUsers() protected function selectUsers()
{ {
@ -49,15 +52,15 @@ class LdapUserBackend extends UserBackend
} }
/** /**
* Create query * Create a query filtered by the given username
* *
* @param string $username * @param string $username
* *
* @return \Icinga\Protocol\Ldap\Query * @return Query
**/ */
protected function selectUser($username) protected function selectUser($username)
{ {
return $this->selectUsers()->where( return $this->selectUsers()->setUsePagedResults(false)->where(
$this->userNameAttribute, $this->userNameAttribute,
str_replace('*', '', $username) str_replace('*', '', $username)
); );
@ -68,7 +71,7 @@ class LdapUserBackend extends UserBackend
* *
* Try to bind to the backend and query all available users to check if: * Try to bind to the backend and query all available users to check if:
* <ul> * <ul>
* <li>User connection credentials are correct and the bind is possible</li> * <li>Connection credentials are correct and the bind is possible</li>
* <li>At least one user exists</li> * <li>At least one user exists</li>
* <li>The specified userClass has the property specified by userNameAttribute</li> * <li>The specified userClass has the property specified by userNameAttribute</li>
* </ul> * </ul>
@ -78,13 +81,12 @@ class LdapUserBackend extends UserBackend
public function assertAuthenticationPossible() public function assertAuthenticationPossible()
{ {
try { try {
$q = $this->conn->select()->setBase($this->baseDn)->from($this->userClass); $result = $this->selectUsers()->fetchRow();
$result = $q->fetchRow();
} catch (LdapException $e) { } catch (LdapException $e) {
throw new AuthenticationException('Connection not possible.', $e); throw new AuthenticationException('Connection not possible.', $e);
} }
if (! isset($result)) { if ($result === null) {
throw new AuthenticationException( throw new AuthenticationException(
'No objects with objectClass="%s" in DN="%s" found.', 'No objects with objectClass="%s" in DN="%s" found.',
$this->userClass, $this->userClass,
@ -139,17 +141,16 @@ class LdapUserBackend extends UserBackend
} }
/** /**
* Test whether the given user exists * Return 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)
{ {
$username = $user->getUsername(); $username = $user->getUsername();
$entry = $this->conn->fetchOne($this->selectUser($username)); $entry = $this->selectUser($username)->fetchOne();
if (is_array($entry)) { if (is_array($entry)) {
return in_array(strtolower($username), array_map('strtolower', $entry)); return in_array(strtolower($username), array_map('strtolower', $entry));
@ -159,24 +160,22 @@ class LdapUserBackend extends UserBackend
} }
/** /**
* Authenticate the given user and return true on success, false on failure and null on error * Return whether the given user credentials are valid
* *
* @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 * @param boolean $healthCheck Assert that authentication is possible at all
* of a configuration or backend error
* *
* @return bool True when the authentication was successful, false when the username * @return bool
* or password was invalid *
* @throws AuthenticationException When an error occurred during authentication and authentication is not possible * @throws AuthenticationException In case an error occured or the health check has failed
*/ */
public function authenticate(User $user, $password, $healthCheck = true) public function authenticate(User $user, $password, $healthCheck = false)
{ {
if ($healthCheck) { if ($healthCheck) {
try { try {
$this->assertAuthenticationPossible(); $this->assertAuthenticationPossible();
} catch (AuthenticationException $e) { } catch (AuthenticationException $e) {
// Authentication not possible
throw new AuthenticationException( throw new AuthenticationException(
'Authentication against backend "%s" not possible.', 'Authentication against backend "%s" not possible.',
$this->getName(), $this->getName(),
@ -184,24 +183,27 @@ class LdapUserBackend extends UserBackend
); );
} }
} }
if (! $this->hasUser($user)) { if (! $this->hasUser($user)) {
return false; return false;
} }
try { try {
$userDn = $this->conn->fetchDN($this->selectUser($user->getUsername())); $userDn = $this->conn->fetchDN($this->selectUser($user->getUsername()));
$authenticated = $this->conn->testCredentials( $authenticated = $this->conn->testCredentials(
$userDn, $userDn,
$password $password
); );
if ($authenticated) { if ($authenticated) {
$groups = $this->getGroups($userDn); $groups = $this->getGroups($userDn);
if ($groups !== null) { if ($groups !== null) {
$user->setGroups($groups); $user->setGroups($groups);
} }
} }
return $authenticated; return $authenticated;
} catch (LdapException $e) { } catch (LdapException $e) {
// Error during authentication of this specific user
throw new AuthenticationException( throw new AuthenticationException(
'Failed to authenticate user "%s" against backend "%s". An exception was thrown:', 'Failed to authenticate user "%s" against backend "%s". An exception was thrown:',
$user->getUsername(), $user->getUsername(),
@ -238,6 +240,7 @@ class LdapUserBackend extends UserBackend
$users[] = $row->{$this->userNameAttribute}; $users[] = $row->{$this->userNameAttribute};
} }
} }
return $users; return $users;
} }
} }

View File

@ -84,7 +84,7 @@ class Manager
$preferences = new Preferences(); $preferences = new Preferences();
} }
$user->setPreferences($preferences); $user->setPreferences($preferences);
$groups = array(); $groups = $user->getGroups();
foreach (Config::app('groups') as $name => $config) { foreach (Config::app('groups') as $name => $config) {
try { try {
$groupBackend = UserGroupBackend::create($name, $config); $groupBackend = UserGroupBackend::create($name, $config);

View File

@ -93,10 +93,10 @@ abstract class UserBackend implements Countable
break; break;
case 'msldap': case 'msldap':
$groupOptions = array( $groupOptions = array(
'group_base_dn' => $backendConfig->group_base_dn, 'group_base_dn' => $backendConfig->get('group_base_dn', $resource->getDN()),
'group_attribute' => $backendConfig->group_attribute, 'group_attribute' => $backendConfig->get('group_attribute', 'sAMAccountName'),
'group_member_attribute' => $backendConfig->group_member_attribute, 'group_member_attribute' => $backendConfig->get('group_member_attribute', 'member'),
'group_class' => $backendConfig->group_class 'group_class' => $backendConfig->get('group_class', 'group')
); );
$backend = new LdapUserBackend( $backend = new LdapUserBackend(
$resource, $resource,

View File

@ -32,6 +32,8 @@ class Connection
{ {
const LDAP_NO_SUCH_OBJECT = 32; const LDAP_NO_SUCH_OBJECT = 32;
const LDAP_SIZELIMIT_EXCEEDED = 4; const LDAP_SIZELIMIT_EXCEEDED = 4;
const LDAP_ADMINLIMIT_EXCEEDED = 11;
const PAGE_SIZE = 1000;
protected $ds; protected $ds;
protected $hostname; protected $hostname;
@ -98,9 +100,6 @@ class Connection
protected $namingContexts; protected $namingContexts;
protected $discoverySuccess = false; protected $discoverySuccess = false;
protected $lastResult;
protected $pageCookie;
/** /**
* Constructor * Constructor
* *
@ -171,11 +170,9 @@ class Connection
return false; return false;
} }
throw new LdapException( throw new LdapException(
sprintf(
'LDAP list for "%s" failed: %s', 'LDAP list for "%s" failed: %s',
$dn, $dn,
ldap_error($this->ds) ldap_error($this->ds)
)
); );
} }
$children = ldap_get_entries($this->ds, $result); $children = ldap_get_entries($this->ds, $result);
@ -183,7 +180,7 @@ class Connection
$result = $this->deleteRecursively($children[$i]['dn']); $result = $this->deleteRecursively($children[$i]['dn']);
if (!$result) { if (!$result) {
//return result code, if delete fails //return result code, if delete fails
throw new LdapException(sprintf('Recursively deleting "%s" failed', $dn)); throw new LdapException('Recursively deleting "%s" failed', $dn);
} }
} }
return $this->deleteDN($dn); return $this->deleteDN($dn);
@ -200,11 +197,9 @@ class Connection
return false; return false;
} }
throw new LdapException( throw new LdapException(
sprintf(
'LDAP delete for "%s" failed: %s', 'LDAP delete for "%s" failed: %s',
$dn, $dn,
ldap_error($this->ds) ldap_error($this->ds)
)
); );
} }
@ -225,10 +220,8 @@ class Connection
$rows = $this->fetchAll($query, $fields); $rows = $this->fetchAll($query, $fields);
if (count($rows) !== 1) { if (count($rows) !== 1) {
throw new LdapException( throw new LdapException(
sprintf(
'Cannot fetch single DN for %s', 'Cannot fetch single DN for %s',
$query->create() $query->create()
)
); );
} }
return key($rows); return key($rows);
@ -244,6 +237,7 @@ class Connection
{ {
$query = clone $query; $query = clone $query;
$query->limit(1); $query->limit(1);
$query->setUsePagedResults(false);
$results = $this->fetchAll($query, $fields); $results = $this->fetchAll($query, $fields);
return array_shift($results); return array_shift($results);
} }
@ -273,37 +267,146 @@ class Connection
$this->connect(); $this->connect();
$this->bind(); $this->bind();
$offset = $limit = null; if ($query->getUsePagedResults() && version_compare(PHP_VERSION, '5.4.0') >= 0) {
if ($query->hasLimit()) { return $this->runPagedQuery($query, $fields);
$offset = $query->getOffset(); } else {
return $this->runQuery($query, $fields);
}
}
protected function runQuery(Query $query, $fields = array())
{
$limit = $query->getLimit(); $limit = $query->getLimit();
$offset = $query->hasOffset() ? $query->getOffset() - 1 : 0;
$results = @ldap_search(
$this->ds,
$query->hasBase() ? $query->getBase() : $this->root_dn,
$query->create(),
empty($fields) ? $query->listFields() : $fields,
0, // Attributes and values
$limit ? $offset + $limit : 0
);
if ($results === false) {
if (ldap_errno($this->ds) === self::LDAP_NO_SUCH_OBJECT) {
return array();
}
throw new LdapException(
'LDAP query "%s" (base %s) failed. Error: %s',
$query->create(),
$query->hasBase() ? $query->getBase() : $this->root_dn,
ldap_error($this->ds)
);
} elseif (ldap_count_entries($this->ds, $results) === 0) {
return array();
}
foreach ($query->getSortColumns() as $col) {
ldap_sort($this->ds, $results, $col[0]);
} }
$count = 0; $count = 0;
$entries = array(); $entries = array();
$results = $this->runQuery($query, $fields);
while (! empty($results)) {
$entry = ldap_first_entry($this->ds, $results); $entry = ldap_first_entry($this->ds, $results);
while ($entry) { do {
$count++; $count += 1;
if ( if ($offset === 0 || $offset < $count) {
($offset === null || $offset <= $count)
&& ($limit === null || $limit > count($entries))
) {
$entries[ldap_get_dn($this->ds, $entry)] = $this->cleanupAttributes( $entries[ldap_get_dn($this->ds, $entry)] = $this->cleanupAttributes(
ldap_get_attributes($this->ds, $entry) ldap_get_attributes($this->ds, $entry)
); );
} }
} while (($limit === 0 || $limit !== count($entries)) && ($entry = ldap_next_entry($this->ds, $entry)));
$entry = ldap_next_entry($this->ds, $entry); ldap_free_result($results);
}
$results = $this->runQuery($query, $fields);
}
return $entries; return $entries;
} }
protected function runPagedQuery(Query $query, $fields = array())
{
$limit = $query->getLimit();
$offset = $query->hasOffset() ? $query->getOffset() - 1 : 0;
$queryString = $query->create();
$base = $query->hasBase() ? $query->getBase() : $this->root_dn;
if (empty($fields)) {
$fields = $query->listFields();
}
$count = 0;
$cookie = '';
$entries = array();
do {
ldap_control_paged_result($this->ds, static::PAGE_SIZE, true, $cookie);
$results = @ldap_search($this->ds, $base, $queryString, $fields, 0, $limit ? $offset + $limit : 0);
if ($results === false) {
if (ldap_errno($this->ds) === self::LDAP_NO_SUCH_OBJECT) {
break;
}
throw new LdapException(
'LDAP query "%s" (base %s) failed. Error: %s',
$queryString,
$base,
ldap_error($this->ds)
);
} elseif (ldap_count_entries($this->ds, $results) === 0) {
if (in_array(
ldap_errno($this->ds),
array(static::LDAP_SIZELIMIT_EXCEEDED, static::LDAP_ADMINLIMIT_EXCEEDED)
)) {
Logger::warning(
'Unable to request more than %u results. Does the server allow paged search requests? (%s)',
$count,
ldap_error($this->ds)
);
}
break;
}
$entry = ldap_first_entry($this->ds, $results);
do {
$count += 1;
if ($offset === 0 || $offset < $count) {
$entries[ldap_get_dn($this->ds, $entry)] = $this->cleanupAttributes(
ldap_get_attributes($this->ds, $entry)
);
}
} while (($limit === 0 || $limit !== count($entries)) && ($entry = ldap_next_entry($this->ds, $entry)));
try {
ldap_control_paged_result_response($this->ds, $results, $cookie);
} catch (Exception $e) {
// If the page size is greater than or equal to the sizeLimit value, the server should ignore the
// control as the request can be satisfied in a single page: https://www.ietf.org/rfc/rfc2696.txt
// This applies no matter whether paged search requests are permitted or not. You're done once you
// got everything you were out for.
if (count($entries) !== $limit) {
Logger::warning(
'Unable to request paged LDAP results. Does the server allow paged search requests? (%s)',
$e->getMessage()
);
}
}
ldap_free_result($results);
} while ($cookie && ($limit === 0 || count($entries) < $limit));
if ($cookie) {
// A sequence of paged search requests is abandoned by the client sending a search request containing a
// pagedResultsControl with the size set to zero (0) and the cookie set to the last cookie returned by
// the server: https://www.ietf.org/rfc/rfc2696.txt
ldap_control_paged_result($this->ds, 0, false, $cookie);
ldap_search($this->ds, $base, $queryString, $fields); // Returns no entries, due to the page size
} else {
// Reset the paged search request so that subsequent requests succeed
ldap_control_paged_result($this->ds, 0);
}
return $entries; // TODO(7693): Sort entries post-processed
}
protected function cleanupAttributes($attrs) protected function cleanupAttributes($attrs)
{ {
$clean = (object) array(); $clean = (object) array();
@ -320,79 +423,6 @@ class Connection
return $clean; return $clean;
} }
protected function runQuery(Query $query, $fields = array())
{
if ($query->getUsePagedResults() && version_compare(PHP_VERSION, '5.4.0') >= 0) {
if ($this->pageCookie === null) {
$this->pageCookie = '';
} else {
try {
ldap_control_paged_result_response($this->ds, $this->lastResult, $this->pageCookie);
} catch (Exception $e) {
$this->pageCookie = '';
if (! $query->hasLimit() || ldap_errno($this->ds) !== static::LDAP_SIZELIMIT_EXCEEDED) {
Logger::error(
'Unable to request paged LDAP results. Does the server allow paged search requests? (%s)',
$e->getMessage()
);
}
}
ldap_free_result($this->lastResult);
if (! $this->pageCookie) {
$this->pageCookie = $this->lastResult = null;
// Abandon the paged search request so that subsequent requests succeed
ldap_control_paged_result($this->ds, 0);
return false;
}
}
// Does not matter whether we'll use a valid page size here,
// as the server applies its hard limit in case its too high
ldap_control_paged_result(
$this->ds,
$query->hasLimit() ? $query->getLimit() : 500,
true,
$this->pageCookie
);
} elseif ($this->lastResult !== null) {
ldap_free_result($this->lastResult);
$this->lastResult = null;
return false;
}
$base = $query->hasBase() ? $query->getBase() : $this->root_dn;
$results = @ldap_search(
$this->ds,
$base,
$query->create(),
empty($fields) ? $query->listFields() : $fields,
0, // Attributes and values
$query->hasLimit() ? $query->getOffset() + $query->getLimit() : 0 // No limit - at least where possible
);
if ($results === false) {
if (ldap_errno($this->ds) === self::LDAP_NO_SUCH_OBJECT) {
return false;
}
throw new LdapException(
sprintf(
'LDAP query "%s" (root %s) failed: %s',
$query->create(),
$this->root_dn,
ldap_error($this->ds)
)
);
}
foreach ($query->getSortColumns() as $col) {
ldap_sort($this->ds, $results, $col[0]);
}
$this->lastResult = $results;
return $results;
}
public function testCredentials($username, $password) public function testCredentials($username, $password)
{ {
$this->connect(); $this->connect();
@ -471,18 +501,14 @@ class Connection
} else { } else {
Logger::debug('LDAP STARTTLS failed: %s', ldap_error($ds)); Logger::debug('LDAP STARTTLS failed: %s', ldap_error($ds));
throw new LdapException( throw new LdapException(
sprintf(
'LDAP STARTTLS failed: %s', 'LDAP STARTTLS failed: %s',
ldap_error($ds) ldap_error($ds)
)
); );
} }
} elseif ($force_tls) { } elseif ($force_tls) {
throw new LdapException( throw new LdapException(
sprintf(
'TLS is required but not announced by %s', 'TLS is required but not announced by %s',
$this->hostname $this->hostname
)
); );
} else { } else {
// TODO: Log noticy -> TLS enabled but not announced // TODO: Log noticy -> TLS enabled but not announced
@ -708,24 +734,20 @@ class Connection
if (! $result) { if (! $result) {
throw new LdapException( throw new LdapException(
sprintf( 'Capability query failed (%s:%d): %s. Check if hostname and port of the'
'Capability query failed (%s:%d): %s. Check if hostname and port of the ldap resource are correct ' . ' ldap resource are correct and if anonymous access is permitted.',
. ' and if anonymous access is permitted.',
$this->hostname, $this->hostname,
$this->port, $this->port,
ldap_error($ds) ldap_error($ds)
)
); );
} }
$entry = ldap_first_entry($ds, $result); $entry = ldap_first_entry($ds, $result);
if ($entry === false) { if ($entry === false) {
throw new LdapException( throw new LdapException(
sprintf(
'Capabilities not available (%s:%d): %s. Discovery of root DSE probably not permitted.', 'Capabilities not available (%s:%d): %s. Discovery of root DSE probably not permitted.',
$this->hostname, $this->hostname,
$this->port, $this->port,
ldap_error($ds) ldap_error($ds)
)
); );
} }
@ -771,14 +793,12 @@ class Connection
$r = @ldap_bind($this->ds, $this->bind_dn, $this->bind_pw); $r = @ldap_bind($this->ds, $this->bind_dn, $this->bind_pw);
if (! $r) { if (! $r) {
throw new LdapException( throw new LdapException(
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)
)
); );
} }
$this->bound = true; $this->bound = true;

View File

@ -3,10 +3,12 @@
namespace Icinga\Protocol\Ldap; namespace Icinga\Protocol\Ldap;
use Icinga\Exception\IcingaException;
/** /**
* Class Exception * Class Exception
* @package Icinga\Protocol\Ldap * @package Icinga\Protocol\Ldap
*/ */
class Exception extends \Exception class Exception extends IcingaException
{ {
} }

View File

@ -27,8 +27,8 @@ class Query
protected $connection; protected $connection;
protected $filters = array(); protected $filters = array();
protected $fields = array(); protected $fields = array();
protected $limit_count; protected $limit_count = 0;
protected $limit_offset; protected $limit_offset = 0;
protected $sort_columns = array(); protected $sort_columns = array();
protected $count; protected $count;
protected $base; protected $base;
@ -111,7 +111,7 @@ class Query
*/ */
public function hasLimit() public function hasLimit()
{ {
return $this->limit_count !== null; return $this->limit_count > 0;
} }
/** /**

View File

@ -5,34 +5,44 @@ class Zend_View_Helper_PluginOutput extends Zend_View_Helper_Abstract
{ {
protected static $purifier; protected static $purifier;
protected static $txtPatterns = array(
'~\\\n~',
'~\\\t~',
'~\\\n\\\n~',
'~(\[|\()OK(\]|\))~',
'~(\[|\()WARNING(\]|\))~',
'~(\[|\()CRITICAL(\]|\))~',
'~(\[|\()UNKNOWN(\]|\))~',
'~\@{6,}~'
);
protected static $txtReplacements = array(
"\n",
"\t",
"\n",
'<span class="state ok">$1OK$2</span>',
'<span class="state warning">$1WARNING$2</span>',
'<span class="state critical">$1CRITICAL$2</span>',
'<span class="state error">$1UNKNOWN$2</span>',
'@@@@@@',
);
public function pluginOutput($output) public function pluginOutput($output)
{ {
if (empty($output)) { if (empty($output)) {
return ''; return '';
} }
$output = preg_replace('~<br[^>]+>~', "\n", $output); $output = preg_replace('~<br[^>]+>~', "\n", $output);
if (preg_match('~<\w+[^>]*>~', $output)) { if (preg_match('~<\w+[^>^\\\]{,60}>~', $output)) {
// HTML // HTML
$output = preg_replace('~<table~', '<table style="font-size: 0.75em"', $output = preg_replace('~<table~', '<table style="font-size: 0.75em"',
$this->getPurifier()->purify($output) $this->getPurifier()->purify($output)
); );
} elseif (preg_match('~\\\n~', $output)) {
// Plaintext
$output = '<pre class="pluginoutput">'
. preg_replace(
'~\\\n~', "\n", preg_replace(
'~\\\n\\\n~', "\n",
preg_replace('~\[OK\]~', '<span class="ok">[OK]</span>',
preg_replace('~\[WARNING\]~', '<span class="warning">[WARNING]</span>',
preg_replace('~\[CRITICAL\]~', '<span class="error">[CRITICAL]</span>',
preg_replace('~\@{6,}~', '@@@@@@',
$this->view->escape($output)
))))
)
) . '</pre>';
} else { } else {
$output = '<pre class="pluginoutput">' // Plaintext
. preg_replace('~\@{6,}~', '@@@@@@', $output = '<pre class="pluginoutput">' . preg_replace(
self::$txtPatterns,
self::$txtReplacements,
$this->view->escape($output) $this->view->escape($output)
) . '</pre>'; ) . '</pre>';
} }
@ -55,7 +65,7 @@ class Zend_View_Helper_PluginOutput extends Zend_View_Helper_Abstract
parse_str($m[1], $params); parse_str($m[1], $params);
if (isset($params['host'])) { if (isset($params['host'])) {
$tag->setAttribute('href', $this->view->baseUrl( $tag->setAttribute('href', $this->view->baseUrl(
'/monitoring/detail/show?host=' . urlencode($params['host'] '/monitoring/host/show?host=' . urlencode($params['host']
))); )));
} }
} else { } else {

View File

@ -737,7 +737,6 @@
} }
this.icinga.ui.assignUniqueContainerIds(); this.icinga.ui.assignUniqueContainerIds();
console.log(origFocus);
if (origFocus.length == origFocus[0] !== '') { if (origFocus.length == origFocus[0] !== '') {
setTimeout(function() { setTimeout(function() {
$(self.icinga.utils.getElementByDomPath(origFocus)).focus(); $(self.icinga.utils.getElementByDomPath(origFocus)).focus();

View File

@ -284,10 +284,8 @@
if (! $element) { if (! $element) {
$element = $(selector); $element = $(selector);
} else { } else {
console.log(selector);
$element = $element.children(selector).first(); $element = $element.children(selector).first();
if (! $element[0]) { if (! $element[0]) {
console.log("element not existing stopping...");
return false; return false;
} }
} }