diff --git a/app/Lib/Dashboard/MispSystemResourceWidget.php b/app/Lib/Dashboard/MispSystemResourceWidget.php
new file mode 100644
index 000000000..42000bc01
--- /dev/null
+++ b/app/Lib/Dashboard/MispSystemResourceWidget.php
@@ -0,0 +1,57 @@
+ 'Treshold for disk space'
+ );
+ public $description = 'Basic widget showing some system server statistics.';
+ public $cacheLifetime = false;
+ public $autoRefreshDelay = 30;
+ public $placeholder =
+ '{
+ "treshold": "85"
+ }';
+
+ public function handler($user, $options = array())
+ {
+ $treshold = (int)$params['treshold'];
+
+ $drive = round((1 - disk_free_space(getcwd())/disk_total_space(getcwd()))*100,2);
+ if ($drive > $treshold) {
+ $driveFree = $drive . "% - [Above Treshhold]";
+ $driveFreeClass = "red";
+ }
+ else {
+ $driveFree = $drive . "%";
+ $driveFreeClass = "";
+ }
+
+ $sysload = sys_getloadavg();
+
+ preg_match('#MemFree:[\s\t]+([\d]+)\s+kB#', file_get_contents('/proc/meminfo'), $matches);
+ $memoryFree = $matches[1];
+ preg_match('#MemTotal:[\s\t]+([\d]+)\s+kB#', file_get_contents('/proc/meminfo'), $matches);
+ $memoryTotal = $matches[1];
+
+ $data = array(
+ array( 'title' => __('System'), 'value' => php_uname()),
+ array( 'title' => __('Disk usage'), 'value' => h($driveFree), 'class' => $driveFreeClass),
+ array( 'title' => __('Load'), 'value' => h($sysload[0] . " - " . $sysload[1] . " - " . $sysload[2])),
+ array( 'title' => __('Memory'), 'value' => h(round($memoryFree/1024,2) . "M free (" . round((1 - $memoryFree/$memoryTotal)*100,2) . "% used)")),
+ );
+ return $data;
+ }
+
+ public function checkPermissions($user)
+ {
+ if (empty($user['Role']['perm_site_admin'])) {
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/app/Lib/Dashboard/RecentSightingsWidget.php b/app/Lib/Dashboard/RecentSightingsWidget.php
new file mode 100644
index 000000000..0860f8da4
--- /dev/null
+++ b/app/Lib/Dashboard/RecentSightingsWidget.php
@@ -0,0 +1,66 @@
+ 'Maximum amount of sightings to return',
+ 'last' => 'Limit sightins to last 1d, 12h, ...'
+ );
+ public $description = 'Widget showing information on recent sightings';
+ public $cacheLifetime = false;
+ public $autoRefreshDelay = 30;
+ public $placeholder =
+ '{
+ "limit": "10",
+ "last": "1d",
+ }';
+
+ public function handler($user, $options = array())
+ {
+ $params = array(
+ 'last' => empty($options['last']) ? "1d" : $options['last'],
+ 'limit' => empty($options['limit']) ? "10" : $options['limit']
+ );
+ $last = $params['last'];
+ $limit = $params['limit'];
+
+ $this->Sighting = ClassRegistry::init('Sighting');
+ $filters = array( 'last' => $last, 'includeAttribute' => 'true', 'includeEvent' => 'true');
+ $data = array();
+ $count = 0;
+
+ foreach(json_decode($this->Sighting->restSearch($user, 'json', $filters))->{'response'} as $el) {
+ $sighting = $el->{'Sighting'};
+ $event = $sighting->{'Event'};
+ $attribute = $sighting->{'Attribute'};
+
+ if ($sighting->{'type'} == 0) $type = "Sighting";
+ elseif ($sighting->{'type'} == 1) $type = "False positive";
+ else $type = "Expiration";
+
+ $output = $attribute->{'value'} . " (id: " . $attribute->{'id'} . ") in " . $event->{'info'} . " (id: " . $event->{'id'} . ")";
+ $data[] = array( 'title' => __($type), 'value' => $output,
+ 'html' => sprintf(
+ ' (Event %s)',
+ Configure::read('MISP.baseurl') . '/events/view/', $event->{'id'},
+ $event->{'id'}
+ )
+ );
+ ++$count;
+ if ($count >= $limit ) break;
+ }
+ return $data;
+ }
+
+ public function checkPermissions($user)
+ {
+ if (empty($user['Role']['perm_site_admin'])) {
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/app/Lib/Dashboard/TresholdSightingsWidget.php b/app/Lib/Dashboard/TresholdSightingsWidget.php
new file mode 100644
index 000000000..891ac8218
--- /dev/null
+++ b/app/Lib/Dashboard/TresholdSightingsWidget.php
@@ -0,0 +1,72 @@
+ 'Treshold for sightings'
+ );
+ public $description = 'Widget showing information on sightings above certain treshold';
+ public $cacheLifetime = false;
+ public $autoRefreshDelay = 30;
+ public $placeholder =
+ '{
+ "treshold": "10"
+ }';
+
+ public function handler($user, $options = array())
+ {
+ $params = array(
+ 'treshold' => empty($options['treshold']) ? 10 : $options['treshold'],
+ );
+ $treshold = $params['treshold'];
+
+ $this->Sighting = ClassRegistry::init('Sighting');
+
+ $filters = array( 'includeAttribute' => 'true', 'includeEvent' => 'true');
+
+ $data = array();
+ $sightings_score = array();
+ $restSearch = json_decode($this->Sighting->restSearch($user, 'json', $filters))->{'response'};
+
+ foreach($restSearch as $el) {
+ $sighting = $el->{'Sighting'};
+ $attribute = $sighting->{'Attribute'};
+ $event = $sighting->{'Event'};
+
+ if (!array_key_exists($attribute->{'id'}, $sightings_score)) $sightings_score[$attribute->{'id'}] = array( 'value' => $attribute->{'value'},
+ 'score' => 0,
+ 'event_title' => $event->{'info'},
+ 'event_id' => $event->{'id'});
+ # Sighting
+ if ($sighting->{'type'} == 0) $sightings_score[$attribute->{'id'}]['score'] = $sightings_score[$attribute->{'id'}]['score'] - 1;
+ # False Positive
+ elseif ($sighting->{'type'} == 1) $sightings_score[$attribute->{'id'}]['score'] = $sightings_score[$attribute->{'id'}]['score'] + 1;
+ }
+
+ foreach($sightings_score as $attribute_id => $s) {
+ if ((int)$s['score'] >= (int)$treshold ) {
+ $output = "Score: " . $s['score'] . ": " . $s['value'] . " (id: " . $attribute_id . ") in " . $s['event_title'] . " (id: " . $s['event_id'] . ")";
+ $data[] = array( 'title' => __("False positive above threshold"), 'value' => $output,
+ 'html' => sprintf(
+ ' (Event %s)',
+ Configure::read('MISP.baseurl') . '/events/view/', $s['event_id'],
+ $s['event_id']
+ ));
+ };
+ }
+
+ return $data;
+ }
+
+ public function checkPermissions($user)
+ {
+ if (empty($user['Role']['perm_site_admin'])) {
+ return false;
+ }
+ return true;
+ }
+}