diff --git a/build.xml b/build.xml deleted file mode 100644 index eac5a0d..0000000 --- a/build.xml +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..3585a76 --- /dev/null +++ b/composer.json @@ -0,0 +1,16 @@ +{ + "name": "cacti/plugin_npc", + "description": "Nagios Plugin for Cacti", + "license": "GPL-2.0-or-later", + "require-dev": { + "pestphp/pest": "^1.23" + }, + "config": { + "allow-plugins": { + "pestphp/pest-plugin": true + } + }, + "autoload-dev": { + "files": ["tests/bootstrap.php"] + } +} diff --git a/config.php b/config.php index 30b8c44..b3df926 100644 --- a/config.php +++ b/config.php @@ -1,23 +1,5 @@ setAttribute(Doctrine::ATTR_MODEL_LOADING, Doctrine::MODEL_LOADING_CONSERVATIVE); - -// Load our models -Doctrine::loadModels(dirname(__FILE__) . '/models'); +require_once(dirname(__FILE__) . '/controllers/controller.php'); diff --git a/controllers/comments.php b/controllers/comments.php index f65980e..aca79ae 100644 --- a/controllers/comments.php +++ b/controllers/comments.php @@ -18,7 +18,7 @@ * Comments controller class * * Comments controller provides functionality, such as building the - * Doctrine queries and formatting output. + * queries and formatting output. * * @package npc * @subpackage npc.controllers @@ -172,22 +172,13 @@ function deleteAllServiceComments() { * @return array icon and alt */ function getHostIcon($id) { + $results = db_fetch_row_prepared('SELECT h.icon_image, h.icon_image_alt + FROM npc_services s + LEFT JOIN npc_hosts h ON s.host_object_id = h.host_object_id + WHERE s.service_object_id = ?', + array($id)); - $q = new Doctrine_Pager( - Doctrine_Query::create() - ->select('s.service_id,' - .'h.icon_image,' - .'h.icon_image_alt') - ->from('NpcServices s') - ->leftJoin('s.Host h') - ->where("s.service_object_id = ?", $id), - $this->currentPage, - $this->limit - ); - - $results = $q->execute(array(), Doctrine::HYDRATE_ARRAY); - - return($results[0]['Host']); + return($results); } /** @@ -197,57 +188,78 @@ function getHostIcon($id) { * * @return array The comments */ - function comments($id=null, $where='') { + function comments($id = null, $where = '') { - // Maps searchable fields passed in from the client + /* Maps searchable fields passed in from the client */ $fieldMap = array('service_description' => 'o.name2', 'host_name' => 'o.name1', 'author_name' => 'c.author_name', 'comment_data' => 'c.comment_data'); + $params = array(); if ($this->id || $id) { if ($where != '') { $where .= ' AND '; } - $where .= sprintf("c.object_id = %d", is_null($id) ? $this->id : $id); + $where .= 'c.object_id = ?'; + $params[] = is_null($id) ? $this->id : $id; } if ($this->searchString) { - $where = $this->searchClause($where, $fieldMap); + $where = $this->searchClause($where, $fieldMap, $params); } - if ($this->sort) { - $orderBy = $this->sort . ' ' . $this->dir; - } else { - $orderBy = 'c.entry_time DESC, c.entry_time_usec DESC'; - } - - $q = new Doctrine_Pager( - Doctrine_Query::create() - ->select('i.instance_name,' - .'o.name1 AS host_name,' - .'o.name2 AS service_description,' - .'s.icon_image AS svc_icon_image,' - .'s.icon_image_alt AS svc_icon_image_alt,' - .'h.icon_image AS host_icon_image,' - .'h.icon_image_alt AS host_icon_image_alt,' - .'c.*') - ->from('NpcComments c') - ->leftJoin('c.Object o') - ->leftJoin('c.Instance i') - ->leftJoin('c.Service s') - ->leftJoin('c.Host h') - ->where($where) - ->orderby($orderBy), - $this->currentPage, - $this->limit + $allowedSort = array( + 'entry_time' => 'c.entry_time', + 'author_name' => 'c.author_name', + 'comment_data' => 'c.comment_data', + 'host_name' => 'o.name1', + 'service_description' => 'o.name2', ); + $sortCol = ($this->sort && isset($allowedSort[$this->sort])) + ? $allowedSort[$this->sort] + : 'c.entry_time'; + $sortDir = (strtoupper((string) $this->dir) === 'ASC') ? 'ASC' : 'DESC'; + $orderBy = $sortCol . ' ' . $sortDir; + if ($sortCol === 'c.entry_time') { + $orderBy .= ', c.entry_time_usec ' . $sortDir; + } - $results = $q->execute(array(), Doctrine::HYDRATE_ARRAY); + $whereClause = ''; + if ($where != '') { + $whereClause = 'WHERE ' . $where; + } - // Set the total number of records - $this->numRecords = $q->getNumResults(); + /* Get the total count */ + $this->numRecords = db_fetch_cell_prepared('SELECT COUNT(*) + FROM npc_comments c + LEFT JOIN npc_objects o ON c.object_id = o.object_id + LEFT JOIN npc_instances i ON c.instance_id = i.instance_id + LEFT JOIN npc_services s ON c.object_id = s.service_object_id + LEFT JOIN npc_hosts h ON c.object_id = h.host_object_id + ' . $whereClause, + $params); + + $offset = ($this->currentPage - 1) * $this->limit; + + $results = db_fetch_assoc_prepared('SELECT i.instance_name, + o.name1 AS host_name, + o.name2 AS service_description, + s.icon_image AS svc_icon_image, + s.icon_image_alt AS svc_icon_image_alt, + h.icon_image AS host_icon_image, + h.icon_image_alt AS host_icon_image_alt, + c.* + FROM npc_comments c + LEFT JOIN npc_objects o ON c.object_id = o.object_id + LEFT JOIN npc_instances i ON c.instance_id = i.instance_id + LEFT JOIN npc_services s ON c.object_id = s.service_object_id + LEFT JOIN npc_hosts h ON c.object_id = h.host_object_id + ' . $whereClause . ' + ORDER BY ' . $orderBy . ' + LIMIT ?, ?', + array_merge($params, array($offset, $this->limit))); return($results); } diff --git a/controllers/controller.php b/controllers/controller.php index 4ab6a53..cfcd4da 100644 --- a/controllers/controller.php +++ b/controllers/controller.php @@ -19,7 +19,6 @@ * @subpackage npc.controllers */ class Controller { - var $conn = null; /** * The default state to query @@ -313,36 +312,39 @@ function flattenArray($array=array()) { /** * searchClause * - * Appends search parameters to the passed in where clause - * @param string $where An existing where clause - * @param array $fieldMap Maps passed in field names - * @return string The appended where clasue + * Appends search parameters to the passed in where clause. + * Returns both the SQL fragment and an array of bind params + * for use with prepared statements. + * + * @param string $where An existing where clause + * @param array $fieldMap Maps passed in field names + * @param array $params Existing bind params array (passed by reference) + * @return string The appended where clause */ - function searchClause($where, $fieldMap) { - - if (!$where) { - $where = ' ( '; - } else { - $where .= ' AND ( '; - } - - $fields = json_decode(stripslashes($this->searchFields)); - $count = count($fields); - - $x = 1; - foreach ($fields as $field) { - if (isset($fieldMap[$field])) { - $where .= $fieldMap[$field] . " LIKE '%" . $this->searchString . "%' "; - if ($x < $count) { - $where .= ' OR '; - } - $x++; - } else { - $count = $count - 1; - } - } - - $where .= ' ) '; + function searchClause($where, $fieldMap, &$params = array()) { + $fields = json_decode(stripslashes($this->searchFields)); + if (!is_array($fields)) { + return $where; + } + + $searchValue = '%' . $this->searchString . '%'; + + $clauses = array(); + $searchParams = array(); + foreach ($fields as $field) { + if (isset($fieldMap[$field])) { + $clauses[] = $fieldMap[$field] . ' LIKE ?'; + $searchParams[] = $searchValue; + } + } + + if (empty($clauses)) { + return $where; + } + + $params = array_merge($params, $searchParams); + $where .= $where ? ' AND ( ' : ' ( '; + $where .= implode(' OR ', $clauses) . ' ) '; return($where); } @@ -483,4 +485,3 @@ function updateCsrf() { bottom_footer(); } // end drawFrame } - diff --git a/controllers/downtime.php b/controllers/downtime.php index b07b86d..6584d44 100644 --- a/controllers/downtime.php +++ b/controllers/downtime.php @@ -18,7 +18,7 @@ * Downtime controller class * * Downtime controller provides functionality, such as building the - * Doctrine queries and formatting output. + * queries and formatting output. * * @package npc * @subpackage npc.controllers @@ -125,26 +125,26 @@ function getTriggeredByCombo() { * * @return array */ - function scheduledDowntime($id=null, $where='1=1') { + function scheduledDowntime($id = null, $where = '1=1') { + + $params = array(); if ($this->id || $id) { - $where .= ' AND '; - $where .= sprintf("d.object_id = %d", is_null($id) ? $this->id : $id); + $where .= ' AND d.object_id = ?'; + $params[] = is_null($id) ? $this->id : $id; } - $q = new Doctrine_Query(); - $q->select('i.instance_name,' - .'o.objecttype_id,' - .'o.name1 AS host_name,' - .'o.name2 AS service_description,' - .'d.*') - ->from('NpcScheduleddowntime d') - ->leftJoin('d.Object o') - ->leftJoin('d.Instance i') - ->where("$where") - ->orderby( 'd.scheduled_start_time DESC, d.scheduleddowntime_id DESC' ); - - $results = $q->execute(array(), Doctrine::HYDRATE_ARRAY); + $results = db_fetch_assoc_prepared('SELECT i.instance_name, + o.objecttype_id, + o.name1 AS host_name, + o.name2 AS service_description, + d.* + FROM npc_scheduleddowntime d + LEFT JOIN npc_objects o ON d.object_id = o.object_id + LEFT JOIN npc_instances i ON d.instance_id = i.instance_id + WHERE ' . $where . ' + ORDER BY d.scheduled_start_time DESC, d.scheduleddowntime_id DESC', + $params); return($results); } @@ -156,34 +156,44 @@ function scheduledDowntime($id=null, $where='1=1') { * * @return array */ - function downtimeHistory($id=null, $where='') { + function downtimeHistory($id = null, $where = '') { + + $params = array(); if ($this->id || $id) { if ($where != '') { $where .= ' AND '; } - $where .= sprintf("d.object_id = %d", is_null($id) ? $this->id : $id); + $where .= 'd.object_id = ?'; + $params[] = is_null($id) ? $this->id : $id; + } + + $whereClause = ''; + if ($where != '') { + $whereClause = 'WHERE ' . $where; } - $q = new Doctrine_Pager( - Doctrine_Query::create() - ->select('i.instance_name,' - .'o.name1 AS host_name,' - .'o.name2 AS service_description,' - .'d.*') - ->from('NpcDowntimehistory d') - ->leftJoin('d.Object o') - ->leftJoin('d.Instance i') - ->where("$where") - ->orderby( 'd.scheduled_start_time DESC, d.actual_start_time DESC, d.actual_start_time_usec DESC' ), - $this->currentPage, - $this->limit - ); - - $results = $q->execute(array(), Doctrine::HYDRATE_ARRAY); - - // Set the total number of records - $this->numRecords = $q->getNumResults(); + /* Get total count */ + $this->numRecords = db_fetch_cell_prepared('SELECT COUNT(*) + FROM npc_downtimehistory d + LEFT JOIN npc_objects o ON d.object_id = o.object_id + LEFT JOIN npc_instances i ON d.instance_id = i.instance_id + ' . $whereClause, + $params); + + $offset = ($this->currentPage - 1) * $this->limit; + + $results = db_fetch_assoc_prepared('SELECT i.instance_name, + o.name1 AS host_name, + o.name2 AS service_description, + d.* + FROM npc_downtimehistory d + LEFT JOIN npc_objects o ON d.object_id = o.object_id + LEFT JOIN npc_instances i ON d.instance_id = i.instance_id + ' . $whereClause . ' + ORDER BY d.scheduled_start_time DESC, d.actual_start_time DESC, d.actual_start_time_usec DESC + LIMIT ?, ?', + array_merge($params, array($offset, $this->limit))); return($results); } diff --git a/controllers/hostgroups.php b/controllers/hostgroups.php index 13beae5..909504c 100644 --- a/controllers/hostgroups.php +++ b/controllers/hostgroups.php @@ -1,388 +1,240 @@ - * @copyright Copyright (c) 2007 - * @link http://trac2.assembla.com/npc - * @package npc - * @subpackage npc.controllers - * @since NPC 2.0 - * @version $Id$ - */ +/* + +-------------------------------------------------------------------------+ + | Nagios Plugin for Cacti | + | | + | Copyright (C) 2007 Billy Gunn (billy@gunn.org) | + | Copyright (C) 2004-2026 The Cacti Group | + +-------------------------------------------------------------------------+ + | Cacti and Nagios are the copyright of their respective owners. | + +-------------------------------------------------------------------------+ +*/ if (isset($config)) { - require_once($config["base_path"]."/plugins/npc/controllers/services.php"); + require_once($config['base_path'] . '/plugins/npc/controllers/services.php'); } else { - require_once("plugins/npc/controllers/services.php"); + require_once('plugins/npc/controllers/services.php'); } - -/** - * Hostgroups controller class - * - * Hostgroups controller provides functionality, such as building the - * Doctrine queries and formatting output. - * - * @package npc - * @subpackage npc.controllers - */ class NpcHostgroupsController extends Controller { - /** - * A service status cache - * - * @var array - * @access private - */ - private $statusCache = array(); - - /** - * getHostgroupHostStatus - * - * Returns host status counts by hostgroup. - * - * @return string json output - */ - function getHostgroupHostStatus() { - - // Initialize the output array - $output = array(); - - // Initialize the hosts array - $hosts = array(); - - $fields = array('hostgroup_object_id', - 'alias', - 'instance_id'); - - $results = $this->setupResultsArray(); - - for ($i = 0; $i < count($results); $i++) { - $hg = $results[$i]['hostgroup_object_id']; - if(!isset($output[$hg])) { - $output[$hg] = array('down' => 0, - 'unreachable' => 0, - 'up' => 0, - 'pending' => 0); - } - if (!isset($hosts[$hg][$results[$i]['host_name']])) { - $output[$hg][$this->hostState[$results[$i]['current_state']]]++; - $hosts[$hg][$results[$i]['host_name']] = 1; - } - foreach ($results[$i] as $key => $val) { - if (in_array($key, $fields)) { - $output[$hg][$key] = $val; - } - } - } - - // Set the total number of records - $this->numRecords = count($output); - - // Implement paging by slicing the output array - $output = array_slice($output, $this->start, $this->limit); - - $response['response']['value']['items'] = $output; - $response['response']['value']['total_count'] = $this->numRecords; - $response['response']['value']['version'] = 1; - - return(json_encode($response)); - } - - /** - * getHostgroupServiceStatus - * - * Returns service status counts by hostgroup. - * - * @return string json output - */ - function getHostgroupServiceStatus() { - - // Initialize the output array - $output = array(); - - $fields = array('hostgroup_object_id', - 'alias', - 'hostgroup_name', - 'instance_id'); - - // Combine servicegroup/service/host etc. into a single record - $results = $this->setupResultsArray(); - - for ($i = 0; $i < count($results); $i++) { - $hg = $results[$i]['hostgroup_object_id']; - $ss = $this->getHostgroupMemberServiceStatus($results[$i]['host_object_id']); - if(!isset($output[$hg])) { - $output[$hg] = $ss; - } else { - foreach ($ss as $k => $v) { - $output[$hg][$k] = $output[$hg][$k] + $v; - } - } - foreach ($results[$i] as $key => $val) { - if (in_array($key, $fields)) { - $output[$hg][$key] = $val; - } - } - } - - // Set the total number of records - $this->numRecords = count($output); - - // Implement paging by slicing the output array - $output = array_slice($output, $this->start, $this->limit); - - $response['response']['value']['items'] = $output; - $response['response']['value']['total_count'] = $this->numRecords; - $response['response']['value']['version'] = 1; - - return(json_encode($response)); - } - - - /** - * getOverview - * - * Returns all hosts by hostgroup. Used to populate - * the Servicegroup Grid screen. - * - * @return string json output - */ - function getOverview() { - - $fields = array('hostgroup_object_id', - 'alias', - 'instance_id', - 'host_name'); - - // Initialize the output array - $output = array(); - - // Combine servicegroup/service/host etc. into a single record - $results = $this->setupResultsArray(); - - /* Loop through the results array and build an output array - * that includes a single record per host within the hostgroup - * and the number of crit, warn , ok services within - * that hostgroup. - */ - for ($i = 0; $i < count($results); $i++) { - $hg = $results[$i]['hostgroup_object_id']; - $host = $results[$i]['host_name']; - $ss = $this->getHostgroupMemberServiceStatus($results[$i]['host_object_id']); - if(!isset($temp[$hg][$host])) { - $ss['host_state'] = $results[$i]['current_state']; - $temp[$hg][$host] = $ss; - } - foreach ($results[$i] as $key => $val) { - $temp[$hg][$host][$key] = $val; - } - } - - $x = 0; - foreach ($temp as $i => $s) { - foreach ($s as $h => $v) { - foreach ($v as $key => $val) { - $output[$x][$key] = $val; - } - $x++; - } - } - - // Set the total number of records - $this->numRecords = count($output); - - // Implement paging by slicing the output array - $output = array_slice($output, $this->start, $this->limit); - - return($this->jsonOutput($output)); - } - - - /** - * getHosts - * - * Returns all hosts by hostgroup. Used to populate - * the Hostgroup Grid screen. - * - * @return string json output - */ - function getHosts() { - - $output = $this->setupResultsArray(); - - // Set the total number of records - $this->numRecords = count($output); - - // Implement paging by slicing the output array - $output = array_slice($output, $this->start, $this->limit); - - return($this->jsonOutput($output)); - } - - /** - * getHostList - * - * Retrieves all hosts in the specified hostgroup - * - * @return array - */ - function getHostList($params) { - - $column = key($params); - $value = $params[$column]; - - $q = new Doctrine_Query(); - $q->select('h.host_object_id, h.display_name, h.address') - ->from('NpcHosts h, NpcHostgroups hg, NpcHostgroupMembers hgm') - ->where('hg.hostgroup_id = hgm.hostgroup_id AND hgm.host_object_id = h.host_object_id AND hg.'.$column.' = ?', $value); - - $results = $q->execute(array(), Doctrine::HYDRATE_ARRAY); - - return($results); - } - - /** - * getHostgroupMemberServiceStatus - * - * Returns a count of the status of all services for a given host. - * - * @return array - */ - private function getHostgroupMemberServiceStatus($host_object_id) { - - if(isset($this->statusCache[$host_object_id])) { - return($this->statusCache[$host_object_id]); - } - - // initialize the status array - $this->statusCache[$host_object_id] = array('critical' => 0, - 'warning' => 0, - 'unknown' => 0, - 'ok' => 0, - 'pending' => 0); - - - $obj = new NpcServicesController; - $results = $obj->getServiceStatesByHost($host_object_id); - - for ($i = 0; $i < count($results); $i++) { - $this->statusCache[$host_object_id][$this->serviceState[$results[$i]['current_state']]]++; - } - - return($this->statusCache[$host_object_id]); - } - - /** - * listHostsCli - * - * Retrieves all hosts in the specified hostgroup for the cli - * - * @return array - */ - function listHostsCli($hg) { - - $q = new Doctrine_Query(); - $q->select('h.host_id, h.host_object_id AS id, h.display_name AS name, h.address') - ->from('NpcHosts h, NpcHostgroups hg, NpcHostgroupMembers hgm') - ->where('hg.hostgroup_id = hgm.hostgroup_id AND hgm.host_object_id = h.host_object_id AND hg.alias = ?', $hg); - - $results = $q->execute(array(), Doctrine::HYDRATE_ARRAY); - - return($results); - } - - - /** - * listHostgroupsCli - * - * Returns all hostgroups and associated object ID's - * - * @return array Array of hostgroups/id's - */ - function listHostgroupsCli() { - - $q = new Doctrine_Query(); - $q->select('alias as name, hostgroup_object_id as id')->from('NpcHostgroups')->orderBy('alias ASC'); - - return($q->execute(array(), Doctrine::HYDRATE_ARRAY)); - } - - - /** - * getHostgroups - * - * Retrieves all hosts with current state by hostgroup - * - * @return array - */ - function getHostgroups() { - $where = '1 = 1'; - - // Maps searchable fields passed in from the client - $fieldMap = array('service_description' => 'o2.name2', - 'host_name' => 'o2.name1', - 'alias' => 'sg.alias', - 'output' => 's.output'); - - if ($this->id) { - $where .= " AND hg.hostgroup_object_id = " . $this->id . " "; - } - - if ($this->searchString) { - $where = $this->searchClause(null, $fieldMap); - } - - $q = new Doctrine_Query(); - $q->select('i.instance_name,' - .'o1.name1 AS hostgroup_name,' - .'hs.host_object_id,' - .'hs.current_state,' - .'hs.output,' - .'o2.name1 AS host_name,' - .'hg.*') - ->distinct() - ->from('NpcHostgroups hg') - ->innerJoin('hg.HostgroupMembers hgm') - ->innerJoin('hg.Hoststatus hs ON hgm.host_object_id = hs.host_object_id') - ->innerJoin('hg.Object o1') - ->innerJoin('hs.Object o2') - ->innerJoin('hg.Instance i') - ->where("$where") - ->orderBy('hostgroup_name ASC, host_name ASC'); - - $results = $q->execute(array(), Doctrine::HYDRATE_ARRAY); - - return($results); - } - - /** - * setupResultsArray - * - * A utility method to handle some common formatting tasks. - * - * @return array - */ - function setupResultsArray() { - - // Get the servicegroups - $results = $this->getHostgroups(); - - // Flatten the 1st level of nested arrays - $results = $this->flattenArray($results); - - // Combine servicegroup/service/host etc. into a single record. - $results = $this->flattenNestedArray($results); - - return($results); - } - + private $statusCache = array(); + + function getHostgroupHostStatus() { + $output = array(); + $hosts = array(); + + $fields = array('hostgroup_object_id', 'alias', 'instance_id'); + $results = $this->setupResultsArray(); + + for ($i = 0; $i < count($results); $i++) { + $hg = $results[$i]['hostgroup_object_id']; + if (!isset($output[$hg])) { + $output[$hg] = array('down' => 0, 'unreachable' => 0, 'up' => 0, 'pending' => 0); + } + if (!isset($hosts[$hg][$results[$i]['host_name']])) { + $state = $results[$i]['current_state']; + if (isset($this->hostState[$state])) { + $output[$hg][$this->hostState[$state]]++; + } + $hosts[$hg][$results[$i]['host_name']] = 1; + } + foreach ($results[$i] as $key => $val) { + if (in_array($key, $fields, true)) { + $output[$hg][$key] = $val; + } + } + } + + $this->numRecords = count($output); + $output = array_slice($output, $this->start, $this->limit); + + $response = array( + 'response' => array( + 'value' => array( + 'items' => $output, + 'total_count' => $this->numRecords, + 'version' => 1, + ) + ) + ); + + return json_encode($response); + } + + function getHostgroupServiceStatus() { + $output = array(); + $fields = array('hostgroup_object_id', 'alias', 'hostgroup_name', 'instance_id'); + + $results = $this->setupResultsArray(); + + for ($i = 0; $i < count($results); $i++) { + $hg = $results[$i]['hostgroup_object_id']; + $ss = $this->getHostgroupMemberServiceStatus($results[$i]['host_object_id']); + if (!isset($output[$hg])) { + $output[$hg] = $ss; + } else { + foreach ($ss as $k => $v) { + $output[$hg][$k] = $output[$hg][$k] + $v; + } + } + foreach ($results[$i] as $key => $val) { + if (in_array($key, $fields, true)) { + $output[$hg][$key] = $val; + } + } + } + + $this->numRecords = count($output); + $output = array_slice($output, $this->start, $this->limit); + + $response = array( + 'response' => array( + 'value' => array( + 'items' => $output, + 'total_count' => $this->numRecords, + 'version' => 1, + ) + ) + ); + + return json_encode($response); + } + + function getOverview() { + $fields = array('hostgroup_object_id', 'alias', 'instance_id', 'host_name'); + $output = array(); + $temp = array(); + + $results = $this->setupResultsArray(); + + for ($i = 0; $i < count($results); $i++) { + $hg = $results[$i]['hostgroup_object_id']; + $host = $results[$i]['host_name']; + $ss = $this->getHostgroupMemberServiceStatus($results[$i]['host_object_id']); + if (!isset($temp[$hg][$host])) { + $ss['host_state'] = $results[$i]['current_state']; + $temp[$hg][$host] = $ss; + } + foreach ($results[$i] as $key => $val) { + $temp[$hg][$host][$key] = $val; + } + } + + $x = 0; + foreach ($temp as $i => $s) { + foreach ($s as $h => $v) { + foreach ($v as $key => $val) { + $output[$x][$key] = $val; + } + $x++; + } + } + + $this->numRecords = count($output); + $output = array_slice($output, $this->start, $this->limit); + + return $this->jsonOutput($output); + } + + function getHosts() { + $output = $this->setupResultsArray(); + $this->numRecords = count($output); + $output = array_slice($output, $this->start, $this->limit); + + return $this->jsonOutput($output); + } + + function getHostList($params) { + $allowed_columns = array('alias', 'hostgroup_object_id', 'hostgroup_id'); + $column = key($params); + + if (!in_array($column, $allowed_columns, true)) { + return array(); + } + + $value = $params[$column]; + + return db_fetch_assoc_prepared( + 'SELECT h.host_object_id, h.display_name, h.address + FROM npc_hosts h + INNER JOIN npc_hostgroup_members hgm ON hgm.host_object_id = h.host_object_id + INNER JOIN npc_hostgroups hg ON hg.hostgroup_id = hgm.hostgroup_id + WHERE hg.' . $column . ' = ?', + array($value)); + } + + private function getHostgroupMemberServiceStatus($host_object_id) { + if (isset($this->statusCache[$host_object_id])) { + return $this->statusCache[$host_object_id]; + } + + $this->statusCache[$host_object_id] = array( + 'critical' => 0, 'warning' => 0, 'unknown' => 0, 'ok' => 0, 'pending' => 0 + ); + + $obj = new NpcServicesController; + $results = $obj->getServiceStatesByHost($host_object_id); + + for ($i = 0; $i < count($results); $i++) { + $state_key = $results[$i]['current_state']; + if (isset($this->serviceState[$state_key])) { + $this->statusCache[$host_object_id][$this->serviceState[$state_key]]++; + } + } + + return $this->statusCache[$host_object_id]; + } + + function listHostsCli($hg) { + return db_fetch_assoc_prepared( + 'SELECT h.host_id, h.host_object_id AS id, h.display_name AS name, h.address + FROM npc_hosts h + INNER JOIN npc_hostgroup_members hgm ON hgm.host_object_id = h.host_object_id + INNER JOIN npc_hostgroups hg ON hg.hostgroup_id = hgm.hostgroup_id + WHERE hg.alias = ?', + array($hg)); + } + + function listHostgroupsCli() { + return db_fetch_assoc('SELECT alias AS name, hostgroup_object_id AS id + FROM npc_hostgroups + ORDER BY alias ASC'); + } + + function getHostgroups() { + $params = array(); + $where = '1 = 1'; + + if ($this->id) { + $where .= ' AND hg.hostgroup_object_id = ?'; + $params[] = intval($this->id); + } + + return db_fetch_assoc_prepared( + 'SELECT DISTINCT i.instance_name, + o1.name1 AS hostgroup_name, + hs.host_object_id, + hs.current_state, + hs.output, + o2.name1 AS host_name, + hg.* + FROM npc_hostgroups hg + INNER JOIN npc_hostgroup_members hgm ON hg.hostgroup_id = hgm.hostgroup_id + INNER JOIN npc_hoststatus hs ON hgm.host_object_id = hs.host_object_id + INNER JOIN npc_objects o1 ON hg.hostgroup_object_id = o1.object_id + INNER JOIN npc_objects o2 ON hs.host_object_id = o2.object_id + INNER JOIN npc_instances i ON hg.instance_id = i.instance_id + WHERE ' . $where . ' + ORDER BY o1.name1 ASC, o2.name1 ASC', + $params); + } + + function setupResultsArray() { + $results = $this->getHostgroups(); + $results = $this->flattenArray($results); + $results = $this->flattenNestedArray($results); + + return $results; + } } - - - diff --git a/controllers/hosts.php b/controllers/hosts.php index 3422640..47c7f63 100644 --- a/controllers/hosts.php +++ b/controllers/hosts.php @@ -1,347 +1,264 @@ - * @copyright Copyright (c) 2007 - * @link http://trac2.assembla.com/npc - * @package npc - * @subpackage npc.controllers - * @since NPC 2.0 - * @version $Id$ - */ - -require_once($config["base_path"]."/plugins/npc/controllers/comments.php"); - -/** - * Hosts controller class - * - * Hosts controller provides functionality, such as building the - * Doctrine queries and formatting output. - * - * @package npc - * @subpackage npc.controllers - */ -class NpcHostsController extends Controller { +/* + +-------------------------------------------------------------------------+ + | Nagios Plugin for Cacti | + | | + | Copyright (C) 2007 Billy Gunn (billy@gunn.org) | + | Copyright (C) 2004-2026 The Cacti Group | + +-------------------------------------------------------------------------+ + | Cacti and Nagios are the copyright of their respective owners. | + +-------------------------------------------------------------------------+ +*/ + +require_once($config['base_path'] . '/plugins/npc/controllers/comments.php'); - /** - * getHosts - * - * Gets and formats hosts for output. - * - * @return string json output - */ - function getHosts() { - - $results = $this->hosts(); - - $comments = new NpcCommentsController; - - $hosts = $this->flattenArray($results); - - - for ($i = 0; $i < count($hosts); $i++) { - if ($hosts[$i]['problem_has_been_acknowledged']) { - $hosts[$i]['acknowledgement'] = $comments->getAck($hosts[$i]['host_object_id']); - } - // Add the last comment to the array - $hosts[$i]['comment'] = $comments->getLastComment($hosts[$i]['host_object_id']); - - // Count the services and delete the entries - $services = 0; - foreach ($hosts[$i] as $k => $v) { - if (is_array($v)) { - $services++; - unset($hosts[$i][$k]); - } - } - - $hosts[$i]['service_count'] = $services; - } - - $response['response']['value']['items'] = $hosts; - $response['response']['value']['total_count'] = $this->numRecords; - $response['response']['value']['version'] = 1; - - return(json_encode($response)); - } - - /** - * getStateInfo - * - * Gets and formats host state information - * - * @return string json output - */ - function getStateInfo() { - - $fields = array( - 'current_state', - 'output', - 'perfdata', - 'last_state_change', - 'check_command', - 'address', - 'current_check_attempt', - 'last_check', - 'next_check', - 'event_handler', - 'latency', - 'execution_time', - 'is_flapping', - 'scheduled_downtime_depth', - 'process_performance_data', - 'active_checks_enabled', - 'passive_checks_enabled', - 'event_handler_enabled', - 'flap_detection_enabled', - 'notifications_enabled', - 'obsess_over_host' - ); - - $hosts = $this->hosts(); - - $results = $this->flattenArray($hosts); - - $x = 0; - foreach ($fields as $key) { - $output[$x] = array('name' => $this->columnAlias[$key], 'value' => $this->formatStateInfo($key, $results[0])); - $x++; - } - - return($this->jsonOutput($output)); - } - - /** - * summary - * - * Returns a state count for all hosts - * - * @return string json output - */ - function summary() { - - $status = array( - 'down' => 0, - 'unreachable' => 0, - 'up' => 0, - 'pending' => 0 - ); - - $q = new Doctrine_Query(); - $q->select('hs.current_state') - ->from('NpcHoststatus hs') - ->leftJoin('hs.Host h') - ->where('h.config_type = ?', $this->config_type); - - $hosts = $q->execute(array(), Doctrine::HYDRATE_ARRAY); - - for ($i = 0; $i < count($hosts); $i++) { - $status[$this->hostState[$hosts[$i]['current_state']]]++; - } - - return($this->jsonOutput($status)); - } - - function getPerfData($id) { - - $q = new Doctrine_Query(); - $q->select('perfdata')->from('NpcHostchecks')->where('host_object_id = ?', $id); - - return($q->execute(array(), Doctrine::HYDRATE_ARRAY)); - } - - /** - * hosts - * - * Retrieves all hosts along with status information - * - * @return array - */ - function hosts() { - - // Maps searchable fields passed in from the client - $fieldMap = array('host_name' => 'o.name1', - 'alias' => 'h.alias', - 'output' => 'hs.output'); - - - // Build the where clause - $where = " hs.current_state in (" . $this->stringToState[$this->state] . ") AND h.config_type = " . $this->config_type; - - - if ($this->id) { - $where .= sprintf(" AND hs.host_object_id = %d", $this->id); - } - - if ($this->searchString) { - $where = $this->searchClause($where, $fieldMap); - } - - if ($this->sort) { - $orderBy = $this->sort . ' ' . $this->dir; - } else { - $orderBy = 'i.instance_name ASC, host_name ASC'; - } - - $q = new Doctrine_Pager( - Doctrine_Query::create() - ->select('i.instance_name,' - .'o.name1 AS host_name,' - .'h.alias,' - .'h.address,' - .'h.notes,' - .'h.notes_url,' - .'h.action_url,' - .'h.icon_image,' - .'h.icon_image_alt,' - .'s.service_object_id,' - .'s.display_name,' - .'g.local_graph_id,' - .'hs.*') - ->from('NpcHoststatus hs') - ->leftJoin('hs.Object o') - ->leftJoin('hs.Host h') - ->leftJoin('hs.Instance i') - ->leftJoin('hs.Services s') - ->leftJoin('hs.Graph g') - ->where($where) - ->orderby($orderBy), - $this->currentPage, - $this->limit - ); - - $hosts = $q->execute(array(), Doctrine::HYDRATE_ARRAY); - - // Set the total number of records - $this->numRecords = $q->getNumResults(); - - return($hosts); - } - - /** - * listHostsCli - * - * Returns all hosts and associated object ID's - * - * @return array Array of hosts/id's - */ - function listHostsCli() { - - $q = new Doctrine_Query(); - $q->select('display_name as name, host_object_id as id, address')->from('NpcHosts')->orderBy('display_name ASC'); - - return($q->execute(array(), Doctrine::HYDRATE_ARRAY)); - } - - /** - * getMappedGraph - * - * Returns the requested npc_host_graphs record - * - * @return string json encoded results - */ - function getMappedGraph() { - - $q = new Doctrine_Query(); - $q->select('hg.*') - ->from('NpcHostGraphs hg') - ->where('hg.host_object_id = ?', $this->id); - - $results = $q->execute(array(), Doctrine::HYDRATE_ARRAY); - - return($this->jsonOutput($results)); - } - - /** - * setMappedGraph - * - * Sets the graph mapping - * - * @return string json encoded results - */ - function setMappedGraph($params) { - - $table = $this->conn->getTable('NpcHostGraphs'); - - $results = $table->findByDql("host_object_id = ?", array($params['object_id'])); - $graph = $results[0]; - - if (!isset($graph->local_graph_id)) { - $graph = new NpcServiceGraphs(); - } - - $graph->host_object_id = $params['object_id']; - $graph->local_graph_id = $params['local_graph_id']; - $graph->save(); - - return(json_encode(array('success' => true))); - } - - - - /** - * formatStateInfo - * - * Formats the host state info results for display - * - * @return string The formatted results - */ - function formatStateInfo($key, $results) { - - // Set the default return value - $return = $results[$key]; - - $cs = array( - '0' => '', - '1' => '', - '2' => '', - '-1' => '' - ); - - if ($key == 'current_state') { - $return = $cs[$results[$key]]; - if ($results['problem_has_been_acknowledged']) { - $comments = new NpcCommentsController; - $string = $comments->getAck($results['host_object_id']); - $ack = preg_split("/\*\|\*/", $string); - $return = '
' . $return . '   (Acknowledged by ' . $ack[0] . ')
'; - } - } - - if ($key == 'current_check_attempt') { - $return = $results[$key] . '/' . $results['max_check_attempts']; - } - - if (preg_match("/_enabled/", $key) || $key == 'obsess_over_host') { - if($results[$key]) { - $return = ''; - } else { - $return = ''; - } - } - - if ($key == 'last_state_change' || $key == 'last_check' || $key == 'next_check') { - $format = read_config_option('npc_date_format') . ' ' . read_config_option('npc_time_format'); - $return = date($format, strtotime($results[$key])); - } - - if ($key == 'scheduled_downtime_depth' || $key == 'is_flapping' || $key == 'process_performance_data') { - if ($results[$key]) { - $return = 'Yes'; - } else { - $return = 'No'; - } - } - - if ($return == '' || !$return) { - $return = 'NA'; - } - - return($return); - } +class NpcHostsController extends Controller { + function getHosts() { + $results = $this->hosts(); + + $comments = new NpcCommentsController; + $hosts = $this->flattenArray($results); + + for ($i = 0; $i < count($hosts); $i++) { + if ($hosts[$i]['problem_has_been_acknowledged']) { + $hosts[$i]['acknowledgement'] = $comments->getAck($hosts[$i]['host_object_id']); + } + $hosts[$i]['comment'] = $comments->getLastComment($hosts[$i]['host_object_id']); + + $services = 0; + foreach ($hosts[$i] as $k => $v) { + if (is_array($v)) { + $services++; + unset($hosts[$i][$k]); + } + } + $hosts[$i]['service_count'] = $services; + } + + $response = array( + 'response' => array( + 'value' => array( + 'items' => $hosts, + 'total_count' => $this->numRecords, + 'version' => 1, + ) + ) + ); + + return json_encode($response); + } + + function getStateInfo() { + $fields = array( + 'current_state', 'output', 'perfdata', 'last_state_change', + 'check_command', 'address', 'current_check_attempt', 'last_check', + 'next_check', 'event_handler', 'latency', 'execution_time', + 'is_flapping', 'scheduled_downtime_depth', 'process_performance_data', + 'active_checks_enabled', 'passive_checks_enabled', + 'event_handler_enabled', 'flap_detection_enabled', + 'notifications_enabled', 'obsess_over_host' + ); + + $hosts = $this->hosts(); + $results = $this->flattenArray($hosts); + $output = array(); + + $x = 0; + foreach ($fields as $key) { + $output[$x] = array( + 'name' => $this->columnAlias[$key], + 'value' => $this->formatStateInfo($key, $results[0]) + ); + $x++; + } + + return $this->jsonOutput($output); + } + + function summary() { + $status = array( + 'down' => 0, + 'unreachable' => 0, + 'up' => 0, + 'pending' => 0 + ); + + $hosts = db_fetch_assoc_prepared('SELECT hs.current_state + FROM npc_hoststatus hs + LEFT JOIN npc_hosts h ON hs.host_object_id = h.host_object_id + WHERE h.config_type = ?', + array($this->config_type)); + + for ($i = 0; $i < count($hosts); $i++) { + $state_key = $hosts[$i]['current_state']; + if (isset($this->hostState[$state_key])) { + $status[$this->hostState[$state_key]]++; + } + } + + return $this->jsonOutput($status); + } + + function getPerfData($id) { + return db_fetch_assoc_prepared('SELECT perfdata + FROM npc_hostchecks + WHERE host_object_id = ?', + array($id)); + } + + function hosts() { + $fieldMap = array( + 'host_name' => 'o.name1', + 'alias' => 'h.alias', + 'output' => 'hs.output' + ); + + $params = array(); + $where = ''; + + /* State filter */ + $states = $this->stringToState[$this->state]; + $state_list = implode(',', array_map('intval', explode(',', $states))); + $where .= 'hs.current_state IN (' . $state_list . ')'; + $where .= ' AND h.config_type = ?'; + $params[] = $this->config_type; + + if ($this->id) { + $where .= ' AND hs.host_object_id = ?'; + $params[] = intval($this->id); + } + + if ($this->searchString) { + $where = $this->searchClause($where, $fieldMap, $params); + } + + $orderBy = 'i.instance_name ASC, o.name1 ASC'; + if ($this->sort) { + $allowed_sorts = array( + 'instance_name', 'host_name', 'alias', 'address', + 'current_state', 'last_check', 'output', 'last_state_change' + ); + if (in_array($this->sort, $allowed_sorts, true)) { + $dir = ($this->dir == 'DESC') ? 'DESC' : 'ASC'; + $orderBy = $this->sort . ' ' . $dir; + } + } + + /* Total count */ + $this->numRecords = db_fetch_cell_prepared( + 'SELECT COUNT(*) + FROM npc_hoststatus hs + LEFT JOIN npc_objects o ON hs.host_object_id = o.object_id + LEFT JOIN npc_hosts h ON hs.host_object_id = h.host_object_id + LEFT JOIN npc_instances i ON h.instance_id = i.instance_id + WHERE ' . $where, + $params); + + /* Paginated results */ + $offset = ($this->currentPage - 1) * $this->limit; + + $hosts = db_fetch_assoc_prepared( + 'SELECT i.instance_name, + o.name1 AS host_name, + h.alias, + h.address, + h.notes, + h.notes_url, + h.action_url, + h.icon_image, + h.icon_image_alt, + hg.local_graph_id, + hs.* + FROM npc_hoststatus hs + LEFT JOIN npc_objects o ON hs.host_object_id = o.object_id + LEFT JOIN npc_hosts h ON hs.host_object_id = h.host_object_id + LEFT JOIN npc_instances i ON h.instance_id = i.instance_id + LEFT JOIN npc_host_graphs hg ON hs.host_object_id = hg.host_object_id + WHERE ' . $where . ' + ORDER BY ' . $orderBy . ' + LIMIT ?, ?', + array_merge($params, array($offset, $this->limit))); + + return $hosts; + } + + function listHostsCli() { + return db_fetch_assoc('SELECT display_name AS name, host_object_id AS id, address + FROM npc_hosts + ORDER BY display_name ASC'); + } + + function getMappedGraph() { + $results = db_fetch_assoc_prepared( + 'SELECT * FROM npc_host_graphs WHERE host_object_id = ?', + array($this->id)); + + return $this->jsonOutput($results); + } + + function setMappedGraph($params) { + $object_id = intval($params['object_id']); + $local_graph_id = intval($params['local_graph_id']); + + $existing = db_fetch_row_prepared( + 'SELECT * FROM npc_host_graphs WHERE host_object_id = ?', + array($object_id)); + + if (cacti_sizeof($existing)) { + db_execute_prepared( + 'UPDATE npc_host_graphs SET local_graph_id = ? WHERE host_object_id = ?', + array($local_graph_id, $object_id)); + } else { + db_execute_prepared( + 'INSERT INTO npc_host_graphs (host_object_id, local_graph_id) VALUES (?, ?)', + array($object_id, $local_graph_id)); + } + + return json_encode(array('success' => true)); + } + + function formatStateInfo($key, $results) { + $return = isset($results[$key]) ? $results[$key] : ''; + + $cs = array( + '0' => '', + '1' => '', + '2' => '', + '-1' => '' + ); + + if ($key == 'current_state') { + $return = isset($cs[$results[$key]]) ? $cs[$results[$key]] : ''; + if ($results['problem_has_been_acknowledged']) { + $comments = new NpcCommentsController; + $string = $comments->getAck($results['host_object_id']); + $ack = preg_split('/\*\|\*/', $string); + $return .= ' (Acknowledged by ' . html_escape($ack[0]) . ')'; + } + } + + if ($key == 'current_check_attempt') { + $return = $results[$key] . '/' . $results['max_check_attempts']; + } + + if (preg_match('/_enabled/', $key) || $key == 'obsess_over_host') { + $return = $results[$key] ? __('Yes', 'npc') : __('No', 'npc'); + } + + if ($key == 'last_state_change' || $key == 'last_check' || $key == 'next_check') { + $format = read_config_option('npc_date_format') . ' ' . read_config_option('npc_time_format'); + $return = date($format, strtotime($results[$key])); + } + + if ($key == 'scheduled_downtime_depth' || $key == 'is_flapping' || $key == 'process_performance_data') { + $return = $results[$key] ? __('Yes', 'npc') : __('No', 'npc'); + } + + if ($return == '' || !$return) { + $return = __('N/A', 'npc'); + } + + return $return; + } } diff --git a/controllers/layout.php b/controllers/layout.php index 45396c4..77134da 100644 --- a/controllers/layout.php +++ b/controllers/layout.php @@ -1,87 +1,64 @@ drawCommonFrame($config['url_path'] . 'plugins/npc/npc.php?module=layout&action=drawLayout', $params); - } - - function drawLayout($params) { + function drawFrame($params) { $config = $params['config']; - $npc_base = $config['url_path'] . 'plugins/npc/js/'; - $npc_ext_base = $config['url_path'] . 'plugins/npc/js/ext/'; - $npc_css_base = $config['url_path'] . 'plugins/npc/css/'; - ?> - - - - - - - - + general_header(); - - - - - -
-
-
-
-
-
-
-
-
+ \n"; + + bottom_footer(); + } +} diff --git a/controllers/layoutDev.php b/controllers/layoutDev.php deleted file mode 100644 index d7f1735..0000000 --- a/controllers/layoutDev.php +++ /dev/null @@ -1,135 +0,0 @@ -drawCommonFrame($config['url_path'] . 'plugins/npc/npc.php?module=layoutDev&action=drawLayout', $params); - } - - function drawLayout($params) { - $config = $params['config']; - $npc_ext_base = $config['url_path'] . 'plugins/npc/js/ext/'; - $npc_plugins_base = $config['url_path'] . 'plugins/npc/js/src/plugins/'; - $npc_monitor_base = $config['url_path'] . 'plugins/npc/js/src/monitoring/'; - $npc_common_base = $config['url_path'] . 'plugins/npc/js/src/'; - $npc_css_base = $config['url_path'] . 'plugins/npc/css/'; - ?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
-
-
-
-
-
-
- 'l.logentry_data', 'instance_name' => 'i.instance_name'); - $where = '1 = 1'; + $params = array(); if ($this->searchString) { - $where = $this->searchClause($where, $fieldMap); + $where = $this->searchClause($where, $fieldMap, $params); } - $q = new Doctrine_Pager( - Doctrine_Query::create() - ->select('i.instance_name,' - .'l.*') - ->from('NpcLogentries l') - ->leftJoin('l.Instance i') - ->where("$where") - ->orderby( 'l.entry_time DESC, l.entry_time_usec DESC' ), - $this->currentPage, - $this->limit - ); + /* Get total count */ + $this->numRecords = db_fetch_cell_prepared('SELECT COUNT(*) + FROM npc_logentries l + LEFT JOIN npc_instances i ON l.instance_id = i.instance_id + WHERE ' . $where, + $params); + + $offset = ($this->currentPage - 1) * $this->limit; - $results = $this->flattenArray($q->execute(array(), Doctrine::HYDRATE_ARRAY)); + $results = db_fetch_assoc_prepared('SELECT i.instance_name, l.* + FROM npc_logentries l + LEFT JOIN npc_instances i ON l.instance_id = i.instance_id + WHERE ' . $where . ' + ORDER BY l.entry_time DESC, l.entry_time_usec DESC + LIMIT ?, ?', + array_merge($params, array($offset, $this->limit))); - // Set the total number of records - $this->numRecords = $q->getNumResults(); + $results = $this->flattenArray($results); $response['response']['value']['items'] = $results; $response['response']['value']['total_count'] = $this->numRecords; diff --git a/controllers/nagios.php b/controllers/nagios.php index c05c329..2128759 100644 --- a/controllers/nagios.php +++ b/controllers/nagios.php @@ -91,19 +91,15 @@ function getProcessInfoGrid() { * @return string json output */ function processInfo() { - $q = new Doctrine_Query(); - $q->select('ps.*')->from('NpcProgramstatus ps'); - - $results = $q->execute(array(), Doctrine::HYDRATE_ARRAY); + $results = db_fetch_assoc_prepared('SELECT ps.* + FROM npc_programstatus ps', array()); if (cacti_sizeof($results)) { - $q = new Doctrine_Query(); - $q->select('p.instance_id, p.program_version, max(p.processevent_id)') - ->from('NpcProcessevents p') - ->where('p.instance_id = ?', $results[0]['instance_id']) - ->groupby('p.program_version'); - - $version = $q->execute(array(), Doctrine::HYDRATE_ARRAY); + $version = db_fetch_assoc_prepared('SELECT p.instance_id, p.program_version, MAX(p.processevent_id) AS max_id + FROM npc_processevents p + WHERE p.instance_id = ? + GROUP BY p.program_version', + array($results[0]['instance_id'])); $results[0]['server_time'] = date('Y-m-d H:i:s'); if (isset($version[0])) { @@ -126,7 +122,7 @@ function processInfo() { * @return string */ function command($params) { - // Get the passed command + /* Get the passed command */ $cmd = $params['command']; $globalCommands = array( @@ -155,7 +151,7 @@ function command($params) { $nagios = new NagiosCmd; $args = array(); - // Do some sanity checking: + /* Do some sanity checking */ if (!read_config_option('npc_nagios_commands')) { $response = array('success' => false, 'msg' => __('Remote Commands must be enabled under console->Settings->NPC', 'npc')); @@ -172,23 +168,21 @@ function command($params) { return(json_encode($response)); } - // A quick hack to check that the user has permission to - // execute the command based on realm setting + /* Check that the user has permission to execute the command */ if (!api_plugin_user_realm_auth('npc1.php')) { $response = array('success' => false, 'msg' => __('You do not have permission to execute this command.', 'npc')); return(json_encode($response)); } - // Get the command definition + /* Get the command definition */ $commandDef = $nagios->getCommands($cmd); - // Build the args array + /* Build the args array */ foreach ($commandDef as $k => $v) { if (isset($params[$k])) { $value = $params[$k]; - // Checkboxes from EXT come as a string of either "true" or "false". - // These need to be set to 1 or 0 + /* Checkboxes from EXT come as a string of either "true" or "false". */ if ($value == 'true') { $value = 1; } @@ -198,13 +192,8 @@ function command($params) { } if ($k == 'comment') { - // Replace newline characters: $value = str_replace(array("\r", "\n"), '
', $value); - - // Replace html spaces $value = str_replace(" ", ' ', $value); - - // Strip any semicolons $value = str_replace(";", ' ', $value); } @@ -212,26 +201,25 @@ function command($params) { } } - // Build the command string + /* Build the command string */ if (!$nagios->setCommand($cmd, $args)) { $response = array('success' => false, 'msg' => $nagios->message); return(json_encode($response)); } - // Execute the command + /* Execute the command */ if (!$nagios->execute()) { $response = array('success' => false, 'msg' => $nagios->message); return(json_encode($response)); } - // Some forms require extra business logic like running another command. + /* Some forms require extra business logic */ if ($cmd == "SCHEDULE_HOSTGROUP_SVC_DOWNTIME" && $params['hosts'] == 'true') { $cmd = 'SCHEDULE_HOSTGROUP_HOST_DOWNTIME'; $nagios->setCommand($cmd, $args); $nagios->execute(); } - // Return success to the form return(json_encode(array('success' => true))); } @@ -243,40 +231,41 @@ function command($params) { * @return string json output */ function checkPerf($params) { - // Set the resolution in days to measure check performance. if (isset($params['resolution'])) { $resolution = $params['resolution']; } else { $resolution = 7; } - $q = new Doctrine_Query(); - $q->select('ROUND(MIN(hc.execution_time), 3) AS min_execution, - ROUND(MAX(hc.execution_time), 3) AS max_execution, - ROUND(AVG(hc.execution_time), 3) AS avg_execution, - ROUND(MIN(hc.latency), 3) AS min_latency, - ROUND(MAX(hc.latency), 3) AS max_latency, - ROUND(AVG(hc.latency), 3) AS avg_latency' - ); - $q->from('NpcHostchecks hc, NpcHosts h, NpcObjects o'); - $q->where('hc.host_object_id = o.object_id AND o.is_active = 1 AND hc.start_time > DATE_SUB(NOW(),INTERVAL ? DAY) ' - . 'AND hc.host_object_id = h.host_object_id AND h.active_checks_enabled = 1'); - - $hostPerf = $q->execute(array($resolution), Doctrine::HYDRATE_ARRAY); - - $q = new Doctrine_Query(); - $q->select('ROUND(MIN(sc.execution_time), 3) AS min_execution, - ROUND(MAX(sc.execution_time), 3) AS max_execution, - ROUND(AVG(sc.execution_time), 3) AS avg_execution, - ROUND(MIN(sc.latency), 3) AS min_latency, - ROUND(MAX(sc.latency), 3) AS max_latency, - ROUND(AVG(sc.latency), 3) AS avg_latency' - ); - $q->from('NpcServicechecks sc, NpcServices s, NpcObjects o'); - $q->where('sc.service_object_id = o.object_id AND o.is_active = 1 AND sc.start_time > DATE_SUB(NOW(),INTERVAL ? DAY) ' - . 'AND sc.service_object_id = s.service_object_id AND s.active_checks_enabled = 1'); - - $servicePerf = $q->execute(array($resolution), Doctrine::HYDRATE_ARRAY); + $hostPerf = db_fetch_assoc_prepared('SELECT + ROUND(MIN(hc.execution_time), 3) AS min_execution, + ROUND(MAX(hc.execution_time), 3) AS max_execution, + ROUND(AVG(hc.execution_time), 3) AS avg_execution, + ROUND(MIN(hc.latency), 3) AS min_latency, + ROUND(MAX(hc.latency), 3) AS max_latency, + ROUND(AVG(hc.latency), 3) AS avg_latency + FROM npc_hostchecks hc, npc_hosts h, npc_objects o + WHERE hc.host_object_id = o.object_id + AND o.is_active = 1 + AND hc.start_time > DATE_SUB(NOW(), INTERVAL ? DAY) + AND hc.host_object_id = h.host_object_id + AND h.active_checks_enabled = 1', + array($resolution)); + + $servicePerf = db_fetch_assoc_prepared('SELECT + ROUND(MIN(sc.execution_time), 3) AS min_execution, + ROUND(MAX(sc.execution_time), 3) AS max_execution, + ROUND(AVG(sc.execution_time), 3) AS avg_execution, + ROUND(MIN(sc.latency), 3) AS min_latency, + ROUND(MAX(sc.latency), 3) AS max_latency, + ROUND(AVG(sc.latency), 3) AS avg_latency + FROM npc_servicechecks sc, npc_services s, npc_objects o + WHERE sc.service_object_id = o.object_id + AND o.is_active = 1 + AND sc.start_time > DATE_SUB(NOW(), INTERVAL ? DAY) + AND sc.service_object_id = s.service_object_id + AND s.active_checks_enabled = 1', + array($resolution)); $output = array( array_merge(array('name' => __('Service Check Execution Time', 'npc')), array_slice($servicePerf[0], 0, 3)), @@ -300,13 +289,10 @@ function checkPerf($params) { * formatProcessInfo * * Formats the process info results for display. - * This is a workaround for some of the limitations of - * EXT property grid. * * @return string The formatted results */ function formatProcessInfo($key, $results) { - // Set the default return value $return = $results[$key]; $toggle = array( @@ -322,12 +308,8 @@ function formatProcessInfo($key, $results) { 'process_performance_data' ); - if (in_array($key, $toggle)) { - if($results[$key]) { - $return = ''; - } else { - $return = ''; - } + if (in_array($key, $toggle, true)) { + $return = $results[$key] ? __('Yes', 'npc') : __('No', 'npc'); } if ($key == 'program_start_time' || $key == 'status_update_time' || $key == 'last_command_check' || $key == 'last_log_rotation' || $key == 'program_end_time') { @@ -348,4 +330,3 @@ function formatProcessInfo($key, $results) { return($return); } } - diff --git a/controllers/notifications.php b/controllers/notifications.php index 09ef65f..095b09f 100644 --- a/controllers/notifications.php +++ b/controllers/notifications.php @@ -18,7 +18,7 @@ * Notifications controller class * * Notifications controller provides functionality, such as building the - * Doctrine queries and formatting output. + * queries and formatting output. * * @package npc * @subpackage npc.controllers @@ -35,30 +35,34 @@ class NpcNotificationsController extends Controller { function getNotifications() { $where = '1 = 1'; + $params = array(); if ($this->id) { - $where = sprintf("n.object_id = %d", $this->id); + $where = 'n.object_id = ?'; + $params[] = $this->id; } - $q = new Doctrine_Pager( - Doctrine_Query::create() - ->select('i.instance_name,' - .'o.name1 AS host_name,' - .'o.name2 AS service_description,' - .'n.*') - ->from('NpcNotifications n') - ->leftJoin('n.Object o') - ->leftJoin('n.Instance i') - ->where("$where") - ->orderby( 'n.start_time DESC, n.start_time_usec DESC' ), - $this->currentPage, - $this->limit - ); + /* Get total count */ + $this->numRecords = db_fetch_cell_prepared('SELECT COUNT(*) + FROM npc_notifications n + LEFT JOIN npc_objects o ON n.object_id = o.object_id + LEFT JOIN npc_instances i ON n.instance_id = i.instance_id + WHERE ' . $where, + $params); - $results = $q->execute(array(), Doctrine::HYDRATE_ARRAY); + $offset = ($this->currentPage - 1) * $this->limit; - // Set the total number of records - $this->numRecords = $q->getNumResults(); + $results = db_fetch_assoc_prepared('SELECT i.instance_name, + o.name1 AS host_name, + o.name2 AS service_description, + n.* + FROM npc_notifications n + LEFT JOIN npc_objects o ON n.object_id = o.object_id + LEFT JOIN npc_instances i ON n.instance_id = i.instance_id + WHERE ' . $where . ' + ORDER BY n.start_time DESC, n.start_time_usec DESC + LIMIT ?, ?', + array_merge($params, array($offset, $this->limit))); return($this->jsonOutput($results)); } diff --git a/controllers/servicegroups.php b/controllers/servicegroups.php index ce16296..6ea210d 100644 --- a/controllers/servicegroups.php +++ b/controllers/servicegroups.php @@ -1,366 +1,228 @@ - * @copyright Copyright (c) 2007 - * @link http://trac2.assembla.com/npc - * @package npc - * @subpackage npc.controllers - * @since NPC 2.0 - * @version $Id$ - */ - -require_once("include/auth.php"); -require_once("plugins/npc/controllers/comments.php"); - -/** - * Servicegroups controller class - * - * Servicegroups controller provides functionality, such as building the - * Doctrine queries and formatting output. - * - * @package npc - * @subpackage npc.controllers - */ -class NpcServicegroupsController extends Controller { - - /** - * A host status cache - * - * @var array - * @access private - */ - private $hostStatusCache = array(); - - - /** - * getHostStatusPortlet - * - * Returns host status counts by servicegroup. - * - * @return string json output - */ - function getHostStatusPortlet() { - - $startTime = $this->getTime(); - - // Initialize the output array - $output = array(); - - // Initialize the hosts array - $hosts = array(); - - $fields = array('servicegroup_object_id', - 'alias', - 'instance_id'); - - // Combine servicegroup/service/host etc. into a single record - $results = $this->setupResultsArray(); - - // Loop through the results array and build an output array - // that includes a single record per servicegroup - // and the number of crit, warn , ok services within - // that servicegroup. - for ($i = 0; $i < count($results); $i++) { - $sg = $results[$i]['servicegroup_object_id']; - if(!isset($output[$sg])) { - $output[$sg] = array('down' => 0, - 'unreachable' => 0, - 'up' => 0, - 'pending' => 0); - } - if (!isset($hosts[$sg][$results[$i]['host_name']])) { - $hostState = $this->getServicegroupMemberHoststatus($results[$i]['host_name']); - $output[$sg][$this->hostState[$hostState]]++; - $hosts[$sg][$results[$i]['host_name']] = 1; - } - foreach ($results[$i] as $key => $val) { - if (in_array($key, $fields)) { - $output[$sg][$key] = $val; - } - } - } - - // Set the total number of records - $this->numRecords = count($output); - - // Implement paging by slicing the output array - $output = array_slice($output, $this->start, $this->limit); - - $response['response']['value']['items'] = $output; - $response['response']['value']['total_count'] = $this->numRecords; - $response['response']['value']['version'] = 1; - - $this->logger('debug', get_class($this), 'getHostStatusPortlet', "Method execution time: ".sprintf("%01.2f", ($this->getTime() - $startTime)). " seconds"); - - return(json_encode($response)); - } - - /** - * getServicegroupServiceStatus - * - * Returns service status counts by servicegroup. - * - * @return string json output - */ - function getServicegroupServiceStatus() { - - $startTime = $this->getTime(); - - // Initialize the output array - $output = array(); - - $fields = array('servicegroup_object_id', - 'alias', - 'instance_id'); - - // Combine servicegroup/service/host etc. into a single record - $results = $this->setupResultsArray(); - - for ($i = 0; $i < count($results); $i++) { - $sg = $results[$i]['servicegroup_object_id']; - if(!isset($output[$sg])) { - $output[$sg] = array('critical' => 0, - 'warning' => 0, - 'unknown' => 0, - 'ok' => 0, - 'pending' => 0); - } - foreach ($results[$i] as $key => $val) { - if ($key == 'current_state') { - $output[$sg][$this->serviceState[$val]]++; - } else if(in_array($key, $fields)) { - $output[$sg][$key] = $val; - } - } - } - - // Set the total number of records - $this->numRecords = count($output); - - // Implement paging by slicing the output array - $output = array_slice($output, $this->start, $this->limit); - - $response['response']['value']['items'] = $output; - $response['response']['value']['total_count'] = $this->numRecords; - $response['response']['value']['version'] = 1; - - $this->logger('debug', get_class($this), 'getServicegroupServiceStatus', "Method execution time: ".sprintf("%01.2f", ($this->getTime() - $startTime)). " seconds"); - - return(json_encode($response)); - } - - /** - * getOverview - * - * Returns all hosts by servicegroup. Used to populate - * the Servicegroup Grid screen. - * - * @return string json output - */ - function getOverview() { - - $startTime = $this->getTime(); - - $fields = array('servicegroup_object_id', - 'alias', - 'instance_id', - 'host_name'); - - // Initialize the output array - $output = array(); - - // Combine servicegroup/service/host etc. into a single record - $results = $this->setupResultsArray(); - - // Loop through the results array and build an output array - // that includes a single record per host with the servicegroup - // and the number of crit, warn , ok services within - // that servicegroup. - for ($i = 0; $i < count($results); $i++) { - $sg = $results[$i]['servicegroup_object_id']; - $host = $results[$i]['host_name']; - $hostState = $this->getServicegroupMemberHoststatus($host); - if(!isset($temp[$sg][$host])) { - $temp[$sg][$host] = array('host_state' => $hostState, - 'critical' => 0, - 'warning' => 0, - 'unknown' => 0, - 'ok' => 0, - 'pending' => 0); - } - foreach ($results[$i] as $key => $val) { - if ($key == 'current_state') { - $temp[$sg][$host][$this->serviceState[$val]]++; - } else if(in_array($key, $fields)) { - $temp[$sg][$host][$key] = $val; - } - } - } - - $x = 0; - foreach ($temp as $i => $s) { - foreach ($s as $h => $v) { - foreach ($v as $key => $val) { - $output[$x][$key] = $val; - } - $x++; - } - } - - // Set the total number of records - $this->numRecords = count($output); - - // Implement paging by slicing the output array - $output = array_slice($output, $this->start, $this->limit); - - $this->logger('debug', get_class($this), 'getOverview', "Method execution time: ".sprintf("%01.2f", ($this->getTime() - $startTime)). " seconds"); - - return($this->jsonOutput($output)); - } - - /** - * getHostSummary - * - * Returns host status by servicegroup - * - * @return string json output - */ - function getHostSummary() { - $status = $this->getServicegroupMemberHoststatus('workstation'); - - print_r($status); - exit; - } - - /** - * getServices - * - * Returns all services by servicegroup. Used to populate - * the Servicegroup Grid screen. - * - * @return string json output - */ - function getServices() { - - $startTime = $this->getTime(); - - $results = $this->setupResultsArray(); - - $comments = new NpcCommentsController; - - $services = $this->flattenArray($results); - - for ($i = 0; $i < count($services); $i++) { - if ($services[$i]['problem_has_been_acknowledged']) { - $services[$i]['acknowledgement'] = $comments->getAck($services[$i]['service_object_id']); - } - // Add the last comment to the array - $services[$i]['comment'] = $comments->getLastComment($services[$i]['service_object_id']); - } - - // Set the total number of records - $this->numRecords = count($services); - - // Implement paging by slicing the output array - $services = array_slice($services, $this->start, $this->limit); - - $this->logger('debug', get_class($this), 'getServices', "Method execution time: ".sprintf("%01.2f", ($this->getTime() - $startTime)). " seconds"); - - return($this->jsonOutput($services)); - } - - function getServicegroupMemberHoststatus($hostname) { - - $startTime = $this->getTime(); - - if(isset($this->hostStatusCache[$hostname])) { - return($this->hostStatusCache[$hostname]); - } - - $q = new Doctrine_Query(); - $q->select('hs.current_state') - ->from('NpcHoststatus hs, NpcHosts h') - ->where('hs.host_object_id = h.host_object_id AND h.display_name = ?', $hostname); - - $results = $q->execute(array(), Doctrine::HYDRATE_ARRAY); - - $this->hostStatusCache[$hostname] = $results[0]['current_state']; - - $this->logger('debug', get_class($this), 'getServicegroupMemberHoststatus', "Method execution time: ".sprintf("%01.2f", ($this->getTime() - $startTime)). " seconds"); - - return($this->hostStatusCache[$hostname]); - } - - function getServicegroups() { - - $startTime = $this->getTime(); - - $where = '1 = 1'; - - if ($this->id) { - $where = "sg.servicegroup_object_id = " . $this->id; - } - - // Maps searchable fields passed in from the client - $fieldMap = array('service_description' => 'o2.name2', - 'host_name' => 'o2.name1', - 'alias' => 'sg.alias', - 'output' => 'ss.output'); - - if ($this->searchString) { - $where .= $this->searchClause(null, $fieldMap); - } - - $q = new Doctrine_Query(); - $q->select('i.instance_name,' - .'o1.name1 AS servicegroup_name,' - .'o2.name1 AS host_name,' - .'o2.name2 AS service_description,' - .'ss.*,' - .'sg.*') - ->from('NpcServicegroups sg') - ->innerJoin('sg.ServicegroupMembers sgm') - ->innerJoin('sg.Servicestatus ss ON sgm.service_object_id = ss.service_object_id') - ->innerJoin('sg.Object o1') - ->innerJoin('ss.Object o2') - ->innerJoin('sg.Instance i') - ->where("$where") - ->orderBy('servicegroup_name ASC, host_name ASC, service_description ASC'); - - $results = $q->execute(array(), Doctrine::HYDRATE_ARRAY); +/* + +-------------------------------------------------------------------------+ + | Nagios Plugin for Cacti | + | | + | Copyright (C) 2007 Billy Gunn (billy@gunn.org) | + | Copyright (C) 2004-2026 The Cacti Group | + +-------------------------------------------------------------------------+ + | Cacti and Nagios are the copyright of their respective owners. | + +-------------------------------------------------------------------------+ +*/ + +require_once('include/auth.php'); +require_once('plugins/npc/controllers/comments.php'); - $this->logger('debug', get_class($this), 'getServicegroups', "Method execution time: ".sprintf("%01.2f", ($this->getTime() - $startTime)). " seconds"); - - return($results); - } - - /** - * setupResultsArray - * - * A utility method to handle some common formatting tasks. - * - * @return array - */ - function setupResultsArray() { - - // Get the servicegroups - $results = $this->getServicegroups(); - - // Flatten the 1st level of nested arrays - $results = $this->flattenArray($results); - - // Combine servicegroup/service/host etc. into a single record. - $results = $this->flattenNestedArray($results); - - return($results); - } +class NpcServicegroupsController extends Controller { + private $hostStatusCache = array(); + + function getHostStatusPortlet() { + $output = array(); + $hosts = array(); + $fields = array('servicegroup_object_id', 'alias', 'instance_id'); + + $results = $this->setupResultsArray(); + + for ($i = 0; $i < count($results); $i++) { + $sg = $results[$i]['servicegroup_object_id']; + if (!isset($output[$sg])) { + $output[$sg] = array('down' => 0, 'unreachable' => 0, 'up' => 0, 'pending' => 0); + } + if (!isset($hosts[$sg][$results[$i]['host_name']])) { + $hostState = $this->getServicegroupMemberHoststatus($results[$i]['host_name']); + if (isset($this->hostState[$hostState])) { + $output[$sg][$this->hostState[$hostState]]++; + } + $hosts[$sg][$results[$i]['host_name']] = 1; + } + foreach ($results[$i] as $key => $val) { + if (in_array($key, $fields, true)) { + $output[$sg][$key] = $val; + } + } + } + + $this->numRecords = count($output); + $output = array_slice($output, $this->start, $this->limit); + + $response = array( + 'response' => array( + 'value' => array( + 'items' => $output, + 'total_count' => $this->numRecords, + 'version' => 1, + ) + ) + ); + + return json_encode($response); + } + + function getServicegroupServiceStatus() { + $output = array(); + $fields = array('servicegroup_object_id', 'alias', 'instance_id'); + + $results = $this->setupResultsArray(); + + for ($i = 0; $i < count($results); $i++) { + $sg = $results[$i]['servicegroup_object_id']; + if (!isset($output[$sg])) { + $output[$sg] = array('critical' => 0, 'warning' => 0, 'unknown' => 0, 'ok' => 0, 'pending' => 0); + } + foreach ($results[$i] as $key => $val) { + if ($key == 'current_state' && isset($this->serviceState[$val])) { + $output[$sg][$this->serviceState[$val]]++; + } elseif (in_array($key, $fields, true)) { + $output[$sg][$key] = $val; + } + } + } + + $this->numRecords = count($output); + $output = array_slice($output, $this->start, $this->limit); + + $response = array( + 'response' => array( + 'value' => array( + 'items' => $output, + 'total_count' => $this->numRecords, + 'version' => 1, + ) + ) + ); + + return json_encode($response); + } + + function getOverview() { + $fields = array('servicegroup_object_id', 'alias', 'instance_id', 'host_name'); + $output = array(); + $temp = array(); + + $results = $this->setupResultsArray(); + + for ($i = 0; $i < count($results); $i++) { + $sg = $results[$i]['servicegroup_object_id']; + $host = $results[$i]['host_name']; + $hostState = $this->getServicegroupMemberHoststatus($host); + if (!isset($temp[$sg][$host])) { + $temp[$sg][$host] = array( + 'host_state' => $hostState, + 'critical' => 0, + 'warning' => 0, + 'unknown' => 0, + 'ok' => 0, + 'pending' => 0 + ); + } + foreach ($results[$i] as $key => $val) { + if ($key == 'current_state' && isset($this->serviceState[$val])) { + $temp[$sg][$host][$this->serviceState[$val]]++; + } elseif (in_array($key, $fields, true)) { + $temp[$sg][$host][$key] = $val; + } + } + } + + $x = 0; + foreach ($temp as $i => $s) { + foreach ($s as $h => $v) { + foreach ($v as $key => $val) { + $output[$x][$key] = $val; + } + $x++; + } + } + + $this->numRecords = count($output); + $output = array_slice($output, $this->start, $this->limit); + + return $this->jsonOutput($output); + } + + function getHostSummary() { + /* Placeholder; original had debug print_r/exit */ + return $this->jsonOutput(array()); + } + + function getServices() { + $results = $this->setupResultsArray(); + $comments = new NpcCommentsController; + $services = $this->flattenArray($results); + + for ($i = 0; $i < count($services); $i++) { + if ($services[$i]['problem_has_been_acknowledged']) { + $services[$i]['acknowledgement'] = $comments->getAck($services[$i]['service_object_id']); + } + $services[$i]['comment'] = $comments->getLastComment($services[$i]['service_object_id']); + } + + $this->numRecords = count($services); + $services = array_slice($services, $this->start, $this->limit); + + return $this->jsonOutput($services); + } + + function getServicegroupMemberHoststatus($hostname) { + if (isset($this->hostStatusCache[$hostname])) { + return $this->hostStatusCache[$hostname]; + } + + $result = db_fetch_row_prepared( + 'SELECT hs.current_state + FROM npc_hoststatus hs + INNER JOIN npc_hosts h ON hs.host_object_id = h.host_object_id + WHERE h.display_name = ?', + array($hostname)); + + $this->hostStatusCache[$hostname] = cacti_sizeof($result) ? $result['current_state'] : '0'; + + return $this->hostStatusCache[$hostname]; + } + + function getServicegroups() { + $fieldMap = array( + 'servicegroup_name' => 'o1.name1', + 'host_name' => 'o2.name1', + 'service_description' => 'o2.name2', + 'output' => 'ss.output' + ); + $params = array(); + $where = '1 = 1'; + + if ($this->id) { + $where .= ' AND sg.servicegroup_object_id = ?'; + $params[] = intval($this->id); + } + + if ($this->searchString) { + $where = $this->searchClause($where, $fieldMap, $params); + } + + return db_fetch_assoc_prepared( + 'SELECT DISTINCT i.instance_name, + o1.name1 AS servicegroup_name, + o2.name1 AS host_name, + o2.name2 AS service_description, + ss.*, + sg.* + FROM npc_servicegroups sg + INNER JOIN npc_servicegroup_members sgm ON sg.servicegroup_id = sgm.servicegroup_id + INNER JOIN npc_servicestatus ss ON sgm.service_object_id = ss.service_object_id + INNER JOIN npc_objects o1 ON sg.servicegroup_object_id = o1.object_id + INNER JOIN npc_objects o2 ON ss.service_object_id = o2.object_id + INNER JOIN npc_instances i ON sg.instance_id = i.instance_id + WHERE ' . $where . ' + ORDER BY o1.name1 ASC, o2.name1 ASC, o2.name2 ASC', + $params); + } + + function setupResultsArray() { + $results = $this->getServicegroups(); + $results = $this->flattenArray($results); + $results = $this->flattenNestedArray($results); + + return $results; + } } - - - diff --git a/controllers/services.php b/controllers/services.php index 508daf4..c0a86b7 100644 --- a/controllers/services.php +++ b/controllers/services.php @@ -1,478 +1,372 @@ - * @copyright Copyright (c) 2007 - * @link http://trac2.assembla.com/npc - * @package npc - * @subpackage npc.controllers - * @since NPC 2.0 - * @version $Id$ - */ - -require_once($config["base_path"]."/plugins/npc/controllers/comments.php"); -require_once($config["base_path"]."/plugins/npc/controllers/downtime.php"); - -/** - * Services controller class - * - * Services controller provides functionality, such as building the - * Doctrine queries and formatting output. - * - * @package npc - * @subpackage npc.controllers - */ +/* + +-------------------------------------------------------------------------+ + | Nagios Plugin for Cacti | + | | + | Copyright (C) 2007 Billy Gunn (billy@gunn.org) | + | Copyright (C) 2004-2026 The Cacti Group | + +-------------------------------------------------------------------------+ + | Cacti and Nagios are the copyright of their respective owners. | + +-------------------------------------------------------------------------+ +*/ + +require_once($config['base_path'] . '/plugins/npc/controllers/comments.php'); +require_once($config['base_path'] . '/plugins/npc/controllers/downtime.php'); + class NpcServicesController extends Controller { - /** - * getServices - * - * Gets and formats services for output. - * - * @return string json output - */ - function getServices() { - - $services = $this->services(); - - $comments = new NpcCommentsController; - $downtime = new NpcDowntimeController; - - for ($i = 0; $i < count($services); $i++) { - - foreach($services[$i] as $k => $v) { - if (is_array($v)) { - $services[$i] = array_merge($services[$i], $v); - unset($services[$i][$k]); - } - } - - unset($services[$i]['Host']); - if ($services[$i]['problem_has_been_acknowledged']) { - $services[$i]['acknowledgement'] = $comments->getAck($services[$i]['service_object_id']); - } - - // Add the last comment to the array - $services[$i]['comment'] = $comments->getLastComment($services[$i]['service_object_id']); - - // Set the in_downtime bit - $services[$i]['in_downtime'] = 0; - if ($downtime->inDowntime($services[$i]['service_object_id'])) { - $services[$i]['in_downtime'] = 1; - } - } - - $response['response']['value']['items'] = $services; - $response['response']['value']['total_count'] = $this->numRecords; - $response['response']['value']['version'] = 1; - - return(json_encode($response)); - } - - /** - * getStateInfo - * - * Gets and formats service state information - * - * @return string json output - */ - function getStateInfo() { - - require_once("plugins/npc/controllers/hostgroups.php"); - $obj = new NpcHostgroupsController; - $hg = $obj->setupResultsArray(); - // $results[$i]['hostgroup_object_id'] - - $fields = array( - 'current_state', - 'output', - 'perfdata', - 'notes', - 'last_state_change', - 'check_command', - 'command_line', - 'host_address', - 'Host Groups', - 'current_check_attempt', - 'last_check', - 'next_check', - 'event_handler', - 'latency', - 'execution_time', - 'is_flapping', - 'scheduled_downtime_depth', - 'process_performance_data', - 'active_checks_enabled', - 'passive_checks_enabled', - 'event_handler_enabled', - 'flap_detection_enabled', - 'notifications_enabled', - 'obsess_over_service' - ); - - $service = $this->services(); - - $results = $this->flattenArray($service); - - $hostgroups = array(); - foreach ($hg as $i => $a) { - if ($a['host_name'] == $results[0]['host_name']) { - $hostgroups[] = $a['hostgroup_name']; - } - } - - $x = 0; - foreach ($fields as $key) { - if ($key == 'Host Groups') { - $name = 'Host Groups'; - $value = implode(", ", array_unique($hostgroups)); - } else { - $name = $this->columnAlias[$key]; - $value = $this->formatStateInfo($key, $results[0]); - } - - $output[$x] = array('name' => $name, 'value' => $value); - $x++; - } - - return($this->jsonOutput($output)); - } - - /** - * summary - * - * Returns a summary of the state of all services. - * - * @return string json output - */ - function summary() { - - $status = array('critical' => 0, - 'warning' => 0, - 'unknown' => 0, - 'ok' => 0, - 'pending' => 0); - - $q = new Doctrine_Query(); - $q->select('ss.current_state') - ->from('NpcServicestatus ss') - ->leftJoin('ss.Service s') - ->where('s.config_type = ?', $this->config_type); - - $services = $q->execute(array(), Doctrine::HYDRATE_ARRAY); - - for ($i = 0; $i < count($services); $i++) { - $status[$this->serviceState[$services[$i]['current_state']]]++; - } - - return($this->jsonOutput($status)); - } - - /** - * getServiceStatesByHost - * - * A utility method to simply return the state of every service belonging - * to the specified host. - * - * @return array list of all services with status - */ - function getServiceStatesByHost($host_object_id) { - - $q = new Doctrine_Query(); - $q->select('ss.current_state') - ->from('NpcServicestatus ss, NpcServices s') - ->where('ss.service_object_id = s.service_object_id AND s.host_object_id = ?', $host_object_id); - - $results = $q->execute(array(), Doctrine::HYDRATE_ARRAY); - - return($results); - } - - /** - * services - * - * Retrieves all services along with status information - * - * @return array list of all services with status - */ - function services($id=null, $where=null) { - - // Maps searchable fields passed in from the client - $fieldMap = array('service_description' => 'o.name2', - 'host_name' => 'o.name1', - 'host_alias' => 'h.alias', - 'notes' => 's.notes', - 'output' => 'ss.output'); - - - // Build the where clause - if ($where) { - $where .= ' AND '; - } - - $where .= " ss.current_state in (" . $this->stringToState[$this->state] . ") AND s.config_type = " . $this->config_type; - - if (isset($this->unhandled)) { - $where .= " AND ss.problem_has_been_acknowledged = 0 "; - } - - if ($this->id || $id) { - $where .= sprintf(" AND s.service_object_id = %d", is_null($id) ? $this->id : $id);; - } + function getServices() { + $services = $this->services(); + + $comments = new NpcCommentsController; + $downtime = new NpcDowntimeController; + + for ($i = 0; $i < count($services); $i++) { + foreach ($services[$i] as $k => $v) { + if (is_array($v)) { + $services[$i] = array_merge($services[$i], $v); + unset($services[$i][$k]); + } + } + + unset($services[$i]['Host']); + + if ($services[$i]['problem_has_been_acknowledged']) { + $services[$i]['acknowledgement'] = $comments->getAck($services[$i]['service_object_id']); + } + + $services[$i]['comment'] = $comments->getLastComment($services[$i]['service_object_id']); + + $services[$i]['in_downtime'] = 0; + if ($downtime->inDowntime($services[$i]['service_object_id'])) { + $services[$i]['in_downtime'] = 1; + } + } + + $response = array( + 'response' => array( + 'value' => array( + 'items' => $services, + 'total_count' => $this->numRecords, + 'version' => 1, + ) + ) + ); + + return json_encode($response); + } + + function getStateInfo() { + require_once('plugins/npc/controllers/hostgroups.php'); + $obj = new NpcHostgroupsController; + $hg = $obj->setupResultsArray(); + + $fields = array( + 'current_state', 'output', 'perfdata', 'notes', + 'last_state_change', 'check_command', 'command_line', + 'host_address', 'Host Groups', 'current_check_attempt', + 'last_check', 'next_check', 'event_handler', 'latency', + 'execution_time', 'is_flapping', 'scheduled_downtime_depth', + 'process_performance_data', 'active_checks_enabled', + 'passive_checks_enabled', 'event_handler_enabled', + 'flap_detection_enabled', 'notifications_enabled', + 'obsess_over_service' + ); + + $service = $this->services(); + $results = $this->flattenArray($service); + + $hostgroups = array(); + foreach ($hg as $i => $a) { + if ($a['host_name'] == $results[0]['host_name']) { + $hostgroups[] = $a['hostgroup_name']; + } + } + + $output = array(); + $x = 0; + foreach ($fields as $key) { + if ($key == 'Host Groups') { + $name = __('Host Groups', 'npc'); + $value = implode(', ', array_unique($hostgroups)); + } else { + $name = $this->columnAlias[$key]; + $value = $this->formatStateInfo($key, $results[0]); + } + $output[$x] = array('name' => $name, 'value' => $value); + $x++; + } + + return $this->jsonOutput($output); + } + + function summary() { + $status = array( + 'critical' => 0, + 'warning' => 0, + 'unknown' => 0, + 'ok' => 0, + 'pending' => 0 + ); + + $services = db_fetch_assoc_prepared('SELECT ss.current_state + FROM npc_servicestatus ss + LEFT JOIN npc_services s ON ss.service_object_id = s.service_object_id + WHERE s.config_type = ?', + array($this->config_type)); + + for ($i = 0; $i < count($services); $i++) { + $state_key = $services[$i]['current_state']; + if (isset($this->serviceState[$state_key])) { + $status[$this->serviceState[$state_key]]++; + } + } + + return $this->jsonOutput($status); + } + + function getServiceStatesByHost($host_object_id) { + return db_fetch_assoc_prepared('SELECT ss.current_state + FROM npc_servicestatus ss + INNER JOIN npc_services s ON ss.service_object_id = s.service_object_id + WHERE s.host_object_id = ?', + array($host_object_id)); + } + + function services($id = null, $where = null) { + $fieldMap = array( + 'service_description' => 'o.name2', + 'host_name' => 'o.name1', + 'host_alias' => 'h.alias', + 'notes' => 's.notes', + 'output' => 'ss.output' + ); + + $params = array(); + + if ($where) { + $where .= ' AND '; + } else { + $where = ''; + } + + $states = $this->stringToState[$this->state]; + $state_list = implode(',', array_map('intval', explode(',', $states))); + $where .= 'ss.current_state IN (' . $state_list . ')'; + $where .= ' AND s.config_type = ?'; + $params[] = $this->config_type; + + if (isset($this->unhandled)) { + $where .= ' AND ss.problem_has_been_acknowledged = 0'; + } + + $svc_id = $this->id ? $this->id : $id; + if ($svc_id) { + $where .= ' AND s.service_object_id = ?'; + $params[] = intval($svc_id); + } if (isset($this->hostgroup)) { - $where .= sprintf(" AND hg.alias = '%s'", $this->hostgroup); + $where .= ' AND hg.alias = ?'; + $params[] = $this->hostgroup; } - if ($this->searchString) { - $where = $this->searchClause($where, $fieldMap); - } + if ($this->searchString) { + $where = $this->searchClause($where, $fieldMap, $params); + } + $orderBy = 'o.name1 ASC, o.name2 ASC'; if ($this->sort) { - $orderBy = $this->sort . ' ' . $this->dir; + $allowed_sorts = array( + 'instance_name', 'host_name', 'service_description', 'host_alias', + 'host_address', 'current_state', 'last_check', 'output', + 'last_state_change' + ); + if (in_array($this->sort, $allowed_sorts, true)) { + $dir = ($this->dir == 'DESC') ? 'DESC' : 'ASC'; + $orderBy = $this->sort . ' ' . $dir; + } + } + + /* Total count */ + $this->numRecords = db_fetch_cell_prepared( + 'SELECT COUNT(*) + FROM npc_servicestatus ss + LEFT JOIN npc_objects o ON ss.service_object_id = o.object_id + LEFT JOIN npc_services s ON ss.service_object_id = s.service_object_id + LEFT JOIN npc_hosts h ON s.host_object_id = h.host_object_id + LEFT JOIN npc_hostgroup_members hgm ON h.host_object_id = hgm.host_object_id + LEFT JOIN npc_hostgroups hg ON hgm.hostgroup_id = hg.hostgroup_id + LEFT JOIN npc_instances i ON s.instance_id = i.instance_id + WHERE ' . $where, + $params); + + $offset = ($this->currentPage - 1) * $this->limit; + + $services = db_fetch_assoc_prepared( + 'SELECT i.instance_name, + s.host_object_id, + s.notes, + s.notes_url, + s.action_url, + s.icon_image, + s.icon_image_alt, + h.alias AS host_alias, + h.address AS host_address, + h.icon_image AS host_icon_image, + h.icon_image_alt AS host_icon_image_alt, + h.host_object_id, + o.name1 AS host_name, + o.name2 AS service_description, + sg.local_graph_id, + ss.* + FROM npc_servicestatus ss + LEFT JOIN npc_objects o ON ss.service_object_id = o.object_id + LEFT JOIN npc_services s ON ss.service_object_id = s.service_object_id + LEFT JOIN npc_hosts h ON s.host_object_id = h.host_object_id + LEFT JOIN npc_hostgroup_members hgm ON h.host_object_id = hgm.host_object_id + LEFT JOIN npc_hostgroups hg ON hgm.hostgroup_id = hg.hostgroup_id + LEFT JOIN npc_instances i ON s.instance_id = i.instance_id + LEFT JOIN npc_service_graphs sg ON ss.service_object_id = sg.service_object_id + WHERE ' . $where . ' + ORDER BY ' . $orderBy . ' + LIMIT ?, ?', + array_merge($params, array($offset, $this->limit))); + + return $services; + } + + function getPerfData($id = null, $host = null, $service = null) { + $id = $this->id ? $this->id : $id; + + if (!$host) { + $check_id = db_fetch_cell_prepared( + 'SELECT MAX(servicecheck_id) FROM npc_servicechecks WHERE service_object_id = ?', + array($id)); } else { - $orderBy = 'host_name ASC, service_description ASC'; + $check_id = db_fetch_cell_prepared( + 'SELECT MAX(n.servicecheck_id) + FROM npc_servicechecks n + INNER JOIN npc_objects o ON o.object_id = n.service_object_id + WHERE o.is_active = 1 AND o.name1 = ? AND o.name2 = ?', + array($host, $service)); } - $q = new Doctrine_Pager( - Doctrine_Query::create() - ->select('i.instance_name,' - .'s.host_object_id,' - .'s.notes,' - .'s.notes_url,' - .'s.action_url,' - .'s.icon_image,' - .'s.icon_image_alt,' - .'h.alias AS host_alias,' - .'h.address AS host_address,' - .'h.icon_image AS host_icon_image,' - .'h.icon_image_alt AS host_icon_image_alt,' - .'h.host_object_id,' - .'hg.hostgroup_id,' - .'o.name1 AS host_name,' - .'o.name2 AS service_description,' - .'g.local_graph_id,' - .'ss.*') - ->from('NpcServicestatus ss') - ->leftJoin('ss.Object o') - ->leftJoin('ss.Service s') - ->leftJoin('s.Host h') - ->leftJoin('h.Hostgroup hg') - ->leftJoin('ss.Instance i') - ->leftJoin('ss.Graph g') - ->where($where) - ->orderby($orderBy), - $this->currentPage, - $this->limit - ); - - $services = $q->execute(array(), Doctrine::HYDRATE_ARRAY); - - // Set the total number of records - $this->numRecords = $q->getNumResults(); - - return($services); - } - - /** - * Returns the last perfdata entry for a particular service - * - * @return array - */ - function getPerfData($id=null, $host=null, $service=null) { - - $id = $this->id ? $this->id : $id; - - - // Get the last update - if (!$host) { - $q = new Doctrine_Query(); - $q->select('max(n.servicecheck_id) AS id') - ->from('NpcServicechecks n') - ->where('n.service_object_id = ?', $id); - $id = $q->execute(); - } else { - $q = new Doctrine_Query(); - $q->select('max(n.servicecheck_id) AS id') - ->from('NpcServicechecks n, NpcObjects o') - ->where('o.is_active = 1 AND o.object_id = n.service_object_id') - ->andWhere('o.name1 = ?', $host) - ->andWhere('o.name2 = ?', $service); - $id = $q->execute(); - } - - // Get the perf data - $q = new Doctrine_Query(); - $q->select('n.*') - ->from('NpcServicechecks n') - ->where('n.servicecheck_id = ?', $id[0]['id']); - - return($q->execute(array(), Doctrine::HYDRATE_ARRAY)); - } - - /** - * Returns the performance history for the specified service and period - * - * @return array - */ - function getPerfHistory($host, $service, $begin, $end=null) { - - $q = new Doctrine_Query(); - $q->select('end_time, perfdata') - ->from('NpcServicechecks n, NpcObjects o') - ->where('o.is_active = 1 AND o.object_id = n.service_object_id') - ->andWhere('o.name1 = ?', $host) - ->andWhere('o.name2 = ?', $service) - ->andWhere('n.end_time >= ?', $begin); - - if ($end) { - $q->andWhere('n.end_time <= ?', $end); - } - - return($q->execute(array(), Doctrine::HYDRATE_ARRAY)); - } - - - /** - * listServivcesCli - * - * Returns all services and associated object ID's - * - * @return array Array of services/id's - */ - function listServicesCli($host = null) { - - $q = new Doctrine_Query(); - $q->select('s.*,' - .'h.display_name AS host,' - .'i.instance_name AS instance') - ->from('NpcServices s, s.Host h, s.Instance i'); + if (!$check_id) { + return array(); + } + + return db_fetch_assoc_prepared( + 'SELECT * FROM npc_servicechecks WHERE servicecheck_id = ?', + array($check_id)); + } + + function getPerfHistory($host, $service, $begin, $end = null) { + $params = array($host, $service, $begin); + $sql = 'SELECT n.end_time, n.perfdata + FROM npc_servicechecks n + INNER JOIN npc_objects o ON o.object_id = n.service_object_id + WHERE o.is_active = 1 AND o.name1 = ? AND o.name2 = ? + AND n.end_time >= ?'; + + if ($end) { + $sql .= ' AND n.end_time <= ?'; + $params[] = $end; + } + + return db_fetch_assoc_prepared($sql, $params); + } + + function listServicesCli($host = null) { + $sql = 'SELECT s.*, h.display_name AS host, i.instance_name AS instance + FROM npc_services s + LEFT JOIN npc_hosts h ON s.host_object_id = h.host_object_id + LEFT JOIN npc_instances i ON s.instance_id = i.instance_id'; if ($host) { - $q->where('h.display_name = ?', $host); + $sql .= ' WHERE h.display_name = ?'; + return $this->flattenArray(db_fetch_assoc_prepared($sql, array($host))); } - return($this->flattenArray($q->execute(array(), Doctrine::HYDRATE_ARRAY))); - } - - /** - * getMappedGraph - * - * Returns the url to the currently mapped graph - * - * @return string json encoded results - */ - function getMappedGraph() { - $q = new Doctrine_Query(); - $q->select('sg.*') - ->from('NpcServiceGraphs sg') - ->where('sg.service_object_id = ?', $this->id); - - $results = $q->execute(array(), Doctrine::HYDRATE_ARRAY); - - return($this->jsonOutput($results)); - } - - /** - * setMappedGraph - * - * Sets the graph mapping - * - * @return string json encoded results - */ - function setMappedGraph($params) { - $table = $this->conn->getTable('NpcServiceGraphs'); - - $results = $table->findByDql("service_object_id = ?", array($params['object_id'])); - $graph = $results[0]; - - if (!isset($graph->local_graph_id)) { - $graph = new NpcServiceGraphs(); - } - - $graph->service_object_id = $params['object_id']; - $graph->local_graph_id = $params['local_graph_id']; - $graph->save(); - - return(json_encode(array('success' => true))); - } - - /** - * formatStateInfo - * - * Formats the service state info results for display. - * This is a workaround for some of the limitations of - * EXT property grid. - * - * @return string The formatted results - */ - function formatStateInfo($key, $results) { - - // Set the default return value - if (isset($results[$key])) { - $return = $results[$key]; - } - - $cs = array( - '0' => '', - '1' => '', - '2' => '', - '3' => '', - '-1' => '' - ); - - if ($key == 'current_state') { - $return = $cs[$results[$key]]; - if ($results['problem_has_been_acknowledged']) { - $comments = new NpcCommentsController; - $string = $comments->getAck($results['service_object_id']); - $ack = preg_split("/\*\|\*/", $string); - $return = '
' . $return . '   (Acknowledged by ' . $ack[0] . ')
'; - } - } - - if ($key == 'current_check_attempt') { - $return = $results[$key] . '/' . $results['max_check_attempts']; - } - - if (preg_match("/_enabled/", $key) || $key == 'obsess_over_service') { - if($results[$key]) { - $return = ''; - } else { - $return = ''; - } - } - - if ($key == 'last_state_change' || $key == 'last_check' || $key == 'next_check') { - $format = read_config_option('npc_date_format') . ' ' . read_config_option('npc_time_format'); - $return = date($format, strtotime($results[$key])); - } - - if ($key == 'scheduled_downtime_depth' || $key == 'is_flapping' || $key == 'process_performance_data') { - if ($results[$key]) { - $return = 'Yes'; - } else { - $return = 'No'; - } - } - - // Add the full command as a tooltip - if ($key == 'command_line') { - $perf = $this->getPerfData($results['service_object_id']); - $return = $perf[0]['command_line']; - } - - if ($return == '' || !$return) { - $return = 'NA'; - } - - return($return); - } -} + return $this->flattenArray(db_fetch_assoc($sql)); + } + + function getMappedGraph() { + $results = db_fetch_assoc_prepared( + 'SELECT * FROM npc_service_graphs WHERE service_object_id = ?', + array($this->id)); + + return $this->jsonOutput($results); + } + function setMappedGraph($params) { + $object_id = intval($params['object_id']); + $local_graph_id = intval($params['local_graph_id']); + $existing = db_fetch_row_prepared( + 'SELECT * FROM npc_service_graphs WHERE service_object_id = ?', + array($object_id)); + if (cacti_sizeof($existing)) { + db_execute_prepared( + 'UPDATE npc_service_graphs SET local_graph_id = ? WHERE service_object_id = ?', + array($local_graph_id, $object_id)); + } else { + db_execute_prepared( + 'INSERT INTO npc_service_graphs (service_object_id, local_graph_id) VALUES (?, ?)', + array($object_id, $local_graph_id)); + } + + return json_encode(array('success' => true)); + } + + function formatStateInfo($key, $results) { + $return = isset($results[$key]) ? $results[$key] : ''; + + $cs = array( + '0' => '', + '1' => '', + '2' => '', + '3' => '', + '-1' => '' + ); + + if ($key == 'current_state') { + $return = isset($cs[$results[$key]]) ? $cs[$results[$key]] : ''; + if ($results['problem_has_been_acknowledged']) { + $comments = new NpcCommentsController; + $string = $comments->getAck($results['service_object_id']); + $ack = preg_split('/\*\|\*/', $string); + $return .= ' (Acknowledged by ' . html_escape($ack[0]) . ')'; + } + } + + if ($key == 'current_check_attempt') { + $return = $results[$key] . '/' . $results['max_check_attempts']; + } + + if (preg_match('/_enabled/', $key) || $key == 'obsess_over_service') { + $return = $results[$key] ? __('Yes', 'npc') : __('No', 'npc'); + } + + if ($key == 'last_state_change' || $key == 'last_check' || $key == 'next_check') { + $format = read_config_option('npc_date_format') . ' ' . read_config_option('npc_time_format'); + $return = date($format, strtotime($results[$key])); + } + + if ($key == 'scheduled_downtime_depth' || $key == 'is_flapping' || $key == 'process_performance_data') { + $return = $results[$key] ? __('Yes', 'npc') : __('No', 'npc'); + } + + if ($key == 'command_line') { + $perf = $this->getPerfData($results['service_object_id']); + $return = cacti_sizeof($perf) ? $perf[0]['command_line'] : ''; + } + + if ($return == '' || !$return) { + $return = __('N/A', 'npc'); + } + + return $return; + } +} diff --git a/controllers/settings.php b/controllers/settings.php index 94a7295..a154392 100644 --- a/controllers/settings.php +++ b/controllers/settings.php @@ -27,12 +27,12 @@ class NpcSettingsController extends Controller { function getSettings($id) { - - $q = new Doctrine_Query(); - $settings = $this->conn->getTable('NpcSettings')->find($id); + $settings = db_fetch_row_prepared('SELECT * + FROM npc_settings + WHERE user_id = ?', + array($id)); return($settings); - } function save($params) { @@ -40,16 +40,17 @@ function save($params) { $user_id = $_SESSION['sess_user_id']; $obj = $this->getSettings($user_id); - $settings = unserialize($obj->settings); - if (isset($params['name'])) { - $settings[$params['name']] = $params['value']; - } + $settings = @unserialize($obj['settings'], ["allowed_classes" => false]); + if (isset($params['name'])) { + $settings[$params['name']] = $params['value']; + } - $obj->settings = serialize($settings); - $obj->save(); + db_execute_prepared('UPDATE npc_settings + SET settings = ? + WHERE user_id = ?', + array(serialize($settings), $user_id)); return(true); } } - diff --git a/controllers/statehistory.php b/controllers/statehistory.php index fecd924..dcada7b 100644 --- a/controllers/statehistory.php +++ b/controllers/statehistory.php @@ -18,7 +18,7 @@ * Statehistory controller class * * Statehistory controller provides functionality, such as building the - * Doctrine queries and formatting output. + * queries and formatting output. * * @package npc * @subpackage npc.controllers @@ -35,30 +35,35 @@ class NpcStatehistoryController extends Controller { function getStateHistory() { $where = '1 = 1'; + $params = array(); if ($this->id) { - $where = sprintf("sh.object_id = %d ", $this->id); + $where = 'sh.object_id = ?'; + $params[] = $this->id; } - $q = new Doctrine_Pager( - Doctrine_Query::create() - ->select('i.instance_name,' - .'o.name1 AS host_name,' - .'o.name2 AS service_description,' - .'sh.*') - ->from('NpcStatehistory sh') - ->leftJoin('sh.Object o') - ->leftJoin('sh.Instance i') - ->where("$where") - ->orderby( 'sh.state_time DESC, sh.state_time_usec DESC' ), - $this->currentPage, - $this->limit - ); + /* Get total count */ + $this->numRecords = db_fetch_cell_prepared('SELECT COUNT(*) + FROM npc_statehistory sh + LEFT JOIN npc_objects o ON sh.object_id = o.object_id + LEFT JOIN npc_instances i ON sh.instance_id = i.instance_id + WHERE ' . $where, + $params); - $results = $q->execute(array(), Doctrine::HYDRATE_ARRAY); + $offset = (int) (($this->currentPage - 1) * $this->limit); + $limit = (int) $this->limit; - // Set the total number of records - $this->numRecords = $q->getNumResults(); + $results = db_fetch_assoc_prepared('SELECT i.instance_name, + o.name1 AS host_name, + o.name2 AS service_description, + sh.* + FROM npc_statehistory sh + LEFT JOIN npc_objects o ON sh.object_id = o.object_id + LEFT JOIN npc_instances i ON sh.instance_id = i.instance_id + WHERE ' . $where . ' + ORDER BY sh.state_time DESC, sh.state_time_usec DESC + LIMIT ?, ?', + array_merge($params, array($offset, $limit))); return($this->jsonOutput($results)); } diff --git a/css/ext-ux-livegrid.css b/css/ext-ux-livegrid.css deleted file mode 100644 index ef461b8..0000000 --- a/css/ext-ux-livegrid.css +++ /dev/null @@ -1,22 +0,0 @@ -.ext-ux-livegrid-drop-waiting { - background-image:url(../images/loading.gif) !important; -} - -.ext-ux-livegrid-liveScroller { - z-index:1; - background:none!important; - position:absolute; - height:3px; - right:0px; - width:18px; - overflow:scroll; - overflow-x:hidden; -} - -.ext-ux-livegrid-liveScroller div { - background:none; - width:1px; - overflow:hidden; - font-size:1px; - height:0px; -} \ No newline at end of file diff --git a/css/main.css b/css/main.css deleted file mode 100644 index 2311e6b..0000000 --- a/css/main.css +++ /dev/null @@ -1,229 +0,0 @@ -#msg-div { -position:absolute; -left:35%; -top:10px; -width:350px; -z-index:20000; -} - -.errorGo { -background-image:url(../images/icons/error_go.png) !important; -} - -.configuration { -background-image:url(../images/icons/cog_go.png) !important; -} - -.add { -background-image:url(../images/icons/add.png) !important; -} - -.cogAdd { -background-image:url(../images/icons/cog_add.png) !important; -} - -.appViewDetail { -background-image:url(../images/icons/application_view_detail.png) !important; -} - -.chartBar { -background-image:url(../images/icons/chart_bar.png) !important; -} - -.chartBarAdd { -background-image:url(../images/icons/chart_bar_add.png) !important; -} - -.scriptAdd { -background-image:url(../images/icons/script_add.png) !important; -} - -.commentAdd { -background-image:url(../images/icons/comment_add.png) !important; -} - -.commentsDelete { -background-image:url(../images/icons/comments_delete.png) !important; -} - -.commentDelete { -background-image:url(../images/icons/comment_delete.png) !important; -} - -.cancel { -background-image:url(../images/icons/cancel.png) !important; -} - -.reporting { -background-image:url(../images/icons/report_go.png) !important; -} - -.monitoring { -background-image:url(../images/icons/application_view_gallery.png) !important; -} - -.resultsetNext { -background-image:url(../images/icons/resultset_next.png) !important; -} - -.hosts { -background-image:url(../images/icons/server.png) !important; -} - -.tnode { -background-image:url(../images/icons/folder.png) !important; -} - -.tleaf { -background-image:url(../images/icons/tab.png) !important; -} - -.layout { -background-image:url(../images/icons/layout.png); -} - -.layoutEdit { -background-image:url(../images/icons/layout_edit.png) !important; -} - -.pageWhiteWrench { -background-image:url(../images/icons/page_white_wrench.png) !important; -} - -#navcontainer ul -{ -list-style-type: none; -text-align: left; -} - -#navcontainer ul li a -{ -background: transparent url(../images/list-off.gif) left center no-repeat; -padding-left: 15px; -text-align: left; -font: normal 11px "Lucida Grande", "Lucida Sans Unicode", verdana, lucida, sans-serif; -text-decoration: none; -color: #999; -} - -#navcontainer ul li a:hover -{ -background: transparent url(../images/list-on.gif) left center no-repeat; -color: black; -} - -#navcontainer ul li a#current -{ -background: transparent url(../images/list-active.gif) left center no-repeat; -color: #666; -} - -.x-portal .x-panel-dd-spacer { - margin-bottom:10px; -} - -.x-portlet { - margin-bottom:10px; -} - -/* Clean up the look of the portlets */ -.x-portlet .x-panel-ml { - padding-left:2px; -} -.x-portlet .x-panel-mr { - padding-right:2px; -} -.x-portlet .x-panel-bl { - padding-left:2px; -} - -.x-portlet .x-panel-br { - padding-right:2px; -} -.x-portlet .x-panel-body { - background:white; -} -.x-portlet .x-panel-mc { - padding-top:2px; -} -.x-portlet .x-panel-bc .x-panel-footer { - padding-bottom:2px; -} -.x-portlet .x-panel-nofooter .x-panel-bc { - height:2px; -} - -.x-form-checkbox { - margin-top: 5px; -} - -.xcheckbox-wrap { - line-height: 18px; - padding-top:2px; -} -.xcheckbox-wrap a { - display:block; - width:16px; - height:16px; -} -.x-toolbar .xcheckbox-wrap { - padding: 0 0 2px 0; -} -.xcheckbox-on { - background:transparent url(../js/ext/resources/images/default/menu/checked.gif) no-repeat 0 0; -} -.xcheckbox-off { - background:transparent url(../js/ext/resources/images/default/menu/unchecked.gif) no-repeat 0 0; -} - -.x-grid3-cell-inner, .x-grid3-hd-inner{ - overflow:hidden; - -o-text-overflow: ellipsis; - text-overflow: ellipsis; - padding:3px 3px 3px 5px; - white-space: normal; -} - -.status-bar { - height:18px; - float:left; - width:0; - border-top:1px solid #D1E4FD; - border-bottom:1px solid #7FA9E4; - border-right:1px solid #7FA9E4; -} - -.status-bar-text { - font-size:11px; - font-weight:bold; - color:#000000; - padding:1px 5px; - overflow:hidden; - position:absolute; - text-align:center; -} -.status-bar-text-back { - color:#000000; - line-height:16px; -} - - -.statusPENDING { background-color: #ACACAC; } -.statusOK { background-color: #33FF00; } -.statusRECOVERY { background-color: #33FF00; } -.statusUNKNOWN { background-color: #FF9900; } -.statusWARNING { background-color: #FFFF00; } -.statusCRITICAL { background-color: #F83838; } - -.serviceTotalsOk { background: #33FF00; } -.serviceTotalsWarning { background: #FFFF00; font-weight: bold; } -.serviceTotalsUnknown { background: #FF9900; font-weight: bold; } -.serviceTotalsCritical { background: #F83838; font-weight: bold; } -.serviceTotalsPending { background: #0099FF; } -.serviceTotalsProblems { background: orange; font-weight: bold; } - -.hostTotalsUp { background: #33FF00; } -.hostTotalsDown { background: #F83838; } -.hostTotalsUnreachable { background: #F83838; } -.hostTotalsPending { background: #0099FF; } - diff --git a/js/ext/adapter/ext/ext-base.js b/js/ext/adapter/ext/ext-base.js deleted file mode 100644 index b68f63d..0000000 --- a/js/ext/adapter/ext/ext-base.js +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Ext JS Library 2.2 - * Copyright(c) 2006-2008, Ext JS, LLC. - * licensing@extjs.com - * - * http://extjs.com/license - */ - -Ext={version:"2.2"};window["undefined"]=window["undefined"];Ext.apply=function(C,D,B){if(B){Ext.apply(C,B)}if(C&&D&&typeof D=="object"){for(var A in D){C[A]=D[A]}}return C};(function(){var idSeed=0;var ua=navigator.userAgent.toLowerCase();var isStrict=document.compatMode=="CSS1Compat",isOpera=ua.indexOf("opera")>-1,isSafari=(/webkit|khtml/).test(ua),isSafari3=isSafari&&ua.indexOf("webkit/5")!=-1,isIE=!isOpera&&ua.indexOf("msie")>-1,isIE7=!isOpera&&ua.indexOf("msie 7")>-1,isGecko=!isSafari&&ua.indexOf("gecko")>-1,isGecko3=!isSafari&&ua.indexOf("rv:1.9")>-1,isBorderBox=isIE&&!isStrict,isWindows=(ua.indexOf("windows")!=-1||ua.indexOf("win32")!=-1),isMac=(ua.indexOf("macintosh")!=-1||ua.indexOf("mac os x")!=-1),isAir=(ua.indexOf("adobeair")!=-1),isLinux=(ua.indexOf("linux")!=-1),isSecure=window.location.href.toLowerCase().indexOf("https")===0;if(isIE&&!isIE7){try{document.execCommand("BackgroundImageCache",false,true)}catch(e){}}Ext.apply(Ext,{isStrict:isStrict,isSecure:isSecure,isReady:false,enableGarbageCollector:true,enableListenerCollection:false,SSL_SECURE_URL:"javascript:false",BLANK_IMAGE_URL:"http:/"+"/extjs.com/s.gif",emptyFn:function(){},applyIf:function(o,c){if(o&&c){for(var p in c){if(typeof o[p]=="undefined"){o[p]=c[p]}}}return o},addBehaviors:function(o){if(!Ext.isReady){Ext.onReady(function(){Ext.addBehaviors(o)});return }var cache={};for(var b in o){var parts=b.split("@");if(parts[1]){var s=parts[0];if(!cache[s]){cache[s]=Ext.select(s)}cache[s].on(parts[1],o[b])}}cache=null},id:function(el,prefix){prefix=prefix||"ext-gen";el=Ext.getDom(el);var id=prefix+(++idSeed);return el?(el.id?el.id:(el.id=id)):id},extend:function(){var io=function(o){for(var m in o){this[m]=o[m]}};var oc=Object.prototype.constructor;return function(sb,sp,overrides){if(typeof sp=="object"){overrides=sp;sp=sb;sb=overrides.constructor!=oc?overrides.constructor:function(){sp.apply(this,arguments)}}var F=function(){},sbp,spp=sp.prototype;F.prototype=spp;sbp=sb.prototype=new F();sbp.constructor=sb;sb.superclass=spp;if(spp.constructor==oc){spp.constructor=sp}sb.override=function(o){Ext.override(sb,o)};sbp.override=io;Ext.override(sb,overrides);sb.extend=function(o){Ext.extend(sb,o)};return sb}}(),override:function(origclass,overrides){if(overrides){var p=origclass.prototype;for(var method in overrides){p[method]=overrides[method]}}},namespace:function(){var a=arguments,o=null,i,j,d,rt;for(i=0;i=0){L=G[P]}if(!S||!L){return false}this.doRemove(S,O,L[this.WFN],false);delete G[P][this.WFN];delete G[P][this.FN];G.splice(P,1);return true},getTarget:function(N,M){N=N.browserEvent||N;var L=N.target||N.srcElement;return this.resolveTextNode(L)},resolveTextNode:function(L){if(Ext.isSafari&&L&&3==L.nodeType){return L.parentNode}else{return L}},getPageX:function(M){M=M.browserEvent||M;var L=M.pageX;if(!L&&0!==L){L=M.clientX||0;if(Ext.isIE){L+=this.getScroll()[1]}}return L},getPageY:function(L){L=L.browserEvent||L;var M=L.pageY;if(!M&&0!==M){M=L.clientY||0;if(Ext.isIE){M+=this.getScroll()[0]}}return M},getXY:function(L){L=L.browserEvent||L;return[this.getPageX(L),this.getPageY(L)]},getRelatedTarget:function(M){M=M.browserEvent||M;var L=M.relatedTarget;if(!L){if(M.type=="mouseout"){L=M.toElement}else{if(M.type=="mouseover"){L=M.fromElement}}}return this.resolveTextNode(L)},getTime:function(N){N=N.browserEvent||N;if(!N.time){var M=new Date().getTime();try{N.time=M}catch(L){this.lastError=L;return M}}return N.time},stopEvent:function(L){this.stopPropagation(L);this.preventDefault(L)},stopPropagation:function(L){L=L.browserEvent||L;if(L.stopPropagation){L.stopPropagation()}else{L.cancelBubble=true}},preventDefault:function(L){L=L.browserEvent||L;if(L.preventDefault){L.preventDefault()}else{L.returnValue=false}},getEvent:function(M){var L=M||window.event;if(!L){var N=this.getEvent.caller;while(N){L=N.arguments[0];if(L&&Event==L.constructor){break}N=N.caller}}return L},getCharCode:function(L){L=L.browserEvent||L;return L.charCode||L.keyCode||0},_getCacheIndex:function(Q,N,P){for(var O=0,M=G.length;O0)}var Q=[];for(var M=0,L=H.length;M0){for(var Q=0,S=T.length;Q0){O=G.length;while(O){N=O-1;M=G[N];if(M){R.removeListener(M[R.EL],M[R.TYPE],M[R.FN],N)}O=O-1}M=null;R.clearCache()}R.doRemove(window,"unload",R._unload)},getScroll:function(){var L=document.documentElement,M=document.body;if(L&&(L.scrollTop||L.scrollLeft)){return[L.scrollTop,L.scrollLeft]}else{if(M){return[M.scrollTop,M.scrollLeft]}else{return[0,0]}}},doAdd:function(){if(window.addEventListener){return function(O,M,N,L){O.addEventListener(M,N,(L))}}else{if(window.attachEvent){return function(O,M,N,L){O.attachEvent("on"+M,N)}}else{return function(){}}}}(),doRemove:function(){if(window.removeEventListener){return function(O,M,N,L){O.removeEventListener(M,N,(L))}}else{if(window.detachEvent){return function(N,L,M){N.detachEvent("on"+L,M)}}else{return function(){}}}}()}}();var D=Ext.lib.Event;D.on=D.addListener;D.un=D.removeListener;if(document&&document.body){D._load()}else{D.doAdd(window,"load",D._load)}D.doAdd(window,"unload",D._unload);D._tryPreloadAttach();Ext.lib.Ajax={request:function(K,I,E,J,F){if(F){var G=F.headers;if(G){for(var H in G){if(G.hasOwnProperty(H)){this.initHeader(H,G[H],false)}}}if(F.xmlData){if(!G||!G["Content-Type"]){this.initHeader("Content-Type","text/xml",false)}K=(K?K:(F.method?F.method:"POST"));J=F.xmlData}else{if(F.jsonData){if(!G||!G["Content-Type"]){this.initHeader("Content-Type","application/json",false)}K=(K?K:(F.method?F.method:"POST"));J=typeof F.jsonData=="object"?Ext.encode(F.jsonData):F.jsonData}}}return this.asyncRequest(K,I,E,J)},serializeForm:function(F){if(typeof F=="string"){F=(document.getElementById(F)||document.forms[F])}var G,E,H,J,K="",M=false;for(var L=0;L=200&&G<300){F=this.createResponseObject(I,J.argument);if(J.success){if(!J.scope){J.success(F)}else{J.success.apply(J.scope,[F])}}}else{switch(G){case 12002:case 12029:case 12030:case 12031:case 12152:case 13030:F=this.createExceptionObject(I.tId,J.argument,(E?E:false));if(J.failure){if(!J.scope){J.failure(F)}else{J.failure.apply(J.scope,[F])}}break;default:F=this.createResponseObject(I,J.argument);if(J.failure){if(!J.scope){J.failure(F)}else{J.failure.apply(J.scope,[F])}}}}this.releaseObject(I);F=null},createResponseObject:function(E,K){var H={};var M={};try{var G=E.conn.getAllResponseHeaders();var J=G.split("\n");for(var I=0;I=this.left&&E.right<=this.right&&E.top>=this.top&&E.bottom<=this.bottom)},getArea:function(){return((this.bottom-this.top)*(this.right-this.left))},intersect:function(I){var G=Math.max(this.top,I.top);var H=Math.min(this.right,I.right);var E=Math.min(this.bottom,I.bottom);var F=Math.max(this.left,I.left);if(E>=G&&H>=F){return new Ext.lib.Region(G,H,E,F)}else{return null}},union:function(I){var G=Math.min(this.top,I.top);var H=Math.max(this.right,I.right);var E=Math.max(this.bottom,I.bottom);var F=Math.min(this.left,I.left);return new Ext.lib.Region(G,H,E,F)},constrainTo:function(E){this.top=this.top.constrain(E.top,E.bottom);this.bottom=this.bottom.constrain(E.top,E.bottom);this.left=this.left.constrain(E.left,E.right);this.right=this.right.constrain(E.left,E.right);return this},adjust:function(G,F,E,H){this.top+=G;this.left+=F;this.right+=H;this.bottom+=E;return this}};Ext.lib.Region.getRegion=function(H){var J=Ext.lib.Dom.getXY(H);var G=J[1];var I=J[0]+H.offsetWidth;var E=J[1]+H.offsetHeight;var F=J[0];return new Ext.lib.Region(G,I,E,F)};Ext.lib.Point=function(E,F){if(Ext.isArray(E)){F=E[1];E=E[0]}this.x=this.right=this.left=this[0]=E;this.y=this.top=this.bottom=this[1]=F};Ext.lib.Point.prototype=new Ext.lib.Region();Ext.lib.Anim={scroll:function(H,F,I,J,E,G){return this.run(H,F,I,J,E,G,Ext.lib.Scroll)},motion:function(H,F,I,J,E,G){return this.run(H,F,I,J,E,G,Ext.lib.Motion)},color:function(H,F,I,J,E,G){return this.run(H,F,I,J,E,G,Ext.lib.ColorAnim)},run:function(I,F,K,L,E,H,G){G=G||Ext.lib.AnimBase;if(typeof L=="string"){L=Ext.lib.Easing[L]}var J=new G(I,F,K,L);J.animateX(function(){Ext.callback(E,H)});return J}};function C(E){if(!B){B=new Ext.Element.Flyweight()}B.dom=E;return B}if(Ext.isIE){function A(){var E=Function.prototype;delete E.createSequence;delete E.defer;delete E.createDelegate;delete E.createCallback;delete E.createInterceptor;window.detachEvent("onunload",A)}window.attachEvent("onunload",A)}Ext.lib.AnimBase=function(F,E,G,H){if(F){this.init(F,E,G,H)}};Ext.lib.AnimBase.prototype={toString:function(){var E=this.getEl();var F=E.id||E.tagName;return("Anim "+F)},patterns:{noNegatives:/width|height|opacity|padding/i,offsetAttribute:/^((width|height)|(top|left))$/,defaultUnit:/width|height|top$|bottom$|left$|right$/i,offsetUnit:/\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i},doMethod:function(E,G,F){return this.method(this.currentFrame,G,F-G,this.totalFrames)},setAttribute:function(E,G,F){if(this.patterns.noNegatives.test(E)){G=(G>0)?G:0}Ext.fly(this.getEl(),"_anim").setStyle(E,G+F)},getAttribute:function(E){var G=this.getEl();var I=C(G).getStyle(E);if(I!=="auto"&&!this.patterns.offsetUnit.test(I)){return parseFloat(I)}var F=this.patterns.offsetAttribute.exec(E)||[];var J=!!(F[3]);var H=!!(F[2]);if(H||(C(G).getStyle("position")=="absolute"&&J)){I=G["offset"+F[0].charAt(0).toUpperCase()+F[0].substr(1)]}else{I=0}return I},getDefaultUnit:function(E){if(this.patterns.defaultUnit.test(E)){return"px"}return""},animateX:function(G,E){var F=function(){this.onComplete.removeListener(F);if(typeof G=="function"){G.call(E||this,this)}};this.onComplete.addListener(F,this);this.animate()},setRuntimeAttribute:function(F){var K;var G;var H=this.attributes;this.runtimeAttributes[F]={};var J=function(L){return(typeof L!=="undefined")};if(!J(H[F]["to"])&&!J(H[F]["by"])){return false}K=(J(H[F]["from"]))?H[F]["from"]:this.getAttribute(F);if(J(H[F]["to"])){G=H[F]["to"]}else{if(J(H[F]["by"])){if(K.constructor==Array){G=[];for(var I=0,E=K.length;I0&&isFinite(O)){if(K.currentFrame+O>=N){O=N-(M+1)}K.currentFrame+=O}}};Ext.lib.Bezier=new function(){this.getPosition=function(I,H){var J=I.length;var G=[];for(var F=0;F0&&!Ext.isArray(O[0])){O=[O]}else{var N=[];for(P=0,R=O.length;P0){this.runtimeAttributes[S]=this.runtimeAttributes[S].concat(O)}this.runtimeAttributes[S][this.runtimeAttributes[S].length]=L}else{I.setRuntimeAttribute.call(this,S)}};var E=function(J,L){var K=Ext.lib.Dom.getXY(this.getEl());J=[J[0]-K[0]+L[0],J[1]-K[1]+L[1]];return J};var G=function(J){return(typeof J!=="undefined")}})();(function(){Ext.lib.Scroll=function(I,H,J,K){if(I){Ext.lib.Scroll.superclass.constructor.call(this,I,H,J,K)}};Ext.extend(Ext.lib.Scroll,Ext.lib.ColorAnim);var F=Ext.lib;var G=F.Scroll.superclass;var E=F.Scroll.prototype;E.toString=function(){var H=this.getEl();var I=H.id||H.tagName;return("Scroll "+I)};E.doMethod=function(H,K,I){var J=null;if(H=="scroll"){J=[this.method(this.currentFrame,K[0],I[0]-K[0],this.totalFrames),this.method(this.currentFrame,K[1],I[1]-K[1],this.totalFrames)]}else{J=G.doMethod.call(this,H,K,I)}return J};E.getAttribute=function(H){var J=null;var I=this.getEl();if(H=="scroll"){J=[I.scrollLeft,I.scrollTop]}else{J=G.getAttribute.call(this,H)}return J};E.setAttribute=function(H,K,J){var I=this.getEl();if(H=="scroll"){I.scrollLeft=K[0];I.scrollTop=K[1]}else{G.setAttribute.call(this,H,K,J)}}})()})(); diff --git a/js/ext/adapter/jquery/ext-jquery-adapter.js b/js/ext/adapter/jquery/ext-jquery-adapter.js deleted file mode 100644 index 40e3333..0000000 --- a/js/ext/adapter/jquery/ext-jquery-adapter.js +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Ext JS Library 2.2 - * Copyright(c) 2006-2008, Ext JS, LLC. - * licensing@extjs.com - * - * http://extjs.com/license - */ - -Ext={version:"2.2"};window["undefined"]=window["undefined"];Ext.apply=function(C,D,B){if(B){Ext.apply(C,B)}if(C&&D&&typeof D=="object"){for(var A in D){C[A]=D[A]}}return C};(function(){var idSeed=0;var ua=navigator.userAgent.toLowerCase();var isStrict=document.compatMode=="CSS1Compat",isOpera=ua.indexOf("opera")>-1,isSafari=(/webkit|khtml/).test(ua),isSafari3=isSafari&&ua.indexOf("webkit/5")!=-1,isIE=!isOpera&&ua.indexOf("msie")>-1,isIE7=!isOpera&&ua.indexOf("msie 7")>-1,isGecko=!isSafari&&ua.indexOf("gecko")>-1,isGecko3=!isSafari&&ua.indexOf("rv:1.9")>-1,isBorderBox=isIE&&!isStrict,isWindows=(ua.indexOf("windows")!=-1||ua.indexOf("win32")!=-1),isMac=(ua.indexOf("macintosh")!=-1||ua.indexOf("mac os x")!=-1),isAir=(ua.indexOf("adobeair")!=-1),isLinux=(ua.indexOf("linux")!=-1),isSecure=window.location.href.toLowerCase().indexOf("https")===0;if(isIE&&!isIE7){try{document.execCommand("BackgroundImageCache",false,true)}catch(e){}}Ext.apply(Ext,{isStrict:isStrict,isSecure:isSecure,isReady:false,enableGarbageCollector:true,enableListenerCollection:false,SSL_SECURE_URL:"javascript:false",BLANK_IMAGE_URL:"http:/"+"/extjs.com/s.gif",emptyFn:function(){},applyIf:function(o,c){if(o&&c){for(var p in c){if(typeof o[p]=="undefined"){o[p]=c[p]}}}return o},addBehaviors:function(o){if(!Ext.isReady){Ext.onReady(function(){Ext.addBehaviors(o)});return }var cache={};for(var b in o){var parts=b.split("@");if(parts[1]){var s=parts[0];if(!cache[s]){cache[s]=Ext.select(s)}cache[s].on(parts[1],o[b])}}cache=null},id:function(el,prefix){prefix=prefix||"ext-gen";el=Ext.getDom(el);var id=prefix+(++idSeed);return el?(el.id?el.id:(el.id=id)):id},extend:function(){var io=function(o){for(var m in o){this[m]=o[m]}};var oc=Object.prototype.constructor;return function(sb,sp,overrides){if(typeof sp=="object"){overrides=sp;sp=sb;sb=overrides.constructor!=oc?overrides.constructor:function(){sp.apply(this,arguments)}}var F=function(){},sbp,spp=sp.prototype;F.prototype=spp;sbp=sb.prototype=new F();sbp.constructor=sb;sb.superclass=spp;if(spp.constructor==oc){spp.constructor=sp}sb.override=function(o){Ext.override(sb,o)};sbp.override=io;Ext.override(sb,overrides);sb.extend=function(o){Ext.extend(sb,o)};return sb}}(),override:function(origclass,overrides){if(overrides){var p=origclass.prototype;for(var method in overrides){p[method]=overrides[method]}}},namespace:function(){var a=arguments,o=null,i,j,d,rt;for(i=0;i10000){clearInterval(G)}var J=document.getElementById(I);if(J){clearInterval(G);E.call(D||window,J)}};var G=setInterval(F,50)},resolveTextNode:function(D){if(D&&3==D.nodeType){return D.parentNode}else{return D}},getRelatedTarget:function(E){E=E.browserEvent||E;var D=E.relatedTarget;if(!D){if(E.type=="mouseout"){D=E.toElement}else{if(E.type=="mouseover"){D=E.fromElement}}}return this.resolveTextNode(D)}};Ext.lib.Ajax=function(){var D=function(E){return function(G,F){if((F=="error"||F=="timeout")&&E.failure){E.failure.call(E.scope||window,{responseText:G.responseText,responseXML:G.responseXML,argument:E.argument})}else{if(E.success){E.success.call(E.scope||window,{responseText:G.responseText,responseXML:G.responseXML,argument:E.argument})}}}};return{request:function(K,H,E,I,F){var J={type:K,url:H,data:I,timeout:E.timeout,complete:D(E)};if(F){var G=F.headers;if(F.xmlData){J.data=F.xmlData;J.processData=false;J.type=(K?K:(F.method?F.method:"POST"));if(!G||!G["Content-Type"]){J.contentType="text/xml"}}else{if(F.jsonData){J.data=typeof F.jsonData=="object"?Ext.encode(F.jsonData):F.jsonData;J.processData=false;J.type=(K?K:(F.method?F.method:"POST"));if(!G||!G["Content-Type"]){J.contentType="application/json"}}}if(G){J.beforeSend=function(M){for(var L in G){if(G.hasOwnProperty(L)){M.setRequestHeader(L,G[L])}}}}}jQuery.ajax(J)},formRequest:function(I,H,F,J,E,G){jQuery.ajax({type:Ext.getDom(I).method||"POST",url:H,data:jQuery(I).serialize()+(J?"&"+J:""),timeout:F.timeout,complete:D(F)})},isCallInProgress:function(E){return false},abort:function(E){return false},serializeForm:function(E){return jQuery(E.dom||E).serialize()}}}();Ext.lib.Anim=function(){var D=function(E,F){var G=true;return{stop:function(H){},isAnimated:function(){return G},proxyCallback:function(){G=false;Ext.callback(E,F)}}};return{scroll:function(H,F,J,K,E,G){var I=D(E,G);H=Ext.getDom(H);if(typeof F.scroll.to[0]=="number"){H.scrollLeft=F.scroll.to[0]}if(typeof F.scroll.to[1]=="number"){H.scrollTop=F.scroll.to[1]}I.proxyCallback();return I},motion:function(H,F,I,J,E,G){return this.run(H,F,I,J,E,G)},color:function(H,F,J,K,E,G){var I=D(E,G);I.proxyCallback();return I},run:function(F,N,I,M,G,P,O){var J=D(G,P),K=Ext.fly(F,"_animrun");var E={};for(var H in N){if(N[H].from){if(H!="points"){K.setStyle(H,N[H].from)}}switch(H){case"points":var L,R;K.position();if(L=N.points.by){var Q=K.getXY();R=K.translatePoints([Q[0]+L[0],Q[1]+L[1]])}else{R=K.translatePoints(N.points.to)}E.left=R.left;E.top=R.top;if(!parseInt(K.getStyle("left"),10)){K.setLeft(0)}if(!parseInt(K.getStyle("top"),10)){K.setTop(0)}if(N.points.from){K.setXY(N.points.from)}break;case"width":E.width=N.width.to;break;case"height":E.height=N.height.to;break;case"opacity":E.opacity=N.opacity.to;break;case"left":E.left=N.left.to;break;case"top":E.top=N.top.to;break;default:E[H]=N[H].to;break}}jQuery(F).animate(E,I*1000,undefined,J.proxyCallback);return J}}}();Ext.lib.Region=function(F,G,D,E){this.top=F;this[1]=F;this.right=G;this.bottom=D;this.left=E;this[0]=E};Ext.lib.Region.prototype={contains:function(D){return(D.left>=this.left&&D.right<=this.right&&D.top>=this.top&&D.bottom<=this.bottom)},getArea:function(){return((this.bottom-this.top)*(this.right-this.left))},intersect:function(H){var F=Math.max(this.top,H.top);var G=Math.min(this.right,H.right);var D=Math.min(this.bottom,H.bottom);var E=Math.max(this.left,H.left);if(D>=F&&G>=E){return new Ext.lib.Region(F,G,D,E)}else{return null}},union:function(H){var F=Math.min(this.top,H.top);var G=Math.max(this.right,H.right);var D=Math.max(this.bottom,H.bottom);var E=Math.min(this.left,H.left);return new Ext.lib.Region(F,G,D,E)},constrainTo:function(D){this.top=this.top.constrain(D.top,D.bottom);this.bottom=this.bottom.constrain(D.top,D.bottom);this.left=this.left.constrain(D.left,D.right);this.right=this.right.constrain(D.left,D.right);return this},adjust:function(F,E,D,G){this.top+=F;this.left+=E;this.right+=G;this.bottom+=D;return this}};Ext.lib.Region.getRegion=function(G){var I=Ext.lib.Dom.getXY(G);var F=I[1];var H=I[0]+G.offsetWidth;var D=I[1]+G.offsetHeight;var E=I[0];return new Ext.lib.Region(F,H,D,E)};Ext.lib.Point=function(D,E){if(Ext.isArray(D)){E=D[1];D=D[0]}this.x=this.right=this.left=this[0]=D;this.y=this.top=this.bottom=this[1]=E};Ext.lib.Point.prototype=new Ext.lib.Region();if(Ext.isIE){function A(){var D=Function.prototype;delete D.createSequence;delete D.defer;delete D.createDelegate;delete D.createCallback;delete D.createInterceptor;window.detachEvent("onunload",A)}window.attachEvent("onunload",A)}})(); diff --git a/js/ext/adapter/jquery/jquery.js b/js/ext/adapter/jquery/jquery.js deleted file mode 100644 index 2e43a82..0000000 --- a/js/ext/adapter/jquery/jquery.js +++ /dev/null @@ -1,3408 +0,0 @@ -(function(){ -/* - * jQuery 1.2.3 - New Wave Javascript - * - * Copyright (c) 2008 John Resig (jquery.com) - * Dual licensed under the MIT (MIT-LICENSE.txt) - * and GPL (GPL-LICENSE.txt) licenses. - * - * $Date: 2008-02-06 00:21:25 -0500 (Wed, 06 Feb 2008) $ - * $Rev: 4663 $ - */ - -// Map over jQuery in case of overwrite -if ( window.jQuery ) - var _jQuery = window.jQuery; - -var jQuery = window.jQuery = function( selector, context ) { - // The jQuery object is actually just the init constructor 'enhanced' - return new jQuery.prototype.init( selector, context ); -}; - -// Map over the $ in case of overwrite -if ( window.$ ) - var _$ = window.$; - -// Map the jQuery namespace to the '$' one -window.$ = jQuery; - -// A simple way to check for HTML strings or ID strings -// (both of which we optimize for) -var quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/; - -// Is it a simple selector -var isSimple = /^.[^:#\[\.]*$/; - -jQuery.fn = jQuery.prototype = { - init: function( selector, context ) { - // Make sure that a selection was provided - selector = selector || document; - - // Handle $(DOMElement) - if ( selector.nodeType ) { - this[0] = selector; - this.length = 1; - return this; - - // Handle HTML strings - } else if ( typeof selector == "string" ) { - // Are we dealing with HTML string or an ID? - var match = quickExpr.exec( selector ); - - // Verify a match, and that no context was specified for #id - if ( match && (match[1] || !context) ) { - - // HANDLE: $(html) -> $(array) - if ( match[1] ) - selector = jQuery.clean( [ match[1] ], context ); - - // HANDLE: $("#id") - else { - var elem = document.getElementById( match[3] ); - - // Make sure an element was located - if ( elem ) - // Handle the case where IE and Opera return items - // by name instead of ID - if ( elem.id != match[3] ) - return jQuery().find( selector ); - - // Otherwise, we inject the element directly into the jQuery object - else { - this[0] = elem; - this.length = 1; - return this; - } - - else - selector = []; - } - - // HANDLE: $(expr, [context]) - // (which is just equivalent to: $(content).find(expr) - } else - return new jQuery( context ).find( selector ); - - // HANDLE: $(function) - // Shortcut for document ready - } else if ( jQuery.isFunction( selector ) ) - return new jQuery( document )[ jQuery.fn.ready ? "ready" : "load" ]( selector ); - - return this.setArray( - // HANDLE: $(array) - selector.constructor == Array && selector || - - // HANDLE: $(arraylike) - // Watch for when an array-like object, contains DOM nodes, is passed in as the selector - (selector.jquery || selector.length && selector != window && !selector.nodeType && selector[0] != undefined && selector[0].nodeType) && jQuery.makeArray( selector ) || - - // HANDLE: $(*) - [ selector ] ); - }, - - // The current version of jQuery being used - jquery: "1.2.3", - - // The number of elements contained in the matched element set - size: function() { - return this.length; - }, - - // The number of elements contained in the matched element set - length: 0, - - // Get the Nth element in the matched element set OR - // Get the whole matched element set as a clean array - get: function( num ) { - return num == undefined ? - - // Return a 'clean' array - jQuery.makeArray( this ) : - - // Return just the object - this[ num ]; - }, - - // Take an array of elements and push it onto the stack - // (returning the new matched element set) - pushStack: function( elems ) { - // Build a new jQuery matched element set - var ret = jQuery( elems ); - - // Add the old object onto the stack (as a reference) - ret.prevObject = this; - - // Return the newly-formed element set - return ret; - }, - - // Force the current matched set of elements to become - // the specified array of elements (destroying the stack in the process) - // You should use pushStack() in order to do this, but maintain the stack - setArray: function( elems ) { - // Resetting the length to 0, then using the native Array push - // is a super-fast way to populate an object with array-like properties - this.length = 0; - Array.prototype.push.apply( this, elems ); - - return this; - }, - - // Execute a callback for every element in the matched set. - // (You can seed the arguments with an array of args, but this is - // only used internally.) - each: function( callback, args ) { - return jQuery.each( this, callback, args ); - }, - - // Determine the position of an element within - // the matched set of elements - index: function( elem ) { - var ret = -1; - - // Locate the position of the desired element - this.each(function(i){ - if ( this == elem ) - ret = i; - }); - - return ret; - }, - - attr: function( name, value, type ) { - var options = name; - - // Look for the case where we're accessing a style value - if ( name.constructor == String ) - if ( value == undefined ) - return this.length && jQuery[ type || "attr" ]( this[0], name ) || undefined; - - else { - options = {}; - options[ name ] = value; - } - - // Check to see if we're setting style values - return this.each(function(i){ - // Set all the styles - for ( name in options ) - jQuery.attr( - type ? - this.style : - this, - name, jQuery.prop( this, options[ name ], type, i, name ) - ); - }); - }, - - css: function( key, value ) { - // ignore negative width and height values - if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 ) - value = undefined; - return this.attr( key, value, "curCSS" ); - }, - - text: function( text ) { - if ( typeof text != "object" && text != null ) - return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) ); - - var ret = ""; - - jQuery.each( text || this, function(){ - jQuery.each( this.childNodes, function(){ - if ( this.nodeType != 8 ) - ret += this.nodeType != 1 ? - this.nodeValue : - jQuery.fn.text( [ this ] ); - }); - }); - - return ret; - }, - - wrapAll: function( html ) { - if ( this[0] ) - // The elements to wrap the target around - jQuery( html, this[0].ownerDocument ) - .clone() - .insertBefore( this[0] ) - .map(function(){ - var elem = this; - - while ( elem.firstChild ) - elem = elem.firstChild; - - return elem; - }) - .append(this); - - return this; - }, - - wrapInner: function( html ) { - return this.each(function(){ - jQuery( this ).contents().wrapAll( html ); - }); - }, - - wrap: function( html ) { - return this.each(function(){ - jQuery( this ).wrapAll( html ); - }); - }, - - append: function() { - return this.domManip(arguments, true, false, function(elem){ - if (this.nodeType == 1) - this.appendChild( elem ); - }); - }, - - prepend: function() { - return this.domManip(arguments, true, true, function(elem){ - if (this.nodeType == 1) - this.insertBefore( elem, this.firstChild ); - }); - }, - - before: function() { - return this.domManip(arguments, false, false, function(elem){ - this.parentNode.insertBefore( elem, this ); - }); - }, - - after: function() { - return this.domManip(arguments, false, true, function(elem){ - this.parentNode.insertBefore( elem, this.nextSibling ); - }); - }, - - end: function() { - return this.prevObject || jQuery( [] ); - }, - - find: function( selector ) { - var elems = jQuery.map(this, function(elem){ - return jQuery.find( selector, elem ); - }); - - return this.pushStack( /[^+>] [^+>]/.test( selector ) || selector.indexOf("..") > -1 ? - jQuery.unique( elems ) : - elems ); - }, - - clone: function( events ) { - // Do the clone - var ret = this.map(function(){ - if ( jQuery.browser.msie && !jQuery.isXMLDoc(this) ) { - // IE copies events bound via attachEvent when - // using cloneNode. Calling detachEvent on the - // clone will also remove the events from the orignal - // In order to get around this, we use innerHTML. - // Unfortunately, this means some modifications to - // attributes in IE that are actually only stored - // as properties will not be copied (such as the - // the name attribute on an input). - var clone = this.cloneNode(true), - container = document.createElement("div"); - container.appendChild(clone); - return jQuery.clean([container.innerHTML])[0]; - } else - return this.cloneNode(true); - }); - - // Need to set the expando to null on the cloned set if it exists - // removeData doesn't work here, IE removes it from the original as well - // this is primarily for IE but the data expando shouldn't be copied over in any browser - var clone = ret.find("*").andSelf().each(function(){ - if ( this[ expando ] != undefined ) - this[ expando ] = null; - }); - - // Copy the events from the original to the clone - if ( events === true ) - this.find("*").andSelf().each(function(i){ - if (this.nodeType == 3) - return; - var events = jQuery.data( this, "events" ); - - for ( var type in events ) - for ( var handler in events[ type ] ) - jQuery.event.add( clone[ i ], type, events[ type ][ handler ], events[ type ][ handler ].data ); - }); - - // Return the cloned set - return ret; - }, - - filter: function( selector ) { - return this.pushStack( - jQuery.isFunction( selector ) && - jQuery.grep(this, function(elem, i){ - return selector.call( elem, i ); - }) || - - jQuery.multiFilter( selector, this ) ); - }, - - not: function( selector ) { - if ( selector.constructor == String ) - // test special case where just one selector is passed in - if ( isSimple.test( selector ) ) - return this.pushStack( jQuery.multiFilter( selector, this, true ) ); - else - selector = jQuery.multiFilter( selector, this ); - - var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType; - return this.filter(function() { - return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector; - }); - }, - - add: function( selector ) { - return !selector ? this : this.pushStack( jQuery.merge( - this.get(), - selector.constructor == String ? - jQuery( selector ).get() : - selector.length != undefined && (!selector.nodeName || jQuery.nodeName(selector, "form")) ? - selector : [selector] ) ); - }, - - is: function( selector ) { - return selector ? - jQuery.multiFilter( selector, this ).length > 0 : - false; - }, - - hasClass: function( selector ) { - return this.is( "." + selector ); - }, - - val: function( value ) { - if ( value == undefined ) { - - if ( this.length ) { - var elem = this[0]; - - // We need to handle select boxes special - if ( jQuery.nodeName( elem, "select" ) ) { - var index = elem.selectedIndex, - values = [], - options = elem.options, - one = elem.type == "select-one"; - - // Nothing was selected - if ( index < 0 ) - return null; - - // Loop through all the selected options - for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { - var option = options[ i ]; - - if ( option.selected ) { - // Get the specifc value for the option - value = jQuery.browser.msie && !option.attributes.value.specified ? option.text : option.value; - - // We don't need an array for one selects - if ( one ) - return value; - - // Multi-Selects return an array - values.push( value ); - } - } - - return values; - - // Everything else, we just grab the value - } else - return (this[0].value || "").replace(/\r/g, ""); - - } - - return undefined; - } - - return this.each(function(){ - if ( this.nodeType != 1 ) - return; - - if ( value.constructor == Array && /radio|checkbox/.test( this.type ) ) - this.checked = (jQuery.inArray(this.value, value) >= 0 || - jQuery.inArray(this.name, value) >= 0); - - else if ( jQuery.nodeName( this, "select" ) ) { - var values = value.constructor == Array ? - value : - [ value ]; - - jQuery( "option", this ).each(function(){ - this.selected = (jQuery.inArray( this.value, values ) >= 0 || - jQuery.inArray( this.text, values ) >= 0); - }); - - if ( !values.length ) - this.selectedIndex = -1; - - } else - this.value = value; - }); - }, - - html: function( value ) { - return value == undefined ? - (this.length ? - this[0].innerHTML : - null) : - this.empty().append( value ); - }, - - replaceWith: function( value ) { - return this.after( value ).remove(); - }, - - eq: function( i ) { - return this.slice( i, i + 1 ); - }, - - slice: function() { - return this.pushStack( Array.prototype.slice.apply( this, arguments ) ); - }, - - map: function( callback ) { - return this.pushStack( jQuery.map(this, function(elem, i){ - return callback.call( elem, i, elem ); - })); - }, - - andSelf: function() { - return this.add( this.prevObject ); - }, - - data: function( key, value ){ - var parts = key.split("."); - parts[1] = parts[1] ? "." + parts[1] : ""; - - if ( value == null ) { - var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); - - if ( data == undefined && this.length ) - data = jQuery.data( this[0], key ); - - return data == null && parts[1] ? - this.data( parts[0] ) : - data; - } else - return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){ - jQuery.data( this, key, value ); - }); - }, - - removeData: function( key ){ - return this.each(function(){ - jQuery.removeData( this, key ); - }); - }, - - domManip: function( args, table, reverse, callback ) { - var clone = this.length > 1, elems; - - return this.each(function(){ - if ( !elems ) { - elems = jQuery.clean( args, this.ownerDocument ); - - if ( reverse ) - elems.reverse(); - } - - var obj = this; - - if ( table && jQuery.nodeName( this, "table" ) && jQuery.nodeName( elems[0], "tr" ) ) - obj = this.getElementsByTagName("tbody")[0] || this.appendChild( this.ownerDocument.createElement("tbody") ); - - var scripts = jQuery( [] ); - - jQuery.each(elems, function(){ - var elem = clone ? - jQuery( this ).clone( true )[0] : - this; - - // execute all scripts after the elements have been injected - if ( jQuery.nodeName( elem, "script" ) ) { - scripts = scripts.add( elem ); - } else { - // Remove any inner scripts for later evaluation - if ( elem.nodeType == 1 ) - scripts = scripts.add( jQuery( "script", elem ).remove() ); - - // Inject the elements into the document - callback.call( obj, elem ); - } - }); - - scripts.each( evalScript ); - }); - } -}; - -// Give the init function the jQuery prototype for later instantiation -jQuery.prototype.init.prototype = jQuery.prototype; - -function evalScript( i, elem ) { - if ( elem.src ) - jQuery.ajax({ - url: elem.src, - async: false, - dataType: "script" - }); - - else - jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" ); - - if ( elem.parentNode ) - elem.parentNode.removeChild( elem ); -} - -jQuery.extend = jQuery.fn.extend = function() { - // copy reference to target object - var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options; - - // Handle a deep copy situation - if ( target.constructor == Boolean ) { - deep = target; - target = arguments[1] || {}; - // skip the boolean and the target - i = 2; - } - - // Handle case when target is a string or something (possible in deep copy) - if ( typeof target != "object" && typeof target != "function" ) - target = {}; - - // extend jQuery itself if only one argument is passed - if ( length == 1 ) { - target = this; - i = 0; - } - - for ( ; i < length; i++ ) - // Only deal with non-null/undefined values - if ( (options = arguments[ i ]) != null ) - // Extend the base object - for ( var name in options ) { - // Prevent never-ending loop - if ( target === options[ name ] ) - continue; - - // Recurse if we're merging object values - if ( deep && options[ name ] && typeof options[ name ] == "object" && target[ name ] && !options[ name ].nodeType ) - target[ name ] = jQuery.extend( target[ name ], options[ name ] ); - - // Don't bring in undefined values - else if ( options[ name ] != undefined ) - target[ name ] = options[ name ]; - - } - - // Return the modified object - return target; -}; - -var expando = "jQuery" + (new Date()).getTime(), uuid = 0, windowData = {}; - -// exclude the following css properties to add px -var exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i; - -jQuery.extend({ - noConflict: function( deep ) { - window.$ = _$; - - if ( deep ) - window.jQuery = _jQuery; - - return jQuery; - }, - - // See test/unit/core.js for details concerning this function. - isFunction: function( fn ) { - return !!fn && typeof fn != "string" && !fn.nodeName && - fn.constructor != Array && /function/i.test( fn + "" ); - }, - - // check if an element is in a (or is an) XML document - isXMLDoc: function( elem ) { - return elem.documentElement && !elem.body || - elem.tagName && elem.ownerDocument && !elem.ownerDocument.body; - }, - - // Evalulates a script in a global context - globalEval: function( data ) { - data = jQuery.trim( data ); - - if ( data ) { - // Inspired by code by Andrea Giammarchi - // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html - var head = document.getElementsByTagName("head")[0] || document.documentElement, - script = document.createElement("script"); - - script.type = "text/javascript"; - if ( jQuery.browser.msie ) - script.text = data; - else - script.appendChild( document.createTextNode( data ) ); - - head.appendChild( script ); - head.removeChild( script ); - } - }, - - nodeName: function( elem, name ) { - return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase(); - }, - - cache: {}, - - data: function( elem, name, data ) { - elem = elem == window ? - windowData : - elem; - - var id = elem[ expando ]; - - // Compute a unique ID for the element - if ( !id ) - id = elem[ expando ] = ++uuid; - - // Only generate the data cache if we're - // trying to access or manipulate it - if ( name && !jQuery.cache[ id ] ) - jQuery.cache[ id ] = {}; - - // Prevent overriding the named cache with undefined values - if ( data != undefined ) - jQuery.cache[ id ][ name ] = data; - - // Return the named cache data, or the ID for the element - return name ? - jQuery.cache[ id ][ name ] : - id; - }, - - removeData: function( elem, name ) { - elem = elem == window ? - windowData : - elem; - - var id = elem[ expando ]; - - // If we want to remove a specific section of the element's data - if ( name ) { - if ( jQuery.cache[ id ] ) { - // Remove the section of cache data - delete jQuery.cache[ id ][ name ]; - - // If we've removed all the data, remove the element's cache - name = ""; - - for ( name in jQuery.cache[ id ] ) - break; - - if ( !name ) - jQuery.removeData( elem ); - } - - // Otherwise, we want to remove all of the element's data - } else { - // Clean up the element expando - try { - delete elem[ expando ]; - } catch(e){ - // IE has trouble directly removing the expando - // but it's ok with using removeAttribute - if ( elem.removeAttribute ) - elem.removeAttribute( expando ); - } - - // Completely remove the data cache - delete jQuery.cache[ id ]; - } - }, - - // args is for internal usage only - each: function( object, callback, args ) { - if ( args ) { - if ( object.length == undefined ) { - for ( var name in object ) - if ( callback.apply( object[ name ], args ) === false ) - break; - } else - for ( var i = 0, length = object.length; i < length; i++ ) - if ( callback.apply( object[ i ], args ) === false ) - break; - - // A special, fast, case for the most common use of each - } else { - if ( object.length == undefined ) { - for ( var name in object ) - if ( callback.call( object[ name ], name, object[ name ] ) === false ) - break; - } else - for ( var i = 0, length = object.length, value = object[0]; - i < length && callback.call( value, i, value ) !== false; value = object[++i] ){} - } - - return object; - }, - - prop: function( elem, value, type, i, name ) { - // Handle executable functions - if ( jQuery.isFunction( value ) ) - value = value.call( elem, i ); - - // Handle passing in a number to a CSS property - return value && value.constructor == Number && type == "curCSS" && !exclude.test( name ) ? - value + "px" : - value; - }, - - className: { - // internal only, use addClass("class") - add: function( elem, classNames ) { - jQuery.each((classNames || "").split(/\s+/), function(i, className){ - if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) ) - elem.className += (elem.className ? " " : "") + className; - }); - }, - - // internal only, use removeClass("class") - remove: function( elem, classNames ) { - if (elem.nodeType == 1) - elem.className = classNames != undefined ? - jQuery.grep(elem.className.split(/\s+/), function(className){ - return !jQuery.className.has( classNames, className ); - }).join(" ") : - ""; - }, - - // internal only, use is(".class") - has: function( elem, className ) { - return jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1; - } - }, - - // A method for quickly swapping in/out CSS properties to get correct calculations - swap: function( elem, options, callback ) { - var old = {}; - // Remember the old values, and insert the new ones - for ( var name in options ) { - old[ name ] = elem.style[ name ]; - elem.style[ name ] = options[ name ]; - } - - callback.call( elem ); - - // Revert the old values - for ( var name in options ) - elem.style[ name ] = old[ name ]; - }, - - css: function( elem, name, force ) { - if ( name == "width" || name == "height" ) { - var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ]; - - function getWH() { - val = name == "width" ? elem.offsetWidth : elem.offsetHeight; - var padding = 0, border = 0; - jQuery.each( which, function() { - padding += parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0; - border += parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0; - }); - val -= Math.round(padding + border); - } - - if ( jQuery(elem).is(":visible") ) - getWH(); - else - jQuery.swap( elem, props, getWH ); - - return Math.max(0, val); - } - - return jQuery.curCSS( elem, name, force ); - }, - - curCSS: function( elem, name, force ) { - var ret; - - // A helper method for determining if an element's values are broken - function color( elem ) { - if ( !jQuery.browser.safari ) - return false; - - var ret = document.defaultView.getComputedStyle( elem, null ); - return !ret || ret.getPropertyValue("color") == ""; - } - - // We need to handle opacity special in IE - if ( name == "opacity" && jQuery.browser.msie ) { - ret = jQuery.attr( elem.style, "opacity" ); - - return ret == "" ? - "1" : - ret; - } - // Opera sometimes will give the wrong display answer, this fixes it, see #2037 - if ( jQuery.browser.opera && name == "display" ) { - var save = elem.style.outline; - elem.style.outline = "0 solid black"; - elem.style.outline = save; - } - - // Make sure we're using the right name for getting the float value - if ( name.match( /float/i ) ) - name = styleFloat; - - if ( !force && elem.style && elem.style[ name ] ) - ret = elem.style[ name ]; - - else if ( document.defaultView && document.defaultView.getComputedStyle ) { - - // Only "float" is needed here - if ( name.match( /float/i ) ) - name = "float"; - - name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase(); - - var getComputedStyle = document.defaultView.getComputedStyle( elem, null ); - - if ( getComputedStyle && !color( elem ) ) - ret = getComputedStyle.getPropertyValue( name ); - - // If the element isn't reporting its values properly in Safari - // then some display: none elements are involved - else { - var swap = [], stack = []; - - // Locate all of the parent display: none elements - for ( var a = elem; a && color(a); a = a.parentNode ) - stack.unshift(a); - - // Go through and make them visible, but in reverse - // (It would be better if we knew the exact display type that they had) - for ( var i = 0; i < stack.length; i++ ) - if ( color( stack[ i ] ) ) { - swap[ i ] = stack[ i ].style.display; - stack[ i ].style.display = "block"; - } - - // Since we flip the display style, we have to handle that - // one special, otherwise get the value - ret = name == "display" && swap[ stack.length - 1 ] != null ? - "none" : - ( getComputedStyle && getComputedStyle.getPropertyValue( name ) ) || ""; - - // Finally, revert the display styles back - for ( var i = 0; i < swap.length; i++ ) - if ( swap[ i ] != null ) - stack[ i ].style.display = swap[ i ]; - } - - // We should always get a number back from opacity - if ( name == "opacity" && ret == "" ) - ret = "1"; - - } else if ( elem.currentStyle ) { - var camelCase = name.replace(/\-(\w)/g, function(all, letter){ - return letter.toUpperCase(); - }); - - ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ]; - - // From the awesome hack by Dean Edwards - // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 - - // If we're not dealing with a regular pixel number - // but a number that has a weird ending, we need to convert it to pixels - if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) { - // Remember the original values - var style = elem.style.left, runtimeStyle = elem.runtimeStyle.left; - - // Put in the new values to get a computed value out - elem.runtimeStyle.left = elem.currentStyle.left; - elem.style.left = ret || 0; - ret = elem.style.pixelLeft + "px"; - - // Revert the changed values - elem.style.left = style; - elem.runtimeStyle.left = runtimeStyle; - } - } - - return ret; - }, - - clean: function( elems, context ) { - var ret = []; - context = context || document; - // !context.createElement fails in IE with an error but returns typeof 'object' - if (typeof context.createElement == 'undefined') - context = context.ownerDocument || context[0] && context[0].ownerDocument || document; - - jQuery.each(elems, function(i, elem){ - if ( !elem ) - return; - - if ( elem.constructor == Number ) - elem = elem.toString(); - - // Convert html string into DOM nodes - if ( typeof elem == "string" ) { - // Fix "XHTML"-style tags in all browsers - elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){ - return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ? - all : - front + ">"; - }); - - // Trim whitespace, otherwise indexOf won't work as expected - var tags = jQuery.trim( elem ).toLowerCase(), div = context.createElement("div"); - - var wrap = - // option or optgroup - !tags.indexOf("", "" ] || - - !tags.indexOf("", "" ] || - - tags.match(/^<(thead|tbody|tfoot|colg|cap)/) && - [ 1, "", "
" ] || - - !tags.indexOf("", "" ] || - - // matched above - (!tags.indexOf("", "" ] || - - !tags.indexOf("", "" ] || - - // IE can't serialize and